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