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