]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/rfapi/vnc_zebra.c
Merge pull request #3899 from ton31337/fix/remove_private_as_with_local_as
[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:
108 if (bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen != 32) {
109 vnc_zlog_debug_verbose(
110 "%s: redist nve group VN prefix len (%d) != 32, skipping",
111 __func__,
112 bgp->rfapi_cfg->rfg_redist->vn_prefix
113 .prefixlen);
114 return;
115 }
116 vnaddr.addr.v4 =
117 bgp->rfapi_cfg->rfg_redist->vn_prefix.u.prefix4;
118 break;
119 case AF_INET6:
120 if (bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen != 128) {
121 vnc_zlog_debug_verbose(
122 "%s: redist nve group VN prefix len (%d) != 128, skipping",
123 __func__,
124 bgp->rfapi_cfg->rfg_redist->vn_prefix
125 .prefixlen);
126 return;
127 }
128 vnaddr.addr.v6 =
129 bgp->rfapi_cfg->rfg_redist->vn_prefix.u.prefix6;
130 break;
131 default:
132 vnc_zlog_debug_verbose(
133 "%s: no redist nve group VN host prefix configured, skipping",
134 __func__);
135 return;
136 }
137
138 /*
139 * Assume nve group's configured UN address prefix is a host
140 * route which also happens to give the NVE UN address to use
141 * for redistributing into VNC.
142 */
143
144 /*
145 * Set UN address in dummy nve descriptor so add_vnc_route
146 * can use it in VNC tunnel SubTLV
147 */
148 {
149 struct rfapi_ip_prefix pfx_un;
150
151 rfapiQprefix2Rprefix(&bgp->rfapi_cfg->rfg_redist->un_prefix,
152 &pfx_un);
153
154 switch (pfx_un.prefix.addr_family) {
155 case AF_INET:
156 if (pfx_un.length != 32) {
157 vnc_zlog_debug_verbose(
158 "%s: redist nve group UN prefix len (%d) != 32, skipping",
159 __func__, pfx_un.length);
160 return;
161 }
162 break;
163 case AF_INET6:
164 if (pfx_un.length != 128) {
165 vnc_zlog_debug_verbose(
166 "%s: redist nve group UN prefix len (%d) != 128, skipping",
167 __func__, pfx_un.length);
168 return;
169 }
170 break;
171 default:
172 vnc_zlog_debug_verbose(
173 "%s: no redist nve group UN host prefix configured, skipping",
174 __func__);
175 return;
176 }
177
178 vncHD1VR.un_addr = pfx_un.prefix;
179
180 if (!vncHD1VR.peer) {
181 /*
182 * Same setup as in rfapi_open()
183 */
184 vncHD1VR.peer = peer_new(bgp);
185 vncHD1VR.peer->status =
186 Established; /* keep bgp core happy */
187 bgp_sync_delete(vncHD1VR.peer); /* don't need these */
424ab01d 188
becedef6
QY
189 /*
190 * since this peer is not on the I/O thread, this lock
191 * is not strictly necessary, but serves as a reminder
192 * to those who may meddle...
193 */
424ab01d
QY
194 pthread_mutex_lock(&vncHD1VR.peer->io_mtx);
195 {
196 // we don't need any I/O related facilities
197 if (vncHD1VR.peer->ibuf)
198 stream_fifo_free(vncHD1VR.peer->ibuf);
199 if (vncHD1VR.peer->obuf)
200 stream_fifo_free(vncHD1VR.peer->obuf);
201
202 if (vncHD1VR.peer->ibuf_work)
74ffbfe6 203 ringbuf_del(vncHD1VR.peer->ibuf_work);
424ab01d
QY
204 if (vncHD1VR.peer->obuf_work)
205 stream_free(vncHD1VR.peer->obuf_work);
206
d62a17ae 207 vncHD1VR.peer->ibuf = NULL;
d62a17ae 208 vncHD1VR.peer->obuf = NULL;
424ab01d
QY
209 vncHD1VR.peer->obuf_work = NULL;
210 vncHD1VR.peer->ibuf_work = NULL;
d62a17ae 211 }
424ab01d
QY
212 pthread_mutex_unlock(&vncHD1VR.peer->io_mtx);
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;
291 struct bgp_node *prn;
292 struct bgp_node *rn;
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 */
307 for (prn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); prn;
308 prn = bgp_route_next(prn)) {
309 memset(&prd, 0, sizeof(prd));
310 prd.family = AF_UNSPEC;
311 prd.prefixlen = 64;
312 memcpy(prd.val, prn->p.u.val, 8);
313
314 /* This is the per-RD table of prefixes */
67009e22 315 table = bgp_node_get_bgp_table_info(prn);
2eab1324
RW
316 if (!table)
317 continue;
d62a17ae 318
319 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
320
4b7e6066 321 struct bgp_path_info *ri;
d62a17ae 322
6f94b685
DS
323 for (ri = bgp_node_get_bgp_path_info(rn); ri;
324 ri = ri->next) {
d62a17ae 325 if (ri->type
326 == type) { /* has matching redist type */
327 break;
328 }
329 }
330 if (ri) {
331 del_vnc_route(
332 &vncHD1VR, /* use dummy ptr as cookie */
333 vncHD1VR.peer, bgp, SAFI_MPLS_VPN,
334 &(rn->p), &prd, type,
335 BGP_ROUTE_REDISTRIBUTE, NULL, 0);
336 }
337 }
338 }
339 vnc_zlog_debug_verbose("%s: return", __func__);
65efcfce
LB
340}
341
342/*
343 * Zebra route add and delete treatment.
344 *
345 * Assumes 1 nexthop
346 */
74489921
RW
347static int vnc_zebra_read_route(int command, struct zclient *zclient,
348 zebra_size_t length, vrf_id_t vrf_id)
65efcfce 349{
74489921
RW
350 struct zapi_route api;
351 int add;
d62a17ae 352
74489921
RW
353 if (zapi_route_decode(zclient->ibuf, &api) < 0)
354 return -1;
65efcfce 355
74489921
RW
356 /* we completely ignore srcdest routes for now. */
357 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
d62a17ae 358 return 0;
359
74489921
RW
360 add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
361 if (add)
362 vnc_redistribute_add(&api.prefix, api.metric, api.type);
d62a17ae 363 else
74489921 364 vnc_redistribute_delete(&api.prefix, api.type);
d62a17ae 365
74489921
RW
366 if (BGP_DEBUG(zebra, ZEBRA)) {
367 char buf[PREFIX_STRLEN];
d62a17ae 368
74489921
RW
369 prefix2str(&api.prefix, buf, sizeof(buf));
370 vnc_zlog_debug_verbose(
371 "%s: Zebra rcvd: route delete %s %s metric %u",
372 __func__, zebra_route_string(api.type), buf,
373 api.metric);
d62a17ae 374 }
375
376 return 0;
65efcfce
LB
377}
378
379/***********************************************************************
380 * vnc_bgp_zebra_*: VNC sends updates/withdraws to Zebra
381 ***********************************************************************/
382
383/*
384 * low-level message builder
385 */
a74e593b
RW
386static void vnc_zebra_route_msg(struct prefix *p, unsigned int nhp_count,
387 void *nhp_ary, int add) /* 1 = add, 0 = del */
65efcfce 388{
2ad4f093
RW
389 struct zapi_route api;
390 struct zapi_nexthop *api_nh;
391 int i;
b40c5062
LB
392 struct in_addr **nhp_ary4 = nhp_ary;
393 struct in6_addr **nhp_ary6 = nhp_ary;
2ad4f093 394
d62a17ae 395 if (!nhp_count) {
396 vnc_zlog_debug_verbose("%s: empty nexthop list, skipping",
397 __func__);
398 return;
399 }
400
2ad4f093
RW
401 memset(&api, 0, sizeof(api));
402 api.vrf_id = VRF_DEFAULT;
403 api.type = ZEBRA_ROUTE_VNC;
404 api.safi = SAFI_UNICAST;
405 api.prefix = *p;
406
407 /* Nexthops */
408 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
a74e593b
RW
409 api.nexthop_num = MIN(nhp_count, multipath_num);
410 for (i = 0; i < api.nexthop_num; i++) {
2ad4f093
RW
411
412 api_nh = &api.nexthops[i];
4a7371e9 413 api_nh->vrf_id = VRF_DEFAULT;
2ad4f093
RW
414 switch (p->family) {
415 case AF_INET:
b40c5062 416 memcpy(&api_nh->gate.ipv4, nhp_ary4[i],
9913029c
RW
417 sizeof(api_nh->gate.ipv4));
418 api_nh->type = NEXTHOP_TYPE_IPV4;
2ad4f093
RW
419 break;
420 case AF_INET6:
b40c5062 421 memcpy(&api_nh->gate.ipv6, nhp_ary6[i],
9913029c
RW
422 sizeof(api_nh->gate.ipv6));
423 api_nh->type = NEXTHOP_TYPE_IPV6;
2ad4f093 424 break;
9913029c 425 }
2ad4f093 426 }
9913029c 427
2ad4f093
RW
428 if (BGP_DEBUG(zebra, ZEBRA)) {
429 char buf[PREFIX_STRLEN];
d62a17ae 430
2ad4f093 431 prefix2str(&api.prefix, buf, sizeof(buf));
d62a17ae 432 vnc_zlog_debug_verbose(
2ad4f093
RW
433 "%s: Zebra send: route %s %s, nhp_count=%d", __func__,
434 (add ? "add" : "del"), buf, nhp_count);
d62a17ae 435 }
2ad4f093
RW
436
437 zclient_route_send((add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE),
438 zclient_vnc, &api);
65efcfce
LB
439}
440
441
442static void
d7c0a89a 443nve_list_to_nh_array(uint8_t family, struct list *nve_list,
a74e593b 444 unsigned int *nh_count_ret,
d62a17ae 445 void **nh_ary_ret, /* returned address array */
446 void **nhp_ary_ret) /* returned pointer array */
65efcfce 447{
d62a17ae 448 int nve_count = listcount(nve_list);
65efcfce 449
d62a17ae 450 *nh_count_ret = 0;
451 *nh_ary_ret = NULL;
452 *nhp_ary_ret = NULL;
65efcfce 453
d62a17ae 454 if (!nve_count) {
455 vnc_zlog_debug_verbose("%s: empty nve_list, skipping",
456 __func__);
457 return;
458 }
65efcfce 459
d62a17ae 460 if (family == AF_INET) {
461 struct listnode *ln;
462 struct in_addr *iap;
463 struct in_addr **v;
65efcfce 464
d62a17ae 465 /*
466 * Array of nexthop addresses
467 */
468 *nh_ary_ret =
469 XCALLOC(MTYPE_TMP, nve_count * sizeof(struct in_addr));
65efcfce 470
d62a17ae 471 /*
472 * Array of pointers to nexthop addresses
473 */
474 *nhp_ary_ret = XCALLOC(MTYPE_TMP,
475 nve_count * sizeof(struct in_addr *));
476 iap = *nh_ary_ret;
477 v = *nhp_ary_ret;
65efcfce 478
d62a17ae 479 for (ln = listhead(nve_list); ln; ln = listnextnode(ln)) {
65efcfce 480
d62a17ae 481 struct rfapi_descriptor *irfd;
482 struct prefix nhp;
65efcfce 483
d62a17ae 484 irfd = listgetdata(ln);
65efcfce 485
d62a17ae 486 if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
487 continue;
65efcfce 488
d62a17ae 489 *iap = nhp.u.prefix4;
490 *v = iap;
491 vnc_zlog_debug_verbose(
492 "%s: ipadr: (%p)<-0x%x, ptr: (%p)<-%p",
493 __func__, iap, nhp.u.prefix4.s_addr, v, iap);
65efcfce 494
d62a17ae 495 ++iap;
496 ++v;
497 ++*nh_count_ret;
498 }
65efcfce 499
d62a17ae 500 } else if (family == AF_INET6) {
65efcfce 501
d62a17ae 502 struct listnode *ln;
65efcfce 503
d62a17ae 504 *nh_ary_ret =
505 XCALLOC(MTYPE_TMP, nve_count * sizeof(struct in6_addr));
65efcfce 506
d62a17ae 507 *nhp_ary_ret = XCALLOC(MTYPE_TMP,
508 nve_count * sizeof(struct in6_addr *));
65efcfce 509
d62a17ae 510 for (ln = listhead(nve_list); ln; ln = listnextnode(ln)) {
65efcfce 511
d62a17ae 512 struct rfapi_descriptor *irfd;
513 struct in6_addr *iap = *nh_ary_ret;
514 struct in6_addr **v = *nhp_ary_ret;
515 struct prefix nhp;
65efcfce 516
d62a17ae 517 irfd = listgetdata(ln);
65efcfce 518
d62a17ae 519 if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
520 continue;
65efcfce 521
d62a17ae 522 *iap = nhp.u.prefix6;
523 *v = iap;
65efcfce 524
d62a17ae 525 ++iap;
526 ++v;
527 ++*nh_count_ret;
528 }
529 }
65efcfce
LB
530}
531
d62a17ae 532static void import_table_to_nve_list_zebra(struct bgp *bgp,
533 struct rfapi_import_table *it,
534 struct list **nves, uint8_t family)
65efcfce 535{
d62a17ae 536 struct listnode *node;
537 struct rfapi_rfg_name *rfgn;
538
539 /*
540 * Loop over the list of NVE-Groups configured for
541 * exporting to direct-bgp.
542 *
543 * Build a list of NVEs that use this import table
544 */
545 *nves = NULL;
546 for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node,
547 rfgn)) {
548
549 /*
550 * If this NVE-Group's import table matches the current one
551 */
552 if (rfgn->rfg && rfgn->rfg->nves
553 && rfgn->rfg->rfapi_import_table == it) {
554
555 nve_group_to_nve_list(rfgn->rfg, nves, family);
556 }
557 }
65efcfce
LB
558}
559
d62a17ae 560static void vnc_zebra_add_del_prefix(struct bgp *bgp,
561 struct rfapi_import_table *import_table,
fe08ba7e 562 struct agg_node *rn,
d62a17ae 563 int add) /* !0 = add, 0 = del */
65efcfce 564{
d62a17ae 565 struct list *nves;
566
a74e593b 567 unsigned int nexthop_count = 0;
d62a17ae 568 void *nh_ary = NULL;
569 void *nhp_ary = NULL;
570
571 vnc_zlog_debug_verbose("%s: entry, add=%d", __func__, add);
572
573 if (zclient_vnc->sock < 0)
574 return;
575
576 if (rn->p.family != AF_INET && rn->p.family != AF_INET6) {
450971aa 577 flog_err(EC_LIB_DEVELOPMENT,
1c50c1c0 578 "%s: invalid route node addr family", __func__);
d62a17ae 579 return;
580 }
581
9f2337c9
RW
582 if (!vrf_bitmap_check(zclient_vnc->redist[family2afi(rn->p.family)]
583 [ZEBRA_ROUTE_VNC],
584 VRF_DEFAULT))
d62a17ae 585 return;
586
587 if (!bgp->rfapi_cfg) {
588 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
589 __func__);
590 return;
591 }
592 if (!listcount(bgp->rfapi_cfg->rfg_export_zebra_l)) {
593 vnc_zlog_debug_verbose(
594 "%s: no zebra export nve group, skipping", __func__);
595 return;
596 }
597
598 import_table_to_nve_list_zebra(bgp, import_table, &nves, rn->p.family);
599
600 if (nves) {
601 nve_list_to_nh_array(rn->p.family, nves, &nexthop_count,
602 &nh_ary, &nhp_ary);
603
6a154c88 604 list_delete(&nves);
d62a17ae 605
606 if (nexthop_count)
607 vnc_zebra_route_msg(&rn->p, nexthop_count, nhp_ary,
608 add);
609 }
610
0a22ddfb
QY
611 XFREE(MTYPE_TMP, nhp_ary);
612 XFREE(MTYPE_TMP, nh_ary);
65efcfce
LB
613}
614
d62a17ae 615void vnc_zebra_add_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, 1);
65efcfce
LB
620}
621
d62a17ae 622void vnc_zebra_del_prefix(struct bgp *bgp,
623 struct rfapi_import_table *import_table,
fe08ba7e 624 struct agg_node *rn)
65efcfce 625{
d62a17ae 626 vnc_zebra_add_del_prefix(bgp, import_table, rn, 0);
65efcfce
LB
627}
628
629
d62a17ae 630static void vnc_zebra_add_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd,
631 int add) /* 0 = del, !0 = add */
65efcfce 632{
d62a17ae 633 struct listnode *node;
634 struct rfapi_rfg_name *rfgn;
635 struct rfapi_nve_group_cfg *rfg = rfd->rfg;
636 afi_t afi = family2afi(rfd->vn_addr.addr_family);
637 struct prefix nhp;
638 // struct prefix *nhpp;
639 void *pAddr;
640
641 vnc_zlog_debug_verbose("%s: entry, add=%d", __func__, add);
642
643 if (zclient_vnc->sock < 0)
644 return;
645
9f2337c9
RW
646 if (!vrf_bitmap_check(zclient_vnc->redist[afi][ZEBRA_ROUTE_VNC],
647 VRF_DEFAULT))
d62a17ae 648 return;
649
650 if (afi != AFI_IP && afi != AFI_IP6) {
450971aa 651 flog_err(EC_LIB_DEVELOPMENT, "%s: invalid vn addr family",
1c50c1c0 652 __func__);
d62a17ae 653 return;
654 }
655
656 if (!bgp)
657 return;
658 if (!bgp->rfapi_cfg) {
659 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
660 __func__);
661 return;
662 }
663
664 if (rfapiRaddr2Qprefix(&rfd->vn_addr, &nhp)) {
665 vnc_zlog_debug_verbose("%s: can't convert vn address, skipping",
666 __func__);
667 return;
668 }
669
670 pAddr = &nhp.u.prefix4;
671
672 /*
673 * Loop over the list of NVE-Groups configured for
674 * exporting to zebra and see if this new NVE's
675 * group is among them.
676 */
677 for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node,
678 rfgn)) {
679
680 /*
681 * Yes, this NVE's group is configured for export to zebra
682 */
683 if (rfgn->rfg == rfg) {
684
fe08ba7e
DS
685 struct agg_table *rt = NULL;
686 struct agg_node *rn;
d62a17ae 687 struct rfapi_import_table *import_table;
688 import_table = rfg->rfapi_import_table;
689
690 vnc_zlog_debug_verbose(
691 "%s: this nve's group is in zebra export list",
692 __func__);
693
694 rt = import_table->imported_vpn[afi];
695
696 /*
697 * Walk the NVE-Group's VNC Import table
698 */
fe08ba7e
DS
699 for (rn = agg_route_top(rt); rn;
700 rn = agg_route_next(rn)) {
d62a17ae 701
702 if (rn->info) {
703
704 vnc_zlog_debug_verbose(
705 "%s: sending %s", __func__,
706 (add ? "add" : "del"));
707 vnc_zebra_route_msg(&rn->p, 1, &pAddr,
708 add);
709 }
710 }
711 }
712 }
65efcfce
LB
713}
714
d62a17ae 715void vnc_zebra_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
65efcfce 716{
d62a17ae 717 vnc_zebra_add_del_nve(bgp, rfd, 1);
65efcfce
LB
718}
719
d62a17ae 720void vnc_zebra_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
65efcfce 721{
d62a17ae 722 vnc_zebra_add_del_nve(bgp, rfd, 0);
65efcfce
LB
723}
724
d62a17ae 725static void vnc_zebra_add_del_group_afi(struct bgp *bgp,
726 struct rfapi_nve_group_cfg *rfg,
727 afi_t afi, int add)
65efcfce 728{
fe08ba7e
DS
729 struct agg_table *rt = NULL;
730 struct agg_node *rn;
d62a17ae 731 struct rfapi_import_table *import_table;
732 uint8_t family = afi2family(afi);
733
734 struct list *nves = NULL;
a74e593b 735 unsigned int nexthop_count = 0;
d62a17ae 736 void *nh_ary = NULL;
737 void *nhp_ary = NULL;
738
739 vnc_zlog_debug_verbose("%s: entry", __func__);
740 import_table = rfg->rfapi_import_table;
741 if (!import_table) {
742 vnc_zlog_debug_verbose(
743 "%s: import table not defined, returning", __func__);
744 return;
745 }
746
747 if (afi == AFI_IP || afi == AFI_IP6) {
748 rt = import_table->imported_vpn[afi];
749 } else {
450971aa 750 flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d", __func__, afi);
d62a17ae 751 return;
752 }
753
754 if (!family) {
450971aa 755 flog_err(EC_LIB_DEVELOPMENT, "%s: computed bad family: %d",
1c50c1c0 756 __func__, family);
d62a17ae 757 return;
758 }
759
760 if (!rfg->nves) {
761 /* avoid segfault below if list doesn't exist */
762 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__);
763 return;
764 }
765
766 nve_group_to_nve_list(rfg, &nves, family);
767 if (nves) {
768 vnc_zlog_debug_verbose("%s: have nves", __func__);
769 nve_list_to_nh_array(family, nves, &nexthop_count, &nh_ary,
770 &nhp_ary);
771
772 vnc_zlog_debug_verbose("%s: family: %d, nve count: %d",
773 __func__, family, nexthop_count);
774
6a154c88 775 list_delete(&nves);
d62a17ae 776
777 if (nexthop_count) {
778 /*
779 * Walk the NVE-Group's VNC Import table
780 */
fe08ba7e
DS
781 for (rn = agg_route_top(rt); rn;
782 rn = agg_route_next(rn)) {
d62a17ae 783 if (rn->info) {
784 vnc_zebra_route_msg(&rn->p,
785 nexthop_count,
786 nhp_ary, add);
787 }
788 }
789 }
0a22ddfb
QY
790 XFREE(MTYPE_TMP, nhp_ary);
791 XFREE(MTYPE_TMP, nh_ary);
d62a17ae 792 }
65efcfce
LB
793}
794
d62a17ae 795void vnc_zebra_add_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
65efcfce 796{
d62a17ae 797 vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP, 1);
798 vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP6, 1);
65efcfce
LB
799}
800
d62a17ae 801void vnc_zebra_del_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
65efcfce 802{
d62a17ae 803 vnc_zlog_debug_verbose("%s: entry", __func__);
804 vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP, 0);
805 vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP6, 0);
65efcfce
LB
806}
807
d62a17ae 808void vnc_zebra_reexport_group_afi(struct bgp *bgp,
809 struct rfapi_nve_group_cfg *rfg, afi_t afi)
65efcfce 810{
d62a17ae 811 struct listnode *node;
812 struct rfapi_rfg_name *rfgn;
813
814 for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node,
815 rfgn)) {
816
817 if (rfgn->rfg == rfg) {
818 vnc_zebra_add_del_group_afi(bgp, rfg, afi, 0);
819 vnc_zebra_add_del_group_afi(bgp, rfg, afi, 1);
820 break;
821 }
822 }
65efcfce
LB
823}
824
825
826/***********************************************************************
827 * CONTROL INTERFACE
828 ***********************************************************************/
829
830
831/* Other routes redistribution into BGP. */
d62a17ae 832int vnc_redistribute_set(struct bgp *bgp, afi_t afi, int type)
65efcfce 833{
d62a17ae 834 if (!bgp->rfapi_cfg) {
835 return CMD_WARNING_CONFIG_FAILED;
836 }
65efcfce 837
d62a17ae 838 /* Set flag to BGP instance. */
839 bgp->rfapi_cfg->redist[afi][type] = 1;
65efcfce 840
d62a17ae 841 // bgp->redist[afi][type] = 1;
65efcfce 842
d62a17ae 843 /* Return if already redistribute flag is set. */
9f2337c9 844 if (vrf_bitmap_check(zclient_vnc->redist[afi][type], VRF_DEFAULT))
d62a17ae 845 return CMD_WARNING_CONFIG_FAILED;
65efcfce 846
d62a17ae 847 vrf_bitmap_set(zclient_vnc->redist[afi][type], VRF_DEFAULT);
65efcfce 848
9f2337c9 849 // vrf_bitmap_set(zclient_vnc->redist[afi][type], VRF_DEFAULT);
65efcfce 850
d62a17ae 851 /* Return if zebra connection is not established. */
852 if (zclient_vnc->sock < 0)
853 return CMD_WARNING_CONFIG_FAILED;
65efcfce 854
d62a17ae 855 if (BGP_DEBUG(zebra, ZEBRA))
856 vnc_zlog_debug_verbose("Zebra send: redistribute add %s",
857 zebra_route_string(type));
65efcfce 858
d62a17ae 859 /* Send distribute add message to zebra. */
860 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient_vnc, afi, type,
861 0, VRF_DEFAULT);
65efcfce 862
d62a17ae 863 return CMD_SUCCESS;
65efcfce
LB
864}
865
866/* Unset redistribution. */
d62a17ae 867int vnc_redistribute_unset(struct bgp *bgp, afi_t afi, int type)
65efcfce 868{
d62a17ae 869 vnc_zlog_debug_verbose("%s: type=%d entry", __func__, type);
870
871 if (!bgp->rfapi_cfg) {
872 vnc_zlog_debug_verbose("%s: return (no rfapi_cfg)", __func__);
873 return CMD_WARNING_CONFIG_FAILED;
874 }
875
876 /* Unset flag from BGP instance. */
877 bgp->rfapi_cfg->redist[afi][type] = 0;
878
879 /* Return if zebra connection is disabled. */
9f2337c9 880 if (!vrf_bitmap_check(zclient_vnc->redist[afi][type], VRF_DEFAULT))
d62a17ae 881 return CMD_WARNING_CONFIG_FAILED;
9f2337c9 882 vrf_bitmap_unset(zclient_vnc->redist[afi][type], VRF_DEFAULT);
d62a17ae 883
884 if (bgp->rfapi_cfg->redist[AFI_IP][type] == 0
885 && bgp->rfapi_cfg->redist[AFI_IP6][type] == 0
886 && zclient_vnc->sock >= 0) {
887 /* Send distribute delete message to zebra. */
888 if (BGP_DEBUG(zebra, ZEBRA))
889 vnc_zlog_debug_verbose(
890 "Zebra send: redistribute delete %s",
891 zebra_route_string(type));
892 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient_vnc,
893 afi, type, 0, VRF_DEFAULT);
894 }
895
896 /* Withdraw redistributed routes from current BGP's routing table. */
897 vnc_redistribute_withdraw(bgp, afi, type);
898
899 vnc_zlog_debug_verbose("%s: return", __func__);
900
901 return CMD_SUCCESS;
65efcfce
LB
902}
903
342213ea 904extern struct zebra_privs_t bgpd_privs;
65efcfce
LB
905
906/*
907 * Modeled after bgp_zebra.c'bgp_zebra_init()
908 * Charriere asks, "Is it possible to carry two?"
909 */
d62a17ae 910void vnc_zebra_init(struct thread_master *master)
65efcfce 911{
d62a17ae 912 /* Set default values. */
26f63a1e 913 zclient_vnc = zclient_new(master, &zclient_options_default);
342213ea 914 zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0, &bgpd_privs);
d62a17ae 915
74489921
RW
916 zclient_vnc->redistribute_route_add = vnc_zebra_read_route;
917 zclient_vnc->redistribute_route_del = vnc_zebra_read_route;
65efcfce
LB
918}
919
d62a17ae 920void vnc_zebra_destroy(void)
65efcfce 921{
d62a17ae 922 if (zclient_vnc == NULL)
923 return;
924 zclient_stop(zclient_vnc);
925 zclient_free(zclient_vnc);
926 zclient_vnc = NULL;
65efcfce 927}