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/table.h"
31 #include "lib/memory.h"
32 #include "lib/linklist.h"
33 #include "lib/plist.h"
34 #include "lib/routemap.h"
36 #include "bgpd/bgpd.h"
37 #include "bgpd/bgp_ecommunity.h"
38 #include "bgpd/bgp_attr.h"
39 #include "bgpd/bgp_route.h"
40 #include "bgpd/bgp_mplsvpn.h" /* for RD_TYPE_IP */
42 #include "bgpd/rfapi/vnc_export_bgp.h"
43 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
44 #include "bgpd/rfapi/rfapi.h"
45 #include "bgpd/rfapi/rfapi_import.h"
46 #include "bgpd/rfapi/rfapi_private.h"
47 #include "bgpd/rfapi/rfapi_monitor.h"
48 #include "bgpd/rfapi/rfapi_vty.h"
49 #include "bgpd/rfapi/vnc_import_bgp.h"
50 #include "bgpd/rfapi/vnc_import_bgp_p.h"
51 #include "bgpd/rfapi/vnc_debug.h"
53 #define ENABLE_VNC_RHNCK
55 #define DEBUG_RHN_LIST 0
57 static struct rfapi_descriptor vncHDBgpDirect
; /* dummy nve descriptor */
58 static struct rfapi_descriptor vncHDResolveNve
; /* dummy nve descriptor */
61 * For routes from another AS:
64 * LOCAL_PREF = 255 - MIN(255, MED)
66 * LOCAL_PREF = default_local_pref
68 * For routes from the same AS:
70 * LOCAL_PREF unchanged
72 uint32_t calc_local_pref(struct attr
*attr
, struct peer
*peer
)
74 uint32_t local_pref
= 0;
78 return peer
->bgp
->default_local_pref
;
80 return bgp_get_default()->default_local_pref
;
83 if (peer
&& (peer
->as
!= peer
->bgp
->as
)) {
84 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
85 if (attr
->med
> 255) {
88 local_pref
= 255 - attr
->med
;
91 local_pref
= peer
->bgp
->default_local_pref
;
94 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
95 local_pref
= attr
->local_pref
;
97 if (peer
&& peer
->bgp
) {
98 local_pref
= peer
->bgp
->default_local_pref
;
106 static int is_host_prefix(struct prefix
*p
)
110 return (p
->prefixlen
== 32);
112 return (p
->prefixlen
== 128);
117 /***********************************************************************
119 ***********************************************************************/
122 struct prefix hpfx
; /* ce address = unicast nexthop */
123 struct prefix upfx
; /* unicast prefix */
124 struct bgp_info
*ubi
; /* unicast route */
127 static const uint8_t maskbit
[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
128 0xf8, 0xfc, 0xfe, 0xff};
130 int vnc_prefix_cmp(void *pfx1
, void *pfx2
)
136 struct prefix
*p1
= pfx1
;
137 struct prefix
*p2
= pfx2
;
139 if (p1
->family
< p2
->family
)
141 if (p1
->family
> p2
->family
)
144 if (p1
->prefixlen
< p2
->prefixlen
)
146 if (p1
->prefixlen
> p2
->prefixlen
)
149 offset
= p1
->prefixlen
/ 8;
150 shift
= p1
->prefixlen
% 8;
151 if (shift
== 0 && offset
) { /* catch aligned case */
156 /* Set both prefix's head pointer. */
157 const uint8_t *pp1
= (const uint8_t *)&p1
->u
.prefix
;
158 const uint8_t *pp2
= (const uint8_t *)&p2
->u
.prefix
;
169 mask
= maskbit
[shift
];
170 if ((*pp1
& mask
) < (*pp2
& mask
))
172 if ((*pp1
& mask
) > (*pp2
& mask
))
178 static void prefix_bag_free(void *pb
)
180 XFREE(MTYPE_RFAPI_PREFIX_BAG
, pb
);
184 static void print_rhn_list(const char *tag1
, const char *tag2
)
188 struct skiplistnode
*p
;
189 struct prefix_bag
*pb
;
192 bgp
= bgp_get_default();
196 sl
= bgp
->frapi
->resolve_nve_nexthop
;
198 vnc_zlog_debug_verbose("%s: %s: RHN List is empty",
199 (tag1
? tag1
: ""), (tag2
? tag2
: ""));
203 vnc_zlog_debug_verbose("%s: %s: RHN list:", (tag1
? tag1
: ""),
206 /* XXX uses secret knowledge of skiplist structure */
207 for (p
= sl
->header
->forward
[0]; p
; p
= p
->forward
[0]) {
208 char kbuf
[PREFIX_STRLEN
];
209 char hbuf
[PREFIX_STRLEN
];
210 char ubuf
[PREFIX_STRLEN
];
214 prefix2str(p
->key
, kbuf
, sizeof(kbuf
));
215 prefix2str(&pb
->hpfx
, hbuf
, sizeof(hbuf
));
216 prefix2str(&pb
->upfx
, ubuf
, sizeof(ubuf
));
218 vnc_zlog_debug_verbose(
219 "RHN Entry %d (q=%p): kpfx=%s, upfx=%s, hpfx=%s, ubi=%p",
220 ++count
, p
, kbuf
, ubuf
, hbuf
, pb
->ubi
);
225 #ifdef ENABLE_VNC_RHNCK
226 static void vnc_rhnck(char *tag
)
230 struct skiplistnode
*p
;
232 bgp
= bgp_get_default();
235 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
240 /* XXX uses secret knowledge of skiplist structure */
241 for (p
= sl
->header
->forward
[0]; p
; p
= p
->forward
[0]) {
242 struct prefix_bag
*pb
;
245 struct prefix pfx_orig_nexthop
;
247 memset(&pfx_orig_nexthop
, 0,
248 sizeof(struct prefix
)); /* keep valgrind happy */
253 afi
= family2afi(pb
->upfx
.family
);
255 rfapiUnicastNexthop2Prefix(afi
, pb
->ubi
->attr
,
258 /* pb->hpfx, pb->ubi nexthop, pkey should all reflect the same
260 assert(!vnc_prefix_cmp(&pb
->hpfx
, pkey
));
261 if (vnc_prefix_cmp(&pb
->hpfx
, &pfx_orig_nexthop
)) {
262 char str_onh
[PREFIX_STRLEN
];
263 char str_nve_pfx
[PREFIX_STRLEN
];
265 prefix2str(&pfx_orig_nexthop
, str_onh
, sizeof(str_onh
));
266 prefix2str(&pb
->hpfx
, str_nve_pfx
, sizeof(str_nve_pfx
));
268 vnc_zlog_debug_verbose(
269 "%s: %s: FATAL: resolve_nve_nexthop list item bi nexthop %s != nve pfx %s",
270 __func__
, tag
, str_onh
, str_nve_pfx
);
274 vnc_zlog_debug_verbose("%s: vnc_rhnck OK", tag
);
277 #define VNC_RHNCK(n) do {char buf[BUFSIZ];sprintf(buf,"%s: %s", __func__, #n);vnc_rhnck(buf);} while (0)
285 /***********************************************************************
286 * Add/Delete Unicast Route
287 ***********************************************************************/
290 * "Adding a Route" import process
294 * extract and package information from the BGP unicast route.
295 * Return code 0 means OK, non-0 means drop.
297 * If return code is 0, caller MUST release ecom
299 static int process_unicast_route(struct bgp
*bgp
, /* in */
301 struct prefix
*prefix
, /* in */
302 struct bgp_info
*info
, /* in */
303 struct ecommunity
**ecom
, /* OUT */
304 struct prefix
*unicast_nexthop
) /* OUT */
306 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
307 struct peer
*peer
= info
->peer
;
308 struct attr
*attr
= info
->attr
;
310 struct route_map
*rmap
= NULL
;
311 struct prefix pfx_orig_nexthop
;
313 memset(&pfx_orig_nexthop
, 0,
314 sizeof(struct prefix
)); /* keep valgrind happy */
319 if (hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
320 vnc_zlog_debug_verbose("%s: HC prefix list is set, checking",
322 if (prefix_list_apply(
323 hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
],
326 vnc_zlog_debug_verbose(
327 "%s: prefix list returns DENY, blocking route",
331 vnc_zlog_debug_verbose(
332 "%s: prefix list returns PASS, allowing route",
336 /* apply routemap, if any, later */
337 rmap
= hc
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
340 * Extract original nexthop, which we expect to be a NVE connected
342 * Note that this is the nexthop before any possible application of
346 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
347 * but if v4 it is in attr->nexthop
349 rfapiUnicastNexthop2Prefix(afi
, attr
, &pfx_orig_nexthop
);
353 * This code is here because it allocates an interned attr which
354 * must be freed before we return. It's easier to put it after
355 * all of the possible returns above.
357 memset(&hattr
, 0, sizeof(struct attr
));
358 bgp_attr_dup(&hattr
, attr
); /* hattr becomes a ghost attr */
361 struct bgp_info info
;
362 route_map_result_t ret
;
364 memset(&info
, 0, sizeof(info
));
367 ret
= route_map_apply(rmap
, prefix
, RMAP_BGP
, &info
);
368 if (ret
== RMAP_DENYMATCH
) {
369 bgp_attr_flush(&hattr
);
370 vnc_zlog_debug_verbose(
371 "%s: route map \"%s\" says DENY, returning",
372 __func__
, rmap
->name
);
378 * Get the (possibly altered by policy) unicast nexthop
379 * for later lookup in the Import Table by caller
381 rfapiUnicastNexthop2Prefix(afi
, &hattr
, unicast_nexthop
);
383 if (hattr
.ecommunity
)
384 *ecom
= ecommunity_dup(hattr
.ecommunity
);
386 *ecom
= ecommunity_new();
389 * Done with hattr, clean up
391 bgp_attr_flush(&hattr
);
394 * Add EC that carries original NH of iBGP route (2 bytes = magic
395 * value indicating it came from an VNC gateway; default 5226, but
396 * must be user configurable). Note that this is the nexthop before
397 * any application of policy.
400 struct ecommunity_val vnc_gateway_magic
;
403 /* Using route origin extended community type */
404 memset(&vnc_gateway_magic
, 0, sizeof(vnc_gateway_magic
));
405 vnc_gateway_magic
.val
[0] = 0x01;
406 vnc_gateway_magic
.val
[1] = 0x03;
408 /* Only works for IPv4 nexthops */
409 if (prefix
->family
== AF_INET
) {
410 memcpy(vnc_gateway_magic
.val
+ 2,
411 &unicast_nexthop
->u
.prefix4
, 4);
413 localadmin
= htons(hc
->resolve_nve_roo_local_admin
);
414 memcpy(vnc_gateway_magic
.val
+ 6, (char *)&localadmin
, 2);
416 ecommunity_add_val(*ecom
, &vnc_gateway_magic
);
423 static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
424 struct bgp
*bgp
, afi_t afi
, struct bgp_info
*bi
, /* VPN bi */
425 struct prefix_rd
*prd
, /* RD */
426 struct prefix
*prefix
, /* unicast route prefix */
427 uint32_t *local_pref
, /* NULL = no local_pref */
428 uint32_t *med
, /* NULL = no med */
429 struct ecommunity
*ecom
) /* generated ecoms */
432 struct prefix nexthop
;
433 struct rfapi_ip_addr nexthop_h
;
436 struct bgp_attr_encap_subtlv
*encaptlvs
;
439 struct rfapi_un_option optary
[3];
440 struct rfapi_un_option
*opt
= NULL
;
443 vnc_zlog_debug_verbose("%s: entry", __func__
);
445 if (bi
->type
!= ZEBRA_ROUTE_BGP
&& bi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
) {
449 if (bi
->sub_type
!= BGP_ROUTE_NORMAL
&& bi
->sub_type
!= BGP_ROUTE_STATIC
450 && bi
->sub_type
!= BGP_ROUTE_RFP
) {
454 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
457 vncHDResolveNve
.peer
= bi
->peer
;
458 if (!rfapiGetVncTunnelUnAddr(bi
->attr
, &un
)) {
459 if (rfapiQprefix2Raddr(&un
, &vncHDResolveNve
.un_addr
))
462 memset(&vncHDResolveNve
.un_addr
, 0,
463 sizeof(vncHDResolveNve
.un_addr
));
466 /* Use nexthop of VPN route as nexthop of constructed route */
467 rfapiNexthop2Prefix(bi
->attr
, &nexthop
);
468 rfapiQprefix2Raddr(&nexthop
, &nexthop_h
);
470 if (rfapiGetVncLifetime(bi
->attr
, &lifetime
)) {
473 plifetime
= &lifetime
;
477 encaptlvs
= bi
->attr
->vnc_subtlvs
;
478 if (bi
->attr
->encap_tunneltype
!= BGP_ENCAP_TYPE_RESERVED
479 && bi
->attr
->encap_tunneltype
!= BGP_ENCAP_TYPE_MPLS
) {
481 opt
->next
= &optary
[cur_opt
];
482 opt
= &optary
[cur_opt
++];
483 memset(opt
, 0, sizeof(struct rfapi_un_option
));
484 opt
->type
= RFAPI_UN_OPTION_TYPE_TUNNELTYPE
;
485 opt
->v
.tunnel
.type
= bi
->attr
->encap_tunneltype
;
486 /* TBD parse bi->attr->extra->encap_subtlvs */
492 struct ecommunity
*new_ecom
= ecommunity_dup(ecom
);
494 if (bi
->attr
&& bi
->attr
->ecommunity
)
495 ecommunity_merge(new_ecom
, bi
->attr
->ecommunity
);
498 label
= decode_label(&bi
->extra
->label
[0]);
500 add_vnc_route(&vncHDResolveNve
, bgp
, SAFI_MPLS_VPN
,
501 prefix
, /* unicast route prefix */
502 prd
, &nexthop_h
, /* new nexthop */
503 local_pref
, plifetime
,
504 (struct bgp_tea_options
*)encaptlvs
, /* RFP options */
505 opt
, NULL
, new_ecom
, med
, /* NULL => don't set med */
506 (label
? &label
: NULL
), /* NULL= default */
507 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
508 RFAPI_AHR_RFPOPT_IS_VNCTLV
); /* flags */
510 ecommunity_free(&new_ecom
);
513 static void vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
514 struct prefix_rd
*prd
, /* RD */
515 struct bgp_table
*table_rd
, /* per-rd VPN route table */
516 afi_t afi
, struct bgp
*bgp
, struct prefix
*prefix
, /* unicast prefix */
517 struct ecommunity
*ecom
, /* generated ecoms */
518 uint32_t *local_pref
, /* NULL = no local_pref */
519 uint32_t *med
, /* NULL = no med */
520 struct prefix
*ubi_nexthop
) /* unicast nexthop */
529 char str_nh
[PREFIX_STRLEN
];
531 prefix2str(ubi_nexthop
, str_nh
, sizeof(str_nh
));
533 vnc_zlog_debug_verbose("%s: ubi_nexthop=%s", __func__
, str_nh
);
537 bn
= bgp_node_lookup(table_rd
, ubi_nexthop
);
539 vnc_zlog_debug_verbose(
540 "%s: no match in RD's table for ubi_nexthop", __func__
);
544 /* Iterate over bgp_info items at this node */
545 for (bi
= bn
->info
; bi
; bi
= bi
->next
) {
547 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
548 bgp
, afi
, bi
, /* VPN bi */
549 prd
, prefix
, local_pref
, med
, ecom
);
555 static void vnc_import_bgp_add_route_mode_resolve_nve(
556 struct bgp
*bgp
, struct prefix
*prefix
, /* unicast prefix */
557 struct bgp_info
*info
) /* unicast info */
559 afi_t afi
= family2afi(prefix
->family
);
560 struct rfapi_cfg
*hc
= NULL
;
562 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
564 struct ecommunity
*ecom
= NULL
;
566 uint32_t *med
= NULL
;
568 struct prefix_bag
*pb
;
569 struct bgp_node
*bnp
; /* prd table node */
572 if (VNC_DEBUG(VERBOSE
)) {
573 char str_pfx
[PREFIX_STRLEN
];
574 char str_nh
[PREFIX_STRLEN
];
577 prefix2str(prefix
, str_pfx
, sizeof(str_pfx
));
580 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &nh
);
582 prefix2str(&nh
, str_nh
, sizeof(str_nh
));
588 vnc_zlog_debug_verbose(
589 "%s(bgp=%p, unicast prefix=%s, unicast nh=%s)",
590 __func__
, bgp
, str_pfx
, str_nh
);
593 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
594 vnc_zlog_debug_verbose(
595 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
596 __func__
, info
->type
, zebra_route_string(info
->type
),
597 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
606 zlog_err("%s: can't get afi of prefix", __func__
);
610 if (!(hc
= 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
);
635 && (info
->attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))) {
637 med
= &info
->attr
->med
;
642 * At this point, we have allocated:
644 * ecom ecommunity ptr, union of unicast and ROO parts (no NVE part)
648 * pfx_unicast_nexthop nexthop of uncast route
651 if (!bgp
->rfapi
->resolve_nve_nexthop
) {
652 bgp
->rfapi
->resolve_nve_nexthop
=
653 skiplist_new(SKIPLIST_FLAG_ALLOW_DUPLICATES
,
654 vnc_prefix_cmp
, prefix_bag_free
);
657 pb
= XCALLOC(MTYPE_RFAPI_PREFIX_BAG
, sizeof(struct prefix_bag
));
658 pb
->hpfx
= pfx_unicast_nexthop
;
662 bgp_info_lock(info
); /* skiplist refers to it */
663 skiplist_insert(bgp
->rfapi
->resolve_nve_nexthop
, &pb
->hpfx
, pb
);
666 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
667 * (exact match, /32). If an exact match is found, call add_vnc_route.
670 for (bnp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bnp
;
671 bnp
= bgp_route_next(bnp
)) {
673 struct bgp_table
*table
;
675 table
= (struct bgp_table
*)(bnp
->info
);
680 vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
681 (struct prefix_rd
*)&bnp
->p
, table
, afi
, bgp
, prefix
,
682 ecom
, &local_pref
, med
, &pfx_unicast_nexthop
);
687 ecommunity_free(&ecom
);
689 vnc_zlog_debug_verbose("%s: done", __func__
);
693 static void vnc_import_bgp_add_route_mode_plain(struct bgp
*bgp
,
694 struct prefix
*prefix
,
695 struct bgp_info
*info
)
697 afi_t afi
= family2afi(prefix
->family
);
698 struct peer
*peer
= info
->peer
;
699 struct attr
*attr
= info
->attr
;
701 struct rfapi_cfg
*hc
= NULL
;
702 struct attr
*iattr
= NULL
;
704 struct rfapi_ip_addr vnaddr
;
705 struct prefix vn_pfx_space
;
706 struct prefix
*vn_pfx
= NULL
;
708 struct ecommunity
*ecom
= NULL
;
709 struct prefix_rd prd
;
710 struct route_map
*rmap
= NULL
;
712 uint32_t *med
= NULL
;
715 char buf
[PREFIX_STRLEN
];
717 prefix2str(prefix
, buf
, sizeof(buf
));
718 vnc_zlog_debug_verbose("%s(prefix=%s) entry", __func__
, buf
);
722 zlog_err("%s: can't get afi of prefix", __func__
);
726 if (!(hc
= bgp
->rfapi_cfg
)) {
727 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
732 /* check vnc redist flag for bgp direct routes */
733 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
734 vnc_zlog_debug_verbose(
735 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
741 * mode "plain" specific code
744 vnc_zlog_debug_verbose("%s: NOT using redist RFG", __func__
);
749 if (hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
750 vnc_zlog_debug_verbose(
751 "%s: HC prefix list is set, checking",
753 if (prefix_list_apply(
754 hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
758 vnc_zlog_debug_verbose(
759 "%s: prefix list returns DENY, blocking route",
763 vnc_zlog_debug_verbose(
764 "%s: prefix list returns PASS, allowing route",
768 /* apply routemap, if any, later */
769 rmap
= hc
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
772 * Incoming prefix is unicast. If v6, it is in multiprotocol
774 * but if v4 it is in attr->nexthop
776 rfapiUnicastNexthop2Prefix(afi
, attr
, &vn_pfx_space
);
777 vn_pfx
= &vn_pfx_space
;
780 ahr_flags
|= RFAPI_AHR_NO_TUNNEL_SUBTLV
;
783 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
784 char buf
[PREFIX_STRLEN
];
786 prefix2str(vn_pfx
, buf
, sizeof(buf
));
787 vnc_zlog_debug_any("%s vn_pfx=%s", __func__
, buf
);
793 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
794 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
801 * This code is here because it allocates an interned attr which
802 * must be freed before we return. It's easier to put it after
803 * all of the possible returns above.
805 memset(&hattr
, 0, sizeof(struct attr
));
806 bgp_attr_dup(&hattr
, attr
); /* hattr becomes a ghost attr */
809 struct bgp_info info
;
810 route_map_result_t ret
;
812 memset(&info
, 0, sizeof(info
));
815 ret
= route_map_apply(rmap
, prefix
, RMAP_BGP
, &info
);
816 if (ret
== RMAP_DENYMATCH
) {
817 bgp_attr_flush(&hattr
);
818 vnc_zlog_debug_verbose(
819 "%s: route map \"%s\" says DENY, returning",
820 __func__
, rmap
->name
);
825 iattr
= bgp_attr_intern(&hattr
);
826 bgp_attr_flush(&hattr
);
828 /* Now iattr is an allocated interned attr */
831 * Mode "plain" specific code
833 * Sets RD in dummy HD
837 if (vnaddr
.addr_family
!= AF_INET
) {
838 vnc_zlog_debug_verbose(
839 "%s: can't auto-assign RD, VN AF (%d) is not IPv4, skipping",
840 __func__
, vnaddr
.addr_family
);
842 bgp_attr_unintern(&iattr
);
846 memset(&prd
, 0, sizeof(prd
));
847 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
849 if (iattr
&& iattr
->ecommunity
)
850 ecom
= ecommunity_dup(iattr
->ecommunity
);
853 local_pref
= calc_local_pref(iattr
, peer
);
855 if (iattr
&& (iattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))) {
859 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
860 char buf
[PREFIX_STRLEN
];
862 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, sizeof(buf
));
863 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
866 vncHDBgpDirect
.peer
= peer
;
867 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
868 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
869 NULL
, /* RFP options */
870 NULL
, NULL
, ecom
, med
, /* med */
871 NULL
, /* label: default */
872 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
874 vncHDBgpDirect
.peer
= NULL
;
877 ecommunity_free(&ecom
);
881 vnc_import_bgp_add_route_mode_nvegroup(struct bgp
*bgp
, struct prefix
*prefix
,
882 struct bgp_info
*info
,
883 struct rfapi_nve_group_cfg
*rfg
)
885 afi_t afi
= family2afi(prefix
->family
);
886 struct peer
*peer
= info
->peer
;
887 struct attr
*attr
= info
->attr
;
889 struct rfapi_cfg
*hc
= NULL
;
890 struct attr
*iattr
= NULL
;
892 struct rfapi_ip_addr vnaddr
;
893 struct prefix
*vn_pfx
= NULL
;
895 struct ecommunity
*ecom
= NULL
;
896 struct prefix_rd prd
;
897 struct route_map
*rmap
= NULL
;
901 char buf
[PREFIX_STRLEN
];
903 prefix2str(prefix
, buf
, sizeof(buf
));
904 vnc_zlog_debug_verbose("%s(prefix=%s) entry", __func__
, buf
);
910 zlog_err("%s: can't get afi of prefix", __func__
);
914 if (!(hc
= bgp
->rfapi_cfg
)) {
915 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
920 /* check vnc redist flag for bgp direct routes */
921 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
922 vnc_zlog_debug_verbose(
923 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
934 struct rfapi_ip_prefix pfx_un
;
936 vnc_zlog_debug_verbose("%s: using redist RFG", __func__
);
939 * RFG prefix list check
941 if (rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
942 vnc_zlog_debug_verbose(
943 "%s: RFG prefix list is set, checking",
945 if (prefix_list_apply(
946 rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
950 vnc_zlog_debug_verbose(
951 "%s: prefix list returns DENY, blocking route",
955 vnc_zlog_debug_verbose(
956 "%s: prefix list returns PASS, allowing route",
960 /* apply routemap, if any, later */
961 rmap
= rfg
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
964 * export nve group's VN addr prefix must be a /32 which
965 * will yield the VN addr to use
967 vn_pfx
= &rfg
->vn_prefix
;
972 if (!is_host_prefix(&rfg
->un_prefix
)) {
973 /* NB prefixlen==0 means it has not been configured */
974 vnc_zlog_debug_verbose(
975 "%s: redist RFG UN pfx not host pfx (plen=%d), skipping",
976 __func__
, rfg
->un_prefix
.prefixlen
);
980 rfapiQprefix2Rprefix(&rfg
->un_prefix
, &pfx_un
);
982 vncHDBgpDirect
.un_addr
= pfx_un
.prefix
;
985 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
986 char buf
[PREFIX_STRLEN
];
988 prefix2str(vn_pfx
, buf
, sizeof(buf
));
989 vnc_zlog_debug_any("%s vn_pfx=%s", __func__
, buf
);
995 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
996 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
1002 * route map handling
1003 * This code is here because it allocates an interned attr which
1004 * must be freed before we return. It's easier to put it after
1005 * all of the possible returns above.
1007 memset(&hattr
, 0, sizeof(struct attr
));
1008 bgp_attr_dup(&hattr
, attr
); /* hattr becomes a ghost attr */
1011 struct bgp_info info
;
1012 route_map_result_t ret
;
1014 memset(&info
, 0, sizeof(info
));
1017 ret
= route_map_apply(rmap
, prefix
, RMAP_BGP
, &info
);
1018 if (ret
== RMAP_DENYMATCH
) {
1019 bgp_attr_flush(&hattr
);
1020 vnc_zlog_debug_verbose(
1021 "%s: route map \"%s\" says DENY, returning",
1022 __func__
, rmap
->name
);
1027 iattr
= bgp_attr_intern(&hattr
);
1028 bgp_attr_flush(&hattr
);
1030 /* Now iattr is an allocated interned attr */
1035 * Sets RD in dummy HD
1040 memset(&prd
, 0, sizeof(prd
));
1042 prd
.family
= AF_UNSPEC
;
1045 if (rfg
->rd
.family
== AF_UNIX
) {
1046 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
1049 if (rfg
->rt_export_list
)
1050 ecom
= ecommunity_dup(
1051 bgp
->rfapi_cfg
->rfg_redist
->rt_export_list
);
1053 ecom
= ecommunity_new();
1055 if (iattr
&& iattr
->ecommunity
)
1056 ecom
= ecommunity_merge(ecom
, iattr
->ecommunity
);
1059 local_pref
= calc_local_pref(iattr
, peer
);
1061 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
1065 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, BUFSIZ
);
1066 buf
[BUFSIZ
- 1] = 0;
1067 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
1070 vncHDBgpDirect
.peer
= peer
;
1071 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
1072 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
1073 NULL
, /* RFP options */
1074 NULL
, NULL
, ecom
, NULL
, /* med */
1075 NULL
, /* label: default */
1076 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1078 vncHDBgpDirect
.peer
= NULL
;
1081 ecommunity_free(&ecom
);
1084 static void vnc_import_bgp_del_route_mode_plain(struct bgp
*bgp
,
1085 struct prefix
*prefix
,
1086 struct bgp_info
*info
)
1088 struct prefix_rd prd
;
1089 afi_t afi
= family2afi(prefix
->family
);
1090 struct prefix
*vn_pfx
= NULL
;
1091 struct rfapi_ip_addr vnaddr
;
1092 struct prefix vn_pfx_space
;
1098 * Compute VN address
1101 if (info
&& info
->attr
) {
1102 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &vn_pfx_space
);
1104 vnc_zlog_debug_verbose("%s: no attr, can't delete route",
1108 vn_pfx
= &vn_pfx_space
;
1110 vnaddr
.addr_family
= vn_pfx
->family
;
1111 switch (vn_pfx
->family
) {
1113 if (vn_pfx
->prefixlen
!= 32) {
1114 vnc_zlog_debug_verbose(
1115 "%s: redist VN plen (%d) != 32, skipping",
1116 __func__
, vn_pfx
->prefixlen
);
1119 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1123 if (vn_pfx
->prefixlen
!= 128) {
1124 vnc_zlog_debug_verbose(
1125 "%s: redist VN plen (%d) != 128, skipping",
1126 __func__
, vn_pfx
->prefixlen
);
1129 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1133 vnc_zlog_debug_verbose(
1134 "%s: no redist RFG VN host pfx configured, skipping",
1140 memset(&prd
, 0, sizeof(prd
));
1141 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1142 vnc_zlog_debug_verbose("%s: can't auto-assign RD, skipping",
1147 vncHDBgpDirect
.peer
= info
->peer
;
1148 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1149 vncHDBgpDirect
.peer
);
1150 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1151 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1154 vncHDBgpDirect
.peer
= NULL
;
1157 static void vnc_import_bgp_del_route_mode_nvegroup(struct bgp
*bgp
,
1158 struct prefix
*prefix
,
1159 struct bgp_info
*info
)
1161 struct prefix_rd prd
;
1162 afi_t afi
= family2afi(prefix
->family
);
1163 struct rfapi_nve_group_cfg
*rfg
= NULL
;
1164 struct prefix
*vn_pfx
= NULL
;
1165 struct rfapi_ip_addr vnaddr
;
1170 rfg
= bgp
->rfapi_cfg
->rfg_redist
;
1174 * Compute VN address
1178 * export nve group's VN addr prefix must be a /32 which
1179 * will yield the VN addr to use
1181 vn_pfx
= &rfg
->vn_prefix
;
1184 vnaddr
.addr_family
= vn_pfx
->family
;
1185 switch (vn_pfx
->family
) {
1187 if (vn_pfx
->prefixlen
!= 32) {
1188 vnc_zlog_debug_verbose(
1189 "%s: redist VN plen (%d) != 32, skipping",
1190 __func__
, vn_pfx
->prefixlen
);
1193 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1197 if (vn_pfx
->prefixlen
!= 128) {
1198 vnc_zlog_debug_verbose(
1199 "%s: redist VN plen (%d) != 128, skipping",
1200 __func__
, vn_pfx
->prefixlen
);
1203 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1207 vnc_zlog_debug_verbose(
1208 "%s: no redist RFG VN host pfx configured, skipping",
1213 memset(&prd
, 0, sizeof(prd
));
1215 prd
.family
= AF_UNSPEC
;
1218 if (rfg
->rd
.family
== AF_UNIX
) {
1219 /* means "auto" with VN addr */
1220 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1221 vnc_zlog_debug_verbose(
1222 "%s: can't auto-assign RD, skipping", __func__
);
1228 vncHDBgpDirect
.peer
= info
->peer
;
1229 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1230 vncHDBgpDirect
.peer
);
1231 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1232 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1235 vncHDBgpDirect
.peer
= NULL
;
1238 static void vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1239 struct bgp
*bgp
, afi_t afi
, struct bgp_info
*bi
, /* VPN bi */
1240 struct prefix_rd
*prd
, /* RD */
1241 struct prefix
*prefix
) /* unicast route prefix */
1245 if (bi
->type
!= ZEBRA_ROUTE_BGP
&& bi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
) {
1249 if (bi
->sub_type
!= BGP_ROUTE_NORMAL
&& bi
->sub_type
!= BGP_ROUTE_STATIC
1250 && bi
->sub_type
!= BGP_ROUTE_RFP
) {
1254 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
1257 vncHDResolveNve
.peer
= bi
->peer
;
1258 if (!rfapiGetVncTunnelUnAddr(bi
->attr
, &un
)) {
1259 if (rfapiQprefix2Raddr(&un
, &vncHDResolveNve
.un_addr
))
1262 memset(&vncHDResolveNve
.un_addr
, 0,
1263 sizeof(vncHDResolveNve
.un_addr
));
1266 del_vnc_route(&vncHDResolveNve
, vncHDResolveNve
.peer
, bgp
,
1267 SAFI_MPLS_VPN
, prefix
, /* unicast route prefix */
1268 prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
, NULL
,
1272 static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1273 struct prefix_rd
*prd
,
1274 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1275 afi_t afi
, struct bgp
*bgp
, struct prefix
*prefix
, /* unicast prefix */
1276 struct prefix
*ubi_nexthop
) /* unicast bi's nexthop */
1278 struct bgp_node
*bn
;
1279 struct bgp_info
*bi
;
1285 char str_nh
[PREFIX_STRLEN
];
1287 prefix2str(ubi_nexthop
, str_nh
, sizeof(str_nh
));
1288 vnc_zlog_debug_verbose("%s: ubi_nexthop=%s", __func__
, str_nh
);
1293 bn
= bgp_node_lookup(table_rd
, ubi_nexthop
);
1295 vnc_zlog_debug_verbose(
1296 "%s: no match in RD's table for ubi_nexthop", __func__
);
1300 /* Iterate over bgp_info items at this node */
1301 for (bi
= bn
->info
; bi
; bi
= bi
->next
) {
1303 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1304 bgp
, afi
, bi
, /* VPN bi */
1306 prefix
); /* unicast route prefix */
1309 bgp_unlock_node(bn
);
1312 static void vnc_import_bgp_del_route_mode_resolve_nve(struct bgp
*bgp
,
1314 struct prefix
*prefix
,
1315 struct bgp_info
*info
)
1317 struct ecommunity
*ecom
= NULL
;
1318 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
1320 // struct listnode *hnode;
1321 // struct rfapi_descriptor *rfd;
1322 struct prefix_bag
*pb
;
1324 struct skiplist
*sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1326 struct bgp_node
*bnp
; /* prd table node */
1329 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1334 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
1335 vnc_zlog_debug_verbose(
1336 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
1337 __func__
, info
->type
, zebra_route_string(info
->type
),
1338 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
1342 if (process_unicast_route(bgp
, afi
, prefix
, info
, &ecom
,
1343 &pfx_unicast_nexthop
)) {
1345 vnc_zlog_debug_verbose(
1346 "%s: process_unicast_route error, skipping", __func__
);
1350 rc
= skiplist_first_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1353 if (pb
->ubi
== info
) {
1354 skiplist_delete(sl
, &pfx_unicast_nexthop
, pb
);
1355 bgp_info_unlock(info
);
1358 rc
= skiplist_next_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1363 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
1364 * (exact match, /32). If an exact match is found, call add_vnc_route.
1367 for (bnp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bnp
;
1368 bnp
= bgp_route_next(bnp
)) {
1370 struct bgp_table
*table
;
1372 table
= (struct bgp_table
*)(bnp
->info
);
1377 vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1378 (struct prefix_rd
*)&bnp
->p
, table
, afi
, bgp
, prefix
,
1379 &pfx_unicast_nexthop
); /* TBD how is this set? */
1383 ecommunity_free(&ecom
);
1387 /***********************************************************************
1388 * Add/Delete CE->NVE routes
1389 ***********************************************************************/
1392 * Should be called whan a bi is added to VPN RIB. This function
1393 * will check if it is a host route and return immediately if not.
1395 void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1396 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1397 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1398 struct prefix
*prefix
, /* VPN prefix */
1399 struct bgp_info
*bi
) /* new VPN host route */
1401 afi_t afi
= family2afi(prefix
->family
);
1402 struct skiplist
*sl
= NULL
;
1404 struct prefix_bag
*pb
;
1406 struct rfapi_cfg
*hc
= NULL
;
1408 vnc_zlog_debug_verbose("%s: entry", __func__
);
1410 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1411 vnc_zlog_debug_verbose("%s: bad afi %d, skipping", __func__
,
1416 if (!(hc
= bgp
->rfapi_cfg
)) {
1417 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1422 /* check vnc redist flag for bgp direct routes */
1423 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1424 vnc_zlog_debug_verbose(
1425 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1430 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1431 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1437 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1440 vnc_zlog_debug_verbose(
1441 "%s: no resolve_nve_nexthop skiplist, skipping",
1446 if (!is_host_prefix(prefix
)) {
1447 vnc_zlog_debug_verbose("%s: not host prefix, skipping",
1452 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1454 struct ecommunity
*ecom
;
1455 struct prefix pfx_unicast_nexthop
;
1456 uint32_t *med
= NULL
;
1457 uint32_t local_pref
;
1459 memset(&pfx_unicast_nexthop
, 0,
1460 sizeof(struct prefix
)); /* keep valgrind happy */
1462 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
1463 char hbuf
[PREFIX_STRLEN
];
1464 char ubuf
[PREFIX_STRLEN
];
1466 prefix2str(&pb
->hpfx
, hbuf
, sizeof(hbuf
));
1467 prefix2str(&pb
->upfx
, ubuf
, sizeof(ubuf
));
1470 "%s: examining RHN Entry (q=%p): upfx=%s, hpfx=%s, ubi=%p",
1471 __func__
, cursor
, ubuf
, hbuf
, pb
->ubi
);
1474 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubi
, &ecom
,
1475 &pfx_unicast_nexthop
)) {
1477 vnc_zlog_debug_verbose(
1478 "%s: process_unicast_route error, skipping",
1482 local_pref
= calc_local_pref(pb
->ubi
->attr
, pb
->ubi
->peer
);
1485 && (pb
->ubi
->attr
->flag
1486 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))) {
1488 med
= &pb
->ubi
->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 bi 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
, bi
, /* VPN bi */
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 struct prefix
*prefix
, /* VPN prefix */
1539 struct bgp_info
*bi
) /* 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
->ubi
, &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 bi 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
, bi
, 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_info
*bi_interior
)
1651 if (!VALID_INTERIOR_TYPE(bi_interior
->type
)) {
1652 #if DEBUG_IS_USABLE_INTERIOR
1653 vnc_zlog_debug_verbose(
1654 "%s: NO: type %d is not valid interior type", __func__
,
1659 if (!CHECK_FLAG(bi_interior
->flags
, BGP_INFO_VALID
)) {
1660 #if DEBUG_IS_USABLE_INTERIOR
1661 vnc_zlog_debug_verbose("%s: NO: BGP_INFO_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 struct prefix
*prefix
, /* unicast prefix */
1681 struct bgp_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 vnc_zlog_debug_verbose("%s: no info, skipping", __func__
);
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 route_table
*table
;
1739 struct route_node
*rn
;
1740 struct route_node
*par
;
1741 struct bgp_info
*bi_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
= route_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 (bi_interior
= rn
->info
; bi_interior
;
1762 bi_interior
= bi_interior
->next
) {
1763 struct prefix_rd
*prd
;
1764 struct attr new_attr
;
1767 if (!is_usable_interior_route(bi_interior
))
1770 vnc_zlog_debug_verbose(
1771 "%s: usable: bi_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 (bi_interior
->extra
) {
1783 prd
= &bi_interior
->extra
->vnc
.import
1785 label
= decode_label(
1786 &bi_interior
->extra
->label
[0]);
1790 /* use local_pref from unicast route */
1791 memset(&new_attr
, 0, sizeof(struct attr
));
1792 bgp_attr_dup(&new_attr
, bi_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 bi_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
=
1822 route_lock_node(rn
); /* for skiplist */
1824 route_lock_node(rn
); /* for skiplist entry */
1825 prefix_copy(pfx_mon
, prefix
);
1826 if (!skiplist_insert(
1827 RFAPI_MONITOR_EXTERIOR(rn
)->source
,
1830 bgp_info_lock(info
);
1835 route_lock_node(par
);
1836 route_unlock_node(rn
);
1840 route_unlock_node(rn
);
1842 if (!have_usable_route
) {
1843 struct prefix
*pfx_mon
= prefix_new();
1844 prefix_copy(pfx_mon
, prefix
);
1845 if (!skiplist_insert(it
->monitor_exterior_orphans
, info
,
1848 bgp_info_lock(info
);
1854 void vnc_import_bgp_exterior_add_route(
1855 struct bgp
*bgp
, /* exterior instance, we hope */
1856 struct prefix
*prefix
, /* unicast prefix */
1857 struct bgp_info
*info
) /* unicast info */
1859 vnc_import_bgp_exterior_add_route_it(bgp
, prefix
, info
, NULL
);
1863 * There should be only one of these per prefix at a time.
1864 * This should probably be called as a result of selection operation.
1866 * NB should be called espacially for bgp instances that are named,
1867 * because the exterior routes will always come from one of those.
1868 * We filter here on the instance name to make sure we get only the
1871 void vnc_import_bgp_exterior_del_route(
1872 struct bgp
*bgp
, struct prefix
*prefix
, /* unicast prefix */
1873 struct bgp_info
*info
) /* unicast info */
1876 struct rfapi_cfg
*hc
;
1877 struct rfapi_import_table
*it
;
1878 struct prefix pfx_orig_nexthop
;
1879 afi_t afi
= family2afi(prefix
->family
);
1880 struct bgp
*bgp_default
= bgp_get_default();
1885 memset(&pfx_orig_nexthop
, 0,
1886 sizeof(struct prefix
)); /* keep valgrind happy */
1888 h
= bgp_default
->rfapi
;
1889 hc
= bgp_default
->rfapi_cfg
;
1892 vnc_zlog_debug_verbose(
1893 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1897 if (!hc
->redist_bgp_exterior_view
) {
1898 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1902 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1903 vnc_zlog_debug_verbose(
1904 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1905 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1908 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1909 vnc_zlog_debug_verbose(
1910 "%s: redist of exterior routes no enabled, skipping",
1916 vnc_zlog_debug_verbose("%s: no info, skipping", __func__
);
1921 * Extract nexthop from exterior route
1923 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1924 * but if v4 it is in attr->nexthop
1926 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1928 for (it
= h
->imports
; it
; it
= it
->next
) {
1929 struct route_table
*table
;
1930 struct route_node
*rn
;
1931 struct route_node
*par
;
1932 struct bgp_info
*bi_interior
;
1933 int have_usable_route
;
1935 table
= it
->imported_vpn
[afi
];
1937 for (rn
= route_node_match(table
, &pfx_orig_nexthop
),
1938 have_usable_route
= 0;
1939 (!have_usable_route
) && rn
;) {
1941 for (bi_interior
= rn
->info
; bi_interior
;
1942 bi_interior
= bi_interior
->next
) {
1943 struct prefix_rd
*prd
;
1946 if (!is_usable_interior_route(bi_interior
))
1950 * have a legitimate route to exterior's nexthop
1953 * Import unicast route to the import table
1955 have_usable_route
= 1;
1957 if (bi_interior
->extra
) {
1958 prd
= &bi_interior
->extra
->vnc
.import
1960 label
= decode_label(
1961 &bi_interior
->extra
->label
[0]);
1965 rfapiBgpInfoFilteredImportVPN(
1966 it
, FIF_ACTION_KILL
, bi_interior
->peer
,
1968 prefix
, NULL
, afi
, prd
,
1970 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1971 BGP_ROUTE_REDISTRIBUTE
, &label
);
1976 * TBD factor this out into its own function
1979 if (RFAPI_MONITOR_EXTERIOR(rn
)
1981 if (!skiplist_delete(
1982 RFAPI_MONITOR_EXTERIOR(
1987 bgp_info_unlock(info
);
1993 RFAPI_MONITOR_EXTERIOR(
1997 RFAPI_MONITOR_EXTERIOR(
2000 RFAPI_MONITOR_EXTERIOR(
2013 route_lock_node(par
);
2014 route_unlock_node(rn
);
2018 route_unlock_node(rn
);
2020 if (!have_usable_route
) {
2021 if (!skiplist_delete(it
->monitor_exterior_orphans
, info
,
2024 bgp_info_unlock(info
);
2031 * This function should be called after a new interior VPN route
2032 * has been added to an import_table.
2034 * NB should also be called whenever an existing vpn interior route
2035 * becomes valid (e.g., valid_interior_count is inremented)
2037 void vnc_import_bgp_exterior_add_route_interior(
2038 struct bgp
*bgp
, struct rfapi_import_table
*it
,
2039 struct route_node
*rn_interior
, /* VPN IT node */
2040 struct bgp_info
*bi_interior
) /* VPN IT route */
2042 afi_t afi
= family2afi(rn_interior
->p
.family
);
2043 struct route_node
*par
;
2044 struct bgp_info
*bi_exterior
;
2045 struct prefix
*pfx_exterior
; /* exterior pfx */
2048 struct list
*list_adopted
;
2050 vnc_zlog_debug_verbose("%s: entry", __func__
);
2052 if (!is_usable_interior_route(bi_interior
)) {
2053 vnc_zlog_debug_verbose(
2054 "%s: not usable interior route, skipping", __func__
);
2058 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2059 vnc_zlog_debug_verbose(
2060 "%s: redist of exterior routes no enabled, skipping",
2065 if (it
== bgp
->rfapi
->it_ce
) {
2066 vnc_zlog_debug_verbose("%s: import table is it_ce, skipping",
2073 char str_pfx
[PREFIX_STRLEN
];
2075 prefix2str(&rn_interior
->p
, str_pfx
, sizeof(str_pfx
));
2076 vnc_zlog_debug_verbose("%s: interior prefix=%s, bi type=%d",
2077 __func__
, str_pfx
, bi_interior
->type
);
2080 if (RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
2082 int count
= 0; /* debugging */
2084 vnc_zlog_debug_verbose(
2085 "%s: has exterior monitor; ext src: %p", __func__
,
2086 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2089 * There is a monitor here already. Therefore, we do not need
2090 * to do any pulldown. Just construct exterior routes based
2091 * on the new interior route.
2094 for (rc
= skiplist_next(
2095 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2096 (void **)&bi_exterior
, (void **)&pfx_exterior
,
2098 !rc
; rc
= skiplist_next(
2099 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2100 (void **)&bi_exterior
, (void **)&pfx_exterior
,
2103 struct prefix_rd
*prd
;
2104 struct attr new_attr
;
2108 ++count
; /* debugging */
2110 assert(bi_exterior
);
2111 assert(pfx_exterior
);
2113 if (bi_interior
->extra
) {
2114 prd
= &bi_interior
->extra
->vnc
.import
.rd
;
2115 label
= decode_label(
2116 &bi_interior
->extra
->label
[0]);
2120 /* use local_pref from unicast route */
2121 memset(&new_attr
, 0, sizeof(struct attr
));
2122 bgp_attr_dup(&new_attr
, bi_interior
->attr
);
2124 && (bi_exterior
->attr
->flag
2125 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2126 new_attr
.local_pref
=
2127 bi_exterior
->attr
->local_pref
;
2129 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2132 rfapiBgpInfoFilteredImportVPN(
2133 it
, FIF_ACTION_UPDATE
, bi_interior
->peer
,
2135 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2136 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2137 BGP_ROUTE_REDISTRIBUTE
, &label
);
2139 vnc_zlog_debug_verbose(
2140 "%s: finished constructing exteriors based on existing monitors",
2145 vnc_zlog_debug_verbose("%s: no exterior monitor", __func__
);
2148 * No monitor at this node. Is this the first valid interior
2149 * route at this node?
2151 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
> 1) {
2152 vnc_zlog_debug_verbose(
2153 "%s: new interior route not first valid one, skipping pulldown",
2159 * Look up the tree for possible pulldown candidates.
2160 * Find nearest parent with an exterior route monitor
2162 for (par
= rn_interior
->parent
; par
; par
= par
->parent
) {
2163 if (RFAPI_HAS_MONITOR_EXTERIOR(par
))
2169 vnc_zlog_debug_verbose(
2170 "%s: checking parent %p for possible pulldowns",
2173 /* check monitors at par for possible pulldown */
2175 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2176 (void **)&bi_exterior
,
2177 (void **)&pfx_exterior
, &cursor
);
2179 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2180 (void **)&bi_exterior
,
2181 (void **)&pfx_exterior
, &cursor
)) {
2183 struct prefix pfx_nexthop
;
2185 memset(&pfx_nexthop
, 0,
2186 sizeof(struct prefix
)); /* keep valgrind happy */
2188 /* check original nexthop for prefix match */
2189 rfapiUnicastNexthop2Prefix(afi
, bi_exterior
->attr
,
2192 if (prefix_match(&rn_interior
->p
, &pfx_nexthop
)) {
2194 struct bgp_info
*bi
;
2195 struct prefix_rd
*prd
;
2196 struct attr new_attr
;
2202 * add monitor to longer prefix
2204 struct prefix
*pfx_mon
= prefix_new();
2205 prefix_copy(pfx_mon
, pfx_exterior
);
2206 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)
2208 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2209 ->source
= skiplist_new(
2211 (void (*)(void *))prefix_free
);
2212 route_lock_node(rn_interior
);
2215 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2217 bi_exterior
, pfx_mon
);
2218 route_lock_node(rn_interior
);
2221 * Delete constructed exterior routes based on
2224 for (bi
= par
->info
; bi
; bi
= bi
->next
) {
2227 prd
= &bi
->extra
->vnc
.import
.rd
;
2228 label
= decode_label(
2229 &bi
->extra
->label
[0]);
2233 rfapiBgpInfoFilteredImportVPN(
2234 it
, FIF_ACTION_KILL
, bi
->peer
,
2236 pfx_exterior
, NULL
, afi
, prd
,
2238 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2239 BGP_ROUTE_REDISTRIBUTE
, &label
);
2244 * Add constructed exterior routes based on
2245 * the new interior route at longer prefix.
2247 if (bi_interior
->extra
) {
2248 prd
= &bi_interior
->extra
->vnc
.import
2250 label
= decode_label(
2251 &bi_interior
->extra
->label
[0]);
2255 /* use local_pref from unicast route */
2256 memset(&new_attr
, 0, sizeof(struct attr
));
2257 bgp_attr_dup(&new_attr
, bi_interior
->attr
);
2259 && (bi_exterior
->attr
->flag
2260 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2261 new_attr
.local_pref
=
2262 bi_exterior
->attr
->local_pref
;
2263 new_attr
.flag
|= ATTR_FLAG_BIT(
2264 BGP_ATTR_LOCAL_PREF
);
2267 rfapiBgpInfoFilteredImportVPN(
2268 it
, FIF_ACTION_UPDATE
,
2269 bi_interior
->peer
, NULL
, /* rfd */
2270 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2271 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2272 BGP_ROUTE_REDISTRIBUTE
, &label
);
2277 * The only monitors at rn_interior are the ones we added just
2278 * above, so we can use the rn_interior list to identify which
2279 * monitors to delete from the parent.
2282 for (rc
= skiplist_next(
2283 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2284 (void **)&bi_exterior
, NULL
, &cursor
);
2285 !rc
; rc
= skiplist_next(
2286 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2287 (void **)&bi_exterior
, NULL
, &cursor
)) {
2290 skiplist_delete(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2292 route_unlock_node(par
); /* sl entry */
2294 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par
)->source
)) {
2295 skiplist_free(RFAPI_MONITOR_EXTERIOR(par
)->source
);
2296 RFAPI_MONITOR_EXTERIOR(par
)->source
= NULL
;
2297 route_unlock_node(par
); /* sl itself */
2301 vnc_zlog_debug_verbose("%s: checking orphans", __func__
);
2304 * See if any orphans can be pulled down to the current node
2307 list_adopted
= NULL
;
2308 for (rc
= skiplist_next(it
->monitor_exterior_orphans
,
2309 (void **)&bi_exterior
, (void **)&pfx_exterior
,
2311 !rc
; rc
= skiplist_next(it
->monitor_exterior_orphans
,
2312 (void **)&bi_exterior
,
2313 (void **)&pfx_exterior
, &cursor
)) {
2315 struct prefix pfx_nexthop
;
2316 char buf
[PREFIX_STRLEN
];
2317 afi_t afi_exterior
= family2afi(pfx_exterior
->family
);
2319 prefix2str(pfx_exterior
, buf
, sizeof(buf
));
2320 vnc_zlog_debug_verbose(
2321 "%s: checking exterior orphan at prefix %s", __func__
,
2324 if (afi_exterior
!= afi
) {
2325 vnc_zlog_debug_verbose(
2326 "%s: exterior orphan afi %d != interior afi %d, skip",
2327 __func__
, afi_exterior
, afi
);
2331 /* check original nexthop for prefix match */
2332 rfapiUnicastNexthop2Prefix(afi
, bi_exterior
->attr
,
2335 if (prefix_match(&rn_interior
->p
, &pfx_nexthop
)) {
2337 struct prefix_rd
*prd
;
2338 struct attr new_attr
;
2344 * add monitor to longer prefix
2347 struct prefix
*pfx_mon
= prefix_new();
2348 prefix_copy(pfx_mon
, pfx_exterior
);
2349 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
) {
2350 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
=
2353 (void (*)(void *))prefix_free
);
2354 route_lock_node(rn_interior
); /* sl */
2357 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2358 bi_exterior
, pfx_mon
);
2359 route_lock_node(rn_interior
); /* sl entry */
2360 if (!list_adopted
) {
2361 list_adopted
= list_new();
2363 listnode_add(list_adopted
, bi_exterior
);
2366 * Add constructed exterior routes based on the
2367 * new interior route at the longer prefix.
2369 if (bi_interior
->extra
) {
2370 prd
= &bi_interior
->extra
->vnc
.import
.rd
;
2371 label
= decode_label(
2372 &bi_interior
->extra
->label
[0]);
2376 /* use local_pref from unicast route */
2377 memset(&new_attr
, 0, sizeof(struct attr
));
2378 bgp_attr_dup(&new_attr
, bi_interior
->attr
);
2380 && (bi_exterior
->attr
->flag
2381 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2382 new_attr
.local_pref
=
2383 bi_exterior
->attr
->local_pref
;
2385 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2388 rfapiBgpInfoFilteredImportVPN(
2389 it
, FIF_ACTION_UPDATE
, bi_interior
->peer
,
2391 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2392 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2393 BGP_ROUTE_REDISTRIBUTE
, &label
);
2397 struct listnode
*node
;
2398 struct route_node
*bi_exterior
;
2400 for (ALL_LIST_ELEMENTS_RO(list_adopted
, node
, bi_exterior
)) {
2401 skiplist_delete(it
->monitor_exterior_orphans
,
2404 list_delete_and_null(&list_adopted
);
2409 * This function should be called after an interior VPN route
2410 * has been deleted from an import_table.
2411 * bi_interior must still be valid, but it must already be detached
2412 * from its route node and the route node's valid_interior_count
2413 * must already be decremented.
2415 * NB should also be called whenever an existing vpn interior route
2416 * becomes invalid (e.g., valid_interior_count is decremented)
2418 void vnc_import_bgp_exterior_del_route_interior(
2419 struct bgp
*bgp
, struct rfapi_import_table
*it
,
2420 struct route_node
*rn_interior
, /* VPN IT node */
2421 struct bgp_info
*bi_interior
) /* VPN IT route */
2423 afi_t afi
= family2afi(rn_interior
->p
.family
);
2424 struct route_node
*par
;
2425 struct bgp_info
*bi_exterior
;
2426 struct prefix
*pfx_exterior
; /* exterior pfx */
2430 if (!VALID_INTERIOR_TYPE(bi_interior
->type
)) {
2431 vnc_zlog_debug_verbose(
2432 "%s: type %d not valid interior type, skipping",
2433 __func__
, bi_interior
->type
);
2437 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2438 vnc_zlog_debug_verbose(
2439 "%s: redist of exterior routes no enabled, skipping",
2444 if (it
== bgp
->rfapi
->it_ce
) {
2445 vnc_zlog_debug_verbose("%s: it is it_ce, skipping", __func__
);
2449 /* If no exterior routes depend on this prefix, nothing to do */
2450 if (!RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
2451 vnc_zlog_debug_verbose("%s: no exterior monitor, skipping",
2458 char str_pfx
[PREFIX_STRLEN
];
2460 prefix2str(&rn_interior
->p
, str_pfx
, sizeof(str_pfx
));
2462 vnc_zlog_debug_verbose("%s: interior prefix=%s, bi type=%d",
2463 __func__
, str_pfx
, bi_interior
->type
);
2467 * Remove constructed routes based on the deleted interior route
2470 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2471 (void **)&bi_exterior
, (void **)&pfx_exterior
,
2474 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2475 (void **)&bi_exterior
, (void **)&pfx_exterior
,
2478 struct prefix_rd
*prd
;
2481 if (bi_interior
->extra
) {
2482 prd
= &bi_interior
->extra
->vnc
.import
.rd
;
2483 label
= decode_label(&bi_interior
->extra
->label
[0]);
2487 rfapiBgpInfoFilteredImportVPN(
2488 it
, FIF_ACTION_KILL
, bi_interior
->peer
, NULL
, /* rfd */
2489 pfx_exterior
, NULL
, afi
, prd
, bi_interior
->attr
,
2490 ZEBRA_ROUTE_BGP_DIRECT_EXT
, BGP_ROUTE_REDISTRIBUTE
,
2495 * If there are no remaining valid interior routes at this prefix,
2496 * we need to look up the tree for a possible node to move monitors to
2498 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
) {
2499 vnc_zlog_debug_verbose(
2500 "%s: interior routes still present, skipping",
2506 * Find nearest parent with at least one valid interior route
2507 * If none is found, par will end up NULL, and we will move
2508 * the monitors to the orphan list for this import table
2510 for (par
= rn_interior
->parent
; par
; par
= par
->parent
) {
2511 if (RFAPI_MONITOR_EXTERIOR(par
)->valid_interior_count
)
2515 vnc_zlog_debug_verbose("%s: par=%p, ext src: %p", __func__
, par
,
2516 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2518 /* move all monitors */
2520 * We will use and delete every element of the source skiplist
2522 while (!skiplist_first(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2523 (void **)&bi_exterior
, (void **)&pfx_exterior
)) {
2525 struct prefix
*pfx_mon
= prefix_new();
2527 prefix_copy(pfx_mon
, pfx_exterior
);
2531 struct bgp_info
*bi
;
2534 * Add monitor to parent node
2536 if (!RFAPI_MONITOR_EXTERIOR(par
)->source
) {
2537 RFAPI_MONITOR_EXTERIOR(par
)->source
=
2540 (void (*)(void *))prefix_free
);
2541 route_lock_node(par
); /* sl */
2543 skiplist_insert(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2544 bi_exterior
, pfx_mon
);
2545 route_lock_node(par
); /* sl entry */
2547 /* Add constructed exterior routes based on parent */
2548 for (bi
= par
->info
; bi
; bi
= bi
->next
) {
2550 struct prefix_rd
*prd
;
2551 struct attr new_attr
;
2554 if (bi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
)
2558 prd
= &bi
->extra
->vnc
.import
.rd
;
2559 label
= decode_label(
2560 &bi
->extra
->label
[0]);
2564 /* use local_pref from unicast route */
2565 memset(&new_attr
, 0, sizeof(struct attr
));
2566 bgp_attr_dup(&new_attr
, bi
->attr
);
2568 && (bi_exterior
->attr
->flag
2569 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2570 new_attr
.local_pref
=
2571 bi_exterior
->attr
->local_pref
;
2572 new_attr
.flag
|= ATTR_FLAG_BIT(
2573 BGP_ATTR_LOCAL_PREF
);
2576 rfapiBgpInfoFilteredImportVPN(
2577 it
, FIF_ACTION_UPDATE
, bi
->peer
,
2579 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2580 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2581 BGP_ROUTE_REDISTRIBUTE
, &label
);
2587 * No interior route for exterior's nexthop. Save
2589 * in orphan list to await future route.
2591 skiplist_insert(it
->monitor_exterior_orphans
,
2592 bi_exterior
, pfx_mon
);
2595 skiplist_delete_first(
2596 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2597 route_unlock_node(rn_interior
); /* sl entry */
2599 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
)) {
2600 skiplist_free(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2601 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
= NULL
;
2602 route_unlock_node(rn_interior
); /* sl itself */
2606 /***********************************************************************
2607 * Generic add/delete unicast routes
2608 ***********************************************************************/
2610 void vnc_import_bgp_add_route(struct bgp
*bgp
, struct prefix
*prefix
,
2611 struct bgp_info
*info
)
2613 afi_t afi
= family2afi(prefix
->family
);
2615 if (VNC_DEBUG(VERBOSE
)) {
2616 struct prefix pfx_nexthop
;
2617 char buf
[PREFIX_STRLEN
];
2618 char buf_nh
[PREFIX_STRLEN
];
2620 prefix2str(prefix
, buf
, sizeof(buf
));
2621 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2622 prefix2str(&pfx_nexthop
, buf_nh
, sizeof(buf_nh
));
2624 vnc_zlog_debug_verbose("%s: pfx %s, nh %s", __func__
, buf
,
2628 print_rhn_list(__func__
, "ENTER ");
2633 zlog_err("%s: can't get afi of prefix", __func__
);
2637 if (!bgp
->rfapi_cfg
) {
2638 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2643 /* check vnc redist flag for bgp direct routes */
2644 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2645 vnc_zlog_debug_verbose(
2646 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
2647 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2651 switch (bgp
->rfapi_cfg
->redist_mode
) {
2652 case VNC_REDIST_MODE_PLAIN
:
2653 vnc_import_bgp_add_route_mode_plain(bgp
, prefix
, info
);
2656 case VNC_REDIST_MODE_RFG
:
2657 if (bgp
->rfapi_cfg
->rfg_redist
)
2658 vnc_import_bgp_add_route_mode_nvegroup(
2659 bgp
, prefix
, info
, bgp
->rfapi_cfg
->rfg_redist
);
2661 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2665 case VNC_REDIST_MODE_RESOLVE_NVE
:
2666 vnc_import_bgp_add_route_mode_resolve_nve(bgp
, prefix
, info
);
2670 print_rhn_list(__func__
, "LEAVE ");
2676 * "Withdrawing a Route" import process
2678 void vnc_import_bgp_del_route(struct bgp
*bgp
, struct prefix
*prefix
,
2679 struct bgp_info
*info
) /* unicast info */
2681 afi_t afi
= family2afi(prefix
->family
);
2686 struct prefix pfx_nexthop
;
2687 char buf
[PREFIX_STRLEN
];
2688 char buf_nh
[PREFIX_STRLEN
];
2690 prefix2str(prefix
, buf
, sizeof(buf
));
2691 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2692 prefix2str(&pfx_nexthop
, buf_nh
, sizeof(buf_nh
));
2694 vnc_zlog_debug_verbose("%s: pfx %s, nh %s", __func__
, buf
,
2698 print_rhn_list(__func__
, "ENTER ");
2702 if (!bgp
->rfapi_cfg
) {
2703 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2708 /* check bgp redist flag for vnc direct ("vpn") routes */
2709 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2710 vnc_zlog_debug_verbose(
2711 "%s: bgp redistribution of afi=%d VNC direct routes is off",
2716 switch (bgp
->rfapi_cfg
->redist_mode
) {
2717 case VNC_REDIST_MODE_PLAIN
:
2718 vnc_import_bgp_del_route_mode_plain(bgp
, prefix
, info
);
2721 case VNC_REDIST_MODE_RFG
:
2722 if (bgp
->rfapi_cfg
->rfg_redist
)
2723 vnc_import_bgp_del_route_mode_nvegroup(bgp
, prefix
,
2726 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2730 case VNC_REDIST_MODE_RESOLVE_NVE
:
2731 vnc_import_bgp_del_route_mode_resolve_nve(bgp
, afi
, prefix
,
2736 print_rhn_list(__func__
, "LEAVE ");
2742 /***********************************************************************
2744 ***********************************************************************/
2746 void vnc_import_bgp_redist_enable(struct bgp
*bgp
, afi_t afi
)
2748 /* iterate over bgp unicast v4 and v6 routes, call
2749 * vnc_import_bgp_add_route */
2751 struct bgp_node
*rn
;
2753 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
2755 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2756 vnc_zlog_debug_verbose(
2757 "%s: already enabled for afi %d, skipping", __func__
,
2761 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 1;
2763 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); rn
;
2764 rn
= bgp_route_next(rn
)) {
2766 struct bgp_info
*bi
;
2768 for (bi
= rn
->info
; bi
; bi
= bi
->next
) {
2770 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
2773 vnc_import_bgp_add_route(bgp
, &rn
->p
, bi
);
2776 vnc_zlog_debug_verbose(
2777 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2778 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2781 void vnc_import_bgp_exterior_redist_enable(struct bgp
*bgp
, afi_t afi
)
2783 struct bgp
*bgp_exterior
;
2784 struct bgp_node
*rn
;
2786 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2788 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2789 vnc_zlog_debug_verbose(
2790 "%s: already enabled for afi %d, skipping", __func__
,
2794 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 1;
2796 if (!bgp_exterior
) {
2797 vnc_zlog_debug_verbose(
2798 "%s: no exterior view set yet, no routes to import yet",
2803 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); rn
;
2804 rn
= bgp_route_next(rn
)) {
2806 struct bgp_info
*bi
;
2808 for (bi
= rn
->info
; bi
; bi
= bi
->next
) {
2810 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
2813 vnc_import_bgp_exterior_add_route(bgp_exterior
, &rn
->p
,
2817 vnc_zlog_debug_verbose(
2818 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2819 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2823 * This function is for populating a newly-created Import Table
2825 void vnc_import_bgp_exterior_redist_enable_it(
2826 struct bgp
*bgp
, afi_t afi
, struct rfapi_import_table
*it_only
)
2828 struct bgp
*bgp_exterior
;
2829 struct bgp_node
*rn
;
2831 vnc_zlog_debug_verbose("%s: entry", __func__
);
2833 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2835 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2836 vnc_zlog_debug_verbose("%s: not enabled for afi %d, skipping",
2841 if (!bgp_exterior
) {
2842 vnc_zlog_debug_verbose(
2843 "%s: no exterior view set yet, no routes to import yet",
2848 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); rn
;
2849 rn
= bgp_route_next(rn
)) {
2851 struct bgp_info
*bi
;
2853 for (bi
= rn
->info
; bi
; bi
= bi
->next
) {
2855 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
2858 vnc_import_bgp_exterior_add_route_it(
2859 bgp_exterior
, &rn
->p
, bi
, it_only
);
2865 void vnc_import_bgp_redist_disable(struct bgp
*bgp
, afi_t afi
)
2868 * iterate over vpn routes, find routes of type ZEBRA_ROUTE_BGP_DIRECT,
2869 * delete (call timer expire immediately)
2871 struct bgp_node
*rn1
;
2872 struct bgp_node
*rn2
;
2874 vnc_zlog_debug_verbose("%s: entry", __func__
);
2876 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2877 vnc_zlog_debug_verbose(
2878 "%s: already disabled for afi %d, skipping", __func__
,
2884 * Two-level table for SAFI_MPLS_VPN
2885 * Be careful when changing the things we iterate over
2887 for (rn1
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); rn1
;
2888 rn1
= bgp_route_next(rn1
)) {
2891 for (rn2
= bgp_table_top(rn1
->info
); rn2
;
2892 rn2
= bgp_route_next(rn2
)) {
2894 struct bgp_info
*bi
;
2895 struct bgp_info
*nextbi
;
2897 for (bi
= rn2
->info
; bi
; bi
= nextbi
) {
2902 == ZEBRA_ROUTE_BGP_DIRECT
) {
2904 struct rfapi_descriptor
*rfd
;
2905 vncHDBgpDirect
.peer
= bi
->peer
;
2909 rfd
= bi
->extra
->vnc
.export
2912 vnc_zlog_debug_verbose(
2913 "%s: deleting bi=%p, bi->peer=%p, bi->type=%d, bi->sub_type=%d, bi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]",
2914 __func__
, bi
, bi
->peer
,
2915 bi
->type
, bi
->sub_type
,
2927 SAFI_MPLS_VPN
, &rn2
->p
,
2928 (struct prefix_rd
*)&rn1
2930 bi
->type
, bi
->sub_type
,
2931 NULL
, 1); /* kill */
2933 vncHDBgpDirect
.peer
= NULL
;
2939 /* Clear RHN list */
2940 if (bgp
->rfapi
->resolve_nve_nexthop
) {
2941 struct prefix_bag
*pb
;
2942 struct bgp_info
*info
;
2943 while (!skiplist_first(bgp
->rfapi
->resolve_nve_nexthop
, NULL
,
2946 skiplist_delete_first(bgp
->rfapi
->resolve_nve_nexthop
);
2947 bgp_info_unlock(info
);
2951 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 0;
2952 vnc_zlog_debug_verbose("%s: return", __func__
);
2956 void vnc_import_bgp_exterior_redist_disable(struct bgp
*bgp
, afi_t afi
)
2958 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
2959 struct bgp
*bgp_exterior
= hc
->redist_bgp_exterior_view
;
2961 vnc_zlog_debug_verbose("%s: entry", __func__
);
2963 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2964 vnc_zlog_debug_verbose(
2965 "%s: already disabled for afi %d, skipping", __func__
,
2970 if (!bgp_exterior
) {
2971 vnc_zlog_debug_verbose(
2972 "%s: bgp exterior view not defined, skipping",
2979 struct bgp_node
*rn
;
2980 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]);
2981 rn
; rn
= bgp_route_next(rn
)) {
2983 struct bgp_info
*bi
;
2985 for (bi
= rn
->info
; bi
; bi
= bi
->next
) {
2987 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
2990 vnc_import_bgp_exterior_del_route(bgp_exterior
,
2995 print_rhn_list(__func__
, NULL
);
2999 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 0;
3000 vnc_zlog_debug_verbose("%s: return", __func__
);