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