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