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