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