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