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