netstack3_filter/
actions.rs

1// Copyright 2025 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use netstack3_base::Mark;
6
7/// An action that can be applied to a mark.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum MarkAction {
10    /// This action sets the mark specified by the `mark` and `clearing_mask`.
11    ///
12    /// If the current mark is [`None`], it will just set it to `mark`.
13    SetMark {
14        /// This value will be combined with the result of the masking using a
15        /// bitwise OR to get the final mark.
16        mark: u32,
17        /// The bits specified by this mask will be cleared out from the
18        /// existing mark.
19        clearing_mask: u32,
20    },
21}
22
23impl MarkAction {
24    /// Applies the change to the given [`Mark`].
25    pub fn apply(self, mark: &mut Mark) {
26        let Mark(cur) = mark;
27        match self {
28            MarkAction::SetMark { clearing_mask, mark } => {
29                *cur = Some(match cur {
30                    Some(v) => (*v & !clearing_mask) | mark,
31                    None => mark,
32                });
33            }
34        }
35    }
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41    use test_case::test_case;
42
43    #[test_case(Mark(None), MarkAction::SetMark { mark: 1, clearing_mask: 0 } => Mark(Some(1))
44            ; "set new mark")]
45    #[test_case(Mark(Some(1)), MarkAction::SetMark { mark: 2, clearing_mask: 1 } => Mark(Some(2))
46            ; "clear with mask")]
47    #[test_case(Mark(Some(1)), MarkAction::SetMark { mark: 2, clearing_mask: 0 } => Mark(Some(3))
48            ; "or mark")]
49    fn apply_mark_action(mut mark: Mark, action: MarkAction) -> Mark {
50        action.apply(&mut mark);
51        mark
52    }
53}