Skip to content

Commit

Permalink
zebra: Explicitly read FDB entry for flooded traffic using MDT
Browse files Browse the repository at this point in the history
When VNI configuration is performed using VLAN-VNI mapping (i.e., without
individual VXLAN interfaces) and flooded traffic is handled via multicast,
the multicast group corresponding to the VNI needs to be explicitly read
from the bridge FDB. This is relevant in the case of netlink interface to
the kernel and for the scenario where a new VNI is provisioned or comes up.

Signed-off-by: Vivek Venkatraman <vivek@nvidia.com>

Ticket: #2603831
Reviewed By:
Testing Done:
1. Manual verification - logs in the ticket
2. Precommit (user job FRRouting#171) and evpn-min (user job FRRouting#170)
  • Loading branch information
vivek-cumulus committed Apr 26, 2021
1 parent 7b349d1 commit f68ba58
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 21 deletions.
2 changes: 2 additions & 0 deletions zebra/rt.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ extern void kernel_terminate(struct zebra_ns *zns, bool complete);
extern void macfdb_read(struct zebra_ns *zns);
extern void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
struct interface *br_if, vlanid_t vid);
extern void macfdb_read_mcast_entry_for_vni(struct zebra_ns *zns,
struct interface *ifp, vni_t vni);
extern void macfdb_read_specific_mac(struct zebra_ns *zns,
struct interface *br_if,
struct ethaddr *mac, vlanid_t vid);
Expand Down
78 changes: 57 additions & 21 deletions zebra/rt_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -3255,45 +3255,55 @@ int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
return ret;
}


/* Request for MAC FDB for a specific MAC address in VLAN from the kernel */
static int netlink_request_specific_mac_in_bridge(struct zebra_ns *zns,
int family,
int type,
struct interface *br_if,
struct ethaddr *mac,
vlanid_t vid)
/* Request for MAC FDB for a specific MAC address from the kernel */
static int netlink_request_specific_mac(struct zebra_ns *zns,
int family, int type,
struct interface *ifp,
struct ethaddr *mac,
vlanid_t vid, vni_t vni,
uint8_t flags)
{
struct {
struct nlmsghdr n;
struct ndmsg ndm;
char buf[256];
} req;
struct zebra_if *br_zif;
struct zebra_if *zif;
char buf[ETHER_ADDR_STRLEN];

memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
req.n.nlmsg_type = type; /* RTM_GETNEIGH */
req.n.nlmsg_flags = NLM_F_REQUEST;
req.ndm.ndm_family = family; /* AF_BRIDGE */
req.ndm.ndm_flags = flags;
/* req.ndm.ndm_state = NUD_REACHABLE; */

nl_attr_put(&req.n, sizeof(req), NDA_LLADDR, mac, 6);

br_zif = (struct zebra_if *)br_if->info;
if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0)
nl_attr_put16(&req.n, sizeof(req), NDA_VLAN, vid);
zif = (struct zebra_if *)ifp->info;

/* Is this a read on a VXLAN interface? */
if (IS_ZEBRA_IF_VXLAN(ifp)) {
nl_attr_put32(&req.n, sizeof(req), NDA_VNI, vni);
/* TBD: Why is ifindex not filled in the non-vxlan case? */
req.ndm.ndm_ifindex = ifp->ifindex;
} else {
if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(zif) && vid > 0)
nl_attr_put16(&req.n, sizeof(req), NDA_VLAN, vid);

nl_attr_put32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex);
nl_attr_put32(&req.n, sizeof(req), NDA_MASTER, ifp->ifindex);

}

if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"%s: Tx family %s IF %s(%u) vrf %s(%u) MAC %s vid %u",
__func__, nl_family_to_str(req.ndm.ndm_family),
br_if->name, br_if->ifindex,
vrf_id_to_name(br_if->vrf_id), br_if->vrf_id,
prefix_mac2str(mac, buf, sizeof(buf)), vid);
"Tx %s %s IF %s(%u) MAC %s vid %u vni %u",
nl_msg_type_to_str(type),
nl_family_to_str(req.ndm.ndm_family),
ifp->name, ifp->ifindex,
prefix_mac2str(mac, buf, sizeof(buf)),
vid, vni);

return netlink_request(&zns->netlink_cmd, &req);
}
Expand All @@ -3309,9 +3319,35 @@ int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,

/* Get bridge FDB table for specific bridge - we do the VLAN filtering.
*/
ret = netlink_request_specific_mac_in_bridge(zns, AF_BRIDGE,
RTM_GETNEIGH,
br_if, mac, vid);
ret = netlink_request_specific_mac(zns, AF_BRIDGE, RTM_GETNEIGH,
br_if, mac, vid, 0, 0);
if (ret < 0)
return ret;

ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd,
&dp_info, 1, 0);

return ret;
}

int netlink_macfdb_read_mcast_for_vni(struct zebra_ns *zns,
struct interface *ifp,
vni_t vni)
{
struct zebra_if *zif;
struct ethaddr mac = {.octet = {0}};
struct zebra_dplane_info dp_info;
int ret = 0;

zif = ifp->info;
if (IS_ZEBRA_VXLAN_IF_VNI(zif))
return 0;

zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);

/* Get specific FDB entry for BUM handling, if any */
ret = netlink_request_specific_mac(zns, AF_BRIDGE, RTM_GETNEIGH,
ifp, &mac, 0, vni, NTF_SELF);
if (ret < 0)
return ret;

Expand Down
2 changes: 2 additions & 0 deletions zebra/rt_netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ extern int netlink_macfdb_read(struct zebra_ns *zns);
extern int netlink_macfdb_read_for_bridge(struct zebra_ns *zns,
struct interface *ifp,
struct interface *br_if, vlanid_t vid);
extern int netlink_macfdb_read_mcast_for_vni(struct zebra_ns *zns,
struct interface *ifp, vni_t vni);
extern int netlink_neigh_read(struct zebra_ns *zns);
extern int netlink_neigh_read_for_vlan(struct zebra_ns *zns,
struct interface *vlan_if);
Expand Down
6 changes: 6 additions & 0 deletions zebra/rtread_getmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,12 @@ void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
{
}

void macfdb_read_mcast_entry_for_vni(struct zebra_ns *zns,
struct interface *ifp,
vni_t vni)
{
}

void macfdb_read_specific_mac(struct zebra_ns *zns, struct interface *br_if,
struct ethaddr *mac, vlanid_t vid)
{
Expand Down
7 changes: 7 additions & 0 deletions zebra/rtread_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
netlink_macfdb_read_for_bridge(zns, ifp, br_if, vid);
}

void macfdb_read_mcast_entry_for_vni(struct zebra_ns *zns,
struct interface *ifp,
vni_t vni)
{
netlink_macfdb_read_mcast_for_vni(zns, ifp, vni);
}

void macfdb_read_specific_mac(struct zebra_ns *zns, struct interface *br_if,
struct ethaddr *mac, vlanid_t vid)
{
Expand Down
6 changes: 6 additions & 0 deletions zebra/rtread_sysctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
{
}

void macfdb_read_mcast_entry_for_vni(struct zebra_ns *zns,
struct interface *ifp,
vni_t vni)
{
}

void macfdb_read_specific_mac(struct zebra_ns *zns, struct interface *br_if,
struct ethaddr *mac, vlanid_t vid)
{
Expand Down
4 changes: 4 additions & 0 deletions zebra/zebra_evpn.c
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,10 @@ void zebra_evpn_read_mac_neigh(zebra_evpn_t *zevpn, struct interface *ifp)
zif->brslave_info.bridge_ifindex);

macfdb_read_for_bridge(zns, ifp, zif->brslave_info.br_if, vni->access_vlan);
/* We need to specifically read and retrieve the entry for BUM handling
* via multicast, if any.
*/
macfdb_read_mcast_entry_for_vni(zns, ifp, zevpn->vni);
vlan_if = zvni_map_to_svi(vni->access_vlan, zif->brslave_info.br_if);
if (vlan_if) {
/* Add SVI MAC */
Expand Down

0 comments on commit f68ba58

Please sign in to comment.