3 * Copyright 2009-2016, LabN Consulting, L.L.C.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 * File: vnc_import_bgp.c
23 * Purpose: Import routes from BGP unicast directly (not via zebra)
26 #include "lib/zebra.h"
27 #include "lib/prefix.h"
28 #include "lib/agg_table.h"
31 #include "lib/memory.h"
32 #include "lib/linklist.h"
33 #include "lib/plist.h"
34 #include "lib/routemap.h"
35 #include "lib/lib_errors.h"
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_ecommunity.h"
39 #include "bgpd/bgp_attr.h"
40 #include "bgpd/bgp_route.h"
41 #include "bgpd/bgp_mplsvpn.h" /* for RD_TYPE_IP */
43 #include "bgpd/rfapi/vnc_export_bgp.h"
44 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
45 #include "bgpd/rfapi/rfapi.h"
46 #include "bgpd/rfapi/rfapi_import.h"
47 #include "bgpd/rfapi/rfapi_private.h"
48 #include "bgpd/rfapi/rfapi_monitor.h"
49 #include "bgpd/rfapi/rfapi_vty.h"
50 #include "bgpd/rfapi/vnc_import_bgp.h"
51 #include "bgpd/rfapi/vnc_import_bgp_p.h"
52 #include "bgpd/rfapi/vnc_debug.h"
54 #define ENABLE_VNC_RHNCK
56 #define DEBUG_RHN_LIST 0
58 static struct rfapi_descriptor vncHDBgpDirect
; /* dummy nve descriptor */
59 static struct rfapi_descriptor vncHDResolveNve
; /* dummy nve descriptor */
62 * For routes from another AS:
65 * LOCAL_PREF = 255 - MIN(255, MED)
67 * LOCAL_PREF = default_local_pref
69 * For routes from the same AS:
71 * LOCAL_PREF unchanged
73 uint32_t calc_local_pref(struct attr
*attr
, struct peer
*peer
)
75 uint32_t local_pref
= 0;
79 return peer
->bgp
->default_local_pref
;
81 return bgp_get_default()->default_local_pref
;
84 if (peer
&& (peer
->as
!= peer
->bgp
->as
)) {
85 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
86 if (attr
->med
> 255) {
89 local_pref
= 255 - attr
->med
;
92 local_pref
= peer
->bgp
->default_local_pref
;
95 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
96 local_pref
= attr
->local_pref
;
98 if (peer
&& peer
->bgp
) {
99 local_pref
= peer
->bgp
->default_local_pref
;
107 static int is_host_prefix(const struct prefix
*p
)
111 return (p
->prefixlen
== IPV4_MAX_BITLEN
);
113 return (p
->prefixlen
== IPV6_MAX_BITLEN
);
118 /***********************************************************************
120 ***********************************************************************/
123 struct prefix hpfx
; /* ce address = unicast nexthop */
124 struct prefix upfx
; /* unicast prefix */
125 struct bgp_path_info
*ubpi
; /* unicast route */
128 static const uint8_t maskbit
[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
129 0xf8, 0xfc, 0xfe, 0xff};
131 int vnc_prefix_cmp(const void *pfx1
, const void *pfx2
)
137 const struct prefix
*p1
= pfx1
;
138 const struct prefix
*p2
= pfx2
;
140 if (p1
->family
< p2
->family
)
142 if (p1
->family
> p2
->family
)
145 if (p1
->prefixlen
< p2
->prefixlen
)
147 if (p1
->prefixlen
> p2
->prefixlen
)
150 offset
= p1
->prefixlen
/ 8;
151 shift
= p1
->prefixlen
% 8;
152 if (shift
== 0 && offset
) { /* catch aligned case */
157 /* Set both prefix's head pointer. */
158 const uint8_t *pp1
= (const uint8_t *)&p1
->u
.prefix
;
159 const uint8_t *pp2
= (const uint8_t *)&p2
->u
.prefix
;
170 mask
= maskbit
[shift
];
171 if ((*pp1
& mask
) < (*pp2
& mask
))
173 if ((*pp1
& mask
) > (*pp2
& mask
))
179 static void prefix_bag_free(void *pb
)
181 XFREE(MTYPE_RFAPI_PREFIX_BAG
, pb
);
185 static void print_rhn_list(const char *tag1
, const char *tag2
)
189 struct skiplistnode
*p
;
190 struct prefix_bag
*pb
;
193 bgp
= bgp_get_default();
197 sl
= bgp
->frapi
->resolve_nve_nexthop
;
199 vnc_zlog_debug_verbose("%s: %s: RHN List is empty",
200 (tag1
? tag1
: ""), (tag2
? tag2
: ""));
204 vnc_zlog_debug_verbose("%s: %s: RHN list:", (tag1
? tag1
: ""),
207 /* XXX uses secret knowledge of skiplist structure */
208 for (p
= sl
->header
->forward
[0]; p
; p
= p
->forward
[0]) {
211 vnc_zlog_debug_verbose(
212 "RHN Entry %d (q=%p): kpfx=%pFX, upfx=%pFX, hpfx=%pFX, ubpi=%p",
213 ++count
, p
, p
->key
, &pb
->upfx
, &pb
->hpfx
, pb
->ubpi
);
218 #ifdef ENABLE_VNC_RHNCK
219 static void vnc_rhnck(char *tag
)
223 struct skiplistnode
*p
;
225 bgp
= bgp_get_default();
228 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
233 /* XXX uses secret knowledge of skiplist structure */
234 for (p
= sl
->header
->forward
[0]; p
; p
= p
->forward
[0]) {
235 struct prefix_bag
*pb
;
238 struct prefix pfx_orig_nexthop
;
240 memset(&pfx_orig_nexthop
, 0,
241 sizeof(pfx_orig_nexthop
)); /* keep valgrind happy */
246 afi
= family2afi(pb
->upfx
.family
);
248 rfapiUnicastNexthop2Prefix(afi
, pb
->ubpi
->attr
,
251 /* pb->hpfx, pb->ubpi nexthop, pkey should all reflect the same
253 assert(!vnc_prefix_cmp(&pb
->hpfx
, pkey
));
254 if (vnc_prefix_cmp(&pb
->hpfx
, &pfx_orig_nexthop
)) {
255 vnc_zlog_debug_verbose(
256 "%s: %s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
257 __func__
, tag
, &pfx_orig_nexthop
, &pb
->hpfx
);
261 vnc_zlog_debug_verbose("%s: vnc_rhnck OK", tag
);
264 #define VNC_RHNCK(n) \
267 snprintf(buf, sizeof(buf), "%s: %s", __func__, #n); \
277 /***********************************************************************
278 * Add/Delete Unicast Route
279 ***********************************************************************/
282 * "Adding a Route" import process
286 * extract and package information from the BGP unicast route.
287 * Return code 0 means OK, non-0 means drop.
289 * If return code is 0, caller MUST release ecom
291 static int process_unicast_route(struct bgp
*bgp
, /* in */
293 const struct prefix
*prefix
, /* in */
294 struct bgp_path_info
*info
, /* in */
295 struct ecommunity
**ecom
, /* OUT */
296 struct prefix
*unicast_nexthop
) /* OUT */
298 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
299 struct peer
*peer
= info
->peer
;
300 struct attr
*attr
= info
->attr
;
302 struct route_map
*rmap
= NULL
;
303 struct prefix pfx_orig_nexthop
;
305 memset(&pfx_orig_nexthop
, 0,
306 sizeof(pfx_orig_nexthop
)); /* keep valgrind happy */
311 if (hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
312 vnc_zlog_debug_verbose("%s: HC prefix list is set, checking",
314 if (prefix_list_apply(
315 hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
],
318 vnc_zlog_debug_verbose(
319 "%s: prefix list returns DENY, blocking route",
323 vnc_zlog_debug_verbose(
324 "%s: prefix list returns PASS, allowing route",
328 /* apply routemap, if any, later */
329 rmap
= hc
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
332 * Extract original nexthop, which we expect to be a NVE connected
334 * Note that this is the nexthop before any possible application of
338 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
339 * but if v4 it is in attr->nexthop
341 rfapiUnicastNexthop2Prefix(afi
, attr
, &pfx_orig_nexthop
);
345 * This code is here because it allocates an interned attr which
346 * must be freed before we return. It's easier to put it after
347 * all of the possible returns above.
349 memset(&hattr
, 0, sizeof(hattr
));
350 /* hattr becomes a ghost attr */
354 struct bgp_path_info info
;
355 route_map_result_t ret
;
357 memset(&info
, 0, sizeof(info
));
360 ret
= route_map_apply(rmap
, prefix
, &info
);
361 if (ret
== RMAP_DENYMATCH
) {
362 bgp_attr_flush(&hattr
);
363 vnc_zlog_debug_verbose(
364 "%s: route map \"%s\" says DENY, returning",
365 __func__
, rmap
->name
);
371 * Get the (possibly altered by policy) unicast nexthop
372 * for later lookup in the Import Table by caller
374 rfapiUnicastNexthop2Prefix(afi
, &hattr
, unicast_nexthop
);
376 if (bgp_attr_get_ecommunity(&hattr
))
377 *ecom
= ecommunity_dup(bgp_attr_get_ecommunity(&hattr
));
379 *ecom
= ecommunity_new();
382 * Done with hattr, clean up
384 bgp_attr_flush(&hattr
);
387 * Add EC that carries original NH of iBGP route (2 bytes = magic
388 * value indicating it came from an VNC gateway; default 5226, but
389 * must be user configurable). Note that this is the nexthop before
390 * any application of policy.
393 struct ecommunity_val vnc_gateway_magic
;
396 /* Using route origin extended community type */
397 memset(&vnc_gateway_magic
, 0, sizeof(vnc_gateway_magic
));
398 vnc_gateway_magic
.val
[0] = 0x01;
399 vnc_gateway_magic
.val
[1] = 0x03;
401 /* Only works for IPv4 nexthops */
402 if (prefix
->family
== AF_INET
) {
403 memcpy(vnc_gateway_magic
.val
+ 2,
404 &unicast_nexthop
->u
.prefix4
, 4);
406 localadmin
= htons(hc
->resolve_nve_roo_local_admin
);
407 memcpy(vnc_gateway_magic
.val
+ 6, (char *)&localadmin
, 2);
409 ecommunity_add_val(*ecom
, &vnc_gateway_magic
, false, false);
416 static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
417 struct bgp
*bgp
, afi_t afi
, struct bgp_path_info
*bpi
, /* VPN bpi */
418 struct prefix_rd
*prd
, /* RD */
419 const struct prefix
*prefix
, /* unicast route prefix */
420 uint32_t *local_pref
, /* NULL = no local_pref */
421 uint32_t *med
, /* NULL = no med */
422 struct ecommunity
*ecom
) /* generated ecoms */
425 struct prefix nexthop
;
426 struct rfapi_ip_addr nexthop_h
;
429 struct bgp_attr_encap_subtlv
*encaptlvs
;
432 struct rfapi_un_option optary
[3];
433 struct rfapi_un_option
*opt
= NULL
;
436 vnc_zlog_debug_verbose("%s: entry", __func__
);
438 if (bpi
->type
!= ZEBRA_ROUTE_BGP
439 && bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
) {
443 if (bpi
->sub_type
!= BGP_ROUTE_NORMAL
444 && bpi
->sub_type
!= BGP_ROUTE_STATIC
445 && bpi
->sub_type
!= BGP_ROUTE_RFP
) {
449 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
452 vncHDResolveNve
.peer
= bpi
->peer
;
453 if (!rfapiGetVncTunnelUnAddr(bpi
->attr
, &un
)) {
454 if (rfapiQprefix2Raddr(&un
, &vncHDResolveNve
.un_addr
))
457 memset(&vncHDResolveNve
.un_addr
, 0,
458 sizeof(vncHDResolveNve
.un_addr
));
461 /* Use nexthop of VPN route as nexthop of constructed route */
462 rfapiNexthop2Prefix(bpi
->attr
, &nexthop
);
463 rfapiQprefix2Raddr(&nexthop
, &nexthop_h
);
465 if (rfapiGetVncLifetime(bpi
->attr
, &lifetime
)) {
468 plifetime
= &lifetime
;
471 encaptlvs
= bgp_attr_get_vnc_subtlvs(bpi
->attr
);
472 if (bpi
->attr
->encap_tunneltype
!= BGP_ENCAP_TYPE_RESERVED
473 && bpi
->attr
->encap_tunneltype
!= BGP_ENCAP_TYPE_MPLS
) {
474 opt
= &optary
[cur_opt
++];
475 memset(opt
, 0, sizeof(struct rfapi_un_option
));
476 opt
->type
= RFAPI_UN_OPTION_TYPE_TUNNELTYPE
;
477 opt
->v
.tunnel
.type
= bpi
->attr
->encap_tunneltype
;
478 /* TBD parse bpi->attr->extra->encap_subtlvs */
481 struct ecommunity
*new_ecom
= ecommunity_dup(ecom
);
483 if (bgp_attr_get_ecommunity(bpi
->attr
))
484 ecommunity_merge(new_ecom
, bgp_attr_get_ecommunity(bpi
->attr
));
487 label
= decode_label(&bpi
->extra
->label
[0]);
489 add_vnc_route(&vncHDResolveNve
, bgp
, SAFI_MPLS_VPN
,
490 prefix
, /* unicast route prefix */
491 prd
, &nexthop_h
, /* new nexthop */
492 local_pref
, plifetime
,
493 (struct bgp_tea_options
*)encaptlvs
, /* RFP options */
494 opt
, NULL
, new_ecom
, med
, /* NULL => don't set med */
495 (label
? &label
: NULL
), /* NULL= default */
496 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
497 RFAPI_AHR_RFPOPT_IS_VNCTLV
); /* flags */
499 ecommunity_free(&new_ecom
);
502 static void vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
503 struct prefix_rd
*prd
, /* RD */
504 struct bgp_table
*table_rd
, /* per-rd VPN route table */
505 afi_t afi
, struct bgp
*bgp
,
506 const struct prefix
*prefix
, /* unicast prefix */
507 struct ecommunity
*ecom
, /* generated ecoms */
508 uint32_t *local_pref
, /* NULL = no local_pref */
509 uint32_t *med
, /* NULL = no med */
510 struct prefix
*ubpi_nexthop
) /* unicast nexthop */
513 struct bgp_path_info
*bpi
;
518 vnc_zlog_debug_verbose("%s: ubpi_nexthop=%pFX", __func__
, ubpi_nexthop
);
521 bd
= bgp_node_lookup(table_rd
, ubpi_nexthop
);
523 vnc_zlog_debug_verbose(
524 "%s: no match in RD's table for ubpi_nexthop",
529 /* Iterate over bgp_info items at this node */
530 for (bpi
= bgp_dest_get_bgp_path_info(bd
); bpi
; bpi
= bpi
->next
) {
532 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
533 bgp
, afi
, bpi
, /* VPN bpi */
534 prd
, prefix
, local_pref
, med
, ecom
);
537 bgp_dest_unlock_node(bd
);
540 static void vnc_import_bgp_add_route_mode_resolve_nve(
541 struct bgp
*bgp
, const struct prefix
*prefix
, /* unicast prefix */
542 struct bgp_path_info
*info
) /* unicast info */
544 afi_t afi
= family2afi(prefix
->family
);
546 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
548 struct ecommunity
*ecom
= NULL
;
550 uint32_t *med
= NULL
;
552 struct prefix_bag
*pb
;
553 struct bgp_dest
*bdp
; /* prd table node */
556 if (VNC_DEBUG(VERBOSE
)) {
557 char str_nh
[PREFIX_STRLEN
];
561 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &nh
);
563 prefix2str(&nh
, str_nh
, sizeof(str_nh
));
569 vnc_zlog_debug_verbose(
570 "%s(bgp=%p, unicast prefix=%pFX, unicast nh=%s)",
571 __func__
, bgp
, prefix
, str_nh
);
574 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
575 vnc_zlog_debug_verbose(
576 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
577 __func__
, info
->type
, zebra_route_string(info
->type
),
578 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
587 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
592 if (!(bgp
->rfapi_cfg
)) {
593 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
598 /* check vnc redist flag for bgp direct routes */
599 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
600 vnc_zlog_debug_verbose(
601 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
607 if (process_unicast_route(bgp
, afi
, prefix
, info
, &ecom
,
608 &pfx_unicast_nexthop
)) {
610 vnc_zlog_debug_verbose(
611 "%s: process_unicast_route error, skipping", __func__
);
615 local_pref
= calc_local_pref(info
->attr
, info
->peer
);
616 if (info
->attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
617 med
= &info
->attr
->med
;
620 * At this point, we have allocated:
622 * ecom ecommunity ptr, union of unicast and ROO parts (no NVE part)
626 * pfx_unicast_nexthop nexthop of uncast route
629 if (!bgp
->rfapi
->resolve_nve_nexthop
) {
630 bgp
->rfapi
->resolve_nve_nexthop
=
631 skiplist_new(SKIPLIST_FLAG_ALLOW_DUPLICATES
,
632 vnc_prefix_cmp
, prefix_bag_free
);
635 pb
= XCALLOC(MTYPE_RFAPI_PREFIX_BAG
, sizeof(struct prefix_bag
));
636 pb
->hpfx
= pfx_unicast_nexthop
;
640 bgp_path_info_lock(info
); /* skiplist refers to it */
641 skiplist_insert(bgp
->rfapi
->resolve_nve_nexthop
, &pb
->hpfx
, pb
);
644 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
645 * (exact match, /32). If an exact match is found, call add_vnc_route.
648 for (bdp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bdp
;
649 bdp
= bgp_route_next(bdp
)) {
651 struct bgp_table
*table
;
653 table
= bgp_dest_get_bgp_table_info(bdp
);
658 vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
659 (struct prefix_rd
*)bgp_dest_get_prefix(bdp
), table
,
660 afi
, bgp
, prefix
, ecom
, &local_pref
, med
,
661 &pfx_unicast_nexthop
);
666 ecommunity_free(&ecom
);
668 vnc_zlog_debug_verbose("%s: done", __func__
);
672 static void vnc_import_bgp_add_route_mode_plain(struct bgp
*bgp
,
673 const struct prefix
*prefix
,
674 struct bgp_path_info
*info
)
676 afi_t afi
= family2afi(prefix
->family
);
677 struct peer
*peer
= info
->peer
;
678 struct attr
*attr
= info
->attr
;
680 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
681 struct attr
*iattr
= NULL
;
683 struct rfapi_ip_addr vnaddr
;
684 struct prefix vn_pfx_space
;
685 struct prefix
*vn_pfx
= NULL
;
687 struct ecommunity
*ecom
= NULL
;
688 struct prefix_rd prd
;
689 struct route_map
*rmap
= NULL
;
691 uint32_t *med
= NULL
;
693 vnc_zlog_debug_verbose("%s(prefix=%pFX) entry", __func__
, prefix
);
696 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
702 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
707 /* check vnc redist flag for bgp direct routes */
708 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
709 vnc_zlog_debug_verbose(
710 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
716 * mode "plain" specific code
719 vnc_zlog_debug_verbose("%s: NOT using redist RFG", __func__
);
724 if (hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
725 vnc_zlog_debug_verbose(
726 "%s: HC prefix list is set, checking",
728 if (prefix_list_apply(
729 hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
733 vnc_zlog_debug_verbose(
734 "%s: prefix list returns DENY, blocking route",
738 vnc_zlog_debug_verbose(
739 "%s: prefix list returns PASS, allowing route",
743 /* apply routemap, if any, later */
744 rmap
= hc
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
747 * Incoming prefix is unicast. If v6, it is in multiprotocol
749 * but if v4 it is in attr->nexthop
751 rfapiUnicastNexthop2Prefix(afi
, attr
, &vn_pfx_space
);
752 vn_pfx
= &vn_pfx_space
;
755 ahr_flags
|= RFAPI_AHR_NO_TUNNEL_SUBTLV
;
758 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
))
759 vnc_zlog_debug_any("%s vn_pfx=%pFX", __func__
, vn_pfx
);
764 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
765 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
772 * This code is here because it allocates an interned attr which
773 * must be freed before we return. It's easier to put it after
774 * all of the possible returns above.
776 memset(&hattr
, 0, sizeof(hattr
));
777 /* hattr becomes a ghost attr */
781 struct bgp_path_info info
;
782 route_map_result_t ret
;
784 memset(&info
, 0, sizeof(info
));
787 ret
= route_map_apply(rmap
, prefix
, &info
);
788 if (ret
== RMAP_DENYMATCH
) {
789 bgp_attr_flush(&hattr
);
790 vnc_zlog_debug_verbose(
791 "%s: route map \"%s\" says DENY, returning",
792 __func__
, rmap
->name
);
797 iattr
= bgp_attr_intern(&hattr
);
798 bgp_attr_flush(&hattr
);
800 /* Now iattr is an allocated interned attr */
803 * Mode "plain" specific code
805 * Sets RD in dummy HD
809 if (vnaddr
.addr_family
!= AF_INET
) {
810 vnc_zlog_debug_verbose(
811 "%s: can't auto-assign RD, VN AF (%d) is not IPv4, skipping",
812 __func__
, vnaddr
.addr_family
);
814 bgp_attr_unintern(&iattr
);
818 memset(&prd
, 0, sizeof(prd
));
819 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
821 if (iattr
&& bgp_attr_get_ecommunity(iattr
))
822 ecom
= ecommunity_dup(bgp_attr_get_ecommunity(iattr
));
825 local_pref
= calc_local_pref(iattr
, peer
);
827 if (iattr
&& (iattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))) {
831 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
832 char buf
[PREFIX_STRLEN
];
834 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, sizeof(buf
));
835 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
838 vncHDBgpDirect
.peer
= peer
;
839 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
840 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
841 NULL
, /* RFP options */
842 NULL
, NULL
, ecom
, med
, /* med */
843 NULL
, /* label: default */
844 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
846 vncHDBgpDirect
.peer
= NULL
;
849 ecommunity_free(&ecom
);
852 static void vnc_import_bgp_add_route_mode_nvegroup(
853 struct bgp
*bgp
, const struct prefix
*prefix
,
854 struct bgp_path_info
*info
, struct rfapi_nve_group_cfg
*rfg
)
856 afi_t afi
= family2afi(prefix
->family
);
857 struct peer
*peer
= info
->peer
;
858 struct attr
*attr
= info
->attr
;
860 struct attr
*iattr
= NULL
;
862 struct rfapi_ip_addr vnaddr
;
863 struct prefix
*vn_pfx
= NULL
;
865 struct ecommunity
*ecom
= NULL
;
866 struct prefix_rd prd
;
867 struct route_map
*rmap
= NULL
;
870 vnc_zlog_debug_verbose("%s(prefix=%pFX) entry", __func__
, prefix
);
875 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
880 if (!(bgp
->rfapi_cfg
)) {
881 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
886 /* check vnc redist flag for bgp direct routes */
887 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
888 vnc_zlog_debug_verbose(
889 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
900 struct rfapi_ip_prefix pfx_un
;
902 vnc_zlog_debug_verbose("%s: using redist RFG", __func__
);
905 * RFG prefix list check
907 if (rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
908 vnc_zlog_debug_verbose(
909 "%s: RFG prefix list is set, checking",
911 if (prefix_list_apply(
912 rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
916 vnc_zlog_debug_verbose(
917 "%s: prefix list returns DENY, blocking route",
921 vnc_zlog_debug_verbose(
922 "%s: prefix list returns PASS, allowing route",
926 /* apply routemap, if any, later */
927 rmap
= rfg
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
930 * export nve group's VN addr prefix must be a /32 which
931 * will yield the VN addr to use
933 vn_pfx
= &rfg
->vn_prefix
;
938 if (!is_host_prefix(&rfg
->un_prefix
)) {
939 /* NB prefixlen==0 means it has not been configured */
940 vnc_zlog_debug_verbose(
941 "%s: redist RFG UN pfx not host pfx (plen=%d), skipping",
942 __func__
, rfg
->un_prefix
.prefixlen
);
946 rfapiQprefix2Rprefix(&rfg
->un_prefix
, &pfx_un
);
948 vncHDBgpDirect
.un_addr
= pfx_un
.prefix
;
951 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
))
952 vnc_zlog_debug_any("%s vn_pfx=%pFX", __func__
, vn_pfx
);
957 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
958 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
965 * This code is here because it allocates an interned attr which
966 * must be freed before we return. It's easier to put it after
967 * all of the possible returns above.
969 memset(&hattr
, 0, sizeof(hattr
));
970 /* hattr becomes a ghost attr */
974 struct bgp_path_info path
;
975 route_map_result_t ret
;
977 memset(&path
, 0, sizeof(path
));
980 ret
= route_map_apply(rmap
, prefix
, &path
);
981 if (ret
== RMAP_DENYMATCH
) {
982 bgp_attr_flush(&hattr
);
983 vnc_zlog_debug_verbose(
984 "%s: route map \"%s\" says DENY, returning",
985 __func__
, rmap
->name
);
990 iattr
= bgp_attr_intern(&hattr
);
991 bgp_attr_flush(&hattr
);
993 /* Now iattr is an allocated interned attr */
998 * Sets RD in dummy HD
1003 memset(&prd
, 0, sizeof(prd
));
1005 prd
.family
= AF_UNSPEC
;
1008 if (rfg
->rd
.family
== AF_UNIX
) {
1009 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
1012 if (rfg
->rt_export_list
)
1013 ecom
= ecommunity_dup(
1014 bgp
->rfapi_cfg
->rfg_redist
->rt_export_list
);
1016 ecom
= ecommunity_new();
1018 if (iattr
&& bgp_attr_get_ecommunity(iattr
))
1019 ecom
= ecommunity_merge(ecom
,
1020 bgp_attr_get_ecommunity(iattr
));
1023 local_pref
= calc_local_pref(iattr
, peer
);
1025 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
1029 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, BUFSIZ
);
1030 buf
[BUFSIZ
- 1] = 0;
1031 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
1034 vncHDBgpDirect
.peer
= peer
;
1035 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
1036 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
1037 NULL
, /* RFP options */
1038 NULL
, NULL
, ecom
, NULL
, /* med */
1039 NULL
, /* label: default */
1040 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1042 vncHDBgpDirect
.peer
= NULL
;
1045 ecommunity_free(&ecom
);
1048 static void vnc_import_bgp_del_route_mode_plain(struct bgp
*bgp
,
1049 const struct prefix
*prefix
,
1050 struct bgp_path_info
*info
)
1052 struct prefix_rd prd
;
1053 afi_t afi
= family2afi(prefix
->family
);
1054 struct prefix
*vn_pfx
= NULL
;
1055 struct rfapi_ip_addr vnaddr
;
1056 struct prefix vn_pfx_space
;
1062 * Compute VN address
1066 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &vn_pfx_space
);
1068 vnc_zlog_debug_verbose("%s: no attr, can't delete route",
1072 vn_pfx
= &vn_pfx_space
;
1074 vnaddr
.addr_family
= vn_pfx
->family
;
1075 switch (vn_pfx
->family
) {
1077 if (vn_pfx
->prefixlen
!= IPV4_MAX_BITLEN
) {
1078 vnc_zlog_debug_verbose(
1079 "%s: redist VN plen (%d) != 32, skipping",
1080 __func__
, vn_pfx
->prefixlen
);
1083 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1087 if (vn_pfx
->prefixlen
!= IPV6_MAX_BITLEN
) {
1088 vnc_zlog_debug_verbose(
1089 "%s: redist VN plen (%d) != 128, skipping",
1090 __func__
, vn_pfx
->prefixlen
);
1093 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1097 vnc_zlog_debug_verbose(
1098 "%s: no redist RFG VN host pfx configured, skipping",
1104 memset(&prd
, 0, sizeof(prd
));
1105 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1106 vnc_zlog_debug_verbose("%s: can't auto-assign RD, skipping",
1111 vncHDBgpDirect
.peer
= info
->peer
;
1112 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1113 vncHDBgpDirect
.peer
);
1114 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1115 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1118 vncHDBgpDirect
.peer
= NULL
;
1121 static void vnc_import_bgp_del_route_mode_nvegroup(struct bgp
*bgp
,
1122 const struct prefix
*prefix
,
1123 struct bgp_path_info
*info
)
1125 struct prefix_rd prd
;
1126 afi_t afi
= family2afi(prefix
->family
);
1127 struct rfapi_nve_group_cfg
*rfg
= NULL
;
1128 struct prefix
*vn_pfx
= NULL
;
1129 struct rfapi_ip_addr vnaddr
;
1134 rfg
= bgp
->rfapi_cfg
->rfg_redist
;
1138 * Compute VN address
1142 * export nve group's VN addr prefix must be a /32 which
1143 * will yield the VN addr to use
1145 vn_pfx
= &rfg
->vn_prefix
;
1148 vnaddr
.addr_family
= vn_pfx
->family
;
1149 switch (vn_pfx
->family
) {
1151 if (vn_pfx
->prefixlen
!= IPV4_MAX_BITLEN
) {
1152 vnc_zlog_debug_verbose(
1153 "%s: redist VN plen (%d) != 32, skipping",
1154 __func__
, vn_pfx
->prefixlen
);
1157 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1161 if (vn_pfx
->prefixlen
!= IPV6_MAX_BITLEN
) {
1162 vnc_zlog_debug_verbose(
1163 "%s: redist VN plen (%d) != 128, skipping",
1164 __func__
, vn_pfx
->prefixlen
);
1167 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1171 vnc_zlog_debug_verbose(
1172 "%s: no redist RFG VN host pfx configured, skipping",
1177 memset(&prd
, 0, sizeof(prd
));
1179 prd
.family
= AF_UNSPEC
;
1182 if (rfg
->rd
.family
== AF_UNIX
) {
1183 /* means "auto" with VN addr */
1184 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1185 vnc_zlog_debug_verbose(
1186 "%s: can't auto-assign RD, skipping", __func__
);
1192 vncHDBgpDirect
.peer
= info
->peer
;
1193 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1194 vncHDBgpDirect
.peer
);
1195 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1196 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1199 vncHDBgpDirect
.peer
= NULL
;
1202 static void vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1203 struct bgp
*bgp
, afi_t afi
, struct bgp_path_info
*bpi
, /* VPN bpi */
1204 struct prefix_rd
*prd
, /* RD */
1205 const struct prefix
*prefix
) /* unicast route prefix */
1209 if (bpi
->type
!= ZEBRA_ROUTE_BGP
1210 && bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
) {
1214 if (bpi
->sub_type
!= BGP_ROUTE_NORMAL
1215 && bpi
->sub_type
!= BGP_ROUTE_STATIC
1216 && bpi
->sub_type
!= BGP_ROUTE_RFP
) {
1220 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
1223 vncHDResolveNve
.peer
= bpi
->peer
;
1224 if (!rfapiGetVncTunnelUnAddr(bpi
->attr
, &un
)) {
1225 if (rfapiQprefix2Raddr(&un
, &vncHDResolveNve
.un_addr
))
1228 memset(&vncHDResolveNve
.un_addr
, 0,
1229 sizeof(vncHDResolveNve
.un_addr
));
1232 del_vnc_route(&vncHDResolveNve
, vncHDResolveNve
.peer
, bgp
,
1233 SAFI_MPLS_VPN
, prefix
, /* unicast route prefix */
1234 prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
, NULL
,
1238 static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1239 struct prefix_rd
*prd
,
1240 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1241 afi_t afi
, struct bgp
*bgp
,
1242 const struct prefix
*prefix
, /* unicast prefix */
1243 const struct prefix
*ubpi_nexthop
) /* unicast bpi's nexthop */
1245 struct bgp_dest
*bd
;
1246 struct bgp_path_info
*bpi
;
1251 vnc_zlog_debug_verbose("%s: ubpi_nexthop=%pFX", __func__
, ubpi_nexthop
);
1255 bd
= bgp_node_lookup(table_rd
, ubpi_nexthop
);
1257 vnc_zlog_debug_verbose(
1258 "%s: no match in RD's table for ubpi_nexthop",
1263 /* Iterate over bgp_info items at this node */
1264 for (bpi
= bgp_dest_get_bgp_path_info(bd
); bpi
; bpi
= bpi
->next
) {
1266 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1267 bgp
, afi
, bpi
, /* VPN bpi */
1269 prefix
); /* unicast route prefix */
1272 bgp_dest_unlock_node(bd
);
1276 vnc_import_bgp_del_route_mode_resolve_nve(struct bgp
*bgp
, afi_t afi
,
1277 const struct prefix
*prefix
,
1278 struct bgp_path_info
*info
)
1280 struct ecommunity
*ecom
= NULL
;
1281 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
1283 // struct listnode *hnode;
1284 // struct rfapi_descriptor *rfd;
1285 struct prefix_bag
*pb
;
1287 struct skiplist
*sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1289 struct bgp_dest
*bdp
; /* prd table node */
1292 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1297 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
1298 vnc_zlog_debug_verbose(
1299 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
1300 __func__
, info
->type
, zebra_route_string(info
->type
),
1301 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
1305 if (process_unicast_route(bgp
, afi
, prefix
, info
, &ecom
,
1306 &pfx_unicast_nexthop
)) {
1308 vnc_zlog_debug_verbose(
1309 "%s: process_unicast_route error, skipping", __func__
);
1313 rc
= skiplist_first_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1316 if (pb
->ubpi
== info
) {
1317 skiplist_delete(sl
, &pfx_unicast_nexthop
, pb
);
1318 bgp_path_info_unlock(info
);
1321 rc
= skiplist_next_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1326 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
1327 * (exact match, /32). If an exact match is found, call add_vnc_route.
1330 for (bdp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bdp
;
1331 bdp
= bgp_route_next(bdp
)) {
1333 struct bgp_table
*table
;
1335 table
= bgp_dest_get_bgp_table_info(bdp
);
1340 vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1341 (struct prefix_rd
*)bgp_dest_get_prefix(bdp
), table
,
1342 afi
, bgp
, prefix
, &pfx_unicast_nexthop
);
1346 ecommunity_free(&ecom
);
1350 /***********************************************************************
1351 * Add/Delete CE->NVE routes
1352 ***********************************************************************/
1355 * Should be called whan a bpi is added to VPN RIB. This function
1356 * will check if it is a host route and return immediately if not.
1358 void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1359 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1360 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1361 const struct prefix
*prefix
, /* VPN prefix */
1362 struct bgp_path_info
*bpi
) /* new VPN host route */
1364 afi_t afi
= family2afi(prefix
->family
);
1365 struct skiplist
*sl
= NULL
;
1367 struct prefix_bag
*pb
;
1369 struct rfapi_cfg
*hc
= NULL
;
1371 vnc_zlog_debug_verbose("%s: entry", __func__
);
1373 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1374 vnc_zlog_debug_verbose("%s: bad afi %d, skipping", __func__
,
1379 if (!(hc
= bgp
->rfapi_cfg
)) {
1380 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1385 /* check vnc redist flag for bgp direct routes */
1386 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1387 vnc_zlog_debug_verbose(
1388 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1393 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1394 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1400 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1403 vnc_zlog_debug_verbose(
1404 "%s: no resolve_nve_nexthop skiplist, skipping",
1409 if (!is_host_prefix(prefix
)) {
1410 vnc_zlog_debug_verbose("%s: not host prefix, skipping",
1415 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1417 struct ecommunity
*ecom
;
1418 struct prefix pfx_unicast_nexthop
;
1419 uint32_t *med
= NULL
;
1420 uint32_t local_pref
;
1422 memset(&pfx_unicast_nexthop
, 0,
1423 sizeof(pfx_unicast_nexthop
)); /* keep valgrind happy */
1425 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
))
1427 "%s: examining RHN Entry (q=%p): upfx=%pFX, hpfx=%pFX, ubpi=%p",
1428 __func__
, cursor
, &pb
->upfx
, &pb
->hpfx
,
1431 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubpi
, &ecom
,
1432 &pfx_unicast_nexthop
)) {
1434 vnc_zlog_debug_verbose(
1435 "%s: process_unicast_route error, skipping",
1439 local_pref
= calc_local_pref(pb
->ubpi
->attr
, pb
->ubpi
->peer
);
1441 if (pb
->ubpi
->attr
->flag
1442 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
1443 med
= &pb
->ubpi
->attr
->med
;
1448 if (vnc_prefix_cmp(&pfx_unicast_nexthop
, prefix
)) {
1449 vnc_zlog_debug_verbose(
1450 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
1451 __func__
, &pfx_unicast_nexthop
, prefix
);
1455 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
1456 bgp
, afi
, bpi
, /* VPN bpi */
1457 prd
, &pb
->upfx
, /* unicast prefix */
1458 &local_pref
, med
, ecom
);
1461 ecommunity_free(&ecom
);
1466 vnc_zlog_debug_verbose(
1467 "%s: advancing past RHN Entry (q=%p): with prefix %pFX",
1468 __func__
, cursor
, prefix
);
1469 print_rhn_list(__func__
, NULL
); /* debug */
1472 rc
= skiplist_next_value(sl
, prefix
, (void *)&pb
, &cursor
);
1474 vnc_zlog_debug_verbose("%s: done", __func__
);
1478 void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
1479 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1480 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1481 const struct prefix
*prefix
, /* VPN prefix */
1482 struct bgp_path_info
*bpi
) /* old VPN host route */
1484 afi_t afi
= family2afi(prefix
->family
);
1485 struct skiplist
*sl
= NULL
;
1486 struct prefix_bag
*pb
;
1488 struct rfapi_cfg
*hc
= NULL
;
1491 vnc_zlog_debug_verbose("%s(bgp=%p, nve prefix=%pFX)", __func__
, bgp
,
1494 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
)
1497 if (!(hc
= bgp
->rfapi_cfg
)) {
1498 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1503 /* check vnc redist flag for bgp direct routes */
1504 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1505 vnc_zlog_debug_verbose(
1506 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1511 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1512 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1518 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1521 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1526 if (!is_host_prefix(prefix
)) {
1527 vnc_zlog_debug_verbose("%s: not host route, skip", __func__
);
1532 * Find all entries with key == CE in the RHN list
1534 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1537 struct ecommunity
*ecom
;
1538 struct prefix pfx_unicast_nexthop
;
1540 memset(&pfx_unicast_nexthop
, 0,
1541 sizeof(pfx_unicast_nexthop
)); /* keep valgrind happy */
1543 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubpi
, &ecom
,
1544 &pfx_unicast_nexthop
)) {
1546 vnc_zlog_debug_verbose(
1547 "%s: process_unicast_route error, skipping",
1555 if (vnc_prefix_cmp(&pfx_unicast_nexthop
, prefix
)) {
1556 vnc_zlog_debug_verbose(
1557 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
1558 __func__
, &pfx_unicast_nexthop
, prefix
);
1562 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1563 bgp
, afi
, bpi
, prd
, &pb
->upfx
);
1566 ecommunity_free(&ecom
);
1568 rc
= skiplist_next_value(sl
, prefix
, (void *)&pb
, &cursor
);
1573 /***********************************************************************
1575 ***********************************************************************/
1577 #define DEBUG_IS_USABLE_INTERIOR 1
1579 static int is_usable_interior_route(struct bgp_path_info
*bpi_interior
)
1581 if (!VALID_INTERIOR_TYPE(bpi_interior
->type
)) {
1582 #if DEBUG_IS_USABLE_INTERIOR
1583 vnc_zlog_debug_verbose(
1584 "%s: NO: type %d is not valid interior type", __func__
,
1585 bpi_interior
->type
);
1589 if (!CHECK_FLAG(bpi_interior
->flags
, BGP_PATH_VALID
)) {
1590 #if DEBUG_IS_USABLE_INTERIOR
1591 vnc_zlog_debug_verbose("%s: NO: BGP_PATH_VALID not set",
1600 * There should be only one of these per prefix at a time.
1601 * This should be called as a result of selection operation
1603 * NB should be called espacially for bgp instances that are named,
1604 * because the exterior routes will always come from one of those.
1605 * We filter here on the instance name to make sure we get only the
1608 static void vnc_import_bgp_exterior_add_route_it(
1609 struct bgp
*bgp
, /* exterior instance, we hope */
1610 const struct prefix
*prefix
, /* unicast prefix */
1611 struct bgp_path_info
*info
, /* unicast info */
1612 struct rfapi_import_table
*it_only
) /* NULL, or limit to this IT */
1615 struct rfapi_cfg
*hc
;
1616 struct prefix pfx_orig_nexthop
;
1617 struct rfapi_import_table
*it
;
1618 struct bgp
*bgp_default
= bgp_get_default();
1619 afi_t afi
= family2afi(prefix
->family
);
1624 h
= bgp_default
->rfapi
;
1625 hc
= bgp_default
->rfapi_cfg
;
1627 vnc_zlog_debug_verbose("%s: entry with it=%p", __func__
, it_only
);
1630 vnc_zlog_debug_verbose(
1631 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1635 if (!hc
->redist_bgp_exterior_view
) {
1636 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1640 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1641 vnc_zlog_debug_verbose(
1642 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1643 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1647 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1648 vnc_zlog_debug_verbose(
1649 "%s: redist of exterior routes not enabled, skipping",
1655 * Extract nexthop from exterior route
1657 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1658 * but if v4 it is in attr->nexthop
1660 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1662 for (it
= h
->imports
; it
; it
= it
->next
) {
1663 struct agg_table
*table
;
1664 struct agg_node
*rn
;
1665 struct agg_node
*par
;
1666 struct bgp_path_info
*bpi_interior
;
1667 int have_usable_route
;
1669 vnc_zlog_debug_verbose("%s: doing it %p", __func__
, it
);
1671 if (it_only
&& (it_only
!= it
)) {
1672 vnc_zlog_debug_verbose("%s: doesn't match it_only %p",
1677 table
= it
->imported_vpn
[afi
];
1679 for (rn
= agg_node_match(table
, &pfx_orig_nexthop
),
1680 have_usable_route
= 0;
1681 (!have_usable_route
) && rn
;) {
1683 vnc_zlog_debug_verbose("%s: it %p trying rn %p",
1686 for (bpi_interior
= rn
->info
; bpi_interior
;
1687 bpi_interior
= bpi_interior
->next
) {
1688 struct prefix_rd
*prd
;
1689 struct attr new_attr
;
1692 if (!is_usable_interior_route(bpi_interior
))
1695 vnc_zlog_debug_verbose(
1696 "%s: usable: bpi_interior %p", __func__
,
1700 * have a legitimate route to exterior's nexthop
1703 * Import unicast route to the import table
1705 have_usable_route
= 1;
1707 if (bpi_interior
->extra
) {
1708 prd
= &bpi_interior
->extra
->vnc
.import
1710 label
= decode_label(
1711 &bpi_interior
->extra
->label
[0]);
1715 /* use local_pref from unicast route */
1716 memset(&new_attr
, 0, sizeof(new_attr
));
1717 new_attr
= *bpi_interior
->attr
;
1718 if (info
->attr
->flag
1719 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
1720 new_attr
.local_pref
=
1721 info
->attr
->local_pref
;
1722 new_attr
.flag
|= ATTR_FLAG_BIT(
1723 BGP_ATTR_LOCAL_PREF
);
1726 rfapiBgpInfoFilteredImportVPN(
1727 it
, FIF_ACTION_UPDATE
,
1728 bpi_interior
->peer
, NULL
, /* rfd */
1729 prefix
, NULL
, afi
, prd
, &new_attr
,
1730 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1731 BGP_ROUTE_REDISTRIBUTE
, &label
);
1734 if (have_usable_route
) {
1738 * TBD factor this out into its own function
1740 struct prefix
*pfx_mon
= prefix_new();
1741 if (!RFAPI_MONITOR_EXTERIOR(rn
)->source
) {
1742 RFAPI_MONITOR_EXTERIOR(rn
)->source
=
1746 agg_lock_node(rn
); /* for skiplist */
1748 agg_lock_node(rn
); /* for skiplist entry */
1749 prefix_copy(pfx_mon
, prefix
);
1750 if (!skiplist_insert(
1751 RFAPI_MONITOR_EXTERIOR(rn
)->source
,
1754 bgp_path_info_lock(info
);
1757 par
= agg_node_parent(rn
);
1760 agg_unlock_node(rn
);
1764 agg_unlock_node(rn
);
1766 if (!have_usable_route
) {
1767 struct prefix
*pfx_mon
= prefix_new();
1768 prefix_copy(pfx_mon
, prefix
);
1769 if (!skiplist_insert(it
->monitor_exterior_orphans
, info
,
1772 bgp_path_info_lock(info
);
1778 void vnc_import_bgp_exterior_add_route(
1779 struct bgp
*bgp
, /* exterior instance, we hope */
1780 const struct prefix
*prefix
, /* unicast prefix */
1781 struct bgp_path_info
*info
) /* unicast info */
1783 vnc_import_bgp_exterior_add_route_it(bgp
, prefix
, info
, NULL
);
1787 * There should be only one of these per prefix at a time.
1788 * This should probably be called as a result of selection operation.
1790 * NB should be called espacially for bgp instances that are named,
1791 * because the exterior routes will always come from one of those.
1792 * We filter here on the instance name to make sure we get only the
1795 void vnc_import_bgp_exterior_del_route(
1796 struct bgp
*bgp
, const struct prefix
*prefix
, /* unicast prefix */
1797 struct bgp_path_info
*info
) /* unicast info */
1800 struct rfapi_cfg
*hc
;
1801 struct rfapi_import_table
*it
;
1802 struct prefix pfx_orig_nexthop
;
1803 afi_t afi
= family2afi(prefix
->family
);
1804 struct bgp
*bgp_default
= bgp_get_default();
1809 memset(&pfx_orig_nexthop
, 0,
1810 sizeof(pfx_orig_nexthop
)); /* keep valgrind happy */
1812 h
= bgp_default
->rfapi
;
1813 hc
= bgp_default
->rfapi_cfg
;
1816 vnc_zlog_debug_verbose(
1817 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1821 if (!hc
->redist_bgp_exterior_view
) {
1822 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1826 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1827 vnc_zlog_debug_verbose(
1828 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1829 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1832 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1833 vnc_zlog_debug_verbose(
1834 "%s: redist of exterior routes no enabled, skipping",
1840 * Extract nexthop from exterior route
1842 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1843 * but if v4 it is in attr->nexthop
1845 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1847 for (it
= h
->imports
; it
; it
= it
->next
) {
1848 struct agg_table
*table
;
1849 struct agg_node
*rn
;
1850 struct agg_node
*par
;
1851 struct bgp_path_info
*bpi_interior
;
1852 int have_usable_route
;
1854 table
= it
->imported_vpn
[afi
];
1856 for (rn
= agg_node_match(table
, &pfx_orig_nexthop
),
1857 have_usable_route
= 0;
1858 (!have_usable_route
) && rn
;) {
1860 for (bpi_interior
= rn
->info
; bpi_interior
;
1861 bpi_interior
= bpi_interior
->next
) {
1862 struct prefix_rd
*prd
;
1865 if (!is_usable_interior_route(bpi_interior
))
1869 * have a legitimate route to exterior's nexthop
1872 * Import unicast route to the import table
1874 have_usable_route
= 1;
1876 if (bpi_interior
->extra
) {
1877 prd
= &bpi_interior
->extra
->vnc
.import
1879 label
= decode_label(
1880 &bpi_interior
->extra
->label
[0]);
1884 rfapiBgpInfoFilteredImportVPN(
1885 it
, FIF_ACTION_KILL
, bpi_interior
->peer
,
1887 prefix
, NULL
, afi
, prd
,
1889 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1890 BGP_ROUTE_REDISTRIBUTE
, &label
);
1895 * TBD factor this out into its own function
1898 if (RFAPI_MONITOR_EXTERIOR(rn
)
1900 if (!skiplist_delete(
1901 RFAPI_MONITOR_EXTERIOR(
1906 bgp_path_info_unlock(
1913 RFAPI_MONITOR_EXTERIOR(
1917 RFAPI_MONITOR_EXTERIOR(
1920 RFAPI_MONITOR_EXTERIOR(
1931 par
= agg_node_parent(rn
);
1934 agg_unlock_node(rn
);
1938 agg_unlock_node(rn
);
1940 if (!have_usable_route
) {
1941 if (!skiplist_delete(it
->monitor_exterior_orphans
, info
,
1944 bgp_path_info_unlock(info
);
1951 * This function should be called after a new interior VPN route
1952 * has been added to an import_table.
1954 * NB should also be called whenever an existing vpn interior route
1955 * becomes valid (e.g., valid_interior_count is inremented)
1957 void vnc_import_bgp_exterior_add_route_interior(
1958 struct bgp
*bgp
, struct rfapi_import_table
*it
,
1959 struct agg_node
*rn_interior
, /* VPN IT node */
1960 struct bgp_path_info
*bpi_interior
) /* VPN IT route */
1962 const struct prefix
*p
= agg_node_get_prefix(rn_interior
);
1963 afi_t afi
= family2afi(p
->family
);
1964 struct agg_node
*par
;
1965 struct bgp_path_info
*bpi_exterior
;
1966 struct prefix
*pfx_exterior
; /* exterior pfx */
1969 struct list
*list_adopted
;
1971 vnc_zlog_debug_verbose("%s: entry", __func__
);
1973 if (!is_usable_interior_route(bpi_interior
)) {
1974 vnc_zlog_debug_verbose(
1975 "%s: not usable interior route, skipping", __func__
);
1979 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1980 vnc_zlog_debug_verbose(
1981 "%s: redist of exterior routes no enabled, skipping",
1986 if (it
== bgp
->rfapi
->it_ce
) {
1987 vnc_zlog_debug_verbose("%s: import table is it_ce, skipping",
1993 vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
1994 __func__
, rn_interior
, bpi_interior
->type
);
1996 if (RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
1998 int count
= 0; /* debugging */
2000 vnc_zlog_debug_verbose(
2001 "%s: has exterior monitor; ext src: %p", __func__
,
2002 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2005 * There is a monitor here already. Therefore, we do not need
2006 * to do any pulldown. Just construct exterior routes based
2007 * on the new interior route.
2010 for (rc
= skiplist_next(
2011 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2012 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2014 !rc
; rc
= skiplist_next(
2015 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2016 (void **)&bpi_exterior
,
2017 (void **)&pfx_exterior
, &cursor
)) {
2019 struct prefix_rd
*prd
;
2020 struct attr new_attr
;
2024 ++count
; /* debugging */
2026 assert(bpi_exterior
);
2027 assert(pfx_exterior
);
2029 if (bpi_interior
->extra
) {
2030 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2031 label
= decode_label(
2032 &bpi_interior
->extra
->label
[0]);
2036 /* use local_pref from unicast route */
2037 memset(&new_attr
, 0, sizeof(struct attr
));
2038 new_attr
= *bpi_interior
->attr
;
2040 && (bpi_exterior
->attr
->flag
2041 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2042 new_attr
.local_pref
=
2043 bpi_exterior
->attr
->local_pref
;
2045 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2048 rfapiBgpInfoFilteredImportVPN(
2049 it
, FIF_ACTION_UPDATE
, bpi_interior
->peer
,
2051 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2052 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2053 BGP_ROUTE_REDISTRIBUTE
, &label
);
2055 vnc_zlog_debug_verbose(
2056 "%s: finished constructing exteriors based on existing monitors",
2061 vnc_zlog_debug_verbose("%s: no exterior monitor", __func__
);
2064 * No monitor at this node. Is this the first valid interior
2065 * route at this node?
2067 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
> 1) {
2068 vnc_zlog_debug_verbose(
2069 "%s: new interior route not first valid one, skipping pulldown",
2075 * Look up the tree for possible pulldown candidates.
2076 * Find nearest parent with an exterior route monitor
2078 for (par
= agg_node_parent(rn_interior
); par
;
2079 par
= agg_node_parent(par
)) {
2080 if (RFAPI_HAS_MONITOR_EXTERIOR(par
))
2086 vnc_zlog_debug_verbose(
2087 "%s: checking parent %p for possible pulldowns",
2090 /* check monitors at par for possible pulldown */
2092 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2093 (void **)&bpi_exterior
,
2094 (void **)&pfx_exterior
, &cursor
);
2096 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2097 (void **)&bpi_exterior
,
2098 (void **)&pfx_exterior
, &cursor
)) {
2100 struct prefix pfx_nexthop
;
2102 memset(&pfx_nexthop
, 0,
2103 sizeof(struct prefix
)); /* keep valgrind happy */
2105 /* check original nexthop for prefix match */
2106 rfapiUnicastNexthop2Prefix(afi
, bpi_exterior
->attr
,
2109 if (prefix_match(p
, &pfx_nexthop
)) {
2111 struct bgp_path_info
*bpi
;
2112 struct prefix_rd
*prd
;
2113 struct attr new_attr
;
2119 * add monitor to longer prefix
2121 struct prefix
*pfx_mon
= prefix_new();
2122 prefix_copy(pfx_mon
, pfx_exterior
);
2123 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)
2125 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2126 ->source
= skiplist_new(
2127 0, NULL
, prefix_free_lists
);
2128 agg_lock_node(rn_interior
);
2131 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2133 bpi_exterior
, pfx_mon
);
2134 agg_lock_node(rn_interior
);
2137 * Delete constructed exterior routes based on
2140 for (bpi
= par
->info
; bpi
; bpi
= bpi
->next
) {
2143 prd
= &bpi
->extra
->vnc
.import
2145 label
= decode_label(
2146 &bpi
->extra
->label
[0]);
2150 rfapiBgpInfoFilteredImportVPN(
2151 it
, FIF_ACTION_KILL
, bpi
->peer
,
2153 pfx_exterior
, NULL
, afi
, prd
,
2155 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2156 BGP_ROUTE_REDISTRIBUTE
, &label
);
2161 * Add constructed exterior routes based on
2162 * the new interior route at longer prefix.
2164 if (bpi_interior
->extra
) {
2165 prd
= &bpi_interior
->extra
->vnc
.import
2167 label
= decode_label(
2168 &bpi_interior
->extra
->label
[0]);
2172 /* use local_pref from unicast route */
2173 memset(&new_attr
, 0, sizeof(struct attr
));
2174 new_attr
= *bpi_interior
->attr
;
2176 && (bpi_exterior
->attr
->flag
2177 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2178 new_attr
.local_pref
=
2179 bpi_exterior
->attr
->local_pref
;
2180 new_attr
.flag
|= ATTR_FLAG_BIT(
2181 BGP_ATTR_LOCAL_PREF
);
2184 rfapiBgpInfoFilteredImportVPN(
2185 it
, FIF_ACTION_UPDATE
,
2186 bpi_interior
->peer
, NULL
, /* rfd */
2187 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2188 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2189 BGP_ROUTE_REDISTRIBUTE
, &label
);
2194 * The only monitors at rn_interior are the ones we added just
2195 * above, so we can use the rn_interior list to identify which
2196 * monitors to delete from the parent.
2199 for (rc
= skiplist_next(
2200 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2201 (void **)&bpi_exterior
, NULL
, &cursor
);
2202 !rc
; rc
= skiplist_next(
2203 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2204 (void **)&bpi_exterior
, NULL
, &cursor
)) {
2207 skiplist_delete(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2208 bpi_exterior
, NULL
);
2209 agg_unlock_node(par
); /* sl entry */
2211 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par
)->source
)) {
2212 skiplist_free(RFAPI_MONITOR_EXTERIOR(par
)->source
);
2213 RFAPI_MONITOR_EXTERIOR(par
)->source
= NULL
;
2214 agg_unlock_node(par
); /* sl itself */
2218 vnc_zlog_debug_verbose("%s: checking orphans", __func__
);
2221 * See if any orphans can be pulled down to the current node
2224 list_adopted
= NULL
;
2225 for (rc
= skiplist_next(it
->monitor_exterior_orphans
,
2226 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2228 !rc
; rc
= skiplist_next(it
->monitor_exterior_orphans
,
2229 (void **)&bpi_exterior
,
2230 (void **)&pfx_exterior
, &cursor
)) {
2232 struct prefix pfx_nexthop
;
2233 afi_t afi_exterior
= family2afi(pfx_exterior
->family
);
2235 vnc_zlog_debug_verbose(
2236 "%s: checking exterior orphan at prefix %pFX", __func__
,
2239 if (afi_exterior
!= afi
) {
2240 vnc_zlog_debug_verbose(
2241 "%s: exterior orphan afi %d != interior afi %d, skip",
2242 __func__
, afi_exterior
, afi
);
2246 /* check original nexthop for prefix match */
2247 rfapiUnicastNexthop2Prefix(afi
, bpi_exterior
->attr
,
2250 if (prefix_match(p
, &pfx_nexthop
)) {
2252 struct prefix_rd
*prd
;
2253 struct attr new_attr
;
2259 * add monitor to longer prefix
2262 struct prefix
*pfx_mon
= prefix_new();
2263 prefix_copy(pfx_mon
, pfx_exterior
);
2264 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
) {
2265 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
=
2267 0, NULL
, prefix_free_lists
);
2268 agg_lock_node(rn_interior
); /* sl */
2271 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2272 bpi_exterior
, pfx_mon
);
2273 agg_lock_node(rn_interior
); /* sl entry */
2274 if (!list_adopted
) {
2275 list_adopted
= list_new();
2277 listnode_add(list_adopted
, bpi_exterior
);
2280 * Add constructed exterior routes based on the
2281 * new interior route at the longer prefix.
2283 if (bpi_interior
->extra
) {
2284 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2285 label
= decode_label(
2286 &bpi_interior
->extra
->label
[0]);
2290 /* use local_pref from unicast route */
2291 memset(&new_attr
, 0, sizeof(struct attr
));
2292 new_attr
= *bpi_interior
->attr
;
2294 && (bpi_exterior
->attr
->flag
2295 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2296 new_attr
.local_pref
=
2297 bpi_exterior
->attr
->local_pref
;
2299 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2302 rfapiBgpInfoFilteredImportVPN(
2303 it
, FIF_ACTION_UPDATE
, bpi_interior
->peer
,
2305 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2306 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2307 BGP_ROUTE_REDISTRIBUTE
, &label
);
2311 struct listnode
*node
;
2312 struct agg_node
*an_bpi_exterior
;
2314 for (ALL_LIST_ELEMENTS_RO(list_adopted
, node
,
2316 skiplist_delete(it
->monitor_exterior_orphans
,
2317 an_bpi_exterior
, NULL
);
2319 list_delete(&list_adopted
);
2324 * This function should be called after an interior VPN route
2325 * has been deleted from an import_table.
2326 * bpi_interior must still be valid, but it must already be detached
2327 * from its route node and the route node's valid_interior_count
2328 * must already be decremented.
2330 * NB should also be called whenever an existing vpn interior route
2331 * becomes invalid (e.g., valid_interior_count is decremented)
2333 void vnc_import_bgp_exterior_del_route_interior(
2334 struct bgp
*bgp
, struct rfapi_import_table
*it
,
2335 struct agg_node
*rn_interior
, /* VPN IT node */
2336 struct bgp_path_info
*bpi_interior
) /* VPN IT route */
2338 const struct prefix
*p
= agg_node_get_prefix(rn_interior
);
2339 afi_t afi
= family2afi(p
->family
);
2340 struct agg_node
*par
;
2341 struct bgp_path_info
*bpi_exterior
;
2342 struct prefix
*pfx_exterior
; /* exterior pfx */
2346 if (!VALID_INTERIOR_TYPE(bpi_interior
->type
)) {
2347 vnc_zlog_debug_verbose(
2348 "%s: type %d not valid interior type, skipping",
2349 __func__
, bpi_interior
->type
);
2353 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2354 vnc_zlog_debug_verbose(
2355 "%s: redist of exterior routes no enabled, skipping",
2360 if (it
== bgp
->rfapi
->it_ce
) {
2361 vnc_zlog_debug_verbose("%s: it is it_ce, skipping", __func__
);
2365 /* If no exterior routes depend on this prefix, nothing to do */
2366 if (!RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
2367 vnc_zlog_debug_verbose("%s: no exterior monitor, skipping",
2373 vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
2374 __func__
, rn_interior
, bpi_interior
->type
);
2377 * Remove constructed routes based on the deleted interior route
2380 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2381 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2384 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2385 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2388 struct prefix_rd
*prd
;
2391 if (bpi_interior
->extra
) {
2392 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2393 label
= decode_label(&bpi_interior
->extra
->label
[0]);
2397 rfapiBgpInfoFilteredImportVPN(
2398 it
, FIF_ACTION_KILL
, bpi_interior
->peer
, NULL
, /* rfd */
2399 pfx_exterior
, NULL
, afi
, prd
, bpi_interior
->attr
,
2400 ZEBRA_ROUTE_BGP_DIRECT_EXT
, BGP_ROUTE_REDISTRIBUTE
,
2405 * If there are no remaining valid interior routes at this prefix,
2406 * we need to look up the tree for a possible node to move monitors to
2408 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
) {
2409 vnc_zlog_debug_verbose(
2410 "%s: interior routes still present, skipping",
2416 * Find nearest parent with at least one valid interior route
2417 * If none is found, par will end up NULL, and we will move
2418 * the monitors to the orphan list for this import table
2420 for (par
= agg_node_parent(rn_interior
); par
;
2421 par
= agg_node_parent(par
)) {
2422 if (RFAPI_MONITOR_EXTERIOR(par
)->valid_interior_count
)
2426 vnc_zlog_debug_verbose("%s: par=%p, ext src: %p", __func__
, par
,
2427 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2429 /* move all monitors */
2431 * We will use and delete every element of the source skiplist
2433 while (!skiplist_first(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2434 (void **)&bpi_exterior
,
2435 (void **)&pfx_exterior
)) {
2437 struct prefix
*pfx_mon
= prefix_new();
2439 prefix_copy(pfx_mon
, pfx_exterior
);
2443 struct bgp_path_info
*bpi
;
2446 * Add monitor to parent node
2448 if (!RFAPI_MONITOR_EXTERIOR(par
)->source
) {
2449 RFAPI_MONITOR_EXTERIOR(par
)->source
=
2451 0, NULL
, prefix_free_lists
);
2452 agg_lock_node(par
); /* sl */
2454 skiplist_insert(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2455 bpi_exterior
, pfx_mon
);
2456 agg_lock_node(par
); /* sl entry */
2458 /* Add constructed exterior routes based on parent */
2459 for (bpi
= par
->info
; bpi
; bpi
= bpi
->next
) {
2461 struct prefix_rd
*prd
;
2462 struct attr new_attr
;
2465 if (bpi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
)
2469 prd
= &bpi
->extra
->vnc
.import
.rd
;
2470 label
= decode_label(
2471 &bpi
->extra
->label
[0]);
2475 /* use local_pref from unicast route */
2476 memset(&new_attr
, 0, sizeof(new_attr
));
2477 new_attr
= *bpi
->attr
;
2479 && (bpi_exterior
->attr
->flag
2480 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2481 new_attr
.local_pref
=
2482 bpi_exterior
->attr
->local_pref
;
2483 new_attr
.flag
|= ATTR_FLAG_BIT(
2484 BGP_ATTR_LOCAL_PREF
);
2487 rfapiBgpInfoFilteredImportVPN(
2488 it
, FIF_ACTION_UPDATE
, bpi
->peer
,
2490 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2491 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2492 BGP_ROUTE_REDISTRIBUTE
, &label
);
2498 * No interior route for exterior's nexthop. Save
2500 * in orphan list to await future route.
2502 skiplist_insert(it
->monitor_exterior_orphans
,
2503 bpi_exterior
, pfx_mon
);
2506 skiplist_delete_first(
2507 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2508 agg_unlock_node(rn_interior
); /* sl entry */
2510 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
)) {
2511 skiplist_free(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2512 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
= NULL
;
2513 agg_unlock_node(rn_interior
); /* sl itself */
2517 /***********************************************************************
2518 * Generic add/delete unicast routes
2519 ***********************************************************************/
2521 void vnc_import_bgp_add_route(struct bgp
*bgp
, const struct prefix
*prefix
,
2522 struct bgp_path_info
*info
)
2524 afi_t afi
= family2afi(prefix
->family
);
2526 if (VNC_DEBUG(VERBOSE
)) {
2527 struct prefix pfx_nexthop
;
2529 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2530 vnc_zlog_debug_verbose("%s: pfx %pFX, nh %pFX", __func__
,
2531 prefix
, &pfx_nexthop
);
2534 print_rhn_list(__func__
, "ENTER ");
2539 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
2544 if (!bgp
->rfapi_cfg
) {
2545 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2550 /* check vnc redist flag for bgp direct routes */
2551 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2552 vnc_zlog_debug_verbose(
2553 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
2554 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2558 switch (bgp
->rfapi_cfg
->redist_mode
) {
2559 case VNC_REDIST_MODE_PLAIN
:
2560 vnc_import_bgp_add_route_mode_plain(bgp
, prefix
, info
);
2563 case VNC_REDIST_MODE_RFG
:
2564 if (bgp
->rfapi_cfg
->rfg_redist
)
2565 vnc_import_bgp_add_route_mode_nvegroup(
2566 bgp
, prefix
, info
, bgp
->rfapi_cfg
->rfg_redist
);
2568 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2572 case VNC_REDIST_MODE_RESOLVE_NVE
:
2573 vnc_import_bgp_add_route_mode_resolve_nve(bgp
, prefix
, info
);
2577 print_rhn_list(__func__
, "LEAVE ");
2583 * "Withdrawing a Route" import process
2585 void vnc_import_bgp_del_route(struct bgp
*bgp
, const struct prefix
*prefix
,
2586 struct bgp_path_info
*info
) /* unicast info */
2588 afi_t afi
= family2afi(prefix
->family
);
2593 struct prefix pfx_nexthop
;
2595 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2596 vnc_zlog_debug_verbose("%s: pfx %pFX, nh %pFX", __func__
,
2597 prefix
, &pfx_nexthop
);
2600 print_rhn_list(__func__
, "ENTER ");
2604 if (!bgp
->rfapi_cfg
) {
2605 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2610 /* check bgp redist flag for vnc direct ("vpn") routes */
2611 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2612 vnc_zlog_debug_verbose(
2613 "%s: bgp redistribution of afi=%d VNC direct routes is off",
2618 switch (bgp
->rfapi_cfg
->redist_mode
) {
2619 case VNC_REDIST_MODE_PLAIN
:
2620 vnc_import_bgp_del_route_mode_plain(bgp
, prefix
, info
);
2623 case VNC_REDIST_MODE_RFG
:
2624 if (bgp
->rfapi_cfg
->rfg_redist
)
2625 vnc_import_bgp_del_route_mode_nvegroup(bgp
, prefix
,
2628 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2632 case VNC_REDIST_MODE_RESOLVE_NVE
:
2633 vnc_import_bgp_del_route_mode_resolve_nve(bgp
, afi
, prefix
,
2638 print_rhn_list(__func__
, "LEAVE ");
2644 /***********************************************************************
2646 ***********************************************************************/
2648 void vnc_import_bgp_redist_enable(struct bgp
*bgp
, afi_t afi
)
2650 /* iterate over bgp unicast v4 and v6 routes, call
2651 * vnc_import_bgp_add_route */
2653 struct bgp_dest
*dest
;
2655 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
2657 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2658 vnc_zlog_debug_verbose(
2659 "%s: already enabled for afi %d, skipping", __func__
,
2663 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 1;
2665 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); dest
;
2666 dest
= bgp_route_next(dest
)) {
2668 struct bgp_path_info
*bpi
;
2670 for (bpi
= bgp_dest_get_bgp_path_info(dest
); bpi
;
2673 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2676 vnc_import_bgp_add_route(bgp
, bgp_dest_get_prefix(dest
),
2680 vnc_zlog_debug_verbose(
2681 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2682 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2685 void vnc_import_bgp_exterior_redist_enable(struct bgp
*bgp
, afi_t afi
)
2687 struct bgp
*bgp_exterior
;
2688 struct bgp_dest
*dest
;
2690 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2692 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2693 vnc_zlog_debug_verbose(
2694 "%s: already enabled for afi %d, skipping", __func__
,
2698 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 1;
2700 if (!bgp_exterior
) {
2701 vnc_zlog_debug_verbose(
2702 "%s: no exterior view set yet, no routes to import yet",
2707 for (dest
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); dest
;
2708 dest
= bgp_route_next(dest
)) {
2710 struct bgp_path_info
*bpi
;
2712 for (bpi
= bgp_dest_get_bgp_path_info(dest
); bpi
;
2715 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2718 vnc_import_bgp_exterior_add_route(
2719 bgp_exterior
, bgp_dest_get_prefix(dest
), bpi
);
2722 vnc_zlog_debug_verbose(
2723 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2724 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2728 * This function is for populating a newly-created Import Table
2730 void vnc_import_bgp_exterior_redist_enable_it(
2731 struct bgp
*bgp
, afi_t afi
, struct rfapi_import_table
*it_only
)
2733 struct bgp
*bgp_exterior
;
2734 struct bgp_dest
*dest
;
2736 vnc_zlog_debug_verbose("%s: entry", __func__
);
2738 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2740 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2741 vnc_zlog_debug_verbose("%s: not enabled for afi %d, skipping",
2746 if (!bgp_exterior
) {
2747 vnc_zlog_debug_verbose(
2748 "%s: no exterior view set yet, no routes to import yet",
2753 for (dest
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); dest
;
2754 dest
= bgp_route_next(dest
)) {
2756 struct bgp_path_info
*bpi
;
2758 for (bpi
= bgp_dest_get_bgp_path_info(dest
); bpi
;
2761 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2764 vnc_import_bgp_exterior_add_route_it(
2765 bgp_exterior
, bgp_dest_get_prefix(dest
), bpi
,
2772 void vnc_import_bgp_redist_disable(struct bgp
*bgp
, afi_t afi
)
2775 * iterate over vpn routes, find routes of type ZEBRA_ROUTE_BGP_DIRECT,
2776 * delete (call timer expire immediately)
2778 struct bgp_dest
*dest1
;
2779 struct bgp_dest
*dest2
;
2781 vnc_zlog_debug_verbose("%s: entry", __func__
);
2783 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2784 vnc_zlog_debug_verbose(
2785 "%s: already disabled for afi %d, skipping", __func__
,
2791 * Two-level table for SAFI_MPLS_VPN
2792 * Be careful when changing the things we iterate over
2794 for (dest1
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); dest1
;
2795 dest1
= bgp_route_next(dest1
)) {
2796 const struct prefix
*dest1_p
;
2798 if (!bgp_dest_has_bgp_path_info_data(dest1
))
2801 dest1_p
= bgp_dest_get_prefix(dest1
);
2802 for (dest2
= bgp_table_top(bgp_dest_get_bgp_table_info(dest1
));
2803 dest2
; dest2
= bgp_route_next(dest2
)) {
2804 const struct prefix
*dest2_p
=
2805 bgp_dest_get_prefix(dest2
);
2806 struct bgp_path_info
*bpi
;
2807 struct bgp_path_info
*nextbpi
;
2809 for (bpi
= bgp_dest_get_bgp_path_info(dest2
); bpi
;
2812 nextbpi
= bpi
->next
;
2814 if (bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
)
2817 struct rfapi_descriptor
*rfd
;
2818 vncHDBgpDirect
.peer
= bpi
->peer
;
2822 rfd
= bpi
->extra
->vnc
.export
.rfapi_handle
;
2824 vnc_zlog_debug_verbose(
2825 "%s: deleting bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]",
2826 __func__
, bpi
, bpi
->peer
, bpi
->type
,
2828 (bpi
->extra
? bpi
->extra
->vnc
.export
2833 del_vnc_route(rfd
, bpi
->peer
, bgp
,
2834 SAFI_MPLS_VPN
, dest2_p
,
2835 (struct prefix_rd
*)dest1_p
,
2836 bpi
->type
, bpi
->sub_type
, NULL
,
2839 vncHDBgpDirect
.peer
= NULL
;
2843 /* Clear RHN list */
2844 if (bgp
->rfapi
->resolve_nve_nexthop
) {
2845 struct prefix_bag
*pb
;
2846 struct bgp_path_info
*info
;
2847 while (!skiplist_first(bgp
->rfapi
->resolve_nve_nexthop
, NULL
,
2850 skiplist_delete_first(bgp
->rfapi
->resolve_nve_nexthop
);
2851 bgp_path_info_unlock(info
);
2855 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 0;
2856 vnc_zlog_debug_verbose("%s: return", __func__
);
2860 void vnc_import_bgp_exterior_redist_disable(struct bgp
*bgp
, afi_t afi
)
2862 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
2863 struct bgp
*bgp_exterior
= hc
->redist_bgp_exterior_view
;
2865 vnc_zlog_debug_verbose("%s: entry", __func__
);
2867 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2868 vnc_zlog_debug_verbose(
2869 "%s: already disabled for afi %d, skipping", __func__
,
2874 if (!bgp_exterior
) {
2875 vnc_zlog_debug_verbose(
2876 "%s: bgp exterior view not defined, skipping",
2883 struct bgp_dest
*dest
;
2884 for (dest
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]);
2885 dest
; dest
= bgp_route_next(dest
)) {
2887 struct bgp_path_info
*bpi
;
2889 for (bpi
= bgp_dest_get_bgp_path_info(dest
); bpi
;
2892 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2895 vnc_import_bgp_exterior_del_route(
2896 bgp_exterior
, bgp_dest_get_prefix(dest
),
2901 print_rhn_list(__func__
, NULL
);
2905 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 0;
2906 vnc_zlog_debug_verbose("%s: return", __func__
);