Mailing List Archive

[PATCH 26/57] bgpd: handling EVPN Route Type 5 NLRI message
This patch introduces code to receive a NLRI message with route type
5, as defined in draft-ietf-bess-evpn-prefix-advertisement-02. It
It increases the number of parameters to extract from the NLRI and
to store into bgp extra information structure. Those parameters are
the ESI (ethernet segment identifier), the gateway IP Address (which
acts like nexthop attribute but is contained inside the NLRI itself)
and the ethernet tag identifier ( that acts for the VXLan Identifier)

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
---
bgpd/Makefile.am | 4 +-
bgpd/bgp_attr_evpn.c | 1 +
bgpd/bgp_attr_evpn.h | 7 ++
bgpd/bgp_encap.c | 4 +-
bgpd/bgp_evpn.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++
bgpd/bgp_evpn.h | 36 +++++++++++
bgpd/bgp_mplsvpn.c | 4 +-
bgpd/bgp_packet.c | 4 ++
bgpd/bgp_route.c | 26 +++++---
bgpd/bgp_route.h | 11 +++-
bgpd/bgpd.c | 1 +
11 files changed, 257 insertions(+), 18 deletions(-)
create mode 100644 bgpd/bgp_evpn.c
create mode 100644 bgpd/bgp_evpn.h

diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am
index a2ebe2dcd8cc..da1146c69880 100644
--- a/bgpd/Makefile.am
+++ b/bgpd/Makefile.am
@@ -16,7 +16,7 @@ libbgp_a_SOURCES = \
bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \
bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_mplsvpn.c bgp_nexthop.c \
bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \
- bgp_encap.c bgp_encap_tlv.c bgp_nht.c bgp_attr_evpn.c
+ bgp_encap.c bgp_encap_tlv.c bgp_nht.c bgp_attr_evpn.c bgp_evpn.c

noinst_HEADERS = \
bgp_aspath.h bgp_attr.h bgp_community.h bgp_debug.h bgp_fsm.h \
@@ -25,7 +25,7 @@ noinst_HEADERS = \
bgp_ecommunity.h bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \
bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h \
bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h bgp_nht.h \
- bgp_attr_evpn.h
+ bgp_attr_evpn.h bgp_evpn.h

bgpd_SOURCES = bgp_main.c
bgpd_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@
diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c
index 9a092a11ff21..66751342ec7b 100644
--- a/bgpd/bgp_attr_evpn.c
+++ b/bgpd/bgp_attr_evpn.c
@@ -21,6 +21,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include <zebra.h>

#include "command.h"
+#include "filter.h"
#include "prefix.h"
#include "log.h"
#include "memory.h"
diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h
index 1f5e579a0f00..d50a6f66758a 100644
--- a/bgpd/bgp_attr_evpn.h
+++ b/bgpd/bgp_attr_evpn.h
@@ -48,6 +48,13 @@ union gw_addr {
#endif /* HAVE_IPV6 */
};

+struct bgp_route_evpn
+{
+ uint32_t eth_t_id;
+ struct eth_segment_id eth_s_id;
+ union gw_addr gw_ip;
+};
+
extern int str2esi (const char *str, struct eth_segment_id *id);
extern int str2mac (const char *str, char *mac);
extern char *esi2str (struct eth_segment_id *id);
diff --git a/bgpd/bgp_encap.c b/bgpd/bgp_encap.c
index 2cf55131c9d5..48817e05da88 100644
--- a/bgpd/bgp_encap.c
+++ b/bgpd/bgp_encap.c
@@ -183,10 +183,10 @@ bgp_nlri_parse_encap(

if (attr) {
bgp_update (peer, &p, attr, afi, SAFI_ENCAP,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0, 0);
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0, 0, NULL);
} else {
bgp_withdraw (peer, &p, attr, afi, SAFI_ENCAP,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0);
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0, NULL);
}
}

diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
new file mode 100644
index 000000000000..1d537fa7eab8
--- /dev/null
+++ b/bgpd/bgp_evpn.c
@@ -0,0 +1,177 @@
+/* Ethernet-VPN Packet and vty Processing File
+ Copyright (C) 2016 6WIND
+
+This file is part of GNU Quagga
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING. If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "filter.h"
+#include "prefix.h"
+#include "log.h"
+#include "memory.h"
+#include "stream.h"
+
+#include "bgpd/bgp_attr_evpn.h"
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_table.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_evpn.h"
+
+int
+bgp_nlri_parse_evpn (struct peer *peer, struct attr *attr,
+ struct bgp_nlri *packet)
+{
+ u_char *pnt;
+ u_char *lim;
+ struct prefix p;
+ struct prefix_rd prd;
+ struct bgp_route_evpn evpn;
+ uint8_t route_type, route_length;
+ uint32_t labels[BGP_MAX_LABELS];
+ size_t nlabels;
+
+ /* Check peer status. */
+ if (peer->status != Established)
+ return 0;
+
+ /* Make prefix_rd */
+ prd.family = AF_UNSPEC;
+ prd.prefixlen = 64;
+
+ pnt = packet->nlri;
+ lim = pnt + packet->length;
+ while (pnt < lim)
+ {
+ /* clear evpn structure */
+ memset (&evpn, 0, sizeof (evpn));
+
+ /* Clear prefix structure. */
+ memset (&p, 0, sizeof (struct prefix));
+ memset(&evpn.gw_ip, 0, sizeof(union gw_addr));
+ evpn.eth_t_id = 0;
+ memset(&evpn.eth_s_id, 0, sizeof(struct eth_segment_id));
+
+ /* Fetch Route Type */
+ route_type = *pnt++;
+ route_length = *pnt++;
+ /* simply ignore. goto next route type if any */
+ if(route_type != EVPN_IP_PREFIX)
+ {
+ if (pnt + route_length > lim)
+ {
+ zlog_err ("not enough bytes for New Route Type left in NLRI?");
+ return -1;
+ }
+ pnt += route_length;
+ continue;
+ }
+
+ /* Fetch RD */
+ if (pnt + 8 > lim)
+ {
+ zlog_err ("not enough bytes for RD left in NLRI?");
+ return -1;
+ }
+
+ /* Copy routing distinguisher to rd. */
+ memcpy (&prd.val, pnt, 8);
+ pnt += 8;
+
+ /* Fetch ESI */
+ if (pnt + 10 > lim)
+ {
+ zlog_err ("not enough bytes for ESI left in NLRI?");
+ return -1;
+ }
+ memcpy(&evpn.eth_s_id.val, pnt, 10);
+ pnt += 10;
+
+ /* Fetch Ethernet Tag */
+ if (pnt + 4 > lim)
+ {
+ zlog_err ("not enough bytes for Eth Tag left in NLRI?");
+ return -1;
+ }
+
+ if (route_type == EVPN_IP_PREFIX)
+ {
+ memcpy(&evpn.eth_t_id, pnt, 4);
+ evpn.eth_t_id = ntohl(evpn.eth_t_id);
+ pnt += 4;
+
+ /* Fetch prefix length. */
+ p.prefixlen = *pnt++;
+
+ if (p.prefixlen > 128)
+ {
+ zlog_err ("invalid prefixlen %d in EVPN NLRI?", p.prefixlen);
+ return -1;
+ }
+ /* determine IPv4 or IPv6 prefix */
+ if(route_length - 4 - 10 - 8 - 3 /* label to be read */ >= 32)
+ {
+ p.family = AF_INET6;
+ memcpy (&p.u.prefix, pnt, 16);
+ pnt += 16;
+ memcpy(&evpn.gw_ip.ipv6, pnt, 16);
+ pnt += 16;
+ }
+ else
+ {
+ p.family = AF_INET;
+ memcpy (&p.u.prefix, pnt, 4);
+ pnt += 4;
+ memcpy(&evpn.gw_ip.ipv4, pnt, 4);
+ pnt += 4;
+ }
+ }
+
+ /* Fetch Label */
+ if (pnt + 3 > lim)
+ {
+ zlog_err ("not enough bytes for Label left in NLRI?");
+ return -1;
+ }
+ labels[0] = (pnt[0] << 16) + (pnt[1] << 8) + pnt[2];
+ nlabels = 1;
+
+ pnt += 3;
+
+ if (attr)
+ {
+ bgp_update (peer, &p, attr, AFI_INTERNAL_L2VPN, SAFI_INTERNAL_EVPN,
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
+ labels, nlabels, 0, &evpn);
+ }
+ else
+ {
+ bgp_withdraw (peer, &p, attr, AFI_INTERNAL_L2VPN, SAFI_INTERNAL_EVPN,
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
+ &prd, labels, nlabels, &evpn);
+ }
+ }
+
+ /* Packet length consistency check. */
+ if (pnt != lim)
+ return -1;
+
+ return 0;
+}
diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h
new file mode 100644
index 000000000000..a3c4f3498004
--- /dev/null
+++ b/bgpd/bgp_evpn.h
@@ -0,0 +1,36 @@
+/* E-VPN header for packet handling
+ Copyright (C) 2016 6WIND
+
+This file is part of GNU Quagga.
+
+GNU Quagga is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Quagga is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Quagga; see the file COPYING. If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#ifndef _QUAGGA_BGP_EVPN_H
+#define _QUAGGA_BGP_EVPN_H
+
+extern int bgp_nlri_parse_evpn (struct peer *peer, struct attr *attr,
+ struct bgp_nlri *packet);
+
+/* EVPN route types as per RFC7432 and
+ * as per draft-ietf-bess-evpn-prefix-advertisement-02
+ */
+#define EVPN_ETHERNET_AUTO_DISCOVERY 1
+#define EVPN_MACIP_ADVERTISEMENT 2
+#define EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG 3
+#define EVPN_ETHERNET_SEGMENT 4
+#define EVPN_IP_PREFIX 5
+
+#endif /* _QUAGGA_BGP_EVPN_H */
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 8f7b8921283b..09a20a1c18b7 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -238,10 +238,10 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,

if (attr)
bgp_update (peer, &p, attr, packet->afi, SAFI_MPLS_VPN,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, labels, nlabels, 0);
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, labels, nlabels, 0, NULL);
else
bgp_withdraw (peer, &p, attr, packet->afi, SAFI_MPLS_VPN,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, labels, nlabels);
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, labels, nlabels, NULL);
}
/* Packet length consistency check. */
if (pnt != lim)
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 22998c4aabdc..f568806bf7ff 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -47,6 +47,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_ecommunity.h"
#include "bgpd/bgp_network.h"
#include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_evpn.h"
#include "bgpd/bgp_encap.h"
#include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_vty.h"
@@ -1654,6 +1655,9 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
return bgp_nlri_parse_vpn (peer, attr, packet);
case SAFI_ENCAP:
return bgp_nlri_parse_encap (peer, attr, packet);
+ case SAFI_EVPN:
+ case SAFI_INTERNAL_EVPN:
+ return bgp_nlri_parse_evpn (peer, attr, packet);
}
return -1;
}
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index a958a2e42fba..32577c299f6a 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2552,7 +2552,8 @@ labels_equal(struct bgp_info *info, uint32_t *labels, size_t nlabels)
static void
bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
struct attr *attr, struct peer *peer, struct prefix *p, int type,
- int sub_type, struct prefix_rd *prd, uint32_t *labels, size_t nlabels)
+ int sub_type, struct prefix_rd *prd, uint32_t *labels, size_t nlabels,
+ struct bgp_route_evpn* evpn)
{
struct bgp_node *rn;
struct bgp *bgp;
@@ -2780,7 +2781,7 @@ static int
bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
afi_t afi, safi_t safi, int type, int sub_type,
struct prefix_rd *prd, uint32_t *labels, size_t nlabels,
- int soft_reconfig)
+ int soft_reconfig, struct bgp_route_evpn* evpn)
{
int ret;
int aspath_loop_count = 0;
@@ -3134,7 +3135,7 @@ int
bgp_update (struct peer *peer, struct prefix *p, struct attr *attr,
afi_t afi, safi_t safi, int type, int sub_type,
struct prefix_rd *prd, uint32_t *labels, size_t nlabels,
- int soft_reconfig)
+ int soft_reconfig, struct bgp_route_evpn* evpn)
{
struct peer *rsclient;
struct listnode *node, *nnode;
@@ -3142,7 +3143,8 @@ bgp_update (struct peer *peer, struct prefix *p, struct attr *attr,
int ret;

ret = bgp_update_main (peer, p, attr, afi, safi, type, sub_type, prd,
- labels, nlabels, soft_reconfig);
+ labels, nlabels, soft_reconfig,
+ evpn);

bgp = peer->bgp;

@@ -3151,7 +3153,7 @@ bgp_update (struct peer *peer, struct prefix *p, struct attr *attr,
{
if (CHECK_FLAG (rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
bgp_update_rsclient (rsclient, afi, safi, attr, peer, p, type,
- sub_type, prd, labels, nlabels);
+ sub_type, prd, labels, nlabels, evpn);
}

return ret;
@@ -3160,7 +3162,8 @@ bgp_update (struct peer *peer, struct prefix *p, struct attr *attr,
int
bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr,
afi_t afi, safi_t safi, int type, int sub_type,
- struct prefix_rd *prd, uint32_t *labels, size_t nlabels)
+ struct prefix_rd *prd, uint32_t *labels, size_t nlabels,
+ struct bgp_route_evpn* evpn)
{
struct bgp *bgp;
char buf[SU_ADDRSTRLEN];
@@ -3419,7 +3422,8 @@ bgp_soft_reconfig_table_rsclient (struct peer *rsclient, afi_t afi,
size_t nlabels = (ri && ri->extra) ? ri->extra->nlabels : 0;

bgp_update_rsclient (rsclient, afi, safi, ain->attr, ain->peer,
- &rn->p, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd, labels, nlabels);
+ &rn->p, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd,
+ labels, nlabels, NULL);
}
}

@@ -3468,7 +3472,7 @@ bgp_soft_reconfig_table (struct peer *peer, afi_t afi, safi_t safi,

ret = bgp_update (peer, &rn->p, ain->attr, afi, safi,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- prd, labels, nlabels, 1);
+ prd, labels, nlabels, 1, NULL);

if (ret < 0)
{
@@ -4044,10 +4048,12 @@ bgp_nlri_parse_ip (struct peer *peer, struct attr *attr,
/* Normal process. */
if (attr)
ret = bgp_update (peer, &p, attr, packet->afi, packet->safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, 0, 0);
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, 0, 0,
+ NULL);
else
ret = bgp_withdraw (peer, &p, attr, packet->afi, packet->safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, 0);
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, 0,
+ NULL);

/* Address family configuration mismatch or maximum-prefix count
overflow. */
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 1357dee2eabb..5047b5c48b18 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -27,6 +27,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#define BGP_MAX_LABELS 6

struct bgp_nexthop_cache;
+struct bgp_route_evpn;

/* Ancillary information to struct bgp_info,
* used for uncommonly used data (aggregation, MPLS, etc.)
@@ -48,6 +49,7 @@ struct bgp_info_extra
size_t nlabels;

struct prefix_rd vrf_rd;
+
};

struct bgp_info
@@ -253,10 +255,15 @@ extern int bgp_static_unset_safi (safi_t safi, struct vty *, const char *,
/* this is primarily for MPLS-VPN */
extern int bgp_update (struct peer *, struct prefix *, struct attr *,
afi_t, safi_t, int, int, struct prefix_rd *,
- uint32_t *labels, size_t nlabels, int);
+ uint32_t *labels, size_t nlabels, int,
+ struct bgp_route_evpn* evpn);
+
+
extern int bgp_withdraw (struct peer *, struct prefix *, struct attr *,
afi_t, safi_t, int, int, struct prefix_rd *,
- uint32_t *labels, size_t nlabels);
+ uint32_t *labels, size_t nlabels,
+ struct bgp_route_evpn* evpn);
+

/* for bgp_nexthop and bgp_damp */
extern void bgp_process (struct bgp *, struct bgp_node *, afi_t, safi_t);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index bd8ee96c1ce1..35266394b0cd 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -58,6 +58,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_damp.h"
#include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_encap.h"
+#include "bgpd/bgp_evpn.h"
#include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_network.h"
#include "bgpd/bgp_vty.h"
--
2.1.4


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