Merge pull request #103 from pguibert6WIND/frr_6wind_evpn_5

Provide EVPN basic support on master branch + EVPN Route Target 5 Support (V2)
This commit is contained in:
Lou Berger 2017-02-17 12:18:08 -05:00 committed by GitHub
commit bac515c64c
53 changed files with 2622 additions and 525 deletions

View File

@ -79,7 +79,8 @@ libbgp_a_SOURCES = \
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_encap.c bgp_encap_tlv.c $(BGP_VNC_RFAPI_SRC) bgp_attr_evpn.c \
bgp_evpn.c bgp_evpn_vty.c bgp_vpn.c
noinst_HEADERS = \
bgp_memory.h \
@ -90,7 +91,7 @@ noinst_HEADERS = \
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_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h bgp_evpn_vty.h bgp_vpn.h
bgpd_SOURCES = bgp_main.c
bgpd_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@

View File

@ -50,6 +50,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# include "bgp_encap_types.h"
# include "bgp_vnc_types.h"
#endif
#include "bgp_encap_types.h"
#include "bgp_evpn.h"
/* Attribute strings for logging. */
static const struct message attr_str [] =
@ -419,6 +421,18 @@ encap_finish (void)
#endif
}
static bool
overlay_index_same(const struct attr_extra *ae1, const struct attr_extra *ae2)
{
if(!ae1 && ae2)
return false;
if(!ae2 && ae1)
return false;
if(!ae1 && !ae2)
return true;
return !memcmp(&(ae1->evpn_overlay), &(ae2->evpn_overlay), sizeof(struct overlay_index));
}
/* Unknown transit attribute. */
static struct hash *transit_hash;
@ -730,7 +744,8 @@ attrhash_cmp (const void *p1, const void *p2)
#if ENABLE_BGP_VNC
&& encap_same(ae1->vnc_subtlvs, ae2->vnc_subtlvs)
#endif
&& IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id))
&& IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id)
&& overlay_index_same(ae1, ae2))
return 1;
else if (ae1 || ae2)
return 0;
@ -2799,6 +2814,39 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
break;
}
break;
case AFI_L2VPN:
switch (safi)
{
case SAFI_EVPN:
if (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV4)
{
stream_putc (s, 12);
stream_putl (s, 0); /* RD = 0, per RFC */
stream_putl (s, 0);
stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
}
else if (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL)
{
stream_putc (s, 24);
stream_putl (s, 0); /* RD = 0, per RFC */
stream_putl (s, 0);
stream_put (s, &attr->extra->mp_nexthop_global, IPV6_MAX_BYTELEN);
}
else if (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
{
stream_putc (s, 48);
stream_putl (s, 0); /* RD = 0, per RFC */
stream_putl (s, 0);
stream_put (s, &attr->extra->mp_nexthop_global, IPV6_MAX_BYTELEN);
stream_putl (s, 0); /* RD = 0, per RFC */
stream_putl (s, 0);
stream_put (s, &attr->extra->mp_nexthop_local, IPV6_MAX_BYTELEN);
}
break;
break;
default:
break;
}
default:
break;
}
@ -2812,7 +2860,7 @@ void
bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
struct prefix *p, struct prefix_rd *prd,
u_char *tag, int addpath_encode,
u_int32_t addpath_tx_id)
u_int32_t addpath_tx_id, struct attr *attr)
{
if (safi == SAFI_MPLS_VPN)
{
@ -2824,6 +2872,10 @@ bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
stream_put (s, prd->val, 8);
stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
}
else if ((safi == SAFI_EVPN))
{
bgp_packet_mpattr_route_type_5(s, p, prd, tag, attr);
}
else
stream_put_prefix_addpath (s, p, addpath_encode, addpath_tx_id);
}
@ -2977,7 +3029,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
AFI_MAX), /* get from NH */
vecarr, attr);
bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag,
addpath_encode, addpath_tx_id);
addpath_encode, addpath_tx_id, attr);
bgp_packet_mpattr_end(s, mpattrlen_pos);
}
@ -3338,8 +3390,9 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
}
if ((afi == AFI_IP || afi == AFI_IP6) &&
(safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
if (((afi == AFI_IP || afi == AFI_IP6) &&
(safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN)) ||
(afi == AFI_L2VPN && safi == SAFI_EVPN))
{
/* Tunnel Encap attribute */
bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
@ -3385,21 +3438,10 @@ void
bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
afi_t afi, safi_t safi, struct prefix_rd *prd,
u_char *tag, int addpath_encode,
u_int32_t addpath_tx_id)
u_int32_t addpath_tx_id, struct attr *attr)
{
if (safi == SAFI_MPLS_VPN)
{
/* addpath TX ID */
if (addpath_encode)
stream_putl(s, addpath_tx_id);
stream_putc (s, p->prefixlen + 88);
stream_put (s, tag, 3);
stream_put (s, prd->val, 8);
stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
}
else
stream_put_prefix_addpath (s, p, addpath_encode, addpath_tx_id);
return bgp_packet_mpattr_prefix (s, afi, safi, p, prd,
tag, addpath_encode, addpath_tx_id, attr);
}
void

View File

@ -21,6 +21,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#ifndef _QUAGGA_BGP_ATTR_H
#define _QUAGGA_BGP_ATTR_H
#include "bgp_attr_evpn.h"
/* Simple bit mapping. */
#define BITMAP_NBBY 8
@ -80,6 +82,13 @@ struct bgp_tea_options {
#endif
/* Overlay Index Info */
struct overlay_index
{
struct eth_segment_id eth_s_id;
union gw_addr gw_ip;
};
/* Additional/uncommon BGP attributes.
* lazily allocated as and when a struct attr
* requires it.
@ -131,6 +140,8 @@ struct attr_extra
#if ENABLE_BGP_VNC
struct bgp_attr_encap_subtlv *vnc_subtlvs; /* VNC-specific */
#endif
/* EVPN */
struct overlay_index evpn_overlay;
};
/* BGP core attribute structure. */
@ -283,7 +294,8 @@ extern size_t bgp_packet_mpattr_start(struct stream *s, afi_t afi, safi_t safi,
extern void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
struct prefix *p, struct prefix_rd *prd,
u_char *tag, int addpath_encode,
u_int32_t addpath_tx_id);
u_int32_t addpath_tx_id,
struct attr *);
extern size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
struct prefix *p);
extern void bgp_packet_mpattr_end(struct stream *s, size_t sizep);
@ -292,7 +304,7 @@ extern size_t bgp_packet_mpunreach_start (struct stream *s, afi_t afi,
safi_t safi);
extern void bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
afi_t afi, safi_t safi, struct prefix_rd *prd,
u_char *tag, int, u_int32_t);
u_char *tag, int, u_int32_t, struct attr *);
extern void bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt);
static inline int

141
bgpd/bgp_attr_evpn.c Normal file
View File

@ -0,0 +1,141 @@
/* Ethernet-VPN Attribute handling 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/bgpd.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_attr_evpn.h"
#include "bgpd/bgp_ecommunity.h"
#include "bgpd/bgp_evpn.h"
void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac)
{
struct ecommunity_val routermac_ecom;
if (attr->extra) {
memset(&routermac_ecom, 0, sizeof(struct ecommunity_val));
routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN;
routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC;
memcpy(&routermac_ecom.val[2], routermac->octet, ETHER_ADDR_LEN);
if (!attr->extra->ecommunity)
attr->extra->ecommunity = ecommunity_new();
ecommunity_add_val(attr->extra->ecommunity, &routermac_ecom);
ecommunity_str (attr->extra->ecommunity);
}
}
/* converts to an esi
* returns 1 on success, 0 otherwise
* format accepted: AA:BB:CC:DD:EE:FF:GG:HH:II:JJ
* if id is null, check only is done
*/
int str2esi(const char *str, struct eth_segment_id *id)
{
unsigned int a[ESI_LEN];
int i;
if (!str)
return 0;
if (sscanf (str, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x",
a + 0, a + 1, a + 2, a + 3, a + 4, a + 5,
a + 6, a + 7, a + 8, a + 9) != ESI_LEN)
{
/* error in incoming str length */
return 0;
}
/* valid mac address */
if (!id)
return 1;
for (i = 0; i < ESI_LEN; ++i)
id->val[i] = a[i] & 0xff;
return 1;
}
char *esi2str(struct eth_segment_id *id)
{
char *ptr;
u_char *val;
if (!id)
return NULL;
val = id->val;
ptr = (char *)XMALLOC(MTYPE_TMP, (ESI_LEN * 2 + ESI_LEN - 1 + 1) * sizeof(char));
snprintf(ptr, (ESI_LEN * 2 + ESI_LEN - 1 + 1),
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
val[0], val[1], val[2], val[3], val[4],
val[5], val[6], val[7], val[8], val[9]);
return ptr;
}
char *ecom_mac2str(char *ecom_mac)
{
char *en;
en = ecom_mac;
en += 2;
return prefix_mac2str((struct ethaddr *)en, NULL, 0);
}
/* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
extern int
bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag, struct prefix *dst)
{
struct evpn_addr *p_evpn_p;
struct prefix p2;
struct prefix *src = &p2;
if (!dst || dst->family == 0)
return -1;
/* store initial prefix in src */
prefix_copy(src, dst);
memset(dst, 0, sizeof(struct prefix));
p_evpn_p = &(dst->u.prefix_evpn);
dst->family = AF_ETHERNET;
p_evpn_p->route_type = evpn_type;
if (evpn_type == EVPN_IP_PREFIX) {
p_evpn_p->eth_tag = eth_tag;
p_evpn_p->ip_prefix_length = p2.prefixlen;
if (src->family == AF_INET) {
p_evpn_p->flags = IP_PREFIX_V4;
memcpy(&p_evpn_p->ip.v4_addr, &src->u.prefix4,
sizeof(struct in_addr));
dst->prefixlen = (u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV4;
} else {
p_evpn_p->flags = IP_PREFIX_V6;
memcpy(&p_evpn_p->ip.v6_addr, &src->u.prefix6,
sizeof(struct in6_addr));
dst->prefixlen = (u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV6;
}
} else
return -1;
return 0;
}

59
bgpd/bgp_attr_evpn.h Normal file
View File

@ -0,0 +1,59 @@
/* E-VPN attribute handling structure 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. */
#ifndef _QUAGGA_BGP_ATTR_EVPN_H
#define _QUAGGA_BGP_ATTR_EVPN_H
/* value of first byte of ESI */
#define ESI_TYPE_ARBITRARY 0 /* */
#define ESI_TYPE_LACP 1 /* <> */
#define ESI_TYPE_BRIDGE 2 /* <Root bridge Mac-6B>:<Root Br Priority-2B>:00 */
#define ESI_TYPE_MAC 3 /* <Syst Mac Add-6B>:<Local Discriminator Value-3B> */
#define ESI_TYPE_ROUTER 4 /* <RouterId-4B>:<Local Discriminator Value-4B> */
#define ESI_TYPE_AS 5 /* <AS-4B>:<Local Discriminator Value-4B> */
#define MAX_ESI {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}
#define ESI_LEN 10
#define MAX_ET 0xffffffff
u_long eth_tag_id;
struct attr;
struct eth_segment_id {
u_char val[ESI_LEN];
};
union gw_addr {
struct in_addr ipv4;
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 char *esi2str(struct eth_segment_id *id);
extern char *ecom_mac2str(char *ecom_mac);
extern void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac);
extern int bgp_build_evpn_prefix(int type, uint32_t eth_tag,
struct prefix *dst);
#endif /* _QUAGGA_BGP_ATTR_EVPN_H */

View File

@ -1166,14 +1166,14 @@ extcommunity_list_set (struct community_list_handler *ch,
}
if (ecom)
ecom->str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_DISPLAY);
ecom->str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_DISPLAY, 0);
entry = community_entry_new ();
entry->direct = direct;
entry->style = style;
entry->any = (str ? 0 : 1);
if (ecom)
entry->config = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_COMMUNITY_LIST);
entry->config = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_COMMUNITY_LIST, 0);
else if (regex)
entry->config = XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG, str);
else

View File

@ -38,6 +38,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_community.h"
#include "bgpd/bgp_updgrp.h"
#include "bgpd/bgp_mplsvpn.h"
#define BGP_ADDPATH_STR 20
unsigned long conf_bgp_debug_as4;
unsigned long conf_bgp_debug_neighbor_events;
@ -2086,3 +2089,31 @@ bgp_debug_zebra (struct prefix *p)
return 0;
}
const char *
bgp_debug_rdpfxpath2str (struct prefix_rd *prd, union prefixconstptr pu,
int addpath_valid, u_int32_t addpath_id,
char *str, int size)
{
char rd_buf[RD_ADDRSTRLEN];
char pfx_buf[PREFIX_STRLEN];
char pathid_buf[BGP_ADDPATH_STR];
if (size < BGP_PRD_PATH_STRLEN)
return NULL;
/* Note: Path-id is created by default, but only included in update sometimes. */
pathid_buf[0] = '\0';
if (addpath_valid)
sprintf(pathid_buf, " with addpath ID %d", addpath_id);
if (prd)
snprintf (str, size, "RD %s %s%s",
prefix_rd2str(prd, rd_buf, sizeof (rd_buf)),
prefix2str (pu, pfx_buf, sizeof (pfx_buf)), pathid_buf);
else
snprintf (str, size, "%s%s",
prefix2str (pu, pfx_buf, sizeof (pfx_buf)), pathid_buf);
return str;
}

View File

@ -36,6 +36,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
/* dump detail */
#define DUMP_DETAIL 32
/* RD + Prefix + Path-Id */
#define BGP_PRD_PATH_STRLEN (PREFIX_STRLEN + RD_ADDRSTRLEN + 20)
extern int dump_open;
extern int dump_update;
extern int dump_keepalive;
@ -151,4 +154,6 @@ extern int bgp_debug_bestpath(struct prefix *p);
extern int bgp_debug_zebra(struct prefix *p);
extern int bgp_debug_count(void);
extern const char *bgp_debug_rdpfxpath2str (struct prefix_rd *, union prefixconstptr,
int, u_int32_t, char *, int);
#endif /* _QUAGGA_BGP_DEBUG_H */

View File

@ -175,7 +175,7 @@ char *
ecommunity_str (struct ecommunity *ecom)
{
if (! ecom->str)
ecom->str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_DISPLAY);
ecom->str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_DISPLAY, 0);
return ecom->str;
}
@ -213,7 +213,7 @@ ecommunity_intern (struct ecommunity *ecom)
find->refcnt++;
if (! find->str)
find->str = ecommunity_ecom2str (find, ECOMMUNITY_FORMAT_DISPLAY);
find->str = ecommunity_ecom2str (find, ECOMMUNITY_FORMAT_DISPLAY, 0);
return find;
}
@ -601,9 +601,12 @@ ecommunity_str2com (const char *str, int type, int keyword_included)
ECOMMUNITY_FORMAT_ROUTE_MAP
ECOMMUNITY_FORMAT_COMMUNITY_LIST
ECOMMUNITY_FORMAT_DISPLAY
Filter is added to display only ECOMMUNITY_ROUTE_TARGET in some cases.
0 value displays all
*/
char *
ecommunity_ecom2str (struct ecommunity *ecom, int format)
ecommunity_ecom2str (struct ecommunity *ecom, int format, int filter)
{
int i;
u_int8_t *pnt;
@ -640,6 +643,7 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format)
/* Prepare buffer. */
str_buf = XMALLOC (MTYPE_ECOMMUNITY_STR, ECOMMUNITY_STR_DEFAULT_LEN + 1);
str_size = ECOMMUNITY_STR_DEFAULT_LEN + 1;
str_buf[0] = '\0';
str_pnt = 0;
for (i = 0; i < ecom->size; i++)
@ -668,6 +672,10 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format)
break;
case ECOMMUNITY_ENCODE_OPAQUE:
if(filter == ECOMMUNITY_ROUTE_TARGET)
{
continue;
}
if (*pnt == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP)
{
uint16_t tunneltype;
@ -678,8 +686,31 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format)
first = 0;
continue;
}
/* fall through */
len = sprintf (str_buf + str_pnt, "?");
str_pnt += len;
first = 0;
continue;
case ECOMMUNITY_ENCODE_EVPN:
if(filter == ECOMMUNITY_ROUTE_TARGET)
{
continue;
}
if (*pnt == ECOMMUNITY_SITE_ORIGIN)
{
char macaddr[6];
pnt++;
memcpy(&macaddr, pnt, 6);
len = sprintf(str_buf + str_pnt, "EVPN:%02x:%02x:%02x:%02x:%02x:%02x",
macaddr[0], macaddr[1], macaddr[2],
macaddr[3], macaddr[4], macaddr[5]);
str_pnt += len;
first = 0;
continue;
}
len = sprintf (str_buf + str_pnt, "?");
str_pnt += len;
first = 0;
continue;
default:
len = sprintf (str_buf + str_pnt, "?");
str_pnt += len;
@ -791,3 +822,64 @@ ecommunity_match (const struct ecommunity *ecom1,
else
return 0;
}
/* return first occurence of type */
extern struct ecommunity_val *ecommunity_lookup (const struct ecommunity *ecom, uint8_t type, uint8_t subtype)
{
u_int8_t *p;
int c;
/* If the value already exists in the structure return 0. */
c = 0;
for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++)
{
if(p == NULL)
{
continue;
}
if(p[0] == type && p[1] == subtype)
return (struct ecommunity_val *)p;
}
return NULL;
}
/* remove ext. community matching type and subtype
* return 1 on success ( removed ), 0 otherwise (not present)
*/
extern int ecommunity_strip (struct ecommunity *ecom, uint8_t type, uint8_t subtype)
{
u_int8_t *p;
int c, found = 0;
/* When this is fist value, just add it. */
if (ecom == NULL || ecom->val == NULL)
{
return 0;
}
/* If the value already exists in the structure return 0. */
c = 0;
for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++)
{
if (p[0] == type && p[1] == subtype)
{
found = 1;
break;
}
}
if (found == 0)
return 0;
/* Strip The selected value */
ecom->size--;
/* size is reduced. no memmove to do */
p = XMALLOC (MTYPE_ECOMMUNITY_VAL, ecom->size * ECOMMUNITY_SIZE);
if (c != 0)
memcpy(p, ecom->val, c * ECOMMUNITY_SIZE);
if( (ecom->size - c) != 0)
memcpy(p + (c) * ECOMMUNITY_SIZE,
ecom->val + (c +1)* ECOMMUNITY_SIZE,
(ecom->size - c) * ECOMMUNITY_SIZE);
/* shift last ecommunities */
XFREE (MTYPE_ECOMMUNITY, ecom->val);
ecom->val = p;
return 1;
}

View File

@ -26,11 +26,18 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#define ECOMMUNITY_ENCODE_IP 0x01
#define ECOMMUNITY_ENCODE_AS4 0x02
#define ECOMMUNITY_ENCODE_OPAQUE 0x03
#define ECOMMUNITY_ENCODE_EVPN 0x06
/* Low-order octet of the Extended Communities type field. */
#define ECOMMUNITY_ROUTE_TARGET 0x02
#define ECOMMUNITY_SITE_ORIGIN 0x03
#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00
#define ECOMMUNITY_EVPN_SUBTYPE_ESI_LABEL 0x01
#define ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT 0x02
#define ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC 0x03
#define ECOMMUNITY_EVPN_SUBTYPE_DEF_GW 0x0d
/* Low-order octet of the Extended Communities type field for OPAQUE types */
#define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c
@ -81,11 +88,15 @@ extern int ecommunity_cmp (const void *, const void *);
extern void ecommunity_unintern (struct ecommunity **);
extern unsigned int ecommunity_hash_make (void *);
extern struct ecommunity *ecommunity_str2com (const char *, int, int);
extern char *ecommunity_ecom2str (struct ecommunity *, int);
extern char *ecommunity_ecom2str (struct ecommunity *, int, int);
extern int ecommunity_match (const struct ecommunity *, const struct ecommunity *);
extern char *ecommunity_str (struct ecommunity *);
extern struct ecommunity_val *ecommunity_lookup (const struct ecommunity *, uint8_t, uint8_t );
extern int ecommunity_add_val (struct ecommunity *ecom, struct ecommunity_val *eval);
/* for vpn */
extern struct ecommunity *ecommunity_new (void);
extern int ecommunity_add_val (struct ecommunity *, struct ecommunity_val *);
extern int ecommunity_strip (struct ecommunity *ecom, uint8_t type, uint8_t subtype);
extern struct ecommunity *ecommunity_new (void);
#endif /* _QUAGGA_BGP_ECOMMUNITY_H */

View File

@ -188,10 +188,10 @@ bgp_nlri_parse_encap(
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);
}
}
@ -219,7 +219,8 @@ DEFUN (encap_network,
int idx_ipv4 = 1;
int idx_rd = 3;
int idx_word = 5;
return bgp_static_set_safi (SAFI_ENCAP, vty, argv[idx_ipv4]->arg, argv[idx_rd]->arg, argv[idx_word]->arg, NULL);
return bgp_static_set_safi (SAFI_ENCAP, vty, argv[idx_ipv4]->arg, argv[idx_rd]->arg, argv[idx_word]->arg,
NULL, 0, NULL, NULL, NULL, NULL);
}
/* For testing purpose, static route of ENCAP. */
@ -237,7 +238,8 @@ DEFUN (no_encap_network,
int idx_ipv4 = 2;
int idx_rd = 4;
int idx_word = 6;
return bgp_static_unset_safi (SAFI_ENCAP, vty, argv[idx_ipv4]->arg, argv[idx_rd]->arg, argv[idx_word]->arg);
return bgp_static_unset_safi (SAFI_ENCAP, vty, argv[idx_ipv4]->arg, argv[idx_rd]->arg, argv[idx_word]->arg,
0, NULL, NULL, NULL);
}
static int

View File

@ -391,8 +391,30 @@ bgp_encap_type_vxlan_to_tlv(
struct attr *attr)
{
struct attr_extra *extra = bgp_attr_extra_get(attr);
struct bgp_attr_encap_subtlv *tlv;
uint32_t vnid;
extra->encap_tunneltype = BGP_ENCAP_TYPE_VXLAN;
if(bet == NULL ||!bet->vnid)
return;
if(extra->encap_subtlvs)
XFREE(MTYPE_ENCAP_TLV, extra->encap_subtlvs);
tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+12);
tlv->type = 1; /* encapsulation type */
tlv->length = 12;
if(bet->vnid)
{
vnid = htonl(bet->vnid | VXLAN_ENCAP_MASK_VNID_VALID);
memcpy(&tlv->value, &vnid, 4);
}
if(bet->mac_address)
{
char *ptr = (char *)&tlv->value + 4;
memcpy( ptr, bet->mac_address, 6);
}
extra->encap_subtlvs = tlv;
return;
}
void

View File

@ -167,10 +167,15 @@ struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode {
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
};
#define VXLAN_ENCAP_MASK_VNID_VALID 0x80000000
#define VXLAN_ENCAP_MASK_MAC_VALID 0x40000000
struct bgp_encap_type_vxlan {
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
/* No subtlvs defined in spec? */
/* draft-ietf-idr-tunnel-encaps-02 */
uint32_t vnid; /* does not include V and M bit */
uint8_t *mac_address; /* optional */
};
struct bgp_encap_type_nvgre {

225
bgpd/bgp_evpn.c Normal file
View File

@ -0,0 +1,225 @@
/* 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;
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;
}
void
bgp_packet_mpattr_route_type_5(struct stream *s,
struct prefix *p, struct prefix_rd *prd,
u_char * label, struct attr *attr)
{
int len;
char temp[16];
struct evpn_addr *p_evpn_p;
memset(&temp, 0, 16);
if (p->family != AF_ETHERNET)
return;
p_evpn_p = &(p->u.prefix_evpn);
if (p_evpn_p->flags & IP_PREFIX_V4)
len = 8; /* ipv4 */
else
len = 32; /* ipv6 */
stream_putc(s, EVPN_IP_PREFIX);
stream_putc(s,
8 /* RD */ + 10 /* ESI */ + 4 /* EthTag */ + 1 + len +
3 /* label */ );
stream_put(s, prd->val, 8);
if (attr && attr->extra)
stream_put(s, &(attr->extra->evpn_overlay.eth_s_id), 10);
else
stream_put(s, &temp, 10);
stream_putl(s, p_evpn_p->eth_tag);
stream_putc(s, p_evpn_p->ip_prefix_length);
if (p_evpn_p->flags & IP_PREFIX_V4)
stream_put_ipv4(s, p_evpn_p->ip.v4_addr.s_addr);
else
stream_put(s, &p_evpn_p->ip.v6_addr, 16);
if (attr && attr->extra) {
if (p_evpn_p->flags & IP_PREFIX_V4)
stream_put_ipv4(s,
attr->extra->evpn_overlay.gw_ip.ipv4.
s_addr);
else
stream_put(s, &(attr->extra->evpn_overlay.gw_ip.ipv6),
16);
} else {
if (p_evpn_p->flags & IP_PREFIX_V4)
stream_put_ipv4(s, 0);
else
stream_put(s, &temp, 16);
}
if (label)
stream_put(s, label, 3);
else
stream_put3(s, 0);
return;
}

40
bgpd/bgp_evpn.h Normal file
View File

@ -0,0 +1,40 @@
/* 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);
extern void
bgp_packet_mpattr_route_type_5(struct stream *s,
struct prefix *p, struct prefix_rd *prd,
u_char * label, struct attr *attr);
/* 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 */

750
bgpd/bgp_evpn_vty.c Normal file
View File

@ -0,0 +1,750 @@
/* Ethernet-VPN Packet and vty Processing File
Copyright (C) 2017 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 "prefix.h"
#include "lib/json.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_vpn.h"
#include "bgpd/bgp_evpn_vty.h"
#include "bgpd/bgp_evpn.h"
#define SHOW_DISPLAY_STANDARD 0
#define SHOW_DISPLAY_TAGS 1
#define SHOW_DISPLAY_OVERLAY 2
static int
bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
enum bgp_show_type type, void *output_arg, int option,
u_char use_json)
{
afi_t afi = AFI_L2VPN;
struct bgp *bgp;
struct bgp_table *table;
struct bgp_node *rn;
struct bgp_node *rm;
struct bgp_info *ri;
int rd_header;
int header = 1;
char v4_header[] =
" Network Next Hop Metric LocPrf Weight Path%s";
char v4_header_tag[] =
" Network Next Hop In tag/Out tag%s";
char v4_header_overlay[] =
" Network Next Hop EthTag Overlay Index RouterMac%s";
unsigned long output_count = 0;
unsigned long total_count = 0;
json_object *json = NULL;
json_object *json_nroute = NULL;
json_object *json_array = NULL;
json_object *json_scode = NULL;
json_object *json_ocode = NULL;
bgp = bgp_get_default();
if (bgp == NULL) {
if (!use_json)
vty_out(vty, "No BGP process is configured%s",
VTY_NEWLINE);
return CMD_WARNING;
}
if (use_json) {
json_scode = json_object_new_object();
json_ocode = json_object_new_object();
json = json_object_new_object();
json_nroute = json_object_new_object();
json_object_string_add(json_scode, "suppressed", "s");
json_object_string_add(json_scode, "damped", "d");
json_object_string_add(json_scode, "history", "h");
json_object_string_add(json_scode, "valid", "*");
json_object_string_add(json_scode, "best", ">");
json_object_string_add(json_scode, "internal", "i");
json_object_string_add(json_ocode, "igp", "i");
json_object_string_add(json_ocode, "egp", "e");
json_object_string_add(json_ocode, "incomplete", "?");
}
for (rn = bgp_table_top(bgp->rib[afi][SAFI_EVPN]); rn;
rn = bgp_route_next(rn)) {
if (use_json)
continue; /* XXX json TODO */
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
continue;
if ((table = rn->info) != NULL) {
rd_header = 1;
for (rm = bgp_table_top(table); rm;
rm = bgp_route_next(rm))
for (ri = rm->info; ri; ri = ri->next) {
total_count++;
if (type == bgp_show_type_neighbor) {
union sockunion *su =
output_arg;
if (ri->peer->su_remote == NULL
|| !sockunion_same(ri->
peer->
su_remote,
su))
continue;
}
if (header == 0) {
if (use_json) {
if (option ==
SHOW_DISPLAY_TAGS) {
json_object_int_add
(json,
"bgpTableVersion",
0);
json_object_string_add
(json,
"bgpLocalRouterId",
inet_ntoa
(bgp->
router_id));
json_object_object_add
(json,
"bgpStatusCodes",
json_scode);
json_object_object_add
(json,
"bgpOriginCodes",
json_ocode);
}
} else {
if (option ==
SHOW_DISPLAY_TAGS)
vty_out(vty,
v4_header_tag,
VTY_NEWLINE);
else if (option ==
SHOW_DISPLAY_OVERLAY)
vty_out(vty,
v4_header_overlay,
VTY_NEWLINE);
else {
vty_out(vty,
"BGP table version is 0, local router ID is %s%s",
inet_ntoa
(bgp->
router_id),
VTY_NEWLINE);
vty_out(vty,
"Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
VTY_NEWLINE);
vty_out(vty,
"Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
VTY_NEWLINE,
VTY_NEWLINE);
vty_out(vty,
v4_header,
VTY_NEWLINE);
}
}
header = 0;
}
if (rd_header) {
u_int16_t type;
struct rd_as rd_as;
struct rd_ip rd_ip;
u_char *pnt;
pnt = rn->p.u.val;
/* Decode RD type. */
type = decode_rd_type(pnt);
/* Decode RD value. */
if (type == RD_TYPE_AS)
decode_rd_as(pnt + 2,
&rd_as);
else if (type == RD_TYPE_AS4)
decode_rd_as4(pnt + 2,
&rd_as);
else if (type == RD_TYPE_IP)
decode_rd_ip(pnt + 2,
&rd_ip);
if (use_json) {
char buffer[BUFSIZ];
if (type == RD_TYPE_AS
|| type ==
RD_TYPE_AS4)
sprintf(buffer,
"%u:%d",
rd_as.
as,
rd_as.
val);
else if (type ==
RD_TYPE_IP)
sprintf(buffer,
"%s:%d",
inet_ntoa
(rd_ip.
ip),
rd_ip.
val);
json_object_string_add
(json_nroute,
"routeDistinguisher",
buffer);
} else {
vty_out(vty,
"Route Distinguisher: ");
if (type == RD_TYPE_AS)
vty_out(vty,
"as2 %u:%d",
rd_as.
as,
rd_as.
val);
else if (type ==
RD_TYPE_AS4)
vty_out(vty,
"as4 %u:%d",
rd_as.
as,
rd_as.
val);
else if (type ==
RD_TYPE_IP)
vty_out(vty,
"ip %s:%d",
inet_ntoa
(rd_ip.
ip),
rd_ip.
val);
vty_out(vty, "%s",
VTY_NEWLINE);
}
rd_header = 0;
}
if (use_json)
json_array =
json_object_new_array();
else
json_array = NULL;
if (option == SHOW_DISPLAY_TAGS)
route_vty_out_tag(vty, &rm->p,
ri, 0,
SAFI_EVPN,
json_array);
else if (option == SHOW_DISPLAY_OVERLAY)
route_vty_out_overlay(vty,
&rm->p,
ri, 0,
json_array);
else
route_vty_out(vty, &rm->p, ri,
0, SAFI_EVPN,
json_array);
output_count++;
}
/* XXX json */
}
}
if (output_count == 0)
vty_out(vty, "No prefixes displayed, %ld exist%s", total_count,
VTY_NEWLINE);
else
vty_out(vty, "%sDisplayed %ld out of %ld total prefixes%s",
VTY_NEWLINE, output_count, total_count, VTY_NEWLINE);
return CMD_SUCCESS;
}
DEFUN(show_ip_bgp_l2vpn_evpn,
show_ip_bgp_l2vpn_evpn_cmd,
"show [ip] bgp l2vpn evpn [json]",
SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR)
{
return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL, 0,
use_json(argc, argv));
}
DEFUN(show_ip_bgp_l2vpn_evpn_rd,
show_ip_bgp_l2vpn_evpn_rd_cmd,
"show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn [json]",
SHOW_STR
IP_STR
BGP_STR
L2VPN_HELP_STR
EVPN_HELP_STR
"Display information for a route distinguisher\n"
"VPN Route Distinguisher\n" JSON_STR)
{
int idx_ext_community = 6;
int ret;
struct prefix_rd prd;
ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
if (!ret) {
vty_out(vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
return CMD_WARNING;
}
return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 0,
use_json(argc, argv));
}
DEFUN(show_ip_bgp_l2vpn_evpn_all_tags,
show_ip_bgp_l2vpn_evpn_all_tags_cmd,
"show [ip] bgp l2vpn evpn all tags",
SHOW_STR
IP_STR
BGP_STR
L2VPN_HELP_STR
EVPN_HELP_STR
"Display information about all EVPN NLRIs\n"
"Display BGP tags for prefixes\n")
{
return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL, 1,
0);
}
DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags,
show_ip_bgp_l2vpn_evpn_rd_tags_cmd,
"show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn tags",
SHOW_STR
IP_STR
BGP_STR
L2VPN_HELP_STR
EVPN_HELP_STR
"Display information for a route distinguisher\n"
"VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
{
int idx_ext_community = 6;
int ret;
struct prefix_rd prd;
ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
if (!ret) {
vty_out(vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
return CMD_WARNING;
}
return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 1,
0);
}
DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes,
show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd,
"show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
SHOW_STR
IP_STR
BGP_STR
L2VPN_HELP_STR
EVPN_HELP_STR
"Display information about all EVPN NLRIs\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Display routes learned from neighbor\n" JSON_STR)
{
int idx_ipv4 = 6;
union sockunion su;
struct peer *peer;
int ret;
u_char uj = use_json(argc, argv);
ret = str2sockunion(argv[idx_ipv4]->arg, &su);
if (ret < 0) {
if (uj) {
json_object *json_no = NULL;
json_no = json_object_new_object();
json_object_string_add(json_no, "warning",
"Malformed address");
vty_out(vty, "%s%s",
json_object_to_json_string(json_no),
VTY_NEWLINE);
json_object_free(json_no);
} else
vty_out(vty, "Malformed address: %s%s",
argv[idx_ipv4]->arg, VTY_NEWLINE);
return CMD_WARNING;
}
peer = peer_lookup(NULL, &su);
if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
if (uj) {
json_object *json_no = NULL;
json_no = json_object_new_object();
json_object_string_add(json_no, "warning",
"No such neighbor or address family");
vty_out(vty, "%s%s",
json_object_to_json_string(json_no),
VTY_NEWLINE);
json_object_free(json_no);
} else
vty_out(vty, "%% No such neighbor or address family%s",
VTY_NEWLINE);
return CMD_WARNING;
}
return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_neighbor, &su, 0,
uj);
}
DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd,
"show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes [json]",
SHOW_STR
IP_STR
BGP_STR
L2VPN_HELP_STR
EVPN_HELP_STR
"Display information for a route distinguisher\n"
"VPN Route Distinguisher\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Display routes learned from neighbor\n" JSON_STR)
{
int idx_ext_community = 6;
int idx_ipv4 = 8;
int ret;
union sockunion su;
struct peer *peer;
struct prefix_rd prd;
u_char uj = use_json(argc, argv);
ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
if (!ret) {
if (uj) {
json_object *json_no = NULL;
json_no = json_object_new_object();
json_object_string_add(json_no, "warning",
"Malformed Route Distinguisher");
vty_out(vty, "%s%s",
json_object_to_json_string(json_no),
VTY_NEWLINE);
json_object_free(json_no);
} else
vty_out(vty, "%% Malformed Route Distinguisher%s",
VTY_NEWLINE);
return CMD_WARNING;
}
ret = str2sockunion(argv[idx_ipv4]->arg, &su);
if (ret < 0) {
if (uj) {
json_object *json_no = NULL;
json_no = json_object_new_object();
json_object_string_add(json_no, "warning",
"Malformed address");
vty_out(vty, "%s%s",
json_object_to_json_string(json_no),
VTY_NEWLINE);
json_object_free(json_no);
} else
vty_out(vty, "Malformed address: %s%s",
argv[idx_ext_community]->arg, VTY_NEWLINE);
return CMD_WARNING;
}
peer = peer_lookup(NULL, &su);
if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
if (uj) {
json_object *json_no = NULL;
json_no = json_object_new_object();
json_object_string_add(json_no, "warning",
"No such neighbor or address family");
vty_out(vty, "%s%s",
json_object_to_json_string(json_no),
VTY_NEWLINE);
json_object_free(json_no);
} else
vty_out(vty, "%% No such neighbor or address family%s",
VTY_NEWLINE);
return CMD_WARNING;
}
return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_neighbor, &su, 0,
uj);
}
DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes,
show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd,
"show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
SHOW_STR
IP_STR
BGP_STR
L2VPN_HELP_STR
EVPN_HELP_STR
"Display information about all EVPN NLRIs\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Display the routes advertised to a BGP neighbor\n" JSON_STR)
{
int idx_ipv4 = 7;
int ret;
struct peer *peer;
union sockunion su;
u_char uj = use_json(argc, argv);
ret = str2sockunion(argv[idx_ipv4]->arg, &su);
if (ret < 0) {
if (uj) {
json_object *json_no = NULL;
json_no = json_object_new_object();
json_object_string_add(json_no, "warning",
"Malformed address");
vty_out(vty, "%s%s",
json_object_to_json_string(json_no),
VTY_NEWLINE);
json_object_free(json_no);
} else
vty_out(vty, "Malformed address: %s%s",
argv[idx_ipv4]->arg, VTY_NEWLINE);
return CMD_WARNING;
}
peer = peer_lookup(NULL, &su);
if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
if (uj) {
json_object *json_no = NULL;
json_no = json_object_new_object();
json_object_string_add(json_no, "warning",
"No such neighbor or address family");
vty_out(vty, "%s%s",
json_object_to_json_string(json_no),
VTY_NEWLINE);
json_object_free(json_no);
} else
vty_out(vty, "%% No such neighbor or address family%s",
VTY_NEWLINE);
return CMD_WARNING;
}
return show_adj_route_vpn(vty, peer, NULL, AFI_L2VPN, SAFI_EVPN, uj);
}
DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd,
"show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes [json]",
SHOW_STR
IP_STR
BGP_STR
L2VPN_HELP_STR
EVPN_HELP_STR
"Display information for a route distinguisher\n"
"VPN Route Distinguisher\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Display the routes advertised to a BGP neighbor\n" JSON_STR)
{
int idx_ext_community = 6;
int idx_ipv4 = 8;
int ret;
struct peer *peer;
struct prefix_rd prd;
union sockunion su;
u_char uj = use_json(argc, argv);
ret = str2sockunion(argv[idx_ipv4]->arg, &su);
if (ret < 0) {
if (uj) {
json_object *json_no = NULL;
json_no = json_object_new_object();
json_object_string_add(json_no, "warning",
"Malformed address");
vty_out(vty, "%s%s",
json_object_to_json_string(json_no),
VTY_NEWLINE);
json_object_free(json_no);
} else
vty_out(vty, "Malformed address: %s%s",
argv[idx_ext_community]->arg, VTY_NEWLINE);
return CMD_WARNING;
}
peer = peer_lookup(NULL, &su);
if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
if (uj) {
json_object *json_no = NULL;
json_no = json_object_new_object();
json_object_string_add(json_no, "warning",
"No such neighbor or address family");
vty_out(vty, "%s%s",
json_object_to_json_string(json_no),
VTY_NEWLINE);
json_object_free(json_no);
} else
vty_out(vty, "%% No such neighbor or address family%s",
VTY_NEWLINE);
return CMD_WARNING;
}
ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
if (!ret) {
if (uj) {
json_object *json_no = NULL;
json_no = json_object_new_object();
json_object_string_add(json_no, "warning",
"Malformed Route Distinguisher");
vty_out(vty, "%s%s",
json_object_to_json_string(json_no),
VTY_NEWLINE);
json_object_free(json_no);
} else
vty_out(vty, "%% Malformed Route Distinguisher%s",
VTY_NEWLINE);
return CMD_WARNING;
}
return show_adj_route_vpn(vty, peer, &prd, AFI_L2VPN, SAFI_EVPN, uj);
}
DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay,
show_ip_bgp_l2vpn_evpn_all_overlay_cmd,
"show [ip] bgp l2vpn evpn all overlay",
SHOW_STR
IP_STR
BGP_STR
L2VPN_HELP_STR
EVPN_HELP_STR
"Display information about all EVPN NLRIs\n"
"Display BGP Overlay Information for prefixes\n")
{
return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
SHOW_DISPLAY_OVERLAY, use_json(argc,
argv));
}
DEFUN(show_ip_bgp_evpn_rd_overlay,
show_ip_bgp_evpn_rd_overlay_cmd,
"show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn overlay",
SHOW_STR
IP_STR
BGP_STR
L2VPN_HELP_STR
EVPN_HELP_STR
"Display information for a route distinguisher\n"
"VPN Route Distinguisher\n"
"Display BGP Overlay Information for prefixes\n")
{
int idx_ext_community = 6;
int ret;
struct prefix_rd prd;
ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
if (!ret) {
vty_out(vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
return CMD_WARNING;
}
return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
SHOW_DISPLAY_OVERLAY, use_json(argc,
argv));
}
/* For testing purpose, static route of MPLS-VPN. */
DEFUN(evpnrt5_network,
evpnrt5_network_cmd,
"network <A.B.C.D/M|X:X::X:X/M> rd ASN:nn_or_IP-address:nn ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X> routermac WORD [route-map WORD]",
"Specify a network to announce via BGP\n"
"IP prefix\n"
"IPv6 prefix\n"
"Specify Route Distinguisher\n"
"VPN Route Distinguisher\n"
"Ethernet Tag\n"
"Ethernet Tag Value\n"
"BGP label\n"
"label value\n"
"Ethernet Segment Identifier\n"
"ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
"Gateway IP\n"
"Gateway IP ( A.B.C.D )\n"
"Gateway IPv6 ( X:X::X:X )\n"
"Router Mac Ext Comm\n"
"Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n")
{
int idx_ipv4_prefixlen = 1;
int idx_ext_community = 3;
int idx_word = 7;
int idx_esi = 9;
int idx_gwip = 11;
int idx_ethtag = 5;
int idx_routermac = 13;
int idx_rmap = 15;
return bgp_static_set_safi(SAFI_EVPN, vty,
argv[idx_ipv4_prefixlen]->arg,
argv[idx_ext_community]->arg,
argv[idx_word]->arg,
argv[idx_rmap] ? argv[idx_gwip]->arg : NULL,
EVPN_IP_PREFIX, argv[idx_esi]->arg,
argv[idx_gwip]->arg, argv[idx_ethtag]->arg,
argv[idx_routermac]->arg);
}
/* For testing purpose, static route of MPLS-VPN. */
DEFUN(no_evpnrt5_network,
no_evpnrt5_network_cmd,
"no network <A.B.C.D/M|X:X::X:X/M> rd ASN:nn_or_IP-address:nn ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X>",
NO_STR
"Specify a network to announce via BGP\n"
"IP prefix\n"
"IPv6 prefix\n"
"Specify Route Distinguisher\n"
"VPN Route Distinguisher\n"
"Ethernet Tag\n"
"Ethernet Tag Value\n"
"BGP label\n"
"label value\n"
"Ethernet Segment Identifier\n"
"ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
"Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
{
int idx_ipv4_prefixlen = 2;
int idx_ext_community = 4;
int idx_label = 8;
int idx_ethtag = 6;
int idx_esi = 10;
int idx_gwip = 12;
return bgp_static_unset_safi(SAFI_EVPN, vty,
argv[idx_ipv4_prefixlen]->arg,
argv[idx_ext_community]->arg,
argv[idx_label]->arg, EVPN_IP_PREFIX,
argv[idx_esi]->arg, argv[idx_gwip]->arg,
argv[idx_ethtag]->arg);
}
void bgp_ethernetvpn_init(void)
{
install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
install_element(VIEW_NODE,
&show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd);
install_element(VIEW_NODE,
&show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
install_element(VIEW_NODE,
&show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd);
install_element(VIEW_NODE,
&show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
}

29
bgpd/bgp_evpn_vty.h Normal file
View File

@ -0,0 +1,29 @@
/* EVPN VTY functions to EVPN
Copyright (C) 2017 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 _FRR_BGP_EVPN_VTY_H
#define _FRR_BGP_EVPN_VTY_H
extern void bgp_ethernetvpn_init(void);
#define L2VPN_HELP_STR "Layer 2 Virtual Private Network\n"
#define EVPN_HELP_STR "Ethernet Virtual Private Network\n"
#endif /* _QUAGGA_BGP_EVPN_VTY_H */

View File

@ -36,6 +36,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_packet.h"
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_vpn.h"
#if ENABLE_BGP_VNC
#include "bgpd/rfapi/rfapi_backend.h"
@ -146,7 +147,7 @@ decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip)
#if ENABLE_BGP_VNC
/* type == RD_TYPE_VNC_ETH */
static void
void
decode_rd_vnc_eth (u_char *pnt, struct rd_vnc_eth *rd_vnc_eth)
{
rd_vnc_eth->type = RD_TYPE_VNC_ETH;
@ -288,12 +289,12 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
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. */
@ -470,7 +471,8 @@ DEFUN (vpnv4_network,
int idx_ipv4_prefixlen = 1;
int idx_ext_community = 3;
int idx_word = 5;
return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, NULL);
return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg,
argv[idx_word]->arg, NULL, 0, NULL, NULL, NULL, NULL);
}
DEFUN (vpnv4_network_route_map,
@ -489,7 +491,8 @@ DEFUN (vpnv4_network_route_map,
int idx_ext_community = 3;
int idx_word = 5;
int idx_word_2 = 7;
return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, argv[idx_word_2]->arg);
return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg,
argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL);
}
/* For testing purpose, static route of MPLS-VPN. */
@ -507,7 +510,9 @@ DEFUN (no_vpnv4_network,
int idx_ipv4_prefixlen = 2;
int idx_ext_community = 4;
int idx_word = 6;
return bgp_static_unset_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg);
return bgp_static_unset_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg,
argv[idx_ext_community]->arg, argv[idx_word]->arg,
0, NULL, NULL, NULL);
}
DEFUN (vpnv6_network,
@ -527,9 +532,9 @@ DEFUN (vpnv6_network,
int idx_word = 5;
int idx_word_2 = 7;
if (argv[idx_word_2])
return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, argv[idx_word_2]->arg);
return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL);
else
return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, NULL);
return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, NULL, 0, NULL, NULL, NULL, NULL);
}
/* For testing purpose, static route of MPLS-VPN. */
@ -547,178 +552,9 @@ DEFUN (no_vpnv6_network,
int idx_ipv6_prefix = 2;
int idx_ext_community = 4;
int idx_word = 6;
return bgp_static_unset_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg);
return bgp_static_unset_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, 0, NULL, NULL, NULL);
}
#if defined(KEEP_OLD_VPN_COMMANDS)
static int
show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd, u_char use_json, afi_t afi)
{
struct bgp *bgp;
struct bgp_table *table;
struct bgp_node *rn;
struct bgp_node *rm;
struct attr *attr;
int rd_header;
int header = 1;
char v4_header[] = " Network Next Hop Metric LocPrf Weight Path%s";
json_object *json = NULL;
json_object *json_scode = NULL;
json_object *json_ocode = NULL;
json_object *json_routes = NULL;
json_object *json_array = NULL;
bgp = bgp_get_default ();
if (bgp == NULL)
{
if (!use_json)
vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (use_json)
{
json_scode = json_object_new_object();
json_ocode = json_object_new_object();
json_routes = json_object_new_object();
json = json_object_new_object();
json_object_string_add(json_scode, "suppressed", "s");
json_object_string_add(json_scode, "damped", "d");
json_object_string_add(json_scode, "history", "h");
json_object_string_add(json_scode, "valid", "*");
json_object_string_add(json_scode, "best", ">");
json_object_string_add(json_scode, "internal", "i");
json_object_string_add(json_ocode, "igp", "i");
json_object_string_add(json_ocode, "egp", "e");
json_object_string_add(json_ocode, "incomplete", "?");
}
for (rn = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); rn;
rn = bgp_route_next (rn))
{
if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
continue;
if ((table = rn->info) != NULL)
{
if (use_json)
json_array = json_object_new_array();
else
json_array = NULL;
rd_header = 1;
for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
{
if ((attr = rm->info) != NULL)
{
if (header)
{
if (use_json)
{
json_object_int_add(json, "bgpTableVersion", 0);
json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id));
json_object_object_add(json, "bgpStatusCodes", json_scode);
json_object_object_add(json, "bgpOriginCodes", json_ocode);
}
else
{
vty_out (vty, "BGP table version is 0, local router ID is %s%s",
inet_ntoa (bgp->router_id), VTY_NEWLINE);
vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
VTY_NEWLINE);
vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
VTY_NEWLINE, VTY_NEWLINE);
vty_out (vty, v4_header, VTY_NEWLINE);
}
header = 0;
}
if (rd_header)
{
u_int16_t type;
struct rd_as rd_as;
struct rd_ip rd_ip = {0};
#if ENABLE_BGP_VNC
struct rd_vnc_eth rd_vnc_eth = {0};
#endif
u_char *pnt;
pnt = rn->p.u.val;
/* Decode RD type. */
type = decode_rd_type (pnt);
/* Decode RD value. */
if (type == RD_TYPE_AS)
decode_rd_as (pnt + 2, &rd_as);
else if (type == RD_TYPE_AS4)
decode_rd_as4 (pnt + 2, &rd_as);
else if (type == RD_TYPE_IP)
decode_rd_ip (pnt + 2, &rd_ip);
#if ENABLE_BGP_VNC
else if (type == RD_TYPE_VNC_ETH)
decode_rd_vnc_eth (pnt, &rd_vnc_eth);
#endif
if (use_json)
{
char buffer[BUFSIZ];
if (type == RD_TYPE_AS || type == RD_TYPE_AS4)
sprintf (buffer, "%u:%d", rd_as.as, rd_as.val);
else if (type == RD_TYPE_IP)
sprintf (buffer, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
json_object_string_add(json_routes, "routeDistinguisher", buffer);
}
else
{
vty_out (vty, "Route Distinguisher: ");
if (type == RD_TYPE_AS || type == RD_TYPE_AS4)
vty_out (vty, "%u:%d", rd_as.as, rd_as.val);
else if (type == RD_TYPE_IP)
vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
#if ENABLE_BGP_VNC
else if (type == RD_TYPE_VNC_ETH)
vty_out (vty, "%u:%02x:%02x:%02x:%02x:%02x:%02x",
rd_vnc_eth.local_nve_id,
rd_vnc_eth.macaddr.octet[0],
rd_vnc_eth.macaddr.octet[1],
rd_vnc_eth.macaddr.octet[2],
rd_vnc_eth.macaddr.octet[3],
rd_vnc_eth.macaddr.octet[4],
rd_vnc_eth.macaddr.octet[5]);
#endif
vty_out (vty, "%s", VTY_NEWLINE);
}
rd_header = 0;
}
route_vty_out_tmp (vty, &rm->p, attr, SAFI_MPLS_VPN, use_json, json_array);
}
}
if (use_json)
{
struct prefix *p;
char buf_a[BUFSIZ];
char buf_b[BUFSIZ];
p = &rm->p;
sprintf(buf_a, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf_b, BUFSIZ), p->prefixlen);
json_object_object_add(json_routes, buf_a, json_array);
}
}
}
if (use_json)
{
json_object_object_add(json, "routes", json_routes);
vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
json_object_free(json);
}
return CMD_SUCCESS;
}
#endif
int
bgp_show_mpls_vpn (struct vty *vty, afi_t afi, struct prefix_rd *prd,
enum bgp_show_type type, void *output_arg, int tags, u_char use_json)
@ -1281,8 +1117,7 @@ DEFUN (show_ip_bgp_vpn_all_neighbor_advertised_routes,
vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
return CMD_WARNING;
}
return show_adj_route_vpn (vty, peer, NULL, uj, afi);
return show_adj_route_vpn (vty, peer, NULL, AFI_IP, SAFI_MPLS_VPN, uj);
}
return CMD_SUCCESS;
}
@ -1360,7 +1195,7 @@ DEFUN (show_ip_bgp_vpn_rd_neighbor_advertised_routes,
return CMD_WARNING;
}
return show_adj_route_vpn (vty, peer, &prd, uj, afi);
return show_adj_route_vpn (vty, peer, &prd, AFI_IP, SAFI_MPLS_VPN, uj);
}
return CMD_SUCCESS;
}

View File

@ -100,7 +100,8 @@ extern void decode_rd_as (u_char *, struct rd_as *);
extern void decode_rd_as4 (u_char *, struct rd_as *);
extern void decode_rd_ip (u_char *, struct rd_ip *);
#if ENABLE_BGP_VNC
extern void decode_vnc_eth (u_char *, struct rd_vnc_eth *);
extern void
decode_rd_vnc_eth (u_char *pnt, struct rd_vnc_eth *rd_vnc_eth);
#endif
extern int str2prefix_rd (const char *, struct prefix_rd *);
extern int str2tag (const char *, u_char *);

View File

@ -93,6 +93,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
case AFI_IP6:
json_object_string_add(json_cap, "capabilityErrorMultiProtocolAfi", "IPv6");
break;
case AFI_L2VPN:
json_object_string_add(json_cap, "capabilityErrorMultiProtocolAfi", "L2VPN");
break;
default:
json_object_int_add(json_cap, "capabilityErrorMultiProtocolAfiUnknown", ntohs (mpc.afi));
break;
@ -111,6 +114,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
case SAFI_ENCAP:
json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "encap");
break;
case SAFI_EVPN:
json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "EVPN");
break;
default:
json_object_int_add(json_cap, "capabilityErrorMultiProtocolSafiUnknown", mpc.safi);
break;
@ -127,6 +133,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
case AFI_IP6:
vty_out (vty, "AFI IPv6, ");
break;
case AFI_L2VPN:
vty_out (vty, "AFI L2VPN, ");
break;
default:
vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi));
break;
@ -145,6 +154,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
case SAFI_ENCAP:
vty_out (vty, "SAFI ENCAP");
break;
case SAFI_EVPN:
vty_out (vty, "SAFI EVPN");
break;
default:
vty_out (vty, "SAFI Unknown %d ", mpc.safi);
break;
@ -1136,7 +1148,8 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
&& ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
&& ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
&& ! peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
&& ! peer->afc_nego[AFI_IP6][SAFI_ENCAP])
&& ! peer->afc_nego[AFI_IP6][SAFI_ENCAP]
&& ! peer->afc_nego[AFI_L2VPN][SAFI_EVPN])
{
zlog_err ("%s [Error] Configured AFI/SAFIs do not "
"overlap with received MP capabilities",

View File

@ -49,7 +49,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#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_evpn.h"
#include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_updgrp.h"
@ -246,13 +248,13 @@ bgp_write_packet (struct peer *peer)
if (!(PAF_SUBGRP(paf))->t_coalesce &&
peer->afc_nego[afi][safi] && peer->synctime
&& ! CHECK_FLAG (peer->af_sflags[afi][safi],
PEER_STATUS_EOR_SEND))
PEER_STATUS_EOR_SEND)
&& safi != SAFI_EVPN)
{
SET_FLAG (peer->af_sflags[afi][safi],
PEER_STATUS_EOR_SEND);
return bgp_update_packet_eor (peer, afi, safi);
}
}
continue;
}
@ -1327,19 +1329,24 @@ bgp_update_explicit_eors (struct peer *peer)
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;
}
@ -1531,11 +1538,11 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
{
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;

View File

@ -55,7 +55,7 @@ extern void bgp_default_withdraw_send (struct peer *, afi_t, safi_t);
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 *);

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgp_table.h"
struct bgp_nexthop_cache;
struct bgp_route_evpn;
enum bgp_show_type
{
@ -93,7 +94,7 @@ struct bgp_info_extra
struct in6_addr addr6;
} un; /* cached un address */
time_t create_time;
struct prefix aux_prefix; /* AFI_ETHER: the IP addr, if family set */
struct prefix aux_prefix; /* AFI_L2VPN: the IP addr, if family set */
} import;
} vnc;
@ -202,6 +203,12 @@ struct bgp_static
/* MPLS label. */
u_char tag[3];
/* EVPN */
struct eth_segment_id *eth_s_id;
struct ethaddr *router_mac;
uint16_t encap_tunneltype;
struct prefix gatewayIp;
};
#define BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen) \
@ -312,17 +319,20 @@ extern void bgp_static_update (struct bgp *, struct prefix *, struct bgp_static
extern void bgp_static_withdraw (struct bgp *, struct prefix *, afi_t, safi_t);
extern int bgp_static_set_safi (safi_t safi, struct vty *vty, const char *,
const char *, const char *, const char *);
const char *, const char *, const char *,
int, const char *, const char *, const char *, const char *);
extern int bgp_static_unset_safi (safi_t safi, struct vty *, const char *,
const char *, const char *);
const char *, const char *,
int, const char *, const char *, const char *);
/* 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);
@ -350,6 +360,9 @@ extern safi_t bgp_node_safi (struct vty *);
extern void route_vty_out (struct vty *, struct prefix *, struct bgp_info *, int, safi_t, json_object *);
extern void route_vty_out_tag (struct vty *, struct prefix *, struct bgp_info *, int, safi_t, json_object *);
extern void route_vty_out_tmp (struct vty *, struct prefix *, struct attr *, safi_t, u_char, json_object *);
extern void
route_vty_out_overlay (struct vty *vty, struct prefix *p,
struct bgp_info *binfo, int display, json_object *json);
extern int
subgroup_process_announce_selected (struct update_subgroup *subgrp,

View File

@ -605,6 +605,7 @@ subgroup_announce_table (struct update_subgroup *subgrp,
if (safi != SAFI_MPLS_VPN
&& safi != SAFI_ENCAP
&& safi != SAFI_EVPN
&& CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
subgroup_default_originate (subgrp, 0);
@ -668,7 +669,8 @@ subgroup_announce_route (struct update_subgroup *subgrp)
return;
if (SUBGRP_SAFI (subgrp) != SAFI_MPLS_VPN &&
SUBGRP_SAFI (subgrp) != SAFI_ENCAP)
SUBGRP_SAFI (subgrp) != SAFI_ENCAP &&
SUBGRP_SAFI (subgrp) != SAFI_EVPN)
subgroup_announce_table (subgrp, NULL);
else
for (rn = bgp_table_top (update_subgroup_rib (subgrp)); rn;

View File

@ -53,6 +53,7 @@
#include "bgpd/bgp_updgrp.h"
#include "bgpd/bgp_nexthop.h"
#include "bgpd/bgp_nht.h"
#include "bgpd/bgp_mplsvpn.h"
/********************
* PRIVATE FUNCTIONS
@ -617,6 +618,7 @@ static void
bgp_info_addpath_tx_str (int addpath_encode, u_int32_t addpath_tx_id,
char *buf)
{
buf[0] = '\0';
if (addpath_encode)
sprintf(buf, " with addpath ID %d", addpath_tx_id);
}
@ -648,6 +650,7 @@ subgroup_update_packet (struct update_subgroup *subgrp)
int num_pfx = 0;
int addpath_encode = 0;
u_int32_t addpath_tx_id = 0;
struct prefix_rd *prd = NULL;
if (!subgrp)
return NULL;
@ -751,7 +754,6 @@ subgroup_update_packet (struct update_subgroup *subgrp)
else
{
/* Encode the prefix in MP_REACH_NLRI attribute */
struct prefix_rd *prd = NULL;
u_char *tag = NULL;
if (rn->prn)
@ -764,16 +766,16 @@ subgroup_update_packet (struct update_subgroup *subgrp)
(peer_cap_enhe(peer) ? AFI_IP6 :
AFI_MAX), /* get from NH */
&vecarr, adv->baa->attr);
bgp_packet_mpattr_prefix (snlri, afi, safi, &rn->p, prd, tag,
addpath_encode, addpath_tx_id);
bgp_packet_mpattr_prefix (snlri, afi, safi, &rn->p, prd,
tag, addpath_encode, addpath_tx_id, adv->baa->attr);
}
num_pfx++;
if (bgp_debug_update(NULL, &rn->p, subgrp->update_group, 0))
{
char buf[INET6_BUFSIZ];
char tx_id_buf[30];
char pfx_buf[BGP_PRD_PATH_STRLEN];
if (!send_attr_printed)
{
@ -782,11 +784,11 @@ subgroup_update_packet (struct update_subgroup *subgrp)
send_attr_printed = 1;
}
bgp_info_addpath_tx_str (addpath_encode, addpath_tx_id, tx_id_buf);
zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s/%d%s",
zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s",
subgrp->update_group->id, subgrp->id,
inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
rn->p.prefixlen, tx_id_buf);
bgp_debug_rdpfxpath2str (prd, &rn->p, addpath_encode,
addpath_tx_id,
pfx_buf, sizeof (pfx_buf)));
}
/* Synchnorize attribute. */
@ -863,6 +865,8 @@ subgroup_withdraw_packet (struct update_subgroup *subgrp)
int num_pfx = 0;
int addpath_encode = 0;
u_int32_t addpath_tx_id = 0;
struct prefix_rd *prd = NULL;
if (!subgrp)
return NULL;
@ -905,8 +909,6 @@ subgroup_withdraw_packet (struct update_subgroup *subgrp)
stream_put_prefix_addpath (s, &rn->p, addpath_encode, addpath_tx_id);
else
{
struct prefix_rd *prd = NULL;
if (rn->prn)
prd = (struct prefix_rd *) &rn->prn->p;
@ -921,20 +923,20 @@ subgroup_withdraw_packet (struct update_subgroup *subgrp)
}
bgp_packet_mpunreach_prefix (s, &rn->p, afi, safi, prd, NULL,
addpath_encode, addpath_tx_id);
addpath_encode, addpath_tx_id, NULL);
}
num_pfx++;
if (bgp_debug_update(NULL, &rn->p, subgrp->update_group, 0))
{
char buf[INET6_BUFSIZ];
char tx_id_buf[30];
bgp_info_addpath_tx_str (addpath_encode, addpath_tx_id, tx_id_buf);
zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s/%d%s -- unreachable",
char pfx_buf[BGP_PRD_PATH_STRLEN];
zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s -- unreachable",
subgrp->update_group->id, subgrp->id,
inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
rn->p.prefixlen, tx_id_buf);
bgp_debug_rdpfxpath2str (prd, &rn->p,
addpath_encode, addpath_tx_id,
pfx_buf, sizeof (pfx_buf)));
}
subgrp->scount--;
@ -1010,16 +1012,16 @@ subgroup_default_update_packet (struct update_subgroup *subgrp,
if (bgp_debug_update(NULL, &p, subgrp->update_group, 0))
{
char attrstr[BUFSIZ];
char buf[INET6_BUFSIZ];
char buf[PREFIX_STRLEN];
char tx_id_buf[30];
attrstr[0] = '\0';
bgp_dump_attr (peer, attr, attrstr, BUFSIZ);
bgp_info_addpath_tx_str (addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE, tx_id_buf);
zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s/%d%s %s",
zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s %s",
(SUBGRP_UPDGRP (subgrp))->id, subgrp->id,
inet_ntop (p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
p.prefixlen, tx_id_buf, attrstr);
prefix2str (&p, buf, sizeof (buf)),
tx_id_buf, attrstr);
}
s = stream_new (BGP_MAX_PACKET_SIZE);
@ -1084,14 +1086,13 @@ subgroup_default_withdraw_packet (struct update_subgroup *subgrp)
if (bgp_debug_update(NULL, &p, subgrp->update_group, 0))
{
char buf[INET6_BUFSIZ];
char buf[PREFIX_STRLEN];
char tx_id_buf[INET6_BUFSIZ];
bgp_info_addpath_tx_str (addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE, tx_id_buf);
zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s/%d%s -- unreachable",
zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s -- unreachable",
(SUBGRP_UPDGRP (subgrp))->id, subgrp->id,
inet_ntop (p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
p.prefixlen, tx_id_buf);
prefix2str (&p, buf, sizeof (buf)), tx_id_buf);
}
s = stream_new (BGP_MAX_PACKET_SIZE);
@ -1126,7 +1127,7 @@ subgroup_default_withdraw_packet (struct update_subgroup *subgrp)
mplen_pos = bgp_packet_mpunreach_start (s, afi, safi);
bgp_packet_mpunreach_prefix (s, &p, afi, safi, NULL, NULL,
addpath_encode,
BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE, NULL);
/* Set the mp_unreach attr's length */
bgp_packet_mpunreach_end (s, mplen_pos);

200
bgpd/bgp_vpn.c Normal file
View File

@ -0,0 +1,200 @@
/* VPN Related functions
Copyright (C) 2017 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 "prefix.h"
#include "lib/json.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_vpn.h"
int
show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd,
afi_t afi, safi_t safi, u_char use_json)
{
struct bgp *bgp;
struct bgp_table *table;
struct bgp_node *rn;
struct bgp_node *rm;
struct attr *attr;
int rd_header;
int header = 1;
char v4_header[] = " Network Next Hop Metric LocPrf Weight Path%s";
json_object *json = NULL;
json_object *json_scode = NULL;
json_object *json_ocode = NULL;
json_object *json_routes = NULL;
json_object *json_array = NULL;
bgp = bgp_get_default ();
if (bgp == NULL)
{
if (!use_json)
vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (use_json)
{
json_scode = json_object_new_object();
json_ocode = json_object_new_object();
json_routes = json_object_new_object();
json = json_object_new_object();
json_object_string_add(json_scode, "suppressed", "s");
json_object_string_add(json_scode, "damped", "d");
json_object_string_add(json_scode, "history", "h");
json_object_string_add(json_scode, "valid", "*");
json_object_string_add(json_scode, "best", ">");
json_object_string_add(json_scode, "internal", "i");
json_object_string_add(json_ocode, "igp", "i");
json_object_string_add(json_ocode, "egp", "e");
json_object_string_add(json_ocode, "incomplete", "?");
}
for (rn = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); rn;
rn = bgp_route_next (rn))
{
if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
continue;
if ((table = rn->info) != NULL)
{
if (use_json)
json_array = json_object_new_array();
else
json_array = NULL;
rd_header = 1;
for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
{
if ((attr = rm->info) != NULL)
{
if (header)
{
if (use_json)
{
json_object_int_add(json, "bgpTableVersion", 0);
json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id));
json_object_object_add(json, "bgpStatusCodes", json_scode);
json_object_object_add(json, "bgpOriginCodes", json_ocode);
}
else
{
vty_out (vty, "BGP table version is 0, local router ID is %s%s",
inet_ntoa (bgp->router_id), VTY_NEWLINE);
vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
VTY_NEWLINE);
vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
VTY_NEWLINE, VTY_NEWLINE);
vty_out (vty, v4_header, VTY_NEWLINE);
}
header = 0;
}
if (rd_header)
{
u_int16_t type;
struct rd_as rd_as;
struct rd_ip rd_ip = {0};
#if ENABLE_BGP_VNC
struct rd_vnc_eth rd_vnc_eth = {0};
#endif
u_char *pnt;
pnt = rn->p.u.val;
/* Decode RD type. */
type = decode_rd_type (pnt);
/* Decode RD value. */
if (type == RD_TYPE_AS)
decode_rd_as (pnt + 2, &rd_as);
else if (type == RD_TYPE_AS4)
decode_rd_as4 (pnt + 2, &rd_as);
else if (type == RD_TYPE_IP)
decode_rd_ip (pnt + 2, &rd_ip);
#if ENABLE_BGP_VNC
else if (type == RD_TYPE_VNC_ETH)
decode_rd_vnc_eth (pnt, &rd_vnc_eth);
#endif
if (use_json)
{
char buffer[BUFSIZ];
if (type == RD_TYPE_AS || type == RD_TYPE_AS4)
sprintf (buffer, "%u:%d", rd_as.as, rd_as.val);
else if (type == RD_TYPE_IP)
sprintf (buffer, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
json_object_string_add(json_routes, "routeDistinguisher", buffer);
}
else
{
vty_out (vty, "Route Distinguisher: ");
if (type == RD_TYPE_AS || type == RD_TYPE_AS4)
vty_out (vty, "%u:%d", rd_as.as, rd_as.val);
else if (type == RD_TYPE_IP)
vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
#if ENABLE_BGP_VNC
else if (type == RD_TYPE_VNC_ETH)
vty_out (vty, "%u:%02x:%02x:%02x:%02x:%02x:%02x",
rd_vnc_eth.local_nve_id,
rd_vnc_eth.macaddr.octet[0],
rd_vnc_eth.macaddr.octet[1],
rd_vnc_eth.macaddr.octet[2],
rd_vnc_eth.macaddr.octet[3],
rd_vnc_eth.macaddr.octet[4],
rd_vnc_eth.macaddr.octet[5]);
#endif
vty_out (vty, "%s", VTY_NEWLINE);
}
rd_header = 0;
}
route_vty_out_tmp (vty, &rm->p, attr, SAFI_MPLS_VPN, use_json, json_array);
}
}
if (use_json)
{
struct prefix *p;
char buf_a[BUFSIZ];
char buf_b[BUFSIZ];
p = &rm->p;
sprintf(buf_a, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf_b, BUFSIZ), p->prefixlen);
json_object_object_add(json_routes, buf_a, json_array);
}
}
}
if (use_json)
{
json_object_object_add(json, "routes", json_routes);
vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
json_object_free(json);
}
return CMD_SUCCESS;
}

30
bgpd/bgp_vpn.h Normal file
View File

@ -0,0 +1,30 @@
/* VPN common functions to MP-BGP
Copyright (C) 2017 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 _FRR_BGP_VPN_H
#define _FRR_BGP_VPN_H
#include <zebra.h>
extern int
show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd,
afi_t afi, safi_t safi, u_char use_json);
#endif /* _QUAGGA_BGP_VPN_H */

View File

@ -74,6 +74,9 @@ bgp_node_afi (struct vty *vty)
case BGP_ENCAPV6_NODE:
afi = AFI_IP6;
break;
case BGP_EVPN_NODE:
afi = AFI_L2VPN;
break;
default:
afi = AFI_IP;
break;
@ -101,6 +104,9 @@ bgp_node_safi (struct vty *vty)
case BGP_IPV6M_NODE:
safi = SAFI_MULTICAST;
break;
case BGP_EVPN_NODE:
safi = SAFI_EVPN;
break;
default:
safi = SAFI_UNICAST;
break;
@ -119,6 +125,9 @@ bgp_vty_afi_from_arg(const char *afi_str)
else if (!strcmp(afi_str, "ipv6")) {
afi = AFI_IP6;
}
else if (!strcmp(afi_str, "l2vpn")) {
afi = AFI_L2VPN;
}
return afi;
}
@ -195,6 +204,12 @@ argv_find_and_parse_safi (struct cmd_token **argv, int argc, int *index, safi_t
if (safi)
*safi = SAFI_ENCAP;
}
else if (argv_find (argv, argc, "evpn", index))
{
ret = 1;
if (safi)
*safi = SAFI_EVPN;
}
return ret;
}
@ -5695,6 +5710,18 @@ DEFUN (address_family_encapv6,
return CMD_SUCCESS;
}
DEFUN (address_family_evpn,
address_family_evpn_cmd,
"address-family <l2vpn evpn>",
"Enter Address Family command mode\n"
"EVPN Address family\n"
"Layer2 VPN Address family\n"
"Ethernet Virtual Private Network Subsequent Address Family\n")
{
vty->node = BGP_EVPN_NODE;
return CMD_SUCCESS;
}
DEFUN (exit_address_family,
exit_address_family_cmd,
"exit-address-family",
@ -5707,7 +5734,8 @@ DEFUN (exit_address_family,
|| vty->node == BGP_IPV6M_NODE
|| vty->node == BGP_VPNV6_NODE
|| vty->node == BGP_ENCAP_NODE
|| vty->node == BGP_ENCAPV6_NODE)
|| vty->node == BGP_ENCAPV6_NODE
|| vty->node == BGP_EVPN_NODE)
vty->node = BGP_NODE;
return CMD_SUCCESS;
}
@ -6662,7 +6690,7 @@ bgp_show_summary_afi_safi (struct vty *vty, struct bgp *bgp, int afi, int safi,
}
afi++;
if (! afi_wildcard ||
afi == AFI_ETHER) /* special case, not handled yet */
afi == AFI_L2VPN) /* special case, not handled yet */
afi = AFI_MAX;
}
@ -6806,6 +6834,8 @@ afi_safi_print (afi_t afi, safi_t safi)
return "IPv6 VPN";
else if (afi == AFI_IP6 && safi == SAFI_ENCAP)
return "IPv6 Encap";
else if (afi == AFI_L2VPN && safi == SAFI_EVPN)
return "L2VPN EVPN";
else
return "Unknown";
}
@ -6829,6 +6859,8 @@ afi_safi_json (afi_t afi, safi_t safi)
return "IPv6VPN";
else if (afi == AFI_IP6 && safi == SAFI_ENCAP)
return "IPv6Encap";
else if (afi == AFI_L2VPN && safi == SAFI_EVPN)
return "L2VPN EVPN";
else
return "Unknown";
}
@ -9966,6 +9998,13 @@ static struct cmd_node bgp_encapv6_node =
1
};
static struct cmd_node bgp_evpn_node =
{
BGP_EVPN_NODE,
"%s(config-router-evpn)# ",
1
};
static void community_list_vty (void);
void
@ -9981,6 +10020,7 @@ bgp_vty_init (void)
install_node (&bgp_vpnv6_node, NULL);
install_node (&bgp_encap_node, NULL);
install_node (&bgp_encapv6_node, NULL);
install_node (&bgp_evpn_node, NULL);
/* Install default VTY commands to new nodes. */
install_default (BGP_NODE);
@ -9992,6 +10032,7 @@ bgp_vty_init (void)
install_default (BGP_VPNV6_NODE);
install_default (BGP_ENCAP_NODE);
install_default (BGP_ENCAPV6_NODE);
install_default (BGP_EVPN_NODE);
/* "bgp multiple-instance" commands. */
install_element (CONFIG_NODE, &bgp_multiple_instance_cmd);
@ -10205,6 +10246,7 @@ bgp_vty_init (void)
install_element (BGP_VPNV6_NODE, &neighbor_activate_cmd);
install_element (BGP_ENCAP_NODE, &neighbor_activate_cmd);
install_element (BGP_ENCAPV6_NODE, &neighbor_activate_cmd);
install_element (BGP_EVPN_NODE, &neighbor_activate_cmd);
/* "no neighbor activate" commands. */
install_element (BGP_NODE, &no_neighbor_activate_cmd);
@ -10216,6 +10258,7 @@ bgp_vty_init (void)
install_element (BGP_VPNV6_NODE, &no_neighbor_activate_cmd);
install_element (BGP_ENCAP_NODE, &no_neighbor_activate_cmd);
install_element (BGP_ENCAPV6_NODE, &no_neighbor_activate_cmd);
install_element (BGP_EVPN_NODE, &no_neighbor_activate_cmd);
/* "neighbor peer-group" set commands.
* Long term we should only accept this command under BGP_NODE and not all of
@ -10286,6 +10329,9 @@ bgp_vty_init (void)
install_element (BGP_ENCAPV6_NODE, &neighbor_attr_unchanged_cmd);
install_element (BGP_ENCAPV6_NODE, &no_neighbor_attr_unchanged_cmd);
install_element (BGP_EVPN_NODE, &neighbor_attr_unchanged_cmd);
install_element (BGP_EVPN_NODE, &no_neighbor_attr_unchanged_cmd);
/* "nexthop-local unchanged" commands */
install_element (BGP_IPV6_NODE, &neighbor_nexthop_local_unchanged_cmd);
install_element (BGP_IPV6_NODE, &no_neighbor_nexthop_local_unchanged_cmd);
@ -10828,6 +10874,8 @@ bgp_vty_init (void)
install_element (BGP_NODE, &address_family_encap_cmd);
install_element (BGP_NODE, &address_family_encapv6_cmd);
install_element (BGP_NODE, &address_family_evpn_cmd);
/* "exit-address-family" command. */
install_element (BGP_IPV4_NODE, &exit_address_family_cmd);
install_element (BGP_IPV4M_NODE, &exit_address_family_cmd);
@ -10837,6 +10885,7 @@ bgp_vty_init (void)
install_element (BGP_VPNV6_NODE, &exit_address_family_cmd);
install_element (BGP_ENCAP_NODE, &exit_address_family_cmd);
install_element (BGP_ENCAPV6_NODE, &exit_address_family_cmd);
install_element (BGP_EVPN_NODE, &exit_address_family_cmd);
/* "clear ip bgp commands" */
install_element (ENABLE_NODE, &clear_ip_bgp_all_cmd);

View File

@ -66,6 +66,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#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"
@ -77,6 +78,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_updgrp.h"
#include "bgpd/bgp_bfd.h"
#include "bgpd/bgp_memory.h"
#include "bgpd/bgp_evpn_vty.h"
DEFINE_QOBJ_TYPE(bgp_master)
DEFINE_QOBJ_TYPE(bgp)
@ -1643,6 +1645,8 @@ peer_as_change (struct peer *peer, as_t as, int as_specified)
PEER_FLAG_REFLECTOR_CLIENT);
UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP],
PEER_FLAG_REFLECTOR_CLIENT);
UNSET_FLAG (peer->af_flags[AFI_L2VPN][SAFI_EVPN],
PEER_FLAG_REFLECTOR_CLIENT);
}
/* local-as reset */
@ -7217,7 +7221,11 @@ bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
else if (safi == SAFI_ENCAP)
vty_out (vty, "ipv6 encap");
}
else if (afi == AFI_L2VPN)
{
if (safi == SAFI_EVPN)
vty_out (vty, "l2vpn evpn");
}
vty_out (vty, "%s", VTY_NEWLINE);
*write = 1;
@ -7518,6 +7526,9 @@ bgp_config_write (struct vty *vty)
/* ENCAPv6 configuration. */
write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP);
/* EVPN configuration. */
write += bgp_config_write_family (vty, bgp, AFI_L2VPN, SAFI_EVPN);
#if ENABLE_BGP_VNC
write += bgp_rfapi_cfg_write(vty, bgp);
#endif
@ -7615,6 +7626,7 @@ bgp_init (void)
#if ENABLE_BGP_VNC
rfapi_init ();
#endif
bgp_ethernetvpn_init ();
/* Access list initialize. */
access_list_init ();

View File

@ -73,6 +73,7 @@ enum bgp_af_index
BGP_AF_IPV6_VPN,
BGP_AF_IPV4_ENCAP,
BGP_AF_IPV6_ENCAP,
BGP_AF_L2VPN_EVPN,
BGP_AF_MAX
};
@ -1414,6 +1415,16 @@ afindex (afi_t afi, safi_t safi)
break;
}
break;
case AFI_L2VPN:
switch (safi)
{
case SAFI_EVPN:
return BGP_AF_L2VPN_EVPN;
break;
default:
return BGP_AF_MAX;
break;
}
default:
return BGP_AF_MAX;
break;

View File

@ -4352,7 +4352,7 @@ bgp_rfapi_cfg_write (struct vty *vty, struct bgp *bgp)
ecommunity_cmp (rfg->rt_import_list, rfg->rt_export_list))
{
char *b = ecommunity_ecom2str (rfg->rt_import_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET);
vty_out (vty, " rt both %s%s", b, VTY_NEWLINE);
XFREE (MTYPE_ECOMMUNITY_STR, b);
}
@ -4361,14 +4361,14 @@ bgp_rfapi_cfg_write (struct vty *vty, struct bgp *bgp)
if (rfg->rt_import_list)
{
char *b = ecommunity_ecom2str (rfg->rt_import_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET);
vty_out (vty, " rt import %s%s", b, VTY_NEWLINE);
XFREE (MTYPE_ECOMMUNITY_STR, b);
}
if (rfg->rt_export_list)
{
char *b = ecommunity_ecom2str (rfg->rt_export_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET);
vty_out (vty, " rt export %s%s", b, VTY_NEWLINE);
XFREE (MTYPE_ECOMMUNITY_STR, b);
}
@ -4483,7 +4483,7 @@ bgp_rfapi_cfg_write (struct vty *vty, struct bgp *bgp)
ecommunity_cmp (rfg->rt_import_list, rfg->rt_export_list))
{
char *b = ecommunity_ecom2str (rfg->rt_import_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET);
vty_out (vty, " rt both %s%s", b, VTY_NEWLINE);
XFREE (MTYPE_ECOMMUNITY_STR, b);
}
@ -4492,14 +4492,14 @@ bgp_rfapi_cfg_write (struct vty *vty, struct bgp *bgp)
if (rfg->rt_import_list)
{
char *b = ecommunity_ecom2str (rfg->rt_import_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET);
vty_out (vty, " rt import %s%s", b, VTY_NEWLINE);
XFREE (MTYPE_ECOMMUNITY_STR, b);
}
if (rfg->rt_export_list)
{
char *b = ecommunity_ecom2str (rfg->rt_export_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET);
vty_out (vty, " rt export %s%s", b, VTY_NEWLINE);
XFREE (MTYPE_ECOMMUNITY_STR, b);
}
@ -4570,7 +4570,7 @@ bgp_rfapi_cfg_write (struct vty *vty, struct bgp *bgp)
hc->default_rt_export_list))
{
char *b = ecommunity_ecom2str (hc->default_rt_import_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET);
vty_out (vty, " rt both %s%s", b, VTY_NEWLINE);
XFREE (MTYPE_ECOMMUNITY_STR, b);
}
@ -4579,14 +4579,14 @@ bgp_rfapi_cfg_write (struct vty *vty, struct bgp *bgp)
if (hc->default_rt_import_list)
{
char *b = ecommunity_ecom2str (hc->default_rt_import_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET);
vty_out (vty, " rt import %s%s", b, VTY_NEWLINE);
XFREE (MTYPE_ECOMMUNITY_STR, b);
}
if (hc->default_rt_export_list)
{
char *b = ecommunity_ecom2str (hc->default_rt_export_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET);
vty_out (vty, " rt export %s%s", b, VTY_NEWLINE);
XFREE (MTYPE_ECOMMUNITY_STR, b);
}
@ -4685,7 +4685,8 @@ bgp_rfapi_cfg_write (struct vty *vty, struct bgp *bgp)
ecommunity_cmp (rfg->rt_import_list, rfg->rt_export_list))
{
char *b = ecommunity_ecom2str (rfg->rt_import_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP,
ECOMMUNITY_ROUTE_TARGET);
vty_out (vty, " rt both %s%s", b, VTY_NEWLINE);
XFREE (MTYPE_ECOMMUNITY_STR, b);
}
@ -4694,14 +4695,15 @@ bgp_rfapi_cfg_write (struct vty *vty, struct bgp *bgp)
if (rfg->rt_import_list)
{
char *b = ecommunity_ecom2str (rfg->rt_import_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP,
ECOMMUNITY_ROUTE_TARGET);
vty_out (vty, " rt import %s%s", b, VTY_NEWLINE);
XFREE (MTYPE_ECOMMUNITY_STR, b);
}
if (rfg->rt_export_list)
{
char *b = ecommunity_ecom2str (rfg->rt_export_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET);
vty_out (vty, " rt export %s%s", b, VTY_NEWLINE);
XFREE (MTYPE_ECOMMUNITY_STR, b);
}

View File

@ -1451,7 +1451,7 @@ rfapi_open_inner (
#define RFD_RTINIT(rh, ary) do {\
RFD_RTINIT_AFI(rh, ary, AFI_IP);\
RFD_RTINIT_AFI(rh, ary, AFI_IP6);\
RFD_RTINIT_AFI(rh, ary, AFI_ETHER);\
RFD_RTINIT_AFI(rh, ary, AFI_L2VPN);\
} while(0)
RFD_RTINIT(rfd, rfd->rib);
@ -1733,7 +1733,7 @@ rfapi_query_inner (
__func__, rfd, buf, ppNextHopEntry);
s = ecommunity_ecom2str(rfd->import_table->rt_import_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
vnc_zlog_debug_verbose("%s rfd->import_table=%p, rfd->import_table->rt_import_list: %s",
__func__, rfd->import_table, s); XFREE (MTYPE_ECOMMUNITY_STR, s);
}
@ -3809,7 +3809,7 @@ DEFUN (debug_rfapi_show_import,
for (it = h->imports; it; it = it->next)
{
s = ecommunity_ecom2str (it->rt_import_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
vty_out (vty, "Import Table %p, RTs: %s%s", it, s, VTY_NEWLINE);
XFREE (MTYPE_ECOMMUNITY_STR, s);
@ -3835,7 +3835,7 @@ DEFUN (debug_rfapi_show_import,
&cursor))
{
if (it->imported_vpn[AFI_ETHER])
if (it->imported_vpn[AFI_L2VPN])
{
lni = lni_as_ptr;
if (first_l2)
@ -3845,7 +3845,7 @@ DEFUN (debug_rfapi_show_import,
first_l2 = 0;
}
snprintf (buf, BUFSIZ, "L2VPN LNI=%u", lni);
rfapiShowImportTable (vty, buf, it->imported_vpn[AFI_ETHER], 1);
rfapiShowImportTable (vty, buf, it->imported_vpn[AFI_L2VPN], 1);
}
}
}

View File

@ -1091,8 +1091,8 @@ rfapiEcommunitiesIntersect (struct ecommunity *e1, struct ecommunity *e2)
{
char *s1, *s2;
s1 = ecommunity_ecom2str (e1, ECOMMUNITY_FORMAT_DISPLAY);
s2 = ecommunity_ecom2str (e2, ECOMMUNITY_FORMAT_DISPLAY);
s1 = ecommunity_ecom2str (e1, ECOMMUNITY_FORMAT_DISPLAY, 0);
s2 = ecommunity_ecom2str (e2, ECOMMUNITY_FORMAT_DISPLAY, 0);
vnc_zlog_debug_verbose ("%s: e1[%s], e2[%s]", __func__, s1, s2);
XFREE (MTYPE_ECOMMUNITY_STR, s1);
XFREE (MTYPE_ECOMMUNITY_STR, s2);
@ -2077,7 +2077,7 @@ rfapiEthRouteTable2NextHopList (
it = rfapiMacImportTableGet (bgp, logical_net_id);
rt = it->imported_vpn[AFI_ETHER];
rt = it->imported_vpn[AFI_L2VPN];
for (rn = route_top (rt); rn; rn = route_next (rn))
{
@ -3607,7 +3607,7 @@ rfapiBgpInfoFilteredImportVPN (
struct peer *peer,
void *rfd, /* set for looped back routes */
struct prefix *p,
struct prefix *aux_prefix, /* AFI_ETHER: optional IP */
struct prefix *aux_prefix, /* AFI_L2VPN: optional IP */
afi_t afi,
struct prefix_rd *prd,
struct attr *attr, /* part of bgp_info */
@ -3702,7 +3702,7 @@ rfapiBgpInfoFilteredImportVPN (
{
case AFI_IP:
case AFI_IP6:
case AFI_ETHER:
case AFI_L2VPN:
rt = import_table->imported_vpn[afi];
break;
@ -3909,7 +3909,7 @@ rfapiBgpInfoFilteredImportVPN (
* For ethernet routes, if there is an accompanying IP address,
* save it in the bi
*/
if ((AFI_ETHER == afi) && aux_prefix)
if ((AFI_L2VPN == afi) && aux_prefix)
{
vnc_zlog_debug_verbose ("%s: setting BI's aux_prefix", __func__);
@ -4178,7 +4178,7 @@ rfapiProcessUpdate (
rfd,
&pfx_mac_buf, /* prefix */
p, /* aux prefix: IP addr */
AFI_ETHER,
AFI_L2VPN,
prd,
attr,
type,
@ -4291,7 +4291,7 @@ rfapiProcessWithdraw (
#if DEBUG_L2_EXTRA
vnc_zlog_debug_verbose
("%s: calling rfapiBgpInfoFilteredImportVPN(it=%p, afi=AFI_ETHER)",
("%s: calling rfapiBgpInfoFilteredImportVPN(it=%p, afi=AFI_L2VPN)",
__func__, it);
#endif
@ -4302,7 +4302,7 @@ rfapiProcessWithdraw (
rfd,
&pfx_mac_buf, /* prefix */
p, /* aux_prefix: IP */
AFI_ETHER,
AFI_L2VPN,
prd,
attr,
type,
@ -4808,7 +4808,7 @@ rfapiDeleteRemotePrefixesIt (
vnc_zlog_debug_verbose ("%s: rn pfx=%s", __func__, buf_pfx);
}
/* TBD is this valid for afi == AFI_ETHER? */
/* TBD is this valid for afi == AFI_L2VPN? */
RFAPI_CHECK_REFCOUNT (rn, SAFI_MPLS_VPN, 1);
for (bi = rn->info; bi; bi = next)
@ -5166,10 +5166,10 @@ rfapiCountAllItRoutes (int *pALRcount, /* active local routes */
rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor))
{
total_active_local += it->local_count[AFI_ETHER];
total_active_remote += it->remote_count[AFI_ETHER];
total_holddown += it->holddown_count[AFI_ETHER];
total_imported += it->imported_count[AFI_ETHER];
total_active_local += it->local_count[AFI_L2VPN];
total_active_remote += it->remote_count[AFI_L2VPN];
total_holddown += it->holddown_count[AFI_L2VPN];
total_imported += it->imported_count[AFI_L2VPN];
}
}

View File

@ -941,7 +941,7 @@ rfapiMonitorItNodeChanged (
__func__, import_table, it_node, buf_prefix);
#endif
if (AFI_ETHER == afi)
if (AFI_L2VPN == afi)
{
struct rfapi_monitor_eth *m;
struct skiplist *sl;
@ -1044,7 +1044,7 @@ rfapiMonitorItNodeChanged (
/*
* All-routes L2 monitors
*/
if (AFI_ETHER == afi)
if (AFI_L2VPN == afi)
{
struct rfapi_monitor_eth *e;
@ -1305,7 +1305,7 @@ rfapiMonitorEthAttachImportHd (struct bgp *bgp, struct rfapi_descriptor *rfd)
pfx_mac_buf.prefixlen = 48;
pfx_mac_buf.u.prefix_eth = mon->macaddr;
rn = route_node_get (it->imported_vpn[AFI_ETHER], &pfx_mac_buf);
rn = route_node_get (it->imported_vpn[AFI_L2VPN], &pfx_mac_buf);
assert (rn);
(void) rfapiMonitorEthAttachImport (it, rn, mon);
@ -1361,7 +1361,7 @@ rfapiMonitorEthDetachImport (
pfx_mac_buf.prefixlen = 48;
pfx_mac_buf.u.prefix_eth = mon->macaddr;
rn = route_node_get (it->imported_vpn[AFI_ETHER], &pfx_mac_buf);
rn = route_node_get (it->imported_vpn[AFI_L2VPN], &pfx_mac_buf);
assert (rn);
#if DEBUG_L2_EXTRA
@ -1423,7 +1423,7 @@ rfapiMonitorEthAdd (
if (!RFAPI_0_ETHERADDR (macaddr))
{
rn = route_node_get (it->imported_vpn[AFI_ETHER], &pfx_mac_buf);
rn = route_node_get (it->imported_vpn[AFI_L2VPN], &pfx_mac_buf);
assert (rn);
}
@ -1635,7 +1635,7 @@ rfapiMonitorCallbacksOff (struct bgp *bgp)
/*
* The actual route table
*/
rt = it->imported_vpn[AFI_ETHER];
rt = it->imported_vpn[AFI_L2VPN];
/*
* Find non-0 monitors (i.e., actual addresses, not FTD monitors)

View File

@ -133,7 +133,7 @@ struct rfapi_descriptor
uint32_t flags;
#define RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_IP 0x00000001
#define RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_IP6 0x00000002
#define RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_ETHER 0x00000004
#define RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_L2VPN 0x00000004
#define RFAPI_HD_FLAG_PROVISIONAL 0x00000008
#define RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY 0x00000010
#define RFAPI_HD_FLAG_IS_VRF 0x00000012
@ -142,7 +142,7 @@ struct rfapi_descriptor
#define RFAPI_QUEUED_FLAG(afi) ( \
((afi) == AFI_IP)? RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_IP: \
(((afi) == AFI_IP6)? RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_IP6: \
(((afi) == AFI_ETHER)? RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_ETHER: \
(((afi) == AFI_L2VPN)? RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_L2VPN: \
(assert(0), 0) )))

View File

@ -916,7 +916,7 @@ process_pending_node (
vnc_zlog_debug_verbose ("%s: afi=%d, %s pn->info=%p",
__func__, afi, buf_prefix, pn->info);
if (AFI_ETHER != afi)
if (AFI_L2VPN != afi)
{
rfapiQprefix2Rprefix (&pn->p, &hp);
}
@ -1246,7 +1246,7 @@ callback:
else
{
new->prefix = hp;
if (AFI_ETHER == afi)
if (AFI_L2VPN == afi)
{
/* hp is 0; need to set length to match AF of vn */
new->prefix.length =
@ -1334,7 +1334,7 @@ callback:
else
{
new->prefix = hp;
if (AFI_ETHER == afi)
if (AFI_L2VPN == afi)
{
/* hp is 0; need to set length to match AF of vn */
new->prefix.length =
@ -1976,7 +1976,7 @@ rfapiRibPreload (
continue;
}
afi = AFI_ETHER;
afi = AFI_L2VPN;
rfapiL2o2Qprefix (pL2o, &pfx);
}
else
@ -2181,7 +2181,7 @@ rfapiRibPendingDeleteRoute (
vnc_zlog_debug_verbose ("%s: entry, it=%p, afi=%d, it_node=%p, pfx=%s",
__func__, it, afi, it_node, buf);
if (AFI_ETHER == afi)
if (AFI_L2VPN == afi)
{
/*
* ethernet import tables are per-LNI and each ethernet monitor

View File

@ -472,7 +472,7 @@ rfapi_vty_out_vncinfo (
if (bi->attr && bi->attr->extra && bi->attr->extra->ecommunity)
{
s = ecommunity_ecom2str (bi->attr->extra->ecommunity,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
vty_out (vty, " EC{%s}", s);
XFREE (MTYPE_ECOMMUNITY_STR, s);
}
@ -676,7 +676,7 @@ rfapiPrintBi (void *stream, struct bgp_info *bi)
if (bi->attr->extra->ecommunity)
{
s = ecommunity_ecom2str (bi->attr->extra->ecommunity,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
r = snprintf (p, REMAIN, " %s", s);
INCP;
XFREE (MTYPE_ECOMMUNITY_STR, s);
@ -1329,7 +1329,7 @@ rfapiShowRemoteRegistrationsIt (
int show_local,
int show_remote,
int show_imported, /* either/or */
uint32_t *pLni) /* AFI_ETHER only */
uint32_t *pLni) /* AFI_L2VPN only */
{
afi_t afi;
int printed_rtlist_hdr = 0;
@ -1433,7 +1433,7 @@ rfapiShowRemoteRegistrationsIt (
}
s = ecommunity_ecom2str (it->rt_import_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
if (pLni)
{
@ -1807,7 +1807,7 @@ rfapiPrintDescriptor (struct vty *vty, struct rfapi_descriptor *rfd)
{
s =
ecommunity_ecom2str (rfd->rt_export_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
vty_out (vty, " Export %s%s", s, HVTY_NEWLINE);
XFREE (MTYPE_ECOMMUNITY_STR, s);
}
@ -1820,7 +1820,7 @@ rfapiPrintDescriptor (struct vty *vty, struct rfapi_descriptor *rfd)
if (rfd->import_table)
{
s = ecommunity_ecom2str (rfd->import_table->rt_import_list,
ECOMMUNITY_FORMAT_ROUTE_MAP);
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
vty_out (vty, " Import %s%s", s, HVTY_NEWLINE);
XFREE (MTYPE_ECOMMUNITY_STR, s);
}

View File

@ -340,7 +340,7 @@ vnc_direct_bgp_add_route_ce (
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);
}
@ -425,7 +425,7 @@ vnc_direct_bgp_del_route_ce (
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 */
}
@ -534,7 +534,7 @@ vnc_direct_bgp_vpn_disable_ce (struct bgp *bgp, afi_t afi)
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 */
}
}
}
@ -911,7 +911,7 @@ vnc_direct_bgp_add_prefix (
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);
}
@ -1011,7 +1011,7 @@ vnc_direct_bgp_del_prefix (
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 */
}
}
}
@ -1150,7 +1150,7 @@ vnc_direct_bgp_add_nve (struct bgp *bgp, struct rfapi_descriptor *rfd)
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);
@ -1250,7 +1250,7 @@ vnc_direct_bgp_del_nve (struct bgp *bgp, struct rfapi_descriptor *rfd)
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 */
}
}
@ -1377,7 +1377,7 @@ vnc_direct_bgp_add_group_afi (
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);
}
@ -1462,7 +1462,7 @@ vnc_direct_bgp_del_group_afi (
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 */
}
}
@ -1540,7 +1540,7 @@ vnc_direct_bgp_unexport_table (
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 */
}
}
@ -1777,8 +1777,8 @@ vnc_direct_bgp_rh_add_route (
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);
}
@ -1801,7 +1801,7 @@ vncExportWithdrawTimer (struct thread *t)
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
@ -2019,8 +2019,8 @@ vnc_direct_bgp_rh_vpn_enable (struct bgp *bgp, afi_t afi)
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);
}
}
@ -2085,7 +2085,7 @@ vnc_direct_bgp_rh_vpn_disable (struct bgp *bgp, afi_t afi)
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 */
}
}
}

View File

@ -1055,6 +1055,7 @@ node_parent ( enum node_type node )
case BGP_IPV4M_NODE:
case BGP_IPV6_NODE:
case BGP_IPV6M_NODE:
case BGP_EVPN_NODE:
ret = BGP_NODE;
break;
case KEYCHAIN_KEY_NODE:
@ -1421,6 +1422,7 @@ cmd_exit (struct vty *vty)
case BGP_VNC_L2_GROUP_NODE:
case BGP_IPV6_NODE:
case BGP_IPV6M_NODE:
case BGP_EVPN_NODE:
vty->node = BGP_NODE;
break;
case LDP_IPV4_NODE:
@ -1489,6 +1491,7 @@ DEFUN (config_end,
case BGP_IPV4M_NODE:
case BGP_IPV6_NODE:
case BGP_IPV6M_NODE:
case BGP_EVPN_NODE:
case RMAP_NODE:
case OSPF_NODE:
case OSPF6_NODE:

View File

@ -105,6 +105,7 @@ enum node_type
BGP_VNC_NVE_GROUP_NODE, /* BGP VNC nve group */
BGP_VNC_L2_GROUP_NODE, /* BGP VNC L2 group */
RFP_DEFAULTS_NODE, /* RFP defaults node */
BGP_EVPN_NODE, /* BGP EVPN node. */
OSPF_NODE, /* OSPF protocol mode */
OSPF6_NODE, /* OSPF protocol for IPv6 mode */
LDP_NODE, /* LDP protocol mode */

View File

@ -972,7 +972,7 @@ vty_prefix_list_install (struct vty *vty, afi_t afi, const char *name,
apply_mask_ipv6 ((struct prefix_ipv6 *) &p_tmp);
break;
case AFI_ETHER:
case AFI_L2VPN:
default:
vty_out (vty, "%% Unrecognized AFI (%d)%s", afi, VTY_NEWLINE);
return CMD_WARNING;

View File

@ -209,7 +209,7 @@ afi2family (afi_t afi)
return AF_INET;
else if (afi == AFI_IP6)
return AF_INET6;
else if (afi == AFI_ETHER)
else if (afi == AFI_L2VPN)
return AF_ETHERNET;
return 0;
}
@ -222,7 +222,7 @@ family2afi (int family)
else if (family == AF_INET6)
return AFI_IP6;
else if (family == AF_ETHERNET)
return AFI_ETHER;
return AFI_L2VPN;
return 0;
}
@ -234,8 +234,8 @@ afi2str(afi_t afi)
return "IPv4";
case AFI_IP6:
return "IPv6";
case AFI_ETHER:
return "ethernet";
case AFI_L2VPN:
return "l2vpn";
case AFI_MAX:
return "bad-value";
default:
@ -256,6 +256,8 @@ safi2str(safi_t safi)
return "encap";
case SAFI_MPLS_VPN:
return "vpn";
case SAFI_EVPN:
return "evpn";
}
return NULL;
}
@ -300,15 +302,15 @@ prefix_copy (struct prefix *dest, const struct prefix *src)
dest->u.prefix4 = src->u.prefix4;
else if (src->family == AF_INET6)
dest->u.prefix6 = src->u.prefix6;
else if (src->family == AF_ETHERNET)
{
memcpy (&dest->u.prefix_evpn, &src->u.prefix_evpn, sizeof (struct evpn_addr));
}
else if (src->family == AF_UNSPEC)
{
dest->u.lp.id = src->u.lp.id;
dest->u.lp.adv_router = src->u.lp.adv_router;
}
else if (src->family == AF_ETHERNET)
{
dest->u.prefix_eth = src->u.prefix_eth;
}
else
{
zlog (NULL, LOG_ERR, "prefix_copy(): Unknown address family %d",
@ -342,10 +344,9 @@ prefix_same (const struct prefix *p1, const struct prefix *p2)
if (p1->family == AF_INET6 )
if (IPV6_ADDR_SAME (&p1->u.prefix6.s6_addr, &p2->u.prefix6.s6_addr))
return 1;
if (p1->family == AF_ETHERNET) {
if (!memcmp(p1->u.prefix_eth.octet, p2->u.prefix_eth.octet, ETHER_ADDR_LEN))
return 1;
}
if (p1->family == AF_ETHERNET )
if (!memcmp (&p1->u.prefix_evpn, &p2->u.prefix_evpn, sizeof (struct evpn_addr)))
return 1;
}
return 0;
}
@ -408,6 +409,9 @@ prefix_common_bits (const struct prefix *p1, const struct prefix *p2)
length = IPV4_MAX_BYTELEN;
if (p1->family == AF_INET6)
length = IPV6_MAX_BYTELEN;
if (p1->family == AF_ETHERNET)
length = 8 * sizeof (struct evpn_addr);
if (p1->family != p2->family || !length)
return -1;
@ -849,23 +853,46 @@ str2prefix (const char *str, struct prefix *p)
}
const char *
prefix2str (union prefix46constptr pu, char *str, int size)
prefix2str (union prefixconstptr pu, char *str, int size)
{
const struct prefix *p = pu.p;
char buf[PREFIX2STR_BUFFER];
if (p->family == AF_ETHERNET)
switch (p->family)
{
snprintf(str, size, "%02x:%02x:%02x:%02x:%02x:%02x/%d",
p->u.prefix_eth.octet[0], p->u.prefix_eth.octet[1],
p->u.prefix_eth.octet[2], p->u.prefix_eth.octet[3],
p->u.prefix_eth.octet[4], p->u.prefix_eth.octet[5],
p->prefixlen);
}
else
{
char buf[PREFIX2STR_BUFFER];
inet_ntop(p->family, &p->u.prefix, buf, sizeof(buf));
snprintf(str, size, "%s/%d", buf, p->prefixlen);
case AF_INET:
case AF_INET6:
snprintf (str, size, "%s/%d",
inet_ntop (p->family, &p->u.prefix, buf, PREFIX2STR_BUFFER),
p->prefixlen);
break;
case AF_ETHERNET:
if (p->u.prefix_evpn.route_type == 5)
{
u_char family;
family = (p->u.prefix_evpn.flags & (IP_ADDR_V4 | IP_PREFIX_V4)) ?
AF_INET : AF_INET6;
snprintf (str, size, "[%d]:[%u][%s]/%d",
p->u.prefix_evpn.route_type,
p->u.prefix_evpn.eth_tag,
inet_ntop (family, &p->u.prefix_evpn.ip.addr,
buf, PREFIX2STR_BUFFER),
p->prefixlen);
}
else
{
sprintf (str, "UNK AF_ETHER prefix");
snprintf(str, size, "%02x:%02x:%02x:%02x:%02x:%02x/%d",
p->u.prefix_eth.octet[0], p->u.prefix_eth.octet[1],
p->u.prefix_eth.octet[2], p->u.prefix_eth.octet[3],
p->u.prefix_eth.octet[4], p->u.prefix_eth.octet[5],
p->prefixlen);
}
break;
default:
sprintf (str, "UNK prefix");
break;
}
return str;

View File

@ -49,9 +49,45 @@
*/
struct ethaddr {
u_char octet[ETHER_ADDR_LEN];
} __packed;
} __attribute__ ((packed));
/* length is the number of valuable bits of prefix structure
* 18 bytes is current length in structure, if address is ipv4
* 30 bytes is in case of ipv6
*/
#define PREFIX_LEN_ROUTE_TYPE_5_IPV4 (18*8)
#define PREFIX_LEN_ROUTE_TYPE_5_IPV6 (30*8)
/* EVPN address (RFC 7432) */
struct evpn_addr
{
u_char route_type;
u_char flags;
#define IP_ADDR_NONE 0x0
#define IP_ADDR_V4 0x1
#define IP_ADDR_V6 0x2
#define IP_PREFIX_V4 0x4
#define IP_PREFIX_V6 0x8
struct ethaddr mac;
uint32_t eth_tag;
u_char ip_prefix_length;
union
{
u_char addr;
struct in_addr v4_addr;
struct in6_addr v6_addr;
} ip;
};
/* EVPN prefix structure. */
struct prefix_evpn
{
u_char family;
u_char prefixlen;
struct evpn_addr prefix __attribute__ ((aligned (8)));
};
/*
* A struct prefix contains an address family, a prefix length, and an
* address. This can represent either a 'network prefix' as defined
@ -88,6 +124,7 @@ struct prefix
struct ethaddr prefix_eth; /* AF_ETHERNET */
u_char val[8];
uintptr_t ptr;
struct evpn_addr prefix_evpn;
} u __attribute__ ((aligned (8)));
};
@ -152,18 +189,20 @@ struct prefix_sg
* side, which strips type safety since the cast will accept any pointer
* type.)
*/
union prefix46ptr
union prefixptr
{
struct prefix *p;
struct prefix_ipv4 *p4;
struct prefix_ipv6 *p6;
struct prefix_evpn *evp;
} __attribute__ ((transparent_union));
union prefix46constptr
union prefixconstptr
{
const struct prefix *p;
const struct prefix_ipv4 *p4;
const struct prefix_ipv6 *p6;
const struct prefix_evpn *evp;
} __attribute__ ((transparent_union));
#ifndef INET_ADDRSTRLEN
@ -237,7 +276,7 @@ extern int str2prefix (const char *, struct prefix *);
#define PREFIX2STR_BUFFER PREFIX_STRLEN
extern const char *prefix2str (union prefix46constptr, char *, int);
extern const char *prefix2str (union prefixconstptr, char *, int);
extern int prefix_match (const struct prefix *, const struct prefix *);
extern int prefix_same (const struct prefix *, const struct prefix *);
extern int prefix_cmp (const struct prefix *, const struct prefix *);

View File

@ -242,7 +242,7 @@ srcdest_route_next(struct route_node *rn)
}
struct route_node *
srcdest_rnode_get (struct route_table *table, union prefix46ptr dst_pu,
srcdest_rnode_get (struct route_table *table, union prefixptr dst_pu,
struct prefix_ipv6 *src_p)
{
struct prefix_ipv6 *dst_p = dst_pu.p6;
@ -253,7 +253,7 @@ srcdest_rnode_get (struct route_table *table, union prefix46ptr dst_pu,
}
struct route_node *
srcdest_rnode_lookup (struct route_table *table, union prefix46ptr dst_pu,
srcdest_rnode_lookup (struct route_table *table, union prefixptr dst_pu,
struct prefix_ipv6 *src_p)
{
struct prefix_ipv6 *dst_p = dst_pu.p6;

View File

@ -57,10 +57,10 @@ extern route_table_delegate_t _srcdest_srcnode_delegate;
extern struct route_table *srcdest_table_init(void);
extern struct route_node *srcdest_rnode_get(struct route_table *table,
union prefix46ptr dst_pu,
union prefixptr dst_pu,
struct prefix_ipv6 *src_p);
extern struct route_node *srcdest_rnode_lookup(struct route_table *table,
union prefix46ptr dst_pu,
union prefixptr dst_pu,
struct prefix_ipv6 *src_p);
extern void srcdest_rnode_prefixes (struct route_node *rn, struct prefix **p,
struct prefix **src_p);

View File

@ -750,6 +750,7 @@ vty_end_config (struct vty *vty)
case BGP_IPV4M_NODE:
case BGP_IPV6_NODE:
case BGP_IPV6M_NODE:
case BGP_EVPN_NODE:
case RMAP_NODE:
case OSPF_NODE:
case OSPF6_NODE:

View File

@ -401,8 +401,8 @@ extern const char *zserv_command_string (unsigned int command);
typedef enum {
AFI_IP = 1,
AFI_IP6 = 2,
AFI_ETHER = 3, /* RFC 1700 has "6" for 802.* */
AFI_MAX = 4
AFI_L2VPN = 4,
AFI_MAX = 5
} afi_t;
/* Subsequent Address Family Identifier. */
@ -412,7 +412,8 @@ typedef enum {
#define SAFI_RESERVED_4 4
#define SAFI_ENCAP 5
#define SAFI_RESERVED_5 5
#define SAFI_MAX 6
#define SAFI_EVPN 6
#define SAFI_MAX 7
#define IANA_SAFI_RESERVED 0
#define IANA_SAFI_UNICAST 1
@ -442,6 +443,7 @@ typedef enum {
#define IANA_SAFI_UNICAST 1
#define IANA_SAFI_MULTICAST 2
#define IANA_SAFI_ENCAP 7
#define IANA_SAFI_EVPN 70
#define IANA_SAFI_MPLS_VPN 128
/* Default Administrative Distance of each protocol. */
@ -482,6 +484,8 @@ static inline afi_t afi_iana2int (iana_afi_t afi)
return AFI_IP;
if (afi == IANA_AFI_IPV6)
return AFI_IP6;
if (afi == IANA_AFI_L2VPN)
return AFI_L2VPN;
return AFI_MAX;
}
@ -491,6 +495,8 @@ static inline iana_afi_t afi_int2iana (afi_t afi)
return IANA_AFI_IPV4;
if (afi == AFI_IP6)
return IANA_AFI_IPV6;
if (afi == AFI_L2VPN)
return IANA_AFI_L2VPN;
return IANA_AFI_RESERVED;
}
@ -504,6 +510,8 @@ static inline safi_t safi_iana2int (safi_t safi)
return SAFI_MPLS_VPN;
if (safi == IANA_SAFI_ENCAP)
return SAFI_ENCAP;
if (safi == IANA_SAFI_EVPN)
return SAFI_EVPN;
return SAFI_MAX;
}
@ -517,6 +525,8 @@ static inline safi_t safi_int2iana (safi_t safi)
return IANA_SAFI_MPLS_VPN;
if (safi == SAFI_ENCAP)
return IANA_SAFI_ENCAP;
if (safi == SAFI_EVPN)
return IANA_SAFI_EVPN;
return IANA_SAFI_RESERVED;
}

View File

@ -97,10 +97,10 @@ validate (struct ecommunity *ecom, const struct test_spec *sp)
char *str1, *str2;
printf ("got:\n %s\n", ecommunity_str (ecom));
str1 = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_COMMUNITY_LIST);
str1 = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_COMMUNITY_LIST, 0);
etmp = ecommunity_str2com (str1, 0, 1);
if (etmp)
str2 = ecommunity_ecom2str (etmp, ECOMMUNITY_FORMAT_COMMUNITY_LIST);
str2 = ecommunity_ecom2str (etmp, ECOMMUNITY_FORMAT_COMMUNITY_LIST, 0);
else
str2 = NULL;

View File

@ -725,11 +725,10 @@ parse_test (struct peer *peer, struct test_segment *t, int type)
if (!parse_ret)
{
if (type == BGP_ATTR_MP_REACH_NLRI)
nlri_ret = bgp_nlri_parse (peer, &attr, &nlri);
nlri_ret = bgp_nlri_parse (peer, &attr, &nlri, 0);
else
nlri_ret = bgp_nlri_parse (peer, NULL, &nlri);
nlri_ret = bgp_nlri_parse (peer, &attr, &nlri, 1);
}
zlog_err("xxxxxxxxxxxxxxxx nlri ret %u", nlri_ret);
handle_result (peer, t, parse_ret, nlri_ret);
}

View File

@ -307,7 +307,7 @@ vtysh_execute_func (const char *line, int pager)
|| saved_node == BGP_ENCAP_NODE || saved_node == BGP_ENCAPV6_NODE
|| saved_node == BGP_IPV4_NODE
|| saved_node == BGP_IPV6_NODE || saved_node == BGP_IPV4M_NODE
|| saved_node == BGP_IPV6M_NODE)
|| saved_node == BGP_IPV6M_NODE || saved_node == BGP_EVPN_NODE)
&& (tried == 1))
{
vtysh_execute("exit-address-family");
@ -561,7 +561,8 @@ vtysh_mark_file (const char *filename)
{
if ((prev_node == BGP_VPNV4_NODE || prev_node == BGP_IPV4_NODE
|| prev_node == BGP_IPV6_NODE || prev_node == BGP_IPV4M_NODE
|| prev_node == BGP_IPV6M_NODE || prev_node == BGP_VPNV6_NODE)
|| prev_node == BGP_IPV6M_NODE || prev_node == BGP_VPNV6_NODE
|| prev_node == BGP_EVPN_NODE)
&& (tried == 1))
{
fprintf(stdout, "exit-address-family\n");
@ -956,6 +957,12 @@ static struct cmd_node bgp_ipv6m_node =
"%s(config-router-af)# "
};
static struct cmd_node bgp_evpn_node =
{
BGP_EVPN_NODE,
"%s(config-router-af)# "
};
static struct cmd_node bgp_vnc_defaults_node =
{
BGP_VNC_DEFAULTS_NODE,
@ -1203,6 +1210,21 @@ DEFUNSH (VTYSH_BGPD,
return CMD_SUCCESS;
}
DEFUNSH (VTYSH_BGPD,
address_family_evpn,
address_family_evpn_cmd,
"address-family <l2vpn evpn>",
"Enter Address Family command mode\n"
"EVPN Address family\n"
"Layer2 VPN Address family\n"
"Ethernet Virtual Private Network Subsequent Address Family\n")
{
#if defined(HAVE_EVPN)
vty->node = BGP_EVPN_NODE;
#endif /* HAVE_EVPN */
return CMD_SUCCESS;
}
#if defined (ENABLE_BGP_VNC)
DEFUNSH (VTYSH_BGPD,
vnc_defaults,
@ -1511,6 +1533,7 @@ vtysh_exit (struct vty *vty)
case BGP_IPV6_NODE:
case BGP_IPV6M_NODE:
case BGP_VRF_POLICY_NODE:
case BGP_EVPN_NODE:
case BGP_VNC_DEFAULTS_NODE:
case BGP_VNC_NVE_GROUP_NODE:
case BGP_VNC_L2_GROUP_NODE:
@ -3114,6 +3137,7 @@ vtysh_init_vty (void)
install_node (&bgp_ipv6_node, NULL);
install_node (&bgp_ipv6m_node, NULL);
install_node (&bgp_vrf_policy_node, NULL);
install_node (&bgp_evpn_node, NULL);
install_node (&bgp_vnc_defaults_node, NULL);
install_node (&bgp_vnc_nve_group_node, NULL);
install_node (&bgp_vnc_l2_group_node, NULL);
@ -3150,6 +3174,7 @@ vtysh_init_vty (void)
vtysh_install_default (BGP_IPV4M_NODE);
vtysh_install_default (BGP_IPV6_NODE);
vtysh_install_default (BGP_IPV6M_NODE);
vtysh_install_default (BGP_EVPN_NODE);
#if ENABLE_BGP_VNC
vtysh_install_default (BGP_VRF_POLICY_NODE);
vtysh_install_default (BGP_VNC_DEFAULTS_NODE);
@ -3222,6 +3247,7 @@ vtysh_init_vty (void)
install_element (BGP_IPV6_NODE, &vtysh_quit_bgpd_cmd);
install_element (BGP_IPV6M_NODE, &vtysh_exit_bgpd_cmd);
install_element (BGP_IPV6M_NODE, &vtysh_quit_bgpd_cmd);
install_element (BGP_EVPN_NODE, &vtysh_quit_bgpd_cmd);
#if defined (ENABLE_BGP_VNC)
install_element (BGP_VRF_POLICY_NODE, &vtysh_exit_bgpd_cmd);
install_element (BGP_VRF_POLICY_NODE, &vtysh_quit_bgpd_cmd);
@ -3267,6 +3293,7 @@ vtysh_init_vty (void)
install_element (BGP_IPV6_NODE, &vtysh_end_all_cmd);
install_element (BGP_IPV6M_NODE, &vtysh_end_all_cmd);
install_element (BGP_VRF_POLICY_NODE, &vtysh_end_all_cmd);
install_element (BGP_EVPN_NODE, &vtysh_end_all_cmd);
install_element (BGP_VNC_DEFAULTS_NODE, &vtysh_end_all_cmd);
install_element (BGP_VNC_NVE_GROUP_NODE, &vtysh_end_all_cmd);
install_element (BGP_VNC_L2_GROUP_NODE, &vtysh_end_all_cmd);
@ -3322,6 +3349,7 @@ vtysh_init_vty (void)
#endif
install_element (BGP_NODE, &address_family_ipv4_unicast_cmd);
install_element (BGP_NODE, &address_family_ipv6_cmd);
install_element (BGP_NODE, &address_family_evpn_cmd);
install_element (BGP_VPNV4_NODE, &exit_address_family_cmd);
install_element (BGP_VPNV6_NODE, &exit_address_family_cmd);
install_element (BGP_ENCAP_NODE, &exit_address_family_cmd);
@ -3330,6 +3358,7 @@ vtysh_init_vty (void)
install_element (BGP_IPV4M_NODE, &exit_address_family_cmd);
install_element (BGP_IPV6_NODE, &exit_address_family_cmd);
install_element (BGP_IPV6M_NODE, &exit_address_family_cmd);
install_element (BGP_EVPN_NODE, &exit_address_family_cmd);
install_element (BGP_VRF_POLICY_NODE, &exit_vrf_policy_cmd);
install_element (BGP_VNC_DEFAULTS_NODE, &exit_vnc_config_cmd);

View File

@ -314,8 +314,8 @@ extern void rib_lookup_and_dump (struct prefix_ipv4 *, vrf_id_t);
extern void rib_lookup_and_pushup (struct prefix_ipv4 *, vrf_id_t);
#define rib_dump(prefix, src, rib) _rib_dump(__func__, prefix, src, rib)
extern void _rib_dump (const char *,
union prefix46constptr,
union prefix46constptr, const struct rib *);
union prefixconstptr,
union prefixconstptr, const struct rib *);
extern int rib_lookup_ipv4_route (struct prefix_ipv4 *, union sockunion *,
vrf_id_t);
#define ZEBRA_RIB_LOOKUP_ERROR -1

View File

@ -2135,8 +2135,8 @@ rib_delnode (struct route_node *rn, struct rib *rib)
*/
void _rib_dump (const char * func,
union prefix46constptr pp,
union prefix46constptr src_pp,
union prefixconstptr pp,
union prefixconstptr src_pp,
const struct rib * rib)
{
const struct prefix *p = pp.p;