3 * Copyright 2009-2016, LabN Consulting, L.L.C.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 * File: vnc_import_bgp.c
23 * Purpose: Import routes from BGP unicast directly (not via zebra)
26 #include "lib/zebra.h"
27 #include "lib/prefix.h"
28 #include "lib/table.h"
31 #include "lib/memory.h"
32 #include "lib/linklist.h"
33 #include "lib/plist.h"
34 #include "lib/routemap.h"
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_info
*ubi
; /* 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, ubi=%p",
221 ++count
, p
, kbuf
, ubuf
, hbuf
, pb
->ubi
);
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
->ubi
->attr
,
259 /* pb->hpfx, pb->ubi 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 bi 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_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_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_info
*bi
, /* VPN bi */
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 (bi
->type
!= ZEBRA_ROUTE_BGP
&& bi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
) {
450 if (bi
->sub_type
!= BGP_ROUTE_NORMAL
&& bi
->sub_type
!= BGP_ROUTE_STATIC
451 && bi
->sub_type
!= BGP_ROUTE_RFP
) {
455 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
458 vncHDResolveNve
.peer
= bi
->peer
;
459 if (!rfapiGetVncTunnelUnAddr(bi
->attr
, &un
)) {
460 if (rfapiQprefix2Raddr(&un
, &vncHDResolveNve
.un_addr
))
463 memset(&vncHDResolveNve
.un_addr
, 0,
464 sizeof(vncHDResolveNve
.un_addr
));
467 /* Use nexthop of VPN route as nexthop of constructed route */
468 rfapiNexthop2Prefix(bi
->attr
, &nexthop
);
469 rfapiQprefix2Raddr(&nexthop
, &nexthop_h
);
471 if (rfapiGetVncLifetime(bi
->attr
, &lifetime
)) {
474 plifetime
= &lifetime
;
478 encaptlvs
= bi
->attr
->vnc_subtlvs
;
479 if (bi
->attr
->encap_tunneltype
!= BGP_ENCAP_TYPE_RESERVED
480 && bi
->attr
->encap_tunneltype
!= BGP_ENCAP_TYPE_MPLS
) {
482 opt
->next
= &optary
[cur_opt
];
483 opt
= &optary
[cur_opt
++];
484 memset(opt
, 0, sizeof(struct rfapi_un_option
));
485 opt
->type
= RFAPI_UN_OPTION_TYPE_TUNNELTYPE
;
486 opt
->v
.tunnel
.type
= bi
->attr
->encap_tunneltype
;
487 /* TBD parse bi->attr->extra->encap_subtlvs */
493 struct ecommunity
*new_ecom
= ecommunity_dup(ecom
);
495 if (bi
->attr
&& bi
->attr
->ecommunity
)
496 ecommunity_merge(new_ecom
, bi
->attr
->ecommunity
);
499 label
= decode_label(&bi
->extra
->label
[0]);
501 add_vnc_route(&vncHDResolveNve
, bgp
, SAFI_MPLS_VPN
,
502 prefix
, /* unicast route prefix */
503 prd
, &nexthop_h
, /* new nexthop */
504 local_pref
, plifetime
,
505 (struct bgp_tea_options
*)encaptlvs
, /* RFP options */
506 opt
, NULL
, new_ecom
, med
, /* NULL => don't set med */
507 (label
? &label
: NULL
), /* NULL= default */
508 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
509 RFAPI_AHR_RFPOPT_IS_VNCTLV
); /* flags */
511 ecommunity_free(&new_ecom
);
514 static void vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
515 struct prefix_rd
*prd
, /* RD */
516 struct bgp_table
*table_rd
, /* per-rd VPN route table */
517 afi_t afi
, struct bgp
*bgp
, struct prefix
*prefix
, /* unicast prefix */
518 struct ecommunity
*ecom
, /* generated ecoms */
519 uint32_t *local_pref
, /* NULL = no local_pref */
520 uint32_t *med
, /* NULL = no med */
521 struct prefix
*ubi_nexthop
) /* unicast nexthop */
530 char str_nh
[PREFIX_STRLEN
];
532 prefix2str(ubi_nexthop
, str_nh
, sizeof(str_nh
));
534 vnc_zlog_debug_verbose("%s: ubi_nexthop=%s", __func__
, str_nh
);
538 bn
= bgp_node_lookup(table_rd
, ubi_nexthop
);
540 vnc_zlog_debug_verbose(
541 "%s: no match in RD's table for ubi_nexthop", __func__
);
545 /* Iterate over bgp_info items at this node */
546 for (bi
= bn
->info
; bi
; bi
= bi
->next
) {
548 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
549 bgp
, afi
, bi
, /* VPN bi */
550 prd
, prefix
, local_pref
, med
, ecom
);
556 static void vnc_import_bgp_add_route_mode_resolve_nve(
557 struct bgp
*bgp
, struct prefix
*prefix
, /* unicast prefix */
558 struct bgp_info
*info
) /* unicast info */
560 afi_t afi
= family2afi(prefix
->family
);
562 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
564 struct ecommunity
*ecom
= NULL
;
566 uint32_t *med
= NULL
;
568 struct prefix_bag
*pb
;
569 struct bgp_node
*bnp
; /* prd table node */
572 if (VNC_DEBUG(VERBOSE
)) {
573 char str_pfx
[PREFIX_STRLEN
];
574 char str_nh
[PREFIX_STRLEN
];
577 prefix2str(prefix
, str_pfx
, sizeof(str_pfx
));
580 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &nh
);
582 prefix2str(&nh
, str_nh
, sizeof(str_nh
));
588 vnc_zlog_debug_verbose(
589 "%s(bgp=%p, unicast prefix=%s, unicast nh=%s)",
590 __func__
, bgp
, str_pfx
, str_nh
);
593 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
594 vnc_zlog_debug_verbose(
595 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
596 __func__
, info
->type
, zebra_route_string(info
->type
),
597 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
606 flog_err(LIB_ERR_DEVELOPMENT
, "%s: can't get afi of prefix",
611 if (!(bgp
->rfapi_cfg
)) {
612 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
617 /* check vnc redist flag for bgp direct routes */
618 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
619 vnc_zlog_debug_verbose(
620 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
626 if (process_unicast_route(bgp
, afi
, prefix
, info
, &ecom
,
627 &pfx_unicast_nexthop
)) {
629 vnc_zlog_debug_verbose(
630 "%s: process_unicast_route error, skipping", __func__
);
634 local_pref
= calc_local_pref(info
->attr
, info
->peer
);
636 && (info
->attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))) {
638 med
= &info
->attr
->med
;
643 * At this point, we have allocated:
645 * ecom ecommunity ptr, union of unicast and ROO parts (no NVE part)
649 * pfx_unicast_nexthop nexthop of uncast route
652 if (!bgp
->rfapi
->resolve_nve_nexthop
) {
653 bgp
->rfapi
->resolve_nve_nexthop
=
654 skiplist_new(SKIPLIST_FLAG_ALLOW_DUPLICATES
,
655 vnc_prefix_cmp
, prefix_bag_free
);
658 pb
= XCALLOC(MTYPE_RFAPI_PREFIX_BAG
, sizeof(struct prefix_bag
));
659 pb
->hpfx
= pfx_unicast_nexthop
;
663 bgp_info_lock(info
); /* skiplist refers to it */
664 skiplist_insert(bgp
->rfapi
->resolve_nve_nexthop
, &pb
->hpfx
, pb
);
667 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
668 * (exact match, /32). If an exact match is found, call add_vnc_route.
671 for (bnp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bnp
;
672 bnp
= bgp_route_next(bnp
)) {
674 struct bgp_table
*table
;
676 table
= (struct bgp_table
*)(bnp
->info
);
681 vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
682 (struct prefix_rd
*)&bnp
->p
, table
, afi
, bgp
, prefix
,
683 ecom
, &local_pref
, med
, &pfx_unicast_nexthop
);
688 ecommunity_free(&ecom
);
690 vnc_zlog_debug_verbose("%s: done", __func__
);
694 static void vnc_import_bgp_add_route_mode_plain(struct bgp
*bgp
,
695 struct prefix
*prefix
,
696 struct bgp_info
*info
)
698 afi_t afi
= family2afi(prefix
->family
);
699 struct peer
*peer
= info
->peer
;
700 struct attr
*attr
= info
->attr
;
702 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
703 struct attr
*iattr
= NULL
;
705 struct rfapi_ip_addr vnaddr
;
706 struct prefix vn_pfx_space
;
707 struct prefix
*vn_pfx
= NULL
;
709 struct ecommunity
*ecom
= NULL
;
710 struct prefix_rd prd
;
711 struct route_map
*rmap
= NULL
;
713 uint32_t *med
= NULL
;
716 char buf
[PREFIX_STRLEN
];
718 prefix2str(prefix
, buf
, sizeof(buf
));
719 vnc_zlog_debug_verbose("%s(prefix=%s) entry", __func__
, buf
);
723 flog_err(LIB_ERR_DEVELOPMENT
, "%s: can't get afi of prefix",
729 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
734 /* check vnc redist flag for bgp direct routes */
735 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
736 vnc_zlog_debug_verbose(
737 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
743 * mode "plain" specific code
746 vnc_zlog_debug_verbose("%s: NOT using redist RFG", __func__
);
751 if (hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
752 vnc_zlog_debug_verbose(
753 "%s: HC prefix list is set, checking",
755 if (prefix_list_apply(
756 hc
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
760 vnc_zlog_debug_verbose(
761 "%s: prefix list returns DENY, blocking route",
765 vnc_zlog_debug_verbose(
766 "%s: prefix list returns PASS, allowing route",
770 /* apply routemap, if any, later */
771 rmap
= hc
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
774 * Incoming prefix is unicast. If v6, it is in multiprotocol
776 * but if v4 it is in attr->nexthop
778 rfapiUnicastNexthop2Prefix(afi
, attr
, &vn_pfx_space
);
779 vn_pfx
= &vn_pfx_space
;
782 ahr_flags
|= RFAPI_AHR_NO_TUNNEL_SUBTLV
;
785 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
786 char buf
[PREFIX_STRLEN
];
788 prefix2str(vn_pfx
, buf
, sizeof(buf
));
789 vnc_zlog_debug_any("%s vn_pfx=%s", __func__
, buf
);
795 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
796 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
803 * This code is here because it allocates an interned attr which
804 * must be freed before we return. It's easier to put it after
805 * all of the possible returns above.
807 memset(&hattr
, 0, sizeof(struct attr
));
808 bgp_attr_dup(&hattr
, attr
); /* hattr becomes a ghost attr */
811 struct bgp_info info
;
812 route_map_result_t ret
;
814 memset(&info
, 0, sizeof(info
));
817 ret
= route_map_apply(rmap
, prefix
, RMAP_BGP
, &info
);
818 if (ret
== RMAP_DENYMATCH
) {
819 bgp_attr_flush(&hattr
);
820 vnc_zlog_debug_verbose(
821 "%s: route map \"%s\" says DENY, returning",
822 __func__
, rmap
->name
);
827 iattr
= bgp_attr_intern(&hattr
);
828 bgp_attr_flush(&hattr
);
830 /* Now iattr is an allocated interned attr */
833 * Mode "plain" specific code
835 * Sets RD in dummy HD
839 if (vnaddr
.addr_family
!= AF_INET
) {
840 vnc_zlog_debug_verbose(
841 "%s: can't auto-assign RD, VN AF (%d) is not IPv4, skipping",
842 __func__
, vnaddr
.addr_family
);
844 bgp_attr_unintern(&iattr
);
848 memset(&prd
, 0, sizeof(prd
));
849 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
851 if (iattr
&& iattr
->ecommunity
)
852 ecom
= ecommunity_dup(iattr
->ecommunity
);
855 local_pref
= calc_local_pref(iattr
, peer
);
857 if (iattr
&& (iattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))) {
861 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
862 char buf
[PREFIX_STRLEN
];
864 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, sizeof(buf
));
865 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
868 vncHDBgpDirect
.peer
= peer
;
869 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
870 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
871 NULL
, /* RFP options */
872 NULL
, NULL
, ecom
, med
, /* med */
873 NULL
, /* label: default */
874 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
876 vncHDBgpDirect
.peer
= NULL
;
879 ecommunity_free(&ecom
);
883 vnc_import_bgp_add_route_mode_nvegroup(struct bgp
*bgp
, struct prefix
*prefix
,
884 struct bgp_info
*info
,
885 struct rfapi_nve_group_cfg
*rfg
)
887 afi_t afi
= family2afi(prefix
->family
);
888 struct peer
*peer
= info
->peer
;
889 struct attr
*attr
= info
->attr
;
891 struct attr
*iattr
= NULL
;
893 struct rfapi_ip_addr vnaddr
;
894 struct prefix
*vn_pfx
= NULL
;
896 struct ecommunity
*ecom
= NULL
;
897 struct prefix_rd prd
;
898 struct route_map
*rmap
= NULL
;
902 char buf
[PREFIX_STRLEN
];
904 prefix2str(prefix
, buf
, sizeof(buf
));
905 vnc_zlog_debug_verbose("%s(prefix=%s) entry", __func__
, buf
);
911 flog_err(LIB_ERR_DEVELOPMENT
, "%s: can't get afi of prefix",
916 if (!(bgp
->rfapi_cfg
)) {
917 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
922 /* check vnc redist flag for bgp direct routes */
923 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
924 vnc_zlog_debug_verbose(
925 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
936 struct rfapi_ip_prefix pfx_un
;
938 vnc_zlog_debug_verbose("%s: using redist RFG", __func__
);
941 * RFG prefix list check
943 if (rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
][afi
]) {
944 vnc_zlog_debug_verbose(
945 "%s: RFG prefix list is set, checking",
947 if (prefix_list_apply(
948 rfg
->plist_redist
[ZEBRA_ROUTE_BGP_DIRECT
]
952 vnc_zlog_debug_verbose(
953 "%s: prefix list returns DENY, blocking route",
957 vnc_zlog_debug_verbose(
958 "%s: prefix list returns PASS, allowing route",
962 /* apply routemap, if any, later */
963 rmap
= rfg
->routemap_redist
[ZEBRA_ROUTE_BGP_DIRECT
];
966 * export nve group's VN addr prefix must be a /32 which
967 * will yield the VN addr to use
969 vn_pfx
= &rfg
->vn_prefix
;
974 if (!is_host_prefix(&rfg
->un_prefix
)) {
975 /* NB prefixlen==0 means it has not been configured */
976 vnc_zlog_debug_verbose(
977 "%s: redist RFG UN pfx not host pfx (plen=%d), skipping",
978 __func__
, rfg
->un_prefix
.prefixlen
);
982 rfapiQprefix2Rprefix(&rfg
->un_prefix
, &pfx_un
);
984 vncHDBgpDirect
.un_addr
= pfx_un
.prefix
;
987 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
988 char buf
[PREFIX_STRLEN
];
990 prefix2str(vn_pfx
, buf
, sizeof(buf
));
991 vnc_zlog_debug_any("%s vn_pfx=%s", __func__
, buf
);
997 if (rfapiQprefix2Raddr(vn_pfx
, &vnaddr
)) {
998 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
1004 * route map handling
1005 * This code is here because it allocates an interned attr which
1006 * must be freed before we return. It's easier to put it after
1007 * all of the possible returns above.
1009 memset(&hattr
, 0, sizeof(struct attr
));
1010 bgp_attr_dup(&hattr
, attr
); /* hattr becomes a ghost attr */
1013 struct bgp_info info
;
1014 route_map_result_t ret
;
1016 memset(&info
, 0, sizeof(info
));
1019 ret
= route_map_apply(rmap
, prefix
, RMAP_BGP
, &info
);
1020 if (ret
== RMAP_DENYMATCH
) {
1021 bgp_attr_flush(&hattr
);
1022 vnc_zlog_debug_verbose(
1023 "%s: route map \"%s\" says DENY, returning",
1024 __func__
, rmap
->name
);
1029 iattr
= bgp_attr_intern(&hattr
);
1030 bgp_attr_flush(&hattr
);
1032 /* Now iattr is an allocated interned attr */
1037 * Sets RD in dummy HD
1042 memset(&prd
, 0, sizeof(prd
));
1044 prd
.family
= AF_UNSPEC
;
1047 if (rfg
->rd
.family
== AF_UNIX
) {
1048 rfapi_set_autord_from_vn(&prd
, &vnaddr
);
1051 if (rfg
->rt_export_list
)
1052 ecom
= ecommunity_dup(
1053 bgp
->rfapi_cfg
->rfg_redist
->rt_export_list
);
1055 ecom
= ecommunity_new();
1057 if (iattr
&& iattr
->ecommunity
)
1058 ecom
= ecommunity_merge(ecom
, iattr
->ecommunity
);
1061 local_pref
= calc_local_pref(iattr
, peer
);
1063 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
1067 rfapiRfapiIpAddr2Str(&vnaddr
, buf
, BUFSIZ
);
1068 buf
[BUFSIZ
- 1] = 0;
1069 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__
, buf
);
1072 vncHDBgpDirect
.peer
= peer
;
1073 add_vnc_route(&vncHDBgpDirect
, bgp
, SAFI_MPLS_VPN
, prefix
, &prd
,
1074 &vnaddr
, &local_pref
, &(bgp
->rfapi_cfg
->redist_lifetime
),
1075 NULL
, /* RFP options */
1076 NULL
, NULL
, ecom
, NULL
, /* med */
1077 NULL
, /* label: default */
1078 ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1080 vncHDBgpDirect
.peer
= NULL
;
1083 ecommunity_free(&ecom
);
1086 static void vnc_import_bgp_del_route_mode_plain(struct bgp
*bgp
,
1087 struct prefix
*prefix
,
1088 struct bgp_info
*info
)
1090 struct prefix_rd prd
;
1091 afi_t afi
= family2afi(prefix
->family
);
1092 struct prefix
*vn_pfx
= NULL
;
1093 struct rfapi_ip_addr vnaddr
;
1094 struct prefix vn_pfx_space
;
1100 * Compute VN address
1103 if (info
&& info
->attr
) {
1104 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &vn_pfx_space
);
1106 vnc_zlog_debug_verbose("%s: no attr, can't delete route",
1110 vn_pfx
= &vn_pfx_space
;
1112 vnaddr
.addr_family
= vn_pfx
->family
;
1113 switch (vn_pfx
->family
) {
1115 if (vn_pfx
->prefixlen
!= 32) {
1116 vnc_zlog_debug_verbose(
1117 "%s: redist VN plen (%d) != 32, skipping",
1118 __func__
, vn_pfx
->prefixlen
);
1121 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1125 if (vn_pfx
->prefixlen
!= 128) {
1126 vnc_zlog_debug_verbose(
1127 "%s: redist VN plen (%d) != 128, skipping",
1128 __func__
, vn_pfx
->prefixlen
);
1131 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1135 vnc_zlog_debug_verbose(
1136 "%s: no redist RFG VN host pfx configured, skipping",
1142 memset(&prd
, 0, sizeof(prd
));
1143 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1144 vnc_zlog_debug_verbose("%s: can't auto-assign RD, skipping",
1149 vncHDBgpDirect
.peer
= info
->peer
;
1150 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1151 vncHDBgpDirect
.peer
);
1152 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1153 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1156 vncHDBgpDirect
.peer
= NULL
;
1159 static void vnc_import_bgp_del_route_mode_nvegroup(struct bgp
*bgp
,
1160 struct prefix
*prefix
,
1161 struct bgp_info
*info
)
1163 struct prefix_rd prd
;
1164 afi_t afi
= family2afi(prefix
->family
);
1165 struct rfapi_nve_group_cfg
*rfg
= NULL
;
1166 struct prefix
*vn_pfx
= NULL
;
1167 struct rfapi_ip_addr vnaddr
;
1172 rfg
= bgp
->rfapi_cfg
->rfg_redist
;
1176 * Compute VN address
1180 * export nve group's VN addr prefix must be a /32 which
1181 * will yield the VN addr to use
1183 vn_pfx
= &rfg
->vn_prefix
;
1186 vnaddr
.addr_family
= vn_pfx
->family
;
1187 switch (vn_pfx
->family
) {
1189 if (vn_pfx
->prefixlen
!= 32) {
1190 vnc_zlog_debug_verbose(
1191 "%s: redist VN plen (%d) != 32, skipping",
1192 __func__
, vn_pfx
->prefixlen
);
1195 vnaddr
.addr
.v4
= vn_pfx
->u
.prefix4
;
1199 if (vn_pfx
->prefixlen
!= 128) {
1200 vnc_zlog_debug_verbose(
1201 "%s: redist VN plen (%d) != 128, skipping",
1202 __func__
, vn_pfx
->prefixlen
);
1205 vnaddr
.addr
.v6
= vn_pfx
->u
.prefix6
;
1209 vnc_zlog_debug_verbose(
1210 "%s: no redist RFG VN host pfx configured, skipping",
1215 memset(&prd
, 0, sizeof(prd
));
1217 prd
.family
= AF_UNSPEC
;
1220 if (rfg
->rd
.family
== AF_UNIX
) {
1221 /* means "auto" with VN addr */
1222 if (rfapi_set_autord_from_vn(&prd
, &vnaddr
)) {
1223 vnc_zlog_debug_verbose(
1224 "%s: can't auto-assign RD, skipping", __func__
);
1230 vncHDBgpDirect
.peer
= info
->peer
;
1231 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__
,
1232 vncHDBgpDirect
.peer
);
1233 del_vnc_route(&vncHDBgpDirect
, info
->peer
, bgp
, SAFI_MPLS_VPN
, prefix
,
1234 &prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
,
1237 vncHDBgpDirect
.peer
= NULL
;
1240 static void vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1241 struct bgp
*bgp
, afi_t afi
, struct bgp_info
*bi
, /* VPN bi */
1242 struct prefix_rd
*prd
, /* RD */
1243 struct prefix
*prefix
) /* unicast route prefix */
1247 if (bi
->type
!= ZEBRA_ROUTE_BGP
&& bi
->type
!= ZEBRA_ROUTE_BGP_DIRECT
) {
1251 if (bi
->sub_type
!= BGP_ROUTE_NORMAL
&& bi
->sub_type
!= BGP_ROUTE_STATIC
1252 && bi
->sub_type
!= BGP_ROUTE_RFP
) {
1256 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
1259 vncHDResolveNve
.peer
= bi
->peer
;
1260 if (!rfapiGetVncTunnelUnAddr(bi
->attr
, &un
)) {
1261 if (rfapiQprefix2Raddr(&un
, &vncHDResolveNve
.un_addr
))
1264 memset(&vncHDResolveNve
.un_addr
, 0,
1265 sizeof(vncHDResolveNve
.un_addr
));
1268 del_vnc_route(&vncHDResolveNve
, vncHDResolveNve
.peer
, bgp
,
1269 SAFI_MPLS_VPN
, prefix
, /* unicast route prefix */
1270 prd
, ZEBRA_ROUTE_BGP_DIRECT
, BGP_ROUTE_REDISTRIBUTE
, NULL
,
1274 static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1275 struct prefix_rd
*prd
,
1276 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1277 afi_t afi
, struct bgp
*bgp
, struct prefix
*prefix
, /* unicast prefix */
1278 struct prefix
*ubi_nexthop
) /* unicast bi's nexthop */
1280 struct bgp_node
*bn
;
1281 struct bgp_info
*bi
;
1287 char str_nh
[PREFIX_STRLEN
];
1289 prefix2str(ubi_nexthop
, str_nh
, sizeof(str_nh
));
1290 vnc_zlog_debug_verbose("%s: ubi_nexthop=%s", __func__
, str_nh
);
1295 bn
= bgp_node_lookup(table_rd
, ubi_nexthop
);
1297 vnc_zlog_debug_verbose(
1298 "%s: no match in RD's table for ubi_nexthop", __func__
);
1302 /* Iterate over bgp_info items at this node */
1303 for (bi
= bn
->info
; bi
; bi
= bi
->next
) {
1305 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1306 bgp
, afi
, bi
, /* VPN bi */
1308 prefix
); /* unicast route prefix */
1311 bgp_unlock_node(bn
);
1314 static void vnc_import_bgp_del_route_mode_resolve_nve(struct bgp
*bgp
,
1316 struct prefix
*prefix
,
1317 struct bgp_info
*info
)
1319 struct ecommunity
*ecom
= NULL
;
1320 struct prefix pfx_unicast_nexthop
= {0}; /* happy valgrind */
1322 // struct listnode *hnode;
1323 // struct rfapi_descriptor *rfd;
1324 struct prefix_bag
*pb
;
1326 struct skiplist
*sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1328 struct bgp_node
*bnp
; /* prd table node */
1331 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1336 if (info
->type
!= ZEBRA_ROUTE_BGP
) {
1337 vnc_zlog_debug_verbose(
1338 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
1339 __func__
, info
->type
, zebra_route_string(info
->type
),
1340 ZEBRA_ROUTE_BGP
, "ZEBRA_ROUTE_BGP");
1344 if (process_unicast_route(bgp
, afi
, prefix
, info
, &ecom
,
1345 &pfx_unicast_nexthop
)) {
1347 vnc_zlog_debug_verbose(
1348 "%s: process_unicast_route error, skipping", __func__
);
1352 rc
= skiplist_first_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1355 if (pb
->ubi
== info
) {
1356 skiplist_delete(sl
, &pfx_unicast_nexthop
, pb
);
1357 bgp_info_unlock(info
);
1360 rc
= skiplist_next_value(sl
, &pfx_unicast_nexthop
, (void *)&pb
,
1365 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
1366 * (exact match, /32). If an exact match is found, call add_vnc_route.
1369 for (bnp
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); bnp
;
1370 bnp
= bgp_route_next(bnp
)) {
1372 struct bgp_table
*table
;
1374 table
= (struct bgp_table
*)(bnp
->info
);
1379 vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1380 (struct prefix_rd
*)&bnp
->p
, table
, afi
, bgp
, prefix
,
1381 &pfx_unicast_nexthop
); /* TBD how is this set? */
1385 ecommunity_free(&ecom
);
1389 /***********************************************************************
1390 * Add/Delete CE->NVE routes
1391 ***********************************************************************/
1394 * Should be called whan a bi is added to VPN RIB. This function
1395 * will check if it is a host route and return immediately if not.
1397 void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1398 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1399 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1400 struct prefix
*prefix
, /* VPN prefix */
1401 struct bgp_info
*bi
) /* new VPN host route */
1403 afi_t afi
= family2afi(prefix
->family
);
1404 struct skiplist
*sl
= NULL
;
1406 struct prefix_bag
*pb
;
1408 struct rfapi_cfg
*hc
= NULL
;
1410 vnc_zlog_debug_verbose("%s: entry", __func__
);
1412 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1413 vnc_zlog_debug_verbose("%s: bad afi %d, skipping", __func__
,
1418 if (!(hc
= bgp
->rfapi_cfg
)) {
1419 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1424 /* check vnc redist flag for bgp direct routes */
1425 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1426 vnc_zlog_debug_verbose(
1427 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1432 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1433 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1439 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1442 vnc_zlog_debug_verbose(
1443 "%s: no resolve_nve_nexthop skiplist, skipping",
1448 if (!is_host_prefix(prefix
)) {
1449 vnc_zlog_debug_verbose("%s: not host prefix, skipping",
1454 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1456 struct ecommunity
*ecom
;
1457 struct prefix pfx_unicast_nexthop
;
1458 uint32_t *med
= NULL
;
1459 uint32_t local_pref
;
1461 memset(&pfx_unicast_nexthop
, 0,
1462 sizeof(struct prefix
)); /* keep valgrind happy */
1464 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE
)) {
1465 char hbuf
[PREFIX_STRLEN
];
1466 char ubuf
[PREFIX_STRLEN
];
1468 prefix2str(&pb
->hpfx
, hbuf
, sizeof(hbuf
));
1469 prefix2str(&pb
->upfx
, ubuf
, sizeof(ubuf
));
1472 "%s: examining RHN Entry (q=%p): upfx=%s, hpfx=%s, ubi=%p",
1473 __func__
, cursor
, ubuf
, hbuf
, pb
->ubi
);
1476 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubi
, &ecom
,
1477 &pfx_unicast_nexthop
)) {
1479 vnc_zlog_debug_verbose(
1480 "%s: process_unicast_route error, skipping",
1484 local_pref
= calc_local_pref(pb
->ubi
->attr
, pb
->ubi
->peer
);
1487 && (pb
->ubi
->attr
->flag
1488 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))) {
1490 med
= &pb
->ubi
->attr
->med
;
1496 if (vnc_prefix_cmp(&pfx_unicast_nexthop
, prefix
)) {
1497 char str_unh
[PREFIX_STRLEN
];
1498 char str_nve_pfx
[PREFIX_STRLEN
];
1500 prefix2str(&pfx_unicast_nexthop
, str_unh
,
1502 prefix2str(prefix
, str_nve_pfx
, sizeof(str_nve_pfx
));
1504 vnc_zlog_debug_verbose(
1505 "%s: FATAL: resolve_nve_nexthop list item bi nexthop %s != nve pfx %s",
1506 __func__
, str_unh
, str_nve_pfx
);
1510 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
1511 bgp
, afi
, bi
, /* VPN bi */
1512 prd
, &pb
->upfx
, /* unicast prefix */
1513 &local_pref
, med
, ecom
);
1516 ecommunity_free(&ecom
);
1521 char pbuf
[PREFIX_STRLEN
];
1523 prefix2str(prefix
, pbuf
, sizeof(pbuf
));
1525 vnc_zlog_debug_verbose(
1526 "%s: advancing past RHN Entry (q=%p): with prefix %s",
1527 __func__
, cursor
, pbuf
);
1528 print_rhn_list(__func__
, NULL
); /* debug */
1531 rc
= skiplist_next_value(sl
, prefix
, (void *)&pb
, &cursor
);
1533 vnc_zlog_debug_verbose("%s: done", __func__
);
1537 void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
1538 struct bgp
*bgp
, struct prefix_rd
*prd
, /* RD */
1539 struct bgp_table
*table_rd
, /* per-rd VPN route table */
1540 struct prefix
*prefix
, /* VPN prefix */
1541 struct bgp_info
*bi
) /* old VPN host route */
1543 afi_t afi
= family2afi(prefix
->family
);
1544 struct skiplist
*sl
= NULL
;
1545 struct prefix_bag
*pb
;
1547 struct rfapi_cfg
*hc
= NULL
;
1551 char str_pfx
[PREFIX_STRLEN
];
1553 prefix2str(prefix
, str_pfx
, sizeof(str_pfx
));
1555 vnc_zlog_debug_verbose("%s(bgp=%p, nve prefix=%s)", __func__
,
1559 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
)
1562 if (!(hc
= bgp
->rfapi_cfg
)) {
1563 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1568 /* check vnc redist flag for bgp direct routes */
1569 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
1570 vnc_zlog_debug_verbose(
1571 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1576 if (hc
->redist_mode
!= VNC_REDIST_MODE_RESOLVE_NVE
) {
1577 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1583 sl
= bgp
->rfapi
->resolve_nve_nexthop
;
1586 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1591 if (!is_host_prefix(prefix
)) {
1592 vnc_zlog_debug_verbose("%s: not host route, skip", __func__
);
1597 * Find all entries with key == CE in the RHN list
1599 rc
= skiplist_first_value(sl
, prefix
, (void *)&pb
, &cursor
);
1602 struct ecommunity
*ecom
;
1603 struct prefix pfx_unicast_nexthop
;
1605 memset(&pfx_unicast_nexthop
, 0,
1606 sizeof(struct prefix
)); /* keep valgrind happy */
1608 if (process_unicast_route(bgp
, afi
, &pb
->upfx
, pb
->ubi
, &ecom
,
1609 &pfx_unicast_nexthop
)) {
1611 vnc_zlog_debug_verbose(
1612 "%s: process_unicast_route error, skipping",
1620 if (vnc_prefix_cmp(&pfx_unicast_nexthop
, prefix
)) {
1621 char str_unh
[PREFIX_STRLEN
];
1622 char str_nve_pfx
[PREFIX_STRLEN
];
1624 prefix2str(&pfx_unicast_nexthop
, str_unh
,
1626 prefix2str(prefix
, str_nve_pfx
, sizeof(str_nve_pfx
));
1628 vnc_zlog_debug_verbose(
1629 "%s: FATAL: resolve_nve_nexthop list item bi nexthop %s != nve pfx %s",
1630 __func__
, str_unh
, str_nve_pfx
);
1634 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1635 bgp
, afi
, bi
, prd
, &pb
->upfx
);
1638 ecommunity_free(&ecom
);
1640 rc
= skiplist_next_value(sl
, prefix
, (void *)&pb
, &cursor
);
1645 /***********************************************************************
1647 ***********************************************************************/
1649 #define DEBUG_IS_USABLE_INTERIOR 1
1651 static int is_usable_interior_route(struct bgp_info
*bi_interior
)
1653 if (!VALID_INTERIOR_TYPE(bi_interior
->type
)) {
1654 #if DEBUG_IS_USABLE_INTERIOR
1655 vnc_zlog_debug_verbose(
1656 "%s: NO: type %d is not valid interior type", __func__
,
1661 if (!CHECK_FLAG(bi_interior
->flags
, BGP_INFO_VALID
)) {
1662 #if DEBUG_IS_USABLE_INTERIOR
1663 vnc_zlog_debug_verbose("%s: NO: BGP_INFO_VALID not set",
1672 * There should be only one of these per prefix at a time.
1673 * This should be called as a result of selection operation
1675 * NB should be called espacially for bgp instances that are named,
1676 * because the exterior routes will always come from one of those.
1677 * We filter here on the instance name to make sure we get only the
1680 static void vnc_import_bgp_exterior_add_route_it(
1681 struct bgp
*bgp
, /* exterior instance, we hope */
1682 struct prefix
*prefix
, /* unicast prefix */
1683 struct bgp_info
*info
, /* unicast info */
1684 struct rfapi_import_table
*it_only
) /* NULL, or limit to this IT */
1687 struct rfapi_cfg
*hc
;
1688 struct prefix pfx_orig_nexthop
;
1689 struct rfapi_import_table
*it
;
1690 struct bgp
*bgp_default
= bgp_get_default();
1691 afi_t afi
= family2afi(prefix
->family
);
1696 h
= bgp_default
->rfapi
;
1697 hc
= bgp_default
->rfapi_cfg
;
1699 vnc_zlog_debug_verbose("%s: entry with it=%p", __func__
, it_only
);
1702 vnc_zlog_debug_verbose(
1703 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1707 if (!hc
->redist_bgp_exterior_view
) {
1708 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1712 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1713 vnc_zlog_debug_verbose(
1714 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1715 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1719 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1720 vnc_zlog_debug_verbose(
1721 "%s: redist of exterior routes not enabled, skipping",
1727 vnc_zlog_debug_verbose("%s: no info, skipping", __func__
);
1732 * Extract nexthop from exterior route
1734 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1735 * but if v4 it is in attr->nexthop
1737 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1739 for (it
= h
->imports
; it
; it
= it
->next
) {
1740 struct route_table
*table
;
1741 struct route_node
*rn
;
1742 struct route_node
*par
;
1743 struct bgp_info
*bi_interior
;
1744 int have_usable_route
;
1746 vnc_zlog_debug_verbose("%s: doing it %p", __func__
, it
);
1748 if (it_only
&& (it_only
!= it
)) {
1749 vnc_zlog_debug_verbose("%s: doesn't match it_only %p",
1754 table
= it
->imported_vpn
[afi
];
1756 for (rn
= route_node_match(table
, &pfx_orig_nexthop
),
1757 have_usable_route
= 0;
1758 (!have_usable_route
) && rn
;) {
1760 vnc_zlog_debug_verbose("%s: it %p trying rn %p",
1763 for (bi_interior
= rn
->info
; bi_interior
;
1764 bi_interior
= bi_interior
->next
) {
1765 struct prefix_rd
*prd
;
1766 struct attr new_attr
;
1769 if (!is_usable_interior_route(bi_interior
))
1772 vnc_zlog_debug_verbose(
1773 "%s: usable: bi_interior %p", __func__
,
1777 * have a legitimate route to exterior's nexthop
1780 * Import unicast route to the import table
1782 have_usable_route
= 1;
1784 if (bi_interior
->extra
) {
1785 prd
= &bi_interior
->extra
->vnc
.import
1787 label
= decode_label(
1788 &bi_interior
->extra
->label
[0]);
1792 /* use local_pref from unicast route */
1793 memset(&new_attr
, 0, sizeof(struct attr
));
1794 bgp_attr_dup(&new_attr
, bi_interior
->attr
);
1795 if (info
->attr
->flag
1796 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
1797 new_attr
.local_pref
=
1798 info
->attr
->local_pref
;
1799 new_attr
.flag
|= ATTR_FLAG_BIT(
1800 BGP_ATTR_LOCAL_PREF
);
1803 rfapiBgpInfoFilteredImportVPN(
1804 it
, FIF_ACTION_UPDATE
,
1805 bi_interior
->peer
, NULL
, /* rfd */
1806 prefix
, NULL
, afi
, prd
, &new_attr
,
1807 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1808 BGP_ROUTE_REDISTRIBUTE
, &label
);
1811 if (have_usable_route
) {
1815 * TBD factor this out into its own function
1817 struct prefix
*pfx_mon
= prefix_new();
1818 if (!RFAPI_MONITOR_EXTERIOR(rn
)->source
) {
1819 RFAPI_MONITOR_EXTERIOR(rn
)->source
=
1824 route_lock_node(rn
); /* for skiplist */
1826 route_lock_node(rn
); /* for skiplist entry */
1827 prefix_copy(pfx_mon
, prefix
);
1828 if (!skiplist_insert(
1829 RFAPI_MONITOR_EXTERIOR(rn
)->source
,
1832 bgp_info_lock(info
);
1837 route_lock_node(par
);
1838 route_unlock_node(rn
);
1842 route_unlock_node(rn
);
1844 if (!have_usable_route
) {
1845 struct prefix
*pfx_mon
= prefix_new();
1846 prefix_copy(pfx_mon
, prefix
);
1847 if (!skiplist_insert(it
->monitor_exterior_orphans
, info
,
1850 bgp_info_lock(info
);
1856 void vnc_import_bgp_exterior_add_route(
1857 struct bgp
*bgp
, /* exterior instance, we hope */
1858 struct prefix
*prefix
, /* unicast prefix */
1859 struct bgp_info
*info
) /* unicast info */
1861 vnc_import_bgp_exterior_add_route_it(bgp
, prefix
, info
, NULL
);
1865 * There should be only one of these per prefix at a time.
1866 * This should probably be called as a result of selection operation.
1868 * NB should be called espacially for bgp instances that are named,
1869 * because the exterior routes will always come from one of those.
1870 * We filter here on the instance name to make sure we get only the
1873 void vnc_import_bgp_exterior_del_route(
1874 struct bgp
*bgp
, struct prefix
*prefix
, /* unicast prefix */
1875 struct bgp_info
*info
) /* unicast info */
1878 struct rfapi_cfg
*hc
;
1879 struct rfapi_import_table
*it
;
1880 struct prefix pfx_orig_nexthop
;
1881 afi_t afi
= family2afi(prefix
->family
);
1882 struct bgp
*bgp_default
= bgp_get_default();
1887 memset(&pfx_orig_nexthop
, 0,
1888 sizeof(struct prefix
)); /* keep valgrind happy */
1890 h
= bgp_default
->rfapi
;
1891 hc
= bgp_default
->rfapi_cfg
;
1894 vnc_zlog_debug_verbose(
1895 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1899 if (!hc
->redist_bgp_exterior_view
) {
1900 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1904 if (bgp
!= hc
->redist_bgp_exterior_view
) {
1905 vnc_zlog_debug_verbose(
1906 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1907 __func__
, bgp
, hc
->redist_bgp_exterior_view
);
1910 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
1911 vnc_zlog_debug_verbose(
1912 "%s: redist of exterior routes no enabled, skipping",
1918 vnc_zlog_debug_verbose("%s: no info, skipping", __func__
);
1923 * Extract nexthop from exterior route
1925 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1926 * but if v4 it is in attr->nexthop
1928 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_orig_nexthop
);
1930 for (it
= h
->imports
; it
; it
= it
->next
) {
1931 struct route_table
*table
;
1932 struct route_node
*rn
;
1933 struct route_node
*par
;
1934 struct bgp_info
*bi_interior
;
1935 int have_usable_route
;
1937 table
= it
->imported_vpn
[afi
];
1939 for (rn
= route_node_match(table
, &pfx_orig_nexthop
),
1940 have_usable_route
= 0;
1941 (!have_usable_route
) && rn
;) {
1943 for (bi_interior
= rn
->info
; bi_interior
;
1944 bi_interior
= bi_interior
->next
) {
1945 struct prefix_rd
*prd
;
1948 if (!is_usable_interior_route(bi_interior
))
1952 * have a legitimate route to exterior's nexthop
1955 * Import unicast route to the import table
1957 have_usable_route
= 1;
1959 if (bi_interior
->extra
) {
1960 prd
= &bi_interior
->extra
->vnc
.import
1962 label
= decode_label(
1963 &bi_interior
->extra
->label
[0]);
1967 rfapiBgpInfoFilteredImportVPN(
1968 it
, FIF_ACTION_KILL
, bi_interior
->peer
,
1970 prefix
, NULL
, afi
, prd
,
1972 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
1973 BGP_ROUTE_REDISTRIBUTE
, &label
);
1978 * TBD factor this out into its own function
1981 if (RFAPI_MONITOR_EXTERIOR(rn
)
1983 if (!skiplist_delete(
1984 RFAPI_MONITOR_EXTERIOR(
1989 bgp_info_unlock(info
);
1995 RFAPI_MONITOR_EXTERIOR(
1999 RFAPI_MONITOR_EXTERIOR(
2002 RFAPI_MONITOR_EXTERIOR(
2015 route_lock_node(par
);
2016 route_unlock_node(rn
);
2020 route_unlock_node(rn
);
2022 if (!have_usable_route
) {
2023 if (!skiplist_delete(it
->monitor_exterior_orphans
, info
,
2026 bgp_info_unlock(info
);
2033 * This function should be called after a new interior VPN route
2034 * has been added to an import_table.
2036 * NB should also be called whenever an existing vpn interior route
2037 * becomes valid (e.g., valid_interior_count is inremented)
2039 void vnc_import_bgp_exterior_add_route_interior(
2040 struct bgp
*bgp
, struct rfapi_import_table
*it
,
2041 struct route_node
*rn_interior
, /* VPN IT node */
2042 struct bgp_info
*bi_interior
) /* VPN IT route */
2044 afi_t afi
= family2afi(rn_interior
->p
.family
);
2045 struct route_node
*par
;
2046 struct bgp_info
*bi_exterior
;
2047 struct prefix
*pfx_exterior
; /* exterior pfx */
2050 struct list
*list_adopted
;
2052 vnc_zlog_debug_verbose("%s: entry", __func__
);
2054 if (!is_usable_interior_route(bi_interior
)) {
2055 vnc_zlog_debug_verbose(
2056 "%s: not usable interior route, skipping", __func__
);
2060 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2061 vnc_zlog_debug_verbose(
2062 "%s: redist of exterior routes no enabled, skipping",
2067 if (it
== bgp
->rfapi
->it_ce
) {
2068 vnc_zlog_debug_verbose("%s: import table is it_ce, skipping",
2075 char str_pfx
[PREFIX_STRLEN
];
2077 prefix2str(&rn_interior
->p
, str_pfx
, sizeof(str_pfx
));
2078 vnc_zlog_debug_verbose("%s: interior prefix=%s, bi type=%d",
2079 __func__
, str_pfx
, bi_interior
->type
);
2082 if (RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
2084 int count
= 0; /* debugging */
2086 vnc_zlog_debug_verbose(
2087 "%s: has exterior monitor; ext src: %p", __func__
,
2088 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2091 * There is a monitor here already. Therefore, we do not need
2092 * to do any pulldown. Just construct exterior routes based
2093 * on the new interior route.
2096 for (rc
= skiplist_next(
2097 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2098 (void **)&bi_exterior
, (void **)&pfx_exterior
,
2100 !rc
; rc
= skiplist_next(
2101 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2102 (void **)&bi_exterior
, (void **)&pfx_exterior
,
2105 struct prefix_rd
*prd
;
2106 struct attr new_attr
;
2110 ++count
; /* debugging */
2112 assert(bi_exterior
);
2113 assert(pfx_exterior
);
2115 if (bi_interior
->extra
) {
2116 prd
= &bi_interior
->extra
->vnc
.import
.rd
;
2117 label
= decode_label(
2118 &bi_interior
->extra
->label
[0]);
2122 /* use local_pref from unicast route */
2123 memset(&new_attr
, 0, sizeof(struct attr
));
2124 bgp_attr_dup(&new_attr
, bi_interior
->attr
);
2126 && (bi_exterior
->attr
->flag
2127 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2128 new_attr
.local_pref
=
2129 bi_exterior
->attr
->local_pref
;
2131 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2134 rfapiBgpInfoFilteredImportVPN(
2135 it
, FIF_ACTION_UPDATE
, bi_interior
->peer
,
2137 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2138 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2139 BGP_ROUTE_REDISTRIBUTE
, &label
);
2141 vnc_zlog_debug_verbose(
2142 "%s: finished constructing exteriors based on existing monitors",
2147 vnc_zlog_debug_verbose("%s: no exterior monitor", __func__
);
2150 * No monitor at this node. Is this the first valid interior
2151 * route at this node?
2153 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
> 1) {
2154 vnc_zlog_debug_verbose(
2155 "%s: new interior route not first valid one, skipping pulldown",
2161 * Look up the tree for possible pulldown candidates.
2162 * Find nearest parent with an exterior route monitor
2164 for (par
= rn_interior
->parent
; par
; par
= par
->parent
) {
2165 if (RFAPI_HAS_MONITOR_EXTERIOR(par
))
2171 vnc_zlog_debug_verbose(
2172 "%s: checking parent %p for possible pulldowns",
2175 /* check monitors at par for possible pulldown */
2177 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2178 (void **)&bi_exterior
,
2179 (void **)&pfx_exterior
, &cursor
);
2181 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2182 (void **)&bi_exterior
,
2183 (void **)&pfx_exterior
, &cursor
)) {
2185 struct prefix pfx_nexthop
;
2187 memset(&pfx_nexthop
, 0,
2188 sizeof(struct prefix
)); /* keep valgrind happy */
2190 /* check original nexthop for prefix match */
2191 rfapiUnicastNexthop2Prefix(afi
, bi_exterior
->attr
,
2194 if (prefix_match(&rn_interior
->p
, &pfx_nexthop
)) {
2196 struct bgp_info
*bi
;
2197 struct prefix_rd
*prd
;
2198 struct attr new_attr
;
2204 * add monitor to longer prefix
2206 struct prefix
*pfx_mon
= prefix_new();
2207 prefix_copy(pfx_mon
, pfx_exterior
);
2208 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)
2210 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2211 ->source
= skiplist_new(
2213 (void (*)(void *))prefix_free
);
2214 route_lock_node(rn_interior
);
2217 RFAPI_MONITOR_EXTERIOR(rn_interior
)
2219 bi_exterior
, pfx_mon
);
2220 route_lock_node(rn_interior
);
2223 * Delete constructed exterior routes based on
2226 for (bi
= par
->info
; bi
; bi
= bi
->next
) {
2229 prd
= &bi
->extra
->vnc
.import
.rd
;
2230 label
= decode_label(
2231 &bi
->extra
->label
[0]);
2235 rfapiBgpInfoFilteredImportVPN(
2236 it
, FIF_ACTION_KILL
, bi
->peer
,
2238 pfx_exterior
, NULL
, afi
, prd
,
2240 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2241 BGP_ROUTE_REDISTRIBUTE
, &label
);
2246 * Add constructed exterior routes based on
2247 * the new interior route at longer prefix.
2249 if (bi_interior
->extra
) {
2250 prd
= &bi_interior
->extra
->vnc
.import
2252 label
= decode_label(
2253 &bi_interior
->extra
->label
[0]);
2257 /* use local_pref from unicast route */
2258 memset(&new_attr
, 0, sizeof(struct attr
));
2259 bgp_attr_dup(&new_attr
, bi_interior
->attr
);
2261 && (bi_exterior
->attr
->flag
2262 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2263 new_attr
.local_pref
=
2264 bi_exterior
->attr
->local_pref
;
2265 new_attr
.flag
|= ATTR_FLAG_BIT(
2266 BGP_ATTR_LOCAL_PREF
);
2269 rfapiBgpInfoFilteredImportVPN(
2270 it
, FIF_ACTION_UPDATE
,
2271 bi_interior
->peer
, NULL
, /* rfd */
2272 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2273 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2274 BGP_ROUTE_REDISTRIBUTE
, &label
);
2279 * The only monitors at rn_interior are the ones we added just
2280 * above, so we can use the rn_interior list to identify which
2281 * monitors to delete from the parent.
2284 for (rc
= skiplist_next(
2285 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2286 (void **)&bi_exterior
, NULL
, &cursor
);
2287 !rc
; rc
= skiplist_next(
2288 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2289 (void **)&bi_exterior
, NULL
, &cursor
)) {
2292 skiplist_delete(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2294 route_unlock_node(par
); /* sl entry */
2296 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par
)->source
)) {
2297 skiplist_free(RFAPI_MONITOR_EXTERIOR(par
)->source
);
2298 RFAPI_MONITOR_EXTERIOR(par
)->source
= NULL
;
2299 route_unlock_node(par
); /* sl itself */
2303 vnc_zlog_debug_verbose("%s: checking orphans", __func__
);
2306 * See if any orphans can be pulled down to the current node
2309 list_adopted
= NULL
;
2310 for (rc
= skiplist_next(it
->monitor_exterior_orphans
,
2311 (void **)&bi_exterior
, (void **)&pfx_exterior
,
2313 !rc
; rc
= skiplist_next(it
->monitor_exterior_orphans
,
2314 (void **)&bi_exterior
,
2315 (void **)&pfx_exterior
, &cursor
)) {
2317 struct prefix pfx_nexthop
;
2318 char buf
[PREFIX_STRLEN
];
2319 afi_t afi_exterior
= family2afi(pfx_exterior
->family
);
2321 prefix2str(pfx_exterior
, buf
, sizeof(buf
));
2322 vnc_zlog_debug_verbose(
2323 "%s: checking exterior orphan at prefix %s", __func__
,
2326 if (afi_exterior
!= afi
) {
2327 vnc_zlog_debug_verbose(
2328 "%s: exterior orphan afi %d != interior afi %d, skip",
2329 __func__
, afi_exterior
, afi
);
2333 /* check original nexthop for prefix match */
2334 rfapiUnicastNexthop2Prefix(afi
, bi_exterior
->attr
,
2337 if (prefix_match(&rn_interior
->p
, &pfx_nexthop
)) {
2339 struct prefix_rd
*prd
;
2340 struct attr new_attr
;
2346 * add monitor to longer prefix
2349 struct prefix
*pfx_mon
= prefix_new();
2350 prefix_copy(pfx_mon
, pfx_exterior
);
2351 if (!RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
) {
2352 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
=
2355 (void (*)(void *))prefix_free
);
2356 route_lock_node(rn_interior
); /* sl */
2359 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2360 bi_exterior
, pfx_mon
);
2361 route_lock_node(rn_interior
); /* sl entry */
2362 if (!list_adopted
) {
2363 list_adopted
= list_new();
2365 listnode_add(list_adopted
, bi_exterior
);
2368 * Add constructed exterior routes based on the
2369 * new interior route at the longer prefix.
2371 if (bi_interior
->extra
) {
2372 prd
= &bi_interior
->extra
->vnc
.import
.rd
;
2373 label
= decode_label(
2374 &bi_interior
->extra
->label
[0]);
2378 /* use local_pref from unicast route */
2379 memset(&new_attr
, 0, sizeof(struct attr
));
2380 bgp_attr_dup(&new_attr
, bi_interior
->attr
);
2382 && (bi_exterior
->attr
->flag
2383 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2384 new_attr
.local_pref
=
2385 bi_exterior
->attr
->local_pref
;
2387 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2390 rfapiBgpInfoFilteredImportVPN(
2391 it
, FIF_ACTION_UPDATE
, bi_interior
->peer
,
2393 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2394 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2395 BGP_ROUTE_REDISTRIBUTE
, &label
);
2399 struct listnode
*node
;
2400 struct route_node
*bi_exterior
;
2402 for (ALL_LIST_ELEMENTS_RO(list_adopted
, node
, bi_exterior
)) {
2403 skiplist_delete(it
->monitor_exterior_orphans
,
2406 list_delete_and_null(&list_adopted
);
2411 * This function should be called after an interior VPN route
2412 * has been deleted from an import_table.
2413 * bi_interior must still be valid, but it must already be detached
2414 * from its route node and the route node's valid_interior_count
2415 * must already be decremented.
2417 * NB should also be called whenever an existing vpn interior route
2418 * becomes invalid (e.g., valid_interior_count is decremented)
2420 void vnc_import_bgp_exterior_del_route_interior(
2421 struct bgp
*bgp
, struct rfapi_import_table
*it
,
2422 struct route_node
*rn_interior
, /* VPN IT node */
2423 struct bgp_info
*bi_interior
) /* VPN IT route */
2425 afi_t afi
= family2afi(rn_interior
->p
.family
);
2426 struct route_node
*par
;
2427 struct bgp_info
*bi_exterior
;
2428 struct prefix
*pfx_exterior
; /* exterior pfx */
2432 if (!VALID_INTERIOR_TYPE(bi_interior
->type
)) {
2433 vnc_zlog_debug_verbose(
2434 "%s: type %d not valid interior type, skipping",
2435 __func__
, bi_interior
->type
);
2439 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2440 vnc_zlog_debug_verbose(
2441 "%s: redist of exterior routes no enabled, skipping",
2446 if (it
== bgp
->rfapi
->it_ce
) {
2447 vnc_zlog_debug_verbose("%s: it is it_ce, skipping", __func__
);
2451 /* If no exterior routes depend on this prefix, nothing to do */
2452 if (!RFAPI_HAS_MONITOR_EXTERIOR(rn_interior
)) {
2453 vnc_zlog_debug_verbose("%s: no exterior monitor, skipping",
2460 char str_pfx
[PREFIX_STRLEN
];
2462 prefix2str(&rn_interior
->p
, str_pfx
, sizeof(str_pfx
));
2464 vnc_zlog_debug_verbose("%s: interior prefix=%s, bi type=%d",
2465 __func__
, str_pfx
, bi_interior
->type
);
2469 * Remove constructed routes based on the deleted interior route
2472 for (rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2473 (void **)&bi_exterior
, (void **)&pfx_exterior
,
2476 rc
= skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2477 (void **)&bi_exterior
, (void **)&pfx_exterior
,
2480 struct prefix_rd
*prd
;
2483 if (bi_interior
->extra
) {
2484 prd
= &bi_interior
->extra
->vnc
.import
.rd
;
2485 label
= decode_label(&bi_interior
->extra
->label
[0]);
2489 rfapiBgpInfoFilteredImportVPN(
2490 it
, FIF_ACTION_KILL
, bi_interior
->peer
, NULL
, /* rfd */
2491 pfx_exterior
, NULL
, afi
, prd
, bi_interior
->attr
,
2492 ZEBRA_ROUTE_BGP_DIRECT_EXT
, BGP_ROUTE_REDISTRIBUTE
,
2497 * If there are no remaining valid interior routes at this prefix,
2498 * we need to look up the tree for a possible node to move monitors to
2500 if (RFAPI_MONITOR_EXTERIOR(rn_interior
)->valid_interior_count
) {
2501 vnc_zlog_debug_verbose(
2502 "%s: interior routes still present, skipping",
2508 * Find nearest parent with at least one valid interior route
2509 * If none is found, par will end up NULL, and we will move
2510 * the monitors to the orphan list for this import table
2512 for (par
= rn_interior
->parent
; par
; par
= par
->parent
) {
2513 if (RFAPI_MONITOR_EXTERIOR(par
)->valid_interior_count
)
2517 vnc_zlog_debug_verbose("%s: par=%p, ext src: %p", __func__
, par
,
2518 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2520 /* move all monitors */
2522 * We will use and delete every element of the source skiplist
2524 while (!skiplist_first(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
,
2525 (void **)&bi_exterior
, (void **)&pfx_exterior
)) {
2527 struct prefix
*pfx_mon
= prefix_new();
2529 prefix_copy(pfx_mon
, pfx_exterior
);
2533 struct bgp_info
*bi
;
2536 * Add monitor to parent node
2538 if (!RFAPI_MONITOR_EXTERIOR(par
)->source
) {
2539 RFAPI_MONITOR_EXTERIOR(par
)->source
=
2542 (void (*)(void *))prefix_free
);
2543 route_lock_node(par
); /* sl */
2545 skiplist_insert(RFAPI_MONITOR_EXTERIOR(par
)->source
,
2546 bi_exterior
, pfx_mon
);
2547 route_lock_node(par
); /* sl entry */
2549 /* Add constructed exterior routes based on parent */
2550 for (bi
= par
->info
; bi
; bi
= bi
->next
) {
2552 struct prefix_rd
*prd
;
2553 struct attr new_attr
;
2556 if (bi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
)
2560 prd
= &bi
->extra
->vnc
.import
.rd
;
2561 label
= decode_label(
2562 &bi
->extra
->label
[0]);
2566 /* use local_pref from unicast route */
2567 memset(&new_attr
, 0, sizeof(struct attr
));
2568 bgp_attr_dup(&new_attr
, bi
->attr
);
2570 && (bi_exterior
->attr
->flag
2571 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))) {
2572 new_attr
.local_pref
=
2573 bi_exterior
->attr
->local_pref
;
2574 new_attr
.flag
|= ATTR_FLAG_BIT(
2575 BGP_ATTR_LOCAL_PREF
);
2578 rfapiBgpInfoFilteredImportVPN(
2579 it
, FIF_ACTION_UPDATE
, bi
->peer
,
2581 pfx_exterior
, NULL
, afi
, prd
, &new_attr
,
2582 ZEBRA_ROUTE_BGP_DIRECT_EXT
,
2583 BGP_ROUTE_REDISTRIBUTE
, &label
);
2589 * No interior route for exterior's nexthop. Save
2591 * in orphan list to await future route.
2593 skiplist_insert(it
->monitor_exterior_orphans
,
2594 bi_exterior
, pfx_mon
);
2597 skiplist_delete_first(
2598 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2599 route_unlock_node(rn_interior
); /* sl entry */
2601 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
)) {
2602 skiplist_free(RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
);
2603 RFAPI_MONITOR_EXTERIOR(rn_interior
)->source
= NULL
;
2604 route_unlock_node(rn_interior
); /* sl itself */
2608 /***********************************************************************
2609 * Generic add/delete unicast routes
2610 ***********************************************************************/
2612 void vnc_import_bgp_add_route(struct bgp
*bgp
, struct prefix
*prefix
,
2613 struct bgp_info
*info
)
2615 afi_t afi
= family2afi(prefix
->family
);
2617 if (VNC_DEBUG(VERBOSE
)) {
2618 struct prefix pfx_nexthop
;
2619 char buf
[PREFIX_STRLEN
];
2620 char buf_nh
[PREFIX_STRLEN
];
2622 prefix2str(prefix
, buf
, sizeof(buf
));
2623 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2624 prefix2str(&pfx_nexthop
, buf_nh
, sizeof(buf_nh
));
2626 vnc_zlog_debug_verbose("%s: pfx %s, nh %s", __func__
, buf
,
2630 print_rhn_list(__func__
, "ENTER ");
2635 flog_err(LIB_ERR_DEVELOPMENT
, "%s: can't get afi of prefix",
2640 if (!bgp
->rfapi_cfg
) {
2641 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2646 /* check vnc redist flag for bgp direct routes */
2647 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2648 vnc_zlog_debug_verbose(
2649 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
2650 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2654 switch (bgp
->rfapi_cfg
->redist_mode
) {
2655 case VNC_REDIST_MODE_PLAIN
:
2656 vnc_import_bgp_add_route_mode_plain(bgp
, prefix
, info
);
2659 case VNC_REDIST_MODE_RFG
:
2660 if (bgp
->rfapi_cfg
->rfg_redist
)
2661 vnc_import_bgp_add_route_mode_nvegroup(
2662 bgp
, prefix
, info
, bgp
->rfapi_cfg
->rfg_redist
);
2664 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2668 case VNC_REDIST_MODE_RESOLVE_NVE
:
2669 vnc_import_bgp_add_route_mode_resolve_nve(bgp
, prefix
, info
);
2673 print_rhn_list(__func__
, "LEAVE ");
2679 * "Withdrawing a Route" import process
2681 void vnc_import_bgp_del_route(struct bgp
*bgp
, struct prefix
*prefix
,
2682 struct bgp_info
*info
) /* unicast info */
2684 afi_t afi
= family2afi(prefix
->family
);
2689 struct prefix pfx_nexthop
;
2690 char buf
[PREFIX_STRLEN
];
2691 char buf_nh
[PREFIX_STRLEN
];
2693 prefix2str(prefix
, buf
, sizeof(buf
));
2694 rfapiUnicastNexthop2Prefix(afi
, info
->attr
, &pfx_nexthop
);
2695 prefix2str(&pfx_nexthop
, buf_nh
, sizeof(buf_nh
));
2697 vnc_zlog_debug_verbose("%s: pfx %s, nh %s", __func__
, buf
,
2701 print_rhn_list(__func__
, "ENTER ");
2705 if (!bgp
->rfapi_cfg
) {
2706 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2711 /* check bgp redist flag for vnc direct ("vpn") routes */
2712 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2713 vnc_zlog_debug_verbose(
2714 "%s: bgp redistribution of afi=%d VNC direct routes is off",
2719 switch (bgp
->rfapi_cfg
->redist_mode
) {
2720 case VNC_REDIST_MODE_PLAIN
:
2721 vnc_import_bgp_del_route_mode_plain(bgp
, prefix
, info
);
2724 case VNC_REDIST_MODE_RFG
:
2725 if (bgp
->rfapi_cfg
->rfg_redist
)
2726 vnc_import_bgp_del_route_mode_nvegroup(bgp
, prefix
,
2729 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2733 case VNC_REDIST_MODE_RESOLVE_NVE
:
2734 vnc_import_bgp_del_route_mode_resolve_nve(bgp
, afi
, prefix
,
2739 print_rhn_list(__func__
, "LEAVE ");
2745 /***********************************************************************
2747 ***********************************************************************/
2749 void vnc_import_bgp_redist_enable(struct bgp
*bgp
, afi_t afi
)
2751 /* iterate over bgp unicast v4 and v6 routes, call
2752 * vnc_import_bgp_add_route */
2754 struct bgp_node
*rn
;
2756 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
2758 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2759 vnc_zlog_debug_verbose(
2760 "%s: already enabled for afi %d, skipping", __func__
,
2764 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 1;
2766 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); rn
;
2767 rn
= bgp_route_next(rn
)) {
2769 struct bgp_info
*bi
;
2771 for (bi
= rn
->info
; bi
; bi
= bi
->next
) {
2773 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
2776 vnc_import_bgp_add_route(bgp
, &rn
->p
, bi
);
2779 vnc_zlog_debug_verbose(
2780 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2781 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2784 void vnc_import_bgp_exterior_redist_enable(struct bgp
*bgp
, afi_t afi
)
2786 struct bgp
*bgp_exterior
;
2787 struct bgp_node
*rn
;
2789 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2791 if (bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2792 vnc_zlog_debug_verbose(
2793 "%s: already enabled for afi %d, skipping", __func__
,
2797 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 1;
2799 if (!bgp_exterior
) {
2800 vnc_zlog_debug_verbose(
2801 "%s: no exterior view set yet, no routes to import yet",
2806 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); rn
;
2807 rn
= bgp_route_next(rn
)) {
2809 struct bgp_info
*bi
;
2811 for (bi
= rn
->info
; bi
; bi
= bi
->next
) {
2813 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
2816 vnc_import_bgp_exterior_add_route(bgp_exterior
, &rn
->p
,
2820 vnc_zlog_debug_verbose(
2821 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2822 __func__
, afi
, ZEBRA_ROUTE_BGP_DIRECT
);
2826 * This function is for populating a newly-created Import Table
2828 void vnc_import_bgp_exterior_redist_enable_it(
2829 struct bgp
*bgp
, afi_t afi
, struct rfapi_import_table
*it_only
)
2831 struct bgp
*bgp_exterior
;
2832 struct bgp_node
*rn
;
2834 vnc_zlog_debug_verbose("%s: entry", __func__
);
2836 bgp_exterior
= bgp
->rfapi_cfg
->redist_bgp_exterior_view
;
2838 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2839 vnc_zlog_debug_verbose("%s: not enabled for afi %d, skipping",
2844 if (!bgp_exterior
) {
2845 vnc_zlog_debug_verbose(
2846 "%s: no exterior view set yet, no routes to import yet",
2851 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]); rn
;
2852 rn
= bgp_route_next(rn
)) {
2854 struct bgp_info
*bi
;
2856 for (bi
= rn
->info
; bi
; bi
= bi
->next
) {
2858 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
2861 vnc_import_bgp_exterior_add_route_it(
2862 bgp_exterior
, &rn
->p
, bi
, it_only
);
2868 void vnc_import_bgp_redist_disable(struct bgp
*bgp
, afi_t afi
)
2871 * iterate over vpn routes, find routes of type ZEBRA_ROUTE_BGP_DIRECT,
2872 * delete (call timer expire immediately)
2874 struct bgp_node
*rn1
;
2875 struct bgp_node
*rn2
;
2877 vnc_zlog_debug_verbose("%s: entry", __func__
);
2879 if (!bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
]) {
2880 vnc_zlog_debug_verbose(
2881 "%s: already disabled for afi %d, skipping", __func__
,
2887 * Two-level table for SAFI_MPLS_VPN
2888 * Be careful when changing the things we iterate over
2890 for (rn1
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); rn1
;
2891 rn1
= bgp_route_next(rn1
)) {
2894 for (rn2
= bgp_table_top(rn1
->info
); rn2
;
2895 rn2
= bgp_route_next(rn2
)) {
2897 struct bgp_info
*bi
;
2898 struct bgp_info
*nextbi
;
2900 for (bi
= rn2
->info
; bi
; bi
= nextbi
) {
2905 == ZEBRA_ROUTE_BGP_DIRECT
) {
2907 struct rfapi_descriptor
*rfd
;
2908 vncHDBgpDirect
.peer
= bi
->peer
;
2912 rfd
= bi
->extra
->vnc
.export
2915 vnc_zlog_debug_verbose(
2916 "%s: deleting bi=%p, bi->peer=%p, bi->type=%d, bi->sub_type=%d, bi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]",
2917 __func__
, bi
, bi
->peer
,
2918 bi
->type
, bi
->sub_type
,
2930 SAFI_MPLS_VPN
, &rn2
->p
,
2931 (struct prefix_rd
*)&rn1
2933 bi
->type
, bi
->sub_type
,
2934 NULL
, 1); /* kill */
2936 vncHDBgpDirect
.peer
= NULL
;
2942 /* Clear RHN list */
2943 if (bgp
->rfapi
->resolve_nve_nexthop
) {
2944 struct prefix_bag
*pb
;
2945 struct bgp_info
*info
;
2946 while (!skiplist_first(bgp
->rfapi
->resolve_nve_nexthop
, NULL
,
2949 skiplist_delete_first(bgp
->rfapi
->resolve_nve_nexthop
);
2950 bgp_info_unlock(info
);
2954 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT
] = 0;
2955 vnc_zlog_debug_verbose("%s: return", __func__
);
2959 void vnc_import_bgp_exterior_redist_disable(struct bgp
*bgp
, afi_t afi
)
2961 struct rfapi_cfg
*hc
= bgp
->rfapi_cfg
;
2962 struct bgp
*bgp_exterior
= hc
->redist_bgp_exterior_view
;
2964 vnc_zlog_debug_verbose("%s: entry", __func__
);
2966 if (!hc
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
]) {
2967 vnc_zlog_debug_verbose(
2968 "%s: already disabled for afi %d, skipping", __func__
,
2973 if (!bgp_exterior
) {
2974 vnc_zlog_debug_verbose(
2975 "%s: bgp exterior view not defined, skipping",
2982 struct bgp_node
*rn
;
2983 for (rn
= bgp_table_top(bgp_exterior
->rib
[afi
][SAFI_UNICAST
]);
2984 rn
; rn
= bgp_route_next(rn
)) {
2986 struct bgp_info
*bi
;
2988 for (bi
= rn
->info
; bi
; bi
= bi
->next
) {
2990 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
2993 vnc_import_bgp_exterior_del_route(bgp_exterior
,
2998 print_rhn_list(__func__
, NULL
);
3002 bgp
->rfapi_cfg
->redist
[afi
][ZEBRA_ROUTE_BGP_DIRECT_EXT
] = 0;
3003 vnc_zlog_debug_verbose("%s: return", __func__
);