Merge pull request #809 from donaldsharp/evpn_plus_struct_attr

Evpn plus struct attr
This commit is contained in:
Russ White 2017-07-14 09:36:31 -04:00 committed by GitHub
commit 805d1ca6b0
81 changed files with 13420 additions and 2123 deletions

View File

@ -83,7 +83,7 @@ libbgp_a_SOURCES = \
bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.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_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \
bgp_encap_tlv.c $(BGP_VNC_RFAPI_SRC) bgp_attr_evpn.c \ bgp_encap_tlv.c $(BGP_VNC_RFAPI_SRC) bgp_attr_evpn.c \
bgp_evpn.c bgp_evpn_vty.c bgp_vpn.c bgp_label.c bgp_evpn.c bgp_evpn_vty.c bgp_vpn.c bgp_label.c bgp_rd.c
noinst_HEADERS = \ noinst_HEADERS = \
bgp_memory.h \ bgp_memory.h \
@ -95,7 +95,7 @@ noinst_HEADERS = \
bgp_advertise.h bgp_vty.h bgp_mpath.h bgp_nht.h \ bgp_advertise.h bgp_vty.h bgp_mpath.h bgp_nht.h \
bgp_updgrp.h bgp_bfd.h bgp_encap_tlv.h bgp_encap_types.h \ bgp_updgrp.h bgp_bfd.h bgp_encap_tlv.h bgp_encap_types.h \
$(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h bgp_evpn_vty.h \ $(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h bgp_evpn_vty.h \
bgp_vpn.h bgp_label.h bgp_vpn.h bgp_label.h bgp_rd.h bgp_evpn_private.h
bgpd_SOURCES = bgp_main.c bgpd_SOURCES = bgp_main.c
bgpd_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@ bgpd_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@

File diff suppressed because it is too large Load Diff

View File

@ -98,12 +98,34 @@ struct overlay_index
union gw_addr gw_ip; union gw_addr gw_ip;
}; };
/* Additional/uncommon BGP attributes. /* BGP core attribute structure. */
* lazily allocated as and when a struct attr struct attr
* requires it.
*/
struct attr_extra
{ {
/* AS Path structure */
struct aspath *aspath;
/* Community structure */
struct community *community;
/* Reference count of this attribute. */
unsigned long refcnt;
/* Flag of attribute is set or not. */
uint64_t flag;
/* Apart from in6_addr, the remaining static attributes */
struct in_addr nexthop;
u_int32_t med;
u_int32_t local_pref;
ifindex_t nh_ifindex;
/* Path origin attribute */
u_char origin;
/* has the route-map changed any attribute?
Used on the peer outbound side. */
u_int32_t rmap_change_flags;
/* Multi-Protocol Nexthop, AFI IPv6 */ /* Multi-Protocol Nexthop, AFI IPv6 */
struct in6_addr mp_nexthop_global; struct in6_addr mp_nexthop_global;
struct in6_addr mp_nexthop_local; struct in6_addr mp_nexthop_local;
@ -140,6 +162,9 @@ struct attr_extra
/* MP Nexthop preference */ /* MP Nexthop preference */
u_char mp_nexthop_prefer_global; u_char mp_nexthop_prefer_global;
/* Static MAC for EVPN */
u_char sticky;
/* route tag */ /* route tag */
route_tag_t tag; route_tag_t tag;
@ -157,38 +182,9 @@ struct attr_extra
#endif #endif
/* EVPN */ /* EVPN */
struct overlay_index evpn_overlay; struct overlay_index evpn_overlay;
};
/* BGP core attribute structure. */ /* EVPN MAC Mobility sequence number, if any. */
struct attr u_int32_t mm_seqnum;
{
/* AS Path structure */
struct aspath *aspath;
/* Community structure */
struct community *community;
/* Lazily allocated pointer to extra attributes */
struct attr_extra *extra;
/* Reference count of this attribute. */
unsigned long refcnt;
/* Flag of attribute is set or not. */
uint64_t flag;
/* Apart from in6_addr, the remaining static attributes */
struct in_addr nexthop;
u_int32_t med;
u_int32_t local_pref;
ifindex_t nh_ifindex;
/* Path origin attribute */
u_char origin;
/* has the route-map changed any attribute?
Used on the peer outbound side. */
u_int32_t rmap_change_flags;
}; };
/* rmap_change_flags definition */ /* rmap_change_flags definition */
@ -220,7 +216,7 @@ struct transit
#define BGP_CLUSTER_LIST_LENGTH(attr) \ #define BGP_CLUSTER_LIST_LENGTH(attr) \
(((attr)->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) ? \ (((attr)->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) ? \
(attr)->extra->cluster->length : 0) (attr)->cluster->length : 0)
typedef enum { typedef enum {
BGP_ATTR_PARSE_PROCEED = 0, BGP_ATTR_PARSE_PROCEED = 0,
@ -239,8 +235,6 @@ extern void bgp_attr_finish (void);
extern bgp_attr_parse_ret_t bgp_attr_parse (struct peer *, struct attr *, extern bgp_attr_parse_ret_t bgp_attr_parse (struct peer *, struct attr *,
bgp_size_t, struct bgp_nlri *, bgp_size_t, struct bgp_nlri *,
struct bgp_nlri *); struct bgp_nlri *);
extern struct attr_extra *bgp_attr_extra_get (struct attr *);
extern void bgp_attr_extra_free (struct attr *);
extern void bgp_attr_dup (struct attr *, struct attr *); extern void bgp_attr_dup (struct attr *, struct attr *);
extern void bgp_attr_deep_dup (struct attr *, struct attr *); extern void bgp_attr_deep_dup (struct attr *, struct attr *);
extern void bgp_attr_deep_free (struct attr *); extern void bgp_attr_deep_free (struct attr *);
@ -333,4 +327,10 @@ bgp_rmap_nhop_changed(u_int32_t out_rmap_flags, u_int32_t in_rmap_flags)
CHECK_FLAG(in_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED)) ? 1 : 0); CHECK_FLAG(in_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED)) ? 1 : 0);
} }
static inline u_int32_t
mac_mobility_seqnum (struct attr *attr)
{
return (attr) ? attr->mm_seqnum : 0;
}
#endif /* _QUAGGA_BGP_ATTR_H */ #endif /* _QUAGGA_BGP_ATTR_H */

View File

@ -33,21 +33,20 @@
#include "bgpd/bgp_attr_evpn.h" #include "bgpd/bgp_attr_evpn.h"
#include "bgpd/bgp_ecommunity.h" #include "bgpd/bgp_ecommunity.h"
#include "bgpd/bgp_evpn.h" #include "bgpd/bgp_evpn.h"
#include "bgpd/bgp_evpn_private.h"
void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac) void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac)
{ {
struct ecommunity_val routermac_ecom; struct ecommunity_val routermac_ecom;
if (attr->extra) {
memset(&routermac_ecom, 0, sizeof(struct ecommunity_val)); memset(&routermac_ecom, 0, sizeof(struct ecommunity_val));
routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN; routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN;
routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC; routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC;
memcpy(&routermac_ecom.val[2], routermac->octet, ETHER_ADDR_LEN); memcpy(&routermac_ecom.val[2], routermac->octet, ETHER_ADDR_LEN);
if (!attr->extra->ecommunity) if (!attr->ecommunity)
attr->extra->ecommunity = ecommunity_new(); attr->ecommunity = ecommunity_new();
ecommunity_add_val(attr->extra->ecommunity, &routermac_ecom); ecommunity_add_val(attr->ecommunity, &routermac_ecom);
ecommunity_str (attr->extra->ecommunity); ecommunity_str (attr->ecommunity);
}
} }
/* converts to an esi /* converts to an esi
@ -102,9 +101,62 @@ char *ecom_mac2str(char *ecom_mac)
en = ecom_mac; en = ecom_mac;
en += 2; en += 2;
return prefix_mac2str((struct ethaddr *)en, NULL, 0); return prefix_mac2str((struct ethaddr *)en, NULL, 0);
} }
/*
* Fetch and return the sequence number from MAC Mobility extended
* community, if present, else 0.
*/
u_int32_t
bgp_attr_mac_mobility_seqnum (struct attr *attr, u_char *sticky)
{
struct ecommunity *ecom;
int i;
u_char flags = 0;
ecom = attr->ecommunity;
if (!ecom || !ecom->size)
return 0;
/* If there is a MAC Mobility extended community, return its
* sequence number.
* TODO: RFC is silent on handling of multiple MAC mobility extended
* communities for the same route. We will bail out upon the first
* one.
*/
for (i = 0; i < ecom->size; i++)
{
u_char *pnt;
u_char type, sub_type;
u_int32_t seq_num;
pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
type = *pnt++;
sub_type = *pnt++;
if (!(type == ECOMMUNITY_ENCODE_EVPN &&
sub_type == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY))
continue;
flags = *pnt++;
if (flags & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY)
*sticky = 1;
else
*sticky = 0;
pnt++;
seq_num = (*pnt++ << 24);
seq_num |= (*pnt++ << 16);
seq_num |= (*pnt++ << 8);
seq_num |= (*pnt++);
return seq_num;
}
return 0;
}
/* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */ /* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
extern int extern int
bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag, struct prefix *dst) bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag, struct prefix *dst)
@ -121,7 +173,7 @@ bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag, struct prefix *dst)
p_evpn_p = &(dst->u.prefix_evpn); p_evpn_p = &(dst->u.prefix_evpn);
dst->family = AF_ETHERNET; dst->family = AF_ETHERNET;
p_evpn_p->route_type = evpn_type; p_evpn_p->route_type = evpn_type;
if (evpn_type == EVPN_IP_PREFIX) { if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) {
p_evpn_p->eth_tag = eth_tag; p_evpn_p->eth_tag = eth_tag;
p_evpn_p->ip_prefix_length = p2.prefixlen; p_evpn_p->ip_prefix_length = p2.prefixlen;
if (src->family == AF_INET) { if (src->family == AF_INET) {

View File

@ -28,23 +28,29 @@
#define ESI_TYPE_MAC 3 /* <Syst Mac Add-6B>:<Local Discriminator Value-3B> */ #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_ROUTER 4 /* <RouterId-4B>:<Local Discriminator Value-4B> */
#define ESI_TYPE_AS 5 /* <AS-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 MAX_ESI {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}
#define ESI_LEN 10 #define ESI_LEN 10
#define MAX_ET 0xffffffff #define MAX_ET 0xffffffff
u_long eth_tag_id; u_long eth_tag_id;
struct attr; struct attr;
struct eth_segment_id { struct eth_segment_id
{
u_char val[ESI_LEN]; u_char val[ESI_LEN];
}; };
union gw_addr { union gw_addr
{
struct in_addr ipv4; struct in_addr ipv4;
struct in6_addr ipv6; struct in6_addr ipv6;
}; };
struct bgp_route_evpn { struct bgp_route_evpn
{
struct eth_segment_id eth_s_id; struct eth_segment_id eth_s_id;
union gw_addr gw_ip; union gw_addr gw_ip;
}; };
@ -56,4 +62,8 @@ extern char *ecom_mac2str(char *ecom_mac);
extern void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac); extern void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac);
extern int bgp_build_evpn_prefix(int type, uint32_t eth_tag, extern int bgp_build_evpn_prefix(int type, uint32_t eth_tag,
struct prefix *dst); struct prefix *dst);
extern u_int32_t
bgp_attr_mac_mobility_seqnum (struct attr *attr, u_char *sticky);
#endif /* _QUAGGA_BGP_ATTR_EVPN_H */ #endif /* _QUAGGA_BGP_ATTR_EVPN_H */

View File

@ -39,6 +39,9 @@
#include "bgpd/bgp_community.h" #include "bgpd/bgp_community.h"
#include "bgpd/bgp_updgrp.h" #include "bgpd/bgp_updgrp.h"
#include "bgpd/bgp_mplsvpn.h" #include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_ecommunity.h"
#include "bgpd/bgp_label.h"
#include "bgpd/bgp_evpn.h"
unsigned long conf_bgp_debug_as4; unsigned long conf_bgp_debug_as4;
unsigned long conf_bgp_debug_neighbor_events; unsigned long conf_bgp_debug_neighbor_events;
@ -384,6 +387,8 @@ bgp_debug_peer_updout_enabled(char *host)
int int
bgp_dump_attr (struct attr *attr, char *buf, size_t size) bgp_dump_attr (struct attr *attr, char *buf, size_t size)
{ {
char addrbuf[BUFSIZ];
if (! attr) if (! attr)
return 0; return 0;
@ -394,22 +399,20 @@ bgp_dump_attr (struct attr *attr, char *buf, size_t size)
snprintf (buf + strlen (buf), size - strlen (buf), ", origin %s", snprintf (buf + strlen (buf), size - strlen (buf), ", origin %s",
bgp_origin_str[attr->origin]); bgp_origin_str[attr->origin]);
if (attr->extra)
{
char addrbuf[BUFSIZ];
/* Add MP case. */ /* Add MP case. */
if (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL
|| attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) || attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
snprintf (buf + strlen (buf), size - strlen (buf), ", mp_nexthop %s", snprintf (buf + strlen (buf), size - strlen (buf), ", mp_nexthop %s",
inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, inet_ntop (AF_INET6, &attr->mp_nexthop_global,
addrbuf, BUFSIZ)); addrbuf, BUFSIZ));
if (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
snprintf (buf + strlen (buf), size - strlen (buf), "(%s)", snprintf (buf + strlen (buf), size - strlen (buf), "(%s)",
inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local, inet_ntop (AF_INET6, &attr->mp_nexthop_local,
addrbuf, BUFSIZ)); addrbuf, BUFSIZ));
}
if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4)
snprintf (buf, size, "nexthop %s", inet_ntoa (attr->nexthop));
if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))) if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
snprintf (buf + strlen (buf), size - strlen (buf), ", localpref %u", snprintf (buf + strlen (buf), size - strlen (buf), ", localpref %u",
@ -423,26 +426,30 @@ bgp_dump_attr (struct attr *attr, char *buf, size_t size)
snprintf (buf + strlen (buf), size - strlen (buf), ", community %s", snprintf (buf + strlen (buf), size - strlen (buf), ", community %s",
community_str (attr->community)); community_str (attr->community));
if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
snprintf (buf + strlen (buf), size - strlen (buf), ", extcommunity %s",
ecommunity_str (attr->ecommunity));
if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))) if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE)))
snprintf (buf + strlen (buf), size - strlen (buf), ", atomic-aggregate"); snprintf (buf + strlen (buf), size - strlen (buf), ", atomic-aggregate");
if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))) if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)))
snprintf (buf + strlen (buf), size - strlen (buf), ", aggregated by %u %s", snprintf (buf + strlen (buf), size - strlen (buf), ", aggregated by %u %s",
attr->extra->aggregator_as, attr->aggregator_as,
inet_ntoa (attr->extra->aggregator_addr)); inet_ntoa (attr->aggregator_addr));
if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID))) if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)))
snprintf (buf + strlen (buf), size - strlen (buf), ", originator %s", snprintf (buf + strlen (buf), size - strlen (buf), ", originator %s",
inet_ntoa (attr->extra->originator_id)); inet_ntoa (attr->originator_id));
if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST))) if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST)))
{ {
int i; int i;
snprintf (buf + strlen (buf), size - strlen (buf), ", clusterlist"); snprintf (buf + strlen (buf), size - strlen (buf), ", clusterlist");
for (i = 0; i < attr->extra->cluster->length / 4; i++) for (i = 0; i < attr->cluster->length / 4; i++)
snprintf (buf + strlen (buf), size - strlen (buf), " %s", snprintf (buf + strlen (buf), size - strlen (buf), " %s",
inet_ntoa (attr->extra->cluster->list[i])); inet_ntoa (attr->cluster->list[i]));
} }
if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))) if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
@ -451,9 +458,9 @@ bgp_dump_attr (struct attr *attr, char *buf, size_t size)
if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID))) if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID)))
{ {
if (attr->extra->label_index != BGP_INVALID_LABEL_INDEX) if (attr->label_index != BGP_INVALID_LABEL_INDEX)
snprintf (buf + strlen (buf), size - strlen (buf), ", label-index %u", snprintf (buf + strlen (buf), size - strlen (buf), ", label-index %u",
attr->extra->label_index); attr->label_index);
} }
if (strlen (buf) > 1) if (strlen (buf) > 1)
@ -2142,12 +2149,14 @@ bgp_debug_zebra (struct prefix *p)
} }
const char * const char *
bgp_debug_rdpfxpath2str (struct prefix_rd *prd, union prefixconstptr pu, bgp_debug_rdpfxpath2str (afi_t afi, safi_t safi,
int addpath_valid, u_int32_t addpath_id, struct prefix_rd *prd, union prefixconstptr pu,
char *str, int size) mpls_label_t *label, int addpath_valid,
u_int32_t addpath_id, char *str, int size)
{ {
char rd_buf[RD_ADDRSTRLEN]; char rd_buf[RD_ADDRSTRLEN];
char pfx_buf[PREFIX_STRLEN]; char pfx_buf[PREFIX_STRLEN];
char tag_buf[30];
/* ' with addpath ID ' 17 /* ' with addpath ID ' 17
* max strlen of uint32 + 10 * max strlen of uint32 + 10
* +/- (just in case) + 1 * +/- (just in case) + 1
@ -2163,13 +2172,24 @@ bgp_debug_rdpfxpath2str (struct prefix_rd *prd, union prefixconstptr pu,
if (addpath_valid) if (addpath_valid)
snprintf(pathid_buf, sizeof(pathid_buf), " with addpath ID %u", addpath_id); snprintf(pathid_buf, sizeof(pathid_buf), " with addpath ID %u", addpath_id);
tag_buf[0] = '\0';
if (bgp_labeled_safi (safi) && label)
{
u_int32_t label_value;
label_value = decode_label (label);
sprintf (tag_buf, " label %u", label_value);
}
if (prd) if (prd)
snprintf (str, size, "RD %s %s%s", snprintf (str, size, "RD %s %s%s%s",
prefix_rd2str(prd, rd_buf, sizeof (rd_buf)), prefix_rd2str(prd, rd_buf, sizeof (rd_buf)),
prefix2str (pu, pfx_buf, sizeof (pfx_buf)), pathid_buf); prefix2str (pu, pfx_buf, sizeof (pfx_buf)),
tag_buf, pathid_buf);
else else
snprintf (str, size, "%s%s", snprintf (str, size, "%s%s%s",
prefix2str (pu, pfx_buf, sizeof (pfx_buf)), pathid_buf); prefix2str (pu, pfx_buf, sizeof (pfx_buf)),
tag_buf, pathid_buf);
return str; return str;
} }

View File

@ -153,7 +153,8 @@ extern int bgp_debug_bestpath(struct prefix *p);
extern int bgp_debug_zebra(struct prefix *p); extern int bgp_debug_zebra(struct prefix *p);
extern int bgp_debug_count(void); extern int bgp_debug_count(void);
extern const char *bgp_debug_rdpfxpath2str (struct prefix_rd *, union prefixconstptr, extern const char *bgp_debug_rdpfxpath2str (afi_t, safi_t, struct prefix_rd *,
union prefixconstptr, mpls_label_t *,
int, u_int32_t, char *, int); int, u_int32_t, char *, int);
const char *bgp_notify_admin_message(char *buf, size_t bufsz, u_char *data, size_t datalen); const char *bgp_notify_admin_message(char *buf, size_t bufsz, u_char *data, size_t datalen);

View File

@ -304,6 +304,61 @@ enum ecommunity_token
ecommunity_token_val, ecommunity_token_val,
}; };
/*
* Encode BGP extended community from passed values. Supports types
* defined in RFC 4360 and well-known sub-types.
*/
static int
ecommunity_encode (u_char type, u_char sub_type, int trans,
as_t as, struct in_addr ip, u_int32_t val,
struct ecommunity_val *eval)
{
assert (eval);
if (type == ECOMMUNITY_ENCODE_AS)
{
if (as > BGP_AS_MAX)
return -1;
}
else if (type == ECOMMUNITY_ENCODE_IP
|| type == ECOMMUNITY_ENCODE_AS4)
{
if (val > UINT16_MAX)
return -1;
}
/* Fill in the values. */
eval->val[0] = type;
if (!trans)
eval->val[0] |= ECOMMUNITY_FLAG_NON_TRANSITIVE;
eval->val[1] = sub_type;
if (type == ECOMMUNITY_ENCODE_AS)
{
eval->val[2] = (as >> 8) & 0xff;
eval->val[3] = as & 0xff;
eval->val[4] = (val >> 24) & 0xff;
eval->val[5] = (val >> 16) & 0xff;
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
else if (type == ECOMMUNITY_ENCODE_IP)
{
memcpy (&eval->val[2], &ip, sizeof (struct in_addr));
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
else
{
eval->val[2] = (as >> 24) & 0xff;
eval->val[3] = (as >> 16) & 0xff;
eval->val[4] = (as >> 8) & 0xff;
eval->val[5] = as & 0xff;
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
return 0;
}
/* Get next Extended Communities token from the string. */ /* Get next Extended Communities token from the string. */
static const char * static const char *
ecommunity_gettoken (const char *str, struct ecommunity_val *eval, ecommunity_gettoken (const char *str, struct ecommunity_val *eval,
@ -318,6 +373,7 @@ ecommunity_gettoken (const char *str, struct ecommunity_val *eval,
struct in_addr ip; struct in_addr ip;
as_t as = 0; as_t as = 0;
u_int32_t val = 0; u_int32_t val = 0;
u_char ecomm_type;
char buf[INET_ADDRSTRLEN + 1]; char buf[INET_ADDRSTRLEN + 1];
/* Skip white space. */ /* Skip white space. */
@ -452,44 +508,15 @@ ecommunity_gettoken (const char *str, struct ecommunity_val *eval,
if (!digit || !separator) if (!digit || !separator)
goto error; goto error;
/* Encode result into routing distinguisher. */ /* Encode result into extended community. */
if (dot) if (dot)
{ ecomm_type = ECOMMUNITY_ENCODE_IP;
if (val > UINT16_MAX)
goto error;
eval->val[0] = ECOMMUNITY_ENCODE_IP;
eval->val[1] = 0;
memcpy (&eval->val[2], &ip, sizeof (struct in_addr));
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
else if (as > BGP_AS_MAX) else if (as > BGP_AS_MAX)
{ ecomm_type = ECOMMUNITY_ENCODE_AS4;
if (val > UINT16_MAX)
goto error;
eval->val[0] = ECOMMUNITY_ENCODE_AS4;
eval->val[1] = 0;
eval->val[2] = (as >>24) & 0xff;
eval->val[3] = (as >>16) & 0xff;
eval->val[4] = (as >>8) & 0xff;
eval->val[5] = as & 0xff;
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
else else
{ ecomm_type = ECOMMUNITY_ENCODE_AS;
eval->val[0] = ECOMMUNITY_ENCODE_AS; if (ecommunity_encode (ecomm_type, 0, 1, as, ip, val, eval))
eval->val[1] = 0; goto error;
eval->val[2] = (as >>8) & 0xff;
eval->val[3] = as & 0xff;
eval->val[4] = (val >>24) & 0xff;
eval->val[5] = (val >>16) & 0xff;
eval->val[6] = (val >>8) & 0xff;
eval->val[7] = val & 0xff;
}
*token = ecommunity_token_val; *token = ecommunity_token_val;
return p; return p;
@ -581,6 +608,81 @@ ecommunity_str2com (const char *str, int type, int keyword_included)
return ecom; return ecom;
} }
static int
ecommunity_rt_soo_str (char *buf, u_int8_t *pnt, int type,
int sub_type, int format)
{
int len = 0;
const char *prefix;
/* For parse Extended Community attribute tupple. */
struct ecommunity_as
{
as_t as;
u_int32_t val;
} eas;
struct ecommunity_ip
{
struct in_addr ip;
u_int16_t val;
} eip;
/* Determine prefix for string, if any. */
switch (format)
{
case ECOMMUNITY_FORMAT_COMMUNITY_LIST:
prefix = (sub_type == ECOMMUNITY_ROUTE_TARGET ? "rt " : "soo ");
break;
case ECOMMUNITY_FORMAT_DISPLAY:
prefix = (sub_type == ECOMMUNITY_ROUTE_TARGET ? "RT:" : "SoO:");
break;
case ECOMMUNITY_FORMAT_ROUTE_MAP:
prefix = "";
break;
default:
prefix = "";
break;
}
/* Put string into buffer. */
if (type == ECOMMUNITY_ENCODE_AS4)
{
eas.as = (*pnt++ << 24);
eas.as |= (*pnt++ << 16);
eas.as |= (*pnt++ << 8);
eas.as |= (*pnt++);
eas.val = (*pnt++ << 8);
eas.val |= (*pnt++);
len = sprintf (buf, "%s%u:%u", prefix, eas.as, eas.val);
}
else if (type == ECOMMUNITY_ENCODE_AS)
{
eas.as = (*pnt++ << 8);
eas.as |= (*pnt++);
eas.val = (*pnt++ << 24);
eas.val |= (*pnt++ << 16);
eas.val |= (*pnt++ << 8);
eas.val |= (*pnt++);
len = sprintf (buf, "%s%u:%u", prefix, eas.as, eas.val);
}
else if (type == ECOMMUNITY_ENCODE_IP)
{
memcpy (&eip.ip, pnt, 4);
pnt += 4;
eip.val = (*pnt++ << 8);
eip.val |= (*pnt++);
len = sprintf (buf, "%s%s:%u", prefix, inet_ntoa (eip.ip), eip.val);
}
return len;
}
/* Convert extended community attribute to string. /* Convert extended community attribute to string.
Due to historical reason of industry standard implementation, there Due to historical reason of industry standard implementation, there
@ -610,29 +712,15 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format, int filter)
{ {
int i; int i;
u_int8_t *pnt; u_int8_t *pnt;
int encode = 0;
int type = 0; int type = 0;
int sub_type = 0;
#define ECOMMUNITY_STR_DEFAULT_LEN 27 #define ECOMMUNITY_STR_DEFAULT_LEN 27
int str_size; int str_size;
int str_pnt; int str_pnt;
char *str_buf; char *str_buf;
const char *prefix;
int len = 0; int len = 0;
int first = 1; int first = 1;
/* For parse Extended Community attribute tupple. */
struct ecommunity_as
{
as_t as;
u_int32_t val;
} eas;
struct ecommunity_ip
{
struct in_addr ip;
u_int16_t val;
} eip;
if (ecom->size == 0) if (ecom->size == 0)
{ {
str_buf = XMALLOC (MTYPE_ECOMMUNITY_STR, 1); str_buf = XMALLOC (MTYPE_ECOMMUNITY_STR, 1);
@ -648,6 +736,8 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format, int filter)
for (i = 0; i < ecom->size; i++) for (i = 0; i < ecom->size; i++)
{ {
int unk_ecom = 0;
/* Make it sure size is enough. */ /* Make it sure size is enough. */
while (str_pnt + ECOMMUNITY_STR_DEFAULT_LEN >= str_size) while (str_pnt + ECOMMUNITY_STR_DEFAULT_LEN >= str_size)
{ {
@ -662,39 +752,39 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format, int filter)
pnt = ecom->val + (i * 8); pnt = ecom->val + (i * 8);
/* High-order octet of type. */ /* High-order octet of type. */
encode = *pnt++; type = *pnt++;
switch (encode) if (type == ECOMMUNITY_ENCODE_AS ||
type == ECOMMUNITY_ENCODE_IP ||
type == ECOMMUNITY_ENCODE_AS4)
{ {
case ECOMMUNITY_ENCODE_AS: /* Low-order octet of type. */
case ECOMMUNITY_ENCODE_IP: sub_type = *pnt++;
case ECOMMUNITY_ENCODE_AS4: if (sub_type != ECOMMUNITY_ROUTE_TARGET &&
break; sub_type != ECOMMUNITY_SITE_ORIGIN)
unk_ecom = 1;
case ECOMMUNITY_ENCODE_OPAQUE: else
if(filter == ECOMMUNITY_ROUTE_TARGET) len = ecommunity_rt_soo_str (str_buf + str_pnt, pnt, type,
{ sub_type, format);
continue;
} }
else if (type == ECOMMUNITY_ENCODE_OPAQUE)
{
if (filter == ECOMMUNITY_ROUTE_TARGET)
continue;
if (*pnt == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP) if (*pnt == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP)
{ {
uint16_t tunneltype; uint16_t tunneltype;
memcpy (&tunneltype, pnt + 5, 2); memcpy (&tunneltype, pnt + 5, 2);
tunneltype = ntohs(tunneltype); tunneltype = ntohs(tunneltype);
len = sprintf (str_buf + str_pnt, "ET:%d", tunneltype); len = sprintf (str_buf + str_pnt, "ET:%d", tunneltype);
str_pnt += len;
first = 0;
continue;
} }
len = sprintf (str_buf + str_pnt, "?"); else
str_pnt += len; unk_ecom = 1;
first = 0; }
continue; else if (type == ECOMMUNITY_ENCODE_EVPN)
case ECOMMUNITY_ENCODE_EVPN:
if(filter == ECOMMUNITY_ROUTE_TARGET)
{ {
if (filter == ECOMMUNITY_ROUTE_TARGET)
continue; continue;
}
if (*pnt == ECOMMUNITY_SITE_ORIGIN) if (*pnt == ECOMMUNITY_SITE_ORIGIN)
{ {
char macaddr[6]; char macaddr[6];
@ -703,91 +793,32 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format, int filter)
len = sprintf(str_buf + str_pnt, "EVPN:%02x:%02x:%02x:%02x:%02x:%02x", len = sprintf(str_buf + str_pnt, "EVPN:%02x:%02x:%02x:%02x:%02x:%02x",
macaddr[0], macaddr[1], macaddr[2], macaddr[0], macaddr[1], macaddr[2],
macaddr[3], macaddr[4], macaddr[5]); macaddr[3], macaddr[4], macaddr[5]);
str_pnt += len;
first = 0;
continue;
} }
else if (*pnt == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY)
{
u_int32_t seqnum;
u_char flags = *++pnt;
memcpy (&seqnum, pnt + 2, 4);
seqnum = ntohl(seqnum);
if (flags & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY)
len = sprintf (str_buf + str_pnt, "MM:%u, sticky MAC", seqnum);
else
len = sprintf (str_buf + str_pnt, "MM:%u", seqnum);
}
else
unk_ecom = 1;
}
else
unk_ecom = 1;
if (unk_ecom)
len = sprintf (str_buf + str_pnt, "?"); len = sprintf (str_buf + str_pnt, "?");
str_pnt += len;
first = 0;
continue;
default:
len = sprintf (str_buf + str_pnt, "?");
str_pnt += len;
first = 0;
continue;
}
/* Low-order octet of type. */
type = *pnt++;
if (type != ECOMMUNITY_ROUTE_TARGET && type != ECOMMUNITY_SITE_ORIGIN)
{
len = sprintf (str_buf + str_pnt, "?");
str_pnt += len;
first = 0;
continue;
}
switch (format)
{
case ECOMMUNITY_FORMAT_COMMUNITY_LIST:
prefix = (type == ECOMMUNITY_ROUTE_TARGET ? "rt " : "soo ");
break;
case ECOMMUNITY_FORMAT_DISPLAY:
prefix = (type == ECOMMUNITY_ROUTE_TARGET ? "RT:" : "SoO:");
break;
case ECOMMUNITY_FORMAT_ROUTE_MAP:
prefix = "";
break;
default:
prefix = "";
break;
}
/* Put string into buffer. */
if (encode == ECOMMUNITY_ENCODE_AS4)
{
eas.as = (*pnt++ << 24);
eas.as |= (*pnt++ << 16);
eas.as |= (*pnt++ << 8);
eas.as |= (*pnt++);
eas.val = (*pnt++ << 8);
eas.val |= (*pnt++);
len = sprintf( str_buf + str_pnt, "%s%u:%u", prefix,
eas.as, eas.val );
str_pnt += len; str_pnt += len;
first = 0; first = 0;
} }
if (encode == ECOMMUNITY_ENCODE_AS)
{
eas.as = (*pnt++ << 8);
eas.as |= (*pnt++);
eas.val = (*pnt++ << 24);
eas.val |= (*pnt++ << 16);
eas.val |= (*pnt++ << 8);
eas.val |= (*pnt++);
len = sprintf (str_buf + str_pnt, "%s%u:%u", prefix,
eas.as, eas.val);
str_pnt += len;
first = 0;
}
else if (encode == ECOMMUNITY_ENCODE_IP)
{
memcpy (&eip.ip, pnt, 4);
pnt += 4;
eip.val = (*pnt++ << 8);
eip.val |= (*pnt++);
len = sprintf (str_buf + str_pnt, "%s%s:%u", prefix,
inet_ntoa (eip.ip), eip.val);
str_pnt += len;
first = 0;
}
}
return str_buf; return str_buf;
} }

View File

@ -32,12 +32,15 @@
#define ECOMMUNITY_ROUTE_TARGET 0x02 #define ECOMMUNITY_ROUTE_TARGET 0x02
#define ECOMMUNITY_SITE_ORIGIN 0x03 #define ECOMMUNITY_SITE_ORIGIN 0x03
/* Low-order octet of the Extended Communities type field for EVPN types */
#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00 #define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00
#define ECOMMUNITY_EVPN_SUBTYPE_ESI_LABEL 0x01 #define ECOMMUNITY_EVPN_SUBTYPE_ESI_LABEL 0x01
#define ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT 0x02 #define ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT 0x02
#define ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC 0x03 #define ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC 0x03
#define ECOMMUNITY_EVPN_SUBTYPE_DEF_GW 0x0d #define ECOMMUNITY_EVPN_SUBTYPE_DEF_GW 0x0d
#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY 0x01
/* Low-order octet of the Extended Communities type field for OPAQUE types */ /* Low-order octet of the Extended Communities type field for OPAQUE types */
#define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c #define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c
@ -76,6 +79,54 @@ struct ecommunity_val
#define ecom_length(X) ((X)->size * ECOMMUNITY_SIZE) #define ecom_length(X) ((X)->size * ECOMMUNITY_SIZE)
/*
* Encode BGP Route Target AS:nn.
*/
static inline void
encode_route_target_as (as_t as, u_int32_t val,
struct ecommunity_val *eval)
{
eval->val[0] = ECOMMUNITY_ENCODE_AS;
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
eval->val[2] = (as >> 8) & 0xff;
eval->val[3] = as & 0xff;
eval->val[4] = (val >> 24) & 0xff;
eval->val[5] = (val >> 16) & 0xff;
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
/*
* Encode BGP Route Target IP:nn.
*/
static inline void
encode_route_target_ip (struct in_addr ip, u_int16_t val,
struct ecommunity_val *eval)
{
eval->val[0] = ECOMMUNITY_ENCODE_IP;
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
memcpy (&eval->val[2], &ip, sizeof (struct in_addr));
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
/*
* Encode BGP Route Target AS4:nn.
*/
static inline void
encode_route_target_as4 (as_t as, u_int16_t val,
struct ecommunity_val *eval)
{
eval->val[0] = ECOMMUNITY_ENCODE_AS4;
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
eval->val[2] = (as >> 24) & 0xff;
eval->val[3] = (as >> 16) & 0xff;
eval->val[4] = (as >> 8) & 0xff;
eval->val[5] = as & 0xff;
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
extern void ecommunity_init (void); extern void ecommunity_init (void);
extern void ecommunity_finish (void); extern void ecommunity_finish (void);
extern void ecommunity_free (struct ecommunity **); extern void ecommunity_free (struct ecommunity **);

View File

@ -238,7 +238,7 @@ subtlv_encode_remote_endpoint(
if (last) {\ if (last) {\
last->next = new;\ last->next = new;\
} else {\ } else {\
extra->encap_subtlvs = new;\ attr->encap_subtlvs = new;\
}\ }\
last = new;\ last = new;\
}\ }\
@ -249,13 +249,12 @@ bgp_encap_type_l2tpv3overip_to_tlv(
struct bgp_encap_type_l2tpv3_over_ip *bet, /* input structure */ struct bgp_encap_type_l2tpv3_over_ip *bet, /* input structure */
struct attr *attr) struct attr *attr)
{ {
struct attr_extra *extra = bgp_attr_extra_get(attr);
struct bgp_attr_encap_subtlv *last; struct bgp_attr_encap_subtlv *last;
/* advance to last subtlv */ /* advance to last subtlv */
for (last = extra->encap_subtlvs; last && last->next; last = last->next); for (last = attr->encap_subtlvs; last && last->next; last = last->next);
extra->encap_tunneltype = BGP_ENCAP_TYPE_L2TPV3_OVER_IP; attr->encap_tunneltype = BGP_ENCAP_TYPE_L2TPV3_OVER_IP;
assert(CHECK_FLAG(bet->valid_subtlvs, BGP_TEA_SUBTLV_ENCAP)); assert(CHECK_FLAG(bet->valid_subtlvs, BGP_TEA_SUBTLV_ENCAP));
@ -270,13 +269,12 @@ bgp_encap_type_gre_to_tlv(
struct bgp_encap_type_gre *bet, /* input structure */ struct bgp_encap_type_gre *bet, /* input structure */
struct attr *attr) struct attr *attr)
{ {
struct attr_extra *extra = bgp_attr_extra_get(attr);
struct bgp_attr_encap_subtlv *last; struct bgp_attr_encap_subtlv *last;
/* advance to last subtlv */ /* advance to last subtlv */
for (last = extra->encap_subtlvs; last && last->next; last = last->next); for (last = attr->encap_subtlvs; last && last->next; last = last->next);
extra->encap_tunneltype = BGP_ENCAP_TYPE_GRE; attr->encap_tunneltype = BGP_ENCAP_TYPE_GRE;
ENC_SUBTLV(BGP_TEA_SUBTLV_ENCAP, subtlv_encode_encap_gre, st_encap); ENC_SUBTLV(BGP_TEA_SUBTLV_ENCAP, subtlv_encode_encap_gre, st_encap);
ENC_SUBTLV(BGP_TEA_SUBTLV_PROTO_TYPE, subtlv_encode_proto_type, st_proto); ENC_SUBTLV(BGP_TEA_SUBTLV_PROTO_TYPE, subtlv_encode_proto_type, st_proto);
@ -289,13 +287,12 @@ bgp_encap_type_ip_in_ip_to_tlv(
struct bgp_encap_type_ip_in_ip *bet, /* input structure */ struct bgp_encap_type_ip_in_ip *bet, /* input structure */
struct attr *attr) struct attr *attr)
{ {
struct attr_extra *extra = bgp_attr_extra_get(attr);
struct bgp_attr_encap_subtlv *last; struct bgp_attr_encap_subtlv *last;
/* advance to last subtlv */ /* advance to last subtlv */
for (last = extra->encap_subtlvs; last && last->next; last = last->next); for (last = attr->encap_subtlvs; last && last->next; last = last->next);
extra->encap_tunneltype = BGP_ENCAP_TYPE_IP_IN_IP; attr->encap_tunneltype = BGP_ENCAP_TYPE_IP_IN_IP;
ENC_SUBTLV(BGP_TEA_SUBTLV_PROTO_TYPE, subtlv_encode_proto_type, st_proto); ENC_SUBTLV(BGP_TEA_SUBTLV_PROTO_TYPE, subtlv_encode_proto_type, st_proto);
ENC_SUBTLV(BGP_TEA_SUBTLV_COLOR, subtlv_encode_color, st_color); ENC_SUBTLV(BGP_TEA_SUBTLV_COLOR, subtlv_encode_color, st_color);
@ -307,13 +304,12 @@ bgp_encap_type_transmit_tunnel_endpoint(
struct bgp_encap_type_transmit_tunnel_endpoint *bet, /* input structure */ struct bgp_encap_type_transmit_tunnel_endpoint *bet, /* input structure */
struct attr *attr) struct attr *attr)
{ {
struct attr_extra *extra = bgp_attr_extra_get(attr);
struct bgp_attr_encap_subtlv *last; struct bgp_attr_encap_subtlv *last;
/* advance to last subtlv */ /* advance to last subtlv */
for (last = extra->encap_subtlvs; last && last->next; last = last->next); for (last = attr->encap_subtlvs; last && last->next; last = last->next);
extra->encap_tunneltype = BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT; attr->encap_tunneltype = BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT;
/* no subtlvs for this type */ /* no subtlvs for this type */
} }
@ -323,13 +319,12 @@ bgp_encap_type_ipsec_in_tunnel_mode_to_tlv(
struct bgp_encap_type_ipsec_in_tunnel_mode *bet, /* input structure */ struct bgp_encap_type_ipsec_in_tunnel_mode *bet, /* input structure */
struct attr *attr) struct attr *attr)
{ {
struct attr_extra *extra = bgp_attr_extra_get(attr);
struct bgp_attr_encap_subtlv *last; struct bgp_attr_encap_subtlv *last;
/* advance to last subtlv */ /* advance to last subtlv */
for (last = extra->encap_subtlvs; last && last->next; last = last->next); for (last = attr->encap_subtlvs; last && last->next; last = last->next);
extra->encap_tunneltype = BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE; attr->encap_tunneltype = BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE;
ENC_SUBTLV(BGP_TEA_SUBTLV_IPSEC_TA, subtlv_encode_ipsec_ta, st_ipsec_ta); ENC_SUBTLV(BGP_TEA_SUBTLV_IPSEC_TA, subtlv_encode_ipsec_ta, st_ipsec_ta);
} }
@ -339,13 +334,12 @@ bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet, /* input structure */ struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet, /* input structure */
struct attr *attr) struct attr *attr)
{ {
struct attr_extra *extra = bgp_attr_extra_get(attr);
struct bgp_attr_encap_subtlv *last; struct bgp_attr_encap_subtlv *last;
/* advance to last subtlv */ /* advance to last subtlv */
for (last = extra->encap_subtlvs; last && last->next; last = last->next); for (last = attr->encap_subtlvs; last && last->next; last = last->next);
extra->encap_tunneltype = BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE; attr->encap_tunneltype = BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE;
ENC_SUBTLV(BGP_TEA_SUBTLV_IPSEC_TA, subtlv_encode_ipsec_ta, st_ipsec_ta); ENC_SUBTLV(BGP_TEA_SUBTLV_IPSEC_TA, subtlv_encode_ipsec_ta, st_ipsec_ta);
} }
@ -355,13 +349,12 @@ bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet, /* input structure */ struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet, /* input structure */
struct attr *attr) struct attr *attr)
{ {
struct attr_extra *extra = bgp_attr_extra_get(attr);
struct bgp_attr_encap_subtlv *last; struct bgp_attr_encap_subtlv *last;
/* advance to last subtlv */ /* advance to last subtlv */
for (last = extra->encap_subtlvs; last && last->next; last = last->next); for (last = attr->encap_subtlvs; last && last->next; last = last->next);
extra->encap_tunneltype = BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE; attr->encap_tunneltype = BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE;
ENC_SUBTLV(BGP_TEA_SUBTLV_IPSEC_TA, subtlv_encode_ipsec_ta, st_ipsec_ta); ENC_SUBTLV(BGP_TEA_SUBTLV_IPSEC_TA, subtlv_encode_ipsec_ta, st_ipsec_ta);
} }
@ -371,13 +364,12 @@ bgp_encap_type_pbb_to_tlv(
struct bgp_encap_type_pbb *bet, /* input structure */ struct bgp_encap_type_pbb *bet, /* input structure */
struct attr *attr) struct attr *attr)
{ {
struct attr_extra *extra = bgp_attr_extra_get(attr);
struct bgp_attr_encap_subtlv *last; struct bgp_attr_encap_subtlv *last;
/* advance to last subtlv */ /* advance to last subtlv */
for (last = extra->encap_subtlvs; last && last->next; last = last->next); for (last = attr->encap_subtlvs; last && last->next; last = last->next);
extra->encap_tunneltype = BGP_ENCAP_TYPE_PBB; attr->encap_tunneltype = BGP_ENCAP_TYPE_PBB;
assert(CHECK_FLAG(bet->valid_subtlvs, BGP_TEA_SUBTLV_ENCAP)); assert(CHECK_FLAG(bet->valid_subtlvs, BGP_TEA_SUBTLV_ENCAP));
ENC_SUBTLV(BGP_TEA_SUBTLV_ENCAP, subtlv_encode_encap_pbb, st_encap); ENC_SUBTLV(BGP_TEA_SUBTLV_ENCAP, subtlv_encode_encap_pbb, st_encap);
@ -388,16 +380,15 @@ bgp_encap_type_vxlan_to_tlv(
struct bgp_encap_type_vxlan *bet, /* input structure */ struct bgp_encap_type_vxlan *bet, /* input structure */
struct attr *attr) struct attr *attr)
{ {
struct attr_extra *extra = bgp_attr_extra_get(attr);
struct bgp_attr_encap_subtlv *tlv; struct bgp_attr_encap_subtlv *tlv;
uint32_t vnid; uint32_t vnid;
extra->encap_tunneltype = BGP_ENCAP_TYPE_VXLAN; attr->encap_tunneltype = BGP_ENCAP_TYPE_VXLAN;
if(bet == NULL ||!bet->vnid) if(bet == NULL ||!bet->vnid)
return; return;
if(extra->encap_subtlvs) if(attr->encap_subtlvs)
XFREE(MTYPE_ENCAP_TLV, extra->encap_subtlvs); XFREE(MTYPE_ENCAP_TLV, attr->encap_subtlvs);
tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+12); tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+12);
tlv->type = 1; /* encapsulation type */ tlv->type = 1; /* encapsulation type */
tlv->length = 12; tlv->length = 12;
@ -411,7 +402,7 @@ bgp_encap_type_vxlan_to_tlv(
char *ptr = (char *)&tlv->value + 4; char *ptr = (char *)&tlv->value + 4;
memcpy( ptr, bet->mac_address, 6); memcpy( ptr, bet->mac_address, 6);
} }
extra->encap_subtlvs = tlv; attr->encap_subtlvs = tlv;
return; return;
} }
@ -420,9 +411,7 @@ bgp_encap_type_nvgre_to_tlv(
struct bgp_encap_type_nvgre *bet, /* input structure */ struct bgp_encap_type_nvgre *bet, /* input structure */
struct attr *attr) struct attr *attr)
{ {
struct attr_extra *extra = bgp_attr_extra_get(attr); attr->encap_tunneltype = BGP_ENCAP_TYPE_NVGRE;
extra->encap_tunneltype = BGP_ENCAP_TYPE_NVGRE;
} }
void void
@ -438,9 +427,7 @@ bgp_encap_type_mpls_in_gre_to_tlv(
struct bgp_encap_type_mpls_in_gre *bet, /* input structure */ struct bgp_encap_type_mpls_in_gre *bet, /* input structure */
struct attr *attr) struct attr *attr)
{ {
struct attr_extra *extra = bgp_attr_extra_get(attr); attr->encap_tunneltype = BGP_ENCAP_TYPE_MPLS_IN_GRE;
extra->encap_tunneltype = BGP_ENCAP_TYPE_MPLS_IN_GRE;
} }
void void
@ -448,9 +435,8 @@ bgp_encap_type_vxlan_gpe_to_tlv(
struct bgp_encap_type_vxlan_gpe *bet, /* input structure */ struct bgp_encap_type_vxlan_gpe *bet, /* input structure */
struct attr *attr) struct attr *attr)
{ {
struct attr_extra *extra = bgp_attr_extra_get(attr);
extra->encap_tunneltype = BGP_ENCAP_TYPE_VXLAN_GPE; attr->encap_tunneltype = BGP_ENCAP_TYPE_VXLAN_GPE;
} }
void void
@ -458,9 +444,8 @@ bgp_encap_type_mpls_in_udp_to_tlv(
struct bgp_encap_type_mpls_in_udp *bet, /* input structure */ struct bgp_encap_type_mpls_in_udp *bet, /* input structure */
struct attr *attr) struct attr *attr)
{ {
struct attr_extra *extra = bgp_attr_extra_get(attr);
extra->encap_tunneltype = BGP_ENCAP_TYPE_MPLS_IN_UDP; attr->encap_tunneltype = BGP_ENCAP_TYPE_MPLS_IN_UDP;
} }

View File

@ -19,6 +19,8 @@
#ifndef _QUAGGA_BGP_ENCAP_TYPES_H #ifndef _QUAGGA_BGP_ENCAP_TYPES_H
#define _QUAGGA_BGP_ENCAP_TYPES_H #define _QUAGGA_BGP_ENCAP_TYPES_H
#include "bgpd/bgp_ecommunity.h"
/* from http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#tunnel-types */ /* from http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#tunnel-types */
typedef enum { typedef enum {
BGP_ENCAP_TYPE_RESERVED=0, BGP_ENCAP_TYPE_RESERVED=0,
@ -213,4 +215,15 @@ struct bgp_encap_type_pbb {
struct bgp_tea_subtlv_encap_pbb st_encap; struct bgp_tea_subtlv_encap_pbb st_encap;
}; };
static inline void
encode_encap_extcomm (bgp_encap_types tnl_type,
struct ecommunity_val *eval)
{
memset (eval, 0, sizeof (*eval));
eval->val[0] = ECOMMUNITY_ENCODE_OPAQUE;
eval->val[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP;
eval->val[6] = ((tnl_type) >> 8) & 0xff;
eval->val[7] = (tnl_type) & 0xff;
}
#endif /* _QUAGGA_BGP_ENCAP_TYPES_H */ #endif /* _QUAGGA_BGP_ENCAP_TYPES_H */

File diff suppressed because it is too large Load Diff

View File

@ -21,20 +21,45 @@
#ifndef _QUAGGA_BGP_EVPN_H #ifndef _QUAGGA_BGP_EVPN_H
#define _QUAGGA_BGP_EVPN_H #define _QUAGGA_BGP_EVPN_H
extern int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, #include "vxlan.h"
struct bgp_nlri *packet, int withdraw);
#define EVPN_ROUTE_STRLEN 200 /* Must be >> MAC + IPv6 strings. */
extern void extern void
bgp_packet_mpattr_route_type_5(struct stream *s, bgp_evpn_handle_router_id_update (struct bgp *bgp, int withdraw);
struct prefix *p, struct prefix_rd *prd, extern char *
mpls_label_t *label, struct attr *attr); bgp_evpn_label2str (mpls_label_t *label, char *buf, int len);
/* EVPN route types as per RFC7432 and extern char *
* as per draft-ietf-bess-evpn-prefix-advertisement-02 bgp_evpn_route2str (struct prefix_evpn *p, char *buf, int len);
*/ extern void
#define EVPN_ETHERNET_AUTO_DISCOVERY 1 bgp_evpn_encode_prefix (struct stream *s, struct prefix *p,
#define EVPN_MACIP_ADVERTISEMENT 2 struct prefix_rd *prd, mpls_label_t *label,
#define EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG 3 struct attr *attr, int addpath_encode,
#define EVPN_ETHERNET_SEGMENT 4 u_int32_t addpath_tx_id);
#define EVPN_IP_PREFIX 5 extern int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
struct bgp_nlri *packet, int withdraw);
extern int
bgp_evpn_import_route (struct bgp *bgp, afi_t afi, safi_t safi,
struct prefix *p, struct bgp_info *ri);
extern int
bgp_evpn_unimport_route (struct bgp *bgp, afi_t afi, safi_t safi,
struct prefix *p, struct bgp_info *ri);
extern int
bgp_evpn_local_macip_del (struct bgp *bgp, vni_t vni,
struct ethaddr *mac, struct ipaddr *ip);
extern int
bgp_evpn_local_macip_add (struct bgp *bgp, vni_t vni,
struct ethaddr *mac, struct ipaddr *ip,
u_char sticky);
extern int
bgp_evpn_local_vni_del (struct bgp *bgp, vni_t vni);
extern int
bgp_evpn_local_vni_add (struct bgp *bgp, vni_t vni, struct in_addr originator_ip);
extern void
bgp_evpn_cleanup_on_disable (struct bgp *bgp);
extern void
bgp_evpn_cleanup (struct bgp *bgp);
extern void
bgp_evpn_init (struct bgp *bgp);
#endif /* _QUAGGA_BGP_EVPN_H */ #endif /* _QUAGGA_BGP_EVPN_H */

232
bgpd/bgp_evpn_private.h Normal file
View File

@ -0,0 +1,232 @@
/* BGP EVPN internal definitions
* Copyright (C) 2017 Cumulus Networks, Inc.
*
* This file is part of FRR.
*
* FRR 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.
*
* FRR 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 FRR; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef _BGP_EVPN_PRIVATE_H
#define _BGP_EVPN_PRIVATE_H
#include "vxlan.h"
#include "zebra.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_ecommunity.h"
/* EVPN prefix lengths. */
#define EVPN_TYPE_2_ROUTE_PREFIXLEN 224
#define EVPN_TYPE_3_ROUTE_PREFIXLEN 224
/* EVPN route types. */
typedef enum
{
BGP_EVPN_AD_ROUTE = 1, /* Ethernet Auto-Discovery (A-D) route */
BGP_EVPN_MAC_IP_ROUTE, /* MAC/IP Advertisement route */
BGP_EVPN_IMET_ROUTE, /* Inclusive Multicast Ethernet Tag route */
BGP_EVPN_ES_ROUTE, /* Ethernet Segment route */
BGP_EVPN_IP_PREFIX_ROUTE, /* IP Prefix route */
} bgp_evpn_route_type;
/*
* Hash table of EVIs. Right now, the only type of EVI supported is with
* VxLAN encapsulation, hence each EVI corresponds to a L2 VNI.
* The VNIs are not "created" through BGP but through some other interface
* on the system. This table stores VNIs that BGP comes to know as present
* on the system (through interaction with zebra) as well as pre-configured
* VNIs (which need to be defined in the system to become "live").
*/
struct bgpevpn
{
vni_t vni;
u_int32_t flags;
#define VNI_FLAG_CFGD 0x1 /* VNI is user configured */
#define VNI_FLAG_LIVE 0x2 /* VNI is "live" */
#define VNI_FLAG_RD_CFGD 0x4 /* RD is user configured. */
#define VNI_FLAG_IMPRT_CFGD 0x8 /* Import RT is user configured */
#define VNI_FLAG_EXPRT_CFGD 0x10 /* Export RT is user configured */
/* Id for deriving the RD automatically for this VNI */
u_int16_t rd_id;
/* RD for this VNI. */
struct prefix_rd prd;
/* Route type 3 field */
struct in_addr originator_ip;
/* Import and Export RTs. */
struct list *import_rtl;
struct list *export_rtl;
/* Route table for EVPN routes for this VNI. */
struct bgp_table *route_table;
QOBJ_FIELDS
};
DECLARE_QOBJ_TYPE(bgpevpn)
/* Mapping of Import RT to VNIs.
* The Import RTs of all VNIs are maintained in a hash table with each
* RT linking to all VNIs that will import routes matching this RT.
*/
struct irt_node
{
/* RT */
struct ecommunity_val rt;
/* List of VNIs importing routes matching this RT. */
struct list *vnis;
};
#define RT_TYPE_IMPORT 1
#define RT_TYPE_EXPORT 2
#define RT_TYPE_BOTH 3
static inline int
is_vni_configured (struct bgpevpn *vpn)
{
return (CHECK_FLAG (vpn->flags, VNI_FLAG_CFGD));
}
static inline int
is_vni_live (struct bgpevpn *vpn)
{
return (CHECK_FLAG (vpn->flags, VNI_FLAG_LIVE));
}
static inline int
is_rd_configured (struct bgpevpn *vpn)
{
return (CHECK_FLAG (vpn->flags, VNI_FLAG_RD_CFGD));
}
static inline int
bgp_evpn_rd_matches_existing (struct bgpevpn *vpn, struct prefix_rd *prd)
{
return(memcmp (&vpn->prd.val, prd->val, ECOMMUNITY_SIZE) == 0);
}
static inline int
is_import_rt_configured (struct bgpevpn *vpn)
{
return (CHECK_FLAG (vpn->flags, VNI_FLAG_IMPRT_CFGD));
}
static inline int
is_export_rt_configured (struct bgpevpn *vpn)
{
return (CHECK_FLAG (vpn->flags, VNI_FLAG_EXPRT_CFGD));
}
static inline int
is_vni_param_configured (struct bgpevpn *vpn)
{
return (is_rd_configured (vpn) ||
is_import_rt_configured (vpn) ||
is_export_rt_configured (vpn));
}
static inline void
vni2label (vni_t vni, mpls_label_t *label)
{
u_char *tag = (u_char *) label;
tag[0] = (vni >> 16) & 0xFF;
tag[1] = (vni >> 8) & 0xFF;
tag[2] = vni & 0xFF;
}
static inline vni_t
label2vni (mpls_label_t *label)
{
u_char *tag = (u_char *) label;
vni_t vni;
vni = ((u_int32_t) *tag++ << 16);
vni |= (u_int32_t) *tag++ << 8;
vni |= (u_int32_t) (*tag & 0xFF);
return vni;
}
static inline void
encode_mac_mobility_extcomm (int static_mac, u_int32_t seq,
struct ecommunity_val *eval)
{
memset (eval, 0, sizeof (*eval));
eval->val[0] = ECOMMUNITY_ENCODE_EVPN;
eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY;
if (static_mac)
eval->val[2] = ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY;
eval->val[4] = (seq >> 24) & 0xff;
eval->val[5] = (seq >> 16) & 0xff;
eval->val[6] = (seq >> 8) & 0xff;
eval->val[7] = seq & 0xff;
}
static inline void
build_evpn_type2_prefix (struct prefix_evpn *p, struct ethaddr *mac,
struct ipaddr *ip)
{
memset (p, 0, sizeof (struct prefix_evpn));
p->family = AF_ETHERNET;
p->prefixlen = EVPN_TYPE_2_ROUTE_PREFIXLEN;
p->prefix.route_type = BGP_EVPN_MAC_IP_ROUTE;
memcpy(&p->prefix.mac.octet, mac->octet, ETHER_ADDR_LEN);
p->prefix.ip.ipa_type = IPADDR_NONE;
if (ip)
memcpy(&p->prefix.ip, ip, sizeof (*ip));
}
static inline void
build_evpn_type3_prefix (struct prefix_evpn *p, struct in_addr originator_ip)
{
memset (p, 0, sizeof (struct prefix_evpn));
p->family = AF_ETHERNET;
p->prefixlen = EVPN_TYPE_3_ROUTE_PREFIXLEN;
p->prefix.route_type = BGP_EVPN_IMET_ROUTE;
p->prefix.ip.ipa_type = IPADDR_V4;
p->prefix.ip.ipaddr_v4 = originator_ip;
}
extern int
bgp_evpn_handle_export_rt_change (struct bgp *bgp, struct bgpevpn *vpn);
extern void
bgp_evpn_handle_rd_change (struct bgp *bgp, struct bgpevpn *vpn, int withdraw);
extern int
bgp_evpn_install_routes (struct bgp *bgp, struct bgpevpn *vpn);
extern int
bgp_evpn_uninstall_routes (struct bgp *bgp, struct bgpevpn *vpn);
extern void
bgp_evpn_map_vni_to_its_rts (struct bgp *bgp, struct bgpevpn *vpn);
extern void
bgp_evpn_unmap_vni_from_its_rts (struct bgp *bgp, struct bgpevpn *vpn);
extern void
bgp_evpn_derive_auto_rt_import (struct bgp *bgp, struct bgpevpn *vpn);
extern void
bgp_evpn_derive_auto_rt_export (struct bgp *bgp, struct bgpevpn *vpn);
extern void
bgp_evpn_derive_auto_rd (struct bgp *bgp, struct bgpevpn *vpn);
extern struct bgpevpn *
bgp_evpn_lookup_vni (struct bgp *bgp, vni_t vni);
extern struct bgpevpn *
bgp_evpn_new (struct bgp *bgp, vni_t vni, struct in_addr originator_ip);
extern void
bgp_evpn_free (struct bgp *bgp, struct bgpevpn *vpn);
#endif /* _BGP_EVPN_PRIVATE_H */

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,9 @@
#ifndef _FRR_BGP_EVPN_VTY_H #ifndef _FRR_BGP_EVPN_VTY_H
#define _FRR_BGP_EVPN_VTY_H #define _FRR_BGP_EVPN_VTY_H
extern void
bgp_config_write_evpn_info (struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi, int *write);
extern void bgp_ethernetvpn_init(void); extern void bgp_ethernetvpn_init(void);
#define L2VPN_HELP_STR "Layer 2 Virtual Private Network\n" #define L2VPN_HELP_STR "Layer 2 Virtual Private Network\n"

View File

@ -151,12 +151,10 @@ bgp_reg_dereg_for_label (struct bgp_node *rn, struct bgp_info *ri,
assert (ri); assert (ri);
if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID)) if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID))
{ {
assert (ri->attr->extra); if (ri->attr->label_index != BGP_INVALID_LABEL_INDEX)
if (ri->attr->extra->label_index != BGP_INVALID_LABEL_INDEX)
{ {
flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX; flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX;
stream_putl (s, ri->attr->extra->label_index); stream_putl (s, ri->attr->label_index);
} }
} }
SET_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL); SET_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);

View File

@ -41,6 +41,9 @@ extern int bgp_nlri_parse_label (struct peer *peer, struct attr *attr,
static inline int static inline int
bgp_labeled_safi (safi_t safi) bgp_labeled_safi (safi_t safi)
{ {
/* NOTE: This API really says a label (tag) MAY be present. Not all EVPN
* routes will have a label.
*/
if ((safi == SAFI_LABELED_UNICAST) || (safi == SAFI_MPLS_VPN) || if ((safi == SAFI_LABELED_UNICAST) || (safi == SAFI_MPLS_VPN) ||
(safi == SAFI_EVPN)) (safi == SAFI_EVPN))
return 1; return 1;

View File

@ -43,7 +43,6 @@ DEFINE_MTYPE(BGPD, BGP_UPDGRP, "BGP update group")
DEFINE_MTYPE(BGPD, BGP_UPD_SUBGRP, "BGP update subgroup") DEFINE_MTYPE(BGPD, BGP_UPD_SUBGRP, "BGP update subgroup")
DEFINE_MTYPE(BGPD, BGP_PACKET, "BGP packet") DEFINE_MTYPE(BGPD, BGP_PACKET, "BGP packet")
DEFINE_MTYPE(BGPD, ATTR, "BGP attribute") DEFINE_MTYPE(BGPD, ATTR, "BGP attribute")
DEFINE_MTYPE(BGPD, ATTR_EXTRA, "BGP extra attributes")
DEFINE_MTYPE(BGPD, AS_PATH, "BGP aspath") DEFINE_MTYPE(BGPD, AS_PATH, "BGP aspath")
DEFINE_MTYPE(BGPD, AS_SEG, "BGP aspath seg") DEFINE_MTYPE(BGPD, AS_SEG, "BGP aspath seg")
DEFINE_MTYPE(BGPD, AS_SEG_DATA, "BGP aspath segment data") DEFINE_MTYPE(BGPD, AS_SEG_DATA, "BGP aspath segment data")
@ -114,3 +113,7 @@ DEFINE_MTYPE(BGPD, BGP_TEA_OPTIONS_VALUE, "BGP TEA Options Value")
DEFINE_MTYPE(BGPD, LCOMMUNITY, "Large Community") DEFINE_MTYPE(BGPD, LCOMMUNITY, "Large Community")
DEFINE_MTYPE(BGPD, LCOMMUNITY_STR, "Large Community display string") DEFINE_MTYPE(BGPD, LCOMMUNITY_STR, "Large Community display string")
DEFINE_MTYPE(BGPD, LCOMMUNITY_VAL, "Large Community value") DEFINE_MTYPE(BGPD, LCOMMUNITY_VAL, "Large Community value")
DEFINE_MTYPE(BGPD, BGP_EVPN, "BGP EVPN Information")
DEFINE_MTYPE(BGPD, BGP_EVPN_IMPORT_RT, "BGP EVPN Import RT")
DEFINE_MTYPE(BGPD, BGP_EVPN_MACIP, "BGP EVPN MAC IP")

View File

@ -39,7 +39,6 @@ DECLARE_MTYPE(BGP_UPDGRP)
DECLARE_MTYPE(BGP_UPD_SUBGRP) DECLARE_MTYPE(BGP_UPD_SUBGRP)
DECLARE_MTYPE(BGP_PACKET) DECLARE_MTYPE(BGP_PACKET)
DECLARE_MTYPE(ATTR) DECLARE_MTYPE(ATTR)
DECLARE_MTYPE(ATTR_EXTRA)
DECLARE_MTYPE(AS_PATH) DECLARE_MTYPE(AS_PATH)
DECLARE_MTYPE(AS_SEG) DECLARE_MTYPE(AS_SEG)
DECLARE_MTYPE(AS_SEG_DATA) DECLARE_MTYPE(AS_SEG_DATA)
@ -110,4 +109,8 @@ DECLARE_MTYPE(BGP_TEA_OPTIONS_VALUE)
DECLARE_MTYPE(LCOMMUNITY) DECLARE_MTYPE(LCOMMUNITY)
DECLARE_MTYPE(LCOMMUNITY_STR) DECLARE_MTYPE(LCOMMUNITY_STR)
DECLARE_MTYPE(LCOMMUNITY_VAL) DECLARE_MTYPE(LCOMMUNITY_VAL)
DECLARE_MTYPE(BGP_EVPN)
DECLARE_MTYPE(BGP_EVPN_IMPORT_RT)
DECLARE_MTYPE(BGP_EVPN_MACIP)
#endif /* _QUAGGA_BGP_MEMORY_H */ #endif /* _QUAGGA_BGP_MEMORY_H */

View File

@ -106,35 +106,31 @@ bgp_maximum_paths_unset (struct bgp *bgp, afi_t afi, safi_t safi,
int int
bgp_info_nexthop_cmp (struct bgp_info *bi1, struct bgp_info *bi2) bgp_info_nexthop_cmp (struct bgp_info *bi1, struct bgp_info *bi2)
{ {
struct attr_extra *ae1, *ae2;
int compare; int compare;
ae1 = bi1->attr->extra;
ae2 = bi2->attr->extra;
compare = IPV4_ADDR_CMP (&bi1->attr->nexthop, &bi2->attr->nexthop); compare = IPV4_ADDR_CMP (&bi1->attr->nexthop, &bi2->attr->nexthop);
if (!compare && ae1 && ae2) if (!compare)
{ {
if (ae1->mp_nexthop_len == ae2->mp_nexthop_len) if (bi1->attr->mp_nexthop_len == bi2->attr->mp_nexthop_len)
{ {
switch (ae1->mp_nexthop_len) switch (bi1->attr->mp_nexthop_len)
{ {
case BGP_ATTR_NHLEN_IPV4: case BGP_ATTR_NHLEN_IPV4:
case BGP_ATTR_NHLEN_VPNV4: case BGP_ATTR_NHLEN_VPNV4:
compare = IPV4_ADDR_CMP (&ae1->mp_nexthop_global_in, compare = IPV4_ADDR_CMP (&bi1->attr->mp_nexthop_global_in,
&ae2->mp_nexthop_global_in); &bi2->attr->mp_nexthop_global_in);
break; break;
case BGP_ATTR_NHLEN_IPV6_GLOBAL: case BGP_ATTR_NHLEN_IPV6_GLOBAL:
case BGP_ATTR_NHLEN_VPNV6_GLOBAL: case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global, compare = IPV6_ADDR_CMP (&bi1->attr->mp_nexthop_global,
&ae2->mp_nexthop_global); &bi2->attr->mp_nexthop_global);
break; break;
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL: case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global, compare = IPV6_ADDR_CMP (&bi1->attr->mp_nexthop_global,
&ae2->mp_nexthop_global); &bi2->attr->mp_nexthop_global);
if (!compare) if (!compare)
compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_local, compare = IPV6_ADDR_CMP (&bi1->attr->mp_nexthop_local,
&ae2->mp_nexthop_local); &bi2->attr->mp_nexthop_local);
break; break;
} }
} }
@ -142,14 +138,14 @@ bgp_info_nexthop_cmp (struct bgp_info *bi1, struct bgp_info *bi2)
/* This can happen if one IPv6 peer sends you global and link-local /* This can happen if one IPv6 peer sends you global and link-local
* nexthops but another IPv6 peer only sends you global * nexthops but another IPv6 peer only sends you global
*/ */
else if (ae1->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL || else if (bi1->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL ||
ae1->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) bi1->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
{ {
compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global, compare = IPV6_ADDR_CMP (&bi1->attr->mp_nexthop_global,
&ae2->mp_nexthop_global); &bi2->attr->mp_nexthop_global);
if (!compare) if (!compare)
{ {
if (ae1->mp_nexthop_len < ae2->mp_nexthop_len) if (bi1->attr->mp_nexthop_len < bi2->attr->mp_nexthop_len)
compare = -1; compare = -1;
else else
compare = 1; compare = 1;
@ -663,7 +659,6 @@ bgp_info_mpath_aggregate_update (struct bgp_info *new_best,
struct community *community, *commerge; struct community *community, *commerge;
struct ecommunity *ecomm, *ecommerge; struct ecommunity *ecomm, *ecommerge;
struct lcommunity *lcomm, *lcommerge; struct lcommunity *lcomm, *lcommerge;
struct attr_extra *ae;
struct attr attr = { 0 }; struct attr attr = { 0 };
if (old_best && (old_best != new_best) && if (old_best && (old_best != new_best) &&
@ -697,9 +692,8 @@ bgp_info_mpath_aggregate_update (struct bgp_info *new_best,
aspath = aspath_dup (attr.aspath); aspath = aspath_dup (attr.aspath);
origin = attr.origin; origin = attr.origin;
community = attr.community ? community_dup (attr.community) : NULL; community = attr.community ? community_dup (attr.community) : NULL;
ae = attr.extra; ecomm = (attr.ecommunity) ? ecommunity_dup (attr.ecommunity) : NULL;
ecomm = (ae && ae->ecommunity) ? ecommunity_dup (ae->ecommunity) : NULL; lcomm = (attr.lcommunity) ? lcommunity_dup (attr.lcommunity) : NULL;
lcomm = (ae && ae->lcommunity) ? lcommunity_dup (ae->lcommunity) : NULL;
for (mpinfo = bgp_info_mpath_first (new_best); mpinfo; for (mpinfo = bgp_info_mpath_first (new_best); mpinfo;
mpinfo = bgp_info_mpath_next (mpinfo)) mpinfo = bgp_info_mpath_next (mpinfo))
@ -723,28 +717,27 @@ bgp_info_mpath_aggregate_update (struct bgp_info *new_best,
community = community_dup (mpinfo->attr->community); community = community_dup (mpinfo->attr->community);
} }
ae = mpinfo->attr->extra; if (mpinfo->attr->ecommunity)
if (ae && ae->ecommunity)
{ {
if (ecomm) if (ecomm)
{ {
ecommerge = ecommunity_merge (ecomm, ae->ecommunity); ecommerge = ecommunity_merge (ecomm, mpinfo->attr->ecommunity);
ecomm = ecommunity_uniq_sort (ecommerge); ecomm = ecommunity_uniq_sort (ecommerge);
ecommunity_free (&ecommerge); ecommunity_free (&ecommerge);
} }
else else
ecomm = ecommunity_dup (ae->ecommunity); ecomm = ecommunity_dup (mpinfo->attr->ecommunity);
} }
if (ae && ae->lcommunity) if (mpinfo->attr->lcommunity)
{ {
if (lcomm) if (lcomm)
{ {
lcommerge = lcommunity_merge (lcomm, ae->lcommunity); lcommerge = lcommunity_merge (lcomm, mpinfo->attr->lcommunity);
lcomm = lcommunity_uniq_sort (lcommerge); lcomm = lcommunity_uniq_sort (lcommerge);
lcommunity_free (&lcommerge); lcommunity_free (&lcommerge);
} }
else else
lcomm = lcommunity_dup (ae->lcommunity); lcomm = lcommunity_dup (mpinfo->attr->lcommunity);
} }
} }
@ -757,21 +750,18 @@ bgp_info_mpath_aggregate_update (struct bgp_info *new_best,
} }
if (ecomm) if (ecomm)
{ {
ae = bgp_attr_extra_get (&attr); attr.ecommunity = ecomm;
ae->ecommunity = ecomm;
attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES); attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
} }
/* Zap multipath attr nexthop so we set nexthop to self */ /* Zap multipath attr nexthop so we set nexthop to self */
attr.nexthop.s_addr = 0; attr.nexthop.s_addr = 0;
if (attr.extra) memset (&attr.mp_nexthop_global, 0, sizeof (struct in6_addr));
memset (&attr.extra->mp_nexthop_global, 0, sizeof (struct in6_addr));
/* TODO: should we set ATOMIC_AGGREGATE and AGGREGATOR? */ /* TODO: should we set ATOMIC_AGGREGATE and AGGREGATOR? */
} }
new_attr = bgp_attr_intern (&attr); new_attr = bgp_attr_intern (&attr);
bgp_attr_extra_free (&attr);
if (new_attr != bgp_info_mpath_attr (new_best)) if (new_attr != bgp_info_mpath_attr (new_best))
{ {

View File

@ -62,31 +62,6 @@ argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc, int *index, afi_t *
return ret; return ret;
} }
u_int16_t
decode_rd_type (u_char *pnt)
{
u_int16_t v;
v = ((u_int16_t) *pnt++ << 8);
#if ENABLE_BGP_VNC
/*
* VNC L2 stores LHI in lower byte, so omit it
*/
if (v != RD_TYPE_VNC_ETH)
v |= (u_int16_t) *pnt;
#else /* duplicate code for clarity */
v |= (u_int16_t) *pnt;
#endif
return v;
}
void
encode_rd_type (u_int16_t v, u_char *pnt)
{
*((u_int16_t *)pnt) = htons(v);
}
u_int32_t u_int32_t
decode_label (mpls_label_t *label_pnt) decode_label (mpls_label_t *label_pnt)
{ {
@ -111,54 +86,6 @@ encode_label(mpls_label_t label,
*pnt++ = ((label<<4)+1) & 0xff; /* S=1 */ *pnt++ = ((label<<4)+1) & 0xff; /* S=1 */
} }
/* type == RD_TYPE_AS */
void
decode_rd_as (u_char *pnt, struct rd_as *rd_as)
{
rd_as->as = (u_int16_t) *pnt++ << 8;
rd_as->as |= (u_int16_t) *pnt++;
rd_as->val = ((u_int32_t) *pnt++ << 24);
rd_as->val |= ((u_int32_t) *pnt++ << 16);
rd_as->val |= ((u_int32_t) *pnt++ << 8);
rd_as->val |= (u_int32_t) *pnt;
}
/* type == RD_TYPE_AS4 */
void
decode_rd_as4 (u_char *pnt, struct rd_as *rd_as)
{
rd_as->as = (u_int32_t) *pnt++ << 24;
rd_as->as |= (u_int32_t) *pnt++ << 16;
rd_as->as |= (u_int32_t) *pnt++ << 8;
rd_as->as |= (u_int32_t) *pnt++;
rd_as->val = ((u_int16_t) *pnt++ << 8);
rd_as->val |= (u_int16_t) *pnt;
}
/* type == RD_TYPE_IP */
void
decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip)
{
memcpy (&rd_ip->ip, pnt, 4);
pnt += 4;
rd_ip->val = ((u_int16_t) *pnt++ << 8);
rd_ip->val |= (u_int16_t) *pnt;
}
#if ENABLE_BGP_VNC
/* type == RD_TYPE_VNC_ETH */
void
decode_rd_vnc_eth (u_char *pnt, struct rd_vnc_eth *rd_vnc_eth)
{
rd_vnc_eth->type = RD_TYPE_VNC_ETH;
rd_vnc_eth->local_nve_id = pnt[1];
memcpy (rd_vnc_eth->macaddr.octet, pnt + 2, ETHER_ADDR_LEN);
}
#endif
int int
bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr, bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
struct bgp_nlri *packet) struct bgp_nlri *packet)
@ -313,129 +240,6 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
#undef VPN_PREFIXLEN_MIN_BYTES #undef VPN_PREFIXLEN_MIN_BYTES
} }
int
str2prefix_rd (const char *str, struct prefix_rd *prd)
{
int ret; /* ret of called functions */
int lret; /* local ret, of this func */
char *p;
char *p2;
struct stream *s = NULL;
char *half = NULL;
struct in_addr addr;
s = stream_new (8);
prd->family = AF_UNSPEC;
prd->prefixlen = 64;
lret = 0;
p = strchr (str, ':');
if (! p)
goto out;
if (! all_digit (p + 1))
goto out;
half = XMALLOC (MTYPE_TMP, (p - str) + 1);
memcpy (half, str, (p - str));
half[p - str] = '\0';
p2 = strchr (str, '.');
if (! p2)
{
unsigned long as_val;
if (! all_digit (half))
goto out;
as_val = atol(half);
if (as_val > 0xffff)
{
stream_putw (s, RD_TYPE_AS4);
stream_putl (s, as_val);
stream_putw (s, atol (p + 1));
}
else
{
stream_putw (s, RD_TYPE_AS);
stream_putw (s, as_val);
stream_putl (s, atol (p + 1));
}
}
else
{
ret = inet_aton (half, &addr);
if (! ret)
goto out;
stream_putw (s, RD_TYPE_IP);
stream_put_in_addr (s, &addr);
stream_putw (s, atol (p + 1));
}
memcpy (prd->val, s->data, 8);
lret = 1;
out:
if (s)
stream_free (s);
if (half)
XFREE(MTYPE_TMP, half);
return lret;
}
char *
prefix_rd2str (struct prefix_rd *prd, char *buf, size_t size)
{
u_char *pnt;
u_int16_t type;
struct rd_as rd_as;
struct rd_ip rd_ip;
if (size < RD_ADDRSTRLEN)
return NULL;
pnt = prd->val;
type = decode_rd_type (pnt);
if (type == RD_TYPE_AS)
{
decode_rd_as (pnt + 2, &rd_as);
snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val);
return buf;
}
else if (type == RD_TYPE_AS4)
{
decode_rd_as4 (pnt + 2, &rd_as);
snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val);
return buf;
}
else if (type == RD_TYPE_IP)
{
decode_rd_ip (pnt + 2, &rd_ip);
snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
return buf;
}
#if ENABLE_BGP_VNC
else if (type == RD_TYPE_VNC_ETH)
{
snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x",
*(pnt+1), /* LHI */
*(pnt+2), /* MAC[0] */
*(pnt+3),
*(pnt+4),
*(pnt+5),
*(pnt+6),
*(pnt+7));
return buf;
}
#endif
return NULL;
}
/* For testing purpose, static route of MPLS-VPN. */ /* For testing purpose, static route of MPLS-VPN. */
DEFUN (vpnv4_network, DEFUN (vpnv4_network,
vpnv4_network_cmd, vpnv4_network_cmd,

View File

@ -1,7 +1,7 @@
/* MPLS-VPN /* MPLS-VPN
* Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org> * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
* *
* This file is part of GNU Zebra. * This file is part of GxNU Zebra.
* *
* GNU Zebra is free software; you can redistribute it and/or modify it * GNU Zebra is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
@ -22,15 +22,7 @@
#define _QUAGGA_BGP_MPLSVPN_H #define _QUAGGA_BGP_MPLSVPN_H
#include "bgpd/bgp_route.h" #include "bgpd/bgp_route.h"
#include "bgpd/bgp_rd.h"
#define RD_TYPE_AS 0
#define RD_TYPE_IP 1
#define RD_TYPE_AS4 2
#if ENABLE_BGP_VNC
#define RD_TYPE_VNC_ETH 0xff00 /* VNC L2VPN */
#endif
#define RD_ADDRSTRLEN 28
#ifdef MPLS_LABEL_MAX #ifdef MPLS_LABEL_MAX
# undef MPLS_LABEL_MAX # undef MPLS_LABEL_MAX
@ -74,44 +66,10 @@ typedef enum {
#define V4_HEADER_OVERLAY \ #define V4_HEADER_OVERLAY \
" Network Next Hop EthTag Overlay Index RouterMac\n" " Network Next Hop EthTag Overlay Index RouterMac\n"
struct rd_as
{
u_int16_t type;
as_t as;
u_int32_t val;
};
struct rd_ip
{
u_int16_t type;
struct in_addr ip;
u_int16_t val;
};
#if ENABLE_BGP_VNC
struct rd_vnc_eth
{
u_int16_t type;
uint8_t local_nve_id;
struct ethaddr macaddr;
};
#endif
extern u_int16_t decode_rd_type (u_char *);
extern void encode_rd_type (u_int16_t, u_char *);
extern void bgp_mplsvpn_init (void); extern void bgp_mplsvpn_init (void);
extern int bgp_nlri_parse_vpn (struct peer *, struct attr *, struct bgp_nlri *); extern int bgp_nlri_parse_vpn (struct peer *, struct attr *, struct bgp_nlri *);
extern u_int32_t decode_label (mpls_label_t *); extern u_int32_t decode_label (mpls_label_t *);
extern void encode_label(mpls_label_t, mpls_label_t *); extern void encode_label(mpls_label_t, mpls_label_t *);
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_rd_vnc_eth (u_char *pnt, struct rd_vnc_eth *rd_vnc_eth);
#endif
extern int str2prefix_rd (const char *, struct prefix_rd *);
extern char *prefix_rd2str (struct prefix_rd *, char *, size_t);
extern int extern int
argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc, int *index, afi_t *afi); argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc, int *index, afi_t *afi);

View File

@ -329,11 +329,11 @@ bgp_connected_delete (struct bgp *bgp, struct connected *ifc)
} }
int int
bgp_nexthop_self (struct bgp *bgp, struct attr *attr) bgp_nexthop_self (struct bgp *bgp, struct in_addr nh_addr)
{ {
struct bgp_addr tmp, *addr; struct bgp_addr tmp, *addr;
tmp.addr = attr->nexthop; tmp.addr = nh_addr;
addr = hash_lookup (bgp->address_hash, &tmp); addr = hash_lookup (bgp->address_hash, &tmp);
if (addr) if (addr)

View File

@ -74,7 +74,7 @@ extern void bgp_connected_add (struct bgp *bgp, struct connected *c);
extern void bgp_connected_delete (struct bgp *bgp, struct connected *c); extern void bgp_connected_delete (struct bgp *bgp, struct connected *c);
extern int bgp_multiaccess_check_v4 (struct in_addr, struct peer *); extern int bgp_multiaccess_check_v4 (struct in_addr, struct peer *);
extern int bgp_config_write_scan_time (struct vty *); extern int bgp_config_write_scan_time (struct vty *);
extern int bgp_nexthop_self (struct bgp *, struct attr *); extern int bgp_nexthop_self (struct bgp *, struct in_addr);
extern struct bgp_nexthop_cache *bnc_new(void); extern struct bgp_nexthop_cache *bnc_new(void);
extern void bnc_free(struct bgp_nexthop_cache *bnc); extern void bnc_free(struct bgp_nexthop_cache *bnc);
extern void bnc_nexthop_free(struct bgp_nexthop_cache *bnc); extern void bnc_nexthop_free(struct bgp_nexthop_cache *bnc);

View File

@ -532,8 +532,8 @@ make_prefix (int afi, struct bgp_info *ri, struct prefix *p)
break; break;
case AFI_IP6: case AFI_IP6:
/* We don't register link local NH */ /* We don't register link local NH */
if (ri->attr->extra->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL if (ri->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL
|| IN6_IS_ADDR_LINKLOCAL (&ri->attr->extra->mp_nexthop_global)) || IN6_IS_ADDR_LINKLOCAL (&ri->attr->mp_nexthop_global))
return -1; return -1;
p->family = AF_INET6; p->family = AF_INET6;
@ -545,7 +545,7 @@ make_prefix (int afi, struct bgp_info *ri, struct prefix *p)
} }
else else
{ {
p->u.prefix6 = ri->attr->extra->mp_nexthop_global; p->u.prefix6 = ri->attr->mp_nexthop_global;
p->prefixlen = IPV6_MAX_BITLEN; p->prefixlen = IPV6_MAX_BITLEN;
} }
break; break;

View File

@ -1364,7 +1364,6 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
u_char *end; u_char *end;
struct stream *s; struct stream *s;
struct attr attr; struct attr attr;
struct attr_extra extra;
bgp_size_t attribute_len; bgp_size_t attribute_len;
bgp_size_t update_len; bgp_size_t update_len;
bgp_size_t withdraw_len; bgp_size_t withdraw_len;
@ -1389,11 +1388,9 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
/* Set initial values. */ /* Set initial values. */
memset (&attr, 0, sizeof (struct attr)); memset (&attr, 0, sizeof (struct attr));
memset (&extra, 0, sizeof (struct attr_extra)); attr.label_index = BGP_INVALID_LABEL_INDEX;
extra.label_index = BGP_INVALID_LABEL_INDEX; attr.label = MPLS_INVALID_LABEL;
extra.label = MPLS_INVALID_LABEL;
memset (&nlris, 0, sizeof (nlris)); memset (&nlris, 0, sizeof (nlris));
attr.extra = &extra;
memset (peer->rcvd_attr_str, 0, BUFSIZ); memset (peer->rcvd_attr_str, 0, BUFSIZ);
peer->rcvd_attr_printed = 0; peer->rcvd_attr_printed = 0;

232
bgpd/bgp_rd.c Normal file
View File

@ -0,0 +1,232 @@
/* BGP RD definitions for BGP-based VPNs (IP/EVPN)
* -- brought over from bgpd/bgp_mplsvpn.c
* Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
*
* This file is part of FRR.
*
* FRR 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.
*
* FRR 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 FRR; 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 "log.h"
#include "prefix.h"
#include "memory.h"
#include "stream.h"
#include "filter.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_rd.h"
#include "bgpd/bgp_attr.h"
#if ENABLE_BGP_VNC
#include "bgpd/rfapi/rfapi_backend.h"
#endif
u_int16_t
decode_rd_type (u_char *pnt)
{
u_int16_t v;
v = ((u_int16_t) *pnt++ << 8);
#if ENABLE_BGP_VNC
/*
* VNC L2 stores LHI in lower byte, so omit it
*/
if (v != RD_TYPE_VNC_ETH)
v |= (u_int16_t) *pnt;
#else /* duplicate code for clarity */
v |= (u_int16_t) *pnt;
#endif
return v;
}
void
encode_rd_type (u_int16_t v, u_char *pnt)
{
*((u_int16_t *)pnt) = htons(v);
}
/* type == RD_TYPE_AS */
void
decode_rd_as (u_char *pnt, struct rd_as *rd_as)
{
rd_as->as = (u_int16_t) *pnt++ << 8;
rd_as->as |= (u_int16_t) *pnt++;
rd_as->val = ((u_int32_t) *pnt++ << 24);
rd_as->val |= ((u_int32_t) *pnt++ << 16);
rd_as->val |= ((u_int32_t) *pnt++ << 8);
rd_as->val |= (u_int32_t) *pnt;
}
/* type == RD_TYPE_AS4 */
void
decode_rd_as4 (u_char *pnt, struct rd_as *rd_as)
{
rd_as->as = (u_int32_t) *pnt++ << 24;
rd_as->as |= (u_int32_t) *pnt++ << 16;
rd_as->as |= (u_int32_t) *pnt++ << 8;
rd_as->as |= (u_int32_t) *pnt++;
rd_as->val = ((u_int16_t) *pnt++ << 8);
rd_as->val |= (u_int16_t) *pnt;
}
/* type == RD_TYPE_IP */
void
decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip)
{
memcpy (&rd_ip->ip, pnt, 4);
pnt += 4;
rd_ip->val = ((u_int16_t) *pnt++ << 8);
rd_ip->val |= (u_int16_t) *pnt;
}
#if ENABLE_BGP_VNC
/* type == RD_TYPE_VNC_ETH */
void
decode_rd_vnc_eth (u_char *pnt, struct rd_vnc_eth *rd_vnc_eth)
{
rd_vnc_eth->type = RD_TYPE_VNC_ETH;
rd_vnc_eth->local_nve_id = pnt[1];
memcpy (rd_vnc_eth->macaddr.octet, pnt + 2, ETHER_ADDR_LEN);
}
#endif
int
str2prefix_rd (const char *str, struct prefix_rd *prd)
{
int ret; /* ret of called functions */
int lret; /* local ret, of this func */
char *p;
char *p2;
struct stream *s = NULL;
char *half = NULL;
struct in_addr addr;
s = stream_new (8);
prd->family = AF_UNSPEC;
prd->prefixlen = 64;
lret = 0;
p = strchr (str, ':');
if (! p)
goto out;
if (! all_digit (p + 1))
goto out;
half = XMALLOC (MTYPE_TMP, (p - str) + 1);
memcpy (half, str, (p - str));
half[p - str] = '\0';
p2 = strchr (str, '.');
if (! p2)
{
unsigned long as_val;
if (! all_digit (half))
goto out;
as_val = atol(half);
if (as_val > 0xffff)
{
stream_putw (s, RD_TYPE_AS4);
stream_putl (s, as_val);
stream_putw (s, atol (p + 1));
}
else
{
stream_putw (s, RD_TYPE_AS);
stream_putw (s, as_val);
stream_putl (s, atol (p + 1));
}
}
else
{
ret = inet_aton (half, &addr);
if (! ret)
goto out;
stream_putw (s, RD_TYPE_IP);
stream_put_in_addr (s, &addr);
stream_putw (s, atol (p + 1));
}
memcpy (prd->val, s->data, 8);
lret = 1;
out:
if (s)
stream_free (s);
if (half)
XFREE(MTYPE_TMP, half);
return lret;
}
char *
prefix_rd2str (struct prefix_rd *prd, char *buf, size_t size)
{
u_char *pnt;
u_int16_t type;
struct rd_as rd_as;
struct rd_ip rd_ip;
if (size < RD_ADDRSTRLEN)
return NULL;
pnt = prd->val;
type = decode_rd_type (pnt);
if (type == RD_TYPE_AS)
{
decode_rd_as (pnt + 2, &rd_as);
snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val);
return buf;
}
else if (type == RD_TYPE_AS4)
{
decode_rd_as4 (pnt + 2, &rd_as);
snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val);
return buf;
}
else if (type == RD_TYPE_IP)
{
decode_rd_ip (pnt + 2, &rd_ip);
snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
return buf;
}
#if ENABLE_BGP_VNC
else if (type == RD_TYPE_VNC_ETH)
{
snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x",
*(pnt+1), /* LHI */
*(pnt+2), /* MAC[0] */
*(pnt+3),
*(pnt+4),
*(pnt+5),
*(pnt+6),
*(pnt+7));
return buf;
}
#endif
return NULL;
}

74
bgpd/bgp_rd.h Normal file
View File

@ -0,0 +1,74 @@
/* BGP RD definitions for BGP-based VPNs (IP/EVPN)
* -- brought over from bgpd/bgp_mplsvpn.h
* Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
*
* This file is part of FRR.
*
* FRR 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.
*
* FRR 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 FRR; 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_RD_H
#define _QUAGGA_BGP_RD_H
/* RD types */
#define RD_TYPE_AS 0
#define RD_TYPE_IP 1
#define RD_TYPE_AS4 2
#if ENABLE_BGP_VNC
#define RD_TYPE_VNC_ETH 0xff00 /* VNC L2VPN */
#endif
#define RD_ADDRSTRLEN 28
struct rd_as
{
u_int16_t type;
as_t as;
u_int32_t val;
};
struct rd_ip
{
u_int16_t type;
struct in_addr ip;
u_int16_t val;
};
#if ENABLE_BGP_VNC
struct rd_vnc_eth
{
u_int16_t type;
uint8_t local_nve_id;
struct ethaddr macaddr;
};
#endif
extern u_int16_t decode_rd_type (u_char *pnt);
extern void encode_rd_type (u_int16_t, u_char *);
extern void decode_rd_as (u_char *pnt, struct rd_as *rd_as);
extern void decode_rd_as4 (u_char *pnt, struct rd_as *rd_as);
extern void decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip);
#if ENABLE_BGP_VNC
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 char *prefix_rd2str (struct prefix_rd *, char *, size_t);
#endif /* _QUAGGA_BGP_RD_H */

File diff suppressed because it is too large Load Diff

View File

@ -99,6 +99,9 @@ struct bgp_info_extra
} vnc; } vnc;
#endif #endif
/* For imported routes into a VNI (or VRF), this points to the parent. */
void *parent;
}; };
struct bgp_info struct bgp_info
@ -174,6 +177,13 @@ struct bgp_info
}; };
/* Structure used in BGP path selection */
struct bgp_info_pair
{
struct bgp_info *old;
struct bgp_info *new;
};
/* BGP static route configuration. */ /* BGP static route configuration. */
struct bgp_static struct bgp_static
{ {
@ -222,8 +232,8 @@ struct bgp_static
#define BGP_ATTR_NEXTHOP_AFI_IP6(attr) \ #define BGP_ATTR_NEXTHOP_AFI_IP6(attr) \
(! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)) && \ (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)) && \
(attr)->extra && ((attr)->extra->mp_nexthop_len == 16 || \ ((attr)->mp_nexthop_len == 16 || \
(attr)->extra->mp_nexthop_len == 32)) (attr)->mp_nexthop_len == 32))
#define BGP_INFO_COUNTABLE(BI) \ #define BGP_INFO_COUNTABLE(BI) \
(! CHECK_FLAG ((BI)->flags, BGP_INFO_HISTORY) \ (! CHECK_FLAG ((BI)->flags, BGP_INFO_HISTORY) \
&& ! CHECK_FLAG ((BI)->flags, BGP_INFO_REMOVED)) && ! CHECK_FLAG ((BI)->flags, BGP_INFO_REMOVED))
@ -309,6 +319,7 @@ extern struct bgp_node *bgp_afi_node_get (struct bgp_table *table, afi_t afi,
extern struct bgp_info *bgp_info_lock (struct bgp_info *); extern struct bgp_info *bgp_info_lock (struct bgp_info *);
extern struct bgp_info *bgp_info_unlock (struct bgp_info *); extern struct bgp_info *bgp_info_unlock (struct bgp_info *);
extern void bgp_info_add (struct bgp_node *rn, struct bgp_info *ri); extern void bgp_info_add (struct bgp_node *rn, struct bgp_info *ri);
extern void bgp_info_reap (struct bgp_node *rn, struct bgp_info *ri);
extern void bgp_info_delete (struct bgp_node *rn, struct bgp_info *ri); extern void bgp_info_delete (struct bgp_node *rn, struct bgp_info *ri);
extern struct bgp_info_extra *bgp_info_extra_get (struct bgp_info *); extern struct bgp_info_extra *bgp_info_extra_get (struct bgp_info *);
extern void bgp_info_set_flag (struct bgp_node *, struct bgp_info *, u_int32_t); extern void bgp_info_set_flag (struct bgp_node *, struct bgp_info *, u_int32_t);
@ -372,6 +383,10 @@ extern u_char bgp_distance_apply (struct prefix *, struct bgp_info *, afi_t, saf
extern afi_t bgp_node_afi (struct vty *); extern afi_t bgp_node_afi (struct vty *);
extern safi_t bgp_node_safi (struct vty *); extern safi_t bgp_node_safi (struct vty *);
extern struct bgp_info *
info_make (int type, int sub_type, u_short instance, struct peer *peer,
struct attr *attr, struct bgp_node *rn);
extern void route_vty_out (struct vty *, struct prefix *, struct bgp_info *, int, safi_t, json_object *); 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_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_tmp (struct vty *, struct prefix *, struct attr *, safi_t, u_char, json_object *);
@ -396,10 +411,32 @@ extern void bgp_process_queues_drain_immediate (void);
extern struct bgp_node * extern struct bgp_node *
bgp_afi_node_get (struct bgp_table *, afi_t , safi_t , struct prefix *, bgp_afi_node_get (struct bgp_table *, afi_t , safi_t , struct prefix *,
struct prefix_rd *); struct prefix_rd *);
extern struct bgp_node *
bgp_afi_node_lookup (struct bgp_table *table, afi_t afi, safi_t safi,
struct prefix *p, struct prefix_rd *prd);
extern struct bgp_info *bgp_info_new (void); extern struct bgp_info *bgp_info_new (void);
extern void bgp_info_restore (struct bgp_node *, struct bgp_info *); extern void bgp_info_restore (struct bgp_node *, struct bgp_info *);
extern int bgp_info_cmp_compatible (struct bgp *, struct bgp_info *, extern int
struct bgp_info *, afi_t, safi_t ); bgp_info_cmp_compatible (struct bgp *, struct bgp_info *, struct bgp_info *,
char *pfx_buf, afi_t afi, safi_t safi);
extern void
bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
struct bgp_maxpaths_cfg *mpath_cfg,
struct bgp_info_pair *result,
afi_t afi, safi_t safi);
extern void bgp_zebra_clear_route_change_flags (struct bgp_node *rn);
extern int
bgp_zebra_has_route_changed (struct bgp_node *rn, struct bgp_info *selected);
extern void
route_vty_out_detail_header (struct vty *vty, struct bgp *bgp,
struct bgp_node *rn,
struct prefix_rd *prd, afi_t afi, safi_t safi,
json_object *json);
extern void
route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
struct bgp_info *binfo, afi_t afi, safi_t safi,
json_object *json_paths);
#endif /* _QUAGGA_BGP_ROUTE_H */ #endif /* _QUAGGA_BGP_ROUTE_H */

View File

@ -868,8 +868,7 @@ route_match_lcommunity (void *rule, struct prefix *prefix,
if (! list) if (! list)
return RMAP_NOMATCH; return RMAP_NOMATCH;
if (bgp_info->attr->extra && if (lcommunity_list_match (bgp_info->attr->lcommunity, list))
lcommunity_list_match (bgp_info->attr->extra->lcommunity, list))
return RMAP_MATCH; return RMAP_MATCH;
} }
@ -933,15 +932,12 @@ route_match_ecommunity (void *rule, struct prefix *prefix,
{ {
bgp_info = object; bgp_info = object;
if (!bgp_info->attr->extra)
return RMAP_NOMATCH;
list = community_list_lookup (bgp_clist, (char *) rule, list = community_list_lookup (bgp_clist, (char *) rule,
EXTCOMMUNITY_LIST_MASTER); EXTCOMMUNITY_LIST_MASTER);
if (! list) if (! list)
return RMAP_NOMATCH; return RMAP_NOMATCH;
if (ecommunity_list_match (bgp_info->attr->extra->ecommunity, list)) if (ecommunity_list_match (bgp_info->attr->ecommunity, list))
return RMAP_MATCH; return RMAP_MATCH;
} }
return RMAP_NOMATCH; return RMAP_NOMATCH;
@ -1149,10 +1145,7 @@ route_match_tag (void *rule, struct prefix *prefix,
tag = rule; tag = rule;
bgp_info = object; bgp_info = object;
if (!bgp_info->attr->extra) return ((bgp_info->attr->tag == *tag)? RMAP_MATCH : RMAP_NOMATCH);
return RMAP_NOMATCH;
return ((bgp_info->attr->extra->tag == *tag)? RMAP_MATCH : RMAP_NOMATCH);
} }
return RMAP_NOMATCH; return RMAP_NOMATCH;
@ -1332,7 +1325,6 @@ route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type,
{ {
struct rmap_value *rv; struct rmap_value *rv;
struct bgp_info *bgp_info; struct bgp_info *bgp_info;
u_int32_t weight;
if (type == RMAP_BGP) if (type == RMAP_BGP)
{ {
@ -1341,11 +1333,7 @@ route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type,
bgp_info = object; bgp_info = object;
/* Set weight value. */ /* Set weight value. */
weight = route_value_adjust(rv, 0, bgp_info->peer); bgp_info->attr->weight = route_value_adjust(rv, 0, bgp_info->peer);
if (weight)
(bgp_attr_extra_get (bgp_info->attr))->weight = weight;
else if (bgp_info->attr->extra)
bgp_info->attr->extra->weight = 0;
} }
return RMAP_OKAY; return RMAP_OKAY;
@ -1644,14 +1632,13 @@ route_set_lcommunity (void *rule, struct prefix *prefix,
rcs = rule; rcs = rule;
binfo = object; binfo = object;
attr = binfo->attr; attr = binfo->attr;
old = (attr->extra) ? attr->extra->lcommunity : NULL; old = attr->lcommunity;
/* "none" case. */ /* "none" case. */
if (rcs->none) if (rcs->none)
{ {
attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES)); attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES));
if (attr->extra) attr->lcommunity = NULL;
attr->extra->lcommunity = NULL;
/* See the longer comment down below. */ /* See the longer comment down below. */
if (old && old->refcnt == 0) if (old && old->refcnt == 0)
@ -1676,7 +1663,7 @@ route_set_lcommunity (void *rule, struct prefix *prefix,
new = lcommunity_dup (rcs->lcom); new = lcommunity_dup (rcs->lcom);
/* will be intern()'d or attr_flush()'d by bgp_update_main() */ /* will be intern()'d or attr_flush()'d by bgp_update_main() */
(bgp_attr_extra_get (attr))->lcommunity = new; attr->lcommunity = new;
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
} }
@ -1766,7 +1753,7 @@ route_set_lcommunity_delete (void *rule, struct prefix *prefix,
binfo = object; binfo = object;
list = community_list_lookup (bgp_clist, rule, list = community_list_lookup (bgp_clist, rule,
LARGE_COMMUNITY_LIST_MASTER); LARGE_COMMUNITY_LIST_MASTER);
old = ((binfo->attr->extra) ? binfo->attr->extra->lcommunity : NULL); old = binfo->attr->lcommunity;
if (list && old) if (list && old)
{ {
@ -1783,13 +1770,13 @@ route_set_lcommunity_delete (void *rule, struct prefix *prefix,
if (new->size == 0) if (new->size == 0)
{ {
binfo->attr->extra->lcommunity = NULL; binfo->attr->lcommunity = NULL;
binfo->attr->flag &= ~ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); binfo->attr->flag &= ~ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
lcommunity_free (&new); lcommunity_free (&new);
} }
else else
{ {
binfo->attr->extra->lcommunity = new; binfo->attr->lcommunity = new;
binfo->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); binfo->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
} }
} }
@ -1946,7 +1933,7 @@ route_set_ecommunity (void *rule, struct prefix *prefix,
return RMAP_OKAY; return RMAP_OKAY;
/* We assume additive for Extended Community. */ /* We assume additive for Extended Community. */
old_ecom = (bgp_attr_extra_get (bgp_info->attr))->ecommunity; old_ecom = bgp_info->attr->ecommunity;
if (old_ecom) if (old_ecom)
{ {
@ -1961,7 +1948,7 @@ route_set_ecommunity (void *rule, struct prefix *prefix,
new_ecom = ecommunity_dup (ecom); new_ecom = ecommunity_dup (ecom);
/* will be intern()'d or attr_flush()'d by bgp_update_main() */ /* will be intern()'d or attr_flush()'d by bgp_update_main() */
bgp_info->attr->extra->ecommunity = new_ecom; bgp_info->attr->ecommunity = new_ecom;
bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES); bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
} }
@ -2129,16 +2116,14 @@ route_set_aggregator_as (void *rule, struct prefix *prefix,
{ {
struct bgp_info *bgp_info; struct bgp_info *bgp_info;
struct aggregator *aggregator; struct aggregator *aggregator;
struct attr_extra *ae;
if (type == RMAP_BGP) if (type == RMAP_BGP)
{ {
bgp_info = object; bgp_info = object;
aggregator = rule; aggregator = rule;
ae = bgp_attr_extra_get (bgp_info->attr);
ae->aggregator_as = aggregator->as; bgp_info->attr->aggregator_as = aggregator->as;
ae->aggregator_addr = aggregator->address; bgp_info->attr->aggregator_addr = aggregator->address;
bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR); bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
} }
@ -2187,16 +2172,14 @@ route_set_tag (void *rule, struct prefix *prefix,
{ {
route_tag_t *tag; route_tag_t *tag;
struct bgp_info *bgp_info; struct bgp_info *bgp_info;
struct attr_extra *ae;
if (type == RMAP_BGP) if (type == RMAP_BGP)
{ {
tag = rule; tag = rule;
bgp_info = object; bgp_info = object;
ae = bgp_attr_extra_get (bgp_info->attr);
/* Set tag value */ /* Set tag value */
ae->tag=*tag; bgp_info->attr->tag=*tag;
} }
@ -2231,7 +2214,7 @@ route_set_label_index (void *rule, struct prefix *prefix,
label_index = rv->value; label_index = rv->value;
if (label_index) if (label_index)
{ {
(bgp_attr_extra_get (bgp_info->attr))->label_index = label_index; bgp_info->attr->label_index = label_index;
bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID); bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID);
} }
} }
@ -2302,14 +2285,11 @@ route_match_ipv6_next_hop (void *rule, struct prefix *prefix,
{ {
bgp_info = object; bgp_info = object;
if (!bgp_info->attr->extra) if (IPV6_ADDR_SAME (&bgp_info->attr->mp_nexthop_global, addr))
return RMAP_NOMATCH;
if (IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_global, addr))
return RMAP_MATCH; return RMAP_MATCH;
if (bgp_info->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL && if (bgp_info->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL &&
IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_local, rule)) IPV6_ADDR_SAME (&bgp_info->attr->mp_nexthop_local, rule))
return RMAP_MATCH; return RMAP_MATCH;
return RMAP_NOMATCH; return RMAP_NOMATCH;
@ -2407,11 +2387,11 @@ route_set_ipv6_nexthop_global (void *rule, struct prefix *prefix,
bgp_info = object; bgp_info = object;
/* Set next hop value. */ /* Set next hop value. */
(bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global = *address; bgp_info->attr->mp_nexthop_global = *address;
/* Set nexthop length. */ /* Set nexthop length. */
if (bgp_info->attr->extra->mp_nexthop_len == 0) if (bgp_info->attr->mp_nexthop_len == 0)
bgp_info->attr->extra->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; bgp_info->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
SET_FLAG(bgp_info->attr->rmap_change_flags, SET_FLAG(bgp_info->attr->rmap_change_flags,
BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED); BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
@ -2477,13 +2457,13 @@ route_set_ipv6_nexthop_prefer_global (void *rule, struct prefix *prefix,
&& sockunion_family (peer->su_remote) == AF_INET6) && sockunion_family (peer->su_remote) == AF_INET6)
{ {
/* Set next hop preference to global */ /* Set next hop preference to global */
bgp_info->attr->extra->mp_nexthop_prefer_global = TRUE; bgp_info->attr->mp_nexthop_prefer_global = TRUE;
SET_FLAG(bgp_info->attr->rmap_change_flags, SET_FLAG(bgp_info->attr->rmap_change_flags,
BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED); BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
} }
else else
{ {
bgp_info->attr->extra->mp_nexthop_prefer_global = FALSE; bgp_info->attr->mp_nexthop_prefer_global = FALSE;
SET_FLAG(bgp_info->attr->rmap_change_flags, SET_FLAG(bgp_info->attr->rmap_change_flags,
BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED); BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
} }
@ -2535,11 +2515,11 @@ route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix,
bgp_info = object; bgp_info = object;
/* Set next hop value. */ /* Set next hop value. */
(bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_local = *address; bgp_info->attr->mp_nexthop_local = *address;
/* Set nexthop length. */ /* Set nexthop length. */
if (bgp_info->attr->extra->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) if (bgp_info->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
bgp_info->attr->extra->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; bgp_info->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
SET_FLAG(bgp_info->attr->rmap_change_flags, SET_FLAG(bgp_info->attr->rmap_change_flags,
BATTR_RMAP_IPV6_LL_NHOP_CHANGED); BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
@ -2611,15 +2591,15 @@ route_set_ipv6_nexthop_peer (void *rule, struct prefix *prefix,
/* Set next hop value and length in attribute. */ /* Set next hop value and length in attribute. */
if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) if (IN6_IS_ADDR_LINKLOCAL(&peer_address))
{ {
(bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_local = peer_address; bgp_info->attr->mp_nexthop_local = peer_address;
if (bgp_info->attr->extra->mp_nexthop_len != 32) if (bgp_info->attr->mp_nexthop_len != 32)
bgp_info->attr->extra->mp_nexthop_len = 32; bgp_info->attr->mp_nexthop_len = 32;
} }
else else
{ {
(bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global = peer_address; bgp_info->attr->mp_nexthop_global = peer_address;
if (bgp_info->attr->extra->mp_nexthop_len == 0) if (bgp_info->attr->mp_nexthop_len == 0)
bgp_info->attr->extra->mp_nexthop_len = 16; bgp_info->attr->mp_nexthop_len = 16;
} }
} }
@ -2633,9 +2613,9 @@ route_set_ipv6_nexthop_peer (void *rule, struct prefix *prefix,
SET_FLAG(bgp_info->attr->rmap_change_flags, SET_FLAG(bgp_info->attr->rmap_change_flags,
BATTR_RMAP_NEXTHOP_PEER_ADDRESS); BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
/* clear next hop value. */ /* clear next hop value. */
memset (&((bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global), memset (&(bgp_info->attr->mp_nexthop_global),
0, sizeof (struct in6_addr)); 0, sizeof (struct in6_addr));
memset (&((bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_local), memset (&(bgp_info->attr->mp_nexthop_local),
0, sizeof (struct in6_addr)); 0, sizeof (struct in6_addr));
} }
} }
@ -2688,8 +2668,8 @@ route_set_vpnv4_nexthop (void *rule, struct prefix *prefix,
bgp_info = object; bgp_info = object;
/* Set next hop value. */ /* Set next hop value. */
(bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global_in = *address; bgp_info->attr->mp_nexthop_global_in = *address;
(bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_len = 4; bgp_info->attr->mp_nexthop_len = 4;
} }
return RMAP_OKAY; return RMAP_OKAY;
@ -2730,8 +2710,8 @@ route_set_vpnv6_nexthop (void *rule, struct prefix *prefix,
bgp_info = object; bgp_info = object;
/* Set next hop value. */ /* Set next hop value. */
memcpy (&(bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global, address, sizeof(struct in6_addr)); memcpy (&bgp_info->attr->mp_nexthop_global, address, sizeof(struct in6_addr));
(bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL; bgp_info->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
} }
return RMAP_OKAY; return RMAP_OKAY;
@ -2794,7 +2774,7 @@ route_set_originator_id (void *rule, struct prefix *prefix, route_map_object_t t
bgp_info = object; bgp_info = object;
bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID); bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
(bgp_attr_extra_get (bgp_info->attr))->originator_id = *address; bgp_info->attr->originator_id = *address;
} }
return RMAP_OKAY; return RMAP_OKAY;
@ -3112,6 +3092,9 @@ bgp_route_map_process_update (struct bgp *bgp, const char *rmap_name, int route_
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
{ {
/* For table route-map updates. */ /* For table route-map updates. */
if (!bgp_fibupd_safi(safi))
continue;
if (bgp->table_map[afi][safi].name && if (bgp->table_map[afi][safi].name &&
(strcmp(rmap_name, bgp->table_map[afi][safi].name) == 0)) (strcmp(rmap_name, bgp->table_map[afi][safi].name) == 0))
{ {

View File

@ -802,16 +802,10 @@ bgp4PathAttrTable (struct variable *v, oid name[], size_t *length,
return SNMP_INTEGER (1); return SNMP_INTEGER (1);
break; break;
case BGP4PATHATTRAGGREGATORAS: /* 10 */ case BGP4PATHATTRAGGREGATORAS: /* 10 */
if (binfo->attr->extra) return SNMP_INTEGER (binfo->attr->aggregator_as);
return SNMP_INTEGER (binfo->attr->extra->aggregator_as);
else
return SNMP_INTEGER (0);
break; break;
case BGP4PATHATTRAGGREGATORADDR: /* 11 */ case BGP4PATHATTRAGGREGATORADDR: /* 11 */
if (binfo->attr->extra) return SNMP_IPADDRESS (binfo->attr->aggregator_addr);
return SNMP_IPADDRESS (binfo->attr->extra->aggregator_addr);
else
return SNMP_INTEGER (0);
break; break;
case BGP4PATHATTRCALCLOCALPREF: /* 12 */ case BGP4PATHATTRCALCLOCALPREF: /* 12 */
return SNMP_INTEGER (-1); return SNMP_INTEGER (-1);

View File

@ -586,7 +586,6 @@ subgroup_announce_table (struct update_subgroup *subgrp,
struct bgp_node *rn; struct bgp_node *rn;
struct bgp_info *ri; struct bgp_info *ri;
struct attr attr; struct attr attr;
struct attr_extra extra;
struct peer *peer; struct peer *peer;
afi_t afi; afi_t afi;
safi_t safi; safi_t safi;
@ -609,9 +608,6 @@ subgroup_announce_table (struct update_subgroup *subgrp,
&& CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
subgroup_default_originate (subgrp, 0); subgroup_default_originate (subgrp, 0);
/* It's initialized in bgp_announce_check() */
attr.extra = &extra;
for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
for (ri = rn->info; ri; ri = ri->next) for (ri = rn->info; ri; ri = ri->next)
@ -715,18 +711,16 @@ subgroup_default_originate (struct update_subgroup *subgrp, int withdraw)
str2prefix ("0.0.0.0/0", &p); str2prefix ("0.0.0.0/0", &p);
else if (afi == AFI_IP6) else if (afi == AFI_IP6)
{ {
struct attr_extra *ae = attr.extra;
str2prefix ("::/0", &p); str2prefix ("::/0", &p);
/* IPv6 global nexthop must be included. */ /* IPv6 global nexthop must be included. */
ae->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
/* If the peer is on shared nextwork and we have link-local /* If the peer is on shared nextwork and we have link-local
nexthop set it. */ nexthop set it. */
if (peer->shared_network if (peer->shared_network
&& !IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local)) && !IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local))
ae->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
} }
if (peer->default_rmap[afi][safi].name) if (peer->default_rmap[afi][safi].name)
@ -738,11 +732,9 @@ subgroup_default_originate (struct update_subgroup *subgrp, int withdraw)
for (ri = rn->info; ri; ri = ri->next) for (ri = rn->info; ri; ri = ri->next)
{ {
struct attr dummy_attr; struct attr dummy_attr;
struct attr_extra dummy_extra;
struct bgp_info info; struct bgp_info info;
/* Provide dummy so the route-map can't modify the attributes */ /* Provide dummy so the route-map can't modify the attributes */
dummy_attr.extra = &dummy_extra;
bgp_attr_dup (&dummy_attr, ri->attr); bgp_attr_dup (&dummy_attr, ri->attr);
info.peer = ri->peer; info.peer = ri->peer;
info.attr = &dummy_attr; info.attr = &dummy_attr;
@ -793,7 +785,6 @@ subgroup_default_originate (struct update_subgroup *subgrp, int withdraw)
} }
} }
bgp_attr_extra_free (&attr);
aspath_unintern (&aspath); aspath_unintern (&aspath);
} }

View File

@ -423,12 +423,10 @@ bpacket_reformat_for_peer (struct bpacket *pkt, struct peer_af *paf)
afi_t nhafi = AFI_MAX; /* NH AFI is based on nhlen! */ afi_t nhafi = AFI_MAX; /* NH AFI is based on nhlen! */
int route_map_sets_nh; int route_map_sets_nh;
nhlen = stream_getc_from (s, vec->offset); nhlen = stream_getc_from (s, vec->offset);
if (paf->afi == AFI_IP || paf->afi == AFI_IP6)
{
nhafi = BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen);
if (peer_cap_enhe(peer, paf->afi, paf->safi)) if (peer_cap_enhe(peer, paf->afi, paf->safi))
nhafi = AFI_IP6; nhafi = AFI_IP6;
} else
nhafi = BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen);
if (nhafi == AFI_IP) if (nhafi == AFI_IP)
{ {
@ -484,6 +482,7 @@ bpacket_reformat_for_peer (struct bpacket *pkt, struct peer_af *paf)
nh_modified = 1; nh_modified = 1;
} }
else if (peer->sort == BGP_PEER_EBGP && else if (peer->sort == BGP_PEER_EBGP &&
paf->safi != SAFI_EVPN &&
(bgp_multiaccess_check_v4 (v4nh, peer) == 0) && (bgp_multiaccess_check_v4 (v4nh, peer) == 0) &&
!CHECK_FLAG(vec->flags, !CHECK_FLAG(vec->flags,
BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED) && BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED) &&
@ -609,6 +608,30 @@ bpacket_reformat_for_peer (struct bpacket *pkt, struct peer_af *paf)
(nhlen == 24 ? " and RD" : "")); (nhlen == 24 ? " and RD" : ""));
} }
} }
else if (paf->afi == AFI_L2VPN)
{
struct in_addr v4nh, *mod_v4nh;
int nh_modified = 0;
stream_get_from (&v4nh, s, vec->offset + 1, 4);
mod_v4nh = &v4nh;
/* No route-map changes allowed for EVPN nexthops. */
if (!v4nh.s_addr)
{
mod_v4nh = &peer->nexthop.v4;
nh_modified = 1;
}
if (nh_modified)
stream_put_in_addr_at (s, vec->offset + 1, mod_v4nh);
if (bgp_debug_update(peer, NULL, NULL, 0))
zlog_debug ("u%" PRIu64 ":s%" PRIu64 " %s send UPDATE w/ nexthop %s",
PAF_SUBGRP(paf)->update_group->id, PAF_SUBGRP(paf)->id,
peer->host, inet_ntoa (*mod_v4nh));
}
} }
bgp_packet_add (peer, s); bgp_packet_add (peer, s);
@ -681,7 +704,7 @@ subgroup_update_packet (struct update_subgroup *subgrp)
int addpath_encode = 0; int addpath_encode = 0;
u_int32_t addpath_tx_id = 0; u_int32_t addpath_tx_id = 0;
struct prefix_rd *prd = NULL; struct prefix_rd *prd = NULL;
char label_buf[20]; mpls_label_t label = MPLS_INVALID_LABEL;
if (!subgrp) if (!subgrp)
return NULL; return NULL;
@ -696,7 +719,6 @@ subgroup_update_packet (struct update_subgroup *subgrp)
stream_reset (s); stream_reset (s);
snlri = subgrp->scratch; snlri = subgrp->scratch;
stream_reset (snlri); stream_reset (snlri);
label_buf[0] = '\0';
bpacket_attr_vec_arr_reset (&vecarr); bpacket_attr_vec_arr_reset (&vecarr);
@ -785,8 +807,6 @@ subgroup_update_packet (struct update_subgroup *subgrp)
else else
{ {
/* Encode the prefix in MP_REACH_NLRI attribute */ /* Encode the prefix in MP_REACH_NLRI attribute */
mpls_label_t label = MPLS_INVALID_LABEL;
if (rn->prn) if (rn->prn)
prd = (struct prefix_rd *) &rn->prn->p; prd = (struct prefix_rd *) &rn->prn->p;
@ -796,9 +816,6 @@ subgroup_update_packet (struct update_subgroup *subgrp)
if (binfo && binfo->extra) if (binfo && binfo->extra)
label = binfo->extra->label; label = binfo->extra->label;
if (bgp_labeled_safi(safi))
sprintf (label_buf, "label %u", label_pton(&label));
if (stream_empty (snlri)) if (stream_empty (snlri))
mpattrlen_pos = bgp_packet_mpattr_start (snlri, peer, afi, safi, mpattrlen_pos = bgp_packet_mpattr_start (snlri, peer, afi, safi,
&vecarr, adv->baa->attr); &vecarr, adv->baa->attr);
@ -831,12 +848,11 @@ subgroup_update_packet (struct update_subgroup *subgrp)
send_attr_printed = 1; send_attr_printed = 1;
} }
zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s %s", bgp_debug_rdpfxpath2str (afi, safi, prd, &rn->p, &label,
subgrp->update_group->id, subgrp->id, addpath_encode, addpath_tx_id,
bgp_debug_rdpfxpath2str (prd, &rn->p, addpath_encode, pfx_buf, sizeof (pfx_buf));
addpath_tx_id, zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s",
pfx_buf, sizeof (pfx_buf)), subgrp->update_group->id, subgrp->id, pfx_buf);
label_buf);
} }
/* Synchnorize attribute. */ /* Synchnorize attribute. */
@ -989,11 +1005,11 @@ subgroup_withdraw_packet (struct update_subgroup *subgrp)
{ {
char pfx_buf[BGP_PRD_PATH_STRLEN]; char pfx_buf[BGP_PRD_PATH_STRLEN];
zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s -- unreachable", bgp_debug_rdpfxpath2str (afi, safi, prd, &rn->p, NULL,
subgrp->update_group->id, subgrp->id,
bgp_debug_rdpfxpath2str (prd, &rn->p,
addpath_encode, addpath_tx_id, addpath_encode, addpath_tx_id,
pfx_buf, sizeof (pfx_buf))); pfx_buf, sizeof (pfx_buf));
zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s -- unreachable",
subgrp->update_group->id, subgrp->id, pfx_buf);
} }
subgrp->scount--; subgrp->scount--;

View File

@ -6711,10 +6711,6 @@ DEFUN (show_bgp_memory,
vty_out (vty, "%ld BGP attributes, using %s of memory\n", count, vty_out (vty, "%ld BGP attributes, using %s of memory\n", count,
mtype_memstr (memstrbuf, sizeof (memstrbuf), mtype_memstr (memstrbuf, sizeof (memstrbuf),
count * sizeof(struct attr))); count * sizeof(struct attr)));
if ((count = mtype_stats_alloc (MTYPE_ATTR_EXTRA)))
vty_out (vty, "%ld BGP extra attributes, using %s of memory\n", count,
mtype_memstr (memstrbuf, sizeof (memstrbuf),
count * sizeof(struct attr_extra)));
if ((count = attr_unknown_count())) if ((count = attr_unknown_count()))
vty_out (vty, "%ld unknown attributes\n", count); vty_out (vty, "%ld unknown attributes\n", count);
@ -7261,7 +7257,7 @@ bgp_show_all_instances_summary_vty (struct vty *vty, afi_t afi, safi_t safi,
} }
static int int
bgp_show_summary_vty (struct vty *vty, const char *name, bgp_show_summary_vty (struct vty *vty, const char *name,
afi_t afi, safi_t safi, u_char use_json) afi_t afi, safi_t safi, u_char use_json)
{ {
@ -10665,6 +10661,13 @@ static struct cmd_node bgp_evpn_node =
1 1
}; };
static struct cmd_node bgp_evpn_vni_node =
{
BGP_EVPN_VNI_NODE,
"%s(config-router-af-vni)# ",
1
};
static void community_list_vty (void); static void community_list_vty (void);
static void static void
@ -10734,6 +10737,7 @@ bgp_vty_init (void)
install_node (&bgp_vpnv4_node, NULL); install_node (&bgp_vpnv4_node, NULL);
install_node (&bgp_vpnv6_node, NULL); install_node (&bgp_vpnv6_node, NULL);
install_node (&bgp_evpn_node, NULL); install_node (&bgp_evpn_node, NULL);
install_node (&bgp_evpn_vni_node, NULL);
/* Install default VTY commands to new nodes. */ /* Install default VTY commands to new nodes. */
install_default (BGP_NODE); install_default (BGP_NODE);
@ -10746,6 +10750,7 @@ bgp_vty_init (void)
install_default (BGP_VPNV4_NODE); install_default (BGP_VPNV4_NODE);
install_default (BGP_VPNV6_NODE); install_default (BGP_VPNV6_NODE);
install_default (BGP_EVPN_NODE); install_default (BGP_EVPN_NODE);
install_default (BGP_EVPN_VNI_NODE);
/* "bgp multiple-instance" commands. */ /* "bgp multiple-instance" commands. */
install_element (CONFIG_NODE, &bgp_multiple_instance_cmd); install_element (CONFIG_NODE, &bgp_multiple_instance_cmd);
@ -11236,6 +11241,8 @@ bgp_vty_init (void)
install_element (BGP_VPNV4_NODE, &no_neighbor_route_reflector_client_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_route_reflector_client_cmd);
install_element (BGP_VPNV6_NODE, &neighbor_route_reflector_client_cmd); install_element (BGP_VPNV6_NODE, &neighbor_route_reflector_client_cmd);
install_element (BGP_VPNV6_NODE, &no_neighbor_route_reflector_client_cmd); install_element (BGP_VPNV6_NODE, &no_neighbor_route_reflector_client_cmd);
install_element (BGP_EVPN_NODE, &neighbor_route_reflector_client_cmd);
install_element (BGP_EVPN_NODE, &no_neighbor_route_reflector_client_cmd);
/* "neighbor route-server" commands.*/ /* "neighbor route-server" commands.*/
install_element (BGP_NODE, &neighbor_route_server_client_hidden_cmd); install_element (BGP_NODE, &neighbor_route_server_client_hidden_cmd);
@ -11609,6 +11616,8 @@ bgp_vty_init (void)
install_element (BGP_VPNV4_NODE, &no_neighbor_allowas_in_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_allowas_in_cmd);
install_element (BGP_VPNV6_NODE, &neighbor_allowas_in_cmd); install_element (BGP_VPNV6_NODE, &neighbor_allowas_in_cmd);
install_element (BGP_VPNV6_NODE, &no_neighbor_allowas_in_cmd); install_element (BGP_VPNV6_NODE, &no_neighbor_allowas_in_cmd);
install_element (BGP_EVPN_NODE, &neighbor_allowas_in_cmd);
install_element (BGP_EVPN_NODE, &no_neighbor_allowas_in_cmd);
/* address-family commands. */ /* address-family commands. */
install_element (BGP_NODE, &address_family_ipv4_safi_cmd); install_element (BGP_NODE, &address_family_ipv4_safi_cmd);

View File

@ -69,4 +69,7 @@ argv_find_and_parse_safi(struct cmd_token **argv, int argc, int *index, safi_t *
extern int extern int
bgp_vty_find_and_parse_afi_safi_bgp (struct vty *vty, struct cmd_token **argv, int argc, int *idx, bgp_vty_find_and_parse_afi_safi_bgp (struct vty *vty, struct cmd_token **argv, int argc, int *idx,
afi_t *afi, safi_t *safi, struct bgp **bgp); afi_t *afi, safi_t *safi, struct bgp **bgp);
extern int
bgp_show_summary_vty (struct vty *vty, const char *name,
afi_t afi, safi_t safi, u_char use_json);
#endif /* _QUAGGA_BGP_VTY_H */ #endif /* _QUAGGA_BGP_VTY_H */

View File

@ -35,6 +35,7 @@
#include "lib/bfd.h" #include "lib/bfd.h"
#include "filter.h" #include "filter.h"
#include "mpls.h" #include "mpls.h"
#include "vxlan.h"
#include "bgpd/bgpd.h" #include "bgpd/bgpd.h"
#include "bgpd/bgp_route.h" #include "bgpd/bgp_route.h"
@ -52,6 +53,7 @@
# include "bgpd/rfapi/rfapi_backend.h" # include "bgpd/rfapi/rfapi_backend.h"
# include "bgpd/rfapi/vnc_export_bgp.h" # include "bgpd/rfapi/vnc_export_bgp.h"
#endif #endif
#include "bgpd/bgp_evpn.h"
/* All information about zebra. */ /* All information about zebra. */
struct zclient *zclient = NULL; struct zclient *zclient = NULL;
@ -71,14 +73,12 @@ struct stream *bgp_label_buf = NULL;
2. use an array to avoid number of mallocs. 2. use an array to avoid number of mallocs.
Number of supported next-hops are finite, use of arrays should be ok. */ Number of supported next-hops are finite, use of arrays should be ok. */
struct attr attr_cp[MULTIPATH_NUM]; struct attr attr_cp[MULTIPATH_NUM];
struct attr_extra attr_extra_cp[MULTIPATH_NUM];
unsigned int attr_index = 0; unsigned int attr_index = 0;
/* Once per address-family initialization of the attribute array */ /* Once per address-family initialization of the attribute array */
#define BGP_INFO_ATTR_BUF_INIT()\ #define BGP_INFO_ATTR_BUF_INIT()\
do {\ do {\
memset(attr_cp, 0, MULTIPATH_NUM * sizeof(struct attr));\ memset(attr_cp, 0, MULTIPATH_NUM * sizeof(struct attr));\
memset(attr_extra_cp, 0, MULTIPATH_NUM * sizeof(struct attr_extra));\
attr_index = 0;\ attr_index = 0;\
} while (0) } while (0)
@ -86,7 +86,6 @@ do {\
do { \ do { \
*info_dst = *info_src; \ *info_dst = *info_src; \
assert(attr_index != multipath_num);\ assert(attr_index != multipath_num);\
attr_cp[attr_index].extra = &attr_extra_cp[attr_index]; \
bgp_attr_dup (&attr_cp[attr_index], info_src->attr); \ bgp_attr_dup (&attr_cp[attr_index], info_src->attr); \
bgp_attr_deep_dup (&attr_cp[attr_index], info_src->attr); \ bgp_attr_deep_dup (&attr_cp[attr_index], info_src->attr); \
info_dst->attr = &attr_cp[attr_index]; \ info_dst->attr = &attr_cp[attr_index]; \
@ -1160,23 +1159,23 @@ bgp_info_to_ipv6_nexthop (struct bgp_info *info)
struct in6_addr *nexthop = NULL; struct in6_addr *nexthop = NULL;
/* Only global address nexthop exists. */ /* Only global address nexthop exists. */
if (info->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) if (info->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL)
nexthop = &info->attr->extra->mp_nexthop_global; nexthop = &info->attr->mp_nexthop_global;
/* If both global and link-local address present. */ /* If both global and link-local address present. */
if (info->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) if (info->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
{ {
/* Check if route-map is set to prefer global over link-local */ /* Check if route-map is set to prefer global over link-local */
if (info->attr->extra->mp_nexthop_prefer_global) if (info->attr->mp_nexthop_prefer_global)
nexthop = &info->attr->extra->mp_nexthop_global; nexthop = &info->attr->mp_nexthop_global;
else else
{ {
/* Workaround for Cisco's nexthop bug. */ /* Workaround for Cisco's nexthop bug. */
if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global) if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->mp_nexthop_global)
&& info->peer->su_remote->sa.sa_family == AF_INET6) && info->peer->su_remote->sa.sa_family == AF_INET6)
nexthop = &info->peer->su_remote->sin6.sin6_addr; nexthop = &info->peer->su_remote->sin6.sin6_addr;
else else
nexthop = &info->attr->extra->mp_nexthop_local; nexthop = &info->attr->mp_nexthop_local;
} }
} }
@ -1246,10 +1245,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
flags = 0; flags = 0;
peer = info->peer; peer = info->peer;
if ((info->attr->extra) && (info->attr->extra->tag != 0)) tag = info->attr->tag;
tag = info->attr->extra->tag;
else
tag = 0;
/* When we create an aggregate route we must also install a Null0 route in /* When we create an aggregate route we must also install a Null0 route in
* the RIB */ * the RIB */
@ -1303,7 +1299,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
{ {
/* Metric is currently based on the best-path only */ /* Metric is currently based on the best-path only */
metric = info_cp->attr->med; metric = info_cp->attr->med;
tag = info_cp->attr->extra->tag; tag = info_cp->attr->tag;
} }
nexthop = &info_cp->attr->nexthop; nexthop = &info_cp->attr->nexthop;
} }
@ -1418,8 +1414,6 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
ifindex = 0; ifindex = 0;
nexthop = NULL; nexthop = NULL;
assert (info->attr->extra);
if (bgp->table_map[afi][safi].name) if (bgp->table_map[afi][safi].name)
BGP_INFO_ATTR_BUF_INIT(); BGP_INFO_ATTR_BUF_INIT();
@ -1439,7 +1433,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
if (mpinfo == info) if (mpinfo == info)
{ {
metric = info_cp->attr->med; metric = info_cp->attr->med;
tag = info_cp->attr->extra->tag; tag = info_cp->attr->tag;
} }
nexthop = bgp_info_to_ipv6_nexthop(info_cp); nexthop = bgp_info_to_ipv6_nexthop(info_cp);
} }
@ -1452,7 +1446,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
continue; continue;
if ((mpinfo == info) && if ((mpinfo == info) &&
mpinfo->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) mpinfo->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
if (mpinfo->peer->nexthop.ifp) if (mpinfo->peer->nexthop.ifp)
ifindex = mpinfo->peer->nexthop.ifp->ifindex; ifindex = mpinfo->peer->nexthop.ifp->ifindex;
@ -1672,10 +1666,10 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
api.metric = info->attr->med; api.metric = info->attr->med;
api.tag = 0; api.tag = 0;
if ((info->attr->extra) && (info->attr->extra->tag != 0)) if (info->attr->tag != 0)
{ {
SET_FLAG(api.message, ZAPI_MESSAGE_TAG); SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
api.tag = info->attr->extra->tag; api.tag = info->attr->tag;
} }
if (bgp_debug_zebra(p)) if (bgp_debug_zebra(p))
@ -1695,8 +1689,6 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
{ {
struct zapi_ipv6 api; struct zapi_ipv6 api;
assert (info->attr->extra);
api.vrf_id = peer->bgp->vrf_id; api.vrf_id = peer->bgp->vrf_id;
api.flags = flags; api.flags = flags;
api.type = ZEBRA_ROUTE_BGP; api.type = ZEBRA_ROUTE_BGP;
@ -1712,10 +1704,10 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
api.metric = info->attr->med; api.metric = info->attr->med;
api.tag = 0; api.tag = 0;
if ((info->attr->extra) && (info->attr->extra->tag != 0)) if (info->attr->tag != 0)
{ {
SET_FLAG(api.message, ZAPI_MESSAGE_TAG); SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
api.tag = info->attr->extra->tag; api.tag = info->attr->tag;
} }
if (bgp_debug_zebra(p)) if (bgp_debug_zebra(p))
@ -1901,9 +1893,7 @@ bgp_redistribute_metric_set (struct bgp *bgp, struct bgp_redist *red, afi_t afi,
{ {
struct attr *old_attr; struct attr *old_attr;
struct attr new_attr; struct attr new_attr;
struct attr_extra new_extra;
new_attr.extra = &new_extra;
bgp_attr_dup (&new_attr, ri->attr); bgp_attr_dup (&new_attr, ri->attr);
new_attr.med = red->redist_metric; new_attr.med = red->redist_metric;
old_attr = ri->attr; old_attr = ri->attr;
@ -2033,6 +2023,11 @@ bgp_zebra_instance_register (struct bgp *bgp)
/* Register for router-id, interfaces, redistributed routes. */ /* Register for router-id, interfaces, redistributed routes. */
zclient_send_reg_requests (zclient, bgp->vrf_id); zclient_send_reg_requests (zclient, bgp->vrf_id);
/* For default instance, register to learn about VNIs, if appropriate. */
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
&& bgp->advertise_all_vni)
bgp_zebra_advertise_all_vni (bgp, 1);
} }
/* Deregister this instance with Zebra. Invoked upon the instance /* Deregister this instance with Zebra. Invoked upon the instance
@ -2048,6 +2043,11 @@ bgp_zebra_instance_deregister (struct bgp *bgp)
if (BGP_DEBUG (zebra, ZEBRA)) if (BGP_DEBUG (zebra, ZEBRA))
zlog_debug("Deregistering VRF %u", bgp->vrf_id); zlog_debug("Deregistering VRF %u", bgp->vrf_id);
/* For default instance, unregister learning about VNIs, if appropriate. */
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
&& bgp->advertise_all_vni)
bgp_zebra_advertise_all_vni (bgp, 0);
/* Deregister for router-id, interfaces, redistributed routes. */ /* Deregister for router-id, interfaces, redistributed routes. */
zclient_send_dereg_requests (zclient, bgp->vrf_id); zclient_send_dereg_requests (zclient, bgp->vrf_id);
} }
@ -2080,6 +2080,29 @@ bgp_zebra_terminate_radv (struct bgp *bgp, struct peer *peer)
zclient_send_interface_radv_req (zclient, bgp->vrf_id, peer->ifp, 0, 0); zclient_send_interface_radv_req (zclient, bgp->vrf_id, peer->ifp, 0, 0);
} }
int
bgp_zebra_advertise_all_vni (struct bgp *bgp, int advertise)
{
struct stream *s;
/* Check socket. */
if (!zclient || zclient->sock < 0)
return 0;
/* Don't try to register if Zebra doesn't know of this instance. */
if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
return 0;
s = zclient->obuf;
stream_reset (s);
zclient_create_header (s, ZEBRA_ADVERTISE_ALL_VNI, bgp->vrf_id);
stream_putc(s, advertise);
stream_putw_at (s, 0, stream_get_endp (s));
return zclient_send_message(zclient);
}
/* BGP has established connection with Zebra. */ /* BGP has established connection with Zebra. */
static void static void
bgp_zebra_connected (struct zclient *zclient) bgp_zebra_connected (struct zclient *zclient)
@ -2106,6 +2129,85 @@ bgp_zebra_connected (struct zclient *zclient)
*/ */
} }
static int
bgp_zebra_process_local_vni (int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
struct stream *s;
vni_t vni;
struct bgp *bgp;
struct in_addr vtep_ip;
s = zclient->ibuf;
vni = stream_getl (s);
if (command == ZEBRA_VNI_ADD)
vtep_ip.s_addr = stream_get_ipv4 (s);
bgp = bgp_lookup_by_vrf_id (vrf_id);
if (!bgp)
return 0;
if (BGP_DEBUG (zebra, ZEBRA))
zlog_debug("Rx VNI %s VRF %u VNI %u",
(command == ZEBRA_VNI_ADD) ? "add" : "del", vrf_id, vni);
if (command == ZEBRA_VNI_ADD)
return bgp_evpn_local_vni_add (bgp, vni, vtep_ip.s_addr? vtep_ip : bgp->router_id);
else
return bgp_evpn_local_vni_del (bgp, vni);
}
static int
bgp_zebra_process_local_macip (int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
struct stream *s;
vni_t vni;
struct bgp *bgp;
struct ethaddr mac;
struct ipaddr ip;
int ipa_len;
char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
u_char sticky;
memset (&ip, 0, sizeof (ip));
s = zclient->ibuf;
vni = stream_getl (s);
stream_get (&mac.octet, s, ETHER_ADDR_LEN);
ipa_len = stream_getl (s);
if (ipa_len != 0 &&
ipa_len != IPV4_MAX_BYTELEN &&
ipa_len != IPV6_MAX_BYTELEN)
{
zlog_err ("%u:Recv MACIP %s with invalid IP addr length %d",
vrf_id, (command == ZEBRA_MACIP_ADD) ? "Add" : "Del",
ipa_len);
return -1;
}
if (ipa_len)
{
ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4: IPADDR_V6;
stream_get (&ip.ip.addr, s, ipa_len);
}
sticky = stream_getc (s);
bgp = bgp_lookup_by_vrf_id (vrf_id);
if (!bgp)
return 0;
if (BGP_DEBUG (zebra, ZEBRA))
zlog_debug ("%u:Recv MACIP %s %sMAC %s IP %s VNI %u",
vrf_id, (command == ZEBRA_MACIP_ADD) ? "Add" : "Del",
sticky ? "sticky " : "",
prefix_mac2str (&mac, buf, sizeof (buf)),
ipaddr2str (&ip, buf1, sizeof(buf1)), vni);
if (command == ZEBRA_MACIP_ADD)
return bgp_evpn_local_macip_add (bgp, vni, &mac, &ip, sticky);
else
return bgp_evpn_local_macip_del (bgp, vni, &mac, &ip);
}
void void
bgp_zebra_init (struct thread_master *master) bgp_zebra_init (struct thread_master *master)
@ -2133,6 +2235,10 @@ bgp_zebra_init (struct thread_master *master)
zclient->nexthop_update = bgp_read_nexthop_update; zclient->nexthop_update = bgp_read_nexthop_update;
zclient->import_check_update = bgp_read_import_check_update; zclient->import_check_update = bgp_read_import_check_update;
zclient->fec_update = bgp_read_fec_update; zclient->fec_update = bgp_read_fec_update;
zclient->local_vni_add = bgp_zebra_process_local_vni;
zclient->local_vni_del = bgp_zebra_process_local_vni;
zclient->local_macip_add = bgp_zebra_process_local_macip;
zclient->local_macip_del = bgp_zebra_process_local_macip;
bgp_nexthop_buf = stream_new(multipath_num * sizeof (struct in6_addr)); bgp_nexthop_buf = stream_new(multipath_num * sizeof (struct in6_addr));
bgp_ifindices_buf = stream_new(multipath_num * sizeof (unsigned int)); bgp_ifindices_buf = stream_new(multipath_num * sizeof (unsigned int));

View File

@ -54,6 +54,8 @@ extern struct interface *if_lookup_by_ipv4_exact (struct in_addr *, vrf_id_t);
extern struct interface *if_lookup_by_ipv6 (struct in6_addr *, ifindex_t, vrf_id_t); extern struct interface *if_lookup_by_ipv6 (struct in6_addr *, ifindex_t, vrf_id_t);
extern struct interface *if_lookup_by_ipv6_exact (struct in6_addr *, ifindex_t, vrf_id_t); extern struct interface *if_lookup_by_ipv6_exact (struct in6_addr *, ifindex_t, vrf_id_t);
extern int bgp_zebra_advertise_all_vni (struct bgp *, int);
extern int bgp_zebra_num_connects(void); extern int bgp_zebra_num_connects(void);
#endif /* _QUAGGA_BGP_ZEBRA_H */ #endif /* _QUAGGA_BGP_ZEBRA_H */

View File

@ -227,6 +227,10 @@ bgp_router_id_set (struct bgp *bgp, const struct in_addr *id)
if (IPV4_ADDR_SAME (&bgp->router_id, id)) if (IPV4_ADDR_SAME (&bgp->router_id, id))
return 0; return 0;
/* EVPN uses router id in RD, withdraw them */
if (bgp->advertise_all_vni)
bgp_evpn_handle_router_id_update (bgp, TRUE);
IPV4_ADDR_COPY (&bgp->router_id, id); IPV4_ADDR_COPY (&bgp->router_id, id);
/* Set all peer's local identifier with this value. */ /* Set all peer's local identifier with this value. */
@ -241,6 +245,11 @@ bgp_router_id_set (struct bgp *bgp, const struct in_addr *id)
BGP_NOTIFY_CEASE_CONFIG_CHANGE); BGP_NOTIFY_CEASE_CONFIG_CHANGE);
} }
} }
/* EVPN uses router id in RD, update them */
if (bgp->advertise_all_vni)
bgp_evpn_handle_router_id_update (bgp, FALSE);
return 0; return 0;
} }
@ -3004,6 +3013,7 @@ bgp_create (as_t *as, const char *name, enum bgp_instance_type inst_type)
QOBJ_REG (bgp, bgp); QOBJ_REG (bgp, bgp);
update_bgp_group_init(bgp); update_bgp_group_init(bgp);
bgp_evpn_init(bgp);
return bgp; return bgp;
} }
@ -3355,6 +3365,8 @@ bgp_free (struct bgp *bgp)
bgp_scan_finish (bgp); bgp_scan_finish (bgp);
bgp_address_destroy (bgp); bgp_address_destroy (bgp);
bgp_evpn_cleanup (bgp);
if (bgp->name) if (bgp->name)
XFREE(MTYPE_BGP, bgp->name); XFREE(MTYPE_BGP, bgp->name);
@ -7367,6 +7379,9 @@ bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
bgp_config_write_maxpaths (vty, bgp, afi, safi, &write); bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
bgp_config_write_table_map (vty, bgp, afi, safi, &write); bgp_config_write_table_map (vty, bgp, afi, safi, &write);
if (safi == SAFI_EVPN)
bgp_config_write_evpn_info (vty, bgp, afi, safi, &write);
if (write) if (write)
vty_out (vty, " exit-address-family\n"); vty_out (vty, " exit-address-family\n");

View File

@ -33,6 +33,7 @@
#include "linklist.h" #include "linklist.h"
#include "defaults.h" #include "defaults.h"
#include "bgp_memory.h" #include "bgp_memory.h"
#include "bitfield.h"
#define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */ #define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */
@ -367,6 +368,20 @@ struct bgp
struct rfapi *rfapi; struct rfapi *rfapi;
#endif #endif
/* EVPN related information */
/* EVI hash table */
struct hash *vnihash;
/* EVPN enable - advertise local VNIs and their MACs etc. */
int advertise_all_vni;
/* Hash table of Import RTs to EVIs */
struct hash *import_rt_hash;
/* Id space for automatic RD derivation for an EVI */
bitfield_t rd_idspace;
QOBJ_FIELDS QOBJ_FIELDS
}; };
DECLARE_QOBJ_TYPE(bgp) DECLARE_QOBJ_TYPE(bgp)

View File

@ -715,7 +715,6 @@ add_vnc_route (
/* Cripes, the memory management of attributes is byzantine */ /* Cripes, the memory management of attributes is byzantine */
bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE); bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE);
assert (attr.extra);
/* /*
* At this point: * At this point:
@ -772,7 +771,6 @@ add_vnc_route (
/* Encap SAFI not used with MPLS */ /* Encap SAFI not used with MPLS */
vnc_zlog_debug_verbose ("%s: mpls tunnel type, encap safi omitted", __func__); vnc_zlog_debug_verbose ("%s: mpls tunnel type, encap safi omitted", __func__);
aspath_unintern (&attr.aspath); /* Unintern original. */ aspath_unintern (&attr.aspath); /* Unintern original. */
bgp_attr_extra_free (&attr);
return; return;
} }
} }
@ -790,7 +788,7 @@ add_vnc_route (
} }
/* override default weight assigned by bgp_attr_default_set() */ /* override default weight assigned by bgp_attr_default_set() */
attr.extra->weight = rfd->peer ? rfd->peer->weight[afi][safi] : 0; attr.weight = rfd->peer ? rfd->peer->weight[afi][safi] : 0;
/* /*
* NB: ticket 81: do not reset attr.aspath here because it would * NB: ticket 81: do not reset attr.aspath here because it would
@ -808,7 +806,7 @@ add_vnc_route (
if (type == ZEBRA_ROUTE_BGP_DIRECT || type == ZEBRA_ROUTE_BGP_DIRECT_EXT) if (type == ZEBRA_ROUTE_BGP_DIRECT || type == ZEBRA_ROUTE_BGP_DIRECT_EXT)
{ {
attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID); attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
attr.extra->originator_id = bgp->router_id; attr.originator_id = bgp->router_id;
} }
@ -825,7 +823,7 @@ add_vnc_route (
encaptlv->length = 4; encaptlv->length = 4;
lt = htonl (*lifetime); lt = htonl (*lifetime);
memcpy (encaptlv->value, &lt, 4); memcpy (encaptlv->value, &lt, 4);
attr.extra->vnc_subtlvs = encaptlv; attr.vnc_subtlvs = encaptlv;
vnc_zlog_debug_verbose ("%s: set Encap Attr Prefix Lifetime to %d", vnc_zlog_debug_verbose ("%s: set Encap Attr Prefix Lifetime to %d",
__func__, *lifetime); __func__, *lifetime);
} }
@ -845,13 +843,13 @@ add_vnc_route (
*/ */
encaptlv = encaptlv =
encap_tlv_dup ((struct bgp_attr_encap_subtlv *) rfp_options); encap_tlv_dup ((struct bgp_attr_encap_subtlv *) rfp_options);
if (attr.extra->vnc_subtlvs) if (attr.vnc_subtlvs)
{ {
attr.extra->vnc_subtlvs->next = encaptlv; attr.vnc_subtlvs->next = encaptlv;
} }
else else
{ {
attr.extra->vnc_subtlvs = encaptlv; attr.vnc_subtlvs = encaptlv;
} }
} }
@ -859,7 +857,7 @@ add_vnc_route (
{ {
struct bgp_tea_options *hop; struct bgp_tea_options *hop;
/* XXX max of one tlv present so far from above code */ /* XXX max of one tlv present so far from above code */
struct bgp_attr_encap_subtlv *tail = attr.extra->vnc_subtlvs; struct bgp_attr_encap_subtlv *tail = attr.vnc_subtlvs;
for (hop = rfp_options; hop; hop = hop->next) for (hop = rfp_options; hop; hop = hop->next)
{ {
@ -887,7 +885,7 @@ add_vnc_route (
} }
else else
{ {
attr.extra->vnc_subtlvs = encaptlv; attr.vnc_subtlvs = encaptlv;
} }
tail = encaptlv; tail = encaptlv;
} }
@ -903,8 +901,8 @@ add_vnc_route (
*/ */
attr.extra->ecommunity = ecommunity_new (); attr.ecommunity = ecommunity_new ();
assert (attr.extra->ecommunity); assert (attr.ecommunity);
if (TunnelType != BGP_ENCAP_TYPE_MPLS && if (TunnelType != BGP_ENCAP_TYPE_MPLS &&
TunnelType != BGP_ENCAP_TYPE_RESERVED) TunnelType != BGP_ENCAP_TYPE_RESERVED)
@ -921,7 +919,7 @@ add_vnc_route (
beec.val[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP; beec.val[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP;
beec.val[6] = ((TunnelType) >> 8) & 0xff; beec.val[6] = ((TunnelType) >> 8) & 0xff;
beec.val[7] = (TunnelType) & 0xff; beec.val[7] = (TunnelType) & 0xff;
ecommunity_add_val (attr.extra->ecommunity, &beec); ecommunity_add_val (attr.ecommunity, &beec);
} }
/* /*
@ -929,21 +927,21 @@ add_vnc_route (
*/ */
if (rt_export_list) if (rt_export_list)
{ {
attr.extra->ecommunity = attr.ecommunity =
ecommunity_merge (attr.extra->ecommunity, rt_export_list); ecommunity_merge (attr.ecommunity, rt_export_list);
} }
if (attr.extra->ecommunity->size) if (attr.ecommunity->size)
{ {
attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES); attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
} }
else else
{ {
ecommunity_free (&attr.extra->ecommunity); ecommunity_free (&attr.ecommunity);
attr.extra->ecommunity = NULL; attr.ecommunity = NULL;
} }
vnc_zlog_debug_verbose ("%s: attr.extra->ecommunity=%p", __func__, vnc_zlog_debug_verbose ("%s: attr.ecommunity=%p", __func__,
attr.extra->ecommunity); attr.ecommunity);
/* /*
@ -965,13 +963,13 @@ add_vnc_route (
*/ */
attr.nexthop.s_addr = nexthop->addr.v4.s_addr; attr.nexthop.s_addr = nexthop->addr.v4.s_addr;
attr.extra->mp_nexthop_global_in = nexthop->addr.v4; attr.mp_nexthop_global_in = nexthop->addr.v4;
attr.extra->mp_nexthop_len = 4; attr.mp_nexthop_len = 4;
break; break;
case AF_INET6: case AF_INET6:
attr.extra->mp_nexthop_global = nexthop->addr.v6; attr.mp_nexthop_global = nexthop->addr.v6;
attr.extra->mp_nexthop_len = 16; attr.mp_nexthop_len = 16;
break; break;
default: default:
@ -1016,7 +1014,6 @@ add_vnc_route (
new_attr = bgp_attr_intern (&attr); new_attr = bgp_attr_intern (&attr);
aspath_unintern (&attr.aspath); /* Unintern original. */ aspath_unintern (&attr.aspath); /* Unintern original. */
bgp_attr_extra_free (&attr);
/* /*
* At this point: * At this point:

View File

@ -162,28 +162,24 @@ rfapi_tunneltype_option_to_tlv (
struct rfapi_un_option * struct rfapi_un_option *
rfapi_encap_tlv_to_un_option (struct attr *attr) rfapi_encap_tlv_to_un_option (struct attr *attr)
{ {
struct attr_extra *attre = attr->extra;
struct rfapi_un_option *uo = NULL; struct rfapi_un_option *uo = NULL;
struct rfapi_tunneltype_option *tto; struct rfapi_tunneltype_option *tto;
int rc; int rc;
struct bgp_attr_encap_subtlv *stlv; struct bgp_attr_encap_subtlv *stlv;
if (!attre)
return NULL;
/* no tunnel encap attr stored */ /* no tunnel encap attr stored */
if (!attre->encap_tunneltype) if (!attr->encap_tunneltype)
return NULL; return NULL;
stlv = attre->encap_subtlvs; stlv = attr->encap_subtlvs;
uo = XCALLOC (MTYPE_RFAPI_UN_OPTION, sizeof (struct rfapi_un_option)); uo = XCALLOC (MTYPE_RFAPI_UN_OPTION, sizeof (struct rfapi_un_option));
assert (uo); assert (uo);
uo->type = RFAPI_UN_OPTION_TYPE_TUNNELTYPE; uo->type = RFAPI_UN_OPTION_TYPE_TUNNELTYPE;
uo->v.tunnel.type = attre->encap_tunneltype; uo->v.tunnel.type = attr->encap_tunneltype;
tto = &uo->v.tunnel; tto = &uo->v.tunnel;
switch (attre->encap_tunneltype) switch (attr->encap_tunneltype)
{ {
case BGP_ENCAP_TYPE_L2TPV3_OVER_IP: case BGP_ENCAP_TYPE_L2TPV3_OVER_IP:
rc = tlv_to_bgp_encap_type_l2tpv3overip (stlv, &tto->bgpinfo.l2tpv3_ip); rc = tlv_to_bgp_encap_type_l2tpv3overip (stlv, &tto->bgpinfo.l2tpv3_ip);
@ -249,7 +245,7 @@ rfapi_encap_tlv_to_un_option (struct attr *attr)
default: default:
vnc_zlog_debug_verbose ("%s: unknown tunnel type %d", vnc_zlog_debug_verbose ("%s: unknown tunnel type %d",
__func__, attre->encap_tunneltype); __func__, attr->encap_tunneltype);
rc = -1; rc = -1;
break; break;
} }

View File

@ -308,12 +308,12 @@ rfapi_deferred_close_workfunc (struct work_queue *q, void *data)
int int
rfapiGetL2o (struct attr *attr, struct rfapi_l2address_option *l2o) rfapiGetL2o (struct attr *attr, struct rfapi_l2address_option *l2o)
{ {
if (attr && attr->extra) if (attr)
{ {
struct bgp_attr_encap_subtlv *pEncap; struct bgp_attr_encap_subtlv *pEncap;
for (pEncap = attr->extra->vnc_subtlvs; pEncap; pEncap = pEncap->next) for (pEncap = attr->vnc_subtlvs; pEncap; pEncap = pEncap->next)
{ {
if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION) if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION)
@ -358,10 +358,10 @@ rfapiGetVncLifetime (struct attr *attr, uint32_t * lifetime)
*lifetime = RFAPI_INFINITE_LIFETIME; /* default to infinite */ *lifetime = RFAPI_INFINITE_LIFETIME; /* default to infinite */
if (attr && attr->extra) if (attr)
{ {
for (pEncap = attr->extra->vnc_subtlvs; pEncap; pEncap = pEncap->next) for (pEncap = attr->vnc_subtlvs; pEncap; pEncap = pEncap->next)
{ {
if (pEncap->type == BGP_VNC_SUBTLV_TYPE_LIFETIME) if (pEncap->type == BGP_VNC_SUBTLV_TYPE_LIFETIME)
@ -387,9 +387,9 @@ rfapiGetTunnelType (struct attr *attr,
bgp_encap_types *type) bgp_encap_types *type)
{ {
*type = BGP_ENCAP_TYPE_MPLS; /* default to MPLS */ *type = BGP_ENCAP_TYPE_MPLS; /* default to MPLS */
if (attr && attr->extra && attr->extra->ecommunity) if (attr && attr->ecommunity)
{ {
struct ecommunity *ecom = attr->extra->ecommunity; struct ecommunity *ecom = attr->ecommunity;
int i; int i;
for (i = 0; i < (ecom->size * ECOMMUNITY_SIZE); i += ECOMMUNITY_SIZE) for (i = 0; i < (ecom->size * ECOMMUNITY_SIZE); i += ECOMMUNITY_SIZE)
@ -431,9 +431,9 @@ rfapiGetVncTunnelUnAddr (struct attr *attr, struct prefix *p)
return ENOENT; return ENOENT;
} }
if (attr && attr->extra) if (attr)
{ {
for (pEncap = attr->extra->encap_subtlvs; pEncap; pEncap = pEncap->next) for (pEncap = attr->encap_subtlvs; pEncap; pEncap = pEncap->next)
{ {
if (pEncap->type == BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT) if (pEncap->type == BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT)
@ -1184,7 +1184,7 @@ rfapiVpnBiNhEqualsPt (struct bgp_info *bi, struct rfapi_ip_addr *hpt)
if (!hpt || !bi) if (!hpt || !bi)
return 0; return 0;
family = BGP_MP_NEXTHOP_FAMILY (bi->attr->extra->mp_nexthop_len); family = BGP_MP_NEXTHOP_FAMILY (bi->attr->mp_nexthop_len);
if (hpt->addr_family != family) if (hpt->addr_family != family)
return 0; return 0;
@ -1192,12 +1192,12 @@ rfapiVpnBiNhEqualsPt (struct bgp_info *bi, struct rfapi_ip_addr *hpt)
switch (family) switch (family)
{ {
case AF_INET: case AF_INET:
if (bi->attr->extra->mp_nexthop_global_in.s_addr != hpt->addr.v4.s_addr) if (bi->attr->mp_nexthop_global_in.s_addr != hpt->addr.v4.s_addr)
return 0; return 0;
break; break;
case AF_INET6: case AF_INET6:
if (IPV6_ADDR_CMP (&bi->attr->extra->mp_nexthop_global, &hpt->addr.v6)) if (IPV6_ADDR_CMP (&bi->attr->mp_nexthop_global, &hpt->addr.v6))
return 0; return 0;
break; break;
@ -1225,31 +1225,27 @@ rfapiVpnBiSamePtUn (struct bgp_info *bi1, struct bgp_info *bi2)
if (!bi1->attr || !bi2->attr) if (!bi1->attr || !bi2->attr)
return 0; return 0;
if (!bi1->attr->extra || !bi2->attr->extra)
return 0;
/* /*
* VN address comparisons * VN address comparisons
*/ */
if (BGP_MP_NEXTHOP_FAMILY (bi1->attr->extra->mp_nexthop_len) != if (BGP_MP_NEXTHOP_FAMILY (bi1->attr->mp_nexthop_len) !=
BGP_MP_NEXTHOP_FAMILY (bi2->attr->extra->mp_nexthop_len)) BGP_MP_NEXTHOP_FAMILY (bi2->attr->mp_nexthop_len))
{ {
return 0; return 0;
} }
switch (BGP_MP_NEXTHOP_FAMILY (bi1->attr->extra->mp_nexthop_len)) switch (BGP_MP_NEXTHOP_FAMILY (bi1->attr->mp_nexthop_len))
{ {
case AF_INET: case AF_INET:
if (bi1->attr->extra->mp_nexthop_global_in.s_addr != if (bi1->attr->mp_nexthop_global_in.s_addr !=
bi2->attr->extra->mp_nexthop_global_in.s_addr) bi2->attr->mp_nexthop_global_in.s_addr)
return 0; return 0;
break; break;
case AF_INET6: case AF_INET6:
if (IPV6_ADDR_CMP (&bi1->attr->extra->mp_nexthop_global, if (IPV6_ADDR_CMP (&bi1->attr->mp_nexthop_global,
&bi2->attr->extra->mp_nexthop_global)) &bi2->attr->mp_nexthop_global))
return 0; return 0;
break; break;
@ -1419,11 +1415,11 @@ rfapiRouteInfo2NextHopEntry (
memcpy (&vo->v.l2addr.macaddr, &rn->p.u.prefix_eth.octet, memcpy (&vo->v.l2addr.macaddr, &rn->p.u.prefix_eth.octet,
ETHER_ADDR_LEN); ETHER_ADDR_LEN);
/* only low 3 bytes of this are significant */ /* only low 3 bytes of this are significant */
if (bi->attr && bi->attr->extra) if (bi->attr)
{ {
(void) rfapiEcommunityGetLNI (bi->attr->extra->ecommunity, (void) rfapiEcommunityGetLNI (bi->attr->ecommunity,
&vo->v.l2addr.logical_net_id); &vo->v.l2addr.logical_net_id);
(void) rfapiEcommunityGetEthernetTag (bi->attr->extra->ecommunity, (void) rfapiEcommunityGetEthernetTag (bi->attr->ecommunity,
&vo->v.l2addr.tag_id); &vo->v.l2addr.tag_id);
} }
@ -1451,31 +1447,28 @@ rfapiRouteInfo2NextHopEntry (
bgp_encap_types tun_type; bgp_encap_types tun_type;
new->prefix.cost = rfapiRfpCost (bi->attr); new->prefix.cost = rfapiRfpCost (bi->attr);
if (bi->attr->extra)
{
struct bgp_attr_encap_subtlv *pEncap; struct bgp_attr_encap_subtlv *pEncap;
switch (BGP_MP_NEXTHOP_FAMILY (bi->attr->extra->mp_nexthop_len)) switch (BGP_MP_NEXTHOP_FAMILY (bi->attr->mp_nexthop_len))
{ {
case AF_INET: case AF_INET:
new->vn_address.addr_family = AF_INET; new->vn_address.addr_family = AF_INET;
new->vn_address.addr.v4 = bi->attr->extra->mp_nexthop_global_in; new->vn_address.addr.v4 = bi->attr->mp_nexthop_global_in;
break; break;
case AF_INET6: case AF_INET6:
new->vn_address.addr_family = AF_INET6; new->vn_address.addr_family = AF_INET6;
new->vn_address.addr.v6 = bi->attr->extra->mp_nexthop_global; new->vn_address.addr.v6 = bi->attr->mp_nexthop_global;
break; break;
default: default:
zlog_warn ("%s: invalid vpn nexthop length: %d", zlog_warn ("%s: invalid vpn nexthop length: %d",
__func__, bi->attr->extra->mp_nexthop_len); __func__, bi->attr->mp_nexthop_len);
rfapi_free_next_hop_list (new); rfapi_free_next_hop_list (new);
return NULL; return NULL;
} }
for (pEncap = bi->attr->extra->vnc_subtlvs; pEncap; for (pEncap = bi->attr->vnc_subtlvs; pEncap;
pEncap = pEncap->next) pEncap = pEncap->next)
{ {
switch (pEncap->type) switch (pEncap->type)
@ -1506,7 +1499,7 @@ rfapiRouteInfo2NextHopEntry (
} }
} }
for (pEncap = bi->attr->extra->encap_subtlvs; pEncap; for (pEncap = bi->attr->encap_subtlvs; pEncap;
pEncap = pEncap->next) pEncap = pEncap->next)
{ {
switch (pEncap->type) switch (pEncap->type)
@ -1576,7 +1569,7 @@ rfapiRouteInfo2NextHopEntry (
} }
} }
} }
}
new->lifetime = lifetime; new->lifetime = lifetime;
return new; return new;
} }
@ -2121,6 +2114,8 @@ rfapiBgpInfoAttachSorted (
struct bgp *bgp; struct bgp *bgp;
struct bgp_info *prev; struct bgp_info *prev;
struct bgp_info *next; struct bgp_info *next;
char pfx_buf[PREFIX2STR_BUFFER];
bgp = bgp_get_default (); /* assume 1 instance for now */ bgp = bgp_get_default (); /* assume 1 instance for now */
@ -2136,7 +2131,7 @@ rfapiBgpInfoAttachSorted (
if (!bgp || if (!bgp ||
(!CHECK_FLAG (info_new->flags, BGP_INFO_REMOVED) && (!CHECK_FLAG (info_new->flags, BGP_INFO_REMOVED) &&
CHECK_FLAG (next->flags, BGP_INFO_REMOVED)) || CHECK_FLAG (next->flags, BGP_INFO_REMOVED)) ||
bgp_info_cmp_compatible (bgp, info_new, next, afi, safi) == -1) bgp_info_cmp_compatible (bgp, info_new, next, pfx_buf, afi, safi) == -1)
{ /* -1 if 1st is better */ { /* -1 if 1st is better */
break; break;
} }
@ -2700,19 +2695,18 @@ rfapiNexthop2Prefix (struct attr *attr, struct prefix *p)
{ {
assert (p); assert (p);
assert (attr); assert (attr);
assert (attr->extra);
memset (p, 0, sizeof (struct prefix)); memset (p, 0, sizeof (struct prefix));
switch (p->family = BGP_MP_NEXTHOP_FAMILY (attr->extra->mp_nexthop_len)) switch (p->family = BGP_MP_NEXTHOP_FAMILY (attr->mp_nexthop_len))
{ {
case AF_INET: case AF_INET:
p->u.prefix4 = attr->extra->mp_nexthop_global_in; p->u.prefix4 = attr->mp_nexthop_global_in;
p->prefixlen = 32; p->prefixlen = 32;
break; break;
case AF_INET6: case AF_INET6:
p->u.prefix6 = attr->extra->mp_nexthop_global; p->u.prefix6 = attr->mp_nexthop_global;
p->prefixlen = 128; p->prefixlen = 128;
break; break;
@ -2777,9 +2771,7 @@ rfapiAttrNexthopAddrDifferent (struct prefix *p1, struct prefix *p2)
static void static void
rfapiCopyUnEncap2VPN (struct bgp_info *encap_bi, struct bgp_info *vpn_bi) rfapiCopyUnEncap2VPN (struct bgp_info *encap_bi, struct bgp_info *vpn_bi)
{ {
struct attr_extra *attre; if (!encap_bi->attr)
if (!encap_bi->attr || !encap_bi->attr->extra)
{ {
zlog_warn ("%s: no encap bi attr/extra, can't copy UN address", zlog_warn ("%s: no encap bi attr/extra, can't copy UN address",
__func__); __func__);
@ -2793,9 +2785,7 @@ rfapiCopyUnEncap2VPN (struct bgp_info *encap_bi, struct bgp_info *vpn_bi)
return; return;
} }
attre = encap_bi->attr->extra; switch (BGP_MP_NEXTHOP_FAMILY (encap_bi->attr->mp_nexthop_len))
switch (BGP_MP_NEXTHOP_FAMILY (attre->mp_nexthop_len))
{ {
case AF_INET: case AF_INET:
@ -2809,17 +2799,17 @@ rfapiCopyUnEncap2VPN (struct bgp_info *encap_bi, struct bgp_info *vpn_bi)
} }
vpn_bi->extra->vnc.import.un_family = AF_INET; vpn_bi->extra->vnc.import.un_family = AF_INET;
vpn_bi->extra->vnc.import.un.addr4 = attre->mp_nexthop_global_in; vpn_bi->extra->vnc.import.un.addr4 = encap_bi->attr->mp_nexthop_global_in;
break; break;
case AF_INET6: case AF_INET6:
vpn_bi->extra->vnc.import.un_family = AF_INET6; vpn_bi->extra->vnc.import.un_family = AF_INET6;
vpn_bi->extra->vnc.import.un.addr6 = attre->mp_nexthop_global; vpn_bi->extra->vnc.import.un.addr6 = encap_bi->attr->mp_nexthop_global;
break; break;
default: default:
zlog_warn ("%s: invalid encap nexthop length: %d", zlog_warn ("%s: invalid encap nexthop length: %d",
__func__, attre->mp_nexthop_len); __func__, encap_bi->attr->mp_nexthop_len);
vpn_bi->extra->vnc.import.un_family = 0; vpn_bi->extra->vnc.import.un_family = 0;
break; break;
} }
@ -3100,21 +3090,21 @@ rfapiExpireEncapNow (
static int static int
rfapiGetNexthop (struct attr *attr, struct prefix *prefix) rfapiGetNexthop (struct attr *attr, struct prefix *prefix)
{ {
switch (BGP_MP_NEXTHOP_FAMILY (attr->extra->mp_nexthop_len)) switch (BGP_MP_NEXTHOP_FAMILY (attr->mp_nexthop_len))
{ {
case AF_INET: case AF_INET:
prefix->family = AF_INET; prefix->family = AF_INET;
prefix->prefixlen = 32; prefix->prefixlen = 32;
prefix->u.prefix4 = attr->extra->mp_nexthop_global_in; prefix->u.prefix4 = attr->mp_nexthop_global_in;
break; break;
case AF_INET6: case AF_INET6:
prefix->family = AF_INET6; prefix->family = AF_INET6;
prefix->prefixlen = 128; prefix->prefixlen = 128;
prefix->u.prefix6 = attr->extra->mp_nexthop_global; prefix->u.prefix6 = attr->mp_nexthop_global;
break; break;
default: default:
vnc_zlog_debug_verbose ("%s: unknown attr->extra->mp_nexthop_len %d", __func__, vnc_zlog_debug_verbose ("%s: unknown attr->mp_nexthop_len %d", __func__,
attr->extra->mp_nexthop_len); attr->mp_nexthop_len);
return EINVAL; return EINVAL;
} }
return 0; return 0;
@ -3185,7 +3175,7 @@ rfapiBgpInfoFilteredImportEncap (
* On a withdraw, peer and RD are sufficient to determine if * On a withdraw, peer and RD are sufficient to determine if
* we should act. * we should act.
*/ */
if (!attr || !attr->extra || !attr->extra->ecommunity) if (!attr || !attr->ecommunity)
{ {
vnc_zlog_debug_verbose ("%s: attr, extra, or ecommunity missing, not importing", vnc_zlog_debug_verbose ("%s: attr, extra, or ecommunity missing, not importing",
@ -3193,7 +3183,7 @@ rfapiBgpInfoFilteredImportEncap (
return; return;
} }
#if RFAPI_REQUIRE_ENCAP_BEEC #if RFAPI_REQUIRE_ENCAP_BEEC
if (!rfapiEcommunitiesMatchBeec (attr->extra->ecommunity)) if (!rfapiEcommunitiesMatchBeec (attr->ecommunity))
{ {
vnc_zlog_debug_verbose ("%s: it=%p: no match for BGP Encapsulation ecommunity", vnc_zlog_debug_verbose ("%s: it=%p: no match for BGP Encapsulation ecommunity",
__func__, import_table); __func__, import_table);
@ -3201,7 +3191,7 @@ rfapiBgpInfoFilteredImportEncap (
} }
#endif #endif
if (!rfapiEcommunitiesIntersect (import_table->rt_import_list, if (!rfapiEcommunitiesIntersect (import_table->rt_import_list,
attr->extra->ecommunity)) attr->ecommunity))
{ {
vnc_zlog_debug_verbose ("%s: it=%p: no ecommunity intersection", vnc_zlog_debug_verbose ("%s: it=%p: no ecommunity intersection",
@ -3667,7 +3657,7 @@ rfapiBgpInfoFilteredImportVPN (
*/ */
if (action == FIF_ACTION_UPDATE) if (action == FIF_ACTION_UPDATE)
{ {
if (!attr || !attr->extra || !attr->extra->ecommunity) if (!attr || !attr->ecommunity)
{ {
vnc_zlog_debug_verbose ("%s: attr, extra, or ecommunity missing, not importing", vnc_zlog_debug_verbose ("%s: attr, extra, or ecommunity missing, not importing",
@ -3676,7 +3666,7 @@ rfapiBgpInfoFilteredImportVPN (
} }
if ((import_table != bgp->rfapi->it_ce) && if ((import_table != bgp->rfapi->it_ce) &&
!rfapiEcommunitiesIntersect (import_table->rt_import_list, !rfapiEcommunitiesIntersect (import_table->rt_import_list,
attr->extra->ecommunity)) attr->ecommunity))
{ {
vnc_zlog_debug_verbose ("%s: it=%p: no ecommunity intersection", vnc_zlog_debug_verbose ("%s: it=%p: no ecommunity intersection",
@ -4160,12 +4150,12 @@ rfapiProcessUpdate (
* Find rt containing LNI (Logical Network ID), which * Find rt containing LNI (Logical Network ID), which
* _should_ always be present when mac address is present * _should_ always be present when mac address is present
*/ */
rc = rfapiEcommunityGetLNI (attr->extra->ecommunity, &lni); rc = rfapiEcommunityGetLNI (attr->ecommunity, &lni);
vnc_zlog_debug_verbose vnc_zlog_debug_verbose
("%s: rfapiEcommunityGetLNI returned %d, lni=%d, attr=%p, attr->extra=%p", ("%s: rfapiEcommunityGetLNI returned %d, lni=%d, attr=%p",
__func__, rc, lni, attr, attr->extra); __func__, rc, lni, attr);
if (attr && attr->extra && !rc) if (attr && !rc)
{ {
it = rfapiMacImportTableGet (bgp, lni); it = rfapiMacImportTableGet (bgp, lni);

View File

@ -664,7 +664,7 @@ rfapiRibBi2Ri(
ri->lifetime = lifetime; ri->lifetime = lifetime;
/* This loop based on rfapiRouteInfo2NextHopEntry() */ /* This loop based on rfapiRouteInfo2NextHopEntry() */
for (pEncap = bi->attr->extra->vnc_subtlvs; pEncap; pEncap = pEncap->next) for (pEncap = bi->attr->vnc_subtlvs; pEncap; pEncap = pEncap->next)
{ {
struct bgp_tea_options *hop; struct bgp_tea_options *hop;
@ -723,11 +723,11 @@ rfapiRibBi2Ri(
memcpy (&vo->v.l2addr.macaddr, bi->extra->vnc.import.rd.val+2, memcpy (&vo->v.l2addr.macaddr, bi->extra->vnc.import.rd.val+2,
ETHER_ADDR_LEN); ETHER_ADDR_LEN);
if (bi->attr && bi->attr->extra) if (bi->attr)
{ {
(void) rfapiEcommunityGetLNI (bi->attr->extra->ecommunity, (void) rfapiEcommunityGetLNI (bi->attr->ecommunity,
&vo->v.l2addr.logical_net_id); &vo->v.l2addr.logical_net_id);
(void) rfapiEcommunityGetEthernetTag (bi->attr->extra->ecommunity, (void) rfapiEcommunityGetEthernetTag (bi->attr->ecommunity,
&vo->v.l2addr.tag_id); &vo->v.l2addr.tag_id);
} }

View File

@ -469,9 +469,9 @@ rfapi_vty_out_vncinfo (
} }
} }
if (bi->attr && bi->attr->extra && bi->attr->extra->ecommunity) if (bi->attr && bi->attr->ecommunity)
{ {
s = ecommunity_ecom2str (bi->attr->extra->ecommunity, s = ecommunity_ecom2str (bi->attr->ecommunity,
ECOMMUNITY_FORMAT_ROUTE_MAP, 0); ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
vty_out (vty, " EC{%s}", s); vty_out (vty, " EC{%s}", s);
XFREE (MTYPE_ECOMMUNITY_STR, s); XFREE (MTYPE_ECOMMUNITY_STR, s);
@ -499,7 +499,6 @@ rfapiPrintAttrPtrs (void *stream, struct attr *attr)
void *out; void *out;
const char *vty_newline; const char *vty_newline;
struct attr_extra *ae;
char buf[BUFSIZ]; char buf[BUFSIZ];
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0)
@ -518,15 +517,12 @@ rfapiPrintAttrPtrs (void *stream, struct attr *attr)
fp (out, " community=%p, refcnt=%d%s", attr->community, fp (out, " community=%p, refcnt=%d%s", attr->community,
(attr->community ? attr->community->refcnt : 0), HVTYNL); (attr->community ? attr->community->refcnt : 0), HVTYNL);
if ((ae = attr->extra)) fp (out, " ecommunity=%p, refcnt=%d%s", attr->ecommunity,
{ (attr->ecommunity ? attr->ecommunity->refcnt : 0), HVTYNL);
fp (out, " ecommunity=%p, refcnt=%d%s", ae->ecommunity, fp (out, " cluster=%p, refcnt=%d%s", attr->cluster,
(ae->ecommunity ? ae->ecommunity->refcnt : 0), HVTYNL); (attr->cluster ? attr->cluster->refcnt : 0), HVTYNL);
fp (out, " cluster=%p, refcnt=%d%s", ae->cluster, fp (out, " transit=%p, refcnt=%d%s", attr->transit,
(ae->cluster ? ae->cluster->refcnt : 0), HVTYNL); (attr->transit ? attr->transit->refcnt : 0), HVTYNL);
fp (out, " transit=%p, refcnt=%d%s", ae->transit,
(ae->transit ? ae->transit->refcnt : 0), HVTYNL);
}
} }
/* /*
@ -593,26 +589,26 @@ rfapiPrintBi (void *stream, struct bgp_info *bi)
* RFP option sizes (they are opaque values) * RFP option sizes (they are opaque values)
* extended communities (RTs) * extended communities (RTs)
*/ */
if (bi->attr && bi->attr->extra) if (bi->attr)
{ {
uint32_t lifetime; uint32_t lifetime;
int printed_1st_gol = 0; int printed_1st_gol = 0;
struct bgp_attr_encap_subtlv *pEncap; struct bgp_attr_encap_subtlv *pEncap;
struct prefix pfx_un; struct prefix pfx_un;
int af = BGP_MP_NEXTHOP_FAMILY (bi->attr->extra->mp_nexthop_len); int af = BGP_MP_NEXTHOP_FAMILY (bi->attr->mp_nexthop_len);
/* Nexthop */ /* Nexthop */
if (af == AF_INET) if (af == AF_INET)
{ {
r = snprintf (p, REMAIN, "%s", inet_ntop (AF_INET, r = snprintf (p, REMAIN, "%s", inet_ntop (AF_INET,
&bi->attr->extra->mp_nexthop_global_in, &bi->attr->mp_nexthop_global_in,
buf, BUFSIZ)); buf, BUFSIZ));
INCP; INCP;
} }
else if (af == AF_INET6) else if (af == AF_INET6)
{ {
r = snprintf (p, REMAIN, "%s", inet_ntop (AF_INET6, r = snprintf (p, REMAIN, "%s", inet_ntop (AF_INET6,
&bi->attr->extra->mp_nexthop_global, &bi->attr->mp_nexthop_global,
buf, BUFSIZ)); buf, BUFSIZ));
INCP; INCP;
} }
@ -650,7 +646,7 @@ rfapiPrintBi (void *stream, struct bgp_info *bi)
} }
/* RFP option lengths */ /* RFP option lengths */
for (pEncap = bi->attr->extra->vnc_subtlvs; pEncap; for (pEncap = bi->attr->vnc_subtlvs; pEncap;
pEncap = pEncap->next) pEncap = pEncap->next)
{ {
@ -673,9 +669,9 @@ rfapiPrintBi (void *stream, struct bgp_info *bi)
} }
/* RT list */ /* RT list */
if (bi->attr->extra->ecommunity) if (bi->attr->ecommunity)
{ {
s = ecommunity_ecom2str (bi->attr->extra->ecommunity, s = ecommunity_ecom2str (bi->attr->ecommunity,
ECOMMUNITY_FORMAT_ROUTE_MAP, 0); ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
r = snprintf (p, REMAIN, " %s", s); r = snprintf (p, REMAIN, " %s", s);
INCP; INCP;
@ -704,9 +700,9 @@ rfapiPrintBi (void *stream, struct bgp_info *bi)
if (bi->attr) if (bi->attr)
{ {
if (bi->attr->extra) if (bi->attr->weight)
{ {
r = snprintf (p, REMAIN, " W=%d", bi->attr->extra->weight); r = snprintf (p, REMAIN, " W=%d", bi->attr->weight);
INCP; INCP;
} }

View File

@ -74,7 +74,6 @@ encap_attr_export_ce (
*/ */
memset (new, 0, sizeof (struct attr)); memset (new, 0, sizeof (struct attr));
bgp_attr_dup (new, orig); bgp_attr_dup (new, orig);
bgp_attr_extra_get (new);
/* /*
* Set nexthop * Set nexthop
@ -83,17 +82,13 @@ encap_attr_export_ce (
{ {
case AF_INET: case AF_INET:
new->nexthop = use_nexthop->u.prefix4; new->nexthop = use_nexthop->u.prefix4;
new->extra->mp_nexthop_len = 4; /* bytes */ new->mp_nexthop_len = 4; /* bytes */
new->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP); new->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
break; break;
case AF_INET6: case AF_INET6:
if (!new->extra) new->mp_nexthop_global = use_nexthop->u.prefix6;
{ new->mp_nexthop_len = 16; /* bytes */
new->extra = XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
}
new->extra->mp_nexthop_global = use_nexthop->u.prefix6;
new->extra->mp_nexthop_len = 16; /* bytes */
break; break;
default: default:
@ -133,7 +128,6 @@ encap_attr_export_ce (
* *
* Caller should, after using the attr, call: * Caller should, after using the attr, call:
* - bgp_attr_flush() to free non-interned parts * - bgp_attr_flush() to free non-interned parts
* - call bgp_attr_extra_free() to free extra
*/ */
} }
@ -144,8 +138,8 @@ getce (struct bgp *bgp, struct attr *attr, struct prefix *pfx_ce)
int i; int i;
uint16_t localadmin = bgp->rfapi_cfg->resolve_nve_roo_local_admin; uint16_t localadmin = bgp->rfapi_cfg->resolve_nve_roo_local_admin;
for (ecp = attr->extra->ecommunity->val, i = 0; for (ecp = attr->ecommunity->val, i = 0;
i < attr->extra->ecommunity->size; ++i, ecp += ECOMMUNITY_SIZE) i < attr->ecommunity->size; ++i, ecp += ECOMMUNITY_SIZE)
{ {
if (VNC_DEBUG(EXPORT_BGP_GETCE)) if (VNC_DEBUG(EXPORT_BGP_GETCE))
@ -309,14 +303,12 @@ vnc_direct_bgp_add_route_ce (
if (ret == RMAP_DENYMATCH) if (ret == RMAP_DENYMATCH)
{ {
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
return; return;
} }
} }
iattr = bgp_attr_intern (&hattr); iattr = bgp_attr_intern (&hattr);
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
/* /*
* Rule: disallow route-map alteration of next-hop, because it * Rule: disallow route-map alteration of next-hop, because it
@ -563,14 +555,14 @@ vnc_route_origin_ecom (struct route_node *rn)
struct ecommunity_val roec; struct ecommunity_val roec;
switch (BGP_MP_NEXTHOP_FAMILY (bi->attr->extra->mp_nexthop_len)) switch (BGP_MP_NEXTHOP_FAMILY (bi->attr->mp_nexthop_len))
{ {
case AF_INET: case AF_INET:
memset (&roec, 0, sizeof (roec)); memset (&roec, 0, sizeof (roec));
roec.val[0] = 0x01; roec.val[0] = 0x01;
roec.val[1] = 0x03; roec.val[1] = 0x03;
memcpy (roec.val + 2, memcpy (roec.val + 2,
&bi->attr->extra->mp_nexthop_global_in.s_addr, 4); &bi->attr->mp_nexthop_global_in.s_addr, 4);
roec.val[6] = 0; roec.val[6] = 0;
roec.val[7] = 0; roec.val[7] = 0;
ecommunity_add_val (new, &roec); ecommunity_add_val (new, &roec);
@ -642,16 +634,16 @@ encap_attr_export (
{ {
use_nexthop = &orig_nexthop; use_nexthop = &orig_nexthop;
orig_nexthop.family = orig_nexthop.family =
BGP_MP_NEXTHOP_FAMILY (orig->extra->mp_nexthop_len); BGP_MP_NEXTHOP_FAMILY (orig->mp_nexthop_len);
if (orig_nexthop.family == AF_INET) if (orig_nexthop.family == AF_INET)
{ {
orig_nexthop.prefixlen = 32; orig_nexthop.prefixlen = 32;
orig_nexthop.u.prefix4 = orig->extra->mp_nexthop_global_in; orig_nexthop.u.prefix4 = orig->mp_nexthop_global_in;
} }
else if (orig_nexthop.family == AF_INET6) else if (orig_nexthop.family == AF_INET6)
{ {
orig_nexthop.prefixlen = 128; orig_nexthop.prefixlen = 128;
orig_nexthop.u.prefix6 = orig->extra->mp_nexthop_global; orig_nexthop.u.prefix6 = orig->mp_nexthop_global;
} }
else else
{ {
@ -673,17 +665,13 @@ encap_attr_export (
{ {
case AF_INET: case AF_INET:
new->nexthop = use_nexthop->u.prefix4; new->nexthop = use_nexthop->u.prefix4;
new->extra->mp_nexthop_len = 4; /* bytes */ new->mp_nexthop_len = 4; /* bytes */
new->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP); new->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
break; break;
case AF_INET6: case AF_INET6:
if (!new->extra) new->mp_nexthop_global = use_nexthop->u.prefix6;
{ new->mp_nexthop_len = 16; /* bytes */
new->extra = XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
}
new->extra->mp_nexthop_global = use_nexthop->u.prefix6;
new->extra->mp_nexthop_len = 16; /* bytes */
break; break;
default: default:
@ -691,7 +679,6 @@ encap_attr_export (
break; break;
} }
bgp_attr_extra_get (new);
if (rn) if (rn)
{ {
ecom_ro = vnc_route_origin_ecom (rn); ecom_ro = vnc_route_origin_ecom (rn);
@ -701,17 +688,14 @@ encap_attr_export (
/* TBD test/assert for IPv6 */ /* TBD test/assert for IPv6 */
ecom_ro = vnc_route_origin_ecom_single (&use_nexthop->u.prefix4); ecom_ro = vnc_route_origin_ecom_single (&use_nexthop->u.prefix4);
} }
if (new->extra->ecommunity) if (new->ecommunity)
{ {
if (ecom_ro) if (ecom_ro)
{ new->ecommunity = ecommunity_merge (ecom_ro, new->ecommunity);
new->extra->ecommunity =
ecommunity_merge (ecom_ro, new->extra->ecommunity);
}
} }
else else
{ {
new->extra->ecommunity = ecom_ro; new->ecommunity = ecom_ro;
} }
if (ecom_ro) if (ecom_ro)
{ {
@ -750,7 +734,6 @@ encap_attr_export (
* *
* Caller should, after using the attr, call: * Caller should, after using the attr, call:
* - bgp_attr_flush() to free non-interned parts * - bgp_attr_flush() to free non-interned parts
* - call bgp_attr_extra_free() to free extra
*/ */
return 0; return 0;
@ -887,7 +870,6 @@ vnc_direct_bgp_add_prefix (
if (ret == RMAP_DENYMATCH) if (ret == RMAP_DENYMATCH)
{ {
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
vnc_zlog_debug_verbose vnc_zlog_debug_verbose
("%s: route map says DENY, so not calling bgp_update", ("%s: route map says DENY, so not calling bgp_update",
__func__); __func__);
@ -903,7 +885,6 @@ vnc_direct_bgp_add_prefix (
iattr = bgp_attr_intern (&hattr); iattr = bgp_attr_intern (&hattr);
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
bgp_update (irfd->peer, &rn->p, /* prefix */ bgp_update (irfd->peer, &rn->p, /* prefix */
0, /* addpath_id */ 0, /* addpath_id */
@ -917,7 +898,6 @@ vnc_direct_bgp_add_prefix (
} }
aspath_unintern (&attr.aspath); aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
} }
/* /*
@ -1134,7 +1114,6 @@ vnc_direct_bgp_add_nve (struct bgp *bgp, struct rfapi_descriptor *rfd)
if (ret == RMAP_DENYMATCH) if (ret == RMAP_DENYMATCH)
{ {
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
continue; continue;
} }
@ -1142,7 +1121,6 @@ vnc_direct_bgp_add_nve (struct bgp *bgp, struct rfapi_descriptor *rfd)
iattr = bgp_attr_intern (&hattr); iattr = bgp_attr_intern (&hattr);
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
bgp_update (irfd->peer, &rn->p, /* prefix */ bgp_update (irfd->peer, &rn->p, /* prefix */
0, /* addpath_id */ 0, /* addpath_id */
@ -1157,7 +1135,6 @@ vnc_direct_bgp_add_nve (struct bgp *bgp, struct rfapi_descriptor *rfd)
} }
aspath_unintern (&attr.aspath); aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
} }
} }
} }
@ -1361,7 +1338,6 @@ vnc_direct_bgp_add_group_afi (
if (ret == RMAP_DENYMATCH) if (ret == RMAP_DENYMATCH)
{ {
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
continue; continue;
} }
@ -1369,7 +1345,6 @@ vnc_direct_bgp_add_group_afi (
iattr = bgp_attr_intern (&hattr); iattr = bgp_attr_intern (&hattr);
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
bgp_update (irfd->peer, &rn->p, /* prefix */ bgp_update (irfd->peer, &rn->p, /* prefix */
0, /* addpath_id */ 0, /* addpath_id */
@ -1384,7 +1359,6 @@ vnc_direct_bgp_add_group_afi (
} }
aspath_unintern (&attr.aspath); aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
} }
@ -1744,14 +1718,12 @@ vnc_direct_bgp_rh_add_route (
if (ret == RMAP_DENYMATCH) if (ret == RMAP_DENYMATCH)
{ {
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
return; return;
} }
} }
iattr = bgp_attr_intern (&hattr); iattr = bgp_attr_intern (&hattr);
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
/* /*
* record route information that we will need to expire * record route information that we will need to expire
@ -1983,7 +1955,6 @@ vnc_direct_bgp_rh_vpn_enable (struct bgp *bgp, afi_t afi)
if (ret == RMAP_DENYMATCH) if (ret == RMAP_DENYMATCH)
{ {
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
vnc_zlog_debug_verbose ("%s: route map says DENY", __func__); vnc_zlog_debug_verbose ("%s: route map says DENY", __func__);
continue; continue;
} }
@ -1991,7 +1962,6 @@ vnc_direct_bgp_rh_vpn_enable (struct bgp *bgp, afi_t afi)
iattr = bgp_attr_intern (&hattr); iattr = bgp_attr_intern (&hattr);
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
/* /*
* record route information that we will need to expire * record route information that we will need to expire

View File

@ -393,7 +393,6 @@ process_unicast_route (
if (ret == RMAP_DENYMATCH) if (ret == RMAP_DENYMATCH)
{ {
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
vnc_zlog_debug_verbose ("%s: route map \"%s\" says DENY, returning", __func__, vnc_zlog_debug_verbose ("%s: route map \"%s\" says DENY, returning", __func__,
rmap->name); rmap->name);
return -1; return -1;
@ -406,8 +405,8 @@ process_unicast_route (
*/ */
rfapiUnicastNexthop2Prefix (afi, &hattr, unicast_nexthop); rfapiUnicastNexthop2Prefix (afi, &hattr, unicast_nexthop);
if (hattr.extra && hattr.extra->ecommunity) if (hattr.ecommunity)
*ecom = ecommunity_dup (hattr.extra->ecommunity); *ecom = ecommunity_dup (hattr.ecommunity);
else else
*ecom = ecommunity_new (); *ecom = ecommunity_new ();
@ -415,7 +414,6 @@ process_unicast_route (
* Done with hattr, clean up * Done with hattr, clean up
*/ */
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
/* /*
* Add EC that carries original NH of iBGP route (2 bytes = magic * Add EC that carries original NH of iBGP route (2 bytes = magic
@ -510,18 +508,18 @@ vnc_import_bgp_add_route_mode_resolve_nve_one_bi (
plifetime = &lifetime; plifetime = &lifetime;
} }
if (bi->attr && bi->attr->extra) if (bi->attr)
{ {
encaptlvs = bi->attr->extra->vnc_subtlvs; encaptlvs = bi->attr->vnc_subtlvs;
if (bi->attr->extra->encap_tunneltype != BGP_ENCAP_TYPE_RESERVED && if (bi->attr->encap_tunneltype != BGP_ENCAP_TYPE_RESERVED &&
bi->attr->extra->encap_tunneltype != BGP_ENCAP_TYPE_MPLS) bi->attr->encap_tunneltype != BGP_ENCAP_TYPE_MPLS)
{ {
if (opt != NULL) if (opt != NULL)
opt->next = &optary[cur_opt]; opt->next = &optary[cur_opt];
opt = &optary[cur_opt++]; opt = &optary[cur_opt++];
memset (opt, 0, sizeof (struct rfapi_un_option)); memset (opt, 0, sizeof (struct rfapi_un_option));
opt->type = RFAPI_UN_OPTION_TYPE_TUNNELTYPE; opt->type = RFAPI_UN_OPTION_TYPE_TUNNELTYPE;
opt->v.tunnel.type = bi->attr->extra->encap_tunneltype; opt->v.tunnel.type = bi->attr->encap_tunneltype;
/* TBD parse bi->attr->extra->encap_subtlvs */ /* TBD parse bi->attr->extra->encap_subtlvs */
} }
} }
@ -532,8 +530,8 @@ vnc_import_bgp_add_route_mode_resolve_nve_one_bi (
struct ecommunity *new_ecom = ecommunity_dup (ecom); struct ecommunity *new_ecom = ecommunity_dup (ecom);
if (bi->attr && bi->attr->extra && bi->attr->extra->ecommunity) if (bi->attr && bi->attr->ecommunity)
ecommunity_merge (new_ecom, bi->attr->extra->ecommunity); ecommunity_merge (new_ecom, bi->attr->ecommunity);
if (bi->extra) if (bi->extra)
label = decode_label (&bi->extra->label); label = decode_label (&bi->extra->label);
@ -891,7 +889,6 @@ vnc_import_bgp_add_route_mode_plain (struct bgp *bgp,
if (ret == RMAP_DENYMATCH) if (ret == RMAP_DENYMATCH)
{ {
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
vnc_zlog_debug_verbose ("%s: route map \"%s\" says DENY, returning", __func__, vnc_zlog_debug_verbose ("%s: route map \"%s\" says DENY, returning", __func__,
rmap->name); rmap->name);
return; return;
@ -900,7 +897,6 @@ vnc_import_bgp_add_route_mode_plain (struct bgp *bgp,
iattr = bgp_attr_intern (&hattr); iattr = bgp_attr_intern (&hattr);
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
/* Now iattr is an allocated interned attr */ /* Now iattr is an allocated interned attr */
@ -925,8 +921,8 @@ vnc_import_bgp_add_route_mode_plain (struct bgp *bgp,
memset (&prd, 0, sizeof (prd)); memset (&prd, 0, sizeof (prd));
rfapi_set_autord_from_vn (&prd, &vnaddr); rfapi_set_autord_from_vn (&prd, &vnaddr);
if (iattr && iattr->extra && iattr->extra->ecommunity) if (iattr && iattr->ecommunity)
ecom = ecommunity_dup (iattr->extra->ecommunity); ecom = ecommunity_dup (iattr->ecommunity);
} }
@ -1103,7 +1099,6 @@ vnc_import_bgp_add_route_mode_nvegroup (struct bgp *bgp,
if (ret == RMAP_DENYMATCH) if (ret == RMAP_DENYMATCH)
{ {
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
vnc_zlog_debug_verbose ("%s: route map \"%s\" says DENY, returning", __func__, vnc_zlog_debug_verbose ("%s: route map \"%s\" says DENY, returning", __func__,
rmap->name); rmap->name);
return; return;
@ -1112,7 +1107,6 @@ vnc_import_bgp_add_route_mode_nvegroup (struct bgp *bgp,
iattr = bgp_attr_intern (&hattr); iattr = bgp_attr_intern (&hattr);
bgp_attr_flush (&hattr); bgp_attr_flush (&hattr);
bgp_attr_extra_free (&hattr);
/* Now iattr is an allocated interned attr */ /* Now iattr is an allocated interned attr */
@ -1139,8 +1133,8 @@ vnc_import_bgp_add_route_mode_nvegroup (struct bgp *bgp,
else else
ecom = ecommunity_new (); ecom = ecommunity_new ();
if (iattr && iattr->extra && iattr->extra->ecommunity) if (iattr && iattr->ecommunity)
ecom = ecommunity_merge (ecom, iattr->extra->ecommunity); ecom = ecommunity_merge (ecom, iattr->ecommunity);
} }
local_pref = calc_local_pref (iattr, peer); local_pref = calc_local_pref (iattr, peer);
@ -1942,7 +1936,6 @@ vnc_import_bgp_exterior_add_route_it (
ZEBRA_ROUTE_BGP_DIRECT_EXT, ZEBRA_ROUTE_BGP_DIRECT_EXT,
BGP_ROUTE_REDISTRIBUTE, &label); BGP_ROUTE_REDISTRIBUTE, &label);
bgp_attr_extra_free (&new_attr);
} }
if (have_usable_route) if (have_usable_route)
@ -2273,7 +2266,6 @@ vnc_import_bgp_exterior_add_route_interior (
ZEBRA_ROUTE_BGP_DIRECT_EXT, ZEBRA_ROUTE_BGP_DIRECT_EXT,
BGP_ROUTE_REDISTRIBUTE, &label); BGP_ROUTE_REDISTRIBUTE, &label);
bgp_attr_extra_free (&new_attr);
} }
vnc_zlog_debug_verbose vnc_zlog_debug_verbose
("%s: finished constructing exteriors based on existing monitors", ("%s: finished constructing exteriors based on existing monitors",
@ -2412,7 +2404,6 @@ vnc_import_bgp_exterior_add_route_interior (
ZEBRA_ROUTE_BGP_DIRECT_EXT, ZEBRA_ROUTE_BGP_DIRECT_EXT,
BGP_ROUTE_REDISTRIBUTE, &label); BGP_ROUTE_REDISTRIBUTE, &label);
bgp_attr_extra_free (&new_attr);
} }
} }
@ -2536,7 +2527,6 @@ vnc_import_bgp_exterior_add_route_interior (
ZEBRA_ROUTE_BGP_DIRECT_EXT, ZEBRA_ROUTE_BGP_DIRECT_EXT,
BGP_ROUTE_REDISTRIBUTE, &label); BGP_ROUTE_REDISTRIBUTE, &label);
bgp_attr_extra_free (&new_attr);
} }
} }
if (list_adopted) if (list_adopted)
@ -2740,7 +2730,6 @@ vnc_import_bgp_exterior_del_route_interior (
ZEBRA_ROUTE_BGP_DIRECT_EXT, ZEBRA_ROUTE_BGP_DIRECT_EXT,
BGP_ROUTE_REDISTRIBUTE, &label); BGP_ROUTE_REDISTRIBUTE, &label);
bgp_attr_extra_free (&new_attr);
} }
} }

View File

@ -909,6 +909,9 @@ node_parent ( enum node_type node )
case BGP_IPV6L_NODE: case BGP_IPV6L_NODE:
ret = BGP_NODE; ret = BGP_NODE;
break; break;
case BGP_EVPN_VNI_NODE:
ret = BGP_EVPN_NODE;
break;
case KEYCHAIN_KEY_NODE: case KEYCHAIN_KEY_NODE:
ret = KEYCHAIN_NODE; ret = KEYCHAIN_NODE;
break; break;
@ -1278,6 +1281,9 @@ cmd_exit (struct vty *vty)
case BGP_IPV6L_NODE: case BGP_IPV6L_NODE:
vty->node = BGP_NODE; vty->node = BGP_NODE;
break; break;
case BGP_EVPN_VNI_NODE:
vty->node = BGP_EVPN_NODE;
break;
case LDP_IPV4_NODE: case LDP_IPV4_NODE:
case LDP_IPV6_NODE: case LDP_IPV6_NODE:
vty->node = LDP_NODE; vty->node = LDP_NODE;
@ -1346,6 +1352,7 @@ DEFUN (config_end,
case BGP_IPV6_NODE: case BGP_IPV6_NODE:
case BGP_IPV6M_NODE: case BGP_IPV6M_NODE:
case BGP_EVPN_NODE: case BGP_EVPN_NODE:
case BGP_EVPN_VNI_NODE:
case BGP_IPV6L_NODE: case BGP_IPV6L_NODE:
case RMAP_NODE: case RMAP_NODE:
case OSPF_NODE: case OSPF_NODE:

View File

@ -136,6 +136,7 @@ enum node_type
MPLS_NODE, /* MPLS config node */ MPLS_NODE, /* MPLS config node */
VTY_NODE, /* Vty node. */ VTY_NODE, /* Vty node. */
LINK_PARAMS_NODE, /* Link-parameters node */ LINK_PARAMS_NODE, /* Link-parameters node */
BGP_EVPN_VNI_NODE, /* BGP EVPN VNI */
}; };
/* Node which has some commands and prompt string and configuration /* Node which has some commands and prompt string and configuration

View File

@ -946,6 +946,15 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY (ZEBRA_LABEL_MANAGER_CONNECT), DESC_ENTRY (ZEBRA_LABEL_MANAGER_CONNECT),
DESC_ENTRY (ZEBRA_GET_LABEL_CHUNK), DESC_ENTRY (ZEBRA_GET_LABEL_CHUNK),
DESC_ENTRY (ZEBRA_RELEASE_LABEL_CHUNK), DESC_ENTRY (ZEBRA_RELEASE_LABEL_CHUNK),
DESC_ENTRY (ZEBRA_ADVERTISE_ALL_VNI),
DESC_ENTRY (ZEBRA_VNI_ADD),
DESC_ENTRY (ZEBRA_VNI_DEL),
DESC_ENTRY (ZEBRA_REMOTE_VTEP_ADD),
DESC_ENTRY (ZEBRA_REMOTE_VTEP_DEL),
DESC_ENTRY (ZEBRA_MACIP_ADD),
DESC_ENTRY (ZEBRA_MACIP_DEL),
DESC_ENTRY (ZEBRA_REMOTE_MACIP_ADD),
DESC_ENTRY (ZEBRA_REMOTE_MACIP_DEL),
}; };
#undef DESC_ENTRY #undef DESC_ENTRY

View File

@ -768,6 +768,7 @@ vty_end_config (struct vty *vty)
case MASC_NODE: case MASC_NODE:
case PIM_NODE: case PIM_NODE:
case VTY_NODE: case VTY_NODE:
case BGP_EVPN_VNI_NODE:
vty_config_unlock (vty); vty_config_unlock (vty);
vty->node = ENABLE_NODE; vty->node = ENABLE_NODE;
break; break;

View File

@ -2047,6 +2047,22 @@ zclient_read (struct thread *thread)
if (zclient->fec_update) if (zclient->fec_update)
(*zclient->fec_update) (command, zclient, length); (*zclient->fec_update) (command, zclient, length);
break; break;
case ZEBRA_VNI_ADD:
if (zclient->local_vni_add)
(*zclient->local_vni_add) (command, zclient, length, vrf_id);
break;
case ZEBRA_VNI_DEL:
if (zclient->local_vni_del)
(*zclient->local_vni_del) (command, zclient, length, vrf_id);
break;
case ZEBRA_MACIP_ADD:
if (zclient->local_macip_add)
(*zclient->local_macip_add) (command, zclient, length, vrf_id);
break;
case ZEBRA_MACIP_DEL:
if (zclient->local_macip_del)
(*zclient->local_macip_del) (command, zclient, length, vrf_id);
break;
default: default:
break; break;
} }

View File

@ -96,6 +96,15 @@ typedef enum {
ZEBRA_FEC_REGISTER, ZEBRA_FEC_REGISTER,
ZEBRA_FEC_UNREGISTER, ZEBRA_FEC_UNREGISTER,
ZEBRA_FEC_UPDATE, ZEBRA_FEC_UPDATE,
ZEBRA_ADVERTISE_ALL_VNI,
ZEBRA_VNI_ADD,
ZEBRA_VNI_DEL,
ZEBRA_REMOTE_VTEP_ADD,
ZEBRA_REMOTE_VTEP_DEL,
ZEBRA_MACIP_ADD,
ZEBRA_MACIP_DEL,
ZEBRA_REMOTE_MACIP_ADD,
ZEBRA_REMOTE_MACIP_DEL,
} zebra_message_types_t; } zebra_message_types_t;
struct redist_proto struct redist_proto
@ -167,6 +176,10 @@ struct zclient
int (*redistribute_route_ipv6_add) (int, struct zclient *, uint16_t, vrf_id_t); int (*redistribute_route_ipv6_add) (int, struct zclient *, uint16_t, vrf_id_t);
int (*redistribute_route_ipv6_del) (int, struct zclient *, uint16_t, vrf_id_t); int (*redistribute_route_ipv6_del) (int, struct zclient *, uint16_t, vrf_id_t);
int (*fec_update) (int, struct zclient *, uint16_t); int (*fec_update) (int, struct zclient *, uint16_t);
int (*local_vni_add) (int, struct zclient *, uint16_t, vrf_id_t);
int (*local_vni_del) (int, struct zclient *, uint16_t, vrf_id_t);
int (*local_macip_add) (int, struct zclient *, uint16_t, vrf_id_t);
int (*local_macip_del) (int, struct zclient *, uint16_t, vrf_id_t);
}; };
/* Zebra API message flag. */ /* Zebra API message flag. */

View File

@ -314,6 +314,10 @@ vtysh_execute_func (const char *line, int pager)
{ {
vtysh_execute("exit-address-family"); vtysh_execute("exit-address-family");
} }
else if ((saved_node == BGP_EVPN_VNI_NODE) && (tried == 1))
{
vtysh_execute("exit-vni");
}
else if (saved_node == BGP_VRF_POLICY_NODE && (tried == 1)) else if (saved_node == BGP_VRF_POLICY_NODE && (tried == 1))
{ {
vtysh_execute("exit-vrf-policy"); vtysh_execute("exit-vrf-policy");
@ -576,6 +580,10 @@ vtysh_mark_file (const char *filename)
{ {
fprintf(stdout, "exit-address-family\n"); fprintf(stdout, "exit-address-family\n");
} }
else if ((prev_node == BGP_EVPN_VNI_NODE) && (tried == 1))
{
fprintf(stdout, "exit-vni\n");
}
else if ((prev_node == KEYCHAIN_KEY_NODE) && (tried == 1)) else if ((prev_node == KEYCHAIN_KEY_NODE) && (tried == 1))
{ {
fprintf(stdout, "exit\n"); fprintf(stdout, "exit\n");
@ -989,6 +997,12 @@ static struct cmd_node bgp_evpn_node =
"%s(config-router-af)# " "%s(config-router-af)# "
}; };
static struct cmd_node bgp_evpn_vni_node =
{
BGP_EVPN_VNI_NODE,
"%s(config-router-af-vni)# "
};
static struct cmd_node bgp_ipv6l_node = static struct cmd_node bgp_ipv6l_node =
{ {
BGP_IPV6L_NODE, BGP_IPV6L_NODE,
@ -1283,6 +1297,30 @@ DEFUNSH (VTYSH_BGPD,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
#if defined (HAVE_CUMULUS)
DEFUNSH (VTYSH_BGPD,
address_family_evpn2,
address_family_evpn2_cmd,
"address-family evpn",
"Enter Address Family command mode\n"
"EVPN Address family\n")
{
vty->node = BGP_EVPN_NODE;
return CMD_SUCCESS;
}
#endif
DEFUNSH (VTYSH_BGPD,
bgp_evpn_vni,
bgp_evpn_vni_cmd,
"vni (1-16777215)",
"VXLAN Network Identifier\n"
"VNI number\n")
{
vty->node = BGP_EVPN_VNI_NODE;
return CMD_SUCCESS;
}
#if defined (ENABLE_BGP_VNC) #if defined (ENABLE_BGP_VNC)
DEFUNSH (VTYSH_BGPD, DEFUNSH (VTYSH_BGPD,
vnc_defaults, vnc_defaults,
@ -1622,6 +1660,9 @@ vtysh_exit (struct vty *vty)
case BGP_VNC_L2_GROUP_NODE: case BGP_VNC_L2_GROUP_NODE:
vty->node = BGP_NODE; vty->node = BGP_NODE;
break; break;
case BGP_EVPN_VNI_NODE:
vty->node = BGP_EVPN_NODE;
break;
case LDP_IPV4_NODE: case LDP_IPV4_NODE:
case LDP_IPV6_NODE: case LDP_IPV6_NODE:
vty->node = LDP_NODE; vty->node = LDP_NODE;
@ -1678,11 +1719,23 @@ DEFUNSH (VTYSH_BGPD,
|| vty->node == BGP_VPNV6_NODE || vty->node == BGP_VPNV6_NODE
|| vty->node == BGP_IPV6_NODE || vty->node == BGP_IPV6_NODE
|| vty->node == BGP_IPV6L_NODE || vty->node == BGP_IPV6L_NODE
|| vty->node == BGP_IPV6M_NODE) || vty->node == BGP_IPV6M_NODE
|| vty->node == BGP_EVPN_NODE)
vty->node = BGP_NODE; vty->node = BGP_NODE;
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUNSH (VTYSH_BGPD,
exit_vni,
exit_vni_cmd,
"exit-vni",
"Exit from VNI mode\n")
{
if (vty->node == BGP_EVPN_VNI_NODE)
vty->node = BGP_EVPN_NODE;
return CMD_SUCCESS;
}
DEFUNSH (VTYSH_BGPD, DEFUNSH (VTYSH_BGPD,
exit_vnc_config, exit_vnc_config,
exit_vnc_config_cmd, exit_vnc_config_cmd,
@ -3289,6 +3342,7 @@ vtysh_init_vty (void)
install_node (&bgp_ipv6l_node, NULL); install_node (&bgp_ipv6l_node, NULL);
install_node (&bgp_vrf_policy_node, NULL); install_node (&bgp_vrf_policy_node, NULL);
install_node (&bgp_evpn_node, NULL); install_node (&bgp_evpn_node, NULL);
install_node (&bgp_evpn_vni_node, NULL);
install_node (&bgp_vnc_defaults_node, NULL); install_node (&bgp_vnc_defaults_node, NULL);
install_node (&bgp_vnc_nve_group_node, NULL); install_node (&bgp_vnc_nve_group_node, NULL);
install_node (&bgp_vnc_l2_group_node, NULL); install_node (&bgp_vnc_l2_group_node, NULL);
@ -3327,6 +3381,7 @@ vtysh_init_vty (void)
vtysh_install_default (BGP_IPV6_NODE); vtysh_install_default (BGP_IPV6_NODE);
vtysh_install_default (BGP_IPV6M_NODE); vtysh_install_default (BGP_IPV6M_NODE);
vtysh_install_default (BGP_EVPN_NODE); vtysh_install_default (BGP_EVPN_NODE);
vtysh_install_default (BGP_EVPN_VNI_NODE);
vtysh_install_default (BGP_IPV6L_NODE); vtysh_install_default (BGP_IPV6L_NODE);
#if ENABLE_BGP_VNC #if ENABLE_BGP_VNC
vtysh_install_default (BGP_VRF_POLICY_NODE); vtysh_install_default (BGP_VRF_POLICY_NODE);
@ -3405,6 +3460,9 @@ vtysh_init_vty (void)
install_element (BGP_IPV6M_NODE, &vtysh_exit_bgpd_cmd); install_element (BGP_IPV6M_NODE, &vtysh_exit_bgpd_cmd);
install_element (BGP_IPV6M_NODE, &vtysh_quit_bgpd_cmd); install_element (BGP_IPV6M_NODE, &vtysh_quit_bgpd_cmd);
install_element (BGP_EVPN_NODE, &vtysh_quit_bgpd_cmd); install_element (BGP_EVPN_NODE, &vtysh_quit_bgpd_cmd);
install_element (BGP_EVPN_NODE, &vtysh_exit_bgpd_cmd);
install_element (BGP_EVPN_VNI_NODE, &vtysh_exit_bgpd_cmd);
install_element (BGP_EVPN_VNI_NODE, &vtysh_quit_bgpd_cmd);
install_element (BGP_IPV6L_NODE, &vtysh_exit_bgpd_cmd); install_element (BGP_IPV6L_NODE, &vtysh_exit_bgpd_cmd);
install_element (BGP_IPV6L_NODE, &vtysh_quit_bgpd_cmd); install_element (BGP_IPV6L_NODE, &vtysh_quit_bgpd_cmd);
#if defined (ENABLE_BGP_VNC) #if defined (ENABLE_BGP_VNC)
@ -3455,6 +3513,7 @@ vtysh_init_vty (void)
install_element (BGP_IPV6L_NODE, &vtysh_end_all_cmd); install_element (BGP_IPV6L_NODE, &vtysh_end_all_cmd);
install_element (BGP_VRF_POLICY_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_EVPN_NODE, &vtysh_end_all_cmd);
install_element (BGP_EVPN_VNI_NODE, &vtysh_end_all_cmd);
install_element (BGP_VNC_DEFAULTS_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_NVE_GROUP_NODE, &vtysh_end_all_cmd);
install_element (BGP_VNC_L2_GROUP_NODE, &vtysh_end_all_cmd); install_element (BGP_VNC_L2_GROUP_NODE, &vtysh_end_all_cmd);
@ -3517,6 +3576,9 @@ vtysh_init_vty (void)
install_element (BGP_NODE, &address_family_ipv6_vpn_cmd); install_element (BGP_NODE, &address_family_ipv6_vpn_cmd);
install_element (BGP_NODE, &address_family_ipv6_labeled_unicast_cmd); install_element (BGP_NODE, &address_family_ipv6_labeled_unicast_cmd);
install_element (BGP_NODE, &address_family_evpn_cmd); install_element (BGP_NODE, &address_family_evpn_cmd);
#if defined (HAVE_CUMULUS)
install_element (BGP_NODE, &address_family_evpn2_cmd);
#endif
install_element (BGP_VPNV4_NODE, &exit_address_family_cmd); install_element (BGP_VPNV4_NODE, &exit_address_family_cmd);
install_element (BGP_VPNV6_NODE, &exit_address_family_cmd); install_element (BGP_VPNV6_NODE, &exit_address_family_cmd);
install_element (BGP_IPV4_NODE, &exit_address_family_cmd); install_element (BGP_IPV4_NODE, &exit_address_family_cmd);
@ -3527,6 +3589,10 @@ vtysh_init_vty (void)
install_element (BGP_EVPN_NODE, &exit_address_family_cmd); install_element (BGP_EVPN_NODE, &exit_address_family_cmd);
install_element (BGP_IPV6L_NODE, &exit_address_family_cmd); install_element (BGP_IPV6L_NODE, &exit_address_family_cmd);
/* EVPN commands */
install_element (BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
install_element (BGP_EVPN_VNI_NODE, &exit_vni_cmd);
install_element (BGP_VRF_POLICY_NODE, &exit_vrf_policy_cmd); install_element (BGP_VRF_POLICY_NODE, &exit_vrf_policy_cmd);
install_element (BGP_VNC_DEFAULTS_NODE, &exit_vnc_config_cmd); install_element (BGP_VNC_DEFAULTS_NODE, &exit_vnc_config_cmd);
install_element (BGP_VNC_NVE_GROUP_NODE, &exit_vnc_config_cmd); install_element (BGP_VNC_NVE_GROUP_NODE, &exit_vnc_config_cmd);

View File

@ -33,6 +33,8 @@ zebra_SOURCES = \
zebra_ns.c zebra_vrf.c zebra_static.c zebra_mpls.c zebra_mpls_vty.c \ zebra_ns.c zebra_vrf.c zebra_static.c zebra_mpls.c zebra_mpls_vty.c \
zebra_mroute.c \ zebra_mroute.c \
label_manager.c \ label_manager.c \
zebra_l2.c \
zebra_vxlan.c \
# end # end
noinst_HEADERS = \ noinst_HEADERS = \
@ -42,7 +44,8 @@ noinst_HEADERS = \
rt_netlink.h zebra_fpm_private.h zebra_rnh.h \ rt_netlink.h zebra_fpm_private.h zebra_rnh.h \
zebra_ptm_redistribute.h zebra_ptm.h zebra_routemap.h \ zebra_ptm_redistribute.h zebra_ptm.h zebra_routemap.h \
zebra_ns.h zebra_vrf.h ioctl_solaris.h zebra_static.h zebra_mpls.h \ zebra_ns.h zebra_vrf.h ioctl_solaris.h zebra_static.h zebra_mpls.h \
kernel_netlink.h if_netlink.h zebra_mroute.h label_manager.h kernel_netlink.h if_netlink.h zebra_mroute.h label_manager.h \
zebra_l2.h zebra_vxlan_private.h zebra_vxlan.h
zebra_LDADD = $(otherobj) ../lib/libfrr.la $(LIBCAP) zebra_LDADD = $(otherobj) ../lib/libfrr.la $(LIBCAP)

View File

@ -31,6 +31,7 @@ unsigned long zebra_debug_rib;
unsigned long zebra_debug_fpm; unsigned long zebra_debug_fpm;
unsigned long zebra_debug_nht; unsigned long zebra_debug_nht;
unsigned long zebra_debug_mpls; unsigned long zebra_debug_mpls;
unsigned long zebra_debug_vxlan;
DEFUN (show_debugging_zebra, DEFUN (show_debugging_zebra,
show_debugging_zebra_cmd, show_debugging_zebra_cmd,
@ -118,6 +119,17 @@ DEFUN (debug_zebra_mpls,
return CMD_WARNING_CONFIG_FAILED; return CMD_WARNING_CONFIG_FAILED;
} }
DEFUN (debug_zebra_vxlan,
debug_zebra_vxlan_cmd,
"debug zebra vxlan",
DEBUG_STR
"Zebra configuration\n"
"Debug option set for zebra VxLAN (EVPN)\n")
{
zebra_debug_vxlan = ZEBRA_DEBUG_VXLAN;
return CMD_WARNING;
}
DEFUN (debug_zebra_packet, DEFUN (debug_zebra_packet,
debug_zebra_packet_cmd, debug_zebra_packet_cmd,
"debug zebra packet [<recv|send>] [detail]", "debug zebra packet [<recv|send>] [detail]",
@ -248,6 +260,18 @@ DEFUN (no_debug_zebra_mpls,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN (no_debug_zebra_vxlan,
no_debug_zebra_vxlan_cmd,
"no debug zebra vxlan",
NO_STR
DEBUG_STR
"Zebra configuration\n"
"Debug option set for zebra VxLAN (EVPN)\n")
{
zebra_debug_vxlan = 0;
return CMD_SUCCESS;
}
DEFUN (no_debug_zebra_packet, DEFUN (no_debug_zebra_packet,
no_debug_zebra_packet_cmd, no_debug_zebra_packet_cmd,
"no debug zebra packet [<recv|send>]", "no debug zebra packet [<recv|send>]",
@ -413,6 +437,11 @@ config_write_debug (struct vty *vty)
vty_out (vty, "debug zebra mpls\n"); vty_out (vty, "debug zebra mpls\n");
write++; write++;
} }
if (IS_ZEBRA_DEBUG_VXLAN)
{
vty_out (vty, "debug zebra vxlan\n");
write++;
}
return write; return write;
} }
@ -425,6 +454,7 @@ zebra_debug_init (void)
zebra_debug_rib = 0; zebra_debug_rib = 0;
zebra_debug_fpm = 0; zebra_debug_fpm = 0;
zebra_debug_mpls = 0; zebra_debug_mpls = 0;
zebra_debug_vxlan = 0;
install_node (&debug_node, config_write_debug); install_node (&debug_node, config_write_debug);
@ -433,6 +463,7 @@ zebra_debug_init (void)
install_element (ENABLE_NODE, &debug_zebra_events_cmd); install_element (ENABLE_NODE, &debug_zebra_events_cmd);
install_element (ENABLE_NODE, &debug_zebra_nht_cmd); install_element (ENABLE_NODE, &debug_zebra_nht_cmd);
install_element (ENABLE_NODE, &debug_zebra_mpls_cmd); install_element (ENABLE_NODE, &debug_zebra_mpls_cmd);
install_element (ENABLE_NODE, &debug_zebra_vxlan_cmd);
install_element (ENABLE_NODE, &debug_zebra_packet_cmd); install_element (ENABLE_NODE, &debug_zebra_packet_cmd);
install_element (ENABLE_NODE, &debug_zebra_kernel_cmd); install_element (ENABLE_NODE, &debug_zebra_kernel_cmd);
install_element (ENABLE_NODE, &debug_zebra_kernel_msgdump_cmd); install_element (ENABLE_NODE, &debug_zebra_kernel_msgdump_cmd);
@ -442,6 +473,7 @@ zebra_debug_init (void)
install_element (ENABLE_NODE, &no_debug_zebra_events_cmd); install_element (ENABLE_NODE, &no_debug_zebra_events_cmd);
install_element (ENABLE_NODE, &no_debug_zebra_nht_cmd); install_element (ENABLE_NODE, &no_debug_zebra_nht_cmd);
install_element (ENABLE_NODE, &no_debug_zebra_mpls_cmd); install_element (ENABLE_NODE, &no_debug_zebra_mpls_cmd);
install_element (ENABLE_NODE, &no_debug_zebra_vxlan_cmd);
install_element (ENABLE_NODE, &no_debug_zebra_packet_cmd); install_element (ENABLE_NODE, &no_debug_zebra_packet_cmd);
install_element (ENABLE_NODE, &no_debug_zebra_kernel_cmd); install_element (ENABLE_NODE, &no_debug_zebra_kernel_cmd);
install_element (ENABLE_NODE, &no_debug_zebra_kernel_msgdump_cmd); install_element (ENABLE_NODE, &no_debug_zebra_kernel_msgdump_cmd);
@ -452,6 +484,7 @@ zebra_debug_init (void)
install_element (CONFIG_NODE, &debug_zebra_events_cmd); install_element (CONFIG_NODE, &debug_zebra_events_cmd);
install_element (CONFIG_NODE, &debug_zebra_nht_cmd); install_element (CONFIG_NODE, &debug_zebra_nht_cmd);
install_element (CONFIG_NODE, &debug_zebra_mpls_cmd); install_element (CONFIG_NODE, &debug_zebra_mpls_cmd);
install_element (CONFIG_NODE, &debug_zebra_vxlan_cmd);
install_element (CONFIG_NODE, &debug_zebra_packet_cmd); install_element (CONFIG_NODE, &debug_zebra_packet_cmd);
install_element (CONFIG_NODE, &debug_zebra_kernel_cmd); install_element (CONFIG_NODE, &debug_zebra_kernel_cmd);
install_element (CONFIG_NODE, &debug_zebra_kernel_msgdump_cmd); install_element (CONFIG_NODE, &debug_zebra_kernel_msgdump_cmd);
@ -461,6 +494,7 @@ zebra_debug_init (void)
install_element (CONFIG_NODE, &no_debug_zebra_events_cmd); install_element (CONFIG_NODE, &no_debug_zebra_events_cmd);
install_element (CONFIG_NODE, &no_debug_zebra_nht_cmd); install_element (CONFIG_NODE, &no_debug_zebra_nht_cmd);
install_element (CONFIG_NODE, &no_debug_zebra_mpls_cmd); install_element (CONFIG_NODE, &no_debug_zebra_mpls_cmd);
install_element (CONFIG_NODE, &no_debug_zebra_vxlan_cmd);
install_element (CONFIG_NODE, &no_debug_zebra_packet_cmd); install_element (CONFIG_NODE, &no_debug_zebra_packet_cmd);
install_element (CONFIG_NODE, &no_debug_zebra_kernel_cmd); install_element (CONFIG_NODE, &no_debug_zebra_kernel_cmd);
install_element (CONFIG_NODE, &no_debug_zebra_kernel_msgdump_cmd); install_element (CONFIG_NODE, &no_debug_zebra_kernel_msgdump_cmd);

View File

@ -42,6 +42,8 @@
#define ZEBRA_DEBUG_MPLS 0x01 #define ZEBRA_DEBUG_MPLS 0x01
#define ZEBRA_DEBUG_VXLAN 0x01
/* Debug related macro. */ /* Debug related macro. */
#define IS_ZEBRA_DEBUG_EVENT (zebra_debug_event & ZEBRA_DEBUG_EVENT) #define IS_ZEBRA_DEBUG_EVENT (zebra_debug_event & ZEBRA_DEBUG_EVENT)
@ -63,6 +65,7 @@
#define IS_ZEBRA_DEBUG_FPM (zebra_debug_fpm & ZEBRA_DEBUG_FPM) #define IS_ZEBRA_DEBUG_FPM (zebra_debug_fpm & ZEBRA_DEBUG_FPM)
#define IS_ZEBRA_DEBUG_NHT (zebra_debug_nht & ZEBRA_DEBUG_NHT) #define IS_ZEBRA_DEBUG_NHT (zebra_debug_nht & ZEBRA_DEBUG_NHT)
#define IS_ZEBRA_DEBUG_MPLS (zebra_debug_mpls & ZEBRA_DEBUG_MPLS) #define IS_ZEBRA_DEBUG_MPLS (zebra_debug_mpls & ZEBRA_DEBUG_MPLS)
#define IS_ZEBRA_DEBUG_VXLAN (zebra_debug_vxlan & ZEBRA_DEBUG_VXLAN)
extern unsigned long zebra_debug_event; extern unsigned long zebra_debug_event;
extern unsigned long zebra_debug_packet; extern unsigned long zebra_debug_packet;
@ -71,6 +74,7 @@ extern unsigned long zebra_debug_rib;
extern unsigned long zebra_debug_fpm; extern unsigned long zebra_debug_fpm;
extern unsigned long zebra_debug_nht; extern unsigned long zebra_debug_nht;
extern unsigned long zebra_debug_mpls; extern unsigned long zebra_debug_mpls;
extern unsigned long zebra_debug_vxlan;
extern void zebra_debug_init (void); extern void zebra_debug_init (void);

View File

@ -20,6 +20,15 @@
*/ */
#include <zebra.h> #include <zebra.h>
/* The following definition is to workaround an issue in the Linux kernel
* header files with redefinition of 'struct in6_addr' in both
* netinet/in.h and linux/in6.h.
* Reference - https://sourceware.org/ml/libc-alpha/2013-01/msg00599.html
*/
#define _LINUX_IN6_H
#include <linux/if_bridge.h>
#include <net/if_arp.h> #include <net/if_arp.h>
#include <linux/sockios.h> #include <linux/sockios.h>
#include <linux/ethtool.h> #include <linux/ethtool.h>
@ -175,6 +184,23 @@ netlink_to_zebra_link_type (unsigned int hwt)
} }
} }
static void
netlink_determine_zebra_iftype (char *kind, zebra_iftype_t *zif_type)
{
*zif_type = ZEBRA_IF_OTHER;
if (!kind)
return;
if (strcmp(kind, "vrf") == 0)
*zif_type = ZEBRA_IF_VRF;
else if (strcmp(kind, "bridge") == 0)
*zif_type = ZEBRA_IF_BRIDGE;
else if (strcmp(kind, "vlan") == 0)
*zif_type = ZEBRA_IF_VLAN;
else if (strcmp(kind, "vxlan") == 0)
*zif_type = ZEBRA_IF_VXLAN;
}
//Temporary Assignments to compile on older platforms. //Temporary Assignments to compile on older platforms.
#ifndef IFLA_BR_MAX #ifndef IFLA_BR_MAX
@ -341,6 +367,173 @@ get_iflink_speed (const char *ifname)
return (ecmd.speed_hi << 16 ) | ecmd.speed; return (ecmd.speed_hi << 16 ) | ecmd.speed;
} }
static int
netlink_extract_bridge_info (struct rtattr *link_data,
struct zebra_l2info_bridge *bridge_info)
{
struct rtattr *attr[IFLA_BR_MAX+1];
memset (bridge_info, 0, sizeof (*bridge_info));
memset (attr, 0, sizeof attr);
parse_rtattr_nested(attr, IFLA_BR_MAX, link_data);
if (attr[IFLA_BR_VLAN_FILTERING])
bridge_info->vlan_aware = *(u_char *)RTA_DATA(attr[IFLA_BR_VLAN_FILTERING]);
return 0;
}
static int
netlink_extract_vlan_info (struct rtattr *link_data,
struct zebra_l2info_vlan *vlan_info)
{
struct rtattr *attr[IFLA_VLAN_MAX+1];
vlanid_t vid_in_msg;
memset (vlan_info, 0, sizeof (*vlan_info));
memset (attr, 0, sizeof attr);
parse_rtattr_nested(attr, IFLA_VLAN_MAX, link_data);
if (!attr[IFLA_VLAN_ID])
{
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("IFLA_VLAN_ID missing from VLAN IF message");
return -1;
}
vid_in_msg = *(vlanid_t *)RTA_DATA(attr[IFLA_VLAN_ID]);
vlan_info->vid = vid_in_msg;
return 0;
}
static int
netlink_extract_vxlan_info (struct rtattr *link_data,
struct zebra_l2info_vxlan *vxl_info)
{
struct rtattr *attr[IFLA_VXLAN_MAX+1];
vni_t vni_in_msg;
struct in_addr vtep_ip_in_msg;
memset (vxl_info, 0, sizeof (*vxl_info));
memset (attr, 0, sizeof attr);
parse_rtattr_nested(attr, IFLA_VXLAN_MAX, link_data);
if (!attr[IFLA_VXLAN_ID])
{
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("IFLA_VXLAN_ID missing from VXLAN IF message");
return -1;
}
vni_in_msg = *(vni_t *)RTA_DATA(attr[IFLA_VXLAN_ID]);
vxl_info->vni = vni_in_msg;
if (!attr[IFLA_VXLAN_LOCAL])
{
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("IFLA_VXLAN_LOCAL missing from VXLAN IF message");
}
else
{
vtep_ip_in_msg = *(struct in_addr *)RTA_DATA(attr[IFLA_VXLAN_LOCAL]);
vxl_info->vtep_ip = vtep_ip_in_msg;
}
return 0;
}
/*
* Extract and save L2 params (of interest) for an interface. When a
* bridge interface is added or updated, take further actions to map
* its members. Likewise, for VxLAN interface.
*/
static void
netlink_interface_update_l2info (struct interface *ifp,
struct rtattr *link_data,
int add)
{
if (!link_data)
return;
if (IS_ZEBRA_IF_BRIDGE(ifp))
{
struct zebra_l2info_bridge bridge_info;
netlink_extract_bridge_info (link_data, &bridge_info);
zebra_l2_bridge_add_update (ifp, &bridge_info, add);
}
else if (IS_ZEBRA_IF_VLAN(ifp))
{
struct zebra_l2info_vlan vlan_info;
netlink_extract_vlan_info (link_data, &vlan_info);
zebra_l2_vlanif_update (ifp, &vlan_info);
}
else if (IS_ZEBRA_IF_VXLAN(ifp))
{
struct zebra_l2info_vxlan vxlan_info;
netlink_extract_vxlan_info (link_data, &vxlan_info);
zebra_l2_vxlanif_add_update (ifp, &vxlan_info, add);
}
}
static int
netlink_bridge_interface (struct nlmsghdr *h, int len,
ns_id_t ns_id, int startup)
{
char *name = NULL;
struct ifinfomsg *ifi;
struct rtattr *tb[IFLA_MAX + 1];
struct interface *ifp;
struct rtattr *aftb[IFLA_BRIDGE_MAX + 1];
struct
{
u_int16_t flags;
u_int16_t vid;
} *vinfo;
vlanid_t access_vlan;
/* Fetch name and ifindex */
ifi = NLMSG_DATA (h);
memset (tb, 0, sizeof tb);
netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
if (tb[IFLA_IFNAME] == NULL)
return -1;
name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
/* The interface should already be known, if not discard. */
ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (ns_id),
ifi->ifi_index);
if (!ifp)
{
zlog_warn ("Cannot find bridge IF %s(%u)",
name, ifi->ifi_index);
return 0;
}
if (!IS_ZEBRA_IF_VXLAN(ifp))
return 0;
/* We are only interested in the access VLAN i.e., AF_SPEC */
if (!tb[IFLA_AF_SPEC])
return 0;
/* There is a 1-to-1 mapping of VLAN to VxLAN - hence
* only 1 access VLAN is accepted.
*/
memset (aftb, 0, sizeof aftb);
parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, tb[IFLA_AF_SPEC]);
if (!aftb[IFLA_BRIDGE_VLAN_INFO])
return 0;
vinfo = RTA_DATA(aftb[IFLA_BRIDGE_VLAN_INFO]);
if (!(vinfo->flags & BRIDGE_VLAN_INFO_PVID))
return 0;
access_vlan = (vlanid_t) vinfo->vid;
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("Access VLAN %u for VxLAN IF %s(%u)",
access_vlan, name, ifi->ifi_index);
zebra_l2_vxlanif_update_access_vlan (ifp, access_vlan);
return 0;
}
/* Called from interface_lookup_netlink(). This function is only used /* Called from interface_lookup_netlink(). This function is only used
during bootstrap. */ during bootstrap. */
static int static int
@ -355,9 +548,12 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h,
char *name = NULL; char *name = NULL;
char *kind = NULL; char *kind = NULL;
char *slave_kind = NULL; char *slave_kind = NULL;
int vrf_device = 0;
struct zebra_ns *zns; struct zebra_ns *zns;
vrf_id_t vrf_id = VRF_DEFAULT; vrf_id_t vrf_id = VRF_DEFAULT;
zebra_iftype_t zif_type = ZEBRA_IF_OTHER;
zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE;
ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
ifindex_t link_ifindex = IFINDEX_INTERNAL;
zns = zebra_ns_lookup (ns_id); zns = zebra_ns_lookup (ns_id);
ifi = NLMSG_DATA (h); ifi = NLMSG_DATA (h);
@ -369,11 +565,13 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h,
if (len < 0) if (len < 0)
return -1; return -1;
/* We are interested in some AF_BRIDGE notifications. */
if (ifi->ifi_family == AF_BRIDGE) if (ifi->ifi_family == AF_BRIDGE)
return 0; return netlink_bridge_interface (h, len, ns_id, startup);
/* Looking up interface name. */ /* Looking up interface name. */
memset (tb, 0, sizeof tb); memset (tb, 0, sizeof tb);
memset (linkinfo, 0, sizeof linkinfo);
netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len); netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
#ifdef IFLA_WIRELESS #ifdef IFLA_WIRELESS
@ -392,7 +590,6 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h,
if (tb[IFLA_LINKINFO]) if (tb[IFLA_LINKINFO])
{ {
memset (linkinfo, 0, sizeof linkinfo);
parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
if (linkinfo[IFLA_INFO_KIND]) if (linkinfo[IFLA_INFO_KIND])
@ -403,37 +600,64 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h,
slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]);
#endif #endif
if (kind && strcmp(kind, "vrf") == 0) netlink_determine_zebra_iftype (kind, &zif_type);
}
/* If VRF, create the VRF structure itself. */
if (zif_type == ZEBRA_IF_VRF)
{ {
vrf_device = 1;
netlink_vrf_change(h, tb[IFLA_LINKINFO], name); netlink_vrf_change(h, tb[IFLA_LINKINFO], name);
vrf_id = (vrf_id_t)ifi->ifi_index; vrf_id = (vrf_id_t)ifi->ifi_index;
} }
}
if (tb[IFLA_MASTER]) if (tb[IFLA_MASTER])
{ {
if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) if (slave_kind && (strcmp(slave_kind, "vrf") == 0))
{
zif_slave_type = ZEBRA_IF_SLAVE_VRF;
vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]);
} }
else if (slave_kind && (strcmp(slave_kind, "bridge") == 0))
{
zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE;
bridge_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
}
else
zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
}
/* If linking to another interface, note it. */
if (tb[IFLA_LINK])
link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]);
/* Add interface. */ /* Add interface. */
ifp = if_get_by_name (name, vrf_id); ifp = if_get_by_name (name, vrf_id);
set_ifindex(ifp, ifi->ifi_index, zns); set_ifindex(ifp, ifi->ifi_index, zns);
ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->flags = ifi->ifi_flags & 0x0000fffff;
if (vrf_device) if (IS_ZEBRA_IF_VRF(ifp))
SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]);
ifp->metric = 0; ifp->metric = 0;
ifp->speed = get_iflink_speed (name); ifp->speed = get_iflink_speed (name);
ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
/* Set zebra interface type */
zebra_if_set_ziftype (ifp, zif_type, zif_slave_type);
/* Update link. */
zebra_if_update_link (ifp, link_ifindex);
/* Hardware type and address. */ /* Hardware type and address. */
ifp->ll_type = netlink_to_zebra_link_type (ifi->ifi_type); ifp->ll_type = netlink_to_zebra_link_type (ifi->ifi_type);
netlink_interface_update_hw_addr (tb, ifp); netlink_interface_update_hw_addr (tb, ifp);
if_add_update (ifp); if_add_update (ifp);
/* Extract and save L2 interface information, take additional actions. */
netlink_interface_update_l2info (ifp, linkinfo[IFLA_INFO_DATA], 1);
if (IS_ZEBRA_IF_BRIDGE_SLAVE (ifp))
zebra_l2if_update_bridge_slave (ifp, bridge_ifindex);
return 0; return 0;
} }
@ -477,6 +701,24 @@ interface_lookup_netlink (struct zebra_ns *zns)
if (ret < 0) if (ret < 0)
return ret; return ret;
/* Get interface information - for bridge interfaces. */
ret = netlink_request_intf_addr (zns, AF_BRIDGE, RTM_GETLINK,
RTEXT_FILTER_BRVLAN);
if (ret < 0)
return ret;
ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0, 0);
if (ret < 0)
return ret;
/* Get interface information - for bridge interfaces. */
ret = netlink_request_intf_addr (zns, AF_BRIDGE, RTM_GETLINK,
RTEXT_FILTER_BRVLAN);
if (ret < 0)
return ret;
ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0, 0);
if (ret < 0)
return ret;
/* Get IPv4 address of the interfaces. */ /* Get IPv4 address of the interfaces. */
ret = netlink_request_intf_addr (zns, AF_INET, RTM_GETADDR, 0); ret = netlink_request_intf_addr (zns, AF_INET, RTM_GETADDR, 0);
if (ret < 0) if (ret < 0)
@ -712,9 +954,13 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
char *name = NULL; char *name = NULL;
char *kind = NULL; char *kind = NULL;
char *slave_kind = NULL; char *slave_kind = NULL;
int vrf_device = 0;
struct zebra_ns *zns; struct zebra_ns *zns;
vrf_id_t vrf_id = VRF_DEFAULT; vrf_id_t vrf_id = VRF_DEFAULT;
zebra_iftype_t zif_type = ZEBRA_IF_OTHER;
zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE;
ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
ifindex_t link_ifindex = IFINDEX_INTERNAL;
zns = zebra_ns_lookup (ns_id); zns = zebra_ns_lookup (ns_id);
ifi = NLMSG_DATA (h); ifi = NLMSG_DATA (h);
@ -731,11 +977,13 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
if (len < 0) if (len < 0)
return -1; return -1;
/* We are interested in some AF_BRIDGE notifications. */
if (ifi->ifi_family == AF_BRIDGE) if (ifi->ifi_family == AF_BRIDGE)
return 0; return netlink_bridge_interface (h, len, ns_id, startup);
/* Looking up interface name. */ /* Looking up interface name. */
memset (tb, 0, sizeof tb); memset (tb, 0, sizeof tb);
memset (linkinfo, 0, sizeof linkinfo);
netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len); netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
#ifdef IFLA_WIRELESS #ifdef IFLA_WIRELESS
@ -754,7 +1002,6 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
if (tb[IFLA_LINKINFO]) if (tb[IFLA_LINKINFO])
{ {
memset (linkinfo, 0, sizeof linkinfo);
parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
if (linkinfo[IFLA_INFO_KIND]) if (linkinfo[IFLA_INFO_KIND])
@ -765,13 +1012,19 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]);
#endif #endif
if (kind && strcmp(kind, "vrf") == 0) netlink_determine_zebra_iftype (kind, &zif_type);
}
/* If linking to another interface, note it. */
if (tb[IFLA_LINK])
link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]);
/* If VRF, create or update the VRF structure itself. */
if (zif_type == ZEBRA_IF_VRF)
{ {
vrf_device = 1;
netlink_vrf_change(h, tb[IFLA_LINKINFO], name); netlink_vrf_change(h, tb[IFLA_LINKINFO], name);
vrf_id = (vrf_id_t)ifi->ifi_index; vrf_id = (vrf_id_t)ifi->ifi_index;
} }
}
/* See if interface is present. */ /* See if interface is present. */
ifp = if_lookup_by_name_per_ns (zns, name); ifp = if_lookup_by_name_per_ns (zns, name);
@ -781,15 +1034,27 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
if (tb[IFLA_MASTER]) if (tb[IFLA_MASTER])
{ {
if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) if (slave_kind && (strcmp(slave_kind, "vrf") == 0))
{
zif_slave_type = ZEBRA_IF_SLAVE_VRF;
vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]);
} }
else if (slave_kind && (strcmp(slave_kind, "bridge") == 0))
{
zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE;
bridge_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
}
else
zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
}
if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
{ {
/* Add interface notification from kernel */ /* Add interface notification from kernel */
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("RTM_NEWLINK for %s(%u) (ifp %p) vrf_id %u flags 0x%x", zlog_debug ("RTM_NEWLINK ADD for %s(%u) vrf_id %u type %d "
name, ifi->ifi_index, ifp, vrf_id, ifi->ifi_flags); "sl_type %d master %u flags 0x%x",
name, ifi->ifi_index, vrf_id, zif_type, zif_slave_type,
bridge_ifindex, ifi->ifi_flags);
if (ifp == NULL) if (ifp == NULL)
{ {
@ -806,16 +1071,27 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
/* Update interface information. */ /* Update interface information. */
set_ifindex(ifp, ifi->ifi_index, zns); set_ifindex(ifp, ifi->ifi_index, zns);
ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->flags = ifi->ifi_flags & 0x0000fffff;
if (vrf_device) if (IS_ZEBRA_IF_VRF(ifp))
SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
ifp->metric = 0; ifp->metric = 0;
ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
/* Set interface type */
zebra_if_set_ziftype (ifp, zif_type, zif_slave_type);
/* Update link. */
zebra_if_update_link (ifp, link_ifindex);
netlink_interface_update_hw_addr (tb, ifp); netlink_interface_update_hw_addr (tb, ifp);
/* Inform clients, install any configured addresses. */ /* Inform clients, install any configured addresses. */
if_add_update (ifp); if_add_update (ifp);
/* Extract and save L2 interface information, take additional actions. */
netlink_interface_update_l2info (ifp, linkinfo[IFLA_INFO_DATA], 1);
if (IS_ZEBRA_IF_BRIDGE_SLAVE (ifp))
zebra_l2if_update_bridge_slave (ifp, bridge_ifindex);
} }
else if (ifp->vrf_id != vrf_id) else if (ifp->vrf_id != vrf_id)
{ {
@ -830,33 +1106,60 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
} }
else else
{ {
/* Interface status change. */ int was_bridge_slave;
/* Interface update. */
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("RTM_NEWLINK status for %s(%u) flags 0x%x", zlog_debug ("RTM_NEWLINK update for %s(%u) "
name, ifp->ifindex, ifi->ifi_flags); "sl_type %d master %u flags 0x%x",
name, ifp->ifindex, zif_slave_type,
bridge_ifindex, ifi->ifi_flags);
set_ifindex(ifp, ifi->ifi_index, zns); set_ifindex(ifp, ifi->ifi_index, zns);
ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
ifp->metric = 0; ifp->metric = 0;
/* Update interface type - NOTE: Only slave_type can change. */
was_bridge_slave = IS_ZEBRA_IF_BRIDGE_SLAVE (ifp);
zebra_if_set_ziftype (ifp, zif_type, zif_slave_type);
netlink_interface_update_hw_addr (tb, ifp); netlink_interface_update_hw_addr (tb, ifp);
if (if_is_no_ptm_operative (ifp)) if (if_is_no_ptm_operative (ifp))
{ {
ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->flags = ifi->ifi_flags & 0x0000fffff;
if (!if_is_no_ptm_operative (ifp)) if (!if_is_no_ptm_operative (ifp))
{
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("Intf %s(%u) has gone DOWN",
name, ifp->ifindex);
if_down (ifp); if_down (ifp);
}
else if (if_is_operative (ifp)) else if (if_is_operative (ifp))
{
/* Must notify client daemons of new interface status. */ /* Must notify client daemons of new interface status. */
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("Intf %s(%u) PTM up, notifying clients",
name, ifp->ifindex);
zebra_interface_up_update (ifp); zebra_interface_up_update (ifp);
} }
}
else else
{ {
ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->flags = ifi->ifi_flags & 0x0000fffff;
if (if_is_operative (ifp)) if (if_is_operative (ifp))
{
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("Intf %s(%u) has come UP", name, ifp->ifindex);
if_up (ifp); if_up (ifp);
} }
} }
/* Extract and save L2 interface information, take additional actions. */
netlink_interface_update_l2info (ifp, linkinfo[IFLA_INFO_DATA], 0);
if (IS_ZEBRA_IF_BRIDGE_SLAVE (ifp) || was_bridge_slave)
zebra_l2if_update_bridge_slave (ifp, bridge_ifindex);
}
} }
else else
{ {
@ -873,7 +1176,13 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
if (!vrf_device) /* Special handling for bridge or VxLAN interfaces. */
if (IS_ZEBRA_IF_BRIDGE (ifp))
zebra_l2_bridge_del (ifp);
else if (IS_ZEBRA_IF_VXLAN (ifp))
zebra_l2_vxlanif_del (ifp);
if (!IS_ZEBRA_IF_VRF(ifp))
if_delete_update (ifp); if_delete_update (ifp);
} }

View File

@ -47,6 +47,7 @@
#include "zebra/zebra_ptm.h" #include "zebra/zebra_ptm.h"
#include "zebra/rt_netlink.h" #include "zebra/rt_netlink.h"
#include "zebra/interface.h" #include "zebra/interface.h"
#include "zebra/zebra_vxlan.h"
#define ZEBRA_PTM_SUPPORT #define ZEBRA_PTM_SUPPORT
@ -680,6 +681,8 @@ if_delete_connected (struct interface *ifp)
void void
if_delete_update (struct interface *ifp) if_delete_update (struct interface *ifp)
{ {
struct zebra_if *zif;
if (if_is_up(ifp)) if (if_is_up(ifp))
{ {
zlog_err ("interface %s vrf %u index %d is still up while being deleted.", zlog_err ("interface %s vrf %u index %d is still up while being deleted.",
@ -713,6 +716,16 @@ if_delete_update (struct interface *ifp)
/* if the ifp is in a vrf, move it to default so vrf can be deleted if desired */ /* if the ifp is in a vrf, move it to default so vrf can be deleted if desired */
if (ifp->vrf_id) if (ifp->vrf_id)
if_handle_vrf_change (ifp, VRF_DEFAULT); if_handle_vrf_change (ifp, VRF_DEFAULT);
/* Reset some zebra interface params to default values. */
zif = ifp->info;
if (zif)
{
zif->zif_type = ZEBRA_IF_OTHER;
zif->zif_slave_type = ZEBRA_IF_SLAVE_NONE;
memset (&zif->l2info, 0, sizeof (union zebra_l2if_info));
memset (&zif->brslave_info, 0, sizeof (struct zebra_l2info_brslave));
}
} }
/* VRF change for an interface */ /* VRF change for an interface */
@ -834,6 +847,7 @@ void
if_up (struct interface *ifp) if_up (struct interface *ifp)
{ {
struct zebra_if *zif; struct zebra_if *zif;
struct interface *link_if;
zif = ifp->info; zif = ifp->info;
zif->up_count++; zif->up_count++;
@ -868,6 +882,24 @@ if_up (struct interface *ifp)
rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
zebra_vrf_static_route_interface_fixup (ifp); zebra_vrf_static_route_interface_fixup (ifp);
/* Handle interface up for specific types for EVPN. Non-VxLAN interfaces
* are checked to see if (remote) neighbor entries need to be installed
* on them for ARP suppression.
*/
if (IS_ZEBRA_IF_VXLAN (ifp))
zebra_vxlan_if_up (ifp);
else if (IS_ZEBRA_IF_BRIDGE (ifp))
{
link_if = ifp;
zebra_vxlan_svi_up (ifp, link_if);
}
else if (IS_ZEBRA_IF_VLAN (ifp))
{
link_if = zif->link;
if (link_if)
zebra_vxlan_svi_up (ifp, link_if);
}
} }
/* Interface goes down. We have to manage different behavior of based /* Interface goes down. We have to manage different behavior of based
@ -876,11 +908,31 @@ void
if_down (struct interface *ifp) if_down (struct interface *ifp)
{ {
struct zebra_if *zif; struct zebra_if *zif;
struct interface *link_if;
zif = ifp->info; zif = ifp->info;
zif->down_count++; zif->down_count++;
quagga_timestamp (2, zif->down_last, sizeof (zif->down_last)); quagga_timestamp (2, zif->down_last, sizeof (zif->down_last));
/* Handle interface down for specific types for EVPN. Non-VxLAN interfaces
* are checked to see if (remote) neighbor entries need to be purged
* for ARP suppression.
*/
if (IS_ZEBRA_IF_VXLAN (ifp))
zebra_vxlan_if_down (ifp);
else if (IS_ZEBRA_IF_BRIDGE (ifp))
{
link_if = ifp;
zebra_vxlan_svi_down (ifp, link_if);
}
else if (IS_ZEBRA_IF_VLAN (ifp))
{
link_if = zif->link;
if (link_if)
zebra_vxlan_svi_down (ifp, link_if);
}
/* Notify to the protocol daemons. */ /* Notify to the protocol daemons. */
zebra_interface_down_update (ifp); zebra_interface_down_update (ifp);
@ -904,6 +956,17 @@ if_refresh (struct interface *ifp)
if_get_flags (ifp); if_get_flags (ifp);
} }
void
zebra_if_update_link (struct interface *ifp, ifindex_t link_ifindex)
{
struct zebra_if *zif;
zif = (struct zebra_if *)ifp->info;
zif->link_ifindex = link_ifindex;
zif->link = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT),
link_ifindex);
}
/* Output prefix string to vty. */ /* Output prefix string to vty. */
static int static int
@ -1020,6 +1083,37 @@ nd_dump_vty (struct vty *vty, struct interface *ifp)
} }
#endif /* HAVE_RTADV */ #endif /* HAVE_RTADV */
static const char *
zebra_ziftype_2str (zebra_iftype_t zif_type)
{
switch (zif_type)
{
case ZEBRA_IF_OTHER:
return "Other";
break;
case ZEBRA_IF_BRIDGE:
return "Bridge";
break;
case ZEBRA_IF_VLAN:
return "Vlan";
break;
case ZEBRA_IF_VXLAN:
return "Vxlan";
break;
case ZEBRA_IF_VRF:
return "VRF";
break;
default:
return "Unknown";
break;
}
}
/* Interface's information print out to vty interface. */ /* Interface's information print out to vty interface. */
static void static void
if_dump_vty (struct vty *vty, struct interface *ifp) if_dump_vty (struct vty *vty, struct interface *ifp)
@ -1115,6 +1209,51 @@ if_dump_vty (struct vty *vty, struct interface *ifp)
connected_dump_vty (vty, connected); connected_dump_vty (vty, connected);
} }
vty_out(vty, " Interface Type %s\n",
zebra_ziftype_2str (zebra_if->zif_type));
if (IS_ZEBRA_IF_BRIDGE (ifp))
{
struct zebra_l2info_bridge *bridge_info;
bridge_info = &zebra_if->l2info.br;
vty_out(vty, " Bridge VLAN-aware: %s\n",
bridge_info->vlan_aware ? "yes" : "no");
}
else if (IS_ZEBRA_IF_VLAN(ifp))
{
struct zebra_l2info_vlan *vlan_info;
vlan_info = &zebra_if->l2info.vl;
vty_out(vty, " VLAN Id %u\n",
vlan_info->vid);
}
else if (IS_ZEBRA_IF_VXLAN (ifp))
{
struct zebra_l2info_vxlan *vxlan_info;
vxlan_info = &zebra_if->l2info.vxl;
vty_out(vty, " VxLAN Id %u", vxlan_info->vni);
if (vxlan_info->vtep_ip.s_addr != INADDR_ANY)
vty_out(vty, " VTEP IP: %s", inet_ntoa (vxlan_info->vtep_ip));
if (vxlan_info->access_vlan)
vty_out(vty, " Access VLAN Id %u", vxlan_info->access_vlan);
vty_out(vty, "\n");
}
if (IS_ZEBRA_IF_BRIDGE_SLAVE (ifp))
{
struct zebra_l2info_brslave *br_slave;
br_slave = &zebra_if->brslave_info;
if (br_slave->bridge_ifindex != IFINDEX_INTERNAL)
vty_out(vty, " Master (bridge) ifindex %u\n",
br_slave->bridge_ifindex);
}
if (zebra_if->link_ifindex != IFINDEX_INTERNAL)
vty_out(vty, " Link ifindex %u\n",
zebra_if->link_ifindex);
if (HAS_LINK_PARAMS(ifp)) if (HAS_LINK_PARAMS(ifp))
{ {
int i; int i;

View File

@ -28,6 +28,8 @@
#include "zebra/irdp.h" #include "zebra/irdp.h"
#endif #endif
#include "zebra/zebra_l2.h"
/* For interface multicast configuration. */ /* For interface multicast configuration. */
#define IF_ZEBRA_MULTICAST_UNSPEC 0 #define IF_ZEBRA_MULTICAST_UNSPEC 0
#define IF_ZEBRA_MULTICAST_ON 1 #define IF_ZEBRA_MULTICAST_ON 1
@ -180,6 +182,25 @@ struct rtadvconf
#endif /* HAVE_RTADV */ #endif /* HAVE_RTADV */
/* Zebra interface type - ones of interest. */
typedef enum
{
ZEBRA_IF_VXLAN, /* VxLAN interface */
ZEBRA_IF_VRF, /* VRF device */
ZEBRA_IF_BRIDGE, /* bridge device */
ZEBRA_IF_VLAN, /* VLAN sub-interface */
ZEBRA_IF_OTHER, /* Anything else */
} zebra_iftype_t;
/* Zebra "slave" interface type */
typedef enum
{
ZEBRA_IF_SLAVE_NONE, /* Not a slave */
ZEBRA_IF_SLAVE_VRF, /* Member of a VRF */
ZEBRA_IF_SLAVE_BRIDGE, /* Member of a bridge */
ZEBRA_IF_SLAVE_OTHER, /* Something else - e.g., bond slave */
} zebra_slave_iftype_t;
/* `zebra' daemon local interface structure. */ /* `zebra' daemon local interface structure. */
struct zebra_if struct zebra_if
{ {
@ -231,8 +252,53 @@ struct zebra_if
/* ptm enable configuration */ /* ptm enable configuration */
u_char ptm_enable; u_char ptm_enable;
/* Zebra interface and "slave" interface type */
zebra_iftype_t zif_type;
zebra_slave_iftype_t zif_slave_type;
/* Additional L2 info, depends on zif_type */
union zebra_l2if_info l2info;
/* For members of a bridge, link to bridge. */
/* Note: If additional fields become necessary, this can be modified to
* be a pointer to a dynamically allocd struct.
*/
struct zebra_l2info_brslave brslave_info;
/* Link fields - for sub-interfaces. */
ifindex_t link_ifindex;
struct interface *link;
}; };
static inline void
zebra_if_set_ziftype (struct interface *ifp, zebra_iftype_t zif_type,
zebra_slave_iftype_t zif_slave_type)
{
struct zebra_if *zif;
zif = (struct zebra_if *)ifp->info;
zif->zif_type = zif_type;
zif->zif_slave_type = zif_slave_type;
}
#define IS_ZEBRA_IF_VRF(ifp) \
(((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VRF)
#define IS_ZEBRA_IF_BRIDGE(ifp) \
(((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_BRIDGE)
#define IS_ZEBRA_IF_VLAN(ifp) \
(((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VLAN)
#define IS_ZEBRA_IF_VXLAN(ifp) \
(((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VXLAN)
#define IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) \
(((struct zebra_if *)(ifp->info))->zif_slave_type == ZEBRA_IF_SLAVE_BRIDGE)
#define IS_ZEBRA_IF_VRF_SLAVE(ifp) \
(((struct zebra_if *)(ifp->info))->zif_slave_type == ZEBRA_IF_SLAVE_VRF)
extern struct interface *if_lookup_by_index_per_ns (struct zebra_ns *, u_int32_t); extern struct interface *if_lookup_by_index_per_ns (struct zebra_ns *, u_int32_t);
extern struct interface *if_lookup_by_name_per_ns (struct zebra_ns *, const char *); extern struct interface *if_lookup_by_name_per_ns (struct zebra_ns *, const char *);
@ -253,6 +319,7 @@ extern int if_subnet_add (struct interface *, struct connected *);
extern int if_subnet_delete (struct interface *, struct connected *); extern int if_subnet_delete (struct interface *, struct connected *);
extern int ipv6_address_configured (struct interface *ifp); extern int ipv6_address_configured (struct interface *ifp);
extern void if_handle_vrf_change (struct interface *ifp, vrf_id_t vrf_id); extern void if_handle_vrf_change (struct interface *ifp, vrf_id_t vrf_id);
extern void zebra_if_update_link (struct interface *ifp, ifindex_t link_ifindex);
extern void vrf_add_update (struct vrf *vrfp); extern void vrf_add_update (struct vrf *vrfp);

View File

@ -269,6 +269,12 @@ netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h,
case RTM_DELADDR: case RTM_DELADDR:
return netlink_interface_addr (snl, h, ns_id, startup); return netlink_interface_addr (snl, h, ns_id, startup);
break; break;
case RTM_NEWNEIGH:
return netlink_neigh_change (snl, h, ns_id);
break;
case RTM_DELNEIGH:
return netlink_neigh_change (snl, h, ns_id);
break;
default: default:
zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type, zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type,
ns_id); ns_id);
@ -297,17 +303,21 @@ static void netlink_install_filter (int sock, __u32 pid)
struct sock_filter filter[] = { struct sock_filter filter[] = {
/* 0: ldh [4] */ /* 0: ldh [4] */
BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)), BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)),
/* 1: jeq 0x18 jt 3 jf 6 */ /* 1: jeq 0x18 jt 5 jf next */
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 1, 0), BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 3, 0),
/* 2: jeq 0x19 jt 3 jf 6 */ /* 2: jeq 0x19 jt 5 jf next */
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 0, 3), BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 2, 0),
/* 3: ldw [12] */ /* 3: jeq 0x19 jt 5 jf next */
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWNEIGH), 1, 0),
/* 4: jeq 0x19 jt 5 jf 8 */
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELNEIGH), 0, 3),
/* 5: ldw [12] */
BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)), BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)),
/* 4: jeq XX jt 5 jf 6 */ /* 6: jeq XX jt 7 jf 8 */
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1), BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1),
/* 5: ret 0 (skip) */ /* 7: ret 0 (skip) */
BPF_STMT(BPF_RET|BPF_K, 0), BPF_STMT(BPF_RET|BPF_K, 0),
/* 6: ret 0xffff (keep) */ /* 8: ret 0xffff (keep) */
BPF_STMT(BPF_RET|BPF_K, 0xffff), BPF_STMT(BPF_RET|BPF_K, 0xffff),
}; };
@ -786,7 +796,7 @@ kernel_init (struct zebra_ns *zns)
/* Initialize netlink sockets */ /* Initialize netlink sockets */
groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR | groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR |
RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR |
RTMGRP_IPV4_MROUTE; RTMGRP_IPV4_MROUTE | RTMGRP_NEIGH;
snprintf (zns->netlink.name, sizeof (zns->netlink.name), snprintf (zns->netlink.name, sizeof (zns->netlink.name),
"netlink-listen (NS %u)", zns->ns_id); "netlink-listen (NS %u)", zns->ns_id);

View File

@ -24,6 +24,8 @@
#include "prefix.h" #include "prefix.h"
#include "if.h" #include "if.h"
#include "vlan.h"
#include "vxlan.h"
#include "zebra/rib.h" #include "zebra/rib.h"
#include "zebra/zebra_ns.h" #include "zebra/zebra_ns.h"
#include "zebra/zebra_mpls.h" #include "zebra/zebra_mpls.h"
@ -41,4 +43,18 @@ extern int kernel_del_lsp (zebra_lsp_t *);
extern int mpls_kernel_init (void); extern int mpls_kernel_init (void);
extern int kernel_get_ipmr_sg_stats (void *mroute); extern int kernel_get_ipmr_sg_stats (void *mroute);
extern int kernel_add_vtep (vni_t vni, struct interface *ifp,
struct in_addr *vtep_ip);
extern int kernel_del_vtep (vni_t vni, struct interface *ifp,
struct in_addr *vtep_ip);
extern int kernel_add_mac (struct interface *ifp, vlanid_t vid,
struct ethaddr *mac, struct in_addr vtep_ip,
u_char sticky);
extern int kernel_del_mac (struct interface *ifp, vlanid_t vid,
struct ethaddr *mac, struct in_addr vtep_ip, int local);
extern int kernel_add_neigh (struct interface *ifp, struct ipaddr *ip,
struct ethaddr *mac);
extern int kernel_del_neigh (struct interface *ifp, struct ipaddr *ip);
#endif /* _ZEBRA_RT_H */ #endif /* _ZEBRA_RT_H */

View File

@ -41,6 +41,7 @@
#include "vrf.h" #include "vrf.h"
#include "vty.h" #include "vty.h"
#include "mpls.h" #include "mpls.h"
#include "vxlan.h"
#include "zebra/zserv.h" #include "zebra/zserv.h"
#include "zebra/zebra_ns.h" #include "zebra/zebra_ns.h"
@ -55,6 +56,7 @@
#include "zebra/kernel_netlink.h" #include "zebra/kernel_netlink.h"
#include "zebra/rt_netlink.h" #include "zebra/rt_netlink.h"
#include "zebra/zebra_mroute.h" #include "zebra/zebra_mroute.h"
#include "zebra/zebra_vxlan.h"
/* TODO - Temporary definitions, need to refine. */ /* TODO - Temporary definitions, need to refine. */
@ -93,8 +95,30 @@
#ifndef NDA_MASTER #ifndef NDA_MASTER
#define NDA_MASTER 9 #define NDA_MASTER 9
#endif #endif
#ifndef NTF_MASTER
#define NTF_MASTER 0x04
#endif
#ifndef NTF_SELF
#define NTF_SELF 0x02
#endif
#ifndef NTF_EXT_LEARNED
#define NTF_EXT_LEARNED 0x10
#endif
#ifndef NDA_IFINDEX
#define NDA_IFINDEX 8
#endif
#ifndef NDA_VLAN
#define NDA_VLAN 5
#endif
/* End of temporary definitions */ /* End of temporary definitions */
static vlanid_t filter_vlan = 0;
struct gw_family_t struct gw_family_t
{ {
u_int16_t filler; u_int16_t filler;
@ -1554,6 +1578,712 @@ kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen)
lla, llalen); lla, llalen);
} }
/*
* Add remote VTEP to the flood list for this VxLAN interface (VNI). This
* is done by adding an FDB entry with a MAC of 00:00:00:00:00:00.
*/
static int
netlink_vxlan_flood_list_update (struct interface *ifp,
struct in_addr *vtep_ip,
int cmd)
{
struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
struct
{
struct nlmsghdr n;
struct ndmsg ndm;
char buf[256];
} req;
u_char dst_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
memset(&req.n, 0, sizeof(req.n));
memset(&req.ndm, 0, sizeof(req.ndm));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
req.n.nlmsg_flags = NLM_F_REQUEST;
if (cmd == RTM_NEWNEIGH)
req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_APPEND);
req.n.nlmsg_type = cmd;
req.ndm.ndm_family = PF_BRIDGE;
req.ndm.ndm_state = NUD_NOARP | NUD_PERMANENT;
req.ndm.ndm_flags |= NTF_SELF; // Handle by "self", not "master"
addattr_l (&req.n, sizeof (req), NDA_LLADDR, &dst_mac, 6);
req.ndm.ndm_ifindex = ifp->ifindex;
addattr_l (&req.n, sizeof (req), NDA_DST, &vtep_ip->s_addr, 4);
return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
}
/*
* Add remote VTEP for this VxLAN interface (VNI). In Linux, this involves adding
* a "flood" MAC FDB entry.
*/
int
kernel_add_vtep (vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
{
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug ("Install %s into flood list for VNI %u intf %s(%u)",
inet_ntoa (*vtep_ip), vni, ifp->name, ifp->ifindex);
return netlink_vxlan_flood_list_update (ifp, vtep_ip, RTM_NEWNEIGH);
}
/*
* Remove remote VTEP for this VxLAN interface (VNI). In Linux, this involves
* deleting the "flood" MAC FDB entry.
*/
int
kernel_del_vtep (vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
{
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug ("Uninstall %s from flood list for VNI %u intf %s(%u)",
inet_ntoa (*vtep_ip), vni, ifp->name, ifp->ifindex);
return netlink_vxlan_flood_list_update (ifp, vtep_ip, RTM_DELNEIGH);
}
#ifndef NDA_RTA
#define NDA_RTA(r) \
((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
#endif
static int
netlink_macfdb_change (struct sockaddr_nl *snl, struct nlmsghdr *h, int len)
{
struct ndmsg *ndm;
struct interface *ifp;
struct zebra_if *zif;
struct zebra_vrf *zvrf;
struct rtattr *tb[NDA_MAX + 1];
struct interface *br_if;
struct ethaddr mac;
vlanid_t vid = 0;
struct prefix vtep_ip;
int vid_present = 0, dst_present = 0;
char buf[ETHER_ADDR_STRLEN];
char vid_buf[20];
char dst_buf[30];
u_char sticky = 0;
ndm = NLMSG_DATA (h);
/* The interface should exist. */
ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), ndm->ndm_ifindex);
if (!ifp)
return 0;
/* Locate VRF corresponding to interface. We only process MAC notifications
* if EVPN is enabled on this VRF.
*/
zvrf = vrf_info_lookup(ifp->vrf_id);
if (!zvrf || !EVPN_ENABLED(zvrf))
return 0;
if (!ifp->info)
return 0;
/* The interface should be something we're interested in. */
if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
return 0;
/* Drop "permanent" entries. */
if (ndm->ndm_state & NUD_PERMANENT)
return 0;
zif = (struct zebra_if *)ifp->info;
if ((br_if = zif->brslave_info.br_if) == NULL)
{
zlog_warn ("%s family %s IF %s(%u) brIF %u - no bridge master",
nl_msg_type_to_str (h->nlmsg_type),
nl_family_to_str (ndm->ndm_family),
ifp->name, ndm->ndm_ifindex,
zif->brslave_info.bridge_ifindex);
return 0;
}
/* Parse attributes and extract fields of interest. */
memset (tb, 0, sizeof tb);
netlink_parse_rtattr (tb, NDA_MAX, NDA_RTA (ndm), len);
if (!tb[NDA_LLADDR])
{
zlog_warn ("%s family %s IF %s(%u) brIF %u - no LLADDR",
nl_msg_type_to_str (h->nlmsg_type),
nl_family_to_str (ndm->ndm_family),
ifp->name, ndm->ndm_ifindex,
zif->brslave_info.bridge_ifindex);
return 0;
}
if (RTA_PAYLOAD (tb[NDA_LLADDR]) != ETHER_ADDR_LEN)
{
zlog_warn ("%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %ld",
nl_msg_type_to_str (h->nlmsg_type),
nl_family_to_str (ndm->ndm_family),
ifp->name, ndm->ndm_ifindex,
zif->brslave_info.bridge_ifindex,
RTA_PAYLOAD (tb[NDA_LLADDR]));
return 0;
}
memcpy (&mac, RTA_DATA (tb[NDA_LLADDR]), ETHER_ADDR_LEN);
if ((NDA_VLAN <= NDA_MAX) && tb[NDA_VLAN])
{
vid_present = 1;
vid = *(u_int16_t *) RTA_DATA(tb[NDA_VLAN]);
sprintf (vid_buf, " VLAN %u", vid);
}
if (tb[NDA_DST])
{
/* TODO: Only IPv4 supported now. */
dst_present = 1;
vtep_ip.family = AF_INET;
vtep_ip.prefixlen = IPV4_MAX_BITLEN;
memcpy (&(vtep_ip.u.prefix4.s_addr), RTA_DATA (tb[NDA_DST]), IPV4_MAX_BYTELEN);
sprintf (dst_buf, " dst %s", inet_ntoa (vtep_ip.u.prefix4));
}
sticky = (ndm->ndm_state & NUD_NOARP) ? 1 : 0;
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("Rx %s family %s IF %s(%u)%s %sMAC %s%s",
nl_msg_type_to_str (h->nlmsg_type),
nl_family_to_str (ndm->ndm_family),
ifp->name, ndm->ndm_ifindex,
vid_present ? vid_buf : "",
sticky ? "sticky " : "",
prefix_mac2str (&mac, buf, sizeof (buf)),
dst_present ? dst_buf: "");
if (filter_vlan && vid != filter_vlan)
return 0;
/* If add or update, do accordingly if learnt on a "local" interface; if
* the notification is over VxLAN, this has to be related to multi-homing,
* so perform an implicit delete of any local entry (if it exists).
*/
if (h->nlmsg_type == RTM_NEWNEIGH)
{
/* Drop "permanent" entries. */
if (ndm->ndm_state & NUD_PERMANENT)
return 0;
if (IS_ZEBRA_IF_VXLAN(ifp))
return zebra_vxlan_check_del_local_mac (ifp, br_if, &mac, vid);
return zebra_vxlan_local_mac_add_update (ifp, br_if, &mac, vid, sticky);
}
/* This is a delete notification.
* 1. For a MAC over VxLan, check if it needs to be refreshed(readded)
* 2. For a MAC over "local" interface, delete the mac
* Note: We will get notifications from both bridge driver and VxLAN driver.
* Ignore the notification from VxLan driver as it is also generated
* when mac moves from remote to local.
*/
if (dst_present)
return 0;
if (IS_ZEBRA_IF_VXLAN(ifp))
return zebra_vxlan_check_readd_remote_mac (ifp, br_if, &mac, vid);
return zebra_vxlan_local_mac_del (ifp, br_if, &mac, vid);
}
static int
netlink_macfdb_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
ns_id_t ns_id, int startup)
{
int len;
struct ndmsg *ndm;
if (h->nlmsg_type != RTM_NEWNEIGH)
return 0;
/* Length validity. */
len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ndmsg));
if (len < 0)
return -1;
/* We are interested only in AF_BRIDGE notifications. */
ndm = NLMSG_DATA (h);
if (ndm->ndm_family != AF_BRIDGE)
return 0;
return netlink_macfdb_change (snl, h, len);
}
/* Request for MAC FDB information from the kernel */
static int
netlink_request_macs (struct zebra_ns *zns, int family, int type,
ifindex_t master_ifindex)
{
struct
{
struct nlmsghdr n;
struct ifinfomsg ifm;
char buf[256];
} req;
/* Form the request, specifying filter (rtattr) if needed. */
memset (&req, 0, sizeof (req));
req.n.nlmsg_type = type;
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
req.ifm.ifi_family = family;
if (master_ifindex)
addattr32 (&req.n, sizeof(req), IFLA_MASTER, master_ifindex);
return netlink_request (&zns->netlink_cmd, &req.n);
}
/*
* MAC forwarding database read using netlink interface. This is invoked
* at startup.
*/
int
netlink_macfdb_read (struct zebra_ns *zns)
{
int ret;
/* Get bridge FDB table. */
ret = netlink_request_macs (zns, AF_BRIDGE, RTM_GETNEIGH, 0);
if (ret < 0)
return ret;
/* We are reading entire table. */
filter_vlan = 0;
ret = netlink_parse_info (netlink_macfdb_table, &zns->netlink_cmd, zns, 0, 1);
return ret;
}
/*
* MAC forwarding database read using netlink interface. This is for a
* specific bridge and matching specific access VLAN (if VLAN-aware bridge).
*/
int
netlink_macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp,
struct interface *br_if)
{
struct zebra_if *br_zif;
struct zebra_if *zif;
struct zebra_l2info_vxlan *vxl;
int ret = 0;
/* Save VLAN we're filtering on, if needed. */
br_zif = (struct zebra_if *) br_if->info;
zif = (struct zebra_if *) ifp->info;
vxl = &zif->l2info.vxl;
if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
filter_vlan = vxl->access_vlan;
/* Get bridge FDB table for specific bridge - we do the VLAN filtering. */
ret = netlink_request_macs (zns, AF_BRIDGE, RTM_GETNEIGH, br_if->ifindex);
if (ret < 0)
return ret;
ret = netlink_parse_info (netlink_macfdb_table, &zns->netlink_cmd, zns, 0, 0);
/* Reset VLAN filter. */
filter_vlan = 0;
return ret;
}
static int
netlink_macfdb_update (struct interface *ifp, vlanid_t vid,
struct ethaddr *mac,
struct in_addr vtep_ip,
int local, int cmd,
u_char sticky)
{
struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
struct
{
struct nlmsghdr n;
struct ndmsg ndm;
char buf[256];
} req;
int dst_alen;
struct zebra_if *zif;
struct interface *br_if;
struct zebra_if *br_zif;
char buf[ETHER_ADDR_STRLEN];
int vid_present = 0, dst_present = 0;
char vid_buf[20];
char dst_buf[30];
zif = ifp->info;
if ((br_if = zif->brslave_info.br_if) == NULL)
{
zlog_warn ("MAC %s on IF %s(%u) - no mapping to bridge",
(cmd == RTM_NEWNEIGH) ? "add" : "del",
ifp->name, ifp->ifindex);
return -1;
}
memset(&req.n, 0, sizeof(req.n));
memset(&req.ndm, 0, sizeof(req.ndm));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
req.n.nlmsg_flags = NLM_F_REQUEST;
if (cmd == RTM_NEWNEIGH)
req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
req.n.nlmsg_type = cmd;
req.ndm.ndm_family = AF_BRIDGE;
req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
req.ndm.ndm_state = NUD_REACHABLE;
if (sticky)
req.ndm.ndm_state |= NUD_NOARP;
else
req.ndm.ndm_flags |= NTF_EXT_LEARNED;
addattr_l (&req.n, sizeof (req), NDA_LLADDR, mac, 6);
req.ndm.ndm_ifindex = ifp->ifindex;
if (!local)
{
dst_alen = 4; // TODO: hardcoded
addattr_l (&req.n, sizeof (req), NDA_DST, &vtep_ip, dst_alen);
dst_present = 1;
sprintf (dst_buf, " dst %s", inet_ntoa (vtep_ip));
}
br_zif = (struct zebra_if *) br_if->info;
if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0)
{
addattr16 (&req.n, sizeof (req), NDA_VLAN, vid);
vid_present = 1;
sprintf (vid_buf, " VLAN %u", vid);
}
addattr32 (&req.n, sizeof (req), NDA_MASTER, br_if->ifindex);
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("Tx %s family %s IF %s(%u)%s %sMAC %s%s",
nl_msg_type_to_str (cmd),
nl_family_to_str (req.ndm.ndm_family),
ifp->name, ifp->ifindex,
vid_present ? vid_buf : "",
sticky ? "sticky " : "",
prefix_mac2str (mac, buf, sizeof (buf)),
dst_present ? dst_buf : "");
return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
}
#define NUD_VALID (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | \
NUD_PROBE | NUD_STALE | NUD_DELAY)
static int
netlink_ipneigh_change (struct sockaddr_nl *snl, struct nlmsghdr *h, int len)
{
struct ndmsg *ndm;
struct interface *ifp;
struct zebra_if *zif;
struct zebra_vrf *zvrf;
struct rtattr *tb[NDA_MAX + 1];
struct interface *link_if;
struct ethaddr mac;
struct ipaddr ip;
char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
int mac_present = 0;
u_char ext_learned;
ndm = NLMSG_DATA (h);
/* The interface should exist. */
ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), ndm->ndm_ifindex);
if (!ifp)
return 0;
/* Locate VRF corresponding to interface. We only process neigh notifications
* if EVPN is enabled on this VRF.
*/
zvrf = vrf_info_lookup(ifp->vrf_id);
if (!zvrf || !EVPN_ENABLED(zvrf))
return 0;
if (!ifp->info)
return 0;
/* Drop "permanent" entries. */
if (ndm->ndm_state & NUD_PERMANENT)
return 0;
zif = (struct zebra_if *)ifp->info;
/* The neighbor is present on an SVI. From this, we locate the underlying
* bridge because we're only interested in neighbors on a VxLAN bridge.
* The bridge is located based on the nature of the SVI:
* (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
* and is linked to the bridge
* (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
* itself
*/
if (IS_ZEBRA_IF_VLAN(ifp))
{
link_if = zif->link;
if (!link_if)
return 0;
}
else if (IS_ZEBRA_IF_BRIDGE(ifp))
link_if = ifp;
else
return 0;
/* Parse attributes and extract fields of interest. */
memset (tb, 0, sizeof tb);
netlink_parse_rtattr (tb, NDA_MAX, NDA_RTA (ndm), len);
if (!tb[NDA_DST])
{
zlog_warn ("%s family %s IF %s(%u) - no DST",
nl_msg_type_to_str (h->nlmsg_type),
nl_family_to_str (ndm->ndm_family),
ifp->name, ndm->ndm_ifindex);
return 0;
}
memset (&mac, 0, sizeof (struct ethaddr));
memset (&ip, 0, sizeof (struct ipaddr));
ip.ipa_type = (ndm->ndm_family == AF_INET) ? IPADDR_V4 : IPADDR_V6;
memcpy (&ip.ip.addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
if (h->nlmsg_type == RTM_NEWNEIGH)
{
if (tb[NDA_LLADDR])
{
if (RTA_PAYLOAD (tb[NDA_LLADDR]) != ETHER_ADDR_LEN)
{
zlog_warn ("%s family %s IF %s(%u) - LLADDR is not MAC, len %ld",
nl_msg_type_to_str (h->nlmsg_type),
nl_family_to_str (ndm->ndm_family),
ifp->name, ndm->ndm_ifindex,
RTA_PAYLOAD (tb[NDA_LLADDR]));
return 0;
}
mac_present = 1;
memcpy (&mac, RTA_DATA (tb[NDA_LLADDR]), ETHER_ADDR_LEN);
}
ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0;
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("Rx %s family %s IF %s(%u) IP %s MAC %s state 0x%x flags 0x%x",
nl_msg_type_to_str (h->nlmsg_type),
nl_family_to_str (ndm->ndm_family),
ifp->name, ndm->ndm_ifindex,
ipaddr2str (&ip, buf2, sizeof(buf2)),
mac_present ? prefix_mac2str (&mac, buf, sizeof (buf)) : "",
ndm->ndm_state, ndm->ndm_flags);
/* If the neighbor state is valid for use, process as an add or update
* else process as a delete. Note that the delete handling may result
* in re-adding the neighbor if it is a valid "remote" neighbor.
*/
if (ndm->ndm_state & NUD_VALID)
return zebra_vxlan_local_neigh_add_update (ifp, link_if,
&ip, &mac,
ndm->ndm_state, ext_learned);
return zebra_vxlan_local_neigh_del (ifp, link_if, &ip);
}
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("Rx %s family %s IF %s(%u) IP %s",
nl_msg_type_to_str (h->nlmsg_type),
nl_family_to_str (ndm->ndm_family),
ifp->name, ndm->ndm_ifindex,
ipaddr2str (&ip, buf2, sizeof(buf2)));
/* Process the delete - it may result in re-adding the neighbor if it is
* a valid "remote" neighbor.
*/
return zebra_vxlan_local_neigh_del (ifp, link_if, &ip);
}
static int
netlink_neigh_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
ns_id_t ns_id, int startup)
{
int len;
struct ndmsg *ndm;
if (h->nlmsg_type != RTM_NEWNEIGH)
return 0;
/* Length validity. */
len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ndmsg));
if (len < 0)
return -1;
/* We are interested only in AF_INET or AF_INET6 notifications. */
ndm = NLMSG_DATA (h);
if (ndm->ndm_family != AF_INET && ndm->ndm_family != AF_INET6)
return 0;
return netlink_neigh_change (snl, h, len);
}
/* Request for IP neighbor information from the kernel */
static int
netlink_request_neigh (struct zebra_ns *zns, int family, int type,
ifindex_t ifindex)
{
struct
{
struct nlmsghdr n;
struct ndmsg ndm;
char buf[256];
} req;
/* Form the request, specifying filter (rtattr) if needed. */
memset (&req, 0, sizeof (req));
req.n.nlmsg_type = type;
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
req.ndm.ndm_family = family;
if (ifindex)
addattr32 (&req.n, sizeof(req), NDA_IFINDEX, ifindex);
return netlink_request (&zns->netlink_cmd, &req.n);
}
/*
* IP Neighbor table read using netlink interface. This is invoked
* at startup.
*/
int
netlink_neigh_read (struct zebra_ns *zns)
{
int ret;
/* Get IP neighbor table. */
ret = netlink_request_neigh (zns, AF_UNSPEC, RTM_GETNEIGH, 0);
if (ret < 0)
return ret;
ret = netlink_parse_info (netlink_neigh_table, &zns->netlink_cmd, zns, 0, 1);
return ret;
}
/*
* IP Neighbor table read using netlink interface. This is for a specific
* VLAN device.
*/
int
netlink_neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if)
{
int ret = 0;
ret = netlink_request_neigh (zns, AF_UNSPEC, RTM_GETNEIGH, vlan_if->ifindex);
if (ret < 0)
return ret;
ret = netlink_parse_info (netlink_neigh_table, &zns->netlink_cmd, zns, 0, 0);
return ret;
}
int
netlink_neigh_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
ns_id_t ns_id)
{
int len;
struct ndmsg *ndm;
if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH))
return 0;
/* Length validity. */
len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ndmsg));
if (len < 0)
return -1;
/* Is this a notification for the MAC FDB or IP neighbor table? */
ndm = NLMSG_DATA (h);
if (ndm->ndm_family == AF_BRIDGE)
return netlink_macfdb_change (snl, h, len);
if (ndm->ndm_type != RTN_UNICAST)
return 0;
if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6)
return netlink_ipneigh_change (snl, h, len);
return 0;
}
static int
netlink_neigh_update2 (struct interface *ifp, struct ipaddr *ip,
struct ethaddr *mac, u_int32_t flags, int cmd)
{
struct {
struct nlmsghdr n;
struct ndmsg ndm;
char buf[256];
} req;
int ipa_len;
struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
char buf[INET6_ADDRSTRLEN];
char buf2[ETHER_ADDR_STRLEN];
memset(&req.n, 0, sizeof(req.n));
memset(&req.ndm, 0, sizeof(req.ndm));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
req.n.nlmsg_flags = NLM_F_REQUEST;
if (cmd == RTM_NEWNEIGH)
req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
req.n.nlmsg_type = cmd; //RTM_NEWNEIGH or RTM_DELNEIGH
req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6;
req.ndm.ndm_state = flags;
req.ndm.ndm_ifindex = ifp->ifindex;
req.ndm.ndm_type = RTN_UNICAST;
req.ndm.ndm_flags = NTF_EXT_LEARNED;
ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
if (mac)
addattr_l (&req.n, sizeof (req), NDA_LLADDR, mac, 6);
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("Tx %s family %s IF %s(%u) Neigh %s MAC %s",
nl_msg_type_to_str (cmd),
nl_family_to_str (req.ndm.ndm_family),
ifp->name, ifp->ifindex,
ipaddr2str (ip, buf, sizeof(buf)),
mac ? prefix_mac2str (mac, buf2, sizeof (buf2)) : "null");
return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
}
int
kernel_add_mac (struct interface *ifp, vlanid_t vid,
struct ethaddr *mac, struct in_addr vtep_ip,
u_char sticky)
{
return netlink_macfdb_update (ifp, vid, mac, vtep_ip, 0, RTM_NEWNEIGH, sticky);
}
int
kernel_del_mac (struct interface *ifp, vlanid_t vid,
struct ethaddr *mac, struct in_addr vtep_ip, int local)
{
return netlink_macfdb_update (ifp, vid, mac, vtep_ip, local, RTM_DELNEIGH, 0);
}
int kernel_add_neigh (struct interface *ifp, struct ipaddr *ip,
struct ethaddr *mac)
{
return netlink_neigh_update2 (ifp, ip, mac, NUD_REACHABLE,
RTM_NEWNEIGH);
}
int kernel_del_neigh (struct interface *ifp, struct ipaddr *ip)
{
return netlink_neigh_update2 (ifp, ip, NULL, 0, RTM_DELNEIGH);
}
/* /*
* MPLS label forwarding table change via netlink interface. * MPLS label forwarding table change via netlink interface.
*/ */

View File

@ -51,6 +51,15 @@ extern int netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
ns_id_t ns_id, int startup); ns_id_t ns_id, int startup);
extern int netlink_route_read (struct zebra_ns *zns); extern int netlink_route_read (struct zebra_ns *zns);
extern int netlink_neigh_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
ns_id_t ns_id);
extern int netlink_macfdb_read (struct zebra_ns *zns);
extern int netlink_macfdb_read_for_bridge (struct zebra_ns *zns,
struct interface *ifp, struct interface *br_if);
extern int netlink_neigh_read (struct zebra_ns *zns);
extern int netlink_neigh_read_for_vlan (struct zebra_ns *zns,
struct interface *vlan_if);
#endif /* HAVE_NETLINK */ #endif /* HAVE_NETLINK */
#endif /* _ZEBRA_RT_NETLINK_H */ #endif /* _ZEBRA_RT_NETLINK_H */

View File

@ -29,6 +29,7 @@
#include "sockunion.h" #include "sockunion.h"
#include "log.h" #include "log.h"
#include "privs.h" #include "privs.h"
#include "vxlan.h"
#include "zebra/debug.h" #include "zebra/debug.h"
#include "zebra/rib.h" #include "zebra/rib.h"
@ -426,3 +427,41 @@ kernel_get_ipmr_sg_stats (void *mroute)
{ {
return 0; return 0;
} }
int
kernel_add_vtep (vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
{
return 0;
}
int
kernel_del_vtep (vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
{
return 0;
}
int
kernel_add_mac (struct interface *ifp, vlanid_t vid,
struct ethaddr *mac, struct in_addr vtep_ip,
u_char sticky)
{
return 0;
}
int
kernel_del_mac (struct interface *ifp, vlanid_t vid,
struct ethaddr *mac, struct in_addr vtep_ip, int local)
{
return 0;
}
int kernel_add_neigh (struct interface *ifp, struct ipaddr *ip,
struct ethaddr *mac)
{
return 0;
}
int kernel_del_neigh (struct interface *ifp, struct ipaddr *ip)
{
return 0;
}

View File

@ -237,3 +237,23 @@ route_read (struct zebra_ns *zns)
exit: exit:
close (dev); close (dev);
} }
/* Only implemented for netlink method */
void
macfdb_read (struct zebra_ns *zns)
{
}
void macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp,
struct interface *br_if)
{
}
void
neigh_read (struct zebra_ns *zns)
{
}
void neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if)
{
}

View File

@ -29,3 +29,24 @@ void route_read (struct zebra_ns *zns)
{ {
netlink_route_read (zns); netlink_route_read (zns);
} }
void macfdb_read (struct zebra_ns *zns)
{
netlink_macfdb_read (zns);
}
void macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp,
struct interface *br_if)
{
netlink_macfdb_read_for_bridge (zns, ifp, br_if);
}
void neigh_read (struct zebra_ns *zns)
{
netlink_neigh_read (zns);
}
void neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if)
{
netlink_neigh_read_for_vlan (zns, vlan_if);
}

View File

@ -83,3 +83,23 @@ route_read (struct zebra_ns *zns)
return; return;
} }
/* Only implemented for the netlink method. */
void
macfdb_read (struct zebra_ns *zns)
{
}
void macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp,
struct interface *br_if)
{
}
void
neigh_read (struct zebra_ns *zns)
{
}
void neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if)
{
}

251
zebra/zebra_l2.c Normal file
View File

@ -0,0 +1,251 @@
/*
* Zebra Layer-2 interface handling code
* Copyright (C) 2016, 2017 Cumulus Networks, Inc.
*
* This file is part of FRR.
*
* FRR 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.
*
* FRR 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 FRR; 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 "if.h"
#include "prefix.h"
#include "table.h"
#include "memory.h"
#include "log.h"
#include "linklist.h"
#include "stream.h"
#include "hash.h"
#include "jhash.h"
#include "zebra/rib.h"
#include "zebra/rt.h"
#include "zebra/zebra_ns.h"
#include "zebra/zserv.h"
#include "zebra/debug.h"
#include "zebra/interface.h"
#include "zebra/zebra_memory.h"
#include "zebra/zebra_vrf.h"
#include "zebra/rt_netlink.h"
#include "zebra/zebra_l2.h"
#include "zebra/zebra_vxlan.h"
/* definitions */
/* static function declarations */
/* Private functions */
static void
map_slaves_to_bridge (struct interface *br_if, int link)
{
struct vrf *vrf;
struct listnode *node;
struct interface *ifp;
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
{
for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp))
{
struct zebra_if *zif;
struct zebra_l2info_brslave *br_slave;
if (ifp->ifindex == IFINDEX_INTERNAL ||
!ifp->info)
continue;
if (!IS_ZEBRA_IF_BRIDGE_SLAVE (ifp))
continue;
/* NOTE: This assumes 'zebra_l2info_brslave' is the first field
* for any L2 interface.
*/
zif = (struct zebra_if *) ifp->info;
br_slave = &zif->brslave_info;
if (link)
{
if (br_slave->bridge_ifindex == br_if->ifindex)
br_slave->br_if = br_if;
}
else
{
if (br_slave->br_if == br_if)
br_slave->br_if = NULL;
}
}
}
}
/* Public functions */
void
zebra_l2_map_slave_to_bridge (struct zebra_l2info_brslave *br_slave)
{
struct interface *br_if;
/* TODO: Handle change of master */
br_if = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT),
br_slave->bridge_ifindex);
if (br_if)
br_slave->br_if = br_if;
}
void
zebra_l2_unmap_slave_from_bridge (struct zebra_l2info_brslave *br_slave)
{
br_slave->br_if = NULL;
}
/*
* Handle Bridge interface add or update. Update relevant info,
* map slaves (if any) to the bridge.
*/
void
zebra_l2_bridge_add_update (struct interface *ifp,
struct zebra_l2info_bridge *bridge_info,
int add)
{
struct zebra_if *zif;
zif = ifp->info;
assert(zif);
/* Copy over the L2 information. */
memcpy (&zif->l2info.br, bridge_info, sizeof (*bridge_info));
/* Link all slaves to this bridge */
map_slaves_to_bridge (ifp, 1);
}
/*
* Handle Bridge interface delete.
*/
void
zebra_l2_bridge_del (struct interface *ifp)
{
/* Unlink all slaves to this bridge */
map_slaves_to_bridge (ifp, 0);
}
/*
* Update L2 info for a VLAN interface. Only relevant parameter is the
* VLAN Id and this cannot change.
*/
void
zebra_l2_vlanif_update (struct interface *ifp,
struct zebra_l2info_vlan *vlan_info)
{
struct zebra_if *zif;
zif = ifp->info;
assert(zif);
/* Copy over the L2 information. */
memcpy (&zif->l2info.vl, vlan_info, sizeof (*vlan_info));
}
/*
* Update L2 info for a VxLAN interface. This is called upon interface
* addition as well as update. Upon add, need to invoke the VNI create
* function. Upon update, the params of interest are the local tunnel
* IP and VLAN mapping, but the latter is handled separately.
*/
void
zebra_l2_vxlanif_add_update (struct interface *ifp,
struct zebra_l2info_vxlan *vxlan_info,
int add)
{
struct zebra_if *zif;
struct in_addr old_vtep_ip;
zif = ifp->info;
assert(zif);
if (add)
{
memcpy (&zif->l2info.vxl, vxlan_info, sizeof (*vxlan_info));
zebra_vxlan_if_add (ifp);
return;
}
old_vtep_ip = zif->l2info.vxl.vtep_ip;
if (IPV4_ADDR_SAME(&old_vtep_ip, &vxlan_info->vtep_ip))
return;
zif->l2info.vxl.vtep_ip = vxlan_info->vtep_ip;
zebra_vxlan_if_update (ifp, ZEBRA_VXLIF_LOCAL_IP_CHANGE);
}
/*
* Handle change to VLAN to VNI mapping.
*/
void
zebra_l2_vxlanif_update_access_vlan (struct interface *ifp,
vlanid_t access_vlan)
{
struct zebra_if *zif;
vlanid_t old_access_vlan;
zif = ifp->info;
assert(zif);
old_access_vlan = zif->l2info.vxl.access_vlan;
if (old_access_vlan == access_vlan)
return;
zif->l2info.vxl.access_vlan = access_vlan;
zebra_vxlan_if_update (ifp, ZEBRA_VXLIF_VLAN_CHANGE);
}
/*
* Handle VxLAN interface delete.
*/
void
zebra_l2_vxlanif_del (struct interface *ifp)
{
zebra_vxlan_if_del (ifp);
}
/*
* Map or unmap interface from bridge.
* NOTE: It is currently assumped that an interface has to be unmapped
* from a bridge before it can be mapped to another bridge.
*/
void
zebra_l2if_update_bridge_slave (struct interface *ifp,
ifindex_t bridge_ifindex)
{
struct zebra_if *zif;
ifindex_t old_bridge_ifindex;
zif = ifp->info;
assert(zif);
old_bridge_ifindex = zif->brslave_info.bridge_ifindex;
if (old_bridge_ifindex == bridge_ifindex)
return;
zif->brslave_info.bridge_ifindex = bridge_ifindex;
/* Set up or remove link with master */
if (bridge_ifindex != IFINDEX_INTERNAL)
zebra_l2_map_slave_to_bridge (&zif->brslave_info);
else if (old_bridge_ifindex != IFINDEX_INTERNAL)
zebra_l2_unmap_slave_from_bridge (&zif->brslave_info);
/* In the case of VxLAN, invoke the handler for EVPN. */
if (zif->zif_type == ZEBRA_IF_VXLAN)
zebra_vxlan_if_update (ifp, ZEBRA_VXLIF_MASTER_CHANGE);
}

94
zebra/zebra_l2.h Normal file
View File

@ -0,0 +1,94 @@
/*
* Zebra Layer-2 interface Data structures and definitions
* Copyright (C) 2016, 2017 Cumulus Networks, Inc.
*
* This file is part of FRR.
*
* FRR 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.
*
* FRR 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 FRR; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef _ZEBRA_L2_H
#define _ZEBRA_L2_H
#include <zebra.h>
#include "if.h"
#include "vlan.h"
#include "vxlan.h"
/* zebra L2 interface information - bridge slave (linkage to bridge) */
struct zebra_l2info_brslave
{
ifindex_t bridge_ifindex; /* Bridge Master */
struct interface *br_if; /* Pointer to master */
};
/* zebra L2 interface information - bridge interface */
struct zebra_l2info_bridge
{
u_char vlan_aware; /* VLAN-aware bridge? */
};
/* zebra L2 interface information - VLAN interface */
struct zebra_l2info_vlan
{
vlanid_t vid; /* VLAN id */
};
/* zebra L2 interface information - VXLAN interface */
struct zebra_l2info_vxlan
{
vni_t vni; /* VNI */
struct in_addr vtep_ip; /* Local tunnel IP */
vlanid_t access_vlan; /* Access VLAN - for VLAN-aware bridge. */
};
union zebra_l2if_info
{
struct zebra_l2info_bridge br;
struct zebra_l2info_vlan vl;
struct zebra_l2info_vxlan vxl;
};
/* NOTE: These macros are to be invoked only in the "correct" context.
* IOW, the macro VNI_FROM_ZEBRA_IF() will assume the interface is
* of type ZEBRA_IF_VXLAN.
*/
#define VNI_FROM_ZEBRA_IF(zif) (zif)->l2info.vxl.vni
#define VLAN_ID_FROM_ZEBRA_IF(zif) (zif)->l2info.vl.vid
#define IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(zif) \
((zif)->l2info.br.vlan_aware == 1)
extern void zebra_l2_map_slave_to_bridge (struct zebra_l2info_brslave *br_slave);
extern void zebra_l2_unmap_slave_from_bridge (struct zebra_l2info_brslave *br_slave);
extern void zebra_l2_bridge_add_update (struct interface *ifp,
struct zebra_l2info_bridge *bridge_info,
int add);
extern void zebra_l2_bridge_del (struct interface *ifp);
extern void zebra_l2_vlanif_update (struct interface *ifp,
struct zebra_l2info_vlan *vlan_info);
extern void zebra_l2_vxlanif_add_update (struct interface *ifp,
struct zebra_l2info_vxlan *vxlan_info,
int add);
extern void zebra_l2_vxlanif_update_access_vlan (struct interface *ifp,
vlanid_t access_vlan);
extern void zebra_l2_vxlanif_del (struct interface *ifp);
extern void zebra_l2if_update_bridge_slave (struct interface *ifp,
ifindex_t bridge_ifindex);
#endif /* _ZEBRA_L2_H */

76
zebra/zebra_l2_null.c Normal file
View File

@ -0,0 +1,76 @@
/*
* Zebra Layer-2 interface Data structures and definitions
* Copyright (C) 2016, 2017 Cumulus Networks, Inc.
*
* This file is part of FRR.
*
* FRR 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.
*
* FRR 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 FRR; 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 "if.h"
#include "zebra/debug.h"
#include "zebra/zserv.h"
#include "zebra/rib.h"
#include "zebra/zebra_vrf.h"
#include "zebra/zebra_l2.h"
void zebra_l2_map_slave_to_bridge (struct zebra_l2info_brslave *br_slave)
{
}
void
zebra_l2_unmap_slave_from_bridge (struct zebra_l2info_brslave *br_slave)
{
}
void zebra_l2_bridge_add_update (struct interface *ifp,
struct zebra_l2info_bridge *bridge_info,
int add)
{
}
void zebra_l2_bridge_del (struct interface *ifp)
{
}
void zebra_l2_vlanif_update (struct interface *ifp,
struct zebra_l2info_vlan *vlan_info)
{
}
void zebra_l2_vxlanif_add_update (struct interface *ifp,
struct zebra_l2info_vxlan *vxlan_info,
int add)
{
}
void
zebra_l2_vxlanif_update_access_vlan (struct interface *ifp,
vlanid_t access_vlan)
{
}
void zebra_l2_vxlanif_del (struct interface *ifp)
{
}
void
zebra_l2if_update_bridge_slave (struct interface *ifp,
ifindex_t bridge_ifindex)
{
}

View File

@ -37,6 +37,7 @@
#include "zebra/zebra_static.h" #include "zebra/zebra_static.h"
#include "zebra/interface.h" #include "zebra/interface.h"
#include "zebra/zebra_mpls.h" #include "zebra/zebra_mpls.h"
#include "zebra/zebra_vxlan.h"
extern struct zebra_t zebrad; extern struct zebra_t zebrad;
@ -244,6 +245,9 @@ zebra_vrf_delete (struct vrf *vrf)
rib_close_table (zvrf->other_table[afi][table_id]); rib_close_table (zvrf->other_table[afi][table_id]);
} }
/* Cleanup Vxlan table and update kernel */
zebra_vxlan_close_tables (zvrf);
zebra_mpls_close_tables (zvrf); zebra_mpls_close_tables (zvrf);
for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp)) for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp))
@ -421,6 +425,7 @@ zebra_vrf_alloc (void)
zvrf->import_check_table[afi] = table; zvrf->import_check_table[afi] = table;
} }
zebra_vxlan_init_tables (zvrf);
zebra_mpls_init_tables (zvrf); zebra_mpls_init_tables (zvrf);
return zvrf; return zvrf;

View File

@ -95,6 +95,15 @@ struct zebra_vrf
u_int16_t mpls_flags; u_int16_t mpls_flags;
#define MPLS_FLAG_SCHEDULE_LSPS (1 << 0) #define MPLS_FLAG_SCHEDULE_LSPS (1 << 0)
/*
* VNI hash table (for EVPN). Only in default instance.
*/
struct hash *vni_table;
/*
* Whether EVPN is enabled or not.
*/
int advertise_all_vni;
/* Route Installs */ /* Route Installs */
uint64_t installs; uint64_t installs;
uint64_t removals; uint64_t removals;

View File

@ -32,6 +32,7 @@
#include "mpls.h" #include "mpls.h"
#include "routemap.h" #include "routemap.h"
#include "srcdest_table.h" #include "srcdest_table.h"
#include "vxlan.h"
#include "zebra/zserv.h" #include "zebra/zserv.h"
#include "zebra/zebra_vrf.h" #include "zebra/zebra_vrf.h"
@ -41,6 +42,7 @@
#include "zebra/zebra_routemap.h" #include "zebra/zebra_routemap.h"
#include "zebra/zebra_static.h" #include "zebra/zebra_static.h"
#include "lib/json.h" #include "lib/json.h"
#include "zebra/zebra_vxlan.h"
extern int allow_delete; extern int allow_delete;
@ -54,6 +56,9 @@ static void vty_show_ip_route_detail (struct vty *vty, struct route_node *rn,
#define ONE_DAY_SECOND 60*60*24 #define ONE_DAY_SECOND 60*60*24
#define ONE_WEEK_SECOND 60*60*24*7 #define ONE_WEEK_SECOND 60*60*24*7
/* VNI range as per RFC 7432 */
#define CMD_VNI_RANGE "(1-16777215)"
/* General function for static route. */ /* General function for static route. */
int int
zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd,
@ -3044,6 +3049,237 @@ DEFUN (show_vrf,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN (show_evpn_vni,
show_evpn_vni_cmd,
"show evpn vni",
SHOW_STR
"EVPN\n"
"VxLAN information\n")
{
struct zebra_vrf *zvrf;
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_vnis(vty, zvrf);
return CMD_SUCCESS;
}
DEFUN (show_evpn_vni_vni,
show_evpn_vni_vni_cmd,
"show evpn vni " CMD_VNI_RANGE,
SHOW_STR
"EVPN\n"
"VxLAN Network Identifier\n"
"VNI number\n")
{
struct zebra_vrf *zvrf;
vni_t vni;
vni = strtoul(argv[3]->arg, NULL, 10);
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_vni(vty, zvrf, vni);
return CMD_SUCCESS;
}
DEFUN (show_evpn_mac_vni,
show_evpn_mac_vni_cmd,
"show evpn mac vni " CMD_VNI_RANGE,
SHOW_STR
"EVPN\n"
"MAC addresses\n"
"VxLAN Network Identifier\n"
"VNI number\n")
{
struct zebra_vrf *zvrf;
vni_t vni;
vni = strtoul(argv[4]->arg, NULL, 10);
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_macs_vni(vty, zvrf, vni);
return CMD_SUCCESS;
}
DEFUN (show_evpn_mac_vni_all,
show_evpn_mac_vni_all_cmd,
"show evpn mac vni all",
SHOW_STR
"EVPN\n"
"MAC addresses\n"
"VxLAN Network Identifier\n"
"All VNIs\n")
{
struct zebra_vrf *zvrf;
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_macs_all_vni(vty, zvrf);
return CMD_SUCCESS;
}
DEFUN (show_evpn_mac_vni_all_vtep,
show_evpn_mac_vni_all_vtep_cmd,
"show evpn mac vni all vtep A.B.C.D",
SHOW_STR
"EVPN\n"
"MAC addresses\n"
"VxLAN Network Identifier\n"
"All VNIs\n"
"Remote VTEP\n"
"Remote VTEP IP address\n")
{
struct zebra_vrf *zvrf;
struct in_addr vtep_ip;
if (!inet_aton (argv[6]->arg, &vtep_ip))
{
vty_out (vty, "%% Malformed VTEP IP address\n");
return CMD_WARNING;
}
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip);
return CMD_SUCCESS;
}
DEFUN (show_evpn_mac_vni_mac,
show_evpn_mac_vni_mac_cmd,
"show evpn mac vni " CMD_VNI_RANGE " mac WORD",
SHOW_STR
"EVPN\n"
"MAC addresses\n"
"VxLAN Network Identifier\n"
"VNI number\n"
"MAC\n"
"MAC address (e.g., 00:e0:ec:20:12:62)\n")
{
struct zebra_vrf *zvrf;
vni_t vni;
struct ethaddr mac;
vni = strtoul(argv[4]->arg, NULL, 10);
if (!prefix_str2mac (argv[6]->arg, &mac))
{
vty_out (vty, "%% Malformed MAC address");
return CMD_WARNING;
}
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac);
return CMD_SUCCESS;
}
DEFUN (show_evpn_mac_vni_vtep,
show_evpn_mac_vni_vtep_cmd,
"show evpn mac vni " CMD_VNI_RANGE " vtep A.B.C.D",
SHOW_STR
"EVPN\n"
"MAC addresses\n"
"VxLAN Network Identifier\n"
"VNI number\n"
"Remote VTEP\n"
"Remote VTEP IP address\n")
{
struct zebra_vrf *zvrf;
vni_t vni;
struct in_addr vtep_ip;
vni = strtoul(argv[4]->arg, NULL, 10);
if (!inet_aton (argv[6]->arg, &vtep_ip))
{
vty_out (vty, "%% Malformed VTEP IP address\n");
return CMD_WARNING;
}
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip);
return CMD_SUCCESS;
}
DEFUN (show_evpn_neigh_vni,
show_evpn_neigh_vni_cmd,
"show evpn arp-cache vni " CMD_VNI_RANGE,
SHOW_STR
"EVPN\n"
"ARP and ND cache\n"
"VxLAN Network Identifier\n"
"VNI number\n")
{
struct zebra_vrf *zvrf;
vni_t vni;
vni = strtoul(argv[4]->arg, NULL, 10);
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_neigh_vni(vty, zvrf, vni);
return CMD_SUCCESS;
}
DEFUN (show_evpn_neigh_vni_all,
show_evpn_neigh_vni_all_cmd,
"show evpn arp-cache vni all",
SHOW_STR
"EVPN\n"
"ARP and ND cache\n"
"VxLAN Network Identifier\n"
"All VNIs\n")
{
struct zebra_vrf *zvrf;
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_neigh_all_vni(vty, zvrf);
return CMD_SUCCESS;
}
DEFUN (show_evpn_neigh_vni_neigh,
show_evpn_neigh_vni_neigh_cmd,
"show evpn arp-cache vni " CMD_VNI_RANGE " ip WORD",
SHOW_STR
"EVPN\n"
"ARP and ND cache\n"
"VxLAN Network Identifier\n"
"VNI number\n"
"Neighbor\n"
"Neighbor address (IPv4 or IPv6 address)\n")
{
struct zebra_vrf *zvrf;
vni_t vni;
struct ipaddr ip;
vni = strtoul(argv[4]->arg, NULL, 10);
if (str2ipaddr (argv[6]->arg, &ip) != 0)
{
vty_out (vty, "%% Malformed Neighbor address\n");
return CMD_WARNING;
}
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip);
return CMD_SUCCESS;
}
DEFUN (show_evpn_neigh_vni_vtep,
show_evpn_neigh_vni_vtep_cmd,
"show evpn arp-cache vni " CMD_VNI_RANGE " vtep A.B.C.D",
SHOW_STR
"EVPN\n"
"ARP and ND cache\n"
"VxLAN Network Identifier\n"
"VNI number\n"
"Remote VTEP\n"
"Remote VTEP IP address\n")
{
struct zebra_vrf *zvrf;
vni_t vni;
struct in_addr vtep_ip;
vni = strtoul(argv[4]->arg, NULL, 10);
if (!inet_aton (argv[6]->arg, &vtep_ip))
{
vty_out (vty, "%% Malformed VTEP IP address\n");
return CMD_WARNING;
}
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip);
return CMD_SUCCESS;
}
/* Static ip route configuration write function. */ /* Static ip route configuration write function. */
static int static int
zebra_ip_config (struct vty *vty) zebra_ip_config (struct vty *vty)
@ -3234,4 +3470,16 @@ zebra_vty_init (void)
install_element (VIEW_NODE, &show_ipv6_route_vrf_all_prefix_cmd); install_element (VIEW_NODE, &show_ipv6_route_vrf_all_prefix_cmd);
install_element (VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd); install_element (VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd);
install_element (VIEW_NODE, &show_evpn_vni_cmd);
install_element (VIEW_NODE, &show_evpn_vni_vni_cmd);
install_element (VIEW_NODE, &show_evpn_mac_vni_cmd);
install_element (VIEW_NODE, &show_evpn_mac_vni_all_cmd);
install_element (VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
install_element (VIEW_NODE, &show_evpn_mac_vni_mac_cmd);
install_element (VIEW_NODE, &show_evpn_mac_vni_vtep_cmd);
install_element (VIEW_NODE, &show_evpn_neigh_vni_cmd);
install_element (VIEW_NODE, &show_evpn_neigh_vni_all_cmd);
install_element (VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
install_element (VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
} }

3380
zebra/zebra_vxlan.c Normal file

File diff suppressed because it is too large Load Diff

108
zebra/zebra_vxlan.h Normal file
View File

@ -0,0 +1,108 @@
/*
* Zebra VxLAN (EVPN) Data structures and definitions
* These are public definitions referenced by other files.
* Copyright (C) 2016, 2017 Cumulus Networks, Inc.
*
* This file is part of FRR.
*
* FRR 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.
*
* FRR 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 FRR; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef _ZEBRA_VXLAN_H
#define _ZEBRA_VXLAN_H
#include <zebra.h>
#include "linklist.h"
#include "if.h"
#include "vlan.h"
#include "vxlan.h"
#include "zebra/zebra_vrf.h"
/* Is EVPN enabled? */
#define EVPN_ENABLED(zvrf) (zvrf)->advertise_all_vni
/* VxLAN interface change flags of interest. */
#define ZEBRA_VXLIF_LOCAL_IP_CHANGE 0x1
#define ZEBRA_VXLIF_MASTER_CHANGE 0x2
#define ZEBRA_VXLIF_VLAN_CHANGE 0x4
extern void zebra_vxlan_print_macs_vni (struct vty *vty, struct zebra_vrf *zvrf,
vni_t vni);
extern void zebra_vxlan_print_macs_all_vni (struct vty *vty,
struct zebra_vrf *zvrf);
extern void zebra_vxlan_print_macs_all_vni_vtep (struct vty *vty,
struct zebra_vrf *zvrf,
struct in_addr vtep_ip);
extern void zebra_vxlan_print_specific_mac_vni (struct vty *vty,
struct zebra_vrf *zvrf, vni_t vni, struct ethaddr *mac);
extern void zebra_vxlan_print_macs_vni_vtep (struct vty *vty,
struct zebra_vrf *zvrf, vni_t vni, struct in_addr vtep_ip);
extern void zebra_vxlan_print_neigh_vni (struct vty *vty, struct zebra_vrf *zvrf,
vni_t vni);
extern void zebra_vxlan_print_neigh_all_vni (struct vty *vty,
struct zebra_vrf *zvrf);
extern void zebra_vxlan_print_specific_neigh_vni (struct vty *vty,
struct zebra_vrf *zvrf, vni_t vni, struct ipaddr *ip);
extern void zebra_vxlan_print_neigh_vni_vtep (struct vty *vty,
struct zebra_vrf *zvrf, vni_t vni, struct in_addr vtep_ip);
extern void zebra_vxlan_print_vni (struct vty *vty, struct zebra_vrf *zvrf, vni_t vni);
extern void zebra_vxlan_print_vnis (struct vty *vty, struct zebra_vrf *zvrf);
extern int zebra_vxlan_svi_up (struct interface *ifp, struct interface *link_if);
extern int zebra_vxlan_svi_down (struct interface *ifp, struct interface *link_if);
extern int zebra_vxlan_local_neigh_add_update (struct interface *ifp,
struct interface *link_if,
struct ipaddr *ip,
struct ethaddr *macaddr,
u_int16_t state,
u_char ext_learned);
extern int zebra_vxlan_local_neigh_del (struct interface *ifp,
struct interface *link_if,
struct ipaddr *ip);
extern int zebra_vxlan_remote_macip_add (struct zserv *client, int sock,
u_short length, struct zebra_vrf *zvrf);
extern int zebra_vxlan_remote_macip_del (struct zserv *client, int sock,
u_short length, struct zebra_vrf *zvrf);
extern int zebra_vxlan_local_mac_add_update (struct interface *ifp,
struct interface *br_if,
struct ethaddr *mac, vlanid_t vid,
u_char sticky);
extern int zebra_vxlan_local_mac_del (struct interface *ifp,
struct interface *br_if,
struct ethaddr *mac, vlanid_t vid);
extern int zebra_vxlan_check_readd_remote_mac (struct interface *ifp,
struct interface *br_if,
struct ethaddr *mac, vlanid_t vid);
extern int zebra_vxlan_check_del_local_mac (struct interface *ifp,
struct interface *br_if,
struct ethaddr *mac, vlanid_t vid);
extern int zebra_vxlan_if_up (struct interface *ifp);
extern int zebra_vxlan_if_down (struct interface *ifp);
extern int zebra_vxlan_if_add (struct interface *ifp);
extern int zebra_vxlan_if_update (struct interface *ifp, u_int16_t chgflags);
extern int zebra_vxlan_if_del (struct interface *ifp);
extern int zebra_vxlan_remote_vtep_add (struct zserv *client, int sock,
u_short length, struct zebra_vrf *zvrf);
extern int zebra_vxlan_remote_vtep_del (struct zserv *client, int sock,
u_short length, struct zebra_vrf *zvrf);
extern int zebra_vxlan_advertise_all_vni (struct zserv *client, int sock,
u_short length, struct zebra_vrf *zvrf);
extern void zebra_vxlan_init_tables (struct zebra_vrf *zvrf);
extern void zebra_vxlan_close_tables (struct zebra_vrf *);
#endif /* _ZEBRA_VXLAN_H */

197
zebra/zebra_vxlan_null.c Normal file
View File

@ -0,0 +1,197 @@
/*
* Zebra VxLAN (EVPN)
* Copyright (C) 2016, 2017 Cumulus Networks, Inc.
*
* This file is part of FRR.
*
* FRR 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.
*
* FRR 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 FRR; 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 "if.h"
#include "zebra/debug.h"
#include "zebra/zserv.h"
#include "zebra/rib.h"
#include "zebra/zebra_vrf.h"
#include "zebra/zebra_l2.h"
#include "zebra/zebra_vxlan.h"
void
zebra_vxlan_print_macs_vni (struct vty *vty, struct zebra_vrf *zvrf, vni_t vni)
{
}
void zebra_vxlan_print_macs_all_vni (struct vty *vty, struct zebra_vrf *zvrf)
{
}
void zebra_vxlan_print_macs_all_vni_vtep (struct vty *vty, struct zebra_vrf *zvrf, struct in_addr vtep_ip)
{
}
void
zebra_vxlan_print_specific_mac_vni (struct vty *vty, struct zebra_vrf *zvrf,
vni_t vni, struct ethaddr *mac)
{
}
void
zebra_vxlan_print_macs_vni_vtep (struct vty *vty, struct zebra_vrf *zvrf,
vni_t vni, struct in_addr vtep_ip)
{
}
void
zebra_vxlan_print_neigh_vni (struct vty *vty, struct zebra_vrf *zvrf,
vni_t vni)
{
}
void
zebra_vxlan_print_neigh_all_vni (struct vty *vty, struct zebra_vrf *zvrf)
{
}
void
zebra_vxlan_print_specific_neigh_vni (struct vty *vty, struct zebra_vrf *zvrf,
vni_t vni, struct ipaddr *ip)
{
}
void zebra_vxlan_print_neigh_vni_vtep (struct vty *vty, struct zebra_vrf *zvrf,
vni_t vni, struct in_addr vtep_ip)
{
}
void
zebra_vxlan_print_vni (struct vty *vty, struct zebra_vrf *zvrf, vni_t vni)
{
}
void
zebra_vxlan_print_vnis (struct vty *vty, struct zebra_vrf *zvrf)
{
}
int zebra_vxlan_svi_up (struct interface *ifp, struct interface *link_if)
{
return 0;
}
int zebra_vxlan_svi_down (struct interface *ifp, struct interface *link_if)
{
return 0;
}
int zebra_vxlan_remote_macip_add (struct zserv *client, int sock,
u_short length, struct zebra_vrf *zvrf)
{
return 0;
}
int zebra_vxlan_remote_macip_del (struct zserv *client, int sock,
u_short length, struct zebra_vrf *zvrf)
{
return 0;
}
int zebra_vxlan_local_mac_add_update (struct interface *ifp,
struct interface *br_if,
struct ethaddr *mac, vlanid_t vid,
u_char sticky)
{
return 0;
}
int zebra_vxlan_local_mac_del (struct interface *ifp,
struct interface *br_if,
struct ethaddr *mac, vlanid_t vid)
{
return 0;
}
int zebra_vxlan_check_readd_remote_mac (struct interface *ifp,
struct interface *br_if,
struct ethaddr *mac, vlanid_t vid)
{
return 0;
}
int zebra_vxlan_check_del_local_mac (struct interface *ifp,
struct interface *br_if,
struct ethaddr *mac, vlanid_t vid)
{
return 0;
}
int
zebra_vxlan_if_up (struct interface *ifp)
{
return 0;
}
int
zebra_vxlan_if_down (struct interface *ifp)
{
return 0;
}
int
zebra_vxlan_if_add (struct interface *ifp)
{
return 0;
}
int
zebra_vxlan_if_update (struct interface *ifp, u_int16_t chgflags)
{
return 0;
}
int
zebra_vxlan_if_del (struct interface *ifp)
{
return 0;
}
int zebra_vxlan_remote_vtep_add (struct zserv *client, int sock,
u_short length, struct zebra_vrf *zvrf)
{
return 0;
}
int zebra_vxlan_remote_vtep_del (struct zserv *client, int sock,
u_short length, struct zebra_vrf *zvrf)
{
return 0;
}
int zebra_vxlan_advertise_all_vni (struct zserv *client, int sock,
u_short length, struct zebra_vrf *zvrf)
{
return 0;
}
void
zebra_vxlan_init_tables (struct zebra_vrf *zvrf)
{
}
void
zebra_vxlan_close_tables (struct zebra_vrf *zvrf)
{
}

199
zebra/zebra_vxlan_private.h Normal file
View File

@ -0,0 +1,199 @@
/*
* Zebra VxLAN (EVPN) Data structures and definitions
* These are "internal" to this function.
* Copyright (C) 2016, 2017 Cumulus Networks, Inc.
*
* This file is part of FRR.
*
* FRR 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.
*
* FRR 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 FRR; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef _ZEBRA_VXLAN_PRIVATE_H
#define _ZEBRA_VXLAN_PRIVATE_H
#include <zebra.h>
#include <zebra.h>
#include "if.h"
#include "linklist.h"
/* definitions */
typedef struct zebra_vni_t_ zebra_vni_t;
typedef struct zebra_vtep_t_ zebra_vtep_t;
typedef struct zebra_mac_t_ zebra_mac_t;
typedef struct zebra_neigh_t_ zebra_neigh_t;
/*
* VTEP info
*
* Right now, this just has each remote VTEP's IP address.
*/
struct zebra_vtep_t_
{
/* Remote IP. */
/* NOTE: Can only be IPv4 right now. */
struct in_addr vtep_ip;
/* Links. */
struct zebra_vtep_t_ *next;
struct zebra_vtep_t_ *prev;
};
/*
* VNI hash table
*
* Contains information pertaining to a VNI:
* - the list of remote VTEPs (with this VNI)
*/
struct zebra_vni_t_
{
/* VNI - key */
vni_t vni;
/* Corresponding VxLAN interface. */
struct interface *vxlan_if;
/* List of remote VTEPs */
zebra_vtep_t *vteps;
/* Local IP */
struct in_addr local_vtep_ip;
/* List of local or remote MAC */
struct hash *mac_table;
/* List of local or remote neighbors (MAC+IP) */
struct hash *neigh_table;
};
/*
* MAC hash table.
*
* This table contains the MAC addresses pertaining to this VNI.
* This includes local MACs learnt on an attached VLAN that maps
* to this VNI as well as remote MACs learnt and installed by BGP.
* Local MACs will be known either on a VLAN sub-interface or
* on (port, VLAN); however, it is sufficient for zebra to maintain
* against the VNI i.e., it does not need to retain the local "port"
* information. The correct VNI will be obtained as zebra maintains
* the mapping (of VLAN to VNI).
*/
struct zebra_mac_t_
{
/* MAC address. */
struct ethaddr macaddr;
u_int32_t flags;
#define ZEBRA_MAC_LOCAL 0x01
#define ZEBRA_MAC_REMOTE 0x02
#define ZEBRA_MAC_AUTO 0x04 /* Auto created for neighbor. */
#define ZEBRA_MAC_STICKY 0x08 /* Static MAC */
/* Local or remote info. */
union
{
struct
{
ifindex_t ifindex;
vlanid_t vid;
} local;
struct in_addr r_vtep_ip;
} fwd_info;
u_int32_t neigh_refcnt;
};
/*
* Context for MAC hash walk - used by callbacks.
*/
struct mac_walk_ctx
{
zebra_vni_t *zvni; /* VNI hash */
struct zebra_vrf *zvrf; /* VRF - for client notification. */
int uninstall; /* uninstall from kernel? */
int upd_client; /* uninstall from client? */
u_int32_t flags;
#define DEL_LOCAL_MAC 0x1
#define DEL_REMOTE_MAC 0x2
#define DEL_ALL_MAC (DEL_LOCAL_MAC | DEL_REMOTE_MAC)
#define DEL_REMOTE_MAC_FROM_VTEP 0x4
#define SHOW_REMOTE_MAC_FROM_VTEP 0x8
struct in_addr r_vtep_ip; /* To walk MACs from specific VTEP */
struct vty *vty; /* Used by VTY handlers */
u_int32_t count; /* Used by VTY handlers */
};
/*
* Neighbor hash table.
*
* This table contains the neighbors (IP to MAC bindings) pertaining to
* this VNI. This includes local neighbors learnt on the attached VLAN
* device that maps to this VNI as well as remote neighbors learnt and
* installed by BGP.
* Local neighbors will be known against the VLAN device (SVI); however,
* it is sufficient for zebra to maintain against the VNI. The correct
* VNI will be obtained as zebra maintains the mapping (of VLAN to VNI).
*/
struct zebra_neigh_t_
{
/* IP address. */
struct ipaddr ip;
/* MAC address. */
struct ethaddr emac;
/* Underlying interface. */
ifindex_t ifindex;
u_int32_t flags;
#define ZEBRA_NEIGH_LOCAL 0x01
#define ZEBRA_NEIGH_REMOTE 0x02
/* Remote VTEP IP - applicable only for remote neighbors. */
struct in_addr r_vtep_ip;
};
/*
* Context for neighbor hash walk - used by callbacks.
*/
struct neigh_walk_ctx
{
zebra_vni_t *zvni; /* VNI hash */
struct zebra_vrf *zvrf; /* VRF - for client notification. */
int uninstall; /* uninstall from kernel? */
int upd_client; /* uninstall from client? */
u_int32_t flags;
#define DEL_LOCAL_NEIGH 0x1
#define DEL_REMOTE_NEIGH 0x2
#define DEL_ALL_NEIGH (DEL_LOCAL_NEIGH | DEL_REMOTE_NEIGH)
#define DEL_REMOTE_NEIGH_FROM_VTEP 0x4
#define SHOW_REMOTE_NEIGH_FROM_VTEP 0x8
struct in_addr r_vtep_ip; /* To walk neighbors from specific VTEP */
struct vty *vty; /* Used by VTY handlers */
u_int32_t count; /* Used by VTY handlers */
u_char addr_width; /* Used by VTY handlers */
};
#endif /* _ZEBRA_VXLAN_PRIVATE_H */

View File

@ -54,6 +54,7 @@
#include "zebra/zebra_mpls.h" #include "zebra/zebra_mpls.h"
#include "zebra/zebra_mroute.h" #include "zebra/zebra_mroute.h"
#include "zebra/label_manager.h" #include "zebra/label_manager.h"
#include "zebra/zebra_vxlan.h"
/* Event list of zebra. */ /* Event list of zebra. */
enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE }; enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE };
@ -2434,6 +2435,21 @@ zebra_client_read (struct thread *thread)
case ZEBRA_FEC_UNREGISTER: case ZEBRA_FEC_UNREGISTER:
zserv_fec_unregister (client, sock, length); zserv_fec_unregister (client, sock, length);
break; break;
case ZEBRA_ADVERTISE_ALL_VNI:
zebra_vxlan_advertise_all_vni (client, sock, length, zvrf);
break;
case ZEBRA_REMOTE_VTEP_ADD:
zebra_vxlan_remote_vtep_add (client, sock, length, zvrf);
break;
case ZEBRA_REMOTE_VTEP_DEL:
zebra_vxlan_remote_vtep_del (client, sock, length, zvrf);
break;
case ZEBRA_REMOTE_MACIP_ADD:
zebra_vxlan_remote_macip_add (client, sock, length, zvrf);
break;
case ZEBRA_REMOTE_MACIP_DEL:
zebra_vxlan_remote_macip_del (client, sock, length, zvrf);
break;
default: default:
zlog_info ("Zebra received unknown command %d", command); zlog_info ("Zebra received unknown command %d", command);
break; break;
@ -2725,6 +2741,10 @@ zebra_show_client_detail (struct vty *vty, struct zserv *client)
client->bfd_peer_upd8_cnt, client->bfd_peer_del_cnt); client->bfd_peer_upd8_cnt, client->bfd_peer_del_cnt);
vty_out (vty, "Interface Up Notifications: %d\n",client->ifup_cnt); vty_out (vty, "Interface Up Notifications: %d\n",client->ifup_cnt);
vty_out (vty, "Interface Down Notifications: %d\n",client->ifdown_cnt); vty_out (vty, "Interface Down Notifications: %d\n",client->ifdown_cnt);
vty_out (vty, "VNI add notifications: %d\n", client->vniadd_cnt);
vty_out (vty, "VNI delete notifications: %d\n", client->vnidel_cnt);
vty_out (vty, "MAC-IP add notifications: %d\n", client->macipadd_cnt);
vty_out (vty, "MAC-IP delete notifications: %d\n", client->macipdel_cnt);
vty_out (vty, "\n"); vty_out (vty, "\n");
return; return;

View File

@ -105,6 +105,10 @@ struct zserv
u_int32_t vrfdel_cnt; u_int32_t vrfdel_cnt;
u_int32_t if_vrfchg_cnt; u_int32_t if_vrfchg_cnt;
u_int32_t bfd_client_reg_cnt; u_int32_t bfd_client_reg_cnt;
u_int32_t vniadd_cnt;
u_int32_t vnidel_cnt;
u_int32_t macipadd_cnt;
u_int32_t macipdel_cnt;
time_t connect_time; time_t connect_time;
time_t last_read_time; time_t last_read_time;
@ -145,6 +149,11 @@ extern void hostinfo_get (void);
extern void rib_init (void); extern void rib_init (void);
extern void interface_list (struct zebra_ns *); extern void interface_list (struct zebra_ns *);
extern void route_read (struct zebra_ns *); extern void route_read (struct zebra_ns *);
extern void macfdb_read (struct zebra_ns *);
extern void macfdb_read_for_bridge (struct zebra_ns *, struct interface *,
struct interface *);
extern void neigh_read (struct zebra_ns *);
extern void neigh_read_for_vlan (struct zebra_ns *, struct interface *);
extern void kernel_init (struct zebra_ns *); extern void kernel_init (struct zebra_ns *);
extern void kernel_terminate (struct zebra_ns *); extern void kernel_terminate (struct zebra_ns *);
extern void zebra_route_map_init (void); extern void zebra_route_map_init (void);