]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/rfapi/vnc_zebra.c
Merge pull request #531 from qlyoung/fix-stack-ref
[mirror_frr.git] / bgpd / rfapi / vnc_zebra.c
CommitLineData
65efcfce
LB
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
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21
22/*
23 * File: vnc_zebra.c
24 * Purpose: Handle exchange of routes between VNC and Zebra
25 */
26
f8b6f499
LB
27#include "lib/zebra.h"
28#include "lib/prefix.h"
29#include "lib/table.h"
30#include "lib/log.h"
31#include "lib/command.h"
32#include "lib/zclient.h"
33#include "lib/stream.h"
34#include "lib/memory.h"
65efcfce 35
f8b6f499
LB
36#include "bgpd/bgpd.h"
37#include "bgpd/bgp_ecommunity.h"
38#include "bgpd/bgp_route.h"
39#include "bgpd/bgp_debug.h"
40#include "bgpd/bgp_advertise.h"
65efcfce 41
f8b6f499
LB
42#include "bgpd/rfapi/bgp_rfapi_cfg.h"
43#include "bgpd/rfapi/rfapi.h"
44#include "bgpd/rfapi/rfapi_import.h"
45#include "bgpd/rfapi/rfapi_private.h"
46#include "bgpd/rfapi/vnc_zebra.h"
47#include "bgpd/rfapi/rfapi_vty.h"
48#include "bgpd/rfapi/rfapi_backend.h"
a3b55c25 49#include "bgpd/rfapi/vnc_debug.h"
65efcfce
LB
50
51static struct rfapi_descriptor vncHD1VR; /* Single-VR export dummy nve descr */
52static struct zclient *zclient_vnc = NULL;
53
54/***********************************************************************
55 * REDISTRIBUTE: Zebra sends updates/withdraws to BGPD
56 ***********************************************************************/
57
58/*
59 * Routes coming from zebra get added to VNC here
60 */
61static void
62vnc_redistribute_add (
63 struct prefix *p,
64 struct in_addr *nexthop,
65 u_int32_t metric,
66 uint8_t type)
67{
68 struct bgp *bgp = bgp_get_default ();
69 struct prefix_rd prd;
70 struct rfapi_ip_addr vnaddr;
71 afi_t afi;
72 uint32_t local_pref = rfp_cost_to_localpref (metric > 255 ? 255 : metric);
73
74 if (!bgp)
75 return;
76
77 if (!bgp->rfapi_cfg)
78 {
a3b55c25 79 vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__);
65efcfce
LB
80 return;
81 }
82
83 afi = family2afi (p->family);
84 if (!afi)
85 {
a3b55c25 86 vnc_zlog_debug_verbose ("%s: unknown prefix address family %d", __func__,
65efcfce
LB
87 p->family);
88 return;
89 }
90
91 if (!bgp->rfapi_cfg->redist[afi][type])
92 {
a3b55c25 93 vnc_zlog_debug_verbose
65efcfce
LB
94 ("%s: bgp->rfapi_cfg->redist[afi=%d][type=%d] is 0, skipping",
95 __func__, afi, type);
96 return;
97 }
98 if (!bgp->rfapi_cfg->rfg_redist)
99 {
a3b55c25 100 vnc_zlog_debug_verbose ("%s: no redist nve group, skipping", __func__);
65efcfce
LB
101 return;
102 }
103
104 /*
105 * Assume nve group's configured VN address prefix is a host
106 * route which also happens to give the NVE VN address to use
107 * for redistributing into VNC.
108 */
109 vnaddr.addr_family = bgp->rfapi_cfg->rfg_redist->vn_prefix.family;
110 switch (bgp->rfapi_cfg->rfg_redist->vn_prefix.family)
111 {
112 case AF_INET:
113 if (bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen != 32)
114 {
a3b55c25 115 vnc_zlog_debug_verbose
65efcfce
LB
116 ("%s: redist nve group VN prefix len (%d) != 32, skipping",
117 __func__, bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen);
118 return;
119 }
120 vnaddr.addr.v4 = bgp->rfapi_cfg->rfg_redist->vn_prefix.u.prefix4;
121 break;
122 case AF_INET6:
123 if (bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen != 128)
124 {
a3b55c25 125 vnc_zlog_debug_verbose
65efcfce
LB
126 ("%s: redist nve group VN prefix len (%d) != 128, skipping",
127 __func__, bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen);
128 return;
129 }
130 vnaddr.addr.v6 = bgp->rfapi_cfg->rfg_redist->vn_prefix.u.prefix6;
131 break;
132 default:
a3b55c25 133 vnc_zlog_debug_verbose
65efcfce
LB
134 ("%s: no redist nve group VN host prefix configured, skipping",
135 __func__);
136 return;
137 }
138
139 /*
140 * Assume nve group's configured UN address prefix is a host
141 * route which also happens to give the NVE UN address to use
142 * for redistributing into VNC.
143 */
144
145 /*
146 * Set UN address in dummy nve descriptor so add_vnc_route
147 * can use it in VNC tunnel SubTLV
148 */
149 {
150 struct rfapi_ip_prefix pfx_un;
151
152 rfapiQprefix2Rprefix (&bgp->rfapi_cfg->rfg_redist->un_prefix, &pfx_un);
153
154 switch (pfx_un.prefix.addr_family)
155 {
156 case AF_INET:
157 if (pfx_un.length != 32)
158 {
a3b55c25 159 vnc_zlog_debug_verbose
65efcfce
LB
160 ("%s: redist nve group UN prefix len (%d) != 32, skipping",
161 __func__, pfx_un.length);
162 return;
163 }
164 break;
165 case AF_INET6:
166 if (pfx_un.length != 128)
167 {
a3b55c25 168 vnc_zlog_debug_verbose
65efcfce
LB
169 ("%s: redist nve group UN prefix len (%d) != 128, skipping",
170 __func__, pfx_un.length);
171 return;
172 }
173 break;
174 default:
a3b55c25 175 vnc_zlog_debug_verbose
65efcfce
LB
176 ("%s: no redist nve group UN host prefix configured, skipping",
177 __func__);
178 return;
179 }
180
181 vncHD1VR.un_addr = pfx_un.prefix;
182
183 if (!vncHD1VR.peer)
184 {
185 /*
186 * Same setup as in rfapi_open()
187 */
188 vncHD1VR.peer = peer_new (bgp);
189 vncHD1VR.peer->status = Established; /* keep bgp core happy */
190 bgp_sync_delete (vncHD1VR.peer); /* don't need these */
191 if (vncHD1VR.peer->ibuf)
192 {
193 stream_free (vncHD1VR.peer->ibuf); /* don't need it */
194 vncHD1VR.peer->ibuf = NULL;
195 }
196 if (vncHD1VR.peer->obuf)
197 {
198 stream_fifo_free (vncHD1VR.peer->obuf); /* don't need it */
199 vncHD1VR.peer->obuf = NULL;
200 }
201 if (vncHD1VR.peer->work)
202 {
203 stream_free (vncHD1VR.peer->work); /* don't need it */
204 vncHD1VR.peer->work = NULL;
205 }
206 /* base code assumes have valid host pointer */
207 vncHD1VR.peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, ".zebra.");
208
209 /* Mark peer as belonging to HD */
210 SET_FLAG (vncHD1VR.peer->flags, PEER_FLAG_IS_RFAPI_HD);
211 }
212 }
213
214 memset (&prd, 0, sizeof (prd));
215 prd = bgp->rfapi_cfg->rfg_redist->rd;
216 prd.family = AF_UNSPEC;
217 prd.prefixlen = 64;
218
219 add_vnc_route (&vncHD1VR, /* cookie + UN addr */
220 bgp, SAFI_MPLS_VPN, p, &prd, &vnaddr, &local_pref, &(bgp->rfapi_cfg->redist_lifetime), NULL, /* RFP options */
221 NULL, /* struct rfapi_un_option */
222 NULL, /* struct rfapi_vn_option */
223 bgp->rfapi_cfg->rfg_redist->rt_export_list, NULL, NULL, /* label: default */
224 type, BGP_ROUTE_REDISTRIBUTE, 0); /* flags */
225}
226
227/*
228 * Route deletions from zebra propagate to VNC here
229 */
230static void
231vnc_redistribute_delete (struct prefix *p, uint8_t type)
232{
233 struct bgp *bgp = bgp_get_default ();
234 struct prefix_rd prd;
235 afi_t afi;
236
237 if (!bgp)
238 return;
239
240 if (!bgp->rfapi_cfg)
241 {
a3b55c25 242 vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__);
65efcfce
LB
243 return;
244 }
245 afi = family2afi (p->family);
246 if (!afi)
247 {
a3b55c25 248 vnc_zlog_debug_verbose ("%s: unknown prefix address family %d", __func__,
65efcfce
LB
249 p->family);
250 return;
251 }
252 if (!bgp->rfapi_cfg->redist[afi][type])
253 {
a3b55c25 254 vnc_zlog_debug_verbose
65efcfce
LB
255 ("%s: bgp->rfapi_cfg->redist[afi=%d][type=%d] is 0, skipping",
256 __func__, afi, type);
257 return;
258 }
259 if (!bgp->rfapi_cfg->rfg_redist)
260 {
a3b55c25 261 vnc_zlog_debug_verbose ("%s: no redist nve group, skipping", __func__);
65efcfce
LB
262 return;
263 }
264
265 memset (&prd, 0, sizeof (prd));
266 prd = bgp->rfapi_cfg->rfg_redist->rd;
267 prd.family = AF_UNSPEC;
268 prd.prefixlen = 64;
269
270 del_vnc_route (&vncHD1VR, /* use dummy ptr as cookie */
271 vncHD1VR.peer,
272 bgp,
273 SAFI_MPLS_VPN,
274 p, &prd, type, BGP_ROUTE_REDISTRIBUTE, NULL, 0);
275}
276
277/*
278 * Flush all redistributed routes of type <type>
279 */
280static void
281vnc_redistribute_withdraw (struct bgp *bgp, afi_t afi, uint8_t type)
282{
283 struct prefix_rd prd;
284 struct bgp_table *table;
285 struct bgp_node *prn;
286 struct bgp_node *rn;
287
a3b55c25 288 vnc_zlog_debug_verbose ("%s: entry", __func__);
65efcfce
LB
289
290 if (!bgp)
291 return;
292 if (!bgp->rfapi_cfg)
293 {
a3b55c25 294 vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__);
65efcfce
LB
295 return;
296 }
297
298 /*
299 * Loop over all the RDs
300 */
301 for (prn = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); prn;
302 prn = bgp_route_next (prn))
303 {
304 memset (&prd, 0, sizeof (prd));
305 prd.family = AF_UNSPEC;
306 prd.prefixlen = 64;
307 memcpy (prd.val, prn->p.u.val, 8);
308
309 /* This is the per-RD table of prefixes */
310 table = prn->info;
311
312 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
313 {
314
315 struct bgp_info *ri;
316
317 for (ri = rn->info; ri; ri = ri->next)
318 {
319 if (ri->type == type)
320 { /* has matching redist type */
321 break;
322 }
323 }
324 if (ri)
325 {
326 del_vnc_route (&vncHD1VR, /* use dummy ptr as cookie */
327 vncHD1VR.peer,
328 bgp,
329 SAFI_MPLS_VPN,
330 &(rn->p),
331 &prd, type, BGP_ROUTE_REDISTRIBUTE, NULL, 0);
332 }
333 }
334 }
a3b55c25 335 vnc_zlog_debug_verbose ("%s: return", __func__);
65efcfce
LB
336}
337
338/*
339 * Zebra route add and delete treatment.
340 *
341 * Assumes 1 nexthop
342 */
343static int
344vnc_zebra_read_ipv4 (
345 int command,
346 struct zclient *zclient,
347 zebra_size_t length,
348 vrf_id_t vrf_id)
349{
350 struct stream *s;
351 struct zapi_ipv4 api;
65efcfce
LB
352 struct in_addr nexthop;
353 struct prefix_ipv4 p;
354
355 s = zclient->ibuf;
65efcfce
LB
356 nexthop.s_addr = 0;
357
358 /* Type, flags, message. */
359 api.type = stream_getc (s);
360 api.flags = stream_getc (s);
361 api.message = stream_getc (s);
362
363 /* IPv4 prefix. */
364 memset (&p, 0, sizeof (struct prefix_ipv4));
365 p.family = AF_INET;
366 p.prefixlen = stream_getc (s);
367 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
368
369 /* Nexthop, ifindex, distance, metric. */
370 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
371 {
372 api.nexthop_num = stream_getc (s);
373 nexthop.s_addr = stream_get_ipv4 (s);
374 }
375 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
376 {
377 api.ifindex_num = stream_getc (s);
2de1475f 378 stream_getl (s);
65efcfce
LB
379 }
380 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
381 api.distance = stream_getc (s);
382 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
383 api.metric = stream_getl (s);
384 else
385 api.metric = 0;
386
387 if (command == ZEBRA_IPV4_ROUTE_ADD)
388 {
389 if (BGP_DEBUG (zebra, ZEBRA))
390 {
391 char buf[2][INET_ADDRSTRLEN];
a3b55c25 392 vnc_zlog_debug_verbose
65efcfce
LB
393 ("%s: Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u",
394 __func__, zebra_route_string (api.type), inet_ntop (AF_INET,
395 &p.prefix,
396 buf[0],
397 sizeof (buf
398 [0])),
399 p.prefixlen, inet_ntop (AF_INET, &nexthop, buf[1],
400 sizeof (buf[1])), api.metric);
401 }
402 vnc_redistribute_add ((struct prefix *) &p, &nexthop, api.metric,
403 api.type);
404 }
405 else
406 {
407 if (BGP_DEBUG (zebra, ZEBRA))
408 {
409 char buf[2][INET_ADDRSTRLEN];
a3b55c25 410 vnc_zlog_debug_verbose ("%s: Zebra rcvd: IPv4 route delete %s %s/%d "
65efcfce
LB
411 "nexthop %s metric %u",
412 __func__,
413 zebra_route_string (api.type),
414 inet_ntop (AF_INET, &p.prefix, buf[0], sizeof (buf[0])),
415 p.prefixlen,
416 inet_ntop (AF_INET, &nexthop, buf[1], sizeof (buf[1])),
417 api.metric);
418 }
419 vnc_redistribute_delete ((struct prefix *) &p, api.type);
420 }
421
422 return 0;
423}
424
425/* Zebra route add and delete treatment. */
426static int
427vnc_zebra_read_ipv6 (
428 int command,
429 struct zclient *zclient,
430 zebra_size_t length,
431 vrf_id_t vrf_id)
432{
433 struct stream *s;
434 struct zapi_ipv6 api;
65efcfce 435 struct in6_addr nexthop;
81a164e2 436 struct prefix_ipv6 p, src_p;
65efcfce
LB
437
438 s = zclient->ibuf;
65efcfce
LB
439 memset (&nexthop, 0, sizeof (struct in6_addr));
440
441 /* Type, flags, message. */
442 api.type = stream_getc (s);
443 api.flags = stream_getc (s);
444 api.message = stream_getc (s);
445
446 /* IPv6 prefix. */
447 memset (&p, 0, sizeof (struct prefix_ipv6));
448 p.family = AF_INET6;
449 p.prefixlen = stream_getc (s);
450 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
451
81a164e2
CF
452 memset (&src_p, 0, sizeof (struct prefix_ipv6));
453 src_p.family = AF_INET6;
454 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_SRCPFX))
455 {
456 src_p.prefixlen = stream_getc (s);
457 stream_get (&src_p.prefix, s, PSIZE (src_p.prefixlen));
458 }
459
460 if (src_p.prefixlen)
461 /* we completely ignore srcdest routes for now. */
462 return 0;
463
65efcfce
LB
464 /* Nexthop, ifindex, distance, metric. */
465 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
466 {
467 api.nexthop_num = stream_getc (s);
468 stream_get (&nexthop, s, 16);
469 }
470 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
471 {
472 api.ifindex_num = stream_getc (s);
2de1475f 473 stream_getl (s);
65efcfce
LB
474 }
475 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
476 api.distance = stream_getc (s);
477 else
478 api.distance = 0;
479 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
480 api.metric = stream_getl (s);
481 else
482 api.metric = 0;
483
484 /* Simply ignore link-local address. */
485 if (IN6_IS_ADDR_LINKLOCAL (&p.prefix))
486 return 0;
487
488 if (command == ZEBRA_IPV6_ROUTE_ADD)
489 {
490 if (BGP_DEBUG (zebra, ZEBRA))
491 {
492 char buf[INET6_ADDRSTRLEN];
a3b55c25 493 vnc_zlog_debug_verbose ("Zebra rcvd: IPv6 route add %s %s/%d metric %u",
65efcfce
LB
494 zebra_route_string (api.type),
495 inet_ntop (AF_INET6, &p.prefix, buf, sizeof (buf)),
496 p.prefixlen, api.metric);
497 }
498 vnc_redistribute_add ((struct prefix *) &p, NULL, api.metric, api.type);
499 }
500 else
501 {
502 if (BGP_DEBUG (zebra, ZEBRA))
503 {
504 char buf[INET6_ADDRSTRLEN];
a3b55c25 505 vnc_zlog_debug_verbose ("Zebra rcvd: IPv6 route delete %s %s/%d metric %u",
65efcfce
LB
506 zebra_route_string (api.type),
507 inet_ntop (AF_INET6, &p.prefix, buf, sizeof (buf)),
508 p.prefixlen, api.metric);
509 }
510 vnc_redistribute_delete ((struct prefix *) &p, api.type);
511 }
512
513 return 0;
514}
515
516/***********************************************************************
517 * vnc_bgp_zebra_*: VNC sends updates/withdraws to Zebra
518 ***********************************************************************/
519
520/*
521 * low-level message builder
522 */
523static void
524vnc_zebra_route_msg (
525 struct prefix *p,
526 int nhp_count,
527 void *nhp_ary,
528 int add) /* 1 = add, 0 = del */
529{
530 if (!nhp_count)
531 {
a3b55c25 532 vnc_zlog_debug_verbose ("%s: empty nexthop list, skipping", __func__);
65efcfce
LB
533 return;
534 }
535
536 if (p->family == AF_INET)
537 {
538
539 struct zapi_ipv4 api;
540
541 api.flags = 0;
542 api.vrf_id = VRF_DEFAULT;
543 api.type = ZEBRA_ROUTE_VNC;
544 api.message = 0;
545 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); /* TBD what's it mean? */
546 api.nexthop_num = nhp_count;
547 api.nexthop = nhp_ary;
548 api.ifindex_num = 0;
98280b73 549 api.instance = 0;
daf9ddbb 550 api.safi = SAFI_UNICAST;
65efcfce
LB
551
552 if (BGP_DEBUG (zebra, ZEBRA))
553 {
554
555 char buf[INET_ADDRSTRLEN];
a3b55c25 556 vnc_zlog_debug_verbose ("%s: Zebra send: IPv4 route %s %s/%d, nhp_count=%d",
65efcfce
LB
557 __func__,
558 (add ? "add" : "del"),
559 inet_ntop (AF_INET, &p->u.prefix4, buf, sizeof (buf)),
560 p->prefixlen, nhp_count);
561 }
562
563 zapi_ipv4_route ((add ? ZEBRA_IPV4_NEXTHOP_ADD :
564 ZEBRA_IPV4_NEXTHOP_DELETE), zclient_vnc,
565 (struct prefix_ipv4 *) p, &api);
566
567 }
568 else if (p->family == AF_INET6)
569 {
570
571 struct zapi_ipv6 api;
572 ifindex_t ifindex = 0;
573
574 /* Make Zebra API structure. */
575 api.flags = 0;
576 api.vrf_id = VRF_DEFAULT;
577 api.type = ZEBRA_ROUTE_VNC;
578 api.message = 0;
579 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); /* TBD means? */
580 api.nexthop_num = nhp_count;
581 api.nexthop = nhp_ary;
582 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
583 api.ifindex_num = 1;
584 api.ifindex = &ifindex;
98280b73 585 api.instance = 0;
daf9ddbb 586 api.safi = SAFI_UNICAST;
65efcfce
LB
587
588 if (BGP_DEBUG (zebra, ZEBRA))
589 {
590
591 char buf[INET6_ADDRSTRLEN];
a3b55c25 592 vnc_zlog_debug_verbose ("%s: Zebra send: IPv6 route %s %s/%d nhp_count=%d",
65efcfce
LB
593 __func__,
594 (add ? "add" : "del"),
595 inet_ntop (AF_INET6, &p->u.prefix6, buf, sizeof (buf)),
596 p->prefixlen, nhp_count);
597 }
598
599 zapi_ipv6_route ((add ? ZEBRA_IPV6_NEXTHOP_ADD :
600 ZEBRA_IPV6_NEXTHOP_DELETE), zclient_vnc,
d75f3b00 601 (struct prefix_ipv6 *) p, NULL, &api);
65efcfce
LB
602 }
603 else
604 {
a3b55c25 605 vnc_zlog_debug_verbose ("%s: unknown prefix address family, skipping", __func__);
65efcfce
LB
606 return;
607 }
608}
609
610
611static void
612nve_list_to_nh_array (
613 u_char family,
614 struct list *nve_list,
615 int *nh_count_ret,
616 void **nh_ary_ret, /* returned address array */
617 void **nhp_ary_ret) /* returned pointer array */
618{
619 int nve_count = listcount (nve_list);
620
621 *nh_count_ret = 0;
622 *nh_ary_ret = NULL;
623 *nhp_ary_ret = NULL;
624
625 if (!nve_count)
626 {
a3b55c25 627 vnc_zlog_debug_verbose ("%s: empty nve_list, skipping", __func__);
65efcfce
LB
628 return;
629 }
630
631 if (family == AF_INET)
632 {
633 struct listnode *ln;
634 struct in_addr *iap;
635 struct in_addr **v;
636
637 /*
638 * Array of nexthop addresses
639 */
640 *nh_ary_ret = XCALLOC (MTYPE_TMP, nve_count * sizeof (struct in_addr));
641
642 /*
643 * Array of pointers to nexthop addresses
644 */
645 *nhp_ary_ret =
646 XCALLOC (MTYPE_TMP, nve_count * sizeof (struct in_addr *));
647 iap = *nh_ary_ret;
648 v = *nhp_ary_ret;
649
650 for (ln = listhead (nve_list); ln; ln = listnextnode (ln))
651 {
652
653 struct rfapi_descriptor *irfd;
654 struct prefix nhp;
655
656 irfd = listgetdata (ln);
657
658 if (rfapiRaddr2Qprefix (&irfd->vn_addr, &nhp))
659 continue;
660
661 *iap = nhp.u.prefix4;
662 *v = iap;
a3b55c25 663 vnc_zlog_debug_verbose ("%s: ipadr: (%p)<-0x%x, ptr: (%p)<-%p",
65efcfce
LB
664 __func__, iap, nhp.u.prefix4.s_addr, v, iap);
665
666 ++iap;
667 ++v;
668 ++*nh_count_ret;
669 }
670
671 }
672 else if (family == AF_INET6)
673 {
674
675 struct listnode *ln;
676
677 *nh_ary_ret = XCALLOC (MTYPE_TMP, nve_count * sizeof (struct in6_addr));
678
679 *nhp_ary_ret = XCALLOC (MTYPE_TMP,
680 nve_count * sizeof (struct in6_addr *));
681
682 for (ln = listhead (nve_list); ln; ln = listnextnode (ln))
683 {
684
685 struct rfapi_descriptor *irfd;
686 struct in6_addr *iap = *nh_ary_ret;
687 struct in6_addr **v = *nhp_ary_ret;
688 struct prefix nhp;
689
690 irfd = listgetdata (ln);
691
692 if (rfapiRaddr2Qprefix (&irfd->vn_addr, &nhp))
693 continue;
694
695 *iap = nhp.u.prefix6;
696 *v = iap;
697
698 ++iap;
699 ++v;
700 ++*nh_count_ret;
701 }
702 }
703}
704
705static void
706import_table_to_nve_list_zebra (
707 struct bgp *bgp,
708 struct rfapi_import_table *it,
709 struct list **nves,
710 uint8_t family)
711{
712 struct listnode *node;
713 struct rfapi_rfg_name *rfgn;
714
715 /*
716 * Loop over the list of NVE-Groups configured for
717 * exporting to direct-bgp.
718 *
719 * Build a list of NVEs that use this import table
720 */
721 *nves = NULL;
722 for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn))
723 {
724
725 /*
726 * If this NVE-Group's import table matches the current one
727 */
728 if (rfgn->rfg && rfgn->rfg->nves && rfgn->rfg->rfapi_import_table == it)
729 {
730
731 nve_group_to_nve_list (rfgn->rfg, nves, family);
732 }
733 }
734}
735
736static void
737vnc_zebra_add_del_prefix (
738 struct bgp *bgp,
739 struct rfapi_import_table *import_table,
740 struct route_node *rn,
741 int add) /* !0 = add, 0 = del */
742{
743 struct list *nves;
744
745 int nexthop_count = 0;
746 void *nh_ary = NULL;
747 void *nhp_ary = NULL;
748
a3b55c25 749 vnc_zlog_debug_verbose ("%s: entry, add=%d", __func__, add);
65efcfce
LB
750
751 if (zclient_vnc->sock < 0)
752 return;
753
754 if (rn->p.family != AF_INET
755 && rn->p.family != AF_INET6)
756 {
757 zlog_err ("%s: invalid route node addr family", __func__);
758 return;
759 }
760
761 if (!zclient_vnc->redist[family2afi(rn->p.family)][ZEBRA_ROUTE_VNC])
762 return;
763
764 if (!bgp->rfapi_cfg)
765 {
a3b55c25 766 vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__);
65efcfce
LB
767 return;
768 }
769 if (!listcount (bgp->rfapi_cfg->rfg_export_zebra_l))
770 {
a3b55c25 771 vnc_zlog_debug_verbose ("%s: no zebra export nve group, skipping", __func__);
65efcfce
LB
772 return;
773 }
774
775 import_table_to_nve_list_zebra (bgp, import_table, &nves, rn->p.family);
776
777 if (nves)
778 {
779 nve_list_to_nh_array (rn->p.family,
780 nves, &nexthop_count, &nh_ary, &nhp_ary);
781
782 list_delete (nves);
783
784 if (nexthop_count)
785 vnc_zebra_route_msg (&rn->p, nexthop_count, nhp_ary, add);
786 }
787
788 if (nhp_ary)
789 XFREE (MTYPE_TMP, nhp_ary);
790 if (nh_ary)
791 XFREE (MTYPE_TMP, nh_ary);
792}
793
794void
795vnc_zebra_add_prefix (
796 struct bgp *bgp,
797 struct rfapi_import_table *import_table,
798 struct route_node *rn)
799{
800 vnc_zebra_add_del_prefix (bgp, import_table, rn, 1);
801}
802
803void
804vnc_zebra_del_prefix (
805 struct bgp *bgp,
806 struct rfapi_import_table *import_table,
807 struct route_node *rn)
808{
809 vnc_zebra_add_del_prefix (bgp, import_table, rn, 0);
810}
811
812
813
814static void
815vnc_zebra_add_del_nve (
816 struct bgp *bgp,
817 struct rfapi_descriptor *rfd,
818 int add) /* 0 = del, !0 = add */
819{
820 struct listnode *node;
821 struct rfapi_rfg_name *rfgn;
822 struct rfapi_nve_group_cfg *rfg = rfd->rfg;
823 afi_t afi = family2afi (rfd->vn_addr.addr_family);
824 struct prefix nhp;
825// struct prefix *nhpp;
826 void *pAddr;
827
a3b55c25 828 vnc_zlog_debug_verbose ("%s: entry, add=%d", __func__, add);
65efcfce
LB
829
830 if (zclient_vnc->sock < 0)
831 return;
832
833 if (!zclient_vnc->redist[afi][ZEBRA_ROUTE_VNC])
834 return;
835
836 if (afi != AFI_IP && afi != AFI_IP6)
837 {
838 zlog_err ("%s: invalid vn addr family", __func__);
839 return;
840 }
841
842 if (!bgp)
843 return;
844 if (!bgp->rfapi_cfg)
845 {
a3b55c25 846 vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__);
65efcfce
LB
847 return;
848 }
849
850 if (rfapiRaddr2Qprefix (&rfd->vn_addr, &nhp))
851 {
a3b55c25 852 vnc_zlog_debug_verbose ("%s: can't convert vn address, skipping", __func__);
65efcfce
LB
853 return;
854 }
855
856 pAddr = &nhp.u.prefix4;
857
858 /*
859 * Loop over the list of NVE-Groups configured for
860 * exporting to zebra and see if this new NVE's
861 * group is among them.
862 */
863 for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn))
864 {
865
866 /*
867 * Yes, this NVE's group is configured for export to zebra
868 */
869 if (rfgn->rfg == rfg)
870 {
871
872 struct route_table *rt = NULL;
873 struct route_node *rn;
874 struct rfapi_import_table *import_table;
875 import_table = rfg->rfapi_import_table;
876
a3b55c25 877 vnc_zlog_debug_verbose ("%s: this nve's group is in zebra export list",
65efcfce
LB
878 __func__);
879
880 rt = import_table->imported_vpn[afi];
881
882 /*
883 * Walk the NVE-Group's VNC Import table
884 */
885 for (rn = route_top (rt); rn; rn = route_next (rn))
886 {
887
888 if (rn->info)
889 {
890
a3b55c25 891 vnc_zlog_debug_verbose ("%s: sending %s", __func__,
65efcfce
LB
892 (add ? "add" : "del"));
893 vnc_zebra_route_msg (&rn->p, 1, &pAddr, add);
894 }
895 }
896 }
897 }
898}
899
900void
901vnc_zebra_add_nve (struct bgp *bgp, struct rfapi_descriptor *rfd)
902{
903 vnc_zebra_add_del_nve (bgp, rfd, 1);
904}
905
906void
907vnc_zebra_del_nve (struct bgp *bgp, struct rfapi_descriptor *rfd)
908{
909 vnc_zebra_add_del_nve (bgp, rfd, 0);
910}
911
912static void
913vnc_zebra_add_del_group_afi (
914 struct bgp *bgp,
915 struct rfapi_nve_group_cfg *rfg,
916 afi_t afi,
917 int add)
918{
919 struct route_table *rt = NULL;
920 struct route_node *rn;
921 struct rfapi_import_table *import_table;
922 uint8_t family = afi2family (afi);
923
924 struct list *nves = NULL;
925 int nexthop_count = 0;
926 void *nh_ary = NULL;
927 void *nhp_ary = NULL;
928
a3b55c25 929 vnc_zlog_debug_verbose ("%s: entry", __func__);
65efcfce
LB
930 import_table = rfg->rfapi_import_table;
931 if (!import_table)
932 {
a3b55c25 933 vnc_zlog_debug_verbose ("%s: import table not defined, returning", __func__);
65efcfce
LB
934 return;
935 }
936
937 if (afi == AFI_IP
938 || afi == AFI_IP6)
939 {
940 rt = import_table->imported_vpn[afi];
941 }
942 else
943 {
944 zlog_err ("%s: bad afi %d", __func__, afi);
945 return;
946 }
947
948 if (!family)
949 {
950 zlog_err ("%s: computed bad family: %d", __func__, family);
951 return;
952 }
953
954 if (!rfg->nves)
955 {
956 /* avoid segfault below if list doesn't exist */
a3b55c25 957 vnc_zlog_debug_verbose ("%s: no NVEs in this group", __func__);
65efcfce
LB
958 return;
959 }
960
961 nve_group_to_nve_list (rfg, &nves, family);
962 if (nves)
963 {
a3b55c25 964 vnc_zlog_debug_verbose ("%s: have nves", __func__);
65efcfce
LB
965 nve_list_to_nh_array (family, nves, &nexthop_count, &nh_ary, &nhp_ary);
966
a3b55c25 967 vnc_zlog_debug_verbose ("%s: family: %d, nve count: %d", __func__, family,
65efcfce
LB
968 nexthop_count);
969
970 list_delete (nves);
971
972 if (nexthop_count)
973 {
974 /*
975 * Walk the NVE-Group's VNC Import table
976 */
977 for (rn = route_top (rt); rn; rn = route_next (rn))
978 {
979 if (rn->info)
980 {
981 vnc_zebra_route_msg (&rn->p, nexthop_count, nhp_ary, add);
982 }
983 }
984 }
985 if (nhp_ary)
986 XFREE (MTYPE_TMP, nhp_ary);
987 if (nh_ary)
988 XFREE (MTYPE_TMP, nh_ary);
989 }
990}
991
992void
993vnc_zebra_add_group (struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
994{
995 vnc_zebra_add_del_group_afi (bgp, rfg, AFI_IP, 1);
996 vnc_zebra_add_del_group_afi (bgp, rfg, AFI_IP6, 1);
997}
998
999void
1000vnc_zebra_del_group (struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
1001{
a3b55c25 1002 vnc_zlog_debug_verbose ("%s: entry", __func__);
65efcfce
LB
1003 vnc_zebra_add_del_group_afi (bgp, rfg, AFI_IP, 0);
1004 vnc_zebra_add_del_group_afi (bgp, rfg, AFI_IP6, 0);
1005}
1006
1007void
1008vnc_zebra_reexport_group_afi (
1009 struct bgp *bgp,
1010 struct rfapi_nve_group_cfg *rfg,
1011 afi_t afi)
1012{
1013 struct listnode *node;
1014 struct rfapi_rfg_name *rfgn;
1015
1016 for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn))
1017 {
1018
1019 if (rfgn->rfg == rfg)
1020 {
1021 vnc_zebra_add_del_group_afi (bgp, rfg, afi, 0);
1022 vnc_zebra_add_del_group_afi (bgp, rfg, afi, 1);
1023 break;
1024 }
1025 }
1026}
1027
1028
1029/***********************************************************************
1030 * CONTROL INTERFACE
1031 ***********************************************************************/
1032
1033
1034/* Other routes redistribution into BGP. */
1035int
1036vnc_redistribute_set (struct bgp *bgp, afi_t afi, int type)
1037{
1038 if (!bgp->rfapi_cfg)
1039 {
1040 return CMD_WARNING;
1041 }
1042
1043 /* Set flag to BGP instance. */
1044 bgp->rfapi_cfg->redist[afi][type] = 1;
1045
1046// bgp->redist[afi][type] = 1;
1047
1048 /* Return if already redistribute flag is set. */
1049 if (zclient_vnc->redist[afi][type])
1050 return CMD_WARNING;
1051
1052 vrf_bitmap_set (zclient_vnc->redist[afi][type], VRF_DEFAULT);
1053
1054 //zclient_vnc->redist[afi][type] = 1;
1055
1056 /* Return if zebra connection is not established. */
1057 if (zclient_vnc->sock < 0)
1058 return CMD_WARNING;
1059
1060 if (BGP_DEBUG (zebra, ZEBRA))
a3b55c25 1061 vnc_zlog_debug_verbose ("Zebra send: redistribute add %s", zebra_route_string (type));
65efcfce
LB
1062
1063 /* Send distribute add message to zebra. */
1064 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient_vnc, afi, type, 0, VRF_DEFAULT);
1065
1066 return CMD_SUCCESS;
1067}
1068
1069/* Unset redistribution. */
1070int
1071vnc_redistribute_unset (struct bgp *bgp, afi_t afi, int type)
1072{
a3b55c25 1073 vnc_zlog_debug_verbose ("%s: type=%d entry", __func__, type);
65efcfce
LB
1074
1075 if (!bgp->rfapi_cfg)
1076 {
a3b55c25 1077 vnc_zlog_debug_verbose ("%s: return (no rfapi_cfg)", __func__);
65efcfce
LB
1078 return CMD_WARNING;
1079 }
1080
1081 /* Unset flag from BGP instance. */
1082 bgp->rfapi_cfg->redist[afi][type] = 0;
1083
1084 /* Return if zebra connection is disabled. */
1085 if (!zclient_vnc->redist[afi][type])
1086 return CMD_WARNING;
1087 zclient_vnc->redist[afi][type] = 0;
1088
1089 if (bgp->rfapi_cfg->redist[AFI_IP][type] == 0
1090 && bgp->rfapi_cfg->redist[AFI_IP6][type] == 0 && zclient_vnc->sock >= 0)
1091 {
1092 /* Send distribute delete message to zebra. */
1093 if (BGP_DEBUG (zebra, ZEBRA))
a3b55c25 1094 vnc_zlog_debug_verbose ("Zebra send: redistribute delete %s",
65efcfce
LB
1095 zebra_route_string (type));
1096 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient_vnc, afi, type,
1097 0, VRF_DEFAULT);
1098 }
1099
1100 /* Withdraw redistributed routes from current BGP's routing table. */
1101 vnc_redistribute_withdraw (bgp, afi, type);
1102
a3b55c25 1103 vnc_zlog_debug_verbose ("%s: return", __func__);
65efcfce
LB
1104
1105 return CMD_SUCCESS;
1106}
1107
1108
1109/*
1110 * Modeled after bgp_zebra.c'bgp_zebra_init()
1111 * Charriere asks, "Is it possible to carry two?"
1112 */
1113void
1114vnc_zebra_init (struct thread_master *master)
1115{
1116 /* Set default values. */
1117 zclient_vnc = zclient_new (master);
1118 zclient_init (zclient_vnc, ZEBRA_ROUTE_VNC, 0);
1119
1120 zclient_vnc->redistribute_route_ipv4_add = vnc_zebra_read_ipv4;
1121 zclient_vnc->redistribute_route_ipv4_del = vnc_zebra_read_ipv4;
1122 zclient_vnc->redistribute_route_ipv6_add = vnc_zebra_read_ipv6;
1123 zclient_vnc->redistribute_route_ipv6_del = vnc_zebra_read_ipv6;
1124}
1125
1126void
1127vnc_zebra_destroy (void)
1128{
1129 if (zclient_vnc == NULL)
1130 return;
1131 zclient_stop (zclient_vnc);
1132 zclient_free (zclient_vnc);
1133 zclient_vnc = NULL;
1134}