Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: smoltcp-rs/smoltcp
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 2d31ef966532
Choose a base ref
...
head repository: smoltcp-rs/smoltcp
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 17cec8743f4a
Choose a head ref
  • 2 commits
  • 11 files changed
  • 1 contributor

Commits on Sep 24, 2017

  1. Reorganize features using namespaces, to match module hierarchy.

    I'm about to add a whole lot more features, and it's going to get
    quite confusing otherwise.
    whitequark committed Sep 24, 2017
    Copy the full SHA
    440b6f5 View commit details

Commits on Sep 25, 2017

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    17cec87 View commit details
Showing with 121 additions and 52 deletions.
  1. +17 −5 .travis.yml
  2. +8 −3 Cargo.toml
  3. +15 −6 README.md
  4. +29 −4 src/iface/ethernet.rs
  5. +1 −1 src/lib.rs
  6. +6 −6 src/phy/mod.rs
  7. +7 −6 src/phy/sys/linux.rs
  8. +4 −4 src/phy/sys/mod.rs
  9. +27 −14 src/socket/mod.rs
  10. +5 −3 src/socket/set.rs
  11. +2 −0 src/storage/assembler.rs
22 changes: 17 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
language: rust
matrix:
include:
# litmus check that we work on stable/beta
- rust: stable
env: FEATURES='std raw_socket tap_interface' MODE='test'
env: FEATURES='default' MODE='test'
- rust: beta
env: FEATURES='std raw_socket tap_interface' MODE='test'
env: FEATURES='default' MODE='test'
# actually test everything
- rust: nightly
env: FEATURES='std raw_socket tap_interface' MODE='test'
env: FEATURES='default' MODE='test'
- rust: nightly
env: FEATURES='std raw_socket tap_interface log' MODE='test'
env: FEATURES='std' MODE='test'
- rust: nightly
env: FEATURES='alloc' MODE='build'
- rust: nightly
env: FEATURES='' MODE='build'
env: FEATURES='phy-raw_socket' MODE='build'
- rust: nightly
env: FEATURES='phy-tap_interface' MODE='build'
- rust: nightly
env: FEATURES='socket-raw' MODE='build'
- rust: nightly
env: FEATURES='socket-udp' MODE='build'
- rust: nightly
env: FEATURES='socket-tcp' MODE='build'
- rust: nightly
env: FEATURES='socket-raw socket-udp socket-tcp' MODE='build'
script:
- cargo "$MODE" --no-default-features --features "$FEATURES"
notifications:
11 changes: 8 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -26,9 +26,14 @@ getopts = "0.2"
std = ["managed/std"]
alloc = ["managed/alloc"]
verbose = []
raw_socket = ["libc"]
tap_interface = ["libc"]
default = ["std", "raw_socket", "tap_interface", "log", "verbose"]
"phy-raw_socket" = ["std", "libc"]
"phy-tap_interface" = ["std", "libc"]
"socket-raw" = []
"socket-udp" = []
"socket-tcp" = []
default = ["std", "log",
"phy-raw_socket", "phy-tap_interface",
"socket-raw", "socket-udp", "socket-tcp"]

[[example]]
name = "tcpdump"
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -94,17 +94,13 @@ dependency on `std::boxed::Box` and `std::vec::Vec`.

This feature is enabled by default.

### Features `raw_socket` and `tap_interface`

Enable `smoltcp::phy::RawSocket` and `smoltcp::phy::TapInterface`, respectively.

These features are enabled by default.

### Feature `alloc`

The `alloc` feature enables use of objects owned by the networking stack through a dependency
on collections from the `alloc` crate. This only works on nightly rustc.

This feature is disabled by default.

### Feature `log`

The `log` feature enables logging of events within the networking stack through
@@ -125,6 +121,19 @@ or `BufWriter` is used, which are of course not available on heap-less systems.

This feature is disabled by default.

### Features `phy-raw_socket` and `phy-tap_interface`

Enable `smoltcp::phy::RawSocket` and `smoltcp::phy::TapInterface`, respectively.

These features are enabled by default.

### Features `socket-raw`, `socket-udp`, and `socket-tcp`

Enable `smoltcp::socket::RawSocket`, `smoltcp::socket::UdpSocket`,
and `smoltcp::socket::TcpSocket`, respectively.

These features are enabled by default.

## Hosted usage examples

_smoltcp_, being a freestanding networking stack, needs to be able to transmit and receive
33 changes: 29 additions & 4 deletions src/iface/ethernet.rs
Original file line number Diff line number Diff line change
@@ -10,8 +10,12 @@ use wire::{ArpPacket, ArpRepr, ArpOperation};
use wire::{Ipv4Packet, Ipv4Repr};
use wire::{Icmpv4Packet, Icmpv4Repr, Icmpv4DstUnreachable};
use wire::{IpAddress, IpProtocol, IpRepr};
use wire::{UdpPacket, UdpRepr, TcpPacket, TcpRepr, TcpControl};
use socket::{Socket, SocketSet, RawSocket, TcpSocket, UdpSocket, AsSocket};
#[cfg(feature = "socket-udp")] use wire::{UdpPacket, UdpRepr};
#[cfg(feature = "socket-tcp")] use wire::{TcpPacket, TcpRepr, TcpControl};
use socket::{Socket, SocketSet, AsSocket};
#[cfg(feature = "socket-raw")] use socket::RawSocket;
#[cfg(feature = "socket-udp")] use socket::UdpSocket;
#[cfg(feature = "socket-tcp")] use socket::TcpSocket;
use super::ArpCache;

/// An Ethernet network interface.
@@ -30,8 +34,11 @@ enum Packet<'a> {
None,
Arp(ArpRepr),
Icmpv4(Ipv4Repr, Icmpv4Repr<'a>),
#[cfg(feature = "socket-raw")]
Raw((IpRepr, &'a [u8])),
#[cfg(feature = "socket-udp")]
Udp((IpRepr, UdpRepr<'a>)),
#[cfg(feature = "socket-tcp")]
Tcp((IpRepr, TcpRepr<'a>))
}

@@ -169,22 +176,25 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
let mut device_result = Ok(());
let socket_result =
match socket {
#[cfg(feature = "socket-raw")]
&mut Socket::Raw(ref mut socket) =>
socket.dispatch(|response| {
device_result = self.dispatch(timestamp, Packet::Raw(response));
device_result
}),
#[cfg(feature = "socket-udp")]
&mut Socket::Udp(ref mut socket) =>
socket.dispatch(|response| {
device_result = self.dispatch(timestamp, Packet::Udp(response));
device_result
}),
#[cfg(feature = "socket-tcp")]
&mut Socket::Tcp(ref mut socket) =>
socket.dispatch(timestamp, &limits, |response| {
device_result = self.dispatch(timestamp, Packet::Tcp(response));
device_result
}),
&mut Socket::__Nonexhaustive => unreachable!()
&mut Socket::__Nonexhaustive(_) => unreachable!()
};
match (device_result, socket_result) {
(Err(Error::Unaddressable), _) => break, // no one to transmit to
@@ -285,8 +295,11 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
let ip_repr = IpRepr::Ipv4(ipv4_repr);
let ip_payload = ipv4_packet.payload();

// Pass every IP packet to all raw sockets we have registered.
#[cfg(feature = "socket-raw")]
let mut handled_by_raw_socket = false;

// Pass every IP packet to all raw sockets we have registered.
#[cfg(feature = "socket-raw")]
for raw_socket in sockets.iter_mut().filter_map(
<Socket as AsSocket<RawSocket>>::try_as_socket) {
if !raw_socket.accepts(&ip_repr) { continue }
@@ -309,12 +322,19 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
match ipv4_repr.protocol {
IpProtocol::Icmp =>
Self::process_icmpv4(ipv4_repr, ip_payload),

#[cfg(feature = "socket-udp")]
IpProtocol::Udp =>
Self::process_udp(sockets, ip_repr, ip_payload),

#[cfg(feature = "socket-tcp")]
IpProtocol::Tcp =>
Self::process_tcp(sockets, timestamp, ip_repr, ip_payload),

#[cfg(feature = "socket-raw")]
_ if handled_by_raw_socket =>
Ok(Packet::None),

_ => {
let icmp_reply_repr = Icmpv4Repr::DstUnreachable {
reason: Icmpv4DstUnreachable::ProtoUnreachable,
@@ -362,6 +382,7 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
}
}

#[cfg(feature = "socket-udp")]
fn process_udp<'frame>(sockets: &mut SocketSet,
ip_repr: IpRepr, ip_payload: &'frame [u8]) ->
Result<Packet<'frame>> {
@@ -403,6 +424,7 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
}
}

#[cfg(feature = "socket-tcp")]
fn process_tcp<'frame>(sockets: &mut SocketSet, timestamp: u64,
ip_repr: IpRepr, ip_payload: &'frame [u8]) ->
Result<Packet<'frame>> {
@@ -454,17 +476,20 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
icmpv4_repr.emit(&mut Icmpv4Packet::new(payload));
})
}
#[cfg(feature = "socket-raw")]
Packet::Raw((ip_repr, raw_packet)) => {
self.dispatch_ip(timestamp, ip_repr, |_ip_repr, payload| {
payload.copy_from_slice(raw_packet);
})
}
#[cfg(feature = "socket-udp")]
Packet::Udp((ip_repr, udp_repr)) => {
self.dispatch_ip(timestamp, ip_repr, |ip_repr, payload| {
udp_repr.emit(&mut UdpPacket::new(payload),
&ip_repr.src_addr(), &ip_repr.dst_addr());
})
}
#[cfg(feature = "socket-tcp")]
Packet::Tcp((ip_repr, mut tcp_repr)) => {
let limits = self.device.limits();
self.dispatch_ip(timestamp, ip_repr, |ip_repr, payload| {
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -72,7 +72,7 @@ extern crate managed;
#[cfg(any(test, feature = "std"))]
#[macro_use]
extern crate std;
#[cfg(any(feature = "raw_socket", feature="tap_interface"))]
#[cfg(any(feature = "phy-raw_socket", feature = "phy-tap_interface"))]
extern crate libc;
#[cfg(feature = "alloc")]
extern crate alloc;
12 changes: 6 additions & 6 deletions src/phy/mod.rs
Original file line number Diff line number Diff line change
@@ -106,30 +106,30 @@ impl Drop for EthernetTxBuffer {

use Result;

#[cfg(any(feature = "raw_socket", feature = "tap_interface"))]
#[cfg(any(feature = "phy-raw_socket", feature = "phy-tap_interface"))]
mod sys;

mod tracer;
mod fault_injector;
mod pcap_writer;
#[cfg(any(feature = "std", feature = "alloc"))]
mod loopback;
#[cfg(feature = "raw_socket")]
#[cfg(feature = "phy-raw_socket")]
mod raw_socket;
#[cfg(all(feature = "tap_interface", target_os = "linux"))]
#[cfg(all(feature = "phy-tap_interface", target_os = "linux"))]
mod tap_interface;

#[cfg(any(feature = "raw_socket", feature = "tap_interface"))]
#[cfg(any(feature = "phy-raw_socket", feature = "phy-tap_interface"))]
pub use self::sys::wait;

pub use self::tracer::Tracer;
pub use self::fault_injector::FaultInjector;
pub use self::pcap_writer::{PcapLinkType, PcapMode, PcapSink, PcapWriter};
#[cfg(any(feature = "std", feature = "alloc"))]
pub use self::loopback::Loopback;
#[cfg(any(feature = "raw_socket"))]
#[cfg(any(feature = "phy-raw_socket"))]
pub use self::raw_socket::RawSocket;
#[cfg(all(feature = "tap_interface", target_os = "linux"))]
#[cfg(all(feature = "phy-tap_interface", target_os = "linux"))]
pub use self::tap_interface::TapInterface;

/// A tracer device for Ethernet frames.
13 changes: 7 additions & 6 deletions src/phy/sys/linux.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use libc;

#[cfg(any(feature = "raw_socket"))]
#[cfg(any(feature = "phy-raw_socket",
feature = "phy-tap_interface"))]
pub const SIOCGIFMTU: libc::c_ulong = 0x8921;
#[cfg(any(feature = "raw_socket"))]
#[cfg(any(feature = "phy-raw_socket"))]
pub const SIOCGIFINDEX: libc::c_ulong = 0x8933;
#[cfg(any(feature = "raw_socket"))]
#[cfg(any(feature = "phy-raw_socket"))]
pub const ETH_P_ALL: libc::c_short = 0x0003;

#[cfg(feature = "tap_interface")]
#[cfg(feature = "phy-tap_interface")]
pub const TUNSETIFF: libc::c_ulong = 0x400454CA;
#[cfg(feature = "tap_interface")]
#[cfg(feature = "phy-tap_interface")]
pub const IFF_TAP: libc::c_int = 0x0002;
#[cfg(feature = "tap_interface")]
#[cfg(feature = "phy-tap_interface")]
pub const IFF_NO_PI: libc::c_int = 0x1000;

8 changes: 4 additions & 4 deletions src/phy/sys/mod.rs
Original file line number Diff line number Diff line change
@@ -6,14 +6,14 @@ use std::os::unix::io::RawFd;
#[path = "linux.rs"]
mod imp;

#[cfg(feature = "raw_socket")]
#[cfg(feature = "phy-raw_socket")]
pub mod raw_socket;
#[cfg(all(feature = "tap_interface", target_os = "linux"))]
#[cfg(all(feature = "phy-tap_interface", target_os = "linux"))]
pub mod tap_interface;

#[cfg(feature = "raw_socket")]
#[cfg(feature = "phy-raw_socket")]
pub use self::raw_socket::RawSocketDesc;
#[cfg(all(feature = "tap_interface", target_os = "linux"))]
#[cfg(all(feature = "phy-tap_interface", target_os = "linux"))]
pub use self::tap_interface::TapInterfaceDesc;

/// Wait until given file descriptor becomes readable, but no longer than given timeout.
41 changes: 27 additions & 14 deletions src/socket/mod.rs
Original file line number Diff line number Diff line change
@@ -10,24 +10,28 @@
//! The interface implemented by this module uses explicit buffering: you decide on the good
//! size for a buffer, allocate it, and let the networking stack use it.
use core::marker::PhantomData;
use wire::IpRepr;

mod raw;
mod udp;
mod tcp;
#[cfg(feature = "socket-raw")] mod raw;
#[cfg(feature = "socket-udp")] mod udp;
#[cfg(feature = "socket-tcp")] mod tcp;
mod set;

pub use self::raw::PacketBuffer as RawPacketBuffer;
pub use self::raw::SocketBuffer as RawSocketBuffer;
pub use self::raw::RawSocket;
#[cfg(feature = "socket-raw")]
pub use self::raw::{PacketBuffer as RawPacketBuffer,
SocketBuffer as RawSocketBuffer,
RawSocket};

pub use self::udp::PacketBuffer as UdpPacketBuffer;
pub use self::udp::SocketBuffer as UdpSocketBuffer;
pub use self::udp::UdpSocket;
#[cfg(feature = "socket-udp")]
pub use self::udp::{PacketBuffer as UdpPacketBuffer,
SocketBuffer as UdpSocketBuffer,
UdpSocket};

pub use self::tcp::SocketBuffer as TcpSocketBuffer;
pub use self::tcp::State as TcpState;
pub use self::tcp::TcpSocket;
#[cfg(feature = "socket-tcp")]
pub use self::tcp::{SocketBuffer as TcpSocketBuffer,
State as TcpState,
TcpSocket};

pub use self::set::{Set as SocketSet, Item as SocketSetItem, Handle as SocketHandle};
pub use self::set::{Iter as SocketSetIter, IterMut as SocketSetIterMut};
@@ -47,20 +51,26 @@ pub use self::set::{Iter as SocketSetIter, IterMut as SocketSetIterMut};
/// since the lower layers treat the packet as an opaque octet sequence.
#[derive(Debug)]
pub enum Socket<'a, 'b: 'a> {
#[cfg(feature = "socket-raw")]
Raw(RawSocket<'a, 'b>),
#[cfg(feature = "socket-udp")]
Udp(UdpSocket<'a, 'b>),
#[cfg(feature = "socket-tcp")]
Tcp(TcpSocket<'a>),
#[doc(hidden)]
__Nonexhaustive
__Nonexhaustive(PhantomData<(&'a (), &'b ())>)
}

macro_rules! dispatch_socket {
($self_:expr, |$socket:ident [$( $mut_:tt )*]| $code:expr) => ({
match $self_ {
#[cfg(feature = "socket-raw")]
&$( $mut_ )* Socket::Raw(ref $( $mut_ )* $socket) => $code,
#[cfg(feature = "socket-udp")]
&$( $mut_ )* Socket::Udp(ref $( $mut_ )* $socket) => $code,
#[cfg(feature = "socket-tcp")]
&$( $mut_ )* Socket::Tcp(ref $( $mut_ )* $socket) => $code,
&$( $mut_ )* Socket::__Nonexhaustive => unreachable!()
&$( $mut_ )* Socket::__Nonexhaustive(_) => unreachable!()
}
})
}
@@ -115,6 +125,9 @@ macro_rules! as_socket {
}
}

#[cfg(feature = "socket-raw")]
as_socket!(RawSocket<'a, 'b>, Raw);
#[cfg(feature = "socket-udp")]
as_socket!(UdpSocket<'a, 'b>, Udp);
#[cfg(feature = "socket-tcp")]
as_socket!(TcpSocket<'a>, Tcp);
Loading