mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-12-29 19:51:04 +00:00
Merge pull request #3508 from chiragshah6/evpn_dev2
zebra: EVPN remote entry delete check local entry presence
This commit is contained in:
commit
262d4dda2a
@ -731,6 +731,7 @@ static int netlink_request_intf_addr(struct nlsock *netlink_cmd, int family,
|
||||
/* Form the request, specifying filter (rtattr) if needed. */
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.n.nlmsg_type = type;
|
||||
req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
|
||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||
req.ifm.ifi_family = family;
|
||||
|
||||
|
||||
@ -1032,7 +1032,6 @@ int netlink_request(struct nlsock *nl, struct nlmsghdr *n)
|
||||
}
|
||||
|
||||
/* Fill common fields for all requests. */
|
||||
n->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
|
||||
n->nlmsg_pid = nl->snl.nl_pid;
|
||||
n->nlmsg_seq = ++nl->seq;
|
||||
|
||||
|
||||
@ -78,8 +78,13 @@ 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);
|
||||
extern void macfdb_read_specific_mac(struct zebra_ns *zns,
|
||||
struct interface *br_if,
|
||||
struct ethaddr *mac, vlanid_t vid);
|
||||
extern void neigh_read(struct zebra_ns *zns);
|
||||
extern void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *ifp);
|
||||
extern void neigh_read_specific_ip(struct ipaddr *ip,
|
||||
struct interface *vlan_if);
|
||||
extern void route_read(struct zebra_ns *zns);
|
||||
|
||||
#endif /* _ZEBRA_RT_H */
|
||||
|
||||
@ -879,6 +879,7 @@ static int netlink_request_route(struct zebra_ns *zns, int family, int type)
|
||||
/* Form the request, specifying filter (rtattr) if needed. */
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.n.nlmsg_type = type;
|
||||
req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
|
||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
|
||||
req.rtm.rtm_family = family;
|
||||
|
||||
@ -2127,6 +2128,7 @@ static int netlink_request_macs(struct nlsock *netlink_cmd, int family,
|
||||
/* Form the request, specifying filter (rtattr) if needed. */
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.n.nlmsg_type = type;
|
||||
req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
|
||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||
req.ifm.ifi_family = family;
|
||||
if (master_ifindex)
|
||||
@ -2195,6 +2197,70 @@ 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)
|
||||
{
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct ndmsg ndm;
|
||||
char buf[256];
|
||||
} req;
|
||||
struct zebra_if *br_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_state = NUD_REACHABLE; */
|
||||
|
||||
addattr_l(&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)
|
||||
addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
|
||||
|
||||
addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex);
|
||||
|
||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||
zlog_debug("%s: Tx family %s IF %s(%u) MAC %s vid %u",
|
||||
__PRETTY_FUNCTION__,
|
||||
nl_family_to_str(req.ndm.ndm_family), br_if->name,
|
||||
br_if->ifindex,
|
||||
prefix_mac2str(mac, buf, sizeof(buf)), vid);
|
||||
|
||||
return netlink_request(&zns->netlink_cmd, &req.n);
|
||||
}
|
||||
|
||||
int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,
|
||||
struct interface *br_if,
|
||||
struct ethaddr *mac, vlanid_t vid)
|
||||
{
|
||||
int ret = 0;
|
||||
struct zebra_dplane_info dp_info;
|
||||
|
||||
zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
|
||||
|
||||
/* 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);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd,
|
||||
&dp_info, 1, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
|
||||
struct ethaddr *mac, struct in_addr vtep_ip,
|
||||
int cmd, bool sticky)
|
||||
@ -2454,6 +2520,7 @@ static int netlink_request_neigh(struct nlsock *netlink_cmd, int family,
|
||||
/* Form the request, specifying filter (rtattr) if needed. */
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.n.nlmsg_type = type;
|
||||
req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
|
||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
|
||||
req.ndm.ndm_family = family;
|
||||
if (ifindex)
|
||||
@ -2505,6 +2572,73 @@ int netlink_neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Request for a specific IP in VLAN (SVI) device from IP Neighbor table,
|
||||
* read using netlink interface.
|
||||
*/
|
||||
static int netlink_request_specific_neigh_in_vlan(struct zebra_ns *zns,
|
||||
int type, struct ipaddr *ip,
|
||||
ifindex_t ifindex)
|
||||
{
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct ndmsg ndm;
|
||||
char buf[256];
|
||||
} req;
|
||||
int ipa_len;
|
||||
|
||||
/* Form the request, specifying filter (rtattr) if needed. */
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
|
||||
req.n.nlmsg_flags = NLM_F_REQUEST;
|
||||
req.n.nlmsg_type = type; /* RTM_GETNEIGH */
|
||||
req.ndm.ndm_ifindex = ifindex;
|
||||
|
||||
if (IS_IPADDR_V4(ip)) {
|
||||
ipa_len = IPV4_MAX_BYTELEN;
|
||||
req.ndm.ndm_family = AF_INET;
|
||||
|
||||
} else {
|
||||
ipa_len = IPV6_MAX_BYTELEN;
|
||||
req.ndm.ndm_family = AF_INET6;
|
||||
}
|
||||
|
||||
addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
|
||||
|
||||
return netlink_request(&zns->netlink_cmd, &req.n);
|
||||
}
|
||||
|
||||
int netlink_neigh_read_specific_ip(struct ipaddr *ip,
|
||||
struct interface *vlan_if)
|
||||
{
|
||||
int ret = 0;
|
||||
struct zebra_ns *zns;
|
||||
struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(vlan_if->vrf_id);
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
struct zebra_dplane_info dp_info;
|
||||
|
||||
zns = zvrf->zns;
|
||||
|
||||
zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
|
||||
|
||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||
zlog_debug("%s: neigh request IF %s(%u) IP %s vrf_id %u",
|
||||
__PRETTY_FUNCTION__, vlan_if->name,
|
||||
vlan_if->ifindex,
|
||||
ipaddr2str(ip, buf, sizeof(buf)),
|
||||
vlan_if->vrf_id);
|
||||
|
||||
ret = netlink_request_specific_neigh_in_vlan(zns, RTM_GETNEIGH, ip,
|
||||
vlan_if->ifindex);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd,
|
||||
&dp_info, 1, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id)
|
||||
{
|
||||
int len;
|
||||
|
||||
@ -73,6 +73,11 @@ extern int netlink_macfdb_read_for_bridge(struct zebra_ns *zns,
|
||||
extern int netlink_neigh_read(struct zebra_ns *zns);
|
||||
extern int netlink_neigh_read_for_vlan(struct zebra_ns *zns,
|
||||
struct interface *vlan_if);
|
||||
extern int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,
|
||||
struct interface *br_if,
|
||||
struct ethaddr *mac, uint16_t vid);
|
||||
extern int netlink_neigh_read_specific_ip(struct ipaddr *ip,
|
||||
struct interface *vlan_if);
|
||||
|
||||
#endif /* HAVE_NETLINK */
|
||||
|
||||
|
||||
@ -261,6 +261,11 @@ void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
|
||||
{
|
||||
}
|
||||
|
||||
void macfdb_read_specific_mac(struct zebra_ns *zns, struct interface *br_if,
|
||||
struct ethaddr *mac, vlanid_t vid)
|
||||
{
|
||||
}
|
||||
|
||||
void neigh_read(struct zebra_ns *zns)
|
||||
{
|
||||
}
|
||||
@ -269,6 +274,10 @@ void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
|
||||
{
|
||||
}
|
||||
|
||||
void neigh_read_specific_ip(struct ipaddr *ip, struct interface *vlan_if)
|
||||
{
|
||||
}
|
||||
|
||||
void kernel_read_pbr_rules(struct zebra_ns *zns)
|
||||
{
|
||||
}
|
||||
|
||||
@ -45,6 +45,12 @@ void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
|
||||
netlink_macfdb_read_for_bridge(zns, ifp, br_if);
|
||||
}
|
||||
|
||||
void macfdb_read_specific_mac(struct zebra_ns *zns, struct interface *br_if,
|
||||
struct ethaddr *mac, vlanid_t vid)
|
||||
{
|
||||
netlink_macfdb_read_specific_mac(zns, br_if, mac, vid);
|
||||
}
|
||||
|
||||
void neigh_read(struct zebra_ns *zns)
|
||||
{
|
||||
netlink_neigh_read(zns);
|
||||
@ -55,6 +61,11 @@ void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
|
||||
netlink_neigh_read_for_vlan(zns, vlan_if);
|
||||
}
|
||||
|
||||
void neigh_read_specific_ip(struct ipaddr *ip, struct interface *vlan_if)
|
||||
{
|
||||
netlink_neigh_read_specific_ip(ip, vlan_if);
|
||||
}
|
||||
|
||||
void kernel_read_pbr_rules(struct zebra_ns *zns)
|
||||
{
|
||||
netlink_rules_read(zns);
|
||||
|
||||
@ -88,6 +88,11 @@ void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
|
||||
{
|
||||
}
|
||||
|
||||
void macfdb_read_specific_mac(struct zebra_ns *zns, struct interface *br_if,
|
||||
struct ethaddr *mac, vlanid_t vid)
|
||||
{
|
||||
}
|
||||
|
||||
void neigh_read(struct zebra_ns *zns)
|
||||
{
|
||||
}
|
||||
@ -96,6 +101,10 @@ void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
|
||||
{
|
||||
}
|
||||
|
||||
void neigh_read_specific_ip(struct ipaddr *ip, struct interface *vlan_if)
|
||||
{
|
||||
}
|
||||
|
||||
void kernel_read_pbr_rules(struct zebra_ns *zns)
|
||||
{
|
||||
}
|
||||
|
||||
@ -5337,6 +5337,9 @@ static void process_remote_macip_del(vni_t vni,
|
||||
zebra_neigh_t *n = NULL;
|
||||
struct interface *ifp = NULL;
|
||||
struct zebra_if *zif = NULL;
|
||||
struct zebra_ns *zns;
|
||||
struct zebra_l2info_vxlan *vxl;
|
||||
struct zebra_vrf *zvrf;
|
||||
char buf[ETHER_ADDR_STRLEN];
|
||||
char buf1[INET6_ADDRSTRLEN];
|
||||
|
||||
@ -5360,6 +5363,8 @@ static void process_remote_macip_del(vni_t vni,
|
||||
vni);
|
||||
return;
|
||||
}
|
||||
zns = zebra_ns_lookup(NS_DEFAULT);
|
||||
vxl = &zif->l2info.vxl;
|
||||
|
||||
/* The remote VTEP specified is normally expected to exist, but
|
||||
* it is possible that the peer may delete the VTEP before deleting
|
||||
@ -5386,9 +5391,10 @@ static void process_remote_macip_del(vni_t vni,
|
||||
if (!mac && !n)
|
||||
return;
|
||||
|
||||
zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
|
||||
|
||||
/* Ignore the delete if this mac is a gateway mac-ip */
|
||||
if (mac
|
||||
&& CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
|
||||
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
|
||||
&& CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) {
|
||||
zlog_warn(
|
||||
"Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
|
||||
@ -5402,6 +5408,23 @@ static void process_remote_macip_del(vni_t vni,
|
||||
|
||||
/* Uninstall remote neighbor or MAC. */
|
||||
if (n) {
|
||||
if (zvrf->dad_freeze &&
|
||||
CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE) &&
|
||||
CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) &&
|
||||
(memcmp(n->emac.octet, macaddr->octet, ETH_ALEN) == 0)) {
|
||||
struct interface *vlan_if;
|
||||
|
||||
vlan_if = zvni_map_to_svi(vxl->access_vlan,
|
||||
zif->brslave_info.br_if);
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
|
||||
__PRETTY_FUNCTION__,
|
||||
ipaddr2str(ipaddr, buf1,
|
||||
sizeof(buf1)), n->flags,
|
||||
vlan_if->name);
|
||||
neigh_read_specific_ip(ipaddr, vlan_if);
|
||||
}
|
||||
|
||||
/* When the MAC changes for an IP, it is possible the
|
||||
* client may update the new MAC before trying to delete the
|
||||
* "old" neighbor (as these are two different MACIP routes).
|
||||
@ -5414,6 +5437,25 @@ static void process_remote_macip_del(vni_t vni,
|
||||
zvni_deref_ip2mac(zvni, mac);
|
||||
}
|
||||
} else {
|
||||
/* DAD: when MAC is freeze state as remote learn event,
|
||||
* remote mac-ip delete event is received will result in freeze
|
||||
* entry removal, first fetch kernel for the same entry present
|
||||
* as LOCAL and reachable, avoid deleting this entry instead
|
||||
* use kerenel local entry to update during unfreeze time.
|
||||
*/
|
||||
if (zvrf->dad_freeze &&
|
||||
CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) &&
|
||||
CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
|
||||
__PRETTY_FUNCTION__,
|
||||
prefix_mac2str(macaddr, buf,
|
||||
sizeof(buf)),
|
||||
mac->flags);
|
||||
macfdb_read_specific_mac(zns, zif->brslave_info.br_if,
|
||||
macaddr, vxl->access_vlan);
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
|
||||
zvni_process_neigh_on_remote_mac_del(zvni, mac);
|
||||
/*
|
||||
|
||||
Loading…
Reference in New Issue
Block a user