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