3 * Copyright 2009-2016, LabN Consulting, L.L.C.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 * File: vnc_import_bgp.c
23 * Purpose: Import routes from BGP unicast directly (not via zebra)
26 #include "lib/zebra.h"
27 #include "lib/prefix.h"
28 #include "lib/agg_table.h"
31 #include "lib/memory.h"
32 #include "lib/linklist.h"
33 #include "lib/plist.h"
34 #include "lib/routemap.h"
35 #include "lib/lib_errors.h"
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_ecommunity.h"
39 #include "bgpd/bgp_attr.h"
40 #include "bgpd/bgp_route.h"
41 #include "bgpd/bgp_mplsvpn.h" /* for RD_TYPE_IP */
43 #include "bgpd/rfapi/vnc_export_bgp.h"
44 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
45 #include "bgpd/rfapi/rfapi.h"
46 #include "bgpd/rfapi/rfapi_import.h"
47 #include "bgpd/rfapi/rfapi_private.h"
48 #include "bgpd/rfapi/rfapi_monitor.h"
49 #include "bgpd/rfapi/rfapi_vty.h"
50 #include "bgpd/rfapi/vnc_import_bgp.h"
51 #include "bgpd/rfapi/vnc_import_bgp_p.h"
52 #include "bgpd/rfapi/vnc_debug.h"
54 #define ENABLE_VNC_RHNCK
56 #define DEBUG_RHN_LIST 0
58 static struct rfapi_descriptor vncHDBgpDirect
; /* dummy nve descriptor */
59 static struct rfapi_descriptor vncHDResolveNve
; /* dummy nve descriptor */
62 * For routes from another AS:
65 * LOCAL_PREF = 255 - MIN(255, MED)
67 * LOCAL_PREF = default_local_pref
69 * For routes from the same AS:
71 * LOCAL_PREF unchanged
73 uint32_t calc_local_pref(struct attr
*attr
, struct peer
*peer
)
75 uint32_t local_pref
= 0;
79 return peer
->bgp
->default_local_pref
;
81 return bgp_get_default()->default_local_pref
;
84 if (peer
&& (peer
->as
!= peer
->bgp
->as
)) {
85 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
86 if (attr
->med
> 255) {
89 local_pref
= 255 - attr
->med
;
92 local_pref
= peer
->bgp
->default_local_pref
;
95 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
96 local_pref
= attr
->local_pref
;
98 if (peer
&& peer
->bgp
) {
99 local_pref
= peer
->bgp
->default_local_pref
;
107 static int is_host_prefix(const struct prefix
*p
)
111 return (p
->prefixlen
== 32);
113 return (p
->prefixlen
== 128);
118 /***********************************************************************
120 ***********************************************************************/
123 struct prefix hpfx
; /* ce address = unicast nexthop */
124 struct prefix upfx
; /* unicast prefix */
125 struct bgp_path_info
*ubpi
; /* unicast route */
128 static const uint8_t maskbit
[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
129 0xf8, 0xfc, 0xfe, 0xff};
131 int vnc_prefix_cmp(const void *pfx1
, const void *pfx2
)
137 const struct prefix
*p1
= pfx1
;
138 const struct prefix
*p2
= pfx2
;
140 if (p1
->family
< p2
->family
)
142 if (p1
->family
> p2
->family
)
145 if (p1
->prefixlen
< p2
->prefixlen
)
147 if (p1
->prefixlen
> p2
->prefixlen
)
150 offset
= p1
->prefixlen
/ 8;
151 shift
= p1
->prefixlen
% 8;
152 if (shift
== 0 && offset
) { /* catch aligned case */
157 /* Set both prefix's head pointer. */
158 const uint8_t *pp1
= (const uint8_t *)&p1
->u
.prefix
;
159 const uint8_t *pp2
= (const uint8_t *)&p2
->u
.prefix
;
170 mask
= maskbit
[shift
];
171 if ((*pp1
& mask
) < (*pp2
& mask
))
173 if ((*pp1
& mask
) > (*pp2
& mask
))
179 static void prefix_bag_free(void *pb
)
181 XFREE(MTYPE_RFAPI_PREFIX_BAG
, pb
);
185 static void print_rhn_list(const char *tag1
, const char *tag2
)
189 struct skiplistnode
*p
;
190 struct prefix_bag
*pb
;
193 bgp
= bgp_get_default();
197 sl
= bgp
->frapi
->resolve_nve_nexthop
;
199 vnc_zlog_debug_verbose("%s: %s: RHN List is empty",
200 (tag1
? tag1
: ""), (tag2
? tag2
: ""));
204 vnc_zlog_debug_verbose("%s: %s: RHN list:", (tag1
? tag1
: ""),
207 /* XXX uses secret knowledge of skiplist structure */
208 for (p
= sl
->header
->forward
[0]; p
; p
= p
->forward
[0]) {
209 char kbuf
[PREFIX_STRLEN
];
210 char hbuf
[PREFIX_STRLEN
];
211 char ubuf
[PREFIX_STRLEN
];
215 prefix2str(p
->key
, kbuf
, sizeof(kbuf
));
216 prefix2str(&pb
->hpfx
, hbuf
, sizeof(hbuf
));
217 prefix2str(&pb
->upfx
, ubuf
, sizeof(ubuf
));
219 vnc_zlog_debug_verbose(
220 "RHN Entry %d (q=%p): kpfx=%s, upfx=%s, hpfx=%s, ubpi=%p",
221 ++count
, p
, kbuf
, ubuf
, hbuf
, pb
->ubpi
);
226 #ifdef ENABLE_VNC_RHNCK
227 static void vnc_rhnck(char *tag
)
231 struct skiplistnode
*p
;
233 bgp
= bgp_get_default();
236 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
241 /* XXX uses secret knowledge of skiplist structure */
242 for (p
= sl
->header
->forward
[0]; p
; p
= p
->forward
[0]) {
243 struct prefix_bag
*pb
;
246 struct prefix pfx_orig_nexthop
;
248 memset(&pfx_orig_nexthop
, 0,
249 sizeof(struct prefix
)); /* keep valgrind happy */
254 afi
= family2afi(pb
->upfx
.family
);
256 rfapiUnicastNexthop2Prefix(afi
, pb
->ubpi
->attr
,
259 /* pb->hpfx, pb->ubpi nexthop, pkey should all reflect the same
261 assert(!vnc_prefix_cmp(&pb
->hpfx
, pkey
));
262 if (vnc_prefix_cmp(&pb
->hpfx
, &pfx_orig_nexthop
)) {
263 char str_onh
[PREFIX_STRLEN
];
264 char str_nve_pfx
[PREFIX_STRLEN
];
266 prefix2str(&pfx_orig_nexthop
, str_onh
, sizeof(str_onh
));
267 prefix2str(&pb
->hpfx
, str_nve_pfx
, sizeof(str_nve_pfx
));
269 vnc_zlog_debug_verbose(
270 "%s: %s: FATAL: resolve_nve_nexthop list item bpi nexthop %s != nve pfx %s",
271 __func__
, tag
, str_onh
, str_nve_pfx
);
275 vnc_zlog_debug_verbose("%s: vnc_rhnck OK", tag
);
278 #define VNC_RHNCK(n) \
281 snprintf(buf, sizeof(buf), "%s: %s", __func__, #n); \
291 /***********************************************************************
292 * Add/Delete Unicast Route
293 ***********************************************************************/
296 * "Adding a Route" import process
300 * extract and package information from the BGP unicast route.
301 * Return code 0 means OK, non-0 means drop.
303 * If return code is 0, caller MUST release ecom
305 static int process_unicast_route(struct bgp
*bgp
, /* in */
307 const struct prefix
*prefix
, /* in */
308 struct bgp_path_info
*info
, /* in */
309 struct ecommunity
**ecom
, /* OUT */
310 struct prefix
*unicast_nexthop
) /* OUT */
312 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
313 struct peer
*peer
= info
->peer
;
314 struct attr
*attr
= info
->attr
;
316 struct route_map
*rmap
= NULL
;
317 struct prefix pfx_orig_nexthop
;
319 memset(&pfx_orig_nexthop
, 0,
320 sizeof(struct prefix
)); /* keep valgrind happy */
325 if (hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
326 vnc_zlog_debug_verbose("%s: HC prefix list is set, checking",
328 if (prefix_list_apply(
329 hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
],
332 vnc_zlog_debug_verbose(
333 "%s: prefix list returns DENY, blocking route",
337 vnc_zlog_debug_verbose(
338 "%s: prefix list returns PASS, allowing route",
342 /* apply routemap, if any, later */
343 rmap
= hc
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
346 * Extract original nexthop, which we expect to be a NVE connected
348 * Note that this is the nexthop before any possible application of
352 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
353 * but if v4 it is in attr->nexthop
355 rfapiUnicastNexthop2Prefix(afi
, attr
, &pfx_orig_nexthop
);
359 * This code is here because it allocates an interned attr which
360 * must be freed before we return. It's easier to put it after
361 * all of the possible returns above.
363 memset(&hattr
, 0, sizeof(struct attr
));
364 /* hattr becomes a ghost attr */
368 struct bgp_path_info info
;
369 route_map_result_t ret
;
371 memset(&info
, 0, sizeof(info
));
374 ret
= route_map_apply(rmap
, prefix
, RMAP_BGP
, &info
);
375 if (ret
== RMAP_DENYMATCH
) {
376 bgp_attr_flush(&hattr
);
377 vnc_zlog_debug_verbose(
378 "%s: route map \"%s\" says DENY, returning",
379 __func__
, rmap
->name
);
385 * Get the (possibly altered by policy) unicast nexthop
386 * for later lookup in the Import Table by caller
388 rfapiUnicastNexthop2Prefix(afi
, &hattr
, unicast_nexthop
);
390 if (hattr
.ecommunity
)
391 *ecom
= ecommunity_dup(hattr
.ecommunity
);
393 *ecom
= ecommunity_new();
396 * Done with hattr, clean up
398 bgp_attr_flush(&hattr
);
401 * Add EC that carries original NH of iBGP route (2 bytes = magic
402 * value indicating it came from an VNC gateway; default 5226, but
403 * must be user configurable). Note that this is the nexthop before
404 * any application of policy.
407 struct ecommunity_val vnc_gateway_magic
;
410 /* Using route origin extended community type */
411 memset(&vnc_gateway_magic
, 0, sizeof(vnc_gateway_magic
));
412 vnc_gateway_magic
.val
[0] = 0x01;
413 vnc_gateway_magic
.val
[1] = 0x03;
415 /* Only works for IPv4 nexthops */
416 if (prefix
->family
== AF_INET
) {
417 memcpy(vnc_gateway_magic
.val
+ 2,
418 &unicast_nexthop
->u
.prefix4
, 4);
420 localadmin
= htons(hc
->resolve_nve_roo_local_admin
);
421 memcpy(vnc_gateway_magic
.val
+ 6, (char *)&localadmin
, 2);
423 ecommunity_add_val(*ecom
, &vnc_gateway_magic
, false, false);
430 static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
431 struct bgp
*bgp
, afi_t afi
, struct bgp_path_info
*bpi
, /* VPN bpi */
432 struct prefix_rd
*prd
, /* RD */
433 const struct prefix
*prefix
, /* unicast route prefix */
434 uint32_t *local_pref
, /* NULL = no local_pref */
435 uint32_t *med
, /* NULL = no med */
436 struct ecommunity
*ecom
) /* generated ecoms */
439 struct prefix nexthop
;
440 struct rfapi_ip_addr nexthop_h
;
443 struct bgp_attr_encap_subtlv
*encaptlvs
;
446 struct rfapi_un_option optary
[3];
447 struct rfapi_un_option
*opt
= NULL
;
450 vnc_zlog_debug_verbose("%s: entry", __func__
);
452 if (bpi
->type
!= ZEBRA_ROUTE_BGP
453 && bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
) {
457 if (bpi
->sub_type
!= BGP_ROUTE_NORMAL
458 && bpi
->sub_type
!= BGP_ROUTE_STATIC
459 && bpi
->sub_type
!= BGP_ROUTE_RFP
) {
463 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
466 vncHDResolveNve
.peer
= bpi
->peer
;
467 if (!rfapiGetVncTunnelUnAddr(bpi
->attr
, &un
)) {
468 if (rfapiQprefix2Raddr(&un
, &vncHDResolveNve
.un_addr
))
471 memset(&vncHDResolveNve
.un_addr
, 0,
472 sizeof(vncHDResolveNve
.un_addr
));
475 /* Use nexthop of VPN route as nexthop of constructed route */
476 rfapiNexthop2Prefix(bpi
->attr
, &nexthop
);
477 rfapiQprefix2Raddr(&nexthop
, &nexthop_h
);
479 if (rfapiGetVncLifetime(bpi
->attr
, &lifetime
)) {
482 plifetime
= &lifetime
;
485 encaptlvs
= bpi
->attr
->vnc_subtlvs
;
486 if (bpi
->attr
->encap_tunneltype
!= BGP_ENCAP_TYPE_RESERVED
487 && bpi
->attr
->encap_tunneltype
!= BGP_ENCAP_TYPE_MPLS
) {
488 opt
= &optary
[cur_opt
++];
489 memset(opt
, 0, sizeof(struct rfapi_un_option
));
490 opt
->type
= RFAPI_UN_OPTION_TYPE_TUNNELTYPE
;
491 opt
->v
.tunnel
.type
= bpi
->attr
->encap_tunneltype
;
492 /* TBD parse bpi->attr->extra->encap_subtlvs */
495 struct ecommunity
*new_ecom
= ecommunity_dup(ecom
);
497 if (bpi
->attr
->ecommunity
)
498 ecommunity_merge(new_ecom
, bpi
->attr
->ecommunity
);
501 label
= decode_label(&bpi
->extra
->label
[0]);
503 add_vnc_route(&vncHDResolveNve
, bgp
, SAFI_MPLS_VPN
,
504 prefix
, /* unicast route prefix */
505 prd
, &nexthop_h
, /* new nexthop */
506 local_pref
, plifetime
,
507 (struct bgp_tea_options
*)encaptlvs
, /* RFP options */
508 opt
, NULL
, new_ecom
, med
, /* NULL => don't set med */
509 (label
? &label
: NULL
), /* NULL= default */
510 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
511 RFAPI_AHR_RFPOPT_IS_VNCTLV
); /* flags */
513 ecommunity_free(&new_ecom
);
516 static void vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
517 struct prefix_rd
*prd
, /* RD */
518 struct bgp_table
*table_rd
, /* per-rd VPN route table */
519 afi_t afi
, struct bgp
*bgp
,
520 const struct prefix
*prefix
, /* unicast prefix */
521 struct ecommunity
*ecom
, /* generated ecoms */
522 uint32_t *local_pref
, /* NULL = no local_pref */
523 uint32_t *med
, /* NULL = no med */
524 struct prefix
*ubpi_nexthop
) /* unicast nexthop */
527 struct bgp_path_info
*bpi
;
533 char str_nh
[PREFIX_STRLEN
];
535 prefix2str(ubpi_nexthop
, str_nh
, sizeof(str_nh
));
537 vnc_zlog_debug_verbose("%s: ubpi_nexthop=%s", __func__
, str_nh
);
541 bn
= bgp_node_lookup(table_rd
, ubpi_nexthop
);
543 vnc_zlog_debug_verbose(
544 "%s: no match in RD's table for ubpi_nexthop",
549 /* Iterate over bgp_info items at this node */
550 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
) {
552 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
553 bgp
, afi
, bpi
, /* VPN bpi */
554 prd
, prefix
, local_pref
, med
, ecom
);
560 static void vnc_import_bgp_add_route_mode_resolve_nve(
561 struct bgp
*bgp
, const struct prefix
*prefix
, /* unicast prefix */
562 struct bgp_path_info
*info
) /* unicast info */
564 afi_t afi
= family2afi(prefix
->family
);
566 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
568 struct ecommunity
*ecom
= NULL
;
570 uint32_t *med
= NULL
;
572 struct prefix_bag
*pb
;
573 struct bgp_node
*bnp
; /* prd table node */
576 if (VNC_DEBUG(VERBOSE
)) {
577 char str_pfx
[PREFIX_STRLEN
];
578 char str_nh
[PREFIX_STRLEN
];
581 prefix2str(prefix
, str_pfx
, sizeof(str_pfx
));
584 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &nh
);
586 prefix2str(&nh
, str_nh
, sizeof(str_nh
));
592 vnc_zlog_debug_verbose(
593 "%s(bgp=%p, unicast prefix=%s, unicast nh=%s)",
594 __func__
, bgp
, str_pfx
, str_nh
);
597 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
598 vnc_zlog_debug_verbose(
599 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
600 __func__
, info
->type
, zebra_route_string(info
->type
),
601 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
610 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
615 if (!(bgp
->rfapi_cfg
)) {
616 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
621 /* check vnc redist flag for bgp direct routes */
622 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
623 vnc_zlog_debug_verbose(
624 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
630 if (process_unicast_route(bgp
, afi
, prefix
, info
, &ecom
,
631 &pfx_unicast_nexthop
)) {
633 vnc_zlog_debug_verbose(
634 "%s: process_unicast_route error, skipping", __func__
);
638 local_pref
= calc_local_pref(info
->attr
, info
->peer
);
639 if (info
->attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
640 med
= &info
->attr
->med
;
643 * At this point, we have allocated:
645 * ecom ecommunity ptr, union of unicast and ROO parts (no NVE part)
649 * pfx_unicast_nexthop nexthop of uncast route
652 if (!bgp
->rfapi
->resolve_nve_nexthop
) {
653 bgp
->rfapi
->resolve_nve_nexthop
=
654 skiplist_new(SKIPLIST_FLAG_ALLOW_DUPLICATES
,
655 vnc_prefix_cmp
, prefix_bag_free
);
658 pb
= XCALLOC(MTYPE_RFAPI_PREFIX_BAG
, sizeof(struct prefix_bag
));
659 pb
->hpfx
= pfx_unicast_nexthop
;
663 bgp_path_info_lock(info
); /* skiplist refers to it */
664 skiplist_insert(bgp
->rfapi
->resolve_nve_nexthop
, &pb
->hpfx
, pb
);
667 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
668 * (exact match, /32). If an exact match is found, call add_vnc_route.
671 for (bnp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bnp
;
672 bnp
= bgp_route_next(bnp
)) {
674 struct bgp_table
*table
;
676 table
= bgp_node_get_bgp_table_info(bnp
);
681 vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
682 (struct prefix_rd
*)bgp_node_get_prefix(bnp
), table
,
683 afi
, bgp
, prefix
, ecom
, &local_pref
, med
,
684 &pfx_unicast_nexthop
);
689 ecommunity_free(&ecom
);
691 vnc_zlog_debug_verbose("%s: done", __func__
);
695 static void vnc_import_bgp_add_route_mode_plain(struct bgp
*bgp
,
696 const struct prefix
*prefix
,
697 struct bgp_path_info
*info
)
699 afi_t afi
= family2afi(prefix
->family
);
700 struct peer
*peer
= info
->peer
;
701 struct attr
*attr
= info
->attr
;
703 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
704 struct attr
*iattr
= NULL
;
706 struct rfapi_ip_addr vnaddr
;
707 struct prefix vn_pfx_space
;
708 struct prefix
*vn_pfx
= NULL
;
710 struct ecommunity
*ecom
= NULL
;
711 struct prefix_rd prd
;
712 struct route_map
*rmap
= NULL
;
714 uint32_t *med
= NULL
;
717 char buf
[PREFIX_STRLEN
];
719 prefix2str(prefix
, buf
, sizeof(buf
));
720 vnc_zlog_debug_verbose("%s(prefix=%s) entry", __func__
, buf
);
724 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
730 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
735 /* check vnc redist flag for bgp direct routes */
736 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
737 vnc_zlog_debug_verbose(
738 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
744 * mode "plain" specific code
747 vnc_zlog_debug_verbose("%s: NOT using redist RFG", __func__
);
752 if (hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
753 vnc_zlog_debug_verbose(
754 "%s: HC prefix list is set, checking",
756 if (prefix_list_apply(
757 hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
761 vnc_zlog_debug_verbose(
762 "%s: prefix list returns DENY, blocking route",
766 vnc_zlog_debug_verbose(
767 "%s: prefix list returns PASS, allowing route",
771 /* apply routemap, if any, later */
772 rmap
= hc
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
775 * Incoming prefix is unicast. If v6, it is in multiprotocol
777 * but if v4 it is in attr->nexthop
779 rfapiUnicastNexthop2Prefix(afi
, attr
, &vn_pfx_space
);
780 vn_pfx
= &vn_pfx_space
;
783 ahr_flags
|= RFAPI_AHR_NO_TUNNEL_SUBTLV
;
786 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
787 char buf
[PREFIX_STRLEN
];
789 prefix2str(vn_pfx
, buf
, sizeof(buf
));
790 vnc_zlog_debug_any("%s vn_pfx=%s", __func__
, buf
);
796 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
797 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
804 * This code is here because it allocates an interned attr which
805 * must be freed before we return. It's easier to put it after
806 * all of the possible returns above.
808 memset(&hattr
, 0, sizeof(struct attr
));
809 /* hattr becomes a ghost attr */
813 struct bgp_path_info info
;
814 route_map_result_t ret
;
816 memset(&info
, 0, sizeof(info
));
819 ret
= route_map_apply(rmap
, prefix
, RMAP_BGP
, &info
);
820 if (ret
== RMAP_DENYMATCH
) {
821 bgp_attr_flush(&hattr
);
822 vnc_zlog_debug_verbose(
823 "%s: route map \"%s\" says DENY, returning",
824 __func__
, rmap
->name
);
829 iattr
= bgp_attr_intern(&hattr
);
830 bgp_attr_flush(&hattr
);
832 /* Now iattr is an allocated interned attr */
835 * Mode "plain" specific code
837 * Sets RD in dummy HD
841 if (vnaddr
.addr_family
!= AF_INET
) {
842 vnc_zlog_debug_verbose(
843 "%s: can't auto-assign RD, VN AF (%d) is not IPv4, skipping",
844 __func__
, vnaddr
.addr_family
);
846 bgp_attr_unintern(&iattr
);
850 memset(&prd
, 0, sizeof(prd
));
851 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
853 if (iattr
&& iattr
->ecommunity
)
854 ecom
= ecommunity_dup(iattr
->ecommunity
);
857 local_pref
= calc_local_pref(iattr
, peer
);
859 if (iattr
&& (iattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))) {
863 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
864 char buf
[PREFIX_STRLEN
];
866 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, sizeof(buf
));
867 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
870 vncHDBgpDirect
.peer
= peer
;
871 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
872 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
873 NULL
, /* RFP options */
874 NULL
, NULL
, ecom
, med
, /* med */
875 NULL
, /* label: default */
876 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
878 vncHDBgpDirect
.peer
= NULL
;
881 ecommunity_free(&ecom
);
884 static void vnc_import_bgp_add_route_mode_nvegroup(
885 struct bgp
*bgp
, const struct prefix
*prefix
,
886 struct bgp_path_info
*info
, struct rfapi_nve_group_cfg
*rfg
)
888 afi_t afi
= family2afi(prefix
->family
);
889 struct peer
*peer
= info
->peer
;
890 struct attr
*attr
= info
->attr
;
892 struct attr
*iattr
= NULL
;
894 struct rfapi_ip_addr vnaddr
;
895 struct prefix
*vn_pfx
= NULL
;
897 struct ecommunity
*ecom
= NULL
;
898 struct prefix_rd prd
;
899 struct route_map
*rmap
= NULL
;
903 char buf
[PREFIX_STRLEN
];
905 prefix2str(prefix
, buf
, sizeof(buf
));
906 vnc_zlog_debug_verbose("%s(prefix=%s) entry", __func__
, buf
);
912 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
917 if (!(bgp
->rfapi_cfg
)) {
918 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
923 /* check vnc redist flag for bgp direct routes */
924 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
925 vnc_zlog_debug_verbose(
926 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
937 struct rfapi_ip_prefix pfx_un
;
939 vnc_zlog_debug_verbose("%s: using redist RFG", __func__
);
942 * RFG prefix list check
944 if (rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
945 vnc_zlog_debug_verbose(
946 "%s: RFG prefix list is set, checking",
948 if (prefix_list_apply(
949 rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
953 vnc_zlog_debug_verbose(
954 "%s: prefix list returns DENY, blocking route",
958 vnc_zlog_debug_verbose(
959 "%s: prefix list returns PASS, allowing route",
963 /* apply routemap, if any, later */
964 rmap
= rfg
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
967 * export nve group's VN addr prefix must be a /32 which
968 * will yield the VN addr to use
970 vn_pfx
= &rfg
->vn_prefix
;
975 if (!is_host_prefix(&rfg
->un_prefix
)) {
976 /* NB prefixlen==0 means it has not been configured */
977 vnc_zlog_debug_verbose(
978 "%s: redist RFG UN pfx not host pfx (plen=%d), skipping",
979 __func__
, rfg
->un_prefix
.prefixlen
);
983 rfapiQprefix2Rprefix(&rfg
->un_prefix
, &pfx_un
);
985 vncHDBgpDirect
.un_addr
= pfx_un
.prefix
;
988 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
989 char buf
[PREFIX_STRLEN
];
991 prefix2str(vn_pfx
, buf
, sizeof(buf
));
992 vnc_zlog_debug_any("%s vn_pfx=%s", __func__
, buf
);
998 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
999 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
1005 * route map handling
1006 * This code is here because it allocates an interned attr which
1007 * must be freed before we return. It's easier to put it after
1008 * all of the possible returns above.
1010 memset(&hattr
, 0, sizeof(struct attr
));
1011 /* hattr becomes a ghost attr */
1015 struct bgp_path_info path
;
1016 route_map_result_t ret
;
1018 memset(&path
, 0, sizeof(path
));
1021 ret
= route_map_apply(rmap
, prefix
, RMAP_BGP
, &path
);
1022 if (ret
== RMAP_DENYMATCH
) {
1023 bgp_attr_flush(&hattr
);
1024 vnc_zlog_debug_verbose(
1025 "%s: route map \"%s\" says DENY, returning",
1026 __func__
, rmap
->name
);
1031 iattr
= bgp_attr_intern(&hattr
);
1032 bgp_attr_flush(&hattr
);
1034 /* Now iattr is an allocated interned attr */
1039 * Sets RD in dummy HD
1044 memset(&prd
, 0, sizeof(prd
));
1046 prd
.family
= AF_UNSPEC
;
1049 if (rfg
->rd
.family
== AF_UNIX
) {
1050 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
1053 if (rfg
->rt_export_list
)
1054 ecom
= ecommunity_dup(
1055 bgp
->rfapi_cfg
->rfg_redist
->rt_export_list
);
1057 ecom
= ecommunity_new();
1059 if (iattr
&& iattr
->ecommunity
)
1060 ecom
= ecommunity_merge(ecom
, iattr
->ecommunity
);
1063 local_pref
= calc_local_pref(iattr
, peer
);
1065 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
1069 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, BUFSIZ
);
1070 buf
[BUFSIZ
- 1] = 0;
1071 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
1074 vncHDBgpDirect
.peer
= peer
;
1075 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
1076 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
1077 NULL
, /* RFP options */
1078 NULL
, NULL
, ecom
, NULL
, /* med */
1079 NULL
, /* label: default */
1080 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1082 vncHDBgpDirect
.peer
= NULL
;
1085 ecommunity_free(&ecom
);
1088 static void vnc_import_bgp_del_route_mode_plain(struct bgp
*bgp
,
1089 const struct prefix
*prefix
,
1090 struct bgp_path_info
*info
)
1092 struct prefix_rd prd
;
1093 afi_t afi
= family2afi(prefix
->family
);
1094 struct prefix
*vn_pfx
= NULL
;
1095 struct rfapi_ip_addr vnaddr
;
1096 struct prefix vn_pfx_space
;
1102 * Compute VN address
1106 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &vn_pfx_space
);
1108 vnc_zlog_debug_verbose("%s: no attr, can't delete route",
1112 vn_pfx
= &vn_pfx_space
;
1114 vnaddr
.addr_family
= vn_pfx
->family
;
1115 switch (vn_pfx
->family
) {
1117 if (vn_pfx
->prefixlen
!= 32) {
1118 vnc_zlog_debug_verbose(
1119 "%s: redist VN plen (%d) != 32, skipping",
1120 __func__
, vn_pfx
->prefixlen
);
1123 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1127 if (vn_pfx
->prefixlen
!= 128) {
1128 vnc_zlog_debug_verbose(
1129 "%s: redist VN plen (%d) != 128, skipping",
1130 __func__
, vn_pfx
->prefixlen
);
1133 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1137 vnc_zlog_debug_verbose(
1138 "%s: no redist RFG VN host pfx configured, skipping",
1144 memset(&prd
, 0, sizeof(prd
));
1145 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1146 vnc_zlog_debug_verbose("%s: can't auto-assign RD, skipping",
1151 vncHDBgpDirect
.peer
= info
->peer
;
1152 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1153 vncHDBgpDirect
.peer
);
1154 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1155 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1158 vncHDBgpDirect
.peer
= NULL
;
1161 static void vnc_import_bgp_del_route_mode_nvegroup(struct bgp
*bgp
,
1162 const struct prefix
*prefix
,
1163 struct bgp_path_info
*info
)
1165 struct prefix_rd prd
;
1166 afi_t afi
= family2afi(prefix
->family
);
1167 struct rfapi_nve_group_cfg
*rfg
= NULL
;
1168 struct prefix
*vn_pfx
= NULL
;
1169 struct rfapi_ip_addr vnaddr
;
1174 rfg
= bgp
->rfapi_cfg
->rfg_redist
;
1178 * Compute VN address
1182 * export nve group's VN addr prefix must be a /32 which
1183 * will yield the VN addr to use
1185 vn_pfx
= &rfg
->vn_prefix
;
1188 vnaddr
.addr_family
= vn_pfx
->family
;
1189 switch (vn_pfx
->family
) {
1191 if (vn_pfx
->prefixlen
!= 32) {
1192 vnc_zlog_debug_verbose(
1193 "%s: redist VN plen (%d) != 32, skipping",
1194 __func__
, vn_pfx
->prefixlen
);
1197 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1201 if (vn_pfx
->prefixlen
!= 128) {
1202 vnc_zlog_debug_verbose(
1203 "%s: redist VN plen (%d) != 128, skipping",
1204 __func__
, vn_pfx
->prefixlen
);
1207 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1211 vnc_zlog_debug_verbose(
1212 "%s: no redist RFG VN host pfx configured, skipping",
1217 memset(&prd
, 0, sizeof(prd
));
1219 prd
.family
= AF_UNSPEC
;
1222 if (rfg
->rd
.family
== AF_UNIX
) {
1223 /* means "auto" with VN addr */
1224 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1225 vnc_zlog_debug_verbose(
1226 "%s: can't auto-assign RD, skipping", __func__
);
1232 vncHDBgpDirect
.peer
= info
->peer
;
1233 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1234 vncHDBgpDirect
.peer
);
1235 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1236 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1239 vncHDBgpDirect
.peer
= NULL
;
1242 static void vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1243 struct bgp
*bgp
, afi_t afi
, struct bgp_path_info
*bpi
, /* VPN bpi */
1244 struct prefix_rd
*prd
, /* RD */
1245 const struct prefix
*prefix
) /* unicast route prefix */
1249 if (bpi
->type
!= ZEBRA_ROUTE_BGP
1250 && bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
) {
1254 if (bpi
->sub_type
!= BGP_ROUTE_NORMAL
1255 && bpi
->sub_type
!= BGP_ROUTE_STATIC
1256 && bpi
->sub_type
!= BGP_ROUTE_RFP
) {
1260 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
1263 vncHDResolveNve
.peer
= bpi
->peer
;
1264 if (!rfapiGetVncTunnelUnAddr(bpi
->attr
, &un
)) {
1265 if (rfapiQprefix2Raddr(&un
, &vncHDResolveNve
.un_addr
))
1268 memset(&vncHDResolveNve
.un_addr
, 0,
1269 sizeof(vncHDResolveNve
.un_addr
));
1272 del_vnc_route(&vncHDResolveNve
, vncHDResolveNve
.peer
, bgp
,
1273 SAFI_MPLS_VPN
, prefix
, /* unicast route prefix */
1274 prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
, NULL
,
1278 static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1279 struct prefix_rd
*prd
,
1280 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1281 afi_t afi
, struct bgp
*bgp
,
1282 const struct prefix
*prefix
, /* unicast prefix */
1283 const struct prefix
*ubpi_nexthop
) /* unicast bpi's nexthop */
1285 struct bgp_node
*bn
;
1286 struct bgp_path_info
*bpi
;
1292 char str_nh
[PREFIX_STRLEN
];
1294 prefix2str(ubpi_nexthop
, str_nh
, sizeof(str_nh
));
1295 vnc_zlog_debug_verbose("%s: ubpi_nexthop=%s", __func__
, str_nh
);
1300 bn
= bgp_node_lookup(table_rd
, ubpi_nexthop
);
1302 vnc_zlog_debug_verbose(
1303 "%s: no match in RD's table for ubpi_nexthop",
1308 /* Iterate over bgp_info items at this node */
1309 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
) {
1311 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1312 bgp
, afi
, bpi
, /* VPN bpi */
1314 prefix
); /* unicast route prefix */
1317 bgp_unlock_node(bn
);
1321 vnc_import_bgp_del_route_mode_resolve_nve(struct bgp
*bgp
, afi_t afi
,
1322 const struct prefix
*prefix
,
1323 struct bgp_path_info
*info
)
1325 struct ecommunity
*ecom
= NULL
;
1326 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
1328 // struct listnode *hnode;
1329 // struct rfapi_descriptor *rfd;
1330 struct prefix_bag
*pb
;
1332 struct skiplist
*sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1334 struct bgp_node
*bnp
; /* prd table node */
1337 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1342 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
1343 vnc_zlog_debug_verbose(
1344 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
1345 __func__
, info
->type
, zebra_route_string(info
->type
),
1346 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
1350 if (process_unicast_route(bgp
, afi
, prefix
, info
, &ecom
,
1351 &pfx_unicast_nexthop
)) {
1353 vnc_zlog_debug_verbose(
1354 "%s: process_unicast_route error, skipping", __func__
);
1358 rc
= skiplist_first_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1361 if (pb
->ubpi
== info
) {
1362 skiplist_delete(sl
, &pfx_unicast_nexthop
, pb
);
1363 bgp_path_info_unlock(info
);
1366 rc
= skiplist_next_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1371 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
1372 * (exact match, /32). If an exact match is found, call add_vnc_route.
1375 for (bnp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bnp
;
1376 bnp
= bgp_route_next(bnp
)) {
1378 struct bgp_table
*table
;
1380 table
= bgp_node_get_bgp_table_info(bnp
);
1385 vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1386 (struct prefix_rd
*)bgp_node_get_prefix(bnp
), table
,
1387 afi
, bgp
, prefix
, &pfx_unicast_nexthop
);
1391 ecommunity_free(&ecom
);
1395 /***********************************************************************
1396 * Add/Delete CE->NVE routes
1397 ***********************************************************************/
1400 * Should be called whan a bpi is added to VPN RIB. This function
1401 * will check if it is a host route and return immediately if not.
1403 void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1404 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1405 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1406 const struct prefix
*prefix
, /* VPN prefix */
1407 struct bgp_path_info
*bpi
) /* new VPN host route */
1409 afi_t afi
= family2afi(prefix
->family
);
1410 struct skiplist
*sl
= NULL
;
1412 struct prefix_bag
*pb
;
1414 struct rfapi_cfg
*hc
= NULL
;
1416 vnc_zlog_debug_verbose("%s: entry", __func__
);
1418 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1419 vnc_zlog_debug_verbose("%s: bad afi %d, skipping", __func__
,
1424 if (!(hc
= bgp
->rfapi_cfg
)) {
1425 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1430 /* check vnc redist flag for bgp direct routes */
1431 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1432 vnc_zlog_debug_verbose(
1433 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1438 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1439 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1445 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1448 vnc_zlog_debug_verbose(
1449 "%s: no resolve_nve_nexthop skiplist, skipping",
1454 if (!is_host_prefix(prefix
)) {
1455 vnc_zlog_debug_verbose("%s: not host prefix, skipping",
1460 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1462 struct ecommunity
*ecom
;
1463 struct prefix pfx_unicast_nexthop
;
1464 uint32_t *med
= NULL
;
1465 uint32_t local_pref
;
1467 memset(&pfx_unicast_nexthop
, 0,
1468 sizeof(struct prefix
)); /* keep valgrind happy */
1470 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
1471 char hbuf
[PREFIX_STRLEN
];
1472 char ubuf
[PREFIX_STRLEN
];
1474 prefix2str(&pb
->hpfx
, hbuf
, sizeof(hbuf
));
1475 prefix2str(&pb
->upfx
, ubuf
, sizeof(ubuf
));
1478 "%s: examining RHN Entry (q=%p): upfx=%s, hpfx=%s, ubpi=%p",
1479 __func__
, cursor
, ubuf
, hbuf
, pb
->ubpi
);
1482 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubpi
, &ecom
,
1483 &pfx_unicast_nexthop
)) {
1485 vnc_zlog_debug_verbose(
1486 "%s: process_unicast_route error, skipping",
1490 local_pref
= calc_local_pref(pb
->ubpi
->attr
, pb
->ubpi
->peer
);
1492 if (pb
->ubpi
->attr
->flag
1493 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
1494 med
= &pb
->ubpi
->attr
->med
;
1499 if (vnc_prefix_cmp(&pfx_unicast_nexthop
, prefix
)) {
1500 char str_unh
[PREFIX_STRLEN
];
1501 char str_nve_pfx
[PREFIX_STRLEN
];
1503 prefix2str(&pfx_unicast_nexthop
, str_unh
,
1505 prefix2str(prefix
, str_nve_pfx
, sizeof(str_nve_pfx
));
1507 vnc_zlog_debug_verbose(
1508 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %s != nve pfx %s",
1509 __func__
, str_unh
, str_nve_pfx
);
1513 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
1514 bgp
, afi
, bpi
, /* VPN bpi */
1515 prd
, &pb
->upfx
, /* unicast prefix */
1516 &local_pref
, med
, ecom
);
1519 ecommunity_free(&ecom
);
1524 char pbuf
[PREFIX_STRLEN
];
1526 prefix2str(prefix
, pbuf
, sizeof(pbuf
));
1528 vnc_zlog_debug_verbose(
1529 "%s: advancing past RHN Entry (q=%p): with prefix %s",
1530 __func__
, cursor
, pbuf
);
1531 print_rhn_list(__func__
, NULL
); /* debug */
1534 rc
= skiplist_next_value(sl
, prefix
, (void *)&pb
, &cursor
);
1536 vnc_zlog_debug_verbose("%s: done", __func__
);
1540 void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
1541 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1542 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1543 const struct prefix
*prefix
, /* VPN prefix */
1544 struct bgp_path_info
*bpi
) /* old VPN host route */
1546 afi_t afi
= family2afi(prefix
->family
);
1547 struct skiplist
*sl
= NULL
;
1548 struct prefix_bag
*pb
;
1550 struct rfapi_cfg
*hc
= NULL
;
1554 char str_pfx
[PREFIX_STRLEN
];
1556 prefix2str(prefix
, str_pfx
, sizeof(str_pfx
));
1558 vnc_zlog_debug_verbose("%s(bgp=%p, nve prefix=%s)", __func__
,
1562 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
)
1565 if (!(hc
= bgp
->rfapi_cfg
)) {
1566 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1571 /* check vnc redist flag for bgp direct routes */
1572 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1573 vnc_zlog_debug_verbose(
1574 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1579 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1580 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1586 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1589 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1594 if (!is_host_prefix(prefix
)) {
1595 vnc_zlog_debug_verbose("%s: not host route, skip", __func__
);
1600 * Find all entries with key == CE in the RHN list
1602 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1605 struct ecommunity
*ecom
;
1606 struct prefix pfx_unicast_nexthop
;
1608 memset(&pfx_unicast_nexthop
, 0,
1609 sizeof(struct prefix
)); /* keep valgrind happy */
1611 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubpi
, &ecom
,
1612 &pfx_unicast_nexthop
)) {
1614 vnc_zlog_debug_verbose(
1615 "%s: process_unicast_route error, skipping",
1623 if (vnc_prefix_cmp(&pfx_unicast_nexthop
, prefix
)) {
1624 char str_unh
[PREFIX_STRLEN
];
1625 char str_nve_pfx
[PREFIX_STRLEN
];
1627 prefix2str(&pfx_unicast_nexthop
, str_unh
,
1629 prefix2str(prefix
, str_nve_pfx
, sizeof(str_nve_pfx
));
1631 vnc_zlog_debug_verbose(
1632 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %s != nve pfx %s",
1633 __func__
, str_unh
, str_nve_pfx
);
1637 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1638 bgp
, afi
, bpi
, prd
, &pb
->upfx
);
1641 ecommunity_free(&ecom
);
1643 rc
= skiplist_next_value(sl
, prefix
, (void *)&pb
, &cursor
);
1648 /***********************************************************************
1650 ***********************************************************************/
1652 #define DEBUG_IS_USABLE_INTERIOR 1
1654 static int is_usable_interior_route(struct bgp_path_info
*bpi_interior
)
1656 if (!VALID_INTERIOR_TYPE(bpi_interior
->type
)) {
1657 #if DEBUG_IS_USABLE_INTERIOR
1658 vnc_zlog_debug_verbose(
1659 "%s: NO: type %d is not valid interior type", __func__
,
1660 bpi_interior
->type
);
1664 if (!CHECK_FLAG(bpi_interior
->flags
, BGP_PATH_VALID
)) {
1665 #if DEBUG_IS_USABLE_INTERIOR
1666 vnc_zlog_debug_verbose("%s: NO: BGP_PATH_VALID not set",
1675 * There should be only one of these per prefix at a time.
1676 * This should be called as a result of selection operation
1678 * NB should be called espacially for bgp instances that are named,
1679 * because the exterior routes will always come from one of those.
1680 * We filter here on the instance name to make sure we get only the
1683 static void vnc_import_bgp_exterior_add_route_it(
1684 struct bgp
*bgp
, /* exterior instance, we hope */
1685 const struct prefix
*prefix
, /* unicast prefix */
1686 struct bgp_path_info
*info
, /* unicast info */
1687 struct rfapi_import_table
*it_only
) /* NULL, or limit to this IT */
1690 struct rfapi_cfg
*hc
;
1691 struct prefix pfx_orig_nexthop
;
1692 struct rfapi_import_table
*it
;
1693 struct bgp
*bgp_default
= bgp_get_default();
1694 afi_t afi
= family2afi(prefix
->family
);
1699 h
= bgp_default
->rfapi
;
1700 hc
= bgp_default
->rfapi_cfg
;
1702 vnc_zlog_debug_verbose("%s: entry with it=%p", __func__
, it_only
);
1705 vnc_zlog_debug_verbose(
1706 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1710 if (!hc
->redist_bgp_exterior_view
) {
1711 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1715 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1716 vnc_zlog_debug_verbose(
1717 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1718 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1722 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1723 vnc_zlog_debug_verbose(
1724 "%s: redist of exterior routes not enabled, skipping",
1730 * Extract nexthop from exterior route
1732 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1733 * but if v4 it is in attr->nexthop
1735 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1737 for (it
= h
->imports
; it
; it
= it
->next
) {
1738 struct agg_table
*table
;
1739 struct agg_node
*rn
;
1740 struct agg_node
*par
;
1741 struct bgp_path_info
*bpi_interior
;
1742 int have_usable_route
;
1744 vnc_zlog_debug_verbose("%s: doing it %p", __func__
, it
);
1746 if (it_only
&& (it_only
!= it
)) {
1747 vnc_zlog_debug_verbose("%s: doesn't match it_only %p",
1752 table
= it
->imported_vpn
[afi
];
1754 for (rn
= agg_node_match(table
, &pfx_orig_nexthop
),
1755 have_usable_route
= 0;
1756 (!have_usable_route
) && rn
;) {
1758 vnc_zlog_debug_verbose("%s: it %p trying rn %p",
1761 for (bpi_interior
= rn
->info
; bpi_interior
;
1762 bpi_interior
= bpi_interior
->next
) {
1763 struct prefix_rd
*prd
;
1764 struct attr new_attr
;
1767 if (!is_usable_interior_route(bpi_interior
))
1770 vnc_zlog_debug_verbose(
1771 "%s: usable: bpi_interior %p", __func__
,
1775 * have a legitimate route to exterior's nexthop
1778 * Import unicast route to the import table
1780 have_usable_route
= 1;
1782 if (bpi_interior
->extra
) {
1783 prd
= &bpi_interior
->extra
->vnc
.import
1785 label
= decode_label(
1786 &bpi_interior
->extra
->label
[0]);
1790 /* use local_pref from unicast route */
1791 memset(&new_attr
, 0, sizeof(struct attr
));
1792 new_attr
= *bpi_interior
->attr
;
1793 if (info
->attr
->flag
1794 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
1795 new_attr
.local_pref
=
1796 info
->attr
->local_pref
;
1797 new_attr
.flag
|= ATTR_FLAG_BIT(
1798 BGP_ATTR_LOCAL_PREF
);
1801 rfapiBgpInfoFilteredImportVPN(
1802 it
, FIF_ACTION_UPDATE
,
1803 bpi_interior
->peer
, NULL
, /* rfd */
1804 prefix
, NULL
, afi
, prd
, &new_attr
,
1805 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1806 BGP_ROUTE_REDISTRIBUTE
, &label
);
1809 if (have_usable_route
) {
1813 * TBD factor this out into its own function
1815 struct prefix
*pfx_mon
= prefix_new();
1816 if (!RFAPI_MONITOR_EXTERIOR(rn
)->source
) {
1817 RFAPI_MONITOR_EXTERIOR(rn
)->source
=
1821 agg_lock_node(rn
); /* for skiplist */
1823 agg_lock_node(rn
); /* for skiplist entry */
1824 prefix_copy(pfx_mon
, prefix
);
1825 if (!skiplist_insert(
1826 RFAPI_MONITOR_EXTERIOR(rn
)->source
,
1829 bgp_path_info_lock(info
);
1832 par
= agg_node_parent(rn
);
1835 agg_unlock_node(rn
);
1839 agg_unlock_node(rn
);
1841 if (!have_usable_route
) {
1842 struct prefix
*pfx_mon
= prefix_new();
1843 prefix_copy(pfx_mon
, prefix
);
1844 if (!skiplist_insert(it
->monitor_exterior_orphans
, info
,
1847 bgp_path_info_lock(info
);
1853 void vnc_import_bgp_exterior_add_route(
1854 struct bgp
*bgp
, /* exterior instance, we hope */
1855 const struct prefix
*prefix
, /* unicast prefix */
1856 struct bgp_path_info
*info
) /* unicast info */
1858 vnc_import_bgp_exterior_add_route_it(bgp
, prefix
, info
, NULL
);
1862 * There should be only one of these per prefix at a time.
1863 * This should probably be called as a result of selection operation.
1865 * NB should be called espacially for bgp instances that are named,
1866 * because the exterior routes will always come from one of those.
1867 * We filter here on the instance name to make sure we get only the
1870 void vnc_import_bgp_exterior_del_route(
1871 struct bgp
*bgp
, const struct prefix
*prefix
, /* unicast prefix */
1872 struct bgp_path_info
*info
) /* unicast info */
1875 struct rfapi_cfg
*hc
;
1876 struct rfapi_import_table
*it
;
1877 struct prefix pfx_orig_nexthop
;
1878 afi_t afi
= family2afi(prefix
->family
);
1879 struct bgp
*bgp_default
= bgp_get_default();
1884 memset(&pfx_orig_nexthop
, 0,
1885 sizeof(struct prefix
)); /* keep valgrind happy */
1887 h
= bgp_default
->rfapi
;
1888 hc
= bgp_default
->rfapi_cfg
;
1891 vnc_zlog_debug_verbose(
1892 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1896 if (!hc
->redist_bgp_exterior_view
) {
1897 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1901 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1902 vnc_zlog_debug_verbose(
1903 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1904 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1907 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1908 vnc_zlog_debug_verbose(
1909 "%s: redist of exterior routes no enabled, skipping",
1915 * Extract nexthop from exterior route
1917 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1918 * but if v4 it is in attr->nexthop
1920 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1922 for (it
= h
->imports
; it
; it
= it
->next
) {
1923 struct agg_table
*table
;
1924 struct agg_node
*rn
;
1925 struct agg_node
*par
;
1926 struct bgp_path_info
*bpi_interior
;
1927 int have_usable_route
;
1929 table
= it
->imported_vpn
[afi
];
1931 for (rn
= agg_node_match(table
, &pfx_orig_nexthop
),
1932 have_usable_route
= 0;
1933 (!have_usable_route
) && rn
;) {
1935 for (bpi_interior
= rn
->info
; bpi_interior
;
1936 bpi_interior
= bpi_interior
->next
) {
1937 struct prefix_rd
*prd
;
1940 if (!is_usable_interior_route(bpi_interior
))
1944 * have a legitimate route to exterior's nexthop
1947 * Import unicast route to the import table
1949 have_usable_route
= 1;
1951 if (bpi_interior
->extra
) {
1952 prd
= &bpi_interior
->extra
->vnc
.import
1954 label
= decode_label(
1955 &bpi_interior
->extra
->label
[0]);
1959 rfapiBgpInfoFilteredImportVPN(
1960 it
, FIF_ACTION_KILL
, bpi_interior
->peer
,
1962 prefix
, NULL
, afi
, prd
,
1964 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1965 BGP_ROUTE_REDISTRIBUTE
, &label
);
1970 * TBD factor this out into its own function
1973 if (RFAPI_MONITOR_EXTERIOR(rn
)
1975 if (!skiplist_delete(
1976 RFAPI_MONITOR_EXTERIOR(
1981 bgp_path_info_unlock(
1988 RFAPI_MONITOR_EXTERIOR(
1992 RFAPI_MONITOR_EXTERIOR(
1995 RFAPI_MONITOR_EXTERIOR(
2006 par
= agg_node_parent(rn
);
2009 agg_unlock_node(rn
);
2013 agg_unlock_node(rn
);
2015 if (!have_usable_route
) {
2016 if (!skiplist_delete(it
->monitor_exterior_orphans
, info
,
2019 bgp_path_info_unlock(info
);
2026 * This function should be called after a new interior VPN route
2027 * has been added to an import_table.
2029 * NB should also be called whenever an existing vpn interior route
2030 * becomes valid (e.g., valid_interior_count is inremented)
2032 void vnc_import_bgp_exterior_add_route_interior(
2033 struct bgp
*bgp
, struct rfapi_import_table
*it
,
2034 struct agg_node
*rn_interior
, /* VPN IT node */
2035 struct bgp_path_info
*bpi_interior
) /* VPN IT route */
2037 const struct prefix
*p
= agg_node_get_prefix(rn_interior
);
2038 afi_t afi
= family2afi(p
->family
);
2039 struct agg_node
*par
;
2040 struct bgp_path_info
*bpi_exterior
;
2041 struct prefix
*pfx_exterior
; /* exterior pfx */
2044 struct list
*list_adopted
;
2046 vnc_zlog_debug_verbose("%s: entry", __func__
);
2048 if (!is_usable_interior_route(bpi_interior
)) {
2049 vnc_zlog_debug_verbose(
2050 "%s: not usable interior route, skipping", __func__
);
2054 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2055 vnc_zlog_debug_verbose(
2056 "%s: redist of exterior routes no enabled, skipping",
2061 if (it
== bgp
->rfapi
->it_ce
) {
2062 vnc_zlog_debug_verbose("%s: import table is it_ce, skipping",
2068 vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
2069 __func__
, rn_interior
, bpi_interior
->type
);
2071 if (RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
2073 int count
= 0; /* debugging */
2075 vnc_zlog_debug_verbose(
2076 "%s: has exterior monitor; ext src: %p", __func__
,
2077 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2080 * There is a monitor here already. Therefore, we do not need
2081 * to do any pulldown. Just construct exterior routes based
2082 * on the new interior route.
2085 for (rc
= skiplist_next(
2086 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2087 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2089 !rc
; rc
= skiplist_next(
2090 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2091 (void **)&bpi_exterior
,
2092 (void **)&pfx_exterior
, &cursor
)) {
2094 struct prefix_rd
*prd
;
2095 struct attr new_attr
;
2099 ++count
; /* debugging */
2101 assert(bpi_exterior
);
2102 assert(pfx_exterior
);
2104 if (bpi_interior
->extra
) {
2105 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2106 label
= decode_label(
2107 &bpi_interior
->extra
->label
[0]);
2111 /* use local_pref from unicast route */
2112 memset(&new_attr
, 0, sizeof(struct attr
));
2113 new_attr
= *bpi_interior
->attr
;
2115 && (bpi_exterior
->attr
->flag
2116 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2117 new_attr
.local_pref
=
2118 bpi_exterior
->attr
->local_pref
;
2120 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2123 rfapiBgpInfoFilteredImportVPN(
2124 it
, FIF_ACTION_UPDATE
, bpi_interior
->peer
,
2126 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2127 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2128 BGP_ROUTE_REDISTRIBUTE
, &label
);
2130 vnc_zlog_debug_verbose(
2131 "%s: finished constructing exteriors based on existing monitors",
2136 vnc_zlog_debug_verbose("%s: no exterior monitor", __func__
);
2139 * No monitor at this node. Is this the first valid interior
2140 * route at this node?
2142 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
> 1) {
2143 vnc_zlog_debug_verbose(
2144 "%s: new interior route not first valid one, skipping pulldown",
2150 * Look up the tree for possible pulldown candidates.
2151 * Find nearest parent with an exterior route monitor
2153 for (par
= agg_node_parent(rn_interior
); par
;
2154 par
= agg_node_parent(par
)) {
2155 if (RFAPI_HAS_MONITOR_EXTERIOR(par
))
2161 vnc_zlog_debug_verbose(
2162 "%s: checking parent %p for possible pulldowns",
2165 /* check monitors at par for possible pulldown */
2167 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2168 (void **)&bpi_exterior
,
2169 (void **)&pfx_exterior
, &cursor
);
2171 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2172 (void **)&bpi_exterior
,
2173 (void **)&pfx_exterior
, &cursor
)) {
2175 struct prefix pfx_nexthop
;
2177 memset(&pfx_nexthop
, 0,
2178 sizeof(struct prefix
)); /* keep valgrind happy */
2180 /* check original nexthop for prefix match */
2181 rfapiUnicastNexthop2Prefix(afi
, bpi_exterior
->attr
,
2184 if (prefix_match(p
, &pfx_nexthop
)) {
2186 struct bgp_path_info
*bpi
;
2187 struct prefix_rd
*prd
;
2188 struct attr new_attr
;
2194 * add monitor to longer prefix
2196 struct prefix
*pfx_mon
= prefix_new();
2197 prefix_copy(pfx_mon
, pfx_exterior
);
2198 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)
2200 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2201 ->source
= skiplist_new(
2202 0, NULL
, prefix_free_lists
);
2203 agg_lock_node(rn_interior
);
2206 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2208 bpi_exterior
, pfx_mon
);
2209 agg_lock_node(rn_interior
);
2212 * Delete constructed exterior routes based on
2215 for (bpi
= par
->info
; bpi
; bpi
= bpi
->next
) {
2218 prd
= &bpi
->extra
->vnc
.import
2220 label
= decode_label(
2221 &bpi
->extra
->label
[0]);
2225 rfapiBgpInfoFilteredImportVPN(
2226 it
, FIF_ACTION_KILL
, bpi
->peer
,
2228 pfx_exterior
, NULL
, afi
, prd
,
2230 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2231 BGP_ROUTE_REDISTRIBUTE
, &label
);
2236 * Add constructed exterior routes based on
2237 * the new interior route at longer prefix.
2239 if (bpi_interior
->extra
) {
2240 prd
= &bpi_interior
->extra
->vnc
.import
2242 label
= decode_label(
2243 &bpi_interior
->extra
->label
[0]);
2247 /* use local_pref from unicast route */
2248 memset(&new_attr
, 0, sizeof(struct attr
));
2249 new_attr
= *bpi_interior
->attr
;
2251 && (bpi_exterior
->attr
->flag
2252 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2253 new_attr
.local_pref
=
2254 bpi_exterior
->attr
->local_pref
;
2255 new_attr
.flag
|= ATTR_FLAG_BIT(
2256 BGP_ATTR_LOCAL_PREF
);
2259 rfapiBgpInfoFilteredImportVPN(
2260 it
, FIF_ACTION_UPDATE
,
2261 bpi_interior
->peer
, NULL
, /* rfd */
2262 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2263 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2264 BGP_ROUTE_REDISTRIBUTE
, &label
);
2269 * The only monitors at rn_interior are the ones we added just
2270 * above, so we can use the rn_interior list to identify which
2271 * monitors to delete from the parent.
2274 for (rc
= skiplist_next(
2275 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2276 (void **)&bpi_exterior
, NULL
, &cursor
);
2277 !rc
; rc
= skiplist_next(
2278 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2279 (void **)&bpi_exterior
, NULL
, &cursor
)) {
2282 skiplist_delete(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2283 bpi_exterior
, NULL
);
2284 agg_unlock_node(par
); /* sl entry */
2286 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par
)->source
)) {
2287 skiplist_free(RFAPI_MONITOR_EXTERIOR(par
)->source
);
2288 RFAPI_MONITOR_EXTERIOR(par
)->source
= NULL
;
2289 agg_unlock_node(par
); /* sl itself */
2293 vnc_zlog_debug_verbose("%s: checking orphans", __func__
);
2296 * See if any orphans can be pulled down to the current node
2299 list_adopted
= NULL
;
2300 for (rc
= skiplist_next(it
->monitor_exterior_orphans
,
2301 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2303 !rc
; rc
= skiplist_next(it
->monitor_exterior_orphans
,
2304 (void **)&bpi_exterior
,
2305 (void **)&pfx_exterior
, &cursor
)) {
2307 struct prefix pfx_nexthop
;
2308 char buf
[PREFIX_STRLEN
];
2309 afi_t afi_exterior
= family2afi(pfx_exterior
->family
);
2311 prefix2str(pfx_exterior
, buf
, sizeof(buf
));
2312 vnc_zlog_debug_verbose(
2313 "%s: checking exterior orphan at prefix %s", __func__
,
2316 if (afi_exterior
!= afi
) {
2317 vnc_zlog_debug_verbose(
2318 "%s: exterior orphan afi %d != interior afi %d, skip",
2319 __func__
, afi_exterior
, afi
);
2323 /* check original nexthop for prefix match */
2324 rfapiUnicastNexthop2Prefix(afi
, bpi_exterior
->attr
,
2327 if (prefix_match(p
, &pfx_nexthop
)) {
2329 struct prefix_rd
*prd
;
2330 struct attr new_attr
;
2336 * add monitor to longer prefix
2339 struct prefix
*pfx_mon
= prefix_new();
2340 prefix_copy(pfx_mon
, pfx_exterior
);
2341 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
) {
2342 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
=
2344 0, NULL
, prefix_free_lists
);
2345 agg_lock_node(rn_interior
); /* sl */
2348 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2349 bpi_exterior
, pfx_mon
);
2350 agg_lock_node(rn_interior
); /* sl entry */
2351 if (!list_adopted
) {
2352 list_adopted
= list_new();
2354 listnode_add(list_adopted
, bpi_exterior
);
2357 * Add constructed exterior routes based on the
2358 * new interior route at the longer prefix.
2360 if (bpi_interior
->extra
) {
2361 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2362 label
= decode_label(
2363 &bpi_interior
->extra
->label
[0]);
2367 /* use local_pref from unicast route */
2368 memset(&new_attr
, 0, sizeof(struct attr
));
2369 new_attr
= *bpi_interior
->attr
;
2371 && (bpi_exterior
->attr
->flag
2372 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2373 new_attr
.local_pref
=
2374 bpi_exterior
->attr
->local_pref
;
2376 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2379 rfapiBgpInfoFilteredImportVPN(
2380 it
, FIF_ACTION_UPDATE
, bpi_interior
->peer
,
2382 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2383 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2384 BGP_ROUTE_REDISTRIBUTE
, &label
);
2388 struct listnode
*node
;
2389 struct agg_node
*an_bpi_exterior
;
2391 for (ALL_LIST_ELEMENTS_RO(list_adopted
, node
,
2393 skiplist_delete(it
->monitor_exterior_orphans
,
2394 an_bpi_exterior
, NULL
);
2396 list_delete(&list_adopted
);
2401 * This function should be called after an interior VPN route
2402 * has been deleted from an import_table.
2403 * bpi_interior must still be valid, but it must already be detached
2404 * from its route node and the route node's valid_interior_count
2405 * must already be decremented.
2407 * NB should also be called whenever an existing vpn interior route
2408 * becomes invalid (e.g., valid_interior_count is decremented)
2410 void vnc_import_bgp_exterior_del_route_interior(
2411 struct bgp
*bgp
, struct rfapi_import_table
*it
,
2412 struct agg_node
*rn_interior
, /* VPN IT node */
2413 struct bgp_path_info
*bpi_interior
) /* VPN IT route */
2415 const struct prefix
*p
= agg_node_get_prefix(rn_interior
);
2416 afi_t afi
= family2afi(p
->family
);
2417 struct agg_node
*par
;
2418 struct bgp_path_info
*bpi_exterior
;
2419 struct prefix
*pfx_exterior
; /* exterior pfx */
2423 if (!VALID_INTERIOR_TYPE(bpi_interior
->type
)) {
2424 vnc_zlog_debug_verbose(
2425 "%s: type %d not valid interior type, skipping",
2426 __func__
, bpi_interior
->type
);
2430 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2431 vnc_zlog_debug_verbose(
2432 "%s: redist of exterior routes no enabled, skipping",
2437 if (it
== bgp
->rfapi
->it_ce
) {
2438 vnc_zlog_debug_verbose("%s: it is it_ce, skipping", __func__
);
2442 /* If no exterior routes depend on this prefix, nothing to do */
2443 if (!RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
2444 vnc_zlog_debug_verbose("%s: no exterior monitor, skipping",
2450 vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
2451 __func__
, rn_interior
, bpi_interior
->type
);
2454 * Remove constructed routes based on the deleted interior route
2457 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2458 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2461 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2462 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2465 struct prefix_rd
*prd
;
2468 if (bpi_interior
->extra
) {
2469 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2470 label
= decode_label(&bpi_interior
->extra
->label
[0]);
2474 rfapiBgpInfoFilteredImportVPN(
2475 it
, FIF_ACTION_KILL
, bpi_interior
->peer
, NULL
, /* rfd */
2476 pfx_exterior
, NULL
, afi
, prd
, bpi_interior
->attr
,
2477 ZEBRA_ROUTE_BGP_DIRECT_EXT
, BGP_ROUTE_REDISTRIBUTE
,
2482 * If there are no remaining valid interior routes at this prefix,
2483 * we need to look up the tree for a possible node to move monitors to
2485 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
) {
2486 vnc_zlog_debug_verbose(
2487 "%s: interior routes still present, skipping",
2493 * Find nearest parent with at least one valid interior route
2494 * If none is found, par will end up NULL, and we will move
2495 * the monitors to the orphan list for this import table
2497 for (par
= agg_node_parent(rn_interior
); par
;
2498 par
= agg_node_parent(par
)) {
2499 if (RFAPI_MONITOR_EXTERIOR(par
)->valid_interior_count
)
2503 vnc_zlog_debug_verbose("%s: par=%p, ext src: %p", __func__
, par
,
2504 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2506 /* move all monitors */
2508 * We will use and delete every element of the source skiplist
2510 while (!skiplist_first(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2511 (void **)&bpi_exterior
,
2512 (void **)&pfx_exterior
)) {
2514 struct prefix
*pfx_mon
= prefix_new();
2516 prefix_copy(pfx_mon
, pfx_exterior
);
2520 struct bgp_path_info
*bpi
;
2523 * Add monitor to parent node
2525 if (!RFAPI_MONITOR_EXTERIOR(par
)->source
) {
2526 RFAPI_MONITOR_EXTERIOR(par
)->source
=
2528 0, NULL
, prefix_free_lists
);
2529 agg_lock_node(par
); /* sl */
2531 skiplist_insert(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2532 bpi_exterior
, pfx_mon
);
2533 agg_lock_node(par
); /* sl entry */
2535 /* Add constructed exterior routes based on parent */
2536 for (bpi
= par
->info
; bpi
; bpi
= bpi
->next
) {
2538 struct prefix_rd
*prd
;
2539 struct attr new_attr
;
2542 if (bpi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
)
2546 prd
= &bpi
->extra
->vnc
.import
.rd
;
2547 label
= decode_label(
2548 &bpi
->extra
->label
[0]);
2552 /* use local_pref from unicast route */
2553 memset(&new_attr
, 0, sizeof(struct attr
));
2554 new_attr
= *bpi
->attr
;
2556 && (bpi_exterior
->attr
->flag
2557 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2558 new_attr
.local_pref
=
2559 bpi_exterior
->attr
->local_pref
;
2560 new_attr
.flag
|= ATTR_FLAG_BIT(
2561 BGP_ATTR_LOCAL_PREF
);
2564 rfapiBgpInfoFilteredImportVPN(
2565 it
, FIF_ACTION_UPDATE
, bpi
->peer
,
2567 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2568 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2569 BGP_ROUTE_REDISTRIBUTE
, &label
);
2575 * No interior route for exterior's nexthop. Save
2577 * in orphan list to await future route.
2579 skiplist_insert(it
->monitor_exterior_orphans
,
2580 bpi_exterior
, pfx_mon
);
2583 skiplist_delete_first(
2584 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2585 agg_unlock_node(rn_interior
); /* sl entry */
2587 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
)) {
2588 skiplist_free(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2589 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
= NULL
;
2590 agg_unlock_node(rn_interior
); /* sl itself */
2594 /***********************************************************************
2595 * Generic add/delete unicast routes
2596 ***********************************************************************/
2598 void vnc_import_bgp_add_route(struct bgp
*bgp
, const struct prefix
*prefix
,
2599 struct bgp_path_info
*info
)
2601 afi_t afi
= family2afi(prefix
->family
);
2603 if (VNC_DEBUG(VERBOSE
)) {
2604 struct prefix pfx_nexthop
;
2605 char buf
[PREFIX_STRLEN
];
2606 char buf_nh
[PREFIX_STRLEN
];
2608 prefix2str(prefix
, buf
, sizeof(buf
));
2609 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2610 prefix2str(&pfx_nexthop
, buf_nh
, sizeof(buf_nh
));
2612 vnc_zlog_debug_verbose("%s: pfx %s, nh %s", __func__
, buf
,
2616 print_rhn_list(__func__
, "ENTER ");
2621 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
2626 if (!bgp
->rfapi_cfg
) {
2627 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2632 /* check vnc redist flag for bgp direct routes */
2633 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2634 vnc_zlog_debug_verbose(
2635 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
2636 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2640 switch (bgp
->rfapi_cfg
->redist_mode
) {
2641 case VNC_REDIST_MODE_PLAIN
:
2642 vnc_import_bgp_add_route_mode_plain(bgp
, prefix
, info
);
2645 case VNC_REDIST_MODE_RFG
:
2646 if (bgp
->rfapi_cfg
->rfg_redist
)
2647 vnc_import_bgp_add_route_mode_nvegroup(
2648 bgp
, prefix
, info
, bgp
->rfapi_cfg
->rfg_redist
);
2650 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2654 case VNC_REDIST_MODE_RESOLVE_NVE
:
2655 vnc_import_bgp_add_route_mode_resolve_nve(bgp
, prefix
, info
);
2659 print_rhn_list(__func__
, "LEAVE ");
2665 * "Withdrawing a Route" import process
2667 void vnc_import_bgp_del_route(struct bgp
*bgp
, const struct prefix
*prefix
,
2668 struct bgp_path_info
*info
) /* unicast info */
2670 afi_t afi
= family2afi(prefix
->family
);
2675 struct prefix pfx_nexthop
;
2676 char buf
[PREFIX_STRLEN
];
2677 char buf_nh
[PREFIX_STRLEN
];
2679 prefix2str(prefix
, buf
, sizeof(buf
));
2680 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2681 prefix2str(&pfx_nexthop
, buf_nh
, sizeof(buf_nh
));
2683 vnc_zlog_debug_verbose("%s: pfx %s, nh %s", __func__
, buf
,
2687 print_rhn_list(__func__
, "ENTER ");
2691 if (!bgp
->rfapi_cfg
) {
2692 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2697 /* check bgp redist flag for vnc direct ("vpn") routes */
2698 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2699 vnc_zlog_debug_verbose(
2700 "%s: bgp redistribution of afi=%d VNC direct routes is off",
2705 switch (bgp
->rfapi_cfg
->redist_mode
) {
2706 case VNC_REDIST_MODE_PLAIN
:
2707 vnc_import_bgp_del_route_mode_plain(bgp
, prefix
, info
);
2710 case VNC_REDIST_MODE_RFG
:
2711 if (bgp
->rfapi_cfg
->rfg_redist
)
2712 vnc_import_bgp_del_route_mode_nvegroup(bgp
, prefix
,
2715 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2719 case VNC_REDIST_MODE_RESOLVE_NVE
:
2720 vnc_import_bgp_del_route_mode_resolve_nve(bgp
, afi
, prefix
,
2725 print_rhn_list(__func__
, "LEAVE ");
2731 /***********************************************************************
2733 ***********************************************************************/
2735 void vnc_import_bgp_redist_enable(struct bgp
*bgp
, afi_t afi
)
2737 /* iterate over bgp unicast v4 and v6 routes, call
2738 * vnc_import_bgp_add_route */
2740 struct bgp_node
*rn
;
2742 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
2744 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2745 vnc_zlog_debug_verbose(
2746 "%s: already enabled for afi %d, skipping", __func__
,
2750 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 1;
2752 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); rn
;
2753 rn
= bgp_route_next(rn
)) {
2755 struct bgp_path_info
*bpi
;
2757 for (bpi
= bgp_node_get_bgp_path_info(rn
); bpi
;
2760 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2763 vnc_import_bgp_add_route(bgp
, bgp_node_get_prefix(rn
),
2767 vnc_zlog_debug_verbose(
2768 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2769 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2772 void vnc_import_bgp_exterior_redist_enable(struct bgp
*bgp
, afi_t afi
)
2774 struct bgp
*bgp_exterior
;
2775 struct bgp_node
*rn
;
2777 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2779 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2780 vnc_zlog_debug_verbose(
2781 "%s: already enabled for afi %d, skipping", __func__
,
2785 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 1;
2787 if (!bgp_exterior
) {
2788 vnc_zlog_debug_verbose(
2789 "%s: no exterior view set yet, no routes to import yet",
2794 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); rn
;
2795 rn
= bgp_route_next(rn
)) {
2797 struct bgp_path_info
*bpi
;
2799 for (bpi
= bgp_node_get_bgp_path_info(rn
); bpi
;
2802 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2805 vnc_import_bgp_exterior_add_route(
2806 bgp_exterior
, bgp_node_get_prefix(rn
), bpi
);
2809 vnc_zlog_debug_verbose(
2810 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2811 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2815 * This function is for populating a newly-created Import Table
2817 void vnc_import_bgp_exterior_redist_enable_it(
2818 struct bgp
*bgp
, afi_t afi
, struct rfapi_import_table
*it_only
)
2820 struct bgp
*bgp_exterior
;
2821 struct bgp_node
*rn
;
2823 vnc_zlog_debug_verbose("%s: entry", __func__
);
2825 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2827 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2828 vnc_zlog_debug_verbose("%s: not enabled for afi %d, skipping",
2833 if (!bgp_exterior
) {
2834 vnc_zlog_debug_verbose(
2835 "%s: no exterior view set yet, no routes to import yet",
2840 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); rn
;
2841 rn
= bgp_route_next(rn
)) {
2843 struct bgp_path_info
*bpi
;
2845 for (bpi
= bgp_node_get_bgp_path_info(rn
); bpi
;
2848 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2851 vnc_import_bgp_exterior_add_route_it(
2852 bgp_exterior
, bgp_node_get_prefix(rn
), bpi
,
2859 void vnc_import_bgp_redist_disable(struct bgp
*bgp
, afi_t afi
)
2862 * iterate over vpn routes, find routes of type ZEBRA_ROUTE_BGP_DIRECT,
2863 * delete (call timer expire immediately)
2865 struct bgp_node
*rn1
;
2866 struct bgp_node
*rn2
;
2868 vnc_zlog_debug_verbose("%s: entry", __func__
);
2870 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2871 vnc_zlog_debug_verbose(
2872 "%s: already disabled for afi %d, skipping", __func__
,
2878 * Two-level table for SAFI_MPLS_VPN
2879 * Be careful when changing the things we iterate over
2881 for (rn1
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); rn1
;
2882 rn1
= bgp_route_next(rn1
)) {
2883 const struct prefix
*rn1_p
;
2885 if (!bgp_node_has_bgp_path_info_data(rn1
))
2888 rn1_p
= bgp_node_get_prefix(rn1
);
2889 for (rn2
= bgp_table_top(bgp_node_get_bgp_table_info(rn1
)); rn2
;
2890 rn2
= bgp_route_next(rn2
)) {
2891 const struct prefix
*rn2_p
= bgp_node_get_prefix(rn2
);
2892 struct bgp_path_info
*bpi
;
2893 struct bgp_path_info
*nextbpi
;
2895 for (bpi
= bgp_node_get_bgp_path_info(rn2
); bpi
;
2898 nextbpi
= bpi
->next
;
2900 if (bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
)
2903 struct rfapi_descriptor
*rfd
;
2904 vncHDBgpDirect
.peer
= bpi
->peer
;
2908 rfd
= bpi
->extra
->vnc
.export
.rfapi_handle
;
2910 vnc_zlog_debug_verbose(
2911 "%s: deleting bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]",
2912 __func__
, bpi
, bpi
->peer
, bpi
->type
,
2914 (bpi
->extra
? bpi
->extra
->vnc
.export
2919 del_vnc_route(rfd
, bpi
->peer
, bgp
,
2920 SAFI_MPLS_VPN
, rn2_p
,
2921 (struct prefix_rd
*)rn1_p
,
2922 bpi
->type
, bpi
->sub_type
, NULL
,
2925 vncHDBgpDirect
.peer
= NULL
;
2929 /* Clear RHN list */
2930 if (bgp
->rfapi
->resolve_nve_nexthop
) {
2931 struct prefix_bag
*pb
;
2932 struct bgp_path_info
*info
;
2933 while (!skiplist_first(bgp
->rfapi
->resolve_nve_nexthop
, NULL
,
2936 skiplist_delete_first(bgp
->rfapi
->resolve_nve_nexthop
);
2937 bgp_path_info_unlock(info
);
2941 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 0;
2942 vnc_zlog_debug_verbose("%s: return", __func__
);
2946 void vnc_import_bgp_exterior_redist_disable(struct bgp
*bgp
, afi_t afi
)
2948 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
2949 struct bgp
*bgp_exterior
= hc
->redist_bgp_exterior_view
;
2951 vnc_zlog_debug_verbose("%s: entry", __func__
);
2953 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2954 vnc_zlog_debug_verbose(
2955 "%s: already disabled for afi %d, skipping", __func__
,
2960 if (!bgp_exterior
) {
2961 vnc_zlog_debug_verbose(
2962 "%s: bgp exterior view not defined, skipping",
2969 struct bgp_node
*rn
;
2970 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]);
2971 rn
; rn
= bgp_route_next(rn
)) {
2973 struct bgp_path_info
*bpi
;
2975 for (bpi
= bgp_node_get_bgp_path_info(rn
); bpi
;
2978 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2981 vnc_import_bgp_exterior_del_route(
2982 bgp_exterior
, bgp_node_get_prefix(rn
),
2987 print_rhn_list(__func__
, NULL
);
2991 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 0;
2992 vnc_zlog_debug_verbose("%s: return", __func__
);