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