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