]> git.proxmox.com Git - mirror_frr.git/blob - ripngd/ripng_zebra.c
bgpd: add L3/L2VPN Virtual Network Control feature
[mirror_frr.git] / ripngd / ripng_zebra.c
1 /*
2 * RIPngd and zebra interface.
3 * Copyright (C) 1998, 1999 Kunihiro Ishiguro
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23 #include <zebra.h>
24
25 #include "command.h"
26 #include "prefix.h"
27 #include "table.h"
28 #include "stream.h"
29 #include "memory.h"
30 #include "routemap.h"
31 #include "zclient.h"
32 #include "log.h"
33
34 #include "ripngd/ripngd.h"
35 #include "ripngd/ripng_debug.h"
36
37 /* All information about zebra. */
38 struct zclient *zclient = NULL;
39
40 /* Send ECMP routes to zebra. */
41 static void
42 ripng_zebra_ipv6_send (struct route_node *rp, u_char cmd)
43 {
44 static struct in6_addr **nexthops = NULL;
45 static ifindex_t *ifindexes = NULL;
46 static unsigned int nexthops_len = 0;
47
48 struct list *list = (struct list *)rp->info;
49 struct zapi_ipv6 api;
50 struct listnode *listnode = NULL;
51 struct ripng_info *rinfo = NULL;
52 int count = 0;
53
54 if (vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], VRF_DEFAULT))
55 {
56 api.vrf_id = VRF_DEFAULT;
57 api.type = ZEBRA_ROUTE_RIPNG;
58 api.instance = 0;
59 api.flags = 0;
60 api.message = 0;
61 api.safi = SAFI_UNICAST;
62
63 if (nexthops_len < listcount (list))
64 {
65 nexthops_len = listcount (list);
66 nexthops = XREALLOC (MTYPE_TMP, nexthops,
67 nexthops_len * sizeof (struct in6_addr *));
68 ifindexes = XREALLOC (MTYPE_TMP, ifindexes,
69 nexthops_len * sizeof (unsigned int));
70 }
71
72 SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
73 SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
74 for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
75 {
76 nexthops[count] = &rinfo->nexthop;
77 ifindexes[count] = rinfo->ifindex;
78 count++;
79 if (cmd == ZEBRA_IPV6_ROUTE_ADD)
80 SET_FLAG (rinfo->flags, RIPNG_RTF_FIB);
81 else
82 UNSET_FLAG (rinfo->flags, RIPNG_RTF_FIB);
83 }
84
85 api.nexthop = nexthops;
86 api.nexthop_num = count;
87 api.ifindex = ifindexes;
88 api.ifindex_num = count;
89
90 rinfo = listgetdata (listhead (list));
91
92 SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
93 api.metric = rinfo->metric;
94
95 zapi_ipv6_route (cmd, zclient,
96 (struct prefix_ipv6 *)&rp->p, &api);
97
98 if (IS_RIPNG_DEBUG_ZEBRA)
99 {
100 if (ripng->ecmp)
101 zlog_debug ("%s: %s/%d nexthops %d",
102 (cmd == ZEBRA_IPV6_ROUTE_ADD) ? \
103 "Install into zebra" : "Delete from zebra",
104 inet6_ntoa (rp->p.u.prefix6), rp->p.prefixlen, count);
105 else
106 zlog_debug ("%s: %s/%d",
107 (cmd == ZEBRA_IPV6_ROUTE_ADD) ? \
108 "Install into zebra" : "Delete from zebra",
109 inet6_ntoa (rp->p.u.prefix6), rp->p.prefixlen);
110 }
111 }
112 }
113
114 /* Add/update ECMP routes to zebra. */
115 void
116 ripng_zebra_ipv6_add (struct route_node *rp)
117 {
118 ripng_zebra_ipv6_send (rp, ZEBRA_IPV6_ROUTE_ADD);
119 }
120
121 /* Delete ECMP routes from zebra. */
122 void
123 ripng_zebra_ipv6_delete (struct route_node *rp)
124 {
125 ripng_zebra_ipv6_send (rp, ZEBRA_IPV6_ROUTE_DELETE);
126 }
127
128 /* Zebra route add and delete treatment. */
129 static int
130 ripng_zebra_read_ipv6 (int command, struct zclient *zclient,
131 zebra_size_t length, vrf_id_t vrf_id)
132 {
133 struct stream *s;
134 struct zapi_ipv6 api;
135 unsigned long ifindex;
136 struct in6_addr nexthop;
137 struct prefix_ipv6 p;
138
139 s = zclient->ibuf;
140 ifindex = 0;
141 memset (&nexthop, 0, sizeof (struct in6_addr));
142
143 /* Type, flags, message. */
144 api.type = stream_getc (s);
145 api.instance = stream_getw (s);
146 api.flags = stream_getl (s);
147 api.message = stream_getc (s);
148
149 /* IPv6 prefix. */
150 memset (&p, 0, sizeof (struct prefix_ipv6));
151 p.family = AF_INET6;
152 p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc (s));
153 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
154
155 /* Nexthop, ifindex, distance, metric. */
156 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
157 {
158 api.nexthop_num = stream_getc (s);
159 stream_get (&nexthop, s, 16);
160 }
161 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
162 {
163 api.ifindex_num = stream_getc (s);
164 ifindex = stream_getl (s);
165 }
166 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
167 api.distance = stream_getc (s);
168 else
169 api.distance = 0;
170 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
171 api.metric = stream_getl (s);
172 else
173 api.metric = 0;
174
175 if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
176 ripng_redistribute_add (api.type, RIPNG_ROUTE_REDISTRIBUTE, &p, ifindex, &nexthop);
177 else
178 ripng_redistribute_delete (api.type, RIPNG_ROUTE_REDISTRIBUTE, &p, ifindex);
179
180 return 0;
181 }
182
183 void
184 ripng_zclient_reset (void)
185 {
186 zclient_reset (zclient);
187 }
188
189 static int
190 ripng_redistribute_unset (int type)
191 {
192
193 if (! vrf_bitmap_check (zclient->redist[AFI_IP6][type], VRF_DEFAULT))
194 return CMD_SUCCESS;
195
196 vrf_bitmap_set (zclient->redist[AFI_IP6][type], VRF_DEFAULT);
197
198 if (zclient->sock > 0)
199 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP6, type, 0, VRF_DEFAULT);
200
201 ripng_redistribute_withdraw (type);
202
203 return CMD_SUCCESS;
204 }
205
206 int
207 ripng_redistribute_check (int type)
208 {
209 return vrf_bitmap_check (zclient->redist[AFI_IP6][type], VRF_DEFAULT);
210 }
211
212 static void
213 ripng_redistribute_metric_set (int type, int metric)
214 {
215 ripng->route_map[type].metric_config = 1;
216 ripng->route_map[type].metric = metric;
217 }
218
219 static int
220 ripng_redistribute_metric_unset (int type)
221 {
222 ripng->route_map[type].metric_config = 0;
223 ripng->route_map[type].metric = 0;
224 return 0;
225 }
226
227 static void
228 ripng_redistribute_routemap_set (int type, const char *name)
229 {
230 if (ripng->route_map[type].name)
231 free (ripng->route_map[type].name);
232
233 ripng->route_map[type].name = strdup (name);
234 ripng->route_map[type].map = route_map_lookup_by_name (name);
235 }
236
237 static void
238 ripng_redistribute_routemap_unset (int type)
239 {
240 if (ripng->route_map[type].name)
241 free (ripng->route_map[type].name);
242
243 ripng->route_map[type].name = NULL;
244 ripng->route_map[type].map = NULL;
245 }
246
247 /* Redistribution types */
248 static struct {
249 int type;
250 int str_min_len;
251 const char *str;
252 } redist_type[] = {
253 {ZEBRA_ROUTE_KERNEL, 1, "kernel"},
254 {ZEBRA_ROUTE_CONNECT, 1, "connected"},
255 {ZEBRA_ROUTE_STATIC, 1, "static"},
256 {ZEBRA_ROUTE_OSPF6, 1, "ospf6"},
257 {ZEBRA_ROUTE_BGP, 2, "bgp"},
258 {ZEBRA_ROUTE_VNC, 1, "vnc"},
259 {0, 0, NULL}
260 };
261
262 void
263 ripng_redistribute_clean ()
264 {
265 int i;
266
267 for (i = 0; redist_type[i].str; i++)
268 {
269 if (vrf_bitmap_check (zclient->redist[AFI_IP6][redist_type[i].type], VRF_DEFAULT))
270 {
271 if (zclient->sock > 0)
272 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE,
273 zclient, AFI_IP6, redist_type[i].type, 0,
274 VRF_DEFAULT);
275
276 vrf_bitmap_unset (zclient->redist[AFI_IP6][redist_type[i].type], VRF_DEFAULT);
277
278 /* Remove the routes from RIPng table. */
279 ripng_redistribute_withdraw (redist_type[i].type);
280 }
281 }
282 }
283
284 DEFUN (router_zebra,
285 router_zebra_cmd,
286 "router zebra",
287 "Enable a routing process\n"
288 "Make connection to zebra daemon\n")
289 {
290 vty->node = ZEBRA_NODE;
291 zclient->enable = 1;
292 zclient_start (zclient);
293 return CMD_SUCCESS;
294 }
295
296 DEFUN (no_router_zebra,
297 no_router_zebra_cmd,
298 "no router zebra",
299 NO_STR
300 "Disable a routing process\n"
301 "Stop connection to zebra daemon\n")
302 {
303 zclient->enable = 0;
304 zclient_stop (zclient);
305 return CMD_SUCCESS;
306 }
307
308 DEFUN (ripng_redistribute_ripng,
309 ripng_redistribute_ripng_cmd,
310 "redistribute ripng",
311 "Redistribute information from another routing protocol\n"
312 "RIPng route\n")
313 {
314 vrf_bitmap_set (zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], VRF_DEFAULT);
315 return CMD_SUCCESS;
316 }
317
318 DEFUN (no_ripng_redistribute_ripng,
319 no_ripng_redistribute_ripng_cmd,
320 "no redistribute ripng",
321 NO_STR
322 "Redistribute information from another routing protocol\n"
323 "RIPng route\n")
324 {
325 vrf_bitmap_unset (zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], VRF_DEFAULT);
326 return CMD_SUCCESS;
327 }
328
329 DEFUN (ripng_redistribute_type,
330 ripng_redistribute_type_cmd,
331 "redistribute " QUAGGA_REDIST_STR_RIPNGD,
332 "Redistribute\n"
333 QUAGGA_REDIST_HELP_STR_RIPNGD)
334 {
335 int type;
336
337 type = proto_redistnum(AFI_IP6, argv[0]);
338
339 if (type < 0)
340 {
341 vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
342 return CMD_WARNING;
343 }
344
345 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0, VRF_DEFAULT);
346 return CMD_SUCCESS;
347 }
348
349 DEFUN (no_ripng_redistribute_type,
350 no_ripng_redistribute_type_cmd,
351 "no redistribute " QUAGGA_REDIST_STR_RIPNGD,
352 NO_STR
353 "Redistribute\n"
354 QUAGGA_REDIST_HELP_STR_RIPNGD)
355 {
356 int type;
357
358 type = proto_redistnum(AFI_IP6, argv[0]);
359
360 if (type < 0)
361 {
362 vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
363 return CMD_WARNING;
364 }
365
366 ripng_redistribute_metric_unset (type);
367 ripng_redistribute_routemap_unset (type);
368 return ripng_redistribute_unset (type);
369 }
370
371
372 DEFUN (ripng_redistribute_type_metric,
373 ripng_redistribute_type_metric_cmd,
374 "redistribute " QUAGGA_REDIST_STR_RIPNGD " metric <0-16>",
375 "Redistribute\n"
376 QUAGGA_REDIST_HELP_STR_RIPNGD
377 "Metric\n"
378 "Metric value\n")
379 {
380 int type;
381 int metric;
382
383 metric = atoi (argv[1]);
384 type = proto_redistnum(AFI_IP6, argv[0]);
385
386 if (type < 0)
387 {
388 vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
389 return CMD_WARNING;
390 }
391
392 ripng_redistribute_metric_set (type, metric);
393 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
394 VRF_DEFAULT);
395 return CMD_SUCCESS;
396 }
397
398 ALIAS (no_ripng_redistribute_type,
399 no_ripng_redistribute_type_metric_cmd,
400 "no redistribute " QUAGGA_REDIST_STR_RIPNGD " metric <0-16>",
401 NO_STR
402 "Redistribute\n"
403 QUAGGA_REDIST_HELP_STR_RIPNGD
404 "Metric\n"
405 "Metric value\n")
406
407 DEFUN (ripng_redistribute_type_routemap,
408 ripng_redistribute_type_routemap_cmd,
409 "redistribute " QUAGGA_REDIST_STR_RIPNGD " route-map WORD",
410 "Redistribute\n"
411 QUAGGA_REDIST_HELP_STR_RIPNGD
412 "Route map reference\n"
413 "Pointer to route-map entries\n")
414 {
415 int type;
416
417 type = proto_redistnum(AFI_IP6, argv[0]);
418
419 if (type < 0)
420 {
421 vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
422 return CMD_WARNING;
423 }
424
425 ripng_redistribute_routemap_set (type, argv[1]);
426 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
427 VRF_DEFAULT);
428 return CMD_SUCCESS;
429 }
430
431 ALIAS (no_ripng_redistribute_type,
432 no_ripng_redistribute_type_routemap_cmd,
433 "no redistribute " QUAGGA_REDIST_STR_RIPNGD " route-map WORD",
434 NO_STR
435 "Redistribute\n"
436 QUAGGA_REDIST_HELP_STR_RIPNGD
437 "Route map reference\n"
438 "Pointer to route-map entries\n")
439
440 DEFUN (ripng_redistribute_type_metric_routemap,
441 ripng_redistribute_type_metric_routemap_cmd,
442 "redistribute " QUAGGA_REDIST_STR_RIPNGD " metric <0-16> route-map WORD",
443 "Redistribute\n"
444 QUAGGA_REDIST_HELP_STR_RIPNGD
445 "Metric\n"
446 "Metric value\n"
447 "Route map reference\n"
448 "Pointer to route-map entries\n")
449 {
450 int type;
451 int metric;
452
453 type = proto_redistnum(AFI_IP6, argv[0]);
454 metric = atoi (argv[1]);
455
456 if (type < 0)
457 {
458 vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
459 return CMD_WARNING;
460 }
461
462 ripng_redistribute_metric_set (type, metric);
463 ripng_redistribute_routemap_set (type, argv[2]);
464 zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0, VRF_DEFAULT);
465 return CMD_SUCCESS;
466 }
467
468 ALIAS (no_ripng_redistribute_type,
469 no_ripng_redistribute_type_metric_routemap_cmd,
470 "no redistribute " QUAGGA_REDIST_STR_RIPNGD " metric <0-16> route-map WORD",
471 NO_STR
472 "Redistribute\n"
473 QUAGGA_REDIST_HELP_STR_RIPNGD
474 "Route map reference\n"
475 "Pointer to route-map entries\n")
476
477 void
478 ripng_redistribute_write (struct vty *vty, int config_mode)
479 {
480 int i;
481
482 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
483 if (i != zclient->redist_default &&
484 vrf_bitmap_check (zclient->redist[AFI_IP6][i], VRF_DEFAULT))
485 {
486 if (config_mode)
487 {
488 if (ripng->route_map[i].metric_config)
489 {
490 if (ripng->route_map[i].name)
491 vty_out (vty, " redistribute %s metric %d route-map %s%s",
492 zebra_route_string(i), ripng->route_map[i].metric,
493 ripng->route_map[i].name, VTY_NEWLINE);
494 else
495 vty_out (vty, " redistribute %s metric %d%s",
496 zebra_route_string(i), ripng->route_map[i].metric,
497 VTY_NEWLINE);
498 }
499 else
500 {
501 if (ripng->route_map[i].name)
502 vty_out (vty, " redistribute %s route-map %s%s",
503 zebra_route_string(i), ripng->route_map[i].name,
504 VTY_NEWLINE);
505 else
506 vty_out (vty, " redistribute %s%s", zebra_route_string(i),
507 VTY_NEWLINE);
508 }
509 }
510 else
511 vty_out (vty, " %s", zebra_route_string(i));
512 }
513 }
514
515 /* RIPng configuration write function. */
516 static int
517 zebra_config_write (struct vty *vty)
518 {
519 if (! zclient->enable)
520 {
521 vty_out (vty, "no router zebra%s", VTY_NEWLINE);
522 return 1;
523 }
524 else if (! vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], VRF_DEFAULT))
525 {
526 vty_out (vty, "router zebra%s", VTY_NEWLINE);
527 vty_out (vty, " no redistribute ripng%s", VTY_NEWLINE);
528 return 1;
529 }
530 return 0;
531 }
532
533 /* Zebra node structure. */
534 static struct cmd_node zebra_node =
535 {
536 ZEBRA_NODE,
537 "%s(config-router)# ",
538 };
539
540 static void
541 ripng_zebra_connected (struct zclient *zclient)
542 {
543 zclient_send_reg_requests (zclient, VRF_DEFAULT);
544 }
545
546 /* Initialize zebra structure and it's commands. */
547 void
548 zebra_init (struct thread_master *master)
549 {
550 /* Allocate zebra structure. */
551 zclient = zclient_new(master);
552 zclient_init (zclient, ZEBRA_ROUTE_RIPNG, 0);
553
554 zclient->zebra_connected = ripng_zebra_connected;
555 zclient->interface_up = ripng_interface_up;
556 zclient->interface_down = ripng_interface_down;
557 zclient->interface_add = ripng_interface_add;
558 zclient->interface_delete = ripng_interface_delete;
559 zclient->interface_address_add = ripng_interface_address_add;
560 zclient->interface_address_delete = ripng_interface_address_delete;
561 zclient->redistribute_route_ipv6_add = ripng_zebra_read_ipv6;
562 zclient->redistribute_route_ipv6_del = ripng_zebra_read_ipv6;
563
564 /* Install zebra node. */
565 install_node (&zebra_node, zebra_config_write);
566
567 /* Install command element for zebra node. */
568 install_element (CONFIG_NODE, &router_zebra_cmd);
569 install_element (CONFIG_NODE, &no_router_zebra_cmd);
570 install_default (ZEBRA_NODE);
571 install_element (ZEBRA_NODE, &ripng_redistribute_ripng_cmd);
572 install_element (ZEBRA_NODE, &no_ripng_redistribute_ripng_cmd);
573
574 /* Install command elements to ripng node */
575 install_element (RIPNG_NODE, &ripng_redistribute_type_cmd);
576 install_element (RIPNG_NODE, &ripng_redistribute_type_routemap_cmd);
577 install_element (RIPNG_NODE, &ripng_redistribute_type_metric_cmd);
578 install_element (RIPNG_NODE, &ripng_redistribute_type_metric_routemap_cmd);
579 install_element (RIPNG_NODE, &no_ripng_redistribute_type_cmd);
580 install_element (RIPNG_NODE, &no_ripng_redistribute_type_routemap_cmd);
581 install_element (RIPNG_NODE, &no_ripng_redistribute_type_metric_cmd);
582 install_element (RIPNG_NODE, &no_ripng_redistribute_type_metric_routemap_cmd);
583 }