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