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_encap_types.h"
#include "bgpd/bgp_debug.h" #include "bgpd/bgp_debug.h"
#include "bgpd/bgp_aspath.h" #include "bgpd/bgp_aspath.h"
#include "bgpd/bgp_zebra.h"
#include "bgpd/bgp_nexthop.h"
/* /*
* Definitions and external declarations. * Definitions and external declarations.
@ -1199,6 +1201,13 @@ static int handle_tunnel_ip_change(struct bgp *bgp, struct bgpevpn *vpn,
return 0; 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 /* Need to withdraw type-3 route as the originator IP is part
* of the key. * of the key.
*/ */
@ -2178,6 +2187,71 @@ char *bgp_evpn_label2str(mpls_label_t *label, char *buf, int len)
return buf; 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. * Function to convert evpn route to string.
* NOTE: We don't use prefix2str as the output here is a bit different. * 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); 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. * 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); 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. */ /* Clear "live" flag and see if hash needs to be freed. */
UNSET_FLAG(vpn->flags, VNI_FLAG_LIVE); UNSET_FLAG(vpn->flags, VNI_FLAG_LIVE);
if (!is_vni_configured(vpn)) 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); bgp->vrf_id, vni);
return -1; 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)) if (is_vni_live(vpn))
return 0; return 0;
/* Mark as "live" */ /* Mark as "live" */
SET_FLAG(vpn->flags, VNI_FLAG_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. */ /* Create EVPN type-3 route and schedule for processing. */
build_evpn_type3_prefix(&p, vpn->originator_ip); build_evpn_type3_prefix(&p, vpn->originator_ip);
if (update_evpn_route(bgp, vpn, &p, 0)) { 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); 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; return 0;
} }

View File

@ -28,6 +28,7 @@
extern void bgp_evpn_handle_router_id_update(struct bgp *bgp, int withdraw); 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_label2str(mpls_label_t *label, char *buf, int len);
extern char *bgp_evpn_route2str(struct prefix_evpn *p, 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, extern void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
struct prefix_rd *prd, mpls_label_t *label, struct prefix_rd *prd, mpls_label_t *label,
struct attr *attr, int addpath_encode, 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); struct prefix *p, struct bgp_info *ri);
extern int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi, extern int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi,
struct prefix *p, struct bgp_info *ri); 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, extern int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni,
struct ethaddr *mac, struct ipaddr *ip); struct ethaddr *mac, struct ipaddr *ip);
extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, 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/bgpd.h"
#include "bgpd/bgp_ecommunity.h" #include "bgpd/bgp_ecommunity.h"
#define RT_ADDRSTRLEN 28
/* EVPN prefix lengths. */ /* EVPN prefix lengths. */
#define EVPN_TYPE_2_ROUTE_PREFIXLEN 224 #define EVPN_TYPE_2_ROUTE_PREFIXLEN 224
#define EVPN_TYPE_3_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_REGEXP, "BGP regexp")
DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate") DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate")
DEFINE_MTYPE(BGPD, BGP_ADDR, "BGP own address") 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_REDIST, "BGP redistribution")
DEFINE_MTYPE(BGPD, BGP_FILTER_NAME, "BGP Filter Information") 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_REGEXP)
DECLARE_MTYPE(BGP_AGGREGATE) DECLARE_MTYPE(BGP_AGGREGATE)
DECLARE_MTYPE(BGP_ADDR) DECLARE_MTYPE(BGP_ADDR)
DECLARE_MTYPE(TIP_ADDR)
DECLARE_MTYPE(BGP_REDIST) DECLARE_MTYPE(BGP_REDIST)
DECLARE_MTYPE(BGP_FILTER_NAME) 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 */ static void *bgp_tip_hash_alloc(void *p)
struct bgp_addr { {
struct in_addr addr; const struct in_addr *val = (const struct in_addr *)p;
int refcnt; 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) 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) int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
{ {
struct bgp_addr tmp, *addr; struct bgp_addr tmp, *addr;
struct tip_addr tmp_tip, *tip;
tmp.addr = nh_addr; tmp.addr = nh_addr;
@ -311,6 +387,11 @@ int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
if (addr) if (addr)
return 1; return 1;
tmp_tip.addr = nh_addr;
tip = hash_lookup(bgp->tip_hash, &tmp_tip);
if (tip)
return 1;
return 0; return 0;
} }

View File

@ -66,6 +66,18 @@ struct bgp_nexthop_cache {
struct bgp *bgp; 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 *, extern int bgp_nexthop_lookup(afi_t, struct peer *peer, struct bgp_info *,
int *, int *); int *, int *);
extern void bgp_connected_add(struct bgp *bgp, struct connected *c); 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_scan_vty_init(void);
extern void bgp_address_init(struct bgp *bgp); extern void bgp_address_init(struct bgp *bgp);
extern void bgp_address_destroy(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 */ #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); 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 * make_prefix - make a prefix structure from the path (essentially
* path's node. * 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); 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 */ #endif /* _BGP_NHT_H */

View File

@ -1271,7 +1271,6 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
as_t local_as; as_t local_as;
u_int32_t restart_time; u_int32_t restart_time;
u_char afi_safi_count = 0; u_char afi_safi_count = 0;
struct utsname names;
int adv_addpath_tx = 0; int adv_addpath_tx = 0;
/* Remember current pointer for Opt Parm Len. */ /* Remember current pointer for Opt Parm Len. */
@ -1441,8 +1440,7 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
} }
/* Hostname capability */ /* Hostname capability */
uname(&names); if (cmd_hostname_get()) {
if (names.nodename[0] != '\0') {
SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV); SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP); stream_putc(s, BGP_OPEN_OPT_CAP);
rcapp = stream_get_endp(s); /* Ptr to length placeholder */ 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); stream_putc(s, CAPABILITY_CODE_FQDN);
capp = stream_get_endp(s); capp = stream_get_endp(s);
stream_putc(s, 0); /* dummy len for now */ stream_putc(s, 0); /* dummy len for now */
len = strlen(names.nodename); len = strlen(cmd_hostname_get());
if (len > BGP_MAX_HOSTNAME) if (len > BGP_MAX_HOSTNAME)
len = BGP_MAX_HOSTNAME; len = BGP_MAX_HOSTNAME;
stream_putc(s, len); stream_putc(s, len);
stream_put(s, names.nodename, len); stream_put(s, cmd_hostname_get(), len);
#ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME if (cmd_domainname_get()) {
if ((names.domainname[0] != '\0') len = strlen(cmd_domainname_get());
&& (strcmp(names.domainname, "(none)") != 0)) {
len = strlen(names.domainname);
if (len > BGP_MAX_HOSTNAME) if (len > BGP_MAX_HOSTNAME)
len = BGP_MAX_HOSTNAME; len = BGP_MAX_HOSTNAME;
stream_putc(s, len); stream_putc(s, len);
stream_put(s, names.domainname, len); stream_put(s, cmd_domainname_get(), len);
} else } else
#endif
{
stream_putc(s, 0); /* 0 length */ stream_putc(s, 0); /* 0 length */
}
/* Set the lengths straight */ /* Set the lengths straight */
len = stream_get_endp(s) - rcapp - 1; 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); stream_putc_at(s, capp, len);
if (bgp_debug_neighbor_events(peer)) if (bgp_debug_neighbor_events(peer))
#ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME
zlog_debug( zlog_debug(
"%s Sending hostname cap with hn = %s, dn = %s", "%s Sending hostname cap with hn = %s, dn = %s",
peer->host, names.nodename, names.domainname); peer->host, cmd_hostname_get(),
#else cmd_domainname_get());
zlog_debug("%s Sending hostname cap with hn = %s",
peer->host, names.nodename);
#endif
} }
/* Sending base graceful-restart capability irrespective of the config /* 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? /* Do we need to allocate or free labels?
* Right now, since we only deal with per-prefix labels, it is not * Right now, since we only deal with per-prefix labels, it is not
* necessary * necessary to do this upon changes to best path except if the label
* to do this upon changes to best path except of the label index * index changes
* changes.
*/ */
if (bgp->allocate_mpls_labels[afi][safi]) { if (bgp->allocate_mpls_labels[afi][safi]) {
if (new_select) { 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 /* Unconditionally remove the route from the RIB, without taking
* damping into consideration (eg, because the session went down) * 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) struct peer *peer, afi_t afi, safi_t safi)
{ {
bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi, 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 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; int len;
u_int32_t destination; u_int32_t destination;
char buf[BUFSIZ]; char buf[BUFSIZ];
if (p->family == AF_INET) { if (p->family == AF_INET) {
if (!json) {
len = vty_out(vty, "%s", 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); destination = ntohl(p->u.prefix4.s_addr);
if ((IN_CLASSC(destination) && p->prefixlen == 24) if ((IN_CLASSC(destination) && p->prefixlen == 24)
|| (IN_CLASSB(destination) && p->prefixlen == 16) || (IN_CLASSB(destination) && p->prefixlen == 16)
|| (IN_CLASSA(destination) && p->prefixlen == 8) || (IN_CLASSA(destination) && p->prefixlen == 8)
|| p->u.prefix4.s_addr == 0) { || p->u.prefix4.s_addr == 0) {
/* When mask is natural, mask is not displayed. */ /* When mask is natural,
mask is not displayed. */
} else } else
len += vty_out(vty, "/%d", p->prefixlen); 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) { } else if (p->family == AF_ETHERNET) {
prefix2str(p, buf, PREFIX_STRLEN); prefix2str(p, buf, PREFIX_STRLEN);
len = vty_out(vty, "%s", buf); len = vty_out(vty, "%s", buf);
} else if (p->family == AF_EVPN) { } else if (p->family == AF_EVPN) {
#if defined(HAVE_CUMULUS) #if defined(HAVE_CUMULUS)
if (!json)
len = vty_out(vty, "%s", len = vty_out(vty, "%s",
bgp_evpn_route2str((struct prefix_evpn *)p, buf, bgp_evpn_route2str((struct prefix_evpn *)p,
BUFSIZ)); buf, BUFSIZ));
else
bgp_evpn_route2json((struct prefix_evpn *) p, json);
#else #else
prefix2str(p, buf, PREFIX_STRLEN); prefix2str(p, buf, PREFIX_STRLEN);
len = vty_out(vty, "%s", buf); len = vty_out(vty, "%s", buf);
#endif #endif
} else } else {
if (!json)
len = vty_out(vty, "%s/%d", 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); p->prefixlen);
}
if (!json) {
len = 17 - len; len = 17 - len;
if (len < 1) if (len < 1)
vty_out(vty, "\n%*s", 20, " "); vty_out(vty, "\n%*s", 20, " ");
else else
vty_out(vty, "%*s", len, " "); vty_out(vty, "%*s", len, " ");
} }
}
enum bgp_display_type { enum bgp_display_type {
normal_list, normal_list,
@ -6413,9 +6431,11 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
if (!json_paths) { if (!json_paths) {
/* print prefix and mask */ /* print prefix and mask */
if (!display) if (!display)
route_vty_out_route(p, vty); route_vty_out_route(p, vty, json_path);
else else
vty_out(vty, "%*s", 17, " "); vty_out(vty, "%*s", 17, " ");
} else {
route_vty_out_route(p, vty, json_path);
} }
/* Print attribute */ /* Print attribute */
@ -6711,7 +6731,7 @@ void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
json_net, "addrPrefix", json_net, "addrPrefix",
inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ)); inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ));
else else
route_vty_out_route(p, vty); route_vty_out_route(p, vty, NULL);
/* Print attribute */ /* Print attribute */
if (attr) { if (attr) {
@ -6844,7 +6864,7 @@ void route_vty_out_tag(struct vty *vty, struct prefix *p,
/* print prefix and mask */ /* print prefix and mask */
if (json == NULL) { if (json == NULL) {
if (!display) if (!display)
route_vty_out_route(p, vty); route_vty_out_route(p, vty, NULL);
else else
vty_out(vty, "%*s", 17, " "); vty_out(vty, "%*s", 17, " ");
} }
@ -6959,7 +6979,7 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p,
/* print prefix and mask */ /* print prefix and mask */
if (!display) if (!display)
route_vty_out_route(p, vty); route_vty_out_route(p, vty, NULL);
else else
vty_out(vty, "%*s", 17, " "); 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 */ /* print prefix and mask */
if (!use_json) { if (!use_json) {
if (!display) if (!display)
route_vty_out_route(p, vty); route_vty_out_route(p, vty, NULL);
else else
vty_out(vty, "%*s", 17, " "); 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 */ /* print prefix and mask */
if (!use_json) { if (!use_json) {
if (!display) if (!display)
route_vty_out_route(p, vty); route_vty_out_route(p, vty, NULL);
else else
vty_out(vty, "%*s", 17, " "); 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) #if defined(HAVE_CUMULUS)
char buf3[EVPN_ROUTE_STRLEN]; char buf3[EVPN_ROUTE_STRLEN];
#endif #endif
char prefix_str[BUFSIZ];
int count = 0; int count = 0;
int best = 0; int best = 0;
int suppress = 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_int_add(json, "localLabel", label);
json_object_string_add(json, "prefix", json_object_string_add(json, "prefix",
inet_ntop(p->family, &p->u.prefix, buf2, prefix2str(p, prefix_str,
INET6_ADDRSTRLEN)); sizeof(prefix_str)));
json_object_int_add(json, "prefixlen", p->prefixlen);
} else { } else {
#if defined(HAVE_CUMULUS) #if defined(HAVE_CUMULUS)
if (safi == SAFI_EVPN) if (safi == SAFI_EVPN)

View File

@ -294,6 +294,8 @@ static inline int bgp_fibupd_safi(safi_t safi)
} }
/* Prototypes. */ /* 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_process_queue_init(void);
extern void bgp_route_init(void); extern void bgp_route_init(void);
extern void bgp_route_finish(void); extern void bgp_route_finish(void);

View File

@ -6424,6 +6424,59 @@ DEFUN (show_bgp_vrfs,
return CMD_SUCCESS; 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, DEFUN (show_bgp_memory,
show_bgp_memory_cmd, show_bgp_memory_cmd,
"show [ip] bgp memory", "show [ip] bgp memory",
@ -7528,6 +7581,12 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
"defaultNotSent"); "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 if (filter->plist[FILTER_IN].name
|| filter->dlist[FILTER_IN].name || filter->dlist[FILTER_IN].name
|| filter->aslist[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"); 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 if (filter->plist[FILTER_IN].name
|| filter->dlist[FILTER_IN].name || filter->dlist[FILTER_IN].name
|| filter->aslist[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_cap, "multiprotocolExtensions",
json_multi); 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 */ /* Gracefull Restart */
if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV) if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)
|| CHECK_FLAG(p->cap, || 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 */ /* Hostname capability */
if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_ADV)
|| CHECK_FLAG(p->cap,
PEER_CAP_HOSTNAME_RCV)) {
vty_out(vty, vty_out(vty,
" Hostname Capability:"); " Hostname Capability:");
if (CHECK_FLAG(p->cap,
PEER_CAP_HOSTNAME_ADV)) if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_ADV)) {
vty_out(vty, " advertised"); vty_out(vty,
if (CHECK_FLAG(p->cap, " advertised (name: %s,domain name: %s)",
PEER_CAP_HOSTNAME_RCV)) bgp->peer_self->hostname ?
vty_out(vty, " %sreceived", bgp->peer_self->hostname
CHECK_FLAG( : "n/a",
p->cap, bgp->peer_self->domainname ?
PEER_CAP_HOSTNAME_ADV) bgp->peer_self->domainname
? "and " : "n/a");
: ""); } else {
vty_out(vty, "\n"); 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 */ /* Gracefull Restart */
if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV) if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)
|| CHECK_FLAG(p->cap, || CHECK_FLAG(p->cap,
@ -12264,6 +12379,9 @@ void bgp_vty_init(void)
/* "show [ip] bgp memory" commands. */ /* "show [ip] bgp memory" commands. */
install_element(VIEW_NODE, &show_bgp_memory_cmd); 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. */ /* "show [ip] bgp views" commands. */
install_element(VIEW_NODE, &show_bgp_views_cmd); 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); XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host);
bgp->peer_self->host = bgp->peer_self->host =
XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement"); 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 = list_new();
bgp->peer->cmp = (int (*)(void *, void *))peer_cmp; bgp->peer->cmp = (int (*)(void *, void *))peer_cmp;
bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_same, NULL); 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 = bgp_create(as, name, inst_type);
bgp_router_id_set(bgp, &bgp->router_id_zebra); bgp_router_id_set(bgp, &bgp->router_id_zebra);
bgp_address_init(bgp); bgp_address_init(bgp);
bgp_tip_hash_init(bgp);
bgp_scan_init(bgp); bgp_scan_init(bgp);
*bgp_val = bgp; *bgp_val = bgp;
@ -3069,6 +3085,9 @@ void bgp_instance_down(struct bgp *bgp)
/* Purge network and redistributed routes. */ /* Purge network and redistributed routes. */
bgp_purge_static_redist_routes(bgp); bgp_purge_static_redist_routes(bgp);
/* Cleanup registered nexthops (flags) */
bgp_cleanup_nexthops(bgp);
} }
/* Delete BGP instance. */ /* Delete BGP instance. */
@ -3200,6 +3219,7 @@ void bgp_free(struct bgp *bgp)
bgp_scan_finish(bgp); bgp_scan_finish(bgp);
bgp_address_destroy(bgp); bgp_address_destroy(bgp);
bgp_tip_hash_destroy(bgp);
bgp_evpn_cleanup(bgp); bgp_evpn_cleanup(bgp);

View File

@ -318,6 +318,10 @@ struct bgp {
struct hash *address_hash; 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. */ /* Static route configuration. */
struct bgp_table *route[AFI_MAX][SAFI_MAX]; 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), vty_out(vty, " * %s %s\n", sysid_print(isis->sysid),
unix_hostname()); cmd_hostname_get());
return; return;
} }

View File

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

View File

@ -431,24 +431,6 @@ struct in_addr newprefix2inaddr(u_char *prefix_start, u_char prefix_masklen)
return new_prefix; 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. * Returns the dynamic hostname associated with the passed system ID.
* If no dynamic hostname found then returns formatted 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 */ /* For our system ID return our host name */
if (memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN) == 0) if (memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN) == 0)
return unix_hostname(); return cmd_hostname_get();
dyn = dynhn_find_by_id(sysid); dyn = dynhn_find_by_id(sysid);
if (dyn) if (dyn)

View File

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

View File

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

View File

@ -125,6 +125,23 @@ vector cmdvec = NULL;
/* Host information structure. */ /* Host information structure. */
struct host host; 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. */ /* Standard command node structures. */
static struct cmd_node auth_node = { static struct cmd_node auth_node = {
AUTH_NODE, "Password: ", AUTH_NODE, "Password: ",
@ -475,8 +492,8 @@ static char *zencrypt(const char *passwd)
/* This function write configuration of this host. */ /* This function write configuration of this host. */
static int config_write_host(struct vty *vty) static int config_write_host(struct vty *vty)
{ {
if (host.name) if (cmd_hostname_get())
vty_out(vty, "hostname %s\n", host.name); vty_out(vty, "hostname %s\n", cmd_hostname_get());
if (host.encrypt) { if (host.encrypt) {
if (host.password_encrypt) if (host.password_encrypt)
@ -1411,7 +1428,7 @@ DEFUN (show_version,
"Displays zebra version\n") "Displays zebra version\n")
{ {
vty_out(vty, "%s %s (%s).\n", FRR_FULL_NAME, FRR_VERSION, 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, "%s%s\n", FRR_COPYRIGHT, GIT_INFO);
vty_out(vty, "configured with:\n %s\n", FRR_CONFIG_ARGS); vty_out(vty, "configured with:\n %s\n", FRR_CONFIG_ARGS);
@ -1745,6 +1762,40 @@ DEFUN (show_startup_config,
return CMD_SUCCESS; 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) int cmd_hostname_set(const char *hostname)
{ {
XFREE(MTYPE_HOST, host.name); 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 */ * terminal = -1 -- watchfrr / no logging, but minimal config control */
void cmd_init(int terminal) void cmd_init(int terminal)
{ {
struct utsname names;
if (array_size(node_names) != NODE_TYPE_MAX) if (array_size(node_names) != NODE_TYPE_MAX)
assert(!"Update the CLI node description array!"); assert(!"Update the CLI node description array!");
uname(&names);
qobj_init(); qobj_init();
varhandlers = list_new(); varhandlers = list_new();
@ -2526,7 +2580,15 @@ void cmd_init(int terminal)
cmdvec = vector_init(VECTOR_MIN_SIZE); cmdvec = vector_init(VECTOR_MIN_SIZE);
/* Default host value settings. */ /* 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.password = NULL;
host.enable = NULL; host.enable = NULL;
host.logfile = NULL; host.logfile = NULL;
@ -2579,6 +2641,8 @@ void cmd_init(int terminal)
install_element(CONFIG_NODE, &hostname_cmd); install_element(CONFIG_NODE, &hostname_cmd);
install_element(CONFIG_NODE, &no_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, &frr_version_defaults_cmd);
install_element(CONFIG_NODE, &debug_memstats_cmd); install_element(CONFIG_NODE, &debug_memstats_cmd);
@ -2644,6 +2708,8 @@ void cmd_terminate()
if (host.name) if (host.name)
XFREE(MTYPE_HOST, host.name); XFREE(MTYPE_HOST, host.name);
if (host.domainname)
XFREE(MTYPE_HOST, host.domainname);
if (host.password) if (host.password)
XFREE(MTYPE_HOST, host.password); XFREE(MTYPE_HOST, host.password);
if (host.password_encrypt) if (host.password_encrypt)

View File

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

View File

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

View File

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

View File

@ -2891,21 +2891,9 @@ void vtysh_readline_init(void)
char *vtysh_prompt(void) char *vtysh_prompt(void)
{ {
static struct utsname names;
static char buf[100]; 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; return buf;
} }

View File

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

View File

@ -873,7 +873,8 @@ void if_up(struct interface *ifp)
link_if = ifp; link_if = ifp;
zebra_vxlan_svi_up(ifp, link_if); zebra_vxlan_svi_up(ifp, link_if);
} else if (IS_ZEBRA_IF_VLAN(ifp)) { } 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) if (link_if)
zebra_vxlan_svi_up(ifp, link_if); zebra_vxlan_svi_up(ifp, link_if);
} }
@ -901,7 +902,8 @@ void if_down(struct interface *ifp)
link_if = ifp; link_if = ifp;
zebra_vxlan_svi_down(ifp, link_if); zebra_vxlan_svi_down(ifp, link_if);
} else if (IS_ZEBRA_IF_VLAN(ifp)) { } 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) if (link_if)
zebra_vxlan_svi_down(ifp, 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 * itself
*/ */
if (IS_ZEBRA_IF_VLAN(ifp)) { 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) if (!link_if)
return 0; return 0;
} else if (IS_ZEBRA_IF_BRIDGE(ifp)) } 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; zif->brslave_info.bridge_ifindex = bridge_ifindex;
/* Set up or remove link with master */ /* 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); 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. */ /* In the case of VxLAN, invoke the handler for EVPN. */
if (zif->zif_type == ZEBRA_IF_VXLAN) if (zif->zif_type == ZEBRA_IF_VXLAN)
zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_MASTER_CHANGE); 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) { if (json == NULL) {
vty_out(vty, " Remote VTEP: %s", vty_out(vty, " Remote VTEP: %s",
inet_ntoa(n->r_vtep_ip)); inet_ntoa(n->r_vtep_ip));
vty_out(vty, " State: %s", IS_ZEBRA_NEIGH_ACTIVE(n)
? "Active"
: "Inactive");
} else } else
json_object_string_add(json, "remoteVtep", json_object_string_add(json, "remoteVtep",
inet_ntoa(n->r_vtep_ip)); 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) if (json == NULL)
vty_out(vty, "\n"); 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)) { } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
vty_out(vty, " Auto Mac "); vty_out(vty, " Auto Mac ");
} }
vty_out(vty, " ARP ref: %u\n", mac->neigh_refcnt);
vty_out(vty, "\n");
/* print all the associated neigh */ /* print all the associated neigh */
vty_out(vty, " Neighbors:\n"); vty_out(vty, " Neighbors:\n");
if (!listcount(mac->neigh_list)) 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); memcpy(&n->emac, macaddr, ETH_ALEN);
n->ifindex = ifp->ifindex; n->ifindex = ifp->ifindex;
/* We have a neigh associated to mac increment the refcnt*/
mac->neigh_refcnt++;
if (IS_ZEBRA_DEBUG_VXLAN) if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug( zlog_debug(
"%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s add to BGP", "%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 zebra_l2info_vxlan zl2_info;
struct interface *vlan_if = NULL; struct interface *vlan_if = NULL;
struct interface *vrr_if = NULL; struct interface *vrr_if = NULL;
struct interface *ifp;
/* Add primary SVI MAC*/ /* Add primary SVI MAC*/
zvni = (zebra_vni_t *)backet->data; zvni = (zebra_vni_t *)backet->data;
if (!zvni) if (!zvni)
return; 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; zl2_info = zif->l2info.vxl;
vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan, 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 zebra_l2info_vxlan zl2_info;
struct interface *vlan_if = NULL; struct interface *vlan_if = NULL;
struct interface *vrr_if = NULL; struct interface *vrr_if = NULL;
struct interface *ifp = NULL;
zvni = (zebra_vni_t *)backet->data; zvni = (zebra_vni_t *)backet->data;
if (!zvni) 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)) if (!advertise_gw_macip_enabled(zvrf, zvni))
return; 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; zl2_info = zif->l2info.vxl;
vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan, 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; vlanid_t vid = 0;
zebra_vni_t *zvni; zebra_vni_t *zvni;
if (!br_if)
return NULL;
/* Make sure the linked interface is a bridge. */ /* Make sure the linked interface is a bridge. */
if (!IS_ZEBRA_IF_BRIDGE(br_if)) if (!IS_ZEBRA_IF_BRIDGE(br_if))
return NULL; 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; struct zebra_l2info_vlan *vl;
u_char bridge_vlan_aware; 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 */ /* Determine if bridge is VLAN-aware or not */
zif = br_if->info; zif = br_if->info;
assert(zif); 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, static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac,
int uninstall) int uninstall)
{ {
if (mac->neigh_refcnt) if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) ||
mac->neigh_refcnt--; !list_isempty(mac->neigh_list))
if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) || mac->neigh_refcnt > 0)
return; return;
if (uninstall) if (uninstall)
@ -2853,7 +2877,7 @@ int zebra_vxlan_local_neigh_del(struct interface *ifp,
/* see if the AUTO mac needs to be deleted */ /* see if the AUTO mac needs to be deleted */
if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO) if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
|| !listcount(zmac->neigh_list)) && !listcount(zmac->neigh_list))
zvni_mac_del(zvni, zmac); zvni_mac_del(zvni, zmac);
return 0; return 0;
@ -2872,10 +2896,9 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
zebra_vni_t *zvni; zebra_vni_t *zvni;
zebra_neigh_t *n; zebra_neigh_t *n;
struct zebra_vrf *zvrf; struct zebra_vrf *zvrf;
zebra_mac_t *zmac; zebra_mac_t *zmac, *old_zmac;
char buf[ETHER_ADDR_STRLEN]; char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN]; char buf2[INET6_ADDRSTRLEN];
int send_upd = 1, send_del = 0;
/* We are only interested in neighbors on an SVI that resides on top /* We are only interested in neighbors on an SVI that resides on top
* of a VxLAN bridge. * 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, if (memcmp(n->emac.octet, macaddr->octet,
ETH_ALEN) ETH_ALEN)
== 0) { == 0) {
if (n->ifindex == ifp->ifindex) /* Update any params and return - client doesn't
/* we're not interested in whatever has * care about a purely local change.
* 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.
*/ */
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) } else if (ext_learned)
/* The neighbor is remote and that is the notification we got. /* 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); UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
n->r_vtep_ip.s_addr = 0; n->r_vtep_ip.s_addr = 0;
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
n->ifindex = ifp->ifindex;
} }
} else { } else {
n = zvni_neigh_add(zvni, ip, macaddr); 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); ifp->name, ifp->ifindex, zvni->vni);
return -1; 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 "local" forwarding info. */
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
n->ifindex = ifp->ifindex; n->ifindex = ifp->ifindex;
}
/* Before we program this in BGP, we need to check if MAC is locally /* Before we program this in BGP, we need to check if MAC is locally
* learnt as well */ * learnt as well */
@ -2989,8 +3024,7 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
return 0; return 0;
} }
/* Inform BGP if required. */ /* Inform BGP. */
if (send_upd) {
if (IS_ZEBRA_DEBUG_VXLAN) if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug( zlog_debug(
"%u: neigh %s (MAC %s) is now ACTIVE on VNI %u", "%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); macaddr, 0);
} }
return 0;
}
/* /*
* Handle message from client to delete a remote MACIP for a VNI. * 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; u_short l = 0, ipa_len;
char buf[ETHER_ADDR_STRLEN]; char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN]; char buf1[INET6_ADDRSTRLEN];
struct interface *ifp = NULL;
struct zebra_if *zif = NULL;
s = client->ibuf; 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); zvrf_id(zvrf), vni);
continue; continue;
} }
if (!zvni->vxlan_if) { ifp = zvni->vxlan_if;
if (!ifp) {
zlog_err( zlog_err(
"VNI %u hash %p doesn't have intf upon remote MACIP DEL", "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
vni, zvni); vni, zvni);
continue; 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 /* The remote VTEP specified is normally expected to exist, but
* it is * 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)) if (!zvni_vtep_find(zvni, &vtep_ip))
continue; 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); mac = zvni_mac_lookup(zvni, &macaddr);
if (ipa_len) if (ipa_len)
n = zvni_neigh_lookup(zvni, &ip); 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, zvni_process_neigh_on_remote_mac_del(zvrf, zvni,
mac); mac);
if (!mac->neigh_refcnt) { if (list_isempty(mac->neigh_list)) {
zvni_mac_uninstall(zvni, mac, 0); zvni_mac_uninstall(zvni, mac, 0);
zvni_mac_del(zvni, mac); zvni_mac_del(zvni, mac);
} else } 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 buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN]; char buf1[INET6_ADDRSTRLEN];
u_char sticky; u_char sticky;
struct interface *ifp = NULL;
struct zebra_if *zif = NULL;
assert(EVPN_ENABLED(zvrf)); 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); zvrf_id(zvrf), vni);
continue; continue;
} }
if (!zvni->vxlan_if) { ifp = zvni->vxlan_if;
if (!ifp) {
zlog_err( zlog_err(
"VNI %u hash %p doesn't have intf upon remote MACIP add", "VNI %u hash %p doesn't have intf upon remote MACIP add",
vni, zvni); vni, zvni);
continue; continue;
} }
/* If the local VxLAN interface is not up (should be a transient zif = ifp->info;
* event), there's nothing more to do.
*/ /* If down or not mapped to a bridge, we're done. */
if (!if_is_operative(zvni->vxlan_if)) if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
continue; continue;
/* The remote VTEP specified should normally exist, but it is /* 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? */ /* Is this MAC created for a MACIP? */
if (ipa_len) if (ipa_len)
SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); 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. */ /* 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; return -1;
} }
/* New neighbor referring to this MAC. */
mac->neigh_refcnt++;
} else if (memcmp(&n->emac, &macaddr, sizeof(macaddr)) } else if (memcmp(&n->emac, &macaddr, sizeof(macaddr))
!= 0) { != 0) {
/* MAC change, update ref counts for old and new /* MAC change, update neigh list for old and new
* MAC. */ * mac */
old_mac = zvni_mac_lookup(zvni, &n->emac); 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); zvni_deref_ip2mac(zvni, old_mac, 1);
mac->neigh_refcnt++; }
listnode_add_sort(mac->neigh_list, n);
memcpy(&n->emac, &macaddr, ETH_ALEN); 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; struct in_addr vtep_ip;
zebra_vni_t *zvni; zebra_vni_t *zvni;
zebra_vtep_t *zvtep; zebra_vtep_t *zvtep;
struct interface *ifp;
struct zebra_if *zif;
s = client->ibuf; s = client->ibuf;
@ -3713,6 +3749,18 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length,
continue; 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 /* If the remote VTEP does not exist, there's nothing more to
* do. * do.
* Otherwise, uninstall any remote MACs pointing to this VTEP * 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; vni_t vni;
struct in_addr vtep_ip; struct in_addr vtep_ip;
zebra_vni_t *zvni; zebra_vni_t *zvni;
struct interface *ifp;
struct zebra_if *zif;
assert(EVPN_ENABLED(zvrf)); 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); zvrf_id(zvrf), vni);
continue; continue;
} }
if (!zvni->vxlan_if) {
ifp = zvni->vxlan_if;
if (!ifp) {
zlog_err( zlog_err(
"VNI %u hash %p doesn't have intf upon remote VTEP ADD", "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
zvni->vni, zvni); zvni->vni, zvni);
continue; continue;
} }
zif = ifp->info;
/* If the remote VTEP already exists, or the local VxLAN /* If down or not mapped to a bridge, we're done. */
* interface is if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
* 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))
continue; 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; continue;
if (zvni_vtep_add(zvni, &vtep_ip) == NULL) { 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) if (!ifp_zif)
return -1; 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) { if (!svi_if) {
zlog_err("%u:MACVLAN %s(%u) without link information", zlog_err("%u:MACVLAN %s(%u) without link information",
ifp->vrf_id, ifp->name, ifp->ifindex); 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 (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; svi_if_zif = svi_if->info;
if (svi_if_zif) if (svi_if_zif) {
zvni = zvni_map_svi(svi_if, svi_if_zif->link); 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)) { } 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); zvni = zvni_map_svi(svi_if, svi_if);
} }
} else if (IS_ZEBRA_IF_VLAN(ifp)) { } else if (IS_ZEBRA_IF_VLAN(ifp)) {
struct zebra_if *svi_if_zif = struct zebra_if *svi_if_zif =
NULL; /* Zebra daemon specific info for SVI */ 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; svi_if_zif = ifp->info;
if (svi_if_zif) svi_if_link =
zvni = zvni_map_svi(ifp, svi_if_zif->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)) { } else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
zvni = zvni_map_svi(ifp, 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), vxl->access_vlan, inet_ntoa(vxl->vtep_ip),
zif->brslave_info.bridge_ifindex, chgflags); zif->brslave_info.bridge_ifindex, chgflags);
/* Removed from bridge? */ /* Removed from bridge? Cleanup and return */
if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE) if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
&& (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) { && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
/* Delete from client, remove all remote VTEPs */ /* 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_neigh_del_all(zvrf, zvni, 1, 0, DEL_ALL_NEIGH);
zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC); zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC);
zvni_vtep_del_all(zvni, 1); 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 /* Remove all existing local neighbors and MACs for this VNI
* (including from BGP) * (including from BGP)
*/ */
@ -4268,6 +4346,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, int sock,
int advertise; int advertise;
vni_t vni = 0; vni_t vni = 0;
zebra_vni_t *zvni = NULL; zebra_vni_t *zvni = NULL;
struct interface *ifp = NULL;
s = client->ibuf; s = client->ibuf;
advertise = stream_getc(s); advertise = stream_getc(s);
@ -4318,7 +4397,16 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, int sock,
zvni->advertise_gw_macip = advertise; 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; zl2_info = zif->l2info.vxl;
vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan, 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; struct in_addr r_vtep_ip;
} fwd_info; } fwd_info;
u_int32_t neigh_refcnt;
/* List of neigh associated with this mac */ /* List of neigh associated with this mac */
struct list *neigh_list; struct list *neigh_list;
}; };