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