Linux SocketCAN access in Rust

Overview

Rust SocketCAN support

Maintenance status: This crate is in the process of entering renewed joint maintainership with @fpagliughi. Please stay patient for a while for this to get cleaned up. -- @mbr.

The Linux kernel supports using CAN-devices through a network-like API (see https://www.kernel.org/doc/Documentation/networking/can.txt). This crate allows easy access to this functionality without having to wrestle libc calls.

Please see the documentation for details.

Comments
  • Unmaintained?

    Unmaintained?

    This crate appears to be unmaintained. Any plans to continue supporting? If so, I'll consider making some pull-requests. If not, I might fork or consider other options.

    opened by twaddington 24
  • Standard/extended identifier implementation incorrect?

    Standard/extended identifier implementation incorrect?

    I believe the current implementation of the CANFrame constructor is incorrect, because it does not allow the construction of frames with an extended identifier less than 0x800.

    Code is currently as follows:

        pub fn new(id: u32, data: &[u8], rtr: bool, err: bool) -> Result<CanFrame, ConstructionError> {
    
            ...
    
            if id > EFF_MASK {
                return Err(ConstructionError::IDTooLarge);
            }
    
            // set EFF_FLAG on large message
            if id > SFF_MASK {
                _id |= EFF_FLAG;
            }
    

    Say I wanted to construct a frame with extended identifier 0x100. If I pass id=EFF_FLAG | 0x100 the constructor would return an IDTooLarge error. If I pass id=0x100, the constructor returns a frame with a standard identifier.

    The CAN standard allows for extended identifiers less than 0x800, and in fact these are commonly used, here are a few examples: https://stackoverflow.com/questions/63213413/standard-and-extended-messages-with-same-identifier https://forum.hms-networks.com/t/about-extended-frame-format/2237 https://kb.vector.com/entry/1093/

    Recommendation: add an argument to CANFrame::new to set the identifier type explicitly (this is a breaking change to the API- but current behavior is incorrect in some cases)

    opened by stabler 11
  • Embedded HAL Traits

    Embedded HAL Traits

    This MR builds off of @fpagliughi 's netlink-update branch (https://github.com/mbr/socketcan-rs/pull/20).

    I have implemented the following:

    • Embedded HAL blocking and non-blocking traits for CAN
    • Added examples for blocking read/write
    • Moved some code around into dedicated modules
    • Moved integration tests into tests/ folder

    Could probably use some advice on the best way to map the errors.

    opened by nnarain 9
  • Cross-platform support

    Cross-platform support

    Inherently, there is no need to use the kernel driver for this, since at least some of the features of this crate could be used also on MacOS or Windows. Using conditional compilation and features it might be possible to make it truly cross-platform

    opened by XVilka 6
  • Initial modernization (WIP)

    Initial modernization (WIP)

    This is an initial update to start work on this package again; to update the dependencies and start moving toward a more recent version of Rust.

    • Pulls in #13, and updates to the latest neli v0.6
    • Updates nix dependency to latest v0.23
    • Moves to Rust 2018 w/ MSRV 1.54
    • Errors conform to std::error::Error
    opened by fpagliughi 6
  • Netlink extensions (issue #32)

    Netlink extensions (issue #32)

    Hi everyone,

    this is a first step towards the requirements in #32. Specifically, it implements:

    • creating vcan (and theoretically other) CAN interfaces
    • deleting interfaces
    • reading rudimentary interface data (name, MTU, up/down) (can be extended easily by adding more entries in the corresponding loop)
    • setting MTU (switching VCAN from FD to non-FD and vice versa)

    All of the tests added here need to be run as root and/or with CAP_NET_ADMIN capability. As such, I hid them behind another feature flag. They work locally for me.

    I did not get to bitrate and such because that actually does not work with vcan out-of-the-box; and I don't have a physical CAN device at home atm.

    For follow-up changes it might be interesting to know where I got the information from (which was quite painful as they documentation leaves some things to be desired..):

    • netlink and rnetlink documentation (https://man7.org/linux/man-pages/man7/netlink.7.html and https://man7.org/linux/man-pages/man7/rtnetlink.7.html)
    • iproute2 (aka iptools) source: https://github.com/shemminger/iproute2
    • ultimately, I mostly ended up just using strace with the ip link commands I was interested in
    opened by jreppnow 5
  • Use libc types instead of manually choosing i32 or i64

    Use libc types instead of manually choosing i32 or i64

    Hi Marc,

    LIBC's timeval struct is defined as this:

    timeval {
        tv_sec: time_t;
        tv_usec: suseconds_t
    }
    

    Those types are available in rust as well, and for that reason should be used.

    I had to fix that to use socketcan on x86_64 macos, where tv_sec is an i64 while tv_usec is an i32. Some differencies may appear on other platforms as well.

    Although macos does not support CAN interface, as we use macbooks for development it is very handy to use socketcan for replaying can dumps

    Note that this patch works well on top of release 1.6.0; on master branch I get even more errors because of the new dependency to netlink-rs. If you accept this change, it would be nice to publish a fixed release 1.6.1!

    Best regards

    opened by RouquinBlanc 5
  • Exchange custom netlink fork for neli crate

    Exchange custom netlink fork for neli crate

    This removes the custom netlink dependency in exchange for the neli-crate. I have tested bring_up and bring_down and it seems to work. There is a minor difference in the send that I have not figured out yet why sa_family is not added in neli or if that is even relevant since it has the intended effect.

    strace -s 100 -f -x of

        let iface = CanInterface::open("vcan0").expect("Failed to lookup vcan0 iface");
        iface.bring_down().unwrap();
    

    netlink-rs fork:

    bind(3, {sa_family=AF_NETLINK, nl_pid=29418, nl_groups=00000000}, 16) = 0
    sendto(3, {{len=32, type=RTM_NEWLINK, flags=NLM_F_REQUEST|NLM_F_ACK, seq=0, pid=0}, {ifi_family=AF_UNSPEC, ifi_type=ARPHRD_NETROM, ifi_index=if_nametoindex("vcan0"), ifi_flags=0, ifi_change=0x1}}, 32, 0, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, 16) = 302
    recvfrom(3, {{len=36, type=NLMSG_ERROR, flags=NLM_F_CAPPED, seq=0, pid=29418}, {error=0, msg={len=32, type=RTM_NEWLINK, flags=NLM_F_REQUEST|NLM_F_ACK, seq=0, pid=0}}}, 4096, 0, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, [16->12]) = 36
    

    neli:

    bind(3, {sa_family=AF_NETLINK, nl_pid=960, nl_groups=00000000}, 12) = 0
    sendto(3, {{len=32, type=RTM_NEWLINK, flags=NLM_F_REQUEST|NLM_F_ACK, seq=0, pid=0}, {ifi_family=AF_UNSPEC, ifi_type=ARPHRD_NETROM, ifi_index=if_nametoindex("vcan0"), ifi_flags=0, ifi_change=0x1}}, 32, 0, NULL, 0) = 32
    recvfrom(3, {{len=36, type=NLMSG_ERROR, flags=NLM_F_CAPPED, seq=0, pid=960}, {error=0, msg={len=32, type=RTM_NEWLINK, flags=NLM_F_REQUEST|NLM_F_ACK, seq=0, pid=0}}}, 32768, 0, NULL, NULL) = 36
    

    WIP: since this is still waiting for merge of: https://github.com/jbaublitz/neli/pull/61, I will exchange the git link for a version once that is released.

    opened by marcelbuesing 4
  • non blocking write_frame

    non blocking write_frame

    I see that write_frame and write_frame_insists serve different purpose. write_frame_insists is supposed to be blocking while write_frame isn't. So, I tried to use write_frame with expectation that it won't block and return immediately, practically just adding can frame to the tx_queue. However, I observed that between each frame, there is a delay about 1 ms. When I read socketcan app in C/C++, I found this little piece of code:

    fcntl(soc, F_SETFL, O_NONBLOCK);

    I forked this repo without informing you first to particularly add that line of code, because I need it right away in my project. So, what do you think to handle this issue? How do we expose this configuration? adding set_nonblocking method to CANSocket struct? Add new parameter open method?

    FYI, I am using v1.6.

    opened by wijayaadhisurya 4
  • Setup GH action based on actions-rs/meta template

    Setup GH action based on actions-rs/meta template

    Basically a copy from actions-rs/meta with adapted MSRV. I think it might make sense to add the security-audit job as well in the future but I think that requires separate secret variable config in the repository.

    opened by marcelbuesing 3
  • Using socketcan with asynchronous loop

    Using socketcan with asynchronous loop

    Hi Marc,

    For a quick project I have been playing with socketcan, but all my other IO (mainly TCP) were using Metal IO; as a first run I'm using 2 different threads, but in a short future it would be nice to read/write to the CAN socket directly from the async loop!

    2 things are missing at the moment, which I added in a fork in this fork:

    • access to the internal file descriptor
    • API to set as non-blocking. (Directly related to #6)

    Then I wrote this small miocan adapter to make the glue between socketcan 1.6 and mio 0.6.9, plus an example of usage which works nicely on read.

    I don't know yet what would be the best course (integration in socketcan? in mio? 3rd repo as now?), but at least it's pretty cool to bootstrap that work!

    Please comment when you have time. Cheers!

    opened by RouquinBlanc 3
  • Netlink (neli) code for the CAN interfaces

    Netlink (neli) code for the CAN interfaces

    It would be great to have full coverage of the Netlink API to interact with the CAN interfaces. Or even something better than what is already there. I don't have any experience with the Netlink CAN interfaces, so if anyone has some existing code to get it started, that would be helpful.

    @marcelbuesing ? @jreppnow ?

    help wanted 
    opened by fpagliughi 7
  • Use 'nix' crate instead of 'libc' when possible.

    Use 'nix' crate instead of 'libc' when possible.

    The libc crate is a low-level, unsafe wrapper around much of the standard C library and platform system calls. The nix crate sits at a slightly higher level, wrapping the libc calls into safe alternatives. I just submit a couple small PR's to the nix repo to add some missing functionality for SocketCAN in Linux:

    • https://github.com/nix-rust/nix/pull/1914
    • https://github.com/nix-rust/nix/pull/1912

    If those land, we can start rewriting some of the socket functionality to use it. It moves the CanAddr upstream, and makes, for example, the CanSocket::if_open() much simpler without any unsafe calls directly:

    pub fn open_interface(ifindex: c_uint) -> nix::Result<CanSocket> {
        let addr = CanAddr::new(ifindex);
    
        let fd = socket(
            AddressFamily::Can,
            SockType::Raw,
            SockFlag::empty(),
            SockProtocol::CanRaw
        )?;
    
        if let Err(err) = bind(fd, &addr) {
            close(fd);
            return Err(err);
        }
    
        Ok(CanSocket { fd })
    }
    
    opened by fpagliughi 0
  • socketcan2-rs

    socketcan2-rs

    Since there isn't that much progress in this library for some time, I published my implementation of a libc-socketcan wrapper. You can find it here: https://crates.io/crates/socketcan2

    socketcan2 supports timestamps which also work in combination with multithreading (in contrast to the method used in this project) and it is possible to wait on multiple CAN devices in the same thread using one timeout what indispensable for certain kinds of applications.

    opened by xR3b0rn 8
  • Ideas for v2.0

    Ideas for v2.0

    Hey All. Thanks for all the feedback recently. It feels good to finally get some inertia on this crate after so long!

    I'd like to get v2.0 released by the end of the year, if that's possible. Here's what I'm thinking for it:

    • Get all the outstanding issues and PR's done:

      • @j4r0u53k is working on #16 to bring in CAN FD support.
      • @nnarain 's PR #24 would solve some of the API and the ExtendedID issues.
      • @marcelbuesing 's #21 would restore CI to the repo
    • Make better use of the upstream crates.

      • Some of the low-level types, constants, and other definitions have since been added to the upstream crates, like nix. So give a quick review and remove whatever possible from this one.
    • [Maybe] Consolidate the error types or make a wrapping Error type with a Result

      • Lately I've been finding it tough to use a lot of libraries in an application when each has a dozen error types.
      • It's nice when a library has a single, top-level error to say, for example, "Was this a CAN error?"
    • Overall cleanup:

      • Better documentation on all the types, functions, modules, etc
      • More restrictive linte like #![deny(missing_docs)], etc
      • Unit Tests!
    • Timestamps

      • The whole reason I wanted to update this crate in the first place was because I needed hardware timestamps! Now I can't even remember if I did anything about that.

    After that is finished and released, I would like to start putting together v2.1 to add full NetLink support for the CAN interfaces.

    opened by fpagliughi 0
  • No way to mutate CanFrame

    No way to mutate CanFrame

    I'm currently writing a rust lib for uavcan. I'm planning to use socketcan as the main testing platform (for convenience reasons).

    The way the CanFrame is currently structured there's no way to mutate the dlc/data after a frame has been created. That means I will have to work with an intermediate structure until the moment I'm ready to transfer, then convert it into a socketcan::CanFrame.

    Would you mind exposing some methods which makes it possible to implement something similar to the following trait?

    pub trait TransferFrame {
    /// Maximum data length the transfer protocol supports.
    const MAX_DATA_LENGTH: usize;
    
    /// Create a new TransferFrame with id: id, and length 0.
    /// Data length can be changed with `set_data_length(&self)`.
    /// Data can be changed with `data_as_mut(&mut self)`.
    fn new(id: TransferFrameID) -> Self;
    
    /// Returns the 28 bit ID of this TransferFrame.
    ///
    /// When deciding which frame that will be transmitted,
    /// the ID is used to prioritze (lower ID means higher priority)
    fn id(&self) -> TransferFrameID;
    
    /// Returns a slice with the data in this TransferFrame
    ///
    /// Length can be found by checking the length
    /// of this slice `self.data().len()`
    fn data(&self) -> &[u8];
    
    /// Returns a mutable slice with the data in this TransferFrame
    /// use this method to set/change the data inside this TransferFrame
    fn data_as_mut(&mut self) -> &mut[u8];
    
    /// Set the data length of this TransferFrame
    ///
    /// ## Panics
    /// `set_data_lengt(&mut self, length: usize)` should panic if `length > T::MAX_DATA_LENGTH`
    fn set_data_length(&mut self, length: usize);
    
    opened by kjetilkjeka 0
Rust DLT (Diagnostic Log and Trace) packet parser

dlt_parse A zero allocation rust library for basic parsing & writing DLT (Diagnostic Log and Trace) packets. Currently only the parsing and writing of

Julian Schmid 23 Dec 16, 2022
Rust dbc parser

can-dbc A CAN-dbc format parser written with Rust's nom parser combinator library. 1. Example Read dbc file and generate Rust structs based on the mes

Marcel 38 Dec 19, 2022
Asynchronous Linux SocketCAN sockets with tokio

tokio-socketcan SocketCAN support for tokio based on the socketcan crate. Example echo server use futures_util::stream::StreamExt; use tokio_socketcan

Terry 29 Nov 8, 2022
Asynchronous Linux SocketCAN - Broadcast Manager support (BCM) with tokio

tokio-socketcan-bcm The Broadcast Manager protocol provides a command based configuration interface to filter and send (e.g. cyclic) CAN messages in k

Marcel 4 Nov 8, 2022
An easy-to-use SocketCAN library for Python and C++, built in Rust.

JCAN An easy-to-use SocketCAN library for Python and C++, built in Rust, using cxx-rs and pyo3. Warning: I have never used Rust before and I don't kno

Leigh Oliver 4 Feb 9, 2023
Access German-language public broadcasting live streams and archives on the Linux Desktop

Deutsche Version Televido Televido (“Television” in Esperanto) lets you livestream, search, play and download media from German-language public televi

David C. 10 Nov 4, 2023
TMM is a Linux native game modding tool. it allows to install and depoly mods for Linux native and wine games.

Tux Mod Manager TMM is a Linux native mod manager made with the Tauri toolkit. It can install, load, remove and deploy mods for both Linux native and

Mathiew May 119 Dec 27, 2022
Rust crate which provides direct access to files within a Debian archive

debarchive This Rust crate provides direct access to files within a Debian archive. This crate is used by our debrep utility to generate the Packages

Pop!_OS 11 Dec 18, 2021
SubStrings, Slices and Random String Access in Rust

SubStrings, Slices and Random String Access in Rust This is a simple way to do it. Description Rust string processing is kind of hard, because text in

João Nuno Carvalho 2 Oct 24, 2021
Community SVD file, peripheral access crate in embedde Rust for WinnerMicro W800, W801 & W806 chip

Community SVD file, peripheral access crate in embedde Rust for WinnerMicro W800, W801 & W806 chip

Luo Jia 37 Jul 31, 2022
A Rust synchronisation primitive for "Multiplexed Concurrent Single-Threaded Read" access

exit-left verb; 1. To exit or disappear in a quiet, non-dramatic fashion, making way for more interesting events. 2. (imperative) Leave the scene, and

Jonathan de Jong 0 Dec 5, 2021
Low level access to ATmega32U4 registers in Rust

Deprecation Note: This crate will soon be deprecated in favor of avr-device. The approach of generating the svd from hand-written register definitions

Rahix 9 Jan 27, 2021
zigfi is an open-source stocks, commodities and cryptocurrencies price monitoring CLI app, written fully in Rust, where you can organize assets you're watching easily into watchlists for easy access on your terminal.

zigfi zigfi is an open-source stocks, commodities and cryptocurrencies price monitoring CLI app, written fully in Rust, where you can organize assets

Aldrin Zigmund Cortez Velasco 18 Oct 24, 2022
Fully typed access to the Erigon db in rust

Overview Fully typed access to the Erigon database in rust. use erigon_db::{Erigon, env_open}; use ethereum_types::Address; fn main() -> eyre::Result

Gio 89 Dec 5, 2022
OBKV Table Client is Rust Library that can be used to access table data from OceanBase storage layer.

OBKV Table Client is Rust Library that can be used to access table data from OceanBase storage layer. Its access method is different from JDBC, it skips the SQL parsing layer, so it has significant performance advantage.

OceanBase 4 Nov 14, 2022
Easy access of struct fields in strings using different/custom pre/postfix: "Hello, {field}" in rust

Easy access to struct fields in strings ?? add strung to the dependencies in the Cargo.toml: [dependencies] strung = "0.1.3" ?? use/import everything

Dekirisu 2 Sep 19, 2022
Pure rust library for reading / writing DNG files providing access to the raw data in a zero-copy friendly way.

DNG-rs   A pure rust library for reading / writing DNG files providing access to the raw data in a zero-copy friendly way. Also containing code for re

apertus° - open source cinema 4 Dec 1, 2022
Rust wrapper for the Google Places API. Access their hundreds of millions of places, reviews, and ratings.

Google Places API Working Examples cargo run --example nearby_search cargo run --example place_details cargo run --example find_place cargo run --exam

Jared Ucherek 4 Jun 12, 2023
Rust library for concurrent data access, using memory-mapped files, zero-copy deserialization, and wait-free synchronization.

mmap-sync mmap-sync is a Rust crate designed to manage high-performance, concurrent data access between a single writer process and multiple reader pr

Cloudflare 97 Jun 26, 2023
🍥 Access the rust playground right in your terminal

rustycli — ?? Access the rust playground right in your terminal ?? rustycli is a tool, allowing you to access the rust playground right in the termina

Nabeen Tiwaree 29 Jul 31, 2023