]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/rfapi/vnc_zebra.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / bgpd / rfapi / vnc_zebra.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 *
4 * Copyright 2009-2016, LabN Consulting, L.L.C.
5 *
6 */
7
8 /*
9 * File: vnc_zebra.c
10 * Purpose: Handle exchange of routes between VNC and Zebra
11 */
12
13 #include "lib/zebra.h"
14 #include "lib/prefix.h"
15 #include "lib/agg_table.h"
16 #include "lib/log.h"
17 #include "lib/command.h"
18 #include "lib/zclient.h"
19 #include "lib/stream.h"
20 #include "lib/ringbuf.h"
21 #include "lib/memory.h"
22 #include "lib/lib_errors.h"
23
24 #include "bgpd/bgpd.h"
25 #include "bgpd/bgp_ecommunity.h"
26 #include "bgpd/bgp_route.h"
27 #include "bgpd/bgp_debug.h"
28 #include "bgpd/bgp_advertise.h"
29
30 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
31 #include "bgpd/rfapi/rfapi.h"
32 #include "bgpd/rfapi/rfapi_import.h"
33 #include "bgpd/rfapi/rfapi_private.h"
34 #include "bgpd/rfapi/vnc_zebra.h"
35 #include "bgpd/rfapi/rfapi_vty.h"
36 #include "bgpd/rfapi/rfapi_backend.h"
37 #include "bgpd/rfapi/vnc_debug.h"
38
39 static struct rfapi_descriptor vncHD1VR; /* Single-VR export dummy nve descr */
40 static struct zclient *zclient_vnc = NULL;
41
42 /***********************************************************************
43 * REDISTRIBUTE: Zebra sends updates/withdraws to BGPD
44 ***********************************************************************/
45
46 /*
47 * Routes coming from zebra get added to VNC here
48 */
49 static void vnc_redistribute_add(struct prefix *p, uint32_t metric,
50 uint8_t type)
51 {
52 struct bgp *bgp = bgp_get_default();
53 struct prefix_rd prd;
54 struct rfapi_ip_addr vnaddr;
55 afi_t afi;
56 uint32_t local_pref =
57 rfp_cost_to_localpref(metric > 255 ? 255 : metric);
58
59 if (!bgp)
60 return;
61
62 if (!bgp->rfapi_cfg) {
63 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
64 __func__);
65 return;
66 }
67
68 afi = family2afi(p->family);
69 if (!afi) {
70 vnc_zlog_debug_verbose("%s: unknown prefix address family %d",
71 __func__, p->family);
72 return;
73 }
74
75 if (!bgp->rfapi_cfg->redist[afi][type]) {
76 vnc_zlog_debug_verbose(
77 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d] is 0, skipping",
78 __func__, afi, type);
79 return;
80 }
81 if (!bgp->rfapi_cfg->rfg_redist) {
82 vnc_zlog_debug_verbose("%s: no redist nve group, skipping",
83 __func__);
84 return;
85 }
86
87 /*
88 * Assume nve group's configured VN address prefix is a host
89 * route which also happens to give the NVE VN address to use
90 * for redistributing into VNC.
91 */
92 vnaddr.addr_family = bgp->rfapi_cfg->rfg_redist->vn_prefix.family;
93 switch (bgp->rfapi_cfg->rfg_redist->vn_prefix.family) {
94 case AF_INET:
95 if (bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen
96 != IPV4_MAX_BITLEN) {
97 vnc_zlog_debug_verbose(
98 "%s: redist nve group VN prefix len (%d) != 32, skipping",
99 __func__,
100 bgp->rfapi_cfg->rfg_redist->vn_prefix
101 .prefixlen);
102 return;
103 }
104 vnaddr.addr.v4 =
105 bgp->rfapi_cfg->rfg_redist->vn_prefix.u.prefix4;
106 break;
107 case AF_INET6:
108 if (bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen
109 != IPV6_MAX_BITLEN) {
110 vnc_zlog_debug_verbose(
111 "%s: redist nve group VN prefix len (%d) != 128, skipping",
112 __func__,
113 bgp->rfapi_cfg->rfg_redist->vn_prefix
114 .prefixlen);
115 return;
116 }
117 vnaddr.addr.v6 =
118 bgp->rfapi_cfg->rfg_redist->vn_prefix.u.prefix6;
119 break;
120 default:
121 vnc_zlog_debug_verbose(
122 "%s: no redist nve group VN host prefix configured, skipping",
123 __func__);
124 return;
125 }
126
127 /*
128 * Assume nve group's configured UN address prefix is a host
129 * route which also happens to give the NVE UN address to use
130 * for redistributing into VNC.
131 */
132
133 /*
134 * Set UN address in dummy nve descriptor so add_vnc_route
135 * can use it in VNC tunnel SubTLV
136 */
137 {
138 struct rfapi_ip_prefix pfx_un;
139
140 rfapiQprefix2Rprefix(&bgp->rfapi_cfg->rfg_redist->un_prefix,
141 &pfx_un);
142
143 switch (pfx_un.prefix.addr_family) {
144 case AF_INET:
145 if (pfx_un.length != IPV4_MAX_BITLEN) {
146 vnc_zlog_debug_verbose(
147 "%s: redist nve group UN prefix len (%d) != 32, skipping",
148 __func__, pfx_un.length);
149 return;
150 }
151 break;
152 case AF_INET6:
153 if (pfx_un.length != IPV6_MAX_BITLEN) {
154 vnc_zlog_debug_verbose(
155 "%s: redist nve group UN prefix len (%d) != 128, skipping",
156 __func__, pfx_un.length);
157 return;
158 }
159 break;
160 default:
161 vnc_zlog_debug_verbose(
162 "%s: no redist nve group UN host prefix configured, skipping",
163 __func__);
164 return;
165 }
166
167 vncHD1VR.un_addr = pfx_un.prefix;
168
169 if (!vncHD1VR.peer) {
170 /*
171 * Same setup as in rfapi_open()
172 */
173 vncHD1VR.peer = peer_new(bgp);
174 vncHD1VR.peer->status =
175 Established; /* keep bgp core happy */
176 bgp_sync_delete(vncHD1VR.peer); /* don't need these */
177
178 /*
179 * since this peer is not on the I/O thread, this lock
180 * is not strictly necessary, but serves as a reminder
181 * to those who may meddle...
182 */
183 frr_with_mutex (&vncHD1VR.peer->io_mtx) {
184 // we don't need any I/O related facilities
185 if (vncHD1VR.peer->ibuf)
186 stream_fifo_free(vncHD1VR.peer->ibuf);
187 if (vncHD1VR.peer->obuf)
188 stream_fifo_free(vncHD1VR.peer->obuf);
189
190 if (vncHD1VR.peer->ibuf_work)
191 ringbuf_del(vncHD1VR.peer->ibuf_work);
192 if (vncHD1VR.peer->obuf_work)
193 stream_free(vncHD1VR.peer->obuf_work);
194
195 vncHD1VR.peer->ibuf = NULL;
196 vncHD1VR.peer->obuf = NULL;
197 vncHD1VR.peer->obuf_work = NULL;
198 vncHD1VR.peer->ibuf_work = NULL;
199 }
200
201 /* base code assumes have valid host pointer */
202 vncHD1VR.peer->host =
203 XSTRDUP(MTYPE_BGP_PEER_HOST, ".zebra.");
204
205 /* Mark peer as belonging to HD */
206 SET_FLAG(vncHD1VR.peer->flags, PEER_FLAG_IS_RFAPI_HD);
207 }
208 }
209
210 memset(&prd, 0, sizeof(prd));
211 prd = bgp->rfapi_cfg->rfg_redist->rd;
212 prd.family = AF_UNSPEC;
213 prd.prefixlen = 64;
214
215 add_vnc_route(&vncHD1VR, /* cookie + UN addr */
216 bgp, SAFI_MPLS_VPN, p, &prd, &vnaddr, &local_pref,
217 &(bgp->rfapi_cfg->redist_lifetime),
218 NULL, /* RFP options */
219 NULL, /* struct rfapi_un_option */
220 NULL, /* struct rfapi_vn_option */
221 bgp->rfapi_cfg->rfg_redist->rt_export_list, NULL,
222 NULL, /* label: default */
223 type, BGP_ROUTE_REDISTRIBUTE, 0); /* flags */
224 }
225
226 /*
227 * Route deletions from zebra propagate to VNC here
228 */
229 static void vnc_redistribute_delete(struct prefix *p, uint8_t type)
230 {
231 struct bgp *bgp = bgp_get_default();
232 struct prefix_rd prd;
233 afi_t afi;
234
235 if (!bgp)
236 return;
237
238 if (!bgp->rfapi_cfg) {
239 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
240 __func__);
241 return;
242 }
243 afi = family2afi(p->family);
244 if (!afi) {
245 vnc_zlog_debug_verbose("%s: unknown prefix address family %d",
246 __func__, p->family);
247 return;
248 }
249 if (!bgp->rfapi_cfg->redist[afi][type]) {
250 vnc_zlog_debug_verbose(
251 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d] is 0, skipping",
252 __func__, afi, type);
253 return;
254 }
255 if (!bgp->rfapi_cfg->rfg_redist) {
256 vnc_zlog_debug_verbose("%s: no redist nve group, skipping",
257 __func__);
258 return;
259 }
260
261 memset(&prd, 0, sizeof(prd));
262 prd = bgp->rfapi_cfg->rfg_redist->rd;
263 prd.family = AF_UNSPEC;
264 prd.prefixlen = 64;
265
266 del_vnc_route(&vncHD1VR, /* use dummy ptr as cookie */
267 vncHD1VR.peer, bgp, SAFI_MPLS_VPN, p, &prd, type,
268 BGP_ROUTE_REDISTRIBUTE, NULL, 0);
269 }
270
271 /*
272 * Flush all redistributed routes of type <type>
273 */
274 static void vnc_redistribute_withdraw(struct bgp *bgp, afi_t afi, uint8_t type)
275 {
276 struct prefix_rd prd;
277 struct bgp_table *table;
278 struct bgp_dest *pdest;
279 struct bgp_dest *dest;
280
281 vnc_zlog_debug_verbose("%s: entry", __func__);
282
283 if (!bgp)
284 return;
285 if (!bgp->rfapi_cfg) {
286 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
287 __func__);
288 return;
289 }
290
291 /*
292 * Loop over all the RDs
293 */
294 for (pdest = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); pdest;
295 pdest = bgp_route_next(pdest)) {
296 const struct prefix *pdest_p = bgp_dest_get_prefix(pdest);
297
298 memset(&prd, 0, sizeof(prd));
299 prd.family = AF_UNSPEC;
300 prd.prefixlen = 64;
301 memcpy(prd.val, pdest_p->u.val, 8);
302
303 /* This is the per-RD table of prefixes */
304 table = bgp_dest_get_bgp_table_info(pdest);
305 if (!table)
306 continue;
307
308 for (dest = bgp_table_top(table); dest;
309 dest = bgp_route_next(dest)) {
310
311 struct bgp_path_info *ri;
312
313 for (ri = bgp_dest_get_bgp_path_info(dest); ri;
314 ri = ri->next) {
315 if (ri->type
316 == type) { /* has matching redist type */
317 break;
318 }
319 }
320 if (ri) {
321 del_vnc_route(
322 &vncHD1VR, /* use dummy ptr as cookie */
323 vncHD1VR.peer, bgp, SAFI_MPLS_VPN,
324 bgp_dest_get_prefix(dest), &prd, type,
325 BGP_ROUTE_REDISTRIBUTE, NULL, 0);
326 }
327 }
328 }
329 vnc_zlog_debug_verbose("%s: return", __func__);
330 }
331
332 /*
333 * Zebra route add and delete treatment.
334 *
335 * Assumes 1 nexthop
336 */
337 static int vnc_zebra_read_route(ZAPI_CALLBACK_ARGS)
338 {
339 struct zapi_route api;
340 int add;
341
342 if (zapi_route_decode(zclient->ibuf, &api) < 0)
343 return -1;
344
345 /* we completely ignore srcdest routes for now. */
346 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
347 return 0;
348
349 add = (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
350 if (add)
351 vnc_redistribute_add(&api.prefix, api.metric, api.type);
352 else
353 vnc_redistribute_delete(&api.prefix, api.type);
354
355 if (BGP_DEBUG(zebra, ZEBRA))
356 vnc_zlog_debug_verbose(
357 "%s: Zebra rcvd: route delete %s %pFX metric %u",
358 __func__, zebra_route_string(api.type), &api.prefix,
359 api.metric);
360
361 return 0;
362 }
363
364 /***********************************************************************
365 * vnc_bgp_zebra_*: VNC sends updates/withdraws to Zebra
366 ***********************************************************************/
367
368 /*
369 * low-level message builder
370 */
371 static void vnc_zebra_route_msg(const struct prefix *p, unsigned int nhp_count,
372 void *nhp_ary, int add) /* 1 = add, 0 = del */
373 {
374 struct zapi_route api;
375 struct zapi_nexthop *api_nh;
376 int i;
377 struct in_addr **nhp_ary4 = nhp_ary;
378 struct in6_addr **nhp_ary6 = nhp_ary;
379
380 if (!nhp_count) {
381 vnc_zlog_debug_verbose("%s: empty nexthop list, skipping",
382 __func__);
383 return;
384 }
385
386 memset(&api, 0, sizeof(api));
387 api.vrf_id = VRF_DEFAULT;
388 api.type = ZEBRA_ROUTE_VNC;
389 api.safi = SAFI_UNICAST;
390 api.prefix = *p;
391
392 /* Nexthops */
393 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
394 api.nexthop_num = MIN(nhp_count, multipath_num);
395 for (i = 0; i < api.nexthop_num; i++) {
396
397 api_nh = &api.nexthops[i];
398 api_nh->vrf_id = VRF_DEFAULT;
399 switch (p->family) {
400 case AF_INET:
401 memcpy(&api_nh->gate.ipv4, nhp_ary4[i],
402 sizeof(api_nh->gate.ipv4));
403 api_nh->type = NEXTHOP_TYPE_IPV4;
404 break;
405 case AF_INET6:
406 memcpy(&api_nh->gate.ipv6, nhp_ary6[i],
407 sizeof(api_nh->gate.ipv6));
408 api_nh->type = NEXTHOP_TYPE_IPV6;
409 break;
410 }
411 }
412
413 if (BGP_DEBUG(zebra, ZEBRA))
414 vnc_zlog_debug_verbose(
415 "%s: Zebra send: route %s %pFX, nhp_count=%d", __func__,
416 (add ? "add" : "del"), &api.prefix, nhp_count);
417
418 zclient_route_send((add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE),
419 zclient_vnc, &api);
420 }
421
422
423 static void
424 nve_list_to_nh_array(uint8_t family, struct list *nve_list,
425 unsigned int *nh_count_ret,
426 void **nh_ary_ret, /* returned address array */
427 void **nhp_ary_ret) /* returned pointer array */
428 {
429 int nve_count = listcount(nve_list);
430
431 *nh_count_ret = 0;
432 *nh_ary_ret = NULL;
433 *nhp_ary_ret = NULL;
434
435 if (!nve_count) {
436 vnc_zlog_debug_verbose("%s: empty nve_list, skipping",
437 __func__);
438 return;
439 }
440
441 if (family == AF_INET) {
442 struct listnode *ln;
443 struct in_addr *iap;
444 struct in_addr **v;
445
446 /*
447 * Array of nexthop addresses
448 */
449 *nh_ary_ret =
450 XCALLOC(MTYPE_TMP, nve_count * sizeof(struct in_addr));
451
452 /*
453 * Array of pointers to nexthop addresses
454 */
455 *nhp_ary_ret = XCALLOC(MTYPE_TMP,
456 nve_count * sizeof(struct in_addr *));
457 iap = *nh_ary_ret;
458 v = *nhp_ary_ret;
459
460 for (ln = listhead(nve_list); ln; ln = listnextnode(ln)) {
461
462 struct rfapi_descriptor *irfd;
463 struct prefix nhp;
464
465 irfd = listgetdata(ln);
466
467 if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
468 continue;
469
470 *iap = nhp.u.prefix4;
471 *v = iap;
472 vnc_zlog_debug_verbose(
473 "%s: ipadr: (%p)<-0x%x, ptr: (%p)<-%p",
474 __func__, iap, nhp.u.prefix4.s_addr, v, iap);
475
476 ++iap;
477 ++v;
478 ++*nh_count_ret;
479 }
480
481 } else if (family == AF_INET6) {
482
483 struct listnode *ln;
484
485 *nh_ary_ret =
486 XCALLOC(MTYPE_TMP, nve_count * sizeof(struct in6_addr));
487
488 *nhp_ary_ret = XCALLOC(MTYPE_TMP,
489 nve_count * sizeof(struct in6_addr *));
490
491 for (ln = listhead(nve_list); ln; ln = listnextnode(ln)) {
492
493 struct rfapi_descriptor *irfd;
494 struct in6_addr *iap = *nh_ary_ret;
495 struct in6_addr **v = *nhp_ary_ret;
496 struct prefix nhp;
497
498 irfd = listgetdata(ln);
499
500 if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
501 continue;
502
503 *iap = nhp.u.prefix6;
504 *v = iap;
505
506 ++iap;
507 ++v;
508 ++*nh_count_ret;
509 }
510 }
511 }
512
513 static void import_table_to_nve_list_zebra(struct bgp *bgp,
514 struct rfapi_import_table *it,
515 struct list **nves, uint8_t family)
516 {
517 struct listnode *node;
518 struct rfapi_rfg_name *rfgn;
519
520 /*
521 * Loop over the list of NVE-Groups configured for
522 * exporting to direct-bgp.
523 *
524 * Build a list of NVEs that use this import table
525 */
526 *nves = NULL;
527 for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node,
528 rfgn)) {
529
530 /*
531 * If this NVE-Group's import table matches the current one
532 */
533 if (rfgn->rfg && rfgn->rfg->nves
534 && rfgn->rfg->rfapi_import_table == it) {
535
536 nve_group_to_nve_list(rfgn->rfg, nves, family);
537 }
538 }
539 }
540
541 static void vnc_zebra_add_del_prefix(struct bgp *bgp,
542 struct rfapi_import_table *import_table,
543 struct agg_node *rn,
544 int add) /* !0 = add, 0 = del */
545 {
546 struct list *nves;
547 const struct prefix *p = agg_node_get_prefix(rn);
548 unsigned int nexthop_count = 0;
549 void *nh_ary = NULL;
550 void *nhp_ary = NULL;
551
552 vnc_zlog_debug_verbose("%s: entry, add=%d", __func__, add);
553
554 if (zclient_vnc->sock < 0)
555 return;
556
557 if (p->family != AF_INET && p->family != AF_INET6) {
558 flog_err(EC_LIB_DEVELOPMENT,
559 "%s: invalid route node addr family", __func__);
560 return;
561 }
562
563 if (!vrf_bitmap_check(
564 zclient_vnc->redist[family2afi(p->family)][ZEBRA_ROUTE_VNC],
565 VRF_DEFAULT))
566 return;
567
568 if (!bgp->rfapi_cfg) {
569 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
570 __func__);
571 return;
572 }
573 if (!listcount(bgp->rfapi_cfg->rfg_export_zebra_l)) {
574 vnc_zlog_debug_verbose(
575 "%s: no zebra export nve group, skipping", __func__);
576 return;
577 }
578
579 import_table_to_nve_list_zebra(bgp, import_table, &nves, p->family);
580
581 if (nves) {
582 nve_list_to_nh_array(p->family, nves, &nexthop_count, &nh_ary,
583 &nhp_ary);
584
585 list_delete(&nves);
586
587 if (nexthop_count)
588 vnc_zebra_route_msg(p, nexthop_count, nhp_ary, add);
589 }
590
591 XFREE(MTYPE_TMP, nhp_ary);
592 XFREE(MTYPE_TMP, nh_ary);
593 }
594
595 void vnc_zebra_add_prefix(struct bgp *bgp,
596 struct rfapi_import_table *import_table,
597 struct agg_node *rn)
598 {
599 vnc_zebra_add_del_prefix(bgp, import_table, rn, 1);
600 }
601
602 void vnc_zebra_del_prefix(struct bgp *bgp,
603 struct rfapi_import_table *import_table,
604 struct agg_node *rn)
605 {
606 vnc_zebra_add_del_prefix(bgp, import_table, rn, 0);
607 }
608
609
610 static void vnc_zebra_add_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd,
611 int add) /* 0 = del, !0 = add */
612 {
613 struct listnode *node;
614 struct rfapi_rfg_name *rfgn;
615 struct rfapi_nve_group_cfg *rfg = rfd->rfg;
616 afi_t afi = family2afi(rfd->vn_addr.addr_family);
617 struct prefix nhp;
618 void *pAddr;
619
620 vnc_zlog_debug_verbose("%s: entry, add=%d", __func__, add);
621
622 if (zclient_vnc->sock < 0)
623 return;
624
625 if (!vrf_bitmap_check(zclient_vnc->redist[afi][ZEBRA_ROUTE_VNC],
626 VRF_DEFAULT))
627 return;
628
629 if (afi != AFI_IP && afi != AFI_IP6) {
630 flog_err(EC_LIB_DEVELOPMENT, "%s: invalid vn addr family",
631 __func__);
632 return;
633 }
634
635 if (!bgp)
636 return;
637 if (!bgp->rfapi_cfg) {
638 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
639 __func__);
640 return;
641 }
642
643 if (rfapiRaddr2Qprefix(&rfd->vn_addr, &nhp)) {
644 vnc_zlog_debug_verbose("%s: can't convert vn address, skipping",
645 __func__);
646 return;
647 }
648
649 pAddr = &nhp.u.val;
650
651 /*
652 * Loop over the list of NVE-Groups configured for
653 * exporting to zebra and see if this new NVE's
654 * group is among them.
655 */
656 for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node,
657 rfgn)) {
658
659 /*
660 * Yes, this NVE's group is configured for export to zebra
661 */
662 if (rfgn->rfg == rfg) {
663
664 struct agg_table *rt = NULL;
665 struct agg_node *rn;
666 struct rfapi_import_table *import_table;
667 import_table = rfg->rfapi_import_table;
668
669 vnc_zlog_debug_verbose(
670 "%s: this nve's group is in zebra export list",
671 __func__);
672
673 rt = import_table->imported_vpn[afi];
674
675 /*
676 * Walk the NVE-Group's VNC Import table
677 */
678 for (rn = agg_route_top(rt); rn;
679 rn = agg_route_next(rn)) {
680 if (!rn->info)
681 continue;
682
683 vnc_zlog_debug_verbose("%s: sending %s",
684 __func__,
685 (add ? "add" : "del"));
686 vnc_zebra_route_msg(agg_node_get_prefix(rn), 1,
687 &pAddr, add);
688 }
689 }
690 }
691 }
692
693 void vnc_zebra_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
694 {
695 vnc_zebra_add_del_nve(bgp, rfd, 1);
696 }
697
698 void vnc_zebra_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
699 {
700 vnc_zebra_add_del_nve(bgp, rfd, 0);
701 }
702
703 static void vnc_zebra_add_del_group_afi(struct bgp *bgp,
704 struct rfapi_nve_group_cfg *rfg,
705 afi_t afi, int add)
706 {
707 struct agg_table *rt = NULL;
708 struct agg_node *rn;
709 struct rfapi_import_table *import_table;
710 uint8_t family = afi2family(afi);
711
712 struct list *nves = NULL;
713 unsigned int nexthop_count = 0;
714 void *nh_ary = NULL;
715 void *nhp_ary = NULL;
716
717 vnc_zlog_debug_verbose("%s: entry", __func__);
718 import_table = rfg->rfapi_import_table;
719 if (!import_table) {
720 vnc_zlog_debug_verbose(
721 "%s: import table not defined, returning", __func__);
722 return;
723 }
724
725 if (afi == AFI_IP || afi == AFI_IP6) {
726 rt = import_table->imported_vpn[afi];
727 } else {
728 flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d", __func__, afi);
729 return;
730 }
731
732 if (!family) {
733 flog_err(EC_LIB_DEVELOPMENT, "%s: computed bad family: %d",
734 __func__, family);
735 return;
736 }
737
738 if (!rfg->nves) {
739 /* avoid segfault below if list doesn't exist */
740 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__);
741 return;
742 }
743
744 nve_group_to_nve_list(rfg, &nves, family);
745 if (nves) {
746 vnc_zlog_debug_verbose("%s: have nves", __func__);
747 nve_list_to_nh_array(family, nves, &nexthop_count, &nh_ary,
748 &nhp_ary);
749
750 vnc_zlog_debug_verbose("%s: family: %d, nve count: %d",
751 __func__, family, nexthop_count);
752
753 list_delete(&nves);
754
755 if (nexthop_count) {
756 /*
757 * Walk the NVE-Group's VNC Import table
758 */
759 for (rn = agg_route_top(rt); rn;
760 rn = agg_route_next(rn)) {
761 if (rn->info) {
762 vnc_zebra_route_msg(
763 agg_node_get_prefix(rn),
764 nexthop_count, nhp_ary, add);
765 }
766 }
767 }
768 XFREE(MTYPE_TMP, nhp_ary);
769 XFREE(MTYPE_TMP, nh_ary);
770 }
771 }
772
773 void vnc_zebra_add_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
774 {
775 vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP, 1);
776 vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP6, 1);
777 }
778
779 void vnc_zebra_del_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
780 {
781 vnc_zlog_debug_verbose("%s: entry", __func__);
782 vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP, 0);
783 vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP6, 0);
784 }
785
786 void vnc_zebra_reexport_group_afi(struct bgp *bgp,
787 struct rfapi_nve_group_cfg *rfg, afi_t afi)
788 {
789 struct listnode *node;
790 struct rfapi_rfg_name *rfgn;
791
792 for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node,
793 rfgn)) {
794
795 if (rfgn->rfg == rfg) {
796 vnc_zebra_add_del_group_afi(bgp, rfg, afi, 0);
797 vnc_zebra_add_del_group_afi(bgp, rfg, afi, 1);
798 break;
799 }
800 }
801 }
802
803
804 /***********************************************************************
805 * CONTROL INTERFACE
806 ***********************************************************************/
807
808
809 /* Other routes redistribution into BGP. */
810 int vnc_redistribute_set(struct bgp *bgp, afi_t afi, int type)
811 {
812 if (!bgp->rfapi_cfg) {
813 return CMD_WARNING_CONFIG_FAILED;
814 }
815
816 /* Set flag to BGP instance. */
817 bgp->rfapi_cfg->redist[afi][type] = 1;
818
819 // bgp->redist[afi][type] = 1;
820
821 /* Return if already redistribute flag is set. */
822 if (vrf_bitmap_check(zclient_vnc->redist[afi][type], VRF_DEFAULT))
823 return CMD_WARNING_CONFIG_FAILED;
824
825 vrf_bitmap_set(zclient_vnc->redist[afi][type], VRF_DEFAULT);
826
827 // vrf_bitmap_set(zclient_vnc->redist[afi][type], VRF_DEFAULT);
828
829 /* Return if zebra connection is not established. */
830 if (zclient_vnc->sock < 0)
831 return CMD_WARNING_CONFIG_FAILED;
832
833 if (BGP_DEBUG(zebra, ZEBRA))
834 vnc_zlog_debug_verbose("Zebra send: redistribute add %s",
835 zebra_route_string(type));
836
837 /* Send distribute add message to zebra. */
838 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient_vnc, afi, type,
839 0, VRF_DEFAULT);
840
841 return CMD_SUCCESS;
842 }
843
844 /* Unset redistribution. */
845 int vnc_redistribute_unset(struct bgp *bgp, afi_t afi, int type)
846 {
847 vnc_zlog_debug_verbose("%s: type=%d entry", __func__, type);
848
849 if (!bgp->rfapi_cfg) {
850 vnc_zlog_debug_verbose("%s: return (no rfapi_cfg)", __func__);
851 return CMD_WARNING_CONFIG_FAILED;
852 }
853
854 /* Unset flag from BGP instance. */
855 bgp->rfapi_cfg->redist[afi][type] = 0;
856
857 /* Return if zebra connection is disabled. */
858 if (!vrf_bitmap_check(zclient_vnc->redist[afi][type], VRF_DEFAULT))
859 return CMD_WARNING_CONFIG_FAILED;
860 vrf_bitmap_unset(zclient_vnc->redist[afi][type], VRF_DEFAULT);
861
862 if (bgp->rfapi_cfg->redist[AFI_IP][type] == 0
863 && bgp->rfapi_cfg->redist[AFI_IP6][type] == 0
864 && zclient_vnc->sock >= 0) {
865 /* Send distribute delete message to zebra. */
866 if (BGP_DEBUG(zebra, ZEBRA))
867 vnc_zlog_debug_verbose(
868 "Zebra send: redistribute delete %s",
869 zebra_route_string(type));
870 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient_vnc,
871 afi, type, 0, VRF_DEFAULT);
872 }
873
874 /* Withdraw redistributed routes from current BGP's routing table. */
875 vnc_redistribute_withdraw(bgp, afi, type);
876
877 vnc_zlog_debug_verbose("%s: return", __func__);
878
879 return CMD_SUCCESS;
880 }
881
882 extern struct zebra_privs_t bgpd_privs;
883
884 static zclient_handler *const vnc_handlers[] = {
885 [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = vnc_zebra_read_route,
886 [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = vnc_zebra_read_route,
887 };
888
889 /*
890 * Modeled after bgp_zebra.c'bgp_zebra_init()
891 * Charriere asks, "Is it possible to carry two?"
892 */
893 void vnc_zebra_init(struct thread_master *master)
894 {
895 /* Set default values. */
896 zclient_vnc = zclient_new(master, &zclient_options_default,
897 vnc_handlers, array_size(vnc_handlers));
898 zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0, &bgpd_privs);
899 }
900
901 void vnc_zebra_destroy(void)
902 {
903 if (zclient_vnc == NULL)
904 return;
905 zclient_stop(zclient_vnc);
906 zclient_free(zclient_vnc);
907 zclient_vnc = NULL;
908 }