diff options
Diffstat (limited to 'meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/backend.rs')
-rw-r--r-- | meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/backend.rs | 170 |
1 files changed, 0 insertions, 170 deletions
diff --git a/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/backend.rs b/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/backend.rs deleted file mode 100644 index 177c76cc..00000000 --- a/meta-egvirt/recipes-extended/vhost-device-can/vhost-device-can-0.1.0/src/backend.rs +++ /dev/null @@ -1,170 +0,0 @@ -// VIRTIO CAN Emulation via vhost-user -// -// Copyright 2023 VIRTUAL OPEN SYSTEMS SAS. All Rights Reserved. -// Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com> -// -// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause - -use log::{error, info, warn}; -use std::process::exit; -use std::sync::{Arc, RwLock}; -use std::thread::{spawn, JoinHandle}; - -use clap::Parser; -use thiserror::Error as ThisError; -use vhost::{vhost_user, vhost_user::Listener}; -use vhost_user_backend::VhostUserDaemon; -use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap}; - -use crate::can::{CanController}; -use crate::vhu_can::VhostUserCanBackend; - -pub(crate) type Result<T> = std::result::Result<T, Error>; - -#[derive(Debug, ThisError)] -/// Errors related to low level CAN helpers -pub(crate) enum Error { - #[error("Invalid socket count: {0}")] - SocketCountInvalid(usize), - #[error("Failed to join threads")] - FailedJoiningThreads, - #[error("Could not create can controller: {0}")] - CouldNotCreateCanController(crate::can::Error), - #[error("Could not create can backend: {0}")] - CouldNotCreateBackend(crate::vhu_can::Error), - #[error("Could not create daemon: {0}")] - CouldNotCreateDaemon(vhost_user_backend::Error), -} - -#[derive(Parser, Debug)] -#[clap(author, version, about, long_about = None)] -struct CanArgs { - /// Location of vhost-user Unix domain socket. This is suffixed by 0,1,2..socket_count-1. - #[clap(short, long)] - socket_path: String, - - /// A can device name to be used for reading (ex. vcan, can0, can1, ... etc.) - #[clap(short = 'i', long)] - can_in: String, - - /// A can device name to be used for writing (ex. vcan, can0, can1, ... etc.) - #[clap(short = 'o', long)] - can_out: String, - - /// Number of guests (sockets) to connect to. - #[clap(short = 'c', long, default_value_t = 1)] - socket_count: u32, -} - -#[derive(PartialEq, Debug)] -struct CanConfiguration { - socket_path: String, - socket_count: u32, - can_in: String, - can_out: String, -} - -impl TryFrom<CanArgs> for CanConfiguration { - type Error = Error; - - fn try_from(args: CanArgs) -> Result<Self> { - - if args.socket_count == 0 { - return Err(Error::SocketCountInvalid(0)); - } - - let can_in = args.can_in.trim().to_string(); - let can_out = args.can_out.trim().to_string(); - - Ok(CanConfiguration { - socket_path: args.socket_path, - socket_count: args.socket_count, - can_in, - can_out, - }) - } -} - -fn start_backend(args: CanArgs) -> Result<()> { - - println!("start_backend function!\n"); - - let config = CanConfiguration::try_from(args).unwrap(); - let mut handles = Vec::new(); - - for _ in 0..config.socket_count { - let socket = config.socket_path.to_owned(); - let can_in = config.can_in.to_owned(); - let can_out = config.can_out.to_owned(); - - let handle: JoinHandle<Result<()>> = spawn(move || loop { - // A separate thread is spawned for each socket and can connect to a separate guest. - // These are run in an infinite loop to not require the daemon to be restarted once a - // guest exits. - // - // There isn't much value in complicating code here to return an error from the - // threads, and so the code uses unwrap() instead. The panic on a thread won't cause - // trouble to other threads/guests or the main() function and should be safe for the - // daemon. - - let controller = - CanController::new(can_in.clone(), can_out.clone()).map_err(Error::CouldNotCreateCanController)?; - let shared_controller_1 = Arc::new(RwLock::new(controller)); - let shared_controller_2 = shared_controller_1.clone(); - let vu_can_backend = Arc::new(RwLock::new( - VhostUserCanBackend::new(shared_controller_1).map_err(Error::CouldNotCreateBackend)?, - )); - let _read_hanlde = CanController::start_read_thread(shared_controller_2); - - let mut daemon = VhostUserDaemon::new( - String::from("vhost-device-can-backend"), - vu_can_backend.clone(), - GuestMemoryAtomic::new(GuestMemoryMmap::new()), - ) - .map_err(Error::CouldNotCreateDaemon)?; - - /* Start the read thread -- need to handle it after termination */ - let vring_workers = daemon.get_epoll_handlers(); - vu_can_backend.read() - .unwrap() - .set_vring_worker(&vring_workers[0]); - - let listener = Listener::new(socket.clone(), true).unwrap(); - daemon.start(listener).unwrap(); - - match daemon.wait() { - Ok(()) => { - info!("Stopping cleanly."); - } - Err(vhost_user_backend::Error::HandleRequest( - vhost_user::Error::PartialMessage | vhost_user::Error::Disconnected, - )) => { - info!("vhost-user connection closed with partial message. If the VM is shutting down, this is expected behavior; otherwise, it might be a bug."); - } - Err(e) => { - warn!("Error running daemon: {:?}", e); - } - } - - // No matter the result, we need to shut down the worker thread. - vu_can_backend.read().unwrap().exit_event.write(1).unwrap(); - }); - - handles.push(handle); - } - - for handle in handles { - handle.join().map_err(|_| Error::FailedJoiningThreads)??; - } - - Ok(()) -} - -pub(crate) fn can_init() { - env_logger::init(); - println!("Can_init function!"); - if let Err(e) = start_backend(CanArgs::parse()) { - error!("{e}"); - exit(1); - } -} |