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