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