mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 06:50:17 +00:00
Merge branch 'master' into frr-bgp_cli
This commit is contained in:
commit
2531163802
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,6 +7,7 @@
|
||||
/config.status
|
||||
/config.guess
|
||||
/config.sub
|
||||
/config.version
|
||||
/ltmain.sh
|
||||
/stamp-h
|
||||
/stamp-h[0-9]*
|
||||
|
16
Makefile.am
16
Makefile.am
@ -4,6 +4,7 @@ AUTOMAKE_OPTIONS = subdir-objects 1.12
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
AM_CFLAGS = \
|
||||
$(UNWIND_CFLAGS) \
|
||||
$(SAN_FLAGS) \
|
||||
$(WERROR) \
|
||||
# end
|
||||
@ -18,6 +19,10 @@ AM_LDFLAGS = \
|
||||
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -DCONFDATE=$(CONFDATE)
|
||||
LIBCAP = @LIBCAP@
|
||||
|
||||
AR_FLAGS = @AR_FLAGS@
|
||||
ARFLAGS = @ARFLAGS@
|
||||
RANLIB = @RANLIB@
|
||||
|
||||
# these two targets are provided to easily grab autoconf/Makefile variables
|
||||
# you can use either:
|
||||
# eval `make VARFD=3 shvar-CFLAGS 3>&1 1>&2`
|
||||
@ -77,6 +82,7 @@ var-%:
|
||||
EXTRA_DIST =
|
||||
BUILT_SOURCES =
|
||||
CLEANFILES =
|
||||
DISTCLEANFILES =
|
||||
|
||||
examplesdir = $(exampledir)
|
||||
|
||||
@ -156,6 +162,7 @@ EXTRA_DIST += \
|
||||
README.md \
|
||||
m4/README.txt \
|
||||
m4/libtool-whole-archive.patch \
|
||||
config.version \
|
||||
\
|
||||
python/clidef.py \
|
||||
python/clippy/__init__.py \
|
||||
@ -210,6 +217,15 @@ EXTRA_DIST += \
|
||||
|
||||
noinst_HEADERS += defaults.h
|
||||
|
||||
clean-local: clean-python
|
||||
.PHONY: clean-python
|
||||
clean-python:
|
||||
find -name __pycache__ -o -name .pytest_cache | xargs rm -rf
|
||||
find -name "*.pyc" -o -name "*_clippy.c" | xargs rm -f
|
||||
|
||||
redistclean:
|
||||
$(MAKE) distclean CONFIG_CLEAN_FILES="$(filter-out $(EXTRA_DIST), $(CONFIG_CLEAN_FILES))"
|
||||
|
||||
indent:
|
||||
tools/indent.py `find sharpd bgpd eigrpd include isisd lib nhrpd ospf6d ospfd pimd qpb ripd vtysh zebra -name '*.[ch]' | grep -v include/linux`
|
||||
|
||||
|
@ -32,7 +32,7 @@ THE SOFTWARE.
|
||||
#define CONFIG_NO 1
|
||||
#define CONFIG_YES 2
|
||||
|
||||
/* babeld interface informations */
|
||||
/* babeld interface information */
|
||||
struct babel_interface {
|
||||
unsigned short flags; /* see below */
|
||||
unsigned short cost;
|
||||
|
@ -385,7 +385,7 @@ show_babel_main_configuration (struct vty *vty)
|
||||
vty_out (vty,
|
||||
"state file = %s\n"
|
||||
"configuration file = %s\n"
|
||||
"protocol informations:\n"
|
||||
"protocol information:\n"
|
||||
" multicast address = %s\n"
|
||||
" port = %d\n"
|
||||
"vty address = %s\n"
|
||||
|
17
bfdd/bfd.c
17
bfdd/bfd.c
@ -861,15 +861,10 @@ static struct hash *bfd_vrf_hash;
|
||||
static struct hash *bfd_iface_hash;
|
||||
|
||||
static unsigned int bfd_id_hash_do(void *p);
|
||||
static int bfd_id_hash_cmp(const void *n1, const void *n2);
|
||||
static unsigned int bfd_shop_hash_do(void *p);
|
||||
static int bfd_shop_hash_cmp(const void *n1, const void *n2);
|
||||
static unsigned int bfd_mhop_hash_do(void *p);
|
||||
static int bfd_mhop_hash_cmp(const void *n1, const void *n2);
|
||||
static unsigned int bfd_vrf_hash_do(void *p);
|
||||
static int bfd_vrf_hash_cmp(const void *n1, const void *n2);
|
||||
static unsigned int bfd_iface_hash_do(void *p);
|
||||
static int bfd_iface_hash_cmp(const void *n1, const void *n2);
|
||||
|
||||
static void _shop_key(struct bfd_session *bs, const struct bfd_shop_key *shop);
|
||||
static void _shop_key2(struct bfd_session *bs, const struct bfd_shop_key *shop);
|
||||
@ -889,7 +884,7 @@ static unsigned int bfd_id_hash_do(void *p)
|
||||
return jhash_1word(bs->discrs.my_discr, 0);
|
||||
}
|
||||
|
||||
static int bfd_id_hash_cmp(const void *n1, const void *n2)
|
||||
static bool bfd_id_hash_cmp(const void *n1, const void *n2)
|
||||
{
|
||||
const struct bfd_session *bs1 = n1, *bs2 = n2;
|
||||
|
||||
@ -904,7 +899,7 @@ static unsigned int bfd_shop_hash_do(void *p)
|
||||
return jhash(&bs->shop, sizeof(bs->shop), 0);
|
||||
}
|
||||
|
||||
static int bfd_shop_hash_cmp(const void *n1, const void *n2)
|
||||
static bool bfd_shop_hash_cmp(const void *n1, const void *n2)
|
||||
{
|
||||
const struct bfd_session *bs1 = n1, *bs2 = n2;
|
||||
|
||||
@ -919,7 +914,7 @@ static unsigned int bfd_mhop_hash_do(void *p)
|
||||
return jhash(&bs->mhop, sizeof(bs->mhop), 0);
|
||||
}
|
||||
|
||||
static int bfd_mhop_hash_cmp(const void *n1, const void *n2)
|
||||
static bool bfd_mhop_hash_cmp(const void *n1, const void *n2)
|
||||
{
|
||||
const struct bfd_session *bs1 = n1, *bs2 = n2;
|
||||
|
||||
@ -934,7 +929,7 @@ static unsigned int bfd_vrf_hash_do(void *p)
|
||||
return jhash_1word(vrf->vrf_id, 0);
|
||||
}
|
||||
|
||||
static int bfd_vrf_hash_cmp(const void *n1, const void *n2)
|
||||
static bool bfd_vrf_hash_cmp(const void *n1, const void *n2)
|
||||
{
|
||||
const struct bfd_vrf *v1 = n1, *v2 = n2;
|
||||
|
||||
@ -949,7 +944,7 @@ static unsigned int bfd_iface_hash_do(void *p)
|
||||
return string_hash_make(iface->ifname);
|
||||
}
|
||||
|
||||
static int bfd_iface_hash_cmp(const void *n1, const void *n2)
|
||||
static bool bfd_iface_hash_cmp(const void *n1, const void *n2)
|
||||
{
|
||||
const struct bfd_iface *i1 = n1, *i2 = n2;
|
||||
|
||||
@ -1045,7 +1040,7 @@ struct bfd_session *bfd_mhop_lookup(struct bfd_mhop_key mhop)
|
||||
|
||||
_mhop_key(&bs, &mhop);
|
||||
|
||||
return hash_lookup(bfd_shop_hash, &bs);
|
||||
return hash_lookup(bfd_mhop_hash, &bs);
|
||||
}
|
||||
|
||||
struct bfd_vrf *bfd_vrf_lookup(int vrf_id)
|
||||
|
@ -90,7 +90,7 @@ DEFUN_NOSH(bfd_enter, bfd_enter_cmd, "bfd", "Configure BFD peers\n")
|
||||
|
||||
DEFUN_NOSH(
|
||||
bfd_peer_enter, bfd_peer_enter_cmd,
|
||||
"peer <A.B.C.D|X:X::X:X> [{multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]",
|
||||
"peer <A.B.C.D|X:X::X:X> [{[multihop] local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]",
|
||||
PEER_STR PEER_IPV4_STR PEER_IPV6_STR
|
||||
MHOP_STR
|
||||
LOCAL_STR LOCAL_IPV4_STR LOCAL_IPV6_STR
|
||||
|
@ -104,8 +104,8 @@ bgp_route.[hc]:
|
||||
looking for data in hash table, and putting there if missing, refcnt
|
||||
using pointer to existing data
|
||||
many validity checks
|
||||
get new struct bgp_info (10 words/40 bytes)
|
||||
call bgp_info_add with rn and bgp_info
|
||||
get new struct bgp_path_info
|
||||
call bgp_path_info_add with rn and bgp_path_info
|
||||
call bgp_process
|
||||
|
||||
bgp_routemap.c
|
||||
@ -149,7 +149,7 @@ bgpd.c
|
||||
Question: How much memory does quagga's bgpd use as a function of
|
||||
state received from peers?
|
||||
|
||||
It seems that a struct bgp_info is kept for each prefix. The "struct
|
||||
It seems that a struct bgp_path_info is kept for each prefix. The "struct
|
||||
attr *" is interned, and variables within that are interned. So, 40
|
||||
bytes are kept per received prefix, plus interned shared values. This
|
||||
could be 36 if 'int suppress' where changed to a u_char and moved to
|
||||
|
@ -71,7 +71,7 @@ unsigned int baa_hash_key(void *p)
|
||||
return attrhash_key_make(baa->attr);
|
||||
}
|
||||
|
||||
int baa_hash_cmp(const void *p1, const void *p2)
|
||||
bool baa_hash_cmp(const void *p1, const void *p2)
|
||||
{
|
||||
const struct bgp_advertise_attr *baa1 = p1;
|
||||
const struct bgp_advertise_attr *baa2 = p2;
|
||||
@ -90,9 +90,9 @@ struct bgp_advertise *bgp_advertise_new(void)
|
||||
|
||||
void bgp_advertise_free(struct bgp_advertise *adv)
|
||||
{
|
||||
if (adv->binfo)
|
||||
bgp_info_unlock(
|
||||
adv->binfo); /* bgp_advertise bgp_info reference */
|
||||
if (adv->pathi)
|
||||
/* bgp_advertise bgp_path_info reference */
|
||||
bgp_path_info_unlock(adv->pathi);
|
||||
XFREE(MTYPE_BGP_ADVERTISE, adv);
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ struct bgp_advertise {
|
||||
struct bgp_advertise_attr *baa;
|
||||
|
||||
/* BGP info. */
|
||||
struct bgp_info *binfo;
|
||||
struct bgp_path_info *pathi;
|
||||
};
|
||||
|
||||
/* BGP adjacency out. */
|
||||
@ -113,7 +113,7 @@ struct bgp_synchronize {
|
||||
};
|
||||
|
||||
/* BGP adjacency linked list. */
|
||||
#define BGP_INFO_ADD(N, A, TYPE) \
|
||||
#define BGP_PATH_INFO_ADD(N, A, TYPE) \
|
||||
do { \
|
||||
(A)->prev = NULL; \
|
||||
(A)->next = (N)->TYPE; \
|
||||
@ -122,7 +122,7 @@ struct bgp_synchronize {
|
||||
(N)->TYPE = (A); \
|
||||
} while (0)
|
||||
|
||||
#define BGP_INFO_DEL(N, A, TYPE) \
|
||||
#define BGP_PATH_INFO_DEL(N, A, TYPE) \
|
||||
do { \
|
||||
if ((A)->next) \
|
||||
(A)->next->prev = (A)->prev; \
|
||||
@ -132,10 +132,10 @@ struct bgp_synchronize {
|
||||
(N)->TYPE = (A)->next; \
|
||||
} while (0)
|
||||
|
||||
#define BGP_ADJ_IN_ADD(N,A) BGP_INFO_ADD(N,A,adj_in)
|
||||
#define BGP_ADJ_IN_DEL(N,A) BGP_INFO_DEL(N,A,adj_in)
|
||||
#define BGP_ADJ_OUT_ADD(N,A) BGP_INFO_ADD(N,A,adj_out)
|
||||
#define BGP_ADJ_OUT_DEL(N,A) BGP_INFO_DEL(N,A,adj_out)
|
||||
#define BGP_ADJ_IN_ADD(N, A) BGP_PATH_INFO_ADD(N, A, adj_in)
|
||||
#define BGP_ADJ_IN_DEL(N, A) BGP_PATH_INFO_DEL(N, A, adj_in)
|
||||
#define BGP_ADJ_OUT_ADD(N, A) BGP_PATH_INFO_ADD(N, A, adj_out)
|
||||
#define BGP_ADJ_OUT_DEL(N, A) BGP_PATH_INFO_DEL(N, A, adj_out)
|
||||
|
||||
#define BGP_ADV_FIFO_ADD(F, N) \
|
||||
do { \
|
||||
@ -177,7 +177,7 @@ extern void bgp_adj_in_remove(struct bgp_node *, struct bgp_adj_in *);
|
||||
extern void bgp_sync_init(struct peer *);
|
||||
extern void bgp_sync_delete(struct peer *);
|
||||
extern unsigned int baa_hash_key(void *p);
|
||||
extern int baa_hash_cmp(const void *p1, const void *p2);
|
||||
extern bool baa_hash_cmp(const void *p1, const void *p2);
|
||||
extern void bgp_advertise_add(struct bgp_advertise_attr *baa,
|
||||
struct bgp_advertise *adv);
|
||||
extern struct bgp_advertise *bgp_advertise_new(void);
|
||||
|
@ -1726,23 +1726,23 @@ struct aspath *aspath_reconcile_as4(struct aspath *aspath,
|
||||
/* Compare leftmost AS value for MED check. If as1's leftmost AS and
|
||||
as2's leftmost AS is same return 1. (confederation as-path
|
||||
only). */
|
||||
int aspath_cmp_left_confed(const struct aspath *aspath1,
|
||||
const struct aspath *aspath2)
|
||||
bool aspath_cmp_left_confed(const struct aspath *aspath1,
|
||||
const struct aspath *aspath2)
|
||||
{
|
||||
if (!(aspath1 && aspath2))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (!(aspath1->segments && aspath2->segments))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if ((aspath1->segments->type != AS_CONFED_SEQUENCE)
|
||||
|| (aspath2->segments->type != AS_CONFED_SEQUENCE))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (aspath1->segments->as[0] == aspath2->segments->as[0])
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Delete all AS_CONFED_SEQUENCE/SET segments from aspath.
|
||||
@ -2008,7 +2008,7 @@ unsigned int aspath_key_make(void *p)
|
||||
}
|
||||
|
||||
/* If two aspath have same value then return 1 else return 0 */
|
||||
int aspath_cmp(const void *arg1, const void *arg2)
|
||||
bool aspath_cmp(const void *arg1, const void *arg2)
|
||||
{
|
||||
const struct assegment *seg1 = ((const struct aspath *)arg1)->segments;
|
||||
const struct assegment *seg2 = ((const struct aspath *)arg2)->segments;
|
||||
@ -2016,18 +2016,18 @@ int aspath_cmp(const void *arg1, const void *arg2)
|
||||
while (seg1 || seg2) {
|
||||
int i;
|
||||
if ((!seg1 && seg2) || (seg1 && !seg2))
|
||||
return 0;
|
||||
return false;
|
||||
if (seg1->type != seg2->type)
|
||||
return 0;
|
||||
return false;
|
||||
if (seg1->length != seg2->length)
|
||||
return 0;
|
||||
return false;
|
||||
for (i = 0; i < seg1->length; i++)
|
||||
if (seg1->as[i] != seg2->as[i])
|
||||
return 0;
|
||||
return false;
|
||||
seg1 = seg1->next;
|
||||
seg2 = seg2->next;
|
||||
}
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* AS path hash initialize. */
|
||||
|
@ -85,9 +85,10 @@ extern struct aspath *aspath_filter_exclude(struct aspath *, struct aspath *);
|
||||
extern struct aspath *aspath_add_seq_n(struct aspath *, as_t, unsigned);
|
||||
extern struct aspath *aspath_add_seq(struct aspath *, as_t);
|
||||
extern struct aspath *aspath_add_confed_seq(struct aspath *, as_t);
|
||||
extern int aspath_cmp(const void *, const void *);
|
||||
extern bool aspath_cmp(const void *as1, const void *as2);
|
||||
extern int aspath_cmp_left(const struct aspath *, const struct aspath *);
|
||||
extern int aspath_cmp_left_confed(const struct aspath *, const struct aspath *);
|
||||
extern bool aspath_cmp_left_confed(const struct aspath *as1,
|
||||
const struct aspath *as2xs);
|
||||
extern struct aspath *aspath_delete_confed_seq(struct aspath *);
|
||||
extern struct aspath *aspath_empty(void);
|
||||
extern struct aspath *aspath_empty_get(void);
|
||||
|
@ -146,7 +146,7 @@ static unsigned int cluster_hash_key_make(void *p)
|
||||
return jhash(cluster->list, cluster->length, 0);
|
||||
}
|
||||
|
||||
static int cluster_hash_cmp(const void *p1, const void *p2)
|
||||
static bool cluster_hash_cmp(const void *p1, const void *p2)
|
||||
{
|
||||
const struct cluster_list *cluster1 = p1;
|
||||
const struct cluster_list *cluster2 = p2;
|
||||
@ -355,7 +355,7 @@ static unsigned int encap_hash_key_make(void *p)
|
||||
return jhash(encap->value, encap->length, 0);
|
||||
}
|
||||
|
||||
static int encap_hash_cmp(const void *p1, const void *p2)
|
||||
static bool encap_hash_cmp(const void *p1, const void *p2)
|
||||
{
|
||||
return encap_same((const struct bgp_attr_encap_subtlv *)p1,
|
||||
(const struct bgp_attr_encap_subtlv *)p2);
|
||||
@ -441,7 +441,7 @@ static unsigned int transit_hash_key_make(void *p)
|
||||
return jhash(transit->val, transit->length, 0);
|
||||
}
|
||||
|
||||
static int transit_hash_cmp(const void *p1, const void *p2)
|
||||
static bool transit_hash_cmp(const void *p1, const void *p2)
|
||||
{
|
||||
const struct transit *transit1 = p1;
|
||||
const struct transit *transit2 = p2;
|
||||
@ -527,7 +527,7 @@ unsigned int attrhash_key_make(void *p)
|
||||
return key;
|
||||
}
|
||||
|
||||
int attrhash_cmp(const void *p1, const void *p2)
|
||||
bool attrhash_cmp(const void *p1, const void *p2)
|
||||
{
|
||||
const struct attr *attr1 = p1;
|
||||
const struct attr *attr2 = p2;
|
||||
@ -565,10 +565,10 @@ int attrhash_cmp(const void *p1, const void *p2)
|
||||
&& overlay_index_same(attr1, attr2)
|
||||
&& attr1->nh_ifindex == attr2->nh_ifindex
|
||||
&& attr1->nh_lla_ifindex == attr2->nh_lla_ifindex)
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void attrhash_init(void)
|
||||
@ -723,8 +723,10 @@ struct attr *bgp_attr_default_set(struct attr *attr, uint8_t origin)
|
||||
/* Create the attributes for an aggregate */
|
||||
struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin,
|
||||
struct aspath *aspath,
|
||||
struct community *community, int as_set,
|
||||
uint8_t atomic_aggregate)
|
||||
struct community *community,
|
||||
struct ecommunity *ecommunity,
|
||||
struct lcommunity *lcommunity,
|
||||
int as_set, uint8_t atomic_aggregate)
|
||||
{
|
||||
struct attr attr;
|
||||
struct attr *new;
|
||||
@ -760,6 +762,16 @@ struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin,
|
||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
|
||||
}
|
||||
|
||||
if (ecommunity) {
|
||||
attr.ecommunity = ecommunity;
|
||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
|
||||
}
|
||||
|
||||
if (lcommunity) {
|
||||
attr.lcommunity = lcommunity;
|
||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
|
||||
}
|
||||
|
||||
if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
|
||||
bgp_attr_add_gshut_community(&attr);
|
||||
}
|
||||
@ -837,7 +849,7 @@ void bgp_attr_undup(struct attr *new, struct attr *old)
|
||||
aspath_free(new->aspath);
|
||||
|
||||
if (new->community != old->community)
|
||||
community_free(new->community);
|
||||
community_free(&new->community);
|
||||
|
||||
if (new->ecommunity != old->ecommunity)
|
||||
ecommunity_free(&new->ecommunity);
|
||||
@ -875,11 +887,8 @@ void bgp_attr_flush(struct attr *attr)
|
||||
aspath_free(attr->aspath);
|
||||
attr->aspath = NULL;
|
||||
}
|
||||
if (attr->community && !attr->community->refcnt) {
|
||||
community_free(attr->community);
|
||||
attr->community = NULL;
|
||||
}
|
||||
|
||||
if (attr->community && !attr->community->refcnt)
|
||||
community_free(&attr->community);
|
||||
if (attr->ecommunity && !attr->ecommunity->refcnt)
|
||||
ecommunity_free(&attr->ecommunity);
|
||||
if (attr->lcommunity && !attr->lcommunity->refcnt)
|
||||
@ -1688,7 +1697,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
|
||||
* - for consistency in rx processing
|
||||
*
|
||||
* The following comment is to signal GCC this intention
|
||||
* and supress the warning
|
||||
* and suppress the warning
|
||||
*/
|
||||
/* FALLTHRU */
|
||||
case BGP_ATTR_NHLEN_IPV4:
|
||||
@ -2615,7 +2624,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If hard error occured immediately return to the caller. */
|
||||
/* If hard error occurred immediately return to the caller. */
|
||||
if (ret == BGP_ATTR_PARSE_ERROR) {
|
||||
flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR,
|
||||
"%s: Attribute %s, parse error", peer->host,
|
||||
|
@ -272,10 +272,13 @@ extern void bgp_attr_unintern_sub(struct attr *);
|
||||
extern void bgp_attr_unintern(struct attr **);
|
||||
extern void bgp_attr_flush(struct attr *);
|
||||
extern struct attr *bgp_attr_default_set(struct attr *attr, uint8_t);
|
||||
extern struct attr *bgp_attr_aggregate_intern(struct bgp *, uint8_t,
|
||||
struct aspath *,
|
||||
struct community *, int as_set,
|
||||
uint8_t);
|
||||
extern struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin,
|
||||
struct aspath *aspath,
|
||||
struct community *community,
|
||||
struct ecommunity *ecommunity,
|
||||
struct lcommunity *lcommunity,
|
||||
int as_set,
|
||||
uint8_t atomic_aggregate);
|
||||
extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *,
|
||||
struct stream *, struct attr *,
|
||||
struct bpacket_attr_vec_arr *vecarr,
|
||||
@ -284,7 +287,7 @@ extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *,
|
||||
mpls_label_t *, uint32_t, int, uint32_t);
|
||||
extern void bgp_dump_routes_attr(struct stream *, struct attr *,
|
||||
struct prefix *);
|
||||
extern int attrhash_cmp(const void *, const void *);
|
||||
extern bool attrhash_cmp(const void *arg1, const void *arg2);
|
||||
extern unsigned int attrhash_key_make(void *);
|
||||
extern void attr_show_all(struct vty *);
|
||||
extern unsigned long int attr_count(void);
|
||||
|
@ -65,7 +65,7 @@ static void community_entry_free(struct community_entry *entry)
|
||||
switch (entry->style) {
|
||||
case COMMUNITY_LIST_STANDARD:
|
||||
if (entry->u.com)
|
||||
community_free(entry->u.com);
|
||||
community_free(&entry->u.com);
|
||||
break;
|
||||
case LARGE_COMMUNITY_LIST_STANDARD:
|
||||
if (entry->u.lcom)
|
||||
@ -903,7 +903,7 @@ int community_list_unset(struct community_list_handler *ch, const char *name,
|
||||
|
||||
if (com) {
|
||||
entry = community_list_entry_lookup(list, com, direct);
|
||||
community_free(com);
|
||||
community_free(&com);
|
||||
} else
|
||||
entry = community_list_entry_lookup(list, str, direct);
|
||||
|
||||
|
@ -39,19 +39,19 @@ static struct community *community_new(void)
|
||||
}
|
||||
|
||||
/* Free communities value. */
|
||||
void community_free(struct community *com)
|
||||
void community_free(struct community **com)
|
||||
{
|
||||
if (com->val)
|
||||
XFREE(MTYPE_COMMUNITY_VAL, com->val);
|
||||
if (com->str)
|
||||
XFREE(MTYPE_COMMUNITY_STR, com->str);
|
||||
if ((*com)->val)
|
||||
XFREE(MTYPE_COMMUNITY_VAL, (*com)->val);
|
||||
if ((*com)->str)
|
||||
XFREE(MTYPE_COMMUNITY_STR, (*com)->str);
|
||||
|
||||
if (com->json) {
|
||||
json_object_free(com->json);
|
||||
com->json = NULL;
|
||||
if ((*com)->json) {
|
||||
json_object_free((*com)->json);
|
||||
(*com)->json = NULL;
|
||||
}
|
||||
|
||||
XFREE(MTYPE_COMMUNITY, com);
|
||||
XFREE(MTYPE_COMMUNITY, (*com));
|
||||
}
|
||||
|
||||
/* Add one community value to the community. */
|
||||
@ -498,7 +498,7 @@ struct community *community_intern(struct community *com)
|
||||
/* Arguemnt com is allocated temporary. So when it is not used in
|
||||
hash, it should be freed. */
|
||||
if (find != com)
|
||||
community_free(com);
|
||||
community_free(&com);
|
||||
|
||||
/* Increment refrence counter. */
|
||||
find->refcnt++;
|
||||
@ -524,8 +524,7 @@ void community_unintern(struct community **com)
|
||||
ret = (struct community *)hash_release(comhash, *com);
|
||||
assert(ret != NULL);
|
||||
|
||||
community_free(*com);
|
||||
*com = NULL;
|
||||
community_free(com);
|
||||
}
|
||||
}
|
||||
|
||||
@ -614,17 +613,17 @@ int community_match(const struct community *com1, const struct community *com2)
|
||||
|
||||
/* If two aspath have same value then return 1 else return 0. This
|
||||
function is used by hash package. */
|
||||
int community_cmp(const struct community *com1, const struct community *com2)
|
||||
bool community_cmp(const struct community *com1, const struct community *com2)
|
||||
{
|
||||
if (com1 == NULL && com2 == NULL)
|
||||
return 1;
|
||||
return true;
|
||||
if (com1 == NULL || com2 == NULL)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (com1->size == com2->size)
|
||||
if (memcmp(com1->val, com2->val, com1->size * 4) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Add com2 to the end of com1. */
|
||||
@ -874,13 +873,13 @@ struct community *community_str2com(const char *str)
|
||||
break;
|
||||
case community_token_unknown:
|
||||
if (com)
|
||||
community_free(com);
|
||||
community_free(&com);
|
||||
return NULL;
|
||||
}
|
||||
} while (str);
|
||||
|
||||
com_sort = community_uniq_sort(com);
|
||||
community_free(com);
|
||||
community_free(&com);
|
||||
|
||||
return com_sort;
|
||||
}
|
||||
@ -902,7 +901,7 @@ void community_init(void)
|
||||
{
|
||||
comhash =
|
||||
hash_create((unsigned int (*)(void *))community_hash_make,
|
||||
(int (*)(const void *, const void *))community_cmp,
|
||||
(bool (*)(const void *, const void *))community_cmp,
|
||||
"BGP Community Hash");
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ struct community {
|
||||
/* Prototypes of communities attribute functions. */
|
||||
extern void community_init(void);
|
||||
extern void community_finish(void);
|
||||
extern void community_free(struct community *);
|
||||
extern void community_free(struct community **comm);
|
||||
extern struct community *community_uniq_sort(struct community *);
|
||||
extern struct community *community_parse(uint32_t *, unsigned short);
|
||||
extern struct community *community_intern(struct community *);
|
||||
@ -77,7 +77,8 @@ extern char *community_str(struct community *, bool make_json);
|
||||
extern unsigned int community_hash_make(struct community *);
|
||||
extern struct community *community_str2com(const char *);
|
||||
extern int community_match(const struct community *, const struct community *);
|
||||
extern int community_cmp(const struct community *, const struct community *);
|
||||
extern bool community_cmp(const struct community *c1,
|
||||
const struct community *c2);
|
||||
extern struct community *community_merge(struct community *,
|
||||
struct community *);
|
||||
extern struct community *community_delete(struct community *,
|
||||
|
101
bgpd/bgp_damp.c
101
bgpd/bgp_damp.c
@ -42,8 +42,8 @@ static struct bgp_damp_config *damp = &bgp_damp_cfg;
|
||||
|
||||
/* Utility macro to add and delete BGP dampening information to no
|
||||
used list. */
|
||||
#define BGP_DAMP_LIST_ADD(N,A) BGP_INFO_ADD(N,A,no_reuse_list)
|
||||
#define BGP_DAMP_LIST_DEL(N,A) BGP_INFO_DEL(N,A,no_reuse_list)
|
||||
#define BGP_DAMP_LIST_ADD(N, A) BGP_PATH_INFO_ADD(N, A, no_reuse_list)
|
||||
#define BGP_DAMP_LIST_DEL(N, A) BGP_PATH_INFO_DEL(N, A, no_reuse_list)
|
||||
|
||||
/* Calculate reuse list index by penalty value. */
|
||||
static int bgp_reuse_index(int penalty)
|
||||
@ -128,7 +128,7 @@ static int bgp_reuse_timer(struct thread *t)
|
||||
|
||||
/* 3. if ( the saved list head pointer is non-empty ) */
|
||||
for (; bdi; bdi = next) {
|
||||
struct bgp *bgp = bdi->binfo->peer->bgp;
|
||||
struct bgp *bgp = bdi->path->peer->bgp;
|
||||
|
||||
next = bdi->next;
|
||||
|
||||
@ -145,15 +145,15 @@ static int bgp_reuse_timer(struct thread *t)
|
||||
/* if (figure-of-merit < reuse). */
|
||||
if (bdi->penalty < damp->reuse_limit) {
|
||||
/* Reuse the route. */
|
||||
bgp_info_unset_flag(bdi->rn, bdi->binfo,
|
||||
BGP_INFO_DAMPED);
|
||||
bgp_path_info_unset_flag(bdi->rn, bdi->path,
|
||||
BGP_PATH_DAMPED);
|
||||
bdi->suppress_time = 0;
|
||||
|
||||
if (bdi->lastrecord == BGP_RECORD_UPDATE) {
|
||||
bgp_info_unset_flag(bdi->rn, bdi->binfo,
|
||||
BGP_INFO_HISTORY);
|
||||
bgp_path_info_unset_flag(bdi->rn, bdi->path,
|
||||
BGP_PATH_HISTORY);
|
||||
bgp_aggregate_increment(bgp, &bdi->rn->p,
|
||||
bdi->binfo, bdi->afi,
|
||||
bdi->path, bdi->afi,
|
||||
bdi->safi);
|
||||
bgp_process(bgp, bdi->rn, bdi->afi, bdi->safi);
|
||||
}
|
||||
@ -172,8 +172,8 @@ static int bgp_reuse_timer(struct thread *t)
|
||||
}
|
||||
|
||||
/* A route becomes unreachable (RFC2439 Section 4.8.2). */
|
||||
int bgp_damp_withdraw(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi,
|
||||
safi_t safi, int attr_change)
|
||||
int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_node *rn,
|
||||
afi_t afi, safi_t safi, int attr_change)
|
||||
{
|
||||
time_t t_now;
|
||||
struct bgp_damp_info *bdi = NULL;
|
||||
@ -182,8 +182,8 @@ int bgp_damp_withdraw(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi,
|
||||
t_now = bgp_clock();
|
||||
|
||||
/* Processing Unreachable Messages. */
|
||||
if (binfo->extra)
|
||||
bdi = binfo->extra->damp_info;
|
||||
if (path->extra)
|
||||
bdi = path->extra->damp_info;
|
||||
|
||||
if (bdi == NULL) {
|
||||
/* If there is no previous stability history. */
|
||||
@ -195,7 +195,7 @@ int bgp_damp_withdraw(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi,
|
||||
|
||||
bdi = XCALLOC(MTYPE_BGP_DAMP_INFO,
|
||||
sizeof(struct bgp_damp_info));
|
||||
bdi->binfo = binfo;
|
||||
bdi->path = path;
|
||||
bdi->rn = rn;
|
||||
bdi->penalty =
|
||||
(attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY);
|
||||
@ -205,7 +205,7 @@ int bgp_damp_withdraw(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi,
|
||||
bdi->index = -1;
|
||||
bdi->afi = afi;
|
||||
bdi->safi = safi;
|
||||
(bgp_info_extra_get(binfo))->damp_info = bdi;
|
||||
(bgp_path_info_extra_get(path))->damp_info = bdi;
|
||||
BGP_DAMP_LIST_ADD(damp, bdi);
|
||||
} else {
|
||||
last_penalty = bdi->penalty;
|
||||
@ -222,16 +222,16 @@ int bgp_damp_withdraw(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi,
|
||||
bdi->flap++;
|
||||
}
|
||||
|
||||
assert((rn == bdi->rn) && (binfo == bdi->binfo));
|
||||
assert((rn == bdi->rn) && (path == bdi->path));
|
||||
|
||||
bdi->lastrecord = BGP_RECORD_WITHDRAW;
|
||||
bdi->t_updated = t_now;
|
||||
|
||||
/* Make this route as historical status. */
|
||||
bgp_info_set_flag(rn, binfo, BGP_INFO_HISTORY);
|
||||
bgp_path_info_set_flag(rn, path, BGP_PATH_HISTORY);
|
||||
|
||||
/* Remove the route from a reuse list if it is on one. */
|
||||
if (CHECK_FLAG(bdi->binfo->flags, BGP_INFO_DAMPED)) {
|
||||
if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)) {
|
||||
/* If decay rate isn't equal to 0, reinsert brn. */
|
||||
if (bdi->penalty != last_penalty && bdi->index >= 0) {
|
||||
bgp_reuse_list_delete(bdi);
|
||||
@ -243,7 +243,7 @@ int bgp_damp_withdraw(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi,
|
||||
/* If not suppressed before, do annonunce this withdraw and
|
||||
insert into reuse_list. */
|
||||
if (bdi->penalty >= damp->suppress_value) {
|
||||
bgp_info_set_flag(rn, binfo, BGP_INFO_DAMPED);
|
||||
bgp_path_info_set_flag(rn, path, BGP_PATH_DAMPED);
|
||||
bdi->suppress_time = t_now;
|
||||
BGP_DAMP_LIST_DEL(damp, bdi);
|
||||
bgp_reuse_list_add(bdi);
|
||||
@ -252,28 +252,28 @@ int bgp_damp_withdraw(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi,
|
||||
return BGP_DAMP_USED;
|
||||
}
|
||||
|
||||
int bgp_damp_update(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi,
|
||||
int bgp_damp_update(struct bgp_path_info *path, struct bgp_node *rn, afi_t afi,
|
||||
safi_t safi)
|
||||
{
|
||||
time_t t_now;
|
||||
struct bgp_damp_info *bdi;
|
||||
int status;
|
||||
|
||||
if (!binfo->extra || !((bdi = binfo->extra->damp_info)))
|
||||
if (!path->extra || !((bdi = path->extra->damp_info)))
|
||||
return BGP_DAMP_USED;
|
||||
|
||||
t_now = bgp_clock();
|
||||
bgp_info_unset_flag(rn, binfo, BGP_INFO_HISTORY);
|
||||
bgp_path_info_unset_flag(rn, path, BGP_PATH_HISTORY);
|
||||
|
||||
bdi->lastrecord = BGP_RECORD_UPDATE;
|
||||
bdi->penalty = bgp_damp_decay(t_now - bdi->t_updated, bdi->penalty);
|
||||
|
||||
if (!CHECK_FLAG(bdi->binfo->flags, BGP_INFO_DAMPED)
|
||||
if (!CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)
|
||||
&& (bdi->penalty < damp->suppress_value))
|
||||
status = BGP_DAMP_USED;
|
||||
else if (CHECK_FLAG(bdi->binfo->flags, BGP_INFO_DAMPED)
|
||||
else if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)
|
||||
&& (bdi->penalty < damp->reuse_limit)) {
|
||||
bgp_info_unset_flag(rn, binfo, BGP_INFO_DAMPED);
|
||||
bgp_path_info_unset_flag(rn, path, BGP_PATH_DAMPED);
|
||||
bgp_reuse_list_delete(bdi);
|
||||
BGP_DAMP_LIST_ADD(damp, bdi);
|
||||
bdi->suppress_time = 0;
|
||||
@ -290,28 +290,29 @@ int bgp_damp_update(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi,
|
||||
}
|
||||
|
||||
/* Remove dampening information and history route. */
|
||||
int bgp_damp_scan(struct bgp_info *binfo, afi_t afi, safi_t safi)
|
||||
int bgp_damp_scan(struct bgp_path_info *path, afi_t afi, safi_t safi)
|
||||
{
|
||||
time_t t_now, t_diff;
|
||||
struct bgp_damp_info *bdi;
|
||||
|
||||
assert(binfo->extra && binfo->extra->damp_info);
|
||||
assert(path->extra && path->extra->damp_info);
|
||||
|
||||
t_now = bgp_clock();
|
||||
bdi = binfo->extra->damp_info;
|
||||
bdi = path->extra->damp_info;
|
||||
|
||||
if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) {
|
||||
if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
|
||||
t_diff = t_now - bdi->suppress_time;
|
||||
|
||||
if (t_diff >= damp->max_suppress_time) {
|
||||
bgp_info_unset_flag(bdi->rn, binfo, BGP_INFO_DAMPED);
|
||||
bgp_path_info_unset_flag(bdi->rn, path,
|
||||
BGP_PATH_DAMPED);
|
||||
bgp_reuse_list_delete(bdi);
|
||||
BGP_DAMP_LIST_ADD(damp, bdi);
|
||||
bdi->penalty = damp->reuse_limit;
|
||||
bdi->suppress_time = 0;
|
||||
bdi->t_updated = t_now;
|
||||
|
||||
/* Need to announce UPDATE once this binfo is usable
|
||||
/* Need to announce UPDATE once this path is usable
|
||||
* again. */
|
||||
if (bdi->lastrecord == BGP_RECORD_UPDATE)
|
||||
return 1;
|
||||
@ -323,7 +324,7 @@ int bgp_damp_scan(struct bgp_info *binfo, afi_t afi, safi_t safi)
|
||||
bdi->penalty = bgp_damp_decay(t_diff, bdi->penalty);
|
||||
|
||||
if (bdi->penalty <= damp->reuse_limit / 2.0) {
|
||||
/* release the bdi, bdi->binfo. */
|
||||
/* release the bdi, bdi->path. */
|
||||
bgp_damp_info_free(bdi, 1);
|
||||
return 0;
|
||||
} else
|
||||
@ -334,23 +335,24 @@ int bgp_damp_scan(struct bgp_info *binfo, afi_t afi, safi_t safi)
|
||||
|
||||
void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw)
|
||||
{
|
||||
struct bgp_info *binfo;
|
||||
struct bgp_path_info *path;
|
||||
|
||||
if (!bdi)
|
||||
return;
|
||||
|
||||
binfo = bdi->binfo;
|
||||
binfo->extra->damp_info = NULL;
|
||||
path = bdi->path;
|
||||
path->extra->damp_info = NULL;
|
||||
|
||||
if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED))
|
||||
if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
|
||||
bgp_reuse_list_delete(bdi);
|
||||
else
|
||||
BGP_DAMP_LIST_DEL(damp, bdi);
|
||||
|
||||
bgp_info_unset_flag(bdi->rn, binfo, BGP_INFO_HISTORY | BGP_INFO_DAMPED);
|
||||
bgp_path_info_unset_flag(bdi->rn, path,
|
||||
BGP_PATH_HISTORY | BGP_PATH_DAMPED);
|
||||
|
||||
if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw)
|
||||
bgp_info_delete(bdi->rn, binfo);
|
||||
bgp_path_info_delete(bdi->rn, path);
|
||||
|
||||
XFREE(MTYPE_BGP_DAMP_INFO, bdi);
|
||||
}
|
||||
@ -446,12 +448,15 @@ static void bgp_damp_config_clean(struct bgp_damp_config *damp)
|
||||
{
|
||||
/* Free decay array */
|
||||
XFREE(MTYPE_BGP_DAMP_ARRAY, damp->decay_array);
|
||||
damp->decay_array_size = 0;
|
||||
|
||||
/* Free reuse index array */
|
||||
XFREE(MTYPE_BGP_DAMP_ARRAY, damp->reuse_index);
|
||||
damp->reuse_index_size = 0;
|
||||
|
||||
/* Free reuse list array. */
|
||||
XFREE(MTYPE_BGP_DAMP_ARRAY, damp->reuse_list);
|
||||
damp->reuse_list_size = 0;
|
||||
}
|
||||
|
||||
/* Clean all the bgp_damp_info stored in reuse_list. */
|
||||
@ -588,7 +593,7 @@ static const char *bgp_get_reuse_time(unsigned int penalty, char *buf,
|
||||
return buf;
|
||||
}
|
||||
|
||||
void bgp_damp_info_vty(struct vty *vty, struct bgp_info *binfo,
|
||||
void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path,
|
||||
json_object *json_path)
|
||||
{
|
||||
struct bgp_damp_info *bdi;
|
||||
@ -596,11 +601,11 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_info *binfo,
|
||||
char timebuf[BGP_UPTIME_LEN];
|
||||
int penalty;
|
||||
|
||||
if (!binfo->extra)
|
||||
if (!path->extra)
|
||||
return;
|
||||
|
||||
/* BGP dampening information. */
|
||||
bdi = binfo->extra->damp_info;
|
||||
bdi = path->extra->damp_info;
|
||||
|
||||
/* If dampening is not enabled or there is no dampening information,
|
||||
return immediately. */
|
||||
@ -618,8 +623,8 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_info *binfo,
|
||||
peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, 1,
|
||||
json_path);
|
||||
|
||||
if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)
|
||||
&& !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
|
||||
if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
|
||||
&& !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
|
||||
bgp_get_reuse_time(penalty, timebuf, BGP_UPTIME_LEN, 1,
|
||||
json_path);
|
||||
} else {
|
||||
@ -629,8 +634,8 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_info *binfo,
|
||||
peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, 0,
|
||||
json_path));
|
||||
|
||||
if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)
|
||||
&& !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
|
||||
if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
|
||||
&& !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
|
||||
vty_out(vty, ", reuse in %s",
|
||||
bgp_get_reuse_time(penalty, timebuf,
|
||||
BGP_UPTIME_LEN, 0,
|
||||
@ -640,7 +645,7 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_info *binfo,
|
||||
}
|
||||
}
|
||||
|
||||
const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_info *binfo,
|
||||
const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path,
|
||||
char *timebuf, size_t len, bool use_json,
|
||||
json_object *json)
|
||||
{
|
||||
@ -648,11 +653,11 @@ const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_info *binfo,
|
||||
time_t t_now, t_diff;
|
||||
int penalty;
|
||||
|
||||
if (!binfo->extra)
|
||||
if (!path->extra)
|
||||
return NULL;
|
||||
|
||||
/* BGP dampening information. */
|
||||
bdi = binfo->extra->damp_info;
|
||||
bdi = path->extra->damp_info;
|
||||
|
||||
/* If dampening is not enabled or there is no dampening information,
|
||||
return immediately. */
|
||||
@ -684,7 +689,7 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi)
|
||||
vty_out(vty, "Suppress penalty: %d\n", damp->suppress_value);
|
||||
vty_out(vty, "Max suppress time: %lld min\n",
|
||||
(long long)damp->max_suppress_time / 60);
|
||||
vty_out(vty, "Max supress penalty: %u\n", damp->ceiling);
|
||||
vty_out(vty, "Max suppress penalty: %u\n", damp->ceiling);
|
||||
vty_out(vty, "\n");
|
||||
} else
|
||||
vty_out(vty, "dampening not enabled for %s\n",
|
||||
|
@ -43,8 +43,8 @@ struct bgp_damp_info {
|
||||
/* Time of route start to be suppressed. */
|
||||
time_t suppress_time;
|
||||
|
||||
/* Back reference to bgp_info. */
|
||||
struct bgp_info *binfo;
|
||||
/* Back reference to bgp_path_info. */
|
||||
struct bgp_path_info *path;
|
||||
|
||||
/* Back reference to bgp_node. */
|
||||
struct bgp_node *rn;
|
||||
@ -130,18 +130,19 @@ struct bgp_damp_config {
|
||||
extern int bgp_damp_enable(struct bgp *, afi_t, safi_t, time_t, unsigned int,
|
||||
unsigned int, time_t);
|
||||
extern int bgp_damp_disable(struct bgp *, afi_t, safi_t);
|
||||
extern int bgp_damp_withdraw(struct bgp_info *, struct bgp_node *, afi_t,
|
||||
safi_t, int);
|
||||
extern int bgp_damp_update(struct bgp_info *, struct bgp_node *, afi_t, safi_t);
|
||||
extern int bgp_damp_scan(struct bgp_info *, afi_t, safi_t);
|
||||
extern void bgp_damp_info_free(struct bgp_damp_info *, int);
|
||||
extern int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_node *rn,
|
||||
afi_t afi, safi_t safi, int attr_change);
|
||||
extern int bgp_damp_update(struct bgp_path_info *path, struct bgp_node *rn,
|
||||
afi_t afi, safi_t saff);
|
||||
extern int bgp_damp_scan(struct bgp_path_info *path, afi_t afi, safi_t safi);
|
||||
extern void bgp_damp_info_free(struct bgp_damp_info *path, int withdraw);
|
||||
extern void bgp_damp_info_clean(void);
|
||||
extern int bgp_damp_decay(time_t, int);
|
||||
extern void bgp_config_write_damp(struct vty *);
|
||||
extern void bgp_damp_info_vty(struct vty *, struct bgp_info *,
|
||||
extern void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path,
|
||||
json_object *json_path);
|
||||
extern const char *bgp_damp_reuse_time_vty(struct vty *vty,
|
||||
struct bgp_info *binfo,
|
||||
struct bgp_path_info *path,
|
||||
char *timebuf, size_t len,
|
||||
bool use_json, json_object *json);
|
||||
extern int bgp_show_dampening_parameters(struct vty *vty, afi_t, safi_t);
|
||||
|
@ -1380,7 +1380,7 @@ DEFUN (no_debug_bgp_update_direct_peer,
|
||||
|
||||
DEFPY (debug_bgp_update_prefix_afi_safi,
|
||||
debug_bgp_update_prefix_afi_safi_cmd,
|
||||
"debug bgp updates prefix l2vpn$afi evpn$safi type <macip mac <M:A:C|M:A:C/M> [ip <A.B.C.D|X:X::X:X>]|multicast ip <A.B.C.D|X:X::X:X>|prefix ip <A.B.C.D/M|X:X::X:X/M>>",
|
||||
"debug bgp updates prefix l2vpn$afi evpn$safi type <macip mac <X:X:X:X:X:X|X:X:X:X:X:X/M> [ip <A.B.C.D|X:X::X:X>]|multicast ip <A.B.C.D|X:X::X:X>|prefix ip <A.B.C.D/M|X:X::X:X/M>>",
|
||||
DEBUG_STR
|
||||
BGP_STR
|
||||
"BGP updates\n"
|
||||
@ -1443,7 +1443,7 @@ DEFPY (debug_bgp_update_prefix_afi_safi,
|
||||
|
||||
DEFPY (no_debug_bgp_update_prefix_afi_safi,
|
||||
no_debug_bgp_update_prefix_afi_safi_cmd,
|
||||
"no debug bgp updates prefix l2vpn$afi evpn$safi type <macip mac <M:A:C|M:A:C/M> [ip <A.B.C.D|X:X::X:X>]|multicast ip <A.B.C.D|X:X::X:X>|prefix ip <A.B.C.D/M|X:X::X:X/M>>",
|
||||
"no debug bgp updates prefix l2vpn$afi evpn$safi type <macip mac <X:X:X:X:X:X|X:X:X:X:X:X/M> [ip <A.B.C.D|X:X::X:X>]|multicast ip <A.B.C.D|X:X::X:X>|prefix ip <A.B.C.D/M|X:X::X:X/M>>",
|
||||
NO_STR
|
||||
DEBUG_STR
|
||||
BGP_STR
|
||||
|
@ -299,9 +299,9 @@ static void bgp_dump_routes_index_table(struct bgp *bgp)
|
||||
}
|
||||
|
||||
|
||||
static struct bgp_info *bgp_dump_route_node_record(int afi, struct bgp_node *rn,
|
||||
struct bgp_info *info,
|
||||
unsigned int seq)
|
||||
static struct bgp_path_info *
|
||||
bgp_dump_route_node_record(int afi, struct bgp_node *rn,
|
||||
struct bgp_path_info *path, unsigned int seq)
|
||||
{
|
||||
struct stream *obuf;
|
||||
size_t sizep;
|
||||
@ -349,18 +349,18 @@ static struct bgp_info *bgp_dump_route_node_record(int afi, struct bgp_node *rn,
|
||||
stream_putw(obuf, 0);
|
||||
|
||||
endp = stream_get_endp(obuf);
|
||||
for (; info; info = info->next) {
|
||||
for (; path; path = path->next) {
|
||||
size_t cur_endp;
|
||||
|
||||
/* Peer index */
|
||||
stream_putw(obuf, info->peer->table_dump_index);
|
||||
stream_putw(obuf, path->peer->table_dump_index);
|
||||
|
||||
/* Originated */
|
||||
stream_putl(obuf, time(NULL) - (bgp_clock() - info->uptime));
|
||||
stream_putl(obuf, time(NULL) - (bgp_clock() - path->uptime));
|
||||
|
||||
/* Dump attribute. */
|
||||
/* Skip prefix & AFI/SAFI for MP_NLRI */
|
||||
bgp_dump_routes_attr(obuf, info->attr, &rn->p);
|
||||
bgp_dump_routes_attr(obuf, path->attr, &rn->p);
|
||||
|
||||
cur_endp = stream_get_endp(obuf);
|
||||
if (cur_endp > BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER
|
||||
@ -379,7 +379,7 @@ static struct bgp_info *bgp_dump_route_node_record(int afi, struct bgp_node *rn,
|
||||
bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);
|
||||
fwrite(STREAM_DATA(obuf), stream_get_endp(obuf), 1, bgp_dump_routes.fp);
|
||||
|
||||
return info;
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
@ -387,7 +387,7 @@ static struct bgp_info *bgp_dump_route_node_record(int afi, struct bgp_node *rn,
|
||||
static unsigned int bgp_dump_routes_func(int afi, int first_run,
|
||||
unsigned int seq)
|
||||
{
|
||||
struct bgp_info *info;
|
||||
struct bgp_path_info *path;
|
||||
struct bgp_node *rn;
|
||||
struct bgp *bgp;
|
||||
struct bgp_table *table;
|
||||
@ -410,9 +410,9 @@ static unsigned int bgp_dump_routes_func(int afi, int first_run,
|
||||
table = bgp->rib[afi][SAFI_UNICAST];
|
||||
|
||||
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
|
||||
info = rn->info;
|
||||
while (info) {
|
||||
info = bgp_dump_route_node_record(afi, rn, info, seq);
|
||||
path = rn->info;
|
||||
while (path) {
|
||||
path = bgp_dump_route_node_record(afi, rn, path, seq);
|
||||
seq++;
|
||||
}
|
||||
}
|
||||
|
@ -253,16 +253,16 @@ unsigned int ecommunity_hash_make(void *arg)
|
||||
}
|
||||
|
||||
/* Compare two Extended Communities Attribute structure. */
|
||||
int ecommunity_cmp(const void *arg1, const void *arg2)
|
||||
bool ecommunity_cmp(const void *arg1, const void *arg2)
|
||||
{
|
||||
const struct ecommunity *ecom1 = arg1;
|
||||
const struct ecommunity *ecom2 = arg2;
|
||||
|
||||
if (ecom1 == NULL && ecom2 == NULL)
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
if (ecom1 == NULL || ecom2 == NULL)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return (ecom1->size == ecom2->size
|
||||
&& memcmp(ecom1->val, ecom2->val, ecom1->size * ECOMMUNITY_SIZE)
|
||||
|
@ -154,7 +154,7 @@ extern struct ecommunity *ecommunity_merge(struct ecommunity *,
|
||||
struct ecommunity *);
|
||||
extern struct ecommunity *ecommunity_uniq_sort(struct ecommunity *);
|
||||
extern struct ecommunity *ecommunity_intern(struct ecommunity *);
|
||||
extern int ecommunity_cmp(const void *, const void *);
|
||||
extern bool ecommunity_cmp(const void *arg1, const void *arg2);
|
||||
extern void ecommunity_unintern(struct ecommunity **);
|
||||
extern unsigned int ecommunity_hash_make(void *);
|
||||
extern struct ecommunity *ecommunity_str2com(const char *, int, int);
|
||||
|
@ -171,7 +171,7 @@ static struct log_ref ferr_bgp_warn[] = {
|
||||
},
|
||||
{
|
||||
.code = EC_BGP_CAPABILITY_VENDOR,
|
||||
.title = "BGP has recieved capability data specific to a particular vendor",
|
||||
.title = "BGP has received capability data specific to a particular vendor",
|
||||
.description = "BGP has received a capability that is vendor specific and as such we have no knowledge of how to use this capability in FRR",
|
||||
.suggestion = "On peer turn off this feature"
|
||||
},
|
||||
@ -197,43 +197,43 @@ static struct log_ref ferr_bgp_err[] = {
|
||||
.code = EC_BGP_ATTR_FLAG,
|
||||
.title = "BGP attribute flag is incorrect",
|
||||
.description = "BGP attribute flag is set to the wrong value (Optional/Transitive/Partial)",
|
||||
.suggestion = "Determine the soure of the attribute and determine why the attribute flag has been set incorrectly"
|
||||
.suggestion = "Determine the source of the attribute and determine why the attribute flag has been set incorrectly"
|
||||
},
|
||||
{
|
||||
.code = EC_BGP_ATTR_LEN,
|
||||
.title = "BGP attribute length is incorrect",
|
||||
.description = "BGP attribute length is incorrect",
|
||||
.suggestion = "Determine the soure of the attribute and determine why the attribute length has been set incorrectly"
|
||||
.suggestion = "Determine the source of the attribute and determine why the attribute length has been set incorrectly"
|
||||
},
|
||||
{
|
||||
.code = EC_BGP_ATTR_ORIGIN,
|
||||
.title = "BGP attribute origin value invalid",
|
||||
.description = "BGP attribute origin value is invalid",
|
||||
.suggestion = "Determine the soure of the attribute and determine why the origin attribute has been set incorrectly"
|
||||
.suggestion = "Determine the source of the attribute and determine why the origin attribute has been set incorrectly"
|
||||
},
|
||||
{
|
||||
.code = EC_BGP_ATTR_MAL_AS_PATH,
|
||||
.title = "BGP as path is invalid",
|
||||
.description = "BGP as path has been malformed",
|
||||
.suggestion = "Determine the soure of the update and determine why the as path has been set incorrectly"
|
||||
.suggestion = "Determine the source of the update and determine why the as path has been set incorrectly"
|
||||
},
|
||||
{
|
||||
.code = EC_BGP_ATTR_FIRST_AS,
|
||||
.title = "BGP as path first as is invalid",
|
||||
.description = "BGP update has invalid first as in as path",
|
||||
.suggestion = "Determine the soure of the update and determine why the as path first as value has been set incorrectly"
|
||||
.suggestion = "Determine the source of the update and determine why the as path first as value has been set incorrectly"
|
||||
},
|
||||
{
|
||||
.code = EC_BGP_ATTR_PMSI_TYPE,
|
||||
.title = "BGP PMSI tunnel attribute type is invalid",
|
||||
.description = "BGP update has invalid type for PMSI tunnel",
|
||||
.suggestion = "Determine the soure of the update and determine why the PMSI tunnel attribute type has been set incorrectly"
|
||||
.suggestion = "Determine the source of the update and determine why the PMSI tunnel attribute type has been set incorrectly"
|
||||
},
|
||||
{
|
||||
.code = EC_BGP_ATTR_PMSI_LEN,
|
||||
.title = "BGP PMSI tunnel attribute length is invalid",
|
||||
.description = "BGP update has invalid length for PMSI tunnel",
|
||||
.suggestion = "Determine the soure of the update and determine why the PMSI tunnel attribute length has been set incorrectly"
|
||||
.suggestion = "Determine the source of the update and determine why the PMSI tunnel attribute length has been set incorrectly"
|
||||
},
|
||||
{
|
||||
.code = EC_BGP_PEER_GROUP,
|
||||
@ -269,7 +269,7 @@ static struct log_ref ferr_bgp_err[] = {
|
||||
.code = EC_BGP_JSON_MEM_ERROR,
|
||||
.title = "BGP unable to allocate memory for JSON output",
|
||||
.description = "BGP attempted to generate JSON output and was unable to allocate the memory required",
|
||||
.suggestion = "Ensure that the device has adequate memory to suport the required functions"
|
||||
.suggestion = "Ensure that the device has adequate memory to support the required functions"
|
||||
},
|
||||
{
|
||||
.code = EC_BGP_UPDGRP_ATTR_LEN,
|
||||
|
1001
bgpd/bgp_evpn.c
1001
bgpd/bgp_evpn.c
File diff suppressed because it is too large
Load Diff
@ -76,9 +76,9 @@ static inline int advertise_type5_routes(struct bgp *bgp_vrf,
|
||||
}
|
||||
|
||||
/* Flag if the route's parent is a EVPN route. */
|
||||
static inline int is_route_parent_evpn(struct bgp_info *ri)
|
||||
static inline int is_route_parent_evpn(struct bgp_path_info *ri)
|
||||
{
|
||||
struct bgp_info *parent_ri;
|
||||
struct bgp_path_info *parent_ri;
|
||||
struct bgp_table *table;
|
||||
struct bgp_node *rn;
|
||||
|
||||
@ -89,7 +89,7 @@ static inline int is_route_parent_evpn(struct bgp_info *ri)
|
||||
return 0;
|
||||
|
||||
/* See if the parent is of family L2VPN/EVPN */
|
||||
parent_ri = (struct bgp_info *)ri->extra->parent;
|
||||
parent_ri = (struct bgp_path_info *)ri->extra->parent;
|
||||
rn = parent_ri->net;
|
||||
if (!rn)
|
||||
return 0;
|
||||
@ -124,9 +124,9 @@ extern void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
|
||||
extern int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
|
||||
struct bgp_nlri *packet, int withdraw);
|
||||
extern int bgp_evpn_import_route(struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
struct prefix *p, struct bgp_info *ri);
|
||||
struct prefix *p, struct bgp_path_info *ri);
|
||||
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_path_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);
|
||||
@ -145,6 +145,7 @@ extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
|
||||
struct ipaddr *originator_ip);
|
||||
extern int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi,
|
||||
struct ipaddr *originator_ip);
|
||||
extern void bgp_evpn_flood_control_change(struct bgp *bgp);
|
||||
extern void bgp_evpn_cleanup_on_disable(struct bgp *bgp);
|
||||
extern void bgp_evpn_cleanup(struct bgp *bgp);
|
||||
extern void bgp_evpn_init(struct bgp *bgp);
|
||||
|
@ -536,7 +536,7 @@ static void show_esi_routes(struct bgp *bgp,
|
||||
{
|
||||
int header = 1;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *pi;
|
||||
uint32_t prefix_cnt, path_cnt;
|
||||
uint64_t tbl_ver;
|
||||
|
||||
@ -573,13 +573,13 @@ static void show_esi_routes(struct bgp *bgp,
|
||||
/* For EVPN, the prefix is displayed for each path (to fit in
|
||||
* with code that already exists).
|
||||
*/
|
||||
for (ri = rn->info; ri; ri = ri->next) {
|
||||
for (pi = rn->info; pi; pi = pi->next) {
|
||||
json_object *json_path = NULL;
|
||||
|
||||
if (json)
|
||||
json_path = json_object_new_array();
|
||||
|
||||
route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN, json_path);
|
||||
route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN, json_path);
|
||||
|
||||
if (json)
|
||||
json_object_array_add(json_paths, json_path);
|
||||
@ -616,7 +616,7 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
|
||||
json_object *json)
|
||||
{
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *pi;
|
||||
struct bgp_table *table;
|
||||
int header = 1;
|
||||
uint64_t tbl_ver;
|
||||
@ -660,18 +660,18 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
|
||||
/* For EVPN, the prefix is displayed for each path (to fit in
|
||||
* with code that already exists).
|
||||
*/
|
||||
for (ri = rn->info; ri; ri = ri->next) {
|
||||
for (pi = rn->info; pi; pi = pi->next) {
|
||||
json_object *json_path = NULL;
|
||||
|
||||
if (vtep_ip.s_addr
|
||||
&& !IPV4_ADDR_SAME(&(vtep_ip),
|
||||
&(ri->attr->nexthop)))
|
||||
&(pi->attr->nexthop)))
|
||||
continue;
|
||||
|
||||
if (json)
|
||||
json_path = json_object_new_array();
|
||||
|
||||
route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN, json_path);
|
||||
route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN, json_path);
|
||||
|
||||
if (json)
|
||||
json_object_array_add(json_paths, json_path);
|
||||
@ -990,7 +990,7 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
|
||||
struct bgp_table *table;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_node *rm;
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *pi;
|
||||
int rd_header;
|
||||
int header = 1;
|
||||
|
||||
@ -1046,14 +1046,14 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
|
||||
tbl_ver = table->version;
|
||||
|
||||
for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm))
|
||||
for (ri = rm->info; ri; ri = ri->next) {
|
||||
for (pi = rm->info; pi; pi = pi->next) {
|
||||
total_count++;
|
||||
if (type == bgp_show_type_neighbor) {
|
||||
union sockunion *su = output_arg;
|
||||
|
||||
if (ri->peer->su_remote == NULL
|
||||
if (pi->peer->su_remote == NULL
|
||||
|| !sockunion_same(
|
||||
ri->peer->su_remote, su))
|
||||
pi->peer->su_remote, su))
|
||||
continue;
|
||||
}
|
||||
if (header == 0) {
|
||||
@ -1162,14 +1162,14 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
|
||||
else
|
||||
json_array = NULL;
|
||||
if (option == SHOW_DISPLAY_TAGS)
|
||||
route_vty_out_tag(vty, &rm->p, ri, 0,
|
||||
route_vty_out_tag(vty, &rm->p, pi, 0,
|
||||
SAFI_EVPN,
|
||||
json_array);
|
||||
else if (option == SHOW_DISPLAY_OVERLAY)
|
||||
route_vty_out_overlay(vty, &rm->p, ri,
|
||||
route_vty_out_overlay(vty, &rm->p, pi,
|
||||
0, json_array);
|
||||
else
|
||||
route_vty_out(vty, &rm->p, ri, 0,
|
||||
route_vty_out(vty, &rm->p, pi, 0,
|
||||
SAFI_EVPN, json_array);
|
||||
output_count++;
|
||||
}
|
||||
@ -2017,7 +2017,7 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
|
||||
struct bgpevpn *vpn;
|
||||
struct prefix_evpn p;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *pi;
|
||||
uint32_t path_cnt = 0;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
@ -2049,13 +2049,13 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
|
||||
route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
|
||||
|
||||
/* Display each path for this prefix. */
|
||||
for (ri = rn->info; ri; ri = ri->next) {
|
||||
for (pi = rn->info; pi; pi = pi->next) {
|
||||
json_object *json_path = NULL;
|
||||
|
||||
if (json)
|
||||
json_path = json_object_new_array();
|
||||
|
||||
route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
|
||||
route_vty_out_detail(vty, bgp, &rn->p, pi, afi, safi,
|
||||
json_path);
|
||||
|
||||
if (json)
|
||||
@ -2086,7 +2086,7 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
|
||||
struct bgpevpn *vpn;
|
||||
struct prefix_evpn p;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *pi;
|
||||
uint32_t path_cnt = 0;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
@ -2119,13 +2119,13 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
|
||||
route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
|
||||
|
||||
/* Display each path for this prefix. */
|
||||
for (ri = rn->info; ri; ri = ri->next) {
|
||||
for (pi = rn->info; pi; pi = pi->next) {
|
||||
json_object *json_path = NULL;
|
||||
|
||||
if (json)
|
||||
json_path = json_object_new_array();
|
||||
|
||||
route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
|
||||
route_vty_out_detail(vty, bgp, &rn->p, pi, afi, safi,
|
||||
json_path);
|
||||
|
||||
if (json)
|
||||
@ -2196,7 +2196,7 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
|
||||
{
|
||||
struct prefix_evpn p;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *pi;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
uint32_t path_cnt = 0;
|
||||
@ -2226,13 +2226,13 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
|
||||
json_paths = json_object_new_array();
|
||||
|
||||
/* Display each path for this prefix. */
|
||||
for (ri = rn->info; ri; ri = ri->next) {
|
||||
for (pi = rn->info; pi; pi = pi->next) {
|
||||
json_object *json_path = NULL;
|
||||
|
||||
if (json)
|
||||
json_path = json_object_new_array();
|
||||
|
||||
route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
|
||||
route_vty_out_detail(vty, bgp, &rn->p, pi, afi, safi,
|
||||
json_path);
|
||||
|
||||
if (json)
|
||||
@ -2262,7 +2262,7 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
|
||||
struct bgp_node *rd_rn;
|
||||
struct bgp_table *table;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *pi;
|
||||
int rd_header = 1;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
@ -2330,13 +2330,13 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
|
||||
json_paths = json_object_new_array();
|
||||
|
||||
/* Display each path for this prefix. */
|
||||
for (ri = rn->info; ri; ri = ri->next) {
|
||||
for (pi = rn->info; pi; pi = pi->next) {
|
||||
json_object *json_path = NULL;
|
||||
|
||||
if (json)
|
||||
json_path = json_object_new_array();
|
||||
|
||||
route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
|
||||
route_vty_out_detail(vty, bgp, &rn->p, pi, afi, safi,
|
||||
json_path);
|
||||
|
||||
if (json)
|
||||
@ -2383,7 +2383,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
|
||||
struct bgp_node *rd_rn;
|
||||
struct bgp_table *table;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *pi;
|
||||
int header = 1;
|
||||
int rd_header;
|
||||
afi_t afi;
|
||||
@ -2467,7 +2467,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
|
||||
* fit in
|
||||
* with code that already exists).
|
||||
*/
|
||||
for (ri = rn->info; ri; ri = ri->next) {
|
||||
for (pi = rn->info; pi; pi = pi->next) {
|
||||
json_object *json_path = NULL;
|
||||
path_cnt++;
|
||||
add_prefix_to_json = 1;
|
||||
@ -2476,7 +2476,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
|
||||
if (json)
|
||||
json_path = json_object_new_array();
|
||||
|
||||
route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN,
|
||||
route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN,
|
||||
json_path);
|
||||
|
||||
if (json)
|
||||
@ -2807,6 +2807,40 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef VTYSH_EXTRACT_PL
|
||||
#include "bgpd/bgp_evpn_vty_clippy.c"
|
||||
#endif
|
||||
|
||||
DEFPY(bgp_evpn_flood_control,
|
||||
bgp_evpn_flood_control_cmd,
|
||||
"[no$no] flooding <disable$disable|head-end-replication$her>",
|
||||
NO_STR
|
||||
"Specify handling for BUM packets\n"
|
||||
"Do not flood any BUM packets\n"
|
||||
"Flood BUM packets using head-end replication\n")
|
||||
{
|
||||
struct bgp *bgp = VTY_GET_CONTEXT(bgp);
|
||||
enum vxlan_flood_control flood_ctrl;
|
||||
|
||||
if (!bgp)
|
||||
return CMD_WARNING;
|
||||
|
||||
if (disable && !no)
|
||||
flood_ctrl = VXLAN_FLOOD_DISABLED;
|
||||
else if (her || no)
|
||||
flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
|
||||
else
|
||||
return CMD_WARNING;
|
||||
|
||||
if (bgp->vxlan_flood_ctrl == flood_ctrl)
|
||||
return CMD_SUCCESS;
|
||||
|
||||
bgp->vxlan_flood_ctrl = flood_ctrl;
|
||||
bgp_evpn_flood_control_change(bgp);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (bgp_evpn_advertise_default_gw_vni,
|
||||
bgp_evpn_advertise_default_gw_vni_cmd,
|
||||
"advertise-default-gw",
|
||||
@ -3210,6 +3244,12 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
|
||||
json_object_string_add(json, "advertiseAllVnis",
|
||||
is_evpn_enabled() ? "Enabled"
|
||||
: "Disabled");
|
||||
json_object_string_add(
|
||||
json, "flooding",
|
||||
bgp_def->vxlan_flood_ctrl
|
||||
== VXLAN_FLOOD_HEAD_END_REPL
|
||||
? "Head-end replication"
|
||||
: "Disabled");
|
||||
json_object_int_add(json, "numVnis", num_vnis);
|
||||
json_object_int_add(json, "numL2Vnis", num_l2vnis);
|
||||
json_object_int_add(json, "numL3Vnis", num_l3vnis);
|
||||
@ -3219,6 +3259,11 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
|
||||
: "Disabled");
|
||||
vty_out(vty, "Advertise All VNI flag: %s\n",
|
||||
is_evpn_enabled() ? "Enabled" : "Disabled");
|
||||
vty_out(vty, "BUM flooding: %s\n",
|
||||
bgp_def->vxlan_flood_ctrl
|
||||
== VXLAN_FLOOD_HEAD_END_REPL
|
||||
? "Head-end replication"
|
||||
: "Disabled");
|
||||
vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
|
||||
vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
|
||||
}
|
||||
@ -3954,7 +3999,7 @@ DEFUN(test_withdraw_evpn_type4_route,
|
||||
}
|
||||
|
||||
if (!bgp->peer_self) {
|
||||
vty_out(vty, "%%BGP instance doesnt have self peer\n");
|
||||
vty_out(vty, "%%BGP instance doesn't have self peer\n");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
@ -4874,6 +4919,9 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
if (bgp->advertise_gw_macip)
|
||||
vty_out(vty, " advertise-default-gw\n");
|
||||
|
||||
if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
|
||||
vty_out(vty, " flooding disable\n");
|
||||
|
||||
if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
|
||||
BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
|
||||
if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
|
||||
@ -4965,6 +5013,7 @@ void bgp_ethernetvpn_init(void)
|
||||
install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
|
||||
install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
|
||||
install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
|
||||
install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd);
|
||||
|
||||
/* test commands */
|
||||
install_element(BGP_EVPN_NODE, &test_adv_evpn_type4_route_cmd);
|
||||
|
@ -77,7 +77,7 @@ struct as_list {
|
||||
struct as_filter *tail;
|
||||
};
|
||||
|
||||
/* ip as-path access-list 10 permit AS1. */
|
||||
/* as-path access-list 10 permit AS1. */
|
||||
|
||||
static struct as_list_master as_list_master = {{NULL, NULL},
|
||||
{NULL, NULL},
|
||||
@ -401,9 +401,9 @@ static int config_bgp_aspath_validate(const char *regstr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFUN(ip_as_path, ip_as_path_cmd,
|
||||
"ip as-path access-list WORD <deny|permit> LINE...",
|
||||
IP_STR
|
||||
DEFUN(as_path, bgp_as_path_cmd,
|
||||
"bgp as-path access-list WORD <deny|permit> LINE...",
|
||||
BGP_STR
|
||||
"BGP autonomous system path filter\n"
|
||||
"Specify an access list name\n"
|
||||
"Regular expression access list name\n"
|
||||
@ -418,6 +418,13 @@ DEFUN(ip_as_path, ip_as_path_cmd,
|
||||
regex_t *regex;
|
||||
char *regstr;
|
||||
|
||||
if (argv_find(argv, argc, "ip", &idx)) {
|
||||
vty_out(vty, "This config option is deprecated and is scheduled for removal.\n");
|
||||
vty_out(vty, "if you are using this please migrate to the below command\n");
|
||||
vty_out(vty, "'bgp as-path access-list WORD <deny|permit> LINE'\n");
|
||||
zlog_warn("Deprecated option: 'ip as-path access-list WORD <deny|permit> LINE' being used");
|
||||
}
|
||||
|
||||
/* Retrieve access list name */
|
||||
argv_find(argv, argc, "WORD", &idx);
|
||||
char *alname = argv[idx]->arg;
|
||||
@ -459,9 +466,23 @@ DEFUN(ip_as_path, ip_as_path_cmd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(no_ip_as_path, no_ip_as_path_cmd,
|
||||
"no ip as-path access-list WORD <deny|permit> LINE...",
|
||||
NO_STR IP_STR
|
||||
#if CONFDATE > 20191005
|
||||
CPP_NOTICE("bgpd: remove deprecated 'ip as-path access-list WORD <deny|permit> LINE' command")
|
||||
#endif
|
||||
ALIAS(as_path, ip_as_path_cmd,
|
||||
"ip as-path access-list WORD <deny|permit> LINE...",
|
||||
IP_STR
|
||||
"BGP autonomous system path filter\n"
|
||||
"Specify an access list name\n"
|
||||
"Regular expression access list name\n"
|
||||
"Specify packets to reject\n"
|
||||
"Specify packets to forward\n"
|
||||
"A regular-expression (1234567890_(^|[,{}() ]|$)) to match the BGP AS paths\n")
|
||||
|
||||
DEFUN(no_as_path, no_bgp_as_path_cmd,
|
||||
"no bgp as-path access-list WORD <deny|permit> LINE...",
|
||||
NO_STR
|
||||
BGP_STR
|
||||
"BGP autonomous system path filter\n"
|
||||
"Specify an access list name\n"
|
||||
"Regular expression access list name\n"
|
||||
@ -476,13 +497,19 @@ DEFUN(no_ip_as_path, no_ip_as_path_cmd,
|
||||
char *regstr;
|
||||
regex_t *regex;
|
||||
|
||||
if (argv_find(argv, argc, "ip", &idx)) {
|
||||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||||
vty_out(vty, "if you are using this please migrate to the below command\n");
|
||||
vty_out(vty, "'no bgp as-path access-list WORD <deny|permit> LINE'\n");
|
||||
zlog_warn("Deprecated option: 'no ip as-path access-list WORD <deny|permit> LINE' being used");
|
||||
}
|
||||
char *aslistname =
|
||||
argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL;
|
||||
|
||||
/* Lookup AS list from AS path list. */
|
||||
aslist = as_list_lookup(aslistname);
|
||||
if (aslist == NULL) {
|
||||
vty_out(vty, "ip as-path access-list %s doesn't exist\n",
|
||||
vty_out(vty, "bgp as-path access-list %s doesn't exist\n",
|
||||
aslistname);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
@ -530,21 +557,39 @@ DEFUN(no_ip_as_path, no_ip_as_path_cmd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_ip_as_path_all,
|
||||
no_ip_as_path_all_cmd,
|
||||
"no ip as-path access-list WORD",
|
||||
ALIAS(no_as_path, no_ip_as_path_cmd,
|
||||
"no ip as-path access-list WORD <deny|permit> LINE...",
|
||||
NO_STR IP_STR
|
||||
"BGP autonomous system path filter\n"
|
||||
"Specify an access list name\n"
|
||||
"Regular expression access list name\n"
|
||||
"Specify packets to reject\n"
|
||||
"Specify packets to forward\n"
|
||||
"A regular-expression (1234567890_(^|[,{}() ]|$)) to match the BGP AS paths\n")
|
||||
|
||||
DEFUN (no_as_path_all,
|
||||
no_bgp_as_path_all_cmd,
|
||||
"no bgp as-path access-list WORD",
|
||||
NO_STR
|
||||
IP_STR
|
||||
BGP_STR
|
||||
"BGP autonomous system path filter\n"
|
||||
"Specify an access list name\n"
|
||||
"Regular expression access list name\n")
|
||||
{
|
||||
int idx_word = 4;
|
||||
struct as_list *aslist;
|
||||
int idx = 0;
|
||||
|
||||
if (argv_find(argv, argc, "ip", &idx)) {
|
||||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||||
vty_out(vty, "if you are using this please migrate to the below command\n");
|
||||
vty_out(vty, "'no bgp as-path access-list WORD'\n");
|
||||
zlog_warn("Deprecated option: `no ip as-path access-list WORD` being used");
|
||||
}
|
||||
|
||||
aslist = as_list_lookup(argv[idx_word]->arg);
|
||||
if (aslist == NULL) {
|
||||
vty_out(vty, "ip as-path access-list %s doesn't exist\n",
|
||||
vty_out(vty, "bgp as-path access-list %s doesn't exist\n",
|
||||
argv[idx_word]->arg);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
@ -558,6 +603,15 @@ DEFUN (no_ip_as_path_all,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
ALIAS (no_as_path_all,
|
||||
no_ip_as_path_all_cmd,
|
||||
"no ip as-path access-list WORD",
|
||||
NO_STR
|
||||
IP_STR
|
||||
"BGP autonomous system path filter\n"
|
||||
"Specify an access list name\n"
|
||||
"Regular expression access list name\n")
|
||||
|
||||
static void as_list_show(struct vty *vty, struct as_list *aslist)
|
||||
{
|
||||
struct as_filter *asfilter;
|
||||
@ -598,17 +652,24 @@ static void as_list_show_all(struct vty *vty)
|
||||
}
|
||||
}
|
||||
|
||||
DEFUN (show_ip_as_path_access_list,
|
||||
show_ip_as_path_access_list_cmd,
|
||||
"show ip as-path-access-list WORD",
|
||||
DEFUN (show_as_path_access_list,
|
||||
show_bgp_as_path_access_list_cmd,
|
||||
"show bgp as-path-access-list WORD",
|
||||
SHOW_STR
|
||||
IP_STR
|
||||
BGP_STR
|
||||
"List AS path access lists\n"
|
||||
"AS path access list name\n")
|
||||
{
|
||||
int idx_word = 3;
|
||||
struct as_list *aslist;
|
||||
int idx = 0;
|
||||
|
||||
if (argv_find(argv, argc, "ip", &idx)) {
|
||||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||||
vty_out(vty, "if you are using this please migrate to the below command\n");
|
||||
vty_out(vty, "'show bgp as-path-access-list WORD'\n");
|
||||
zlog_warn("Deprecated option: 'show ip as-path-access-list WORD' being used");
|
||||
}
|
||||
aslist = as_list_lookup(argv[idx_word]->arg);
|
||||
if (aslist)
|
||||
as_list_show(vty, aslist);
|
||||
@ -616,16 +677,39 @@ DEFUN (show_ip_as_path_access_list,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_ip_as_path_access_list_all,
|
||||
ALIAS (show_as_path_access_list,
|
||||
show_ip_as_path_access_list_cmd,
|
||||
"show ip as-path-access-list WORD",
|
||||
SHOW_STR
|
||||
IP_STR
|
||||
"List AS path access lists\n"
|
||||
"AS path access list name\n")
|
||||
|
||||
DEFUN (show_as_path_access_list_all,
|
||||
show_bgp_as_path_access_list_all_cmd,
|
||||
"show bgp as-path-access-list",
|
||||
SHOW_STR
|
||||
BGP_STR
|
||||
"List AS path access lists\n")
|
||||
{
|
||||
int idx = 0;
|
||||
|
||||
if (argv_find(argv, argc, "ip", &idx)) {
|
||||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||||
vty_out(vty, "if you are using this please migrate to the below command\n");
|
||||
vty_out(vty, "'show bgp as-path-access-list'\n");
|
||||
zlog_warn("Deprecated option: 'show ip as-path-access-list' being used");
|
||||
}
|
||||
as_list_show_all(vty);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
ALIAS (show_as_path_access_list_all,
|
||||
show_ip_as_path_access_list_all_cmd,
|
||||
"show ip as-path-access-list",
|
||||
SHOW_STR
|
||||
IP_STR
|
||||
"List AS path access lists\n")
|
||||
{
|
||||
as_list_show_all(vty);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int config_write_as_list(struct vty *vty)
|
||||
{
|
||||
@ -636,7 +720,7 @@ static int config_write_as_list(struct vty *vty)
|
||||
for (aslist = as_list_master.num.head; aslist; aslist = aslist->next)
|
||||
for (asfilter = aslist->head; asfilter;
|
||||
asfilter = asfilter->next) {
|
||||
vty_out(vty, "ip as-path access-list %s %s %s\n",
|
||||
vty_out(vty, "bgp as-path access-list %s %s %s\n",
|
||||
aslist->name, filter_type_str(asfilter->type),
|
||||
asfilter->reg_str);
|
||||
write++;
|
||||
@ -645,7 +729,7 @@ static int config_write_as_list(struct vty *vty)
|
||||
for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
|
||||
for (asfilter = aslist->head; asfilter;
|
||||
asfilter = asfilter->next) {
|
||||
vty_out(vty, "ip as-path access-list %s %s %s\n",
|
||||
vty_out(vty, "bgp as-path access-list %s %s %s\n",
|
||||
aslist->name, filter_type_str(asfilter->type),
|
||||
asfilter->reg_str);
|
||||
write++;
|
||||
@ -660,11 +744,16 @@ void bgp_filter_init(void)
|
||||
{
|
||||
install_node(&as_list_node, config_write_as_list);
|
||||
|
||||
install_element(CONFIG_NODE, &bgp_as_path_cmd);
|
||||
install_element(CONFIG_NODE, &ip_as_path_cmd);
|
||||
install_element(CONFIG_NODE, &no_bgp_as_path_cmd);
|
||||
install_element(CONFIG_NODE, &no_ip_as_path_cmd);
|
||||
install_element(CONFIG_NODE, &no_bgp_as_path_all_cmd);
|
||||
install_element(CONFIG_NODE, &no_ip_as_path_all_cmd);
|
||||
|
||||
install_element(VIEW_NODE, &show_bgp_as_path_access_list_cmd);
|
||||
install_element(VIEW_NODE, &show_ip_as_path_access_list_cmd);
|
||||
install_element(VIEW_NODE, &show_bgp_as_path_access_list_all_cmd);
|
||||
install_element(VIEW_NODE, &show_ip_as_path_access_list_all_cmd);
|
||||
}
|
||||
|
||||
|
@ -44,8 +44,8 @@ extern void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
|
||||
json_object *json_path);
|
||||
|
||||
extern void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
|
||||
struct bgp_info *binfo,
|
||||
int display, json_object *json_paths);
|
||||
struct bgp_path_info *path, int display,
|
||||
json_object *json_paths);
|
||||
extern int bgp_fs_config_write_pbr(struct vty *vty, struct bgp *bgp,
|
||||
afi_t afi, safi_t safi);
|
||||
|
||||
|
@ -253,8 +253,8 @@ void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
|
||||
}
|
||||
|
||||
void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
|
||||
struct bgp_info *binfo,
|
||||
int display, json_object *json_paths)
|
||||
struct bgp_path_info *path, int display,
|
||||
json_object *json_paths)
|
||||
{
|
||||
struct attr *attr;
|
||||
char return_string[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
|
||||
@ -274,9 +274,9 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
|
||||
else
|
||||
json_nlri_path = json_paths;
|
||||
}
|
||||
if (display == NLRI_STRING_FORMAT_LARGE && binfo)
|
||||
if (display == NLRI_STRING_FORMAT_LARGE && path)
|
||||
vty_out(vty, "BGP flowspec entry: (flags 0x%x)\n",
|
||||
binfo->flags);
|
||||
path->flags);
|
||||
bgp_fs_nlri_get_string((unsigned char *)
|
||||
p->u.prefix_flowspec.ptr,
|
||||
p->u.prefix_flowspec.prefixlen,
|
||||
@ -292,11 +292,11 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
|
||||
else if (json_paths && display == NLRI_STRING_FORMAT_JSON)
|
||||
json_object_array_add(json_paths, json_nlri_path);
|
||||
}
|
||||
if (!binfo)
|
||||
if (!path)
|
||||
return;
|
||||
if (binfo->attr && binfo->attr->ecommunity) {
|
||||
if (path->attr && path->attr->ecommunity) {
|
||||
/* Print attribute */
|
||||
attr = binfo->attr;
|
||||
attr = path->attr;
|
||||
s = ecommunity_ecom2str(attr->ecommunity,
|
||||
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
if (!s)
|
||||
@ -318,7 +318,7 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
|
||||
vty_out(vty, "\tNH %-16s\n", inet_ntoa(attr->nexthop));
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, s);
|
||||
}
|
||||
peer_uptime(binfo->uptime, timebuf, BGP_UPTIME_LEN, 0, NULL);
|
||||
peer_uptime(path->uptime, timebuf, BGP_UPTIME_LEN, 0, NULL);
|
||||
if (display == NLRI_STRING_FORMAT_LARGE) {
|
||||
vty_out(vty, "\treceived for %8s\n", timebuf);
|
||||
} else if (json_paths) {
|
||||
@ -329,7 +329,8 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
|
||||
json_object_array_add(json_paths, json_time_path);
|
||||
}
|
||||
if (display == NLRI_STRING_FORMAT_LARGE) {
|
||||
struct bgp_info_extra *extra = bgp_info_extra_get(binfo);
|
||||
struct bgp_path_info_extra *extra =
|
||||
bgp_path_info_extra_get(path);
|
||||
|
||||
if (extra->bgp_fs_pbr) {
|
||||
struct listnode *node;
|
||||
@ -368,7 +369,7 @@ int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
void *output_arg, bool use_json, int is_last,
|
||||
unsigned long *output_cum, unsigned long *total_cum)
|
||||
{
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *pi;
|
||||
struct bgp_node *rn;
|
||||
unsigned long total_count = 0;
|
||||
json_object *json_paths = NULL;
|
||||
@ -384,12 +385,10 @@ int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
json_paths = json_object_new_array();
|
||||
display = NLRI_STRING_FORMAT_JSON;
|
||||
}
|
||||
for (ri = rn->info; ri; ri = ri->next) {
|
||||
for (pi = rn->info; pi; pi = pi->next) {
|
||||
total_count++;
|
||||
route_vty_out_flowspec(vty, &rn->p,
|
||||
ri, display,
|
||||
route_vty_out_flowspec(vty, &rn->p, pi, display,
|
||||
json_paths);
|
||||
|
||||
}
|
||||
if (use_json) {
|
||||
vty_out(vty, "%s\n",
|
||||
|
@ -931,7 +931,7 @@ static void bgp_update_delay_process_status_change(struct peer *peer)
|
||||
}
|
||||
}
|
||||
|
||||
/* Called after event occured, this function change status and reset
|
||||
/* Called after event occurred, this function change status and reset
|
||||
read/write and timer thread. */
|
||||
void bgp_fsm_change_status(struct peer *peer, int status)
|
||||
{
|
||||
@ -1677,6 +1677,15 @@ static int bgp_establish(struct peer *peer)
|
||||
peer_delete(peer->doppelganger);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are replacing the old peer for a doppelganger
|
||||
* then switch it around in the bgp->peerhash
|
||||
* the doppelgangers su and this peer's su are the same
|
||||
* so the hash_release is the same for either.
|
||||
*/
|
||||
hash_release(peer->bgp->peerhash, peer);
|
||||
hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
|
||||
|
||||
bgp_bfd_register_peer(peer);
|
||||
return ret;
|
||||
}
|
||||
|
@ -123,10 +123,11 @@ static void peer_process(struct hash_backet *hb, void *arg)
|
||||
*next_update = diff;
|
||||
}
|
||||
|
||||
static int peer_hash_cmp(const void *f, const void *s)
|
||||
static bool peer_hash_cmp(const void *f, const void *s)
|
||||
{
|
||||
const struct pkat *p1 = f;
|
||||
const struct pkat *p2 = s;
|
||||
|
||||
return p1->peer == p2->peer;
|
||||
}
|
||||
|
||||
|
@ -94,18 +94,18 @@ int bgp_parse_fec_update(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri,
|
||||
mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_path_info *pi,
|
||||
struct peer *to, afi_t afi, safi_t safi)
|
||||
{
|
||||
struct peer *from;
|
||||
mpls_label_t remote_label;
|
||||
int reflect;
|
||||
|
||||
if (!rn || !ri || !to)
|
||||
if (!rn || !pi || !to)
|
||||
return MPLS_INVALID_LABEL;
|
||||
|
||||
remote_label = ri->extra ? ri->extra->label[0] : MPLS_INVALID_LABEL;
|
||||
from = ri->peer;
|
||||
remote_label = pi->extra ? pi->extra->label[0] : MPLS_INVALID_LABEL;
|
||||
from = pi->peer;
|
||||
reflect =
|
||||
((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP));
|
||||
|
||||
@ -120,7 +120,8 @@ mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri,
|
||||
return rn->local_label;
|
||||
}
|
||||
|
||||
void bgp_reg_dereg_for_label(struct bgp_node *rn, struct bgp_info *ri, int reg)
|
||||
void bgp_reg_dereg_for_label(struct bgp_node *rn, struct bgp_path_info *pi,
|
||||
int reg)
|
||||
{
|
||||
struct stream *s;
|
||||
struct prefix *p;
|
||||
@ -142,11 +143,11 @@ void bgp_reg_dereg_for_label(struct bgp_node *rn, struct bgp_info *ri, int reg)
|
||||
stream_putw(s, PREFIX_FAMILY(p));
|
||||
stream_put_prefix(s, p);
|
||||
if (reg) {
|
||||
assert(ri);
|
||||
if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
|
||||
if (ri->attr->label_index != BGP_INVALID_LABEL_INDEX) {
|
||||
assert(pi);
|
||||
if (pi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
|
||||
if (pi->attr->label_index != BGP_INVALID_LABEL_INDEX) {
|
||||
flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX;
|
||||
stream_putl(s, ri->attr->label_index);
|
||||
stream_putl(s, pi->attr->label_index);
|
||||
}
|
||||
}
|
||||
SET_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);
|
||||
|
@ -27,13 +27,13 @@
|
||||
#define BGP_PREVENT_VRF_2_VRF_LEAK 0xFFFFFFFE
|
||||
|
||||
struct bgp_node;
|
||||
struct bgp_info;
|
||||
struct bgp_path_info;
|
||||
struct peer;
|
||||
|
||||
extern void bgp_reg_dereg_for_label(struct bgp_node *rn, struct bgp_info *ri,
|
||||
int reg);
|
||||
extern void bgp_reg_dereg_for_label(struct bgp_node *rn,
|
||||
struct bgp_path_info *pi, int reg);
|
||||
extern int bgp_parse_fec_update(void);
|
||||
extern mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri,
|
||||
extern mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_path_info *pi,
|
||||
struct peer *to, afi_t afi, safi_t safi);
|
||||
|
||||
extern int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
|
||||
@ -85,9 +85,9 @@ static inline void bgp_unset_valid_label(mpls_label_t *label)
|
||||
}
|
||||
|
||||
static inline void bgp_register_for_label(struct bgp_node *rn,
|
||||
struct bgp_info *ri)
|
||||
struct bgp_path_info *pi)
|
||||
{
|
||||
bgp_reg_dereg_for_label(rn, ri, 1);
|
||||
bgp_reg_dereg_for_label(rn, pi, 1);
|
||||
}
|
||||
|
||||
static inline void bgp_unregister_for_label(struct bgp_node *rn)
|
||||
|
@ -313,11 +313,17 @@ unsigned int lcommunity_hash_make(void *arg)
|
||||
}
|
||||
|
||||
/* Compare two Large Communities Attribute structure. */
|
||||
int lcommunity_cmp(const void *arg1, const void *arg2)
|
||||
bool lcommunity_cmp(const void *arg1, const void *arg2)
|
||||
{
|
||||
const struct lcommunity *lcom1 = arg1;
|
||||
const struct lcommunity *lcom2 = arg2;
|
||||
|
||||
if (lcom1 == NULL && lcom2 == NULL)
|
||||
return 1;
|
||||
|
||||
if (lcom1 == NULL || lcom2 == NULL)
|
||||
return 0;
|
||||
|
||||
return (lcom1->size == lcom2->size
|
||||
&& memcmp(lcom1->val, lcom2->val, lcom_length(lcom1)) == 0);
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ extern struct lcommunity *lcommunity_merge(struct lcommunity *,
|
||||
struct lcommunity *);
|
||||
extern struct lcommunity *lcommunity_uniq_sort(struct lcommunity *);
|
||||
extern struct lcommunity *lcommunity_intern(struct lcommunity *);
|
||||
extern int lcommunity_cmp(const void *, const void *);
|
||||
extern bool lcommunity_cmp(const void *arg1, const void *arg2);
|
||||
extern void lcommunity_unintern(struct lcommunity **);
|
||||
extern unsigned int lcommunity_hash_make(void *);
|
||||
extern struct hash *lcommunity_hash(void);
|
||||
|
318
bgpd/bgp_mpath.c
318
bgpd/bgp_mpath.c
@ -113,45 +113,47 @@ static int bgp_interface_same(struct interface *ifp1, struct interface *ifp2)
|
||||
|
||||
|
||||
/*
|
||||
* bgp_info_nexthop_cmp
|
||||
* bgp_path_info_nexthop_cmp
|
||||
*
|
||||
* Compare the nexthops of two paths. Return value is less than, equal to,
|
||||
* or greater than zero if bi1 is respectively less than, equal to,
|
||||
* or greater than bi2.
|
||||
* or greater than zero if bpi1 is respectively less than, equal to,
|
||||
* or greater than bpi2.
|
||||
*/
|
||||
int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2)
|
||||
int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1,
|
||||
struct bgp_path_info *bpi2)
|
||||
{
|
||||
int compare;
|
||||
struct in6_addr addr1, addr2;
|
||||
|
||||
compare = IPV4_ADDR_CMP(&bi1->attr->nexthop, &bi2->attr->nexthop);
|
||||
compare = IPV4_ADDR_CMP(&bpi1->attr->nexthop, &bpi2->attr->nexthop);
|
||||
if (!compare) {
|
||||
if (bi1->attr->mp_nexthop_len == bi2->attr->mp_nexthop_len) {
|
||||
switch (bi1->attr->mp_nexthop_len) {
|
||||
if (bpi1->attr->mp_nexthop_len == bpi2->attr->mp_nexthop_len) {
|
||||
switch (bpi1->attr->mp_nexthop_len) {
|
||||
case BGP_ATTR_NHLEN_IPV4:
|
||||
case BGP_ATTR_NHLEN_VPNV4:
|
||||
compare = IPV4_ADDR_CMP(
|
||||
&bi1->attr->mp_nexthop_global_in,
|
||||
&bi2->attr->mp_nexthop_global_in);
|
||||
&bpi1->attr->mp_nexthop_global_in,
|
||||
&bpi2->attr->mp_nexthop_global_in);
|
||||
break;
|
||||
case BGP_ATTR_NHLEN_IPV6_GLOBAL:
|
||||
case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
|
||||
compare = IPV6_ADDR_CMP(
|
||||
&bi1->attr->mp_nexthop_global,
|
||||
&bi2->attr->mp_nexthop_global);
|
||||
&bpi1->attr->mp_nexthop_global,
|
||||
&bpi2->attr->mp_nexthop_global);
|
||||
break;
|
||||
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
|
||||
addr1 = (bi1->attr->mp_nexthop_prefer_global)
|
||||
? bi1->attr->mp_nexthop_global
|
||||
: bi1->attr->mp_nexthop_local;
|
||||
addr2 = (bi2->attr->mp_nexthop_prefer_global)
|
||||
? bi2->attr->mp_nexthop_global
|
||||
: bi2->attr->mp_nexthop_local;
|
||||
addr1 = (bpi1->attr->mp_nexthop_prefer_global)
|
||||
? bpi1->attr->mp_nexthop_global
|
||||
: bpi1->attr->mp_nexthop_local;
|
||||
addr2 = (bpi2->attr->mp_nexthop_prefer_global)
|
||||
? bpi2->attr->mp_nexthop_global
|
||||
: bpi2->attr->mp_nexthop_local;
|
||||
|
||||
if (!bi1->attr->mp_nexthop_prefer_global
|
||||
&& !bi2->attr->mp_nexthop_prefer_global)
|
||||
if (!bpi1->attr->mp_nexthop_prefer_global
|
||||
&& !bpi2->attr->mp_nexthop_prefer_global)
|
||||
compare = !bgp_interface_same(
|
||||
bi1->peer->ifp, bi2->peer->ifp);
|
||||
bpi1->peer->ifp,
|
||||
bpi2->peer->ifp);
|
||||
|
||||
if (!compare)
|
||||
compare = IPV6_ADDR_CMP(&addr1, &addr2);
|
||||
@ -163,14 +165,15 @@ int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2)
|
||||
* link-local
|
||||
* nexthops but another IPv6 peer only sends you global
|
||||
*/
|
||||
else if (bi1->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL
|
||||
|| bi1->attr->mp_nexthop_len
|
||||
else if (bpi1->attr->mp_nexthop_len
|
||||
== BGP_ATTR_NHLEN_IPV6_GLOBAL
|
||||
|| bpi1->attr->mp_nexthop_len
|
||||
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
|
||||
compare = IPV6_ADDR_CMP(&bi1->attr->mp_nexthop_global,
|
||||
&bi2->attr->mp_nexthop_global);
|
||||
compare = IPV6_ADDR_CMP(&bpi1->attr->mp_nexthop_global,
|
||||
&bpi2->attr->mp_nexthop_global);
|
||||
if (!compare) {
|
||||
if (bi1->attr->mp_nexthop_len
|
||||
< bi2->attr->mp_nexthop_len)
|
||||
if (bpi1->attr->mp_nexthop_len
|
||||
< bpi2->attr->mp_nexthop_len)
|
||||
compare = -1;
|
||||
else
|
||||
compare = 1;
|
||||
@ -182,7 +185,7 @@ int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2)
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_info_mpath_cmp
|
||||
* bgp_path_info_mpath_cmp
|
||||
*
|
||||
* This function determines our multipath list ordering. By ordering
|
||||
* the list we can deterministically select which paths are included
|
||||
@ -193,26 +196,26 @@ int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2)
|
||||
* The order of paths is determined first by received nexthop, and then
|
||||
* by peer address if the nexthops are the same.
|
||||
*/
|
||||
static int bgp_info_mpath_cmp(void *val1, void *val2)
|
||||
static int bgp_path_info_mpath_cmp(void *val1, void *val2)
|
||||
{
|
||||
struct bgp_info *bi1, *bi2;
|
||||
struct bgp_path_info *bpi1, *bpi2;
|
||||
int compare;
|
||||
|
||||
bi1 = val1;
|
||||
bi2 = val2;
|
||||
bpi1 = val1;
|
||||
bpi2 = val2;
|
||||
|
||||
compare = bgp_info_nexthop_cmp(bi1, bi2);
|
||||
compare = bgp_path_info_nexthop_cmp(bpi1, bpi2);
|
||||
|
||||
if (!compare) {
|
||||
if (!bi1->peer->su_remote && !bi2->peer->su_remote)
|
||||
if (!bpi1->peer->su_remote && !bpi2->peer->su_remote)
|
||||
compare = 0;
|
||||
else if (!bi1->peer->su_remote)
|
||||
else if (!bpi1->peer->su_remote)
|
||||
compare = 1;
|
||||
else if (!bi2->peer->su_remote)
|
||||
else if (!bpi2->peer->su_remote)
|
||||
compare = -1;
|
||||
else
|
||||
compare = sockunion_cmp(bi1->peer->su_remote,
|
||||
bi2->peer->su_remote);
|
||||
compare = sockunion_cmp(bpi1->peer->su_remote,
|
||||
bpi2->peer->su_remote);
|
||||
}
|
||||
|
||||
return compare;
|
||||
@ -228,7 +231,7 @@ void bgp_mp_list_init(struct list *mp_list)
|
||||
{
|
||||
assert(mp_list);
|
||||
memset(mp_list, 0, sizeof(struct list));
|
||||
mp_list->cmp = bgp_info_mpath_cmp;
|
||||
mp_list->cmp = bgp_path_info_mpath_cmp;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -247,31 +250,31 @@ void bgp_mp_list_clear(struct list *mp_list)
|
||||
*
|
||||
* Adds a multipath entry to the mp_list
|
||||
*/
|
||||
void bgp_mp_list_add(struct list *mp_list, struct bgp_info *mpinfo)
|
||||
void bgp_mp_list_add(struct list *mp_list, struct bgp_path_info *mpinfo)
|
||||
{
|
||||
assert(mp_list && mpinfo);
|
||||
listnode_add_sort(mp_list, mpinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_info_mpath_new
|
||||
* bgp_path_info_mpath_new
|
||||
*
|
||||
* Allocate and zero memory for a new bgp_info_mpath element
|
||||
* Allocate and zero memory for a new bgp_path_info_mpath element
|
||||
*/
|
||||
static struct bgp_info_mpath *bgp_info_mpath_new(void)
|
||||
static struct bgp_path_info_mpath *bgp_path_info_mpath_new(void)
|
||||
{
|
||||
struct bgp_info_mpath *new_mpath;
|
||||
new_mpath =
|
||||
XCALLOC(MTYPE_BGP_MPATH_INFO, sizeof(struct bgp_info_mpath));
|
||||
struct bgp_path_info_mpath *new_mpath;
|
||||
new_mpath = XCALLOC(MTYPE_BGP_MPATH_INFO,
|
||||
sizeof(struct bgp_path_info_mpath));
|
||||
return new_mpath;
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_info_mpath_free
|
||||
* bgp_path_info_mpath_free
|
||||
*
|
||||
* Release resources for a bgp_info_mpath element and zero out pointer
|
||||
* Release resources for a bgp_path_info_mpath element and zero out pointer
|
||||
*/
|
||||
void bgp_info_mpath_free(struct bgp_info_mpath **mpath)
|
||||
void bgp_path_info_mpath_free(struct bgp_path_info_mpath **mpath)
|
||||
{
|
||||
if (mpath && *mpath) {
|
||||
if ((*mpath)->mp_attr)
|
||||
@ -282,37 +285,38 @@ void bgp_info_mpath_free(struct bgp_info_mpath **mpath)
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_info_mpath_get
|
||||
* bgp_path_info_mpath_get
|
||||
*
|
||||
* Fetch the mpath element for the given bgp_info. Used for
|
||||
* Fetch the mpath element for the given bgp_path_info. Used for
|
||||
* doing lazy allocation.
|
||||
*/
|
||||
static struct bgp_info_mpath *bgp_info_mpath_get(struct bgp_info *binfo)
|
||||
static struct bgp_path_info_mpath *
|
||||
bgp_path_info_mpath_get(struct bgp_path_info *path)
|
||||
{
|
||||
struct bgp_info_mpath *mpath;
|
||||
if (!binfo->mpath) {
|
||||
mpath = bgp_info_mpath_new();
|
||||
struct bgp_path_info_mpath *mpath;
|
||||
if (!path->mpath) {
|
||||
mpath = bgp_path_info_mpath_new();
|
||||
if (!mpath)
|
||||
return NULL;
|
||||
binfo->mpath = mpath;
|
||||
mpath->mp_info = binfo;
|
||||
path->mpath = mpath;
|
||||
mpath->mp_info = path;
|
||||
}
|
||||
return binfo->mpath;
|
||||
return path->mpath;
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_info_mpath_enqueue
|
||||
* bgp_path_info_mpath_enqueue
|
||||
*
|
||||
* Enqueue a path onto the multipath list given the previous multipath
|
||||
* list entry
|
||||
*/
|
||||
static void bgp_info_mpath_enqueue(struct bgp_info *prev_info,
|
||||
struct bgp_info *binfo)
|
||||
static void bgp_path_info_mpath_enqueue(struct bgp_path_info *prev_info,
|
||||
struct bgp_path_info *path)
|
||||
{
|
||||
struct bgp_info_mpath *prev, *mpath;
|
||||
struct bgp_path_info_mpath *prev, *mpath;
|
||||
|
||||
prev = bgp_info_mpath_get(prev_info);
|
||||
mpath = bgp_info_mpath_get(binfo);
|
||||
prev = bgp_path_info_mpath_get(prev_info);
|
||||
mpath = bgp_path_info_mpath_get(path);
|
||||
if (!prev || !mpath)
|
||||
return;
|
||||
|
||||
@ -322,17 +326,17 @@ static void bgp_info_mpath_enqueue(struct bgp_info *prev_info,
|
||||
prev->mp_next->mp_prev = mpath;
|
||||
prev->mp_next = mpath;
|
||||
|
||||
SET_FLAG(binfo->flags, BGP_INFO_MULTIPATH);
|
||||
SET_FLAG(path->flags, BGP_PATH_MULTIPATH);
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_info_mpath_dequeue
|
||||
* bgp_path_info_mpath_dequeue
|
||||
*
|
||||
* Remove a path from the multipath list
|
||||
*/
|
||||
void bgp_info_mpath_dequeue(struct bgp_info *binfo)
|
||||
void bgp_path_info_mpath_dequeue(struct bgp_path_info *path)
|
||||
{
|
||||
struct bgp_info_mpath *mpath = binfo->mpath;
|
||||
struct bgp_path_info_mpath *mpath = path->mpath;
|
||||
if (!mpath)
|
||||
return;
|
||||
if (mpath->mp_prev)
|
||||
@ -340,101 +344,105 @@ void bgp_info_mpath_dequeue(struct bgp_info *binfo)
|
||||
if (mpath->mp_next)
|
||||
mpath->mp_next->mp_prev = mpath->mp_prev;
|
||||
mpath->mp_next = mpath->mp_prev = NULL;
|
||||
UNSET_FLAG(binfo->flags, BGP_INFO_MULTIPATH);
|
||||
UNSET_FLAG(path->flags, BGP_PATH_MULTIPATH);
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_info_mpath_next
|
||||
* bgp_path_info_mpath_next
|
||||
*
|
||||
* Given a bgp_info, return the next multipath entry
|
||||
* Given a bgp_path_info, return the next multipath entry
|
||||
*/
|
||||
struct bgp_info *bgp_info_mpath_next(struct bgp_info *binfo)
|
||||
struct bgp_path_info *bgp_path_info_mpath_next(struct bgp_path_info *path)
|
||||
{
|
||||
if (!binfo->mpath || !binfo->mpath->mp_next)
|
||||
if (!path->mpath || !path->mpath->mp_next)
|
||||
return NULL;
|
||||
return binfo->mpath->mp_next->mp_info;
|
||||
return path->mpath->mp_next->mp_info;
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_info_mpath_first
|
||||
* bgp_path_info_mpath_first
|
||||
*
|
||||
* Given bestpath bgp_info, return the first multipath entry.
|
||||
* Given bestpath bgp_path_info, return the first multipath entry.
|
||||
*/
|
||||
struct bgp_info *bgp_info_mpath_first(struct bgp_info *binfo)
|
||||
struct bgp_path_info *bgp_path_info_mpath_first(struct bgp_path_info *path)
|
||||
{
|
||||
return bgp_info_mpath_next(binfo);
|
||||
return bgp_path_info_mpath_next(path);
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_info_mpath_count
|
||||
* bgp_path_info_mpath_count
|
||||
*
|
||||
* Given the bestpath bgp_info, return the number of multipath entries
|
||||
* Given the bestpath bgp_path_info, return the number of multipath entries
|
||||
*/
|
||||
uint32_t bgp_info_mpath_count(struct bgp_info *binfo)
|
||||
uint32_t bgp_path_info_mpath_count(struct bgp_path_info *path)
|
||||
{
|
||||
if (!binfo->mpath)
|
||||
if (!path->mpath)
|
||||
return 0;
|
||||
return binfo->mpath->mp_count;
|
||||
return path->mpath->mp_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_info_mpath_count_set
|
||||
* bgp_path_info_mpath_count_set
|
||||
*
|
||||
* Sets the count of multipaths into bestpath's mpath element
|
||||
*/
|
||||
static void bgp_info_mpath_count_set(struct bgp_info *binfo, uint32_t count)
|
||||
static void bgp_path_info_mpath_count_set(struct bgp_path_info *path,
|
||||
uint32_t count)
|
||||
{
|
||||
struct bgp_info_mpath *mpath;
|
||||
if (!count && !binfo->mpath)
|
||||
struct bgp_path_info_mpath *mpath;
|
||||
if (!count && !path->mpath)
|
||||
return;
|
||||
mpath = bgp_info_mpath_get(binfo);
|
||||
mpath = bgp_path_info_mpath_get(path);
|
||||
if (!mpath)
|
||||
return;
|
||||
mpath->mp_count = count;
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_info_mpath_attr
|
||||
* bgp_path_info_mpath_attr
|
||||
*
|
||||
* Given bestpath bgp_info, return aggregated attribute set used
|
||||
* Given bestpath bgp_path_info, return aggregated attribute set used
|
||||
* for advertising the multipath route
|
||||
*/
|
||||
struct attr *bgp_info_mpath_attr(struct bgp_info *binfo)
|
||||
struct attr *bgp_path_info_mpath_attr(struct bgp_path_info *path)
|
||||
{
|
||||
if (!binfo->mpath)
|
||||
if (!path->mpath)
|
||||
return NULL;
|
||||
return binfo->mpath->mp_attr;
|
||||
return path->mpath->mp_attr;
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_info_mpath_attr_set
|
||||
* bgp_path_info_mpath_attr_set
|
||||
*
|
||||
* Sets the aggregated attribute into bestpath's mpath element
|
||||
*/
|
||||
static void bgp_info_mpath_attr_set(struct bgp_info *binfo, struct attr *attr)
|
||||
static void bgp_path_info_mpath_attr_set(struct bgp_path_info *path,
|
||||
struct attr *attr)
|
||||
{
|
||||
struct bgp_info_mpath *mpath;
|
||||
if (!attr && !binfo->mpath)
|
||||
struct bgp_path_info_mpath *mpath;
|
||||
if (!attr && !path->mpath)
|
||||
return;
|
||||
mpath = bgp_info_mpath_get(binfo);
|
||||
mpath = bgp_path_info_mpath_get(path);
|
||||
if (!mpath)
|
||||
return;
|
||||
mpath->mp_attr = attr;
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_info_mpath_update
|
||||
* bgp_path_info_mpath_update
|
||||
*
|
||||
* Compare and sync up the multipath list with the mp_list generated by
|
||||
* bgp_best_selection
|
||||
*/
|
||||
void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best,
|
||||
struct bgp_info *old_best, struct list *mp_list,
|
||||
struct bgp_maxpaths_cfg *mpath_cfg)
|
||||
void bgp_path_info_mpath_update(struct bgp_node *rn,
|
||||
struct bgp_path_info *new_best,
|
||||
struct bgp_path_info *old_best,
|
||||
struct list *mp_list,
|
||||
struct bgp_maxpaths_cfg *mpath_cfg)
|
||||
{
|
||||
uint16_t maxpaths, mpath_count, old_mpath_count;
|
||||
struct listnode *mp_node, *mp_next_node;
|
||||
struct bgp_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath;
|
||||
struct bgp_path_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath;
|
||||
int mpath_changed, debug;
|
||||
char pfx_buf[PREFIX2STR_BUFFER], nh_buf[2][INET6_ADDRSTRLEN];
|
||||
char path_buf[PATH_ADDPATH_STR_BUFFER];
|
||||
@ -454,17 +462,17 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best,
|
||||
if (new_best) {
|
||||
mpath_count++;
|
||||
if (new_best != old_best)
|
||||
bgp_info_mpath_dequeue(new_best);
|
||||
bgp_path_info_mpath_dequeue(new_best);
|
||||
maxpaths = (new_best->peer->sort == BGP_PEER_IBGP)
|
||||
? mpath_cfg->maxpaths_ibgp
|
||||
: mpath_cfg->maxpaths_ebgp;
|
||||
}
|
||||
|
||||
if (old_best) {
|
||||
cur_mpath = bgp_info_mpath_first(old_best);
|
||||
old_mpath_count = bgp_info_mpath_count(old_best);
|
||||
bgp_info_mpath_count_set(old_best, 0);
|
||||
bgp_info_mpath_dequeue(old_best);
|
||||
cur_mpath = bgp_path_info_mpath_first(old_best);
|
||||
old_mpath_count = bgp_path_info_mpath_count(old_best);
|
||||
bgp_path_info_mpath_count_set(old_best, 0);
|
||||
bgp_path_info_mpath_dequeue(old_best);
|
||||
}
|
||||
|
||||
if (debug)
|
||||
@ -485,7 +493,7 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best,
|
||||
* to skip over it
|
||||
*/
|
||||
while (mp_node || cur_mpath) {
|
||||
struct bgp_info *tmp_info;
|
||||
struct bgp_path_info *tmp_info;
|
||||
|
||||
/*
|
||||
* We can bail out of this loop if all existing paths on the
|
||||
@ -496,7 +504,8 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best,
|
||||
break;
|
||||
|
||||
mp_next_node = mp_node ? listnextnode(mp_node) : NULL;
|
||||
next_mpath = cur_mpath ? bgp_info_mpath_next(cur_mpath) : NULL;
|
||||
next_mpath =
|
||||
cur_mpath ? bgp_path_info_mpath_next(cur_mpath) : NULL;
|
||||
tmp_info = mp_node ? listgetdata(mp_node) : NULL;
|
||||
|
||||
if (debug)
|
||||
@ -512,14 +521,16 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best,
|
||||
*/
|
||||
if (mp_node && (listgetdata(mp_node) == cur_mpath)) {
|
||||
list_delete_node(mp_list, mp_node);
|
||||
bgp_info_mpath_dequeue(cur_mpath);
|
||||
bgp_path_info_mpath_dequeue(cur_mpath);
|
||||
if ((mpath_count < maxpaths)
|
||||
&& bgp_info_nexthop_cmp(prev_mpath, cur_mpath)) {
|
||||
bgp_info_mpath_enqueue(prev_mpath, cur_mpath);
|
||||
&& bgp_path_info_nexthop_cmp(prev_mpath,
|
||||
cur_mpath)) {
|
||||
bgp_path_info_mpath_enqueue(prev_mpath,
|
||||
cur_mpath);
|
||||
prev_mpath = cur_mpath;
|
||||
mpath_count++;
|
||||
if (debug) {
|
||||
bgp_info_path_with_addpath_rx_str(
|
||||
bgp_path_info_path_with_addpath_rx_str(
|
||||
cur_mpath, path_buf);
|
||||
zlog_debug(
|
||||
"%s: %s is still multipath, cur count %d",
|
||||
@ -528,7 +539,7 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best,
|
||||
} else {
|
||||
mpath_changed = 1;
|
||||
if (debug) {
|
||||
bgp_info_path_with_addpath_rx_str(
|
||||
bgp_path_info_path_with_addpath_rx_str(
|
||||
cur_mpath, path_buf);
|
||||
zlog_debug(
|
||||
"%s: remove mpath %s nexthop %s, cur count %d",
|
||||
@ -548,7 +559,8 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best,
|
||||
|
||||
if (cur_mpath
|
||||
&& (!mp_node
|
||||
|| (bgp_info_mpath_cmp(cur_mpath, listgetdata(mp_node))
|
||||
|| (bgp_path_info_mpath_cmp(cur_mpath,
|
||||
listgetdata(mp_node))
|
||||
< 0))) {
|
||||
/*
|
||||
* If here, we have an old multipath and either the
|
||||
@ -557,11 +569,11 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best,
|
||||
* multipath, so we need to purge this path from the
|
||||
* multipath list
|
||||
*/
|
||||
bgp_info_mpath_dequeue(cur_mpath);
|
||||
bgp_path_info_mpath_dequeue(cur_mpath);
|
||||
mpath_changed = 1;
|
||||
if (debug) {
|
||||
bgp_info_path_with_addpath_rx_str(cur_mpath,
|
||||
path_buf);
|
||||
bgp_path_info_path_with_addpath_rx_str(
|
||||
cur_mpath, path_buf);
|
||||
zlog_debug(
|
||||
"%s: remove mpath %s nexthop %s, cur count %d",
|
||||
pfx_buf, path_buf,
|
||||
@ -595,17 +607,19 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best,
|
||||
assert(new_mpath);
|
||||
assert(prev_mpath);
|
||||
if ((mpath_count < maxpaths) && (new_mpath != new_best)
|
||||
&& bgp_info_nexthop_cmp(prev_mpath, new_mpath)) {
|
||||
&& bgp_path_info_nexthop_cmp(prev_mpath,
|
||||
new_mpath)) {
|
||||
if (new_mpath == next_mpath)
|
||||
bgp_info_mpath_next(new_mpath);
|
||||
bgp_info_mpath_dequeue(new_mpath);
|
||||
bgp_path_info_mpath_next(new_mpath);
|
||||
bgp_path_info_mpath_dequeue(new_mpath);
|
||||
|
||||
bgp_info_mpath_enqueue(prev_mpath, new_mpath);
|
||||
bgp_path_info_mpath_enqueue(prev_mpath,
|
||||
new_mpath);
|
||||
prev_mpath = new_mpath;
|
||||
mpath_changed = 1;
|
||||
mpath_count++;
|
||||
if (debug) {
|
||||
bgp_info_path_with_addpath_rx_str(
|
||||
bgp_path_info_path_with_addpath_rx_str(
|
||||
new_mpath, path_buf);
|
||||
zlog_debug(
|
||||
"%s: add mpath %s nexthop %s, cur count %d",
|
||||
@ -629,39 +643,39 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best,
|
||||
pfx_buf, mpath_count,
|
||||
mpath_changed ? "YES" : "NO");
|
||||
|
||||
bgp_info_mpath_count_set(new_best, mpath_count - 1);
|
||||
bgp_path_info_mpath_count_set(new_best, mpath_count - 1);
|
||||
if (mpath_changed
|
||||
|| (bgp_info_mpath_count(new_best) != old_mpath_count))
|
||||
SET_FLAG(new_best->flags, BGP_INFO_MULTIPATH_CHG);
|
||||
|| (bgp_path_info_mpath_count(new_best) != old_mpath_count))
|
||||
SET_FLAG(new_best->flags, BGP_PATH_MULTIPATH_CHG);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_mp_dmed_deselect
|
||||
*
|
||||
* Clean up multipath information for BGP_INFO_DMED_SELECTED path that
|
||||
* Clean up multipath information for BGP_PATH_DMED_SELECTED path that
|
||||
* is not selected as best path
|
||||
*/
|
||||
void bgp_mp_dmed_deselect(struct bgp_info *dmed_best)
|
||||
void bgp_mp_dmed_deselect(struct bgp_path_info *dmed_best)
|
||||
{
|
||||
struct bgp_info *mpinfo, *mpnext;
|
||||
struct bgp_path_info *mpinfo, *mpnext;
|
||||
|
||||
if (!dmed_best)
|
||||
return;
|
||||
|
||||
for (mpinfo = bgp_info_mpath_first(dmed_best); mpinfo;
|
||||
for (mpinfo = bgp_path_info_mpath_first(dmed_best); mpinfo;
|
||||
mpinfo = mpnext) {
|
||||
mpnext = bgp_info_mpath_next(mpinfo);
|
||||
bgp_info_mpath_dequeue(mpinfo);
|
||||
mpnext = bgp_path_info_mpath_next(mpinfo);
|
||||
bgp_path_info_mpath_dequeue(mpinfo);
|
||||
}
|
||||
|
||||
bgp_info_mpath_count_set(dmed_best, 0);
|
||||
UNSET_FLAG(dmed_best->flags, BGP_INFO_MULTIPATH_CHG);
|
||||
assert(bgp_info_mpath_first(dmed_best) == 0);
|
||||
bgp_path_info_mpath_count_set(dmed_best, 0);
|
||||
UNSET_FLAG(dmed_best->flags, BGP_PATH_MULTIPATH_CHG);
|
||||
assert(bgp_path_info_mpath_first(dmed_best) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_info_mpath_aggregate_update
|
||||
* bgp_path_info_mpath_aggregate_update
|
||||
*
|
||||
* Set the multipath aggregate attribute. We need to see if the
|
||||
* aggregate has changed and then set the ATTR_CHANGED flag on the
|
||||
@ -672,10 +686,10 @@ void bgp_mp_dmed_deselect(struct bgp_info *dmed_best)
|
||||
* is no change in multipath selection and no attribute change in
|
||||
* any multipath.
|
||||
*/
|
||||
void bgp_info_mpath_aggregate_update(struct bgp_info *new_best,
|
||||
struct bgp_info *old_best)
|
||||
void bgp_path_info_mpath_aggregate_update(struct bgp_path_info *new_best,
|
||||
struct bgp_path_info *old_best)
|
||||
{
|
||||
struct bgp_info *mpinfo;
|
||||
struct bgp_path_info *mpinfo;
|
||||
struct aspath *aspath;
|
||||
struct aspath *asmerge;
|
||||
struct attr *new_attr, *old_attr;
|
||||
@ -686,19 +700,19 @@ void bgp_info_mpath_aggregate_update(struct bgp_info *new_best,
|
||||
struct attr attr = {0};
|
||||
|
||||
if (old_best && (old_best != new_best)
|
||||
&& (old_attr = bgp_info_mpath_attr(old_best))) {
|
||||
&& (old_attr = bgp_path_info_mpath_attr(old_best))) {
|
||||
bgp_attr_unintern(&old_attr);
|
||||
bgp_info_mpath_attr_set(old_best, NULL);
|
||||
bgp_path_info_mpath_attr_set(old_best, NULL);
|
||||
}
|
||||
|
||||
if (!new_best)
|
||||
return;
|
||||
|
||||
if (!bgp_info_mpath_count(new_best)) {
|
||||
if ((new_attr = bgp_info_mpath_attr(new_best))) {
|
||||
if (!bgp_path_info_mpath_count(new_best)) {
|
||||
if ((new_attr = bgp_path_info_mpath_attr(new_best))) {
|
||||
bgp_attr_unintern(&new_attr);
|
||||
bgp_info_mpath_attr_set(new_best, NULL);
|
||||
SET_FLAG(new_best->flags, BGP_INFO_ATTR_CHANGED);
|
||||
bgp_path_info_mpath_attr_set(new_best, NULL);
|
||||
SET_FLAG(new_best->flags, BGP_PATH_ATTR_CHANGED);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -718,8 +732,8 @@ void bgp_info_mpath_aggregate_update(struct bgp_info *new_best,
|
||||
lcomm = (attr.lcommunity) ? lcommunity_dup(attr.lcommunity)
|
||||
: NULL;
|
||||
|
||||
for (mpinfo = bgp_info_mpath_first(new_best); mpinfo;
|
||||
mpinfo = bgp_info_mpath_next(mpinfo)) {
|
||||
for (mpinfo = bgp_path_info_mpath_first(new_best); mpinfo;
|
||||
mpinfo = bgp_path_info_mpath_next(mpinfo)) {
|
||||
asmerge =
|
||||
aspath_aggregate(aspath, mpinfo->attr->aspath);
|
||||
aspath_free(aspath);
|
||||
@ -735,7 +749,7 @@ void bgp_info_mpath_aggregate_update(struct bgp_info *new_best,
|
||||
mpinfo->attr->community);
|
||||
community =
|
||||
community_uniq_sort(commerge);
|
||||
community_free(commerge);
|
||||
community_free(&commerge);
|
||||
} else
|
||||
community = community_dup(
|
||||
mpinfo->attr->community);
|
||||
@ -789,11 +803,11 @@ void bgp_info_mpath_aggregate_update(struct bgp_info *new_best,
|
||||
|
||||
new_attr = bgp_attr_intern(&attr);
|
||||
|
||||
if (new_attr != bgp_info_mpath_attr(new_best)) {
|
||||
if ((old_attr = bgp_info_mpath_attr(new_best)))
|
||||
if (new_attr != bgp_path_info_mpath_attr(new_best)) {
|
||||
if ((old_attr = bgp_path_info_mpath_attr(new_best)))
|
||||
bgp_attr_unintern(&old_attr);
|
||||
bgp_info_mpath_attr_set(new_best, new_attr);
|
||||
SET_FLAG(new_best->flags, BGP_INFO_ATTR_CHANGED);
|
||||
bgp_path_info_mpath_attr_set(new_best, new_attr);
|
||||
SET_FLAG(new_best->flags, BGP_PATH_ATTR_CHANGED);
|
||||
} else
|
||||
bgp_attr_unintern(&new_attr);
|
||||
}
|
||||
|
@ -22,18 +22,18 @@
|
||||
#ifndef _QUAGGA_BGP_MPATH_H
|
||||
#define _QUAGGA_BGP_MPATH_H
|
||||
|
||||
/* Supplemental information linked to bgp_info for keeping track of
|
||||
/* Supplemental information linked to bgp_path_info for keeping track of
|
||||
* multipath selections, lazily allocated to save memory
|
||||
*/
|
||||
struct bgp_info_mpath {
|
||||
struct bgp_path_info_mpath {
|
||||
/* Points to the first multipath (on bestpath) or the next multipath */
|
||||
struct bgp_info_mpath *mp_next;
|
||||
struct bgp_path_info_mpath *mp_next;
|
||||
|
||||
/* Points to the previous multipath or NULL on bestpath */
|
||||
struct bgp_info_mpath *mp_prev;
|
||||
struct bgp_path_info_mpath *mp_prev;
|
||||
|
||||
/* Points to bgp_info associated with this multipath info */
|
||||
struct bgp_info *mp_info;
|
||||
/* Points to bgp_path_info associated with this multipath info */
|
||||
struct bgp_path_info *mp_info;
|
||||
|
||||
/* When attached to best path, the number of selected multipaths */
|
||||
uint32_t mp_count;
|
||||
@ -50,27 +50,33 @@ extern int bgp_maximum_paths_unset(struct bgp *, afi_t, safi_t, int);
|
||||
/* Functions used by bgp_best_selection to record current
|
||||
* multipath selections
|
||||
*/
|
||||
extern int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2);
|
||||
extern int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1,
|
||||
struct bgp_path_info *bpi2);
|
||||
extern void bgp_mp_list_init(struct list *);
|
||||
extern void bgp_mp_list_clear(struct list *);
|
||||
extern void bgp_mp_list_add(struct list *, struct bgp_info *);
|
||||
extern void bgp_mp_dmed_deselect(struct bgp_info *);
|
||||
extern void bgp_info_mpath_update(struct bgp_node *, struct bgp_info *,
|
||||
struct bgp_info *, struct list *,
|
||||
struct bgp_maxpaths_cfg *);
|
||||
extern void bgp_info_mpath_aggregate_update(struct bgp_info *,
|
||||
struct bgp_info *);
|
||||
extern void bgp_mp_list_add(struct list *mp_list, struct bgp_path_info *mpinfo);
|
||||
extern void bgp_mp_dmed_deselect(struct bgp_path_info *dmed_best);
|
||||
extern void bgp_path_info_mpath_update(struct bgp_node *rn,
|
||||
struct bgp_path_info *new_best,
|
||||
struct bgp_path_info *old_best,
|
||||
struct list *mp_list,
|
||||
struct bgp_maxpaths_cfg *mpath_cfg);
|
||||
extern void
|
||||
bgp_path_info_mpath_aggregate_update(struct bgp_path_info *new_best,
|
||||
struct bgp_path_info *old_best);
|
||||
|
||||
/* Unlink and free multipath information associated with a bgp_info */
|
||||
extern void bgp_info_mpath_dequeue(struct bgp_info *);
|
||||
extern void bgp_info_mpath_free(struct bgp_info_mpath **);
|
||||
/* Unlink and free multipath information associated with a bgp_path_info */
|
||||
extern void bgp_path_info_mpath_dequeue(struct bgp_path_info *path);
|
||||
extern void bgp_path_info_mpath_free(struct bgp_path_info_mpath **mpath);
|
||||
|
||||
/* Walk list of multipaths associated with a best path */
|
||||
extern struct bgp_info *bgp_info_mpath_first(struct bgp_info *);
|
||||
extern struct bgp_info *bgp_info_mpath_next(struct bgp_info *);
|
||||
extern struct bgp_path_info *
|
||||
bgp_path_info_mpath_first(struct bgp_path_info *path);
|
||||
extern struct bgp_path_info *
|
||||
bgp_path_info_mpath_next(struct bgp_path_info *path);
|
||||
|
||||
/* Accessors for multipath information */
|
||||
extern uint32_t bgp_info_mpath_count(struct bgp_info *);
|
||||
extern struct attr *bgp_info_mpath_attr(struct bgp_info *);
|
||||
extern uint32_t bgp_path_info_mpath_count(struct bgp_path_info *path);
|
||||
extern struct attr *bgp_path_info_mpath_attr(struct bgp_path_info *path);
|
||||
|
||||
#endif /* _QUAGGA_BGP_MPATH_H */
|
||||
|
@ -402,22 +402,23 @@ static int ecom_intersect(struct ecommunity *e1, struct ecommunity *e2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool labels_same(struct bgp_info *bi, mpls_label_t *label, uint32_t n)
|
||||
static bool labels_same(struct bgp_path_info *bpi, mpls_label_t *label,
|
||||
uint32_t n)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if (!bi->extra) {
|
||||
if (!bpi->extra) {
|
||||
if (!n)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if (n != bi->extra->num_labels)
|
||||
if (n != bpi->extra->num_labels)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (label[i] != bi->extra->label[i])
|
||||
if (label[i] != bpi->extra->label[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -426,22 +427,21 @@ static bool labels_same(struct bgp_info *bi, mpls_label_t *label, uint32_t n)
|
||||
/*
|
||||
* make encoded route labels match specified encoded label set
|
||||
*/
|
||||
static void setlabels(
|
||||
struct bgp_info *bi,
|
||||
mpls_label_t *label, /* array of labels */
|
||||
uint32_t num_labels)
|
||||
static void setlabels(struct bgp_path_info *bpi,
|
||||
mpls_label_t *label, /* array of labels */
|
||||
uint32_t num_labels)
|
||||
{
|
||||
if (num_labels)
|
||||
assert(label);
|
||||
assert(num_labels <= BGP_MAX_LABELS);
|
||||
|
||||
if (!num_labels) {
|
||||
if (bi->extra)
|
||||
bi->extra->num_labels = 0;
|
||||
if (bpi->extra)
|
||||
bpi->extra->num_labels = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
struct bgp_info_extra *extra = bgp_info_extra_get(bi);
|
||||
struct bgp_path_info_extra *extra = bgp_path_info_extra_get(bpi);
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < num_labels; ++i) {
|
||||
@ -454,35 +454,27 @@ static void setlabels(
|
||||
}
|
||||
|
||||
/*
|
||||
* returns pointer to new bgp_info upon success
|
||||
* returns pointer to new bgp_path_info upon success
|
||||
*/
|
||||
static struct bgp_info *
|
||||
leak_update(
|
||||
struct bgp *bgp, /* destination bgp instance */
|
||||
struct bgp_node *bn,
|
||||
struct attr *new_attr, /* already interned */
|
||||
afi_t afi,
|
||||
safi_t safi,
|
||||
struct bgp_info *source_bi,
|
||||
mpls_label_t *label,
|
||||
uint32_t num_labels,
|
||||
void *parent,
|
||||
struct bgp *bgp_orig,
|
||||
struct prefix *nexthop_orig,
|
||||
int nexthop_self_flag,
|
||||
int debug)
|
||||
static struct bgp_path_info *
|
||||
leak_update(struct bgp *bgp, /* destination bgp instance */
|
||||
struct bgp_node *bn, struct attr *new_attr, /* already interned */
|
||||
afi_t afi, safi_t safi, struct bgp_path_info *source_bpi,
|
||||
mpls_label_t *label, uint32_t num_labels, void *parent,
|
||||
struct bgp *bgp_orig, struct prefix *nexthop_orig,
|
||||
int nexthop_self_flag, int debug)
|
||||
{
|
||||
struct prefix *p = &bn->p;
|
||||
struct bgp_info *bi;
|
||||
struct bgp_info *bi_ultimate;
|
||||
struct bgp_info *new;
|
||||
struct bgp_path_info *bpi;
|
||||
struct bgp_path_info *bpi_ultimate;
|
||||
struct bgp_path_info *new;
|
||||
char buf_prefix[PREFIX_STRLEN];
|
||||
|
||||
if (debug) {
|
||||
prefix2str(&bn->p, buf_prefix, sizeof(buf_prefix));
|
||||
zlog_debug("%s: entry: leak-to=%s, p=%s, type=%d, sub_type=%d",
|
||||
__func__, bgp->name_pretty, buf_prefix,
|
||||
source_bi->type, source_bi->sub_type);
|
||||
__func__, bgp->name_pretty, buf_prefix,
|
||||
source_bpi->type, source_bpi->sub_type);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -494,31 +486,30 @@ leak_update(
|
||||
* should have nexthop tracking, we must find the ultimate
|
||||
* parent so we can check its sub_type.
|
||||
*
|
||||
* As of now, source_bi may at most be a second-generation route
|
||||
* As of now, source_bpi may at most be a second-generation route
|
||||
* (only one hop back to ultimate parent for vrf-vpn-vrf scheme).
|
||||
* Using a loop here supports more complex intra-bgp import-export
|
||||
* schemes that could be implemented in the future.
|
||||
*
|
||||
*/
|
||||
for (bi_ultimate = source_bi;
|
||||
bi_ultimate->extra && bi_ultimate->extra->parent;
|
||||
bi_ultimate = bi_ultimate->extra->parent)
|
||||
;
|
||||
for (bpi_ultimate = source_bpi;
|
||||
bpi_ultimate->extra && bpi_ultimate->extra->parent;
|
||||
bpi_ultimate = bpi_ultimate->extra->parent)
|
||||
;
|
||||
|
||||
/*
|
||||
* match parent
|
||||
*/
|
||||
for (bi = bn->info; bi; bi = bi->next) {
|
||||
if (bi->extra && bi->extra->parent == parent)
|
||||
for (bpi = bn->info; bpi; bpi = bpi->next) {
|
||||
if (bpi->extra && bpi->extra->parent == parent)
|
||||
break;
|
||||
}
|
||||
|
||||
if (bi) {
|
||||
bool labelssame = labels_same(bi, label, num_labels);
|
||||
if (bpi) {
|
||||
bool labelssame = labels_same(bpi, label, num_labels);
|
||||
|
||||
if (attrhash_cmp(bi->attr, new_attr)
|
||||
&& labelssame
|
||||
&& !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) {
|
||||
if (attrhash_cmp(bpi->attr, new_attr) && labelssame
|
||||
&& !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
|
||||
|
||||
bgp_attr_unintern(&new_attr);
|
||||
if (debug)
|
||||
@ -530,43 +521,42 @@ leak_update(
|
||||
}
|
||||
|
||||
/* attr is changed */
|
||||
bgp_info_set_flag(bn, bi, BGP_INFO_ATTR_CHANGED);
|
||||
bgp_path_info_set_flag(bn, bpi, BGP_PATH_ATTR_CHANGED);
|
||||
|
||||
/* Rewrite BGP route information. */
|
||||
if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
|
||||
bgp_info_restore(bn, bi);
|
||||
if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
|
||||
bgp_path_info_restore(bn, bpi);
|
||||
else
|
||||
bgp_aggregate_decrement(bgp, p, bi, afi, safi);
|
||||
bgp_attr_unintern(&bi->attr);
|
||||
bi->attr = new_attr;
|
||||
bi->uptime = bgp_clock();
|
||||
bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
|
||||
bgp_attr_unintern(&bpi->attr);
|
||||
bpi->attr = new_attr;
|
||||
bpi->uptime = bgp_clock();
|
||||
|
||||
/*
|
||||
* rewrite labels
|
||||
*/
|
||||
if (!labelssame)
|
||||
setlabels(bi, label, num_labels);
|
||||
setlabels(bpi, label, num_labels);
|
||||
|
||||
if (nexthop_self_flag)
|
||||
bgp_info_set_flag(bn, bi, BGP_INFO_ANNC_NH_SELF);
|
||||
bgp_path_info_set_flag(bn, bpi, BGP_PATH_ANNC_NH_SELF);
|
||||
|
||||
struct bgp *bgp_nexthop = bgp;
|
||||
int nh_valid;
|
||||
|
||||
if (bi->extra && bi->extra->bgp_orig)
|
||||
bgp_nexthop = bi->extra->bgp_orig;
|
||||
if (bpi->extra && bpi->extra->bgp_orig)
|
||||
bgp_nexthop = bpi->extra->bgp_orig;
|
||||
|
||||
/* No nexthop tracking for redistributed routes */
|
||||
if (bi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE)
|
||||
if (bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE)
|
||||
nh_valid = 1;
|
||||
else
|
||||
/*
|
||||
* TBD do we need to do anything about the
|
||||
* 'connected' parameter?
|
||||
*/
|
||||
nh_valid = bgp_find_or_add_nexthop(
|
||||
bgp, bgp_nexthop,
|
||||
afi, bi, NULL, 0);
|
||||
nh_valid = bgp_find_or_add_nexthop(bgp, bgp_nexthop,
|
||||
afi, bpi, NULL, 0);
|
||||
|
||||
if (debug)
|
||||
zlog_debug("%s: nexthop is %svalid (in vrf %s)",
|
||||
@ -574,10 +564,10 @@ leak_update(
|
||||
bgp_nexthop->name_pretty);
|
||||
|
||||
if (nh_valid)
|
||||
bgp_info_set_flag(bn, bi, BGP_INFO_VALID);
|
||||
bgp_path_info_set_flag(bn, bpi, BGP_PATH_VALID);
|
||||
|
||||
/* Process change. */
|
||||
bgp_aggregate_increment(bgp, p, bi, afi, safi);
|
||||
bgp_aggregate_increment(bgp, p, bpi, afi, safi);
|
||||
bgp_process(bgp, bn, afi, safi);
|
||||
bgp_unlock_node(bn);
|
||||
|
||||
@ -585,22 +575,22 @@ leak_update(
|
||||
zlog_debug("%s: ->%s: %s Found route, changed attr",
|
||||
__func__, bgp->name_pretty, buf_prefix);
|
||||
|
||||
return bi;
|
||||
return bpi;
|
||||
}
|
||||
|
||||
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0,
|
||||
bgp->peer_self, new_attr, bn);
|
||||
|
||||
if (nexthop_self_flag)
|
||||
bgp_info_set_flag(bn, new, BGP_INFO_ANNC_NH_SELF);
|
||||
bgp_path_info_set_flag(bn, new, BGP_PATH_ANNC_NH_SELF);
|
||||
|
||||
bgp_info_extra_get(new);
|
||||
bgp_path_info_extra_get(new);
|
||||
|
||||
if (num_labels)
|
||||
setlabels(new, label, num_labels);
|
||||
|
||||
new->extra->parent = bgp_info_lock(parent);
|
||||
bgp_lock_node((struct bgp_node *)((struct bgp_info *)parent)->net);
|
||||
new->extra->parent = bgp_path_info_lock(parent);
|
||||
bgp_lock_node((struct bgp_node *)((struct bgp_path_info *)parent)->net);
|
||||
if (bgp_orig)
|
||||
new->extra->bgp_orig = bgp_lock(bgp_orig);
|
||||
if (nexthop_orig)
|
||||
@ -620,7 +610,7 @@ leak_update(
|
||||
* their originating protocols will do the tracking and
|
||||
* withdraw those routes if the nexthops become unreachable
|
||||
*/
|
||||
if (bi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE)
|
||||
if (bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE)
|
||||
nh_valid = 1;
|
||||
else
|
||||
/*
|
||||
@ -635,10 +625,10 @@ leak_update(
|
||||
__func__, (nh_valid ? "" : "not "),
|
||||
bgp_nexthop->name_pretty);
|
||||
if (nh_valid)
|
||||
bgp_info_set_flag(bn, new, BGP_INFO_VALID);
|
||||
bgp_path_info_set_flag(bn, new, BGP_PATH_VALID);
|
||||
|
||||
bgp_aggregate_increment(bgp, p, new, afi, safi);
|
||||
bgp_info_add(bn, new);
|
||||
bgp_path_info_add(bn, new);
|
||||
|
||||
bgp_unlock_node(bn);
|
||||
bgp_process(bgp, bn, afi, safi);
|
||||
@ -651,12 +641,12 @@ leak_update(
|
||||
}
|
||||
|
||||
/* cf vnc_import_bgp_add_route_mode_nvegroup() and add_vnc_route() */
|
||||
void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */
|
||||
struct bgp *bgp_vrf, /* from */
|
||||
struct bgp_info *info_vrf) /* route */
|
||||
void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */
|
||||
struct bgp *bgp_vrf, /* from */
|
||||
struct bgp_path_info *path_vrf) /* route */
|
||||
{
|
||||
int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
|
||||
struct prefix *p = &info_vrf->net->p;
|
||||
struct prefix *p = &path_vrf->net->p;
|
||||
afi_t afi = family2afi(p->family);
|
||||
struct attr static_attr = {0};
|
||||
struct attr *new_attr = NULL;
|
||||
@ -670,12 +660,12 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */
|
||||
if (debug)
|
||||
zlog_debug("%s: from vrf %s", __func__, bgp_vrf->name_pretty);
|
||||
|
||||
if (debug && info_vrf->attr->ecommunity) {
|
||||
char *s = ecommunity_ecom2str(info_vrf->attr->ecommunity,
|
||||
if (debug && path_vrf->attr->ecommunity) {
|
||||
char *s = ecommunity_ecom2str(path_vrf->attr->ecommunity,
|
||||
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
|
||||
zlog_debug("%s: %s info_vrf->type=%d, EC{%s}", __func__,
|
||||
bgp_vrf->name, info_vrf->type, s);
|
||||
zlog_debug("%s: %s path_vrf->type=%d, EC{%s}", __func__,
|
||||
bgp_vrf->name, path_vrf->type, s);
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, s);
|
||||
}
|
||||
|
||||
@ -689,7 +679,7 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */
|
||||
}
|
||||
|
||||
/* loop check - should not be an imported route. */
|
||||
if (info_vrf->extra && info_vrf->extra->bgp_orig)
|
||||
if (path_vrf->extra && path_vrf->extra->bgp_orig)
|
||||
return;
|
||||
|
||||
|
||||
@ -700,13 +690,13 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */
|
||||
return;
|
||||
}
|
||||
|
||||
bgp_attr_dup(&static_attr, info_vrf->attr); /* shallow copy */
|
||||
bgp_attr_dup(&static_attr, path_vrf->attr); /* shallow copy */
|
||||
|
||||
/*
|
||||
* route map handling
|
||||
*/
|
||||
if (bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN]) {
|
||||
struct bgp_info info;
|
||||
struct bgp_path_info info;
|
||||
route_map_result_t ret;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
@ -818,8 +808,8 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */
|
||||
* IPv4 nexthops as the attr has been copied
|
||||
* otherwise.
|
||||
*/
|
||||
if (afi == AFI_IP &&
|
||||
!BGP_ATTR_NEXTHOP_AFI_IP6(info_vrf->attr)) {
|
||||
if (afi == AFI_IP
|
||||
&& !BGP_ATTR_NEXTHOP_AFI_IP6(path_vrf->attr)) {
|
||||
static_attr.mp_nexthop_global_in.s_addr =
|
||||
static_attr.nexthop.s_addr;
|
||||
static_attr.mp_nexthop_len = 4;
|
||||
@ -859,10 +849,10 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */
|
||||
bn = bgp_afi_node_get(bgp_vpn->rib[afi][safi], afi, safi, p,
|
||||
&(bgp_vrf->vpn_policy[afi].tovpn_rd));
|
||||
|
||||
struct bgp_info *new_info;
|
||||
struct bgp_path_info *new_info;
|
||||
|
||||
new_info = leak_update(bgp_vpn, bn, new_attr, afi, safi, info_vrf,
|
||||
&label, 1, info_vrf, bgp_vrf, NULL,
|
||||
new_info = leak_update(bgp_vpn, bn, new_attr, afi, safi, path_vrf,
|
||||
&label, 1, path_vrf, bgp_vrf, NULL,
|
||||
nexthop_self_flag, debug);
|
||||
|
||||
/*
|
||||
@ -878,15 +868,15 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */
|
||||
vpn_leak_to_vrf_update(bgp_vrf, new_info);
|
||||
}
|
||||
|
||||
void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, /* to */
|
||||
struct bgp *bgp_vrf, /* from */
|
||||
struct bgp_info *info_vrf) /* route */
|
||||
void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, /* to */
|
||||
struct bgp *bgp_vrf, /* from */
|
||||
struct bgp_path_info *path_vrf) /* route */
|
||||
{
|
||||
int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
|
||||
struct prefix *p = &info_vrf->net->p;
|
||||
struct prefix *p = &path_vrf->net->p;
|
||||
afi_t afi = family2afi(p->family);
|
||||
safi_t safi = SAFI_MPLS_VPN;
|
||||
struct bgp_info *bi;
|
||||
struct bgp_path_info *bpi;
|
||||
struct bgp_node *bn;
|
||||
const char *debugmsg;
|
||||
char buf_prefix[PREFIX_STRLEN];
|
||||
@ -896,16 +886,16 @@ void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, /* to */
|
||||
zlog_debug(
|
||||
"%s: entry: leak-from=%s, p=%s, type=%d, sub_type=%d",
|
||||
__func__, bgp_vrf->name_pretty, buf_prefix,
|
||||
info_vrf->type, info_vrf->sub_type);
|
||||
path_vrf->type, path_vrf->sub_type);
|
||||
}
|
||||
|
||||
if (info_vrf->sub_type != BGP_ROUTE_NORMAL
|
||||
&& info_vrf->sub_type != BGP_ROUTE_STATIC
|
||||
&& info_vrf->sub_type != BGP_ROUTE_REDISTRIBUTE) {
|
||||
if (path_vrf->sub_type != BGP_ROUTE_NORMAL
|
||||
&& path_vrf->sub_type != BGP_ROUTE_STATIC
|
||||
&& path_vrf->sub_type != BGP_ROUTE_REDISTRIBUTE) {
|
||||
|
||||
if (debug)
|
||||
zlog_debug("%s: wrong sub_type %d", __func__,
|
||||
info_vrf->sub_type);
|
||||
path_vrf->sub_type);
|
||||
return;
|
||||
}
|
||||
if (!bgp_vpn)
|
||||
@ -924,27 +914,27 @@ void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, /* to */
|
||||
}
|
||||
|
||||
if (debug)
|
||||
zlog_debug("%s: withdrawing (info_vrf=%p)", __func__, info_vrf);
|
||||
zlog_debug("%s: withdrawing (path_vrf=%p)", __func__, path_vrf);
|
||||
|
||||
bn = bgp_afi_node_get(bgp_vpn->rib[afi][safi], afi, safi, p,
|
||||
&(bgp_vrf->vpn_policy[afi].tovpn_rd));
|
||||
|
||||
/*
|
||||
* vrf -> vpn
|
||||
* match original bi imported from
|
||||
* match original bpi imported from
|
||||
*/
|
||||
for (bi = (bn ? bn->info : NULL); bi; bi = bi->next) {
|
||||
if (bi->extra && bi->extra->parent == info_vrf) {
|
||||
for (bpi = (bn ? bn->info : NULL); bpi; bpi = bpi->next) {
|
||||
if (bpi->extra && bpi->extra->parent == path_vrf) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bi) {
|
||||
if (bpi) {
|
||||
/* withdraw from looped vrfs as well */
|
||||
vpn_leak_to_vrf_withdraw(bgp_vpn, bi);
|
||||
vpn_leak_to_vrf_withdraw(bgp_vpn, bpi);
|
||||
|
||||
bgp_aggregate_decrement(bgp_vpn, p, bi, afi, safi);
|
||||
bgp_info_delete(bn, bi);
|
||||
bgp_aggregate_decrement(bgp_vpn, p, bpi, afi, safi);
|
||||
bgp_path_info_delete(bn, bpi);
|
||||
bgp_process(bgp_vpn, bn, afi, safi);
|
||||
}
|
||||
bgp_unlock_node(bn);
|
||||
@ -959,14 +949,14 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, /* to */
|
||||
safi_t safi = SAFI_MPLS_VPN;
|
||||
|
||||
/*
|
||||
* Walk vpn table, delete bi with bgp_orig == bgp_vrf
|
||||
* Walk vpn table, delete bpi with bgp_orig == bgp_vrf
|
||||
*/
|
||||
for (prn = bgp_table_top(bgp_vpn->rib[afi][safi]); prn;
|
||||
prn = bgp_route_next(prn)) {
|
||||
|
||||
struct bgp_table *table;
|
||||
struct bgp_node *bn;
|
||||
struct bgp_info *bi;
|
||||
struct bgp_path_info *bpi;
|
||||
|
||||
/* This is the per-RD table of prefixes */
|
||||
table = prn->info;
|
||||
@ -984,24 +974,24 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, /* to */
|
||||
prefix2str(&bn->p, buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
for (bi = bn->info; bi; bi = bi->next) {
|
||||
for (bpi = bn->info; bpi; bpi = bpi->next) {
|
||||
if (debug)
|
||||
zlog_debug("%s: type %d, sub_type %d",
|
||||
__func__, bi->type,
|
||||
bi->sub_type);
|
||||
if (bi->sub_type != BGP_ROUTE_IMPORTED)
|
||||
__func__, bpi->type,
|
||||
bpi->sub_type);
|
||||
if (bpi->sub_type != BGP_ROUTE_IMPORTED)
|
||||
continue;
|
||||
if (!bi->extra)
|
||||
if (!bpi->extra)
|
||||
continue;
|
||||
if ((struct bgp *)bi->extra->bgp_orig
|
||||
if ((struct bgp *)bpi->extra->bgp_orig
|
||||
== bgp_vrf) {
|
||||
/* delete route */
|
||||
if (debug)
|
||||
zlog_debug("%s: deleting it\n",
|
||||
__func__);
|
||||
bgp_aggregate_decrement(bgp_vpn, &bn->p,
|
||||
bi, afi, safi);
|
||||
bgp_info_delete(bn, bi);
|
||||
bpi, afi, safi);
|
||||
bgp_path_info_delete(bn, bpi);
|
||||
bgp_process(bgp_vpn, bn, afi, safi);
|
||||
}
|
||||
}
|
||||
@ -1014,7 +1004,7 @@ void vpn_leak_from_vrf_update_all(struct bgp *bgp_vpn, /* to */
|
||||
afi_t afi)
|
||||
{
|
||||
struct bgp_node *bn;
|
||||
struct bgp_info *bi;
|
||||
struct bgp_path_info *bpi;
|
||||
int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
|
||||
|
||||
if (debug)
|
||||
@ -1027,21 +1017,22 @@ void vpn_leak_from_vrf_update_all(struct bgp *bgp_vpn, /* to */
|
||||
if (debug)
|
||||
zlog_debug("%s: node=%p", __func__, bn);
|
||||
|
||||
for (bi = bn->info; bi; bi = bi->next) {
|
||||
for (bpi = bn->info; bpi; bpi = bpi->next) {
|
||||
if (debug)
|
||||
zlog_debug(
|
||||
"%s: calling vpn_leak_from_vrf_update",
|
||||
__func__);
|
||||
vpn_leak_from_vrf_update(bgp_vpn, bgp_vrf, bi);
|
||||
vpn_leak_from_vrf_update(bgp_vpn, bgp_vrf, bpi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
|
||||
struct bgp *bgp_vpn, /* from */
|
||||
struct bgp_info *info_vpn) /* route */
|
||||
static void
|
||||
vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
|
||||
struct bgp *bgp_vpn, /* from */
|
||||
struct bgp_path_info *path_vpn) /* route */
|
||||
{
|
||||
struct prefix *p = &info_vpn->net->p;
|
||||
struct prefix *p = &path_vpn->net->p;
|
||||
afi_t afi = family2afi(p->family);
|
||||
|
||||
struct attr static_attr = {0};
|
||||
@ -1053,7 +1044,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
|
||||
mpls_label_t *pLabels = NULL;
|
||||
uint32_t num_labels = 0;
|
||||
int nexthop_self_flag = 1;
|
||||
struct bgp_info *bi_ultimate = NULL;
|
||||
struct bgp_path_info *bpi_ultimate = NULL;
|
||||
int origin_local = 0;
|
||||
struct bgp *src_vrf;
|
||||
|
||||
@ -1068,7 +1059,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
|
||||
/* Check for intersection of route targets */
|
||||
if (!ecom_intersect(
|
||||
bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
|
||||
info_vpn->attr->ecommunity)) {
|
||||
path_vpn->attr->ecommunity)) {
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1077,7 +1068,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
|
||||
zlog_debug("%s: updating to vrf %s", __func__,
|
||||
bgp_vrf->name_pretty);
|
||||
|
||||
bgp_attr_dup(&static_attr, info_vpn->attr); /* shallow copy */
|
||||
bgp_attr_dup(&static_attr, path_vpn->attr); /* shallow copy */
|
||||
|
||||
/*
|
||||
* Nexthop: stash and clear
|
||||
@ -1086,15 +1077,17 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
|
||||
* Stash it for later label resolution by vrf ingress path and then
|
||||
* overwrite with 0, i.e., "me", for the sake of vrf advertisement.
|
||||
*/
|
||||
uint8_t nhfamily = NEXTHOP_FAMILY(info_vpn->attr->mp_nexthop_len);
|
||||
uint8_t nhfamily = NEXTHOP_FAMILY(path_vpn->attr->mp_nexthop_len);
|
||||
|
||||
if (nhfamily != AF_UNSPEC)
|
||||
static_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
|
||||
memset(&nexthop_orig, 0, sizeof(nexthop_orig));
|
||||
nexthop_orig.family = nhfamily;
|
||||
|
||||
switch (nhfamily) {
|
||||
case AF_INET:
|
||||
/* save */
|
||||
nexthop_orig.u.prefix4 = info_vpn->attr->mp_nexthop_global_in;
|
||||
nexthop_orig.u.prefix4 = path_vpn->attr->mp_nexthop_global_in;
|
||||
nexthop_orig.prefixlen = 32;
|
||||
|
||||
if (CHECK_FLAG(bgp_vrf->af_flags[afi][safi],
|
||||
@ -1103,15 +1096,14 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
|
||||
nexthop_orig.u.prefix4.s_addr;
|
||||
|
||||
static_attr.mp_nexthop_global_in =
|
||||
info_vpn->attr->mp_nexthop_global_in;
|
||||
path_vpn->attr->mp_nexthop_global_in;
|
||||
static_attr.mp_nexthop_len =
|
||||
info_vpn->attr->mp_nexthop_len;
|
||||
path_vpn->attr->mp_nexthop_len;
|
||||
}
|
||||
static_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
|
||||
break;
|
||||
case AF_INET6:
|
||||
/* save */
|
||||
nexthop_orig.u.prefix6 = info_vpn->attr->mp_nexthop_global;
|
||||
nexthop_orig.u.prefix6 = path_vpn->attr->mp_nexthop_global;
|
||||
nexthop_orig.prefixlen = 128;
|
||||
|
||||
if (CHECK_FLAG(bgp_vrf->af_flags[afi][safi],
|
||||
@ -1125,7 +1117,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
|
||||
* route map handling
|
||||
*/
|
||||
if (bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_FROMVPN]) {
|
||||
struct bgp_info info;
|
||||
struct bgp_path_info info;
|
||||
route_map_result_t ret;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
@ -1173,30 +1165,30 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
|
||||
if (!CHECK_FLAG(bgp_vrf->af_flags[afi][safi],
|
||||
BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
|
||||
/* work back to original route */
|
||||
for (bi_ultimate = info_vpn;
|
||||
bi_ultimate->extra && bi_ultimate->extra->parent;
|
||||
bi_ultimate = bi_ultimate->extra->parent)
|
||||
for (bpi_ultimate = path_vpn;
|
||||
bpi_ultimate->extra && bpi_ultimate->extra->parent;
|
||||
bpi_ultimate = bpi_ultimate->extra->parent)
|
||||
;
|
||||
|
||||
/*
|
||||
* if original route was unicast,
|
||||
* then it did not arrive over vpn
|
||||
*/
|
||||
if (bi_ultimate->net) {
|
||||
if (bpi_ultimate->net) {
|
||||
struct bgp_table *table;
|
||||
|
||||
table = bgp_node_table(bi_ultimate->net);
|
||||
table = bgp_node_table(bpi_ultimate->net);
|
||||
if (table && (table->safi == SAFI_UNICAST))
|
||||
origin_local = 1;
|
||||
}
|
||||
|
||||
/* copy labels */
|
||||
if (!origin_local &&
|
||||
info_vpn->extra && info_vpn->extra->num_labels) {
|
||||
num_labels = info_vpn->extra->num_labels;
|
||||
if (!origin_local && path_vpn->extra
|
||||
&& path_vpn->extra->num_labels) {
|
||||
num_labels = path_vpn->extra->num_labels;
|
||||
if (num_labels > BGP_MAX_LABELS)
|
||||
num_labels = BGP_MAX_LABELS;
|
||||
pLabels = info_vpn->extra->label;
|
||||
pLabels = path_vpn->extra->label;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1211,19 +1203,18 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
|
||||
* For VRF-2-VRF route-leaking,
|
||||
* the source will be the originating VRF.
|
||||
*/
|
||||
if (info_vpn->extra && info_vpn->extra->bgp_orig)
|
||||
src_vrf = info_vpn->extra->bgp_orig;
|
||||
if (path_vpn->extra && path_vpn->extra->bgp_orig)
|
||||
src_vrf = path_vpn->extra->bgp_orig;
|
||||
else
|
||||
src_vrf = bgp_vpn;
|
||||
|
||||
leak_update(bgp_vrf, bn, new_attr, afi, safi, info_vpn,
|
||||
pLabels, num_labels,
|
||||
info_vpn, /* parent */
|
||||
src_vrf, &nexthop_orig, nexthop_self_flag, debug);
|
||||
leak_update(bgp_vrf, bn, new_attr, afi, safi, path_vpn, pLabels,
|
||||
num_labels, path_vpn, /* parent */
|
||||
src_vrf, &nexthop_orig, nexthop_self_flag, debug);
|
||||
}
|
||||
|
||||
void vpn_leak_to_vrf_update(struct bgp *bgp_vpn, /* from */
|
||||
struct bgp_info *info_vpn) /* route */
|
||||
void vpn_leak_to_vrf_update(struct bgp *bgp_vpn, /* from */
|
||||
struct bgp_path_info *path_vpn) /* route */
|
||||
{
|
||||
struct listnode *mnode, *mnnode;
|
||||
struct bgp *bgp;
|
||||
@ -1231,20 +1222,20 @@ void vpn_leak_to_vrf_update(struct bgp *bgp_vpn, /* from */
|
||||
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
|
||||
|
||||
if (debug)
|
||||
zlog_debug("%s: start (info_vpn=%p)", __func__, info_vpn);
|
||||
zlog_debug("%s: start (path_vpn=%p)", __func__, path_vpn);
|
||||
|
||||
/* Loop over VRFs */
|
||||
for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
|
||||
|
||||
if (!info_vpn->extra
|
||||
|| info_vpn->extra->bgp_orig != bgp) { /* no loop */
|
||||
vpn_leak_to_vrf_update_onevrf(bgp, bgp_vpn, info_vpn);
|
||||
if (!path_vpn->extra
|
||||
|| path_vpn->extra->bgp_orig != bgp) { /* no loop */
|
||||
vpn_leak_to_vrf_update_onevrf(bgp, bgp_vpn, path_vpn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, /* from */
|
||||
struct bgp_info *info_vpn) /* route */
|
||||
void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, /* from */
|
||||
struct bgp_path_info *path_vpn) /* route */
|
||||
{
|
||||
struct prefix *p;
|
||||
afi_t afi;
|
||||
@ -1252,38 +1243,38 @@ void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, /* from */
|
||||
struct bgp *bgp;
|
||||
struct listnode *mnode, *mnnode;
|
||||
struct bgp_node *bn;
|
||||
struct bgp_info *bi;
|
||||
struct bgp_path_info *bpi;
|
||||
const char *debugmsg;
|
||||
char buf_prefix[PREFIX_STRLEN];
|
||||
|
||||
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
|
||||
|
||||
if (debug) {
|
||||
prefix2str(&info_vpn->net->p, buf_prefix, sizeof(buf_prefix));
|
||||
zlog_debug("%s: entry: p=%s, type=%d, sub_type=%d",
|
||||
__func__, buf_prefix,
|
||||
info_vpn->type, info_vpn->sub_type);
|
||||
prefix2str(&path_vpn->net->p, buf_prefix, sizeof(buf_prefix));
|
||||
zlog_debug("%s: entry: p=%s, type=%d, sub_type=%d", __func__,
|
||||
buf_prefix, path_vpn->type, path_vpn->sub_type);
|
||||
}
|
||||
|
||||
if (debug)
|
||||
zlog_debug("%s: start (info_vpn=%p)", __func__, info_vpn);
|
||||
zlog_debug("%s: start (path_vpn=%p)", __func__, path_vpn);
|
||||
|
||||
if (!info_vpn->net) {
|
||||
if (!path_vpn->net) {
|
||||
#if ENABLE_BGP_VNC
|
||||
/* BGP_ROUTE_RFP routes do not have info_vpn->net set (yet) */
|
||||
if (info_vpn->type == ZEBRA_ROUTE_BGP &&
|
||||
info_vpn->sub_type == BGP_ROUTE_RFP) {
|
||||
/* BGP_ROUTE_RFP routes do not have path_vpn->net set (yet) */
|
||||
if (path_vpn->type == ZEBRA_ROUTE_BGP
|
||||
&& path_vpn->sub_type == BGP_ROUTE_RFP) {
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (debug)
|
||||
zlog_debug("%s: info_vpn->net unexpectedly NULL, no prefix, bailing",
|
||||
zlog_debug(
|
||||
"%s: path_vpn->net unexpectedly NULL, no prefix, bailing",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
p = &info_vpn->net->p;
|
||||
p = &path_vpn->net->p;
|
||||
afi = family2afi(p->family);
|
||||
|
||||
/* Loop over VRFs */
|
||||
@ -1298,7 +1289,7 @@ void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, /* from */
|
||||
/* Check for intersection of route targets */
|
||||
if (!ecom_intersect(bgp->vpn_policy[afi]
|
||||
.rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
|
||||
info_vpn->attr->ecommunity)) {
|
||||
path_vpn->attr->ecommunity)) {
|
||||
|
||||
continue;
|
||||
}
|
||||
@ -1308,19 +1299,20 @@ void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, /* from */
|
||||
bgp->name_pretty);
|
||||
|
||||
bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
|
||||
for (bi = (bn ? bn->info : NULL); bi; bi = bi->next) {
|
||||
if (bi->extra
|
||||
&& (struct bgp_info *)bi->extra->parent
|
||||
== info_vpn) {
|
||||
for (bpi = (bn ? bn->info : NULL); bpi; bpi = bpi->next) {
|
||||
if (bpi->extra
|
||||
&& (struct bgp_path_info *)bpi->extra->parent
|
||||
== path_vpn) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bi) {
|
||||
if (bpi) {
|
||||
if (debug)
|
||||
zlog_debug("%s: deleting bi %p", __func__, bi);
|
||||
bgp_aggregate_decrement(bgp, p, bi, afi, safi);
|
||||
bgp_info_delete(bn, bi);
|
||||
zlog_debug("%s: deleting bpi %p", __func__,
|
||||
bpi);
|
||||
bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
|
||||
bgp_path_info_delete(bn, bpi);
|
||||
bgp_process(bgp, bn, afi, safi);
|
||||
}
|
||||
bgp_unlock_node(bn);
|
||||
@ -1331,25 +1323,25 @@ void vpn_leak_to_vrf_withdraw_all(struct bgp *bgp_vrf, /* to */
|
||||
afi_t afi)
|
||||
{
|
||||
struct bgp_node *bn;
|
||||
struct bgp_info *bi;
|
||||
struct bgp_path_info *bpi;
|
||||
safi_t safi = SAFI_UNICAST;
|
||||
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
|
||||
|
||||
if (debug)
|
||||
zlog_debug("%s: entry", __func__);
|
||||
/*
|
||||
* Walk vrf table, delete bi with bgp_orig in a different vrf
|
||||
* Walk vrf table, delete bpi with bgp_orig in a different vrf
|
||||
*/
|
||||
for (bn = bgp_table_top(bgp_vrf->rib[afi][safi]); bn;
|
||||
bn = bgp_route_next(bn)) {
|
||||
|
||||
for (bi = bn->info; bi; bi = bi->next) {
|
||||
if (bi->extra && bi->extra->bgp_orig != bgp_vrf) {
|
||||
for (bpi = bn->info; bpi; bpi = bpi->next) {
|
||||
if (bpi->extra && bpi->extra->bgp_orig != bgp_vrf) {
|
||||
|
||||
/* delete route */
|
||||
bgp_aggregate_decrement(bgp_vrf, &bn->p, bi,
|
||||
bgp_aggregate_decrement(bgp_vrf, &bn->p, bpi,
|
||||
afi, safi);
|
||||
bgp_info_delete(bn, bi);
|
||||
bgp_path_info_delete(bn, bpi);
|
||||
bgp_process(bgp_vrf, bn, afi, safi);
|
||||
}
|
||||
}
|
||||
@ -1374,7 +1366,7 @@ void vpn_leak_to_vrf_update_all(struct bgp *bgp_vrf, /* to */
|
||||
|
||||
struct bgp_table *table;
|
||||
struct bgp_node *bn;
|
||||
struct bgp_info *bi;
|
||||
struct bgp_path_info *bpi;
|
||||
|
||||
memset(&prd, 0, sizeof(prd));
|
||||
prd.family = AF_UNSPEC;
|
||||
@ -1389,13 +1381,14 @@ void vpn_leak_to_vrf_update_all(struct bgp *bgp_vrf, /* to */
|
||||
|
||||
for (bn = bgp_table_top(table); bn; bn = bgp_route_next(bn)) {
|
||||
|
||||
for (bi = bn->info; bi; bi = bi->next) {
|
||||
for (bpi = bn->info; bpi; bpi = bpi->next) {
|
||||
|
||||
if (bi->extra && bi->extra->bgp_orig == bgp_vrf)
|
||||
if (bpi->extra
|
||||
&& bpi->extra->bgp_orig == bgp_vrf)
|
||||
continue;
|
||||
|
||||
vpn_leak_to_vrf_update_onevrf(bgp_vrf, bgp_vpn,
|
||||
bi);
|
||||
bpi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,10 +53,10 @@ extern int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd,
|
||||
int tags, bool use_json);
|
||||
|
||||
extern void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
|
||||
struct bgp_info *info_vrf);
|
||||
struct bgp_path_info *path_vrf);
|
||||
|
||||
extern void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
|
||||
struct bgp_info *info_vrf);
|
||||
struct bgp_path_info *path_vrf);
|
||||
|
||||
extern void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn,
|
||||
struct bgp *bgp_vrf, afi_t afi);
|
||||
@ -70,10 +70,10 @@ extern void vpn_leak_to_vrf_update_all(struct bgp *bgp_vrf, struct bgp *bgp_vpn,
|
||||
afi_t afi);
|
||||
|
||||
extern void vpn_leak_to_vrf_update(struct bgp *bgp_vpn,
|
||||
struct bgp_info *info_vpn);
|
||||
struct bgp_path_info *path_vpn);
|
||||
|
||||
extern void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn,
|
||||
struct bgp_info *info_vpn);
|
||||
struct bgp_path_info *path_vpn);
|
||||
|
||||
extern void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi);
|
||||
extern void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi);
|
||||
|
@ -406,7 +406,6 @@ static int bgp_accept(struct thread *thread)
|
||||
|
||||
peer = peer_create(&su, peer1->conf_if, peer1->bgp, peer1->local_as,
|
||||
peer1->as, peer1->as_type, 0, 0, NULL);
|
||||
peer->su = su;
|
||||
hash_release(peer->bgp->peerhash, peer);
|
||||
hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
|
||||
|
||||
|
@ -47,6 +47,8 @@
|
||||
#include "zebra/rib.h"
|
||||
#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
|
||||
|
||||
DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Address Intf String");
|
||||
|
||||
char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size)
|
||||
{
|
||||
prefix2str(&(bnc->node->p), buf, size);
|
||||
@ -82,11 +84,18 @@ static void bgp_nexthop_cache_reset(struct bgp_table *table)
|
||||
|
||||
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
|
||||
bnc = bgp_nexthop_get_node_info(rn);
|
||||
if (bnc != NULL) {
|
||||
bnc_free(bnc);
|
||||
bgp_nexthop_set_node_info(rn, NULL);
|
||||
bgp_unlock_node(rn);
|
||||
if (!bnc)
|
||||
continue;
|
||||
|
||||
while (!LIST_EMPTY(&(bnc->paths))) {
|
||||
struct bgp_path_info *path = LIST_FIRST(&(bnc->paths));
|
||||
|
||||
path_nh_map(path, bnc, false);
|
||||
}
|
||||
|
||||
bnc_free(bnc);
|
||||
bgp_nexthop_set_node_info(rn, NULL);
|
||||
bgp_unlock_node(rn);
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,7 +123,7 @@ static unsigned int bgp_tip_hash_key_make(void *p)
|
||||
return jhash_1word(addr->addr.s_addr, 0);
|
||||
}
|
||||
|
||||
static int bgp_tip_hash_cmp(const void *p1, const void *p2)
|
||||
static bool bgp_tip_hash_cmp(const void *p1, const void *p2)
|
||||
{
|
||||
const struct tip_addr *addr1 = p1;
|
||||
const struct tip_addr *addr2 = p2;
|
||||
@ -205,7 +214,7 @@ static void bgp_address_hash_string_del(void *val)
|
||||
{
|
||||
char *data = val;
|
||||
|
||||
XFREE(MTYPE_TMP, data);
|
||||
XFREE(MTYPE_MARTIAN_STRING, data);
|
||||
}
|
||||
|
||||
static void *bgp_address_hash_alloc(void *p)
|
||||
@ -237,7 +246,7 @@ static unsigned int bgp_address_hash_key_make(void *p)
|
||||
return jhash_1word(addr->addr.s_addr, 0);
|
||||
}
|
||||
|
||||
static int bgp_address_hash_cmp(const void *p1, const void *p2)
|
||||
static bool bgp_address_hash_cmp(const void *p1, const void *p2)
|
||||
{
|
||||
const struct bgp_addr *addr1 = p1;
|
||||
const struct bgp_addr *addr2 = p2;
|
||||
@ -278,7 +287,7 @@ static void bgp_address_add(struct bgp *bgp, struct connected *ifc,
|
||||
break;
|
||||
}
|
||||
if (!node) {
|
||||
name = XSTRDUP(MTYPE_TMP, ifc->ifp->name);
|
||||
name = XSTRDUP(MTYPE_MARTIAN_STRING, ifc->ifp->name);
|
||||
listnode_add(addr->ifp_name_list, name);
|
||||
}
|
||||
}
|
||||
@ -303,8 +312,10 @@ static void bgp_address_del(struct bgp *bgp, struct connected *ifc,
|
||||
break;
|
||||
}
|
||||
|
||||
if (node)
|
||||
if (node) {
|
||||
list_delete_node(addr->ifp_name_list, node);
|
||||
XFREE(MTYPE_MARTIAN_STRING, name);
|
||||
}
|
||||
|
||||
if (addr->ifp_name_list->count == 0) {
|
||||
hash_release(bgp->address_hash, addr);
|
||||
|
@ -63,7 +63,7 @@ struct bgp_nexthop_cache {
|
||||
|
||||
struct bgp_node *node;
|
||||
void *nht_info; /* In BGP, peer session */
|
||||
LIST_HEAD(path_list, bgp_info) paths;
|
||||
LIST_HEAD(path_list, bgp_path_info) paths;
|
||||
unsigned int path_count;
|
||||
struct bgp *bgp;
|
||||
};
|
||||
@ -74,8 +74,6 @@ struct tip_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);
|
||||
extern void bgp_connected_delete(struct bgp *bgp, struct connected *c);
|
||||
extern int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
|
||||
|
@ -50,9 +50,7 @@ static void register_zebra_rnh(struct bgp_nexthop_cache *bnc,
|
||||
static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc,
|
||||
int is_bgp_static_route);
|
||||
static void evaluate_paths(struct bgp_nexthop_cache *bnc);
|
||||
static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p);
|
||||
static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc,
|
||||
int keep);
|
||||
static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p);
|
||||
|
||||
static int bgp_isvalid_nexthop(struct bgp_nexthop_cache *bnc)
|
||||
{
|
||||
@ -66,7 +64,7 @@ static int bgp_isvalid_labeled_nexthop(struct bgp_nexthop_cache *bnc)
|
||||
|| (bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID)));
|
||||
}
|
||||
|
||||
int bgp_find_nexthop(struct bgp_info *path, int connected)
|
||||
int bgp_find_nexthop(struct bgp_path_info *path, int connected)
|
||||
{
|
||||
struct bgp_nexthop_cache *bnc = path->nexthop;
|
||||
|
||||
@ -104,14 +102,14 @@ static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc)
|
||||
}
|
||||
}
|
||||
|
||||
void bgp_unlink_nexthop(struct bgp_info *path)
|
||||
void bgp_unlink_nexthop(struct bgp_path_info *path)
|
||||
{
|
||||
struct bgp_nexthop_cache *bnc = path->nexthop;
|
||||
|
||||
if (!bnc)
|
||||
return;
|
||||
|
||||
path_nh_map(path, NULL, 0);
|
||||
path_nh_map(path, NULL, false);
|
||||
|
||||
bgp_unlink_nexthop_check(bnc);
|
||||
}
|
||||
@ -143,7 +141,7 @@ void bgp_unlink_nexthop_by_peer(struct peer *peer)
|
||||
* we need both the bgp_route and bgp_nexthop pointers.
|
||||
*/
|
||||
int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
|
||||
afi_t afi, struct bgp_info *ri,
|
||||
afi_t afi, struct bgp_path_info *pi,
|
||||
struct peer *peer, int connected)
|
||||
{
|
||||
struct bgp_node *rn;
|
||||
@ -151,9 +149,9 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
|
||||
struct prefix p;
|
||||
int is_bgp_static_route = 0;
|
||||
|
||||
if (ri) {
|
||||
is_bgp_static_route = ((ri->type == ZEBRA_ROUTE_BGP)
|
||||
&& (ri->sub_type == BGP_ROUTE_STATIC))
|
||||
if (pi) {
|
||||
is_bgp_static_route = ((pi->type == ZEBRA_ROUTE_BGP)
|
||||
&& (pi->sub_type == BGP_ROUTE_STATIC))
|
||||
? 1
|
||||
: 0;
|
||||
|
||||
@ -161,19 +159,14 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
|
||||
to derive
|
||||
address-family from the next-hop. */
|
||||
if (!is_bgp_static_route)
|
||||
afi = BGP_ATTR_NEXTHOP_AFI_IP6(ri->attr) ? AFI_IP6
|
||||
afi = BGP_ATTR_NEXTHOP_AFI_IP6(pi->attr) ? AFI_IP6
|
||||
: AFI_IP;
|
||||
|
||||
/* This will return TRUE if the global IPv6 NH is a link local
|
||||
* addr */
|
||||
if (make_prefix(afi, ri, &p) < 0)
|
||||
if (make_prefix(afi, pi, &p) < 0)
|
||||
return 1;
|
||||
} else if (peer) {
|
||||
/* Don't register link local NH */
|
||||
if (afi == AFI_IP6
|
||||
&& IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr))
|
||||
return 1;
|
||||
|
||||
if (!sockunion2hostprefix(&peer->su, &p)) {
|
||||
if (BGP_DEBUG(nht, NHT)) {
|
||||
zlog_debug(
|
||||
@ -251,19 +244,20 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
|
||||
bnc->flags |= BGP_NEXTHOP_VALID;
|
||||
} else if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
|
||||
register_zebra_rnh(bnc, is_bgp_static_route);
|
||||
if (ri && ri->nexthop != bnc) {
|
||||
if (pi && pi->nexthop != bnc) {
|
||||
/* Unlink from existing nexthop cache, if any. This will also
|
||||
* free
|
||||
* the nexthop cache entry, if appropriate.
|
||||
*/
|
||||
bgp_unlink_nexthop(ri);
|
||||
bgp_unlink_nexthop(pi);
|
||||
|
||||
path_nh_map(ri, bnc, 1); /* updates NHT ri list reference */
|
||||
/* updates NHT pi list reference */
|
||||
path_nh_map(pi, bnc, true);
|
||||
|
||||
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
|
||||
(bgp_info_extra_get(ri))->igpmetric = bnc->metric;
|
||||
else if (ri->extra)
|
||||
ri->extra->igpmetric = 0;
|
||||
(bgp_path_info_extra_get(pi))->igpmetric = bnc->metric;
|
||||
else if (pi->extra)
|
||||
pi->extra->igpmetric = 0;
|
||||
} else if (peer)
|
||||
bnc->nht_info = (void *)peer; /* NHT peer reference */
|
||||
|
||||
@ -287,10 +281,6 @@ void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer)
|
||||
if (!peer)
|
||||
return;
|
||||
|
||||
/* We don't register link local address for NHT */
|
||||
if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr))
|
||||
return;
|
||||
|
||||
if (!sockunion2hostprefix(&peer->su, &p))
|
||||
return;
|
||||
|
||||
@ -437,8 +427,9 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
|
||||
* we receive from bgp. This is to allow us
|
||||
* to work with v4 routing over v6 nexthops
|
||||
*/
|
||||
if (peer &&
|
||||
CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)
|
||||
if (peer && !peer->ifp
|
||||
&& CHECK_FLAG(peer->flags,
|
||||
PEER_FLAG_CAPABILITY_ENHE)
|
||||
&& nhr.prefix.family == AF_INET6) {
|
||||
struct interface *ifp;
|
||||
|
||||
@ -535,11 +526,11 @@ void bgp_cleanup_nexthops(struct bgp *bgp)
|
||||
* make_prefix - make a prefix structure from the path (essentially
|
||||
* path's node.
|
||||
*/
|
||||
static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p)
|
||||
static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
|
||||
{
|
||||
|
||||
int is_bgp_static = ((ri->type == ZEBRA_ROUTE_BGP)
|
||||
&& (ri->sub_type == BGP_ROUTE_STATIC))
|
||||
int is_bgp_static = ((pi->type == ZEBRA_ROUTE_BGP)
|
||||
&& (pi->sub_type == BGP_ROUTE_STATIC))
|
||||
? 1
|
||||
: 0;
|
||||
|
||||
@ -548,26 +539,21 @@ static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p)
|
||||
case AFI_IP:
|
||||
p->family = AF_INET;
|
||||
if (is_bgp_static) {
|
||||
p->u.prefix4 = ri->net->p.u.prefix4;
|
||||
p->prefixlen = ri->net->p.prefixlen;
|
||||
p->u.prefix4 = pi->net->p.u.prefix4;
|
||||
p->prefixlen = pi->net->p.prefixlen;
|
||||
} else {
|
||||
p->u.prefix4 = ri->attr->nexthop;
|
||||
p->u.prefix4 = pi->attr->nexthop;
|
||||
p->prefixlen = IPV4_MAX_BITLEN;
|
||||
}
|
||||
break;
|
||||
case AFI_IP6:
|
||||
/* We don't register link local NH */
|
||||
if (ri->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL
|
||||
|| IN6_IS_ADDR_LINKLOCAL(&ri->attr->mp_nexthop_global))
|
||||
return -1;
|
||||
|
||||
p->family = AF_INET6;
|
||||
|
||||
if (is_bgp_static) {
|
||||
p->u.prefix6 = ri->net->p.u.prefix6;
|
||||
p->prefixlen = ri->net->p.prefixlen;
|
||||
p->u.prefix6 = pi->net->p.u.prefix6;
|
||||
p->prefixlen = pi->net->p.prefixlen;
|
||||
} else {
|
||||
p->u.prefix6 = ri->attr->mp_nexthop_global;
|
||||
p->u.prefix6 = pi->attr->mp_nexthop_global;
|
||||
p->prefixlen = IPV6_MAX_BITLEN;
|
||||
}
|
||||
break;
|
||||
@ -686,7 +672,7 @@ static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc,
|
||||
static void evaluate_paths(struct bgp_nexthop_cache *bnc)
|
||||
{
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *path;
|
||||
struct bgp_path_info *path;
|
||||
int afi;
|
||||
struct peer *peer = (struct peer *)bnc->nht_info;
|
||||
struct bgp_table *table;
|
||||
@ -753,14 +739,16 @@ static void evaluate_paths(struct bgp_nexthop_cache *bnc)
|
||||
(bnc_is_valid_nexthop ? "" : "not "));
|
||||
}
|
||||
|
||||
if ((CHECK_FLAG(path->flags, BGP_INFO_VALID) ? 1 : 0)
|
||||
if ((CHECK_FLAG(path->flags, BGP_PATH_VALID) ? 1 : 0)
|
||||
!= bnc_is_valid_nexthop) {
|
||||
if (CHECK_FLAG(path->flags, BGP_INFO_VALID)) {
|
||||
if (CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
|
||||
bgp_aggregate_decrement(bgp_path, &rn->p,
|
||||
path, afi, safi);
|
||||
bgp_info_unset_flag(rn, path, BGP_INFO_VALID);
|
||||
bgp_path_info_unset_flag(rn, path,
|
||||
BGP_PATH_VALID);
|
||||
} else {
|
||||
bgp_info_set_flag(rn, path, BGP_INFO_VALID);
|
||||
bgp_path_info_set_flag(rn, path,
|
||||
BGP_PATH_VALID);
|
||||
bgp_aggregate_increment(bgp_path, &rn->p,
|
||||
path, afi, safi);
|
||||
}
|
||||
@ -769,13 +757,14 @@ static void evaluate_paths(struct bgp_nexthop_cache *bnc)
|
||||
/* Copy the metric to the path. Will be used for bestpath
|
||||
* computation */
|
||||
if (bgp_isvalid_nexthop(bnc) && bnc->metric)
|
||||
(bgp_info_extra_get(path))->igpmetric = bnc->metric;
|
||||
(bgp_path_info_extra_get(path))->igpmetric =
|
||||
bnc->metric;
|
||||
else if (path->extra)
|
||||
path->extra->igpmetric = 0;
|
||||
|
||||
if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED)
|
||||
|| CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED))
|
||||
SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED);
|
||||
SET_FLAG(path->flags, BGP_PATH_IGP_CHANGED);
|
||||
|
||||
bgp_process(bgp_path, rn, afi, safi);
|
||||
}
|
||||
@ -799,8 +788,8 @@ static void evaluate_paths(struct bgp_nexthop_cache *bnc)
|
||||
* make - if set, make the association. if unset, just break the existing
|
||||
* association.
|
||||
*/
|
||||
static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc,
|
||||
int make)
|
||||
void path_nh_map(struct bgp_path_info *path, struct bgp_nexthop_cache *bnc,
|
||||
bool make)
|
||||
{
|
||||
if (path->nexthop) {
|
||||
LIST_REMOVE(path, nh_thread);
|
||||
|
@ -32,7 +32,7 @@ extern void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id);
|
||||
* p - path for which the nexthop object is being looked up
|
||||
* connected - True if NH MUST be a connected route
|
||||
*/
|
||||
extern int bgp_find_nexthop(struct bgp_info *p, int connected);
|
||||
extern int bgp_find_nexthop(struct bgp_path_info *p, int connected);
|
||||
|
||||
/**
|
||||
* bgp_find_or_add_nexthop() - lookup the nexthop cache table for the bnc
|
||||
@ -47,16 +47,17 @@ extern int bgp_find_nexthop(struct bgp_info *p, int connected);
|
||||
* connected - True if NH MUST be a connected route
|
||||
*/
|
||||
extern int bgp_find_or_add_nexthop(struct bgp *bgp_route,
|
||||
struct bgp *bgp_nexthop, afi_t a, struct bgp_info *p,
|
||||
struct peer *peer, int connected);
|
||||
struct bgp *bgp_nexthop, afi_t a,
|
||||
struct bgp_path_info *p, struct peer *peer,
|
||||
int connected);
|
||||
|
||||
/**
|
||||
* bgp_unlink_nexthop() - Unlink the nexthop object from the path structure.
|
||||
* ARGUMENTS:
|
||||
* p - path structure.
|
||||
*/
|
||||
extern void bgp_unlink_nexthop(struct bgp_info *p);
|
||||
void bgp_unlink_nexthop_by_peer(struct peer *);
|
||||
extern void bgp_unlink_nexthop(struct bgp_path_info *p);
|
||||
void bgp_unlink_nexthop_by_peer(struct peer *peer);
|
||||
|
||||
/**
|
||||
* bgp_delete_connected_nexthop() - Reset the 'peer' pointer for a connected
|
||||
@ -74,4 +75,11 @@ extern void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer);
|
||||
*/
|
||||
extern void bgp_cleanup_nexthops(struct bgp *bgp);
|
||||
|
||||
/*
|
||||
* Add or remove the tracking of the bgp_path_info that
|
||||
* uses this nexthop
|
||||
*/
|
||||
extern void path_nh_map(struct bgp_path_info *path,
|
||||
struct bgp_nexthop_cache *bnc, bool make);
|
||||
|
||||
#endif /* _BGP_NHT_H */
|
||||
|
@ -272,7 +272,7 @@ static void bgp_update_explicit_eors(struct peer *peer)
|
||||
PEER_STATUS_EOR_RECEIVED)) {
|
||||
if (bgp_debug_neighbor_events(peer))
|
||||
zlog_debug(
|
||||
" afi %d safi %d didnt receive EOR",
|
||||
" afi %d safi %d didn't receive EOR",
|
||||
afi, safi);
|
||||
return;
|
||||
}
|
||||
|
300
bgpd/bgp_pbr.c
300
bgpd/bgp_pbr.c
@ -227,7 +227,7 @@ struct bgp_pbr_or_filter {
|
||||
};
|
||||
|
||||
static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
|
||||
struct bgp_info *binfo,
|
||||
struct bgp_path_info *path,
|
||||
struct bgp_pbr_filter *bpf,
|
||||
struct nexthop *nh,
|
||||
float *rate);
|
||||
@ -627,7 +627,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
|
||||
|
||||
/* return -1 if build or validation failed */
|
||||
static int bgp_pbr_build_and_validate_entry(struct prefix *p,
|
||||
struct bgp_info *info,
|
||||
struct bgp_path_info *path,
|
||||
struct bgp_pbr_entry_main *api)
|
||||
{
|
||||
int ret;
|
||||
@ -645,8 +645,8 @@ static int bgp_pbr_build_and_validate_entry(struct prefix *p,
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
/* extract actiosn from flowspec ecom list */
|
||||
if (info && info->attr && info->attr->ecommunity) {
|
||||
ecom = info->attr->ecommunity;
|
||||
if (path && path->attr && path->attr->ecommunity) {
|
||||
ecom = path->attr->ecommunity;
|
||||
for (i = 0; i < ecom->size; i++) {
|
||||
ecom_eval = (struct ecommunity_val *)
|
||||
(ecom->val + (i * ECOMMUNITY_SIZE));
|
||||
@ -690,7 +690,7 @@ static int bgp_pbr_build_and_validate_entry(struct prefix *p,
|
||||
(char)ECOMMUNITY_REDIRECT_IP_NH)) {
|
||||
api_action->action = ACTION_REDIRECT_IP;
|
||||
api_action->u.zr.redirect_ip_v4.s_addr =
|
||||
info->attr->nexthop.s_addr;
|
||||
path->attr->nexthop.s_addr;
|
||||
api_action->u.zr.duplicate = ecom_eval->val[7];
|
||||
} else {
|
||||
if (ecom_eval->val[0] !=
|
||||
@ -847,7 +847,7 @@ uint32_t bgp_pbr_match_hash_key(void *arg)
|
||||
return jhash_1word(pbm->type, key);
|
||||
}
|
||||
|
||||
int bgp_pbr_match_hash_equal(const void *arg1, const void *arg2)
|
||||
bool bgp_pbr_match_hash_equal(const void *arg1, const void *arg2)
|
||||
{
|
||||
const struct bgp_pbr_match *r1, *r2;
|
||||
|
||||
@ -855,35 +855,35 @@ int bgp_pbr_match_hash_equal(const void *arg1, const void *arg2)
|
||||
r2 = (const struct bgp_pbr_match *)arg2;
|
||||
|
||||
if (r1->vrf_id != r2->vrf_id)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (r1->type != r2->type)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (r1->flags != r2->flags)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (r1->action != r2->action)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (r1->pkt_len_min != r2->pkt_len_min)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (r1->pkt_len_max != r2->pkt_len_max)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (r1->tcp_flags != r2->tcp_flags)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (r1->tcp_mask_flags != r2->tcp_mask_flags)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (r1->dscp_value != r2->dscp_value)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (r1->fragment != r2->fragment)
|
||||
return 0;
|
||||
return 1;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t bgp_pbr_match_entry_hash_key(void *arg)
|
||||
@ -903,45 +903,41 @@ uint32_t bgp_pbr_match_entry_hash_key(void *arg)
|
||||
return key;
|
||||
}
|
||||
|
||||
int bgp_pbr_match_entry_hash_equal(const void *arg1, const void *arg2)
|
||||
bool bgp_pbr_match_entry_hash_equal(const void *arg1, const void *arg2)
|
||||
{
|
||||
const struct bgp_pbr_match_entry *r1, *r2;
|
||||
|
||||
r1 = (const struct bgp_pbr_match_entry *)arg1;
|
||||
r2 = (const struct bgp_pbr_match_entry *)arg2;
|
||||
|
||||
/* on updates, comparing
|
||||
* backpointer is not necessary
|
||||
*/
|
||||
|
||||
/* unique value is self calculated
|
||||
*/
|
||||
|
||||
/* rate is ignored for now
|
||||
/*
|
||||
* on updates, comparing backpointer is not necessary
|
||||
* unique value is self calculated
|
||||
* rate is ignored for now
|
||||
*/
|
||||
|
||||
if (!prefix_same(&r1->src, &r2->src))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (!prefix_same(&r1->dst, &r2->dst))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (r1->src_port_min != r2->src_port_min)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (r1->dst_port_min != r2->dst_port_min)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (r1->src_port_max != r2->src_port_max)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (r1->dst_port_max != r2->dst_port_max)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (r1->proto != r2->proto)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t bgp_pbr_action_hash_key(void *arg)
|
||||
@ -955,7 +951,7 @@ uint32_t bgp_pbr_action_hash_key(void *arg)
|
||||
return key;
|
||||
}
|
||||
|
||||
int bgp_pbr_action_hash_equal(const void *arg1, const void *arg2)
|
||||
bool bgp_pbr_action_hash_equal(const void *arg1, const void *arg2)
|
||||
{
|
||||
const struct bgp_pbr_action *r1, *r2;
|
||||
|
||||
@ -967,11 +963,12 @@ int bgp_pbr_action_hash_equal(const void *arg1, const void *arg2)
|
||||
* rate is ignored
|
||||
*/
|
||||
if (r1->vrf_id != r2->vrf_id)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (memcmp(&r1->nh, &r2->nh, sizeof(struct nexthop)))
|
||||
return 0;
|
||||
return 1;
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct bgp_pbr_action *bgp_pbr_action_rule_lookup(vrf_id_t vrf_id,
|
||||
@ -1223,16 +1220,16 @@ static void bgp_pbr_flush_entry(struct bgp *bgp, struct bgp_pbr_action *bpa,
|
||||
bgp_send_pbr_ipset_entry_match(bpme, false);
|
||||
bpme->installed = false;
|
||||
bpme->backpointer = NULL;
|
||||
if (bpme->bgp_info) {
|
||||
struct bgp_info *bgp_info;
|
||||
struct bgp_info_extra *extra;
|
||||
if (bpme->path) {
|
||||
struct bgp_path_info *path;
|
||||
struct bgp_path_info_extra *extra;
|
||||
|
||||
/* unlink bgp_info to bpme */
|
||||
bgp_info = (struct bgp_info *)bpme->bgp_info;
|
||||
extra = bgp_info_extra_get(bgp_info);
|
||||
/* unlink bgp_path_info to bpme */
|
||||
path = (struct bgp_path_info *)bpme->path;
|
||||
extra = bgp_path_info_extra_get(path);
|
||||
if (extra->bgp_fs_pbr)
|
||||
listnode_delete(extra->bgp_fs_pbr, bpme);
|
||||
bpme->bgp_info = NULL;
|
||||
bpme->path = NULL;
|
||||
}
|
||||
}
|
||||
hash_release(bpm->entry_hash, bpme);
|
||||
@ -1304,9 +1301,8 @@ static int bgp_pbr_get_remaining_entry(struct hash_backet *backet, void *arg)
|
||||
return HASHWALK_ABORT;
|
||||
}
|
||||
|
||||
static void bgp_pbr_policyroute_remove_from_zebra_unit(struct bgp *bgp,
|
||||
struct bgp_info *binfo,
|
||||
struct bgp_pbr_filter *bpf)
|
||||
static void bgp_pbr_policyroute_remove_from_zebra_unit(
|
||||
struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_filter *bpf)
|
||||
{
|
||||
struct bgp_pbr_match temp;
|
||||
struct bgp_pbr_match_entry temp2;
|
||||
@ -1438,13 +1434,10 @@ static uint8_t bgp_pbr_next_type_entry(uint8_t type_entry)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bgp_pbr_icmp_action(struct bgp *bgp,
|
||||
struct bgp_info *binfo,
|
||||
struct bgp_pbr_filter *bpf,
|
||||
struct bgp_pbr_or_filter *bpof,
|
||||
bool add,
|
||||
struct nexthop *nh,
|
||||
float *rate)
|
||||
static void bgp_pbr_icmp_action(struct bgp *bgp, struct bgp_path_info *path,
|
||||
struct bgp_pbr_filter *bpf,
|
||||
struct bgp_pbr_or_filter *bpof, bool add,
|
||||
struct nexthop *nh, float *rate)
|
||||
{
|
||||
struct bgp_pbr_range_port srcp, dstp;
|
||||
struct bgp_pbr_val_mask *icmp_type, *icmp_code;
|
||||
@ -1466,11 +1459,11 @@ static void bgp_pbr_icmp_action(struct bgp *bgp,
|
||||
for (ALL_LIST_ELEMENTS_RO(bpof->icmp_code, cnode, icmp_code)) {
|
||||
dstp.min_port = icmp_code->val;
|
||||
if (add)
|
||||
bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo,
|
||||
bpf, nh, rate);
|
||||
bgp_pbr_policyroute_add_to_zebra_unit(
|
||||
bgp, path, bpf, nh, rate);
|
||||
else
|
||||
bgp_pbr_policyroute_remove_from_zebra_unit(
|
||||
bgp, binfo, bpf);
|
||||
bgp, path, bpf);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1487,31 +1480,27 @@ static void bgp_pbr_icmp_action(struct bgp *bgp,
|
||||
dstp.max_port = 255;
|
||||
if (add)
|
||||
bgp_pbr_policyroute_add_to_zebra_unit(
|
||||
bgp, binfo,
|
||||
bpf, nh, rate);
|
||||
bgp, path, bpf, nh, rate);
|
||||
else
|
||||
bgp_pbr_policyroute_remove_from_zebra_unit(bgp,
|
||||
binfo, bpf);
|
||||
bgp_pbr_policyroute_remove_from_zebra_unit(
|
||||
bgp, path, bpf);
|
||||
continue;
|
||||
}
|
||||
for (ALL_LIST_ELEMENTS_RO(bpof->icmp_code, cnode, icmp_code)) {
|
||||
dstp.min_port = icmp_code->val;
|
||||
if (add)
|
||||
bgp_pbr_policyroute_add_to_zebra_unit(
|
||||
bgp, binfo,
|
||||
bpf, nh, rate);
|
||||
bgp, path, bpf, nh, rate);
|
||||
else
|
||||
bgp_pbr_policyroute_remove_from_zebra_unit(
|
||||
bgp, binfo, bpf);
|
||||
bgp, path, bpf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bgp_pbr_policyroute_remove_from_zebra_recursive(struct bgp *bgp,
|
||||
struct bgp_info *binfo,
|
||||
struct bgp_pbr_filter *bpf,
|
||||
struct bgp_pbr_or_filter *bpof,
|
||||
uint8_t type_entry)
|
||||
static void bgp_pbr_policyroute_remove_from_zebra_recursive(
|
||||
struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_filter *bpf,
|
||||
struct bgp_pbr_or_filter *bpof, uint8_t type_entry)
|
||||
{
|
||||
struct listnode *node, *nnode;
|
||||
struct bgp_pbr_val_mask *valmask;
|
||||
@ -1520,8 +1509,8 @@ static void bgp_pbr_policyroute_remove_from_zebra_recursive(struct bgp *bgp,
|
||||
struct bgp_pbr_val_mask **target_val;
|
||||
|
||||
if (type_entry == 0)
|
||||
return bgp_pbr_policyroute_remove_from_zebra_unit(bgp,
|
||||
binfo, bpf);
|
||||
return bgp_pbr_policyroute_remove_from_zebra_unit(bgp, path,
|
||||
bpf);
|
||||
next_type_entry = bgp_pbr_next_type_entry(type_entry);
|
||||
if (type_entry == FLOWSPEC_TCP_FLAGS && bpof->tcpflags) {
|
||||
orig_list = bpof->tcpflags;
|
||||
@ -1538,53 +1527,43 @@ static void bgp_pbr_policyroute_remove_from_zebra_recursive(struct bgp *bgp,
|
||||
} else if (type_entry == FLOWSPEC_ICMP_TYPE &&
|
||||
(bpof->icmp_type || bpof->icmp_code)) {
|
||||
/* enumerate list for icmp - must be last one */
|
||||
bgp_pbr_icmp_action(bgp, binfo, bpf, bpof, false, NULL, NULL);
|
||||
bgp_pbr_icmp_action(bgp, path, bpf, bpof, false, NULL, NULL);
|
||||
return;
|
||||
} else {
|
||||
return bgp_pbr_policyroute_remove_from_zebra_recursive(bgp,
|
||||
binfo,
|
||||
bpf, bpof,
|
||||
next_type_entry);
|
||||
return bgp_pbr_policyroute_remove_from_zebra_recursive(
|
||||
bgp, path, bpf, bpof, next_type_entry);
|
||||
}
|
||||
for (ALL_LIST_ELEMENTS(orig_list, node, nnode, valmask)) {
|
||||
*target_val = valmask;
|
||||
bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
|
||||
bpf, bpof,
|
||||
next_type_entry);
|
||||
bgp_pbr_policyroute_remove_from_zebra_recursive(
|
||||
bgp, path, bpf, bpof, next_type_entry);
|
||||
}
|
||||
}
|
||||
|
||||
static void bgp_pbr_policyroute_remove_from_zebra(struct bgp *bgp,
|
||||
struct bgp_info *binfo,
|
||||
struct bgp_pbr_filter *bpf,
|
||||
struct bgp_pbr_or_filter *bpof)
|
||||
static void bgp_pbr_policyroute_remove_from_zebra(
|
||||
struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_filter *bpf,
|
||||
struct bgp_pbr_or_filter *bpof)
|
||||
{
|
||||
if (!bpof)
|
||||
return bgp_pbr_policyroute_remove_from_zebra_unit(bgp,
|
||||
binfo,
|
||||
return bgp_pbr_policyroute_remove_from_zebra_unit(bgp, path,
|
||||
bpf);
|
||||
if (bpof->tcpflags)
|
||||
bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
|
||||
bpf, bpof,
|
||||
FLOWSPEC_TCP_FLAGS);
|
||||
bgp_pbr_policyroute_remove_from_zebra_recursive(
|
||||
bgp, path, bpf, bpof, FLOWSPEC_TCP_FLAGS);
|
||||
else if (bpof->dscp)
|
||||
bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
|
||||
bpf, bpof,
|
||||
FLOWSPEC_DSCP);
|
||||
bgp_pbr_policyroute_remove_from_zebra_recursive(
|
||||
bgp, path, bpf, bpof, FLOWSPEC_DSCP);
|
||||
else if (bpof->pkt_len)
|
||||
bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
|
||||
bpf, bpof,
|
||||
FLOWSPEC_PKT_LEN);
|
||||
bgp_pbr_policyroute_remove_from_zebra_recursive(
|
||||
bgp, path, bpf, bpof, FLOWSPEC_PKT_LEN);
|
||||
else if (bpof->fragment)
|
||||
bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
|
||||
bpf, bpof,
|
||||
FLOWSPEC_FRAGMENT);
|
||||
bgp_pbr_policyroute_remove_from_zebra_recursive(
|
||||
bgp, path, bpf, bpof, FLOWSPEC_FRAGMENT);
|
||||
else if (bpof->icmp_type || bpof->icmp_code)
|
||||
bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
|
||||
bpf, bpof,
|
||||
FLOWSPEC_ICMP_TYPE);
|
||||
bgp_pbr_policyroute_remove_from_zebra_recursive(
|
||||
bgp, path, bpf, bpof, FLOWSPEC_ICMP_TYPE);
|
||||
else
|
||||
bgp_pbr_policyroute_remove_from_zebra_unit(bgp, binfo, bpf);
|
||||
bgp_pbr_policyroute_remove_from_zebra_unit(bgp, path, bpf);
|
||||
/* flush bpof */
|
||||
if (bpof->tcpflags)
|
||||
list_delete_all_node(bpof->tcpflags);
|
||||
@ -1692,10 +1671,10 @@ static void bgp_pbr_dump_entry(struct bgp_pbr_filter *bpf, bool add)
|
||||
}
|
||||
|
||||
static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
|
||||
struct bgp_info *binfo,
|
||||
struct bgp_pbr_filter *bpf,
|
||||
struct nexthop *nh,
|
||||
float *rate)
|
||||
struct bgp_path_info *path,
|
||||
struct bgp_pbr_filter *bpf,
|
||||
struct nexthop *nh,
|
||||
float *rate)
|
||||
{
|
||||
struct bgp_pbr_match temp;
|
||||
struct bgp_pbr_match_entry temp2;
|
||||
@ -1848,19 +1827,21 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
|
||||
bpme->installed = false;
|
||||
bpme->install_in_progress = false;
|
||||
/* link bgp info to bpme */
|
||||
bpme->bgp_info = (void *)binfo;
|
||||
bpme->path = (void *)path;
|
||||
} else
|
||||
bpme_found = true;
|
||||
|
||||
/* already installed */
|
||||
if (bpme_found) {
|
||||
struct bgp_info_extra *extra = bgp_info_extra_get(binfo);
|
||||
struct bgp_path_info_extra *extra =
|
||||
bgp_path_info_extra_get(path);
|
||||
|
||||
if (extra && extra->bgp_fs_pbr &&
|
||||
listnode_lookup(extra->bgp_fs_pbr, bpme)) {
|
||||
if (BGP_DEBUG(pbr, PBR_ERROR))
|
||||
zlog_err("%s: entry %p/%p already installed in bgp pbr",
|
||||
__func__, binfo, bpme);
|
||||
zlog_err(
|
||||
"%s: entry %p/%p already installed in bgp pbr",
|
||||
__func__, path, bpme);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1911,13 +1892,10 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
|
||||
|
||||
}
|
||||
|
||||
static void bgp_pbr_policyroute_add_to_zebra_recursive(struct bgp *bgp,
|
||||
struct bgp_info *binfo,
|
||||
struct bgp_pbr_filter *bpf,
|
||||
struct bgp_pbr_or_filter *bpof,
|
||||
struct nexthop *nh,
|
||||
float *rate,
|
||||
uint8_t type_entry)
|
||||
static void bgp_pbr_policyroute_add_to_zebra_recursive(
|
||||
struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_filter *bpf,
|
||||
struct bgp_pbr_or_filter *bpof, struct nexthop *nh, float *rate,
|
||||
uint8_t type_entry)
|
||||
{
|
||||
struct listnode *node, *nnode;
|
||||
struct bgp_pbr_val_mask *valmask;
|
||||
@ -1926,8 +1904,8 @@ static void bgp_pbr_policyroute_add_to_zebra_recursive(struct bgp *bgp,
|
||||
struct bgp_pbr_val_mask **target_val;
|
||||
|
||||
if (type_entry == 0)
|
||||
return bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo, bpf,
|
||||
nh, rate);
|
||||
return bgp_pbr_policyroute_add_to_zebra_unit(bgp, path, bpf, nh,
|
||||
rate);
|
||||
next_type_entry = bgp_pbr_next_type_entry(type_entry);
|
||||
if (type_entry == FLOWSPEC_TCP_FLAGS && bpof->tcpflags) {
|
||||
orig_list = bpof->tcpflags;
|
||||
@ -1944,59 +1922,45 @@ static void bgp_pbr_policyroute_add_to_zebra_recursive(struct bgp *bgp,
|
||||
} else if (type_entry == FLOWSPEC_ICMP_TYPE &&
|
||||
(bpof->icmp_type || bpof->icmp_code)) {
|
||||
/* enumerate list for icmp - must be last one */
|
||||
bgp_pbr_icmp_action(bgp, binfo, bpf, bpof, true, nh, rate);
|
||||
bgp_pbr_icmp_action(bgp, path, bpf, bpof, true, nh, rate);
|
||||
return;
|
||||
} else {
|
||||
return bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
|
||||
bpf, bpof, nh, rate,
|
||||
next_type_entry);
|
||||
return bgp_pbr_policyroute_add_to_zebra_recursive(
|
||||
bgp, path, bpf, bpof, nh, rate, next_type_entry);
|
||||
}
|
||||
for (ALL_LIST_ELEMENTS(orig_list, node, nnode, valmask)) {
|
||||
*target_val = valmask;
|
||||
bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
|
||||
bpf, bpof,
|
||||
nh, rate,
|
||||
next_type_entry);
|
||||
bgp_pbr_policyroute_add_to_zebra_recursive(
|
||||
bgp, path, bpf, bpof, nh, rate, next_type_entry);
|
||||
}
|
||||
}
|
||||
|
||||
static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
|
||||
struct bgp_info *binfo,
|
||||
struct bgp_pbr_filter *bpf,
|
||||
struct bgp_pbr_or_filter *bpof,
|
||||
struct nexthop *nh,
|
||||
float *rate)
|
||||
struct bgp_path_info *path,
|
||||
struct bgp_pbr_filter *bpf,
|
||||
struct bgp_pbr_or_filter *bpof,
|
||||
struct nexthop *nh, float *rate)
|
||||
{
|
||||
if (!bpof)
|
||||
return bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo,
|
||||
bpf, nh, rate);
|
||||
return bgp_pbr_policyroute_add_to_zebra_unit(bgp, path, bpf, nh,
|
||||
rate);
|
||||
if (bpof->tcpflags)
|
||||
bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
|
||||
bpf, bpof,
|
||||
nh, rate,
|
||||
FLOWSPEC_TCP_FLAGS);
|
||||
bgp_pbr_policyroute_add_to_zebra_recursive(
|
||||
bgp, path, bpf, bpof, nh, rate, FLOWSPEC_TCP_FLAGS);
|
||||
else if (bpof->dscp)
|
||||
bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
|
||||
bpf, bpof,
|
||||
nh, rate,
|
||||
FLOWSPEC_DSCP);
|
||||
bgp_pbr_policyroute_add_to_zebra_recursive(
|
||||
bgp, path, bpf, bpof, nh, rate, FLOWSPEC_DSCP);
|
||||
else if (bpof->pkt_len)
|
||||
bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
|
||||
bpf, bpof,
|
||||
nh, rate,
|
||||
FLOWSPEC_PKT_LEN);
|
||||
bgp_pbr_policyroute_add_to_zebra_recursive(
|
||||
bgp, path, bpf, bpof, nh, rate, FLOWSPEC_PKT_LEN);
|
||||
else if (bpof->fragment)
|
||||
bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
|
||||
bpf, bpof,
|
||||
nh, rate,
|
||||
FLOWSPEC_FRAGMENT);
|
||||
bgp_pbr_policyroute_add_to_zebra_recursive(
|
||||
bgp, path, bpf, bpof, nh, rate, FLOWSPEC_FRAGMENT);
|
||||
else if (bpof->icmp_type || bpof->icmp_code)
|
||||
bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
|
||||
bpf, bpof, nh, rate,
|
||||
FLOWSPEC_ICMP_TYPE);
|
||||
bgp_pbr_policyroute_add_to_zebra_recursive(
|
||||
bgp, path, bpf, bpof, nh, rate, FLOWSPEC_ICMP_TYPE);
|
||||
else
|
||||
bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo, bpf,
|
||||
nh, rate);
|
||||
bgp_pbr_policyroute_add_to_zebra_unit(bgp, path, bpf, nh, rate);
|
||||
/* flush bpof */
|
||||
if (bpof->tcpflags)
|
||||
list_delete_all_node(bpof->tcpflags);
|
||||
@ -2012,10 +1976,8 @@ static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
|
||||
list_delete_all_node(bpof->icmp_code);
|
||||
}
|
||||
|
||||
static void bgp_pbr_handle_entry(struct bgp *bgp,
|
||||
struct bgp_info *binfo,
|
||||
struct bgp_pbr_entry_main *api,
|
||||
bool add)
|
||||
static void bgp_pbr_handle_entry(struct bgp *bgp, struct bgp_path_info *path,
|
||||
struct bgp_pbr_entry_main *api, bool add)
|
||||
{
|
||||
struct nexthop nh;
|
||||
int i = 0;
|
||||
@ -2151,9 +2113,8 @@ static void bgp_pbr_handle_entry(struct bgp *bgp,
|
||||
bpf.src_port = srcp;
|
||||
bpf.dst_port = dstp;
|
||||
if (!add)
|
||||
return bgp_pbr_policyroute_remove_from_zebra(bgp,
|
||||
binfo,
|
||||
&bpf, &bpof);
|
||||
return bgp_pbr_policyroute_remove_from_zebra(bgp, path, &bpf,
|
||||
&bpof);
|
||||
/* no action for add = true */
|
||||
for (i = 0; i < api->action_num; i++) {
|
||||
switch (api->actions[i].action) {
|
||||
@ -2162,9 +2123,8 @@ static void bgp_pbr_handle_entry(struct bgp *bgp,
|
||||
if (api->actions[i].u.r.rate == 0) {
|
||||
nh.vrf_id = api->vrf_id;
|
||||
nh.type = NEXTHOP_TYPE_BLACKHOLE;
|
||||
bgp_pbr_policyroute_add_to_zebra(bgp, binfo,
|
||||
&bpf, &bpof,
|
||||
&nh, &rate);
|
||||
bgp_pbr_policyroute_add_to_zebra(
|
||||
bgp, path, &bpf, &bpof, &nh, &rate);
|
||||
} else {
|
||||
/* update rate. can be reentrant */
|
||||
rate = api->actions[i].u.r.rate;
|
||||
@ -2204,8 +2164,7 @@ static void bgp_pbr_handle_entry(struct bgp *bgp,
|
||||
nh.gate.ipv4.s_addr =
|
||||
api->actions[i].u.zr.redirect_ip_v4.s_addr;
|
||||
nh.vrf_id = api->vrf_id;
|
||||
bgp_pbr_policyroute_add_to_zebra(bgp, binfo,
|
||||
&bpf, &bpof,
|
||||
bgp_pbr_policyroute_add_to_zebra(bgp, path, &bpf, &bpof,
|
||||
&nh, &rate);
|
||||
/* XXX combination with REDIRECT_VRF
|
||||
* + REDIRECT_NH_IP not done
|
||||
@ -2215,8 +2174,7 @@ static void bgp_pbr_handle_entry(struct bgp *bgp,
|
||||
case ACTION_REDIRECT:
|
||||
nh.vrf_id = api->actions[i].u.redirect_vrf;
|
||||
nh.type = NEXTHOP_TYPE_IPV4;
|
||||
bgp_pbr_policyroute_add_to_zebra(bgp, binfo,
|
||||
&bpf, &bpof,
|
||||
bgp_pbr_policyroute_add_to_zebra(bgp, path, &bpf, &bpof,
|
||||
&nh, &rate);
|
||||
continue_loop = 0;
|
||||
break;
|
||||
@ -2236,8 +2194,8 @@ static void bgp_pbr_handle_entry(struct bgp *bgp,
|
||||
}
|
||||
|
||||
void bgp_pbr_update_entry(struct bgp *bgp, struct prefix *p,
|
||||
struct bgp_info *info, afi_t afi, safi_t safi,
|
||||
bool nlri_update)
|
||||
struct bgp_path_info *info, afi_t afi, safi_t safi,
|
||||
bool nlri_update)
|
||||
{
|
||||
struct bgp_pbr_entry_main api;
|
||||
|
||||
|
@ -219,7 +219,7 @@ struct bgp_pbr_match_entry {
|
||||
uint16_t dst_port_max;
|
||||
uint8_t proto;
|
||||
|
||||
void *bgp_info;
|
||||
void *path;
|
||||
|
||||
bool installed;
|
||||
bool install_in_progress;
|
||||
@ -267,23 +267,22 @@ extern void bgp_pbr_cleanup(struct bgp *bgp);
|
||||
extern void bgp_pbr_init(struct bgp *bgp);
|
||||
|
||||
extern uint32_t bgp_pbr_action_hash_key(void *arg);
|
||||
extern int bgp_pbr_action_hash_equal(const void *arg1,
|
||||
extern bool bgp_pbr_action_hash_equal(const void *arg1,
|
||||
const void *arg2);
|
||||
extern uint32_t bgp_pbr_match_entry_hash_key(void *arg);
|
||||
extern int bgp_pbr_match_entry_hash_equal(const void *arg1,
|
||||
extern bool bgp_pbr_match_entry_hash_equal(const void *arg1,
|
||||
const void *arg2);
|
||||
extern uint32_t bgp_pbr_match_hash_key(void *arg);
|
||||
extern int bgp_pbr_match_hash_equal(const void *arg1,
|
||||
extern bool bgp_pbr_match_hash_equal(const void *arg1,
|
||||
const void *arg2);
|
||||
|
||||
void bgp_pbr_print_policy_route(struct bgp_pbr_entry_main *api);
|
||||
|
||||
struct bgp_node;
|
||||
struct bgp_info;
|
||||
struct bgp_path_info;
|
||||
extern void bgp_pbr_update_entry(struct bgp *bgp, struct prefix *p,
|
||||
struct bgp_info *new_select,
|
||||
afi_t afi, safi_t safi,
|
||||
bool nlri_update);
|
||||
struct bgp_path_info *new_select, afi_t afi,
|
||||
safi_t safi, bool nlri_update);
|
||||
|
||||
/* bgp pbr utilities */
|
||||
extern struct bgp_pbr_interface *pbr_interface_lookup(const char *name);
|
||||
|
2108
bgpd/bgp_route.c
2108
bgpd/bgp_route.c
File diff suppressed because it is too large
Load Diff
154
bgpd/bgp_route.h
154
bgpd/bgp_route.h
@ -72,11 +72,11 @@ enum bgp_show_adj_route_type {
|
||||
*/
|
||||
#define BGP_MAX_LABELS 2
|
||||
|
||||
/* Ancillary information to struct bgp_info,
|
||||
/* Ancillary information to struct bgp_path_info,
|
||||
* used for uncommonly used data (aggregation, MPLS, etc.)
|
||||
* and lazily allocated to save memory.
|
||||
*/
|
||||
struct bgp_info_extra {
|
||||
struct bgp_path_info_extra {
|
||||
/* Pointer to dampening structure. */
|
||||
struct bgp_damp_info *damp_info;
|
||||
|
||||
@ -150,13 +150,13 @@ struct bgp_info_extra {
|
||||
struct list *bgp_fs_pbr;
|
||||
};
|
||||
|
||||
struct bgp_info {
|
||||
struct bgp_path_info {
|
||||
/* For linked list. */
|
||||
struct bgp_info *next;
|
||||
struct bgp_info *prev;
|
||||
struct bgp_path_info *next;
|
||||
struct bgp_path_info *prev;
|
||||
|
||||
/* For nexthop linked list */
|
||||
LIST_ENTRY(bgp_info) nh_thread;
|
||||
LIST_ENTRY(bgp_path_info) nh_thread;
|
||||
|
||||
/* Back pointer to the prefix node */
|
||||
struct bgp_node *net;
|
||||
@ -171,11 +171,11 @@ struct bgp_info {
|
||||
struct attr *attr;
|
||||
|
||||
/* Extra information */
|
||||
struct bgp_info_extra *extra;
|
||||
struct bgp_path_info_extra *extra;
|
||||
|
||||
|
||||
/* Multipath information */
|
||||
struct bgp_info_mpath *mpath;
|
||||
struct bgp_path_info_mpath *mpath;
|
||||
|
||||
/* Uptime. */
|
||||
time_t uptime;
|
||||
@ -185,21 +185,21 @@ struct bgp_info {
|
||||
|
||||
/* BGP information status. */
|
||||
uint16_t flags;
|
||||
#define BGP_INFO_IGP_CHANGED (1 << 0)
|
||||
#define BGP_INFO_DAMPED (1 << 1)
|
||||
#define BGP_INFO_HISTORY (1 << 2)
|
||||
#define BGP_INFO_SELECTED (1 << 3)
|
||||
#define BGP_INFO_VALID (1 << 4)
|
||||
#define BGP_INFO_ATTR_CHANGED (1 << 5)
|
||||
#define BGP_INFO_DMED_CHECK (1 << 6)
|
||||
#define BGP_INFO_DMED_SELECTED (1 << 7)
|
||||
#define BGP_INFO_STALE (1 << 8)
|
||||
#define BGP_INFO_REMOVED (1 << 9)
|
||||
#define BGP_INFO_COUNTED (1 << 10)
|
||||
#define BGP_INFO_MULTIPATH (1 << 11)
|
||||
#define BGP_INFO_MULTIPATH_CHG (1 << 12)
|
||||
#define BGP_INFO_RIB_ATTR_CHG (1 << 13)
|
||||
#define BGP_INFO_ANNC_NH_SELF (1 << 14)
|
||||
#define BGP_PATH_IGP_CHANGED (1 << 0)
|
||||
#define BGP_PATH_DAMPED (1 << 1)
|
||||
#define BGP_PATH_HISTORY (1 << 2)
|
||||
#define BGP_PATH_SELECTED (1 << 3)
|
||||
#define BGP_PATH_VALID (1 << 4)
|
||||
#define BGP_PATH_ATTR_CHANGED (1 << 5)
|
||||
#define BGP_PATH_DMED_CHECK (1 << 6)
|
||||
#define BGP_PATH_DMED_SELECTED (1 << 7)
|
||||
#define BGP_PATH_STALE (1 << 8)
|
||||
#define BGP_PATH_REMOVED (1 << 9)
|
||||
#define BGP_PATH_COUNTED (1 << 10)
|
||||
#define BGP_PATH_MULTIPATH (1 << 11)
|
||||
#define BGP_PATH_MULTIPATH_CHG (1 << 12)
|
||||
#define BGP_PATH_RIB_ATTR_CHG (1 << 13)
|
||||
#define BGP_PATH_ANNC_NH_SELF (1 << 14)
|
||||
|
||||
/* BGP route type. This can be static, RIP, OSPF, BGP etc. */
|
||||
uint8_t type;
|
||||
@ -224,9 +224,9 @@ struct bgp_info {
|
||||
};
|
||||
|
||||
/* Structure used in BGP path selection */
|
||||
struct bgp_info_pair {
|
||||
struct bgp_info *old;
|
||||
struct bgp_info *new;
|
||||
struct bgp_path_info_pair {
|
||||
struct bgp_path_info *old;
|
||||
struct bgp_path_info *new;
|
||||
};
|
||||
|
||||
/* BGP static route configuration. */
|
||||
@ -277,20 +277,20 @@ struct bgp_static {
|
||||
#define BGP_ATTR_NEXTHOP_AFI_IP6(attr) \
|
||||
(!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) \
|
||||
&& ((attr)->mp_nexthop_len == 16 || (attr)->mp_nexthop_len == 32))
|
||||
#define BGP_INFO_COUNTABLE(BI) \
|
||||
(!CHECK_FLAG((BI)->flags, BGP_INFO_HISTORY) \
|
||||
&& !CHECK_FLAG((BI)->flags, BGP_INFO_REMOVED))
|
||||
#define BGP_PATH_COUNTABLE(BI) \
|
||||
(!CHECK_FLAG((BI)->flags, BGP_PATH_HISTORY) \
|
||||
&& !CHECK_FLAG((BI)->flags, BGP_PATH_REMOVED))
|
||||
|
||||
/* Flags which indicate a route is unuseable in some form */
|
||||
#define BGP_INFO_UNUSEABLE \
|
||||
(BGP_INFO_HISTORY | BGP_INFO_DAMPED | BGP_INFO_REMOVED)
|
||||
#define BGP_PATH_UNUSEABLE \
|
||||
(BGP_PATH_HISTORY | BGP_PATH_DAMPED | BGP_PATH_REMOVED)
|
||||
/* Macro to check BGP information is alive or not. Sadly,
|
||||
* not equivalent to just checking previous, because of the
|
||||
* sense of the additional VALID flag.
|
||||
*/
|
||||
#define BGP_INFO_HOLDDOWN(BI) \
|
||||
(!CHECK_FLAG((BI)->flags, BGP_INFO_VALID) \
|
||||
|| CHECK_FLAG((BI)->flags, BGP_INFO_UNUSEABLE))
|
||||
#define BGP_PATH_HOLDDOWN(BI) \
|
||||
(!CHECK_FLAG((BI)->flags, BGP_PATH_VALID) \
|
||||
|| CHECK_FLAG((BI)->flags, BGP_PATH_UNUSEABLE))
|
||||
|
||||
#define DISTRIBUTE_IN_NAME(F) ((F)->dlist[FILTER_IN].name)
|
||||
#define DISTRIBUTE_IN(F) ((F)->dlist[FILTER_IN].alist)
|
||||
@ -318,7 +318,11 @@ struct bgp_static {
|
||||
/* path PREFIX (addpath rxid NUMBER) */
|
||||
#define PATH_ADDPATH_STR_BUFFER PREFIX2STR_BUFFER + 32
|
||||
|
||||
enum bgp_path_type { BGP_PATH_ALL, BGP_PATH_BESTPATH, BGP_PATH_MULTIPATH };
|
||||
enum bgp_path_type {
|
||||
BGP_PATH_SHOW_ALL,
|
||||
BGP_PATH_SHOW_BESTPATH,
|
||||
BGP_PATH_SHOW_MULTIPATH
|
||||
};
|
||||
|
||||
static inline void bgp_bump_version(struct bgp_node *node)
|
||||
{
|
||||
@ -335,7 +339,7 @@ static inline int bgp_fibupd_safi(safi_t safi)
|
||||
}
|
||||
|
||||
/* Prototypes. */
|
||||
extern void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri,
|
||||
extern void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi,
|
||||
struct peer *peer, afi_t afi, safi_t safi);
|
||||
extern void bgp_process_queue_init(void);
|
||||
extern void bgp_route_init(void);
|
||||
@ -354,15 +358,19 @@ extern void bgp_clear_stale_route(struct peer *, afi_t, safi_t);
|
||||
extern struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
|
||||
safi_t safi, struct prefix *p,
|
||||
struct prefix_rd *prd);
|
||||
extern struct bgp_info *bgp_info_lock(struct bgp_info *);
|
||||
extern struct bgp_info *bgp_info_unlock(struct bgp_info *);
|
||||
extern void bgp_info_add(struct bgp_node *rn, struct bgp_info *ri);
|
||||
extern void bgp_info_reap(struct bgp_node *rn, struct bgp_info *ri);
|
||||
extern void bgp_info_delete(struct bgp_node *rn, struct bgp_info *ri);
|
||||
extern struct bgp_info_extra *bgp_info_extra_get(struct bgp_info *);
|
||||
extern void bgp_info_set_flag(struct bgp_node *, struct bgp_info *, uint32_t);
|
||||
extern void bgp_info_unset_flag(struct bgp_node *, struct bgp_info *, uint32_t);
|
||||
extern void bgp_info_path_with_addpath_rx_str(struct bgp_info *ri, char *buf);
|
||||
extern struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path);
|
||||
extern struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path);
|
||||
extern void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi);
|
||||
extern void bgp_path_info_reap(struct bgp_node *rn, struct bgp_path_info *pi);
|
||||
extern void bgp_path_info_delete(struct bgp_node *rn, struct bgp_path_info *pi);
|
||||
extern struct bgp_path_info_extra *
|
||||
bgp_path_info_extra_get(struct bgp_path_info *path);
|
||||
extern void bgp_path_info_set_flag(struct bgp_node *rn,
|
||||
struct bgp_path_info *path, uint32_t flag);
|
||||
extern void bgp_path_info_unset_flag(struct bgp_node *rn,
|
||||
struct bgp_path_info *path, uint32_t flag);
|
||||
extern void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi,
|
||||
char *buf);
|
||||
|
||||
extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *);
|
||||
|
||||
@ -416,38 +424,44 @@ extern void bgp_config_write_network(struct vty *, struct bgp *, afi_t, safi_t);
|
||||
extern void bgp_config_write_distance(struct vty *, struct bgp *, afi_t,
|
||||
safi_t);
|
||||
|
||||
extern void bgp_aggregate_increment(struct bgp *, struct prefix *,
|
||||
struct bgp_info *, afi_t, safi_t);
|
||||
extern void bgp_aggregate_decrement(struct bgp *, struct prefix *,
|
||||
struct bgp_info *, afi_t, safi_t);
|
||||
extern void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
|
||||
struct bgp_path_info *path, afi_t afi,
|
||||
safi_t safi);
|
||||
extern void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
|
||||
struct bgp_path_info *path, afi_t afi,
|
||||
safi_t safi);
|
||||
|
||||
extern uint8_t bgp_distance_apply(struct prefix *, struct bgp_info *, afi_t,
|
||||
safi_t, struct bgp *);
|
||||
extern uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *path,
|
||||
afi_t afi, safi_t safi, struct bgp *bgp);
|
||||
|
||||
extern afi_t bgp_node_afi(struct vty *);
|
||||
extern safi_t bgp_node_safi(struct vty *);
|
||||
|
||||
extern struct bgp_info *info_make(int type, int sub_type,
|
||||
unsigned short instance, struct peer *peer,
|
||||
struct attr *attr, struct bgp_node *rn);
|
||||
extern struct bgp_path_info *info_make(int type, int sub_type,
|
||||
unsigned short instance,
|
||||
struct peer *peer, struct attr *attr,
|
||||
struct bgp_node *rn);
|
||||
|
||||
extern void route_vty_out(struct vty *, struct prefix *, struct bgp_info *, int,
|
||||
safi_t, json_object *);
|
||||
extern void route_vty_out_tag(struct vty *, struct prefix *, struct bgp_info *,
|
||||
int, safi_t, json_object *);
|
||||
extern void route_vty_out(struct vty *vty, struct prefix *p,
|
||||
struct bgp_path_info *path, int display, safi_t safi,
|
||||
json_object *json_paths);
|
||||
extern void route_vty_out_tag(struct vty *vty, struct prefix *p,
|
||||
struct bgp_path_info *path, int display,
|
||||
safi_t safi, json_object *json);
|
||||
extern void route_vty_out_tmp(struct vty *vty, struct prefix *p,
|
||||
struct attr *attr, safi_t safi, bool use_json,
|
||||
json_object *json_ar);
|
||||
extern void route_vty_out_overlay(struct vty *vty, struct prefix *p,
|
||||
struct bgp_info *binfo, int display,
|
||||
struct bgp_path_info *path, int display,
|
||||
json_object *json);
|
||||
|
||||
extern int subgroup_process_announce_selected(struct update_subgroup *subgrp,
|
||||
struct bgp_info *selected,
|
||||
struct bgp_path_info *selected,
|
||||
struct bgp_node *rn,
|
||||
uint32_t addpath_tx_id);
|
||||
|
||||
extern int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri,
|
||||
extern int subgroup_announce_check(struct bgp_node *rn,
|
||||
struct bgp_path_info *pi,
|
||||
struct update_subgroup *subgrp,
|
||||
struct prefix *p, struct attr *attr);
|
||||
|
||||
@ -458,28 +472,30 @@ extern void bgp_process_queues_drain_immediate(void);
|
||||
extern struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
|
||||
safi_t safi, struct prefix *p,
|
||||
struct prefix_rd *prd);
|
||||
extern struct bgp_info *bgp_info_new(void);
|
||||
extern void bgp_info_restore(struct bgp_node *, struct bgp_info *);
|
||||
extern struct bgp_path_info *bgp_path_info_new(void);
|
||||
extern void bgp_path_info_restore(struct bgp_node *rn,
|
||||
struct bgp_path_info *path);
|
||||
|
||||
extern int bgp_info_cmp_compatible(struct bgp *, struct bgp_info *,
|
||||
struct bgp_info *, char *pfx_buf, afi_t afi,
|
||||
safi_t safi);
|
||||
extern int bgp_path_info_cmp_compatible(struct bgp *bgp,
|
||||
struct bgp_path_info *new,
|
||||
struct bgp_path_info *exist,
|
||||
char *pfx_buf, afi_t afi, safi_t safi);
|
||||
extern void bgp_attr_add_gshut_community(struct attr *attr);
|
||||
|
||||
extern void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
|
||||
struct bgp_maxpaths_cfg *mpath_cfg,
|
||||
struct bgp_info_pair *result, afi_t afi,
|
||||
struct bgp_path_info_pair *result, afi_t afi,
|
||||
safi_t safi);
|
||||
extern void bgp_zebra_clear_route_change_flags(struct bgp_node *rn);
|
||||
extern int bgp_zebra_has_route_changed(struct bgp_node *rn,
|
||||
struct bgp_info *selected);
|
||||
struct bgp_path_info *selected);
|
||||
|
||||
extern void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
|
||||
struct bgp_node *rn,
|
||||
struct prefix_rd *prd, afi_t afi,
|
||||
safi_t safi, json_object *json);
|
||||
extern void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
|
||||
struct prefix *p, struct bgp_info *binfo,
|
||||
struct prefix *p, struct bgp_path_info *path,
|
||||
afi_t afi, safi_t safi,
|
||||
json_object *json_paths);
|
||||
extern int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -217,12 +217,12 @@ static route_map_result_t route_match(void *rule, const struct prefix *prefix,
|
||||
route_map_object_t type, void *object)
|
||||
{
|
||||
int *rpki_status = rule;
|
||||
struct bgp_info *bgp_info;
|
||||
struct bgp_path_info *path;
|
||||
|
||||
if (type == RMAP_BGP) {
|
||||
bgp_info = object;
|
||||
path = object;
|
||||
|
||||
if (rpki_validate_prefix(bgp_info->peer, bgp_info->attr, prefix)
|
||||
if (rpki_validate_prefix(path->peer, path->attr, prefix)
|
||||
== *rpki_status) {
|
||||
return RMAP_MATCH;
|
||||
}
|
||||
@ -418,13 +418,13 @@ static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
|
||||
|
||||
for (ain = bgp_node->adj_in; ain; ain = ain->next) {
|
||||
int ret;
|
||||
struct bgp_info *bgp_info = bgp_node->info;
|
||||
struct bgp_path_info *path = bgp_node->info;
|
||||
mpls_label_t *label = NULL;
|
||||
uint32_t num_labels = 0;
|
||||
|
||||
if (bgp_info && bgp_info->extra) {
|
||||
label = bgp_info->extra->label;
|
||||
num_labels = bgp_info->extra->num_labels;
|
||||
if (path && path->extra) {
|
||||
label = path->extra->label;
|
||||
num_labels = path->extra->num_labels;
|
||||
}
|
||||
ret = bgp_update(ain->peer, &bgp_node->p, ain->addpath_rx_id,
|
||||
ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
|
||||
|
@ -674,14 +674,15 @@ static uint8_t *bgpRcvdPathAttrTable(struct variable *v, oid name[],
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct bgp_info *bgp4PathAttrLookup(struct variable *v, oid name[],
|
||||
size_t *length, struct bgp *bgp,
|
||||
struct prefix_ipv4 *addr, int exact)
|
||||
static struct bgp_path_info *bgp4PathAttrLookup(struct variable *v, oid name[],
|
||||
size_t *length, struct bgp *bgp,
|
||||
struct prefix_ipv4 *addr,
|
||||
int exact)
|
||||
{
|
||||
oid *offset;
|
||||
int offsetlen;
|
||||
struct bgp_info *binfo;
|
||||
struct bgp_info *min;
|
||||
struct bgp_path_info *path;
|
||||
struct bgp_path_info *min;
|
||||
struct bgp_node *rn;
|
||||
union sockunion su;
|
||||
unsigned int len;
|
||||
@ -714,9 +715,9 @@ static struct bgp_info *bgp4PathAttrLookup(struct variable *v, oid name[],
|
||||
if (rn) {
|
||||
bgp_unlock_node(rn);
|
||||
|
||||
for (binfo = rn->info; binfo; binfo = binfo->next)
|
||||
if (sockunion_same(&binfo->peer->su, &su))
|
||||
return binfo;
|
||||
for (path = rn->info; path; path = path->next)
|
||||
if (sockunion_same(&path->peer->su, &su))
|
||||
return path;
|
||||
}
|
||||
} else {
|
||||
offset = name + v->namelen;
|
||||
@ -761,22 +762,22 @@ static struct bgp_info *bgp4PathAttrLookup(struct variable *v, oid name[],
|
||||
do {
|
||||
min = NULL;
|
||||
|
||||
for (binfo = rn->info; binfo; binfo = binfo->next) {
|
||||
if (binfo->peer->su.sin.sin_family == AF_INET
|
||||
for (path = rn->info; path; path = path->next) {
|
||||
if (path->peer->su.sin.sin_family == AF_INET
|
||||
&& ntohl(paddr.s_addr)
|
||||
< ntohl(binfo->peer->su.sin
|
||||
< ntohl(path->peer->su.sin
|
||||
.sin_addr
|
||||
.s_addr)) {
|
||||
if (min) {
|
||||
if (ntohl(binfo->peer->su.sin
|
||||
if (ntohl(path->peer->su.sin
|
||||
.sin_addr
|
||||
.s_addr)
|
||||
< ntohl(min->peer->su.sin
|
||||
.sin_addr
|
||||
.s_addr))
|
||||
min = binfo;
|
||||
min = path;
|
||||
} else
|
||||
min = binfo;
|
||||
min = path;
|
||||
}
|
||||
}
|
||||
|
||||
@ -812,7 +813,7 @@ static uint8_t *bgp4PathAttrTable(struct variable *v, oid name[],
|
||||
WriteMethod **write_method)
|
||||
{
|
||||
struct bgp *bgp;
|
||||
struct bgp_info *binfo;
|
||||
struct bgp_path_info *path;
|
||||
struct prefix_ipv4 addr;
|
||||
|
||||
bgp = bgp_get_default();
|
||||
@ -824,13 +825,13 @@ static uint8_t *bgp4PathAttrTable(struct variable *v, oid name[],
|
||||
return NULL;
|
||||
memset(&addr, 0, sizeof(struct prefix_ipv4));
|
||||
|
||||
binfo = bgp4PathAttrLookup(v, name, length, bgp, &addr, exact);
|
||||
if (!binfo)
|
||||
path = bgp4PathAttrLookup(v, name, length, bgp, &addr, exact);
|
||||
if (!path)
|
||||
return NULL;
|
||||
|
||||
switch (v->magic) {
|
||||
case BGP4PATHATTRPEER: /* 1 */
|
||||
return SNMP_IPADDRESS(binfo->peer->su.sin.sin_addr);
|
||||
return SNMP_IPADDRESS(path->peer->su.sin.sin_addr);
|
||||
break;
|
||||
case BGP4PATHATTRIPADDRPREFIXLEN: /* 2 */
|
||||
return SNMP_INTEGER(addr.prefixlen);
|
||||
@ -839,28 +840,28 @@ static uint8_t *bgp4PathAttrTable(struct variable *v, oid name[],
|
||||
return SNMP_IPADDRESS(addr.prefix);
|
||||
break;
|
||||
case BGP4PATHATTRORIGIN: /* 4 */
|
||||
return SNMP_INTEGER(binfo->attr->origin);
|
||||
return SNMP_INTEGER(path->attr->origin);
|
||||
break;
|
||||
case BGP4PATHATTRASPATHSEGMENT: /* 5 */
|
||||
return aspath_snmp_pathseg(binfo->attr->aspath, var_len);
|
||||
return aspath_snmp_pathseg(path->attr->aspath, var_len);
|
||||
break;
|
||||
case BGP4PATHATTRNEXTHOP: /* 6 */
|
||||
return SNMP_IPADDRESS(binfo->attr->nexthop);
|
||||
return SNMP_IPADDRESS(path->attr->nexthop);
|
||||
break;
|
||||
case BGP4PATHATTRMULTIEXITDISC: /* 7 */
|
||||
return SNMP_INTEGER(binfo->attr->med);
|
||||
return SNMP_INTEGER(path->attr->med);
|
||||
break;
|
||||
case BGP4PATHATTRLOCALPREF: /* 8 */
|
||||
return SNMP_INTEGER(binfo->attr->local_pref);
|
||||
return SNMP_INTEGER(path->attr->local_pref);
|
||||
break;
|
||||
case BGP4PATHATTRATOMICAGGREGATE: /* 9 */
|
||||
return SNMP_INTEGER(1);
|
||||
break;
|
||||
case BGP4PATHATTRAGGREGATORAS: /* 10 */
|
||||
return SNMP_INTEGER(binfo->attr->aggregator_as);
|
||||
return SNMP_INTEGER(path->attr->aggregator_as);
|
||||
break;
|
||||
case BGP4PATHATTRAGGREGATORADDR: /* 11 */
|
||||
return SNMP_IPADDRESS(binfo->attr->aggregator_addr);
|
||||
return SNMP_IPADDRESS(path->attr->aggregator_addr);
|
||||
break;
|
||||
case BGP4PATHATTRCALCLOCALPREF: /* 12 */
|
||||
return SNMP_INTEGER(-1);
|
||||
@ -868,7 +869,7 @@ static uint8_t *bgp4PathAttrTable(struct variable *v, oid name[],
|
||||
case BGP4PATHATTRBEST: /* 13 */
|
||||
#define BGP4_PathAttrBest_false 1
|
||||
#define BGP4_PathAttrBest_true 2
|
||||
if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED))
|
||||
if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
|
||||
return SNMP_INTEGER(BGP4_PathAttrBest_true);
|
||||
else
|
||||
return SNMP_INTEGER(BGP4_PathAttrBest_false);
|
||||
|
@ -104,7 +104,7 @@ struct bgp_table *bgp_table_init(struct bgp *bgp, afi_t afi, safi_t safi)
|
||||
route_table_set_info(rt->route_table, rt);
|
||||
|
||||
/*
|
||||
* pointer to bgp instance allows working back from bgp_info to bgp
|
||||
* pointer to bgp instance allows working back from bgp_path_info to bgp
|
||||
*/
|
||||
rt->bgp = bgp;
|
||||
|
||||
|
@ -393,7 +393,7 @@ static unsigned int updgrp_hash_key_make(void *p)
|
||||
return key;
|
||||
}
|
||||
|
||||
static int updgrp_hash_cmp(const void *p1, const void *p2)
|
||||
static bool updgrp_hash_cmp(const void *p1, const void *p2)
|
||||
{
|
||||
const struct update_group *grp1;
|
||||
const struct update_group *grp2;
|
||||
@ -407,7 +407,7 @@ static int updgrp_hash_cmp(const void *p1, const void *p2)
|
||||
safi_t safi;
|
||||
|
||||
if (!p1 || !p2)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
grp1 = p1;
|
||||
grp2 = p2;
|
||||
@ -422,68 +422,68 @@ static int updgrp_hash_cmp(const void *p1, const void *p2)
|
||||
|
||||
/* put EBGP and IBGP peers in different update groups */
|
||||
if (pe1->sort != pe2->sort)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* check peer flags */
|
||||
if ((pe1->flags & PEER_UPDGRP_FLAGS)
|
||||
!= (pe2->flags & PEER_UPDGRP_FLAGS))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* If there is 'local-as' configured, it should match. */
|
||||
if (pe1->change_local_as != pe2->change_local_as)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* flags like route reflector client */
|
||||
if ((flags1 & PEER_UPDGRP_AF_FLAGS) != (flags2 & PEER_UPDGRP_AF_FLAGS))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if ((pe1->cap & PEER_UPDGRP_CAP_FLAGS)
|
||||
!= (pe2->cap & PEER_UPDGRP_CAP_FLAGS))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if ((pe1->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS)
|
||||
!= (pe2->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (pe1->v_routeadv != pe2->v_routeadv)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (pe1->group != pe2->group)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* route-map names should be the same */
|
||||
if ((fl1->map[RMAP_OUT].name && !fl2->map[RMAP_OUT].name)
|
||||
|| (!fl1->map[RMAP_OUT].name && fl2->map[RMAP_OUT].name)
|
||||
|| (fl1->map[RMAP_OUT].name && fl2->map[RMAP_OUT].name
|
||||
&& strcmp(fl1->map[RMAP_OUT].name, fl2->map[RMAP_OUT].name)))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if ((fl1->dlist[FILTER_OUT].name && !fl2->dlist[FILTER_OUT].name)
|
||||
|| (!fl1->dlist[FILTER_OUT].name && fl2->dlist[FILTER_OUT].name)
|
||||
|| (fl1->dlist[FILTER_OUT].name && fl2->dlist[FILTER_OUT].name
|
||||
&& strcmp(fl1->dlist[FILTER_OUT].name,
|
||||
fl2->dlist[FILTER_OUT].name)))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if ((fl1->plist[FILTER_OUT].name && !fl2->plist[FILTER_OUT].name)
|
||||
|| (!fl1->plist[FILTER_OUT].name && fl2->plist[FILTER_OUT].name)
|
||||
|| (fl1->plist[FILTER_OUT].name && fl2->plist[FILTER_OUT].name
|
||||
&& strcmp(fl1->plist[FILTER_OUT].name,
|
||||
fl2->plist[FILTER_OUT].name)))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if ((fl1->aslist[FILTER_OUT].name && !fl2->aslist[FILTER_OUT].name)
|
||||
|| (!fl1->aslist[FILTER_OUT].name && fl2->aslist[FILTER_OUT].name)
|
||||
|| (fl1->aslist[FILTER_OUT].name && fl2->aslist[FILTER_OUT].name
|
||||
&& strcmp(fl1->aslist[FILTER_OUT].name,
|
||||
fl2->aslist[FILTER_OUT].name)))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if ((fl1->usmap.name && !fl2->usmap.name)
|
||||
|| (!fl1->usmap.name && fl2->usmap.name)
|
||||
|| (fl1->usmap.name && fl2->usmap.name
|
||||
&& strcmp(fl1->usmap.name, fl2->usmap.name)))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if ((pe1->default_rmap[afi][safi].name
|
||||
&& !pe2->default_rmap[afi][safi].name)
|
||||
@ -493,19 +493,19 @@ static int updgrp_hash_cmp(const void *p1, const void *p2)
|
||||
&& pe2->default_rmap[afi][safi].name
|
||||
&& strcmp(pe1->default_rmap[afi][safi].name,
|
||||
pe2->default_rmap[afi][safi].name)))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if ((afi == AFI_IP6) && (pe1->shared_network != pe2->shared_network))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if ((CHECK_FLAG(pe1->flags, PEER_FLAG_LONESOUL)
|
||||
|| CHECK_FLAG(pe1->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
|
||||
|| CHECK_FLAG(pe1->af_cap[afi][safi],
|
||||
PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
|
||||
&& !sockunion_same(&pe1->su, &pe2->su))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void peer_lonesoul_or_not(struct peer *peer, int set)
|
||||
@ -1906,7 +1906,7 @@ int bgp_addpath_encode_tx(struct peer *peer, afi_t afi, safi_t safi)
|
||||
* configured addpath-tx knob
|
||||
*/
|
||||
int bgp_addpath_tx_path(struct peer *peer, afi_t afi, safi_t safi,
|
||||
struct bgp_info *ri)
|
||||
struct bgp_path_info *pi)
|
||||
{
|
||||
if (CHECK_FLAG(peer->af_flags[afi][safi],
|
||||
PEER_FLAG_ADDPATH_TX_ALL_PATHS))
|
||||
@ -1914,7 +1914,7 @@ int bgp_addpath_tx_path(struct peer *peer, afi_t afi, safi_t safi,
|
||||
|
||||
if (CHECK_FLAG(peer->af_flags[afi][safi],
|
||||
PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)
|
||||
&& CHECK_FLAG(ri->flags, BGP_INFO_DMED_SELECTED))
|
||||
&& CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
@ -293,7 +293,7 @@ typedef int (*updgrp_walkcb)(struct update_group *updgrp, void *ctx);
|
||||
struct updwalk_context {
|
||||
struct vty *vty;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *pi;
|
||||
uint64_t updgrp_id;
|
||||
uint64_t subgrp_id;
|
||||
bgp_policy_type_e policy_type;
|
||||
@ -442,7 +442,7 @@ extern void subgroup_announce_all(struct update_subgroup *subgrp);
|
||||
extern void subgroup_default_originate(struct update_subgroup *subgrp,
|
||||
int withdraw);
|
||||
extern void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
struct bgp_node *rn, struct bgp_info *ri);
|
||||
struct bgp_node *rn, struct bgp_path_info *pi);
|
||||
extern void subgroup_clear_table(struct update_subgroup *subgrp);
|
||||
extern void update_group_announce(struct bgp *bgp);
|
||||
extern void update_group_announce_rrclients(struct bgp *bgp);
|
||||
@ -455,7 +455,8 @@ extern void bgp_adj_out_remove_subgroup(struct bgp_node *rn,
|
||||
struct update_subgroup *subgrp);
|
||||
extern void bgp_adj_out_set_subgroup(struct bgp_node *rn,
|
||||
struct update_subgroup *subgrp,
|
||||
struct attr *attr, struct bgp_info *binfo);
|
||||
struct attr *attr,
|
||||
struct bgp_path_info *path);
|
||||
extern void bgp_adj_out_unset_subgroup(struct bgp_node *rn,
|
||||
struct update_subgroup *subgrp,
|
||||
char withdraw, uint32_t addpath_tx_id);
|
||||
@ -469,7 +470,7 @@ extern int update_group_clear_update_dbg(struct update_group *updgrp,
|
||||
extern void update_bgp_group_free(struct bgp *bgp);
|
||||
extern int bgp_addpath_encode_tx(struct peer *peer, afi_t afi, safi_t safi);
|
||||
extern int bgp_addpath_tx_path(struct peer *peer, afi_t afi, safi_t safi,
|
||||
struct bgp_info *ri);
|
||||
struct bgp_path_info *pi);
|
||||
|
||||
/*
|
||||
* Inline functions
|
||||
|
@ -101,7 +101,7 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
|
||||
{
|
||||
struct updwalk_context *ctx = arg;
|
||||
struct update_subgroup *subgrp;
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *pi;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
struct peer *peer;
|
||||
@ -140,15 +140,15 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
|
||||
adj_next = adj->next;
|
||||
|
||||
if (adj->subgroup == subgrp) {
|
||||
for (ri = ctx->rn->info; ri;
|
||||
ri = ri->next) {
|
||||
if (ri->addpath_tx_id
|
||||
for (pi = ctx->rn->info; pi;
|
||||
pi = pi->next) {
|
||||
if (pi->addpath_tx_id
|
||||
== adj->addpath_tx_id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ri) {
|
||||
if (!pi) {
|
||||
subgroup_process_announce_selected(
|
||||
subgrp, NULL,
|
||||
ctx->rn,
|
||||
@ -157,32 +157,32 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
for (ri = ctx->rn->info; ri; ri = ri->next) {
|
||||
for (pi = ctx->rn->info; pi; pi = pi->next) {
|
||||
/* Skip the bestpath for now */
|
||||
if (ri == ctx->ri)
|
||||
if (pi == ctx->pi)
|
||||
continue;
|
||||
|
||||
subgroup_process_announce_selected(
|
||||
subgrp, ri, ctx->rn,
|
||||
ri->addpath_tx_id);
|
||||
subgrp, pi, ctx->rn,
|
||||
pi->addpath_tx_id);
|
||||
}
|
||||
|
||||
/* Process the bestpath last so the "show [ip]
|
||||
* bgp neighbor x.x.x.x advertised"
|
||||
* output shows the attributes from the bestpath
|
||||
*/
|
||||
if (ctx->ri)
|
||||
if (ctx->pi)
|
||||
subgroup_process_announce_selected(
|
||||
subgrp, ctx->ri, ctx->rn,
|
||||
ctx->ri->addpath_tx_id);
|
||||
subgrp, ctx->pi, ctx->rn,
|
||||
ctx->pi->addpath_tx_id);
|
||||
}
|
||||
|
||||
/* An update-group that does not use addpath */
|
||||
else {
|
||||
if (ctx->ri) {
|
||||
if (ctx->pi) {
|
||||
subgroup_process_announce_selected(
|
||||
subgrp, ctx->ri, ctx->rn,
|
||||
ctx->ri->addpath_tx_id);
|
||||
subgrp, ctx->pi, ctx->rn,
|
||||
ctx->pi->addpath_tx_id);
|
||||
} else {
|
||||
/* Find the addpath_tx_id of the path we
|
||||
* had advertised and
|
||||
@ -429,7 +429,7 @@ bgp_advertise_clean_subgroup(struct update_subgroup *subgrp,
|
||||
|
||||
void bgp_adj_out_set_subgroup(struct bgp_node *rn,
|
||||
struct update_subgroup *subgrp, struct attr *attr,
|
||||
struct bgp_info *binfo)
|
||||
struct bgp_path_info *path)
|
||||
{
|
||||
struct bgp_adj_out *adj = NULL;
|
||||
struct bgp_advertise *adv;
|
||||
@ -438,10 +438,10 @@ void bgp_adj_out_set_subgroup(struct bgp_node *rn,
|
||||
return;
|
||||
|
||||
/* Look for adjacency information. */
|
||||
adj = adj_lookup(rn, subgrp, binfo->addpath_tx_id);
|
||||
adj = adj_lookup(rn, subgrp, path->addpath_tx_id);
|
||||
|
||||
if (!adj) {
|
||||
adj = bgp_adj_out_alloc(subgrp, rn, binfo->addpath_tx_id);
|
||||
adj = bgp_adj_out_alloc(subgrp, rn, path->addpath_tx_id);
|
||||
if (!adj)
|
||||
return;
|
||||
}
|
||||
@ -452,8 +452,9 @@ void bgp_adj_out_set_subgroup(struct bgp_node *rn,
|
||||
|
||||
adv = adj->adv;
|
||||
adv->rn = rn;
|
||||
assert(adv->binfo == NULL);
|
||||
adv->binfo = bgp_info_lock(binfo); /* bgp_info adj_out reference */
|
||||
assert(adv->pathi == NULL);
|
||||
/* bgp_path_info adj_out reference */
|
||||
adv->pathi = bgp_path_info_lock(path);
|
||||
|
||||
if (attr)
|
||||
adv->baa = bgp_advertise_intern(subgrp->hash, attr);
|
||||
@ -568,7 +569,7 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
|
||||
struct bgp_table *table)
|
||||
{
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *ri;
|
||||
struct attr attr;
|
||||
struct peer *peer;
|
||||
afi_t afi;
|
||||
@ -594,7 +595,7 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
|
||||
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
|
||||
for (ri = rn->info; ri; ri = ri->next)
|
||||
|
||||
if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)
|
||||
if (CHECK_FLAG(ri->flags, BGP_PATH_SELECTED)
|
||||
|| (addpath_capable
|
||||
&& bgp_addpath_tx_path(peer, afi, safi, ri))) {
|
||||
if (subgroup_announce_check(rn, ri, subgrp,
|
||||
@ -663,11 +664,12 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
|
||||
{
|
||||
struct bgp *bgp;
|
||||
struct attr attr;
|
||||
struct bgp_info *info, init_info, tmp_info;
|
||||
struct aspath *aspath;
|
||||
struct bgp_path_info tmp_info;
|
||||
struct prefix p;
|
||||
struct peer *from;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *ri;
|
||||
struct peer *peer;
|
||||
int ret = RMAP_DENYMATCH;
|
||||
afi_t afi;
|
||||
@ -687,59 +689,46 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
|
||||
from = bgp->peer_self;
|
||||
|
||||
bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
|
||||
aspath = attr.aspath;
|
||||
|
||||
attr.local_pref = bgp->default_local_pref;
|
||||
|
||||
if ((afi == AFI_IP6) || peer_cap_enhe(peer, afi, safi)) {
|
||||
/* IPv6 global nexthop must be included.
|
||||
*/
|
||||
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
|
||||
|
||||
/* If the peer is on shared nextwork and
|
||||
* we have link-local nexthop set it. */
|
||||
if (peer->shared_network
|
||||
&& !IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_local))
|
||||
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
|
||||
}
|
||||
init_info.attr = &attr;
|
||||
info = &init_info;
|
||||
bgp_attr_intern(info->attr);
|
||||
|
||||
memset(&p, 0, sizeof(p));
|
||||
p.family = afi2family(afi);
|
||||
p.prefixlen = 0;
|
||||
|
||||
if ((afi == AFI_IP6) || peer_cap_enhe(peer, afi, safi)) {
|
||||
/* IPv6 global nexthop must be included. */
|
||||
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
|
||||
|
||||
/* If the peer is on shared nextwork and we have link-local
|
||||
nexthop set it. */
|
||||
if (peer->shared_network
|
||||
&& !IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_local))
|
||||
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
|
||||
}
|
||||
|
||||
if (peer->default_rmap[afi][safi].name) {
|
||||
SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT);
|
||||
for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
|
||||
rn = bgp_route_next(rn)) {
|
||||
for (ri = rn->info; ri; ri = ri->next) {
|
||||
struct attr dummy_attr;
|
||||
|
||||
/* Provide dummy so the route-map can't modify
|
||||
* the attributes */
|
||||
bgp_attr_dup(&dummy_attr, ri->attr);
|
||||
tmp_info.peer = ri->peer;
|
||||
tmp_info.attr = ri->attr;
|
||||
|
||||
/* Reset attributes every time to avoid \
|
||||
* unexpected as-path prepends */
|
||||
bgp_attr_default_set(tmp_info.attr,
|
||||
BGP_ORIGIN_IGP);
|
||||
|
||||
if ((afi == AFI_IP6)
|
||||
|| peer_cap_enhe(peer, afi, safi)) {
|
||||
tmp_info.attr->mp_nexthop_len =
|
||||
BGP_ATTR_NHLEN_IPV6_GLOBAL;
|
||||
|
||||
if (peer->shared_network
|
||||
&& !IN6_IS_ADDR_UNSPECIFIED(
|
||||
&peer->nexthop.v6_local))
|
||||
tmp_info.attr->mp_nexthop_len =
|
||||
BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
|
||||
}
|
||||
tmp_info.attr = &dummy_attr;
|
||||
|
||||
ret = route_map_apply(
|
||||
peer->default_rmap[afi][safi].map,
|
||||
&rn->p, RMAP_BGP, &tmp_info);
|
||||
|
||||
info = &tmp_info;
|
||||
bgp_attr_intern(info->attr);
|
||||
|
||||
/* The route map might have set attributes. If
|
||||
* we don't flush them
|
||||
* here, they will be leaked. */
|
||||
bgp_attr_flush(&dummy_attr);
|
||||
if (ret != RMAP_DENYMATCH)
|
||||
break;
|
||||
}
|
||||
@ -761,13 +750,12 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
|
||||
SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
|
||||
|
||||
if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
|
||||
bgp_attr_add_gshut_community(info->attr);
|
||||
bgp_attr_add_gshut_community(&attr);
|
||||
}
|
||||
|
||||
SET_FLAG(subgrp->sflags,
|
||||
SUBGRP_STATUS_DEFAULT_ORIGINATE);
|
||||
subgroup_default_update_packet(subgrp, info->attr,
|
||||
from);
|
||||
subgroup_default_update_packet(subgrp, &attr, from);
|
||||
|
||||
/* The 'neighbor x.x.x.x default-originate' default will
|
||||
* act as an
|
||||
@ -787,7 +775,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
|
||||
BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
|
||||
}
|
||||
}
|
||||
aspath_unintern(&info->attr->aspath);
|
||||
|
||||
aspath_unintern(&aspath);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -830,10 +819,10 @@ void subgroup_announce_all(struct update_subgroup *subgrp)
|
||||
* input route.
|
||||
*/
|
||||
void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
struct bgp_node *rn, struct bgp_info *ri)
|
||||
struct bgp_node *rn, struct bgp_path_info *pi)
|
||||
{
|
||||
struct updwalk_context ctx;
|
||||
ctx.ri = ri;
|
||||
ctx.pi = pi;
|
||||
ctx.rn = rn;
|
||||
update_group_af_walk(bgp, afi, safi, group_announce_route_walkcb, &ctx);
|
||||
}
|
||||
|
@ -687,7 +687,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
|
||||
struct bgp_adj_out *adj;
|
||||
struct bgp_advertise *adv;
|
||||
struct bgp_node *rn = NULL;
|
||||
struct bgp_info *binfo = NULL;
|
||||
struct bgp_path_info *path = NULL;
|
||||
bgp_size_t total_attr_len = 0;
|
||||
unsigned long attrlen_pos = 0;
|
||||
size_t mpattrlen_pos = 0;
|
||||
@ -731,7 +731,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
|
||||
rn = adv->rn;
|
||||
adj = adv->adj;
|
||||
addpath_tx_id = adj->addpath_tx_id;
|
||||
binfo = adv->binfo;
|
||||
path = adv->pathi;
|
||||
|
||||
space_remaining = STREAM_CONCAT_REMAIN(s, snlri, STREAM_SIZE(s))
|
||||
- BGP_MAX_PACKET_SIZE_OVERFLOW;
|
||||
@ -747,8 +747,8 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
|
||||
if (stream_empty(s)) {
|
||||
struct peer *from = NULL;
|
||||
|
||||
if (binfo)
|
||||
from = binfo->peer;
|
||||
if (path)
|
||||
from = path->peer;
|
||||
|
||||
/* 1: Write the BGP message header - 16 bytes marker, 2
|
||||
* bytes length,
|
||||
@ -821,13 +821,13 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
|
||||
prd = (struct prefix_rd *)&rn->prn->p;
|
||||
|
||||
if (safi == SAFI_LABELED_UNICAST) {
|
||||
label = bgp_adv_label(rn, binfo, peer, afi,
|
||||
label = bgp_adv_label(rn, path, peer, afi,
|
||||
safi);
|
||||
label_pnt = &label;
|
||||
num_labels = 1;
|
||||
} else if (binfo && binfo->extra) {
|
||||
label_pnt = &binfo->extra->label[0];
|
||||
num_labels = binfo->extra->num_labels;
|
||||
} else if (path && path->extra) {
|
||||
label_pnt = &path->extra->label[0];
|
||||
num_labels = path->extra->num_labels;
|
||||
}
|
||||
|
||||
if (stream_empty(snlri))
|
||||
@ -1123,6 +1123,8 @@ void subgroup_default_update_packet(struct update_subgroup *subgrp,
|
||||
snprintf(tx_id_buf, sizeof(tx_id_buf),
|
||||
" with addpath ID %u",
|
||||
BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
|
||||
else
|
||||
tx_id_buf[0] = '\0';
|
||||
|
||||
zlog_debug("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s %s",
|
||||
(SUBGRP_UPDGRP(subgrp))->id, subgrp->id,
|
||||
|
833
bgpd/bgp_vty.c
833
bgpd/bgp_vty.c
File diff suppressed because it is too large
Load Diff
194
bgpd/bgp_zebra.c
194
bgpd/bgp_zebra.c
@ -925,41 +925,40 @@ bool bgp_zebra_nexthop_set(union sockunion *local, union sockunion *remote,
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct in6_addr *bgp_info_to_ipv6_nexthop(struct bgp_info *info,
|
||||
ifindex_t *ifindex)
|
||||
static struct in6_addr *
|
||||
bgp_path_info_to_ipv6_nexthop(struct bgp_path_info *path, ifindex_t *ifindex)
|
||||
{
|
||||
struct in6_addr *nexthop = NULL;
|
||||
|
||||
/* Only global address nexthop exists. */
|
||||
if (info->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
|
||||
nexthop = &info->attr->mp_nexthop_global;
|
||||
if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
|
||||
nexthop = &path->attr->mp_nexthop_global;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(nexthop))
|
||||
*ifindex = info->attr->nh_ifindex;
|
||||
|
||||
*ifindex = path->attr->nh_ifindex;
|
||||
}
|
||||
|
||||
/* If both global and link-local address present. */
|
||||
if (info->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
|
||||
if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
|
||||
/* Check if route-map is set to prefer global over link-local */
|
||||
if (info->attr->mp_nexthop_prefer_global) {
|
||||
nexthop = &info->attr->mp_nexthop_global;
|
||||
if (path->attr->mp_nexthop_prefer_global) {
|
||||
nexthop = &path->attr->mp_nexthop_global;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(nexthop))
|
||||
*ifindex = info->attr->nh_ifindex;
|
||||
*ifindex = path->attr->nh_ifindex;
|
||||
} else {
|
||||
/* Workaround for Cisco's nexthop bug. */
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(
|
||||
&info->attr->mp_nexthop_global)
|
||||
&& info->peer->su_remote->sa.sa_family
|
||||
&path->attr->mp_nexthop_global)
|
||||
&& path->peer->su_remote->sa.sa_family
|
||||
== AF_INET6) {
|
||||
nexthop =
|
||||
&info->peer->su_remote->sin6.sin6_addr;
|
||||
&path->peer->su_remote->sin6.sin6_addr;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(nexthop))
|
||||
*ifindex = info->peer->nexthop.ifp
|
||||
*ifindex = path->peer->nexthop.ifp
|
||||
->ifindex;
|
||||
} else {
|
||||
nexthop = &info->attr->mp_nexthop_local;
|
||||
nexthop = &path->attr->mp_nexthop_local;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(nexthop))
|
||||
*ifindex = info->attr->nh_lla_ifindex;
|
||||
*ifindex = path->attr->nh_lla_ifindex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -968,12 +967,12 @@ static struct in6_addr *bgp_info_to_ipv6_nexthop(struct bgp_info *info,
|
||||
}
|
||||
|
||||
static int bgp_table_map_apply(struct route_map *map, struct prefix *p,
|
||||
struct bgp_info *info)
|
||||
struct bgp_path_info *path)
|
||||
{
|
||||
route_map_result_t ret;
|
||||
|
||||
ret = route_map_apply(map, p, RMAP_BGP, info);
|
||||
bgp_attr_flush(info->attr);
|
||||
ret = route_map_apply(map, p, RMAP_BGP, path);
|
||||
bgp_attr_flush(path->attr);
|
||||
|
||||
if (ret != RMAP_DENYMATCH)
|
||||
return 1;
|
||||
@ -986,7 +985,7 @@ static int bgp_table_map_apply(struct route_map *map, struct prefix *p,
|
||||
inet_ntop(AF_INET, &p->u.prefix4, buf[0],
|
||||
sizeof(buf[0])),
|
||||
p->prefixlen,
|
||||
inet_ntop(AF_INET, &info->attr->nexthop, buf[1],
|
||||
inet_ntop(AF_INET, &path->attr->nexthop, buf[1],
|
||||
sizeof(buf[1])));
|
||||
}
|
||||
if (p->family == AF_INET6) {
|
||||
@ -994,7 +993,7 @@ static int bgp_table_map_apply(struct route_map *map, struct prefix *p,
|
||||
ifindex_t ifindex;
|
||||
struct in6_addr *nexthop;
|
||||
|
||||
nexthop = bgp_info_to_ipv6_nexthop(info, &ifindex);
|
||||
nexthop = bgp_path_info_to_ipv6_nexthop(path, &ifindex);
|
||||
zlog_debug(
|
||||
"Zebra rmap deny: IPv6 route %s/%d nexthop %s",
|
||||
inet_ntop(AF_INET6, &p->u.prefix6, buf[0],
|
||||
@ -1121,17 +1120,15 @@ static int update_ipv4nh_for_route_install(int nh_othervrf,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int update_ipv6nh_for_route_install(int nh_othervrf,
|
||||
struct in6_addr *nexthop,
|
||||
ifindex_t ifindex,
|
||||
struct bgp_info *ri,
|
||||
struct bgp_info *best_ri,
|
||||
bool is_evpn,
|
||||
struct zapi_nexthop *api_nh)
|
||||
static int
|
||||
update_ipv6nh_for_route_install(int nh_othervrf, struct in6_addr *nexthop,
|
||||
ifindex_t ifindex, struct bgp_path_info *pi,
|
||||
struct bgp_path_info *best_pi, bool is_evpn,
|
||||
struct zapi_nexthop *api_nh)
|
||||
{
|
||||
struct attr *attr;
|
||||
|
||||
attr = ri->attr;
|
||||
attr = pi->attr;
|
||||
|
||||
if (is_evpn)
|
||||
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
@ -1150,22 +1147,22 @@ static int update_ipv6nh_for_route_install(int nh_othervrf,
|
||||
}
|
||||
} else {
|
||||
if (IN6_IS_ADDR_LINKLOCAL(nexthop)) {
|
||||
if (ri == best_ri &&
|
||||
attr->mp_nexthop_len
|
||||
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
|
||||
if (ri->peer->nexthop.ifp)
|
||||
ifindex = ri->peer->nexthop.ifp
|
||||
->ifindex;
|
||||
if (pi == best_pi
|
||||
&& attr->mp_nexthop_len
|
||||
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
|
||||
if (pi->peer->nexthop.ifp)
|
||||
ifindex =
|
||||
pi->peer->nexthop.ifp->ifindex;
|
||||
if (!ifindex) {
|
||||
if (ri->peer->conf_if)
|
||||
ifindex = ri->peer->ifp->ifindex;
|
||||
else if (ri->peer->ifname)
|
||||
if (pi->peer->conf_if)
|
||||
ifindex = pi->peer->ifp->ifindex;
|
||||
else if (pi->peer->ifname)
|
||||
ifindex = ifname2ifindex(
|
||||
ri->peer->ifname,
|
||||
ri->peer->bgp->vrf_id);
|
||||
else if (ri->peer->nexthop.ifp)
|
||||
ifindex = ri->peer->nexthop.ifp
|
||||
->ifindex;
|
||||
pi->peer->ifname,
|
||||
pi->peer->bgp->vrf_id);
|
||||
else if (pi->peer->nexthop.ifp)
|
||||
ifindex =
|
||||
pi->peer->nexthop.ifp->ifindex;
|
||||
}
|
||||
|
||||
if (ifindex == 0)
|
||||
@ -1183,7 +1180,7 @@ static int update_ipv6nh_for_route_install(int nh_othervrf,
|
||||
}
|
||||
|
||||
void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
struct bgp_info *info, struct bgp *bgp, afi_t afi,
|
||||
struct bgp_path_info *info, struct bgp *bgp, afi_t afi,
|
||||
safi_t safi)
|
||||
{
|
||||
struct zapi_route api;
|
||||
@ -1193,11 +1190,11 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
int has_valid_label = 0;
|
||||
uint8_t distance;
|
||||
struct peer *peer;
|
||||
struct bgp_info *mpinfo;
|
||||
struct bgp_path_info *mpinfo;
|
||||
uint32_t metric;
|
||||
struct attr local_attr;
|
||||
struct bgp_info local_info;
|
||||
struct bgp_info *mpinfo_cp = &local_info;
|
||||
struct bgp_path_info local_info;
|
||||
struct bgp_path_info *mpinfo_cp = &local_info;
|
||||
route_tag_t tag;
|
||||
mpls_label_t label;
|
||||
int nh_othervrf = 0;
|
||||
@ -1242,7 +1239,8 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
|
||||
/* Obtain peer from parent */
|
||||
if (info->extra && info->extra->parent)
|
||||
peer = ((struct bgp_info *)(info->extra->parent))->peer;
|
||||
peer = ((struct bgp_path_info *)(info->extra->parent))
|
||||
->peer;
|
||||
}
|
||||
|
||||
tag = info->attr->tag;
|
||||
@ -1266,7 +1264,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
|
||||
/* Metric is currently based on the best-path only */
|
||||
metric = info->attr->med;
|
||||
for (mpinfo = info; mpinfo; mpinfo = bgp_info_mpath_next(mpinfo)) {
|
||||
for (mpinfo = info; mpinfo; mpinfo = bgp_path_info_mpath_next(mpinfo)) {
|
||||
if (valid_nh_count >= multipath_num)
|
||||
break;
|
||||
|
||||
@ -1356,8 +1354,8 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
tag = mpinfo_cp->attr->tag;
|
||||
}
|
||||
}
|
||||
nexthop = bgp_info_to_ipv6_nexthop(mpinfo_cp,
|
||||
&ifindex);
|
||||
nexthop = bgp_path_info_to_ipv6_nexthop(mpinfo_cp,
|
||||
&ifindex);
|
||||
nh_updated = update_ipv6nh_for_route_install(
|
||||
nh_othervrf, nexthop, ifindex,
|
||||
mpinfo, info, is_evpn, api_nh);
|
||||
@ -1466,7 +1464,7 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
|
||||
{
|
||||
struct bgp_node *rn;
|
||||
struct bgp_table *table;
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *pi;
|
||||
|
||||
/* Don't try to install if we're not connected to Zebra or Zebra doesn't
|
||||
* know of this instance.
|
||||
@ -1479,18 +1477,18 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
|
||||
return;
|
||||
|
||||
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
|
||||
for (ri = rn->info; ri; ri = ri->next)
|
||||
if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED) &&
|
||||
for (pi = rn->info; pi; pi = pi->next)
|
||||
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) &&
|
||||
|
||||
(ri->type == ZEBRA_ROUTE_BGP
|
||||
&& (ri->sub_type == BGP_ROUTE_NORMAL
|
||||
|| ri->sub_type == BGP_ROUTE_IMPORTED)))
|
||||
(pi->type == ZEBRA_ROUTE_BGP
|
||||
&& (pi->sub_type == BGP_ROUTE_NORMAL
|
||||
|| pi->sub_type == BGP_ROUTE_IMPORTED)))
|
||||
|
||||
bgp_zebra_announce(rn, &rn->p, ri, bgp, afi,
|
||||
bgp_zebra_announce(rn, &rn->p, pi, bgp, afi,
|
||||
safi);
|
||||
}
|
||||
|
||||
void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info,
|
||||
void bgp_zebra_withdraw(struct prefix *p, struct bgp_path_info *info,
|
||||
struct bgp *bgp, safi_t safi)
|
||||
{
|
||||
struct zapi_route api;
|
||||
@ -1662,7 +1660,8 @@ int bgp_redistribute_resend(struct bgp *bgp, afi_t afi, int type,
|
||||
}
|
||||
|
||||
/* Redistribute with route-map specification. */
|
||||
int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name)
|
||||
int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name,
|
||||
struct route_map *route_map)
|
||||
{
|
||||
if (red->rmap.name && (strcmp(red->rmap.name, name) == 0))
|
||||
return 0;
|
||||
@ -1670,7 +1669,7 @@ int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name)
|
||||
if (red->rmap.name)
|
||||
XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name);
|
||||
red->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name);
|
||||
red->rmap.map = route_map_lookup_by_name(name);
|
||||
red->rmap.map = route_map;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1680,7 +1679,7 @@ int bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red,
|
||||
afi_t afi, int type, uint32_t metric)
|
||||
{
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *pi;
|
||||
|
||||
if (red->redist_metric_flag && red->redist_metric == metric)
|
||||
return 0;
|
||||
@ -1690,21 +1689,21 @@ int bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red,
|
||||
|
||||
for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn;
|
||||
rn = bgp_route_next(rn)) {
|
||||
for (ri = rn->info; ri; ri = ri->next) {
|
||||
if (ri->sub_type == BGP_ROUTE_REDISTRIBUTE
|
||||
&& ri->type == type
|
||||
&& ri->instance == red->instance) {
|
||||
for (pi = rn->info; pi; pi = pi->next) {
|
||||
if (pi->sub_type == BGP_ROUTE_REDISTRIBUTE
|
||||
&& pi->type == type
|
||||
&& pi->instance == red->instance) {
|
||||
struct attr *old_attr;
|
||||
struct attr new_attr;
|
||||
|
||||
bgp_attr_dup(&new_attr, ri->attr);
|
||||
bgp_attr_dup(&new_attr, pi->attr);
|
||||
new_attr.med = red->redist_metric;
|
||||
old_attr = ri->attr;
|
||||
ri->attr = bgp_attr_intern(&new_attr);
|
||||
old_attr = pi->attr;
|
||||
pi->attr = bgp_attr_intern(&new_attr);
|
||||
bgp_attr_unintern(&old_attr);
|
||||
|
||||
bgp_info_set_flag(rn, ri,
|
||||
BGP_INFO_ATTR_CHANGED);
|
||||
bgp_path_info_set_flag(rn, pi,
|
||||
BGP_PATH_ATTR_CHANGED);
|
||||
bgp_process(bgp, rn, afi, SAFI_UNICAST);
|
||||
}
|
||||
}
|
||||
@ -1933,6 +1932,29 @@ int bgp_zebra_advertise_gw_macip(struct bgp *bgp, int advertise, vni_t vni)
|
||||
return zclient_send_message(zclient);
|
||||
}
|
||||
|
||||
int bgp_zebra_vxlan_flood_control(struct bgp *bgp,
|
||||
enum vxlan_flood_control flood_ctrl)
|
||||
{
|
||||
struct stream *s;
|
||||
|
||||
/* Check socket. */
|
||||
if (!zclient || zclient->sock < 0)
|
||||
return 0;
|
||||
|
||||
/* Don't try to register if Zebra doesn't know of this instance. */
|
||||
if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
|
||||
return 0;
|
||||
|
||||
s = zclient->obuf;
|
||||
stream_reset(s);
|
||||
|
||||
zclient_create_header(s, ZEBRA_VXLAN_FLOOD_CONTROL, bgp->vrf_id);
|
||||
stream_putc(s, flood_ctrl);
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
|
||||
return zclient_send_message(zclient);
|
||||
}
|
||||
|
||||
int bgp_zebra_advertise_all_vni(struct bgp *bgp, int advertise)
|
||||
{
|
||||
struct stream *s;
|
||||
@ -1950,6 +1972,10 @@ int bgp_zebra_advertise_all_vni(struct bgp *bgp, int advertise)
|
||||
|
||||
zclient_create_header(s, ZEBRA_ADVERTISE_ALL_VNI, bgp->vrf_id);
|
||||
stream_putc(s, advertise);
|
||||
/* Also inform current BUM handling setting. This is really
|
||||
* relevant only when 'advertise' is set.
|
||||
*/
|
||||
stream_putc(s, bgp->vxlan_flood_ctrl);
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
|
||||
return zclient_send_message(zclient);
|
||||
@ -2081,20 +2107,20 @@ static int ipset_entry_notify_owner(int command, struct zclient *zclient,
|
||||
break;
|
||||
case ZAPI_IPSET_ENTRY_INSTALLED:
|
||||
{
|
||||
struct bgp_info *bgp_info;
|
||||
struct bgp_info_extra *extra;
|
||||
struct bgp_path_info *path;
|
||||
struct bgp_path_info_extra *extra;
|
||||
|
||||
bgp_pbime->installed = true;
|
||||
bgp_pbime->install_in_progress = false;
|
||||
if (BGP_DEBUG(zebra, ZEBRA))
|
||||
zlog_debug("%s: Received IPSET_ENTRY_INSTALLED",
|
||||
__PRETTY_FUNCTION__);
|
||||
/* link bgp_info to bpme */
|
||||
bgp_info = (struct bgp_info *)bgp_pbime->bgp_info;
|
||||
extra = bgp_info_extra_get(bgp_info);
|
||||
if (extra->bgp_fs_pbr == NULL)
|
||||
extra->bgp_fs_pbr = list_new();
|
||||
listnode_add(extra->bgp_fs_pbr, bgp_pbime);
|
||||
bgp_pbime->installed = true;
|
||||
bgp_pbime->install_in_progress = false;
|
||||
if (BGP_DEBUG(zebra, ZEBRA))
|
||||
zlog_debug("%s: Received IPSET_ENTRY_INSTALLED",
|
||||
__PRETTY_FUNCTION__);
|
||||
/* link bgp_path_info to bpme */
|
||||
path = (struct bgp_path_info *)bgp_pbime->path;
|
||||
extra = bgp_path_info_extra_get(path);
|
||||
if (extra->bgp_fs_pbr == NULL)
|
||||
extra->bgp_fs_pbr = list_new();
|
||||
listnode_add(extra->bgp_fs_pbr, bgp_pbime);
|
||||
}
|
||||
break;
|
||||
case ZAPI_IPSET_ENTRY_FAIL_REMOVE:
|
||||
|
@ -36,11 +36,12 @@ extern void bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t,
|
||||
safi_t);
|
||||
extern void bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t,
|
||||
safi_t);
|
||||
extern void bgp_zebra_announce(struct bgp_node *, struct prefix *,
|
||||
struct bgp_info *, struct bgp *, afi_t, safi_t);
|
||||
extern void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
struct bgp_path_info *path, struct bgp *bgp,
|
||||
afi_t afi, safi_t safi);
|
||||
extern void bgp_zebra_announce_table(struct bgp *, afi_t, safi_t);
|
||||
extern void bgp_zebra_withdraw(struct prefix *, struct bgp_info *,
|
||||
struct bgp *, safi_t);
|
||||
extern void bgp_zebra_withdraw(struct prefix *p, struct bgp_path_info *path,
|
||||
struct bgp *bgp, safi_t safi);
|
||||
|
||||
extern void bgp_zebra_initiate_radv(struct bgp *bgp, struct peer *peer);
|
||||
extern void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer);
|
||||
@ -55,7 +56,8 @@ extern struct bgp_redist *bgp_redist_add(struct bgp *, afi_t, uint8_t,
|
||||
extern int bgp_redistribute_set(struct bgp *, afi_t, int, unsigned short,
|
||||
bool changed);
|
||||
extern int bgp_redistribute_resend(struct bgp *, afi_t, int, unsigned short);
|
||||
extern int bgp_redistribute_rmap_set(struct bgp_redist *, const char *);
|
||||
extern int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name,
|
||||
struct route_map *route_map);
|
||||
extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, afi_t,
|
||||
int, uint32_t);
|
||||
extern int bgp_redistribute_unset(struct bgp *, afi_t, int, unsigned short);
|
||||
@ -71,6 +73,8 @@ extern int bgp_zebra_advertise_subnet(struct bgp *bgp, int advertise,
|
||||
vni_t vni);
|
||||
extern int bgp_zebra_advertise_gw_macip(struct bgp *, int, vni_t);
|
||||
extern int bgp_zebra_advertise_all_vni(struct bgp *, int);
|
||||
extern int bgp_zebra_vxlan_flood_control(struct bgp *bgp,
|
||||
enum vxlan_flood_control flood_ctrl);
|
||||
|
||||
extern int bgp_zebra_num_connects(void);
|
||||
|
||||
|
71
bgpd/bgpd.c
71
bgpd/bgpd.c
@ -769,7 +769,7 @@ static unsigned int peer_hash_key_make(void *p)
|
||||
return sockunion_hash(&peer->su);
|
||||
}
|
||||
|
||||
static int peer_hash_same(const void *p1, const void *p2)
|
||||
static bool peer_hash_same(const void *p1, const void *p2)
|
||||
{
|
||||
const struct peer *peer1 = p1;
|
||||
const struct peer *peer2 = p2;
|
||||
@ -1422,7 +1422,15 @@ void bgp_recalculate_all_bestpaths(struct bgp *bgp)
|
||||
}
|
||||
}
|
||||
|
||||
/* Create new BGP peer. */
|
||||
/*
|
||||
* Create new BGP peer.
|
||||
*
|
||||
* conf_if and su are mutually exclusive if configuring from the cli.
|
||||
* If we are handing a doppelganger, then we *must* pass in both
|
||||
* the original peer's su and conf_if, so that we can appropriately
|
||||
* track the bgp->peerhash( ie we don't want to remove the current
|
||||
* one from the config ).
|
||||
*/
|
||||
struct peer *peer_create(union sockunion *su, const char *conf_if,
|
||||
struct bgp *bgp, as_t local_as, as_t remote_as,
|
||||
int as_type, afi_t afi, safi_t safi,
|
||||
@ -1435,7 +1443,10 @@ struct peer *peer_create(union sockunion *su, const char *conf_if,
|
||||
peer = peer_new(bgp);
|
||||
if (conf_if) {
|
||||
peer->conf_if = XSTRDUP(MTYPE_PEER_CONF_IF, conf_if);
|
||||
bgp_peer_conf_if_to_su_update(peer);
|
||||
if (su)
|
||||
peer->su = *su;
|
||||
else
|
||||
bgp_peer_conf_if_to_su_update(peer);
|
||||
if (peer->host)
|
||||
XFREE(MTYPE_BGP_PEER_HOST, peer->host);
|
||||
peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, conf_if);
|
||||
@ -4485,7 +4496,7 @@ int peer_update_source_unset(struct peer *peer)
|
||||
}
|
||||
|
||||
int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
|
||||
const char *rmap)
|
||||
const char *rmap, struct route_map *route_map)
|
||||
{
|
||||
struct peer *member;
|
||||
struct listnode *node, *nnode;
|
||||
@ -4501,8 +4512,7 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
|
||||
|
||||
peer->default_rmap[afi][safi].name =
|
||||
XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
|
||||
peer->default_rmap[afi][safi].map =
|
||||
route_map_lookup_by_name(rmap);
|
||||
peer->default_rmap[afi][safi].map = route_map;
|
||||
}
|
||||
} else if (!rmap) {
|
||||
if (peer->default_rmap[afi][safi].name)
|
||||
@ -4546,8 +4556,7 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
|
||||
|
||||
member->default_rmap[afi][safi].name =
|
||||
XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
|
||||
member->default_rmap[afi][safi].map =
|
||||
route_map_lookup_by_name(rmap);
|
||||
member->default_rmap[afi][safi].map = route_map;
|
||||
}
|
||||
|
||||
/* Update peer route announcements. */
|
||||
@ -6012,7 +6021,7 @@ static void peer_aslist_del(const char *aslist_name)
|
||||
|
||||
|
||||
int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
|
||||
const char *name)
|
||||
const char *name, struct route_map *route_map)
|
||||
{
|
||||
struct peer *member;
|
||||
struct bgp_filter *filter;
|
||||
@ -6026,7 +6035,7 @@ int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
|
||||
if (filter->map[direct].name)
|
||||
XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
|
||||
filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
|
||||
filter->map[direct].map = route_map_lookup_by_name(name);
|
||||
filter->map[direct].map = route_map;
|
||||
|
||||
/* Check if handling a regular peer. */
|
||||
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
|
||||
@ -6055,7 +6064,7 @@ int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
|
||||
if (filter->map[direct].name)
|
||||
XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
|
||||
filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
|
||||
filter->map[direct].map = route_map_lookup_by_name(name);
|
||||
filter->map[direct].map = route_map;
|
||||
|
||||
/* Process peer route updates. */
|
||||
peer_on_policy_change(member, afi, safi,
|
||||
@ -6130,7 +6139,7 @@ int peer_route_map_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
|
||||
|
||||
/* Set unsuppress-map to the peer. */
|
||||
int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
|
||||
const char *name)
|
||||
const char *name, struct route_map *route_map)
|
||||
{
|
||||
struct peer *member;
|
||||
struct bgp_filter *filter;
|
||||
@ -6141,7 +6150,7 @@ int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
|
||||
if (filter->usmap.name)
|
||||
XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
|
||||
filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
|
||||
filter->usmap.map = route_map_lookup_by_name(name);
|
||||
filter->usmap.map = route_map;
|
||||
|
||||
/* Check if handling a regular peer. */
|
||||
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
|
||||
@ -6169,7 +6178,7 @@ int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
|
||||
if (filter->usmap.name)
|
||||
XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
|
||||
filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
|
||||
filter->usmap.map = route_map_lookup_by_name(name);
|
||||
filter->usmap.map = route_map;
|
||||
|
||||
/* Process peer route updates. */
|
||||
peer_on_policy_change(member, afi, safi, 1);
|
||||
@ -6297,9 +6306,6 @@ int peer_maximum_prefix_set(struct peer *peer, afi_t afi, safi_t safi,
|
||||
|
||||
int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi)
|
||||
{
|
||||
struct peer *member;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
/* Inherit configuration from peer-group if peer is member. */
|
||||
if (peer_group_active(peer)) {
|
||||
peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_MAX_PREFIX);
|
||||
@ -6323,19 +6329,26 @@ int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi)
|
||||
* Remove flags and configuration from all peer-group members, unless
|
||||
* they are explicitely overriding peer-group configuration.
|
||||
*/
|
||||
for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
|
||||
/* Skip peers with overridden configuration. */
|
||||
if (CHECK_FLAG(member->af_flags_override[afi][safi],
|
||||
PEER_FLAG_MAX_PREFIX))
|
||||
continue;
|
||||
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
|
||||
struct peer *member;
|
||||
struct listnode *node;
|
||||
|
||||
/* Remove flag and configuration on peer-group member. */
|
||||
UNSET_FLAG(member->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
|
||||
UNSET_FLAG(member->af_flags[afi][safi],
|
||||
PEER_FLAG_MAX_PREFIX_WARNING);
|
||||
member->pmax[afi][safi] = 0;
|
||||
member->pmax_threshold[afi][safi] = 0;
|
||||
member->pmax_restart[afi][safi] = 0;
|
||||
for (ALL_LIST_ELEMENTS_RO(peer->group->peer, node, member)) {
|
||||
/* Skip peers with overridden configuration. */
|
||||
if (CHECK_FLAG(member->af_flags_override[afi][safi],
|
||||
PEER_FLAG_MAX_PREFIX))
|
||||
continue;
|
||||
|
||||
/* Remove flag and configuration on peer-group member.
|
||||
*/
|
||||
UNSET_FLAG(member->af_flags[afi][safi],
|
||||
PEER_FLAG_MAX_PREFIX);
|
||||
UNSET_FLAG(member->af_flags[afi][safi],
|
||||
PEER_FLAG_MAX_PREFIX_WARNING);
|
||||
member->pmax[afi][safi] = 0;
|
||||
member->pmax_threshold[afi][safi] = 0;
|
||||
member->pmax_restart[afi][safi] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
17
bgpd/bgpd.h
17
bgpd/bgpd.h
@ -485,6 +485,11 @@ struct bgp {
|
||||
/* EVPN - use RFC 8365 to auto-derive RT */
|
||||
int advertise_autort_rfc8365;
|
||||
|
||||
/*
|
||||
* Flooding mechanism for BUM packets for VxLAN-EVPN.
|
||||
*/
|
||||
enum vxlan_flood_control vxlan_flood_ctrl;
|
||||
|
||||
/* Hash table of Import RTs to EVIs */
|
||||
struct hash *import_rt_hash;
|
||||
|
||||
@ -1605,8 +1610,9 @@ extern int peer_update_source_if_set(struct peer *, const char *);
|
||||
extern int peer_update_source_addr_set(struct peer *, const union sockunion *);
|
||||
extern int peer_update_source_unset(struct peer *);
|
||||
|
||||
extern int peer_default_originate_set(struct peer *, afi_t, safi_t,
|
||||
const char *);
|
||||
extern int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
|
||||
const char *rmap,
|
||||
struct route_map *route_map);
|
||||
extern int peer_default_originate_unset(struct peer *, afi_t, safi_t);
|
||||
|
||||
extern int peer_port_set(struct peer *, uint16_t);
|
||||
@ -1644,10 +1650,13 @@ extern int peer_prefix_list_unset(struct peer *, afi_t, safi_t, int);
|
||||
extern int peer_aslist_set(struct peer *, afi_t, safi_t, int, const char *);
|
||||
extern int peer_aslist_unset(struct peer *, afi_t, safi_t, int);
|
||||
|
||||
extern int peer_route_map_set(struct peer *, afi_t, safi_t, int, const char *);
|
||||
extern int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int,
|
||||
const char *name, struct route_map *route_map);
|
||||
extern int peer_route_map_unset(struct peer *, afi_t, safi_t, int);
|
||||
|
||||
extern int peer_unsuppress_map_set(struct peer *, afi_t, safi_t, const char *);
|
||||
extern int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
|
||||
const char *name,
|
||||
struct route_map *route_map);
|
||||
|
||||
extern int peer_password_set(struct peer *, const char *);
|
||||
extern int peer_password_unset(struct peer *);
|
||||
|
@ -1601,8 +1601,10 @@ DEFUN (vnc_nve_group_export_no_prefixlist,
|
||||
idx += 2; /* skip afi and keyword */
|
||||
|
||||
if (is_bgp) {
|
||||
if (idx == argc || strmatch(argv[idx]->arg,
|
||||
rfg->plist_export_bgp_name[afi])) {
|
||||
if (idx == argc
|
||||
|| (rfg->plist_export_bgp_name[afi]
|
||||
&& strmatch(argv[idx]->arg,
|
||||
rfg->plist_export_bgp_name[afi]))) {
|
||||
if (rfg->plist_export_bgp_name[afi])
|
||||
free(rfg->plist_export_bgp_name[afi]);
|
||||
rfg->plist_export_bgp_name[afi] = NULL;
|
||||
@ -1612,8 +1614,9 @@ DEFUN (vnc_nve_group_export_no_prefixlist,
|
||||
}
|
||||
} else {
|
||||
if (idx == argc
|
||||
|| strmatch(argv[idx]->arg,
|
||||
rfg->plist_export_zebra_name[afi])) {
|
||||
|| (rfg->plist_export_zebra_name[afi]
|
||||
&& strmatch(argv[idx]->arg,
|
||||
rfg->plist_export_zebra_name[afi]))) {
|
||||
if (rfg->plist_export_zebra_name[afi])
|
||||
free(rfg->plist_export_zebra_name[afi]);
|
||||
rfg->plist_export_zebra_name[afi] = NULL;
|
||||
@ -1732,8 +1735,10 @@ DEFUN (vnc_nve_group_export_no_routemap,
|
||||
}
|
||||
|
||||
if (is_bgp) {
|
||||
if (idx == argc || strmatch(argv[idx]->arg,
|
||||
rfg->routemap_export_bgp_name)) {
|
||||
if (idx == argc
|
||||
|| (rfg->routemap_export_bgp_name
|
||||
&& strmatch(argv[idx]->arg,
|
||||
rfg->routemap_export_bgp_name))) {
|
||||
if (rfg->routemap_export_bgp_name)
|
||||
free(rfg->routemap_export_bgp_name);
|
||||
rfg->routemap_export_bgp_name = NULL;
|
||||
@ -1743,8 +1748,10 @@ DEFUN (vnc_nve_group_export_no_routemap,
|
||||
vnc_direct_bgp_reexport_group_afi(bgp, rfg, AFI_IP6);
|
||||
}
|
||||
} else {
|
||||
if (idx == argc || strmatch(argv[idx]->arg,
|
||||
rfg->routemap_export_zebra_name)) {
|
||||
if (idx == argc
|
||||
|| (rfg->routemap_export_zebra_name
|
||||
&& strmatch(argv[idx]->arg,
|
||||
rfg->routemap_export_zebra_name))) {
|
||||
if (rfg->routemap_export_zebra_name)
|
||||
free(rfg->routemap_export_zebra_name);
|
||||
rfg->routemap_export_zebra_name = NULL;
|
||||
@ -3468,7 +3475,7 @@ DEFUN (vnc_l2_group_lni,
|
||||
|
||||
DEFUN (vnc_l2_group_labels,
|
||||
vnc_l2_group_labels_cmd,
|
||||
"labels LABELLIST...",
|
||||
"labels (0-1048575)...",
|
||||
"Specify label values associated with group\n"
|
||||
"Space separated list of label values <0-1048575>\n")
|
||||
{
|
||||
@ -3502,7 +3509,7 @@ DEFUN (vnc_l2_group_labels,
|
||||
|
||||
DEFUN (vnc_l2_group_no_labels,
|
||||
vnc_l2_group_no_labels_cmd,
|
||||
"no labels LABELLIST...",
|
||||
"no labels (0-1048575)...",
|
||||
NO_STR
|
||||
"Specify label values associated with L2 group\n"
|
||||
"Space separated list of label values <0-1048575>\n")
|
||||
|
@ -361,7 +361,7 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
|
||||
{
|
||||
afi_t afi; /* of the VN address */
|
||||
struct bgp_node *bn;
|
||||
struct bgp_info *bi;
|
||||
struct bgp_path_info *bpi;
|
||||
char buf[PREFIX_STRLEN];
|
||||
char buf2[RD_ADDRSTRLEN];
|
||||
struct prefix_rd prd0;
|
||||
@ -384,21 +384,22 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
|
||||
__func__, peer, buf, prefix_rd2str(prd, buf2, sizeof(buf2)),
|
||||
afi, safi, bn, (bn ? bn->info : NULL));
|
||||
|
||||
for (bi = (bn ? bn->info : NULL); bi; bi = bi->next) {
|
||||
for (bpi = (bn ? bn->info : NULL); bpi; bpi = bpi->next) {
|
||||
|
||||
vnc_zlog_debug_verbose(
|
||||
"%s: trying bi=%p, bi->peer=%p, bi->type=%d, bi->sub_type=%d, bi->extra->vnc.export.rfapi_handle=%p, local_pref=%u",
|
||||
__func__, bi, bi->peer, bi->type, bi->sub_type,
|
||||
(bi->extra ? bi->extra->vnc.export.rfapi_handle : NULL),
|
||||
((bi->attr
|
||||
&& CHECK_FLAG(bi->attr->flag,
|
||||
"%s: trying bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p, local_pref=%u",
|
||||
__func__, bpi, bpi->peer, bpi->type, bpi->sub_type,
|
||||
(bpi->extra ? bpi->extra->vnc.export.rfapi_handle
|
||||
: NULL),
|
||||
((bpi->attr
|
||||
&& CHECK_FLAG(bpi->attr->flag,
|
||||
ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))
|
||||
? bi->attr->local_pref
|
||||
? bpi->attr->local_pref
|
||||
: 0));
|
||||
|
||||
if (bi->peer == peer && bi->type == type
|
||||
&& bi->sub_type == sub_type && bi->extra
|
||||
&& bi->extra->vnc.export.rfapi_handle == (void *)rfd) {
|
||||
if (bpi->peer == peer && bpi->type == type
|
||||
&& bpi->sub_type == sub_type && bpi->extra
|
||||
&& bpi->extra->vnc.export.rfapi_handle == (void *)rfd) {
|
||||
|
||||
vnc_zlog_debug_verbose("%s: matched it", __func__);
|
||||
|
||||
@ -412,8 +413,8 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
|
||||
* route. Leave the route itself in place.
|
||||
* TBD add return code reporting of success/failure
|
||||
*/
|
||||
if (!bi || !bi->extra
|
||||
|| !bi->extra->vnc.export.local_nexthops) {
|
||||
if (!bpi || !bpi->extra
|
||||
|| !bpi->extra->vnc.export.local_nexthops) {
|
||||
/*
|
||||
* no local nexthops
|
||||
*/
|
||||
@ -429,7 +430,7 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
|
||||
struct listnode *node;
|
||||
struct rfapi_nexthop *pLnh = NULL;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(bi->extra->vnc.export.local_nexthops,
|
||||
for (ALL_LIST_ELEMENTS_RO(bpi->extra->vnc.export.local_nexthops,
|
||||
node, pLnh)) {
|
||||
|
||||
if (prefix_same(&pLnh->addr, &lnh->addr)) {
|
||||
@ -438,7 +439,7 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
|
||||
}
|
||||
|
||||
if (pLnh) {
|
||||
listnode_delete(bi->extra->vnc.export.local_nexthops,
|
||||
listnode_delete(bpi->extra->vnc.export.local_nexthops,
|
||||
pLnh);
|
||||
|
||||
/* silly rabbit, listnode_delete doesn't invoke
|
||||
@ -458,7 +459,7 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
|
||||
*/
|
||||
rfapiProcessWithdraw(peer, rfd, p, prd, NULL, afi, safi, type, kill);
|
||||
|
||||
if (bi) {
|
||||
if (bpi) {
|
||||
prefix2str(p, buf, sizeof(buf));
|
||||
vnc_zlog_debug_verbose(
|
||||
"%s: Found route (safi=%d) to delete at prefix %s",
|
||||
@ -474,7 +475,7 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
|
||||
table = (struct bgp_table *)(prn->info);
|
||||
|
||||
vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
|
||||
bgp, prd, table, p, bi);
|
||||
bgp, prd, table, p, bpi);
|
||||
}
|
||||
bgp_unlock_node(prn);
|
||||
}
|
||||
@ -482,13 +483,11 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
|
||||
/*
|
||||
* Delete local_nexthops list
|
||||
*/
|
||||
if (bi->extra && bi->extra->vnc.export.local_nexthops) {
|
||||
list_delete(
|
||||
&bi->extra->vnc.export.local_nexthops);
|
||||
}
|
||||
if (bpi->extra && bpi->extra->vnc.export.local_nexthops)
|
||||
list_delete(&bpi->extra->vnc.export.local_nexthops);
|
||||
|
||||
bgp_aggregate_decrement(bgp, p, bi, afi, safi);
|
||||
bgp_info_delete(bn, bi);
|
||||
bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
|
||||
bgp_path_info_delete(bn, bpi);
|
||||
bgp_process(bgp, bn, afi, safi);
|
||||
} else {
|
||||
vnc_zlog_debug_verbose(
|
||||
@ -575,8 +574,8 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
|
||||
int flags)
|
||||
{
|
||||
afi_t afi; /* of the VN address */
|
||||
struct bgp_info *new;
|
||||
struct bgp_info *bi;
|
||||
struct bgp_path_info *new;
|
||||
struct bgp_path_info *bpi;
|
||||
struct bgp_node *bn;
|
||||
|
||||
struct attr attr = {0};
|
||||
@ -946,29 +945,29 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
|
||||
* ecommunity: POINTS TO interned/refcounted dynamic 2-part AS attr
|
||||
* aspath: POINTS TO interned/refcounted hashed block
|
||||
*/
|
||||
for (bi = bn->info; bi; bi = bi->next) {
|
||||
for (bpi = bn->info; bpi; bpi = bpi->next) {
|
||||
/* probably only need to check
|
||||
* bi->extra->vnc.export.rfapi_handle */
|
||||
if (bi->peer == rfd->peer && bi->type == type
|
||||
&& bi->sub_type == sub_type && bi->extra
|
||||
&& bi->extra->vnc.export.rfapi_handle == (void *)rfd) {
|
||||
* bpi->extra->vnc.export.rfapi_handle */
|
||||
if (bpi->peer == rfd->peer && bpi->type == type
|
||||
&& bpi->sub_type == sub_type && bpi->extra
|
||||
&& bpi->extra->vnc.export.rfapi_handle == (void *)rfd) {
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bi) {
|
||||
if (bpi) {
|
||||
|
||||
/*
|
||||
* Adding new local_nexthop, which does not by itself change
|
||||
* what is advertised via BGP
|
||||
*/
|
||||
if (lnh) {
|
||||
if (!bi->extra->vnc.export.local_nexthops) {
|
||||
if (!bpi->extra->vnc.export.local_nexthops) {
|
||||
/* TBD make arrangements to free when needed */
|
||||
bi->extra->vnc.export.local_nexthops =
|
||||
bpi->extra->vnc.export.local_nexthops =
|
||||
list_new();
|
||||
bi->extra->vnc.export.local_nexthops->del =
|
||||
bpi->extra->vnc.export.local_nexthops->del =
|
||||
rfapi_nexthop_free;
|
||||
}
|
||||
|
||||
@ -979,8 +978,8 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
|
||||
struct rfapi_nexthop *pLnh = NULL;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(
|
||||
bi->extra->vnc.export.local_nexthops, node,
|
||||
pLnh)) {
|
||||
bpi->extra->vnc.export.local_nexthops,
|
||||
node, pLnh)) {
|
||||
|
||||
if (prefix_same(&pLnh->addr, &lnh->addr)) {
|
||||
break;
|
||||
@ -993,13 +992,13 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
|
||||
if (!pLnh) {
|
||||
pLnh = rfapi_nexthop_new(lnh);
|
||||
listnode_add(
|
||||
bi->extra->vnc.export.local_nexthops,
|
||||
bpi->extra->vnc.export.local_nexthops,
|
||||
pLnh);
|
||||
}
|
||||
}
|
||||
|
||||
if (attrhash_cmp(bi->attr, new_attr)
|
||||
&& !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) {
|
||||
if (attrhash_cmp(bpi->attr, new_attr)
|
||||
&& !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
|
||||
bgp_attr_unintern(&new_attr);
|
||||
bgp_unlock_node(bn);
|
||||
|
||||
@ -1010,7 +1009,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
|
||||
goto done;
|
||||
} else {
|
||||
/* The attribute is changed. */
|
||||
bgp_info_set_flag(bn, bi, BGP_INFO_ATTR_CHANGED);
|
||||
bgp_path_info_set_flag(bn, bpi, BGP_PATH_ATTR_CHANGED);
|
||||
|
||||
if (safi == SAFI_MPLS_VPN) {
|
||||
struct bgp_node *prn = NULL;
|
||||
@ -1022,19 +1021,19 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
|
||||
table = (struct bgp_table *)(prn->info);
|
||||
|
||||
vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
|
||||
bgp, prd, table, p, bi);
|
||||
bgp, prd, table, p, bpi);
|
||||
}
|
||||
bgp_unlock_node(prn);
|
||||
}
|
||||
|
||||
/* Rewrite BGP route information. */
|
||||
if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
|
||||
bgp_info_restore(bn, bi);
|
||||
if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
|
||||
bgp_path_info_restore(bn, bpi);
|
||||
else
|
||||
bgp_aggregate_decrement(bgp, p, bi, afi, safi);
|
||||
bgp_attr_unintern(&bi->attr);
|
||||
bi->attr = new_attr;
|
||||
bi->uptime = bgp_clock();
|
||||
bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
|
||||
bgp_attr_unintern(&bpi->attr);
|
||||
bpi->attr = new_attr;
|
||||
bpi->uptime = bgp_clock();
|
||||
|
||||
|
||||
if (safi == SAFI_MPLS_VPN) {
|
||||
@ -1047,13 +1046,13 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
|
||||
table = (struct bgp_table *)(prn->info);
|
||||
|
||||
vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
|
||||
bgp, prd, table, p, bi);
|
||||
bgp, prd, table, p, bpi);
|
||||
}
|
||||
bgp_unlock_node(prn);
|
||||
}
|
||||
|
||||
/* Process change. */
|
||||
bgp_aggregate_increment(bgp, p, bi, afi, safi);
|
||||
bgp_aggregate_increment(bgp, p, bpi, afi, safi);
|
||||
bgp_process(bgp, bn, afi, safi);
|
||||
bgp_unlock_node(bn);
|
||||
|
||||
@ -1066,16 +1065,16 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
|
||||
}
|
||||
|
||||
|
||||
new = bgp_info_new();
|
||||
new = bgp_path_info_new();
|
||||
new->type = type;
|
||||
new->sub_type = sub_type;
|
||||
new->peer = rfd->peer;
|
||||
SET_FLAG(new->flags, BGP_INFO_VALID);
|
||||
SET_FLAG(new->flags, BGP_PATH_VALID);
|
||||
new->attr = new_attr;
|
||||
new->uptime = bgp_clock();
|
||||
|
||||
/* save backref to rfapi handle */
|
||||
assert(bgp_info_extra_get(new));
|
||||
assert(bgp_path_info_extra_get(new));
|
||||
new->extra->vnc.export.rfapi_handle = (void *)rfd;
|
||||
encode_label(label_val, &new->extra->label[0]);
|
||||
|
||||
@ -1087,7 +1086,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
|
||||
}
|
||||
|
||||
bgp_aggregate_increment(bgp, p, new, afi, safi);
|
||||
bgp_info_add(bn, new);
|
||||
bgp_path_info_add(bn, new);
|
||||
|
||||
if (safi == SAFI_MPLS_VPN) {
|
||||
struct bgp_node *prn = NULL;
|
||||
@ -3690,7 +3689,7 @@ static void rfapi_print_exported(struct bgp *bgp)
|
||||
{
|
||||
struct bgp_node *rdn;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *bi;
|
||||
struct bgp_path_info *bpi;
|
||||
|
||||
if (!bgp)
|
||||
return;
|
||||
@ -3705,8 +3704,8 @@ static void rfapi_print_exported(struct bgp *bgp)
|
||||
if (!rn->info)
|
||||
continue;
|
||||
fprintf(stderr, "%s: rn=%p\n", __func__, rn);
|
||||
for (bi = rn->info; bi; bi = bi->next) {
|
||||
rfapiPrintBi((void *)2, bi); /* 2 => stderr */
|
||||
for (bpi = rn->info; bpi; bpi = bpi->next) {
|
||||
rfapiPrintBi((void *)2, bpi); /* 2 => stderr */
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3720,8 +3719,8 @@ static void rfapi_print_exported(struct bgp *bgp)
|
||||
if (!rn->info)
|
||||
continue;
|
||||
fprintf(stderr, "%s: rn=%p\n", __func__, rn);
|
||||
for (bi = rn->info; bi; bi = bi->next) {
|
||||
rfapiPrintBi((void *)2, bi); /* 2 => stderr */
|
||||
for (bpi = rn->info; bpi; bpi = bpi->next) {
|
||||
rfapiPrintBi((void *)2, bpi); /* 2 => stderr */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,14 +48,16 @@ extern void rfapiProcessWithdraw(struct peer *peer, void *rfd, struct prefix *p,
|
||||
|
||||
extern void rfapiProcessPeerDown(struct peer *peer);
|
||||
|
||||
extern void vnc_zebra_announce(struct prefix *p, struct bgp_info *new_select,
|
||||
extern void vnc_zebra_announce(struct prefix *p,
|
||||
struct bgp_path_info *new_select,
|
||||
struct bgp *bgp);
|
||||
|
||||
extern void vnc_zebra_withdraw(struct prefix *p, struct bgp_info *old_select);
|
||||
extern void vnc_zebra_withdraw(struct prefix *p,
|
||||
struct bgp_path_info *old_select);
|
||||
|
||||
|
||||
extern void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p,
|
||||
struct bgp_info *bi, safi_t safi);
|
||||
struct bgp_path_info *bpi, safi_t safi);
|
||||
|
||||
|
||||
extern void vnc_direct_bgp_vpn_enable(struct bgp *bgp, afi_t afi);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -31,7 +31,7 @@
|
||||
/*
|
||||
* These are per-rt-import-list
|
||||
*
|
||||
* routes are not segregated by RD - the RD is stored in bgp_info_extra
|
||||
* routes are not segregated by RD - the RD is stored in bgp_path_info_extra
|
||||
* and is needed to determine if two prefixes are the same.
|
||||
*/
|
||||
struct rfapi_import_table {
|
||||
@ -51,18 +51,18 @@ struct rfapi_import_table {
|
||||
int imported_count[AFI_MAX];
|
||||
};
|
||||
|
||||
#define RFAPI_LOCAL_BI(bi) \
|
||||
(((bi)->type == ZEBRA_ROUTE_BGP) && ((bi)->sub_type == BGP_ROUTE_RFP))
|
||||
#define RFAPI_LOCAL_BI(bpi) \
|
||||
(((bpi)->type == ZEBRA_ROUTE_BGP) && ((bpi)->sub_type == BGP_ROUTE_RFP))
|
||||
|
||||
#define RFAPI_DIRECT_IMPORT_BI(bi) \
|
||||
(((bi)->type == ZEBRA_ROUTE_BGP_DIRECT) \
|
||||
|| ((bi)->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))
|
||||
#define RFAPI_DIRECT_IMPORT_BI(bpi) \
|
||||
(((bpi)->type == ZEBRA_ROUTE_BGP_DIRECT) \
|
||||
|| ((bpi)->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))
|
||||
|
||||
#define RFAPI_UPDATE_ITABLE_COUNT(bi, itable, afi, cnt) \
|
||||
if (RFAPI_LOCAL_BI(bi)) { \
|
||||
#define RFAPI_UPDATE_ITABLE_COUNT(bpi, itable, afi, cnt) \
|
||||
if (RFAPI_LOCAL_BI(bpi)) { \
|
||||
(itable)->local_count[(afi)] += (cnt); \
|
||||
} else { \
|
||||
if (RFAPI_DIRECT_IMPORT_BI(bi)) \
|
||||
if (RFAPI_DIRECT_IMPORT_BI(bpi)) \
|
||||
(itable)->imported_count[(afi)] += (cnt); \
|
||||
else \
|
||||
(itable)->remote_count[(afi)] += (cnt); \
|
||||
@ -75,9 +75,9 @@ extern void rfapiDebugBacktrace(void);
|
||||
extern void rfapiCheckRouteCount(void);
|
||||
|
||||
/*
|
||||
* Print BI in an Import Table
|
||||
* Print BPI in an Import Table
|
||||
*/
|
||||
extern void rfapiPrintBi(void *stream, struct bgp_info *bi);
|
||||
extern void rfapiPrintBi(void *stream, struct bgp_path_info *bpi);
|
||||
|
||||
extern void rfapiShowImportTable(void *stream, const char *label,
|
||||
struct agg_table *rt, int isvpn);
|
||||
@ -94,7 +94,7 @@ extern void rfapiImportTableRefDelByIt(struct bgp *bgp,
|
||||
* Construct an rfapi nexthop list based on the routes attached to
|
||||
* the specified node.
|
||||
*
|
||||
* If there are any routes that do NOT have BGP_INFO_REMOVED set,
|
||||
* If there are any routes that do NOT have BGP_PATH_REMOVED set,
|
||||
* return those only. If there are ONLY routes with BGP_INFO_REMOVED,
|
||||
* then return those, and also include all the non-removed routes from the
|
||||
* next less-specific node (i.e., this node's parent) at the end.
|
||||
@ -128,7 +128,7 @@ extern int rfapiHasNonRemovedRoutes(struct agg_node *rn);
|
||||
|
||||
extern int rfapiProcessDeferredClose(struct thread *t);
|
||||
|
||||
extern int rfapiGetUnAddrOfVpnBi(struct bgp_info *bi, struct prefix *p);
|
||||
extern int rfapiGetUnAddrOfVpnBi(struct bgp_path_info *bpi, struct prefix *p);
|
||||
|
||||
extern void rfapiNexthop2Prefix(struct attr *attr, struct prefix *p);
|
||||
|
||||
@ -146,10 +146,10 @@ extern void rfapiBgpInfoFilteredImportVPN(
|
||||
struct prefix *p,
|
||||
struct prefix *aux_prefix, /* AFI_ETHER: optional IP */
|
||||
afi_t afi, struct prefix_rd *prd,
|
||||
struct attr *attr, /* part of bgp_info */
|
||||
uint8_t type, /* part of bgp_info */
|
||||
uint8_t sub_type, /* part of bgp_info */
|
||||
uint32_t *label); /* part of bgp_info */
|
||||
struct attr *attr, /* part of bgp_path_info */
|
||||
uint8_t type, /* part of bgp_path_info */
|
||||
uint8_t sub_type, /* part of bgp_path_info */
|
||||
uint32_t *label); /* part of bgp_path_info */
|
||||
|
||||
extern struct rfapi_next_hop_entry *rfapiEthRouteNode2NextHopList(
|
||||
struct agg_node *rn, struct rfapi_ip_prefix *rprefix,
|
||||
|
@ -226,7 +226,7 @@ void rfapiMonitorExtraFlush(safi_t safi, struct agg_node *rn)
|
||||
agg_unlock_node(rn);
|
||||
}
|
||||
if (hie->u.vpn.idx_rd) {
|
||||
/* looping through bi->extra->vnc.import.rd is tbd */
|
||||
/* looping through bpi->extra->vnc.import.rd is tbd */
|
||||
while (!skiplist_delete_first(hie->u.vpn.idx_rd)) {
|
||||
agg_unlock_node(rn);
|
||||
}
|
||||
@ -346,16 +346,16 @@ struct agg_node *rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd,
|
||||
for (rn = agg_node_match(rfd->import_table->imported_vpn[afi], p);
|
||||
rn;) {
|
||||
|
||||
struct bgp_info *bi;
|
||||
struct bgp_path_info *bpi;
|
||||
struct prefix pfx_dummy;
|
||||
|
||||
/* TBD update this code to use new valid_interior_count */
|
||||
for (bi = rn->info; bi; bi = bi->next) {
|
||||
for (bpi = rn->info; bpi; bpi = bpi->next) {
|
||||
/*
|
||||
* If there is a cached ENCAP UN address, it's a usable
|
||||
* VPN route
|
||||
*/
|
||||
if (bi->extra && bi->extra->vnc.import.un_family) {
|
||||
if (bpi->extra && bpi->extra->vnc.import.un_family) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -364,11 +364,11 @@ struct agg_node *rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd,
|
||||
* address,
|
||||
* it's a usable VPN route.
|
||||
*/
|
||||
if (!rfapiGetVncTunnelUnAddr(bi->attr, &pfx_dummy)) {
|
||||
if (!rfapiGetVncTunnelUnAddr(bpi->attr, &pfx_dummy)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bi)
|
||||
if (bpi)
|
||||
break;
|
||||
|
||||
agg_unlock_node(rn);
|
||||
|
@ -45,7 +45,7 @@ struct rfapi_monitor_encap {
|
||||
struct rfapi_monitor_encap *next;
|
||||
struct rfapi_monitor_encap *prev;
|
||||
struct agg_node *node; /* VPN node */
|
||||
struct bgp_info *bi; /* VPN bi */
|
||||
struct bgp_path_info *bpi; /* VPN bpi */
|
||||
struct agg_node *rn; /* parent node */
|
||||
};
|
||||
|
||||
@ -83,7 +83,7 @@ struct rfapi_it_extra {
|
||||
* Encap TLV */
|
||||
int valid_interior_count;
|
||||
|
||||
/* unicast exterior routes, key=bi,
|
||||
/* unicast exterior routes, key=bpi,
|
||||
* val=allocated prefix */
|
||||
struct skiplist *source;
|
||||
} e;
|
||||
|
@ -212,7 +212,7 @@ struct rfapi {
|
||||
|
||||
/*
|
||||
* when importing bgp-direct routes in resolve-nve mode,
|
||||
* this list maps unicast route nexthops to their bgp_infos
|
||||
* this list maps unicast route nexthops to their bgp_path_infos
|
||||
* in the unicast table
|
||||
*/
|
||||
struct skiplist *resolve_nve_nexthop;
|
||||
|
@ -616,18 +616,18 @@ void rfapiRibFree(struct rfapi_descriptor *rfd)
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies struct bgp_info to struct rfapi_info, except for rk fields and un
|
||||
* Copies struct bgp_path_info to struct rfapi_info, except for rk fields and un
|
||||
*/
|
||||
static void rfapiRibBi2Ri(struct bgp_info *bi, struct rfapi_info *ri,
|
||||
static void rfapiRibBi2Ri(struct bgp_path_info *bpi, struct rfapi_info *ri,
|
||||
uint32_t lifetime)
|
||||
{
|
||||
struct bgp_attr_encap_subtlv *pEncap;
|
||||
|
||||
ri->cost = rfapiRfpCost(bi->attr);
|
||||
ri->cost = rfapiRfpCost(bpi->attr);
|
||||
ri->lifetime = lifetime;
|
||||
|
||||
/* This loop based on rfapiRouteInfo2NextHopEntry() */
|
||||
for (pEncap = bi->attr->vnc_subtlvs; pEncap; pEncap = pEncap->next) {
|
||||
for (pEncap = bpi->attr->vnc_subtlvs; pEncap; pEncap = pEncap->next) {
|
||||
struct bgp_tea_options *hop;
|
||||
|
||||
switch (pEncap->type) {
|
||||
@ -665,13 +665,13 @@ static void rfapiRibBi2Ri(struct bgp_info *bi, struct rfapi_info *ri,
|
||||
}
|
||||
|
||||
rfapi_un_options_free(ri->un_options); /* maybe free old version */
|
||||
ri->un_options = rfapi_encap_tlv_to_un_option(bi->attr);
|
||||
ri->un_options = rfapi_encap_tlv_to_un_option(bpi->attr);
|
||||
|
||||
/*
|
||||
* VN options
|
||||
*/
|
||||
if (bi->extra
|
||||
&& decode_rd_type(bi->extra->vnc.import.rd.val)
|
||||
if (bpi->extra
|
||||
&& decode_rd_type(bpi->extra->vnc.import.rd.val)
|
||||
== RD_TYPE_VNC_ETH) {
|
||||
/* ethernet route */
|
||||
|
||||
@ -683,21 +683,21 @@ static void rfapiRibBi2Ri(struct bgp_info *bi, struct rfapi_info *ri,
|
||||
|
||||
vo->type = RFAPI_VN_OPTION_TYPE_L2ADDR;
|
||||
|
||||
/* copy from RD already stored in bi, so we don't need it_node
|
||||
/* copy from RD already stored in bpi, so we don't need it_node
|
||||
*/
|
||||
memcpy(&vo->v.l2addr.macaddr, bi->extra->vnc.import.rd.val + 2,
|
||||
memcpy(&vo->v.l2addr.macaddr, bpi->extra->vnc.import.rd.val + 2,
|
||||
ETH_ALEN);
|
||||
|
||||
(void)rfapiEcommunityGetLNI(bi->attr->ecommunity,
|
||||
(void)rfapiEcommunityGetLNI(bpi->attr->ecommunity,
|
||||
&vo->v.l2addr.logical_net_id);
|
||||
(void)rfapiEcommunityGetEthernetTag(bi->attr->ecommunity,
|
||||
(void)rfapiEcommunityGetEthernetTag(bpi->attr->ecommunity,
|
||||
&vo->v.l2addr.tag_id);
|
||||
|
||||
/* local_nve_id comes from RD */
|
||||
vo->v.l2addr.local_nve_id = bi->extra->vnc.import.rd.val[1];
|
||||
vo->v.l2addr.local_nve_id = bpi->extra->vnc.import.rd.val[1];
|
||||
|
||||
/* label comes from MP_REACH_NLRI label */
|
||||
vo->v.l2addr.label = decode_label(&bi->extra->label[0]);
|
||||
vo->v.l2addr.label = decode_label(&bpi->extra->label[0]);
|
||||
|
||||
rfapi_vn_options_free(
|
||||
ri->vn_options); /* maybe free old version */
|
||||
@ -707,8 +707,8 @@ static void rfapiRibBi2Ri(struct bgp_info *bi, struct rfapi_info *ri,
|
||||
/*
|
||||
* If there is an auxiliary IP address (L2 can have it), copy it
|
||||
*/
|
||||
if (bi->extra && bi->extra->vnc.import.aux_prefix.family) {
|
||||
ri->rk.aux_prefix = bi->extra->vnc.import.aux_prefix;
|
||||
if (bpi->extra && bpi->extra->vnc.import.aux_prefix.family) {
|
||||
ri->rk.aux_prefix = bpi->extra->vnc.import.aux_prefix;
|
||||
}
|
||||
}
|
||||
|
||||
@ -733,7 +733,7 @@ static void rfapiRibBi2Ri(struct bgp_info *bi, struct rfapi_info *ri,
|
||||
int rfapiRibPreloadBi(
|
||||
struct agg_node *rfd_rib_node, /* NULL = don't preload or filter */
|
||||
struct prefix *pfx_vn, struct prefix *pfx_un, uint32_t lifetime,
|
||||
struct bgp_info *bi)
|
||||
struct bgp_path_info *bpi)
|
||||
{
|
||||
struct rfapi_descriptor *rfd;
|
||||
struct skiplist *slRibPt = NULL;
|
||||
@ -751,13 +751,13 @@ int rfapiRibPreloadBi(
|
||||
|
||||
memset((void *)&rk, 0, sizeof(rk));
|
||||
rk.vn = *pfx_vn;
|
||||
rk.rd = bi->extra->vnc.import.rd;
|
||||
rk.rd = bpi->extra->vnc.import.rd;
|
||||
|
||||
/*
|
||||
* If there is an auxiliary IP address (L2 can have it), copy it
|
||||
*/
|
||||
if (bi->extra->vnc.import.aux_prefix.family) {
|
||||
rk.aux_prefix = bi->extra->vnc.import.aux_prefix;
|
||||
if (bpi->extra->vnc.import.aux_prefix.family) {
|
||||
rk.aux_prefix = bpi->extra->vnc.import.aux_prefix;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -774,13 +774,13 @@ int rfapiRibPreloadBi(
|
||||
|
||||
/* found: update contents of existing route in RIB */
|
||||
ori->un = *pfx_un;
|
||||
rfapiRibBi2Ri(bi, ori, lifetime);
|
||||
rfapiRibBi2Ri(bpi, ori, lifetime);
|
||||
} else {
|
||||
/* not found: add new route to RIB */
|
||||
ori = rfapi_info_new();
|
||||
ori->rk = rk;
|
||||
ori->un = *pfx_un;
|
||||
rfapiRibBi2Ri(bi, ori, lifetime);
|
||||
rfapiRibBi2Ri(bpi, ori, lifetime);
|
||||
|
||||
if (!slRibPt) {
|
||||
slRibPt = skiplist_new(0, rfapi_rib_key_cmp, NULL);
|
||||
@ -1590,7 +1590,7 @@ void rfapiRibUpdatePendingNode(
|
||||
struct agg_node *it_node, uint32_t lifetime)
|
||||
{
|
||||
struct prefix *prefix;
|
||||
struct bgp_info *bi;
|
||||
struct bgp_path_info *bpi;
|
||||
struct agg_node *pn;
|
||||
afi_t afi;
|
||||
uint32_t queued_flag;
|
||||
@ -1640,25 +1640,25 @@ void rfapiRibUpdatePendingNode(
|
||||
}
|
||||
|
||||
/*
|
||||
* The BIs in the import table are already sorted by cost
|
||||
* The BPIs in the import table are already sorted by cost
|
||||
*/
|
||||
for (bi = it_node->info; bi; bi = bi->next) {
|
||||
for (bpi = it_node->info; bpi; bpi = bpi->next) {
|
||||
|
||||
struct rfapi_info *ri;
|
||||
struct prefix pfx_nh;
|
||||
|
||||
if (!bi->attr) {
|
||||
if (!bpi->attr) {
|
||||
/* shouldn't happen */
|
||||
/* TBD increment error stats counter */
|
||||
continue;
|
||||
}
|
||||
if (!bi->extra) {
|
||||
if (!bpi->extra) {
|
||||
/* shouldn't happen */
|
||||
/* TBD increment error stats counter */
|
||||
continue;
|
||||
}
|
||||
|
||||
rfapiNexthop2Prefix(bi->attr, &pfx_nh);
|
||||
rfapiNexthop2Prefix(bpi->attr, &pfx_nh);
|
||||
|
||||
/*
|
||||
* Omit route if nexthop is self
|
||||
@ -1675,15 +1675,15 @@ void rfapiRibUpdatePendingNode(
|
||||
|
||||
ri = rfapi_info_new();
|
||||
ri->rk.vn = pfx_nh;
|
||||
ri->rk.rd = bi->extra->vnc.import.rd;
|
||||
ri->rk.rd = bpi->extra->vnc.import.rd;
|
||||
/*
|
||||
* If there is an auxiliary IP address (L2 can have it), copy it
|
||||
*/
|
||||
if (bi->extra->vnc.import.aux_prefix.family) {
|
||||
ri->rk.aux_prefix = bi->extra->vnc.import.aux_prefix;
|
||||
if (bpi->extra->vnc.import.aux_prefix.family) {
|
||||
ri->rk.aux_prefix = bpi->extra->vnc.import.aux_prefix;
|
||||
}
|
||||
|
||||
if (rfapiGetUnAddrOfVpnBi(bi, &ri->un)) {
|
||||
if (rfapiGetUnAddrOfVpnBi(bpi, &ri->un)) {
|
||||
rfapi_info_free(ri);
|
||||
continue;
|
||||
}
|
||||
@ -1711,7 +1711,7 @@ void rfapiRibUpdatePendingNode(
|
||||
continue;
|
||||
}
|
||||
|
||||
rfapiRibBi2Ri(bi, ri, lifetime);
|
||||
rfapiRibBi2Ri(bpi, ri, lifetime);
|
||||
|
||||
if (!pn->info) {
|
||||
pn->info = list_new();
|
||||
|
@ -105,7 +105,7 @@ extern void rfapiRibUpdatePendingNodeSubtree(struct bgp *bgp,
|
||||
|
||||
extern int rfapiRibPreloadBi(struct agg_node *rfd_rib_node,
|
||||
struct prefix *pfx_vn, struct prefix *pfx_un,
|
||||
uint32_t lifetime, struct bgp_info *bi);
|
||||
uint32_t lifetime, struct bgp_path_info *bpi);
|
||||
|
||||
extern struct rfapi_next_hop_entry *
|
||||
rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd,
|
||||
|
@ -394,7 +394,7 @@ int rfapiStream2Vty(void *stream, /* input */
|
||||
|
||||
/* called from bgpd/bgp_vty.c'route_vty_out() */
|
||||
void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p,
|
||||
struct bgp_info *bi, safi_t safi)
|
||||
struct bgp_path_info *bpi, safi_t safi)
|
||||
{
|
||||
char *s;
|
||||
uint32_t lifetime;
|
||||
@ -410,7 +410,7 @@ void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p,
|
||||
if (safi == SAFI_MPLS_VPN) {
|
||||
struct prefix pfx_un;
|
||||
|
||||
if (!rfapiGetVncTunnelUnAddr(bi->attr, &pfx_un)) {
|
||||
if (!rfapiGetVncTunnelUnAddr(bpi->attr, &pfx_un)) {
|
||||
char buf[BUFSIZ];
|
||||
vty_out(vty, "UN=%s",
|
||||
inet_ntop(pfx_un.family, pfx_un.u.val, buf,
|
||||
@ -418,27 +418,27 @@ void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p,
|
||||
}
|
||||
}
|
||||
|
||||
if (bi->attr && bi->attr->ecommunity) {
|
||||
s = ecommunity_ecom2str(bi->attr->ecommunity,
|
||||
if (bpi->attr && bpi->attr->ecommunity) {
|
||||
s = ecommunity_ecom2str(bpi->attr->ecommunity,
|
||||
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
vty_out(vty, " EC{%s}", s);
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, s);
|
||||
}
|
||||
|
||||
if (bi->extra != NULL) {
|
||||
if (bi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
|
||||
if (bpi->extra != NULL) {
|
||||
if (bpi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
|
||||
vty_out(vty, " label=VRF2VRF");
|
||||
else
|
||||
vty_out(vty, " label=%u",
|
||||
decode_label(&bi->extra->label[0]));
|
||||
decode_label(&bpi->extra->label[0]));
|
||||
}
|
||||
|
||||
if (!rfapiGetVncLifetime(bi->attr, &lifetime)) {
|
||||
if (!rfapiGetVncLifetime(bpi->attr, &lifetime)) {
|
||||
vty_out(vty, " life=%d", lifetime);
|
||||
}
|
||||
|
||||
vty_out(vty, " type=%s, subtype=%d", zebra_route_string(bi->type),
|
||||
bi->sub_type);
|
||||
vty_out(vty, " type=%s, subtype=%d", zebra_route_string(bpi->type),
|
||||
bpi->sub_type);
|
||||
|
||||
vty_out(vty, "%s", HVTYNL);
|
||||
}
|
||||
@ -477,9 +477,9 @@ void rfapiPrintAttrPtrs(void *stream, struct attr *attr)
|
||||
}
|
||||
|
||||
/*
|
||||
* Print BI in an Import Table
|
||||
* Print BPI in an Import Table
|
||||
*/
|
||||
void rfapiPrintBi(void *stream, struct bgp_info *bi)
|
||||
void rfapiPrintBi(void *stream, struct bgp_path_info *bpi)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
char *s;
|
||||
@ -503,12 +503,13 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi)
|
||||
if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
|
||||
return;
|
||||
|
||||
if (!bi)
|
||||
if (!bpi)
|
||||
return;
|
||||
|
||||
if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) && bi->extra
|
||||
&& bi->extra->vnc.import.timer) {
|
||||
struct thread *t = (struct thread *)bi->extra->vnc.import.timer;
|
||||
if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) && bpi->extra
|
||||
&& bpi->extra->vnc.import.timer) {
|
||||
struct thread *t =
|
||||
(struct thread *)bpi->extra->vnc.import.timer;
|
||||
r = snprintf(p, REMAIN, " [%4lu] ",
|
||||
thread_timer_remain_second(t));
|
||||
INCP;
|
||||
@ -518,14 +519,14 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi)
|
||||
INCP;
|
||||
}
|
||||
|
||||
if (bi->extra) {
|
||||
if (bpi->extra) {
|
||||
/* TBD This valid only for SAFI_MPLS_VPN, but not for encap */
|
||||
if (decode_rd_type(bi->extra->vnc.import.rd.val)
|
||||
if (decode_rd_type(bpi->extra->vnc.import.rd.val)
|
||||
== RD_TYPE_VNC_ETH) {
|
||||
has_macaddr = 1;
|
||||
memcpy(macaddr.octet, bi->extra->vnc.import.rd.val + 2,
|
||||
memcpy(macaddr.octet, bpi->extra->vnc.import.rd.val + 2,
|
||||
6);
|
||||
l2hid = bi->extra->vnc.import.rd.val[1];
|
||||
l2hid = bpi->extra->vnc.import.rd.val[1];
|
||||
}
|
||||
}
|
||||
|
||||
@ -537,24 +538,24 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi)
|
||||
* RFP option sizes (they are opaque values)
|
||||
* extended communities (RTs)
|
||||
*/
|
||||
if (bi->attr) {
|
||||
if (bpi->attr) {
|
||||
uint32_t lifetime;
|
||||
int printed_1st_gol = 0;
|
||||
struct bgp_attr_encap_subtlv *pEncap;
|
||||
struct prefix pfx_un;
|
||||
int af = BGP_MP_NEXTHOP_FAMILY(bi->attr->mp_nexthop_len);
|
||||
int af = BGP_MP_NEXTHOP_FAMILY(bpi->attr->mp_nexthop_len);
|
||||
|
||||
/* Nexthop */
|
||||
if (af == AF_INET) {
|
||||
r = snprintf(p, REMAIN, "%s",
|
||||
inet_ntop(AF_INET,
|
||||
&bi->attr->mp_nexthop_global_in,
|
||||
&bpi->attr->mp_nexthop_global_in,
|
||||
buf, BUFSIZ));
|
||||
INCP;
|
||||
} else if (af == AF_INET6) {
|
||||
r = snprintf(p, REMAIN, "%s",
|
||||
inet_ntop(AF_INET6,
|
||||
&bi->attr->mp_nexthop_global,
|
||||
&bpi->attr->mp_nexthop_global,
|
||||
buf, BUFSIZ));
|
||||
INCP;
|
||||
} else {
|
||||
@ -565,7 +566,7 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi)
|
||||
/*
|
||||
* VNC tunnel subtlv, if present, contains UN address
|
||||
*/
|
||||
if (!rfapiGetVncTunnelUnAddr(bi->attr, &pfx_un)) {
|
||||
if (!rfapiGetVncTunnelUnAddr(bpi->attr, &pfx_un)) {
|
||||
r = snprintf(p, REMAIN, " un=%s",
|
||||
inet_ntop(pfx_un.family, pfx_un.u.val, buf,
|
||||
BUFSIZ));
|
||||
@ -573,7 +574,7 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi)
|
||||
}
|
||||
|
||||
/* Lifetime */
|
||||
if (rfapiGetVncLifetime(bi->attr, &lifetime)) {
|
||||
if (rfapiGetVncLifetime(bpi->attr, &lifetime)) {
|
||||
r = snprintf(p, REMAIN, " nolife");
|
||||
INCP;
|
||||
} else {
|
||||
@ -585,7 +586,7 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi)
|
||||
}
|
||||
|
||||
/* RFP option lengths */
|
||||
for (pEncap = bi->attr->vnc_subtlvs; pEncap;
|
||||
for (pEncap = bpi->attr->vnc_subtlvs; pEncap;
|
||||
pEncap = pEncap->next) {
|
||||
|
||||
if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION) {
|
||||
@ -604,8 +605,8 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi)
|
||||
}
|
||||
|
||||
/* RT list */
|
||||
if (bi->attr->ecommunity) {
|
||||
s = ecommunity_ecom2str(bi->attr->ecommunity,
|
||||
if (bpi->attr->ecommunity) {
|
||||
s = ecommunity_ecom2str(bpi->attr->ecommunity,
|
||||
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
r = snprintf(p, REMAIN, " %s", s);
|
||||
INCP;
|
||||
@ -613,13 +614,13 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi)
|
||||
}
|
||||
}
|
||||
|
||||
r = snprintf(p, REMAIN, " bi@%p", bi);
|
||||
r = snprintf(p, REMAIN, " bpi@%p", bpi);
|
||||
INCP;
|
||||
|
||||
r = snprintf(p, REMAIN, " p@%p", bi->peer);
|
||||
r = snprintf(p, REMAIN, " p@%p", bpi->peer);
|
||||
INCP;
|
||||
|
||||
if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) {
|
||||
if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
|
||||
r = snprintf(p, REMAIN, " HD=yes");
|
||||
INCP;
|
||||
} else {
|
||||
@ -627,15 +628,16 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi)
|
||||
INCP;
|
||||
}
|
||||
|
||||
if (bi->attr) {
|
||||
if (bpi->attr) {
|
||||
|
||||
if (bi->attr->weight) {
|
||||
r = snprintf(p, REMAIN, " W=%d", bi->attr->weight);
|
||||
if (bpi->attr->weight) {
|
||||
r = snprintf(p, REMAIN, " W=%d", bpi->attr->weight);
|
||||
INCP;
|
||||
}
|
||||
|
||||
if (bi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
|
||||
r = snprintf(p, REMAIN, " LP=%d", bi->attr->local_pref);
|
||||
if (bpi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
|
||||
r = snprintf(p, REMAIN, " LP=%d",
|
||||
bpi->attr->local_pref);
|
||||
INCP;
|
||||
} else {
|
||||
r = snprintf(p, REMAIN, " LP=unset");
|
||||
@ -643,8 +645,8 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi)
|
||||
}
|
||||
}
|
||||
|
||||
r = snprintf(p, REMAIN, " %c:%u", zebra_route_char(bi->type),
|
||||
bi->sub_type);
|
||||
r = snprintf(p, REMAIN, " %c:%u", zebra_route_char(bpi->type),
|
||||
bpi->sub_type);
|
||||
INCP;
|
||||
|
||||
fp(out, "%s%s", line, HVTYNL);
|
||||
@ -656,7 +658,7 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi)
|
||||
HVTYNL);
|
||||
}
|
||||
|
||||
if (!rfapiGetL2o(bi->attr, &l2o_buf)) {
|
||||
if (!rfapiGetL2o(bpi->attr, &l2o_buf)) {
|
||||
fp(out,
|
||||
" L2O ETH=%02x:%02x:%02x:%02x:%02x:%02x LBL=%d LNI=%d LHI=%hhu%s",
|
||||
l2o_buf.macaddr.octet[0], l2o_buf.macaddr.octet[1],
|
||||
@ -665,12 +667,12 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi)
|
||||
l2o_buf.label, l2o_buf.logical_net_id, l2o_buf.local_nve_id,
|
||||
HVTYNL);
|
||||
}
|
||||
if (bi->extra && bi->extra->vnc.import.aux_prefix.family) {
|
||||
if (bpi->extra && bpi->extra->vnc.import.aux_prefix.family) {
|
||||
const char *sp;
|
||||
|
||||
sp = rfapi_ntop(bi->extra->vnc.import.aux_prefix.family,
|
||||
&bi->extra->vnc.import.aux_prefix.u.prefix, buf,
|
||||
BUFSIZ);
|
||||
sp = rfapi_ntop(bpi->extra->vnc.import.aux_prefix.family,
|
||||
&bpi->extra->vnc.import.aux_prefix.u.prefix,
|
||||
buf, BUFSIZ);
|
||||
buf[BUFSIZ - 1] = 0;
|
||||
if (sp) {
|
||||
fp(out, " IP: %s%s", sp, HVTYNL);
|
||||
@ -678,7 +680,7 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi)
|
||||
}
|
||||
{
|
||||
struct rfapi_un_option *uo =
|
||||
rfapi_encap_tlv_to_un_option(bi->attr);
|
||||
rfapi_encap_tlv_to_un_option(bpi->attr);
|
||||
if (uo) {
|
||||
rfapi_print_tunneltype_option(stream, 8, &uo->v.tunnel);
|
||||
rfapi_un_options_free(uo);
|
||||
@ -734,13 +736,13 @@ static void rfapiDebugPrintMonitorEncap(void *stream,
|
||||
if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
|
||||
return;
|
||||
|
||||
fp(out, " Mon m=%p, next=%p, node=%p, bi=%p%s", m, m->next, m->node,
|
||||
m->bi, HVTYNL);
|
||||
fp(out, " Mon m=%p, next=%p, node=%p, bpi=%p%s", m, m->next, m->node,
|
||||
m->bpi, HVTYNL);
|
||||
}
|
||||
|
||||
void rfapiShowItNode(void *stream, struct agg_node *rn)
|
||||
{
|
||||
struct bgp_info *bi;
|
||||
struct bgp_path_info *bpi;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
int (*fp)(void *, const char *, ...);
|
||||
@ -755,8 +757,8 @@ void rfapiShowItNode(void *stream, struct agg_node *rn)
|
||||
rfapi_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ),
|
||||
rn->p.prefixlen, rn, rn->lock, HVTYNL);
|
||||
|
||||
for (bi = rn->info; bi; bi = bi->next) {
|
||||
rfapiPrintBi(stream, bi);
|
||||
for (bpi = rn->info; bpi; bpi = bpi->next) {
|
||||
rfapiPrintBi(stream, bpi);
|
||||
}
|
||||
|
||||
/* doesn't show montors */
|
||||
@ -779,7 +781,7 @@ void rfapiShowImportTable(void *stream, const char *label, struct agg_table *rt,
|
||||
fp(out, "Import Table [%s]%s", label, HVTYNL);
|
||||
|
||||
for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) {
|
||||
struct bgp_info *bi;
|
||||
struct bgp_path_info *bpi;
|
||||
|
||||
if (rn->p.family == AF_ETHERNET) {
|
||||
rfapiEthAddr2Str(&rn->p.u.prefix_eth, buf, BUFSIZ);
|
||||
@ -791,8 +793,8 @@ void rfapiShowImportTable(void *stream, const char *label, struct agg_table *rt,
|
||||
rn->lock - 1, /* account for loop iterator locking */
|
||||
HVTYNL);
|
||||
|
||||
for (bi = rn->info; bi; bi = bi->next) {
|
||||
rfapiPrintBi(stream, bi);
|
||||
for (bpi = rn->info; bpi; bpi = bpi->next) {
|
||||
rfapiPrintBi(stream, bpi);
|
||||
}
|
||||
|
||||
if (isvpn) {
|
||||
@ -1008,7 +1010,7 @@ int rfapiShowVncQueries(void *stream, struct prefix *pfx_match)
|
||||
}
|
||||
|
||||
static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
|
||||
struct agg_node *rn, struct bgp_info *bi)
|
||||
struct agg_node *rn, struct bgp_path_info *bpi)
|
||||
{
|
||||
int (*fp)(void *, const char *, ...);
|
||||
struct vty *vty;
|
||||
@ -1047,26 +1049,26 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
|
||||
* UN addr
|
||||
*/
|
||||
buf_un[0] = 0;
|
||||
if (!rfapiGetUnAddrOfVpnBi(bi, &pfx_un)) {
|
||||
if (!rfapiGetUnAddrOfVpnBi(bpi, &pfx_un)) {
|
||||
snprintf(buf_un, BUFSIZ, "%s",
|
||||
inet_ntop(pfx_un.family, &pfx_un.u.prefix, buf_ntop,
|
||||
BUFSIZ));
|
||||
}
|
||||
|
||||
rfapiGetTunnelType(bi->attr, &tun_type);
|
||||
rfapiGetTunnelType(bpi->attr, &tun_type);
|
||||
/*
|
||||
* VN addr
|
||||
*/
|
||||
buf_vn[0] = 0;
|
||||
rfapiNexthop2Prefix(bi->attr, &pfx_vn);
|
||||
rfapiNexthop2Prefix(bpi->attr, &pfx_vn);
|
||||
if (tun_type == BGP_ENCAP_TYPE_MPLS) {
|
||||
/* MPLS carries un in nrli next hop (same as vn for IP tunnels)
|
||||
*/
|
||||
snprintf(buf_un, BUFSIZ, "%s",
|
||||
inet_ntop(pfx_vn.family, &pfx_vn.u.prefix, buf_ntop,
|
||||
BUFSIZ));
|
||||
if (bi->extra) {
|
||||
uint32_t l = decode_label(&bi->extra->label[0]);
|
||||
if (bpi->extra) {
|
||||
uint32_t l = decode_label(&bpi->extra->label[0]);
|
||||
snprintf(buf_vn, BUFSIZ, "Label: %d", l);
|
||||
} else /* should never happen */
|
||||
{
|
||||
@ -1085,10 +1087,10 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
|
||||
* See rfapi_import.c'rfapiRouteInfo2NextHopEntry() for conversion
|
||||
* back to cost.
|
||||
*/
|
||||
if (bi->attr) {
|
||||
if (bpi->attr) {
|
||||
uint32_t local_pref;
|
||||
if (bi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
|
||||
local_pref = bi->attr->local_pref;
|
||||
if (bpi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
|
||||
local_pref = bpi->attr->local_pref;
|
||||
else
|
||||
local_pref = 0;
|
||||
cost = (local_pref > 255) ? 0 : 255 - local_pref;
|
||||
@ -1103,7 +1105,7 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
|
||||
|
||||
/* Lifetime */
|
||||
/* NB rfapiGetVncLifetime sets infinite value when returning !0 */
|
||||
if (rfapiGetVncLifetime(bi->attr, &lifetime)
|
||||
if (rfapiGetVncLifetime(bpi->attr, &lifetime)
|
||||
|| (lifetime == RFAPI_INFINITE_LIFETIME)) {
|
||||
|
||||
fp(out, "%-10s ", "infinite");
|
||||
@ -1113,20 +1115,21 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
|
||||
fp(out, "%-10s ", buf_lifetime);
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) && bi->extra
|
||||
&& bi->extra->vnc.import.timer) {
|
||||
if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) && bpi->extra
|
||||
&& bpi->extra->vnc.import.timer) {
|
||||
|
||||
uint32_t remaining;
|
||||
time_t age;
|
||||
char buf_age[BUFSIZ];
|
||||
|
||||
struct thread *t = (struct thread *)bi->extra->vnc.import.timer;
|
||||
struct thread *t =
|
||||
(struct thread *)bpi->extra->vnc.import.timer;
|
||||
remaining = thread_timer_remain_second(t);
|
||||
|
||||
#if RFAPI_REGISTRATIONS_REPORT_AGE
|
||||
/*
|
||||
* Calculate when the timer started. Doing so here saves
|
||||
* us a timestamp field in "struct bgp_info".
|
||||
* us a timestamp field in "struct bgp_path_info".
|
||||
*
|
||||
* See rfapi_import.c'rfapiBiStartWithdrawTimer() for the
|
||||
* original calculation.
|
||||
@ -1140,12 +1143,12 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
|
||||
|
||||
fp(out, "%-10s ", buf_age);
|
||||
|
||||
} else if (RFAPI_LOCAL_BI(bi)) {
|
||||
} else if (RFAPI_LOCAL_BI(bpi)) {
|
||||
|
||||
char buf_age[BUFSIZ];
|
||||
|
||||
if (bi->extra && bi->extra->vnc.import.create_time) {
|
||||
rfapiFormatAge(bi->extra->vnc.import.create_time,
|
||||
if (bpi->extra && bpi->extra->vnc.import.create_time) {
|
||||
rfapiFormatAge(bpi->extra->vnc.import.create_time,
|
||||
buf_age, BUFSIZ);
|
||||
} else {
|
||||
buf_age[0] = '?';
|
||||
@ -1161,12 +1164,12 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
|
||||
* print that on the next line
|
||||
*/
|
||||
|
||||
if (bi->extra && bi->extra->vnc.import.aux_prefix.family) {
|
||||
if (bpi->extra && bpi->extra->vnc.import.aux_prefix.family) {
|
||||
const char *sp;
|
||||
|
||||
sp = rfapi_ntop(
|
||||
bi->extra->vnc.import.aux_prefix.family,
|
||||
&bi->extra->vnc.import.aux_prefix.u.prefix,
|
||||
bpi->extra->vnc.import.aux_prefix.family,
|
||||
&bpi->extra->vnc.import.aux_prefix.u.prefix,
|
||||
buf_ntop, BUFSIZ);
|
||||
buf_ntop[BUFSIZ - 1] = 0;
|
||||
|
||||
@ -1177,8 +1180,8 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tun_type != BGP_ENCAP_TYPE_MPLS && bi->extra) {
|
||||
uint32_t l = decode_label(&bi->extra->label[0]);
|
||||
if (tun_type != BGP_ENCAP_TYPE_MPLS && bpi->extra) {
|
||||
uint32_t l = decode_label(&bpi->extra->label[0]);
|
||||
if (!MPLS_LABEL_IS_NULL(l)) {
|
||||
fp(out, " Label: %d", l);
|
||||
if (nlines == 1)
|
||||
@ -1222,7 +1225,7 @@ static int rfapiShowRemoteRegistrationsIt(struct bgp *bgp, void *stream,
|
||||
for (rn = agg_route_top(it->imported_vpn[afi]); rn;
|
||||
rn = agg_route_next(rn)) {
|
||||
|
||||
struct bgp_info *bi;
|
||||
struct bgp_path_info *bpi;
|
||||
int count_only;
|
||||
|
||||
/* allow for wider or more narrow mask from user */
|
||||
@ -1232,30 +1235,32 @@ static int rfapiShowRemoteRegistrationsIt(struct bgp *bgp, void *stream,
|
||||
else
|
||||
count_only = 0;
|
||||
|
||||
for (bi = rn->info; bi; bi = bi->next) {
|
||||
for (bpi = rn->info; bpi; bpi = bpi->next) {
|
||||
|
||||
if (!show_local && RFAPI_LOCAL_BI(bi)) {
|
||||
if (!show_local && RFAPI_LOCAL_BI(bpi)) {
|
||||
|
||||
/* local route from RFP */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!show_remote && !RFAPI_LOCAL_BI(bi)) {
|
||||
if (!show_remote && !RFAPI_LOCAL_BI(bpi)) {
|
||||
|
||||
/* remote route */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (show_expiring
|
||||
&& !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
|
||||
&& !CHECK_FLAG(bpi->flags,
|
||||
BGP_PATH_REMOVED))
|
||||
continue;
|
||||
|
||||
if (!show_expiring
|
||||
&& CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
|
||||
&& CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
|
||||
continue;
|
||||
|
||||
if (bi->type == ZEBRA_ROUTE_BGP_DIRECT
|
||||
|| bi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT) {
|
||||
if (bpi->type == ZEBRA_ROUTE_BGP_DIRECT
|
||||
|| bpi->type
|
||||
== ZEBRA_ROUTE_BGP_DIRECT_EXT) {
|
||||
if (!show_imported)
|
||||
continue;
|
||||
} else {
|
||||
@ -1277,7 +1282,7 @@ static int rfapiShowRemoteRegistrationsIt(struct bgp *bgp, void *stream,
|
||||
type = "Holddown";
|
||||
} else {
|
||||
if (RFAPI_LOCAL_BI(
|
||||
bi)) {
|
||||
bpi)) {
|
||||
type = "Local";
|
||||
} else {
|
||||
type = "Remote";
|
||||
@ -1327,7 +1332,7 @@ static int rfapiShowRemoteRegistrationsIt(struct bgp *bgp, void *stream,
|
||||
"Lifetime", agetype, HVTYNL);
|
||||
}
|
||||
printed += rfapiPrintRemoteRegBi(bgp, stream,
|
||||
rn, bi);
|
||||
rn, bpi);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1535,7 +1540,7 @@ void rfapiPrintAdvertisedInfo(struct vty *vty, struct rfapi_descriptor *rfd,
|
||||
{
|
||||
afi_t afi; /* of the VN address */
|
||||
struct bgp_node *bn;
|
||||
struct bgp_info *bi;
|
||||
struct bgp_path_info *bpi;
|
||||
uint8_t type = ZEBRA_ROUTE_BGP;
|
||||
struct bgp *bgp;
|
||||
int printed = 0;
|
||||
@ -1543,7 +1548,7 @@ void rfapiPrintAdvertisedInfo(struct vty *vty, struct rfapi_descriptor *rfd,
|
||||
struct prefix_rd *prd;
|
||||
|
||||
/*
|
||||
* Find the bgp_info in the RIB corresponding to this
|
||||
* Find the bgp_path in the RIB corresponding to this
|
||||
* prefix and rfd
|
||||
*/
|
||||
|
||||
@ -1565,12 +1570,12 @@ void rfapiPrintAdvertisedInfo(struct vty *vty, struct rfapi_descriptor *rfd,
|
||||
|
||||
vty_out(vty, " bn=%p%s", bn, HVTYNL);
|
||||
|
||||
for (bi = bn->info; bi; bi = bi->next) {
|
||||
if (bi->peer == rfd->peer && bi->type == type
|
||||
&& bi->sub_type == BGP_ROUTE_RFP && bi->extra
|
||||
&& bi->extra->vnc.export.rfapi_handle == (void *)rfd) {
|
||||
for (bpi = bn->info; bpi; bpi = bpi->next) {
|
||||
if (bpi->peer == rfd->peer && bpi->type == type
|
||||
&& bpi->sub_type == BGP_ROUTE_RFP && bpi->extra
|
||||
&& bpi->extra->vnc.export.rfapi_handle == (void *)rfd) {
|
||||
|
||||
rfapiPrintBi(vty, bi);
|
||||
rfapiPrintBi(vty, bpi);
|
||||
printed = 1;
|
||||
}
|
||||
}
|
||||
@ -4840,6 +4845,10 @@ DEFUN (add_vrf_prefix_rd_label_pref,
|
||||
static int rfapi_cfg_group_it_count(struct rfapi_nve_group_cfg *rfg)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (rfg->rfapi_import_table == NULL)
|
||||
return 0;
|
||||
|
||||
afi_t afi = AFI_MAX;
|
||||
while (afi-- > 0) {
|
||||
count += rfg->rfapi_import_table->local_count[afi];
|
||||
|
@ -173,14 +173,14 @@ static int getce(struct bgp *bgp, struct attr *attr, struct prefix *pfx_ce)
|
||||
|
||||
|
||||
void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn,
|
||||
struct bgp_info *bi)
|
||||
struct bgp_path_info *bpi)
|
||||
{
|
||||
struct attr *attr = bi->attr;
|
||||
struct peer *peer = bi->peer;
|
||||
struct attr *attr = bpi->attr;
|
||||
struct peer *peer = bpi->peer;
|
||||
struct prefix *prefix = &rn->p;
|
||||
afi_t afi = family2afi(prefix->family);
|
||||
struct bgp_node *urn;
|
||||
struct bgp_info *ubi;
|
||||
struct bgp_path_info *ubpi;
|
||||
struct attr hattr;
|
||||
struct attr *iattr;
|
||||
struct prefix ce_nexthop;
|
||||
@ -193,10 +193,10 @@ void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn,
|
||||
return;
|
||||
}
|
||||
|
||||
if ((bi->type != ZEBRA_ROUTE_BGP)
|
||||
|| (bi->sub_type != BGP_ROUTE_NORMAL
|
||||
&& bi->sub_type != BGP_ROUTE_RFP
|
||||
&& bi->sub_type != BGP_ROUTE_STATIC)) {
|
||||
if ((bpi->type != ZEBRA_ROUTE_BGP)
|
||||
|| (bpi->sub_type != BGP_ROUTE_NORMAL
|
||||
&& bpi->sub_type != BGP_ROUTE_RFP
|
||||
&& bpi->sub_type != BGP_ROUTE_STATIC)) {
|
||||
|
||||
vnc_zlog_debug_verbose(
|
||||
"%s: wrong route type/sub_type for export, skipping",
|
||||
@ -256,17 +256,17 @@ void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn,
|
||||
*/
|
||||
urn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST,
|
||||
prefix, NULL);
|
||||
for (ubi = urn->info; ubi; ubi = ubi->next) {
|
||||
for (ubpi = urn->info; ubpi; ubpi = ubpi->next) {
|
||||
struct prefix unicast_nexthop;
|
||||
|
||||
if (CHECK_FLAG(ubi->flags, BGP_INFO_REMOVED))
|
||||
if (CHECK_FLAG(ubpi->flags, BGP_PATH_REMOVED))
|
||||
continue;
|
||||
|
||||
rfapiUnicastNexthop2Prefix(afi, ubi->attr, &unicast_nexthop);
|
||||
rfapiUnicastNexthop2Prefix(afi, ubpi->attr, &unicast_nexthop);
|
||||
|
||||
if (ubi->type == ZEBRA_ROUTE_VNC_DIRECT
|
||||
&& ubi->sub_type == BGP_ROUTE_REDISTRIBUTE
|
||||
&& ubi->peer == peer
|
||||
if (ubpi->type == ZEBRA_ROUTE_VNC_DIRECT
|
||||
&& ubpi->sub_type == BGP_ROUTE_REDISTRIBUTE
|
||||
&& ubpi->peer == peer
|
||||
&& prefix_same(&unicast_nexthop, &ce_nexthop)) {
|
||||
|
||||
vnc_zlog_debug_verbose(
|
||||
@ -282,7 +282,7 @@ void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn,
|
||||
*/
|
||||
encap_attr_export_ce(&hattr, attr, &ce_nexthop);
|
||||
if (bgp->rfapi_cfg->routemap_export_bgp) {
|
||||
struct bgp_info info;
|
||||
struct bgp_path_info info;
|
||||
route_map_result_t ret;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
@ -328,10 +328,10 @@ void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn,
|
||||
* "Withdrawing a Route" export process
|
||||
*/
|
||||
void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn,
|
||||
struct bgp_info *bi)
|
||||
struct bgp_path_info *bpi)
|
||||
{
|
||||
afi_t afi = family2afi(rn->p.family);
|
||||
struct bgp_info *vbi;
|
||||
struct bgp_path_info *vbpi;
|
||||
struct prefix ce_nexthop;
|
||||
|
||||
if (!afi) {
|
||||
@ -364,7 +364,7 @@ void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn,
|
||||
* This works only for IPv4 because IPv6 addresses are too big
|
||||
* to fit in an extended community
|
||||
*/
|
||||
if (getce(bgp, bi->attr, &ce_nexthop)) {
|
||||
if (getce(bgp, bpi->attr, &ce_nexthop)) {
|
||||
vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping",
|
||||
__func__);
|
||||
return;
|
||||
@ -376,13 +376,13 @@ void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn,
|
||||
* route from the unicast RIB
|
||||
*/
|
||||
|
||||
for (vbi = rn->info; vbi; vbi = vbi->next) {
|
||||
for (vbpi = rn->info; vbpi; vbpi = vbpi->next) {
|
||||
struct prefix ce;
|
||||
if (bi == vbi)
|
||||
if (bpi == vbpi)
|
||||
continue;
|
||||
if (bi->peer != vbi->peer)
|
||||
if (bpi->peer != vbpi->peer)
|
||||
continue;
|
||||
if (getce(bgp, vbi->attr, &ce))
|
||||
if (getce(bgp, vbpi->attr, &ce))
|
||||
continue;
|
||||
if (prefix_same(&ce, &ce_nexthop)) {
|
||||
vnc_zlog_debug_verbose(
|
||||
@ -395,8 +395,8 @@ void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn,
|
||||
/*
|
||||
* withdraw the route
|
||||
*/
|
||||
bgp_withdraw(bi->peer, &rn->p, 0, /* addpath_id */
|
||||
NULL, /* attr, ignored */
|
||||
bgp_withdraw(bpi->peer, &rn->p, 0, /* addpath_id */
|
||||
NULL, /* attr, ignored */
|
||||
afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
|
||||
BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
|
||||
NULL, 0, NULL); /* tag not used for unicast */
|
||||
@ -405,7 +405,7 @@ void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn,
|
||||
static void vnc_direct_bgp_vpn_enable_ce(struct bgp *bgp, afi_t afi)
|
||||
{
|
||||
struct agg_node *rn;
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *ri;
|
||||
|
||||
vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
|
||||
|
||||
@ -480,8 +480,8 @@ static void vnc_direct_bgp_vpn_disable_ce(struct bgp *bgp, afi_t afi)
|
||||
for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn;
|
||||
rn = bgp_route_next(rn)) {
|
||||
|
||||
struct bgp_info *ri;
|
||||
struct bgp_info *next;
|
||||
struct bgp_path_info *ri;
|
||||
struct bgp_path_info *next;
|
||||
|
||||
for (ri = rn->info, next = NULL; ri; ri = next) {
|
||||
|
||||
@ -516,24 +516,24 @@ static void vnc_direct_bgp_vpn_disable_ce(struct bgp *bgp, afi_t afi)
|
||||
static struct ecommunity *vnc_route_origin_ecom(struct agg_node *rn)
|
||||
{
|
||||
struct ecommunity *new;
|
||||
struct bgp_info *bi;
|
||||
struct bgp_path_info *bpi;
|
||||
|
||||
if (!rn->info)
|
||||
return NULL;
|
||||
|
||||
new = ecommunity_new();
|
||||
|
||||
for (bi = rn->info; bi; bi = bi->next) {
|
||||
for (bpi = rn->info; bpi; bpi = bpi->next) {
|
||||
|
||||
struct ecommunity_val roec;
|
||||
|
||||
switch (BGP_MP_NEXTHOP_FAMILY(bi->attr->mp_nexthop_len)) {
|
||||
switch (BGP_MP_NEXTHOP_FAMILY(bpi->attr->mp_nexthop_len)) {
|
||||
case AF_INET:
|
||||
memset(&roec, 0, sizeof(roec));
|
||||
roec.val[0] = 0x01;
|
||||
roec.val[1] = 0x03;
|
||||
memcpy(roec.val + 2,
|
||||
&bi->attr->mp_nexthop_global_in.s_addr, 4);
|
||||
&bpi->attr->mp_nexthop_global_in.s_addr, 4);
|
||||
roec.val[6] = 0;
|
||||
roec.val[7] = 0;
|
||||
ecommunity_add_val(new, &roec);
|
||||
@ -996,7 +996,7 @@ void vnc_direct_bgp_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
|
||||
struct rfapi_descriptor *irfd = rfd;
|
||||
struct attr hattr;
|
||||
struct attr *iattr;
|
||||
struct bgp_info info;
|
||||
struct bgp_path_info info;
|
||||
|
||||
if (rfapiRaddr2Qprefix(&irfd->vn_addr,
|
||||
&nhp))
|
||||
@ -1165,7 +1165,7 @@ static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
|
||||
afi_t afi, struct rfapi_descriptor *irfd)
|
||||
{
|
||||
struct prefix nhp;
|
||||
struct bgp_info info;
|
||||
struct bgp_path_info info;
|
||||
struct attr hattr;
|
||||
struct attr *iattr;
|
||||
|
||||
@ -1403,7 +1403,6 @@ static void vnc_direct_bgp_del_group_afi(struct bgp *bgp,
|
||||
return;
|
||||
}
|
||||
|
||||
assert(afi == AFI_IP || afi == AFI_IP6);
|
||||
rt = import_table->imported_vpn[afi];
|
||||
|
||||
if (!rfg->nves && rfg->type != RFAPI_GROUP_CFG_VRF) {
|
||||
@ -1629,7 +1628,7 @@ void vnc_direct_bgp_vpn_disable(struct bgp *bgp, afi_t afi)
|
||||
|
||||
/*
|
||||
* "Adding a Route" export process
|
||||
* TBD do we need to check bi->type and bi->sub_type here, or does
|
||||
* TBD do we need to check bpi->type and bpi->sub_type here, or does
|
||||
* caller do it?
|
||||
*/
|
||||
void vnc_direct_bgp_rh_add_route(struct bgp *bgp, afi_t afi,
|
||||
@ -1684,7 +1683,7 @@ void vnc_direct_bgp_rh_add_route(struct bgp *bgp, afi_t afi,
|
||||
if (encap_attr_export(&hattr, attr, NULL, NULL))
|
||||
return;
|
||||
if (hc->routemap_export_bgp) {
|
||||
struct bgp_info info;
|
||||
struct bgp_path_info info;
|
||||
route_map_result_t ret;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
@ -1753,7 +1752,7 @@ static int vncExportWithdrawTimer(struct thread *t)
|
||||
|
||||
/*
|
||||
* "Withdrawing a Route" export process
|
||||
* TBD do we need to check bi->type and bi->sub_type here, or does
|
||||
* TBD do we need to check bpi->type and bpi->sub_type here, or does
|
||||
* caller do it?
|
||||
*/
|
||||
void vnc_direct_bgp_rh_del_route(struct bgp *bgp, afi_t afi,
|
||||
@ -1839,7 +1838,7 @@ void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi)
|
||||
|
||||
struct bgp_table *table;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *ri;
|
||||
|
||||
memset(&prd, 0, sizeof(prd));
|
||||
prd.family = AF_UNSPEC;
|
||||
@ -1910,7 +1909,7 @@ void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi)
|
||||
}
|
||||
|
||||
if (hc->routemap_export_bgp) {
|
||||
struct bgp_info info;
|
||||
struct bgp_path_info info;
|
||||
route_map_result_t ret;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
@ -2001,8 +2000,8 @@ void vnc_direct_bgp_rh_vpn_disable(struct bgp *bgp, afi_t afi)
|
||||
for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn;
|
||||
rn = bgp_route_next(rn)) {
|
||||
|
||||
struct bgp_info *ri;
|
||||
struct bgp_info *next;
|
||||
struct bgp_path_info *ri;
|
||||
struct bgp_path_info *next;
|
||||
|
||||
for (ri = rn->info, next = NULL; ri; ri = next) {
|
||||
|
||||
|
@ -30,10 +30,10 @@
|
||||
#include "rfapi_private.h"
|
||||
|
||||
extern void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn,
|
||||
struct bgp_info *bi);
|
||||
struct bgp_path_info *bpi);
|
||||
|
||||
extern void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn,
|
||||
struct bgp_info *bi);
|
||||
struct bgp_path_info *bpi);
|
||||
|
||||
extern void vnc_direct_bgp_add_prefix(struct bgp *bgp,
|
||||
struct rfapi_import_table *import_table,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -35,10 +35,10 @@ extern uint32_t calc_local_pref(struct attr *attr, struct peer *peer);
|
||||
extern int vnc_prefix_cmp(void *pfx1, void *pfx2);
|
||||
|
||||
extern void vnc_import_bgp_add_route(struct bgp *bgp, struct prefix *prefix,
|
||||
struct bgp_info *info);
|
||||
struct bgp_path_info *info);
|
||||
|
||||
extern void vnc_import_bgp_del_route(struct bgp *bgp, struct prefix *prefix,
|
||||
struct bgp_info *info);
|
||||
struct bgp_path_info *info);
|
||||
|
||||
extern void vnc_import_bgp_redist_enable(struct bgp *bgp, afi_t afi);
|
||||
|
||||
@ -50,25 +50,24 @@ extern void vnc_import_bgp_exterior_redist_disable(struct bgp *bgp, afi_t afi);
|
||||
|
||||
|
||||
extern void vnc_import_bgp_exterior_add_route(
|
||||
struct bgp *bgp, /* exterior instance, we hope */
|
||||
struct prefix *prefix, /* unicast prefix */
|
||||
struct bgp_info *info); /* unicast info */
|
||||
struct bgp *bgp, /* exterior instance, we hope */
|
||||
struct prefix *prefix, /* unicast prefix */
|
||||
struct bgp_path_info *info); /* unicast info */
|
||||
|
||||
extern void
|
||||
vnc_import_bgp_exterior_del_route(struct bgp *bgp,
|
||||
struct prefix *prefix, /* unicast prefix */
|
||||
struct bgp_info *info); /* unicast info */
|
||||
extern void vnc_import_bgp_exterior_del_route(
|
||||
struct bgp *bgp, struct prefix *prefix, /* unicast prefix */
|
||||
struct bgp_path_info *info); /* unicast info */
|
||||
|
||||
extern void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
|
||||
struct bgp *bgp, struct prefix_rd *prd, /* RD */
|
||||
struct bgp_table *table_rd, /* per-rd VPN route table */
|
||||
struct prefix *prefix, /* VPN prefix */
|
||||
struct bgp_info *bi); /* new VPN host route */
|
||||
struct bgp_path_info *bpi); /* new VPN host route */
|
||||
|
||||
extern void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
|
||||
struct bgp *bgp, struct prefix_rd *prd, /* RD */
|
||||
struct bgp_table *table_rd, /* per-rd VPN route table */
|
||||
struct prefix *prefix, /* VPN prefix */
|
||||
struct bgp_info *bi); /* old VPN host route */
|
||||
struct bgp_path_info *bpi); /* old VPN host route */
|
||||
|
||||
#endif /* _QUAGGA_RFAPI_VNC_IMPORT_BGP_H_ */
|
||||
|
@ -29,13 +29,13 @@
|
||||
|
||||
extern void vnc_import_bgp_exterior_add_route_interior(
|
||||
struct bgp *bgp, struct rfapi_import_table *it,
|
||||
struct agg_node *rn_interior, /* VPN IT node */
|
||||
struct bgp_info *bi_interior); /* VPN IT route */
|
||||
struct agg_node *rn_interior, /* VPN IT node */
|
||||
struct bgp_path_info *bpi_interior); /* VPN IT route */
|
||||
|
||||
extern void vnc_import_bgp_exterior_del_route_interior(
|
||||
struct bgp *bgp, struct rfapi_import_table *it,
|
||||
struct agg_node *rn_interior, /* VPN IT node */
|
||||
struct bgp_info *bi_interior); /* VPN IT route */
|
||||
struct agg_node *rn_interior, /* VPN IT node */
|
||||
struct bgp_path_info *bpi_interior); /* VPN IT route */
|
||||
|
||||
extern void
|
||||
vnc_import_bgp_exterior_redist_enable_it(struct bgp *bgp, afi_t afi,
|
||||
|
@ -313,10 +313,12 @@ static void vnc_redistribute_withdraw(struct bgp *bgp, afi_t afi, uint8_t type)
|
||||
|
||||
/* This is the per-RD table of prefixes */
|
||||
table = prn->info;
|
||||
if (!table)
|
||||
continue;
|
||||
|
||||
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
|
||||
|
||||
struct bgp_info *ri;
|
||||
struct bgp_path_info *ri;
|
||||
|
||||
for (ri = rn->info; ri; ri = ri->next) {
|
||||
if (ri->type
|
||||
@ -576,7 +578,9 @@ static void vnc_zebra_add_del_prefix(struct bgp *bgp,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!zclient_vnc->redist[family2afi(rn->p.family)][ZEBRA_ROUTE_VNC])
|
||||
if (!vrf_bitmap_check(zclient_vnc->redist[family2afi(rn->p.family)]
|
||||
[ZEBRA_ROUTE_VNC],
|
||||
VRF_DEFAULT))
|
||||
return;
|
||||
|
||||
if (!bgp->rfapi_cfg) {
|
||||
@ -640,7 +644,8 @@ static void vnc_zebra_add_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd,
|
||||
if (zclient_vnc->sock < 0)
|
||||
return;
|
||||
|
||||
if (!zclient_vnc->redist[afi][ZEBRA_ROUTE_VNC])
|
||||
if (!vrf_bitmap_check(zclient_vnc->redist[afi][ZEBRA_ROUTE_VNC],
|
||||
VRF_DEFAULT))
|
||||
return;
|
||||
|
||||
if (afi != AFI_IP && afi != AFI_IP6) {
|
||||
@ -839,12 +844,12 @@ int vnc_redistribute_set(struct bgp *bgp, afi_t afi, int type)
|
||||
// bgp->redist[afi][type] = 1;
|
||||
|
||||
/* Return if already redistribute flag is set. */
|
||||
if (zclient_vnc->redist[afi][type])
|
||||
if (vrf_bitmap_check(zclient_vnc->redist[afi][type], VRF_DEFAULT))
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
vrf_bitmap_set(zclient_vnc->redist[afi][type], VRF_DEFAULT);
|
||||
|
||||
// zclient_vnc->redist[afi][type] = 1;
|
||||
// vrf_bitmap_set(zclient_vnc->redist[afi][type], VRF_DEFAULT);
|
||||
|
||||
/* Return if zebra connection is not established. */
|
||||
if (zclient_vnc->sock < 0)
|
||||
@ -875,9 +880,9 @@ int vnc_redistribute_unset(struct bgp *bgp, afi_t afi, int type)
|
||||
bgp->rfapi_cfg->redist[afi][type] = 0;
|
||||
|
||||
/* Return if zebra connection is disabled. */
|
||||
if (!zclient_vnc->redist[afi][type])
|
||||
if (!vrf_bitmap_check(zclient_vnc->redist[afi][type], VRF_DEFAULT))
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
zclient_vnc->redist[afi][type] = 0;
|
||||
vrf_bitmap_unset(zclient_vnc->redist[afi][type], VRF_DEFAULT);
|
||||
|
||||
if (bgp->rfapi_cfg->redist[AFI_IP][type] == 0
|
||||
&& bgp->rfapi_cfg->redist[AFI_IP6][type] == 0
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
if ENABLE_BGP_VNC
|
||||
sbin_PROGRAMS += bgpd/rfp-example/rfptest/rfptest
|
||||
noinst_PROGRAMS += bgpd/rfp-example/rfptest/rfptest
|
||||
endif
|
||||
|
||||
bgpd_rfp_example_rfptest_rfptest_CFLAGS = -I$(top_srcdir)/bgpd/rfapi
|
||||
|
@ -208,6 +208,8 @@ bgpd_bgpd_rpki_la_CFLAGS = $(WERROR) $(RTRLIB_CFLAGS)
|
||||
bgpd_bgpd_rpki_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
bgpd_bgpd_rpki_la_LIBADD = $(RTRLIB_LIBS)
|
||||
|
||||
bgpd/bgp_evpn_vty_clippy.c: $(CLIPPY_DEPS)
|
||||
bgpd/bgp_evpn_vty.$(OBJEXT): bgpd/bgp_evpn_vty_clippy.c
|
||||
bgpd/bgp_vty_clippy.c: $(CLIPPY_DEPS)
|
||||
bgpd/bgp_vty.$(OBJEXT): bgpd/bgp_vty_clippy.c
|
||||
bgpd/bgp_route_clippy.c: $(CLIPPY_DEPS)
|
||||
|
4
config.version.in
Normal file
4
config.version.in
Normal file
@ -0,0 +1,4 @@
|
||||
# this file is used to carry --with-pkg-extra-version into tarballs
|
||||
EXTRAVERSION="@EXTRAVERSION@"
|
||||
# for easy access by scripts before ./configure is run
|
||||
DIST_PACKAGE_VERSION="@PACKAGE_VERSION@"
|
162
configure.ac
162
configure.ac
@ -323,12 +323,48 @@ fi
|
||||
AC_SUBST(AC_LDFLAGS)
|
||||
AM_CONDITIONAL([STATIC_BIN], [test "x$enable_static_bin" = "xyes"])
|
||||
|
||||
dnl $AR and $RANLIB are set by LT_INIT above
|
||||
AC_MSG_CHECKING([whether $AR supports D option])
|
||||
if $AR crD conftest.a; then
|
||||
AC_MSG_RESULT([yes])
|
||||
dnl ARFLAGS is for automake, AR_FLAGS for libtool m-(
|
||||
ARFLAGS="crD"
|
||||
AR_FLAGS="crD"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
ARFLAGS="cru"
|
||||
AR_FLAGS="cru"
|
||||
fi
|
||||
AC_SUBST(ARFLAGS)
|
||||
AC_SUBST(AR_FLAGS)
|
||||
|
||||
AC_MSG_CHECKING([whether $RANLIB supports D option])
|
||||
if $RANLIB -D conftest.a; then
|
||||
AC_MSG_RESULT([yes])
|
||||
RANLIB="$RANLIB -D"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
AC_SUBST(RANLIB)
|
||||
|
||||
test -f conftest.a && rm conftest.a
|
||||
|
||||
dnl ----------------------
|
||||
dnl Packages configuration
|
||||
dnl ----------------------
|
||||
if test -f config.version; then
|
||||
. ./config.version
|
||||
elif test -f "${srcdir}/config.version"; then
|
||||
. "${srcdir}/config.version"
|
||||
fi
|
||||
AC_ARG_WITH(pkg-extra-version,
|
||||
AS_HELP_STRING([--with-pkg-extra-version=VER], [add extra version field, for packagers/distributions]),
|
||||
[EXTRAVERSION=$withval],)
|
||||
AS_HELP_STRING([--with-pkg-extra-version=VER], [add extra version field, for packagers/distributions]), [
|
||||
if test "$withval" = "no"; then
|
||||
EXTRAVERSION=
|
||||
else
|
||||
EXTRAVERSION=$withval
|
||||
fi
|
||||
], [])
|
||||
AC_ARG_WITH(pkg-git-version,
|
||||
AS_HELP_STRING([--with-pkg-git-version], [add git information to MOTD and build version string]),
|
||||
[ test "x$withval" != "xno" && with_pkg_git_version="yes" ])
|
||||
@ -462,9 +498,9 @@ AC_ARG_ENABLE([memory-sanitizer],
|
||||
AS_IF([test "${enable_clippy_only}" != "yes"], [
|
||||
AC_CHECK_HEADERS(json-c/json.h)
|
||||
AC_CHECK_LIB(json-c, json_object_get, LIBS="$LIBS -ljson-c", [], [-lm])
|
||||
if test $ac_cv_lib_json_c_json_object_get = no; then
|
||||
if test "$ac_cv_lib_json_c_json_object_get" = no; then
|
||||
AC_CHECK_LIB(json, json_object_get, LIBS="$LIBS -ljson")
|
||||
if test $ac_cv_lib_json_json_object_get = no; then
|
||||
if test "$ac_cv_lib_json_json_object_get" = no; then
|
||||
AC_MSG_ERROR([lib json is needed to compile])
|
||||
fi
|
||||
fi
|
||||
@ -742,6 +778,7 @@ if test "x${EXTRAVERSION}" != "x" ; then
|
||||
AC_SUBST(PACKAGE_EXTRAVERSION, ["${EXTRAVERSION}"])
|
||||
PACKAGE_STRING="${PACKAGE_STRING}${EXTRAVERSION}"
|
||||
fi
|
||||
AC_SUBST(EXTRAVERSION)
|
||||
|
||||
if test "x$with_pkg_git_version" = "xyes"; then
|
||||
if test -d "${srcdir}/.git"; then
|
||||
@ -958,11 +995,6 @@ case "$host_os" in
|
||||
AC_CHECK_LIB(socket, main)
|
||||
AC_CHECK_LIB(nsl, main)
|
||||
AC_CHECK_LIB(umem, main)
|
||||
AC_CHECK_FUNCS([printstack], [
|
||||
AC_DEFINE([HAVE_PRINTSTACK],1,[Solaris printstack])
|
||||
AC_DEFINE([HAVE_STACK_TRACE],1,[Stack symbols decode functionality])
|
||||
])
|
||||
CURSES=-lcurses
|
||||
SOLARIS="solaris"
|
||||
;;
|
||||
linux*)
|
||||
@ -1028,40 +1060,47 @@ dnl ---------------------
|
||||
dnl Integrated VTY option
|
||||
dnl ---------------------
|
||||
case "${enable_vtysh}" in
|
||||
"no") VTYSH="";;
|
||||
*) VTYSH="vtysh";
|
||||
AC_DEFINE(VTYSH,,VTY shell)
|
||||
dnl Vtysh uses libreadline, which looks for termcap functions at
|
||||
dnl configure time. We follow readlines search order.
|
||||
dnl The required procedures are in libtermcap on NetBSD, in
|
||||
dnl [TODO] on Linux, and in [TODO] on Solaris.
|
||||
AC_CHECK_LIB(termcap, tputs, LIBREADLINE="$LIBREADLINE -ltermcap",
|
||||
[AC_CHECK_LIB(tinfo, tputs, LIBREADLINE="$LIBREADLINE -ltinfo",
|
||||
[AC_CHECK_LIB(curses, tputs, LIBREADLINE="$LIBREADLINE -lcurses",
|
||||
[AC_CHECK_LIB(ncurses, tputs,
|
||||
LIBREADLINE="$LIBREADLINE -lncurses")]
|
||||
)]
|
||||
)]
|
||||
)
|
||||
AC_CHECK_LIB(readline, main, LIBREADLINE="-lreadline $LIBREADLINE",,
|
||||
"$LIBREADLINE")
|
||||
if test $ac_cv_lib_readline_main = no; then
|
||||
AC_MSG_ERROR([vtysh needs libreadline but was not found and usable on your system.])
|
||||
fi
|
||||
AC_CHECK_HEADER(readline/history.h)
|
||||
if test $ac_cv_header_readline_history_h = no;then
|
||||
AC_MSG_ERROR([readline is too old to have readline/history.h, please update to the latest readline library.])
|
||||
fi
|
||||
AC_CHECK_LIB(readline, rl_completion_matches,
|
||||
LIBREADLINE="$LIBREADLINE",, "$LIBREADLINE")
|
||||
if test $ac_cv_lib_readline_rl_completion_matches = no; then
|
||||
AC_DEFINE(rl_completion_matches,completion_matches,Old readline)
|
||||
fi
|
||||
AC_SEARCH_LIBS([append_history], [readline], [frr_cv_append_history=yes], [frr_cv_append_history=no])
|
||||
if test "$frr_cv_append_history" = yes; then
|
||||
AC_DEFINE(HAVE_APPEND_HISTORY, 1, [Have history.h append_history])
|
||||
fi
|
||||
;;
|
||||
"no")
|
||||
VTYSH="";;
|
||||
*)
|
||||
VTYSH="vtysh";
|
||||
AC_DEFINE(VTYSH,,VTY shell)
|
||||
|
||||
prev_libs="$LIBS"
|
||||
AC_CHECK_LIB(readline, main, [
|
||||
LIBREADLINE="-lreadline"
|
||||
], [
|
||||
dnl readline failed - it might be incorrectly linked and missing its
|
||||
dnl termcap/tinfo/curses dependency. see if we can fix that...
|
||||
AC_SEARCH_LIBS(tputs, [termcap tinfo curses ncurses], [
|
||||
LIBREADLINE="$ac_cv_search_tputs"
|
||||
], [
|
||||
AC_MSG_ERROR([libreadline (needed for vtysh) not found and/or missing dependencies])
|
||||
])
|
||||
|
||||
dnl re-try with the lib we found above
|
||||
unset ac_cv_lib_readline_main
|
||||
AC_CHECK_LIB(readline, main, [
|
||||
LIBREADLINE="-lreadline $LIBREADLINE"
|
||||
], [
|
||||
AC_MSG_ERROR([libreadline (needed for vtysh) not found and/or missing dependencies])
|
||||
], [$LIBREADLINE])
|
||||
], [])
|
||||
LIBS="$prev_libs"
|
||||
|
||||
AC_CHECK_HEADER(readline/history.h)
|
||||
if test $ac_cv_header_readline_history_h = no;then
|
||||
AC_MSG_ERROR([readline is too old to have readline/history.h, please update to the latest readline library.])
|
||||
fi
|
||||
AC_CHECK_LIB(readline, rl_completion_matches, [true], [], [$LIBREADLINE])
|
||||
if test $ac_cv_lib_readline_rl_completion_matches = no; then
|
||||
AC_DEFINE(rl_completion_matches,completion_matches,Old readline)
|
||||
fi
|
||||
AC_CHECK_LIB(readline, [append_history], [frr_cv_append_history=yes], [frr_cv_append_history=no], [$LIBREADLINE])
|
||||
if test "$frr_cv_append_history" = yes; then
|
||||
AC_DEFINE(HAVE_APPEND_HISTORY, 1, [Have history.h append_history])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(LIBREADLINE)
|
||||
AM_CONDITIONAL(VTYSH, test "x$VTYSH" = "xvtysh")
|
||||
@ -1402,7 +1441,7 @@ fi
|
||||
|
||||
AM_CONDITIONAL(BFDD, [test "x$BFDD" = "xbfdd"])
|
||||
|
||||
if test $ac_cv_lib_json_c_json_object_get = no -a "x$BFDD" = "xbfdd"; then
|
||||
if test "$ac_cv_lib_json_c_json_object_get" = no -a "x$BFDD" = "xbfdd"; then
|
||||
AC_MSG_ERROR(["you must use json-c library to use bfdd"])
|
||||
fi
|
||||
|
||||
@ -1462,7 +1501,6 @@ fi
|
||||
AM_CONDITIONAL([ENABLE_BGP_VNC], [test x${enable_bgp_vnc} != xno])
|
||||
|
||||
AC_SUBST(SOLARIS)
|
||||
AC_SUBST(CURSES)
|
||||
AC_CHECK_LIB(crypt, crypt, [],
|
||||
[AC_CHECK_LIB(crypto, DES_crypt)])
|
||||
AC_CHECK_LIB(resolv, res_init)
|
||||
@ -1497,6 +1535,11 @@ if test "${enable_snmp}" != "" -a "${enable_snmp}" != "no"; then
|
||||
fi
|
||||
SNMP_LIBS="`${NETSNMP_CONFIG} --agent-libs`"
|
||||
SNMP_CFLAGS="`${NETSNMP_CONFIG} --base-cflags`"
|
||||
# net-snmp lists all of its own dependencies. we absolutely do not want that
|
||||
# among other things we avoid a GPL vs. OpenSSL license conflict here
|
||||
for removelib in crypto ssl sensors pci wrap; do
|
||||
SNMP_LIBS="`echo $SNMP_LIBS | sed -e 's/\(^\|\s\)-l'$removelib'\b/ /g' -e 's/\(^\|\s\)\([^\s]*\/\)\?lib'$removelib'\.[^\s]\+\b/ /g'`"
|
||||
done
|
||||
AC_MSG_CHECKING([whether we can link to Net-SNMP])
|
||||
AC_LINK_IFELSE_FLAGS([$SNMP_CFLAGS], [$SNMP_LIBS], [AC_LANG_PROGRAM([
|
||||
int main(void);
|
||||
@ -1811,17 +1854,31 @@ dnl check for glibc 'backtrace'
|
||||
dnl ---------------------------
|
||||
if test x"${enable_backtrace}" != x"no" ; then
|
||||
backtrace_ok=no
|
||||
AC_CHECK_HEADER([execinfo.h], [
|
||||
AC_SEARCH_LIBS([backtrace], [execinfo], [
|
||||
AC_DEFINE(HAVE_GLIBC_BACKTRACE,,[Glibc backtrace])
|
||||
AC_DEFINE(HAVE_STACK_TRACE,,[Stack symbol decoding])
|
||||
backtrace_ok=yes
|
||||
],, [-lm])
|
||||
PKG_CHECK_MODULES([UNWIND], [libunwind], [
|
||||
AC_DEFINE(HAVE_LIBUNWIND, 1, [libunwind])
|
||||
backtrace_ok=yes
|
||||
], [
|
||||
case "$host_os" in
|
||||
sunos* | solaris2*)
|
||||
AC_CHECK_FUNCS([printstack], [
|
||||
AC_DEFINE([HAVE_PRINTSTACK], 1, [Solaris printstack])
|
||||
backtrace_ok=yes
|
||||
])
|
||||
;;
|
||||
esac
|
||||
if test "$backtrace_ok" = no; then
|
||||
AC_CHECK_HEADER([execinfo.h], [
|
||||
AC_SEARCH_LIBS([backtrace], [execinfo], [
|
||||
AC_DEFINE(HAVE_GLIBC_BACKTRACE, 1, [Glibc backtrace])
|
||||
backtrace_ok=yes
|
||||
],, [-lm])
|
||||
])
|
||||
fi
|
||||
])
|
||||
|
||||
if test x"${enable_backtrace}" = x"yes" -a x"${backtrace_ok}" = x"no"; then
|
||||
dnl user explicitly requested backtrace but we failed to find support
|
||||
AC_MSG_FAILURE([failed to find backtrace support])
|
||||
AC_MSG_FAILURE([failed to find backtrace or libunwind support])
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -2018,6 +2075,7 @@ AC_MSG_RESULT($ac_cv_htonl_works)
|
||||
AC_CONFIG_FILES([Makefile],[sed -e 's/^#AUTODERP# //' -i Makefile])
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
config.version
|
||||
redhat/frr.spec
|
||||
solaris/Makefile
|
||||
debianpkg/changelog
|
||||
|
@ -4,7 +4,7 @@ Priority: optional
|
||||
Maintainer: Nobody <nobody@frrouting.org>
|
||||
Uploaders: Nobody <nobody@frrouting.org>
|
||||
XSBC-Original-Maintainer: <maintainers@frrouting.org>
|
||||
Build-Depends: debhelper (>= 7.0.50~), libncurses5-dev, libreadline-dev, texlive-latex-base, texlive-generic-recommended, libpam0g-dev | libpam-dev, libcap-dev, texinfo (>= 4.7), autotools-dev, libpcre3-dev, gawk, chrpath, libsnmp-dev, git, dh-autoreconf, libjson-c-dev, libjson-c2 | libjson-c3, dh-systemd, libsystemd-dev, bison, flex, libc-ares-dev, pkg-config, python (>= 2.7), python-ipaddr, python-sphinx, libpython-dev, install-info
|
||||
Build-Depends: debhelper (>= 7.0.50~), libreadline-dev, libpam0g-dev | libpam-dev, libcap-dev, texinfo (>= 4.7), autotools-dev, libpcre3-dev, gawk, chrpath, libsnmp-dev, git, dh-autoreconf, libjson-c-dev, libjson-c2 | libjson-c3, dh-systemd, libsystemd-dev, bison, flex, libc-ares-dev, pkg-config, python (>= 2.7) | python3, python-sphinx | python3-sphinx, libpython-dev | libpython3-dev, install-info
|
||||
Standards-Version: 3.9.6
|
||||
Homepage: http://www.frrouting.org/
|
||||
|
||||
|
@ -4,5 +4,4 @@ etc/iproute2/rt_protos.d/
|
||||
usr/share/doc/frr/
|
||||
usr/share/doc/frr/examples/
|
||||
usr/share/lintian/overrides/
|
||||
usr/share/snmp/mibs/
|
||||
var/log/frr/
|
||||
|
@ -5,7 +5,6 @@ usr/include/frr/
|
||||
usr/lib/
|
||||
tools/frr usr/lib/frr
|
||||
usr/share/doc/frr/
|
||||
usr/share/snmp/mibs/
|
||||
tools/etc/* etc/
|
||||
tools/*.service lib/systemd/system
|
||||
tools/frr-reload usr/lib/frr/
|
||||
|
@ -17,7 +17,7 @@
|
||||
# open, as well as the daemons, so always signal the daemons.
|
||||
# It's safe, a NOP if (only) syslog is being used.
|
||||
for i in babeld bgpd eigrpd isisd ldpd nhrpd ospf6d ospfd \
|
||||
pimd ripd ripngd zebra staticd ; do
|
||||
pimd ripd ripngd zebra staticd fabricd; do
|
||||
if [ -e /var/run/frr/$i.pid ] ; then
|
||||
pids="$pids $(cat /var/run/frr/$i.pid)"
|
||||
fi
|
||||
|
@ -13,3 +13,4 @@ doc/manpages/_build/man/zebra.8
|
||||
doc/manpages/_build/man/isisd.8
|
||||
doc/manpages/_build/man/watchfrr.8
|
||||
doc/manpages/_build/man/mtracebis.8
|
||||
doc/manpages/_build/man/fabricd.8
|
||||
|
@ -7,15 +7,15 @@
|
||||
# The following are the defaults. They can be overridden by setting a
|
||||
# env variable to a different value
|
||||
|
||||
WANT_LDP ?= 1
|
||||
WANT_PIM ?= 1
|
||||
# -Werror - don't enable this unless you're doing a dev package build
|
||||
WANT_WERROR ?= 0
|
||||
|
||||
WANT_OSPFAPI ?= 1
|
||||
WANT_BGP_VNC ?= 1
|
||||
WANT_CUMULUS_MODE ?= 0
|
||||
WANT_MULTIPATH ?= 1
|
||||
WANT_SNMP ?= 0
|
||||
WANT_RPKI ?= 0
|
||||
WANT_BFD ?= 1
|
||||
|
||||
# NOTES:
|
||||
#
|
||||
@ -39,6 +39,7 @@ WANT_FRR_USER ?= frr
|
||||
WANT_FRR_VTY_GROUP ?= frrvty
|
||||
|
||||
# Don't build PDF docs by default
|
||||
# add build deps: texlive-latex-base, texlive-generic-recommended
|
||||
GENERATE_PDF ?= 0
|
||||
|
||||
#
|
||||
@ -56,18 +57,6 @@ else
|
||||
$(warning "DEBIAN: SNMP disabled, see README.Debian")
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_LDP), 1)
|
||||
USE_LDP=--enable-ldpd
|
||||
else
|
||||
USE_LDP=--disable-ldpd
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_PIM), 1)
|
||||
USE_PIM=--enable-pimd
|
||||
else
|
||||
USE_PIM=--disable-pimd
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_OSPFAPI), 1)
|
||||
USE_OSPFAPI=--enable-ospfapi=yes
|
||||
else
|
||||
@ -102,10 +91,10 @@ else
|
||||
USE_RPKI=--disable-rpki
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_BFD), 1)
|
||||
USE_BFD=--enable-bfdd
|
||||
ifeq ($(WANT_WERROR), 1)
|
||||
USE_WERROR=--enable-werror
|
||||
else
|
||||
USE_BFD=--disable-bfdd
|
||||
USE_WERROR=--disable-werror
|
||||
endif
|
||||
|
||||
ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
|
||||
@ -127,14 +116,6 @@ else
|
||||
endif
|
||||
|
||||
override_dh_auto_configure:
|
||||
# Frr needs /proc to check some BSD vs Linux specific stuff.
|
||||
# Else it fails with an obscure error message pointing out that
|
||||
# IPCTL_FORWARDING is an undefined symbol which is not very helpful.
|
||||
@if ! [ -d /proc/1 ]; then \
|
||||
echo "./configure needs a mounted /proc"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
if ! [ -e config.status ]; then \
|
||||
dh_auto_configure -- \
|
||||
--enable-exampledir=/usr/share/doc/frr/examples/ \
|
||||
@ -144,32 +125,23 @@ override_dh_auto_configure:
|
||||
$(USE_SNMP) \
|
||||
$(USE_OSPFAPI) \
|
||||
$(USE_MULTIPATH) \
|
||||
$(USE_LDP) \
|
||||
--enable-fpm \
|
||||
$(USE_FRR_USER) $(USE_FRR_GROUP) \
|
||||
$(USE_FRR_VTY_GROUP) \
|
||||
--enable-configfile-mask=0640 \
|
||||
--enable-logfile-mask=0640 \
|
||||
--enable-werror \
|
||||
$(USE_WERROR) \
|
||||
--with-libpam \
|
||||
--enable-systemd=yes \
|
||||
--enable-poll=yes \
|
||||
$(USE_CUMULUS) \
|
||||
$(USE_PIM) \
|
||||
--enable-dependency-tracking \
|
||||
--disable-dependency-tracking \
|
||||
$(USE_BGP_VNC) \
|
||||
$(USE_RPKI) \
|
||||
$(USE_BFD) \
|
||||
$(shell dpkg-buildflags --export=configure); \
|
||||
fi
|
||||
|
||||
override_dh_auto_build:
|
||||
# doc/ is a bit crazy
|
||||
ifeq ($(GENERATE_PDF), 1)
|
||||
dh_auto_build -- -C doc pdf
|
||||
endif
|
||||
rm -vf doc/user/_build/texinfo/frr.info
|
||||
dh_auto_build -- -C doc info
|
||||
dh_auto_build
|
||||
|
||||
override_dh_auto_test:
|
||||
|
||||
@ -186,12 +158,9 @@ override_dh_auto_install:
|
||||
mkdir -p debian/tmp/etc/frr/
|
||||
perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample*
|
||||
|
||||
# leftover from previously shipping SMUX client OID MIB
|
||||
mkdir -p debian/tmp/usr/share/snmp/mibs/
|
||||
|
||||
# cleaning .la files
|
||||
sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la
|
||||
sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/frr/modules/*.la
|
||||
# we don't need .la files
|
||||
rm debian/tmp/usr/lib/*.la
|
||||
rm debian/tmp/usr/lib/frr/modules/*.la
|
||||
|
||||
override_dh_systemd_start:
|
||||
dh_systemd_start frr.service
|
||||
|
@ -6,7 +6,7 @@ set -e
|
||||
|
||||
# modify config file to enable all daemons and copy config files
|
||||
CONFIG_FILE=/etc/frr/daemons
|
||||
DAEMONS=("zebra" "bgpd" "ospfd" "ospf6d" "ripd" "ripngd" "isisd" "pimd")
|
||||
DAEMONS=("zebra" "bgpd" "ospfd" "ospf6d" "ripd" "ripngd" "isisd" "pimd" "fabricd")
|
||||
|
||||
for daemon in "${DAEMONS[@]}"
|
||||
do
|
||||
|
@ -44,8 +44,7 @@ Add packages:
|
||||
|
||||
sudo yum install git autoconf automake libtool make gawk \
|
||||
readline-devel texinfo net-snmp-devel groff pkgconfig \
|
||||
json-c-devel pam-devel flex epel-release perl-XML-LibXML \
|
||||
c-ares-devel
|
||||
json-c-devel pam-devel flex epel-release c-ares-devel
|
||||
|
||||
Install newer version of bison (CentOS 6 package source is too old) from CentOS
|
||||
7:
|
||||
@ -154,19 +153,12 @@ an example.)
|
||||
--disable-pimd \
|
||||
--enable-snmp=agentx \
|
||||
--enable-multipath=64 \
|
||||
--enable-ospfclient=yes \
|
||||
--enable-ospfapi=yes \
|
||||
--enable-user=frr \
|
||||
--enable-group=frr \
|
||||
--enable-vty-group=frrvty \
|
||||
--enable-rtadv \
|
||||
--disable-exampledir \
|
||||
--enable-watchfrr \
|
||||
--disable-ldpd \
|
||||
--enable-fpm \
|
||||
--enable-nhrpd \
|
||||
--enable-eigrpd \
|
||||
--enable-babeld \
|
||||
--with-pkg-git-version \
|
||||
--with-pkg-extra-version=-MyOwnFRRVersion \
|
||||
SPHINXBUILD=sphinx-build2.7
|
||||
|
@ -22,7 +22,7 @@ Add packages:
|
||||
sudo yum install git autoconf automake libtool make gawk \
|
||||
readline-devel texinfo net-snmp-devel groff pkgconfig \
|
||||
json-c-devel pam-devel bison flex pytest c-ares-devel \
|
||||
perl-XML-LibXML python-devel systemd-devel python-sphinx
|
||||
python-devel systemd-devel python-sphinx
|
||||
|
||||
Get FRR, compile it and install it (from Git)
|
||||
---------------------------------------------
|
||||
@ -59,23 +59,15 @@ an example.)
|
||||
--libexecdir=/usr/lib/frr \
|
||||
--localstatedir=/var/run/frr \
|
||||
--with-moduledir=/usr/lib/frr/modules \
|
||||
--enable-pimd \
|
||||
--enable-snmp=agentx \
|
||||
--enable-multipath=64 \
|
||||
--enable-ospfclient=yes \
|
||||
--enable-ospfapi=yes \
|
||||
--enable-user=frr \
|
||||
--enable-group=frr \
|
||||
--enable-vty-group=frrvty \
|
||||
--enable-rtadv \
|
||||
--enable-systemd=yes \
|
||||
--disable-exampledir \
|
||||
--enable-watchfrr \
|
||||
--disable-ldpd \
|
||||
--enable-fpm \
|
||||
--enable-nhrpd \
|
||||
--enable-eigrpd \
|
||||
--enable-babeld \
|
||||
--with-pkg-git-version \
|
||||
--with-pkg-extra-version=-MyOwnFRRVersion
|
||||
make
|
||||
|
@ -58,21 +58,13 @@ an example.)
|
||||
--localstatedir=/var/run/frr \
|
||||
--sbindir=/usr/lib/frr \
|
||||
--sysconfdir=/etc/frr \
|
||||
--enable-vtysh \
|
||||
--enable-isisd \
|
||||
--enable-pimd \
|
||||
--enable-watchfrr \
|
||||
--enable-ospfclient=yes \
|
||||
--enable-ospfapi=yes \
|
||||
--enable-multipath=64 \
|
||||
--enable-user=frr \
|
||||
--enable-group=frr \
|
||||
--enable-vty-group=frrvty \
|
||||
--enable-configfile-mask=0640 \
|
||||
--enable-logfile-mask=0640 \
|
||||
--enable-rtadv \
|
||||
--enable-fpm \
|
||||
--enable-ldpd \
|
||||
--with-pkg-git-version \
|
||||
--with-pkg-extra-version=-MyOwnFRRVersion
|
||||
make
|
||||
|
@ -39,28 +39,19 @@ an example.)
|
||||
|
||||
git clone https://github.com/frrouting/frr.git frr
|
||||
cd frr
|
||||
git checkout stable/3.0
|
||||
./bootstrap.sh
|
||||
./configure \
|
||||
--enable-exampledir=/usr/share/doc/frr/examples/ \
|
||||
--localstatedir=/var/opt/frr \
|
||||
--sbindir=/usr/lib/frr \
|
||||
--sysconfdir=/etc/frr \
|
||||
--enable-vtysh \
|
||||
--enable-isisd \
|
||||
--enable-pimd \
|
||||
--enable-watchfrr \
|
||||
--enable-ospfclient=yes \
|
||||
--enable-ospfapi=yes \
|
||||
--enable-multipath=64 \
|
||||
--enable-user=frr \
|
||||
--enable-group=frr \
|
||||
--enable-vty-group=frrvty \
|
||||
--enable-configfile-mask=0640 \
|
||||
--enable-logfile-mask=0640 \
|
||||
--enable-rtadv \
|
||||
--enable-fpm \
|
||||
--enable-ldpd \
|
||||
--with-pkg-git-version \
|
||||
--with-pkg-extra-version=-MyOwnFRRVersion
|
||||
make
|
||||
|
@ -14,8 +14,8 @@ Add packages:
|
||||
|
||||
sudo dnf install git autoconf automake libtool make gawk \
|
||||
readline-devel texinfo net-snmp-devel groff pkgconfig \
|
||||
json-c-devel pam-devel perl-XML-LibXML pytest bison flex \
|
||||
c-ares-devel python3-devel python3-sphinx
|
||||
json-c-devel pam-devel pytest bison flex c-ares-devel \
|
||||
python3-devel python3-sphinx
|
||||
|
||||
Get FRR, compile it and install it (from Git)
|
||||
---------------------------------------------
|
||||
@ -52,22 +52,13 @@ an example.)
|
||||
--libexecdir=/usr/lib/frr \
|
||||
--localstatedir=/var/run/frr \
|
||||
--with-moduledir=/usr/lib/frr/modules \
|
||||
--enable-pimd \
|
||||
--enable-snmp=agentx \
|
||||
--enable-multipath=64 \
|
||||
--enable-ospfclient=yes \
|
||||
--enable-ospfapi=yes \
|
||||
--enable-user=frr \
|
||||
--enable-group=frr \
|
||||
--enable-vty-group=frrvty \
|
||||
--enable-rtadv \
|
||||
--disable-exampledir \
|
||||
--enable-watchfrr \
|
||||
--enable-ldpd \
|
||||
--enable-fpm \
|
||||
--enable-nhrpd \
|
||||
--enable-eigrpd \
|
||||
--enable-babeld \
|
||||
--with-pkg-git-version \
|
||||
--with-pkg-extra-version=-MyOwnFRRVersion
|
||||
make
|
||||
|
@ -59,15 +59,12 @@ an example)
|
||||
--enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \
|
||||
--localstatedir=/var/run/frr \
|
||||
--prefix=/usr/local \
|
||||
--enable-ospfclient=yes \
|
||||
--enable-ospfapi=yes \
|
||||
--enable-multipath=64 \
|
||||
--enable-user=frr \
|
||||
--enable-group=frr \
|
||||
--enable-vty-group=frrvty \
|
||||
--enable-configfile-mask=0640 \
|
||||
--enable-logfile-mask=0640 \
|
||||
--enable-rtadv \
|
||||
--enable-fpm \
|
||||
--with-pkg-git-version \
|
||||
--with-pkg-extra-version=-MyOwnFRRVersion
|
||||
|
@ -64,15 +64,12 @@ an example)
|
||||
--enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \
|
||||
--localstatedir=/var/run/frr \
|
||||
--prefix=/usr/local \
|
||||
--enable-ospfclient=yes \
|
||||
--enable-ospfapi=yes \
|
||||
--enable-multipath=64 \
|
||||
--enable-user=frr \
|
||||
--enable-group=frr \
|
||||
--enable-vty-group=frrvty \
|
||||
--enable-configfile-mask=0640 \
|
||||
--enable-logfile-mask=0640 \
|
||||
--enable-rtadv \
|
||||
--enable-fpm \
|
||||
--with-pkg-git-version \
|
||||
--with-pkg-extra-version=-MyOwnFRRVersion
|
||||
|
@ -72,15 +72,12 @@ an example)
|
||||
--enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \
|
||||
--localstatedir=/var/run/frr \
|
||||
--prefix=/usr/local \
|
||||
--enable-ospfclient=yes \
|
||||
--enable-ospfapi=yes \
|
||||
--enable-multipath=64 \
|
||||
--enable-user=frr \
|
||||
--enable-group=frr \
|
||||
--enable-vty-group=frrvty \
|
||||
--enable-configfile-mask=0640 \
|
||||
--enable-logfile-mask=0640 \
|
||||
--enable-rtadv \
|
||||
--enable-fpm \
|
||||
--with-pkg-git-version \
|
||||
--with-pkg-extra-version=-MyOwnFRRVersion
|
||||
|
@ -72,15 +72,12 @@ an example)
|
||||
--enable-exampledir=/usr/pkg/share/examples/frr \
|
||||
--enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \
|
||||
--localstatedir=/var/run/frr \
|
||||
--enable-ospfclient=yes \
|
||||
--enable-ospfapi=yes \
|
||||
--enable-multipath=64 \
|
||||
--enable-user=frr \
|
||||
--enable-group=frr \
|
||||
--enable-vty-group=frrvty \
|
||||
--enable-configfile-mask=0640 \
|
||||
--enable-logfile-mask=0640 \
|
||||
--enable-rtadv \
|
||||
--enable-fpm \
|
||||
--with-pkg-git-version \
|
||||
--with-pkg-extra-version=-MyOwnFRRVersion
|
||||
|
@ -63,15 +63,12 @@ an example)
|
||||
--enable-exampledir=/usr/pkg/share/examples/frr \
|
||||
--enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \
|
||||
--localstatedir=/var/run/frr \
|
||||
--enable-ospfclient=yes \
|
||||
--enable-ospfapi=yes \
|
||||
--enable-multipath=64 \
|
||||
--enable-user=frr \
|
||||
--enable-group=frr \
|
||||
--enable-vty-group=frrvty \
|
||||
--enable-configfile-mask=0640 \
|
||||
--enable-logfile-mask=0640 \
|
||||
--enable-rtadv \
|
||||
--enable-fpm \
|
||||
--with-pkg-git-version \
|
||||
--with-pkg-extra-version=-MyOwnFRRVersion
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user