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