From 43229a54acd466f267aa47e461dbf702a0117ad4 Mon Sep 17 00:00:00 2001 From: Igor Putovny Date: Tue, 5 Aug 2025 18:20:12 +0200 Subject: [PATCH] Netlink: Add parsing of bridge and VXLAN interface attributes --- nest/iface.h | 6 +++++ sysdep/linux/netlink.c | 61 ++++++++++++++++++++++++++++++++++++++++++ sysdep/unix/krt.h | 10 +++++++ 3 files changed, 77 insertions(+) diff --git a/nest/iface.h b/nest/iface.h index 93441b396..f06ab0028 100644 --- a/nest/iface.h +++ b/nest/iface.h @@ -45,6 +45,12 @@ struct iface { struct rta *attrs; }; +enum iface_type { + IF_TYPE_UNDEF, + IF_TYPE_BRIDGE, + IF_TYPE_VXLAN, +}; + #define IF_UP 1 /* Currently just IF_ADMIN_UP */ #define IF_MULTIACCESS 2 #define IF_BROADCAST 4 diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 15df573b9..a9b382cf8 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -381,6 +381,21 @@ static struct nl_want_attrs ifinfo_attr_want[BIRD_INFO_MAX] = { [IFLA_INFO_DATA]= { 1, 0, 0 }, }; +#define BIRD_IFLA_BR_MAX (IFLA_BR_VLAN_FILTERING+1) + +static struct nl_want_attrs ifla_br_attr_want[BIRD_IFLA_BR_MAX] = { + [IFLA_BR_VLAN_FILTERING] = { 1, 1, sizeof(u8) }, +}; + +#define BIRD_IFLA_VXLAN_MAX (IFLA_VXLAN_LOCAL6+1) + +static struct nl_want_attrs ifla_vxlan_attr_want[BIRD_IFLA_VXLAN_MAX] = { + [IFLA_VXLAN_ID] = { 1, 1, sizeof(u32) }, + [IFLA_VXLAN_LEARNING] = { 1, 1, sizeof(u8) }, + [IFLA_VXLAN_LOCAL] = { 1, 1, sizeof(ip4_addr) }, + [IFLA_VXLAN_LOCAL6] = { 1, 1, sizeof(ip6_addr) }, +}; + #define BIRD_IFA_MAX (IFA_FLAGS+1) @@ -514,6 +529,9 @@ nl_parse_attrs(struct rtattr *a, struct nl_want_attrs *want, struct rtattr **k, return 1; } +static inline u8 rta_get_u8(struct rtattr *a) +{ return *(u8 *) RTA_DATA(a); } + static inline u16 rta_get_u16(struct rtattr *a) { return *(u16 *) RTA_DATA(a); } @@ -986,8 +1004,51 @@ nl_parse_link(struct nlmsghdr *h, int scan) struct rtattr *li[BIRD_INFO_MAX]; nl_attr_len = RTA_PAYLOAD(a[IFLA_LINKINFO]); nl_parse_attrs(RTA_DATA(a[IFLA_LINKINFO]), ifinfo_attr_want, li, sizeof(li)); + if (li[IFLA_INFO_KIND]) kind = RTA_DATA(li[IFLA_INFO_KIND]); + + if (!strcmp(kind, "bridge") && li[IFLA_INFO_DATA]) + { + ea_set_attr_u32(&f.attrs->eattrs, tmp_linpool, EA_IFACE_TYPE, 0, EAF_TYPE_INT, IF_TYPE_BRIDGE); + + struct rtattr *data[BIRD_IFLA_BR_MAX]; + nl_attr_len = RTA_PAYLOAD(li[IFLA_INFO_DATA]); + nl_parse_attrs(RTA_DATA(li[IFLA_INFO_DATA]), ifla_br_attr_want, data, sizeof(data)); + + if (data[IFLA_BR_VLAN_FILTERING]) + { + u8 vlan_filtering = rta_get_u32(data[IFLA_BR_VLAN_FILTERING]); + ea_set_attr_u32(&f.attrs->eattrs, tmp_linpool, EA_IFACE_BRIDGE_VLAN_FILTERING, 0, EAF_TYPE_INT, vlan_filtering); + } + } + else if (!strcmp(kind, "vxlan") && li[IFLA_INFO_DATA]) + { + ea_set_attr_u32(&f.attrs->eattrs, tmp_linpool, EA_IFACE_TYPE, 0, EAF_TYPE_INT, IF_TYPE_VXLAN); + + struct rtattr *data[BIRD_IFLA_VXLAN_MAX]; + nl_attr_len = RTA_PAYLOAD(li[IFLA_INFO_DATA]); + nl_parse_attrs(RTA_DATA(li[IFLA_INFO_DATA]), ifla_vxlan_attr_want, data, sizeof(data)); + + if (data[IFLA_VXLAN_ID]) + { + u32 id = rta_get_u32(data[IFLA_VXLAN_ID]); + ea_set_attr_u32(&f.attrs->eattrs, tmp_linpool, EA_IFACE_VXLAN_ID, 0, EAF_TYPE_INT, id); + } + + if (data[IFLA_VXLAN_LEARNING]) + { + u8 learning = rta_get_u8(data[IFLA_VXLAN_LEARNING]); + ea_set_attr_u32(&f.attrs->eattrs, tmp_linpool, EA_IFACE_VXLAN_LEARNING, 0, EAF_TYPE_INT, learning); + } + + if (data[IFLA_VXLAN_LOCAL] || data[IFLA_VXLAN_LOCAL6]) + { + struct rtattr *attr = data[IFLA_VXLAN_LOCAL] ? data[IFLA_VXLAN_LOCAL] : data[IFLA_VXLAN_LOCAL6]; + ip_addr addr = rta_get_ipa(attr); + ea_set_attr_data(&f.attrs->eattrs, tmp_linpool, EA_IFACE_VXLAN_IP_ADDR, 0, EAF_TYPE_IP_ADDRESS, &addr, sizeof(addr)); + } + } } ifi = if_find_by_index(i->ifi_index); diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h index 2b1dfa96d..1377bea51 100644 --- a/sysdep/unix/krt.h +++ b/sysdep/unix/krt.h @@ -31,6 +31,16 @@ struct kif_proto; #define KRT_LEARN_ALIEN 1 /* Learn KRT_SRC_ALIEN routes */ #define KRT_LEARN_ALL 2 /* Learn both KRT_SRC_ALIEN and KRT_SRC_KERNEL routes */ + +#define EA_IFACE_TYPE EA_CODE(PROTOCOL_DEVICE, 0) + +#define EA_IFACE_BRIDGE_VLAN_FILTERING EA_CODE(PROTOCOL_DEVICE, 1) + +#define EA_IFACE_VXLAN_ID EA_CODE(PROTOCOL_DEVICE, 2) +#define EA_IFACE_VXLAN_LEARNING EA_CODE(PROTOCOL_DEVICE, 3) +#define EA_IFACE_VXLAN_IP_ADDR EA_CODE(PROTOCOL_DEVICE, 4) + + /* Whenever we recognize our own routes, we allow learing of foreign routes */ #ifdef CONFIG_SELF_CONSCIOUS -- 2.47.2