Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multicast: use single Cargo feature for both ipv4 and ipv6. #988

Merged
merged 1 commit into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading