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