bgp_mplsvpn.c bgp_nexthop.c \
bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \
bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \
- bgp_encap.c bgp_encap_tlv.c $(BGP_VNC_RFAPI_SRC) bgp_attr_evpn.c
+ bgp_encap.c bgp_encap_tlv.c $(BGP_VNC_RFAPI_SRC) bgp_attr_evpn.c \
+ bgp_evpn.c
noinst_HEADERS = \
bgp_memory.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_nht.h \
bgp_updgrp.h bgp_bfd.h bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h \
- $(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h
+ $(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h
bgpd_SOURCES = bgp_main.c
bgpd_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@
#include <zebra.h>
#include "command.h"
+#include "filter.h"
#include "prefix.h"
#include "log.h"
#include "memory.h"
struct in6_addr ipv6;
};
+struct bgp_route_evpn
+{
+ 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);
if (attr) {
bgp_update (peer, &p, 0, attr, afi, SAFI_ENCAP,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0);
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0, NULL);
} else {
bgp_withdraw (peer, &p, 0, attr, afi, SAFI_ENCAP,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL);
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, NULL);
}
}
--- /dev/null
+/* Ethernet-VPN Packet and vty Processing File
+ Copyright (C) 2016 6WIND
+
+This file is part of Free Range Routing.
+
+Free Range Routing 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.
+
+Free Range Routing 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 Free Range Routing; 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, int withdraw)
+{
+ u_char *pnt;
+ u_char *lim;
+ struct prefix p;
+ struct prefix_rd prd;
+ struct evpn_addr *p_evpn_p;
+ struct bgp_route_evpn evpn;
+ uint8_t route_type, route_length;
+ u_char *pnt_label;
+ u_int32_t addpath_id = 0;
+
+ /* Check peer status. */
+ if (peer->status != Established)
+ return 0;
+
+ /* Make prefix_rd */
+ prd.family = AF_UNSPEC;
+ prd.prefixlen = 64;
+
+#if !defined(HAVE_EVPN)
+ return -1;
+#endif /* HAVE_EVPN */
+
+ p_evpn_p = &p.u.prefix_evpn;
+ 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));
+ 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)
+ {
+ p_evpn_p->route_type = route_type;
+ memcpy (&(p_evpn_p->eth_tag), pnt, 4);
+ p_evpn_p->eth_tag = ntohl(p_evpn_p->eth_tag);
+ pnt += 4;
+
+ /* Fetch IP prefix length. */
+ p_evpn_p->ip_prefix_length = *pnt++;
+
+ if (p_evpn_p->ip_prefix_length > 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_evpn_p->flags = IP_PREFIX_V6;
+ memcpy (&(p_evpn_p->ip.v4_addr), pnt, 16);
+ pnt += 16;
+ memcpy(&evpn.gw_ip.ipv6, pnt, 16);
+ pnt += 16;
+ }
+ else
+ {
+ p_evpn_p->flags = IP_PREFIX_V4;
+ memcpy (&(p_evpn_p->ip.v4_addr), pnt, 4);
+ pnt += 4;
+ memcpy(&evpn.gw_ip.ipv4, pnt, 4);
+ pnt += 4;
+ }
+ p.family = AFI_L2VPN;
+ if (p_evpn_p->flags == IP_PREFIX_V4)
+ p.prefixlen = (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
+ else
+ p.prefixlen = PREFIX_LEN_ROUTE_TYPE_5_IPV6;
+ p.family = AF_ETHERNET;
+ }
+
+ /* Fetch Label */
+ if (pnt + 3 > lim)
+ {
+ zlog_err ("not enough bytes for Label left in NLRI?");
+ return -1;
+ }
+ pnt_label = pnt;
+
+ pnt += 3;
+
+ if (!withdraw)
+ {
+ bgp_update (peer, &p, addpath_id, attr, AFI_L2VPN, SAFI_EVPN,
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
+ pnt_label, 0, &evpn);
+ }
+ else
+ {
+ bgp_withdraw (peer, &p, addpath_id, attr, AFI_L2VPN, SAFI_EVPN,
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
+ &prd, pnt_label, &evpn);
+ }
+ }
+
+ /* Packet length consistency check. */
+ if (pnt != lim)
+ return -1;
+
+ return 0;
+}
--- /dev/null
+/* E-VPN header for packet handling
+ Copyright (C) 2016 6WIND
+
+This file is part of Free Range Routing.
+
+Free Range Routing 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.
+
+Free Range Routing 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 Free Range Routing; 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, int withdraw);
+
+/* 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 */
if (attr)
{
bgp_update (peer, &p, addpath_id, attr, packet->afi, SAFI_MPLS_VPN,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0);
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0, NULL);
}
else
{
bgp_withdraw (peer, &p, addpath_id, attr, packet->afi, SAFI_MPLS_VPN,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, NULL);
}
}
/* Packet length consistency check. */
#include "bgpd/bgp_lcommunity.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"
bgp_check_update_delay(peer->bgp);
}
-/* Frontend for NLRI parsing, to fan-out to AFI/SAFI specific parsers */
+/* Frontend for NLRI parsing, to fan-out to AFI/SAFI specific parsers
+ * mp_withdraw, if set, is used to nullify attr structure on most of the calling safi function
+ * and for evpn, passed as parameter
+ */
int
-bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
+bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet, int mp_withdraw)
{
switch (packet->safi)
{
case SAFI_UNICAST:
case SAFI_MULTICAST:
- return bgp_nlri_parse_ip (peer, attr, packet);
+ return bgp_nlri_parse_ip (peer, mp_withdraw?NULL:attr, packet);
case SAFI_MPLS_VPN:
- return bgp_nlri_parse_vpn (peer, attr, packet);
+ return bgp_nlri_parse_vpn (peer, mp_withdraw?NULL:attr, packet);
case SAFI_ENCAP:
- return bgp_nlri_parse_encap (peer, attr, packet);
+ return bgp_nlri_parse_encap (peer, mp_withdraw?NULL:attr, packet);
+ case SAFI_EVPN:
+ return bgp_nlri_parse_evpn (peer, attr, packet, mp_withdraw);
}
return -1;
}
{
case NLRI_UPDATE:
case NLRI_MP_UPDATE:
- nlri_ret = bgp_nlri_parse (peer, NLRI_ATTR_ARG, &nlris[i]);
+ nlri_ret = bgp_nlri_parse (peer, NLRI_ATTR_ARG, &nlris[i], 0);
break;
case NLRI_WITHDRAW:
case NLRI_MP_WITHDRAW:
- nlri_ret = bgp_nlri_parse (peer, NULL, &nlris[i]);
+ nlri_ret = bgp_nlri_parse (peer, &attr, &nlris[i], 1);
break;
default:
nlri_ret = -1;
extern int bgp_capability_receive (struct peer *, bgp_size_t);
-extern int bgp_nlri_parse (struct peer *, struct attr *, struct bgp_nlri *);
+extern int bgp_nlri_parse (struct peer *, struct attr *, struct bgp_nlri *, int mp_withdraw);
extern void bgp_update_restarted_peers (struct peer *);
extern void bgp_update_implicit_eors (struct peer *);
bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
struct attr *attr, afi_t afi, safi_t safi, int type,
int sub_type, struct prefix_rd *prd, u_char *tag,
- int soft_reconfig)
+ int soft_reconfig, struct bgp_route_evpn* evpn)
{
int ret;
int aspath_loop_count = 0;
int
bgp_withdraw (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
struct attr *attr, afi_t afi, safi_t safi, int type, int sub_type,
- struct prefix_rd *prd, u_char *tag)
+ struct prefix_rd *prd, u_char *tag, struct bgp_route_evpn *evpn)
{
struct bgp *bgp;
char buf[SU_ADDRSTRLEN];
ret = bgp_update (peer, &rn->p, ain->addpath_rx_id, ain->attr,
afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- prd, tag, 1);
+ prd, tag, 1, NULL);
if (ret < 0)
{
/* Normal process. */
if (attr)
ret = bgp_update (peer, &p, addpath_id, attr, afi, safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, 0);
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, 0, NULL);
else
ret = bgp_withdraw (peer, &p, addpath_id, attr, afi, safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL);
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, NULL);
/* Address family configuration mismatch or maximum-prefix count
overflow. */
#include "bgp_table.h"
struct bgp_nexthop_cache;
+struct bgp_route_evpn;
enum bgp_show_type
{
/* this is primarily for MPLS-VPN */
extern int bgp_update (struct peer *, struct prefix *, u_int32_t, struct attr *,
- afi_t, safi_t, int, int, struct prefix_rd *,
- u_char *, int);
+ afi_t, safi_t, int, int, struct prefix_rd *,
+ u_char *, int, struct bgp_route_evpn *);
extern int bgp_withdraw (struct peer *, struct prefix *, u_int32_t, struct attr *,
- afi_t, safi_t, int, int, struct prefix_rd *, u_char *);
+ afi_t, safi_t, int, int, struct prefix_rd *, u_char *,
+ struct bgp_route_evpn *);
/* for bgp_nexthop and bgp_damp */
extern void bgp_process (struct bgp *, struct bgp_node *, afi_t, safi_t);
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
#include "bgpd/rfapi/rfapi_backend.h"
#endif
+#include "bgpd/bgp_evpn.h"
#include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_network.h"
#include "bgpd/bgp_vty.h"
iattr, /* bgp_update copies this attr */
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
NULL, /* tag not used for unicast */
- 0);
+ 0, NULL); /* EVPN not used */
bgp_attr_unintern (&iattr);
}
0, /* addpath_id */
NULL, /* attr, ignored */
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
- NULL); /* tag not used for unicast */
+ NULL, NULL); /* tag not used for unicast */
}
0, /* addpath_id */
NULL, /* ignored */
AFI_IP, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
- NULL); /* tag not used for unicast */
+ NULL, NULL); /* tag not used for unicast */
}
}
}
iattr, /* bgp_update copies it */
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
NULL, /* tag not used for unicast */
- 0);
+ 0, NULL); /* EVPN not used */
bgp_attr_unintern (&iattr);
}
0, /* addpath_id */
NULL, /* attr, ignored */
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
- NULL); /* tag not used for unicast */
+ NULL, NULL); /* tag not used for unicast */
}
}
}
iattr, /* bgp_update copies it */
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
NULL, /* tag not used for unicast */
- 0);
+ 0, NULL); /* EVPN not used */
bgp_attr_unintern (&iattr);
0, /* addpath_id */
NULL, /* attr, ignored */
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
- NULL); /* tag not used for unicast */
+ NULL, NULL); /* tag not used for unicast */
}
}
iattr, /* bgp_update copies it */
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
NULL, /* tag not used for unicast */
- 0);
+ 0, NULL); /* EVPN not used */
bgp_attr_unintern (&iattr);
}
0, /* addpath_id */
NULL, /* attr, ignored */
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
- NULL); /* tag not used for unicast */
+ NULL, NULL); /* tag not used for unicast */
}
}
0, /* addpath_id */
NULL, /* attr, ignored */
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
- NULL); /* tag not used for unicast */
+ NULL, NULL); /* tag not used for unicast, EVPN neither */
}
}
0, /* addpath_id */
iattr, /* bgp_update copies this attr */
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
- NULL, /* tag not used for unicast */
- 0);
+ NULL, /* tag not used for unicast, EVPN neither */
+ 0, NULL); /* EVPN not used */
bgp_attr_unintern (&iattr);
}
eti->type,
eti->subtype,
NULL, /* RD not used for unicast */
- NULL); /* tag not used for unicast */
+ NULL, NULL); /* tag not used for unicast, EVPN neither */
/*
* Free the eti
0, /* addpath_id */
iattr, /* bgp_update copies it */
AFI_IP, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
- NULL, /* tag not used for unicast */
- 0);
+ NULL, /* tag not used for unicast, EVPN neither */
+ 0, NULL); /* EVPN not used */
bgp_attr_unintern (&iattr);
}
}
0, /* addpath_id */
NULL, /* ignored */
AFI_IP, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
- NULL); /* tag not used for unicast */
+ NULL, NULL); /* tag not used for unicast, EVPN neither */
}
}
}