]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: RFC compliance wrt invalid RMAC, GWIP, ESI and VNI
authorKishore Aramalla <karamalla@vmware.com>
Mon, 10 Feb 2020 19:38:27 +0000 (11:38 -0800)
committerKishore Aramalla <karamalla@vmware.com>
Tue, 11 Feb 2020 20:36:50 +0000 (12:36 -0800)
A route where ESI, GW IP, MAC and Label are all zero at the same time SHOULD
be treat-as-withdraw.
Invalid MAC addresses are broadcast or multicast MAC addresses. The route
MUST be treat-as-withdraw in case of an invalid MAC address.

As FRR support Ethernet NVO Tunnels only.
Route will be withdrawn when ESI, GW IP and MAC are zero or Invalid MAC

Test cases:
1) ET-5 route with valid RMAC extended community
2) ET-5 route no RMAC extended community
3) ET-5 route with Multicast MAC in RMAC extended community
4) ET-5 route with Broadcast MAC in RMAC extended community

Signed-off-by: Kishore Aramalla <karamalla@vmware.com>
bgpd/bgp_attr_evpn.c
bgpd/bgp_attr_evpn.h
bgpd/bgp_evpn.c
lib/prefix.c
lib/prefix.h

index 15fa32215972c819cd6d31b0d07fa861cf3fbf5c..ec9656a98da57632f6b819cfd1bfd629041b73af 100644 (file)
@@ -281,3 +281,25 @@ extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
                return -1;
        return 0;
 }
+
+extern bool is_zero_gw_ip(const union gw_addr *gw_ip, const afi_t afi)
+{
+       if (afi == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(&gw_ip->ipv6))
+               return true;
+
+       if (afi == AF_INET && gw_ip->ipv4.s_addr == INADDR_ANY)
+               return true;
+
+       return false;
+}
+
+extern bool is_zero_esi(const struct eth_segment_id *esi)
+{
+       int i;
+
+       for (i = 0; i < ESI_LEN; i++)
+               if (esi->val[i])
+                       return false;
+
+       return true;
+}
index 5b0ce1da2886ec290a752f1d87de634ba7682f92..a8a35e8174f64978da36c47540158a8c0248b871 100644 (file)
@@ -67,4 +67,7 @@ extern uint8_t bgp_attr_default_gw(struct attr *attr);
 
 extern void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag);
 
+extern bool is_zero_gw_ip(const union gw_addr *gw_ip, afi_t afi);
+
+extern bool is_zero_esi(const struct eth_segment_id *esi);
 #endif /* _QUAGGA_BGP_ATTR_EVPN_H */
index 76c7d93ad175b120afae4acb8d74cfcbdb720dbf..206680c403fba25d82af8ba5d2446e1ff7a83156 100644 (file)
@@ -4192,6 +4192,8 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
        uint32_t eth_tag;
        mpls_label_t label; /* holds the VNI as in the packet */
        int ret;
+       afi_t gw_afi;
+       bool is_valid_update = false;
 
        /* Type-5 route should be 34 or 58 bytes:
         * RD (8), ESI (10), Eth Tag (4), IP len (1), IP (4 or 16),
@@ -4250,12 +4252,14 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
                pfx += 4;
                memcpy(&evpn.gw_ip.ipv4, pfx, 4);
                pfx += 4;
+               gw_afi = AF_INET;
        } else {
                SET_IPADDR_V6(&p.prefix.prefix_addr.ip);
                memcpy(&p.prefix.prefix_addr.ip.ipaddr_v6, pfx, 16);
                pfx += 16;
                memcpy(&evpn.gw_ip.ipv6, pfx, 16);
                pfx += 16;
+               gw_afi = AF_INET6;
        }
 
        /* Get the VNI (in MPLS label field). Stored as bytes here. */
@@ -4268,8 +4272,18 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
         * field
         */
 
+       if (attr) {
+               is_valid_update = true;
+               if (is_zero_mac(&attr->rmac) && is_zero_esi(&evpn.eth_s_id) &&
+                   is_zero_gw_ip(&evpn.gw_ip, gw_afi))
+                       is_valid_update = false;
+
+               if (is_mcast_mac(&attr->rmac) || is_bcast_mac(&attr->rmac))
+                       is_valid_update = false;
+       }
+
        /* Process the route. */
-       if (attr)
+       if (is_valid_update)
                ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
                                 afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
                                 &prd, &label, 1, 0, &evpn);
index 199ff3267bce011aa2cbb96876685846b9f8075a..030ffe3471c3d7ec4d1b564b3ad3147020432708 100644 (file)
@@ -56,6 +56,25 @@ int is_zero_mac(const struct ethaddr *mac)
        return 1;
 }
 
+bool is_bcast_mac(const struct ethaddr *mac)
+{
+       int i = 0;
+
+       for (i = 0; i < ETH_ALEN; i++)
+               if (mac->octet[i] != 0xFF)
+                       return false;
+
+       return true;
+}
+
+bool is_mcast_mac(const struct ethaddr *mac)
+{
+       if ((mac->octet[0] & 0x01) == 0x01)
+               return true;
+
+       return false;
+}
+
 unsigned int prefix_bit(const uint8_t *prefix, const uint16_t prefixlen)
 {
        unsigned int offset = prefixlen / 8;
index fb80c4ca6cab9430f7bc3ceeb6b00ce49a1a5a91..b01f7d1fdc96c4ed4df410615228dddcd454fbad 100644 (file)
@@ -470,6 +470,8 @@ extern void masklen2ip6(const int, struct in6_addr *);
 extern const char *inet6_ntoa(struct in6_addr);
 
 extern int is_zero_mac(const struct ethaddr *mac);
+extern bool is_mcast_mac(const struct ethaddr *mac);
+extern bool is_bcast_mac(const struct ethaddr *mac);
 extern int prefix_str2mac(const char *str, struct ethaddr *mac);
 extern char *prefix_mac2str(const struct ethaddr *mac, char *buf, int size);