]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/rfapi/vnc_zebra.c
isisd: Let's use an actual NULL pointer to test for a NULL pointer
[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"
fe08ba7e 28#include "lib/agg_table.h"
f8b6f499
LB
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"
02705213 35#include "lib/lib_errors.h"
65efcfce 36
f8b6f499
LB
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"
65efcfce 42
f8b6f499
LB
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"
a3b55c25 50#include "bgpd/rfapi/vnc_debug.h"
65efcfce 51
d62a17ae 52static struct rfapi_descriptor vncHD1VR; /* Single-VR export dummy nve descr */
65efcfce
LB
53static 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 */
d7c0a89a 62static void vnc_redistribute_add(struct prefix *p, uint32_t metric,
74489921 63 uint8_t type)
65efcfce 64{
d62a17ae 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:
12256b84
DA
108 if (bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen
109 != IPV4_MAX_BITLEN) {
d62a17ae 110 vnc_zlog_debug_verbose(
111 "%s: redist nve group VN prefix len (%d) != 32, skipping",
112 __func__,
113 bgp->rfapi_cfg->rfg_redist->vn_prefix
114 .prefixlen);
115 return;
116 }
117 vnaddr.addr.v4 =
118 bgp->rfapi_cfg->rfg_redist->vn_prefix.u.prefix4;
119 break;
120 case AF_INET6:
13ccce6e
DA
121 if (bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen
122 != IPV6_MAX_BITLEN) {
d62a17ae 123 vnc_zlog_debug_verbose(
124 "%s: redist nve group VN prefix len (%d) != 128, skipping",
125 __func__,
126 bgp->rfapi_cfg->rfg_redist->vn_prefix
127 .prefixlen);
128 return;
129 }
130 vnaddr.addr.v6 =
131 bgp->rfapi_cfg->rfg_redist->vn_prefix.u.prefix6;
132 break;
133 default:
134 vnc_zlog_debug_verbose(
135 "%s: no redist nve group VN host prefix configured, skipping",
136 __func__);
137 return;
138 }
139
140 /*
141 * Assume nve group's configured UN address prefix is a host
142 * route which also happens to give the NVE UN address to use
143 * for redistributing into VNC.
144 */
145
146 /*
147 * Set UN address in dummy nve descriptor so add_vnc_route
148 * can use it in VNC tunnel SubTLV
149 */
150 {
151 struct rfapi_ip_prefix pfx_un;
152
153 rfapiQprefix2Rprefix(&bgp->rfapi_cfg->rfg_redist->un_prefix,
154 &pfx_un);
155
156 switch (pfx_un.prefix.addr_family) {
157 case AF_INET:
12256b84 158 if (pfx_un.length != IPV4_MAX_BITLEN) {
d62a17ae 159 vnc_zlog_debug_verbose(
160 "%s: redist nve group UN prefix len (%d) != 32, skipping",
161 __func__, pfx_un.length);
162 return;
163 }
164 break;
165 case AF_INET6:
13ccce6e 166 if (pfx_un.length != IPV6_MAX_BITLEN) {
d62a17ae 167 vnc_zlog_debug_verbose(
168 "%s: redist nve group UN prefix len (%d) != 128, skipping",
169 __func__, pfx_un.length);
170 return;
171 }
172 break;
173 default:
174 vnc_zlog_debug_verbose(
175 "%s: no redist nve group UN host prefix configured, skipping",
176 __func__);
177 return;
178 }
179
180 vncHD1VR.un_addr = pfx_un.prefix;
181
182 if (!vncHD1VR.peer) {
183 /*
184 * Same setup as in rfapi_open()
185 */
186 vncHD1VR.peer = peer_new(bgp);
187 vncHD1VR.peer->status =
188 Established; /* keep bgp core happy */
189 bgp_sync_delete(vncHD1VR.peer); /* don't need these */
424ab01d 190
becedef6
QY
191 /*
192 * since this peer is not on the I/O thread, this lock
193 * is not strictly necessary, but serves as a reminder
194 * to those who may meddle...
195 */
00dffa8c 196 frr_with_mutex(&vncHD1VR.peer->io_mtx) {
424ab01d
QY
197 // we don't need any I/O related facilities
198 if (vncHD1VR.peer->ibuf)
199 stream_fifo_free(vncHD1VR.peer->ibuf);
200 if (vncHD1VR.peer->obuf)
201 stream_fifo_free(vncHD1VR.peer->obuf);
202
203 if (vncHD1VR.peer->ibuf_work)
74ffbfe6 204 ringbuf_del(vncHD1VR.peer->ibuf_work);
424ab01d
QY
205 if (vncHD1VR.peer->obuf_work)
206 stream_free(vncHD1VR.peer->obuf_work);
207
d62a17ae 208 vncHD1VR.peer->ibuf = NULL;
d62a17ae 209 vncHD1VR.peer->obuf = NULL;
424ab01d
QY
210 vncHD1VR.peer->obuf_work = NULL;
211 vncHD1VR.peer->ibuf_work = NULL;
d62a17ae 212 }
424ab01d 213
d62a17ae 214 /* base code assumes have valid host pointer */
215 vncHD1VR.peer->host =
216 XSTRDUP(MTYPE_BGP_PEER_HOST, ".zebra.");
217
218 /* Mark peer as belonging to HD */
219 SET_FLAG(vncHD1VR.peer->flags, PEER_FLAG_IS_RFAPI_HD);
220 }
221 }
222
223 memset(&prd, 0, sizeof(prd));
224 prd = bgp->rfapi_cfg->rfg_redist->rd;
225 prd.family = AF_UNSPEC;
226 prd.prefixlen = 64;
227
228 add_vnc_route(&vncHD1VR, /* cookie + UN addr */
229 bgp, SAFI_MPLS_VPN, p, &prd, &vnaddr, &local_pref,
230 &(bgp->rfapi_cfg->redist_lifetime),
231 NULL, /* RFP options */
232 NULL, /* struct rfapi_un_option */
233 NULL, /* struct rfapi_vn_option */
234 bgp->rfapi_cfg->rfg_redist->rt_export_list, NULL,
235 NULL, /* label: default */
236 type, BGP_ROUTE_REDISTRIBUTE, 0); /* flags */
65efcfce
LB
237}
238
239/*
240 * Route deletions from zebra propagate to VNC here
241 */
d62a17ae 242static void vnc_redistribute_delete(struct prefix *p, uint8_t type)
65efcfce 243{
d62a17ae 244 struct bgp *bgp = bgp_get_default();
245 struct prefix_rd prd;
246 afi_t afi;
247
248 if (!bgp)
249 return;
250
251 if (!bgp->rfapi_cfg) {
252 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
253 __func__);
254 return;
255 }
256 afi = family2afi(p->family);
257 if (!afi) {
258 vnc_zlog_debug_verbose("%s: unknown prefix address family %d",
259 __func__, p->family);
260 return;
261 }
262 if (!bgp->rfapi_cfg->redist[afi][type]) {
263 vnc_zlog_debug_verbose(
264 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d] is 0, skipping",
265 __func__, afi, type);
266 return;
267 }
268 if (!bgp->rfapi_cfg->rfg_redist) {
269 vnc_zlog_debug_verbose("%s: no redist nve group, skipping",
270 __func__);
271 return;
272 }
273
274 memset(&prd, 0, sizeof(prd));
275 prd = bgp->rfapi_cfg->rfg_redist->rd;
276 prd.family = AF_UNSPEC;
277 prd.prefixlen = 64;
278
279 del_vnc_route(&vncHD1VR, /* use dummy ptr as cookie */
280 vncHD1VR.peer, bgp, SAFI_MPLS_VPN, p, &prd, type,
281 BGP_ROUTE_REDISTRIBUTE, NULL, 0);
65efcfce
LB
282}
283
284/*
285 * Flush all redistributed routes of type <type>
286 */
d62a17ae 287static void vnc_redistribute_withdraw(struct bgp *bgp, afi_t afi, uint8_t type)
65efcfce 288{
d62a17ae 289 struct prefix_rd prd;
290 struct bgp_table *table;
9bcb3eef
DS
291 struct bgp_dest *pdest;
292 struct bgp_dest *dest;
d62a17ae 293
294 vnc_zlog_debug_verbose("%s: entry", __func__);
295
296 if (!bgp)
297 return;
298 if (!bgp->rfapi_cfg) {
299 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
300 __func__);
301 return;
302 }
303
304 /*
305 * Loop over all the RDs
306 */
9bcb3eef
DS
307 for (pdest = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); pdest;
308 pdest = bgp_route_next(pdest)) {
309 const struct prefix *pdest_p = bgp_dest_get_prefix(pdest);
b54892e0 310
d62a17ae 311 memset(&prd, 0, sizeof(prd));
312 prd.family = AF_UNSPEC;
313 prd.prefixlen = 64;
9bcb3eef 314 memcpy(prd.val, pdest_p->u.val, 8);
d62a17ae 315
316 /* This is the per-RD table of prefixes */
9bcb3eef 317 table = bgp_dest_get_bgp_table_info(pdest);
2eab1324
RW
318 if (!table)
319 continue;
d62a17ae 320
9bcb3eef
DS
321 for (dest = bgp_table_top(table); dest;
322 dest = bgp_route_next(dest)) {
d62a17ae 323
4b7e6066 324 struct bgp_path_info *ri;
d62a17ae 325
9bcb3eef 326 for (ri = bgp_dest_get_bgp_path_info(dest); ri;
6f94b685 327 ri = ri->next) {
d62a17ae 328 if (ri->type
329 == type) { /* has matching redist type */
330 break;
331 }
332 }
333 if (ri) {
334 del_vnc_route(
335 &vncHD1VR, /* use dummy ptr as cookie */
336 vncHD1VR.peer, bgp, SAFI_MPLS_VPN,
9bcb3eef 337 bgp_dest_get_prefix(dest), &prd, type,
d62a17ae 338 BGP_ROUTE_REDISTRIBUTE, NULL, 0);
339 }
340 }
341 }
342 vnc_zlog_debug_verbose("%s: return", __func__);
65efcfce
LB
343}
344
345/*
346 * Zebra route add and delete treatment.
347 *
348 * Assumes 1 nexthop
349 */
121f9dee 350static int vnc_zebra_read_route(ZAPI_CALLBACK_ARGS)
65efcfce 351{
74489921
RW
352 struct zapi_route api;
353 int add;
d62a17ae 354
74489921
RW
355 if (zapi_route_decode(zclient->ibuf, &api) < 0)
356 return -1;
65efcfce 357
74489921
RW
358 /* we completely ignore srcdest routes for now. */
359 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
d62a17ae 360 return 0;
361
121f9dee 362 add = (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
74489921
RW
363 if (add)
364 vnc_redistribute_add(&api.prefix, api.metric, api.type);
d62a17ae 365 else
74489921 366 vnc_redistribute_delete(&api.prefix, api.type);
d62a17ae 367
2dbe669b 368 if (BGP_DEBUG(zebra, ZEBRA))
74489921 369 vnc_zlog_debug_verbose(
2dbe669b
DA
370 "%s: Zebra rcvd: route delete %s %pFX metric %u",
371 __func__, zebra_route_string(api.type), &api.prefix,
74489921 372 api.metric);
d62a17ae 373
374 return 0;
65efcfce
LB
375}
376
377/***********************************************************************
378 * vnc_bgp_zebra_*: VNC sends updates/withdraws to Zebra
379 ***********************************************************************/
380
381/*
382 * low-level message builder
383 */
26a3ffd6 384static void vnc_zebra_route_msg(const struct prefix *p, unsigned int nhp_count,
a74e593b 385 void *nhp_ary, int add) /* 1 = add, 0 = del */
65efcfce 386{
2ad4f093
RW
387 struct zapi_route api;
388 struct zapi_nexthop *api_nh;
389 int i;
b40c5062
LB
390 struct in_addr **nhp_ary4 = nhp_ary;
391 struct in6_addr **nhp_ary6 = nhp_ary;
2ad4f093 392
d62a17ae 393 if (!nhp_count) {
394 vnc_zlog_debug_verbose("%s: empty nexthop list, skipping",
395 __func__);
396 return;
397 }
398
2ad4f093
RW
399 memset(&api, 0, sizeof(api));
400 api.vrf_id = VRF_DEFAULT;
401 api.type = ZEBRA_ROUTE_VNC;
402 api.safi = SAFI_UNICAST;
403 api.prefix = *p;
404
405 /* Nexthops */
406 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
a74e593b
RW
407 api.nexthop_num = MIN(nhp_count, multipath_num);
408 for (i = 0; i < api.nexthop_num; i++) {
2ad4f093
RW
409
410 api_nh = &api.nexthops[i];
4a7371e9 411 api_nh->vrf_id = VRF_DEFAULT;
2ad4f093
RW
412 switch (p->family) {
413 case AF_INET:
b40c5062 414 memcpy(&api_nh->gate.ipv4, nhp_ary4[i],
9913029c
RW
415 sizeof(api_nh->gate.ipv4));
416 api_nh->type = NEXTHOP_TYPE_IPV4;
2ad4f093
RW
417 break;
418 case AF_INET6:
b40c5062 419 memcpy(&api_nh->gate.ipv6, nhp_ary6[i],
9913029c
RW
420 sizeof(api_nh->gate.ipv6));
421 api_nh->type = NEXTHOP_TYPE_IPV6;
2ad4f093 422 break;
9913029c 423 }
2ad4f093 424 }
9913029c 425
2dbe669b 426 if (BGP_DEBUG(zebra, ZEBRA))
d62a17ae 427 vnc_zlog_debug_verbose(
2dbe669b
DA
428 "%s: Zebra send: route %s %pFX, nhp_count=%d", __func__,
429 (add ? "add" : "del"), &api.prefix, nhp_count);
2ad4f093
RW
430
431 zclient_route_send((add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE),
432 zclient_vnc, &api);
65efcfce
LB
433}
434
435
436static void
d7c0a89a 437nve_list_to_nh_array(uint8_t family, struct list *nve_list,
a74e593b 438 unsigned int *nh_count_ret,
d62a17ae 439 void **nh_ary_ret, /* returned address array */
440 void **nhp_ary_ret) /* returned pointer array */
65efcfce 441{
d62a17ae 442 int nve_count = listcount(nve_list);
65efcfce 443
d62a17ae 444 *nh_count_ret = 0;
445 *nh_ary_ret = NULL;
446 *nhp_ary_ret = NULL;
65efcfce 447
d62a17ae 448 if (!nve_count) {
449 vnc_zlog_debug_verbose("%s: empty nve_list, skipping",
450 __func__);
451 return;
452 }
65efcfce 453
d62a17ae 454 if (family == AF_INET) {
455 struct listnode *ln;
456 struct in_addr *iap;
457 struct in_addr **v;
65efcfce 458
d62a17ae 459 /*
460 * Array of nexthop addresses
461 */
462 *nh_ary_ret =
463 XCALLOC(MTYPE_TMP, nve_count * sizeof(struct in_addr));
65efcfce 464
d62a17ae 465 /*
466 * Array of pointers to nexthop addresses
467 */
468 *nhp_ary_ret = XCALLOC(MTYPE_TMP,
469 nve_count * sizeof(struct in_addr *));
470 iap = *nh_ary_ret;
471 v = *nhp_ary_ret;
65efcfce 472
d62a17ae 473 for (ln = listhead(nve_list); ln; ln = listnextnode(ln)) {
65efcfce 474
d62a17ae 475 struct rfapi_descriptor *irfd;
476 struct prefix nhp;
65efcfce 477
d62a17ae 478 irfd = listgetdata(ln);
65efcfce 479
d62a17ae 480 if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
481 continue;
65efcfce 482
d62a17ae 483 *iap = nhp.u.prefix4;
484 *v = iap;
485 vnc_zlog_debug_verbose(
486 "%s: ipadr: (%p)<-0x%x, ptr: (%p)<-%p",
487 __func__, iap, nhp.u.prefix4.s_addr, v, iap);
65efcfce 488
d62a17ae 489 ++iap;
490 ++v;
491 ++*nh_count_ret;
492 }
65efcfce 493
d62a17ae 494 } else if (family == AF_INET6) {
65efcfce 495
d62a17ae 496 struct listnode *ln;
65efcfce 497
d62a17ae 498 *nh_ary_ret =
499 XCALLOC(MTYPE_TMP, nve_count * sizeof(struct in6_addr));
65efcfce 500
d62a17ae 501 *nhp_ary_ret = XCALLOC(MTYPE_TMP,
502 nve_count * sizeof(struct in6_addr *));
65efcfce 503
d62a17ae 504 for (ln = listhead(nve_list); ln; ln = listnextnode(ln)) {
65efcfce 505
d62a17ae 506 struct rfapi_descriptor *irfd;
507 struct in6_addr *iap = *nh_ary_ret;
508 struct in6_addr **v = *nhp_ary_ret;
509 struct prefix nhp;
65efcfce 510
d62a17ae 511 irfd = listgetdata(ln);
65efcfce 512
d62a17ae 513 if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
514 continue;
65efcfce 515
d62a17ae 516 *iap = nhp.u.prefix6;
517 *v = iap;
65efcfce 518
d62a17ae 519 ++iap;
520 ++v;
521 ++*nh_count_ret;
522 }
523 }
65efcfce
LB
524}
525
d62a17ae 526static void import_table_to_nve_list_zebra(struct bgp *bgp,
527 struct rfapi_import_table *it,
528 struct list **nves, uint8_t family)
65efcfce 529{
d62a17ae 530 struct listnode *node;
531 struct rfapi_rfg_name *rfgn;
532
533 /*
534 * Loop over the list of NVE-Groups configured for
535 * exporting to direct-bgp.
536 *
537 * Build a list of NVEs that use this import table
538 */
539 *nves = NULL;
540 for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node,
541 rfgn)) {
542
543 /*
544 * If this NVE-Group's import table matches the current one
545 */
546 if (rfgn->rfg && rfgn->rfg->nves
547 && rfgn->rfg->rfapi_import_table == it) {
548
549 nve_group_to_nve_list(rfgn->rfg, nves, family);
550 }
551 }
65efcfce
LB
552}
553
d62a17ae 554static void vnc_zebra_add_del_prefix(struct bgp *bgp,
555 struct rfapi_import_table *import_table,
fe08ba7e 556 struct agg_node *rn,
d62a17ae 557 int add) /* !0 = add, 0 = del */
65efcfce 558{
d62a17ae 559 struct list *nves;
26a3ffd6 560 const struct prefix *p = agg_node_get_prefix(rn);
a74e593b 561 unsigned int nexthop_count = 0;
d62a17ae 562 void *nh_ary = NULL;
563 void *nhp_ary = NULL;
564
565 vnc_zlog_debug_verbose("%s: entry, add=%d", __func__, add);
566
567 if (zclient_vnc->sock < 0)
568 return;
569
26a3ffd6 570 if (p->family != AF_INET && p->family != AF_INET6) {
450971aa 571 flog_err(EC_LIB_DEVELOPMENT,
1c50c1c0 572 "%s: invalid route node addr family", __func__);
d62a17ae 573 return;
574 }
575
26a3ffd6
DS
576 if (!vrf_bitmap_check(
577 zclient_vnc->redist[family2afi(p->family)][ZEBRA_ROUTE_VNC],
578 VRF_DEFAULT))
d62a17ae 579 return;
580
581 if (!bgp->rfapi_cfg) {
582 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
583 __func__);
584 return;
585 }
586 if (!listcount(bgp->rfapi_cfg->rfg_export_zebra_l)) {
587 vnc_zlog_debug_verbose(
588 "%s: no zebra export nve group, skipping", __func__);
589 return;
590 }
591
26a3ffd6 592 import_table_to_nve_list_zebra(bgp, import_table, &nves, p->family);
d62a17ae 593
594 if (nves) {
26a3ffd6
DS
595 nve_list_to_nh_array(p->family, nves, &nexthop_count, &nh_ary,
596 &nhp_ary);
d62a17ae 597
6a154c88 598 list_delete(&nves);
d62a17ae 599
600 if (nexthop_count)
26a3ffd6 601 vnc_zebra_route_msg(p, nexthop_count, nhp_ary, add);
d62a17ae 602 }
603
0a22ddfb
QY
604 XFREE(MTYPE_TMP, nhp_ary);
605 XFREE(MTYPE_TMP, nh_ary);
65efcfce
LB
606}
607
d62a17ae 608void vnc_zebra_add_prefix(struct bgp *bgp,
609 struct rfapi_import_table *import_table,
fe08ba7e 610 struct agg_node *rn)
65efcfce 611{
d62a17ae 612 vnc_zebra_add_del_prefix(bgp, import_table, rn, 1);
65efcfce
LB
613}
614
d62a17ae 615void vnc_zebra_del_prefix(struct bgp *bgp,
616 struct rfapi_import_table *import_table,
fe08ba7e 617 struct agg_node *rn)
65efcfce 618{
d62a17ae 619 vnc_zebra_add_del_prefix(bgp, import_table, rn, 0);
65efcfce
LB
620}
621
622
d62a17ae 623static void vnc_zebra_add_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd,
624 int add) /* 0 = del, !0 = add */
65efcfce 625{
d62a17ae 626 struct listnode *node;
627 struct rfapi_rfg_name *rfgn;
628 struct rfapi_nve_group_cfg *rfg = rfd->rfg;
629 afi_t afi = family2afi(rfd->vn_addr.addr_family);
630 struct prefix nhp;
631 // struct prefix *nhpp;
632 void *pAddr;
633
634 vnc_zlog_debug_verbose("%s: entry, add=%d", __func__, add);
635
636 if (zclient_vnc->sock < 0)
637 return;
638
9f2337c9
RW
639 if (!vrf_bitmap_check(zclient_vnc->redist[afi][ZEBRA_ROUTE_VNC],
640 VRF_DEFAULT))
d62a17ae 641 return;
642
643 if (afi != AFI_IP && afi != AFI_IP6) {
450971aa 644 flog_err(EC_LIB_DEVELOPMENT, "%s: invalid vn addr family",
1c50c1c0 645 __func__);
d62a17ae 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
fe08ba7e
DS
678 struct agg_table *rt = NULL;
679 struct agg_node *rn;
d62a17ae 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 */
fe08ba7e
DS
692 for (rn = agg_route_top(rt); rn;
693 rn = agg_route_next(rn)) {
26a3ffd6
DS
694 if (!rn->info)
695 continue;
696
697 vnc_zlog_debug_verbose("%s: sending %s",
698 __func__,
699 (add ? "add" : "del"));
700 vnc_zebra_route_msg(agg_node_get_prefix(rn), 1,
701 &pAddr, add);
d62a17ae 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{
fe08ba7e
DS
721 struct agg_table *rt = NULL;
722 struct agg_node *rn;
d62a17ae 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 {
450971aa 742 flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d", __func__, afi);
d62a17ae 743 return;
744 }
745
746 if (!family) {
450971aa 747 flog_err(EC_LIB_DEVELOPMENT, "%s: computed bad family: %d",
1c50c1c0 748 __func__, family);
d62a17ae 749 return;
750 }
751
752 if (!rfg->nves) {
753 /* avoid segfault below if list doesn't exist */
754 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__);
755 return;
756 }
757
758 nve_group_to_nve_list(rfg, &nves, family);
759 if (nves) {
760 vnc_zlog_debug_verbose("%s: have nves", __func__);
761 nve_list_to_nh_array(family, nves, &nexthop_count, &nh_ary,
762 &nhp_ary);
763
764 vnc_zlog_debug_verbose("%s: family: %d, nve count: %d",
765 __func__, family, nexthop_count);
766
6a154c88 767 list_delete(&nves);
d62a17ae 768
769 if (nexthop_count) {
770 /*
771 * Walk the NVE-Group's VNC Import table
772 */
fe08ba7e
DS
773 for (rn = agg_route_top(rt); rn;
774 rn = agg_route_next(rn)) {
d62a17ae 775 if (rn->info) {
26a3ffd6
DS
776 vnc_zebra_route_msg(
777 agg_node_get_prefix(rn),
778 nexthop_count, nhp_ary, add);
d62a17ae 779 }
780 }
781 }
0a22ddfb
QY
782 XFREE(MTYPE_TMP, nhp_ary);
783 XFREE(MTYPE_TMP, nh_ary);
d62a17ae 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. */
9f2337c9 836 if (vrf_bitmap_check(zclient_vnc->redist[afi][type], VRF_DEFAULT))
d62a17ae 837 return CMD_WARNING_CONFIG_FAILED;
65efcfce 838
d62a17ae 839 vrf_bitmap_set(zclient_vnc->redist[afi][type], VRF_DEFAULT);
65efcfce 840
9f2337c9 841 // vrf_bitmap_set(zclient_vnc->redist[afi][type], VRF_DEFAULT);
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. */
9f2337c9 872 if (!vrf_bitmap_check(zclient_vnc->redist[afi][type], VRF_DEFAULT))
d62a17ae 873 return CMD_WARNING_CONFIG_FAILED;
9f2337c9 874 vrf_bitmap_unset(zclient_vnc->redist[afi][type], VRF_DEFAULT);
d62a17ae 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 897
a243d1db
DL
898static zclient_handler *const vnc_handlers[] = {
899 [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = vnc_zebra_read_route,
900 [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = vnc_zebra_read_route,
901};
902
65efcfce
LB
903/*
904 * Modeled after bgp_zebra.c'bgp_zebra_init()
905 * Charriere asks, "Is it possible to carry two?"
906 */
d62a17ae 907void vnc_zebra_init(struct thread_master *master)
65efcfce 908{
d62a17ae 909 /* Set default values. */
a243d1db
DL
910 zclient_vnc = zclient_new(master, &zclient_options_default,
911 vnc_handlers, array_size(vnc_handlers));
342213ea 912 zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0, &bgpd_privs);
65efcfce
LB
913}
914
d62a17ae 915void vnc_zebra_destroy(void)
65efcfce 916{
d62a17ae 917 if (zclient_vnc == NULL)
918 return;
919 zclient_stop(zclient_vnc);
920 zclient_free(zclient_vnc);
921 zclient_vnc = NULL;
65efcfce 922}