]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/rfapi/rfapi.c
Merge pull request #870 from chiragshah6/mdev
[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 afi_t 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 afi_t 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 == rfapiApDelete(bgp, rfd, &p, pfx_mac, &prd,
2607 &adv_tunnel)) {
2608 if (adv_tunnel)
2609 rfapiTunnelRouteAnnounce(
2610 bgp, rfd, &rfd->max_prefix_lifetime);
2611 }
2612
2613 } else {
2614
2615 int adv_tunnel = 0;
2616 uint32_t local_pref;
2617 struct ecommunity *rtlist = NULL;
2618 struct ecommunity_val ecom_value;
2619
2620 if (!rfapiApCount(rfd)) {
2621 /*
2622 * make sure we advertise tunnel route upon adding the
2623 * first VPN route
2624 */
2625 adv_tunnel = 1;
2626 }
2627
2628 if (rfapiApAdd(bgp, rfd, &p, pfx_mac, &prd, lifetime,
2629 prefix->cost, l2o)) {
2630 adv_tunnel = 1;
2631 }
2632
2633 vnc_zlog_debug_verbose("%s: adv_tunnel = %d", __func__,
2634 adv_tunnel);
2635 if (adv_tunnel) {
2636 vnc_zlog_debug_verbose("%s: announcing tunnel route",
2637 __func__);
2638 rfapiTunnelRouteAnnounce(bgp, rfd,
2639 &rfd->max_prefix_lifetime);
2640 }
2641
2642 vnc_zlog_debug_verbose("%s: calling add_vnc_route", __func__);
2643
2644 local_pref = rfp_cost_to_localpref(prefix->cost);
2645
2646 if (l2o && l2o->label)
2647 label = &l2o->label;
2648
2649 if (pfx_mac) {
2650 struct ecommunity *l2com = NULL;
2651
2652 if (label) {
2653 l2com = bgp_rfapi_get_ecommunity_by_lni_label(
2654 bgp, 1, l2o->logical_net_id, *label);
2655 }
2656 if (l2com) {
2657 rtlist = ecommunity_dup(l2com);
2658 } else {
2659 /*
2660 * If mac address is set, add an RT based on the
2661 * registered LNI
2662 */
2663 memset((char *)&ecom_value, 0,
2664 sizeof(ecom_value));
2665 ecom_value.val[1] = ECOMMUNITY_ROUTE_TARGET;
2666 ecom_value.val[5] =
2667 (l2o->logical_net_id >> 16) & 0xff;
2668 ecom_value.val[6] =
2669 (l2o->logical_net_id >> 8) & 0xff;
2670 ecom_value.val[7] =
2671 (l2o->logical_net_id >> 0) & 0xff;
2672 rtlist = ecommunity_new();
2673 ecommunity_add_val(rtlist, &ecom_value);
2674 }
2675 if (l2o->tag_id) {
2676 as_t as = bgp->as;
2677 uint16_t val = l2o->tag_id;
2678 memset((char *)&ecom_value, 0,
2679 sizeof(ecom_value));
2680 ecom_value.val[1] = ECOMMUNITY_ROUTE_TARGET;
2681 if (as > BGP_AS_MAX) {
2682 ecom_value.val[0] =
2683 ECOMMUNITY_ENCODE_AS4;
2684 ecom_value.val[2] = (as >> 24) & 0xff;
2685 ecom_value.val[3] = (as >> 16) & 0xff;
2686 ecom_value.val[4] = (as >> 8) & 0xff;
2687 ecom_value.val[5] = as & 0xff;
2688 } else {
2689 ecom_value.val[0] =
2690 ECOMMUNITY_ENCODE_AS;
2691 ecom_value.val[2] = (as >> 8) & 0xff;
2692 ecom_value.val[3] = as & 0xff;
2693 }
2694 ecom_value.val[6] = (val >> 8) & 0xff;
2695 ecom_value.val[7] = val & 0xff;
2696 if (rtlist == NULL)
2697 rtlist = ecommunity_new();
2698 ecommunity_add_val(rtlist, &ecom_value);
2699 }
2700 }
2701
2702 /*
2703 * advertise prefix via tunnel endpoint
2704 */
2705 add_vnc_route(
2706 rfd, /* rfapi descr, for export list & backref */
2707 bgp, /* which bgp instance */
2708 SAFI_MPLS_VPN, /* which SAFI */
2709 (pfx_ip ? pfx_ip
2710 : &pfx_vn_buf), /* prefix being advertised */
2711 &prd, /* route distinguisher to use (0 for ENCAP) */
2712 &rfd->vn_addr, /* nexthop */
2713 &local_pref,
2714 &lifetime, /* prefix lifetime -> Tunnel Encap attr */
2715 NULL, options_un, /* rfapi un options */
2716 options_vn, /* rfapi vn options */
2717 (rtlist ? rtlist : rfd->rt_export_list), NULL, /* med */
2718 label, /* label: default */
2719 ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, 0);
2720
2721 if (rtlist)
2722 ecommunity_free(&rtlist); /* sets rtlist = NULL */
2723 }
2724
2725 vnc_zlog_debug_verbose("%s: success", __func__);
2726 return 0;
2727 }
2728
2729 int rfapi_query(void *handle, struct rfapi_ip_addr *target,
2730 struct rfapi_l2address_option *l2o, /* may be NULL */
2731 struct rfapi_next_hop_entry **ppNextHopEntry)
2732 {
2733 struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
2734 struct bgp *bgp = rfd->bgp;
2735 int rc;
2736
2737 assert(ppNextHopEntry);
2738 *ppNextHopEntry = NULL;
2739
2740 if (bgp && bgp->rfapi) {
2741 bgp->rfapi->stat.count_queries++;
2742 }
2743
2744 if (!rfd->rfg) {
2745 if (bgp && bgp->rfapi)
2746 ++bgp->rfapi->stat.count_queries_failed;
2747 return ESTALE;
2748 }
2749
2750 if ((rc = rfapi_query_inner(handle, target, l2o, ppNextHopEntry))) {
2751 if (bgp && bgp->rfapi)
2752 ++bgp->rfapi->stat.count_queries_failed;
2753 }
2754 return rc;
2755 }
2756
2757 int rfapi_query_done(rfapi_handle handle, struct rfapi_ip_addr *target)
2758 {
2759 struct prefix p;
2760 int rc;
2761 struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
2762 struct bgp *bgp = rfd->bgp;
2763
2764 if (!rfd->rfg)
2765 return ESTALE;
2766
2767 assert(target);
2768 rc = rfapiRaddr2Qprefix(target, &p);
2769 assert(!rc);
2770
2771 if (!is_valid_rfd(rfd))
2772 return EBADF;
2773
2774 /* preemptive */
2775 if (!bgp || !bgp->rfapi)
2776 return ENXIO;
2777
2778 if (bgp->rfapi->flags & RFAPI_INCALLBACK)
2779 return EDEADLK;
2780
2781 rfapiMonitorDel(bgp, rfd, &p);
2782
2783 return 0;
2784 }
2785
2786 int rfapi_query_done_all(rfapi_handle handle, int *count)
2787 {
2788 struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
2789 struct bgp *bgp = rfd->bgp;
2790 ;
2791 int num;
2792
2793 if (!rfd->rfg)
2794 return ESTALE;
2795
2796 if (!is_valid_rfd(rfd))
2797 return EBADF;
2798
2799 /* preemptive */
2800 if (!bgp || !bgp->rfapi)
2801 return ENXIO;
2802
2803 if (bgp->rfapi->flags & RFAPI_INCALLBACK)
2804 return EDEADLK;
2805
2806 num = rfapiMonitorDelHd(rfd);
2807
2808 if (count)
2809 *count = num;
2810
2811 return 0;
2812 }
2813
2814 void rfapi_free_next_hop_list(struct rfapi_next_hop_entry *list)
2815 {
2816 struct rfapi_next_hop_entry *nh;
2817 struct rfapi_next_hop_entry *next;
2818
2819 for (nh = list; nh; nh = next) {
2820 next = nh->next;
2821 rfapi_un_options_free(nh->un_options);
2822 nh->un_options = NULL;
2823 rfapi_vn_options_free(nh->vn_options);
2824 nh->vn_options = NULL;
2825 XFREE(MTYPE_RFAPI_NEXTHOP, nh);
2826 }
2827 }
2828
2829 /*
2830 * NULL handle => return total count across all nves
2831 */
2832 uint32_t rfapi_monitor_count(void *handle)
2833 {
2834 struct bgp *bgp = bgp_get_default();
2835 uint32_t count;
2836
2837 if (handle) {
2838 struct rfapi_descriptor *rfd =
2839 (struct rfapi_descriptor *)handle;
2840 count = rfd->monitor_count;
2841 } else {
2842
2843 if (!bgp || !bgp->rfapi)
2844 return 0;
2845
2846 count = bgp->rfapi->monitor_count;
2847 }
2848
2849 return count;
2850 }
2851
2852 /***********************************************************************
2853 * CLI/CONFIG
2854 ***********************************************************************/
2855
2856 DEFUN (debug_rfapi_show_nves,
2857 debug_rfapi_show_nves_cmd,
2858 "debug rfapi-dev show nves",
2859 DEBUG_STR
2860 DEBUG_RFAPI_STR
2861 SHOW_STR
2862 "NVE Information\n")
2863 {
2864 rfapiPrintMatchingDescriptors(vty, NULL, NULL);
2865 return CMD_SUCCESS;
2866 }
2867
2868 DEFUN (
2869 debug_rfapi_show_nves_vn_un,
2870 debug_rfapi_show_nves_vn_un_cmd,
2871 "debug rfapi-dev show nves <vn|un> <A.B.C.D|X:X::X:X>", /* prefix also ok */
2872 DEBUG_STR
2873 DEBUG_RFAPI_STR
2874 SHOW_STR
2875 "NVE Information\n"
2876 "Specify virtual network\n"
2877 "Specify underlay network interface\n"
2878 "IPv4 address\n"
2879 "IPv6 address\n")
2880 {
2881 struct prefix pfx;
2882
2883 if (!str2prefix(argv[5]->arg, &pfx)) {
2884 vty_out(vty, "Malformed address \"%s\"\n", argv[5]->arg);
2885 return CMD_WARNING_CONFIG_FAILED;
2886 }
2887 if (pfx.family != AF_INET && pfx.family != AF_INET6) {
2888 vty_out(vty, "Invalid address \"%s\"\n", argv[5]->arg);
2889 return CMD_WARNING_CONFIG_FAILED;
2890 }
2891
2892 if (argv[4]->arg[0] == 'u') {
2893 rfapiPrintMatchingDescriptors(vty, NULL, &pfx);
2894 } else {
2895 rfapiPrintMatchingDescriptors(vty, &pfx, NULL);
2896 }
2897 return CMD_SUCCESS;
2898 }
2899
2900 /*
2901 * Note: this function does not flush vty output, so if it is called
2902 * with a stream pointing to a vty, the user will have to type something
2903 * before the callback output shows up
2904 */
2905 static void test_nexthops_callback(
2906 // struct rfapi_ip_addr *target,
2907 struct rfapi_next_hop_entry *next_hops, void *userdata)
2908 {
2909 void *stream = userdata;
2910
2911 int (*fp)(void *, const char *, ...);
2912 struct vty *vty;
2913 void *out;
2914 const char *vty_newline;
2915
2916 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
2917 return;
2918
2919 fp(out, "Nexthops Callback, Target=(");
2920 // rfapiPrintRfapiIpAddr(stream, target);
2921 fp(out, ")\n");
2922
2923 rfapiPrintNhl(stream, next_hops);
2924
2925 rfapi_free_next_hop_list(next_hops);
2926 }
2927
2928 DEFUN (debug_rfapi_open,
2929 debug_rfapi_open_cmd,
2930 "debug rfapi-dev open vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2931 DEBUG_STR
2932 DEBUG_RFAPI_STR
2933 "rfapi_open\n"
2934 "indicate vn addr follows\n"
2935 "virtual network interface IPv4 address\n"
2936 "virtual network interface IPv6 address\n"
2937 "indicate xt addr follows\n"
2938 "underlay network interface IPv4 address\n"
2939 "underlay network interface IPv6 address\n")
2940 {
2941 struct rfapi_ip_addr vn;
2942 struct rfapi_ip_addr un;
2943 uint32_t lifetime;
2944 int rc;
2945 rfapi_handle handle;
2946
2947 /*
2948 * Get VN addr
2949 */
2950 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
2951 return rc;
2952
2953 /*
2954 * Get UN addr
2955 */
2956 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
2957 return rc;
2958
2959 rc = rfapi_open(rfapi_get_rfp_start_val_by_bgp(bgp_get_default()), &vn,
2960 &un, /*&uo */ NULL, &lifetime, NULL, &handle);
2961
2962 vty_out(vty, "rfapi_open: status %d, handle %p, lifetime %d\n", rc,
2963 handle, lifetime);
2964
2965 rc = rfapi_set_response_cb(handle, test_nexthops_callback);
2966
2967 vty_out(vty, "rfapi_set_response_cb: status %d\n", rc);
2968
2969 return CMD_SUCCESS;
2970 }
2971
2972
2973 DEFUN (debug_rfapi_close_vn_un,
2974 debug_rfapi_close_vn_un_cmd,
2975 "debug rfapi-dev close vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2976 DEBUG_STR
2977 DEBUG_RFAPI_STR
2978 "rfapi_close\n"
2979 "indicate vn addr follows\n"
2980 "virtual network interface IPv4 address\n"
2981 "virtual network interface IPv6 address\n"
2982 "indicate xt addr follows\n"
2983 "underlay network interface IPv4 address\n"
2984 "underlay network interface IPv6 address\n")
2985 {
2986 struct rfapi_ip_addr vn;
2987 struct rfapi_ip_addr un;
2988 rfapi_handle handle;
2989 int rc;
2990
2991 /*
2992 * Get VN addr
2993 */
2994 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
2995 return rc;
2996
2997
2998 /*
2999 * Get UN addr
3000 */
3001 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
3002 return rc;
3003
3004
3005 if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3006 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3007 argv[4]->arg, argv[6]->arg);
3008 return CMD_WARNING_CONFIG_FAILED;
3009 }
3010
3011 rc = rfapi_close(handle);
3012
3013 vty_out(vty, "rfapi_close(handle=%p): status %d\n", handle, rc);
3014
3015 return CMD_SUCCESS;
3016 }
3017
3018 DEFUN (debug_rfapi_close_rfd,
3019 debug_rfapi_close_rfd_cmd,
3020 "debug rfapi-dev close rfd HANDLE",
3021 DEBUG_STR
3022 DEBUG_RFAPI_STR
3023 "rfapi_close\n"
3024 "indicate handle follows\n" "rfapi handle in hexadecimal\n")
3025 {
3026 rfapi_handle handle;
3027 int rc;
3028 char *endptr = NULL;
3029
3030 handle = (rfapi_handle)(uintptr_t)(strtoull(argv[4]->arg, &endptr, 16));
3031
3032 if (*endptr != '\0' || (uintptr_t)handle == UINTPTR_MAX) {
3033 vty_out(vty, "Invalid value: %s\n", argv[4]->arg);
3034 return CMD_WARNING_CONFIG_FAILED;
3035 }
3036
3037 rc = rfapi_close(handle);
3038
3039 vty_out(vty, "rfapi_close(handle=%p): status %d\n", handle, rc);
3040
3041 return CMD_SUCCESS;
3042 }
3043
3044 DEFUN (debug_rfapi_register_vn_un,
3045 debug_rfapi_register_vn_un_cmd,
3046 "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",
3047 DEBUG_STR
3048 DEBUG_RFAPI_STR
3049 "rfapi_register\n"
3050 "indicate vn addr follows\n"
3051 "virtual network IPv4 interface address\n"
3052 "virtual network IPv6 interface address\n"
3053 "indicate un addr follows\n"
3054 "underlay network IPv4 interface address\n"
3055 "underlay network IPv6 interface address\n"
3056 "indicate prefix follows\n"
3057 "IPv4 prefix\n"
3058 "IPv6 prefix\n"
3059 "indicate lifetime follows\n"
3060 "lifetime\n")
3061 {
3062 struct rfapi_ip_addr vn;
3063 struct rfapi_ip_addr un;
3064 rfapi_handle handle;
3065 struct prefix pfx;
3066 uint32_t lifetime;
3067 struct rfapi_ip_prefix hpfx;
3068 int rc;
3069
3070 /*
3071 * Get VN addr
3072 */
3073 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
3074 return rc;
3075
3076
3077 /*
3078 * Get UN addr
3079 */
3080 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
3081 return rc;
3082
3083
3084 if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3085 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3086 argv[4]->arg, argv[6]->arg);
3087 return CMD_WARNING_CONFIG_FAILED;
3088 }
3089
3090 /*
3091 * Get prefix to advertise
3092 */
3093 if (!str2prefix(argv[8]->arg, &pfx)) {
3094 vty_out(vty, "Malformed prefix \"%s\"\n", argv[8]->arg);
3095 return CMD_WARNING_CONFIG_FAILED;
3096 }
3097 if (pfx.family != AF_INET && pfx.family != AF_INET6) {
3098 vty_out(vty, "Bad family for prefix \"%s\"\n", argv[8]->arg);
3099 return CMD_WARNING_CONFIG_FAILED;
3100 }
3101 rfapiQprefix2Rprefix(&pfx, &hpfx);
3102
3103 if (strmatch(argv[10]->text, "infinite")) {
3104 lifetime = RFAPI_INFINITE_LIFETIME;
3105 } else {
3106 lifetime = strtoul(argv[10]->arg, NULL, 10);
3107 }
3108
3109
3110 rc = rfapi_register(handle, &hpfx, lifetime, NULL, NULL, 0);
3111 if (rc) {
3112 vty_out(vty, "rfapi_register failed with rc=%d (%s)\n", rc,
3113 strerror(rc));
3114 }
3115
3116 return CMD_SUCCESS;
3117 }
3118
3119 DEFUN (debug_rfapi_register_vn_un_l2o,
3120 debug_rfapi_register_vn_un_l2o_cmd,
3121 "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)",
3122 DEBUG_STR
3123 DEBUG_RFAPI_STR
3124 "rfapi_register\n"
3125 "indicate vn addr follows\n"
3126 "virtual network IPv4 interface address\n"
3127 "virtual network IPv6 interface address\n"
3128 "indicate un addr follows\n"
3129 "underlay network IPv4 interface address\n"
3130 "underlay network IPv6 interface address\n"
3131 "indicate prefix follows\n"
3132 "IPv4 prefix\n"
3133 "IPv6 prefix\n"
3134 "indicate lifetime follows\n"
3135 "Seconds of lifetime\n"
3136 "indicate MAC address follows\n"
3137 "MAC address\n"
3138 "indicate lni follows\n"
3139 "lni value range\n")
3140 {
3141 struct rfapi_ip_addr vn;
3142 struct rfapi_ip_addr un;
3143 rfapi_handle handle;
3144 struct prefix pfx;
3145 uint32_t lifetime;
3146 struct rfapi_ip_prefix hpfx;
3147 int rc;
3148 struct rfapi_vn_option optary[10]; /* XXX must be big enough */
3149 struct rfapi_vn_option *opt = NULL;
3150 int opt_next = 0;
3151
3152 /*
3153 * Get VN addr
3154 */
3155 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
3156 return rc;
3157
3158
3159 /*
3160 * Get UN addr
3161 */
3162 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
3163 return rc;
3164
3165
3166 if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3167 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3168 argv[4]->arg, argv[6]->arg);
3169 return CMD_WARNING_CONFIG_FAILED;
3170 }
3171
3172 /*
3173 * Get prefix to advertise
3174 */
3175 if (!str2prefix(argv[8]->arg, &pfx)) {
3176 vty_out(vty, "Malformed prefix \"%s\"\n", argv[8]->arg);
3177 return CMD_WARNING_CONFIG_FAILED;
3178 }
3179 if (pfx.family != AF_INET && pfx.family != AF_INET6) {
3180 vty_out(vty, "Bad family for prefix \"%s\"\n", argv[8]->arg);
3181 return CMD_WARNING_CONFIG_FAILED;
3182 }
3183 rfapiQprefix2Rprefix(&pfx, &hpfx);
3184
3185 if (strmatch(argv[10]->text, "infinite")) {
3186 lifetime = RFAPI_INFINITE_LIFETIME;
3187 } else {
3188 lifetime = strtoul(argv[10]->arg, NULL, 10);
3189 }
3190
3191 /* L2 option parsing START */
3192 memset(optary, 0, sizeof(optary));
3193 optary[opt_next].v.l2addr.logical_net_id =
3194 strtoul(argv[14]->arg, NULL, 10);
3195 if ((rc = rfapiStr2EthAddr(argv[12]->arg,
3196 &optary[opt_next].v.l2addr.macaddr))) {
3197 vty_out(vty, "Bad mac address \"%s\"\n", argv[12]->arg);
3198 return CMD_WARNING_CONFIG_FAILED;
3199 }
3200 optary[opt_next].type = RFAPI_VN_OPTION_TYPE_L2ADDR;
3201 if (opt_next) {
3202 optary[opt_next - 1].next = optary + opt_next;
3203 } else {
3204 opt = optary;
3205 }
3206 ++opt_next;
3207 /* L2 option parsing END */
3208
3209 /* TBD fixme */
3210 rc = rfapi_register(handle, &hpfx, lifetime, NULL /* &uo */, opt, 0);
3211 if (rc) {
3212 vty_out(vty, "rfapi_register failed with rc=%d (%s)\n", rc,
3213 strerror(rc));
3214 }
3215
3216 return CMD_SUCCESS;
3217 }
3218
3219
3220 DEFUN (debug_rfapi_unregister_vn_un,
3221 debug_rfapi_unregister_vn_un_cmd,
3222 "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>",
3223 DEBUG_STR
3224 DEBUG_RFAPI_STR
3225 "rfapi_register\n"
3226 "indicate vn addr follows\n"
3227 "virtual network interface address\n"
3228 "indicate xt addr follows\n"
3229 "underlay network interface address\n"
3230 "indicate prefix follows\n" "prefix")
3231 {
3232 struct rfapi_ip_addr vn;
3233 struct rfapi_ip_addr un;
3234 rfapi_handle handle;
3235 struct prefix pfx;
3236 struct rfapi_ip_prefix hpfx;
3237 int rc;
3238
3239 /*
3240 * Get VN addr
3241 */
3242 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
3243 return rc;
3244
3245
3246 /*
3247 * Get UN addr
3248 */
3249 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
3250 return rc;
3251
3252
3253 if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3254 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3255 argv[4]->arg, argv[6]->arg);
3256 return CMD_WARNING_CONFIG_FAILED;
3257 }
3258
3259 /*
3260 * Get prefix to advertise
3261 */
3262 if (!str2prefix(argv[8]->arg, &pfx)) {
3263 vty_out(vty, "Malformed prefix \"%s\"\n", argv[8]->arg);
3264 return CMD_WARNING_CONFIG_FAILED;
3265 }
3266 if (pfx.family != AF_INET && pfx.family != AF_INET6) {
3267 vty_out(vty, "Bad family for prefix \"%s\"\n", argv[8]->arg);
3268 return CMD_WARNING_CONFIG_FAILED;
3269 }
3270 rfapiQprefix2Rprefix(&pfx, &hpfx);
3271
3272 rfapi_register(handle, &hpfx, 0, NULL, NULL, 1);
3273
3274 return CMD_SUCCESS;
3275 }
3276
3277 DEFUN (debug_rfapi_query_vn_un,
3278 debug_rfapi_query_vn_un_cmd,
3279 "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>",
3280 DEBUG_STR
3281 DEBUG_RFAPI_STR
3282 "rfapi_query\n"
3283 "indicate vn addr follows\n"
3284 "virtual network interface IPv4 address\n"
3285 "virtual network interface IPv6 address\n"
3286 "indicate un addr follows\n"
3287 "IPv4 un address\n"
3288 "IPv6 un address\n"
3289 "indicate target follows\n"
3290 "target IPv4 address\n"
3291 "target IPv6 address\n")
3292 {
3293 struct rfapi_ip_addr vn;
3294 struct rfapi_ip_addr un;
3295 struct rfapi_ip_addr target;
3296 rfapi_handle handle;
3297 int rc;
3298 struct rfapi_next_hop_entry *pNextHopEntry;
3299
3300 /*
3301 * Get VN addr
3302 */
3303 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
3304 return rc;
3305
3306
3307 /*
3308 * Get UN addr
3309 */
3310 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
3311 return rc;
3312
3313
3314 /*
3315 * Get target addr
3316 */
3317 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[8]->arg, &target)))
3318 return rc;
3319
3320
3321 if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3322 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3323 argv[4]->arg, argv[6]->arg);
3324 return CMD_WARNING_CONFIG_FAILED;
3325 }
3326
3327 /*
3328 * options parameter not used? Set to NULL for now
3329 */
3330 rc = rfapi_query(handle, &target, NULL, &pNextHopEntry);
3331
3332 if (rc) {
3333 vty_out(vty, "rfapi_query failed with rc=%d (%s)\n", rc,
3334 strerror(rc));
3335 } else {
3336 /*
3337 * print nexthop list
3338 */
3339 test_nexthops_callback(/*&target, */ pNextHopEntry,
3340 vty); /* frees nh list! */
3341 }
3342
3343 return CMD_SUCCESS;
3344 }
3345
3346
3347 DEFUN (debug_rfapi_query_vn_un_l2o,
3348 debug_rfapi_query_vn_un_l2o_cmd,
3349 "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",
3350 DEBUG_STR
3351 DEBUG_RFAPI_STR
3352 "rfapi_query\n"
3353 "indicate vn addr follows\n"
3354 "virtual network interface IPv4 address\n"
3355 "virtual network interface IPv6 address\n"
3356 "indicate xt addr follows\n"
3357 "underlay network interface IPv4 address\n"
3358 "underlay network interface IPv6 address\n"
3359 "logical network ID follows\n"
3360 "logical network ID\n"
3361 "indicate target MAC addr follows\n"
3362 "target MAC addr\n")
3363 {
3364 struct rfapi_ip_addr vn;
3365 struct rfapi_ip_addr un;
3366 struct rfapi_ip_addr target;
3367 rfapi_handle handle;
3368 int rc;
3369 struct rfapi_next_hop_entry *pNextHopEntry;
3370 struct rfapi_l2address_option l2o_buf;
3371 struct bgp_tea_options hopt;
3372 uint8_t valbuf[14];
3373
3374 /*
3375 * Get VN addr
3376 */
3377 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
3378 return rc;
3379
3380
3381 /*
3382 * Get UN addr
3383 */
3384 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
3385 return rc;
3386
3387
3388 #if 0 /* there is no IP target arg here ?????? */
3389 /*
3390 * Get target addr
3391 */
3392 if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[2], &target)))
3393 return rc;
3394 #else
3395 vty_out(vty, "%% This command is broken.\n");
3396 return CMD_WARNING_CONFIG_FAILED;
3397 #endif
3398
3399 if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3400 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3401 argv[4]->arg, argv[6]->arg);
3402 return CMD_WARNING_CONFIG_FAILED;
3403 }
3404
3405 /*
3406 * Set up L2 parameters
3407 */
3408 memset(&l2o_buf, 0, sizeof(l2o_buf));
3409 if (rfapiStr2EthAddr(argv[10]->arg, &l2o_buf.macaddr)) {
3410 vty_out(vty, "Bad mac address \"%s\"\n", argv[10]->arg);
3411 return CMD_WARNING_CONFIG_FAILED;
3412 }
3413
3414 l2o_buf.logical_net_id = strtoul(argv[8]->arg, NULL, 10);
3415
3416 /* construct option chain */
3417
3418 memset(valbuf, 0, sizeof(valbuf));
3419 memcpy(valbuf, &l2o_buf.macaddr.octet, ETHER_ADDR_LEN);
3420 valbuf[11] = (l2o_buf.logical_net_id >> 16) & 0xff;
3421 valbuf[12] = (l2o_buf.logical_net_id >> 8) & 0xff;
3422 valbuf[13] = l2o_buf.logical_net_id & 0xff;
3423
3424 memset(&hopt, 0, sizeof(hopt));
3425 hopt.options_count = 1;
3426 hopt.options_length = sizeof(valbuf); /* is this right? */
3427 hopt.type = RFAPI_VN_OPTION_TYPE_L2ADDR;
3428 hopt.length = sizeof(valbuf);
3429 hopt.value = valbuf;
3430
3431
3432 /*
3433 * options parameter not used? Set to NULL for now
3434 */
3435 rc = rfapi_query(handle, &target, &l2o_buf, &pNextHopEntry);
3436
3437 if (rc) {
3438 vty_out(vty, "rfapi_query failed with rc=%d (%s)\n", rc,
3439 strerror(rc));
3440 } else {
3441 /*
3442 * print nexthop list
3443 */
3444 /* TBD enhance to print L2 information */
3445 test_nexthops_callback(/*&target, */ pNextHopEntry,
3446 vty); /* frees nh list! */
3447 }
3448
3449 return CMD_SUCCESS;
3450 }
3451
3452
3453 DEFUN (debug_rfapi_query_done_vn_un,
3454 debug_rfapi_query_vn_un_done_cmd,
3455 "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>",
3456 DEBUG_STR
3457 DEBUG_RFAPI_STR
3458 "rfapi_query_done\n"
3459 "rfapi_query_done\n"
3460 "indicate vn addr follows\n"
3461 "virtual network interface IPv4 address\n"
3462 "virtual network interface IPv6 address\n"
3463 "indicate xt addr follows\n"
3464 "underlay network interface IPv4 address\n"
3465 "underlay network interface IPv6 address\n"
3466 "indicate target follows\n"
3467 "Target IPv4 address\n"
3468 "Target IPv6 address\n")
3469 {
3470 struct rfapi_ip_addr vn;
3471 struct rfapi_ip_addr un;
3472 struct rfapi_ip_addr target;
3473 rfapi_handle handle;
3474 int rc;
3475
3476 /*
3477 * Get VN addr
3478 */
3479 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[5]->arg, &vn)))
3480 return rc;
3481
3482
3483 /*
3484 * Get UN addr
3485 */
3486 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[7]->arg, &un)))
3487 return rc;
3488
3489
3490 /*
3491 * Get target addr
3492 */
3493 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[9]->arg, &target)))
3494 return rc;
3495
3496
3497 if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3498 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3499 argv[5]->arg, argv[7]->arg);
3500 return CMD_WARNING_CONFIG_FAILED;
3501 }
3502
3503 /*
3504 * options parameter not used? Set to NULL for now
3505 */
3506 rc = rfapi_query_done(handle, &target);
3507
3508 vty_out(vty, "rfapi_query_done returned %d\n", rc);
3509
3510 return CMD_SUCCESS;
3511 }
3512
3513 DEFUN (debug_rfapi_show_import,
3514 debug_rfapi_show_import_cmd,
3515 "debug rfapi-dev show import",
3516 DEBUG_STR
3517 DEBUG_RFAPI_STR
3518 SHOW_STR
3519 "import\n")
3520 {
3521 struct bgp *bgp;
3522 struct rfapi *h;
3523 struct rfapi_import_table *it;
3524 char *s;
3525 int first_l2 = 1;
3526
3527 /*
3528 * Show all import tables
3529 */
3530
3531 bgp = bgp_get_default(); /* assume 1 instance for now */
3532 if (!bgp) {
3533 vty_out(vty, "No BGP instance\n");
3534 return CMD_WARNING_CONFIG_FAILED;
3535 }
3536
3537 h = bgp->rfapi;
3538 if (!h) {
3539 vty_out(vty, "No RFAPI instance\n");
3540 return CMD_WARNING_CONFIG_FAILED;
3541 }
3542
3543 /*
3544 * Iterate over all import tables; do a filtered import
3545 * for the afi/safi combination
3546 */
3547
3548
3549 for (it = h->imports; it; it = it->next) {
3550 s = ecommunity_ecom2str(it->rt_import_list,
3551 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
3552 vty_out(vty, "Import Table %p, RTs: %s\n", it, s);
3553 XFREE(MTYPE_ECOMMUNITY_STR, s);
3554
3555 rfapiShowImportTable(vty, "IP VPN", it->imported_vpn[AFI_IP],
3556 1);
3557 rfapiShowImportTable(vty, "IP ENCAP",
3558 it->imported_encap[AFI_IP], 0);
3559 rfapiShowImportTable(vty, "IP6 VPN", it->imported_vpn[AFI_IP6],
3560 1);
3561 rfapiShowImportTable(vty, "IP6 ENCAP",
3562 it->imported_encap[AFI_IP6], 0);
3563 }
3564
3565 if (h->import_mac) {
3566 void *cursor = NULL;
3567 uint32_t lni;
3568 uintptr_t lni_as_ptr;
3569 int rc;
3570 char buf[BUFSIZ];
3571
3572 for (rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr,
3573 (void **)&it, &cursor);
3574 !rc;
3575 rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr,
3576 (void **)&it, &cursor)) {
3577
3578 if (it->imported_vpn[AFI_L2VPN]) {
3579 lni = lni_as_ptr;
3580 if (first_l2) {
3581 vty_out(vty,
3582 "\nLNI-based Ethernet Tables:\n");
3583 first_l2 = 0;
3584 }
3585 snprintf(buf, BUFSIZ, "L2VPN LNI=%u", lni);
3586 rfapiShowImportTable(
3587 vty, buf, it->imported_vpn[AFI_L2VPN],
3588 1);
3589 }
3590 }
3591 }
3592
3593 rfapiShowImportTable(vty, "CE IT - IP VPN",
3594 h->it_ce->imported_vpn[AFI_IP], 1);
3595
3596 return CMD_SUCCESS;
3597 }
3598
3599 DEFUN (debug_rfapi_show_import_vn_un,
3600 debug_rfapi_show_import_vn_un_cmd,
3601 "debug rfapi-dev show import vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
3602 DEBUG_STR
3603 DEBUG_RFAPI_STR
3604 SHOW_STR
3605 "import\n"
3606 "indicate vn addr follows\n"
3607 "virtual network interface IPv4 address\n"
3608 "virtual network interface IPv6 address\n"
3609 "indicate xt addr follows\n"
3610 "underlay network interface IPv4 address\n"
3611 "underlay network interface IPv6 address\n")
3612 {
3613 struct rfapi_ip_addr vn;
3614 struct rfapi_ip_addr un;
3615 rfapi_handle handle;
3616 int rc;
3617 struct rfapi_descriptor *rfd;
3618
3619 /*
3620 * Get VN addr
3621 */
3622 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[5]->arg, &vn)))
3623 return rc;
3624
3625
3626 /*
3627 * Get UN addr
3628 */
3629 if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[7]->arg, &un)))
3630 return rc;
3631
3632
3633 if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3634 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3635 argv[5]->arg, argv[7]->arg);
3636 return CMD_WARNING_CONFIG_FAILED;
3637 }
3638
3639 rfd = (struct rfapi_descriptor *)handle;
3640
3641 rfapiShowImportTable(vty, "IP VPN",
3642 rfd->import_table->imported_vpn[AFI_IP], 1);
3643 rfapiShowImportTable(vty, "IP ENCAP",
3644 rfd->import_table->imported_encap[AFI_IP], 0);
3645 rfapiShowImportTable(vty, "IP6 VPN",
3646 rfd->import_table->imported_vpn[AFI_IP6], 1);
3647 rfapiShowImportTable(vty, "IP6 ENCAP",
3648 rfd->import_table->imported_encap[AFI_IP6], 0);
3649
3650 return CMD_SUCCESS;
3651 }
3652
3653 DEFUN (debug_rfapi_response_omit_self,
3654 debug_rfapi_response_omit_self_cmd,
3655 "debug rfapi-dev response-omit-self <on|off>",
3656 DEBUG_STR
3657 DEBUG_RFAPI_STR
3658 "Omit self in RFP responses\n"
3659 "filter out self from responses\n" "leave self in responses\n")
3660 {
3661 struct bgp *bgp = bgp_get_default();
3662
3663 if (!bgp) {
3664 vty_out(vty, "No BGP process is configured\n");
3665 return CMD_WARNING_CONFIG_FAILED;
3666 }
3667 if (!bgp->rfapi_cfg) {
3668 vty_out(vty, "VNC not configured\n");
3669 return CMD_WARNING_CONFIG_FAILED;
3670 }
3671
3672 if (strmatch(argv[3]->text, "on"))
3673 SET_FLAG(bgp->rfapi_cfg->flags,
3674 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP);
3675 else
3676 UNSET_FLAG(bgp->rfapi_cfg->flags,
3677 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP);
3678
3679 return CMD_SUCCESS;
3680 }
3681
3682
3683 #ifdef RFAPI_DEBUG_SKIPLIST_CLI
3684
3685 #include "lib/skiplist.h"
3686 DEFUN (skiplist_test_cli,
3687 skiplist_test_cli_cmd,
3688 "skiplist test",
3689 "skiplist command\n"
3690 "test\n")
3691 {
3692 skiplist_test(vty);
3693
3694 return CMD_SUCCESS;
3695 }
3696
3697 DEFUN (skiplist_debug_cli,
3698 skiplist_debug_cli_cmd,
3699 "skiplist debug",
3700 "skiplist command\n"
3701 "debug\n")
3702 {
3703 skiplist_debug(vty, NULL);
3704 return CMD_SUCCESS;
3705 }
3706
3707 #endif /* RFAPI_DEBUG_SKIPLIST_CLI */
3708
3709 void rfapi_init(void)
3710 {
3711 bgp_rfapi_cfg_init();
3712 vnc_debug_init();
3713
3714 install_element(ENABLE_NODE, &debug_rfapi_show_import_cmd);
3715 install_element(ENABLE_NODE, &debug_rfapi_show_import_vn_un_cmd);
3716
3717 install_element(ENABLE_NODE, &debug_rfapi_open_cmd);
3718 install_element(ENABLE_NODE, &debug_rfapi_close_vn_un_cmd);
3719 install_element(ENABLE_NODE, &debug_rfapi_close_rfd_cmd);
3720 install_element(ENABLE_NODE, &debug_rfapi_register_vn_un_cmd);
3721 install_element(ENABLE_NODE, &debug_rfapi_unregister_vn_un_cmd);
3722 install_element(ENABLE_NODE, &debug_rfapi_query_vn_un_cmd);
3723 install_element(ENABLE_NODE, &debug_rfapi_query_vn_un_done_cmd);
3724 install_element(ENABLE_NODE, &debug_rfapi_query_vn_un_l2o_cmd);
3725
3726 install_element(ENABLE_NODE, &debug_rfapi_response_omit_self_cmd);
3727
3728 /* Need the following show commands for gpz test scripts */
3729 install_element(ENABLE_NODE, &debug_rfapi_show_nves_cmd);
3730 install_element(ENABLE_NODE, &debug_rfapi_show_nves_vn_un_cmd);
3731 install_element(ENABLE_NODE, &debug_rfapi_register_vn_un_l2o_cmd);
3732
3733 #ifdef RFAPI_DEBUG_SKIPLIST_CLI
3734 install_element(ENABLE_NODE, &skiplist_test_cli_cmd);
3735 install_element(ENABLE_NODE, &skiplist_debug_cli_cmd);
3736 #endif
3737
3738 rfapi_vty_init();
3739 }
3740
3741 #ifdef DEBUG_RFAPI
3742 static void rfapi_print_exported(struct bgp *bgp)
3743 {
3744 struct bgp_node *rdn;
3745 struct bgp_node *rn;
3746 struct bgp_info *bi;
3747
3748 if (!bgp)
3749 return;
3750
3751 for (rdn = bgp_table_top(bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rdn;
3752 rdn = bgp_route_next(rdn)) {
3753 if (!rdn->info)
3754 continue;
3755 fprintf(stderr, "%s: vpn rdn=%p\n", __func__, rdn);
3756 for (rn = bgp_table_top(rdn->info); rn;
3757 rn = bgp_route_next(rn)) {
3758 if (!rn->info)
3759 continue;
3760 fprintf(stderr, "%s: rn=%p\n", __func__, rn);
3761 for (bi = rn->info; bi; bi = bi->next) {
3762 rfapiPrintBi((void *)2, bi); /* 2 => stderr */
3763 }
3764 }
3765 }
3766 for (rdn = bgp_table_top(bgp->rib[AFI_IP][SAFI_ENCAP]); rdn;
3767 rdn = bgp_route_next(rdn)) {
3768 if (!rdn->info)
3769 continue;
3770 fprintf(stderr, "%s: encap rdn=%p\n", __func__, rdn);
3771 for (rn = bgp_table_top(rdn->info); rn;
3772 rn = bgp_route_next(rn)) {
3773 if (!rn->info)
3774 continue;
3775 fprintf(stderr, "%s: rn=%p\n", __func__, rn);
3776 for (bi = rn->info; bi; bi = bi->next) {
3777 rfapiPrintBi((void *)2, bi); /* 2 => stderr */
3778 }
3779 }
3780 }
3781 }
3782 #endif /* defined(DEBUG_RFAPI) */
3783
3784 /*
3785 * Free all memory to prepare for clean exit as seen by valgrind memcheck
3786 */
3787 void rfapi_delete(struct bgp *bgp)
3788 {
3789 extern void rfp_clear_vnc_nve_all(void); /* can't fix correctly yet */
3790
3791 /*
3792 * This clears queries and registered routes, and closes nves
3793 */
3794 if (bgp->rfapi)
3795 rfp_clear_vnc_nve_all();
3796 bgp_rfapi_cfg_destroy(bgp, bgp->rfapi_cfg);
3797 bgp->rfapi_cfg = NULL;
3798 bgp_rfapi_destroy(bgp, bgp->rfapi);
3799 bgp->rfapi = NULL;
3800 #ifdef DEBUG_RFAPI
3801 /*
3802 * show what's left in the BGP MPLSVPN RIB
3803 */
3804 rfapi_print_exported(bgp);
3805 #endif
3806 }
3807
3808 int rfapi_set_autord_from_vn(struct prefix_rd *rd, struct rfapi_ip_addr *vn)
3809 {
3810 vnc_zlog_debug_verbose("%s: auto-assigning RD", __func__);
3811 if (vn->addr_family != AF_INET && vn->addr_family != AF_INET6) {
3812 vnc_zlog_debug_verbose(
3813 "%s: can't auto-assign RD, VN addr family is not IPv4"
3814 "|v6",
3815 __func__);
3816 return EAFNOSUPPORT;
3817 }
3818 rd->family = AF_UNSPEC;
3819 rd->prefixlen = 64;
3820 rd->val[1] = RD_TYPE_IP;
3821 if (vn->addr_family == AF_INET) {
3822 memcpy(rd->val + 2, &vn->addr.v4.s_addr, 4);
3823 } else { /* is v6 */
3824 memcpy(rd->val + 2, &vn->addr.v6.s6_addr32[3],
3825 4); /* low order 4 bytes */
3826 }
3827 {
3828 char buf[BUFSIZ];
3829 buf[0] = 0;
3830 prefix_rd2str(rd, buf, BUFSIZ);
3831 buf[BUFSIZ - 1] = 0;
3832 vnc_zlog_debug_verbose("%s: auto-RD is set to %s", __func__,
3833 buf);
3834 }
3835 return 0;
3836 }
3837
3838 /*------------------------------------------
3839 * rfapi_bgp_lookup_by_rfp
3840 *
3841 * Find bgp instance pointer based on value returned by rfp_start
3842 *
3843 * input:
3844 * rfp_start_val value returned by rfp_startor
3845 * NULL (=get default instance)
3846 *
3847 * output:
3848 * none
3849 *
3850 * return value:
3851 * bgp bgp instance pointer
3852 * NULL = not found
3853 *
3854 --------------------------------------------*/
3855 struct bgp *rfapi_bgp_lookup_by_rfp(void *rfp_start_val)
3856 {
3857 struct bgp *bgp = NULL;
3858 struct listnode *node, *nnode;
3859
3860 if (rfp_start_val == NULL)
3861 bgp = bgp_get_default();
3862 else
3863 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3864 if (bgp->rfapi != NULL
3865 && bgp->rfapi->rfp == rfp_start_val)
3866 return bgp;
3867 return bgp;
3868 }
3869
3870 /*------------------------------------------
3871 * rfapi_get_rfp_start_val_by_bgp
3872 *
3873 * Find bgp instance pointer based on value returned by rfp_start
3874 *
3875 * input:
3876 * bgp bgp instance pointer
3877 *
3878 * output:
3879 * none
3880 *
3881 * return value:
3882 * rfp_start_val
3883 * NULL = not found
3884 *
3885 --------------------------------------------*/
3886 void *rfapi_get_rfp_start_val_by_bgp(struct bgp *bgp)
3887 {
3888 if (!bgp || !bgp->rfapi)
3889 return NULL;
3890 return bgp->rfapi->rfp;
3891 }
3892
3893 /***********************************************************************
3894 * RFP group specific configuration
3895 ***********************************************************************/
3896 static void *rfapi_rfp_get_or_init_group_config_default(struct rfapi_cfg *rfc,
3897 struct vty *vty,
3898 uint32_t size)
3899 {
3900 if (rfc->default_rfp_cfg == NULL && size > 0) {
3901 rfc->default_rfp_cfg = XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG, size);
3902 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__,
3903 size);
3904 }
3905 return rfc->default_rfp_cfg;
3906 }
3907
3908 static void *rfapi_rfp_get_or_init_group_config_nve(struct rfapi_cfg *rfc,
3909 struct vty *vty,
3910 uint32_t size)
3911 {
3912 struct rfapi_nve_group_cfg *rfg =
3913 VTY_GET_CONTEXT_SUB(rfapi_nve_group_cfg);
3914
3915 /* make sure group is still in list */
3916 if (!rfg || !listnode_lookup(rfc->nve_groups_sequential, rfg)) {
3917 /* Not in list anymore */
3918 vty_out(vty, "Current NVE group no longer exists\n");
3919 return NULL;
3920 }
3921
3922 if (rfg->rfp_cfg == NULL && size > 0) {
3923 rfg->rfp_cfg = XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG, size);
3924 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__,
3925 size);
3926 }
3927 return rfg->rfp_cfg;
3928 }
3929
3930 static void *rfapi_rfp_get_or_init_group_config_l2(struct rfapi_cfg *rfc,
3931 struct vty *vty,
3932 uint32_t size)
3933 {
3934 struct rfapi_l2_group_cfg *rfg =
3935 VTY_GET_CONTEXT_SUB(rfapi_l2_group_cfg);
3936
3937 /* make sure group is still in list */
3938 if (!rfg || !listnode_lookup(rfc->l2_groups, rfg)) {
3939 /* Not in list anymore */
3940 vty_out(vty, "Current L2 group no longer exists\n");
3941 return NULL;
3942 }
3943 if (rfg->rfp_cfg == NULL && size > 0) {
3944 rfg->rfp_cfg = XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG, size);
3945 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__,
3946 size);
3947 }
3948 return rfg->rfp_cfg;
3949 }
3950
3951 /*------------------------------------------
3952 * rfapi_rfp_init_group_config_ptr_vty
3953 *
3954 * This is used to init or return a previously init'ed group specific
3955 * configuration pointer. Group is identified by vty context.
3956 * NOTE: size is ignored when a previously init'ed value is returned.
3957 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
3958 * bgp restart or shutdown.
3959 *
3960 * input:
3961 * rfp_start_val value returned by rfp_start
3962 * type group type
3963 * vty quagga vty context
3964 * size number of bytes to allocation
3965 *
3966 * output:
3967 * none
3968 *
3969 * return value:
3970 * rfp_cfg_group NULL or Pointer to configuration structure
3971 --------------------------------------------*/
3972 void *rfapi_rfp_init_group_config_ptr_vty(void *rfp_start_val,
3973 rfapi_rfp_cfg_group_type type,
3974 struct vty *vty, uint32_t size)
3975 {
3976 struct bgp *bgp;
3977 void *ret = NULL;
3978
3979 if (rfp_start_val == NULL || vty == NULL)
3980 return NULL;
3981
3982 bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
3983 if (!bgp || !bgp->rfapi_cfg)
3984 return NULL;
3985
3986 switch (type) {
3987 case RFAPI_RFP_CFG_GROUP_DEFAULT:
3988 ret = rfapi_rfp_get_or_init_group_config_default(bgp->rfapi_cfg,
3989 vty, size);
3990 break;
3991 case RFAPI_RFP_CFG_GROUP_NVE:
3992 ret = rfapi_rfp_get_or_init_group_config_nve(bgp->rfapi_cfg,
3993 vty, size);
3994 break;
3995 case RFAPI_RFP_CFG_GROUP_L2:
3996 ret = rfapi_rfp_get_or_init_group_config_l2(bgp->rfapi_cfg, vty,
3997 size);
3998 break;
3999 default:
4000 zlog_err("%s: Unknown group type=%d", __func__, type);
4001 /* should never happen */
4002 assert("Unknown type" == NULL);
4003 break;
4004 }
4005 return ret;
4006 }
4007
4008 /*------------------------------------------
4009 * rfapi_rfp_get_group_config_ptr_vty
4010 *
4011 * This is used to get group specific configuration pointer.
4012 * Group is identified by type and vty context.
4013 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
4014 * bgp restart or shutdown.
4015 *
4016 * input:
4017 * rfp_start_val value returned by rfp_start
4018 * type group type
4019 * vty quagga vty context
4020 *
4021 * output:
4022 * none
4023 *
4024 * return value:
4025 * rfp_cfg_group Pointer to configuration structure
4026 --------------------------------------------*/
4027 void *rfapi_rfp_get_group_config_ptr_vty(void *rfp_start_val,
4028 rfapi_rfp_cfg_group_type type,
4029 struct vty *vty)
4030 {
4031 return rfapi_rfp_init_group_config_ptr_vty(rfp_start_val, type, vty, 0);
4032 }
4033
4034 static void *
4035 rfapi_rfp_get_group_config_name_nve(struct rfapi_cfg *rfc, const char *name,
4036 void *criteria,
4037 rfp_group_config_search_cb_t *search_cb)
4038 {
4039 struct rfapi_nve_group_cfg *rfg;
4040 struct listnode *node;
4041
4042 for (ALL_LIST_ELEMENTS_RO(rfc->nve_groups_sequential, node, rfg)) {
4043 if (!strcmp(rfg->name, name) && /* name match */
4044 (search_cb == NULL || !search_cb(criteria, rfg->rfp_cfg)))
4045 return rfg->rfp_cfg;
4046 }
4047 return NULL;
4048 }
4049
4050 static void *
4051 rfapi_rfp_get_group_config_name_l2(struct rfapi_cfg *rfc, const char *name,
4052 void *criteria,
4053 rfp_group_config_search_cb_t *search_cb)
4054 {
4055 struct rfapi_l2_group_cfg *rfg;
4056 struct listnode *node;
4057
4058 for (ALL_LIST_ELEMENTS_RO(rfc->l2_groups, node, rfg)) {
4059 if (!strcmp(rfg->name, name) && /* name match */
4060 (search_cb == NULL || !search_cb(criteria, rfg->rfp_cfg)))
4061 return rfg->rfp_cfg;
4062 }
4063 return NULL;
4064 }
4065
4066 /*------------------------------------------
4067 * rfapi_rfp_get_group_config_ptr_name
4068 *
4069 * This is used to get group specific configuration pointer.
4070 * Group is identified by type and name context.
4071 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
4072 * bgp restart or shutdown.
4073 *
4074 * input:
4075 * rfp_start_val value returned by rfp_start
4076 * type group type
4077 * name group name
4078 * criteria RFAPI caller provided serach criteria
4079 * search_cb optional rfp_group_config_search_cb_t
4080 *
4081 * output:
4082 * none
4083 *
4084 * return value:
4085 * rfp_cfg_group Pointer to configuration structure
4086 --------------------------------------------*/
4087 void *rfapi_rfp_get_group_config_ptr_name(
4088 void *rfp_start_val, rfapi_rfp_cfg_group_type type, const char *name,
4089 void *criteria, rfp_group_config_search_cb_t *search_cb)
4090 {
4091 struct bgp *bgp;
4092 void *ret = NULL;
4093
4094 if (rfp_start_val == NULL || name == NULL)
4095 return NULL;
4096
4097 bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
4098 if (!bgp || !bgp->rfapi_cfg)
4099 return NULL;
4100
4101 switch (type) {
4102 case RFAPI_RFP_CFG_GROUP_DEFAULT:
4103 ret = bgp->rfapi_cfg->default_rfp_cfg;
4104 break;
4105 case RFAPI_RFP_CFG_GROUP_NVE:
4106 ret = rfapi_rfp_get_group_config_name_nve(bgp->rfapi_cfg, name,
4107 criteria, search_cb);
4108 break;
4109 case RFAPI_RFP_CFG_GROUP_L2:
4110 ret = rfapi_rfp_get_group_config_name_l2(bgp->rfapi_cfg, name,
4111 criteria, search_cb);
4112 break;
4113 default:
4114 zlog_err("%s: Unknown group type=%d", __func__, type);
4115 /* should never happen */
4116 assert("Unknown type" == NULL);
4117 break;
4118 }
4119 return ret;
4120 }
4121
4122 /*------------------------------------------
4123 * rfapi_rfp_get_l2_group_config_ptr_lni
4124 *
4125 * This is used to get group specific configuration pointer.
4126 * Group is identified by type and logical network identifier.
4127 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
4128 * bgp restart or shutdown.
4129 *
4130 * input:
4131 * rfp_start_val value returned by rfp_start
4132 * type group type
4133 * logical_net_id group logical network identifier
4134 * criteria RFAPI caller provided serach criteria
4135 * search_cb optional rfp_group_config_search_cb_t
4136 *
4137 * output:
4138 * none
4139 *
4140 * return value:
4141 * rfp_cfg_group Pointer to configuration structure
4142 --------------------------------------------*/
4143 void *
4144 rfapi_rfp_get_l2_group_config_ptr_lni(void *rfp_start_val,
4145 uint32_t logical_net_id, void *criteria,
4146 rfp_group_config_search_cb_t *search_cb)
4147 {
4148 struct bgp *bgp;
4149 struct rfapi_l2_group_cfg *rfg;
4150 struct listnode *node;
4151
4152 if (rfp_start_val == NULL)
4153 return NULL;
4154
4155 bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
4156 if (!bgp || !bgp->rfapi_cfg)
4157 return NULL;
4158
4159 for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->l2_groups, node, rfg)) {
4160 if (rfg->logical_net_id == logical_net_id
4161 && (search_cb == NULL
4162 || !search_cb(criteria, rfg->rfp_cfg))) {
4163 if (rfg->rfp_cfg == NULL)
4164 vnc_zlog_debug_verbose(
4165 "%s: returning rfp group config for lni=0",
4166 __func__);
4167 return rfg->rfp_cfg;
4168 }
4169 }
4170 return NULL;
4171 }