summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKishore Aramalla <karamalla@vmware.com>2020-02-10 11:38:27 -0800
committerKishore Aramalla <karamalla@vmware.com>2020-02-11 12:36:50 -0800
commitc6ec0c745a77024c0b5690127ebd961493daed3d (patch)
tree3861a7eb9a4902b7b4551d6b7f526dafe323578a
parentf94ed830df98218447f00b97f856de811bfcc4a2 (diff)
bgpd: RFC compliance wrt invalid RMAC, GWIP, ESI and VNI
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>
-rw-r--r--bgpd/bgp_attr_evpn.c22
-rw-r--r--bgpd/bgp_attr_evpn.h3
-rw-r--r--bgpd/bgp_evpn.c16
-rw-r--r--lib/prefix.c19
-rw-r--r--lib/prefix.h2
5 files changed, 61 insertions, 1 deletions
diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c
index 15fa322159..ec9656a98d 100644
--- a/bgpd/bgp_attr_evpn.c
+++ b/bgpd/bgp_attr_evpn.c
@@ -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;
+}
diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h
index 5b0ce1da28..a8a35e8174 100644
--- a/bgpd/bgp_attr_evpn.h
+++ b/bgpd/bgp_attr_evpn.h
@@ -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 */
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 76c7d93ad1..206680c403 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -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);
diff --git a/lib/prefix.c b/lib/prefix.c
index 199ff3267b..030ffe3471 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -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;
diff --git a/lib/prefix.h b/lib/prefix.h
index fb80c4ca6c..b01f7d1fdc 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -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);