summaryrefslogtreecommitdiffstats
path: root/meta-egvirt/recipes-extended/vhost-device-can/files/vhost-device-can-0.1.0/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'meta-egvirt/recipes-extended/vhost-device-can/files/vhost-device-can-0.1.0/src/main.rs')
-rwxr-xr-xmeta-egvirt/recipes-extended/vhost-device-can/files/vhost-device-can-0.1.0/src/main.rs96
1 files changed, 96 insertions, 0 deletions
diff --git a/meta-egvirt/recipes-extended/vhost-device-can/files/vhost-device-can-0.1.0/src/main.rs b/meta-egvirt/recipes-extended/vhost-device-can/files/vhost-device-can-0.1.0/src/main.rs
new file mode 100755
index 00000000..97386884
--- /dev/null
+++ b/meta-egvirt/recipes-extended/vhost-device-can/files/vhost-device-can-0.1.0/src/main.rs
@@ -0,0 +1,96 @@
+// VIRTIO CAN Emulation via vhost-user
+//
+// Copyright 2023-2024 VIRTUAL OPEN SYSTEMS SAS. All Rights Reserved.
+// Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>
+//
+// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
+
+mod backend;
+mod can;
+mod vhu_can;
+mod virtio_can;
+
+use clap::Parser;
+use log::{error, info};
+use socketcan::{CanSocket, Socket};
+use std::convert::TryFrom;
+use std::path::PathBuf;
+use std::process::exit;
+
+pub(crate) type Result<T> = std::result::Result<T, Error>;
+use crate::backend::{start_backend, Error, VuCanConfig};
+
+#[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, value_name = "SOCKET")]
+ socket_path: PathBuf,
+
+ /// A can device name to be used for reading (ex. vcan, can0, can1, ... etc.)
+ #[clap(short = 'd', long)]
+ can_devices: String,
+
+ /// Number of guests (sockets) to connect to.
+ #[clap(short = 'c', long, default_value_t = 1)]
+ socket_count: u32,
+}
+
+fn check_can_devices(can_devices: &[String]) -> Result<()> {
+ for can_dev in can_devices {
+ if CanSocket::open(can_dev).is_err() {
+ info!("There is no interface with the following name {}", can_dev);
+ return Err(Error::CouldNotFindCANDevs);
+ }
+ }
+ Ok(())
+}
+
+fn parse_can_devices(input: &CanArgs) -> Result<Vec<String>> {
+ let can_devices_vec: Vec<&str> = input.can_devices.split_whitespace().collect();
+ let can_devices: Vec<_> = can_devices_vec.iter().map(|x| x.to_string()).collect();
+
+ if (can_devices.len() as u32) != input.socket_count {
+ info!(
+ "Number of CAN/FD devices ({}) not equal with socket count {}",
+ input.can_devices, input.socket_count
+ );
+ return Err(Error::SocketCountInvalid(
+ input.socket_count.try_into().unwrap(),
+ ));
+ }
+
+ match check_can_devices(&can_devices) {
+ Ok(_) => Ok(can_devices),
+ Err(_) => Err(Error::CouldNotFindCANDevs),
+ }
+}
+
+impl TryFrom<CanArgs> for VuCanConfig {
+ type Error = Error;
+
+ fn try_from(args: CanArgs) -> Result<Self> {
+ if args.socket_count == 0 {
+ return Err(Self::Error::SocketCountInvalid(0));
+ }
+
+ let can_devices = match parse_can_devices(&args) {
+ Ok(can_devs) => can_devs,
+ Err(e) => return Err(e),
+ };
+
+ Ok(VuCanConfig {
+ socket_path: args.socket_path,
+ socket_count: args.socket_count,
+ can_devices,
+ })
+ }
+}
+
+fn main() {
+ env_logger::init();
+ if let Err(e) = VuCanConfig::try_from(CanArgs::parse()).and_then(start_backend) {
+ error!("{e}");
+ exit(1);
+ }
+}