Skip to content

Commit

Permalink
IPv6: implement leave_multicast_group()
Browse files Browse the repository at this point in the history
Also, modify `test_join_ipv6_multicast_group()` so that it joins
the mDNS multicast group instead of 0xfe80::1. Because the lower 24
bits of 0xfe80::01 match the lower part of the IPv6 address assigned
to the test device by `crate::tests::setup()`, `has_multicast_group()`
would always returns `true`.
  • Loading branch information
lucasvr committed Apr 17, 2024
1 parent 6c06cd9 commit cf1744a
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 12 deletions.
36 changes: 25 additions & 11 deletions src/iface/interface/igmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,7 @@ impl Interface {
#[cfg(feature = "proto-ipv6")]
IpAddress::Ipv6(addr) => {
// Build report packet containing this new address
let initial_report_record: &[MldAddressRecordRepr] = &[MldAddressRecordRepr {
num_srcs: 0,
mcast_addr: addr,
record_type: MldRecordType::ChangeToInclude,
aux_data_len: 0,
payload: &[],
}];

let report_record = &[MldAddressRecordRepr::new(MldRecordType::ChangeToInclude, addr)];
let is_not_new = self
.inner
.ipv6_multicast_groups
Expand All @@ -90,7 +83,7 @@ impl Interface {
.is_some();
if is_not_new {
Ok(false)
} else if let Some(pkt) = self.inner.mldv2_report_packet(initial_report_record) {
} else if let Some(pkt) = self.inner.mldv2_report_packet(report_record) {
// Send initial membership report
let tx_token = device
.transmit(timestamp)
Expand Down Expand Up @@ -147,9 +140,30 @@ impl Interface {
Ok(false)
}
}
// Multicast is not yet implemented for other address families
#[cfg(feature = "proto-ipv6")]
IpAddress::Ipv6(addr) => {
let report_record = &[MldAddressRecordRepr::new(MldRecordType::ChangeToExclude, addr)];
let was_not_present = self.inner.ipv6_multicast_groups.remove(&addr).is_none();
if was_not_present {
Ok(false)
} else if let Some(pkt) = self.inner.mldv2_report_packet(report_record) {
// Send group leave packet
let tx_token = device
.transmit(timestamp)
.ok_or(MulticastError::Exhausted)?;

// NOTE(unwrap): packet destination is multicast, which is always routable and doesn't require neighbor discovery.
self.inner
.dispatch_ip(tx_token, PacketMeta::default(), pkt, &mut self.fragmenter)
.unwrap();

Ok(true)
} else {
Ok(false)
}
}
#[allow(unreachable_patterns)]
_ => Err(MulticastError::Ipv6NotSupported),
_ => Err(MulticastError::Unaddressable),
}
}

Expand Down
7 changes: 6 additions & 1 deletion src/iface/interface/tests/ipv6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1204,7 +1204,7 @@ fn test_join_ipv6_multicast_group(#[case] medium: Medium) {
let (mut iface, _sockets, mut device) = setup(medium);

let groups = [
Ipv6Address::from_parts(&[0xff05, 0, 0, 0, 0, 0, 0, 0x0001]),
Ipv6Address::from_parts(&[0xff05, 0, 0, 0, 0, 0, 0, 0x00fb]),
Ipv6Address::from_parts(&[0xff0e, 0, 0, 0, 0, 0, 0, 0x0017]),
];

Expand Down Expand Up @@ -1285,5 +1285,10 @@ fn test_join_ipv6_multicast_group(#[case] medium: Medium) {
payload: &[],
}
);

iface
.leave_multicast_group(&mut device, group_addr, timestamp)
.unwrap();
assert!(!iface.has_multicast_group(group_addr));
}
}
11 changes: 11 additions & 0 deletions src/wire/mld.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,17 @@ pub struct AddressRecordRepr<'a> {
}

impl<'a> AddressRecordRepr<'a> {
/// Create a new MLDv2 address record representation with an empty payload.
pub const fn new(record_type: RecordType, mcast_addr: Ipv6Address) -> Self {
Self {
record_type,
aux_data_len: 0,
num_srcs: 0,
mcast_addr,
payload: &[],
}
}

/// Parse an MLDv2 address record and return a high-level representation.
pub fn parse<T>(record: &AddressRecord<&'a T>) -> Result<Self>
where
Expand Down

0 comments on commit cf1744a

Please sign in to comment.