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