An experimental IPC interface definition language for Hubris.

Overview

Idol: interface definitions for Hubris

This is an experimental interface definition language for defining IPC interfaces between tasks in a Hubris application.

IDL format

Currently, the IDL "format" is merely the idol::syntax::Interface struct as loaded via serde from a RON file. The best docs for the format are the rustdocs on that struct and its children.

Here is a simple example.

Interface(
    name: "Spi",
    ops: {
        "exchange": (
            args: {
                "device_index": (type: "u8"),
            },
            leases: {
                "source": (type: "[u8]", read: true),
                "sink": (type: "[u8]", write: true),
            },
            reply: Result(
                ok: "()",
                err: CLike("SpiError"),
            ),
        ),
    },
)

Generating a client interface

This assumes you have an Idol file called my_interface.idol living somewhere in your source tree, which defines an IPC interface called MyInterface.

By convention in Hubris we use "API crates" to hold IPC client interfaces; for your my-interface, this would conventionally be my-interface-api.

Inside that crate, you need to add this to Cargo.toml:

[build-dependencies]
idol = {git = "https://github.com/oxidecomputer/idol/"}

And then create a build.rs file containing at least the following:

fn main() -> Result<(), Box<dyn std::error::Error>> {
    idol::client::build_client_stub(
        "../../idl/my-interface.idol",  // or whatever path
        "client_stub.rs",
    )?;
    Ok(())
}

That will generate client code at build time. To actually compile the generated code, you have to pull it into your lib.rs by adding:

include!(concat!(env!("OUT_DIR"), "/client_stub.rs"));

This will generate:

  • A MyInterface type that wraps a server TaskId and exposes methods for each IPC operation. Methods take arguments in order, followed by leases (as references).

  • A MyInterfaceOperation enum, which you don't generally need to use directly, but is there if you need it.

Generating a server

This assumes you have an Idol file called my_interface.idol living somewhere in your source tree, which defines an IPC interface called MyInterface.

By convention in Hubris, the server for my-interface would be in a crate called my-interface-server (unless there are multiple implementations).

Inside that crate, you need to add this to Cargo.toml:

[dependencies]
idol-runtime = {git = "https://github.com/oxidecomputer/idol/"}

[build-dependencies]
idol = {git = "https://github.com/oxidecomputer/idol/"}

And then create a build.rs file containing at least the following:

fn main() -> Result<(), Box<dyn std::error::Error>> {
    idol::server::build_server_support(
        "../../idl/my-interface.idol",  // or whatever path
        "server_stub.rs",
        idol::server::ServerStyle::InOrder,
    )?;
    Ok(())
}

(More on that ServerStyle in a moment.)

That will generate server code at build time. To actually compile the generated code, you have to pull it into your main.rs by adding:

include!(concat!(env!("OUT_DIR"), "/server_stub.rs"));

This will generate a trait describing the required implementation of the server. The trait is called InOrderMyInterfaceImpl in this case, and contains a function for each IPC operation. To finish writing a server, you must impl this trait for the type of your choice (generally, a struct holding your server's state).

Finally, the generated code has provided plumbing for you to use this trait with the generic idol_runtime::dispatch function. Your server's main loop should resemble, at minimum:

let mut incoming = [0u8; INCOMING_SIZE];
let mut server = MyServerImpl;
loop {
    idol_runtime::dispatch(&mut incoming, &mut server);
}

Variations and corner cases

Servers that use notifications

To handle notifications,

  • Implement the idol_runtime::NotificationHandler trait for your server, alongside the generated server trait.

  • Call dispatch_n instead of dispatch.

Servers that process multiple messages concurrently

The default InOrder server style must reply to each message before accepting the next. Some servers are more complex than this and have multiple messages in flight. For such servers, switch the style to Pipelined.

In Pipelined style, the generated trait changes: instead of each function returning the IPC's return type, they all return (). Its name also changes, from InOrder(YourService)Impl to Pipelined(YourService)Impl.

This causes dispatch and friends to not automatically send replies, except in egregious cases (operation unknown, arguments failed to unmarshal). Instead, your impl of the server trait is responsible for replying to clients at the appropriate type, using userlib::sys_reply or a wrapper.

When implementing a pipelined server, it's easy to accidentally forget to reply to clients -- be careful!

Using closed RECV

Generated server traits include two functions supporting closed RECV, which are stubbed out by default. Implement them to be able to switch between open and closed at will:

    fn recv_source(&self) -> Option<userlib::TaskId>;
    fn closed_recv_fail(&mut self);

recv_source names the task to listen to, or None for all tasks. closed_recv_fail will be called by idol_runtime if you name a specific task but that task has died.

Enums as arguments

By default, Idol uses zerocopy to marshal and unmarshal argument and return types. This requires that, on the receiving side, any pattern of bits must be a valid member of the type. This isn't true for bool or most enums.

You can request that Idol instead use num_traits::FromPrimitive to unmarshal values. Instead of

"cs_state": (type: "CsState"),

you want:

"cs_state": (
    type: "CsState",
    recv: FromPrimitive("u8"),
,

The value taken by recv is an enum so we can add more methods in the future.

Comments
  • Server stub `INCOMING_SIZE` larger than necessary?

    Server stub `INCOMING_SIZE` larger than necessary?

    Hi folks - I've been fiddling around with hubris on an stm32f4 discovery board, and was trying to update one of my tasks to use idolatry following the changes made to similar tasks in hubris, and ran into a couple questions: should the generated server's INCOMING_SIZE be the max of the message sizes instead of the sum, and what is the proper way to handle alignment when declaring a buffer to be given to idol_runtime::dispatch?

    Specifically, I was updating a task that's almost identical to stm32h7-rcc based on this commit in hubris; this bit in particular:

        // Ensure our buffer is aligned properly for a u32 by declaring it as one.
    -   let mut buffer = [0u32; 1];
    +   let mut buffer = [0u8; idl::INCOMING_SIZE];
    

    The INCOMING_SIZE in the generated server stub is

    pub const INCOMING_SIZE: usize = 0
        + ENABLE_CLOCK_RAW_MSG_SIZE
        + DISABLE_CLOCK_RAW_MSG_SIZE
        + ENTER_RESET_RAW_MSG_SIZE
        + LEAVE_RESET_RAW_MSG_SIZE
        ;
    

    which makes buffer four times larger than it was before (which I believe is unnecessary based on https://github.com/oxidecomputer/idolatry/blob/ec1047c/runtime/src/lib.rs#L154-L161). The comment is also out of date in terms of alignment, but I'm not sure what the right fix is; in my task I tried keeping buffer declared as [0u32; 1] and adding an assertion that its size matched idl::INCOMING_SIZE, which is how I bumped into this question.

    opened by jgallagher 6
  • Add server::build_restricted_server_support()

    Add server::build_restricted_server_support()

    build_restricted_server_support() takes an additional arg compared to build_server_support(): a map of operation names to task names. For any operation present in the map, additional code is generated in the server that checks that the calling task is one of the specified task names (with error checking for operation names or task names that don't exist).

    If the map of allowed callers is nonempty, server code generation is tightly tied to the hubris build system: it will read $HUBRIS_TASKS both to know what task names are legal and to map them to indices for the checks performed.

    This PR also adds a ClientError::AccessViolation variant (which maps to the already-existing ReplyFaultReason::AccessViolation), which is the error we return if a restricted operation is called by a different task.

    opened by jgallagher 4
  • Clippy

    Clippy

    Minor changes to satisfy clippy lints. This was build tested against all app.tomls in hubris & boot tested on the lpc55xpresso board successfully.

    opened by flihp 2
  • Allow leases of type other than [u8]

    Allow leases of type other than [u8]

    Non-[u8] leases seem to work fine, but the generated client code doesn't handle them properly. This change allows leases of any type that implement zerocopy::{AsBytes, FromBytes}.

    opened by pokeylope 1
  • duplicate operations, arguments, and leases are allowed

    duplicate operations, arguments, and leases are allowed

    Through a mismerge in an Idol file, I (accidentally) discovered that the Idolatry allowed duplicate operations and arguments. On the one hand, this is not surprising, as it is Serde's default behavior (with the last key winning), but it would also be be nice to prevent this -- this is certainly an error in the Idol file, and it can be hard to debug. Unfortunately, the normal mechanism for doing this -- namely. use serde_with and then the #[serde(with = "serde_with::rust::maps_duplicate_key_is_error")] annotation -- doesn't work for IndexMap. This calls for more Serde-fu than I currently possess!

    opened by bcantrill 1
  • off-by-one error in maximum lease length calculation in client stub

    off-by-one error in maximum lease length calculation in client stub

    In the client stub, the size calculation is off-by-one:

    https://github.com/oxidecomputer/idolatry/blob/ec1047cce1c35dad72162b102e9a8193f0f4572d/src/client.rs#L134

    This (incorrectly) panics if the length is equal to the maximum allowed length; the check should be >, not >=.

    opened by bcantrill 1
  • Add Encoding::Hubpack

    Add Encoding::Hubpack

    Example of a generated client stub for an idempotent operation with a single u64 arg:

        // operation: get_reset_reason2 (4)
        // idempotent - will auto-retry
        pub fn get_reset_reason2(
            &self,
            foo: u64,
        ) -> ComboResetReason {
            let (arg_foo,) = (foo,);
            #[allow(non_camel_case_types)]
            #[derive(serde::Serialize, hubpack::SerializedSize)]
            struct Jefe_get_reset_reason2_ARGS {
                foo: u64,
            }
    
            const REPLY_SIZE: usize = {
                <ComboResetReason as hubpack::SerializedSize>::MAX_SIZE
            };
    
            let args = Jefe_get_reset_reason2_ARGS {
                foo: arg_foo,
            };
    
            let mut argsbuf = [0; <Jefe_get_reset_reason2_ARGS as hubpack::SerializedSize>::MAX_SIZE];
            let arglen = hubpack::serialize(&mut argsbuf, &args).unwrap_lite();
            let mut reply = [0u8; REPLY_SIZE];
    
            loop {
            let task = self.current_id.get();
    
            let (rc, len) = sys_send(
                task,
                JefeOperation::get_reset_reason2 as u16,
                &argsbuf[..arglen],
                &mut reply,
                &[
                ],
            );
            if let Some(g) = userlib::extract_new_generation(rc) {
                self.current_id.set(userlib::TaskId::for_index_and_gen(task.index(), g));
                continue;
            }
            if rc != 0 { panic!(); }
            let (v, _): (ComboResetReason, _) = hubpack::deserialize(&reply[..len]).unwrap_lite();
            return v;
            }
        }
    

    and the relevant bits from the corresponding server stub:

    pub const GET_RESET_REASON2_MSG_SIZE: usize =
        <Jefe_get_reset_reason2_ARGS as hubpack::SerializedSize>::MAX_SIZE;
    pub const GET_RESET_REASON2_REPLY_SIZE: usize =<ComboResetReason as hubpack::SerializedSize>::MAX_SIZE;
    
    // ...
    
    pub fn read_get_reset_reason2_msg(bytes: &[u8])
        -> Option<Jefe_get_reset_reason2_ARGS>
    {
        hubpack::deserialize(bytes).ok().map(|(x, _)| x)
    }
    
    // ...
    
                JefeOperation::get_reset_reason2 => {
                    let args = read_get_reset_reason2_msg(incoming).ok_or_else(|| ClientError::BadMessageContents.fail())?;
                    let r = self.1.get_reset_reason2(
                        rm,
                        args.foo,
                    );
                    match r {
                        Ok(val) => {
                            let mut reply_buf = [0u8; GET_RESET_REASON2_REPLY_SIZE];
                            let n_reply = hubpack::serialize(&mut reply_buf, &val).map_err(|_| ()).unwrap_lite();
                            userlib::sys_reply(rm.sender, 0, &reply_buf[..n_reply]);
                            Ok(())
                        }
                        Err(val) => Err(val.map_runtime(|e| match e { })),
                    }
                }
    
    opened by jgallagher 0
  • Add retry loop in generated client for idempotent operations

    Add retry loop in generated client for idempotent operations

    It looked like the simplest way to conditionally introduce the loop was to change the final statement to always be (the equivalent of) return v; instead of just v, so I also added a suppression for clippy::needless_return, since all non-idempotent operations now end with a needless return.

    Fixes #19.

    opened by jgallagher 0
  • Client support for non-u8 lease types.

    Client support for non-u8 lease types.

    The server-side runtime support has attempted to allow non-u8 lease types since the beginning, but the client-side code generator is, uh, more grown than designed. :-) This alters it to pass leased buffers through zerocopy::AsBytes, allowing any type that implements the appropriate zerocopy traits to be used.

    Thanks to Github user @pokeylope for pointing this out and sending an initial version of this commit.

    opened by cbiffle 0
  • Fix clippy complaints

    Fix clippy complaints

    This adds a few clippy::allow annotations to make Clippy useful in Hubris; right now, any true issues are hidden behind a wall of complaints about the autogenerated bindings.

    opened by mkeeter 0
  • force REPLY type definitions into DWARF

    force REPLY type definitions into DWARF

    Draft comment:

    The DWARF generated for types is load-bearing in that Humility
    potentially needs them to be able to form arguments to Idol calls and
    to make sense of the reply.  But if an Idol server is declared without
    a consuming Idol client, any synthetic reply type won't be generated.
    This work forces any synthetic reply type definition to be generated
    by creating a meaningless static (that itself will be optimized away),
    which has the side-effect of getting the type that we need in the
    binary (but without changing the generated text or data).
    
    opened by bcantrill 0
  • Simpler server trait for infallible operations

    Simpler server trait for infallible operations

    Infallible operations (i.e. those using Simple(T) or Result<T, ServerDeath> modes) currently require a signature

    Result<T, idol_runtime::RequestError<core::convert::Infallible>>
    

    in the server-side trait.

    We should simplify this to just T to make writing servers more ergonomic. This would require minor Hubris changes, as there are only two Idol APIs using Simple right now.

    opened by mkeeter 1
  • Supporting `Option` for enums

    Supporting `Option` for enums

    It would be nice to support Option<T> where T is a simple enum type.

    This isn't supported by either ssmarshal or zerocopy. I think we'd want to implement a special zerocopy case like we're doing for bool already. It turns out that the compiler is smart enough to pack None into an unused enum slot, which you can find using

        let a: Option<TofinoSeqError> = None;
        let a: u8 = unsafe { std::mem::transmute(a) };
    

    so we could use this value for the None case.

    opened by mkeeter 0
  • argument types are not always generated in DWARF

    argument types are not always generated in DWARF

    One of the annoying bits that I have run into is that argument types are not always generated in DWARF. This is no fault of idolatry.

    As a concrete example, take this definition:

    // Sensor API
    
    Interface(
        name: "Sensor",
        ops: {
            "get": (
                args: {
                    "id": (
                        type: "SensorId",
                        recv: From("usize", None),
                    )
                },
                reply: Result(
                    ok: "f32",
                    err: CLike("SensorError"),
                ),
            ),
        },
    )
    

    And then this SensorId definition:

    #[derive(zerocopy::AsBytes)]
    #[repr(C)]
    pub struct SensorId(pub usize);
    

    For this definition, a reasonable (that is, functional) server -- that is, one that includes a function that takes SensorId and uses the argument -- does not generate DWARF for SensorId! Because this DWARF is load-bearing with respect to Humility-side HIF generation, not having this type is problematic. Futzing around a bit, there seems to be a zero-cost way of adding this; diff:

    diff --git a/src/server.rs b/src/server.rs
    index 5cee78e..0ca3756 100644
    --- a/src/server.rs
    +++ b/src/server.rs
    @@ -288,20 +288,46 @@ pub fn generate_server_in_order_trait(
         writeln!(out, "        use idol_runtime::ClientError;")?;
         writeln!(out, "        match op {{")?;
         for (opname, op) in &iface.ops {
             writeln!(out, "            {}Operation::{} => {{", iface.name, opname)?;
             writeln!(
                 out,
                 "                let {}args = read_{}_msg(incoming).ok_or(ClientError::BadMessage)?;",
                 if op.args.is_empty() { "_" } else { "" },
                 opname
             )?;
    +
    +        if !op.args.is_empty() {
    +            writeln!(out, r##"
    +                // The DWARF generated for types is load-bearing in that
    +                // Humility potentially needs them to form HIF to make Idol
    +                // calls.  Unfortunately, despite the server declaring
    +                // functions that take our argument types as parameters, they
    +                // are NOT necessarily generated in the DWARF!  To force these
    +                // type definitions to be generated, we create meaningless
    +                // locals (that themselves will be optimized away); this has
    +                // the side-effect of getting the types that we need in the
    +                // binary, but without changing the generated instruction
    +                // text."##)?;
    +
    +            for (argname, arg) in &op.args {
    +                writeln!(
    +                    out,
    +                    "                let _arg_{}: Option<&{}> = None;",
    +                    argname,
    +                    arg.ty.0
    +                )?;
    +            }
    +
    +            writeln!(out)?;
    +        }
    +
             writeln!(out, "                let r = self.1.{}(", opname)?;
             writeln!(out, "                    rm,")?;
             for (argname, arg) in &op.args {
                 match &arg.recv {
                     syntax::RecvStrategy::FromBytes => {
                         writeln!(out, "                    args.{},", argname)?;
                     }
                     syntax::RecvStrategy::From(_, None) => {
                         writeln!(
                             out,
    

    This does not change the size of the binary at all (or the instructions generated) but does result in the inclusion of the needed type. (Obviously it would be grand to have a way of doing this that felt less brittle; it would be great -- if complicated -- to add a test for this.)

    opened by bcantrill 1
  • panic!() calls in stubs could be made easier to debug

    panic!() calls in stubs could be made easier to debug

    Currently, stubs will call panic!() without an argument to cut down on ROM size. This is sensible, but in running into #1, the failure was in fact difficult to debug. Here is the panic from #1 as observed:

    humility: attached to dump
    system time = 55965
    ID TASK                 GEN PRI STATE    
     8 hiffy                  1   3 FAULT:  (was: ready)
       |
       +--->  0x20008440 0x0800b53a userlib::sys_panic_stub
                         @ /home/bmc/hubris/sys/userlib/src/lib.rs:686
              0x200084f0 0x0800b582 userlib::sys_panic
                         @ /home/bmc/hubris/sys/userlib/src/lib.rs:678
              0x200084f0 0x0800b588 rust_begin_unwind
                         @ /home/bmc/hubris/sys/userlib/src/lib.rs:863
              0x20008508 0x0800a4ba core::panicking::panic_fmt
                         @ /rustc/ac2d9fc509e36d1b32513744adf58c34bcc4f43c//library/core/src/panicking.rs:88
              0x20008530 0x0800aa34 core::panicking::panic
                         @ /rustc/ac2d9fc509e36d1b32513744adf58c34bcc4f43c//library/core/src/panicking.rs:39
              0x20008580 0x08008b2c task_hiffy::common::qspi_page_program
                         @ /home/bmc/hubris/task/hiffy/src/common.rs:202
              0x20008800 0x0800928c hif::execute::function
                         @ /home/bmc/.cargo/git/checkouts/hif-766e4be28bfdbf05/e512e4c/src/lib.rs:297
              0x20008800 0x08008fe8 hif::execute
                         @ /home/bmc/.cargo/git/checkouts/hif-766e4be28bfdbf05/e512e4c/src/lib.rs:259
              0x20008800 0x0800928c main
                         @ /home/bmc/hubris/task/hiffy/src/main.rs:84
    

    There's a Humility issue here in that the empty panic!() string isn't handled particularly well -- but it's also not overly clear from the stack trace what has happened. One way to achieve the desired results with respect to ROM but also make it much clearer as to the root cause is to inject a frame specific to the error, e.g.:

    diff --git a/src/client.rs b/src/client.rs
    index 62e95bd..8f7c422 100644
    --- a/src/client.rs
    +++ b/src/client.rs
    @@ -51,6 +51,16 @@ pub fn generate_client_stub(
         writeln!(out)?;
     
         writeln!(out, "impl {} {{", iface.name)?;
    +    writeln!(out, r##"
    +    fn bad_lease_panic() {{
    +        // Note: we're not generating a panic message in the client to
    +        // save ROM space -- but we give this panic its own stack frame
    +        // to indicate from the symbol that the client has erred; if the
    +        // user chases the line number into the client stub source file
    +        // the error should be clear.
    +        panic!();
    +    }}"##)?;
    +
         for (idx, (name, op)) in iface.ops.iter().enumerate() {
             writeln!(out, "    // operation: {} ({})", name, idx)?;
             if op.idempotent {
    @@ -132,10 +142,7 @@ pub fn generate_client_stub(
             for (leasename, lease) in &op.leases {
                 if let Some(n) = lease.max_len {
                     writeln!(out, "        if arg_{}.len() >= {} {{", leasename, n)?;
    -                // Note: we're not generating a panic message in the client to
    -                // save ROM space. If the user chases the line number into the
    -                // client stub source file the error should be clear.
    -                writeln!(out, "            panic!();")?;
    +                writeln!(out, "            {}::bad_lease_panic();", iface.name)?;
                     writeln!(out, "        }}")?;
                 }
             }
    

    This results in a much clearer stack:

    humility: attached via ST-Link
    system time = 25639
    ID TASK                 GEN PRI STATE    
     8 hiffy                  1   3 FAULT:  (was: ready)
       |
       +--->  0x20008420 0x0800b722 userlib::sys_panic_stub
                         @ /home/bmc/hubris/sys/userlib/src/lib.rs:686
              0x200084d0 0x0800b76a userlib::sys_panic
                         @ /home/bmc/hubris/sys/userlib/src/lib.rs:678
              0x200084d0 0x0800b770 rust_begin_unwind
                         @ /home/bmc/hubris/sys/userlib/src/lib.rs:863
              0x200084e8 0x0800a692 core::panicking::panic_fmt
                         @ /rustc/ac2d9fc509e36d1b32513744adf58c34bcc4f43c//library/core/src/panicking.rs:88
              0x20008510 0x0800ac0c core::panicking::panic
                         @ /rustc/ac2d9fc509e36d1b32513744adf58c34bcc4f43c//library/core/src/panicking.rs:39
              0x20008518 0x0800aefe drv_gimlet_hf_api::HostFlash::bad_lease_panic
                         @ /home/bmc/hubris/target/thumbv7em-none-eabihf/release/build/drv-gimlet-hf-api-afda7c131dd13e6f/out/client_stub.rs:25
              0x20008580 0x08008d04 drv_gimlet_hf_api::HostFlash::page_program
                         @ /home/bmc/hubris/target/thumbv7em-none-eabihf/release/build/drv-gimlet-hf-api-afda7c131dd13e6f/out/client_stub.rs:194
              0x20008580 0x08008d08 task_hiffy::common::qspi_page_program
                         @ /home/bmc/hubris/task/hiffy/src/common.rs:206
              0x20008800 0x08009464 hif::execute::function
                         @ /home/bmc/.cargo/git/checkouts/hif-766e4be28bfdbf05/e512e4c/src/lib.rs:297
              0x20008800 0x080091c0 hif::execute
                         @ /home/bmc/.cargo/git/checkouts/hif-766e4be28bfdbf05/e512e4c/src/lib.rs:259
              0x20008800 0x08009464 main
                         @ /home/bmc/hubris/task/hiffy/src/main.rs:84
    
    
    opened by bcantrill 4
Owner
Oxide Computer Company
Servers as they should be.
Oxide Computer Company
Modular IPC-based desktop launcher service

Pop Launcher Modular IPC-based desktop launcher service, written in Rust. Desktop launchers may interface with this service via spawning the pop-launc

Pop!_OS 125 Dec 23, 2022
Rust-native IPC broker

elbus - Rust-native IPC broker Note: the project is under development and in alpha stage https://elbus.bma.ai/ What is elbus elbus is a rust-native IP

Altertech 66 Dec 31, 2022
TeleMQ is an experimental MQTT broker implemented in Rust language.

TeleMQ TeleMQ is an experimental MQTT broker implemented in Rust language. The broker implements MQTT version 3.1.1 specification. License This projec

null 12 Dec 27, 2022
An experimental HTTP server in Rust that supports HTTP/1.1, HTTP/2, and HTTP/3 over QUIC.

?? H123 An experimental HTTP server in Rust that supports HTTP/1.1, HTTP/2, and HTTP/3 over QUIC. Warning This is an experimental project and not inte

Naoki Ikeguchi 7 Dec 15, 2022
Tunnel TCP traffic through SOCKS5 or HTTP using a TUN interface.

tun2proxy Tunnel TCP traffic through SOCKS5 or HTTP on Linux. Authentication not yet supported. Error handling incomplete and too restrictive. Build C

B. Blechschmidt 34 Nov 29, 2022
Podman-api-rs - Rust interface to Podman (libpod).

podman-api Rust interface to Podman Usage Add the following to your Cargo.toml file [dependencies] podman-api = "0.1" SSL Connection To enable HTTPS c

Wojciech Kępka 43 Dec 29, 2022
Replay packets from pcap -file to network interface

pktreplay can be used to read packets from pcap file or interface and write them into interface. By default packets are written with the same rate they have been saved into the pcap file, or, when reading from interface, as fast as they are received.

Jukka Taimisto 3 Nov 23, 2022
The netns-rs crate provides an ultra-simple interface for handling network namespaces in Rust.

netns-rs The netns-rs crate provides an ultra-simple interface for handling network namespaces in Rust. Changing namespaces requires elevated privileg

OpenAnolis Community 7 Dec 15, 2022
Rust implementation of the JDA-NAS interface

udpqueue.rs This is a rust implementation of the original JDA-NAS natives. This can be used to make a minimal modular jar with only the required targe

Florian Spieß 13 Mar 8, 2023
Cross-platform, low level networking using the Rust programming language.

libpnet Linux ∪ OS X Build Status: Windows Build Status: Discussion and support: #libpnet on freenode / #rust-networking on irc.mozilla.org / #rust on

null 1.8k Jan 6, 2023
RusTCP is an attempt to rewrite some of the PyTCP stack functionality using Rust language.

RusTCP is an attempt to rewrite some of the PyTCP stack functionality using Rust language. Currently, the main goal of this project is to create a stable IPv6 platform that could be used to facilitate the process of labing the SRv6 technology.

Sebastian Majewski 3 Dec 5, 2022
Easy c̵̰͠r̵̛̠ö̴̪s̶̩̒s̵̭̀-t̶̲͝h̶̯̚r̵̺͐e̷̖̽ḁ̴̍d̶̖̔ ȓ̵͙ė̶͎ḟ̴͙e̸̖͛r̶̖͗ë̶̱́ṉ̵̒ĉ̷̥e̷͚̍ s̷̹͌h̷̲̉a̵̭͋r̷̫̊ḭ̵̊n̷̬͂g̵̦̃ f̶̻̊ơ̵̜ṟ̸̈́ R̵̞̋ù̵̺s̷̖̅ţ̸͗!̸̼͋

Rust S̵̓i̸̓n̵̉ I̴n̴f̶e̸r̵n̷a̴l mutability! Howdy, friendly Rust developer! Ever had a value get m̵̯̅ð̶͊v̴̮̾ê̴̼͘d away right under your nose just when

null 294 Dec 23, 2022
Hubris is a microcontroller operating environment designed for deeply-embedded systems

A lightweight, memory-protected, message-passing kernel for deeply embedded systems.

Oxide Computer Company 2.1k Jan 6, 2023
Interface definition generator and standard for Move packages.

Move IDL Interface definition generator and standard for Move packages. Documentation is currently extremely sparse but will be improved in the near f

The Moving Company 10 Aug 25, 2022
Event-sourcing Schema Definition Language

ESDL Event-sourcing Schema Definition Language Schema definition language for defining aggregates, commands, events & custom types. Heavily inspired b

null 35 Dec 15, 2022
Untrusted IPC with maximum performance and minimum latency. On Rust, on Linux.

Untrusted IPC with maximum performance and minimum latency. On Rust, on Linux. When is this Rust crate useful? Performance or latency is crucial, and

null 72 Jan 3, 2023
A controller for mpv, requires ipc to be enabled in mpv.

Configuration Requires either the flag --input-ipc-server=/tmp/mpvsocket to be passed at mpv runtime, or for this line input-ipc-server=/tmp/mpvsocket

ValleyKnight 3 Jul 25, 2022
A super minimal wrapper around unix sockets for IPC on top of tokio.

tokio-unix-ipc This crate implements a minimal abstraction over UNIX domain sockets for the purpose of IPC on top of tokio.

Armin Ronacher 26 Nov 18, 2022
Modular IPC-based desktop launcher service

Pop Launcher Modular IPC-based desktop launcher service, written in Rust. Desktop launchers may interface with this service via spawning the pop-launc

Pop!_OS 125 Dec 23, 2022
Zero-grammer definition command-line parser

zgclp Zgclp (Zero-grammar definition command-line parser) is one of Rust's command-line parsers. A normal command-line parser generates a parser from

Toshihiro Kamiya 1 Mar 31, 2022