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
);
838 bgp_attr_unintern(&iattr
);
841 static void vnc_import_bgp_add_route_mode_nvegroup(
842 struct bgp
*bgp
, const struct prefix
*prefix
,
843 struct bgp_path_info
*info
, struct rfapi_nve_group_cfg
*rfg
)
845 afi_t afi
= family2afi(prefix
->family
);
846 struct peer
*peer
= info
->peer
;
847 struct attr
*attr
= info
->attr
;
849 struct attr
*iattr
= NULL
;
851 struct rfapi_ip_addr vnaddr
;
852 struct prefix
*vn_pfx
= NULL
;
854 struct ecommunity
*ecom
= NULL
;
855 struct prefix_rd prd
;
856 struct route_map
*rmap
= NULL
;
859 vnc_zlog_debug_verbose("%s(prefix=%pFX) entry", __func__
, prefix
);
864 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
869 if (!(bgp
->rfapi_cfg
)) {
870 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
875 /* check vnc redist flag for bgp direct routes */
876 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
877 vnc_zlog_debug_verbose(
878 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
889 struct rfapi_ip_prefix pfx_un
;
891 vnc_zlog_debug_verbose("%s: using redist RFG", __func__
);
894 * RFG prefix list check
896 if (rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
897 vnc_zlog_debug_verbose(
898 "%s: RFG prefix list is set, checking",
900 if (prefix_list_apply(
901 rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
905 vnc_zlog_debug_verbose(
906 "%s: prefix list returns DENY, blocking route",
910 vnc_zlog_debug_verbose(
911 "%s: prefix list returns PASS, allowing route",
915 /* apply routemap, if any, later */
916 rmap
= rfg
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
919 * export nve group's VN addr prefix must be a /32 which
920 * will yield the VN addr to use
922 vn_pfx
= &rfg
->vn_prefix
;
927 if (!is_host_prefix(&rfg
->un_prefix
)) {
928 /* NB prefixlen==0 means it has not been configured */
929 vnc_zlog_debug_verbose(
930 "%s: redist RFG UN pfx not host pfx (plen=%d), skipping",
931 __func__
, rfg
->un_prefix
.prefixlen
);
935 rfapiQprefix2Rprefix(&rfg
->un_prefix
, &pfx_un
);
937 vncHDBgpDirect
.un_addr
= pfx_un
.prefix
;
940 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
))
941 vnc_zlog_debug_any("%s vn_pfx=%pFX", __func__
, vn_pfx
);
946 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
947 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
954 * This code is here because it allocates an interned attr which
955 * must be freed before we return. It's easier to put it after
956 * all of the possible returns above.
958 memset(&hattr
, 0, sizeof(hattr
));
959 /* hattr becomes a ghost attr */
963 struct bgp_path_info path
;
964 route_map_result_t ret
;
966 memset(&path
, 0, sizeof(path
));
969 ret
= route_map_apply(rmap
, prefix
, &path
);
970 if (ret
== RMAP_DENYMATCH
) {
971 bgp_attr_flush(&hattr
);
972 vnc_zlog_debug_verbose(
973 "%s: route map \"%s\" says DENY, returning",
974 __func__
, rmap
->name
);
979 iattr
= bgp_attr_intern(&hattr
);
980 bgp_attr_flush(&hattr
);
982 /* Now iattr is an allocated interned attr */
987 * Sets RD in dummy HD
992 memset(&prd
, 0, sizeof(prd
));
994 prd
.family
= AF_UNSPEC
;
997 if (rfg
->rd
.family
== AF_UNIX
) {
998 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
1001 if (rfg
->rt_export_list
)
1002 ecom
= ecommunity_dup(
1003 bgp
->rfapi_cfg
->rfg_redist
->rt_export_list
);
1005 ecom
= ecommunity_new();
1007 if (iattr
&& bgp_attr_get_ecommunity(iattr
))
1008 ecom
= ecommunity_merge(ecom
,
1009 bgp_attr_get_ecommunity(iattr
));
1012 local_pref
= calc_local_pref(iattr
, peer
);
1014 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
1018 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, BUFSIZ
);
1019 buf
[BUFSIZ
- 1] = 0;
1020 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
1023 vncHDBgpDirect
.peer
= peer
;
1024 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
1025 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
1026 NULL
, /* RFP options */
1027 NULL
, NULL
, ecom
, NULL
, /* med */
1028 NULL
, /* label: default */
1029 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1031 vncHDBgpDirect
.peer
= NULL
;
1034 ecommunity_free(&ecom
);
1036 bgp_attr_unintern(&iattr
);
1039 static void vnc_import_bgp_del_route_mode_plain(struct bgp
*bgp
,
1040 const struct prefix
*prefix
,
1041 struct bgp_path_info
*info
)
1043 struct prefix_rd prd
;
1044 afi_t afi
= family2afi(prefix
->family
);
1045 struct prefix
*vn_pfx
= NULL
;
1046 struct rfapi_ip_addr vnaddr
;
1047 struct prefix vn_pfx_space
;
1053 * Compute VN address
1057 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &vn_pfx_space
);
1059 vnc_zlog_debug_verbose("%s: no attr, can't delete route",
1063 vn_pfx
= &vn_pfx_space
;
1065 vnaddr
.addr_family
= vn_pfx
->family
;
1066 switch (vn_pfx
->family
) {
1068 if (vn_pfx
->prefixlen
!= IPV4_MAX_BITLEN
) {
1069 vnc_zlog_debug_verbose(
1070 "%s: redist VN plen (%d) != 32, skipping",
1071 __func__
, vn_pfx
->prefixlen
);
1074 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1078 if (vn_pfx
->prefixlen
!= IPV6_MAX_BITLEN
) {
1079 vnc_zlog_debug_verbose(
1080 "%s: redist VN plen (%d) != 128, skipping",
1081 __func__
, vn_pfx
->prefixlen
);
1084 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1088 vnc_zlog_debug_verbose(
1089 "%s: no redist RFG VN host pfx configured, skipping",
1095 memset(&prd
, 0, sizeof(prd
));
1096 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1097 vnc_zlog_debug_verbose("%s: can't auto-assign RD, skipping",
1102 vncHDBgpDirect
.peer
= info
->peer
;
1103 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1104 vncHDBgpDirect
.peer
);
1105 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1106 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1109 vncHDBgpDirect
.peer
= NULL
;
1112 static void vnc_import_bgp_del_route_mode_nvegroup(struct bgp
*bgp
,
1113 const struct prefix
*prefix
,
1114 struct bgp_path_info
*info
)
1116 struct prefix_rd prd
;
1117 afi_t afi
= family2afi(prefix
->family
);
1118 struct rfapi_nve_group_cfg
*rfg
= NULL
;
1119 struct prefix
*vn_pfx
= NULL
;
1120 struct rfapi_ip_addr vnaddr
;
1125 rfg
= bgp
->rfapi_cfg
->rfg_redist
;
1129 * Compute VN address
1133 * export nve group's VN addr prefix must be a /32 which
1134 * will yield the VN addr to use
1136 vn_pfx
= &rfg
->vn_prefix
;
1139 vnaddr
.addr_family
= vn_pfx
->family
;
1140 switch (vn_pfx
->family
) {
1142 if (vn_pfx
->prefixlen
!= IPV4_MAX_BITLEN
) {
1143 vnc_zlog_debug_verbose(
1144 "%s: redist VN plen (%d) != 32, skipping",
1145 __func__
, vn_pfx
->prefixlen
);
1148 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1152 if (vn_pfx
->prefixlen
!= IPV6_MAX_BITLEN
) {
1153 vnc_zlog_debug_verbose(
1154 "%s: redist VN plen (%d) != 128, skipping",
1155 __func__
, vn_pfx
->prefixlen
);
1158 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1162 vnc_zlog_debug_verbose(
1163 "%s: no redist RFG VN host pfx configured, skipping",
1168 memset(&prd
, 0, sizeof(prd
));
1170 prd
.family
= AF_UNSPEC
;
1173 if (rfg
->rd
.family
== AF_UNIX
) {
1174 /* means "auto" with VN addr */
1175 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1176 vnc_zlog_debug_verbose(
1177 "%s: can't auto-assign RD, skipping", __func__
);
1183 vncHDBgpDirect
.peer
= info
->peer
;
1184 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1185 vncHDBgpDirect
.peer
);
1186 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1187 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1190 vncHDBgpDirect
.peer
= NULL
;
1193 static void vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1194 struct bgp
*bgp
, afi_t afi
, struct bgp_path_info
*bpi
, /* VPN bpi */
1195 struct prefix_rd
*prd
, /* RD */
1196 const struct prefix
*prefix
) /* unicast route prefix */
1200 if (bpi
->type
!= ZEBRA_ROUTE_BGP
1201 && bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
) {
1205 if (bpi
->sub_type
!= BGP_ROUTE_NORMAL
1206 && bpi
->sub_type
!= BGP_ROUTE_STATIC
1207 && bpi
->sub_type
!= BGP_ROUTE_RFP
) {
1211 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
1214 vncHDResolveNve
.peer
= bpi
->peer
;
1215 if (!rfapiGetVncTunnelUnAddr(bpi
->attr
, &un
)) {
1216 if (rfapiQprefix2Raddr(&un
, &vncHDResolveNve
.un_addr
))
1219 memset(&vncHDResolveNve
.un_addr
, 0,
1220 sizeof(vncHDResolveNve
.un_addr
));
1223 del_vnc_route(&vncHDResolveNve
, vncHDResolveNve
.peer
, bgp
,
1224 SAFI_MPLS_VPN
, prefix
, /* unicast route prefix */
1225 prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
, NULL
,
1229 static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1230 struct prefix_rd
*prd
,
1231 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1232 afi_t afi
, struct bgp
*bgp
,
1233 const struct prefix
*prefix
, /* unicast prefix */
1234 const struct prefix
*ubpi_nexthop
) /* unicast bpi's nexthop */
1236 struct bgp_dest
*bd
;
1237 struct bgp_path_info
*bpi
;
1242 vnc_zlog_debug_verbose("%s: ubpi_nexthop=%pFX", __func__
, ubpi_nexthop
);
1246 bd
= bgp_node_lookup(table_rd
, ubpi_nexthop
);
1248 vnc_zlog_debug_verbose(
1249 "%s: no match in RD's table for ubpi_nexthop",
1254 /* Iterate over bgp_info items at this node */
1255 for (bpi
= bgp_dest_get_bgp_path_info(bd
); bpi
; bpi
= bpi
->next
) {
1257 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1258 bgp
, afi
, bpi
, /* VPN bpi */
1260 prefix
); /* unicast route prefix */
1263 bgp_dest_unlock_node(bd
);
1267 vnc_import_bgp_del_route_mode_resolve_nve(struct bgp
*bgp
, afi_t afi
,
1268 const struct prefix
*prefix
,
1269 struct bgp_path_info
*info
)
1271 struct ecommunity
*ecom
= NULL
;
1272 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
1274 // struct listnode *hnode;
1275 // struct rfapi_descriptor *rfd;
1276 struct prefix_bag
*pb
;
1278 struct skiplist
*sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1280 struct bgp_dest
*bdp
; /* prd table node */
1283 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1288 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
1289 vnc_zlog_debug_verbose(
1290 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
1291 __func__
, info
->type
, zebra_route_string(info
->type
),
1292 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
1296 if (process_unicast_route(bgp
, afi
, prefix
, info
, &ecom
,
1297 &pfx_unicast_nexthop
)) {
1299 vnc_zlog_debug_verbose(
1300 "%s: process_unicast_route error, skipping", __func__
);
1304 rc
= skiplist_first_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1307 if (pb
->ubpi
== info
) {
1308 skiplist_delete(sl
, &pfx_unicast_nexthop
, pb
);
1309 bgp_path_info_unlock(info
);
1312 rc
= skiplist_next_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1317 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
1318 * (exact match, /32). If an exact match is found, call add_vnc_route.
1321 for (bdp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bdp
;
1322 bdp
= bgp_route_next(bdp
)) {
1324 struct bgp_table
*table
;
1326 table
= bgp_dest_get_bgp_table_info(bdp
);
1331 vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1332 (struct prefix_rd
*)bgp_dest_get_prefix(bdp
), table
,
1333 afi
, bgp
, prefix
, &pfx_unicast_nexthop
);
1337 ecommunity_free(&ecom
);
1341 /***********************************************************************
1342 * Add/Delete CE->NVE routes
1343 ***********************************************************************/
1346 * Should be called whan a bpi is added to VPN RIB. This function
1347 * will check if it is a host route and return immediately if not.
1349 void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1350 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1351 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1352 const struct prefix
*prefix
, /* VPN prefix */
1353 struct bgp_path_info
*bpi
) /* new VPN host route */
1355 afi_t afi
= family2afi(prefix
->family
);
1356 struct skiplist
*sl
= NULL
;
1358 struct prefix_bag
*pb
;
1360 struct rfapi_cfg
*hc
= NULL
;
1362 vnc_zlog_debug_verbose("%s: entry", __func__
);
1364 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1365 vnc_zlog_debug_verbose("%s: bad afi %d, skipping", __func__
,
1370 if (!(hc
= bgp
->rfapi_cfg
)) {
1371 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1376 /* check vnc redist flag for bgp direct routes */
1377 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1378 vnc_zlog_debug_verbose(
1379 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1384 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1385 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1391 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1394 vnc_zlog_debug_verbose(
1395 "%s: no resolve_nve_nexthop skiplist, skipping",
1400 if (!is_host_prefix(prefix
)) {
1401 vnc_zlog_debug_verbose("%s: not host prefix, skipping",
1406 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1408 struct ecommunity
*ecom
;
1409 struct prefix pfx_unicast_nexthop
;
1410 uint32_t *med
= NULL
;
1411 uint32_t local_pref
;
1413 memset(&pfx_unicast_nexthop
, 0,
1414 sizeof(pfx_unicast_nexthop
)); /* keep valgrind happy */
1416 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
))
1418 "%s: examining RHN Entry (q=%p): upfx=%pFX, hpfx=%pFX, ubpi=%p",
1419 __func__
, cursor
, &pb
->upfx
, &pb
->hpfx
,
1422 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubpi
, &ecom
,
1423 &pfx_unicast_nexthop
)) {
1425 vnc_zlog_debug_verbose(
1426 "%s: process_unicast_route error, skipping",
1430 local_pref
= calc_local_pref(pb
->ubpi
->attr
, pb
->ubpi
->peer
);
1432 if (pb
->ubpi
->attr
->flag
1433 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
1434 med
= &pb
->ubpi
->attr
->med
;
1439 if (vnc_prefix_cmp(&pfx_unicast_nexthop
, prefix
)) {
1440 vnc_zlog_debug_verbose(
1441 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
1442 __func__
, &pfx_unicast_nexthop
, prefix
);
1446 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
1447 bgp
, afi
, bpi
, /* VPN bpi */
1448 prd
, &pb
->upfx
, /* unicast prefix */
1449 &local_pref
, med
, ecom
);
1452 ecommunity_free(&ecom
);
1457 vnc_zlog_debug_verbose(
1458 "%s: advancing past RHN Entry (q=%p): with prefix %pFX",
1459 __func__
, cursor
, prefix
);
1460 print_rhn_list(__func__
, NULL
); /* debug */
1463 rc
= skiplist_next_value(sl
, prefix
, (void *)&pb
, &cursor
);
1465 vnc_zlog_debug_verbose("%s: done", __func__
);
1469 void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
1470 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1471 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1472 const struct prefix
*prefix
, /* VPN prefix */
1473 struct bgp_path_info
*bpi
) /* old VPN host route */
1475 afi_t afi
= family2afi(prefix
->family
);
1476 struct skiplist
*sl
= NULL
;
1477 struct prefix_bag
*pb
;
1479 struct rfapi_cfg
*hc
= NULL
;
1482 vnc_zlog_debug_verbose("%s(bgp=%p, nve prefix=%pFX)", __func__
, bgp
,
1485 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
)
1488 if (!(hc
= bgp
->rfapi_cfg
)) {
1489 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1494 /* check vnc redist flag for bgp direct routes */
1495 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1496 vnc_zlog_debug_verbose(
1497 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1502 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1503 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1509 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1512 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1517 if (!is_host_prefix(prefix
)) {
1518 vnc_zlog_debug_verbose("%s: not host route, skip", __func__
);
1523 * Find all entries with key == CE in the RHN list
1525 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1528 struct ecommunity
*ecom
;
1529 struct prefix pfx_unicast_nexthop
;
1531 memset(&pfx_unicast_nexthop
, 0,
1532 sizeof(pfx_unicast_nexthop
)); /* keep valgrind happy */
1534 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubpi
, &ecom
,
1535 &pfx_unicast_nexthop
)) {
1537 vnc_zlog_debug_verbose(
1538 "%s: process_unicast_route error, skipping",
1546 if (vnc_prefix_cmp(&pfx_unicast_nexthop
, prefix
)) {
1547 vnc_zlog_debug_verbose(
1548 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
1549 __func__
, &pfx_unicast_nexthop
, prefix
);
1553 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1554 bgp
, afi
, bpi
, prd
, &pb
->upfx
);
1557 ecommunity_free(&ecom
);
1559 rc
= skiplist_next_value(sl
, prefix
, (void *)&pb
, &cursor
);
1564 /***********************************************************************
1566 ***********************************************************************/
1568 #define DEBUG_IS_USABLE_INTERIOR 1
1570 static int is_usable_interior_route(struct bgp_path_info
*bpi_interior
)
1572 if (!VALID_INTERIOR_TYPE(bpi_interior
->type
)) {
1573 #if DEBUG_IS_USABLE_INTERIOR
1574 vnc_zlog_debug_verbose(
1575 "%s: NO: type %d is not valid interior type", __func__
,
1576 bpi_interior
->type
);
1580 if (!CHECK_FLAG(bpi_interior
->flags
, BGP_PATH_VALID
)) {
1581 #if DEBUG_IS_USABLE_INTERIOR
1582 vnc_zlog_debug_verbose("%s: NO: BGP_PATH_VALID not set",
1591 * There should be only one of these per prefix at a time.
1592 * This should be called as a result of selection operation
1594 * NB should be called espacially for bgp instances that are named,
1595 * because the exterior routes will always come from one of those.
1596 * We filter here on the instance name to make sure we get only the
1599 static void vnc_import_bgp_exterior_add_route_it(
1600 struct bgp
*bgp
, /* exterior instance, we hope */
1601 const struct prefix
*prefix
, /* unicast prefix */
1602 struct bgp_path_info
*info
, /* unicast info */
1603 struct rfapi_import_table
*it_only
) /* NULL, or limit to this IT */
1606 struct rfapi_cfg
*hc
;
1607 struct prefix pfx_orig_nexthop
;
1608 struct rfapi_import_table
*it
;
1609 struct bgp
*bgp_default
= bgp_get_default();
1610 afi_t afi
= family2afi(prefix
->family
);
1615 h
= bgp_default
->rfapi
;
1616 hc
= bgp_default
->rfapi_cfg
;
1618 vnc_zlog_debug_verbose("%s: entry with it=%p", __func__
, it_only
);
1621 vnc_zlog_debug_verbose(
1622 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1626 if (!hc
->redist_bgp_exterior_view
) {
1627 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1631 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1632 vnc_zlog_debug_verbose(
1633 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1634 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1638 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1639 vnc_zlog_debug_verbose(
1640 "%s: redist of exterior routes not enabled, skipping",
1646 * Extract nexthop from exterior route
1648 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1649 * but if v4 it is in attr->nexthop
1651 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1653 for (it
= h
->imports
; it
; it
= it
->next
) {
1654 struct agg_table
*table
;
1655 struct agg_node
*rn
;
1656 struct agg_node
*par
;
1657 struct bgp_path_info
*bpi_interior
;
1658 int have_usable_route
;
1660 vnc_zlog_debug_verbose("%s: doing it %p", __func__
, it
);
1662 if (it_only
&& (it_only
!= it
)) {
1663 vnc_zlog_debug_verbose("%s: doesn't match it_only %p",
1668 table
= it
->imported_vpn
[afi
];
1670 for (rn
= agg_node_match(table
, &pfx_orig_nexthop
),
1671 have_usable_route
= 0;
1672 (!have_usable_route
) && rn
;) {
1674 vnc_zlog_debug_verbose("%s: it %p trying rn %p",
1677 for (bpi_interior
= rn
->info
; bpi_interior
;
1678 bpi_interior
= bpi_interior
->next
) {
1679 struct prefix_rd
*prd
;
1680 struct attr new_attr
;
1683 if (!is_usable_interior_route(bpi_interior
))
1686 vnc_zlog_debug_verbose(
1687 "%s: usable: bpi_interior %p", __func__
,
1691 * have a legitimate route to exterior's nexthop
1694 * Import unicast route to the import table
1696 have_usable_route
= 1;
1698 if (bpi_interior
->extra
) {
1699 prd
= &bpi_interior
->extra
->vnc
.import
1701 label
= decode_label(
1702 &bpi_interior
->extra
->label
[0]);
1706 /* use local_pref from unicast route */
1707 memset(&new_attr
, 0, sizeof(new_attr
));
1708 new_attr
= *bpi_interior
->attr
;
1709 if (info
->attr
->flag
1710 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
1711 new_attr
.local_pref
=
1712 info
->attr
->local_pref
;
1713 new_attr
.flag
|= ATTR_FLAG_BIT(
1714 BGP_ATTR_LOCAL_PREF
);
1717 rfapiBgpInfoFilteredImportVPN(
1718 it
, FIF_ACTION_UPDATE
,
1719 bpi_interior
->peer
, NULL
, /* rfd */
1720 prefix
, NULL
, afi
, prd
, &new_attr
,
1721 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1722 BGP_ROUTE_REDISTRIBUTE
, &label
);
1725 if (have_usable_route
) {
1729 * TBD factor this out into its own function
1731 struct prefix
*pfx_mon
= prefix_new();
1732 if (!RFAPI_MONITOR_EXTERIOR(rn
)->source
) {
1733 RFAPI_MONITOR_EXTERIOR(rn
)->source
=
1737 agg_lock_node(rn
); /* for skiplist */
1739 agg_lock_node(rn
); /* for skiplist entry */
1740 prefix_copy(pfx_mon
, prefix
);
1741 if (!skiplist_insert(
1742 RFAPI_MONITOR_EXTERIOR(rn
)->source
,
1745 bgp_path_info_lock(info
);
1748 par
= agg_node_parent(rn
);
1751 agg_unlock_node(rn
);
1755 agg_unlock_node(rn
);
1757 if (!have_usable_route
) {
1758 struct prefix
*pfx_mon
= prefix_new();
1759 prefix_copy(pfx_mon
, prefix
);
1760 if (!skiplist_insert(it
->monitor_exterior_orphans
, info
,
1763 bgp_path_info_lock(info
);
1769 void vnc_import_bgp_exterior_add_route(
1770 struct bgp
*bgp
, /* exterior instance, we hope */
1771 const struct prefix
*prefix
, /* unicast prefix */
1772 struct bgp_path_info
*info
) /* unicast info */
1774 vnc_import_bgp_exterior_add_route_it(bgp
, prefix
, info
, NULL
);
1778 * There should be only one of these per prefix at a time.
1779 * This should probably be called as a result of selection operation.
1781 * NB should be called espacially for bgp instances that are named,
1782 * because the exterior routes will always come from one of those.
1783 * We filter here on the instance name to make sure we get only the
1786 void vnc_import_bgp_exterior_del_route(
1787 struct bgp
*bgp
, const struct prefix
*prefix
, /* unicast prefix */
1788 struct bgp_path_info
*info
) /* unicast info */
1791 struct rfapi_cfg
*hc
;
1792 struct rfapi_import_table
*it
;
1793 struct prefix pfx_orig_nexthop
;
1794 afi_t afi
= family2afi(prefix
->family
);
1795 struct bgp
*bgp_default
= bgp_get_default();
1800 memset(&pfx_orig_nexthop
, 0,
1801 sizeof(pfx_orig_nexthop
)); /* keep valgrind happy */
1803 h
= bgp_default
->rfapi
;
1804 hc
= bgp_default
->rfapi_cfg
;
1807 vnc_zlog_debug_verbose(
1808 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1812 if (!hc
->redist_bgp_exterior_view
) {
1813 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1817 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1818 vnc_zlog_debug_verbose(
1819 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1820 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1823 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1824 vnc_zlog_debug_verbose(
1825 "%s: redist of exterior routes no enabled, skipping",
1831 * Extract nexthop from exterior route
1833 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1834 * but if v4 it is in attr->nexthop
1836 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1838 for (it
= h
->imports
; it
; it
= it
->next
) {
1839 struct agg_table
*table
;
1840 struct agg_node
*rn
;
1841 struct agg_node
*par
;
1842 struct bgp_path_info
*bpi_interior
;
1843 int have_usable_route
;
1845 table
= it
->imported_vpn
[afi
];
1847 for (rn
= agg_node_match(table
, &pfx_orig_nexthop
),
1848 have_usable_route
= 0;
1849 (!have_usable_route
) && rn
;) {
1851 for (bpi_interior
= rn
->info
; bpi_interior
;
1852 bpi_interior
= bpi_interior
->next
) {
1853 struct prefix_rd
*prd
;
1856 if (!is_usable_interior_route(bpi_interior
))
1860 * have a legitimate route to exterior's nexthop
1863 * Import unicast route to the import table
1865 have_usable_route
= 1;
1867 if (bpi_interior
->extra
) {
1868 prd
= &bpi_interior
->extra
->vnc
.import
1870 label
= decode_label(
1871 &bpi_interior
->extra
->label
[0]);
1875 rfapiBgpInfoFilteredImportVPN(
1876 it
, FIF_ACTION_KILL
, bpi_interior
->peer
,
1878 prefix
, NULL
, afi
, prd
,
1880 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1881 BGP_ROUTE_REDISTRIBUTE
, &label
);
1886 * TBD factor this out into its own function
1889 if (RFAPI_MONITOR_EXTERIOR(rn
)
1891 if (!skiplist_delete(
1892 RFAPI_MONITOR_EXTERIOR(
1897 bgp_path_info_unlock(
1904 RFAPI_MONITOR_EXTERIOR(
1908 RFAPI_MONITOR_EXTERIOR(
1911 RFAPI_MONITOR_EXTERIOR(
1922 par
= agg_node_parent(rn
);
1925 agg_unlock_node(rn
);
1929 agg_unlock_node(rn
);
1931 if (!have_usable_route
) {
1932 if (!skiplist_delete(it
->monitor_exterior_orphans
, info
,
1935 bgp_path_info_unlock(info
);
1942 * This function should be called after a new interior VPN route
1943 * has been added to an import_table.
1945 * NB should also be called whenever an existing vpn interior route
1946 * becomes valid (e.g., valid_interior_count is inremented)
1948 void vnc_import_bgp_exterior_add_route_interior(
1949 struct bgp
*bgp
, struct rfapi_import_table
*it
,
1950 struct agg_node
*rn_interior
, /* VPN IT node */
1951 struct bgp_path_info
*bpi_interior
) /* VPN IT route */
1953 const struct prefix
*p
= agg_node_get_prefix(rn_interior
);
1954 afi_t afi
= family2afi(p
->family
);
1955 struct agg_node
*par
;
1956 struct bgp_path_info
*bpi_exterior
;
1957 struct prefix
*pfx_exterior
; /* exterior pfx */
1960 struct list
*list_adopted
;
1962 vnc_zlog_debug_verbose("%s: entry", __func__
);
1964 if (!is_usable_interior_route(bpi_interior
)) {
1965 vnc_zlog_debug_verbose(
1966 "%s: not usable interior route, skipping", __func__
);
1970 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1971 vnc_zlog_debug_verbose(
1972 "%s: redist of exterior routes no enabled, skipping",
1977 if (it
== bgp
->rfapi
->it_ce
) {
1978 vnc_zlog_debug_verbose("%s: import table is it_ce, skipping",
1984 vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
1985 __func__
, rn_interior
, bpi_interior
->type
);
1987 if (RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
1989 vnc_zlog_debug_verbose(
1990 "%s: has exterior monitor; ext src: %p", __func__
,
1991 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
1994 * There is a monitor here already. Therefore, we do not need
1995 * to do any pulldown. Just construct exterior routes based
1996 * on the new interior route.
1999 for (rc
= skiplist_next(
2000 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2001 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2003 !rc
; rc
= skiplist_next(
2004 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2005 (void **)&bpi_exterior
,
2006 (void **)&pfx_exterior
, &cursor
)) {
2008 struct prefix_rd
*prd
;
2009 struct attr new_attr
;
2012 assert(bpi_exterior
);
2013 assert(pfx_exterior
);
2015 if (bpi_interior
->extra
) {
2016 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2017 label
= decode_label(
2018 &bpi_interior
->extra
->label
[0]);
2022 /* use local_pref from unicast route */
2023 memset(&new_attr
, 0, sizeof(struct attr
));
2024 new_attr
= *bpi_interior
->attr
;
2026 && (bpi_exterior
->attr
->flag
2027 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2028 new_attr
.local_pref
=
2029 bpi_exterior
->attr
->local_pref
;
2031 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2034 rfapiBgpInfoFilteredImportVPN(
2035 it
, FIF_ACTION_UPDATE
, bpi_interior
->peer
,
2037 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2038 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2039 BGP_ROUTE_REDISTRIBUTE
, &label
);
2041 vnc_zlog_debug_verbose(
2042 "%s: finished constructing exteriors based on existing monitors",
2047 vnc_zlog_debug_verbose("%s: no exterior monitor", __func__
);
2050 * No monitor at this node. Is this the first valid interior
2051 * route at this node?
2053 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
> 1) {
2054 vnc_zlog_debug_verbose(
2055 "%s: new interior route not first valid one, skipping pulldown",
2061 * Look up the tree for possible pulldown candidates.
2062 * Find nearest parent with an exterior route monitor
2064 for (par
= agg_node_parent(rn_interior
); par
;
2065 par
= agg_node_parent(par
)) {
2066 if (RFAPI_HAS_MONITOR_EXTERIOR(par
))
2072 vnc_zlog_debug_verbose(
2073 "%s: checking parent %p for possible pulldowns",
2076 /* check monitors at par for possible pulldown */
2078 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2079 (void **)&bpi_exterior
,
2080 (void **)&pfx_exterior
, &cursor
);
2082 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2083 (void **)&bpi_exterior
,
2084 (void **)&pfx_exterior
, &cursor
)) {
2086 struct prefix pfx_nexthop
;
2088 memset(&pfx_nexthop
, 0,
2089 sizeof(struct prefix
)); /* keep valgrind happy */
2091 /* check original nexthop for prefix match */
2092 rfapiUnicastNexthop2Prefix(afi
, bpi_exterior
->attr
,
2095 if (prefix_match(p
, &pfx_nexthop
)) {
2097 struct bgp_path_info
*bpi
;
2098 struct prefix_rd
*prd
;
2099 struct attr new_attr
;
2105 * add monitor to longer prefix
2107 struct prefix
*pfx_mon
= prefix_new();
2108 prefix_copy(pfx_mon
, pfx_exterior
);
2109 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)
2111 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2112 ->source
= skiplist_new(
2113 0, NULL
, prefix_free_lists
);
2114 agg_lock_node(rn_interior
);
2117 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2119 bpi_exterior
, pfx_mon
);
2120 agg_lock_node(rn_interior
);
2123 * Delete constructed exterior routes based on
2126 for (bpi
= par
->info
; bpi
; bpi
= bpi
->next
) {
2129 prd
= &bpi
->extra
->vnc
.import
2131 label
= decode_label(
2132 &bpi
->extra
->label
[0]);
2136 rfapiBgpInfoFilteredImportVPN(
2137 it
, FIF_ACTION_KILL
, bpi
->peer
,
2139 pfx_exterior
, NULL
, afi
, prd
,
2141 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2142 BGP_ROUTE_REDISTRIBUTE
, &label
);
2147 * Add constructed exterior routes based on
2148 * the new interior route at longer prefix.
2150 if (bpi_interior
->extra
) {
2151 prd
= &bpi_interior
->extra
->vnc
.import
2153 label
= decode_label(
2154 &bpi_interior
->extra
->label
[0]);
2158 /* use local_pref from unicast route */
2159 memset(&new_attr
, 0, sizeof(struct attr
));
2160 new_attr
= *bpi_interior
->attr
;
2162 && (bpi_exterior
->attr
->flag
2163 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2164 new_attr
.local_pref
=
2165 bpi_exterior
->attr
->local_pref
;
2166 new_attr
.flag
|= ATTR_FLAG_BIT(
2167 BGP_ATTR_LOCAL_PREF
);
2170 rfapiBgpInfoFilteredImportVPN(
2171 it
, FIF_ACTION_UPDATE
,
2172 bpi_interior
->peer
, NULL
, /* rfd */
2173 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2174 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2175 BGP_ROUTE_REDISTRIBUTE
, &label
);
2180 * The only monitors at rn_interior are the ones we added just
2181 * above, so we can use the rn_interior list to identify which
2182 * monitors to delete from the parent.
2185 for (rc
= skiplist_next(
2186 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2187 (void **)&bpi_exterior
, NULL
, &cursor
);
2188 !rc
; rc
= skiplist_next(
2189 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2190 (void **)&bpi_exterior
, NULL
, &cursor
)) {
2193 skiplist_delete(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2194 bpi_exterior
, NULL
);
2195 agg_unlock_node(par
); /* sl entry */
2197 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par
)->source
)) {
2198 skiplist_free(RFAPI_MONITOR_EXTERIOR(par
)->source
);
2199 RFAPI_MONITOR_EXTERIOR(par
)->source
= NULL
;
2200 agg_unlock_node(par
); /* sl itself */
2204 vnc_zlog_debug_verbose("%s: checking orphans", __func__
);
2207 * See if any orphans can be pulled down to the current node
2210 list_adopted
= NULL
;
2211 for (rc
= skiplist_next(it
->monitor_exterior_orphans
,
2212 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2214 !rc
; rc
= skiplist_next(it
->monitor_exterior_orphans
,
2215 (void **)&bpi_exterior
,
2216 (void **)&pfx_exterior
, &cursor
)) {
2218 struct prefix pfx_nexthop
;
2219 afi_t afi_exterior
= family2afi(pfx_exterior
->family
);
2221 vnc_zlog_debug_verbose(
2222 "%s: checking exterior orphan at prefix %pFX", __func__
,
2225 if (afi_exterior
!= afi
) {
2226 vnc_zlog_debug_verbose(
2227 "%s: exterior orphan afi %d != interior afi %d, skip",
2228 __func__
, afi_exterior
, afi
);
2232 /* check original nexthop for prefix match */
2233 rfapiUnicastNexthop2Prefix(afi
, bpi_exterior
->attr
,
2236 if (prefix_match(p
, &pfx_nexthop
)) {
2238 struct prefix_rd
*prd
;
2239 struct attr new_attr
;
2245 * add monitor to longer prefix
2248 struct prefix
*pfx_mon
= prefix_new();
2249 prefix_copy(pfx_mon
, pfx_exterior
);
2250 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
) {
2251 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
=
2253 0, NULL
, prefix_free_lists
);
2254 agg_lock_node(rn_interior
); /* sl */
2257 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2258 bpi_exterior
, pfx_mon
);
2259 agg_lock_node(rn_interior
); /* sl entry */
2260 if (!list_adopted
) {
2261 list_adopted
= list_new();
2263 listnode_add(list_adopted
, bpi_exterior
);
2266 * Add constructed exterior routes based on the
2267 * new interior route at the longer prefix.
2269 if (bpi_interior
->extra
) {
2270 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2271 label
= decode_label(
2272 &bpi_interior
->extra
->label
[0]);
2276 /* use local_pref from unicast route */
2277 memset(&new_attr
, 0, sizeof(struct attr
));
2278 new_attr
= *bpi_interior
->attr
;
2280 && (bpi_exterior
->attr
->flag
2281 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2282 new_attr
.local_pref
=
2283 bpi_exterior
->attr
->local_pref
;
2285 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2288 rfapiBgpInfoFilteredImportVPN(
2289 it
, FIF_ACTION_UPDATE
, bpi_interior
->peer
,
2291 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2292 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2293 BGP_ROUTE_REDISTRIBUTE
, &label
);
2297 struct listnode
*node
;
2298 struct agg_node
*an_bpi_exterior
;
2300 for (ALL_LIST_ELEMENTS_RO(list_adopted
, node
,
2302 skiplist_delete(it
->monitor_exterior_orphans
,
2303 an_bpi_exterior
, NULL
);
2305 list_delete(&list_adopted
);
2310 * This function should be called after an interior VPN route
2311 * has been deleted from an import_table.
2312 * bpi_interior must still be valid, but it must already be detached
2313 * from its route node and the route node's valid_interior_count
2314 * must already be decremented.
2316 * NB should also be called whenever an existing vpn interior route
2317 * becomes invalid (e.g., valid_interior_count is decremented)
2319 void vnc_import_bgp_exterior_del_route_interior(
2320 struct bgp
*bgp
, struct rfapi_import_table
*it
,
2321 struct agg_node
*rn_interior
, /* VPN IT node */
2322 struct bgp_path_info
*bpi_interior
) /* VPN IT route */
2324 const struct prefix
*p
= agg_node_get_prefix(rn_interior
);
2325 afi_t afi
= family2afi(p
->family
);
2326 struct agg_node
*par
;
2327 struct bgp_path_info
*bpi_exterior
;
2328 struct prefix
*pfx_exterior
; /* exterior pfx */
2332 if (!VALID_INTERIOR_TYPE(bpi_interior
->type
)) {
2333 vnc_zlog_debug_verbose(
2334 "%s: type %d not valid interior type, skipping",
2335 __func__
, bpi_interior
->type
);
2339 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2340 vnc_zlog_debug_verbose(
2341 "%s: redist of exterior routes no enabled, skipping",
2346 if (it
== bgp
->rfapi
->it_ce
) {
2347 vnc_zlog_debug_verbose("%s: it is it_ce, skipping", __func__
);
2351 /* If no exterior routes depend on this prefix, nothing to do */
2352 if (!RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
2353 vnc_zlog_debug_verbose("%s: no exterior monitor, skipping",
2359 vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
2360 __func__
, rn_interior
, bpi_interior
->type
);
2363 * Remove constructed routes based on the deleted interior route
2366 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2367 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2370 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2371 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2374 struct prefix_rd
*prd
;
2377 if (bpi_interior
->extra
) {
2378 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2379 label
= decode_label(&bpi_interior
->extra
->label
[0]);
2383 rfapiBgpInfoFilteredImportVPN(
2384 it
, FIF_ACTION_KILL
, bpi_interior
->peer
, NULL
, /* rfd */
2385 pfx_exterior
, NULL
, afi
, prd
, bpi_interior
->attr
,
2386 ZEBRA_ROUTE_BGP_DIRECT_EXT
, BGP_ROUTE_REDISTRIBUTE
,
2391 * If there are no remaining valid interior routes at this prefix,
2392 * we need to look up the tree for a possible node to move monitors to
2394 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
) {
2395 vnc_zlog_debug_verbose(
2396 "%s: interior routes still present, skipping",
2402 * Find nearest parent with at least one valid interior route
2403 * If none is found, par will end up NULL, and we will move
2404 * the monitors to the orphan list for this import table
2406 for (par
= agg_node_parent(rn_interior
); par
;
2407 par
= agg_node_parent(par
)) {
2408 if (RFAPI_MONITOR_EXTERIOR(par
)->valid_interior_count
)
2412 vnc_zlog_debug_verbose("%s: par=%p, ext src: %p", __func__
, par
,
2413 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2415 /* move all monitors */
2417 * We will use and delete every element of the source skiplist
2419 while (!skiplist_first(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2420 (void **)&bpi_exterior
,
2421 (void **)&pfx_exterior
)) {
2423 struct prefix
*pfx_mon
= prefix_new();
2425 prefix_copy(pfx_mon
, pfx_exterior
);
2429 struct bgp_path_info
*bpi
;
2432 * Add monitor to parent node
2434 if (!RFAPI_MONITOR_EXTERIOR(par
)->source
) {
2435 RFAPI_MONITOR_EXTERIOR(par
)->source
=
2437 0, NULL
, prefix_free_lists
);
2438 agg_lock_node(par
); /* sl */
2440 skiplist_insert(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2441 bpi_exterior
, pfx_mon
);
2442 agg_lock_node(par
); /* sl entry */
2444 /* Add constructed exterior routes based on parent */
2445 for (bpi
= par
->info
; bpi
; bpi
= bpi
->next
) {
2447 struct prefix_rd
*prd
;
2448 struct attr new_attr
;
2451 if (bpi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
)
2455 prd
= &bpi
->extra
->vnc
.import
.rd
;
2456 label
= decode_label(
2457 &bpi
->extra
->label
[0]);
2461 /* use local_pref from unicast route */
2462 memset(&new_attr
, 0, sizeof(new_attr
));
2463 new_attr
= *bpi
->attr
;
2465 && (bpi_exterior
->attr
->flag
2466 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2467 new_attr
.local_pref
=
2468 bpi_exterior
->attr
->local_pref
;
2469 new_attr
.flag
|= ATTR_FLAG_BIT(
2470 BGP_ATTR_LOCAL_PREF
);
2473 rfapiBgpInfoFilteredImportVPN(
2474 it
, FIF_ACTION_UPDATE
, bpi
->peer
,
2476 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2477 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2478 BGP_ROUTE_REDISTRIBUTE
, &label
);
2484 * No interior route for exterior's nexthop. Save
2486 * in orphan list to await future route.
2488 skiplist_insert(it
->monitor_exterior_orphans
,
2489 bpi_exterior
, pfx_mon
);
2492 skiplist_delete_first(
2493 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2494 agg_unlock_node(rn_interior
); /* sl entry */
2496 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
)) {
2497 skiplist_free(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2498 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
= NULL
;
2499 agg_unlock_node(rn_interior
); /* sl itself */
2503 /***********************************************************************
2504 * Generic add/delete unicast routes
2505 ***********************************************************************/
2507 void vnc_import_bgp_add_route(struct bgp
*bgp
, const struct prefix
*prefix
,
2508 struct bgp_path_info
*info
)
2510 afi_t afi
= family2afi(prefix
->family
);
2512 if (VNC_DEBUG(VERBOSE
)) {
2513 struct prefix pfx_nexthop
;
2515 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2516 vnc_zlog_debug_verbose("%s: pfx %pFX, nh %pFX", __func__
,
2517 prefix
, &pfx_nexthop
);
2520 print_rhn_list(__func__
, "ENTER ");
2525 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
2530 if (!bgp
->rfapi_cfg
) {
2531 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2536 /* check vnc redist flag for bgp direct routes */
2537 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2538 vnc_zlog_debug_verbose(
2539 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
2540 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2544 switch (bgp
->rfapi_cfg
->redist_mode
) {
2545 case VNC_REDIST_MODE_PLAIN
:
2546 vnc_import_bgp_add_route_mode_plain(bgp
, prefix
, info
);
2549 case VNC_REDIST_MODE_RFG
:
2550 if (bgp
->rfapi_cfg
->rfg_redist
)
2551 vnc_import_bgp_add_route_mode_nvegroup(
2552 bgp
, prefix
, info
, bgp
->rfapi_cfg
->rfg_redist
);
2554 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2558 case VNC_REDIST_MODE_RESOLVE_NVE
:
2559 vnc_import_bgp_add_route_mode_resolve_nve(bgp
, prefix
, info
);
2563 print_rhn_list(__func__
, "LEAVE ");
2569 * "Withdrawing a Route" import process
2571 void vnc_import_bgp_del_route(struct bgp
*bgp
, const struct prefix
*prefix
,
2572 struct bgp_path_info
*info
) /* unicast info */
2574 afi_t afi
= family2afi(prefix
->family
);
2579 struct prefix pfx_nexthop
;
2581 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2582 vnc_zlog_debug_verbose("%s: pfx %pFX, nh %pFX", __func__
,
2583 prefix
, &pfx_nexthop
);
2586 print_rhn_list(__func__
, "ENTER ");
2590 if (!bgp
->rfapi_cfg
) {
2591 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2596 /* check bgp redist flag for vnc direct ("vpn") routes */
2597 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2598 vnc_zlog_debug_verbose(
2599 "%s: bgp redistribution of afi=%d VNC direct routes is off",
2604 switch (bgp
->rfapi_cfg
->redist_mode
) {
2605 case VNC_REDIST_MODE_PLAIN
:
2606 vnc_import_bgp_del_route_mode_plain(bgp
, prefix
, info
);
2609 case VNC_REDIST_MODE_RFG
:
2610 if (bgp
->rfapi_cfg
->rfg_redist
)
2611 vnc_import_bgp_del_route_mode_nvegroup(bgp
, prefix
,
2614 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2618 case VNC_REDIST_MODE_RESOLVE_NVE
:
2619 vnc_import_bgp_del_route_mode_resolve_nve(bgp
, afi
, prefix
,
2624 print_rhn_list(__func__
, "LEAVE ");
2630 /***********************************************************************
2632 ***********************************************************************/
2634 void vnc_import_bgp_redist_enable(struct bgp
*bgp
, afi_t afi
)
2636 /* iterate over bgp unicast v4 and v6 routes, call
2637 * vnc_import_bgp_add_route */
2639 struct bgp_dest
*dest
;
2641 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
2643 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2644 vnc_zlog_debug_verbose(
2645 "%s: already enabled for afi %d, skipping", __func__
,
2649 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 1;
2651 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); dest
;
2652 dest
= bgp_route_next(dest
)) {
2654 struct bgp_path_info
*bpi
;
2656 for (bpi
= bgp_dest_get_bgp_path_info(dest
); bpi
;
2659 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2662 vnc_import_bgp_add_route(bgp
, bgp_dest_get_prefix(dest
),
2666 vnc_zlog_debug_verbose(
2667 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2668 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2671 void vnc_import_bgp_exterior_redist_enable(struct bgp
*bgp
, afi_t afi
)
2673 struct bgp
*bgp_exterior
;
2674 struct bgp_dest
*dest
;
2676 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2678 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2679 vnc_zlog_debug_verbose(
2680 "%s: already enabled for afi %d, skipping", __func__
,
2684 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 1;
2686 if (!bgp_exterior
) {
2687 vnc_zlog_debug_verbose(
2688 "%s: no exterior view set yet, no routes to import yet",
2693 for (dest
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); dest
;
2694 dest
= bgp_route_next(dest
)) {
2696 struct bgp_path_info
*bpi
;
2698 for (bpi
= bgp_dest_get_bgp_path_info(dest
); bpi
;
2701 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2704 vnc_import_bgp_exterior_add_route(
2705 bgp_exterior
, bgp_dest_get_prefix(dest
), bpi
);
2708 vnc_zlog_debug_verbose(
2709 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2710 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2714 * This function is for populating a newly-created Import Table
2716 void vnc_import_bgp_exterior_redist_enable_it(
2717 struct bgp
*bgp
, afi_t afi
, struct rfapi_import_table
*it_only
)
2719 struct bgp
*bgp_exterior
;
2720 struct bgp_dest
*dest
;
2722 vnc_zlog_debug_verbose("%s: entry", __func__
);
2724 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2726 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2727 vnc_zlog_debug_verbose("%s: not enabled for afi %d, skipping",
2732 if (!bgp_exterior
) {
2733 vnc_zlog_debug_verbose(
2734 "%s: no exterior view set yet, no routes to import yet",
2739 for (dest
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); dest
;
2740 dest
= bgp_route_next(dest
)) {
2742 struct bgp_path_info
*bpi
;
2744 for (bpi
= bgp_dest_get_bgp_path_info(dest
); bpi
;
2747 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2750 vnc_import_bgp_exterior_add_route_it(
2751 bgp_exterior
, bgp_dest_get_prefix(dest
), bpi
,
2758 void vnc_import_bgp_redist_disable(struct bgp
*bgp
, afi_t afi
)
2761 * iterate over vpn routes, find routes of type ZEBRA_ROUTE_BGP_DIRECT,
2762 * delete (call timer expire immediately)
2764 struct bgp_dest
*dest1
;
2765 struct bgp_dest
*dest2
;
2767 vnc_zlog_debug_verbose("%s: entry", __func__
);
2769 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2770 vnc_zlog_debug_verbose(
2771 "%s: already disabled for afi %d, skipping", __func__
,
2777 * Two-level table for SAFI_MPLS_VPN
2778 * Be careful when changing the things we iterate over
2780 for (dest1
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); dest1
;
2781 dest1
= bgp_route_next(dest1
)) {
2782 const struct prefix
*dest1_p
;
2784 if (!bgp_dest_has_bgp_path_info_data(dest1
))
2787 dest1_p
= bgp_dest_get_prefix(dest1
);
2788 for (dest2
= bgp_table_top(bgp_dest_get_bgp_table_info(dest1
));
2789 dest2
; dest2
= bgp_route_next(dest2
)) {
2790 const struct prefix
*dest2_p
=
2791 bgp_dest_get_prefix(dest2
);
2792 struct bgp_path_info
*bpi
;
2793 struct bgp_path_info
*nextbpi
;
2795 for (bpi
= bgp_dest_get_bgp_path_info(dest2
); bpi
;
2798 nextbpi
= bpi
->next
;
2800 if (bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
)
2803 struct rfapi_descriptor
*rfd
;
2804 vncHDBgpDirect
.peer
= bpi
->peer
;
2808 rfd
= bpi
->extra
->vnc
.export
.rfapi_handle
;
2810 vnc_zlog_debug_verbose(
2811 "%s: deleting bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]",
2812 __func__
, bpi
, bpi
->peer
, bpi
->type
,
2814 (bpi
->extra
? bpi
->extra
->vnc
.export
2819 del_vnc_route(rfd
, bpi
->peer
, bgp
,
2820 SAFI_MPLS_VPN
, dest2_p
,
2821 (struct prefix_rd
*)dest1_p
,
2822 bpi
->type
, bpi
->sub_type
, NULL
,
2825 vncHDBgpDirect
.peer
= NULL
;
2829 /* Clear RHN list */
2830 if (bgp
->rfapi
->resolve_nve_nexthop
) {
2831 struct prefix_bag
*pb
;
2832 struct bgp_path_info
*info
;
2833 while (!skiplist_first(bgp
->rfapi
->resolve_nve_nexthop
, NULL
,
2836 skiplist_delete_first(bgp
->rfapi
->resolve_nve_nexthop
);
2837 bgp_path_info_unlock(info
);
2841 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 0;
2842 vnc_zlog_debug_verbose("%s: return", __func__
);
2846 void vnc_import_bgp_exterior_redist_disable(struct bgp
*bgp
, afi_t afi
)
2848 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
2849 struct bgp
*bgp_exterior
= hc
->redist_bgp_exterior_view
;
2851 vnc_zlog_debug_verbose("%s: entry", __func__
);
2853 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2854 vnc_zlog_debug_verbose(
2855 "%s: already disabled for afi %d, skipping", __func__
,
2860 if (!bgp_exterior
) {
2861 vnc_zlog_debug_verbose(
2862 "%s: bgp exterior view not defined, skipping",
2869 struct bgp_dest
*dest
;
2870 for (dest
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]);
2871 dest
; dest
= bgp_route_next(dest
)) {
2873 struct bgp_path_info
*bpi
;
2875 for (bpi
= bgp_dest_get_bgp_path_info(dest
); bpi
;
2878 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2881 vnc_import_bgp_exterior_del_route(
2882 bgp_exterior
, bgp_dest_get_prefix(dest
),
2887 print_rhn_list(__func__
, NULL
);
2891 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 0;
2892 vnc_zlog_debug_verbose("%s: return", __func__
);