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