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