mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 07:21:59 +00:00
commit
14f6aefe43
164
bgpd/bgp_evpn.c
164
bgpd/bgp_evpn.c
@ -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.
|
||||
*/
|
||||
@ -1431,7 +1440,7 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp,
|
||||
if (is_route_matching_for_vni(bgp, vpn, ri)) {
|
||||
if (install)
|
||||
ret = install_evpn_route_entry(
|
||||
bgp, vpn, evp, ri);
|
||||
bgp, vpn, evp, ri);
|
||||
else
|
||||
ret = uninstall_evpn_route_entry(
|
||||
bgp, vpn, evp, ri);
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
1149
bgpd/bgp_evpn_vty.c
1149
bgpd/bgp_evpn_vty.c
File diff suppressed because it is too large
Load Diff
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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.
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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,46 +6269,65 @@ 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) {
|
||||
len = vty_out(vty, "%s",
|
||||
inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ));
|
||||
destination = ntohl(p->u.prefix4.s_addr);
|
||||
if (!json) {
|
||||
len = vty_out(vty, "%s",
|
||||
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. */
|
||||
} else
|
||||
len += vty_out(vty, "/%d", p->prefixlen);
|
||||
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. */
|
||||
} 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)
|
||||
len = vty_out(vty, "%s",
|
||||
bgp_evpn_route2str((struct prefix_evpn *)p, buf,
|
||||
BUFSIZ));
|
||||
if (!json)
|
||||
len = vty_out(vty, "%s",
|
||||
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
|
||||
len = vty_out(vty, "%s/%d",
|
||||
inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
|
||||
p->prefixlen);
|
||||
} else {
|
||||
if (!json)
|
||||
len = vty_out(vty, "%s/%d",
|
||||
inet_ntop(p->family, &p->u.prefix, buf,
|
||||
BUFSIZ),
|
||||
p->prefixlen);
|
||||
}
|
||||
|
||||
len = 17 - len;
|
||||
if (len < 1)
|
||||
vty_out(vty, "\n%*s", 20, " ");
|
||||
else
|
||||
vty_out(vty, "%*s", len, " ");
|
||||
if (!json) {
|
||||
len = 17 - len;
|
||||
if (len < 1)
|
||||
vty_out(vty, "\n%*s", 20, " ");
|
||||
else
|
||||
vty_out(vty, "%*s", len, " ");
|
||||
}
|
||||
}
|
||||
|
||||
enum bgp_display_type {
|
||||
@ -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)
|
||||
|
@ -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);
|
||||
|
150
bgpd/bgp_vty.c
150
bgpd/bgp_vty.c
@ -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,
|
||||
" 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");
|
||||
" 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);
|
||||
|
||||
|
20
bgpd/bgpd.c
20
bgpd/bgpd.c
@ -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);
|
||||
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
11
lib/vty.c
11
lib/vty.c
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
/* 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);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
@ -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,17 +3006,11 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
|
||||
ifp->name, ifp->ifindex, zvni->vni);
|
||||
return -1;
|
||||
}
|
||||
/* Set "local" forwarding info. */
|
||||
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
|
||||
n->ifindex = ifp->ifindex;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) {
|
||||
@ -2989,23 +3024,20 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Inform BGP if required. */
|
||||
if (send_upd) {
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug(
|
||||
"%u: neigh %s (MAC %s) is now ACTIVE on VNI %u",
|
||||
ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
|
||||
prefix_mac2str(macaddr, buf, sizeof(buf)),
|
||||
zvni->vni);
|
||||
/* Inform BGP. */
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug(
|
||||
"%u: neigh %s (MAC %s) is now ACTIVE on VNI %u",
|
||||
ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
|
||||
prefix_mac2str(macaddr, buf, sizeof(buf)),
|
||||
zvni->vni);
|
||||
|
||||
ZEBRA_NEIGH_SET_ACTIVE(n);
|
||||
return zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip,
|
||||
macaddr, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
ZEBRA_NEIGH_SET_ACTIVE(n);
|
||||
return zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip,
|
||||
macaddr, 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*/
|
||||
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,
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user