1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright 2009-2016, LabN Consulting, L.L.C.
9 * File: vnc_import_bgp.c
10 * Purpose: Import routes from BGP unicast directly (not via zebra)
13 #include "lib/zebra.h"
14 #include "lib/prefix.h"
15 #include "lib/agg_table.h"
18 #include "lib/memory.h"
19 #include "lib/linklist.h"
20 #include "lib/plist.h"
21 #include "lib/routemap.h"
22 #include "lib/lib_errors.h"
24 #include "bgpd/bgpd.h"
25 #include "bgpd/bgp_ecommunity.h"
26 #include "bgpd/bgp_attr.h"
27 #include "bgpd/bgp_route.h"
28 #include "bgpd/bgp_mplsvpn.h" /* for RD_TYPE_IP */
30 #include "bgpd/rfapi/vnc_export_bgp.h"
31 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
32 #include "bgpd/rfapi/rfapi.h"
33 #include "bgpd/rfapi/rfapi_import.h"
34 #include "bgpd/rfapi/rfapi_private.h"
35 #include "bgpd/rfapi/rfapi_monitor.h"
36 #include "bgpd/rfapi/rfapi_vty.h"
37 #include "bgpd/rfapi/vnc_import_bgp.h"
38 #include "bgpd/rfapi/vnc_import_bgp_p.h"
39 #include "bgpd/rfapi/vnc_debug.h"
41 #define ENABLE_VNC_RHNCK
43 #define DEBUG_RHN_LIST 0
45 static struct rfapi_descriptor vncHDBgpDirect
; /* dummy nve descriptor */
46 static struct rfapi_descriptor vncHDResolveNve
; /* dummy nve descriptor */
49 * For routes from another AS:
52 * LOCAL_PREF = 255 - MIN(255, MED)
54 * LOCAL_PREF = default_local_pref
56 * For routes from the same AS:
58 * LOCAL_PREF unchanged
60 uint32_t calc_local_pref(struct attr
*attr
, struct peer
*peer
)
62 uint32_t local_pref
= 0;
66 return peer
->bgp
->default_local_pref
;
68 return bgp_get_default()->default_local_pref
;
71 if (peer
&& (peer
->as
!= peer
->bgp
->as
)) {
72 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
73 if (attr
->med
> 255) {
76 local_pref
= 255 - attr
->med
;
79 local_pref
= peer
->bgp
->default_local_pref
;
82 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
83 local_pref
= attr
->local_pref
;
85 if (peer
&& peer
->bgp
) {
86 local_pref
= peer
->bgp
->default_local_pref
;
94 static int is_host_prefix(const struct prefix
*p
)
98 return (p
->prefixlen
== IPV4_MAX_BITLEN
);
100 return (p
->prefixlen
== IPV6_MAX_BITLEN
);
105 /***********************************************************************
107 ***********************************************************************/
110 struct prefix hpfx
; /* ce address = unicast nexthop */
111 struct prefix upfx
; /* unicast prefix */
112 struct bgp_path_info
*ubpi
; /* unicast route */
115 static const uint8_t maskbit
[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
116 0xf8, 0xfc, 0xfe, 0xff};
118 int vnc_prefix_cmp(const void *pfx1
, const void *pfx2
)
124 const struct prefix
*p1
= pfx1
;
125 const struct prefix
*p2
= pfx2
;
127 if (p1
->family
< p2
->family
)
129 if (p1
->family
> p2
->family
)
132 if (p1
->prefixlen
< p2
->prefixlen
)
134 if (p1
->prefixlen
> p2
->prefixlen
)
137 offset
= p1
->prefixlen
/ 8;
138 shift
= p1
->prefixlen
% 8;
139 if (shift
== 0 && offset
) { /* catch aligned case */
144 /* Set both prefix's head pointer. */
145 const uint8_t *pp1
= (const uint8_t *)&p1
->u
.prefix
;
146 const uint8_t *pp2
= (const uint8_t *)&p2
->u
.prefix
;
157 mask
= maskbit
[shift
];
158 if ((*pp1
& mask
) < (*pp2
& mask
))
160 if ((*pp1
& mask
) > (*pp2
& mask
))
166 static void prefix_bag_free(void *pb
)
168 XFREE(MTYPE_RFAPI_PREFIX_BAG
, pb
);
172 static void print_rhn_list(const char *tag1
, const char *tag2
)
176 struct skiplistnode
*p
;
177 struct prefix_bag
*pb
;
180 bgp
= bgp_get_default();
184 sl
= bgp
->frapi
->resolve_nve_nexthop
;
186 vnc_zlog_debug_verbose("%s: %s: RHN List is empty",
187 (tag1
? tag1
: ""), (tag2
? tag2
: ""));
191 vnc_zlog_debug_verbose("%s: %s: RHN list:", (tag1
? tag1
: ""),
194 /* XXX uses secret knowledge of skiplist structure */
195 for (p
= sl
->header
->forward
[0]; p
; p
= p
->forward
[0]) {
198 vnc_zlog_debug_verbose(
199 "RHN Entry %d (q=%p): kpfx=%pFX, upfx=%pFX, hpfx=%pFX, ubpi=%p",
200 ++count
, p
, p
->key
, &pb
->upfx
, &pb
->hpfx
, pb
->ubpi
);
205 #ifdef ENABLE_VNC_RHNCK
206 static void vnc_rhnck(char *tag
)
210 struct skiplistnode
*p
;
212 bgp
= bgp_get_default();
215 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
220 /* XXX uses secret knowledge of skiplist structure */
221 for (p
= sl
->header
->forward
[0]; p
; p
= p
->forward
[0]) {
222 struct prefix_bag
*pb
;
225 struct prefix pfx_orig_nexthop
;
227 memset(&pfx_orig_nexthop
, 0,
228 sizeof(pfx_orig_nexthop
)); /* keep valgrind happy */
233 afi
= family2afi(pb
->upfx
.family
);
235 rfapiUnicastNexthop2Prefix(afi
, pb
->ubpi
->attr
,
238 /* pb->hpfx, pb->ubpi nexthop, pkey should all reflect the same
240 assert(!vnc_prefix_cmp(&pb
->hpfx
, pkey
));
241 if (vnc_prefix_cmp(&pb
->hpfx
, &pfx_orig_nexthop
)) {
242 vnc_zlog_debug_verbose(
243 "%s: %s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
244 __func__
, tag
, &pfx_orig_nexthop
, &pb
->hpfx
);
248 vnc_zlog_debug_verbose("%s: vnc_rhnck OK", tag
);
251 #define VNC_RHNCK(n) \
254 snprintf(buf, sizeof(buf), "%s: %s", __func__, #n); \
264 /***********************************************************************
265 * Add/Delete Unicast Route
266 ***********************************************************************/
269 * "Adding a Route" import process
273 * extract and package information from the BGP unicast route.
274 * Return code 0 means OK, non-0 means drop.
276 * If return code is 0, caller MUST release ecom
278 static int process_unicast_route(struct bgp
*bgp
, /* in */
280 const struct prefix
*prefix
, /* in */
281 struct bgp_path_info
*info
, /* in */
282 struct ecommunity
**ecom
, /* OUT */
283 struct prefix
*unicast_nexthop
) /* OUT */
285 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
286 struct peer
*peer
= info
->peer
;
287 struct attr
*attr
= info
->attr
;
289 struct route_map
*rmap
= NULL
;
290 struct prefix pfx_orig_nexthop
;
292 memset(&pfx_orig_nexthop
, 0,
293 sizeof(pfx_orig_nexthop
)); /* keep valgrind happy */
298 if (hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
299 vnc_zlog_debug_verbose("%s: HC prefix list is set, checking",
301 if (prefix_list_apply(
302 hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
],
305 vnc_zlog_debug_verbose(
306 "%s: prefix list returns DENY, blocking route",
310 vnc_zlog_debug_verbose(
311 "%s: prefix list returns PASS, allowing route",
315 /* apply routemap, if any, later */
316 rmap
= hc
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
319 * Extract original nexthop, which we expect to be a NVE connected
321 * Note that this is the nexthop before any possible application of
325 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
326 * but if v4 it is in attr->nexthop
328 rfapiUnicastNexthop2Prefix(afi
, attr
, &pfx_orig_nexthop
);
332 * This code is here because it allocates an interned attr which
333 * must be freed before we return. It's easier to put it after
334 * all of the possible returns above.
336 memset(&hattr
, 0, sizeof(hattr
));
337 /* hattr becomes a ghost attr */
341 struct bgp_path_info info
;
342 route_map_result_t ret
;
344 memset(&info
, 0, sizeof(info
));
347 ret
= route_map_apply(rmap
, prefix
, &info
);
348 if (ret
== RMAP_DENYMATCH
) {
349 bgp_attr_flush(&hattr
);
350 vnc_zlog_debug_verbose(
351 "%s: route map \"%s\" says DENY, returning",
352 __func__
, rmap
->name
);
358 * Get the (possibly altered by policy) unicast nexthop
359 * for later lookup in the Import Table by caller
361 rfapiUnicastNexthop2Prefix(afi
, &hattr
, unicast_nexthop
);
363 if (bgp_attr_get_ecommunity(&hattr
))
364 *ecom
= ecommunity_dup(bgp_attr_get_ecommunity(&hattr
));
366 *ecom
= ecommunity_new();
369 * Done with hattr, clean up
371 bgp_attr_flush(&hattr
);
374 * Add EC that carries original NH of iBGP route (2 bytes = magic
375 * value indicating it came from an VNC gateway; default 5226, but
376 * must be user configurable). Note that this is the nexthop before
377 * any application of policy.
380 struct ecommunity_val vnc_gateway_magic
;
383 /* Using route origin extended community type */
384 memset(&vnc_gateway_magic
, 0, sizeof(vnc_gateway_magic
));
385 vnc_gateway_magic
.val
[0] = 0x01;
386 vnc_gateway_magic
.val
[1] = 0x03;
388 /* Only works for IPv4 nexthops */
389 if (prefix
->family
== AF_INET
) {
390 memcpy(vnc_gateway_magic
.val
+ 2,
391 &unicast_nexthop
->u
.prefix4
, 4);
393 localadmin
= htons(hc
->resolve_nve_roo_local_admin
);
394 memcpy(vnc_gateway_magic
.val
+ 6, (char *)&localadmin
, 2);
396 ecommunity_add_val(*ecom
, &vnc_gateway_magic
, false, false);
403 static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
404 struct bgp
*bgp
, afi_t afi
, struct bgp_path_info
*bpi
, /* VPN bpi */
405 struct prefix_rd
*prd
, /* RD */
406 const struct prefix
*prefix
, /* unicast route prefix */
407 uint32_t *local_pref
, /* NULL = no local_pref */
408 uint32_t *med
, /* NULL = no med */
409 struct ecommunity
*ecom
) /* generated ecoms */
412 struct prefix nexthop
;
413 struct rfapi_ip_addr nexthop_h
;
416 struct bgp_attr_encap_subtlv
*encaptlvs
;
419 struct rfapi_un_option optary
[3];
420 struct rfapi_un_option
*opt
= NULL
;
423 vnc_zlog_debug_verbose("%s: entry", __func__
);
425 if (bpi
->type
!= ZEBRA_ROUTE_BGP
426 && bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
) {
430 if (bpi
->sub_type
!= BGP_ROUTE_NORMAL
431 && bpi
->sub_type
!= BGP_ROUTE_STATIC
432 && bpi
->sub_type
!= BGP_ROUTE_RFP
) {
436 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
439 vncHDResolveNve
.peer
= bpi
->peer
;
440 if (!rfapiGetVncTunnelUnAddr(bpi
->attr
, &un
)) {
441 if (rfapiQprefix2Raddr(&un
, &vncHDResolveNve
.un_addr
))
444 memset(&vncHDResolveNve
.un_addr
, 0,
445 sizeof(vncHDResolveNve
.un_addr
));
448 /* Use nexthop of VPN route as nexthop of constructed route */
449 rfapiNexthop2Prefix(bpi
->attr
, &nexthop
);
450 rfapiQprefix2Raddr(&nexthop
, &nexthop_h
);
452 if (rfapiGetVncLifetime(bpi
->attr
, &lifetime
)) {
455 plifetime
= &lifetime
;
458 encaptlvs
= bgp_attr_get_vnc_subtlvs(bpi
->attr
);
459 if (bpi
->attr
->encap_tunneltype
!= BGP_ENCAP_TYPE_RESERVED
460 && bpi
->attr
->encap_tunneltype
!= BGP_ENCAP_TYPE_MPLS
) {
461 opt
= &optary
[cur_opt
++];
462 memset(opt
, 0, sizeof(struct rfapi_un_option
));
463 opt
->type
= RFAPI_UN_OPTION_TYPE_TUNNELTYPE
;
464 opt
->v
.tunnel
.type
= bpi
->attr
->encap_tunneltype
;
465 /* TBD parse bpi->attr->extra->encap_subtlvs */
468 struct ecommunity
*new_ecom
= ecommunity_dup(ecom
);
470 if (bgp_attr_get_ecommunity(bpi
->attr
))
471 ecommunity_merge(new_ecom
, bgp_attr_get_ecommunity(bpi
->attr
));
474 label
= decode_label(&bpi
->extra
->label
[0]);
476 add_vnc_route(&vncHDResolveNve
, bgp
, SAFI_MPLS_VPN
,
477 prefix
, /* unicast route prefix */
478 prd
, &nexthop_h
, /* new nexthop */
479 local_pref
, plifetime
,
480 (struct bgp_tea_options
*)encaptlvs
, /* RFP options */
481 opt
, NULL
, new_ecom
, med
, /* NULL => don't set med */
482 (label
? &label
: NULL
), /* NULL= default */
483 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
484 RFAPI_AHR_RFPOPT_IS_VNCTLV
); /* flags */
486 ecommunity_free(&new_ecom
);
489 static void vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
490 struct prefix_rd
*prd
, /* RD */
491 struct bgp_table
*table_rd
, /* per-rd VPN route table */
492 afi_t afi
, struct bgp
*bgp
,
493 const struct prefix
*prefix
, /* unicast prefix */
494 struct ecommunity
*ecom
, /* generated ecoms */
495 uint32_t *local_pref
, /* NULL = no local_pref */
496 uint32_t *med
, /* NULL = no med */
497 struct prefix
*ubpi_nexthop
) /* unicast nexthop */
500 struct bgp_path_info
*bpi
;
505 vnc_zlog_debug_verbose("%s: ubpi_nexthop=%pFX", __func__
, ubpi_nexthop
);
508 bd
= bgp_node_lookup(table_rd
, ubpi_nexthop
);
510 vnc_zlog_debug_verbose(
511 "%s: no match in RD's table for ubpi_nexthop",
516 /* Iterate over bgp_info items at this node */
517 for (bpi
= bgp_dest_get_bgp_path_info(bd
); bpi
; bpi
= bpi
->next
) {
519 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
520 bgp
, afi
, bpi
, /* VPN bpi */
521 prd
, prefix
, local_pref
, med
, ecom
);
524 bgp_dest_unlock_node(bd
);
527 static void vnc_import_bgp_add_route_mode_resolve_nve(
528 struct bgp
*bgp
, const struct prefix
*prefix
, /* unicast prefix */
529 struct bgp_path_info
*info
) /* unicast info */
531 afi_t afi
= family2afi(prefix
->family
);
533 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
535 struct ecommunity
*ecom
= NULL
;
537 uint32_t *med
= NULL
;
539 struct prefix_bag
*pb
;
540 struct bgp_dest
*bdp
; /* prd table node */
543 if (VNC_DEBUG(VERBOSE
)) {
544 char str_nh
[PREFIX_STRLEN
];
548 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &nh
);
550 prefix2str(&nh
, str_nh
, sizeof(str_nh
));
556 vnc_zlog_debug_verbose(
557 "%s(bgp=%p, unicast prefix=%pFX, unicast nh=%s)",
558 __func__
, bgp
, prefix
, str_nh
);
561 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
562 vnc_zlog_debug_verbose(
563 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
564 __func__
, info
->type
, zebra_route_string(info
->type
),
565 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
574 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
579 if (!(bgp
->rfapi_cfg
)) {
580 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
585 /* check vnc redist flag for bgp direct routes */
586 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
587 vnc_zlog_debug_verbose(
588 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
594 if (process_unicast_route(bgp
, afi
, prefix
, info
, &ecom
,
595 &pfx_unicast_nexthop
)) {
597 vnc_zlog_debug_verbose(
598 "%s: process_unicast_route error, skipping", __func__
);
602 local_pref
= calc_local_pref(info
->attr
, info
->peer
);
603 if (info
->attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
604 med
= &info
->attr
->med
;
607 * At this point, we have allocated:
609 * ecom ecommunity ptr, union of unicast and ROO parts (no NVE part)
613 * pfx_unicast_nexthop nexthop of uncast route
616 if (!bgp
->rfapi
->resolve_nve_nexthop
) {
617 bgp
->rfapi
->resolve_nve_nexthop
=
618 skiplist_new(SKIPLIST_FLAG_ALLOW_DUPLICATES
,
619 vnc_prefix_cmp
, prefix_bag_free
);
622 pb
= XCALLOC(MTYPE_RFAPI_PREFIX_BAG
, sizeof(struct prefix_bag
));
623 pb
->hpfx
= pfx_unicast_nexthop
;
627 bgp_path_info_lock(info
); /* skiplist refers to it */
628 skiplist_insert(bgp
->rfapi
->resolve_nve_nexthop
, &pb
->hpfx
, pb
);
631 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
632 * (exact match, /32). If an exact match is found, call add_vnc_route.
635 for (bdp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bdp
;
636 bdp
= bgp_route_next(bdp
)) {
638 struct bgp_table
*table
;
640 table
= bgp_dest_get_bgp_table_info(bdp
);
645 vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
646 (struct prefix_rd
*)bgp_dest_get_prefix(bdp
), table
,
647 afi
, bgp
, prefix
, ecom
, &local_pref
, med
,
648 &pfx_unicast_nexthop
);
653 ecommunity_free(&ecom
);
655 vnc_zlog_debug_verbose("%s: done", __func__
);
659 static void vnc_import_bgp_add_route_mode_plain(struct bgp
*bgp
,
660 const struct prefix
*prefix
,
661 struct bgp_path_info
*info
)
663 afi_t afi
= family2afi(prefix
->family
);
664 struct peer
*peer
= info
->peer
;
665 struct attr
*attr
= info
->attr
;
667 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
668 struct attr
*iattr
= NULL
;
670 struct rfapi_ip_addr vnaddr
;
671 struct prefix vn_pfx_space
;
672 struct prefix
*vn_pfx
= NULL
;
674 struct ecommunity
*ecom
= NULL
;
675 struct prefix_rd prd
;
676 struct route_map
*rmap
= NULL
;
678 uint32_t *med
= NULL
;
680 vnc_zlog_debug_verbose("%s(prefix=%pFX) entry", __func__
, prefix
);
683 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
689 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
694 /* check vnc redist flag for bgp direct routes */
695 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
696 vnc_zlog_debug_verbose(
697 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
703 * mode "plain" specific code
706 vnc_zlog_debug_verbose("%s: NOT using redist RFG", __func__
);
711 if (hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
712 vnc_zlog_debug_verbose(
713 "%s: HC prefix list is set, checking",
715 if (prefix_list_apply(
716 hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
720 vnc_zlog_debug_verbose(
721 "%s: prefix list returns DENY, blocking route",
725 vnc_zlog_debug_verbose(
726 "%s: prefix list returns PASS, allowing route",
730 /* apply routemap, if any, later */
731 rmap
= hc
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
734 * Incoming prefix is unicast. If v6, it is in multiprotocol
736 * but if v4 it is in attr->nexthop
738 rfapiUnicastNexthop2Prefix(afi
, attr
, &vn_pfx_space
);
739 vn_pfx
= &vn_pfx_space
;
742 ahr_flags
|= RFAPI_AHR_NO_TUNNEL_SUBTLV
;
745 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
))
746 vnc_zlog_debug_any("%s vn_pfx=%pFX", __func__
, vn_pfx
);
751 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
752 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
759 * This code is here because it allocates an interned attr which
760 * must be freed before we return. It's easier to put it after
761 * all of the possible returns above.
763 memset(&hattr
, 0, sizeof(hattr
));
764 /* hattr becomes a ghost attr */
768 struct bgp_path_info info
;
769 route_map_result_t ret
;
771 memset(&info
, 0, sizeof(info
));
774 ret
= route_map_apply(rmap
, prefix
, &info
);
775 if (ret
== RMAP_DENYMATCH
) {
776 bgp_attr_flush(&hattr
);
777 vnc_zlog_debug_verbose(
778 "%s: route map \"%s\" says DENY, returning",
779 __func__
, rmap
->name
);
784 iattr
= bgp_attr_intern(&hattr
);
785 bgp_attr_flush(&hattr
);
787 /* Now iattr is an allocated interned attr */
790 * Mode "plain" specific code
792 * Sets RD in dummy HD
796 if (vnaddr
.addr_family
!= AF_INET
) {
797 vnc_zlog_debug_verbose(
798 "%s: can't auto-assign RD, VN AF (%d) is not IPv4, skipping",
799 __func__
, vnaddr
.addr_family
);
801 bgp_attr_unintern(&iattr
);
805 memset(&prd
, 0, sizeof(prd
));
806 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
808 if (iattr
&& bgp_attr_get_ecommunity(iattr
))
809 ecom
= ecommunity_dup(bgp_attr_get_ecommunity(iattr
));
812 local_pref
= calc_local_pref(iattr
, peer
);
814 if (iattr
&& (iattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))) {
818 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
819 char buf
[PREFIX_STRLEN
];
821 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, sizeof(buf
));
822 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
825 vncHDBgpDirect
.peer
= peer
;
826 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
827 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
828 NULL
, /* RFP options */
829 NULL
, NULL
, ecom
, med
, /* med */
830 NULL
, /* label: default */
831 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
833 vncHDBgpDirect
.peer
= NULL
;
836 ecommunity_free(&ecom
);
839 static void vnc_import_bgp_add_route_mode_nvegroup(
840 struct bgp
*bgp
, const struct prefix
*prefix
,
841 struct bgp_path_info
*info
, struct rfapi_nve_group_cfg
*rfg
)
843 afi_t afi
= family2afi(prefix
->family
);
844 struct peer
*peer
= info
->peer
;
845 struct attr
*attr
= info
->attr
;
847 struct attr
*iattr
= NULL
;
849 struct rfapi_ip_addr vnaddr
;
850 struct prefix
*vn_pfx
= NULL
;
852 struct ecommunity
*ecom
= NULL
;
853 struct prefix_rd prd
;
854 struct route_map
*rmap
= NULL
;
857 vnc_zlog_debug_verbose("%s(prefix=%pFX) entry", __func__
, prefix
);
862 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
867 if (!(bgp
->rfapi_cfg
)) {
868 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
873 /* check vnc redist flag for bgp direct routes */
874 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
875 vnc_zlog_debug_verbose(
876 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
887 struct rfapi_ip_prefix pfx_un
;
889 vnc_zlog_debug_verbose("%s: using redist RFG", __func__
);
892 * RFG prefix list check
894 if (rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
895 vnc_zlog_debug_verbose(
896 "%s: RFG prefix list is set, checking",
898 if (prefix_list_apply(
899 rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
903 vnc_zlog_debug_verbose(
904 "%s: prefix list returns DENY, blocking route",
908 vnc_zlog_debug_verbose(
909 "%s: prefix list returns PASS, allowing route",
913 /* apply routemap, if any, later */
914 rmap
= rfg
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
917 * export nve group's VN addr prefix must be a /32 which
918 * will yield the VN addr to use
920 vn_pfx
= &rfg
->vn_prefix
;
925 if (!is_host_prefix(&rfg
->un_prefix
)) {
926 /* NB prefixlen==0 means it has not been configured */
927 vnc_zlog_debug_verbose(
928 "%s: redist RFG UN pfx not host pfx (plen=%d), skipping",
929 __func__
, rfg
->un_prefix
.prefixlen
);
933 rfapiQprefix2Rprefix(&rfg
->un_prefix
, &pfx_un
);
935 vncHDBgpDirect
.un_addr
= pfx_un
.prefix
;
938 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
))
939 vnc_zlog_debug_any("%s vn_pfx=%pFX", __func__
, vn_pfx
);
944 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
945 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
952 * This code is here because it allocates an interned attr which
953 * must be freed before we return. It's easier to put it after
954 * all of the possible returns above.
956 memset(&hattr
, 0, sizeof(hattr
));
957 /* hattr becomes a ghost attr */
961 struct bgp_path_info path
;
962 route_map_result_t ret
;
964 memset(&path
, 0, sizeof(path
));
967 ret
= route_map_apply(rmap
, prefix
, &path
);
968 if (ret
== RMAP_DENYMATCH
) {
969 bgp_attr_flush(&hattr
);
970 vnc_zlog_debug_verbose(
971 "%s: route map \"%s\" says DENY, returning",
972 __func__
, rmap
->name
);
977 iattr
= bgp_attr_intern(&hattr
);
978 bgp_attr_flush(&hattr
);
980 /* Now iattr is an allocated interned attr */
985 * Sets RD in dummy HD
990 memset(&prd
, 0, sizeof(prd
));
992 prd
.family
= AF_UNSPEC
;
995 if (rfg
->rd
.family
== AF_UNIX
) {
996 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
999 if (rfg
->rt_export_list
)
1000 ecom
= ecommunity_dup(
1001 bgp
->rfapi_cfg
->rfg_redist
->rt_export_list
);
1003 ecom
= ecommunity_new();
1005 if (iattr
&& bgp_attr_get_ecommunity(iattr
))
1006 ecom
= ecommunity_merge(ecom
,
1007 bgp_attr_get_ecommunity(iattr
));
1010 local_pref
= calc_local_pref(iattr
, peer
);
1012 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
1016 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, BUFSIZ
);
1017 buf
[BUFSIZ
- 1] = 0;
1018 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
1021 vncHDBgpDirect
.peer
= peer
;
1022 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
1023 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
1024 NULL
, /* RFP options */
1025 NULL
, NULL
, ecom
, NULL
, /* med */
1026 NULL
, /* label: default */
1027 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1029 vncHDBgpDirect
.peer
= NULL
;
1032 ecommunity_free(&ecom
);
1035 static void vnc_import_bgp_del_route_mode_plain(struct bgp
*bgp
,
1036 const struct prefix
*prefix
,
1037 struct bgp_path_info
*info
)
1039 struct prefix_rd prd
;
1040 afi_t afi
= family2afi(prefix
->family
);
1041 struct prefix
*vn_pfx
= NULL
;
1042 struct rfapi_ip_addr vnaddr
;
1043 struct prefix vn_pfx_space
;
1049 * Compute VN address
1053 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &vn_pfx_space
);
1055 vnc_zlog_debug_verbose("%s: no attr, can't delete route",
1059 vn_pfx
= &vn_pfx_space
;
1061 vnaddr
.addr_family
= vn_pfx
->family
;
1062 switch (vn_pfx
->family
) {
1064 if (vn_pfx
->prefixlen
!= IPV4_MAX_BITLEN
) {
1065 vnc_zlog_debug_verbose(
1066 "%s: redist VN plen (%d) != 32, skipping",
1067 __func__
, vn_pfx
->prefixlen
);
1070 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1074 if (vn_pfx
->prefixlen
!= IPV6_MAX_BITLEN
) {
1075 vnc_zlog_debug_verbose(
1076 "%s: redist VN plen (%d) != 128, skipping",
1077 __func__
, vn_pfx
->prefixlen
);
1080 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1084 vnc_zlog_debug_verbose(
1085 "%s: no redist RFG VN host pfx configured, skipping",
1091 memset(&prd
, 0, sizeof(prd
));
1092 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1093 vnc_zlog_debug_verbose("%s: can't auto-assign RD, skipping",
1098 vncHDBgpDirect
.peer
= info
->peer
;
1099 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1100 vncHDBgpDirect
.peer
);
1101 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1102 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1105 vncHDBgpDirect
.peer
= NULL
;
1108 static void vnc_import_bgp_del_route_mode_nvegroup(struct bgp
*bgp
,
1109 const struct prefix
*prefix
,
1110 struct bgp_path_info
*info
)
1112 struct prefix_rd prd
;
1113 afi_t afi
= family2afi(prefix
->family
);
1114 struct rfapi_nve_group_cfg
*rfg
= NULL
;
1115 struct prefix
*vn_pfx
= NULL
;
1116 struct rfapi_ip_addr vnaddr
;
1121 rfg
= bgp
->rfapi_cfg
->rfg_redist
;
1125 * Compute VN address
1129 * export nve group's VN addr prefix must be a /32 which
1130 * will yield the VN addr to use
1132 vn_pfx
= &rfg
->vn_prefix
;
1135 vnaddr
.addr_family
= vn_pfx
->family
;
1136 switch (vn_pfx
->family
) {
1138 if (vn_pfx
->prefixlen
!= IPV4_MAX_BITLEN
) {
1139 vnc_zlog_debug_verbose(
1140 "%s: redist VN plen (%d) != 32, skipping",
1141 __func__
, vn_pfx
->prefixlen
);
1144 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1148 if (vn_pfx
->prefixlen
!= IPV6_MAX_BITLEN
) {
1149 vnc_zlog_debug_verbose(
1150 "%s: redist VN plen (%d) != 128, skipping",
1151 __func__
, vn_pfx
->prefixlen
);
1154 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1158 vnc_zlog_debug_verbose(
1159 "%s: no redist RFG VN host pfx configured, skipping",
1164 memset(&prd
, 0, sizeof(prd
));
1166 prd
.family
= AF_UNSPEC
;
1169 if (rfg
->rd
.family
== AF_UNIX
) {
1170 /* means "auto" with VN addr */
1171 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1172 vnc_zlog_debug_verbose(
1173 "%s: can't auto-assign RD, skipping", __func__
);
1179 vncHDBgpDirect
.peer
= info
->peer
;
1180 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1181 vncHDBgpDirect
.peer
);
1182 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1183 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1186 vncHDBgpDirect
.peer
= NULL
;
1189 static void vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1190 struct bgp
*bgp
, afi_t afi
, struct bgp_path_info
*bpi
, /* VPN bpi */
1191 struct prefix_rd
*prd
, /* RD */
1192 const struct prefix
*prefix
) /* unicast route prefix */
1196 if (bpi
->type
!= ZEBRA_ROUTE_BGP
1197 && bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
) {
1201 if (bpi
->sub_type
!= BGP_ROUTE_NORMAL
1202 && bpi
->sub_type
!= BGP_ROUTE_STATIC
1203 && bpi
->sub_type
!= BGP_ROUTE_RFP
) {
1207 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
1210 vncHDResolveNve
.peer
= bpi
->peer
;
1211 if (!rfapiGetVncTunnelUnAddr(bpi
->attr
, &un
)) {
1212 if (rfapiQprefix2Raddr(&un
, &vncHDResolveNve
.un_addr
))
1215 memset(&vncHDResolveNve
.un_addr
, 0,
1216 sizeof(vncHDResolveNve
.un_addr
));
1219 del_vnc_route(&vncHDResolveNve
, vncHDResolveNve
.peer
, bgp
,
1220 SAFI_MPLS_VPN
, prefix
, /* unicast route prefix */
1221 prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
, NULL
,
1225 static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1226 struct prefix_rd
*prd
,
1227 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1228 afi_t afi
, struct bgp
*bgp
,
1229 const struct prefix
*prefix
, /* unicast prefix */
1230 const struct prefix
*ubpi_nexthop
) /* unicast bpi's nexthop */
1232 struct bgp_dest
*bd
;
1233 struct bgp_path_info
*bpi
;
1238 vnc_zlog_debug_verbose("%s: ubpi_nexthop=%pFX", __func__
, ubpi_nexthop
);
1242 bd
= bgp_node_lookup(table_rd
, ubpi_nexthop
);
1244 vnc_zlog_debug_verbose(
1245 "%s: no match in RD's table for ubpi_nexthop",
1250 /* Iterate over bgp_info items at this node */
1251 for (bpi
= bgp_dest_get_bgp_path_info(bd
); bpi
; bpi
= bpi
->next
) {
1253 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1254 bgp
, afi
, bpi
, /* VPN bpi */
1256 prefix
); /* unicast route prefix */
1259 bgp_dest_unlock_node(bd
);
1263 vnc_import_bgp_del_route_mode_resolve_nve(struct bgp
*bgp
, afi_t afi
,
1264 const struct prefix
*prefix
,
1265 struct bgp_path_info
*info
)
1267 struct ecommunity
*ecom
= NULL
;
1268 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
1270 // struct listnode *hnode;
1271 // struct rfapi_descriptor *rfd;
1272 struct prefix_bag
*pb
;
1274 struct skiplist
*sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1276 struct bgp_dest
*bdp
; /* prd table node */
1279 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1284 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
1285 vnc_zlog_debug_verbose(
1286 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
1287 __func__
, info
->type
, zebra_route_string(info
->type
),
1288 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
1292 if (process_unicast_route(bgp
, afi
, prefix
, info
, &ecom
,
1293 &pfx_unicast_nexthop
)) {
1295 vnc_zlog_debug_verbose(
1296 "%s: process_unicast_route error, skipping", __func__
);
1300 rc
= skiplist_first_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1303 if (pb
->ubpi
== info
) {
1304 skiplist_delete(sl
, &pfx_unicast_nexthop
, pb
);
1305 bgp_path_info_unlock(info
);
1308 rc
= skiplist_next_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1313 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
1314 * (exact match, /32). If an exact match is found, call add_vnc_route.
1317 for (bdp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bdp
;
1318 bdp
= bgp_route_next(bdp
)) {
1320 struct bgp_table
*table
;
1322 table
= bgp_dest_get_bgp_table_info(bdp
);
1327 vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1328 (struct prefix_rd
*)bgp_dest_get_prefix(bdp
), table
,
1329 afi
, bgp
, prefix
, &pfx_unicast_nexthop
);
1333 ecommunity_free(&ecom
);
1337 /***********************************************************************
1338 * Add/Delete CE->NVE routes
1339 ***********************************************************************/
1342 * Should be called whan a bpi is added to VPN RIB. This function
1343 * will check if it is a host route and return immediately if not.
1345 void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1346 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1347 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1348 const struct prefix
*prefix
, /* VPN prefix */
1349 struct bgp_path_info
*bpi
) /* new VPN host route */
1351 afi_t afi
= family2afi(prefix
->family
);
1352 struct skiplist
*sl
= NULL
;
1354 struct prefix_bag
*pb
;
1356 struct rfapi_cfg
*hc
= NULL
;
1358 vnc_zlog_debug_verbose("%s: entry", __func__
);
1360 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1361 vnc_zlog_debug_verbose("%s: bad afi %d, skipping", __func__
,
1366 if (!(hc
= bgp
->rfapi_cfg
)) {
1367 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1372 /* check vnc redist flag for bgp direct routes */
1373 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1374 vnc_zlog_debug_verbose(
1375 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1380 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1381 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1387 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1390 vnc_zlog_debug_verbose(
1391 "%s: no resolve_nve_nexthop skiplist, skipping",
1396 if (!is_host_prefix(prefix
)) {
1397 vnc_zlog_debug_verbose("%s: not host prefix, skipping",
1402 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1404 struct ecommunity
*ecom
;
1405 struct prefix pfx_unicast_nexthop
;
1406 uint32_t *med
= NULL
;
1407 uint32_t local_pref
;
1409 memset(&pfx_unicast_nexthop
, 0,
1410 sizeof(pfx_unicast_nexthop
)); /* keep valgrind happy */
1412 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
))
1414 "%s: examining RHN Entry (q=%p): upfx=%pFX, hpfx=%pFX, ubpi=%p",
1415 __func__
, cursor
, &pb
->upfx
, &pb
->hpfx
,
1418 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubpi
, &ecom
,
1419 &pfx_unicast_nexthop
)) {
1421 vnc_zlog_debug_verbose(
1422 "%s: process_unicast_route error, skipping",
1426 local_pref
= calc_local_pref(pb
->ubpi
->attr
, pb
->ubpi
->peer
);
1428 if (pb
->ubpi
->attr
->flag
1429 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
1430 med
= &pb
->ubpi
->attr
->med
;
1435 if (vnc_prefix_cmp(&pfx_unicast_nexthop
, prefix
)) {
1436 vnc_zlog_debug_verbose(
1437 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
1438 __func__
, &pfx_unicast_nexthop
, prefix
);
1442 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
1443 bgp
, afi
, bpi
, /* VPN bpi */
1444 prd
, &pb
->upfx
, /* unicast prefix */
1445 &local_pref
, med
, ecom
);
1448 ecommunity_free(&ecom
);
1453 vnc_zlog_debug_verbose(
1454 "%s: advancing past RHN Entry (q=%p): with prefix %pFX",
1455 __func__
, cursor
, prefix
);
1456 print_rhn_list(__func__
, NULL
); /* debug */
1459 rc
= skiplist_next_value(sl
, prefix
, (void *)&pb
, &cursor
);
1461 vnc_zlog_debug_verbose("%s: done", __func__
);
1465 void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
1466 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1467 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1468 const struct prefix
*prefix
, /* VPN prefix */
1469 struct bgp_path_info
*bpi
) /* old VPN host route */
1471 afi_t afi
= family2afi(prefix
->family
);
1472 struct skiplist
*sl
= NULL
;
1473 struct prefix_bag
*pb
;
1475 struct rfapi_cfg
*hc
= NULL
;
1478 vnc_zlog_debug_verbose("%s(bgp=%p, nve prefix=%pFX)", __func__
, bgp
,
1481 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
)
1484 if (!(hc
= bgp
->rfapi_cfg
)) {
1485 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1490 /* check vnc redist flag for bgp direct routes */
1491 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1492 vnc_zlog_debug_verbose(
1493 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1498 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1499 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1505 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1508 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1513 if (!is_host_prefix(prefix
)) {
1514 vnc_zlog_debug_verbose("%s: not host route, skip", __func__
);
1519 * Find all entries with key == CE in the RHN list
1521 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1524 struct ecommunity
*ecom
;
1525 struct prefix pfx_unicast_nexthop
;
1527 memset(&pfx_unicast_nexthop
, 0,
1528 sizeof(pfx_unicast_nexthop
)); /* keep valgrind happy */
1530 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubpi
, &ecom
,
1531 &pfx_unicast_nexthop
)) {
1533 vnc_zlog_debug_verbose(
1534 "%s: process_unicast_route error, skipping",
1542 if (vnc_prefix_cmp(&pfx_unicast_nexthop
, prefix
)) {
1543 vnc_zlog_debug_verbose(
1544 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
1545 __func__
, &pfx_unicast_nexthop
, prefix
);
1549 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1550 bgp
, afi
, bpi
, prd
, &pb
->upfx
);
1553 ecommunity_free(&ecom
);
1555 rc
= skiplist_next_value(sl
, prefix
, (void *)&pb
, &cursor
);
1560 /***********************************************************************
1562 ***********************************************************************/
1564 #define DEBUG_IS_USABLE_INTERIOR 1
1566 static int is_usable_interior_route(struct bgp_path_info
*bpi_interior
)
1568 if (!VALID_INTERIOR_TYPE(bpi_interior
->type
)) {
1569 #if DEBUG_IS_USABLE_INTERIOR
1570 vnc_zlog_debug_verbose(
1571 "%s: NO: type %d is not valid interior type", __func__
,
1572 bpi_interior
->type
);
1576 if (!CHECK_FLAG(bpi_interior
->flags
, BGP_PATH_VALID
)) {
1577 #if DEBUG_IS_USABLE_INTERIOR
1578 vnc_zlog_debug_verbose("%s: NO: BGP_PATH_VALID not set",
1587 * There should be only one of these per prefix at a time.
1588 * This should be called as a result of selection operation
1590 * NB should be called espacially for bgp instances that are named,
1591 * because the exterior routes will always come from one of those.
1592 * We filter here on the instance name to make sure we get only the
1595 static void vnc_import_bgp_exterior_add_route_it(
1596 struct bgp
*bgp
, /* exterior instance, we hope */
1597 const struct prefix
*prefix
, /* unicast prefix */
1598 struct bgp_path_info
*info
, /* unicast info */
1599 struct rfapi_import_table
*it_only
) /* NULL, or limit to this IT */
1602 struct rfapi_cfg
*hc
;
1603 struct prefix pfx_orig_nexthop
;
1604 struct rfapi_import_table
*it
;
1605 struct bgp
*bgp_default
= bgp_get_default();
1606 afi_t afi
= family2afi(prefix
->family
);
1611 h
= bgp_default
->rfapi
;
1612 hc
= bgp_default
->rfapi_cfg
;
1614 vnc_zlog_debug_verbose("%s: entry with it=%p", __func__
, it_only
);
1617 vnc_zlog_debug_verbose(
1618 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1622 if (!hc
->redist_bgp_exterior_view
) {
1623 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1627 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1628 vnc_zlog_debug_verbose(
1629 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1630 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1634 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1635 vnc_zlog_debug_verbose(
1636 "%s: redist of exterior routes not enabled, skipping",
1642 * Extract nexthop from exterior route
1644 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1645 * but if v4 it is in attr->nexthop
1647 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1649 for (it
= h
->imports
; it
; it
= it
->next
) {
1650 struct agg_table
*table
;
1651 struct agg_node
*rn
;
1652 struct agg_node
*par
;
1653 struct bgp_path_info
*bpi_interior
;
1654 int have_usable_route
;
1656 vnc_zlog_debug_verbose("%s: doing it %p", __func__
, it
);
1658 if (it_only
&& (it_only
!= it
)) {
1659 vnc_zlog_debug_verbose("%s: doesn't match it_only %p",
1664 table
= it
->imported_vpn
[afi
];
1666 for (rn
= agg_node_match(table
, &pfx_orig_nexthop
),
1667 have_usable_route
= 0;
1668 (!have_usable_route
) && rn
;) {
1670 vnc_zlog_debug_verbose("%s: it %p trying rn %p",
1673 for (bpi_interior
= rn
->info
; bpi_interior
;
1674 bpi_interior
= bpi_interior
->next
) {
1675 struct prefix_rd
*prd
;
1676 struct attr new_attr
;
1679 if (!is_usable_interior_route(bpi_interior
))
1682 vnc_zlog_debug_verbose(
1683 "%s: usable: bpi_interior %p", __func__
,
1687 * have a legitimate route to exterior's nexthop
1690 * Import unicast route to the import table
1692 have_usable_route
= 1;
1694 if (bpi_interior
->extra
) {
1695 prd
= &bpi_interior
->extra
->vnc
.import
1697 label
= decode_label(
1698 &bpi_interior
->extra
->label
[0]);
1702 /* use local_pref from unicast route */
1703 memset(&new_attr
, 0, sizeof(new_attr
));
1704 new_attr
= *bpi_interior
->attr
;
1705 if (info
->attr
->flag
1706 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
1707 new_attr
.local_pref
=
1708 info
->attr
->local_pref
;
1709 new_attr
.flag
|= ATTR_FLAG_BIT(
1710 BGP_ATTR_LOCAL_PREF
);
1713 rfapiBgpInfoFilteredImportVPN(
1714 it
, FIF_ACTION_UPDATE
,
1715 bpi_interior
->peer
, NULL
, /* rfd */
1716 prefix
, NULL
, afi
, prd
, &new_attr
,
1717 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1718 BGP_ROUTE_REDISTRIBUTE
, &label
);
1721 if (have_usable_route
) {
1725 * TBD factor this out into its own function
1727 struct prefix
*pfx_mon
= prefix_new();
1728 if (!RFAPI_MONITOR_EXTERIOR(rn
)->source
) {
1729 RFAPI_MONITOR_EXTERIOR(rn
)->source
=
1733 agg_lock_node(rn
); /* for skiplist */
1735 agg_lock_node(rn
); /* for skiplist entry */
1736 prefix_copy(pfx_mon
, prefix
);
1737 if (!skiplist_insert(
1738 RFAPI_MONITOR_EXTERIOR(rn
)->source
,
1741 bgp_path_info_lock(info
);
1744 par
= agg_node_parent(rn
);
1747 agg_unlock_node(rn
);
1751 agg_unlock_node(rn
);
1753 if (!have_usable_route
) {
1754 struct prefix
*pfx_mon
= prefix_new();
1755 prefix_copy(pfx_mon
, prefix
);
1756 if (!skiplist_insert(it
->monitor_exterior_orphans
, info
,
1759 bgp_path_info_lock(info
);
1765 void vnc_import_bgp_exterior_add_route(
1766 struct bgp
*bgp
, /* exterior instance, we hope */
1767 const struct prefix
*prefix
, /* unicast prefix */
1768 struct bgp_path_info
*info
) /* unicast info */
1770 vnc_import_bgp_exterior_add_route_it(bgp
, prefix
, info
, NULL
);
1774 * There should be only one of these per prefix at a time.
1775 * This should probably be called as a result of selection operation.
1777 * NB should be called espacially for bgp instances that are named,
1778 * because the exterior routes will always come from one of those.
1779 * We filter here on the instance name to make sure we get only the
1782 void vnc_import_bgp_exterior_del_route(
1783 struct bgp
*bgp
, const struct prefix
*prefix
, /* unicast prefix */
1784 struct bgp_path_info
*info
) /* unicast info */
1787 struct rfapi_cfg
*hc
;
1788 struct rfapi_import_table
*it
;
1789 struct prefix pfx_orig_nexthop
;
1790 afi_t afi
= family2afi(prefix
->family
);
1791 struct bgp
*bgp_default
= bgp_get_default();
1796 memset(&pfx_orig_nexthop
, 0,
1797 sizeof(pfx_orig_nexthop
)); /* keep valgrind happy */
1799 h
= bgp_default
->rfapi
;
1800 hc
= bgp_default
->rfapi_cfg
;
1803 vnc_zlog_debug_verbose(
1804 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1808 if (!hc
->redist_bgp_exterior_view
) {
1809 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1813 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1814 vnc_zlog_debug_verbose(
1815 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1816 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1819 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1820 vnc_zlog_debug_verbose(
1821 "%s: redist of exterior routes no enabled, skipping",
1827 * Extract nexthop from exterior route
1829 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1830 * but if v4 it is in attr->nexthop
1832 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1834 for (it
= h
->imports
; it
; it
= it
->next
) {
1835 struct agg_table
*table
;
1836 struct agg_node
*rn
;
1837 struct agg_node
*par
;
1838 struct bgp_path_info
*bpi_interior
;
1839 int have_usable_route
;
1841 table
= it
->imported_vpn
[afi
];
1843 for (rn
= agg_node_match(table
, &pfx_orig_nexthop
),
1844 have_usable_route
= 0;
1845 (!have_usable_route
) && rn
;) {
1847 for (bpi_interior
= rn
->info
; bpi_interior
;
1848 bpi_interior
= bpi_interior
->next
) {
1849 struct prefix_rd
*prd
;
1852 if (!is_usable_interior_route(bpi_interior
))
1856 * have a legitimate route to exterior's nexthop
1859 * Import unicast route to the import table
1861 have_usable_route
= 1;
1863 if (bpi_interior
->extra
) {
1864 prd
= &bpi_interior
->extra
->vnc
.import
1866 label
= decode_label(
1867 &bpi_interior
->extra
->label
[0]);
1871 rfapiBgpInfoFilteredImportVPN(
1872 it
, FIF_ACTION_KILL
, bpi_interior
->peer
,
1874 prefix
, NULL
, afi
, prd
,
1876 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1877 BGP_ROUTE_REDISTRIBUTE
, &label
);
1882 * TBD factor this out into its own function
1885 if (RFAPI_MONITOR_EXTERIOR(rn
)
1887 if (!skiplist_delete(
1888 RFAPI_MONITOR_EXTERIOR(
1893 bgp_path_info_unlock(
1900 RFAPI_MONITOR_EXTERIOR(
1904 RFAPI_MONITOR_EXTERIOR(
1907 RFAPI_MONITOR_EXTERIOR(
1918 par
= agg_node_parent(rn
);
1921 agg_unlock_node(rn
);
1925 agg_unlock_node(rn
);
1927 if (!have_usable_route
) {
1928 if (!skiplist_delete(it
->monitor_exterior_orphans
, info
,
1931 bgp_path_info_unlock(info
);
1938 * This function should be called after a new interior VPN route
1939 * has been added to an import_table.
1941 * NB should also be called whenever an existing vpn interior route
1942 * becomes valid (e.g., valid_interior_count is inremented)
1944 void vnc_import_bgp_exterior_add_route_interior(
1945 struct bgp
*bgp
, struct rfapi_import_table
*it
,
1946 struct agg_node
*rn_interior
, /* VPN IT node */
1947 struct bgp_path_info
*bpi_interior
) /* VPN IT route */
1949 const struct prefix
*p
= agg_node_get_prefix(rn_interior
);
1950 afi_t afi
= family2afi(p
->family
);
1951 struct agg_node
*par
;
1952 struct bgp_path_info
*bpi_exterior
;
1953 struct prefix
*pfx_exterior
; /* exterior pfx */
1956 struct list
*list_adopted
;
1958 vnc_zlog_debug_verbose("%s: entry", __func__
);
1960 if (!is_usable_interior_route(bpi_interior
)) {
1961 vnc_zlog_debug_verbose(
1962 "%s: not usable interior route, skipping", __func__
);
1966 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1967 vnc_zlog_debug_verbose(
1968 "%s: redist of exterior routes no enabled, skipping",
1973 if (it
== bgp
->rfapi
->it_ce
) {
1974 vnc_zlog_debug_verbose("%s: import table is it_ce, skipping",
1980 vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
1981 __func__
, rn_interior
, bpi_interior
->type
);
1983 if (RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
1985 int count
= 0; /* debugging */
1987 vnc_zlog_debug_verbose(
1988 "%s: has exterior monitor; ext src: %p", __func__
,
1989 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
1992 * There is a monitor here already. Therefore, we do not need
1993 * to do any pulldown. Just construct exterior routes based
1994 * on the new interior route.
1997 for (rc
= skiplist_next(
1998 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
1999 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2001 !rc
; rc
= skiplist_next(
2002 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2003 (void **)&bpi_exterior
,
2004 (void **)&pfx_exterior
, &cursor
)) {
2006 struct prefix_rd
*prd
;
2007 struct attr new_attr
;
2011 ++count
; /* debugging */
2013 assert(bpi_exterior
);
2014 assert(pfx_exterior
);
2016 if (bpi_interior
->extra
) {
2017 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2018 label
= decode_label(
2019 &bpi_interior
->extra
->label
[0]);
2023 /* use local_pref from unicast route */
2024 memset(&new_attr
, 0, sizeof(struct attr
));
2025 new_attr
= *bpi_interior
->attr
;
2027 && (bpi_exterior
->attr
->flag
2028 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2029 new_attr
.local_pref
=
2030 bpi_exterior
->attr
->local_pref
;
2032 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2035 rfapiBgpInfoFilteredImportVPN(
2036 it
, FIF_ACTION_UPDATE
, bpi_interior
->peer
,
2038 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2039 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2040 BGP_ROUTE_REDISTRIBUTE
, &label
);
2042 vnc_zlog_debug_verbose(
2043 "%s: finished constructing exteriors based on existing monitors",
2048 vnc_zlog_debug_verbose("%s: no exterior monitor", __func__
);
2051 * No monitor at this node. Is this the first valid interior
2052 * route at this node?
2054 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
> 1) {
2055 vnc_zlog_debug_verbose(
2056 "%s: new interior route not first valid one, skipping pulldown",
2062 * Look up the tree for possible pulldown candidates.
2063 * Find nearest parent with an exterior route monitor
2065 for (par
= agg_node_parent(rn_interior
); par
;
2066 par
= agg_node_parent(par
)) {
2067 if (RFAPI_HAS_MONITOR_EXTERIOR(par
))
2073 vnc_zlog_debug_verbose(
2074 "%s: checking parent %p for possible pulldowns",
2077 /* check monitors at par for possible pulldown */
2079 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2080 (void **)&bpi_exterior
,
2081 (void **)&pfx_exterior
, &cursor
);
2083 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2084 (void **)&bpi_exterior
,
2085 (void **)&pfx_exterior
, &cursor
)) {
2087 struct prefix pfx_nexthop
;
2089 memset(&pfx_nexthop
, 0,
2090 sizeof(struct prefix
)); /* keep valgrind happy */
2092 /* check original nexthop for prefix match */
2093 rfapiUnicastNexthop2Prefix(afi
, bpi_exterior
->attr
,
2096 if (prefix_match(p
, &pfx_nexthop
)) {
2098 struct bgp_path_info
*bpi
;
2099 struct prefix_rd
*prd
;
2100 struct attr new_attr
;
2106 * add monitor to longer prefix
2108 struct prefix
*pfx_mon
= prefix_new();
2109 prefix_copy(pfx_mon
, pfx_exterior
);
2110 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)
2112 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2113 ->source
= skiplist_new(
2114 0, NULL
, prefix_free_lists
);
2115 agg_lock_node(rn_interior
);
2118 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2120 bpi_exterior
, pfx_mon
);
2121 agg_lock_node(rn_interior
);
2124 * Delete constructed exterior routes based on
2127 for (bpi
= par
->info
; bpi
; bpi
= bpi
->next
) {
2130 prd
= &bpi
->extra
->vnc
.import
2132 label
= decode_label(
2133 &bpi
->extra
->label
[0]);
2137 rfapiBgpInfoFilteredImportVPN(
2138 it
, FIF_ACTION_KILL
, bpi
->peer
,
2140 pfx_exterior
, NULL
, afi
, prd
,
2142 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2143 BGP_ROUTE_REDISTRIBUTE
, &label
);
2148 * Add constructed exterior routes based on
2149 * the new interior route at longer prefix.
2151 if (bpi_interior
->extra
) {
2152 prd
= &bpi_interior
->extra
->vnc
.import
2154 label
= decode_label(
2155 &bpi_interior
->extra
->label
[0]);
2159 /* use local_pref from unicast route */
2160 memset(&new_attr
, 0, sizeof(struct attr
));
2161 new_attr
= *bpi_interior
->attr
;
2163 && (bpi_exterior
->attr
->flag
2164 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2165 new_attr
.local_pref
=
2166 bpi_exterior
->attr
->local_pref
;
2167 new_attr
.flag
|= ATTR_FLAG_BIT(
2168 BGP_ATTR_LOCAL_PREF
);
2171 rfapiBgpInfoFilteredImportVPN(
2172 it
, FIF_ACTION_UPDATE
,
2173 bpi_interior
->peer
, NULL
, /* rfd */
2174 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2175 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2176 BGP_ROUTE_REDISTRIBUTE
, &label
);
2181 * The only monitors at rn_interior are the ones we added just
2182 * above, so we can use the rn_interior list to identify which
2183 * monitors to delete from the parent.
2186 for (rc
= skiplist_next(
2187 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2188 (void **)&bpi_exterior
, NULL
, &cursor
);
2189 !rc
; rc
= skiplist_next(
2190 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2191 (void **)&bpi_exterior
, NULL
, &cursor
)) {
2194 skiplist_delete(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2195 bpi_exterior
, NULL
);
2196 agg_unlock_node(par
); /* sl entry */
2198 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par
)->source
)) {
2199 skiplist_free(RFAPI_MONITOR_EXTERIOR(par
)->source
);
2200 RFAPI_MONITOR_EXTERIOR(par
)->source
= NULL
;
2201 agg_unlock_node(par
); /* sl itself */
2205 vnc_zlog_debug_verbose("%s: checking orphans", __func__
);
2208 * See if any orphans can be pulled down to the current node
2211 list_adopted
= NULL
;
2212 for (rc
= skiplist_next(it
->monitor_exterior_orphans
,
2213 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2215 !rc
; rc
= skiplist_next(it
->monitor_exterior_orphans
,
2216 (void **)&bpi_exterior
,
2217 (void **)&pfx_exterior
, &cursor
)) {
2219 struct prefix pfx_nexthop
;
2220 afi_t afi_exterior
= family2afi(pfx_exterior
->family
);
2222 vnc_zlog_debug_verbose(
2223 "%s: checking exterior orphan at prefix %pFX", __func__
,
2226 if (afi_exterior
!= afi
) {
2227 vnc_zlog_debug_verbose(
2228 "%s: exterior orphan afi %d != interior afi %d, skip",
2229 __func__
, afi_exterior
, afi
);
2233 /* check original nexthop for prefix match */
2234 rfapiUnicastNexthop2Prefix(afi
, bpi_exterior
->attr
,
2237 if (prefix_match(p
, &pfx_nexthop
)) {
2239 struct prefix_rd
*prd
;
2240 struct attr new_attr
;
2246 * add monitor to longer prefix
2249 struct prefix
*pfx_mon
= prefix_new();
2250 prefix_copy(pfx_mon
, pfx_exterior
);
2251 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
) {
2252 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
=
2254 0, NULL
, prefix_free_lists
);
2255 agg_lock_node(rn_interior
); /* sl */
2258 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2259 bpi_exterior
, pfx_mon
);
2260 agg_lock_node(rn_interior
); /* sl entry */
2261 if (!list_adopted
) {
2262 list_adopted
= list_new();
2264 listnode_add(list_adopted
, bpi_exterior
);
2267 * Add constructed exterior routes based on the
2268 * new interior route at the longer prefix.
2270 if (bpi_interior
->extra
) {
2271 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2272 label
= decode_label(
2273 &bpi_interior
->extra
->label
[0]);
2277 /* use local_pref from unicast route */
2278 memset(&new_attr
, 0, sizeof(struct attr
));
2279 new_attr
= *bpi_interior
->attr
;
2281 && (bpi_exterior
->attr
->flag
2282 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2283 new_attr
.local_pref
=
2284 bpi_exterior
->attr
->local_pref
;
2286 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2289 rfapiBgpInfoFilteredImportVPN(
2290 it
, FIF_ACTION_UPDATE
, bpi_interior
->peer
,
2292 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2293 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2294 BGP_ROUTE_REDISTRIBUTE
, &label
);
2298 struct listnode
*node
;
2299 struct agg_node
*an_bpi_exterior
;
2301 for (ALL_LIST_ELEMENTS_RO(list_adopted
, node
,
2303 skiplist_delete(it
->monitor_exterior_orphans
,
2304 an_bpi_exterior
, NULL
);
2306 list_delete(&list_adopted
);
2311 * This function should be called after an interior VPN route
2312 * has been deleted from an import_table.
2313 * bpi_interior must still be valid, but it must already be detached
2314 * from its route node and the route node's valid_interior_count
2315 * must already be decremented.
2317 * NB should also be called whenever an existing vpn interior route
2318 * becomes invalid (e.g., valid_interior_count is decremented)
2320 void vnc_import_bgp_exterior_del_route_interior(
2321 struct bgp
*bgp
, struct rfapi_import_table
*it
,
2322 struct agg_node
*rn_interior
, /* VPN IT node */
2323 struct bgp_path_info
*bpi_interior
) /* VPN IT route */
2325 const struct prefix
*p
= agg_node_get_prefix(rn_interior
);
2326 afi_t afi
= family2afi(p
->family
);
2327 struct agg_node
*par
;
2328 struct bgp_path_info
*bpi_exterior
;
2329 struct prefix
*pfx_exterior
; /* exterior pfx */
2333 if (!VALID_INTERIOR_TYPE(bpi_interior
->type
)) {
2334 vnc_zlog_debug_verbose(
2335 "%s: type %d not valid interior type, skipping",
2336 __func__
, bpi_interior
->type
);
2340 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2341 vnc_zlog_debug_verbose(
2342 "%s: redist of exterior routes no enabled, skipping",
2347 if (it
== bgp
->rfapi
->it_ce
) {
2348 vnc_zlog_debug_verbose("%s: it is it_ce, skipping", __func__
);
2352 /* If no exterior routes depend on this prefix, nothing to do */
2353 if (!RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
2354 vnc_zlog_debug_verbose("%s: no exterior monitor, skipping",
2360 vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
2361 __func__
, rn_interior
, bpi_interior
->type
);
2364 * Remove constructed routes based on the deleted interior route
2367 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2368 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2371 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2372 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2375 struct prefix_rd
*prd
;
2378 if (bpi_interior
->extra
) {
2379 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2380 label
= decode_label(&bpi_interior
->extra
->label
[0]);
2384 rfapiBgpInfoFilteredImportVPN(
2385 it
, FIF_ACTION_KILL
, bpi_interior
->peer
, NULL
, /* rfd */
2386 pfx_exterior
, NULL
, afi
, prd
, bpi_interior
->attr
,
2387 ZEBRA_ROUTE_BGP_DIRECT_EXT
, BGP_ROUTE_REDISTRIBUTE
,
2392 * If there are no remaining valid interior routes at this prefix,
2393 * we need to look up the tree for a possible node to move monitors to
2395 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
) {
2396 vnc_zlog_debug_verbose(
2397 "%s: interior routes still present, skipping",
2403 * Find nearest parent with at least one valid interior route
2404 * If none is found, par will end up NULL, and we will move
2405 * the monitors to the orphan list for this import table
2407 for (par
= agg_node_parent(rn_interior
); par
;
2408 par
= agg_node_parent(par
)) {
2409 if (RFAPI_MONITOR_EXTERIOR(par
)->valid_interior_count
)
2413 vnc_zlog_debug_verbose("%s: par=%p, ext src: %p", __func__
, par
,
2414 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2416 /* move all monitors */
2418 * We will use and delete every element of the source skiplist
2420 while (!skiplist_first(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2421 (void **)&bpi_exterior
,
2422 (void **)&pfx_exterior
)) {
2424 struct prefix
*pfx_mon
= prefix_new();
2426 prefix_copy(pfx_mon
, pfx_exterior
);
2430 struct bgp_path_info
*bpi
;
2433 * Add monitor to parent node
2435 if (!RFAPI_MONITOR_EXTERIOR(par
)->source
) {
2436 RFAPI_MONITOR_EXTERIOR(par
)->source
=
2438 0, NULL
, prefix_free_lists
);
2439 agg_lock_node(par
); /* sl */
2441 skiplist_insert(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2442 bpi_exterior
, pfx_mon
);
2443 agg_lock_node(par
); /* sl entry */
2445 /* Add constructed exterior routes based on parent */
2446 for (bpi
= par
->info
; bpi
; bpi
= bpi
->next
) {
2448 struct prefix_rd
*prd
;
2449 struct attr new_attr
;
2452 if (bpi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
)
2456 prd
= &bpi
->extra
->vnc
.import
.rd
;
2457 label
= decode_label(
2458 &bpi
->extra
->label
[0]);
2462 /* use local_pref from unicast route */
2463 memset(&new_attr
, 0, sizeof(new_attr
));
2464 new_attr
= *bpi
->attr
;
2466 && (bpi_exterior
->attr
->flag
2467 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2468 new_attr
.local_pref
=
2469 bpi_exterior
->attr
->local_pref
;
2470 new_attr
.flag
|= ATTR_FLAG_BIT(
2471 BGP_ATTR_LOCAL_PREF
);
2474 rfapiBgpInfoFilteredImportVPN(
2475 it
, FIF_ACTION_UPDATE
, bpi
->peer
,
2477 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2478 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2479 BGP_ROUTE_REDISTRIBUTE
, &label
);
2485 * No interior route for exterior's nexthop. Save
2487 * in orphan list to await future route.
2489 skiplist_insert(it
->monitor_exterior_orphans
,
2490 bpi_exterior
, pfx_mon
);
2493 skiplist_delete_first(
2494 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2495 agg_unlock_node(rn_interior
); /* sl entry */
2497 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
)) {
2498 skiplist_free(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2499 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
= NULL
;
2500 agg_unlock_node(rn_interior
); /* sl itself */
2504 /***********************************************************************
2505 * Generic add/delete unicast routes
2506 ***********************************************************************/
2508 void vnc_import_bgp_add_route(struct bgp
*bgp
, const struct prefix
*prefix
,
2509 struct bgp_path_info
*info
)
2511 afi_t afi
= family2afi(prefix
->family
);
2513 if (VNC_DEBUG(VERBOSE
)) {
2514 struct prefix pfx_nexthop
;
2516 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2517 vnc_zlog_debug_verbose("%s: pfx %pFX, nh %pFX", __func__
,
2518 prefix
, &pfx_nexthop
);
2521 print_rhn_list(__func__
, "ENTER ");
2526 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
2531 if (!bgp
->rfapi_cfg
) {
2532 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2537 /* check vnc redist flag for bgp direct routes */
2538 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2539 vnc_zlog_debug_verbose(
2540 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
2541 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2545 switch (bgp
->rfapi_cfg
->redist_mode
) {
2546 case VNC_REDIST_MODE_PLAIN
:
2547 vnc_import_bgp_add_route_mode_plain(bgp
, prefix
, info
);
2550 case VNC_REDIST_MODE_RFG
:
2551 if (bgp
->rfapi_cfg
->rfg_redist
)
2552 vnc_import_bgp_add_route_mode_nvegroup(
2553 bgp
, prefix
, info
, bgp
->rfapi_cfg
->rfg_redist
);
2555 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2559 case VNC_REDIST_MODE_RESOLVE_NVE
:
2560 vnc_import_bgp_add_route_mode_resolve_nve(bgp
, prefix
, info
);
2564 print_rhn_list(__func__
, "LEAVE ");
2570 * "Withdrawing a Route" import process
2572 void vnc_import_bgp_del_route(struct bgp
*bgp
, const struct prefix
*prefix
,
2573 struct bgp_path_info
*info
) /* unicast info */
2575 afi_t afi
= family2afi(prefix
->family
);
2580 struct prefix pfx_nexthop
;
2582 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2583 vnc_zlog_debug_verbose("%s: pfx %pFX, nh %pFX", __func__
,
2584 prefix
, &pfx_nexthop
);
2587 print_rhn_list(__func__
, "ENTER ");
2591 if (!bgp
->rfapi_cfg
) {
2592 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2597 /* check bgp redist flag for vnc direct ("vpn") routes */
2598 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2599 vnc_zlog_debug_verbose(
2600 "%s: bgp redistribution of afi=%d VNC direct routes is off",
2605 switch (bgp
->rfapi_cfg
->redist_mode
) {
2606 case VNC_REDIST_MODE_PLAIN
:
2607 vnc_import_bgp_del_route_mode_plain(bgp
, prefix
, info
);
2610 case VNC_REDIST_MODE_RFG
:
2611 if (bgp
->rfapi_cfg
->rfg_redist
)
2612 vnc_import_bgp_del_route_mode_nvegroup(bgp
, prefix
,
2615 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2619 case VNC_REDIST_MODE_RESOLVE_NVE
:
2620 vnc_import_bgp_del_route_mode_resolve_nve(bgp
, afi
, prefix
,
2625 print_rhn_list(__func__
, "LEAVE ");
2631 /***********************************************************************
2633 ***********************************************************************/
2635 void vnc_import_bgp_redist_enable(struct bgp
*bgp
, afi_t afi
)
2637 /* iterate over bgp unicast v4 and v6 routes, call
2638 * vnc_import_bgp_add_route */
2640 struct bgp_dest
*dest
;
2642 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
2644 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2645 vnc_zlog_debug_verbose(
2646 "%s: already enabled for afi %d, skipping", __func__
,
2650 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 1;
2652 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); dest
;
2653 dest
= bgp_route_next(dest
)) {
2655 struct bgp_path_info
*bpi
;
2657 for (bpi
= bgp_dest_get_bgp_path_info(dest
); bpi
;
2660 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2663 vnc_import_bgp_add_route(bgp
, bgp_dest_get_prefix(dest
),
2667 vnc_zlog_debug_verbose(
2668 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2669 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2672 void vnc_import_bgp_exterior_redist_enable(struct bgp
*bgp
, afi_t afi
)
2674 struct bgp
*bgp_exterior
;
2675 struct bgp_dest
*dest
;
2677 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2679 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2680 vnc_zlog_debug_verbose(
2681 "%s: already enabled for afi %d, skipping", __func__
,
2685 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 1;
2687 if (!bgp_exterior
) {
2688 vnc_zlog_debug_verbose(
2689 "%s: no exterior view set yet, no routes to import yet",
2694 for (dest
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); dest
;
2695 dest
= bgp_route_next(dest
)) {
2697 struct bgp_path_info
*bpi
;
2699 for (bpi
= bgp_dest_get_bgp_path_info(dest
); bpi
;
2702 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2705 vnc_import_bgp_exterior_add_route(
2706 bgp_exterior
, bgp_dest_get_prefix(dest
), bpi
);
2709 vnc_zlog_debug_verbose(
2710 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2711 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2715 * This function is for populating a newly-created Import Table
2717 void vnc_import_bgp_exterior_redist_enable_it(
2718 struct bgp
*bgp
, afi_t afi
, struct rfapi_import_table
*it_only
)
2720 struct bgp
*bgp_exterior
;
2721 struct bgp_dest
*dest
;
2723 vnc_zlog_debug_verbose("%s: entry", __func__
);
2725 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2727 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2728 vnc_zlog_debug_verbose("%s: not enabled for afi %d, skipping",
2733 if (!bgp_exterior
) {
2734 vnc_zlog_debug_verbose(
2735 "%s: no exterior view set yet, no routes to import yet",
2740 for (dest
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); dest
;
2741 dest
= bgp_route_next(dest
)) {
2743 struct bgp_path_info
*bpi
;
2745 for (bpi
= bgp_dest_get_bgp_path_info(dest
); bpi
;
2748 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2751 vnc_import_bgp_exterior_add_route_it(
2752 bgp_exterior
, bgp_dest_get_prefix(dest
), bpi
,
2759 void vnc_import_bgp_redist_disable(struct bgp
*bgp
, afi_t afi
)
2762 * iterate over vpn routes, find routes of type ZEBRA_ROUTE_BGP_DIRECT,
2763 * delete (call timer expire immediately)
2765 struct bgp_dest
*dest1
;
2766 struct bgp_dest
*dest2
;
2768 vnc_zlog_debug_verbose("%s: entry", __func__
);
2770 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2771 vnc_zlog_debug_verbose(
2772 "%s: already disabled for afi %d, skipping", __func__
,
2778 * Two-level table for SAFI_MPLS_VPN
2779 * Be careful when changing the things we iterate over
2781 for (dest1
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); dest1
;
2782 dest1
= bgp_route_next(dest1
)) {
2783 const struct prefix
*dest1_p
;
2785 if (!bgp_dest_has_bgp_path_info_data(dest1
))
2788 dest1_p
= bgp_dest_get_prefix(dest1
);
2789 for (dest2
= bgp_table_top(bgp_dest_get_bgp_table_info(dest1
));
2790 dest2
; dest2
= bgp_route_next(dest2
)) {
2791 const struct prefix
*dest2_p
=
2792 bgp_dest_get_prefix(dest2
);
2793 struct bgp_path_info
*bpi
;
2794 struct bgp_path_info
*nextbpi
;
2796 for (bpi
= bgp_dest_get_bgp_path_info(dest2
); bpi
;
2799 nextbpi
= bpi
->next
;
2801 if (bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
)
2804 struct rfapi_descriptor
*rfd
;
2805 vncHDBgpDirect
.peer
= bpi
->peer
;
2809 rfd
= bpi
->extra
->vnc
.export
.rfapi_handle
;
2811 vnc_zlog_debug_verbose(
2812 "%s: deleting bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]",
2813 __func__
, bpi
, bpi
->peer
, bpi
->type
,
2815 (bpi
->extra
? bpi
->extra
->vnc
.export
2820 del_vnc_route(rfd
, bpi
->peer
, bgp
,
2821 SAFI_MPLS_VPN
, dest2_p
,
2822 (struct prefix_rd
*)dest1_p
,
2823 bpi
->type
, bpi
->sub_type
, NULL
,
2826 vncHDBgpDirect
.peer
= NULL
;
2830 /* Clear RHN list */
2831 if (bgp
->rfapi
->resolve_nve_nexthop
) {
2832 struct prefix_bag
*pb
;
2833 struct bgp_path_info
*info
;
2834 while (!skiplist_first(bgp
->rfapi
->resolve_nve_nexthop
, NULL
,
2837 skiplist_delete_first(bgp
->rfapi
->resolve_nve_nexthop
);
2838 bgp_path_info_unlock(info
);
2842 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 0;
2843 vnc_zlog_debug_verbose("%s: return", __func__
);
2847 void vnc_import_bgp_exterior_redist_disable(struct bgp
*bgp
, afi_t afi
)
2849 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
2850 struct bgp
*bgp_exterior
= hc
->redist_bgp_exterior_view
;
2852 vnc_zlog_debug_verbose("%s: entry", __func__
);
2854 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2855 vnc_zlog_debug_verbose(
2856 "%s: already disabled for afi %d, skipping", __func__
,
2861 if (!bgp_exterior
) {
2862 vnc_zlog_debug_verbose(
2863 "%s: bgp exterior view not defined, skipping",
2870 struct bgp_dest
*dest
;
2871 for (dest
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]);
2872 dest
; dest
= bgp_route_next(dest
)) {
2874 struct bgp_path_info
*bpi
;
2876 for (bpi
= bgp_dest_get_bgp_path_info(dest
); bpi
;
2879 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2882 vnc_import_bgp_exterior_del_route(
2883 bgp_exterior
, bgp_dest_get_prefix(dest
),
2888 print_rhn_list(__func__
, NULL
);
2892 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 0;
2893 vnc_zlog_debug_verbose("%s: return", __func__
);