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