3 // Copyright 2023 VIRTUAL OPEN SYSTEMS SAS. All Rights Reserved.
4 // Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>
6 // SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
8 use log::{warn, error};
10 use std::slice::from_raw_parts;
11 use std::sync::{Arc, RwLock};
14 io::{self, Result as IoResult},
16 use std::os::fd::AsRawFd;
17 use thiserror::Error as ThisError;
18 use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};
19 use vhost_user_backend::{VhostUserBackendMut, VringRwLock, VringT};
20 use virtio_bindings::bindings::virtio_config::{VIRTIO_F_NOTIFY_ON_EMPTY, VIRTIO_F_VERSION_1};
21 use virtio_bindings::bindings::virtio_ring::{
22 VIRTIO_RING_F_EVENT_IDX, VIRTIO_RING_F_INDIRECT_DESC,
24 use virtio_queue::{DescriptorChain, QueueOwnedT};
26 ByteValued, Bytes, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryLoadGuard,
27 GuestMemoryMmap, Le16, Le32,
29 use vmm_sys_util::epoll::EventSet;
30 use vmm_sys_util::eventfd::{EventFd, EFD_NONBLOCK};
32 CanController, CAN_EFF_FLAG, CAN_RTR_FLAG, CAN_ERR_FLAG, CAN_SFF_MASK,
33 CAN_EFF_MASK, VIRTIO_CAN_FLAGS_FD, VIRTIO_CAN_FLAGS_RTR,
34 VIRTIO_CAN_FLAGS_EXTENDED, VIRTIO_CAN_TX, VIRTIO_CAN_RX,
35 CAN_FRMF_TYPE_FD, CAN_ERR_BUSOFF,
37 use vhost_user_backend::VringEpollHandler;
39 /// Feature bit numbers
40 pub const VIRTIO_CAN_F_CAN_CLASSIC: u16 = 0;
41 pub const VIRTIO_CAN_F_CAN_FD: u16 = 1;
42 //pub const VIRTIO_CAN_F_LATE_TX_ACK: u16 = 2;
43 pub const VIRTIO_CAN_F_RTR_FRAMES: u16 = 3;
45 /// Possible values of the status field
46 pub const VIRTIO_CAN_STATUS_OK: u8 = 0x0;
47 pub const VIRTIO_CAN_STATUS_ERR: u8 = 0x1;
49 /// CAN Control messages
50 const VIRTIO_CAN_SET_CTRL_MODE_START: u16 = 0x0201;
51 const VIRTIO_CAN_SET_CTRL_MODE_STOP: u16 = 0x0202;
53 /// Virtio configuration
54 const QUEUE_SIZE: usize = 64;
55 const NUM_QUEUES: usize = 3;
58 const TX_QUEUE: u16 = 0;
59 const RX_QUEUE: u16 = 1;
60 const CTRL_QUEUE: u16 = 2;
61 const BACKEND_EFD: u16 = 4;
63 type Result<T> = std::result::Result<T, Error>;
65 #[derive(Copy, Clone, Debug, PartialEq, ThisError)]
66 /// Errors related to vhost-device-gpio-daemon.
67 pub(crate) enum Error {
68 #[error("Failed to handle event, didn't match EPOLLIN")]
69 HandleEventNotEpollIn,
70 #[error("Failed to handle unknown event")]
72 #[error("Received unexpected write only descriptor at index {0}")]
73 UnexpectedWriteOnlyDescriptor(usize),
74 #[error("Received unexpected readable descriptor at index {0}")]
75 UnexpectedReadableDescriptor(usize),
76 #[error("Invalid descriptor count {0}")]
77 UnexpectedDescriptorCount(usize),
78 #[error("Invalid descriptor size, expected: {0}, found: {1}")]
79 UnexpectedDescriptorSize(usize, u32),
80 #[error("Descriptor not found")]
82 #[error("Descriptor read failed")]
84 #[error("Descriptor write failed")]
85 DescriptorWriteFailed,
86 #[error("Failed to send notification")]
88 #[error("Failed to create new EventFd")]
90 #[error("Unknown can message type: {0}")]
91 UnexpectedCanMsgType(u16),
92 #[error("RTR frames not negotiated")]
94 #[error("Can FD frames not negotiated")]
96 #[error("Classic CAN frames not negotiated")]
97 UnexpectedClassicFlag,
100 impl convert::From<Error> for io::Error {
101 fn from(e: Error) -> Self {
102 io::Error::new(io::ErrorKind::Other, e)
106 /// Virtio CAN Request / Response messages
108 /// The response message is a stream of bytes, where first byte represents the
109 /// status, and rest is message specific data.
111 #[derive(Copy, Clone, Default)]
113 struct VirtioCanTxResponse {
116 // SAFETY: The layout of the structure is fixed and can be initialized by
117 // reading its content from byte array.
118 unsafe impl ByteValued for VirtioCanTxResponse {}
120 #[derive(Copy, Clone, Debug)]
122 pub struct VirtioCanFrame {
124 pub length: Le16, /* 0..8 CC, 0..64 CANFD, 0..2048 CANXL, 12 bits */
125 pub reserved: Le32, /* May be needed in part for CAN XL priority */
131 impl Default for VirtioCanFrame {
132 fn default() -> Self {
134 msg_type: Le16::default(),
135 length: Le16::default(),
136 reserved: Le32::default(),
137 flags: Le32::default(),
138 can_id: Le32::default(),
139 sdu: [0; 64], // Initialize "asd" with default value (0 in this case)
144 // SAFETY: The layout of the structure is fixed and can be initialized by
145 // reading its content from byte array.
146 unsafe impl ByteValued for VirtioCanFrame {}
148 #[derive(Copy, Clone, Default)]
150 struct VirtioCanCtrlRequest {
153 // SAFETY: The layout of the structure is fixed and can be initialized by
154 // reading its content from byte array.
155 unsafe impl ByteValued for VirtioCanCtrlRequest {}
157 #[derive(Copy, Clone, Default)]
159 struct VirtioCanCtrlResponse {
162 // SAFETY: The layout of the structure is fixed and can be initialized by
163 // reading its content from byte array.
164 unsafe impl ByteValued for VirtioCanCtrlResponse {}
166 pub(crate) struct VhostUserCanBackend {
167 controller: Arc<RwLock<CanController>>,
170 pub(crate) exit_event: EventFd,
171 mem: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
174 type CanDescriptorChain = DescriptorChain<GuestMemoryLoadGuard<GuestMemoryMmap<()>>>;
176 impl VhostUserCanBackend {
177 pub(crate) fn new(controller: Arc<RwLock<CanController>>) -> Result<Self> {
178 Ok(VhostUserCanBackend {
179 controller: controller,
182 exit_event: EventFd::new(EFD_NONBLOCK).map_err(|_| Error::EventFdFailed)?,
187 fn check_features (&self, features: u16) -> bool {
188 (self.acked_features & (1 << features)) != 0
191 fn process_ctrl_requests(
193 requests: Vec<CanDescriptorChain>,
196 dbg!("process_ctrl_requests");
198 if requests.is_empty() {
202 for desc_chain in requests {
203 let descriptors: Vec<_> = desc_chain.clone().collect();
205 if descriptors.len() < 1 {
206 warn!("Error::UnexpectedDescriptorCount");
207 return Err(Error::UnexpectedDescriptorCount(descriptors.len()));
210 println!("descriptors.len(): {:?}", descriptors.len());
212 let desc_request = descriptors[0];
213 if desc_request.is_write_only() {
214 warn!("Error::UnexpectedWriteOnlyDescriptor");
215 return Err(Error::UnexpectedWriteOnlyDescriptor(0));
218 if desc_request.len() as usize != size_of::<VirtioCanCtrlRequest>() {
219 println!("UnexpectedDescriptorSize, len = {:?}", desc_request.len());
220 return Err(Error::UnexpectedDescriptorSize(
221 size_of::<VirtioCanCtrlRequest>(),
226 let request = desc_chain
228 .read_obj::<VirtioCanCtrlRequest>(desc_request.addr())
229 .map_err(|_| Error::DescriptorReadFailed)?;
232 match request.msg_type.into() {
233 VIRTIO_CAN_SET_CTRL_MODE_START => {
234 println!("VIRTIO_CAN_SET_CTRL_MODE_START");
235 //vcan->busoff = false;
238 VIRTIO_CAN_SET_CTRL_MODE_STOP => {
239 println!("VIRTIO_CAN_SET_CTRL_MODE_STOP");
240 //vcan->busoff = false;
244 println!("Ctrl queue: msg type 0x{:?} unknown", request.msg_type);
245 return Err(Error::HandleEventUnknown.into())
249 let desc_response = descriptors[1];
250 if !desc_response.is_write_only() {
251 println!("This is not wirtable");
252 return Err(Error::UnexpectedReadableDescriptor(1));
255 let response = VIRTIO_CAN_STATUS_OK;
259 .write_slice(response.as_slice(), desc_response.addr())
260 .map_err(|_| Error::DescriptorWriteFailed)?;
262 if vring.add_used(desc_chain.head_index(), desc_response.len()).is_err() {
263 println!("Couldn't return used descriptors to the ring");
264 warn!("Couldn't return used descriptors to the ring");
271 fn process_tx_requests(
273 requests: Vec<CanDescriptorChain>,
276 dbg!("process_tx_requests");
278 if requests.is_empty() {
282 println!("requests.len: {:?}", requests.len());
283 for desc_chain in requests {
284 let descriptors: Vec<_> = desc_chain.clone().collect();
286 if descriptors.len() != 2 {
287 println!("Error::UnexpectedDescriptorCount");
288 return Err(Error::UnexpectedDescriptorCount(descriptors.len()));
291 let desc_request = descriptors[0];
292 if desc_request.is_write_only() {
293 println!("Error::UnexpectedReadOnlyDescriptor");
294 return Err(Error::UnexpectedWriteOnlyDescriptor(0));
297 if desc_request.len() as usize != size_of::<VirtioCanFrame>() {
298 println!("Tx UnexpectedDescriptorSize, len = {:?}", desc_request.len());
299 //return Err(Error::UnexpectedDescriptorSize(
300 // size_of::<VirtioCanFrame>(),
301 // desc_request.len(),
305 let request = desc_chain
307 .read_obj::<VirtioCanFrame>(desc_request.addr())
308 .map_err(|_| Error::DescriptorReadFailed)?;
310 CanController::print_can_frame(request);
312 let msg_type = request.msg_type.to_native();
313 let mut can_id = request.can_id.to_native();
314 let mut flags = request.flags.to_native();
315 let mut length = request.length.to_native();
317 if msg_type != VIRTIO_CAN_TX {
318 warn!("TX: Message type 0x{:x} unknown\n", msg_type);
319 return Err(Error::UnexpectedCanMsgType(msg_type));
322 if (flags & VIRTIO_CAN_FLAGS_FD) != 0 {
324 println!("Cut sdu_len from {:?} to 64\n", request.length);
329 println!("Cut sdu_len from {:?} to 8\n", request.length);
335 * Copy Virtio frame structure to qemu frame structure and
336 * check while doing this whether the frame type was negotiated
338 if (flags & VIRTIO_CAN_FLAGS_EXTENDED) != 0 {
339 flags &= CAN_EFF_MASK;
340 flags |= CAN_EFF_FLAG;
342 flags &= CAN_SFF_MASK;
345 if (flags & VIRTIO_CAN_FLAGS_RTR) != 0 {
346 if !self.check_features(VIRTIO_CAN_F_CAN_CLASSIC) ||
347 !self.check_features(VIRTIO_CAN_F_RTR_FRAMES) {
348 warn!("TX: RTR frames not negotiated");
349 return Err(Error::UnexpectedRtrFlag);
351 can_id |= flags | CAN_RTR_FLAG;
354 if (flags & VIRTIO_CAN_FLAGS_FD) != 0 {
355 if !self.check_features(VIRTIO_CAN_F_CAN_FD) {
356 warn!("TX: FD frames not negotiated\n");
357 return Err(Error::UnexpectedFdFlag);
359 flags |= CAN_FRMF_TYPE_FD;
361 if !self.check_features(VIRTIO_CAN_F_CAN_CLASSIC) {
362 warn!("TX: Classic frames not negotiated\n");
363 return Err(Error::UnexpectedClassicFlag);
368 let mut corrected_request = VirtioCanFrame::default();
369 corrected_request.msg_type = msg_type.into();
370 corrected_request.can_id = can_id.into();
371 corrected_request.flags = flags.into();
372 corrected_request.length = length.into();
373 corrected_request.sdu.copy_from_slice(&request.sdu[0..64]);
375 let desc_response = descriptors[1];
376 if !desc_response.is_write_only() {
377 println!("Error::UnexpectedWriteOnlyDescriptor");
378 return Err(Error::UnexpectedReadableDescriptor(1));
381 let response = match self.controller.write().unwrap().operation(corrected_request) {
386 warn!("We got an error from controller send func");
387 VIRTIO_CAN_STATUS_ERR
393 .write_slice(response.as_slice(), desc_response.addr())
394 .map_err(|_| Error::DescriptorWriteFailed)?;
396 if vring.add_used(desc_chain.head_index(), desc_response.len()).is_err() {
397 println!("Couldn't return used descriptors to the ring");
398 warn!("Couldn't return used descriptors to the ring");
405 fn process_rx_requests(
407 requests: Vec<CanDescriptorChain>,
410 dbg!("process_rx_requests");
412 if requests.is_empty() {
416 let desc_chain = &requests[0];
417 let descriptors: Vec<_> = desc_chain.clone().collect();
419 if descriptors.len() != 1 {
420 println!("Error::UnexpectedDescriptorCount");
421 return Err(Error::UnexpectedDescriptorCount(descriptors.len()));
424 let desc_response = descriptors[0];
425 if !desc_response.is_write_only() {
426 return Err(Error::UnexpectedReadableDescriptor(1));
429 let mut response = match self.controller.write().unwrap().pop() {
431 Err(_) => return Err(Error::HandleEventUnknown),
434 CanController::print_can_frame(response);
436 if (response.can_id.to_native() & CAN_ERR_FLAG) != 0 {
437 if (response.can_id.to_native() & CAN_ERR_BUSOFF) != 0 {
438 warn!("Got BusOff error frame, device does a local bus off\n");
439 //vcan->busoff = true;
441 println!("Dropping error frame 0x{:x}\n", response.can_id.to_native());
446 let mut can_rx = VirtioCanFrame::default();
447 can_rx.msg_type = VIRTIO_CAN_RX.into();
448 can_rx.can_id = response.can_id;
449 can_rx.length = response.length;
450 can_rx.flags = (can_rx.flags.to_native() | VIRTIO_CAN_FLAGS_FD).into();
452 if (response.flags.to_native() & CAN_FRMF_TYPE_FD) != 0 {
453 if !self.check_features(VIRTIO_CAN_F_CAN_FD) {
454 warn!("Drop non-supported CAN FD frame");
455 return Err(Error::UnexpectedFdFlag);
458 if !self.check_features(VIRTIO_CAN_F_CAN_CLASSIC) {
459 warn!("Drop non-supported CAN classic frame");
460 return Err(Error::UnexpectedClassicFlag);
463 if (response.can_id.to_native() & CAN_RTR_FLAG) != 0 &&
464 !self.check_features(VIRTIO_CAN_F_RTR_FRAMES) {
465 warn!("Drop non-supported RTR frame");
466 return Err(Error::UnexpectedRtrFlag);
469 if (response.can_id.to_native() & CAN_EFF_FLAG) != 0 {
470 can_rx.flags = VIRTIO_CAN_FLAGS_EXTENDED.into();
471 can_rx.can_id = (response.can_id.to_native() & CAN_EFF_MASK).into();
473 can_rx.can_id = (response.can_id.to_native() & CAN_SFF_MASK).into();
475 if (response.can_id.to_native() & CAN_RTR_FLAG) != 0 {
476 can_rx.flags = (can_rx.flags.to_native() & VIRTIO_CAN_FLAGS_RTR).into();
479 // HACK AHEAD: Vcan can not be comfigured as CANFD interface, but possible
480 // to configure its MTU to 64 bytes. So if a messages bigger than 8 bytes
481 // is being received we consider it as CANFD message.
482 let can_in_name = self.controller.read().unwrap().can_in_name.clone();
483 if self.check_features(VIRTIO_CAN_F_CAN_FD) &&
484 response.length.to_native() > 8 && can_in_name == "vcan0" {
485 response.flags = (response.flags.to_native() | CAN_FRMF_TYPE_FD).into();
486 warn!("\n\n\nCANFD VCAN0\n\n");
489 if (response.flags.to_native() & CAN_FRMF_TYPE_FD) != 0 {
490 can_rx.flags = (can_rx.flags.to_native() | VIRTIO_CAN_FLAGS_FD).into();
491 if response.length.to_native() > 64 {
492 warn!("%s(): Cut length from {} to 64\n", response.length.to_native());
493 can_rx.length = 64.into();
496 if response.length.to_native() > 8 {
497 warn!("%s(): Cut length from {} to 8\n", response.length.to_native());
498 can_rx.length = 8.into();
502 can_rx.sdu.copy_from_slice(&response.sdu[0..64]);
503 CanController::print_can_frame(can_rx);
507 .write_slice(can_rx.as_slice(), desc_response.addr())
508 .map_err(|_| Error::DescriptorWriteFailed)?;
510 if vring.add_used(desc_chain.head_index(), desc_response.len()).is_err() {
511 warn!("Couldn't return used descriptors to the ring");
517 /// Process the messages in the vring and dispatch replies
518 fn process_ctrl_queue(&mut self, vring: &VringRwLock) -> Result<()> {
519 dbg!("process_ctrl_queue");
520 let requests: Vec<_> = vring
523 .iter(self.mem.as_ref().unwrap().memory())
524 .map_err(|_| Error::DescriptorNotFound)?
527 if self.process_ctrl_requests(requests, vring)? {
528 // Send notification once all the requests are processed
531 .map_err(|_| Error::NotificationFailed)?;
536 /// Process the messages in the vring and dispatch replies
537 fn process_tx_queue(&self, vring: &VringRwLock) -> Result<()> {
538 dbg!("process_tx_queue");
539 let requests: Vec<_> = vring
542 .iter(self.mem.as_ref().unwrap().memory())
543 .map_err(|_| Error::DescriptorNotFound)?
546 if self.process_tx_requests(requests, vring)? {
547 // Send notification once all the requests are processed
551 println!("signal_used_queue error");
552 Error::NotificationFailed
559 /// Process the messages in the vring and dispatch replies
560 fn process_rx_queue(&mut self, vring: &VringRwLock) -> Result<()> {
561 dbg!("process_rx_queue");
562 let requests: Vec<_> = vring
565 .iter(self.mem.as_ref().unwrap().memory())
566 .map_err(|_| Error::DescriptorNotFound)?
569 if self.process_rx_requests(requests, vring)? {
570 // Send notification once all the requests are processed
574 println!("NotificationFailed");
575 Error::NotificationFailed
581 fn process_rx_queue_dump(&mut self, _vring: &VringRwLock) -> Result<()> {
582 dbg!("Do nothing, if you reach that point!");
586 /// Set self's VringWorker.
587 pub(crate) fn set_vring_worker(
589 vring_worker: &Arc<VringEpollHandler<Arc<RwLock<VhostUserCanBackend>>, VringRwLock, ()>>,
591 let rx_event_fd = self.controller.read().unwrap().rx_event_fd.as_raw_fd();
596 //u64::from(BACKEND_EFD))
602 /// VhostUserBackendMut trait methods
603 impl VhostUserBackendMut<VringRwLock, ()>
604 for VhostUserCanBackend
606 fn num_queues(&self) -> usize {
607 println!("num_queues: {:?}", NUM_QUEUES);
611 fn max_queue_size(&self) -> usize {
612 println!("max_queue_size: {:?}", QUEUE_SIZE);
616 fn features(&self) -> u64 {
617 // this matches the current libvhost defaults except VHOST_F_LOG_ALL
618 let features = 1 << VIRTIO_F_VERSION_1
619 | 1 << VIRTIO_F_NOTIFY_ON_EMPTY
620 | 1 << VIRTIO_RING_F_EVENT_IDX
621 | 1 << VIRTIO_CAN_F_CAN_CLASSIC
622 | 1 << VIRTIO_CAN_F_CAN_FD
623 | 1 << VIRTIO_RING_F_INDIRECT_DESC
624 | VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
626 println!("vhu_can->features: {:x}", features);
630 fn acked_features(&mut self, _features: u64) {
631 println!("\nacked_features: 0x{:x}\n", _features);
632 self.acked_features = _features;
635 fn protocol_features(&self) -> VhostUserProtocolFeatures {
636 let protocol_features = VhostUserProtocolFeatures::MQ
637 | VhostUserProtocolFeatures::CONFIG
638 | VhostUserProtocolFeatures::REPLY_ACK;
639 //| VhostUserProtocolFeatures::STATUS
641 println!("protocol_features: {:x}", protocol_features);
645 fn get_config(&self, offset: u32, size: u32) -> Vec<u8> {
646 // SAFETY: The layout of the structure is fixed and can be initialized by
647 // reading its content from byte array.
648 dbg!("vhu_can->get_config");
651 self.controller.write().unwrap()
655 .offset(offset as isize) as *const _ as *const _,
662 fn set_event_idx(&mut self, enabled: bool) {
663 dbg!(self.event_idx = enabled);
666 fn update_memory(&mut self, mem: GuestMemoryAtomic<GuestMemoryMmap>) -> IoResult<()> {
667 dbg!("update_memory\n");
668 self.mem = Some(mem);
676 vrings: &[VringRwLock],
678 ) -> IoResult<bool> {
679 dbg!("\nhandle_event:");
681 if evset != EventSet::IN {
682 return Err(Error::HandleEventNotEpollIn.into());
684 if device_event == RX_QUEUE {
685 println!("RX_QUEUE\n");
688 let vring = if device_event != BACKEND_EFD {
689 &vrings[device_event as usize]
691 println!("BACKEND_EFD\n");
692 let _ = self.controller.write().unwrap().rx_event_fd.read();
693 &vrings[RX_QUEUE as usize]
696 // vm-virtio's Queue implementation only checks avail_index
697 // once, so to properly support EVENT_IDX we need to keep
698 // calling process_request_queue() until it stops finding
699 // new requests on the queue.
701 vring.disable_notification().unwrap();
704 CTRL_QUEUE => self.process_ctrl_queue(vring),
705 TX_QUEUE => self.process_tx_queue(vring),
706 RX_QUEUE => self.process_rx_queue_dump(vring),
707 BACKEND_EFD => self.process_rx_queue(vring),
708 _ => Err(Error::HandleEventUnknown.into()),
710 if !vring.enable_notification().unwrap() {
715 // Without EVENT_IDX, a single call is enough.
717 CTRL_QUEUE => self.process_ctrl_queue(vring),
718 TX_QUEUE => self.process_tx_queue(vring),
719 RX_QUEUE => self.process_rx_queue_dump(vring),
720 BACKEND_EFD => self.process_rx_queue(vring),
721 _ => Err(Error::HandleEventUnknown.into()),
727 fn exit_event(&self, _thread_index: usize) -> Option<EventFd> {
728 dbg!("exit_event\n");
729 self.exit_event.try_clone().ok()