Skip to content

Commit

Permalink
Merge pull request #988 from smoltcp-rs/multicast-refactor-features
Browse files Browse the repository at this point in the history
multicast: use single Cargo feature for both ipv4 and ipv6.
  • Loading branch information
Dirbaio authored Sep 16, 2024
2 parents dee8975 + 07f0991 commit 469dccd
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 182 deletions.
9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ defmt = ["dep:defmt", "heapless/defmt-03"]

"proto-ipv4" = []
"proto-ipv4-fragmentation" = ["proto-ipv4", "_proto-fragmentation"]
"proto-igmp" = ["proto-ipv4"]
"proto-dhcpv4" = ["proto-ipv4"]
"proto-ipv6" = []
"proto-ipv6-hbh" = ["proto-ipv6"]
Expand All @@ -64,6 +63,8 @@ defmt = ["dep:defmt", "heapless/defmt-03"]
"proto-ipsec-ah" = []
"proto-ipsec-esp" = []

"multicast" = []

"socket" = []
"socket-raw" = ["socket"]
"socket-udp" = ["socket"]
Expand Down Expand Up @@ -96,10 +97,10 @@ default = [
"std", "log", # needed for `cargo test --no-default-features --features default` :/
"medium-ethernet", "medium-ip", "medium-ieee802154",
"phy-raw_socket", "phy-tuntap_interface",
"proto-ipv4", "proto-igmp", "proto-dhcpv4", "proto-ipv6", "proto-dns",
"proto-ipv4", "proto-dhcpv4", "proto-ipv6", "proto-dns",
"proto-ipv4-fragmentation", "proto-sixlowpan-fragmentation",
"socket-raw", "socket-icmp", "socket-udp", "socket-tcp", "socket-dhcpv4", "socket-dns", "socket-mdns",
"packetmeta-id", "async"
"packetmeta-id", "async", "multicast"
]

# Private features
Expand Down Expand Up @@ -301,7 +302,7 @@ required-features = ["std", "log", "medium-ethernet", "proto-ipv4", "socket-tcp"

[[example]]
name = "multicast"
required-features = ["std", "medium-ethernet", "medium-ip", "phy-tuntap_interface", "proto-ipv4", "proto-igmp", "socket-udp"]
required-features = ["std", "medium-ethernet", "medium-ip", "phy-tuntap_interface", "proto-ipv4", "multicast", "socket-udp"]

[[example]]
name = "multicast6"
Expand Down
12 changes: 6 additions & 6 deletions ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ FEATURES_TEST=(
"std,medium-ethernet,phy-raw_socket,proto-ipv6,socket-udp,socket-dns"
"std,medium-ethernet,phy-tuntap_interface,proto-ipv6,socket-udp"
"std,medium-ethernet,proto-ipv4,proto-ipv4-fragmentation,socket-raw,socket-dns"
"std,medium-ethernet,proto-ipv4,proto-igmp,socket-raw,socket-dns"
"std,medium-ethernet,proto-ipv4,multicast,socket-raw,socket-dns"
"std,medium-ethernet,proto-ipv4,socket-udp,socket-tcp,socket-dns"
"std,medium-ethernet,proto-ipv4,proto-dhcpv4,socket-udp"
"std,medium-ethernet,medium-ip,medium-ieee802154,proto-ipv6,proto-igmp,proto-rpl,socket-udp,socket-dns"
"std,medium-ethernet,medium-ip,medium-ieee802154,proto-ipv6,multicast,proto-rpl,socket-udp,socket-dns"
"std,medium-ethernet,proto-ipv6,socket-tcp"
"std,medium-ethernet,medium-ip,proto-ipv4,socket-icmp,socket-tcp"
"std,medium-ip,proto-ipv6,socket-icmp,socket-tcp"
"std,medium-ieee802154,proto-sixlowpan,socket-udp"
"std,medium-ieee802154,proto-sixlowpan,proto-sixlowpan-fragmentation,socket-udp"
"std,medium-ieee802154,proto-rpl,proto-sixlowpan,proto-sixlowpan-fragmentation,socket-udp"
"std,medium-ip,proto-ipv4,proto-ipv6,socket-tcp,socket-udp"
"std,medium-ethernet,medium-ip,medium-ieee802154,proto-ipv4,proto-ipv6,proto-igmp,proto-rpl,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async"
"std,medium-ethernet,medium-ip,medium-ieee802154,proto-ipv4,proto-ipv6,multicast,proto-rpl,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async"
"std,medium-ieee802154,medium-ip,proto-ipv4,socket-raw"
"std,medium-ethernet,proto-ipv4,proto-ipsec,socket-raw"
)
Expand All @@ -39,9 +39,9 @@ FEATURES_TEST_NIGHTLY=(
)

FEATURES_CHECK=(
"medium-ip,medium-ethernet,medium-ieee802154,proto-ipv6,proto-ipv6,proto-igmp,proto-dhcpv4,proto-ipsec,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async"
"defmt,medium-ip,medium-ethernet,proto-ipv6,proto-ipv6,proto-igmp,proto-dhcpv4,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async"
"defmt,alloc,medium-ip,medium-ethernet,proto-ipv6,proto-ipv6,proto-igmp,proto-dhcpv4,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async"
"medium-ip,medium-ethernet,medium-ieee802154,proto-ipv6,proto-ipv6,multicast,proto-dhcpv4,proto-ipsec,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async"
"defmt,medium-ip,medium-ethernet,proto-ipv6,proto-ipv6,multicast,proto-dhcpv4,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async"
"defmt,alloc,medium-ip,medium-ethernet,proto-ipv6,proto-ipv6,multicast,proto-dhcpv4,socket-raw,socket-udp,socket-tcp,socket-icmp,socket-dns,async"
)

test() {
Expand Down
45 changes: 1 addition & 44 deletions src/iface/interface/ipv4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ impl InterfaceInner {
match ipv4_repr.next_header {
IpProtocol::Icmp => self.process_icmpv4(sockets, ipv4_repr, ip_payload),

#[cfg(feature = "proto-igmp")]
#[cfg(feature = "multicast")]
IpProtocol::Igmp => self.process_igmp(ipv4_repr, ip_payload),

#[cfg(any(feature = "socket-udp", feature = "socket-dns"))]
Expand Down Expand Up @@ -464,47 +464,4 @@ impl InterfaceInner {
frag.ipv4.frag_offset += payload_len as u16;
})
}

#[cfg(feature = "proto-igmp")]
pub(super) fn igmp_report_packet<'any>(
&self,
version: IgmpVersion,
group_addr: Ipv4Address,
) -> Option<Packet<'any>> {
let iface_addr = self.ipv4_addr()?;
let igmp_repr = IgmpRepr::MembershipReport {
group_addr,
version,
};
let pkt = Packet::new_ipv4(
Ipv4Repr {
src_addr: iface_addr,
// Send to the group being reported
dst_addr: group_addr,
next_header: IpProtocol::Igmp,
payload_len: igmp_repr.buffer_len(),
hop_limit: 1,
// [#183](https://github.com/m-labs/smoltcp/issues/183).
},
IpPayload::Igmp(igmp_repr),
);
Some(pkt)
}

#[cfg(feature = "proto-igmp")]
pub(super) fn igmp_leave_packet<'any>(&self, group_addr: Ipv4Address) -> Option<Packet<'any>> {
self.ipv4_addr().map(|iface_addr| {
let igmp_repr = IgmpRepr::LeaveGroup { group_addr };
Packet::new_ipv4(
Ipv4Repr {
src_addr: iface_addr,
dst_addr: Ipv4Address::MULTICAST_ALL_ROUTERS,
next_header: IpProtocol::Igmp,
payload_len: igmp_repr.buffer_len(),
hop_limit: 1,
},
IpPayload::Igmp(igmp_repr),
)
})
}
}
76 changes: 20 additions & 56 deletions src/iface/interface/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,17 @@ mod ipv6;
#[cfg(feature = "proto-sixlowpan")]
mod sixlowpan;

#[cfg(feature = "proto-igmp")]
mod igmp;
#[cfg(feature = "multicast")]
pub(crate) mod multicast;
#[cfg(feature = "socket-tcp")]
mod tcp;
#[cfg(any(feature = "socket-udp", feature = "socket-dns"))]
mod udp;

#[cfg(feature = "proto-igmp")]
pub use igmp::MulticastError;

use super::packet::*;

use core::result::Result;
use heapless::{LinearMap, Vec};
use heapless::Vec;

#[cfg(feature = "_proto-fragmentation")]
use super::fragmentation::FragKey;
Expand All @@ -41,10 +38,7 @@ use super::fragmentation::{Fragmenter, FragmentsBuffer};
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
use super::neighbor::{Answer as NeighborAnswer, Cache as NeighborCache};
use super::socket_set::SocketSet;
use crate::config::{
IFACE_MAX_ADDR_COUNT, IFACE_MAX_MULTICAST_GROUP_COUNT,
IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT,
};
use crate::config::{IFACE_MAX_ADDR_COUNT, IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT};
use crate::iface::Routes;
use crate::phy::PacketMeta;
use crate::phy::{ChecksumCapabilities, Device, DeviceCapabilities, Medium, RxToken, TxToken};
Expand Down Expand Up @@ -82,16 +76,6 @@ pub struct Interface {
fragmenter: Fragmenter,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum MulticastGroupState {
/// Joining group, we have to send the join packet.
Joining,
/// We've already sent the join packet, we have nothing to do.
Joined,
/// We want to leave the group, we have to send a leave packet.
Leaving,
}

/// The device independent part of an Ethernet network interface.
///
/// Separating the device from the data required for processing and dispatching makes
Expand Down Expand Up @@ -121,11 +105,8 @@ pub struct InterfaceInner {
ip_addrs: Vec<IpCidr, IFACE_MAX_ADDR_COUNT>,
any_ip: bool,
routes: Routes,
#[cfg(any(feature = "proto-igmp", feature = "proto-ipv6"))]
multicast_groups: LinearMap<IpAddress, MulticastGroupState, IFACE_MAX_MULTICAST_GROUP_COUNT>,
/// When to report for (all or) the next multicast group membership via IGMP
#[cfg(feature = "proto-igmp")]
igmp_report_state: IgmpReportState,
#[cfg(feature = "multicast")]
multicast: multicast::State,
}

/// Configuration structure used for creating a network interface.
Expand Down Expand Up @@ -234,10 +215,8 @@ impl Interface {
routes: Routes::new(),
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
neighbor_cache: NeighborCache::new(),
#[cfg(any(feature = "proto-igmp", feature = "proto-ipv6"))]
multicast_groups: LinearMap::new(),
#[cfg(feature = "proto-igmp")]
igmp_report_state: IgmpReportState::Inactive,
#[cfg(feature = "multicast")]
multicast: multicast::State::new(),
#[cfg(feature = "medium-ieee802154")]
sequence_no,
#[cfg(feature = "medium-ieee802154")]
Expand Down Expand Up @@ -445,10 +424,8 @@ impl Interface {
let mut readiness_may_have_changed = self.socket_ingress(device, sockets);
readiness_may_have_changed |= self.socket_egress(device, sockets);

#[cfg(feature = "proto-igmp")]
{
readiness_may_have_changed |= self.multicast_egress(device);
}
#[cfg(feature = "multicast")]
self.multicast_egress(device);

readiness_may_have_changed
}
Expand Down Expand Up @@ -755,36 +732,23 @@ impl InterfaceInner {
}

/// Check whether the interface listens to given destination multicast IP address.
///
/// If built without feature `proto-igmp` this function will
/// always return `false` when using IPv4.
fn has_multicast_group<T: Into<IpAddress>>(&self, addr: T) -> bool {
/// Return false if we don't have the multicast group,
/// or we're leaving it.
fn wanted_state(x: Option<&MulticastGroupState>) -> bool {
match x {
None => false,
Some(MulticastGroupState::Joining) => true,
Some(MulticastGroupState::Joined) => true,
Some(MulticastGroupState::Leaving) => false,
}
let addr = addr.into();

#[cfg(feature = "multicast")]
if self.multicast.has_multicast_group(addr) {
return true;
}

let addr = addr.into();
match addr {
#[cfg(feature = "proto-igmp")]
IpAddress::Ipv4(key) => {
key == Ipv4Address::MULTICAST_ALL_SYSTEMS
|| wanted_state(self.multicast_groups.get(&addr))
}
#[cfg(feature = "proto-ipv4")]
IpAddress::Ipv4(key) => key == Ipv4Address::MULTICAST_ALL_SYSTEMS,
#[cfg(feature = "proto-rpl")]
IpAddress::Ipv6(Ipv6Address::LINK_LOCAL_ALL_RPL_NODES) => true,
#[cfg(feature = "proto-ipv6")]
IpAddress::Ipv6(key) => {
key == Ipv6Address::LINK_LOCAL_ALL_NODES
|| self.has_solicited_node(key)
|| wanted_state(self.multicast_groups.get(&addr))
key == Ipv6Address::LINK_LOCAL_ALL_NODES || self.has_solicited_node(key)
}
#[cfg(feature = "proto-rpl")]
IpAddress::Ipv6(Ipv6Address::LINK_LOCAL_ALL_RPL_NODES) => true,
#[allow(unreachable_patterns)]
_ => false,
}
Expand Down
Loading

0 comments on commit 469dccd

Please sign in to comment.