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