vhost-device-can: use the same socket for send/recv#937
Conversation
|
When fixing this, some tests started to fail since now the opening of the socket is happening in new(). Before, those tests did not require to open a socket to work. I fixed those tests by adding a few commits together with the fix. I wonder if these tests should be fixed here or in another PR. |
|
To run the tests, we require a virtual can interface in the host named |
Is this something new (i.e. added here) or was there before this PR? |
It was in the code before but it was not being tested. The tests were done to not use a can interface. I am not sure if that was done on purpose. |
|
I think we should wrap the CanFdSocket field into an enum, and add a This way we can add support in the future for classic Can sockets (i.e. not FD) which is something I wanted to do anyway. |
Maybe to avoid updating the container image xD (I have no idea). |
If the linux images contain the |
Thanks! I'll try that. I did not get it completely yet though. |
Use the same socket for send/receive in the backend to prevent the guest from receiving two copies of the message when it sends to the local CAN bus. Fix tests and remove test_can_read_socket_fail() test since read_can_socket() does not open the socket anymore. Fixes rust-vmm#925 Reported-by: Francesco Valla <francesco@valla.it> Signed-off-by: Matias Ezequiel Vara Larsen <mvaralar@redhat.com>
Most of the tests were using `can0` as interface but some used `can`. Use `can0` interface for all tests and `canx` for those that expect an interface down. Signed-off-by: Matias Ezequiel Vara Larsen <mvaralar@redhat.com>
To support 64 bytes packet, set CAN_FRMF_TYPE_FD flag in test_can_controller_operation test. Signed-off-by: Matias Ezequiel Vara Larsen <mvaralar@redhat.com>
|
The PR has now a wider scope :(. I am OK to split if it is required. Bear in mind that I used Claude for the last commit. Claude proposed a single builder for both socket types but I ignored it for the moment. |
Rename this test that previously had to fail since the interface was down. The previous test was testing the NoOutputInterface path which does not exist anymore. Make the test pass when transmission succeeds. Signed-off-by: Matias Ezequiel Vara Larsen <mvaralar@redhat.com>
Add a mock socket for tests so that tests no longer require a CAN interface on the host. Signed-off-by: Matias Ezequiel Vara Larsen <mvaralar@redhat.com>
stefano-garzarella
left a comment
There was a problem hiding this comment.
Maybe we should re-order commit, for example the last 1 and other fixes should come first, but I did just a quick look, I may be wrong.
There was a problem hiding this comment.
About commit 6c94dae can we improve better the commit description?
What I don't get is why having 1 socket fixes the issue we had (I don't know much about can sockets, etc.).
| ctrl.can_socket.read_frame() | ||
| }; | ||
|
|
||
| if let Ok(frame) = frame_result { |
There was a problem hiding this comment.
What happens here if there is no frame returned by read_frame() ?
Are we spinning acquiring now the shared lock?
Maybe this is fine, since we are releasing it in the loop, but I'd like just to understand better if it's expected.
There was a problem hiding this comment.
I did not get the question.
There was a problem hiding this comment.
I mean, if read_frame() doesn't return any frame, here we loop calling read_frame() in a loop, since IIUC the socket is no-blocking.
Is that okay?
There was a problem hiding this comment.
I am not sure if that's OK. It seems working, i.e., I did not observe starvation in the other thread that get a write lock.
| if self.check_features(VIRTIO_CAN_F_CAN_FD) && res_len > 8 && can_name == "vcan0" { | ||
| if self.check_features(VIRTIO_CAN_F_CAN_FD) && res_len > 8 && can_name == "can0" { | ||
| res_flags |= CAN_FRMF_TYPE_FD; | ||
| warn!("\n\n\nCANFD VCAN0\n\n"); |
There was a problem hiding this comment.
stil VCAN0 here?
BTW are we sure it's fine to can0 instead of vcan0?
Not sure if v prefix was done for a virtual purporse.
There was a problem hiding this comment.
The v is from virtual CAN which is the interface used in the host although it can be named also can0. In the guest, the driver is a real can, e.g., virtio-can. Virtual CAN is like an emulator.
There was a problem hiding this comment.
sorry, now I'm more confused than before :-)
What this code is doing ? Is related to test ?
There was a problem hiding this comment.
This code is not related with the test. There is a problem with this code. It is inferring that the host is using virtual can since the name is vcan0, which can be false since the name can be anything. I missed that when I changed the name although it would work because I can just set the name of the interface to can0 but it does not seem correct.
There was a problem hiding this comment.
ah, so maybe better to use a dedicated commit for this and explain better the issue
| @@ -248,7 +248,7 @@ mod tests { | |||
| #[test] | |||
| fn test_can_valid_configuration_start_backend_server_fail() { | |||
There was a problem hiding this comment.
I think this is pre-existing, but the test name here is a bit confusing, I mean "valid_configuration" while we are opening an invalid interface IIUC.
There was a problem hiding this comment.
yes it is, and I wonder what is the difference with test_can_valid_configuration_start_backend() test
There was a problem hiding this comment.
mmm, so if we run cargo test before commit 3be95bc but after commit 1 is it working or failing?
IMO we should keep tests running to avoid breaking the bisectability, so better to move this commit or squash.
There was a problem hiding this comment.
I see you mean that test shall pass for each commit right?
There was a problem hiding this comment.
yep, each commit should build and pass tests
| match self { | ||
| CanSocketKind::Fd(socket) => socket.read_frame(), | ||
| #[cfg(test)] | ||
| CanSocketKind::Mock => Err(std::io::ErrorKind::WouldBlock.into()), |
There was a problem hiding this comment.
Why returning WouldBlock ?
There was a problem hiding this comment.
It seems it tries to emulate what recv() in socket.read_frame() returns when there is nothing to read, which is always the case for the Mock interface.
Summary of the PR
Use the same socket for send/receive in the backend to prevent guest to receiving two copies of the message when it sends to the local CAN bus.
Fixes #925
Reported-by: Francesco Valla francesco@valla.it
Requirements
Before submitting your PR, please make sure you addressed the following
requirements:
git commit -s), and the commit message has max 60 characters for thesummary and max 75 characters for each description line.
test.
Release" section of CHANGELOG.md (if no such section exists, please create one).
unsafecode is properly documented.