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