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