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