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(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(void *pfx1
, void *pfx2
)
137 struct prefix
*p1
= pfx1
;
138 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 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 bgp_attr_dup(&hattr
, attr
); /* hattr becomes a ghost attr */
362 struct bgp_path_info info
;
363 route_map_result_t ret
;
365 memset(&info
, 0, sizeof(info
));
368 ret
= route_map_apply(rmap
, prefix
, RMAP_BGP
, &info
);
369 if (ret
== RMAP_DENYMATCH
) {
370 bgp_attr_flush(&hattr
);
371 vnc_zlog_debug_verbose(
372 "%s: route map \"%s\" says DENY, returning",
373 __func__
, rmap
->name
);
379 * Get the (possibly altered by policy) unicast nexthop
380 * for later lookup in the Import Table by caller
382 rfapiUnicastNexthop2Prefix(afi
, &hattr
, unicast_nexthop
);
384 if (hattr
.ecommunity
)
385 *ecom
= ecommunity_dup(hattr
.ecommunity
);
387 *ecom
= ecommunity_new();
390 * Done with hattr, clean up
392 bgp_attr_flush(&hattr
);
395 * Add EC that carries original NH of iBGP route (2 bytes = magic
396 * value indicating it came from an VNC gateway; default 5226, but
397 * must be user configurable). Note that this is the nexthop before
398 * any application of policy.
401 struct ecommunity_val vnc_gateway_magic
;
404 /* Using route origin extended community type */
405 memset(&vnc_gateway_magic
, 0, sizeof(vnc_gateway_magic
));
406 vnc_gateway_magic
.val
[0] = 0x01;
407 vnc_gateway_magic
.val
[1] = 0x03;
409 /* Only works for IPv4 nexthops */
410 if (prefix
->family
== AF_INET
) {
411 memcpy(vnc_gateway_magic
.val
+ 2,
412 &unicast_nexthop
->u
.prefix4
, 4);
414 localadmin
= htons(hc
->resolve_nve_roo_local_admin
);
415 memcpy(vnc_gateway_magic
.val
+ 6, (char *)&localadmin
, 2);
417 ecommunity_add_val(*ecom
, &vnc_gateway_magic
);
424 static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
425 struct bgp
*bgp
, afi_t afi
, struct bgp_path_info
*bpi
, /* VPN bpi */
426 struct prefix_rd
*prd
, /* RD */
427 struct prefix
*prefix
, /* unicast route prefix */
428 uint32_t *local_pref
, /* NULL = no local_pref */
429 uint32_t *med
, /* NULL = no med */
430 struct ecommunity
*ecom
) /* generated ecoms */
433 struct prefix nexthop
;
434 struct rfapi_ip_addr nexthop_h
;
437 struct bgp_attr_encap_subtlv
*encaptlvs
;
440 struct rfapi_un_option optary
[3];
441 struct rfapi_un_option
*opt
= NULL
;
444 vnc_zlog_debug_verbose("%s: entry", __func__
);
446 if (bpi
->type
!= ZEBRA_ROUTE_BGP
447 && bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
) {
451 if (bpi
->sub_type
!= BGP_ROUTE_NORMAL
452 && bpi
->sub_type
!= BGP_ROUTE_STATIC
453 && bpi
->sub_type
!= BGP_ROUTE_RFP
) {
457 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
460 vncHDResolveNve
.peer
= bpi
->peer
;
461 if (!rfapiGetVncTunnelUnAddr(bpi
->attr
, &un
)) {
462 if (rfapiQprefix2Raddr(&un
, &vncHDResolveNve
.un_addr
))
465 memset(&vncHDResolveNve
.un_addr
, 0,
466 sizeof(vncHDResolveNve
.un_addr
));
469 /* Use nexthop of VPN route as nexthop of constructed route */
470 rfapiNexthop2Prefix(bpi
->attr
, &nexthop
);
471 rfapiQprefix2Raddr(&nexthop
, &nexthop_h
);
473 if (rfapiGetVncLifetime(bpi
->attr
, &lifetime
)) {
476 plifetime
= &lifetime
;
479 encaptlvs
= bpi
->attr
->vnc_subtlvs
;
480 if (bpi
->attr
->encap_tunneltype
!= BGP_ENCAP_TYPE_RESERVED
481 && bpi
->attr
->encap_tunneltype
!= BGP_ENCAP_TYPE_MPLS
) {
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
= bpi
->attr
->encap_tunneltype
;
486 /* TBD parse bpi->attr->extra->encap_subtlvs */
489 struct ecommunity
*new_ecom
= ecommunity_dup(ecom
);
491 if (bpi
->attr
->ecommunity
)
492 ecommunity_merge(new_ecom
, bpi
->attr
->ecommunity
);
495 label
= decode_label(&bpi
->extra
->label
[0]);
497 add_vnc_route(&vncHDResolveNve
, bgp
, SAFI_MPLS_VPN
,
498 prefix
, /* unicast route prefix */
499 prd
, &nexthop_h
, /* new nexthop */
500 local_pref
, plifetime
,
501 (struct bgp_tea_options
*)encaptlvs
, /* RFP options */
502 opt
, NULL
, new_ecom
, med
, /* NULL => don't set med */
503 (label
? &label
: NULL
), /* NULL= default */
504 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
505 RFAPI_AHR_RFPOPT_IS_VNCTLV
); /* flags */
507 ecommunity_free(&new_ecom
);
510 static void vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
511 struct prefix_rd
*prd
, /* RD */
512 struct bgp_table
*table_rd
, /* per-rd VPN route table */
513 afi_t afi
, struct bgp
*bgp
, struct prefix
*prefix
, /* unicast prefix */
514 struct ecommunity
*ecom
, /* generated ecoms */
515 uint32_t *local_pref
, /* NULL = no local_pref */
516 uint32_t *med
, /* NULL = no med */
517 struct prefix
*ubpi_nexthop
) /* unicast nexthop */
520 struct bgp_path_info
*bpi
;
526 char str_nh
[PREFIX_STRLEN
];
528 prefix2str(ubpi_nexthop
, str_nh
, sizeof(str_nh
));
530 vnc_zlog_debug_verbose("%s: ubpi_nexthop=%s", __func__
, str_nh
);
534 bn
= bgp_node_lookup(table_rd
, ubpi_nexthop
);
536 vnc_zlog_debug_verbose(
537 "%s: no match in RD's table for ubpi_nexthop",
542 /* Iterate over bgp_info items at this node */
543 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
) {
545 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
546 bgp
, afi
, bpi
, /* VPN bpi */
547 prd
, prefix
, local_pref
, med
, ecom
);
553 static void vnc_import_bgp_add_route_mode_resolve_nve(
554 struct bgp
*bgp
, struct prefix
*prefix
, /* unicast prefix */
555 struct bgp_path_info
*info
) /* unicast info */
557 afi_t afi
= family2afi(prefix
->family
);
559 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
561 struct ecommunity
*ecom
= NULL
;
563 uint32_t *med
= NULL
;
565 struct prefix_bag
*pb
;
566 struct bgp_node
*bnp
; /* prd table node */
569 if (VNC_DEBUG(VERBOSE
)) {
570 char str_pfx
[PREFIX_STRLEN
];
571 char str_nh
[PREFIX_STRLEN
];
574 prefix2str(prefix
, str_pfx
, sizeof(str_pfx
));
577 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &nh
);
579 prefix2str(&nh
, str_nh
, sizeof(str_nh
));
585 vnc_zlog_debug_verbose(
586 "%s(bgp=%p, unicast prefix=%s, unicast nh=%s)",
587 __func__
, bgp
, str_pfx
, str_nh
);
590 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
591 vnc_zlog_debug_verbose(
592 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
593 __func__
, info
->type
, zebra_route_string(info
->type
),
594 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
603 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
608 if (!(bgp
->rfapi_cfg
)) {
609 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
614 /* check vnc redist flag for bgp direct routes */
615 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
616 vnc_zlog_debug_verbose(
617 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
623 if (process_unicast_route(bgp
, afi
, prefix
, info
, &ecom
,
624 &pfx_unicast_nexthop
)) {
626 vnc_zlog_debug_verbose(
627 "%s: process_unicast_route error, skipping", __func__
);
631 local_pref
= calc_local_pref(info
->attr
, info
->peer
);
632 if (info
->attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
633 med
= &info
->attr
->med
;
636 * At this point, we have allocated:
638 * ecom ecommunity ptr, union of unicast and ROO parts (no NVE part)
642 * pfx_unicast_nexthop nexthop of uncast route
645 if (!bgp
->rfapi
->resolve_nve_nexthop
) {
646 bgp
->rfapi
->resolve_nve_nexthop
=
647 skiplist_new(SKIPLIST_FLAG_ALLOW_DUPLICATES
,
648 vnc_prefix_cmp
, prefix_bag_free
);
651 pb
= XCALLOC(MTYPE_RFAPI_PREFIX_BAG
, sizeof(struct prefix_bag
));
652 pb
->hpfx
= pfx_unicast_nexthop
;
656 bgp_path_info_lock(info
); /* skiplist refers to it */
657 skiplist_insert(bgp
->rfapi
->resolve_nve_nexthop
, &pb
->hpfx
, pb
);
660 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
661 * (exact match, /32). If an exact match is found, call add_vnc_route.
664 for (bnp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bnp
;
665 bnp
= bgp_route_next(bnp
)) {
667 struct bgp_table
*table
;
669 table
= bgp_node_get_bgp_table_info(bnp
);
674 vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
675 (struct prefix_rd
*)&bnp
->p
, table
, afi
, bgp
, prefix
,
676 ecom
, &local_pref
, med
, &pfx_unicast_nexthop
);
681 ecommunity_free(&ecom
);
683 vnc_zlog_debug_verbose("%s: done", __func__
);
687 static void vnc_import_bgp_add_route_mode_plain(struct bgp
*bgp
,
688 struct prefix
*prefix
,
689 struct bgp_path_info
*info
)
691 afi_t afi
= family2afi(prefix
->family
);
692 struct peer
*peer
= info
->peer
;
693 struct attr
*attr
= info
->attr
;
695 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
696 struct attr
*iattr
= NULL
;
698 struct rfapi_ip_addr vnaddr
;
699 struct prefix vn_pfx_space
;
700 struct prefix
*vn_pfx
= NULL
;
702 struct ecommunity
*ecom
= NULL
;
703 struct prefix_rd prd
;
704 struct route_map
*rmap
= NULL
;
706 uint32_t *med
= NULL
;
709 char buf
[PREFIX_STRLEN
];
711 prefix2str(prefix
, buf
, sizeof(buf
));
712 vnc_zlog_debug_verbose("%s(prefix=%s) entry", __func__
, buf
);
716 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
722 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
727 /* check vnc redist flag for bgp direct routes */
728 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
729 vnc_zlog_debug_verbose(
730 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
736 * mode "plain" specific code
739 vnc_zlog_debug_verbose("%s: NOT using redist RFG", __func__
);
744 if (hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
745 vnc_zlog_debug_verbose(
746 "%s: HC prefix list is set, checking",
748 if (prefix_list_apply(
749 hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
753 vnc_zlog_debug_verbose(
754 "%s: prefix list returns DENY, blocking route",
758 vnc_zlog_debug_verbose(
759 "%s: prefix list returns PASS, allowing route",
763 /* apply routemap, if any, later */
764 rmap
= hc
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
767 * Incoming prefix is unicast. If v6, it is in multiprotocol
769 * but if v4 it is in attr->nexthop
771 rfapiUnicastNexthop2Prefix(afi
, attr
, &vn_pfx_space
);
772 vn_pfx
= &vn_pfx_space
;
775 ahr_flags
|= RFAPI_AHR_NO_TUNNEL_SUBTLV
;
778 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
779 char buf
[PREFIX_STRLEN
];
781 prefix2str(vn_pfx
, buf
, sizeof(buf
));
782 vnc_zlog_debug_any("%s vn_pfx=%s", __func__
, buf
);
788 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
789 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
796 * This code is here because it allocates an interned attr which
797 * must be freed before we return. It's easier to put it after
798 * all of the possible returns above.
800 memset(&hattr
, 0, sizeof(struct attr
));
801 bgp_attr_dup(&hattr
, attr
); /* hattr becomes a ghost attr */
804 struct bgp_path_info info
;
805 route_map_result_t ret
;
807 memset(&info
, 0, sizeof(info
));
810 ret
= route_map_apply(rmap
, prefix
, RMAP_BGP
, &info
);
811 if (ret
== RMAP_DENYMATCH
) {
812 bgp_attr_flush(&hattr
);
813 vnc_zlog_debug_verbose(
814 "%s: route map \"%s\" says DENY, returning",
815 __func__
, rmap
->name
);
820 iattr
= bgp_attr_intern(&hattr
);
821 bgp_attr_flush(&hattr
);
823 /* Now iattr is an allocated interned attr */
826 * Mode "plain" specific code
828 * Sets RD in dummy HD
832 if (vnaddr
.addr_family
!= AF_INET
) {
833 vnc_zlog_debug_verbose(
834 "%s: can't auto-assign RD, VN AF (%d) is not IPv4, skipping",
835 __func__
, vnaddr
.addr_family
);
837 bgp_attr_unintern(&iattr
);
841 memset(&prd
, 0, sizeof(prd
));
842 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
844 if (iattr
&& iattr
->ecommunity
)
845 ecom
= ecommunity_dup(iattr
->ecommunity
);
848 local_pref
= calc_local_pref(iattr
, peer
);
850 if (iattr
&& (iattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))) {
854 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
855 char buf
[PREFIX_STRLEN
];
857 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, sizeof(buf
));
858 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
861 vncHDBgpDirect
.peer
= peer
;
862 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
863 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
864 NULL
, /* RFP options */
865 NULL
, NULL
, ecom
, med
, /* med */
866 NULL
, /* label: default */
867 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
869 vncHDBgpDirect
.peer
= NULL
;
872 ecommunity_free(&ecom
);
876 vnc_import_bgp_add_route_mode_nvegroup(struct bgp
*bgp
, struct prefix
*prefix
,
877 struct bgp_path_info
*info
,
878 struct rfapi_nve_group_cfg
*rfg
)
880 afi_t afi
= family2afi(prefix
->family
);
881 struct peer
*peer
= info
->peer
;
882 struct attr
*attr
= info
->attr
;
884 struct attr
*iattr
= NULL
;
886 struct rfapi_ip_addr vnaddr
;
887 struct prefix
*vn_pfx
= NULL
;
889 struct ecommunity
*ecom
= NULL
;
890 struct prefix_rd prd
;
891 struct route_map
*rmap
= NULL
;
895 char buf
[PREFIX_STRLEN
];
897 prefix2str(prefix
, buf
, sizeof(buf
));
898 vnc_zlog_debug_verbose("%s(prefix=%s) entry", __func__
, buf
);
904 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
909 if (!(bgp
->rfapi_cfg
)) {
910 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
915 /* check vnc redist flag for bgp direct routes */
916 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
917 vnc_zlog_debug_verbose(
918 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
929 struct rfapi_ip_prefix pfx_un
;
931 vnc_zlog_debug_verbose("%s: using redist RFG", __func__
);
934 * RFG prefix list check
936 if (rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
937 vnc_zlog_debug_verbose(
938 "%s: RFG prefix list is set, checking",
940 if (prefix_list_apply(
941 rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
945 vnc_zlog_debug_verbose(
946 "%s: prefix list returns DENY, blocking route",
950 vnc_zlog_debug_verbose(
951 "%s: prefix list returns PASS, allowing route",
955 /* apply routemap, if any, later */
956 rmap
= rfg
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
959 * export nve group's VN addr prefix must be a /32 which
960 * will yield the VN addr to use
962 vn_pfx
= &rfg
->vn_prefix
;
967 if (!is_host_prefix(&rfg
->un_prefix
)) {
968 /* NB prefixlen==0 means it has not been configured */
969 vnc_zlog_debug_verbose(
970 "%s: redist RFG UN pfx not host pfx (plen=%d), skipping",
971 __func__
, rfg
->un_prefix
.prefixlen
);
975 rfapiQprefix2Rprefix(&rfg
->un_prefix
, &pfx_un
);
977 vncHDBgpDirect
.un_addr
= pfx_un
.prefix
;
980 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
981 char buf
[PREFIX_STRLEN
];
983 prefix2str(vn_pfx
, buf
, sizeof(buf
));
984 vnc_zlog_debug_any("%s vn_pfx=%s", __func__
, buf
);
990 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
991 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
998 * This code is here because it allocates an interned attr which
999 * must be freed before we return. It's easier to put it after
1000 * all of the possible returns above.
1002 memset(&hattr
, 0, sizeof(struct attr
));
1003 bgp_attr_dup(&hattr
, attr
); /* hattr becomes a ghost attr */
1006 struct bgp_path_info path
;
1007 route_map_result_t ret
;
1009 memset(&path
, 0, sizeof(path
));
1012 ret
= route_map_apply(rmap
, prefix
, RMAP_BGP
, &path
);
1013 if (ret
== RMAP_DENYMATCH
) {
1014 bgp_attr_flush(&hattr
);
1015 vnc_zlog_debug_verbose(
1016 "%s: route map \"%s\" says DENY, returning",
1017 __func__
, rmap
->name
);
1022 iattr
= bgp_attr_intern(&hattr
);
1023 bgp_attr_flush(&hattr
);
1025 /* Now iattr is an allocated interned attr */
1030 * Sets RD in dummy HD
1035 memset(&prd
, 0, sizeof(prd
));
1037 prd
.family
= AF_UNSPEC
;
1040 if (rfg
->rd
.family
== AF_UNIX
) {
1041 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
1044 if (rfg
->rt_export_list
)
1045 ecom
= ecommunity_dup(
1046 bgp
->rfapi_cfg
->rfg_redist
->rt_export_list
);
1048 ecom
= ecommunity_new();
1050 if (iattr
&& iattr
->ecommunity
)
1051 ecom
= ecommunity_merge(ecom
, iattr
->ecommunity
);
1054 local_pref
= calc_local_pref(iattr
, peer
);
1056 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
1060 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, BUFSIZ
);
1061 buf
[BUFSIZ
- 1] = 0;
1062 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
1065 vncHDBgpDirect
.peer
= peer
;
1066 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
1067 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
1068 NULL
, /* RFP options */
1069 NULL
, NULL
, ecom
, NULL
, /* med */
1070 NULL
, /* label: default */
1071 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1073 vncHDBgpDirect
.peer
= NULL
;
1076 ecommunity_free(&ecom
);
1079 static void vnc_import_bgp_del_route_mode_plain(struct bgp
*bgp
,
1080 struct prefix
*prefix
,
1081 struct bgp_path_info
*info
)
1083 struct prefix_rd prd
;
1084 afi_t afi
= family2afi(prefix
->family
);
1085 struct prefix
*vn_pfx
= NULL
;
1086 struct rfapi_ip_addr vnaddr
;
1087 struct prefix vn_pfx_space
;
1093 * Compute VN address
1097 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &vn_pfx_space
);
1099 vnc_zlog_debug_verbose("%s: no attr, can't delete route",
1103 vn_pfx
= &vn_pfx_space
;
1105 vnaddr
.addr_family
= vn_pfx
->family
;
1106 switch (vn_pfx
->family
) {
1108 if (vn_pfx
->prefixlen
!= 32) {
1109 vnc_zlog_debug_verbose(
1110 "%s: redist VN plen (%d) != 32, skipping",
1111 __func__
, vn_pfx
->prefixlen
);
1114 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1118 if (vn_pfx
->prefixlen
!= 128) {
1119 vnc_zlog_debug_verbose(
1120 "%s: redist VN plen (%d) != 128, skipping",
1121 __func__
, vn_pfx
->prefixlen
);
1124 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1128 vnc_zlog_debug_verbose(
1129 "%s: no redist RFG VN host pfx configured, skipping",
1135 memset(&prd
, 0, sizeof(prd
));
1136 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1137 vnc_zlog_debug_verbose("%s: can't auto-assign RD, skipping",
1142 vncHDBgpDirect
.peer
= info
->peer
;
1143 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1144 vncHDBgpDirect
.peer
);
1145 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1146 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1149 vncHDBgpDirect
.peer
= NULL
;
1152 static void vnc_import_bgp_del_route_mode_nvegroup(struct bgp
*bgp
,
1153 struct prefix
*prefix
,
1154 struct bgp_path_info
*info
)
1156 struct prefix_rd prd
;
1157 afi_t afi
= family2afi(prefix
->family
);
1158 struct rfapi_nve_group_cfg
*rfg
= NULL
;
1159 struct prefix
*vn_pfx
= NULL
;
1160 struct rfapi_ip_addr vnaddr
;
1165 rfg
= bgp
->rfapi_cfg
->rfg_redist
;
1169 * Compute VN address
1173 * export nve group's VN addr prefix must be a /32 which
1174 * will yield the VN addr to use
1176 vn_pfx
= &rfg
->vn_prefix
;
1179 vnaddr
.addr_family
= vn_pfx
->family
;
1180 switch (vn_pfx
->family
) {
1182 if (vn_pfx
->prefixlen
!= 32) {
1183 vnc_zlog_debug_verbose(
1184 "%s: redist VN plen (%d) != 32, skipping",
1185 __func__
, vn_pfx
->prefixlen
);
1188 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1192 if (vn_pfx
->prefixlen
!= 128) {
1193 vnc_zlog_debug_verbose(
1194 "%s: redist VN plen (%d) != 128, skipping",
1195 __func__
, vn_pfx
->prefixlen
);
1198 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1202 vnc_zlog_debug_verbose(
1203 "%s: no redist RFG VN host pfx configured, skipping",
1208 memset(&prd
, 0, sizeof(prd
));
1210 prd
.family
= AF_UNSPEC
;
1213 if (rfg
->rd
.family
== AF_UNIX
) {
1214 /* means "auto" with VN addr */
1215 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1216 vnc_zlog_debug_verbose(
1217 "%s: can't auto-assign RD, skipping", __func__
);
1223 vncHDBgpDirect
.peer
= info
->peer
;
1224 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1225 vncHDBgpDirect
.peer
);
1226 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1227 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1230 vncHDBgpDirect
.peer
= NULL
;
1233 static void vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1234 struct bgp
*bgp
, afi_t afi
, struct bgp_path_info
*bpi
, /* VPN bpi */
1235 struct prefix_rd
*prd
, /* RD */
1236 struct prefix
*prefix
) /* unicast route prefix */
1240 if (bpi
->type
!= ZEBRA_ROUTE_BGP
1241 && bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
) {
1245 if (bpi
->sub_type
!= BGP_ROUTE_NORMAL
1246 && bpi
->sub_type
!= BGP_ROUTE_STATIC
1247 && bpi
->sub_type
!= BGP_ROUTE_RFP
) {
1251 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
1254 vncHDResolveNve
.peer
= bpi
->peer
;
1255 if (!rfapiGetVncTunnelUnAddr(bpi
->attr
, &un
)) {
1256 if (rfapiQprefix2Raddr(&un
, &vncHDResolveNve
.un_addr
))
1259 memset(&vncHDResolveNve
.un_addr
, 0,
1260 sizeof(vncHDResolveNve
.un_addr
));
1263 del_vnc_route(&vncHDResolveNve
, vncHDResolveNve
.peer
, bgp
,
1264 SAFI_MPLS_VPN
, prefix
, /* unicast route prefix */
1265 prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
, NULL
,
1269 static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1270 struct prefix_rd
*prd
,
1271 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1272 afi_t afi
, struct bgp
*bgp
, struct prefix
*prefix
, /* unicast prefix */
1273 struct prefix
*ubpi_nexthop
) /* unicast bpi's nexthop */
1275 struct bgp_node
*bn
;
1276 struct bgp_path_info
*bpi
;
1282 char str_nh
[PREFIX_STRLEN
];
1284 prefix2str(ubpi_nexthop
, str_nh
, sizeof(str_nh
));
1285 vnc_zlog_debug_verbose("%s: ubpi_nexthop=%s", __func__
, str_nh
);
1290 bn
= bgp_node_lookup(table_rd
, ubpi_nexthop
);
1292 vnc_zlog_debug_verbose(
1293 "%s: no match in RD's table for ubpi_nexthop",
1298 /* Iterate over bgp_info items at this node */
1299 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
) {
1301 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1302 bgp
, afi
, bpi
, /* VPN bpi */
1304 prefix
); /* unicast route prefix */
1307 bgp_unlock_node(bn
);
1311 vnc_import_bgp_del_route_mode_resolve_nve(struct bgp
*bgp
, afi_t afi
,
1312 struct prefix
*prefix
,
1313 struct bgp_path_info
*info
)
1315 struct ecommunity
*ecom
= NULL
;
1316 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
1318 // struct listnode *hnode;
1319 // struct rfapi_descriptor *rfd;
1320 struct prefix_bag
*pb
;
1322 struct skiplist
*sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1324 struct bgp_node
*bnp
; /* prd table node */
1327 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1332 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
1333 vnc_zlog_debug_verbose(
1334 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
1335 __func__
, info
->type
, zebra_route_string(info
->type
),
1336 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
1340 if (process_unicast_route(bgp
, afi
, prefix
, info
, &ecom
,
1341 &pfx_unicast_nexthop
)) {
1343 vnc_zlog_debug_verbose(
1344 "%s: process_unicast_route error, skipping", __func__
);
1348 rc
= skiplist_first_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1351 if (pb
->ubpi
== info
) {
1352 skiplist_delete(sl
, &pfx_unicast_nexthop
, pb
);
1353 bgp_path_info_unlock(info
);
1356 rc
= skiplist_next_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1361 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
1362 * (exact match, /32). If an exact match is found, call add_vnc_route.
1365 for (bnp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bnp
;
1366 bnp
= bgp_route_next(bnp
)) {
1368 struct bgp_table
*table
;
1370 table
= bgp_node_get_bgp_table_info(bnp
);
1375 vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1376 (struct prefix_rd
*)&bnp
->p
, table
, afi
, bgp
, prefix
,
1377 &pfx_unicast_nexthop
); /* TBD how is this set? */
1381 ecommunity_free(&ecom
);
1385 /***********************************************************************
1386 * Add/Delete CE->NVE routes
1387 ***********************************************************************/
1390 * Should be called whan a bpi is added to VPN RIB. This function
1391 * will check if it is a host route and return immediately if not.
1393 void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1394 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1395 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1396 struct prefix
*prefix
, /* VPN prefix */
1397 struct bgp_path_info
*bpi
) /* new VPN host route */
1399 afi_t afi
= family2afi(prefix
->family
);
1400 struct skiplist
*sl
= NULL
;
1402 struct prefix_bag
*pb
;
1404 struct rfapi_cfg
*hc
= NULL
;
1406 vnc_zlog_debug_verbose("%s: entry", __func__
);
1408 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1409 vnc_zlog_debug_verbose("%s: bad afi %d, skipping", __func__
,
1414 if (!(hc
= bgp
->rfapi_cfg
)) {
1415 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1420 /* check vnc redist flag for bgp direct routes */
1421 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1422 vnc_zlog_debug_verbose(
1423 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1428 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1429 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1435 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1438 vnc_zlog_debug_verbose(
1439 "%s: no resolve_nve_nexthop skiplist, skipping",
1444 if (!is_host_prefix(prefix
)) {
1445 vnc_zlog_debug_verbose("%s: not host prefix, skipping",
1450 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1452 struct ecommunity
*ecom
;
1453 struct prefix pfx_unicast_nexthop
;
1454 uint32_t *med
= NULL
;
1455 uint32_t local_pref
;
1457 memset(&pfx_unicast_nexthop
, 0,
1458 sizeof(struct prefix
)); /* keep valgrind happy */
1460 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
1461 char hbuf
[PREFIX_STRLEN
];
1462 char ubuf
[PREFIX_STRLEN
];
1464 prefix2str(&pb
->hpfx
, hbuf
, sizeof(hbuf
));
1465 prefix2str(&pb
->upfx
, ubuf
, sizeof(ubuf
));
1468 "%s: examining RHN Entry (q=%p): upfx=%s, hpfx=%s, ubpi=%p",
1469 __func__
, cursor
, ubuf
, hbuf
, pb
->ubpi
);
1472 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubpi
, &ecom
,
1473 &pfx_unicast_nexthop
)) {
1475 vnc_zlog_debug_verbose(
1476 "%s: process_unicast_route error, skipping",
1480 local_pref
= calc_local_pref(pb
->ubpi
->attr
, pb
->ubpi
->peer
);
1482 if (pb
->ubpi
->attr
->flag
1483 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
1484 med
= &pb
->ubpi
->attr
->med
;
1489 if (vnc_prefix_cmp(&pfx_unicast_nexthop
, prefix
)) {
1490 char str_unh
[PREFIX_STRLEN
];
1491 char str_nve_pfx
[PREFIX_STRLEN
];
1493 prefix2str(&pfx_unicast_nexthop
, str_unh
,
1495 prefix2str(prefix
, str_nve_pfx
, sizeof(str_nve_pfx
));
1497 vnc_zlog_debug_verbose(
1498 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %s != nve pfx %s",
1499 __func__
, str_unh
, str_nve_pfx
);
1503 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
1504 bgp
, afi
, bpi
, /* VPN bpi */
1505 prd
, &pb
->upfx
, /* unicast prefix */
1506 &local_pref
, med
, ecom
);
1509 ecommunity_free(&ecom
);
1514 char pbuf
[PREFIX_STRLEN
];
1516 prefix2str(prefix
, pbuf
, sizeof(pbuf
));
1518 vnc_zlog_debug_verbose(
1519 "%s: advancing past RHN Entry (q=%p): with prefix %s",
1520 __func__
, cursor
, pbuf
);
1521 print_rhn_list(__func__
, NULL
); /* debug */
1524 rc
= skiplist_next_value(sl
, prefix
, (void *)&pb
, &cursor
);
1526 vnc_zlog_debug_verbose("%s: done", __func__
);
1530 void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
1531 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1532 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1533 struct prefix
*prefix
, /* VPN prefix */
1534 struct bgp_path_info
*bpi
) /* old VPN host route */
1536 afi_t afi
= family2afi(prefix
->family
);
1537 struct skiplist
*sl
= NULL
;
1538 struct prefix_bag
*pb
;
1540 struct rfapi_cfg
*hc
= NULL
;
1544 char str_pfx
[PREFIX_STRLEN
];
1546 prefix2str(prefix
, str_pfx
, sizeof(str_pfx
));
1548 vnc_zlog_debug_verbose("%s(bgp=%p, nve prefix=%s)", __func__
,
1552 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
)
1555 if (!(hc
= bgp
->rfapi_cfg
)) {
1556 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1561 /* check vnc redist flag for bgp direct routes */
1562 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1563 vnc_zlog_debug_verbose(
1564 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1569 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1570 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1576 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1579 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1584 if (!is_host_prefix(prefix
)) {
1585 vnc_zlog_debug_verbose("%s: not host route, skip", __func__
);
1590 * Find all entries with key == CE in the RHN list
1592 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1595 struct ecommunity
*ecom
;
1596 struct prefix pfx_unicast_nexthop
;
1598 memset(&pfx_unicast_nexthop
, 0,
1599 sizeof(struct prefix
)); /* keep valgrind happy */
1601 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubpi
, &ecom
,
1602 &pfx_unicast_nexthop
)) {
1604 vnc_zlog_debug_verbose(
1605 "%s: process_unicast_route error, skipping",
1613 if (vnc_prefix_cmp(&pfx_unicast_nexthop
, prefix
)) {
1614 char str_unh
[PREFIX_STRLEN
];
1615 char str_nve_pfx
[PREFIX_STRLEN
];
1617 prefix2str(&pfx_unicast_nexthop
, str_unh
,
1619 prefix2str(prefix
, str_nve_pfx
, sizeof(str_nve_pfx
));
1621 vnc_zlog_debug_verbose(
1622 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %s != nve pfx %s",
1623 __func__
, str_unh
, str_nve_pfx
);
1627 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1628 bgp
, afi
, bpi
, prd
, &pb
->upfx
);
1631 ecommunity_free(&ecom
);
1633 rc
= skiplist_next_value(sl
, prefix
, (void *)&pb
, &cursor
);
1638 /***********************************************************************
1640 ***********************************************************************/
1642 #define DEBUG_IS_USABLE_INTERIOR 1
1644 static int is_usable_interior_route(struct bgp_path_info
*bpi_interior
)
1646 if (!VALID_INTERIOR_TYPE(bpi_interior
->type
)) {
1647 #if DEBUG_IS_USABLE_INTERIOR
1648 vnc_zlog_debug_verbose(
1649 "%s: NO: type %d is not valid interior type", __func__
,
1650 bpi_interior
->type
);
1654 if (!CHECK_FLAG(bpi_interior
->flags
, BGP_PATH_VALID
)) {
1655 #if DEBUG_IS_USABLE_INTERIOR
1656 vnc_zlog_debug_verbose("%s: NO: BGP_PATH_VALID not set",
1665 * There should be only one of these per prefix at a time.
1666 * This should be called as a result of selection operation
1668 * NB should be called espacially for bgp instances that are named,
1669 * because the exterior routes will always come from one of those.
1670 * We filter here on the instance name to make sure we get only the
1673 static void vnc_import_bgp_exterior_add_route_it(
1674 struct bgp
*bgp
, /* exterior instance, we hope */
1675 struct prefix
*prefix
, /* unicast prefix */
1676 struct bgp_path_info
*info
, /* unicast info */
1677 struct rfapi_import_table
*it_only
) /* NULL, or limit to this IT */
1680 struct rfapi_cfg
*hc
;
1681 struct prefix pfx_orig_nexthop
;
1682 struct rfapi_import_table
*it
;
1683 struct bgp
*bgp_default
= bgp_get_default();
1684 afi_t afi
= family2afi(prefix
->family
);
1689 h
= bgp_default
->rfapi
;
1690 hc
= bgp_default
->rfapi_cfg
;
1692 vnc_zlog_debug_verbose("%s: entry with it=%p", __func__
, it_only
);
1695 vnc_zlog_debug_verbose(
1696 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1700 if (!hc
->redist_bgp_exterior_view
) {
1701 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1705 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1706 vnc_zlog_debug_verbose(
1707 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1708 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1712 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1713 vnc_zlog_debug_verbose(
1714 "%s: redist of exterior routes not enabled, skipping",
1720 * Extract nexthop from exterior route
1722 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1723 * but if v4 it is in attr->nexthop
1725 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1727 for (it
= h
->imports
; it
; it
= it
->next
) {
1728 struct agg_table
*table
;
1729 struct agg_node
*rn
;
1730 struct agg_node
*par
;
1731 struct bgp_path_info
*bpi_interior
;
1732 int have_usable_route
;
1734 vnc_zlog_debug_verbose("%s: doing it %p", __func__
, it
);
1736 if (it_only
&& (it_only
!= it
)) {
1737 vnc_zlog_debug_verbose("%s: doesn't match it_only %p",
1742 table
= it
->imported_vpn
[afi
];
1744 for (rn
= agg_node_match(table
, &pfx_orig_nexthop
),
1745 have_usable_route
= 0;
1746 (!have_usable_route
) && rn
;) {
1748 vnc_zlog_debug_verbose("%s: it %p trying rn %p",
1751 for (bpi_interior
= rn
->info
; bpi_interior
;
1752 bpi_interior
= bpi_interior
->next
) {
1753 struct prefix_rd
*prd
;
1754 struct attr new_attr
;
1757 if (!is_usable_interior_route(bpi_interior
))
1760 vnc_zlog_debug_verbose(
1761 "%s: usable: bpi_interior %p", __func__
,
1765 * have a legitimate route to exterior's nexthop
1768 * Import unicast route to the import table
1770 have_usable_route
= 1;
1772 if (bpi_interior
->extra
) {
1773 prd
= &bpi_interior
->extra
->vnc
.import
1775 label
= decode_label(
1776 &bpi_interior
->extra
->label
[0]);
1780 /* use local_pref from unicast route */
1781 memset(&new_attr
, 0, sizeof(struct attr
));
1782 bgp_attr_dup(&new_attr
, bpi_interior
->attr
);
1783 if (info
->attr
->flag
1784 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
1785 new_attr
.local_pref
=
1786 info
->attr
->local_pref
;
1787 new_attr
.flag
|= ATTR_FLAG_BIT(
1788 BGP_ATTR_LOCAL_PREF
);
1791 rfapiBgpInfoFilteredImportVPN(
1792 it
, FIF_ACTION_UPDATE
,
1793 bpi_interior
->peer
, NULL
, /* rfd */
1794 prefix
, NULL
, afi
, prd
, &new_attr
,
1795 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1796 BGP_ROUTE_REDISTRIBUTE
, &label
);
1799 if (have_usable_route
) {
1803 * TBD factor this out into its own function
1805 struct prefix
*pfx_mon
= prefix_new();
1806 if (!RFAPI_MONITOR_EXTERIOR(rn
)->source
) {
1807 RFAPI_MONITOR_EXTERIOR(rn
)->source
=
1812 agg_lock_node(rn
); /* for skiplist */
1814 agg_lock_node(rn
); /* for skiplist entry */
1815 prefix_copy(pfx_mon
, prefix
);
1816 if (!skiplist_insert(
1817 RFAPI_MONITOR_EXTERIOR(rn
)->source
,
1820 bgp_path_info_lock(info
);
1823 par
= agg_node_parent(rn
);
1826 agg_unlock_node(rn
);
1830 agg_unlock_node(rn
);
1832 if (!have_usable_route
) {
1833 struct prefix
*pfx_mon
= prefix_new();
1834 prefix_copy(pfx_mon
, prefix
);
1835 if (!skiplist_insert(it
->monitor_exterior_orphans
, info
,
1838 bgp_path_info_lock(info
);
1844 void vnc_import_bgp_exterior_add_route(
1845 struct bgp
*bgp
, /* exterior instance, we hope */
1846 struct prefix
*prefix
, /* unicast prefix */
1847 struct bgp_path_info
*info
) /* unicast info */
1849 vnc_import_bgp_exterior_add_route_it(bgp
, prefix
, info
, NULL
);
1853 * There should be only one of these per prefix at a time.
1854 * This should probably be called as a result of selection operation.
1856 * NB should be called espacially for bgp instances that are named,
1857 * because the exterior routes will always come from one of those.
1858 * We filter here on the instance name to make sure we get only the
1861 void vnc_import_bgp_exterior_del_route(
1862 struct bgp
*bgp
, struct prefix
*prefix
, /* unicast prefix */
1863 struct bgp_path_info
*info
) /* unicast info */
1866 struct rfapi_cfg
*hc
;
1867 struct rfapi_import_table
*it
;
1868 struct prefix pfx_orig_nexthop
;
1869 afi_t afi
= family2afi(prefix
->family
);
1870 struct bgp
*bgp_default
= bgp_get_default();
1875 memset(&pfx_orig_nexthop
, 0,
1876 sizeof(struct prefix
)); /* keep valgrind happy */
1878 h
= bgp_default
->rfapi
;
1879 hc
= bgp_default
->rfapi_cfg
;
1882 vnc_zlog_debug_verbose(
1883 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1887 if (!hc
->redist_bgp_exterior_view
) {
1888 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1892 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1893 vnc_zlog_debug_verbose(
1894 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1895 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1898 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1899 vnc_zlog_debug_verbose(
1900 "%s: redist of exterior routes no enabled, skipping",
1906 * Extract nexthop from exterior route
1908 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1909 * but if v4 it is in attr->nexthop
1911 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1913 for (it
= h
->imports
; it
; it
= it
->next
) {
1914 struct agg_table
*table
;
1915 struct agg_node
*rn
;
1916 struct agg_node
*par
;
1917 struct bgp_path_info
*bpi_interior
;
1918 int have_usable_route
;
1920 table
= it
->imported_vpn
[afi
];
1922 for (rn
= agg_node_match(table
, &pfx_orig_nexthop
),
1923 have_usable_route
= 0;
1924 (!have_usable_route
) && rn
;) {
1926 for (bpi_interior
= rn
->info
; bpi_interior
;
1927 bpi_interior
= bpi_interior
->next
) {
1928 struct prefix_rd
*prd
;
1931 if (!is_usable_interior_route(bpi_interior
))
1935 * have a legitimate route to exterior's nexthop
1938 * Import unicast route to the import table
1940 have_usable_route
= 1;
1942 if (bpi_interior
->extra
) {
1943 prd
= &bpi_interior
->extra
->vnc
.import
1945 label
= decode_label(
1946 &bpi_interior
->extra
->label
[0]);
1950 rfapiBgpInfoFilteredImportVPN(
1951 it
, FIF_ACTION_KILL
, bpi_interior
->peer
,
1953 prefix
, NULL
, afi
, prd
,
1955 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1956 BGP_ROUTE_REDISTRIBUTE
, &label
);
1961 * TBD factor this out into its own function
1964 if (RFAPI_MONITOR_EXTERIOR(rn
)
1966 if (!skiplist_delete(
1967 RFAPI_MONITOR_EXTERIOR(
1972 bgp_path_info_unlock(
1979 RFAPI_MONITOR_EXTERIOR(
1983 RFAPI_MONITOR_EXTERIOR(
1986 RFAPI_MONITOR_EXTERIOR(
1997 par
= agg_node_parent(rn
);
2000 agg_unlock_node(rn
);
2004 agg_unlock_node(rn
);
2006 if (!have_usable_route
) {
2007 if (!skiplist_delete(it
->monitor_exterior_orphans
, info
,
2010 bgp_path_info_unlock(info
);
2017 * This function should be called after a new interior VPN route
2018 * has been added to an import_table.
2020 * NB should also be called whenever an existing vpn interior route
2021 * becomes valid (e.g., valid_interior_count is inremented)
2023 void vnc_import_bgp_exterior_add_route_interior(
2024 struct bgp
*bgp
, struct rfapi_import_table
*it
,
2025 struct agg_node
*rn_interior
, /* VPN IT node */
2026 struct bgp_path_info
*bpi_interior
) /* VPN IT route */
2028 afi_t afi
= family2afi(rn_interior
->p
.family
);
2029 struct agg_node
*par
;
2030 struct bgp_path_info
*bpi_exterior
;
2031 struct prefix
*pfx_exterior
; /* exterior pfx */
2034 struct list
*list_adopted
;
2036 vnc_zlog_debug_verbose("%s: entry", __func__
);
2038 if (!is_usable_interior_route(bpi_interior
)) {
2039 vnc_zlog_debug_verbose(
2040 "%s: not usable interior route, skipping", __func__
);
2044 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2045 vnc_zlog_debug_verbose(
2046 "%s: redist of exterior routes no enabled, skipping",
2051 if (it
== bgp
->rfapi
->it_ce
) {
2052 vnc_zlog_debug_verbose("%s: import table is it_ce, skipping",
2059 char str_pfx
[PREFIX_STRLEN
];
2061 prefix2str(&rn_interior
->p
, str_pfx
, sizeof(str_pfx
));
2062 vnc_zlog_debug_verbose("%s: interior prefix=%s, bpi type=%d",
2063 __func__
, str_pfx
, 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 bgp_attr_dup(&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(&rn_interior
->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(
2198 (void (*)(void *))prefix_free
);
2199 agg_lock_node(rn_interior
);
2202 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2204 bpi_exterior
, pfx_mon
);
2205 agg_lock_node(rn_interior
);
2208 * Delete constructed exterior routes based on
2211 for (bpi
= par
->info
; bpi
; bpi
= bpi
->next
) {
2214 prd
= &bpi
->extra
->vnc
.import
2216 label
= decode_label(
2217 &bpi
->extra
->label
[0]);
2221 rfapiBgpInfoFilteredImportVPN(
2222 it
, FIF_ACTION_KILL
, bpi
->peer
,
2224 pfx_exterior
, NULL
, afi
, prd
,
2226 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2227 BGP_ROUTE_REDISTRIBUTE
, &label
);
2232 * Add constructed exterior routes based on
2233 * the new interior route at longer prefix.
2235 if (bpi_interior
->extra
) {
2236 prd
= &bpi_interior
->extra
->vnc
.import
2238 label
= decode_label(
2239 &bpi_interior
->extra
->label
[0]);
2243 /* use local_pref from unicast route */
2244 memset(&new_attr
, 0, sizeof(struct attr
));
2245 bgp_attr_dup(&new_attr
, bpi_interior
->attr
);
2247 && (bpi_exterior
->attr
->flag
2248 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2249 new_attr
.local_pref
=
2250 bpi_exterior
->attr
->local_pref
;
2251 new_attr
.flag
|= ATTR_FLAG_BIT(
2252 BGP_ATTR_LOCAL_PREF
);
2255 rfapiBgpInfoFilteredImportVPN(
2256 it
, FIF_ACTION_UPDATE
,
2257 bpi_interior
->peer
, NULL
, /* rfd */
2258 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2259 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2260 BGP_ROUTE_REDISTRIBUTE
, &label
);
2265 * The only monitors at rn_interior are the ones we added just
2266 * above, so we can use the rn_interior list to identify which
2267 * monitors to delete from the parent.
2270 for (rc
= skiplist_next(
2271 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2272 (void **)&bpi_exterior
, NULL
, &cursor
);
2273 !rc
; rc
= skiplist_next(
2274 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2275 (void **)&bpi_exterior
, NULL
, &cursor
)) {
2278 skiplist_delete(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2279 bpi_exterior
, NULL
);
2280 agg_unlock_node(par
); /* sl entry */
2282 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par
)->source
)) {
2283 skiplist_free(RFAPI_MONITOR_EXTERIOR(par
)->source
);
2284 RFAPI_MONITOR_EXTERIOR(par
)->source
= NULL
;
2285 agg_unlock_node(par
); /* sl itself */
2289 vnc_zlog_debug_verbose("%s: checking orphans", __func__
);
2292 * See if any orphans can be pulled down to the current node
2295 list_adopted
= NULL
;
2296 for (rc
= skiplist_next(it
->monitor_exterior_orphans
,
2297 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2299 !rc
; rc
= skiplist_next(it
->monitor_exterior_orphans
,
2300 (void **)&bpi_exterior
,
2301 (void **)&pfx_exterior
, &cursor
)) {
2303 struct prefix pfx_nexthop
;
2304 char buf
[PREFIX_STRLEN
];
2305 afi_t afi_exterior
= family2afi(pfx_exterior
->family
);
2307 prefix2str(pfx_exterior
, buf
, sizeof(buf
));
2308 vnc_zlog_debug_verbose(
2309 "%s: checking exterior orphan at prefix %s", __func__
,
2312 if (afi_exterior
!= afi
) {
2313 vnc_zlog_debug_verbose(
2314 "%s: exterior orphan afi %d != interior afi %d, skip",
2315 __func__
, afi_exterior
, afi
);
2319 /* check original nexthop for prefix match */
2320 rfapiUnicastNexthop2Prefix(afi
, bpi_exterior
->attr
,
2323 if (prefix_match(&rn_interior
->p
, &pfx_nexthop
)) {
2325 struct prefix_rd
*prd
;
2326 struct attr new_attr
;
2332 * add monitor to longer prefix
2335 struct prefix
*pfx_mon
= prefix_new();
2336 prefix_copy(pfx_mon
, pfx_exterior
);
2337 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
) {
2338 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
=
2341 (void (*)(void *))prefix_free
);
2342 agg_lock_node(rn_interior
); /* sl */
2345 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2346 bpi_exterior
, pfx_mon
);
2347 agg_lock_node(rn_interior
); /* sl entry */
2348 if (!list_adopted
) {
2349 list_adopted
= list_new();
2351 listnode_add(list_adopted
, bpi_exterior
);
2354 * Add constructed exterior routes based on the
2355 * new interior route at the longer prefix.
2357 if (bpi_interior
->extra
) {
2358 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2359 label
= decode_label(
2360 &bpi_interior
->extra
->label
[0]);
2364 /* use local_pref from unicast route */
2365 memset(&new_attr
, 0, sizeof(struct attr
));
2366 bgp_attr_dup(&new_attr
, bpi_interior
->attr
);
2368 && (bpi_exterior
->attr
->flag
2369 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2370 new_attr
.local_pref
=
2371 bpi_exterior
->attr
->local_pref
;
2373 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2376 rfapiBgpInfoFilteredImportVPN(
2377 it
, FIF_ACTION_UPDATE
, bpi_interior
->peer
,
2379 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2380 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2381 BGP_ROUTE_REDISTRIBUTE
, &label
);
2385 struct listnode
*node
;
2386 struct agg_node
*an_bpi_exterior
;
2388 for (ALL_LIST_ELEMENTS_RO(list_adopted
, node
,
2390 skiplist_delete(it
->monitor_exterior_orphans
,
2391 an_bpi_exterior
, NULL
);
2393 list_delete(&list_adopted
);
2398 * This function should be called after an interior VPN route
2399 * has been deleted from an import_table.
2400 * bpi_interior must still be valid, but it must already be detached
2401 * from its route node and the route node's valid_interior_count
2402 * must already be decremented.
2404 * NB should also be called whenever an existing vpn interior route
2405 * becomes invalid (e.g., valid_interior_count is decremented)
2407 void vnc_import_bgp_exterior_del_route_interior(
2408 struct bgp
*bgp
, struct rfapi_import_table
*it
,
2409 struct agg_node
*rn_interior
, /* VPN IT node */
2410 struct bgp_path_info
*bpi_interior
) /* VPN IT route */
2412 afi_t afi
= family2afi(rn_interior
->p
.family
);
2413 struct agg_node
*par
;
2414 struct bgp_path_info
*bpi_exterior
;
2415 struct prefix
*pfx_exterior
; /* exterior pfx */
2419 if (!VALID_INTERIOR_TYPE(bpi_interior
->type
)) {
2420 vnc_zlog_debug_verbose(
2421 "%s: type %d not valid interior type, skipping",
2422 __func__
, bpi_interior
->type
);
2426 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2427 vnc_zlog_debug_verbose(
2428 "%s: redist of exterior routes no enabled, skipping",
2433 if (it
== bgp
->rfapi
->it_ce
) {
2434 vnc_zlog_debug_verbose("%s: it is it_ce, skipping", __func__
);
2438 /* If no exterior routes depend on this prefix, nothing to do */
2439 if (!RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
2440 vnc_zlog_debug_verbose("%s: no exterior monitor, skipping",
2447 char str_pfx
[PREFIX_STRLEN
];
2449 prefix2str(&rn_interior
->p
, str_pfx
, sizeof(str_pfx
));
2451 vnc_zlog_debug_verbose("%s: interior prefix=%s, bpi type=%d",
2452 __func__
, str_pfx
, bpi_interior
->type
);
2456 * Remove constructed routes based on the deleted interior route
2459 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2460 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2463 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2464 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2467 struct prefix_rd
*prd
;
2470 if (bpi_interior
->extra
) {
2471 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2472 label
= decode_label(&bpi_interior
->extra
->label
[0]);
2476 rfapiBgpInfoFilteredImportVPN(
2477 it
, FIF_ACTION_KILL
, bpi_interior
->peer
, NULL
, /* rfd */
2478 pfx_exterior
, NULL
, afi
, prd
, bpi_interior
->attr
,
2479 ZEBRA_ROUTE_BGP_DIRECT_EXT
, BGP_ROUTE_REDISTRIBUTE
,
2484 * If there are no remaining valid interior routes at this prefix,
2485 * we need to look up the tree for a possible node to move monitors to
2487 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
) {
2488 vnc_zlog_debug_verbose(
2489 "%s: interior routes still present, skipping",
2495 * Find nearest parent with at least one valid interior route
2496 * If none is found, par will end up NULL, and we will move
2497 * the monitors to the orphan list for this import table
2499 for (par
= agg_node_parent(rn_interior
); par
;
2500 par
= agg_node_parent(par
)) {
2501 if (RFAPI_MONITOR_EXTERIOR(par
)->valid_interior_count
)
2505 vnc_zlog_debug_verbose("%s: par=%p, ext src: %p", __func__
, par
,
2506 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2508 /* move all monitors */
2510 * We will use and delete every element of the source skiplist
2512 while (!skiplist_first(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2513 (void **)&bpi_exterior
,
2514 (void **)&pfx_exterior
)) {
2516 struct prefix
*pfx_mon
= prefix_new();
2518 prefix_copy(pfx_mon
, pfx_exterior
);
2522 struct bgp_path_info
*bpi
;
2525 * Add monitor to parent node
2527 if (!RFAPI_MONITOR_EXTERIOR(par
)->source
) {
2528 RFAPI_MONITOR_EXTERIOR(par
)->source
=
2531 (void (*)(void *))prefix_free
);
2532 agg_lock_node(par
); /* sl */
2534 skiplist_insert(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2535 bpi_exterior
, pfx_mon
);
2536 agg_lock_node(par
); /* sl entry */
2538 /* Add constructed exterior routes based on parent */
2539 for (bpi
= par
->info
; bpi
; bpi
= bpi
->next
) {
2541 struct prefix_rd
*prd
;
2542 struct attr new_attr
;
2545 if (bpi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
)
2549 prd
= &bpi
->extra
->vnc
.import
.rd
;
2550 label
= decode_label(
2551 &bpi
->extra
->label
[0]);
2555 /* use local_pref from unicast route */
2556 memset(&new_attr
, 0, sizeof(struct attr
));
2557 bgp_attr_dup(&new_attr
, bpi
->attr
);
2559 && (bpi_exterior
->attr
->flag
2560 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2561 new_attr
.local_pref
=
2562 bpi_exterior
->attr
->local_pref
;
2563 new_attr
.flag
|= ATTR_FLAG_BIT(
2564 BGP_ATTR_LOCAL_PREF
);
2567 rfapiBgpInfoFilteredImportVPN(
2568 it
, FIF_ACTION_UPDATE
, bpi
->peer
,
2570 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2571 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2572 BGP_ROUTE_REDISTRIBUTE
, &label
);
2578 * No interior route for exterior's nexthop. Save
2580 * in orphan list to await future route.
2582 skiplist_insert(it
->monitor_exterior_orphans
,
2583 bpi_exterior
, pfx_mon
);
2586 skiplist_delete_first(
2587 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2588 agg_unlock_node(rn_interior
); /* sl entry */
2590 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
)) {
2591 skiplist_free(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2592 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
= NULL
;
2593 agg_unlock_node(rn_interior
); /* sl itself */
2597 /***********************************************************************
2598 * Generic add/delete unicast routes
2599 ***********************************************************************/
2601 void vnc_import_bgp_add_route(struct bgp
*bgp
, struct prefix
*prefix
,
2602 struct bgp_path_info
*info
)
2604 afi_t afi
= family2afi(prefix
->family
);
2606 if (VNC_DEBUG(VERBOSE
)) {
2607 struct prefix pfx_nexthop
;
2608 char buf
[PREFIX_STRLEN
];
2609 char buf_nh
[PREFIX_STRLEN
];
2611 prefix2str(prefix
, buf
, sizeof(buf
));
2612 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2613 prefix2str(&pfx_nexthop
, buf_nh
, sizeof(buf_nh
));
2615 vnc_zlog_debug_verbose("%s: pfx %s, nh %s", __func__
, buf
,
2619 print_rhn_list(__func__
, "ENTER ");
2624 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
2629 if (!bgp
->rfapi_cfg
) {
2630 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2635 /* check vnc redist flag for bgp direct routes */
2636 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2637 vnc_zlog_debug_verbose(
2638 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
2639 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2643 switch (bgp
->rfapi_cfg
->redist_mode
) {
2644 case VNC_REDIST_MODE_PLAIN
:
2645 vnc_import_bgp_add_route_mode_plain(bgp
, prefix
, info
);
2648 case VNC_REDIST_MODE_RFG
:
2649 if (bgp
->rfapi_cfg
->rfg_redist
)
2650 vnc_import_bgp_add_route_mode_nvegroup(
2651 bgp
, prefix
, info
, bgp
->rfapi_cfg
->rfg_redist
);
2653 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2657 case VNC_REDIST_MODE_RESOLVE_NVE
:
2658 vnc_import_bgp_add_route_mode_resolve_nve(bgp
, prefix
, info
);
2662 print_rhn_list(__func__
, "LEAVE ");
2668 * "Withdrawing a Route" import process
2670 void vnc_import_bgp_del_route(struct bgp
*bgp
, struct prefix
*prefix
,
2671 struct bgp_path_info
*info
) /* unicast info */
2673 afi_t afi
= family2afi(prefix
->family
);
2678 struct prefix pfx_nexthop
;
2679 char buf
[PREFIX_STRLEN
];
2680 char buf_nh
[PREFIX_STRLEN
];
2682 prefix2str(prefix
, buf
, sizeof(buf
));
2683 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2684 prefix2str(&pfx_nexthop
, buf_nh
, sizeof(buf_nh
));
2686 vnc_zlog_debug_verbose("%s: pfx %s, nh %s", __func__
, buf
,
2690 print_rhn_list(__func__
, "ENTER ");
2694 if (!bgp
->rfapi_cfg
) {
2695 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2700 /* check bgp redist flag for vnc direct ("vpn") routes */
2701 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2702 vnc_zlog_debug_verbose(
2703 "%s: bgp redistribution of afi=%d VNC direct routes is off",
2708 switch (bgp
->rfapi_cfg
->redist_mode
) {
2709 case VNC_REDIST_MODE_PLAIN
:
2710 vnc_import_bgp_del_route_mode_plain(bgp
, prefix
, info
);
2713 case VNC_REDIST_MODE_RFG
:
2714 if (bgp
->rfapi_cfg
->rfg_redist
)
2715 vnc_import_bgp_del_route_mode_nvegroup(bgp
, prefix
,
2718 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2722 case VNC_REDIST_MODE_RESOLVE_NVE
:
2723 vnc_import_bgp_del_route_mode_resolve_nve(bgp
, afi
, prefix
,
2728 print_rhn_list(__func__
, "LEAVE ");
2734 /***********************************************************************
2736 ***********************************************************************/
2738 void vnc_import_bgp_redist_enable(struct bgp
*bgp
, afi_t afi
)
2740 /* iterate over bgp unicast v4 and v6 routes, call
2741 * vnc_import_bgp_add_route */
2743 struct bgp_node
*rn
;
2745 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
2747 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2748 vnc_zlog_debug_verbose(
2749 "%s: already enabled for afi %d, skipping", __func__
,
2753 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 1;
2755 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); rn
;
2756 rn
= bgp_route_next(rn
)) {
2758 struct bgp_path_info
*bpi
;
2760 for (bpi
= bgp_node_get_bgp_path_info(rn
); bpi
;
2763 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2766 vnc_import_bgp_add_route(bgp
, &rn
->p
, bpi
);
2769 vnc_zlog_debug_verbose(
2770 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2771 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2774 void vnc_import_bgp_exterior_redist_enable(struct bgp
*bgp
, afi_t afi
)
2776 struct bgp
*bgp_exterior
;
2777 struct bgp_node
*rn
;
2779 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2781 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2782 vnc_zlog_debug_verbose(
2783 "%s: already enabled for afi %d, skipping", __func__
,
2787 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 1;
2789 if (!bgp_exterior
) {
2790 vnc_zlog_debug_verbose(
2791 "%s: no exterior view set yet, no routes to import yet",
2796 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); rn
;
2797 rn
= bgp_route_next(rn
)) {
2799 struct bgp_path_info
*bpi
;
2801 for (bpi
= bgp_node_get_bgp_path_info(rn
); bpi
;
2804 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2807 vnc_import_bgp_exterior_add_route(bgp_exterior
, &rn
->p
,
2811 vnc_zlog_debug_verbose(
2812 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2813 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2817 * This function is for populating a newly-created Import Table
2819 void vnc_import_bgp_exterior_redist_enable_it(
2820 struct bgp
*bgp
, afi_t afi
, struct rfapi_import_table
*it_only
)
2822 struct bgp
*bgp_exterior
;
2823 struct bgp_node
*rn
;
2825 vnc_zlog_debug_verbose("%s: entry", __func__
);
2827 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2829 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2830 vnc_zlog_debug_verbose("%s: not enabled for afi %d, skipping",
2835 if (!bgp_exterior
) {
2836 vnc_zlog_debug_verbose(
2837 "%s: no exterior view set yet, no routes to import yet",
2842 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); rn
;
2843 rn
= bgp_route_next(rn
)) {
2845 struct bgp_path_info
*bpi
;
2847 for (bpi
= bgp_node_get_bgp_path_info(rn
); bpi
;
2850 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2853 vnc_import_bgp_exterior_add_route_it(
2854 bgp_exterior
, &rn
->p
, bpi
, it_only
);
2860 void vnc_import_bgp_redist_disable(struct bgp
*bgp
, afi_t afi
)
2863 * iterate over vpn routes, find routes of type ZEBRA_ROUTE_BGP_DIRECT,
2864 * delete (call timer expire immediately)
2866 struct bgp_node
*rn1
;
2867 struct bgp_node
*rn2
;
2869 vnc_zlog_debug_verbose("%s: entry", __func__
);
2871 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2872 vnc_zlog_debug_verbose(
2873 "%s: already disabled for afi %d, skipping", __func__
,
2879 * Two-level table for SAFI_MPLS_VPN
2880 * Be careful when changing the things we iterate over
2882 for (rn1
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); rn1
;
2883 rn1
= bgp_route_next(rn1
)) {
2885 if (bgp_node_has_bgp_path_info_data(rn1
)) {
2887 for (rn2
= bgp_table_top(
2888 bgp_node_get_bgp_table_info(rn1
));
2889 rn2
; rn2
= bgp_route_next(rn2
)) {
2891 struct bgp_path_info
*bpi
;
2892 struct bgp_path_info
*nextbpi
;
2894 for (bpi
= bgp_node_get_bgp_path_info(rn2
); bpi
;
2897 nextbpi
= bpi
->next
;
2900 == ZEBRA_ROUTE_BGP_DIRECT
) {
2902 struct rfapi_descriptor
*rfd
;
2903 vncHDBgpDirect
.peer
= bpi
->peer
;
2907 rfd
= bpi
->extra
->vnc
.export
2910 vnc_zlog_debug_verbose(
2911 "%s: deleting bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]",
2913 bpi
->peer
, bpi
->type
,
2925 rfd
, bpi
->peer
, bgp
,
2926 SAFI_MPLS_VPN
, &rn2
->p
,
2927 (struct prefix_rd
*)&rn1
2930 bpi
->sub_type
, NULL
,
2933 vncHDBgpDirect
.peer
= NULL
;
2939 /* Clear RHN list */
2940 if (bgp
->rfapi
->resolve_nve_nexthop
) {
2941 struct prefix_bag
*pb
;
2942 struct bgp_path_info
*info
;
2943 while (!skiplist_first(bgp
->rfapi
->resolve_nve_nexthop
, NULL
,
2946 skiplist_delete_first(bgp
->rfapi
->resolve_nve_nexthop
);
2947 bgp_path_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_path_info
*bpi
;
2985 for (bpi
= bgp_node_get_bgp_path_info(rn
); bpi
;
2988 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2991 vnc_import_bgp_exterior_del_route(bgp_exterior
,
2996 print_rhn_list(__func__
, NULL
);
3000 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 0;
3001 vnc_zlog_debug_verbose("%s: return", __func__
);