Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to configure ChecksumCapabilities for RawSocket #328

Open
champtar opened this issue Mar 15, 2020 · 4 comments
Open

Allow to configure ChecksumCapabilities for RawSocket #328

champtar opened this issue Mar 15, 2020 · 4 comments

Comments

@champtar
Copy link

On Linux, packets that stay local to the machine (moving from the host to a container for example) don't always have their checksum computed, see for example https://patchwork.ozlabs.org/patch/261822/.
The proper fix would be to check for TP_STATUS_CSUMNOTREADY, but an easy workaround is to have a way to change the ChecksumCapabilities or DeviceCapabilities.

As a rust noob here my solution for now:

#[derive(Debug)]
pub struct RawSocket2 {
    inner: RawSocket,
}

impl AsRawFd for RawSocket2 {
    fn as_raw_fd(&self) -> RawFd {
        self.inner.as_raw_fd()
    }
}

impl RawSocket2 {
    pub fn new(name: &str) -> io::Result<RawSocket2> {
        Ok(RawSocket2{
            inner: RawSocket::new(name)?,
        })
    }
}

impl<'a> Device<'a> for RawSocket2 {
    type RxToken = <RawSocket as Device<'a>>::RxToken;
    type TxToken = <RawSocket as Device<'a>>::TxToken;

    fn capabilities(&self) -> DeviceCapabilities {
        let mut checksum_caps = ChecksumCapabilities::default();
        checksum_caps.ipv4 = Checksum::Tx;
        checksum_caps.udp = Checksum::Tx;
        checksum_caps.tcp = Checksum::Tx;
        checksum_caps.icmpv4 = Checksum::Tx;
        checksum_caps.icmpv6 = Checksum::Tx;
        let mut c = self.inner.capabilities();
        c.checksum = checksum_caps;
        c
    }

    fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
        self.inner.receive()
    }

    fn transmit(&'a mut self) -> Option<Self::TxToken> {
        self.inner.transmit()
    }
}
@whitequark
Copy link
Contributor

whitequark commented Apr 14, 2020

I agree that checking for TP_STATUS_CSUMNOTREADY would be a proper solution. Unfortunately we can't integrate it with the rest of smoltcp at the moment, I believe, since checksum capabilities are tracked in it per-interface, not per-packet. Is there a way to determine whether an interface will always return packets with TP_STATUS_CSUMNOTREADY set?

@champtar
Copy link
Author

I'm only using smoltcp for a POC, so being able to configure ChecksumCapabilities is good enough me.
No interface will return 100% packets with TP_STATUS_CSUMNOTREADY I think, anything routed from outside will have a checksum. I don't see any good heuristics.

@whitequark
Copy link
Contributor

What do you think about checking for TP_STATUS_CSUMNOTREADY and if it is set, recalculating the checksum?

@champtar
Copy link
Author

good idea, that would make smoltcp just work even if not optimal for performance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants