mirror of
https://git.proxmox.com/git/mirror_frr
synced 2026-01-08 20:56:22 +00:00
*: reindent
indent.py `git ls-files | pcregrep '\.[ch]$' | pcregrep -v '^(ldpd|babeld|nhrpd)/'` Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
parent
888ac268a0
commit
d62a17aede
@ -43,249 +43,227 @@
|
||||
/* BGP advertise attribute is used for pack same attribute update into
|
||||
one packet. To do that we maintain attribute hash in struct
|
||||
peer. */
|
||||
struct bgp_advertise_attr *
|
||||
baa_new (void)
|
||||
struct bgp_advertise_attr *baa_new(void)
|
||||
{
|
||||
return (struct bgp_advertise_attr *)
|
||||
XCALLOC (MTYPE_BGP_ADVERTISE_ATTR, sizeof (struct bgp_advertise_attr));
|
||||
return (struct bgp_advertise_attr *)XCALLOC(
|
||||
MTYPE_BGP_ADVERTISE_ATTR, sizeof(struct bgp_advertise_attr));
|
||||
}
|
||||
|
||||
static void
|
||||
baa_free (struct bgp_advertise_attr *baa)
|
||||
static void baa_free(struct bgp_advertise_attr *baa)
|
||||
{
|
||||
XFREE (MTYPE_BGP_ADVERTISE_ATTR, baa);
|
||||
XFREE(MTYPE_BGP_ADVERTISE_ATTR, baa);
|
||||
}
|
||||
|
||||
static void *
|
||||
baa_hash_alloc (void *p)
|
||||
static void *baa_hash_alloc(void *p)
|
||||
{
|
||||
struct bgp_advertise_attr * ref = (struct bgp_advertise_attr *) p;
|
||||
struct bgp_advertise_attr *baa;
|
||||
struct bgp_advertise_attr *ref = (struct bgp_advertise_attr *)p;
|
||||
struct bgp_advertise_attr *baa;
|
||||
|
||||
baa = baa_new ();
|
||||
baa->attr = ref->attr;
|
||||
return baa;
|
||||
baa = baa_new();
|
||||
baa->attr = ref->attr;
|
||||
return baa;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
baa_hash_key (void *p)
|
||||
unsigned int baa_hash_key(void *p)
|
||||
{
|
||||
struct bgp_advertise_attr * baa = (struct bgp_advertise_attr *) p;
|
||||
struct bgp_advertise_attr *baa = (struct bgp_advertise_attr *)p;
|
||||
|
||||
return attrhash_key_make (baa->attr);
|
||||
return attrhash_key_make(baa->attr);
|
||||
}
|
||||
|
||||
int
|
||||
baa_hash_cmp (const void *p1, const void *p2)
|
||||
int baa_hash_cmp(const void *p1, const void *p2)
|
||||
{
|
||||
const struct bgp_advertise_attr * baa1 = p1;
|
||||
const struct bgp_advertise_attr * baa2 = p2;
|
||||
const struct bgp_advertise_attr *baa1 = p1;
|
||||
const struct bgp_advertise_attr *baa2 = p2;
|
||||
|
||||
return attrhash_cmp (baa1->attr, baa2->attr);
|
||||
return attrhash_cmp(baa1->attr, baa2->attr);
|
||||
}
|
||||
|
||||
/* BGP update and withdraw information is stored in BGP advertise
|
||||
structure. This structure is referred from BGP adjacency
|
||||
information. */
|
||||
struct bgp_advertise *
|
||||
bgp_advertise_new (void)
|
||||
struct bgp_advertise *bgp_advertise_new(void)
|
||||
{
|
||||
return (struct bgp_advertise *)
|
||||
XCALLOC (MTYPE_BGP_ADVERTISE, sizeof (struct bgp_advertise));
|
||||
return (struct bgp_advertise *)XCALLOC(MTYPE_BGP_ADVERTISE,
|
||||
sizeof(struct bgp_advertise));
|
||||
}
|
||||
|
||||
void
|
||||
bgp_advertise_free (struct bgp_advertise *adv)
|
||||
void bgp_advertise_free(struct bgp_advertise *adv)
|
||||
{
|
||||
if (adv->binfo)
|
||||
bgp_info_unlock (adv->binfo); /* bgp_advertise bgp_info reference */
|
||||
XFREE (MTYPE_BGP_ADVERTISE, adv);
|
||||
if (adv->binfo)
|
||||
bgp_info_unlock(
|
||||
adv->binfo); /* bgp_advertise bgp_info reference */
|
||||
XFREE(MTYPE_BGP_ADVERTISE, adv);
|
||||
}
|
||||
|
||||
void
|
||||
bgp_advertise_add (struct bgp_advertise_attr *baa,
|
||||
struct bgp_advertise *adv)
|
||||
void bgp_advertise_add(struct bgp_advertise_attr *baa,
|
||||
struct bgp_advertise *adv)
|
||||
{
|
||||
adv->next = baa->adv;
|
||||
if (baa->adv)
|
||||
baa->adv->prev = adv;
|
||||
baa->adv = adv;
|
||||
adv->next = baa->adv;
|
||||
if (baa->adv)
|
||||
baa->adv->prev = adv;
|
||||
baa->adv = adv;
|
||||
}
|
||||
|
||||
void
|
||||
bgp_advertise_delete (struct bgp_advertise_attr *baa,
|
||||
struct bgp_advertise *adv)
|
||||
void bgp_advertise_delete(struct bgp_advertise_attr *baa,
|
||||
struct bgp_advertise *adv)
|
||||
{
|
||||
if (adv->next)
|
||||
adv->next->prev = adv->prev;
|
||||
if (adv->prev)
|
||||
adv->prev->next = adv->next;
|
||||
else
|
||||
baa->adv = adv->next;
|
||||
if (adv->next)
|
||||
adv->next->prev = adv->prev;
|
||||
if (adv->prev)
|
||||
adv->prev->next = adv->next;
|
||||
else
|
||||
baa->adv = adv->next;
|
||||
}
|
||||
|
||||
struct bgp_advertise_attr *
|
||||
bgp_advertise_intern (struct hash *hash, struct attr *attr)
|
||||
struct bgp_advertise_attr *bgp_advertise_intern(struct hash *hash,
|
||||
struct attr *attr)
|
||||
{
|
||||
struct bgp_advertise_attr ref;
|
||||
struct bgp_advertise_attr *baa;
|
||||
struct bgp_advertise_attr ref;
|
||||
struct bgp_advertise_attr *baa;
|
||||
|
||||
ref.attr = bgp_attr_intern (attr);
|
||||
baa = (struct bgp_advertise_attr *) hash_get (hash, &ref, baa_hash_alloc);
|
||||
baa->refcnt++;
|
||||
ref.attr = bgp_attr_intern(attr);
|
||||
baa = (struct bgp_advertise_attr *)hash_get(hash, &ref, baa_hash_alloc);
|
||||
baa->refcnt++;
|
||||
|
||||
return baa;
|
||||
return baa;
|
||||
}
|
||||
|
||||
void
|
||||
bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa)
|
||||
void bgp_advertise_unintern(struct hash *hash, struct bgp_advertise_attr *baa)
|
||||
{
|
||||
if (baa->refcnt)
|
||||
baa->refcnt--;
|
||||
if (baa->refcnt)
|
||||
baa->refcnt--;
|
||||
|
||||
if (baa->refcnt && baa->attr)
|
||||
bgp_attr_unintern (&baa->attr);
|
||||
else
|
||||
{
|
||||
if (baa->attr)
|
||||
{
|
||||
hash_release (hash, baa);
|
||||
bgp_attr_unintern (&baa->attr);
|
||||
if (baa->refcnt && baa->attr)
|
||||
bgp_attr_unintern(&baa->attr);
|
||||
else {
|
||||
if (baa->attr) {
|
||||
hash_release(hash, baa);
|
||||
bgp_attr_unintern(&baa->attr);
|
||||
}
|
||||
baa_free(baa);
|
||||
}
|
||||
baa_free (baa);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
bgp_adj_out_lookup (struct peer *peer, struct bgp_node *rn,
|
||||
u_int32_t addpath_tx_id)
|
||||
int bgp_adj_out_lookup(struct peer *peer, struct bgp_node *rn,
|
||||
u_int32_t addpath_tx_id)
|
||||
{
|
||||
struct bgp_adj_out *adj;
|
||||
struct peer_af *paf;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
int addpath_capable;
|
||||
struct bgp_adj_out *adj;
|
||||
struct peer_af *paf;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
int addpath_capable;
|
||||
|
||||
for (adj = rn->adj_out; adj; adj = adj->next)
|
||||
SUBGRP_FOREACH_PEER(adj->subgroup, paf)
|
||||
if (paf->peer == peer)
|
||||
{
|
||||
afi = SUBGRP_AFI (adj->subgroup);
|
||||
safi = SUBGRP_SAFI (adj->subgroup);
|
||||
addpath_capable = bgp_addpath_encode_tx (peer, afi, safi);
|
||||
for (adj = rn->adj_out; adj; adj = adj->next)
|
||||
SUBGRP_FOREACH_PEER(adj->subgroup, paf)
|
||||
if (paf->peer == peer) {
|
||||
afi = SUBGRP_AFI(adj->subgroup);
|
||||
safi = SUBGRP_SAFI(adj->subgroup);
|
||||
addpath_capable = bgp_addpath_encode_tx(peer, afi, safi);
|
||||
|
||||
/* Match on a specific addpath_tx_id if we are using addpath for this
|
||||
* peer and if an addpath_tx_id was specified */
|
||||
if (addpath_capable && addpath_tx_id && adj->addpath_tx_id != addpath_tx_id)
|
||||
continue;
|
||||
/* Match on a specific addpath_tx_id if we are using addpath for
|
||||
* this
|
||||
* peer and if an addpath_tx_id was specified */
|
||||
if (addpath_capable && addpath_tx_id
|
||||
&& adj->addpath_tx_id != addpath_tx_id)
|
||||
continue;
|
||||
|
||||
return (adj->adv
|
||||
? (adj->adv->baa ? 1 : 0)
|
||||
: (adj->attr ? 1 : 0));
|
||||
return (adj->adv ? (adj->adv->baa ? 1 : 0)
|
||||
: (adj->attr ? 1 : 0));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr,
|
||||
u_int32_t addpath_id)
|
||||
void bgp_adj_in_set(struct bgp_node *rn, struct peer *peer, struct attr *attr,
|
||||
u_int32_t addpath_id)
|
||||
{
|
||||
struct bgp_adj_in *adj;
|
||||
struct bgp_adj_in *adj;
|
||||
|
||||
for (adj = rn->adj_in; adj; adj = adj->next)
|
||||
{
|
||||
if (adj->peer == peer && adj->addpath_rx_id == addpath_id)
|
||||
{
|
||||
if (adj->attr != attr)
|
||||
{
|
||||
bgp_attr_unintern (&adj->attr);
|
||||
adj->attr = bgp_attr_intern (attr);
|
||||
}
|
||||
return;
|
||||
for (adj = rn->adj_in; adj; adj = adj->next) {
|
||||
if (adj->peer == peer && adj->addpath_rx_id == addpath_id) {
|
||||
if (adj->attr != attr) {
|
||||
bgp_attr_unintern(&adj->attr);
|
||||
adj->attr = bgp_attr_intern(attr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
adj = XCALLOC (MTYPE_BGP_ADJ_IN, sizeof (struct bgp_adj_in));
|
||||
adj->peer = peer_lock (peer); /* adj_in peer reference */
|
||||
adj->attr = bgp_attr_intern (attr);
|
||||
adj->addpath_rx_id = addpath_id;
|
||||
BGP_ADJ_IN_ADD (rn, adj);
|
||||
bgp_lock_node (rn);
|
||||
adj = XCALLOC(MTYPE_BGP_ADJ_IN, sizeof(struct bgp_adj_in));
|
||||
adj->peer = peer_lock(peer); /* adj_in peer reference */
|
||||
adj->attr = bgp_attr_intern(attr);
|
||||
adj->addpath_rx_id = addpath_id;
|
||||
BGP_ADJ_IN_ADD(rn, adj);
|
||||
bgp_lock_node(rn);
|
||||
}
|
||||
|
||||
void
|
||||
bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
|
||||
void bgp_adj_in_remove(struct bgp_node *rn, struct bgp_adj_in *bai)
|
||||
{
|
||||
bgp_attr_unintern (&bai->attr);
|
||||
BGP_ADJ_IN_DEL (rn, bai);
|
||||
peer_unlock (bai->peer); /* adj_in peer reference */
|
||||
XFREE (MTYPE_BGP_ADJ_IN, bai);
|
||||
bgp_attr_unintern(&bai->attr);
|
||||
BGP_ADJ_IN_DEL(rn, bai);
|
||||
peer_unlock(bai->peer); /* adj_in peer reference */
|
||||
XFREE(MTYPE_BGP_ADJ_IN, bai);
|
||||
}
|
||||
|
||||
int
|
||||
bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer,
|
||||
u_int32_t addpath_id)
|
||||
int bgp_adj_in_unset(struct bgp_node *rn, struct peer *peer,
|
||||
u_int32_t addpath_id)
|
||||
{
|
||||
struct bgp_adj_in *adj;
|
||||
struct bgp_adj_in *adj_next;
|
||||
struct bgp_adj_in *adj;
|
||||
struct bgp_adj_in *adj_next;
|
||||
|
||||
adj = rn->adj_in;
|
||||
adj = rn->adj_in;
|
||||
|
||||
if (!adj)
|
||||
return 0;
|
||||
if (!adj)
|
||||
return 0;
|
||||
|
||||
while (adj)
|
||||
{
|
||||
adj_next = adj->next;
|
||||
while (adj) {
|
||||
adj_next = adj->next;
|
||||
|
||||
if (adj->peer == peer && adj->addpath_rx_id == addpath_id)
|
||||
{
|
||||
bgp_adj_in_remove (rn, adj);
|
||||
bgp_unlock_node (rn);
|
||||
}
|
||||
if (adj->peer == peer && adj->addpath_rx_id == addpath_id) {
|
||||
bgp_adj_in_remove(rn, adj);
|
||||
bgp_unlock_node(rn);
|
||||
}
|
||||
|
||||
adj = adj_next;
|
||||
}
|
||||
adj = adj_next;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
bgp_sync_init (struct peer *peer)
|
||||
void bgp_sync_init(struct peer *peer)
|
||||
{
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
struct bgp_synchronize *sync;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
struct bgp_synchronize *sync;
|
||||
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
|
||||
{
|
||||
sync = XCALLOC (MTYPE_BGP_SYNCHRONISE,
|
||||
sizeof (struct bgp_synchronize));
|
||||
BGP_ADV_FIFO_INIT (&sync->update);
|
||||
BGP_ADV_FIFO_INIT (&sync->withdraw);
|
||||
BGP_ADV_FIFO_INIT (&sync->withdraw_low);
|
||||
peer->sync[afi][safi] = sync;
|
||||
peer->hash[afi][safi] = hash_create (baa_hash_key, baa_hash_cmp, NULL);
|
||||
}
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
|
||||
sync = XCALLOC(MTYPE_BGP_SYNCHRONISE,
|
||||
sizeof(struct bgp_synchronize));
|
||||
BGP_ADV_FIFO_INIT(&sync->update);
|
||||
BGP_ADV_FIFO_INIT(&sync->withdraw);
|
||||
BGP_ADV_FIFO_INIT(&sync->withdraw_low);
|
||||
peer->sync[afi][safi] = sync;
|
||||
peer->hash[afi][safi] =
|
||||
hash_create(baa_hash_key, baa_hash_cmp, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bgp_sync_delete (struct peer *peer)
|
||||
void bgp_sync_delete(struct peer *peer)
|
||||
{
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
|
||||
{
|
||||
if (peer->sync[afi][safi])
|
||||
XFREE (MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]);
|
||||
peer->sync[afi][safi] = NULL;
|
||||
|
||||
if (peer->hash[afi][safi])
|
||||
hash_free (peer->hash[afi][safi]);
|
||||
peer->hash[afi][safi] = NULL;
|
||||
}
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
|
||||
if (peer->sync[afi][safi])
|
||||
XFREE(MTYPE_BGP_SYNCHRONISE,
|
||||
peer->sync[afi][safi]);
|
||||
peer->sync[afi][safi] = NULL;
|
||||
|
||||
if (peer->hash[afi][safi])
|
||||
hash_free(peer->hash[afi][safi]);
|
||||
peer->hash[afi][safi] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,172 +26,168 @@
|
||||
struct update_subgroup;
|
||||
|
||||
/* BGP advertise FIFO. */
|
||||
struct bgp_advertise_fifo
|
||||
{
|
||||
struct bgp_advertise *next;
|
||||
struct bgp_advertise *prev;
|
||||
u_int32_t count;
|
||||
struct bgp_advertise_fifo {
|
||||
struct bgp_advertise *next;
|
||||
struct bgp_advertise *prev;
|
||||
u_int32_t count;
|
||||
};
|
||||
|
||||
/* BGP advertise attribute. */
|
||||
struct bgp_advertise_attr
|
||||
{
|
||||
/* Head of advertisement pointer. */
|
||||
struct bgp_advertise *adv;
|
||||
struct bgp_advertise_attr {
|
||||
/* Head of advertisement pointer. */
|
||||
struct bgp_advertise *adv;
|
||||
|
||||
/* Reference counter. */
|
||||
unsigned long refcnt;
|
||||
/* Reference counter. */
|
||||
unsigned long refcnt;
|
||||
|
||||
/* Attribute pointer to be announced. */
|
||||
struct attr *attr;
|
||||
/* Attribute pointer to be announced. */
|
||||
struct attr *attr;
|
||||
};
|
||||
|
||||
struct bgp_advertise
|
||||
{
|
||||
/* FIFO for advertisement. */
|
||||
struct bgp_advertise_fifo fifo;
|
||||
struct bgp_advertise {
|
||||
/* FIFO for advertisement. */
|
||||
struct bgp_advertise_fifo fifo;
|
||||
|
||||
/* Link list for same attribute advertise. */
|
||||
struct bgp_advertise *next;
|
||||
struct bgp_advertise *prev;
|
||||
/* Link list for same attribute advertise. */
|
||||
struct bgp_advertise *next;
|
||||
struct bgp_advertise *prev;
|
||||
|
||||
/* Prefix information. */
|
||||
struct bgp_node *rn;
|
||||
/* Prefix information. */
|
||||
struct bgp_node *rn;
|
||||
|
||||
/* Reference pointer. */
|
||||
struct bgp_adj_out *adj;
|
||||
/* Reference pointer. */
|
||||
struct bgp_adj_out *adj;
|
||||
|
||||
/* Advertisement attribute. */
|
||||
struct bgp_advertise_attr *baa;
|
||||
/* Advertisement attribute. */
|
||||
struct bgp_advertise_attr *baa;
|
||||
|
||||
/* BGP info. */
|
||||
struct bgp_info *binfo;
|
||||
/* BGP info. */
|
||||
struct bgp_info *binfo;
|
||||
};
|
||||
|
||||
/* BGP adjacency out. */
|
||||
struct bgp_adj_out
|
||||
{
|
||||
/* Lined list pointer. */
|
||||
struct bgp_adj_out *next;
|
||||
struct bgp_adj_out *prev;
|
||||
struct bgp_adj_out {
|
||||
/* Lined list pointer. */
|
||||
struct bgp_adj_out *next;
|
||||
struct bgp_adj_out *prev;
|
||||
|
||||
/* Advertised subgroup. */
|
||||
struct update_subgroup *subgroup;
|
||||
/* Advertised subgroup. */
|
||||
struct update_subgroup *subgroup;
|
||||
|
||||
/* Threading that makes the adj part of subgroup's adj queue */
|
||||
TAILQ_ENTRY(bgp_adj_out) subgrp_adj_train;
|
||||
/* Threading that makes the adj part of subgroup's adj queue */
|
||||
TAILQ_ENTRY(bgp_adj_out) subgrp_adj_train;
|
||||
|
||||
/* Prefix information. */
|
||||
struct bgp_node *rn;
|
||||
/* Prefix information. */
|
||||
struct bgp_node *rn;
|
||||
|
||||
u_int32_t addpath_tx_id;
|
||||
u_int32_t addpath_tx_id;
|
||||
|
||||
/* Advertised attribute. */
|
||||
struct attr *attr;
|
||||
/* Advertised attribute. */
|
||||
struct attr *attr;
|
||||
|
||||
/* Advertisement information. */
|
||||
struct bgp_advertise *adv;
|
||||
/* Advertisement information. */
|
||||
struct bgp_advertise *adv;
|
||||
};
|
||||
|
||||
/* BGP adjacency in. */
|
||||
struct bgp_adj_in
|
||||
{
|
||||
/* Linked list pointer. */
|
||||
struct bgp_adj_in *next;
|
||||
struct bgp_adj_in *prev;
|
||||
struct bgp_adj_in {
|
||||
/* Linked list pointer. */
|
||||
struct bgp_adj_in *next;
|
||||
struct bgp_adj_in *prev;
|
||||
|
||||
/* Received peer. */
|
||||
struct peer *peer;
|
||||
/* Received peer. */
|
||||
struct peer *peer;
|
||||
|
||||
/* Received attribute. */
|
||||
struct attr *attr;
|
||||
/* Received attribute. */
|
||||
struct attr *attr;
|
||||
|
||||
/* Addpath identifier */
|
||||
u_int32_t addpath_rx_id;
|
||||
/* Addpath identifier */
|
||||
u_int32_t addpath_rx_id;
|
||||
};
|
||||
|
||||
/* BGP advertisement list. */
|
||||
struct bgp_synchronize
|
||||
{
|
||||
struct bgp_advertise_fifo update;
|
||||
struct bgp_advertise_fifo withdraw;
|
||||
struct bgp_advertise_fifo withdraw_low;
|
||||
struct bgp_synchronize {
|
||||
struct bgp_advertise_fifo update;
|
||||
struct bgp_advertise_fifo withdraw;
|
||||
struct bgp_advertise_fifo withdraw_low;
|
||||
};
|
||||
|
||||
/* BGP adjacency linked list. */
|
||||
#define BGP_INFO_ADD(N,A,TYPE) \
|
||||
do { \
|
||||
(A)->prev = NULL; \
|
||||
(A)->next = (N)->TYPE; \
|
||||
if ((N)->TYPE) \
|
||||
(N)->TYPE->prev = (A); \
|
||||
(N)->TYPE = (A); \
|
||||
} while (0)
|
||||
#define BGP_INFO_ADD(N, A, TYPE) \
|
||||
do { \
|
||||
(A)->prev = NULL; \
|
||||
(A)->next = (N)->TYPE; \
|
||||
if ((N)->TYPE) \
|
||||
(N)->TYPE->prev = (A); \
|
||||
(N)->TYPE = (A); \
|
||||
} while (0)
|
||||
|
||||
#define BGP_INFO_DEL(N,A,TYPE) \
|
||||
do { \
|
||||
if ((A)->next) \
|
||||
(A)->next->prev = (A)->prev; \
|
||||
if ((A)->prev) \
|
||||
(A)->prev->next = (A)->next; \
|
||||
else \
|
||||
(N)->TYPE = (A)->next; \
|
||||
} while (0)
|
||||
#define BGP_INFO_DEL(N, A, TYPE) \
|
||||
do { \
|
||||
if ((A)->next) \
|
||||
(A)->next->prev = (A)->prev; \
|
||||
if ((A)->prev) \
|
||||
(A)->prev->next = (A)->next; \
|
||||
else \
|
||||
(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_ADV_FIFO_ADD(F, N) \
|
||||
do { \
|
||||
FIFO_ADD((F), (N)); \
|
||||
(F)->count++; \
|
||||
} while (0)
|
||||
#define BGP_ADV_FIFO_ADD(F, N) \
|
||||
do { \
|
||||
FIFO_ADD((F), (N)); \
|
||||
(F)->count++; \
|
||||
} while (0)
|
||||
|
||||
#define BGP_ADV_FIFO_DEL(F, N) \
|
||||
do { \
|
||||
FIFO_DEL((N)); \
|
||||
(F)->count--; \
|
||||
} while (0)
|
||||
#define BGP_ADV_FIFO_DEL(F, N) \
|
||||
do { \
|
||||
FIFO_DEL((N)); \
|
||||
(F)->count--; \
|
||||
} while (0)
|
||||
|
||||
#define BGP_ADV_FIFO_INIT(F) \
|
||||
do { \
|
||||
FIFO_INIT((F)); \
|
||||
(F)->count = 0; \
|
||||
} while (0)
|
||||
#define BGP_ADV_FIFO_INIT(F) \
|
||||
do { \
|
||||
FIFO_INIT((F)); \
|
||||
(F)->count = 0; \
|
||||
} while (0)
|
||||
|
||||
#define BGP_ADV_FIFO_COUNT(F) \
|
||||
(F)->count
|
||||
#define BGP_ADV_FIFO_COUNT(F) (F)->count
|
||||
|
||||
#define BGP_ADV_FIFO_EMPTY(F) \
|
||||
(((struct bgp_advertise_fifo *)(F))->next == (struct bgp_advertise *)(F))
|
||||
#define BGP_ADV_FIFO_EMPTY(F) \
|
||||
(((struct bgp_advertise_fifo *)(F))->next \
|
||||
== (struct bgp_advertise *)(F))
|
||||
|
||||
#define BGP_ADV_FIFO_HEAD(F) \
|
||||
((((struct bgp_advertise_fifo *)(F))->next == (struct bgp_advertise *)(F)) \
|
||||
? NULL : (F)->next)
|
||||
#define BGP_ADV_FIFO_HEAD(F) \
|
||||
((((struct bgp_advertise_fifo *)(F))->next \
|
||||
== (struct bgp_advertise *)(F)) \
|
||||
? NULL \
|
||||
: (F)->next)
|
||||
|
||||
/* Prototypes. */
|
||||
extern int bgp_adj_out_lookup (struct peer *, struct bgp_node *, u_int32_t);
|
||||
extern void bgp_adj_in_set (struct bgp_node *, struct peer *, struct attr *, u_int32_t);
|
||||
extern int bgp_adj_in_unset (struct bgp_node *, struct peer *, u_int32_t);
|
||||
extern void bgp_adj_in_remove (struct bgp_node *, struct bgp_adj_in *);
|
||||
extern int bgp_adj_out_lookup(struct peer *, struct bgp_node *, u_int32_t);
|
||||
extern void bgp_adj_in_set(struct bgp_node *, struct peer *, struct attr *,
|
||||
u_int32_t);
|
||||
extern int bgp_adj_in_unset(struct bgp_node *, struct peer *, u_int32_t);
|
||||
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 void bgp_advertise_add (struct bgp_advertise_attr *baa,
|
||||
struct bgp_advertise *adv);
|
||||
extern struct bgp_advertise *bgp_advertise_new (void);
|
||||
extern void bgp_advertise_free (struct bgp_advertise *adv);
|
||||
extern struct bgp_advertise_attr *
|
||||
bgp_advertise_intern (struct hash *hash, struct attr *attr);
|
||||
extern struct bgp_advertise_attr *baa_new (void);
|
||||
extern void
|
||||
bgp_advertise_delete (struct bgp_advertise_attr *baa,
|
||||
struct bgp_advertise *adv);
|
||||
extern void
|
||||
bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa);
|
||||
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 void bgp_advertise_add(struct bgp_advertise_attr *baa,
|
||||
struct bgp_advertise *adv);
|
||||
extern struct bgp_advertise *bgp_advertise_new(void);
|
||||
extern void bgp_advertise_free(struct bgp_advertise *adv);
|
||||
extern struct bgp_advertise_attr *bgp_advertise_intern(struct hash *hash,
|
||||
struct attr *attr);
|
||||
extern struct bgp_advertise_attr *baa_new(void);
|
||||
extern void bgp_advertise_delete(struct bgp_advertise_attr *baa,
|
||||
struct bgp_advertise *adv);
|
||||
extern void bgp_advertise_unintern(struct hash *hash,
|
||||
struct bgp_advertise_attr *baa);
|
||||
|
||||
#endif /* _QUAGGA_BGP_ADVERTISE_H */
|
||||
|
||||
3128
bgpd/bgp_aspath.c
3128
bgpd/bgp_aspath.c
File diff suppressed because it is too large
Load Diff
@ -43,87 +43,89 @@
|
||||
/* Transition 16Bit AS as defined by IANA */
|
||||
#define BGP_AS_TRANS 23456U
|
||||
|
||||
#define BGP_AS_IS_PRIVATE(ASN) \
|
||||
(((ASN) >= BGP_PRIVATE_AS_MIN && (ASN) <= BGP_PRIVATE_AS_MAX) || \
|
||||
((ASN) >= BGP_PRIVATE_AS4_MIN && (ASN) <= BGP_PRIVATE_AS4_MAX))
|
||||
#define BGP_AS_IS_PRIVATE(ASN) \
|
||||
(((ASN) >= BGP_PRIVATE_AS_MIN && (ASN) <= BGP_PRIVATE_AS_MAX) \
|
||||
|| ((ASN) >= BGP_PRIVATE_AS4_MIN && (ASN) <= BGP_PRIVATE_AS4_MAX))
|
||||
|
||||
/* AS_PATH segment data in abstracted form, no limit is placed on length */
|
||||
struct assegment
|
||||
{
|
||||
struct assegment *next;
|
||||
as_t *as;
|
||||
u_short length;
|
||||
u_char type;
|
||||
struct assegment {
|
||||
struct assegment *next;
|
||||
as_t *as;
|
||||
u_short length;
|
||||
u_char type;
|
||||
};
|
||||
|
||||
/* AS path may be include some AsSegments. */
|
||||
struct aspath
|
||||
{
|
||||
/* Reference count to this aspath. */
|
||||
unsigned long refcnt;
|
||||
struct aspath {
|
||||
/* Reference count to this aspath. */
|
||||
unsigned long refcnt;
|
||||
|
||||
/* segment data */
|
||||
struct assegment *segments;
|
||||
|
||||
/* AS path as a json object */
|
||||
json_object *json;
|
||||
/* segment data */
|
||||
struct assegment *segments;
|
||||
|
||||
/* String expression of AS path. This string is used by vty output
|
||||
and AS path regular expression match. */
|
||||
char *str;
|
||||
unsigned short str_len;
|
||||
/* AS path as a json object */
|
||||
json_object *json;
|
||||
|
||||
/* String expression of AS path. This string is used by vty output
|
||||
and AS path regular expression match. */
|
||||
char *str;
|
||||
unsigned short str_len;
|
||||
};
|
||||
|
||||
#define ASPATH_STR_DEFAULT_LEN 32
|
||||
|
||||
/* Prototypes. */
|
||||
extern void aspath_init (void);
|
||||
extern void aspath_finish (void);
|
||||
extern struct aspath *aspath_parse (struct stream *, size_t, int);
|
||||
extern struct aspath *aspath_dup (struct aspath *);
|
||||
extern struct aspath *aspath_aggregate (struct aspath *, struct aspath *);
|
||||
extern struct aspath *aspath_prepend (struct aspath *, struct aspath *);
|
||||
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 int aspath_cmp_left (const struct aspath *, const struct aspath *);
|
||||
extern int aspath_cmp_left_confed (const struct aspath *, const struct aspath *);
|
||||
extern struct aspath *aspath_delete_confed_seq (struct aspath *);
|
||||
extern struct aspath *aspath_empty (void);
|
||||
extern struct aspath *aspath_empty_get (void);
|
||||
extern struct aspath *aspath_str2aspath (const char *);
|
||||
extern void aspath_free (struct aspath *);
|
||||
extern struct aspath *aspath_intern (struct aspath *);
|
||||
extern void aspath_unintern (struct aspath **);
|
||||
extern const char *aspath_print (struct aspath *);
|
||||
extern void aspath_print_vty (struct vty *, const char *, struct aspath *, const char *);
|
||||
extern void aspath_print_all_vty (struct vty *);
|
||||
extern unsigned int aspath_key_make (void *);
|
||||
extern unsigned int aspath_get_first_as (struct aspath *);
|
||||
extern unsigned int aspath_get_last_as (struct aspath *);
|
||||
extern int aspath_loop_check (struct aspath *, as_t);
|
||||
extern int aspath_private_as_check (struct aspath *);
|
||||
extern int aspath_single_asn_check (struct aspath *, as_t asn);
|
||||
extern struct aspath *aspath_replace_specific_asn (struct aspath *aspath, as_t target_asn, as_t our_asn);
|
||||
extern struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn);
|
||||
extern struct aspath *aspath_remove_private_asns (struct aspath *aspath);
|
||||
extern int aspath_firstas_check (struct aspath *, as_t);
|
||||
extern int aspath_confed_check (struct aspath *);
|
||||
extern int aspath_left_confed_check (struct aspath *);
|
||||
extern unsigned long aspath_count (void);
|
||||
extern unsigned int aspath_count_hops (const struct aspath *);
|
||||
extern unsigned int aspath_count_confeds (struct aspath *);
|
||||
extern unsigned int aspath_size (struct aspath *);
|
||||
extern as_t aspath_highest (struct aspath *);
|
||||
extern as_t aspath_leftmost (struct aspath *);
|
||||
extern size_t aspath_put (struct stream *, struct aspath *, int);
|
||||
extern void aspath_init(void);
|
||||
extern void aspath_finish(void);
|
||||
extern struct aspath *aspath_parse(struct stream *, size_t, int);
|
||||
extern struct aspath *aspath_dup(struct aspath *);
|
||||
extern struct aspath *aspath_aggregate(struct aspath *, struct aspath *);
|
||||
extern struct aspath *aspath_prepend(struct aspath *, struct aspath *);
|
||||
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 int aspath_cmp_left(const struct aspath *, const struct aspath *);
|
||||
extern int aspath_cmp_left_confed(const struct aspath *, const struct aspath *);
|
||||
extern struct aspath *aspath_delete_confed_seq(struct aspath *);
|
||||
extern struct aspath *aspath_empty(void);
|
||||
extern struct aspath *aspath_empty_get(void);
|
||||
extern struct aspath *aspath_str2aspath(const char *);
|
||||
extern void aspath_free(struct aspath *);
|
||||
extern struct aspath *aspath_intern(struct aspath *);
|
||||
extern void aspath_unintern(struct aspath **);
|
||||
extern const char *aspath_print(struct aspath *);
|
||||
extern void aspath_print_vty(struct vty *, const char *, struct aspath *,
|
||||
const char *);
|
||||
extern void aspath_print_all_vty(struct vty *);
|
||||
extern unsigned int aspath_key_make(void *);
|
||||
extern unsigned int aspath_get_first_as(struct aspath *);
|
||||
extern unsigned int aspath_get_last_as(struct aspath *);
|
||||
extern int aspath_loop_check(struct aspath *, as_t);
|
||||
extern int aspath_private_as_check(struct aspath *);
|
||||
extern int aspath_single_asn_check(struct aspath *, as_t asn);
|
||||
extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
|
||||
as_t target_asn,
|
||||
as_t our_asn);
|
||||
extern struct aspath *aspath_replace_private_asns(struct aspath *aspath,
|
||||
as_t asn);
|
||||
extern struct aspath *aspath_remove_private_asns(struct aspath *aspath);
|
||||
extern int aspath_firstas_check(struct aspath *, as_t);
|
||||
extern int aspath_confed_check(struct aspath *);
|
||||
extern int aspath_left_confed_check(struct aspath *);
|
||||
extern unsigned long aspath_count(void);
|
||||
extern unsigned int aspath_count_hops(const struct aspath *);
|
||||
extern unsigned int aspath_count_confeds(struct aspath *);
|
||||
extern unsigned int aspath_size(struct aspath *);
|
||||
extern as_t aspath_highest(struct aspath *);
|
||||
extern as_t aspath_leftmost(struct aspath *);
|
||||
extern size_t aspath_put(struct stream *, struct aspath *, int);
|
||||
|
||||
extern struct aspath *aspath_reconcile_as4 (struct aspath *, struct aspath *);
|
||||
extern unsigned int aspath_has_as4 (struct aspath *);
|
||||
extern struct aspath *aspath_reconcile_as4(struct aspath *, struct aspath *);
|
||||
extern unsigned int aspath_has_as4(struct aspath *);
|
||||
|
||||
/* For SNMP BGP4PATHATTRASPATHSEGMENT, might be useful for debug */
|
||||
extern u_char *aspath_snmp_pathseg (struct aspath *, size_t *);
|
||||
extern u_char *aspath_snmp_pathseg(struct aspath *, size_t *);
|
||||
|
||||
#endif /* _QUAGGA_BGP_ASPATH_H */
|
||||
|
||||
5617
bgpd/bgp_attr.c
5617
bgpd/bgp_attr.c
File diff suppressed because it is too large
Load Diff
348
bgpd/bgp_attr.h
348
bgpd/bgp_attr.h
@ -1,4 +1,4 @@
|
||||
/* BGP attributes.
|
||||
/* BGP attributes.
|
||||
* Copyright (C) 1996, 97, 98 Kunihiro Ishiguro
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
@ -27,15 +27,14 @@
|
||||
/* Simple bit mapping. */
|
||||
#define BITMAP_NBBY 8
|
||||
|
||||
#define SET_BITMAP(MAP, NUM) \
|
||||
SET_FLAG (MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY))
|
||||
#define SET_BITMAP(MAP, NUM) \
|
||||
SET_FLAG(MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY))
|
||||
|
||||
#define CHECK_BITMAP(MAP, NUM) \
|
||||
CHECK_FLAG (MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY))
|
||||
#define CHECK_BITMAP(MAP, NUM) \
|
||||
CHECK_FLAG(MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY))
|
||||
|
||||
#define BGP_MED_MAX UINT32_MAX
|
||||
|
||||
|
||||
/* BGP Attribute type range. */
|
||||
#define BGP_ATTR_TYPE_RANGE 256
|
||||
#define BGP_ATTR_BITMAP_SIZE (BGP_ATTR_TYPE_RANGE / BITMAP_NBBY)
|
||||
@ -68,12 +67,12 @@
|
||||
#define BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH 6
|
||||
|
||||
struct bgp_attr_encap_subtlv {
|
||||
struct bgp_attr_encap_subtlv *next; /* for chaining */
|
||||
/* Reference count of this attribute. */
|
||||
unsigned long refcnt;
|
||||
uint16_t type;
|
||||
uint16_t length;
|
||||
uint8_t value[1]; /* will be extended */
|
||||
struct bgp_attr_encap_subtlv *next; /* for chaining */
|
||||
/* Reference count of this attribute. */
|
||||
unsigned long refcnt;
|
||||
uint16_t type;
|
||||
uint16_t length;
|
||||
uint8_t value[1]; /* will be extended */
|
||||
};
|
||||
|
||||
#if ENABLE_BGP_VNC
|
||||
@ -81,110 +80,108 @@ struct bgp_attr_encap_subtlv {
|
||||
* old rfp<->rfapi representation
|
||||
*/
|
||||
struct bgp_tea_options {
|
||||
struct bgp_tea_options *next;
|
||||
uint8_t options_count;
|
||||
uint16_t options_length; /* each TLV may be 256 in length */
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
void *value; /* pointer to data */
|
||||
struct bgp_tea_options *next;
|
||||
uint8_t options_count;
|
||||
uint16_t options_length; /* each TLV may be 256 in length */
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
void *value; /* pointer to data */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* Overlay Index Info */
|
||||
struct overlay_index
|
||||
{
|
||||
struct eth_segment_id eth_s_id;
|
||||
union gw_addr gw_ip;
|
||||
struct overlay_index {
|
||||
struct eth_segment_id eth_s_id;
|
||||
union gw_addr gw_ip;
|
||||
};
|
||||
|
||||
/* BGP core attribute structure. */
|
||||
struct attr
|
||||
{
|
||||
/* AS Path structure */
|
||||
struct aspath *aspath;
|
||||
struct attr {
|
||||
/* AS Path structure */
|
||||
struct aspath *aspath;
|
||||
|
||||
/* Community structure */
|
||||
struct community *community;
|
||||
/* Community structure */
|
||||
struct community *community;
|
||||
|
||||
/* Reference count of this attribute. */
|
||||
unsigned long refcnt;
|
||||
/* Reference count of this attribute. */
|
||||
unsigned long refcnt;
|
||||
|
||||
/* Flag of attribute is set or not. */
|
||||
uint64_t flag;
|
||||
/* Flag of attribute is set or not. */
|
||||
uint64_t flag;
|
||||
|
||||
/* Apart from in6_addr, the remaining static attributes */
|
||||
struct in_addr nexthop;
|
||||
u_int32_t med;
|
||||
u_int32_t local_pref;
|
||||
ifindex_t nh_ifindex;
|
||||
/* Apart from in6_addr, the remaining static attributes */
|
||||
struct in_addr nexthop;
|
||||
u_int32_t med;
|
||||
u_int32_t local_pref;
|
||||
ifindex_t nh_ifindex;
|
||||
|
||||
/* Path origin attribute */
|
||||
u_char origin;
|
||||
/* Path origin attribute */
|
||||
u_char origin;
|
||||
|
||||
/* has the route-map changed any attribute?
|
||||
Used on the peer outbound side. */
|
||||
u_int32_t rmap_change_flags;
|
||||
/* has the route-map changed any attribute?
|
||||
Used on the peer outbound side. */
|
||||
u_int32_t rmap_change_flags;
|
||||
|
||||
/* Multi-Protocol Nexthop, AFI IPv6 */
|
||||
struct in6_addr mp_nexthop_global;
|
||||
struct in6_addr mp_nexthop_local;
|
||||
/* Multi-Protocol Nexthop, AFI IPv6 */
|
||||
struct in6_addr mp_nexthop_global;
|
||||
struct in6_addr mp_nexthop_local;
|
||||
|
||||
/* Extended Communities attribute. */
|
||||
struct ecommunity *ecommunity;
|
||||
/* Extended Communities attribute. */
|
||||
struct ecommunity *ecommunity;
|
||||
|
||||
/* Large Communities attribute. */
|
||||
struct lcommunity *lcommunity;
|
||||
/* Large Communities attribute. */
|
||||
struct lcommunity *lcommunity;
|
||||
|
||||
/* Route-Reflector Cluster attribute */
|
||||
struct cluster_list *cluster;
|
||||
|
||||
/* Unknown transitive attribute. */
|
||||
struct transit *transit;
|
||||
/* Route-Reflector Cluster attribute */
|
||||
struct cluster_list *cluster;
|
||||
|
||||
struct in_addr mp_nexthop_global_in;
|
||||
|
||||
/* Aggregator Router ID attribute */
|
||||
struct in_addr aggregator_addr;
|
||||
|
||||
/* Route Reflector Originator attribute */
|
||||
struct in_addr originator_id;
|
||||
|
||||
/* Local weight, not actually an attribute */
|
||||
u_int32_t weight;
|
||||
|
||||
/* Aggregator ASN */
|
||||
as_t aggregator_as;
|
||||
|
||||
/* MP Nexthop length */
|
||||
u_char mp_nexthop_len;
|
||||
/* Unknown transitive attribute. */
|
||||
struct transit *transit;
|
||||
|
||||
/* MP Nexthop preference */
|
||||
u_char mp_nexthop_prefer_global;
|
||||
struct in_addr mp_nexthop_global_in;
|
||||
|
||||
/* Static MAC for EVPN */
|
||||
u_char sticky;
|
||||
/* Aggregator Router ID attribute */
|
||||
struct in_addr aggregator_addr;
|
||||
|
||||
/* route tag */
|
||||
route_tag_t tag;
|
||||
/* Route Reflector Originator attribute */
|
||||
struct in_addr originator_id;
|
||||
|
||||
/* Label index */
|
||||
u_int32_t label_index;
|
||||
/* Local weight, not actually an attribute */
|
||||
u_int32_t weight;
|
||||
|
||||
/* MPLS label */
|
||||
mpls_label_t label;
|
||||
/* Aggregator ASN */
|
||||
as_t aggregator_as;
|
||||
|
||||
uint16_t encap_tunneltype; /* grr */
|
||||
struct bgp_attr_encap_subtlv *encap_subtlvs; /* rfc5512 */
|
||||
/* MP Nexthop length */
|
||||
u_char mp_nexthop_len;
|
||||
|
||||
/* MP Nexthop preference */
|
||||
u_char mp_nexthop_prefer_global;
|
||||
|
||||
/* Static MAC for EVPN */
|
||||
u_char sticky;
|
||||
|
||||
/* route tag */
|
||||
route_tag_t tag;
|
||||
|
||||
/* Label index */
|
||||
u_int32_t label_index;
|
||||
|
||||
/* MPLS label */
|
||||
mpls_label_t label;
|
||||
|
||||
uint16_t encap_tunneltype; /* grr */
|
||||
struct bgp_attr_encap_subtlv *encap_subtlvs; /* rfc5512 */
|
||||
|
||||
#if ENABLE_BGP_VNC
|
||||
struct bgp_attr_encap_subtlv *vnc_subtlvs; /* VNC-specific */
|
||||
struct bgp_attr_encap_subtlv *vnc_subtlvs; /* VNC-specific */
|
||||
#endif
|
||||
/* EVPN */
|
||||
struct overlay_index evpn_overlay;
|
||||
/* EVPN */
|
||||
struct overlay_index evpn_overlay;
|
||||
|
||||
/* EVPN MAC Mobility sequence number, if any. */
|
||||
u_int32_t mm_seqnum;
|
||||
/* EVPN MAC Mobility sequence number, if any. */
|
||||
u_int32_t mm_seqnum;
|
||||
};
|
||||
|
||||
/* rmap_change_flags definition */
|
||||
@ -197,97 +194,97 @@ struct attr
|
||||
#define BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED (1 << 6)
|
||||
|
||||
/* Router Reflector related structure. */
|
||||
struct cluster_list
|
||||
{
|
||||
unsigned long refcnt;
|
||||
int length;
|
||||
struct in_addr *list;
|
||||
struct cluster_list {
|
||||
unsigned long refcnt;
|
||||
int length;
|
||||
struct in_addr *list;
|
||||
};
|
||||
|
||||
/* Unknown transit attribute. */
|
||||
struct transit
|
||||
{
|
||||
unsigned long refcnt;
|
||||
int length;
|
||||
u_char *val;
|
||||
struct transit {
|
||||
unsigned long refcnt;
|
||||
int length;
|
||||
u_char *val;
|
||||
};
|
||||
|
||||
#define ATTR_FLAG_BIT(X) (1ULL << ((X) - 1))
|
||||
|
||||
#define BGP_CLUSTER_LIST_LENGTH(attr) \
|
||||
(((attr)->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) ? \
|
||||
(attr)->cluster->length : 0)
|
||||
#define BGP_CLUSTER_LIST_LENGTH(attr) \
|
||||
(((attr)->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) \
|
||||
? (attr)->cluster->length \
|
||||
: 0)
|
||||
|
||||
typedef enum {
|
||||
BGP_ATTR_PARSE_PROCEED = 0,
|
||||
BGP_ATTR_PARSE_ERROR = -1,
|
||||
BGP_ATTR_PARSE_WITHDRAW = -2,
|
||||
BGP_ATTR_PARSE_PROCEED = 0,
|
||||
BGP_ATTR_PARSE_ERROR = -1,
|
||||
BGP_ATTR_PARSE_WITHDRAW = -2,
|
||||
|
||||
/* only used internally, send notify + convert to BGP_ATTR_PARSE_ERROR */
|
||||
BGP_ATTR_PARSE_ERROR_NOTIFYPLS = -3,
|
||||
/* only used internally, send notify + convert to BGP_ATTR_PARSE_ERROR
|
||||
*/
|
||||
BGP_ATTR_PARSE_ERROR_NOTIFYPLS = -3,
|
||||
} bgp_attr_parse_ret_t;
|
||||
|
||||
struct bpacket_attr_vec_arr;
|
||||
|
||||
/* Prototypes. */
|
||||
extern void bgp_attr_init (void);
|
||||
extern void bgp_attr_finish (void);
|
||||
extern bgp_attr_parse_ret_t bgp_attr_parse (struct peer *, struct attr *,
|
||||
bgp_size_t, struct bgp_nlri *,
|
||||
struct bgp_nlri *);
|
||||
extern void bgp_attr_dup (struct attr *, struct attr *);
|
||||
extern void bgp_attr_deep_dup (struct attr *, struct attr *);
|
||||
extern void bgp_attr_deep_free (struct attr *);
|
||||
extern struct attr *bgp_attr_intern (struct attr *attr);
|
||||
extern struct attr *bgp_attr_refcount (struct attr *attr);
|
||||
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, u_char);
|
||||
extern struct attr *bgp_attr_aggregate_intern (struct bgp *, u_char,
|
||||
struct aspath *,
|
||||
struct community *, int as_set, u_char);
|
||||
extern bgp_size_t bgp_packet_attribute (struct bgp *bgp, struct peer *,
|
||||
struct stream *, struct attr *,
|
||||
struct bpacket_attr_vec_arr *vecarr,
|
||||
struct prefix *, afi_t, safi_t,
|
||||
struct peer *, struct prefix_rd *,
|
||||
mpls_label_t *, int, u_int32_t);
|
||||
extern void bgp_dump_routes_attr (struct stream *, struct attr *,
|
||||
struct prefix *);
|
||||
extern int attrhash_cmp (const void *, const void *);
|
||||
extern unsigned int attrhash_key_make (void *);
|
||||
extern void attr_show_all (struct vty *);
|
||||
extern unsigned long int attr_count (void);
|
||||
extern unsigned long int attr_unknown_count (void);
|
||||
extern void bgp_attr_init(void);
|
||||
extern void bgp_attr_finish(void);
|
||||
extern bgp_attr_parse_ret_t bgp_attr_parse(struct peer *, struct attr *,
|
||||
bgp_size_t, struct bgp_nlri *,
|
||||
struct bgp_nlri *);
|
||||
extern void bgp_attr_dup(struct attr *, struct attr *);
|
||||
extern void bgp_attr_deep_dup(struct attr *, struct attr *);
|
||||
extern void bgp_attr_deep_free(struct attr *);
|
||||
extern struct attr *bgp_attr_intern(struct attr *attr);
|
||||
extern struct attr *bgp_attr_refcount(struct attr *attr);
|
||||
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, u_char);
|
||||
extern struct attr *bgp_attr_aggregate_intern(struct bgp *, u_char,
|
||||
struct aspath *,
|
||||
struct community *, int as_set,
|
||||
u_char);
|
||||
extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *,
|
||||
struct stream *, struct attr *,
|
||||
struct bpacket_attr_vec_arr *vecarr,
|
||||
struct prefix *, afi_t, safi_t,
|
||||
struct peer *, struct prefix_rd *,
|
||||
mpls_label_t *, int, u_int32_t);
|
||||
extern void bgp_dump_routes_attr(struct stream *, struct attr *,
|
||||
struct prefix *);
|
||||
extern int attrhash_cmp(const void *, const void *);
|
||||
extern unsigned int attrhash_key_make(void *);
|
||||
extern void attr_show_all(struct vty *);
|
||||
extern unsigned long int attr_count(void);
|
||||
extern unsigned long int attr_unknown_count(void);
|
||||
|
||||
/* Cluster list prototypes. */
|
||||
extern int cluster_loop_check (struct cluster_list *, struct in_addr);
|
||||
extern void cluster_unintern (struct cluster_list *);
|
||||
extern int cluster_loop_check(struct cluster_list *, struct in_addr);
|
||||
extern void cluster_unintern(struct cluster_list *);
|
||||
|
||||
/* Transit attribute prototypes. */
|
||||
void transit_unintern (struct transit *);
|
||||
void transit_unintern(struct transit *);
|
||||
|
||||
/* Below exported for unit-test purposes only */
|
||||
struct bgp_attr_parser_args {
|
||||
struct peer *peer;
|
||||
bgp_size_t length; /* attribute data length; */
|
||||
bgp_size_t total; /* total length, inc header */
|
||||
struct attr *attr;
|
||||
u_int8_t type;
|
||||
u_int8_t flags;
|
||||
u_char *startp;
|
||||
struct peer *peer;
|
||||
bgp_size_t length; /* attribute data length; */
|
||||
bgp_size_t total; /* total length, inc header */
|
||||
struct attr *attr;
|
||||
u_int8_t type;
|
||||
u_int8_t flags;
|
||||
u_char *startp;
|
||||
};
|
||||
extern int bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
|
||||
struct bgp_nlri *);
|
||||
extern int bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
|
||||
struct bgp_nlri *);
|
||||
extern int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
|
||||
struct bgp_nlri *);
|
||||
extern int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
|
||||
struct bgp_nlri *);
|
||||
|
||||
extern struct bgp_attr_encap_subtlv *
|
||||
encap_tlv_dup(struct bgp_attr_encap_subtlv *orig);
|
||||
|
||||
extern void
|
||||
bgp_attr_flush_encap(struct attr *attr);
|
||||
extern void bgp_attr_flush_encap(struct attr *attr);
|
||||
|
||||
/**
|
||||
* Set of functions to encode MP_REACH_NLRI and MP_UNREACH_NLRI attributes.
|
||||
@ -296,41 +293,44 @@ bgp_attr_flush_encap(struct attr *attr);
|
||||
* finally the _end() function.
|
||||
*/
|
||||
extern size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer,
|
||||
afi_t afi, safi_t safi,
|
||||
struct bpacket_attr_vec_arr *vecarr,
|
||||
afi_t afi, safi_t safi,
|
||||
struct bpacket_attr_vec_arr *vecarr,
|
||||
struct attr *attr);
|
||||
extern void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
|
||||
struct prefix *p, struct prefix_rd *prd,
|
||||
mpls_label_t *label, int addpath_encode,
|
||||
u_int32_t addpath_tx_id,
|
||||
struct attr *);
|
||||
u_int32_t addpath_tx_id, struct attr *);
|
||||
extern size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
|
||||
struct prefix *p);
|
||||
struct prefix *p);
|
||||
extern void bgp_packet_mpattr_end(struct stream *s, size_t sizep);
|
||||
|
||||
extern size_t bgp_packet_mpunreach_start (struct stream *s, afi_t afi,
|
||||
safi_t safi);
|
||||
extern void bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
|
||||
afi_t afi, safi_t safi, struct prefix_rd *prd,
|
||||
mpls_label_t *, int, u_int32_t, struct attr *);
|
||||
extern void bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt);
|
||||
extern size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi,
|
||||
safi_t safi);
|
||||
extern void bgp_packet_mpunreach_prefix(struct stream *s, struct prefix *p,
|
||||
afi_t afi, safi_t safi,
|
||||
struct prefix_rd *prd, mpls_label_t *,
|
||||
int, u_int32_t, struct attr *);
|
||||
extern void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt);
|
||||
|
||||
static inline int
|
||||
bgp_rmap_nhop_changed(u_int32_t out_rmap_flags, u_int32_t in_rmap_flags)
|
||||
static inline int bgp_rmap_nhop_changed(u_int32_t out_rmap_flags,
|
||||
u_int32_t in_rmap_flags)
|
||||
{
|
||||
return ((CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_PEER_ADDRESS) ||
|
||||
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED) ||
|
||||
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV4_NHOP_CHANGED) ||
|
||||
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED) ||
|
||||
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED) ||
|
||||
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_LL_NHOP_CHANGED) ||
|
||||
CHECK_FLAG(in_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED)) ? 1 : 0);
|
||||
return ((CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_PEER_ADDRESS)
|
||||
|| CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED)
|
||||
|| CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV4_NHOP_CHANGED)
|
||||
|| CHECK_FLAG(out_rmap_flags,
|
||||
BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED)
|
||||
|| CHECK_FLAG(out_rmap_flags,
|
||||
BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED)
|
||||
|| CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_LL_NHOP_CHANGED)
|
||||
|| CHECK_FLAG(in_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED))
|
||||
? 1
|
||||
: 0);
|
||||
}
|
||||
|
||||
static inline u_int32_t
|
||||
mac_mobility_seqnum (struct attr *attr)
|
||||
static inline u_int32_t mac_mobility_seqnum(struct attr *attr)
|
||||
{
|
||||
return (attr) ? attr->mm_seqnum : 0;
|
||||
return (attr) ? attr->mm_seqnum : 0;
|
||||
}
|
||||
|
||||
#endif /* _QUAGGA_BGP_ATTR_H */
|
||||
|
||||
@ -37,16 +37,16 @@
|
||||
|
||||
void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac)
|
||||
{
|
||||
struct ecommunity_val routermac_ecom;
|
||||
struct ecommunity_val routermac_ecom;
|
||||
|
||||
memset(&routermac_ecom, 0, sizeof(struct ecommunity_val));
|
||||
routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN;
|
||||
routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC;
|
||||
memcpy(&routermac_ecom.val[2], routermac->octet, ETHER_ADDR_LEN);
|
||||
if (!attr->ecommunity)
|
||||
attr->ecommunity = ecommunity_new();
|
||||
ecommunity_add_val(attr->ecommunity, &routermac_ecom);
|
||||
ecommunity_str (attr->ecommunity);
|
||||
memset(&routermac_ecom, 0, sizeof(struct ecommunity_val));
|
||||
routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN;
|
||||
routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC;
|
||||
memcpy(&routermac_ecom.val[2], routermac->octet, ETHER_ADDR_LEN);
|
||||
if (!attr->ecommunity)
|
||||
attr->ecommunity = ecommunity_new();
|
||||
ecommunity_add_val(attr->ecommunity, &routermac_ecom);
|
||||
ecommunity_str(attr->ecommunity);
|
||||
}
|
||||
|
||||
/* converts to an esi
|
||||
@ -56,138 +56,136 @@ void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac)
|
||||
*/
|
||||
int str2esi(const char *str, struct eth_segment_id *id)
|
||||
{
|
||||
unsigned int a[ESI_LEN];
|
||||
int i;
|
||||
unsigned int a[ESI_LEN];
|
||||
int i;
|
||||
|
||||
if (!str)
|
||||
return 0;
|
||||
if (sscanf (str, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x",
|
||||
a + 0, a + 1, a + 2, a + 3, a + 4, a + 5,
|
||||
a + 6, a + 7, a + 8, a + 9) != ESI_LEN)
|
||||
{
|
||||
/* error in incoming str length */
|
||||
return 0;
|
||||
}
|
||||
/* valid mac address */
|
||||
if (!id)
|
||||
return 1;
|
||||
for (i = 0; i < ESI_LEN; ++i)
|
||||
id->val[i] = a[i] & 0xff;
|
||||
return 1;
|
||||
if (!str)
|
||||
return 0;
|
||||
if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x", a + 0, a + 1,
|
||||
a + 2, a + 3, a + 4, a + 5, a + 6, a + 7, a + 8, a + 9)
|
||||
!= ESI_LEN) {
|
||||
/* error in incoming str length */
|
||||
return 0;
|
||||
}
|
||||
/* valid mac address */
|
||||
if (!id)
|
||||
return 1;
|
||||
for (i = 0; i < ESI_LEN; ++i)
|
||||
id->val[i] = a[i] & 0xff;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *esi2str(struct eth_segment_id *id)
|
||||
{
|
||||
char *ptr;
|
||||
u_char *val;
|
||||
char *ptr;
|
||||
u_char *val;
|
||||
|
||||
if (!id)
|
||||
return NULL;
|
||||
if (!id)
|
||||
return NULL;
|
||||
|
||||
val = id->val;
|
||||
ptr = (char *)XMALLOC(MTYPE_TMP, (ESI_LEN * 2 + ESI_LEN - 1 + 1) * sizeof(char));
|
||||
val = id->val;
|
||||
ptr = (char *)XMALLOC(MTYPE_TMP,
|
||||
(ESI_LEN * 2 + ESI_LEN - 1 + 1) * sizeof(char));
|
||||
|
||||
snprintf(ptr, (ESI_LEN * 2 + ESI_LEN - 1 + 1),
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
val[0], val[1], val[2], val[3], val[4],
|
||||
val[5], val[6], val[7], val[8], val[9]);
|
||||
snprintf(ptr, (ESI_LEN * 2 + ESI_LEN - 1 + 1),
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", val[0],
|
||||
val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8],
|
||||
val[9]);
|
||||
|
||||
return ptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
char *ecom_mac2str(char *ecom_mac)
|
||||
{
|
||||
char *en;
|
||||
char *en;
|
||||
|
||||
en = ecom_mac;
|
||||
en += 2;
|
||||
en = ecom_mac;
|
||||
en += 2;
|
||||
|
||||
return prefix_mac2str((struct ethaddr *)en, NULL, 0);
|
||||
return prefix_mac2str((struct ethaddr *)en, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch and return the sequence number from MAC Mobility extended
|
||||
* community, if present, else 0.
|
||||
*/
|
||||
u_int32_t
|
||||
bgp_attr_mac_mobility_seqnum (struct attr *attr, u_char *sticky)
|
||||
u_int32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, u_char *sticky)
|
||||
{
|
||||
struct ecommunity *ecom;
|
||||
int i;
|
||||
u_char flags = 0;
|
||||
struct ecommunity *ecom;
|
||||
int i;
|
||||
u_char flags = 0;
|
||||
|
||||
ecom = attr->ecommunity;
|
||||
if (!ecom || !ecom->size)
|
||||
return 0;
|
||||
ecom = attr->ecommunity;
|
||||
if (!ecom || !ecom->size)
|
||||
return 0;
|
||||
|
||||
/* If there is a MAC Mobility extended community, return its
|
||||
* sequence number.
|
||||
* TODO: RFC is silent on handling of multiple MAC mobility extended
|
||||
* communities for the same route. We will bail out upon the first
|
||||
* one.
|
||||
*/
|
||||
for (i = 0; i < ecom->size; i++)
|
||||
{
|
||||
u_char *pnt;
|
||||
u_char type, sub_type;
|
||||
u_int32_t seq_num;
|
||||
/* If there is a MAC Mobility extended community, return its
|
||||
* sequence number.
|
||||
* TODO: RFC is silent on handling of multiple MAC mobility extended
|
||||
* communities for the same route. We will bail out upon the first
|
||||
* one.
|
||||
*/
|
||||
for (i = 0; i < ecom->size; i++) {
|
||||
u_char *pnt;
|
||||
u_char type, sub_type;
|
||||
u_int32_t seq_num;
|
||||
|
||||
pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
|
||||
type = *pnt++;
|
||||
sub_type = *pnt++;
|
||||
if (!(type == ECOMMUNITY_ENCODE_EVPN &&
|
||||
sub_type == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY))
|
||||
continue;
|
||||
flags = *pnt++;
|
||||
pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
|
||||
type = *pnt++;
|
||||
sub_type = *pnt++;
|
||||
if (!(type == ECOMMUNITY_ENCODE_EVPN
|
||||
&& sub_type == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY))
|
||||
continue;
|
||||
flags = *pnt++;
|
||||
|
||||
if (flags & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY)
|
||||
*sticky = 1;
|
||||
else
|
||||
*sticky = 0;
|
||||
if (flags & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY)
|
||||
*sticky = 1;
|
||||
else
|
||||
*sticky = 0;
|
||||
|
||||
pnt++;
|
||||
seq_num = (*pnt++ << 24);
|
||||
seq_num |= (*pnt++ << 16);
|
||||
seq_num |= (*pnt++ << 8);
|
||||
seq_num |= (*pnt++);
|
||||
pnt++;
|
||||
seq_num = (*pnt++ << 24);
|
||||
seq_num |= (*pnt++ << 16);
|
||||
seq_num |= (*pnt++ << 8);
|
||||
seq_num |= (*pnt++);
|
||||
|
||||
return seq_num;
|
||||
}
|
||||
return seq_num;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
|
||||
extern int
|
||||
bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag, struct prefix *dst)
|
||||
extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
|
||||
struct prefix *dst)
|
||||
{
|
||||
struct evpn_addr *p_evpn_p;
|
||||
struct prefix p2;
|
||||
struct prefix *src = &p2;
|
||||
struct evpn_addr *p_evpn_p;
|
||||
struct prefix p2;
|
||||
struct prefix *src = &p2;
|
||||
|
||||
if (!dst || dst->family == 0)
|
||||
return -1;
|
||||
/* store initial prefix in src */
|
||||
prefix_copy(src, dst);
|
||||
memset(dst, 0, sizeof(struct prefix));
|
||||
p_evpn_p = &(dst->u.prefix_evpn);
|
||||
dst->family = AF_ETHERNET;
|
||||
p_evpn_p->route_type = evpn_type;
|
||||
if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) {
|
||||
p_evpn_p->eth_tag = eth_tag;
|
||||
p_evpn_p->ip_prefix_length = p2.prefixlen;
|
||||
if (src->family == AF_INET) {
|
||||
SET_IPADDR_V4 (&p_evpn_p->ip);
|
||||
memcpy(&p_evpn_p->ip.ipaddr_v4, &src->u.prefix4,
|
||||
sizeof(struct in_addr));
|
||||
dst->prefixlen = (u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV4;
|
||||
} else {
|
||||
SET_IPADDR_V6 (&p_evpn_p->ip);
|
||||
memcpy(&p_evpn_p->ip.ipaddr_v6, &src->u.prefix6,
|
||||
sizeof(struct in6_addr));
|
||||
dst->prefixlen = (u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV6;
|
||||
}
|
||||
} else
|
||||
return -1;
|
||||
return 0;
|
||||
if (!dst || dst->family == 0)
|
||||
return -1;
|
||||
/* store initial prefix in src */
|
||||
prefix_copy(src, dst);
|
||||
memset(dst, 0, sizeof(struct prefix));
|
||||
p_evpn_p = &(dst->u.prefix_evpn);
|
||||
dst->family = AF_ETHERNET;
|
||||
p_evpn_p->route_type = evpn_type;
|
||||
if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) {
|
||||
p_evpn_p->eth_tag = eth_tag;
|
||||
p_evpn_p->ip_prefix_length = p2.prefixlen;
|
||||
if (src->family == AF_INET) {
|
||||
SET_IPADDR_V4(&p_evpn_p->ip);
|
||||
memcpy(&p_evpn_p->ip.ipaddr_v4, &src->u.prefix4,
|
||||
sizeof(struct in_addr));
|
||||
dst->prefixlen = (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
|
||||
} else {
|
||||
SET_IPADDR_V6(&p_evpn_p->ip);
|
||||
memcpy(&p_evpn_p->ip.ipaddr_v6, &src->u.prefix6,
|
||||
sizeof(struct in6_addr));
|
||||
dst->prefixlen = (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV6;
|
||||
}
|
||||
} else
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -29,7 +29,6 @@
|
||||
#define ESI_TYPE_ROUTER 4 /* <RouterId-4B>:<Local Discriminator Value-4B> */
|
||||
#define ESI_TYPE_AS 5 /* <AS-4B>:<Local Discriminator Value-4B> */
|
||||
|
||||
|
||||
#define MAX_ESI {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}
|
||||
#define ESI_LEN 10
|
||||
|
||||
@ -38,32 +37,30 @@
|
||||
u_long eth_tag_id;
|
||||
struct attr;
|
||||
|
||||
struct eth_segment_id
|
||||
{
|
||||
u_char val[ESI_LEN];
|
||||
struct eth_segment_id {
|
||||
u_char val[ESI_LEN];
|
||||
};
|
||||
|
||||
union gw_addr
|
||||
{
|
||||
struct in_addr ipv4;
|
||||
struct in6_addr ipv6;
|
||||
union gw_addr {
|
||||
struct in_addr ipv4;
|
||||
struct in6_addr ipv6;
|
||||
};
|
||||
|
||||
struct bgp_route_evpn
|
||||
{
|
||||
struct eth_segment_id eth_s_id;
|
||||
union gw_addr gw_ip;
|
||||
struct bgp_route_evpn {
|
||||
struct eth_segment_id eth_s_id;
|
||||
union gw_addr gw_ip;
|
||||
};
|
||||
|
||||
extern int str2esi(const char *str, struct eth_segment_id *id);
|
||||
extern char *esi2str(struct eth_segment_id *id);
|
||||
extern char *ecom_mac2str(char *ecom_mac);
|
||||
|
||||
extern void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac);
|
||||
extern void bgp_add_routermac_ecom(struct attr *attr,
|
||||
struct ethaddr *routermac);
|
||||
extern int bgp_build_evpn_prefix(int type, uint32_t eth_tag,
|
||||
struct prefix *dst);
|
||||
struct prefix *dst);
|
||||
|
||||
extern u_int32_t
|
||||
bgp_attr_mac_mobility_seqnum (struct attr *attr, u_char *sticky);
|
||||
extern u_int32_t bgp_attr_mac_mobility_seqnum(struct attr *attr,
|
||||
u_char *sticky);
|
||||
|
||||
#endif /* _QUAGGA_BGP_ATTR_EVPN_H */
|
||||
#endif /* _QUAGGA_BGP_ATTR_EVPN_H */
|
||||
|
||||
857
bgpd/bgp_bfd.c
857
bgpd/bgp_bfd.c
File diff suppressed because it is too large
Load Diff
@ -23,25 +23,20 @@
|
||||
#ifndef _QUAGGA_BGP_BFD_H
|
||||
#define _QUAGGA_BGP_BFD_H
|
||||
|
||||
extern void
|
||||
bgp_bfd_init(void);
|
||||
extern void bgp_bfd_init(void);
|
||||
|
||||
extern void
|
||||
bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer);
|
||||
extern void bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer);
|
||||
|
||||
extern void
|
||||
bgp_bfd_register_peer (struct peer *peer);
|
||||
extern void bgp_bfd_register_peer(struct peer *peer);
|
||||
|
||||
extern void
|
||||
bgp_bfd_deregister_peer (struct peer *peer);
|
||||
extern void bgp_bfd_deregister_peer(struct peer *peer);
|
||||
|
||||
extern void
|
||||
bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr);
|
||||
extern void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer,
|
||||
char *addr);
|
||||
|
||||
extern void
|
||||
bgp_bfd_show_info(struct vty *vty, struct peer *peer, u_char use_json, json_object *json_neigh);
|
||||
extern void bgp_bfd_show_info(struct vty *vty, struct peer *peer,
|
||||
u_char use_json, json_object *json_neigh);
|
||||
|
||||
extern int
|
||||
bgp_bfd_is_peer_multihop(struct peer *peer);
|
||||
extern int bgp_bfd_is_peer_multihop(struct peer *peer);
|
||||
|
||||
#endif /* _QUAGGA_BGP_BFD_H */
|
||||
|
||||
459
bgpd/bgp_btoa.c
459
bgpd/bgp_btoa.c
@ -35,280 +35,255 @@
|
||||
#include "bgpd/bgp_aspath.h"
|
||||
|
||||
/* privileges */
|
||||
static zebra_capabilities_t _caps_p [] =
|
||||
{
|
||||
ZCAP_BIND,
|
||||
ZCAP_NET_RAW,
|
||||
ZCAP_NET_ADMIN,
|
||||
static zebra_capabilities_t _caps_p[] = {
|
||||
ZCAP_BIND, ZCAP_NET_RAW, ZCAP_NET_ADMIN,
|
||||
};
|
||||
|
||||
struct zebra_privs_t bgpd_privs =
|
||||
{
|
||||
struct zebra_privs_t bgpd_privs = {
|
||||
#if defined(FRR_USER) && defined(FRR_GROUP)
|
||||
.user = FRR_USER,
|
||||
.group = FRR_GROUP,
|
||||
.user = FRR_USER,
|
||||
.group = FRR_GROUP,
|
||||
#endif
|
||||
#ifdef VTY_GROUP
|
||||
.vty_group = VTY_GROUP,
|
||||
.vty_group = VTY_GROUP,
|
||||
#endif
|
||||
.caps_p = _caps_p,
|
||||
.cap_num_p = array_size(_caps_p),
|
||||
.cap_num_i = 0,
|
||||
.caps_p = _caps_p,
|
||||
.cap_num_p = array_size(_caps_p),
|
||||
.cap_num_i = 0,
|
||||
};
|
||||
|
||||
enum MRT_MSG_TYPES {
|
||||
MSG_NULL,
|
||||
MSG_START, /* sender is starting up */
|
||||
MSG_DIE, /* receiver should shut down */
|
||||
MSG_I_AM_DEAD, /* sender is shutting down */
|
||||
MSG_PEER_DOWN, /* sender's peer is down */
|
||||
MSG_PROTOCOL_BGP, /* msg is a BGP packet */
|
||||
MSG_PROTOCOL_RIP, /* msg is a RIP packet */
|
||||
MSG_PROTOCOL_IDRP, /* msg is an IDRP packet */
|
||||
MSG_PROTOCOL_RIPNG, /* msg is a RIPNG packet */
|
||||
MSG_PROTOCOL_BGP4PLUS, /* msg is a BGP4+ packet */
|
||||
MSG_PROTOCOL_BGP4PLUS_01, /* msg is a BGP4+ (draft 01) packet */
|
||||
MSG_PROTOCOL_OSPF, /* msg is an OSPF packet */
|
||||
MSG_TABLE_DUMP /* routing table dump */
|
||||
MSG_NULL,
|
||||
MSG_START, /* sender is starting up */
|
||||
MSG_DIE, /* receiver should shut down */
|
||||
MSG_I_AM_DEAD, /* sender is shutting down */
|
||||
MSG_PEER_DOWN, /* sender's peer is down */
|
||||
MSG_PROTOCOL_BGP, /* msg is a BGP packet */
|
||||
MSG_PROTOCOL_RIP, /* msg is a RIP packet */
|
||||
MSG_PROTOCOL_IDRP, /* msg is an IDRP packet */
|
||||
MSG_PROTOCOL_RIPNG, /* msg is a RIPNG packet */
|
||||
MSG_PROTOCOL_BGP4PLUS, /* msg is a BGP4+ packet */
|
||||
MSG_PROTOCOL_BGP4PLUS_01, /* msg is a BGP4+ (draft 01) packet */
|
||||
MSG_PROTOCOL_OSPF, /* msg is an OSPF packet */
|
||||
MSG_TABLE_DUMP /* routing table dump */
|
||||
};
|
||||
|
||||
static int
|
||||
attr_parse (struct stream *s, u_int16_t len)
|
||||
static int attr_parse(struct stream *s, u_int16_t len)
|
||||
{
|
||||
u_int flag;
|
||||
u_int type;
|
||||
u_int16_t length;
|
||||
u_int16_t lim;
|
||||
u_int flag;
|
||||
u_int type;
|
||||
u_int16_t length;
|
||||
u_int16_t lim;
|
||||
|
||||
lim = s->getp + len;
|
||||
lim = s->getp + len;
|
||||
|
||||
printf ("attr_parse s->getp %zd, len %d, lim %d\n", s->getp, len, lim);
|
||||
printf("attr_parse s->getp %zd, len %d, lim %d\n", s->getp, len, lim);
|
||||
|
||||
while (s->getp < lim)
|
||||
{
|
||||
flag = stream_getc (s);
|
||||
type = stream_getc (s);
|
||||
while (s->getp < lim) {
|
||||
flag = stream_getc(s);
|
||||
type = stream_getc(s);
|
||||
|
||||
if (flag & BGP_ATTR_FLAG_EXTLEN)
|
||||
length = stream_getw (s);
|
||||
else
|
||||
length = stream_getc (s);
|
||||
if (flag & BGP_ATTR_FLAG_EXTLEN)
|
||||
length = stream_getw(s);
|
||||
else
|
||||
length = stream_getc(s);
|
||||
|
||||
printf ("FLAG: %d\n", flag);
|
||||
printf ("TYPE: %d\n", type);
|
||||
printf ("Len: %d\n", length);
|
||||
printf("FLAG: %d\n", flag);
|
||||
printf("TYPE: %d\n", type);
|
||||
printf("Len: %d\n", length);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case BGP_ATTR_ORIGIN:
|
||||
{
|
||||
u_char origin;
|
||||
origin = stream_getc (s);
|
||||
printf ("ORIGIN: %d\n", origin);
|
||||
}
|
||||
break;
|
||||
case BGP_ATTR_AS_PATH:
|
||||
{
|
||||
struct aspath *aspath;
|
||||
switch (type) {
|
||||
case BGP_ATTR_ORIGIN: {
|
||||
u_char origin;
|
||||
origin = stream_getc(s);
|
||||
printf("ORIGIN: %d\n", origin);
|
||||
} break;
|
||||
case BGP_ATTR_AS_PATH: {
|
||||
struct aspath *aspath;
|
||||
|
||||
aspath = aspath_parse (s, length, 1);
|
||||
printf ("ASPATH: %s\n", aspath->str);
|
||||
aspath_free(aspath);
|
||||
}
|
||||
break;
|
||||
case BGP_ATTR_NEXT_HOP:
|
||||
{
|
||||
struct in_addr nexthop;
|
||||
nexthop.s_addr = stream_get_ipv4 (s);
|
||||
printf ("NEXTHOP: %s\n", inet_ntoa (nexthop));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
stream_getw_from (s, length);
|
||||
break;
|
||||
aspath = aspath_parse(s, length, 1);
|
||||
printf("ASPATH: %s\n", aspath->str);
|
||||
aspath_free(aspath);
|
||||
} break;
|
||||
case BGP_ATTR_NEXT_HOP: {
|
||||
struct in_addr nexthop;
|
||||
nexthop.s_addr = stream_get_ipv4(s);
|
||||
printf("NEXTHOP: %s\n", inet_ntoa(nexthop));
|
||||
} break;
|
||||
default:
|
||||
stream_getw_from(s, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
FILE *fp;
|
||||
struct stream *s;
|
||||
time_t now;
|
||||
int type;
|
||||
int subtype;
|
||||
size_t len;
|
||||
int source_as;
|
||||
int dest_as;
|
||||
ifindex_t ifindex;
|
||||
int family;
|
||||
struct in_addr sip;
|
||||
struct in_addr dip;
|
||||
u_int16_t viewno, seq_num;
|
||||
struct prefix_ipv4 p;
|
||||
int ret;
|
||||
FILE *fp;
|
||||
struct stream *s;
|
||||
time_t now;
|
||||
int type;
|
||||
int subtype;
|
||||
size_t len;
|
||||
int source_as;
|
||||
int dest_as;
|
||||
ifindex_t ifindex;
|
||||
int family;
|
||||
struct in_addr sip;
|
||||
struct in_addr dip;
|
||||
u_int16_t viewno, seq_num;
|
||||
struct prefix_ipv4 p;
|
||||
|
||||
s = stream_new (10000);
|
||||
s = stream_new(10000);
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
fprintf (stderr, "Usage: %s FILENAME\n", argv[0]);
|
||||
exit (1);
|
||||
}
|
||||
fp = fopen (argv[1], "r");
|
||||
if (!fp)
|
||||
{
|
||||
fprintf (stdout,"%% Can't open configuration file %s due to '%s'.\n",
|
||||
argv[1], safe_strerror(errno));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
stream_reset (s);
|
||||
|
||||
ret = fread (s->data, 12, 1, fp);
|
||||
if (!ret || feof (fp))
|
||||
{
|
||||
printf ("END OF FILE\n");
|
||||
break;
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s FILENAME\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (ferror (fp))
|
||||
{
|
||||
printf ("ERROR OF FREAD\n");
|
||||
break;
|
||||
fp = fopen(argv[1], "r");
|
||||
if (!fp) {
|
||||
fprintf(stdout,
|
||||
"%% Can't open configuration file %s due to '%s'.\n",
|
||||
argv[1], safe_strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Extract header. */
|
||||
now = stream_getl (s);
|
||||
type = stream_getw (s);
|
||||
subtype = stream_getw (s);
|
||||
len = stream_getl (s);
|
||||
while (1) {
|
||||
stream_reset(s);
|
||||
|
||||
printf ("TIME: %s", ctime (&now));
|
||||
ret = fread(s->data, 12, 1, fp);
|
||||
if (!ret || feof(fp)) {
|
||||
printf("END OF FILE\n");
|
||||
break;
|
||||
}
|
||||
if (ferror(fp)) {
|
||||
printf("ERROR OF FREAD\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* printf ("TYPE: %d/%d\n", type, subtype); */
|
||||
/* Extract header. */
|
||||
now = stream_getl(s);
|
||||
type = stream_getw(s);
|
||||
subtype = stream_getw(s);
|
||||
len = stream_getl(s);
|
||||
|
||||
if (type == MSG_PROTOCOL_BGP4MP)
|
||||
printf ("TYPE: BGP4MP");
|
||||
else if (type == MSG_PROTOCOL_BGP4MP_ET)
|
||||
printf ("TYPE: BGP4MP_ET");
|
||||
else if (type == MSG_TABLE_DUMP)
|
||||
printf ("TYPE: MSG_TABLE_DUMP");
|
||||
else
|
||||
printf ("TYPE: Unknown %d", type);
|
||||
printf("TIME: %s", ctime(&now));
|
||||
|
||||
if (type == MSG_TABLE_DUMP)
|
||||
switch (subtype)
|
||||
{
|
||||
case AFI_IP:
|
||||
printf ("/AFI_IP\n");
|
||||
break;
|
||||
case AFI_IP6:
|
||||
printf ("/AFI_IP6\n");
|
||||
break;
|
||||
default:
|
||||
printf ("/UNKNOWN %d", subtype);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (subtype)
|
||||
{
|
||||
case BGP4MP_STATE_CHANGE:
|
||||
printf ("/CHANGE\n");
|
||||
break;
|
||||
case BGP4MP_MESSAGE:
|
||||
printf ("/MESSAGE\n");
|
||||
break;
|
||||
case BGP4MP_ENTRY:
|
||||
printf ("/ENTRY\n");
|
||||
break;
|
||||
case BGP4MP_SNAPSHOT:
|
||||
printf ("/SNAPSHOT\n");
|
||||
break;
|
||||
default:
|
||||
printf ("/UNKNOWN %d", subtype);
|
||||
break;
|
||||
}
|
||||
/* printf ("TYPE: %d/%d\n", type, subtype); */
|
||||
|
||||
if (type == MSG_PROTOCOL_BGP4MP)
|
||||
printf("TYPE: BGP4MP");
|
||||
else if (type == MSG_PROTOCOL_BGP4MP_ET)
|
||||
printf("TYPE: BGP4MP_ET");
|
||||
else if (type == MSG_TABLE_DUMP)
|
||||
printf("TYPE: MSG_TABLE_DUMP");
|
||||
else
|
||||
printf("TYPE: Unknown %d", type);
|
||||
|
||||
if (type == MSG_TABLE_DUMP)
|
||||
switch (subtype) {
|
||||
case AFI_IP:
|
||||
printf("/AFI_IP\n");
|
||||
break;
|
||||
case AFI_IP6:
|
||||
printf("/AFI_IP6\n");
|
||||
break;
|
||||
default:
|
||||
printf("/UNKNOWN %d", subtype);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
switch (subtype) {
|
||||
case BGP4MP_STATE_CHANGE:
|
||||
printf("/CHANGE\n");
|
||||
break;
|
||||
case BGP4MP_MESSAGE:
|
||||
printf("/MESSAGE\n");
|
||||
break;
|
||||
case BGP4MP_ENTRY:
|
||||
printf("/ENTRY\n");
|
||||
break;
|
||||
case BGP4MP_SNAPSHOT:
|
||||
printf("/SNAPSHOT\n");
|
||||
break;
|
||||
default:
|
||||
printf("/UNKNOWN %d", subtype);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("len: %zd\n", len);
|
||||
|
||||
fread(s->data + 12, len, 1, fp);
|
||||
if (feof(fp)) {
|
||||
printf("ENDOF FILE 2\n");
|
||||
break;
|
||||
}
|
||||
if (ferror(fp)) {
|
||||
printf("ERROR OF FREAD 2\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* printf ("now read %d\n", len); */
|
||||
|
||||
if (type == MSG_TABLE_DUMP) {
|
||||
u_char status;
|
||||
time_t originated;
|
||||
struct in_addr peer;
|
||||
u_int16_t attrlen;
|
||||
|
||||
viewno = stream_getw(s);
|
||||
seq_num = stream_getw(s);
|
||||
printf("VIEW: %d\n", viewno);
|
||||
printf("SEQUENCE: %d\n", seq_num);
|
||||
|
||||
/* start */
|
||||
while (s->getp < len - 16) {
|
||||
p.prefix.s_addr = stream_get_ipv4(s);
|
||||
p.prefixlen = stream_getc(s);
|
||||
printf("PREFIX: %s/%d\n", inet_ntoa(p.prefix),
|
||||
p.prefixlen);
|
||||
|
||||
status = stream_getc(s);
|
||||
originated = stream_getl(s);
|
||||
peer.s_addr = stream_get_ipv4(s);
|
||||
source_as = stream_getw(s);
|
||||
|
||||
printf("FROM: %s AS%d\n", inet_ntoa(peer),
|
||||
source_as);
|
||||
printf("ORIGINATED: %s", ctime(&originated));
|
||||
|
||||
attrlen = stream_getw(s);
|
||||
printf("ATTRLEN: %d\n", attrlen);
|
||||
|
||||
attr_parse(s, attrlen);
|
||||
|
||||
printf("STATUS: 0x%x\n", status);
|
||||
}
|
||||
} else {
|
||||
source_as = stream_getw(s);
|
||||
dest_as = stream_getw(s);
|
||||
printf("source_as: %d\n", source_as);
|
||||
printf("dest_as: %d\n", dest_as);
|
||||
|
||||
ifindex = stream_getw(s);
|
||||
family = stream_getw(s);
|
||||
|
||||
printf("ifindex: %d\n", ifindex);
|
||||
printf("family: %d\n", family);
|
||||
|
||||
sip.s_addr = stream_get_ipv4(s);
|
||||
dip.s_addr = stream_get_ipv4(s);
|
||||
|
||||
printf("saddr: %s\n", inet_ntoa(sip));
|
||||
printf("daddr: %s\n", inet_ntoa(dip));
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
printf ("len: %zd\n", len);
|
||||
|
||||
fread (s->data + 12, len, 1, fp);
|
||||
if (feof (fp))
|
||||
{
|
||||
printf ("ENDOF FILE 2\n");
|
||||
break;
|
||||
}
|
||||
if (ferror (fp))
|
||||
{
|
||||
printf ("ERROR OF FREAD 2\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* printf ("now read %d\n", len); */
|
||||
|
||||
if (type == MSG_TABLE_DUMP)
|
||||
{
|
||||
u_char status;
|
||||
time_t originated;
|
||||
struct in_addr peer;
|
||||
u_int16_t attrlen;
|
||||
|
||||
viewno = stream_getw (s);
|
||||
seq_num = stream_getw (s);
|
||||
printf ("VIEW: %d\n", viewno);
|
||||
printf ("SEQUENCE: %d\n", seq_num);
|
||||
|
||||
/* start */
|
||||
while (s->getp < len - 16)
|
||||
{
|
||||
p.prefix.s_addr = stream_get_ipv4 (s);
|
||||
p.prefixlen = stream_getc (s);
|
||||
printf ("PREFIX: %s/%d\n", inet_ntoa (p.prefix), p.prefixlen);
|
||||
|
||||
status = stream_getc (s);
|
||||
originated = stream_getl (s);
|
||||
peer.s_addr = stream_get_ipv4 (s);
|
||||
source_as = stream_getw(s);
|
||||
|
||||
printf ("FROM: %s AS%d\n", inet_ntoa (peer), source_as);
|
||||
printf ("ORIGINATED: %s", ctime (&originated));
|
||||
|
||||
attrlen = stream_getw (s);
|
||||
printf ("ATTRLEN: %d\n", attrlen);
|
||||
|
||||
attr_parse (s, attrlen);
|
||||
|
||||
printf ("STATUS: 0x%x\n", status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
source_as = stream_getw (s);
|
||||
dest_as = stream_getw (s);
|
||||
printf ("source_as: %d\n", source_as);
|
||||
printf ("dest_as: %d\n", dest_as);
|
||||
|
||||
ifindex = stream_getw (s);
|
||||
family = stream_getw (s);
|
||||
|
||||
printf ("ifindex: %d\n", ifindex);
|
||||
printf ("family: %d\n", family);
|
||||
|
||||
sip.s_addr = stream_get_ipv4 (s);
|
||||
dip.s_addr = stream_get_ipv4 (s);
|
||||
|
||||
printf ("saddr: %s\n", inet_ntoa (sip));
|
||||
printf ("daddr: %s\n", inet_ntoa (dip));
|
||||
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
||||
fclose (fp);
|
||||
return 0;
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
1734
bgpd/bgp_clist.c
1734
bgpd/bgp_clist.c
File diff suppressed because it is too large
Load Diff
154
bgpd/bgp_clist.h
154
bgpd/bgp_clist.h
@ -43,82 +43,76 @@
|
||||
#define LARGE_COMMUNITY_LIST_EXPANDED 5 /* Expanded Large community-list. */
|
||||
|
||||
/* Community-list. */
|
||||
struct community_list
|
||||
{
|
||||
/* Name of the community-list. */
|
||||
char *name;
|
||||
struct community_list {
|
||||
/* Name of the community-list. */
|
||||
char *name;
|
||||
|
||||
/* String or number. */
|
||||
int sort;
|
||||
/* String or number. */
|
||||
int sort;
|
||||
|
||||
/* Link to upper list. */
|
||||
struct community_list_list *parent;
|
||||
/* Link to upper list. */
|
||||
struct community_list_list *parent;
|
||||
|
||||
/* Linked list for other community-list. */
|
||||
struct community_list *next;
|
||||
struct community_list *prev;
|
||||
/* Linked list for other community-list. */
|
||||
struct community_list *next;
|
||||
struct community_list *prev;
|
||||
|
||||
/* Community-list entry in this community-list. */
|
||||
struct community_entry *head;
|
||||
struct community_entry *tail;
|
||||
/* Community-list entry in this community-list. */
|
||||
struct community_entry *head;
|
||||
struct community_entry *tail;
|
||||
};
|
||||
|
||||
/* Each entry in community-list. */
|
||||
struct community_entry
|
||||
{
|
||||
struct community_entry *next;
|
||||
struct community_entry *prev;
|
||||
struct community_entry {
|
||||
struct community_entry *next;
|
||||
struct community_entry *prev;
|
||||
|
||||
/* Permit or deny. */
|
||||
u_char direct;
|
||||
/* Permit or deny. */
|
||||
u_char direct;
|
||||
|
||||
/* Standard or expanded. */
|
||||
u_char style;
|
||||
/* Standard or expanded. */
|
||||
u_char style;
|
||||
|
||||
/* Any match. */
|
||||
u_char any;
|
||||
/* Any match. */
|
||||
u_char any;
|
||||
|
||||
/* Community structure. */
|
||||
union
|
||||
{
|
||||
struct community *com;
|
||||
struct ecommunity *ecom;
|
||||
struct lcommunity *lcom;
|
||||
} u;
|
||||
/* Community structure. */
|
||||
union {
|
||||
struct community *com;
|
||||
struct ecommunity *ecom;
|
||||
struct lcommunity *lcom;
|
||||
} u;
|
||||
|
||||
/* Configuration string. */
|
||||
char *config;
|
||||
/* Configuration string. */
|
||||
char *config;
|
||||
|
||||
/* Expanded community-list regular expression. */
|
||||
regex_t *reg;
|
||||
/* Expanded community-list regular expression. */
|
||||
regex_t *reg;
|
||||
};
|
||||
|
||||
/* Linked list of community-list. */
|
||||
struct community_list_list
|
||||
{
|
||||
struct community_list *head;
|
||||
struct community_list *tail;
|
||||
struct community_list_list {
|
||||
struct community_list *head;
|
||||
struct community_list *tail;
|
||||
};
|
||||
|
||||
/* Master structure of community-list and extcommunity-list. */
|
||||
struct community_list_master
|
||||
{
|
||||
struct community_list_list num;
|
||||
struct community_list_list str;
|
||||
struct community_list_master {
|
||||
struct community_list_list num;
|
||||
struct community_list_list str;
|
||||
};
|
||||
|
||||
/* Community-list handler. community_list_init() returns this
|
||||
structure as handler. */
|
||||
struct community_list_handler
|
||||
{
|
||||
/* Community-list. */
|
||||
struct community_list_master community_list;
|
||||
struct community_list_handler {
|
||||
/* Community-list. */
|
||||
struct community_list_master community_list;
|
||||
|
||||
/* Exteded community-list. */
|
||||
struct community_list_master extcommunity_list;
|
||||
/* Exteded community-list. */
|
||||
struct community_list_master extcommunity_list;
|
||||
|
||||
/* Large community-list. */
|
||||
struct community_list_master lcommunity_list;
|
||||
/* Large community-list. */
|
||||
struct community_list_master lcommunity_list;
|
||||
};
|
||||
|
||||
/* Error code of community-list. */
|
||||
@ -131,42 +125,42 @@ struct community_list_handler
|
||||
extern struct community_list_handler *bgp_clist;
|
||||
|
||||
/* Prototypes. */
|
||||
extern struct community_list_handler *community_list_init (void);
|
||||
extern void community_list_terminate (struct community_list_handler *);
|
||||
extern struct community_list_handler *community_list_init(void);
|
||||
extern void community_list_terminate(struct community_list_handler *);
|
||||
|
||||
extern int community_list_set (struct community_list_handler *ch,
|
||||
extern int community_list_set(struct community_list_handler *ch,
|
||||
const char *name, const char *str, int direct,
|
||||
int style);
|
||||
extern int community_list_unset(struct community_list_handler *ch,
|
||||
const char *name, const char *str, int direct,
|
||||
int style, int delete_all);
|
||||
extern int extcommunity_list_set(struct community_list_handler *ch,
|
||||
const char *name, const char *str, int direct,
|
||||
int style);
|
||||
extern int extcommunity_list_unset(struct community_list_handler *ch,
|
||||
const char *name, const char *str,
|
||||
int direct, int style, int delete_all);
|
||||
extern int lcommunity_list_set(struct community_list_handler *ch,
|
||||
const char *name, const char *str, int direct,
|
||||
int style);
|
||||
extern int community_list_unset (struct community_list_handler *ch,
|
||||
const char *name, const char *str,
|
||||
int direct, int style, int delete_all);
|
||||
extern int extcommunity_list_set (struct community_list_handler *ch,
|
||||
const char *name, const char *str,
|
||||
int direct, int style);
|
||||
extern int extcommunity_list_unset (struct community_list_handler *ch,
|
||||
const char *name, const char *str,
|
||||
int direct, int style, int delete_all);
|
||||
extern int lcommunity_list_set (struct community_list_handler *ch,
|
||||
const char *name, const char *str,
|
||||
int direct, int style);
|
||||
extern int lcommunity_list_unset (struct community_list_handler *ch,
|
||||
const char *name, const char *str,
|
||||
int direct, int style);
|
||||
extern int lcommunity_list_unset(struct community_list_handler *ch,
|
||||
const char *name, const char *str, int direct,
|
||||
int style);
|
||||
|
||||
extern struct community_list_master *
|
||||
community_list_master_lookup (struct community_list_handler *, int);
|
||||
community_list_master_lookup(struct community_list_handler *, int);
|
||||
|
||||
extern struct community_list *
|
||||
community_list_lookup (struct community_list_handler *, const char *, int);
|
||||
community_list_lookup(struct community_list_handler *, const char *, int);
|
||||
|
||||
extern int community_list_match (struct community *, struct community_list *);
|
||||
extern int ecommunity_list_match (struct ecommunity *, struct community_list *);
|
||||
extern int lcommunity_list_match (struct lcommunity *, struct community_list *);
|
||||
extern int community_list_exact_match (struct community *,
|
||||
struct community_list *);
|
||||
extern struct community *
|
||||
community_list_match_delete (struct community *, struct community_list *);
|
||||
extern int community_list_match(struct community *, struct community_list *);
|
||||
extern int ecommunity_list_match(struct ecommunity *, struct community_list *);
|
||||
extern int lcommunity_list_match(struct lcommunity *, struct community_list *);
|
||||
extern int community_list_exact_match(struct community *,
|
||||
struct community_list *);
|
||||
extern struct community *community_list_match_delete(struct community *,
|
||||
struct community_list *);
|
||||
extern struct lcommunity *
|
||||
lcommunity_list_match_delete (struct lcommunity *lcom,
|
||||
struct community_list *list);
|
||||
lcommunity_list_match_delete(struct lcommunity *lcom,
|
||||
struct community_list *list);
|
||||
#endif /* _QUAGGA_BGP_CLIST_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -24,23 +24,22 @@
|
||||
#include "lib/json.h"
|
||||
|
||||
/* Communities attribute. */
|
||||
struct community
|
||||
{
|
||||
/* Reference count of communities value. */
|
||||
unsigned long refcnt;
|
||||
struct community {
|
||||
/* Reference count of communities value. */
|
||||
unsigned long refcnt;
|
||||
|
||||
/* Communities value size. */
|
||||
int size;
|
||||
/* Communities value size. */
|
||||
int size;
|
||||
|
||||
/* Communities value. */
|
||||
u_int32_t *val;
|
||||
/* Communities value. */
|
||||
u_int32_t *val;
|
||||
|
||||
/* Communities as a json object */
|
||||
json_object *json;
|
||||
/* Communities as a json object */
|
||||
json_object *json;
|
||||
|
||||
/* String of community attribute. This sring is used by vty output
|
||||
and expanded community-list for regular expression match. */
|
||||
char *str;
|
||||
/* String of community attribute. This sring is used by vty output
|
||||
and expanded community-list for regular expression match. */
|
||||
char *str;
|
||||
};
|
||||
|
||||
/* Well-known communities value. */
|
||||
@ -56,25 +55,27 @@ struct community
|
||||
#define com_nthval(X,n) ((X)->val + (n))
|
||||
|
||||
/* Prototypes of communities attribute functions. */
|
||||
extern void community_init (void);
|
||||
extern void community_finish (void);
|
||||
extern void community_free (struct community *);
|
||||
extern struct community *community_uniq_sort (struct community *);
|
||||
extern struct community *community_parse (u_int32_t *, u_short);
|
||||
extern struct community *community_intern (struct community *);
|
||||
extern void community_unintern (struct community **);
|
||||
extern char *community_str (struct community *);
|
||||
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 struct community *community_merge (struct community *, struct community *);
|
||||
extern struct community *community_delete (struct community *, struct community *);
|
||||
extern struct community *community_dup (struct community *);
|
||||
extern int community_include (struct community *, u_int32_t);
|
||||
extern void community_del_val (struct community *, u_int32_t *);
|
||||
extern unsigned long community_count (void);
|
||||
extern struct hash *community_hash (void);
|
||||
extern u_int32_t community_val_get (struct community *com, int i);
|
||||
extern void community_init(void);
|
||||
extern void community_finish(void);
|
||||
extern void community_free(struct community *);
|
||||
extern struct community *community_uniq_sort(struct community *);
|
||||
extern struct community *community_parse(u_int32_t *, u_short);
|
||||
extern struct community *community_intern(struct community *);
|
||||
extern void community_unintern(struct community **);
|
||||
extern char *community_str(struct community *);
|
||||
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 struct community *community_merge(struct community *,
|
||||
struct community *);
|
||||
extern struct community *community_delete(struct community *,
|
||||
struct community *);
|
||||
extern struct community *community_dup(struct community *);
|
||||
extern int community_include(struct community *, u_int32_t);
|
||||
extern void community_del_val(struct community *, u_int32_t *);
|
||||
extern unsigned long community_count(void);
|
||||
extern struct hash *community_hash(void);
|
||||
extern u_int32_t community_val_get(struct community *com, int i);
|
||||
|
||||
#endif /* _QUAGGA_BGP_COMMUNITY_H */
|
||||
|
||||
1065
bgpd/bgp_damp.c
1065
bgpd/bgp_damp.c
File diff suppressed because it is too large
Load Diff
160
bgpd/bgp_damp.h
160
bgpd/bgp_damp.h
@ -22,92 +22,90 @@
|
||||
#define _QUAGGA_BGP_DAMP_H
|
||||
|
||||
/* Structure maintained on a per-route basis. */
|
||||
struct bgp_damp_info
|
||||
{
|
||||
/* Doubly linked list. This information must be linked to
|
||||
reuse_list or no_reuse_list. */
|
||||
struct bgp_damp_info *next;
|
||||
struct bgp_damp_info *prev;
|
||||
struct bgp_damp_info {
|
||||
/* Doubly linked list. This information must be linked to
|
||||
reuse_list or no_reuse_list. */
|
||||
struct bgp_damp_info *next;
|
||||
struct bgp_damp_info *prev;
|
||||
|
||||
/* Figure-of-merit. */
|
||||
unsigned int penalty;
|
||||
/* Figure-of-merit. */
|
||||
unsigned int penalty;
|
||||
|
||||
/* Number of flapping. */
|
||||
unsigned int flap;
|
||||
|
||||
/* First flap time */
|
||||
time_t start_time;
|
||||
|
||||
/* Last time penalty was updated. */
|
||||
time_t t_updated;
|
||||
/* Number of flapping. */
|
||||
unsigned int flap;
|
||||
|
||||
/* Time of route start to be suppressed. */
|
||||
time_t suppress_time;
|
||||
/* First flap time */
|
||||
time_t start_time;
|
||||
|
||||
/* Back reference to bgp_info. */
|
||||
struct bgp_info *binfo;
|
||||
/* Last time penalty was updated. */
|
||||
time_t t_updated;
|
||||
|
||||
/* Back reference to bgp_node. */
|
||||
struct bgp_node *rn;
|
||||
/* Time of route start to be suppressed. */
|
||||
time_t suppress_time;
|
||||
|
||||
/* Current index in the reuse_list. */
|
||||
int index;
|
||||
/* Back reference to bgp_info. */
|
||||
struct bgp_info *binfo;
|
||||
|
||||
/* Last time message type. */
|
||||
u_char lastrecord;
|
||||
/* Back reference to bgp_node. */
|
||||
struct bgp_node *rn;
|
||||
|
||||
/* Current index in the reuse_list. */
|
||||
int index;
|
||||
|
||||
/* Last time message type. */
|
||||
u_char lastrecord;
|
||||
#define BGP_RECORD_UPDATE 1U
|
||||
#define BGP_RECORD_WITHDRAW 2U
|
||||
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
};
|
||||
|
||||
/* Specified parameter set configuration. */
|
||||
struct bgp_damp_config
|
||||
{
|
||||
/* Value over which routes suppressed. */
|
||||
unsigned int suppress_value;
|
||||
struct bgp_damp_config {
|
||||
/* Value over which routes suppressed. */
|
||||
unsigned int suppress_value;
|
||||
|
||||
/* Value below which suppressed routes reused. */
|
||||
unsigned int reuse_limit;
|
||||
/* Value below which suppressed routes reused. */
|
||||
unsigned int reuse_limit;
|
||||
|
||||
/* Max time a route can be suppressed. */
|
||||
time_t max_suppress_time;
|
||||
/* Max time a route can be suppressed. */
|
||||
time_t max_suppress_time;
|
||||
|
||||
/* Time during which accumulated penalty reduces by half. */
|
||||
time_t half_life;
|
||||
/* Time during which accumulated penalty reduces by half. */
|
||||
time_t half_life;
|
||||
|
||||
/* Non-configurable parameters but fixed at implementation time.
|
||||
* To change this values, init_bgp_damp() should be modified.
|
||||
*/
|
||||
time_t tmax; /* Max time previous instability retained */
|
||||
unsigned int reuse_list_size; /* Number of reuse lists */
|
||||
unsigned int reuse_index_size; /* Size of reuse index array */
|
||||
/* Non-configurable parameters but fixed at implementation time.
|
||||
* To change this values, init_bgp_damp() should be modified.
|
||||
*/
|
||||
time_t tmax; /* Max time previous instability retained */
|
||||
unsigned int reuse_list_size; /* Number of reuse lists */
|
||||
unsigned int reuse_index_size; /* Size of reuse index array */
|
||||
|
||||
/* Non-configurable parameters. Most of these are calculated from
|
||||
* the configurable parameters above.
|
||||
*/
|
||||
unsigned int ceiling; /* Max value a penalty can attain */
|
||||
unsigned int decay_rate_per_tick; /* Calculated from half-life */
|
||||
unsigned int decay_array_size; /* Calculated using config parameters */
|
||||
double scale_factor;
|
||||
unsigned int reuse_scale_factor;
|
||||
|
||||
/* Decay array per-set based. */
|
||||
double *decay_array;
|
||||
/* Non-configurable parameters. Most of these are calculated from
|
||||
* the configurable parameters above.
|
||||
*/
|
||||
unsigned int ceiling; /* Max value a penalty can attain */
|
||||
unsigned int decay_rate_per_tick; /* Calculated from half-life */
|
||||
unsigned int decay_array_size; /* Calculated using config parameters */
|
||||
double scale_factor;
|
||||
unsigned int reuse_scale_factor;
|
||||
|
||||
/* Reuse index array per-set based. */
|
||||
int *reuse_index;
|
||||
/* Decay array per-set based. */
|
||||
double *decay_array;
|
||||
|
||||
/* Reuse list array per-set based. */
|
||||
struct bgp_damp_info **reuse_list;
|
||||
int reuse_offset;
|
||||
|
||||
/* All dampening information which is not on reuse list. */
|
||||
struct bgp_damp_info *no_reuse_list;
|
||||
/* Reuse index array per-set based. */
|
||||
int *reuse_index;
|
||||
|
||||
/* Reuse timer thread per-set base. */
|
||||
struct thread* t_reuse;
|
||||
/* Reuse list array per-set based. */
|
||||
struct bgp_damp_info **reuse_list;
|
||||
int reuse_offset;
|
||||
|
||||
/* All dampening information which is not on reuse list. */
|
||||
struct bgp_damp_info *no_reuse_list;
|
||||
|
||||
/* Reuse timer thread per-set base. */
|
||||
struct thread *t_reuse;
|
||||
};
|
||||
|
||||
#define BGP_DAMP_NONE 0
|
||||
@ -129,20 +127,22 @@ struct bgp_damp_config
|
||||
#define REUSE_LIST_SIZE 256
|
||||
#define REUSE_ARRAY_SIZE 1024
|
||||
|
||||
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 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 *, json_object *json_path);
|
||||
extern const char * bgp_damp_reuse_time_vty (struct vty *, struct bgp_info *,
|
||||
char *, size_t, u_char, json_object *);
|
||||
extern int bgp_show_dampening_parameters (struct vty *vty, afi_t, safi_t);
|
||||
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 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 *,
|
||||
json_object *json_path);
|
||||
extern const char *bgp_damp_reuse_time_vty(struct vty *, struct bgp_info *,
|
||||
char *, size_t, u_char,
|
||||
json_object *);
|
||||
extern int bgp_show_dampening_parameters(struct vty *vty, afi_t, safi_t);
|
||||
|
||||
#endif /* _QUAGGA_BGP_DAMP_H */
|
||||
|
||||
2706
bgpd/bgp_debug.c
2706
bgpd/bgp_debug.c
File diff suppressed because it is too large
Load Diff
@ -57,10 +57,10 @@ extern int Debug_Radix;
|
||||
#define DETAIL 6
|
||||
|
||||
/* Prototypes. */
|
||||
extern void bgp_debug_init (void);
|
||||
extern void bgp_packet_dump (struct stream *);
|
||||
extern void bgp_debug_init(void);
|
||||
extern void bgp_packet_dump(struct stream *);
|
||||
|
||||
extern int debug (unsigned int option);
|
||||
extern int debug(unsigned int option);
|
||||
|
||||
extern unsigned long conf_bgp_debug_as4;
|
||||
extern unsigned long conf_bgp_debug_neighbor_events;
|
||||
@ -92,10 +92,9 @@ extern struct list *bgp_debug_update_prefixes;
|
||||
extern struct list *bgp_debug_bestpath_prefixes;
|
||||
extern struct list *bgp_debug_zebra_prefixes;
|
||||
|
||||
struct bgp_debug_filter
|
||||
{
|
||||
char *host;
|
||||
struct prefix *p;
|
||||
struct bgp_debug_filter {
|
||||
char *host;
|
||||
struct prefix *p;
|
||||
};
|
||||
|
||||
#define BGP_DEBUG_AS4 0x01
|
||||
@ -122,40 +121,41 @@ struct bgp_debug_filter
|
||||
#define TERM_DEBUG_ON(a, b) (term_bgp_debug_ ## a |= (BGP_DEBUG_ ## b))
|
||||
#define TERM_DEBUG_OFF(a, b) (term_bgp_debug_ ## a &= ~(BGP_DEBUG_ ## b))
|
||||
|
||||
#define DEBUG_ON(a, b) \
|
||||
do { \
|
||||
CONF_DEBUG_ON(a, b); \
|
||||
TERM_DEBUG_ON(a, b); \
|
||||
} while (0)
|
||||
#define DEBUG_OFF(a, b) \
|
||||
do { \
|
||||
CONF_DEBUG_OFF(a, b); \
|
||||
TERM_DEBUG_OFF(a, b); \
|
||||
} while (0)
|
||||
#define DEBUG_ON(a, b) \
|
||||
do { \
|
||||
CONF_DEBUG_ON(a, b); \
|
||||
TERM_DEBUG_ON(a, b); \
|
||||
} while (0)
|
||||
#define DEBUG_OFF(a, b) \
|
||||
do { \
|
||||
CONF_DEBUG_OFF(a, b); \
|
||||
TERM_DEBUG_OFF(a, b); \
|
||||
} while (0)
|
||||
|
||||
#define BGP_DEBUG(a, b) (term_bgp_debug_ ## a & BGP_DEBUG_ ## b)
|
||||
#define CONF_BGP_DEBUG(a, b) (conf_bgp_debug_ ## a & BGP_DEBUG_ ## b)
|
||||
|
||||
extern const char *bgp_type_str[];
|
||||
|
||||
extern int bgp_dump_attr (struct attr *, char *, size_t);
|
||||
extern int bgp_dump_attr(struct attr *, char *, size_t);
|
||||
extern int bgp_debug_peer_updout_enabled(char *host);
|
||||
extern const char *bgp_notify_code_str(char);
|
||||
extern const char *bgp_notify_subcode_str(char, char);
|
||||
extern void bgp_notify_print (struct peer *, struct bgp_notify *, const char *);
|
||||
extern void bgp_notify_print(struct peer *, struct bgp_notify *, const char *);
|
||||
|
||||
extern const struct message bgp_status_msg[];
|
||||
extern int bgp_debug_neighbor_events(struct peer *peer);
|
||||
extern int bgp_debug_keepalive(struct peer *peer);
|
||||
extern int bgp_debug_update(struct peer *peer, struct prefix *p,
|
||||
struct update_group *updgrp, unsigned int inbound);
|
||||
struct update_group *updgrp, unsigned int inbound);
|
||||
extern int bgp_debug_bestpath(struct prefix *p);
|
||||
extern int bgp_debug_zebra(struct prefix *p);
|
||||
|
||||
extern int bgp_debug_count(void);
|
||||
extern const char *bgp_debug_rdpfxpath2str (afi_t, safi_t, struct prefix_rd *,
|
||||
union prefixconstptr, mpls_label_t *,
|
||||
int, u_int32_t, char *, int);
|
||||
const char *bgp_notify_admin_message(char *buf, size_t bufsz, u_char *data, size_t datalen);
|
||||
extern const char *bgp_debug_rdpfxpath2str(afi_t, safi_t, struct prefix_rd *,
|
||||
union prefixconstptr, mpls_label_t *,
|
||||
int, u_int32_t, char *, int);
|
||||
const char *bgp_notify_admin_message(char *buf, size_t bufsz, u_char *data,
|
||||
size_t datalen);
|
||||
|
||||
#endif /* _QUAGGA_BGP_DEBUG_H */
|
||||
|
||||
1223
bgpd/bgp_dump.c
1223
bgpd/bgp_dump.c
File diff suppressed because it is too large
Load Diff
@ -49,9 +49,9 @@
|
||||
#define TABLE_DUMP_V2_PEER_INDEX_TABLE_AS2 0
|
||||
#define TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4 2
|
||||
|
||||
extern void bgp_dump_init (void);
|
||||
extern void bgp_dump_finish (void);
|
||||
extern void bgp_dump_state (struct peer *, int, int);
|
||||
extern void bgp_dump_packet (struct peer *, int, struct stream *);
|
||||
extern void bgp_dump_init(void);
|
||||
extern void bgp_dump_finish(void);
|
||||
extern void bgp_dump_state(struct peer *, int, int);
|
||||
extern void bgp_dump_packet(struct peer *, int, struct stream *);
|
||||
|
||||
#endif /* _QUAGGA_BGP_DUMP_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -56,25 +56,23 @@
|
||||
#define ECOMMUNITY_FLAG_NON_TRANSITIVE 0x40
|
||||
|
||||
/* Extended Communities attribute. */
|
||||
struct ecommunity
|
||||
{
|
||||
/* Reference counter. */
|
||||
unsigned long refcnt;
|
||||
struct ecommunity {
|
||||
/* Reference counter. */
|
||||
unsigned long refcnt;
|
||||
|
||||
/* Size of Extended Communities attribute. */
|
||||
int size;
|
||||
/* Size of Extended Communities attribute. */
|
||||
int size;
|
||||
|
||||
/* Extended Communities value. */
|
||||
u_int8_t *val;
|
||||
/* Extended Communities value. */
|
||||
u_int8_t *val;
|
||||
|
||||
/* Human readable format string. */
|
||||
char *str;
|
||||
/* Human readable format string. */
|
||||
char *str;
|
||||
};
|
||||
|
||||
/* Extended community value is eight octet. */
|
||||
struct ecommunity_val
|
||||
{
|
||||
char val[ECOMMUNITY_SIZE];
|
||||
struct ecommunity_val {
|
||||
char val[ECOMMUNITY_SIZE];
|
||||
};
|
||||
|
||||
#define ecom_length(X) ((X)->size * ECOMMUNITY_SIZE)
|
||||
@ -82,72 +80,74 @@ struct ecommunity_val
|
||||
/*
|
||||
* Encode BGP Route Target AS:nn.
|
||||
*/
|
||||
static inline void
|
||||
encode_route_target_as (as_t as, u_int32_t val,
|
||||
struct ecommunity_val *eval)
|
||||
static inline void encode_route_target_as(as_t as, u_int32_t val,
|
||||
struct ecommunity_val *eval)
|
||||
{
|
||||
eval->val[0] = ECOMMUNITY_ENCODE_AS;
|
||||
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
|
||||
eval->val[2] = (as >> 8) & 0xff;
|
||||
eval->val[3] = as & 0xff;
|
||||
eval->val[4] = (val >> 24) & 0xff;
|
||||
eval->val[5] = (val >> 16) & 0xff;
|
||||
eval->val[6] = (val >> 8) & 0xff;
|
||||
eval->val[7] = val & 0xff;
|
||||
eval->val[0] = ECOMMUNITY_ENCODE_AS;
|
||||
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
|
||||
eval->val[2] = (as >> 8) & 0xff;
|
||||
eval->val[3] = as & 0xff;
|
||||
eval->val[4] = (val >> 24) & 0xff;
|
||||
eval->val[5] = (val >> 16) & 0xff;
|
||||
eval->val[6] = (val >> 8) & 0xff;
|
||||
eval->val[7] = val & 0xff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode BGP Route Target IP:nn.
|
||||
*/
|
||||
static inline void
|
||||
encode_route_target_ip (struct in_addr ip, u_int16_t val,
|
||||
struct ecommunity_val *eval)
|
||||
static inline void encode_route_target_ip(struct in_addr ip, u_int16_t val,
|
||||
struct ecommunity_val *eval)
|
||||
{
|
||||
eval->val[0] = ECOMMUNITY_ENCODE_IP;
|
||||
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
|
||||
memcpy (&eval->val[2], &ip, sizeof (struct in_addr));
|
||||
eval->val[6] = (val >> 8) & 0xff;
|
||||
eval->val[7] = val & 0xff;
|
||||
eval->val[0] = ECOMMUNITY_ENCODE_IP;
|
||||
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
|
||||
memcpy(&eval->val[2], &ip, sizeof(struct in_addr));
|
||||
eval->val[6] = (val >> 8) & 0xff;
|
||||
eval->val[7] = val & 0xff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode BGP Route Target AS4:nn.
|
||||
*/
|
||||
static inline void
|
||||
encode_route_target_as4 (as_t as, u_int16_t val,
|
||||
struct ecommunity_val *eval)
|
||||
static inline void encode_route_target_as4(as_t as, u_int16_t val,
|
||||
struct ecommunity_val *eval)
|
||||
{
|
||||
eval->val[0] = ECOMMUNITY_ENCODE_AS4;
|
||||
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
|
||||
eval->val[2] = (as >> 24) & 0xff;
|
||||
eval->val[3] = (as >> 16) & 0xff;
|
||||
eval->val[4] = (as >> 8) & 0xff;
|
||||
eval->val[5] = as & 0xff;
|
||||
eval->val[6] = (val >> 8) & 0xff;
|
||||
eval->val[7] = val & 0xff;
|
||||
eval->val[0] = ECOMMUNITY_ENCODE_AS4;
|
||||
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
|
||||
eval->val[2] = (as >> 24) & 0xff;
|
||||
eval->val[3] = (as >> 16) & 0xff;
|
||||
eval->val[4] = (as >> 8) & 0xff;
|
||||
eval->val[5] = as & 0xff;
|
||||
eval->val[6] = (val >> 8) & 0xff;
|
||||
eval->val[7] = val & 0xff;
|
||||
}
|
||||
|
||||
extern void ecommunity_init (void);
|
||||
extern void ecommunity_finish (void);
|
||||
extern void ecommunity_free (struct ecommunity **);
|
||||
extern struct ecommunity *ecommunity_parse (u_int8_t *, u_short);
|
||||
extern struct ecommunity *ecommunity_dup (struct ecommunity *);
|
||||
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 void ecommunity_unintern (struct ecommunity **);
|
||||
extern unsigned int ecommunity_hash_make (void *);
|
||||
extern struct ecommunity *ecommunity_str2com (const char *, int, int);
|
||||
extern char *ecommunity_ecom2str (struct ecommunity *, int, int);
|
||||
extern int ecommunity_match (const struct ecommunity *, const struct ecommunity *);
|
||||
extern char *ecommunity_str (struct ecommunity *);
|
||||
extern struct ecommunity_val *ecommunity_lookup (const struct ecommunity *, uint8_t, uint8_t );
|
||||
extern int ecommunity_add_val (struct ecommunity *ecom, struct ecommunity_val *eval);
|
||||
extern void ecommunity_init(void);
|
||||
extern void ecommunity_finish(void);
|
||||
extern void ecommunity_free(struct ecommunity **);
|
||||
extern struct ecommunity *ecommunity_parse(u_int8_t *, u_short);
|
||||
extern struct ecommunity *ecommunity_dup(struct ecommunity *);
|
||||
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 void ecommunity_unintern(struct ecommunity **);
|
||||
extern unsigned int ecommunity_hash_make(void *);
|
||||
extern struct ecommunity *ecommunity_str2com(const char *, int, int);
|
||||
extern char *ecommunity_ecom2str(struct ecommunity *, int, int);
|
||||
extern int ecommunity_match(const struct ecommunity *,
|
||||
const struct ecommunity *);
|
||||
extern char *ecommunity_str(struct ecommunity *);
|
||||
extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *,
|
||||
uint8_t, uint8_t);
|
||||
extern int ecommunity_add_val(struct ecommunity *ecom,
|
||||
struct ecommunity_val *eval);
|
||||
|
||||
/* for vpn */
|
||||
extern struct ecommunity *ecommunity_new (void);
|
||||
extern int ecommunity_add_val (struct ecommunity *, struct ecommunity_val *);
|
||||
extern int ecommunity_strip (struct ecommunity *ecom, uint8_t type, uint8_t subtype);
|
||||
extern struct ecommunity *ecommunity_new (void);
|
||||
extern struct ecommunity *ecommunity_new(void);
|
||||
extern int ecommunity_add_val(struct ecommunity *, struct ecommunity_val *);
|
||||
extern int ecommunity_strip(struct ecommunity *ecom, uint8_t type,
|
||||
uint8_t subtype);
|
||||
extern struct ecommunity *ecommunity_new(void);
|
||||
#endif /* _QUAGGA_BGP_ECOMMUNITY_H */
|
||||
|
||||
1410
bgpd/bgp_encap_tlv.c
1410
bgpd/bgp_encap_tlv.c
File diff suppressed because it is too large
Load Diff
@ -19,158 +19,116 @@
|
||||
#ifndef _QUAGGA_BGP_ENCAP_TLV_H
|
||||
#define _QUAGGA_BGP_ENCAP_TLV_H
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* TUNNEL TYPE-SPECIFIC TLV ENCODE
|
||||
***********************************************************************/
|
||||
|
||||
extern void
|
||||
bgp_encap_type_l2tpv3overip_to_tlv(
|
||||
struct bgp_encap_type_l2tpv3_over_ip *bet,
|
||||
struct attr *attr);
|
||||
bgp_encap_type_l2tpv3overip_to_tlv(struct bgp_encap_type_l2tpv3_over_ip *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void bgp_encap_type_gre_to_tlv(struct bgp_encap_type_gre *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void bgp_encap_type_ip_in_ip_to_tlv(struct bgp_encap_type_ip_in_ip *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void bgp_encap_type_transmit_tunnel_endpoint(
|
||||
struct bgp_encap_type_transmit_tunnel_endpoint *bet, struct attr *attr);
|
||||
|
||||
extern void bgp_encap_type_ipsec_in_tunnel_mode_to_tlv(
|
||||
struct bgp_encap_type_ipsec_in_tunnel_mode *bet, struct attr *attr);
|
||||
|
||||
extern void bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
|
||||
struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
|
||||
struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void bgp_encap_type_pbb_to_tlv(struct bgp_encap_type_pbb *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void bgp_encap_type_vxlan_to_tlv(struct bgp_encap_type_vxlan *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void bgp_encap_type_nvgre_to_tlv(struct bgp_encap_type_nvgre *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void bgp_encap_type_mpls_to_tlv(struct bgp_encap_type_mpls *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void
|
||||
bgp_encap_type_gre_to_tlv(
|
||||
struct bgp_encap_type_gre *bet,
|
||||
struct attr *attr);
|
||||
bgp_encap_type_mpls_in_gre_to_tlv(struct bgp_encap_type_mpls_in_gre *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void
|
||||
bgp_encap_type_ip_in_ip_to_tlv(
|
||||
struct bgp_encap_type_ip_in_ip *bet,
|
||||
struct attr *attr);
|
||||
bgp_encap_type_vxlan_gpe_to_tlv(struct bgp_encap_type_vxlan_gpe *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void
|
||||
bgp_encap_type_transmit_tunnel_endpoint(
|
||||
struct bgp_encap_type_transmit_tunnel_endpoint *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void
|
||||
bgp_encap_type_ipsec_in_tunnel_mode_to_tlv(
|
||||
struct bgp_encap_type_ipsec_in_tunnel_mode *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void
|
||||
bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
|
||||
struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void
|
||||
bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
|
||||
struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void
|
||||
bgp_encap_type_pbb_to_tlv(
|
||||
struct bgp_encap_type_pbb *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void
|
||||
bgp_encap_type_vxlan_to_tlv(
|
||||
struct bgp_encap_type_vxlan *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void
|
||||
bgp_encap_type_nvgre_to_tlv(
|
||||
struct bgp_encap_type_nvgre *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void
|
||||
bgp_encap_type_mpls_to_tlv(
|
||||
struct bgp_encap_type_mpls *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void
|
||||
bgp_encap_type_mpls_in_gre_to_tlv(
|
||||
struct bgp_encap_type_mpls_in_gre *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void
|
||||
bgp_encap_type_vxlan_gpe_to_tlv(
|
||||
struct bgp_encap_type_vxlan_gpe *bet,
|
||||
struct attr *attr);
|
||||
|
||||
extern void
|
||||
bgp_encap_type_mpls_in_udp_to_tlv(
|
||||
struct bgp_encap_type_mpls_in_udp *bet,
|
||||
struct attr *attr);
|
||||
bgp_encap_type_mpls_in_udp_to_tlv(struct bgp_encap_type_mpls_in_udp *bet,
|
||||
struct attr *attr);
|
||||
|
||||
/***********************************************************************
|
||||
* TUNNEL TYPE-SPECIFIC TLV DECODE
|
||||
***********************************************************************/
|
||||
|
||||
extern int
|
||||
tlv_to_bgp_encap_type_l2tpv3overip(
|
||||
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
|
||||
struct bgp_encap_type_l2tpv3_over_ip *bet); /* caller-allocated */
|
||||
extern int tlv_to_bgp_encap_type_l2tpv3overip(
|
||||
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
|
||||
struct bgp_encap_type_l2tpv3_over_ip *bet); /* caller-allocated */
|
||||
|
||||
extern int tlv_to_bgp_encap_type_gre(
|
||||
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
|
||||
struct bgp_encap_type_gre *bet); /* caller-allocated */
|
||||
|
||||
extern int tlv_to_bgp_encap_type_ip_in_ip(
|
||||
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
|
||||
struct bgp_encap_type_ip_in_ip *bet); /* caller-allocated */
|
||||
|
||||
extern int tlv_to_bgp_encap_type_transmit_tunnel_endpoint(
|
||||
struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_transmit_tunnel_endpoint *bet);
|
||||
|
||||
extern int tlv_to_bgp_encap_type_ipsec_in_tunnel_mode(
|
||||
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
|
||||
struct bgp_encap_type_ipsec_in_tunnel_mode *bet); /* caller-allocated */
|
||||
|
||||
extern int tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode(
|
||||
struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet);
|
||||
|
||||
extern int tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode(
|
||||
struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet);
|
||||
|
||||
extern int tlv_to_bgp_encap_type_vxlan(struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_vxlan *bet);
|
||||
|
||||
extern int tlv_to_bgp_encap_type_nvgre(struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_nvgre *bet);
|
||||
|
||||
extern int tlv_to_bgp_encap_type_mpls(struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_mpls *bet);
|
||||
|
||||
extern int tlv_to_bgp_encap_type_mpls(struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_mpls *bet);
|
||||
|
||||
extern int
|
||||
tlv_to_bgp_encap_type_gre(
|
||||
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
|
||||
struct bgp_encap_type_gre *bet); /* caller-allocated */
|
||||
tlv_to_bgp_encap_type_mpls_in_gre(struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_mpls_in_gre *bet);
|
||||
|
||||
extern int
|
||||
tlv_to_bgp_encap_type_ip_in_ip(
|
||||
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
|
||||
struct bgp_encap_type_ip_in_ip *bet); /* caller-allocated */
|
||||
tlv_to_bgp_encap_type_vxlan_gpe(struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_vxlan_gpe *bet);
|
||||
|
||||
extern int
|
||||
tlv_to_bgp_encap_type_transmit_tunnel_endpoint(
|
||||
struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_transmit_tunnel_endpoint *bet);
|
||||
tlv_to_bgp_encap_type_mpls_in_udp(struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_mpls_in_udp *bet);
|
||||
|
||||
extern int
|
||||
tlv_to_bgp_encap_type_ipsec_in_tunnel_mode(
|
||||
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
|
||||
struct bgp_encap_type_ipsec_in_tunnel_mode *bet); /* caller-allocated */
|
||||
|
||||
extern int
|
||||
tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode(
|
||||
struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet);
|
||||
|
||||
extern int
|
||||
tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode(
|
||||
struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet);
|
||||
|
||||
extern int
|
||||
tlv_to_bgp_encap_type_vxlan(
|
||||
struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_vxlan *bet);
|
||||
|
||||
extern int
|
||||
tlv_to_bgp_encap_type_nvgre(
|
||||
struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_nvgre *bet);
|
||||
|
||||
extern int
|
||||
tlv_to_bgp_encap_type_mpls(
|
||||
struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_mpls *bet);
|
||||
|
||||
extern int
|
||||
tlv_to_bgp_encap_type_mpls(
|
||||
struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_mpls *bet);
|
||||
|
||||
extern int
|
||||
tlv_to_bgp_encap_type_mpls_in_gre(
|
||||
struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_mpls_in_gre *bet);
|
||||
|
||||
extern int
|
||||
tlv_to_bgp_encap_type_vxlan_gpe(
|
||||
struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_vxlan_gpe *bet);
|
||||
|
||||
extern int
|
||||
tlv_to_bgp_encap_type_mpls_in_udp(
|
||||
struct bgp_attr_encap_subtlv *stlv,
|
||||
struct bgp_encap_type_mpls_in_udp *bet);
|
||||
|
||||
extern int
|
||||
tlv_to_bgp_encap_type_pbb(
|
||||
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
|
||||
struct bgp_encap_type_pbb *bet); /* caller-allocated */
|
||||
extern int tlv_to_bgp_encap_type_pbb(
|
||||
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
|
||||
struct bgp_encap_type_pbb *bet); /* caller-allocated */
|
||||
|
||||
#endif /* _QUAGGA_BGP_ENCAP_TLV_H */
|
||||
|
||||
@ -21,70 +21,73 @@
|
||||
|
||||
#include "bgpd/bgp_ecommunity.h"
|
||||
|
||||
/* from http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#tunnel-types */
|
||||
/* from
|
||||
* http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#tunnel-types
|
||||
*/
|
||||
typedef enum {
|
||||
BGP_ENCAP_TYPE_RESERVED=0,
|
||||
BGP_ENCAP_TYPE_L2TPV3_OVER_IP=1,
|
||||
BGP_ENCAP_TYPE_GRE=2,
|
||||
BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT=3,
|
||||
BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE=4,
|
||||
BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE=5,
|
||||
BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE=6,
|
||||
BGP_ENCAP_TYPE_IP_IN_IP=7,
|
||||
BGP_ENCAP_TYPE_VXLAN=8,
|
||||
BGP_ENCAP_TYPE_NVGRE=9,
|
||||
BGP_ENCAP_TYPE_MPLS=10, /* NOTE: Encap SAFI&Attribute not used */
|
||||
BGP_ENCAP_TYPE_MPLS_IN_GRE=11,
|
||||
BGP_ENCAP_TYPE_VXLAN_GPE=12,
|
||||
BGP_ENCAP_TYPE_MPLS_IN_UDP=13,
|
||||
BGP_ENCAP_TYPE_PBB
|
||||
BGP_ENCAP_TYPE_RESERVED = 0,
|
||||
BGP_ENCAP_TYPE_L2TPV3_OVER_IP = 1,
|
||||
BGP_ENCAP_TYPE_GRE = 2,
|
||||
BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT = 3,
|
||||
BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE = 4,
|
||||
BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE = 5,
|
||||
BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE = 6,
|
||||
BGP_ENCAP_TYPE_IP_IN_IP = 7,
|
||||
BGP_ENCAP_TYPE_VXLAN = 8,
|
||||
BGP_ENCAP_TYPE_NVGRE = 9,
|
||||
BGP_ENCAP_TYPE_MPLS = 10, /* NOTE: Encap SAFI&Attribute not used */
|
||||
BGP_ENCAP_TYPE_MPLS_IN_GRE = 11,
|
||||
BGP_ENCAP_TYPE_VXLAN_GPE = 12,
|
||||
BGP_ENCAP_TYPE_MPLS_IN_UDP = 13,
|
||||
BGP_ENCAP_TYPE_PBB
|
||||
} bgp_encap_types;
|
||||
|
||||
typedef enum {
|
||||
BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION=1,
|
||||
BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE=2,
|
||||
BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA=3,
|
||||
BGP_ENCAP_SUBTLV_TYPE_COLOR=4,
|
||||
BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT=6 /* speculative, IANA assignment TBD */
|
||||
BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION = 1,
|
||||
BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE = 2,
|
||||
BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA = 3,
|
||||
BGP_ENCAP_SUBTLV_TYPE_COLOR = 4,
|
||||
BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT =
|
||||
6 /* speculative, IANA assignment TBD */
|
||||
} bgp_encap_subtlv_types;
|
||||
|
||||
/*
|
||||
* Tunnel Encapsulation Attribute subtlvs
|
||||
*/
|
||||
struct bgp_tea_subtlv_encap_l2tpv3_over_ip {
|
||||
uint32_t sessionid;
|
||||
uint8_t cookie_length;
|
||||
uint8_t cookie[8];
|
||||
uint32_t sessionid;
|
||||
uint8_t cookie_length;
|
||||
uint8_t cookie[8];
|
||||
};
|
||||
|
||||
struct bgp_tea_subtlv_encap_gre_key {
|
||||
uint32_t gre_key;
|
||||
uint32_t gre_key;
|
||||
};
|
||||
|
||||
struct bgp_tea_subtlv_encap_pbb {
|
||||
uint32_t flag_isid:1;
|
||||
uint32_t flag_vid:1;
|
||||
uint32_t isid:24;
|
||||
uint16_t vid:12;
|
||||
uint8_t macaddr[6];
|
||||
uint32_t flag_isid : 1;
|
||||
uint32_t flag_vid : 1;
|
||||
uint32_t isid : 24;
|
||||
uint16_t vid : 12;
|
||||
uint8_t macaddr[6];
|
||||
};
|
||||
|
||||
struct bgp_tea_subtlv_proto_type {
|
||||
uint16_t proto; /* ether-type */
|
||||
uint16_t proto; /* ether-type */
|
||||
};
|
||||
|
||||
struct bgp_tea_subtlv_color {
|
||||
uint32_t color;
|
||||
uint32_t color;
|
||||
};
|
||||
|
||||
/* per draft-rosen-idr-tunnel-encaps */
|
||||
struct bgp_tea_subtlv_remote_endpoint {
|
||||
u_char family; /* IPv4 or IPv6 */
|
||||
union {
|
||||
struct in_addr v4;
|
||||
struct in6_addr v6;
|
||||
} ip_address;
|
||||
as_t as4; /* always 4 bytes */
|
||||
u_char family; /* IPv4 or IPv6 */
|
||||
union {
|
||||
struct in_addr v4;
|
||||
struct in6_addr v6;
|
||||
} ip_address;
|
||||
as_t as4; /* always 4 bytes */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -94,9 +97,9 @@ struct bgp_tea_subtlv_remote_endpoint {
|
||||
#define BGP_ENCAP_SUBTLV_IPSEC_TA_SIZE 20
|
||||
|
||||
struct bgp_tea_subtlv_ipsec_ta {
|
||||
uint16_t authenticator_type; /* only type 1 is supported so far */
|
||||
uint8_t authenticator_length; /* octets in value field */
|
||||
uint8_t value[BGP_ENCAP_SUBTLV_IPSEC_TA_SIZE];
|
||||
uint16_t authenticator_type; /* only type 1 is supported so far */
|
||||
uint8_t authenticator_length; /* octets in value field */
|
||||
uint8_t value[BGP_ENCAP_SUBTLV_IPSEC_TA_SIZE];
|
||||
};
|
||||
|
||||
/*
|
||||
@ -117,113 +120,112 @@ struct bgp_tea_subtlv_ipsec_ta {
|
||||
* Tunnel Type-specific APIs
|
||||
*/
|
||||
struct bgp_encap_type_reserved {
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
};
|
||||
|
||||
struct bgp_encap_type_l2tpv3_over_ip {
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_encap_l2tpv3_over_ip st_encap;
|
||||
struct bgp_tea_subtlv_proto_type st_proto; /* optional */
|
||||
struct bgp_tea_subtlv_color st_color; /* optional */
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_encap_l2tpv3_over_ip st_encap;
|
||||
struct bgp_tea_subtlv_proto_type st_proto; /* optional */
|
||||
struct bgp_tea_subtlv_color st_color; /* optional */
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
};
|
||||
|
||||
struct bgp_encap_type_gre {
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_encap_gre_key st_encap; /* optional */
|
||||
struct bgp_tea_subtlv_proto_type st_proto; /* optional */
|
||||
struct bgp_tea_subtlv_color st_color; /* optional */
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_encap_gre_key st_encap; /* optional */
|
||||
struct bgp_tea_subtlv_proto_type st_proto; /* optional */
|
||||
struct bgp_tea_subtlv_color st_color; /* optional */
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
};
|
||||
|
||||
struct bgp_encap_type_ip_in_ip {
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_proto_type st_proto; /* optional */
|
||||
struct bgp_tea_subtlv_color st_color; /* optional */
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_proto_type st_proto; /* optional */
|
||||
struct bgp_tea_subtlv_color st_color; /* optional */
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
};
|
||||
|
||||
struct bgp_encap_type_transmit_tunnel_endpoint {
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
/* No subtlvs defined in spec? */
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
/* No subtlvs defined in spec? */
|
||||
};
|
||||
|
||||
struct bgp_encap_type_ipsec_in_tunnel_mode {
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
};
|
||||
|
||||
struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode {
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
};
|
||||
|
||||
struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode {
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
};
|
||||
|
||||
#define VXLAN_ENCAP_MASK_VNID_VALID 0x80000000
|
||||
#define VXLAN_ENCAP_MASK_MAC_VALID 0x40000000
|
||||
|
||||
struct bgp_encap_type_vxlan {
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
/* draft-ietf-idr-tunnel-encaps-02 */
|
||||
uint32_t vnid; /* does not include V and M bit */
|
||||
uint8_t *mac_address; /* optional */
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
/* draft-ietf-idr-tunnel-encaps-02 */
|
||||
uint32_t vnid; /* does not include V and M bit */
|
||||
uint8_t *mac_address; /* optional */
|
||||
};
|
||||
|
||||
struct bgp_encap_type_nvgre {
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
/* No subtlvs defined in spec? */
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
/* No subtlvs defined in spec? */
|
||||
};
|
||||
|
||||
struct bgp_encap_type_mpls {
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
/* No subtlvs defined in spec? */
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
/* No subtlvs defined in spec? */
|
||||
};
|
||||
|
||||
struct bgp_encap_type_mpls_in_gre {
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
/* No subtlvs defined in spec? */
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
/* No subtlvs defined in spec? */
|
||||
};
|
||||
|
||||
struct bgp_encap_type_vxlan_gpe {
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
/* No subtlvs defined in spec? */
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
/* No subtlvs defined in spec? */
|
||||
};
|
||||
|
||||
struct bgp_encap_type_mpls_in_udp {
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
/* No subtlvs defined in spec? */
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
/* No subtlvs defined in spec? */
|
||||
};
|
||||
|
||||
struct bgp_encap_type_pbb {
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
struct bgp_tea_subtlv_encap_pbb st_encap;
|
||||
uint32_t valid_subtlvs;
|
||||
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
|
||||
struct bgp_tea_subtlv_encap_pbb st_encap;
|
||||
};
|
||||
|
||||
static inline void
|
||||
encode_encap_extcomm (bgp_encap_types tnl_type,
|
||||
struct ecommunity_val *eval)
|
||||
static inline void encode_encap_extcomm(bgp_encap_types tnl_type,
|
||||
struct ecommunity_val *eval)
|
||||
{
|
||||
memset (eval, 0, sizeof (*eval));
|
||||
eval->val[0] = ECOMMUNITY_ENCODE_OPAQUE;
|
||||
eval->val[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP;
|
||||
eval->val[6] = ((tnl_type) >> 8) & 0xff;
|
||||
eval->val[7] = (tnl_type) & 0xff;
|
||||
memset(eval, 0, sizeof(*eval));
|
||||
eval->val[0] = ECOMMUNITY_ENCODE_OPAQUE;
|
||||
eval->val[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP;
|
||||
eval->val[6] = ((tnl_type) >> 8) & 0xff;
|
||||
eval->val[7] = (tnl_type)&0xff;
|
||||
}
|
||||
|
||||
#endif /* _QUAGGA_BGP_ENCAP_TYPES_H */
|
||||
|
||||
3822
bgpd/bgp_evpn.c
3822
bgpd/bgp_evpn.c
File diff suppressed because it is too large
Load Diff
@ -25,41 +25,29 @@
|
||||
|
||||
#define EVPN_ROUTE_STRLEN 200 /* Must be >> MAC + IPv6 strings. */
|
||||
|
||||
extern void
|
||||
bgp_evpn_handle_router_id_update (struct bgp *bgp, int withdraw);
|
||||
extern char *
|
||||
bgp_evpn_label2str (mpls_label_t *label, char *buf, int len);
|
||||
extern char *
|
||||
bgp_evpn_route2str (struct prefix_evpn *p, char *buf, int len);
|
||||
extern void
|
||||
bgp_evpn_encode_prefix (struct stream *s, struct prefix *p,
|
||||
struct prefix_rd *prd, mpls_label_t *label,
|
||||
struct attr *attr, int addpath_encode,
|
||||
u_int32_t addpath_tx_id);
|
||||
extern void bgp_evpn_handle_router_id_update(struct bgp *bgp, int withdraw);
|
||||
extern char *bgp_evpn_label2str(mpls_label_t *label, char *buf, int len);
|
||||
extern char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len);
|
||||
extern void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
|
||||
struct prefix_rd *prd, mpls_label_t *label,
|
||||
struct attr *attr, int addpath_encode,
|
||||
u_int32_t addpath_tx_id);
|
||||
extern int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
|
||||
struct bgp_nlri *packet, int withdraw);
|
||||
extern int
|
||||
bgp_evpn_import_route (struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
struct prefix *p, struct bgp_info *ri);
|
||||
extern int
|
||||
bgp_evpn_unimport_route (struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
struct prefix *p, struct bgp_info *ri);
|
||||
extern int
|
||||
bgp_evpn_local_macip_del (struct bgp *bgp, vni_t vni,
|
||||
struct ethaddr *mac, struct ipaddr *ip);
|
||||
extern int
|
||||
bgp_evpn_local_macip_add (struct bgp *bgp, vni_t vni,
|
||||
struct ethaddr *mac, struct ipaddr *ip,
|
||||
u_char sticky);
|
||||
extern int
|
||||
bgp_evpn_local_vni_del (struct bgp *bgp, vni_t vni);
|
||||
extern int
|
||||
bgp_evpn_local_vni_add (struct bgp *bgp, vni_t vni, struct in_addr originator_ip);
|
||||
extern void
|
||||
bgp_evpn_cleanup_on_disable (struct bgp *bgp);
|
||||
extern void
|
||||
bgp_evpn_cleanup (struct bgp *bgp);
|
||||
extern void
|
||||
bgp_evpn_init (struct bgp *bgp);
|
||||
extern int bgp_evpn_import_route(struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
struct prefix *p, struct bgp_info *ri);
|
||||
extern int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
struct prefix *p, struct bgp_info *ri);
|
||||
extern int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni,
|
||||
struct ethaddr *mac, struct ipaddr *ip);
|
||||
extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni,
|
||||
struct ethaddr *mac, struct ipaddr *ip,
|
||||
u_char sticky);
|
||||
extern int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni);
|
||||
extern int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
|
||||
struct in_addr originator_ip);
|
||||
extern void bgp_evpn_cleanup_on_disable(struct bgp *bgp);
|
||||
extern void bgp_evpn_cleanup(struct bgp *bgp);
|
||||
extern void bgp_evpn_init(struct bgp *bgp);
|
||||
|
||||
#endif /* _QUAGGA_BGP_EVPN_H */
|
||||
|
||||
@ -33,13 +33,12 @@
|
||||
#define EVPN_TYPE_3_ROUTE_PREFIXLEN 224
|
||||
|
||||
/* EVPN route types. */
|
||||
typedef enum
|
||||
{
|
||||
BGP_EVPN_AD_ROUTE = 1, /* Ethernet Auto-Discovery (A-D) route */
|
||||
BGP_EVPN_MAC_IP_ROUTE, /* MAC/IP Advertisement route */
|
||||
BGP_EVPN_IMET_ROUTE, /* Inclusive Multicast Ethernet Tag route */
|
||||
BGP_EVPN_ES_ROUTE, /* Ethernet Segment route */
|
||||
BGP_EVPN_IP_PREFIX_ROUTE, /* IP Prefix route */
|
||||
typedef enum {
|
||||
BGP_EVPN_AD_ROUTE = 1, /* Ethernet Auto-Discovery (A-D) route */
|
||||
BGP_EVPN_MAC_IP_ROUTE, /* MAC/IP Advertisement route */
|
||||
BGP_EVPN_IMET_ROUTE, /* Inclusive Multicast Ethernet Tag route */
|
||||
BGP_EVPN_ES_ROUTE, /* Ethernet Segment route */
|
||||
BGP_EVPN_IP_PREFIX_ROUTE, /* IP Prefix route */
|
||||
} bgp_evpn_route_type;
|
||||
|
||||
/*
|
||||
@ -50,33 +49,32 @@ typedef enum
|
||||
* on the system (through interaction with zebra) as well as pre-configured
|
||||
* VNIs (which need to be defined in the system to become "live").
|
||||
*/
|
||||
struct bgpevpn
|
||||
{
|
||||
vni_t vni;
|
||||
u_int32_t flags;
|
||||
struct bgpevpn {
|
||||
vni_t vni;
|
||||
u_int32_t flags;
|
||||
#define VNI_FLAG_CFGD 0x1 /* VNI is user configured */
|
||||
#define VNI_FLAG_LIVE 0x2 /* VNI is "live" */
|
||||
#define VNI_FLAG_RD_CFGD 0x4 /* RD is user configured. */
|
||||
#define VNI_FLAG_IMPRT_CFGD 0x8 /* Import RT is user configured */
|
||||
#define VNI_FLAG_EXPRT_CFGD 0x10 /* Export RT is user configured */
|
||||
|
||||
/* Id for deriving the RD automatically for this VNI */
|
||||
u_int16_t rd_id;
|
||||
/* Id for deriving the RD automatically for this VNI */
|
||||
u_int16_t rd_id;
|
||||
|
||||
/* RD for this VNI. */
|
||||
struct prefix_rd prd;
|
||||
/* RD for this VNI. */
|
||||
struct prefix_rd prd;
|
||||
|
||||
/* Route type 3 field */
|
||||
struct in_addr originator_ip;
|
||||
/* Route type 3 field */
|
||||
struct in_addr originator_ip;
|
||||
|
||||
/* Import and Export RTs. */
|
||||
struct list *import_rtl;
|
||||
struct list *export_rtl;
|
||||
/* Import and Export RTs. */
|
||||
struct list *import_rtl;
|
||||
struct list *export_rtl;
|
||||
|
||||
/* Route table for EVPN routes for this VNI. */
|
||||
struct bgp_table *route_table;
|
||||
/* Route table for EVPN routes for this VNI. */
|
||||
struct bgp_table *route_table;
|
||||
|
||||
QOBJ_FIELDS
|
||||
QOBJ_FIELDS
|
||||
};
|
||||
|
||||
DECLARE_QOBJ_TYPE(bgpevpn)
|
||||
@ -85,148 +83,131 @@ DECLARE_QOBJ_TYPE(bgpevpn)
|
||||
* The Import RTs of all VNIs are maintained in a hash table with each
|
||||
* RT linking to all VNIs that will import routes matching this RT.
|
||||
*/
|
||||
struct irt_node
|
||||
{
|
||||
/* RT */
|
||||
struct ecommunity_val rt;
|
||||
struct irt_node {
|
||||
/* RT */
|
||||
struct ecommunity_val rt;
|
||||
|
||||
/* List of VNIs importing routes matching this RT. */
|
||||
struct list *vnis;
|
||||
/* List of VNIs importing routes matching this RT. */
|
||||
struct list *vnis;
|
||||
};
|
||||
|
||||
#define RT_TYPE_IMPORT 1
|
||||
#define RT_TYPE_EXPORT 2
|
||||
#define RT_TYPE_BOTH 3
|
||||
|
||||
static inline int
|
||||
is_vni_configured (struct bgpevpn *vpn)
|
||||
static inline int is_vni_configured(struct bgpevpn *vpn)
|
||||
{
|
||||
return (CHECK_FLAG (vpn->flags, VNI_FLAG_CFGD));
|
||||
return (CHECK_FLAG(vpn->flags, VNI_FLAG_CFGD));
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_vni_live (struct bgpevpn *vpn)
|
||||
static inline int is_vni_live(struct bgpevpn *vpn)
|
||||
{
|
||||
return (CHECK_FLAG (vpn->flags, VNI_FLAG_LIVE));
|
||||
return (CHECK_FLAG(vpn->flags, VNI_FLAG_LIVE));
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_rd_configured (struct bgpevpn *vpn)
|
||||
static inline int is_rd_configured(struct bgpevpn *vpn)
|
||||
{
|
||||
return (CHECK_FLAG (vpn->flags, VNI_FLAG_RD_CFGD));
|
||||
return (CHECK_FLAG(vpn->flags, VNI_FLAG_RD_CFGD));
|
||||
}
|
||||
|
||||
static inline int
|
||||
bgp_evpn_rd_matches_existing (struct bgpevpn *vpn, struct prefix_rd *prd)
|
||||
static inline int bgp_evpn_rd_matches_existing(struct bgpevpn *vpn,
|
||||
struct prefix_rd *prd)
|
||||
{
|
||||
return(memcmp (&vpn->prd.val, prd->val, ECOMMUNITY_SIZE) == 0);
|
||||
return (memcmp(&vpn->prd.val, prd->val, ECOMMUNITY_SIZE) == 0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_import_rt_configured (struct bgpevpn *vpn)
|
||||
static inline int is_import_rt_configured(struct bgpevpn *vpn)
|
||||
{
|
||||
return (CHECK_FLAG (vpn->flags, VNI_FLAG_IMPRT_CFGD));
|
||||
return (CHECK_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD));
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_export_rt_configured (struct bgpevpn *vpn)
|
||||
static inline int is_export_rt_configured(struct bgpevpn *vpn)
|
||||
{
|
||||
return (CHECK_FLAG (vpn->flags, VNI_FLAG_EXPRT_CFGD));
|
||||
return (CHECK_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD));
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_vni_param_configured (struct bgpevpn *vpn)
|
||||
static inline int is_vni_param_configured(struct bgpevpn *vpn)
|
||||
{
|
||||
return (is_rd_configured (vpn) ||
|
||||
is_import_rt_configured (vpn) ||
|
||||
is_export_rt_configured (vpn));
|
||||
return (is_rd_configured(vpn) || is_import_rt_configured(vpn)
|
||||
|| is_export_rt_configured(vpn));
|
||||
}
|
||||
|
||||
static inline void
|
||||
vni2label (vni_t vni, mpls_label_t *label)
|
||||
static inline void vni2label(vni_t vni, mpls_label_t *label)
|
||||
{
|
||||
u_char *tag = (u_char *) label;
|
||||
tag[0] = (vni >> 16) & 0xFF;
|
||||
tag[1] = (vni >> 8) & 0xFF;
|
||||
tag[2] = vni & 0xFF;
|
||||
u_char *tag = (u_char *)label;
|
||||
tag[0] = (vni >> 16) & 0xFF;
|
||||
tag[1] = (vni >> 8) & 0xFF;
|
||||
tag[2] = vni & 0xFF;
|
||||
}
|
||||
|
||||
static inline vni_t
|
||||
label2vni (mpls_label_t *label)
|
||||
static inline vni_t label2vni(mpls_label_t *label)
|
||||
{
|
||||
u_char *tag = (u_char *) label;
|
||||
vni_t vni;
|
||||
u_char *tag = (u_char *)label;
|
||||
vni_t vni;
|
||||
|
||||
vni = ((u_int32_t) *tag++ << 16);
|
||||
vni |= (u_int32_t) *tag++ << 8;
|
||||
vni |= (u_int32_t) (*tag & 0xFF);
|
||||
vni = ((u_int32_t)*tag++ << 16);
|
||||
vni |= (u_int32_t)*tag++ << 8;
|
||||
vni |= (u_int32_t)(*tag & 0xFF);
|
||||
|
||||
return vni;
|
||||
return vni;
|
||||
}
|
||||
|
||||
static inline void
|
||||
encode_mac_mobility_extcomm (int static_mac, u_int32_t seq,
|
||||
struct ecommunity_val *eval)
|
||||
static inline void encode_mac_mobility_extcomm(int static_mac, u_int32_t seq,
|
||||
struct ecommunity_val *eval)
|
||||
{
|
||||
memset (eval, 0, sizeof (*eval));
|
||||
eval->val[0] = ECOMMUNITY_ENCODE_EVPN;
|
||||
eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY;
|
||||
if (static_mac)
|
||||
eval->val[2] = ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY;
|
||||
eval->val[4] = (seq >> 24) & 0xff;
|
||||
eval->val[5] = (seq >> 16) & 0xff;
|
||||
eval->val[6] = (seq >> 8) & 0xff;
|
||||
eval->val[7] = seq & 0xff;
|
||||
memset(eval, 0, sizeof(*eval));
|
||||
eval->val[0] = ECOMMUNITY_ENCODE_EVPN;
|
||||
eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY;
|
||||
if (static_mac)
|
||||
eval->val[2] = ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY;
|
||||
eval->val[4] = (seq >> 24) & 0xff;
|
||||
eval->val[5] = (seq >> 16) & 0xff;
|
||||
eval->val[6] = (seq >> 8) & 0xff;
|
||||
eval->val[7] = seq & 0xff;
|
||||
}
|
||||
|
||||
static inline void
|
||||
build_evpn_type2_prefix (struct prefix_evpn *p, struct ethaddr *mac,
|
||||
struct ipaddr *ip)
|
||||
static inline void build_evpn_type2_prefix(struct prefix_evpn *p,
|
||||
struct ethaddr *mac,
|
||||
struct ipaddr *ip)
|
||||
{
|
||||
memset (p, 0, sizeof (struct prefix_evpn));
|
||||
p->family = AF_ETHERNET;
|
||||
p->prefixlen = EVPN_TYPE_2_ROUTE_PREFIXLEN;
|
||||
p->prefix.route_type = BGP_EVPN_MAC_IP_ROUTE;
|
||||
memcpy(&p->prefix.mac.octet, mac->octet, ETHER_ADDR_LEN);
|
||||
p->prefix.ip.ipa_type = IPADDR_NONE;
|
||||
if (ip)
|
||||
memcpy(&p->prefix.ip, ip, sizeof (*ip));
|
||||
memset(p, 0, sizeof(struct prefix_evpn));
|
||||
p->family = AF_ETHERNET;
|
||||
p->prefixlen = EVPN_TYPE_2_ROUTE_PREFIXLEN;
|
||||
p->prefix.route_type = BGP_EVPN_MAC_IP_ROUTE;
|
||||
memcpy(&p->prefix.mac.octet, mac->octet, ETHER_ADDR_LEN);
|
||||
p->prefix.ip.ipa_type = IPADDR_NONE;
|
||||
if (ip)
|
||||
memcpy(&p->prefix.ip, ip, sizeof(*ip));
|
||||
}
|
||||
|
||||
static inline void
|
||||
build_evpn_type3_prefix (struct prefix_evpn *p, struct in_addr originator_ip)
|
||||
static inline void build_evpn_type3_prefix(struct prefix_evpn *p,
|
||||
struct in_addr originator_ip)
|
||||
{
|
||||
memset (p, 0, sizeof (struct prefix_evpn));
|
||||
p->family = AF_ETHERNET;
|
||||
p->prefixlen = EVPN_TYPE_3_ROUTE_PREFIXLEN;
|
||||
p->prefix.route_type = BGP_EVPN_IMET_ROUTE;
|
||||
p->prefix.ip.ipa_type = IPADDR_V4;
|
||||
p->prefix.ip.ipaddr_v4 = originator_ip;
|
||||
memset(p, 0, sizeof(struct prefix_evpn));
|
||||
p->family = AF_ETHERNET;
|
||||
p->prefixlen = EVPN_TYPE_3_ROUTE_PREFIXLEN;
|
||||
p->prefix.route_type = BGP_EVPN_IMET_ROUTE;
|
||||
p->prefix.ip.ipa_type = IPADDR_V4;
|
||||
p->prefix.ip.ipaddr_v4 = originator_ip;
|
||||
}
|
||||
|
||||
|
||||
extern int
|
||||
bgp_evpn_handle_export_rt_change (struct bgp *bgp, struct bgpevpn *vpn);
|
||||
extern void
|
||||
bgp_evpn_handle_rd_change (struct bgp *bgp, struct bgpevpn *vpn, int withdraw);
|
||||
extern int
|
||||
bgp_evpn_install_routes (struct bgp *bgp, struct bgpevpn *vpn);
|
||||
extern int
|
||||
bgp_evpn_uninstall_routes (struct bgp *bgp, struct bgpevpn *vpn);
|
||||
extern void
|
||||
bgp_evpn_map_vni_to_its_rts (struct bgp *bgp, struct bgpevpn *vpn);
|
||||
extern void
|
||||
bgp_evpn_unmap_vni_from_its_rts (struct bgp *bgp, struct bgpevpn *vpn);
|
||||
extern void
|
||||
bgp_evpn_derive_auto_rt_import (struct bgp *bgp, struct bgpevpn *vpn);
|
||||
extern void
|
||||
bgp_evpn_derive_auto_rt_export (struct bgp *bgp, struct bgpevpn *vpn);
|
||||
extern void
|
||||
bgp_evpn_derive_auto_rd (struct bgp *bgp, struct bgpevpn *vpn);
|
||||
extern struct bgpevpn *
|
||||
bgp_evpn_lookup_vni (struct bgp *bgp, vni_t vni);
|
||||
extern struct bgpevpn *
|
||||
bgp_evpn_new (struct bgp *bgp, vni_t vni, struct in_addr originator_ip);
|
||||
extern void
|
||||
bgp_evpn_free (struct bgp *bgp, struct bgpevpn *vpn);
|
||||
extern int bgp_evpn_handle_export_rt_change(struct bgp *bgp,
|
||||
struct bgpevpn *vpn);
|
||||
extern void bgp_evpn_handle_rd_change(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
int withdraw);
|
||||
extern int bgp_evpn_install_routes(struct bgp *bgp, struct bgpevpn *vpn);
|
||||
extern int bgp_evpn_uninstall_routes(struct bgp *bgp, struct bgpevpn *vpn);
|
||||
extern void bgp_evpn_map_vni_to_its_rts(struct bgp *bgp, struct bgpevpn *vpn);
|
||||
extern void bgp_evpn_unmap_vni_from_its_rts(struct bgp *bgp,
|
||||
struct bgpevpn *vpn);
|
||||
extern void bgp_evpn_derive_auto_rt_import(struct bgp *bgp,
|
||||
struct bgpevpn *vpn);
|
||||
extern void bgp_evpn_derive_auto_rt_export(struct bgp *bgp,
|
||||
struct bgpevpn *vpn);
|
||||
extern void bgp_evpn_derive_auto_rd(struct bgp *bgp, struct bgpevpn *vpn);
|
||||
extern struct bgpevpn *bgp_evpn_lookup_vni(struct bgp *bgp, vni_t vni);
|
||||
extern struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni,
|
||||
struct in_addr originator_ip);
|
||||
extern void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn);
|
||||
#endif /* _BGP_EVPN_PRIVATE_H */
|
||||
|
||||
2746
bgpd/bgp_evpn_vty.c
2746
bgpd/bgp_evpn_vty.c
File diff suppressed because it is too large
Load Diff
@ -21,12 +21,11 @@
|
||||
#ifndef _FRR_BGP_EVPN_VTY_H
|
||||
#define _FRR_BGP_EVPN_VTY_H
|
||||
|
||||
extern void
|
||||
bgp_config_write_evpn_info (struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
safi_t safi, int *write);
|
||||
extern void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp,
|
||||
afi_t afi, safi_t safi, int *write);
|
||||
extern void bgp_ethernetvpn_init(void);
|
||||
|
||||
#define L2VPN_HELP_STR "Layer 2 Virtual Private Network\n"
|
||||
#define EVPN_HELP_STR "Ethernet Virtual Private Network\n"
|
||||
|
||||
#endif /* _QUAGGA_BGP_EVPN_VTY_H */
|
||||
#endif /* _QUAGGA_BGP_EVPN_VTY_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -21,19 +21,15 @@
|
||||
#ifndef _QUAGGA_BGP_FILTER_H
|
||||
#define _QUAGGA_BGP_FILTER_H
|
||||
|
||||
enum as_filter_type
|
||||
{
|
||||
AS_FILTER_DENY,
|
||||
AS_FILTER_PERMIT
|
||||
};
|
||||
enum as_filter_type { AS_FILTER_DENY, AS_FILTER_PERMIT };
|
||||
|
||||
extern void bgp_filter_init (void);
|
||||
extern void bgp_filter_reset (void);
|
||||
extern void bgp_filter_init(void);
|
||||
extern void bgp_filter_reset(void);
|
||||
|
||||
extern enum as_filter_type as_list_apply (struct as_list *, void *);
|
||||
extern enum as_filter_type as_list_apply(struct as_list *, void *);
|
||||
|
||||
extern struct as_list *as_list_lookup (const char *);
|
||||
extern void as_list_add_hook (void (*func) (char *));
|
||||
extern void as_list_delete_hook (void (*func) (const char *));
|
||||
extern struct as_list *as_list_lookup(const char *);
|
||||
extern void as_list_add_hook(void (*func)(char *));
|
||||
extern void as_list_delete_hook(void (*func)(const char *));
|
||||
|
||||
#endif /* _QUAGGA_BGP_FILTER_H */
|
||||
|
||||
2831
bgpd/bgp_fsm.c
2831
bgpd/bgp_fsm.c
File diff suppressed because it is too large
Load Diff
121
bgpd/bgp_fsm.h
121
bgpd/bgp_fsm.h
@ -1,4 +1,4 @@
|
||||
/* BGP-4 Finite State Machine
|
||||
/* BGP-4 Finite State Machine
|
||||
* From RFC1771 [A Border Gateway Protocol 4 (BGP-4)]
|
||||
* Copyright (C) 1998 Kunihiro Ishiguro
|
||||
*
|
||||
@ -23,82 +23,83 @@
|
||||
#define _QUAGGA_BGP_FSM_H
|
||||
|
||||
/* Macro for BGP read, write and timer thread. */
|
||||
#define BGP_READ_ON(T,F,V) \
|
||||
do { \
|
||||
if ((peer->status != Deleted)) \
|
||||
thread_add_read (bm->master,(F),peer,(V),&(T)); \
|
||||
} while (0)
|
||||
#define BGP_READ_ON(T, F, V) \
|
||||
do { \
|
||||
if ((peer->status != Deleted)) \
|
||||
thread_add_read(bm->master, (F), peer, (V), &(T)); \
|
||||
} while (0)
|
||||
|
||||
#define BGP_READ_OFF(T) \
|
||||
do { \
|
||||
if (T) \
|
||||
THREAD_READ_OFF(T); \
|
||||
} while (0)
|
||||
#define BGP_READ_OFF(T) \
|
||||
do { \
|
||||
if (T) \
|
||||
THREAD_READ_OFF(T); \
|
||||
} while (0)
|
||||
|
||||
#define BGP_WRITE_ON(T,F,V) \
|
||||
do { \
|
||||
if ((peer)->status != Deleted) \
|
||||
thread_add_write (bm->master,(F),(peer),(V),&(T)); \
|
||||
} while (0)
|
||||
#define BGP_WRITE_ON(T, F, V) \
|
||||
do { \
|
||||
if ((peer)->status != Deleted) \
|
||||
thread_add_write(bm->master, (F), (peer), (V), &(T)); \
|
||||
} while (0)
|
||||
|
||||
#define BGP_PEER_WRITE_ON(T,F,V, peer) \
|
||||
do { \
|
||||
if ((peer)->status != Deleted) \
|
||||
thread_add_write (bm->master,(F),(peer),(V),&(T)); \
|
||||
} while (0)
|
||||
#define BGP_PEER_WRITE_ON(T, F, V, peer) \
|
||||
do { \
|
||||
if ((peer)->status != Deleted) \
|
||||
thread_add_write(bm->master, (F), (peer), (V), &(T)); \
|
||||
} while (0)
|
||||
|
||||
#define BGP_WRITE_OFF(T) \
|
||||
do { \
|
||||
if (T) \
|
||||
THREAD_WRITE_OFF(T); \
|
||||
} while (0)
|
||||
#define BGP_WRITE_OFF(T) \
|
||||
do { \
|
||||
if (T) \
|
||||
THREAD_WRITE_OFF(T); \
|
||||
} while (0)
|
||||
|
||||
#define BGP_TIMER_ON(T,F,V) \
|
||||
do { \
|
||||
if ((peer->status != Deleted)) \
|
||||
thread_add_timer (bm->master,(F),peer,(V),&(T)); \
|
||||
} while (0)
|
||||
#define BGP_TIMER_ON(T, F, V) \
|
||||
do { \
|
||||
if ((peer->status != Deleted)) \
|
||||
thread_add_timer(bm->master, (F), peer, (V), &(T)); \
|
||||
} while (0)
|
||||
|
||||
#define BGP_TIMER_OFF(T) \
|
||||
do { \
|
||||
if (T) \
|
||||
THREAD_TIMER_OFF(T); \
|
||||
} while (0)
|
||||
#define BGP_TIMER_OFF(T) \
|
||||
do { \
|
||||
if (T) \
|
||||
THREAD_TIMER_OFF(T); \
|
||||
} while (0)
|
||||
|
||||
#define BGP_EVENT_ADD(P,E) \
|
||||
do { \
|
||||
if ((P)->status != Deleted) \
|
||||
thread_add_event (bm->master, bgp_event, (P), (E), NULL); \
|
||||
} while (0)
|
||||
#define BGP_EVENT_ADD(P, E) \
|
||||
do { \
|
||||
if ((P)->status != Deleted) \
|
||||
thread_add_event(bm->master, bgp_event, (P), (E), \
|
||||
NULL); \
|
||||
} while (0)
|
||||
|
||||
#define BGP_EVENT_FLUSH(P) \
|
||||
do { \
|
||||
assert (peer); \
|
||||
thread_cancel_event (bm->master, (P)); \
|
||||
} while (0)
|
||||
#define BGP_EVENT_FLUSH(P) \
|
||||
do { \
|
||||
assert(peer); \
|
||||
thread_cancel_event(bm->master, (P)); \
|
||||
} while (0)
|
||||
|
||||
#define BGP_MSEC_JITTER 10
|
||||
|
||||
/* Prototypes. */
|
||||
extern void bgp_fsm_nht_update(struct peer *, int valid);
|
||||
extern int bgp_event (struct thread *);
|
||||
extern int bgp_event_update (struct peer *, int event);
|
||||
extern int bgp_stop (struct peer *peer);
|
||||
extern void bgp_timer_set (struct peer *);
|
||||
extern int bgp_routeadv_timer (struct thread *);
|
||||
extern void bgp_fsm_change_status (struct peer *peer, int status);
|
||||
extern int bgp_event(struct thread *);
|
||||
extern int bgp_event_update(struct peer *, int event);
|
||||
extern int bgp_stop(struct peer *peer);
|
||||
extern void bgp_timer_set(struct peer *);
|
||||
extern int bgp_routeadv_timer(struct thread *);
|
||||
extern void bgp_fsm_change_status(struct peer *peer, int status);
|
||||
extern const char *peer_down_str[];
|
||||
extern void bgp_update_delay_end (struct bgp *);
|
||||
extern void bgp_maxmed_update (struct bgp *);
|
||||
extern int bgp_maxmed_onstartup_configured (struct bgp *);
|
||||
extern int bgp_maxmed_onstartup_active (struct bgp *);
|
||||
extern void bgp_update_delay_end(struct bgp *);
|
||||
extern void bgp_maxmed_update(struct bgp *);
|
||||
extern int bgp_maxmed_onstartup_configured(struct bgp *);
|
||||
extern int bgp_maxmed_onstartup_active(struct bgp *);
|
||||
|
||||
/**
|
||||
* Start the route advertisement timer (that honors MRAI) for all the
|
||||
* peers. Typically called at the end of initial convergence, coming
|
||||
* out of read-only mode.
|
||||
*/
|
||||
extern void bgp_start_routeadv (struct bgp *);
|
||||
extern void bgp_start_routeadv(struct bgp *);
|
||||
|
||||
/**
|
||||
* See if the route advertisement timer needs to be adjusted for a
|
||||
@ -107,10 +108,10 @@ extern void bgp_start_routeadv (struct bgp *);
|
||||
* timer to expire to send the new set of prefixes. It should fire
|
||||
* instantly and updates should go out sooner.
|
||||
*/
|
||||
extern void bgp_adjust_routeadv (struct peer *);
|
||||
extern void bgp_adjust_routeadv(struct peer *);
|
||||
|
||||
#include "hook.h"
|
||||
DECLARE_HOOK(peer_backward_transition, (struct peer *peer), (peer))
|
||||
DECLARE_HOOK(peer_established, (struct peer *peer), (peer))
|
||||
DECLARE_HOOK(peer_backward_transition, (struct peer * peer), (peer))
|
||||
DECLARE_HOOK(peer_established, (struct peer * peer), (peer))
|
||||
|
||||
#endif /* _QUAGGA_BGP_FSM_H */
|
||||
|
||||
490
bgpd/bgp_label.c
490
bgpd/bgp_label.c
@ -41,309 +41,301 @@
|
||||
|
||||
extern struct zclient *zclient;
|
||||
|
||||
int
|
||||
bgp_parse_fec_update (void)
|
||||
int bgp_parse_fec_update(void)
|
||||
{
|
||||
struct stream *s;
|
||||
struct bgp_node *rn;
|
||||
struct bgp *bgp;
|
||||
struct bgp_table *table;
|
||||
struct prefix p;
|
||||
u_int32_t label;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
struct stream *s;
|
||||
struct bgp_node *rn;
|
||||
struct bgp *bgp;
|
||||
struct bgp_table *table;
|
||||
struct prefix p;
|
||||
u_int32_t label;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
|
||||
s = zclient->ibuf;
|
||||
s = zclient->ibuf;
|
||||
|
||||
memset(&p, 0, sizeof(struct prefix));
|
||||
p.family = stream_getw(s);
|
||||
p.prefixlen = stream_getc(s);
|
||||
stream_get(&p.u.prefix, s, PSIZE(p.prefixlen));
|
||||
label = stream_getl(s);
|
||||
memset(&p, 0, sizeof(struct prefix));
|
||||
p.family = stream_getw(s);
|
||||
p.prefixlen = stream_getc(s);
|
||||
stream_get(&p.u.prefix, s, PSIZE(p.prefixlen));
|
||||
label = stream_getl(s);
|
||||
|
||||
/* hack for the bgp instance & SAFI = have to send/receive it */
|
||||
afi = family2afi(p.family);
|
||||
safi = SAFI_UNICAST;
|
||||
bgp = bgp_get_default();
|
||||
if (!bgp)
|
||||
{
|
||||
zlog_debug("no default bgp instance");
|
||||
return -1;
|
||||
}
|
||||
/* hack for the bgp instance & SAFI = have to send/receive it */
|
||||
afi = family2afi(p.family);
|
||||
safi = SAFI_UNICAST;
|
||||
bgp = bgp_get_default();
|
||||
if (!bgp) {
|
||||
zlog_debug("no default bgp instance");
|
||||
return -1;
|
||||
}
|
||||
|
||||
table = bgp->rib[afi][safi];
|
||||
if (!table)
|
||||
{
|
||||
zlog_debug("no %u unicast table", p.family);
|
||||
return -1;
|
||||
}
|
||||
rn = bgp_node_lookup(table, &p);
|
||||
if (!rn)
|
||||
{
|
||||
zlog_debug("no node for the prefix");
|
||||
return -1;
|
||||
}
|
||||
table = bgp->rib[afi][safi];
|
||||
if (!table) {
|
||||
zlog_debug("no %u unicast table", p.family);
|
||||
return -1;
|
||||
}
|
||||
rn = bgp_node_lookup(table, &p);
|
||||
if (!rn) {
|
||||
zlog_debug("no node for the prefix");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* treat it as implicit withdraw - the label is invalid */
|
||||
if (label == MPLS_INVALID_LABEL)
|
||||
bgp_unset_valid_label(&rn->local_label);
|
||||
else
|
||||
{
|
||||
label_ntop(label, 1, &rn->local_label);
|
||||
bgp_set_valid_label(&rn->local_label);
|
||||
}
|
||||
SET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
|
||||
bgp_unlock_node (rn);
|
||||
bgp_process (bgp, rn, afi, safi);
|
||||
return 1;
|
||||
/* treat it as implicit withdraw - the label is invalid */
|
||||
if (label == MPLS_INVALID_LABEL)
|
||||
bgp_unset_valid_label(&rn->local_label);
|
||||
else {
|
||||
label_ntop(label, 1, &rn->local_label);
|
||||
bgp_set_valid_label(&rn->local_label);
|
||||
}
|
||||
SET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
|
||||
bgp_unlock_node(rn);
|
||||
bgp_process(bgp, rn, afi, safi);
|
||||
return 1;
|
||||
}
|
||||
|
||||
mpls_label_t
|
||||
bgp_adv_label (struct bgp_node *rn, struct bgp_info *ri, struct peer *to,
|
||||
afi_t afi, safi_t safi)
|
||||
mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri,
|
||||
struct peer *to, afi_t afi, safi_t safi)
|
||||
{
|
||||
struct peer *from;
|
||||
mpls_label_t remote_label;
|
||||
int reflect;
|
||||
struct peer *from;
|
||||
mpls_label_t remote_label;
|
||||
int reflect;
|
||||
|
||||
if (!rn || !ri || !to)
|
||||
return MPLS_INVALID_LABEL;
|
||||
if (!rn || !ri || !to)
|
||||
return MPLS_INVALID_LABEL;
|
||||
|
||||
remote_label = ri->extra ? ri->extra->label : MPLS_INVALID_LABEL;
|
||||
from = ri->peer;
|
||||
reflect = ((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP));
|
||||
remote_label = ri->extra ? ri->extra->label : MPLS_INVALID_LABEL;
|
||||
from = ri->peer;
|
||||
reflect =
|
||||
((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP));
|
||||
|
||||
if (reflect && !CHECK_FLAG(to->af_flags[afi][safi],
|
||||
PEER_FLAG_FORCE_NEXTHOP_SELF))
|
||||
return remote_label;
|
||||
if (reflect
|
||||
&& !CHECK_FLAG(to->af_flags[afi][safi],
|
||||
PEER_FLAG_FORCE_NEXTHOP_SELF))
|
||||
return remote_label;
|
||||
|
||||
if (CHECK_FLAG(to->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED))
|
||||
return remote_label;
|
||||
if (CHECK_FLAG(to->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED))
|
||||
return remote_label;
|
||||
|
||||
return rn->local_label;
|
||||
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_info *ri, int reg)
|
||||
{
|
||||
struct stream *s;
|
||||
struct prefix *p;
|
||||
int command;
|
||||
u_int16_t flags = 0;
|
||||
size_t flags_pos = 0;
|
||||
struct stream *s;
|
||||
struct prefix *p;
|
||||
int command;
|
||||
u_int16_t flags = 0;
|
||||
size_t flags_pos = 0;
|
||||
|
||||
/* Check socket. */
|
||||
if (!zclient || zclient->sock < 0)
|
||||
return;
|
||||
/* Check socket. */
|
||||
if (!zclient || zclient->sock < 0)
|
||||
return;
|
||||
|
||||
p = &(rn->p);
|
||||
s = zclient->obuf;
|
||||
stream_reset (s);
|
||||
command = (reg) ? ZEBRA_FEC_REGISTER : ZEBRA_FEC_UNREGISTER;
|
||||
zclient_create_header (s, command, VRF_DEFAULT);
|
||||
flags_pos = stream_get_endp (s); /* save position of 'flags' */
|
||||
stream_putw(s, flags); /* initial flags */
|
||||
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)
|
||||
{
|
||||
flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX;
|
||||
stream_putl (s, ri->attr->label_index);
|
||||
}
|
||||
}
|
||||
SET_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);
|
||||
}
|
||||
else
|
||||
UNSET_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);
|
||||
p = &(rn->p);
|
||||
s = zclient->obuf;
|
||||
stream_reset(s);
|
||||
command = (reg) ? ZEBRA_FEC_REGISTER : ZEBRA_FEC_UNREGISTER;
|
||||
zclient_create_header(s, command, VRF_DEFAULT);
|
||||
flags_pos = stream_get_endp(s); /* save position of 'flags' */
|
||||
stream_putw(s, flags); /* initial flags */
|
||||
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) {
|
||||
flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX;
|
||||
stream_putl(s, ri->attr->label_index);
|
||||
}
|
||||
}
|
||||
SET_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);
|
||||
} else
|
||||
UNSET_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);
|
||||
|
||||
/* Set length and flags */
|
||||
stream_putw_at (s, 0, stream_get_endp (s));
|
||||
stream_putw_at (s, flags_pos, flags);
|
||||
/* Set length and flags */
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
stream_putw_at(s, flags_pos, flags);
|
||||
|
||||
zclient_send_message(zclient);
|
||||
zclient_send_message(zclient);
|
||||
}
|
||||
|
||||
static int
|
||||
bgp_nlri_get_labels (struct peer *peer, u_char *pnt, u_char plen, mpls_label_t *label)
|
||||
static int bgp_nlri_get_labels(struct peer *peer, u_char *pnt, u_char plen,
|
||||
mpls_label_t *label)
|
||||
{
|
||||
u_char *data = pnt;
|
||||
u_char *lim = pnt + plen;
|
||||
u_char llen = 0;
|
||||
u_char label_depth = 0;
|
||||
u_char *data = pnt;
|
||||
u_char *lim = pnt + plen;
|
||||
u_char llen = 0;
|
||||
u_char label_depth = 0;
|
||||
|
||||
for (; data < lim; data += BGP_LABEL_BYTES)
|
||||
{
|
||||
memcpy(label, data, BGP_LABEL_BYTES);
|
||||
llen += BGP_LABEL_BYTES;
|
||||
for (; data < lim; data += BGP_LABEL_BYTES) {
|
||||
memcpy(label, data, BGP_LABEL_BYTES);
|
||||
llen += BGP_LABEL_BYTES;
|
||||
|
||||
bgp_set_valid_label(label);
|
||||
label_depth += 1;
|
||||
bgp_set_valid_label(label);
|
||||
label_depth += 1;
|
||||
|
||||
if (bgp_is_withdraw_label(label) || label_bos(label))
|
||||
break;
|
||||
}
|
||||
if (bgp_is_withdraw_label(label) || label_bos(label))
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we RX multiple labels we will end up keeping only the last
|
||||
* one. We do not yet support a label stack greater than 1. */
|
||||
if (label_depth > 1)
|
||||
zlog_warn("%s rcvd UPDATE with label stack %d deep",
|
||||
peer->host, label_depth);
|
||||
/* If we RX multiple labels we will end up keeping only the last
|
||||
* one. We do not yet support a label stack greater than 1. */
|
||||
if (label_depth > 1)
|
||||
zlog_warn("%s rcvd UPDATE with label stack %d deep", peer->host,
|
||||
label_depth);
|
||||
|
||||
if (!(bgp_is_withdraw_label(label) || label_bos(label)))
|
||||
zlog_warn("%s rcvd UPDATE with invalid label stack - no bottom of stack",
|
||||
peer->host);
|
||||
if (!(bgp_is_withdraw_label(label) || label_bos(label)))
|
||||
zlog_warn(
|
||||
"%s rcvd UPDATE with invalid label stack - no bottom of stack",
|
||||
peer->host);
|
||||
|
||||
return llen;
|
||||
return llen;
|
||||
}
|
||||
|
||||
int
|
||||
bgp_nlri_parse_label (struct peer *peer, struct attr *attr,
|
||||
struct bgp_nlri *packet)
|
||||
int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
|
||||
struct bgp_nlri *packet)
|
||||
{
|
||||
u_char *pnt;
|
||||
u_char *lim;
|
||||
struct prefix p;
|
||||
int psize = 0;
|
||||
int prefixlen;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
int addpath_encoded;
|
||||
u_int32_t addpath_id;
|
||||
mpls_label_t label = MPLS_INVALID_LABEL;
|
||||
u_char llen;
|
||||
u_char *pnt;
|
||||
u_char *lim;
|
||||
struct prefix p;
|
||||
int psize = 0;
|
||||
int prefixlen;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
int addpath_encoded;
|
||||
u_int32_t addpath_id;
|
||||
mpls_label_t label = MPLS_INVALID_LABEL;
|
||||
u_char llen;
|
||||
|
||||
/* Check peer status. */
|
||||
if (peer->status != Established)
|
||||
return 0;
|
||||
/* Check peer status. */
|
||||
if (peer->status != Established)
|
||||
return 0;
|
||||
|
||||
pnt = packet->nlri;
|
||||
lim = pnt + packet->length;
|
||||
afi = packet->afi;
|
||||
safi = packet->safi;
|
||||
addpath_id = 0;
|
||||
pnt = packet->nlri;
|
||||
lim = pnt + packet->length;
|
||||
afi = packet->afi;
|
||||
safi = packet->safi;
|
||||
addpath_id = 0;
|
||||
|
||||
addpath_encoded = (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) &&
|
||||
CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV));
|
||||
addpath_encoded =
|
||||
(CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
|
||||
&& CHECK_FLAG(peer->af_cap[afi][safi],
|
||||
PEER_CAP_ADDPATH_AF_TX_RCV));
|
||||
|
||||
for (; pnt < lim; pnt += psize)
|
||||
{
|
||||
/* Clear prefix structure. */
|
||||
memset (&p, 0, sizeof (struct prefix));
|
||||
llen = 0;
|
||||
for (; pnt < lim; pnt += psize) {
|
||||
/* Clear prefix structure. */
|
||||
memset(&p, 0, sizeof(struct prefix));
|
||||
llen = 0;
|
||||
|
||||
if (addpath_encoded)
|
||||
{
|
||||
if (addpath_encoded) {
|
||||
|
||||
/* When packet overflow occurs return immediately. */
|
||||
if (pnt + BGP_ADDPATH_ID_LEN > lim)
|
||||
return -1;
|
||||
/* When packet overflow occurs return immediately. */
|
||||
if (pnt + BGP_ADDPATH_ID_LEN > lim)
|
||||
return -1;
|
||||
|
||||
addpath_id = ntohl(*((uint32_t*) pnt));
|
||||
pnt += BGP_ADDPATH_ID_LEN;
|
||||
}
|
||||
addpath_id = ntohl(*((uint32_t *)pnt));
|
||||
pnt += BGP_ADDPATH_ID_LEN;
|
||||
}
|
||||
|
||||
/* Fetch prefix length. */
|
||||
prefixlen = *pnt++;
|
||||
p.family = afi2family (packet->afi);
|
||||
psize = PSIZE (prefixlen);
|
||||
/* Fetch prefix length. */
|
||||
prefixlen = *pnt++;
|
||||
p.family = afi2family(packet->afi);
|
||||
psize = PSIZE(prefixlen);
|
||||
|
||||
/* sanity check against packet data */
|
||||
if ((pnt + psize) > lim)
|
||||
{
|
||||
zlog_err ("%s [Error] Update packet error / L-U (prefix length %d exceeds packet size %u)",
|
||||
peer->host,
|
||||
prefixlen, (uint)(lim-pnt));
|
||||
return -1;
|
||||
}
|
||||
/* sanity check against packet data */
|
||||
if ((pnt + psize) > lim) {
|
||||
zlog_err(
|
||||
"%s [Error] Update packet error / L-U (prefix length %d exceeds packet size %u)",
|
||||
peer->host, prefixlen, (uint)(lim - pnt));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Fill in the labels */
|
||||
llen = bgp_nlri_get_labels(peer, pnt, psize, &label);
|
||||
p.prefixlen = prefixlen - BSIZE(llen);
|
||||
/* Fill in the labels */
|
||||
llen = bgp_nlri_get_labels(peer, pnt, psize, &label);
|
||||
p.prefixlen = prefixlen - BSIZE(llen);
|
||||
|
||||
/* There needs to be at least one label */
|
||||
if (prefixlen < 24)
|
||||
{
|
||||
zlog_err ("%s [Error] Update packet error"
|
||||
" (wrong label length %d)",
|
||||
peer->host, prefixlen);
|
||||
bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
|
||||
BGP_NOTIFY_UPDATE_INVAL_NETWORK);
|
||||
return -1;
|
||||
}
|
||||
/* There needs to be at least one label */
|
||||
if (prefixlen < 24) {
|
||||
zlog_err(
|
||||
"%s [Error] Update packet error"
|
||||
" (wrong label length %d)",
|
||||
peer->host, prefixlen);
|
||||
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
|
||||
BGP_NOTIFY_UPDATE_INVAL_NETWORK);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((afi == AFI_IP && p.prefixlen > 32)
|
||||
|| (afi == AFI_IP6 && p.prefixlen > 128))
|
||||
return -1;
|
||||
if ((afi == AFI_IP && p.prefixlen > 32)
|
||||
|| (afi == AFI_IP6 && p.prefixlen > 128))
|
||||
return -1;
|
||||
|
||||
/* Fetch prefix from NLRI packet */
|
||||
memcpy (&p.u.prefix, pnt + llen, psize - llen);
|
||||
/* Fetch prefix from NLRI packet */
|
||||
memcpy(&p.u.prefix, pnt + llen, psize - llen);
|
||||
|
||||
/* Check address. */
|
||||
if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST)
|
||||
{
|
||||
if (IN_CLASSD (ntohl (p.u.prefix4.s_addr)))
|
||||
{
|
||||
/* From RFC4271 Section 6.3:
|
||||
*
|
||||
* If a prefix in the NLRI field is semantically incorrect
|
||||
* (e.g., an unexpected multicast IP address), an error SHOULD
|
||||
* be logged locally, and the prefix SHOULD be ignored.
|
||||
*/
|
||||
zlog_err ("%s: IPv4 labeled-unicast NLRI is multicast address %s, ignoring",
|
||||
peer->host, inet_ntoa (p.u.prefix4));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* Check address. */
|
||||
if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) {
|
||||
if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
|
||||
/* From RFC4271 Section 6.3:
|
||||
*
|
||||
* If a prefix in the NLRI field is semantically
|
||||
* incorrect
|
||||
* (e.g., an unexpected multicast IP address),
|
||||
* an error SHOULD
|
||||
* be logged locally, and the prefix SHOULD be
|
||||
* ignored.
|
||||
*/
|
||||
zlog_err(
|
||||
"%s: IPv4 labeled-unicast NLRI is multicast address %s, ignoring",
|
||||
peer->host, inet_ntoa(p.u.prefix4));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check address. */
|
||||
if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST)
|
||||
{
|
||||
if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
/* Check address. */
|
||||
if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) {
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
|
||||
char buf[BUFSIZ];
|
||||
|
||||
zlog_err ("%s: IPv6 labeled-unicast NLRI is link-local address %s, ignoring",
|
||||
peer->host, inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ));
|
||||
zlog_err(
|
||||
"%s: IPv6 labeled-unicast NLRI is link-local address %s, ignoring",
|
||||
peer->host,
|
||||
inet_ntop(AF_INET6, &p.u.prefix6, buf,
|
||||
BUFSIZ));
|
||||
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IN6_IS_ADDR_MULTICAST (&p.u.prefix6))
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
|
||||
char buf[BUFSIZ];
|
||||
|
||||
zlog_err ("%s: IPv6 unicast NLRI is multicast address %s, ignoring",
|
||||
peer->host, inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ));
|
||||
zlog_err(
|
||||
"%s: IPv6 unicast NLRI is multicast address %s, ignoring",
|
||||
peer->host,
|
||||
inet_ntop(AF_INET6, &p.u.prefix6, buf,
|
||||
BUFSIZ));
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr)
|
||||
{
|
||||
bgp_update (peer, &p, addpath_id, attr, packet->afi, SAFI_UNICAST,
|
||||
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, &label, 0, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
bgp_withdraw (peer, &p, addpath_id, attr, packet->afi, SAFI_UNICAST,
|
||||
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, &label, NULL);
|
||||
}
|
||||
}
|
||||
if (attr) {
|
||||
bgp_update(peer, &p, addpath_id, attr, packet->afi,
|
||||
SAFI_UNICAST, ZEBRA_ROUTE_BGP,
|
||||
BGP_ROUTE_NORMAL, NULL, &label, 0, NULL);
|
||||
} else {
|
||||
bgp_withdraw(peer, &p, addpath_id, attr, packet->afi,
|
||||
SAFI_UNICAST, ZEBRA_ROUTE_BGP,
|
||||
BGP_ROUTE_NORMAL, NULL, &label, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Packet length consistency check. */
|
||||
if (pnt != lim)
|
||||
{
|
||||
zlog_err ("%s [Error] Update packet error / L-U (%zu data remaining after parsing)",
|
||||
peer->host, lim - pnt);
|
||||
return -1;
|
||||
}
|
||||
/* Packet length consistency check. */
|
||||
if (pnt != lim) {
|
||||
zlog_err(
|
||||
"%s [Error] Update packet error / L-U (%zu data remaining after parsing)",
|
||||
peer->host, lim - pnt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
114
bgpd/bgp_label.h
114
bgpd/bgp_label.h
@ -29,103 +29,95 @@ struct bgp_node;
|
||||
struct bgp_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_info *ri,
|
||||
int reg);
|
||||
extern int bgp_parse_fec_update(void);
|
||||
extern mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri,
|
||||
struct peer *to, afi_t afi, safi_t safi);
|
||||
struct peer *to, afi_t afi, safi_t safi);
|
||||
|
||||
extern int bgp_nlri_parse_label (struct peer *peer, struct attr *attr,
|
||||
struct bgp_nlri *packet);
|
||||
extern int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
|
||||
struct bgp_nlri *packet);
|
||||
|
||||
static inline int
|
||||
bgp_labeled_safi (safi_t safi)
|
||||
static inline int bgp_labeled_safi(safi_t safi)
|
||||
{
|
||||
/* NOTE: This API really says a label (tag) MAY be present. Not all EVPN
|
||||
* routes will have a label.
|
||||
*/
|
||||
if ((safi == SAFI_LABELED_UNICAST) || (safi == SAFI_MPLS_VPN) ||
|
||||
(safi == SAFI_EVPN))
|
||||
return 1;
|
||||
return 0;
|
||||
/* NOTE: This API really says a label (tag) MAY be present. Not all EVPN
|
||||
* routes will have a label.
|
||||
*/
|
||||
if ((safi == SAFI_LABELED_UNICAST) || (safi == SAFI_MPLS_VPN)
|
||||
|| (safi == SAFI_EVPN))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
bgp_is_withdraw_label (mpls_label_t *label)
|
||||
static inline int bgp_is_withdraw_label(mpls_label_t *label)
|
||||
{
|
||||
u_char *pkt = (u_char *) label;
|
||||
u_char *pkt = (u_char *)label;
|
||||
|
||||
/* The check on pkt[2] for 0x00 or 0x02 is in case bgp_set_valid_label()
|
||||
* was called on the withdraw label */
|
||||
if ((pkt[0] == 0x80) && (pkt[1] == 0x00) && ((pkt[2] == 0x00) || (pkt[2] == 0x02)))
|
||||
return 1;
|
||||
return 0;
|
||||
/* The check on pkt[2] for 0x00 or 0x02 is in case bgp_set_valid_label()
|
||||
* was called on the withdraw label */
|
||||
if ((pkt[0] == 0x80) && (pkt[1] == 0x00)
|
||||
&& ((pkt[2] == 0x00) || (pkt[2] == 0x02)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
bgp_is_valid_label (mpls_label_t *label)
|
||||
static inline int bgp_is_valid_label(mpls_label_t *label)
|
||||
{
|
||||
u_char *t= (u_char *) label;
|
||||
if (!t)
|
||||
return 0;
|
||||
return (t[2] & 0x02);
|
||||
u_char *t = (u_char *)label;
|
||||
if (!t)
|
||||
return 0;
|
||||
return (t[2] & 0x02);
|
||||
}
|
||||
|
||||
static inline void
|
||||
bgp_set_valid_label (mpls_label_t *label)
|
||||
static inline void bgp_set_valid_label(mpls_label_t *label)
|
||||
{
|
||||
u_char *t= (u_char *) label;
|
||||
if (t)
|
||||
t[2] |= 0x02;
|
||||
u_char *t = (u_char *)label;
|
||||
if (t)
|
||||
t[2] |= 0x02;
|
||||
}
|
||||
|
||||
static inline void
|
||||
bgp_unset_valid_label (mpls_label_t *label)
|
||||
static inline void bgp_unset_valid_label(mpls_label_t *label)
|
||||
{
|
||||
u_char *t= (u_char *) label;
|
||||
if (t)
|
||||
t[2] &= ~0x02;
|
||||
u_char *t = (u_char *)label;
|
||||
if (t)
|
||||
t[2] &= ~0x02;
|
||||
}
|
||||
|
||||
static inline void
|
||||
bgp_register_for_label (struct bgp_node *rn, struct bgp_info *ri)
|
||||
static inline void bgp_register_for_label(struct bgp_node *rn,
|
||||
struct bgp_info *ri)
|
||||
{
|
||||
bgp_reg_dereg_for_label (rn, ri, 1);
|
||||
bgp_reg_dereg_for_label(rn, ri, 1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
bgp_unregister_for_label (struct bgp_node *rn)
|
||||
static inline void bgp_unregister_for_label(struct bgp_node *rn)
|
||||
{
|
||||
bgp_reg_dereg_for_label (rn, NULL, 0);
|
||||
bgp_reg_dereg_for_label(rn, NULL, 0);
|
||||
}
|
||||
|
||||
/* Label stream to value */
|
||||
static inline u_int32_t
|
||||
label_pton (mpls_label_t *label)
|
||||
static inline u_int32_t label_pton(mpls_label_t *label)
|
||||
{
|
||||
u_char *t= (u_char *) label;
|
||||
return ((((unsigned int) t[0]) << 12) | (((unsigned int) t[1]) << 4) |
|
||||
((unsigned int) ((t[2] & 0xF0) >> 4)));
|
||||
u_char *t = (u_char *)label;
|
||||
return ((((unsigned int)t[0]) << 12) | (((unsigned int)t[1]) << 4)
|
||||
| ((unsigned int)((t[2] & 0xF0) >> 4)));
|
||||
}
|
||||
|
||||
/* Encode label values */
|
||||
static inline void
|
||||
label_ntop (u_int32_t l, int bos, mpls_label_t *label)
|
||||
static inline void label_ntop(u_int32_t l, int bos, mpls_label_t *label)
|
||||
{
|
||||
u_char *t= (u_char *) label;
|
||||
t[0] = ((l & 0x000FF000) >> 12);
|
||||
t[1] = ((l & 0x00000FF0) >> 4);
|
||||
t[2] = ((l & 0x0000000F) << 4);
|
||||
if (bos)
|
||||
t[2] |= 0x01;
|
||||
u_char *t = (u_char *)label;
|
||||
t[0] = ((l & 0x000FF000) >> 12);
|
||||
t[1] = ((l & 0x00000FF0) >> 4);
|
||||
t[2] = ((l & 0x0000000F) << 4);
|
||||
if (bos)
|
||||
t[2] |= 0x01;
|
||||
}
|
||||
|
||||
/* Return BOS value of label stream */
|
||||
static inline u_char
|
||||
label_bos (mpls_label_t *label)
|
||||
static inline u_char label_bos(mpls_label_t *label)
|
||||
{
|
||||
u_char *t= (u_char *) label;
|
||||
return (t[2] & 0x01);
|
||||
u_char *t = (u_char *)label;
|
||||
return (t[2] & 0x01);
|
||||
};
|
||||
|
||||
#endif /* _BGP_LABEL_H */
|
||||
|
||||
@ -34,29 +34,26 @@
|
||||
static struct hash *lcomhash;
|
||||
|
||||
/* Allocate a new lcommunities. */
|
||||
static struct lcommunity *
|
||||
lcommunity_new (void)
|
||||
static struct lcommunity *lcommunity_new(void)
|
||||
{
|
||||
return (struct lcommunity *) XCALLOC (MTYPE_LCOMMUNITY,
|
||||
sizeof (struct lcommunity));
|
||||
return (struct lcommunity *)XCALLOC(MTYPE_LCOMMUNITY,
|
||||
sizeof(struct lcommunity));
|
||||
}
|
||||
|
||||
/* Allocate lcommunities. */
|
||||
void
|
||||
lcommunity_free (struct lcommunity **lcom)
|
||||
void lcommunity_free(struct lcommunity **lcom)
|
||||
{
|
||||
if ((*lcom)->val)
|
||||
XFREE (MTYPE_LCOMMUNITY_VAL, (*lcom)->val);
|
||||
if ((*lcom)->str)
|
||||
XFREE (MTYPE_LCOMMUNITY_STR, (*lcom)->str);
|
||||
XFREE (MTYPE_LCOMMUNITY, *lcom);
|
||||
lcom = NULL;
|
||||
if ((*lcom)->val)
|
||||
XFREE(MTYPE_LCOMMUNITY_VAL, (*lcom)->val);
|
||||
if ((*lcom)->str)
|
||||
XFREE(MTYPE_LCOMMUNITY_STR, (*lcom)->str);
|
||||
XFREE(MTYPE_LCOMMUNITY, *lcom);
|
||||
lcom = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
lcommunity_hash_free (struct lcommunity *lcom)
|
||||
static void lcommunity_hash_free(struct lcommunity *lcom)
|
||||
{
|
||||
lcommunity_free (&lcom);
|
||||
lcommunity_free(&lcom);
|
||||
}
|
||||
|
||||
/* Add a new Large Communities value to Large Communities
|
||||
@ -64,329 +61,308 @@ lcommunity_hash_free (struct lcommunity *lcom)
|
||||
structure, we don't add the value. Newly added value is sorted by
|
||||
numerical order. When the value is added to the structure return 1
|
||||
else return 0. */
|
||||
static int
|
||||
lcommunity_add_val (struct lcommunity *lcom, struct lcommunity_val *lval)
|
||||
static int lcommunity_add_val(struct lcommunity *lcom,
|
||||
struct lcommunity_val *lval)
|
||||
{
|
||||
u_int8_t *p;
|
||||
int ret;
|
||||
int c;
|
||||
u_int8_t *p;
|
||||
int ret;
|
||||
int c;
|
||||
|
||||
/* When this is fist value, just add it. */
|
||||
if (lcom->val == NULL)
|
||||
{
|
||||
lcom->size++;
|
||||
lcom->val = XMALLOC (MTYPE_LCOMMUNITY_VAL, lcom_length (lcom));
|
||||
memcpy (lcom->val, lval->val, LCOMMUNITY_SIZE);
|
||||
return 1;
|
||||
}
|
||||
/* When this is fist value, just add it. */
|
||||
if (lcom->val == NULL) {
|
||||
lcom->size++;
|
||||
lcom->val = XMALLOC(MTYPE_LCOMMUNITY_VAL, lcom_length(lcom));
|
||||
memcpy(lcom->val, lval->val, LCOMMUNITY_SIZE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If the value already exists in the structure return 0. */
|
||||
c = 0;
|
||||
for (p = lcom->val; c < lcom->size; p += LCOMMUNITY_SIZE, c++)
|
||||
{
|
||||
ret = memcmp (p, lval->val, LCOMMUNITY_SIZE);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
if (ret > 0)
|
||||
break;
|
||||
}
|
||||
/* If the value already exists in the structure return 0. */
|
||||
c = 0;
|
||||
for (p = lcom->val; c < lcom->size; p += LCOMMUNITY_SIZE, c++) {
|
||||
ret = memcmp(p, lval->val, LCOMMUNITY_SIZE);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
if (ret > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Add the value to the structure with numerical sorting. */
|
||||
lcom->size++;
|
||||
lcom->val = XREALLOC (MTYPE_LCOMMUNITY_VAL, lcom->val, lcom_length (lcom));
|
||||
/* Add the value to the structure with numerical sorting. */
|
||||
lcom->size++;
|
||||
lcom->val =
|
||||
XREALLOC(MTYPE_LCOMMUNITY_VAL, lcom->val, lcom_length(lcom));
|
||||
|
||||
memmove (lcom->val + (c + 1) * LCOMMUNITY_SIZE,
|
||||
lcom->val + c * LCOMMUNITY_SIZE,
|
||||
(lcom->size - 1 - c) * LCOMMUNITY_SIZE);
|
||||
memcpy (lcom->val + c * LCOMMUNITY_SIZE, lval->val, LCOMMUNITY_SIZE);
|
||||
memmove(lcom->val + (c + 1) * LCOMMUNITY_SIZE,
|
||||
lcom->val + c * LCOMMUNITY_SIZE,
|
||||
(lcom->size - 1 - c) * LCOMMUNITY_SIZE);
|
||||
memcpy(lcom->val + c * LCOMMUNITY_SIZE, lval->val, LCOMMUNITY_SIZE);
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This function takes pointer to Large Communites strucutre then
|
||||
create a new Large Communities structure by uniq and sort each
|
||||
Large Communities value. */
|
||||
struct lcommunity *
|
||||
lcommunity_uniq_sort (struct lcommunity *lcom)
|
||||
struct lcommunity *lcommunity_uniq_sort(struct lcommunity *lcom)
|
||||
{
|
||||
int i;
|
||||
struct lcommunity *new;
|
||||
struct lcommunity_val *lval;
|
||||
int i;
|
||||
struct lcommunity *new;
|
||||
struct lcommunity_val *lval;
|
||||
|
||||
if (! lcom)
|
||||
return NULL;
|
||||
if (!lcom)
|
||||
return NULL;
|
||||
|
||||
new = lcommunity_new ();
|
||||
new = lcommunity_new();
|
||||
|
||||
for (i = 0; i < lcom->size; i++)
|
||||
{
|
||||
lval = (struct lcommunity_val *) (lcom->val + (i * LCOMMUNITY_SIZE));
|
||||
lcommunity_add_val (new, lval);
|
||||
}
|
||||
return new;
|
||||
for (i = 0; i < lcom->size; i++) {
|
||||
lval = (struct lcommunity_val *)(lcom->val
|
||||
+ (i * LCOMMUNITY_SIZE));
|
||||
lcommunity_add_val(new, lval);
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Parse Large Communites Attribute in BGP packet. */
|
||||
struct lcommunity *
|
||||
lcommunity_parse (u_int8_t *pnt, u_short length)
|
||||
struct lcommunity *lcommunity_parse(u_int8_t *pnt, u_short length)
|
||||
{
|
||||
struct lcommunity tmp;
|
||||
struct lcommunity *new;
|
||||
struct lcommunity tmp;
|
||||
struct lcommunity *new;
|
||||
|
||||
/* Length check. */
|
||||
if (length % LCOMMUNITY_SIZE)
|
||||
return NULL;
|
||||
/* Length check. */
|
||||
if (length % LCOMMUNITY_SIZE)
|
||||
return NULL;
|
||||
|
||||
/* Prepare tmporary structure for making a new Large Communities
|
||||
Attribute. */
|
||||
tmp.size = length / LCOMMUNITY_SIZE;
|
||||
tmp.val = pnt;
|
||||
/* Prepare tmporary structure for making a new Large Communities
|
||||
Attribute. */
|
||||
tmp.size = length / LCOMMUNITY_SIZE;
|
||||
tmp.val = pnt;
|
||||
|
||||
/* Create a new Large Communities Attribute by uniq and sort each
|
||||
Large Communities value */
|
||||
new = lcommunity_uniq_sort (&tmp);
|
||||
/* Create a new Large Communities Attribute by uniq and sort each
|
||||
Large Communities value */
|
||||
new = lcommunity_uniq_sort(&tmp);
|
||||
|
||||
return lcommunity_intern (new);
|
||||
return lcommunity_intern(new);
|
||||
}
|
||||
|
||||
/* Duplicate the Large Communities Attribute structure. */
|
||||
struct lcommunity *
|
||||
lcommunity_dup (struct lcommunity *lcom)
|
||||
struct lcommunity *lcommunity_dup(struct lcommunity *lcom)
|
||||
{
|
||||
struct lcommunity *new;
|
||||
struct lcommunity *new;
|
||||
|
||||
new = XCALLOC (MTYPE_LCOMMUNITY, sizeof (struct lcommunity));
|
||||
new->size = lcom->size;
|
||||
if (new->size)
|
||||
{
|
||||
new->val = XMALLOC (MTYPE_LCOMMUNITY_VAL, lcom->size * LCOMMUNITY_SIZE);
|
||||
memcpy (new->val, lcom->val, lcom->size * LCOMMUNITY_SIZE);
|
||||
}
|
||||
else
|
||||
new->val = NULL;
|
||||
return new;
|
||||
new = XCALLOC(MTYPE_LCOMMUNITY, sizeof(struct lcommunity));
|
||||
new->size = lcom->size;
|
||||
if (new->size) {
|
||||
new->val = XMALLOC(MTYPE_LCOMMUNITY_VAL,
|
||||
lcom->size * LCOMMUNITY_SIZE);
|
||||
memcpy(new->val, lcom->val, lcom->size * LCOMMUNITY_SIZE);
|
||||
} else
|
||||
new->val = NULL;
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Retrun string representation of communities attribute. */
|
||||
char *
|
||||
lcommunity_str (struct lcommunity *lcom)
|
||||
char *lcommunity_str(struct lcommunity *lcom)
|
||||
{
|
||||
if (! lcom->str)
|
||||
lcom->str = lcommunity_lcom2str (lcom, LCOMMUNITY_FORMAT_DISPLAY);
|
||||
return lcom->str;
|
||||
if (!lcom->str)
|
||||
lcom->str =
|
||||
lcommunity_lcom2str(lcom, LCOMMUNITY_FORMAT_DISPLAY);
|
||||
return lcom->str;
|
||||
}
|
||||
|
||||
/* Merge two Large Communities Attribute structure. */
|
||||
struct lcommunity *
|
||||
lcommunity_merge (struct lcommunity *lcom1, struct lcommunity *lcom2)
|
||||
struct lcommunity *lcommunity_merge(struct lcommunity *lcom1,
|
||||
struct lcommunity *lcom2)
|
||||
{
|
||||
if (lcom1->val)
|
||||
lcom1->val = XREALLOC (MTYPE_LCOMMUNITY_VAL, lcom1->val,
|
||||
(lcom1->size + lcom2->size) * LCOMMUNITY_SIZE);
|
||||
else
|
||||
lcom1->val = XMALLOC (MTYPE_LCOMMUNITY_VAL,
|
||||
(lcom1->size + lcom2->size) * LCOMMUNITY_SIZE);
|
||||
if (lcom1->val)
|
||||
lcom1->val =
|
||||
XREALLOC(MTYPE_LCOMMUNITY_VAL, lcom1->val,
|
||||
(lcom1->size + lcom2->size) * LCOMMUNITY_SIZE);
|
||||
else
|
||||
lcom1->val =
|
||||
XMALLOC(MTYPE_LCOMMUNITY_VAL,
|
||||
(lcom1->size + lcom2->size) * LCOMMUNITY_SIZE);
|
||||
|
||||
memcpy (lcom1->val + (lcom1->size * LCOMMUNITY_SIZE),
|
||||
lcom2->val, lcom2->size * LCOMMUNITY_SIZE);
|
||||
lcom1->size += lcom2->size;
|
||||
memcpy(lcom1->val + (lcom1->size * LCOMMUNITY_SIZE), lcom2->val,
|
||||
lcom2->size * LCOMMUNITY_SIZE);
|
||||
lcom1->size += lcom2->size;
|
||||
|
||||
return lcom1;
|
||||
return lcom1;
|
||||
}
|
||||
|
||||
/* Intern Large Communities Attribute. */
|
||||
struct lcommunity *
|
||||
lcommunity_intern (struct lcommunity *lcom)
|
||||
struct lcommunity *lcommunity_intern(struct lcommunity *lcom)
|
||||
{
|
||||
struct lcommunity *find;
|
||||
struct lcommunity *find;
|
||||
|
||||
assert (lcom->refcnt == 0);
|
||||
assert(lcom->refcnt == 0);
|
||||
|
||||
find = (struct lcommunity *) hash_get (lcomhash, lcom, hash_alloc_intern);
|
||||
find = (struct lcommunity *)hash_get(lcomhash, lcom, hash_alloc_intern);
|
||||
|
||||
if (find != lcom)
|
||||
lcommunity_free (&lcom);
|
||||
if (find != lcom)
|
||||
lcommunity_free(&lcom);
|
||||
|
||||
find->refcnt++;
|
||||
find->refcnt++;
|
||||
|
||||
if (! find->str)
|
||||
find->str = lcommunity_lcom2str (find, LCOMMUNITY_FORMAT_DISPLAY);
|
||||
if (!find->str)
|
||||
find->str =
|
||||
lcommunity_lcom2str(find, LCOMMUNITY_FORMAT_DISPLAY);
|
||||
|
||||
return find;
|
||||
return find;
|
||||
}
|
||||
|
||||
/* Unintern Large Communities Attribute. */
|
||||
void
|
||||
lcommunity_unintern (struct lcommunity **lcom)
|
||||
void lcommunity_unintern(struct lcommunity **lcom)
|
||||
{
|
||||
struct lcommunity *ret;
|
||||
struct lcommunity *ret;
|
||||
|
||||
if ((*lcom)->refcnt)
|
||||
(*lcom)->refcnt--;
|
||||
if ((*lcom)->refcnt)
|
||||
(*lcom)->refcnt--;
|
||||
|
||||
/* Pull off from hash. */
|
||||
if ((*lcom)->refcnt == 0)
|
||||
{
|
||||
/* Large community must be in the hash. */
|
||||
ret = (struct lcommunity *) hash_release (lcomhash, *lcom);
|
||||
assert (ret != NULL);
|
||||
/* Pull off from hash. */
|
||||
if ((*lcom)->refcnt == 0) {
|
||||
/* Large community must be in the hash. */
|
||||
ret = (struct lcommunity *)hash_release(lcomhash, *lcom);
|
||||
assert(ret != NULL);
|
||||
|
||||
lcommunity_free (lcom);
|
||||
}
|
||||
lcommunity_free(lcom);
|
||||
}
|
||||
}
|
||||
|
||||
/* Utility function to make hash key. */
|
||||
unsigned int
|
||||
lcommunity_hash_make (void *arg)
|
||||
unsigned int lcommunity_hash_make(void *arg)
|
||||
{
|
||||
const struct lcommunity *lcom = arg;
|
||||
int size = lcom->size * LCOMMUNITY_SIZE;
|
||||
u_int8_t *pnt = lcom->val;
|
||||
unsigned int key = 0;
|
||||
int c;
|
||||
const struct lcommunity *lcom = arg;
|
||||
int size = lcom->size * LCOMMUNITY_SIZE;
|
||||
u_int8_t *pnt = lcom->val;
|
||||
unsigned int key = 0;
|
||||
int c;
|
||||
|
||||
for (c = 0; c < size; c += LCOMMUNITY_SIZE)
|
||||
{
|
||||
key += pnt[c];
|
||||
key += pnt[c + 1];
|
||||
key += pnt[c + 2];
|
||||
key += pnt[c + 3];
|
||||
key += pnt[c + 4];
|
||||
key += pnt[c + 5];
|
||||
key += pnt[c + 6];
|
||||
key += pnt[c + 7];
|
||||
key += pnt[c + 8];
|
||||
key += pnt[c + 9];
|
||||
key += pnt[c + 10];
|
||||
key += pnt[c + 11];
|
||||
}
|
||||
for (c = 0; c < size; c += LCOMMUNITY_SIZE) {
|
||||
key += pnt[c];
|
||||
key += pnt[c + 1];
|
||||
key += pnt[c + 2];
|
||||
key += pnt[c + 3];
|
||||
key += pnt[c + 4];
|
||||
key += pnt[c + 5];
|
||||
key += pnt[c + 6];
|
||||
key += pnt[c + 7];
|
||||
key += pnt[c + 8];
|
||||
key += pnt[c + 9];
|
||||
key += pnt[c + 10];
|
||||
key += pnt[c + 11];
|
||||
}
|
||||
|
||||
return key;
|
||||
return key;
|
||||
}
|
||||
|
||||
/* Compare two Large Communities Attribute structure. */
|
||||
int
|
||||
lcommunity_cmp (const void *arg1, const void *arg2)
|
||||
int lcommunity_cmp(const void *arg1, const void *arg2)
|
||||
{
|
||||
const struct lcommunity *lcom1 = arg1;
|
||||
const struct lcommunity *lcom2 = arg2;
|
||||
const struct lcommunity *lcom1 = arg1;
|
||||
const struct lcommunity *lcom2 = arg2;
|
||||
|
||||
return (lcom1->size == lcom2->size
|
||||
&& memcmp (lcom1->val, lcom2->val, lcom1->size * LCOMMUNITY_SIZE) == 0);
|
||||
return (lcom1->size == lcom2->size
|
||||
&& memcmp(lcom1->val, lcom2->val, lcom1->size * LCOMMUNITY_SIZE)
|
||||
== 0);
|
||||
}
|
||||
|
||||
/* Return communities hash. */
|
||||
struct hash *
|
||||
lcommunity_hash (void)
|
||||
struct hash *lcommunity_hash(void)
|
||||
{
|
||||
return lcomhash;
|
||||
return lcomhash;
|
||||
}
|
||||
|
||||
/* Initialize Large Comminities related hash. */
|
||||
void
|
||||
lcommunity_init (void)
|
||||
void lcommunity_init(void)
|
||||
{
|
||||
lcomhash = hash_create (lcommunity_hash_make, lcommunity_cmp, NULL);
|
||||
lcomhash = hash_create(lcommunity_hash_make, lcommunity_cmp, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
lcommunity_finish (void)
|
||||
void lcommunity_finish(void)
|
||||
{
|
||||
hash_clean (lcomhash, (void (*)(void *))lcommunity_hash_free);
|
||||
hash_free (lcomhash);
|
||||
lcomhash = NULL;
|
||||
hash_clean(lcomhash, (void (*)(void *))lcommunity_hash_free);
|
||||
hash_free(lcomhash);
|
||||
lcomhash = NULL;
|
||||
}
|
||||
|
||||
/* Large Communities token enum. */
|
||||
enum lcommunity_token
|
||||
{
|
||||
lcommunity_token_unknown = 0,
|
||||
lcommunity_token_val,
|
||||
enum lcommunity_token {
|
||||
lcommunity_token_unknown = 0,
|
||||
lcommunity_token_val,
|
||||
};
|
||||
|
||||
/* Get next Large Communities token from the string. */
|
||||
static const char *
|
||||
lcommunity_gettoken (const char *str, struct lcommunity_val *lval,
|
||||
enum lcommunity_token *token)
|
||||
static const char *lcommunity_gettoken(const char *str,
|
||||
struct lcommunity_val *lval,
|
||||
enum lcommunity_token *token)
|
||||
{
|
||||
const char *p = str;
|
||||
const char *p = str;
|
||||
|
||||
/* Skip white space. */
|
||||
while (isspace ((int) *p))
|
||||
{
|
||||
p++;
|
||||
str++;
|
||||
}
|
||||
|
||||
/* Check the end of the line. */
|
||||
if (*p == '\0')
|
||||
return NULL;
|
||||
|
||||
/* Community value. */
|
||||
if (isdigit ((int) *p))
|
||||
{
|
||||
int separator = 0;
|
||||
int digit = 0;
|
||||
u_int32_t globaladmin = 0;
|
||||
u_int32_t localdata1 = 0;
|
||||
u_int32_t localdata2 = 0;
|
||||
|
||||
while (isdigit ((int) *p) || *p == ':')
|
||||
{
|
||||
if (*p == ':')
|
||||
{
|
||||
if (separator == 2)
|
||||
{
|
||||
*token = lcommunity_token_unknown;
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
separator++;
|
||||
digit = 0;
|
||||
if (separator == 1) {
|
||||
globaladmin = localdata2;
|
||||
} else {
|
||||
localdata1 = localdata2;
|
||||
}
|
||||
localdata2 = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
digit = 1;
|
||||
localdata2 *= 10;
|
||||
localdata2 += (*p - '0');
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if (! digit)
|
||||
{
|
||||
*token = lcommunity_token_unknown;
|
||||
return NULL;
|
||||
/* Skip white space. */
|
||||
while (isspace((int)*p)) {
|
||||
p++;
|
||||
str++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the large comm.
|
||||
*/
|
||||
lval->val[0] = (globaladmin >> 24) & 0xff;
|
||||
lval->val[1] = (globaladmin >> 16) & 0xff;
|
||||
lval->val[2] = (globaladmin >> 8) & 0xff;
|
||||
lval->val[3] = globaladmin & 0xff;
|
||||
lval->val[4] = (localdata1 >> 24) & 0xff;
|
||||
lval->val[5] = (localdata1 >> 16) & 0xff;
|
||||
lval->val[6] = (localdata1 >> 8) & 0xff;
|
||||
lval->val[7] = localdata1 & 0xff;
|
||||
lval->val[8] = (localdata2 >> 24) & 0xff;
|
||||
lval->val[9] = (localdata2 >> 16) & 0xff;
|
||||
lval->val[10] = (localdata2 >> 8) & 0xff;
|
||||
lval->val[11] = localdata2 & 0xff;
|
||||
/* Check the end of the line. */
|
||||
if (*p == '\0')
|
||||
return NULL;
|
||||
|
||||
*token = lcommunity_token_val;
|
||||
return p;
|
||||
}
|
||||
*token = lcommunity_token_unknown;
|
||||
return p;
|
||||
/* Community value. */
|
||||
if (isdigit((int)*p)) {
|
||||
int separator = 0;
|
||||
int digit = 0;
|
||||
u_int32_t globaladmin = 0;
|
||||
u_int32_t localdata1 = 0;
|
||||
u_int32_t localdata2 = 0;
|
||||
|
||||
while (isdigit((int)*p) || *p == ':') {
|
||||
if (*p == ':') {
|
||||
if (separator == 2) {
|
||||
*token = lcommunity_token_unknown;
|
||||
return NULL;
|
||||
} else {
|
||||
separator++;
|
||||
digit = 0;
|
||||
if (separator == 1) {
|
||||
globaladmin = localdata2;
|
||||
} else {
|
||||
localdata1 = localdata2;
|
||||
}
|
||||
localdata2 = 0;
|
||||
}
|
||||
} else {
|
||||
digit = 1;
|
||||
localdata2 *= 10;
|
||||
localdata2 += (*p - '0');
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if (!digit) {
|
||||
*token = lcommunity_token_unknown;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the large comm.
|
||||
*/
|
||||
lval->val[0] = (globaladmin >> 24) & 0xff;
|
||||
lval->val[1] = (globaladmin >> 16) & 0xff;
|
||||
lval->val[2] = (globaladmin >> 8) & 0xff;
|
||||
lval->val[3] = globaladmin & 0xff;
|
||||
lval->val[4] = (localdata1 >> 24) & 0xff;
|
||||
lval->val[5] = (localdata1 >> 16) & 0xff;
|
||||
lval->val[6] = (localdata1 >> 8) & 0xff;
|
||||
lval->val[7] = localdata1 & 0xff;
|
||||
lval->val[8] = (localdata2 >> 24) & 0xff;
|
||||
lval->val[9] = (localdata2 >> 16) & 0xff;
|
||||
lval->val[10] = (localdata2 >> 8) & 0xff;
|
||||
lval->val[11] = localdata2 & 0xff;
|
||||
|
||||
*token = lcommunity_token_val;
|
||||
return p;
|
||||
}
|
||||
*token = lcommunity_token_unknown;
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -396,174 +372,168 @@ lcommunity_gettoken (const char *str, struct lcommunity_val *lval,
|
||||
When string includes keyword for each large community value.
|
||||
Please specify keyword_included as non-zero value.
|
||||
*/
|
||||
struct lcommunity *
|
||||
lcommunity_str2com (const char *str)
|
||||
struct lcommunity *lcommunity_str2com(const char *str)
|
||||
{
|
||||
struct lcommunity *lcom = NULL;
|
||||
enum lcommunity_token token = lcommunity_token_unknown;
|
||||
struct lcommunity_val lval;
|
||||
struct lcommunity *lcom = NULL;
|
||||
enum lcommunity_token token = lcommunity_token_unknown;
|
||||
struct lcommunity_val lval;
|
||||
|
||||
while ((str = lcommunity_gettoken (str, &lval, &token)))
|
||||
{
|
||||
switch (token)
|
||||
{
|
||||
case lcommunity_token_val:
|
||||
if (lcom == NULL)
|
||||
lcom = lcommunity_new ();
|
||||
lcommunity_add_val (lcom, &lval);
|
||||
break;
|
||||
case lcommunity_token_unknown:
|
||||
default:
|
||||
if (lcom)
|
||||
lcommunity_free (&lcom);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return lcom;
|
||||
while ((str = lcommunity_gettoken(str, &lval, &token))) {
|
||||
switch (token) {
|
||||
case lcommunity_token_val:
|
||||
if (lcom == NULL)
|
||||
lcom = lcommunity_new();
|
||||
lcommunity_add_val(lcom, &lval);
|
||||
break;
|
||||
case lcommunity_token_unknown:
|
||||
default:
|
||||
if (lcom)
|
||||
lcommunity_free(&lcom);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return lcom;
|
||||
}
|
||||
|
||||
int
|
||||
lcommunity_include (struct lcommunity *lcom, u_char *ptr)
|
||||
int lcommunity_include(struct lcommunity *lcom, u_char *ptr)
|
||||
{
|
||||
int i;
|
||||
u_char *lcom_ptr;
|
||||
int i;
|
||||
u_char *lcom_ptr;
|
||||
|
||||
lcom_ptr = lcom->val;
|
||||
for (i = 0; i < lcom->size; i++) {
|
||||
lcom_ptr += (i * LCOMMUNITY_SIZE);
|
||||
if (memcmp (ptr, lcom_ptr, LCOMMUNITY_SIZE) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
lcom_ptr = lcom->val;
|
||||
for (i = 0; i < lcom->size; i++) {
|
||||
lcom_ptr += (i * LCOMMUNITY_SIZE);
|
||||
if (memcmp(ptr, lcom_ptr, LCOMMUNITY_SIZE) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert large community attribute to string.
|
||||
The large coms will be in 65535:65531:0 format.
|
||||
*/
|
||||
char *
|
||||
lcommunity_lcom2str (struct lcommunity *lcom, int format)
|
||||
char *lcommunity_lcom2str(struct lcommunity *lcom, int format)
|
||||
{
|
||||
int i;
|
||||
u_int8_t *pnt;
|
||||
int i;
|
||||
u_int8_t *pnt;
|
||||
#define LCOMMUNITY_STR_DEFAULT_LEN 40
|
||||
int str_size;
|
||||
int str_pnt;
|
||||
char *str_buf;
|
||||
int len = 0;
|
||||
int first = 1;
|
||||
u_int32_t globaladmin, localdata1, localdata2;
|
||||
int str_size;
|
||||
int str_pnt;
|
||||
char *str_buf;
|
||||
int len = 0;
|
||||
int first = 1;
|
||||
u_int32_t globaladmin, localdata1, localdata2;
|
||||
|
||||
if (lcom->size == 0)
|
||||
{
|
||||
str_buf = XMALLOC (MTYPE_LCOMMUNITY_STR, 1);
|
||||
str_buf[0] = '\0';
|
||||
return str_buf;
|
||||
}
|
||||
|
||||
/* Prepare buffer. */
|
||||
str_buf = XMALLOC (MTYPE_LCOMMUNITY_STR, LCOMMUNITY_STR_DEFAULT_LEN + 1);
|
||||
str_size = LCOMMUNITY_STR_DEFAULT_LEN + 1;
|
||||
str_pnt = 0;
|
||||
|
||||
for (i = 0; i < lcom->size; i++)
|
||||
{
|
||||
/* Make it sure size is enough. */
|
||||
while (str_pnt + LCOMMUNITY_STR_DEFAULT_LEN >= str_size)
|
||||
{
|
||||
str_size *= 2;
|
||||
str_buf = XREALLOC (MTYPE_LCOMMUNITY_STR, str_buf, str_size);
|
||||
if (lcom->size == 0) {
|
||||
str_buf = XMALLOC(MTYPE_LCOMMUNITY_STR, 1);
|
||||
str_buf[0] = '\0';
|
||||
return str_buf;
|
||||
}
|
||||
|
||||
/* Space between each value. */
|
||||
if (! first)
|
||||
str_buf[str_pnt++] = ' ';
|
||||
/* Prepare buffer. */
|
||||
str_buf = XMALLOC(MTYPE_LCOMMUNITY_STR, LCOMMUNITY_STR_DEFAULT_LEN + 1);
|
||||
str_size = LCOMMUNITY_STR_DEFAULT_LEN + 1;
|
||||
str_pnt = 0;
|
||||
|
||||
pnt = lcom->val + (i * 12);
|
||||
for (i = 0; i < lcom->size; i++) {
|
||||
/* Make it sure size is enough. */
|
||||
while (str_pnt + LCOMMUNITY_STR_DEFAULT_LEN >= str_size) {
|
||||
str_size *= 2;
|
||||
str_buf = XREALLOC(MTYPE_LCOMMUNITY_STR, str_buf,
|
||||
str_size);
|
||||
}
|
||||
|
||||
globaladmin = (*pnt++ << 24);
|
||||
globaladmin |= (*pnt++ << 16);
|
||||
globaladmin |= (*pnt++ << 8);
|
||||
globaladmin |= (*pnt++);
|
||||
/* Space between each value. */
|
||||
if (!first)
|
||||
str_buf[str_pnt++] = ' ';
|
||||
|
||||
localdata1 = (*pnt++ << 24);
|
||||
localdata1 |= (*pnt++ << 16);
|
||||
localdata1 |= (*pnt++ << 8);
|
||||
localdata1 |= (*pnt++);
|
||||
pnt = lcom->val + (i * 12);
|
||||
|
||||
localdata2 = (*pnt++ << 24);
|
||||
localdata2 |= (*pnt++ << 16);
|
||||
localdata2 |= (*pnt++ << 8);
|
||||
localdata2 |= (*pnt++);
|
||||
globaladmin = (*pnt++ << 24);
|
||||
globaladmin |= (*pnt++ << 16);
|
||||
globaladmin |= (*pnt++ << 8);
|
||||
globaladmin |= (*pnt++);
|
||||
|
||||
len = sprintf( str_buf + str_pnt, "%u:%u:%u", globaladmin,
|
||||
localdata1, localdata2);
|
||||
str_pnt += len;
|
||||
first = 0;
|
||||
}
|
||||
return str_buf;
|
||||
localdata1 = (*pnt++ << 24);
|
||||
localdata1 |= (*pnt++ << 16);
|
||||
localdata1 |= (*pnt++ << 8);
|
||||
localdata1 |= (*pnt++);
|
||||
|
||||
localdata2 = (*pnt++ << 24);
|
||||
localdata2 |= (*pnt++ << 16);
|
||||
localdata2 |= (*pnt++ << 8);
|
||||
localdata2 |= (*pnt++);
|
||||
|
||||
len = sprintf(str_buf + str_pnt, "%u:%u:%u", globaladmin,
|
||||
localdata1, localdata2);
|
||||
str_pnt += len;
|
||||
first = 0;
|
||||
}
|
||||
return str_buf;
|
||||
}
|
||||
|
||||
int
|
||||
lcommunity_match (const struct lcommunity *lcom1,
|
||||
const struct lcommunity *lcom2)
|
||||
int lcommunity_match(const struct lcommunity *lcom1,
|
||||
const struct lcommunity *lcom2)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
if (lcom1 == NULL && lcom2 == NULL)
|
||||
return 1;
|
||||
if (lcom1 == NULL && lcom2 == NULL)
|
||||
return 1;
|
||||
|
||||
if (lcom1 == NULL || lcom2 == NULL)
|
||||
return 0;
|
||||
if (lcom1 == NULL || lcom2 == NULL)
|
||||
return 0;
|
||||
|
||||
if (lcom1->size < lcom2->size)
|
||||
return 0;
|
||||
if (lcom1->size < lcom2->size)
|
||||
return 0;
|
||||
|
||||
/* Every community on com2 needs to be on com1 for this to match */
|
||||
while (i < lcom1->size && j < lcom2->size)
|
||||
{
|
||||
if (memcmp (lcom1->val + (i*12), lcom2->val + (j*12), LCOMMUNITY_SIZE) == 0)
|
||||
j++;
|
||||
i++;
|
||||
}
|
||||
/* Every community on com2 needs to be on com1 for this to match */
|
||||
while (i < lcom1->size && j < lcom2->size) {
|
||||
if (memcmp(lcom1->val + (i * 12), lcom2->val + (j * 12),
|
||||
LCOMMUNITY_SIZE)
|
||||
== 0)
|
||||
j++;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (j == lcom2->size)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
if (j == lcom2->size)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Delete one lcommunity. */
|
||||
void
|
||||
lcommunity_del_val (struct lcommunity *lcom, u_char *ptr)
|
||||
void lcommunity_del_val(struct lcommunity *lcom, u_char *ptr)
|
||||
{
|
||||
int i = 0;
|
||||
int c = 0;
|
||||
int i = 0;
|
||||
int c = 0;
|
||||
|
||||
if (! lcom->val)
|
||||
return;
|
||||
if (!lcom->val)
|
||||
return;
|
||||
|
||||
while (i < lcom->size)
|
||||
{
|
||||
if (memcmp (lcom->val + i*LCOMMUNITY_SIZE, ptr, LCOMMUNITY_SIZE) == 0)
|
||||
{
|
||||
c = lcom->size -i -1;
|
||||
while (i < lcom->size) {
|
||||
if (memcmp(lcom->val + i * LCOMMUNITY_SIZE, ptr,
|
||||
LCOMMUNITY_SIZE)
|
||||
== 0) {
|
||||
c = lcom->size - i - 1;
|
||||
|
||||
if (c > 0)
|
||||
memmove (lcom->val + i*LCOMMUNITY_SIZE, lcom->val + (i + 1)*LCOMMUNITY_SIZE, c * LCOMMUNITY_SIZE);
|
||||
if (c > 0)
|
||||
memmove(lcom->val + i * LCOMMUNITY_SIZE,
|
||||
lcom->val + (i + 1) * LCOMMUNITY_SIZE,
|
||||
c * LCOMMUNITY_SIZE);
|
||||
|
||||
lcom->size--;
|
||||
lcom->size--;
|
||||
|
||||
if (lcom->size > 0)
|
||||
lcom->val = XREALLOC (MTYPE_COMMUNITY_VAL, lcom->val,
|
||||
lcom_length (lcom));
|
||||
else
|
||||
{
|
||||
XFREE (MTYPE_COMMUNITY_VAL, lcom->val);
|
||||
lcom->val = NULL;
|
||||
}
|
||||
return;
|
||||
if (lcom->size > 0)
|
||||
lcom->val =
|
||||
XREALLOC(MTYPE_COMMUNITY_VAL, lcom->val,
|
||||
lcom_length(lcom));
|
||||
else {
|
||||
XFREE(MTYPE_COMMUNITY_VAL, lcom->val);
|
||||
lcom->val = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,45 +30,45 @@
|
||||
#define LCOMMUNITY_SIZE 12
|
||||
|
||||
/* Large Communities attribute. */
|
||||
struct lcommunity
|
||||
{
|
||||
/* Reference counter. */
|
||||
unsigned long refcnt;
|
||||
struct lcommunity {
|
||||
/* Reference counter. */
|
||||
unsigned long refcnt;
|
||||
|
||||
/* Size of Extended Communities attribute. */
|
||||
int size;
|
||||
/* Size of Extended Communities attribute. */
|
||||
int size;
|
||||
|
||||
/* Extended Communities value. */
|
||||
u_int8_t *val;
|
||||
/* Extended Communities value. */
|
||||
u_int8_t *val;
|
||||
|
||||
/* Human readable format string. */
|
||||
char *str;
|
||||
/* Human readable format string. */
|
||||
char *str;
|
||||
};
|
||||
|
||||
/* Extended community value is eight octet. */
|
||||
struct lcommunity_val
|
||||
{
|
||||
char val[LCOMMUNITY_SIZE];
|
||||
struct lcommunity_val {
|
||||
char val[LCOMMUNITY_SIZE];
|
||||
};
|
||||
|
||||
#define lcom_length(X) ((X)->size * LCOMMUNITY_SIZE)
|
||||
|
||||
extern void lcommunity_init (void);
|
||||
extern void lcommunity_finish (void);
|
||||
extern void lcommunity_free (struct lcommunity **);
|
||||
extern struct lcommunity *lcommunity_parse (u_int8_t *, u_short);
|
||||
extern struct lcommunity *lcommunity_dup (struct lcommunity *);
|
||||
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 void lcommunity_unintern (struct lcommunity **);
|
||||
extern unsigned int lcommunity_hash_make (void *);
|
||||
extern struct hash *lcommunity_hash (void);
|
||||
extern struct lcommunity *lcommunity_str2com (const char *);
|
||||
extern char *lcommunity_lcom2str (struct lcommunity *, int);
|
||||
extern int lcommunity_match (const struct lcommunity *, const struct lcommunity *);
|
||||
extern char *lcommunity_str (struct lcommunity *);
|
||||
extern int lcommunity_include (struct lcommunity *lcom, u_char *ptr);
|
||||
extern void lcommunity_del_val (struct lcommunity *lcom, u_char *ptr);
|
||||
extern void lcommunity_init(void);
|
||||
extern void lcommunity_finish(void);
|
||||
extern void lcommunity_free(struct lcommunity **);
|
||||
extern struct lcommunity *lcommunity_parse(u_int8_t *, u_short);
|
||||
extern struct lcommunity *lcommunity_dup(struct lcommunity *);
|
||||
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 void lcommunity_unintern(struct lcommunity **);
|
||||
extern unsigned int lcommunity_hash_make(void *);
|
||||
extern struct hash *lcommunity_hash(void);
|
||||
extern struct lcommunity *lcommunity_str2com(const char *);
|
||||
extern char *lcommunity_lcom2str(struct lcommunity *, int);
|
||||
extern int lcommunity_match(const struct lcommunity *,
|
||||
const struct lcommunity *);
|
||||
extern char *lcommunity_str(struct lcommunity *);
|
||||
extern int lcommunity_include(struct lcommunity *lcom, u_char *ptr);
|
||||
extern void lcommunity_del_val(struct lcommunity *lcom, u_char *ptr);
|
||||
#endif /* _QUAGGA_BGP_LCOMMUNITY_H */
|
||||
|
||||
498
bgpd/bgp_main.c
498
bgpd/bgp_main.c
@ -60,112 +60,101 @@
|
||||
#endif
|
||||
|
||||
/* bgpd options, we use GNU getopt library. */
|
||||
static const struct option longopts[] =
|
||||
{
|
||||
{ "bgp_port", required_argument, NULL, 'p'},
|
||||
{ "listenon", required_argument, NULL, 'l'},
|
||||
{ "retain", no_argument, NULL, 'r'},
|
||||
{ "no_kernel", no_argument, NULL, 'n'},
|
||||
{ "skip_runas", no_argument, NULL, 'S'},
|
||||
{ "ecmp", required_argument, NULL, 'e'},
|
||||
{ 0 }
|
||||
};
|
||||
static const struct option longopts[] = {
|
||||
{"bgp_port", required_argument, NULL, 'p'},
|
||||
{"listenon", required_argument, NULL, 'l'},
|
||||
{"retain", no_argument, NULL, 'r'},
|
||||
{"no_kernel", no_argument, NULL, 'n'},
|
||||
{"skip_runas", no_argument, NULL, 'S'},
|
||||
{"ecmp", required_argument, NULL, 'e'},
|
||||
{0}};
|
||||
|
||||
/* signal definitions */
|
||||
void sighup (void);
|
||||
void sigint (void);
|
||||
void sigusr1 (void);
|
||||
void sighup(void);
|
||||
void sigint(void);
|
||||
void sigusr1(void);
|
||||
|
||||
static void bgp_exit (int);
|
||||
static void bgp_vrf_terminate (void);
|
||||
static void bgp_exit(int);
|
||||
static void bgp_vrf_terminate(void);
|
||||
|
||||
static struct quagga_signal_t bgp_signals[] =
|
||||
{
|
||||
{
|
||||
.signal = SIGHUP,
|
||||
.handler = &sighup,
|
||||
},
|
||||
{
|
||||
.signal = SIGUSR1,
|
||||
.handler = &sigusr1,
|
||||
},
|
||||
{
|
||||
.signal = SIGINT,
|
||||
.handler = &sigint,
|
||||
},
|
||||
{
|
||||
.signal = SIGTERM,
|
||||
.handler = &sigint,
|
||||
},
|
||||
static struct quagga_signal_t bgp_signals[] = {
|
||||
{
|
||||
.signal = SIGHUP,
|
||||
.handler = &sighup,
|
||||
},
|
||||
{
|
||||
.signal = SIGUSR1,
|
||||
.handler = &sigusr1,
|
||||
},
|
||||
{
|
||||
.signal = SIGINT,
|
||||
.handler = &sigint,
|
||||
},
|
||||
{
|
||||
.signal = SIGTERM,
|
||||
.handler = &sigint,
|
||||
},
|
||||
};
|
||||
|
||||
/* Route retain mode flag. */
|
||||
static int retain_mode = 0;
|
||||
|
||||
/* privileges */
|
||||
static zebra_capabilities_t _caps_p [] =
|
||||
{
|
||||
ZCAP_BIND,
|
||||
ZCAP_NET_RAW,
|
||||
ZCAP_NET_ADMIN,
|
||||
static zebra_capabilities_t _caps_p[] = {
|
||||
ZCAP_BIND, ZCAP_NET_RAW, ZCAP_NET_ADMIN,
|
||||
};
|
||||
|
||||
struct zebra_privs_t bgpd_privs =
|
||||
{
|
||||
struct zebra_privs_t bgpd_privs = {
|
||||
#if defined(FRR_USER) && defined(FRR_GROUP)
|
||||
.user = FRR_USER,
|
||||
.group = FRR_GROUP,
|
||||
.user = FRR_USER,
|
||||
.group = FRR_GROUP,
|
||||
#endif
|
||||
#ifdef VTY_GROUP
|
||||
.vty_group = VTY_GROUP,
|
||||
.vty_group = VTY_GROUP,
|
||||
#endif
|
||||
.caps_p = _caps_p,
|
||||
.cap_num_p = array_size(_caps_p),
|
||||
.cap_num_i = 0,
|
||||
.caps_p = _caps_p,
|
||||
.cap_num_p = array_size(_caps_p),
|
||||
.cap_num_i = 0,
|
||||
};
|
||||
|
||||
static struct frr_daemon_info bgpd_di;
|
||||
|
||||
/* SIGHUP handler. */
|
||||
void
|
||||
sighup (void)
|
||||
void sighup(void)
|
||||
{
|
||||
zlog_info ("SIGHUP received");
|
||||
zlog_info("SIGHUP received");
|
||||
|
||||
/* Terminate all thread. */
|
||||
bgp_terminate ();
|
||||
bgp_reset ();
|
||||
zlog_info ("bgpd restarting!");
|
||||
/* Terminate all thread. */
|
||||
bgp_terminate();
|
||||
bgp_reset();
|
||||
zlog_info("bgpd restarting!");
|
||||
|
||||
/* Reload config file. */
|
||||
vty_read_config (bgpd_di.config_file, config_default);
|
||||
/* Reload config file. */
|
||||
vty_read_config(bgpd_di.config_file, config_default);
|
||||
|
||||
/* Try to return to normal operation. */
|
||||
/* Try to return to normal operation. */
|
||||
}
|
||||
|
||||
/* SIGINT handler. */
|
||||
__attribute__((__noreturn__)) void
|
||||
sigint (void)
|
||||
__attribute__((__noreturn__)) void sigint(void)
|
||||
{
|
||||
zlog_notice ("Terminating on signal");
|
||||
zlog_notice("Terminating on signal");
|
||||
|
||||
if (! retain_mode)
|
||||
{
|
||||
bgp_terminate ();
|
||||
if (bgpd_privs.user) /* NULL if skip_runas flag set */
|
||||
zprivs_terminate (&bgpd_privs);
|
||||
}
|
||||
if (!retain_mode) {
|
||||
bgp_terminate();
|
||||
if (bgpd_privs.user) /* NULL if skip_runas flag set */
|
||||
zprivs_terminate(&bgpd_privs);
|
||||
}
|
||||
|
||||
bgp_exit (0);
|
||||
bgp_exit(0);
|
||||
|
||||
exit (0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* SIGUSR1 handler. */
|
||||
void
|
||||
sigusr1 (void)
|
||||
void sigusr1(void)
|
||||
{
|
||||
zlog_rotate();
|
||||
zlog_rotate();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -175,265 +164,250 @@ sigusr1 (void)
|
||||
Zebra route removal and protocol teardown are not meant to be done here.
|
||||
For example, "retain_mode" may be set.
|
||||
*/
|
||||
static __attribute__((__noreturn__)) void
|
||||
bgp_exit (int status)
|
||||
static __attribute__((__noreturn__)) void bgp_exit(int status)
|
||||
{
|
||||
struct bgp *bgp;
|
||||
struct listnode *node, *nnode;
|
||||
struct bgp *bgp;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
/* it only makes sense for this to be called on a clean exit */
|
||||
assert (status == 0);
|
||||
/* it only makes sense for this to be called on a clean exit */
|
||||
assert(status == 0);
|
||||
|
||||
bfd_gbl_exit();
|
||||
bfd_gbl_exit();
|
||||
|
||||
bgp_close();
|
||||
bgp_close();
|
||||
|
||||
if (retain_mode)
|
||||
if_add_hook (IF_DELETE_HOOK, NULL);
|
||||
if (retain_mode)
|
||||
if_add_hook(IF_DELETE_HOOK, NULL);
|
||||
|
||||
/* reverse bgp_master_init */
|
||||
for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
|
||||
bgp_delete (bgp);
|
||||
/* reverse bgp_master_init */
|
||||
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
|
||||
bgp_delete(bgp);
|
||||
|
||||
/* reverse bgp_dump_init */
|
||||
bgp_dump_finish ();
|
||||
/* reverse bgp_dump_init */
|
||||
bgp_dump_finish();
|
||||
|
||||
/* reverse bgp_route_init */
|
||||
bgp_route_finish ();
|
||||
/* reverse bgp_route_init */
|
||||
bgp_route_finish();
|
||||
|
||||
/* cleanup route maps */
|
||||
bgp_route_map_terminate();
|
||||
/* cleanup route maps */
|
||||
bgp_route_map_terminate();
|
||||
|
||||
/* reverse bgp_attr_init */
|
||||
bgp_attr_finish ();
|
||||
/* reverse bgp_attr_init */
|
||||
bgp_attr_finish();
|
||||
|
||||
/* reverse access_list_init */
|
||||
access_list_add_hook (NULL);
|
||||
access_list_delete_hook (NULL);
|
||||
access_list_reset ();
|
||||
/* reverse access_list_init */
|
||||
access_list_add_hook(NULL);
|
||||
access_list_delete_hook(NULL);
|
||||
access_list_reset();
|
||||
|
||||
/* reverse bgp_filter_init */
|
||||
as_list_add_hook (NULL);
|
||||
as_list_delete_hook (NULL);
|
||||
bgp_filter_reset ();
|
||||
/* reverse bgp_filter_init */
|
||||
as_list_add_hook(NULL);
|
||||
as_list_delete_hook(NULL);
|
||||
bgp_filter_reset();
|
||||
|
||||
/* reverse prefix_list_init */
|
||||
prefix_list_add_hook (NULL);
|
||||
prefix_list_delete_hook (NULL);
|
||||
prefix_list_reset ();
|
||||
/* reverse prefix_list_init */
|
||||
prefix_list_add_hook(NULL);
|
||||
prefix_list_delete_hook(NULL);
|
||||
prefix_list_reset();
|
||||
|
||||
/* reverse community_list_init */
|
||||
community_list_terminate (bgp_clist);
|
||||
/* reverse community_list_init */
|
||||
community_list_terminate(bgp_clist);
|
||||
|
||||
bgp_vrf_terminate ();
|
||||
cmd_terminate ();
|
||||
vty_terminate ();
|
||||
bgp_vrf_terminate();
|
||||
cmd_terminate();
|
||||
vty_terminate();
|
||||
#if ENABLE_BGP_VNC
|
||||
vnc_zebra_destroy();
|
||||
vnc_zebra_destroy();
|
||||
#endif
|
||||
bgp_zebra_destroy();
|
||||
bgp_zebra_destroy();
|
||||
|
||||
/* reverse bgp_master_init */
|
||||
if (bm->master)
|
||||
thread_master_free (bm->master);
|
||||
/* reverse bgp_master_init */
|
||||
if (bm->master)
|
||||
thread_master_free(bm->master);
|
||||
|
||||
closezlog ();
|
||||
closezlog();
|
||||
|
||||
list_delete (bm->bgp);
|
||||
memset (bm, 0, sizeof (*bm));
|
||||
list_delete(bm->bgp);
|
||||
memset(bm, 0, sizeof(*bm));
|
||||
|
||||
if (bgp_debug_count())
|
||||
log_memstats_stderr ("bgpd");
|
||||
exit (status);
|
||||
if (bgp_debug_count())
|
||||
log_memstats_stderr("bgpd");
|
||||
exit(status);
|
||||
}
|
||||
|
||||
static int
|
||||
bgp_vrf_new (struct vrf *vrf)
|
||||
static int bgp_vrf_new(struct vrf *vrf)
|
||||
{
|
||||
if (BGP_DEBUG (zebra, ZEBRA))
|
||||
zlog_debug ("VRF Created: %s(%d)", vrf->name, vrf->vrf_id);
|
||||
if (BGP_DEBUG(zebra, ZEBRA))
|
||||
zlog_debug("VRF Created: %s(%d)", vrf->name, vrf->vrf_id);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bgp_vrf_delete (struct vrf *vrf)
|
||||
static int bgp_vrf_delete(struct vrf *vrf)
|
||||
{
|
||||
if (BGP_DEBUG (zebra, ZEBRA))
|
||||
zlog_debug ("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id);
|
||||
if (BGP_DEBUG(zebra, ZEBRA))
|
||||
zlog_debug("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bgp_vrf_enable (struct vrf *vrf)
|
||||
static int bgp_vrf_enable(struct vrf *vrf)
|
||||
{
|
||||
struct bgp *bgp;
|
||||
vrf_id_t old_vrf_id;
|
||||
struct bgp *bgp;
|
||||
vrf_id_t old_vrf_id;
|
||||
|
||||
if (BGP_DEBUG (zebra, ZEBRA))
|
||||
zlog_debug("VRF enable add %s id %d", vrf->name, vrf->vrf_id);
|
||||
if (BGP_DEBUG(zebra, ZEBRA))
|
||||
zlog_debug("VRF enable add %s id %d", vrf->name, vrf->vrf_id);
|
||||
|
||||
bgp = bgp_lookup_by_name (vrf->name);
|
||||
if (bgp)
|
||||
{
|
||||
old_vrf_id = bgp->vrf_id;
|
||||
/* We have instance configured, link to VRF and make it "up". */
|
||||
bgp_vrf_link (bgp, vrf);
|
||||
bgp = bgp_lookup_by_name(vrf->name);
|
||||
if (bgp) {
|
||||
old_vrf_id = bgp->vrf_id;
|
||||
/* We have instance configured, link to VRF and make it "up". */
|
||||
bgp_vrf_link(bgp, vrf);
|
||||
|
||||
/* Update any redistribute vrf bitmaps if the vrf_id changed */
|
||||
if (old_vrf_id != bgp->vrf_id)
|
||||
bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
|
||||
bgp_instance_up (bgp);
|
||||
}
|
||||
/* Update any redistribute vrf bitmaps if the vrf_id changed */
|
||||
if (old_vrf_id != bgp->vrf_id)
|
||||
bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
|
||||
bgp_instance_up(bgp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bgp_vrf_disable (struct vrf *vrf)
|
||||
static int bgp_vrf_disable(struct vrf *vrf)
|
||||
{
|
||||
struct bgp *bgp;
|
||||
vrf_id_t old_vrf_id;
|
||||
struct bgp *bgp;
|
||||
vrf_id_t old_vrf_id;
|
||||
|
||||
if (vrf->vrf_id == VRF_DEFAULT)
|
||||
return 0;
|
||||
if (vrf->vrf_id == VRF_DEFAULT)
|
||||
return 0;
|
||||
|
||||
if (BGP_DEBUG (zebra, ZEBRA))
|
||||
zlog_debug("VRF disable %s id %d", vrf->name, vrf->vrf_id);
|
||||
if (BGP_DEBUG(zebra, ZEBRA))
|
||||
zlog_debug("VRF disable %s id %d", vrf->name, vrf->vrf_id);
|
||||
|
||||
bgp = bgp_lookup_by_name (vrf->name);
|
||||
if (bgp)
|
||||
{
|
||||
old_vrf_id = bgp->vrf_id;
|
||||
/* We have instance configured, unlink from VRF and make it "down". */
|
||||
bgp_vrf_unlink (bgp, vrf);
|
||||
/* Update any redistribute vrf bitmaps if the vrf_id changed */
|
||||
if (old_vrf_id != bgp->vrf_id)
|
||||
bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
|
||||
bgp_instance_down (bgp);
|
||||
}
|
||||
bgp = bgp_lookup_by_name(vrf->name);
|
||||
if (bgp) {
|
||||
old_vrf_id = bgp->vrf_id;
|
||||
/* We have instance configured, unlink from VRF and make it
|
||||
* "down". */
|
||||
bgp_vrf_unlink(bgp, vrf);
|
||||
/* Update any redistribute vrf bitmaps if the vrf_id changed */
|
||||
if (old_vrf_id != bgp->vrf_id)
|
||||
bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
|
||||
bgp_instance_down(bgp);
|
||||
}
|
||||
|
||||
/* Note: This is a callback, the VRF will be deleted by the caller. */
|
||||
return 0;
|
||||
/* Note: This is a callback, the VRF will be deleted by the caller. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
bgp_vrf_init (void)
|
||||
static void bgp_vrf_init(void)
|
||||
{
|
||||
vrf_init (bgp_vrf_new,
|
||||
bgp_vrf_enable,
|
||||
bgp_vrf_disable,
|
||||
bgp_vrf_delete);
|
||||
vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable, bgp_vrf_delete);
|
||||
}
|
||||
|
||||
static void
|
||||
bgp_vrf_terminate (void)
|
||||
static void bgp_vrf_terminate(void)
|
||||
{
|
||||
vrf_terminate ();
|
||||
vrf_terminate();
|
||||
}
|
||||
|
||||
FRR_DAEMON_INFO(bgpd, BGP,
|
||||
.vty_port = BGP_VTY_PORT,
|
||||
FRR_DAEMON_INFO(bgpd, BGP, .vty_port = BGP_VTY_PORT,
|
||||
|
||||
.proghelp = "Implementation of the BGP routing protocol.",
|
||||
.proghelp = "Implementation of the BGP routing protocol.",
|
||||
|
||||
.signals = bgp_signals,
|
||||
.n_signals = array_size(bgp_signals),
|
||||
.signals = bgp_signals, .n_signals = array_size(bgp_signals),
|
||||
|
||||
.privs = &bgpd_privs,
|
||||
)
|
||||
.privs = &bgpd_privs, )
|
||||
|
||||
/* Main routine of bgpd. Treatment of argument and start bgp finite
|
||||
state machine is handled at here. */
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int opt;
|
||||
int tmp_port;
|
||||
int opt;
|
||||
int tmp_port;
|
||||
|
||||
int bgp_port = BGP_PORT_DEFAULT;
|
||||
char *bgp_address = NULL;
|
||||
int no_fib_flag = 0;
|
||||
int skip_runas = 0;
|
||||
int bgp_port = BGP_PORT_DEFAULT;
|
||||
char *bgp_address = NULL;
|
||||
int no_fib_flag = 0;
|
||||
int skip_runas = 0;
|
||||
|
||||
frr_preinit(&bgpd_di, argc, argv);
|
||||
frr_opt_add("p:l:rne:", longopts,
|
||||
" -p, --bgp_port Set bgp protocol's port number\n"
|
||||
" -l, --listenon Listen on specified address (implies -n)\n"
|
||||
" -r, --retain When program terminates, retain added route by bgpd.\n"
|
||||
" -n, --no_kernel Do not install route to kernel.\n"
|
||||
" -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n"
|
||||
" -e, --ecmp Specify ECMP to use.\n");
|
||||
frr_preinit(&bgpd_di, argc, argv);
|
||||
frr_opt_add(
|
||||
"p:l:rne:", longopts,
|
||||
" -p, --bgp_port Set bgp protocol's port number\n"
|
||||
" -l, --listenon Listen on specified address (implies -n)\n"
|
||||
" -r, --retain When program terminates, retain added route by bgpd.\n"
|
||||
" -n, --no_kernel Do not install route to kernel.\n"
|
||||
" -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n"
|
||||
" -e, --ecmp Specify ECMP to use.\n");
|
||||
|
||||
/* Command line argument treatment. */
|
||||
while (1)
|
||||
{
|
||||
opt = frr_getopt (argc, argv, 0);
|
||||
|
||||
if (opt == EOF)
|
||||
break;
|
||||
/* Command line argument treatment. */
|
||||
while (1) {
|
||||
opt = frr_getopt(argc, argv, 0);
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 'p':
|
||||
tmp_port = atoi (optarg);
|
||||
if (tmp_port <= 0 || tmp_port > 0xffff)
|
||||
bgp_port = BGP_PORT_DEFAULT;
|
||||
else
|
||||
bgp_port = tmp_port;
|
||||
break;
|
||||
case 'e':
|
||||
multipath_num = atoi (optarg);
|
||||
if (multipath_num > MULTIPATH_NUM || multipath_num <= 0)
|
||||
{
|
||||
zlog_err ("Multipath Number specified must be less than %d and greater than 0", MULTIPATH_NUM);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
retain_mode = 1;
|
||||
break;
|
||||
case 'l':
|
||||
bgp_address = optarg;
|
||||
/* listenon implies -n */
|
||||
/* fallthru */
|
||||
case 'n':
|
||||
no_fib_flag = 1;
|
||||
break;
|
||||
case 'S':
|
||||
skip_runas = 1;
|
||||
break;
|
||||
default:
|
||||
frr_help_exit (1);
|
||||
break;
|
||||
if (opt == EOF)
|
||||
break;
|
||||
|
||||
switch (opt) {
|
||||
case 0:
|
||||
break;
|
||||
case 'p':
|
||||
tmp_port = atoi(optarg);
|
||||
if (tmp_port <= 0 || tmp_port > 0xffff)
|
||||
bgp_port = BGP_PORT_DEFAULT;
|
||||
else
|
||||
bgp_port = tmp_port;
|
||||
break;
|
||||
case 'e':
|
||||
multipath_num = atoi(optarg);
|
||||
if (multipath_num > MULTIPATH_NUM
|
||||
|| multipath_num <= 0) {
|
||||
zlog_err(
|
||||
"Multipath Number specified must be less than %d and greater than 0",
|
||||
MULTIPATH_NUM);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
retain_mode = 1;
|
||||
break;
|
||||
case 'l':
|
||||
bgp_address = optarg;
|
||||
/* listenon implies -n */
|
||||
/* fallthru */
|
||||
case 'n':
|
||||
no_fib_flag = 1;
|
||||
break;
|
||||
case 'S':
|
||||
skip_runas = 1;
|
||||
break;
|
||||
default:
|
||||
frr_help_exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (skip_runas)
|
||||
memset (&bgpd_privs, 0, sizeof (bgpd_privs));
|
||||
if (skip_runas)
|
||||
memset(&bgpd_privs, 0, sizeof(bgpd_privs));
|
||||
|
||||
/* BGP master init. */
|
||||
bgp_master_init (frr_init ());
|
||||
bm->port = bgp_port;
|
||||
bm->address = bgp_address;
|
||||
if (no_fib_flag)
|
||||
bgp_option_set (BGP_OPT_NO_FIB);
|
||||
/* BGP master init. */
|
||||
bgp_master_init(frr_init());
|
||||
bm->port = bgp_port;
|
||||
bm->address = bgp_address;
|
||||
if (no_fib_flag)
|
||||
bgp_option_set(BGP_OPT_NO_FIB);
|
||||
|
||||
/* Initializations. */
|
||||
bgp_vrf_init ();
|
||||
/* Initializations. */
|
||||
bgp_vrf_init();
|
||||
|
||||
/* BGP related initialization. */
|
||||
bgp_init ();
|
||||
/* BGP related initialization. */
|
||||
bgp_init();
|
||||
|
||||
snprintf (bgpd_di.startinfo, sizeof (bgpd_di.startinfo), ", bgp@%s:%d",
|
||||
(bm->address ? bm->address : "<all>"),
|
||||
bm->port);
|
||||
snprintf(bgpd_di.startinfo, sizeof(bgpd_di.startinfo), ", bgp@%s:%d",
|
||||
(bm->address ? bm->address : "<all>"), bm->port);
|
||||
|
||||
frr_config_fork ();
|
||||
frr_run (bm->master);
|
||||
frr_config_fork();
|
||||
frr_run(bm->master);
|
||||
|
||||
/* Not reached. */
|
||||
return (0);
|
||||
/* Not reached. */
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -29,91 +29,91 @@
|
||||
* files they're used in */
|
||||
|
||||
DEFINE_MGROUP(BGPD, "bgpd")
|
||||
DEFINE_MTYPE(BGPD, BGP, "BGP instance")
|
||||
DEFINE_MTYPE(BGPD, BGP_LISTENER, "BGP listen socket details")
|
||||
DEFINE_MTYPE(BGPD, BGP_PEER, "BGP peer")
|
||||
DEFINE_MTYPE(BGPD, BGP_PEER_HOST, "BGP peer hostname")
|
||||
DEFINE_MTYPE(BGPD, BGP_PEER_IFNAME, "BGP peer ifname")
|
||||
DEFINE_MTYPE(BGPD, PEER_GROUP, "Peer group")
|
||||
DEFINE_MTYPE(BGPD, PEER_GROUP_HOST, "BGP Peer group hostname")
|
||||
DEFINE_MTYPE(BGPD, PEER_DESC, "Peer description")
|
||||
DEFINE_MTYPE(BGPD, PEER_PASSWORD, "Peer password string")
|
||||
DEFINE_MTYPE(BGPD, BGP_PEER_AF, "BGP peer af")
|
||||
DEFINE_MTYPE(BGPD, BGP_UPDGRP, "BGP update group")
|
||||
DEFINE_MTYPE(BGPD, BGP_UPD_SUBGRP, "BGP update subgroup")
|
||||
DEFINE_MTYPE(BGPD, BGP_PACKET, "BGP packet")
|
||||
DEFINE_MTYPE(BGPD, ATTR, "BGP attribute")
|
||||
DEFINE_MTYPE(BGPD, AS_PATH, "BGP aspath")
|
||||
DEFINE_MTYPE(BGPD, AS_SEG, "BGP aspath seg")
|
||||
DEFINE_MTYPE(BGPD, AS_SEG_DATA, "BGP aspath segment data")
|
||||
DEFINE_MTYPE(BGPD, AS_STR, "BGP aspath str")
|
||||
DEFINE_MTYPE(BGPD, BGP, "BGP instance")
|
||||
DEFINE_MTYPE(BGPD, BGP_LISTENER, "BGP listen socket details")
|
||||
DEFINE_MTYPE(BGPD, BGP_PEER, "BGP peer")
|
||||
DEFINE_MTYPE(BGPD, BGP_PEER_HOST, "BGP peer hostname")
|
||||
DEFINE_MTYPE(BGPD, BGP_PEER_IFNAME, "BGP peer ifname")
|
||||
DEFINE_MTYPE(BGPD, PEER_GROUP, "Peer group")
|
||||
DEFINE_MTYPE(BGPD, PEER_GROUP_HOST, "BGP Peer group hostname")
|
||||
DEFINE_MTYPE(BGPD, PEER_DESC, "Peer description")
|
||||
DEFINE_MTYPE(BGPD, PEER_PASSWORD, "Peer password string")
|
||||
DEFINE_MTYPE(BGPD, BGP_PEER_AF, "BGP peer af")
|
||||
DEFINE_MTYPE(BGPD, BGP_UPDGRP, "BGP update group")
|
||||
DEFINE_MTYPE(BGPD, BGP_UPD_SUBGRP, "BGP update subgroup")
|
||||
DEFINE_MTYPE(BGPD, BGP_PACKET, "BGP packet")
|
||||
DEFINE_MTYPE(BGPD, ATTR, "BGP attribute")
|
||||
DEFINE_MTYPE(BGPD, AS_PATH, "BGP aspath")
|
||||
DEFINE_MTYPE(BGPD, AS_SEG, "BGP aspath seg")
|
||||
DEFINE_MTYPE(BGPD, AS_SEG_DATA, "BGP aspath segment data")
|
||||
DEFINE_MTYPE(BGPD, AS_STR, "BGP aspath str")
|
||||
|
||||
DEFINE_MTYPE(BGPD, BGP_TABLE, "BGP table")
|
||||
DEFINE_MTYPE(BGPD, BGP_NODE, "BGP node")
|
||||
DEFINE_MTYPE(BGPD, BGP_ROUTE, "BGP route")
|
||||
DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA, "BGP ancillary route info")
|
||||
DEFINE_MTYPE(BGPD, BGP_CONN, "BGP connected")
|
||||
DEFINE_MTYPE(BGPD, BGP_STATIC, "BGP static")
|
||||
DEFINE_MTYPE(BGPD, BGP_ADVERTISE_ATTR, "BGP adv attr")
|
||||
DEFINE_MTYPE(BGPD, BGP_ADVERTISE, "BGP adv")
|
||||
DEFINE_MTYPE(BGPD, BGP_SYNCHRONISE, "BGP synchronise")
|
||||
DEFINE_MTYPE(BGPD, BGP_ADJ_IN, "BGP adj in")
|
||||
DEFINE_MTYPE(BGPD, BGP_ADJ_OUT, "BGP adj out")
|
||||
DEFINE_MTYPE(BGPD, BGP_MPATH_INFO, "BGP multipath info")
|
||||
DEFINE_MTYPE(BGPD, BGP_TABLE, "BGP table")
|
||||
DEFINE_MTYPE(BGPD, BGP_NODE, "BGP node")
|
||||
DEFINE_MTYPE(BGPD, BGP_ROUTE, "BGP route")
|
||||
DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA, "BGP ancillary route info")
|
||||
DEFINE_MTYPE(BGPD, BGP_CONN, "BGP connected")
|
||||
DEFINE_MTYPE(BGPD, BGP_STATIC, "BGP static")
|
||||
DEFINE_MTYPE(BGPD, BGP_ADVERTISE_ATTR, "BGP adv attr")
|
||||
DEFINE_MTYPE(BGPD, BGP_ADVERTISE, "BGP adv")
|
||||
DEFINE_MTYPE(BGPD, BGP_SYNCHRONISE, "BGP synchronise")
|
||||
DEFINE_MTYPE(BGPD, BGP_ADJ_IN, "BGP adj in")
|
||||
DEFINE_MTYPE(BGPD, BGP_ADJ_OUT, "BGP adj out")
|
||||
DEFINE_MTYPE(BGPD, BGP_MPATH_INFO, "BGP multipath info")
|
||||
|
||||
DEFINE_MTYPE(BGPD, AS_LIST, "BGP AS list")
|
||||
DEFINE_MTYPE(BGPD, AS_FILTER, "BGP AS filter")
|
||||
DEFINE_MTYPE(BGPD, AS_FILTER_STR, "BGP AS filter str")
|
||||
DEFINE_MTYPE(BGPD, AS_LIST, "BGP AS list")
|
||||
DEFINE_MTYPE(BGPD, AS_FILTER, "BGP AS filter")
|
||||
DEFINE_MTYPE(BGPD, AS_FILTER_STR, "BGP AS filter str")
|
||||
|
||||
DEFINE_MTYPE(BGPD, COMMUNITY, "community")
|
||||
DEFINE_MTYPE(BGPD, COMMUNITY_VAL, "community val")
|
||||
DEFINE_MTYPE(BGPD, COMMUNITY_STR, "community str")
|
||||
DEFINE_MTYPE(BGPD, COMMUNITY, "community")
|
||||
DEFINE_MTYPE(BGPD, COMMUNITY_VAL, "community val")
|
||||
DEFINE_MTYPE(BGPD, COMMUNITY_STR, "community str")
|
||||
|
||||
DEFINE_MTYPE(BGPD, ECOMMUNITY, "extcommunity")
|
||||
DEFINE_MTYPE(BGPD, ECOMMUNITY_VAL, "extcommunity val")
|
||||
DEFINE_MTYPE(BGPD, ECOMMUNITY_STR, "extcommunity str")
|
||||
DEFINE_MTYPE(BGPD, ECOMMUNITY, "extcommunity")
|
||||
DEFINE_MTYPE(BGPD, ECOMMUNITY_VAL, "extcommunity val")
|
||||
DEFINE_MTYPE(BGPD, ECOMMUNITY_STR, "extcommunity str")
|
||||
|
||||
DEFINE_MTYPE(BGPD, COMMUNITY_LIST, "community-list")
|
||||
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_NAME, "community-list name")
|
||||
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_ENTRY, "community-list entry")
|
||||
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_CONFIG, "community-list config")
|
||||
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_HANDLER, "community-list handler")
|
||||
DEFINE_MTYPE(BGPD, COMMUNITY_LIST, "community-list")
|
||||
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_NAME, "community-list name")
|
||||
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_ENTRY, "community-list entry")
|
||||
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_CONFIG, "community-list config")
|
||||
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_HANDLER, "community-list handler")
|
||||
|
||||
DEFINE_MTYPE(BGPD, CLUSTER, "Cluster list")
|
||||
DEFINE_MTYPE(BGPD, CLUSTER_VAL, "Cluster list val")
|
||||
DEFINE_MTYPE(BGPD, CLUSTER, "Cluster list")
|
||||
DEFINE_MTYPE(BGPD, CLUSTER_VAL, "Cluster list val")
|
||||
|
||||
DEFINE_MTYPE(BGPD, BGP_PROCESS_QUEUE, "BGP Process queue")
|
||||
DEFINE_MTYPE(BGPD, BGP_CLEAR_NODE_QUEUE, "BGP node clear queue")
|
||||
DEFINE_MTYPE(BGPD, BGP_PROCESS_QUEUE, "BGP Process queue")
|
||||
DEFINE_MTYPE(BGPD, BGP_CLEAR_NODE_QUEUE, "BGP node clear queue")
|
||||
|
||||
DEFINE_MTYPE(BGPD, TRANSIT, "BGP transit attr")
|
||||
DEFINE_MTYPE(BGPD, TRANSIT_VAL, "BGP transit val")
|
||||
DEFINE_MTYPE(BGPD, TRANSIT, "BGP transit attr")
|
||||
DEFINE_MTYPE(BGPD, TRANSIT_VAL, "BGP transit val")
|
||||
|
||||
DEFINE_MTYPE(BGPD, BGP_DEBUG_FILTER, "BGP debug filter")
|
||||
DEFINE_MTYPE(BGPD, BGP_DEBUG_STR, "BGP debug filter string")
|
||||
DEFINE_MTYPE(BGPD, BGP_DEBUG_FILTER, "BGP debug filter")
|
||||
DEFINE_MTYPE(BGPD, BGP_DEBUG_STR, "BGP debug filter string")
|
||||
|
||||
DEFINE_MTYPE(BGPD, BGP_DISTANCE, "BGP distance")
|
||||
DEFINE_MTYPE(BGPD, BGP_NEXTHOP_CACHE, "BGP nexthop")
|
||||
DEFINE_MTYPE(BGPD, BGP_CONFED_LIST, "BGP confed list")
|
||||
DEFINE_MTYPE(BGPD, PEER_UPDATE_SOURCE, "BGP peer update interface")
|
||||
DEFINE_MTYPE(BGPD, PEER_CONF_IF, "BGP peer config interface")
|
||||
DEFINE_MTYPE(BGPD, BGP_DAMP_INFO, "Dampening info")
|
||||
DEFINE_MTYPE(BGPD, BGP_DAMP_ARRAY, "BGP Dampening array")
|
||||
DEFINE_MTYPE(BGPD, BGP_REGEXP, "BGP regexp")
|
||||
DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate")
|
||||
DEFINE_MTYPE(BGPD, BGP_ADDR, "BGP own address")
|
||||
DEFINE_MTYPE(BGPD, BGP_DISTANCE, "BGP distance")
|
||||
DEFINE_MTYPE(BGPD, BGP_NEXTHOP_CACHE, "BGP nexthop")
|
||||
DEFINE_MTYPE(BGPD, BGP_CONFED_LIST, "BGP confed list")
|
||||
DEFINE_MTYPE(BGPD, PEER_UPDATE_SOURCE, "BGP peer update interface")
|
||||
DEFINE_MTYPE(BGPD, PEER_CONF_IF, "BGP peer config interface")
|
||||
DEFINE_MTYPE(BGPD, BGP_DAMP_INFO, "Dampening info")
|
||||
DEFINE_MTYPE(BGPD, BGP_DAMP_ARRAY, "BGP Dampening array")
|
||||
DEFINE_MTYPE(BGPD, BGP_REGEXP, "BGP regexp")
|
||||
DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate")
|
||||
DEFINE_MTYPE(BGPD, BGP_ADDR, "BGP own address")
|
||||
|
||||
DEFINE_MTYPE(BGPD, BGP_REDIST, "BGP redistribution")
|
||||
DEFINE_MTYPE(BGPD, BGP_FILTER_NAME, "BGP Filter Information")
|
||||
DEFINE_MTYPE(BGPD, BGP_DUMP_STR, "BGP Dump String Information")
|
||||
DEFINE_MTYPE(BGPD, ENCAP_TLV, "ENCAP TLV")
|
||||
DEFINE_MTYPE(BGPD, BGP_REDIST, "BGP redistribution")
|
||||
DEFINE_MTYPE(BGPD, BGP_FILTER_NAME, "BGP Filter Information")
|
||||
DEFINE_MTYPE(BGPD, BGP_DUMP_STR, "BGP Dump String Information")
|
||||
DEFINE_MTYPE(BGPD, ENCAP_TLV, "ENCAP TLV")
|
||||
|
||||
DEFINE_MTYPE(BGPD, BGP_TEA_OPTIONS, "BGP TEA Options")
|
||||
DEFINE_MTYPE(BGPD, BGP_TEA_OPTIONS, "BGP TEA Options")
|
||||
DEFINE_MTYPE(BGPD, BGP_TEA_OPTIONS_VALUE, "BGP TEA Options Value")
|
||||
|
||||
DEFINE_MTYPE(BGPD, LCOMMUNITY, "Large Community")
|
||||
DEFINE_MTYPE(BGPD, LCOMMUNITY_STR, "Large Community display string")
|
||||
DEFINE_MTYPE(BGPD, LCOMMUNITY_VAL, "Large Community value")
|
||||
|
||||
DEFINE_MTYPE(BGPD, BGP_EVPN, "BGP EVPN Information")
|
||||
DEFINE_MTYPE(BGPD, BGP_EVPN_IMPORT_RT, "BGP EVPN Import RT")
|
||||
DEFINE_MTYPE(BGPD, BGP_EVPN_MACIP, "BGP EVPN MAC IP")
|
||||
DEFINE_MTYPE(BGPD, BGP_EVPN, "BGP EVPN Information")
|
||||
DEFINE_MTYPE(BGPD, BGP_EVPN_IMPORT_RT, "BGP EVPN Import RT")
|
||||
DEFINE_MTYPE(BGPD, BGP_EVPN_MACIP, "BGP EVPN MAC IP")
|
||||
|
||||
986
bgpd/bgp_mpath.c
986
bgpd/bgp_mpath.c
File diff suppressed because it is too large
Load Diff
@ -25,53 +25,52 @@
|
||||
/* Supplemental information linked to bgp_info for keeping track of
|
||||
* multipath selections, lazily allocated to save memory
|
||||
*/
|
||||
struct bgp_info_mpath
|
||||
{
|
||||
/* Points to the first multipath (on bestpath) or the next multipath */
|
||||
struct bgp_info_mpath *mp_next;
|
||||
struct bgp_info_mpath {
|
||||
/* Points to the first multipath (on bestpath) or the next multipath */
|
||||
struct bgp_info_mpath *mp_next;
|
||||
|
||||
/* Points to the previous multipath or NULL on bestpath */
|
||||
struct bgp_info_mpath *mp_prev;
|
||||
/* Points to the previous multipath or NULL on bestpath */
|
||||
struct bgp_info_mpath *mp_prev;
|
||||
|
||||
/* Points to bgp_info associated with this multipath info */
|
||||
struct bgp_info *mp_info;
|
||||
/* Points to bgp_info associated with this multipath info */
|
||||
struct bgp_info *mp_info;
|
||||
|
||||
/* When attached to best path, the number of selected multipaths */
|
||||
u_int32_t mp_count;
|
||||
/* When attached to best path, the number of selected multipaths */
|
||||
u_int32_t mp_count;
|
||||
|
||||
/* Aggregated attribute for advertising multipath route */
|
||||
struct attr *mp_attr;
|
||||
/* Aggregated attribute for advertising multipath route */
|
||||
struct attr *mp_attr;
|
||||
};
|
||||
|
||||
/* Functions to support maximum-paths configuration */
|
||||
extern int bgp_maximum_paths_set (struct bgp *, afi_t, safi_t, int, u_int16_t,
|
||||
u_int16_t);
|
||||
extern int bgp_maximum_paths_unset (struct bgp *, afi_t, safi_t, int);
|
||||
extern int bgp_maximum_paths_set(struct bgp *, afi_t, safi_t, int, u_int16_t,
|
||||
u_int16_t);
|
||||
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 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 int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2);
|
||||
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 *);
|
||||
|
||||
/* 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 **);
|
||||
extern void bgp_info_mpath_dequeue(struct bgp_info *);
|
||||
extern void bgp_info_mpath_free(struct bgp_info_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_info *bgp_info_mpath_first(struct bgp_info *);
|
||||
extern struct bgp_info *bgp_info_mpath_next(struct bgp_info *);
|
||||
|
||||
/* Accessors for multipath information */
|
||||
extern u_int32_t bgp_info_mpath_count (struct bgp_info *);
|
||||
extern struct attr *bgp_info_mpath_attr (struct bgp_info *);
|
||||
extern u_int32_t bgp_info_mpath_count(struct bgp_info *);
|
||||
extern struct attr *bgp_info_mpath_attr(struct bgp_info *);
|
||||
|
||||
#endif /* _QUAGGA_BGP_MPATH_H */
|
||||
|
||||
1399
bgpd/bgp_mplsvpn.c
1399
bgpd/bgp_mplsvpn.c
File diff suppressed because it is too large
Load Diff
@ -25,55 +25,54 @@
|
||||
#include "bgpd/bgp_rd.h"
|
||||
|
||||
#ifdef MPLS_LABEL_MAX
|
||||
# undef MPLS_LABEL_MAX
|
||||
#undef MPLS_LABEL_MAX
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
MPLS_LABEL_IPV4_EXPLICIT_NULL = 0, /* [RFC3032] */
|
||||
MPLS_LABEL_ROUTER_ALERT = 1, /* [RFC3032] */
|
||||
MPLS_LABEL_IPV6_EXPLICIT_NULL = 2, /* [RFC3032] */
|
||||
MPLS_LABEL_IMPLICIT_NULL = 3, /* [RFC3032] */
|
||||
MPLS_LABEL_UNASSIGNED4 = 4,
|
||||
MPLS_LABEL_UNASSIGNED5 = 5,
|
||||
MPLS_LABEL_UNASSIGNED6 = 6,
|
||||
MPLS_LABEL_ELI = 7, /* Entropy Indicator [RFC6790] */
|
||||
MPLS_LABEL_UNASSIGNED8 = 8,
|
||||
MPLS_LABEL_UNASSIGNED9 = 9,
|
||||
MPLS_LABEL_UNASSIGNED10 = 10,
|
||||
MPLS_LABEL_UNASSIGNED11 = 11,
|
||||
MPLS_LABEL_GAL = 13, /* [RFC5586] */
|
||||
MPLS_LABEL_OAM_ALERT = 14, /* [RFC3429] */
|
||||
MPLS_LABEL_EXTENSION = 15, /* [RFC7274] */
|
||||
MPLS_LABEL_MAX = 1048575,
|
||||
MPLS_LABEL_ILLEGAL = 0xFFFFFFFF /* for internal use only */
|
||||
MPLS_LABEL_IPV4_EXPLICIT_NULL = 0, /* [RFC3032] */
|
||||
MPLS_LABEL_ROUTER_ALERT = 1, /* [RFC3032] */
|
||||
MPLS_LABEL_IPV6_EXPLICIT_NULL = 2, /* [RFC3032] */
|
||||
MPLS_LABEL_IMPLICIT_NULL = 3, /* [RFC3032] */
|
||||
MPLS_LABEL_UNASSIGNED4 = 4,
|
||||
MPLS_LABEL_UNASSIGNED5 = 5,
|
||||
MPLS_LABEL_UNASSIGNED6 = 6,
|
||||
MPLS_LABEL_ELI = 7, /* Entropy Indicator [RFC6790] */
|
||||
MPLS_LABEL_UNASSIGNED8 = 8,
|
||||
MPLS_LABEL_UNASSIGNED9 = 9,
|
||||
MPLS_LABEL_UNASSIGNED10 = 10,
|
||||
MPLS_LABEL_UNASSIGNED11 = 11,
|
||||
MPLS_LABEL_GAL = 13, /* [RFC5586] */
|
||||
MPLS_LABEL_OAM_ALERT = 14, /* [RFC3429] */
|
||||
MPLS_LABEL_EXTENSION = 15, /* [RFC7274] */
|
||||
MPLS_LABEL_MAX = 1048575,
|
||||
MPLS_LABEL_ILLEGAL = 0xFFFFFFFF /* for internal use only */
|
||||
} mpls_special_label_t;
|
||||
|
||||
#define MPLS_LABEL_IS_SPECIAL(label) \
|
||||
((label) <= MPLS_LABEL_EXTENSION)
|
||||
#define MPLS_LABEL_IS_NULL(label) \
|
||||
((label) == MPLS_LABEL_IPV4_EXPLICIT_NULL || \
|
||||
(label) == MPLS_LABEL_IPV6_EXPLICIT_NULL || \
|
||||
(label) == MPLS_LABEL_IMPLICIT_NULL)
|
||||
#define MPLS_LABEL_IS_SPECIAL(label) ((label) <= MPLS_LABEL_EXTENSION)
|
||||
#define MPLS_LABEL_IS_NULL(label) \
|
||||
((label) == MPLS_LABEL_IPV4_EXPLICIT_NULL \
|
||||
|| (label) == MPLS_LABEL_IPV6_EXPLICIT_NULL \
|
||||
|| (label) == MPLS_LABEL_IMPLICIT_NULL)
|
||||
|
||||
#define BGP_VPNVX_HELP_STR \
|
||||
"Address Family\n" \
|
||||
"Address Family\n"
|
||||
#define BGP_VPNVX_HELP_STR \
|
||||
"Address Family\n" \
|
||||
"Address Family\n"
|
||||
|
||||
#define V4_HEADER \
|
||||
" Network Next Hop Metric LocPrf Weight Path\n"
|
||||
#define V4_HEADER_TAG \
|
||||
" Network Next Hop In tag/Out tag\n"
|
||||
#define V4_HEADER_OVERLAY \
|
||||
" Network Next Hop EthTag Overlay Index RouterMac\n"
|
||||
#define V4_HEADER \
|
||||
" Network Next Hop Metric LocPrf Weight Path\n"
|
||||
#define V4_HEADER_TAG " Network Next Hop In tag/Out tag\n"
|
||||
#define V4_HEADER_OVERLAY \
|
||||
" Network Next Hop EthTag Overlay Index RouterMac\n"
|
||||
|
||||
extern void bgp_mplsvpn_init (void);
|
||||
extern int bgp_nlri_parse_vpn (struct peer *, struct attr *, struct bgp_nlri *);
|
||||
extern u_int32_t decode_label (mpls_label_t *);
|
||||
extern void bgp_mplsvpn_init(void);
|
||||
extern int bgp_nlri_parse_vpn(struct peer *, struct attr *, struct bgp_nlri *);
|
||||
extern u_int32_t decode_label(mpls_label_t *);
|
||||
extern void encode_label(mpls_label_t, mpls_label_t *);
|
||||
|
||||
extern int
|
||||
argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc, int *index, afi_t *afi);
|
||||
extern int bgp_show_mpls_vpn (struct vty *vty, afi_t afi, struct prefix_rd *prd,
|
||||
enum bgp_show_type type, void *output_arg, int tags, u_char use_json);
|
||||
extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc,
|
||||
int *index, afi_t *afi);
|
||||
extern int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd,
|
||||
enum bgp_show_type type, void *output_arg,
|
||||
int tags, u_char use_json);
|
||||
|
||||
#endif /* _QUAGGA_BGP_MPLSVPN_H */
|
||||
|
||||
1148
bgpd/bgp_network.c
1148
bgpd/bgp_network.c
File diff suppressed because it is too large
Load Diff
@ -23,13 +23,13 @@
|
||||
|
||||
#define BGP_SOCKET_SNDBUF_SIZE 65536
|
||||
|
||||
extern int bgp_socket (unsigned short, const char *);
|
||||
extern void bgp_close (void);
|
||||
extern int bgp_connect (struct peer *);
|
||||
extern int bgp_getsockname (struct peer *);
|
||||
extern int bgp_socket(unsigned short, const char *);
|
||||
extern void bgp_close(void);
|
||||
extern int bgp_connect(struct peer *);
|
||||
extern int bgp_getsockname(struct peer *);
|
||||
|
||||
extern int bgp_md5_set (struct peer *);
|
||||
extern int bgp_md5_unset (struct peer *);
|
||||
extern int bgp_md5_set(struct peer *);
|
||||
extern int bgp_md5_unset(struct peer *);
|
||||
extern int bgp_set_socket_ttl(struct peer *, int fd);
|
||||
|
||||
#endif /* _QUAGGA_BGP_NETWORK_H */
|
||||
|
||||
@ -45,443 +45,445 @@
|
||||
#include "bgpd/bgp_fsm.h"
|
||||
#include "bgpd/bgp_vty.h"
|
||||
#include "zebra/rib.h"
|
||||
#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
|
||||
#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
|
||||
|
||||
char *
|
||||
bnc_str (struct bgp_nexthop_cache *bnc, char *buf, int size)
|
||||
char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size)
|
||||
{
|
||||
prefix2str(&(bnc->node->p), buf, size);
|
||||
return buf;
|
||||
prefix2str(&(bnc->node->p), buf, size);
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
bnc_nexthop_free (struct bgp_nexthop_cache *bnc)
|
||||
void bnc_nexthop_free(struct bgp_nexthop_cache *bnc)
|
||||
{
|
||||
nexthops_free(bnc->nexthop);
|
||||
nexthops_free(bnc->nexthop);
|
||||
}
|
||||
|
||||
struct bgp_nexthop_cache *
|
||||
bnc_new (void)
|
||||
struct bgp_nexthop_cache *bnc_new(void)
|
||||
{
|
||||
struct bgp_nexthop_cache *bnc;
|
||||
struct bgp_nexthop_cache *bnc;
|
||||
|
||||
bnc = XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache));
|
||||
LIST_INIT(&(bnc->paths));
|
||||
return bnc;
|
||||
bnc = XCALLOC(MTYPE_BGP_NEXTHOP_CACHE,
|
||||
sizeof(struct bgp_nexthop_cache));
|
||||
LIST_INIT(&(bnc->paths));
|
||||
return bnc;
|
||||
}
|
||||
|
||||
void
|
||||
bnc_free (struct bgp_nexthop_cache *bnc)
|
||||
void bnc_free(struct bgp_nexthop_cache *bnc)
|
||||
{
|
||||
bnc_nexthop_free (bnc);
|
||||
XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);
|
||||
bnc_nexthop_free(bnc);
|
||||
XFREE(MTYPE_BGP_NEXTHOP_CACHE, bnc);
|
||||
}
|
||||
|
||||
/* Reset and free all BGP nexthop cache. */
|
||||
static void
|
||||
bgp_nexthop_cache_reset (struct bgp_table *table)
|
||||
static void bgp_nexthop_cache_reset(struct bgp_table *table)
|
||||
{
|
||||
struct bgp_node *rn;
|
||||
struct bgp_nexthop_cache *bnc;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_nexthop_cache *bnc;
|
||||
|
||||
for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
|
||||
if ((bnc = rn->info) != NULL)
|
||||
{
|
||||
bnc_free (bnc);
|
||||
rn->info = NULL;
|
||||
bgp_unlock_node (rn);
|
||||
}
|
||||
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
|
||||
if ((bnc = rn->info) != NULL) {
|
||||
bnc_free(bnc);
|
||||
rn->info = NULL;
|
||||
bgp_unlock_node(rn);
|
||||
}
|
||||
}
|
||||
|
||||
/* BGP own address structure */
|
||||
struct bgp_addr
|
||||
{
|
||||
struct in_addr addr;
|
||||
int refcnt;
|
||||
struct bgp_addr {
|
||||
struct in_addr addr;
|
||||
int refcnt;
|
||||
};
|
||||
|
||||
static void *
|
||||
bgp_address_hash_alloc (void *p)
|
||||
static void *bgp_address_hash_alloc(void *p)
|
||||
{
|
||||
const struct in_addr *val = (const struct in_addr *)p;
|
||||
struct bgp_addr *addr;
|
||||
const struct in_addr *val = (const struct in_addr *)p;
|
||||
struct bgp_addr *addr;
|
||||
|
||||
addr = XMALLOC (MTYPE_BGP_ADDR, sizeof (struct bgp_addr));
|
||||
addr->refcnt = 0;
|
||||
addr->addr.s_addr = val->s_addr;
|
||||
addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addr));
|
||||
addr->refcnt = 0;
|
||||
addr->addr.s_addr = val->s_addr;
|
||||
|
||||
return addr;
|
||||
return addr;
|
||||
}
|
||||
|
||||
static void
|
||||
bgp_address_hash_free (void *addr)
|
||||
static void bgp_address_hash_free(void *addr)
|
||||
{
|
||||
XFREE (MTYPE_BGP_ADDR, addr);
|
||||
XFREE(MTYPE_BGP_ADDR, addr);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
bgp_address_hash_key_make (void *p)
|
||||
static unsigned int bgp_address_hash_key_make(void *p)
|
||||
{
|
||||
const struct bgp_addr *addr = p;
|
||||
const struct bgp_addr *addr = p;
|
||||
|
||||
return jhash_1word(addr->addr.s_addr, 0);
|
||||
return jhash_1word(addr->addr.s_addr, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
bgp_address_hash_cmp (const void *p1, const void *p2)
|
||||
static int bgp_address_hash_cmp(const void *p1, const void *p2)
|
||||
{
|
||||
const struct bgp_addr *addr1 = p1;
|
||||
const struct bgp_addr *addr2 = p2;
|
||||
const struct bgp_addr *addr1 = p1;
|
||||
const struct bgp_addr *addr2 = p2;
|
||||
|
||||
return addr1->addr.s_addr == addr2->addr.s_addr;
|
||||
return addr1->addr.s_addr == addr2->addr.s_addr;
|
||||
}
|
||||
|
||||
void
|
||||
bgp_address_init (struct bgp *bgp)
|
||||
void bgp_address_init(struct bgp *bgp)
|
||||
{
|
||||
bgp->address_hash = hash_create (bgp_address_hash_key_make,
|
||||
bgp_address_hash_cmp, NULL);
|
||||
bgp->address_hash = hash_create(bgp_address_hash_key_make,
|
||||
bgp_address_hash_cmp, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
bgp_address_destroy (struct bgp *bgp)
|
||||
void bgp_address_destroy(struct bgp *bgp)
|
||||
{
|
||||
if (bgp->address_hash == NULL)
|
||||
return;
|
||||
hash_clean(bgp->address_hash, bgp_address_hash_free);
|
||||
hash_free(bgp->address_hash);
|
||||
bgp->address_hash = NULL;
|
||||
if (bgp->address_hash == NULL)
|
||||
return;
|
||||
hash_clean(bgp->address_hash, bgp_address_hash_free);
|
||||
hash_free(bgp->address_hash);
|
||||
bgp->address_hash = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bgp_address_add (struct bgp *bgp, struct prefix *p)
|
||||
static void bgp_address_add(struct bgp *bgp, struct prefix *p)
|
||||
{
|
||||
struct bgp_addr tmp;
|
||||
struct bgp_addr *addr;
|
||||
struct bgp_addr tmp;
|
||||
struct bgp_addr *addr;
|
||||
|
||||
tmp.addr = p->u.prefix4;
|
||||
tmp.addr = p->u.prefix4;
|
||||
|
||||
addr = hash_get (bgp->address_hash, &tmp, bgp_address_hash_alloc);
|
||||
if (!addr)
|
||||
return;
|
||||
addr = hash_get(bgp->address_hash, &tmp, bgp_address_hash_alloc);
|
||||
if (!addr)
|
||||
return;
|
||||
|
||||
addr->refcnt++;
|
||||
addr->refcnt++;
|
||||
}
|
||||
|
||||
static void
|
||||
bgp_address_del (struct bgp *bgp, struct prefix *p)
|
||||
static void bgp_address_del(struct bgp *bgp, struct prefix *p)
|
||||
{
|
||||
struct bgp_addr tmp;
|
||||
struct bgp_addr *addr;
|
||||
struct bgp_addr tmp;
|
||||
struct bgp_addr *addr;
|
||||
|
||||
tmp.addr = p->u.prefix4;
|
||||
tmp.addr = p->u.prefix4;
|
||||
|
||||
addr = hash_lookup (bgp->address_hash, &tmp);
|
||||
/* may have been deleted earlier by bgp_interface_down() */
|
||||
if (addr == NULL)
|
||||
return;
|
||||
addr = hash_lookup(bgp->address_hash, &tmp);
|
||||
/* may have been deleted earlier by bgp_interface_down() */
|
||||
if (addr == NULL)
|
||||
return;
|
||||
|
||||
addr->refcnt--;
|
||||
addr->refcnt--;
|
||||
|
||||
if (addr->refcnt == 0)
|
||||
{
|
||||
hash_release (bgp->address_hash, addr);
|
||||
XFREE (MTYPE_BGP_ADDR, addr);
|
||||
}
|
||||
if (addr->refcnt == 0) {
|
||||
hash_release(bgp->address_hash, addr);
|
||||
XFREE(MTYPE_BGP_ADDR, addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct bgp_connected_ref
|
||||
{
|
||||
unsigned int refcnt;
|
||||
struct bgp_connected_ref {
|
||||
unsigned int refcnt;
|
||||
};
|
||||
|
||||
void
|
||||
bgp_connected_add (struct bgp *bgp, struct connected *ifc)
|
||||
void bgp_connected_add(struct bgp *bgp, struct connected *ifc)
|
||||
{
|
||||
struct prefix p;
|
||||
struct prefix *addr;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_connected_ref *bc;
|
||||
struct listnode *node, *nnode;
|
||||
struct peer *peer;
|
||||
struct prefix p;
|
||||
struct prefix *addr;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_connected_ref *bc;
|
||||
struct listnode *node, *nnode;
|
||||
struct peer *peer;
|
||||
|
||||
addr = ifc->address;
|
||||
addr = ifc->address;
|
||||
|
||||
p = *(CONNECTED_PREFIX(ifc));
|
||||
if (addr->family == AF_INET)
|
||||
{
|
||||
apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
|
||||
p = *(CONNECTED_PREFIX(ifc));
|
||||
if (addr->family == AF_INET) {
|
||||
apply_mask_ipv4((struct prefix_ipv4 *)&p);
|
||||
|
||||
if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
|
||||
return;
|
||||
if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
|
||||
return;
|
||||
|
||||
bgp_address_add (bgp, addr);
|
||||
bgp_address_add(bgp, addr);
|
||||
|
||||
rn = bgp_node_get (bgp->connected_table[AFI_IP], (struct prefix *) &p);
|
||||
if (rn->info)
|
||||
{
|
||||
bc = rn->info;
|
||||
bc->refcnt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
|
||||
bc->refcnt = 1;
|
||||
rn->info = bc;
|
||||
}
|
||||
rn = bgp_node_get(bgp->connected_table[AFI_IP],
|
||||
(struct prefix *)&p);
|
||||
if (rn->info) {
|
||||
bc = rn->info;
|
||||
bc->refcnt++;
|
||||
} else {
|
||||
bc = XCALLOC(MTYPE_BGP_CONN,
|
||||
sizeof(struct bgp_connected_ref));
|
||||
bc->refcnt = 1;
|
||||
rn->info = bc;
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
|
||||
{
|
||||
if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0) &&
|
||||
peer->status != Established &&
|
||||
!CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
|
||||
{
|
||||
if (peer_active(peer))
|
||||
BGP_EVENT_ADD (peer, BGP_Stop);
|
||||
BGP_EVENT_ADD (peer, BGP_Start);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (addr->family == AF_INET6)
|
||||
{
|
||||
apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
|
||||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
|
||||
return;
|
||||
|
||||
if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
|
||||
return;
|
||||
|
||||
rn = bgp_node_get (bgp->connected_table[AFI_IP6], (struct prefix *) &p);
|
||||
if (rn->info)
|
||||
{
|
||||
bc = rn->info;
|
||||
bc->refcnt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
|
||||
bc->refcnt = 1;
|
||||
rn->info = bc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bgp_connected_delete (struct bgp *bgp, struct connected *ifc)
|
||||
{
|
||||
struct prefix p;
|
||||
struct prefix *addr;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_connected_ref *bc;
|
||||
|
||||
addr = ifc->address;
|
||||
|
||||
p = *(CONNECTED_PREFIX(ifc));
|
||||
if (addr->family == AF_INET)
|
||||
{
|
||||
apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
|
||||
|
||||
if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
|
||||
return;
|
||||
|
||||
bgp_address_del (bgp, addr);
|
||||
|
||||
rn = bgp_node_lookup (bgp->connected_table[AFI_IP], &p);
|
||||
if (! rn)
|
||||
return;
|
||||
|
||||
bc = rn->info;
|
||||
bc->refcnt--;
|
||||
if (bc->refcnt == 0)
|
||||
{
|
||||
XFREE (MTYPE_BGP_CONN, bc);
|
||||
rn->info = NULL;
|
||||
}
|
||||
bgp_unlock_node (rn);
|
||||
bgp_unlock_node (rn);
|
||||
}
|
||||
else if (addr->family == AF_INET6)
|
||||
{
|
||||
apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
|
||||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
|
||||
return;
|
||||
|
||||
if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
|
||||
return;
|
||||
|
||||
rn = bgp_node_lookup (bgp->connected_table[AFI_IP6], (struct prefix *) &p);
|
||||
if (! rn)
|
||||
return;
|
||||
|
||||
bc = rn->info;
|
||||
bc->refcnt--;
|
||||
if (bc->refcnt == 0)
|
||||
{
|
||||
XFREE (MTYPE_BGP_CONN, bc);
|
||||
rn->info = NULL;
|
||||
}
|
||||
bgp_unlock_node (rn);
|
||||
bgp_unlock_node (rn);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
bgp_nexthop_self (struct bgp *bgp, struct in_addr nh_addr)
|
||||
{
|
||||
struct bgp_addr tmp, *addr;
|
||||
|
||||
tmp.addr = nh_addr;
|
||||
|
||||
addr = hash_lookup (bgp->address_hash, &tmp);
|
||||
if (addr)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer)
|
||||
{
|
||||
struct bgp_node *rn1;
|
||||
struct bgp_node *rn2;
|
||||
struct prefix p;
|
||||
int ret;
|
||||
|
||||
p.family = AF_INET;
|
||||
p.prefixlen = IPV4_MAX_BITLEN;
|
||||
p.u.prefix4 = nexthop;
|
||||
|
||||
rn1 = bgp_node_match (peer->bgp->connected_table[AFI_IP], &p);
|
||||
if (!rn1)
|
||||
return 0;
|
||||
|
||||
p.family = AF_INET;
|
||||
p.prefixlen = IPV4_MAX_BITLEN;
|
||||
p.u.prefix4 = peer->su.sin.sin_addr;
|
||||
|
||||
rn2 = bgp_node_match (peer->bgp->connected_table[AFI_IP], &p);
|
||||
if (!rn2)
|
||||
{
|
||||
bgp_unlock_node(rn1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = (rn1 == rn2) ? 1 : 0;
|
||||
|
||||
bgp_unlock_node(rn1);
|
||||
bgp_unlock_node(rn2);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
bgp_show_nexthops (struct vty *vty, struct bgp *bgp, int detail)
|
||||
{
|
||||
struct bgp_node *rn;
|
||||
struct bgp_nexthop_cache *bnc;
|
||||
char buf[PREFIX2STR_BUFFER];
|
||||
struct nexthop *nexthop;
|
||||
time_t tbuf;
|
||||
afi_t afi;
|
||||
|
||||
vty_out (vty, "Current BGP nexthop cache:\n");
|
||||
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
|
||||
{
|
||||
if (!bgp->nexthop_cache_table[afi])
|
||||
continue;
|
||||
|
||||
for (rn = bgp_table_top (bgp->nexthop_cache_table[afi]); rn; rn = bgp_route_next (rn))
|
||||
{
|
||||
if ((bnc = rn->info) != NULL)
|
||||
{
|
||||
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
|
||||
{
|
||||
vty_out (vty, " %s valid [IGP metric %d], #paths %d\n",
|
||||
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf)),
|
||||
bnc->metric, bnc->path_count);
|
||||
if (detail)
|
||||
for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
|
||||
switch (nexthop->type)
|
||||
{
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
vty_out (vty, " gate %s\n",
|
||||
inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, sizeof(buf)));
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
||||
vty_out (vty, " gate %s, if %s\n",
|
||||
inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
|
||||
sizeof (buf)),
|
||||
ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
vty_out (vty, " gate %s\n",
|
||||
inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, sizeof(buf)));
|
||||
break;
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
vty_out (vty, " if %s\n",
|
||||
ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||
vty_out (vty, " gate %s, if %s\n",
|
||||
inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
|
||||
sizeof (buf)),
|
||||
ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
|
||||
break;
|
||||
default:
|
||||
vty_out (vty, " invalid nexthop type %u\n",
|
||||
nexthop->type);
|
||||
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
|
||||
if (peer->conf_if
|
||||
&& (strcmp(peer->conf_if, ifc->ifp->name) == 0)
|
||||
&& peer->status != Established
|
||||
&& !CHECK_FLAG(peer->flags,
|
||||
PEER_FLAG_IFPEER_V6ONLY)) {
|
||||
if (peer_active(peer))
|
||||
BGP_EVENT_ADD(peer, BGP_Stop);
|
||||
BGP_EVENT_ADD(peer, BGP_Start);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vty_out (vty, " %s invalid\n",
|
||||
inet_ntop(rn->p.family, &rn->p.u.prefix, buf, sizeof(buf)));
|
||||
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
|
||||
vty_out (vty, " Must be Connected\n");
|
||||
} else if (addr->family == AF_INET6) {
|
||||
apply_mask_ipv6((struct prefix_ipv6 *)&p);
|
||||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
|
||||
return;
|
||||
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
|
||||
return;
|
||||
|
||||
rn = bgp_node_get(bgp->connected_table[AFI_IP6],
|
||||
(struct prefix *)&p);
|
||||
if (rn->info) {
|
||||
bc = rn->info;
|
||||
bc->refcnt++;
|
||||
} else {
|
||||
bc = XCALLOC(MTYPE_BGP_CONN,
|
||||
sizeof(struct bgp_connected_ref));
|
||||
bc->refcnt = 1;
|
||||
rn->info = bc;
|
||||
}
|
||||
tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
|
||||
vty_out (vty, " Last update: %s", ctime(&tbuf));
|
||||
vty_out (vty, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
show_ip_bgp_nexthop_table (struct vty *vty, const char *name, int detail)
|
||||
void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
|
||||
{
|
||||
struct bgp *bgp;
|
||||
struct prefix p;
|
||||
struct prefix *addr;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_connected_ref *bc;
|
||||
|
||||
if (name)
|
||||
bgp = bgp_lookup_by_name (name);
|
||||
else
|
||||
bgp = bgp_get_default ();
|
||||
if (!bgp)
|
||||
{
|
||||
vty_out (vty, "%% No such BGP instance exist\n");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
addr = ifc->address;
|
||||
|
||||
bgp_show_nexthops (vty, bgp, detail);
|
||||
p = *(CONNECTED_PREFIX(ifc));
|
||||
if (addr->family == AF_INET) {
|
||||
apply_mask_ipv4((struct prefix_ipv4 *)&p);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
|
||||
return;
|
||||
|
||||
bgp_address_del(bgp, addr);
|
||||
|
||||
rn = bgp_node_lookup(bgp->connected_table[AFI_IP], &p);
|
||||
if (!rn)
|
||||
return;
|
||||
|
||||
bc = rn->info;
|
||||
bc->refcnt--;
|
||||
if (bc->refcnt == 0) {
|
||||
XFREE(MTYPE_BGP_CONN, bc);
|
||||
rn->info = NULL;
|
||||
}
|
||||
bgp_unlock_node(rn);
|
||||
bgp_unlock_node(rn);
|
||||
} else if (addr->family == AF_INET6) {
|
||||
apply_mask_ipv6((struct prefix_ipv6 *)&p);
|
||||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
|
||||
return;
|
||||
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
|
||||
return;
|
||||
|
||||
rn = bgp_node_lookup(bgp->connected_table[AFI_IP6],
|
||||
(struct prefix *)&p);
|
||||
if (!rn)
|
||||
return;
|
||||
|
||||
bc = rn->info;
|
||||
bc->refcnt--;
|
||||
if (bc->refcnt == 0) {
|
||||
XFREE(MTYPE_BGP_CONN, bc);
|
||||
rn->info = NULL;
|
||||
}
|
||||
bgp_unlock_node(rn);
|
||||
bgp_unlock_node(rn);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bgp_show_all_instances_nexthops_vty (struct vty *vty)
|
||||
int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
|
||||
{
|
||||
struct listnode *node, *nnode;
|
||||
struct bgp *bgp;
|
||||
struct bgp_addr tmp, *addr;
|
||||
|
||||
for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
|
||||
{
|
||||
vty_out (vty, "\nInstance %s:\n",
|
||||
(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? "Default" : bgp->name);
|
||||
bgp_show_nexthops (vty, bgp, 0);
|
||||
}
|
||||
tmp.addr = nh_addr;
|
||||
|
||||
addr = hash_lookup(bgp->address_hash, &tmp);
|
||||
if (addr)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
|
||||
{
|
||||
struct bgp_node *rn1;
|
||||
struct bgp_node *rn2;
|
||||
struct prefix p;
|
||||
int ret;
|
||||
|
||||
p.family = AF_INET;
|
||||
p.prefixlen = IPV4_MAX_BITLEN;
|
||||
p.u.prefix4 = nexthop;
|
||||
|
||||
rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
|
||||
if (!rn1)
|
||||
return 0;
|
||||
|
||||
p.family = AF_INET;
|
||||
p.prefixlen = IPV4_MAX_BITLEN;
|
||||
p.u.prefix4 = peer->su.sin.sin_addr;
|
||||
|
||||
rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
|
||||
if (!rn2) {
|
||||
bgp_unlock_node(rn1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = (rn1 == rn2) ? 1 : 0;
|
||||
|
||||
bgp_unlock_node(rn1);
|
||||
bgp_unlock_node(rn2);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail)
|
||||
{
|
||||
struct bgp_node *rn;
|
||||
struct bgp_nexthop_cache *bnc;
|
||||
char buf[PREFIX2STR_BUFFER];
|
||||
struct nexthop *nexthop;
|
||||
time_t tbuf;
|
||||
afi_t afi;
|
||||
|
||||
vty_out(vty, "Current BGP nexthop cache:\n");
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
||||
if (!bgp->nexthop_cache_table[afi])
|
||||
continue;
|
||||
|
||||
for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn;
|
||||
rn = bgp_route_next(rn)) {
|
||||
if ((bnc = rn->info) != NULL) {
|
||||
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
|
||||
vty_out(vty,
|
||||
" %s valid [IGP metric %d], #paths %d\n",
|
||||
inet_ntop(rn->p.family,
|
||||
&rn->p.u.prefix, buf,
|
||||
sizeof(buf)),
|
||||
bnc->metric, bnc->path_count);
|
||||
if (detail)
|
||||
for (nexthop = bnc->nexthop;
|
||||
nexthop;
|
||||
nexthop = nexthop->next)
|
||||
switch (nexthop->type) {
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
vty_out(vty,
|
||||
" gate %s\n",
|
||||
inet_ntop(
|
||||
AF_INET6,
|
||||
&nexthop->gate
|
||||
.ipv6,
|
||||
buf,
|
||||
sizeof(buf)));
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
||||
vty_out(vty,
|
||||
" gate %s, if %s\n",
|
||||
inet_ntop(
|
||||
AF_INET6,
|
||||
&nexthop->gate
|
||||
.ipv6,
|
||||
buf,
|
||||
sizeof(buf)),
|
||||
ifindex2ifname(
|
||||
nexthop->ifindex,
|
||||
bgp->vrf_id));
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
vty_out(vty,
|
||||
" gate %s\n",
|
||||
inet_ntop(
|
||||
AF_INET,
|
||||
&nexthop->gate
|
||||
.ipv4,
|
||||
buf,
|
||||
sizeof(buf)));
|
||||
break;
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
vty_out(vty,
|
||||
" if %s\n",
|
||||
ifindex2ifname(
|
||||
nexthop->ifindex,
|
||||
bgp->vrf_id));
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||
vty_out(vty,
|
||||
" gate %s, if %s\n",
|
||||
inet_ntop(
|
||||
AF_INET,
|
||||
&nexthop->gate
|
||||
.ipv4,
|
||||
buf,
|
||||
sizeof(buf)),
|
||||
ifindex2ifname(
|
||||
nexthop->ifindex,
|
||||
bgp->vrf_id));
|
||||
break;
|
||||
default:
|
||||
vty_out(vty,
|
||||
" invalid nexthop type %u\n",
|
||||
nexthop->type);
|
||||
}
|
||||
} else {
|
||||
vty_out(vty, " %s invalid\n",
|
||||
inet_ntop(rn->p.family,
|
||||
&rn->p.u.prefix, buf,
|
||||
sizeof(buf)));
|
||||
if (CHECK_FLAG(bnc->flags,
|
||||
BGP_NEXTHOP_CONNECTED))
|
||||
vty_out(vty,
|
||||
" Must be Connected\n");
|
||||
}
|
||||
tbuf = time(NULL)
|
||||
- (bgp_clock() - bnc->last_update);
|
||||
vty_out(vty, " Last update: %s", ctime(&tbuf));
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
|
||||
int detail)
|
||||
{
|
||||
struct bgp *bgp;
|
||||
|
||||
if (name)
|
||||
bgp = bgp_lookup_by_name(name);
|
||||
else
|
||||
bgp = bgp_get_default();
|
||||
if (!bgp) {
|
||||
vty_out(vty, "%% No such BGP instance exist\n");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
bgp_show_nexthops(vty, bgp, detail);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void bgp_show_all_instances_nexthops_vty(struct vty *vty)
|
||||
{
|
||||
struct listnode *node, *nnode;
|
||||
struct bgp *bgp;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
|
||||
vty_out(vty, "\nInstance %s:\n",
|
||||
(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
|
||||
? "Default"
|
||||
: bgp->name);
|
||||
bgp_show_nexthops(vty, bgp, 0);
|
||||
}
|
||||
}
|
||||
|
||||
DEFUN (show_ip_bgp_nexthop,
|
||||
@ -494,10 +496,10 @@ DEFUN (show_ip_bgp_nexthop,
|
||||
"BGP nexthop table\n"
|
||||
"Show detailed information\n")
|
||||
{
|
||||
int idx = 0;
|
||||
char *vrf = argv_find (argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL;
|
||||
int detail = argv_find (argv, argc, "detail", &idx) ? 1 : 0;
|
||||
return show_ip_bgp_nexthop_table (vty, vrf, detail);
|
||||
int idx = 0;
|
||||
char *vrf = argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL;
|
||||
int detail = argv_find(argv, argc, "detail", &idx) ? 1 : 0;
|
||||
return show_ip_bgp_nexthop_table(vty, vrf, detail);
|
||||
}
|
||||
|
||||
DEFUN (show_ip_bgp_instance_all_nexthop,
|
||||
@ -509,46 +511,43 @@ DEFUN (show_ip_bgp_instance_all_nexthop,
|
||||
BGP_INSTANCE_ALL_HELP_STR
|
||||
"BGP nexthop table\n")
|
||||
{
|
||||
bgp_show_all_instances_nexthops_vty (vty);
|
||||
return CMD_SUCCESS;
|
||||
bgp_show_all_instances_nexthops_vty(vty);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
bgp_scan_init (struct bgp *bgp)
|
||||
void bgp_scan_init(struct bgp *bgp)
|
||||
{
|
||||
afi_t afi;
|
||||
afi_t afi;
|
||||
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||
{
|
||||
bgp->nexthop_cache_table[afi] = bgp_table_init (afi, SAFI_UNICAST);
|
||||
bgp->connected_table[afi] = bgp_table_init (afi, SAFI_UNICAST);
|
||||
bgp->import_check_table[afi] = bgp_table_init (afi, SAFI_UNICAST);
|
||||
}
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
||||
bgp->nexthop_cache_table[afi] =
|
||||
bgp_table_init(afi, SAFI_UNICAST);
|
||||
bgp->connected_table[afi] = bgp_table_init(afi, SAFI_UNICAST);
|
||||
bgp->import_check_table[afi] =
|
||||
bgp_table_init(afi, SAFI_UNICAST);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bgp_scan_vty_init (void)
|
||||
void bgp_scan_vty_init(void)
|
||||
{
|
||||
install_element (VIEW_NODE, &show_ip_bgp_nexthop_cmd);
|
||||
install_element (VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
|
||||
install_element(VIEW_NODE, &show_ip_bgp_nexthop_cmd);
|
||||
install_element(VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
|
||||
}
|
||||
|
||||
void
|
||||
bgp_scan_finish (struct bgp *bgp)
|
||||
void bgp_scan_finish(struct bgp *bgp)
|
||||
{
|
||||
afi_t afi;
|
||||
afi_t afi;
|
||||
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||
{
|
||||
/* Only the current one needs to be reset. */
|
||||
bgp_nexthop_cache_reset (bgp->nexthop_cache_table[afi]);
|
||||
bgp_table_unlock (bgp->nexthop_cache_table[afi]);
|
||||
bgp->nexthop_cache_table[afi] = NULL;
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
||||
/* Only the current one needs to be reset. */
|
||||
bgp_nexthop_cache_reset(bgp->nexthop_cache_table[afi]);
|
||||
bgp_table_unlock(bgp->nexthop_cache_table[afi]);
|
||||
bgp->nexthop_cache_table[afi] = NULL;
|
||||
|
||||
bgp_table_unlock (bgp->connected_table[afi]);
|
||||
bgp->connected_table[afi] = NULL;
|
||||
bgp_table_unlock(bgp->connected_table[afi]);
|
||||
bgp->connected_table[afi] = NULL;
|
||||
|
||||
bgp_table_unlock (bgp->import_check_table[afi]);
|
||||
bgp->import_check_table[afi] = NULL;
|
||||
}
|
||||
bgp_table_unlock(bgp->import_check_table[afi]);
|
||||
bgp->import_check_table[afi] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,28 +25,26 @@
|
||||
#include "queue.h"
|
||||
#include "prefix.h"
|
||||
|
||||
#define NEXTHOP_FAMILY(nexthop_len) ( \
|
||||
((nexthop_len) == 4 || \
|
||||
(nexthop_len) == 12 ? AF_INET : \
|
||||
((nexthop_len) == 16 || \
|
||||
(nexthop_len) == 24 || \
|
||||
(nexthop_len) == 48 ? AF_INET6 : \
|
||||
AF_UNSPEC)) \
|
||||
)
|
||||
#define NEXTHOP_FAMILY(nexthop_len) \
|
||||
(((nexthop_len) == 4 || (nexthop_len) == 12 \
|
||||
? AF_INET \
|
||||
: ((nexthop_len) == 16 || (nexthop_len) == 24 \
|
||||
|| (nexthop_len) == 48 \
|
||||
? AF_INET6 \
|
||||
: AF_UNSPEC)))
|
||||
|
||||
#define BGP_MP_NEXTHOP_FAMILY NEXTHOP_FAMILY
|
||||
|
||||
/* BGP nexthop cache value structure. */
|
||||
struct bgp_nexthop_cache
|
||||
{
|
||||
/* IGP route's metric. */
|
||||
u_int32_t metric;
|
||||
struct bgp_nexthop_cache {
|
||||
/* IGP route's metric. */
|
||||
u_int32_t metric;
|
||||
|
||||
/* Nexthop number and nexthop linked list.*/
|
||||
u_char nexthop_num;
|
||||
struct nexthop *nexthop;
|
||||
time_t last_update;
|
||||
u_int16_t flags;
|
||||
/* Nexthop number and nexthop linked list.*/
|
||||
u_char nexthop_num;
|
||||
struct nexthop *nexthop;
|
||||
time_t last_update;
|
||||
u_int16_t flags;
|
||||
|
||||
#define BGP_NEXTHOP_VALID (1 << 0)
|
||||
#define BGP_NEXTHOP_REGISTERED (1 << 1)
|
||||
@ -55,26 +53,26 @@ struct bgp_nexthop_cache
|
||||
#define BGP_STATIC_ROUTE (1 << 4)
|
||||
#define BGP_STATIC_ROUTE_EXACT_MATCH (1 << 5)
|
||||
|
||||
u_int16_t change_flags;
|
||||
u_int16_t change_flags;
|
||||
|
||||
#define BGP_NEXTHOP_CHANGED (1 << 0)
|
||||
#define BGP_NEXTHOP_METRIC_CHANGED (1 << 1)
|
||||
#define BGP_NEXTHOP_CONNECTED_CHANGED (1 << 2)
|
||||
|
||||
struct bgp_node *node;
|
||||
void *nht_info; /* In BGP, peer session */
|
||||
LIST_HEAD(path_list, bgp_info) paths;
|
||||
unsigned int path_count;
|
||||
struct bgp *bgp;
|
||||
struct bgp_node *node;
|
||||
void *nht_info; /* In BGP, peer session */
|
||||
LIST_HEAD(path_list, bgp_info) paths;
|
||||
unsigned int path_count;
|
||||
struct bgp *bgp;
|
||||
};
|
||||
|
||||
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_multiaccess_check_v4 (struct in_addr, struct peer *);
|
||||
extern int bgp_config_write_scan_time (struct vty *);
|
||||
extern int bgp_nexthop_self (struct bgp *, struct in_addr);
|
||||
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_multiaccess_check_v4(struct in_addr, struct peer *);
|
||||
extern int bgp_config_write_scan_time(struct vty *);
|
||||
extern int bgp_nexthop_self(struct bgp *, struct in_addr);
|
||||
extern struct bgp_nexthop_cache *bnc_new(void);
|
||||
extern void bnc_free(struct bgp_nexthop_cache *bnc);
|
||||
extern void bnc_nexthop_free(struct bgp_nexthop_cache *bnc);
|
||||
@ -82,7 +80,7 @@ extern char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size);
|
||||
extern void bgp_scan_init(struct bgp *bgp);
|
||||
extern void bgp_scan_finish(struct bgp *bgp);
|
||||
extern void bgp_scan_vty_init(void);
|
||||
extern void bgp_address_init (struct bgp *bgp);
|
||||
extern void bgp_address_destroy (struct bgp *bgp);
|
||||
extern void bgp_address_init(struct bgp *bgp);
|
||||
extern void bgp_address_destroy(struct bgp *bgp);
|
||||
|
||||
#endif /* _QUAGGA_BGP_NEXTHOP_H */
|
||||
|
||||
1117
bgpd/bgp_nht.c
1117
bgpd/bgp_nht.c
File diff suppressed because it is too large
Load Diff
@ -45,8 +45,8 @@ extern int bgp_find_nexthop(struct bgp_info *p, int connected);
|
||||
* peer - The BGP peer associated with this NHT
|
||||
* connected - True if NH MUST be a connected route
|
||||
*/
|
||||
extern int bgp_find_or_add_nexthop(struct bgp *bgp, afi_t a,
|
||||
struct bgp_info *p, struct peer *peer, int connected);
|
||||
extern int bgp_find_or_add_nexthop(struct bgp *bgp, afi_t a, struct bgp_info *p,
|
||||
struct peer *peer, int connected);
|
||||
|
||||
/**
|
||||
* bgp_unlink_nexthop() - Unlink the nexthop object from the path structure.
|
||||
@ -54,7 +54,7 @@ extern int bgp_find_or_add_nexthop(struct bgp *bgp, afi_t a,
|
||||
* p - path structure.
|
||||
*/
|
||||
extern void bgp_unlink_nexthop(struct bgp_info *p);
|
||||
void bgp_unlink_nexthop_by_peer (struct peer *);
|
||||
void bgp_unlink_nexthop_by_peer(struct peer *);
|
||||
|
||||
/**
|
||||
* bgp_delete_connected_nexthop() - Reset the 'peer' pointer for a connected
|
||||
@ -64,6 +64,6 @@ void bgp_unlink_nexthop_by_peer (struct peer *);
|
||||
* afi - afi: AFI_IP or AF_IP6
|
||||
* peer - Ptr to peer
|
||||
*/
|
||||
extern void bgp_delete_connected_nexthop (afi_t afi, struct peer *peer);
|
||||
extern void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer);
|
||||
|
||||
#endif /* _BGP_NHT_H */
|
||||
|
||||
2606
bgpd/bgp_open.c
2606
bgpd/bgp_open.c
File diff suppressed because it is too large
Load Diff
@ -22,36 +22,31 @@
|
||||
#define _QUAGGA_BGP_OPEN_H
|
||||
|
||||
/* Standard header for capability TLV */
|
||||
struct capability_header
|
||||
{
|
||||
u_char code;
|
||||
u_char length;
|
||||
struct capability_header {
|
||||
u_char code;
|
||||
u_char length;
|
||||
};
|
||||
|
||||
/* Generic MP capability data */
|
||||
struct capability_mp_data
|
||||
{
|
||||
iana_afi_t afi;
|
||||
u_char reserved;
|
||||
safi_t safi;
|
||||
struct capability_mp_data {
|
||||
iana_afi_t afi;
|
||||
u_char reserved;
|
||||
safi_t safi;
|
||||
};
|
||||
|
||||
struct capability_as4
|
||||
{
|
||||
uint32_t as4;
|
||||
struct capability_as4 {
|
||||
uint32_t as4;
|
||||
};
|
||||
|
||||
struct graceful_restart_af
|
||||
{
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
u_char flag;
|
||||
struct graceful_restart_af {
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
u_char flag;
|
||||
};
|
||||
|
||||
struct capability_gr
|
||||
{
|
||||
u_int16_t restart_flag_time;
|
||||
struct graceful_restart_af gr[];
|
||||
struct capability_gr {
|
||||
u_int16_t restart_flag_time;
|
||||
struct graceful_restart_af gr[];
|
||||
};
|
||||
|
||||
/* Capability Code */
|
||||
@ -68,7 +63,6 @@ struct capability_gr
|
||||
#define CAPABILITY_CODE_REFRESH_OLD 128 /* Route Refresh Capability(cisco) */
|
||||
#define CAPABILITY_CODE_ORF_OLD 130 /* Cooperative Route Filtering Capability(cisco) */
|
||||
|
||||
|
||||
/* Capability Length */
|
||||
#define CAPABILITY_CODE_MP_LEN 4
|
||||
#define CAPABILITY_CODE_REFRESH_LEN 0
|
||||
@ -99,9 +93,10 @@ struct capability_gr
|
||||
#define RESTART_R_BIT 0x8000
|
||||
#define RESTART_F_BIT 0x80
|
||||
|
||||
extern int bgp_open_option_parse (struct peer *, u_char, int *);
|
||||
extern void bgp_open_capability (struct stream *, struct peer *);
|
||||
extern void bgp_capability_vty_out (struct vty *, struct peer *, u_char, json_object *);
|
||||
extern as_t peek_for_as4_capability (struct peer *, u_char);
|
||||
extern int bgp_open_option_parse(struct peer *, u_char, int *);
|
||||
extern void bgp_open_capability(struct stream *, struct peer *);
|
||||
extern void bgp_capability_vty_out(struct vty *, struct peer *, u_char,
|
||||
json_object *);
|
||||
extern as_t peek_for_as4_capability(struct peer *, u_char);
|
||||
|
||||
#endif /* _QUAGGA_BGP_OPEN_H */
|
||||
|
||||
3858
bgpd/bgp_packet.c
3858
bgpd/bgp_packet.c
File diff suppressed because it is too large
Load Diff
@ -38,31 +38,33 @@
|
||||
#define ORF_COMMON_PART_DENY 0x20
|
||||
|
||||
/* Packet send and receive function prototypes. */
|
||||
extern int bgp_read (struct thread *);
|
||||
extern int bgp_write (struct thread *);
|
||||
extern int bgp_connect_check (struct peer *, int change_state);
|
||||
extern int bgp_read(struct thread *);
|
||||
extern int bgp_write(struct thread *);
|
||||
extern int bgp_connect_check(struct peer *, int change_state);
|
||||
|
||||
extern void bgp_keepalive_send (struct peer *);
|
||||
extern void bgp_open_send (struct peer *);
|
||||
extern void bgp_notify_send (struct peer *, u_int8_t, u_int8_t);
|
||||
extern void bgp_notify_send_with_data (struct peer *, u_int8_t, u_int8_t,
|
||||
u_int8_t *, size_t);
|
||||
extern void bgp_route_refresh_send (struct peer *, afi_t, safi_t, u_char, u_char, int);
|
||||
extern void bgp_capability_send (struct peer *, afi_t, safi_t, int, int);
|
||||
extern void bgp_default_update_send (struct peer *, struct attr *,
|
||||
afi_t, safi_t, struct peer *);
|
||||
extern void bgp_default_withdraw_send (struct peer *, afi_t, safi_t);
|
||||
extern void bgp_keepalive_send(struct peer *);
|
||||
extern void bgp_open_send(struct peer *);
|
||||
extern void bgp_notify_send(struct peer *, u_int8_t, u_int8_t);
|
||||
extern void bgp_notify_send_with_data(struct peer *, u_int8_t, u_int8_t,
|
||||
u_int8_t *, size_t);
|
||||
extern void bgp_route_refresh_send(struct peer *, afi_t, safi_t, u_char, u_char,
|
||||
int);
|
||||
extern void bgp_capability_send(struct peer *, afi_t, safi_t, int, int);
|
||||
extern void bgp_default_update_send(struct peer *, struct attr *, afi_t, safi_t,
|
||||
struct peer *);
|
||||
extern void bgp_default_withdraw_send(struct peer *, afi_t, safi_t);
|
||||
|
||||
extern int bgp_capability_receive (struct peer *, bgp_size_t);
|
||||
extern int bgp_capability_receive(struct peer *, bgp_size_t);
|
||||
|
||||
extern int bgp_nlri_parse (struct peer *, struct attr *, struct bgp_nlri *, int mp_withdraw);
|
||||
extern int bgp_nlri_parse(struct peer *, struct attr *, struct bgp_nlri *,
|
||||
int mp_withdraw);
|
||||
|
||||
extern void bgp_update_restarted_peers (struct peer *);
|
||||
extern void bgp_update_implicit_eors (struct peer *);
|
||||
extern void bgp_check_update_delay (struct bgp *);
|
||||
extern void bgp_update_restarted_peers(struct peer *);
|
||||
extern void bgp_update_implicit_eors(struct peer *);
|
||||
extern void bgp_check_update_delay(struct bgp *);
|
||||
|
||||
extern int bgp_packet_set_marker (struct stream *s, u_char type);
|
||||
extern int bgp_packet_set_size (struct stream *s);
|
||||
extern void bgp_packet_add (struct peer *peer, struct stream *s);
|
||||
extern int bgp_packet_set_marker(struct stream *s, u_char type);
|
||||
extern int bgp_packet_set_size(struct stream *s);
|
||||
extern void bgp_packet_add(struct peer *peer, struct stream *s);
|
||||
|
||||
#endif /* _QUAGGA_BGP_PACKET_H */
|
||||
|
||||
257
bgpd/bgp_rd.c
257
bgpd/bgp_rd.c
@ -36,197 +36,174 @@
|
||||
#include "bgpd/rfapi/rfapi_backend.h"
|
||||
#endif
|
||||
|
||||
u_int16_t
|
||||
decode_rd_type (u_char *pnt)
|
||||
u_int16_t decode_rd_type(u_char *pnt)
|
||||
{
|
||||
u_int16_t v;
|
||||
u_int16_t v;
|
||||
|
||||
v = ((u_int16_t) *pnt++ << 8);
|
||||
v = ((u_int16_t)*pnt++ << 8);
|
||||
#if ENABLE_BGP_VNC
|
||||
/*
|
||||
* VNC L2 stores LHI in lower byte, so omit it
|
||||
*/
|
||||
if (v != RD_TYPE_VNC_ETH)
|
||||
v |= (u_int16_t) *pnt;
|
||||
#else /* duplicate code for clarity */
|
||||
v |= (u_int16_t) *pnt;
|
||||
/*
|
||||
* VNC L2 stores LHI in lower byte, so omit it
|
||||
*/
|
||||
if (v != RD_TYPE_VNC_ETH)
|
||||
v |= (u_int16_t)*pnt;
|
||||
#else /* duplicate code for clarity */
|
||||
v |= (u_int16_t)*pnt;
|
||||
#endif
|
||||
return v;
|
||||
return v;
|
||||
}
|
||||
|
||||
void
|
||||
encode_rd_type (u_int16_t v, u_char *pnt)
|
||||
void encode_rd_type(u_int16_t v, u_char *pnt)
|
||||
{
|
||||
*((u_int16_t *)pnt) = htons(v);
|
||||
*((u_int16_t *)pnt) = htons(v);
|
||||
}
|
||||
|
||||
/* type == RD_TYPE_AS */
|
||||
void
|
||||
decode_rd_as (u_char *pnt, struct rd_as *rd_as)
|
||||
void decode_rd_as(u_char *pnt, struct rd_as *rd_as)
|
||||
{
|
||||
rd_as->as = (u_int16_t) *pnt++ << 8;
|
||||
rd_as->as |= (u_int16_t) *pnt++;
|
||||
rd_as->as = (u_int16_t)*pnt++ << 8;
|
||||
rd_as->as |= (u_int16_t)*pnt++;
|
||||
|
||||
rd_as->val = ((u_int32_t) *pnt++ << 24);
|
||||
rd_as->val |= ((u_int32_t) *pnt++ << 16);
|
||||
rd_as->val |= ((u_int32_t) *pnt++ << 8);
|
||||
rd_as->val |= (u_int32_t) *pnt;
|
||||
rd_as->val = ((u_int32_t)*pnt++ << 24);
|
||||
rd_as->val |= ((u_int32_t)*pnt++ << 16);
|
||||
rd_as->val |= ((u_int32_t)*pnt++ << 8);
|
||||
rd_as->val |= (u_int32_t)*pnt;
|
||||
}
|
||||
|
||||
/* type == RD_TYPE_AS4 */
|
||||
void
|
||||
decode_rd_as4 (u_char *pnt, struct rd_as *rd_as)
|
||||
void decode_rd_as4(u_char *pnt, struct rd_as *rd_as)
|
||||
{
|
||||
rd_as->as = (u_int32_t) *pnt++ << 24;
|
||||
rd_as->as |= (u_int32_t) *pnt++ << 16;
|
||||
rd_as->as |= (u_int32_t) *pnt++ << 8;
|
||||
rd_as->as |= (u_int32_t) *pnt++;
|
||||
rd_as->as = (u_int32_t)*pnt++ << 24;
|
||||
rd_as->as |= (u_int32_t)*pnt++ << 16;
|
||||
rd_as->as |= (u_int32_t)*pnt++ << 8;
|
||||
rd_as->as |= (u_int32_t)*pnt++;
|
||||
|
||||
rd_as->val = ((u_int16_t) *pnt++ << 8);
|
||||
rd_as->val |= (u_int16_t) *pnt;
|
||||
rd_as->val = ((u_int16_t)*pnt++ << 8);
|
||||
rd_as->val |= (u_int16_t)*pnt;
|
||||
}
|
||||
|
||||
/* type == RD_TYPE_IP */
|
||||
void
|
||||
decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip)
|
||||
void decode_rd_ip(u_char *pnt, struct rd_ip *rd_ip)
|
||||
{
|
||||
memcpy (&rd_ip->ip, pnt, 4);
|
||||
pnt += 4;
|
||||
memcpy(&rd_ip->ip, pnt, 4);
|
||||
pnt += 4;
|
||||
|
||||
rd_ip->val = ((u_int16_t) *pnt++ << 8);
|
||||
rd_ip->val |= (u_int16_t) *pnt;
|
||||
rd_ip->val = ((u_int16_t)*pnt++ << 8);
|
||||
rd_ip->val |= (u_int16_t)*pnt;
|
||||
}
|
||||
|
||||
#if ENABLE_BGP_VNC
|
||||
/* type == RD_TYPE_VNC_ETH */
|
||||
void
|
||||
decode_rd_vnc_eth (u_char *pnt, struct rd_vnc_eth *rd_vnc_eth)
|
||||
void decode_rd_vnc_eth(u_char *pnt, struct rd_vnc_eth *rd_vnc_eth)
|
||||
{
|
||||
rd_vnc_eth->type = RD_TYPE_VNC_ETH;
|
||||
rd_vnc_eth->local_nve_id = pnt[1];
|
||||
memcpy (rd_vnc_eth->macaddr.octet, pnt + 2, ETHER_ADDR_LEN);
|
||||
rd_vnc_eth->type = RD_TYPE_VNC_ETH;
|
||||
rd_vnc_eth->local_nve_id = pnt[1];
|
||||
memcpy(rd_vnc_eth->macaddr.octet, pnt + 2, ETHER_ADDR_LEN);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
str2prefix_rd (const char *str, struct prefix_rd *prd)
|
||||
int str2prefix_rd(const char *str, struct prefix_rd *prd)
|
||||
{
|
||||
int ret; /* ret of called functions */
|
||||
int lret; /* local ret, of this func */
|
||||
char *p;
|
||||
char *p2;
|
||||
struct stream *s = NULL;
|
||||
char *half = NULL;
|
||||
struct in_addr addr;
|
||||
int ret; /* ret of called functions */
|
||||
int lret; /* local ret, of this func */
|
||||
char *p;
|
||||
char *p2;
|
||||
struct stream *s = NULL;
|
||||
char *half = NULL;
|
||||
struct in_addr addr;
|
||||
|
||||
s = stream_new (8);
|
||||
s = stream_new(8);
|
||||
|
||||
prd->family = AF_UNSPEC;
|
||||
prd->prefixlen = 64;
|
||||
prd->family = AF_UNSPEC;
|
||||
prd->prefixlen = 64;
|
||||
|
||||
lret = 0;
|
||||
p = strchr (str, ':');
|
||||
if (! p)
|
||||
goto out;
|
||||
lret = 0;
|
||||
p = strchr(str, ':');
|
||||
if (!p)
|
||||
goto out;
|
||||
|
||||
if (! all_digit (p + 1))
|
||||
goto out;
|
||||
if (!all_digit(p + 1))
|
||||
goto out;
|
||||
|
||||
half = XMALLOC (MTYPE_TMP, (p - str) + 1);
|
||||
memcpy (half, str, (p - str));
|
||||
half[p - str] = '\0';
|
||||
half = XMALLOC(MTYPE_TMP, (p - str) + 1);
|
||||
memcpy(half, str, (p - str));
|
||||
half[p - str] = '\0';
|
||||
|
||||
p2 = strchr (str, '.');
|
||||
p2 = strchr(str, '.');
|
||||
|
||||
if (! p2)
|
||||
{
|
||||
unsigned long as_val;
|
||||
if (!p2) {
|
||||
unsigned long as_val;
|
||||
|
||||
if (! all_digit (half))
|
||||
goto out;
|
||||
if (!all_digit(half))
|
||||
goto out;
|
||||
|
||||
as_val = atol(half);
|
||||
if (as_val > 0xffff)
|
||||
{
|
||||
stream_putw (s, RD_TYPE_AS4);
|
||||
stream_putl (s, as_val);
|
||||
stream_putw (s, atol (p + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
stream_putw (s, RD_TYPE_AS);
|
||||
stream_putw (s, as_val);
|
||||
stream_putl (s, atol (p + 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = inet_aton (half, &addr);
|
||||
if (! ret)
|
||||
goto out;
|
||||
as_val = atol(half);
|
||||
if (as_val > 0xffff) {
|
||||
stream_putw(s, RD_TYPE_AS4);
|
||||
stream_putl(s, as_val);
|
||||
stream_putw(s, atol(p + 1));
|
||||
} else {
|
||||
stream_putw(s, RD_TYPE_AS);
|
||||
stream_putw(s, as_val);
|
||||
stream_putl(s, atol(p + 1));
|
||||
}
|
||||
} else {
|
||||
ret = inet_aton(half, &addr);
|
||||
if (!ret)
|
||||
goto out;
|
||||
|
||||
stream_putw (s, RD_TYPE_IP);
|
||||
stream_put_in_addr (s, &addr);
|
||||
stream_putw (s, atol (p + 1));
|
||||
}
|
||||
memcpy (prd->val, s->data, 8);
|
||||
lret = 1;
|
||||
stream_putw(s, RD_TYPE_IP);
|
||||
stream_put_in_addr(s, &addr);
|
||||
stream_putw(s, atol(p + 1));
|
||||
}
|
||||
memcpy(prd->val, s->data, 8);
|
||||
lret = 1;
|
||||
|
||||
out:
|
||||
if (s)
|
||||
stream_free (s);
|
||||
if (half)
|
||||
XFREE(MTYPE_TMP, half);
|
||||
return lret;
|
||||
if (s)
|
||||
stream_free(s);
|
||||
if (half)
|
||||
XFREE(MTYPE_TMP, half);
|
||||
return lret;
|
||||
}
|
||||
|
||||
char *
|
||||
prefix_rd2str (struct prefix_rd *prd, char *buf, size_t size)
|
||||
char *prefix_rd2str(struct prefix_rd *prd, char *buf, size_t size)
|
||||
{
|
||||
u_char *pnt;
|
||||
u_int16_t type;
|
||||
struct rd_as rd_as;
|
||||
struct rd_ip rd_ip;
|
||||
u_char *pnt;
|
||||
u_int16_t type;
|
||||
struct rd_as rd_as;
|
||||
struct rd_ip rd_ip;
|
||||
|
||||
if (size < RD_ADDRSTRLEN)
|
||||
return NULL;
|
||||
if (size < RD_ADDRSTRLEN)
|
||||
return NULL;
|
||||
|
||||
pnt = prd->val;
|
||||
pnt = prd->val;
|
||||
|
||||
type = decode_rd_type (pnt);
|
||||
type = decode_rd_type(pnt);
|
||||
|
||||
if (type == RD_TYPE_AS)
|
||||
{
|
||||
decode_rd_as (pnt + 2, &rd_as);
|
||||
snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val);
|
||||
return buf;
|
||||
}
|
||||
else if (type == RD_TYPE_AS4)
|
||||
{
|
||||
decode_rd_as4 (pnt + 2, &rd_as);
|
||||
snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val);
|
||||
return buf;
|
||||
}
|
||||
else if (type == RD_TYPE_IP)
|
||||
{
|
||||
decode_rd_ip (pnt + 2, &rd_ip);
|
||||
snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
|
||||
return buf;
|
||||
}
|
||||
if (type == RD_TYPE_AS) {
|
||||
decode_rd_as(pnt + 2, &rd_as);
|
||||
snprintf(buf, size, "%u:%d", rd_as.as, rd_as.val);
|
||||
return buf;
|
||||
} else if (type == RD_TYPE_AS4) {
|
||||
decode_rd_as4(pnt + 2, &rd_as);
|
||||
snprintf(buf, size, "%u:%d", rd_as.as, rd_as.val);
|
||||
return buf;
|
||||
} else if (type == RD_TYPE_IP) {
|
||||
decode_rd_ip(pnt + 2, &rd_ip);
|
||||
snprintf(buf, size, "%s:%d", inet_ntoa(rd_ip.ip), rd_ip.val);
|
||||
return buf;
|
||||
}
|
||||
#if ENABLE_BGP_VNC
|
||||
else if (type == RD_TYPE_VNC_ETH)
|
||||
{
|
||||
snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
*(pnt+1), /* LHI */
|
||||
*(pnt+2), /* MAC[0] */
|
||||
*(pnt+3),
|
||||
*(pnt+4),
|
||||
*(pnt+5),
|
||||
*(pnt+6),
|
||||
*(pnt+7));
|
||||
else if (type == RD_TYPE_VNC_ETH) {
|
||||
snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
*(pnt + 1), /* LHI */
|
||||
*(pnt + 2), /* MAC[0] */
|
||||
*(pnt + 3), *(pnt + 4), *(pnt + 5), *(pnt + 6),
|
||||
*(pnt + 7));
|
||||
|
||||
return buf;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -34,41 +34,37 @@
|
||||
|
||||
#define RD_ADDRSTRLEN 28
|
||||
|
||||
struct rd_as
|
||||
{
|
||||
u_int16_t type;
|
||||
as_t as;
|
||||
u_int32_t val;
|
||||
struct rd_as {
|
||||
u_int16_t type;
|
||||
as_t as;
|
||||
u_int32_t val;
|
||||
};
|
||||
|
||||
struct rd_ip
|
||||
{
|
||||
u_int16_t type;
|
||||
struct in_addr ip;
|
||||
u_int16_t val;
|
||||
struct rd_ip {
|
||||
u_int16_t type;
|
||||
struct in_addr ip;
|
||||
u_int16_t val;
|
||||
};
|
||||
|
||||
#if ENABLE_BGP_VNC
|
||||
struct rd_vnc_eth
|
||||
{
|
||||
u_int16_t type;
|
||||
uint8_t local_nve_id;
|
||||
struct ethaddr macaddr;
|
||||
struct rd_vnc_eth {
|
||||
u_int16_t type;
|
||||
uint8_t local_nve_id;
|
||||
struct ethaddr macaddr;
|
||||
};
|
||||
#endif
|
||||
|
||||
extern u_int16_t decode_rd_type (u_char *pnt);
|
||||
extern void encode_rd_type (u_int16_t, u_char *);
|
||||
extern u_int16_t decode_rd_type(u_char *pnt);
|
||||
extern void encode_rd_type(u_int16_t, u_char *);
|
||||
|
||||
extern void decode_rd_as (u_char *pnt, struct rd_as *rd_as);
|
||||
extern void decode_rd_as4 (u_char *pnt, struct rd_as *rd_as);
|
||||
extern void decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip);
|
||||
extern void decode_rd_as(u_char *pnt, struct rd_as *rd_as);
|
||||
extern void decode_rd_as4(u_char *pnt, struct rd_as *rd_as);
|
||||
extern void decode_rd_ip(u_char *pnt, struct rd_ip *rd_ip);
|
||||
#if ENABLE_BGP_VNC
|
||||
extern void
|
||||
decode_rd_vnc_eth (u_char *pnt, struct rd_vnc_eth *rd_vnc_eth);
|
||||
extern void decode_rd_vnc_eth(u_char *pnt, struct rd_vnc_eth *rd_vnc_eth);
|
||||
#endif
|
||||
|
||||
extern int str2prefix_rd (const char *, struct prefix_rd *);
|
||||
extern char *prefix_rd2str (struct prefix_rd *, char *, size_t);
|
||||
extern int str2prefix_rd(const char *, struct prefix_rd *);
|
||||
extern char *prefix_rd2str(struct prefix_rd *, char *, size_t);
|
||||
|
||||
#endif /* _QUAGGA_BGP_RD_H */
|
||||
|
||||
@ -31,65 +31,59 @@
|
||||
#include "bgp_regex.h"
|
||||
|
||||
/* Character `_' has special mean. It represents [,{}() ] and the
|
||||
beginning of the line(^) and the end of the line ($).
|
||||
beginning of the line(^) and the end of the line ($).
|
||||
|
||||
(^|[,{}() ]|$) */
|
||||
|
||||
regex_t *
|
||||
bgp_regcomp (const char *regstr)
|
||||
regex_t *bgp_regcomp(const char *regstr)
|
||||
{
|
||||
/* Convert _ character to generic regular expression. */
|
||||
int i, j;
|
||||
int len;
|
||||
int magic = 0;
|
||||
char *magic_str;
|
||||
char magic_regexp[] = "(^|[,{}() ]|$)";
|
||||
int ret;
|
||||
regex_t *regex;
|
||||
/* Convert _ character to generic regular expression. */
|
||||
int i, j;
|
||||
int len;
|
||||
int magic = 0;
|
||||
char *magic_str;
|
||||
char magic_regexp[] = "(^|[,{}() ]|$)";
|
||||
int ret;
|
||||
regex_t *regex;
|
||||
|
||||
len = strlen (regstr);
|
||||
for (i = 0; i < len; i++)
|
||||
if (regstr[i] == '_')
|
||||
magic++;
|
||||
len = strlen(regstr);
|
||||
for (i = 0; i < len; i++)
|
||||
if (regstr[i] == '_')
|
||||
magic++;
|
||||
|
||||
magic_str = XMALLOC (MTYPE_TMP, len + (14 * magic) + 1);
|
||||
|
||||
for (i = 0, j = 0; i < len; i++)
|
||||
{
|
||||
if (regstr[i] == '_')
|
||||
{
|
||||
memcpy (magic_str + j, magic_regexp, strlen (magic_regexp));
|
||||
j += strlen (magic_regexp);
|
||||
magic_str = XMALLOC(MTYPE_TMP, len + (14 * magic) + 1);
|
||||
|
||||
for (i = 0, j = 0; i < len; i++) {
|
||||
if (regstr[i] == '_') {
|
||||
memcpy(magic_str + j, magic_regexp,
|
||||
strlen(magic_regexp));
|
||||
j += strlen(magic_regexp);
|
||||
} else
|
||||
magic_str[j++] = regstr[i];
|
||||
}
|
||||
else
|
||||
magic_str[j++] = regstr[i];
|
||||
}
|
||||
magic_str[j] = '\0';
|
||||
magic_str[j] = '\0';
|
||||
|
||||
regex = XMALLOC (MTYPE_BGP_REGEXP, sizeof (regex_t));
|
||||
regex = XMALLOC(MTYPE_BGP_REGEXP, sizeof(regex_t));
|
||||
|
||||
ret = regcomp (regex, magic_str, REG_EXTENDED|REG_NOSUB);
|
||||
ret = regcomp(regex, magic_str, REG_EXTENDED | REG_NOSUB);
|
||||
|
||||
XFREE (MTYPE_TMP, magic_str);
|
||||
XFREE(MTYPE_TMP, magic_str);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
XFREE (MTYPE_BGP_REGEXP, regex);
|
||||
return NULL;
|
||||
}
|
||||
if (ret != 0) {
|
||||
XFREE(MTYPE_BGP_REGEXP, regex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return regex;
|
||||
return regex;
|
||||
}
|
||||
|
||||
int
|
||||
bgp_regexec (regex_t *regex, struct aspath *aspath)
|
||||
int bgp_regexec(regex_t *regex, struct aspath *aspath)
|
||||
{
|
||||
return regexec (regex, aspath->str, 0, NULL, 0);
|
||||
return regexec(regex, aspath->str, 0, NULL, 0);
|
||||
}
|
||||
|
||||
void
|
||||
bgp_regex_free (regex_t *regex)
|
||||
void bgp_regex_free(regex_t *regex)
|
||||
{
|
||||
regfree (regex);
|
||||
XFREE (MTYPE_BGP_REGEXP, regex);
|
||||
regfree(regex);
|
||||
XFREE(MTYPE_BGP_REGEXP, regex);
|
||||
}
|
||||
|
||||
@ -24,13 +24,13 @@
|
||||
#include <zebra.h>
|
||||
|
||||
#ifdef HAVE_LIBPCREPOSIX
|
||||
# include <pcreposix.h>
|
||||
#include <pcreposix.h>
|
||||
#else
|
||||
# include <regex.h>
|
||||
#include <regex.h>
|
||||
#endif /* HAVE_LIBPCREPOSIX */
|
||||
|
||||
extern void bgp_regex_free (regex_t *regex);
|
||||
extern regex_t *bgp_regcomp (const char *str);
|
||||
extern int bgp_regexec (regex_t *regex, struct aspath *aspath);
|
||||
extern void bgp_regex_free(regex_t *regex);
|
||||
extern regex_t *bgp_regcomp(const char *str);
|
||||
extern int bgp_regexec(regex_t *regex, struct aspath *aspath);
|
||||
|
||||
#endif /* _QUAGGA_BGP_REGEX_H */
|
||||
|
||||
18080
bgpd/bgp_route.c
18080
bgpd/bgp_route.c
File diff suppressed because it is too large
Load Diff
535
bgpd/bgp_route.h
535
bgpd/bgp_route.h
@ -27,119 +27,125 @@
|
||||
struct bgp_nexthop_cache;
|
||||
struct bgp_route_evpn;
|
||||
|
||||
enum bgp_show_type
|
||||
{
|
||||
bgp_show_type_normal,
|
||||
bgp_show_type_regexp,
|
||||
bgp_show_type_prefix_list,
|
||||
bgp_show_type_filter_list,
|
||||
bgp_show_type_route_map,
|
||||
bgp_show_type_neighbor,
|
||||
bgp_show_type_cidr_only,
|
||||
bgp_show_type_prefix_longer,
|
||||
bgp_show_type_community_all,
|
||||
bgp_show_type_community,
|
||||
bgp_show_type_community_exact,
|
||||
bgp_show_type_community_list,
|
||||
bgp_show_type_community_list_exact,
|
||||
bgp_show_type_lcommunity_all,
|
||||
bgp_show_type_lcommunity,
|
||||
bgp_show_type_lcommunity_list,
|
||||
bgp_show_type_flap_statistics,
|
||||
bgp_show_type_flap_neighbor,
|
||||
bgp_show_type_dampend_paths,
|
||||
bgp_show_type_damp_neighbor
|
||||
enum bgp_show_type {
|
||||
bgp_show_type_normal,
|
||||
bgp_show_type_regexp,
|
||||
bgp_show_type_prefix_list,
|
||||
bgp_show_type_filter_list,
|
||||
bgp_show_type_route_map,
|
||||
bgp_show_type_neighbor,
|
||||
bgp_show_type_cidr_only,
|
||||
bgp_show_type_prefix_longer,
|
||||
bgp_show_type_community_all,
|
||||
bgp_show_type_community,
|
||||
bgp_show_type_community_exact,
|
||||
bgp_show_type_community_list,
|
||||
bgp_show_type_community_list_exact,
|
||||
bgp_show_type_lcommunity_all,
|
||||
bgp_show_type_lcommunity,
|
||||
bgp_show_type_lcommunity_list,
|
||||
bgp_show_type_flap_statistics,
|
||||
bgp_show_type_flap_neighbor,
|
||||
bgp_show_type_dampend_paths,
|
||||
bgp_show_type_damp_neighbor
|
||||
};
|
||||
|
||||
|
||||
#define BGP_SHOW_SCODE_HEADER "Status codes: s suppressed, d damped, "\
|
||||
"h history, * valid, > best, = multipath,\n"\
|
||||
" i internal, r RIB-failure, S Stale, R Removed\n"
|
||||
#define BGP_SHOW_SCODE_HEADER \
|
||||
"Status codes: s suppressed, d damped, " \
|
||||
"h history, * valid, > best, = multipath,\n" \
|
||||
" i internal, r RIB-failure, S Stale, R Removed\n"
|
||||
#define BGP_SHOW_OCODE_HEADER "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n"
|
||||
#define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path\n"
|
||||
|
||||
/* Ancillary information to struct bgp_info,
|
||||
/* Ancillary information to struct bgp_info,
|
||||
* used for uncommonly used data (aggregation, MPLS, etc.)
|
||||
* and lazily allocated to save memory.
|
||||
*/
|
||||
struct bgp_info_extra
|
||||
{
|
||||
/* Pointer to dampening structure. */
|
||||
struct bgp_damp_info *damp_info;
|
||||
struct bgp_info_extra {
|
||||
/* Pointer to dampening structure. */
|
||||
struct bgp_damp_info *damp_info;
|
||||
|
||||
/* This route is suppressed with aggregation. */
|
||||
int suppress;
|
||||
/* This route is suppressed with aggregation. */
|
||||
int suppress;
|
||||
|
||||
/* Nexthop reachability check. */
|
||||
u_int32_t igpmetric;
|
||||
/* Nexthop reachability check. */
|
||||
u_int32_t igpmetric;
|
||||
|
||||
/* MPLS label. */
|
||||
mpls_label_t label;
|
||||
/* MPLS label. */
|
||||
mpls_label_t label;
|
||||
|
||||
#if ENABLE_BGP_VNC
|
||||
union {
|
||||
union {
|
||||
|
||||
struct {
|
||||
void *rfapi_handle; /* export: NVE advertising this route */
|
||||
struct list *local_nexthops; /* optional, for static routes */
|
||||
} export;
|
||||
struct {
|
||||
void *rfapi_handle; /* export: NVE advertising this
|
||||
route */
|
||||
struct list *local_nexthops; /* optional, for static
|
||||
routes */
|
||||
} export;
|
||||
|
||||
struct {
|
||||
struct thread *timer;
|
||||
void *hme; /* encap monitor, if this is a VPN route */
|
||||
struct prefix_rd rd; /* import: route's route-distinguisher */
|
||||
u_char un_family; /* family of cached un address, 0 if unset */
|
||||
union {
|
||||
struct in_addr addr4;
|
||||
struct in6_addr addr6;
|
||||
} un; /* cached un address */
|
||||
time_t create_time;
|
||||
struct prefix aux_prefix; /* AFI_L2VPN: the IP addr, if family set */
|
||||
} import;
|
||||
struct {
|
||||
struct thread *timer;
|
||||
void *hme; /* encap monitor, if this is a VPN route */
|
||||
struct prefix_rd
|
||||
rd; /* import: route's route-distinguisher */
|
||||
u_char un_family; /* family of cached un address, 0 if
|
||||
unset */
|
||||
union {
|
||||
struct in_addr addr4;
|
||||
struct in6_addr addr6;
|
||||
} un; /* cached un address */
|
||||
time_t create_time;
|
||||
struct
|
||||
prefix
|
||||
aux_prefix; /* AFI_L2VPN: the IP addr,
|
||||
if family set */
|
||||
} import;
|
||||
|
||||
} vnc;
|
||||
} vnc;
|
||||
#endif
|
||||
|
||||
/* For imported routes into a VNI (or VRF), this points to the parent. */
|
||||
void *parent;
|
||||
/* For imported routes into a VNI (or VRF), this points to the parent.
|
||||
*/
|
||||
void *parent;
|
||||
};
|
||||
|
||||
struct bgp_info
|
||||
{
|
||||
/* For linked list. */
|
||||
struct bgp_info *next;
|
||||
struct bgp_info *prev;
|
||||
struct bgp_info {
|
||||
/* For linked list. */
|
||||
struct bgp_info *next;
|
||||
struct bgp_info *prev;
|
||||
|
||||
/* For nexthop linked list */
|
||||
LIST_ENTRY(bgp_info) nh_thread;
|
||||
/* For nexthop linked list */
|
||||
LIST_ENTRY(bgp_info) nh_thread;
|
||||
|
||||
/* Back pointer to the prefix node */
|
||||
struct bgp_node *net;
|
||||
/* Back pointer to the prefix node */
|
||||
struct bgp_node *net;
|
||||
|
||||
/* Back pointer to the nexthop structure */
|
||||
struct bgp_nexthop_cache *nexthop;
|
||||
/* Back pointer to the nexthop structure */
|
||||
struct bgp_nexthop_cache *nexthop;
|
||||
|
||||
/* Peer structure. */
|
||||
struct peer *peer;
|
||||
/* Peer structure. */
|
||||
struct peer *peer;
|
||||
|
||||
/* Attribute structure. */
|
||||
struct attr *attr;
|
||||
|
||||
/* Extra information */
|
||||
struct bgp_info_extra *extra;
|
||||
|
||||
/* Attribute structure. */
|
||||
struct attr *attr;
|
||||
|
||||
/* Multipath information */
|
||||
struct bgp_info_mpath *mpath;
|
||||
/* Extra information */
|
||||
struct bgp_info_extra *extra;
|
||||
|
||||
/* Uptime. */
|
||||
time_t uptime;
|
||||
|
||||
/* reference count */
|
||||
int lock;
|
||||
|
||||
/* BGP information status. */
|
||||
u_int16_t flags;
|
||||
/* Multipath information */
|
||||
struct bgp_info_mpath *mpath;
|
||||
|
||||
/* Uptime. */
|
||||
time_t uptime;
|
||||
|
||||
/* reference count */
|
||||
int lock;
|
||||
|
||||
/* BGP information status. */
|
||||
u_int16_t flags;
|
||||
#define BGP_INFO_IGP_CHANGED (1 << 0)
|
||||
#define BGP_INFO_DAMPED (1 << 1)
|
||||
#define BGP_INFO_HISTORY (1 << 2)
|
||||
@ -155,12 +161,12 @@ struct bgp_info
|
||||
#define BGP_INFO_MULTIPATH_CHG (1 << 12)
|
||||
#define BGP_INFO_RIB_ATTR_CHG (1 << 13)
|
||||
|
||||
/* BGP route type. This can be static, RIP, OSPF, BGP etc. */
|
||||
u_char type;
|
||||
/* BGP route type. This can be static, RIP, OSPF, BGP etc. */
|
||||
u_char type;
|
||||
|
||||
/* When above type is BGP. This sub type specify BGP sub type
|
||||
information. */
|
||||
u_char sub_type;
|
||||
/* When above type is BGP. This sub type specify BGP sub type
|
||||
information. */
|
||||
u_char sub_type;
|
||||
#define BGP_ROUTE_NORMAL 0
|
||||
#define BGP_ROUTE_STATIC 1
|
||||
#define BGP_ROUTE_AGGREGATE 2
|
||||
@ -169,85 +175,81 @@ struct bgp_info
|
||||
# define BGP_ROUTE_RFP 4
|
||||
#endif
|
||||
|
||||
u_short instance;
|
||||
|
||||
/* Addpath identifiers */
|
||||
u_int32_t addpath_rx_id;
|
||||
u_int32_t addpath_tx_id;
|
||||
u_short instance;
|
||||
|
||||
/* Addpath identifiers */
|
||||
u_int32_t addpath_rx_id;
|
||||
u_int32_t addpath_tx_id;
|
||||
};
|
||||
|
||||
/* Structure used in BGP path selection */
|
||||
struct bgp_info_pair
|
||||
{
|
||||
struct bgp_info *old;
|
||||
struct bgp_info *new;
|
||||
struct bgp_info_pair {
|
||||
struct bgp_info *old;
|
||||
struct bgp_info *new;
|
||||
};
|
||||
|
||||
/* BGP static route configuration. */
|
||||
struct bgp_static
|
||||
{
|
||||
/* Backdoor configuration. */
|
||||
int backdoor;
|
||||
struct bgp_static {
|
||||
/* Backdoor configuration. */
|
||||
int backdoor;
|
||||
|
||||
/* Label index configuration; applies to LU prefixes. */
|
||||
u_int32_t label_index;
|
||||
/* Label index configuration; applies to LU prefixes. */
|
||||
u_int32_t label_index;
|
||||
#define BGP_INVALID_LABEL_INDEX 0xFFFFFFFF
|
||||
|
||||
/* Import check status. */
|
||||
u_char valid;
|
||||
/* Import check status. */
|
||||
u_char valid;
|
||||
|
||||
/* IGP metric. */
|
||||
u_int32_t igpmetric;
|
||||
/* IGP metric. */
|
||||
u_int32_t igpmetric;
|
||||
|
||||
/* IGP nexthop. */
|
||||
struct in_addr igpnexthop;
|
||||
/* IGP nexthop. */
|
||||
struct in_addr igpnexthop;
|
||||
|
||||
/* Atomic set reference count (ie cause of pathlimit) */
|
||||
u_int32_t atomic;
|
||||
|
||||
/* BGP redistribute route-map. */
|
||||
struct
|
||||
{
|
||||
char *name;
|
||||
struct route_map *map;
|
||||
} rmap;
|
||||
/* Atomic set reference count (ie cause of pathlimit) */
|
||||
u_int32_t atomic;
|
||||
|
||||
/* Route Distinguisher */
|
||||
struct prefix_rd prd;
|
||||
/* BGP redistribute route-map. */
|
||||
struct {
|
||||
char *name;
|
||||
struct route_map *map;
|
||||
} rmap;
|
||||
|
||||
/* MPLS label. */
|
||||
mpls_label_t label;
|
||||
/* Route Distinguisher */
|
||||
struct prefix_rd prd;
|
||||
|
||||
/* EVPN */
|
||||
struct eth_segment_id *eth_s_id;
|
||||
struct ethaddr *router_mac;
|
||||
uint16_t encap_tunneltype;
|
||||
struct prefix gatewayIp;
|
||||
/* MPLS label. */
|
||||
mpls_label_t label;
|
||||
|
||||
/* EVPN */
|
||||
struct eth_segment_id *eth_s_id;
|
||||
struct ethaddr *router_mac;
|
||||
uint16_t encap_tunneltype;
|
||||
struct prefix gatewayIp;
|
||||
};
|
||||
|
||||
#define BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen) \
|
||||
((nhlen) < IPV4_MAX_BYTELEN ? 0 : \
|
||||
((nhlen) < IPV6_MAX_BYTELEN ? AFI_IP : AFI_IP6))
|
||||
#define BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen) \
|
||||
((nhlen) < IPV4_MAX_BYTELEN \
|
||||
? 0 \
|
||||
: ((nhlen) < IPV6_MAX_BYTELEN ? AFI_IP : AFI_IP6))
|
||||
|
||||
#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_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))
|
||||
|
||||
/* 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_INFO_UNUSEABLE \
|
||||
(BGP_INFO_HISTORY | BGP_INFO_DAMPED | BGP_INFO_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_INFO_HOLDDOWN(BI) \
|
||||
(!CHECK_FLAG((BI)->flags, BGP_INFO_VALID) \
|
||||
|| CHECK_FLAG((BI)->flags, BGP_INFO_UNUSEABLE))
|
||||
|
||||
#define DISTRIBUTE_IN_NAME(F) ((F)->dlist[FILTER_IN].name)
|
||||
#define DISTRIBUTE_IN(F) ((F)->dlist[FILTER_IN].alist)
|
||||
@ -275,168 +277,167 @@ 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_ALL, BGP_PATH_BESTPATH, BGP_PATH_MULTIPATH };
|
||||
|
||||
static inline void
|
||||
bgp_bump_version (struct bgp_node *node)
|
||||
static inline void bgp_bump_version(struct bgp_node *node)
|
||||
{
|
||||
node->version = bgp_table_next_version(bgp_node_table(node));
|
||||
node->version = bgp_table_next_version(bgp_node_table(node));
|
||||
}
|
||||
|
||||
static inline int
|
||||
bgp_fibupd_safi (safi_t safi)
|
||||
static inline int bgp_fibupd_safi(safi_t safi)
|
||||
{
|
||||
if (safi == SAFI_UNICAST ||
|
||||
safi == SAFI_MULTICAST ||
|
||||
safi == SAFI_LABELED_UNICAST)
|
||||
return 1;
|
||||
return 0;
|
||||
if (safi == SAFI_UNICAST || safi == SAFI_MULTICAST
|
||||
|| safi == SAFI_LABELED_UNICAST)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Prototypes. */
|
||||
extern void bgp_process_queue_init (void);
|
||||
extern void bgp_route_init (void);
|
||||
extern void bgp_route_finish (void);
|
||||
extern void bgp_cleanup_routes (struct bgp *);
|
||||
extern void bgp_announce_route (struct peer *, afi_t, safi_t);
|
||||
extern void bgp_process_queue_init(void);
|
||||
extern void bgp_route_init(void);
|
||||
extern void bgp_route_finish(void);
|
||||
extern void bgp_cleanup_routes(struct bgp *);
|
||||
extern void bgp_announce_route(struct peer *, afi_t, safi_t);
|
||||
extern void bgp_stop_announce_route_timer(struct peer_af *paf);
|
||||
extern void bgp_announce_route_all (struct peer *);
|
||||
extern void bgp_default_originate (struct peer *, afi_t, safi_t, int);
|
||||
extern void bgp_soft_reconfig_in (struct peer *, afi_t, safi_t);
|
||||
extern void bgp_clear_route (struct peer *, afi_t, safi_t);
|
||||
extern void bgp_clear_route_all (struct peer *);
|
||||
extern void bgp_clear_adj_in (struct peer *, afi_t, safi_t);
|
||||
extern void bgp_clear_stale_route (struct peer *, afi_t, safi_t);
|
||||
extern void bgp_announce_route_all(struct peer *);
|
||||
extern void bgp_default_originate(struct peer *, afi_t, safi_t, int);
|
||||
extern void bgp_soft_reconfig_in(struct peer *, afi_t, safi_t);
|
||||
extern void bgp_clear_route(struct peer *, afi_t, safi_t);
|
||||
extern void bgp_clear_route_all(struct peer *);
|
||||
extern void bgp_clear_adj_in(struct peer *, afi_t, safi_t);
|
||||
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 *, u_int32_t);
|
||||
extern void bgp_info_unset_flag (struct bgp_node *, struct bgp_info *, u_int32_t);
|
||||
extern void bgp_info_path_with_addpath_rx_str (struct bgp_info *ri, char *buf);
|
||||
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 *, u_int32_t);
|
||||
extern void bgp_info_unset_flag(struct bgp_node *, struct bgp_info *,
|
||||
u_int32_t);
|
||||
extern void bgp_info_path_with_addpath_rx_str(struct bgp_info *ri, char *buf);
|
||||
|
||||
extern int bgp_nlri_parse_ip (struct peer *, struct attr *, struct bgp_nlri *);
|
||||
extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *);
|
||||
|
||||
extern int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t, int);
|
||||
extern int bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int);
|
||||
|
||||
extern void bgp_redistribute_add (struct bgp *, struct prefix *, const struct in_addr *,
|
||||
const struct in6_addr *, unsigned int ifindex,
|
||||
u_int32_t, u_char, u_short, route_tag_t);
|
||||
extern void bgp_redistribute_delete (struct bgp *, struct prefix *, u_char, u_short);
|
||||
extern void bgp_redistribute_withdraw (struct bgp *, afi_t, int, u_short);
|
||||
extern void bgp_redistribute_add(struct bgp *, struct prefix *,
|
||||
const struct in_addr *,
|
||||
const struct in6_addr *, unsigned int ifindex,
|
||||
u_int32_t, u_char, u_short, route_tag_t);
|
||||
extern void bgp_redistribute_delete(struct bgp *, struct prefix *, u_char,
|
||||
u_short);
|
||||
extern void bgp_redistribute_withdraw(struct bgp *, afi_t, int, u_short);
|
||||
|
||||
extern void bgp_static_add (struct bgp *);
|
||||
extern void bgp_static_delete (struct bgp *);
|
||||
extern void bgp_static_redo_import_check (struct bgp *);
|
||||
extern void bgp_purge_static_redist_routes (struct bgp *bgp);
|
||||
extern void bgp_static_update (struct bgp *, struct prefix *, struct bgp_static *,
|
||||
afi_t, safi_t);
|
||||
extern void bgp_static_withdraw (struct bgp *, struct prefix *, afi_t, safi_t);
|
||||
|
||||
extern int bgp_static_set_safi (afi_t afi, safi_t safi, struct vty *vty, const char *,
|
||||
const char *, const char *, const char *,
|
||||
int, const char *, const char *, const char *, const char *);
|
||||
extern void bgp_static_add(struct bgp *);
|
||||
extern void bgp_static_delete(struct bgp *);
|
||||
extern void bgp_static_redo_import_check(struct bgp *);
|
||||
extern void bgp_purge_static_redist_routes(struct bgp *bgp);
|
||||
extern void bgp_static_update(struct bgp *, struct prefix *,
|
||||
struct bgp_static *, afi_t, safi_t);
|
||||
extern void bgp_static_withdraw(struct bgp *, struct prefix *, afi_t, safi_t);
|
||||
|
||||
extern int bgp_static_unset_safi (afi_t afi, safi_t safi, struct vty *, const char *,
|
||||
const char *, const char *,
|
||||
int, const char *, const char *, const char *);
|
||||
extern int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
|
||||
const char *, const char *, const char *,
|
||||
const char *, int, const char *, const char *,
|
||||
const char *, const char *);
|
||||
|
||||
extern int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *,
|
||||
const char *, const char *, const char *, int,
|
||||
const char *, const char *, const char *);
|
||||
|
||||
/* this is primarily for MPLS-VPN */
|
||||
extern int bgp_update (struct peer *, struct prefix *, u_int32_t, struct attr *,
|
||||
afi_t, safi_t, int, int, struct prefix_rd *,
|
||||
mpls_label_t *, int, struct bgp_route_evpn *);
|
||||
extern int bgp_withdraw (struct peer *, struct prefix *, u_int32_t, struct attr *,
|
||||
afi_t, safi_t, int, int, struct prefix_rd *, mpls_label_t *,
|
||||
struct bgp_route_evpn *);
|
||||
extern int bgp_update(struct peer *, struct prefix *, u_int32_t, struct attr *,
|
||||
afi_t, safi_t, int, int, struct prefix_rd *,
|
||||
mpls_label_t *, int, struct bgp_route_evpn *);
|
||||
extern int bgp_withdraw(struct peer *, struct prefix *, u_int32_t,
|
||||
struct attr *, afi_t, safi_t, int, int,
|
||||
struct prefix_rd *, mpls_label_t *,
|
||||
struct bgp_route_evpn *);
|
||||
|
||||
/* for bgp_nexthop and bgp_damp */
|
||||
extern void bgp_process (struct bgp *, struct bgp_node *, afi_t, safi_t);
|
||||
extern void bgp_process(struct bgp *, struct bgp_node *, afi_t, safi_t);
|
||||
|
||||
/*
|
||||
* Add an end-of-initial-update marker to the process queue. This is just a
|
||||
* queue element with NULL bgp node.
|
||||
*/
|
||||
extern void bgp_add_eoiu_mark (struct bgp *);
|
||||
extern int bgp_config_write_table_map (struct vty *, struct bgp *, afi_t, safi_t,
|
||||
int *);
|
||||
extern int bgp_config_write_network (struct vty *, struct bgp *, afi_t, safi_t, int *);
|
||||
extern int bgp_config_write_distance (struct vty *, struct bgp *, afi_t, safi_t, int *);
|
||||
extern void bgp_add_eoiu_mark(struct bgp *);
|
||||
extern int bgp_config_write_table_map(struct vty *, struct bgp *, afi_t, safi_t,
|
||||
int *);
|
||||
extern int bgp_config_write_network(struct vty *, struct bgp *, afi_t, safi_t,
|
||||
int *);
|
||||
extern int bgp_config_write_distance(struct vty *, struct bgp *, afi_t, safi_t,
|
||||
int *);
|
||||
|
||||
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 *, 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 u_char bgp_distance_apply (struct prefix *, struct bgp_info *, afi_t, safi_t, struct bgp *);
|
||||
extern u_char bgp_distance_apply(struct prefix *, struct bgp_info *, afi_t,
|
||||
safi_t, struct bgp *);
|
||||
|
||||
extern afi_t bgp_node_afi (struct vty *);
|
||||
extern safi_t bgp_node_safi (struct vty *);
|
||||
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, u_short instance, struct peer *peer,
|
||||
struct attr *attr, struct bgp_node *rn);
|
||||
extern struct bgp_info *info_make(int type, int sub_type, u_short instance,
|
||||
struct peer *peer, struct attr *attr,
|
||||
struct bgp_node *rn);
|
||||
|
||||
extern void route_vty_out (struct vty *, struct prefix *, struct bgp_info *, int, safi_t, json_object *);
|
||||
extern void route_vty_out_tag (struct vty *, struct prefix *, struct bgp_info *, int, safi_t, json_object *);
|
||||
extern void route_vty_out_tmp (struct vty *, struct prefix *, struct attr *, safi_t, u_char, json_object *);
|
||||
extern void
|
||||
route_vty_out_overlay (struct vty *vty, struct prefix *p,
|
||||
struct bgp_info *binfo, int display, json_object *json);
|
||||
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_tmp(struct vty *, struct prefix *, struct attr *,
|
||||
safi_t, u_char, json_object *);
|
||||
extern void route_vty_out_overlay(struct vty *vty, struct prefix *p,
|
||||
struct bgp_info *binfo, int display,
|
||||
json_object *json);
|
||||
|
||||
extern int
|
||||
subgroup_process_announce_selected (struct update_subgroup *subgrp,
|
||||
struct bgp_info *selected,
|
||||
struct bgp_node *rn,
|
||||
u_int32_t addpath_tx_id);
|
||||
extern int subgroup_process_announce_selected(struct update_subgroup *subgrp,
|
||||
struct bgp_info *selected,
|
||||
struct bgp_node *rn,
|
||||
u_int32_t addpath_tx_id);
|
||||
|
||||
extern int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri,
|
||||
struct update_subgroup *subgrp,
|
||||
struct prefix *p, struct attr *attr);
|
||||
|
||||
extern void bgp_peer_clear_node_queue_drain_immediate (struct peer *peer);
|
||||
extern void bgp_process_queues_drain_immediate (void);
|
||||
extern void bgp_peer_clear_node_queue_drain_immediate(struct peer *peer);
|
||||
extern void bgp_process_queues_drain_immediate(void);
|
||||
|
||||
/* for encap/vpn */
|
||||
extern struct bgp_node *
|
||||
bgp_afi_node_get (struct bgp_table *, afi_t , safi_t , struct prefix *,
|
||||
struct prefix_rd *);
|
||||
extern struct bgp_node *
|
||||
bgp_afi_node_lookup (struct bgp_table *table, afi_t afi, safi_t safi,
|
||||
struct prefix *p, struct prefix_rd *prd);
|
||||
extern struct bgp_info *bgp_info_new (void);
|
||||
extern void bgp_info_restore (struct bgp_node *, struct bgp_info *);
|
||||
extern struct bgp_node *bgp_afi_node_get(struct bgp_table *, afi_t, safi_t,
|
||||
struct prefix *, struct prefix_rd *);
|
||||
extern struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
|
||||
safi_t safi, struct prefix *p,
|
||||
struct prefix_rd *prd);
|
||||
extern struct bgp_info *bgp_info_new(void);
|
||||
extern void bgp_info_restore(struct bgp_node *, struct bgp_info *);
|
||||
|
||||
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_info_cmp_compatible(struct bgp *, struct bgp_info *,
|
||||
struct bgp_info *, char *pfx_buf, afi_t afi,
|
||||
safi_t safi);
|
||||
|
||||
extern void
|
||||
bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
|
||||
struct bgp_maxpaths_cfg *mpath_cfg,
|
||||
struct bgp_info_pair *result,
|
||||
afi_t afi, safi_t safi);
|
||||
extern void bgp_zebra_clear_route_change_flags (struct bgp_node *rn);
|
||||
extern int
|
||||
bgp_zebra_has_route_changed (struct bgp_node *rn, struct bgp_info *selected);
|
||||
extern void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
|
||||
struct bgp_maxpaths_cfg *mpath_cfg,
|
||||
struct bgp_info_pair *result, afi_t afi,
|
||||
safi_t safi);
|
||||
extern void bgp_zebra_clear_route_change_flags(struct bgp_node *rn);
|
||||
extern int bgp_zebra_has_route_changed(struct bgp_node *rn,
|
||||
struct bgp_info *selected);
|
||||
|
||||
extern void
|
||||
route_vty_out_detail_header (struct vty *vty, struct bgp *bgp,
|
||||
struct bgp_node *rn,
|
||||
struct prefix_rd *prd, afi_t afi, safi_t safi,
|
||||
json_object *json);
|
||||
extern void
|
||||
route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
|
||||
struct bgp_info *binfo, afi_t afi, safi_t safi,
|
||||
json_object *json_paths);
|
||||
extern void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
|
||||
struct bgp_node *rn,
|
||||
struct prefix_rd *prd, afi_t afi,
|
||||
safi_t safi, json_object *json);
|
||||
extern void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
|
||||
struct prefix *p, struct bgp_info *binfo,
|
||||
afi_t afi, safi_t safi,
|
||||
json_object *json_paths);
|
||||
#endif /* _QUAGGA_BGP_ROUTE_H */
|
||||
|
||||
5263
bgpd/bgp_routemap.c
5263
bgpd/bgp_routemap.c
File diff suppressed because it is too large
Load Diff
1393
bgpd/bgp_snmp.c
1393
bgpd/bgp_snmp.c
File diff suppressed because it is too large
Load Diff
@ -30,91 +30,82 @@
|
||||
#include "bgpd/bgpd.h"
|
||||
#include "bgpd/bgp_table.h"
|
||||
|
||||
void
|
||||
bgp_table_lock (struct bgp_table *rt)
|
||||
void bgp_table_lock(struct bgp_table *rt)
|
||||
{
|
||||
rt->lock++;
|
||||
rt->lock++;
|
||||
}
|
||||
|
||||
void
|
||||
bgp_table_unlock (struct bgp_table *rt)
|
||||
void bgp_table_unlock(struct bgp_table *rt)
|
||||
{
|
||||
assert (rt->lock > 0);
|
||||
rt->lock--;
|
||||
assert(rt->lock > 0);
|
||||
rt->lock--;
|
||||
|
||||
if (rt->lock != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (rt->lock != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
route_table_finish (rt->route_table);
|
||||
rt->route_table = NULL;
|
||||
route_table_finish(rt->route_table);
|
||||
rt->route_table = NULL;
|
||||
|
||||
XFREE (MTYPE_BGP_TABLE, rt);
|
||||
XFREE(MTYPE_BGP_TABLE, rt);
|
||||
}
|
||||
|
||||
void
|
||||
bgp_table_finish (struct bgp_table **rt)
|
||||
void bgp_table_finish(struct bgp_table **rt)
|
||||
{
|
||||
if (*rt != NULL)
|
||||
{
|
||||
bgp_table_unlock(*rt);
|
||||
*rt = NULL;
|
||||
}
|
||||
if (*rt != NULL) {
|
||||
bgp_table_unlock(*rt);
|
||||
*rt = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_node_create
|
||||
*/
|
||||
static struct route_node *
|
||||
bgp_node_create (route_table_delegate_t *delegate, struct route_table *table)
|
||||
static struct route_node *bgp_node_create(route_table_delegate_t *delegate,
|
||||
struct route_table *table)
|
||||
{
|
||||
struct bgp_node *node;
|
||||
node = XCALLOC (MTYPE_BGP_NODE, sizeof (struct bgp_node));
|
||||
return bgp_node_to_rnode (node);
|
||||
struct bgp_node *node;
|
||||
node = XCALLOC(MTYPE_BGP_NODE, sizeof(struct bgp_node));
|
||||
return bgp_node_to_rnode(node);
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_node_destroy
|
||||
*/
|
||||
static void
|
||||
bgp_node_destroy (route_table_delegate_t *delegate,
|
||||
struct route_table *table, struct route_node *node)
|
||||
static void bgp_node_destroy(route_table_delegate_t *delegate,
|
||||
struct route_table *table, struct route_node *node)
|
||||
{
|
||||
struct bgp_node *bgp_node;
|
||||
bgp_node = bgp_node_from_rnode (node);
|
||||
XFREE (MTYPE_BGP_NODE, bgp_node);
|
||||
struct bgp_node *bgp_node;
|
||||
bgp_node = bgp_node_from_rnode(node);
|
||||
XFREE(MTYPE_BGP_NODE, bgp_node);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function vector to customize the behavior of the route table
|
||||
* library for BGP route tables.
|
||||
*/
|
||||
route_table_delegate_t bgp_table_delegate = {
|
||||
.create_node = bgp_node_create,
|
||||
.destroy_node = bgp_node_destroy
|
||||
};
|
||||
route_table_delegate_t bgp_table_delegate = {.create_node = bgp_node_create,
|
||||
.destroy_node = bgp_node_destroy};
|
||||
|
||||
/*
|
||||
* bgp_table_init
|
||||
*/
|
||||
struct bgp_table *
|
||||
bgp_table_init (afi_t afi, safi_t safi)
|
||||
struct bgp_table *bgp_table_init(afi_t afi, safi_t safi)
|
||||
{
|
||||
struct bgp_table *rt;
|
||||
struct bgp_table *rt;
|
||||
|
||||
rt = XCALLOC (MTYPE_BGP_TABLE, sizeof (struct bgp_table));
|
||||
rt = XCALLOC(MTYPE_BGP_TABLE, sizeof(struct bgp_table));
|
||||
|
||||
rt->route_table = route_table_init_with_delegate (&bgp_table_delegate);
|
||||
rt->route_table = route_table_init_with_delegate(&bgp_table_delegate);
|
||||
|
||||
/*
|
||||
* Set up back pointer to bgp_table.
|
||||
*/
|
||||
rt->route_table->info = rt;
|
||||
/*
|
||||
* Set up back pointer to bgp_table.
|
||||
*/
|
||||
rt->route_table->info = rt;
|
||||
|
||||
bgp_table_lock (rt);
|
||||
rt->afi = afi;
|
||||
rt->safi = safi;
|
||||
bgp_table_lock(rt);
|
||||
rt->afi = afi;
|
||||
rt->safi = safi;
|
||||
|
||||
return rt;
|
||||
return rt;
|
||||
}
|
||||
|
||||
210
bgpd/bgp_table.h
210
bgpd/bgp_table.h
@ -24,40 +24,38 @@
|
||||
#include "mpls.h"
|
||||
#include "table.h"
|
||||
|
||||
struct bgp_table
|
||||
{
|
||||
/* afi/safi of this table */
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
|
||||
int lock;
|
||||
struct bgp_table {
|
||||
/* afi/safi of this table */
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
|
||||
struct route_table *route_table;
|
||||
uint64_t version;
|
||||
int lock;
|
||||
|
||||
struct route_table *route_table;
|
||||
uint64_t version;
|
||||
};
|
||||
|
||||
struct bgp_node
|
||||
{
|
||||
/*
|
||||
* CAUTION
|
||||
*
|
||||
* These fields must be the very first fields in this structure.
|
||||
*
|
||||
* @see bgp_node_to_rnode
|
||||
* @see bgp_node_from_rnode
|
||||
*/
|
||||
ROUTE_NODE_FIELDS
|
||||
struct bgp_node {
|
||||
/*
|
||||
* CAUTION
|
||||
*
|
||||
* These fields must be the very first fields in this structure.
|
||||
*
|
||||
* @see bgp_node_to_rnode
|
||||
* @see bgp_node_from_rnode
|
||||
*/
|
||||
ROUTE_NODE_FIELDS
|
||||
|
||||
struct bgp_adj_out *adj_out;
|
||||
struct bgp_adj_out *adj_out;
|
||||
|
||||
struct bgp_adj_in *adj_in;
|
||||
struct bgp_adj_in *adj_in;
|
||||
|
||||
struct bgp_node *prn;
|
||||
struct bgp_node *prn;
|
||||
|
||||
mpls_label_t local_label;
|
||||
mpls_label_t local_label;
|
||||
|
||||
uint64_t version;
|
||||
u_char flags;
|
||||
uint64_t version;
|
||||
u_char flags;
|
||||
#define BGP_NODE_PROCESS_SCHEDULED (1 << 0)
|
||||
#define BGP_NODE_USER_CLEAR (1 << 1)
|
||||
#define BGP_NODE_LABEL_CHANGED (1 << 2)
|
||||
@ -66,19 +64,18 @@ struct bgp_node
|
||||
|
||||
/*
|
||||
* bgp_table_iter_t
|
||||
*
|
||||
*
|
||||
* Structure that holds state for iterating over a bgp table.
|
||||
*/
|
||||
typedef struct bgp_table_iter_t_
|
||||
{
|
||||
struct bgp_table *table;
|
||||
route_table_iter_t rt_iter;
|
||||
typedef struct bgp_table_iter_t_ {
|
||||
struct bgp_table *table;
|
||||
route_table_iter_t rt_iter;
|
||||
} bgp_table_iter_t;
|
||||
|
||||
extern struct bgp_table *bgp_table_init (afi_t, safi_t);
|
||||
extern void bgp_table_lock (struct bgp_table *);
|
||||
extern void bgp_table_unlock (struct bgp_table *);
|
||||
extern void bgp_table_finish (struct bgp_table **);
|
||||
extern struct bgp_table *bgp_table_init(afi_t, safi_t);
|
||||
extern void bgp_table_lock(struct bgp_table *);
|
||||
extern void bgp_table_unlock(struct bgp_table *);
|
||||
extern void bgp_table_finish(struct bgp_table **);
|
||||
|
||||
|
||||
/*
|
||||
@ -86,10 +83,9 @@ extern void bgp_table_finish (struct bgp_table **);
|
||||
*
|
||||
* Returns the bgp_node structure corresponding to a route_node.
|
||||
*/
|
||||
static inline struct bgp_node *
|
||||
bgp_node_from_rnode (struct route_node *rnode)
|
||||
static inline struct bgp_node *bgp_node_from_rnode(struct route_node *rnode)
|
||||
{
|
||||
return (struct bgp_node *) rnode;
|
||||
return (struct bgp_node *)rnode;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -97,10 +93,9 @@ bgp_node_from_rnode (struct route_node *rnode)
|
||||
*
|
||||
* Returns the route_node structure corresponding to a bgp_node.
|
||||
*/
|
||||
static inline struct route_node *
|
||||
bgp_node_to_rnode (struct bgp_node *node)
|
||||
static inline struct route_node *bgp_node_to_rnode(struct bgp_node *node)
|
||||
{
|
||||
return (struct route_node *) node;
|
||||
return (struct route_node *)node;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -108,10 +103,9 @@ bgp_node_to_rnode (struct bgp_node *node)
|
||||
*
|
||||
* Returns the bgp_table that the given node is in.
|
||||
*/
|
||||
static inline struct bgp_table *
|
||||
bgp_node_table (struct bgp_node *node)
|
||||
static inline struct bgp_table *bgp_node_table(struct bgp_node *node)
|
||||
{
|
||||
return bgp_node_to_rnode (node)->table->info;
|
||||
return bgp_node_to_rnode(node)->table->info;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -119,19 +113,17 @@ bgp_node_table (struct bgp_node *node)
|
||||
*
|
||||
* Gets the parent node of the given node without locking it.
|
||||
*/
|
||||
static inline struct bgp_node *
|
||||
bgp_node_parent_nolock (struct bgp_node *node)
|
||||
static inline struct bgp_node *bgp_node_parent_nolock(struct bgp_node *node)
|
||||
{
|
||||
return bgp_node_from_rnode (node->parent);
|
||||
return bgp_node_from_rnode(node->parent);
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_unlock_node
|
||||
*/
|
||||
static inline void
|
||||
bgp_unlock_node (struct bgp_node *node)
|
||||
static inline void bgp_unlock_node(struct bgp_node *node)
|
||||
{
|
||||
route_unlock_node (bgp_node_to_rnode (node));
|
||||
route_unlock_node(bgp_node_to_rnode(node));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -142,183 +134,173 @@ bgp_unlock_node (struct bgp_node *node)
|
||||
* @see bgp_table_top
|
||||
*/
|
||||
static inline struct bgp_node *
|
||||
bgp_table_top_nolock (const struct bgp_table *const table)
|
||||
bgp_table_top_nolock(const struct bgp_table *const table)
|
||||
{
|
||||
return bgp_node_from_rnode (table->route_table->top);
|
||||
return bgp_node_from_rnode(table->route_table->top);
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_table_top
|
||||
*/
|
||||
static inline struct bgp_node *
|
||||
bgp_table_top (const struct bgp_table *const table)
|
||||
bgp_table_top(const struct bgp_table *const table)
|
||||
{
|
||||
return bgp_node_from_rnode (route_top (table->route_table));
|
||||
return bgp_node_from_rnode(route_top(table->route_table));
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_route_next
|
||||
*/
|
||||
static inline struct bgp_node *
|
||||
bgp_route_next (struct bgp_node *node)
|
||||
static inline struct bgp_node *bgp_route_next(struct bgp_node *node)
|
||||
{
|
||||
return bgp_node_from_rnode (route_next (bgp_node_to_rnode (node)));
|
||||
return bgp_node_from_rnode(route_next(bgp_node_to_rnode(node)));
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_route_next_until
|
||||
*/
|
||||
static inline struct bgp_node *
|
||||
bgp_route_next_until (struct bgp_node *node, struct bgp_node *limit)
|
||||
static inline struct bgp_node *bgp_route_next_until(struct bgp_node *node,
|
||||
struct bgp_node *limit)
|
||||
{
|
||||
struct route_node *rnode;
|
||||
struct route_node *rnode;
|
||||
|
||||
rnode = route_next_until (bgp_node_to_rnode (node),
|
||||
bgp_node_to_rnode (limit));
|
||||
return bgp_node_from_rnode (rnode);
|
||||
rnode = route_next_until(bgp_node_to_rnode(node),
|
||||
bgp_node_to_rnode(limit));
|
||||
return bgp_node_from_rnode(rnode);
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_node_get
|
||||
*/
|
||||
static inline struct bgp_node *
|
||||
bgp_node_get (struct bgp_table *const table, struct prefix *p)
|
||||
static inline struct bgp_node *bgp_node_get(struct bgp_table *const table,
|
||||
struct prefix *p)
|
||||
{
|
||||
return bgp_node_from_rnode (route_node_get (table->route_table, p));
|
||||
return bgp_node_from_rnode(route_node_get(table->route_table, p));
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_node_lookup
|
||||
*/
|
||||
static inline struct bgp_node *
|
||||
bgp_node_lookup (const struct bgp_table *const table, struct prefix *p)
|
||||
bgp_node_lookup(const struct bgp_table *const table, struct prefix *p)
|
||||
{
|
||||
return bgp_node_from_rnode (route_node_lookup (table->route_table, p));
|
||||
return bgp_node_from_rnode(route_node_lookup(table->route_table, p));
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_lock_node
|
||||
*/
|
||||
static inline struct bgp_node *
|
||||
bgp_lock_node (struct bgp_node *node)
|
||||
static inline struct bgp_node *bgp_lock_node(struct bgp_node *node)
|
||||
{
|
||||
return bgp_node_from_rnode (route_lock_node (bgp_node_to_rnode (node)));
|
||||
return bgp_node_from_rnode(route_lock_node(bgp_node_to_rnode(node)));
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_node_match
|
||||
*/
|
||||
static inline struct bgp_node *
|
||||
bgp_node_match (const struct bgp_table *table, struct prefix *p)
|
||||
static inline struct bgp_node *bgp_node_match(const struct bgp_table *table,
|
||||
struct prefix *p)
|
||||
{
|
||||
return bgp_node_from_rnode (route_node_match (table->route_table, p));
|
||||
return bgp_node_from_rnode(route_node_match(table->route_table, p));
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_node_match_ipv4
|
||||
*/
|
||||
static inline struct bgp_node *
|
||||
bgp_node_match_ipv4 (const struct bgp_table *table, struct in_addr *addr)
|
||||
bgp_node_match_ipv4(const struct bgp_table *table, struct in_addr *addr)
|
||||
{
|
||||
return bgp_node_from_rnode (route_node_match_ipv4 (table->route_table,
|
||||
addr));
|
||||
return bgp_node_from_rnode(
|
||||
route_node_match_ipv4(table->route_table, addr));
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_node_match_ipv6
|
||||
*/
|
||||
static inline struct bgp_node *
|
||||
bgp_node_match_ipv6 (const struct bgp_table *table, struct in6_addr *addr)
|
||||
bgp_node_match_ipv6(const struct bgp_table *table, struct in6_addr *addr)
|
||||
{
|
||||
return bgp_node_from_rnode (route_node_match_ipv6 (table->route_table,
|
||||
addr));
|
||||
return bgp_node_from_rnode(
|
||||
route_node_match_ipv6(table->route_table, addr));
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
bgp_table_count (const struct bgp_table *const table)
|
||||
static inline unsigned long bgp_table_count(const struct bgp_table *const table)
|
||||
{
|
||||
return route_table_count (table->route_table);
|
||||
return route_table_count(table->route_table);
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_table_get_next
|
||||
*/
|
||||
static inline struct bgp_node *
|
||||
bgp_table_get_next (const struct bgp_table *table, struct prefix *p)
|
||||
static inline struct bgp_node *bgp_table_get_next(const struct bgp_table *table,
|
||||
struct prefix *p)
|
||||
{
|
||||
return bgp_node_from_rnode (route_table_get_next (table->route_table, p));
|
||||
return bgp_node_from_rnode(route_table_get_next(table->route_table, p));
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_table_iter_init
|
||||
*/
|
||||
static inline void
|
||||
bgp_table_iter_init (bgp_table_iter_t * iter, struct bgp_table *table)
|
||||
static inline void bgp_table_iter_init(bgp_table_iter_t *iter,
|
||||
struct bgp_table *table)
|
||||
{
|
||||
bgp_table_lock (table);
|
||||
iter->table = table;
|
||||
route_table_iter_init (&iter->rt_iter, table->route_table);
|
||||
bgp_table_lock(table);
|
||||
iter->table = table;
|
||||
route_table_iter_init(&iter->rt_iter, table->route_table);
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_table_iter_next
|
||||
*/
|
||||
static inline struct bgp_node *
|
||||
bgp_table_iter_next (bgp_table_iter_t * iter)
|
||||
static inline struct bgp_node *bgp_table_iter_next(bgp_table_iter_t *iter)
|
||||
{
|
||||
return bgp_node_from_rnode (route_table_iter_next (&iter->rt_iter));
|
||||
return bgp_node_from_rnode(route_table_iter_next(&iter->rt_iter));
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_table_iter_cleanup
|
||||
*/
|
||||
static inline void
|
||||
bgp_table_iter_cleanup (bgp_table_iter_t * iter)
|
||||
static inline void bgp_table_iter_cleanup(bgp_table_iter_t *iter)
|
||||
{
|
||||
route_table_iter_cleanup (&iter->rt_iter);
|
||||
bgp_table_unlock (iter->table);
|
||||
iter->table = NULL;
|
||||
route_table_iter_cleanup(&iter->rt_iter);
|
||||
bgp_table_unlock(iter->table);
|
||||
iter->table = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_table_iter_pause
|
||||
*/
|
||||
static inline void
|
||||
bgp_table_iter_pause (bgp_table_iter_t * iter)
|
||||
static inline void bgp_table_iter_pause(bgp_table_iter_t *iter)
|
||||
{
|
||||
route_table_iter_pause (&iter->rt_iter);
|
||||
route_table_iter_pause(&iter->rt_iter);
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_table_iter_is_done
|
||||
*/
|
||||
static inline int
|
||||
bgp_table_iter_is_done (bgp_table_iter_t * iter)
|
||||
static inline int bgp_table_iter_is_done(bgp_table_iter_t *iter)
|
||||
{
|
||||
return route_table_iter_is_done (&iter->rt_iter);
|
||||
return route_table_iter_is_done(&iter->rt_iter);
|
||||
}
|
||||
|
||||
/*
|
||||
* bgp_table_iter_started
|
||||
*/
|
||||
static inline int
|
||||
bgp_table_iter_started (bgp_table_iter_t * iter)
|
||||
static inline int bgp_table_iter_started(bgp_table_iter_t *iter)
|
||||
{
|
||||
return route_table_iter_started (&iter->rt_iter);
|
||||
return route_table_iter_started(&iter->rt_iter);
|
||||
}
|
||||
|
||||
/* This would benefit from a real atomic operation...
|
||||
* until then. */
|
||||
static inline uint64_t
|
||||
bgp_table_next_version (struct bgp_table *table)
|
||||
static inline uint64_t bgp_table_next_version(struct bgp_table *table)
|
||||
{
|
||||
return ++table->version;
|
||||
return ++table->version;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
bgp_table_version (struct bgp_table *table)
|
||||
static inline uint64_t bgp_table_version(struct bgp_table *table)
|
||||
{
|
||||
return table->version;
|
||||
return table->version;
|
||||
}
|
||||
|
||||
#endif /* _QUAGGA_BGP_TABLE_H */
|
||||
|
||||
2526
bgpd/bgp_updgrp.c
2526
bgpd/bgp_updgrp.c
File diff suppressed because it is too large
Load Diff
@ -31,46 +31,34 @@
|
||||
|
||||
#define BGP_DEFAULT_SUBGROUP_COALESCE_TIME 200
|
||||
|
||||
#define PEER_UPDGRP_FLAGS (PEER_FLAG_LOCAL_AS_NO_PREPEND | \
|
||||
PEER_FLAG_LOCAL_AS_REPLACE_AS)
|
||||
#define PEER_UPDGRP_FLAGS \
|
||||
(PEER_FLAG_LOCAL_AS_NO_PREPEND | PEER_FLAG_LOCAL_AS_REPLACE_AS)
|
||||
|
||||
#define PEER_UPDGRP_AF_FLAGS (PEER_FLAG_SEND_COMMUNITY | \
|
||||
PEER_FLAG_SEND_EXT_COMMUNITY | \
|
||||
PEER_FLAG_DEFAULT_ORIGINATE | \
|
||||
PEER_FLAG_REFLECTOR_CLIENT | \
|
||||
PEER_FLAG_RSERVER_CLIENT | \
|
||||
PEER_FLAG_NEXTHOP_SELF | \
|
||||
PEER_FLAG_NEXTHOP_UNCHANGED | \
|
||||
PEER_FLAG_FORCE_NEXTHOP_SELF | \
|
||||
PEER_FLAG_AS_PATH_UNCHANGED | \
|
||||
PEER_FLAG_MED_UNCHANGED | \
|
||||
PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED | \
|
||||
PEER_FLAG_REMOVE_PRIVATE_AS | \
|
||||
PEER_FLAG_REMOVE_PRIVATE_AS_ALL | \
|
||||
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE | \
|
||||
PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE | \
|
||||
PEER_FLAG_ADDPATH_TX_ALL_PATHS | \
|
||||
PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS | \
|
||||
PEER_FLAG_AS_OVERRIDE)
|
||||
#define PEER_UPDGRP_AF_FLAGS \
|
||||
(PEER_FLAG_SEND_COMMUNITY | PEER_FLAG_SEND_EXT_COMMUNITY \
|
||||
| PEER_FLAG_DEFAULT_ORIGINATE | PEER_FLAG_REFLECTOR_CLIENT \
|
||||
| PEER_FLAG_RSERVER_CLIENT | PEER_FLAG_NEXTHOP_SELF \
|
||||
| PEER_FLAG_NEXTHOP_UNCHANGED | PEER_FLAG_FORCE_NEXTHOP_SELF \
|
||||
| PEER_FLAG_AS_PATH_UNCHANGED | PEER_FLAG_MED_UNCHANGED \
|
||||
| PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED | PEER_FLAG_REMOVE_PRIVATE_AS \
|
||||
| PEER_FLAG_REMOVE_PRIVATE_AS_ALL \
|
||||
| PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE \
|
||||
| PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE \
|
||||
| PEER_FLAG_ADDPATH_TX_ALL_PATHS \
|
||||
| PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS | PEER_FLAG_AS_OVERRIDE)
|
||||
|
||||
#define PEER_UPDGRP_CAP_FLAGS (PEER_CAP_AS4_RCV)
|
||||
|
||||
#define PEER_UPDGRP_AF_CAP_FLAGS (PEER_CAP_ORF_PREFIX_SM_RCV | \
|
||||
PEER_CAP_ORF_PREFIX_SM_OLD_RCV |\
|
||||
PEER_CAP_ADDPATH_AF_TX_ADV |\
|
||||
PEER_CAP_ADDPATH_AF_RX_RCV |\
|
||||
PEER_CAP_ENHE_AF_NEGO)
|
||||
#define PEER_UPDGRP_AF_CAP_FLAGS \
|
||||
(PEER_CAP_ORF_PREFIX_SM_RCV | PEER_CAP_ORF_PREFIX_SM_OLD_RCV \
|
||||
| PEER_CAP_ADDPATH_AF_TX_ADV | PEER_CAP_ADDPATH_AF_RX_RCV \
|
||||
| PEER_CAP_ENHE_AF_NEGO)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BGP_ATTR_VEC_NH = 0,
|
||||
BGP_ATTR_VEC_MAX
|
||||
} bpacket_attr_vec_type;
|
||||
typedef enum { BGP_ATTR_VEC_NH = 0, BGP_ATTR_VEC_MAX } bpacket_attr_vec_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u_int32_t flags;
|
||||
unsigned long offset;
|
||||
typedef struct {
|
||||
u_int32_t flags;
|
||||
unsigned long offset;
|
||||
} bpacket_attr_vec;
|
||||
|
||||
#define BPKT_ATTRVEC_FLAGS_UPDATED (1 << 0)
|
||||
@ -81,28 +69,25 @@ typedef struct
|
||||
#define BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED (1 << 5)
|
||||
#define BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED (1 << 6)
|
||||
|
||||
typedef struct bpacket_attr_vec_arr
|
||||
{
|
||||
bpacket_attr_vec entries[BGP_ATTR_VEC_MAX];
|
||||
typedef struct bpacket_attr_vec_arr {
|
||||
bpacket_attr_vec entries[BGP_ATTR_VEC_MAX];
|
||||
} bpacket_attr_vec_arr;
|
||||
|
||||
struct bpacket
|
||||
{
|
||||
/* for being part of an update subgroup's message list */
|
||||
TAILQ_ENTRY (bpacket) pkt_train;
|
||||
struct bpacket {
|
||||
/* for being part of an update subgroup's message list */
|
||||
TAILQ_ENTRY(bpacket) pkt_train;
|
||||
|
||||
/* list of peers (well, peer_afs) that the packet needs to be sent to */
|
||||
LIST_HEAD (pkt_peer_list, peer_af) peers;
|
||||
/* list of peers (well, peer_afs) that the packet needs to be sent to */
|
||||
LIST_HEAD(pkt_peer_list, peer_af) peers;
|
||||
|
||||
struct stream *buffer;
|
||||
bpacket_attr_vec_arr arr;
|
||||
struct stream *buffer;
|
||||
bpacket_attr_vec_arr arr;
|
||||
|
||||
unsigned int ver;
|
||||
unsigned int ver;
|
||||
};
|
||||
|
||||
struct bpacket_queue
|
||||
{
|
||||
TAILQ_HEAD (pkt_queue, bpacket) pkts;
|
||||
struct bpacket_queue {
|
||||
TAILQ_HEAD(pkt_queue, bpacket) pkts;
|
||||
|
||||
#if 0
|
||||
/* A dummy packet that is used to thread all peers that have
|
||||
@ -110,149 +95,146 @@ struct bpacket_queue
|
||||
struct bpacket sentinel;
|
||||
#endif
|
||||
|
||||
unsigned int conf_max_count;
|
||||
unsigned int curr_count;
|
||||
unsigned int hwm_count;
|
||||
unsigned int max_count_reached_count;
|
||||
unsigned int conf_max_count;
|
||||
unsigned int curr_count;
|
||||
unsigned int hwm_count;
|
||||
unsigned int max_count_reached_count;
|
||||
};
|
||||
|
||||
struct update_group
|
||||
{
|
||||
/* back pointer to the BGP instance */
|
||||
struct bgp *bgp;
|
||||
struct update_group {
|
||||
/* back pointer to the BGP instance */
|
||||
struct bgp *bgp;
|
||||
|
||||
/* list of subgroups that belong to the update group */
|
||||
LIST_HEAD (subgrp_list, update_subgroup) subgrps;
|
||||
/* list of subgroups that belong to the update group */
|
||||
LIST_HEAD(subgrp_list, update_subgroup) subgrps;
|
||||
|
||||
/* lazy way to store configuration common to all peers
|
||||
hash function will compute from this data */
|
||||
struct peer *conf;
|
||||
/* lazy way to store configuration common to all peers
|
||||
hash function will compute from this data */
|
||||
struct peer *conf;
|
||||
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
int afid;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
int afid;
|
||||
|
||||
uint64_t id;
|
||||
time_t uptime;
|
||||
uint64_t id;
|
||||
time_t uptime;
|
||||
|
||||
u_int32_t join_events;
|
||||
u_int32_t prune_events;
|
||||
u_int32_t merge_events;
|
||||
u_int32_t updgrp_switch_events;
|
||||
u_int32_t peer_refreshes_combined;
|
||||
u_int32_t adj_count;
|
||||
u_int32_t split_events;
|
||||
u_int32_t merge_checks_triggered;
|
||||
u_int32_t join_events;
|
||||
u_int32_t prune_events;
|
||||
u_int32_t merge_events;
|
||||
u_int32_t updgrp_switch_events;
|
||||
u_int32_t peer_refreshes_combined;
|
||||
u_int32_t adj_count;
|
||||
u_int32_t split_events;
|
||||
u_int32_t merge_checks_triggered;
|
||||
|
||||
u_int32_t subgrps_created;
|
||||
u_int32_t subgrps_deleted;
|
||||
u_int32_t subgrps_created;
|
||||
u_int32_t subgrps_deleted;
|
||||
|
||||
u_int32_t num_dbg_en_peers;
|
||||
u_int32_t num_dbg_en_peers;
|
||||
};
|
||||
|
||||
/*
|
||||
* Shorthand for a global statistics counter.
|
||||
*/
|
||||
#define UPDGRP_GLOBAL_STAT(updgrp, stat) \
|
||||
((updgrp)->bgp->update_group_stats.stat)
|
||||
#define UPDGRP_GLOBAL_STAT(updgrp, stat) \
|
||||
((updgrp)->bgp->update_group_stats.stat)
|
||||
|
||||
/*
|
||||
* Add the given value to a counter on an update group and the bgp
|
||||
* instance.
|
||||
*/
|
||||
#define UPDGRP_INCR_STAT_BY(updgrp, stat, value) \
|
||||
do { \
|
||||
(updgrp)->stat += (value); \
|
||||
UPDGRP_GLOBAL_STAT(updgrp, stat) += (value); \
|
||||
} while (0)
|
||||
#define UPDGRP_INCR_STAT_BY(updgrp, stat, value) \
|
||||
do { \
|
||||
(updgrp)->stat += (value); \
|
||||
UPDGRP_GLOBAL_STAT(updgrp, stat) += (value); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Increment a counter on a update group and its parent structures.
|
||||
*/
|
||||
#define UPDGRP_INCR_STAT(subgrp, stat) \
|
||||
UPDGRP_INCR_STAT_BY(subgrp, stat, 1)
|
||||
#define UPDGRP_INCR_STAT(subgrp, stat) UPDGRP_INCR_STAT_BY(subgrp, stat, 1)
|
||||
|
||||
struct update_subgroup
|
||||
{
|
||||
/* back pointer to the parent update group */
|
||||
struct update_group *update_group;
|
||||
struct update_subgroup {
|
||||
/* back pointer to the parent update group */
|
||||
struct update_group *update_group;
|
||||
|
||||
/* list of peers that belong to the subgroup */
|
||||
LIST_HEAD (peer_list, peer_af) peers;
|
||||
int peer_count;
|
||||
/* list of peers that belong to the subgroup */
|
||||
LIST_HEAD(peer_list, peer_af) peers;
|
||||
int peer_count;
|
||||
|
||||
/* for being part of an update group's subgroup list */
|
||||
LIST_ENTRY (update_subgroup) updgrp_train;
|
||||
/* for being part of an update group's subgroup list */
|
||||
LIST_ENTRY(update_subgroup) updgrp_train;
|
||||
|
||||
struct bpacket_queue pkt_queue;
|
||||
struct bpacket_queue pkt_queue;
|
||||
|
||||
/*
|
||||
* List of adj-out structures for this subgroup.
|
||||
* It essentially represents the snapshot of every prefix that
|
||||
* has been advertised to the members of the subgroup
|
||||
*/
|
||||
TAILQ_HEAD (adjout_queue, bgp_adj_out) adjq;
|
||||
/*
|
||||
* List of adj-out structures for this subgroup.
|
||||
* It essentially represents the snapshot of every prefix that
|
||||
* has been advertised to the members of the subgroup
|
||||
*/
|
||||
TAILQ_HEAD(adjout_queue, bgp_adj_out) adjq;
|
||||
|
||||
/* packet buffer for update generation */
|
||||
struct stream *work;
|
||||
/* packet buffer for update generation */
|
||||
struct stream *work;
|
||||
|
||||
/* We use a separate stream to encode MP_REACH_NLRI for efficient
|
||||
* NLRI packing. peer->work stores all the other attributes. The
|
||||
* actual packet is then constructed by concatenating the two.
|
||||
*/
|
||||
struct stream *scratch;
|
||||
/* We use a separate stream to encode MP_REACH_NLRI for efficient
|
||||
* NLRI packing. peer->work stores all the other attributes. The
|
||||
* actual packet is then constructed by concatenating the two.
|
||||
*/
|
||||
struct stream *scratch;
|
||||
|
||||
/* synchronization list and time */
|
||||
struct bgp_synchronize *sync;
|
||||
/* synchronization list and time */
|
||||
struct bgp_synchronize *sync;
|
||||
|
||||
/* send prefix count */
|
||||
unsigned long scount;
|
||||
/* send prefix count */
|
||||
unsigned long scount;
|
||||
|
||||
/* announcement attribute hash */
|
||||
struct hash *hash;
|
||||
/* announcement attribute hash */
|
||||
struct hash *hash;
|
||||
|
||||
struct thread *t_coalesce;
|
||||
u_int32_t v_coalesce;
|
||||
struct thread *t_coalesce;
|
||||
u_int32_t v_coalesce;
|
||||
|
||||
struct thread *t_merge_check;
|
||||
struct thread *t_merge_check;
|
||||
|
||||
/* table version that the subgroup has caught up to. */
|
||||
uint64_t version;
|
||||
/* table version that the subgroup has caught up to. */
|
||||
uint64_t version;
|
||||
|
||||
/* version maintained to record adj changes */
|
||||
uint64_t adj_version;
|
||||
/* version maintained to record adj changes */
|
||||
uint64_t adj_version;
|
||||
|
||||
time_t uptime;
|
||||
time_t uptime;
|
||||
|
||||
/*
|
||||
* Identifying information about the subgroup that this subgroup was split
|
||||
* from, if any.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
uint64_t update_group_id;
|
||||
uint64_t subgroup_id;
|
||||
} split_from;
|
||||
/*
|
||||
* Identifying information about the subgroup that this subgroup was
|
||||
* split
|
||||
* from, if any.
|
||||
*/
|
||||
struct {
|
||||
uint64_t update_group_id;
|
||||
uint64_t subgroup_id;
|
||||
} split_from;
|
||||
|
||||
u_int32_t join_events;
|
||||
u_int32_t prune_events;
|
||||
u_int32_t join_events;
|
||||
u_int32_t prune_events;
|
||||
|
||||
/*
|
||||
* This is bumped up when another subgroup merges into this one.
|
||||
*/
|
||||
u_int32_t merge_events;
|
||||
u_int32_t updgrp_switch_events;
|
||||
u_int32_t peer_refreshes_combined;
|
||||
u_int32_t adj_count;
|
||||
u_int32_t split_events;
|
||||
u_int32_t merge_checks_triggered;
|
||||
/*
|
||||
* This is bumped up when another subgroup merges into this one.
|
||||
*/
|
||||
u_int32_t merge_events;
|
||||
u_int32_t updgrp_switch_events;
|
||||
u_int32_t peer_refreshes_combined;
|
||||
u_int32_t adj_count;
|
||||
u_int32_t split_events;
|
||||
u_int32_t merge_checks_triggered;
|
||||
|
||||
uint64_t id;
|
||||
uint64_t id;
|
||||
|
||||
u_int16_t sflags;
|
||||
u_int16_t sflags;
|
||||
|
||||
/* Subgroup flags, see below */
|
||||
u_int16_t flags;
|
||||
/* Subgroup flags, see below */
|
||||
u_int16_t flags;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -267,43 +249,41 @@ struct update_subgroup
|
||||
* Add the given value to the specified counter on a subgroup and its
|
||||
* parent structures.
|
||||
*/
|
||||
#define SUBGRP_INCR_STAT_BY(subgrp, stat, value) \
|
||||
do { \
|
||||
(subgrp)->stat += (value); \
|
||||
if ((subgrp)->update_group) \
|
||||
UPDGRP_INCR_STAT_BY((subgrp)->update_group, stat, value); \
|
||||
} while (0)
|
||||
#define SUBGRP_INCR_STAT_BY(subgrp, stat, value) \
|
||||
do { \
|
||||
(subgrp)->stat += (value); \
|
||||
if ((subgrp)->update_group) \
|
||||
UPDGRP_INCR_STAT_BY((subgrp)->update_group, stat, \
|
||||
value); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Increment a counter on a subgroup and its parent structures.
|
||||
*/
|
||||
#define SUBGRP_INCR_STAT(subgrp, stat) \
|
||||
SUBGRP_INCR_STAT_BY(subgrp, stat, 1)
|
||||
#define SUBGRP_INCR_STAT(subgrp, stat) SUBGRP_INCR_STAT_BY(subgrp, stat, 1)
|
||||
|
||||
/*
|
||||
* Decrement a counter on a subgroup and its parent structures.
|
||||
*/
|
||||
#define SUBGRP_DECR_STAT(subgrp, stat) \
|
||||
SUBGRP_INCR_STAT_BY(subgrp, stat, -1)
|
||||
#define SUBGRP_DECR_STAT(subgrp, stat) SUBGRP_INCR_STAT_BY(subgrp, stat, -1)
|
||||
|
||||
|
||||
typedef int (*updgrp_walkcb) (struct update_group * updgrp, void *ctx);
|
||||
typedef int (*updgrp_walkcb)(struct update_group *updgrp, void *ctx);
|
||||
|
||||
/* really a private structure */
|
||||
struct updwalk_context
|
||||
{
|
||||
struct vty *vty;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
uint64_t updgrp_id;
|
||||
uint64_t subgrp_id;
|
||||
bgp_policy_type_e policy_type;
|
||||
const char *policy_name;
|
||||
int policy_event_start_flag;
|
||||
int policy_route_update;
|
||||
updgrp_walkcb cb;
|
||||
void *context;
|
||||
u_int8_t flags;
|
||||
struct updwalk_context {
|
||||
struct vty *vty;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
uint64_t updgrp_id;
|
||||
uint64_t subgrp_id;
|
||||
bgp_policy_type_e policy_type;
|
||||
const char *policy_name;
|
||||
int policy_event_start_flag;
|
||||
int policy_route_update;
|
||||
updgrp_walkcb cb;
|
||||
void *context;
|
||||
u_int8_t flags;
|
||||
|
||||
#define UPDWALK_FLAGS_ADVQUEUE (1 << 0)
|
||||
#define UPDWALK_FLAGS_ADVERTISED (1 << 1)
|
||||
@ -321,8 +301,7 @@ struct updwalk_context
|
||||
#define UPDGRP_AFI(u) ((u)->afi)
|
||||
#define UPDGRP_SAFI(u) ((u)->safi)
|
||||
#define UPDGRP_INST(u) ((u)->bgp)
|
||||
#define UPDGRP_AFFLAGS(u) \
|
||||
((u)->conf->af_flags[UPDGRP_AFI(u)][UPDGRP_SAFI(u)])
|
||||
#define UPDGRP_AFFLAGS(u) ((u)->conf->af_flags[UPDGRP_AFI(u)][UPDGRP_SAFI(u)])
|
||||
#define UPDGRP_DBG_ON(u) ((u)->num_dbg_en_peers)
|
||||
#define UPDGRP_PEER_DBG_EN(u) (((u)->num_dbg_en_peers)++)
|
||||
#define UPDGRP_PEER_DBG_DIS(u) (((u)->num_dbg_en_peers)--)
|
||||
@ -341,149 +320,137 @@ struct updwalk_context
|
||||
/*
|
||||
* Walk all subgroups in an update group.
|
||||
*/
|
||||
#define UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) \
|
||||
LIST_FOREACH(subgrp, &((updgrp)->subgrps), updgrp_train)
|
||||
#define UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) \
|
||||
LIST_FOREACH(subgrp, &((updgrp)->subgrps), updgrp_train)
|
||||
|
||||
#define UPDGRP_FOREACH_SUBGRP_SAFE(updgrp, subgrp, tmp_subgrp) \
|
||||
LIST_FOREACH_SAFE(subgrp, &((updgrp)->subgrps), updgrp_train, tmp_subgrp)
|
||||
#define UPDGRP_FOREACH_SUBGRP_SAFE(updgrp, subgrp, tmp_subgrp) \
|
||||
LIST_FOREACH_SAFE(subgrp, &((updgrp)->subgrps), updgrp_train, \
|
||||
tmp_subgrp)
|
||||
|
||||
#define SUBGRP_FOREACH_PEER(subgrp, paf) \
|
||||
LIST_FOREACH(paf, &(subgrp->peers), subgrp_train)
|
||||
#define SUBGRP_FOREACH_PEER(subgrp, paf) \
|
||||
LIST_FOREACH(paf, &(subgrp->peers), subgrp_train)
|
||||
|
||||
#define SUBGRP_FOREACH_PEER_SAFE(subgrp, paf, temp_paf) \
|
||||
LIST_FOREACH_SAFE(paf, &(subgrp->peers), subgrp_train, temp_paf)
|
||||
#define SUBGRP_FOREACH_PEER_SAFE(subgrp, paf, temp_paf) \
|
||||
LIST_FOREACH_SAFE(paf, &(subgrp->peers), subgrp_train, temp_paf)
|
||||
|
||||
#define SUBGRP_FOREACH_ADJ(subgrp, adj) \
|
||||
TAILQ_FOREACH(adj, &(subgrp->adjq), subgrp_adj_train)
|
||||
#define SUBGRP_FOREACH_ADJ(subgrp, adj) \
|
||||
TAILQ_FOREACH(adj, &(subgrp->adjq), subgrp_adj_train)
|
||||
|
||||
#define SUBGRP_FOREACH_ADJ_SAFE(subgrp, adj, adj_temp) \
|
||||
TAILQ_FOREACH_SAFE(adj, &(subgrp->adjq), subgrp_adj_train, adj_temp)
|
||||
#define SUBGRP_FOREACH_ADJ_SAFE(subgrp, adj, adj_temp) \
|
||||
TAILQ_FOREACH_SAFE(adj, &(subgrp->adjq), subgrp_adj_train, adj_temp)
|
||||
|
||||
/* Prototypes. */
|
||||
/* bgp_updgrp.c */
|
||||
extern void update_bgp_group_init (struct bgp *);
|
||||
extern void udpate_bgp_group_free (struct bgp *);
|
||||
extern void update_bgp_group_init(struct bgp *);
|
||||
extern void udpate_bgp_group_free(struct bgp *);
|
||||
|
||||
extern void
|
||||
update_group_show (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, uint64_t subgrp_id);
|
||||
extern void update_group_show_stats (struct bgp *bgp, struct vty *vty);
|
||||
extern void update_group_adjust_peer (struct peer_af *paf);
|
||||
extern int update_group_adjust_soloness (struct peer *peer, int set);
|
||||
extern void update_group_show(struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
struct vty *vty, uint64_t subgrp_id);
|
||||
extern void update_group_show_stats(struct bgp *bgp, struct vty *vty);
|
||||
extern void update_group_adjust_peer(struct peer_af *paf);
|
||||
extern int update_group_adjust_soloness(struct peer *peer, int set);
|
||||
|
||||
extern void
|
||||
update_subgroup_remove_peer (struct update_subgroup *, struct peer_af *);
|
||||
extern struct bgp_table *update_subgroup_rib (struct update_subgroup *);
|
||||
extern void
|
||||
update_subgroup_split_peer (struct peer_af *, struct update_group *);
|
||||
extern void update_subgroup_remove_peer(struct update_subgroup *,
|
||||
struct peer_af *);
|
||||
extern struct bgp_table *update_subgroup_rib(struct update_subgroup *);
|
||||
extern void update_subgroup_split_peer(struct peer_af *, struct update_group *);
|
||||
extern int update_subgroup_check_merge(struct update_subgroup *, const char *);
|
||||
extern int update_subgroup_trigger_merge_check(struct update_subgroup *,
|
||||
int force);
|
||||
extern void update_group_policy_update(struct bgp *bgp, bgp_policy_type_e ptype,
|
||||
const char *pname, int route_update,
|
||||
int start_event);
|
||||
extern void update_group_af_walk(struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
updgrp_walkcb cb, void *ctx);
|
||||
extern void update_group_walk(struct bgp *bgp, updgrp_walkcb cb, void *ctx);
|
||||
extern void update_group_periodic_merge(struct bgp *bgp);
|
||||
extern int
|
||||
update_subgroup_check_merge (struct update_subgroup *, const char *);
|
||||
extern int
|
||||
update_subgroup_trigger_merge_check (struct update_subgroup *,
|
||||
int force);
|
||||
extern void update_group_policy_update (struct bgp *bgp,
|
||||
bgp_policy_type_e ptype, const char *pname,
|
||||
int route_update, int start_event);
|
||||
extern void update_group_af_walk (struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
updgrp_walkcb cb, void *ctx);
|
||||
extern void update_group_walk (struct bgp *bgp, updgrp_walkcb cb, void *ctx);
|
||||
extern void update_group_periodic_merge (struct bgp *bgp);
|
||||
extern int update_group_refresh_default_originate_route_map (struct thread *thread);
|
||||
extern void update_group_start_advtimer (struct bgp *bgp);
|
||||
update_group_refresh_default_originate_route_map(struct thread *thread);
|
||||
extern void update_group_start_advtimer(struct bgp *bgp);
|
||||
|
||||
extern void update_subgroup_inherit_info (struct update_subgroup *to,
|
||||
struct update_subgroup *from);
|
||||
extern void update_subgroup_inherit_info(struct update_subgroup *to,
|
||||
struct update_subgroup *from);
|
||||
|
||||
/* bgp_updgrp_packet.c */
|
||||
extern struct bpacket *bpacket_alloc (void);
|
||||
extern void bpacket_free (struct bpacket *pkt);
|
||||
extern void bpacket_queue_init (struct bpacket_queue *q);
|
||||
extern void bpacket_queue_cleanup (struct bpacket_queue *q);
|
||||
extern void bpacket_queue_sanity_check (struct bpacket_queue *q);
|
||||
extern struct bpacket *bpacket_queue_add (struct bpacket_queue *q,
|
||||
struct stream *s,
|
||||
struct bpacket_attr_vec_arr
|
||||
*vecarr);
|
||||
struct bpacket *bpacket_queue_remove (struct bpacket_queue *q);
|
||||
extern struct bpacket *bpacket_queue_first (struct bpacket_queue *q);
|
||||
struct bpacket *bpacket_queue_last (struct bpacket_queue *q);
|
||||
unsigned int bpacket_queue_length (struct bpacket_queue *q);
|
||||
unsigned int bpacket_queue_hwm_length (struct bpacket_queue *q);
|
||||
int bpacket_queue_is_full (struct bgp *bgp, struct bpacket_queue *q);
|
||||
extern void bpacket_queue_advance_peer (struct peer_af *paf);
|
||||
extern void bpacket_queue_remove_peer (struct peer_af *paf);
|
||||
extern void bpacket_add_peer (struct bpacket *pkt, struct peer_af *paf);
|
||||
unsigned int bpacket_queue_virtual_length (struct peer_af *paf);
|
||||
extern void bpacket_queue_show_vty (struct bpacket_queue *q, struct vty *vty);
|
||||
int subgroup_packets_to_build (struct update_subgroup *subgrp);
|
||||
extern struct bpacket *subgroup_update_packet (struct update_subgroup *s);
|
||||
extern struct bpacket *subgroup_withdraw_packet (struct update_subgroup *s);
|
||||
extern struct stream *bpacket_reformat_for_peer (struct bpacket *pkt,
|
||||
struct peer_af *paf);
|
||||
extern void bpacket_attr_vec_arr_reset (struct bpacket_attr_vec_arr *vecarr);
|
||||
extern void bpacket_attr_vec_arr_set_vec (struct bpacket_attr_vec_arr *vecarr,
|
||||
bpacket_attr_vec_type type,
|
||||
struct stream *s,
|
||||
struct attr *attr);
|
||||
extern void
|
||||
subgroup_default_update_packet (struct update_subgroup *subgrp,
|
||||
struct attr *attr, struct peer *from);
|
||||
extern void subgroup_default_withdraw_packet (struct update_subgroup *subgrp);
|
||||
extern struct bpacket *bpacket_alloc(void);
|
||||
extern void bpacket_free(struct bpacket *pkt);
|
||||
extern void bpacket_queue_init(struct bpacket_queue *q);
|
||||
extern void bpacket_queue_cleanup(struct bpacket_queue *q);
|
||||
extern void bpacket_queue_sanity_check(struct bpacket_queue *q);
|
||||
extern struct bpacket *bpacket_queue_add(struct bpacket_queue *q,
|
||||
struct stream *s,
|
||||
struct bpacket_attr_vec_arr *vecarr);
|
||||
struct bpacket *bpacket_queue_remove(struct bpacket_queue *q);
|
||||
extern struct bpacket *bpacket_queue_first(struct bpacket_queue *q);
|
||||
struct bpacket *bpacket_queue_last(struct bpacket_queue *q);
|
||||
unsigned int bpacket_queue_length(struct bpacket_queue *q);
|
||||
unsigned int bpacket_queue_hwm_length(struct bpacket_queue *q);
|
||||
int bpacket_queue_is_full(struct bgp *bgp, struct bpacket_queue *q);
|
||||
extern void bpacket_queue_advance_peer(struct peer_af *paf);
|
||||
extern void bpacket_queue_remove_peer(struct peer_af *paf);
|
||||
extern void bpacket_add_peer(struct bpacket *pkt, struct peer_af *paf);
|
||||
unsigned int bpacket_queue_virtual_length(struct peer_af *paf);
|
||||
extern void bpacket_queue_show_vty(struct bpacket_queue *q, struct vty *vty);
|
||||
int subgroup_packets_to_build(struct update_subgroup *subgrp);
|
||||
extern struct bpacket *subgroup_update_packet(struct update_subgroup *s);
|
||||
extern struct bpacket *subgroup_withdraw_packet(struct update_subgroup *s);
|
||||
extern struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
|
||||
struct peer_af *paf);
|
||||
extern void bpacket_attr_vec_arr_reset(struct bpacket_attr_vec_arr *vecarr);
|
||||
extern void bpacket_attr_vec_arr_set_vec(struct bpacket_attr_vec_arr *vecarr,
|
||||
bpacket_attr_vec_type type,
|
||||
struct stream *s, struct attr *attr);
|
||||
extern void subgroup_default_update_packet(struct update_subgroup *subgrp,
|
||||
struct attr *attr,
|
||||
struct peer *from);
|
||||
extern void subgroup_default_withdraw_packet(struct update_subgroup *subgrp);
|
||||
|
||||
/* bgp_updgrp_adv.c */
|
||||
extern struct bgp_advertise *bgp_advertise_clean_subgroup (struct
|
||||
update_subgroup
|
||||
*subgrp,
|
||||
struct bgp_adj_out
|
||||
*adj);
|
||||
extern void update_group_show_adj_queue (struct bgp *bgp, afi_t afi,
|
||||
extern struct bgp_advertise *
|
||||
bgp_advertise_clean_subgroup(struct update_subgroup *subgrp,
|
||||
struct bgp_adj_out *adj);
|
||||
extern void update_group_show_adj_queue(struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
struct vty *vty, uint64_t id);
|
||||
extern void update_group_show_advertised(struct bgp *bgp, afi_t afi,
|
||||
safi_t safi, struct vty *vty,
|
||||
uint64_t id);
|
||||
extern void update_group_show_advertised (struct bgp *bgp, afi_t afi,
|
||||
safi_t safi, struct vty *vty,
|
||||
uint64_t id);
|
||||
extern void update_group_show_packet_queue (struct bgp *bgp, afi_t afi,
|
||||
safi_t safi, struct vty *vty,
|
||||
uint64_t id);
|
||||
extern void subgroup_announce_route (struct update_subgroup *subgrp);
|
||||
extern void subgroup_announce_all (struct update_subgroup *subgrp);
|
||||
extern void update_group_show_packet_queue(struct bgp *bgp, afi_t afi,
|
||||
safi_t safi, struct vty *vty,
|
||||
uint64_t id);
|
||||
extern void subgroup_announce_route(struct update_subgroup *subgrp);
|
||||
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);
|
||||
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);
|
||||
extern void peer_af_announce_route (struct peer_af *paf, int combine);
|
||||
extern struct bgp_adj_out *bgp_adj_out_alloc (struct update_subgroup *subgrp,
|
||||
struct bgp_node *rn,
|
||||
u_int32_t addpath_tx_id);
|
||||
extern void bgp_adj_out_remove_subgroup (struct bgp_node *rn,
|
||||
struct bgp_adj_out *adj,
|
||||
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);
|
||||
extern void
|
||||
bgp_adj_out_unset_subgroup (struct bgp_node *rn,
|
||||
struct update_subgroup *subgrp,
|
||||
char withdraw,
|
||||
u_int32_t addpath_tx_id);
|
||||
void
|
||||
subgroup_announce_table (struct update_subgroup *subgrp,
|
||||
struct bgp_table *table);
|
||||
extern void
|
||||
subgroup_trigger_write (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);
|
||||
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);
|
||||
extern void peer_af_announce_route(struct peer_af *paf, int combine);
|
||||
extern struct bgp_adj_out *bgp_adj_out_alloc(struct update_subgroup *subgrp,
|
||||
struct bgp_node *rn,
|
||||
u_int32_t addpath_tx_id);
|
||||
extern void bgp_adj_out_remove_subgroup(struct bgp_node *rn,
|
||||
struct bgp_adj_out *adj,
|
||||
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);
|
||||
extern void bgp_adj_out_unset_subgroup(struct bgp_node *rn,
|
||||
struct update_subgroup *subgrp,
|
||||
char withdraw, u_int32_t addpath_tx_id);
|
||||
void subgroup_announce_table(struct update_subgroup *subgrp,
|
||||
struct bgp_table *table);
|
||||
extern void subgroup_trigger_write(struct update_subgroup *subgrp);
|
||||
|
||||
extern int
|
||||
update_group_clear_update_dbg (struct update_group *updgrp, void *arg);
|
||||
extern int update_group_clear_update_dbg(struct update_group *updgrp,
|
||||
void *arg);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
/*
|
||||
* Inline functions
|
||||
@ -492,18 +459,17 @@ extern int bgp_addpath_tx_path (struct peer *peer, afi_t afi, safi_t safi,
|
||||
/*
|
||||
* bpacket_queue_is_empty
|
||||
*/
|
||||
static inline int
|
||||
bpacket_queue_is_empty (struct bpacket_queue *queue)
|
||||
static inline int bpacket_queue_is_empty(struct bpacket_queue *queue)
|
||||
{
|
||||
|
||||
/*
|
||||
* The packet queue is empty if it only contains a sentinel.
|
||||
*/
|
||||
if (queue->curr_count != 1)
|
||||
return 0;
|
||||
/*
|
||||
* The packet queue is empty if it only contains a sentinel.
|
||||
*/
|
||||
if (queue->curr_count != 1)
|
||||
return 0;
|
||||
|
||||
assert (bpacket_queue_first (queue)->buffer == NULL);
|
||||
return 1;
|
||||
assert(bpacket_queue_first(queue)->buffer == NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -511,10 +477,9 @@ bpacket_queue_is_empty (struct bpacket_queue *queue)
|
||||
*
|
||||
* Returns the packet after the given packet in a bpacket queue.
|
||||
*/
|
||||
static inline struct bpacket *
|
||||
bpacket_next (struct bpacket *pkt)
|
||||
static inline struct bpacket *bpacket_next(struct bpacket *pkt)
|
||||
{
|
||||
return TAILQ_NEXT (pkt, pkt_train);
|
||||
return TAILQ_NEXT(pkt, pkt_train);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -522,18 +487,16 @@ bpacket_next (struct bpacket *pkt)
|
||||
*
|
||||
* Adjust all peer_af structures for the given peer.
|
||||
*/
|
||||
static inline void
|
||||
update_group_adjust_peer_afs (struct peer *peer)
|
||||
static inline void update_group_adjust_peer_afs(struct peer *peer)
|
||||
{
|
||||
struct peer_af *paf;
|
||||
int afidx;
|
||||
struct peer_af *paf;
|
||||
int afidx;
|
||||
|
||||
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++)
|
||||
{
|
||||
paf = peer->peer_af_array[afidx];
|
||||
if (paf != NULL)
|
||||
update_group_adjust_peer (paf);
|
||||
}
|
||||
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
|
||||
paf = peer->peer_af_array[afidx];
|
||||
if (paf != NULL)
|
||||
update_group_adjust_peer(paf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -541,53 +504,51 @@ update_group_adjust_peer_afs (struct peer *peer)
|
||||
*
|
||||
* Remove all peer_af structures for the given peer from their subgroups.
|
||||
*/
|
||||
static inline void
|
||||
update_group_remove_peer_afs (struct peer *peer)
|
||||
static inline void update_group_remove_peer_afs(struct peer *peer)
|
||||
{
|
||||
struct peer_af *paf;
|
||||
int afidx;
|
||||
struct peer_af *paf;
|
||||
int afidx;
|
||||
|
||||
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++)
|
||||
{
|
||||
paf = peer->peer_af_array[afidx];
|
||||
if (paf != NULL)
|
||||
update_subgroup_remove_peer (PAF_SUBGRP (paf), paf);
|
||||
}
|
||||
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
|
||||
paf = peer->peer_af_array[afidx];
|
||||
if (paf != NULL)
|
||||
update_subgroup_remove_peer(PAF_SUBGRP(paf), paf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* update_subgroup_needs_refresh
|
||||
*/
|
||||
static inline int
|
||||
update_subgroup_needs_refresh (const struct update_subgroup *subgrp)
|
||||
update_subgroup_needs_refresh(const struct update_subgroup *subgrp)
|
||||
{
|
||||
if (CHECK_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
if (CHECK_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* update_subgroup_set_needs_refresh
|
||||
*/
|
||||
static inline void
|
||||
update_subgroup_set_needs_refresh (struct update_subgroup *subgrp, int value)
|
||||
update_subgroup_set_needs_refresh(struct update_subgroup *subgrp, int value)
|
||||
{
|
||||
if (value)
|
||||
SET_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
|
||||
else
|
||||
UNSET_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
|
||||
if (value)
|
||||
SET_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
|
||||
else
|
||||
UNSET_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
|
||||
}
|
||||
|
||||
static inline struct update_subgroup *
|
||||
peer_subgroup (struct peer *peer, afi_t afi, safi_t safi)
|
||||
static inline struct update_subgroup *peer_subgroup(struct peer *peer,
|
||||
afi_t afi, safi_t safi)
|
||||
{
|
||||
struct peer_af *paf;
|
||||
struct peer_af *paf;
|
||||
|
||||
paf = peer_af_find (peer, afi, safi);
|
||||
if (paf)
|
||||
return PAF_SUBGRP (paf);
|
||||
return NULL;
|
||||
paf = peer_af_find(peer, afi, safi);
|
||||
if (paf)
|
||||
return PAF_SUBGRP(paf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -595,34 +556,30 @@ peer_subgroup (struct peer *peer, afi_t afi, safi_t safi)
|
||||
*
|
||||
* Adjust all peer_af structures for the given peer.
|
||||
*/
|
||||
static inline void
|
||||
bgp_announce_peer (struct peer *peer)
|
||||
static inline void bgp_announce_peer(struct peer *peer)
|
||||
{
|
||||
struct peer_af *paf;
|
||||
int afidx;
|
||||
struct peer_af *paf;
|
||||
int afidx;
|
||||
|
||||
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++)
|
||||
{
|
||||
paf = peer->peer_af_array[afidx];
|
||||
if (paf != NULL)
|
||||
subgroup_announce_all (PAF_SUBGRP (paf));
|
||||
}
|
||||
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
|
||||
paf = peer->peer_af_array[afidx];
|
||||
if (paf != NULL)
|
||||
subgroup_announce_all(PAF_SUBGRP(paf));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* advertise_list_is_empty
|
||||
*/
|
||||
static inline int
|
||||
advertise_list_is_empty (struct update_subgroup *subgrp)
|
||||
static inline int advertise_list_is_empty(struct update_subgroup *subgrp)
|
||||
{
|
||||
if (!BGP_ADV_FIFO_EMPTY (&subgrp->sync->update) ||
|
||||
!BGP_ADV_FIFO_EMPTY (&subgrp->sync->withdraw) ||
|
||||
!BGP_ADV_FIFO_EMPTY (&subgrp->sync->withdraw_low))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (!BGP_ADV_FIFO_EMPTY(&subgrp->sync->update)
|
||||
|| !BGP_ADV_FIFO_EMPTY(&subgrp->sync->withdraw)
|
||||
|| !BGP_ADV_FIFO_EMPTY(&subgrp->sync->withdraw_low)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* _QUAGGA_BGP_UPDGRP_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright 2015-2016, LabN Consulting, L.L.C.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@ -21,20 +21,20 @@
|
||||
|
||||
#if ENABLE_BGP_VNC
|
||||
typedef enum {
|
||||
BGP_VNC_SUBTLV_TYPE_LIFETIME=1,
|
||||
BGP_VNC_SUBTLV_TYPE_RFPOPTION=2, /* deprecated */
|
||||
BGP_VNC_SUBTLV_TYPE_LIFETIME = 1,
|
||||
BGP_VNC_SUBTLV_TYPE_RFPOPTION = 2, /* deprecated */
|
||||
} bgp_vnc_subtlv_types;
|
||||
|
||||
/*
|
||||
* VNC Attribute subtlvs
|
||||
*/
|
||||
struct bgp_vnc_subtlv_lifetime {
|
||||
uint32_t lifetime;
|
||||
uint32_t lifetime;
|
||||
};
|
||||
|
||||
struct bgp_vnc_subtlv_unaddr {
|
||||
struct prefix un_address; /* IPv4 or IPv6; pfx length ignored */
|
||||
struct prefix un_address; /* IPv4 or IPv6; pfx length ignored */
|
||||
};
|
||||
|
||||
#endif /* ENABLE_BGP_VNC */
|
||||
#endif /* ENABLE_BGP_VNC */
|
||||
#endif /* _QUAGGA_BGP_VNC_TYPES_H */
|
||||
|
||||
341
bgpd/bgp_vpn.c
341
bgpd/bgp_vpn.c
@ -30,170 +30,221 @@
|
||||
#include "bgpd/bgp_mplsvpn.h"
|
||||
#include "bgpd/bgp_vpn.h"
|
||||
|
||||
int
|
||||
show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd,
|
||||
afi_t afi, safi_t safi, u_char use_json)
|
||||
int show_adj_route_vpn(struct vty *vty, struct peer *peer,
|
||||
struct prefix_rd *prd, afi_t afi, safi_t safi,
|
||||
u_char use_json)
|
||||
{
|
||||
struct bgp *bgp;
|
||||
struct bgp_table *table;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_node *rm;
|
||||
struct attr *attr;
|
||||
int rd_header;
|
||||
int header = 1;
|
||||
json_object *json = NULL;
|
||||
json_object *json_scode = NULL;
|
||||
json_object *json_ocode = NULL;
|
||||
json_object *json_routes = NULL;
|
||||
json_object *json_array = NULL;
|
||||
struct bgp *bgp;
|
||||
struct bgp_table *table;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_node *rm;
|
||||
struct attr *attr;
|
||||
int rd_header;
|
||||
int header = 1;
|
||||
json_object *json = NULL;
|
||||
json_object *json_scode = NULL;
|
||||
json_object *json_ocode = NULL;
|
||||
json_object *json_routes = NULL;
|
||||
json_object *json_array = NULL;
|
||||
|
||||
bgp = bgp_get_default ();
|
||||
if (bgp == NULL)
|
||||
{
|
||||
if (!use_json)
|
||||
vty_out (vty, "No BGP process is configured\n");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
bgp = bgp_get_default();
|
||||
if (bgp == NULL) {
|
||||
if (!use_json)
|
||||
vty_out(vty, "No BGP process is configured\n");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (use_json)
|
||||
{
|
||||
json_scode = json_object_new_object();
|
||||
json_ocode = json_object_new_object();
|
||||
json_routes = json_object_new_object();
|
||||
json = json_object_new_object();
|
||||
if (use_json) {
|
||||
json_scode = json_object_new_object();
|
||||
json_ocode = json_object_new_object();
|
||||
json_routes = json_object_new_object();
|
||||
json = json_object_new_object();
|
||||
|
||||
json_object_string_add(json_scode, "suppressed", "s");
|
||||
json_object_string_add(json_scode, "damped", "d");
|
||||
json_object_string_add(json_scode, "history", "h");
|
||||
json_object_string_add(json_scode, "valid", "*");
|
||||
json_object_string_add(json_scode, "best", ">");
|
||||
json_object_string_add(json_scode, "internal", "i");
|
||||
json_object_string_add(json_scode, "suppressed", "s");
|
||||
json_object_string_add(json_scode, "damped", "d");
|
||||
json_object_string_add(json_scode, "history", "h");
|
||||
json_object_string_add(json_scode, "valid", "*");
|
||||
json_object_string_add(json_scode, "best", ">");
|
||||
json_object_string_add(json_scode, "internal", "i");
|
||||
|
||||
json_object_string_add(json_ocode, "igp", "i");
|
||||
json_object_string_add(json_ocode, "egp", "e");
|
||||
json_object_string_add(json_ocode, "incomplete", "?");
|
||||
}
|
||||
json_object_string_add(json_ocode, "igp", "i");
|
||||
json_object_string_add(json_ocode, "egp", "e");
|
||||
json_object_string_add(json_ocode, "incomplete", "?");
|
||||
}
|
||||
|
||||
for (rn = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); rn;
|
||||
rn = bgp_route_next (rn))
|
||||
{
|
||||
if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
|
||||
continue;
|
||||
for (rn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn;
|
||||
rn = bgp_route_next(rn)) {
|
||||
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
|
||||
continue;
|
||||
|
||||
if ((table = rn->info) != NULL)
|
||||
{
|
||||
if (use_json)
|
||||
json_array = json_object_new_array();
|
||||
else
|
||||
json_array = NULL;
|
||||
if ((table = rn->info) != NULL) {
|
||||
if (use_json)
|
||||
json_array = json_object_new_array();
|
||||
else
|
||||
json_array = NULL;
|
||||
|
||||
rd_header = 1;
|
||||
rd_header = 1;
|
||||
|
||||
for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
|
||||
{
|
||||
if ((attr = rm->info) != NULL)
|
||||
{
|
||||
if (header)
|
||||
{
|
||||
if (use_json)
|
||||
{
|
||||
json_object_int_add(json, "bgpTableVersion", 0);
|
||||
json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id));
|
||||
json_object_object_add(json, "bgpStatusCodes", json_scode);
|
||||
json_object_object_add(json, "bgpOriginCodes", json_ocode);
|
||||
}
|
||||
else
|
||||
{
|
||||
vty_out (vty, "BGP table version is 0, local router ID is %s\n",
|
||||
inet_ntoa(bgp->router_id));
|
||||
vty_out (vty,
|
||||
"Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
|
||||
vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
|
||||
vty_out (vty, V4_HEADER);
|
||||
}
|
||||
header = 0;
|
||||
}
|
||||
for (rm = bgp_table_top(table); rm;
|
||||
rm = bgp_route_next(rm)) {
|
||||
if ((attr = rm->info) != NULL) {
|
||||
if (header) {
|
||||
if (use_json) {
|
||||
json_object_int_add(
|
||||
json,
|
||||
"bgpTableVersion",
|
||||
0);
|
||||
json_object_string_add(
|
||||
json,
|
||||
"bgpLocalRouterId",
|
||||
inet_ntoa(
|
||||
bgp->router_id));
|
||||
json_object_object_add(
|
||||
json,
|
||||
"bgpStatusCodes",
|
||||
json_scode);
|
||||
json_object_object_add(
|
||||
json,
|
||||
"bgpOriginCodes",
|
||||
json_ocode);
|
||||
} else {
|
||||
vty_out(vty,
|
||||
"BGP table version is 0, local router ID is %s\n",
|
||||
inet_ntoa(
|
||||
bgp->router_id));
|
||||
vty_out(vty,
|
||||
"Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
|
||||
vty_out(vty,
|
||||
"Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
|
||||
vty_out(vty, V4_HEADER);
|
||||
}
|
||||
header = 0;
|
||||
}
|
||||
|
||||
if (rd_header)
|
||||
{
|
||||
u_int16_t type;
|
||||
struct rd_as rd_as;
|
||||
struct rd_ip rd_ip = {0};
|
||||
if (rd_header) {
|
||||
u_int16_t type;
|
||||
struct rd_as rd_as;
|
||||
struct rd_ip rd_ip = {0};
|
||||
#if ENABLE_BGP_VNC
|
||||
struct rd_vnc_eth rd_vnc_eth = {0};
|
||||
struct rd_vnc_eth rd_vnc_eth = {
|
||||
0};
|
||||
#endif
|
||||
u_char *pnt;
|
||||
u_char *pnt;
|
||||
|
||||
pnt = rn->p.u.val;
|
||||
pnt = rn->p.u.val;
|
||||
|
||||
/* Decode RD type. */
|
||||
type = decode_rd_type (pnt);
|
||||
/* Decode RD value. */
|
||||
if (type == RD_TYPE_AS)
|
||||
decode_rd_as (pnt + 2, &rd_as);
|
||||
else if (type == RD_TYPE_AS4)
|
||||
decode_rd_as4 (pnt + 2, &rd_as);
|
||||
else if (type == RD_TYPE_IP)
|
||||
decode_rd_ip (pnt + 2, &rd_ip);
|
||||
/* Decode RD type. */
|
||||
type = decode_rd_type(pnt);
|
||||
/* Decode RD value. */
|
||||
if (type == RD_TYPE_AS)
|
||||
decode_rd_as(pnt + 2,
|
||||
&rd_as);
|
||||
else if (type == RD_TYPE_AS4)
|
||||
decode_rd_as4(pnt + 2,
|
||||
&rd_as);
|
||||
else if (type == RD_TYPE_IP)
|
||||
decode_rd_ip(pnt + 2,
|
||||
&rd_ip);
|
||||
#if ENABLE_BGP_VNC
|
||||
else if (type == RD_TYPE_VNC_ETH)
|
||||
decode_rd_vnc_eth (pnt, &rd_vnc_eth);
|
||||
else if (type
|
||||
== RD_TYPE_VNC_ETH)
|
||||
decode_rd_vnc_eth(
|
||||
pnt,
|
||||
&rd_vnc_eth);
|
||||
#endif
|
||||
|
||||
if (use_json)
|
||||
{
|
||||
char buffer[BUFSIZ];
|
||||
if (type == RD_TYPE_AS || type == RD_TYPE_AS4)
|
||||
sprintf (buffer, "%u:%d", rd_as.as, rd_as.val);
|
||||
else if (type == RD_TYPE_IP)
|
||||
sprintf (buffer, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
|
||||
json_object_string_add(json_routes, "routeDistinguisher", buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
vty_out (vty, "Route Distinguisher: ");
|
||||
if (use_json) {
|
||||
char buffer[BUFSIZ];
|
||||
if (type == RD_TYPE_AS
|
||||
|| type == RD_TYPE_AS4)
|
||||
sprintf(buffer,
|
||||
"%u:%d",
|
||||
rd_as.as,
|
||||
rd_as.val);
|
||||
else if (type
|
||||
== RD_TYPE_IP)
|
||||
sprintf(buffer,
|
||||
"%s:%d",
|
||||
inet_ntoa(
|
||||
rd_ip.ip),
|
||||
rd_ip.val);
|
||||
json_object_string_add(
|
||||
json_routes,
|
||||
"routeDistinguisher",
|
||||
buffer);
|
||||
} else {
|
||||
vty_out(vty,
|
||||
"Route Distinguisher: ");
|
||||
|
||||
if (type == RD_TYPE_AS || type == RD_TYPE_AS4)
|
||||
vty_out (vty, "%u:%d", rd_as.as, rd_as.val);
|
||||
else if (type == RD_TYPE_IP)
|
||||
vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
|
||||
if (type == RD_TYPE_AS
|
||||
|| type == RD_TYPE_AS4)
|
||||
vty_out(vty,
|
||||
"%u:%d",
|
||||
rd_as.as,
|
||||
rd_as.val);
|
||||
else if (type
|
||||
== RD_TYPE_IP)
|
||||
vty_out(vty,
|
||||
"%s:%d",
|
||||
inet_ntoa(
|
||||
rd_ip.ip),
|
||||
rd_ip.val);
|
||||
#if ENABLE_BGP_VNC
|
||||
else if (type == RD_TYPE_VNC_ETH)
|
||||
vty_out (vty, "%u:%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
rd_vnc_eth.local_nve_id,
|
||||
rd_vnc_eth.macaddr.octet[0],
|
||||
rd_vnc_eth.macaddr.octet[1],
|
||||
rd_vnc_eth.macaddr.octet[2],
|
||||
rd_vnc_eth.macaddr.octet[3],
|
||||
rd_vnc_eth.macaddr.octet[4],
|
||||
rd_vnc_eth.macaddr.octet[5]);
|
||||
else if (
|
||||
type
|
||||
== RD_TYPE_VNC_ETH)
|
||||
vty_out(vty,
|
||||
"%u:%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
rd_vnc_eth
|
||||
.local_nve_id,
|
||||
rd_vnc_eth
|
||||
.macaddr
|
||||
.octet[0],
|
||||
rd_vnc_eth
|
||||
.macaddr
|
||||
.octet[1],
|
||||
rd_vnc_eth
|
||||
.macaddr
|
||||
.octet[2],
|
||||
rd_vnc_eth
|
||||
.macaddr
|
||||
.octet[3],
|
||||
rd_vnc_eth
|
||||
.macaddr
|
||||
.octet[4],
|
||||
rd_vnc_eth
|
||||
.macaddr
|
||||
.octet[5]);
|
||||
#endif
|
||||
|
||||
vty_out (vty, "\n");
|
||||
}
|
||||
rd_header = 0;
|
||||
}
|
||||
route_vty_out_tmp (vty, &rm->p, attr, SAFI_MPLS_VPN, use_json, json_array);
|
||||
}
|
||||
}
|
||||
if (use_json)
|
||||
{
|
||||
struct prefix *p;
|
||||
char buf_a[BUFSIZ];
|
||||
char buf_b[BUFSIZ];
|
||||
p = &rm->p;
|
||||
sprintf(buf_a, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf_b, BUFSIZ), p->prefixlen);
|
||||
json_object_object_add(json_routes, buf_a, json_array);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (use_json)
|
||||
{
|
||||
json_object_object_add(json, "routes", json_routes);
|
||||
vty_out (vty, "%s\n",
|
||||
json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
|
||||
json_object_free(json);
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
rd_header = 0;
|
||||
}
|
||||
route_vty_out_tmp(vty, &rm->p, attr,
|
||||
SAFI_MPLS_VPN,
|
||||
use_json, json_array);
|
||||
}
|
||||
}
|
||||
if (use_json) {
|
||||
struct prefix *p;
|
||||
char buf_a[BUFSIZ];
|
||||
char buf_b[BUFSIZ];
|
||||
p = &rm->p;
|
||||
sprintf(buf_a, "%s/%d",
|
||||
inet_ntop(p->family, &p->u.prefix,
|
||||
buf_b, BUFSIZ),
|
||||
p->prefixlen);
|
||||
json_object_object_add(json_routes, buf_a,
|
||||
json_array);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (use_json) {
|
||||
json_object_object_add(json, "routes", json_routes);
|
||||
vty_out(vty, "%s\n", json_object_to_json_string_ext(
|
||||
json, JSON_C_TO_STRING_PRETTY));
|
||||
json_object_free(json);
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@ -23,8 +23,8 @@
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
extern int
|
||||
show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd,
|
||||
afi_t afi, safi_t safi, u_char use_json);
|
||||
extern int show_adj_route_vpn(struct vty *vty, struct peer *peer,
|
||||
struct prefix_rd *prd, afi_t afi, safi_t safi,
|
||||
u_char use_json);
|
||||
|
||||
#endif /* _QUAGGA_BGP_VPN_H */
|
||||
|
||||
17158
bgpd/bgp_vty.c
17158
bgpd/bgp_vty.c
File diff suppressed because it is too large
Load Diff
@ -29,47 +29,45 @@ struct bgp;
|
||||
#define BGP_AFI_CMD_STR "<ipv4|ipv6>"
|
||||
#define BGP_AFI_HELP_STR "Address Family\nAddress Family\n"
|
||||
#define BGP_SAFI_CMD_STR "<unicast|multicast|vpn>"
|
||||
#define BGP_SAFI_HELP_STR \
|
||||
"Address Family modifier\n" \
|
||||
"Address Family modifier\n" \
|
||||
"Address Family modifier\n"
|
||||
#define BGP_SAFI_HELP_STR \
|
||||
"Address Family modifier\n" \
|
||||
"Address Family modifier\n" \
|
||||
"Address Family modifier\n"
|
||||
#define BGP_AFI_SAFI_CMD_STR BGP_AFI_CMD_STR" "BGP_SAFI_CMD_STR
|
||||
#define BGP_AFI_SAFI_HELP_STR BGP_AFI_HELP_STR BGP_SAFI_HELP_STR
|
||||
|
||||
#define BGP_SAFI_WITH_LABEL_CMD_STR "<unicast|multicast|vpn|labeled-unicast>"
|
||||
#define BGP_SAFI_WITH_LABEL_HELP_STR \
|
||||
"Address Family modifier\n" \
|
||||
"Address Family modifier\n" \
|
||||
"Address Family modifier\n" \
|
||||
"Address Family modifier\n"
|
||||
#define BGP_SAFI_WITH_LABEL_HELP_STR \
|
||||
"Address Family modifier\n" \
|
||||
"Address Family modifier\n" \
|
||||
"Address Family modifier\n" \
|
||||
"Address Family modifier\n"
|
||||
|
||||
extern void bgp_vty_init (void);
|
||||
extern const char *afi_safi_print (afi_t, safi_t);
|
||||
extern const char *afi_safi_json (afi_t, safi_t);
|
||||
extern int bgp_config_write_update_delay (struct vty *, struct bgp *);
|
||||
extern void bgp_vty_init(void);
|
||||
extern const char *afi_safi_print(afi_t, safi_t);
|
||||
extern const char *afi_safi_json(afi_t, safi_t);
|
||||
extern int bgp_config_write_update_delay(struct vty *, struct bgp *);
|
||||
extern int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp);
|
||||
extern int bgp_config_write_listen(struct vty *vty, struct bgp *bgp);
|
||||
extern int bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp);
|
||||
extern int bgp_vty_return (struct vty *vty, int ret);
|
||||
extern struct peer *
|
||||
peer_and_group_lookup_vty (struct vty *vty, const char *peer_str);
|
||||
extern int bgp_vty_return(struct vty *vty, int ret);
|
||||
extern struct peer *peer_and_group_lookup_vty(struct vty *vty,
|
||||
const char *peer_str);
|
||||
|
||||
extern afi_t
|
||||
bgp_vty_afi_from_str(const char *afi_str);
|
||||
extern afi_t bgp_vty_afi_from_str(const char *afi_str);
|
||||
|
||||
extern safi_t
|
||||
bgp_vty_safi_from_str(const char *safi_str);
|
||||
extern safi_t bgp_vty_safi_from_str(const char *safi_str);
|
||||
|
||||
extern int
|
||||
argv_find_and_parse_afi(struct cmd_token **argv, int argc, int *index, afi_t *afi);
|
||||
extern int argv_find_and_parse_afi(struct cmd_token **argv, int argc,
|
||||
int *index, afi_t *afi);
|
||||
|
||||
extern int
|
||||
argv_find_and_parse_safi(struct cmd_token **argv, int argc, int *index, safi_t *safi);
|
||||
extern int argv_find_and_parse_safi(struct cmd_token **argv, int argc,
|
||||
int *index, safi_t *safi);
|
||||
|
||||
extern int
|
||||
bgp_vty_find_and_parse_afi_safi_bgp (struct vty *vty, struct cmd_token **argv, int argc, int *idx,
|
||||
afi_t *afi, safi_t *safi, struct bgp **bgp);
|
||||
extern int
|
||||
bgp_show_summary_vty (struct vty *vty, const char *name,
|
||||
afi_t afi, safi_t safi, u_char use_json);
|
||||
extern int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty,
|
||||
struct cmd_token **argv,
|
||||
int argc, int *idx, afi_t *afi,
|
||||
safi_t *safi, struct bgp **bgp);
|
||||
extern int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
|
||||
safi_t safi, u_char use_json);
|
||||
#endif /* _QUAGGA_BGP_VTY_H */
|
||||
|
||||
3534
bgpd/bgp_zebra.c
3534
bgpd/bgp_zebra.c
File diff suppressed because it is too large
Load Diff
@ -21,40 +21,43 @@
|
||||
#ifndef _QUAGGA_BGP_ZEBRA_H
|
||||
#define _QUAGGA_BGP_ZEBRA_H
|
||||
|
||||
extern void bgp_zebra_init (struct thread_master *master);
|
||||
extern void bgp_zebra_destroy (void);
|
||||
extern int bgp_if_update_all (void);
|
||||
extern int bgp_config_write_maxpaths (struct vty *, struct bgp *, afi_t,
|
||||
safi_t, int *);
|
||||
extern int bgp_config_write_redistribute (struct vty *, struct bgp *, afi_t, safi_t,
|
||||
int *);
|
||||
extern void bgp_zebra_announce (struct bgp_node *, struct prefix *,
|
||||
struct bgp_info *, struct bgp *, afi_t, safi_t);
|
||||
extern void bgp_zebra_announce_table (struct bgp *, afi_t, safi_t);
|
||||
extern void bgp_zebra_withdraw (struct prefix *, struct bgp_info *, safi_t);
|
||||
extern void bgp_zebra_init(struct thread_master *master);
|
||||
extern void bgp_zebra_destroy(void);
|
||||
extern int bgp_if_update_all(void);
|
||||
extern int bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t, safi_t,
|
||||
int *);
|
||||
extern int bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t,
|
||||
safi_t, int *);
|
||||
extern void bgp_zebra_announce(struct bgp_node *, struct prefix *,
|
||||
struct bgp_info *, struct bgp *, afi_t, safi_t);
|
||||
extern void bgp_zebra_announce_table(struct bgp *, afi_t, safi_t);
|
||||
extern void bgp_zebra_withdraw(struct prefix *, struct bgp_info *, safi_t);
|
||||
|
||||
extern void bgp_zebra_initiate_radv (struct bgp *bgp, struct peer *peer);
|
||||
extern void bgp_zebra_terminate_radv (struct bgp *bgp, struct peer *peer);
|
||||
extern void bgp_zebra_initiate_radv(struct bgp *bgp, struct peer *peer);
|
||||
extern void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer);
|
||||
|
||||
extern void bgp_zebra_instance_register (struct bgp *);
|
||||
extern void bgp_zebra_instance_deregister (struct bgp *);
|
||||
extern void bgp_zebra_instance_register(struct bgp *);
|
||||
extern void bgp_zebra_instance_deregister(struct bgp *);
|
||||
|
||||
extern struct bgp_redist *bgp_redist_lookup (struct bgp *, afi_t, u_char, u_short);
|
||||
extern struct bgp_redist *bgp_redist_add (struct bgp *, afi_t, u_char, u_short);
|
||||
extern int bgp_redistribute_set (struct bgp *, afi_t, int, u_short);
|
||||
extern int bgp_redistribute_resend (struct bgp *, afi_t, int, u_short);
|
||||
extern int bgp_redistribute_rmap_set (struct bgp_redist *, const char *);
|
||||
extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *,
|
||||
afi_t, int, u_int32_t);
|
||||
extern int bgp_redistribute_unset (struct bgp *, afi_t, int, u_short);
|
||||
extern int bgp_redistribute_unreg (struct bgp *, afi_t, int, u_short);
|
||||
extern struct bgp_redist *bgp_redist_lookup(struct bgp *, afi_t, u_char,
|
||||
u_short);
|
||||
extern struct bgp_redist *bgp_redist_add(struct bgp *, afi_t, u_char, u_short);
|
||||
extern int bgp_redistribute_set(struct bgp *, afi_t, int, u_short);
|
||||
extern int bgp_redistribute_resend(struct bgp *, afi_t, int, u_short);
|
||||
extern int bgp_redistribute_rmap_set(struct bgp_redist *, const char *);
|
||||
extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, afi_t,
|
||||
int, u_int32_t);
|
||||
extern int bgp_redistribute_unset(struct bgp *, afi_t, int, u_short);
|
||||
extern int bgp_redistribute_unreg(struct bgp *, afi_t, int, u_short);
|
||||
|
||||
extern struct interface *if_lookup_by_ipv4 (struct in_addr *, vrf_id_t);
|
||||
extern struct interface *if_lookup_by_ipv4_exact (struct in_addr *, vrf_id_t);
|
||||
extern struct interface *if_lookup_by_ipv6 (struct in6_addr *, ifindex_t, vrf_id_t);
|
||||
extern struct interface *if_lookup_by_ipv6_exact (struct in6_addr *, ifindex_t, vrf_id_t);
|
||||
extern struct interface *if_lookup_by_ipv4(struct in_addr *, vrf_id_t);
|
||||
extern struct interface *if_lookup_by_ipv4_exact(struct in_addr *, vrf_id_t);
|
||||
extern struct interface *if_lookup_by_ipv6(struct in6_addr *, ifindex_t,
|
||||
vrf_id_t);
|
||||
extern struct interface *if_lookup_by_ipv6_exact(struct in6_addr *, ifindex_t,
|
||||
vrf_id_t);
|
||||
|
||||
extern int bgp_zebra_advertise_all_vni (struct bgp *, int);
|
||||
extern int bgp_zebra_advertise_all_vni(struct bgp *, int);
|
||||
|
||||
extern int bgp_zebra_num_connects(void);
|
||||
|
||||
|
||||
12305
bgpd/bgpd.c
12305
bgpd/bgpd.c
File diff suppressed because it is too large
Load Diff
1577
bgpd/bgpd.h
1577
bgpd/bgpd.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Copyright 2009-2016, LabN Consulting, L.L.C.
|
||||
*
|
||||
@ -27,200 +27,195 @@
|
||||
#if ENABLE_BGP_VNC
|
||||
#include "rfapi.h"
|
||||
|
||||
struct rfapi_l2_group_cfg
|
||||
{
|
||||
char *name;
|
||||
uint32_t logical_net_id;
|
||||
struct list *labels; /* list of uint32_t */
|
||||
struct ecommunity *rt_import_list;
|
||||
struct ecommunity *rt_export_list;
|
||||
void *rfp_cfg; /* rfp owned group config */
|
||||
struct rfapi_l2_group_cfg {
|
||||
char *name;
|
||||
uint32_t logical_net_id;
|
||||
struct list *labels; /* list of uint32_t */
|
||||
struct ecommunity *rt_import_list;
|
||||
struct ecommunity *rt_export_list;
|
||||
void *rfp_cfg; /* rfp owned group config */
|
||||
|
||||
QOBJ_FIELDS
|
||||
QOBJ_FIELDS
|
||||
};
|
||||
DECLARE_QOBJ_TYPE(rfapi_l2_group_cfg)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
RFAPI_GROUP_CFG_NVE = 1,
|
||||
RFAPI_GROUP_CFG_VRF,
|
||||
RFAPI_GROUP_CFG_L2,
|
||||
RFAPI_GROUP_CFG_MAX
|
||||
typedef enum {
|
||||
RFAPI_GROUP_CFG_NVE = 1,
|
||||
RFAPI_GROUP_CFG_VRF,
|
||||
RFAPI_GROUP_CFG_L2,
|
||||
RFAPI_GROUP_CFG_MAX
|
||||
} rfapi_group_cfg_type_t;
|
||||
|
||||
struct rfapi_nve_group_cfg
|
||||
{
|
||||
struct route_node *vn_node; /* backref */
|
||||
struct route_node *un_node; /* backref */
|
||||
struct rfapi_nve_group_cfg {
|
||||
struct route_node *vn_node; /* backref */
|
||||
struct route_node *un_node; /* backref */
|
||||
|
||||
rfapi_group_cfg_type_t type; /* NVE|VPN */
|
||||
char *name; /* unique by type! */
|
||||
struct prefix vn_prefix;
|
||||
struct prefix un_prefix;
|
||||
rfapi_group_cfg_type_t type; /* NVE|VPN */
|
||||
char *name; /* unique by type! */
|
||||
struct prefix vn_prefix;
|
||||
struct prefix un_prefix;
|
||||
|
||||
struct prefix_rd rd;
|
||||
uint8_t l2rd; /* 0 = VN addr LSB */
|
||||
uint32_t response_lifetime;
|
||||
uint32_t flags;
|
||||
struct prefix_rd rd;
|
||||
uint8_t l2rd; /* 0 = VN addr LSB */
|
||||
uint32_t response_lifetime;
|
||||
uint32_t flags;
|
||||
#define RFAPI_RFG_RESPONSE_LIFETIME 0x01 /* bits */
|
||||
#define RFAPI_RFG_L2RD 0x02
|
||||
#define RFAPI_RFG_VPN_NH_SELF 0x04
|
||||
struct ecommunity *rt_import_list;
|
||||
struct ecommunity *rt_export_list;
|
||||
struct rfapi_import_table *rfapi_import_table;
|
||||
struct ecommunity *rt_import_list;
|
||||
struct ecommunity *rt_export_list;
|
||||
struct rfapi_import_table *rfapi_import_table;
|
||||
|
||||
void *rfp_cfg; /* rfp owned group config */
|
||||
/*
|
||||
* List of NVE descriptors that are assigned to this NVE group
|
||||
*
|
||||
* Currently (Mar 2010) this list is used only by the route
|
||||
* export code to generate per-NVE nexthops for each route.
|
||||
*
|
||||
* The nve descriptors listed here have pointers back to
|
||||
* this nve group config structure to enable them to delete
|
||||
* their own list entries when they are closed. Consequently,
|
||||
* if an instance of this nve group config structure is deleted,
|
||||
* we must first set the nve descriptor references to it to NULL.
|
||||
*/
|
||||
struct list *nves;
|
||||
void *rfp_cfg; /* rfp owned group config */
|
||||
/*
|
||||
* List of NVE descriptors that are assigned to this NVE group
|
||||
*
|
||||
* Currently (Mar 2010) this list is used only by the route
|
||||
* export code to generate per-NVE nexthops for each route.
|
||||
*
|
||||
* The nve descriptors listed here have pointers back to
|
||||
* this nve group config structure to enable them to delete
|
||||
* their own list entries when they are closed. Consequently,
|
||||
* if an instance of this nve group config structure is deleted,
|
||||
* we must first set the nve descriptor references to it to NULL.
|
||||
*/
|
||||
struct list *nves;
|
||||
|
||||
/*
|
||||
* Route filtering
|
||||
*
|
||||
* Prefix lists are segregated by afi (part of the base plist code)
|
||||
* Route-maps are not segregated
|
||||
*/
|
||||
char *plist_export_bgp_name[AFI_MAX];
|
||||
struct prefix_list *plist_export_bgp[AFI_MAX];
|
||||
/*
|
||||
* Route filtering
|
||||
*
|
||||
* Prefix lists are segregated by afi (part of the base plist code)
|
||||
* Route-maps are not segregated
|
||||
*/
|
||||
char *plist_export_bgp_name[AFI_MAX];
|
||||
struct prefix_list *plist_export_bgp[AFI_MAX];
|
||||
|
||||
char *plist_export_zebra_name[AFI_MAX];
|
||||
struct prefix_list *plist_export_zebra[AFI_MAX];
|
||||
char *plist_export_zebra_name[AFI_MAX];
|
||||
struct prefix_list *plist_export_zebra[AFI_MAX];
|
||||
|
||||
char *plist_redist_name[ZEBRA_ROUTE_MAX][AFI_MAX];
|
||||
struct prefix_list *plist_redist[ZEBRA_ROUTE_MAX][AFI_MAX];
|
||||
char *plist_redist_name[ZEBRA_ROUTE_MAX][AFI_MAX];
|
||||
struct prefix_list *plist_redist[ZEBRA_ROUTE_MAX][AFI_MAX];
|
||||
|
||||
char *routemap_export_bgp_name;
|
||||
struct route_map *routemap_export_bgp;
|
||||
char *routemap_export_bgp_name;
|
||||
struct route_map *routemap_export_bgp;
|
||||
|
||||
char *routemap_export_zebra_name;
|
||||
struct route_map *routemap_export_zebra;
|
||||
char *routemap_export_zebra_name;
|
||||
struct route_map *routemap_export_zebra;
|
||||
|
||||
char *routemap_redist_name[ZEBRA_ROUTE_MAX];
|
||||
struct route_map *routemap_redist[ZEBRA_ROUTE_MAX];
|
||||
char *routemap_redist_name[ZEBRA_ROUTE_MAX];
|
||||
struct route_map *routemap_redist[ZEBRA_ROUTE_MAX];
|
||||
|
||||
/* for VRF type groups */
|
||||
uint32_t label;
|
||||
struct rfapi_descriptor *rfd;
|
||||
QOBJ_FIELDS
|
||||
/* for VRF type groups */
|
||||
uint32_t label;
|
||||
struct rfapi_descriptor *rfd;
|
||||
QOBJ_FIELDS
|
||||
};
|
||||
DECLARE_QOBJ_TYPE(rfapi_nve_group_cfg)
|
||||
|
||||
struct rfapi_rfg_name
|
||||
{
|
||||
struct rfapi_nve_group_cfg *rfg;
|
||||
char *name;
|
||||
struct rfapi_rfg_name {
|
||||
struct rfapi_nve_group_cfg *rfg;
|
||||
char *name;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VNC_REDIST_MODE_PLAIN = 0, /* 0 = default */
|
||||
VNC_REDIST_MODE_RFG,
|
||||
VNC_REDIST_MODE_RESOLVE_NVE
|
||||
typedef enum {
|
||||
VNC_REDIST_MODE_PLAIN = 0, /* 0 = default */
|
||||
VNC_REDIST_MODE_RFG,
|
||||
VNC_REDIST_MODE_RESOLVE_NVE
|
||||
} vnc_redist_mode_t;
|
||||
|
||||
struct rfapi_cfg
|
||||
{
|
||||
struct prefix_rd default_rd;
|
||||
uint8_t default_l2rd;
|
||||
struct ecommunity *default_rt_import_list;
|
||||
struct ecommunity *default_rt_export_list;
|
||||
uint32_t default_response_lifetime;
|
||||
struct rfapi_cfg {
|
||||
struct prefix_rd default_rd;
|
||||
uint8_t default_l2rd;
|
||||
struct ecommunity *default_rt_import_list;
|
||||
struct ecommunity *default_rt_export_list;
|
||||
uint32_t default_response_lifetime;
|
||||
#define BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT 3600
|
||||
void *default_rfp_cfg; /* rfp owned group config */
|
||||
void *default_rfp_cfg; /* rfp owned group config */
|
||||
|
||||
struct list *l2_groups; /* rfapi_l2_group_cfg list */
|
||||
/* three views into the same collection of rfapi_nve_group_cfg */
|
||||
struct list *nve_groups_sequential;
|
||||
struct route_table nve_groups_vn[AFI_MAX];
|
||||
struct route_table nve_groups_un[AFI_MAX];
|
||||
struct list *l2_groups; /* rfapi_l2_group_cfg list */
|
||||
/* three views into the same collection of rfapi_nve_group_cfg */
|
||||
struct list *nve_groups_sequential;
|
||||
struct route_table nve_groups_vn[AFI_MAX];
|
||||
struct route_table nve_groups_un[AFI_MAX];
|
||||
|
||||
/*
|
||||
* For Single VRF export to ordinary routing protocols. This is
|
||||
* the nve-group that the ordinary protocols belong to. We use it
|
||||
* to set the RD when sending unicast Zebra routes to VNC
|
||||
*/
|
||||
uint8_t redist[AFI_MAX][ZEBRA_ROUTE_MAX];
|
||||
uint32_t redist_lifetime;
|
||||
vnc_redist_mode_t redist_mode;
|
||||
/*
|
||||
* For Single VRF export to ordinary routing protocols. This is
|
||||
* the nve-group that the ordinary protocols belong to. We use it
|
||||
* to set the RD when sending unicast Zebra routes to VNC
|
||||
*/
|
||||
uint8_t redist[AFI_MAX][ZEBRA_ROUTE_MAX];
|
||||
uint32_t redist_lifetime;
|
||||
vnc_redist_mode_t redist_mode;
|
||||
|
||||
/*
|
||||
* view name of BGP unicast instance that holds
|
||||
* exterior routes
|
||||
*/
|
||||
char *redist_bgp_exterior_view_name;
|
||||
struct bgp *redist_bgp_exterior_view;
|
||||
/*
|
||||
* view name of BGP unicast instance that holds
|
||||
* exterior routes
|
||||
*/
|
||||
char *redist_bgp_exterior_view_name;
|
||||
struct bgp *redist_bgp_exterior_view;
|
||||
|
||||
/*
|
||||
* nve group for redistribution of routes from zebra to VNC
|
||||
* (which is probably not useful for production networks)
|
||||
*/
|
||||
char *rfg_redist_name;
|
||||
struct rfapi_nve_group_cfg *rfg_redist;
|
||||
/*
|
||||
* nve group for redistribution of routes from zebra to VNC
|
||||
* (which is probably not useful for production networks)
|
||||
*/
|
||||
char *rfg_redist_name;
|
||||
struct rfapi_nve_group_cfg *rfg_redist;
|
||||
|
||||
/*
|
||||
* List of NVE groups on whose behalf we will export VNC
|
||||
* routes to zebra. ((NB: it's actually a list of <struct rfapi_rfg_name>)
|
||||
* This list is used when BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS is
|
||||
* BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP
|
||||
*/
|
||||
struct list *rfg_export_zebra_l;
|
||||
/*
|
||||
* List of NVE groups on whose behalf we will export VNC
|
||||
* routes to zebra. ((NB: it's actually a list of <struct
|
||||
* rfapi_rfg_name>)
|
||||
* This list is used when BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS is
|
||||
* BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP
|
||||
*/
|
||||
struct list *rfg_export_zebra_l;
|
||||
|
||||
/*
|
||||
* List of NVE groups on whose behalf we will export VNC
|
||||
* routes directly to the bgp unicast RIB. (NB: it's actually
|
||||
* a list of <struct rfapi_rfg_name>)
|
||||
* This list is used when BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS is
|
||||
* BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP
|
||||
*/
|
||||
struct list *rfg_export_direct_bgp_l;
|
||||
/*
|
||||
* List of NVE groups on whose behalf we will export VNC
|
||||
* routes directly to the bgp unicast RIB. (NB: it's actually
|
||||
* a list of <struct rfapi_rfg_name>)
|
||||
* This list is used when BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS is
|
||||
* BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP
|
||||
*/
|
||||
struct list *rfg_export_direct_bgp_l;
|
||||
|
||||
/*
|
||||
* Exported Route filtering
|
||||
*
|
||||
* Prefix lists are segregated by afi (part of the base plist code)
|
||||
* Route-maps are not segregated
|
||||
*/
|
||||
char *plist_export_bgp_name[AFI_MAX];
|
||||
struct prefix_list *plist_export_bgp[AFI_MAX];
|
||||
/*
|
||||
* Exported Route filtering
|
||||
*
|
||||
* Prefix lists are segregated by afi (part of the base plist code)
|
||||
* Route-maps are not segregated
|
||||
*/
|
||||
char *plist_export_bgp_name[AFI_MAX];
|
||||
struct prefix_list *plist_export_bgp[AFI_MAX];
|
||||
|
||||
char *plist_export_zebra_name[AFI_MAX];
|
||||
struct prefix_list *plist_export_zebra[AFI_MAX];
|
||||
char *plist_export_zebra_name[AFI_MAX];
|
||||
struct prefix_list *plist_export_zebra[AFI_MAX];
|
||||
|
||||
char *routemap_export_bgp_name;
|
||||
struct route_map *routemap_export_bgp;
|
||||
char *routemap_export_bgp_name;
|
||||
struct route_map *routemap_export_bgp;
|
||||
|
||||
char *routemap_export_zebra_name;
|
||||
struct route_map *routemap_export_zebra;
|
||||
char *routemap_export_zebra_name;
|
||||
struct route_map *routemap_export_zebra;
|
||||
|
||||
/*
|
||||
* Redistributed route filtering (routes from other
|
||||
* protocols into VNC)
|
||||
*/
|
||||
char *plist_redist_name[ZEBRA_ROUTE_MAX][AFI_MAX];
|
||||
struct prefix_list *plist_redist[ZEBRA_ROUTE_MAX][AFI_MAX];
|
||||
/*
|
||||
* Redistributed route filtering (routes from other
|
||||
* protocols into VNC)
|
||||
*/
|
||||
char *plist_redist_name[ZEBRA_ROUTE_MAX][AFI_MAX];
|
||||
struct prefix_list *plist_redist[ZEBRA_ROUTE_MAX][AFI_MAX];
|
||||
|
||||
char *routemap_redist_name[ZEBRA_ROUTE_MAX];
|
||||
struct route_map *routemap_redist[ZEBRA_ROUTE_MAX];
|
||||
char *routemap_redist_name[ZEBRA_ROUTE_MAX];
|
||||
struct route_map *routemap_redist[ZEBRA_ROUTE_MAX];
|
||||
|
||||
/*
|
||||
* For importing bgp unicast routes to VNC, we encode the CE
|
||||
* (route nexthop) in a Route Origin extended community. The
|
||||
* local part (16-bit) is user-configurable.
|
||||
*/
|
||||
uint16_t resolve_nve_roo_local_admin;
|
||||
/*
|
||||
* For importing bgp unicast routes to VNC, we encode the CE
|
||||
* (route nexthop) in a Route Origin extended community. The
|
||||
* local part (16-bit) is user-configurable.
|
||||
*/
|
||||
uint16_t resolve_nve_roo_local_admin;
|
||||
#define BGP_VNC_CONFIG_RESOLVE_NVE_ROO_LOCAL_ADMIN_DEFAULT 5226
|
||||
|
||||
uint32_t flags;
|
||||
uint32_t flags;
|
||||
#define BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP 0x00000001
|
||||
#define BGP_VNC_CONFIG_CALLBACK_DISABLE 0x00000002
|
||||
#define BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE 0x00000004
|
||||
@ -244,98 +239,76 @@ struct rfapi_cfg
|
||||
/* Filter querying NVE's registrations from responses */
|
||||
/* Default to updated-responses off */
|
||||
/* Default to removal-responses off */
|
||||
#define BGP_VNC_CONFIG_FLAGS_DEFAULT \
|
||||
(BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP |\
|
||||
BGP_VNC_CONFIG_CALLBACK_DISABLE |\
|
||||
BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE)
|
||||
#define BGP_VNC_CONFIG_FLAGS_DEFAULT \
|
||||
(BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP | BGP_VNC_CONFIG_CALLBACK_DISABLE \
|
||||
| BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE)
|
||||
|
||||
struct rfapi_rfp_cfg rfp_cfg; /* rfp related configuration */
|
||||
struct rfapi_rfp_cfg rfp_cfg; /* rfp related configuration */
|
||||
};
|
||||
|
||||
#define VNC_EXPORT_ZEBRA_GRP_ENABLED(hc) \
|
||||
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS) == \
|
||||
BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP)
|
||||
#define VNC_EXPORT_ZEBRA_GRP_ENABLED(hc) \
|
||||
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS) \
|
||||
== BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP)
|
||||
|
||||
#define VNC_EXPORT_ZEBRA_RH_ENABLED(hc) \
|
||||
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS) == \
|
||||
BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_RH)
|
||||
#define VNC_EXPORT_ZEBRA_RH_ENABLED(hc) \
|
||||
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS) \
|
||||
== BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_RH)
|
||||
|
||||
#define VNC_EXPORT_BGP_GRP_ENABLED(hc) \
|
||||
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) == \
|
||||
BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP)
|
||||
#define VNC_EXPORT_BGP_GRP_ENABLED(hc) \
|
||||
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) \
|
||||
== BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP)
|
||||
|
||||
#define VNC_EXPORT_BGP_RH_ENABLED(hc) \
|
||||
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) == \
|
||||
BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH)
|
||||
#define VNC_EXPORT_BGP_RH_ENABLED(hc) \
|
||||
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) \
|
||||
== BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH)
|
||||
|
||||
#define VNC_EXPORT_BGP_CE_ENABLED(hc) \
|
||||
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) == \
|
||||
BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE)
|
||||
#define VNC_EXPORT_BGP_CE_ENABLED(hc) \
|
||||
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) \
|
||||
== BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE)
|
||||
|
||||
|
||||
void
|
||||
bgp_rfapi_cfg_init (void);
|
||||
void bgp_rfapi_cfg_init(void);
|
||||
|
||||
struct rfapi_cfg *
|
||||
bgp_rfapi_cfg_new (struct rfapi_rfp_cfg *cfg);
|
||||
struct rfapi_cfg *bgp_rfapi_cfg_new(struct rfapi_rfp_cfg *cfg);
|
||||
|
||||
void
|
||||
bgp_rfapi_cfg_destroy (struct bgp *bgp, struct rfapi_cfg *h);
|
||||
void bgp_rfapi_cfg_destroy(struct bgp *bgp, struct rfapi_cfg *h);
|
||||
|
||||
int
|
||||
bgp_rfapi_cfg_write (struct vty *vty, struct bgp *bgp);
|
||||
int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp);
|
||||
|
||||
extern int
|
||||
bgp_rfapi_is_vnc_configured (struct bgp *bgp);
|
||||
extern int bgp_rfapi_is_vnc_configured(struct bgp *bgp);
|
||||
|
||||
extern void
|
||||
nve_group_to_nve_list (
|
||||
struct rfapi_nve_group_cfg *rfg,
|
||||
struct list **nves,
|
||||
uint8_t family); /* AF_INET, AF_INET6 */
|
||||
extern void nve_group_to_nve_list(struct rfapi_nve_group_cfg *rfg,
|
||||
struct list **nves,
|
||||
uint8_t family); /* AF_INET, AF_INET6 */
|
||||
|
||||
struct rfapi_nve_group_cfg *bgp_rfapi_cfg_match_group(struct rfapi_cfg *hc,
|
||||
struct prefix *vn,
|
||||
struct prefix *un);
|
||||
|
||||
struct rfapi_nve_group_cfg *
|
||||
bgp_rfapi_cfg_match_group (
|
||||
struct rfapi_cfg *hc,
|
||||
struct prefix *vn,
|
||||
struct prefix *un);
|
||||
bgp_rfapi_cfg_match_byname(struct bgp *bgp, const char *name,
|
||||
rfapi_group_cfg_type_t type); /* _MAX = any */
|
||||
|
||||
struct rfapi_nve_group_cfg *
|
||||
bgp_rfapi_cfg_match_byname (
|
||||
struct bgp *bgp,
|
||||
const char *name,
|
||||
rfapi_group_cfg_type_t type); /* _MAX = any */
|
||||
extern void vnc_prefix_list_update(struct bgp *bgp);
|
||||
|
||||
extern void
|
||||
vnc_prefix_list_update (struct bgp *bgp);
|
||||
extern void vnc_routemap_update(struct bgp *bgp, const char *unused);
|
||||
|
||||
extern void
|
||||
vnc_routemap_update (struct bgp *bgp, const char *unused);
|
||||
extern void bgp_rfapi_show_summary(struct bgp *bgp, struct vty *vty);
|
||||
|
||||
extern void
|
||||
bgp_rfapi_show_summary (struct bgp *bgp, struct vty *vty);
|
||||
|
||||
extern struct rfapi_cfg *
|
||||
bgp_rfapi_get_config (struct bgp *bgp);
|
||||
extern struct rfapi_cfg *bgp_rfapi_get_config(struct bgp *bgp);
|
||||
|
||||
extern struct rfapi_l2_group_cfg *
|
||||
bgp_rfapi_get_group_by_lni_label (
|
||||
struct bgp *bgp,
|
||||
uint32_t logical_net_id,
|
||||
uint32_t label);
|
||||
bgp_rfapi_get_group_by_lni_label(struct bgp *bgp, uint32_t logical_net_id,
|
||||
uint32_t label);
|
||||
|
||||
extern struct ecommunity *
|
||||
bgp_rfapi_get_ecommunity_by_lni_label (
|
||||
struct bgp *bgp,
|
||||
uint32_t is_import,
|
||||
uint32_t logical_net_id,
|
||||
uint32_t label); /* note, 20bit label! */
|
||||
bgp_rfapi_get_ecommunity_by_lni_label(struct bgp *bgp, uint32_t is_import,
|
||||
uint32_t logical_net_id,
|
||||
uint32_t label); /* note, 20bit label! */
|
||||
|
||||
extern struct list *
|
||||
bgp_rfapi_get_labellist_by_lni_label (
|
||||
struct bgp *bgp,
|
||||
uint32_t logical_net_id,
|
||||
uint32_t label); /* note, 20bit label! */
|
||||
bgp_rfapi_get_labellist_by_lni_label(struct bgp *bgp, uint32_t logical_net_id,
|
||||
uint32_t label); /* note, 20bit label! */
|
||||
|
||||
#endif /* ENABLE_BGP_VNC */
|
||||
|
||||
|
||||
6113
bgpd/rfapi/rfapi.c
6113
bgpd/rfapi/rfapi.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Copyright 2009-2016, LabN Consulting, L.L.C.
|
||||
*
|
||||
@ -83,541 +83,476 @@
|
||||
* is used to spread out the sort for adbs with the same lifetime
|
||||
* and thereby make the skip list operations more efficient.
|
||||
*/
|
||||
static int
|
||||
sl_adb_lifetime_cmp (void *adb1, void *adb2)
|
||||
static int sl_adb_lifetime_cmp(void *adb1, void *adb2)
|
||||
{
|
||||
struct rfapi_adb *a1 = adb1;
|
||||
struct rfapi_adb *a2 = adb2;
|
||||
struct rfapi_adb *a1 = adb1;
|
||||
struct rfapi_adb *a2 = adb2;
|
||||
|
||||
if (a1->lifetime < a2->lifetime)
|
||||
return -1;
|
||||
if (a1->lifetime > a2->lifetime)
|
||||
return 1;
|
||||
if (a1->lifetime < a2->lifetime)
|
||||
return -1;
|
||||
if (a1->lifetime > a2->lifetime)
|
||||
return 1;
|
||||
|
||||
if (a1 < a2)
|
||||
return -1;
|
||||
if (a1 > a2)
|
||||
return 1;
|
||||
if (a1 < a2)
|
||||
return -1;
|
||||
if (a1 > a2)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rfapiApInit (struct rfapi_advertised_prefixes *ap)
|
||||
void rfapiApInit(struct rfapi_advertised_prefixes *ap)
|
||||
{
|
||||
ap->ipN_by_prefix = skiplist_new (0, rfapi_rib_key_cmp, NULL);
|
||||
ap->ip0_by_ether = skiplist_new (0, rfapi_rib_key_cmp, NULL);
|
||||
ap->by_lifetime = skiplist_new (0, sl_adb_lifetime_cmp, NULL);
|
||||
ap->ipN_by_prefix = skiplist_new(0, rfapi_rib_key_cmp, NULL);
|
||||
ap->ip0_by_ether = skiplist_new(0, rfapi_rib_key_cmp, NULL);
|
||||
ap->by_lifetime = skiplist_new(0, sl_adb_lifetime_cmp, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
rfapiApRelease (struct rfapi_advertised_prefixes *ap)
|
||||
void rfapiApRelease(struct rfapi_advertised_prefixes *ap)
|
||||
{
|
||||
struct rfapi_adb *adb;
|
||||
struct rfapi_adb *adb;
|
||||
|
||||
/* Free ADBs and lifetime items */
|
||||
while (0 == skiplist_first (ap->by_lifetime, NULL, (void **) &adb))
|
||||
{
|
||||
rfapiAdbFree (adb);
|
||||
skiplist_delete_first (ap->by_lifetime);
|
||||
}
|
||||
/* Free ADBs and lifetime items */
|
||||
while (0 == skiplist_first(ap->by_lifetime, NULL, (void **)&adb)) {
|
||||
rfapiAdbFree(adb);
|
||||
skiplist_delete_first(ap->by_lifetime);
|
||||
}
|
||||
|
||||
while (0 == skiplist_delete_first (ap->ipN_by_prefix));
|
||||
while (0 == skiplist_delete_first (ap->ip0_by_ether));
|
||||
while (0 == skiplist_delete_first(ap->ipN_by_prefix))
|
||||
;
|
||||
while (0 == skiplist_delete_first(ap->ip0_by_ether))
|
||||
;
|
||||
|
||||
/* Free lists */
|
||||
skiplist_free (ap->ipN_by_prefix);
|
||||
skiplist_free (ap->ip0_by_ether);
|
||||
skiplist_free (ap->by_lifetime);
|
||||
/* Free lists */
|
||||
skiplist_free(ap->ipN_by_prefix);
|
||||
skiplist_free(ap->ip0_by_ether);
|
||||
skiplist_free(ap->by_lifetime);
|
||||
|
||||
ap->ipN_by_prefix = NULL;
|
||||
ap->ip0_by_ether = NULL;
|
||||
ap->by_lifetime = NULL;
|
||||
ap->ipN_by_prefix = NULL;
|
||||
ap->ip0_by_ether = NULL;
|
||||
ap->by_lifetime = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
rfapiApCount (struct rfapi_descriptor *rfd)
|
||||
int rfapiApCount(struct rfapi_descriptor *rfd)
|
||||
{
|
||||
if (!rfd->advertised.by_lifetime)
|
||||
return 0;
|
||||
if (!rfd->advertised.by_lifetime)
|
||||
return 0;
|
||||
|
||||
return skiplist_count (rfd->advertised.by_lifetime);
|
||||
return skiplist_count(rfd->advertised.by_lifetime);
|
||||
}
|
||||
|
||||
int
|
||||
rfapiApCountAll (struct bgp *bgp)
|
||||
int rfapiApCountAll(struct bgp *bgp)
|
||||
{
|
||||
struct rfapi *h;
|
||||
struct listnode *node;
|
||||
struct rfapi_descriptor *rfd;
|
||||
int total = 0;
|
||||
struct rfapi *h;
|
||||
struct listnode *node;
|
||||
struct rfapi_descriptor *rfd;
|
||||
int total = 0;
|
||||
|
||||
h = bgp->rfapi;
|
||||
if (h)
|
||||
{
|
||||
for (ALL_LIST_ELEMENTS_RO (&h->descriptors, node, rfd))
|
||||
{
|
||||
total += rfapiApCount (rfd);
|
||||
}
|
||||
}
|
||||
return total;
|
||||
h = bgp->rfapi;
|
||||
if (h) {
|
||||
for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
|
||||
total += rfapiApCount(rfd);
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rfapiApReadvertiseAll (struct bgp *bgp, struct rfapi_descriptor *rfd)
|
||||
void rfapiApReadvertiseAll(struct bgp *bgp, struct rfapi_descriptor *rfd)
|
||||
{
|
||||
struct rfapi_adb *adb;
|
||||
void *cursor = NULL;
|
||||
int rc;
|
||||
struct rfapi_adb *adb;
|
||||
void *cursor = NULL;
|
||||
int rc;
|
||||
|
||||
for (rc =
|
||||
skiplist_next (rfd->advertised.by_lifetime, NULL, (void **) &adb,
|
||||
&cursor); rc == 0;
|
||||
rc =
|
||||
skiplist_next (rfd->advertised.by_lifetime, NULL, (void **) &adb,
|
||||
&cursor))
|
||||
{
|
||||
for (rc = skiplist_next(rfd->advertised.by_lifetime, NULL,
|
||||
(void **)&adb, &cursor);
|
||||
rc == 0; rc = skiplist_next(rfd->advertised.by_lifetime, NULL,
|
||||
(void **)&adb, &cursor)) {
|
||||
|
||||
struct prefix_rd prd;
|
||||
uint32_t local_pref = rfp_cost_to_localpref (adb->cost);
|
||||
struct prefix_rd prd;
|
||||
uint32_t local_pref = rfp_cost_to_localpref(adb->cost);
|
||||
|
||||
prd = rfd->rd;
|
||||
prd.family = AF_UNSPEC;
|
||||
prd.prefixlen = 64;
|
||||
prd = rfd->rd;
|
||||
prd.family = AF_UNSPEC;
|
||||
prd.prefixlen = 64;
|
||||
|
||||
/*
|
||||
* TBD this is not quite right. When pfx_ip is 0/32 or 0/128,
|
||||
* we need to substitute the VN address as the prefix
|
||||
*/
|
||||
add_vnc_route (rfd, bgp, SAFI_MPLS_VPN, &adb->u.s.prefix_ip, &prd, /* RD to use (0 for ENCAP) */
|
||||
&rfd->vn_addr, /* nexthop */
|
||||
&local_pref, &adb->lifetime, NULL, NULL, /* struct rfapi_un_option */
|
||||
NULL, /* struct rfapi_vn_option */
|
||||
rfd->rt_export_list, NULL, /* med */
|
||||
NULL, ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, 0);
|
||||
}
|
||||
/*
|
||||
* TBD this is not quite right. When pfx_ip is 0/32 or 0/128,
|
||||
* we need to substitute the VN address as the prefix
|
||||
*/
|
||||
add_vnc_route(rfd, bgp, SAFI_MPLS_VPN, &adb->u.s.prefix_ip,
|
||||
&prd, /* RD to use (0 for ENCAP) */
|
||||
&rfd->vn_addr, /* nexthop */
|
||||
&local_pref, &adb->lifetime, NULL,
|
||||
NULL, /* struct rfapi_un_option */
|
||||
NULL, /* struct rfapi_vn_option */
|
||||
rfd->rt_export_list, NULL, /* med */
|
||||
NULL, ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rfapiApWithdrawAll (struct bgp *bgp, struct rfapi_descriptor *rfd)
|
||||
void rfapiApWithdrawAll(struct bgp *bgp, struct rfapi_descriptor *rfd)
|
||||
{
|
||||
struct rfapi_adb *adb;
|
||||
void *cursor;
|
||||
int rc;
|
||||
struct rfapi_adb *adb;
|
||||
void *cursor;
|
||||
int rc;
|
||||
|
||||
|
||||
cursor = NULL;
|
||||
for (rc =
|
||||
skiplist_next (rfd->advertised.by_lifetime, NULL, (void **) &adb,
|
||||
&cursor); rc == 0;
|
||||
rc =
|
||||
skiplist_next (rfd->advertised.by_lifetime, NULL, (void **) &adb,
|
||||
&cursor))
|
||||
{
|
||||
cursor = NULL;
|
||||
for (rc = skiplist_next(rfd->advertised.by_lifetime, NULL,
|
||||
(void **)&adb, &cursor);
|
||||
rc == 0; rc = skiplist_next(rfd->advertised.by_lifetime, NULL,
|
||||
(void **)&adb, &cursor)) {
|
||||
|
||||
struct prefix pfx_vn_buf;
|
||||
struct prefix *pfx_ip;
|
||||
struct prefix pfx_vn_buf;
|
||||
struct prefix *pfx_ip;
|
||||
|
||||
if (!(RFAPI_0_PREFIX (&adb->u.s.prefix_ip) &&
|
||||
RFAPI_HOST_PREFIX (&adb->u.s.prefix_ip)))
|
||||
{
|
||||
if (!(RFAPI_0_PREFIX(&adb->u.s.prefix_ip)
|
||||
&& RFAPI_HOST_PREFIX(&adb->u.s.prefix_ip))) {
|
||||
|
||||
pfx_ip = &adb->u.s.prefix_ip;
|
||||
pfx_ip = &adb->u.s.prefix_ip;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
|
||||
pfx_ip = NULL;
|
||||
pfx_ip = NULL;
|
||||
|
||||
/*
|
||||
* 0/32 or 0/128 => mac advertisement
|
||||
*/
|
||||
if (rfapiRaddr2Qprefix (&rfd->vn_addr, &pfx_vn_buf))
|
||||
{
|
||||
/*
|
||||
* Bad: it means we can't delete the route
|
||||
*/
|
||||
vnc_zlog_debug_verbose ("%s: BAD: handle has bad vn_addr: skipping",
|
||||
__func__);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 0/32 or 0/128 => mac advertisement
|
||||
*/
|
||||
if (rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn_buf)) {
|
||||
/*
|
||||
* Bad: it means we can't delete the route
|
||||
*/
|
||||
vnc_zlog_debug_verbose(
|
||||
"%s: BAD: handle has bad vn_addr: skipping",
|
||||
__func__);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
del_vnc_route (rfd, rfd->peer, bgp, SAFI_MPLS_VPN, pfx_ip ? pfx_ip : &pfx_vn_buf, &adb->u.s.prd, /* RD to use (0 for ENCAP) */
|
||||
ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL, 0);
|
||||
}
|
||||
del_vnc_route(rfd, rfd->peer, bgp, SAFI_MPLS_VPN,
|
||||
pfx_ip ? pfx_ip : &pfx_vn_buf,
|
||||
&adb->u.s.prd, /* RD to use (0 for ENCAP) */
|
||||
ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* returns nonzero if tunnel readvertisement is needed, 0 otherwise
|
||||
*/
|
||||
static int
|
||||
rfapiApAdjustLifetimeStats (
|
||||
struct rfapi_descriptor *rfd,
|
||||
uint32_t *old_lifetime, /* set if removing/replacing */
|
||||
uint32_t *new_lifetime) /* set if replacing/adding */
|
||||
static int rfapiApAdjustLifetimeStats(
|
||||
struct rfapi_descriptor *rfd,
|
||||
uint32_t *old_lifetime, /* set if removing/replacing */
|
||||
uint32_t *new_lifetime) /* set if replacing/adding */
|
||||
{
|
||||
int advertise = 0;
|
||||
int find_max = 0;
|
||||
int find_min = 0;
|
||||
int advertise = 0;
|
||||
int find_max = 0;
|
||||
int find_min = 0;
|
||||
|
||||
vnc_zlog_debug_verbose ("%s: rfd=%p, pOldLife=%p, pNewLife=%p",
|
||||
__func__, rfd, old_lifetime, new_lifetime);
|
||||
if (old_lifetime)
|
||||
vnc_zlog_debug_verbose ("%s: OldLife=%d", __func__, *old_lifetime);
|
||||
if (new_lifetime)
|
||||
vnc_zlog_debug_verbose ("%s: NewLife=%d", __func__, *new_lifetime);
|
||||
vnc_zlog_debug_verbose("%s: rfd=%p, pOldLife=%p, pNewLife=%p", __func__,
|
||||
rfd, old_lifetime, new_lifetime);
|
||||
if (old_lifetime)
|
||||
vnc_zlog_debug_verbose("%s: OldLife=%d", __func__,
|
||||
*old_lifetime);
|
||||
if (new_lifetime)
|
||||
vnc_zlog_debug_verbose("%s: NewLife=%d", __func__,
|
||||
*new_lifetime);
|
||||
|
||||
if (new_lifetime)
|
||||
{
|
||||
/*
|
||||
* Adding new lifetime
|
||||
*/
|
||||
if (old_lifetime)
|
||||
{
|
||||
/*
|
||||
* replacing existing lifetime
|
||||
*/
|
||||
if (new_lifetime) {
|
||||
/*
|
||||
* Adding new lifetime
|
||||
*/
|
||||
if (old_lifetime) {
|
||||
/*
|
||||
* replacing existing lifetime
|
||||
*/
|
||||
|
||||
|
||||
/* old and new are same */
|
||||
if (*old_lifetime == *new_lifetime)
|
||||
return 0;
|
||||
/* old and new are same */
|
||||
if (*old_lifetime == *new_lifetime)
|
||||
return 0;
|
||||
|
||||
if (*old_lifetime == rfd->min_prefix_lifetime)
|
||||
{
|
||||
find_min = 1;
|
||||
}
|
||||
if (*old_lifetime == rfd->max_prefix_lifetime)
|
||||
{
|
||||
find_max = 1;
|
||||
}
|
||||
if (*old_lifetime == rfd->min_prefix_lifetime) {
|
||||
find_min = 1;
|
||||
}
|
||||
if (*old_lifetime == rfd->max_prefix_lifetime) {
|
||||
find_max = 1;
|
||||
}
|
||||
|
||||
/* no need to search if new value is at or equals min|max */
|
||||
if (*new_lifetime <= rfd->min_prefix_lifetime)
|
||||
{
|
||||
rfd->min_prefix_lifetime = *new_lifetime;
|
||||
find_min = 0;
|
||||
}
|
||||
if (*new_lifetime >= rfd->max_prefix_lifetime)
|
||||
{
|
||||
rfd->max_prefix_lifetime = *new_lifetime;
|
||||
advertise = 1;
|
||||
find_max = 0;
|
||||
}
|
||||
/* no need to search if new value is at or equals
|
||||
* min|max */
|
||||
if (*new_lifetime <= rfd->min_prefix_lifetime) {
|
||||
rfd->min_prefix_lifetime = *new_lifetime;
|
||||
find_min = 0;
|
||||
}
|
||||
if (*new_lifetime >= rfd->max_prefix_lifetime) {
|
||||
rfd->max_prefix_lifetime = *new_lifetime;
|
||||
advertise = 1;
|
||||
find_max = 0;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Just adding new lifetime
|
||||
*/
|
||||
if (*new_lifetime < rfd->min_prefix_lifetime)
|
||||
{
|
||||
rfd->min_prefix_lifetime = *new_lifetime;
|
||||
}
|
||||
if (*new_lifetime > rfd->max_prefix_lifetime)
|
||||
{
|
||||
advertise = 1;
|
||||
rfd->max_prefix_lifetime = *new_lifetime;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Just adding new lifetime
|
||||
*/
|
||||
if (*new_lifetime < rfd->min_prefix_lifetime) {
|
||||
rfd->min_prefix_lifetime = *new_lifetime;
|
||||
}
|
||||
if (*new_lifetime > rfd->max_prefix_lifetime) {
|
||||
advertise = 1;
|
||||
rfd->max_prefix_lifetime = *new_lifetime;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Deleting
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Deleting
|
||||
*/
|
||||
/*
|
||||
* See if the max prefix lifetime for this NVE has decreased.
|
||||
* The easy optimization: track min & max; walk the table only
|
||||
* if they are different.
|
||||
* The general optimization: index the advertised_prefixes
|
||||
* table by lifetime.
|
||||
*
|
||||
* Note: for a given nve_descriptor, only one of the
|
||||
* advertised_prefixes[] tables will be used: viz., the
|
||||
* address family that matches the VN address.
|
||||
*
|
||||
*/
|
||||
if (rfd->max_prefix_lifetime == rfd->min_prefix_lifetime) {
|
||||
|
||||
/*
|
||||
* See if the max prefix lifetime for this NVE has decreased.
|
||||
* The easy optimization: track min & max; walk the table only
|
||||
* if they are different.
|
||||
* The general optimization: index the advertised_prefixes
|
||||
* table by lifetime.
|
||||
*
|
||||
* Note: for a given nve_descriptor, only one of the
|
||||
* advertised_prefixes[] tables will be used: viz., the
|
||||
* address family that matches the VN address.
|
||||
*
|
||||
*/
|
||||
if (rfd->max_prefix_lifetime == rfd->min_prefix_lifetime)
|
||||
{
|
||||
|
||||
/*
|
||||
* Common case: all lifetimes are the same. Only
|
||||
* thing we need to do here is check if there are
|
||||
* no exported routes left. In that case, reinitialize
|
||||
* the max and min values.
|
||||
*/
|
||||
if (!rfapiApCount (rfd))
|
||||
{
|
||||
rfd->max_prefix_lifetime = 0;
|
||||
rfd->min_prefix_lifetime = UINT32_MAX;
|
||||
}
|
||||
/*
|
||||
* Common case: all lifetimes are the same. Only
|
||||
* thing we need to do here is check if there are
|
||||
* no exported routes left. In that case, reinitialize
|
||||
* the max and min values.
|
||||
*/
|
||||
if (!rfapiApCount(rfd)) {
|
||||
rfd->max_prefix_lifetime = 0;
|
||||
rfd->min_prefix_lifetime = UINT32_MAX;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (old_lifetime)
|
||||
{
|
||||
if (*old_lifetime == rfd->min_prefix_lifetime)
|
||||
{
|
||||
find_min = 1;
|
||||
}
|
||||
if (*old_lifetime == rfd->max_prefix_lifetime)
|
||||
{
|
||||
find_max = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (old_lifetime) {
|
||||
if (*old_lifetime == rfd->min_prefix_lifetime) {
|
||||
find_min = 1;
|
||||
}
|
||||
if (*old_lifetime == rfd->max_prefix_lifetime) {
|
||||
find_max = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (find_min || find_max)
|
||||
{
|
||||
uint32_t min = UINT32_MAX;
|
||||
uint32_t max = 0;
|
||||
if (find_min || find_max) {
|
||||
uint32_t min = UINT32_MAX;
|
||||
uint32_t max = 0;
|
||||
|
||||
struct rfapi_adb *adb_min;
|
||||
struct rfapi_adb *adb_max;
|
||||
struct rfapi_adb *adb_min;
|
||||
struct rfapi_adb *adb_max;
|
||||
|
||||
if (!skiplist_first
|
||||
(rfd->advertised.by_lifetime, (void **) &adb_min, NULL)
|
||||
&& !skiplist_last (rfd->advertised.by_lifetime, (void **) &adb_max,
|
||||
NULL))
|
||||
{
|
||||
if (!skiplist_first(rfd->advertised.by_lifetime,
|
||||
(void **)&adb_min, NULL)
|
||||
&& !skiplist_last(rfd->advertised.by_lifetime,
|
||||
(void **)&adb_max, NULL)) {
|
||||
|
||||
/*
|
||||
* This should always work
|
||||
*/
|
||||
min = adb_min->lifetime;
|
||||
max = adb_max->lifetime;
|
||||
/*
|
||||
* This should always work
|
||||
*/
|
||||
min = adb_min->lifetime;
|
||||
max = adb_max->lifetime;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
|
||||
void *cursor;
|
||||
struct rfapi_rib_key rk;
|
||||
struct rfapi_adb *adb;
|
||||
int rc;
|
||||
void *cursor;
|
||||
struct rfapi_rib_key rk;
|
||||
struct rfapi_adb *adb;
|
||||
int rc;
|
||||
|
||||
vnc_zlog_debug_verbose ("%s: walking to find new min/max", __func__);
|
||||
vnc_zlog_debug_verbose(
|
||||
"%s: walking to find new min/max", __func__);
|
||||
|
||||
cursor = NULL;
|
||||
for (rc = skiplist_next (rfd->advertised.ipN_by_prefix,
|
||||
(void **) &rk, (void **) &adb,
|
||||
&cursor); !rc;
|
||||
rc =
|
||||
skiplist_next (rfd->advertised.ipN_by_prefix,
|
||||
(void **) &rk, (void **) &adb, &cursor))
|
||||
{
|
||||
cursor = NULL;
|
||||
for (rc = skiplist_next(rfd->advertised.ipN_by_prefix,
|
||||
(void **)&rk, (void **)&adb,
|
||||
&cursor);
|
||||
!rc;
|
||||
rc = skiplist_next(rfd->advertised.ipN_by_prefix,
|
||||
(void **)&rk, (void **)&adb,
|
||||
&cursor)) {
|
||||
|
||||
uint32_t lt = adb->lifetime;
|
||||
uint32_t lt = adb->lifetime;
|
||||
|
||||
if (lt > max)
|
||||
max = lt;
|
||||
if (lt < min)
|
||||
min = lt;
|
||||
}
|
||||
cursor = NULL;
|
||||
for (rc = skiplist_next (rfd->advertised.ip0_by_ether,
|
||||
(void **) &rk, (void **) &adb,
|
||||
&cursor); !rc;
|
||||
rc =
|
||||
skiplist_next (rfd->advertised.ip0_by_ether, (void **) &rk,
|
||||
(void **) &adb, &cursor))
|
||||
{
|
||||
if (lt > max)
|
||||
max = lt;
|
||||
if (lt < min)
|
||||
min = lt;
|
||||
}
|
||||
cursor = NULL;
|
||||
for (rc = skiplist_next(rfd->advertised.ip0_by_ether,
|
||||
(void **)&rk, (void **)&adb,
|
||||
&cursor);
|
||||
!rc;
|
||||
rc = skiplist_next(rfd->advertised.ip0_by_ether,
|
||||
(void **)&rk, (void **)&adb,
|
||||
&cursor)) {
|
||||
|
||||
uint32_t lt = adb->lifetime;
|
||||
uint32_t lt = adb->lifetime;
|
||||
|
||||
if (lt > max)
|
||||
max = lt;
|
||||
if (lt < min)
|
||||
min = lt;
|
||||
}
|
||||
}
|
||||
if (lt > max)
|
||||
max = lt;
|
||||
if (lt < min)
|
||||
min = lt;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* trigger tunnel route update
|
||||
* but only if we found a VPN route and it had
|
||||
* a lifetime greater than 0
|
||||
*/
|
||||
if (max && rfd->max_prefix_lifetime != max)
|
||||
advertise = 1;
|
||||
rfd->max_prefix_lifetime = max;
|
||||
rfd->min_prefix_lifetime = min;
|
||||
}
|
||||
/*
|
||||
* trigger tunnel route update
|
||||
* but only if we found a VPN route and it had
|
||||
* a lifetime greater than 0
|
||||
*/
|
||||
if (max && rfd->max_prefix_lifetime != max)
|
||||
advertise = 1;
|
||||
rfd->max_prefix_lifetime = max;
|
||||
rfd->min_prefix_lifetime = min;
|
||||
}
|
||||
|
||||
vnc_zlog_debug_verbose ("%s: returning advertise=%d, min=%d, max=%d",
|
||||
__func__, advertise, rfd->min_prefix_lifetime,
|
||||
rfd->max_prefix_lifetime);
|
||||
vnc_zlog_debug_verbose("%s: returning advertise=%d, min=%d, max=%d",
|
||||
__func__, advertise, rfd->min_prefix_lifetime,
|
||||
rfd->max_prefix_lifetime);
|
||||
|
||||
return (advertise != 0);
|
||||
return (advertise != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Return Value
|
||||
*
|
||||
* 0 No need to advertise tunnel route
|
||||
* non-0 advertise tunnel route
|
||||
*/
|
||||
int
|
||||
rfapiApAdd (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct prefix *pfx_ip,
|
||||
struct prefix *pfx_eth,
|
||||
struct prefix_rd *prd,
|
||||
uint32_t lifetime,
|
||||
uint8_t cost,
|
||||
struct rfapi_l2address_option *l2o) /* other options TBD */
|
||||
int rfapiApAdd(struct bgp *bgp, struct rfapi_descriptor *rfd,
|
||||
struct prefix *pfx_ip, struct prefix *pfx_eth,
|
||||
struct prefix_rd *prd, uint32_t lifetime, uint8_t cost,
|
||||
struct rfapi_l2address_option *l2o) /* other options TBD */
|
||||
{
|
||||
int rc;
|
||||
struct rfapi_adb *adb;
|
||||
uint32_t old_lifetime = 0;
|
||||
int use_ip0 = 0;
|
||||
struct rfapi_rib_key rk;
|
||||
int rc;
|
||||
struct rfapi_adb *adb;
|
||||
uint32_t old_lifetime = 0;
|
||||
int use_ip0 = 0;
|
||||
struct rfapi_rib_key rk;
|
||||
|
||||
rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk);
|
||||
if (RFAPI_0_PREFIX (pfx_ip) && RFAPI_HOST_PREFIX (pfx_ip))
|
||||
{
|
||||
use_ip0 = 1;
|
||||
assert (pfx_eth);
|
||||
rc =
|
||||
skiplist_search (rfd->advertised.ip0_by_ether, &rk,
|
||||
(void **) &adb);
|
||||
rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk);
|
||||
if (RFAPI_0_PREFIX(pfx_ip) && RFAPI_HOST_PREFIX(pfx_ip)) {
|
||||
use_ip0 = 1;
|
||||
assert(pfx_eth);
|
||||
rc = skiplist_search(rfd->advertised.ip0_by_ether, &rk,
|
||||
(void **)&adb);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
|
||||
/* find prefix in advertised prefixes list */
|
||||
rc =
|
||||
skiplist_search (rfd->advertised.ipN_by_prefix, &rk,
|
||||
(void **) &adb);
|
||||
}
|
||||
/* find prefix in advertised prefixes list */
|
||||
rc = skiplist_search(rfd->advertised.ipN_by_prefix, &rk,
|
||||
(void **)&adb);
|
||||
}
|
||||
|
||||
|
||||
if (rc)
|
||||
{
|
||||
/* Not found */
|
||||
adb = XCALLOC (MTYPE_RFAPI_ADB, sizeof (struct rfapi_adb));
|
||||
assert (adb);
|
||||
adb->lifetime = lifetime;
|
||||
adb->u.key = rk;
|
||||
if (rc) {
|
||||
/* Not found */
|
||||
adb = XCALLOC(MTYPE_RFAPI_ADB, sizeof(struct rfapi_adb));
|
||||
assert(adb);
|
||||
adb->lifetime = lifetime;
|
||||
adb->u.key = rk;
|
||||
|
||||
if (use_ip0)
|
||||
{
|
||||
assert (pfx_eth);
|
||||
skiplist_insert (rfd->advertised.ip0_by_ether, &adb->u.key,
|
||||
adb);
|
||||
}
|
||||
else
|
||||
{
|
||||
skiplist_insert (rfd->advertised.ipN_by_prefix, &adb->u.key,
|
||||
adb);
|
||||
}
|
||||
if (use_ip0) {
|
||||
assert(pfx_eth);
|
||||
skiplist_insert(rfd->advertised.ip0_by_ether,
|
||||
&adb->u.key, adb);
|
||||
} else {
|
||||
skiplist_insert(rfd->advertised.ipN_by_prefix,
|
||||
&adb->u.key, adb);
|
||||
}
|
||||
|
||||
skiplist_insert (rfd->advertised.by_lifetime, adb, adb);
|
||||
}
|
||||
else
|
||||
{
|
||||
old_lifetime = adb->lifetime;
|
||||
if (old_lifetime != lifetime)
|
||||
{
|
||||
assert (!skiplist_delete (rfd->advertised.by_lifetime, adb, NULL));
|
||||
adb->lifetime = lifetime;
|
||||
assert (!skiplist_insert (rfd->advertised.by_lifetime, adb, adb));
|
||||
}
|
||||
}
|
||||
adb->cost = cost;
|
||||
if (l2o)
|
||||
adb->l2o = *l2o;
|
||||
else
|
||||
memset (&adb->l2o, 0, sizeof (struct rfapi_l2address_option));
|
||||
skiplist_insert(rfd->advertised.by_lifetime, adb, adb);
|
||||
} else {
|
||||
old_lifetime = adb->lifetime;
|
||||
if (old_lifetime != lifetime) {
|
||||
assert(!skiplist_delete(rfd->advertised.by_lifetime,
|
||||
adb, NULL));
|
||||
adb->lifetime = lifetime;
|
||||
assert(!skiplist_insert(rfd->advertised.by_lifetime,
|
||||
adb, adb));
|
||||
}
|
||||
}
|
||||
adb->cost = cost;
|
||||
if (l2o)
|
||||
adb->l2o = *l2o;
|
||||
else
|
||||
memset(&adb->l2o, 0, sizeof(struct rfapi_l2address_option));
|
||||
|
||||
if (rfapiApAdjustLifetimeStats
|
||||
(rfd, (rc ? NULL : &old_lifetime), &lifetime))
|
||||
return 1;
|
||||
if (rfapiApAdjustLifetimeStats(rfd, (rc ? NULL : &old_lifetime),
|
||||
&lifetime))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* After this function returns successfully, caller should call
|
||||
* rfapiAdjustLifetimeStats() and possibly rfapiTunnelRouteAnnounce()
|
||||
*/
|
||||
int
|
||||
rfapiApDelete (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct prefix *pfx_ip,
|
||||
struct prefix *pfx_eth,
|
||||
struct prefix_rd *prd,
|
||||
int *advertise_tunnel) /* out */
|
||||
int rfapiApDelete(struct bgp *bgp, struct rfapi_descriptor *rfd,
|
||||
struct prefix *pfx_ip, struct prefix *pfx_eth,
|
||||
struct prefix_rd *prd, int *advertise_tunnel) /* out */
|
||||
{
|
||||
int rc;
|
||||
struct rfapi_adb *adb;
|
||||
uint32_t old_lifetime;
|
||||
int use_ip0 = 0;
|
||||
struct rfapi_rib_key rk;
|
||||
int rc;
|
||||
struct rfapi_adb *adb;
|
||||
uint32_t old_lifetime;
|
||||
int use_ip0 = 0;
|
||||
struct rfapi_rib_key rk;
|
||||
|
||||
if (advertise_tunnel)
|
||||
*advertise_tunnel = 0;
|
||||
if (advertise_tunnel)
|
||||
*advertise_tunnel = 0;
|
||||
|
||||
rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk);
|
||||
/* find prefix in advertised prefixes list */
|
||||
if (RFAPI_0_PREFIX (pfx_ip) && RFAPI_HOST_PREFIX (pfx_ip))
|
||||
{
|
||||
use_ip0 = 1;
|
||||
assert (pfx_eth);
|
||||
rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk);
|
||||
/* find prefix in advertised prefixes list */
|
||||
if (RFAPI_0_PREFIX(pfx_ip) && RFAPI_HOST_PREFIX(pfx_ip)) {
|
||||
use_ip0 = 1;
|
||||
assert(pfx_eth);
|
||||
|
||||
rc =
|
||||
skiplist_search (rfd->advertised.ip0_by_ether, &rk,
|
||||
(void **) &adb);
|
||||
rc = skiplist_search(rfd->advertised.ip0_by_ether, &rk,
|
||||
(void **)&adb);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
|
||||
/* find prefix in advertised prefixes list */
|
||||
rc =
|
||||
skiplist_search (rfd->advertised.ipN_by_prefix, &rk,
|
||||
(void **) &adb);
|
||||
}
|
||||
/* find prefix in advertised prefixes list */
|
||||
rc = skiplist_search(rfd->advertised.ipN_by_prefix, &rk,
|
||||
(void **)&adb);
|
||||
}
|
||||
|
||||
if (rc)
|
||||
{
|
||||
return ENOENT;
|
||||
}
|
||||
if (rc) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
old_lifetime = adb->lifetime;
|
||||
old_lifetime = adb->lifetime;
|
||||
|
||||
if (use_ip0)
|
||||
{
|
||||
rc = skiplist_delete (rfd->advertised.ip0_by_ether, &rk, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = skiplist_delete (rfd->advertised.ipN_by_prefix, &rk, NULL);
|
||||
}
|
||||
assert (!rc);
|
||||
if (use_ip0) {
|
||||
rc = skiplist_delete(rfd->advertised.ip0_by_ether, &rk, NULL);
|
||||
} else {
|
||||
rc = skiplist_delete(rfd->advertised.ipN_by_prefix, &rk, NULL);
|
||||
}
|
||||
assert(!rc);
|
||||
|
||||
rc = skiplist_delete (rfd->advertised.by_lifetime, adb, NULL);
|
||||
assert (!rc);
|
||||
rc = skiplist_delete(rfd->advertised.by_lifetime, adb, NULL);
|
||||
assert(!rc);
|
||||
|
||||
rfapiAdbFree (adb);
|
||||
rfapiAdbFree(adb);
|
||||
|
||||
if (rfapiApAdjustLifetimeStats (rfd, &old_lifetime, NULL))
|
||||
{
|
||||
if (advertise_tunnel)
|
||||
*advertise_tunnel = 1;
|
||||
}
|
||||
if (rfapiApAdjustLifetimeStats(rfd, &old_lifetime, NULL)) {
|
||||
if (advertise_tunnel)
|
||||
*advertise_tunnel = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Copyright 2009-2016, LabN Consulting, L.L.C.
|
||||
*
|
||||
@ -56,44 +56,30 @@
|
||||
#include "rfapi_rib.h"
|
||||
|
||||
|
||||
extern void
|
||||
rfapiApInit (struct rfapi_advertised_prefixes *ap);
|
||||
extern void rfapiApInit(struct rfapi_advertised_prefixes *ap);
|
||||
|
||||
extern void
|
||||
rfapiApRelease (struct rfapi_advertised_prefixes *ap);
|
||||
extern void rfapiApRelease(struct rfapi_advertised_prefixes *ap);
|
||||
|
||||
extern int rfapiApCount(struct rfapi_descriptor *rfd);
|
||||
|
||||
|
||||
extern int rfapiApCountAll(struct bgp *bgp);
|
||||
|
||||
extern void rfapiApReadvertiseAll(struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd);
|
||||
|
||||
extern void rfapiApWithdrawAll(struct bgp *bgp, struct rfapi_descriptor *rfd);
|
||||
|
||||
extern int
|
||||
rfapiApCount (struct rfapi_descriptor *rfd);
|
||||
rfapiApAdd(struct bgp *bgp, struct rfapi_descriptor *rfd, struct prefix *pfx_ip,
|
||||
struct prefix *pfx_eth, struct prefix_rd *prd, uint32_t lifetime,
|
||||
uint8_t cost,
|
||||
struct rfapi_l2address_option *l2o); /* other options TBD */
|
||||
|
||||
|
||||
extern int
|
||||
rfapiApCountAll (struct bgp *bgp);
|
||||
|
||||
extern void
|
||||
rfapiApReadvertiseAll (struct bgp *bgp, struct rfapi_descriptor *rfd);
|
||||
|
||||
extern void
|
||||
rfapiApWithdrawAll (struct bgp *bgp, struct rfapi_descriptor *rfd);
|
||||
|
||||
extern int
|
||||
rfapiApAdd (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct prefix *pfx_ip,
|
||||
struct prefix *pfx_eth,
|
||||
struct prefix_rd *prd,
|
||||
uint32_t lifetime,
|
||||
uint8_t cost,
|
||||
struct rfapi_l2address_option *l2o); /* other options TBD */
|
||||
|
||||
extern int
|
||||
rfapiApDelete (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct prefix *pfx_ip,
|
||||
struct prefix *pfx_eth,
|
||||
struct prefix_rd *prd,
|
||||
int *advertise_tunnel); /* out */
|
||||
extern int rfapiApDelete(struct bgp *bgp, struct rfapi_descriptor *rfd,
|
||||
struct prefix *pfx_ip, struct prefix *pfx_eth,
|
||||
struct prefix_rd *prd,
|
||||
int *advertise_tunnel); /* out */
|
||||
|
||||
|
||||
#endif /* _QUAGGA_BGP_RFAPI_AP_H */
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Copyright 2009-2016, LabN Consulting, L.L.C.
|
||||
*
|
||||
@ -26,56 +26,44 @@
|
||||
#include "bgpd/bgp_route.h"
|
||||
#include "bgpd/bgp_nexthop.h"
|
||||
|
||||
extern void rfapi_init (void);
|
||||
extern void vnc_zebra_init (struct thread_master *master);
|
||||
extern void vnc_zebra_destroy (void);
|
||||
extern void rfapi_init(void);
|
||||
extern void vnc_zebra_init(struct thread_master *master);
|
||||
extern void vnc_zebra_destroy(void);
|
||||
|
||||
extern void rfapi_delete (struct bgp *);
|
||||
extern void rfapi_delete(struct bgp *);
|
||||
|
||||
struct rfapi *bgp_rfapi_new (struct bgp *bgp);
|
||||
void bgp_rfapi_destroy (struct bgp *bgp, struct rfapi *h);
|
||||
struct rfapi *bgp_rfapi_new(struct bgp *bgp);
|
||||
void bgp_rfapi_destroy(struct bgp *bgp, struct rfapi *h);
|
||||
|
||||
extern void
|
||||
rfapiProcessUpdate (struct peer *peer,
|
||||
void *rfd,
|
||||
struct prefix *p,
|
||||
struct prefix_rd *prd,
|
||||
struct attr *attr,
|
||||
afi_t afi,
|
||||
safi_t safi,
|
||||
u_char type, u_char sub_type, uint32_t * label);
|
||||
extern void rfapiProcessUpdate(struct peer *peer, void *rfd, struct prefix *p,
|
||||
struct prefix_rd *prd, struct attr *attr,
|
||||
afi_t afi, safi_t safi, u_char type,
|
||||
u_char sub_type, uint32_t *label);
|
||||
|
||||
|
||||
extern void
|
||||
rfapiProcessWithdraw (struct peer *peer,
|
||||
void *rfd,
|
||||
struct prefix *p,
|
||||
struct prefix_rd *prd,
|
||||
struct attr *attr,
|
||||
afi_t afi, safi_t safi, u_char type, int kill);
|
||||
extern void rfapiProcessWithdraw(struct peer *peer, void *rfd, struct prefix *p,
|
||||
struct prefix_rd *prd, struct attr *attr,
|
||||
afi_t afi, safi_t safi, u_char type, int kill);
|
||||
|
||||
extern void rfapiProcessPeerDown (struct peer *peer);
|
||||
extern void rfapiProcessPeerDown(struct peer *peer);
|
||||
|
||||
extern void
|
||||
vnc_zebra_announce (struct prefix *p,
|
||||
struct bgp_info *new_select, struct bgp *bgp);
|
||||
extern void vnc_zebra_announce(struct prefix *p, struct bgp_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_info *old_select);
|
||||
|
||||
|
||||
extern void
|
||||
rfapi_vty_out_vncinfo (struct vty *vty,
|
||||
struct prefix *p, struct bgp_info *bi, safi_t safi);
|
||||
extern void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p,
|
||||
struct bgp_info *bi, safi_t safi);
|
||||
|
||||
|
||||
extern void vnc_direct_bgp_vpn_enable (struct bgp *bgp, afi_t afi);
|
||||
extern void vnc_direct_bgp_vpn_enable(struct bgp *bgp, afi_t afi);
|
||||
|
||||
extern void vnc_direct_bgp_vpn_disable (struct bgp *bgp, afi_t afi);
|
||||
extern void vnc_direct_bgp_vpn_disable(struct bgp *bgp, afi_t afi);
|
||||
|
||||
extern void vnc_direct_bgp_rh_vpn_enable (struct bgp *bgp, afi_t afi);
|
||||
extern void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi);
|
||||
|
||||
extern void vnc_direct_bgp_rh_vpn_disable (struct bgp *bgp, afi_t afi);
|
||||
extern void vnc_direct_bgp_rh_vpn_disable(struct bgp *bgp, afi_t afi);
|
||||
|
||||
#endif /* ENABLE_BGP_VNC */
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Copyright 2009-2016, LabN Consulting, L.L.C.
|
||||
*
|
||||
@ -36,15 +36,14 @@
|
||||
#include "bgpd/rfapi/vnc_debug.h"
|
||||
|
||||
|
||||
void *
|
||||
rfapi_create_generic (struct rfapi_ip_addr *vn, struct rfapi_ip_addr *un)
|
||||
void *rfapi_create_generic(struct rfapi_ip_addr *vn, struct rfapi_ip_addr *un)
|
||||
{
|
||||
struct rfapi_descriptor *rfd;
|
||||
rfd = XCALLOC (MTYPE_RFAPI_DESC, sizeof (struct rfapi_descriptor));
|
||||
vnc_zlog_debug_verbose ("%s: rfd=%p", __func__, rfd);
|
||||
rfd->vn_addr = *vn;
|
||||
rfd->un_addr = *un;
|
||||
return (void *) rfd;
|
||||
struct rfapi_descriptor *rfd;
|
||||
rfd = XCALLOC(MTYPE_RFAPI_DESC, sizeof(struct rfapi_descriptor));
|
||||
vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd);
|
||||
rfd->vn_addr = *vn;
|
||||
rfd->un_addr = *un;
|
||||
return (void *)rfd;
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
@ -52,20 +51,19 @@ rfapi_create_generic (struct rfapi_ip_addr *vn, struct rfapi_ip_addr *un)
|
||||
*
|
||||
* Compare two generic rfapi descriptors.
|
||||
*
|
||||
* input:
|
||||
* input:
|
||||
* grfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
|
||||
*
|
||||
* output:
|
||||
*
|
||||
* return value:
|
||||
* return value:
|
||||
*
|
||||
*------------------------------------------*/
|
||||
void
|
||||
rfapi_free_generic (void *grfd)
|
||||
void rfapi_free_generic(void *grfd)
|
||||
{
|
||||
struct rfapi_descriptor *rfd;
|
||||
rfd = (struct rfapi_descriptor *) grfd;
|
||||
XFREE (MTYPE_RFAPI_DESC, rfd);
|
||||
struct rfapi_descriptor *rfd;
|
||||
rfd = (struct rfapi_descriptor *)grfd;
|
||||
XFREE(MTYPE_RFAPI_DESC, rfd);
|
||||
}
|
||||
|
||||
|
||||
@ -74,7 +72,7 @@ rfapi_free_generic (void *grfd)
|
||||
*
|
||||
* Compare two generic rfapi descriptors.
|
||||
*
|
||||
* input:
|
||||
* input:
|
||||
* rfd1: rfapi descriptor returned by rfapi_open or rfapi_create_generic
|
||||
* rfd2: rfapi descriptor returned by rfapi_open or rfapi_create_generic
|
||||
*
|
||||
@ -84,48 +82,45 @@ rfapi_free_generic (void *grfd)
|
||||
* 0 Mismatch
|
||||
* 1 Match
|
||||
*------------------------------------------*/
|
||||
int
|
||||
rfapi_compare_rfds (void *rfd1, void *rfd2)
|
||||
int rfapi_compare_rfds(void *rfd1, void *rfd2)
|
||||
{
|
||||
struct rfapi_descriptor *rrfd1, *rrfd2;
|
||||
int match = 0;
|
||||
struct rfapi_descriptor *rrfd1, *rrfd2;
|
||||
int match = 0;
|
||||
|
||||
rrfd1 = (struct rfapi_descriptor *) rfd1;
|
||||
rrfd2 = (struct rfapi_descriptor *) rfd2;
|
||||
rrfd1 = (struct rfapi_descriptor *)rfd1;
|
||||
rrfd2 = (struct rfapi_descriptor *)rfd2;
|
||||
|
||||
if (rrfd1->vn_addr.addr_family == rrfd2->vn_addr.addr_family)
|
||||
{
|
||||
if (rrfd1->vn_addr.addr_family == AF_INET)
|
||||
match = IPV4_ADDR_SAME (&(rrfd1->vn_addr.addr.v4),
|
||||
&(rrfd2->vn_addr.addr.v4));
|
||||
else
|
||||
match = IPV6_ADDR_SAME (&(rrfd1->vn_addr.addr.v6),
|
||||
&(rrfd2->vn_addr.addr.v6));
|
||||
}
|
||||
if (rrfd1->vn_addr.addr_family == rrfd2->vn_addr.addr_family) {
|
||||
if (rrfd1->vn_addr.addr_family == AF_INET)
|
||||
match = IPV4_ADDR_SAME(&(rrfd1->vn_addr.addr.v4),
|
||||
&(rrfd2->vn_addr.addr.v4));
|
||||
else
|
||||
match = IPV6_ADDR_SAME(&(rrfd1->vn_addr.addr.v6),
|
||||
&(rrfd2->vn_addr.addr.v6));
|
||||
}
|
||||
|
||||
/*
|
||||
* If the VN addresses don't match in all forms,
|
||||
* give up.
|
||||
*/
|
||||
if (!match)
|
||||
return 0;
|
||||
/*
|
||||
* If the VN addresses don't match in all forms,
|
||||
* give up.
|
||||
*/
|
||||
if (!match)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* do the process again for the UN addresses.
|
||||
*/
|
||||
match = 0;
|
||||
if (rrfd1->un_addr.addr_family == rrfd2->un_addr.addr_family)
|
||||
{
|
||||
/* VN addresses match
|
||||
* UN address families match
|
||||
* now check the actual UN addresses
|
||||
*/
|
||||
if (rrfd1->un_addr.addr_family == AF_INET)
|
||||
match = IPV4_ADDR_SAME (&(rrfd1->un_addr.addr.v4),
|
||||
&(rrfd2->un_addr.addr.v4));
|
||||
else
|
||||
match = IPV6_ADDR_SAME (&(rrfd1->un_addr.addr.v6),
|
||||
&(rrfd2->un_addr.addr.v6));
|
||||
}
|
||||
return match;
|
||||
/*
|
||||
* do the process again for the UN addresses.
|
||||
*/
|
||||
match = 0;
|
||||
if (rrfd1->un_addr.addr_family == rrfd2->un_addr.addr_family) {
|
||||
/* VN addresses match
|
||||
* UN address families match
|
||||
* now check the actual UN addresses
|
||||
*/
|
||||
if (rrfd1->un_addr.addr_family == AF_INET)
|
||||
match = IPV4_ADDR_SAME(&(rrfd1->un_addr.addr.v4),
|
||||
&(rrfd2->un_addr.addr.v4));
|
||||
else
|
||||
match = IPV6_ADDR_SAME(&(rrfd1->un_addr.addr.v6),
|
||||
&(rrfd2->un_addr.addr.v6));
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Copyright 2009-2016, LabN Consulting, L.L.C.
|
||||
*
|
||||
@ -19,20 +19,20 @@
|
||||
*/
|
||||
|
||||
|
||||
extern void *rfapi_create_generic (struct rfapi_ip_addr *vn,
|
||||
struct rfapi_ip_addr *un);
|
||||
extern void *rfapi_create_generic(struct rfapi_ip_addr *vn,
|
||||
struct rfapi_ip_addr *un);
|
||||
|
||||
/*------------------------------------------
|
||||
* rfapi_free_generic
|
||||
*
|
||||
* Compare two generic rfapi descriptors.
|
||||
*
|
||||
* input:
|
||||
* input:
|
||||
* grfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
|
||||
*
|
||||
* output:
|
||||
*
|
||||
* return value:
|
||||
* return value:
|
||||
*
|
||||
*------------------------------------------*/
|
||||
extern void rfapi_free_generic (void *grfd);
|
||||
extern void rfapi_free_generic(void *grfd);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright 2015-2016, LabN Consulting, L.L.C.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@ -22,21 +22,14 @@
|
||||
#define RFAPI_BGP_ENCAP_TYPE_DEFAULT BGP_ENCAP_TYPE_IP_IN_IP
|
||||
|
||||
extern bgp_encap_types
|
||||
rfapi_tunneltype_option_to_tlv (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_ip_addr *ea,
|
||||
struct rfapi_tunneltype_option *tto,
|
||||
struct attr *attr,
|
||||
int always_add);
|
||||
rfapi_tunneltype_option_to_tlv(struct bgp *bgp, struct rfapi_ip_addr *ea,
|
||||
struct rfapi_tunneltype_option *tto,
|
||||
struct attr *attr, int always_add);
|
||||
|
||||
extern struct rfapi_un_option *
|
||||
rfapi_encap_tlv_to_un_option (struct attr *attr);
|
||||
extern struct rfapi_un_option *rfapi_encap_tlv_to_un_option(struct attr *attr);
|
||||
|
||||
extern void
|
||||
rfapi_print_tunneltype_option (
|
||||
void *stream,
|
||||
int column_offset,
|
||||
struct rfapi_tunneltype_option *tto);
|
||||
extern void rfapi_print_tunneltype_option(void *stream, int column_offset,
|
||||
struct rfapi_tunneltype_option *tto);
|
||||
|
||||
|
||||
#endif /* _QUAGGA_BGP_RFAPI_ENCAP_TLV_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Copyright 2009-2016, LabN Consulting, L.L.C.
|
||||
*
|
||||
@ -34,72 +34,60 @@
|
||||
* routes are not segregated by RD - the RD is stored in bgp_info_extra
|
||||
* and is needed to determine if two prefixes are the same.
|
||||
*/
|
||||
struct rfapi_import_table
|
||||
{
|
||||
struct rfapi_import_table *next;
|
||||
struct rfapi_nve_group_cfg *rfg;
|
||||
struct ecommunity *rt_import_list; /* copied from nve grp */
|
||||
int refcount; /* nve grps and nves */
|
||||
uint32_t l2_logical_net_id; /* L2 only: EVPN Eth Seg Id */
|
||||
struct route_table *imported_vpn[AFI_MAX];
|
||||
struct rfapi_monitor_vpn *vpn0_queries[AFI_MAX];
|
||||
struct rfapi_monitor_eth *eth0_queries;
|
||||
struct route_table *imported_encap[AFI_MAX];
|
||||
struct skiplist *monitor_exterior_orphans;
|
||||
int local_count[AFI_MAX];
|
||||
int remote_count[AFI_MAX];
|
||||
int holddown_count[AFI_MAX];
|
||||
int imported_count[AFI_MAX];
|
||||
struct rfapi_import_table {
|
||||
struct rfapi_import_table *next;
|
||||
struct rfapi_nve_group_cfg *rfg;
|
||||
struct ecommunity *rt_import_list; /* copied from nve grp */
|
||||
int refcount; /* nve grps and nves */
|
||||
uint32_t l2_logical_net_id; /* L2 only: EVPN Eth Seg Id */
|
||||
struct route_table *imported_vpn[AFI_MAX];
|
||||
struct rfapi_monitor_vpn *vpn0_queries[AFI_MAX];
|
||||
struct rfapi_monitor_eth *eth0_queries;
|
||||
struct route_table *imported_encap[AFI_MAX];
|
||||
struct skiplist *monitor_exterior_orphans;
|
||||
int local_count[AFI_MAX];
|
||||
int remote_count[AFI_MAX];
|
||||
int holddown_count[AFI_MAX];
|
||||
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(bi) \
|
||||
(((bi)->type == ZEBRA_ROUTE_BGP) && ((bi)->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(bi) \
|
||||
(((bi)->type == ZEBRA_ROUTE_BGP_DIRECT) \
|
||||
|| ((bi)->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))
|
||||
|
||||
#define RFAPI_UPDATE_ITABLE_COUNT(bi, itable, afi, cnt) \
|
||||
if (RFAPI_LOCAL_BI(bi)) { \
|
||||
(itable)->local_count[(afi)] += (cnt); \
|
||||
} else { \
|
||||
if (RFAPI_DIRECT_IMPORT_BI(bi)) \
|
||||
(itable)->imported_count[(afi)] += (cnt); \
|
||||
else \
|
||||
(itable)->remote_count[(afi)] += (cnt); \
|
||||
}
|
||||
#define RFAPI_UPDATE_ITABLE_COUNT(bi, itable, afi, cnt) \
|
||||
if (RFAPI_LOCAL_BI(bi)) { \
|
||||
(itable)->local_count[(afi)] += (cnt); \
|
||||
} else { \
|
||||
if (RFAPI_DIRECT_IMPORT_BI(bi)) \
|
||||
(itable)->imported_count[(afi)] += (cnt); \
|
||||
else \
|
||||
(itable)->remote_count[(afi)] += (cnt); \
|
||||
}
|
||||
|
||||
extern uint8_t
|
||||
rfapiRfpCost (struct attr *attr);
|
||||
extern uint8_t rfapiRfpCost(struct attr *attr);
|
||||
|
||||
extern void
|
||||
rfapiDebugBacktrace (void);
|
||||
extern void rfapiDebugBacktrace(void);
|
||||
|
||||
extern void
|
||||
rfapiCheckRouteCount (void);
|
||||
extern void rfapiCheckRouteCount(void);
|
||||
|
||||
/*
|
||||
* Print BI in an Import Table
|
||||
*/
|
||||
extern void
|
||||
rfapiPrintBi (void *stream, struct bgp_info *bi);
|
||||
extern void rfapiPrintBi(void *stream, struct bgp_info *bi);
|
||||
|
||||
extern void
|
||||
rfapiShowImportTable (
|
||||
void *stream,
|
||||
const char *label,
|
||||
struct route_table *rt,
|
||||
int isvpn);
|
||||
extern void rfapiShowImportTable(void *stream, const char *label,
|
||||
struct route_table *rt, int isvpn);
|
||||
|
||||
extern struct rfapi_import_table *
|
||||
rfapiImportTableRefAdd (
|
||||
struct bgp *bgp,
|
||||
struct ecommunity *rt_import_list,
|
||||
struct rfapi_nve_group_cfg *rfg);
|
||||
rfapiImportTableRefAdd(struct bgp *bgp, struct ecommunity *rt_import_list,
|
||||
struct rfapi_nve_group_cfg *rfg);
|
||||
|
||||
extern void
|
||||
rfapiImportTableRefDelByIt (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_import_table *it_target);
|
||||
extern void rfapiImportTableRefDelByIt(struct bgp *bgp,
|
||||
struct rfapi_import_table *it_target);
|
||||
|
||||
|
||||
/*
|
||||
@ -111,106 +99,78 @@ rfapiImportTableRefDelByIt (
|
||||
* 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.
|
||||
*/
|
||||
extern struct rfapi_next_hop_entry *
|
||||
rfapiRouteNode2NextHopList (
|
||||
struct route_node *rn,
|
||||
uint32_t lifetime, /* put into nexthop entries */
|
||||
struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */
|
||||
struct route_table *rfd_rib_table, /* preload this NVE rib table */
|
||||
struct prefix *pfx_target_original); /* query target */
|
||||
extern struct rfapi_next_hop_entry *rfapiRouteNode2NextHopList(
|
||||
struct route_node *rn, uint32_t lifetime, /* put into nexthop entries */
|
||||
struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */
|
||||
struct route_table *rfd_rib_table, /* preload this NVE rib table */
|
||||
struct prefix *pfx_target_original); /* query target */
|
||||
|
||||
extern struct rfapi_next_hop_entry *
|
||||
rfapiRouteTable2NextHopList (
|
||||
struct route_table *rt,
|
||||
uint32_t lifetime, /* put into nexthop entries */
|
||||
struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */
|
||||
struct route_table *rfd_rib_table, /* preload this NVE rib table */
|
||||
struct prefix *pfx_target_original); /* query target */
|
||||
extern struct rfapi_next_hop_entry *rfapiRouteTable2NextHopList(
|
||||
struct route_table *rt,
|
||||
uint32_t lifetime, /* put into nexthop entries */
|
||||
struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */
|
||||
struct route_table *rfd_rib_table, /* preload this NVE rib table */
|
||||
struct prefix *pfx_target_original); /* query target */
|
||||
|
||||
extern struct rfapi_next_hop_entry *
|
||||
rfapiEthRouteTable2NextHopList (
|
||||
uint32_t logical_net_id,
|
||||
struct rfapi_ip_prefix *rprefix,
|
||||
uint32_t lifetime, /* put into nexthop entries */
|
||||
struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */
|
||||
struct route_table *rib_route_table,/* preload NVE rib node */
|
||||
struct prefix *pfx_target_original); /* query target */
|
||||
extern struct rfapi_next_hop_entry *rfapiEthRouteTable2NextHopList(
|
||||
uint32_t logical_net_id, struct rfapi_ip_prefix *rprefix,
|
||||
uint32_t lifetime, /* put into nexthop entries */
|
||||
struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */
|
||||
struct route_table *rib_route_table, /* preload NVE rib node */
|
||||
struct prefix *pfx_target_original); /* query target */
|
||||
|
||||
extern int
|
||||
rfapiEcommunitiesIntersect (struct ecommunity *e1, struct ecommunity *e2);
|
||||
extern int rfapiEcommunitiesIntersect(struct ecommunity *e1,
|
||||
struct ecommunity *e2);
|
||||
|
||||
extern void
|
||||
rfapiCheckRefcount (struct route_node *rn, safi_t safi, int lockoffset);
|
||||
extern void rfapiCheckRefcount(struct route_node *rn, safi_t safi,
|
||||
int lockoffset);
|
||||
|
||||
extern int
|
||||
rfapiHasNonRemovedRoutes (struct route_node *rn);
|
||||
extern int rfapiHasNonRemovedRoutes(struct route_node *rn);
|
||||
|
||||
extern int
|
||||
rfapiProcessDeferredClose (struct thread *t);
|
||||
extern int rfapiProcessDeferredClose(struct thread *t);
|
||||
|
||||
extern int
|
||||
rfapiGetUnAddrOfVpnBi (struct bgp_info *bi, struct prefix *p);
|
||||
extern int rfapiGetUnAddrOfVpnBi(struct bgp_info *bi, struct prefix *p);
|
||||
|
||||
extern void
|
||||
rfapiNexthop2Prefix (struct attr *attr, struct prefix *p);
|
||||
extern void rfapiNexthop2Prefix(struct attr *attr, struct prefix *p);
|
||||
|
||||
extern void
|
||||
rfapiUnicastNexthop2Prefix (
|
||||
afi_t afi,
|
||||
struct attr *attr,
|
||||
struct prefix *p);
|
||||
extern void rfapiUnicastNexthop2Prefix(afi_t afi, struct attr *attr,
|
||||
struct prefix *p);
|
||||
|
||||
/* Filtered Import Function actions */
|
||||
#define FIF_ACTION_UPDATE 0
|
||||
#define FIF_ACTION_WITHDRAW 1
|
||||
#define FIF_ACTION_KILL 2
|
||||
|
||||
extern void
|
||||
rfapiBgpInfoFilteredImportVPN (
|
||||
struct rfapi_import_table *import_table,
|
||||
int action,
|
||||
struct peer *peer,
|
||||
void *rfd, /* set for looped back routes */
|
||||
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 */
|
||||
u_char type, /* part of bgp_info */
|
||||
u_char sub_type, /* part of bgp_info */
|
||||
uint32_t *label); /* part of bgp_info */
|
||||
extern void rfapiBgpInfoFilteredImportVPN(
|
||||
struct rfapi_import_table *import_table, int action, struct peer *peer,
|
||||
void *rfd, /* set for looped back routes */
|
||||
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 */
|
||||
u_char type, /* part of bgp_info */
|
||||
u_char sub_type, /* part of bgp_info */
|
||||
uint32_t *label); /* part of bgp_info */
|
||||
|
||||
extern struct rfapi_next_hop_entry *
|
||||
rfapiEthRouteNode2NextHopList (
|
||||
struct route_node *rn,
|
||||
struct rfapi_ip_prefix *rprefix,
|
||||
uint32_t lifetime, /* put into nexthop entries */
|
||||
struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */
|
||||
struct route_table *rib_route_table,/* preload NVE rib table */
|
||||
struct prefix *pfx_target_original); /* query target */
|
||||
extern struct rfapi_next_hop_entry *rfapiEthRouteNode2NextHopList(
|
||||
struct route_node *rn, struct rfapi_ip_prefix *rprefix,
|
||||
uint32_t lifetime, /* put into nexthop entries */
|
||||
struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */
|
||||
struct route_table *rib_route_table, /* preload NVE rib table */
|
||||
struct prefix *pfx_target_original); /* query target */
|
||||
|
||||
extern struct rfapi_import_table *
|
||||
rfapiMacImportTableGetNoAlloc (
|
||||
struct bgp *bgp,
|
||||
uint32_t lni);
|
||||
extern struct rfapi_import_table *rfapiMacImportTableGetNoAlloc(struct bgp *bgp,
|
||||
uint32_t lni);
|
||||
|
||||
extern struct rfapi_import_table *
|
||||
rfapiMacImportTableGet (
|
||||
struct bgp *bgp,
|
||||
uint32_t lni);
|
||||
extern struct rfapi_import_table *rfapiMacImportTableGet(struct bgp *bgp,
|
||||
uint32_t lni);
|
||||
|
||||
extern int
|
||||
rfapiGetL2o (
|
||||
struct attr *attr,
|
||||
struct rfapi_l2address_option *l2o);
|
||||
extern int rfapiGetL2o(struct attr *attr, struct rfapi_l2address_option *l2o);
|
||||
|
||||
extern int rfapiEcommunityGetLNI (
|
||||
struct ecommunity *ecom,
|
||||
uint32_t *lni);
|
||||
extern int rfapiEcommunityGetLNI(struct ecommunity *ecom, uint32_t *lni);
|
||||
|
||||
extern int rfapiEcommunityGetEthernetTag (
|
||||
struct ecommunity *ecom,
|
||||
uint16_t * tag_id);
|
||||
extern int rfapiEcommunityGetEthernetTag(struct ecommunity *ecom,
|
||||
uint16_t *tag_id);
|
||||
|
||||
/* enable for debugging; disable for performance */
|
||||
#if 0
|
||||
@ -224,7 +184,7 @@ extern int rfapiEcommunityGetEthernetTag (
|
||||
*
|
||||
* UI helper: For use by the "clear vnc prefixes" command
|
||||
*
|
||||
* input:
|
||||
* input:
|
||||
* un if set, tunnel must match this prefix
|
||||
* vn if set, nexthop prefix must match this prefix
|
||||
* p if set, prefix must match this prefix
|
||||
@ -239,25 +199,21 @@ extern int rfapiEcommunityGetEthernetTag (
|
||||
* return value:
|
||||
* void
|
||||
--------------------------------------------*/
|
||||
extern void
|
||||
rfapiDeleteRemotePrefixes (
|
||||
struct prefix *un,
|
||||
struct prefix *vn,
|
||||
struct prefix *p,
|
||||
struct rfapi_import_table *it,
|
||||
int delete_active,
|
||||
int delete_holddown,
|
||||
uint32_t *pARcount, /* active routes */
|
||||
uint32_t *pAHcount, /* active nves */
|
||||
uint32_t *pHRcount, /* holddown routes */
|
||||
uint32_t *pHHcount); /* holddown nves */
|
||||
extern void rfapiDeleteRemotePrefixes(struct prefix *un, struct prefix *vn,
|
||||
struct prefix *p,
|
||||
struct rfapi_import_table *it,
|
||||
int delete_active, int delete_holddown,
|
||||
uint32_t *pARcount, /* active routes */
|
||||
uint32_t *pAHcount, /* active nves */
|
||||
uint32_t *pHRcount, /* holddown routes */
|
||||
uint32_t *pHHcount); /* holddown nves */
|
||||
|
||||
/*------------------------------------------
|
||||
* rfapiCountAllItRoutes
|
||||
*
|
||||
* UI helper: count VRF routes from BGP side
|
||||
*
|
||||
* input:
|
||||
* input:
|
||||
*
|
||||
* output
|
||||
* pARcount count of active routes
|
||||
@ -267,19 +223,17 @@ rfapiDeleteRemotePrefixes (
|
||||
* return value:
|
||||
* void
|
||||
--------------------------------------------*/
|
||||
extern void
|
||||
rfapiCountAllItRoutes (
|
||||
int *pALRcount, /* active local routes */
|
||||
int *pARRcount, /* active remote routes */
|
||||
int *pHRcount, /* holddown routes */
|
||||
int *pIRcount); /* direct imported routes */
|
||||
extern void rfapiCountAllItRoutes(int *pALRcount, /* active local routes */
|
||||
int *pARRcount, /* active remote routes */
|
||||
int *pHRcount, /* holddown routes */
|
||||
int *pIRcount); /* direct imported routes */
|
||||
|
||||
/*------------------------------------------
|
||||
* rfapiGetHolddownFromLifetime
|
||||
*
|
||||
* calculate holddown value based on lifetime
|
||||
*
|
||||
* input:
|
||||
* input:
|
||||
* lifetime lifetime
|
||||
*
|
||||
* return value:
|
||||
@ -287,7 +241,6 @@ rfapiCountAllItRoutes (
|
||||
* and RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY
|
||||
*
|
||||
--------------------------------------------*/
|
||||
extern uint32_t
|
||||
rfapiGetHolddownFromLifetime (uint32_t lifetime);
|
||||
extern uint32_t rfapiGetHolddownFromLifetime(uint32_t lifetime);
|
||||
|
||||
#endif /* QUAGGA_HGP_RFAPI_IMPORT_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Copyright 2009-2016, LabN Consulting, L.L.C.
|
||||
*
|
||||
@ -29,35 +29,32 @@
|
||||
* These get attached to the nodes in an import table (using "aggregate" ptr)
|
||||
* to indicate which nves are interested in a prefix/target
|
||||
*/
|
||||
struct rfapi_monitor_vpn
|
||||
{
|
||||
struct rfapi_monitor_vpn *next; /* chain from struct route_node */
|
||||
struct rfapi_descriptor *rfd; /* which NVE requested the route */
|
||||
struct prefix p; /* constant: pfx in original request */
|
||||
struct route_node *node; /* node we're currently attached to */
|
||||
uint32_t flags;
|
||||
struct rfapi_monitor_vpn {
|
||||
struct rfapi_monitor_vpn *next; /* chain from struct route_node */
|
||||
struct rfapi_descriptor *rfd; /* which NVE requested the route */
|
||||
struct prefix p; /* constant: pfx in original request */
|
||||
struct route_node *node; /* node we're currently attached to */
|
||||
uint32_t flags;
|
||||
#define RFAPI_MON_FLAG_NEEDCALLBACK 0x00000001 /* deferred callback */
|
||||
|
||||
//int dcount; /* debugging counter */
|
||||
struct thread *timer;
|
||||
// int dcount; /* debugging counter */
|
||||
struct thread *timer;
|
||||
};
|
||||
|
||||
struct rfapi_monitor_encap
|
||||
{
|
||||
struct rfapi_monitor_encap *next;
|
||||
struct rfapi_monitor_encap *prev;
|
||||
struct route_node *node; /* VPN node */
|
||||
struct bgp_info *bi; /* VPN bi */
|
||||
struct route_node *rn; /* parent node */
|
||||
struct rfapi_monitor_encap {
|
||||
struct rfapi_monitor_encap *next;
|
||||
struct rfapi_monitor_encap *prev;
|
||||
struct route_node *node; /* VPN node */
|
||||
struct bgp_info *bi; /* VPN bi */
|
||||
struct route_node *rn; /* parent node */
|
||||
};
|
||||
|
||||
struct rfapi_monitor_eth
|
||||
{
|
||||
struct rfapi_monitor_eth *next; /* for use in vpn0_queries list */
|
||||
struct rfapi_descriptor *rfd; /* which NVE requested the route */
|
||||
struct ethaddr macaddr;
|
||||
uint32_t logical_net_id;
|
||||
struct thread *timer;
|
||||
struct rfapi_monitor_eth {
|
||||
struct rfapi_monitor_eth *next; /* for use in vpn0_queries list */
|
||||
struct rfapi_descriptor *rfd; /* which NVE requested the route */
|
||||
struct ethaddr macaddr;
|
||||
uint32_t logical_net_id;
|
||||
struct thread *timer;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -75,142 +72,119 @@ struct rfapi_monitor_eth
|
||||
* - one lock per chained struct rfapi_monitor_encap
|
||||
*
|
||||
*/
|
||||
struct rfapi_it_extra
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
struct rfapi_monitor_vpn *v;
|
||||
struct skiplist *idx_rd; /* RD index */
|
||||
struct skiplist *mon_eth; /* ether queries */
|
||||
struct
|
||||
{
|
||||
/* routes with UN addrs, either cached encap or Encap TLV */
|
||||
int valid_interior_count;
|
||||
struct rfapi_it_extra {
|
||||
union {
|
||||
struct {
|
||||
struct rfapi_monitor_vpn *v;
|
||||
struct skiplist *idx_rd; /* RD index */
|
||||
struct skiplist *mon_eth; /* ether queries */
|
||||
struct {
|
||||
/* routes with UN addrs, either cached encap or
|
||||
* Encap TLV */
|
||||
int valid_interior_count;
|
||||
|
||||
/* unicast exterior routes, key=bi, val=allocated prefix */
|
||||
struct skiplist *source;
|
||||
} e;
|
||||
} vpn;
|
||||
struct
|
||||
{
|
||||
struct rfapi_monitor_encap *e;
|
||||
} encap;
|
||||
} u;
|
||||
/* unicast exterior routes, key=bi,
|
||||
* val=allocated prefix */
|
||||
struct skiplist *source;
|
||||
} e;
|
||||
} vpn;
|
||||
struct {
|
||||
struct rfapi_monitor_encap *e;
|
||||
} encap;
|
||||
} u;
|
||||
};
|
||||
|
||||
#define RFAPI_IT_EXTRA_GET(rn) ((struct rfapi_it_extra *)( \
|
||||
(rn)->aggregate? (rn)->aggregate: \
|
||||
(route_lock_node(rn), (rn)->aggregate = \
|
||||
XCALLOC(MTYPE_RFAPI_IT_EXTRA,sizeof(struct rfapi_it_extra)))))
|
||||
#define RFAPI_IT_EXTRA_GET(rn) \
|
||||
((struct rfapi_it_extra \
|
||||
*)((rn)->aggregate \
|
||||
? (rn)->aggregate \
|
||||
: (route_lock_node(rn), \
|
||||
(rn)->aggregate = XCALLOC( \
|
||||
MTYPE_RFAPI_IT_EXTRA, \
|
||||
sizeof(struct rfapi_it_extra)))))
|
||||
|
||||
#define RFAPI_RDINDEX(rn) \
|
||||
((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.vpn.idx_rd : NULL)
|
||||
#define RFAPI_RDINDEX(rn) \
|
||||
((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.vpn.idx_rd : NULL)
|
||||
|
||||
#define RFAPI_RDINDEX_W_ALLOC(rn) (RFAPI_IT_EXTRA_GET(rn)->u.vpn.idx_rd)
|
||||
|
||||
#define RFAPI_MONITOR_ETH(rn) \
|
||||
((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.vpn.mon_eth : NULL)
|
||||
#define RFAPI_MONITOR_ETH(rn) \
|
||||
((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.vpn.mon_eth : NULL)
|
||||
|
||||
#define RFAPI_MONITOR_ETH_W_ALLOC(rn) (RFAPI_IT_EXTRA_GET(rn)->u.vpn.mon_eth)
|
||||
|
||||
#define RFAPI_MONITOR_VPN(rn) \
|
||||
((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.vpn.v : NULL)
|
||||
#define RFAPI_MONITOR_VPN(rn) \
|
||||
((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.vpn.v : NULL)
|
||||
|
||||
#define RFAPI_MONITOR_VPN_W_ALLOC(rn) (RFAPI_IT_EXTRA_GET(rn)->u.vpn.v)
|
||||
|
||||
#define RFAPI_MONITOR_ENCAP(rn) \
|
||||
((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.encap.e : NULL)
|
||||
#define RFAPI_MONITOR_ENCAP(rn) \
|
||||
((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.encap.e : NULL)
|
||||
|
||||
#define RFAPI_MONITOR_ENCAP_W_ALLOC(rn) (RFAPI_IT_EXTRA_GET(rn)->u.encap.e)
|
||||
|
||||
#define RFAPI_MONITOR_EXTERIOR(rn) (&(RFAPI_IT_EXTRA_GET(rn)->u.vpn.e))
|
||||
|
||||
#define RFAPI_HAS_MONITOR_EXTERIOR(rn) (rn && rn->aggregate && \
|
||||
((struct rfapi_it_extra *)(rn->aggregate))->u.vpn.e.source && \
|
||||
!skiplist_first(((struct rfapi_it_extra *)(rn->aggregate))-> \
|
||||
u.vpn.e.source, NULL, NULL))
|
||||
#define RFAPI_HAS_MONITOR_EXTERIOR(rn) \
|
||||
(rn && rn->aggregate \
|
||||
&& ((struct rfapi_it_extra *)(rn->aggregate))->u.vpn.e.source \
|
||||
&& !skiplist_first(((struct rfapi_it_extra *)(rn->aggregate)) \
|
||||
->u.vpn.e.source, \
|
||||
NULL, NULL))
|
||||
|
||||
extern void
|
||||
rfapiMonitorLoopCheck (struct rfapi_monitor_vpn *mchain);
|
||||
extern void rfapiMonitorLoopCheck(struct rfapi_monitor_vpn *mchain);
|
||||
|
||||
extern void
|
||||
rfapiMonitorCleanCheck (struct bgp *bgp);
|
||||
extern void rfapiMonitorCleanCheck(struct bgp *bgp);
|
||||
|
||||
extern void
|
||||
rfapiMonitorCheckAttachAllowed (void);
|
||||
extern void rfapiMonitorCheckAttachAllowed(void);
|
||||
|
||||
extern void
|
||||
rfapiMonitorExtraFlush (safi_t safi, struct route_node *rn);
|
||||
extern void rfapiMonitorExtraFlush(safi_t safi, struct route_node *rn);
|
||||
|
||||
extern struct route_node *
|
||||
rfapiMonitorGetAttachNode (struct rfapi_descriptor *rfd, struct prefix *p);
|
||||
rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd, struct prefix *p);
|
||||
|
||||
extern void
|
||||
rfapiMonitorAttachImportHd (struct rfapi_descriptor *rfd);
|
||||
extern void rfapiMonitorAttachImportHd(struct rfapi_descriptor *rfd);
|
||||
|
||||
extern struct route_node *
|
||||
rfapiMonitorAdd (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct prefix *p);
|
||||
extern struct route_node *rfapiMonitorAdd(struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct prefix *p);
|
||||
|
||||
extern void
|
||||
rfapiMonitorDetachImportHd (struct rfapi_descriptor *rfd);
|
||||
extern void rfapiMonitorDetachImportHd(struct rfapi_descriptor *rfd);
|
||||
|
||||
extern void
|
||||
rfapiMonitorDel (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct prefix *p);
|
||||
extern void rfapiMonitorDel(struct bgp *bgp, struct rfapi_descriptor *rfd,
|
||||
struct prefix *p);
|
||||
|
||||
extern int
|
||||
rfapiMonitorDelHd (struct rfapi_descriptor *rfd);
|
||||
extern int rfapiMonitorDelHd(struct rfapi_descriptor *rfd);
|
||||
|
||||
extern void
|
||||
rfapiMonitorCallbacksOff (struct bgp *bgp);
|
||||
extern void rfapiMonitorCallbacksOff(struct bgp *bgp);
|
||||
|
||||
extern void
|
||||
rfapiMonitorCallbacksOn (struct bgp *bgp);
|
||||
extern void rfapiMonitorCallbacksOn(struct bgp *bgp);
|
||||
|
||||
extern void
|
||||
rfapiMonitorResponseRemovalOff (struct bgp *bgp);
|
||||
extern void rfapiMonitorResponseRemovalOff(struct bgp *bgp);
|
||||
|
||||
extern void
|
||||
rfapiMonitorResponseRemovalOn (struct bgp *bgp);
|
||||
extern void rfapiMonitorResponseRemovalOn(struct bgp *bgp);
|
||||
|
||||
extern void
|
||||
rfapiMonitorExtraPrune (safi_t safi, struct route_node *rn);
|
||||
extern void rfapiMonitorExtraPrune(safi_t safi, struct route_node *rn);
|
||||
|
||||
extern void
|
||||
rfapiMonitorTimersRestart (struct rfapi_descriptor *rfd, struct prefix *p);
|
||||
extern void rfapiMonitorTimersRestart(struct rfapi_descriptor *rfd,
|
||||
struct prefix *p);
|
||||
|
||||
extern void
|
||||
rfapiMonitorItNodeChanged (
|
||||
struct rfapi_import_table *import_table,
|
||||
struct route_node *it_node,
|
||||
struct rfapi_monitor_vpn *monitor_list);
|
||||
extern void rfapiMonitorItNodeChanged(struct rfapi_import_table *import_table,
|
||||
struct route_node *it_node,
|
||||
struct rfapi_monitor_vpn *monitor_list);
|
||||
|
||||
extern void
|
||||
rfapiMonitorMovedUp (
|
||||
struct rfapi_import_table *import_table,
|
||||
struct route_node *old_node,
|
||||
struct route_node *new_node,
|
||||
struct rfapi_monitor_vpn *monitor_list);
|
||||
extern void rfapiMonitorMovedUp(struct rfapi_import_table *import_table,
|
||||
struct route_node *old_node,
|
||||
struct route_node *new_node,
|
||||
struct rfapi_monitor_vpn *monitor_list);
|
||||
|
||||
extern struct route_node *
|
||||
rfapiMonitorEthAdd (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct ethaddr *macaddr,
|
||||
uint32_t logical_net_id);
|
||||
extern struct route_node *rfapiMonitorEthAdd(struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct ethaddr *macaddr,
|
||||
uint32_t logical_net_id);
|
||||
|
||||
extern void
|
||||
rfapiMonitorEthDel (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct ethaddr *macaddr,
|
||||
uint32_t logical_net_id);
|
||||
extern void rfapiMonitorEthDel(struct bgp *bgp, struct rfapi_descriptor *rfd,
|
||||
struct ethaddr *macaddr,
|
||||
uint32_t logical_net_id);
|
||||
|
||||
#endif /* QUAGGA_HGP_RFAPI_MONITOR_H */
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Copyright 2009-2016, LabN Consulting, L.L.C.
|
||||
*
|
||||
@ -41,135 +41,118 @@
|
||||
|
||||
#define DEBUG_NVE_ADDR 0
|
||||
|
||||
void rfapiNveAddr2Str (struct rfapi_nve_addr *, char *, int);
|
||||
void rfapiNveAddr2Str(struct rfapi_nve_addr *, char *, int);
|
||||
|
||||
|
||||
#if DEBUG_NVE_ADDR
|
||||
static void
|
||||
logdifferent (const char *tag,
|
||||
struct rfapi_nve_addr *a, struct rfapi_nve_addr *b)
|
||||
static void logdifferent(const char *tag, struct rfapi_nve_addr *a,
|
||||
struct rfapi_nve_addr *b)
|
||||
{
|
||||
char a_str[BUFSIZ];
|
||||
char b_str[BUFSIZ];
|
||||
char a_str[BUFSIZ];
|
||||
char b_str[BUFSIZ];
|
||||
|
||||
rfapiNveAddr2Str (a, a_str, BUFSIZ);
|
||||
rfapiNveAddr2Str (b, b_str, BUFSIZ);
|
||||
vnc_zlog_debug_verbose ("%s: [%s] [%s]", tag, a_str, b_str);
|
||||
rfapiNveAddr2Str(a, a_str, BUFSIZ);
|
||||
rfapiNveAddr2Str(b, b_str, BUFSIZ);
|
||||
vnc_zlog_debug_verbose("%s: [%s] [%s]", tag, a_str, b_str);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
rfapi_nve_addr_cmp (void *k1, void *k2)
|
||||
int rfapi_nve_addr_cmp(void *k1, void *k2)
|
||||
{
|
||||
struct rfapi_nve_addr *a = (struct rfapi_nve_addr *) k1;
|
||||
struct rfapi_nve_addr *b = (struct rfapi_nve_addr *) k2;
|
||||
int ret = 0;
|
||||
struct rfapi_nve_addr *a = (struct rfapi_nve_addr *)k1;
|
||||
struct rfapi_nve_addr *b = (struct rfapi_nve_addr *)k2;
|
||||
int ret = 0;
|
||||
|
||||
if (!a || !b)
|
||||
{
|
||||
if (!a || !b) {
|
||||
#if DEBUG_NVE_ADDR
|
||||
vnc_zlog_debug_verbose ("%s: missing address a=%p b=%p", __func__, a, b);
|
||||
vnc_zlog_debug_verbose("%s: missing address a=%p b=%p",
|
||||
__func__, a, b);
|
||||
#endif
|
||||
return (a - b);
|
||||
}
|
||||
if (a->un.addr_family != b->un.addr_family)
|
||||
{
|
||||
return (a - b);
|
||||
}
|
||||
if (a->un.addr_family != b->un.addr_family) {
|
||||
#if DEBUG_NVE_ADDR
|
||||
vnc_zlog_debug_verbose ("diff: UN addr fam a->un.af=%d, b->un.af=%d",
|
||||
a->un.addr_family, b->un.addr_family);
|
||||
vnc_zlog_debug_verbose(
|
||||
"diff: UN addr fam a->un.af=%d, b->un.af=%d",
|
||||
a->un.addr_family, b->un.addr_family);
|
||||
#endif
|
||||
return (a->un.addr_family - b->un.addr_family);
|
||||
}
|
||||
if (a->un.addr_family == AF_INET)
|
||||
{
|
||||
ret = IPV4_ADDR_CMP (&a->un.addr.v4, &b->un.addr.v4);
|
||||
if (ret != 0)
|
||||
{
|
||||
return (a->un.addr_family - b->un.addr_family);
|
||||
}
|
||||
if (a->un.addr_family == AF_INET) {
|
||||
ret = IPV4_ADDR_CMP(&a->un.addr.v4, &b->un.addr.v4);
|
||||
if (ret != 0) {
|
||||
#if DEBUG_NVE_ADDR
|
||||
logdifferent ("diff: UN addr", a, b);
|
||||
logdifferent("diff: UN addr", a, b);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else if (a->un.addr_family == AF_INET6)
|
||||
{
|
||||
ret = IPV6_ADDR_CMP (&a->un.addr.v6, &b->un.addr.v6);
|
||||
if (ret == 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
} else if (a->un.addr_family == AF_INET6) {
|
||||
ret = IPV6_ADDR_CMP(&a->un.addr.v6, &b->un.addr.v6);
|
||||
if (ret == 0) {
|
||||
#if DEBUG_NVE_ADDR
|
||||
logdifferent ("diff: UN addr", a, b);
|
||||
logdifferent("diff: UN addr", a, b);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (0);
|
||||
}
|
||||
if (a->vn.addr_family != b->vn.addr_family)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
if (a->vn.addr_family != b->vn.addr_family) {
|
||||
#if DEBUG_NVE_ADDR
|
||||
vnc_zlog_debug_verbose ("diff: pT addr fam a->vn.af=%d, b->vn.af=%d",
|
||||
a->vn.addr_family, b->vn.addr_family);
|
||||
vnc_zlog_debug_verbose(
|
||||
"diff: pT addr fam a->vn.af=%d, b->vn.af=%d",
|
||||
a->vn.addr_family, b->vn.addr_family);
|
||||
#endif
|
||||
return (a->vn.addr_family - b->vn.addr_family);
|
||||
}
|
||||
if (a->vn.addr_family == AF_INET)
|
||||
{
|
||||
ret = IPV4_ADDR_CMP (&a->vn.addr.v4, &b->vn.addr.v4);
|
||||
if (ret != 0)
|
||||
{
|
||||
return (a->vn.addr_family - b->vn.addr_family);
|
||||
}
|
||||
if (a->vn.addr_family == AF_INET) {
|
||||
ret = IPV4_ADDR_CMP(&a->vn.addr.v4, &b->vn.addr.v4);
|
||||
if (ret != 0) {
|
||||
#if DEBUG_NVE_ADDR
|
||||
logdifferent ("diff: VN addr", a, b);
|
||||
logdifferent("diff: VN addr", a, b);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else if (a->vn.addr_family == AF_INET6)
|
||||
{
|
||||
ret = IPV6_ADDR_CMP (&a->vn.addr.v6, &b->vn.addr.v6);
|
||||
if (ret == 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
} else if (a->vn.addr_family == AF_INET6) {
|
||||
ret = IPV6_ADDR_CMP(&a->vn.addr.v6, &b->vn.addr.v6);
|
||||
if (ret == 0) {
|
||||
#if DEBUG_NVE_ADDR
|
||||
logdifferent ("diff: VN addr", a, b);
|
||||
logdifferent("diff: VN addr", a, b);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (0);
|
||||
}
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rfapiNveAddr2Str (struct rfapi_nve_addr *na, char *buf, int bufsize)
|
||||
void rfapiNveAddr2Str(struct rfapi_nve_addr *na, char *buf, int bufsize)
|
||||
{
|
||||
char *p = buf;
|
||||
int r;
|
||||
char *p = buf;
|
||||
int r;
|
||||
|
||||
#define REMAIN (bufsize - (p-buf))
|
||||
#define INCP {p += (r > REMAIN)? REMAIN: r;}
|
||||
|
||||
if (bufsize < 1)
|
||||
return;
|
||||
if (bufsize < 1)
|
||||
return;
|
||||
|
||||
r = snprintf (p, REMAIN, "VN=");
|
||||
INCP;
|
||||
r = snprintf(p, REMAIN, "VN=");
|
||||
INCP;
|
||||
|
||||
if (!rfapiRfapiIpAddr2Str (&na->vn, p, REMAIN))
|
||||
goto done;
|
||||
if (!rfapiRfapiIpAddr2Str(&na->vn, p, REMAIN))
|
||||
goto done;
|
||||
|
||||
buf[bufsize - 1] = 0;
|
||||
p = buf + strlen (buf);
|
||||
buf[bufsize - 1] = 0;
|
||||
p = buf + strlen(buf);
|
||||
|
||||
r = snprintf (p, REMAIN, ", UN=");
|
||||
INCP;
|
||||
r = snprintf(p, REMAIN, ", UN=");
|
||||
INCP;
|
||||
|
||||
rfapiRfapiIpAddr2Str (&na->un, p, REMAIN);
|
||||
rfapiRfapiIpAddr2Str(&na->un, p, REMAIN);
|
||||
|
||||
done:
|
||||
buf[bufsize - 1] = 0;
|
||||
buf[bufsize - 1] = 0;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Copyright 2009-2016, LabN Consulting, L.L.C.
|
||||
*
|
||||
@ -23,20 +23,16 @@
|
||||
|
||||
#include "rfapi.h"
|
||||
|
||||
struct rfapi_nve_addr
|
||||
{
|
||||
struct rfapi_ip_addr vn;
|
||||
struct rfapi_ip_addr un;
|
||||
void *info;
|
||||
struct rfapi_nve_addr {
|
||||
struct rfapi_ip_addr vn;
|
||||
struct rfapi_ip_addr un;
|
||||
void *info;
|
||||
};
|
||||
|
||||
|
||||
extern int
|
||||
rfapi_nve_addr_cmp (void *k1, void *k2);
|
||||
|
||||
extern void
|
||||
rfapiNveAddr2Str (struct rfapi_nve_addr *na, char *buf, int bufsize);
|
||||
extern int rfapi_nve_addr_cmp(void *k1, void *k2);
|
||||
|
||||
extern void rfapiNveAddr2Str(struct rfapi_nve_addr *na, char *buf, int bufsize);
|
||||
|
||||
|
||||
#endif /* _QUAGGA_BGP_RFAPI_NVE_ADDR_H */
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Copyright 2009-2016, LabN Consulting, L.L.C.
|
||||
*
|
||||
@ -18,7 +18,7 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* Internal definitions for RFAPI. Not for use by other code
|
||||
*/
|
||||
|
||||
@ -40,96 +40,94 @@
|
||||
* 1. each is referenced in by_lifetime
|
||||
* 2. each is referenced by exactly one of: ipN_by_prefix, ip0_by_ether
|
||||
*/
|
||||
struct rfapi_advertised_prefixes
|
||||
{
|
||||
struct skiplist *ipN_by_prefix; /* all except 0/32, 0/128 */
|
||||
struct skiplist *ip0_by_ether; /* ip prefix 0/32, 0/128 */
|
||||
struct skiplist *by_lifetime; /* all */
|
||||
struct rfapi_advertised_prefixes {
|
||||
struct skiplist *ipN_by_prefix; /* all except 0/32, 0/128 */
|
||||
struct skiplist *ip0_by_ether; /* ip prefix 0/32, 0/128 */
|
||||
struct skiplist *by_lifetime; /* all */
|
||||
};
|
||||
|
||||
struct rfapi_descriptor
|
||||
{
|
||||
struct route_node *un_node; /* backref to un table */
|
||||
struct rfapi_descriptor {
|
||||
struct route_node *un_node; /* backref to un table */
|
||||
|
||||
struct rfapi_descriptor *next; /* next vn_addr */
|
||||
struct rfapi_descriptor *next; /* next vn_addr */
|
||||
|
||||
/* supplied by client */
|
||||
struct bgp *bgp; /* from rfp_start_val */
|
||||
struct rfapi_ip_addr vn_addr;
|
||||
struct rfapi_ip_addr un_addr;
|
||||
rfapi_response_cb_t *response_cb; /* override per-bgp response_cb */
|
||||
void *cookie; /* for callbacks */
|
||||
struct rfapi_tunneltype_option default_tunneltype_option;
|
||||
/* supplied by client */
|
||||
struct bgp *bgp; /* from rfp_start_val */
|
||||
struct rfapi_ip_addr vn_addr;
|
||||
struct rfapi_ip_addr un_addr;
|
||||
rfapi_response_cb_t *response_cb; /* override per-bgp response_cb */
|
||||
void *cookie; /* for callbacks */
|
||||
struct rfapi_tunneltype_option default_tunneltype_option;
|
||||
|
||||
/* supplied by matched configuration */
|
||||
struct prefix_rd rd;
|
||||
struct ecommunity *rt_export_list;
|
||||
uint32_t response_lifetime;
|
||||
/* supplied by matched configuration */
|
||||
struct prefix_rd rd;
|
||||
struct ecommunity *rt_export_list;
|
||||
uint32_t response_lifetime;
|
||||
|
||||
/* list of prefixes currently being advertised by this nve */
|
||||
struct rfapi_advertised_prefixes advertised;
|
||||
/* list of prefixes currently being advertised by this nve */
|
||||
struct rfapi_advertised_prefixes advertised;
|
||||
|
||||
time_t open_time;
|
||||
time_t open_time;
|
||||
|
||||
uint32_t max_prefix_lifetime;
|
||||
uint32_t min_prefix_lifetime;
|
||||
uint32_t max_prefix_lifetime;
|
||||
uint32_t min_prefix_lifetime;
|
||||
|
||||
/* reference to this nve's import table */
|
||||
struct rfapi_import_table *import_table;
|
||||
/* reference to this nve's import table */
|
||||
struct rfapi_import_table *import_table;
|
||||
|
||||
uint32_t monitor_count;
|
||||
struct route_table *mon; /* rfapi_monitors */
|
||||
struct skiplist *mon_eth; /* ethernet monitors */
|
||||
uint32_t monitor_count;
|
||||
struct route_table *mon; /* rfapi_monitors */
|
||||
struct skiplist *mon_eth; /* ethernet monitors */
|
||||
|
||||
/*
|
||||
* rib RIB as seen by NVE
|
||||
* rib_pending RIB containing nodes with updated info chains
|
||||
* rsp_times last time we sent response containing pfx
|
||||
*/
|
||||
uint32_t rib_prefix_count; /* pfxes with routes */
|
||||
struct route_table *rib[AFI_MAX];
|
||||
struct route_table *rib_pending[AFI_MAX];
|
||||
struct work_queue *updated_responses_queue;
|
||||
struct route_table *rsp_times[AFI_MAX];
|
||||
/*
|
||||
* rib RIB as seen by NVE
|
||||
* rib_pending RIB containing nodes with updated info chains
|
||||
* rsp_times last time we sent response containing pfx
|
||||
*/
|
||||
uint32_t rib_prefix_count; /* pfxes with routes */
|
||||
struct route_table *rib[AFI_MAX];
|
||||
struct route_table *rib_pending[AFI_MAX];
|
||||
struct work_queue *updated_responses_queue;
|
||||
struct route_table *rsp_times[AFI_MAX];
|
||||
|
||||
uint32_t rsp_counter; /* dedup initial rsp */
|
||||
time_t rsp_time; /* dedup initial rsp */
|
||||
time_t ftd_last_allowed_time; /* FTD filter */
|
||||
uint32_t rsp_counter; /* dedup initial rsp */
|
||||
time_t rsp_time; /* dedup initial rsp */
|
||||
time_t ftd_last_allowed_time; /* FTD filter */
|
||||
|
||||
unsigned int stat_count_nh_reachable;
|
||||
unsigned int stat_count_nh_removal;
|
||||
unsigned int stat_count_nh_reachable;
|
||||
unsigned int stat_count_nh_removal;
|
||||
|
||||
/*
|
||||
* points to the original nve group structure that matched
|
||||
* when this nve_descriptor was created. We use this pointer
|
||||
* in rfapi_close() to find the nve group structure and
|
||||
* delete its reference back to us.
|
||||
*
|
||||
* If the nve group structure is deleted (via configuration
|
||||
* change) while this nve_descriptor exists, this rfg pointer
|
||||
* will be set to NULL.
|
||||
*/
|
||||
struct rfapi_nve_group_cfg *rfg;
|
||||
/*
|
||||
* points to the original nve group structure that matched
|
||||
* when this nve_descriptor was created. We use this pointer
|
||||
* in rfapi_close() to find the nve group structure and
|
||||
* delete its reference back to us.
|
||||
*
|
||||
* If the nve group structure is deleted (via configuration
|
||||
* change) while this nve_descriptor exists, this rfg pointer
|
||||
* will be set to NULL.
|
||||
*/
|
||||
struct rfapi_nve_group_cfg *rfg;
|
||||
|
||||
/*
|
||||
* This ~7kB structure is here to permit multiple routes for
|
||||
* a prefix to be injected to BGP. There are at least two
|
||||
* situations where such conditions obtain:
|
||||
*
|
||||
* When an VNC route is exported to BGP on behalf of the set of
|
||||
* NVEs that belong to the export NVE group, it is replicated
|
||||
* so that there is one route per NVE (and the route's nexthop
|
||||
* is the NVE's VN address).
|
||||
*
|
||||
* Each of these routes being injected to BGP must have a distinct
|
||||
* peer pointer (otherwise, if they have the same peer pointer, each
|
||||
* route will be considered an implicit waithdraw of the previous
|
||||
* route injected from that peer, and the new route will replace
|
||||
* rather than augment the old one(s)).
|
||||
*/
|
||||
struct peer *peer;
|
||||
/*
|
||||
* This ~7kB structure is here to permit multiple routes for
|
||||
* a prefix to be injected to BGP. There are at least two
|
||||
* situations where such conditions obtain:
|
||||
*
|
||||
* When an VNC route is exported to BGP on behalf of the set of
|
||||
* NVEs that belong to the export NVE group, it is replicated
|
||||
* so that there is one route per NVE (and the route's nexthop
|
||||
* is the NVE's VN address).
|
||||
*
|
||||
* Each of these routes being injected to BGP must have a distinct
|
||||
* peer pointer (otherwise, if they have the same peer pointer, each
|
||||
* route will be considered an implicit waithdraw of the previous
|
||||
* route injected from that peer, and the new route will replace
|
||||
* rather than augment the old one(s)).
|
||||
*/
|
||||
struct peer *peer;
|
||||
|
||||
uint32_t flags;
|
||||
uint32_t flags;
|
||||
#define RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_IP 0x00000001
|
||||
#define RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_IP6 0x00000002
|
||||
#define RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_L2VPN 0x00000004
|
||||
@ -138,30 +136,32 @@ struct rfapi_descriptor
|
||||
#define RFAPI_HD_FLAG_IS_VRF 0x00000012
|
||||
};
|
||||
|
||||
#define RFAPI_QUEUED_FLAG(afi) ( \
|
||||
((afi) == AFI_IP)? RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_IP: \
|
||||
(((afi) == AFI_IP6)? RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_IP6: \
|
||||
(((afi) == AFI_L2VPN)? RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_L2VPN: \
|
||||
(assert(0), 0) )))
|
||||
#define RFAPI_QUEUED_FLAG(afi) \
|
||||
(((afi) == AFI_IP) \
|
||||
? RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_IP \
|
||||
: (((afi) == AFI_IP6) \
|
||||
? RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_IP6 \
|
||||
: (((afi) == AFI_L2VPN) \
|
||||
? RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_L2VPN \
|
||||
: (assert(0), 0))))
|
||||
|
||||
|
||||
struct rfapi_global_stats
|
||||
{
|
||||
time_t last_reset;
|
||||
unsigned int max_descriptors;
|
||||
struct rfapi_global_stats {
|
||||
time_t last_reset;
|
||||
unsigned int max_descriptors;
|
||||
|
||||
unsigned int count_unknown_nves;
|
||||
unsigned int count_unknown_nves;
|
||||
|
||||
unsigned int count_queries;
|
||||
unsigned int count_queries_failed;
|
||||
unsigned int count_queries;
|
||||
unsigned int count_queries_failed;
|
||||
|
||||
unsigned int max_responses; /* semantics? */
|
||||
unsigned int max_responses; /* semantics? */
|
||||
|
||||
unsigned int count_registrations;
|
||||
unsigned int count_registrations_failed;
|
||||
unsigned int count_registrations;
|
||||
unsigned int count_registrations_failed;
|
||||
|
||||
unsigned int count_updated_response_updates;
|
||||
unsigned int count_updated_response_deletes;
|
||||
unsigned int count_updated_response_updates;
|
||||
unsigned int count_updated_response_deletes;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -170,220 +170,187 @@ struct rfapi_global_stats
|
||||
* Radix tree is indexed by un address; follow chain and
|
||||
* check vn address to get exact match.
|
||||
*/
|
||||
struct rfapi
|
||||
{
|
||||
struct route_table un[AFI_MAX];
|
||||
struct rfapi_import_table *imports; /* IPv4, IPv6 */
|
||||
struct list descriptors;/* debug & resolve-nve imports */
|
||||
struct rfapi {
|
||||
struct route_table un[AFI_MAX];
|
||||
struct rfapi_import_table *imports; /* IPv4, IPv6 */
|
||||
struct list descriptors; /* debug & resolve-nve imports */
|
||||
|
||||
struct rfapi_global_stats stat;
|
||||
struct rfapi_global_stats stat;
|
||||
|
||||
/*
|
||||
* callbacks into RFP, set at startup time (bgp_rfapi_new() gets
|
||||
* values from rfp_start()) or via rfapi_rfp_set_cb_methods()
|
||||
* (otherwise NULL). Note that the response_cb method can also
|
||||
* be overridden per-rfd (currently used only for debug/test scenarios)
|
||||
*/
|
||||
struct rfapi_rfp_cb_methods rfp_methods;
|
||||
/*
|
||||
* callbacks into RFP, set at startup time (bgp_rfapi_new() gets
|
||||
* values from rfp_start()) or via rfapi_rfp_set_cb_methods()
|
||||
* (otherwise NULL). Note that the response_cb method can also
|
||||
* be overridden per-rfd (currently used only for debug/test scenarios)
|
||||
*/
|
||||
struct rfapi_rfp_cb_methods rfp_methods;
|
||||
|
||||
/*
|
||||
* Import tables for Ethernet over IPSEC
|
||||
*
|
||||
* The skiplist keys are LNIs. Values are pointers
|
||||
* to struct rfapi_import_table.
|
||||
*/
|
||||
struct skiplist *import_mac; /* L2 */
|
||||
/*
|
||||
* Import tables for Ethernet over IPSEC
|
||||
*
|
||||
* The skiplist keys are LNIs. Values are pointers
|
||||
* to struct rfapi_import_table.
|
||||
*/
|
||||
struct skiplist *import_mac; /* L2 */
|
||||
|
||||
/*
|
||||
* when exporting plain routes ("registered-nve" mode) to
|
||||
* bgp unicast or zebra, we need to keep track of information
|
||||
* related to expiring the routes according to the VNC lifetime
|
||||
*/
|
||||
struct route_table *rt_export_bgp[AFI_MAX];
|
||||
struct route_table *rt_export_zebra[AFI_MAX];
|
||||
/*
|
||||
* when exporting plain routes ("registered-nve" mode) to
|
||||
* bgp unicast or zebra, we need to keep track of information
|
||||
* related to expiring the routes according to the VNC lifetime
|
||||
*/
|
||||
struct route_table *rt_export_bgp[AFI_MAX];
|
||||
struct route_table *rt_export_zebra[AFI_MAX];
|
||||
|
||||
/*
|
||||
* For VNC->BGP unicast exports in CE mode, we need a
|
||||
* routing table that collects all of the VPN routes
|
||||
* in a single tree. The VPN rib is split up according
|
||||
* to RD first, so we can't use that. This is an import
|
||||
* table that matches all RTs.
|
||||
*/
|
||||
struct rfapi_import_table *it_ce;
|
||||
/*
|
||||
* For VNC->BGP unicast exports in CE mode, we need a
|
||||
* routing table that collects all of the VPN routes
|
||||
* in a single tree. The VPN rib is split up according
|
||||
* to RD first, so we can't use that. This is an import
|
||||
* table that matches all RTs.
|
||||
*/
|
||||
struct rfapi_import_table *it_ce;
|
||||
|
||||
/*
|
||||
* when importing bgp-direct routes in resolve-nve mode,
|
||||
* this list maps unicast route nexthops to their bgp_infos
|
||||
* in the unicast table
|
||||
*/
|
||||
struct skiplist *resolve_nve_nexthop;
|
||||
/*
|
||||
* when importing bgp-direct routes in resolve-nve mode,
|
||||
* this list maps unicast route nexthops to their bgp_infos
|
||||
* in the unicast table
|
||||
*/
|
||||
struct skiplist *resolve_nve_nexthop;
|
||||
|
||||
/*
|
||||
* Descriptors for which rfapi_close() was called during a callback.
|
||||
* They will be closed after the callback finishes.
|
||||
*/
|
||||
struct work_queue *deferred_close_q;
|
||||
/*
|
||||
* Descriptors for which rfapi_close() was called during a callback.
|
||||
* They will be closed after the callback finishes.
|
||||
*/
|
||||
struct work_queue *deferred_close_q;
|
||||
|
||||
/*
|
||||
* For "show vnc responses"
|
||||
*/
|
||||
uint32_t response_immediate_count;
|
||||
uint32_t response_updated_count;
|
||||
uint32_t monitor_count;
|
||||
/*
|
||||
* For "show vnc responses"
|
||||
*/
|
||||
uint32_t response_immediate_count;
|
||||
uint32_t response_updated_count;
|
||||
uint32_t monitor_count;
|
||||
|
||||
uint32_t rib_prefix_count_total;
|
||||
uint32_t rib_prefix_count_total_max;
|
||||
uint32_t rib_prefix_count_total;
|
||||
uint32_t rib_prefix_count_total_max;
|
||||
|
||||
uint32_t flags;
|
||||
uint32_t flags;
|
||||
#define RFAPI_INCALLBACK 0x00000001
|
||||
void *rfp; /* from rfp_start */
|
||||
void *rfp; /* from rfp_start */
|
||||
};
|
||||
|
||||
#define RFAPI_RIB_PREFIX_COUNT_INCR(rfd, rfapi) do { \
|
||||
++(rfd)->rib_prefix_count; \
|
||||
++(rfapi)->rib_prefix_count_total; \
|
||||
if ((rfapi)->rib_prefix_count_total > (rfapi)->rib_prefix_count_total_max) \
|
||||
++(rfapi)->rib_prefix_count_total_max; \
|
||||
} while (0)
|
||||
#define RFAPI_RIB_PREFIX_COUNT_INCR(rfd, rfapi) \
|
||||
do { \
|
||||
++(rfd)->rib_prefix_count; \
|
||||
++(rfapi)->rib_prefix_count_total; \
|
||||
if ((rfapi)->rib_prefix_count_total \
|
||||
> (rfapi)->rib_prefix_count_total_max) \
|
||||
++(rfapi)->rib_prefix_count_total_max; \
|
||||
} while (0)
|
||||
|
||||
#define RFAPI_RIB_PREFIX_COUNT_DECR(rfd, rfapi) do { \
|
||||
--(rfd)->rib_prefix_count; \
|
||||
--(rfapi)->rib_prefix_count_total; \
|
||||
} while (0)
|
||||
#define RFAPI_RIB_PREFIX_COUNT_DECR(rfd, rfapi) \
|
||||
do { \
|
||||
--(rfd)->rib_prefix_count; \
|
||||
--(rfapi)->rib_prefix_count_total; \
|
||||
} while (0)
|
||||
|
||||
#define RFAPI_0_PREFIX(prefix) ( \
|
||||
(((prefix)->family == AF_INET)? (prefix)->u.prefix4.s_addr == 0: \
|
||||
(((prefix)->family == AF_INET6)? \
|
||||
(IN6_IS_ADDR_UNSPECIFIED(&(prefix)->u.prefix6)) : 0)) \
|
||||
)
|
||||
#define RFAPI_0_PREFIX(prefix) \
|
||||
((((prefix)->family == AF_INET) \
|
||||
? (prefix)->u.prefix4.s_addr == 0 \
|
||||
: (((prefix)->family == AF_INET6) \
|
||||
? (IN6_IS_ADDR_UNSPECIFIED(&(prefix)->u.prefix6)) \
|
||||
: 0)))
|
||||
|
||||
#define RFAPI_0_ETHERADDR(ea) ( \
|
||||
((ea)->octet[0] | (ea)->octet[1] | (ea)->octet[2] | \
|
||||
(ea)->octet[3] | (ea)->octet[4] | (ea)->octet[5]) == 0)
|
||||
#define RFAPI_0_ETHERADDR(ea) \
|
||||
(((ea)->octet[0] | (ea)->octet[1] | (ea)->octet[2] | (ea)->octet[3] \
|
||||
| (ea)->octet[4] | (ea)->octet[5]) \
|
||||
== 0)
|
||||
|
||||
#define RFAPI_HOST_PREFIX(prefix) ( \
|
||||
((prefix)->family == AF_INET)? ((prefix)->prefixlen == 32): \
|
||||
(((prefix)->family == AF_INET6)? ((prefix)->prefixlen == 128): 0) )
|
||||
#define RFAPI_HOST_PREFIX(prefix) \
|
||||
(((prefix)->family == AF_INET) \
|
||||
? ((prefix)->prefixlen == 32) \
|
||||
: (((prefix)->family == AF_INET6) \
|
||||
? ((prefix)->prefixlen == 128) \
|
||||
: 0))
|
||||
|
||||
extern void rfapiQprefix2Rprefix(struct prefix *qprefix,
|
||||
struct rfapi_ip_prefix *rprefix);
|
||||
|
||||
extern int rfapi_find_rfd(struct bgp *bgp, struct rfapi_ip_addr *vn_addr,
|
||||
struct rfapi_ip_addr *un_addr,
|
||||
struct rfapi_descriptor **rfd);
|
||||
|
||||
extern void
|
||||
rfapiQprefix2Rprefix (
|
||||
struct prefix *qprefix,
|
||||
struct rfapi_ip_prefix *rprefix);
|
||||
|
||||
extern int
|
||||
rfapi_find_rfd (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_ip_addr *vn_addr,
|
||||
struct rfapi_ip_addr *un_addr,
|
||||
struct rfapi_descriptor **rfd);
|
||||
|
||||
extern void
|
||||
add_vnc_route (
|
||||
struct rfapi_descriptor *rfd, /* cookie + UN addr for VPN */
|
||||
struct bgp *bgp,
|
||||
int safi,
|
||||
struct prefix *p,
|
||||
struct prefix_rd *prd,
|
||||
struct rfapi_ip_addr *nexthop,
|
||||
uint32_t *local_pref, /* host byte order */
|
||||
uint32_t *lifetime, /* host byte order */
|
||||
struct bgp_tea_options *rfp_options,
|
||||
struct rfapi_un_option *options_un,
|
||||
struct rfapi_vn_option *options_vn,
|
||||
struct ecommunity *rt_export_list,
|
||||
uint32_t *med,
|
||||
uint32_t *label,
|
||||
uint8_t type,
|
||||
uint8_t sub_type,
|
||||
int flags);
|
||||
add_vnc_route(struct rfapi_descriptor *rfd, /* cookie + UN addr for VPN */
|
||||
struct bgp *bgp, int safi, struct prefix *p,
|
||||
struct prefix_rd *prd, struct rfapi_ip_addr *nexthop,
|
||||
uint32_t *local_pref, /* host byte order */
|
||||
uint32_t *lifetime, /* host byte order */
|
||||
struct bgp_tea_options *rfp_options,
|
||||
struct rfapi_un_option *options_un,
|
||||
struct rfapi_vn_option *options_vn,
|
||||
struct ecommunity *rt_export_list, uint32_t *med, uint32_t *label,
|
||||
uint8_t type, uint8_t sub_type, int flags);
|
||||
#define RFAPI_AHR_NO_TUNNEL_SUBTLV 0x00000001
|
||||
#define RFAPI_AHR_RFPOPT_IS_VNCTLV 0x00000002 /* hack! */
|
||||
#if 0 /* unused? */
|
||||
#if 0 /* unused? */
|
||||
# define RFAPI_AHR_SET_PFX_TO_NEXTHOP 0x00000004
|
||||
#endif
|
||||
|
||||
extern void
|
||||
del_vnc_route (
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct peer *peer,
|
||||
struct bgp *bgp,
|
||||
safi_t safi,
|
||||
struct prefix *p,
|
||||
struct prefix_rd *prd,
|
||||
uint8_t type,
|
||||
uint8_t sub_type,
|
||||
struct rfapi_nexthop *lnh,
|
||||
int kill);
|
||||
extern void del_vnc_route(struct rfapi_descriptor *rfd, struct peer *peer,
|
||||
struct bgp *bgp, safi_t safi, struct prefix *p,
|
||||
struct prefix_rd *prd, uint8_t type, uint8_t sub_type,
|
||||
struct rfapi_nexthop *lnh, int kill);
|
||||
|
||||
extern int
|
||||
rfapiCliGetPrefixAddr (struct vty *vty, const char *str, struct prefix *p);
|
||||
extern int rfapiCliGetPrefixAddr(struct vty *vty, const char *str,
|
||||
struct prefix *p);
|
||||
|
||||
extern int
|
||||
rfapiGetVncLifetime (struct attr *attr, uint32_t * lifetime);
|
||||
extern int rfapiGetVncLifetime(struct attr *attr, uint32_t *lifetime);
|
||||
|
||||
extern int
|
||||
rfapiGetTunnelType (struct attr *attr, bgp_encap_types *type);
|
||||
extern int rfapiGetTunnelType(struct attr *attr, bgp_encap_types *type);
|
||||
|
||||
extern int
|
||||
rfapiGetVncTunnelUnAddr (struct attr *attr, struct prefix *p);
|
||||
extern int rfapiGetVncTunnelUnAddr(struct attr *attr, struct prefix *p);
|
||||
|
||||
extern int
|
||||
rfapi_reopen (struct rfapi_descriptor *rfd, struct bgp *bgp);
|
||||
extern int rfapi_reopen(struct rfapi_descriptor *rfd, struct bgp *bgp);
|
||||
|
||||
extern void
|
||||
vnc_import_bgp_add_rfp_host_route_mode_resolve_nve (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct prefix *prefix);
|
||||
extern void vnc_import_bgp_add_rfp_host_route_mode_resolve_nve(
|
||||
struct bgp *bgp, struct rfapi_descriptor *rfd, struct prefix *prefix);
|
||||
|
||||
extern void
|
||||
vnc_import_bgp_del_rfp_host_route_mode_resolve_nve (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct prefix *prefix);
|
||||
extern void vnc_import_bgp_del_rfp_host_route_mode_resolve_nve(
|
||||
struct bgp *bgp, struct rfapi_descriptor *rfd, struct prefix *prefix);
|
||||
|
||||
extern void
|
||||
rfapiFreeBgpTeaOptionChain (struct bgp_tea_options *p);
|
||||
extern void rfapiFreeBgpTeaOptionChain(struct bgp_tea_options *p);
|
||||
|
||||
extern struct rfapi_vn_option *rfapiVnOptionsDup(struct rfapi_vn_option *orig);
|
||||
|
||||
extern struct rfapi_un_option *rfapiUnOptionsDup(struct rfapi_un_option *orig);
|
||||
|
||||
extern struct bgp_tea_options *rfapiOptionsDup(struct bgp_tea_options *orig);
|
||||
|
||||
extern int rfapi_ip_addr_cmp(struct rfapi_ip_addr *a1,
|
||||
struct rfapi_ip_addr *a2);
|
||||
|
||||
extern uint32_t rfp_cost_to_localpref(uint8_t cost);
|
||||
|
||||
extern int rfapi_set_autord_from_vn(struct prefix_rd *rd,
|
||||
struct rfapi_ip_addr *vn);
|
||||
|
||||
extern struct rfapi_nexthop *rfapi_nexthop_new(struct rfapi_nexthop *copyme);
|
||||
|
||||
extern void rfapi_nexthop_free(void *goner);
|
||||
|
||||
extern struct rfapi_vn_option *
|
||||
rfapiVnOptionsDup (struct rfapi_vn_option *orig);
|
||||
rfapi_vn_options_dup(struct rfapi_vn_option *existing);
|
||||
|
||||
extern struct rfapi_un_option *
|
||||
rfapiUnOptionsDup (struct rfapi_un_option *orig);
|
||||
extern void rfapi_un_options_free(struct rfapi_un_option *goner);
|
||||
|
||||
extern struct bgp_tea_options *
|
||||
rfapiOptionsDup (struct bgp_tea_options *orig);
|
||||
|
||||
extern int
|
||||
rfapi_ip_addr_cmp (struct rfapi_ip_addr *a1, struct rfapi_ip_addr *a2);
|
||||
|
||||
extern uint32_t
|
||||
rfp_cost_to_localpref (uint8_t cost);
|
||||
|
||||
extern int
|
||||
rfapi_set_autord_from_vn (struct prefix_rd *rd, struct rfapi_ip_addr *vn);
|
||||
|
||||
extern struct rfapi_nexthop *
|
||||
rfapi_nexthop_new (struct rfapi_nexthop *copyme);
|
||||
|
||||
extern void
|
||||
rfapi_nexthop_free (void *goner);
|
||||
|
||||
extern struct rfapi_vn_option *
|
||||
rfapi_vn_options_dup (struct rfapi_vn_option *existing);
|
||||
|
||||
extern void
|
||||
rfapi_un_options_free (struct rfapi_un_option *goner);
|
||||
|
||||
extern void
|
||||
rfapi_vn_options_free (struct rfapi_vn_option *goner);
|
||||
extern void rfapi_vn_options_free(struct rfapi_vn_option *goner);
|
||||
|
||||
/*------------------------------------------
|
||||
* rfapi_extract_l2o
|
||||
*
|
||||
* Find Layer 2 options in an option chain
|
||||
* Find Layer 2 options in an option chain
|
||||
*
|
||||
* input:
|
||||
* input:
|
||||
* pHop option chain
|
||||
*
|
||||
* output:
|
||||
@ -394,17 +361,16 @@ rfapi_vn_options_free (struct rfapi_vn_option *goner);
|
||||
* 1 no options found
|
||||
*
|
||||
--------------------------------------------*/
|
||||
extern int
|
||||
rfapi_extract_l2o (
|
||||
struct bgp_tea_options *pHop, /* chain of options */
|
||||
struct rfapi_l2address_option *l2o); /* return extracted value */
|
||||
extern int rfapi_extract_l2o(
|
||||
struct bgp_tea_options *pHop, /* chain of options */
|
||||
struct rfapi_l2address_option *l2o); /* return extracted value */
|
||||
|
||||
/*
|
||||
/*
|
||||
* compaitibility to old quagga_time call
|
||||
* time_t value in terms of stabilised absolute time.
|
||||
* time_t value in terms of stabilised absolute time.
|
||||
* replacement for POSIX time()
|
||||
*/
|
||||
extern time_t rfapi_time (time_t *t);
|
||||
extern time_t rfapi_time(time_t *t);
|
||||
|
||||
DECLARE_MGROUP(RFAPI)
|
||||
DECLARE_MTYPE(RFAPI_CFG)
|
||||
@ -441,10 +407,7 @@ DECLARE_MTYPE(RFAPI_MONITOR_ETH)
|
||||
* The advertised_prefixes[] array elements should be NULL to
|
||||
* have this function set them to newly-allocated radix trees.
|
||||
*/
|
||||
extern int
|
||||
rfapi_init_and_open(
|
||||
struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct rfapi_nve_group_cfg *rfg);
|
||||
extern int rfapi_init_and_open(struct bgp *bgp, struct rfapi_descriptor *rfd,
|
||||
struct rfapi_nve_group_cfg *rfg);
|
||||
|
||||
#endif /* _QUAGGA_BGP_RFAPI_PRIVATE_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Copyright 2009-2016, LabN Consulting, L.L.C.
|
||||
*
|
||||
@ -33,16 +33,15 @@
|
||||
* For L2 RIBs, it is possible to have multiple routes to a given L2
|
||||
* prefix via a given VN address, but each route having a unique aux_prefix.
|
||||
*/
|
||||
struct rfapi_rib_key
|
||||
{
|
||||
struct prefix vn;
|
||||
struct prefix_rd rd;
|
||||
struct rfapi_rib_key {
|
||||
struct prefix vn;
|
||||
struct prefix_rd rd;
|
||||
|
||||
/*
|
||||
* for L2 routes: optional IP addr
|
||||
* .family == 0 means "none"
|
||||
*/
|
||||
struct prefix aux_prefix;
|
||||
/*
|
||||
* for L2 routes: optional IP addr
|
||||
* .family == 0 means "none"
|
||||
*/
|
||||
struct prefix aux_prefix;
|
||||
};
|
||||
#include "rfapi.h"
|
||||
|
||||
@ -51,118 +50,90 @@ struct rfapi_rib_key
|
||||
*
|
||||
* Holds NVE prefix advertisement information
|
||||
*/
|
||||
struct rfapi_adb
|
||||
{
|
||||
union {
|
||||
struct {
|
||||
struct prefix prefix_ip;
|
||||
struct prefix_rd prd;
|
||||
struct prefix prefix_eth;
|
||||
} s; /* mainly for legacy use */
|
||||
struct rfapi_rib_key key;
|
||||
} u;
|
||||
uint32_t lifetime;
|
||||
uint8_t cost;
|
||||
struct rfapi_l2address_option l2o;
|
||||
struct rfapi_adb {
|
||||
union {
|
||||
struct {
|
||||
struct prefix prefix_ip;
|
||||
struct prefix_rd prd;
|
||||
struct prefix prefix_eth;
|
||||
} s; /* mainly for legacy use */
|
||||
struct rfapi_rib_key key;
|
||||
} u;
|
||||
uint32_t lifetime;
|
||||
uint8_t cost;
|
||||
struct rfapi_l2address_option l2o;
|
||||
};
|
||||
|
||||
struct rfapi_info
|
||||
{
|
||||
struct rfapi_rib_key rk; /* NVE VN addr + aux addr */
|
||||
struct prefix un;
|
||||
uint8_t cost;
|
||||
uint32_t lifetime;
|
||||
time_t last_sent_time;
|
||||
uint32_t rsp_counter; /* dedup initial responses */
|
||||
struct bgp_tea_options *tea_options;
|
||||
struct rfapi_un_option *un_options;
|
||||
struct rfapi_vn_option *vn_options;
|
||||
struct thread *timer;
|
||||
struct rfapi_info {
|
||||
struct rfapi_rib_key rk; /* NVE VN addr + aux addr */
|
||||
struct prefix un;
|
||||
uint8_t cost;
|
||||
uint32_t lifetime;
|
||||
time_t last_sent_time;
|
||||
uint32_t rsp_counter; /* dedup initial responses */
|
||||
struct bgp_tea_options *tea_options;
|
||||
struct rfapi_un_option *un_options;
|
||||
struct rfapi_vn_option *vn_options;
|
||||
struct thread *timer;
|
||||
};
|
||||
|
||||
/*
|
||||
* Work item for updated responses queue
|
||||
*/
|
||||
struct rfapi_updated_responses_queue
|
||||
{
|
||||
struct rfapi_descriptor *rfd;
|
||||
afi_t afi;
|
||||
struct rfapi_updated_responses_queue {
|
||||
struct rfapi_descriptor *rfd;
|
||||
afi_t afi;
|
||||
};
|
||||
|
||||
|
||||
extern void
|
||||
rfapiRibClear (struct rfapi_descriptor *rfd);
|
||||
extern void rfapiRibClear(struct rfapi_descriptor *rfd);
|
||||
|
||||
extern void
|
||||
rfapiRibFree (struct rfapi_descriptor *rfd);
|
||||
extern void rfapiRibFree(struct rfapi_descriptor *rfd);
|
||||
|
||||
extern void
|
||||
rfapiRibUpdatePendingNode (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct rfapi_import_table *it,
|
||||
struct route_node *it_node,
|
||||
uint32_t lifetime);
|
||||
extern void rfapiRibUpdatePendingNode(struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct rfapi_import_table *it,
|
||||
struct route_node *it_node,
|
||||
uint32_t lifetime);
|
||||
|
||||
extern void
|
||||
rfapiRibUpdatePendingNodeSubtree (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct rfapi_import_table *it,
|
||||
struct route_node *it_node,
|
||||
struct route_node *omit_subtree,
|
||||
uint32_t lifetime);
|
||||
extern void rfapiRibUpdatePendingNodeSubtree(struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct rfapi_import_table *it,
|
||||
struct route_node *it_node,
|
||||
struct route_node *omit_subtree,
|
||||
uint32_t lifetime);
|
||||
|
||||
extern int
|
||||
rfapiRibPreloadBi(
|
||||
struct route_node *rfd_rib_node,
|
||||
struct prefix *pfx_vn,
|
||||
struct prefix *pfx_un,
|
||||
uint32_t lifetime,
|
||||
struct bgp_info *bi);
|
||||
extern int rfapiRibPreloadBi(struct route_node *rfd_rib_node,
|
||||
struct prefix *pfx_vn, struct prefix *pfx_un,
|
||||
uint32_t lifetime, struct bgp_info *bi);
|
||||
|
||||
extern struct rfapi_next_hop_entry *
|
||||
rfapiRibPreload (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct rfapi_next_hop_entry *response,
|
||||
int use_eth_resolution);
|
||||
rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd,
|
||||
struct rfapi_next_hop_entry *response, int use_eth_resolution);
|
||||
|
||||
extern void rfapiRibPendingDeleteRoute(struct bgp *bgp,
|
||||
struct rfapi_import_table *it, afi_t afi,
|
||||
struct route_node *it_node);
|
||||
|
||||
extern void rfapiRibShowResponsesSummary(void *stream);
|
||||
|
||||
extern void rfapiRibShowResponsesSummaryClear(void);
|
||||
|
||||
extern void rfapiRibShowResponses(void *stream, struct prefix *pfx_match,
|
||||
int show_removed);
|
||||
|
||||
extern int rfapiRibFTDFilterRecentPrefix(
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct route_node *it_rn, /* import table node */
|
||||
struct prefix *pfx_target_original); /* query target */
|
||||
|
||||
extern void rfapiFreeRfapiUnOptionChain(struct rfapi_un_option *p);
|
||||
|
||||
extern void rfapiFreeRfapiVnOptionChain(struct rfapi_vn_option *p);
|
||||
|
||||
extern void
|
||||
rfapiRibPendingDeleteRoute (
|
||||
struct bgp *bgp,
|
||||
struct rfapi_import_table *it,
|
||||
afi_t afi,
|
||||
struct route_node *it_node);
|
||||
|
||||
extern void
|
||||
rfapiRibShowResponsesSummary (void *stream);
|
||||
|
||||
extern void
|
||||
rfapiRibShowResponsesSummaryClear (void);
|
||||
|
||||
extern void
|
||||
rfapiRibShowResponses (
|
||||
void *stream,
|
||||
struct prefix *pfx_match,
|
||||
int show_removed);
|
||||
|
||||
extern int
|
||||
rfapiRibFTDFilterRecentPrefix(
|
||||
struct rfapi_descriptor *rfd,
|
||||
struct route_node *it_rn, /* import table node */
|
||||
struct prefix *pfx_target_original); /* query target */
|
||||
|
||||
extern void
|
||||
rfapiFreeRfapiUnOptionChain (struct rfapi_un_option *p);
|
||||
|
||||
extern void
|
||||
rfapiFreeRfapiVnOptionChain (struct rfapi_vn_option *p);
|
||||
|
||||
extern void
|
||||
rfapiRibCheckCounts (
|
||||
int checkstats, /* validate rfd & global counts */
|
||||
unsigned int offset); /* number of ri's held separately */
|
||||
rfapiRibCheckCounts(int checkstats, /* validate rfd & global counts */
|
||||
unsigned int offset); /* number of ri's held separately */
|
||||
|
||||
/* enable for debugging; disable for performance */
|
||||
#if 0
|
||||
@ -171,16 +142,13 @@ rfapiRibCheckCounts (
|
||||
#define RFAPI_RIB_CHECK_COUNTS(checkstats, offset)
|
||||
#endif
|
||||
|
||||
extern void
|
||||
rfapi_rib_key_init (struct prefix *prefix, /* may be NULL */
|
||||
struct prefix_rd *rd, /* may be NULL */
|
||||
struct prefix *aux, /* may be NULL */
|
||||
struct rfapi_rib_key *rk);
|
||||
extern void rfapi_rib_key_init(struct prefix *prefix, /* may be NULL */
|
||||
struct prefix_rd *rd, /* may be NULL */
|
||||
struct prefix *aux, /* may be NULL */
|
||||
struct rfapi_rib_key *rk);
|
||||
|
||||
extern int
|
||||
rfapi_rib_key_cmp (void *k1, void *k2);
|
||||
extern int rfapi_rib_key_cmp(void *k1, void *k2);
|
||||
|
||||
extern void
|
||||
rfapiAdbFree (struct rfapi_adb *adb);
|
||||
extern void rfapiAdbFree(struct rfapi_adb *adb);
|
||||
|
||||
#endif /* QUAGGA_HGP_RFAPI_RIB_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Copyright 2009-2016, LabN Consulting, L.L.C.
|
||||
*
|
||||
@ -23,74 +23,59 @@
|
||||
|
||||
#include "lib/vty.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SHOW_NVE_SUMMARY_ACTIVE_NVES,
|
||||
SHOW_NVE_SUMMARY_UNKNOWN_NVES, /* legacy */
|
||||
SHOW_NVE_SUMMARY_REGISTERED,
|
||||
SHOW_NVE_SUMMARY_QUERIES,
|
||||
SHOW_NVE_SUMMARY_RESPONSES,
|
||||
SHOW_NVE_SUMMARY_MAX
|
||||
typedef enum {
|
||||
SHOW_NVE_SUMMARY_ACTIVE_NVES,
|
||||
SHOW_NVE_SUMMARY_UNKNOWN_NVES, /* legacy */
|
||||
SHOW_NVE_SUMMARY_REGISTERED,
|
||||
SHOW_NVE_SUMMARY_QUERIES,
|
||||
SHOW_NVE_SUMMARY_RESPONSES,
|
||||
SHOW_NVE_SUMMARY_MAX
|
||||
} show_nve_summary_t;
|
||||
|
||||
#define VNC_SHOW_STR "VNC information\n"
|
||||
|
||||
extern char *
|
||||
rfapiFormatSeconds (uint32_t seconds, char *buf, size_t len);
|
||||
extern char *rfapiFormatSeconds(uint32_t seconds, char *buf, size_t len);
|
||||
|
||||
extern char *
|
||||
rfapiFormatAge (time_t age, char *buf, size_t len);
|
||||
extern char *rfapiFormatAge(time_t age, char *buf, size_t len);
|
||||
|
||||
extern void
|
||||
rfapiRprefixApplyMask (struct rfapi_ip_prefix *rprefix);
|
||||
extern void rfapiRprefixApplyMask(struct rfapi_ip_prefix *rprefix);
|
||||
|
||||
extern int
|
||||
rfapiQprefix2Raddr (struct prefix *qprefix, struct rfapi_ip_addr *raddr);
|
||||
extern int rfapiQprefix2Raddr(struct prefix *qprefix,
|
||||
struct rfapi_ip_addr *raddr);
|
||||
|
||||
extern void
|
||||
rfapiQprefix2Rprefix (struct prefix *qprefix,
|
||||
struct rfapi_ip_prefix *rprefix);
|
||||
extern void rfapiQprefix2Rprefix(struct prefix *qprefix,
|
||||
struct rfapi_ip_prefix *rprefix);
|
||||
|
||||
extern int
|
||||
rfapiRprefix2Qprefix (struct rfapi_ip_prefix *rprefix,
|
||||
struct prefix *qprefix);
|
||||
extern int rfapiRprefix2Qprefix(struct rfapi_ip_prefix *rprefix,
|
||||
struct prefix *qprefix);
|
||||
|
||||
extern int
|
||||
rfapiRaddr2Qprefix (struct rfapi_ip_addr *hia, struct prefix *pfx);
|
||||
extern int rfapiRaddr2Qprefix(struct rfapi_ip_addr *hia, struct prefix *pfx);
|
||||
|
||||
extern int
|
||||
rfapiRprefixSame (struct rfapi_ip_prefix *hp1, struct rfapi_ip_prefix *hp2);
|
||||
extern int rfapiRprefixSame(struct rfapi_ip_prefix *hp1,
|
||||
struct rfapi_ip_prefix *hp2);
|
||||
|
||||
extern void
|
||||
rfapiL2o2Qprefix (struct rfapi_l2address_option *l2o, struct prefix *pfx);
|
||||
extern void rfapiL2o2Qprefix(struct rfapi_l2address_option *l2o,
|
||||
struct prefix *pfx);
|
||||
|
||||
extern int
|
||||
rfapiStr2EthAddr (const char *str, struct ethaddr *ea);
|
||||
extern int rfapiStr2EthAddr(const char *str, struct ethaddr *ea);
|
||||
|
||||
extern const char *
|
||||
rfapi_ntop (
|
||||
int af,
|
||||
const void *src,
|
||||
char *buf,
|
||||
socklen_t size);
|
||||
extern const char *rfapi_ntop(int af, const void *src, char *buf,
|
||||
socklen_t size);
|
||||
|
||||
extern int
|
||||
rfapiDebugPrintf (void *dummy, const char *format, ...);
|
||||
extern int rfapiDebugPrintf(void *dummy, const char *format, ...);
|
||||
|
||||
extern int
|
||||
rfapiStream2Vty (
|
||||
void *stream, /* input */
|
||||
int (**fp) (void *, const char *, ...), /* output */
|
||||
struct vty **vty, /* output */
|
||||
void **outstream, /* output */
|
||||
const char **vty_newline); /* output */
|
||||
extern int rfapiStream2Vty(void *stream, /* input */
|
||||
int (**fp)(void *, const char *, ...), /* output */
|
||||
struct vty **vty, /* output */
|
||||
void **outstream, /* output */
|
||||
const char **vty_newline); /* output */
|
||||
|
||||
/*------------------------------------------
|
||||
* rfapiRfapiIpAddr2Str
|
||||
*
|
||||
* UI helper: generate string from rfapi_ip_addr
|
||||
*
|
||||
* input:
|
||||
* input:
|
||||
* a IP v4/v6 address
|
||||
*
|
||||
* output
|
||||
@ -101,75 +86,50 @@ rfapiStream2Vty (
|
||||
* NULL conversion failed
|
||||
* non-NULL pointer to buf
|
||||
--------------------------------------------*/
|
||||
extern const char *
|
||||
rfapiRfapiIpAddr2Str (struct rfapi_ip_addr *a, char *buf, int bufsize);
|
||||
extern const char *rfapiRfapiIpAddr2Str(struct rfapi_ip_addr *a, char *buf,
|
||||
int bufsize);
|
||||
|
||||
extern void
|
||||
rfapiPrintRfapiIpAddr (void *stream, struct rfapi_ip_addr *a);
|
||||
extern void rfapiPrintRfapiIpAddr(void *stream, struct rfapi_ip_addr *a);
|
||||
|
||||
extern void
|
||||
rfapiPrintRfapiIpPrefix (void *stream, struct rfapi_ip_prefix *p);
|
||||
extern void rfapiPrintRfapiIpPrefix(void *stream, struct rfapi_ip_prefix *p);
|
||||
|
||||
void
|
||||
rfapiPrintRd (struct vty *vty, struct prefix_rd *prd);
|
||||
void rfapiPrintRd(struct vty *vty, struct prefix_rd *prd);
|
||||
|
||||
extern void
|
||||
rfapiPrintAdvertisedInfo (
|
||||
struct vty *vty,
|
||||
struct rfapi_descriptor *rfd,
|
||||
safi_t safi,
|
||||
struct prefix *p);
|
||||
extern void rfapiPrintAdvertisedInfo(struct vty *vty,
|
||||
struct rfapi_descriptor *rfd, safi_t safi,
|
||||
struct prefix *p);
|
||||
|
||||
extern void
|
||||
rfapiPrintDescriptor (struct vty *vty, struct rfapi_descriptor *rfd);
|
||||
extern void rfapiPrintDescriptor(struct vty *vty, struct rfapi_descriptor *rfd);
|
||||
|
||||
extern void
|
||||
rfapiPrintMatchingDescriptors (struct vty *vty,
|
||||
struct prefix *vn_prefix,
|
||||
struct prefix *un_prefix);
|
||||
extern void rfapiPrintMatchingDescriptors(struct vty *vty,
|
||||
struct prefix *vn_prefix,
|
||||
struct prefix *un_prefix);
|
||||
|
||||
extern void
|
||||
rfapiPrintAttrPtrs (void *stream, struct attr *attr);
|
||||
extern void rfapiPrintAttrPtrs(void *stream, struct attr *attr);
|
||||
|
||||
/*
|
||||
* Parse an address and put into a struct prefix
|
||||
*/
|
||||
extern int
|
||||
rfapiCliGetPrefixAddr (struct vty *vty, const char *str, struct prefix *p);
|
||||
extern int rfapiCliGetPrefixAddr(struct vty *vty, const char *str,
|
||||
struct prefix *p);
|
||||
|
||||
extern int
|
||||
rfapiCliGetRfapiIpAddr (
|
||||
struct vty *vty,
|
||||
const char *str,
|
||||
struct rfapi_ip_addr *hai);
|
||||
extern int rfapiCliGetRfapiIpAddr(struct vty *vty, const char *str,
|
||||
struct rfapi_ip_addr *hai);
|
||||
|
||||
extern void
|
||||
rfapiPrintNhl (void *stream, struct rfapi_next_hop_entry *next_hops);
|
||||
extern void rfapiPrintNhl(void *stream, struct rfapi_next_hop_entry *next_hops);
|
||||
|
||||
extern char *
|
||||
rfapiMonitorVpn2Str (
|
||||
struct rfapi_monitor_vpn *m,
|
||||
char *buf,
|
||||
int size);
|
||||
extern char *rfapiMonitorVpn2Str(struct rfapi_monitor_vpn *m, char *buf,
|
||||
int size);
|
||||
|
||||
extern const char *
|
||||
rfapiRfapiIpPrefix2Str (
|
||||
struct rfapi_ip_prefix *p,
|
||||
char *buf,
|
||||
int bufsize);
|
||||
extern const char *rfapiRfapiIpPrefix2Str(struct rfapi_ip_prefix *p, char *buf,
|
||||
int bufsize);
|
||||
|
||||
extern void
|
||||
rfapiShowItNode (void *stream, struct route_node *rn);
|
||||
extern void rfapiShowItNode(void *stream, struct route_node *rn);
|
||||
|
||||
extern char *
|
||||
rfapiEthAddr2Str (
|
||||
const struct ethaddr *ea,
|
||||
char *buf,
|
||||
int bufsize);
|
||||
extern char *rfapiEthAddr2Str(const struct ethaddr *ea, char *buf, int bufsize);
|
||||
|
||||
/* install vty commands */
|
||||
extern void
|
||||
rfapi_vty_init (void);
|
||||
extern void rfapi_vty_init(void);
|
||||
|
||||
/*------------------------------------------
|
||||
* rfapiShowRemoteRegistrations
|
||||
@ -177,7 +137,7 @@ rfapi_vty_init (void);
|
||||
* UI helper: produces the "remote" portion of the output
|
||||
* of "show vnc registrations".
|
||||
*
|
||||
* input:
|
||||
* input:
|
||||
* stream pointer to output stream
|
||||
* prefix_only pointer to prefix. If non-NULL, print only registrations
|
||||
* matching the specified prefix
|
||||
@ -189,21 +149,17 @@ rfapi_vty_init (void);
|
||||
* 0 nothing printed
|
||||
* >0 something printed
|
||||
--------------------------------------------*/
|
||||
extern int
|
||||
rfapiShowRemoteRegistrations (
|
||||
void *stream,
|
||||
struct prefix *prefix_only,
|
||||
int show_expiring,
|
||||
int show_local,
|
||||
int show_remote,
|
||||
int show_imported);
|
||||
extern int rfapiShowRemoteRegistrations(void *stream,
|
||||
struct prefix *prefix_only,
|
||||
int show_expiring, int show_local,
|
||||
int show_remote, int show_imported);
|
||||
|
||||
/*------------------------------------------
|
||||
* rfapi_monitor_count
|
||||
*
|
||||
* UI helper: count number of active monitors
|
||||
*
|
||||
* input:
|
||||
* input:
|
||||
* handle rfapi handle (NULL to count across
|
||||
* all open handles)
|
||||
*
|
||||
@ -212,11 +168,9 @@ rfapiShowRemoteRegistrations (
|
||||
* return value:
|
||||
* count of monitors
|
||||
--------------------------------------------*/
|
||||
extern uint32_t
|
||||
rfapi_monitor_count (rfapi_handle);
|
||||
extern uint32_t rfapi_monitor_count(rfapi_handle);
|
||||
|
||||
extern int
|
||||
rfapiShowVncQueries (void *stream, struct prefix *pfx_match);
|
||||
extern int rfapiShowVncQueries(void *stream, struct prefix *pfx_match);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user