]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/rfapi/vnc_zebra.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / bgpd / rfapi / vnc_zebra.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
d62a17ae 2/*
65efcfce
LB
3 *
4 * Copyright 2009-2016, LabN Consulting, L.L.C.
5 *
65efcfce
LB
6 */
7
8/*
9 * File: vnc_zebra.c
10 * Purpose: Handle exchange of routes between VNC and Zebra
11 */
12
f8b6f499
LB
13#include "lib/zebra.h"
14#include "lib/prefix.h"
fe08ba7e 15#include "lib/agg_table.h"
f8b6f499
LB
16#include "lib/log.h"
17#include "lib/command.h"
18#include "lib/zclient.h"
19#include "lib/stream.h"
74ffbfe6 20#include "lib/ringbuf.h"
f8b6f499 21#include "lib/memory.h"
02705213 22#include "lib/lib_errors.h"
65efcfce 23
f8b6f499
LB
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"
65efcfce 29
f8b6f499
LB
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"
a3b55c25 37#include "bgpd/rfapi/vnc_debug.h"
65efcfce 38
d62a17ae 39static struct rfapi_descriptor vncHD1VR; /* Single-VR export dummy nve descr */
65efcfce
LB
40static 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 */
d7c0a89a 49static void vnc_redistribute_add(struct prefix *p, uint32_t metric,
74489921 50 uint8_t type)
65efcfce 51{
d62a17ae 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:
12256b84
DA
95 if (bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen
96 != IPV4_MAX_BITLEN) {
d62a17ae 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:
13ccce6e
DA
108 if (bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen
109 != IPV6_MAX_BITLEN) {
d62a17ae 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:
12256b84 145 if (pfx_un.length != IPV4_MAX_BITLEN) {
d62a17ae 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:
13ccce6e 153 if (pfx_un.length != IPV6_MAX_BITLEN) {
d62a17ae 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 */
424ab01d 177
becedef6
QY
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 */
cb1991af 183 frr_with_mutex (&vncHD1VR.peer->io_mtx) {
424ab01d
QY
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)
74ffbfe6 191 ringbuf_del(vncHD1VR.peer->ibuf_work);
424ab01d
QY
192 if (vncHD1VR.peer->obuf_work)
193 stream_free(vncHD1VR.peer->obuf_work);
194
d62a17ae 195 vncHD1VR.peer->ibuf = NULL;
d62a17ae 196 vncHD1VR.peer->obuf = NULL;
424ab01d
QY
197 vncHD1VR.peer->obuf_work = NULL;
198 vncHD1VR.peer->ibuf_work = NULL;
d62a17ae 199 }
424ab01d 200
d62a17ae 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 */
65efcfce
LB
224}
225
226/*
227 * Route deletions from zebra propagate to VNC here
228 */
d62a17ae 229static void vnc_redistribute_delete(struct prefix *p, uint8_t type)
65efcfce 230{
d62a17ae 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);
65efcfce
LB
269}
270
271/*
272 * Flush all redistributed routes of type <type>
273 */
d62a17ae 274static void vnc_redistribute_withdraw(struct bgp *bgp, afi_t afi, uint8_t type)
65efcfce 275{
d62a17ae 276 struct prefix_rd prd;
277 struct bgp_table *table;
9bcb3eef
DS
278 struct bgp_dest *pdest;
279 struct bgp_dest *dest;
d62a17ae 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 */
9bcb3eef
DS
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);
b54892e0 297
d62a17ae 298 memset(&prd, 0, sizeof(prd));
299 prd.family = AF_UNSPEC;
300 prd.prefixlen = 64;
9bcb3eef 301 memcpy(prd.val, pdest_p->u.val, 8);
d62a17ae 302
303 /* This is the per-RD table of prefixes */
9bcb3eef 304 table = bgp_dest_get_bgp_table_info(pdest);
2eab1324
RW
305 if (!table)
306 continue;
d62a17ae 307
9bcb3eef
DS
308 for (dest = bgp_table_top(table); dest;
309 dest = bgp_route_next(dest)) {
d62a17ae 310
4b7e6066 311 struct bgp_path_info *ri;
d62a17ae 312
9bcb3eef 313 for (ri = bgp_dest_get_bgp_path_info(dest); ri;
6f94b685 314 ri = ri->next) {
d62a17ae 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,
9bcb3eef 324 bgp_dest_get_prefix(dest), &prd, type,
d62a17ae 325 BGP_ROUTE_REDISTRIBUTE, NULL, 0);
326 }
327 }
328 }
329 vnc_zlog_debug_verbose("%s: return", __func__);
65efcfce
LB
330}
331
332/*
333 * Zebra route add and delete treatment.
334 *
335 * Assumes 1 nexthop
336 */
121f9dee 337static int vnc_zebra_read_route(ZAPI_CALLBACK_ARGS)
65efcfce 338{
74489921
RW
339 struct zapi_route api;
340 int add;
d62a17ae 341
74489921
RW
342 if (zapi_route_decode(zclient->ibuf, &api) < 0)
343 return -1;
65efcfce 344
74489921
RW
345 /* we completely ignore srcdest routes for now. */
346 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
d62a17ae 347 return 0;
348
121f9dee 349 add = (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
74489921
RW
350 if (add)
351 vnc_redistribute_add(&api.prefix, api.metric, api.type);
d62a17ae 352 else
74489921 353 vnc_redistribute_delete(&api.prefix, api.type);
d62a17ae 354
2dbe669b 355 if (BGP_DEBUG(zebra, ZEBRA))
74489921 356 vnc_zlog_debug_verbose(
2dbe669b
DA
357 "%s: Zebra rcvd: route delete %s %pFX metric %u",
358 __func__, zebra_route_string(api.type), &api.prefix,
74489921 359 api.metric);
d62a17ae 360
361 return 0;
65efcfce
LB
362}
363
364/***********************************************************************
365 * vnc_bgp_zebra_*: VNC sends updates/withdraws to Zebra
366 ***********************************************************************/
367
368/*
369 * low-level message builder
370 */
26a3ffd6 371static void vnc_zebra_route_msg(const struct prefix *p, unsigned int nhp_count,
a74e593b 372 void *nhp_ary, int add) /* 1 = add, 0 = del */
65efcfce 373{
2ad4f093
RW
374 struct zapi_route api;
375 struct zapi_nexthop *api_nh;
376 int i;
b40c5062
LB
377 struct in_addr **nhp_ary4 = nhp_ary;
378 struct in6_addr **nhp_ary6 = nhp_ary;
2ad4f093 379
d62a17ae 380 if (!nhp_count) {
381 vnc_zlog_debug_verbose("%s: empty nexthop list, skipping",
382 __func__);
383 return;
384 }
385
2ad4f093
RW
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);
a74e593b
RW
394 api.nexthop_num = MIN(nhp_count, multipath_num);
395 for (i = 0; i < api.nexthop_num; i++) {
2ad4f093
RW
396
397 api_nh = &api.nexthops[i];
4a7371e9 398 api_nh->vrf_id = VRF_DEFAULT;
2ad4f093
RW
399 switch (p->family) {
400 case AF_INET:
b40c5062 401 memcpy(&api_nh->gate.ipv4, nhp_ary4[i],
9913029c
RW
402 sizeof(api_nh->gate.ipv4));
403 api_nh->type = NEXTHOP_TYPE_IPV4;
2ad4f093
RW
404 break;
405 case AF_INET6:
b40c5062 406 memcpy(&api_nh->gate.ipv6, nhp_ary6[i],
9913029c
RW
407 sizeof(api_nh->gate.ipv6));
408 api_nh->type = NEXTHOP_TYPE_IPV6;
2ad4f093 409 break;
9913029c 410 }
2ad4f093 411 }
9913029c 412
2dbe669b 413 if (BGP_DEBUG(zebra, ZEBRA))
d62a17ae 414 vnc_zlog_debug_verbose(
2dbe669b
DA
415 "%s: Zebra send: route %s %pFX, nhp_count=%d", __func__,
416 (add ? "add" : "del"), &api.prefix, nhp_count);
2ad4f093
RW
417
418 zclient_route_send((add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE),
419 zclient_vnc, &api);
65efcfce
LB
420}
421
422
423static void
d7c0a89a 424nve_list_to_nh_array(uint8_t family, struct list *nve_list,
a74e593b 425 unsigned int *nh_count_ret,
d62a17ae 426 void **nh_ary_ret, /* returned address array */
427 void **nhp_ary_ret) /* returned pointer array */
65efcfce 428{
d62a17ae 429 int nve_count = listcount(nve_list);
65efcfce 430
d62a17ae 431 *nh_count_ret = 0;
432 *nh_ary_ret = NULL;
433 *nhp_ary_ret = NULL;
65efcfce 434
d62a17ae 435 if (!nve_count) {
436 vnc_zlog_debug_verbose("%s: empty nve_list, skipping",
437 __func__);
438 return;
439 }
65efcfce 440
d62a17ae 441 if (family == AF_INET) {
442 struct listnode *ln;
443 struct in_addr *iap;
444 struct in_addr **v;
65efcfce 445
d62a17ae 446 /*
447 * Array of nexthop addresses
448 */
449 *nh_ary_ret =
450 XCALLOC(MTYPE_TMP, nve_count * sizeof(struct in_addr));
65efcfce 451
d62a17ae 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;
65efcfce 459
d62a17ae 460 for (ln = listhead(nve_list); ln; ln = listnextnode(ln)) {
65efcfce 461
d62a17ae 462 struct rfapi_descriptor *irfd;
463 struct prefix nhp;
65efcfce 464
d62a17ae 465 irfd = listgetdata(ln);
65efcfce 466
d62a17ae 467 if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
468 continue;
65efcfce 469
d62a17ae 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);
65efcfce 475
d62a17ae 476 ++iap;
477 ++v;
478 ++*nh_count_ret;
479 }
65efcfce 480
d62a17ae 481 } else if (family == AF_INET6) {
65efcfce 482
d62a17ae 483 struct listnode *ln;
65efcfce 484
d62a17ae 485 *nh_ary_ret =
486 XCALLOC(MTYPE_TMP, nve_count * sizeof(struct in6_addr));
65efcfce 487
d62a17ae 488 *nhp_ary_ret = XCALLOC(MTYPE_TMP,
489 nve_count * sizeof(struct in6_addr *));
65efcfce 490
d62a17ae 491 for (ln = listhead(nve_list); ln; ln = listnextnode(ln)) {
65efcfce 492
d62a17ae 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;
65efcfce 497
d62a17ae 498 irfd = listgetdata(ln);
65efcfce 499
d62a17ae 500 if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
501 continue;
65efcfce 502
d62a17ae 503 *iap = nhp.u.prefix6;
504 *v = iap;
65efcfce 505
d62a17ae 506 ++iap;
507 ++v;
508 ++*nh_count_ret;
509 }
510 }
65efcfce
LB
511}
512
d62a17ae 513static void import_table_to_nve_list_zebra(struct bgp *bgp,
514 struct rfapi_import_table *it,
515 struct list **nves, uint8_t family)
65efcfce 516{
d62a17ae 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 }
65efcfce
LB
539}
540
d62a17ae 541static void vnc_zebra_add_del_prefix(struct bgp *bgp,
542 struct rfapi_import_table *import_table,
fe08ba7e 543 struct agg_node *rn,
d62a17ae 544 int add) /* !0 = add, 0 = del */
65efcfce 545{
d62a17ae 546 struct list *nves;
26a3ffd6 547 const struct prefix *p = agg_node_get_prefix(rn);
a74e593b 548 unsigned int nexthop_count = 0;
d62a17ae 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
26a3ffd6 557 if (p->family != AF_INET && p->family != AF_INET6) {
450971aa 558 flog_err(EC_LIB_DEVELOPMENT,
1c50c1c0 559 "%s: invalid route node addr family", __func__);
d62a17ae 560 return;
561 }
562
26a3ffd6
DS
563 if (!vrf_bitmap_check(
564 zclient_vnc->redist[family2afi(p->family)][ZEBRA_ROUTE_VNC],
565 VRF_DEFAULT))
d62a17ae 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
26a3ffd6 579 import_table_to_nve_list_zebra(bgp, import_table, &nves, p->family);
d62a17ae 580
581 if (nves) {
26a3ffd6
DS
582 nve_list_to_nh_array(p->family, nves, &nexthop_count, &nh_ary,
583 &nhp_ary);
d62a17ae 584
6a154c88 585 list_delete(&nves);
d62a17ae 586
587 if (nexthop_count)
26a3ffd6 588 vnc_zebra_route_msg(p, nexthop_count, nhp_ary, add);
d62a17ae 589 }
590
0a22ddfb
QY
591 XFREE(MTYPE_TMP, nhp_ary);
592 XFREE(MTYPE_TMP, nh_ary);
65efcfce
LB
593}
594
d62a17ae 595void vnc_zebra_add_prefix(struct bgp *bgp,
596 struct rfapi_import_table *import_table,
fe08ba7e 597 struct agg_node *rn)
65efcfce 598{
d62a17ae 599 vnc_zebra_add_del_prefix(bgp, import_table, rn, 1);
65efcfce
LB
600}
601
d62a17ae 602void vnc_zebra_del_prefix(struct bgp *bgp,
603 struct rfapi_import_table *import_table,
fe08ba7e 604 struct agg_node *rn)
65efcfce 605{
d62a17ae 606 vnc_zebra_add_del_prefix(bgp, import_table, rn, 0);
65efcfce
LB
607}
608
609
d62a17ae 610static void vnc_zebra_add_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd,
611 int add) /* 0 = del, !0 = add */
65efcfce 612{
d62a17ae 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;
d62a17ae 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
9f2337c9
RW
625 if (!vrf_bitmap_check(zclient_vnc->redist[afi][ZEBRA_ROUTE_VNC],
626 VRF_DEFAULT))
d62a17ae 627 return;
628
629 if (afi != AFI_IP && afi != AFI_IP6) {
450971aa 630 flog_err(EC_LIB_DEVELOPMENT, "%s: invalid vn addr family",
1c50c1c0 631 __func__);
d62a17ae 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
8b5153aa 649 pAddr = &nhp.u.val;
d62a17ae 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
fe08ba7e
DS
664 struct agg_table *rt = NULL;
665 struct agg_node *rn;
d62a17ae 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 */
fe08ba7e
DS
678 for (rn = agg_route_top(rt); rn;
679 rn = agg_route_next(rn)) {
26a3ffd6
DS
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);
d62a17ae 688 }
689 }
690 }
65efcfce
LB
691}
692
d62a17ae 693void vnc_zebra_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
65efcfce 694{
d62a17ae 695 vnc_zebra_add_del_nve(bgp, rfd, 1);
65efcfce
LB
696}
697
d62a17ae 698void vnc_zebra_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
65efcfce 699{
d62a17ae 700 vnc_zebra_add_del_nve(bgp, rfd, 0);
65efcfce
LB
701}
702
d62a17ae 703static void vnc_zebra_add_del_group_afi(struct bgp *bgp,
704 struct rfapi_nve_group_cfg *rfg,
705 afi_t afi, int add)
65efcfce 706{
fe08ba7e
DS
707 struct agg_table *rt = NULL;
708 struct agg_node *rn;
d62a17ae 709 struct rfapi_import_table *import_table;
710 uint8_t family = afi2family(afi);
711
712 struct list *nves = NULL;
a74e593b 713 unsigned int nexthop_count = 0;
d62a17ae 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 {
450971aa 728 flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d", __func__, afi);
d62a17ae 729 return;
730 }
731
732 if (!family) {
450971aa 733 flog_err(EC_LIB_DEVELOPMENT, "%s: computed bad family: %d",
1c50c1c0 734 __func__, family);
d62a17ae 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
6a154c88 753 list_delete(&nves);
d62a17ae 754
755 if (nexthop_count) {
756 /*
757 * Walk the NVE-Group's VNC Import table
758 */
fe08ba7e
DS
759 for (rn = agg_route_top(rt); rn;
760 rn = agg_route_next(rn)) {
d62a17ae 761 if (rn->info) {
26a3ffd6
DS
762 vnc_zebra_route_msg(
763 agg_node_get_prefix(rn),
764 nexthop_count, nhp_ary, add);
d62a17ae 765 }
766 }
767 }
0a22ddfb
QY
768 XFREE(MTYPE_TMP, nhp_ary);
769 XFREE(MTYPE_TMP, nh_ary);
d62a17ae 770 }
65efcfce
LB
771}
772
d62a17ae 773void vnc_zebra_add_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
65efcfce 774{
d62a17ae 775 vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP, 1);
776 vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP6, 1);
65efcfce
LB
777}
778
d62a17ae 779void vnc_zebra_del_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
65efcfce 780{
d62a17ae 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);
65efcfce
LB
784}
785
d62a17ae 786void vnc_zebra_reexport_group_afi(struct bgp *bgp,
787 struct rfapi_nve_group_cfg *rfg, afi_t afi)
65efcfce 788{
d62a17ae 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 }
65efcfce
LB
801}
802
803
804/***********************************************************************
805 * CONTROL INTERFACE
806 ***********************************************************************/
807
808
809/* Other routes redistribution into BGP. */
d62a17ae 810int vnc_redistribute_set(struct bgp *bgp, afi_t afi, int type)
65efcfce 811{
d62a17ae 812 if (!bgp->rfapi_cfg) {
813 return CMD_WARNING_CONFIG_FAILED;
814 }
65efcfce 815
d62a17ae 816 /* Set flag to BGP instance. */
817 bgp->rfapi_cfg->redist[afi][type] = 1;
65efcfce 818
d62a17ae 819 // bgp->redist[afi][type] = 1;
65efcfce 820
d62a17ae 821 /* Return if already redistribute flag is set. */
9f2337c9 822 if (vrf_bitmap_check(zclient_vnc->redist[afi][type], VRF_DEFAULT))
d62a17ae 823 return CMD_WARNING_CONFIG_FAILED;
65efcfce 824
d62a17ae 825 vrf_bitmap_set(zclient_vnc->redist[afi][type], VRF_DEFAULT);
65efcfce 826
9f2337c9 827 // vrf_bitmap_set(zclient_vnc->redist[afi][type], VRF_DEFAULT);
65efcfce 828
d62a17ae 829 /* Return if zebra connection is not established. */
830 if (zclient_vnc->sock < 0)
831 return CMD_WARNING_CONFIG_FAILED;
65efcfce 832
d62a17ae 833 if (BGP_DEBUG(zebra, ZEBRA))
834 vnc_zlog_debug_verbose("Zebra send: redistribute add %s",
835 zebra_route_string(type));
65efcfce 836
d62a17ae 837 /* Send distribute add message to zebra. */
838 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient_vnc, afi, type,
839 0, VRF_DEFAULT);
65efcfce 840
d62a17ae 841 return CMD_SUCCESS;
65efcfce
LB
842}
843
844/* Unset redistribution. */
d62a17ae 845int vnc_redistribute_unset(struct bgp *bgp, afi_t afi, int type)
65efcfce 846{
d62a17ae 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. */
9f2337c9 858 if (!vrf_bitmap_check(zclient_vnc->redist[afi][type], VRF_DEFAULT))
d62a17ae 859 return CMD_WARNING_CONFIG_FAILED;
9f2337c9 860 vrf_bitmap_unset(zclient_vnc->redist[afi][type], VRF_DEFAULT);
d62a17ae 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;
65efcfce
LB
880}
881
342213ea 882extern struct zebra_privs_t bgpd_privs;
65efcfce 883
a243d1db
DL
884static 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
65efcfce
LB
889/*
890 * Modeled after bgp_zebra.c'bgp_zebra_init()
891 * Charriere asks, "Is it possible to carry two?"
892 */
d62a17ae 893void vnc_zebra_init(struct thread_master *master)
65efcfce 894{
d62a17ae 895 /* Set default values. */
a243d1db
DL
896 zclient_vnc = zclient_new(master, &zclient_options_default,
897 vnc_handlers, array_size(vnc_handlers));
342213ea 898 zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0, &bgpd_privs);
65efcfce
LB
899}
900
d62a17ae 901void vnc_zebra_destroy(void)
65efcfce 902{
d62a17ae 903 if (zclient_vnc == NULL)
904 return;
905 zclient_stop(zclient_vnc);
906 zclient_free(zclient_vnc);
907 zclient_vnc = NULL;
65efcfce 908}