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