]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/rfapi/rfapi.c
Merge pull request #12751 from Pdoijode/pdoijode/ospf-vrf-neighbor-detail-1
[mirror_frr.git] / bgpd / rfapi / rfapi.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 *
4 * Copyright 2009-2016, LabN Consulting, L.L.C.
5 *
6 */
7
8 #include "lib/zebra.h"
9 #include "lib/prefix.h"
10 #include "lib/agg_table.h"
11 #include "lib/vty.h"
12 #include "lib/memory.h"
13 #include "lib/routemap.h"
14 #include "lib/log.h"
15 #include "lib/linklist.h"
16 #include "lib/command.h"
17 #include "lib/stream.h"
18 #include "lib/ringbuf.h"
19 #include "lib/lib_errors.h"
20
21 #include "bgpd/bgpd.h"
22 #include "bgpd/bgp_ecommunity.h"
23 #include "bgpd/bgp_attr.h"
24
25 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
26 #include "bgpd/rfapi/rfapi.h"
27 #include "bgpd/rfapi/rfapi_backend.h"
28
29 #include "bgpd/bgp_route.h"
30 #include "bgpd/bgp_mplsvpn.h"
31 #include "bgpd/bgp_aspath.h"
32 #include "bgpd/bgp_advertise.h"
33 #include "bgpd/bgp_vnc_types.h"
34 #include "bgpd/bgp_zebra.h"
35
36 #include "bgpd/rfapi/rfapi_import.h"
37 #include "bgpd/rfapi/rfapi_private.h"
38 #include "bgpd/rfapi/rfapi_monitor.h"
39 #include "bgpd/rfapi/rfapi_vty.h"
40 #include "bgpd/rfapi/vnc_export_bgp.h"
41 #include "bgpd/rfapi/vnc_export_bgp_p.h"
42 #include "bgpd/rfapi/vnc_zebra.h"
43 #include "bgpd/rfapi/vnc_import_bgp.h"
44 #include "bgpd/rfapi/rfapi_rib.h"
45 #include "bgpd/rfapi/rfapi_ap.h"
46 #include "bgpd/rfapi/rfapi_encap_tlv.h"
47 #include "bgpd/rfapi/vnc_debug.h"
48
49 #ifdef HAVE_GLIBC_BACKTRACE
50 /* for backtrace and friends */
51 #include <execinfo.h>
52 #endif /* HAVE_GLIBC_BACKTRACE */
53
54 struct ethaddr rfapi_ethaddr0 = {{0}};
55
56 #define DEBUG_RFAPI_STR "RF API debugging/testing command\n"
57
58 const char *rfapi_error_str(int code)
59 {
60 switch (code) {
61 case 0:
62 return "Success";
63 case ENXIO:
64 return "BGP or VNC not configured";
65 case ENOENT:
66 return "No match";
67 case EEXIST:
68 return "Handle already open";
69 case ENOMSG:
70 return "Incomplete configuration";
71 case EAFNOSUPPORT:
72 return "Invalid address family";
73 case EDEADLK:
74 return "Called from within a callback procedure";
75 case EBADF:
76 return "Invalid handle";
77 case EINVAL:
78 return "Invalid argument";
79 case ESTALE:
80 return "Stale descriptor";
81 default:
82 return "Unknown error";
83 }
84 }
85
86 /*------------------------------------------
87 * rfapi_get_response_lifetime_default
88 *
89 * Returns the default lifetime for a response.
90 * rfp_start_val value returned by rfp_start or
91 * NULL (=use default instance)
92 *
93 * input:
94 * None
95 *
96 * output:
97 *
98 * return value: The bgp instance default lifetime for a response.
99 --------------------------------------------*/
100 int rfapi_get_response_lifetime_default(void *rfp_start_val)
101 {
102 struct bgp *bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
103 if (bgp)
104 return bgp->rfapi_cfg->default_response_lifetime;
105 return BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT;
106 }
107
108 /*------------------------------------------
109 * rfapi_is_vnc_configured
110 *
111 * Returns if VNC is configured
112 *
113 * input:
114 * rfp_start_val value returned by rfp_start or
115 * NULL (=use default instance)
116 *
117 * output:
118 *
119 * return value: If VNC is configured for the bgpd instance
120 * 0 Success
121 * ENXIO VNC not configured
122 --------------------------------------------*/
123 int rfapi_is_vnc_configured(void *rfp_start_val)
124 {
125 struct bgp *bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
126 if (bgp_rfapi_is_vnc_configured(bgp) == 0)
127 return 0;
128 return ENXIO;
129 }
130
131
132 /*------------------------------------------
133 * rfapi_get_vn_addr
134 *
135 * Get the virtual network address used by an NVE based on it's RFD
136 *
137 * input:
138 * rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
139 *
140 * output:
141 *
142 * return value:
143 * vn NVE virtual network address
144 *------------------------------------------*/
145 struct rfapi_ip_addr *rfapi_get_vn_addr(void *rfd)
146 {
147 struct rfapi_descriptor *rrfd = (struct rfapi_descriptor *)rfd;
148 return &rrfd->vn_addr;
149 }
150
151 /*------------------------------------------
152 * rfapi_get_un_addr
153 *
154 * Get the underlay network address used by an NVE based on it's RFD
155 *
156 * input:
157 * rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
158 *
159 * output:
160 *
161 * return value:
162 * un NVE underlay network address
163 *------------------------------------------*/
164 struct rfapi_ip_addr *rfapi_get_un_addr(void *rfd)
165 {
166 struct rfapi_descriptor *rrfd = (struct rfapi_descriptor *)rfd;
167 return &rrfd->un_addr;
168 }
169
170 int rfapi_ip_addr_cmp(struct rfapi_ip_addr *a1, struct rfapi_ip_addr *a2)
171 {
172 if (a1->addr_family != a2->addr_family)
173 return a1->addr_family - a2->addr_family;
174
175 if (a1->addr_family == AF_INET) {
176 return IPV4_ADDR_CMP(&a1->addr.v4, &a2->addr.v4);
177 }
178
179 if (a1->addr_family == AF_INET6) {
180 return IPV6_ADDR_CMP(&a1->addr.v6, &a2->addr.v6);
181 }
182
183 assert(1);
184 /* NOTREACHED */
185 return 1;
186 }
187
188 static int rfapi_find_node(struct bgp *bgp, struct rfapi_ip_addr *vn_addr,
189 struct rfapi_ip_addr *un_addr,
190 struct agg_node **node)
191 {
192 struct rfapi *h;
193 struct prefix p;
194 struct agg_node *rn;
195 int rc;
196 afi_t afi;
197
198 if (!bgp) {
199 return ENXIO;
200 }
201
202 h = bgp->rfapi;
203 if (!h) {
204 return ENXIO;
205 }
206
207 afi = family2afi(un_addr->addr_family);
208 if (!afi) {
209 return EAFNOSUPPORT;
210 }
211
212 if ((rc = rfapiRaddr2Qprefix(un_addr, &p)))
213 return rc;
214
215 rn = agg_node_lookup(h->un[afi], &p);
216
217 if (!rn)
218 return ENOENT;
219
220 agg_unlock_node(rn);
221
222 *node = rn;
223
224 return 0;
225 }
226
227
228 int rfapi_find_rfd(struct bgp *bgp, struct rfapi_ip_addr *vn_addr,
229 struct rfapi_ip_addr *un_addr, struct rfapi_descriptor **rfd)
230 {
231 struct agg_node *rn;
232 int rc;
233
234 rc = rfapi_find_node(bgp, vn_addr, un_addr, &rn);
235
236 if (rc)
237 return rc;
238
239 for (*rfd = (struct rfapi_descriptor *)(rn->info); *rfd;
240 *rfd = (*rfd)->next) {
241 if (!rfapi_ip_addr_cmp(&(*rfd)->vn_addr, vn_addr))
242 break;
243 }
244
245 if (!*rfd)
246 return ENOENT;
247
248 return 0;
249 }
250
251 /*------------------------------------------
252 * rfapi_find_handle
253 *
254 * input:
255 * un underlay network address
256 * vn virtual network address
257 *
258 * output:
259 * pHandle pointer to location to store handle
260 *
261 * return value:
262 * 0 Success
263 * ENOENT no matching handle
264 * ENXIO BGP or VNC not configured
265 *------------------------------------------*/
266 static int rfapi_find_handle(struct bgp *bgp, struct rfapi_ip_addr *vn_addr,
267 struct rfapi_ip_addr *un_addr,
268 rfapi_handle *handle)
269 {
270 struct rfapi_descriptor **rfd;
271
272 rfd = (struct rfapi_descriptor **)handle;
273
274 return rfapi_find_rfd(bgp, vn_addr, un_addr, rfd);
275 }
276
277 static int rfapi_find_handle_vty(struct vty *vty, struct rfapi_ip_addr *vn_addr,
278 struct rfapi_ip_addr *un_addr,
279 rfapi_handle *handle)
280 {
281 struct bgp *bgp;
282 struct rfapi_descriptor **rfd;
283
284 bgp = bgp_get_default(); /* assume 1 instance for now */
285
286 rfd = (struct rfapi_descriptor **)handle;
287
288 return rfapi_find_rfd(bgp, vn_addr, un_addr, rfd);
289 }
290
291 static int is_valid_rfd(struct rfapi_descriptor *rfd)
292 {
293 rfapi_handle hh;
294
295 if (!rfd || rfd->bgp == NULL)
296 return 0;
297
298 if (CHECK_FLAG(
299 rfd->flags,
300 RFAPI_HD_FLAG_IS_VRF)) /* assume VRF/internal are valid */
301 return 1;
302
303 if (rfapi_find_handle(rfd->bgp, &rfd->vn_addr, &rfd->un_addr, &hh))
304 return 0;
305
306 if (rfd != hh)
307 return 0;
308
309 return 1;
310 }
311
312 /*
313 * check status of descriptor
314 */
315 int rfapi_check(void *handle)
316 {
317 struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
318 rfapi_handle hh;
319 int rc;
320
321 if (!rfd || rfd->bgp == NULL)
322 return EINVAL;
323
324 if (CHECK_FLAG(
325 rfd->flags,
326 RFAPI_HD_FLAG_IS_VRF)) /* assume VRF/internal are valid */
327 return 0;
328
329 if ((rc = rfapi_find_handle(rfd->bgp, &rfd->vn_addr, &rfd->un_addr,
330 &hh)))
331 return rc;
332
333 if (rfd != hh)
334 return ENOENT;
335
336 if (!rfd->rfg)
337 return ESTALE;
338
339 return 0;
340 }
341
342
343 void del_vnc_route(struct rfapi_descriptor *rfd,
344 struct peer *peer, /* rfd->peer for RFP regs */
345 struct bgp *bgp, safi_t safi, const struct prefix *p,
346 struct prefix_rd *prd, uint8_t type, uint8_t sub_type,
347 struct rfapi_nexthop *lnh, int kill)
348 {
349 afi_t afi; /* of the VN address */
350 struct bgp_dest *bn;
351 struct bgp_path_info *bpi;
352 struct prefix_rd prd0;
353
354 afi = family2afi(p->family);
355 assert(afi == AFI_IP || afi == AFI_IP6);
356
357 if (safi == SAFI_ENCAP) {
358 memset(&prd0, 0, sizeof(prd0));
359 prd0.family = AF_UNSPEC;
360 prd0.prefixlen = 64;
361 prd = &prd0;
362 }
363 bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
364
365 vnc_zlog_debug_verbose(
366 "%s: peer=%p, prefix=%pFX, prd=%pRDP afi=%d, safi=%d bn=%p, bn->info=%p",
367 __func__, peer, p, prd, afi, safi, bn,
368 (bn ? bgp_dest_get_bgp_path_info(bn) : NULL));
369
370 for (bpi = (bn ? bgp_dest_get_bgp_path_info(bn) : NULL); bpi;
371 bpi = bpi->next) {
372
373 vnc_zlog_debug_verbose(
374 "%s: trying bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p, local_pref=%" PRIu64,
375 __func__, bpi, bpi->peer, bpi->type, bpi->sub_type,
376 (bpi->extra ? bpi->extra->vnc.export.rfapi_handle
377 : NULL),
378 CHECK_FLAG(bpi->attr->flag,
379 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)
380 ? bpi->attr->local_pref : 0));
381
382 if (bpi->peer == peer && bpi->type == type
383 && bpi->sub_type == sub_type && bpi->extra
384 && bpi->extra->vnc.export.rfapi_handle == (void *)rfd) {
385
386 vnc_zlog_debug_verbose("%s: matched it", __func__);
387
388 break;
389 }
390 }
391
392 if (lnh) {
393 /*
394 * lnh set means to JUST delete the local nexthop from this
395 * route. Leave the route itself in place.
396 * TBD add return code reporting of success/failure
397 */
398 if (!bpi || !bpi->extra
399 || !bpi->extra->vnc.export.local_nexthops) {
400 /*
401 * no local nexthops
402 */
403 vnc_zlog_debug_verbose(
404 "%s: lnh list already empty at prefix %pFX",
405 __func__, p);
406 goto done;
407 }
408
409 /*
410 * look for it
411 */
412 struct listnode *node;
413 struct rfapi_nexthop *pLnh = NULL;
414
415 for (ALL_LIST_ELEMENTS_RO(bpi->extra->vnc.export.local_nexthops,
416 node, pLnh)) {
417
418 if (prefix_same(&pLnh->addr, &lnh->addr)) {
419 break;
420 }
421 }
422
423 if (pLnh) {
424 listnode_delete(bpi->extra->vnc.export.local_nexthops,
425 pLnh);
426
427 /* silly rabbit, listnode_delete doesn't invoke
428 * list->del on data */
429 rfapi_nexthop_free(pLnh);
430 } else {
431 vnc_zlog_debug_verbose("%s: desired lnh not found %pFX",
432 __func__, p);
433 }
434 goto done;
435 }
436
437 /*
438 * loop back to import tables
439 * Do this before removing from BGP RIB because rfapiProcessWithdraw
440 * might refer to it
441 */
442 rfapiProcessWithdraw(peer, rfd, p, prd, NULL, afi, safi, type, kill);
443
444 if (bpi) {
445 vnc_zlog_debug_verbose(
446 "%s: Found route (safi=%d) to delete at prefix %pFX",
447 __func__, safi, p);
448
449 if (safi == SAFI_MPLS_VPN) {
450 struct bgp_dest *pdest = NULL;
451 struct bgp_table *table = NULL;
452
453 pdest = bgp_node_get(bgp->rib[afi][safi],
454 (struct prefix *)prd);
455 table = bgp_dest_get_bgp_table_info(pdest);
456 if (table)
457 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
458 bgp, prd, table, p, bpi);
459 bgp_dest_unlock_node(pdest);
460 }
461
462 /*
463 * Delete local_nexthops list
464 */
465 if (bpi->extra && bpi->extra->vnc.export.local_nexthops)
466 list_delete(&bpi->extra->vnc.export.local_nexthops);
467
468 bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
469 bgp_path_info_delete(bn, bpi);
470 bgp_process(bgp, bn, afi, safi);
471 } else {
472 vnc_zlog_debug_verbose(
473 "%s: Couldn't find route (safi=%d) at prefix %pFX",
474 __func__, safi, p);
475 }
476 done:
477 bgp_dest_unlock_node(bn);
478 }
479
480 struct rfapi_nexthop *rfapi_nexthop_new(struct rfapi_nexthop *copyme)
481 {
482 struct rfapi_nexthop *new =
483 XCALLOC(MTYPE_RFAPI_NEXTHOP, sizeof(struct rfapi_nexthop));
484 if (copyme)
485 *new = *copyme;
486 return new;
487 }
488
489 void rfapi_nexthop_free(void *p)
490 {
491 struct rfapi_nexthop *goner = p;
492 XFREE(MTYPE_RFAPI_NEXTHOP, goner);
493 }
494
495 struct rfapi_vn_option *rfapi_vn_options_dup(struct rfapi_vn_option *existing)
496 {
497 struct rfapi_vn_option *p;
498 struct rfapi_vn_option *head = NULL;
499 struct rfapi_vn_option *tail = NULL;
500
501 for (p = existing; p; p = p->next) {
502 struct rfapi_vn_option *new;
503
504 new = XCALLOC(MTYPE_RFAPI_VN_OPTION,
505 sizeof(struct rfapi_vn_option));
506 *new = *p;
507 new->next = NULL;
508 if (tail)
509 (tail)->next = new;
510 tail = new;
511 if (!head) {
512 head = new;
513 }
514 }
515 return head;
516 }
517
518 void rfapi_un_options_free(struct rfapi_un_option *p)
519 {
520 struct rfapi_un_option *next;
521
522 while (p) {
523 next = p->next;
524 XFREE(MTYPE_RFAPI_UN_OPTION, p);
525 p = next;
526 }
527 }
528
529 void rfapi_vn_options_free(struct rfapi_vn_option *p)
530 {
531 struct rfapi_vn_option *next;
532
533 while (p) {
534 next = p->next;
535 XFREE(MTYPE_RFAPI_VN_OPTION, p);
536 p = next;
537 }
538 }
539
540 /* Based on bgp_redistribute_add() */
541 void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
542 struct bgp *bgp, int safi, const struct prefix *p,
543 struct prefix_rd *prd, struct rfapi_ip_addr *nexthop,
544 uint32_t *local_pref,
545 uint32_t *lifetime, /* NULL => dont send lifetime */
546 struct bgp_tea_options *rfp_options,
547 struct rfapi_un_option *options_un,
548 struct rfapi_vn_option *options_vn,
549 struct ecommunity *rt_export_list, /* Copied, not consumed */
550 uint32_t *med, /* NULL => don't set med */
551 uint32_t *label, /* low order 3 bytes */
552 uint8_t type, uint8_t sub_type, /* RFP, NORMAL or REDIST */
553 int flags)
554 {
555 afi_t afi; /* of the VN address */
556 struct bgp_path_info *new;
557 struct bgp_path_info *bpi;
558 struct bgp_dest *bn;
559
560 struct attr attr = {0};
561 struct attr *new_attr;
562 uint32_t label_val;
563
564 struct bgp_attr_encap_subtlv *encaptlv;
565 char buf[PREFIX_STRLEN];
566
567 struct rfapi_nexthop *lnh = NULL; /* local nexthop */
568 struct rfapi_vn_option *vo;
569 struct rfapi_l2address_option *l2o = NULL;
570 struct rfapi_ip_addr *un_addr = &rfd->un_addr;
571
572 bgp_encap_types TunnelType = BGP_ENCAP_TYPE_RESERVED;
573 struct bgp_redist *red;
574
575 if (safi == SAFI_ENCAP
576 && !(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP)) {
577
578 /*
579 * Encap mode not enabled. UN addresses will be communicated
580 * via VNC Tunnel subtlv instead.
581 */
582 vnc_zlog_debug_verbose(
583 "%s: encap mode not enabled, not adding SAFI_ENCAP route",
584 __func__);
585 return;
586 }
587
588 for (vo = options_vn; vo; vo = vo->next) {
589 if (RFAPI_VN_OPTION_TYPE_L2ADDR == vo->type) {
590 l2o = &vo->v.l2addr;
591 if (RFAPI_0_ETHERADDR(&l2o->macaddr))
592 l2o = NULL; /* not MAC resolution */
593 }
594 if (RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP == vo->type) {
595 lnh = &vo->v.local_nexthop;
596 }
597 }
598
599 if (label)
600 label_val = *label;
601 else
602 label_val = MPLS_LABEL_IMPLICIT_NULL;
603
604 afi = family2afi(p->family);
605 assert(afi == AFI_IP || afi == AFI_IP6);
606
607 vnc_zlog_debug_verbose("%s: afi=%s, safi=%s", __func__, afi2str(afi),
608 safi2str(safi));
609
610 /* Make default attribute. Produces already-interned attr.aspath */
611 /* Cripes, the memory management of attributes is byzantine */
612
613 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
614
615 /*
616 * At this point:
617 * attr: static
618 * extra: dynamically allocated, owned by attr
619 * aspath: points to interned hash from aspath hash table
620 */
621
622
623 /*
624 * Route-specific un_options get added to the VPN SAFI
625 * advertisement tunnel encap attribute. (the per-NVE
626 * "default" un_options are put into the 1-per-NVE ENCAP
627 * SAFI advertisement). The VPN SAFI also gets the
628 * default un_options if there are no route-specific options.
629 */
630 if (options_un) {
631 struct rfapi_un_option *uo;
632
633 for (uo = options_un; uo; uo = uo->next) {
634 if (RFAPI_UN_OPTION_TYPE_TUNNELTYPE == uo->type) {
635 TunnelType = rfapi_tunneltype_option_to_tlv(
636 bgp, un_addr, &uo->v.tunnel, &attr,
637 l2o != NULL);
638 }
639 }
640 } else {
641 /*
642 * Add encap attr
643 * These are the NVE-specific "default" un_options which are
644 * put into the 1-per-NVE ENCAP advertisement.
645 */
646 if (rfd->default_tunneltype_option.type) {
647 TunnelType = rfapi_tunneltype_option_to_tlv(
648 bgp, un_addr, &rfd->default_tunneltype_option,
649 &attr, l2o != NULL);
650 } else /* create default for local addse */
651 if (type == ZEBRA_ROUTE_BGP
652 && sub_type == BGP_ROUTE_RFP)
653 TunnelType = rfapi_tunneltype_option_to_tlv(
654 bgp, un_addr, NULL, &attr, l2o != NULL);
655 }
656
657 if (TunnelType == BGP_ENCAP_TYPE_MPLS) {
658 if (safi == SAFI_ENCAP) {
659 /* Encap SAFI not used with MPLS */
660 vnc_zlog_debug_verbose(
661 "%s: mpls tunnel type, encap safi omitted",
662 __func__);
663 aspath_unintern(&attr.aspath); /* Unintern original. */
664 return;
665 }
666 }
667
668 if (local_pref) {
669 attr.local_pref = *local_pref;
670 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
671 }
672
673 if (med) {
674 attr.med = *med;
675 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
676 }
677
678 /* override default weight assigned by bgp_attr_default_set() */
679 attr.weight = rfd->peer ? rfd->peer->weight[afi][safi] : 0;
680
681 /*
682 * NB: ticket 81: do not reset attr.aspath here because it would
683 * cause iBGP peers to drop route
684 */
685
686 /*
687 * Set originator ID for routes imported from BGP directly.
688 * These routes could be synthetic, and therefore could
689 * reuse the peer pointers of the routes they are derived
690 * from. Setting the originator ID to "us" prevents the
691 * wrong originator ID from being sent when this route is
692 * sent from a route reflector.
693 */
694 if (type == ZEBRA_ROUTE_BGP_DIRECT
695 || type == ZEBRA_ROUTE_BGP_DIRECT_EXT) {
696 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
697 attr.originator_id = bgp->router_id;
698 }
699
700
701 /* Set up vnc attribute (sub-tlv for Prefix Lifetime) */
702 if (lifetime && *lifetime != RFAPI_INFINITE_LIFETIME) {
703 uint32_t lt;
704
705 encaptlv = XCALLOC(MTYPE_ENCAP_TLV,
706 sizeof(struct bgp_attr_encap_subtlv) + 4);
707 encaptlv->type =
708 BGP_VNC_SUBTLV_TYPE_LIFETIME; /* prefix lifetime */
709 encaptlv->length = 4;
710 lt = htonl(*lifetime);
711 memcpy(encaptlv->value, &lt, 4);
712 bgp_attr_set_vnc_subtlvs(&attr, encaptlv);
713 vnc_zlog_debug_verbose(
714 "%s: set Encap Attr Prefix Lifetime to %d", __func__,
715 *lifetime);
716 }
717
718 /* add rfp options to vnc attr */
719 if (rfp_options) {
720
721 if (flags & RFAPI_AHR_RFPOPT_IS_VNCTLV) {
722 struct bgp_attr_encap_subtlv *vnc_subtlvs =
723 bgp_attr_get_vnc_subtlvs(&attr);
724 /*
725 * this flag means we're passing a pointer to an
726 * existing encap tlv chain which we should copy.
727 * It's a hack to avoid adding yet another argument
728 * to add_vnc_route()
729 */
730 encaptlv = encap_tlv_dup(
731 (struct bgp_attr_encap_subtlv *)rfp_options);
732 if (vnc_subtlvs)
733 vnc_subtlvs->next = encaptlv;
734 else
735 bgp_attr_set_vnc_subtlvs(&attr, encaptlv);
736 } else {
737 struct bgp_tea_options *hop;
738 /* XXX max of one tlv present so far from above code */
739 struct bgp_attr_encap_subtlv *tail =
740 bgp_attr_get_vnc_subtlvs(&attr);
741
742 for (hop = rfp_options; hop; hop = hop->next) {
743
744 /*
745 * Construct subtlv
746 */
747 encaptlv = XCALLOC(
748 MTYPE_ENCAP_TLV,
749 sizeof(struct bgp_attr_encap_subtlv) + 2
750 + hop->length);
751 encaptlv->type =
752 BGP_VNC_SUBTLV_TYPE_RFPOPTION; /* RFP
753 option
754 */
755 encaptlv->length = 2 + hop->length;
756 *((uint8_t *)(encaptlv->value) + 0) = hop->type;
757 *((uint8_t *)(encaptlv->value) + 1) =
758 hop->length;
759 memcpy(((uint8_t *)encaptlv->value) + 2,
760 hop->value, hop->length);
761
762 /*
763 * add to end of subtlv chain
764 */
765 if (tail)
766 tail->next = encaptlv;
767 else
768 bgp_attr_set_vnc_subtlvs(&attr,
769 encaptlv);
770 tail = encaptlv;
771 }
772 }
773 }
774
775 /*
776 * At this point:
777 * attr: static
778 * extra: dynamically allocated, owned by attr
779 * vnc_subtlvs: dynamic chain, length 1
780 * aspath: points to interned hash from aspath hash table
781 */
782
783
784 bgp_attr_set_ecommunity(&attr, ecommunity_new());
785 assert(bgp_attr_get_ecommunity(&attr));
786
787 if (TunnelType != BGP_ENCAP_TYPE_MPLS
788 && TunnelType != BGP_ENCAP_TYPE_RESERVED) {
789 /*
790 * Add BGP Encapsulation Extended Community. Format described in
791 * section 4.5 of RFC 5512.
792 * Always include when not MPLS type, to disambiguate this case.
793 */
794 struct ecommunity_val beec;
795
796 memset(&beec, 0, sizeof(beec));
797 beec.val[0] = ECOMMUNITY_ENCODE_OPAQUE;
798 beec.val[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP;
799 beec.val[6] = ((TunnelType) >> 8) & 0xff;
800 beec.val[7] = (TunnelType)&0xff;
801 ecommunity_add_val(bgp_attr_get_ecommunity(&attr), &beec, false,
802 false);
803 }
804
805 /*
806 * Add extended community attributes to match rt export list
807 */
808 if (rt_export_list) {
809 bgp_attr_set_ecommunity(
810 &attr, ecommunity_merge(bgp_attr_get_ecommunity(&attr),
811 rt_export_list));
812 }
813
814 struct ecommunity *ecomm = bgp_attr_get_ecommunity(&attr);
815
816 if (!ecomm->size) {
817 ecommunity_free(&ecomm);
818 bgp_attr_set_ecommunity(&attr, NULL);
819 }
820 vnc_zlog_debug_verbose("%s: attr.ecommunity=%p", __func__, ecomm);
821
822
823 /*
824 * At this point:
825 * attr: static
826 * extra: dynamically allocated, owned by attr
827 * vnc_subtlvs: dynamic chain, length 1
828 * ecommunity: dynamic 2-part
829 * aspath: points to interned hash from aspath hash table
830 */
831
832 /* stuff nexthop in attr_extra; which field depends on IPv4 or IPv6 */
833 switch (nexthop->addr_family) {
834 case AF_INET:
835 /*
836 * set this field to prevent bgp_route.c code from setting
837 * mp_nexthop_global_in to self
838 */
839 attr.nexthop.s_addr = nexthop->addr.v4.s_addr;
840
841 attr.mp_nexthop_global_in = nexthop->addr.v4;
842 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
843 break;
844
845 case AF_INET6:
846 attr.mp_nexthop_global = nexthop->addr.v6;
847 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
848 break;
849
850 default:
851 assert(0);
852 }
853
854
855 prefix2str(p, buf, sizeof(buf));
856
857 /*
858 * At this point:
859 *
860 * attr: static
861 * extra: dynamically allocated, owned by attr
862 * vnc_subtlvs: dynamic chain, length 1
863 * ecommunity: dynamic 2-part
864 * aspath: points to interned hash from aspath hash table
865 */
866
867 red = bgp_redist_lookup(bgp, afi, type, 0);
868
869 if (red && red->redist_metric_flag) {
870 attr.med = red->redist_metric;
871 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
872 }
873
874 bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
875
876 /*
877 * bgp_attr_intern creates a new reference to a cached
878 * attribute, but leaves the following bits of trash:
879 * - old attr
880 * - old attr->extra (free via bgp_attr_extra_free(attr))
881 *
882 * Note that it frees the original attr->extra->ecommunity
883 * but leaves the new attribute pointing to the ORIGINAL
884 * vnc options (which therefore we needn't free from the
885 * static attr)
886 */
887 new_attr = bgp_attr_intern(&attr);
888
889 aspath_unintern(&attr.aspath); /* Unintern original. */
890
891 /*
892 * At this point:
893 *
894 * attr: static
895 * extra: dynamically allocated, owned by attr
896 * vnc_subtlvs: dynamic chain, length 1
897 * ecommunity: POINTS TO INTERNED ecom, THIS REF NOT COUNTED
898 *
899 * new_attr: an attr that is part of the hash table, distinct
900 * from attr which is static.
901 * extra: dynamically allocated, owned by new_attr (in hash table)
902 * vnc_subtlvs: POINTS TO SAME dynamic chain AS attr
903 * ecommunity: POINTS TO interned/refcounted dynamic 2-part AS attr
904 * aspath: POINTS TO interned/refcounted hashed block
905 */
906 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) {
907 /* probably only need to check
908 * bpi->extra->vnc.export.rfapi_handle */
909 if (bpi->peer == rfd->peer && bpi->type == type
910 && bpi->sub_type == sub_type && bpi->extra
911 && bpi->extra->vnc.export.rfapi_handle == (void *)rfd) {
912
913 break;
914 }
915 }
916
917 if (bpi) {
918
919 /*
920 * Adding new local_nexthop, which does not by itself change
921 * what is advertised via BGP
922 */
923 if (lnh) {
924 if (!bpi->extra->vnc.export.local_nexthops) {
925 /* TBD make arrangements to free when needed */
926 bpi->extra->vnc.export.local_nexthops =
927 list_new();
928 bpi->extra->vnc.export.local_nexthops->del =
929 rfapi_nexthop_free;
930 }
931
932 /*
933 * already present?
934 */
935 struct listnode *node;
936 struct rfapi_nexthop *pLnh = NULL;
937
938 for (ALL_LIST_ELEMENTS_RO(
939 bpi->extra->vnc.export.local_nexthops,
940 node, pLnh)) {
941
942 if (prefix_same(&pLnh->addr, &lnh->addr)) {
943 break;
944 }
945 }
946
947 /*
948 * Not present, add new one
949 */
950 if (!pLnh) {
951 pLnh = rfapi_nexthop_new(lnh);
952 listnode_add(
953 bpi->extra->vnc.export.local_nexthops,
954 pLnh);
955 }
956 }
957
958 if (attrhash_cmp(bpi->attr, new_attr)
959 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
960 bgp_attr_unintern(&new_attr);
961 bgp_dest_unlock_node(bn);
962
963 vnc_zlog_debug_any(
964 "%s: Found route (safi=%d) at prefix %s, no change",
965 __func__, safi, buf);
966
967 goto done;
968 } else {
969 /* The attribute is changed. */
970 bgp_path_info_set_flag(bn, bpi, BGP_PATH_ATTR_CHANGED);
971
972 if (safi == SAFI_MPLS_VPN) {
973 struct bgp_dest *pdest = NULL;
974 struct bgp_table *table = NULL;
975
976 pdest = bgp_node_get(bgp->rib[afi][safi],
977 (struct prefix *)prd);
978 table = bgp_dest_get_bgp_table_info(pdest);
979 if (table)
980 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
981 bgp, prd, table, p, bpi);
982 bgp_dest_unlock_node(pdest);
983 }
984
985 /* Rewrite BGP route information. */
986 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
987 bgp_path_info_restore(bn, bpi);
988 else
989 bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
990 bgp_attr_unintern(&bpi->attr);
991 bpi->attr = new_attr;
992 bpi->uptime = monotime(NULL);
993
994
995 if (safi == SAFI_MPLS_VPN) {
996 struct bgp_dest *pdest = NULL;
997 struct bgp_table *table = NULL;
998
999 pdest = bgp_node_get(bgp->rib[afi][safi],
1000 (struct prefix *)prd);
1001 table = bgp_dest_get_bgp_table_info(pdest);
1002 if (table)
1003 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1004 bgp, prd, table, p, bpi);
1005 bgp_dest_unlock_node(pdest);
1006 }
1007
1008 /* Process change. */
1009 bgp_aggregate_increment(bgp, p, bpi, afi, safi);
1010 bgp_process(bgp, bn, afi, safi);
1011 bgp_dest_unlock_node(bn);
1012
1013 vnc_zlog_debug_any(
1014 "%s: Found route (safi=%d) at prefix %s, changed attr",
1015 __func__, safi, buf);
1016
1017 goto done;
1018 }
1019 }
1020
1021 new = info_make(type, sub_type, 0, rfd->peer, new_attr, NULL);
1022 SET_FLAG(new->flags, BGP_PATH_VALID);
1023
1024 /* save backref to rfapi handle */
1025 bgp_path_info_extra_get(new);
1026 new->extra->vnc.export.rfapi_handle = (void *)rfd;
1027 encode_label(label_val, &new->extra->label[0]);
1028
1029 /* debug */
1030
1031 if (VNC_DEBUG(VERBOSE)) {
1032 vnc_zlog_debug_verbose("%s: printing BPI", __func__);
1033 rfapiPrintBi(NULL, new);
1034 }
1035
1036 bgp_aggregate_increment(bgp, p, new, afi, safi);
1037 bgp_path_info_add(bn, new);
1038
1039 if (safi == SAFI_MPLS_VPN) {
1040 struct bgp_dest *pdest = NULL;
1041 struct bgp_table *table = NULL;
1042
1043 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
1044 table = bgp_dest_get_bgp_table_info(pdest);
1045 if (table)
1046 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1047 bgp, prd, table, p, new);
1048 bgp_dest_unlock_node(pdest);
1049 encode_label(label_val, &bn->local_label);
1050 }
1051
1052 bgp_dest_unlock_node(bn);
1053 bgp_process(bgp, bn, afi, safi);
1054
1055 vnc_zlog_debug_any(
1056 "%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%pRDP)",
1057 __func__, safi2str(safi), buf, bn, prd);
1058
1059 done:
1060 /* Loop back to import tables */
1061 rfapiProcessUpdate(rfd->peer, rfd, p, prd, new_attr, afi, safi, type,
1062 sub_type, &label_val);
1063 vnc_zlog_debug_verbose("%s: looped back import route (safi=%d)",
1064 __func__, safi);
1065 }
1066
1067 uint32_t rfp_cost_to_localpref(uint8_t cost)
1068 {
1069 return 255 - cost;
1070 }
1071
1072 static void rfapiTunnelRouteAnnounce(struct bgp *bgp,
1073 struct rfapi_descriptor *rfd,
1074 uint32_t *pLifetime)
1075 {
1076 struct prefix_rd prd;
1077 struct prefix pfx_vn;
1078 int rc;
1079 uint32_t local_pref = rfp_cost_to_localpref(0);
1080
1081 rc = rfapiRaddr2Qprefix(&(rfd->vn_addr), &pfx_vn);
1082 assert(!rc);
1083
1084 /*
1085 * Construct route distinguisher = 0
1086 */
1087 memset(&prd, 0, sizeof(prd));
1088 prd.family = AF_UNSPEC;
1089 prd.prefixlen = 64;
1090
1091 add_vnc_route(rfd, /* rfapi descr, for export list & backref */
1092 bgp, /* which bgp instance */
1093 SAFI_ENCAP, /* which SAFI */
1094 &pfx_vn, /* prefix to advertise */
1095 &prd, /* route distinguisher to use */
1096 &rfd->un_addr, /* nexthop */
1097 &local_pref,
1098 pLifetime, /* max lifetime of child VPN routes */
1099 NULL, /* no rfp options for ENCAP safi */
1100 NULL, /* rfp un options */
1101 NULL, /* rfp vn options */
1102 rfd->rt_export_list, NULL, /* med */
1103 NULL, /* label: default */
1104 ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, 0);
1105 }
1106
1107
1108 /***********************************************************************
1109 * RFP processing behavior configuration
1110 ***********************************************************************/
1111
1112 /*------------------------------------------
1113 * rfapi_rfp_set_configuration
1114 *
1115 * This is used to change rfapi's processing behavior based on
1116 * RFP requirements.
1117 *
1118 * input:
1119 * rfp_start_val value returned by rfp_start
1120 * rfapi_rfp_cfg Pointer to configuration structure
1121 *
1122 * output:
1123 * none
1124 *
1125 * return value:
1126 * 0 Success
1127 * ENXIO Unabled to locate configured BGP/VNC
1128 --------------------------------------------*/
1129 int rfapi_rfp_set_configuration(void *rfp_start_val, struct rfapi_rfp_cfg *new)
1130 {
1131 struct rfapi_rfp_cfg *rcfg;
1132 struct bgp *bgp;
1133
1134 bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
1135
1136 if (!new || !bgp || !bgp->rfapi_cfg)
1137 return ENXIO;
1138
1139 rcfg = &bgp->rfapi_cfg->rfp_cfg;
1140 rcfg->download_type = new->download_type;
1141 rcfg->ftd_advertisement_interval = new->ftd_advertisement_interval;
1142 rcfg->holddown_factor = new->holddown_factor;
1143
1144 if (rcfg->use_updated_response != new->use_updated_response) {
1145 rcfg->use_updated_response = new->use_updated_response;
1146 if (rcfg->use_updated_response)
1147 rfapiMonitorCallbacksOn(bgp);
1148 else
1149 rfapiMonitorCallbacksOff(bgp);
1150 }
1151 if (rcfg->use_removes != new->use_removes) {
1152 rcfg->use_removes = new->use_removes;
1153 if (rcfg->use_removes)
1154 rfapiMonitorResponseRemovalOn(bgp);
1155 else
1156 rfapiMonitorResponseRemovalOff(bgp);
1157 }
1158 return 0;
1159 }
1160
1161 /*------------------------------------------
1162 * rfapi_rfp_set_cb_methods
1163 *
1164 * Change registered callback functions for asynchronous notifications
1165 * from RFAPI to the RFP client.
1166 *
1167 * input:
1168 * rfp_start_val value returned by rfp_start
1169 * methods Pointer to struct rfapi_rfp_cb_methods containing
1170 * pointers to callback methods as described above
1171 *
1172 * return value:
1173 * 0 Success
1174 * ENXIO BGP or VNC not configured
1175 *------------------------------------------*/
1176 int rfapi_rfp_set_cb_methods(void *rfp_start_val,
1177 struct rfapi_rfp_cb_methods *methods)
1178 {
1179 struct rfapi *h;
1180 struct bgp *bgp;
1181
1182 bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
1183 if (!bgp)
1184 return ENXIO;
1185
1186 h = bgp->rfapi;
1187 if (!h)
1188 return ENXIO;
1189
1190 h->rfp_methods = *methods;
1191
1192 return 0;
1193 }
1194
1195 /***********************************************************************
1196 * NVE Sessions
1197 ***********************************************************************/
1198 /*
1199 * Caller must supply an already-allocated rfd with the "caller"
1200 * fields already set (vn_addr, un_addr, callback, cookie)
1201 * The advertised_prefixes[] array elements should be NULL to
1202 * have this function set them to newly-allocated radix trees.
1203 */
1204 static int rfapi_open_inner(struct rfapi_descriptor *rfd, struct bgp *bgp,
1205 struct rfapi *h, struct rfapi_nve_group_cfg *rfg)
1206 {
1207 int ret;
1208
1209 if (h->flags & RFAPI_INCALLBACK)
1210 return EDEADLK;
1211
1212 /*
1213 * Fill in configured fields
1214 */
1215
1216 /*
1217 * If group's RD is specified as "auto", then fill in based
1218 * on NVE's VN address
1219 */
1220 rfd->rd = rfg->rd;
1221
1222 if (rfd->rd.family == AF_UNIX) {
1223 ret = rfapi_set_autord_from_vn(&rfd->rd, &rfd->vn_addr);
1224 if (ret != 0)
1225 return ret;
1226 }
1227 rfd->rt_export_list = (rfg->rt_export_list)
1228 ? ecommunity_dup(rfg->rt_export_list)
1229 : NULL;
1230 rfd->response_lifetime = rfg->response_lifetime;
1231 rfd->rfg = rfg;
1232
1233 /*
1234 * Fill in BGP peer structure
1235 */
1236 rfd->peer = peer_new(bgp);
1237 rfd->peer->status = Established; /* keep bgp core happy */
1238 bgp_sync_delete(rfd->peer); /* don't need these */
1239
1240 /*
1241 * since this peer is not on the I/O thread, this lock is not strictly
1242 * necessary, but serves as a reminder to those who may meddle...
1243 */
1244 frr_with_mutex (&rfd->peer->io_mtx) {
1245 // we don't need any I/O related facilities
1246 if (rfd->peer->ibuf)
1247 stream_fifo_free(rfd->peer->ibuf);
1248 if (rfd->peer->obuf)
1249 stream_fifo_free(rfd->peer->obuf);
1250
1251 if (rfd->peer->ibuf_work)
1252 ringbuf_del(rfd->peer->ibuf_work);
1253 if (rfd->peer->obuf_work)
1254 stream_free(rfd->peer->obuf_work);
1255
1256 rfd->peer->ibuf = NULL;
1257 rfd->peer->obuf = NULL;
1258 rfd->peer->obuf_work = NULL;
1259 rfd->peer->ibuf_work = NULL;
1260 }
1261
1262 { /* base code assumes have valid host pointer */
1263 char buf[INET6_ADDRSTRLEN];
1264 buf[0] = 0;
1265
1266 if (rfd->vn_addr.addr_family == AF_INET) {
1267 inet_ntop(AF_INET, &rfd->vn_addr.addr.v4, buf,
1268 sizeof(buf));
1269 } else if (rfd->vn_addr.addr_family == AF_INET6) {
1270 inet_ntop(AF_INET6, &rfd->vn_addr.addr.v6, buf,
1271 sizeof(buf));
1272 }
1273 rfd->peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, buf);
1274 }
1275 /* Mark peer as belonging to HD */
1276 SET_FLAG(rfd->peer->flags, PEER_FLAG_IS_RFAPI_HD);
1277
1278 /*
1279 * Set min prefix lifetime to max value so it will get set
1280 * upon first rfapi_register()
1281 */
1282 rfd->min_prefix_lifetime = UINT32_MAX;
1283
1284 /*
1285 * Allocate response tables if needed
1286 */
1287 #define RFD_RTINIT_AFI(rh, ary, afi) \
1288 do { \
1289 if (!ary[afi]) { \
1290 ary[afi] = agg_table_init(); \
1291 agg_set_table_info(ary[afi], rh); \
1292 } \
1293 } while (0)
1294
1295 #define RFD_RTINIT(rh, ary) \
1296 do { \
1297 RFD_RTINIT_AFI(rh, ary, AFI_IP); \
1298 RFD_RTINIT_AFI(rh, ary, AFI_IP6); \
1299 RFD_RTINIT_AFI(rh, ary, AFI_L2VPN); \
1300 } while (0)
1301
1302 RFD_RTINIT(rfd, rfd->rib);
1303 RFD_RTINIT(rfd, rfd->rib_pending);
1304 RFD_RTINIT(rfd, rfd->rsp_times);
1305
1306 /*
1307 * Link to Import Table
1308 */
1309 rfd->import_table = rfg->rfapi_import_table;
1310 rfd->import_table->refcount += 1;
1311
1312 rfapiApInit(&rfd->advertised);
1313
1314 /*
1315 * add this NVE descriptor to the list of NVEs in the NVE group
1316 */
1317 if (!rfg->nves) {
1318 rfg->nves = list_new();
1319 }
1320 listnode_add(rfg->nves, rfd);
1321
1322 vnc_direct_bgp_add_nve(bgp, rfd);
1323 vnc_zebra_add_nve(bgp, rfd);
1324
1325 return 0;
1326 }
1327
1328 /* moved from rfapi_register */
1329 int rfapi_init_and_open(struct bgp *bgp, struct rfapi_descriptor *rfd,
1330 struct rfapi_nve_group_cfg *rfg)
1331 {
1332 struct rfapi *h = bgp->rfapi;
1333 char buf_vn[BUFSIZ];
1334 char buf_un[BUFSIZ];
1335 afi_t afi_vn, afi_un;
1336 struct prefix pfx_un;
1337 struct agg_node *rn;
1338
1339 rfd->open_time = monotime(NULL);
1340
1341 if (rfg->type == RFAPI_GROUP_CFG_VRF)
1342 SET_FLAG(rfd->flags, RFAPI_HD_FLAG_IS_VRF);
1343
1344 rfapiRfapiIpAddr2Str(&rfd->vn_addr, buf_vn, BUFSIZ);
1345 rfapiRfapiIpAddr2Str(&rfd->un_addr, buf_un, BUFSIZ);
1346
1347 vnc_zlog_debug_verbose("%s: new RFD with VN=%s UN=%s cookie=%p",
1348 __func__, buf_vn, buf_un, rfd->cookie);
1349
1350 if (rfg->type != RFAPI_GROUP_CFG_VRF) /* unclear if needed for VRF */
1351 {
1352 listnode_add(&h->descriptors, rfd);
1353 if (h->descriptors.count > h->stat.max_descriptors) {
1354 h->stat.max_descriptors = h->descriptors.count;
1355 }
1356
1357 /*
1358 * attach to UN radix tree
1359 */
1360 afi_vn = family2afi(rfd->vn_addr.addr_family);
1361 afi_un = family2afi(rfd->un_addr.addr_family);
1362 assert(afi_vn && afi_un);
1363 assert(!rfapiRaddr2Qprefix(&rfd->un_addr, &pfx_un));
1364
1365 rn = agg_node_get(h->un[afi_un], &pfx_un);
1366 assert(rn);
1367 rfd->next = rn->info;
1368 rn->info = rfd;
1369 rfd->un_node = rn;
1370 }
1371 return rfapi_open_inner(rfd, bgp, h, rfg);
1372 }
1373
1374 struct rfapi_vn_option *rfapiVnOptionsDup(struct rfapi_vn_option *orig)
1375 {
1376 struct rfapi_vn_option *head = NULL;
1377 struct rfapi_vn_option *tail = NULL;
1378 struct rfapi_vn_option *vo = NULL;
1379
1380 for (vo = orig; vo; vo = vo->next) {
1381 struct rfapi_vn_option *new;
1382
1383 new = XCALLOC(MTYPE_RFAPI_VN_OPTION,
1384 sizeof(struct rfapi_vn_option));
1385 memcpy(new, vo, sizeof(struct rfapi_vn_option));
1386 new->next = NULL;
1387
1388 if (tail) {
1389 tail->next = new;
1390 } else {
1391 head = tail = new;
1392 }
1393 }
1394 return head;
1395 }
1396
1397 struct rfapi_un_option *rfapiUnOptionsDup(struct rfapi_un_option *orig)
1398 {
1399 struct rfapi_un_option *head = NULL;
1400 struct rfapi_un_option *tail = NULL;
1401 struct rfapi_un_option *uo = NULL;
1402
1403 for (uo = orig; uo; uo = uo->next) {
1404 struct rfapi_un_option *new;
1405
1406 new = XCALLOC(MTYPE_RFAPI_UN_OPTION,
1407 sizeof(struct rfapi_un_option));
1408 memcpy(new, uo, sizeof(struct rfapi_un_option));
1409 new->next = NULL;
1410
1411 if (tail) {
1412 tail->next = new;
1413 } else {
1414 head = tail = new;
1415 }
1416 }
1417 return head;
1418 }
1419
1420 struct bgp_tea_options *rfapiOptionsDup(struct bgp_tea_options *orig)
1421 {
1422 struct bgp_tea_options *head = NULL;
1423 struct bgp_tea_options *tail = NULL;
1424 struct bgp_tea_options *hop = NULL;
1425
1426 for (hop = orig; hop; hop = hop->next) {
1427 struct bgp_tea_options *new;
1428
1429 new = XCALLOC(MTYPE_BGP_TEA_OPTIONS,
1430 sizeof(struct bgp_tea_options));
1431 memcpy(new, hop, sizeof(struct bgp_tea_options));
1432 new->next = NULL;
1433 if (hop->value) {
1434 new->value = XCALLOC(MTYPE_BGP_TEA_OPTIONS_VALUE,
1435 hop->length);
1436 memcpy(new->value, hop->value, hop->length);
1437 }
1438 if (tail) {
1439 tail->next = new;
1440 } else {
1441 head = tail = new;
1442 }
1443 }
1444 return head;
1445 }
1446
1447 void rfapiFreeBgpTeaOptionChain(struct bgp_tea_options *p)
1448 {
1449 struct bgp_tea_options *next;
1450
1451 while (p) {
1452 next = p->next;
1453
1454 XFREE(MTYPE_BGP_TEA_OPTIONS_VALUE, p->value);
1455 XFREE(MTYPE_BGP_TEA_OPTIONS, p);
1456
1457 p = next;
1458 }
1459 }
1460
1461 void rfapiAdbFree(struct rfapi_adb *adb)
1462 {
1463 XFREE(MTYPE_RFAPI_ADB, adb);
1464 }
1465
1466 static int
1467 rfapi_query_inner(void *handle, struct rfapi_ip_addr *target,
1468 struct rfapi_l2address_option *l2o, /* may be NULL */
1469 struct rfapi_next_hop_entry **ppNextHopEntry)
1470 {
1471 afi_t afi;
1472 struct prefix p;
1473 struct prefix p_original;
1474 struct agg_node *rn;
1475 struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
1476 struct bgp *bgp = rfd->bgp;
1477 struct rfapi_next_hop_entry *pNHE = NULL;
1478 struct rfapi_ip_addr *self_vn_addr = NULL;
1479 int eth_is_0 = 0;
1480 int use_eth_resolution = 0;
1481 struct rfapi_next_hop_entry *i_nhe;
1482
1483 /* preemptive */
1484 if (!bgp) {
1485 vnc_zlog_debug_verbose("%s: No BGP instance, returning ENXIO",
1486 __func__);
1487 return ENXIO;
1488 }
1489 if (!bgp->rfapi) {
1490 vnc_zlog_debug_verbose("%s: No RFAPI instance, returning ENXIO",
1491 __func__);
1492 return ENXIO;
1493 }
1494 if (bgp->rfapi->flags & RFAPI_INCALLBACK) {
1495 vnc_zlog_debug_verbose(
1496 "%s: Called during calback, returning EDEADLK",
1497 __func__);
1498 return EDEADLK;
1499 }
1500
1501 if (!is_valid_rfd(rfd)) {
1502 vnc_zlog_debug_verbose("%s: invalid handle, returning EBADF",
1503 __func__);
1504 return EBADF;
1505 }
1506
1507 rfd->rsp_counter++; /* dedup: identify this generation */
1508 rfd->rsp_time = monotime(NULL); /* response content dedup */
1509 rfd->ftd_last_allowed_time =
1510 monotime(NULL) -
1511 bgp->rfapi_cfg->rfp_cfg.ftd_advertisement_interval;
1512
1513 if (l2o) {
1514 if (!memcmp(l2o->macaddr.octet, rfapi_ethaddr0.octet,
1515 ETH_ALEN)) {
1516 eth_is_0 = 1;
1517 }
1518 /* per t/c Paul/Lou 151022 */
1519 if (!eth_is_0 || l2o->logical_net_id) {
1520 use_eth_resolution = 1;
1521 }
1522 }
1523
1524 if (ppNextHopEntry)
1525 *ppNextHopEntry = NULL;
1526
1527 /*
1528 * Save original target in prefix form. In case of L2-based queries,
1529 * p_original will be modified to reflect the L2 target
1530 */
1531 assert(!rfapiRaddr2Qprefix(target, &p_original));
1532
1533 if (bgp->rfapi_cfg->rfp_cfg.download_type == RFAPI_RFP_DOWNLOAD_FULL) {
1534 /* convert query to 0/0 when full-table download is enabled */
1535 memset((char *)&p, 0, sizeof(p));
1536 p.family = target->addr_family;
1537 } else {
1538 p = p_original;
1539 }
1540
1541 {
1542 char *s;
1543
1544 vnc_zlog_debug_verbose("%s(rfd=%p, target=%pFX, ppNextHop=%p)",
1545 __func__, rfd, &p, ppNextHopEntry);
1546
1547 s = ecommunity_ecom2str(rfd->import_table->rt_import_list,
1548 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1549 vnc_zlog_debug_verbose(
1550 "%s rfd->import_table=%p, rfd->import_table->rt_import_list: %s",
1551 __func__, rfd->import_table, s);
1552 XFREE(MTYPE_ECOMMUNITY_STR, s);
1553 }
1554
1555 afi = family2afi(p.family);
1556 assert(afi);
1557
1558 if (CHECK_FLAG(bgp->rfapi_cfg->flags,
1559 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP)) {
1560 self_vn_addr = &rfd->vn_addr;
1561 }
1562
1563 if (use_eth_resolution) {
1564 uint32_t logical_net_id = l2o->logical_net_id;
1565 struct ecommunity *l2com;
1566
1567 /*
1568 * fix up p_original to contain L2 address
1569 */
1570 rfapiL2o2Qprefix(l2o, &p_original);
1571
1572 l2com = bgp_rfapi_get_ecommunity_by_lni_label(
1573 bgp, 1, logical_net_id, l2o->label);
1574 if (l2com) {
1575 uint8_t *v = l2com->val;
1576 logical_net_id = (v[5] << 16) + (v[6] << 8) + (v[7]);
1577 }
1578 /*
1579 * Ethernet/L2-based lookup
1580 *
1581 * Always returns IT node corresponding to route
1582 */
1583
1584 if (RFAPI_RFP_DOWNLOAD_FULL
1585 == bgp->rfapi_cfg->rfp_cfg.download_type) {
1586 eth_is_0 = 1;
1587 }
1588
1589 rn = rfapiMonitorEthAdd(
1590 bgp, rfd, (eth_is_0 ? &rfapi_ethaddr0 : &l2o->macaddr),
1591 logical_net_id);
1592
1593 if (eth_is_0) {
1594 struct rfapi_ip_prefix rprefix;
1595
1596 memset(&rprefix, 0, sizeof(rprefix));
1597 rprefix.prefix.addr_family = target->addr_family;
1598 if (target->addr_family == AF_INET) {
1599 rprefix.length = IPV4_MAX_BITLEN;
1600 } else {
1601 rprefix.length = IPV6_MAX_BITLEN;
1602 }
1603
1604 pNHE = rfapiEthRouteTable2NextHopList(
1605 logical_net_id, &rprefix,
1606 rfd->response_lifetime, self_vn_addr,
1607 rfd->rib[afi], &p_original);
1608 goto done;
1609 }
1610
1611 } else {
1612
1613 /*
1614 * IP-based lookup
1615 */
1616
1617 rn = rfapiMonitorAdd(bgp, rfd, &p);
1618
1619 /*
1620 * If target address is 0, this request is special: means to
1621 * return ALL routes in the table
1622 *
1623 * Monitors for All-Routes queries get put on a special list,
1624 * not in the VPN tree
1625 */
1626 if (RFAPI_0_PREFIX(&p)) {
1627
1628 vnc_zlog_debug_verbose("%s: 0-prefix", __func__);
1629
1630 /*
1631 * Generate nexthop list for caller
1632 */
1633 pNHE = rfapiRouteTable2NextHopList(
1634 rfd->import_table->imported_vpn[afi],
1635 rfd->response_lifetime, self_vn_addr,
1636 rfd->rib[afi], &p_original);
1637 goto done;
1638 }
1639
1640 if (rn) {
1641 agg_lock_node(rn); /* so we can unlock below */
1642 } else {
1643 /*
1644 * returns locked node. Don't unlock yet because the
1645 * unlock
1646 * might free it before we're done with it. This
1647 * situation
1648 * could occur when rfapiMonitorGetAttachNode() returns
1649 * a
1650 * newly-created default node.
1651 */
1652 rn = rfapiMonitorGetAttachNode(rfd, &p);
1653 }
1654 }
1655
1656 assert(rn);
1657 if (!rn->info) {
1658 agg_unlock_node(rn);
1659 vnc_zlog_debug_verbose(
1660 "%s: VPN route not found, returning ENOENT", __func__);
1661 return ENOENT;
1662 }
1663
1664 if (VNC_DEBUG(RFAPI_QUERY)) {
1665 rfapiShowImportTable(NULL, "query",
1666 rfd->import_table->imported_vpn[afi], 1);
1667 }
1668
1669 if (use_eth_resolution) {
1670
1671 struct rfapi_ip_prefix rprefix;
1672
1673 memset(&rprefix, 0, sizeof(rprefix));
1674 rprefix.prefix.addr_family = target->addr_family;
1675 if (target->addr_family == AF_INET) {
1676 rprefix.length = IPV4_MAX_BITLEN;
1677 } else {
1678 rprefix.length = IPV6_MAX_BITLEN;
1679 }
1680
1681 pNHE = rfapiEthRouteNode2NextHopList(
1682 rn, &rprefix, rfd->response_lifetime, self_vn_addr,
1683 rfd->rib[afi], &p_original);
1684
1685
1686 } else {
1687 /*
1688 * Generate answer to query
1689 */
1690 pNHE = rfapiRouteNode2NextHopList(rn, rfd->response_lifetime,
1691 self_vn_addr, rfd->rib[afi],
1692 &p_original);
1693 }
1694
1695 agg_unlock_node(rn);
1696
1697 done:
1698 if (ppNextHopEntry) {
1699 /* only count if caller gets it */
1700 ++bgp->rfapi->response_immediate_count;
1701 }
1702
1703 if (!pNHE) {
1704 vnc_zlog_debug_verbose("%s: NO NHEs, returning ENOENT",
1705 __func__);
1706 return ENOENT;
1707 }
1708
1709 /*
1710 * count nexthops for statistics
1711 */
1712 for (i_nhe = pNHE; i_nhe; i_nhe = i_nhe->next) {
1713 ++rfd->stat_count_nh_reachable;
1714 }
1715
1716 if (ppNextHopEntry) {
1717 *ppNextHopEntry = pNHE;
1718 } else {
1719 rfapi_free_next_hop_list(pNHE);
1720 }
1721
1722 vnc_zlog_debug_verbose("%s: success", __func__);
1723 return 0;
1724 }
1725
1726 /*
1727 * support on-the-fly reassignment of an already-open nve to a new
1728 * nve-group in the event that its original nve-group is
1729 * administratively deleted.
1730 */
1731 static int rfapi_open_rfd(struct rfapi_descriptor *rfd, struct bgp *bgp)
1732 {
1733 struct prefix pfx_vn;
1734 struct prefix pfx_un;
1735 struct rfapi_nve_group_cfg *rfg;
1736 struct rfapi *h;
1737 struct rfapi_cfg *hc;
1738 int rc;
1739
1740 h = bgp->rfapi;
1741 if (!h)
1742 return ENXIO;
1743
1744 hc = bgp->rfapi_cfg;
1745 if (!hc)
1746 return ENXIO;
1747
1748 rc = rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn);
1749 assert(!rc);
1750
1751 rc = rfapiRaddr2Qprefix(&rfd->un_addr, &pfx_un);
1752 assert(!rc);
1753
1754 /*
1755 * Find the matching nve group config block
1756 */
1757 rfg = bgp_rfapi_cfg_match_group(hc, &pfx_vn, &pfx_un);
1758 if (!rfg) {
1759 return ENOENT;
1760 }
1761
1762 /*
1763 * check nve group config block for required values
1764 */
1765 if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
1766
1767 return ENOMSG;
1768 }
1769
1770 rc = rfapi_open_inner(rfd, bgp, h, rfg);
1771 if (rc) {
1772 return rc;
1773 }
1774
1775 /*
1776 * re-advertise registered routes, this time as part of new NVE-group
1777 */
1778 rfapiApReadvertiseAll(bgp, rfd);
1779
1780 /*
1781 * re-attach callbacks to import table
1782 */
1783 if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) {
1784 rfapiMonitorAttachImportHd(rfd);
1785 }
1786
1787 return 0;
1788 }
1789
1790 /*------------------------------------------
1791 * rfapi_open
1792 *
1793 * This function initializes a NVE record and associates it with
1794 * the specified VN and underlay network addresses
1795 *
1796 * input:
1797 * rfp_start_val value returned by rfp_start
1798 * vn NVE virtual network address
1799 *
1800 * un NVE underlay network address
1801 *
1802 * default_options Default options to use on registrations.
1803 * For now only tunnel type is supported.
1804 * May be overridden per-prefix in rfapi_register().
1805 * Caller owns (rfapi_open() does not free)
1806 *
1807 * response_cb Pointer to next hop list update callback function or
1808 * NULL when no callbacks are desired.
1809 *
1810 * userdata Passed to subsequent response_cb invocations.
1811 *
1812 * output:
1813 * response_lifetime The length of time that responses sent to this
1814 * NVE are valid.
1815 *
1816 * pHandle pointer to location to store rfapi handle. The
1817 * handle must be passed on subsequent rfapi_ calls.
1818 *
1819 *
1820 * return value:
1821 * 0 Success
1822 * EEXIST NVE with this {vn,un} already open
1823 * ENOENT No matching nve group config
1824 * ENOMSG Matched nve group config was incomplete
1825 * ENXIO BGP or VNC not configured
1826 * EAFNOSUPPORT Matched nve group specifies auto-assignment of RD,
1827 * but underlay network address is not IPv4
1828 * EDEADLK Called from within a callback procedure
1829 *------------------------------------------*/
1830 int rfapi_open(void *rfp_start_val, struct rfapi_ip_addr *vn,
1831 struct rfapi_ip_addr *un,
1832 struct rfapi_un_option *default_options,
1833 uint32_t *response_lifetime,
1834 void *userdata, /* callback cookie */
1835 rfapi_handle *pHandle)
1836 {
1837 struct bgp *bgp;
1838 struct rfapi *h;
1839 struct rfapi_descriptor *rfd;
1840 struct rfapi_cfg *hc;
1841 struct rfapi_nve_group_cfg *rfg;
1842
1843 struct prefix pfx_vn;
1844 struct prefix pfx_un;
1845
1846 int rc;
1847 rfapi_handle hh = NULL;
1848 int reusing_provisional = 0;
1849
1850 {
1851 char buf[2][INET_ADDRSTRLEN];
1852 vnc_zlog_debug_verbose(
1853 "%s: VN=%s UN=%s", __func__,
1854 rfapiRfapiIpAddr2Str(vn, buf[0], INET_ADDRSTRLEN),
1855 rfapiRfapiIpAddr2Str(un, buf[1], INET_ADDRSTRLEN));
1856 }
1857
1858 assert(pHandle);
1859 *pHandle = NULL;
1860
1861 bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
1862 if (!bgp)
1863 return ENXIO;
1864
1865 h = bgp->rfapi;
1866 if (!h)
1867 return ENXIO;
1868
1869 hc = bgp->rfapi_cfg;
1870 if (!hc)
1871 return ENXIO;
1872
1873 if (h->flags & RFAPI_INCALLBACK)
1874 return EDEADLK;
1875
1876 rc = rfapiRaddr2Qprefix(vn, &pfx_vn);
1877 assert(!rc);
1878
1879 rc = rfapiRaddr2Qprefix(un, &pfx_un);
1880 assert(!rc);
1881
1882 /*
1883 * already have a descriptor with VN and UN?
1884 */
1885 if (!rfapi_find_handle(bgp, vn, un, &hh)) {
1886 /*
1887 * we might have set up a handle for static routes before
1888 * this NVE was opened. In that case, reuse the handle
1889 */
1890 rfd = hh;
1891 if (!CHECK_FLAG(rfd->flags, RFAPI_HD_FLAG_PROVISIONAL)) {
1892 return EEXIST;
1893 }
1894
1895 /*
1896 * reuse provisional descriptor
1897 * hh is not NULL
1898 */
1899 reusing_provisional = 1;
1900 }
1901
1902 /*
1903 * Find the matching nve group config block
1904 */
1905 rfg = bgp_rfapi_cfg_match_group(hc, &pfx_vn, &pfx_un);
1906 if (!rfg) {
1907 ++h->stat.count_unknown_nves;
1908 {
1909 char buf[2][INET_ADDRSTRLEN];
1910 zlog_notice("%s: no matching group VN=%s UN=%s",
1911 __func__,
1912 rfapiRfapiIpAddr2Str(vn, buf[0],
1913 INET_ADDRSTRLEN),
1914 rfapiRfapiIpAddr2Str(un, buf[1],
1915 INET_ADDRSTRLEN));
1916 }
1917 return ENOENT;
1918 }
1919
1920 /*
1921 * check nve group config block for required values
1922 */
1923 if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
1924
1925 ++h->stat.count_unknown_nves;
1926 return ENOMSG;
1927 }
1928
1929 /*
1930 * If group config specifies auto-rd assignment, check that
1931 * VN address is IPv4|v6 so we don't fail in rfapi_open_inner().
1932 * Check here so we don't need to unwind memory allocations, &c.
1933 */
1934 if ((rfg->rd.family == AF_UNIX) && (vn->addr_family != AF_INET)
1935 && (vn->addr_family != AF_INET6)) {
1936 return EAFNOSUPPORT;
1937 }
1938
1939 if (hh) {
1940 /*
1941 * reusing provisional rfd
1942 */
1943 rfd = hh;
1944 } else {
1945 rfd = XCALLOC(MTYPE_RFAPI_DESC,
1946 sizeof(struct rfapi_descriptor));
1947 }
1948
1949 rfd->bgp = bgp;
1950 if (default_options) {
1951 struct rfapi_un_option *p;
1952
1953 for (p = default_options; p; p = p->next) {
1954 if ((RFAPI_UN_OPTION_TYPE_PROVISIONAL == p->type)) {
1955 rfd->flags |= RFAPI_HD_FLAG_PROVISIONAL;
1956 }
1957 if ((RFAPI_UN_OPTION_TYPE_TUNNELTYPE == p->type)) {
1958 rfd->default_tunneltype_option = p->v.tunnel;
1959 }
1960 }
1961 }
1962
1963 /*
1964 * Fill in caller fields
1965 */
1966 rfd->vn_addr = *vn;
1967 rfd->un_addr = *un;
1968 rfd->cookie = userdata;
1969
1970 if (!reusing_provisional) {
1971 rc = rfapi_init_and_open(bgp, rfd, rfg);
1972 /*
1973 * This can fail only if the VN address is IPv6 and the group
1974 * specified auto-assignment of RDs, which only works for v4,
1975 * and the check above should catch it.
1976 *
1977 * Another failure possibility is that we were called
1978 * during an rfapi callback. Also checked above.
1979 */
1980 assert(!rc);
1981 }
1982
1983 if (response_lifetime)
1984 *response_lifetime = rfd->response_lifetime;
1985 *pHandle = rfd;
1986 return 0;
1987 }
1988
1989 /*
1990 * For use with debug functions
1991 */
1992 static int rfapi_set_response_cb(struct rfapi_descriptor *rfd,
1993 rfapi_response_cb_t *response_cb)
1994 {
1995 if (!is_valid_rfd(rfd))
1996 return EBADF;
1997 rfd->response_cb = response_cb;
1998 return 0;
1999 }
2000
2001 /*
2002 * rfapi_close_inner
2003 *
2004 * Does almost all the work of rfapi_close, except:
2005 * 1. preserves the descriptor (doesn't free it)
2006 * 2. preserves the prefix query list (i.e., rfd->mon list)
2007 * 3. preserves the advertised prefix list (rfd->advertised)
2008 * 4. preserves the rib and rib_pending tables
2009 *
2010 * The purpose of organizing it this way is to support on-the-fly
2011 * reassignment of an already-open nve to a new nve-group in the
2012 * event that its original nve-group is administratively deleted.
2013 */
2014 static int rfapi_close_inner(struct rfapi_descriptor *rfd, struct bgp *bgp)
2015 {
2016 int rc;
2017 struct prefix pfx_vn;
2018 struct prefix_rd prd; /* currently always 0 for VN->UN */
2019
2020 if (!is_valid_rfd(rfd))
2021 return EBADF;
2022
2023 rc = rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn);
2024 assert(!rc); /* should never have bad AF in stored vn address */
2025
2026 /*
2027 * update exported routes to reflect disappearance of this NVE as
2028 * nexthop
2029 */
2030 vnc_direct_bgp_del_nve(bgp, rfd);
2031 vnc_zebra_del_nve(bgp, rfd);
2032
2033 /*
2034 * unlink this HD's monitors from import table
2035 */
2036 rfapiMonitorDetachImportHd(rfd);
2037
2038 /*
2039 * Unlink from Import Table
2040 * NB rfd->import_table will be NULL if we are closing a stale
2041 * descriptor
2042 */
2043 if (rfd->import_table)
2044 rfapiImportTableRefDelByIt(bgp, rfd->import_table);
2045 rfd->import_table = NULL;
2046
2047 /*
2048 * Construct route distinguisher
2049 */
2050 memset(&prd, 0, sizeof(prd));
2051 prd = rfd->rd;
2052 prd.family = AF_UNSPEC;
2053 prd.prefixlen = 64;
2054
2055 /*
2056 * withdraw tunnel
2057 */
2058 del_vnc_route(rfd, rfd->peer, bgp, SAFI_ENCAP,
2059 &pfx_vn, /* prefix being advertised */
2060 &prd, /* route distinguisher to use (0 for ENCAP) */
2061 ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL, 0); /* no kill */
2062
2063 /*
2064 * Construct route distinguisher for VPN routes
2065 */
2066 prd = rfd->rd;
2067 prd.family = AF_UNSPEC;
2068 prd.prefixlen = 64;
2069
2070 /*
2071 * find all VPN routes associated with this rfd and delete them, too
2072 */
2073 rfapiApWithdrawAll(bgp, rfd);
2074
2075 /*
2076 * remove this nve descriptor from the list of nves
2077 * associated with the nve group
2078 */
2079 if (rfd->rfg) {
2080 listnode_delete(rfd->rfg->nves, rfd);
2081 rfd->rfg = NULL; /* XXX mark as orphaned/stale */
2082 }
2083
2084 if (rfd->rt_export_list)
2085 ecommunity_free(&rfd->rt_export_list);
2086 rfd->rt_export_list = NULL;
2087
2088 /*
2089 * free peer structure (possibly delayed until its
2090 * refcount reaches zero)
2091 */
2092 if (rfd->peer) {
2093 vnc_zlog_debug_verbose("%s: calling peer_delete(%p), #%d",
2094 __func__, rfd->peer, rfd->peer->lock);
2095 peer_delete(rfd->peer);
2096 }
2097 rfd->peer = NULL;
2098
2099 return 0;
2100 }
2101
2102 int rfapi_close(void *handle)
2103 {
2104 struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
2105 int rc;
2106 struct agg_node *node;
2107 struct bgp *bgp;
2108 struct rfapi *h;
2109
2110 vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd);
2111
2112 #ifdef RFAPI_WHO_IS_CALLING_ME
2113 #ifdef HAVE_GLIBC_BACKTRACE
2114 #define RFAPI_DEBUG_BACKTRACE_NENTRIES 5
2115 {
2116 void *buf[RFAPI_DEBUG_BACKTRACE_NENTRIES];
2117 char **syms;
2118 int i;
2119 size_t size;
2120
2121 size = backtrace(buf, RFAPI_DEBUG_BACKTRACE_NENTRIES);
2122 syms = backtrace_symbols(buf, size);
2123 for (i = 0; i < size && i < RFAPI_DEBUG_BACKTRACE_NENTRIES;
2124 ++i) {
2125 vnc_zlog_debug_verbose("backtrace[%2d]: %s", i,
2126 syms[i]);
2127 }
2128 free(syms);
2129 }
2130 #endif
2131 #endif
2132
2133 bgp = rfd->bgp;
2134 if (!bgp)
2135 return ENXIO;
2136
2137 h = bgp->rfapi;
2138 if (!h)
2139 return ENXIO;
2140
2141 if (!is_valid_rfd(rfd))
2142 return EBADF;
2143
2144 if (h->flags & RFAPI_INCALLBACK) {
2145 /*
2146 * Queue these close requests for processing after callback
2147 * is finished
2148 */
2149 if (!CHECK_FLAG(rfd->flags,
2150 RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY)) {
2151 work_queue_add(h->deferred_close_q, handle);
2152 vnc_zlog_debug_verbose(
2153 "%s: added handle %p to deferred close queue",
2154 __func__, handle);
2155 }
2156 return 0;
2157 }
2158
2159 if (CHECK_FLAG(rfd->flags, RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY)) {
2160
2161 vnc_zlog_debug_verbose("%s administrative close rfd=%p",
2162 __func__, rfd);
2163
2164 if (h->rfp_methods.close_cb) {
2165 vnc_zlog_debug_verbose(
2166 "%s calling close callback rfd=%p", __func__,
2167 rfd);
2168
2169 /*
2170 * call the callback fairly early so that it can still
2171 * lookup un/vn
2172 * from handle, etc.
2173 *
2174 * NB RFAPI_INCALLBACK is tested above, so if we reach
2175 * this point
2176 * we are not already in the context of a callback.
2177 */
2178 h->flags |= RFAPI_INCALLBACK;
2179 (*h->rfp_methods.close_cb)(handle, EIDRM);
2180 h->flags &= ~RFAPI_INCALLBACK;
2181 }
2182 }
2183
2184 if (rfd->rfg) {
2185 /*
2186 * Orphaned descriptors have already done this part, so do
2187 * only for non-orphaned descriptors.
2188 */
2189 if ((rc = rfapi_close_inner(rfd, bgp)))
2190 return rc;
2191 }
2192
2193 /*
2194 * Remove descriptor from UN index
2195 * (remove from chain at node)
2196 */
2197 rc = rfapi_find_node(bgp, &rfd->vn_addr, &rfd->un_addr, &node);
2198 if (!rc) {
2199 struct rfapi_descriptor *hh;
2200
2201 if (node->info == rfd) {
2202 node->info = rfd->next;
2203 } else {
2204
2205 for (hh = node->info; hh; hh = hh->next) {
2206 if (hh->next == rfd) {
2207 hh->next = rfd->next;
2208 break;
2209 }
2210 }
2211 }
2212 agg_unlock_node(node);
2213 }
2214
2215 /*
2216 * remove from descriptor list
2217 */
2218 listnode_delete(&h->descriptors, rfd);
2219
2220 /*
2221 * Delete monitor list items and free monitor structures
2222 */
2223 (void)rfapiMonitorDelHd(rfd);
2224
2225 /*
2226 * release advertised prefix data
2227 */
2228 rfapiApRelease(&rfd->advertised);
2229
2230 /*
2231 * Release RFP callback RIB
2232 */
2233 rfapiRibFree(rfd);
2234
2235 /*
2236 * free descriptor
2237 */
2238 memset(rfd, 0, sizeof(struct rfapi_descriptor));
2239 XFREE(MTYPE_RFAPI_DESC, rfd);
2240
2241 return 0;
2242 }
2243
2244 /*
2245 * Reopen a nve descriptor. If the descriptor's NVE-group
2246 * does not exist (e.g., if it has been administratively removed),
2247 * reassignment to a new NVE-group is attempted.
2248 *
2249 * If NVE-group reassignment fails, the descriptor becomes "stale"
2250 * (rfd->rfg == NULL implies "stale:). The only permissible API operation
2251 * on a stale descriptor is rfapi_close(). Any other rfapi_* API operation
2252 * on the descriptor will return ESTALE.
2253 *
2254 * Reopening a descriptor is a potentially expensive operation, because
2255 * it involves withdrawing any routes advertised by the NVE, withdrawing
2256 * the NVE's route queries, and then re-adding them all after a new
2257 * NVE-group is assigned. There are also possible route-export affects
2258 * caused by deleting and then adding the NVE: advertised prefixes
2259 * and nexthop lists for exported routes can turn over.
2260 */
2261 int rfapi_reopen(struct rfapi_descriptor *rfd, struct bgp *bgp)
2262 {
2263 struct rfapi *h;
2264 int rc;
2265
2266 if ((rc = rfapi_close_inner(rfd, bgp))) {
2267 return rc;
2268 }
2269 if ((rc = rfapi_open_rfd(rfd, bgp))) {
2270
2271 h = bgp->rfapi;
2272
2273 assert(h != NULL && !CHECK_FLAG(h->flags, RFAPI_INCALLBACK));
2274
2275 if (CHECK_FLAG(rfd->flags,
2276 RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY)
2277 && h && h->rfp_methods.close_cb) {
2278
2279 /*
2280 * NB RFAPI_INCALLBACK is tested above, so if we reach
2281 * this point
2282 * we are not already in the context of a callback.
2283 */
2284 h->flags |= RFAPI_INCALLBACK;
2285 (*h->rfp_methods.close_cb)((rfapi_handle)rfd, ESTALE);
2286 h->flags &= ~RFAPI_INCALLBACK;
2287 }
2288 return rc;
2289 }
2290 return 0;
2291 }
2292
2293 /***********************************************************************
2294 * NVE Routes
2295 ***********************************************************************/
2296 /*
2297 * Announce reachability to this prefix via the NVE
2298 */
2299 int rfapi_register(void *handle, struct rfapi_ip_prefix *prefix,
2300 uint32_t lifetime, /* host byte order */
2301 struct rfapi_un_option *options_un,
2302 struct rfapi_vn_option *options_vn,
2303 rfapi_register_action action)
2304 {
2305 struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
2306 struct bgp *bgp;
2307 struct prefix p;
2308 struct prefix *pfx_ip = NULL;
2309 struct prefix_rd prd;
2310 afi_t afi;
2311 struct prefix pfx_mac_buf;
2312 struct prefix *pfx_mac = NULL;
2313 struct prefix pfx_vn_buf;
2314 const char *action_str = NULL;
2315 uint32_t *label = NULL;
2316 struct rfapi_vn_option *vo;
2317 struct rfapi_l2address_option *l2o = NULL;
2318 struct prefix_rd *prd_override = NULL;
2319
2320 switch (action) {
2321 case RFAPI_REGISTER_ADD:
2322 action_str = "add";
2323 break;
2324 case RFAPI_REGISTER_WITHDRAW:
2325 action_str = "withdraw";
2326 break;
2327 case RFAPI_REGISTER_KILL:
2328 action_str = "kill";
2329 break;
2330 default:
2331 assert(0);
2332 break;
2333 }
2334
2335 /*
2336 * Inspect VN options
2337 */
2338 for (vo = options_vn; vo; vo = vo->next) {
2339 if (RFAPI_VN_OPTION_TYPE_L2ADDR == vo->type) {
2340 l2o = &vo->v.l2addr;
2341 }
2342 if (RFAPI_VN_OPTION_TYPE_INTERNAL_RD == vo->type) {
2343 prd_override = &vo->v.internal_rd;
2344 }
2345 }
2346
2347 /*********************************************************************
2348 * advertise prefix
2349 *********************************************************************/
2350
2351 /*
2352 * set <p> based on <prefix>
2353 */
2354 assert(!rfapiRprefix2Qprefix(prefix, &p));
2355
2356 afi = family2afi(prefix->prefix.addr_family);
2357 assert(afi);
2358
2359 vnc_zlog_debug_verbose(
2360 "%s(rfd=%p, pfx=%pFX, lifetime=%d, opts_un=%p, opts_vn=%p, action=%s)",
2361 __func__, rfd, &p, lifetime, options_un, options_vn,
2362 action_str);
2363
2364 /*
2365 * These tests come after the prefix conversion so that we can
2366 * print the prefix in a debug message before failing
2367 */
2368
2369 bgp = rfd->bgp;
2370 if (!bgp) {
2371 vnc_zlog_debug_verbose("%s: no BGP instance: returning ENXIO",
2372 __func__);
2373 return ENXIO;
2374 }
2375 if (!bgp->rfapi) {
2376 vnc_zlog_debug_verbose("%s: no RFAPI instance: returning ENXIO",
2377 __func__);
2378 return ENXIO;
2379 }
2380 if (!rfd->rfg) {
2381 if (RFAPI_REGISTER_ADD == action) {
2382 ++bgp->rfapi->stat.count_registrations_failed;
2383 }
2384 vnc_zlog_debug_verbose(
2385 "%s: rfd=%p, no RF GRP instance: returning ESTALE",
2386 __func__, rfd);
2387 return ESTALE;
2388 }
2389
2390 if (bgp->rfapi->flags & RFAPI_INCALLBACK) {
2391 if (RFAPI_REGISTER_ADD == action) {
2392 ++bgp->rfapi->stat.count_registrations_failed;
2393 }
2394 vnc_zlog_debug_verbose("%s: in callback: returning EDEADLK",
2395 __func__);
2396 return EDEADLK;
2397 }
2398
2399 if (!is_valid_rfd(rfd)) {
2400 if (RFAPI_REGISTER_ADD == action) {
2401 ++bgp->rfapi->stat.count_registrations_failed;
2402 }
2403 vnc_zlog_debug_verbose("%s: invalid handle: returning EBADF",
2404 __func__);
2405 return EBADF;
2406 }
2407
2408 /*
2409 * Is there a MAC address in this registration?
2410 */
2411 if (l2o && !RFAPI_0_ETHERADDR(&l2o->macaddr)) {
2412 rfapiL2o2Qprefix(l2o, &pfx_mac_buf);
2413 pfx_mac = &pfx_mac_buf;
2414 }
2415
2416 /*
2417 * Is there an IP prefix in this registration?
2418 */
2419 if (!(RFAPI_0_PREFIX(&p) && RFAPI_HOST_PREFIX(&p))) {
2420 pfx_ip = &p;
2421 } else {
2422 if (!pfx_mac) {
2423 vnc_zlog_debug_verbose(
2424 "%s: missing mac addr that is required for host 0 pfx",
2425 __func__);
2426 if (RFAPI_REGISTER_ADD == action) {
2427 ++bgp->rfapi->stat.count_registrations_failed;
2428 }
2429 return EINVAL;
2430 }
2431 if (rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn_buf)) {
2432 vnc_zlog_debug_verbose(
2433 "%s: handle has bad vn_addr: returning EBADF",
2434 __func__);
2435 if (RFAPI_REGISTER_ADD == action) {
2436 ++bgp->rfapi->stat.count_registrations_failed;
2437 }
2438 return EBADF;
2439 }
2440 }
2441
2442 if (RFAPI_REGISTER_ADD == action) {
2443 ++bgp->rfapi->stat.count_registrations;
2444 }
2445
2446 /*
2447 * Figure out if this registration is missing an IP address
2448 *
2449 * MAC-addr based:
2450 *
2451 * In RFAPI, we use prefixes in family AF_LINK to store
2452 * the MAC addresses. These prefixes are used for the
2453 * list of advertised prefixes and in the RFAPI import
2454 * tables.
2455 *
2456 * In BGP proper, we use the prefix matching the NVE's
2457 * VN address with a host prefix-length (i.e., 32 or 128).
2458 *
2459 */
2460 if (l2o && l2o->logical_net_id && RFAPI_0_PREFIX(&p)
2461 && RFAPI_HOST_PREFIX(&p)) {
2462
2463 rfapiL2o2Qprefix(l2o, &pfx_mac_buf);
2464 pfx_mac = &pfx_mac_buf;
2465 }
2466
2467 /*
2468 * Construct route distinguisher
2469 */
2470 if (prd_override) {
2471 prd = *prd_override;
2472 } else {
2473 memset(&prd, 0, sizeof(prd));
2474 if (pfx_mac) {
2475 prd.family = AF_UNSPEC;
2476 prd.prefixlen = 64;
2477 encode_rd_type(RD_TYPE_VNC_ETH, prd.val);
2478 if (l2o->local_nve_id
2479 || !(rfd->rfg->flags & RFAPI_RFG_L2RD)) {
2480 /*
2481 * If Local NVE ID is specified in message, use
2482 * it.
2483 * (if no local default configured, also use it
2484 * even if 0)
2485 */
2486 prd.val[1] = l2o->local_nve_id;
2487 } else {
2488 if (rfd->rfg->l2rd) {
2489 /*
2490 * locally-configured literal value
2491 */
2492 prd.val[1] = rfd->rfg->l2rd;
2493 } else {
2494 /*
2495 * 0 means auto:vn, which means use LSB
2496 * of VN addr
2497 */
2498 if (rfd->vn_addr.addr_family
2499 == AF_INET) {
2500 prd.val[1] =
2501 *(((char *)&rfd->vn_addr
2502 .addr.v4
2503 .s_addr)
2504 + 3);
2505 } else {
2506 prd.val[1] =
2507 *(((char *)&rfd->vn_addr
2508 .addr.v6
2509 .s6_addr)
2510 + 15);
2511 }
2512 }
2513 }
2514 memcpy(prd.val + 2, pfx_mac->u.prefix_eth.octet, 6);
2515 } else {
2516 prd = rfd->rd;
2517 prd.family = AF_UNSPEC;
2518 prd.prefixlen = 64;
2519 }
2520 }
2521
2522
2523 if (action == RFAPI_REGISTER_WITHDRAW
2524 || action == RFAPI_REGISTER_KILL) {
2525
2526 int adv_tunnel = 0;
2527
2528 /*
2529 * withdraw previous advertisement
2530 */
2531 del_vnc_route(
2532 rfd, rfd->peer, bgp, SAFI_MPLS_VPN,
2533 pfx_ip ? pfx_ip
2534 : &pfx_vn_buf, /* prefix being advertised */
2535 &prd, /* route distinguisher (0 for ENCAP) */
2536 ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL,
2537 action == RFAPI_REGISTER_KILL);
2538
2539 if (0 == rfapiApDelete(bgp, rfd, &p, pfx_mac, &prd,
2540 &adv_tunnel)) {
2541 if (adv_tunnel)
2542 rfapiTunnelRouteAnnounce(
2543 bgp, rfd, &rfd->max_prefix_lifetime);
2544 }
2545
2546 } else {
2547
2548 int adv_tunnel = 0;
2549 uint32_t local_pref;
2550 struct ecommunity *rtlist = NULL;
2551 struct ecommunity_val ecom_value;
2552
2553 if (!rfapiApCount(rfd)) {
2554 /*
2555 * make sure we advertise tunnel route upon adding the
2556 * first VPN route
2557 */
2558 adv_tunnel = 1;
2559 }
2560
2561 if (rfapiApAdd(bgp, rfd, &p, pfx_mac, &prd, lifetime,
2562 prefix->cost, l2o)) {
2563 adv_tunnel = 1;
2564 }
2565
2566 vnc_zlog_debug_verbose("%s: adv_tunnel = %d", __func__,
2567 adv_tunnel);
2568 if (adv_tunnel) {
2569 vnc_zlog_debug_verbose("%s: announcing tunnel route",
2570 __func__);
2571 rfapiTunnelRouteAnnounce(bgp, rfd,
2572 &rfd->max_prefix_lifetime);
2573 }
2574
2575 vnc_zlog_debug_verbose("%s: calling add_vnc_route", __func__);
2576
2577 local_pref = rfp_cost_to_localpref(prefix->cost);
2578
2579 if (l2o && l2o->label)
2580 label = &l2o->label;
2581
2582 if (pfx_mac) {
2583 struct ecommunity *l2com = NULL;
2584
2585 if (label) {
2586 l2com = bgp_rfapi_get_ecommunity_by_lni_label(
2587 bgp, 1, l2o->logical_net_id, *label);
2588 }
2589 if (l2com) {
2590 rtlist = ecommunity_dup(l2com);
2591 } else {
2592 /*
2593 * If mac address is set, add an RT based on the
2594 * registered LNI
2595 */
2596 memset((char *)&ecom_value, 0,
2597 sizeof(ecom_value));
2598 ecom_value.val[1] = ECOMMUNITY_ROUTE_TARGET;
2599 ecom_value.val[5] =
2600 (l2o->logical_net_id >> 16) & 0xff;
2601 ecom_value.val[6] =
2602 (l2o->logical_net_id >> 8) & 0xff;
2603 ecom_value.val[7] =
2604 (l2o->logical_net_id >> 0) & 0xff;
2605 rtlist = ecommunity_new();
2606 ecommunity_add_val(rtlist, &ecom_value,
2607 false, false);
2608 }
2609 if (l2o->tag_id) {
2610 as_t as = bgp->as;
2611 uint16_t val = l2o->tag_id;
2612 memset((char *)&ecom_value, 0,
2613 sizeof(ecom_value));
2614 ecom_value.val[1] = ECOMMUNITY_ROUTE_TARGET;
2615 if (as > BGP_AS_MAX) {
2616 ecom_value.val[0] =
2617 ECOMMUNITY_ENCODE_AS4;
2618 ecom_value.val[2] = (as >> 24) & 0xff;
2619 ecom_value.val[3] = (as >> 16) & 0xff;
2620 ecom_value.val[4] = (as >> 8) & 0xff;
2621 ecom_value.val[5] = as & 0xff;
2622 } else {
2623 ecom_value.val[0] =
2624 ECOMMUNITY_ENCODE_AS;
2625 ecom_value.val[2] = (as >> 8) & 0xff;
2626 ecom_value.val[3] = as & 0xff;
2627 }
2628 ecom_value.val[6] = (val >> 8) & 0xff;
2629 ecom_value.val[7] = val & 0xff;
2630 if (rtlist == NULL)
2631 rtlist = ecommunity_new();
2632 ecommunity_add_val(rtlist, &ecom_value,
2633 false, false);
2634 }
2635 }
2636
2637 /*
2638 * advertise prefix via tunnel endpoint
2639 */
2640 add_vnc_route(
2641 rfd, /* rfapi descr, for export list & backref */
2642 bgp, /* which bgp instance */
2643 SAFI_MPLS_VPN, /* which SAFI */
2644 (pfx_ip ? pfx_ip
2645 : &pfx_vn_buf), /* prefix being advertised */
2646 &prd, /* route distinguisher to use (0 for ENCAP) */
2647 &rfd->vn_addr, /* nexthop */
2648 &local_pref,
2649 &lifetime, /* prefix lifetime -> Tunnel Encap attr */
2650 NULL, options_un, /* rfapi un options */
2651 options_vn, /* rfapi vn options */
2652 (rtlist ? rtlist : rfd->rt_export_list), NULL, /* med */
2653 label, /* label: default */
2654 ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, 0);
2655
2656 if (rtlist)
2657 ecommunity_free(&rtlist); /* sets rtlist = NULL */
2658 }
2659
2660 vnc_zlog_debug_verbose("%s: success", __func__);
2661 return 0;
2662 }
2663
2664 int rfapi_query(void *handle, struct rfapi_ip_addr *target,
2665 struct rfapi_l2address_option *l2o, /* may be NULL */
2666 struct rfapi_next_hop_entry **ppNextHopEntry)
2667 {
2668 struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
2669 struct bgp *bgp = rfd->bgp;
2670 int rc;
2671
2672 assert(ppNextHopEntry);
2673 *ppNextHopEntry = NULL;
2674
2675 if (bgp && bgp->rfapi) {
2676 bgp->rfapi->stat.count_queries++;
2677 }
2678
2679 if (!rfd->rfg) {
2680 if (bgp && bgp->rfapi)
2681 ++bgp->rfapi->stat.count_queries_failed;
2682 return ESTALE;
2683 }
2684
2685 if ((rc = rfapi_query_inner(handle, target, l2o, ppNextHopEntry))) {
2686 if (bgp && bgp->rfapi)
2687 ++bgp->rfapi->stat.count_queries_failed;
2688 }
2689 return rc;
2690 }
2691
2692 int rfapi_query_done(rfapi_handle handle, struct rfapi_ip_addr *target)
2693 {
2694 struct prefix p;
2695 int rc;
2696 struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
2697 struct bgp *bgp = rfd->bgp;
2698
2699 if (!rfd->rfg)
2700 return ESTALE;
2701
2702 assert(target);
2703 rc = rfapiRaddr2Qprefix(target, &p);
2704 assert(!rc);
2705
2706 if (!is_valid_rfd(rfd))
2707 return EBADF;
2708
2709 /* preemptive */
2710 if (!bgp || !bgp->rfapi)
2711 return ENXIO;
2712
2713 if (bgp->rfapi->flags & RFAPI_INCALLBACK)
2714 return EDEADLK;
2715
2716 rfapiMonitorDel(bgp, rfd, &p);
2717
2718 return 0;
2719 }
2720
2721 int rfapi_query_done_all(rfapi_handle handle, int *count)
2722 {
2723 struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
2724 struct bgp *bgp = rfd->bgp;
2725 ;
2726 int num;
2727
2728 if (!rfd->rfg)
2729 return ESTALE;
2730
2731 if (!is_valid_rfd(rfd))
2732 return EBADF;
2733
2734 /* preemptive */
2735 if (!bgp || !bgp->rfapi)
2736 return ENXIO;
2737
2738 if (bgp->rfapi->flags & RFAPI_INCALLBACK)
2739 return EDEADLK;
2740
2741 num = rfapiMonitorDelHd(rfd);
2742
2743 if (count)
2744 *count = num;
2745
2746 return 0;
2747 }
2748
2749 void rfapi_free_next_hop_list(struct rfapi_next_hop_entry *list)
2750 {
2751 struct rfapi_next_hop_entry *nh;
2752 struct rfapi_next_hop_entry *next;
2753
2754 for (nh = list; nh; nh = next) {
2755 next = nh->next;
2756 rfapi_un_options_free(nh->un_options);
2757 nh->un_options = NULL;
2758 rfapi_vn_options_free(nh->vn_options);
2759 nh->vn_options = NULL;
2760 XFREE(MTYPE_RFAPI_NEXTHOP, nh);
2761 }
2762 }
2763
2764 /*
2765 * NULL handle => return total count across all nves
2766 */
2767 uint32_t rfapi_monitor_count(void *handle)
2768 {
2769 struct bgp *bgp = bgp_get_default();
2770 uint32_t count;
2771
2772 if (handle) {
2773 struct rfapi_descriptor *rfd =
2774 (struct rfapi_descriptor *)handle;
2775 count = rfd->monitor_count;
2776 } else {
2777
2778 if (!bgp || !bgp->rfapi)
2779 return 0;
2780
2781 count = bgp->rfapi->monitor_count;
2782 }
2783
2784 return count;
2785 }
2786
2787 /***********************************************************************
2788 * CLI/CONFIG
2789 ***********************************************************************/
2790
2791 DEFUN (debug_rfapi_show_nves,
2792 debug_rfapi_show_nves_cmd,
2793 "debug rfapi-dev show nves",
2794 DEBUG_STR
2795 DEBUG_RFAPI_STR
2796 SHOW_STR
2797 "NVE Information\n")
2798 {
2799 rfapiPrintMatchingDescriptors(vty, NULL, NULL);
2800 return CMD_SUCCESS;
2801 }
2802
2803 DEFUN (
2804 debug_rfapi_show_nves_vn_un,
2805 debug_rfapi_show_nves_vn_un_cmd,
2806 "debug rfapi-dev show nves <vn|un> <A.B.C.D|X:X::X:X>", /* prefix also ok */
2807 DEBUG_STR
2808 DEBUG_RFAPI_STR
2809 SHOW_STR
2810 "NVE Information\n"
2811 "Specify virtual network\n"
2812 "Specify underlay network interface\n"
2813 "IPv4 address\n"
2814 "IPv6 address\n")
2815 {
2816 struct prefix pfx;
2817
2818 if (!str2prefix(argv[5]->arg, &pfx)) {
2819 vty_out(vty, "Malformed address \"%s\"\n", argv[5]->arg);
2820 return CMD_WARNING_CONFIG_FAILED;
2821 }
2822 if (pfx.family != AF_INET && pfx.family != AF_INET6) {
2823 vty_out(vty, "Invalid address \"%s\"\n", argv[5]->arg);
2824 return CMD_WARNING_CONFIG_FAILED;
2825 }
2826
2827 if (argv[4]->arg[0] == 'u') {
2828 rfapiPrintMatchingDescriptors(vty, NULL, &pfx);
2829 } else {
2830 rfapiPrintMatchingDescriptors(vty, &pfx, NULL);
2831 }
2832 return CMD_SUCCESS;
2833 }
2834
2835 /*
2836 * Note: this function does not flush vty output, so if it is called
2837 * with a stream pointing to a vty, the user will have to type something
2838 * before the callback output shows up
2839 */
2840 static void test_nexthops_callback(
2841 // struct rfapi_ip_addr *target,
2842 struct rfapi_next_hop_entry *next_hops, void *userdata)
2843 {
2844 void *stream = userdata;
2845
2846 int (*fp)(void *, const char *, ...);
2847 struct vty *vty;
2848 void *out;
2849 const char *vty_newline;
2850
2851 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
2852 return;
2853
2854 fp(out, "Nexthops Callback, Target=(");
2855 // rfapiPrintRfapiIpAddr(stream, target);
2856 fp(out, ")\n");
2857
2858 rfapiPrintNhl(stream, next_hops);
2859
2860 fp(out, "\n");
2861
2862 rfapi_free_next_hop_list(next_hops);
2863 }
2864
2865 DEFUN (debug_rfapi_open,
2866 debug_rfapi_open_cmd,
2867 "debug rfapi-dev open vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2868 DEBUG_STR
2869 DEBUG_RFAPI_STR
2870 "rfapi_open\n"
2871 "indicate vn addr follows\n"
2872 "virtual network interface IPv4 address\n"
2873 "virtual network interface IPv6 address\n"
2874 "indicate xt addr follows\n"
2875 "underlay network interface IPv4 address\n"
2876 "underlay network interface IPv6 address\n")
2877 {
2878 struct rfapi_ip_addr vn;
2879 struct rfapi_ip_addr un;
2880 uint32_t lifetime = 0;
2881 int rc;
2882 rfapi_handle handle;
2883
2884 /*
2885 * Get VN addr
2886 */
2887 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
2888 return rc;
2889
2890 /*
2891 * Get UN addr
2892 */
2893 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
2894 return rc;
2895
2896 rc = rfapi_open(rfapi_get_rfp_start_val_by_bgp(bgp_get_default()), &vn,
2897 &un, /*&uo */ NULL, &lifetime, NULL, &handle);
2898
2899 vty_out(vty, "rfapi_open: status %d, handle %p, lifetime %d\n", rc,
2900 handle, lifetime);
2901
2902 rc = rfapi_set_response_cb(handle, test_nexthops_callback);
2903
2904 vty_out(vty, "rfapi_set_response_cb: status %d\n", rc);
2905
2906 return CMD_SUCCESS;
2907 }
2908
2909
2910 DEFUN (debug_rfapi_close_vn_un,
2911 debug_rfapi_close_vn_un_cmd,
2912 "debug rfapi-dev close vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2913 DEBUG_STR
2914 DEBUG_RFAPI_STR
2915 "rfapi_close\n"
2916 "indicate vn addr follows\n"
2917 "virtual network interface IPv4 address\n"
2918 "virtual network interface IPv6 address\n"
2919 "indicate xt addr follows\n"
2920 "underlay network interface IPv4 address\n"
2921 "underlay network interface IPv6 address\n")
2922 {
2923 struct rfapi_ip_addr vn;
2924 struct rfapi_ip_addr un;
2925 rfapi_handle handle;
2926 int rc;
2927
2928 /*
2929 * Get VN addr
2930 */
2931 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
2932 return rc;
2933
2934
2935 /*
2936 * Get UN addr
2937 */
2938 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
2939 return rc;
2940
2941
2942 if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
2943 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
2944 argv[4]->arg, argv[6]->arg);
2945 return CMD_WARNING_CONFIG_FAILED;
2946 }
2947
2948 rc = rfapi_close(handle);
2949
2950 vty_out(vty, "rfapi_close(handle=%p): status %d\n", handle, rc);
2951
2952 return CMD_SUCCESS;
2953 }
2954
2955 DEFUN (debug_rfapi_close_rfd,
2956 debug_rfapi_close_rfd_cmd,
2957 "debug rfapi-dev close rfd HANDLE",
2958 DEBUG_STR
2959 DEBUG_RFAPI_STR
2960 "rfapi_close\n"
2961 "indicate handle follows\n" "rfapi handle in hexadecimal\n")
2962 {
2963 rfapi_handle handle;
2964 int rc;
2965 char *endptr = NULL;
2966
2967 handle = (rfapi_handle)(uintptr_t)(strtoull(argv[4]->arg, &endptr, 16));
2968
2969 if (*endptr != '\0' || (uintptr_t)handle == UINTPTR_MAX) {
2970 vty_out(vty, "Invalid value: %s\n", argv[4]->arg);
2971 return CMD_WARNING_CONFIG_FAILED;
2972 }
2973
2974 rc = rfapi_close(handle);
2975
2976 vty_out(vty, "rfapi_close(handle=%p): status %d\n", handle, rc);
2977
2978 return CMD_SUCCESS;
2979 }
2980
2981 DEFUN (debug_rfapi_register_vn_un,
2982 debug_rfapi_register_vn_un_cmd,
2983 "debug rfapi-dev register vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> lifetime SECONDS [cost (0-255)]",
2984 DEBUG_STR
2985 DEBUG_RFAPI_STR
2986 "rfapi_register\n"
2987 "indicate vn addr follows\n"
2988 "virtual network IPv4 interface address\n"
2989 "virtual network IPv6 interface address\n"
2990 "indicate un addr follows\n"
2991 "underlay network IPv4 interface address\n"
2992 "underlay network IPv6 interface address\n"
2993 "indicate prefix follows\n"
2994 "IPv4 prefix\n"
2995 "IPv6 prefix\n"
2996 "indicate lifetime follows\n"
2997 "lifetime\n"
2998 "Cost (localpref = 255-cost)\n"
2999 "0-255\n")
3000 {
3001 struct rfapi_ip_addr vn;
3002 struct rfapi_ip_addr un;
3003 rfapi_handle handle;
3004 struct prefix pfx;
3005 uint32_t lifetime;
3006 struct rfapi_ip_prefix hpfx;
3007 int rc;
3008 uint8_t cost = 100;
3009
3010 /*
3011 * Get VN addr
3012 */
3013 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
3014 return rc;
3015
3016
3017 /*
3018 * Get UN addr
3019 */
3020 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
3021 return rc;
3022
3023
3024 if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3025 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3026 argv[4]->arg, argv[6]->arg);
3027 return CMD_WARNING_CONFIG_FAILED;
3028 }
3029
3030 /*
3031 * Get prefix to advertise
3032 */
3033 if (!str2prefix(argv[8]->arg, &pfx)) {
3034 vty_out(vty, "Malformed prefix \"%s\"\n", argv[8]->arg);
3035 return CMD_WARNING_CONFIG_FAILED;
3036 }
3037 if (pfx.family != AF_INET && pfx.family != AF_INET6) {
3038 vty_out(vty, "Bad family for prefix \"%s\"\n", argv[8]->arg);
3039 return CMD_WARNING_CONFIG_FAILED;
3040 }
3041 rfapiQprefix2Rprefix(&pfx, &hpfx);
3042
3043 if (strmatch(argv[10]->text, "infinite")) {
3044 lifetime = RFAPI_INFINITE_LIFETIME;
3045 } else {
3046 lifetime = strtoul(argv[10]->arg, NULL, 10);
3047 }
3048
3049 if (argc >= 13)
3050 cost = (uint8_t) strtoul(argv[12]->arg, NULL, 10);
3051 hpfx.cost = cost;
3052
3053 rc = rfapi_register(handle, &hpfx, lifetime, NULL, NULL,
3054 RFAPI_REGISTER_ADD);
3055 if (rc) {
3056 vty_out(vty, "rfapi_register failed with rc=%d (%s)\n", rc,
3057 strerror(rc));
3058 }
3059
3060 return CMD_SUCCESS;
3061 }
3062
3063 DEFUN (debug_rfapi_register_vn_un_l2o,
3064 debug_rfapi_register_vn_un_l2o_cmd,
3065 "debug rfapi-dev register vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> lifetime SECONDS macaddr X:X:X:X:X:X lni (0-16777215)",
3066 DEBUG_STR
3067 DEBUG_RFAPI_STR
3068 "rfapi_register\n"
3069 "indicate vn addr follows\n"
3070 "virtual network IPv4 interface address\n"
3071 "virtual network IPv6 interface address\n"
3072 "indicate un addr follows\n"
3073 "underlay network IPv4 interface address\n"
3074 "underlay network IPv6 interface address\n"
3075 "indicate prefix follows\n"
3076 "IPv4 prefix\n"
3077 "IPv6 prefix\n"
3078 "indicate lifetime follows\n"
3079 "Seconds of lifetime\n"
3080 "indicate MAC address follows\n"
3081 "MAC address\n"
3082 "indicate lni follows\n"
3083 "lni value range\n")
3084 {
3085 struct rfapi_ip_addr vn;
3086 struct rfapi_ip_addr un;
3087 rfapi_handle handle;
3088 struct prefix pfx;
3089 uint32_t lifetime;
3090 struct rfapi_ip_prefix hpfx;
3091 int rc;
3092 struct rfapi_vn_option optary[10]; /* XXX must be big enough */
3093 struct rfapi_vn_option *opt = NULL;
3094 int opt_next = 0;
3095
3096 /*
3097 * Get VN addr
3098 */
3099 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
3100 return rc;
3101
3102
3103 /*
3104 * Get UN addr
3105 */
3106 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
3107 return rc;
3108
3109
3110 if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3111 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3112 argv[4]->arg, argv[6]->arg);
3113 return CMD_WARNING_CONFIG_FAILED;
3114 }
3115
3116 /*
3117 * Get prefix to advertise
3118 */
3119 if (!str2prefix(argv[8]->arg, &pfx)) {
3120 vty_out(vty, "Malformed prefix \"%s\"\n", argv[8]->arg);
3121 return CMD_WARNING_CONFIG_FAILED;
3122 }
3123 if (pfx.family != AF_INET && pfx.family != AF_INET6) {
3124 vty_out(vty, "Bad family for prefix \"%s\"\n", argv[8]->arg);
3125 return CMD_WARNING_CONFIG_FAILED;
3126 }
3127 rfapiQprefix2Rprefix(&pfx, &hpfx);
3128
3129 if (strmatch(argv[10]->text, "infinite")) {
3130 lifetime = RFAPI_INFINITE_LIFETIME;
3131 } else {
3132 lifetime = strtoul(argv[10]->arg, NULL, 10);
3133 }
3134
3135 /* L2 option parsing START */
3136 memset(optary, 0, sizeof(optary));
3137 optary[opt_next].v.l2addr.logical_net_id =
3138 strtoul(argv[14]->arg, NULL, 10);
3139 if (rfapiStr2EthAddr(argv[12]->arg,
3140 &optary[opt_next].v.l2addr.macaddr)) {
3141 vty_out(vty, "Bad mac address \"%s\"\n", argv[12]->arg);
3142 return CMD_WARNING_CONFIG_FAILED;
3143 }
3144 optary[opt_next].type = RFAPI_VN_OPTION_TYPE_L2ADDR;
3145 opt = optary;
3146
3147 /* L2 option parsing END */
3148
3149 /* TBD fixme */
3150 rc = rfapi_register(handle, &hpfx, lifetime, NULL /* &uo */, opt,
3151 RFAPI_REGISTER_ADD);
3152 if (rc) {
3153 vty_out(vty, "rfapi_register failed with rc=%d (%s)\n", rc,
3154 strerror(rc));
3155 }
3156
3157 return CMD_SUCCESS;
3158 }
3159
3160
3161 DEFUN (debug_rfapi_unregister_vn_un,
3162 debug_rfapi_unregister_vn_un_cmd,
3163 "debug rfapi-dev unregister vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> [kill]",
3164 DEBUG_STR
3165 DEBUG_RFAPI_STR
3166 "rfapi_unregister\n"
3167 "indicate vn addr follows\n"
3168 "virtual network interface address\n"
3169 "virtual network interface address\n"
3170 "indicate xt addr follows\n"
3171 "underlay network interface address\n"
3172 "underlay network interface address\n"
3173 "prefix to remove\n"
3174 "prefix to remove\n"
3175 "prefix to remove\n"
3176 "Remove without holddown\n")
3177 {
3178 struct rfapi_ip_addr vn;
3179 struct rfapi_ip_addr un;
3180 rfapi_handle handle;
3181 struct prefix pfx;
3182 struct rfapi_ip_prefix hpfx;
3183 int rc;
3184
3185 /*
3186 * Get VN addr
3187 */
3188 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
3189 return rc;
3190
3191 /*
3192 * Get UN addr
3193 */
3194 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
3195 return rc;
3196
3197
3198 if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3199 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3200 argv[4]->arg, argv[6]->arg);
3201 return CMD_WARNING_CONFIG_FAILED;
3202 }
3203
3204 /*
3205 * Get prefix to advertise
3206 */
3207 if (!str2prefix(argv[8]->arg, &pfx)) {
3208 vty_out(vty, "Malformed prefix \"%s\"\n", argv[8]->arg);
3209 return CMD_WARNING_CONFIG_FAILED;
3210 }
3211 if (pfx.family != AF_INET && pfx.family != AF_INET6) {
3212 vty_out(vty, "Bad family for prefix \"%s\"\n", argv[8]->arg);
3213 return CMD_WARNING_CONFIG_FAILED;
3214 }
3215 rfapiQprefix2Rprefix(&pfx, &hpfx);
3216
3217 rfapi_register(handle, &hpfx, 0, NULL, NULL,
3218 (argc == 10 ?
3219 RFAPI_REGISTER_KILL : RFAPI_REGISTER_WITHDRAW));
3220
3221 return CMD_SUCCESS;
3222 }
3223
3224 DEFUN (debug_rfapi_query_vn_un,
3225 debug_rfapi_query_vn_un_cmd,
3226 "debug rfapi-dev query vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> target <A.B.C.D|X:X::X:X>",
3227 DEBUG_STR
3228 DEBUG_RFAPI_STR
3229 "rfapi_query\n"
3230 "indicate vn addr follows\n"
3231 "virtual network interface IPv4 address\n"
3232 "virtual network interface IPv6 address\n"
3233 "indicate un addr follows\n"
3234 "IPv4 un address\n"
3235 "IPv6 un address\n"
3236 "indicate target follows\n"
3237 "target IPv4 address\n"
3238 "target IPv6 address\n")
3239 {
3240 struct rfapi_ip_addr vn;
3241 struct rfapi_ip_addr un;
3242 struct rfapi_ip_addr target;
3243 rfapi_handle handle;
3244 int rc;
3245 struct rfapi_next_hop_entry *pNextHopEntry;
3246
3247 /*
3248 * Get VN addr
3249 */
3250 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
3251 return rc;
3252
3253
3254 /*
3255 * Get UN addr
3256 */
3257 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
3258 return rc;
3259
3260
3261 /*
3262 * Get target addr
3263 */
3264 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[8]->arg, &target)))
3265 return rc;
3266
3267
3268 if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3269 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3270 argv[4]->arg, argv[6]->arg);
3271 return CMD_WARNING_CONFIG_FAILED;
3272 }
3273
3274 /*
3275 * options parameter not used? Set to NULL for now
3276 */
3277 rc = rfapi_query(handle, &target, NULL, &pNextHopEntry);
3278
3279 if (rc) {
3280 vty_out(vty, "rfapi_query failed with rc=%d (%s)\n", rc,
3281 strerror(rc));
3282 } else {
3283 /*
3284 * print nexthop list
3285 */
3286 test_nexthops_callback(/*&target, */ pNextHopEntry,
3287 vty); /* frees nh list! */
3288 }
3289
3290 return CMD_SUCCESS;
3291 }
3292
3293
3294 DEFUN (debug_rfapi_query_vn_un_l2o,
3295 debug_rfapi_query_vn_un_l2o_cmd,
3296 "debug rfapi-dev query vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lni LNI target X:X:X:X:X:X",
3297 DEBUG_STR
3298 DEBUG_RFAPI_STR
3299 "rfapi_query\n"
3300 "indicate vn addr follows\n"
3301 "virtual network interface IPv4 address\n"
3302 "virtual network interface IPv6 address\n"
3303 "indicate xt addr follows\n"
3304 "underlay network interface IPv4 address\n"
3305 "underlay network interface IPv6 address\n"
3306 "logical network ID follows\n"
3307 "logical network ID\n"
3308 "indicate target MAC addr follows\n"
3309 "target MAC addr\n")
3310 {
3311 struct rfapi_ip_addr vn;
3312 struct rfapi_ip_addr un;
3313 int rc;
3314
3315 /*
3316 * Get VN addr
3317 */
3318 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
3319 return rc;
3320
3321
3322 /*
3323 * Get UN addr
3324 */
3325 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
3326 return rc;
3327
3328 vty_out(vty, "%% This command is broken.\n");
3329 return CMD_WARNING_CONFIG_FAILED;
3330 }
3331
3332
3333 DEFUN (debug_rfapi_query_done_vn_un,
3334 debug_rfapi_query_vn_un_done_cmd,
3335 "debug rfapi-dev query done vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> target <A.B.C.D|X:X::X:X>",
3336 DEBUG_STR
3337 DEBUG_RFAPI_STR
3338 "rfapi_query_done\n"
3339 "rfapi_query_done\n"
3340 "indicate vn addr follows\n"
3341 "virtual network interface IPv4 address\n"
3342 "virtual network interface IPv6 address\n"
3343 "indicate xt addr follows\n"
3344 "underlay network interface IPv4 address\n"
3345 "underlay network interface IPv6 address\n"
3346 "indicate target follows\n"
3347 "Target IPv4 address\n"
3348 "Target IPv6 address\n")
3349 {
3350 struct rfapi_ip_addr vn;
3351 struct rfapi_ip_addr un;
3352 struct rfapi_ip_addr target;
3353 rfapi_handle handle;
3354 int rc;
3355
3356 /*
3357 * Get VN addr
3358 */
3359 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[5]->arg, &vn)))
3360 return rc;
3361
3362
3363 /*
3364 * Get UN addr
3365 */
3366 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[7]->arg, &un)))
3367 return rc;
3368
3369
3370 /*
3371 * Get target addr
3372 */
3373 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[9]->arg, &target)))
3374 return rc;
3375
3376
3377 if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3378 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3379 argv[5]->arg, argv[7]->arg);
3380 return CMD_WARNING_CONFIG_FAILED;
3381 }
3382
3383 /*
3384 * options parameter not used? Set to NULL for now
3385 */
3386 rc = rfapi_query_done(handle, &target);
3387
3388 vty_out(vty, "rfapi_query_done returned %d\n", rc);
3389
3390 return CMD_SUCCESS;
3391 }
3392
3393 DEFUN (debug_rfapi_show_import,
3394 debug_rfapi_show_import_cmd,
3395 "debug rfapi-dev show import",
3396 DEBUG_STR
3397 DEBUG_RFAPI_STR
3398 SHOW_STR
3399 "import\n")
3400 {
3401 struct bgp *bgp;
3402 struct rfapi *h;
3403 struct rfapi_import_table *it;
3404 char *s;
3405 int first_l2 = 1;
3406
3407 /*
3408 * Show all import tables
3409 */
3410
3411 bgp = bgp_get_default(); /* assume 1 instance for now */
3412 if (!bgp) {
3413 vty_out(vty, "No BGP instance\n");
3414 return CMD_WARNING_CONFIG_FAILED;
3415 }
3416
3417 h = bgp->rfapi;
3418 if (!h) {
3419 vty_out(vty, "No RFAPI instance\n");
3420 return CMD_WARNING_CONFIG_FAILED;
3421 }
3422
3423 /*
3424 * Iterate over all import tables; do a filtered import
3425 * for the afi/safi combination
3426 */
3427
3428
3429 for (it = h->imports; it; it = it->next) {
3430 s = ecommunity_ecom2str(it->rt_import_list,
3431 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
3432 vty_out(vty, "Import Table %p, RTs: %s\n", it, s);
3433 XFREE(MTYPE_ECOMMUNITY_STR, s);
3434
3435 rfapiShowImportTable(vty, "IP VPN", it->imported_vpn[AFI_IP],
3436 1);
3437 rfapiShowImportTable(vty, "IP ENCAP",
3438 it->imported_encap[AFI_IP], 0);
3439 rfapiShowImportTable(vty, "IP6 VPN", it->imported_vpn[AFI_IP6],
3440 1);
3441 rfapiShowImportTable(vty, "IP6 ENCAP",
3442 it->imported_encap[AFI_IP6], 0);
3443 }
3444
3445 if (h->import_mac) {
3446 void *cursor = NULL;
3447 uint32_t lni;
3448 uintptr_t lni_as_ptr;
3449 int rc;
3450 char buf[BUFSIZ];
3451
3452 for (rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr,
3453 (void **)&it, &cursor);
3454 !rc;
3455 rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr,
3456 (void **)&it, &cursor)) {
3457
3458 if (it->imported_vpn[AFI_L2VPN]) {
3459 lni = lni_as_ptr;
3460 if (first_l2) {
3461 vty_out(vty,
3462 "\nLNI-based Ethernet Tables:\n");
3463 first_l2 = 0;
3464 }
3465 snprintf(buf, sizeof(buf), "L2VPN LNI=%u", lni);
3466 rfapiShowImportTable(
3467 vty, buf, it->imported_vpn[AFI_L2VPN],
3468 1);
3469 }
3470 }
3471 }
3472
3473 rfapiShowImportTable(vty, "CE IT - IP VPN",
3474 h->it_ce->imported_vpn[AFI_IP], 1);
3475
3476 return CMD_SUCCESS;
3477 }
3478
3479 DEFUN (debug_rfapi_show_import_vn_un,
3480 debug_rfapi_show_import_vn_un_cmd,
3481 "debug rfapi-dev show import vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
3482 DEBUG_STR
3483 DEBUG_RFAPI_STR
3484 SHOW_STR
3485 "import\n"
3486 "indicate vn addr follows\n"
3487 "virtual network interface IPv4 address\n"
3488 "virtual network interface IPv6 address\n"
3489 "indicate xt addr follows\n"
3490 "underlay network interface IPv4 address\n"
3491 "underlay network interface IPv6 address\n")
3492 {
3493 struct rfapi_ip_addr vn;
3494 struct rfapi_ip_addr un;
3495 rfapi_handle handle;
3496 int rc;
3497 struct rfapi_descriptor *rfd;
3498
3499 /*
3500 * Get VN addr
3501 */
3502 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[5]->arg, &vn)))
3503 return rc;
3504
3505
3506 /*
3507 * Get UN addr
3508 */
3509 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[7]->arg, &un)))
3510 return rc;
3511
3512
3513 if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3514 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3515 argv[5]->arg, argv[7]->arg);
3516 return CMD_WARNING_CONFIG_FAILED;
3517 }
3518
3519 rfd = (struct rfapi_descriptor *)handle;
3520
3521 rfapiShowImportTable(vty, "IP VPN",
3522 rfd->import_table->imported_vpn[AFI_IP], 1);
3523 rfapiShowImportTable(vty, "IP ENCAP",
3524 rfd->import_table->imported_encap[AFI_IP], 0);
3525 rfapiShowImportTable(vty, "IP6 VPN",
3526 rfd->import_table->imported_vpn[AFI_IP6], 1);
3527 rfapiShowImportTable(vty, "IP6 ENCAP",
3528 rfd->import_table->imported_encap[AFI_IP6], 0);
3529
3530 return CMD_SUCCESS;
3531 }
3532
3533 DEFUN (debug_rfapi_response_omit_self,
3534 debug_rfapi_response_omit_self_cmd,
3535 "debug rfapi-dev response-omit-self <on|off>",
3536 DEBUG_STR
3537 DEBUG_RFAPI_STR
3538 "Omit self in RFP responses\n"
3539 "filter out self from responses\n" "leave self in responses\n")
3540 {
3541 struct bgp *bgp = bgp_get_default();
3542
3543 if (!bgp) {
3544 vty_out(vty, "No BGP process is configured\n");
3545 return CMD_WARNING_CONFIG_FAILED;
3546 }
3547 if (!bgp->rfapi_cfg) {
3548 vty_out(vty, "VNC not configured\n");
3549 return CMD_WARNING_CONFIG_FAILED;
3550 }
3551
3552 if (strmatch(argv[3]->text, "on"))
3553 SET_FLAG(bgp->rfapi_cfg->flags,
3554 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP);
3555 else
3556 UNSET_FLAG(bgp->rfapi_cfg->flags,
3557 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP);
3558
3559 return CMD_SUCCESS;
3560 }
3561
3562
3563 #ifdef RFAPI_DEBUG_SKIPLIST_CLI
3564
3565 #include "lib/skiplist.h"
3566 DEFUN (skiplist_test_cli,
3567 skiplist_test_cli_cmd,
3568 "skiplist test",
3569 "skiplist command\n"
3570 "test\n")
3571 {
3572 skiplist_test(vty);
3573
3574 return CMD_SUCCESS;
3575 }
3576
3577 DEFUN (skiplist_debug_cli,
3578 skiplist_debug_cli_cmd,
3579 "skiplist debug",
3580 "skiplist command\n"
3581 "debug\n")
3582 {
3583 skiplist_debug(vty, NULL);
3584 return CMD_SUCCESS;
3585 }
3586
3587 #endif /* RFAPI_DEBUG_SKIPLIST_CLI */
3588
3589 void rfapi_init(void)
3590 {
3591 bgp_rfapi_cfg_init();
3592 vnc_debug_init();
3593
3594 install_element(ENABLE_NODE, &debug_rfapi_show_import_cmd);
3595 install_element(ENABLE_NODE, &debug_rfapi_show_import_vn_un_cmd);
3596
3597 install_element(ENABLE_NODE, &debug_rfapi_open_cmd);
3598 install_element(ENABLE_NODE, &debug_rfapi_close_vn_un_cmd);
3599 install_element(ENABLE_NODE, &debug_rfapi_close_rfd_cmd);
3600 install_element(ENABLE_NODE, &debug_rfapi_register_vn_un_cmd);
3601 install_element(ENABLE_NODE, &debug_rfapi_unregister_vn_un_cmd);
3602 install_element(ENABLE_NODE, &debug_rfapi_query_vn_un_cmd);
3603 install_element(ENABLE_NODE, &debug_rfapi_query_vn_un_done_cmd);
3604 install_element(ENABLE_NODE, &debug_rfapi_query_vn_un_l2o_cmd);
3605
3606 install_element(ENABLE_NODE, &debug_rfapi_response_omit_self_cmd);
3607
3608 /* Need the following show commands for gpz test scripts */
3609 install_element(ENABLE_NODE, &debug_rfapi_show_nves_cmd);
3610 install_element(ENABLE_NODE, &debug_rfapi_show_nves_vn_un_cmd);
3611 install_element(ENABLE_NODE, &debug_rfapi_register_vn_un_l2o_cmd);
3612
3613 #ifdef RFAPI_DEBUG_SKIPLIST_CLI
3614 install_element(ENABLE_NODE, &skiplist_test_cli_cmd);
3615 install_element(ENABLE_NODE, &skiplist_debug_cli_cmd);
3616 #endif
3617
3618 rfapi_vty_init();
3619 }
3620
3621 #ifdef DEBUG_RFAPI
3622 static void rfapi_print_exported(struct bgp *bgp)
3623 {
3624 struct bgp_dest *destn;
3625 struct bgp_dest *dest;
3626 struct bgp_path_info *bpi;
3627
3628 if (!bgp)
3629 return;
3630
3631 for (destn = bgp_table_top(bgp->rib[AFI_IP][SAFI_MPLS_VPN]); destn;
3632 destn = bgp_route_next(destn)) {
3633 struct bgp_table *table;
3634
3635 table = bgp_dest_get_bgp_table_info(destn);
3636 if (!table)
3637 continue;
3638 fprintf(stderr, "%s: vpn destn=%p\n", __func__, destn);
3639 for (dest = bgp_table_top(table); dest;
3640 dest = bgp_route_next(dest)) {
3641 bpi = bgp_dest_get_bgp_path_info(dest);
3642
3643 if (!bpi)
3644 continue;
3645 fprintf(stderr, "%s: dest=%p\n", __func__, dest);
3646 for (; bpi; bpi = bpi->next) {
3647 rfapiPrintBi((void *)2, bpi); /* 2 => stderr */
3648 }
3649 }
3650 }
3651 for (destn = bgp_table_top(bgp->rib[AFI_IP][SAFI_ENCAP]); destn;
3652 destn = bgp_route_next(destn)) {
3653 struct bgp_table *table;
3654
3655 table = bgp_dest_get_bgp_table_info(destn);
3656 if (!table)
3657 continue;
3658 fprintf(stderr, "%s: encap destn=%p\n", __func__, destn);
3659 for (dest = bgp_table_top(table); dest;
3660 dest = bgp_route_next(dest)) {
3661 bpi = bgp_dest_get_bgp_path_info(dest);
3662 if (!bpi)
3663 continue;
3664 fprintf(stderr, "%s: dest=%p\n", __func__, dest);
3665 for (; bpi; bpi = bpi->next) {
3666 rfapiPrintBi((void *)2, bpi); /* 2 => stderr */
3667 }
3668 }
3669 }
3670 }
3671 #endif /* defined(DEBUG_RFAPI) */
3672
3673 /*
3674 * Free all memory to prepare for clean exit as seen by valgrind memcheck
3675 */
3676 void rfapi_delete(struct bgp *bgp)
3677 {
3678 extern void rfp_clear_vnc_nve_all(void); /* can't fix correctly yet */
3679
3680 /*
3681 * This clears queries and registered routes, and closes nves
3682 */
3683 if (bgp->rfapi)
3684 rfp_clear_vnc_nve_all();
3685 bgp_rfapi_cfg_destroy(bgp, bgp->rfapi_cfg);
3686 bgp->rfapi_cfg = NULL;
3687 bgp_rfapi_destroy(bgp, bgp->rfapi);
3688 bgp->rfapi = NULL;
3689 #ifdef DEBUG_RFAPI
3690 /*
3691 * show what's left in the BGP MPLSVPN RIB
3692 */
3693 rfapi_print_exported(bgp);
3694 #endif
3695 }
3696
3697 int rfapi_set_autord_from_vn(struct prefix_rd *rd, struct rfapi_ip_addr *vn)
3698 {
3699 vnc_zlog_debug_verbose("%s: auto-assigning RD", __func__);
3700 if (vn->addr_family != AF_INET && vn->addr_family != AF_INET6) {
3701 vnc_zlog_debug_verbose(
3702 "%s: can't auto-assign RD, VN addr family is not IPv4|v6",
3703 __func__);
3704 return EAFNOSUPPORT;
3705 }
3706 rd->family = AF_UNSPEC;
3707 rd->prefixlen = 64;
3708 rd->val[1] = RD_TYPE_IP;
3709 if (vn->addr_family == AF_INET) {
3710 memcpy(rd->val + 2, &vn->addr.v4.s_addr, 4);
3711 } else { /* is v6 */
3712 memcpy(rd->val + 2, &vn->addr.v6.s6_addr32[3],
3713 4); /* low order 4 bytes */
3714 }
3715 vnc_zlog_debug_verbose("%s: auto-RD is set to %pRDP", __func__, rd);
3716 return 0;
3717 }
3718
3719 /*------------------------------------------
3720 * rfapi_bgp_lookup_by_rfp
3721 *
3722 * Find bgp instance pointer based on value returned by rfp_start
3723 *
3724 * input:
3725 * rfp_start_val value returned by rfp_startor
3726 * NULL (=get default instance)
3727 *
3728 * output:
3729 * none
3730 *
3731 * return value:
3732 * bgp bgp instance pointer
3733 * NULL = not found
3734 *
3735 --------------------------------------------*/
3736 struct bgp *rfapi_bgp_lookup_by_rfp(void *rfp_start_val)
3737 {
3738 struct bgp *bgp = NULL;
3739 struct listnode *node, *nnode;
3740
3741 if (rfp_start_val == NULL)
3742 bgp = bgp_get_default();
3743 else
3744 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3745 if (bgp->rfapi != NULL
3746 && bgp->rfapi->rfp == rfp_start_val)
3747 return bgp;
3748 return bgp;
3749 }
3750
3751 /*------------------------------------------
3752 * rfapi_get_rfp_start_val_by_bgp
3753 *
3754 * Find bgp instance pointer based on value returned by rfp_start
3755 *
3756 * input:
3757 * bgp bgp instance pointer
3758 *
3759 * output:
3760 * none
3761 *
3762 * return value:
3763 * rfp_start_val
3764 * NULL = not found
3765 *
3766 --------------------------------------------*/
3767 void *rfapi_get_rfp_start_val_by_bgp(struct bgp *bgp)
3768 {
3769 if (!bgp || !bgp->rfapi)
3770 return NULL;
3771 return bgp->rfapi->rfp;
3772 }
3773
3774 /***********************************************************************
3775 * RFP group specific configuration
3776 ***********************************************************************/
3777 static void *rfapi_rfp_get_or_init_group_config_default(struct rfapi_cfg *rfc,
3778 struct vty *vty,
3779 uint32_t size)
3780 {
3781 if (rfc->default_rfp_cfg == NULL && size > 0) {
3782 rfc->default_rfp_cfg = XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG, size);
3783 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__,
3784 size);
3785 }
3786 return rfc->default_rfp_cfg;
3787 }
3788
3789 static void *rfapi_rfp_get_or_init_group_config_nve(struct rfapi_cfg *rfc,
3790 struct vty *vty,
3791 uint32_t size)
3792 {
3793 struct rfapi_nve_group_cfg *rfg =
3794 VTY_GET_CONTEXT_SUB(rfapi_nve_group_cfg);
3795
3796 /* make sure group is still in list */
3797 if (!rfg || !listnode_lookup(rfc->nve_groups_sequential, rfg)) {
3798 /* Not in list anymore */
3799 vty_out(vty, "Current NVE group no longer exists\n");
3800 return NULL;
3801 }
3802
3803 if (rfg->rfp_cfg == NULL && size > 0) {
3804 rfg->rfp_cfg = XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG, size);
3805 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__,
3806 size);
3807 }
3808 return rfg->rfp_cfg;
3809 }
3810
3811 static void *rfapi_rfp_get_or_init_group_config_l2(struct rfapi_cfg *rfc,
3812 struct vty *vty,
3813 uint32_t size)
3814 {
3815 struct rfapi_l2_group_cfg *rfg =
3816 VTY_GET_CONTEXT_SUB(rfapi_l2_group_cfg);
3817
3818 /* make sure group is still in list */
3819 if (!rfg || !listnode_lookup(rfc->l2_groups, rfg)) {
3820 /* Not in list anymore */
3821 vty_out(vty, "Current L2 group no longer exists\n");
3822 return NULL;
3823 }
3824 if (rfg->rfp_cfg == NULL && size > 0) {
3825 rfg->rfp_cfg = XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG, size);
3826 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__,
3827 size);
3828 }
3829 return rfg->rfp_cfg;
3830 }
3831
3832 /*------------------------------------------
3833 * rfapi_rfp_init_group_config_ptr_vty
3834 *
3835 * This is used to init or return a previously init'ed group specific
3836 * configuration pointer. Group is identified by vty context.
3837 * NOTE: size is ignored when a previously init'ed value is returned.
3838 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
3839 * bgp restart or shutdown.
3840 *
3841 * input:
3842 * rfp_start_val value returned by rfp_start
3843 * type group type
3844 * vty quagga vty context
3845 * size number of bytes to allocation
3846 *
3847 * output:
3848 * none
3849 *
3850 * return value:
3851 * rfp_cfg_group NULL or Pointer to configuration structure
3852 --------------------------------------------*/
3853 void *rfapi_rfp_init_group_config_ptr_vty(void *rfp_start_val,
3854 rfapi_rfp_cfg_group_type type,
3855 struct vty *vty, uint32_t size)
3856 {
3857 struct bgp *bgp;
3858 void *ret = NULL;
3859
3860 if (rfp_start_val == NULL || vty == NULL)
3861 return NULL;
3862
3863 bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
3864 if (!bgp || !bgp->rfapi_cfg)
3865 return NULL;
3866
3867 switch (type) {
3868 case RFAPI_RFP_CFG_GROUP_DEFAULT:
3869 ret = rfapi_rfp_get_or_init_group_config_default(bgp->rfapi_cfg,
3870 vty, size);
3871 break;
3872 case RFAPI_RFP_CFG_GROUP_NVE:
3873 ret = rfapi_rfp_get_or_init_group_config_nve(bgp->rfapi_cfg,
3874 vty, size);
3875 break;
3876 case RFAPI_RFP_CFG_GROUP_L2:
3877 ret = rfapi_rfp_get_or_init_group_config_l2(bgp->rfapi_cfg, vty,
3878 size);
3879 break;
3880 default:
3881 flog_err(EC_LIB_DEVELOPMENT, "%s: Unknown group type=%d",
3882 __func__, type);
3883 /* should never happen */
3884 assert("Unknown type" == NULL);
3885 break;
3886 }
3887 return ret;
3888 }
3889
3890 /*------------------------------------------
3891 * rfapi_rfp_get_group_config_ptr_vty
3892 *
3893 * This is used to get group specific configuration pointer.
3894 * Group is identified by type and vty context.
3895 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
3896 * bgp restart or shutdown.
3897 *
3898 * input:
3899 * rfp_start_val value returned by rfp_start
3900 * type group type
3901 * vty quagga vty context
3902 *
3903 * output:
3904 * none
3905 *
3906 * return value:
3907 * rfp_cfg_group Pointer to configuration structure
3908 --------------------------------------------*/
3909 void *rfapi_rfp_get_group_config_ptr_vty(void *rfp_start_val,
3910 rfapi_rfp_cfg_group_type type,
3911 struct vty *vty)
3912 {
3913 return rfapi_rfp_init_group_config_ptr_vty(rfp_start_val, type, vty, 0);
3914 }
3915
3916 static void *
3917 rfapi_rfp_get_group_config_name_nve(struct rfapi_cfg *rfc, const char *name,
3918 void *criteria,
3919 rfp_group_config_search_cb_t *search_cb)
3920 {
3921 struct rfapi_nve_group_cfg *rfg;
3922 struct listnode *node;
3923
3924 for (ALL_LIST_ELEMENTS_RO(rfc->nve_groups_sequential, node, rfg)) {
3925 if (!strcmp(rfg->name, name) && /* name match */
3926 (search_cb == NULL || !search_cb(criteria, rfg->rfp_cfg)))
3927 return rfg->rfp_cfg;
3928 }
3929 return NULL;
3930 }
3931
3932 static void *
3933 rfapi_rfp_get_group_config_name_l2(struct rfapi_cfg *rfc, const char *name,
3934 void *criteria,
3935 rfp_group_config_search_cb_t *search_cb)
3936 {
3937 struct rfapi_l2_group_cfg *rfg;
3938 struct listnode *node;
3939
3940 for (ALL_LIST_ELEMENTS_RO(rfc->l2_groups, node, rfg)) {
3941 if (!strcmp(rfg->name, name) && /* name match */
3942 (search_cb == NULL || !search_cb(criteria, rfg->rfp_cfg)))
3943 return rfg->rfp_cfg;
3944 }
3945 return NULL;
3946 }
3947
3948 /*------------------------------------------
3949 * rfapi_rfp_get_group_config_ptr_name
3950 *
3951 * This is used to get group specific configuration pointer.
3952 * Group is identified by type and name context.
3953 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
3954 * bgp restart or shutdown.
3955 *
3956 * input:
3957 * rfp_start_val value returned by rfp_start
3958 * type group type
3959 * name group name
3960 * criteria RFAPI caller provided search criteria
3961 * search_cb optional rfp_group_config_search_cb_t
3962 *
3963 * output:
3964 * none
3965 *
3966 * return value:
3967 * rfp_cfg_group Pointer to configuration structure
3968 --------------------------------------------*/
3969 void *rfapi_rfp_get_group_config_ptr_name(
3970 void *rfp_start_val, rfapi_rfp_cfg_group_type type, const char *name,
3971 void *criteria, rfp_group_config_search_cb_t *search_cb)
3972 {
3973 struct bgp *bgp;
3974 void *ret = NULL;
3975
3976 if (rfp_start_val == NULL || name == NULL)
3977 return NULL;
3978
3979 bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
3980 if (!bgp || !bgp->rfapi_cfg)
3981 return NULL;
3982
3983 switch (type) {
3984 case RFAPI_RFP_CFG_GROUP_DEFAULT:
3985 ret = bgp->rfapi_cfg->default_rfp_cfg;
3986 break;
3987 case RFAPI_RFP_CFG_GROUP_NVE:
3988 ret = rfapi_rfp_get_group_config_name_nve(bgp->rfapi_cfg, name,
3989 criteria, search_cb);
3990 break;
3991 case RFAPI_RFP_CFG_GROUP_L2:
3992 ret = rfapi_rfp_get_group_config_name_l2(bgp->rfapi_cfg, name,
3993 criteria, search_cb);
3994 break;
3995 default:
3996 flog_err(EC_LIB_DEVELOPMENT, "%s: Unknown group type=%d",
3997 __func__, type);
3998 /* should never happen */
3999 assert("Unknown type" == NULL);
4000 break;
4001 }
4002 return ret;
4003 }
4004
4005 /*------------------------------------------
4006 * rfapi_rfp_get_l2_group_config_ptr_lni
4007 *
4008 * This is used to get group specific configuration pointer.
4009 * Group is identified by type and logical network identifier.
4010 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
4011 * bgp restart or shutdown.
4012 *
4013 * input:
4014 * rfp_start_val value returned by rfp_start
4015 * type group type
4016 * logical_net_id group logical network identifier
4017 * criteria RFAPI caller provided search criteria
4018 * search_cb optional rfp_group_config_search_cb_t
4019 *
4020 * output:
4021 * none
4022 *
4023 * return value:
4024 * rfp_cfg_group Pointer to configuration structure
4025 --------------------------------------------*/
4026 void *
4027 rfapi_rfp_get_l2_group_config_ptr_lni(void *rfp_start_val,
4028 uint32_t logical_net_id, void *criteria,
4029 rfp_group_config_search_cb_t *search_cb)
4030 {
4031 struct bgp *bgp;
4032 struct rfapi_l2_group_cfg *rfg;
4033 struct listnode *node;
4034
4035 if (rfp_start_val == NULL)
4036 return NULL;
4037
4038 bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
4039 if (!bgp || !bgp->rfapi_cfg)
4040 return NULL;
4041
4042 for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->l2_groups, node, rfg)) {
4043 if (rfg->logical_net_id == logical_net_id
4044 && (search_cb == NULL
4045 || !search_cb(criteria, rfg->rfp_cfg))) {
4046 if (rfg->rfp_cfg == NULL)
4047 vnc_zlog_debug_verbose(
4048 "%s: returning rfp group config for lni=0",
4049 __func__);
4050 return rfg->rfp_cfg;
4051 }
4052 }
4053 return NULL;
4054 }