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