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) do {char buf[BUFSIZ];sprintf(buf,"%s: %s", __func__, #n);vnc_rhnck(buf);} while (0)
286 /***********************************************************************
287 * Add/Delete Unicast Route
288 ***********************************************************************/
291 * "Adding a Route" import process
295 * extract and package information from the BGP unicast route.
296 * Return code 0 means OK, non-0 means drop.
298 * If return code is 0, caller MUST release ecom
300 static int process_unicast_route(struct bgp
*bgp
, /* in */
302 const struct prefix
*prefix
, /* in */
303 struct bgp_path_info
*info
, /* in */
304 struct ecommunity
**ecom
, /* OUT */
305 struct prefix
*unicast_nexthop
) /* OUT */
307 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
308 struct peer
*peer
= info
->peer
;
309 struct attr
*attr
= info
->attr
;
311 struct route_map
*rmap
= NULL
;
312 struct prefix pfx_orig_nexthop
;
314 memset(&pfx_orig_nexthop
, 0,
315 sizeof(struct prefix
)); /* keep valgrind happy */
320 if (hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
321 vnc_zlog_debug_verbose("%s: HC prefix list is set, checking",
323 if (prefix_list_apply(
324 hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
],
327 vnc_zlog_debug_verbose(
328 "%s: prefix list returns DENY, blocking route",
332 vnc_zlog_debug_verbose(
333 "%s: prefix list returns PASS, allowing route",
337 /* apply routemap, if any, later */
338 rmap
= hc
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
341 * Extract original nexthop, which we expect to be a NVE connected
343 * Note that this is the nexthop before any possible application of
347 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
348 * but if v4 it is in attr->nexthop
350 rfapiUnicastNexthop2Prefix(afi
, attr
, &pfx_orig_nexthop
);
354 * This code is here because it allocates an interned attr which
355 * must be freed before we return. It's easier to put it after
356 * all of the possible returns above.
358 memset(&hattr
, 0, sizeof(struct attr
));
359 /* hattr becomes a ghost attr */
363 struct bgp_path_info info
;
364 route_map_result_t ret
;
366 memset(&info
, 0, sizeof(info
));
369 ret
= route_map_apply(rmap
, prefix
, RMAP_BGP
, &info
);
370 if (ret
== RMAP_DENYMATCH
) {
371 bgp_attr_flush(&hattr
);
372 vnc_zlog_debug_verbose(
373 "%s: route map \"%s\" says DENY, returning",
374 __func__
, rmap
->name
);
380 * Get the (possibly altered by policy) unicast nexthop
381 * for later lookup in the Import Table by caller
383 rfapiUnicastNexthop2Prefix(afi
, &hattr
, unicast_nexthop
);
385 if (hattr
.ecommunity
)
386 *ecom
= ecommunity_dup(hattr
.ecommunity
);
388 *ecom
= ecommunity_new();
391 * Done with hattr, clean up
393 bgp_attr_flush(&hattr
);
396 * Add EC that carries original NH of iBGP route (2 bytes = magic
397 * value indicating it came from an VNC gateway; default 5226, but
398 * must be user configurable). Note that this is the nexthop before
399 * any application of policy.
402 struct ecommunity_val vnc_gateway_magic
;
405 /* Using route origin extended community type */
406 memset(&vnc_gateway_magic
, 0, sizeof(vnc_gateway_magic
));
407 vnc_gateway_magic
.val
[0] = 0x01;
408 vnc_gateway_magic
.val
[1] = 0x03;
410 /* Only works for IPv4 nexthops */
411 if (prefix
->family
== AF_INET
) {
412 memcpy(vnc_gateway_magic
.val
+ 2,
413 &unicast_nexthop
->u
.prefix4
, 4);
415 localadmin
= htons(hc
->resolve_nve_roo_local_admin
);
416 memcpy(vnc_gateway_magic
.val
+ 6, (char *)&localadmin
, 2);
418 ecommunity_add_val(*ecom
, &vnc_gateway_magic
);
425 static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
426 struct bgp
*bgp
, afi_t afi
, struct bgp_path_info
*bpi
, /* VPN bpi */
427 struct prefix_rd
*prd
, /* RD */
428 const struct prefix
*prefix
, /* unicast route prefix */
429 uint32_t *local_pref
, /* NULL = no local_pref */
430 uint32_t *med
, /* NULL = no med */
431 struct ecommunity
*ecom
) /* generated ecoms */
434 struct prefix nexthop
;
435 struct rfapi_ip_addr nexthop_h
;
438 struct bgp_attr_encap_subtlv
*encaptlvs
;
441 struct rfapi_un_option optary
[3];
442 struct rfapi_un_option
*opt
= NULL
;
445 vnc_zlog_debug_verbose("%s: entry", __func__
);
447 if (bpi
->type
!= ZEBRA_ROUTE_BGP
448 && bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
) {
452 if (bpi
->sub_type
!= BGP_ROUTE_NORMAL
453 && bpi
->sub_type
!= BGP_ROUTE_STATIC
454 && bpi
->sub_type
!= BGP_ROUTE_RFP
) {
458 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
461 vncHDResolveNve
.peer
= bpi
->peer
;
462 if (!rfapiGetVncTunnelUnAddr(bpi
->attr
, &un
)) {
463 if (rfapiQprefix2Raddr(&un
, &vncHDResolveNve
.un_addr
))
466 memset(&vncHDResolveNve
.un_addr
, 0,
467 sizeof(vncHDResolveNve
.un_addr
));
470 /* Use nexthop of VPN route as nexthop of constructed route */
471 rfapiNexthop2Prefix(bpi
->attr
, &nexthop
);
472 rfapiQprefix2Raddr(&nexthop
, &nexthop_h
);
474 if (rfapiGetVncLifetime(bpi
->attr
, &lifetime
)) {
477 plifetime
= &lifetime
;
480 encaptlvs
= bpi
->attr
->vnc_subtlvs
;
481 if (bpi
->attr
->encap_tunneltype
!= BGP_ENCAP_TYPE_RESERVED
482 && bpi
->attr
->encap_tunneltype
!= BGP_ENCAP_TYPE_MPLS
) {
483 opt
= &optary
[cur_opt
++];
484 memset(opt
, 0, sizeof(struct rfapi_un_option
));
485 opt
->type
= RFAPI_UN_OPTION_TYPE_TUNNELTYPE
;
486 opt
->v
.tunnel
.type
= bpi
->attr
->encap_tunneltype
;
487 /* TBD parse bpi->attr->extra->encap_subtlvs */
490 struct ecommunity
*new_ecom
= ecommunity_dup(ecom
);
492 if (bpi
->attr
->ecommunity
)
493 ecommunity_merge(new_ecom
, bpi
->attr
->ecommunity
);
496 label
= decode_label(&bpi
->extra
->label
[0]);
498 add_vnc_route(&vncHDResolveNve
, bgp
, SAFI_MPLS_VPN
,
499 prefix
, /* unicast route prefix */
500 prd
, &nexthop_h
, /* new nexthop */
501 local_pref
, plifetime
,
502 (struct bgp_tea_options
*)encaptlvs
, /* RFP options */
503 opt
, NULL
, new_ecom
, med
, /* NULL => don't set med */
504 (label
? &label
: NULL
), /* NULL= default */
505 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
506 RFAPI_AHR_RFPOPT_IS_VNCTLV
); /* flags */
508 ecommunity_free(&new_ecom
);
511 static void vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
512 struct prefix_rd
*prd
, /* RD */
513 struct bgp_table
*table_rd
, /* per-rd VPN route table */
514 afi_t afi
, struct bgp
*bgp
,
515 const struct prefix
*prefix
, /* unicast prefix */
516 struct ecommunity
*ecom
, /* generated ecoms */
517 uint32_t *local_pref
, /* NULL = no local_pref */
518 uint32_t *med
, /* NULL = no med */
519 struct prefix
*ubpi_nexthop
) /* unicast nexthop */
522 struct bgp_path_info
*bpi
;
528 char str_nh
[PREFIX_STRLEN
];
530 prefix2str(ubpi_nexthop
, str_nh
, sizeof(str_nh
));
532 vnc_zlog_debug_verbose("%s: ubpi_nexthop=%s", __func__
, str_nh
);
536 bn
= bgp_node_lookup(table_rd
, ubpi_nexthop
);
538 vnc_zlog_debug_verbose(
539 "%s: no match in RD's table for ubpi_nexthop",
544 /* Iterate over bgp_info items at this node */
545 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
) {
547 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
548 bgp
, afi
, bpi
, /* VPN bpi */
549 prd
, prefix
, local_pref
, med
, ecom
);
555 static void vnc_import_bgp_add_route_mode_resolve_nve(
556 struct bgp
*bgp
, const struct prefix
*prefix
, /* unicast prefix */
557 struct bgp_path_info
*info
) /* unicast info */
559 afi_t afi
= family2afi(prefix
->family
);
561 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
563 struct ecommunity
*ecom
= NULL
;
565 uint32_t *med
= NULL
;
567 struct prefix_bag
*pb
;
568 struct bgp_node
*bnp
; /* prd table node */
571 if (VNC_DEBUG(VERBOSE
)) {
572 char str_pfx
[PREFIX_STRLEN
];
573 char str_nh
[PREFIX_STRLEN
];
576 prefix2str(prefix
, str_pfx
, sizeof(str_pfx
));
579 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &nh
);
581 prefix2str(&nh
, str_nh
, sizeof(str_nh
));
587 vnc_zlog_debug_verbose(
588 "%s(bgp=%p, unicast prefix=%s, unicast nh=%s)",
589 __func__
, bgp
, str_pfx
, str_nh
);
592 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
593 vnc_zlog_debug_verbose(
594 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
595 __func__
, info
->type
, zebra_route_string(info
->type
),
596 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
605 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
610 if (!(bgp
->rfapi_cfg
)) {
611 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
616 /* check vnc redist flag for bgp direct routes */
617 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
618 vnc_zlog_debug_verbose(
619 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
625 if (process_unicast_route(bgp
, afi
, prefix
, info
, &ecom
,
626 &pfx_unicast_nexthop
)) {
628 vnc_zlog_debug_verbose(
629 "%s: process_unicast_route error, skipping", __func__
);
633 local_pref
= calc_local_pref(info
->attr
, info
->peer
);
634 if (info
->attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
635 med
= &info
->attr
->med
;
638 * At this point, we have allocated:
640 * ecom ecommunity ptr, union of unicast and ROO parts (no NVE part)
644 * pfx_unicast_nexthop nexthop of uncast route
647 if (!bgp
->rfapi
->resolve_nve_nexthop
) {
648 bgp
->rfapi
->resolve_nve_nexthop
=
649 skiplist_new(SKIPLIST_FLAG_ALLOW_DUPLICATES
,
650 vnc_prefix_cmp
, prefix_bag_free
);
653 pb
= XCALLOC(MTYPE_RFAPI_PREFIX_BAG
, sizeof(struct prefix_bag
));
654 pb
->hpfx
= pfx_unicast_nexthop
;
658 bgp_path_info_lock(info
); /* skiplist refers to it */
659 skiplist_insert(bgp
->rfapi
->resolve_nve_nexthop
, &pb
->hpfx
, pb
);
662 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
663 * (exact match, /32). If an exact match is found, call add_vnc_route.
666 for (bnp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bnp
;
667 bnp
= bgp_route_next(bnp
)) {
669 struct bgp_table
*table
;
671 table
= bgp_node_get_bgp_table_info(bnp
);
676 vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
677 (struct prefix_rd
*)bgp_node_get_prefix(bnp
), table
,
678 afi
, bgp
, prefix
, ecom
, &local_pref
, med
,
679 &pfx_unicast_nexthop
);
684 ecommunity_free(&ecom
);
686 vnc_zlog_debug_verbose("%s: done", __func__
);
690 static void vnc_import_bgp_add_route_mode_plain(struct bgp
*bgp
,
691 const struct prefix
*prefix
,
692 struct bgp_path_info
*info
)
694 afi_t afi
= family2afi(prefix
->family
);
695 struct peer
*peer
= info
->peer
;
696 struct attr
*attr
= info
->attr
;
698 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
699 struct attr
*iattr
= NULL
;
701 struct rfapi_ip_addr vnaddr
;
702 struct prefix vn_pfx_space
;
703 struct prefix
*vn_pfx
= NULL
;
705 struct ecommunity
*ecom
= NULL
;
706 struct prefix_rd prd
;
707 struct route_map
*rmap
= NULL
;
709 uint32_t *med
= NULL
;
712 char buf
[PREFIX_STRLEN
];
714 prefix2str(prefix
, buf
, sizeof(buf
));
715 vnc_zlog_debug_verbose("%s(prefix=%s) entry", __func__
, buf
);
719 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
725 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
730 /* check vnc redist flag for bgp direct routes */
731 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
732 vnc_zlog_debug_verbose(
733 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
739 * mode "plain" specific code
742 vnc_zlog_debug_verbose("%s: NOT using redist RFG", __func__
);
747 if (hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
748 vnc_zlog_debug_verbose(
749 "%s: HC prefix list is set, checking",
751 if (prefix_list_apply(
752 hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
756 vnc_zlog_debug_verbose(
757 "%s: prefix list returns DENY, blocking route",
761 vnc_zlog_debug_verbose(
762 "%s: prefix list returns PASS, allowing route",
766 /* apply routemap, if any, later */
767 rmap
= hc
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
770 * Incoming prefix is unicast. If v6, it is in multiprotocol
772 * but if v4 it is in attr->nexthop
774 rfapiUnicastNexthop2Prefix(afi
, attr
, &vn_pfx_space
);
775 vn_pfx
= &vn_pfx_space
;
778 ahr_flags
|= RFAPI_AHR_NO_TUNNEL_SUBTLV
;
781 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
782 char buf
[PREFIX_STRLEN
];
784 prefix2str(vn_pfx
, buf
, sizeof(buf
));
785 vnc_zlog_debug_any("%s vn_pfx=%s", __func__
, buf
);
791 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
792 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
799 * This code is here because it allocates an interned attr which
800 * must be freed before we return. It's easier to put it after
801 * all of the possible returns above.
803 memset(&hattr
, 0, sizeof(struct attr
));
804 /* hattr becomes a ghost attr */
808 struct bgp_path_info info
;
809 route_map_result_t ret
;
811 memset(&info
, 0, sizeof(info
));
814 ret
= route_map_apply(rmap
, prefix
, RMAP_BGP
, &info
);
815 if (ret
== RMAP_DENYMATCH
) {
816 bgp_attr_flush(&hattr
);
817 vnc_zlog_debug_verbose(
818 "%s: route map \"%s\" says DENY, returning",
819 __func__
, rmap
->name
);
824 iattr
= bgp_attr_intern(&hattr
);
825 bgp_attr_flush(&hattr
);
827 /* Now iattr is an allocated interned attr */
830 * Mode "plain" specific code
832 * Sets RD in dummy HD
836 if (vnaddr
.addr_family
!= AF_INET
) {
837 vnc_zlog_debug_verbose(
838 "%s: can't auto-assign RD, VN AF (%d) is not IPv4, skipping",
839 __func__
, vnaddr
.addr_family
);
841 bgp_attr_unintern(&iattr
);
845 memset(&prd
, 0, sizeof(prd
));
846 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
848 if (iattr
&& iattr
->ecommunity
)
849 ecom
= ecommunity_dup(iattr
->ecommunity
);
852 local_pref
= calc_local_pref(iattr
, peer
);
854 if (iattr
&& (iattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))) {
858 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
859 char buf
[PREFIX_STRLEN
];
861 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, sizeof(buf
));
862 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
865 vncHDBgpDirect
.peer
= peer
;
866 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
867 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
868 NULL
, /* RFP options */
869 NULL
, NULL
, ecom
, med
, /* med */
870 NULL
, /* label: default */
871 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
873 vncHDBgpDirect
.peer
= NULL
;
876 ecommunity_free(&ecom
);
879 static void vnc_import_bgp_add_route_mode_nvegroup(
880 struct bgp
*bgp
, const struct prefix
*prefix
,
881 struct bgp_path_info
*info
, struct rfapi_nve_group_cfg
*rfg
)
883 afi_t afi
= family2afi(prefix
->family
);
884 struct peer
*peer
= info
->peer
;
885 struct attr
*attr
= info
->attr
;
887 struct attr
*iattr
= NULL
;
889 struct rfapi_ip_addr vnaddr
;
890 struct prefix
*vn_pfx
= NULL
;
892 struct ecommunity
*ecom
= NULL
;
893 struct prefix_rd prd
;
894 struct route_map
*rmap
= NULL
;
898 char buf
[PREFIX_STRLEN
];
900 prefix2str(prefix
, buf
, sizeof(buf
));
901 vnc_zlog_debug_verbose("%s(prefix=%s) entry", __func__
, buf
);
907 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
912 if (!(bgp
->rfapi_cfg
)) {
913 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
918 /* check vnc redist flag for bgp direct routes */
919 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
920 vnc_zlog_debug_verbose(
921 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
932 struct rfapi_ip_prefix pfx_un
;
934 vnc_zlog_debug_verbose("%s: using redist RFG", __func__
);
937 * RFG prefix list check
939 if (rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
940 vnc_zlog_debug_verbose(
941 "%s: RFG prefix list is set, checking",
943 if (prefix_list_apply(
944 rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
948 vnc_zlog_debug_verbose(
949 "%s: prefix list returns DENY, blocking route",
953 vnc_zlog_debug_verbose(
954 "%s: prefix list returns PASS, allowing route",
958 /* apply routemap, if any, later */
959 rmap
= rfg
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
962 * export nve group's VN addr prefix must be a /32 which
963 * will yield the VN addr to use
965 vn_pfx
= &rfg
->vn_prefix
;
970 if (!is_host_prefix(&rfg
->un_prefix
)) {
971 /* NB prefixlen==0 means it has not been configured */
972 vnc_zlog_debug_verbose(
973 "%s: redist RFG UN pfx not host pfx (plen=%d), skipping",
974 __func__
, rfg
->un_prefix
.prefixlen
);
978 rfapiQprefix2Rprefix(&rfg
->un_prefix
, &pfx_un
);
980 vncHDBgpDirect
.un_addr
= pfx_un
.prefix
;
983 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
984 char buf
[PREFIX_STRLEN
];
986 prefix2str(vn_pfx
, buf
, sizeof(buf
));
987 vnc_zlog_debug_any("%s vn_pfx=%s", __func__
, buf
);
993 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
994 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
1000 * route map handling
1001 * This code is here because it allocates an interned attr which
1002 * must be freed before we return. It's easier to put it after
1003 * all of the possible returns above.
1005 memset(&hattr
, 0, sizeof(struct attr
));
1006 /* hattr becomes a ghost attr */
1010 struct bgp_path_info path
;
1011 route_map_result_t ret
;
1013 memset(&path
, 0, sizeof(path
));
1016 ret
= route_map_apply(rmap
, prefix
, RMAP_BGP
, &path
);
1017 if (ret
== RMAP_DENYMATCH
) {
1018 bgp_attr_flush(&hattr
);
1019 vnc_zlog_debug_verbose(
1020 "%s: route map \"%s\" says DENY, returning",
1021 __func__
, rmap
->name
);
1026 iattr
= bgp_attr_intern(&hattr
);
1027 bgp_attr_flush(&hattr
);
1029 /* Now iattr is an allocated interned attr */
1034 * Sets RD in dummy HD
1039 memset(&prd
, 0, sizeof(prd
));
1041 prd
.family
= AF_UNSPEC
;
1044 if (rfg
->rd
.family
== AF_UNIX
) {
1045 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
1048 if (rfg
->rt_export_list
)
1049 ecom
= ecommunity_dup(
1050 bgp
->rfapi_cfg
->rfg_redist
->rt_export_list
);
1052 ecom
= ecommunity_new();
1054 if (iattr
&& iattr
->ecommunity
)
1055 ecom
= ecommunity_merge(ecom
, iattr
->ecommunity
);
1058 local_pref
= calc_local_pref(iattr
, peer
);
1060 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
1064 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, BUFSIZ
);
1065 buf
[BUFSIZ
- 1] = 0;
1066 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
1069 vncHDBgpDirect
.peer
= peer
;
1070 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
1071 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
1072 NULL
, /* RFP options */
1073 NULL
, NULL
, ecom
, NULL
, /* med */
1074 NULL
, /* label: default */
1075 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1077 vncHDBgpDirect
.peer
= NULL
;
1080 ecommunity_free(&ecom
);
1083 static void vnc_import_bgp_del_route_mode_plain(struct bgp
*bgp
,
1084 const struct prefix
*prefix
,
1085 struct bgp_path_info
*info
)
1087 struct prefix_rd prd
;
1088 afi_t afi
= family2afi(prefix
->family
);
1089 struct prefix
*vn_pfx
= NULL
;
1090 struct rfapi_ip_addr vnaddr
;
1091 struct prefix vn_pfx_space
;
1097 * Compute VN address
1101 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &vn_pfx_space
);
1103 vnc_zlog_debug_verbose("%s: no attr, can't delete route",
1107 vn_pfx
= &vn_pfx_space
;
1109 vnaddr
.addr_family
= vn_pfx
->family
;
1110 switch (vn_pfx
->family
) {
1112 if (vn_pfx
->prefixlen
!= 32) {
1113 vnc_zlog_debug_verbose(
1114 "%s: redist VN plen (%d) != 32, skipping",
1115 __func__
, vn_pfx
->prefixlen
);
1118 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1122 if (vn_pfx
->prefixlen
!= 128) {
1123 vnc_zlog_debug_verbose(
1124 "%s: redist VN plen (%d) != 128, skipping",
1125 __func__
, vn_pfx
->prefixlen
);
1128 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1132 vnc_zlog_debug_verbose(
1133 "%s: no redist RFG VN host pfx configured, skipping",
1139 memset(&prd
, 0, sizeof(prd
));
1140 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1141 vnc_zlog_debug_verbose("%s: can't auto-assign RD, skipping",
1146 vncHDBgpDirect
.peer
= info
->peer
;
1147 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1148 vncHDBgpDirect
.peer
);
1149 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1150 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1153 vncHDBgpDirect
.peer
= NULL
;
1156 static void vnc_import_bgp_del_route_mode_nvegroup(struct bgp
*bgp
,
1157 const struct prefix
*prefix
,
1158 struct bgp_path_info
*info
)
1160 struct prefix_rd prd
;
1161 afi_t afi
= family2afi(prefix
->family
);
1162 struct rfapi_nve_group_cfg
*rfg
= NULL
;
1163 struct prefix
*vn_pfx
= NULL
;
1164 struct rfapi_ip_addr vnaddr
;
1169 rfg
= bgp
->rfapi_cfg
->rfg_redist
;
1173 * Compute VN address
1177 * export nve group's VN addr prefix must be a /32 which
1178 * will yield the VN addr to use
1180 vn_pfx
= &rfg
->vn_prefix
;
1183 vnaddr
.addr_family
= vn_pfx
->family
;
1184 switch (vn_pfx
->family
) {
1186 if (vn_pfx
->prefixlen
!= 32) {
1187 vnc_zlog_debug_verbose(
1188 "%s: redist VN plen (%d) != 32, skipping",
1189 __func__
, vn_pfx
->prefixlen
);
1192 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1196 if (vn_pfx
->prefixlen
!= 128) {
1197 vnc_zlog_debug_verbose(
1198 "%s: redist VN plen (%d) != 128, skipping",
1199 __func__
, vn_pfx
->prefixlen
);
1202 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1206 vnc_zlog_debug_verbose(
1207 "%s: no redist RFG VN host pfx configured, skipping",
1212 memset(&prd
, 0, sizeof(prd
));
1214 prd
.family
= AF_UNSPEC
;
1217 if (rfg
->rd
.family
== AF_UNIX
) {
1218 /* means "auto" with VN addr */
1219 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1220 vnc_zlog_debug_verbose(
1221 "%s: can't auto-assign RD, skipping", __func__
);
1227 vncHDBgpDirect
.peer
= info
->peer
;
1228 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1229 vncHDBgpDirect
.peer
);
1230 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1231 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1234 vncHDBgpDirect
.peer
= NULL
;
1237 static void vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1238 struct bgp
*bgp
, afi_t afi
, struct bgp_path_info
*bpi
, /* VPN bpi */
1239 struct prefix_rd
*prd
, /* RD */
1240 const struct prefix
*prefix
) /* unicast route prefix */
1244 if (bpi
->type
!= ZEBRA_ROUTE_BGP
1245 && bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
) {
1249 if (bpi
->sub_type
!= BGP_ROUTE_NORMAL
1250 && bpi
->sub_type
!= BGP_ROUTE_STATIC
1251 && bpi
->sub_type
!= BGP_ROUTE_RFP
) {
1255 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
1258 vncHDResolveNve
.peer
= bpi
->peer
;
1259 if (!rfapiGetVncTunnelUnAddr(bpi
->attr
, &un
)) {
1260 if (rfapiQprefix2Raddr(&un
, &vncHDResolveNve
.un_addr
))
1263 memset(&vncHDResolveNve
.un_addr
, 0,
1264 sizeof(vncHDResolveNve
.un_addr
));
1267 del_vnc_route(&vncHDResolveNve
, vncHDResolveNve
.peer
, bgp
,
1268 SAFI_MPLS_VPN
, prefix
, /* unicast route prefix */
1269 prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
, NULL
,
1273 static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1274 struct prefix_rd
*prd
,
1275 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1276 afi_t afi
, struct bgp
*bgp
,
1277 const struct prefix
*prefix
, /* unicast prefix */
1278 const struct prefix
*ubpi_nexthop
) /* unicast bpi's nexthop */
1280 struct bgp_node
*bn
;
1281 struct bgp_path_info
*bpi
;
1287 char str_nh
[PREFIX_STRLEN
];
1289 prefix2str(ubpi_nexthop
, str_nh
, sizeof(str_nh
));
1290 vnc_zlog_debug_verbose("%s: ubpi_nexthop=%s", __func__
, str_nh
);
1295 bn
= bgp_node_lookup(table_rd
, ubpi_nexthop
);
1297 vnc_zlog_debug_verbose(
1298 "%s: no match in RD's table for ubpi_nexthop",
1303 /* Iterate over bgp_info items at this node */
1304 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
) {
1306 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1307 bgp
, afi
, bpi
, /* VPN bpi */
1309 prefix
); /* unicast route prefix */
1312 bgp_unlock_node(bn
);
1316 vnc_import_bgp_del_route_mode_resolve_nve(struct bgp
*bgp
, afi_t afi
,
1317 const struct prefix
*prefix
,
1318 struct bgp_path_info
*info
)
1320 struct ecommunity
*ecom
= NULL
;
1321 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
1323 // struct listnode *hnode;
1324 // struct rfapi_descriptor *rfd;
1325 struct prefix_bag
*pb
;
1327 struct skiplist
*sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1329 struct bgp_node
*bnp
; /* prd table node */
1332 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1337 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
1338 vnc_zlog_debug_verbose(
1339 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
1340 __func__
, info
->type
, zebra_route_string(info
->type
),
1341 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
1345 if (process_unicast_route(bgp
, afi
, prefix
, info
, &ecom
,
1346 &pfx_unicast_nexthop
)) {
1348 vnc_zlog_debug_verbose(
1349 "%s: process_unicast_route error, skipping", __func__
);
1353 rc
= skiplist_first_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1356 if (pb
->ubpi
== info
) {
1357 skiplist_delete(sl
, &pfx_unicast_nexthop
, pb
);
1358 bgp_path_info_unlock(info
);
1361 rc
= skiplist_next_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1366 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
1367 * (exact match, /32). If an exact match is found, call add_vnc_route.
1370 for (bnp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bnp
;
1371 bnp
= bgp_route_next(bnp
)) {
1373 struct bgp_table
*table
;
1375 table
= bgp_node_get_bgp_table_info(bnp
);
1380 vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1381 (struct prefix_rd
*)bgp_node_get_prefix(bnp
), table
,
1382 afi
, bgp
, prefix
, &pfx_unicast_nexthop
);
1386 ecommunity_free(&ecom
);
1390 /***********************************************************************
1391 * Add/Delete CE->NVE routes
1392 ***********************************************************************/
1395 * Should be called whan a bpi is added to VPN RIB. This function
1396 * will check if it is a host route and return immediately if not.
1398 void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1399 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1400 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1401 const struct prefix
*prefix
, /* VPN prefix */
1402 struct bgp_path_info
*bpi
) /* new VPN host route */
1404 afi_t afi
= family2afi(prefix
->family
);
1405 struct skiplist
*sl
= NULL
;
1407 struct prefix_bag
*pb
;
1409 struct rfapi_cfg
*hc
= NULL
;
1411 vnc_zlog_debug_verbose("%s: entry", __func__
);
1413 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1414 vnc_zlog_debug_verbose("%s: bad afi %d, skipping", __func__
,
1419 if (!(hc
= bgp
->rfapi_cfg
)) {
1420 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1425 /* check vnc redist flag for bgp direct routes */
1426 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1427 vnc_zlog_debug_verbose(
1428 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1433 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1434 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1440 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1443 vnc_zlog_debug_verbose(
1444 "%s: no resolve_nve_nexthop skiplist, skipping",
1449 if (!is_host_prefix(prefix
)) {
1450 vnc_zlog_debug_verbose("%s: not host prefix, skipping",
1455 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1457 struct ecommunity
*ecom
;
1458 struct prefix pfx_unicast_nexthop
;
1459 uint32_t *med
= NULL
;
1460 uint32_t local_pref
;
1462 memset(&pfx_unicast_nexthop
, 0,
1463 sizeof(struct prefix
)); /* keep valgrind happy */
1465 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
1466 char hbuf
[PREFIX_STRLEN
];
1467 char ubuf
[PREFIX_STRLEN
];
1469 prefix2str(&pb
->hpfx
, hbuf
, sizeof(hbuf
));
1470 prefix2str(&pb
->upfx
, ubuf
, sizeof(ubuf
));
1473 "%s: examining RHN Entry (q=%p): upfx=%s, hpfx=%s, ubpi=%p",
1474 __func__
, cursor
, ubuf
, hbuf
, pb
->ubpi
);
1477 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubpi
, &ecom
,
1478 &pfx_unicast_nexthop
)) {
1480 vnc_zlog_debug_verbose(
1481 "%s: process_unicast_route error, skipping",
1485 local_pref
= calc_local_pref(pb
->ubpi
->attr
, pb
->ubpi
->peer
);
1487 if (pb
->ubpi
->attr
->flag
1488 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
1489 med
= &pb
->ubpi
->attr
->med
;
1494 if (vnc_prefix_cmp(&pfx_unicast_nexthop
, prefix
)) {
1495 char str_unh
[PREFIX_STRLEN
];
1496 char str_nve_pfx
[PREFIX_STRLEN
];
1498 prefix2str(&pfx_unicast_nexthop
, str_unh
,
1500 prefix2str(prefix
, str_nve_pfx
, sizeof(str_nve_pfx
));
1502 vnc_zlog_debug_verbose(
1503 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %s != nve pfx %s",
1504 __func__
, str_unh
, str_nve_pfx
);
1508 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
1509 bgp
, afi
, bpi
, /* VPN bpi */
1510 prd
, &pb
->upfx
, /* unicast prefix */
1511 &local_pref
, med
, ecom
);
1514 ecommunity_free(&ecom
);
1519 char pbuf
[PREFIX_STRLEN
];
1521 prefix2str(prefix
, pbuf
, sizeof(pbuf
));
1523 vnc_zlog_debug_verbose(
1524 "%s: advancing past RHN Entry (q=%p): with prefix %s",
1525 __func__
, cursor
, pbuf
);
1526 print_rhn_list(__func__
, NULL
); /* debug */
1529 rc
= skiplist_next_value(sl
, prefix
, (void *)&pb
, &cursor
);
1531 vnc_zlog_debug_verbose("%s: done", __func__
);
1535 void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
1536 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1537 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1538 const struct prefix
*prefix
, /* VPN prefix */
1539 struct bgp_path_info
*bpi
) /* old VPN host route */
1541 afi_t afi
= family2afi(prefix
->family
);
1542 struct skiplist
*sl
= NULL
;
1543 struct prefix_bag
*pb
;
1545 struct rfapi_cfg
*hc
= NULL
;
1549 char str_pfx
[PREFIX_STRLEN
];
1551 prefix2str(prefix
, str_pfx
, sizeof(str_pfx
));
1553 vnc_zlog_debug_verbose("%s(bgp=%p, nve prefix=%s)", __func__
,
1557 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
)
1560 if (!(hc
= bgp
->rfapi_cfg
)) {
1561 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1566 /* check vnc redist flag for bgp direct routes */
1567 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1568 vnc_zlog_debug_verbose(
1569 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1574 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1575 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1581 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1584 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1589 if (!is_host_prefix(prefix
)) {
1590 vnc_zlog_debug_verbose("%s: not host route, skip", __func__
);
1595 * Find all entries with key == CE in the RHN list
1597 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1600 struct ecommunity
*ecom
;
1601 struct prefix pfx_unicast_nexthop
;
1603 memset(&pfx_unicast_nexthop
, 0,
1604 sizeof(struct prefix
)); /* keep valgrind happy */
1606 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubpi
, &ecom
,
1607 &pfx_unicast_nexthop
)) {
1609 vnc_zlog_debug_verbose(
1610 "%s: process_unicast_route error, skipping",
1618 if (vnc_prefix_cmp(&pfx_unicast_nexthop
, prefix
)) {
1619 char str_unh
[PREFIX_STRLEN
];
1620 char str_nve_pfx
[PREFIX_STRLEN
];
1622 prefix2str(&pfx_unicast_nexthop
, str_unh
,
1624 prefix2str(prefix
, str_nve_pfx
, sizeof(str_nve_pfx
));
1626 vnc_zlog_debug_verbose(
1627 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %s != nve pfx %s",
1628 __func__
, str_unh
, str_nve_pfx
);
1632 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1633 bgp
, afi
, bpi
, prd
, &pb
->upfx
);
1636 ecommunity_free(&ecom
);
1638 rc
= skiplist_next_value(sl
, prefix
, (void *)&pb
, &cursor
);
1643 /***********************************************************************
1645 ***********************************************************************/
1647 #define DEBUG_IS_USABLE_INTERIOR 1
1649 static int is_usable_interior_route(struct bgp_path_info
*bpi_interior
)
1651 if (!VALID_INTERIOR_TYPE(bpi_interior
->type
)) {
1652 #if DEBUG_IS_USABLE_INTERIOR
1653 vnc_zlog_debug_verbose(
1654 "%s: NO: type %d is not valid interior type", __func__
,
1655 bpi_interior
->type
);
1659 if (!CHECK_FLAG(bpi_interior
->flags
, BGP_PATH_VALID
)) {
1660 #if DEBUG_IS_USABLE_INTERIOR
1661 vnc_zlog_debug_verbose("%s: NO: BGP_PATH_VALID not set",
1670 * There should be only one of these per prefix at a time.
1671 * This should be called as a result of selection operation
1673 * NB should be called espacially for bgp instances that are named,
1674 * because the exterior routes will always come from one of those.
1675 * We filter here on the instance name to make sure we get only the
1678 static void vnc_import_bgp_exterior_add_route_it(
1679 struct bgp
*bgp
, /* exterior instance, we hope */
1680 const struct prefix
*prefix
, /* unicast prefix */
1681 struct bgp_path_info
*info
, /* unicast info */
1682 struct rfapi_import_table
*it_only
) /* NULL, or limit to this IT */
1685 struct rfapi_cfg
*hc
;
1686 struct prefix pfx_orig_nexthop
;
1687 struct rfapi_import_table
*it
;
1688 struct bgp
*bgp_default
= bgp_get_default();
1689 afi_t afi
= family2afi(prefix
->family
);
1694 h
= bgp_default
->rfapi
;
1695 hc
= bgp_default
->rfapi_cfg
;
1697 vnc_zlog_debug_verbose("%s: entry with it=%p", __func__
, it_only
);
1700 vnc_zlog_debug_verbose(
1701 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1705 if (!hc
->redist_bgp_exterior_view
) {
1706 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1710 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1711 vnc_zlog_debug_verbose(
1712 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1713 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1717 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1718 vnc_zlog_debug_verbose(
1719 "%s: redist of exterior routes not enabled, skipping",
1725 * Extract nexthop from exterior route
1727 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1728 * but if v4 it is in attr->nexthop
1730 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1732 for (it
= h
->imports
; it
; it
= it
->next
) {
1733 struct agg_table
*table
;
1734 struct agg_node
*rn
;
1735 struct agg_node
*par
;
1736 struct bgp_path_info
*bpi_interior
;
1737 int have_usable_route
;
1739 vnc_zlog_debug_verbose("%s: doing it %p", __func__
, it
);
1741 if (it_only
&& (it_only
!= it
)) {
1742 vnc_zlog_debug_verbose("%s: doesn't match it_only %p",
1747 table
= it
->imported_vpn
[afi
];
1749 for (rn
= agg_node_match(table
, &pfx_orig_nexthop
),
1750 have_usable_route
= 0;
1751 (!have_usable_route
) && rn
;) {
1753 vnc_zlog_debug_verbose("%s: it %p trying rn %p",
1756 for (bpi_interior
= rn
->info
; bpi_interior
;
1757 bpi_interior
= bpi_interior
->next
) {
1758 struct prefix_rd
*prd
;
1759 struct attr new_attr
;
1762 if (!is_usable_interior_route(bpi_interior
))
1765 vnc_zlog_debug_verbose(
1766 "%s: usable: bpi_interior %p", __func__
,
1770 * have a legitimate route to exterior's nexthop
1773 * Import unicast route to the import table
1775 have_usable_route
= 1;
1777 if (bpi_interior
->extra
) {
1778 prd
= &bpi_interior
->extra
->vnc
.import
1780 label
= decode_label(
1781 &bpi_interior
->extra
->label
[0]);
1785 /* use local_pref from unicast route */
1786 memset(&new_attr
, 0, sizeof(struct attr
));
1787 new_attr
= *bpi_interior
->attr
;
1788 if (info
->attr
->flag
1789 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
1790 new_attr
.local_pref
=
1791 info
->attr
->local_pref
;
1792 new_attr
.flag
|= ATTR_FLAG_BIT(
1793 BGP_ATTR_LOCAL_PREF
);
1796 rfapiBgpInfoFilteredImportVPN(
1797 it
, FIF_ACTION_UPDATE
,
1798 bpi_interior
->peer
, NULL
, /* rfd */
1799 prefix
, NULL
, afi
, prd
, &new_attr
,
1800 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1801 BGP_ROUTE_REDISTRIBUTE
, &label
);
1804 if (have_usable_route
) {
1808 * TBD factor this out into its own function
1810 struct prefix
*pfx_mon
= prefix_new();
1811 if (!RFAPI_MONITOR_EXTERIOR(rn
)->source
) {
1812 RFAPI_MONITOR_EXTERIOR(rn
)->source
=
1816 agg_lock_node(rn
); /* for skiplist */
1818 agg_lock_node(rn
); /* for skiplist entry */
1819 prefix_copy(pfx_mon
, prefix
);
1820 if (!skiplist_insert(
1821 RFAPI_MONITOR_EXTERIOR(rn
)->source
,
1824 bgp_path_info_lock(info
);
1827 par
= agg_node_parent(rn
);
1830 agg_unlock_node(rn
);
1834 agg_unlock_node(rn
);
1836 if (!have_usable_route
) {
1837 struct prefix
*pfx_mon
= prefix_new();
1838 prefix_copy(pfx_mon
, prefix
);
1839 if (!skiplist_insert(it
->monitor_exterior_orphans
, info
,
1842 bgp_path_info_lock(info
);
1848 void vnc_import_bgp_exterior_add_route(
1849 struct bgp
*bgp
, /* exterior instance, we hope */
1850 const struct prefix
*prefix
, /* unicast prefix */
1851 struct bgp_path_info
*info
) /* unicast info */
1853 vnc_import_bgp_exterior_add_route_it(bgp
, prefix
, info
, NULL
);
1857 * There should be only one of these per prefix at a time.
1858 * This should probably be called as a result of selection operation.
1860 * NB should be called espacially for bgp instances that are named,
1861 * because the exterior routes will always come from one of those.
1862 * We filter here on the instance name to make sure we get only the
1865 void vnc_import_bgp_exterior_del_route(
1866 struct bgp
*bgp
, const struct prefix
*prefix
, /* unicast prefix */
1867 struct bgp_path_info
*info
) /* unicast info */
1870 struct rfapi_cfg
*hc
;
1871 struct rfapi_import_table
*it
;
1872 struct prefix pfx_orig_nexthop
;
1873 afi_t afi
= family2afi(prefix
->family
);
1874 struct bgp
*bgp_default
= bgp_get_default();
1879 memset(&pfx_orig_nexthop
, 0,
1880 sizeof(struct prefix
)); /* keep valgrind happy */
1882 h
= bgp_default
->rfapi
;
1883 hc
= bgp_default
->rfapi_cfg
;
1886 vnc_zlog_debug_verbose(
1887 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1891 if (!hc
->redist_bgp_exterior_view
) {
1892 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1896 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1897 vnc_zlog_debug_verbose(
1898 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1899 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1902 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1903 vnc_zlog_debug_verbose(
1904 "%s: redist of exterior routes no enabled, skipping",
1910 * Extract nexthop from exterior route
1912 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1913 * but if v4 it is in attr->nexthop
1915 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1917 for (it
= h
->imports
; it
; it
= it
->next
) {
1918 struct agg_table
*table
;
1919 struct agg_node
*rn
;
1920 struct agg_node
*par
;
1921 struct bgp_path_info
*bpi_interior
;
1922 int have_usable_route
;
1924 table
= it
->imported_vpn
[afi
];
1926 for (rn
= agg_node_match(table
, &pfx_orig_nexthop
),
1927 have_usable_route
= 0;
1928 (!have_usable_route
) && rn
;) {
1930 for (bpi_interior
= rn
->info
; bpi_interior
;
1931 bpi_interior
= bpi_interior
->next
) {
1932 struct prefix_rd
*prd
;
1935 if (!is_usable_interior_route(bpi_interior
))
1939 * have a legitimate route to exterior's nexthop
1942 * Import unicast route to the import table
1944 have_usable_route
= 1;
1946 if (bpi_interior
->extra
) {
1947 prd
= &bpi_interior
->extra
->vnc
.import
1949 label
= decode_label(
1950 &bpi_interior
->extra
->label
[0]);
1954 rfapiBgpInfoFilteredImportVPN(
1955 it
, FIF_ACTION_KILL
, bpi_interior
->peer
,
1957 prefix
, NULL
, afi
, prd
,
1959 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1960 BGP_ROUTE_REDISTRIBUTE
, &label
);
1965 * TBD factor this out into its own function
1968 if (RFAPI_MONITOR_EXTERIOR(rn
)
1970 if (!skiplist_delete(
1971 RFAPI_MONITOR_EXTERIOR(
1976 bgp_path_info_unlock(
1983 RFAPI_MONITOR_EXTERIOR(
1987 RFAPI_MONITOR_EXTERIOR(
1990 RFAPI_MONITOR_EXTERIOR(
2001 par
= agg_node_parent(rn
);
2004 agg_unlock_node(rn
);
2008 agg_unlock_node(rn
);
2010 if (!have_usable_route
) {
2011 if (!skiplist_delete(it
->monitor_exterior_orphans
, info
,
2014 bgp_path_info_unlock(info
);
2021 * This function should be called after a new interior VPN route
2022 * has been added to an import_table.
2024 * NB should also be called whenever an existing vpn interior route
2025 * becomes valid (e.g., valid_interior_count is inremented)
2027 void vnc_import_bgp_exterior_add_route_interior(
2028 struct bgp
*bgp
, struct rfapi_import_table
*it
,
2029 struct agg_node
*rn_interior
, /* VPN IT node */
2030 struct bgp_path_info
*bpi_interior
) /* VPN IT route */
2032 const struct prefix
*p
= agg_node_get_prefix(rn_interior
);
2033 afi_t afi
= family2afi(p
->family
);
2034 struct agg_node
*par
;
2035 struct bgp_path_info
*bpi_exterior
;
2036 struct prefix
*pfx_exterior
; /* exterior pfx */
2039 struct list
*list_adopted
;
2041 vnc_zlog_debug_verbose("%s: entry", __func__
);
2043 if (!is_usable_interior_route(bpi_interior
)) {
2044 vnc_zlog_debug_verbose(
2045 "%s: not usable interior route, skipping", __func__
);
2049 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2050 vnc_zlog_debug_verbose(
2051 "%s: redist of exterior routes no enabled, skipping",
2056 if (it
== bgp
->rfapi
->it_ce
) {
2057 vnc_zlog_debug_verbose("%s: import table is it_ce, skipping",
2063 vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
2064 __func__
, rn_interior
, bpi_interior
->type
);
2066 if (RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
2068 int count
= 0; /* debugging */
2070 vnc_zlog_debug_verbose(
2071 "%s: has exterior monitor; ext src: %p", __func__
,
2072 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2075 * There is a monitor here already. Therefore, we do not need
2076 * to do any pulldown. Just construct exterior routes based
2077 * on the new interior route.
2080 for (rc
= skiplist_next(
2081 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2082 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2084 !rc
; rc
= skiplist_next(
2085 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2086 (void **)&bpi_exterior
,
2087 (void **)&pfx_exterior
, &cursor
)) {
2089 struct prefix_rd
*prd
;
2090 struct attr new_attr
;
2094 ++count
; /* debugging */
2096 assert(bpi_exterior
);
2097 assert(pfx_exterior
);
2099 if (bpi_interior
->extra
) {
2100 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2101 label
= decode_label(
2102 &bpi_interior
->extra
->label
[0]);
2106 /* use local_pref from unicast route */
2107 memset(&new_attr
, 0, sizeof(struct attr
));
2108 new_attr
= *bpi_interior
->attr
;
2110 && (bpi_exterior
->attr
->flag
2111 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2112 new_attr
.local_pref
=
2113 bpi_exterior
->attr
->local_pref
;
2115 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2118 rfapiBgpInfoFilteredImportVPN(
2119 it
, FIF_ACTION_UPDATE
, bpi_interior
->peer
,
2121 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2122 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2123 BGP_ROUTE_REDISTRIBUTE
, &label
);
2125 vnc_zlog_debug_verbose(
2126 "%s: finished constructing exteriors based on existing monitors",
2131 vnc_zlog_debug_verbose("%s: no exterior monitor", __func__
);
2134 * No monitor at this node. Is this the first valid interior
2135 * route at this node?
2137 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
> 1) {
2138 vnc_zlog_debug_verbose(
2139 "%s: new interior route not first valid one, skipping pulldown",
2145 * Look up the tree for possible pulldown candidates.
2146 * Find nearest parent with an exterior route monitor
2148 for (par
= agg_node_parent(rn_interior
); par
;
2149 par
= agg_node_parent(par
)) {
2150 if (RFAPI_HAS_MONITOR_EXTERIOR(par
))
2156 vnc_zlog_debug_verbose(
2157 "%s: checking parent %p for possible pulldowns",
2160 /* check monitors at par for possible pulldown */
2162 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2163 (void **)&bpi_exterior
,
2164 (void **)&pfx_exterior
, &cursor
);
2166 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2167 (void **)&bpi_exterior
,
2168 (void **)&pfx_exterior
, &cursor
)) {
2170 struct prefix pfx_nexthop
;
2172 memset(&pfx_nexthop
, 0,
2173 sizeof(struct prefix
)); /* keep valgrind happy */
2175 /* check original nexthop for prefix match */
2176 rfapiUnicastNexthop2Prefix(afi
, bpi_exterior
->attr
,
2179 if (prefix_match(p
, &pfx_nexthop
)) {
2181 struct bgp_path_info
*bpi
;
2182 struct prefix_rd
*prd
;
2183 struct attr new_attr
;
2189 * add monitor to longer prefix
2191 struct prefix
*pfx_mon
= prefix_new();
2192 prefix_copy(pfx_mon
, pfx_exterior
);
2193 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)
2195 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2196 ->source
= skiplist_new(
2197 0, NULL
, prefix_free_lists
);
2198 agg_lock_node(rn_interior
);
2201 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2203 bpi_exterior
, pfx_mon
);
2204 agg_lock_node(rn_interior
);
2207 * Delete constructed exterior routes based on
2210 for (bpi
= par
->info
; bpi
; bpi
= bpi
->next
) {
2213 prd
= &bpi
->extra
->vnc
.import
2215 label
= decode_label(
2216 &bpi
->extra
->label
[0]);
2220 rfapiBgpInfoFilteredImportVPN(
2221 it
, FIF_ACTION_KILL
, bpi
->peer
,
2223 pfx_exterior
, NULL
, afi
, prd
,
2225 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2226 BGP_ROUTE_REDISTRIBUTE
, &label
);
2231 * Add constructed exterior routes based on
2232 * the new interior route at longer prefix.
2234 if (bpi_interior
->extra
) {
2235 prd
= &bpi_interior
->extra
->vnc
.import
2237 label
= decode_label(
2238 &bpi_interior
->extra
->label
[0]);
2242 /* use local_pref from unicast route */
2243 memset(&new_attr
, 0, sizeof(struct attr
));
2244 new_attr
= *bpi_interior
->attr
;
2246 && (bpi_exterior
->attr
->flag
2247 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2248 new_attr
.local_pref
=
2249 bpi_exterior
->attr
->local_pref
;
2250 new_attr
.flag
|= ATTR_FLAG_BIT(
2251 BGP_ATTR_LOCAL_PREF
);
2254 rfapiBgpInfoFilteredImportVPN(
2255 it
, FIF_ACTION_UPDATE
,
2256 bpi_interior
->peer
, NULL
, /* rfd */
2257 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2258 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2259 BGP_ROUTE_REDISTRIBUTE
, &label
);
2264 * The only monitors at rn_interior are the ones we added just
2265 * above, so we can use the rn_interior list to identify which
2266 * monitors to delete from the parent.
2269 for (rc
= skiplist_next(
2270 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2271 (void **)&bpi_exterior
, NULL
, &cursor
);
2272 !rc
; rc
= skiplist_next(
2273 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2274 (void **)&bpi_exterior
, NULL
, &cursor
)) {
2277 skiplist_delete(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2278 bpi_exterior
, NULL
);
2279 agg_unlock_node(par
); /* sl entry */
2281 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par
)->source
)) {
2282 skiplist_free(RFAPI_MONITOR_EXTERIOR(par
)->source
);
2283 RFAPI_MONITOR_EXTERIOR(par
)->source
= NULL
;
2284 agg_unlock_node(par
); /* sl itself */
2288 vnc_zlog_debug_verbose("%s: checking orphans", __func__
);
2291 * See if any orphans can be pulled down to the current node
2294 list_adopted
= NULL
;
2295 for (rc
= skiplist_next(it
->monitor_exterior_orphans
,
2296 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2298 !rc
; rc
= skiplist_next(it
->monitor_exterior_orphans
,
2299 (void **)&bpi_exterior
,
2300 (void **)&pfx_exterior
, &cursor
)) {
2302 struct prefix pfx_nexthop
;
2303 char buf
[PREFIX_STRLEN
];
2304 afi_t afi_exterior
= family2afi(pfx_exterior
->family
);
2306 prefix2str(pfx_exterior
, buf
, sizeof(buf
));
2307 vnc_zlog_debug_verbose(
2308 "%s: checking exterior orphan at prefix %s", __func__
,
2311 if (afi_exterior
!= afi
) {
2312 vnc_zlog_debug_verbose(
2313 "%s: exterior orphan afi %d != interior afi %d, skip",
2314 __func__
, afi_exterior
, afi
);
2318 /* check original nexthop for prefix match */
2319 rfapiUnicastNexthop2Prefix(afi
, bpi_exterior
->attr
,
2322 if (prefix_match(p
, &pfx_nexthop
)) {
2324 struct prefix_rd
*prd
;
2325 struct attr new_attr
;
2331 * add monitor to longer prefix
2334 struct prefix
*pfx_mon
= prefix_new();
2335 prefix_copy(pfx_mon
, pfx_exterior
);
2336 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
) {
2337 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
=
2339 0, NULL
, prefix_free_lists
);
2340 agg_lock_node(rn_interior
); /* sl */
2343 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2344 bpi_exterior
, pfx_mon
);
2345 agg_lock_node(rn_interior
); /* sl entry */
2346 if (!list_adopted
) {
2347 list_adopted
= list_new();
2349 listnode_add(list_adopted
, bpi_exterior
);
2352 * Add constructed exterior routes based on the
2353 * new interior route at the longer prefix.
2355 if (bpi_interior
->extra
) {
2356 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2357 label
= decode_label(
2358 &bpi_interior
->extra
->label
[0]);
2362 /* use local_pref from unicast route */
2363 memset(&new_attr
, 0, sizeof(struct attr
));
2364 new_attr
= *bpi_interior
->attr
;
2366 && (bpi_exterior
->attr
->flag
2367 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2368 new_attr
.local_pref
=
2369 bpi_exterior
->attr
->local_pref
;
2371 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2374 rfapiBgpInfoFilteredImportVPN(
2375 it
, FIF_ACTION_UPDATE
, bpi_interior
->peer
,
2377 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2378 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2379 BGP_ROUTE_REDISTRIBUTE
, &label
);
2383 struct listnode
*node
;
2384 struct agg_node
*an_bpi_exterior
;
2386 for (ALL_LIST_ELEMENTS_RO(list_adopted
, node
,
2388 skiplist_delete(it
->monitor_exterior_orphans
,
2389 an_bpi_exterior
, NULL
);
2391 list_delete(&list_adopted
);
2396 * This function should be called after an interior VPN route
2397 * has been deleted from an import_table.
2398 * bpi_interior must still be valid, but it must already be detached
2399 * from its route node and the route node's valid_interior_count
2400 * must already be decremented.
2402 * NB should also be called whenever an existing vpn interior route
2403 * becomes invalid (e.g., valid_interior_count is decremented)
2405 void vnc_import_bgp_exterior_del_route_interior(
2406 struct bgp
*bgp
, struct rfapi_import_table
*it
,
2407 struct agg_node
*rn_interior
, /* VPN IT node */
2408 struct bgp_path_info
*bpi_interior
) /* VPN IT route */
2410 const struct prefix
*p
= agg_node_get_prefix(rn_interior
);
2411 afi_t afi
= family2afi(p
->family
);
2412 struct agg_node
*par
;
2413 struct bgp_path_info
*bpi_exterior
;
2414 struct prefix
*pfx_exterior
; /* exterior pfx */
2418 if (!VALID_INTERIOR_TYPE(bpi_interior
->type
)) {
2419 vnc_zlog_debug_verbose(
2420 "%s: type %d not valid interior type, skipping",
2421 __func__
, bpi_interior
->type
);
2425 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2426 vnc_zlog_debug_verbose(
2427 "%s: redist of exterior routes no enabled, skipping",
2432 if (it
== bgp
->rfapi
->it_ce
) {
2433 vnc_zlog_debug_verbose("%s: it is it_ce, skipping", __func__
);
2437 /* If no exterior routes depend on this prefix, nothing to do */
2438 if (!RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
2439 vnc_zlog_debug_verbose("%s: no exterior monitor, skipping",
2445 vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
2446 __func__
, rn_interior
, bpi_interior
->type
);
2449 * Remove constructed routes based on the deleted interior route
2452 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2453 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2456 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2457 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2460 struct prefix_rd
*prd
;
2463 if (bpi_interior
->extra
) {
2464 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2465 label
= decode_label(&bpi_interior
->extra
->label
[0]);
2469 rfapiBgpInfoFilteredImportVPN(
2470 it
, FIF_ACTION_KILL
, bpi_interior
->peer
, NULL
, /* rfd */
2471 pfx_exterior
, NULL
, afi
, prd
, bpi_interior
->attr
,
2472 ZEBRA_ROUTE_BGP_DIRECT_EXT
, BGP_ROUTE_REDISTRIBUTE
,
2477 * If there are no remaining valid interior routes at this prefix,
2478 * we need to look up the tree for a possible node to move monitors to
2480 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
) {
2481 vnc_zlog_debug_verbose(
2482 "%s: interior routes still present, skipping",
2488 * Find nearest parent with at least one valid interior route
2489 * If none is found, par will end up NULL, and we will move
2490 * the monitors to the orphan list for this import table
2492 for (par
= agg_node_parent(rn_interior
); par
;
2493 par
= agg_node_parent(par
)) {
2494 if (RFAPI_MONITOR_EXTERIOR(par
)->valid_interior_count
)
2498 vnc_zlog_debug_verbose("%s: par=%p, ext src: %p", __func__
, par
,
2499 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2501 /* move all monitors */
2503 * We will use and delete every element of the source skiplist
2505 while (!skiplist_first(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2506 (void **)&bpi_exterior
,
2507 (void **)&pfx_exterior
)) {
2509 struct prefix
*pfx_mon
= prefix_new();
2511 prefix_copy(pfx_mon
, pfx_exterior
);
2515 struct bgp_path_info
*bpi
;
2518 * Add monitor to parent node
2520 if (!RFAPI_MONITOR_EXTERIOR(par
)->source
) {
2521 RFAPI_MONITOR_EXTERIOR(par
)->source
=
2523 0, NULL
, prefix_free_lists
);
2524 agg_lock_node(par
); /* sl */
2526 skiplist_insert(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2527 bpi_exterior
, pfx_mon
);
2528 agg_lock_node(par
); /* sl entry */
2530 /* Add constructed exterior routes based on parent */
2531 for (bpi
= par
->info
; bpi
; bpi
= bpi
->next
) {
2533 struct prefix_rd
*prd
;
2534 struct attr new_attr
;
2537 if (bpi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
)
2541 prd
= &bpi
->extra
->vnc
.import
.rd
;
2542 label
= decode_label(
2543 &bpi
->extra
->label
[0]);
2547 /* use local_pref from unicast route */
2548 memset(&new_attr
, 0, sizeof(struct attr
));
2549 new_attr
= *bpi
->attr
;
2551 && (bpi_exterior
->attr
->flag
2552 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2553 new_attr
.local_pref
=
2554 bpi_exterior
->attr
->local_pref
;
2555 new_attr
.flag
|= ATTR_FLAG_BIT(
2556 BGP_ATTR_LOCAL_PREF
);
2559 rfapiBgpInfoFilteredImportVPN(
2560 it
, FIF_ACTION_UPDATE
, bpi
->peer
,
2562 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2563 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2564 BGP_ROUTE_REDISTRIBUTE
, &label
);
2570 * No interior route for exterior's nexthop. Save
2572 * in orphan list to await future route.
2574 skiplist_insert(it
->monitor_exterior_orphans
,
2575 bpi_exterior
, pfx_mon
);
2578 skiplist_delete_first(
2579 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2580 agg_unlock_node(rn_interior
); /* sl entry */
2582 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
)) {
2583 skiplist_free(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2584 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
= NULL
;
2585 agg_unlock_node(rn_interior
); /* sl itself */
2589 /***********************************************************************
2590 * Generic add/delete unicast routes
2591 ***********************************************************************/
2593 void vnc_import_bgp_add_route(struct bgp
*bgp
, const struct prefix
*prefix
,
2594 struct bgp_path_info
*info
)
2596 afi_t afi
= family2afi(prefix
->family
);
2598 if (VNC_DEBUG(VERBOSE
)) {
2599 struct prefix pfx_nexthop
;
2600 char buf
[PREFIX_STRLEN
];
2601 char buf_nh
[PREFIX_STRLEN
];
2603 prefix2str(prefix
, buf
, sizeof(buf
));
2604 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2605 prefix2str(&pfx_nexthop
, buf_nh
, sizeof(buf_nh
));
2607 vnc_zlog_debug_verbose("%s: pfx %s, nh %s", __func__
, buf
,
2611 print_rhn_list(__func__
, "ENTER ");
2616 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
2621 if (!bgp
->rfapi_cfg
) {
2622 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2627 /* check vnc redist flag for bgp direct routes */
2628 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2629 vnc_zlog_debug_verbose(
2630 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
2631 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2635 switch (bgp
->rfapi_cfg
->redist_mode
) {
2636 case VNC_REDIST_MODE_PLAIN
:
2637 vnc_import_bgp_add_route_mode_plain(bgp
, prefix
, info
);
2640 case VNC_REDIST_MODE_RFG
:
2641 if (bgp
->rfapi_cfg
->rfg_redist
)
2642 vnc_import_bgp_add_route_mode_nvegroup(
2643 bgp
, prefix
, info
, bgp
->rfapi_cfg
->rfg_redist
);
2645 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2649 case VNC_REDIST_MODE_RESOLVE_NVE
:
2650 vnc_import_bgp_add_route_mode_resolve_nve(bgp
, prefix
, info
);
2654 print_rhn_list(__func__
, "LEAVE ");
2660 * "Withdrawing a Route" import process
2662 void vnc_import_bgp_del_route(struct bgp
*bgp
, const struct prefix
*prefix
,
2663 struct bgp_path_info
*info
) /* unicast info */
2665 afi_t afi
= family2afi(prefix
->family
);
2670 struct prefix pfx_nexthop
;
2671 char buf
[PREFIX_STRLEN
];
2672 char buf_nh
[PREFIX_STRLEN
];
2674 prefix2str(prefix
, buf
, sizeof(buf
));
2675 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2676 prefix2str(&pfx_nexthop
, buf_nh
, sizeof(buf_nh
));
2678 vnc_zlog_debug_verbose("%s: pfx %s, nh %s", __func__
, buf
,
2682 print_rhn_list(__func__
, "ENTER ");
2686 if (!bgp
->rfapi_cfg
) {
2687 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2692 /* check bgp redist flag for vnc direct ("vpn") routes */
2693 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2694 vnc_zlog_debug_verbose(
2695 "%s: bgp redistribution of afi=%d VNC direct routes is off",
2700 switch (bgp
->rfapi_cfg
->redist_mode
) {
2701 case VNC_REDIST_MODE_PLAIN
:
2702 vnc_import_bgp_del_route_mode_plain(bgp
, prefix
, info
);
2705 case VNC_REDIST_MODE_RFG
:
2706 if (bgp
->rfapi_cfg
->rfg_redist
)
2707 vnc_import_bgp_del_route_mode_nvegroup(bgp
, prefix
,
2710 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2714 case VNC_REDIST_MODE_RESOLVE_NVE
:
2715 vnc_import_bgp_del_route_mode_resolve_nve(bgp
, afi
, prefix
,
2720 print_rhn_list(__func__
, "LEAVE ");
2726 /***********************************************************************
2728 ***********************************************************************/
2730 void vnc_import_bgp_redist_enable(struct bgp
*bgp
, afi_t afi
)
2732 /* iterate over bgp unicast v4 and v6 routes, call
2733 * vnc_import_bgp_add_route */
2735 struct bgp_node
*rn
;
2737 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
2739 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2740 vnc_zlog_debug_verbose(
2741 "%s: already enabled for afi %d, skipping", __func__
,
2745 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 1;
2747 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); rn
;
2748 rn
= bgp_route_next(rn
)) {
2750 struct bgp_path_info
*bpi
;
2752 for (bpi
= bgp_node_get_bgp_path_info(rn
); bpi
;
2755 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2758 vnc_import_bgp_add_route(bgp
, bgp_node_get_prefix(rn
),
2762 vnc_zlog_debug_verbose(
2763 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2764 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2767 void vnc_import_bgp_exterior_redist_enable(struct bgp
*bgp
, afi_t afi
)
2769 struct bgp
*bgp_exterior
;
2770 struct bgp_node
*rn
;
2772 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2774 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2775 vnc_zlog_debug_verbose(
2776 "%s: already enabled for afi %d, skipping", __func__
,
2780 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 1;
2782 if (!bgp_exterior
) {
2783 vnc_zlog_debug_verbose(
2784 "%s: no exterior view set yet, no routes to import yet",
2789 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); rn
;
2790 rn
= bgp_route_next(rn
)) {
2792 struct bgp_path_info
*bpi
;
2794 for (bpi
= bgp_node_get_bgp_path_info(rn
); bpi
;
2797 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2800 vnc_import_bgp_exterior_add_route(
2801 bgp_exterior
, bgp_node_get_prefix(rn
), bpi
);
2804 vnc_zlog_debug_verbose(
2805 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2806 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2810 * This function is for populating a newly-created Import Table
2812 void vnc_import_bgp_exterior_redist_enable_it(
2813 struct bgp
*bgp
, afi_t afi
, struct rfapi_import_table
*it_only
)
2815 struct bgp
*bgp_exterior
;
2816 struct bgp_node
*rn
;
2818 vnc_zlog_debug_verbose("%s: entry", __func__
);
2820 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2822 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2823 vnc_zlog_debug_verbose("%s: not enabled for afi %d, skipping",
2828 if (!bgp_exterior
) {
2829 vnc_zlog_debug_verbose(
2830 "%s: no exterior view set yet, no routes to import yet",
2835 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); rn
;
2836 rn
= bgp_route_next(rn
)) {
2838 struct bgp_path_info
*bpi
;
2840 for (bpi
= bgp_node_get_bgp_path_info(rn
); bpi
;
2843 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2846 vnc_import_bgp_exterior_add_route_it(
2847 bgp_exterior
, bgp_node_get_prefix(rn
), bpi
,
2854 void vnc_import_bgp_redist_disable(struct bgp
*bgp
, afi_t afi
)
2857 * iterate over vpn routes, find routes of type ZEBRA_ROUTE_BGP_DIRECT,
2858 * delete (call timer expire immediately)
2860 struct bgp_node
*rn1
;
2861 struct bgp_node
*rn2
;
2863 vnc_zlog_debug_verbose("%s: entry", __func__
);
2865 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2866 vnc_zlog_debug_verbose(
2867 "%s: already disabled for afi %d, skipping", __func__
,
2873 * Two-level table for SAFI_MPLS_VPN
2874 * Be careful when changing the things we iterate over
2876 for (rn1
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); rn1
;
2877 rn1
= bgp_route_next(rn1
)) {
2878 const struct prefix
*rn1_p
;
2880 if (!bgp_node_has_bgp_path_info_data(rn1
))
2883 rn1_p
= bgp_node_get_prefix(rn1
);
2884 for (rn2
= bgp_table_top(bgp_node_get_bgp_table_info(rn1
)); rn2
;
2885 rn2
= bgp_route_next(rn2
)) {
2886 const struct prefix
*rn2_p
= bgp_node_get_prefix(rn2
);
2887 struct bgp_path_info
*bpi
;
2888 struct bgp_path_info
*nextbpi
;
2890 for (bpi
= bgp_node_get_bgp_path_info(rn2
); bpi
;
2893 nextbpi
= bpi
->next
;
2895 if (bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
)
2898 struct rfapi_descriptor
*rfd
;
2899 vncHDBgpDirect
.peer
= bpi
->peer
;
2903 rfd
= bpi
->extra
->vnc
.export
.rfapi_handle
;
2905 vnc_zlog_debug_verbose(
2906 "%s: deleting bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]",
2907 __func__
, bpi
, bpi
->peer
, bpi
->type
,
2909 (bpi
->extra
? bpi
->extra
->vnc
.export
2914 del_vnc_route(rfd
, bpi
->peer
, bgp
,
2915 SAFI_MPLS_VPN
, rn2_p
,
2916 (struct prefix_rd
*)rn1_p
,
2917 bpi
->type
, bpi
->sub_type
, NULL
,
2920 vncHDBgpDirect
.peer
= NULL
;
2924 /* Clear RHN list */
2925 if (bgp
->rfapi
->resolve_nve_nexthop
) {
2926 struct prefix_bag
*pb
;
2927 struct bgp_path_info
*info
;
2928 while (!skiplist_first(bgp
->rfapi
->resolve_nve_nexthop
, NULL
,
2931 skiplist_delete_first(bgp
->rfapi
->resolve_nve_nexthop
);
2932 bgp_path_info_unlock(info
);
2936 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 0;
2937 vnc_zlog_debug_verbose("%s: return", __func__
);
2941 void vnc_import_bgp_exterior_redist_disable(struct bgp
*bgp
, afi_t afi
)
2943 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
2944 struct bgp
*bgp_exterior
= hc
->redist_bgp_exterior_view
;
2946 vnc_zlog_debug_verbose("%s: entry", __func__
);
2948 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2949 vnc_zlog_debug_verbose(
2950 "%s: already disabled for afi %d, skipping", __func__
,
2955 if (!bgp_exterior
) {
2956 vnc_zlog_debug_verbose(
2957 "%s: bgp exterior view not defined, skipping",
2964 struct bgp_node
*rn
;
2965 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]);
2966 rn
; rn
= bgp_route_next(rn
)) {
2968 struct bgp_path_info
*bpi
;
2970 for (bpi
= bgp_node_get_bgp_path_info(rn
); bpi
;
2973 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2976 vnc_import_bgp_exterior_del_route(
2977 bgp_exterior
, bgp_node_get_prefix(rn
),
2982 print_rhn_list(__func__
, NULL
);
2986 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 0;
2987 vnc_zlog_debug_verbose("%s: return", __func__
);