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