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