Mailing List Archive

[PATCH 42/57] bgpd: build EVPN RT2 message for MP_REACH_NLRI
From: Julien Courtat <julien.courtat@6wind.com>

Send and receive RT2 message only.

Signed-off-by: Julien Courtat <julien.courtat@6wind.com>
---
bgpd/bgp_attr.c | 58 +++++++++++++++++++++++++++++++++++++++++++-
bgpd/bgp_evpn.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 128 insertions(+), 4 deletions(-)

diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index f53fb14c759d..2b57d687800c 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -2572,6 +2572,59 @@ bgp_packet_mpattr_route_type_5 (struct stream *s,
return;
}

+static void
+bgp_packet_mpattr_route_type_2 (struct stream *s,
+ struct prefix *p, struct prefix_rd *prd,
+ uint32_t *labels, size_t nlabels, struct attr *attr)
+{
+ int len;
+ uint8_t ip_len;
+ char temp[16];
+
+ ip_len = p->u.prefix_macip.ip_len;
+ memset(&temp, 0, 16);
+
+ if(ip_len == 32)
+ len = 4; /* ipv4 */
+ else if (ip_len == 128)
+ len = 16; /* ipv6 */
+ else
+ len = 0; /* No Ip address in prefix */
+ stream_putc (s, EVPN_MACIP_ADVERTISEMENT);
+ stream_putc (s, 8 /* RD */ + 10 /* ESI */ + 4 /* EthTag */ + 1 /* MAC len */
+ + 6 /* MAC */ + 1 + len + 3 /* label 1 */ + 3 /* label 2*/ + 1 /* len from TLV */);
+ /* route distinguisher */
+ stream_put (s, prd->val, 8);
+
+ /* Ethernet Segment Identifier */
+ if(attr && attr->extra)
+ stream_put (s, &(attr->extra->evpn_overlay.eth_s_id), 10);
+ else
+ stream_put (s, &temp, 10);
+
+ /* Ethernet Tag Id (VNI), MSB must be null */
+ stream_putl (s, p->u.prefix_macip.eth_tag_id);
+
+ /* MAC address lenght in bits */
+ stream_putc (s, ETHER_ADDR_LEN * 8);
+
+ /* MAC address */
+ stream_put(s, &p->u.prefix_macip.mac, ETHER_ADDR_LEN);
+
+ /* IP address lenght in bits */
+ stream_putc (s, ip_len);
+
+ /* IP address */
+ if (ip_len == 32)
+ stream_put_ipv4 (s, p->u.prefix_macip.ip.in4.s_addr);
+ else if (ip_len == 128)
+ stream_put (s, &p->u.prefix_macip.ip.in6, 16);
+
+ /* labels */
+ for (size_t i = 0; i < nlabels; i++)
+ stream_put3 (s, labels[i]);
+}
+
void
bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
struct prefix *p, struct prefix_rd *prd,
@@ -2598,7 +2651,10 @@ bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
}
else if ((safi == SAFI_INTERNAL_EVPN))
{
- bgp_packet_mpattr_route_type_5(s, p, prd, labels, nlabels, attr);
+ if (p->family == AF_L2VPN)
+ bgp_packet_mpattr_route_type_2(s, p, prd, labels, nlabels, attr);
+ else
+ bgp_packet_mpattr_route_type_5(s, p, prd, labels, nlabels, attr);
}
else
stream_put_prefix (s, p);
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 7828caa02fea..8c402bec3c2f 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -39,7 +39,7 @@ int
bgp_nlri_parse_evpn (struct peer *peer, struct attr *attr,
struct bgp_nlri *packet)
{
- u_char *pnt;
+ u_char *pnt,*pnt2;
u_char *lim;
struct prefix p;
struct prefix_rd prd;
@@ -71,9 +71,10 @@ bgp_nlri_parse_evpn (struct peer *peer, struct attr *attr,

/* Fetch Route Type */
route_type = *pnt++;
+ pnt2 = pnt;
route_length = *pnt++;
/* simply ignore. goto next route type if any */
- if(route_type != EVPN_IP_PREFIX)
+ if(route_type != EVPN_IP_PREFIX && route_type != EVPN_MACIP_ADVERTISEMENT)
{
if (pnt + route_length > lim)
{
@@ -110,8 +111,53 @@ bgp_nlri_parse_evpn (struct peer *peer, struct attr *attr,
zlog_err ("not enough bytes for Eth Tag left in NLRI?");
return -1;
}
+ if (route_type == EVPN_MACIP_ADVERTISEMENT)
+ {
+ memcpy(&p.u.prefix_macip.eth_tag_id, pnt, 4);
+ p.u.prefix_macip.eth_tag_id = ntohl(p.u.prefix_macip.eth_tag_id);
+ pnt += 4;
+
+ /* MAC address len in bits */
+ p.family = AF_L2VPN;
+ p.u.prefix_macip.mac_len = *pnt++;
+
+ if (p.u.prefix_macip.mac_len != 8*ETHER_ADDR_LEN)
+ {
+ zlog_err ("invalid mac length %d in RT2 NLRI, should be 48",
+ p.u.prefix_macip.mac_len);
+ return -1;
+ }
+
+ /* MAC address */
+ memcpy(&p.u.prefix_macip.mac, pnt, ETHER_ADDR_LEN);
+ pnt += ETHER_ADDR_LEN;

- if (route_type == EVPN_IP_PREFIX)
+ /* IP Address lenght in bits */
+ p.u.prefix_macip.ip_len = *pnt++;
+ if (p.u.prefix_macip.ip_len == IPV4_MAX_PREFIXLEN)
+ {
+ p.prefixlen = L2VPN_IPV4_PREFIX_LEN;
+ memcpy (&p.u.prefix_macip.ip.in4, pnt, 4);
+ pnt += 4;
+ p.prefixlen = L2VPN_MAX_PREFIXLEN - IPV6_MAX_PREFIXLEN + IPV4_MAX_PREFIXLEN;
+ }
+ else if (p.u.prefix_macip.ip_len == IPV6_MAX_PREFIXLEN)
+ {
+ p.prefixlen = L2VPN_IPV6_PREFIX_LEN;
+ memcpy (&p.u.prefix_macip.ip.in6, pnt, 16);
+ pnt += 16;
+ p.prefixlen = L2VPN_MAX_PREFIXLEN;
+ }
+ else if (p.u.prefix_macip.ip_len == 0)
+ p.prefixlen = L2VPN_MAX_PREFIXLEN - IPV6_MAX_PREFIXLEN + IPV4_MAX_PREFIXLEN;
+ else
+ {
+ zlog_err ("invalid IP length %d in RT2 NLRI, should be 0, 32 or 128",
+ p.u.prefix_macip.ip_len);
+ return -1;
+ }
+ }
+ else if (route_type == EVPN_IP_PREFIX)
{
memcpy(&evpn.eth_t_id, pnt, 4);
evpn.eth_t_id = ntohl(evpn.eth_t_id);
@@ -155,6 +201,28 @@ bgp_nlri_parse_evpn (struct peer *peer, struct attr *attr,

pnt += 3;

+ if (route_type == EVPN_MACIP_ADVERTISEMENT)
+ {
+ if (pnt + 3 > lim)
+ {
+ zlog_err ("not enough bytes for Label left in NLRI?");
+ return -1;
+ }
+ labels[1] = (pnt[0] << 16) + (pnt[1] << 8) + pnt[2];
+ nlabels = 2;
+
+ pnt += 3;
+
+ if((pnt - route_length != pnt2))
+ {
+ plog_err (peer->log,
+ "%s [Error] Update packet error / EVPN?"
+ " (NLRI length mismatch %d observed %d)",
+ peer->host, route_length, pnt - pnt2);
+ return -1;
+ }
+ }
+
if (attr)
{
bgp_update (peer, &p, attr, AFI_INTERNAL_L2VPN, SAFI_INTERNAL_EVPN,
--
2.1.4


_______________________________________________
Quagga-dev mailing list
Quagga-dev@lists.quagga.net
https://lists.quagga.net/mailman/listinfo/quagga-dev