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
;
480 encaptlvs
= bpi
->attr
->vnc_subtlvs
;
481 if (bpi
->attr
->encap_tunneltype
!= BGP_ENCAP_TYPE_RESERVED
482 && bpi
->attr
->encap_tunneltype
!= BGP_ENCAP_TYPE_MPLS
) {
484 opt
->next
= &optary
[cur_opt
];
485 opt
= &optary
[cur_opt
++];
486 memset(opt
, 0, sizeof(struct rfapi_un_option
));
487 opt
->type
= RFAPI_UN_OPTION_TYPE_TUNNELTYPE
;
488 opt
->v
.tunnel
.type
= bpi
->attr
->encap_tunneltype
;
489 /* TBD parse bpi->attr->extra->encap_subtlvs */
495 struct ecommunity
*new_ecom
= ecommunity_dup(ecom
);
497 if (bpi
->attr
&& bpi
->attr
->ecommunity
)
498 ecommunity_merge(new_ecom
, bpi
->attr
->ecommunity
);
501 label
= decode_label(&bpi
->extra
->label
[0]);
503 add_vnc_route(&vncHDResolveNve
, bgp
, SAFI_MPLS_VPN
,
504 prefix
, /* unicast route prefix */
505 prd
, &nexthop_h
, /* new nexthop */
506 local_pref
, plifetime
,
507 (struct bgp_tea_options
*)encaptlvs
, /* RFP options */
508 opt
, NULL
, new_ecom
, med
, /* NULL => don't set med */
509 (label
? &label
: NULL
), /* NULL= default */
510 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
511 RFAPI_AHR_RFPOPT_IS_VNCTLV
); /* flags */
513 ecommunity_free(&new_ecom
);
516 static void vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
517 struct prefix_rd
*prd
, /* RD */
518 struct bgp_table
*table_rd
, /* per-rd VPN route table */
519 afi_t afi
, struct bgp
*bgp
, struct prefix
*prefix
, /* unicast prefix */
520 struct ecommunity
*ecom
, /* generated ecoms */
521 uint32_t *local_pref
, /* NULL = no local_pref */
522 uint32_t *med
, /* NULL = no med */
523 struct prefix
*ubpi_nexthop
) /* unicast nexthop */
526 struct bgp_path_info
*bpi
;
532 char str_nh
[PREFIX_STRLEN
];
534 prefix2str(ubpi_nexthop
, str_nh
, sizeof(str_nh
));
536 vnc_zlog_debug_verbose("%s: ubpi_nexthop=%s", __func__
, str_nh
);
540 bn
= bgp_node_lookup(table_rd
, ubpi_nexthop
);
542 vnc_zlog_debug_verbose(
543 "%s: no match in RD's table for ubpi_nexthop",
548 /* Iterate over bgp_path_info items at this node */
549 for (bpi
= bn
->info
; bpi
; bpi
= bpi
->next
) {
551 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
552 bgp
, afi
, bpi
, /* VPN bpi */
553 prd
, prefix
, local_pref
, med
, ecom
);
559 static void vnc_import_bgp_add_route_mode_resolve_nve(
560 struct bgp
*bgp
, struct prefix
*prefix
, /* unicast prefix */
561 struct bgp_path_info
*info
) /* unicast info */
563 afi_t afi
= family2afi(prefix
->family
);
565 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
567 struct ecommunity
*ecom
= NULL
;
569 uint32_t *med
= NULL
;
571 struct prefix_bag
*pb
;
572 struct bgp_node
*bnp
; /* prd table node */
575 if (VNC_DEBUG(VERBOSE
)) {
576 char str_pfx
[PREFIX_STRLEN
];
577 char str_nh
[PREFIX_STRLEN
];
580 prefix2str(prefix
, str_pfx
, sizeof(str_pfx
));
583 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &nh
);
585 prefix2str(&nh
, str_nh
, sizeof(str_nh
));
591 vnc_zlog_debug_verbose(
592 "%s(bgp=%p, unicast prefix=%s, unicast nh=%s)",
593 __func__
, bgp
, str_pfx
, str_nh
);
596 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
597 vnc_zlog_debug_verbose(
598 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
599 __func__
, info
->type
, zebra_route_string(info
->type
),
600 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
609 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
614 if (!(bgp
->rfapi_cfg
)) {
615 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
620 /* check vnc redist flag for bgp direct routes */
621 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
622 vnc_zlog_debug_verbose(
623 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
629 if (process_unicast_route(bgp
, afi
, prefix
, info
, &ecom
,
630 &pfx_unicast_nexthop
)) {
632 vnc_zlog_debug_verbose(
633 "%s: process_unicast_route error, skipping", __func__
);
637 local_pref
= calc_local_pref(info
->attr
, info
->peer
);
639 && (info
->attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))) {
641 med
= &info
->attr
->med
;
646 * At this point, we have allocated:
648 * ecom ecommunity ptr, union of unicast and ROO parts (no NVE part)
652 * pfx_unicast_nexthop nexthop of uncast route
655 if (!bgp
->rfapi
->resolve_nve_nexthop
) {
656 bgp
->rfapi
->resolve_nve_nexthop
=
657 skiplist_new(SKIPLIST_FLAG_ALLOW_DUPLICATES
,
658 vnc_prefix_cmp
, prefix_bag_free
);
661 pb
= XCALLOC(MTYPE_RFAPI_PREFIX_BAG
, sizeof(struct prefix_bag
));
662 pb
->hpfx
= pfx_unicast_nexthop
;
666 bgp_path_info_lock(info
); /* skiplist refers to it */
667 skiplist_insert(bgp
->rfapi
->resolve_nve_nexthop
, &pb
->hpfx
, pb
);
670 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
671 * (exact match, /32). If an exact match is found, call add_vnc_route.
674 for (bnp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bnp
;
675 bnp
= bgp_route_next(bnp
)) {
677 struct bgp_table
*table
;
679 table
= (struct bgp_table
*)(bnp
->info
);
684 vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
685 (struct prefix_rd
*)&bnp
->p
, table
, afi
, bgp
, prefix
,
686 ecom
, &local_pref
, med
, &pfx_unicast_nexthop
);
691 ecommunity_free(&ecom
);
693 vnc_zlog_debug_verbose("%s: done", __func__
);
697 static void vnc_import_bgp_add_route_mode_plain(struct bgp
*bgp
,
698 struct prefix
*prefix
,
699 struct bgp_path_info
*info
)
701 afi_t afi
= family2afi(prefix
->family
);
702 struct peer
*peer
= info
->peer
;
703 struct attr
*attr
= info
->attr
;
705 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
706 struct attr
*iattr
= NULL
;
708 struct rfapi_ip_addr vnaddr
;
709 struct prefix vn_pfx_space
;
710 struct prefix
*vn_pfx
= NULL
;
712 struct ecommunity
*ecom
= NULL
;
713 struct prefix_rd prd
;
714 struct route_map
*rmap
= NULL
;
716 uint32_t *med
= NULL
;
719 char buf
[PREFIX_STRLEN
];
721 prefix2str(prefix
, buf
, sizeof(buf
));
722 vnc_zlog_debug_verbose("%s(prefix=%s) entry", __func__
, buf
);
726 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
732 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
737 /* check vnc redist flag for bgp direct routes */
738 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
739 vnc_zlog_debug_verbose(
740 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
746 * mode "plain" specific code
749 vnc_zlog_debug_verbose("%s: NOT using redist RFG", __func__
);
754 if (hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
755 vnc_zlog_debug_verbose(
756 "%s: HC prefix list is set, checking",
758 if (prefix_list_apply(
759 hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
763 vnc_zlog_debug_verbose(
764 "%s: prefix list returns DENY, blocking route",
768 vnc_zlog_debug_verbose(
769 "%s: prefix list returns PASS, allowing route",
773 /* apply routemap, if any, later */
774 rmap
= hc
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
777 * Incoming prefix is unicast. If v6, it is in multiprotocol
779 * but if v4 it is in attr->nexthop
781 rfapiUnicastNexthop2Prefix(afi
, attr
, &vn_pfx_space
);
782 vn_pfx
= &vn_pfx_space
;
785 ahr_flags
|= RFAPI_AHR_NO_TUNNEL_SUBTLV
;
788 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
789 char buf
[PREFIX_STRLEN
];
791 prefix2str(vn_pfx
, buf
, sizeof(buf
));
792 vnc_zlog_debug_any("%s vn_pfx=%s", __func__
, buf
);
798 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
799 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
806 * This code is here because it allocates an interned attr which
807 * must be freed before we return. It's easier to put it after
808 * all of the possible returns above.
810 memset(&hattr
, 0, sizeof(struct attr
));
811 bgp_attr_dup(&hattr
, attr
); /* hattr becomes a ghost attr */
814 struct bgp_path_info info
;
815 route_map_result_t ret
;
817 memset(&info
, 0, sizeof(info
));
820 ret
= route_map_apply(rmap
, prefix
, RMAP_BGP
, &info
);
821 if (ret
== RMAP_DENYMATCH
) {
822 bgp_attr_flush(&hattr
);
823 vnc_zlog_debug_verbose(
824 "%s: route map \"%s\" says DENY, returning",
825 __func__
, rmap
->name
);
830 iattr
= bgp_attr_intern(&hattr
);
831 bgp_attr_flush(&hattr
);
833 /* Now iattr is an allocated interned attr */
836 * Mode "plain" specific code
838 * Sets RD in dummy HD
842 if (vnaddr
.addr_family
!= AF_INET
) {
843 vnc_zlog_debug_verbose(
844 "%s: can't auto-assign RD, VN AF (%d) is not IPv4, skipping",
845 __func__
, vnaddr
.addr_family
);
847 bgp_attr_unintern(&iattr
);
851 memset(&prd
, 0, sizeof(prd
));
852 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
854 if (iattr
&& iattr
->ecommunity
)
855 ecom
= ecommunity_dup(iattr
->ecommunity
);
858 local_pref
= calc_local_pref(iattr
, peer
);
860 if (iattr
&& (iattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))) {
864 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
865 char buf
[PREFIX_STRLEN
];
867 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, sizeof(buf
));
868 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
871 vncHDBgpDirect
.peer
= peer
;
872 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
873 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
874 NULL
, /* RFP options */
875 NULL
, NULL
, ecom
, med
, /* med */
876 NULL
, /* label: default */
877 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
879 vncHDBgpDirect
.peer
= NULL
;
882 ecommunity_free(&ecom
);
886 vnc_import_bgp_add_route_mode_nvegroup(struct bgp
*bgp
, struct prefix
*prefix
,
887 struct bgp_path_info
*info
,
888 struct rfapi_nve_group_cfg
*rfg
)
890 afi_t afi
= family2afi(prefix
->family
);
891 struct peer
*peer
= info
->peer
;
892 struct attr
*attr
= info
->attr
;
894 struct attr
*iattr
= NULL
;
896 struct rfapi_ip_addr vnaddr
;
897 struct prefix
*vn_pfx
= NULL
;
899 struct ecommunity
*ecom
= NULL
;
900 struct prefix_rd prd
;
901 struct route_map
*rmap
= NULL
;
905 char buf
[PREFIX_STRLEN
];
907 prefix2str(prefix
, buf
, sizeof(buf
));
908 vnc_zlog_debug_verbose("%s(prefix=%s) entry", __func__
, buf
);
914 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
919 if (!(bgp
->rfapi_cfg
)) {
920 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
925 /* check vnc redist flag for bgp direct routes */
926 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
927 vnc_zlog_debug_verbose(
928 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
939 struct rfapi_ip_prefix pfx_un
;
941 vnc_zlog_debug_verbose("%s: using redist RFG", __func__
);
944 * RFG prefix list check
946 if (rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
947 vnc_zlog_debug_verbose(
948 "%s: RFG prefix list is set, checking",
950 if (prefix_list_apply(
951 rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
955 vnc_zlog_debug_verbose(
956 "%s: prefix list returns DENY, blocking route",
960 vnc_zlog_debug_verbose(
961 "%s: prefix list returns PASS, allowing route",
965 /* apply routemap, if any, later */
966 rmap
= rfg
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
969 * export nve group's VN addr prefix must be a /32 which
970 * will yield the VN addr to use
972 vn_pfx
= &rfg
->vn_prefix
;
977 if (!is_host_prefix(&rfg
->un_prefix
)) {
978 /* NB prefixlen==0 means it has not been configured */
979 vnc_zlog_debug_verbose(
980 "%s: redist RFG UN pfx not host pfx (plen=%d), skipping",
981 __func__
, rfg
->un_prefix
.prefixlen
);
985 rfapiQprefix2Rprefix(&rfg
->un_prefix
, &pfx_un
);
987 vncHDBgpDirect
.un_addr
= pfx_un
.prefix
;
990 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
991 char buf
[PREFIX_STRLEN
];
993 prefix2str(vn_pfx
, buf
, sizeof(buf
));
994 vnc_zlog_debug_any("%s vn_pfx=%s", __func__
, buf
);
1000 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
1001 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
1007 * route map handling
1008 * This code is here because it allocates an interned attr which
1009 * must be freed before we return. It's easier to put it after
1010 * all of the possible returns above.
1012 memset(&hattr
, 0, sizeof(struct attr
));
1013 bgp_attr_dup(&hattr
, attr
); /* hattr becomes a ghost attr */
1016 struct bgp_path_info path
;
1017 route_map_result_t ret
;
1019 memset(&path
, 0, sizeof(path
));
1022 ret
= route_map_apply(rmap
, prefix
, RMAP_BGP
, &path
);
1023 if (ret
== RMAP_DENYMATCH
) {
1024 bgp_attr_flush(&hattr
);
1025 vnc_zlog_debug_verbose(
1026 "%s: route map \"%s\" says DENY, returning",
1027 __func__
, rmap
->name
);
1032 iattr
= bgp_attr_intern(&hattr
);
1033 bgp_attr_flush(&hattr
);
1035 /* Now iattr is an allocated interned attr */
1040 * Sets RD in dummy HD
1045 memset(&prd
, 0, sizeof(prd
));
1047 prd
.family
= AF_UNSPEC
;
1050 if (rfg
->rd
.family
== AF_UNIX
) {
1051 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
1054 if (rfg
->rt_export_list
)
1055 ecom
= ecommunity_dup(
1056 bgp
->rfapi_cfg
->rfg_redist
->rt_export_list
);
1058 ecom
= ecommunity_new();
1060 if (iattr
&& iattr
->ecommunity
)
1061 ecom
= ecommunity_merge(ecom
, iattr
->ecommunity
);
1064 local_pref
= calc_local_pref(iattr
, peer
);
1066 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
1070 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, BUFSIZ
);
1071 buf
[BUFSIZ
- 1] = 0;
1072 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
1075 vncHDBgpDirect
.peer
= peer
;
1076 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
1077 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
1078 NULL
, /* RFP options */
1079 NULL
, NULL
, ecom
, NULL
, /* med */
1080 NULL
, /* label: default */
1081 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1083 vncHDBgpDirect
.peer
= NULL
;
1086 ecommunity_free(&ecom
);
1089 static void vnc_import_bgp_del_route_mode_plain(struct bgp
*bgp
,
1090 struct prefix
*prefix
,
1091 struct bgp_path_info
*info
)
1093 struct prefix_rd prd
;
1094 afi_t afi
= family2afi(prefix
->family
);
1095 struct prefix
*vn_pfx
= NULL
;
1096 struct rfapi_ip_addr vnaddr
;
1097 struct prefix vn_pfx_space
;
1103 * Compute VN address
1106 if (info
&& info
->attr
) {
1107 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &vn_pfx_space
);
1109 vnc_zlog_debug_verbose("%s: no attr, can't delete route",
1113 vn_pfx
= &vn_pfx_space
;
1115 vnaddr
.addr_family
= vn_pfx
->family
;
1116 switch (vn_pfx
->family
) {
1118 if (vn_pfx
->prefixlen
!= 32) {
1119 vnc_zlog_debug_verbose(
1120 "%s: redist VN plen (%d) != 32, skipping",
1121 __func__
, vn_pfx
->prefixlen
);
1124 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1128 if (vn_pfx
->prefixlen
!= 128) {
1129 vnc_zlog_debug_verbose(
1130 "%s: redist VN plen (%d) != 128, skipping",
1131 __func__
, vn_pfx
->prefixlen
);
1134 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1138 vnc_zlog_debug_verbose(
1139 "%s: no redist RFG VN host pfx configured, skipping",
1145 memset(&prd
, 0, sizeof(prd
));
1146 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1147 vnc_zlog_debug_verbose("%s: can't auto-assign RD, skipping",
1152 vncHDBgpDirect
.peer
= info
->peer
;
1153 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1154 vncHDBgpDirect
.peer
);
1155 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1156 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1159 vncHDBgpDirect
.peer
= NULL
;
1162 static void vnc_import_bgp_del_route_mode_nvegroup(struct bgp
*bgp
,
1163 struct prefix
*prefix
,
1164 struct bgp_path_info
*info
)
1166 struct prefix_rd prd
;
1167 afi_t afi
= family2afi(prefix
->family
);
1168 struct rfapi_nve_group_cfg
*rfg
= NULL
;
1169 struct prefix
*vn_pfx
= NULL
;
1170 struct rfapi_ip_addr vnaddr
;
1175 rfg
= bgp
->rfapi_cfg
->rfg_redist
;
1179 * Compute VN address
1183 * export nve group's VN addr prefix must be a /32 which
1184 * will yield the VN addr to use
1186 vn_pfx
= &rfg
->vn_prefix
;
1189 vnaddr
.addr_family
= vn_pfx
->family
;
1190 switch (vn_pfx
->family
) {
1192 if (vn_pfx
->prefixlen
!= 32) {
1193 vnc_zlog_debug_verbose(
1194 "%s: redist VN plen (%d) != 32, skipping",
1195 __func__
, vn_pfx
->prefixlen
);
1198 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1202 if (vn_pfx
->prefixlen
!= 128) {
1203 vnc_zlog_debug_verbose(
1204 "%s: redist VN plen (%d) != 128, skipping",
1205 __func__
, vn_pfx
->prefixlen
);
1208 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1212 vnc_zlog_debug_verbose(
1213 "%s: no redist RFG VN host pfx configured, skipping",
1218 memset(&prd
, 0, sizeof(prd
));
1220 prd
.family
= AF_UNSPEC
;
1223 if (rfg
->rd
.family
== AF_UNIX
) {
1224 /* means "auto" with VN addr */
1225 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1226 vnc_zlog_debug_verbose(
1227 "%s: can't auto-assign RD, skipping", __func__
);
1233 vncHDBgpDirect
.peer
= info
->peer
;
1234 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1235 vncHDBgpDirect
.peer
);
1236 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1237 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1240 vncHDBgpDirect
.peer
= NULL
;
1243 static void vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1244 struct bgp
*bgp
, afi_t afi
, struct bgp_path_info
*bpi
, /* VPN bpi */
1245 struct prefix_rd
*prd
, /* RD */
1246 struct prefix
*prefix
) /* unicast route prefix */
1250 if (bpi
->type
!= ZEBRA_ROUTE_BGP
1251 && bpi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
) {
1255 if (bpi
->sub_type
!= BGP_ROUTE_NORMAL
1256 && bpi
->sub_type
!= BGP_ROUTE_STATIC
1257 && bpi
->sub_type
!= BGP_ROUTE_RFP
) {
1261 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
1264 vncHDResolveNve
.peer
= bpi
->peer
;
1265 if (!rfapiGetVncTunnelUnAddr(bpi
->attr
, &un
)) {
1266 if (rfapiQprefix2Raddr(&un
, &vncHDResolveNve
.un_addr
))
1269 memset(&vncHDResolveNve
.un_addr
, 0,
1270 sizeof(vncHDResolveNve
.un_addr
));
1273 del_vnc_route(&vncHDResolveNve
, vncHDResolveNve
.peer
, bgp
,
1274 SAFI_MPLS_VPN
, prefix
, /* unicast route prefix */
1275 prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
, NULL
,
1279 static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1280 struct prefix_rd
*prd
,
1281 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1282 afi_t afi
, struct bgp
*bgp
, struct prefix
*prefix
, /* unicast prefix */
1283 struct prefix
*ubpi_nexthop
) /* unicast bpi's nexthop */
1285 struct bgp_node
*bn
;
1286 struct bgp_path_info
*bpi
;
1292 char str_nh
[PREFIX_STRLEN
];
1294 prefix2str(ubpi_nexthop
, str_nh
, sizeof(str_nh
));
1295 vnc_zlog_debug_verbose("%s: ubpi_nexthop=%s", __func__
, str_nh
);
1300 bn
= bgp_node_lookup(table_rd
, ubpi_nexthop
);
1302 vnc_zlog_debug_verbose(
1303 "%s: no match in RD's table for ubpi_nexthop",
1308 /* Iterate over bgp_path_info items at this node */
1309 for (bpi
= bn
->info
; bpi
; bpi
= bpi
->next
) {
1311 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1312 bgp
, afi
, bpi
, /* VPN bpi */
1314 prefix
); /* unicast route prefix */
1317 bgp_unlock_node(bn
);
1321 vnc_import_bgp_del_route_mode_resolve_nve(struct bgp
*bgp
, afi_t afi
,
1322 struct prefix
*prefix
,
1323 struct bgp_path_info
*info
)
1325 struct ecommunity
*ecom
= NULL
;
1326 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
1328 // struct listnode *hnode;
1329 // struct rfapi_descriptor *rfd;
1330 struct prefix_bag
*pb
;
1332 struct skiplist
*sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1334 struct bgp_node
*bnp
; /* prd table node */
1337 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1342 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
1343 vnc_zlog_debug_verbose(
1344 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
1345 __func__
, info
->type
, zebra_route_string(info
->type
),
1346 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
1350 if (process_unicast_route(bgp
, afi
, prefix
, info
, &ecom
,
1351 &pfx_unicast_nexthop
)) {
1353 vnc_zlog_debug_verbose(
1354 "%s: process_unicast_route error, skipping", __func__
);
1358 rc
= skiplist_first_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1361 if (pb
->ubpi
== info
) {
1362 skiplist_delete(sl
, &pfx_unicast_nexthop
, pb
);
1363 bgp_path_info_unlock(info
);
1366 rc
= skiplist_next_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1371 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
1372 * (exact match, /32). If an exact match is found, call add_vnc_route.
1375 for (bnp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bnp
;
1376 bnp
= bgp_route_next(bnp
)) {
1378 struct bgp_table
*table
;
1380 table
= (struct bgp_table
*)(bnp
->info
);
1385 vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1386 (struct prefix_rd
*)&bnp
->p
, table
, afi
, bgp
, prefix
,
1387 &pfx_unicast_nexthop
); /* TBD how is this set? */
1391 ecommunity_free(&ecom
);
1395 /***********************************************************************
1396 * Add/Delete CE->NVE routes
1397 ***********************************************************************/
1400 * Should be called whan a bpi is added to VPN RIB. This function
1401 * will check if it is a host route and return immediately if not.
1403 void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1404 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1405 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1406 struct prefix
*prefix
, /* VPN prefix */
1407 struct bgp_path_info
*bpi
) /* new VPN host route */
1409 afi_t afi
= family2afi(prefix
->family
);
1410 struct skiplist
*sl
= NULL
;
1412 struct prefix_bag
*pb
;
1414 struct rfapi_cfg
*hc
= NULL
;
1416 vnc_zlog_debug_verbose("%s: entry", __func__
);
1418 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1419 vnc_zlog_debug_verbose("%s: bad afi %d, skipping", __func__
,
1424 if (!(hc
= bgp
->rfapi_cfg
)) {
1425 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1430 /* check vnc redist flag for bgp direct routes */
1431 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1432 vnc_zlog_debug_verbose(
1433 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1438 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1439 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1445 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1448 vnc_zlog_debug_verbose(
1449 "%s: no resolve_nve_nexthop skiplist, skipping",
1454 if (!is_host_prefix(prefix
)) {
1455 vnc_zlog_debug_verbose("%s: not host prefix, skipping",
1460 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1462 struct ecommunity
*ecom
;
1463 struct prefix pfx_unicast_nexthop
;
1464 uint32_t *med
= NULL
;
1465 uint32_t local_pref
;
1467 memset(&pfx_unicast_nexthop
, 0,
1468 sizeof(struct prefix
)); /* keep valgrind happy */
1470 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
1471 char hbuf
[PREFIX_STRLEN
];
1472 char ubuf
[PREFIX_STRLEN
];
1474 prefix2str(&pb
->hpfx
, hbuf
, sizeof(hbuf
));
1475 prefix2str(&pb
->upfx
, ubuf
, sizeof(ubuf
));
1478 "%s: examining RHN Entry (q=%p): upfx=%s, hpfx=%s, ubpi=%p",
1479 __func__
, cursor
, ubuf
, hbuf
, pb
->ubpi
);
1482 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubpi
, &ecom
,
1483 &pfx_unicast_nexthop
)) {
1485 vnc_zlog_debug_verbose(
1486 "%s: process_unicast_route error, skipping",
1490 local_pref
= calc_local_pref(pb
->ubpi
->attr
, pb
->ubpi
->peer
);
1493 && (pb
->ubpi
->attr
->flag
1494 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))) {
1496 med
= &pb
->ubpi
->attr
->med
;
1502 if (vnc_prefix_cmp(&pfx_unicast_nexthop
, prefix
)) {
1503 char str_unh
[PREFIX_STRLEN
];
1504 char str_nve_pfx
[PREFIX_STRLEN
];
1506 prefix2str(&pfx_unicast_nexthop
, str_unh
,
1508 prefix2str(prefix
, str_nve_pfx
, sizeof(str_nve_pfx
));
1510 vnc_zlog_debug_verbose(
1511 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %s != nve pfx %s",
1512 __func__
, str_unh
, str_nve_pfx
);
1516 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
1517 bgp
, afi
, bpi
, /* VPN bpi */
1518 prd
, &pb
->upfx
, /* unicast prefix */
1519 &local_pref
, med
, ecom
);
1522 ecommunity_free(&ecom
);
1527 char pbuf
[PREFIX_STRLEN
];
1529 prefix2str(prefix
, pbuf
, sizeof(pbuf
));
1531 vnc_zlog_debug_verbose(
1532 "%s: advancing past RHN Entry (q=%p): with prefix %s",
1533 __func__
, cursor
, pbuf
);
1534 print_rhn_list(__func__
, NULL
); /* debug */
1537 rc
= skiplist_next_value(sl
, prefix
, (void *)&pb
, &cursor
);
1539 vnc_zlog_debug_verbose("%s: done", __func__
);
1543 void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
1544 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1545 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1546 struct prefix
*prefix
, /* VPN prefix */
1547 struct bgp_path_info
*bpi
) /* old VPN host route */
1549 afi_t afi
= family2afi(prefix
->family
);
1550 struct skiplist
*sl
= NULL
;
1551 struct prefix_bag
*pb
;
1553 struct rfapi_cfg
*hc
= NULL
;
1557 char str_pfx
[PREFIX_STRLEN
];
1559 prefix2str(prefix
, str_pfx
, sizeof(str_pfx
));
1561 vnc_zlog_debug_verbose("%s(bgp=%p, nve prefix=%s)", __func__
,
1565 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
)
1568 if (!(hc
= bgp
->rfapi_cfg
)) {
1569 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1574 /* check vnc redist flag for bgp direct routes */
1575 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1576 vnc_zlog_debug_verbose(
1577 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1582 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1583 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1589 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1592 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1597 if (!is_host_prefix(prefix
)) {
1598 vnc_zlog_debug_verbose("%s: not host route, skip", __func__
);
1603 * Find all entries with key == CE in the RHN list
1605 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1608 struct ecommunity
*ecom
;
1609 struct prefix pfx_unicast_nexthop
;
1611 memset(&pfx_unicast_nexthop
, 0,
1612 sizeof(struct prefix
)); /* keep valgrind happy */
1614 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubpi
, &ecom
,
1615 &pfx_unicast_nexthop
)) {
1617 vnc_zlog_debug_verbose(
1618 "%s: process_unicast_route error, skipping",
1626 if (vnc_prefix_cmp(&pfx_unicast_nexthop
, prefix
)) {
1627 char str_unh
[PREFIX_STRLEN
];
1628 char str_nve_pfx
[PREFIX_STRLEN
];
1630 prefix2str(&pfx_unicast_nexthop
, str_unh
,
1632 prefix2str(prefix
, str_nve_pfx
, sizeof(str_nve_pfx
));
1634 vnc_zlog_debug_verbose(
1635 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %s != nve pfx %s",
1636 __func__
, str_unh
, str_nve_pfx
);
1640 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1641 bgp
, afi
, bpi
, prd
, &pb
->upfx
);
1644 ecommunity_free(&ecom
);
1646 rc
= skiplist_next_value(sl
, prefix
, (void *)&pb
, &cursor
);
1651 /***********************************************************************
1653 ***********************************************************************/
1655 #define DEBUG_IS_USABLE_INTERIOR 1
1657 static int is_usable_interior_route(struct bgp_path_info
*bpi_interior
)
1659 if (!VALID_INTERIOR_TYPE(bpi_interior
->type
)) {
1660 #if DEBUG_IS_USABLE_INTERIOR
1661 vnc_zlog_debug_verbose(
1662 "%s: NO: type %d is not valid interior type", __func__
,
1663 bpi_interior
->type
);
1667 if (!CHECK_FLAG(bpi_interior
->flags
, BGP_PATH_VALID
)) {
1668 #if DEBUG_IS_USABLE_INTERIOR
1669 vnc_zlog_debug_verbose("%s: NO: BGP_PATH_VALID not set",
1678 * There should be only one of these per prefix at a time.
1679 * This should be called as a result of selection operation
1681 * NB should be called espacially for bgp instances that are named,
1682 * because the exterior routes will always come from one of those.
1683 * We filter here on the instance name to make sure we get only the
1686 static void vnc_import_bgp_exterior_add_route_it(
1687 struct bgp
*bgp
, /* exterior instance, we hope */
1688 struct prefix
*prefix
, /* unicast prefix */
1689 struct bgp_path_info
*info
, /* unicast info */
1690 struct rfapi_import_table
*it_only
) /* NULL, or limit to this IT */
1693 struct rfapi_cfg
*hc
;
1694 struct prefix pfx_orig_nexthop
;
1695 struct rfapi_import_table
*it
;
1696 struct bgp
*bgp_default
= bgp_get_default();
1697 afi_t afi
= family2afi(prefix
->family
);
1702 h
= bgp_default
->rfapi
;
1703 hc
= bgp_default
->rfapi_cfg
;
1705 vnc_zlog_debug_verbose("%s: entry with it=%p", __func__
, it_only
);
1708 vnc_zlog_debug_verbose(
1709 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1713 if (!hc
->redist_bgp_exterior_view
) {
1714 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1718 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1719 vnc_zlog_debug_verbose(
1720 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1721 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1725 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1726 vnc_zlog_debug_verbose(
1727 "%s: redist of exterior routes not enabled, skipping",
1733 vnc_zlog_debug_verbose("%s: no info, skipping", __func__
);
1738 * Extract nexthop from exterior route
1740 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1741 * but if v4 it is in attr->nexthop
1743 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1745 for (it
= h
->imports
; it
; it
= it
->next
) {
1746 struct agg_table
*table
;
1747 struct agg_node
*rn
;
1748 struct agg_node
*par
;
1749 struct bgp_path_info
*bpi_interior
;
1750 int have_usable_route
;
1752 vnc_zlog_debug_verbose("%s: doing it %p", __func__
, it
);
1754 if (it_only
&& (it_only
!= it
)) {
1755 vnc_zlog_debug_verbose("%s: doesn't match it_only %p",
1760 table
= it
->imported_vpn
[afi
];
1762 for (rn
= agg_node_match(table
, &pfx_orig_nexthop
),
1763 have_usable_route
= 0;
1764 (!have_usable_route
) && rn
;) {
1766 vnc_zlog_debug_verbose("%s: it %p trying rn %p",
1769 for (bpi_interior
= rn
->info
; bpi_interior
;
1770 bpi_interior
= bpi_interior
->next
) {
1771 struct prefix_rd
*prd
;
1772 struct attr new_attr
;
1775 if (!is_usable_interior_route(bpi_interior
))
1778 vnc_zlog_debug_verbose(
1779 "%s: usable: bpi_interior %p", __func__
,
1783 * have a legitimate route to exterior's nexthop
1786 * Import unicast route to the import table
1788 have_usable_route
= 1;
1790 if (bpi_interior
->extra
) {
1791 prd
= &bpi_interior
->extra
->vnc
.import
1793 label
= decode_label(
1794 &bpi_interior
->extra
->label
[0]);
1798 /* use local_pref from unicast route */
1799 memset(&new_attr
, 0, sizeof(struct attr
));
1800 bgp_attr_dup(&new_attr
, bpi_interior
->attr
);
1801 if (info
->attr
->flag
1802 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
1803 new_attr
.local_pref
=
1804 info
->attr
->local_pref
;
1805 new_attr
.flag
|= ATTR_FLAG_BIT(
1806 BGP_ATTR_LOCAL_PREF
);
1809 rfapiBgpInfoFilteredImportVPN(
1810 it
, FIF_ACTION_UPDATE
,
1811 bpi_interior
->peer
, NULL
, /* rfd */
1812 prefix
, NULL
, afi
, prd
, &new_attr
,
1813 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1814 BGP_ROUTE_REDISTRIBUTE
, &label
);
1817 if (have_usable_route
) {
1821 * TBD factor this out into its own function
1823 struct prefix
*pfx_mon
= prefix_new();
1824 if (!RFAPI_MONITOR_EXTERIOR(rn
)->source
) {
1825 RFAPI_MONITOR_EXTERIOR(rn
)->source
=
1830 agg_lock_node(rn
); /* for skiplist */
1832 agg_lock_node(rn
); /* for skiplist entry */
1833 prefix_copy(pfx_mon
, prefix
);
1834 if (!skiplist_insert(
1835 RFAPI_MONITOR_EXTERIOR(rn
)->source
,
1838 bgp_path_info_lock(info
);
1841 par
= agg_node_parent(rn
);
1844 agg_unlock_node(rn
);
1848 agg_unlock_node(rn
);
1850 if (!have_usable_route
) {
1851 struct prefix
*pfx_mon
= prefix_new();
1852 prefix_copy(pfx_mon
, prefix
);
1853 if (!skiplist_insert(it
->monitor_exterior_orphans
, info
,
1856 bgp_path_info_lock(info
);
1862 void vnc_import_bgp_exterior_add_route(
1863 struct bgp
*bgp
, /* exterior instance, we hope */
1864 struct prefix
*prefix
, /* unicast prefix */
1865 struct bgp_path_info
*info
) /* unicast info */
1867 vnc_import_bgp_exterior_add_route_it(bgp
, prefix
, info
, NULL
);
1871 * There should be only one of these per prefix at a time.
1872 * This should probably be called as a result of selection operation.
1874 * NB should be called espacially for bgp instances that are named,
1875 * because the exterior routes will always come from one of those.
1876 * We filter here on the instance name to make sure we get only the
1879 void vnc_import_bgp_exterior_del_route(
1880 struct bgp
*bgp
, struct prefix
*prefix
, /* unicast prefix */
1881 struct bgp_path_info
*info
) /* unicast info */
1884 struct rfapi_cfg
*hc
;
1885 struct rfapi_import_table
*it
;
1886 struct prefix pfx_orig_nexthop
;
1887 afi_t afi
= family2afi(prefix
->family
);
1888 struct bgp
*bgp_default
= bgp_get_default();
1893 memset(&pfx_orig_nexthop
, 0,
1894 sizeof(struct prefix
)); /* keep valgrind happy */
1896 h
= bgp_default
->rfapi
;
1897 hc
= bgp_default
->rfapi_cfg
;
1900 vnc_zlog_debug_verbose(
1901 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1905 if (!hc
->redist_bgp_exterior_view
) {
1906 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1910 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1911 vnc_zlog_debug_verbose(
1912 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1913 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1916 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1917 vnc_zlog_debug_verbose(
1918 "%s: redist of exterior routes no enabled, skipping",
1924 vnc_zlog_debug_verbose("%s: no info, skipping", __func__
);
1929 * Extract nexthop from exterior route
1931 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1932 * but if v4 it is in attr->nexthop
1934 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1936 for (it
= h
->imports
; it
; it
= it
->next
) {
1937 struct agg_table
*table
;
1938 struct agg_node
*rn
;
1939 struct agg_node
*par
;
1940 struct bgp_path_info
*bpi_interior
;
1941 int have_usable_route
;
1943 table
= it
->imported_vpn
[afi
];
1945 for (rn
= agg_node_match(table
, &pfx_orig_nexthop
),
1946 have_usable_route
= 0;
1947 (!have_usable_route
) && rn
;) {
1949 for (bpi_interior
= rn
->info
; bpi_interior
;
1950 bpi_interior
= bpi_interior
->next
) {
1951 struct prefix_rd
*prd
;
1954 if (!is_usable_interior_route(bpi_interior
))
1958 * have a legitimate route to exterior's nexthop
1961 * Import unicast route to the import table
1963 have_usable_route
= 1;
1965 if (bpi_interior
->extra
) {
1966 prd
= &bpi_interior
->extra
->vnc
.import
1968 label
= decode_label(
1969 &bpi_interior
->extra
->label
[0]);
1973 rfapiBgpInfoFilteredImportVPN(
1974 it
, FIF_ACTION_KILL
, bpi_interior
->peer
,
1976 prefix
, NULL
, afi
, prd
,
1978 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1979 BGP_ROUTE_REDISTRIBUTE
, &label
);
1984 * TBD factor this out into its own function
1987 if (RFAPI_MONITOR_EXTERIOR(rn
)
1989 if (!skiplist_delete(
1990 RFAPI_MONITOR_EXTERIOR(
1995 bgp_path_info_unlock(
2002 RFAPI_MONITOR_EXTERIOR(
2006 RFAPI_MONITOR_EXTERIOR(
2009 RFAPI_MONITOR_EXTERIOR(
2020 par
= agg_node_parent(rn
);
2023 agg_unlock_node(rn
);
2027 agg_unlock_node(rn
);
2029 if (!have_usable_route
) {
2030 if (!skiplist_delete(it
->monitor_exterior_orphans
, info
,
2033 bgp_path_info_unlock(info
);
2040 * This function should be called after a new interior VPN route
2041 * has been added to an import_table.
2043 * NB should also be called whenever an existing vpn interior route
2044 * becomes valid (e.g., valid_interior_count is inremented)
2046 void vnc_import_bgp_exterior_add_route_interior(
2047 struct bgp
*bgp
, struct rfapi_import_table
*it
,
2048 struct agg_node
*rn_interior
, /* VPN IT node */
2049 struct bgp_path_info
*bpi_interior
) /* VPN IT route */
2051 afi_t afi
= family2afi(rn_interior
->p
.family
);
2052 struct agg_node
*par
;
2053 struct bgp_path_info
*bpi_exterior
;
2054 struct prefix
*pfx_exterior
; /* exterior pfx */
2057 struct list
*list_adopted
;
2059 vnc_zlog_debug_verbose("%s: entry", __func__
);
2061 if (!is_usable_interior_route(bpi_interior
)) {
2062 vnc_zlog_debug_verbose(
2063 "%s: not usable interior route, skipping", __func__
);
2067 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2068 vnc_zlog_debug_verbose(
2069 "%s: redist of exterior routes no enabled, skipping",
2074 if (it
== bgp
->rfapi
->it_ce
) {
2075 vnc_zlog_debug_verbose("%s: import table is it_ce, skipping",
2082 char str_pfx
[PREFIX_STRLEN
];
2084 prefix2str(&rn_interior
->p
, str_pfx
, sizeof(str_pfx
));
2085 vnc_zlog_debug_verbose("%s: interior prefix=%s, bpi type=%d",
2086 __func__
, str_pfx
, bpi_interior
->type
);
2089 if (RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
2091 int count
= 0; /* debugging */
2093 vnc_zlog_debug_verbose(
2094 "%s: has exterior monitor; ext src: %p", __func__
,
2095 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2098 * There is a monitor here already. Therefore, we do not need
2099 * to do any pulldown. Just construct exterior routes based
2100 * on the new interior route.
2103 for (rc
= skiplist_next(
2104 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2105 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2107 !rc
; rc
= skiplist_next(
2108 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2109 (void **)&bpi_exterior
,
2110 (void **)&pfx_exterior
, &cursor
)) {
2112 struct prefix_rd
*prd
;
2113 struct attr new_attr
;
2117 ++count
; /* debugging */
2119 assert(bpi_exterior
);
2120 assert(pfx_exterior
);
2122 if (bpi_interior
->extra
) {
2123 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2124 label
= decode_label(
2125 &bpi_interior
->extra
->label
[0]);
2129 /* use local_pref from unicast route */
2130 memset(&new_attr
, 0, sizeof(struct attr
));
2131 bgp_attr_dup(&new_attr
, bpi_interior
->attr
);
2133 && (bpi_exterior
->attr
->flag
2134 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2135 new_attr
.local_pref
=
2136 bpi_exterior
->attr
->local_pref
;
2138 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2141 rfapiBgpInfoFilteredImportVPN(
2142 it
, FIF_ACTION_UPDATE
, bpi_interior
->peer
,
2144 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2145 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2146 BGP_ROUTE_REDISTRIBUTE
, &label
);
2148 vnc_zlog_debug_verbose(
2149 "%s: finished constructing exteriors based on existing monitors",
2154 vnc_zlog_debug_verbose("%s: no exterior monitor", __func__
);
2157 * No monitor at this node. Is this the first valid interior
2158 * route at this node?
2160 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
> 1) {
2161 vnc_zlog_debug_verbose(
2162 "%s: new interior route not first valid one, skipping pulldown",
2168 * Look up the tree for possible pulldown candidates.
2169 * Find nearest parent with an exterior route monitor
2171 for (par
= agg_node_parent(rn_interior
); par
;
2172 par
= agg_node_parent(par
)) {
2173 if (RFAPI_HAS_MONITOR_EXTERIOR(par
))
2179 vnc_zlog_debug_verbose(
2180 "%s: checking parent %p for possible pulldowns",
2183 /* check monitors at par for possible pulldown */
2185 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2186 (void **)&bpi_exterior
,
2187 (void **)&pfx_exterior
, &cursor
);
2189 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2190 (void **)&bpi_exterior
,
2191 (void **)&pfx_exterior
, &cursor
)) {
2193 struct prefix pfx_nexthop
;
2195 memset(&pfx_nexthop
, 0,
2196 sizeof(struct prefix
)); /* keep valgrind happy */
2198 /* check original nexthop for prefix match */
2199 rfapiUnicastNexthop2Prefix(afi
, bpi_exterior
->attr
,
2202 if (prefix_match(&rn_interior
->p
, &pfx_nexthop
)) {
2204 struct bgp_path_info
*bpi
;
2205 struct prefix_rd
*prd
;
2206 struct attr new_attr
;
2212 * add monitor to longer prefix
2214 struct prefix
*pfx_mon
= prefix_new();
2215 prefix_copy(pfx_mon
, pfx_exterior
);
2216 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)
2218 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2219 ->source
= skiplist_new(
2221 (void (*)(void *))prefix_free
);
2222 agg_lock_node(rn_interior
);
2225 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2227 bpi_exterior
, pfx_mon
);
2228 agg_lock_node(rn_interior
);
2231 * Delete constructed exterior routes based on
2234 for (bpi
= par
->info
; bpi
; bpi
= bpi
->next
) {
2237 prd
= &bpi
->extra
->vnc
.import
2239 label
= decode_label(
2240 &bpi
->extra
->label
[0]);
2244 rfapiBgpInfoFilteredImportVPN(
2245 it
, FIF_ACTION_KILL
, bpi
->peer
,
2247 pfx_exterior
, NULL
, afi
, prd
,
2249 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2250 BGP_ROUTE_REDISTRIBUTE
, &label
);
2255 * Add constructed exterior routes based on
2256 * the new interior route at longer prefix.
2258 if (bpi_interior
->extra
) {
2259 prd
= &bpi_interior
->extra
->vnc
.import
2261 label
= decode_label(
2262 &bpi_interior
->extra
->label
[0]);
2266 /* use local_pref from unicast route */
2267 memset(&new_attr
, 0, sizeof(struct attr
));
2268 bgp_attr_dup(&new_attr
, bpi_interior
->attr
);
2270 && (bpi_exterior
->attr
->flag
2271 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2272 new_attr
.local_pref
=
2273 bpi_exterior
->attr
->local_pref
;
2274 new_attr
.flag
|= ATTR_FLAG_BIT(
2275 BGP_ATTR_LOCAL_PREF
);
2278 rfapiBgpInfoFilteredImportVPN(
2279 it
, FIF_ACTION_UPDATE
,
2280 bpi_interior
->peer
, NULL
, /* rfd */
2281 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2282 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2283 BGP_ROUTE_REDISTRIBUTE
, &label
);
2288 * The only monitors at rn_interior are the ones we added just
2289 * above, so we can use the rn_interior list to identify which
2290 * monitors to delete from the parent.
2293 for (rc
= skiplist_next(
2294 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2295 (void **)&bpi_exterior
, NULL
, &cursor
);
2296 !rc
; rc
= skiplist_next(
2297 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2298 (void **)&bpi_exterior
, NULL
, &cursor
)) {
2301 skiplist_delete(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2302 bpi_exterior
, NULL
);
2303 agg_unlock_node(par
); /* sl entry */
2305 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par
)->source
)) {
2306 skiplist_free(RFAPI_MONITOR_EXTERIOR(par
)->source
);
2307 RFAPI_MONITOR_EXTERIOR(par
)->source
= NULL
;
2308 agg_unlock_node(par
); /* sl itself */
2312 vnc_zlog_debug_verbose("%s: checking orphans", __func__
);
2315 * See if any orphans can be pulled down to the current node
2318 list_adopted
= NULL
;
2319 for (rc
= skiplist_next(it
->monitor_exterior_orphans
,
2320 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2322 !rc
; rc
= skiplist_next(it
->monitor_exterior_orphans
,
2323 (void **)&bpi_exterior
,
2324 (void **)&pfx_exterior
, &cursor
)) {
2326 struct prefix pfx_nexthop
;
2327 char buf
[PREFIX_STRLEN
];
2328 afi_t afi_exterior
= family2afi(pfx_exterior
->family
);
2330 prefix2str(pfx_exterior
, buf
, sizeof(buf
));
2331 vnc_zlog_debug_verbose(
2332 "%s: checking exterior orphan at prefix %s", __func__
,
2335 if (afi_exterior
!= afi
) {
2336 vnc_zlog_debug_verbose(
2337 "%s: exterior orphan afi %d != interior afi %d, skip",
2338 __func__
, afi_exterior
, afi
);
2342 /* check original nexthop for prefix match */
2343 rfapiUnicastNexthop2Prefix(afi
, bpi_exterior
->attr
,
2346 if (prefix_match(&rn_interior
->p
, &pfx_nexthop
)) {
2348 struct prefix_rd
*prd
;
2349 struct attr new_attr
;
2355 * add monitor to longer prefix
2358 struct prefix
*pfx_mon
= prefix_new();
2359 prefix_copy(pfx_mon
, pfx_exterior
);
2360 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
) {
2361 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
=
2364 (void (*)(void *))prefix_free
);
2365 agg_lock_node(rn_interior
); /* sl */
2368 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2369 bpi_exterior
, pfx_mon
);
2370 agg_lock_node(rn_interior
); /* sl entry */
2371 if (!list_adopted
) {
2372 list_adopted
= list_new();
2374 listnode_add(list_adopted
, bpi_exterior
);
2377 * Add constructed exterior routes based on the
2378 * new interior route at the longer prefix.
2380 if (bpi_interior
->extra
) {
2381 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2382 label
= decode_label(
2383 &bpi_interior
->extra
->label
[0]);
2387 /* use local_pref from unicast route */
2388 memset(&new_attr
, 0, sizeof(struct attr
));
2389 bgp_attr_dup(&new_attr
, bpi_interior
->attr
);
2391 && (bpi_exterior
->attr
->flag
2392 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2393 new_attr
.local_pref
=
2394 bpi_exterior
->attr
->local_pref
;
2396 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2399 rfapiBgpInfoFilteredImportVPN(
2400 it
, FIF_ACTION_UPDATE
, bpi_interior
->peer
,
2402 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2403 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2404 BGP_ROUTE_REDISTRIBUTE
, &label
);
2408 struct listnode
*node
;
2409 struct agg_node
*an_bpi_exterior
;
2411 for (ALL_LIST_ELEMENTS_RO(list_adopted
, node
,
2413 skiplist_delete(it
->monitor_exterior_orphans
,
2414 an_bpi_exterior
, NULL
);
2416 list_delete(&list_adopted
);
2421 * This function should be called after an interior VPN route
2422 * has been deleted from an import_table.
2423 * bpi_interior must still be valid, but it must already be detached
2424 * from its route node and the route node's valid_interior_count
2425 * must already be decremented.
2427 * NB should also be called whenever an existing vpn interior route
2428 * becomes invalid (e.g., valid_interior_count is decremented)
2430 void vnc_import_bgp_exterior_del_route_interior(
2431 struct bgp
*bgp
, struct rfapi_import_table
*it
,
2432 struct agg_node
*rn_interior
, /* VPN IT node */
2433 struct bgp_path_info
*bpi_interior
) /* VPN IT route */
2435 afi_t afi
= family2afi(rn_interior
->p
.family
);
2436 struct agg_node
*par
;
2437 struct bgp_path_info
*bpi_exterior
;
2438 struct prefix
*pfx_exterior
; /* exterior pfx */
2442 if (!VALID_INTERIOR_TYPE(bpi_interior
->type
)) {
2443 vnc_zlog_debug_verbose(
2444 "%s: type %d not valid interior type, skipping",
2445 __func__
, bpi_interior
->type
);
2449 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2450 vnc_zlog_debug_verbose(
2451 "%s: redist of exterior routes no enabled, skipping",
2456 if (it
== bgp
->rfapi
->it_ce
) {
2457 vnc_zlog_debug_verbose("%s: it is it_ce, skipping", __func__
);
2461 /* If no exterior routes depend on this prefix, nothing to do */
2462 if (!RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
2463 vnc_zlog_debug_verbose("%s: no exterior monitor, skipping",
2470 char str_pfx
[PREFIX_STRLEN
];
2472 prefix2str(&rn_interior
->p
, str_pfx
, sizeof(str_pfx
));
2474 vnc_zlog_debug_verbose("%s: interior prefix=%s, bpi type=%d",
2475 __func__
, str_pfx
, bpi_interior
->type
);
2479 * Remove constructed routes based on the deleted interior route
2482 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2483 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2486 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2487 (void **)&bpi_exterior
, (void **)&pfx_exterior
,
2490 struct prefix_rd
*prd
;
2493 if (bpi_interior
->extra
) {
2494 prd
= &bpi_interior
->extra
->vnc
.import
.rd
;
2495 label
= decode_label(&bpi_interior
->extra
->label
[0]);
2499 rfapiBgpInfoFilteredImportVPN(
2500 it
, FIF_ACTION_KILL
, bpi_interior
->peer
, NULL
, /* rfd */
2501 pfx_exterior
, NULL
, afi
, prd
, bpi_interior
->attr
,
2502 ZEBRA_ROUTE_BGP_DIRECT_EXT
, BGP_ROUTE_REDISTRIBUTE
,
2507 * If there are no remaining valid interior routes at this prefix,
2508 * we need to look up the tree for a possible node to move monitors to
2510 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
) {
2511 vnc_zlog_debug_verbose(
2512 "%s: interior routes still present, skipping",
2518 * Find nearest parent with at least one valid interior route
2519 * If none is found, par will end up NULL, and we will move
2520 * the monitors to the orphan list for this import table
2522 for (par
= agg_node_parent(rn_interior
); par
;
2523 par
= agg_node_parent(par
)) {
2524 if (RFAPI_MONITOR_EXTERIOR(par
)->valid_interior_count
)
2528 vnc_zlog_debug_verbose("%s: par=%p, ext src: %p", __func__
, par
,
2529 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2531 /* move all monitors */
2533 * We will use and delete every element of the source skiplist
2535 while (!skiplist_first(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2536 (void **)&bpi_exterior
,
2537 (void **)&pfx_exterior
)) {
2539 struct prefix
*pfx_mon
= prefix_new();
2541 prefix_copy(pfx_mon
, pfx_exterior
);
2545 struct bgp_path_info
*bpi
;
2548 * Add monitor to parent node
2550 if (!RFAPI_MONITOR_EXTERIOR(par
)->source
) {
2551 RFAPI_MONITOR_EXTERIOR(par
)->source
=
2554 (void (*)(void *))prefix_free
);
2555 agg_lock_node(par
); /* sl */
2557 skiplist_insert(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2558 bpi_exterior
, pfx_mon
);
2559 agg_lock_node(par
); /* sl entry */
2561 /* Add constructed exterior routes based on parent */
2562 for (bpi
= par
->info
; bpi
; bpi
= bpi
->next
) {
2564 struct prefix_rd
*prd
;
2565 struct attr new_attr
;
2568 if (bpi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
)
2572 prd
= &bpi
->extra
->vnc
.import
.rd
;
2573 label
= decode_label(
2574 &bpi
->extra
->label
[0]);
2578 /* use local_pref from unicast route */
2579 memset(&new_attr
, 0, sizeof(struct attr
));
2580 bgp_attr_dup(&new_attr
, bpi
->attr
);
2582 && (bpi_exterior
->attr
->flag
2583 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2584 new_attr
.local_pref
=
2585 bpi_exterior
->attr
->local_pref
;
2586 new_attr
.flag
|= ATTR_FLAG_BIT(
2587 BGP_ATTR_LOCAL_PREF
);
2590 rfapiBgpInfoFilteredImportVPN(
2591 it
, FIF_ACTION_UPDATE
, bpi
->peer
,
2593 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2594 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2595 BGP_ROUTE_REDISTRIBUTE
, &label
);
2601 * No interior route for exterior's nexthop. Save
2603 * in orphan list to await future route.
2605 skiplist_insert(it
->monitor_exterior_orphans
,
2606 bpi_exterior
, pfx_mon
);
2609 skiplist_delete_first(
2610 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2611 agg_unlock_node(rn_interior
); /* sl entry */
2613 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
)) {
2614 skiplist_free(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2615 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
= NULL
;
2616 agg_unlock_node(rn_interior
); /* sl itself */
2620 /***********************************************************************
2621 * Generic add/delete unicast routes
2622 ***********************************************************************/
2624 void vnc_import_bgp_add_route(struct bgp
*bgp
, struct prefix
*prefix
,
2625 struct bgp_path_info
*info
)
2627 afi_t afi
= family2afi(prefix
->family
);
2629 if (VNC_DEBUG(VERBOSE
)) {
2630 struct prefix pfx_nexthop
;
2631 char buf
[PREFIX_STRLEN
];
2632 char buf_nh
[PREFIX_STRLEN
];
2634 prefix2str(prefix
, buf
, sizeof(buf
));
2635 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2636 prefix2str(&pfx_nexthop
, buf_nh
, sizeof(buf_nh
));
2638 vnc_zlog_debug_verbose("%s: pfx %s, nh %s", __func__
, buf
,
2642 print_rhn_list(__func__
, "ENTER ");
2647 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of prefix",
2652 if (!bgp
->rfapi_cfg
) {
2653 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2658 /* check vnc redist flag for bgp direct routes */
2659 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2660 vnc_zlog_debug_verbose(
2661 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
2662 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2666 switch (bgp
->rfapi_cfg
->redist_mode
) {
2667 case VNC_REDIST_MODE_PLAIN
:
2668 vnc_import_bgp_add_route_mode_plain(bgp
, prefix
, info
);
2671 case VNC_REDIST_MODE_RFG
:
2672 if (bgp
->rfapi_cfg
->rfg_redist
)
2673 vnc_import_bgp_add_route_mode_nvegroup(
2674 bgp
, prefix
, info
, bgp
->rfapi_cfg
->rfg_redist
);
2676 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2680 case VNC_REDIST_MODE_RESOLVE_NVE
:
2681 vnc_import_bgp_add_route_mode_resolve_nve(bgp
, prefix
, info
);
2685 print_rhn_list(__func__
, "LEAVE ");
2691 * "Withdrawing a Route" import process
2693 void vnc_import_bgp_del_route(struct bgp
*bgp
, struct prefix
*prefix
,
2694 struct bgp_path_info
*info
) /* unicast info */
2696 afi_t afi
= family2afi(prefix
->family
);
2701 struct prefix pfx_nexthop
;
2702 char buf
[PREFIX_STRLEN
];
2703 char buf_nh
[PREFIX_STRLEN
];
2705 prefix2str(prefix
, buf
, sizeof(buf
));
2706 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2707 prefix2str(&pfx_nexthop
, buf_nh
, sizeof(buf_nh
));
2709 vnc_zlog_debug_verbose("%s: pfx %s, nh %s", __func__
, buf
,
2713 print_rhn_list(__func__
, "ENTER ");
2717 if (!bgp
->rfapi_cfg
) {
2718 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2723 /* check bgp redist flag for vnc direct ("vpn") routes */
2724 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2725 vnc_zlog_debug_verbose(
2726 "%s: bgp redistribution of afi=%d VNC direct routes is off",
2731 switch (bgp
->rfapi_cfg
->redist_mode
) {
2732 case VNC_REDIST_MODE_PLAIN
:
2733 vnc_import_bgp_del_route_mode_plain(bgp
, prefix
, info
);
2736 case VNC_REDIST_MODE_RFG
:
2737 if (bgp
->rfapi_cfg
->rfg_redist
)
2738 vnc_import_bgp_del_route_mode_nvegroup(bgp
, prefix
,
2741 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2745 case VNC_REDIST_MODE_RESOLVE_NVE
:
2746 vnc_import_bgp_del_route_mode_resolve_nve(bgp
, afi
, prefix
,
2751 print_rhn_list(__func__
, "LEAVE ");
2757 /***********************************************************************
2759 ***********************************************************************/
2761 void vnc_import_bgp_redist_enable(struct bgp
*bgp
, afi_t afi
)
2763 /* iterate over bgp unicast v4 and v6 routes, call
2764 * vnc_import_bgp_add_route */
2766 struct bgp_node
*rn
;
2768 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
2770 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2771 vnc_zlog_debug_verbose(
2772 "%s: already enabled for afi %d, skipping", __func__
,
2776 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 1;
2778 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); rn
;
2779 rn
= bgp_route_next(rn
)) {
2781 struct bgp_path_info
*bpi
;
2783 for (bpi
= rn
->info
; bpi
; bpi
= bpi
->next
) {
2785 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2788 vnc_import_bgp_add_route(bgp
, &rn
->p
, bpi
);
2791 vnc_zlog_debug_verbose(
2792 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2793 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2796 void vnc_import_bgp_exterior_redist_enable(struct bgp
*bgp
, afi_t afi
)
2798 struct bgp
*bgp_exterior
;
2799 struct bgp_node
*rn
;
2801 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2803 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2804 vnc_zlog_debug_verbose(
2805 "%s: already enabled for afi %d, skipping", __func__
,
2809 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 1;
2811 if (!bgp_exterior
) {
2812 vnc_zlog_debug_verbose(
2813 "%s: no exterior view set yet, no routes to import yet",
2818 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); rn
;
2819 rn
= bgp_route_next(rn
)) {
2821 struct bgp_path_info
*bpi
;
2823 for (bpi
= rn
->info
; bpi
; bpi
= bpi
->next
) {
2825 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2828 vnc_import_bgp_exterior_add_route(bgp_exterior
, &rn
->p
,
2832 vnc_zlog_debug_verbose(
2833 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2834 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2838 * This function is for populating a newly-created Import Table
2840 void vnc_import_bgp_exterior_redist_enable_it(
2841 struct bgp
*bgp
, afi_t afi
, struct rfapi_import_table
*it_only
)
2843 struct bgp
*bgp_exterior
;
2844 struct bgp_node
*rn
;
2846 vnc_zlog_debug_verbose("%s: entry", __func__
);
2848 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2850 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2851 vnc_zlog_debug_verbose("%s: not enabled for afi %d, skipping",
2856 if (!bgp_exterior
) {
2857 vnc_zlog_debug_verbose(
2858 "%s: no exterior view set yet, no routes to import yet",
2863 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); rn
;
2864 rn
= bgp_route_next(rn
)) {
2866 struct bgp_path_info
*bpi
;
2868 for (bpi
= rn
->info
; bpi
; bpi
= bpi
->next
) {
2870 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
2873 vnc_import_bgp_exterior_add_route_it(
2874 bgp_exterior
, &rn
->p
, bpi
, it_only
);
2880 void vnc_import_bgp_redist_disable(struct bgp
*bgp
, afi_t afi
)
2883 * iterate over vpn routes, find routes of type ZEBRA_ROUTE_BGP_DIRECT,
2884 * delete (call timer expire immediately)
2886 struct bgp_node
*rn1
;
2887 struct bgp_node
*rn2
;
2889 vnc_zlog_debug_verbose("%s: entry", __func__
);
2891 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2892 vnc_zlog_debug_verbose(
2893 "%s: already disabled for afi %d, skipping", __func__
,
2899 * Two-level table for SAFI_MPLS_VPN
2900 * Be careful when changing the things we iterate over
2902 for (rn1
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); rn1
;
2903 rn1
= bgp_route_next(rn1
)) {
2906 for (rn2
= bgp_table_top(rn1
->info
); rn2
;
2907 rn2
= bgp_route_next(rn2
)) {
2909 struct bgp_path_info
*bpi
;
2910 struct bgp_path_info
*nextbpi
;
2912 for (bpi
= rn2
->info
; bpi
; bpi
= nextbpi
) {
2914 nextbpi
= bpi
->next
;
2917 == ZEBRA_ROUTE_BGP_DIRECT
) {
2919 struct rfapi_descriptor
*rfd
;
2920 vncHDBgpDirect
.peer
= bpi
->peer
;
2924 rfd
= bpi
->extra
->vnc
.export
2927 vnc_zlog_debug_verbose(
2928 "%s: deleting bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]",
2930 bpi
->peer
, bpi
->type
,
2942 rfd
, bpi
->peer
, bgp
,
2943 SAFI_MPLS_VPN
, &rn2
->p
,
2944 (struct prefix_rd
*)&rn1
2947 bpi
->sub_type
, NULL
,
2950 vncHDBgpDirect
.peer
= NULL
;
2956 /* Clear RHN list */
2957 if (bgp
->rfapi
->resolve_nve_nexthop
) {
2958 struct prefix_bag
*pb
;
2959 struct bgp_path_info
*info
;
2960 while (!skiplist_first(bgp
->rfapi
->resolve_nve_nexthop
, NULL
,
2963 skiplist_delete_first(bgp
->rfapi
->resolve_nve_nexthop
);
2964 bgp_path_info_unlock(info
);
2968 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 0;
2969 vnc_zlog_debug_verbose("%s: return", __func__
);
2973 void vnc_import_bgp_exterior_redist_disable(struct bgp
*bgp
, afi_t afi
)
2975 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
2976 struct bgp
*bgp_exterior
= hc
->redist_bgp_exterior_view
;
2978 vnc_zlog_debug_verbose("%s: entry", __func__
);
2980 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2981 vnc_zlog_debug_verbose(
2982 "%s: already disabled for afi %d, skipping", __func__
,
2987 if (!bgp_exterior
) {
2988 vnc_zlog_debug_verbose(
2989 "%s: bgp exterior view not defined, skipping",
2996 struct bgp_node
*rn
;
2997 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]);
2998 rn
; rn
= bgp_route_next(rn
)) {
3000 struct bgp_path_info
*bpi
;
3002 for (bpi
= rn
->info
; bpi
; bpi
= bpi
->next
) {
3004 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
3007 vnc_import_bgp_exterior_del_route(bgp_exterior
,
3012 print_rhn_list(__func__
, NULL
);
3016 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 0;
3017 vnc_zlog_debug_verbose("%s: return", __func__
);