1use std::marker::PhantomData;
34
35use bit_set::BitSet;
36
37use crate::logging::{log_info, log_warn};
38use crate::protocol_family::NamedNetlinkFamily;
39
40const U32_BITS_USIZE: usize = u32::BITS as usize;
42
43#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
45pub struct ModernGroup(pub u32);
46
47impl Into<usize> for ModernGroup {
48 fn into(self) -> usize {
49 let ModernGroup(group) = self;
50 group.try_into().expect("expected usize >= u32")
51 }
52}
53
54#[derive(Debug, PartialEq)]
57pub struct NoMappingFromModernToLegacyGroupError;
58
59impl TryFrom<ModernGroup> for SingleLegacyGroup {
60 type Error = NoMappingFromModernToLegacyGroupError;
61
62 fn try_from(
63 ModernGroup(group): ModernGroup,
64 ) -> Result<SingleLegacyGroup, NoMappingFromModernToLegacyGroupError> {
65 if let Some(group) = 1u32.checked_shl(group) {
66 Ok(SingleLegacyGroup(group))
67 } else {
68 Err(NoMappingFromModernToLegacyGroupError)
69 }
70 }
71}
72
73#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
76pub struct LegacyGroups(pub u32);
77
78#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
80pub struct SingleLegacyGroup(u32);
81
82impl SingleLegacyGroup {
83 pub fn inner(&self) -> u32 {
85 let SingleLegacyGroup(inner) = self;
86 *inner
87 }
88}
89
90#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
92pub struct MultipleBitsSetError;
93
94impl TryFrom<u32> for SingleLegacyGroup {
95 type Error = MultipleBitsSetError;
96 fn try_from(value: u32) -> Result<Self, Self::Error> {
97 (value.count_ones() <= 1).then_some(SingleLegacyGroup(value)).ok_or(MultipleBitsSetError)
98 }
99}
100
101#[derive(Clone, Copy, Debug, Eq, PartialEq)]
104pub(crate) enum GroupSupport {
105 Supported,
107 Unsupported,
109}
110
111#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
113pub struct InvalidModernGroupError;
114
115pub(crate) trait MulticastCapableNetlinkFamily {
117 fn check_support(group: &ModernGroup) -> Result<GroupSupport, InvalidModernGroupError>;
120}
121
122#[derive(Debug)]
128pub(crate) struct MulticastGroupMemberships<F: MulticastCapableNetlinkFamily> {
129 family: PhantomData<F>,
131
132 memberships: BitSet,
136}
137
138#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
139pub(crate) enum Mutation {
140 None,
141 Add(ModernGroup),
142 Del(ModernGroup),
143}
144
145#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
147pub struct InvalidLegacyGroupsError;
148
149impl<F: MulticastCapableNetlinkFamily + NamedNetlinkFamily> MulticastGroupMemberships<F> {
150 pub(crate) fn new() -> MulticastGroupMemberships<F> {
152 MulticastGroupMemberships { family: PhantomData, memberships: Default::default() }
153 }
154
155 pub(crate) fn member_of_group(&self, group: ModernGroup) -> bool {
157 self.memberships.contains(group.into())
158 }
159
160 pub(crate) fn add_membership(
164 &mut self,
165 group: ModernGroup,
166 ) -> Result<bool, InvalidModernGroupError> {
167 let MulticastGroupMemberships { family: _, memberships } = self;
168 if F::check_support(&group)? == GroupSupport::Unsupported {
169 log_info!(
170 "{}: adding membership for valid but unsupported multicast group {:?}",
171 F::NAME,
172 group
173 );
174 }
175 let was_absent = memberships.insert(group.into());
176 return Ok(was_absent);
177 }
178
179 pub(crate) fn del_membership(
183 &mut self,
184 group: ModernGroup,
185 ) -> Result<bool, InvalidModernGroupError> {
186 let MulticastGroupMemberships { family: _, memberships } = self;
187 let _ = F::check_support(&group)?;
188 let was_present = memberships.remove(group.into());
189 return Ok(was_present);
190 }
191
192 pub(crate) fn set_legacy_memberships(
199 &mut self,
200 LegacyGroups(requested_groups): LegacyGroups,
201 ) -> Result<Vec<Mutation>, InvalidLegacyGroupsError> {
202 crate::logging::log_debug!("set_legacy_memberships");
203 let MulticastGroupMemberships { family: _, memberships } = self;
204
205 let mut mutations = [Mutation::None; U32_BITS_USIZE];
206 for i in 0..U32_BITS_USIZE {
208 let raw_legacy_group = 1 << i;
209 let legacy_group: SingleLegacyGroup = raw_legacy_group
210 .try_into()
211 .expect("raw_legacy_group unexpectedly had multiple bits set");
212
213 let modern_group = ModernGroup(legacy_group.inner().ilog2() + 1);
214 let support = F::check_support(&modern_group);
215 let is_member_of_group = requested_groups & raw_legacy_group != 0;
216 mutations[i] = match (support, is_member_of_group) {
217 (Ok(support), true) => {
218 if support == GroupSupport::Unsupported {
219 log_info!(
220 "{}: adding membership for valid but unsupported multicast group {:?}",
221 F::NAME,
222 modern_group
223 );
224 }
225 Mutation::Add(modern_group)
226 }
227 (Ok(_), false) => Mutation::Del(modern_group),
228 (Err(_), true) => {
229 log_warn!(
230 "{}: failed to join legacy groups ({:?}) because of invalid group: {:?}",
231 F::NAME,
232 requested_groups,
233 legacy_group
234 );
235 return Err(InvalidLegacyGroupsError);
236 }
237 (Err(_), false) => Mutation::None,
238 };
239 }
240
241 let mut return_mutations = Vec::new();
242 for mutation in mutations {
244 match mutation {
245 Mutation::None => {}
246 Mutation::Add(group) => {
247 crate::logging::log_debug!("mutation: add {group:?}");
248 let was_absent = memberships.insert(group.into());
249 if was_absent {
250 return_mutations.push(Mutation::Add(group));
251 }
252 }
253 Mutation::Del(group) => {
254 crate::logging::log_debug!("mutation: del {group:?}");
255 let was_present = memberships.remove(group.into());
256 if was_present {
257 return_mutations.push(Mutation::Del(group));
258 }
259 }
260 }
261 }
262 Ok(return_mutations)
263 }
264
265 pub(crate) fn iter_groups(&self) -> impl Iterator<Item = ModernGroup> + '_ {
266 self.memberships.into_iter().map(|n: usize| {
267 let n = u32::try_from(n).expect("all ModernGroups fit in u32");
268 ModernGroup(n)
269 })
270 }
271}
272
273#[cfg(test)]
274mod tests {
275 use super::*;
276
277 use crate::protocol_family::testutil::{
278 FakeProtocolFamily, INVALID_LEGACY_GROUP, INVALID_MODERN_GROUP, LEGACY_GROUP1,
279 LEGACY_GROUP2, LEGACY_GROUP3, MODERN_GROUP1, MODERN_GROUP2, MODERN_GROUP3,
280 };
281
282 #[test]
283 fn test_single_legacy_groups() {
284 assert_eq!(0.try_into(), Ok(SingleLegacyGroup(0)));
285 assert_eq!(0x00010000.try_into(), Ok(SingleLegacyGroup(0x00010000)));
286 assert_eq!(
287 <u32 as TryInto<SingleLegacyGroup>>::try_into(0x00010100),
288 Err(MultipleBitsSetError {})
289 );
290 }
291
292 #[test]
293 fn test_modern_to_legacy_groups() {
294 assert_eq!(ModernGroup(0).try_into(), Ok(SingleLegacyGroup(0b00000001)));
295 assert_eq!(ModernGroup(4).try_into(), Ok(SingleLegacyGroup(0b00010000)));
296 assert_eq!(
297 ModernGroup(100).try_into(),
298 Err::<SingleLegacyGroup, _>(NoMappingFromModernToLegacyGroupError)
299 );
300 }
301
302 #[test]
303 fn test_add_del_membership() {
304 let mut memberships = MulticastGroupMemberships::<FakeProtocolFamily>::new();
305
306 assert!(!memberships.member_of_group(MODERN_GROUP1));
307 assert!(!memberships.member_of_group(MODERN_GROUP2));
308 assert!(!memberships.member_of_group(MODERN_GROUP3));
309
310 let changed = memberships.add_membership(MODERN_GROUP1).expect("failed to add");
312 assert!(changed, "should have changed group memberships");
313 assert!(memberships.member_of_group(MODERN_GROUP1));
314 assert!(!memberships.member_of_group(MODERN_GROUP2));
315 assert!(!memberships.member_of_group(MODERN_GROUP3));
316 let changed = memberships.add_membership(MODERN_GROUP2).expect("failed to add");
318 assert!(changed, "should have changed group memberships");
319 let changed = memberships.add_membership(MODERN_GROUP3).expect("failed to add");
320 assert!(changed, "should have changed group memberships");
321 assert!(memberships.member_of_group(MODERN_GROUP1));
322 assert!(memberships.member_of_group(MODERN_GROUP2));
323 assert!(memberships.member_of_group(MODERN_GROUP3));
324 let changed = memberships.del_membership(MODERN_GROUP1).expect("failed to del");
326 assert!(changed, "should have changed group memberships");
327 assert!(!memberships.member_of_group(MODERN_GROUP1));
328 assert!(memberships.member_of_group(MODERN_GROUP2));
329 assert!(memberships.member_of_group(MODERN_GROUP3));
330 let changed = memberships.del_membership(MODERN_GROUP2).expect("failed to del");
332 assert!(changed, "should have changed group memberships");
333 let changed = memberships.del_membership(MODERN_GROUP3).expect("failed to del");
334 assert!(changed, "should have changed group memberships");
335 assert!(!memberships.member_of_group(MODERN_GROUP1));
336 assert!(!memberships.member_of_group(MODERN_GROUP2));
337 assert!(!memberships.member_of_group(MODERN_GROUP3));
338 assert_eq!(
340 memberships.add_membership(INVALID_MODERN_GROUP),
341 Err(InvalidModernGroupError {})
342 );
343 assert_eq!(
344 memberships.del_membership(INVALID_MODERN_GROUP),
345 Err(InvalidModernGroupError {})
346 );
347 }
348
349 #[test]
350 fn test_legacy_memberships() {
351 let mut memberships = MulticastGroupMemberships::<FakeProtocolFamily>::new();
352
353 assert!(!memberships.member_of_group(MODERN_GROUP1));
354 assert!(!memberships.member_of_group(MODERN_GROUP2));
355 assert!(!memberships.member_of_group(MODERN_GROUP3));
356
357 let mutations = memberships
359 .set_legacy_memberships(LegacyGroups(LEGACY_GROUP1))
360 .expect("failed to set legacy groups");
361 let expected_mutations = [Mutation::Add(MODERN_GROUP1)];
362 assert_eq!(mutations, expected_mutations);
363 assert!(memberships.member_of_group(MODERN_GROUP1));
364 assert!(!memberships.member_of_group(MODERN_GROUP2));
365 assert!(!memberships.member_of_group(MODERN_GROUP3));
366 let mutations = memberships
368 .set_legacy_memberships(LegacyGroups(LEGACY_GROUP1 | LEGACY_GROUP2 | LEGACY_GROUP3))
369 .expect("failed to set legacy groups");
370 let expected_mutations = [Mutation::Add(MODERN_GROUP2), Mutation::Add(MODERN_GROUP3)];
371 assert_eq!(mutations, expected_mutations);
372 assert!(memberships.member_of_group(MODERN_GROUP1));
373 assert!(memberships.member_of_group(MODERN_GROUP2));
374 assert!(memberships.member_of_group(MODERN_GROUP3));
375 let mutations = memberships
377 .set_legacy_memberships(LegacyGroups(LEGACY_GROUP2 | LEGACY_GROUP3))
378 .expect("failed to set legacy_groups");
379 let expected_mutations = [Mutation::Del(MODERN_GROUP1)];
380 assert_eq!(mutations, expected_mutations);
381 assert!(!memberships.member_of_group(MODERN_GROUP1));
382 assert!(memberships.member_of_group(MODERN_GROUP2));
383 assert!(memberships.member_of_group(MODERN_GROUP3));
384 let mutations = memberships
386 .set_legacy_memberships(LegacyGroups(0))
387 .expect("failed to set legacy groups");
388 let expected_mutations = [Mutation::Del(MODERN_GROUP2), Mutation::Del(MODERN_GROUP3)];
389 assert_eq!(mutations, expected_mutations);
390 assert!(!memberships.member_of_group(MODERN_GROUP1));
391 assert!(!memberships.member_of_group(MODERN_GROUP2));
392 assert!(!memberships.member_of_group(MODERN_GROUP3));
393 assert_eq!(
395 memberships.set_legacy_memberships(LegacyGroups(INVALID_LEGACY_GROUP)),
396 Err(InvalidLegacyGroupsError {})
397 );
398 }
399
400 #[test]
401 fn test_legacy_and_modern_memberships() {
402 let mut memberships = MulticastGroupMemberships::<FakeProtocolFamily>::new();
403
404 assert!(!memberships.member_of_group(MODERN_GROUP1));
405 assert!(!memberships.member_of_group(MODERN_GROUP2));
406
407 let _: Vec<Mutation> = memberships
409 .set_legacy_memberships(LegacyGroups(LEGACY_GROUP1 | LEGACY_GROUP2))
410 .expect("failed to set legacy groups");
411 assert!(memberships.member_of_group(MODERN_GROUP1));
412 assert!(memberships.member_of_group(MODERN_GROUP2));
413 let _: bool = memberships.del_membership(MODERN_GROUP1).expect("failed to del");
414 assert!(!memberships.member_of_group(MODERN_GROUP1));
415 assert!(memberships.member_of_group(MODERN_GROUP2));
416 let _: bool = memberships.del_membership(MODERN_GROUP2).expect("failed to del");
417 assert!(!memberships.member_of_group(MODERN_GROUP1));
418 assert!(!memberships.member_of_group(MODERN_GROUP2));
419
420 let _: bool = memberships.add_membership(MODERN_GROUP1).expect("failed to add");
422 let _: bool = memberships.add_membership(MODERN_GROUP2).expect("failed to add");
423 assert!(memberships.member_of_group(MODERN_GROUP1));
424 assert!(memberships.member_of_group(MODERN_GROUP2));
425 let _: Vec<Mutation> = memberships
426 .set_legacy_memberships(LegacyGroups(LEGACY_GROUP2))
427 .expect("failed to set legacy groups");
428 assert!(!memberships.member_of_group(MODERN_GROUP1));
429 assert!(memberships.member_of_group(MODERN_GROUP2));
430 let _: Vec<Mutation> = memberships
431 .set_legacy_memberships(LegacyGroups(0))
432 .expect("failed to set legacy groups");
433 assert!(!memberships.member_of_group(MODERN_GROUP1));
434 assert!(!memberships.member_of_group(MODERN_GROUP2));
435 }
436}