[pve-devel] [PATCH proxmox-ve-rs v4 08/22] frr: add route-map types
Gabriel Goller
g.goller at proxmox.com
Mon Jul 7 19:13:03 CEST 2025
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!
More information about the pve-devel
mailing list