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