summaryrefslogtreecommitdiff
path: root/bgpd/rfapi/rfapi_import.c
diff options
context:
space:
mode:
authorwhitespace / reindent <invalid@invalid.invalid>2017-07-17 14:03:14 +0200
committerwhitespace / reindent <invalid@invalid.invalid>2017-07-17 14:04:07 +0200
commitd62a17aedeb0eebdba98238874bb13d62c48dbf9 (patch)
tree3b319b1d61c8b85b4d1f06adf8b844bb8a9b5107 /bgpd/rfapi/rfapi_import.c
parent888ac268a0077fc9ebd1218cec6ae472af0bfc40 (diff)
indent.py `git ls-files | pcregrep '\.[ch]$' | pcregrep -v '^(ldpd|babeld|nhrpd)/'` Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'bgpd/rfapi/rfapi_import.c')
-rw-r--r--bgpd/rfapi/rfapi_import.c8714
1 files changed, 4182 insertions, 4532 deletions
diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c
index dc8dc1ed2e..d0379e1ef8 100644
--- a/bgpd/rfapi/rfapi_import.c
+++ b/bgpd/rfapi/rfapi_import.c
@@ -1,22 +1,22 @@
- /*
- *
- * Copyright 2009-2016, LabN Consulting, L.L.C.
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
+/*
+*
+* Copyright 2009-2016, LabN Consulting, L.L.C.
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; see the file COPYING; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
/*
* File: rfapi_import.c
@@ -38,7 +38,7 @@
#include "bgpd/bgp_ecommunity.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_route.h"
-#include "bgpd/bgp_mplsvpn.h" /* prefix_rd2str() */
+#include "bgpd/bgp_mplsvpn.h" /* prefix_rd2str() */
#include "bgpd/bgp_vnc_types.h"
#include "bgpd/rfapi/rfapi.h"
@@ -75,47 +75,44 @@
* Allocated for each withdraw timer instance; freed when the timer
* expires or is canceled
*/
-struct rfapi_withdraw
-{
- struct rfapi_import_table *import_table;
- struct route_node *node;
- struct bgp_info *info;
- safi_t safi; /* used only for bulk operations */
- /*
- * For import table node reference count checking (i.e., debugging).
- * Normally when a timer expires, lockoffset should be 0. However, if
- * the timer expiration function is called directly (e.g.,
- * rfapiExpireVpnNow), the node could be locked by a preceding
- * route_top() or route_next() in a loop, so we need to pass this
- * value in.
- */
- int lockoffset;
+struct rfapi_withdraw {
+ struct rfapi_import_table *import_table;
+ struct route_node *node;
+ struct bgp_info *info;
+ safi_t safi; /* used only for bulk operations */
+ /*
+ * For import table node reference count checking (i.e., debugging).
+ * Normally when a timer expires, lockoffset should be 0. However, if
+ * the timer expiration function is called directly (e.g.,
+ * rfapiExpireVpnNow), the node could be locked by a preceding
+ * route_top() or route_next() in a loop, so we need to pass this
+ * value in.
+ */
+ int lockoffset;
};
-/*
+/*
* DEBUG FUNCTION
* It's evil and fiendish. It's compiler-dependent.
* ? Might need LDFLAGS -rdynamic to produce all function names
*/
-void
-rfapiDebugBacktrace (void)
+void rfapiDebugBacktrace(void)
{
#ifdef HAVE_GLIBC_BACKTRACE
#define RFAPI_DEBUG_BACKTRACE_NENTRIES 200
- void *buf[RFAPI_DEBUG_BACKTRACE_NENTRIES];
- char **syms;
- size_t i;
- size_t size;
+ void *buf[RFAPI_DEBUG_BACKTRACE_NENTRIES];
+ char **syms;
+ size_t i;
+ size_t size;
- size = backtrace (buf, RFAPI_DEBUG_BACKTRACE_NENTRIES);
- syms = backtrace_symbols (buf, size);
+ size = backtrace(buf, RFAPI_DEBUG_BACKTRACE_NENTRIES);
+ syms = backtrace_symbols(buf, size);
- for (i = 0; i < size && i < RFAPI_DEBUG_BACKTRACE_NENTRIES; ++i)
- {
- vnc_zlog_debug_verbose ("backtrace[%2zu]: %s", i, syms[i]);
- }
+ for (i = 0; i < size && i < RFAPI_DEBUG_BACKTRACE_NENTRIES; ++i) {
+ vnc_zlog_debug_verbose("backtrace[%2zu]: %s", i, syms[i]);
+ }
- free (syms);
+ free(syms);
#else
#endif
}
@@ -125,89 +122,80 @@ rfapiDebugBacktrace (void)
* Count remote routes and compare with actively-maintained values.
* Abort if they disagree.
*/
-void
-rfapiCheckRouteCount ()
+void rfapiCheckRouteCount()
{
- struct bgp *bgp = bgp_get_default ();
- struct rfapi *h;
- struct rfapi_import_table *it;
- afi_t afi;
-
- assert (bgp);
-
- h = bgp->rfapi;
- assert (h);
-
- for (it = h->imports; it; it = it->next)
- {
- for (afi = AFI_IP; afi < AFI_MAX; ++afi)
- {
-
- struct route_table *rt;
- struct route_node *rn;
-
- int holddown_count = 0;
- int local_count = 0;
- int imported_count = 0;
- int remote_count = 0;
-
- rt = it->imported_vpn[afi];
-
- for (rn = route_top (rt); rn; rn = route_next (rn))
- {
- struct bgp_info *bi;
- struct bgp_info *next;
-
- for (bi = rn->info; bi; bi = next)
- {
- next = bi->next;
-
- if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED))
- {
- ++holddown_count;
-
- }
- else
- {
- if (RFAPI_LOCAL_BI (bi))
- {
- ++local_count;
- }
- else
- {
- if (RFAPI_DIRECT_IMPORT_BI (bi))
- {
- ++imported_count;
- }
- else
- {
- ++remote_count;
- }
- }
- }
- }
- }
-
- if (it->holddown_count[afi] != holddown_count)
- {
- vnc_zlog_debug_verbose ("%s: it->holddown_count %d != holddown_count %d",
- __func__, it->holddown_count[afi], holddown_count);
- assert (0);
- }
- if (it->remote_count[afi] != remote_count)
- {
- vnc_zlog_debug_verbose ("%s: it->remote_count %d != remote_count %d",
- __func__, it->remote_count[afi], remote_count);
- assert (0);
- }
- if (it->imported_count[afi] != imported_count)
- {
- vnc_zlog_debug_verbose ("%s: it->imported_count %d != imported_count %d",
- __func__, it->imported_count[afi], imported_count);
- assert (0);
- }
- }
- }
+ struct bgp *bgp = bgp_get_default();
+ struct rfapi *h;
+ struct rfapi_import_table *it;
+ afi_t afi;
+
+ assert(bgp);
+
+ h = bgp->rfapi;
+ assert(h);
+
+ for (it = h->imports; it; it = it->next) {
+ for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
+
+ struct route_table *rt;
+ struct route_node *rn;
+
+ int holddown_count = 0;
+ int local_count = 0;
+ int imported_count = 0;
+ int remote_count = 0;
+
+ rt = it->imported_vpn[afi];
+
+ for (rn = route_top(rt); rn; rn = route_next(rn)) {
+ struct bgp_info *bi;
+ struct bgp_info *next;
+
+ for (bi = rn->info; bi; bi = next) {
+ next = bi->next;
+
+ if (CHECK_FLAG(bi->flags,
+ BGP_INFO_REMOVED)) {
+ ++holddown_count;
+
+ } else {
+ if (RFAPI_LOCAL_BI(bi)) {
+ ++local_count;
+ } else {
+ if (RFAPI_DIRECT_IMPORT_BI(
+ bi)) {
+ ++imported_count;
+ } else {
+ ++remote_count;
+ }
+ }
+ }
+ }
+ }
+
+ if (it->holddown_count[afi] != holddown_count) {
+ vnc_zlog_debug_verbose(
+ "%s: it->holddown_count %d != holddown_count %d",
+ __func__, it->holddown_count[afi],
+ holddown_count);
+ assert(0);
+ }
+ if (it->remote_count[afi] != remote_count) {
+ vnc_zlog_debug_verbose(
+ "%s: it->remote_count %d != remote_count %d",
+ __func__, it->remote_count[afi],
+ remote_count);
+ assert(0);
+ }
+ if (it->imported_count[afi] != imported_count) {
+ vnc_zlog_debug_verbose(
+ "%s: it->imported_count %d != imported_count %d",
+ __func__, it->imported_count[afi],
+ imported_count);
+ assert(0);
+ }
+ }
+ }
}
#if DEBUG_ROUTE_COUNTERS
@@ -224,825 +212,777 @@ rfapiCheckRouteCount ()
* node->lock == 1, and we have to validate the refcount before
* the node is deleted. In this case, we specify lockoffset 1.
*/
-void
-rfapiCheckRefcount (struct route_node *rn, safi_t safi, int lockoffset)
+void rfapiCheckRefcount(struct route_node *rn, safi_t safi, int lockoffset)
{
- unsigned int count_bi = 0;
- unsigned int count_monitor = 0;
- struct bgp_info *bi;
- struct rfapi_monitor_encap *hme;
- struct rfapi_monitor_vpn *hmv;
-
- for (bi = rn->info; bi; bi = bi->next)
- ++count_bi;
-
-
- if (rn->aggregate)
- {
- ++count_monitor; /* rfapi_it_extra */
-
- switch (safi)
- {
- void *cursor;
- int rc;
-
- case SAFI_ENCAP:
- for (hme = RFAPI_MONITOR_ENCAP (rn); hme; hme = hme->next)
- ++count_monitor;
- break;
-
- case SAFI_MPLS_VPN:
-
- for (hmv = RFAPI_MONITOR_VPN (rn); hmv; hmv = hmv->next)
- ++count_monitor;
-
- if (RFAPI_MONITOR_EXTERIOR (rn)->source)
- {
- ++count_monitor; /* sl */
- cursor = NULL;
- for (rc = skiplist_next (RFAPI_MONITOR_EXTERIOR (rn)->source,
- NULL, NULL, &cursor);
- !rc;
- rc = skiplist_next (RFAPI_MONITOR_EXTERIOR (rn)->source,
- NULL, NULL, &cursor))
- {
-
- ++count_monitor; /* sl entry */
- }
- }
- break;
-
- default:
- assert (0);
- }
- }
-
- if (count_bi + count_monitor + lockoffset != rn->lock)
- {
- vnc_zlog_debug_verbose
- ("%s: count_bi=%d, count_monitor=%d, lockoffset=%d, rn->lock=%d",
- __func__, count_bi, count_monitor, lockoffset, rn->lock);
- assert (0);
- }
+ unsigned int count_bi = 0;
+ unsigned int count_monitor = 0;
+ struct bgp_info *bi;
+ struct rfapi_monitor_encap *hme;
+ struct rfapi_monitor_vpn *hmv;
+
+ for (bi = rn->info; bi; bi = bi->next)
+ ++count_bi;
+
+
+ if (rn->aggregate) {
+ ++count_monitor; /* rfapi_it_extra */
+
+ switch (safi) {
+ void *cursor;
+ int rc;
+
+ case SAFI_ENCAP:
+ for (hme = RFAPI_MONITOR_ENCAP(rn); hme;
+ hme = hme->next)
+ ++count_monitor;
+ break;
+
+ case SAFI_MPLS_VPN:
+
+ for (hmv = RFAPI_MONITOR_VPN(rn); hmv; hmv = hmv->next)
+ ++count_monitor;
+
+ if (RFAPI_MONITOR_EXTERIOR(rn)->source) {
+ ++count_monitor; /* sl */
+ cursor = NULL;
+ for (rc = skiplist_next(
+ RFAPI_MONITOR_EXTERIOR(rn)->source,
+ NULL, NULL, &cursor);
+ !rc;
+ rc = skiplist_next(
+ RFAPI_MONITOR_EXTERIOR(rn)->source,
+ NULL, NULL, &cursor)) {
+
+ ++count_monitor; /* sl entry */
+ }
+ }
+ break;
+
+ default:
+ assert(0);
+ }
+ }
+
+ if (count_bi + count_monitor + lockoffset != rn->lock) {
+ vnc_zlog_debug_verbose(
+ "%s: count_bi=%d, count_monitor=%d, lockoffset=%d, rn->lock=%d",
+ __func__, count_bi, count_monitor, lockoffset,
+ rn->lock);
+ assert(0);
+ }
}
/*
* Perform deferred rfapi_close operations that were queued
* during callbacks.
*/
-static wq_item_status
-rfapi_deferred_close_workfunc (struct work_queue *q, void *data)
+static wq_item_status rfapi_deferred_close_workfunc(struct work_queue *q,
+ void *data)
{
- struct rfapi_descriptor *rfd = data;
- struct rfapi *h = q->spec.data;
-
- assert (!(h->flags & RFAPI_INCALLBACK));
- rfapi_close (rfd);
- vnc_zlog_debug_verbose ("%s: completed deferred close on handle %p", __func__, rfd);
- return WQ_SUCCESS;
+ struct rfapi_descriptor *rfd = data;
+ struct rfapi *h = q->spec.data;
+
+ assert(!(h->flags & RFAPI_INCALLBACK));
+ rfapi_close(rfd);
+ vnc_zlog_debug_verbose("%s: completed deferred close on handle %p",
+ __func__, rfd);
+ return WQ_SUCCESS;
}
/*
* Extract layer 2 option from Encap TLVS in BGP attrs
*/
-int
-rfapiGetL2o (struct attr *attr, struct rfapi_l2address_option *l2o)
+int rfapiGetL2o(struct attr *attr, struct rfapi_l2address_option *l2o)
{
- if (attr)
- {
-
- struct bgp_attr_encap_subtlv *pEncap;
-
- for (pEncap = attr->vnc_subtlvs; pEncap; pEncap = pEncap->next)
- {
-
- if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION)
- {
- if (pEncap->value[0] == RFAPI_VN_OPTION_TYPE_L2ADDR)
- {
-
- if (pEncap->value[1] == 14)
- {
- memcpy (l2o->macaddr.octet, pEncap->value + 2,
- ETHER_ADDR_LEN);
- l2o->label =
- ((pEncap->value[10] >> 4) & 0x0f) +
- ((pEncap->value[9] << 4) & 0xff0) +
- ((pEncap->value[8] << 12) & 0xff000);
-
- l2o->local_nve_id = pEncap->value[12];
-
- l2o->logical_net_id =
- (pEncap->value[15] & 0xff) +
- ((pEncap->value[14] << 8) & 0xff00) +
- ((pEncap->value[13] << 16) & 0xff0000);
- }
-
- return 0;
- }
- }
- }
- }
-
- return ENOENT;
+ if (attr) {
+
+ struct bgp_attr_encap_subtlv *pEncap;
+
+ for (pEncap = attr->vnc_subtlvs; pEncap;
+ pEncap = pEncap->next) {
+
+ if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION) {
+ if (pEncap->value[0]
+ == RFAPI_VN_OPTION_TYPE_L2ADDR) {
+
+ if (pEncap->value[1] == 14) {
+ memcpy(l2o->macaddr.octet,
+ pEncap->value + 2,
+ ETHER_ADDR_LEN);
+ l2o->label =
+ ((pEncap->value[10]
+ >> 4)
+ & 0x0f)
+ + ((pEncap->value[9]
+ << 4)
+ & 0xff0)
+ + ((pEncap->value[8]
+ << 12)
+ & 0xff000);
+
+ l2o->local_nve_id =
+ pEncap->value[12];
+
+ l2o->logical_net_id =
+ (pEncap->value[15]
+ & 0xff)
+ + ((pEncap->value[14]
+ << 8)
+ & 0xff00)
+ + ((pEncap->value[13]
+ << 16)
+ & 0xff0000);
+ }
+
+ return 0;
+ }
+ }
+ }
+ }
+
+ return ENOENT;
}
/*
* Extract the lifetime from the Tunnel Encap attribute of a route in
* an import table
*/
-int
-rfapiGetVncLifetime (struct attr *attr, uint32_t * lifetime)
+int rfapiGetVncLifetime(struct attr *attr, uint32_t *lifetime)
{
- struct bgp_attr_encap_subtlv *pEncap;
+ struct bgp_attr_encap_subtlv *pEncap;
- *lifetime = RFAPI_INFINITE_LIFETIME; /* default to infinite */
+ *lifetime = RFAPI_INFINITE_LIFETIME; /* default to infinite */
- if (attr)
- {
+ if (attr) {
- for (pEncap = attr->vnc_subtlvs; pEncap; pEncap = pEncap->next)
- {
+ for (pEncap = attr->vnc_subtlvs; pEncap;
+ pEncap = pEncap->next) {
- if (pEncap->type == BGP_VNC_SUBTLV_TYPE_LIFETIME)
- { /* lifetime */
- if (pEncap->length == 4)
- {
- memcpy (lifetime, pEncap->value, 4);
- *lifetime = ntohl (*lifetime);
- return 0;
- }
- }
- }
- }
+ if (pEncap->type
+ == BGP_VNC_SUBTLV_TYPE_LIFETIME) { /* lifetime */
+ if (pEncap->length == 4) {
+ memcpy(lifetime, pEncap->value, 4);
+ *lifetime = ntohl(*lifetime);
+ return 0;
+ }
+ }
+ }
+ }
- return ENOENT;
+ return ENOENT;
}
/*
* Extract the tunnel type from the extended community
*/
-int
-rfapiGetTunnelType (struct attr *attr,
- bgp_encap_types *type)
+int rfapiGetTunnelType(struct attr *attr, bgp_encap_types *type)
{
- *type = BGP_ENCAP_TYPE_MPLS; /* default to MPLS */
- if (attr && attr->ecommunity)
- {
- struct ecommunity *ecom = attr->ecommunity;
- int i;
-
- for (i = 0; i < (ecom->size * ECOMMUNITY_SIZE); i += ECOMMUNITY_SIZE)
- {
- uint8_t *ep;
-
- ep = ecom->val + i;
- if (ep[0] == ECOMMUNITY_ENCODE_OPAQUE &&
- ep[1] == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP)
- {
- *type = (ep[6]<<8) + ep[7];
- return 0;
- }
- }
- }
-
- return ENOENT;
+ *type = BGP_ENCAP_TYPE_MPLS; /* default to MPLS */
+ if (attr && attr->ecommunity) {
+ struct ecommunity *ecom = attr->ecommunity;
+ int i;
+
+ for (i = 0; i < (ecom->size * ECOMMUNITY_SIZE);
+ i += ECOMMUNITY_SIZE) {
+ uint8_t *ep;
+
+ ep = ecom->val + i;
+ if (ep[0] == ECOMMUNITY_ENCODE_OPAQUE
+ && ep[1] == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP) {
+ *type = (ep[6] << 8) + ep[7];
+ return 0;
+ }
+ }
+ }
+
+ return ENOENT;
}
/*
* Look for UN address in Encap attribute
*/
-int
-rfapiGetVncTunnelUnAddr (struct attr *attr, struct prefix *p)
+int rfapiGetVncTunnelUnAddr(struct attr *attr, struct prefix *p)
{
- struct bgp_attr_encap_subtlv *pEncap;
- bgp_encap_types tun_type;
-
- rfapiGetTunnelType (attr, &tun_type);
- if (tun_type == BGP_ENCAP_TYPE_MPLS)
- {
- if (!p)
- return 0;
- /* MPLS carries UN address in next hop */
- rfapiNexthop2Prefix (attr, p);
- if (p->family != 0)
- return 0;
-
- return ENOENT;
- }
- if (attr)
- {
- for (pEncap = attr->encap_subtlvs; pEncap; pEncap = pEncap->next)
- {
-
- if (pEncap->type == BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT)
- { /* un addr */
- switch (pEncap->length)
- {
- case 8:
- if (p)
- {
- p->family = AF_INET;
- p->prefixlen = 32;
- memcpy (p->u.val, pEncap->value, 4);
- }
- return 0;
-
- case 20:
- if (p)
- {
- p->family = AF_INET6;
- p->prefixlen = 128;
- memcpy (p->u.val, pEncap->value, 16);
- }
- return 0;
- }
- }
- }
- }
-
- return ENOENT;
+ struct bgp_attr_encap_subtlv *pEncap;
+ bgp_encap_types tun_type;
+
+ rfapiGetTunnelType(attr, &tun_type);
+ if (tun_type == BGP_ENCAP_TYPE_MPLS) {
+ if (!p)
+ return 0;
+ /* MPLS carries UN address in next hop */
+ rfapiNexthop2Prefix(attr, p);
+ if (p->family != 0)
+ return 0;
+
+ return ENOENT;
+ }
+ if (attr) {
+ for (pEncap = attr->encap_subtlvs; pEncap;
+ pEncap = pEncap->next) {
+
+ if (pEncap->type
+ == BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT) { /* un
+ addr
+ */
+ switch (pEncap->length) {
+ case 8:
+ if (p) {
+ p->family = AF_INET;
+ p->prefixlen = 32;
+ memcpy(p->u.val, pEncap->value,
+ 4);
+ }
+ return 0;
+
+ case 20:
+ if (p) {
+ p->family = AF_INET6;
+ p->prefixlen = 128;
+ memcpy(p->u.val, pEncap->value,
+ 16);
+ }
+ return 0;
+ }
+ }
+ }
+ }
+
+ return ENOENT;
}
/*
* Get UN address wherever it might be
*/
-int
-rfapiGetUnAddrOfVpnBi (struct bgp_info *bi, struct prefix *p)
+int rfapiGetUnAddrOfVpnBi(struct bgp_info *bi, struct prefix *p)
{
- /* If it's in this route's VNC attribute, we're done */
- if (!rfapiGetVncTunnelUnAddr (bi->attr, p))
- return 0;
- /*
- * Otherwise, see if it's cached from a corresponding ENCAP SAFI
- * advertisement
- */
- if (bi->extra)
- {
- switch (bi->extra->vnc.import.un_family)
- {
- case AF_INET:
- if (p)
- {
- p->family = bi->extra->vnc.import.un_family;
- p->u.prefix4 = bi->extra->vnc.import.un.addr4;
- p->prefixlen = 32;
- }
- return 0;
- case AF_INET6:
- if (p)
- {
- p->family = bi->extra->vnc.import.un_family;
- p->u.prefix6 = bi->extra->vnc.import.un.addr6;
- p->prefixlen = 128;
- }
- return 0;
- default:
- if (p)
- p->family = 0;
+ /* If it's in this route's VNC attribute, we're done */
+ if (!rfapiGetVncTunnelUnAddr(bi->attr, p))
+ return 0;
+ /*
+ * Otherwise, see if it's cached from a corresponding ENCAP SAFI
+ * advertisement
+ */
+ if (bi->extra) {
+ switch (bi->extra->vnc.import.un_family) {
+ case AF_INET:
+ if (p) {
+ p->family = bi->extra->vnc.import.un_family;
+ p->u.prefix4 = bi->extra->vnc.import.un.addr4;
+ p->prefixlen = 32;
+ }
+ return 0;
+ case AF_INET6:
+ if (p) {
+ p->family = bi->extra->vnc.import.un_family;
+ p->u.prefix6 = bi->extra->vnc.import.un.addr6;
+ p->prefixlen = 128;
+ }
+ return 0;
+ default:
+ if (p)
+ p->family = 0;
#if DEBUG_ENCAP_MONITOR
- vnc_zlog_debug_verbose ("%s: bi->extra->vnc.import.un_family is 0, no UN addr",
- __func__);
+ vnc_zlog_debug_verbose(
+ "%s: bi->extra->vnc.import.un_family is 0, no UN addr",
+ __func__);
#endif
- break;
- }
- }
+ break;
+ }
+ }
- return ENOENT;
+ return ENOENT;
}
/*
* Make a new bgp_info from gathered parameters
*/
-static struct bgp_info *
-rfapiBgpInfoCreate (
- struct attr *attr,
- struct peer *peer,
- void *rfd,
- struct prefix_rd *prd,
- u_char type,
- u_char sub_type,
- uint32_t *label)
+static struct bgp_info *rfapiBgpInfoCreate(struct attr *attr, struct peer *peer,
+ void *rfd, struct prefix_rd *prd,
+ u_char type, u_char sub_type,
+ uint32_t *label)
{
- struct bgp_info *new;
-
- new = bgp_info_new ();
- assert (new);
-
- if (attr)
- {
- if (!new->attr)
- new->attr = bgp_attr_intern (attr);
- }
- bgp_info_extra_get (new);
- if (prd)
- {
- new->extra->vnc.import.rd = *prd;
- rfapi_time (&new->extra->vnc.import.create_time);
- }
- if (label)
- encode_label (*label, &new->extra->label);
- new->type = type;
- new->sub_type = sub_type;
- new->peer = peer;
- peer_lock (peer);
-
- return new;
+ struct bgp_info *new;
+
+ new = bgp_info_new();
+ assert(new);
+
+ if (attr) {
+ if (!new->attr)
+ new->attr = bgp_attr_intern(attr);
+ }
+ bgp_info_extra_get(new);
+ if (prd) {
+ new->extra->vnc.import.rd = *prd;
+ rfapi_time(&new->extra->vnc.import.create_time);
+ }
+ if (label)
+ encode_label(*label, &new->extra->label);
+ new->type = type;
+ new->sub_type = sub_type;
+ new->peer = peer;
+ peer_lock(peer);
+
+ return new;
}
/*
* Frees bgp_info as used in import tables (parts are not
* allocated exactly the way they are in the main RIBs)
*/
-static void
-rfapiBgpInfoFree (struct bgp_info *goner)
+static void rfapiBgpInfoFree(struct bgp_info *goner)
{
- if (!goner)
- return;
-
- if (goner->peer)
- {
- vnc_zlog_debug_verbose ("%s: calling peer_unlock(%p), #%d",
- __func__, goner->peer, goner->peer->lock);
- peer_unlock (goner->peer);
- }
-
- if (goner->attr)
- {
- bgp_attr_unintern (&goner->attr);
- }
- if (goner->extra)
- {
- assert (!goner->extra->damp_info); /* Not used in import tbls */
- XFREE (MTYPE_BGP_ROUTE_EXTRA, goner->extra);
- goner->extra = NULL;
- }
- XFREE (MTYPE_BGP_ROUTE, goner);
+ if (!goner)
+ return;
+
+ if (goner->peer) {
+ vnc_zlog_debug_verbose("%s: calling peer_unlock(%p), #%d",
+ __func__, goner->peer,
+ goner->peer->lock);
+ peer_unlock(goner->peer);
+ }
+
+ if (goner->attr) {
+ bgp_attr_unintern(&goner->attr);
+ }
+ if (goner->extra) {
+ assert(!goner->extra->damp_info); /* Not used in import tbls */
+ XFREE(MTYPE_BGP_ROUTE_EXTRA, goner->extra);
+ goner->extra = NULL;
+ }
+ XFREE(MTYPE_BGP_ROUTE, goner);
}
-struct rfapi_import_table *
-rfapiMacImportTableGetNoAlloc (struct bgp *bgp, uint32_t lni)
+struct rfapi_import_table *rfapiMacImportTableGetNoAlloc(struct bgp *bgp,
+ uint32_t lni)
{
- struct rfapi *h;
- struct rfapi_import_table *it = NULL;
- uintptr_t lni_as_ptr = lni;
+ struct rfapi *h;
+ struct rfapi_import_table *it = NULL;
+ uintptr_t lni_as_ptr = lni;
- h = bgp->rfapi;
- if (!h)
- return NULL;
+ h = bgp->rfapi;
+ if (!h)
+ return NULL;
- if (!h->import_mac)
- return NULL;
+ if (!h->import_mac)
+ return NULL;
- if (skiplist_search (h->import_mac, (void *) lni_as_ptr, (void **) &it))
- return NULL;
+ if (skiplist_search(h->import_mac, (void *)lni_as_ptr, (void **)&it))
+ return NULL;
- return it;
+ return it;
}
-struct rfapi_import_table *
-rfapiMacImportTableGet (struct bgp *bgp, uint32_t lni)
+struct rfapi_import_table *rfapiMacImportTableGet(struct bgp *bgp, uint32_t lni)
{
- struct rfapi *h;
- struct rfapi_import_table *it = NULL;
- uintptr_t lni_as_ptr = lni;
-
- h = bgp->rfapi;
- assert (h);
-
- if (!h->import_mac)
- {
- /* default cmp is good enough for LNI */
- h->import_mac = skiplist_new (0, NULL, NULL);
- }
-
- if (skiplist_search (h->import_mac, (void *) lni_as_ptr, (void **) &it))
- {
-
- struct ecommunity *enew;
- struct ecommunity_val eval;
- afi_t afi;
-
- it =
- XCALLOC (MTYPE_RFAPI_IMPORTTABLE, sizeof (struct rfapi_import_table));
- /* set RT list of new import table based on LNI */
- memset ((char *) &eval, 0, sizeof (eval));
- eval.val[0] = 0; /* VNC L2VPN */
- eval.val[1] = 2; /* VNC L2VPN */
- eval.val[5] = (lni >> 16) & 0xff;
- eval.val[6] = (lni >> 8) & 0xff;
- eval.val[7] = (lni >> 0) & 0xff;
-
- enew = ecommunity_new ();
- ecommunity_add_val (enew, &eval);
- it->rt_import_list = enew;
-
- for (afi = AFI_IP; afi < AFI_MAX; ++afi)
- {
- it->imported_vpn[afi] = route_table_init ();
- it->imported_encap[afi] = route_table_init ();
- }
-
- it->l2_logical_net_id = lni;
-
- skiplist_insert (h->import_mac, (void *) lni_as_ptr, it);
- }
-
- assert (it);
- return it;
+ struct rfapi *h;
+ struct rfapi_import_table *it = NULL;
+ uintptr_t lni_as_ptr = lni;
+
+ h = bgp->rfapi;
+ assert(h);
+
+ if (!h->import_mac) {
+ /* default cmp is good enough for LNI */
+ h->import_mac = skiplist_new(0, NULL, NULL);
+ }
+
+ if (skiplist_search(h->import_mac, (void *)lni_as_ptr, (void **)&it)) {
+
+ struct ecommunity *enew;
+ struct ecommunity_val eval;
+ afi_t afi;
+
+ it = XCALLOC(MTYPE_RFAPI_IMPORTTABLE,
+ sizeof(struct rfapi_import_table));
+ /* set RT list of new import table based on LNI */
+ memset((char *)&eval, 0, sizeof(eval));
+ eval.val[0] = 0; /* VNC L2VPN */
+ eval.val[1] = 2; /* VNC L2VPN */
+ eval.val[5] = (lni >> 16) & 0xff;
+ eval.val[6] = (lni >> 8) & 0xff;
+ eval.val[7] = (lni >> 0) & 0xff;
+
+ enew = ecommunity_new();
+ ecommunity_add_val(enew, &eval);
+ it->rt_import_list = enew;
+
+ for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
+ it->imported_vpn[afi] = route_table_init();
+ it->imported_encap[afi] = route_table_init();
+ }
+
+ it->l2_logical_net_id = lni;
+
+ skiplist_insert(h->import_mac, (void *)lni_as_ptr, it);
+ }
+
+ assert(it);
+ return it;
}
/*
* Implement MONITOR_MOVE_SHORTER(original_node) from
* RFAPI-Import-Event-Handling.txt
- *
+ *
* Returns pointer to the list of moved monitors
*/
static struct rfapi_monitor_vpn *
-rfapiMonitorMoveShorter (struct route_node *original_vpn_node, int lockoffset)
+rfapiMonitorMoveShorter(struct route_node *original_vpn_node, int lockoffset)
{
- struct bgp_info *bi;
- struct route_node *par;
- struct rfapi_monitor_vpn *m;
- struct rfapi_monitor_vpn *mlast;
- struct rfapi_monitor_vpn *moved;
- int movecount = 0;
- int parent_already_refcounted = 0;
+ struct bgp_info *bi;
+ struct route_node *par;
+ struct rfapi_monitor_vpn *m;
+ struct rfapi_monitor_vpn *mlast;
+ struct rfapi_monitor_vpn *moved;
+ int movecount = 0;
+ int parent_already_refcounted = 0;
- RFAPI_CHECK_REFCOUNT (original_vpn_node, SAFI_MPLS_VPN, lockoffset);
+ RFAPI_CHECK_REFCOUNT(original_vpn_node, SAFI_MPLS_VPN, lockoffset);
#if DEBUG_MONITOR_MOVE_SHORTER
- {
- char buf[BUFSIZ];
+ {
+ char buf[BUFSIZ];
- prefix2str (&original_vpn_node->p, buf, BUFSIZ);
- buf[BUFSIZ - 1] = 0;
- vnc_zlog_debug_verbose ("%s: called with node pfx=%s", __func__, buf);
- }
+ prefix2str(&original_vpn_node->p, buf, BUFSIZ);
+ buf[BUFSIZ - 1] = 0;
+ vnc_zlog_debug_verbose("%s: called with node pfx=%s", __func__,
+ buf);
+ }
#endif
- /*
- * 1. If there is at least one bi (either regular route or
- * route marked as withdrawn, with a pending timer) at
- * original_node with a valid UN address, we're done. Return.
- */
- for (bi = original_vpn_node->info; bi; bi = bi->next)
- {
- struct prefix pfx;
-
- if (!rfapiGetUnAddrOfVpnBi (bi, &pfx))
- {
+ /*
+ * 1. If there is at least one bi (either regular route or
+ * route marked as withdrawn, with a pending timer) at
+ * original_node with a valid UN address, we're done. Return.
+ */
+ for (bi = original_vpn_node->info; bi; bi = bi->next) {
+ struct prefix pfx;
+
+ if (!rfapiGetUnAddrOfVpnBi(bi, &pfx)) {
#if DEBUG_MONITOR_MOVE_SHORTER
- vnc_zlog_debug_verbose ("%s: have valid UN at original node, no change",
- __func__);
+ vnc_zlog_debug_verbose(
+ "%s: have valid UN at original node, no change",
+ __func__);
#endif
- return NULL;
- }
- }
-
- /*
- * 2. Travel up the tree (toward less-specific prefixes) from
- * original_node to find the first node that has at least
- * one route (even if it is only a withdrawn route) with a
- * valid UN address. Call this node "Node P."
- */
- for (par = original_vpn_node->parent; par; par = par->parent)
- {
- for (bi = par->info; bi; bi = bi->next)
- {
- struct prefix pfx;
- if (!rfapiGetUnAddrOfVpnBi (bi, &pfx))
- {
- break;
- }
- }
- if (bi)
- break;
- }
-
- if (par)
- {
- RFAPI_CHECK_REFCOUNT (par, SAFI_MPLS_VPN, 0);
- }
-
- /*
- * If no less-specific routes, try to use the 0/0 node
- */
- if (!par)
- {
- /* this isn't necessarily 0/0 */
- par = route_top (original_vpn_node->table);
-
- /*
- * If we got the top node but it wasn't 0/0,
- * ignore it
- */
- if (par && par->p.prefixlen)
- {
- route_unlock_node (par); /* maybe free */
- par = NULL;
- }
-
- if (par)
- {
- ++parent_already_refcounted;
- }
- }
-
- /*
- * Create 0/0 node if it isn't there
- */
- if (!par)
- {
- struct prefix pfx_default;
-
- memset (&pfx_default, 0, sizeof (pfx_default));
- pfx_default.family = original_vpn_node->p.family;
-
- /* creates default node if none exists */
- par = route_node_get (original_vpn_node->table, &pfx_default);
- ++parent_already_refcounted;
- }
-
- /*
- * 3. Move each of the monitors found at original_node to Node P.
- * These are "Moved Monitors."
- *
- */
-
- /*
- * Attach at end so that the list pointer we return points
- * only to the moved routes
- */
- for (m = RFAPI_MONITOR_VPN (par), mlast = NULL; m; mlast = m, m = m->next);
-
- if (mlast)
- {
- moved = mlast->next = RFAPI_MONITOR_VPN (original_vpn_node);
- }
- else
- {
- moved = RFAPI_MONITOR_VPN_W_ALLOC (par) =
- RFAPI_MONITOR_VPN (original_vpn_node);
- }
- if (RFAPI_MONITOR_VPN (original_vpn_node)) /* check agg, so not allocated */
- RFAPI_MONITOR_VPN_W_ALLOC (original_vpn_node) = NULL;
-
- /*
- * update the node pointers on the monitors
- */
- for (m = moved; m; m = m->next)
- {
- ++movecount;
- m->node = par;
- }
-
- RFAPI_CHECK_REFCOUNT (par, SAFI_MPLS_VPN,
- parent_already_refcounted - movecount);
- while (movecount > parent_already_refcounted)
- {
- route_lock_node (par);
- ++parent_already_refcounted;
- }
- while (movecount < parent_already_refcounted)
- {
- /* unlikely, but code defensively */
- route_unlock_node (par);
- --parent_already_refcounted;
- }
- RFAPI_CHECK_REFCOUNT (original_vpn_node, SAFI_MPLS_VPN,
- movecount + lockoffset);
- while (movecount--)
- {
- route_unlock_node (original_vpn_node);
- }
+ return NULL;
+ }
+ }
+
+ /*
+ * 2. Travel up the tree (toward less-specific prefixes) from
+ * original_node to find the first node that has at least
+ * one route (even if it is only a withdrawn route) with a
+ * valid UN address. Call this node "Node P."
+ */
+ for (par = original_vpn_node->parent; par; par = par->parent) {
+ for (bi = par->info; bi; bi = bi->next) {
+ struct prefix pfx;
+ if (!rfapiGetUnAddrOfVpnBi(bi, &pfx)) {
+ break;
+ }
+ }
+ if (bi)
+ break;
+ }
+
+ if (par) {
+ RFAPI_CHECK_REFCOUNT(par, SAFI_MPLS_VPN, 0);
+ }
+
+ /*
+ * If no less-specific routes, try to use the 0/0 node
+ */
+ if (!par) {
+ /* this isn't necessarily 0/0 */
+ par = route_top(original_vpn_node->table);
+
+ /*
+ * If we got the top node but it wasn't 0/0,
+ * ignore it
+ */
+ if (par && par->p.prefixlen) {
+ route_unlock_node(par); /* maybe free */
+ par = NULL;
+ }
+
+ if (par) {
+ ++parent_already_refcounted;
+ }
+ }
+
+ /*
+ * Create 0/0 node if it isn't there
+ */
+ if (!par) {
+ struct prefix pfx_default;
+
+ memset(&pfx_default, 0, sizeof(pfx_default));
+ pfx_default.family = original_vpn_node->p.family;
+
+ /* creates default node if none exists */
+ par = route_node_get(original_vpn_node->table, &pfx_default);
+ ++parent_already_refcounted;
+ }
+
+ /*
+ * 3. Move each of the monitors found at original_node to Node P.
+ * These are "Moved Monitors."
+ *
+ */
+
+ /*
+ * Attach at end so that the list pointer we return points
+ * only to the moved routes
+ */
+ for (m = RFAPI_MONITOR_VPN(par), mlast = NULL; m;
+ mlast = m, m = m->next)
+ ;
+
+ if (mlast) {
+ moved = mlast->next = RFAPI_MONITOR_VPN(original_vpn_node);
+ } else {
+ moved = RFAPI_MONITOR_VPN_W_ALLOC(par) =
+ RFAPI_MONITOR_VPN(original_vpn_node);
+ }
+ if (RFAPI_MONITOR_VPN(
+ original_vpn_node)) /* check agg, so not allocated */
+ RFAPI_MONITOR_VPN_W_ALLOC(original_vpn_node) = NULL;
+
+ /*
+ * update the node pointers on the monitors
+ */
+ for (m = moved; m; m = m->next) {
+ ++movecount;
+ m->node = par;
+ }
+
+ RFAPI_CHECK_REFCOUNT(par, SAFI_MPLS_VPN,
+ parent_already_refcounted - movecount);
+ while (movecount > parent_already_refcounted) {
+ route_lock_node(par);
+ ++parent_already_refcounted;
+ }
+ while (movecount < parent_already_refcounted) {
+ /* unlikely, but code defensively */
+ route_unlock_node(par);
+ --parent_already_refcounted;
+ }
+ RFAPI_CHECK_REFCOUNT(original_vpn_node, SAFI_MPLS_VPN,
+ movecount + lockoffset);
+ while (movecount--) {
+ route_unlock_node(original_vpn_node);
+ }
#if DEBUG_MONITOR_MOVE_SHORTER
- {
- char buf[BUFSIZ];
+ {
+ char buf[BUFSIZ];
- prefix2str (&par->p, buf, BUFSIZ);
- buf[BUFSIZ - 1] = 0;
- vnc_zlog_debug_verbose ("%s: moved to node pfx=%s", __func__, buf);
- }
+ prefix2str(&par->p, buf, BUFSIZ);
+ buf[BUFSIZ - 1] = 0;
+ vnc_zlog_debug_verbose("%s: moved to node pfx=%s", __func__,
+ buf);
+ }
#endif
- return moved;
+ return moved;
}
/*
* Implement MONITOR_MOVE_LONGER(new_node) from
* RFAPI-Import-Event-Handling.txt
*/
-static void
-rfapiMonitorMoveLonger (struct route_node *new_vpn_node)
+static void rfapiMonitorMoveLonger(struct route_node *new_vpn_node)
{
- struct rfapi_monitor_vpn *monitor;
- struct rfapi_monitor_vpn *mlast;
- struct bgp_info *bi;
- struct route_node *par;
-
- RFAPI_CHECK_REFCOUNT (new_vpn_node, SAFI_MPLS_VPN, 0);
-
- /*
- * Make sure we have at least one valid route at the new node
- */
- for (bi = new_vpn_node->info; bi; bi = bi->next)
- {
- struct prefix pfx;
- if (!rfapiGetUnAddrOfVpnBi (bi, &pfx))
- break;
- }
-
- if (!bi)
- {
- vnc_zlog_debug_verbose ("%s: no valid routes at node %p, so not attempting moves",
- __func__, new_vpn_node);
- return;
- }
-
- /*
- * Find first parent node that has monitors
- */
- for (par = new_vpn_node->parent; par; par = par->parent)
- {
- if (RFAPI_MONITOR_VPN (par))
- break;
- }
-
- if (!par)
- {
- vnc_zlog_debug_verbose ("%s: no parent nodes with monitors, done", __func__);
- return;
- }
-
- /*
- * Check each of these monitors to see of their longest-match
- * is now the updated node. Move any such monitors to the more-
- * specific updated node
- */
- for (mlast = NULL, monitor = RFAPI_MONITOR_VPN (par); monitor;)
- {
-
- /*
- * If new longest match for monitor prefix is the new
- * route's prefix, move monitor to new route's prefix
- */
- if (prefix_match (&new_vpn_node->p, &monitor->p))
- {
- /* detach */
- if (mlast)
- {
- mlast->next = monitor->next;
- }
- else
- {
- RFAPI_MONITOR_VPN_W_ALLOC (par) = monitor->next;
- }
-
-
- /* attach */
- monitor->next = RFAPI_MONITOR_VPN (new_vpn_node);
- RFAPI_MONITOR_VPN_W_ALLOC (new_vpn_node) = monitor;
- monitor->node = new_vpn_node;
-
- route_lock_node (new_vpn_node); /* incr refcount */
-
- monitor = mlast ? mlast->next : RFAPI_MONITOR_VPN (par);
-
- RFAPI_CHECK_REFCOUNT (par, SAFI_MPLS_VPN, 1);
- /* decr refcount after we're done with par as this might free it */
- route_unlock_node (par);
-
- continue;
- }
- mlast = monitor;
- monitor = monitor->next;
- }
-
- RFAPI_CHECK_REFCOUNT (new_vpn_node, SAFI_MPLS_VPN, 0);
+ struct rfapi_monitor_vpn *monitor;
+ struct rfapi_monitor_vpn *mlast;
+ struct bgp_info *bi;
+ struct route_node *par;
+
+ RFAPI_CHECK_REFCOUNT(new_vpn_node, SAFI_MPLS_VPN, 0);
+
+ /*
+ * Make sure we have at least one valid route at the new node
+ */
+ for (bi = new_vpn_node->info; bi; bi = bi->next) {
+ struct prefix pfx;
+ if (!rfapiGetUnAddrOfVpnBi(bi, &pfx))
+ break;
+ }
+
+ if (!bi) {
+ vnc_zlog_debug_verbose(
+ "%s: no valid routes at node %p, so not attempting moves",
+ __func__, new_vpn_node);
+ return;
+ }
+
+ /*
+ * Find first parent node that has monitors
+ */
+ for (par = new_vpn_node->parent; par; par = par->parent) {
+ if (RFAPI_MONITOR_VPN(par))
+ break;
+ }
+
+ if (!par) {
+ vnc_zlog_debug_verbose(
+ "%s: no parent nodes with monitors, done", __func__);
+ return;
+ }
+
+ /*
+ * Check each of these monitors to see of their longest-match
+ * is now the updated node. Move any such monitors to the more-
+ * specific updated node
+ */
+ for (mlast = NULL, monitor = RFAPI_MONITOR_VPN(par); monitor;) {
+
+ /*
+ * If new longest match for monitor prefix is the new
+ * route's prefix, move monitor to new route's prefix
+ */
+ if (prefix_match(&new_vpn_node->p, &monitor->p)) {
+ /* detach */
+ if (mlast) {
+ mlast->next = monitor->next;
+ } else {
+ RFAPI_MONITOR_VPN_W_ALLOC(par) = monitor->next;
+ }
+
+
+ /* attach */
+ monitor->next = RFAPI_MONITOR_VPN(new_vpn_node);
+ RFAPI_MONITOR_VPN_W_ALLOC(new_vpn_node) = monitor;
+ monitor->node = new_vpn_node;
+
+ route_lock_node(new_vpn_node); /* incr refcount */
+
+ monitor = mlast ? mlast->next : RFAPI_MONITOR_VPN(par);
+
+ RFAPI_CHECK_REFCOUNT(par, SAFI_MPLS_VPN, 1);
+ /* decr refcount after we're done with par as this might
+ * free it */
+ route_unlock_node(par);
+
+ continue;
+ }
+ mlast = monitor;
+ monitor = monitor->next;
+ }
+
+ RFAPI_CHECK_REFCOUNT(new_vpn_node, SAFI_MPLS_VPN, 0);
}
-static void
-rfapiBgpInfoChainFree (struct bgp_info *bi)
+static void rfapiBgpInfoChainFree(struct bgp_info *bi)
{
- struct bgp_info *next;
-
- while (bi)
- {
-
- /*
- * If there is a timer waiting to delete this bi, cancel
- * the timer and delete immediately
- */
- if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED) &&
- bi->extra->vnc.import.timer)
- {
-
- struct thread *t = (struct thread *) bi->extra->vnc.import.timer;
- struct rfapi_withdraw *wcb = t->arg;
-
- XFREE (MTYPE_RFAPI_WITHDRAW, wcb);
- thread_cancel (t);
- }
-
- next = bi->next;
- bi->next = NULL;
- rfapiBgpInfoFree (bi);
- bi = next;
- }
+ struct bgp_info *next;
+
+ while (bi) {
+
+ /*
+ * If there is a timer waiting to delete this bi, cancel
+ * the timer and delete immediately
+ */
+ if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)
+ && bi->extra->vnc.import.timer) {
+
+ struct thread *t =
+ (struct thread *)bi->extra->vnc.import.timer;
+ struct rfapi_withdraw *wcb = t->arg;
+
+ XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
+ thread_cancel(t);
+ }
+
+ next = bi->next;
+ bi->next = NULL;
+ rfapiBgpInfoFree(bi);
+ bi = next;
+ }
}
-static void
-rfapiImportTableFlush (struct rfapi_import_table *it)
+static void rfapiImportTableFlush(struct rfapi_import_table *it)
{
- afi_t afi;
-
- /*
- * Free ecommunity
- */
- ecommunity_free (&it->rt_import_list);
- it->rt_import_list = NULL;
-
- for (afi = AFI_IP; afi < AFI_MAX; ++afi)
- {
-
- struct route_node *rn;
-
- for (rn = route_top (it->imported_vpn[afi]); rn; rn = route_next (rn))
- {
- /*
- * Each route_node has:
- * aggregate: points to rfapi_it_extra with monitor chain(s)
- * info: points to chain of bgp_info
- */
- /* free bgp_info and its children */
- rfapiBgpInfoChainFree (rn->info);
- rn->info = NULL;
-
- rfapiMonitorExtraFlush (SAFI_MPLS_VPN, rn);
- }
-
- for (rn = route_top (it->imported_encap[afi]); rn; rn = route_next (rn))
- {
- /* free bgp_info and its children */
- rfapiBgpInfoChainFree (rn->info);
- rn->info = NULL;
-
- rfapiMonitorExtraFlush (SAFI_ENCAP, rn);
- }
-
- route_table_finish (it->imported_vpn[afi]);
- route_table_finish (it->imported_encap[afi]);
- }
- if (it->monitor_exterior_orphans)
- {
- skiplist_free (it->monitor_exterior_orphans);
- }
+ afi_t afi;
+
+ /*
+ * Free ecommunity
+ */
+ ecommunity_free(&it->rt_import_list);
+ it->rt_import_list = NULL;
+
+ for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
+
+ struct route_node *rn;
+
+ for (rn = route_top(it->imported_vpn[afi]); rn;
+ rn = route_next(rn)) {
+ /*
+ * Each route_node has:
+ * aggregate: points to rfapi_it_extra with monitor
+ * chain(s)
+ * info: points to chain of bgp_info
+ */
+ /* free bgp_info and its children */
+ rfapiBgpInfoChainFree(rn->info);
+ rn->info = NULL;
+
+ rfapiMonitorExtraFlush(SAFI_MPLS_VPN, rn);
+ }
+
+ for (rn = route_top(it->imported_encap[afi]); rn;
+ rn = route_next(rn)) {
+ /* free bgp_info and its children */
+ rfapiBgpInfoChainFree(rn->info);
+ rn->info = NULL;
+
+ rfapiMonitorExtraFlush(SAFI_ENCAP, rn);
+ }
+
+ route_table_finish(it->imported_vpn[afi]);
+ route_table_finish(it->imported_encap[afi]);
+ }
+ if (it->monitor_exterior_orphans) {
+ skiplist_free(it->monitor_exterior_orphans);
+ }
}
-void
-rfapiImportTableRefDelByIt (
- struct bgp *bgp,
- struct rfapi_import_table *it_target)
+void rfapiImportTableRefDelByIt(struct bgp *bgp,
+ struct rfapi_import_table *it_target)
{
- struct rfapi *h;
- struct rfapi_import_table *it;
- struct rfapi_import_table *prev = NULL;
-
- assert (it_target);
-
- h = bgp->rfapi;
- assert (h);
-
- for (it = h->imports; it; prev = it, it = it->next)
- {
- if (it == it_target)
- break;
- }
-
- assert (it);
- assert (it->refcount);
-
- it->refcount -= 1;
-
- if (!it->refcount)
- {
- if (prev)
- {
- prev->next = it->next;
- }
- else
- {
- h->imports = it->next;
- }
- rfapiImportTableFlush (it);
- XFREE (MTYPE_RFAPI_IMPORTTABLE, it);
- }
+ struct rfapi *h;
+ struct rfapi_import_table *it;
+ struct rfapi_import_table *prev = NULL;
+
+ assert(it_target);
+
+ h = bgp->rfapi;
+ assert(h);
+
+ for (it = h->imports; it; prev = it, it = it->next) {
+ if (it == it_target)
+ break;
+ }
+
+ assert(it);
+ assert(it->refcount);
+
+ it->refcount -= 1;
+
+ if (!it->refcount) {
+ if (prev) {
+ prev->next = it->next;
+ } else {
+ h->imports = it->next;
+ }
+ rfapiImportTableFlush(it);
+ XFREE(MTYPE_RFAPI_IMPORTTABLE, it);
+ }
}
#if RFAPI_REQUIRE_ENCAP_BEEC
@@ -1050,298 +990,272 @@ rfapiImportTableRefDelByIt (
* Look for magic BGP Encapsulation Extended Community value
* Format in RFC 5512 Sect. 4.5
*/
-static int
-rfapiEcommunitiesMatchBeec (struct ecommunity *ecom,
- bgp_encap_types type)
+static int rfapiEcommunitiesMatchBeec(struct ecommunity *ecom,
+ bgp_encap_types type)
{
- int i;
-
- if (!ecom)
- return 0;
+ int i;
- for (i = 0; i < (ecom->size * ECOMMUNITY_SIZE); i += ECOMMUNITY_SIZE)
- {
+ if (!ecom)
+ return 0;
- uint8_t *ep;
+ for (i = 0; i < (ecom->size * ECOMMUNITY_SIZE); i += ECOMMUNITY_SIZE) {
- ep = ecom->val + i;
+ uint8_t *ep;
- if (ep[0] == ECOMMUNITY_ENCODE_OPAQUE &&
- ep[1] == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP &&
- ep[6] == ((type && 0xff00)>>8) &&
- ep[7] == (type&0xff))
- {
+ ep = ecom->val + i;
- return 1;
- }
- }
- return 0;
+ if (ep[0] == ECOMMUNITY_ENCODE_OPAQUE
+ && ep[1] == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP
+ && ep[6] == ((type && 0xff00) >> 8)
+ && ep[7] == (type & 0xff)) {
+ return 1;
+ }
+ }
+ return 0;
}
#endif
-int
-rfapiEcommunitiesIntersect (struct ecommunity *e1, struct ecommunity *e2)
+int rfapiEcommunitiesIntersect(struct ecommunity *e1, struct ecommunity *e2)
{
- int i, j;
-
- if (!e1 || !e2)
- return 0;
-
- {
- char *s1, *s2;
- s1 = ecommunity_ecom2str (e1, ECOMMUNITY_FORMAT_DISPLAY, 0);
- s2 = ecommunity_ecom2str (e2, ECOMMUNITY_FORMAT_DISPLAY, 0);
- vnc_zlog_debug_verbose ("%s: e1[%s], e2[%s]", __func__, s1, s2);
- XFREE (MTYPE_ECOMMUNITY_STR, s1);
- XFREE (MTYPE_ECOMMUNITY_STR, s2);
- }
-
- for (i = 0; i < e1->size; ++i)
- {
- for (j = 0; j < e2->size; ++j)
- {
- if (!memcmp (e1->val + (i * ECOMMUNITY_SIZE),
- e2->val + (j * ECOMMUNITY_SIZE), ECOMMUNITY_SIZE))
- {
-
- return 1;
- }
- }
- }
- return 0;
+ int i, j;
+
+ if (!e1 || !e2)
+ return 0;
+
+ {
+ char *s1, *s2;
+ s1 = ecommunity_ecom2str(e1, ECOMMUNITY_FORMAT_DISPLAY, 0);
+ s2 = ecommunity_ecom2str(e2, ECOMMUNITY_FORMAT_DISPLAY, 0);
+ vnc_zlog_debug_verbose("%s: e1[%s], e2[%s]", __func__, s1, s2);
+ XFREE(MTYPE_ECOMMUNITY_STR, s1);
+ XFREE(MTYPE_ECOMMUNITY_STR, s2);
+ }
+
+ for (i = 0; i < e1->size; ++i) {
+ for (j = 0; j < e2->size; ++j) {
+ if (!memcmp(e1->val + (i * ECOMMUNITY_SIZE),
+ e2->val + (j * ECOMMUNITY_SIZE),
+ ECOMMUNITY_SIZE)) {
+
+ return 1;
+ }
+ }
+ }
+ return 0;
}
-int
-rfapiEcommunityGetLNI (struct ecommunity *ecom, uint32_t * lni)
+int rfapiEcommunityGetLNI(struct ecommunity *ecom, uint32_t *lni)
{
- if (ecom)
- {
- int i;
- for (i = 0; i < ecom->size; ++i)
- {
- uint8_t *p = ecom->val + (i * ECOMMUNITY_SIZE);
-
- if ((*(p + 0) == 0x00) && (*(p + 1) == 0x02))
- {
-
- *lni = (*(p + 5) << 16) | (*(p + 6) << 8) | (*(p + 7));
- return 0;
- }
- }
- }
- return ENOENT;
+ if (ecom) {
+ int i;
+ for (i = 0; i < ecom->size; ++i) {
+ uint8_t *p = ecom->val + (i * ECOMMUNITY_SIZE);
+
+ if ((*(p + 0) == 0x00) && (*(p + 1) == 0x02)) {
+
+ *lni = (*(p + 5) << 16) | (*(p + 6) << 8)
+ | (*(p + 7));
+ return 0;
+ }
+ }
+ }
+ return ENOENT;
}
-int
-rfapiEcommunityGetEthernetTag (struct ecommunity *ecom, uint16_t * tag_id)
+int rfapiEcommunityGetEthernetTag(struct ecommunity *ecom, uint16_t *tag_id)
{
- struct bgp *bgp = bgp_get_default ();
- *tag_id = 0; /* default to untagged */
- if (ecom)
- {
- int i;
- for (i = 0; i < ecom->size; ++i)
- {
- as_t as = 0;
- int encode = 0;
- uint8_t *p = ecom->val + (i * ECOMMUNITY_SIZE);
-
- /* High-order octet of type. */
- encode = *p++;
-
- if (*p++ == ECOMMUNITY_ROUTE_TARGET) {
- if (encode == ECOMMUNITY_ENCODE_AS4)
- {
- as = (*p++ << 24);
- as |= (*p++ << 16);
- as |= (*p++ << 8);
- as |= (*p++);
- }
- else if (encode == ECOMMUNITY_ENCODE_AS)
- {
- as = (*p++ << 8);
- as |= (*p++);
- p += 2; /* skip next two, tag/vid always in lowest bytes */
- }
- if (as == bgp->as)
- {
- *tag_id = *p++ << 8;
- *tag_id |= (*p++);
- return 0;
- }
- }
- }
- }
- return ENOENT;
+ struct bgp *bgp = bgp_get_default();
+ *tag_id = 0; /* default to untagged */
+ if (ecom) {
+ int i;
+ for (i = 0; i < ecom->size; ++i) {
+ as_t as = 0;
+ int encode = 0;
+ uint8_t *p = ecom->val + (i * ECOMMUNITY_SIZE);
+
+ /* High-order octet of type. */
+ encode = *p++;
+
+ if (*p++ == ECOMMUNITY_ROUTE_TARGET) {
+ if (encode == ECOMMUNITY_ENCODE_AS4) {
+ as = (*p++ << 24);
+ as |= (*p++ << 16);
+ as |= (*p++ << 8);
+ as |= (*p++);
+ } else if (encode == ECOMMUNITY_ENCODE_AS) {
+ as = (*p++ << 8);
+ as |= (*p++);
+ p +=
+ 2; /* skip next two, tag/vid
+ always in lowest bytes */
+ }
+ if (as == bgp->as) {
+ *tag_id = *p++ << 8;
+ *tag_id |= (*p++);
+ return 0;
+ }
+ }
+ }
+ }
+ return ENOENT;
}
-static int
-rfapiVpnBiNhEqualsPt (struct bgp_info *bi, struct rfapi_ip_addr *hpt)
+static int rfapiVpnBiNhEqualsPt(struct bgp_info *bi, struct rfapi_ip_addr *hpt)
{
- uint8_t family;
+ uint8_t family;
- if (!hpt || !bi)
- return 0;
+ if (!hpt || !bi)
+ return 0;
- family = BGP_MP_NEXTHOP_FAMILY (bi->attr->mp_nexthop_len);
+ family = BGP_MP_NEXTHOP_FAMILY(bi->attr->mp_nexthop_len);
- if (hpt->addr_family != family)
- return 0;
+ if (hpt->addr_family != family)
+ return 0;
- switch (family)
- {
- case AF_INET:
- if (bi->attr->mp_nexthop_global_in.s_addr != hpt->addr.v4.s_addr)
- return 0;
- break;
+ switch (family) {
+ case AF_INET:
+ if (bi->attr->mp_nexthop_global_in.s_addr
+ != hpt->addr.v4.s_addr)
+ return 0;
+ break;
- case AF_INET6:
- if (IPV6_ADDR_CMP (&bi->attr->mp_nexthop_global, &hpt->addr.v6))
- return 0;
- break;
+ case AF_INET6:
+ if (IPV6_ADDR_CMP(&bi->attr->mp_nexthop_global, &hpt->addr.v6))
+ return 0;
+ break;
- default:
- return 0;
- break;
- }
+ default:
+ return 0;
+ break;
+ }
- return 1;
+ return 1;
}
/*
* Compare 2 VPN BIs. Return true if they have the same VN and UN addresses
*/
-static int
-rfapiVpnBiSamePtUn (struct bgp_info *bi1, struct bgp_info *bi2)
+static int rfapiVpnBiSamePtUn(struct bgp_info *bi1, struct bgp_info *bi2)
{
- struct prefix pfx_un1;
- struct prefix pfx_un2;
-
- if (!bi1 || !bi2)
- return 0;
-
- if (!bi1->attr || !bi2->attr)
- return 0;
-
- /*
- * VN address comparisons
- */
-
- if (BGP_MP_NEXTHOP_FAMILY (bi1->attr->mp_nexthop_len) !=
- BGP_MP_NEXTHOP_FAMILY (bi2->attr->mp_nexthop_len))
- {
- return 0;
- }
-
- switch (BGP_MP_NEXTHOP_FAMILY (bi1->attr->mp_nexthop_len))
- {
- case AF_INET:
- if (bi1->attr->mp_nexthop_global_in.s_addr !=
- bi2->attr->mp_nexthop_global_in.s_addr)
- return 0;
- break;
-
- case AF_INET6:
- if (IPV6_ADDR_CMP (&bi1->attr->mp_nexthop_global,
- &bi2->attr->mp_nexthop_global))
- return 0;
- break;
-
- default:
- return 0;
- break;
- }
-
- /*
- * UN address comparisons
- */
- if (rfapiGetVncTunnelUnAddr (bi1->attr, &pfx_un1))
- {
- if (bi1->extra)
- {
- pfx_un1.family = bi1->extra->vnc.import.un_family;
- switch (bi1->extra->vnc.import.un_family)
- {
- case AF_INET:
- pfx_un1.u.prefix4 = bi1->extra->vnc.import.un.addr4;
- break;
- case AF_INET6:
- pfx_un1.u.prefix6 = bi1->extra->vnc.import.un.addr6;
- break;
- default:
- pfx_un1.family = 0;
- break;
- }
- }
- }
-
- if (rfapiGetVncTunnelUnAddr (bi2->attr, &pfx_un2))
- {
- if (bi2->extra)
- {
- pfx_un2.family = bi2->extra->vnc.import.un_family;
- switch (bi2->extra->vnc.import.un_family)
- {
- case AF_INET:
- pfx_un2.u.prefix4 = bi2->extra->vnc.import.un.addr4;
- break;
- case AF_INET6:
- pfx_un2.u.prefix6 = bi2->extra->vnc.import.un.addr6;
- break;
- default:
- pfx_un2.family = 0;
- break;
- }
- }
- }
-
- if (!pfx_un1.family || !pfx_un2.family)
- return 0;
-
- if (pfx_un1.family != pfx_un2.family)
- return 0;
-
- switch (pfx_un1.family)
- {
- case AF_INET:
- if (!IPV4_ADDR_SAME
- (&pfx_un1.u.prefix4.s_addr, &pfx_un2.u.prefix4.s_addr))
- return 0;
- break;
- case AF_INET6:
- if (!IPV6_ADDR_SAME (&pfx_un1.u.prefix6, &pfx_un2.u.prefix6))
- return 0;
- break;
- }
-
-
-
- return 1;
+ struct prefix pfx_un1;
+ struct prefix pfx_un2;
+
+ if (!bi1 || !bi2)
+ return 0;
+
+ if (!bi1->attr || !bi2->attr)
+ return 0;
+
+ /*
+ * VN address comparisons
+ */
+
+ if (BGP_MP_NEXTHOP_FAMILY(bi1->attr->mp_nexthop_len)
+ != BGP_MP_NEXTHOP_FAMILY(bi2->attr->mp_nexthop_len)) {
+ return 0;
+ }
+
+ switch (BGP_MP_NEXTHOP_FAMILY(bi1->attr->mp_nexthop_len)) {
+ case AF_INET:
+ if (bi1->attr->mp_nexthop_global_in.s_addr
+ != bi2->attr->mp_nexthop_global_in.s_addr)
+ return 0;
+ break;
+
+ case AF_INET6:
+ if (IPV6_ADDR_CMP(&bi1->attr->mp_nexthop_global,
+ &bi2->attr->mp_nexthop_global))
+ return 0;
+ break;
+
+ default:
+ return 0;
+ break;
+ }
+
+ /*
+ * UN address comparisons
+ */
+ if (rfapiGetVncTunnelUnAddr(bi1->attr, &pfx_un1)) {
+ if (bi1->extra) {
+ pfx_un1.family = bi1->extra->vnc.import.un_family;
+ switch (bi1->extra->vnc.import.un_family) {
+ case AF_INET:
+ pfx_un1.u.prefix4 =
+ bi1->extra->vnc.import.un.addr4;
+ break;
+ case AF_INET6:
+ pfx_un1.u.prefix6 =
+ bi1->extra->vnc.import.un.addr6;
+ break;
+ default:
+ pfx_un1.family = 0;
+ break;
+ }
+ }
+ }
+
+ if (rfapiGetVncTunnelUnAddr(bi2->attr, &pfx_un2)) {
+ if (bi2->extra) {
+ pfx_un2.family = bi2->extra->vnc.import.un_family;
+ switch (bi2->extra->vnc.import.un_family) {
+ case AF_INET:
+ pfx_un2.u.prefix4 =
+ bi2->extra->vnc.import.un.addr4;
+ break;
+ case AF_INET6:
+ pfx_un2.u.prefix6 =
+ bi2->extra->vnc.import.un.addr6;
+ break;
+ default:
+ pfx_un2.family = 0;
+ break;
+ }
+ }
+ }
+
+ if (!pfx_un1.family || !pfx_un2.family)
+ return 0;
+
+ if (pfx_un1.family != pfx_un2.family)
+ return 0;
+
+ switch (pfx_un1.family) {
+ case AF_INET:
+ if (!IPV4_ADDR_SAME(&pfx_un1.u.prefix4.s_addr,
+ &pfx_un2.u.prefix4.s_addr))
+ return 0;
+ break;
+ case AF_INET6:
+ if (!IPV6_ADDR_SAME(&pfx_un1.u.prefix6, &pfx_un2.u.prefix6))
+ return 0;
+ break;
+ }
+
+
+ return 1;
}
-uint8_t
-rfapiRfpCost (struct attr * attr)
+uint8_t rfapiRfpCost(struct attr *attr)
{
- if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
- {
- if (attr->local_pref > 255)
- {
- return 0;
- }
- return 255 - attr->local_pref;
- }
-
- return 255;
+ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
+ if (attr->local_pref > 255) {
+ return 0;
+ }
+ return 255 - attr->local_pref;
+ }
+
+ return 255;
}
/*------------------------------------------
* 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:
@@ -1352,404 +1266,384 @@ rfapiRfpCost (struct attr * attr)
* 1 no options found
*
--------------------------------------------*/
-int
-rfapi_extract_l2o (struct bgp_tea_options *pHop, /* chain of options */
- struct rfapi_l2address_option *l2o) /* return extracted value */
+int rfapi_extract_l2o(
+ struct bgp_tea_options *pHop, /* chain of options */
+ struct rfapi_l2address_option *l2o) /* return extracted value */
{
- struct bgp_tea_options *p;
+ struct bgp_tea_options *p;
- for (p = pHop; p; p = p->next)
- {
- if ((p->type == RFAPI_VN_OPTION_TYPE_L2ADDR) && (p->length >= 8))
- {
+ for (p = pHop; p; p = p->next) {
+ if ((p->type == RFAPI_VN_OPTION_TYPE_L2ADDR)
+ && (p->length >= 8)) {
- char *v = p->value;
+ char *v = p->value;
- memcpy (&l2o->macaddr, v, 6);
+ memcpy(&l2o->macaddr, v, 6);
- l2o->label =
- ((v[6] << 12) & 0xff000) +
- ((v[7] << 4) & 0xff0) + ((v[8] >> 4) & 0xf);
+ l2o->label = ((v[6] << 12) & 0xff000)
+ + ((v[7] << 4) & 0xff0)
+ + ((v[8] >> 4) & 0xf);
- l2o->local_nve_id = (uint8_t) v[10];
+ l2o->local_nve_id = (uint8_t)v[10];
- l2o->logical_net_id = (v[11] << 16) + (v[12] << 8) + (v[13] << 0);
+ l2o->logical_net_id =
+ (v[11] << 16) + (v[12] << 8) + (v[13] << 0);
- return 0;
- }
- }
- return 1;
+ return 0;
+ }
+ }
+ return 1;
}
static struct rfapi_next_hop_entry *
-rfapiRouteInfo2NextHopEntry (
- struct rfapi_ip_prefix *rprefix,
- struct bgp_info *bi, /* route to encode */
- uint32_t lifetime, /* use this in nhe */
- struct route_node *rn) /* req for L2 eth addr */
+rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix,
+ struct bgp_info *bi, /* route to encode */
+ uint32_t lifetime, /* use this in nhe */
+ struct route_node *rn) /* req for L2 eth addr */
{
- struct rfapi_next_hop_entry *new;
- int have_vnc_tunnel_un = 0;
+ struct rfapi_next_hop_entry *new;
+ int have_vnc_tunnel_un = 0;
#if DEBUG_ENCAP_MONITOR
- vnc_zlog_debug_verbose ("%s: entry, bi %p, rn %p", __func__, bi, rn);
+ vnc_zlog_debug_verbose("%s: entry, bi %p, rn %p", __func__, bi, rn);
#endif
- new = XCALLOC (MTYPE_RFAPI_NEXTHOP, sizeof (struct rfapi_next_hop_entry));
- assert (new);
-
- new->prefix = *rprefix;
-
- if (bi->extra &&
- decode_rd_type(bi->extra->vnc.import.rd.val) == RD_TYPE_VNC_ETH)
- {
- /* ethernet */
-
- struct rfapi_vn_option *vo;
-
- vo = XCALLOC (MTYPE_RFAPI_VN_OPTION, sizeof (struct rfapi_vn_option));
- assert (vo);
-
- vo->type = RFAPI_VN_OPTION_TYPE_L2ADDR;
-
- memcpy (&vo->v.l2addr.macaddr, &rn->p.u.prefix_eth.octet,
- ETHER_ADDR_LEN);
- /* only low 3 bytes of this are significant */
- if (bi->attr)
- {
- (void) rfapiEcommunityGetLNI (bi->attr->ecommunity,
- &vo->v.l2addr.logical_net_id);
- (void) rfapiEcommunityGetEthernetTag (bi->attr->ecommunity,
- &vo->v.l2addr.tag_id);
- }
-
- /* local_nve_id comes from lower byte of RD type */
- vo->v.l2addr.local_nve_id = bi->extra->vnc.import.rd.val[1];
-
- /* label comes from MP_REACH_NLRI label */
- vo->v.l2addr.label = decode_label (&bi->extra->label);
-
- new->vn_options = vo;
-
- /*
- * If there is an auxiliary prefix (i.e., host IP address),
- * use it as the nexthop prefix instead of the query prefix
- */
- if (bi->extra->vnc.import.aux_prefix.family)
- {
- rfapiQprefix2Rprefix (&bi->extra->vnc.import.aux_prefix,
- &new->prefix);
- }
- }
-
- if (bi->attr)
- {
- bgp_encap_types tun_type;
- new->prefix.cost = rfapiRfpCost (bi->attr);
-
- struct bgp_attr_encap_subtlv *pEncap;
-
- switch (BGP_MP_NEXTHOP_FAMILY (bi->attr->mp_nexthop_len))
- {
- case AF_INET:
- new->vn_address.addr_family = AF_INET;
- new->vn_address.addr.v4 = bi->attr->mp_nexthop_global_in;
- break;
-
- case AF_INET6:
- new->vn_address.addr_family = AF_INET6;
- new->vn_address.addr.v6 = bi->attr->mp_nexthop_global;
- break;
-
- default:
- zlog_warn ("%s: invalid vpn nexthop length: %d",
- __func__, bi->attr->mp_nexthop_len);
- rfapi_free_next_hop_list (new);
- return NULL;
- }
-
- for (pEncap = bi->attr->vnc_subtlvs; pEncap;
- pEncap = pEncap->next)
- {
- switch (pEncap->type)
- {
- case BGP_VNC_SUBTLV_TYPE_LIFETIME:
- /* use configured lifetime, not attr lifetime */
- break;
-
- default:
- zlog_warn ("%s: unknown VNC option type %d",
- __func__, pEncap->type);
-
-
- break;
- }
- }
-
- rfapiGetTunnelType (bi->attr, &tun_type);
- if (tun_type == BGP_ENCAP_TYPE_MPLS)
- {
- struct prefix p;
- /* MPLS carries UN address in next hop */
- rfapiNexthop2Prefix (bi->attr, &p);
- if (p.family != 0)
- {
- rfapiQprefix2Raddr(&p, &new->un_address);
- have_vnc_tunnel_un = 1;
- }
- }
-
- for (pEncap = bi->attr->encap_subtlvs; pEncap;
- pEncap = pEncap->next)
- {
- switch (pEncap->type)
- {
- case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
- /*
- * Overrides ENCAP UN address, if any
- */
- switch (pEncap->length)
- {
-
- case 8:
- new->un_address.addr_family = AF_INET;
- memcpy (&new->un_address.addr.v4, pEncap->value, 4);
- have_vnc_tunnel_un = 1;
- break;
-
- case 20:
- new->un_address.addr_family = AF_INET6;
- memcpy (&new->un_address.addr.v6, pEncap->value, 16);
- have_vnc_tunnel_un = 1;
- break;
-
- default:
- zlog_warn
- ("%s: invalid tunnel subtlv UN addr length (%d) for bi %p",
- __func__, pEncap->length, bi);
- }
- break;
-
- default:
- zlog_warn ("%s: unknown Encap Attribute option type %d",
- __func__, pEncap->type);
-
-
- break;
- }
- }
-
- new->un_options = rfapi_encap_tlv_to_un_option (bi->attr);
+ new = XCALLOC(MTYPE_RFAPI_NEXTHOP, sizeof(struct rfapi_next_hop_entry));
+ assert(new);
+
+ new->prefix = *rprefix;
+
+ if (bi->extra
+ && decode_rd_type(bi->extra->vnc.import.rd.val)
+ == RD_TYPE_VNC_ETH) {
+ /* ethernet */
+
+ struct rfapi_vn_option *vo;
+
+ vo = XCALLOC(MTYPE_RFAPI_VN_OPTION,
+ sizeof(struct rfapi_vn_option));
+ assert(vo);
+
+ vo->type = RFAPI_VN_OPTION_TYPE_L2ADDR;
+
+ memcpy(&vo->v.l2addr.macaddr, &rn->p.u.prefix_eth.octet,
+ ETHER_ADDR_LEN);
+ /* only low 3 bytes of this are significant */
+ if (bi->attr) {
+ (void)rfapiEcommunityGetLNI(
+ bi->attr->ecommunity,
+ &vo->v.l2addr.logical_net_id);
+ (void)rfapiEcommunityGetEthernetTag(
+ bi->attr->ecommunity, &vo->v.l2addr.tag_id);
+ }
+
+ /* local_nve_id comes from lower byte of RD type */
+ vo->v.l2addr.local_nve_id = bi->extra->vnc.import.rd.val[1];
+
+ /* label comes from MP_REACH_NLRI label */
+ vo->v.l2addr.label = decode_label(&bi->extra->label);
+
+ new->vn_options = vo;
+
+ /*
+ * If there is an auxiliary prefix (i.e., host IP address),
+ * use it as the nexthop prefix instead of the query prefix
+ */
+ if (bi->extra->vnc.import.aux_prefix.family) {
+ rfapiQprefix2Rprefix(&bi->extra->vnc.import.aux_prefix,
+ &new->prefix);
+ }
+ }
+
+ if (bi->attr) {
+ bgp_encap_types tun_type;
+ new->prefix.cost = rfapiRfpCost(bi->attr);
+
+ struct bgp_attr_encap_subtlv *pEncap;
+
+ switch (BGP_MP_NEXTHOP_FAMILY(bi->attr->mp_nexthop_len)) {
+ case AF_INET:
+ new->vn_address.addr_family = AF_INET;
+ new->vn_address.addr.v4 =
+ bi->attr->mp_nexthop_global_in;
+ break;
+
+ case AF_INET6:
+ new->vn_address.addr_family = AF_INET6;
+ new->vn_address.addr.v6 = bi->attr->mp_nexthop_global;
+ break;
+
+ default:
+ zlog_warn("%s: invalid vpn nexthop length: %d",
+ __func__, bi->attr->mp_nexthop_len);
+ rfapi_free_next_hop_list(new);
+ return NULL;
+ }
+
+ for (pEncap = bi->attr->vnc_subtlvs; pEncap;
+ pEncap = pEncap->next) {
+ switch (pEncap->type) {
+ case BGP_VNC_SUBTLV_TYPE_LIFETIME:
+ /* use configured lifetime, not attr lifetime */
+ break;
+
+ default:
+ zlog_warn("%s: unknown VNC option type %d",
+ __func__, pEncap->type);
+
+
+ break;
+ }
+ }
+
+ rfapiGetTunnelType(bi->attr, &tun_type);
+ if (tun_type == BGP_ENCAP_TYPE_MPLS) {
+ struct prefix p;
+ /* MPLS carries UN address in next hop */
+ rfapiNexthop2Prefix(bi->attr, &p);
+ if (p.family != 0) {
+ rfapiQprefix2Raddr(&p, &new->un_address);
+ have_vnc_tunnel_un = 1;
+ }
+ }
+
+ for (pEncap = bi->attr->encap_subtlvs; pEncap;
+ pEncap = pEncap->next) {
+ switch (pEncap->type) {
+ case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
+ /*
+ * Overrides ENCAP UN address, if any
+ */
+ switch (pEncap->length) {
+
+ case 8:
+ new->un_address.addr_family = AF_INET;
+ memcpy(&new->un_address.addr.v4,
+ pEncap->value, 4);
+ have_vnc_tunnel_un = 1;
+ break;
+
+ case 20:
+ new->un_address.addr_family = AF_INET6;
+ memcpy(&new->un_address.addr.v6,
+ pEncap->value, 16);
+ have_vnc_tunnel_un = 1;
+ break;
+
+ default:
+ zlog_warn(
+ "%s: invalid tunnel subtlv UN addr length (%d) for bi %p",
+ __func__, pEncap->length, bi);
+ }
+ break;
+
+ default:
+ zlog_warn(
+ "%s: unknown Encap Attribute option type %d",
+ __func__, pEncap->type);
+
+
+ break;
+ }
+ }
+
+ new->un_options = rfapi_encap_tlv_to_un_option(bi->attr);
#if DEBUG_ENCAP_MONITOR
- vnc_zlog_debug_verbose ("%s: line %d: have_vnc_tunnel_un=%d",
- __func__, __LINE__, have_vnc_tunnel_un);
+ vnc_zlog_debug_verbose("%s: line %d: have_vnc_tunnel_un=%d",
+ __func__, __LINE__, have_vnc_tunnel_un);
#endif
- if (!have_vnc_tunnel_un && bi && bi->extra)
- {
- /*
- * use cached UN address from ENCAP route
- */
- new->un_address.addr_family = bi->extra->vnc.import.un_family;
- switch (new->un_address.addr_family)
- {
- case AF_INET:
- new->un_address.addr.v4 = bi->extra->vnc.import.un.addr4;
- break;
- case AF_INET6:
- new->un_address.addr.v6 = bi->extra->vnc.import.un.addr6;
- break;
- default:
- zlog_warn ("%s: invalid UN addr family (%d) for bi %p",
- __func__, new->un_address.addr_family, bi);
- rfapi_free_next_hop_list (new);
- return NULL;
- break;
- }
- }
- }
-
- new->lifetime = lifetime;
- return new;
+ if (!have_vnc_tunnel_un && bi && bi->extra) {
+ /*
+ * use cached UN address from ENCAP route
+ */
+ new->un_address.addr_family =
+ bi->extra->vnc.import.un_family;
+ switch (new->un_address.addr_family) {
+ case AF_INET:
+ new->un_address.addr.v4 =
+ bi->extra->vnc.import.un.addr4;
+ break;
+ case AF_INET6:
+ new->un_address.addr.v6 =
+ bi->extra->vnc.import.un.addr6;
+ break;
+ default:
+ zlog_warn(
+ "%s: invalid UN addr family (%d) for bi %p",
+ __func__, new->un_address.addr_family,
+ bi);
+ rfapi_free_next_hop_list(new);
+ return NULL;
+ break;
+ }
+ }
+ }
+
+ new->lifetime = lifetime;
+ return new;
}
-int
-rfapiHasNonRemovedRoutes (struct route_node *rn)
+int rfapiHasNonRemovedRoutes(struct route_node *rn)
{
- struct bgp_info *bi;
+ struct bgp_info *bi;
- for (bi = rn->info; bi; bi = bi->next)
- {
- struct prefix pfx;
+ for (bi = rn->info; bi; bi = bi->next) {
+ struct prefix pfx;
- if (!CHECK_FLAG (bi->flags, BGP_INFO_REMOVED) &&
- (bi->extra && !rfapiGetUnAddrOfVpnBi (bi, &pfx)))
- {
+ if (!CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)
+ && (bi->extra && !rfapiGetUnAddrOfVpnBi(bi, &pfx))) {
- return 1;
- }
- }
- return 0;
+ return 1;
+ }
+ }
+ return 0;
}
#if DEBUG_IT_NODES
-/*
+/*
* DEBUG FUNCTION
*/
-void
-rfapiDumpNode (struct route_node *rn)
+void rfapiDumpNode(struct route_node *rn)
{
- struct bgp_info *bi;
-
- vnc_zlog_debug_verbose ("%s: rn=%p", __func__, rn);
- for (bi = rn->info; bi; bi = bi->next)
- {
- struct prefix pfx;
- int ctrc = rfapiGetUnAddrOfVpnBi (bi, &pfx);
- int nr;
-
- if (!CHECK_FLAG (bi->flags, BGP_INFO_REMOVED) && (bi->extra && !ctrc))
- {
-
- nr = 1;
- }
- else
- {
- nr = 0;
- }
-
- vnc_zlog_debug_verbose (" bi=%p, nr=%d, flags=0x%x, extra=%p, ctrc=%d",
- bi, nr, bi->flags, bi->extra, ctrc);
- }
+ struct bgp_info *bi;
+
+ vnc_zlog_debug_verbose("%s: rn=%p", __func__, rn);
+ for (bi = rn->info; bi; bi = bi->next) {
+ struct prefix pfx;
+ int ctrc = rfapiGetUnAddrOfVpnBi(bi, &pfx);
+ int nr;
+
+ if (!CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)
+ && (bi->extra && !ctrc)) {
+
+ nr = 1;
+ } else {
+ nr = 0;
+ }
+
+ vnc_zlog_debug_verbose(
+ " bi=%p, nr=%d, flags=0x%x, extra=%p, ctrc=%d", bi, nr,
+ bi->flags, bi->extra, ctrc);
+ }
}
#endif
-static int
-rfapiNhlAddNodeRoutes (
- struct route_node *rn, /* in */
- struct rfapi_ip_prefix *rprefix, /* in */
- uint32_t lifetime, /* in */
- int removed, /* in */
- struct rfapi_next_hop_entry **head, /* in/out */
- struct rfapi_next_hop_entry **tail, /* in/out */
- struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */
- struct route_node *rfd_rib_node,/* preload this NVE rib node */
- struct prefix *pfx_target_original) /* query target */
+static int rfapiNhlAddNodeRoutes(
+ struct route_node *rn, /* in */
+ struct rfapi_ip_prefix *rprefix, /* in */
+ uint32_t lifetime, /* in */
+ int removed, /* in */
+ struct rfapi_next_hop_entry **head, /* in/out */
+ struct rfapi_next_hop_entry **tail, /* in/out */
+ struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */
+ struct route_node *rfd_rib_node, /* preload this NVE rib node */
+ struct prefix *pfx_target_original) /* query target */
{
- struct bgp_info *bi;
- struct rfapi_next_hop_entry *new;
- struct prefix pfx_un;
- struct skiplist *seen_nexthops;
- int count = 0;
- int is_l2 = (rn->p.family == AF_ETHERNET);
-
- if (rfapiRibFTDFilterRecentPrefix(
- (struct rfapi_descriptor *)(rfd_rib_node->table->info), rn,
- pfx_target_original))
- {
- return 0;
- }
-
- seen_nexthops =
- skiplist_new (0, vnc_prefix_cmp, (void (*)(void *)) prefix_free);
-
- for (bi = rn->info; bi; bi = bi->next)
- {
-
- struct prefix pfx_vn;
- struct prefix *newpfx;
-
- if (removed && !CHECK_FLAG (bi->flags, BGP_INFO_REMOVED))
- {
+ struct bgp_info *bi;
+ struct rfapi_next_hop_entry *new;
+ struct prefix pfx_un;
+ struct skiplist *seen_nexthops;
+ int count = 0;
+ int is_l2 = (rn->p.family == AF_ETHERNET);
+
+ if (rfapiRibFTDFilterRecentPrefix(
+ (struct rfapi_descriptor *)(rfd_rib_node->table->info), rn,
+ pfx_target_original)) {
+ return 0;
+ }
+
+ seen_nexthops =
+ skiplist_new(0, vnc_prefix_cmp, (void (*)(void *))prefix_free);
+
+ for (bi = rn->info; bi; bi = bi->next) {
+
+ struct prefix pfx_vn;
+ struct prefix *newpfx;
+
+ if (removed && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) {
#if DEBUG_RETURNED_NHL
- vnc_zlog_debug_verbose ("%s: want holddown, this route not holddown, skip",
- __func__);
+ vnc_zlog_debug_verbose(
+ "%s: want holddown, this route not holddown, skip",
+ __func__);
#endif
- continue;
- }
- if (!removed && CHECK_FLAG (bi->flags, BGP_INFO_REMOVED))
- {
- continue;
- }
-
- if (!bi->extra)
- {
- continue;
- }
-
- /*
- * Check for excluded VN address
- */
- if (rfapiVpnBiNhEqualsPt (bi, exclude_vnaddr))
- continue;
-
- /*
- * Check for VN address (nexthop) copied already
- */
- if (is_l2)
- {
- /* L2 routes: semantic nexthop in aux_prefix; VN addr ain't it */
- pfx_vn = bi->extra->vnc.import.aux_prefix;
- }
- else
- {
- rfapiNexthop2Prefix (bi->attr, &pfx_vn);
- }
- if (!skiplist_search (seen_nexthops, &pfx_vn, NULL))
- {
+ continue;
+ }
+ if (!removed && CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) {
+ continue;
+ }
+
+ if (!bi->extra) {
+ continue;
+ }
+
+ /*
+ * Check for excluded VN address
+ */
+ if (rfapiVpnBiNhEqualsPt(bi, exclude_vnaddr))
+ continue;
+
+ /*
+ * Check for VN address (nexthop) copied already
+ */
+ if (is_l2) {
+ /* L2 routes: semantic nexthop in aux_prefix; VN addr
+ * ain't it */
+ pfx_vn = bi->extra->vnc.import.aux_prefix;
+ } else {
+ rfapiNexthop2Prefix(bi->attr, &pfx_vn);
+ }
+ if (!skiplist_search(seen_nexthops, &pfx_vn, NULL)) {
#if DEBUG_RETURNED_NHL
- char buf[BUFSIZ];
+ char buf[BUFSIZ];
- prefix2str (&pfx_vn, buf, BUFSIZ);
- buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */
- vnc_zlog_debug_verbose ("%s: already put VN/nexthop %s, skip", __func__, buf);
+ prefix2str(&pfx_vn, buf, BUFSIZ);
+ buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */
+ vnc_zlog_debug_verbose(
+ "%s: already put VN/nexthop %s, skip", __func__,
+ buf);
#endif
- continue;
- }
+ continue;
+ }
- if (rfapiGetUnAddrOfVpnBi (bi, &pfx_un))
- {
+ if (rfapiGetUnAddrOfVpnBi(bi, &pfx_un)) {
#if DEBUG_ENCAP_MONITOR
- vnc_zlog_debug_verbose ("%s: failed to get UN address of this VPN bi",
- __func__);
+ vnc_zlog_debug_verbose(
+ "%s: failed to get UN address of this VPN bi",
+ __func__);
#endif
- continue;
- }
-
- newpfx = prefix_new ();
- *newpfx = pfx_vn;
- skiplist_insert (seen_nexthops, newpfx, newpfx);
-
- new = rfapiRouteInfo2NextHopEntry(rprefix, bi, lifetime, rn);
- if (new)
- {
- if (rfapiRibPreloadBi(rfd_rib_node, &pfx_vn, &pfx_un, lifetime, bi))
- {
- /* duplicate filtered by RIB */
- rfapi_free_next_hop_list (new);
- new = NULL;
- }
- }
-
- if (new)
- {
- if (*tail)
- {
- (*tail)->next = new;
- }
- else
- {
- *head = new;
- }
- *tail = new;
- ++count;
- }
- }
-
- skiplist_free (seen_nexthops);
-
- return count;
+ continue;
+ }
+
+ newpfx = prefix_new();
+ *newpfx = pfx_vn;
+ skiplist_insert(seen_nexthops, newpfx, newpfx);
+
+ new = rfapiRouteInfo2NextHopEntry(rprefix, bi, lifetime, rn);
+ if (new) {
+ if (rfapiRibPreloadBi(rfd_rib_node, &pfx_vn, &pfx_un,
+ lifetime, bi)) {
+ /* duplicate filtered by RIB */
+ rfapi_free_next_hop_list(new);
+ new = NULL;
+ }
+ }
+
+ if (new) {
+ if (*tail) {
+ (*tail)->next = new;
+ } else {
+ *head = new;
+ }
+ *tail = new;
+ ++count;
+ }
+ }
+
+ skiplist_free(seen_nexthops);
+
+ return count;
}
@@ -1762,85 +1656,84 @@ rfapiNhlAddNodeRoutes (
* its routes in the list, so we skip it if the right or left node
* matches (of course, we still travel down its child subtrees).
*/
-static int
-rfapiNhlAddSubtree (
- struct route_node *rn, /* in */
- uint32_t lifetime, /* in */
- struct rfapi_next_hop_entry **head, /* in/out */
- struct rfapi_next_hop_entry **tail, /* in/out */
- struct route_node *omit_node, /* in */
- struct rfapi_ip_addr *exclude_vnaddr,/* omit routes to same NVE */
- struct route_table *rfd_rib_table,/* preload here */
- struct prefix *pfx_target_original) /* query target */
+static int rfapiNhlAddSubtree(
+ struct route_node *rn, /* in */
+ uint32_t lifetime, /* in */
+ struct rfapi_next_hop_entry **head, /* in/out */
+ struct rfapi_next_hop_entry **tail, /* in/out */
+ struct route_node *omit_node, /* in */
+ struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */
+ struct route_table *rfd_rib_table, /* preload here */
+ struct prefix *pfx_target_original) /* query target */
{
- struct rfapi_ip_prefix rprefix;
- int rcount = 0;
-
- /* FIXME: need to find a better way here to work without sticking our
- * hands in node->link */
- if (rn->l_left && rn->l_left != omit_node)
- {
- if (rn->l_left->info)
- {
- int count = 0;
- struct route_node *rib_rn = NULL;
-
- rfapiQprefix2Rprefix (&rn->l_left->p, &rprefix);
- if (rfd_rib_table)
- {
- rib_rn = route_node_get(rfd_rib_table, &rn->l_left->p);
- }
-
- count = rfapiNhlAddNodeRoutes (rn->l_left, &rprefix, lifetime, 0,
- head, tail, exclude_vnaddr, rib_rn, pfx_target_original);
- if (!count)
- {
- count = rfapiNhlAddNodeRoutes (rn->l_left, &rprefix, lifetime, 1,
- head, tail, exclude_vnaddr, rib_rn, pfx_target_original);
- }
- rcount += count;
- if (rib_rn)
- route_unlock_node(rib_rn);
- }
- }
-
- if (rn->l_right && rn->l_right != omit_node)
- {
- if (rn->l_right->info)
- {
- int count = 0;
- struct route_node *rib_rn = NULL;
-
- rfapiQprefix2Rprefix (&rn->l_right->p, &rprefix);
- if (rfd_rib_table)
- {
- rib_rn = route_node_get(rfd_rib_table, &rn->l_right->p);
- }
- count = rfapiNhlAddNodeRoutes (rn->l_right, &rprefix, lifetime, 0,
- head, tail, exclude_vnaddr, rib_rn, pfx_target_original);
- if (!count)
- {
- count = rfapiNhlAddNodeRoutes (rn->l_right, &rprefix, lifetime, 1,
- head, tail, exclude_vnaddr, rib_rn, pfx_target_original);
- }
- rcount += count;
- if (rib_rn)
- route_unlock_node(rib_rn);
- }
- }
-
- if (rn->l_left)
- {
- rcount += rfapiNhlAddSubtree (rn->l_left, lifetime, head, tail, omit_node,
- exclude_vnaddr, rfd_rib_table, pfx_target_original);
- }
- if (rn->l_right)
- {
- rcount += rfapiNhlAddSubtree (rn->l_right, lifetime, head, tail,
- omit_node, exclude_vnaddr, rfd_rib_table, pfx_target_original);
- }
-
- return rcount;
+ struct rfapi_ip_prefix rprefix;
+ int rcount = 0;
+
+ /* FIXME: need to find a better way here to work without sticking our
+ * hands in node->link */
+ if (rn->l_left && rn->l_left != omit_node) {
+ if (rn->l_left->info) {
+ int count = 0;
+ struct route_node *rib_rn = NULL;
+
+ rfapiQprefix2Rprefix(&rn->l_left->p, &rprefix);
+ if (rfd_rib_table) {
+ rib_rn = route_node_get(rfd_rib_table,
+ &rn->l_left->p);
+ }
+
+ count = rfapiNhlAddNodeRoutes(
+ rn->l_left, &rprefix, lifetime, 0, head, tail,
+ exclude_vnaddr, rib_rn, pfx_target_original);
+ if (!count) {
+ count = rfapiNhlAddNodeRoutes(
+ rn->l_left, &rprefix, lifetime, 1, head,
+ tail, exclude_vnaddr, rib_rn,
+ pfx_target_original);
+ }
+ rcount += count;
+ if (rib_rn)
+ route_unlock_node(rib_rn);
+ }
+ }
+
+ if (rn->l_right && rn->l_right != omit_node) {
+ if (rn->l_right->info) {
+ int count = 0;
+ struct route_node *rib_rn = NULL;
+
+ rfapiQprefix2Rprefix(&rn->l_right->p, &rprefix);
+ if (rfd_rib_table) {
+ rib_rn = route_node_get(rfd_rib_table,
+ &rn->l_right->p);
+ }
+ count = rfapiNhlAddNodeRoutes(
+ rn->l_right, &rprefix, lifetime, 0, head, tail,
+ exclude_vnaddr, rib_rn, pfx_target_original);
+ if (!count) {
+ count = rfapiNhlAddNodeRoutes(
+ rn->l_right, &rprefix, lifetime, 1,
+ head, tail, exclude_vnaddr, rib_rn,
+ pfx_target_original);
+ }
+ rcount += count;
+ if (rib_rn)
+ route_unlock_node(rib_rn);
+ }
+ }
+
+ if (rn->l_left) {
+ rcount += rfapiNhlAddSubtree(
+ rn->l_left, lifetime, head, tail, omit_node,
+ exclude_vnaddr, rfd_rib_table, pfx_target_original);
+ }
+ if (rn->l_right) {
+ rcount += rfapiNhlAddSubtree(
+ rn->l_right, lifetime, head, tail, omit_node,
+ exclude_vnaddr, rfd_rib_table, pfx_target_original);
+ }
+
+ return rcount;
}
/*
@@ -1854,343 +1747,326 @@ rfapiNhlAddSubtree (
* 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.
*/
-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 here */
- struct prefix *pfx_target_original) /* query target */
+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 here */
+ struct prefix *pfx_target_original) /* query target */
{
- struct rfapi_ip_prefix rprefix;
- struct rfapi_next_hop_entry *answer = NULL;
- struct rfapi_next_hop_entry *last = NULL;
- struct route_node *parent;
- int count = 0;
- struct route_node *rib_rn;
+ struct rfapi_ip_prefix rprefix;
+ struct rfapi_next_hop_entry *answer = NULL;
+ struct rfapi_next_hop_entry *last = NULL;
+ struct route_node *parent;
+ int count = 0;
+ struct route_node *rib_rn;
#if DEBUG_RETURNED_NHL
- {
- char buf[BUFSIZ];
-
- prefix2str (&rn->p, buf, BUFSIZ);
- buf[BUFSIZ - 1] = 0;
- vnc_zlog_debug_verbose ("%s: called with node pfx=%s", __func__, buf);
- }
- rfapiDebugBacktrace ();
+ {
+ char buf[BUFSIZ];
+
+ prefix2str(&rn->p, buf, BUFSIZ);
+ buf[BUFSIZ - 1] = 0;
+ vnc_zlog_debug_verbose("%s: called with node pfx=%s", __func__,
+ buf);
+ }
+ rfapiDebugBacktrace();
#endif
- rfapiQprefix2Rprefix (&rn->p, &rprefix);
-
- rib_rn = rfd_rib_table? route_node_get(rfd_rib_table, &rn->p): NULL;
-
- /*
- * Add non-withdrawn routes at this node
- */
- count = rfapiNhlAddNodeRoutes (rn, &rprefix, lifetime, 0, &answer, &last,
- exclude_vnaddr, rib_rn, pfx_target_original);
-
- /*
- * If the list has at least one entry, it's finished
- */
- if (count)
- {
- count += rfapiNhlAddSubtree (rn, lifetime, &answer, &last, NULL,
- exclude_vnaddr, rfd_rib_table, pfx_target_original);
- vnc_zlog_debug_verbose ("%s: %d nexthops, answer=%p", __func__, count, answer);
+ rfapiQprefix2Rprefix(&rn->p, &rprefix);
+
+ rib_rn = rfd_rib_table ? route_node_get(rfd_rib_table, &rn->p) : NULL;
+
+ /*
+ * Add non-withdrawn routes at this node
+ */
+ count = rfapiNhlAddNodeRoutes(rn, &rprefix, lifetime, 0, &answer, &last,
+ exclude_vnaddr, rib_rn,
+ pfx_target_original);
+
+ /*
+ * If the list has at least one entry, it's finished
+ */
+ if (count) {
+ count += rfapiNhlAddSubtree(rn, lifetime, &answer, &last, NULL,
+ exclude_vnaddr, rfd_rib_table,
+ pfx_target_original);
+ vnc_zlog_debug_verbose("%s: %d nexthops, answer=%p", __func__,
+ count, answer);
#if DEBUG_RETURNED_NHL
- rfapiPrintNhl (NULL, answer);
+ rfapiPrintNhl(NULL, answer);
#endif
- if (rib_rn)
- route_unlock_node(rib_rn);
- return answer;
- }
-
- /*
- * Add withdrawn routes at this node
- */
- count = rfapiNhlAddNodeRoutes (rn, &rprefix, lifetime, 1, &answer, &last,
- exclude_vnaddr, rib_rn, pfx_target_original);
- if (rib_rn)
- route_unlock_node(rib_rn);
-
- // rfapiPrintNhl(NULL, answer);
-
- /*
- * walk up the tree until we find a node with non-deleted
- * routes, then add them
- */
- for (parent = rn->parent; parent; parent = parent->parent)
- {
- if (rfapiHasNonRemovedRoutes (parent))
- {
- break;
- }
- }
-
- /*
- * Add non-withdrawn routes from less-specific prefix
- */
- if (parent)
- {
- rib_rn = rfd_rib_table? route_node_get(rfd_rib_table, &parent->p): NULL;
- rfapiQprefix2Rprefix (&parent->p, &rprefix);
- count += rfapiNhlAddNodeRoutes (parent, &rprefix, lifetime, 0,
- &answer, &last, exclude_vnaddr, rib_rn, pfx_target_original);
- count += rfapiNhlAddSubtree (parent, lifetime, &answer, &last, rn,
- exclude_vnaddr, rfd_rib_table, pfx_target_original);
- if (rib_rn)
- route_unlock_node(rib_rn);
- }
- else
- {
- /*
- * There is no parent with non-removed routes. Still need to
- * add subtree of original node if it contributed routes to the
- * answer.
- */
- if (count)
- count += rfapiNhlAddSubtree (rn, lifetime, &answer, &last, rn,
- exclude_vnaddr, rfd_rib_table, pfx_target_original);
- }
-
- vnc_zlog_debug_verbose ("%s: %d nexthops, answer=%p", __func__, count, answer);
+ if (rib_rn)
+ route_unlock_node(rib_rn);
+ return answer;
+ }
+
+ /*
+ * Add withdrawn routes at this node
+ */
+ count = rfapiNhlAddNodeRoutes(rn, &rprefix, lifetime, 1, &answer, &last,
+ exclude_vnaddr, rib_rn,
+ pfx_target_original);
+ if (rib_rn)
+ route_unlock_node(rib_rn);
+
+ // rfapiPrintNhl(NULL, answer);
+
+ /*
+ * walk up the tree until we find a node with non-deleted
+ * routes, then add them
+ */
+ for (parent = rn->parent; parent; parent = parent->parent) {
+ if (rfapiHasNonRemovedRoutes(parent)) {
+ break;
+ }
+ }
+
+ /*
+ * Add non-withdrawn routes from less-specific prefix
+ */
+ if (parent) {
+ rib_rn = rfd_rib_table
+ ? route_node_get(rfd_rib_table, &parent->p)
+ : NULL;
+ rfapiQprefix2Rprefix(&parent->p, &rprefix);
+ count += rfapiNhlAddNodeRoutes(parent, &rprefix, lifetime, 0,
+ &answer, &last, exclude_vnaddr,
+ rib_rn, pfx_target_original);
+ count += rfapiNhlAddSubtree(parent, lifetime, &answer, &last,
+ rn, exclude_vnaddr, rfd_rib_table,
+ pfx_target_original);
+ if (rib_rn)
+ route_unlock_node(rib_rn);
+ } else {
+ /*
+ * There is no parent with non-removed routes. Still need to
+ * add subtree of original node if it contributed routes to the
+ * answer.
+ */
+ if (count)
+ count += rfapiNhlAddSubtree(rn, lifetime, &answer,
+ &last, rn, exclude_vnaddr,
+ rfd_rib_table,
+ pfx_target_original);
+ }
+
+ vnc_zlog_debug_verbose("%s: %d nexthops, answer=%p", __func__, count,
+ answer);
#if DEBUG_RETURNED_NHL
- rfapiPrintNhl (NULL, answer);
+ rfapiPrintNhl(NULL, answer);
#endif
- return answer;
+ return answer;
}
/*
* Construct nexthop list of all routes in table
*/
-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 */
+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 */
{
- struct route_node *rn;
- struct rfapi_next_hop_entry *biglist = NULL;
- struct rfapi_next_hop_entry *nhl;
- struct rfapi_next_hop_entry *tail = NULL;
- int count = 0;
-
- for (rn = route_top (rt); rn; rn = route_next (rn))
- {
-
- nhl = rfapiRouteNode2NextHopList (rn, lifetime, exclude_vnaddr,
- rfd_rib_table, pfx_target_original);
- if (!tail)
- {
- tail = biglist = nhl;
- if (tail)
- count = 1;
- }
- else
- {
- tail->next = nhl;
- }
- if (tail)
- {
- while (tail->next)
- {
- ++count;
- tail = tail->next;
- }
- }
- }
-
- vnc_zlog_debug_verbose ("%s: returning %d routes", __func__, count);
- return biglist;
+ struct route_node *rn;
+ struct rfapi_next_hop_entry *biglist = NULL;
+ struct rfapi_next_hop_entry *nhl;
+ struct rfapi_next_hop_entry *tail = NULL;
+ int count = 0;
+
+ for (rn = route_top(rt); rn; rn = route_next(rn)) {
+
+ nhl = rfapiRouteNode2NextHopList(rn, lifetime, exclude_vnaddr,
+ rfd_rib_table,
+ pfx_target_original);
+ if (!tail) {
+ tail = biglist = nhl;
+ if (tail)
+ count = 1;
+ } else {
+ tail->next = nhl;
+ }
+ if (tail) {
+ while (tail->next) {
+ ++count;
+ tail = tail->next;
+ }
+ }
+ }
+
+ vnc_zlog_debug_verbose("%s: returning %d routes", __func__, count);
+ return biglist;
}
-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 *rfd_rib_table,/* preload NVE rib table */
- struct prefix *pfx_target_original) /* query target */
+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 *rfd_rib_table, /* preload NVE rib table */
+ struct prefix *pfx_target_original) /* query target */
{
- int count = 0;
- struct rfapi_next_hop_entry *answer = NULL;
- struct rfapi_next_hop_entry *last = NULL;
- struct route_node *rib_rn;
+ int count = 0;
+ struct rfapi_next_hop_entry *answer = NULL;
+ struct rfapi_next_hop_entry *last = NULL;
+ struct route_node *rib_rn;
- rib_rn = rfd_rib_table? route_node_get(rfd_rib_table, &rn->p): NULL;
+ rib_rn = rfd_rib_table ? route_node_get(rfd_rib_table, &rn->p) : NULL;
- count = rfapiNhlAddNodeRoutes (rn, rprefix, lifetime, 0, &answer, &last,
- NULL, rib_rn, pfx_target_original);
+ count = rfapiNhlAddNodeRoutes(rn, rprefix, lifetime, 0, &answer, &last,
+ NULL, rib_rn, pfx_target_original);
#if DEBUG_ENCAP_MONITOR
- vnc_zlog_debug_verbose ("%s: node %p: %d non-holddown routes", __func__, rn, count);
+ vnc_zlog_debug_verbose("%s: node %p: %d non-holddown routes", __func__,
+ rn, count);
#endif
- if (!count)
- {
- count = rfapiNhlAddNodeRoutes (rn, rprefix, lifetime, 1, &answer, &last,
- exclude_vnaddr, rib_rn, pfx_target_original);
- vnc_zlog_debug_verbose ("%s: node %p: %d holddown routes", __func__, rn, count);
- }
+ if (!count) {
+ count = rfapiNhlAddNodeRoutes(rn, rprefix, lifetime, 1, &answer,
+ &last, exclude_vnaddr, rib_rn,
+ pfx_target_original);
+ vnc_zlog_debug_verbose("%s: node %p: %d holddown routes",
+ __func__, rn, count);
+ }
- if (rib_rn)
- route_unlock_node(rib_rn);
+ if (rib_rn)
+ route_unlock_node(rib_rn);
#if DEBUG_RETURNED_NHL
- rfapiPrintNhl (NULL, answer);
+ rfapiPrintNhl(NULL, answer);
#endif
- return answer;
+ return answer;
}
/*
* Construct nexthop list of all routes in table
*/
-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 *rfd_rib_table, /* preload NVE rib node */
- struct prefix *pfx_target_original) /* query target */
+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 *rfd_rib_table, /* preload NVE rib node */
+ struct prefix *pfx_target_original) /* query target */
{
- struct rfapi_import_table *it;
- struct bgp *bgp = bgp_get_default ();
- struct route_table *rt;
- struct route_node *rn;
- struct rfapi_next_hop_entry *biglist = NULL;
- struct rfapi_next_hop_entry *nhl;
- struct rfapi_next_hop_entry *tail = NULL;
- int count = 0;
-
-
- it = rfapiMacImportTableGet (bgp, logical_net_id);
- rt = it->imported_vpn[AFI_L2VPN];
-
- for (rn = route_top (rt); rn; rn = route_next (rn))
- {
-
- nhl = rfapiEthRouteNode2NextHopList(rn, rprefix, lifetime,
- exclude_vnaddr, rfd_rib_table, pfx_target_original);
- if (!tail)
- {
- tail = biglist = nhl;
- if (tail)
- count = 1;
- }
- else
- {
- tail->next = nhl;
- }
- if (tail)
- {
- while (tail->next)
- {
- ++count;
- tail = tail->next;
- }
- }
- }
-
- vnc_zlog_debug_verbose ("%s: returning %d routes", __func__, count);
- return biglist;
+ struct rfapi_import_table *it;
+ struct bgp *bgp = bgp_get_default();
+ struct route_table *rt;
+ struct route_node *rn;
+ struct rfapi_next_hop_entry *biglist = NULL;
+ struct rfapi_next_hop_entry *nhl;
+ struct rfapi_next_hop_entry *tail = NULL;
+ int count = 0;
+
+
+ it = rfapiMacImportTableGet(bgp, logical_net_id);
+ rt = it->imported_vpn[AFI_L2VPN];
+
+ for (rn = route_top(rt); rn; rn = route_next(rn)) {
+
+ nhl = rfapiEthRouteNode2NextHopList(
+ rn, rprefix, lifetime, exclude_vnaddr, rfd_rib_table,
+ pfx_target_original);
+ if (!tail) {
+ tail = biglist = nhl;
+ if (tail)
+ count = 1;
+ } else {
+ tail->next = nhl;
+ }
+ if (tail) {
+ while (tail->next) {
+ ++count;
+ tail = tail->next;
+ }
+ }
+ }
+
+ vnc_zlog_debug_verbose("%s: returning %d routes", __func__, count);
+ return biglist;
}
/*
* Insert a new bi to the imported route table node,
* keeping the list of BIs sorted best route first
*/
-static void
-rfapiBgpInfoAttachSorted (
- struct route_node *rn,
- struct bgp_info *info_new,
- afi_t afi,
- safi_t safi)
+static void rfapiBgpInfoAttachSorted(struct route_node *rn,
+ struct bgp_info *info_new, afi_t afi,
+ safi_t safi)
{
- struct bgp *bgp;
- struct bgp_info *prev;
- struct bgp_info *next;
- char pfx_buf[PREFIX2STR_BUFFER];
-
-
- bgp = bgp_get_default (); /* assume 1 instance for now */
-
- if (VNC_DEBUG(IMPORT_BI_ATTACH))
- {
- vnc_zlog_debug_verbose ("%s: info_new->peer=%p", __func__, info_new->peer);
- vnc_zlog_debug_verbose ("%s: info_new->peer->su_remote=%p", __func__,
- info_new->peer->su_remote);
- }
-
- for (prev = NULL, next = rn->info; next; prev = next, next = next->next)
- {
- if (!bgp ||
- (!CHECK_FLAG (info_new->flags, BGP_INFO_REMOVED) &&
- CHECK_FLAG (next->flags, BGP_INFO_REMOVED)) ||
- bgp_info_cmp_compatible (bgp, info_new, next, pfx_buf, afi, safi) == -1)
- { /* -1 if 1st is better */
- break;
- }
- }
- vnc_zlog_debug_verbose ("%s: prev=%p, next=%p", __func__, prev, next);
- if (prev)
- {
- prev->next = info_new;
- }
- else
- {
- rn->info = info_new;
- }
- info_new->prev = prev;
- info_new->next = next;
- if (next)
- next->prev = info_new;
- bgp_attr_intern (info_new->attr);
+ struct bgp *bgp;
+ struct bgp_info *prev;
+ struct bgp_info *next;
+ char pfx_buf[PREFIX2STR_BUFFER];
+
+
+ bgp = bgp_get_default(); /* assume 1 instance for now */
+
+ if (VNC_DEBUG(IMPORT_BI_ATTACH)) {
+ vnc_zlog_debug_verbose("%s: info_new->peer=%p", __func__,
+ info_new->peer);
+ vnc_zlog_debug_verbose("%s: info_new->peer->su_remote=%p",
+ __func__, info_new->peer->su_remote);
+ }
+
+ for (prev = NULL, next = rn->info; next;
+ prev = next, next = next->next) {
+ if (!bgp || (!CHECK_FLAG(info_new->flags, BGP_INFO_REMOVED)
+ && CHECK_FLAG(next->flags, BGP_INFO_REMOVED))
+ || bgp_info_cmp_compatible(bgp, info_new, next, pfx_buf,
+ afi, safi)
+ == -1) { /* -1 if 1st is better */
+ break;
+ }
+ }
+ vnc_zlog_debug_verbose("%s: prev=%p, next=%p", __func__, prev, next);
+ if (prev) {
+ prev->next = info_new;
+ } else {
+ rn->info = info_new;
+ }
+ info_new->prev = prev;
+ info_new->next = next;
+ if (next)
+ next->prev = info_new;
+ bgp_attr_intern(info_new->attr);
}
-static void
-rfapiBgpInfoDetach (struct route_node *rn, struct bgp_info *bi)
+static void rfapiBgpInfoDetach(struct route_node *rn, struct bgp_info *bi)
{
- /*
- * Remove the route (doubly-linked)
- */
- // bgp_attr_unintern (&bi->attr);
- if (bi->next)
- bi->next->prev = bi->prev;
- if (bi->prev)
- bi->prev->next = bi->next;
- else
- rn->info = bi->next;
+ /*
+ * Remove the route (doubly-linked)
+ */
+ // bgp_attr_unintern (&bi->attr);
+ if (bi->next)
+ bi->next->prev = bi->prev;
+ if (bi->prev)
+ bi->prev->next = bi->next;
+ else
+ rn->info = bi->next;
}
/*
* For L3-indexed import tables
*/
-static int
-rfapi_bi_peer_rd_cmp (void *b1, void *b2)
+static int rfapi_bi_peer_rd_cmp(void *b1, void *b2)
{
- struct bgp_info *bi1 = b1;
- struct bgp_info *bi2 = b2;
-
- /*
- * Compare peers
- */
- if (bi1->peer < bi2->peer)
- return -1;
- if (bi1->peer > bi2->peer)
- return 1;
-
- /*
- * compare RDs
- */
- return vnc_prefix_cmp ((struct prefix *) &bi1->extra->vnc.import.rd,
- (struct prefix *) &bi2->extra->vnc.import.rd);
+ struct bgp_info *bi1 = b1;
+ struct bgp_info *bi2 = b2;
+
+ /*
+ * Compare peers
+ */
+ if (bi1->peer < bi2->peer)
+ return -1;
+ if (bi1->peer > bi2->peer)
+ return 1;
+
+ /*
+ * compare RDs
+ */
+ return vnc_prefix_cmp((struct prefix *)&bi1->extra->vnc.import.rd,
+ (struct prefix *)&bi2->extra->vnc.import.rd);
}
/*
@@ -2198,765 +2074,717 @@ rfapi_bi_peer_rd_cmp (void *b1, void *b2)
* The BIs in these tables should ALWAYS have an aux_prefix set because
* they arrive via IPv4 or IPv6 advertisements.
*/
-static int
-rfapi_bi_peer_rd_aux_cmp (void *b1, void *b2)
+static int rfapi_bi_peer_rd_aux_cmp(void *b1, void *b2)
{
- struct bgp_info *bi1 = b1;
- struct bgp_info *bi2 = b2;
- int rc;
-
- /*
- * Compare peers
- */
- if (bi1->peer < bi2->peer)
- return -1;
- if (bi1->peer > bi2->peer)
- return 1;
-
- /*
- * compare RDs
- */
- rc = vnc_prefix_cmp ((struct prefix *) &bi1->extra->vnc.import.rd,
- (struct prefix *) &bi2->extra->vnc.import.rd);
- if (rc)
- {
- return rc;
- }
-
- /*
- * L2 import tables can have multiple entries with the
- * same MAC address, same RD, but different L3 addresses.
- *
- * Use presence of aux_prefix with AF=ethernet and prefixlen=1
- * as magic value to signify explicit wildcarding of the aux_prefix.
- * This magic value will not appear in bona fide bi entries in
- * the import table, but is allowed in the "fake" bi used to
- * probe the table when searching. (We have to test both b1 and b2
- * because there is no guarantee of the order the test key and
- * the real key will be passed)
- */
- if ((bi1->extra->vnc.import.aux_prefix.family == AF_ETHERNET &&
- (bi1->extra->vnc.import.aux_prefix.prefixlen == 1)) ||
- (bi2->extra->vnc.import.aux_prefix.family == AF_ETHERNET &&
- (bi2->extra->vnc.import.aux_prefix.prefixlen == 1)))
- {
-
- /*
- * wildcard aux address specified
- */
- return 0;
- }
-
- return vnc_prefix_cmp (&bi1->extra->vnc.import.aux_prefix,
- &bi2->extra->vnc.import.aux_prefix);
+ struct bgp_info *bi1 = b1;
+ struct bgp_info *bi2 = b2;
+ int rc;
+
+ /*
+ * Compare peers
+ */
+ if (bi1->peer < bi2->peer)
+ return -1;
+ if (bi1->peer > bi2->peer)
+ return 1;
+
+ /*
+ * compare RDs
+ */
+ rc = vnc_prefix_cmp((struct prefix *)&bi1->extra->vnc.import.rd,
+ (struct prefix *)&bi2->extra->vnc.import.rd);
+ if (rc) {
+ return rc;
+ }
+
+ /*
+ * L2 import tables can have multiple entries with the
+ * same MAC address, same RD, but different L3 addresses.
+ *
+ * Use presence of aux_prefix with AF=ethernet and prefixlen=1
+ * as magic value to signify explicit wildcarding of the aux_prefix.
+ * This magic value will not appear in bona fide bi entries in
+ * the import table, but is allowed in the "fake" bi used to
+ * probe the table when searching. (We have to test both b1 and b2
+ * because there is no guarantee of the order the test key and
+ * the real key will be passed)
+ */
+ if ((bi1->extra->vnc.import.aux_prefix.family == AF_ETHERNET
+ && (bi1->extra->vnc.import.aux_prefix.prefixlen == 1))
+ || (bi2->extra->vnc.import.aux_prefix.family == AF_ETHERNET
+ && (bi2->extra->vnc.import.aux_prefix.prefixlen == 1))) {
+
+ /*
+ * wildcard aux address specified
+ */
+ return 0;
+ }
+
+ return vnc_prefix_cmp(&bi1->extra->vnc.import.aux_prefix,
+ &bi2->extra->vnc.import.aux_prefix);
}
/*
* Index on RD and Peer
*/
-static void
-rfapiItBiIndexAdd (
- struct route_node *rn, /* Import table VPN node */
- struct bgp_info *bi) /* new BI */
+static void rfapiItBiIndexAdd(struct route_node *rn, /* Import table VPN node */
+ struct bgp_info *bi) /* new BI */
{
- struct skiplist *sl;
-
- assert (rn);
- assert (bi);
- assert (bi->extra);
-
- {
- char buf[BUFSIZ];
- prefix_rd2str (&bi->extra->vnc.import.rd, buf, BUFSIZ);
- vnc_zlog_debug_verbose ("%s: bi %p, peer %p, rd %s", __func__, bi, bi->peer, buf);
- }
-
- sl = RFAPI_RDINDEX_W_ALLOC (rn);
- if (!sl)
- {
- if (AF_ETHERNET == rn->p.family)
- {
- sl = skiplist_new (0, rfapi_bi_peer_rd_aux_cmp, NULL);
- }
- else
- {
- sl = skiplist_new (0, rfapi_bi_peer_rd_cmp, NULL);
- }
- RFAPI_IT_EXTRA_GET (rn)->u.vpn.idx_rd = sl;
- route_lock_node (rn); /* for skiplist */
- }
- assert (!skiplist_insert (sl, (void *) bi, (void *) bi));
- route_lock_node (rn); /* for skiplist entry */
-
- /* NB: BIs in import tables are not refcounted */
+ struct skiplist *sl;
+
+ assert(rn);
+ assert(bi);
+ assert(bi->extra);
+
+ {
+ char buf[BUFSIZ];
+ prefix_rd2str(&bi->extra->vnc.import.rd, buf, BUFSIZ);
+ vnc_zlog_debug_verbose("%s: bi %p, peer %p, rd %s", __func__,
+ bi, bi->peer, buf);
+ }
+
+ sl = RFAPI_RDINDEX_W_ALLOC(rn);
+ if (!sl) {
+ if (AF_ETHERNET == rn->p.family) {
+ sl = skiplist_new(0, rfapi_bi_peer_rd_aux_cmp, NULL);
+ } else {
+ sl = skiplist_new(0, rfapi_bi_peer_rd_cmp, NULL);
+ }
+ RFAPI_IT_EXTRA_GET(rn)->u.vpn.idx_rd = sl;
+ route_lock_node(rn); /* for skiplist */
+ }
+ assert(!skiplist_insert(sl, (void *)bi, (void *)bi));
+ route_lock_node(rn); /* for skiplist entry */
+
+ /* NB: BIs in import tables are not refcounted */
}
-static void
-rfapiItBiIndexDump (struct route_node *rn)
+static void rfapiItBiIndexDump(struct route_node *rn)
{
- struct skiplist *sl;
- void *cursor = NULL;
- struct bgp_info *k;
- struct bgp_info *v;
- int rc;
-
- sl = RFAPI_RDINDEX (rn);
- if (!sl)
- return;
-
- for (rc = skiplist_next (sl, (void **) &k, (void **) &v, &cursor);
- !rc; rc = skiplist_next (sl, (void **) &k, (void **) &v, &cursor))
- {
-
- char buf[BUFSIZ];
- char buf_aux_pfx[BUFSIZ];
-
- prefix_rd2str (&k->extra->vnc.import.rd, buf, BUFSIZ);
- buf_aux_pfx[0] = 0;
- if (k->extra->vnc.import.aux_prefix.family)
- {
- prefix2str (&k->extra->vnc.import.aux_prefix, buf_aux_pfx, BUFSIZ);
- }
- else
- {
- strncpy (buf_aux_pfx, "(none)", BUFSIZ);
- buf_aux_pfx[BUFSIZ - 1] = 0;
- }
-
- vnc_zlog_debug_verbose ("bi %p, peer %p, rd %s, aux_prefix %s", k, k->peer, buf,
- buf_aux_pfx);
- }
+ struct skiplist *sl;
+ void *cursor = NULL;
+ struct bgp_info *k;
+ struct bgp_info *v;
+ int rc;
+
+ sl = RFAPI_RDINDEX(rn);
+ if (!sl)
+ return;
+
+ for (rc = skiplist_next(sl, (void **)&k, (void **)&v, &cursor); !rc;
+ rc = skiplist_next(sl, (void **)&k, (void **)&v, &cursor)) {
+
+ char buf[BUFSIZ];
+ char buf_aux_pfx[BUFSIZ];
+
+ prefix_rd2str(&k->extra->vnc.import.rd, buf, BUFSIZ);
+ buf_aux_pfx[0] = 0;
+ if (k->extra->vnc.import.aux_prefix.family) {
+ prefix2str(&k->extra->vnc.import.aux_prefix,
+ buf_aux_pfx, BUFSIZ);
+ } else {
+ strncpy(buf_aux_pfx, "(none)", BUFSIZ);
+ buf_aux_pfx[BUFSIZ - 1] = 0;
+ }
+
+ vnc_zlog_debug_verbose("bi %p, peer %p, rd %s, aux_prefix %s",
+ k, k->peer, buf, buf_aux_pfx);
+ }
}
-static struct bgp_info *
-rfapiItBiIndexSearch (
- struct route_node *rn, /* Import table VPN node */
- struct prefix_rd *prd,
- struct peer *peer,
- struct prefix *aux_prefix) /* optional L3 addr for L2 ITs */
+static struct bgp_info *rfapiItBiIndexSearch(
+ struct route_node *rn, /* Import table VPN node */
+ struct prefix_rd *prd, struct peer *peer,
+ struct prefix *aux_prefix) /* optional L3 addr for L2 ITs */
{
- struct skiplist *sl;
- int rc;
- struct bgp_info bi_fake;
- struct bgp_info_extra bi_extra;
- struct bgp_info *bi_result;
+ struct skiplist *sl;
+ int rc;
+ struct bgp_info bi_fake;
+ struct bgp_info_extra bi_extra;
+ struct bgp_info *bi_result;
- sl = RFAPI_RDINDEX (rn);
- if (!sl)
- return NULL;
+ sl = RFAPI_RDINDEX(rn);
+ if (!sl)
+ return NULL;
#if DEBUG_BI_SEARCH
- {
- char buf[BUFSIZ];
- char buf_aux_pfx[BUFSIZ];
-
- prefix_rd2str (prd, buf, BUFSIZ);
- if (aux_prefix)
- {
- prefix2str (aux_prefix, buf_aux_pfx, BUFSIZ);
- }
- else
- {
- strncpy (buf_aux_pfx, "(nil)", BUFSIZ - 1);
- buf_aux_pfx[BUFSIZ - 1] = 0;
- }
-
- vnc_zlog_debug_verbose ("%s want prd=%s, peer=%p, aux_prefix=%s",
- __func__, buf, peer, buf_aux_pfx);
- rfapiItBiIndexDump (rn);
- }
+ {
+ char buf[BUFSIZ];
+ char buf_aux_pfx[BUFSIZ];
+
+ prefix_rd2str(prd, buf, BUFSIZ);
+ if (aux_prefix) {
+ prefix2str(aux_prefix, buf_aux_pfx, BUFSIZ);
+ } else {
+ strncpy(buf_aux_pfx, "(nil)", BUFSIZ - 1);
+ buf_aux_pfx[BUFSIZ - 1] = 0;
+ }
+
+ vnc_zlog_debug_verbose("%s want prd=%s, peer=%p, aux_prefix=%s",
+ __func__, buf, peer, buf_aux_pfx);
+ rfapiItBiIndexDump(rn);
+ }
#endif
- /* threshold is a WAG */
- if (sl->count < 3)
- {
+ /* threshold is a WAG */
+ if (sl->count < 3) {
#if DEBUG_BI_SEARCH
- vnc_zlog_debug_verbose ("%s: short list algorithm", __func__);
+ vnc_zlog_debug_verbose("%s: short list algorithm", __func__);
#endif
- /* if short list, linear search might be faster */
- for (bi_result = rn->info; bi_result; bi_result = bi_result->next)
- {
+ /* if short list, linear search might be faster */
+ for (bi_result = rn->info; bi_result;
+ bi_result = bi_result->next) {
#if DEBUG_BI_SEARCH
- {
- char buf[BUFSIZ];
- prefix_rd2str (&bi_result->extra->vnc.import.rd, buf, BUFSIZ);
- vnc_zlog_debug_verbose ("%s: bi has prd=%s, peer=%p", __func__,
- buf, bi_result->peer);
- }
+ {
+ char buf[BUFSIZ];
+ prefix_rd2str(&bi_result->extra->vnc.import.rd,
+ buf, BUFSIZ);
+ vnc_zlog_debug_verbose(
+ "%s: bi has prd=%s, peer=%p", __func__,
+ buf, bi_result->peer);
+ }
#endif
- if (peer == bi_result->peer &&
- !prefix_cmp ((struct prefix *) &bi_result->extra->vnc.import.rd,
- (struct prefix *) prd))
- {
+ if (peer == bi_result->peer
+ && !prefix_cmp((struct prefix *)&bi_result->extra
+ ->vnc.import.rd,
+ (struct prefix *)prd)) {
#if DEBUG_BI_SEARCH
- vnc_zlog_debug_verbose ("%s: peer and RD same, doing aux_prefix check",
- __func__);
+ vnc_zlog_debug_verbose(
+ "%s: peer and RD same, doing aux_prefix check",
+ __func__);
#endif
- if (!aux_prefix ||
- !prefix_cmp (aux_prefix,
- &bi_result->extra->vnc.import.aux_prefix))
- {
+ if (!aux_prefix
+ || !prefix_cmp(aux_prefix,
+ &bi_result->extra->vnc.import
+ .aux_prefix)) {
#if DEBUG_BI_SEARCH
- vnc_zlog_debug_verbose ("%s: match", __func__);
+ vnc_zlog_debug_verbose("%s: match",
+ __func__);
#endif
- break;
- }
-
- }
- }
- return bi_result;
- }
-
- bi_fake.peer = peer;
- bi_fake.extra = &bi_extra;
- bi_fake.extra->vnc.import.rd = *(struct prefix_rd *) prd;
- if (aux_prefix)
- {
- bi_fake.extra->vnc.import.aux_prefix = *aux_prefix;
- }
- else
- {
- /* wildcard */
- bi_fake.extra->vnc.import.aux_prefix.family = AF_ETHERNET;
- bi_fake.extra->vnc.import.aux_prefix.prefixlen = 1;
- }
-
- rc = skiplist_search (sl, (void *) &bi_fake, (void *) &bi_result);
-
- if (rc)
- {
+ break;
+ }
+ }
+ }
+ return bi_result;
+ }
+
+ bi_fake.peer = peer;
+ bi_fake.extra = &bi_extra;
+ bi_fake.extra->vnc.import.rd = *(struct prefix_rd *)prd;
+ if (aux_prefix) {
+ bi_fake.extra->vnc.import.aux_prefix = *aux_prefix;
+ } else {
+ /* wildcard */
+ bi_fake.extra->vnc.import.aux_prefix.family = AF_ETHERNET;
+ bi_fake.extra->vnc.import.aux_prefix.prefixlen = 1;
+ }
+
+ rc = skiplist_search(sl, (void *)&bi_fake, (void *)&bi_result);
+
+ if (rc) {
#if DEBUG_BI_SEARCH
- vnc_zlog_debug_verbose ("%s: no match", __func__);
+ vnc_zlog_debug_verbose("%s: no match", __func__);
#endif
- return NULL;
- }
+ return NULL;
+ }
#if DEBUG_BI_SEARCH
- vnc_zlog_debug_verbose ("%s: matched bi=%p", __func__, bi_result);
+ vnc_zlog_debug_verbose("%s: matched bi=%p", __func__, bi_result);
#endif
- return bi_result;
+ return bi_result;
}
-static void
-rfapiItBiIndexDel (
- struct route_node *rn, /* Import table VPN node */
- struct bgp_info *bi) /* old BI */
+static void rfapiItBiIndexDel(struct route_node *rn, /* Import table VPN node */
+ struct bgp_info *bi) /* old BI */
{
- struct skiplist *sl;
- int rc;
+ struct skiplist *sl;
+ int rc;
- {
- char buf[BUFSIZ];
- prefix_rd2str (&bi->extra->vnc.import.rd, buf, BUFSIZ);
- vnc_zlog_debug_verbose ("%s: bi %p, peer %p, rd %s", __func__, bi, bi->peer, buf);
- }
+ {
+ char buf[BUFSIZ];
+ prefix_rd2str(&bi->extra->vnc.import.rd, buf, BUFSIZ);
+ vnc_zlog_debug_verbose("%s: bi %p, peer %p, rd %s", __func__,
+ bi, bi->peer, buf);
+ }
- sl = RFAPI_RDINDEX (rn);
- assert (sl);
+ sl = RFAPI_RDINDEX(rn);
+ assert(sl);
- rc = skiplist_delete (sl, (void *) (bi), (void *) bi);
- if (rc)
- {
- rfapiItBiIndexDump (rn);
- }
- assert (!rc);
+ rc = skiplist_delete(sl, (void *)(bi), (void *)bi);
+ if (rc) {
+ rfapiItBiIndexDump(rn);
+ }
+ assert(!rc);
- route_unlock_node (rn); /* for skiplist entry */
+ route_unlock_node(rn); /* for skiplist entry */
- /* NB: BIs in import tables are not refcounted */
+ /* NB: BIs in import tables are not refcounted */
}
/*
* Add a backreference at the ENCAP node to the VPN route that
* refers to it
*/
-static void
-rfapiMonitorEncapAdd (
- struct rfapi_import_table *import_table,
- struct prefix *p, /* VN address */
- struct route_node *vpn_rn, /* VPN node */
- struct bgp_info *vpn_bi) /* VPN bi/route */
+static void rfapiMonitorEncapAdd(struct rfapi_import_table *import_table,
+ struct prefix *p, /* VN address */
+ struct route_node *vpn_rn, /* VPN node */
+ struct bgp_info *vpn_bi) /* VPN bi/route */
{
- afi_t afi = family2afi (p->family);
- struct route_node *rn;
- struct rfapi_monitor_encap *m;
-
- assert (afi);
- rn = route_node_get (import_table->imported_encap[afi], p); /* locks rn */
- assert (rn);
-
- m =
- XCALLOC (MTYPE_RFAPI_MONITOR_ENCAP, sizeof (struct rfapi_monitor_encap));
- assert (m);
-
- m->node = vpn_rn;
- m->bi = vpn_bi;
- m->rn = rn;
-
- /* insert to encap node's list */
- m->next = RFAPI_MONITOR_ENCAP (rn);
- if (m->next)
- m->next->prev = m;
- RFAPI_MONITOR_ENCAP_W_ALLOC (rn) = m;
-
- /* for easy lookup when deleting vpn route */
- vpn_bi->extra->vnc.import.hme = m;
-
- vnc_zlog_debug_verbose
- ("%s: it=%p, vpn_bi=%p, afi=%d, encap rn=%p, setting vpn_bi->extra->vnc.import.hme=%p",
- __func__, import_table, vpn_bi, afi, rn, m);
-
- RFAPI_CHECK_REFCOUNT (rn, SAFI_ENCAP, 0);
- bgp_attr_intern (vpn_bi->attr);
+ afi_t afi = family2afi(p->family);
+ struct route_node *rn;
+ struct rfapi_monitor_encap *m;
+
+ assert(afi);
+ rn = route_node_get(import_table->imported_encap[afi],
+ p); /* locks rn */
+ assert(rn);
+
+ m = XCALLOC(MTYPE_RFAPI_MONITOR_ENCAP,
+ sizeof(struct rfapi_monitor_encap));
+ assert(m);
+
+ m->node = vpn_rn;
+ m->bi = vpn_bi;
+ m->rn = rn;
+
+ /* insert to encap node's list */
+ m->next = RFAPI_MONITOR_ENCAP(rn);
+ if (m->next)
+ m->next->prev = m;
+ RFAPI_MONITOR_ENCAP_W_ALLOC(rn) = m;
+
+ /* for easy lookup when deleting vpn route */
+ vpn_bi->extra->vnc.import.hme = m;
+
+ vnc_zlog_debug_verbose(
+ "%s: it=%p, vpn_bi=%p, afi=%d, encap rn=%p, setting vpn_bi->extra->vnc.import.hme=%p",
+ __func__, import_table, vpn_bi, afi, rn, m);
+
+ RFAPI_CHECK_REFCOUNT(rn, SAFI_ENCAP, 0);
+ bgp_attr_intern(vpn_bi->attr);
}
-static void
-rfapiMonitorEncapDelete (struct bgp_info *vpn_bi)
+static void rfapiMonitorEncapDelete(struct bgp_info *vpn_bi)
{
- /*
- * Remove encap monitor
- */
- vnc_zlog_debug_verbose ("%s: vpn_bi=%p", __func__, vpn_bi);
- if (vpn_bi->extra)
- {
- struct rfapi_monitor_encap *hme = vpn_bi->extra->vnc.import.hme;
-
- if (hme)
- {
-
- vnc_zlog_debug_verbose ("%s: hme=%p", __func__, hme);
-
- /* Refcount checking takes too long here */
- //RFAPI_CHECK_REFCOUNT(hme->rn, SAFI_ENCAP, 0);
- if (hme->next)
- hme->next->prev = hme->prev;
- if (hme->prev)
- hme->prev->next = hme->next;
- else
- RFAPI_MONITOR_ENCAP_W_ALLOC (hme->rn) = hme->next;
- /* Refcount checking takes too long here */
- //RFAPI_CHECK_REFCOUNT(hme->rn, SAFI_ENCAP, 1);
-
- /* see if the struct rfapi_it_extra is empty and can be freed */
- rfapiMonitorExtraPrune (SAFI_ENCAP, hme->rn);
-
- route_unlock_node (hme->rn); /* decr ref count */
- XFREE (MTYPE_RFAPI_MONITOR_ENCAP, hme);
- vpn_bi->extra->vnc.import.hme = NULL;
- }
- }
+ /*
+ * Remove encap monitor
+ */
+ vnc_zlog_debug_verbose("%s: vpn_bi=%p", __func__, vpn_bi);
+ if (vpn_bi->extra) {
+ struct rfapi_monitor_encap *hme = vpn_bi->extra->vnc.import.hme;
+
+ if (hme) {
+
+ vnc_zlog_debug_verbose("%s: hme=%p", __func__, hme);
+
+ /* Refcount checking takes too long here */
+ // RFAPI_CHECK_REFCOUNT(hme->rn, SAFI_ENCAP, 0);
+ if (hme->next)
+ hme->next->prev = hme->prev;
+ if (hme->prev)
+ hme->prev->next = hme->next;
+ else
+ RFAPI_MONITOR_ENCAP_W_ALLOC(hme->rn) =
+ hme->next;
+ /* Refcount checking takes too long here */
+ // RFAPI_CHECK_REFCOUNT(hme->rn, SAFI_ENCAP, 1);
+
+ /* see if the struct rfapi_it_extra is empty and can be
+ * freed */
+ rfapiMonitorExtraPrune(SAFI_ENCAP, hme->rn);
+
+ route_unlock_node(hme->rn); /* decr ref count */
+ XFREE(MTYPE_RFAPI_MONITOR_ENCAP, hme);
+ vpn_bi->extra->vnc.import.hme = NULL;
+ }
+ }
}
/*
* quagga lib/thread.h says this must return int even though
* it doesn't do anything with the return value
*/
-static int
-rfapiWithdrawTimerVPN (struct thread *t)
+static int rfapiWithdrawTimerVPN(struct thread *t)
{
- struct rfapi_withdraw *wcb = t->arg;
- struct bgp_info *bi = wcb->info;
- struct bgp *bgp = bgp_get_default ();
-
- struct rfapi_monitor_vpn *moved;
- afi_t afi;
-
- assert (wcb->node);
- assert (bi);
- assert (wcb->import_table);
- assert (bi->extra);
-
- RFAPI_CHECK_REFCOUNT (wcb->node, SAFI_MPLS_VPN, wcb->lockoffset);
-
- {
- char buf[BUFSIZ];
-
- vnc_zlog_debug_verbose ("%s: removing bi %p at prefix %s/%d",
- __func__,
- bi,
- rfapi_ntop (wcb->node->p.family, &wcb->node->p.u.prefix, buf,
- BUFSIZ), wcb->node->p.prefixlen);
- }
-
- /*
- * Remove the route (doubly-linked)
- */
- if (CHECK_FLAG (bi->flags, BGP_INFO_VALID)
- && VALID_INTERIOR_TYPE (bi->type))
- RFAPI_MONITOR_EXTERIOR (wcb->node)->valid_interior_count--;
-
- afi = family2afi (wcb->node->p.family);
- wcb->import_table->holddown_count[afi] -= 1; /* keep count consistent */
- rfapiItBiIndexDel (wcb->node, bi);
- rfapiBgpInfoDetach (wcb->node, bi); /* with removed bi */
-
- vnc_import_bgp_exterior_del_route_interior (bgp, wcb->import_table,
- wcb->node, bi);
-
-
- /*
- * If VNC is configured to send response remove messages, AND
- * if the removed route had a UN address, do response removal
- * processing.
- */
- if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE))
- {
-
- int has_valid_duplicate = 0;
- struct bgp_info *bii;
-
- /*
- * First check if there are any OTHER routes at this node
- * that have the same nexthop and a valid UN address. If
- * there are (e.g., from other peers), then the route isn't
- * really gone, so skip sending a response removal message.
- */
- for (bii = wcb->node->info; bii; bii = bii->next)
- {
- if (rfapiVpnBiSamePtUn (bi, bii))
- {
- has_valid_duplicate = 1;
- break;
- }
- }
-
- vnc_zlog_debug_verbose ("%s: has_valid_duplicate=%d", __func__,
- has_valid_duplicate);
-
- if (!has_valid_duplicate)
- {
- rfapiRibPendingDeleteRoute (bgp, wcb->import_table, afi, wcb->node);
- }
- }
-
- rfapiMonitorEncapDelete (bi);
-
- /*
- * If there are no VPN monitors at this VPN Node A,
- * we are done
- */
- if (!RFAPI_MONITOR_VPN (wcb->node))
- {
- vnc_zlog_debug_verbose ("%s: no VPN monitors at this node", __func__);
- goto done;
- }
-
- /*
- * rfapiMonitorMoveShorter only moves monitors if there are
- * no remaining valid routes at the current node
- */
- moved = rfapiMonitorMoveShorter (wcb->node, 1);
-
- if (moved)
- {
- rfapiMonitorMovedUp (wcb->import_table, wcb->node, moved->node, moved);
- }
+ struct rfapi_withdraw *wcb = t->arg;
+ struct bgp_info *bi = wcb->info;
+ struct bgp *bgp = bgp_get_default();
+
+ struct rfapi_monitor_vpn *moved;
+ afi_t afi;
+
+ assert(wcb->node);
+ assert(bi);
+ assert(wcb->import_table);
+ assert(bi->extra);
+
+ RFAPI_CHECK_REFCOUNT(wcb->node, SAFI_MPLS_VPN, wcb->lockoffset);
+
+ {
+ char buf[BUFSIZ];
+
+ vnc_zlog_debug_verbose(
+ "%s: removing bi %p at prefix %s/%d", __func__, bi,
+ rfapi_ntop(wcb->node->p.family, &wcb->node->p.u.prefix,
+ buf, BUFSIZ),
+ wcb->node->p.prefixlen);
+ }
+
+ /*
+ * Remove the route (doubly-linked)
+ */
+ if (CHECK_FLAG(bi->flags, BGP_INFO_VALID)
+ && VALID_INTERIOR_TYPE(bi->type))
+ RFAPI_MONITOR_EXTERIOR(wcb->node)->valid_interior_count--;
+
+ afi = family2afi(wcb->node->p.family);
+ wcb->import_table->holddown_count[afi] -= 1; /* keep count consistent */
+ rfapiItBiIndexDel(wcb->node, bi);
+ rfapiBgpInfoDetach(wcb->node, bi); /* with removed bi */
+
+ vnc_import_bgp_exterior_del_route_interior(bgp, wcb->import_table,
+ wcb->node, bi);
+
+
+ /*
+ * If VNC is configured to send response remove messages, AND
+ * if the removed route had a UN address, do response removal
+ * processing.
+ */
+ if (!(bgp->rfapi_cfg->flags
+ & BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE)) {
+
+ int has_valid_duplicate = 0;
+ struct bgp_info *bii;
+
+ /*
+ * First check if there are any OTHER routes at this node
+ * that have the same nexthop and a valid UN address. If
+ * there are (e.g., from other peers), then the route isn't
+ * really gone, so skip sending a response removal message.
+ */
+ for (bii = wcb->node->info; bii; bii = bii->next) {
+ if (rfapiVpnBiSamePtUn(bi, bii)) {
+ has_valid_duplicate = 1;
+ break;
+ }
+ }
+
+ vnc_zlog_debug_verbose("%s: has_valid_duplicate=%d", __func__,
+ has_valid_duplicate);
+
+ if (!has_valid_duplicate) {
+ rfapiRibPendingDeleteRoute(bgp, wcb->import_table, afi,
+ wcb->node);
+ }
+ }
+
+ rfapiMonitorEncapDelete(bi);
+
+ /*
+ * If there are no VPN monitors at this VPN Node A,
+ * we are done
+ */
+ if (!RFAPI_MONITOR_VPN(wcb->node)) {
+ vnc_zlog_debug_verbose("%s: no VPN monitors at this node",
+ __func__);
+ goto done;
+ }
+
+ /*
+ * rfapiMonitorMoveShorter only moves monitors if there are
+ * no remaining valid routes at the current node
+ */
+ moved = rfapiMonitorMoveShorter(wcb->node, 1);
+
+ if (moved) {
+ rfapiMonitorMovedUp(wcb->import_table, wcb->node, moved->node,
+ moved);
+ }
done:
- /*
- * Free VPN bi
- */
- rfapiBgpInfoFree (bi);
- wcb->info = NULL;
-
- /*
- * If route count at this node has gone to 0, withdraw exported prefix
- */
- if (!wcb->node->info)
- {
- /* see if the struct rfapi_it_extra is empty and can be freed */
- rfapiMonitorExtraPrune (SAFI_MPLS_VPN, wcb->node);
- vnc_direct_bgp_del_prefix (bgp, wcb->import_table, wcb->node);
- vnc_zebra_del_prefix (bgp, wcb->import_table, wcb->node);
- }
- else
- {
- /*
- * nexthop change event
- * vnc_direct_bgp_add_prefix() will recompute the VN addr ecommunity
- */
- vnc_direct_bgp_add_prefix (bgp, wcb->import_table, wcb->node);
- }
-
- RFAPI_CHECK_REFCOUNT (wcb->node, SAFI_MPLS_VPN, 1 + wcb->lockoffset);
- route_unlock_node (wcb->node); /* decr ref count */
- XFREE (MTYPE_RFAPI_WITHDRAW, wcb);
- return 0;
+ /*
+ * Free VPN bi
+ */
+ rfapiBgpInfoFree(bi);
+ wcb->info = NULL;
+
+ /*
+ * If route count at this node has gone to 0, withdraw exported prefix
+ */
+ if (!wcb->node->info) {
+ /* see if the struct rfapi_it_extra is empty and can be freed */
+ rfapiMonitorExtraPrune(SAFI_MPLS_VPN, wcb->node);
+ vnc_direct_bgp_del_prefix(bgp, wcb->import_table, wcb->node);
+ vnc_zebra_del_prefix(bgp, wcb->import_table, wcb->node);
+ } else {
+ /*
+ * nexthop change event
+ * vnc_direct_bgp_add_prefix() will recompute the VN addr
+ * ecommunity
+ */
+ vnc_direct_bgp_add_prefix(bgp, wcb->import_table, wcb->node);
+ }
+
+ RFAPI_CHECK_REFCOUNT(wcb->node, SAFI_MPLS_VPN, 1 + wcb->lockoffset);
+ route_unlock_node(wcb->node); /* decr ref count */
+ XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
+ return 0;
}
/*
* This works for multiprotocol extension, but not for plain ol'
* unicast IPv4 because that nexthop is stored in attr->nexthop
*/
-void
-rfapiNexthop2Prefix (struct attr *attr, struct prefix *p)
+void rfapiNexthop2Prefix(struct attr *attr, struct prefix *p)
{
- assert (p);
- assert (attr);
-
- memset (p, 0, sizeof (struct prefix));
-
- switch (p->family = BGP_MP_NEXTHOP_FAMILY (attr->mp_nexthop_len))
- {
- case AF_INET:
- p->u.prefix4 = attr->mp_nexthop_global_in;
- p->prefixlen = 32;
- break;
-
- case AF_INET6:
- p->u.prefix6 = attr->mp_nexthop_global;
- p->prefixlen = 128;
- break;
-
- default:
- vnc_zlog_debug_verbose ("%s: Family is unknown = %d",
- __func__, p->family);
- }
+ assert(p);
+ assert(attr);
+
+ memset(p, 0, sizeof(struct prefix));
+
+ switch (p->family = BGP_MP_NEXTHOP_FAMILY(attr->mp_nexthop_len)) {
+ case AF_INET:
+ p->u.prefix4 = attr->mp_nexthop_global_in;
+ p->prefixlen = 32;
+ break;
+
+ case AF_INET6:
+ p->u.prefix6 = attr->mp_nexthop_global;
+ p->prefixlen = 128;
+ break;
+
+ default:
+ vnc_zlog_debug_verbose("%s: Family is unknown = %d", __func__,
+ p->family);
+ }
}
-void
-rfapiUnicastNexthop2Prefix (afi_t afi, struct attr *attr, struct prefix *p)
+void rfapiUnicastNexthop2Prefix(afi_t afi, struct attr *attr, struct prefix *p)
{
- if (afi == AFI_IP)
- {
- p->family = AF_INET;
- p->prefixlen = 32;
- p->u.prefix4 = attr->nexthop;
- }
- else
- {
- rfapiNexthop2Prefix (attr, p);
- }
+ if (afi == AFI_IP) {
+ p->family = AF_INET;
+ p->prefixlen = 32;
+ p->u.prefix4 = attr->nexthop;
+ } else {
+ rfapiNexthop2Prefix(attr, p);
+ }
}
-static int
-rfapiAttrNexthopAddrDifferent (struct prefix *p1, struct prefix *p2)
+static int rfapiAttrNexthopAddrDifferent(struct prefix *p1, struct prefix *p2)
{
- if (!p1 || !p2)
- {
- vnc_zlog_debug_verbose ("%s: p1 or p2 is NULL", __func__);
- return 1;
- }
-
- /*
- * Are address families the same?
- */
- if (p1->family != p2->family)
- {
- return 1;
- }
-
- switch (p1->family)
- {
- case AF_INET:
- if (IPV4_ADDR_SAME (&p1->u.prefix4, &p2->u.prefix4))
- return 0;
- break;
-
- case AF_INET6:
- if (IPV6_ADDR_SAME (&p1->u.prefix6, &p2->u.prefix6))
- return 0;
- break;
-
- default:
- assert (1);
-
- }
-
- return 1;
+ if (!p1 || !p2) {
+ vnc_zlog_debug_verbose("%s: p1 or p2 is NULL", __func__);
+ return 1;
+ }
+
+ /*
+ * Are address families the same?
+ */
+ if (p1->family != p2->family) {
+ return 1;
+ }
+
+ switch (p1->family) {
+ case AF_INET:
+ if (IPV4_ADDR_SAME(&p1->u.prefix4, &p2->u.prefix4))
+ return 0;
+ break;
+
+ case AF_INET6:
+ if (IPV6_ADDR_SAME(&p1->u.prefix6, &p2->u.prefix6))
+ return 0;
+ break;
+
+ default:
+ assert(1);
+ }
+
+ return 1;
}
-static void
-rfapiCopyUnEncap2VPN (struct bgp_info *encap_bi, struct bgp_info *vpn_bi)
+static void rfapiCopyUnEncap2VPN(struct bgp_info *encap_bi,
+ struct bgp_info *vpn_bi)
{
- if (!encap_bi->attr)
- {
- zlog_warn ("%s: no encap bi attr/extra, can't copy UN address",
- __func__);
- return;
- }
-
- if (!vpn_bi || !vpn_bi->extra)
- {
- zlog_warn ("%s: no vpn bi attr/extra, can't copy UN address",
- __func__);
- return;
- }
-
- switch (BGP_MP_NEXTHOP_FAMILY (encap_bi->attr->mp_nexthop_len))
- {
- case AF_INET:
-
- /*
- * instrumentation to debug segfault of 091127
- */
- vnc_zlog_debug_verbose ("%s: vpn_bi=%p", __func__, vpn_bi);
- if (vpn_bi)
- {
- vnc_zlog_debug_verbose ("%s: vpn_bi->extra=%p", __func__, vpn_bi->extra);
- }
-
- vpn_bi->extra->vnc.import.un_family = AF_INET;
- vpn_bi->extra->vnc.import.un.addr4 = encap_bi->attr->mp_nexthop_global_in;
- break;
-
- case AF_INET6:
- vpn_bi->extra->vnc.import.un_family = AF_INET6;
- vpn_bi->extra->vnc.import.un.addr6 = encap_bi->attr->mp_nexthop_global;
- break;
-
- default:
- zlog_warn ("%s: invalid encap nexthop length: %d",
- __func__, encap_bi->attr->mp_nexthop_len);
- vpn_bi->extra->vnc.import.un_family = 0;
- break;
- }
+ if (!encap_bi->attr) {
+ zlog_warn("%s: no encap bi attr/extra, can't copy UN address",
+ __func__);
+ return;
+ }
+
+ if (!vpn_bi || !vpn_bi->extra) {
+ zlog_warn("%s: no vpn bi attr/extra, can't copy UN address",
+ __func__);
+ return;
+ }
+
+ switch (BGP_MP_NEXTHOP_FAMILY(encap_bi->attr->mp_nexthop_len)) {
+ case AF_INET:
+
+ /*
+ * instrumentation to debug segfault of 091127
+ */
+ vnc_zlog_debug_verbose("%s: vpn_bi=%p", __func__, vpn_bi);
+ if (vpn_bi) {
+ vnc_zlog_debug_verbose("%s: vpn_bi->extra=%p", __func__,
+ vpn_bi->extra);
+ }
+
+ vpn_bi->extra->vnc.import.un_family = AF_INET;
+ vpn_bi->extra->vnc.import.un.addr4 =
+ encap_bi->attr->mp_nexthop_global_in;
+ break;
+
+ case AF_INET6:
+ vpn_bi->extra->vnc.import.un_family = AF_INET6;
+ vpn_bi->extra->vnc.import.un.addr6 =
+ encap_bi->attr->mp_nexthop_global;
+ break;
+
+ default:
+ zlog_warn("%s: invalid encap nexthop length: %d", __func__,
+ encap_bi->attr->mp_nexthop_len);
+ vpn_bi->extra->vnc.import.un_family = 0;
+ break;
+ }
}
/*
* returns 0 on success, nonzero on error
*/
-static int
-rfapiWithdrawEncapUpdateCachedUn (
- struct rfapi_import_table *import_table,
- struct bgp_info *encap_bi,
- struct route_node *vpn_rn,
- struct bgp_info *vpn_bi)
+static int rfapiWithdrawEncapUpdateCachedUn(
+ struct rfapi_import_table *import_table, struct bgp_info *encap_bi,
+ struct route_node *vpn_rn, struct bgp_info *vpn_bi)
{
- if (!encap_bi)
- {
-
- /*
- * clear cached UN address
- */
- if (!vpn_bi || !vpn_bi->extra)
- {
- zlog_warn ("%s: missing VPN bi/extra, can't clear UN addr",
- __func__);
- return 1;
- }
- vpn_bi->extra->vnc.import.un_family = 0;
- memset (&vpn_bi->extra->vnc.import.un, 0,
- sizeof (vpn_bi->extra->vnc.import.un));
- if (CHECK_FLAG (vpn_bi->flags, BGP_INFO_VALID))
- {
- if (rfapiGetVncTunnelUnAddr (vpn_bi->attr, NULL))
- {
- UNSET_FLAG (vpn_bi->flags, BGP_INFO_VALID);
- if (VALID_INTERIOR_TYPE (vpn_bi->type))
- RFAPI_MONITOR_EXTERIOR (vpn_rn)->valid_interior_count--;
- /* signal interior route withdrawal to import-exterior */
- vnc_import_bgp_exterior_del_route_interior (bgp_get_default (),
- import_table,
- vpn_rn, vpn_bi);
- }
- }
-
- }
- else
- {
- if (!vpn_bi)
- {
- zlog_warn ("%s: missing VPN bi, can't clear UN addr", __func__);
- return 1;
- }
- rfapiCopyUnEncap2VPN (encap_bi, vpn_bi);
- if (!CHECK_FLAG (vpn_bi->flags, BGP_INFO_VALID))
- {
- SET_FLAG (vpn_bi->flags, BGP_INFO_VALID);
- if (VALID_INTERIOR_TYPE (vpn_bi->type))
- RFAPI_MONITOR_EXTERIOR (vpn_rn)->valid_interior_count++;
- /* signal interior route withdrawal to import-exterior */
- vnc_import_bgp_exterior_add_route_interior (bgp_get_default (),
- import_table,
- vpn_rn, vpn_bi);
- }
- }
- return 0;
+ if (!encap_bi) {
+
+ /*
+ * clear cached UN address
+ */
+ if (!vpn_bi || !vpn_bi->extra) {
+ zlog_warn(
+ "%s: missing VPN bi/extra, can't clear UN addr",
+ __func__);
+ return 1;
+ }
+ vpn_bi->extra->vnc.import.un_family = 0;
+ memset(&vpn_bi->extra->vnc.import.un, 0,
+ sizeof(vpn_bi->extra->vnc.import.un));
+ if (CHECK_FLAG(vpn_bi->flags, BGP_INFO_VALID)) {
+ if (rfapiGetVncTunnelUnAddr(vpn_bi->attr, NULL)) {
+ UNSET_FLAG(vpn_bi->flags, BGP_INFO_VALID);
+ if (VALID_INTERIOR_TYPE(vpn_bi->type))
+ RFAPI_MONITOR_EXTERIOR(vpn_rn)
+ ->valid_interior_count--;
+ /* signal interior route withdrawal to
+ * import-exterior */
+ vnc_import_bgp_exterior_del_route_interior(
+ bgp_get_default(), import_table, vpn_rn,
+ vpn_bi);
+ }
+ }
+
+ } else {
+ if (!vpn_bi) {
+ zlog_warn("%s: missing VPN bi, can't clear UN addr",
+ __func__);
+ return 1;
+ }
+ rfapiCopyUnEncap2VPN(encap_bi, vpn_bi);
+ if (!CHECK_FLAG(vpn_bi->flags, BGP_INFO_VALID)) {
+ SET_FLAG(vpn_bi->flags, BGP_INFO_VALID);
+ if (VALID_INTERIOR_TYPE(vpn_bi->type))
+ RFAPI_MONITOR_EXTERIOR(vpn_rn)
+ ->valid_interior_count++;
+ /* signal interior route withdrawal to import-exterior
+ */
+ vnc_import_bgp_exterior_add_route_interior(
+ bgp_get_default(), import_table, vpn_rn,
+ vpn_bi);
+ }
+ }
+ return 0;
}
-static int
-rfapiWithdrawTimerEncap (struct thread *t)
+static int rfapiWithdrawTimerEncap(struct thread *t)
{
- struct rfapi_withdraw *wcb = t->arg;
- struct bgp_info *bi = wcb->info;
- int was_first_route = 0;
- struct rfapi_monitor_encap *em;
- struct skiplist *vpn_node_sl = skiplist_new (0, NULL, NULL);
-
- assert (wcb->node);
- assert (bi);
- assert (wcb->import_table);
-
- RFAPI_CHECK_REFCOUNT (wcb->node, SAFI_ENCAP, 0);
-
- if (wcb->node->info == bi)
- was_first_route = 1;
-
- /*
- * Remove the route/bi and free it
- */
- rfapiBgpInfoDetach (wcb->node, bi);
- rfapiBgpInfoFree (bi);
-
- if (!was_first_route)
- goto done;
-
- for (em = RFAPI_MONITOR_ENCAP (wcb->node); em; em = em->next)
- {
-
- /*
- * Update monitoring VPN BIs with new encap info at the
- * head of the encap bi chain (which could be NULL after
- * removing the expiring bi above)
- */
- if (rfapiWithdrawEncapUpdateCachedUn
- (wcb->import_table, wcb->node->info, em->node, em->bi))
- continue;
-
- /*
- * Build a list of unique VPN nodes referenced by these monitors.
- * Use a skiplist for speed.
- */
- skiplist_insert (vpn_node_sl, em->node, em->node);
- }
-
-
- /*
- * for each VPN node referenced in the ENCAP monitors:
- */
- struct route_node *rn;
- while (!skiplist_first (vpn_node_sl, (void **) &rn, NULL))
- {
- if (!wcb->node->info)
- {
- struct rfapi_monitor_vpn *moved;
-
- moved = rfapiMonitorMoveShorter (rn, 0);
- if (moved)
- {
- //rfapiDoRouteCallback(wcb->import_table, moved->node, moved);
- rfapiMonitorMovedUp (wcb->import_table, rn, moved->node, moved);
- }
- }
- else
- {
- //rfapiDoRouteCallback(wcb->import_table, rn, NULL);
- rfapiMonitorItNodeChanged (wcb->import_table, rn, NULL);
- }
- skiplist_delete_first (vpn_node_sl);
- }
+ struct rfapi_withdraw *wcb = t->arg;
+ struct bgp_info *bi = wcb->info;
+ int was_first_route = 0;
+ struct rfapi_monitor_encap *em;
+ struct skiplist *vpn_node_sl = skiplist_new(0, NULL, NULL);
+
+ assert(wcb->node);
+ assert(bi);
+ assert(wcb->import_table);
+
+ RFAPI_CHECK_REFCOUNT(wcb->node, SAFI_ENCAP, 0);
+
+ if (wcb->node->info == bi)
+ was_first_route = 1;
+
+ /*
+ * Remove the route/bi and free it
+ */
+ rfapiBgpInfoDetach(wcb->node, bi);
+ rfapiBgpInfoFree(bi);
+
+ if (!was_first_route)
+ goto done;
+
+ for (em = RFAPI_MONITOR_ENCAP(wcb->node); em; em = em->next) {
+
+ /*
+ * Update monitoring VPN BIs with new encap info at the
+ * head of the encap bi chain (which could be NULL after
+ * removing the expiring bi above)
+ */
+ if (rfapiWithdrawEncapUpdateCachedUn(wcb->import_table,
+ wcb->node->info, em->node,
+ em->bi))
+ continue;
+
+ /*
+ * Build a list of unique VPN nodes referenced by these
+ * monitors.
+ * Use a skiplist for speed.
+ */
+ skiplist_insert(vpn_node_sl, em->node, em->node);
+ }
+
+
+ /*
+ * for each VPN node referenced in the ENCAP monitors:
+ */
+ struct route_node *rn;
+ while (!skiplist_first(vpn_node_sl, (void **)&rn, NULL)) {
+ if (!wcb->node->info) {
+ struct rfapi_monitor_vpn *moved;
+
+ moved = rfapiMonitorMoveShorter(rn, 0);
+ if (moved) {
+ // rfapiDoRouteCallback(wcb->import_table,
+ // moved->node, moved);
+ rfapiMonitorMovedUp(wcb->import_table, rn,
+ moved->node, moved);
+ }
+ } else {
+ // rfapiDoRouteCallback(wcb->import_table, rn, NULL);
+ rfapiMonitorItNodeChanged(wcb->import_table, rn, NULL);
+ }
+ skiplist_delete_first(vpn_node_sl);
+ }
done:
- RFAPI_CHECK_REFCOUNT (wcb->node, SAFI_ENCAP, 1);
- route_unlock_node (wcb->node); /* decr ref count */
- XFREE (MTYPE_RFAPI_WITHDRAW, wcb);
- skiplist_free (vpn_node_sl);
- return 0;
+ RFAPI_CHECK_REFCOUNT(wcb->node, SAFI_ENCAP, 1);
+ route_unlock_node(wcb->node); /* decr ref count */
+ XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
+ skiplist_free(vpn_node_sl);
+ return 0;
}
@@ -2965,1391 +2793,1272 @@ done:
* in each case
*/
static void
-rfapiBiStartWithdrawTimer (
- struct rfapi_import_table *import_table,
- struct route_node *rn,
- struct bgp_info *bi,
- afi_t afi,
- safi_t safi,
- int (*timer_service_func) (struct thread *))
+rfapiBiStartWithdrawTimer(struct rfapi_import_table *import_table,
+ struct route_node *rn, struct bgp_info *bi, afi_t afi,
+ safi_t safi,
+ int (*timer_service_func)(struct thread *))
{
- uint32_t lifetime;
- struct rfapi_withdraw *wcb;
-
- if CHECK_FLAG
- (bi->flags, BGP_INFO_REMOVED)
- {
- /*
- * Already on the path to being withdrawn,
- * should already have a timer set up to
- * delete it.
- */
- vnc_zlog_debug_verbose ("%s: already being withdrawn, do nothing", __func__);
- return;
- }
-
- rfapiGetVncLifetime (bi->attr, &lifetime);
- vnc_zlog_debug_verbose ("%s: VNC lifetime is %u", __func__, lifetime);
-
- /*
- * withdrawn routes get to hang around for a while
- */
- SET_FLAG (bi->flags, BGP_INFO_REMOVED);
-
- /* set timer to remove the route later */
- lifetime = rfapiGetHolddownFromLifetime (lifetime);
- vnc_zlog_debug_verbose ("%s: using timeout %u", __func__, lifetime);
-
- /*
- * Stash import_table, node, and info for use by timer
- * service routine, which is supposed to free the wcb.
- */
- wcb = XCALLOC (MTYPE_RFAPI_WITHDRAW, sizeof (struct rfapi_withdraw));
- assert (wcb);
- wcb->node = rn;
- wcb->info = bi;
- wcb->import_table = import_table;
- bgp_attr_intern (bi->attr);
-
- if (VNC_DEBUG(VERBOSE))
- {
- vnc_zlog_debug_verbose
- ("%s: wcb values: node=%p, info=%p, import_table=%p (bi follows)",
- __func__, wcb->node, wcb->info, wcb->import_table);
- rfapiPrintBi (NULL, bi);
- }
-
-
- assert (bi->extra);
- if (lifetime > UINT32_MAX / 1001)
- {
- /* sub-optimal case, but will probably never happen */
- bi->extra->vnc.import.timer = NULL;
- thread_add_timer(bm->master, timer_service_func, wcb, lifetime,
- &bi->extra->vnc.import.timer);
- }
- else
- {
- static uint32_t jitter;
- uint32_t lifetime_msec;
-
- /*
- * the goal here is to spread out the timers so they are
- * sortable in the skip list
- */
- if (++jitter >= 1000)
- jitter = 0;
-
- lifetime_msec = (lifetime * 1000) + jitter;
-
- bi->extra->vnc.import.timer = NULL;
- thread_add_timer_msec(bm->master, timer_service_func, wcb, lifetime_msec,
- &bi->extra->vnc.import.timer);
- }
-
- /* re-sort route list (BGP_INFO_REMOVED routes are last) */
- if (((struct bgp_info *) rn->info)->next)
- {
- rfapiBgpInfoDetach (rn, bi);
- rfapiBgpInfoAttachSorted (rn, bi, afi, safi);
- }
+ uint32_t lifetime;
+ struct rfapi_withdraw *wcb;
+
+ if
+ CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)
+ {
+ /*
+ * Already on the path to being withdrawn,
+ * should already have a timer set up to
+ * delete it.
+ */
+ vnc_zlog_debug_verbose(
+ "%s: already being withdrawn, do nothing",
+ __func__);
+ return;
+ }
+
+ rfapiGetVncLifetime(bi->attr, &lifetime);
+ vnc_zlog_debug_verbose("%s: VNC lifetime is %u", __func__, lifetime);
+
+ /*
+ * withdrawn routes get to hang around for a while
+ */
+ SET_FLAG(bi->flags, BGP_INFO_REMOVED);
+
+ /* set timer to remove the route later */
+ lifetime = rfapiGetHolddownFromLifetime(lifetime);
+ vnc_zlog_debug_verbose("%s: using timeout %u", __func__, lifetime);
+
+ /*
+ * Stash import_table, node, and info for use by timer
+ * service routine, which is supposed to free the wcb.
+ */
+ wcb = XCALLOC(MTYPE_RFAPI_WITHDRAW, sizeof(struct rfapi_withdraw));
+ assert(wcb);
+ wcb->node = rn;
+ wcb->info = bi;
+ wcb->import_table = import_table;
+ bgp_attr_intern(bi->attr);
+
+ if (VNC_DEBUG(VERBOSE)) {
+ vnc_zlog_debug_verbose(
+ "%s: wcb values: node=%p, info=%p, import_table=%p (bi follows)",
+ __func__, wcb->node, wcb->info, wcb->import_table);
+ rfapiPrintBi(NULL, bi);
+ }
+
+
+ assert(bi->extra);
+ if (lifetime > UINT32_MAX / 1001) {
+ /* sub-optimal case, but will probably never happen */
+ bi->extra->vnc.import.timer = NULL;
+ thread_add_timer(bm->master, timer_service_func, wcb, lifetime,
+ &bi->extra->vnc.import.timer);
+ } else {
+ static uint32_t jitter;
+ uint32_t lifetime_msec;
+
+ /*
+ * the goal here is to spread out the timers so they are
+ * sortable in the skip list
+ */
+ if (++jitter >= 1000)
+ jitter = 0;
+
+ lifetime_msec = (lifetime * 1000) + jitter;
+
+ bi->extra->vnc.import.timer = NULL;
+ thread_add_timer_msec(bm->master, timer_service_func, wcb,
+ lifetime_msec,
+ &bi->extra->vnc.import.timer);
+ }
+
+ /* re-sort route list (BGP_INFO_REMOVED routes are last) */
+ if (((struct bgp_info *)rn->info)->next) {
+ rfapiBgpInfoDetach(rn, bi);
+ rfapiBgpInfoAttachSorted(rn, bi, afi, safi);
+ }
}
-typedef void (rfapi_bi_filtered_import_f) (struct rfapi_import_table *,
- int,
- struct peer *,
- void *,
- struct prefix *,
- struct prefix *,
- afi_t,
- struct prefix_rd *,
- struct attr *,
- u_char, u_char, uint32_t *);
+typedef void(rfapi_bi_filtered_import_f)(struct rfapi_import_table *, int,
+ struct peer *, void *, struct prefix *,
+ struct prefix *, afi_t,
+ struct prefix_rd *, struct attr *,
+ u_char, u_char, uint32_t *);
-static void
-rfapiExpireEncapNow (
- struct rfapi_import_table *it,
- struct route_node *rn,
- struct bgp_info *bi)
+static void rfapiExpireEncapNow(struct rfapi_import_table *it,
+ struct route_node *rn, struct bgp_info *bi)
{
- struct rfapi_withdraw *wcb;
- struct thread t;
-
- /*
- * pretend we're an expiring timer
- */
- wcb = XCALLOC (MTYPE_RFAPI_WITHDRAW, sizeof (struct rfapi_withdraw));
- wcb->info = bi;
- wcb->node = rn;
- wcb->import_table = it;
- memset (&t, 0, sizeof (t));
- t.arg = wcb;
- rfapiWithdrawTimerEncap (&t); /* frees wcb */
+ struct rfapi_withdraw *wcb;
+ struct thread t;
+
+ /*
+ * pretend we're an expiring timer
+ */
+ wcb = XCALLOC(MTYPE_RFAPI_WITHDRAW, sizeof(struct rfapi_withdraw));
+ wcb->info = bi;
+ wcb->node = rn;
+ wcb->import_table = it;
+ memset(&t, 0, sizeof(t));
+ t.arg = wcb;
+ rfapiWithdrawTimerEncap(&t); /* frees wcb */
}
-static int
-rfapiGetNexthop (struct attr *attr, struct prefix *prefix)
+static int rfapiGetNexthop(struct attr *attr, struct prefix *prefix)
{
- switch (BGP_MP_NEXTHOP_FAMILY (attr->mp_nexthop_len))
- {
- case AF_INET:
- prefix->family = AF_INET;
- prefix->prefixlen = 32;
- prefix->u.prefix4 = attr->mp_nexthop_global_in;
- break;
- case AF_INET6:
- prefix->family = AF_INET6;
- prefix->prefixlen = 128;
- prefix->u.prefix6 = attr->mp_nexthop_global;
- break;
- default:
- vnc_zlog_debug_verbose ("%s: unknown attr->mp_nexthop_len %d", __func__,
- attr->mp_nexthop_len);
- return EINVAL;
- }
- return 0;
+ switch (BGP_MP_NEXTHOP_FAMILY(attr->mp_nexthop_len)) {
+ case AF_INET:
+ prefix->family = AF_INET;
+ prefix->prefixlen = 32;
+ prefix->u.prefix4 = attr->mp_nexthop_global_in;
+ break;
+ case AF_INET6:
+ prefix->family = AF_INET6;
+ prefix->prefixlen = 128;
+ prefix->u.prefix6 = attr->mp_nexthop_global;
+ break;
+ default:
+ vnc_zlog_debug_verbose("%s: unknown attr->mp_nexthop_len %d",
+ __func__, attr->mp_nexthop_len);
+ return EINVAL;
+ }
+ return 0;
}
-/*
+/*
* import a bgp_info if its route target list intersects with the
* import table's route target list
*/
-static void
-rfapiBgpInfoFilteredImportEncap (
- 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, /* Unused for encap routes */
- 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 */
+static void rfapiBgpInfoFilteredImportEncap(
+ 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, /* Unused for encap routes */
+ 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 */
{
- struct route_table *rt = NULL;
- struct route_node *rn;
- struct bgp_info *info_new;
- struct bgp_info *bi;
- struct bgp_info *next;
- char buf[BUFSIZ];
-
- struct prefix p_firstbi_old;
- struct prefix p_firstbi_new;
- int replacing = 0;
- const char *action_str = NULL;
- struct prefix un_prefix;
-
- struct bgp *bgp;
- bgp = bgp_get_default (); /* assume 1 instance for now */
-
- switch (action)
- {
- case FIF_ACTION_UPDATE:
- action_str = "update";
- break;
- case FIF_ACTION_WITHDRAW:
- action_str = "withdraw";
- break;
- case FIF_ACTION_KILL:
- action_str = "kill";
- break;
- default:
- assert (0);
- break;
- }
-
- vnc_zlog_debug_verbose ("%s: entry: %s: prefix %s/%d", __func__,
- action_str,
- inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen);
-
- memset (&p_firstbi_old, 0, sizeof (p_firstbi_old));
- memset (&p_firstbi_new, 0, sizeof (p_firstbi_new));
-
- if (action == FIF_ACTION_UPDATE)
- {
- /*
- * Compare rt lists. If no intersection, don't import this route
- * On a withdraw, peer and RD are sufficient to determine if
- * we should act.
- */
- if (!attr || !attr->ecommunity)
- {
-
- vnc_zlog_debug_verbose ("%s: attr, extra, or ecommunity missing, not importing",
- __func__);
- return;
- }
+ struct route_table *rt = NULL;
+ struct route_node *rn;
+ struct bgp_info *info_new;
+ struct bgp_info *bi;
+ struct bgp_info *next;
+ char buf[BUFSIZ];
+
+ struct prefix p_firstbi_old;
+ struct prefix p_firstbi_new;
+ int replacing = 0;
+ const char *action_str = NULL;
+ struct prefix un_prefix;
+
+ struct bgp *bgp;
+ bgp = bgp_get_default(); /* assume 1 instance for now */
+
+ switch (action) {
+ case FIF_ACTION_UPDATE:
+ action_str = "update";
+ break;
+ case FIF_ACTION_WITHDRAW:
+ action_str = "withdraw";
+ break;
+ case FIF_ACTION_KILL:
+ action_str = "kill";
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ vnc_zlog_debug_verbose(
+ "%s: entry: %s: prefix %s/%d", __func__, action_str,
+ inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen);
+
+ memset(&p_firstbi_old, 0, sizeof(p_firstbi_old));
+ memset(&p_firstbi_new, 0, sizeof(p_firstbi_new));
+
+ if (action == FIF_ACTION_UPDATE) {
+ /*
+ * Compare rt lists. If no intersection, don't import this route
+ * On a withdraw, peer and RD are sufficient to determine if
+ * we should act.
+ */
+ if (!attr || !attr->ecommunity) {
+
+ vnc_zlog_debug_verbose(
+ "%s: attr, extra, or ecommunity missing, not importing",
+ __func__);
+ return;
+ }
#if RFAPI_REQUIRE_ENCAP_BEEC
- if (!rfapiEcommunitiesMatchBeec (attr->ecommunity))
- {
- vnc_zlog_debug_verbose ("%s: it=%p: no match for BGP Encapsulation ecommunity",
- __func__, import_table);
- return;
- }
+ if (!rfapiEcommunitiesMatchBeec(attr->ecommunity)) {
+ vnc_zlog_debug_verbose(
+ "%s: it=%p: no match for BGP Encapsulation ecommunity",
+ __func__, import_table);
+ return;
+ }
#endif
- if (!rfapiEcommunitiesIntersect (import_table->rt_import_list,
- attr->ecommunity))
- {
-
- vnc_zlog_debug_verbose ("%s: it=%p: no ecommunity intersection",
- __func__, import_table);
- return;
- }
-
- /*
- * Updates must also have a nexthop address
- */
- memset (&un_prefix, 0, sizeof (un_prefix)); /* keep valgrind happy */
- if (rfapiGetNexthop (attr, &un_prefix))
- {
- vnc_zlog_debug_verbose ("%s: missing nexthop address", __func__);
- return;
- }
- }
-
- /*
- * Figure out which radix tree the route would go into
- */
- switch (afi)
- {
- case AFI_IP:
- case AFI_IP6:
- rt = import_table->imported_encap[afi];
- break;
-
- default:
- zlog_err ("%s: bad afi %d", __func__, afi);
- return;
- }
-
- /*
- * route_node_lookup returns a node only if there is at least
- * one route attached.
- */
- rn = route_node_lookup (rt, p);
+ if (!rfapiEcommunitiesIntersect(import_table->rt_import_list,
+ attr->ecommunity)) {
+
+ vnc_zlog_debug_verbose(
+ "%s: it=%p: no ecommunity intersection",
+ __func__, import_table);
+ return;
+ }
+
+ /*
+ * Updates must also have a nexthop address
+ */
+ memset(&un_prefix, 0,
+ sizeof(un_prefix)); /* keep valgrind happy */
+ if (rfapiGetNexthop(attr, &un_prefix)) {
+ vnc_zlog_debug_verbose("%s: missing nexthop address",
+ __func__);
+ return;
+ }
+ }
+
+ /*
+ * Figure out which radix tree the route would go into
+ */
+ switch (afi) {
+ case AFI_IP:
+ case AFI_IP6:
+ rt = import_table->imported_encap[afi];
+ break;
+
+ default:
+ zlog_err("%s: bad afi %d", __func__, afi);
+ return;
+ }
+
+ /*
+ * route_node_lookup returns a node only if there is at least
+ * one route attached.
+ */
+ rn = route_node_lookup(rt, p);
#if DEBUG_ENCAP_MONITOR
- vnc_zlog_debug_verbose ("%s: initial encap lookup(it=%p) rn=%p",
- __func__, import_table, rn);
+ vnc_zlog_debug_verbose("%s: initial encap lookup(it=%p) rn=%p",
+ __func__, import_table, rn);
#endif
- if (rn)
- {
-
- RFAPI_CHECK_REFCOUNT (rn, SAFI_ENCAP, 1);
- route_unlock_node (rn); /* undo lock in route_node_lookup */
-
-
- /*
- * capture nexthop of first bi
- */
- if (rn->info)
- {
- rfapiNexthop2Prefix (((struct bgp_info *) (rn->info))->attr,
- &p_firstbi_old);
- }
-
- for (bi = rn->info; bi; bi = bi->next)
- {
-
- /*
- * Does this bgp_info refer to the same route
- * as we are trying to add?
- */
- vnc_zlog_debug_verbose ("%s: comparing BI %p", __func__, bi);
-
-
- /*
- * Compare RDs
- *
- * RD of import table bi is in bi->extra->vnc.import.rd
- * RD of info_orig is in prd
- */
- if (!bi->extra)
- {
- vnc_zlog_debug_verbose ("%s: no bi->extra", __func__);
- continue;
- }
- if (prefix_cmp ((struct prefix *) &bi->extra->vnc.import.rd,
- (struct prefix *) prd))
- {
-
- vnc_zlog_debug_verbose ("%s: prd does not match", __func__);
- continue;
- }
-
- /*
- * Compare peers
- */
- if (bi->peer != peer)
- {
- vnc_zlog_debug_verbose ("%s: peer does not match", __func__);
- continue;
- }
-
- vnc_zlog_debug_verbose ("%s: found matching bi", __func__);
-
- /* Same route. Delete this bi, replace with new one */
-
- if (action == FIF_ACTION_WITHDRAW)
- {
-
- vnc_zlog_debug_verbose ("%s: withdrawing at prefix %s/%d",
- __func__,
- inet_ntop (rn->p.family, &rn->p.u.prefix, buf,
- BUFSIZ), rn->p.prefixlen);
-
- rfapiBiStartWithdrawTimer (import_table, rn, bi,
- afi, SAFI_ENCAP,
- rfapiWithdrawTimerEncap);
-
- }
- else
- {
- vnc_zlog_debug_verbose ("%s: %s at prefix %s/%d",
- __func__,
- ((action ==
- FIF_ACTION_KILL) ? "killing" : "replacing"),
- inet_ntop (rn->p.family, &rn->p.u.prefix, buf,
- BUFSIZ), rn->p.prefixlen);
-
- /*
- * If this route is waiting to be deleted because of
- * a previous withdraw, we must cancel its timer.
- */
- if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)
- && bi->extra->vnc.import.timer)
- {
-
- struct thread *t =
- (struct thread *) bi->extra->vnc.import.timer;
- struct rfapi_withdraw *wcb = t->arg;
-
- XFREE (MTYPE_RFAPI_WITHDRAW, wcb);
- thread_cancel (t);
- }
-
- if (action == FIF_ACTION_UPDATE)
- {
- rfapiBgpInfoDetach (rn, bi);
- rfapiBgpInfoFree (bi);
- replacing = 1;
- }
- else
- {
- /*
- * Kill: do export stuff when removing bi
- */
- struct rfapi_withdraw *wcb;
- struct thread t;
-
- /*
- * pretend we're an expiring timer
- */
- wcb =
- XCALLOC (MTYPE_RFAPI_WITHDRAW,
- sizeof (struct rfapi_withdraw));
- wcb->info = bi;
- wcb->node = rn;
- wcb->import_table = import_table;
- memset (&t, 0, sizeof (t));
- t.arg = wcb;
- rfapiWithdrawTimerEncap (&t); /* frees wcb */
- }
- }
-
- break;
- }
- }
-
- if (rn)
- RFAPI_CHECK_REFCOUNT (rn, SAFI_ENCAP, replacing ? 1 : 0);
-
- if (action == FIF_ACTION_WITHDRAW || action == FIF_ACTION_KILL)
- return;
-
- info_new = rfapiBgpInfoCreate (attr, peer, rfd, prd, type, sub_type, NULL);
-
- if (rn)
- {
- if (!replacing)
- route_lock_node (rn); /* incr ref count for new BI */
- }
- else
- {
- rn = route_node_get (rt, p);
- }
-
- vnc_zlog_debug_verbose ("%s: (afi=%d, rn=%p) inserting at prefix %s/%d",
- __func__,
- afi,
- rn,
- inet_ntop (rn->p.family, &rn->p.u.prefix, buf, BUFSIZ),
- rn->p.prefixlen);
-
- rfapiBgpInfoAttachSorted (rn, info_new, afi, SAFI_ENCAP);
-
- /*
- * Delete holddown routes from same NVE. See details in
- * rfapiBgpInfoFilteredImportVPN()
- */
- for (bi = info_new->next; bi; bi = next)
- {
-
- struct prefix pfx_un;
- int un_match = 0;
-
- next = bi->next;
- if (!CHECK_FLAG (bi->flags, BGP_INFO_REMOVED))
- continue;
-
- /*
- * We already match the VN address (it is the prefix
- * of the route node)
- */
-
- if (!rfapiGetNexthop (bi->attr, &pfx_un) &&
- prefix_same (&pfx_un, &un_prefix))
- {
-
- un_match = 1;
- }
-
- if (!un_match)
- continue;
-
- vnc_zlog_debug_verbose ("%s: removing holddown bi matching NVE of new route",
- __func__);
- if (bi->extra->vnc.import.timer)
- {
- struct thread *t = (struct thread *) bi->extra->vnc.import.timer;
- struct rfapi_withdraw *wcb = t->arg;
-
- XFREE (MTYPE_RFAPI_WITHDRAW, wcb);
- thread_cancel (t);
- }
- rfapiExpireEncapNow (import_table, rn, bi);
- }
-
- rfapiNexthop2Prefix (((struct bgp_info *) (rn->info))->attr,
- &p_firstbi_new);
-
- /*
- * If the nexthop address of the selected Encap route (i.e.,
- * the UN address) has changed, then we must update the VPN
- * routes that refer to this Encap route and possibly force
- * rfapi callbacks.
- */
- if (rfapiAttrNexthopAddrDifferent (&p_firstbi_old, &p_firstbi_new))
- {
-
- struct rfapi_monitor_encap *m;
- struct rfapi_monitor_encap *mnext;
-
- struct route_node *referenced_vpn_prefix;
-
- /*
- * Optimized approach: build radix tree on the fly to
- * hold list of VPN nodes referenced by the ENCAP monitors
- *
- * The nodes in this table correspond to prefixes of VPN routes.
- * The "info" pointer of the node points to a chain of
- * struct rfapi_monitor_encap, each of which refers to a
- * specific VPN node.
- */
- struct route_table *referenced_vpn_table;
-
- referenced_vpn_table = route_table_init ();
- assert (referenced_vpn_table);
-
- /*
- * iterate over the set of monitors at this ENCAP node.
- */
+ if (rn) {
+
+ RFAPI_CHECK_REFCOUNT(rn, SAFI_ENCAP, 1);
+ route_unlock_node(rn); /* undo lock in route_node_lookup */
+
+
+ /*
+ * capture nexthop of first bi
+ */
+ if (rn->info) {
+ rfapiNexthop2Prefix(
+ ((struct bgp_info *)(rn->info))->attr,
+ &p_firstbi_old);
+ }
+
+ for (bi = rn->info; bi; bi = bi->next) {
+
+ /*
+ * Does this bgp_info refer to the same route
+ * as we are trying to add?
+ */
+ vnc_zlog_debug_verbose("%s: comparing BI %p", __func__,
+ bi);
+
+
+ /*
+ * Compare RDs
+ *
+ * RD of import table bi is in bi->extra->vnc.import.rd
+ * RD of info_orig is in prd
+ */
+ if (!bi->extra) {
+ vnc_zlog_debug_verbose("%s: no bi->extra",
+ __func__);
+ continue;
+ }
+ if (prefix_cmp(
+ (struct prefix *)&bi->extra->vnc.import.rd,
+ (struct prefix *)prd)) {
+
+ vnc_zlog_debug_verbose("%s: prd does not match",
+ __func__);
+ continue;
+ }
+
+ /*
+ * Compare peers
+ */
+ if (bi->peer != peer) {
+ vnc_zlog_debug_verbose(
+ "%s: peer does not match", __func__);
+ continue;
+ }
+
+ vnc_zlog_debug_verbose("%s: found matching bi",
+ __func__);
+
+ /* Same route. Delete this bi, replace with new one */
+
+ if (action == FIF_ACTION_WITHDRAW) {
+
+ vnc_zlog_debug_verbose(
+ "%s: withdrawing at prefix %s/%d",
+ __func__,
+ inet_ntop(rn->p.family, &rn->p.u.prefix,
+ buf, BUFSIZ),
+ rn->p.prefixlen);
+
+ rfapiBiStartWithdrawTimer(
+ import_table, rn, bi, afi, SAFI_ENCAP,
+ rfapiWithdrawTimerEncap);
+
+ } else {
+ vnc_zlog_debug_verbose(
+ "%s: %s at prefix %s/%d", __func__,
+ ((action == FIF_ACTION_KILL)
+ ? "killing"
+ : "replacing"),
+ inet_ntop(rn->p.family, &rn->p.u.prefix,
+ buf, BUFSIZ),
+ rn->p.prefixlen);
+
+ /*
+ * If this route is waiting to be deleted
+ * because of
+ * a previous withdraw, we must cancel its
+ * timer.
+ */
+ if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)
+ && bi->extra->vnc.import.timer) {
+
+ struct thread *t =
+ (struct thread *)bi->extra->vnc
+ .import.timer;
+ struct rfapi_withdraw *wcb = t->arg;
+
+ XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
+ thread_cancel(t);
+ }
+
+ if (action == FIF_ACTION_UPDATE) {
+ rfapiBgpInfoDetach(rn, bi);
+ rfapiBgpInfoFree(bi);
+ replacing = 1;
+ } else {
+ /*
+ * Kill: do export stuff when removing
+ * bi
+ */
+ struct rfapi_withdraw *wcb;
+ struct thread t;
+
+ /*
+ * pretend we're an expiring timer
+ */
+ wcb = XCALLOC(
+ MTYPE_RFAPI_WITHDRAW,
+ sizeof(struct rfapi_withdraw));
+ wcb->info = bi;
+ wcb->node = rn;
+ wcb->import_table = import_table;
+ memset(&t, 0, sizeof(t));
+ t.arg = wcb;
+ rfapiWithdrawTimerEncap(
+ &t); /* frees wcb */
+ }
+ }
+
+ break;
+ }
+ }
+
+ if (rn)
+ RFAPI_CHECK_REFCOUNT(rn, SAFI_ENCAP, replacing ? 1 : 0);
+
+ if (action == FIF_ACTION_WITHDRAW || action == FIF_ACTION_KILL)
+ return;
+
+ info_new =
+ rfapiBgpInfoCreate(attr, peer, rfd, prd, type, sub_type, NULL);
+
+ if (rn) {
+ if (!replacing)
+ route_lock_node(rn); /* incr ref count for new BI */
+ } else {
+ rn = route_node_get(rt, p);
+ }
+
+ vnc_zlog_debug_verbose(
+ "%s: (afi=%d, rn=%p) inserting at prefix %s/%d", __func__, afi,
+ rn, inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ),
+ rn->p.prefixlen);
+
+ rfapiBgpInfoAttachSorted(rn, info_new, afi, SAFI_ENCAP);
+
+ /*
+ * Delete holddown routes from same NVE. See details in
+ * rfapiBgpInfoFilteredImportVPN()
+ */
+ for (bi = info_new->next; bi; bi = next) {
+
+ struct prefix pfx_un;
+ int un_match = 0;
+
+ next = bi->next;
+ if (!CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
+ continue;
+
+ /*
+ * We already match the VN address (it is the prefix
+ * of the route node)
+ */
+
+ if (!rfapiGetNexthop(bi->attr, &pfx_un)
+ && prefix_same(&pfx_un, &un_prefix)) {
+
+ un_match = 1;
+ }
+
+ if (!un_match)
+ continue;
+
+ vnc_zlog_debug_verbose(
+ "%s: removing holddown bi matching NVE of new route",
+ __func__);
+ if (bi->extra->vnc.import.timer) {
+ struct thread *t =
+ (struct thread *)bi->extra->vnc.import.timer;
+ struct rfapi_withdraw *wcb = t->arg;
+
+ XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
+ thread_cancel(t);
+ }
+ rfapiExpireEncapNow(import_table, rn, bi);
+ }
+
+ rfapiNexthop2Prefix(((struct bgp_info *)(rn->info))->attr,
+ &p_firstbi_new);
+
+ /*
+ * If the nexthop address of the selected Encap route (i.e.,
+ * the UN address) has changed, then we must update the VPN
+ * routes that refer to this Encap route and possibly force
+ * rfapi callbacks.
+ */
+ if (rfapiAttrNexthopAddrDifferent(&p_firstbi_old, &p_firstbi_new)) {
+
+ struct rfapi_monitor_encap *m;
+ struct rfapi_monitor_encap *mnext;
+
+ struct route_node *referenced_vpn_prefix;
+
+ /*
+ * Optimized approach: build radix tree on the fly to
+ * hold list of VPN nodes referenced by the ENCAP monitors
+ *
+ * The nodes in this table correspond to prefixes of VPN routes.
+ * The "info" pointer of the node points to a chain of
+ * struct rfapi_monitor_encap, each of which refers to a
+ * specific VPN node.
+ */
+ struct route_table *referenced_vpn_table;
+
+ referenced_vpn_table = route_table_init();
+ assert(referenced_vpn_table);
+
+/*
+ * iterate over the set of monitors at this ENCAP node.
+ */
#if DEBUG_ENCAP_MONITOR
- vnc_zlog_debug_verbose ("%s: examining monitors at rn=%p", __func__, rn);
+ vnc_zlog_debug_verbose("%s: examining monitors at rn=%p",
+ __func__, rn);
#endif
- for (m = RFAPI_MONITOR_ENCAP (rn); m; m = m->next)
- {
-
- /*
- * For each referenced bi/route, copy the ENCAP route's
- * nexthop to the VPN route's cached UN address field and set
- * the address family of the cached UN address field.
- */
- rfapiCopyUnEncap2VPN (info_new, m->bi);
- if (!CHECK_FLAG (m->bi->flags, BGP_INFO_VALID))
- {
- SET_FLAG (m->bi->flags, BGP_INFO_VALID);
- if (VALID_INTERIOR_TYPE (m->bi->type))
- RFAPI_MONITOR_EXTERIOR (m->node)->valid_interior_count++;
- vnc_import_bgp_exterior_add_route_interior (bgp,
- import_table,
- m->node, m->bi);
- }
-
- /*
- * Build a list of unique VPN nodes referenced by these monitors
- *
- * There could be more than one VPN node here with a given
- * prefix. Those are currently in an unsorted linear list
- * per prefix.
- */
-
- referenced_vpn_prefix =
- route_node_get (referenced_vpn_table, &m->node->p);
- assert (referenced_vpn_prefix);
- for (mnext = referenced_vpn_prefix->info; mnext;
- mnext = mnext->next)
- {
-
- if (mnext->node == m->node)
- break;
- }
-
- if (mnext)
- {
- /*
- * already have an entry for this VPN node
- */
- route_unlock_node (referenced_vpn_prefix);
- }
- else
- {
- mnext = XCALLOC (MTYPE_RFAPI_MONITOR_ENCAP,
- sizeof (struct rfapi_monitor_encap));
- assert (mnext);
- mnext->node = m->node;
- mnext->next = referenced_vpn_prefix->info;
- referenced_vpn_prefix->info = mnext;
- }
-
- }
-
- /*
- * for each VPN node referenced in the ENCAP monitors:
- */
- for (referenced_vpn_prefix = route_top (referenced_vpn_table);
- referenced_vpn_prefix;
- referenced_vpn_prefix = route_next (referenced_vpn_prefix))
- {
-
- while ((m = referenced_vpn_prefix->info))
- {
-
- struct route_node *n;
-
- rfapiMonitorMoveLonger (m->node);
- for (n = m->node; n; n = n->parent)
- {
- //rfapiDoRouteCallback(import_table, n, NULL);
- }
- rfapiMonitorItNodeChanged (import_table, m->node, NULL);
-
- referenced_vpn_prefix->info = m->next;
- route_unlock_node (referenced_vpn_prefix);
- XFREE (MTYPE_RFAPI_MONITOR_ENCAP, m);
- }
-
- }
- route_table_finish (referenced_vpn_table);
- }
-
- RFAPI_CHECK_REFCOUNT (rn, SAFI_ENCAP, 0);
+ for (m = RFAPI_MONITOR_ENCAP(rn); m; m = m->next) {
+
+ /*
+ * For each referenced bi/route, copy the ENCAP route's
+ * nexthop to the VPN route's cached UN address field
+ * and set
+ * the address family of the cached UN address field.
+ */
+ rfapiCopyUnEncap2VPN(info_new, m->bi);
+ if (!CHECK_FLAG(m->bi->flags, BGP_INFO_VALID)) {
+ SET_FLAG(m->bi->flags, BGP_INFO_VALID);
+ if (VALID_INTERIOR_TYPE(m->bi->type))
+ RFAPI_MONITOR_EXTERIOR(m->node)
+ ->valid_interior_count++;
+ vnc_import_bgp_exterior_add_route_interior(
+ bgp, import_table, m->node, m->bi);
+ }
+
+ /*
+ * Build a list of unique VPN nodes referenced by these
+ * monitors
+ *
+ * There could be more than one VPN node here with a
+ * given
+ * prefix. Those are currently in an unsorted linear
+ * list
+ * per prefix.
+ */
+
+ referenced_vpn_prefix = route_node_get(
+ referenced_vpn_table, &m->node->p);
+ assert(referenced_vpn_prefix);
+ for (mnext = referenced_vpn_prefix->info; mnext;
+ mnext = mnext->next) {
+
+ if (mnext->node == m->node)
+ break;
+ }
+
+ if (mnext) {
+ /*
+ * already have an entry for this VPN node
+ */
+ route_unlock_node(referenced_vpn_prefix);
+ } else {
+ mnext = XCALLOC(
+ MTYPE_RFAPI_MONITOR_ENCAP,
+ sizeof(struct rfapi_monitor_encap));
+ assert(mnext);
+ mnext->node = m->node;
+ mnext->next = referenced_vpn_prefix->info;
+ referenced_vpn_prefix->info = mnext;
+ }
+ }
+
+ /*
+ * for each VPN node referenced in the ENCAP monitors:
+ */
+ for (referenced_vpn_prefix = route_top(referenced_vpn_table);
+ referenced_vpn_prefix; referenced_vpn_prefix = route_next(
+ referenced_vpn_prefix)) {
+
+ while ((m = referenced_vpn_prefix->info)) {
+
+ struct route_node *n;
+
+ rfapiMonitorMoveLonger(m->node);
+ for (n = m->node; n; n = n->parent) {
+ // rfapiDoRouteCallback(import_table, n,
+ // NULL);
+ }
+ rfapiMonitorItNodeChanged(import_table, m->node,
+ NULL);
+
+ referenced_vpn_prefix->info = m->next;
+ route_unlock_node(referenced_vpn_prefix);
+ XFREE(MTYPE_RFAPI_MONITOR_ENCAP, m);
+ }
+ }
+ route_table_finish(referenced_vpn_table);
+ }
+
+ RFAPI_CHECK_REFCOUNT(rn, SAFI_ENCAP, 0);
}
-static void
-rfapiExpireVpnNow (
- struct rfapi_import_table *it,
- struct route_node *rn,
- struct bgp_info *bi,
- int lockoffset)
+static void rfapiExpireVpnNow(struct rfapi_import_table *it,
+ struct route_node *rn, struct bgp_info *bi,
+ int lockoffset)
{
- struct rfapi_withdraw *wcb;
- struct thread t;
-
- /*
- * pretend we're an expiring timer
- */
- wcb = XCALLOC (MTYPE_RFAPI_WITHDRAW, sizeof (struct rfapi_withdraw));
- wcb->info = bi;
- wcb->node = rn;
- wcb->import_table = it;
- wcb->lockoffset = lockoffset;
- memset (&t, 0, sizeof (t));
- t.arg = wcb;
- rfapiWithdrawTimerVPN (&t); /* frees wcb */
+ struct rfapi_withdraw *wcb;
+ struct thread t;
+
+ /*
+ * pretend we're an expiring timer
+ */
+ wcb = XCALLOC(MTYPE_RFAPI_WITHDRAW, sizeof(struct rfapi_withdraw));
+ wcb->info = bi;
+ wcb->node = rn;
+ wcb->import_table = it;
+ wcb->lockoffset = lockoffset;
+ memset(&t, 0, sizeof(t));
+ t.arg = wcb;
+ rfapiWithdrawTimerVPN(&t); /* frees wcb */
}
-/*
+/*
* import a bgp_info if its route target list intersects with the
* import table's route target list
*/
-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_L2VPN: 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 */
+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_L2VPN: 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 */
{
- struct route_table *rt = NULL;
- struct route_node *rn;
- struct route_node *n;
- struct bgp_info *info_new;
- struct bgp_info *bi;
- struct bgp_info *next;
- char buf[BUFSIZ];
- struct prefix vn_prefix;
- struct prefix un_prefix;
- int un_prefix_valid = 0;
- struct route_node *ern;
- int replacing = 0;
- int original_had_routes = 0;
- struct prefix original_nexthop;
- const char *action_str = NULL;
- int is_it_ce = 0;
-
- struct bgp *bgp;
- bgp = bgp_get_default (); /* assume 1 instance for now */
-
- switch (action)
- {
- case FIF_ACTION_UPDATE:
- action_str = "update";
- break;
- case FIF_ACTION_WITHDRAW:
- action_str = "withdraw";
- break;
- case FIF_ACTION_KILL:
- action_str = "kill";
- break;
- default:
- assert (0);
- break;
- }
-
- if (import_table == bgp->rfapi->it_ce)
- is_it_ce = 1;
-
- vnc_zlog_debug_verbose ("%s: entry: %s%s: prefix %s/%d: it %p, afi %s", __func__,
- (is_it_ce ? "CE-IT " : ""),
- action_str,
- rfapi_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
- p->prefixlen, import_table, afi2str (afi));
-
- VNC_ITRCCK;
-
- /*
- * Compare rt lists. If no intersection, don't import this route
- * On a withdraw, peer and RD are sufficient to determine if
- * we should act.
- */
- if (action == FIF_ACTION_UPDATE)
- {
- if (!attr || !attr->ecommunity)
- {
-
- vnc_zlog_debug_verbose ("%s: attr, extra, or ecommunity missing, not importing",
- __func__);
- return;
- }
- if ((import_table != bgp->rfapi->it_ce) &&
- !rfapiEcommunitiesIntersect (import_table->rt_import_list,
- attr->ecommunity))
- {
-
- vnc_zlog_debug_verbose ("%s: it=%p: no ecommunity intersection",
- __func__, import_table);
- return;
- }
-
- memset (&vn_prefix, 0, sizeof (vn_prefix)); /* keep valgrind happy */
- if (rfapiGetNexthop (attr, &vn_prefix))
- {
- /* missing nexthop address would be a bad, bad thing */
- vnc_zlog_debug_verbose ("%s: missing nexthop", __func__);
- return;
- }
- }
-
- /*
- * Figure out which radix tree the route would go into
- */
- switch (afi)
- {
- case AFI_IP:
- case AFI_IP6:
- case AFI_L2VPN:
- rt = import_table->imported_vpn[afi];
- break;
-
- default:
- zlog_err ("%s: bad afi %d", __func__, afi);
- return;
- }
-
- /* clear it */
- memset (&original_nexthop, 0, sizeof (original_nexthop));
-
- /*
- * route_node_lookup returns a node only if there is at least
- * one route attached.
- */
- rn = route_node_lookup (rt, p);
-
- vnc_zlog_debug_verbose ("%s: rn=%p", __func__, rn);
-
- if (rn)
- {
-
- RFAPI_CHECK_REFCOUNT (rn, SAFI_MPLS_VPN, 1);
- route_unlock_node (rn); /* undo lock in route_node_lookup */
-
- if (rn->info)
- original_had_routes = 1;
-
- if (VNC_DEBUG(VERBOSE))
- {
- vnc_zlog_debug_verbose ("%s: showing IT node on entry", __func__);
- rfapiShowItNode (NULL, rn); /* debug */
- }
-
- /*
- * Look for same route (will have same RD and peer)
- */
- bi = rfapiItBiIndexSearch (rn, prd, peer, aux_prefix);
-
- if (bi)
- {
-
- /*
- * This was an old test when we iterated over the
- * BIs linearly. Since we're now looking up with
- * RD and peer, comparing types should not be
- * needed. Changed to assertion.
- *
- * Compare types. Doing so prevents a RFP-originated
- * route from matching an imported route, for example.
- */
- assert (bi->type == type);
-
- vnc_zlog_debug_verbose ("%s: found matching bi", __func__);
-
- /*
- * In the special CE table, withdrawals occur without holddown
- */
- if (import_table == bgp->rfapi->it_ce)
- {
- vnc_direct_bgp_del_route_ce (bgp, rn, bi);
- if (action == FIF_ACTION_WITHDRAW)
- action = FIF_ACTION_KILL;
- }
-
- if (action == FIF_ACTION_WITHDRAW)
- {
-
- int washolddown = CHECK_FLAG (bi->flags, BGP_INFO_REMOVED);
-
- vnc_zlog_debug_verbose ("%s: withdrawing at prefix %s/%d%s",
- __func__,
- rfapi_ntop (rn->p.family, &rn->p.u.prefix, buf,
- BUFSIZ), rn->p.prefixlen,
- (washolddown ? " (already being withdrawn)" : ""));
-
- VNC_ITRCCK;
- if (!washolddown)
- {
- rfapiBiStartWithdrawTimer (import_table, rn, bi,
- afi, SAFI_MPLS_VPN,
- rfapiWithdrawTimerVPN);
-
- RFAPI_UPDATE_ITABLE_COUNT (bi, import_table, afi, -1);
- import_table->holddown_count[afi] += 1;
- }
- VNC_ITRCCK;
- }
- else
- {
- vnc_zlog_debug_verbose ("%s: %s at prefix %s/%d",
- __func__,
- ((action ==
- FIF_ACTION_KILL) ? "killing" : "replacing"),
- rfapi_ntop (rn->p.family, &rn->p.u.prefix, buf,
- BUFSIZ), rn->p.prefixlen);
-
- /*
- * If this route is waiting to be deleted because of
- * a previous withdraw, we must cancel its timer.
- */
- if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED) &&
- bi->extra->vnc.import.timer)
- {
-
- struct thread *t =
- (struct thread *) bi->extra->vnc.import.timer;
- struct rfapi_withdraw *wcb = t->arg;
-
- XFREE (MTYPE_RFAPI_WITHDRAW, wcb);
- thread_cancel (t);
-
- import_table->holddown_count[afi] -= 1;
- RFAPI_UPDATE_ITABLE_COUNT (bi, import_table, afi, 1);
- }
- /*
- * decrement remote count (if route is remote) because
- * we are going to remove it below
- */
- RFAPI_UPDATE_ITABLE_COUNT (bi, import_table, afi, -1);
- if (action == FIF_ACTION_UPDATE)
- {
- replacing = 1;
-
- /*
- * make copy of original nexthop so we can see if it changed
- */
- rfapiGetNexthop (bi->attr, &original_nexthop);
-
- /*
- * remove bi without doing any export processing
- */
- if (CHECK_FLAG (bi->flags, BGP_INFO_VALID)
- && VALID_INTERIOR_TYPE (bi->type))
- RFAPI_MONITOR_EXTERIOR (rn)->valid_interior_count--;
- rfapiItBiIndexDel (rn, bi);
- rfapiBgpInfoDetach (rn, bi);
- rfapiMonitorEncapDelete (bi);
- vnc_import_bgp_exterior_del_route_interior (bgp,
- import_table,
- rn, bi);
- rfapiBgpInfoFree (bi);
- }
- else
- {
- /* Kill */
- /*
- * remove bi and do export processing
- */
- import_table->holddown_count[afi] += 1;
- rfapiExpireVpnNow (import_table, rn, bi, 0);
- }
-
- }
- }
-
- }
-
- if (rn)
- RFAPI_CHECK_REFCOUNT (rn, SAFI_MPLS_VPN, replacing ? 1 : 0);
-
- if (action == FIF_ACTION_WITHDRAW || action == FIF_ACTION_KILL)
- {
- VNC_ITRCCK;
- return;
- }
-
- info_new = rfapiBgpInfoCreate (attr, peer, rfd, prd, type, sub_type, label);
-
- /*
- * lookup un address in encap table
- */
- ern = route_node_match (import_table->imported_encap[afi], &vn_prefix);
- if (ern)
- {
- rfapiCopyUnEncap2VPN (ern->info, info_new);
- route_unlock_node (ern); /* undo lock in route_note_match */
- }
- else
- {
- char buf[BUFSIZ];
- prefix2str (&vn_prefix, buf, sizeof (buf));
- buf[BUFSIZ - 1] = 0;
- /* Not a big deal, just means VPN route got here first */
- vnc_zlog_debug_verbose ("%s: no encap route for vn addr %s", __func__, buf);
- info_new->extra->vnc.import.un_family = 0;
- }
-
- if (rn)
- {
- if (!replacing)
- route_lock_node (rn);
- }
- else
- {
- /*
- * No need to increment reference count, so only "get"
- * if the node is not there already
- */
- rn = route_node_get (rt, p);
- }
-
- /*
- * For ethernet routes, if there is an accompanying IP address,
- * save it in the bi
- */
- if ((AFI_L2VPN == afi) && aux_prefix)
- {
-
- vnc_zlog_debug_verbose ("%s: setting BI's aux_prefix", __func__);
- info_new->extra->vnc.import.aux_prefix = *aux_prefix;
- }
-
- vnc_zlog_debug_verbose ("%s: inserting bi %p at prefix %s/%d #%d",
- __func__,
- info_new,
- rfapi_ntop (rn->p.family, &rn->p.u.prefix, buf, BUFSIZ),
- rn->p.prefixlen, rn->lock);
-
- rfapiBgpInfoAttachSorted (rn, info_new, afi, SAFI_MPLS_VPN);
- rfapiItBiIndexAdd (rn, info_new);
- if (!rfapiGetUnAddrOfVpnBi (info_new, NULL))
- {
- if (VALID_INTERIOR_TYPE (info_new->type))
- RFAPI_MONITOR_EXTERIOR (rn)->valid_interior_count++;
- SET_FLAG (info_new->flags, BGP_INFO_VALID);
- }
- RFAPI_UPDATE_ITABLE_COUNT (info_new, import_table, afi, 1);
- vnc_import_bgp_exterior_add_route_interior (bgp, import_table, rn,
- info_new);
-
- if (import_table == bgp->rfapi->it_ce)
- vnc_direct_bgp_add_route_ce (bgp, rn, info_new);
-
- if (VNC_DEBUG(VERBOSE))
- {
- vnc_zlog_debug_verbose ("%s: showing IT node", __func__);
- rfapiShowItNode (NULL, rn); /* debug */
- }
-
- rfapiMonitorEncapAdd (import_table, &vn_prefix, rn, info_new);
-
- if (!rfapiGetUnAddrOfVpnBi (info_new, &un_prefix))
- {
-
- /*
- * if we have a valid UN address (either via Encap route
- * or via tunnel attribute), then we should attempt
- * to move any monitors at less-specific nodes to this node
- */
- rfapiMonitorMoveLonger (rn);
-
- un_prefix_valid = 1;
-
- }
-
- /*
- * 101129 Enhancement: if we add a route (implication: it is not
- * in holddown), delete all other routes from this nve at this
- * node that are in holddown, regardless of peer.
- *
- * Reasons it's OK to do that:
- *
- * - if the holddown route being deleted originally came from BGP VPN,
- * it is already gone from BGP (implication of holddown), so there
- * won't be any added inconsistency with the BGP RIB.
- *
- * - once a fresh route is added at a prefix, any routes in holddown
- * at that prefix will not show up in RFP responses, so deleting
- * the holddown routes won't affect the contents of responses.
- *
- * - lifetimes are supposed to be consistent, so there should not
- * be a case where the fresh route has a shorter lifetime than
- * the holddown route, so we don't expect the fresh route to
- * disappear and complete its holddown time before the existing
- * holddown routes time out. Therefore, we won't have a situation
- * where we expect the existing holddown routes to be hidden and
- * then to reappear sometime later (as holddown routes) in a
- * RFP response.
- *
- * Among other things, this would enable us to skirt the problem
- * of local holddown routes that refer to NVE descriptors that
- * have already been closed (if the same NVE triggers a subsequent
- * rfapi_open(), the new peer is different and doesn't match the
- * peer of the holddown route, so the stale holddown route still
- * hangs around until it times out instead of just being replaced
- * by the fresh route).
- */
- /*
- * We know that the new bi will have been inserted before any routes
- * in holddown, so we can skip any that came before it
- */
- for (bi = info_new->next; bi; bi = next)
- {
-
- struct prefix pfx_vn;
- struct prefix pfx_un;
- int un_match = 0;
- int remote_peer_match = 0;
-
- next = bi->next;
-
- /*
- * Must be holddown
- */
- if (!CHECK_FLAG (bi->flags, BGP_INFO_REMOVED))
- continue;
-
- /*
- * Must match VN address (nexthop of VPN route)
- */
- if (rfapiGetNexthop (bi->attr, &pfx_vn))
- continue;
- if (!prefix_same (&pfx_vn, &vn_prefix))
- continue;
-
- if (un_prefix_valid && /* new route UN addr */
- !rfapiGetUnAddrOfVpnBi (bi, &pfx_un) && /* old route UN addr */
- prefix_same (&pfx_un, &un_prefix))
- { /* compare */
- un_match = 1;
- }
- if (!RFAPI_LOCAL_BI (bi) && !RFAPI_LOCAL_BI (info_new) &&
- sockunion_same (&bi->peer->su, &info_new->peer->su))
- {
- /* old & new are both remote, same peer */
- remote_peer_match = 1;
- }
-
- if (!un_match & !remote_peer_match)
- continue;
-
- vnc_zlog_debug_verbose ("%s: removing holddown bi matching NVE of new route",
- __func__);
- if (bi->extra->vnc.import.timer)
- {
- struct thread *t = (struct thread *) bi->extra->vnc.import.timer;
- struct rfapi_withdraw *wcb = t->arg;
-
- XFREE (MTYPE_RFAPI_WITHDRAW, wcb);
- thread_cancel (t);
- }
- rfapiExpireVpnNow (import_table, rn, bi, 0);
- }
-
- if (!original_had_routes)
- {
- /*
- * We went from 0 usable routes to 1 usable route. Perform the
- * "Adding a Route" export process.
- */
- vnc_direct_bgp_add_prefix (bgp, import_table, rn);
- vnc_zebra_add_prefix (bgp, import_table, rn);
- }
- else
- {
- /*
- * Check for nexthop change event
- * Note: the prefix_same() test below detects two situations:
- * 1. route is replaced, new route has different nexthop
- * 2. new route is added (original_nexthop is 0)
- */
- struct prefix new_nexthop;
-
- rfapiGetNexthop (attr, &new_nexthop);
- if (!prefix_same (&original_nexthop, &new_nexthop))
- {
- /*
- * nexthop change event
- * vnc_direct_bgp_add_prefix() will recompute VN addr ecommunity
- */
- vnc_direct_bgp_add_prefix (bgp, import_table, rn);
- }
- }
-
- if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE))
- {
- for (n = rn; n; n = n->parent)
- {
- //rfapiDoRouteCallback(import_table, n, NULL);
- }
- rfapiMonitorItNodeChanged (import_table, rn, NULL);
- }
- RFAPI_CHECK_REFCOUNT (rn, SAFI_MPLS_VPN, 0);
- VNC_ITRCCK;
+ struct route_table *rt = NULL;
+ struct route_node *rn;
+ struct route_node *n;
+ struct bgp_info *info_new;
+ struct bgp_info *bi;
+ struct bgp_info *next;
+ char buf[BUFSIZ];
+ struct prefix vn_prefix;
+ struct prefix un_prefix;
+ int un_prefix_valid = 0;
+ struct route_node *ern;
+ int replacing = 0;
+ int original_had_routes = 0;
+ struct prefix original_nexthop;
+ const char *action_str = NULL;
+ int is_it_ce = 0;
+
+ struct bgp *bgp;
+ bgp = bgp_get_default(); /* assume 1 instance for now */
+
+ switch (action) {
+ case FIF_ACTION_UPDATE:
+ action_str = "update";
+ break;
+ case FIF_ACTION_WITHDRAW:
+ action_str = "withdraw";
+ break;
+ case FIF_ACTION_KILL:
+ action_str = "kill";
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ if (import_table == bgp->rfapi->it_ce)
+ is_it_ce = 1;
+
+ vnc_zlog_debug_verbose("%s: entry: %s%s: prefix %s/%d: it %p, afi %s",
+ __func__, (is_it_ce ? "CE-IT " : ""), action_str,
+ rfapi_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
+ p->prefixlen, import_table, afi2str(afi));
+
+ VNC_ITRCCK;
+
+ /*
+ * Compare rt lists. If no intersection, don't import this route
+ * On a withdraw, peer and RD are sufficient to determine if
+ * we should act.
+ */
+ if (action == FIF_ACTION_UPDATE) {
+ if (!attr || !attr->ecommunity) {
+
+ vnc_zlog_debug_verbose(
+ "%s: attr, extra, or ecommunity missing, not importing",
+ __func__);
+ return;
+ }
+ if ((import_table != bgp->rfapi->it_ce)
+ && !rfapiEcommunitiesIntersect(import_table->rt_import_list,
+ attr->ecommunity)) {
+
+ vnc_zlog_debug_verbose(
+ "%s: it=%p: no ecommunity intersection",
+ __func__, import_table);
+ return;
+ }
+
+ memset(&vn_prefix, 0,
+ sizeof(vn_prefix)); /* keep valgrind happy */
+ if (rfapiGetNexthop(attr, &vn_prefix)) {
+ /* missing nexthop address would be a bad, bad thing */
+ vnc_zlog_debug_verbose("%s: missing nexthop", __func__);
+ return;
+ }
+ }
+
+ /*
+ * Figure out which radix tree the route would go into
+ */
+ switch (afi) {
+ case AFI_IP:
+ case AFI_IP6:
+ case AFI_L2VPN:
+ rt = import_table->imported_vpn[afi];
+ break;
+
+ default:
+ zlog_err("%s: bad afi %d", __func__, afi);
+ return;
+ }
+
+ /* clear it */
+ memset(&original_nexthop, 0, sizeof(original_nexthop));
+
+ /*
+ * route_node_lookup returns a node only if there is at least
+ * one route attached.
+ */
+ rn = route_node_lookup(rt, p);
+
+ vnc_zlog_debug_verbose("%s: rn=%p", __func__, rn);
+
+ if (rn) {
+
+ RFAPI_CHECK_REFCOUNT(rn, SAFI_MPLS_VPN, 1);
+ route_unlock_node(rn); /* undo lock in route_node_lookup */
+
+ if (rn->info)
+ original_had_routes = 1;
+
+ if (VNC_DEBUG(VERBOSE)) {
+ vnc_zlog_debug_verbose("%s: showing IT node on entry",
+ __func__);
+ rfapiShowItNode(NULL, rn); /* debug */
+ }
+
+ /*
+ * Look for same route (will have same RD and peer)
+ */
+ bi = rfapiItBiIndexSearch(rn, prd, peer, aux_prefix);
+
+ if (bi) {
+
+ /*
+ * This was an old test when we iterated over the
+ * BIs linearly. Since we're now looking up with
+ * RD and peer, comparing types should not be
+ * needed. Changed to assertion.
+ *
+ * Compare types. Doing so prevents a RFP-originated
+ * route from matching an imported route, for example.
+ */
+ assert(bi->type == type);
+
+ vnc_zlog_debug_verbose("%s: found matching bi",
+ __func__);
+
+ /*
+ * In the special CE table, withdrawals occur without
+ * holddown
+ */
+ if (import_table == bgp->rfapi->it_ce) {
+ vnc_direct_bgp_del_route_ce(bgp, rn, bi);
+ if (action == FIF_ACTION_WITHDRAW)
+ action = FIF_ACTION_KILL;
+ }
+
+ if (action == FIF_ACTION_WITHDRAW) {
+
+ int washolddown =
+ CHECK_FLAG(bi->flags, BGP_INFO_REMOVED);
+
+ vnc_zlog_debug_verbose(
+ "%s: withdrawing at prefix %s/%d%s",
+ __func__, rfapi_ntop(rn->p.family,
+ &rn->p.u.prefix,
+ buf, BUFSIZ),
+ rn->p.prefixlen,
+ (washolddown
+ ? " (already being withdrawn)"
+ : ""));
+
+ VNC_ITRCCK;
+ if (!washolddown) {
+ rfapiBiStartWithdrawTimer(
+ import_table, rn, bi, afi,
+ SAFI_MPLS_VPN,
+ rfapiWithdrawTimerVPN);
+
+ RFAPI_UPDATE_ITABLE_COUNT(
+ bi, import_table, afi, -1);
+ import_table->holddown_count[afi] += 1;
+ }
+ VNC_ITRCCK;
+ } else {
+ vnc_zlog_debug_verbose(
+ "%s: %s at prefix %s/%d", __func__,
+ ((action == FIF_ACTION_KILL)
+ ? "killing"
+ : "replacing"),
+ rfapi_ntop(rn->p.family,
+ &rn->p.u.prefix, buf,
+ BUFSIZ),
+ rn->p.prefixlen);
+
+ /*
+ * If this route is waiting to be deleted
+ * because of
+ * a previous withdraw, we must cancel its
+ * timer.
+ */
+ if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)
+ && bi->extra->vnc.import.timer) {
+
+ struct thread *t =
+ (struct thread *)bi->extra->vnc
+ .import.timer;
+ struct rfapi_withdraw *wcb = t->arg;
+
+ XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
+ thread_cancel(t);
+
+ import_table->holddown_count[afi] -= 1;
+ RFAPI_UPDATE_ITABLE_COUNT(
+ bi, import_table, afi, 1);
+ }
+ /*
+ * decrement remote count (if route is remote)
+ * because
+ * we are going to remove it below
+ */
+ RFAPI_UPDATE_ITABLE_COUNT(bi, import_table, afi,
+ -1);
+ if (action == FIF_ACTION_UPDATE) {
+ replacing = 1;
+
+ /*
+ * make copy of original nexthop so we
+ * can see if it changed
+ */
+ rfapiGetNexthop(bi->attr,
+ &original_nexthop);
+
+ /*
+ * remove bi without doing any export
+ * processing
+ */
+ if (CHECK_FLAG(bi->flags,
+ BGP_INFO_VALID)
+ && VALID_INTERIOR_TYPE(bi->type))
+ RFAPI_MONITOR_EXTERIOR(rn)
+ ->valid_interior_count--;
+ rfapiItBiIndexDel(rn, bi);
+ rfapiBgpInfoDetach(rn, bi);
+ rfapiMonitorEncapDelete(bi);
+ vnc_import_bgp_exterior_del_route_interior(
+ bgp, import_table, rn, bi);
+ rfapiBgpInfoFree(bi);
+ } else {
+ /* Kill */
+ /*
+ * remove bi and do export processing
+ */
+ import_table->holddown_count[afi] += 1;
+ rfapiExpireVpnNow(import_table, rn, bi,
+ 0);
+ }
+ }
+ }
+ }
+
+ if (rn)
+ RFAPI_CHECK_REFCOUNT(rn, SAFI_MPLS_VPN, replacing ? 1 : 0);
+
+ if (action == FIF_ACTION_WITHDRAW || action == FIF_ACTION_KILL) {
+ VNC_ITRCCK;
+ return;
+ }
+
+ info_new =
+ rfapiBgpInfoCreate(attr, peer, rfd, prd, type, sub_type, label);
+
+ /*
+ * lookup un address in encap table
+ */
+ ern = route_node_match(import_table->imported_encap[afi], &vn_prefix);
+ if (ern) {
+ rfapiCopyUnEncap2VPN(ern->info, info_new);
+ route_unlock_node(ern); /* undo lock in route_note_match */
+ } else {
+ char buf[BUFSIZ];
+ prefix2str(&vn_prefix, buf, sizeof(buf));
+ buf[BUFSIZ - 1] = 0;
+ /* Not a big deal, just means VPN route got here first */
+ vnc_zlog_debug_verbose("%s: no encap route for vn addr %s",
+ __func__, buf);
+ info_new->extra->vnc.import.un_family = 0;
+ }
+
+ if (rn) {
+ if (!replacing)
+ route_lock_node(rn);
+ } else {
+ /*
+ * No need to increment reference count, so only "get"
+ * if the node is not there already
+ */
+ rn = route_node_get(rt, p);
+ }
+
+ /*
+ * For ethernet routes, if there is an accompanying IP address,
+ * save it in the bi
+ */
+ if ((AFI_L2VPN == afi) && aux_prefix) {
+
+ vnc_zlog_debug_verbose("%s: setting BI's aux_prefix", __func__);
+ info_new->extra->vnc.import.aux_prefix = *aux_prefix;
+ }
+
+ vnc_zlog_debug_verbose(
+ "%s: inserting bi %p at prefix %s/%d #%d", __func__, info_new,
+ rfapi_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ),
+ rn->p.prefixlen, rn->lock);
+
+ rfapiBgpInfoAttachSorted(rn, info_new, afi, SAFI_MPLS_VPN);
+ rfapiItBiIndexAdd(rn, info_new);
+ if (!rfapiGetUnAddrOfVpnBi(info_new, NULL)) {
+ if (VALID_INTERIOR_TYPE(info_new->type))
+ RFAPI_MONITOR_EXTERIOR(rn)->valid_interior_count++;
+ SET_FLAG(info_new->flags, BGP_INFO_VALID);
+ }
+ RFAPI_UPDATE_ITABLE_COUNT(info_new, import_table, afi, 1);
+ vnc_import_bgp_exterior_add_route_interior(bgp, import_table, rn,
+ info_new);
+
+ if (import_table == bgp->rfapi->it_ce)
+ vnc_direct_bgp_add_route_ce(bgp, rn, info_new);
+
+ if (VNC_DEBUG(VERBOSE)) {
+ vnc_zlog_debug_verbose("%s: showing IT node", __func__);
+ rfapiShowItNode(NULL, rn); /* debug */
+ }
+
+ rfapiMonitorEncapAdd(import_table, &vn_prefix, rn, info_new);
+
+ if (!rfapiGetUnAddrOfVpnBi(info_new, &un_prefix)) {
+
+ /*
+ * if we have a valid UN address (either via Encap route
+ * or via tunnel attribute), then we should attempt
+ * to move any monitors at less-specific nodes to this node
+ */
+ rfapiMonitorMoveLonger(rn);
+
+ un_prefix_valid = 1;
+ }
+
+ /*
+ * 101129 Enhancement: if we add a route (implication: it is not
+ * in holddown), delete all other routes from this nve at this
+ * node that are in holddown, regardless of peer.
+ *
+ * Reasons it's OK to do that:
+ *
+ * - if the holddown route being deleted originally came from BGP VPN,
+ * it is already gone from BGP (implication of holddown), so there
+ * won't be any added inconsistency with the BGP RIB.
+ *
+ * - once a fresh route is added at a prefix, any routes in holddown
+ * at that prefix will not show up in RFP responses, so deleting
+ * the holddown routes won't affect the contents of responses.
+ *
+ * - lifetimes are supposed to be consistent, so there should not
+ * be a case where the fresh route has a shorter lifetime than
+ * the holddown route, so we don't expect the fresh route to
+ * disappear and complete its holddown time before the existing
+ * holddown routes time out. Therefore, we won't have a situation
+ * where we expect the existing holddown routes to be hidden and
+ * then to reappear sometime later (as holddown routes) in a
+ * RFP response.
+ *
+ * Among other things, this would enable us to skirt the problem
+ * of local holddown routes that refer to NVE descriptors that
+ * have already been closed (if the same NVE triggers a subsequent
+ * rfapi_open(), the new peer is different and doesn't match the
+ * peer of the holddown route, so the stale holddown route still
+ * hangs around until it times out instead of just being replaced
+ * by the fresh route).
+ */
+ /*
+ * We know that the new bi will have been inserted before any routes
+ * in holddown, so we can skip any that came before it
+ */
+ for (bi = info_new->next; bi; bi = next) {
+
+ struct prefix pfx_vn;
+ struct prefix pfx_un;
+ int un_match = 0;
+ int remote_peer_match = 0;
+
+ next = bi->next;
+
+ /*
+ * Must be holddown
+ */
+ if (!CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
+ continue;
+
+ /*
+ * Must match VN address (nexthop of VPN route)
+ */
+ if (rfapiGetNexthop(bi->attr, &pfx_vn))
+ continue;
+ if (!prefix_same(&pfx_vn, &vn_prefix))
+ continue;
+
+ if (un_prefix_valid && /* new route UN addr */
+ !rfapiGetUnAddrOfVpnBi(bi, &pfx_un)
+ && /* old route UN addr */
+ prefix_same(&pfx_un, &un_prefix)) { /* compare */
+ un_match = 1;
+ }
+ if (!RFAPI_LOCAL_BI(bi) && !RFAPI_LOCAL_BI(info_new)
+ && sockunion_same(&bi->peer->su, &info_new->peer->su)) {
+ /* old & new are both remote, same peer */
+ remote_peer_match = 1;
+ }
+
+ if (!un_match & !remote_peer_match)
+ continue;
+
+ vnc_zlog_debug_verbose(
+ "%s: removing holddown bi matching NVE of new route",
+ __func__);
+ if (bi->extra->vnc.import.timer) {
+ struct thread *t =
+ (struct thread *)bi->extra->vnc.import.timer;
+ struct rfapi_withdraw *wcb = t->arg;
+
+ XFREE(MTYPE_RFAPI_WITHDRAW, wcb);
+ thread_cancel(t);
+ }
+ rfapiExpireVpnNow(import_table, rn, bi, 0);
+ }
+
+ if (!original_had_routes) {
+ /*
+ * We went from 0 usable routes to 1 usable route. Perform the
+ * "Adding a Route" export process.
+ */
+ vnc_direct_bgp_add_prefix(bgp, import_table, rn);
+ vnc_zebra_add_prefix(bgp, import_table, rn);
+ } else {
+ /*
+ * Check for nexthop change event
+ * Note: the prefix_same() test below detects two situations:
+ * 1. route is replaced, new route has different nexthop
+ * 2. new route is added (original_nexthop is 0)
+ */
+ struct prefix new_nexthop;
+
+ rfapiGetNexthop(attr, &new_nexthop);
+ if (!prefix_same(&original_nexthop, &new_nexthop)) {
+ /*
+ * nexthop change event
+ * vnc_direct_bgp_add_prefix() will recompute VN addr
+ * ecommunity
+ */
+ vnc_direct_bgp_add_prefix(bgp, import_table, rn);
+ }
+ }
+
+ if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) {
+ for (n = rn; n; n = n->parent) {
+ // rfapiDoRouteCallback(import_table, n, NULL);
+ }
+ rfapiMonitorItNodeChanged(import_table, rn, NULL);
+ }
+ RFAPI_CHECK_REFCOUNT(rn, SAFI_MPLS_VPN, 0);
+ VNC_ITRCCK;
}
static rfapi_bi_filtered_import_f *
-rfapiBgpInfoFilteredImportFunction (safi_t safi)
+rfapiBgpInfoFilteredImportFunction(safi_t safi)
{
- switch (safi)
- {
- case SAFI_MPLS_VPN:
- return rfapiBgpInfoFilteredImportVPN;
-
- case SAFI_ENCAP:
- return rfapiBgpInfoFilteredImportEncap;
- }
- zlog_err ("%s: bad safi %d", __func__, safi);
- return NULL;
+ switch (safi) {
+ case SAFI_MPLS_VPN:
+ return rfapiBgpInfoFilteredImportVPN;
+
+ case SAFI_ENCAP:
+ return rfapiBgpInfoFilteredImportEncap;
+ }
+ zlog_err("%s: bad safi %d", __func__, safi);
+ return NULL;
}
-void
-rfapiProcessUpdate (
- struct peer *peer,
- void *rfd, /* set when looped from RFP/RFAPI */
- 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)
+void rfapiProcessUpdate(struct peer *peer,
+ void *rfd, /* set when looped from RFP/RFAPI */
+ 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)
{
- struct bgp *bgp;
- struct rfapi *h;
- struct rfapi_import_table *it;
- int has_ip_route = 1;
- uint32_t lni = 0;
-
- bgp = bgp_get_default (); /* assume 1 instance for now */
- assert (bgp);
-
- h = bgp->rfapi;
- assert (h);
-
- /*
- * look at high-order byte of RD. FF means MAC
- * address is present (VNC L2VPN)
- */
- if ((safi == SAFI_MPLS_VPN) &&
- (decode_rd_type(prd->val) == RD_TYPE_VNC_ETH))
- {
- struct prefix pfx_mac_buf;
- struct prefix pfx_nexthop_buf;
- int rc;
-
- /*
- * Set flag if prefix and nexthop are the same - don't
- * add the route to normal IP-based import tables
- */
- if (!rfapiGetNexthop (attr, &pfx_nexthop_buf))
- {
- if (!prefix_cmp (&pfx_nexthop_buf, p))
- {
- has_ip_route = 0;
- }
- }
-
- memset (&pfx_mac_buf, 0, sizeof (pfx_mac_buf));
- pfx_mac_buf.family = AF_ETHERNET;
- pfx_mac_buf.prefixlen = 48;
- memcpy (&pfx_mac_buf.u.prefix_eth.octet, prd->val + 2, 6);
-
- /*
- * Find rt containing LNI (Logical Network ID), which
- * _should_ always be present when mac address is present
- */
- rc = rfapiEcommunityGetLNI (attr->ecommunity, &lni);
-
- vnc_zlog_debug_verbose
- ("%s: rfapiEcommunityGetLNI returned %d, lni=%d, attr=%p",
- __func__, rc, lni, attr);
- if (attr && !rc)
- {
- it = rfapiMacImportTableGet (bgp, lni);
-
- rfapiBgpInfoFilteredImportVPN (
- it,
- FIF_ACTION_UPDATE,
- peer,
- rfd,
- &pfx_mac_buf, /* prefix */
- p, /* aux prefix: IP addr */
- AFI_L2VPN,
- prd,
- attr,
- type,
- sub_type,
- label);
- }
-
- }
-
- if (!has_ip_route)
- return;
-
- /*
- * Iterate over all import tables; do a filtered import
- * for the afi/safi combination
- */
- for (it = h->imports; it; it = it->next)
- {
- (*rfapiBgpInfoFilteredImportFunction (safi)) (
- it,
- FIF_ACTION_UPDATE,
- peer,
- rfd,
- p, /* prefix */
- NULL,
- afi,
- prd,
- attr,
- type,
- sub_type,
- label);
- }
-
- if (safi == SAFI_MPLS_VPN)
- {
- vnc_direct_bgp_rh_add_route (bgp, afi, p, peer, attr);
- }
-
- if (safi == SAFI_MPLS_VPN)
- {
- rfapiBgpInfoFilteredImportVPN (
- bgp->rfapi->it_ce,
- FIF_ACTION_UPDATE,
- peer,
- rfd,
- p, /* prefix */
- NULL,
- afi,
- prd,
- attr,
- type,
- sub_type,
- label);
- }
+ struct bgp *bgp;
+ struct rfapi *h;
+ struct rfapi_import_table *it;
+ int has_ip_route = 1;
+ uint32_t lni = 0;
+
+ bgp = bgp_get_default(); /* assume 1 instance for now */
+ assert(bgp);
+
+ h = bgp->rfapi;
+ assert(h);
+
+ /*
+ * look at high-order byte of RD. FF means MAC
+ * address is present (VNC L2VPN)
+ */
+ if ((safi == SAFI_MPLS_VPN)
+ && (decode_rd_type(prd->val) == RD_TYPE_VNC_ETH)) {
+ struct prefix pfx_mac_buf;
+ struct prefix pfx_nexthop_buf;
+ int rc;
+
+ /*
+ * Set flag if prefix and nexthop are the same - don't
+ * add the route to normal IP-based import tables
+ */
+ if (!rfapiGetNexthop(attr, &pfx_nexthop_buf)) {
+ if (!prefix_cmp(&pfx_nexthop_buf, p)) {
+ has_ip_route = 0;
+ }
+ }
+
+ memset(&pfx_mac_buf, 0, sizeof(pfx_mac_buf));
+ pfx_mac_buf.family = AF_ETHERNET;
+ pfx_mac_buf.prefixlen = 48;
+ memcpy(&pfx_mac_buf.u.prefix_eth.octet, prd->val + 2, 6);
+
+ /*
+ * Find rt containing LNI (Logical Network ID), which
+ * _should_ always be present when mac address is present
+ */
+ rc = rfapiEcommunityGetLNI(attr->ecommunity, &lni);
+
+ vnc_zlog_debug_verbose(
+ "%s: rfapiEcommunityGetLNI returned %d, lni=%d, attr=%p",
+ __func__, rc, lni, attr);
+ if (attr && !rc) {
+ it = rfapiMacImportTableGet(bgp, lni);
+
+ rfapiBgpInfoFilteredImportVPN(
+ it, FIF_ACTION_UPDATE, peer, rfd,
+ &pfx_mac_buf, /* prefix */
+ p, /* aux prefix: IP addr */
+ AFI_L2VPN, prd, attr, type, sub_type, label);
+ }
+ }
+
+ if (!has_ip_route)
+ return;
+
+ /*
+ * Iterate over all import tables; do a filtered import
+ * for the afi/safi combination
+ */
+ for (it = h->imports; it; it = it->next) {
+ (*rfapiBgpInfoFilteredImportFunction(safi))(
+ it, FIF_ACTION_UPDATE, peer, rfd, p, /* prefix */
+ NULL, afi, prd, attr, type, sub_type, label);
+ }
+
+ if (safi == SAFI_MPLS_VPN) {
+ vnc_direct_bgp_rh_add_route(bgp, afi, p, peer, attr);
+ }
+
+ if (safi == SAFI_MPLS_VPN) {
+ rfapiBgpInfoFilteredImportVPN(
+ bgp->rfapi->it_ce, FIF_ACTION_UPDATE, peer, rfd,
+ p, /* prefix */
+ NULL, afi, prd, attr, type, sub_type, label);
+ }
}
-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)
+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)
{
- struct bgp *bgp;
- struct rfapi *h;
- struct rfapi_import_table *it;
-
- bgp = bgp_get_default (); /* assume 1 instance for now */
- assert (bgp);
-
- h = bgp->rfapi;
- assert (h);
-
- /*
- * look at high-order byte of RD. FF means MAC
- * address is present (VNC L2VPN)
- */
- if (h->import_mac != NULL && safi == SAFI_MPLS_VPN &&
- decode_rd_type(prd->val) == RD_TYPE_VNC_ETH)
- {
- struct prefix pfx_mac_buf;
- void *cursor = NULL;
- int rc;
-
- memset (&pfx_mac_buf, 0, sizeof (pfx_mac_buf));
- pfx_mac_buf.family = AF_ETHERNET;
- pfx_mac_buf.prefixlen = 48;
- memcpy (&pfx_mac_buf.u.prefix_eth, prd->val + 2, 6);
-
- /*
- * withdraw does not contain attrs, so we don't have
- * access to the route's LNI, which would ordinarily
- * select the specific mac-based import table. Instead,
- * we must iterate over all mac-based tables and rely
- * on the RD to match.
- *
- * If this approach is too slow, add an index where
- * key is {RD, peer} and value is the import table
- */
- for (rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor);
- rc == 0;
- rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor))
- {
+ struct bgp *bgp;
+ struct rfapi *h;
+ struct rfapi_import_table *it;
+
+ bgp = bgp_get_default(); /* assume 1 instance for now */
+ assert(bgp);
+
+ h = bgp->rfapi;
+ assert(h);
+
+ /*
+ * look at high-order byte of RD. FF means MAC
+ * address is present (VNC L2VPN)
+ */
+ if (h->import_mac != NULL && safi == SAFI_MPLS_VPN
+ && decode_rd_type(prd->val) == RD_TYPE_VNC_ETH) {
+ struct prefix pfx_mac_buf;
+ void *cursor = NULL;
+ int rc;
+
+ memset(&pfx_mac_buf, 0, sizeof(pfx_mac_buf));
+ pfx_mac_buf.family = AF_ETHERNET;
+ pfx_mac_buf.prefixlen = 48;
+ memcpy(&pfx_mac_buf.u.prefix_eth, prd->val + 2, 6);
+
+ /*
+ * withdraw does not contain attrs, so we don't have
+ * access to the route's LNI, which would ordinarily
+ * select the specific mac-based import table. Instead,
+ * we must iterate over all mac-based tables and rely
+ * on the RD to match.
+ *
+ * If this approach is too slow, add an index where
+ * key is {RD, peer} and value is the import table
+ */
+ for (rc = skiplist_next(h->import_mac, NULL, (void **)&it,
+ &cursor);
+ rc == 0; rc = skiplist_next(h->import_mac, NULL,
+ (void **)&it, &cursor)) {
#if DEBUG_L2_EXTRA
- vnc_zlog_debug_verbose
- ("%s: calling rfapiBgpInfoFilteredImportVPN(it=%p, afi=AFI_L2VPN)",
- __func__, it);
+ vnc_zlog_debug_verbose(
+ "%s: calling rfapiBgpInfoFilteredImportVPN(it=%p, afi=AFI_L2VPN)",
+ __func__, it);
#endif
- rfapiBgpInfoFilteredImportVPN (
- it,
- (kill ? FIF_ACTION_KILL : FIF_ACTION_WITHDRAW),
- peer,
- rfd,
- &pfx_mac_buf, /* prefix */
- p, /* aux_prefix: IP */
- AFI_L2VPN,
- prd,
- attr,
- type,
- 0,
- NULL); /* sub_type & label unused for withdraw */
- }
- }
-
- /*
- * XXX For the case where the withdraw involves an L2
- * route with no IP information, we rely on the lack
- * of RT-list intersection to filter out the withdraw
- * from the IP-based import tables below
- */
-
- /*
- * Iterate over all import tables; do a filtered import
- * for the afi/safi combination
- */
-
- for (it = h->imports; it; it = it->next)
- {
- (*rfapiBgpInfoFilteredImportFunction (safi)) (
- it,
- (kill ? FIF_ACTION_KILL : FIF_ACTION_WITHDRAW),
- peer,
- rfd,
- p, /* prefix */
- NULL,
- afi,
- prd,
- attr,
- type,
- 0,
- NULL); /* sub_type & label unused for withdraw */
- }
-
- /* TBD the deletion should happen after the lifetime expires */
- if (safi == SAFI_MPLS_VPN)
- vnc_direct_bgp_rh_del_route (bgp, afi, p, peer);
-
- if (safi == SAFI_MPLS_VPN)
- {
- rfapiBgpInfoFilteredImportVPN (
- bgp->rfapi->it_ce,
- (kill ? FIF_ACTION_KILL : FIF_ACTION_WITHDRAW),
- peer,
- rfd,
- p, /* prefix */
- NULL,
- afi,
- prd,
- attr,
- type,
- 0,
- NULL); /* sub_type & label unused for withdraw */
- }
+ rfapiBgpInfoFilteredImportVPN(
+ it,
+ (kill ? FIF_ACTION_KILL : FIF_ACTION_WITHDRAW),
+ peer, rfd, &pfx_mac_buf, /* prefix */
+ p, /* aux_prefix: IP */
+ AFI_L2VPN, prd, attr, type, 0,
+ NULL); /* sub_type & label unused for withdraw
+ */
+ }
+ }
+
+ /*
+ * XXX For the case where the withdraw involves an L2
+ * route with no IP information, we rely on the lack
+ * of RT-list intersection to filter out the withdraw
+ * from the IP-based import tables below
+ */
+
+ /*
+ * Iterate over all import tables; do a filtered import
+ * for the afi/safi combination
+ */
+
+ for (it = h->imports; it; it = it->next) {
+ (*rfapiBgpInfoFilteredImportFunction(safi))(
+ it, (kill ? FIF_ACTION_KILL : FIF_ACTION_WITHDRAW),
+ peer, rfd, p, /* prefix */
+ NULL, afi, prd, attr, type, 0,
+ NULL); /* sub_type & label unused for withdraw */
+ }
+
+ /* TBD the deletion should happen after the lifetime expires */
+ if (safi == SAFI_MPLS_VPN)
+ vnc_direct_bgp_rh_del_route(bgp, afi, p, peer);
+
+ if (safi == SAFI_MPLS_VPN) {
+ rfapiBgpInfoFilteredImportVPN(
+ bgp->rfapi->it_ce,
+ (kill ? FIF_ACTION_KILL : FIF_ACTION_WITHDRAW), peer,
+ rfd, p, /* prefix */
+ NULL, afi, prd, attr, type, 0,
+ NULL); /* sub_type & label unused for withdraw */
+ }
}
/*
@@ -4378,65 +4087,57 @@ rfapiProcessWithdraw (
/* surprise, this gets called from peer_delete(), from rfapi_close() */
-static void
-rfapiProcessPeerDownRt (
- struct peer *peer,
- struct rfapi_import_table *import_table,
- afi_t afi,
- safi_t safi)
+static void rfapiProcessPeerDownRt(struct peer *peer,
+ struct rfapi_import_table *import_table,
+ afi_t afi, safi_t safi)
{
- struct route_node *rn;
- struct bgp_info *bi;
- struct route_table *rt;
- int (*timer_service_func) (struct thread *);
-
- assert (afi == AFI_IP || afi == AFI_IP6);
-
- VNC_ITRCCK;
-
- switch (safi)
- {
- case SAFI_MPLS_VPN:
- rt = import_table->imported_vpn[afi];
- timer_service_func = rfapiWithdrawTimerVPN;
- break;
- case SAFI_ENCAP:
- rt = import_table->imported_encap[afi];
- timer_service_func = rfapiWithdrawTimerEncap;
- break;
- default:
- assert (0);
- }
-
-
- for (rn = route_top (rt); rn; rn = route_next (rn))
- {
- for (bi = rn->info; bi; bi = bi->next)
- {
- if (bi->peer == peer)
- {
-
- if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED))
- {
- /* already in holddown, skip */
- continue;
- }
-
- if (safi == SAFI_MPLS_VPN)
- {
- RFAPI_UPDATE_ITABLE_COUNT (bi, import_table, afi, -1);
- import_table->holddown_count[afi] += 1;
- }
- rfapiBiStartWithdrawTimer (import_table, rn, bi,
- afi, safi,
- timer_service_func);
- }
- }
- }
- VNC_ITRCCK;
+ struct route_node *rn;
+ struct bgp_info *bi;
+ struct route_table *rt;
+ int (*timer_service_func)(struct thread *);
+
+ assert(afi == AFI_IP || afi == AFI_IP6);
+
+ VNC_ITRCCK;
+
+ switch (safi) {
+ case SAFI_MPLS_VPN:
+ rt = import_table->imported_vpn[afi];
+ timer_service_func = rfapiWithdrawTimerVPN;
+ break;
+ case SAFI_ENCAP:
+ rt = import_table->imported_encap[afi];
+ timer_service_func = rfapiWithdrawTimerEncap;
+ break;
+ default:
+ assert(0);
+ }
+
+
+ for (rn = route_top(rt); rn; rn = route_next(rn)) {
+ for (bi = rn->info; bi; bi = bi->next) {
+ if (bi->peer == peer) {
+
+ if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) {
+ /* already in holddown, skip */
+ continue;
+ }
+
+ if (safi == SAFI_MPLS_VPN) {
+ RFAPI_UPDATE_ITABLE_COUNT(
+ bi, import_table, afi, -1);
+ import_table->holddown_count[afi] += 1;
+ }
+ rfapiBiStartWithdrawTimer(import_table, rn, bi,
+ afi, safi,
+ timer_service_func);
+ }
+ }
+ }
+ VNC_ITRCCK;
}
-/*
+/*
* This gets called when a peer connection drops. We have to remove
* all the routes from this peer.
*
@@ -4444,49 +4145,46 @@ rfapiProcessPeerDownRt (
* grouping withdrawn routes so we can generate callbacks more
* efficiently.
*/
-void
-rfapiProcessPeerDown (struct peer *peer)
+void rfapiProcessPeerDown(struct peer *peer)
{
- struct bgp *bgp;
- struct rfapi *h;
- struct rfapi_import_table *it;
-
- /*
- * If this peer is a "dummy" peer structure atached to a RFAPI
- * nve_descriptor, we don't need to walk the import tables
- * because the routes are already withdrawn by rfapi_close()
- */
- if (CHECK_FLAG (peer->flags, PEER_FLAG_IS_RFAPI_HD))
- return;
-
- /*
- * 1. Visit all BIs in all ENCAP import tables.
- * Start withdraw timer on the BIs that match peer.
- *
- * 2. Visit All BIs in all VPN import tables.
- * Start withdraw timer on the BIs that match peer.
- */
-
- bgp = bgp_get_default (); /* assume 1 instance for now */
- if (!bgp)
- return;
-
- h = bgp->rfapi;
- assert (h);
-
- for (it = h->imports; it; it = it->next)
- {
- rfapiProcessPeerDownRt (peer, it, AFI_IP, SAFI_ENCAP);
- rfapiProcessPeerDownRt (peer, it, AFI_IP6, SAFI_ENCAP);
- rfapiProcessPeerDownRt (peer, it, AFI_IP, SAFI_MPLS_VPN);
- rfapiProcessPeerDownRt (peer, it, AFI_IP6, SAFI_MPLS_VPN);
- }
-
- if (h->it_ce)
- {
- rfapiProcessPeerDownRt (peer, h->it_ce, AFI_IP, SAFI_MPLS_VPN);
- rfapiProcessPeerDownRt (peer, h->it_ce, AFI_IP6, SAFI_MPLS_VPN);
- }
+ struct bgp *bgp;
+ struct rfapi *h;
+ struct rfapi_import_table *it;
+
+ /*
+ * If this peer is a "dummy" peer structure atached to a RFAPI
+ * nve_descriptor, we don't need to walk the import tables
+ * because the routes are already withdrawn by rfapi_close()
+ */
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
+ return;
+
+ /*
+ * 1. Visit all BIs in all ENCAP import tables.
+ * Start withdraw timer on the BIs that match peer.
+ *
+ * 2. Visit All BIs in all VPN import tables.
+ * Start withdraw timer on the BIs that match peer.
+ */
+
+ bgp = bgp_get_default(); /* assume 1 instance for now */
+ if (!bgp)
+ return;
+
+ h = bgp->rfapi;
+ assert(h);
+
+ for (it = h->imports; it; it = it->next) {
+ rfapiProcessPeerDownRt(peer, it, AFI_IP, SAFI_ENCAP);
+ rfapiProcessPeerDownRt(peer, it, AFI_IP6, SAFI_ENCAP);
+ rfapiProcessPeerDownRt(peer, it, AFI_IP, SAFI_MPLS_VPN);
+ rfapiProcessPeerDownRt(peer, it, AFI_IP6, SAFI_MPLS_VPN);
+ }
+
+ if (h->it_ce) {
+ rfapiProcessPeerDownRt(peer, h->it_ce, AFI_IP, SAFI_MPLS_VPN);
+ rfapiProcessPeerDownRt(peer, h->it_ce, AFI_IP6, SAFI_MPLS_VPN);
+ }
}
/*
@@ -4494,445 +4192,431 @@ rfapiProcessPeerDown (struct peer *peer)
* filtered according to the import table's RT list
*
* TBD: does this function need additions to match rfapiProcessUpdate()
- * for, e.g., L2 handling?
+ * for, e.g., L2 handling?
*/
-static void
-rfapiBgpTableFilteredImport (
- struct bgp *bgp,
- struct rfapi_import_table *it,
- afi_t afi,
- safi_t safi)
+static void rfapiBgpTableFilteredImport(struct bgp *bgp,
+ struct rfapi_import_table *it,
+ afi_t afi, safi_t safi)
{
- struct bgp_node *rn1;
- struct bgp_node *rn2;
-
- /* Only these SAFIs have 2-level RIBS */
- assert (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP);
-
- /*
- * Now visit all the rd nodes and the nodes of all the
- * route tables attached to them, and import the routes
- * if they have matching route targets
- */
- for (rn1 = bgp_table_top (bgp->rib[afi][safi]);
- rn1; rn1 = bgp_route_next (rn1))
- {
-
- if (rn1->info)
- {
- for (rn2 = bgp_table_top (rn1->info);
- rn2; rn2 = bgp_route_next (rn2))
- {
-
- struct bgp_info *bi;
-
- for (bi = rn2->info; bi; bi = bi->next)
- {
- u_int32_t label = 0;
-
- if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED))
- continue;
-
- if (bi->extra)
- label = decode_label (&bi->extra->label);
- (*rfapiBgpInfoFilteredImportFunction (safi)) (
- it, /* which import table */
- FIF_ACTION_UPDATE,
- bi->peer,
- NULL,
- &rn2->p, /* prefix */
- NULL,
- afi,
- (struct prefix_rd *) &rn1->p,
- bi->attr,
- bi->type,
- bi->sub_type,
- &label);
- }
- }
- }
- }
+ struct bgp_node *rn1;
+ struct bgp_node *rn2;
+
+ /* Only these SAFIs have 2-level RIBS */
+ assert(safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP);
+
+ /*
+ * Now visit all the rd nodes and the nodes of all the
+ * route tables attached to them, and import the routes
+ * if they have matching route targets
+ */
+ for (rn1 = bgp_table_top(bgp->rib[afi][safi]); rn1;
+ rn1 = bgp_route_next(rn1)) {
+
+ if (rn1->info) {
+ for (rn2 = bgp_table_top(rn1->info); rn2;
+ rn2 = bgp_route_next(rn2)) {
+
+ struct bgp_info *bi;
+
+ for (bi = rn2->info; bi; bi = bi->next) {
+ u_int32_t label = 0;
+
+ if (CHECK_FLAG(bi->flags,
+ BGP_INFO_REMOVED))
+ continue;
+
+ if (bi->extra)
+ label = decode_label(
+ &bi->extra->label);
+ (*rfapiBgpInfoFilteredImportFunction(
+ safi))(
+ it, /* which import table */
+ FIF_ACTION_UPDATE, bi->peer,
+ NULL, &rn2->p, /* prefix */
+ NULL, afi,
+ (struct prefix_rd *)&rn1->p,
+ bi->attr, bi->type,
+ bi->sub_type, &label);
+ }
+ }
+ }
+ }
}
/* per-bgp-instance rfapi data */
-struct rfapi *
-bgp_rfapi_new (struct bgp *bgp)
+struct rfapi *bgp_rfapi_new(struct bgp *bgp)
{
- struct rfapi *h;
- int afi;
- struct rfapi_rfp_cfg *cfg = NULL;
- struct rfapi_rfp_cb_methods *cbm = NULL;
-
- assert (bgp->rfapi_cfg == NULL);
-
- h = (struct rfapi *) XCALLOC (MTYPE_RFAPI, sizeof (struct rfapi));
-
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- {
- /* ugly, to deal with addition of delegates, part of 0.99.24.1 merge */
- h->un[afi].delegate = route_table_get_default_delegate ();
- }
-
- /*
- * initialize the ce import table
- */
- h->it_ce =
- XCALLOC (MTYPE_RFAPI_IMPORTTABLE, sizeof (struct rfapi_import_table));
- h->it_ce->imported_vpn[AFI_IP] = route_table_init ();
- h->it_ce->imported_vpn[AFI_IP6] = route_table_init ();
- h->it_ce->imported_encap[AFI_IP] = route_table_init ();
- h->it_ce->imported_encap[AFI_IP6] = route_table_init ();
- rfapiBgpTableFilteredImport (bgp, h->it_ce, AFI_IP, SAFI_MPLS_VPN);
- rfapiBgpTableFilteredImport (bgp, h->it_ce, AFI_IP6, SAFI_MPLS_VPN);
-
- /*
- * Set up work queue for deferred rfapi_close operations
- */
- h->deferred_close_q = work_queue_new (bm->master, "rfapi deferred close");
- h->deferred_close_q->spec.workfunc = rfapi_deferred_close_workfunc;
- h->deferred_close_q->spec.data = h;
-
- h->rfp = rfp_start (bm->master, &cfg, &cbm);
- bgp->rfapi_cfg = bgp_rfapi_cfg_new (cfg);
- if (cbm != NULL)
- {
- h->rfp_methods = *cbm;
- }
- return h;
+ struct rfapi *h;
+ int afi;
+ struct rfapi_rfp_cfg *cfg = NULL;
+ struct rfapi_rfp_cb_methods *cbm = NULL;
+
+ assert(bgp->rfapi_cfg == NULL);
+
+ h = (struct rfapi *)XCALLOC(MTYPE_RFAPI, sizeof(struct rfapi));
+
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ /* ugly, to deal with addition of delegates, part of 0.99.24.1
+ * merge */
+ h->un[afi].delegate = route_table_get_default_delegate();
+ }
+
+ /*
+ * initialize the ce import table
+ */
+ h->it_ce = XCALLOC(MTYPE_RFAPI_IMPORTTABLE,
+ sizeof(struct rfapi_import_table));
+ h->it_ce->imported_vpn[AFI_IP] = route_table_init();
+ h->it_ce->imported_vpn[AFI_IP6] = route_table_init();
+ h->it_ce->imported_encap[AFI_IP] = route_table_init();
+ h->it_ce->imported_encap[AFI_IP6] = route_table_init();
+ rfapiBgpTableFilteredImport(bgp, h->it_ce, AFI_IP, SAFI_MPLS_VPN);
+ rfapiBgpTableFilteredImport(bgp, h->it_ce, AFI_IP6, SAFI_MPLS_VPN);
+
+ /*
+ * Set up work queue for deferred rfapi_close operations
+ */
+ h->deferred_close_q =
+ work_queue_new(bm->master, "rfapi deferred close");
+ h->deferred_close_q->spec.workfunc = rfapi_deferred_close_workfunc;
+ h->deferred_close_q->spec.data = h;
+
+ h->rfp = rfp_start(bm->master, &cfg, &cbm);
+ bgp->rfapi_cfg = bgp_rfapi_cfg_new(cfg);
+ if (cbm != NULL) {
+ h->rfp_methods = *cbm;
+ }
+ return h;
}
-void
-bgp_rfapi_destroy (struct bgp *bgp, struct rfapi *h)
+void bgp_rfapi_destroy(struct bgp *bgp, struct rfapi *h)
{
- if (bgp == NULL || h == NULL)
- return;
-
- if (h->resolve_nve_nexthop)
- {
- skiplist_free (h->resolve_nve_nexthop);
- h->resolve_nve_nexthop = NULL;
- }
-
- route_table_finish (h->it_ce->imported_vpn[AFI_IP]);
- route_table_finish (h->it_ce->imported_vpn[AFI_IP6]);
- route_table_finish (h->it_ce->imported_encap[AFI_IP]);
- route_table_finish (h->it_ce->imported_encap[AFI_IP6]);
-
- if (h->import_mac)
- {
- struct rfapi_import_table *it;
- void *cursor;
- int rc;
-
- for (cursor = NULL,
- rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor);
- !rc;
- rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor))
- {
-
- rfapiImportTableFlush (it);
- XFREE (MTYPE_RFAPI_IMPORTTABLE, it);
- }
- skiplist_free (h->import_mac);
- h->import_mac = NULL;
- }
-
- work_queue_free (h->deferred_close_q);
-
- if (h->rfp != NULL)
- rfp_stop (h->rfp);
- XFREE (MTYPE_RFAPI_IMPORTTABLE, h->it_ce);
- XFREE (MTYPE_RFAPI, h);
+ if (bgp == NULL || h == NULL)
+ return;
+
+ if (h->resolve_nve_nexthop) {
+ skiplist_free(h->resolve_nve_nexthop);
+ h->resolve_nve_nexthop = NULL;
+ }
+
+ route_table_finish(h->it_ce->imported_vpn[AFI_IP]);
+ route_table_finish(h->it_ce->imported_vpn[AFI_IP6]);
+ route_table_finish(h->it_ce->imported_encap[AFI_IP]);
+ route_table_finish(h->it_ce->imported_encap[AFI_IP6]);
+
+ if (h->import_mac) {
+ struct rfapi_import_table *it;
+ void *cursor;
+ int rc;
+
+ for (cursor = NULL,
+ rc = skiplist_next(h->import_mac, NULL, (void **)&it,
+ &cursor);
+ !rc; rc = skiplist_next(h->import_mac, NULL, (void **)&it,
+ &cursor)) {
+
+ rfapiImportTableFlush(it);
+ XFREE(MTYPE_RFAPI_IMPORTTABLE, it);
+ }
+ skiplist_free(h->import_mac);
+ h->import_mac = NULL;
+ }
+
+ work_queue_free(h->deferred_close_q);
+
+ if (h->rfp != NULL)
+ rfp_stop(h->rfp);
+ XFREE(MTYPE_RFAPI_IMPORTTABLE, h->it_ce);
+ XFREE(MTYPE_RFAPI, h);
}
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)
{
- struct rfapi *h;
- struct rfapi_import_table *it;
- afi_t afi;
-
- h = bgp->rfapi;
- assert (h);
-
- for (it = h->imports; it; it = it->next)
- {
- if (ecommunity_cmp (it->rt_import_list, rt_import_list))
- break;
- }
-
- vnc_zlog_debug_verbose ("%s: matched it=%p", __func__, it);
-
- if (!it)
- {
- it =
- XCALLOC (MTYPE_RFAPI_IMPORTTABLE, sizeof (struct rfapi_import_table));
- assert (it);
- it->next = h->imports;
- h->imports = it;
-
- it->rt_import_list = ecommunity_dup (rt_import_list);
- it->rfg = rfg;
- it->monitor_exterior_orphans =
- skiplist_new (0, NULL, (void (*)(void *)) prefix_free);
-
- /*
- * fill import route tables from RIBs
- *
- * Potential area for optimization. If this occurs when
- * tables are large (e.g., the operator adds a nve group
- * with a new RT list to a running system), it could take
- * a while.
- *
- */
- for (afi = AFI_IP; afi < AFI_MAX; ++afi)
- {
-
- it->imported_vpn[afi] = route_table_init ();
- it->imported_encap[afi] = route_table_init ();
-
- rfapiBgpTableFilteredImport (bgp, it, afi, SAFI_MPLS_VPN);
- rfapiBgpTableFilteredImport (bgp, it, afi, SAFI_ENCAP);
-
- vnc_import_bgp_exterior_redist_enable_it (bgp, afi, it);
- }
- }
-
- it->refcount += 1;
-
- return it;
+ struct rfapi *h;
+ struct rfapi_import_table *it;
+ afi_t afi;
+
+ h = bgp->rfapi;
+ assert(h);
+
+ for (it = h->imports; it; it = it->next) {
+ if (ecommunity_cmp(it->rt_import_list, rt_import_list))
+ break;
+ }
+
+ vnc_zlog_debug_verbose("%s: matched it=%p", __func__, it);
+
+ if (!it) {
+ it = XCALLOC(MTYPE_RFAPI_IMPORTTABLE,
+ sizeof(struct rfapi_import_table));
+ assert(it);
+ it->next = h->imports;
+ h->imports = it;
+
+ it->rt_import_list = ecommunity_dup(rt_import_list);
+ it->rfg = rfg;
+ it->monitor_exterior_orphans =
+ skiplist_new(0, NULL, (void (*)(void *))prefix_free);
+
+ /*
+ * fill import route tables from RIBs
+ *
+ * Potential area for optimization. If this occurs when
+ * tables are large (e.g., the operator adds a nve group
+ * with a new RT list to a running system), it could take
+ * a while.
+ *
+ */
+ for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
+
+ it->imported_vpn[afi] = route_table_init();
+ it->imported_encap[afi] = route_table_init();
+
+ rfapiBgpTableFilteredImport(bgp, it, afi,
+ SAFI_MPLS_VPN);
+ rfapiBgpTableFilteredImport(bgp, it, afi, SAFI_ENCAP);
+
+ vnc_import_bgp_exterior_redist_enable_it(bgp, afi, it);
+ }
+ }
+
+ it->refcount += 1;
+
+ return it;
}
/*
* skiplist element free function
*/
-static void
-delete_rem_pfx_na_free (void *na)
+static void delete_rem_pfx_na_free(void *na)
{
- uint32_t *pCounter = ((struct rfapi_nve_addr *) na)->info;
+ uint32_t *pCounter = ((struct rfapi_nve_addr *)na)->info;
- *pCounter += 1;
- XFREE (MTYPE_RFAPI_NVE_ADDR, na);
+ *pCounter += 1;
+ XFREE(MTYPE_RFAPI_NVE_ADDR, na);
}
/*
* Common deleter for IP and MAC import tables
*/
-static void
-rfapiDeleteRemotePrefixesIt (
- struct bgp *bgp,
- struct rfapi_import_table *it,
- struct prefix *un,
- struct prefix *vn,
- struct prefix *p,
- int delete_active,
- int delete_holddown,
- uint32_t *pARcount,
- uint32_t *pAHcount,
- uint32_t *pHRcount,
- uint32_t *pHHcount,
- struct skiplist *uniq_active_nves,
- struct skiplist *uniq_holddown_nves)
+static void rfapiDeleteRemotePrefixesIt(
+ struct bgp *bgp, struct rfapi_import_table *it, struct prefix *un,
+ struct prefix *vn, struct prefix *p, int delete_active,
+ int delete_holddown, uint32_t *pARcount, uint32_t *pAHcount,
+ uint32_t *pHRcount, uint32_t *pHHcount,
+ struct skiplist *uniq_active_nves, struct skiplist *uniq_holddown_nves)
{
- afi_t afi;
+ afi_t afi;
#if DEBUG_L2_EXTRA
- {
- char buf_pfx[BUFSIZ];
-
- if (p)
- {
- prefix2str (p, buf_pfx, BUFSIZ);
- }
- else
- {
- buf_pfx[0] = '*';
- buf_pfx[1] = 0;
- }
-
- vnc_zlog_debug_verbose ("%s: entry, p=%s, delete_active=%d, delete_holddown=%d",
- __func__, buf_pfx, delete_active, delete_holddown);
- }
+ {
+ char buf_pfx[BUFSIZ];
+
+ if (p) {
+ prefix2str(p, buf_pfx, BUFSIZ);
+ } else {
+ buf_pfx[0] = '*';
+ buf_pfx[1] = 0;
+ }
+
+ vnc_zlog_debug_verbose(
+ "%s: entry, p=%s, delete_active=%d, delete_holddown=%d",
+ __func__, buf_pfx, delete_active, delete_holddown);
+ }
#endif
- for (afi = AFI_IP; afi < AFI_MAX; ++afi)
- {
-
- struct route_table *rt;
- struct route_node *rn;
-
- if (p && (family2afi (p->family) != afi))
- {
- continue;
- }
-
- rt = it->imported_vpn[afi];
- if (!rt)
- continue;
-
- vnc_zlog_debug_verbose ("%s: scanning rt for afi=%d", __func__, afi);
-
- for (rn = route_top (rt); rn; rn = route_next (rn))
- {
- struct bgp_info *bi;
- struct bgp_info *next;
-
- if (VNC_DEBUG(IMPORT_DEL_REMOTE))
- {
- char p1line[BUFSIZ];
- char p2line[BUFSIZ];
-
- prefix2str (p, p1line, BUFSIZ);
- prefix2str (&rn->p, p2line, BUFSIZ);
- vnc_zlog_debug_any ("%s: want %s, have %s", __func__, p1line, p2line);
- }
-
- if (p && prefix_cmp (p, &rn->p))
- continue;
-
- {
- char buf_pfx[BUFSIZ];
- prefix2str (&rn->p, buf_pfx, BUFSIZ);
- vnc_zlog_debug_verbose ("%s: rn pfx=%s", __func__, buf_pfx);
- }
-
- /* TBD is this valid for afi == AFI_L2VPN? */
- RFAPI_CHECK_REFCOUNT (rn, SAFI_MPLS_VPN, 1);
-
- for (bi = rn->info; bi; bi = next)
- {
- next = bi->next;
-
- struct prefix qpt;
- struct prefix qct;
- int qpt_valid = 0;
- int qct_valid = 0;
- int is_active = 0;
-
- vnc_zlog_debug_verbose ("%s: examining bi %p", __func__, bi);
-
- if (bi->attr)
- {
- if (!rfapiGetNexthop (bi->attr, &qpt))
- qpt_valid = 1;
- }
- if (vn)
- {
- if (!qpt_valid || !prefix_match (vn, &qpt))
- {
+ for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
+
+ struct route_table *rt;
+ struct route_node *rn;
+
+ if (p && (family2afi(p->family) != afi)) {
+ continue;
+ }
+
+ rt = it->imported_vpn[afi];
+ if (!rt)
+ continue;
+
+ vnc_zlog_debug_verbose("%s: scanning rt for afi=%d", __func__,
+ afi);
+
+ for (rn = route_top(rt); rn; rn = route_next(rn)) {
+ struct bgp_info *bi;
+ struct bgp_info *next;
+
+ if (VNC_DEBUG(IMPORT_DEL_REMOTE)) {
+ char p1line[BUFSIZ];
+ char p2line[BUFSIZ];
+
+ prefix2str(p, p1line, BUFSIZ);
+ prefix2str(&rn->p, p2line, BUFSIZ);
+ vnc_zlog_debug_any("%s: want %s, have %s",
+ __func__, p1line, p2line);
+ }
+
+ if (p && prefix_cmp(p, &rn->p))
+ continue;
+
+ {
+ char buf_pfx[BUFSIZ];
+ prefix2str(&rn->p, buf_pfx, BUFSIZ);
+ vnc_zlog_debug_verbose("%s: rn pfx=%s",
+ __func__, buf_pfx);
+ }
+
+ /* TBD is this valid for afi == AFI_L2VPN? */
+ RFAPI_CHECK_REFCOUNT(rn, SAFI_MPLS_VPN, 1);
+
+ for (bi = rn->info; bi; bi = next) {
+ next = bi->next;
+
+ struct prefix qpt;
+ struct prefix qct;
+ int qpt_valid = 0;
+ int qct_valid = 0;
+ int is_active = 0;
+
+ vnc_zlog_debug_verbose("%s: examining bi %p",
+ __func__, bi);
+
+ if (bi->attr) {
+ if (!rfapiGetNexthop(bi->attr, &qpt))
+ qpt_valid = 1;
+ }
+ if (vn) {
+ if (!qpt_valid
+ || !prefix_match(vn, &qpt)) {
#if DEBUG_L2_EXTRA
- vnc_zlog_debug_verbose
- ("%s: continue at vn && !qpt_valid || !prefix_match(vn, &qpt)",
- __func__);
+ vnc_zlog_debug_verbose(
+ "%s: continue at vn && !qpt_valid || !prefix_match(vn, &qpt)",
+ __func__);
#endif
- continue;
- }
- }
+ continue;
+ }
+ }
- if (!rfapiGetUnAddrOfVpnBi (bi, &qct))
- qct_valid = 1;
+ if (!rfapiGetUnAddrOfVpnBi(bi, &qct))
+ qct_valid = 1;
- if (un)
- {
- if (!qct_valid || !prefix_match (un, &qct))
- {
+ if (un) {
+ if (!qct_valid
+ || !prefix_match(un, &qct)) {
#if DEBUG_L2_EXTRA
- vnc_zlog_debug_verbose
- ("%s: continue at un && !qct_valid || !prefix_match(un, &qct)",
- __func__);
+ vnc_zlog_debug_verbose(
+ "%s: continue at un && !qct_valid || !prefix_match(un, &qct)",
+ __func__);
#endif
- continue;
- }
- }
-
-
- /*
- * Blow bi away
- */
- /*
- * If this route is waiting to be deleted because of
- * a previous withdraw, we must cancel its timer.
- */
- if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED))
- {
- if (!delete_holddown)
- continue;
- if (bi->extra->vnc.import.timer)
- {
-
- struct thread *t =
- (struct thread *) bi->extra->vnc.import.timer;
- struct rfapi_withdraw *wcb = t->arg;
-
- wcb->import_table->holddown_count[afi] -= 1;
- RFAPI_UPDATE_ITABLE_COUNT (bi, wcb->import_table, afi,
- 1);
- XFREE (MTYPE_RFAPI_WITHDRAW, wcb);
- thread_cancel (t);
- }
- }
- else
- {
- if (!delete_active)
- continue;
- is_active = 1;
- }
-
- vnc_zlog_debug_verbose
- ("%s: deleting bi %p (qct_valid=%d, qpt_valid=%d, delete_holddown=%d, delete_active=%d)",
- __func__, bi, qct_valid, qpt_valid, delete_holddown,
- delete_active);
-
-
- /*
- * add nve to list
- */
- if (qct_valid && qpt_valid)
- {
-
- struct rfapi_nve_addr na;
- struct rfapi_nve_addr *nap;
-
- memset (&na, 0, sizeof (na));
- assert (!rfapiQprefix2Raddr (&qct, &na.un));
- assert (!rfapiQprefix2Raddr (&qpt, &na.vn));
-
- if (skiplist_search ((is_active ? uniq_active_nves :
- uniq_holddown_nves), &na,
- (void **) &nap))
- {
- char line[BUFSIZ];
-
- nap = XCALLOC (MTYPE_RFAPI_NVE_ADDR,
- sizeof (struct rfapi_nve_addr));
- assert (nap);
- *nap = na;
- nap->info = is_active ? pAHcount : pHHcount;
- skiplist_insert ((is_active ? uniq_active_nves :
- uniq_holddown_nves), nap, nap);
-
- rfapiNveAddr2Str (nap, line, BUFSIZ);
- }
- }
-
- vnc_direct_bgp_rh_del_route (bgp, afi, &rn->p, bi->peer);
-
- RFAPI_UPDATE_ITABLE_COUNT (bi, it, afi, -1);
- it->holddown_count[afi] += 1;
- rfapiExpireVpnNow (it, rn, bi, 1);
-
- vnc_zlog_debug_verbose ("%s: incrementing count (is_active=%d)",
- __func__, is_active);
-
- if (is_active)
- ++ * pARcount;
- else
- ++ * pHRcount;
- }
- }
- }
+ continue;
+ }
+ }
+
+
+ /*
+ * Blow bi away
+ */
+ /*
+ * If this route is waiting to be deleted
+ * because of
+ * a previous withdraw, we must cancel its
+ * timer.
+ */
+ if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) {
+ if (!delete_holddown)
+ continue;
+ if (bi->extra->vnc.import.timer) {
+
+ struct thread *t =
+ (struct thread *)bi
+ ->extra->vnc
+ .import.timer;
+ struct rfapi_withdraw *wcb =
+ t->arg;
+
+ wcb->import_table
+ ->holddown_count[afi] -=
+ 1;
+ RFAPI_UPDATE_ITABLE_COUNT(
+ bi, wcb->import_table,
+ afi, 1);
+ XFREE(MTYPE_RFAPI_WITHDRAW,
+ wcb);
+ thread_cancel(t);
+ }
+ } else {
+ if (!delete_active)
+ continue;
+ is_active = 1;
+ }
+
+ vnc_zlog_debug_verbose(
+ "%s: deleting bi %p (qct_valid=%d, qpt_valid=%d, delete_holddown=%d, delete_active=%d)",
+ __func__, bi, qct_valid, qpt_valid,
+ delete_holddown, delete_active);
+
+
+ /*
+ * add nve to list
+ */
+ if (qct_valid && qpt_valid) {
+
+ struct rfapi_nve_addr na;
+ struct rfapi_nve_addr *nap;
+
+ memset(&na, 0, sizeof(na));
+ assert(!rfapiQprefix2Raddr(&qct,
+ &na.un));
+ assert(!rfapiQprefix2Raddr(&qpt,
+ &na.vn));
+
+ if (skiplist_search(
+ (is_active
+ ? uniq_active_nves
+ : uniq_holddown_nves),
+ &na, (void **)&nap)) {
+ char line[BUFSIZ];
+
+ nap = XCALLOC(
+ MTYPE_RFAPI_NVE_ADDR,
+ sizeof(struct
+ rfapi_nve_addr));
+ assert(nap);
+ *nap = na;
+ nap->info = is_active
+ ? pAHcount
+ : pHHcount;
+ skiplist_insert(
+ (is_active
+ ? uniq_active_nves
+ : uniq_holddown_nves),
+ nap, nap);
+
+ rfapiNveAddr2Str(nap, line,
+ BUFSIZ);
+ }
+ }
+
+ vnc_direct_bgp_rh_del_route(bgp, afi, &rn->p,
+ bi->peer);
+
+ RFAPI_UPDATE_ITABLE_COUNT(bi, it, afi, -1);
+ it->holddown_count[afi] += 1;
+ rfapiExpireVpnNow(it, rn, bi, 1);
+
+ vnc_zlog_debug_verbose(
+ "%s: incrementing count (is_active=%d)",
+ __func__, is_active);
+
+ if (is_active)
+ ++*pARcount;
+ else
+ ++*pHRcount;
+ }
+ }
+ }
}
@@ -4944,7 +4628,7 @@ rfapiDeleteRemotePrefixesIt (
*
* 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
@@ -4959,133 +4643,110 @@ rfapiDeleteRemotePrefixesIt (
* return value:
* void
--------------------------------------------*/
-void
-rfapiDeleteRemotePrefixes (
- struct prefix *un,
- struct prefix *vn,
- struct prefix *p,
- struct rfapi_import_table *arg_it,
- int delete_active,
- int delete_holddown,
- uint32_t *pARcount,
- uint32_t *pAHcount,
- uint32_t *pHRcount,
- uint32_t *pHHcount)
+void rfapiDeleteRemotePrefixes(struct prefix *un, struct prefix *vn,
+ struct prefix *p,
+ struct rfapi_import_table *arg_it,
+ int delete_active, int delete_holddown,
+ uint32_t *pARcount, uint32_t *pAHcount,
+ uint32_t *pHRcount, uint32_t *pHHcount)
{
- struct bgp *bgp;
- struct rfapi *h;
- struct rfapi_import_table *it;
- uint32_t deleted_holddown_route_count = 0;
- uint32_t deleted_active_route_count = 0;
- uint32_t deleted_holddown_nve_count = 0;
- uint32_t deleted_active_nve_count = 0;
- struct skiplist *uniq_holddown_nves;
- struct skiplist *uniq_active_nves;
-
- VNC_ITRCCK;
-
- bgp = bgp_get_default (); /* assume 1 instance for now */
- /* If no bgp instantiated yet, no vnc prefixes exist */
- if (!bgp)
- return;
-
- h = bgp->rfapi;
- assert (h);
-
- uniq_holddown_nves =
- skiplist_new (0, rfapi_nve_addr_cmp, delete_rem_pfx_na_free);
- uniq_active_nves =
- skiplist_new (0, rfapi_nve_addr_cmp, delete_rem_pfx_na_free);
-
- /*
- * Iterate over all import tables; do a filtered import
- * for the afi/safi combination
- */
-
- if (arg_it)
- it = arg_it;
- else
- it = h->imports;
- for (; it; )
- {
-
- vnc_zlog_debug_verbose
- ("%s: calling rfapiDeleteRemotePrefixesIt() on (IP) import %p",
- __func__, it);
-
- rfapiDeleteRemotePrefixesIt (
- bgp,
- it,
- un,
- vn,
- p,
- delete_active,
- delete_holddown,
- &deleted_active_route_count,
- &deleted_active_nve_count,
- &deleted_holddown_route_count,
- &deleted_holddown_nve_count,
- uniq_active_nves,
- uniq_holddown_nves);
-
- if (arg_it)
- it = NULL;
- else
- it = it->next;
- }
-
- /*
- * Now iterate over L2 import tables
- */
- if (h->import_mac && !(p && (p->family != AF_ETHERNET)))
- {
-
- void *cursor = NULL;
- int rc;
-
- for (cursor = NULL,
- rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor);
- !rc;
- rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor))
- {
-
- vnc_zlog_debug_verbose
- ("%s: calling rfapiDeleteRemotePrefixesIt() on import_mac %p",
- __func__, it);
-
- rfapiDeleteRemotePrefixesIt (
- bgp,
- it,
- un,
- vn,
- p,
- delete_active,
- delete_holddown,
- &deleted_active_route_count,
- &deleted_active_nve_count,
- &deleted_holddown_route_count,
- &deleted_holddown_nve_count,
- uniq_active_nves,
- uniq_holddown_nves);
- }
- }
-
- /*
- * our custom element freeing function above counts as it deletes
- */
- skiplist_free (uniq_holddown_nves);
- skiplist_free (uniq_active_nves);
-
- if (pARcount)
- *pARcount = deleted_active_route_count;
- if (pAHcount)
- *pAHcount = deleted_active_nve_count;
- if (pHRcount)
- *pHRcount = deleted_holddown_route_count;
- if (pHHcount)
- *pHHcount = deleted_holddown_nve_count;
-
- VNC_ITRCCK;
+ struct bgp *bgp;
+ struct rfapi *h;
+ struct rfapi_import_table *it;
+ uint32_t deleted_holddown_route_count = 0;
+ uint32_t deleted_active_route_count = 0;
+ uint32_t deleted_holddown_nve_count = 0;
+ uint32_t deleted_active_nve_count = 0;
+ struct skiplist *uniq_holddown_nves;
+ struct skiplist *uniq_active_nves;
+
+ VNC_ITRCCK;
+
+ bgp = bgp_get_default(); /* assume 1 instance for now */
+ /* If no bgp instantiated yet, no vnc prefixes exist */
+ if (!bgp)
+ return;
+
+ h = bgp->rfapi;
+ assert(h);
+
+ uniq_holddown_nves =
+ skiplist_new(0, rfapi_nve_addr_cmp, delete_rem_pfx_na_free);
+ uniq_active_nves =
+ skiplist_new(0, rfapi_nve_addr_cmp, delete_rem_pfx_na_free);
+
+ /*
+ * Iterate over all import tables; do a filtered import
+ * for the afi/safi combination
+ */
+
+ if (arg_it)
+ it = arg_it;
+ else
+ it = h->imports;
+ for (; it;) {
+
+ vnc_zlog_debug_verbose(
+ "%s: calling rfapiDeleteRemotePrefixesIt() on (IP) import %p",
+ __func__, it);
+
+ rfapiDeleteRemotePrefixesIt(
+ bgp, it, un, vn, p, delete_active, delete_holddown,
+ &deleted_active_route_count, &deleted_active_nve_count,
+ &deleted_holddown_route_count,
+ &deleted_holddown_nve_count, uniq_active_nves,
+ uniq_holddown_nves);
+
+ if (arg_it)
+ it = NULL;
+ else
+ it = it->next;
+ }
+
+ /*
+ * Now iterate over L2 import tables
+ */
+ if (h->import_mac && !(p && (p->family != AF_ETHERNET))) {
+
+ void *cursor = NULL;
+ int rc;
+
+ for (cursor = NULL,
+ rc = skiplist_next(h->import_mac, NULL, (void **)&it,
+ &cursor);
+ !rc; rc = skiplist_next(h->import_mac, NULL, (void **)&it,
+ &cursor)) {
+
+ vnc_zlog_debug_verbose(
+ "%s: calling rfapiDeleteRemotePrefixesIt() on import_mac %p",
+ __func__, it);
+
+ rfapiDeleteRemotePrefixesIt(
+ bgp, it, un, vn, p, delete_active,
+ delete_holddown, &deleted_active_route_count,
+ &deleted_active_nve_count,
+ &deleted_holddown_route_count,
+ &deleted_holddown_nve_count, uniq_active_nves,
+ uniq_holddown_nves);
+ }
+ }
+
+ /*
+ * our custom element freeing function above counts as it deletes
+ */
+ skiplist_free(uniq_holddown_nves);
+ skiplist_free(uniq_active_nves);
+
+ if (pARcount)
+ *pARcount = deleted_active_route_count;
+ if (pAHcount)
+ *pAHcount = deleted_active_nve_count;
+ if (pHRcount)
+ *pHRcount = deleted_holddown_route_count;
+ if (pHHcount)
+ *pHHcount = deleted_holddown_nve_count;
+
+ VNC_ITRCCK;
}
/*------------------------------------------
@@ -5093,7 +4754,7 @@ rfapiDeleteRemotePrefixes (
*
* UI helper: count VRF routes from BGP side
*
- * input:
+ * input:
*
* output
* pALRcount count of active local routes
@@ -5104,83 +4765,73 @@ rfapiDeleteRemotePrefixes (
* return value:
* void
--------------------------------------------*/
-void
-rfapiCountAllItRoutes (int *pALRcount, /* active local routes */
- int *pARRcount, /* active remote routes */
- int *pHRcount, /* holddown routes */
- int *pIRcount) /* imported routes */
+void rfapiCountAllItRoutes(int *pALRcount, /* active local routes */
+ int *pARRcount, /* active remote routes */
+ int *pHRcount, /* holddown routes */
+ int *pIRcount) /* imported routes */
{
- struct bgp *bgp;
- struct rfapi *h;
- struct rfapi_import_table *it;
- afi_t afi;
-
- int total_active_local = 0;
- int total_active_remote = 0;
- int total_holddown = 0;
- int total_imported = 0;
-
- bgp = bgp_get_default (); /* assume 1 instance for now */
- assert (bgp);
-
- h = bgp->rfapi;
- assert (h);
-
- /*
- * Iterate over all import tables; do a filtered import
- * for the afi/safi combination
- */
-
- for (it = h->imports; it; it = it->next)
- {
-
- for (afi = AFI_IP; afi < AFI_MAX; ++afi)
- {
-
- total_active_local += it->local_count[afi];
- total_active_remote += it->remote_count[afi];
- total_holddown += it->holddown_count[afi];
- total_imported += it->imported_count[afi];
-
- }
- }
-
- void *cursor;
- int rc;
-
- if (h->import_mac)
- {
- for (cursor = NULL,
- rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor);
- !rc;
- rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor))
- {
-
- total_active_local += it->local_count[AFI_L2VPN];
- total_active_remote += it->remote_count[AFI_L2VPN];
- total_holddown += it->holddown_count[AFI_L2VPN];
- total_imported += it->imported_count[AFI_L2VPN];
-
- }
- }
-
-
- if (pALRcount)
- {
- *pALRcount = total_active_local;
- }
- if (pARRcount)
- {
- *pARRcount = total_active_remote;
- }
- if (pHRcount)
- {
- *pHRcount = total_holddown;
- }
- if (pIRcount)
- {
- *pIRcount = total_imported;
- }
+ struct bgp *bgp;
+ struct rfapi *h;
+ struct rfapi_import_table *it;
+ afi_t afi;
+
+ int total_active_local = 0;
+ int total_active_remote = 0;
+ int total_holddown = 0;
+ int total_imported = 0;
+
+ bgp = bgp_get_default(); /* assume 1 instance for now */
+ assert(bgp);
+
+ h = bgp->rfapi;
+ assert(h);
+
+ /*
+ * Iterate over all import tables; do a filtered import
+ * for the afi/safi combination
+ */
+
+ for (it = h->imports; it; it = it->next) {
+
+ for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
+
+ total_active_local += it->local_count[afi];
+ total_active_remote += it->remote_count[afi];
+ total_holddown += it->holddown_count[afi];
+ total_imported += it->imported_count[afi];
+ }
+ }
+
+ void *cursor;
+ int rc;
+
+ if (h->import_mac) {
+ for (cursor = NULL,
+ rc = skiplist_next(h->import_mac, NULL, (void **)&it,
+ &cursor);
+ !rc; rc = skiplist_next(h->import_mac, NULL, (void **)&it,
+ &cursor)) {
+
+ total_active_local += it->local_count[AFI_L2VPN];
+ total_active_remote += it->remote_count[AFI_L2VPN];
+ total_holddown += it->holddown_count[AFI_L2VPN];
+ total_imported += it->imported_count[AFI_L2VPN];
+ }
+ }
+
+
+ if (pALRcount) {
+ *pALRcount = total_active_local;
+ }
+ if (pARRcount) {
+ *pARRcount = total_active_remote;
+ }
+ if (pHRcount) {
+ *pHRcount = total_holddown;
+ }
+ if (pIRcount) {
+ *pIRcount = total_imported;
+ }
}
/*------------------------------------------
@@ -5188,7 +4839,7 @@ rfapiCountAllItRoutes (int *pALRcount, /* active local routes */
*
* calculate holddown value based on lifetime
*
- * input:
+ * input:
* lifetime lifetime
*
* return value:
@@ -5197,22 +4848,21 @@ rfapiCountAllItRoutes (int *pALRcount, /* active local routes */
*
--------------------------------------------*/
/* hold down time maxes out at RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY */
-uint32_t
-rfapiGetHolddownFromLifetime (uint32_t lifetime)
+uint32_t rfapiGetHolddownFromLifetime(uint32_t lifetime)
{
- uint32_t factor;
- struct bgp *bgp;
-
- bgp = bgp_get_default ();
- if (bgp && bgp->rfapi_cfg)
- factor = bgp->rfapi_cfg->rfp_cfg.holddown_factor;
- else
- factor = RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR;
-
- if (factor < 100 || lifetime < RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY)
- lifetime = lifetime * factor / 100;
- if (lifetime < RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY)
- return lifetime;
- else
- return RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY;
+ uint32_t factor;
+ struct bgp *bgp;
+
+ bgp = bgp_get_default();
+ if (bgp && bgp->rfapi_cfg)
+ factor = bgp->rfapi_cfg->rfp_cfg.holddown_factor;
+ else
+ factor = RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR;
+
+ if (factor < 100 || lifetime < RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY)
+ lifetime = lifetime * factor / 100;
+ if (lifetime < RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY)
+ return lifetime;
+ else
+ return RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY;
}