Merge pull request #998 from mkanjari/dev-master

Dev master
This commit is contained in:
David Lamparter 2017-08-29 20:03:48 +02:00 committed by GitHub
commit 14f6aefe43
32 changed files with 1681 additions and 516 deletions

View File

@ -45,6 +45,8 @@
#include "bgpd/bgp_encap_types.h"
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_aspath.h"
#include "bgpd/bgp_zebra.h"
#include "bgpd/bgp_nexthop.h"
/*
* Definitions and external declarations.
@ -1199,6 +1201,13 @@ static int handle_tunnel_ip_change(struct bgp *bgp, struct bgpevpn *vpn,
return 0;
}
/* Update the tunnel-ip hash */
bgp_tip_del(bgp, &vpn->originator_ip);
bgp_tip_add(bgp, &originator_ip);
/* filter routes as martian nexthop db has changed */
bgp_filter_evpn_routes_upon_martian_nh_change(bgp);
/* Need to withdraw type-3 route as the originator IP is part
* of the key.
*/
@ -2178,6 +2187,71 @@ char *bgp_evpn_label2str(mpls_label_t *label, char *buf, int len)
return buf;
}
/*
* Function to convert evpn route to json format.
* NOTE: We don't use prefix2str as the output here is a bit different.
*/
void bgp_evpn_route2json(struct prefix_evpn *p, json_object *json)
{
char buf1[ETHER_ADDR_STRLEN];
char buf2[PREFIX2STR_BUFFER];
if (!json)
return;
if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) {
json_object_int_add(json, "routeType", p->prefix.route_type);
json_object_int_add(json, "ethTag", 0);
json_object_int_add(json, "ipLen",
IS_EVPN_PREFIX_IPADDR_V4(p)
? IPV4_MAX_BITLEN
: IPV6_MAX_BITLEN);
json_object_string_add(json, "ip",
inet_ntoa(p->prefix.ip.ipaddr_v4));
} else if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
if (IS_EVPN_PREFIX_IPADDR_NONE(p)) {
json_object_int_add(json, "routeType",
p->prefix.route_type);
json_object_int_add(
json, "esi",
0); /* TODO: we don't support esi yet */
json_object_int_add(json, "ethTag", 0);
json_object_int_add(json, "macLen", 8 * ETH_ALEN);
json_object_string_add(json, "mac",
prefix_mac2str(&p->prefix.mac,
buf1,
sizeof(buf1)));
} else {
u_char family;
family = IS_EVPN_PREFIX_IPADDR_V4(p) ? AF_INET
: AF_INET6;
json_object_int_add(json, "routeType",
p->prefix.route_type);
json_object_int_add(
json, "esi",
0); /* TODO: we don't support esi yet */
json_object_int_add(json, "ethTag", 0);
json_object_int_add(json, "macLen", 8 * ETH_ALEN);
json_object_string_add(json, "mac",
prefix_mac2str(&p->prefix.mac,
buf1,
sizeof(buf1)));
json_object_int_add(json, "ipLen",
IS_EVPN_PREFIX_IPADDR_V4(p)
? IPV4_MAX_BITLEN
: IPV6_MAX_BITLEN);
json_object_string_add(
json, "ip",
inet_ntop(family, &p->prefix.ip.ip.addr, buf2,
PREFIX2STR_BUFFER));
}
} else {
/* Currently, this is to cater to other AF_ETHERNET code. */
}
}
/*
* Function to convert evpn route to string.
* NOTE: We don't use prefix2str as the output here is a bit different.
@ -2562,6 +2636,76 @@ int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi,
return install_uninstall_evpn_route(bgp, afi, safi, p, ri, 0);
}
/* filter routes which have martian next hops */
int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp)
{
afi_t afi;
safi_t safi;
struct bgp_node *rd_rn, *rn;
struct bgp_table *table;
struct bgp_info *ri;
afi = AFI_L2VPN;
safi = SAFI_EVPN;
/* Walk entire global routing table and evaluate routes which could be
* imported into this VPN. Note that we cannot just look at the routes
* for the VNI's RD -
* remote routes applicable for this VNI could have any RD.
*/
/* EVPN routes are a 2-level table. */
for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn;
rd_rn = bgp_route_next(rd_rn)) {
table = (struct bgp_table *)(rd_rn->info);
if (!table)
continue;
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
for (ri = rn->info; ri; ri = ri->next) {
/* Consider "valid" remote routes applicable for
* this VNI. */
if (!(ri->type == ZEBRA_ROUTE_BGP
&& ri->sub_type == BGP_ROUTE_NORMAL))
continue;
if (bgp_nexthop_self(bgp,
ri->attr->nexthop)) {
char attr_str[BUFSIZ];
char pbuf[PREFIX_STRLEN];
bgp_dump_attr(ri->attr, attr_str,
BUFSIZ);
if (bgp_debug_update(ri->peer, &rn->p,
NULL, 1))
zlog_debug(
"%u: prefix %s with attr %s - DENIED due to martian or self nexthop",
bgp->vrf_id,
prefix2str(
&rn->p,
pbuf,
sizeof(pbuf)),
attr_str);
bgp_evpn_unimport_route(bgp, afi, safi,
&rn->p, ri);
bgp_rib_remove(rn, ri, ri->peer,
afi, safi);
}
}
}
}
return 0;
}
/*
* Handle del of a local MACIP.
*/
@ -2657,6 +2801,11 @@ int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni)
*/
delete_routes_for_vni(bgp, vpn);
/*
* tunnel is no longer active, del tunnel ip address from tip_hash
*/
bgp_tip_del(bgp, &vpn->originator_ip);
/* Clear "live" flag and see if hash needs to be freed. */
UNSET_FLAG(vpn->flags, VNI_FLAG_LIVE);
if (!is_vni_configured(vpn))
@ -2702,15 +2851,22 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
bgp->vrf_id, vni);
return -1;
}
}
/* if the VNI is live already, there is nothibng more to do */
/* if the VNI is live already, there is nothing more to do */
if (is_vni_live(vpn))
return 0;
/* Mark as "live" */
SET_FLAG(vpn->flags, VNI_FLAG_LIVE);
/* tunnel is now active, add tunnel-ip to db */
bgp_tip_add(bgp, &originator_ip);
/* filter routes as nexthop database has changed */
bgp_filter_evpn_routes_upon_martian_nh_change(bgp);
/* Create EVPN type-3 route and schedule for processing. */
build_evpn_type3_prefix(&p, vpn->originator_ip);
if (update_evpn_route(bgp, vpn, &p, 0)) {
@ -2725,6 +2881,10 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
*/
install_routes_for_vni(bgp, vpn);
/* If we are advertising gateway mac-ip
It needs to be conveyed again to zebra */
bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip, vpn->vni);
return 0;
}

View File

@ -28,6 +28,7 @@
extern void bgp_evpn_handle_router_id_update(struct bgp *bgp, int withdraw);
extern char *bgp_evpn_label2str(mpls_label_t *label, char *buf, int len);
extern char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len);
extern void bgp_evpn_route2json(struct prefix_evpn *p, json_object *json);
extern void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
struct prefix_rd *prd, mpls_label_t *label,
struct attr *attr, int addpath_encode,
@ -38,6 +39,7 @@ 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_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp);
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,

View File

@ -28,6 +28,8 @@
#include "bgpd/bgpd.h"
#include "bgpd/bgp_ecommunity.h"
#define RT_ADDRSTRLEN 28
/* EVPN prefix lengths. */
#define EVPN_TYPE_2_ROUTE_PREFIXLEN 224
#define EVPN_TYPE_3_ROUTE_PREFIXLEN 224

File diff suppressed because it is too large Load Diff

View File

@ -101,6 +101,7 @@ DEFINE_MTYPE(BGPD, BGP_DAMP_ARRAY, "BGP Dampening array")
DEFINE_MTYPE(BGPD, BGP_REGEXP, "BGP regexp")
DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate")
DEFINE_MTYPE(BGPD, BGP_ADDR, "BGP own address")
DEFINE_MTYPE(BGPD, TIP_ADDR, "BGP own tunnel-ip address")
DEFINE_MTYPE(BGPD, BGP_REDIST, "BGP redistribution")
DEFINE_MTYPE(BGPD, BGP_FILTER_NAME, "BGP Filter Information")

View File

@ -97,6 +97,7 @@ DECLARE_MTYPE(BGP_DAMP_ARRAY)
DECLARE_MTYPE(BGP_REGEXP)
DECLARE_MTYPE(BGP_AGGREGATE)
DECLARE_MTYPE(BGP_ADDR)
DECLARE_MTYPE(TIP_ADDR)
DECLARE_MTYPE(BGP_REDIST)
DECLARE_MTYPE(BGP_FILTER_NAME)

View File

@ -88,11 +88,86 @@ static void bgp_nexthop_cache_reset(struct bgp_table *table)
}
}
/* BGP own address structure */
struct bgp_addr {
struct in_addr addr;
int refcnt;
};
static void *bgp_tip_hash_alloc(void *p)
{
const struct in_addr *val = (const struct in_addr *)p;
struct tip_addr *addr;
addr = XMALLOC(MTYPE_TIP_ADDR, sizeof(struct tip_addr));
addr->refcnt = 0;
addr->addr.s_addr = val->s_addr;
return addr;
}
static void bgp_tip_hash_free(void *addr)
{
XFREE(MTYPE_TIP_ADDR, addr);
}
static unsigned int bgp_tip_hash_key_make(void *p)
{
const struct tip_addr *addr = p;
return jhash_1word(addr->addr.s_addr, 0);
}
static int bgp_tip_hash_cmp(const void *p1, const void *p2)
{
const struct tip_addr *addr1 = p1;
const struct tip_addr *addr2 = p2;
return addr1->addr.s_addr == addr2->addr.s_addr;
}
void bgp_tip_hash_init(struct bgp *bgp)
{
bgp->tip_hash = hash_create(bgp_tip_hash_key_make,
bgp_tip_hash_cmp, NULL);
}
void bgp_tip_hash_destroy(struct bgp *bgp)
{
if (bgp->tip_hash == NULL)
return;
hash_clean(bgp->tip_hash, bgp_tip_hash_free);
hash_free(bgp->tip_hash);
bgp->tip_hash = NULL;
}
void bgp_tip_add(struct bgp *bgp, struct in_addr *tip)
{
struct tip_addr tmp;
struct tip_addr *addr;
tmp.addr = *tip;
addr = hash_get(bgp->tip_hash, &tmp, bgp_tip_hash_alloc);
if (!addr)
return;
addr->refcnt++;
}
void bgp_tip_del(struct bgp *bgp, struct in_addr *tip)
{
struct tip_addr tmp;
struct tip_addr *addr;
tmp.addr = *tip;
addr = hash_lookup(bgp->tip_hash, &tmp);
/* may have been deleted earlier by bgp_interface_down() */
if (addr == NULL)
return;
addr->refcnt--;
if (addr->refcnt == 0) {
hash_release(bgp->tip_hash, addr);
XFREE(MTYPE_TIP_ADDR, addr);
}
}
static void *bgp_address_hash_alloc(void *p)
{
@ -304,6 +379,7 @@ void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
{
struct bgp_addr tmp, *addr;
struct tip_addr tmp_tip, *tip;
tmp.addr = nh_addr;
@ -311,6 +387,11 @@ int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
if (addr)
return 1;
tmp_tip.addr = nh_addr;
tip = hash_lookup(bgp->tip_hash, &tmp_tip);
if (tip)
return 1;
return 0;
}

View File

@ -66,6 +66,18 @@ struct bgp_nexthop_cache {
struct bgp *bgp;
};
/* BGP own address structure */
struct bgp_addr {
struct in_addr addr;
int refcnt;
};
/* Own tunnel-ip address structure */
struct tip_addr {
struct in_addr addr;
int refcnt;
};
extern int bgp_nexthop_lookup(afi_t, struct peer *peer, struct bgp_info *,
int *, int *);
extern void bgp_connected_add(struct bgp *bgp, struct connected *c);
@ -82,5 +94,9 @@ extern void bgp_scan_finish(struct bgp *bgp);
extern void bgp_scan_vty_init(void);
extern void bgp_address_init(struct bgp *bgp);
extern void bgp_address_destroy(struct bgp *bgp);
extern void bgp_tip_add(struct bgp *bgp, struct in_addr *tip);
extern void bgp_tip_del(struct bgp *bgp, struct in_addr *tip);
extern void bgp_tip_hash_init(struct bgp *bgp);
extern void bgp_tip_hash_destroy(struct bgp *bgp);
#endif /* _QUAGGA_BGP_NEXTHOP_H */

View File

@ -482,6 +482,34 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
evaluate_paths(bnc);
}
/*
* Cleanup nexthop registration and status information for BGP nexthops
* pertaining to this VRF. This is invoked upon VRF deletion.
*/
void bgp_cleanup_nexthops(struct bgp *bgp)
{
afi_t afi;
struct bgp_node *rn;
struct bgp_nexthop_cache *bnc;
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
if (!bgp->nexthop_cache_table[afi])
continue;
for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn;
rn = bgp_route_next(rn)) {
bnc = rn->info;
if (!bnc)
continue;
/* Clear relevant flags. */
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
}
}
}
/**
* make_prefix - make a prefix structure from the path (essentially
* path's node.

View File

@ -66,4 +66,10 @@ void bgp_unlink_nexthop_by_peer(struct peer *);
*/
extern void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer);
/*
* Cleanup nexthop registration and status information for BGP nexthops
* pertaining to this VRF. This is invoked upon VRF deletion.
*/
extern void bgp_cleanup_nexthops(struct bgp *bgp);
#endif /* _BGP_NHT_H */

View File

@ -1271,7 +1271,6 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
as_t local_as;
u_int32_t restart_time;
u_char afi_safi_count = 0;
struct utsname names;
int adv_addpath_tx = 0;
/* Remember current pointer for Opt Parm Len. */
@ -1441,8 +1440,7 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
}
/* Hostname capability */
uname(&names);
if (names.nodename[0] != '\0') {
if (cmd_hostname_get()) {
SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
rcapp = stream_get_endp(s); /* Ptr to length placeholder */
@ -1450,26 +1448,21 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
stream_putc(s, CAPABILITY_CODE_FQDN);
capp = stream_get_endp(s);
stream_putc(s, 0); /* dummy len for now */
len = strlen(names.nodename);
len = strlen(cmd_hostname_get());
if (len > BGP_MAX_HOSTNAME)
len = BGP_MAX_HOSTNAME;
stream_putc(s, len);
stream_put(s, names.nodename, len);
#ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME
if ((names.domainname[0] != '\0')
&& (strcmp(names.domainname, "(none)") != 0)) {
len = strlen(names.domainname);
stream_put(s, cmd_hostname_get(), len);
if (cmd_domainname_get()) {
len = strlen(cmd_domainname_get());
if (len > BGP_MAX_HOSTNAME)
len = BGP_MAX_HOSTNAME;
stream_putc(s, len);
stream_put(s, names.domainname, len);
stream_put(s, cmd_domainname_get(), len);
} else
#endif
{
stream_putc(s, 0); /* 0 length */
}
/* Set the lengths straight */
len = stream_get_endp(s) - rcapp - 1;
@ -1478,14 +1471,10 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
stream_putc_at(s, capp, len);
if (bgp_debug_neighbor_events(peer))
#ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME
zlog_debug(
"%s Sending hostname cap with hn = %s, dn = %s",
peer->host, names.nodename, names.domainname);
#else
zlog_debug("%s Sending hostname cap with hn = %s",
peer->host, names.nodename);
#endif
peer->host, cmd_hostname_get(),
cmd_domainname_get());
}
/* Sending base graceful-restart capability irrespective of the config

View File

@ -2042,9 +2042,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
/* Do we need to allocate or free labels?
* Right now, since we only deal with per-prefix labels, it is not
* necessary
* to do this upon changes to best path except of the label index
* changes.
* necessary to do this upon changes to best path except if the label
* index changes
*/
if (bgp->allocate_mpls_labels[afi][safi]) {
if (new_select) {
@ -2425,7 +2424,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
/* Unconditionally remove the route from the RIB, without taking
* damping into consideration (eg, because the session went down)
*/
static void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri,
void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri,
struct peer *peer, afi_t afi, safi_t safi)
{
bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi, safi);
@ -6270,47 +6269,66 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
}
/* Static function to display route. */
static void route_vty_out_route(struct prefix *p, struct vty *vty)
static void route_vty_out_route(struct prefix *p, struct vty *vty,
json_object *json)
{
int len;
u_int32_t destination;
char buf[BUFSIZ];
if (p->family == AF_INET) {
if (!json) {
len = vty_out(vty, "%s",
inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ));
inet_ntop(p->family, &p->u.prefix, buf,
BUFSIZ));
destination = ntohl(p->u.prefix4.s_addr);
if ((IN_CLASSC(destination) && p->prefixlen == 24)
|| (IN_CLASSB(destination) && p->prefixlen == 16)
|| (IN_CLASSA(destination) && p->prefixlen == 8)
|| p->u.prefix4.s_addr == 0) {
/* When mask is natural, mask is not displayed. */
/* When mask is natural,
mask is not displayed. */
} else
len += vty_out(vty, "/%d", p->prefixlen);
} else {
json_object_string_add(json, "prefix",
inet_ntop(p->family,
&p->u.prefix, buf,
BUFSIZ));
json_object_int_add(json, "prefixLen", p->prefixlen);
}
} else if (p->family == AF_ETHERNET) {
prefix2str(p, buf, PREFIX_STRLEN);
len = vty_out(vty, "%s", buf);
} else if (p->family == AF_EVPN) {
#if defined(HAVE_CUMULUS)
if (!json)
len = vty_out(vty, "%s",
bgp_evpn_route2str((struct prefix_evpn *)p, buf,
BUFSIZ));
bgp_evpn_route2str((struct prefix_evpn *)p,
buf, BUFSIZ));
else
bgp_evpn_route2json((struct prefix_evpn *) p, json);
#else
prefix2str(p, buf, PREFIX_STRLEN);
len = vty_out(vty, "%s", buf);
#endif
} else
} else {
if (!json)
len = vty_out(vty, "%s/%d",
inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
inet_ntop(p->family, &p->u.prefix, buf,
BUFSIZ),
p->prefixlen);
}
if (!json) {
len = 17 - len;
if (len < 1)
vty_out(vty, "\n%*s", 20, " ");
else
vty_out(vty, "%*s", len, " ");
}
}
enum bgp_display_type {
normal_list,
@ -6413,9 +6431,11 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
if (!json_paths) {
/* print prefix and mask */
if (!display)
route_vty_out_route(p, vty);
route_vty_out_route(p, vty, json_path);
else
vty_out(vty, "%*s", 17, " ");
} else {
route_vty_out_route(p, vty, json_path);
}
/* Print attribute */
@ -6711,7 +6731,7 @@ void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
json_net, "addrPrefix",
inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ));
else
route_vty_out_route(p, vty);
route_vty_out_route(p, vty, NULL);
/* Print attribute */
if (attr) {
@ -6844,7 +6864,7 @@ void route_vty_out_tag(struct vty *vty, struct prefix *p,
/* print prefix and mask */
if (json == NULL) {
if (!display)
route_vty_out_route(p, vty);
route_vty_out_route(p, vty, NULL);
else
vty_out(vty, "%*s", 17, " ");
}
@ -6959,7 +6979,7 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p,
/* print prefix and mask */
if (!display)
route_vty_out_route(p, vty);
route_vty_out_route(p, vty, NULL);
else
vty_out(vty, "%*s", 17, " ");
@ -7028,7 +7048,7 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p,
/* print prefix and mask */
if (!use_json) {
if (!display)
route_vty_out_route(p, vty);
route_vty_out_route(p, vty, NULL);
else
vty_out(vty, "%*s", 17, " ");
}
@ -7097,7 +7117,7 @@ static void flap_route_vty_out(struct vty *vty, struct prefix *p,
/* print prefix and mask */
if (!use_json) {
if (!display)
route_vty_out_route(p, vty);
route_vty_out_route(p, vty, NULL);
else
vty_out(vty, "%*s", 17, " ");
}
@ -8380,6 +8400,7 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
#if defined(HAVE_CUMULUS)
char buf3[EVPN_ROUTE_STRLEN];
#endif
char prefix_str[BUFSIZ];
int count = 0;
int best = 0;
int suppress = 0;
@ -8402,9 +8423,8 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
json_object_int_add(json, "localLabel", label);
json_object_string_add(json, "prefix",
inet_ntop(p->family, &p->u.prefix, buf2,
INET6_ADDRSTRLEN));
json_object_int_add(json, "prefixlen", p->prefixlen);
prefix2str(p, prefix_str,
sizeof(prefix_str)));
} else {
#if defined(HAVE_CUMULUS)
if (safi == SAFI_EVPN)

View File

@ -294,6 +294,8 @@ static inline int bgp_fibupd_safi(safi_t safi)
}
/* Prototypes. */
extern void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri,
struct peer *peer, afi_t afi, safi_t safi);
extern void bgp_process_queue_init(void);
extern void bgp_route_init(void);
extern void bgp_route_finish(void);

View File

@ -6424,6 +6424,59 @@ DEFUN (show_bgp_vrfs,
return CMD_SUCCESS;
}
static void show_address_entry(struct hash_backet *backet, void *args)
{
struct vty *vty = (struct vty *) args;
struct bgp_addr *addr = (struct bgp_addr *) backet->data;
vty_out(vty, "addr: %s, count: %d\n",
inet_ntoa(addr->addr),
addr->refcnt);
}
static void show_tip_entry(struct hash_backet *backet, void *args)
{
struct vty *vty = (struct vty *)args;
struct tip_addr *tip = (struct tip_addr *) backet->data;
vty_out(vty, "addr: %s, count: %d\n",
inet_ntoa(tip->addr),
tip->refcnt);
}
static void bgp_show_martian_nexthops(struct vty *vty, struct bgp *bgp)
{
vty_out(vty, "self nexthop database:\n");
hash_iterate(bgp->address_hash,
(void (*)(struct hash_backet *, void *))show_address_entry,
vty);
vty_out(vty, "Tunnel-ip database:\n");
hash_iterate(bgp->tip_hash,
(void (*)(struct hash_backet *, void *))show_tip_entry,
vty);
}
DEFUN (show_bgp_martian_nexthop_db,
show_bgp_martian_nexthop_db_cmd,
"show bgp martian next-hop",
SHOW_STR
BGP_STR
"martian next-hops\n"
"martian next-hop database\n")
{
struct bgp *bgp = NULL;
bgp = bgp_get_default();
if (!bgp) {
vty_out(vty, "%% No BGP process is configured\n");
return CMD_WARNING;
}
bgp_show_martian_nexthops(vty, bgp);
return CMD_SUCCESS;
}
DEFUN (show_bgp_memory,
show_bgp_memory_cmd,
"show [ip] bgp memory",
@ -7528,6 +7581,12 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
"defaultNotSent");
}
if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
if (p->bgp->advertise_all_vni)
json_object_boolean_true_add(json_addr,
"advertiseAllVnis");
}
if (filter->plist[FILTER_IN].name
|| filter->dlist[FILTER_IN].name
|| filter->aslist[FILTER_IN].name
@ -7793,6 +7852,12 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
vty_out(vty, " default not sent\n");
}
/* advertise-vni-all */
if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
if (p->bgp->advertise_all_vni)
vty_out(vty, " advertise-all-vni\n");
}
if (filter->plist[FILTER_IN].name
|| filter->dlist[FILTER_IN].name
|| filter->aslist[FILTER_IN].name
@ -8577,6 +8642,46 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json,
json_cap, "multiprotocolExtensions",
json_multi);
/* Hostname capabilities */
json_object *json_hname = NULL;
json_hname = json_object_new_object();
if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_ADV)) {
json_object_string_add(
json_hname,
"advHostName",
bgp->peer_self->hostname ?
bgp->peer_self->hostname
: "n/a");
json_object_string_add(
json_hname,
"advDomainName",
bgp->peer_self->domainname ?
bgp->peer_self->domainname
: "n/a");
}
if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_RCV)) {
json_object_string_add(
json_hname,
"rcvHostName",
p->hostname ?
p->hostname :
"n/a");
json_object_string_add(
json_hname,
"rcvDomainName",
p->domainname ?
p->domainname :
"n/a");
}
json_object_object_add(json_cap,
"hostName",
json_hname);
/* Gracefull Restart */
if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)
|| CHECK_FLAG(p->cap,
@ -8910,25 +9015,35 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json,
}
/* Hostname capability */
if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_ADV)
|| CHECK_FLAG(p->cap,
PEER_CAP_HOSTNAME_RCV)) {
vty_out(vty,
" Hostname Capability:");
if (CHECK_FLAG(p->cap,
PEER_CAP_HOSTNAME_ADV))
vty_out(vty, " advertised");
if (CHECK_FLAG(p->cap,
PEER_CAP_HOSTNAME_RCV))
vty_out(vty, " %sreceived",
CHECK_FLAG(
p->cap,
PEER_CAP_HOSTNAME_ADV)
? "and "
: "");
vty_out(vty, "\n");
if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_ADV)) {
vty_out(vty,
" advertised (name: %s,domain name: %s)",
bgp->peer_self->hostname ?
bgp->peer_self->hostname
: "n/a",
bgp->peer_self->domainname ?
bgp->peer_self->domainname
: "n/a");
} else {
vty_out(vty, " not advertised");
}
if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_RCV)) {
vty_out(vty,
" received (name: %s,domain name: %s)",
p->hostname ?
p->hostname : "n/a",
p->domainname ?
p->domainname : "n/a");
} else {
vty_out(vty, " not received");
}
vty_out(vty, "\n");
/* Gracefull Restart */
if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)
|| CHECK_FLAG(p->cap,
@ -12264,6 +12379,9 @@ void bgp_vty_init(void)
/* "show [ip] bgp memory" commands. */
install_element(VIEW_NODE, &show_bgp_memory_cmd);
/* "show bgp martian next-hop" */
install_element(VIEW_NODE, &show_bgp_martian_nexthop_db_cmd);
/* "show [ip] bgp views" commands. */
install_element(VIEW_NODE, &show_bgp_views_cmd);

View File

@ -2816,6 +2816,21 @@ static struct bgp *bgp_create(as_t *as, const char *name,
XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host);
bgp->peer_self->host =
XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement");
if (bgp->peer_self->hostname != NULL) {
XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->hostname);
bgp->peer_self->hostname = NULL;
}
if (cmd_hostname_get())
bgp->peer_self->hostname = XSTRDUP(MTYPE_BGP_PEER_HOST,
cmd_hostname_get());
if (bgp->peer_self->domainname != NULL) {
XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->domainname);
bgp->peer_self->domainname = NULL;
}
if (cmd_domainname_get())
bgp->peer_self->domainname = XSTRDUP(MTYPE_BGP_PEER_HOST,
cmd_domainname_get());
bgp->peer = list_new();
bgp->peer->cmp = (int (*)(void *, void *))peer_cmp;
bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_same, NULL);
@ -2988,6 +3003,7 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
bgp = bgp_create(as, name, inst_type);
bgp_router_id_set(bgp, &bgp->router_id_zebra);
bgp_address_init(bgp);
bgp_tip_hash_init(bgp);
bgp_scan_init(bgp);
*bgp_val = bgp;
@ -3069,6 +3085,9 @@ void bgp_instance_down(struct bgp *bgp)
/* Purge network and redistributed routes. */
bgp_purge_static_redist_routes(bgp);
/* Cleanup registered nexthops (flags) */
bgp_cleanup_nexthops(bgp);
}
/* Delete BGP instance. */
@ -3200,6 +3219,7 @@ void bgp_free(struct bgp *bgp)
bgp_scan_finish(bgp);
bgp_address_destroy(bgp);
bgp_tip_hash_destroy(bgp);
bgp_evpn_cleanup(bgp);

View File

@ -318,6 +318,10 @@ struct bgp {
struct hash *address_hash;
/* DB for all local tunnel-ips - used mainly for martian checks
Currently it only has all VxLan tunnel IPs*/
struct hash *tip_hash;
/* Static route configuration. */
struct bgp_table *route[AFI_MAX][SAFI_MAX];

View File

@ -146,6 +146,6 @@ void dynhn_print_all(struct vty *vty)
}
vty_out(vty, " * %s %s\n", sysid_print(isis->sysid),
unix_hostname());
cmd_hostname_get());
return;
}

View File

@ -607,7 +607,7 @@ static void lspid_print(u_char *lsp_id, u_char *trg, char dynhost, char frag)
if (dyn)
sprintf((char *)id, "%.14s", dyn->hostname);
else if (!memcmp(isis->sysid, lsp_id, ISIS_SYS_ID_LEN) && dynhost)
sprintf((char *)id, "%.14s", unix_hostname());
sprintf((char *)id, "%.14s", cmd_hostname_get());
else
memcpy(id, sysid_print(lsp_id), 15);
if (frag)
@ -887,9 +887,9 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
}
/* Dynamic Hostname */
if (area->dynhostname) {
isis_tlvs_set_dynamic_hostname(lsp->tlvs, unix_hostname());
isis_tlvs_set_dynamic_hostname(lsp->tlvs, cmd_hostname_get());
lsp_debug("ISIS (%s): Adding dynamic hostname '%s'",
area->area_tag, unix_hostname());
area->area_tag, cmd_hostname_get());
} else {
lsp_debug("ISIS (%s): Not adding dynamic hostname (disabled)",
area->area_tag);

View File

@ -431,24 +431,6 @@ struct in_addr newprefix2inaddr(u_char *prefix_start, u_char prefix_masklen)
return new_prefix;
}
/*
* Returns host.name if any, otherwise
* it returns the system hostname.
*/
const char *unix_hostname(void)
{
static struct utsname names;
const char *hostname;
hostname = host.name;
if (!hostname) {
uname(&names);
hostname = names.nodename;
}
return hostname;
}
/*
* Returns the dynamic hostname associated with the passed system ID.
* If no dynamic hostname found then returns formatted system ID.
@ -462,7 +444,7 @@ const char *print_sys_hostname(const u_char *sysid)
/* For our system ID return our host name */
if (memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN) == 0)
return unix_hostname();
return cmd_hostname_get();
dyn = dynhn_find_by_id(sysid);
if (dyn)

View File

@ -56,7 +56,6 @@ void zlog_dump_data(void *data, int len);
* misc functions
*/
unsigned long isis_jitter(unsigned long timer, unsigned long jitter);
const char *unix_hostname(void);
/*
* macros

View File

@ -1441,7 +1441,7 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level)
lsp = lsp_search(
lspid,
area->lspdb[level]);
} else if (strncmp(unix_hostname(),
} else if (strncmp(cmd_hostname_get(),
sysid, 15)
== 0) {
memcpy(lspid, isis->sysid,

View File

@ -125,6 +125,23 @@ vector cmdvec = NULL;
/* Host information structure. */
struct host host;
/*
* Returns host.name if any, otherwise
* it returns the system hostname.
*/
const char *cmd_hostname_get(void)
{
return host.name;
}
/*
* Returns unix domainname
*/
const char *cmd_domainname_get(void)
{
return host.domainname;
}
/* Standard command node structures. */
static struct cmd_node auth_node = {
AUTH_NODE, "Password: ",
@ -475,8 +492,8 @@ static char *zencrypt(const char *passwd)
/* This function write configuration of this host. */
static int config_write_host(struct vty *vty)
{
if (host.name)
vty_out(vty, "hostname %s\n", host.name);
if (cmd_hostname_get())
vty_out(vty, "hostname %s\n", cmd_hostname_get());
if (host.encrypt) {
if (host.password_encrypt)
@ -1411,7 +1428,7 @@ DEFUN (show_version,
"Displays zebra version\n")
{
vty_out(vty, "%s %s (%s).\n", FRR_FULL_NAME, FRR_VERSION,
host.name ? host.name : "");
cmd_hostname_get() ? cmd_hostname_get() : "");
vty_out(vty, "%s%s\n", FRR_COPYRIGHT, GIT_INFO);
vty_out(vty, "configured with:\n %s\n", FRR_CONFIG_ARGS);
@ -1745,6 +1762,40 @@ DEFUN (show_startup_config,
return CMD_SUCCESS;
}
int cmd_domainname_set(const char *domainname)
{
XFREE(MTYPE_HOST, host.domainname);
host.domainname = domainname ? XSTRDUP(MTYPE_HOST, domainname) : NULL;
return CMD_SUCCESS;
}
/* Hostname configuration */
DEFUN (config_domainname,
domainname_cmd,
"domainname WORD",
"Set system's domain name\n"
"This system's domain name\n")
{
struct cmd_token *word = argv[1];
if (!isalpha((int)word->arg[0])) {
vty_out(vty, "Please specify string starting with alphabet\n");
return CMD_WARNING_CONFIG_FAILED;
}
return cmd_domainname_set(word->arg);
}
DEFUN (config_no_domainname,
no_domainname_cmd,
"no domainname [DOMAINNAME]",
NO_STR
"Reset system's domain name\n"
"domain name of this router\n")
{
return cmd_domainname_set(NULL);
}
int cmd_hostname_set(const char *hostname)
{
XFREE(MTYPE_HOST, host.name);
@ -2515,9 +2566,12 @@ void install_default(enum node_type node)
* terminal = -1 -- watchfrr / no logging, but minimal config control */
void cmd_init(int terminal)
{
struct utsname names;
if (array_size(node_names) != NODE_TYPE_MAX)
assert(!"Update the CLI node description array!");
uname(&names);
qobj_init();
varhandlers = list_new();
@ -2526,7 +2580,15 @@ void cmd_init(int terminal)
cmdvec = vector_init(VECTOR_MIN_SIZE);
/* Default host value settings. */
host.name = NULL;
host.name = XSTRDUP(MTYPE_HOST, names.nodename);
#ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME
if ((strcmp(names.domainname, "(none)") == 0))
host.domainname = NULL;
else
host.domainname = XSTRDUP(MTYPE_HOST, names.domainname);
#else
host.domainname = NULL;
#endif
host.password = NULL;
host.enable = NULL;
host.logfile = NULL;
@ -2579,6 +2641,8 @@ void cmd_init(int terminal)
install_element(CONFIG_NODE, &hostname_cmd);
install_element(CONFIG_NODE, &no_hostname_cmd);
install_element(CONFIG_NODE, &domainname_cmd);
install_element(CONFIG_NODE, &no_domainname_cmd);
install_element(CONFIG_NODE, &frr_version_defaults_cmd);
install_element(CONFIG_NODE, &debug_memstats_cmd);
@ -2644,6 +2708,8 @@ void cmd_terminate()
if (host.name)
XFREE(MTYPE_HOST, host.name);
if (host.domainname)
XFREE(MTYPE_HOST, host.domainname);
if (host.password)
XFREE(MTYPE_HOST, host.password);
if (host.password_encrypt)

View File

@ -41,6 +41,9 @@ struct host {
/* Host name of this router. */
char *name;
/* Domainname of this router */
char *domainname;
/* Password for vty interface. */
char *password;
char *password_encrypt;
@ -398,7 +401,10 @@ extern void cmd_terminate(void);
extern void cmd_exit(struct vty *vty);
extern int cmd_list_cmds(struct vty *vty, int do_permute);
extern int cmd_domainname_set(const char *domainname);
extern int cmd_hostname_set(const char *hostname);
extern const char *cmd_hostname_get(void);
extern const char *cmd_domainname_get(void);
/* NOT safe for general use; call this only if DEV_BUILD! */
extern void grammar_sandbox_init(void);

View File

@ -50,6 +50,7 @@ int main(int argc, char **argv)
/* Library inits. */
cmd_init(1);
host.name = strdup("test");
host.domainname = strdup("testdomainname");
vty_init(master);
memory_init();

View File

@ -250,16 +250,9 @@ void vty_hello(struct vty *vty)
/* Put out prompt and wait input from user. */
static void vty_prompt(struct vty *vty)
{
struct utsname names;
const char *hostname;
if (vty->type == VTY_TERM) {
hostname = host.name;
if (!hostname) {
uname(&names);
hostname = names.nodename;
}
vty_out(vty, cmd_prompt(vty->node), hostname);
vty_out(vty, cmd_prompt(vty->node),
cmd_hostname_get());
}
}

View File

@ -2891,21 +2891,9 @@ void vtysh_readline_init(void)
char *vtysh_prompt(void)
{
static struct utsname names;
static char buf[100];
const char *hostname;
extern struct host host;
hostname = host.name;
if (!hostname) {
if (!names.nodename[0])
uname(&names);
hostname = names.nodename;
}
snprintf(buf, sizeof buf, cmd_prompt(vty->node), hostname);
snprintf(buf, sizeof buf, cmd_prompt(vty->node), cmd_hostname_get());
return buf;
}

View File

@ -423,10 +423,9 @@ int vtysh_read_config(const char *config_default_dir)
void vtysh_config_write()
{
char line[81];
extern struct host host;
if (host.name) {
sprintf(line, "hostname %s", host.name);
if (cmd_hostname_get()) {
sprintf(line, "hostname %s", cmd_hostname_get());
vtysh_config_parse_line(NULL, line);
}
if (vtysh_write_integrated == WRITE_INTEGRATED_NO)

View File

@ -873,7 +873,8 @@ void if_up(struct interface *ifp)
link_if = ifp;
zebra_vxlan_svi_up(ifp, link_if);
} else if (IS_ZEBRA_IF_VLAN(ifp)) {
link_if = zif->link;
link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
zif->link_ifindex);
if (link_if)
zebra_vxlan_svi_up(ifp, link_if);
}
@ -901,7 +902,8 @@ void if_down(struct interface *ifp)
link_if = ifp;
zebra_vxlan_svi_down(ifp, link_if);
} else if (IS_ZEBRA_IF_VLAN(ifp)) {
link_if = zif->link;
link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
zif->link_ifindex);
if (link_if)
zebra_vxlan_svi_down(ifp, link_if);
}

View File

@ -2014,7 +2014,8 @@ static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
* itself
*/
if (IS_ZEBRA_IF_VLAN(ifp)) {
link_if = zif->link;
link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
zif->link_ifindex);
if (!link_if)
return 0;
} else if (IS_ZEBRA_IF_BRIDGE(ifp))

View File

@ -224,12 +224,19 @@ void zebra_l2if_update_bridge_slave(struct interface *ifp,
zif->brslave_info.bridge_ifindex = bridge_ifindex;
/* Set up or remove link with master */
if (bridge_ifindex != IFINDEX_INTERNAL)
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);
} else if (old_bridge_ifindex != IFINDEX_INTERNAL) {
/*
* In the case of VxLAN, invoke the handler for EVPN.
* Note that this should be done *prior*
* to unmapping the interface from the bridge.
*/
if (zif->zif_type == ZEBRA_IF_VXLAN)
zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_MASTER_CHANGE);
zebra_l2_unmap_slave_from_bridge(&zif->brslave_info);
}
}

View File

@ -204,13 +204,18 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
if (json == NULL) {
vty_out(vty, " Remote VTEP: %s",
inet_ntoa(n->r_vtep_ip));
vty_out(vty, " State: %s", IS_ZEBRA_NEIGH_ACTIVE(n)
? "Active"
: "Inactive");
} else
json_object_string_add(json, "remoteVtep",
inet_ntoa(n->r_vtep_ip));
}
if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
if (!json) {
vty_out(vty, "\n");
vty_out(vty, " State: %s",
IS_ZEBRA_NEIGH_ACTIVE(n) ? "Active"
: "Inactive");
}
}
if (json == NULL)
vty_out(vty, "\n");
}
@ -384,8 +389,8 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt)
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
vty_out(vty, " Auto Mac ");
}
vty_out(vty, " ARP ref: %u\n", mac->neigh_refcnt);
vty_out(vty, "\n");
/* print all the associated neigh */
vty_out(vty, " Neighbors:\n");
if (!listcount(mac->neigh_list))
@ -1355,9 +1360,6 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
memcpy(&n->emac, macaddr, ETH_ALEN);
n->ifindex = ifp->ifindex;
/* We have a neigh associated to mac increment the refcnt*/
mac->neigh_refcnt++;
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
"%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s add to BGP",
@ -1431,13 +1433,22 @@ static void zvni_gw_macip_del_for_vni_hash(struct hash_backet *backet,
struct zebra_l2info_vxlan zl2_info;
struct interface *vlan_if = NULL;
struct interface *vrr_if = NULL;
struct interface *ifp;
/* Add primary SVI MAC*/
zvni = (zebra_vni_t *)backet->data;
if (!zvni)
return;
zif = zvni->vxlan_if->info;
ifp = zvni->vxlan_if;
if (!ifp)
return;
zif = ifp->info;
/* If down or not mapped to a bridge, we're done. */
if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
return;
zl2_info = zif->l2info.vxl;
vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan,
@ -1464,6 +1475,7 @@ static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
struct zebra_l2info_vxlan zl2_info;
struct interface *vlan_if = NULL;
struct interface *vrr_if = NULL;
struct interface *ifp = NULL;
zvni = (zebra_vni_t *)backet->data;
if (!zvni)
@ -1472,7 +1484,14 @@ static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
if (!advertise_gw_macip_enabled(zvrf, zvni))
return;
zif = zvni->vxlan_if->info;
ifp = zvni->vxlan_if;
if (!ifp)
return;
zif = ifp->info;
/* If down or not mapped to a bridge, we're done. */
if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
return;
zl2_info = zif->l2info.vxl;
vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan,
@ -1758,6 +1777,9 @@ static zebra_vni_t *zvni_map_svi(struct interface *ifp, struct interface *br_if)
vlanid_t vid = 0;
zebra_vni_t *zvni;
if (!br_if)
return NULL;
/* Make sure the linked interface is a bridge. */
if (!IS_ZEBRA_IF_BRIDGE(br_if))
return NULL;
@ -1827,6 +1849,10 @@ static struct interface *zvni_map_to_svi(struct zebra_vrf *zvrf, vlanid_t vid,
struct zebra_l2info_vlan *vl;
u_char bridge_vlan_aware;
/* Defensive check, caller expected to invoke only with valid bridge. */
if (!br_if)
return NULL;
/* Determine if bridge is VLAN-aware or not */
zif = br_if->info;
assert(zif);
@ -1943,10 +1969,8 @@ static void zvni_install_mac_hash(struct hash_backet *backet, void *ctxt)
static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac,
int uninstall)
{
if (mac->neigh_refcnt)
mac->neigh_refcnt--;
if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) || mac->neigh_refcnt > 0)
if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) ||
!list_isempty(mac->neigh_list))
return;
if (uninstall)
@ -2853,7 +2877,7 @@ int zebra_vxlan_local_neigh_del(struct interface *ifp,
/* see if the AUTO mac needs to be deleted */
if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
|| !listcount(zmac->neigh_list))
&& !listcount(zmac->neigh_list))
zvni_mac_del(zvni, zmac);
return 0;
@ -2872,10 +2896,9 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
zebra_vni_t *zvni;
zebra_neigh_t *n;
struct zebra_vrf *zvrf;
zebra_mac_t *zmac;
zebra_mac_t *zmac, *old_zmac;
char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
int send_upd = 1, send_del = 0;
/* We are only interested in neighbors on an SVI that resides on top
* of a VxLAN bridge.
@ -2930,19 +2953,35 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
if (memcmp(n->emac.octet, macaddr->octet,
ETH_ALEN)
== 0) {
if (n->ifindex == ifp->ifindex)
/* we're not interested in whatever has
* changed. */
return 0;
/* client doesn't care about a purely local
* change. */
send_upd = 0;
} else
/* If the MAC has changed, issue a delete first
* as this means a
* different MACIP route.
/* Update any params and return - client doesn't
* care about a purely local change.
*/
send_del = 1;
n->ifindex = ifp->ifindex;
return 0;
}
/* If the MAC has changed,
* need to issue a delete first
* as this means a different MACIP route.
* Also, need to do some unlinking/relinking.
*/
zvni_neigh_send_del_to_client(zvrf, zvni->vni,
&n->ip, &n->emac,
0);
old_zmac = zvni_mac_lookup(zvni, &n->emac);
if (old_zmac) {
listnode_delete(old_zmac->neigh_list,
n);
zvni_deref_ip2mac(zvni, old_zmac, 0);
}
/* Set "local" forwarding info. */
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
n->ifindex = ifp->ifindex;
memcpy(&n->emac, macaddr, ETH_ALEN);
/* Link to new MAC */
listnode_add_sort(zmac->neigh_list, n);
} else if (ext_learned)
/* The neighbor is remote and that is the notification we got.
*/
@ -2954,6 +2993,8 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
{
UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
n->r_vtep_ip.s_addr = 0;
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
n->ifindex = ifp->ifindex;
}
} else {
n = zvni_neigh_add(zvni, ip, macaddr);
@ -2965,16 +3006,10 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
ifp->name, ifp->ifindex, zvni->vni);
return -1;
}
}
/* Issue delete for older info, if needed. */
if (send_del)
zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, &n->emac,
0);
/* Set "local" forwarding info. */
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
n->ifindex = ifp->ifindex;
}
/* Before we program this in BGP, we need to check if MAC is locally
* learnt as well */
@ -2989,8 +3024,7 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
return 0;
}
/* Inform BGP if required. */
if (send_upd) {
/* Inform BGP. */
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
"%u: neigh %s (MAC %s) is now ACTIVE on VNI %u",
@ -3003,8 +3037,6 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
macaddr, 0);
}
return 0;
}
/*
* Handle message from client to delete a remote MACIP for a VNI.
@ -3023,6 +3055,8 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
u_short l = 0, ipa_len;
char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
struct interface *ifp = NULL;
struct zebra_if *zif = NULL;
s = client->ibuf;
@ -3065,12 +3099,18 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
zvrf_id(zvrf), vni);
continue;
}
if (!zvni->vxlan_if) {
ifp = zvni->vxlan_if;
if (!ifp) {
zlog_err(
"VNI %u hash %p doesn't have intf upon remote MACIP DEL",
vni, zvni);
continue;
}
zif = ifp->info;
/* If down or not mapped to a bridge, we're done. */
if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
continue;
/* The remote VTEP specified is normally expected to exist, but
* it is
@ -3083,12 +3123,6 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
if (!zvni_vtep_find(zvni, &vtep_ip))
continue;
/* If the local VxLAN interface is not up (should be a transient
* event), there's nothing more to do.
*/
if (!if_is_operative(zvni->vxlan_if))
continue;
mac = zvni_mac_lookup(zvni, &macaddr);
if (ipa_len)
n = zvni_neigh_lookup(zvni, &ip);
@ -3132,7 +3166,7 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
zvni_process_neigh_on_remote_mac_del(zvrf, zvni,
mac);
if (!mac->neigh_refcnt) {
if (list_isempty(mac->neigh_list)) {
zvni_mac_uninstall(zvni, mac, 0);
zvni_mac_del(zvni, mac);
} else
@ -3166,6 +3200,8 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
u_char sticky;
struct interface *ifp = NULL;
struct zebra_if *zif = NULL;
assert(EVPN_ENABLED(zvrf));
@ -3213,16 +3249,17 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
zvrf_id(zvrf), vni);
continue;
}
if (!zvni->vxlan_if) {
ifp = zvni->vxlan_if;
if (!ifp) {
zlog_err(
"VNI %u hash %p doesn't have intf upon remote MACIP add",
vni, zvni);
continue;
}
/* If the local VxLAN interface is not up (should be a transient
* event), there's nothing more to do.
*/
if (!if_is_operative(zvni->vxlan_if))
zif = ifp->info;
/* If down or not mapped to a bridge, we're done. */
if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
continue;
/* The remote VTEP specified should normally exist, but it is
@ -3272,9 +3309,6 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
/* Is this MAC created for a MACIP? */
if (ipa_len)
SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
/* Moving from local to remote, issue delete. */
zvni_mac_uninstall(zvni, mac, 1);
}
/* Set "auto" and "remote" forwarding info. */
@ -3326,16 +3360,16 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
return -1;
}
/* New neighbor referring to this MAC. */
mac->neigh_refcnt++;
} else if (memcmp(&n->emac, &macaddr, sizeof(macaddr))
!= 0) {
/* MAC change, update ref counts for old and new
* MAC. */
/* MAC change, update neigh list for old and new
* mac */
old_mac = zvni_mac_lookup(zvni, &n->emac);
if (old_mac)
if (old_mac) {
listnode_delete(old_mac->neigh_list, n);
zvni_deref_ip2mac(zvni, old_mac, 1);
mac->neigh_refcnt++;
}
listnode_add_sort(mac->neigh_list, n);
memcpy(&n->emac, &macaddr, ETH_ALEN);
}
@ -3687,6 +3721,8 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length,
struct in_addr vtep_ip;
zebra_vni_t *zvni;
zebra_vtep_t *zvtep;
struct interface *ifp;
struct zebra_if *zif;
s = client->ibuf;
@ -3713,6 +3749,18 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length,
continue;
}
ifp = zvni->vxlan_if;
if (!ifp) {
zlog_err("VNI %u hash %p doesn't have intf upon remote VTEP DEL",
zvni->vni, zvni);
continue;
}
zif = ifp->info;
/* If down or not mapped to a bridge, we're done. */
if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
continue;
/* If the remote VTEP does not exist, there's nothing more to
* do.
* Otherwise, uninstall any remote MACs pointing to this VTEP
@ -3743,6 +3791,8 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length,
vni_t vni;
struct in_addr vtep_ip;
zebra_vni_t *zvni;
struct interface *ifp;
struct zebra_if *zif;
assert(EVPN_ENABLED(zvrf));
@ -3768,24 +3818,24 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length,
zvrf_id(zvrf), vni);
continue;
}
if (!zvni->vxlan_if) {
ifp = zvni->vxlan_if;
if (!ifp) {
zlog_err(
"VNI %u hash %p doesn't have intf upon remote VTEP ADD",
zvni->vni, zvni);
continue;
}
zif = ifp->info;
/* If the remote VTEP already exists, or the local VxLAN
* interface is
* not up (should be a transient event), there's nothing more
* to do.
* Otherwise, add and install the entry.
*/
if (zvni_vtep_find(zvni, &vtep_ip))
/* If down or not mapped to a bridge, we're done. */
if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
continue;
if (!if_is_operative(zvni->vxlan_if))
/* If the remote VTEP already exists,
there's nothing more to do. */
if (zvni_vtep_find(zvni, &vtep_ip))
continue;
if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
@ -3839,7 +3889,11 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
if (!ifp_zif)
return -1;
svi_if = ifp_zif->link;
/*
* for a MACVLAN interface the link represents the svi_if
*/
svi_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
ifp_zif->link_ifindex);
if (!svi_if) {
zlog_err("%u:MACVLAN %s(%u) without link information",
ifp->vrf_id, ifp->name, ifp->ifindex);
@ -3847,19 +3901,39 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
}
if (IS_ZEBRA_IF_VLAN(svi_if)) {
/*
* If it is a vlan aware bridge then the link gives the
* bridge information
*/
struct interface *svi_if_link = NULL;
svi_if_zif = svi_if->info;
if (svi_if_zif)
zvni = zvni_map_svi(svi_if, svi_if_zif->link);
if (svi_if_zif) {
svi_if_link = if_lookup_by_index_per_ns(
zebra_ns_lookup(
NS_DEFAULT),
svi_if_zif->link_ifindex);
zvni = zvni_map_svi(svi_if, svi_if_link);
}
} else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {
/*
* If it is a vlan unaware bridge then svi is the bridge
* itself
*/
zvni = zvni_map_svi(svi_if, svi_if);
}
} else if (IS_ZEBRA_IF_VLAN(ifp)) {
struct zebra_if *svi_if_zif =
NULL; /* Zebra daemon specific info for SVI */
struct interface *svi_if_link =
NULL; /* link info for the SVI = bridge info */
svi_if_zif = ifp->info;
if (svi_if_zif)
zvni = zvni_map_svi(ifp, svi_if_zif->link);
svi_if_link =
if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
svi_if_zif->link_ifindex);
if (svi_if_zif && svi_if_link)
zvni = zvni_map_svi(ifp, svi_if_link);
} else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
zvni = zvni_map_svi(ifp, ifp);
}
@ -4141,7 +4215,7 @@ int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags)
vxl->access_vlan, inet_ntoa(vxl->vtep_ip),
zif->brslave_info.bridge_ifindex, chgflags);
/* Removed from bridge? */
/* Removed from bridge? Cleanup and return */
if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
&& (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
/* Delete from client, remove all remote VTEPs */
@ -4150,7 +4224,11 @@ int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags)
zvni_neigh_del_all(zvrf, zvni, 1, 0, DEL_ALL_NEIGH);
zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC);
zvni_vtep_del_all(zvni, 1);
} else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
return 0;
}
/* Handle other changes. */
if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
/* Remove all existing local neighbors and MACs for this VNI
* (including from BGP)
*/
@ -4268,6 +4346,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, int sock,
int advertise;
vni_t vni = 0;
zebra_vni_t *zvni = NULL;
struct interface *ifp = NULL;
s = client->ibuf;
advertise = stream_getc(s);
@ -4318,7 +4397,16 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, int sock,
zvni->advertise_gw_macip = advertise;
zif = zvni->vxlan_if->info;
ifp = zvni->vxlan_if;
if (!ifp)
return 0;
zif = ifp->info;
/* If down or not mapped to a bridge, we're done. */
if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
return 0;
zl2_info = zif->l2info.vxl;
vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan,

View File

@ -114,8 +114,6 @@ struct zebra_mac_t_ {
struct in_addr r_vtep_ip;
} fwd_info;
u_int32_t neigh_refcnt;
/* List of neigh associated with this mac */
struct list *neigh_list;
};