diff options
| author | Sharath Ramamurthy <sramamurthy@nvidia.com> | 2021-07-27 13:17:52 +0530 |
|---|---|---|
| committer | Stephen Worley <sworley@nvidia.com> | 2023-02-13 18:12:04 -0500 |
| commit | 784d88aa14c115411ed21f6ac518ab1a8f9d27b7 (patch) | |
| tree | 86c103be00f0442b205027ca2cc2f852275eac94 /zebra/rt_netlink.c | |
| parent | 8d30ff3b5ef815ad5cab092f2ce6dc28ab5e3421 (diff) | |
zebra: multiple vlan aware bridge datastructure changes and vxlan device iftype derivation from netlink
This change set introduces data structure changes required for multiple vlan aware bridge
functionality. A new structure zebra_l2_bridge_if encapsulates the vlan to access_bd
association of the bridge. A vlan_table hash_table is used to record each instance
of the vlan to access_bd of the bridge via zebra_l2_bridge_vlan structure.
vxlan iftype derivation: netlink attribute IFLA_VXLAN_COLLECT_METADATA is used
to derive the iftype of the vxlan device. If the attribute is present, then the
vxlan interface is treated as single vxlan device, otherwise it would default to
traditional vxlan device.
zebra_vxlan_check_readd_vtep, zebra_vxlan_dp_network_mac_add/del is modified to
be vni aware.
mac_fdb_read_for_bridge - is modified to be (vlan, bridge) aware
Signed-off-by: Sharath Ramamurthy <sramamurthy@nvidia.com>
Diffstat (limited to 'zebra/rt_netlink.c')
| -rw-r--r-- | zebra/rt_netlink.c | 81 |
1 files changed, 61 insertions, 20 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 79d6af60ce..21222408b7 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -153,6 +153,22 @@ static bool is_proto_nhg(uint32_t id, int type) return false; } +/* Is vni mcast group */ +static bool is_mac_vni_mcast_group(struct ethaddr *mac, vni_t vni, + struct in_addr grp_addr) +{ + if (!vni) + return false; + + if (!is_zero_mac(mac)) + return false; + + if (!IN_MULTICAST(ntohl(grp_addr.s_addr))) + return false; + + return true; +} + /* * The ipv4_ll data structure is used for all 5549 * additions to the kernel. Let's figure out the @@ -3457,7 +3473,9 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) bool sticky; bool local_inactive = false; bool dp_static = false; + vni_t vni = 0; uint32_t nhg_id = 0; + bool vni_mcast_grp = false; ndm = NLMSG_DATA(h); @@ -3528,12 +3546,16 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) } } + if (tb[NDA_SRC_VNI]) + vni = *(vni_t *)RTA_DATA(tb[NDA_SRC_VNI]); + if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("Rx %s AF_BRIDGE IF %u%s st 0x%x fl 0x%x MAC %pEA%s nhg %d", - nl_msg_type_to_str(h->nlmsg_type), - ndm->ndm_ifindex, vid_present ? vid_buf : "", - ndm->ndm_state, ndm->ndm_flags, &mac, - dst_present ? dst_buf : "", nhg_id); + zlog_debug( + "Rx %s AF_BRIDGE IF %u%s st 0x%x fl 0x%x MAC %pEA%s nhg %d vni %d", + nl_msg_type_to_str(h->nlmsg_type), ndm->ndm_ifindex, + vid_present ? vid_buf : "", ndm->ndm_state, + ndm->ndm_flags, &mac, dst_present ? dst_buf : "", + nhg_id, vni); /* The interface should exist. */ ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), @@ -3556,6 +3578,13 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) return 0; } + /* For per vni device, vni comes from device itself */ + if (IS_ZEBRA_IF_VXLAN(ifp) && IS_ZEBRA_VXLAN_IF_VNI(zif)) { + struct zebra_vxlan_vni *vnip; + vnip = zebra_vxlan_if_vni_find(zif, 0); + vni = vnip->vni; + } + sticky = !!(ndm->ndm_flags & NTF_STICKY); if (filter_vlan && vid != filter_vlan) { @@ -3565,6 +3594,11 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) return 0; } + /* + * Check if this is a mcast group update (svd case) + */ + vni_mcast_grp = is_mac_vni_mcast_group(&mac, vni, vtep_ip); + /* If add or update, do accordingly if learnt on a "local" interface; if * the notification is over VxLAN, this has to be related to * multi-homing, @@ -3572,17 +3606,25 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) */ if (h->nlmsg_type == RTM_NEWNEIGH) { /* Drop "permanent" entries. */ - if (ndm->ndm_state & NUD_PERMANENT) { + if (!vni_mcast_grp && (ndm->ndm_state & NUD_PERMANENT)) { if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( " Dropping entry because of NUD_PERMANENT"); return 0; } - if (IS_ZEBRA_IF_VXLAN(ifp)) - return zebra_vxlan_dp_network_mac_add( - ifp, br_if, &mac, vid, nhg_id, sticky, - !!(ndm->ndm_flags & NTF_EXT_LEARNED)); + if (IS_ZEBRA_IF_VXLAN(ifp)) { + if (!dst_present) + return 0; + + if (vni_mcast_grp) + /* TODO: handle mcast group update for svd */ + + return zebra_vxlan_dp_network_mac_add( + ifp, br_if, &mac, vid, vni, nhg_id, + sticky, + !!(ndm->ndm_flags & NTF_EXT_LEARNED)); + } return zebra_vxlan_local_mac_add_update(ifp, br_if, &mac, vid, sticky, local_inactive, dp_static); @@ -3602,15 +3644,18 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) return 0; if (dst_present) { - u_char zero_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + if (vni_mcast_grp) + /* TODO: handle mcast group update for svd */ + + if (is_zero_mac(&mac)) + return zebra_vxlan_check_readd_vtep(ifp, vni, + vtep_ip); - if (!memcmp(zero_mac, mac.octet, ETH_ALEN)) - return zebra_vxlan_check_readd_vtep(ifp, vtep_ip); return 0; } if (IS_ZEBRA_IF_VXLAN(ifp)) - return zebra_vxlan_dp_network_mac_del(ifp, br_if, &mac, vid); + return 0; return zebra_vxlan_local_mac_del(ifp, br_if, &mac, vid); } @@ -3687,11 +3732,9 @@ int netlink_macfdb_read(struct zebra_ns *zns) * specific bridge and matching specific access VLAN (if VLAN-aware bridge). */ int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, - struct interface *br_if) + struct interface *br_if, vlanid_t vid) { struct zebra_if *br_zif; - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl; struct zebra_dplane_info dp_info; int ret = 0; @@ -3699,10 +3742,8 @@ int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, /* Save VLAN we're filtering on, if needed. */ br_zif = (struct zebra_if *)br_if->info; - zif = (struct zebra_if *)ifp->info; - vxl = &zif->l2info.vxl; if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif)) - filter_vlan = vxl->vni_info.vni.access_vlan; + filter_vlan = vid; /* Get bridge FDB table for specific bridge - we do the VLAN filtering. */ |
