Skip to content

Commit 508b16c

Browse files
committed
feat: Automatically join sol-node mcast addresses
IPv6 over Ethernet should join the solicited-node multicast addresses required by the configured IPv6 addresses, as neighbor solicitations for these addresses have the solicited-node multicast address as destination address. This commit automatically leaves old solicited-node multicast addresses and joins the new set when the IP addresses on the interface are updated.
1 parent cd39653 commit 508b16c

File tree

3 files changed

+48
-7
lines changed

3 files changed

+48
-7
lines changed

src/iface/interface/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,12 @@ impl Interface {
361361
pub fn update_ip_addrs<F: FnOnce(&mut Vec<IpCidr, IFACE_MAX_ADDR_COUNT>)>(&mut self, f: F) {
362362
f(&mut self.inner.ip_addrs);
363363
InterfaceInner::flush_neighbor_cache(&mut self.inner);
364-
InterfaceInner::check_ip_addrs(&self.inner.ip_addrs)
364+
InterfaceInner::check_ip_addrs(&self.inner.ip_addrs);
365+
366+
#[cfg(all(feature = "proto-ipv6", feature = "multicast"))]
367+
if self.inner.caps.medium == Medium::Ethernet {
368+
self.update_solicited_node_groups();
369+
}
365370
}
366371

367372
/// Check whether the interface has the given IP address assigned.

src/iface/interface/multicast.rs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use core::result::Result;
2-
use heapless::LinearMap;
2+
use heapless::{LinearMap, Vec};
33

44
#[cfg(feature = "proto-ipv4")]
55
use super::{check, IpPayload, Packet};
66
use super::{Interface, InterfaceInner};
7-
use crate::config::IFACE_MAX_MULTICAST_GROUP_COUNT;
7+
use crate::config::{IFACE_MAX_ADDR_COUNT, IFACE_MAX_MULTICAST_GROUP_COUNT};
88
use crate::phy::{Device, PacketMeta};
99
use crate::wire::*;
1010

@@ -140,6 +140,36 @@ impl Interface {
140140
self.inner.has_multicast_group(addr)
141141
}
142142

143+
#[cfg(feature = "proto-ipv6")]
144+
pub(super) fn update_solicited_node_groups(&mut self) {
145+
// Remove old solicited-node multicast addresses
146+
let removals: Vec<_, IFACE_MAX_MULTICAST_GROUP_COUNT> = self
147+
.inner
148+
.multicast
149+
.groups
150+
.keys()
151+
.filter_map(|group_addr| match group_addr {
152+
IpAddress::Ipv6(address)
153+
if address.is_solicited_node_multicast()
154+
&& self.inner.has_solicited_node(*address) =>
155+
{
156+
Some(*group_addr)
157+
}
158+
_ => None,
159+
})
160+
.collect();
161+
for removal in removals {
162+
let _ = self.leave_multicast_group(removal);
163+
}
164+
165+
let cidrs: Vec<IpCidr, IFACE_MAX_ADDR_COUNT> = Vec::from_slice(self.ip_addrs()).unwrap();
166+
for cidr in cidrs {
167+
if let IpCidr::Ipv6(cidr) = cidr {
168+
let _ = self.join_multicast_group(cidr.address().solicited_node());
169+
}
170+
}
171+
}
172+
143173
/// Do multicast egress.
144174
///
145175
/// - Send join/leave packets according to the multicast group state.

src/iface/interface/tests/ipv6.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,6 +1296,10 @@ fn test_join_ipv6_multicast_group(#[case] medium: Medium) {
12961296

12971297
let timestamp = Instant::from_millis(0);
12981298

1299+
// Drain the unsolicited node multicast report from the device
1300+
iface.poll(timestamp, &mut device, &mut sockets);
1301+
let _ = recv_icmpv6(&mut device, timestamp);
1302+
12991303
for &group in &groups {
13001304
iface.join_multicast_group(group).unwrap();
13011305
assert!(iface.has_multicast_group(group));
@@ -1372,9 +1376,11 @@ fn test_join_ipv6_multicast_group(#[case] medium: Medium) {
13721376
}
13731377
);
13741378

1375-
iface.leave_multicast_group(group_addr).unwrap();
1376-
assert!(!iface.has_multicast_group(group_addr));
1377-
iface.poll(timestamp, &mut device, &mut sockets);
1378-
assert!(!iface.has_multicast_group(group_addr));
1379+
if !group_addr.is_solicited_node_multicast() {
1380+
iface.leave_multicast_group(group_addr).unwrap();
1381+
assert!(!iface.has_multicast_group(group_addr));
1382+
iface.poll(timestamp, &mut device, &mut sockets);
1383+
assert!(!iface.has_multicast_group(group_addr));
1384+
}
13791385
}
13801386
}

0 commit comments

Comments
 (0)