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