Line data Source code
1 : /*
2 : *
3 : * Copyright 2009-2016, LabN Consulting, L.L.C.
4 : *
5 : *
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.
10 : *
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.
15 : *
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
19 : */
20 :
21 : /*
22 : * File: vnc_import_bgp.c
23 : * Purpose: Import routes from BGP unicast directly (not via zebra)
24 : */
25 :
26 : #include "lib/zebra.h"
27 : #include "lib/prefix.h"
28 : #include "lib/agg_table.h"
29 : #include "lib/vty.h"
30 : #include "lib/log.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"
36 :
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 */
42 :
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"
53 :
54 : #define ENABLE_VNC_RHNCK
55 :
56 : #define DEBUG_RHN_LIST 0
57 :
58 : static struct rfapi_descriptor vncHDBgpDirect; /* dummy nve descriptor */
59 : static struct rfapi_descriptor vncHDResolveNve; /* dummy nve descriptor */
60 :
61 : /*
62 : * For routes from another AS:
63 : *
64 : * If MED is set,
65 : * LOCAL_PREF = 255 - MIN(255, MED)
66 : * else
67 : * LOCAL_PREF = default_local_pref
68 : *
69 : * For routes from the same AS:
70 : *
71 : * LOCAL_PREF unchanged
72 : */
73 0 : uint32_t calc_local_pref(struct attr *attr, struct peer *peer)
74 : {
75 0 : uint32_t local_pref = 0;
76 :
77 0 : if (!attr) {
78 0 : if (peer) {
79 0 : return peer->bgp->default_local_pref;
80 : }
81 0 : return bgp_get_default()->default_local_pref;
82 : }
83 :
84 0 : if (peer && (peer->as != peer->bgp->as)) {
85 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
86 0 : if (attr->med > 255) {
87 : local_pref = 0;
88 : } else {
89 0 : local_pref = 255 - attr->med;
90 : }
91 : } else {
92 0 : local_pref = peer->bgp->default_local_pref;
93 : }
94 : } else {
95 0 : if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
96 0 : local_pref = attr->local_pref;
97 : } else {
98 0 : if (peer && peer->bgp) {
99 0 : local_pref = peer->bgp->default_local_pref;
100 : }
101 : }
102 : }
103 :
104 : return local_pref;
105 : }
106 :
107 0 : static int is_host_prefix(const struct prefix *p)
108 : {
109 0 : switch (p->family) {
110 0 : case AF_INET:
111 0 : return (p->prefixlen == IPV4_MAX_BITLEN);
112 0 : case AF_INET6:
113 0 : return (p->prefixlen == IPV6_MAX_BITLEN);
114 : }
115 : return 0;
116 : }
117 :
118 : /***********************************************************************
119 : * RHN list
120 : ***********************************************************************/
121 :
122 : struct prefix_bag {
123 : struct prefix hpfx; /* ce address = unicast nexthop */
124 : struct prefix upfx; /* unicast prefix */
125 : struct bgp_path_info *ubpi; /* unicast route */
126 : };
127 :
128 : static const uint8_t maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
129 : 0xf8, 0xfc, 0xfe, 0xff};
130 :
131 0 : int vnc_prefix_cmp(const void *pfx1, const void *pfx2)
132 : {
133 0 : int offset;
134 0 : int shift;
135 0 : uint8_t mask;
136 :
137 0 : const struct prefix *p1 = pfx1;
138 0 : const struct prefix *p2 = pfx2;
139 :
140 0 : if (p1->family < p2->family)
141 : return -1;
142 0 : if (p1->family > p2->family)
143 : return 1;
144 :
145 0 : if (p1->prefixlen < p2->prefixlen)
146 : return -1;
147 0 : if (p1->prefixlen > p2->prefixlen)
148 : return 1;
149 :
150 0 : offset = p1->prefixlen / 8;
151 0 : shift = p1->prefixlen % 8;
152 0 : if (shift == 0 && offset) { /* catch aligned case */
153 0 : offset--;
154 0 : shift = 8;
155 : }
156 :
157 : /* Set both prefix's head pointer. */
158 0 : const uint8_t *pp1 = (const uint8_t *)&p1->u.prefix;
159 0 : const uint8_t *pp2 = (const uint8_t *)&p2->u.prefix;
160 :
161 0 : while (offset--) {
162 0 : if (*pp1 < *pp2)
163 : return -1;
164 0 : if (*pp1 > *pp2)
165 : return 1;
166 0 : ++pp1;
167 0 : ++pp2;
168 : }
169 :
170 0 : mask = maskbit[shift];
171 0 : if ((*pp1 & mask) < (*pp2 & mask))
172 : return -1;
173 0 : if ((*pp1 & mask) > (*pp2 & mask))
174 0 : return 1;
175 :
176 : return 0;
177 : }
178 :
179 0 : static void prefix_bag_free(void *pb)
180 : {
181 0 : XFREE(MTYPE_RFAPI_PREFIX_BAG, pb);
182 0 : }
183 :
184 : #if DEBUG_RHN_LIST
185 : static void print_rhn_list(const char *tag1, const char *tag2)
186 : {
187 : struct bgp *bgp;
188 : struct skiplist *sl;
189 : struct skiplistnode *p;
190 : struct prefix_bag *pb;
191 : int count = 0;
192 :
193 : bgp = bgp_get_default();
194 : if (!bgp)
195 : return;
196 :
197 : sl = bgp->frapi->resolve_nve_nexthop;
198 : if (!sl) {
199 : vnc_zlog_debug_verbose("%s: %s: RHN List is empty",
200 : (tag1 ? tag1 : ""), (tag2 ? tag2 : ""));
201 : return;
202 : }
203 :
204 : vnc_zlog_debug_verbose("%s: %s: RHN list:", (tag1 ? tag1 : ""),
205 : (tag2 ? tag2 : ""));
206 :
207 : /* XXX uses secret knowledge of skiplist structure */
208 : for (p = sl->header->forward[0]; p; p = p->forward[0]) {
209 : pb = p->value;
210 :
211 : vnc_zlog_debug_verbose(
212 : "RHN Entry %d (q=%p): kpfx=%pFX, upfx=%pFX, hpfx=%pFX, ubpi=%p",
213 : ++count, p, p->key, &pb->upfx, &pb->hpfx, pb->ubpi);
214 : }
215 : }
216 : #endif
217 :
218 : #ifdef ENABLE_VNC_RHNCK
219 83 : static void vnc_rhnck(char *tag)
220 : {
221 83 : struct bgp *bgp;
222 83 : struct skiplist *sl;
223 83 : struct skiplistnode *p;
224 :
225 83 : bgp = bgp_get_default();
226 83 : if (!bgp)
227 : return;
228 83 : sl = bgp->rfapi->resolve_nve_nexthop;
229 :
230 83 : if (!sl)
231 : return;
232 :
233 : /* XXX uses secret knowledge of skiplist structure */
234 0 : for (p = sl->header->forward[0]; p; p = p->forward[0]) {
235 0 : struct prefix_bag *pb;
236 0 : struct prefix *pkey;
237 0 : afi_t afi;
238 0 : struct prefix pfx_orig_nexthop;
239 :
240 0 : memset(&pfx_orig_nexthop, 0,
241 : sizeof(pfx_orig_nexthop)); /* keep valgrind happy */
242 :
243 0 : pkey = p->key;
244 0 : pb = p->value;
245 :
246 0 : afi = family2afi(pb->upfx.family);
247 :
248 0 : rfapiUnicastNexthop2Prefix(afi, pb->ubpi->attr,
249 : &pfx_orig_nexthop);
250 :
251 : /* pb->hpfx, pb->ubpi nexthop, pkey should all reflect the same
252 : * pfx */
253 0 : assert(!vnc_prefix_cmp(&pb->hpfx, pkey));
254 0 : if (vnc_prefix_cmp(&pb->hpfx, &pfx_orig_nexthop)) {
255 0 : vnc_zlog_debug_verbose(
256 : "%s: %s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
257 : __func__, tag, &pfx_orig_nexthop, &pb->hpfx);
258 0 : assert(0);
259 : }
260 : }
261 0 : vnc_zlog_debug_verbose("%s: vnc_rhnck OK", tag);
262 : }
263 :
264 : #define VNC_RHNCK(n) \
265 : do { \
266 : char buf[BUFSIZ]; \
267 : snprintf(buf, sizeof(buf), "%s: %s", __func__, #n); \
268 : vnc_rhnck(buf); \
269 : } while (0)
270 :
271 : #else
272 :
273 : #define VNC_RHNCK(n)
274 :
275 : #endif
276 :
277 : /***********************************************************************
278 : * Add/Delete Unicast Route
279 : ***********************************************************************/
280 :
281 : /*
282 : * "Adding a Route" import process
283 : */
284 :
285 : /*
286 : * extract and package information from the BGP unicast route.
287 : * Return code 0 means OK, non-0 means drop.
288 : *
289 : * If return code is 0, caller MUST release ecom
290 : */
291 0 : static int process_unicast_route(struct bgp *bgp, /* in */
292 : afi_t afi, /* in */
293 : const struct prefix *prefix, /* in */
294 : struct bgp_path_info *info, /* in */
295 : struct ecommunity **ecom, /* OUT */
296 : struct prefix *unicast_nexthop) /* OUT */
297 : {
298 0 : struct rfapi_cfg *hc = bgp->rfapi_cfg;
299 0 : struct peer *peer = info->peer;
300 0 : struct attr *attr = info->attr;
301 0 : struct attr hattr;
302 0 : struct route_map *rmap = NULL;
303 0 : struct prefix pfx_orig_nexthop;
304 :
305 0 : memset(&pfx_orig_nexthop, 0,
306 : sizeof(pfx_orig_nexthop)); /* keep valgrind happy */
307 :
308 : /*
309 : * prefix list check
310 : */
311 0 : if (hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]) {
312 0 : vnc_zlog_debug_verbose("%s: HC prefix list is set, checking",
313 : __func__);
314 0 : if (prefix_list_apply(
315 : hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi],
316 : prefix)
317 : == PREFIX_DENY) {
318 0 : vnc_zlog_debug_verbose(
319 : "%s: prefix list returns DENY, blocking route",
320 : __func__);
321 0 : return -1;
322 : }
323 0 : vnc_zlog_debug_verbose(
324 : "%s: prefix list returns PASS, allowing route",
325 : __func__);
326 : }
327 :
328 : /* apply routemap, if any, later */
329 0 : rmap = hc->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT];
330 :
331 : /*
332 : * Extract original nexthop, which we expect to be a NVE connected
333 : * router
334 : * Note that this is the nexthop before any possible application of
335 : * policy
336 : */
337 : /*
338 : * Incoming prefix is unicast. If v6, it is in multiprotocol area,
339 : * but if v4 it is in attr->nexthop
340 : */
341 0 : rfapiUnicastNexthop2Prefix(afi, attr, &pfx_orig_nexthop);
342 :
343 : /*
344 : * route map handling
345 : * This code is here because it allocates an interned attr which
346 : * must be freed before we return. It's easier to put it after
347 : * all of the possible returns above.
348 : */
349 0 : memset(&hattr, 0, sizeof(hattr));
350 : /* hattr becomes a ghost attr */
351 0 : hattr = *attr;
352 :
353 0 : if (rmap) {
354 0 : struct bgp_path_info info;
355 0 : route_map_result_t ret;
356 :
357 0 : memset(&info, 0, sizeof(info));
358 0 : info.peer = peer;
359 0 : info.attr = &hattr;
360 0 : ret = route_map_apply(rmap, prefix, &info);
361 0 : if (ret == RMAP_DENYMATCH) {
362 0 : bgp_attr_flush(&hattr);
363 0 : vnc_zlog_debug_verbose(
364 : "%s: route map \"%s\" says DENY, returning",
365 : __func__, rmap->name);
366 0 : return -1;
367 : }
368 : }
369 :
370 : /*
371 : * Get the (possibly altered by policy) unicast nexthop
372 : * for later lookup in the Import Table by caller
373 : */
374 0 : rfapiUnicastNexthop2Prefix(afi, &hattr, unicast_nexthop);
375 :
376 0 : if (bgp_attr_get_ecommunity(&hattr))
377 0 : *ecom = ecommunity_dup(bgp_attr_get_ecommunity(&hattr));
378 : else
379 0 : *ecom = ecommunity_new();
380 :
381 : /*
382 : * Done with hattr, clean up
383 : */
384 0 : bgp_attr_flush(&hattr);
385 :
386 : /*
387 : * Add EC that carries original NH of iBGP route (2 bytes = magic
388 : * value indicating it came from an VNC gateway; default 5226, but
389 : * must be user configurable). Note that this is the nexthop before
390 : * any application of policy.
391 : */
392 : {
393 0 : struct ecommunity_val vnc_gateway_magic;
394 0 : uint16_t localadmin;
395 :
396 : /* Using route origin extended community type */
397 0 : memset(&vnc_gateway_magic, 0, sizeof(vnc_gateway_magic));
398 0 : vnc_gateway_magic.val[0] = 0x01;
399 0 : vnc_gateway_magic.val[1] = 0x03;
400 :
401 : /* Only works for IPv4 nexthops */
402 0 : if (prefix->family == AF_INET) {
403 0 : memcpy(vnc_gateway_magic.val + 2,
404 : &unicast_nexthop->u.prefix4, 4);
405 : }
406 0 : localadmin = htons(hc->resolve_nve_roo_local_admin);
407 0 : memcpy(vnc_gateway_magic.val + 6, (char *)&localadmin, 2);
408 :
409 0 : ecommunity_add_val(*ecom, &vnc_gateway_magic, false, false);
410 : }
411 :
412 0 : return 0;
413 : }
414 :
415 :
416 0 : static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
417 : struct bgp *bgp, afi_t afi, struct bgp_path_info *bpi, /* VPN bpi */
418 : struct prefix_rd *prd, /* RD */
419 : const struct prefix *prefix, /* unicast route prefix */
420 : uint32_t *local_pref, /* NULL = no local_pref */
421 : uint32_t *med, /* NULL = no med */
422 : struct ecommunity *ecom) /* generated ecoms */
423 : {
424 0 : struct prefix un;
425 0 : struct prefix nexthop;
426 0 : struct rfapi_ip_addr nexthop_h;
427 0 : uint32_t lifetime;
428 0 : uint32_t *plifetime;
429 0 : struct bgp_attr_encap_subtlv *encaptlvs;
430 0 : uint32_t label = 0;
431 :
432 0 : struct rfapi_un_option optary[3];
433 0 : struct rfapi_un_option *opt = NULL;
434 0 : int cur_opt = 0;
435 :
436 0 : vnc_zlog_debug_verbose("%s: entry", __func__);
437 :
438 0 : if (bpi->type != ZEBRA_ROUTE_BGP
439 0 : && bpi->type != ZEBRA_ROUTE_BGP_DIRECT) {
440 :
441 0 : return;
442 : }
443 0 : if (bpi->sub_type != BGP_ROUTE_NORMAL
444 : && bpi->sub_type != BGP_ROUTE_STATIC
445 0 : && bpi->sub_type != BGP_ROUTE_RFP) {
446 :
447 : return;
448 : }
449 0 : if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
450 : return;
451 :
452 0 : vncHDResolveNve.peer = bpi->peer;
453 0 : if (!rfapiGetVncTunnelUnAddr(bpi->attr, &un)) {
454 0 : if (rfapiQprefix2Raddr(&un, &vncHDResolveNve.un_addr))
455 : return;
456 : } else {
457 0 : memset(&vncHDResolveNve.un_addr, 0,
458 : sizeof(vncHDResolveNve.un_addr));
459 : }
460 :
461 : /* Use nexthop of VPN route as nexthop of constructed route */
462 0 : rfapiNexthop2Prefix(bpi->attr, &nexthop);
463 0 : rfapiQprefix2Raddr(&nexthop, &nexthop_h);
464 :
465 0 : if (rfapiGetVncLifetime(bpi->attr, &lifetime)) {
466 : plifetime = NULL;
467 : } else {
468 0 : plifetime = &lifetime;
469 : }
470 :
471 0 : encaptlvs = bgp_attr_get_vnc_subtlvs(bpi->attr);
472 0 : if (bpi->attr->encap_tunneltype != BGP_ENCAP_TYPE_RESERVED
473 0 : && bpi->attr->encap_tunneltype != BGP_ENCAP_TYPE_MPLS) {
474 0 : opt = &optary[cur_opt++];
475 0 : memset(opt, 0, sizeof(struct rfapi_un_option));
476 0 : opt->type = RFAPI_UN_OPTION_TYPE_TUNNELTYPE;
477 0 : opt->v.tunnel.type = bpi->attr->encap_tunneltype;
478 : /* TBD parse bpi->attr->extra->encap_subtlvs */
479 : }
480 :
481 0 : struct ecommunity *new_ecom = ecommunity_dup(ecom);
482 :
483 0 : if (bgp_attr_get_ecommunity(bpi->attr))
484 0 : ecommunity_merge(new_ecom, bgp_attr_get_ecommunity(bpi->attr));
485 :
486 0 : if (bpi->extra)
487 0 : label = decode_label(&bpi->extra->label[0]);
488 :
489 0 : add_vnc_route(&vncHDResolveNve, bgp, SAFI_MPLS_VPN,
490 : prefix, /* unicast route prefix */
491 : prd, &nexthop_h, /* new nexthop */
492 : local_pref, plifetime,
493 : (struct bgp_tea_options *)encaptlvs, /* RFP options */
494 : opt, NULL, new_ecom, med, /* NULL => don't set med */
495 0 : (label ? &label : NULL), /* NULL= default */
496 : ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
497 : RFAPI_AHR_RFPOPT_IS_VNCTLV); /* flags */
498 :
499 0 : ecommunity_free(&new_ecom);
500 : }
501 :
502 0 : static void vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
503 : struct prefix_rd *prd, /* RD */
504 : struct bgp_table *table_rd, /* per-rd VPN route table */
505 : afi_t afi, struct bgp *bgp,
506 : const struct prefix *prefix, /* unicast prefix */
507 : struct ecommunity *ecom, /* generated ecoms */
508 : uint32_t *local_pref, /* NULL = no local_pref */
509 : uint32_t *med, /* NULL = no med */
510 : struct prefix *ubpi_nexthop) /* unicast nexthop */
511 : {
512 0 : struct bgp_dest *bd;
513 0 : struct bgp_path_info *bpi;
514 :
515 0 : if (!table_rd)
516 : return;
517 :
518 0 : vnc_zlog_debug_verbose("%s: ubpi_nexthop=%pFX", __func__, ubpi_nexthop);
519 :
520 : /* exact match */
521 0 : bd = bgp_node_lookup(table_rd, ubpi_nexthop);
522 0 : if (!bd) {
523 0 : vnc_zlog_debug_verbose(
524 : "%s: no match in RD's table for ubpi_nexthop",
525 : __func__);
526 0 : return;
527 : }
528 :
529 : /* Iterate over bgp_info items at this node */
530 0 : for (bpi = bgp_dest_get_bgp_path_info(bd); bpi; bpi = bpi->next) {
531 :
532 0 : vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
533 : bgp, afi, bpi, /* VPN bpi */
534 : prd, prefix, local_pref, med, ecom);
535 : }
536 :
537 0 : bgp_dest_unlock_node(bd);
538 : }
539 :
540 0 : static void vnc_import_bgp_add_route_mode_resolve_nve(
541 : struct bgp *bgp, const struct prefix *prefix, /* unicast prefix */
542 : struct bgp_path_info *info) /* unicast info */
543 : {
544 0 : afi_t afi = family2afi(prefix->family);
545 :
546 0 : struct prefix pfx_unicast_nexthop = {0}; /* happy valgrind */
547 :
548 0 : struct ecommunity *ecom = NULL;
549 0 : uint32_t local_pref;
550 0 : uint32_t *med = NULL;
551 :
552 0 : struct prefix_bag *pb;
553 0 : struct bgp_dest *bdp; /* prd table node */
554 :
555 : /*debugging */
556 0 : if (VNC_DEBUG(VERBOSE)) {
557 0 : char str_nh[PREFIX_STRLEN];
558 0 : struct prefix nh;
559 :
560 0 : nh.prefixlen = 0;
561 0 : rfapiUnicastNexthop2Prefix(afi, info->attr, &nh);
562 0 : if (nh.prefixlen) {
563 0 : prefix2str(&nh, str_nh, sizeof(str_nh));
564 : } else {
565 0 : str_nh[0] = '?';
566 0 : str_nh[1] = 0;
567 : }
568 :
569 0 : vnc_zlog_debug_verbose(
570 : "%s(bgp=%p, unicast prefix=%pFX, unicast nh=%s)",
571 : __func__, bgp, prefix, str_nh);
572 : }
573 :
574 0 : if (info->type != ZEBRA_ROUTE_BGP) {
575 0 : vnc_zlog_debug_verbose(
576 : "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
577 : __func__, info->type, zebra_route_string(info->type),
578 : ZEBRA_ROUTE_BGP, "ZEBRA_ROUTE_BGP");
579 0 : return;
580 : }
581 :
582 : /*
583 : * Preliminary checks
584 : */
585 :
586 0 : if (!afi) {
587 0 : flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of prefix",
588 : __func__);
589 0 : return;
590 : }
591 :
592 0 : if (!(bgp->rfapi_cfg)) {
593 0 : vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
594 : __func__);
595 0 : return;
596 : }
597 :
598 : /* check vnc redist flag for bgp direct routes */
599 0 : if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
600 0 : vnc_zlog_debug_verbose(
601 : "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
602 : __func__, afi);
603 0 : return;
604 : }
605 :
606 :
607 0 : if (process_unicast_route(bgp, afi, prefix, info, &ecom,
608 : &pfx_unicast_nexthop)) {
609 :
610 0 : vnc_zlog_debug_verbose(
611 : "%s: process_unicast_route error, skipping", __func__);
612 0 : return;
613 : }
614 :
615 0 : local_pref = calc_local_pref(info->attr, info->peer);
616 0 : if (info->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
617 0 : med = &info->attr->med;
618 :
619 : /*
620 : * At this point, we have allocated:
621 : *
622 : * ecom ecommunity ptr, union of unicast and ROO parts (no NVE part)
623 : *
624 : * And we have set:
625 : *
626 : * pfx_unicast_nexthop nexthop of uncast route
627 : */
628 :
629 0 : if (!bgp->rfapi->resolve_nve_nexthop) {
630 0 : bgp->rfapi->resolve_nve_nexthop =
631 0 : skiplist_new(SKIPLIST_FLAG_ALLOW_DUPLICATES,
632 : vnc_prefix_cmp, prefix_bag_free);
633 : }
634 :
635 0 : pb = XCALLOC(MTYPE_RFAPI_PREFIX_BAG, sizeof(struct prefix_bag));
636 0 : pb->hpfx = pfx_unicast_nexthop;
637 0 : pb->ubpi = info;
638 0 : pb->upfx = *prefix;
639 :
640 0 : bgp_path_info_lock(info); /* skiplist refers to it */
641 0 : skiplist_insert(bgp->rfapi->resolve_nve_nexthop, &pb->hpfx, pb);
642 :
643 : /*
644 : * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
645 : * (exact match, /32). If an exact match is found, call add_vnc_route.
646 : */
647 :
648 0 : for (bdp = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); bdp;
649 0 : bdp = bgp_route_next(bdp)) {
650 :
651 0 : struct bgp_table *table;
652 :
653 0 : table = bgp_dest_get_bgp_table_info(bdp);
654 :
655 0 : if (!table)
656 0 : continue;
657 :
658 0 : vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
659 0 : (struct prefix_rd *)bgp_dest_get_prefix(bdp), table,
660 : afi, bgp, prefix, ecom, &local_pref, med,
661 : &pfx_unicast_nexthop);
662 : }
663 :
664 :
665 0 : if (ecom)
666 0 : ecommunity_free(&ecom);
667 :
668 0 : vnc_zlog_debug_verbose("%s: done", __func__);
669 : }
670 :
671 :
672 0 : static void vnc_import_bgp_add_route_mode_plain(struct bgp *bgp,
673 : const struct prefix *prefix,
674 : struct bgp_path_info *info)
675 : {
676 0 : afi_t afi = family2afi(prefix->family);
677 0 : struct peer *peer = info->peer;
678 0 : struct attr *attr = info->attr;
679 0 : struct attr hattr;
680 0 : struct rfapi_cfg *hc = bgp->rfapi_cfg;
681 0 : struct attr *iattr = NULL;
682 :
683 0 : struct rfapi_ip_addr vnaddr;
684 0 : struct prefix vn_pfx_space;
685 0 : struct prefix *vn_pfx = NULL;
686 0 : int ahr_flags = 0;
687 0 : struct ecommunity *ecom = NULL;
688 0 : struct prefix_rd prd;
689 0 : struct route_map *rmap = NULL;
690 0 : uint32_t local_pref;
691 0 : uint32_t *med = NULL;
692 :
693 0 : vnc_zlog_debug_verbose("%s(prefix=%pFX) entry", __func__, prefix);
694 :
695 0 : if (!afi) {
696 0 : flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of prefix",
697 : __func__);
698 0 : return;
699 : }
700 :
701 0 : if (!hc) {
702 0 : vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
703 : __func__);
704 0 : return;
705 : }
706 :
707 : /* check vnc redist flag for bgp direct routes */
708 0 : if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
709 0 : vnc_zlog_debug_verbose(
710 : "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
711 : __func__, afi);
712 0 : return;
713 : }
714 :
715 : /*
716 : * mode "plain" specific code
717 : */
718 : {
719 0 : vnc_zlog_debug_verbose("%s: NOT using redist RFG", __func__);
720 :
721 : /*
722 : * prefix list check
723 : */
724 0 : if (hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]) {
725 0 : vnc_zlog_debug_verbose(
726 : "%s: HC prefix list is set, checking",
727 : __func__);
728 0 : if (prefix_list_apply(
729 : hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT]
730 : [afi],
731 : prefix)
732 : == PREFIX_DENY) {
733 0 : vnc_zlog_debug_verbose(
734 : "%s: prefix list returns DENY, blocking route",
735 : __func__);
736 0 : return;
737 : }
738 0 : vnc_zlog_debug_verbose(
739 : "%s: prefix list returns PASS, allowing route",
740 : __func__);
741 : }
742 :
743 : /* apply routemap, if any, later */
744 0 : rmap = hc->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT];
745 :
746 : /*
747 : * Incoming prefix is unicast. If v6, it is in multiprotocol
748 : * area,
749 : * but if v4 it is in attr->nexthop
750 : */
751 0 : rfapiUnicastNexthop2Prefix(afi, attr, &vn_pfx_space);
752 0 : vn_pfx = &vn_pfx_space;
753 :
754 : /* UN address */
755 0 : ahr_flags |= RFAPI_AHR_NO_TUNNEL_SUBTLV;
756 : }
757 :
758 0 : if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE))
759 0 : vnc_zlog_debug_any("%s vn_pfx=%pFX", __func__, vn_pfx);
760 :
761 : /*
762 : * Compute VN address
763 : */
764 0 : if (rfapiQprefix2Raddr(vn_pfx, &vnaddr)) {
765 0 : vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
766 : __func__);
767 0 : return;
768 : }
769 :
770 : /*
771 : * route map handling
772 : * This code is here because it allocates an interned attr which
773 : * must be freed before we return. It's easier to put it after
774 : * all of the possible returns above.
775 : */
776 0 : memset(&hattr, 0, sizeof(hattr));
777 : /* hattr becomes a ghost attr */
778 0 : hattr = *attr;
779 :
780 0 : if (rmap) {
781 0 : struct bgp_path_info info;
782 0 : route_map_result_t ret;
783 :
784 0 : memset(&info, 0, sizeof(info));
785 0 : info.peer = peer;
786 0 : info.attr = &hattr;
787 0 : ret = route_map_apply(rmap, prefix, &info);
788 0 : if (ret == RMAP_DENYMATCH) {
789 0 : bgp_attr_flush(&hattr);
790 0 : vnc_zlog_debug_verbose(
791 : "%s: route map \"%s\" says DENY, returning",
792 : __func__, rmap->name);
793 0 : return;
794 : }
795 : }
796 :
797 0 : iattr = bgp_attr_intern(&hattr);
798 0 : bgp_attr_flush(&hattr);
799 :
800 : /* Now iattr is an allocated interned attr */
801 :
802 : /*
803 : * Mode "plain" specific code
804 : *
805 : * Sets RD in dummy HD
806 : * Allocates ecom
807 : */
808 : {
809 0 : if (vnaddr.addr_family != AF_INET) {
810 0 : vnc_zlog_debug_verbose(
811 : "%s: can't auto-assign RD, VN AF (%d) is not IPv4, skipping",
812 : __func__, vnaddr.addr_family);
813 0 : if (iattr) {
814 0 : bgp_attr_unintern(&iattr);
815 : }
816 0 : return;
817 : }
818 0 : memset(&prd, 0, sizeof(prd));
819 0 : rfapi_set_autord_from_vn(&prd, &vnaddr);
820 :
821 0 : if (iattr && bgp_attr_get_ecommunity(iattr))
822 0 : ecom = ecommunity_dup(bgp_attr_get_ecommunity(iattr));
823 : }
824 :
825 0 : local_pref = calc_local_pref(iattr, peer);
826 :
827 0 : if (iattr && (iattr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))) {
828 0 : med = &iattr->med;
829 : }
830 :
831 0 : if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) {
832 0 : char buf[PREFIX_STRLEN];
833 :
834 0 : rfapiRfapiIpAddr2Str(&vnaddr, buf, sizeof(buf));
835 0 : vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__, buf);
836 : }
837 :
838 0 : vncHDBgpDirect.peer = peer;
839 0 : add_vnc_route(&vncHDBgpDirect, bgp, SAFI_MPLS_VPN, prefix, &prd,
840 0 : &vnaddr, &local_pref, &(bgp->rfapi_cfg->redist_lifetime),
841 : NULL, /* RFP options */
842 : NULL, NULL, ecom, med, /* med */
843 : NULL, /* label: default */
844 : ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
845 : ahr_flags);
846 0 : vncHDBgpDirect.peer = NULL;
847 :
848 0 : if (ecom)
849 0 : ecommunity_free(&ecom);
850 : }
851 :
852 0 : static void vnc_import_bgp_add_route_mode_nvegroup(
853 : struct bgp *bgp, const struct prefix *prefix,
854 : struct bgp_path_info *info, struct rfapi_nve_group_cfg *rfg)
855 : {
856 0 : afi_t afi = family2afi(prefix->family);
857 0 : struct peer *peer = info->peer;
858 0 : struct attr *attr = info->attr;
859 0 : struct attr hattr;
860 0 : struct attr *iattr = NULL;
861 :
862 0 : struct rfapi_ip_addr vnaddr;
863 0 : struct prefix *vn_pfx = NULL;
864 0 : int ahr_flags = 0;
865 0 : struct ecommunity *ecom = NULL;
866 0 : struct prefix_rd prd;
867 0 : struct route_map *rmap = NULL;
868 0 : uint32_t local_pref;
869 :
870 0 : vnc_zlog_debug_verbose("%s(prefix=%pFX) entry", __func__, prefix);
871 :
872 0 : assert(rfg);
873 :
874 0 : if (!afi) {
875 0 : flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of prefix",
876 : __func__);
877 0 : return;
878 : }
879 :
880 0 : if (!(bgp->rfapi_cfg)) {
881 0 : vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
882 : __func__);
883 0 : return;
884 : }
885 :
886 : /* check vnc redist flag for bgp direct routes */
887 0 : if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
888 0 : vnc_zlog_debug_verbose(
889 : "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
890 : __func__, afi);
891 0 : return;
892 : }
893 :
894 :
895 : /*
896 : * RFG-specific code
897 : */
898 : {
899 :
900 0 : struct rfapi_ip_prefix pfx_un;
901 :
902 0 : vnc_zlog_debug_verbose("%s: using redist RFG", __func__);
903 :
904 : /*
905 : * RFG prefix list check
906 : */
907 0 : if (rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]) {
908 0 : vnc_zlog_debug_verbose(
909 : "%s: RFG prefix list is set, checking",
910 : __func__);
911 0 : if (prefix_list_apply(
912 : rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT]
913 : [afi],
914 : prefix)
915 : == PREFIX_DENY) {
916 0 : vnc_zlog_debug_verbose(
917 : "%s: prefix list returns DENY, blocking route",
918 : __func__);
919 0 : return;
920 : }
921 0 : vnc_zlog_debug_verbose(
922 : "%s: prefix list returns PASS, allowing route",
923 : __func__);
924 : }
925 :
926 : /* apply routemap, if any, later */
927 0 : rmap = rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT];
928 :
929 : /*
930 : * export nve group's VN addr prefix must be a /32 which
931 : * will yield the VN addr to use
932 : */
933 0 : vn_pfx = &rfg->vn_prefix;
934 :
935 : /*
936 : * UN Address
937 : */
938 0 : if (!is_host_prefix(&rfg->un_prefix)) {
939 : /* NB prefixlen==0 means it has not been configured */
940 0 : vnc_zlog_debug_verbose(
941 : "%s: redist RFG UN pfx not host pfx (plen=%d), skipping",
942 : __func__, rfg->un_prefix.prefixlen);
943 0 : return;
944 : }
945 :
946 0 : rfapiQprefix2Rprefix(&rfg->un_prefix, &pfx_un);
947 :
948 0 : vncHDBgpDirect.un_addr = pfx_un.prefix;
949 : }
950 :
951 0 : if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE))
952 0 : vnc_zlog_debug_any("%s vn_pfx=%pFX", __func__, vn_pfx);
953 :
954 : /*
955 : * Compute VN address
956 : */
957 0 : if (rfapiQprefix2Raddr(vn_pfx, &vnaddr)) {
958 0 : vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
959 : __func__);
960 0 : return;
961 : }
962 :
963 : /*
964 : * route map handling
965 : * This code is here because it allocates an interned attr which
966 : * must be freed before we return. It's easier to put it after
967 : * all of the possible returns above.
968 : */
969 0 : memset(&hattr, 0, sizeof(hattr));
970 : /* hattr becomes a ghost attr */
971 0 : hattr = *attr;
972 :
973 0 : if (rmap) {
974 0 : struct bgp_path_info path;
975 0 : route_map_result_t ret;
976 :
977 0 : memset(&path, 0, sizeof(path));
978 0 : path.peer = peer;
979 0 : path.attr = &hattr;
980 0 : ret = route_map_apply(rmap, prefix, &path);
981 0 : if (ret == RMAP_DENYMATCH) {
982 0 : bgp_attr_flush(&hattr);
983 0 : vnc_zlog_debug_verbose(
984 : "%s: route map \"%s\" says DENY, returning",
985 : __func__, rmap->name);
986 0 : return;
987 : }
988 : }
989 :
990 0 : iattr = bgp_attr_intern(&hattr);
991 0 : bgp_attr_flush(&hattr);
992 :
993 : /* Now iattr is an allocated interned attr */
994 :
995 : /*
996 : * RFG-specific code
997 : *
998 : * Sets RD in dummy HD
999 : * Allocates ecom
1000 : */
1001 : {
1002 :
1003 0 : memset(&prd, 0, sizeof(prd));
1004 0 : prd = rfg->rd;
1005 0 : prd.family = AF_UNSPEC;
1006 0 : prd.prefixlen = 64;
1007 :
1008 0 : if (rfg->rd.family == AF_UNIX) {
1009 0 : rfapi_set_autord_from_vn(&prd, &vnaddr);
1010 : }
1011 :
1012 0 : if (rfg->rt_export_list)
1013 0 : ecom = ecommunity_dup(
1014 0 : bgp->rfapi_cfg->rfg_redist->rt_export_list);
1015 : else
1016 0 : ecom = ecommunity_new();
1017 :
1018 0 : if (iattr && bgp_attr_get_ecommunity(iattr))
1019 0 : ecom = ecommunity_merge(ecom,
1020 : bgp_attr_get_ecommunity(iattr));
1021 : }
1022 :
1023 0 : local_pref = calc_local_pref(iattr, peer);
1024 :
1025 0 : if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) {
1026 0 : char buf[BUFSIZ];
1027 :
1028 0 : buf[0] = 0;
1029 0 : rfapiRfapiIpAddr2Str(&vnaddr, buf, BUFSIZ);
1030 0 : buf[BUFSIZ - 1] = 0;
1031 0 : vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__, buf);
1032 : }
1033 :
1034 0 : vncHDBgpDirect.peer = peer;
1035 0 : add_vnc_route(&vncHDBgpDirect, bgp, SAFI_MPLS_VPN, prefix, &prd,
1036 0 : &vnaddr, &local_pref, &(bgp->rfapi_cfg->redist_lifetime),
1037 : NULL, /* RFP options */
1038 : NULL, NULL, ecom, NULL, /* med */
1039 : NULL, /* label: default */
1040 : ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
1041 : ahr_flags);
1042 0 : vncHDBgpDirect.peer = NULL;
1043 :
1044 0 : if (ecom)
1045 0 : ecommunity_free(&ecom);
1046 : }
1047 :
1048 0 : static void vnc_import_bgp_del_route_mode_plain(struct bgp *bgp,
1049 : const struct prefix *prefix,
1050 : struct bgp_path_info *info)
1051 : {
1052 0 : struct prefix_rd prd;
1053 0 : afi_t afi = family2afi(prefix->family);
1054 0 : struct prefix *vn_pfx = NULL;
1055 0 : struct rfapi_ip_addr vnaddr;
1056 0 : struct prefix vn_pfx_space;
1057 :
1058 :
1059 0 : assert(afi);
1060 :
1061 : /*
1062 : * Compute VN address
1063 : */
1064 :
1065 0 : if (info) {
1066 0 : rfapiUnicastNexthop2Prefix(afi, info->attr, &vn_pfx_space);
1067 : } else {
1068 0 : vnc_zlog_debug_verbose("%s: no attr, can't delete route",
1069 : __func__);
1070 0 : return;
1071 : }
1072 0 : vn_pfx = &vn_pfx_space;
1073 :
1074 0 : vnaddr.addr_family = vn_pfx->family;
1075 0 : switch (vn_pfx->family) {
1076 0 : case AF_INET:
1077 0 : if (vn_pfx->prefixlen != IPV4_MAX_BITLEN) {
1078 0 : vnc_zlog_debug_verbose(
1079 : "%s: redist VN plen (%d) != 32, skipping",
1080 : __func__, vn_pfx->prefixlen);
1081 0 : return;
1082 : }
1083 0 : vnaddr.addr.v4 = vn_pfx->u.prefix4;
1084 0 : break;
1085 :
1086 0 : case AF_INET6:
1087 0 : if (vn_pfx->prefixlen != IPV6_MAX_BITLEN) {
1088 0 : vnc_zlog_debug_verbose(
1089 : "%s: redist VN plen (%d) != 128, skipping",
1090 : __func__, vn_pfx->prefixlen);
1091 0 : return;
1092 : }
1093 0 : vnaddr.addr.v6 = vn_pfx->u.prefix6;
1094 0 : break;
1095 :
1096 0 : default:
1097 0 : vnc_zlog_debug_verbose(
1098 : "%s: no redist RFG VN host pfx configured, skipping",
1099 : __func__);
1100 : return;
1101 : }
1102 :
1103 :
1104 0 : memset(&prd, 0, sizeof(prd));
1105 0 : if (rfapi_set_autord_from_vn(&prd, &vnaddr)) {
1106 0 : vnc_zlog_debug_verbose("%s: can't auto-assign RD, skipping",
1107 : __func__);
1108 0 : return;
1109 : }
1110 :
1111 0 : vncHDBgpDirect.peer = info->peer;
1112 0 : vnc_zlog_debug_verbose("%s: setting peer to %p", __func__,
1113 : vncHDBgpDirect.peer);
1114 0 : del_vnc_route(&vncHDBgpDirect, info->peer, bgp, SAFI_MPLS_VPN, prefix,
1115 : &prd, ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
1116 : NULL, 1);
1117 :
1118 0 : vncHDBgpDirect.peer = NULL;
1119 : }
1120 :
1121 0 : static void vnc_import_bgp_del_route_mode_nvegroup(struct bgp *bgp,
1122 : const struct prefix *prefix,
1123 : struct bgp_path_info *info)
1124 : {
1125 0 : struct prefix_rd prd;
1126 0 : afi_t afi = family2afi(prefix->family);
1127 0 : struct rfapi_nve_group_cfg *rfg = NULL;
1128 0 : struct prefix *vn_pfx = NULL;
1129 0 : struct rfapi_ip_addr vnaddr;
1130 :
1131 :
1132 0 : assert(afi);
1133 :
1134 0 : rfg = bgp->rfapi_cfg->rfg_redist;
1135 0 : assert(rfg);
1136 :
1137 : /*
1138 : * Compute VN address
1139 : */
1140 :
1141 : /*
1142 : * export nve group's VN addr prefix must be a /32 which
1143 : * will yield the VN addr to use
1144 : */
1145 0 : vn_pfx = &rfg->vn_prefix;
1146 :
1147 :
1148 0 : vnaddr.addr_family = vn_pfx->family;
1149 0 : switch (vn_pfx->family) {
1150 0 : case AF_INET:
1151 0 : if (vn_pfx->prefixlen != IPV4_MAX_BITLEN) {
1152 0 : vnc_zlog_debug_verbose(
1153 : "%s: redist VN plen (%d) != 32, skipping",
1154 : __func__, vn_pfx->prefixlen);
1155 0 : return;
1156 : }
1157 0 : vnaddr.addr.v4 = vn_pfx->u.prefix4;
1158 0 : break;
1159 :
1160 0 : case AF_INET6:
1161 0 : if (vn_pfx->prefixlen != IPV6_MAX_BITLEN) {
1162 0 : vnc_zlog_debug_verbose(
1163 : "%s: redist VN plen (%d) != 128, skipping",
1164 : __func__, vn_pfx->prefixlen);
1165 0 : return;
1166 : }
1167 0 : vnaddr.addr.v6 = vn_pfx->u.prefix6;
1168 0 : break;
1169 :
1170 0 : default:
1171 0 : vnc_zlog_debug_verbose(
1172 : "%s: no redist RFG VN host pfx configured, skipping",
1173 : __func__);
1174 : return;
1175 : }
1176 :
1177 0 : memset(&prd, 0, sizeof(prd));
1178 0 : prd = rfg->rd;
1179 0 : prd.family = AF_UNSPEC;
1180 0 : prd.prefixlen = 64;
1181 :
1182 0 : if (rfg->rd.family == AF_UNIX) {
1183 : /* means "auto" with VN addr */
1184 0 : if (rfapi_set_autord_from_vn(&prd, &vnaddr)) {
1185 0 : vnc_zlog_debug_verbose(
1186 : "%s: can't auto-assign RD, skipping", __func__);
1187 0 : return;
1188 : }
1189 : }
1190 :
1191 :
1192 0 : vncHDBgpDirect.peer = info->peer;
1193 0 : vnc_zlog_debug_verbose("%s: setting peer to %p", __func__,
1194 : vncHDBgpDirect.peer);
1195 0 : del_vnc_route(&vncHDBgpDirect, info->peer, bgp, SAFI_MPLS_VPN, prefix,
1196 : &prd, ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
1197 : NULL, 1);
1198 :
1199 0 : vncHDBgpDirect.peer = NULL;
1200 : }
1201 :
1202 0 : static void vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1203 : struct bgp *bgp, afi_t afi, struct bgp_path_info *bpi, /* VPN bpi */
1204 : struct prefix_rd *prd, /* RD */
1205 : const struct prefix *prefix) /* unicast route prefix */
1206 : {
1207 0 : struct prefix un;
1208 :
1209 0 : if (bpi->type != ZEBRA_ROUTE_BGP
1210 0 : && bpi->type != ZEBRA_ROUTE_BGP_DIRECT) {
1211 :
1212 0 : return;
1213 : }
1214 0 : if (bpi->sub_type != BGP_ROUTE_NORMAL
1215 : && bpi->sub_type != BGP_ROUTE_STATIC
1216 0 : && bpi->sub_type != BGP_ROUTE_RFP) {
1217 :
1218 : return;
1219 : }
1220 0 : if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
1221 : return;
1222 :
1223 0 : vncHDResolveNve.peer = bpi->peer;
1224 0 : if (!rfapiGetVncTunnelUnAddr(bpi->attr, &un)) {
1225 0 : if (rfapiQprefix2Raddr(&un, &vncHDResolveNve.un_addr))
1226 : return;
1227 : } else {
1228 0 : memset(&vncHDResolveNve.un_addr, 0,
1229 : sizeof(vncHDResolveNve.un_addr));
1230 : }
1231 :
1232 0 : del_vnc_route(&vncHDResolveNve, vncHDResolveNve.peer, bgp,
1233 : SAFI_MPLS_VPN, prefix, /* unicast route prefix */
1234 : prd, ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL,
1235 : 0); /* flags */
1236 : }
1237 :
1238 0 : static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1239 : struct prefix_rd *prd,
1240 : struct bgp_table *table_rd, /* per-rd VPN route table */
1241 : afi_t afi, struct bgp *bgp,
1242 : const struct prefix *prefix, /* unicast prefix */
1243 : const struct prefix *ubpi_nexthop) /* unicast bpi's nexthop */
1244 : {
1245 0 : struct bgp_dest *bd;
1246 0 : struct bgp_path_info *bpi;
1247 :
1248 0 : if (!table_rd)
1249 : return;
1250 :
1251 0 : vnc_zlog_debug_verbose("%s: ubpi_nexthop=%pFX", __func__, ubpi_nexthop);
1252 :
1253 :
1254 : /* exact match */
1255 0 : bd = bgp_node_lookup(table_rd, ubpi_nexthop);
1256 0 : if (!bd) {
1257 0 : vnc_zlog_debug_verbose(
1258 : "%s: no match in RD's table for ubpi_nexthop",
1259 : __func__);
1260 0 : return;
1261 : }
1262 :
1263 : /* Iterate over bgp_info items at this node */
1264 0 : for (bpi = bgp_dest_get_bgp_path_info(bd); bpi; bpi = bpi->next) {
1265 :
1266 0 : vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1267 : bgp, afi, bpi, /* VPN bpi */
1268 : prd, /* VPN RD */
1269 : prefix); /* unicast route prefix */
1270 : }
1271 :
1272 0 : bgp_dest_unlock_node(bd);
1273 : }
1274 :
1275 : static void
1276 0 : vnc_import_bgp_del_route_mode_resolve_nve(struct bgp *bgp, afi_t afi,
1277 : const struct prefix *prefix,
1278 : struct bgp_path_info *info)
1279 : {
1280 0 : struct ecommunity *ecom = NULL;
1281 0 : struct prefix pfx_unicast_nexthop = {0}; /* happy valgrind */
1282 :
1283 : // struct listnode *hnode;
1284 : // struct rfapi_descriptor *rfd;
1285 0 : struct prefix_bag *pb;
1286 0 : void *cursor;
1287 0 : struct skiplist *sl = bgp->rfapi->resolve_nve_nexthop;
1288 0 : int rc;
1289 0 : struct bgp_dest *bdp; /* prd table node */
1290 :
1291 0 : if (!sl) {
1292 0 : vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1293 : __func__);
1294 0 : return;
1295 : }
1296 :
1297 0 : if (info->type != ZEBRA_ROUTE_BGP) {
1298 0 : vnc_zlog_debug_verbose(
1299 : "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
1300 : __func__, info->type, zebra_route_string(info->type),
1301 : ZEBRA_ROUTE_BGP, "ZEBRA_ROUTE_BGP");
1302 0 : return;
1303 : }
1304 :
1305 0 : if (process_unicast_route(bgp, afi, prefix, info, &ecom,
1306 : &pfx_unicast_nexthop)) {
1307 :
1308 0 : vnc_zlog_debug_verbose(
1309 : "%s: process_unicast_route error, skipping", __func__);
1310 0 : return;
1311 : }
1312 :
1313 0 : rc = skiplist_first_value(sl, &pfx_unicast_nexthop, (void *)&pb,
1314 : &cursor);
1315 0 : while (!rc) {
1316 0 : if (pb->ubpi == info) {
1317 0 : skiplist_delete(sl, &pfx_unicast_nexthop, pb);
1318 0 : bgp_path_info_unlock(info);
1319 0 : break;
1320 : }
1321 0 : rc = skiplist_next_value(sl, &pfx_unicast_nexthop, (void *)&pb,
1322 : &cursor);
1323 : }
1324 :
1325 : /*
1326 : * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
1327 : * (exact match, /32). If an exact match is found, call add_vnc_route.
1328 : */
1329 :
1330 0 : for (bdp = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); bdp;
1331 0 : bdp = bgp_route_next(bdp)) {
1332 :
1333 0 : struct bgp_table *table;
1334 :
1335 0 : table = bgp_dest_get_bgp_table_info(bdp);
1336 :
1337 0 : if (!table)
1338 0 : continue;
1339 :
1340 0 : vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1341 0 : (struct prefix_rd *)bgp_dest_get_prefix(bdp), table,
1342 : afi, bgp, prefix, &pfx_unicast_nexthop);
1343 : }
1344 :
1345 0 : if (ecom)
1346 0 : ecommunity_free(&ecom);
1347 : }
1348 :
1349 :
1350 : /***********************************************************************
1351 : * Add/Delete CE->NVE routes
1352 : ***********************************************************************/
1353 :
1354 : /*
1355 : * Should be called whan a bpi is added to VPN RIB. This function
1356 : * will check if it is a host route and return immediately if not.
1357 : */
1358 0 : void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1359 : struct bgp *bgp, struct prefix_rd *prd, /* RD */
1360 : struct bgp_table *table_rd, /* per-rd VPN route table */
1361 : const struct prefix *prefix, /* VPN prefix */
1362 : struct bgp_path_info *bpi) /* new VPN host route */
1363 : {
1364 0 : afi_t afi = family2afi(prefix->family);
1365 0 : struct skiplist *sl = NULL;
1366 0 : int rc;
1367 0 : struct prefix_bag *pb;
1368 0 : void *cursor;
1369 0 : struct rfapi_cfg *hc = NULL;
1370 :
1371 0 : vnc_zlog_debug_verbose("%s: entry", __func__);
1372 :
1373 0 : if (afi != AFI_IP && afi != AFI_IP6) {
1374 0 : vnc_zlog_debug_verbose("%s: bad afi %d, skipping", __func__,
1375 : afi);
1376 0 : return;
1377 : }
1378 :
1379 0 : if (!(hc = bgp->rfapi_cfg)) {
1380 0 : vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1381 : __func__);
1382 0 : return;
1383 : }
1384 :
1385 : /* check vnc redist flag for bgp direct routes */
1386 0 : if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
1387 0 : vnc_zlog_debug_verbose(
1388 : "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1389 : __func__, afi);
1390 0 : return;
1391 : }
1392 :
1393 0 : if (hc->redist_mode != VNC_REDIST_MODE_RESOLVE_NVE) {
1394 0 : vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1395 : __func__);
1396 0 : return;
1397 : }
1398 :
1399 0 : if (bgp->rfapi)
1400 0 : sl = bgp->rfapi->resolve_nve_nexthop;
1401 :
1402 0 : if (!sl) {
1403 0 : vnc_zlog_debug_verbose(
1404 : "%s: no resolve_nve_nexthop skiplist, skipping",
1405 : __func__);
1406 0 : return;
1407 : }
1408 :
1409 0 : if (!is_host_prefix(prefix)) {
1410 0 : vnc_zlog_debug_verbose("%s: not host prefix, skipping",
1411 : __func__);
1412 0 : return;
1413 : }
1414 :
1415 0 : rc = skiplist_first_value(sl, prefix, (void *)&pb, &cursor);
1416 0 : while (!rc) {
1417 0 : struct ecommunity *ecom;
1418 0 : struct prefix pfx_unicast_nexthop;
1419 0 : uint32_t *med = NULL;
1420 0 : uint32_t local_pref;
1421 :
1422 0 : memset(&pfx_unicast_nexthop, 0,
1423 : sizeof(pfx_unicast_nexthop)); /* keep valgrind happy */
1424 :
1425 0 : if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE))
1426 0 : vnc_zlog_debug_any(
1427 : "%s: examining RHN Entry (q=%p): upfx=%pFX, hpfx=%pFX, ubpi=%p",
1428 : __func__, cursor, &pb->upfx, &pb->hpfx,
1429 : pb->ubpi);
1430 :
1431 0 : if (process_unicast_route(bgp, afi, &pb->upfx, pb->ubpi, &ecom,
1432 : &pfx_unicast_nexthop)) {
1433 :
1434 0 : vnc_zlog_debug_verbose(
1435 : "%s: process_unicast_route error, skipping",
1436 : __func__);
1437 0 : continue;
1438 : }
1439 0 : local_pref = calc_local_pref(pb->ubpi->attr, pb->ubpi->peer);
1440 :
1441 0 : if (pb->ubpi->attr->flag
1442 0 : & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
1443 0 : med = &pb->ubpi->attr->med;
1444 :
1445 : /*
1446 : * Sanity check
1447 : */
1448 0 : if (vnc_prefix_cmp(&pfx_unicast_nexthop, prefix)) {
1449 0 : vnc_zlog_debug_verbose(
1450 : "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
1451 : __func__, &pfx_unicast_nexthop, prefix);
1452 0 : assert(0);
1453 : }
1454 :
1455 0 : vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
1456 : bgp, afi, bpi, /* VPN bpi */
1457 0 : prd, &pb->upfx, /* unicast prefix */
1458 : &local_pref, med, ecom);
1459 :
1460 0 : if (ecom)
1461 0 : ecommunity_free(&ecom);
1462 :
1463 : #if DEBUG_RHN_LIST
1464 : /* debug */
1465 : {
1466 : vnc_zlog_debug_verbose(
1467 : "%s: advancing past RHN Entry (q=%p): with prefix %pFX",
1468 : __func__, cursor, prefix);
1469 : print_rhn_list(__func__, NULL); /* debug */
1470 : }
1471 : #endif
1472 0 : rc = skiplist_next_value(sl, prefix, (void *)&pb, &cursor);
1473 : }
1474 0 : vnc_zlog_debug_verbose("%s: done", __func__);
1475 : }
1476 :
1477 :
1478 0 : void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
1479 : struct bgp *bgp, struct prefix_rd *prd, /* RD */
1480 : struct bgp_table *table_rd, /* per-rd VPN route table */
1481 : const struct prefix *prefix, /* VPN prefix */
1482 : struct bgp_path_info *bpi) /* old VPN host route */
1483 : {
1484 0 : afi_t afi = family2afi(prefix->family);
1485 0 : struct skiplist *sl = NULL;
1486 0 : struct prefix_bag *pb;
1487 0 : void *cursor;
1488 0 : struct rfapi_cfg *hc = NULL;
1489 0 : int rc;
1490 :
1491 0 : vnc_zlog_debug_verbose("%s(bgp=%p, nve prefix=%pFX)", __func__, bgp,
1492 : prefix);
1493 :
1494 0 : if (afi != AFI_IP && afi != AFI_IP6)
1495 0 : return;
1496 :
1497 0 : if (!(hc = bgp->rfapi_cfg)) {
1498 0 : vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1499 : __func__);
1500 0 : return;
1501 : }
1502 :
1503 : /* check vnc redist flag for bgp direct routes */
1504 0 : if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
1505 0 : vnc_zlog_debug_verbose(
1506 : "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1507 : __func__, afi);
1508 0 : return;
1509 : }
1510 :
1511 0 : if (hc->redist_mode != VNC_REDIST_MODE_RESOLVE_NVE) {
1512 0 : vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1513 : __func__);
1514 0 : return;
1515 : }
1516 :
1517 0 : if (bgp->rfapi)
1518 0 : sl = bgp->rfapi->resolve_nve_nexthop;
1519 :
1520 0 : if (!sl) {
1521 0 : vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1522 : __func__);
1523 0 : return;
1524 : }
1525 :
1526 0 : if (!is_host_prefix(prefix)) {
1527 0 : vnc_zlog_debug_verbose("%s: not host route, skip", __func__);
1528 0 : return;
1529 : }
1530 :
1531 : /*
1532 : * Find all entries with key == CE in the RHN list
1533 : */
1534 0 : rc = skiplist_first_value(sl, prefix, (void *)&pb, &cursor);
1535 0 : while (!rc) {
1536 :
1537 0 : struct ecommunity *ecom;
1538 0 : struct prefix pfx_unicast_nexthop;
1539 :
1540 0 : memset(&pfx_unicast_nexthop, 0,
1541 : sizeof(pfx_unicast_nexthop)); /* keep valgrind happy */
1542 :
1543 0 : if (process_unicast_route(bgp, afi, &pb->upfx, pb->ubpi, &ecom,
1544 : &pfx_unicast_nexthop)) {
1545 :
1546 0 : vnc_zlog_debug_verbose(
1547 : "%s: process_unicast_route error, skipping",
1548 : __func__);
1549 0 : continue;
1550 : }
1551 :
1552 : /*
1553 : * Sanity check
1554 : */
1555 0 : if (vnc_prefix_cmp(&pfx_unicast_nexthop, prefix)) {
1556 0 : vnc_zlog_debug_verbose(
1557 : "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
1558 : __func__, &pfx_unicast_nexthop, prefix);
1559 0 : assert(0);
1560 : }
1561 :
1562 0 : vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1563 0 : bgp, afi, bpi, prd, &pb->upfx);
1564 :
1565 0 : if (ecom)
1566 0 : ecommunity_free(&ecom);
1567 :
1568 0 : rc = skiplist_next_value(sl, prefix, (void *)&pb, &cursor);
1569 : }
1570 : }
1571 :
1572 :
1573 : /***********************************************************************
1574 : * Exterior Routes
1575 : ***********************************************************************/
1576 :
1577 : #define DEBUG_IS_USABLE_INTERIOR 1
1578 :
1579 0 : static int is_usable_interior_route(struct bgp_path_info *bpi_interior)
1580 : {
1581 0 : if (!VALID_INTERIOR_TYPE(bpi_interior->type)) {
1582 : #if DEBUG_IS_USABLE_INTERIOR
1583 0 : vnc_zlog_debug_verbose(
1584 : "%s: NO: type %d is not valid interior type", __func__,
1585 : bpi_interior->type);
1586 : #endif
1587 0 : return 0;
1588 : }
1589 0 : if (!CHECK_FLAG(bpi_interior->flags, BGP_PATH_VALID)) {
1590 : #if DEBUG_IS_USABLE_INTERIOR
1591 0 : vnc_zlog_debug_verbose("%s: NO: BGP_PATH_VALID not set",
1592 : __func__);
1593 : #endif
1594 0 : return 0;
1595 : }
1596 : return 1;
1597 : }
1598 :
1599 : /*
1600 : * There should be only one of these per prefix at a time.
1601 : * This should be called as a result of selection operation
1602 : *
1603 : * NB should be called espacially for bgp instances that are named,
1604 : * because the exterior routes will always come from one of those.
1605 : * We filter here on the instance name to make sure we get only the
1606 : * right routes.
1607 : */
1608 78 : static void vnc_import_bgp_exterior_add_route_it(
1609 : struct bgp *bgp, /* exterior instance, we hope */
1610 : const struct prefix *prefix, /* unicast prefix */
1611 : struct bgp_path_info *info, /* unicast info */
1612 : struct rfapi_import_table *it_only) /* NULL, or limit to this IT */
1613 : {
1614 78 : struct rfapi *h;
1615 78 : struct rfapi_cfg *hc;
1616 78 : struct prefix pfx_orig_nexthop;
1617 78 : struct rfapi_import_table *it;
1618 78 : struct bgp *bgp_default = bgp_get_default();
1619 78 : afi_t afi = family2afi(prefix->family);
1620 :
1621 78 : if (!bgp_default)
1622 78 : return;
1623 :
1624 78 : h = bgp_default->rfapi;
1625 78 : hc = bgp_default->rfapi_cfg;
1626 :
1627 78 : vnc_zlog_debug_verbose("%s: entry with it=%p", __func__, it_only);
1628 :
1629 78 : if (!h || !hc) {
1630 0 : vnc_zlog_debug_verbose(
1631 : "%s: rfapi or rfapi_cfg not instantiated, skipping",
1632 : __func__);
1633 0 : return;
1634 : }
1635 78 : if (!hc->redist_bgp_exterior_view) {
1636 78 : vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1637 : __func__);
1638 78 : return;
1639 : }
1640 0 : if (bgp != hc->redist_bgp_exterior_view) {
1641 0 : vnc_zlog_debug_verbose(
1642 : "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1643 : __func__, bgp, hc->redist_bgp_exterior_view);
1644 0 : return;
1645 : }
1646 :
1647 0 : if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
1648 0 : vnc_zlog_debug_verbose(
1649 : "%s: redist of exterior routes not enabled, skipping",
1650 : __func__);
1651 0 : return;
1652 : }
1653 :
1654 : /*
1655 : * Extract nexthop from exterior route
1656 : *
1657 : * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1658 : * but if v4 it is in attr->nexthop
1659 : */
1660 0 : rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_orig_nexthop);
1661 :
1662 0 : for (it = h->imports; it; it = it->next) {
1663 0 : struct agg_table *table;
1664 0 : struct agg_node *rn;
1665 0 : struct agg_node *par;
1666 0 : struct bgp_path_info *bpi_interior;
1667 0 : int have_usable_route;
1668 :
1669 0 : vnc_zlog_debug_verbose("%s: doing it %p", __func__, it);
1670 :
1671 0 : if (it_only && (it_only != it)) {
1672 0 : vnc_zlog_debug_verbose("%s: doesn't match it_only %p",
1673 : __func__, it_only);
1674 0 : continue;
1675 : }
1676 :
1677 0 : table = it->imported_vpn[afi];
1678 :
1679 0 : for (rn = agg_node_match(table, &pfx_orig_nexthop),
1680 0 : have_usable_route = 0;
1681 0 : (!have_usable_route) && rn;) {
1682 :
1683 0 : vnc_zlog_debug_verbose("%s: it %p trying rn %p",
1684 : __func__, it, rn);
1685 :
1686 0 : for (bpi_interior = rn->info; bpi_interior;
1687 0 : bpi_interior = bpi_interior->next) {
1688 0 : struct prefix_rd *prd;
1689 0 : struct attr new_attr;
1690 0 : uint32_t label = 0;
1691 :
1692 0 : if (!is_usable_interior_route(bpi_interior))
1693 0 : continue;
1694 :
1695 0 : vnc_zlog_debug_verbose(
1696 : "%s: usable: bpi_interior %p", __func__,
1697 : bpi_interior);
1698 :
1699 : /*
1700 : * have a legitimate route to exterior's nexthop
1701 : * via NVE.
1702 : *
1703 : * Import unicast route to the import table
1704 : */
1705 0 : have_usable_route = 1;
1706 :
1707 0 : if (bpi_interior->extra) {
1708 0 : prd = &bpi_interior->extra->vnc.import
1709 : .rd;
1710 0 : label = decode_label(
1711 : &bpi_interior->extra->label[0]);
1712 : } else
1713 : prd = NULL;
1714 :
1715 : /* use local_pref from unicast route */
1716 0 : memset(&new_attr, 0, sizeof(new_attr));
1717 0 : new_attr = *bpi_interior->attr;
1718 0 : if (info->attr->flag
1719 0 : & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
1720 0 : new_attr.local_pref =
1721 0 : info->attr->local_pref;
1722 0 : new_attr.flag |= ATTR_FLAG_BIT(
1723 : BGP_ATTR_LOCAL_PREF);
1724 : }
1725 :
1726 0 : rfapiBgpInfoFilteredImportVPN(
1727 : it, FIF_ACTION_UPDATE,
1728 : bpi_interior->peer, NULL, /* rfd */
1729 : prefix, NULL, afi, prd, &new_attr,
1730 : ZEBRA_ROUTE_BGP_DIRECT_EXT,
1731 : BGP_ROUTE_REDISTRIBUTE, &label);
1732 : }
1733 :
1734 0 : if (have_usable_route) {
1735 : /*
1736 : * Make monitor
1737 : *
1738 : * TBD factor this out into its own function
1739 : */
1740 0 : struct prefix *pfx_mon = prefix_new();
1741 0 : if (!RFAPI_MONITOR_EXTERIOR(rn)->source) {
1742 0 : RFAPI_MONITOR_EXTERIOR(rn)->source =
1743 0 : skiplist_new(
1744 : 0, NULL,
1745 : prefix_free_lists);
1746 0 : agg_lock_node(rn); /* for skiplist */
1747 : }
1748 0 : agg_lock_node(rn); /* for skiplist entry */
1749 0 : prefix_copy(pfx_mon, prefix);
1750 0 : if (!skiplist_insert(
1751 0 : RFAPI_MONITOR_EXTERIOR(rn)->source,
1752 : info, pfx_mon)) {
1753 :
1754 0 : bgp_path_info_lock(info);
1755 : }
1756 : }
1757 0 : par = agg_node_parent(rn);
1758 0 : if (par)
1759 0 : agg_lock_node(par);
1760 0 : agg_unlock_node(rn);
1761 0 : rn = par;
1762 : }
1763 0 : if (rn)
1764 0 : agg_unlock_node(rn);
1765 :
1766 0 : if (!have_usable_route) {
1767 0 : struct prefix *pfx_mon = prefix_new();
1768 0 : prefix_copy(pfx_mon, prefix);
1769 0 : if (!skiplist_insert(it->monitor_exterior_orphans, info,
1770 : pfx_mon)) {
1771 :
1772 0 : bgp_path_info_lock(info);
1773 : }
1774 : }
1775 : }
1776 : }
1777 :
1778 78 : void vnc_import_bgp_exterior_add_route(
1779 : struct bgp *bgp, /* exterior instance, we hope */
1780 : const struct prefix *prefix, /* unicast prefix */
1781 : struct bgp_path_info *info) /* unicast info */
1782 : {
1783 78 : vnc_import_bgp_exterior_add_route_it(bgp, prefix, info, NULL);
1784 0 : }
1785 :
1786 : /*
1787 : * There should be only one of these per prefix at a time.
1788 : * This should probably be called as a result of selection operation.
1789 : *
1790 : * NB should be called espacially for bgp instances that are named,
1791 : * because the exterior routes will always come from one of those.
1792 : * We filter here on the instance name to make sure we get only the
1793 : * right routes.
1794 : */
1795 5 : void vnc_import_bgp_exterior_del_route(
1796 : struct bgp *bgp, const struct prefix *prefix, /* unicast prefix */
1797 : struct bgp_path_info *info) /* unicast info */
1798 : {
1799 5 : struct rfapi *h;
1800 5 : struct rfapi_cfg *hc;
1801 5 : struct rfapi_import_table *it;
1802 5 : struct prefix pfx_orig_nexthop;
1803 5 : afi_t afi = family2afi(prefix->family);
1804 5 : struct bgp *bgp_default = bgp_get_default();
1805 :
1806 5 : if (!bgp_default)
1807 5 : return;
1808 :
1809 5 : memset(&pfx_orig_nexthop, 0,
1810 : sizeof(pfx_orig_nexthop)); /* keep valgrind happy */
1811 :
1812 5 : h = bgp_default->rfapi;
1813 5 : hc = bgp_default->rfapi_cfg;
1814 :
1815 5 : if (!h || !hc) {
1816 0 : vnc_zlog_debug_verbose(
1817 : "%s: rfapi or rfapi_cfg not instantiated, skipping",
1818 : __func__);
1819 0 : return;
1820 : }
1821 5 : if (!hc->redist_bgp_exterior_view) {
1822 5 : vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1823 : __func__);
1824 5 : return;
1825 : }
1826 0 : if (bgp != hc->redist_bgp_exterior_view) {
1827 0 : vnc_zlog_debug_verbose(
1828 : "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1829 : __func__, bgp, hc->redist_bgp_exterior_view);
1830 0 : return;
1831 : }
1832 0 : if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
1833 0 : vnc_zlog_debug_verbose(
1834 : "%s: redist of exterior routes no enabled, skipping",
1835 : __func__);
1836 0 : return;
1837 : }
1838 :
1839 : /*
1840 : * Extract nexthop from exterior route
1841 : *
1842 : * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1843 : * but if v4 it is in attr->nexthop
1844 : */
1845 0 : rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_orig_nexthop);
1846 :
1847 0 : for (it = h->imports; it; it = it->next) {
1848 0 : struct agg_table *table;
1849 0 : struct agg_node *rn;
1850 0 : struct agg_node *par;
1851 0 : struct bgp_path_info *bpi_interior;
1852 0 : int have_usable_route;
1853 :
1854 0 : table = it->imported_vpn[afi];
1855 :
1856 0 : for (rn = agg_node_match(table, &pfx_orig_nexthop),
1857 0 : have_usable_route = 0;
1858 0 : (!have_usable_route) && rn;) {
1859 :
1860 0 : for (bpi_interior = rn->info; bpi_interior;
1861 0 : bpi_interior = bpi_interior->next) {
1862 0 : struct prefix_rd *prd;
1863 0 : uint32_t label = 0;
1864 :
1865 0 : if (!is_usable_interior_route(bpi_interior))
1866 0 : continue;
1867 :
1868 : /*
1869 : * have a legitimate route to exterior's nexthop
1870 : * via NVE.
1871 : *
1872 : * Import unicast route to the import table
1873 : */
1874 0 : have_usable_route = 1;
1875 :
1876 0 : if (bpi_interior->extra) {
1877 0 : prd = &bpi_interior->extra->vnc.import
1878 : .rd;
1879 0 : label = decode_label(
1880 : &bpi_interior->extra->label[0]);
1881 : } else
1882 : prd = NULL;
1883 :
1884 0 : rfapiBgpInfoFilteredImportVPN(
1885 : it, FIF_ACTION_KILL, bpi_interior->peer,
1886 : NULL, /* rfd */
1887 : prefix, NULL, afi, prd,
1888 : bpi_interior->attr,
1889 : ZEBRA_ROUTE_BGP_DIRECT_EXT,
1890 : BGP_ROUTE_REDISTRIBUTE, &label);
1891 :
1892 : /*
1893 : * Delete monitor
1894 : *
1895 : * TBD factor this out into its own function
1896 : */
1897 : {
1898 0 : if (RFAPI_MONITOR_EXTERIOR(rn)
1899 0 : ->source) {
1900 0 : if (!skiplist_delete(
1901 0 : RFAPI_MONITOR_EXTERIOR(
1902 : rn)
1903 : ->source,
1904 : info, NULL)) {
1905 :
1906 0 : bgp_path_info_unlock(
1907 : info);
1908 0 : agg_unlock_node(
1909 : rn); /* sl entry
1910 : */
1911 : }
1912 0 : if (skiplist_empty(
1913 0 : RFAPI_MONITOR_EXTERIOR(
1914 : rn)
1915 : ->source)) {
1916 0 : skiplist_free(
1917 0 : RFAPI_MONITOR_EXTERIOR(
1918 : rn)
1919 : ->source);
1920 0 : RFAPI_MONITOR_EXTERIOR(
1921 : rn)
1922 0 : ->source = NULL;
1923 0 : agg_unlock_node(
1924 : rn); /* skiplist
1925 : itself
1926 : */
1927 : }
1928 : }
1929 : }
1930 : }
1931 0 : par = agg_node_parent(rn);
1932 0 : if (par)
1933 0 : agg_lock_node(par);
1934 0 : agg_unlock_node(rn);
1935 0 : rn = par;
1936 : }
1937 0 : if (rn)
1938 0 : agg_unlock_node(rn);
1939 :
1940 0 : if (!have_usable_route) {
1941 0 : if (!skiplist_delete(it->monitor_exterior_orphans, info,
1942 : NULL)) {
1943 :
1944 0 : bgp_path_info_unlock(info);
1945 : }
1946 : }
1947 : }
1948 : }
1949 :
1950 : /*
1951 : * This function should be called after a new interior VPN route
1952 : * has been added to an import_table.
1953 : *
1954 : * NB should also be called whenever an existing vpn interior route
1955 : * becomes valid (e.g., valid_interior_count is inremented)
1956 : */
1957 0 : void vnc_import_bgp_exterior_add_route_interior(
1958 : struct bgp *bgp, struct rfapi_import_table *it,
1959 : struct agg_node *rn_interior, /* VPN IT node */
1960 : struct bgp_path_info *bpi_interior) /* VPN IT route */
1961 : {
1962 0 : const struct prefix *p = agg_node_get_prefix(rn_interior);
1963 0 : afi_t afi = family2afi(p->family);
1964 0 : struct agg_node *par;
1965 0 : struct bgp_path_info *bpi_exterior;
1966 0 : struct prefix *pfx_exterior; /* exterior pfx */
1967 0 : void *cursor;
1968 0 : int rc;
1969 0 : struct list *list_adopted;
1970 :
1971 0 : vnc_zlog_debug_verbose("%s: entry", __func__);
1972 :
1973 0 : if (!is_usable_interior_route(bpi_interior)) {
1974 0 : vnc_zlog_debug_verbose(
1975 : "%s: not usable interior route, skipping", __func__);
1976 0 : return;
1977 : }
1978 :
1979 0 : if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
1980 0 : vnc_zlog_debug_verbose(
1981 : "%s: redist of exterior routes no enabled, skipping",
1982 : __func__);
1983 0 : return;
1984 : }
1985 :
1986 0 : if (it == bgp->rfapi->it_ce) {
1987 0 : vnc_zlog_debug_verbose("%s: import table is it_ce, skipping",
1988 : __func__);
1989 0 : return;
1990 : }
1991 :
1992 : /*debugging */
1993 0 : vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
1994 : __func__, rn_interior, bpi_interior->type);
1995 :
1996 0 : if (RFAPI_HAS_MONITOR_EXTERIOR(rn_interior)) {
1997 :
1998 0 : int count = 0; /* debugging */
1999 :
2000 0 : vnc_zlog_debug_verbose(
2001 : "%s: has exterior monitor; ext src: %p", __func__,
2002 : RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
2003 :
2004 : /*
2005 : * There is a monitor here already. Therefore, we do not need
2006 : * to do any pulldown. Just construct exterior routes based
2007 : * on the new interior route.
2008 : */
2009 0 : cursor = NULL;
2010 0 : for (rc = skiplist_next(
2011 0 : RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2012 : (void **)&bpi_exterior, (void **)&pfx_exterior,
2013 : &cursor);
2014 0 : !rc; rc = skiplist_next(
2015 0 : RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2016 : (void **)&bpi_exterior,
2017 : (void **)&pfx_exterior, &cursor)) {
2018 :
2019 0 : struct prefix_rd *prd;
2020 0 : struct attr new_attr;
2021 0 : uint32_t label = 0;
2022 :
2023 :
2024 0 : ++count; /* debugging */
2025 :
2026 0 : assert(bpi_exterior);
2027 0 : assert(pfx_exterior);
2028 :
2029 0 : if (bpi_interior->extra) {
2030 0 : prd = &bpi_interior->extra->vnc.import.rd;
2031 0 : label = decode_label(
2032 : &bpi_interior->extra->label[0]);
2033 : } else
2034 : prd = NULL;
2035 :
2036 : /* use local_pref from unicast route */
2037 0 : memset(&new_attr, 0, sizeof(struct attr));
2038 0 : new_attr = *bpi_interior->attr;
2039 0 : if (bpi_exterior
2040 0 : && (bpi_exterior->attr->flag
2041 0 : & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
2042 0 : new_attr.local_pref =
2043 0 : bpi_exterior->attr->local_pref;
2044 0 : new_attr.flag |=
2045 : ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2046 : }
2047 :
2048 0 : rfapiBgpInfoFilteredImportVPN(
2049 : it, FIF_ACTION_UPDATE, bpi_interior->peer,
2050 : NULL, /* rfd */
2051 : pfx_exterior, NULL, afi, prd, &new_attr,
2052 : ZEBRA_ROUTE_BGP_DIRECT_EXT,
2053 : BGP_ROUTE_REDISTRIBUTE, &label);
2054 : }
2055 0 : vnc_zlog_debug_verbose(
2056 : "%s: finished constructing exteriors based on existing monitors",
2057 : __func__);
2058 0 : return;
2059 : }
2060 :
2061 0 : vnc_zlog_debug_verbose("%s: no exterior monitor", __func__);
2062 :
2063 : /*
2064 : * No monitor at this node. Is this the first valid interior
2065 : * route at this node?
2066 : */
2067 0 : if (RFAPI_MONITOR_EXTERIOR(rn_interior)->valid_interior_count > 1) {
2068 0 : vnc_zlog_debug_verbose(
2069 : "%s: new interior route not first valid one, skipping pulldown",
2070 : __func__);
2071 0 : return;
2072 : }
2073 :
2074 : /*
2075 : * Look up the tree for possible pulldown candidates.
2076 : * Find nearest parent with an exterior route monitor
2077 : */
2078 0 : for (par = agg_node_parent(rn_interior); par;
2079 0 : par = agg_node_parent(par)) {
2080 0 : if (RFAPI_HAS_MONITOR_EXTERIOR(par))
2081 : break;
2082 : }
2083 :
2084 0 : if (par) {
2085 :
2086 0 : vnc_zlog_debug_verbose(
2087 : "%s: checking parent %p for possible pulldowns",
2088 : __func__, par);
2089 :
2090 : /* check monitors at par for possible pulldown */
2091 0 : cursor = NULL;
2092 0 : for (rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(par)->source,
2093 : (void **)&bpi_exterior,
2094 : (void **)&pfx_exterior, &cursor);
2095 0 : !rc;
2096 0 : rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(par)->source,
2097 : (void **)&bpi_exterior,
2098 : (void **)&pfx_exterior, &cursor)) {
2099 :
2100 0 : struct prefix pfx_nexthop;
2101 :
2102 0 : memset(&pfx_nexthop, 0,
2103 : sizeof(struct prefix)); /* keep valgrind happy */
2104 :
2105 : /* check original nexthop for prefix match */
2106 0 : rfapiUnicastNexthop2Prefix(afi, bpi_exterior->attr,
2107 : &pfx_nexthop);
2108 :
2109 0 : if (prefix_match(p, &pfx_nexthop)) {
2110 :
2111 0 : struct bgp_path_info *bpi;
2112 0 : struct prefix_rd *prd;
2113 0 : struct attr new_attr;
2114 0 : uint32_t label = 0;
2115 :
2116 : /* do pull-down */
2117 :
2118 : /*
2119 : * add monitor to longer prefix
2120 : */
2121 0 : struct prefix *pfx_mon = prefix_new();
2122 0 : prefix_copy(pfx_mon, pfx_exterior);
2123 0 : if (!RFAPI_MONITOR_EXTERIOR(rn_interior)
2124 0 : ->source) {
2125 0 : RFAPI_MONITOR_EXTERIOR(rn_interior)
2126 0 : ->source = skiplist_new(
2127 : 0, NULL, prefix_free_lists);
2128 0 : agg_lock_node(rn_interior);
2129 : }
2130 0 : skiplist_insert(
2131 0 : RFAPI_MONITOR_EXTERIOR(rn_interior)
2132 : ->source,
2133 : bpi_exterior, pfx_mon);
2134 0 : agg_lock_node(rn_interior);
2135 :
2136 : /*
2137 : * Delete constructed exterior routes based on
2138 : * parent routes.
2139 : */
2140 0 : for (bpi = par->info; bpi; bpi = bpi->next) {
2141 :
2142 0 : if (bpi->extra) {
2143 0 : prd = &bpi->extra->vnc.import
2144 : .rd;
2145 0 : label = decode_label(
2146 : &bpi->extra->label[0]);
2147 : } else
2148 : prd = NULL;
2149 :
2150 0 : rfapiBgpInfoFilteredImportVPN(
2151 : it, FIF_ACTION_KILL, bpi->peer,
2152 : NULL, /* rfd */
2153 : pfx_exterior, NULL, afi, prd,
2154 : bpi->attr,
2155 : ZEBRA_ROUTE_BGP_DIRECT_EXT,
2156 : BGP_ROUTE_REDISTRIBUTE, &label);
2157 : }
2158 :
2159 :
2160 : /*
2161 : * Add constructed exterior routes based on
2162 : * the new interior route at longer prefix.
2163 : */
2164 0 : if (bpi_interior->extra) {
2165 0 : prd = &bpi_interior->extra->vnc.import
2166 : .rd;
2167 0 : label = decode_label(
2168 : &bpi_interior->extra->label[0]);
2169 : } else
2170 : prd = NULL;
2171 :
2172 : /* use local_pref from unicast route */
2173 0 : memset(&new_attr, 0, sizeof(struct attr));
2174 0 : new_attr = *bpi_interior->attr;
2175 0 : if (bpi_exterior
2176 0 : && (bpi_exterior->attr->flag
2177 0 : & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
2178 0 : new_attr.local_pref =
2179 0 : bpi_exterior->attr->local_pref;
2180 0 : new_attr.flag |= ATTR_FLAG_BIT(
2181 : BGP_ATTR_LOCAL_PREF);
2182 : }
2183 :
2184 0 : rfapiBgpInfoFilteredImportVPN(
2185 : it, FIF_ACTION_UPDATE,
2186 : bpi_interior->peer, NULL, /* rfd */
2187 : pfx_exterior, NULL, afi, prd, &new_attr,
2188 : ZEBRA_ROUTE_BGP_DIRECT_EXT,
2189 : BGP_ROUTE_REDISTRIBUTE, &label);
2190 : }
2191 : }
2192 :
2193 : /*
2194 : * The only monitors at rn_interior are the ones we added just
2195 : * above, so we can use the rn_interior list to identify which
2196 : * monitors to delete from the parent.
2197 : */
2198 0 : cursor = NULL;
2199 0 : for (rc = skiplist_next(
2200 0 : RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2201 : (void **)&bpi_exterior, NULL, &cursor);
2202 0 : !rc; rc = skiplist_next(
2203 0 : RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2204 : (void **)&bpi_exterior, NULL, &cursor)) {
2205 :
2206 :
2207 0 : skiplist_delete(RFAPI_MONITOR_EXTERIOR(par)->source,
2208 : bpi_exterior, NULL);
2209 0 : agg_unlock_node(par); /* sl entry */
2210 : }
2211 0 : if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par)->source)) {
2212 0 : skiplist_free(RFAPI_MONITOR_EXTERIOR(par)->source);
2213 0 : RFAPI_MONITOR_EXTERIOR(par)->source = NULL;
2214 0 : agg_unlock_node(par); /* sl itself */
2215 : }
2216 : }
2217 :
2218 0 : vnc_zlog_debug_verbose("%s: checking orphans", __func__);
2219 :
2220 : /*
2221 : * See if any orphans can be pulled down to the current node
2222 : */
2223 0 : cursor = NULL;
2224 0 : list_adopted = NULL;
2225 0 : for (rc = skiplist_next(it->monitor_exterior_orphans,
2226 : (void **)&bpi_exterior, (void **)&pfx_exterior,
2227 : &cursor);
2228 0 : !rc; rc = skiplist_next(it->monitor_exterior_orphans,
2229 : (void **)&bpi_exterior,
2230 : (void **)&pfx_exterior, &cursor)) {
2231 :
2232 0 : struct prefix pfx_nexthop;
2233 0 : afi_t afi_exterior = family2afi(pfx_exterior->family);
2234 :
2235 0 : vnc_zlog_debug_verbose(
2236 : "%s: checking exterior orphan at prefix %pFX", __func__,
2237 : pfx_exterior);
2238 :
2239 0 : if (afi_exterior != afi) {
2240 0 : vnc_zlog_debug_verbose(
2241 : "%s: exterior orphan afi %d != interior afi %d, skip",
2242 : __func__, afi_exterior, afi);
2243 0 : continue;
2244 : }
2245 :
2246 : /* check original nexthop for prefix match */
2247 0 : rfapiUnicastNexthop2Prefix(afi, bpi_exterior->attr,
2248 : &pfx_nexthop);
2249 :
2250 0 : if (prefix_match(p, &pfx_nexthop)) {
2251 :
2252 0 : struct prefix_rd *prd;
2253 0 : struct attr new_attr;
2254 0 : uint32_t label = 0;
2255 :
2256 : /* do pull-down */
2257 :
2258 : /*
2259 : * add monitor to longer prefix
2260 : */
2261 :
2262 0 : struct prefix *pfx_mon = prefix_new();
2263 0 : prefix_copy(pfx_mon, pfx_exterior);
2264 0 : if (!RFAPI_MONITOR_EXTERIOR(rn_interior)->source) {
2265 0 : RFAPI_MONITOR_EXTERIOR(rn_interior)->source =
2266 0 : skiplist_new(
2267 : 0, NULL, prefix_free_lists);
2268 0 : agg_lock_node(rn_interior); /* sl */
2269 : }
2270 0 : skiplist_insert(
2271 0 : RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2272 : bpi_exterior, pfx_mon);
2273 0 : agg_lock_node(rn_interior); /* sl entry */
2274 0 : if (!list_adopted) {
2275 0 : list_adopted = list_new();
2276 : }
2277 0 : listnode_add(list_adopted, bpi_exterior);
2278 :
2279 : /*
2280 : * Add constructed exterior routes based on the
2281 : * new interior route at the longer prefix.
2282 : */
2283 0 : if (bpi_interior->extra) {
2284 0 : prd = &bpi_interior->extra->vnc.import.rd;
2285 0 : label = decode_label(
2286 : &bpi_interior->extra->label[0]);
2287 : } else
2288 : prd = NULL;
2289 :
2290 : /* use local_pref from unicast route */
2291 0 : memset(&new_attr, 0, sizeof(struct attr));
2292 0 : new_attr = *bpi_interior->attr;
2293 0 : if (bpi_exterior
2294 0 : && (bpi_exterior->attr->flag
2295 0 : & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
2296 0 : new_attr.local_pref =
2297 0 : bpi_exterior->attr->local_pref;
2298 0 : new_attr.flag |=
2299 : ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2300 : }
2301 :
2302 0 : rfapiBgpInfoFilteredImportVPN(
2303 : it, FIF_ACTION_UPDATE, bpi_interior->peer,
2304 : NULL, /* rfd */
2305 : pfx_exterior, NULL, afi, prd, &new_attr,
2306 : ZEBRA_ROUTE_BGP_DIRECT_EXT,
2307 : BGP_ROUTE_REDISTRIBUTE, &label);
2308 : }
2309 : }
2310 0 : if (list_adopted) {
2311 0 : struct listnode *node;
2312 0 : struct agg_node *an_bpi_exterior;
2313 :
2314 0 : for (ALL_LIST_ELEMENTS_RO(list_adopted, node,
2315 : an_bpi_exterior)) {
2316 0 : skiplist_delete(it->monitor_exterior_orphans,
2317 : an_bpi_exterior, NULL);
2318 : }
2319 0 : list_delete(&list_adopted);
2320 : }
2321 : }
2322 :
2323 : /*
2324 : * This function should be called after an interior VPN route
2325 : * has been deleted from an import_table.
2326 : * bpi_interior must still be valid, but it must already be detached
2327 : * from its route node and the route node's valid_interior_count
2328 : * must already be decremented.
2329 : *
2330 : * NB should also be called whenever an existing vpn interior route
2331 : * becomes invalid (e.g., valid_interior_count is decremented)
2332 : */
2333 0 : void vnc_import_bgp_exterior_del_route_interior(
2334 : struct bgp *bgp, struct rfapi_import_table *it,
2335 : struct agg_node *rn_interior, /* VPN IT node */
2336 : struct bgp_path_info *bpi_interior) /* VPN IT route */
2337 : {
2338 0 : const struct prefix *p = agg_node_get_prefix(rn_interior);
2339 0 : afi_t afi = family2afi(p->family);
2340 0 : struct agg_node *par;
2341 0 : struct bgp_path_info *bpi_exterior;
2342 0 : struct prefix *pfx_exterior; /* exterior pfx */
2343 0 : void *cursor;
2344 0 : int rc;
2345 :
2346 0 : if (!VALID_INTERIOR_TYPE(bpi_interior->type)) {
2347 0 : vnc_zlog_debug_verbose(
2348 : "%s: type %d not valid interior type, skipping",
2349 : __func__, bpi_interior->type);
2350 0 : return;
2351 : }
2352 :
2353 0 : if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
2354 0 : vnc_zlog_debug_verbose(
2355 : "%s: redist of exterior routes no enabled, skipping",
2356 : __func__);
2357 0 : return;
2358 : }
2359 :
2360 0 : if (it == bgp->rfapi->it_ce) {
2361 0 : vnc_zlog_debug_verbose("%s: it is it_ce, skipping", __func__);
2362 0 : return;
2363 : }
2364 :
2365 : /* If no exterior routes depend on this prefix, nothing to do */
2366 0 : if (!RFAPI_HAS_MONITOR_EXTERIOR(rn_interior)) {
2367 0 : vnc_zlog_debug_verbose("%s: no exterior monitor, skipping",
2368 : __func__);
2369 0 : return;
2370 : }
2371 :
2372 : /*debugging */
2373 0 : vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
2374 : __func__, rn_interior, bpi_interior->type);
2375 :
2376 : /*
2377 : * Remove constructed routes based on the deleted interior route
2378 : */
2379 0 : cursor = NULL;
2380 0 : for (rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2381 : (void **)&bpi_exterior, (void **)&pfx_exterior,
2382 : &cursor);
2383 0 : !rc;
2384 0 : rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2385 : (void **)&bpi_exterior, (void **)&pfx_exterior,
2386 : &cursor)) {
2387 :
2388 0 : struct prefix_rd *prd;
2389 0 : uint32_t label = 0;
2390 :
2391 0 : if (bpi_interior->extra) {
2392 0 : prd = &bpi_interior->extra->vnc.import.rd;
2393 0 : label = decode_label(&bpi_interior->extra->label[0]);
2394 : } else
2395 : prd = NULL;
2396 :
2397 0 : rfapiBgpInfoFilteredImportVPN(
2398 : it, FIF_ACTION_KILL, bpi_interior->peer, NULL, /* rfd */
2399 : pfx_exterior, NULL, afi, prd, bpi_interior->attr,
2400 : ZEBRA_ROUTE_BGP_DIRECT_EXT, BGP_ROUTE_REDISTRIBUTE,
2401 : &label);
2402 : }
2403 :
2404 : /*
2405 : * If there are no remaining valid interior routes at this prefix,
2406 : * we need to look up the tree for a possible node to move monitors to
2407 : */
2408 0 : if (RFAPI_MONITOR_EXTERIOR(rn_interior)->valid_interior_count) {
2409 0 : vnc_zlog_debug_verbose(
2410 : "%s: interior routes still present, skipping",
2411 : __func__);
2412 0 : return;
2413 : }
2414 :
2415 : /*
2416 : * Find nearest parent with at least one valid interior route
2417 : * If none is found, par will end up NULL, and we will move
2418 : * the monitors to the orphan list for this import table
2419 : */
2420 0 : for (par = agg_node_parent(rn_interior); par;
2421 0 : par = agg_node_parent(par)) {
2422 0 : if (RFAPI_MONITOR_EXTERIOR(par)->valid_interior_count)
2423 : break;
2424 : }
2425 :
2426 0 : vnc_zlog_debug_verbose("%s: par=%p, ext src: %p", __func__, par,
2427 : RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
2428 :
2429 : /* move all monitors */
2430 : /*
2431 : * We will use and delete every element of the source skiplist
2432 : */
2433 0 : while (!skiplist_first(RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2434 : (void **)&bpi_exterior,
2435 : (void **)&pfx_exterior)) {
2436 :
2437 0 : struct prefix *pfx_mon = prefix_new();
2438 :
2439 0 : prefix_copy(pfx_mon, pfx_exterior);
2440 :
2441 0 : if (par) {
2442 :
2443 0 : struct bgp_path_info *bpi;
2444 :
2445 : /*
2446 : * Add monitor to parent node
2447 : */
2448 0 : if (!RFAPI_MONITOR_EXTERIOR(par)->source) {
2449 0 : RFAPI_MONITOR_EXTERIOR(par)->source =
2450 0 : skiplist_new(
2451 : 0, NULL, prefix_free_lists);
2452 0 : agg_lock_node(par); /* sl */
2453 : }
2454 0 : skiplist_insert(RFAPI_MONITOR_EXTERIOR(par)->source,
2455 : bpi_exterior, pfx_mon);
2456 0 : agg_lock_node(par); /* sl entry */
2457 :
2458 : /* Add constructed exterior routes based on parent */
2459 0 : for (bpi = par->info; bpi; bpi = bpi->next) {
2460 :
2461 0 : struct prefix_rd *prd;
2462 0 : struct attr new_attr;
2463 0 : uint32_t label = 0;
2464 :
2465 0 : if (bpi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT)
2466 0 : continue;
2467 :
2468 0 : if (bpi->extra) {
2469 0 : prd = &bpi->extra->vnc.import.rd;
2470 0 : label = decode_label(
2471 : &bpi->extra->label[0]);
2472 : } else
2473 : prd = NULL;
2474 :
2475 : /* use local_pref from unicast route */
2476 0 : memset(&new_attr, 0, sizeof(new_attr));
2477 0 : new_attr = *bpi->attr;
2478 0 : if (bpi_exterior
2479 0 : && (bpi_exterior->attr->flag
2480 0 : & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
2481 0 : new_attr.local_pref =
2482 0 : bpi_exterior->attr->local_pref;
2483 0 : new_attr.flag |= ATTR_FLAG_BIT(
2484 : BGP_ATTR_LOCAL_PREF);
2485 : }
2486 :
2487 0 : rfapiBgpInfoFilteredImportVPN(
2488 : it, FIF_ACTION_UPDATE, bpi->peer,
2489 : NULL, /* rfd */
2490 : pfx_exterior, NULL, afi, prd, &new_attr,
2491 : ZEBRA_ROUTE_BGP_DIRECT_EXT,
2492 : BGP_ROUTE_REDISTRIBUTE, &label);
2493 : }
2494 :
2495 : } else {
2496 :
2497 : /*
2498 : * No interior route for exterior's nexthop. Save
2499 : * monitor
2500 : * in orphan list to await future route.
2501 : */
2502 0 : skiplist_insert(it->monitor_exterior_orphans,
2503 : bpi_exterior, pfx_mon);
2504 : }
2505 :
2506 0 : skiplist_delete_first(
2507 0 : RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
2508 0 : agg_unlock_node(rn_interior); /* sl entry */
2509 : }
2510 0 : if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(rn_interior)->source)) {
2511 0 : skiplist_free(RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
2512 0 : RFAPI_MONITOR_EXTERIOR(rn_interior)->source = NULL;
2513 0 : agg_unlock_node(rn_interior); /* sl itself */
2514 : }
2515 : }
2516 :
2517 : /***********************************************************************
2518 : * Generic add/delete unicast routes
2519 : ***********************************************************************/
2520 :
2521 78 : void vnc_import_bgp_add_route(struct bgp *bgp, const struct prefix *prefix,
2522 : struct bgp_path_info *info)
2523 : {
2524 78 : afi_t afi = family2afi(prefix->family);
2525 :
2526 78 : if (VNC_DEBUG(VERBOSE)) {
2527 0 : struct prefix pfx_nexthop;
2528 :
2529 0 : rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_nexthop);
2530 0 : vnc_zlog_debug_verbose("%s: pfx %pFX, nh %pFX", __func__,
2531 : prefix, &pfx_nexthop);
2532 : }
2533 : #if DEBUG_RHN_LIST
2534 : print_rhn_list(__func__, "ENTER ");
2535 : #endif
2536 78 : VNC_RHNCK(enter);
2537 :
2538 78 : if (!afi) {
2539 0 : flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of prefix",
2540 : __func__);
2541 0 : return;
2542 : }
2543 :
2544 78 : if (!bgp->rfapi_cfg) {
2545 0 : vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2546 : __func__);
2547 0 : return;
2548 : }
2549 :
2550 : /* check vnc redist flag for bgp direct routes */
2551 78 : if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
2552 78 : vnc_zlog_debug_verbose(
2553 : "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
2554 : __func__, afi, ZEBRA_ROUTE_BGP_DIRECT);
2555 78 : return;
2556 : }
2557 :
2558 0 : switch (bgp->rfapi_cfg->redist_mode) {
2559 0 : case VNC_REDIST_MODE_PLAIN:
2560 0 : vnc_import_bgp_add_route_mode_plain(bgp, prefix, info);
2561 0 : break;
2562 :
2563 0 : case VNC_REDIST_MODE_RFG:
2564 0 : if (bgp->rfapi_cfg->rfg_redist)
2565 0 : vnc_import_bgp_add_route_mode_nvegroup(
2566 : bgp, prefix, info, bgp->rfapi_cfg->rfg_redist);
2567 : else
2568 0 : vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2569 : __func__);
2570 : break;
2571 :
2572 0 : case VNC_REDIST_MODE_RESOLVE_NVE:
2573 0 : vnc_import_bgp_add_route_mode_resolve_nve(bgp, prefix, info);
2574 0 : break;
2575 : }
2576 : #if DEBUG_RHN_LIST
2577 : print_rhn_list(__func__, "LEAVE ");
2578 : #endif
2579 0 : VNC_RHNCK(leave);
2580 : }
2581 :
2582 : /*
2583 : * "Withdrawing a Route" import process
2584 : */
2585 5 : void vnc_import_bgp_del_route(struct bgp *bgp, const struct prefix *prefix,
2586 : struct bgp_path_info *info) /* unicast info */
2587 : {
2588 5 : afi_t afi = family2afi(prefix->family);
2589 :
2590 5 : assert(afi);
2591 :
2592 : {
2593 5 : struct prefix pfx_nexthop;
2594 :
2595 5 : rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_nexthop);
2596 5 : vnc_zlog_debug_verbose("%s: pfx %pFX, nh %pFX", __func__,
2597 : prefix, &pfx_nexthop);
2598 : }
2599 : #if DEBUG_RHN_LIST
2600 : print_rhn_list(__func__, "ENTER ");
2601 : #endif
2602 5 : VNC_RHNCK(enter);
2603 :
2604 5 : if (!bgp->rfapi_cfg) {
2605 0 : vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2606 : __func__);
2607 0 : return;
2608 : }
2609 :
2610 : /* check bgp redist flag for vnc direct ("vpn") routes */
2611 5 : if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
2612 5 : vnc_zlog_debug_verbose(
2613 : "%s: bgp redistribution of afi=%d VNC direct routes is off",
2614 : __func__, afi);
2615 5 : return;
2616 : }
2617 :
2618 0 : switch (bgp->rfapi_cfg->redist_mode) {
2619 0 : case VNC_REDIST_MODE_PLAIN:
2620 0 : vnc_import_bgp_del_route_mode_plain(bgp, prefix, info);
2621 0 : break;
2622 :
2623 0 : case VNC_REDIST_MODE_RFG:
2624 0 : if (bgp->rfapi_cfg->rfg_redist)
2625 0 : vnc_import_bgp_del_route_mode_nvegroup(bgp, prefix,
2626 : info);
2627 : else
2628 0 : vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2629 : __func__);
2630 : break;
2631 :
2632 0 : case VNC_REDIST_MODE_RESOLVE_NVE:
2633 0 : vnc_import_bgp_del_route_mode_resolve_nve(bgp, afi, prefix,
2634 : info);
2635 0 : break;
2636 : }
2637 : #if DEBUG_RHN_LIST
2638 : print_rhn_list(__func__, "LEAVE ");
2639 : #endif
2640 0 : VNC_RHNCK(leave);
2641 : }
2642 :
2643 :
2644 : /***********************************************************************
2645 : * Enable/Disable
2646 : ***********************************************************************/
2647 :
2648 0 : void vnc_import_bgp_redist_enable(struct bgp *bgp, afi_t afi)
2649 : {
2650 : /* iterate over bgp unicast v4 and v6 routes, call
2651 : * vnc_import_bgp_add_route */
2652 :
2653 0 : struct bgp_dest *dest;
2654 :
2655 0 : vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
2656 :
2657 0 : if (bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
2658 0 : vnc_zlog_debug_verbose(
2659 : "%s: already enabled for afi %d, skipping", __func__,
2660 : afi);
2661 0 : return;
2662 : }
2663 0 : bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT] = 1;
2664 :
2665 0 : for (dest = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); dest;
2666 0 : dest = bgp_route_next(dest)) {
2667 :
2668 0 : struct bgp_path_info *bpi;
2669 :
2670 0 : for (bpi = bgp_dest_get_bgp_path_info(dest); bpi;
2671 0 : bpi = bpi->next) {
2672 :
2673 0 : if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
2674 0 : continue;
2675 :
2676 0 : vnc_import_bgp_add_route(bgp, bgp_dest_get_prefix(dest),
2677 : bpi);
2678 : }
2679 : }
2680 0 : vnc_zlog_debug_verbose(
2681 : "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2682 : __func__, afi, ZEBRA_ROUTE_BGP_DIRECT);
2683 : }
2684 :
2685 0 : void vnc_import_bgp_exterior_redist_enable(struct bgp *bgp, afi_t afi)
2686 : {
2687 0 : struct bgp *bgp_exterior;
2688 0 : struct bgp_dest *dest;
2689 :
2690 0 : bgp_exterior = bgp->rfapi_cfg->redist_bgp_exterior_view;
2691 :
2692 0 : if (bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
2693 0 : vnc_zlog_debug_verbose(
2694 : "%s: already enabled for afi %d, skipping", __func__,
2695 : afi);
2696 0 : return;
2697 : }
2698 0 : bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT] = 1;
2699 :
2700 0 : if (!bgp_exterior) {
2701 0 : vnc_zlog_debug_verbose(
2702 : "%s: no exterior view set yet, no routes to import yet",
2703 : __func__);
2704 0 : return;
2705 : }
2706 :
2707 0 : for (dest = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]); dest;
2708 0 : dest = bgp_route_next(dest)) {
2709 :
2710 0 : struct bgp_path_info *bpi;
2711 :
2712 0 : for (bpi = bgp_dest_get_bgp_path_info(dest); bpi;
2713 0 : bpi = bpi->next) {
2714 :
2715 0 : if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
2716 0 : continue;
2717 :
2718 0 : vnc_import_bgp_exterior_add_route(
2719 : bgp_exterior, bgp_dest_get_prefix(dest), bpi);
2720 : }
2721 : }
2722 0 : vnc_zlog_debug_verbose(
2723 : "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2724 : __func__, afi, ZEBRA_ROUTE_BGP_DIRECT);
2725 : }
2726 :
2727 : /*
2728 : * This function is for populating a newly-created Import Table
2729 : */
2730 0 : void vnc_import_bgp_exterior_redist_enable_it(
2731 : struct bgp *bgp, afi_t afi, struct rfapi_import_table *it_only)
2732 : {
2733 0 : struct bgp *bgp_exterior;
2734 0 : struct bgp_dest *dest;
2735 :
2736 0 : vnc_zlog_debug_verbose("%s: entry", __func__);
2737 :
2738 0 : bgp_exterior = bgp->rfapi_cfg->redist_bgp_exterior_view;
2739 :
2740 0 : if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
2741 0 : vnc_zlog_debug_verbose("%s: not enabled for afi %d, skipping",
2742 : __func__, afi);
2743 0 : return;
2744 : }
2745 :
2746 0 : if (!bgp_exterior) {
2747 0 : vnc_zlog_debug_verbose(
2748 : "%s: no exterior view set yet, no routes to import yet",
2749 : __func__);
2750 0 : return;
2751 : }
2752 :
2753 0 : for (dest = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]); dest;
2754 0 : dest = bgp_route_next(dest)) {
2755 :
2756 0 : struct bgp_path_info *bpi;
2757 :
2758 0 : for (bpi = bgp_dest_get_bgp_path_info(dest); bpi;
2759 0 : bpi = bpi->next) {
2760 :
2761 0 : if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
2762 0 : continue;
2763 :
2764 0 : vnc_import_bgp_exterior_add_route_it(
2765 : bgp_exterior, bgp_dest_get_prefix(dest), bpi,
2766 : it_only);
2767 : }
2768 : }
2769 : }
2770 :
2771 :
2772 0 : void vnc_import_bgp_redist_disable(struct bgp *bgp, afi_t afi)
2773 : {
2774 : /*
2775 : * iterate over vpn routes, find routes of type ZEBRA_ROUTE_BGP_DIRECT,
2776 : * delete (call timer expire immediately)
2777 : */
2778 0 : struct bgp_dest *dest1;
2779 0 : struct bgp_dest *dest2;
2780 :
2781 0 : vnc_zlog_debug_verbose("%s: entry", __func__);
2782 :
2783 0 : if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
2784 0 : vnc_zlog_debug_verbose(
2785 : "%s: already disabled for afi %d, skipping", __func__,
2786 : afi);
2787 0 : return;
2788 : }
2789 :
2790 : /*
2791 : * Two-level table for SAFI_MPLS_VPN
2792 : * Be careful when changing the things we iterate over
2793 : */
2794 0 : for (dest1 = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); dest1;
2795 0 : dest1 = bgp_route_next(dest1)) {
2796 0 : const struct prefix *dest1_p;
2797 :
2798 0 : if (!bgp_dest_has_bgp_path_info_data(dest1))
2799 0 : continue;
2800 :
2801 0 : dest1_p = bgp_dest_get_prefix(dest1);
2802 0 : for (dest2 = bgp_table_top(bgp_dest_get_bgp_table_info(dest1));
2803 0 : dest2; dest2 = bgp_route_next(dest2)) {
2804 0 : const struct prefix *dest2_p =
2805 0 : bgp_dest_get_prefix(dest2);
2806 0 : struct bgp_path_info *bpi;
2807 0 : struct bgp_path_info *nextbpi;
2808 :
2809 0 : for (bpi = bgp_dest_get_bgp_path_info(dest2); bpi;
2810 : bpi = nextbpi) {
2811 :
2812 0 : nextbpi = bpi->next;
2813 :
2814 0 : if (bpi->type != ZEBRA_ROUTE_BGP_DIRECT)
2815 0 : continue;
2816 :
2817 0 : struct rfapi_descriptor *rfd;
2818 0 : vncHDBgpDirect.peer = bpi->peer;
2819 :
2820 0 : assert(bpi->extra);
2821 :
2822 0 : rfd = bpi->extra->vnc.export.rfapi_handle;
2823 :
2824 0 : vnc_zlog_debug_verbose(
2825 : "%s: deleting bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]",
2826 : __func__, bpi, bpi->peer, bpi->type,
2827 : bpi->sub_type,
2828 : (bpi->extra ? bpi->extra->vnc.export
2829 : .rfapi_handle
2830 : : NULL),
2831 : rfd);
2832 :
2833 0 : del_vnc_route(rfd, bpi->peer, bgp,
2834 : SAFI_MPLS_VPN, dest2_p,
2835 : (struct prefix_rd *)dest1_p,
2836 0 : bpi->type, bpi->sub_type, NULL,
2837 : 1); /* kill */
2838 :
2839 0 : vncHDBgpDirect.peer = NULL;
2840 : }
2841 : }
2842 : }
2843 : /* Clear RHN list */
2844 0 : if (bgp->rfapi->resolve_nve_nexthop) {
2845 : struct prefix_bag *pb;
2846 : struct bgp_path_info *info;
2847 0 : while (!skiplist_first(bgp->rfapi->resolve_nve_nexthop, NULL,
2848 : (void *)&pb)) {
2849 0 : info = pb->ubpi;
2850 0 : skiplist_delete_first(bgp->rfapi->resolve_nve_nexthop);
2851 0 : bgp_path_info_unlock(info);
2852 : }
2853 : }
2854 :
2855 0 : bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT] = 0;
2856 0 : vnc_zlog_debug_verbose("%s: return", __func__);
2857 : }
2858 :
2859 :
2860 0 : void vnc_import_bgp_exterior_redist_disable(struct bgp *bgp, afi_t afi)
2861 : {
2862 0 : struct rfapi_cfg *hc = bgp->rfapi_cfg;
2863 0 : struct bgp *bgp_exterior = hc->redist_bgp_exterior_view;
2864 :
2865 0 : vnc_zlog_debug_verbose("%s: entry", __func__);
2866 :
2867 0 : if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
2868 0 : vnc_zlog_debug_verbose(
2869 : "%s: already disabled for afi %d, skipping", __func__,
2870 : afi);
2871 0 : return;
2872 : }
2873 :
2874 0 : if (!bgp_exterior) {
2875 0 : vnc_zlog_debug_verbose(
2876 : "%s: bgp exterior view not defined, skipping",
2877 : __func__);
2878 0 : return;
2879 : }
2880 :
2881 :
2882 : {
2883 0 : struct bgp_dest *dest;
2884 0 : for (dest = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]);
2885 0 : dest; dest = bgp_route_next(dest)) {
2886 :
2887 0 : struct bgp_path_info *bpi;
2888 :
2889 0 : for (bpi = bgp_dest_get_bgp_path_info(dest); bpi;
2890 0 : bpi = bpi->next) {
2891 :
2892 0 : if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
2893 0 : continue;
2894 :
2895 0 : vnc_import_bgp_exterior_del_route(
2896 : bgp_exterior, bgp_dest_get_prefix(dest),
2897 : bpi);
2898 : }
2899 : }
2900 : #if DEBUG_RHN_LIST
2901 : print_rhn_list(__func__, NULL);
2902 : #endif
2903 : }
2904 :
2905 0 : bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT] = 0;
2906 0 : vnc_zlog_debug_verbose("%s: return", __func__);
2907 : }
|