]> git.proxmox.com Git - mirror_frr.git/blame - ripngd/ripng_zebra.c
Merge pull request #908 from donaldsharp/safi
[mirror_frr.git] / ripngd / ripng_zebra.c
CommitLineData
718e3744 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 *
896014f4
DL
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
718e3744 20 */
21
22#include <zebra.h>
23
24#include "command.h"
25#include "prefix.h"
c880b636 26#include "table.h"
718e3744 27#include "stream.h"
c880b636 28#include "memory.h"
718e3744 29#include "routemap.h"
30#include "zclient.h"
31#include "log.h"
32
33#include "ripngd/ripngd.h"
c880b636 34#include "ripngd/ripng_debug.h"
718e3744 35
36/* All information about zebra. */
37struct zclient *zclient = NULL;
38
c880b636 39/* Send ECMP routes to zebra. */
d62a17ae 40static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd)
718e3744 41{
d62a17ae 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 }
718e3744 118}
119
c880b636 120/* Add/update ECMP routes to zebra. */
d62a17ae 121void ripng_zebra_ipv6_add(struct route_node *rp)
718e3744 122{
d62a17ae 123 ripng_zebra_ipv6_send(rp, ZEBRA_IPV6_ROUTE_ADD);
c880b636 124}
718e3744 125
c880b636 126/* Delete ECMP routes from zebra. */
d62a17ae 127void ripng_zebra_ipv6_delete(struct route_node *rp)
c880b636 128{
d62a17ae 129 ripng_zebra_ipv6_send(rp, ZEBRA_IPV6_ROUTE_DELETE);
718e3744 130}
131
132/* Zebra route add and delete treatment. */
d62a17ae 133static int ripng_zebra_read_ipv6(int command, struct zclient *zclient,
134 zebra_size_t length, vrf_id_t vrf_id)
718e3744 135{
d62a17ae 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;
718e3744 200}
201
d62a17ae 202void ripng_zclient_reset(void)
a94434b6 203{
d62a17ae 204 zclient_reset(zclient);
a94434b6 205}
206
d62a17ae 207static int ripng_redistribute_unset(int type)
718e3744 208{
7076bb2f 209
d62a17ae 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);
718e3744 214
d62a17ae 215 if (zclient->sock > 0)
216 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
217 AFI_IP6, type, 0, VRF_DEFAULT);
718e3744 218
d62a17ae 219 ripng_redistribute_withdraw(type);
718e3744 220
d62a17ae 221 return CMD_SUCCESS;
718e3744 222}
223
d62a17ae 224int ripng_redistribute_check(int type)
a94434b6 225{
d62a17ae 226 return vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT);
a94434b6 227}
228
d62a17ae 229static void ripng_redistribute_metric_set(int type, int metric)
718e3744 230{
d62a17ae 231 ripng->route_map[type].metric_config = 1;
232 ripng->route_map[type].metric = metric;
718e3744 233}
234
d62a17ae 235static int ripng_redistribute_metric_unset(int type)
718e3744 236{
d62a17ae 237 ripng->route_map[type].metric_config = 0;
238 ripng->route_map[type].metric = 0;
239 return 0;
718e3744 240}
241
d62a17ae 242static void ripng_redistribute_routemap_set(int type, const char *name)
718e3744 243{
d62a17ae 244 if (ripng->route_map[type].name)
245 free(ripng->route_map[type].name);
718e3744 246
d62a17ae 247 ripng->route_map[type].name = strdup(name);
248 ripng->route_map[type].map = route_map_lookup_by_name(name);
718e3744 249}
250
d62a17ae 251static void ripng_redistribute_routemap_unset(int type)
718e3744 252{
d62a17ae 253 if (ripng->route_map[type].name)
254 free(ripng->route_map[type].name);
718e3744 255
d62a17ae 256 ripng->route_map[type].name = NULL;
257 ripng->route_map[type].map = NULL;
718e3744 258}
6b0655a2 259
a94434b6 260/* Redistribution types */
261static struct {
d62a17ae 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
273void ripng_redistribute_clean()
a94434b6 274{
d62a17ae 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 }
a94434b6 295}
296
718e3744 297DEFUN (ripng_redistribute_ripng,
298 ripng_redistribute_ripng_cmd,
299 "redistribute ripng",
300 "Redistribute information from another routing protocol\n"
301 "RIPng route\n")
302{
d62a17ae 303 vrf_bitmap_set(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG],
304 VRF_DEFAULT);
305 return CMD_SUCCESS;
718e3744 306}
307
308DEFUN (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{
d62a17ae 315 vrf_bitmap_unset(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG],
316 VRF_DEFAULT);
317 return CMD_SUCCESS;
718e3744 318}
319
a94434b6 320DEFUN (ripng_redistribute_type,
321 ripng_redistribute_type_cmd,
40d1cbfb 322 "redistribute " FRR_REDIST_STR_RIPNGD,
93079db6 323 "Redistribute\n"
ab0181ee 324 FRR_REDIST_HELP_STR_RIPNGD)
718e3744 325{
d62a17ae 326 int type;
718e3744 327
d62a17ae 328 char *proto = argv[argc - 1]->text;
329 type = proto_redistnum(AFI_IP6, proto);
93079db6 330
d62a17ae 331 if (type < 0) {
332 vty_out(vty, "Invalid type %s\n", proto);
333 return CMD_WARNING_CONFIG_FAILED;
334 }
718e3744 335
d62a17ae 336 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
337 VRF_DEFAULT);
338 return CMD_SUCCESS;
718e3744 339}
340
a94434b6 341DEFUN (no_ripng_redistribute_type,
342 no_ripng_redistribute_type_cmd,
40d1cbfb 343 "no redistribute " FRR_REDIST_STR_RIPNGD " [metric (0-16)] [route-map WORD]",
718e3744 344 NO_STR
93079db6 345 "Redistribute\n"
3b14d86e 346 FRR_REDIST_HELP_STR_RIPNGD
55c727dd
QY
347 "Metric\n"
348 "Metric value\n"
349 "Route map reference\n"
350 "Pointer to route-map entries\n")
718e3744 351{
d62a17ae 352 int type;
6d681bd8 353
d62a17ae 354 char *proto = argv[2]->text;
355 type = proto_redistnum(AFI_IP6, proto);
93079db6 356
d62a17ae 357 if (type < 0) {
358 vty_out(vty, "Invalid type %s\n", proto);
359 return CMD_WARNING_CONFIG_FAILED;
360 }
718e3744 361
d62a17ae 362 ripng_redistribute_metric_unset(type);
363 ripng_redistribute_routemap_unset(type);
364 return ripng_redistribute_unset(type);
718e3744 365}
366
718e3744 367
a94434b6 368DEFUN (ripng_redistribute_type_metric,
369 ripng_redistribute_type_metric_cmd,
40d1cbfb 370 "redistribute " FRR_REDIST_STR_RIPNGD " metric (0-16)",
93079db6 371 "Redistribute\n"
ab0181ee 372 FRR_REDIST_HELP_STR_RIPNGD
718e3744 373 "Metric\n"
374 "Metric value\n")
375{
d62a17ae 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;
718e3744 393}
394
a94434b6 395DEFUN (ripng_redistribute_type_routemap,
396 ripng_redistribute_type_routemap_cmd,
40d1cbfb 397 "redistribute " FRR_REDIST_STR_RIPNGD " route-map WORD",
93079db6 398 "Redistribute\n"
ab0181ee 399 FRR_REDIST_HELP_STR_RIPNGD
718e3744 400 "Route map reference\n"
401 "Pointer to route-map entries\n")
402{
d62a17ae 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;
718e3744 418}
419
a94434b6 420DEFUN (ripng_redistribute_type_metric_routemap,
421 ripng_redistribute_type_metric_routemap_cmd,
40d1cbfb 422 "redistribute " FRR_REDIST_STR_RIPNGD " metric (0-16) route-map WORD",
93079db6 423 "Redistribute\n"
ab0181ee 424 FRR_REDIST_HELP_STR_RIPNGD
718e3744 425 "Metric\n"
426 "Metric value\n"
427 "Route map reference\n"
428 "Pointer to route-map entries\n")
429{
d62a17ae 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;
718e3744 449}
450
d62a17ae 451void ripng_redistribute_write(struct vty *vty, int config_mode)
718e3744 452{
d62a17ae 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 }
718e3744 490}
491
492/* RIPng configuration write function. */
d62a17ae 493static int zebra_config_write(struct vty *vty)
718e3744 494{
d62a17ae 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;
718e3744 506}
507
508/* Zebra node structure. */
d62a17ae 509static struct cmd_node zebra_node = {
9d303b37 510 ZEBRA_NODE, "%s(config-router)# ",
718e3744 511};
512
d62a17ae 513static void ripng_zebra_connected(struct zclient *zclient)
7076bb2f 514{
d62a17ae 515 zclient_send_reg_requests(zclient, VRF_DEFAULT);
7076bb2f
FL
516}
517
718e3744 518/* Initialize zebra structure and it's commands. */
d62a17ae 519void zebra_init(struct thread_master *master)
718e3744 520{
d62a17ae 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);
718e3744 550}
7feb9237 551
d62a17ae 552void ripng_zebra_stop(void)
7feb9237 553{
d62a17ae 554 zclient_stop(zclient);
555 zclient_free(zclient);
7feb9237 556}