On 07.07.2025 13:52, Wolfgang Bumiller wrote:
On Wed, Jul 02, 2025 at 04:49:59PM +0200, Gabriel Goller wrote:
[snip]
+/// A single [`AccessList`] rule.
+///
+/// Every rule in a [`AccessList`] is its own command and gets written into a 
new line (with the
+/// same name). These rules have an action - permit (match) or deny (don't 
match) - and a network
+/// address (which can be a single address or a range). The seq number is used 
to differentiate
+/// between access-lists of the same name and rules. Every [`AccessListRule`] 
has to have a
+/// different seq number.
+/// The `ip` or `ipv6` prefix gets decided based on the Cidr address passed.
+///
+/// This serializes to:
+///
+/// ```text
+/// ip access-list filter permit 10.0.0.0/8
+/// ! or
+/// ipv6 access-list filter permit 2001:db8::/64
+/// ```
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct AccessListRule {
+    pub action: AccessAction,
+    pub network: Cidr,
+    pub seq: Option<u32>,
+}
+
+/// The name of a [`AccessList`].

an*

Yep -_-

+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct AccessListName(String);
+
+impl AccessListName {
+    pub fn new(name: String) -> AccessListName {
+        AccessListName(name)
+    }
+}
+
+impl Display for AccessListName {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+/// A FRR access-list.
+///
+/// Holds a vec of rules. Each rule will get it's own line, FRR will collect 
all the rules with the

its*

Embarrassing.

+/// same name and combine them.
+///
+/// This serializes to:
+///
+/// ```text
+/// ip access-list pve_test permit 10.0.0.0/24
+/// ip access-list pve_test permit 12.1.1.0/24
+/// ip access-list pve_test deny 8.8.8.8/32
+/// ```
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct AccessList {
+    pub name: AccessListName,
+    pub rules: Vec<AccessListRule>,
+}
+
+/// A match statement inside a route-map.
+///
+/// A route-map has one or more match statements which decide on which routes 
the route-map will
+/// execute its actions. If we match on an IP, there are two different 
syntaxes: `match ip ...` or
+/// `match ipv6 ...`.
+///
+/// Serializes to:
+///
+/// ```text
+///  match ip address <access-list-name>
+/// ! or
+///  match ip next-hop <ip-address>
+/// ! or
+///  match ipv6 address <access-list-name>
+/// ! or
+///  match ipv6 next-hop <ip-address>
+/// ```
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum RouteMapMatch {
+    V4(RouteMapMatchInner),
+    V6(RouteMapMatchInner),
+}
+
+impl Display for RouteMapMatch {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            RouteMapMatch::V4(route_map_match_v4) => match route_map_match_v4 {
+                RouteMapMatchInner::IpAddress(access_list_name) => {

(hint: ↑ for now these are still short enough that a single match with a
nested pattern would be less and easier to read, but not really
important - if more variants are added I'd actual recommend using helper
methods on the individual types)

Yep, I agree. This will probably be improved/rewritten anyway when we
add route-maps to the ui.

+                    write!(f, "match ip address {access_list_name}")
+                }
+                RouteMapMatchInner::IpNextHop(next_hop) => {
+                    write!(f, "match ip next-hop {next_hop}")
+                }
+            },
+            RouteMapMatch::V6(route_map_match_v6) => match route_map_match_v6 {
+                RouteMapMatchInner::IpAddress(access_list_name) => {
+                    write!(f, "match ipv6 address {access_list_name}")
+                }
+                RouteMapMatchInner::IpNextHop(next_hop) => {
+                    write!(f, "match ipv6 next-hop {next_hop}")
+                }
+            },
+        }
+    }
+}
+

Thanks!


_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to