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