Crate acton

source · []
Expand description

Acton

acton provides Rust APIs for ethernet over udp networking service.

Examples

More examples, including a packet logger, and a version of the ethernet over udp server & client written, can be found in the examples/ directory.

Ethernet over udp server & client

This code implements an Ethernet over udp server and client. Whenever a ethernet frame @ server is received on an interface, it sends the packet to clients, and Vice versa. In service, simple ethernet mac learning is implemented with mac forwarding table aging. The BUM (Broadcast, Unknown, Multicast) frame sent by server will be flooded to all clients. But local switch between clients is not allowed (P2MP forwarding manner). Proprietary control packets are defined and used for sessions lifecycle management (hello and keepalive control packets)

Scaling

1,000 clients are tested (linux system resource limitation should be considered)

Example

use std::net::Ipv4Addr;
use acton::server;
use acton::client;
use structopt::StructOpt;
use std::path::PathBuf;
use std::str::FromStr;
use eui48::{MacAddress, ParseError};
use ipaddress::IPAddress;
 
#[macro_use]
extern crate log;
 
use env_logger::Env;
 
#[derive(StructOpt, Debug)]
#[structopt(name = "acton")]
// Ethernet over TCP tunnel tools
enum Opt {
    // server listen mode for L2 tunnel requests
    Server {
        #[structopt(short, long, parse(try_from_str), default_value = "0.0.0.0", env = "SERVER_LISTEN_ADDRESS")]
        // server listen address
        listen: Ipv4Addr,
        #[structopt(short, long, default_value = "8080", env = "SERVER_LISTEN_PORT")]
        // server listen port
        port: u16,
        #[structopt(short, long, default_value = "server", env = "SERVER_TAP_NAME")]
        // tap interface name
        tap_name: PathBuf,
        #[structopt(short, long, default_value = "00:00:00:00:00:00", env = "SERVER_TAP_MAC", parse(try_from_str=parse_mac))]
        // tap mac address (xx:xx:xx:xx:xx:xx)
        mac: MacAddress,
        #[structopt(short, long, default_value = "0.0.0.0/0", env = "CLIENT_TAP_NETWORK", parse(try_from_str=parse_ip))]
        // tap ip network (a.b.c.d/n)
        address: IPAddress,
    },
 
    #[structopt(after_help = "Beware `-d`, interoperable with socat command")]
    // client connect mode for L2 tunnel establishment
    Client {
        #[structopt(parse(try_from_str), env = "CLIENT_SERVER_ADDRESS")]
        // server destination address
        server: Ipv4Addr,
        #[structopt(short, long, default_value = "8080", env = "CLIENT_SERVER_PORT")]
        // server destination port
        port: u16,
        #[structopt(short, long, default_value = "client", env = "CLIENT_TAP_NAME")]
        // tap interface name
        tap_name: PathBuf,
        #[structopt(short, long, default_value = "00:00:00:00:00:00", env = "CLIENT_TAP_MAC", parse(try_from_str=parse_mac))]
        // tap mac address (xx:xx:xx:xx:xx:xx)
        mac: MacAddress,
        #[structopt(short, long, default_value = "0.0.0.0/0", env = "CLIENT_TAP_NETWORK", parse(try_from_str=parse_ip))]
        // tap ip network (a.b.c.d/n)
        address: IPAddress,
    },
}
 
fn parse_ip(ipnetwork: &str) -> Result<IPAddress, String> {
    ipaddress::ipv4::new(ipnetwork)
}
 
fn parse_mac(mac_address: &str) -> Result<MacAddress, ParseError> {
    MacAddress::from_str(mac_address)
}
 
 
fn main() {
    let env = Env::default()
        .filter_or("ACTON_LOG_LEVEL", "info")
        .write_style_or("ACTON_LOG_STYLE", "always");
 
    env_logger::init_from_env(env);
 
 
    let args = Opt::from_args();
 
    debug!("args: {:?}", args);
 
    match args {
        Opt::Server { listen, port, tap_name, mac, address } => {
            let listen_addr = format!("{}:{}", listen.to_string(), port);
            server::main(listen_addr.as_str(), tap_name.to_str().unwrap(), mac, address, false);
        }
        Opt::Client { server, port, tap_name, mac,address } => {
            let server = format!("{}:{}", server.to_string(), port);
            client::main(server.as_str(), tap_name.to_str().unwrap(), mac, address, false);
        }
    };
}

Modules

Ethernet over udp client implementation

Minimal Mac learning and socket session management for L2 tunnel forwarding implementation

Linux raw interface binding to send/receive raw ethernet frames

Linux TAP interface creation and programming API module

Ethernet over udp server implementation