]> git.proxmox.com Git - mirror_frr.git/blame - ripngd/ripng_zebra.c
ripngd: retrofit the 'router ripng' command to the new northbound model
[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"
fe08ba7e 26#include "agg_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. */
fe08ba7e 40static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd)
718e3744 41{
d62a17ae 42 struct list *list = (struct list *)rp->info;
c9fb3e23
RW
43 struct zapi_route api;
44 struct zapi_nexthop *api_nh;
d62a17ae 45 struct listnode *listnode = NULL;
46 struct ripng_info *rinfo = NULL;
47 int count = 0;
48
c9fb3e23 49 memset(&api, 0, sizeof(api));
d00061ea
RW
50 api.vrf_id = VRF_DEFAULT;
51 api.type = ZEBRA_ROUTE_RIPNG;
d00061ea 52 api.safi = SAFI_UNICAST;
c9fb3e23 53 api.prefix = rp->p;
d62a17ae 54
d00061ea 55 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
d00061ea 56 for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
a74e593b
RW
57 if (count >= MULTIPATH_NUM)
58 break;
c9fb3e23 59 api_nh = &api.nexthops[count];
4a7371e9 60 api_nh->vrf_id = VRF_DEFAULT;
c9fb3e23
RW
61 api_nh->gate.ipv6 = rinfo->nexthop;
62 api_nh->ifindex = rinfo->ifindex;
63 api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
d00061ea 64 count++;
c9fb3e23 65 if (cmd == ZEBRA_ROUTE_ADD)
d00061ea
RW
66 SET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
67 else
68 UNSET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
69 }
d62a17ae 70
d00061ea 71 api.nexthop_num = count;
d62a17ae 72
d00061ea 73 rinfo = listgetdata(listhead(list));
d62a17ae 74
d00061ea
RW
75 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
76 api.metric = rinfo->metric;
d62a17ae 77
d00061ea
RW
78 if (rinfo->tag) {
79 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
80 api.tag = rinfo->tag;
81 }
d62a17ae 82
c9fb3e23 83 zclient_route_send(cmd, zclient, &api);
d00061ea
RW
84
85 if (IS_RIPNG_DEBUG_ZEBRA) {
86 if (ripng->ecmp)
87 zlog_debug("%s: %s/%d nexthops %d",
c9fb3e23 88 (cmd == ZEBRA_ROUTE_ADD)
d00061ea
RW
89 ? "Install into zebra"
90 : "Delete from zebra",
91 inet6_ntoa(rp->p.u.prefix6), rp->p.prefixlen,
92 count);
93 else
c9fb3e23
RW
94 zlog_debug(
95 "%s: %s/%d",
96 (cmd == ZEBRA_ROUTE_ADD) ? "Install into zebra"
97 : "Delete from zebra",
98 inet6_ntoa(rp->p.u.prefix6), rp->p.prefixlen);
d62a17ae 99 }
718e3744 100}
101
c880b636 102/* Add/update ECMP routes to zebra. */
fe08ba7e 103void ripng_zebra_ipv6_add(struct agg_node *rp)
718e3744 104{
c9fb3e23 105 ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_ADD);
c880b636 106}
718e3744 107
c880b636 108/* Delete ECMP routes from zebra. */
fe08ba7e 109void ripng_zebra_ipv6_delete(struct agg_node *rp)
c880b636 110{
c9fb3e23 111 ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_DELETE);
718e3744 112}
113
114/* Zebra route add and delete treatment. */
74489921
RW
115static int ripng_zebra_read_route(int command, struct zclient *zclient,
116 zebra_size_t length, vrf_id_t vrf_id)
718e3744 117{
74489921 118 struct zapi_route api;
d62a17ae 119 struct in6_addr nexthop;
74489921 120 unsigned long ifindex;
d62a17ae 121
74489921
RW
122 if (zapi_route_decode(zclient->ibuf, &api) < 0)
123 return -1;
d62a17ae 124
74489921
RW
125 /* we completely ignore srcdest routes for now. */
126 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
127 return 0;
d62a17ae 128
74489921
RW
129 nexthop = api.nexthops[0].gate.ipv6;
130 ifindex = api.nexthops[0].ifindex;
d62a17ae 131
74489921
RW
132 if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
133 ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE,
134 (struct prefix_ipv6 *)&api.prefix,
d62a17ae 135 ifindex, &nexthop, api.tag);
136 else
137 ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE,
74489921
RW
138 (struct prefix_ipv6 *)&api.prefix,
139 ifindex);
d62a17ae 140
141 return 0;
718e3744 142}
143
d62a17ae 144void ripng_zclient_reset(void)
a94434b6 145{
d62a17ae 146 zclient_reset(zclient);
a94434b6 147}
148
d62a17ae 149static int ripng_redistribute_unset(int type)
718e3744 150{
7076bb2f 151
d62a17ae 152 if (!vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT))
153 return CMD_SUCCESS;
154
155 vrf_bitmap_set(zclient->redist[AFI_IP6][type], VRF_DEFAULT);
718e3744 156
d62a17ae 157 if (zclient->sock > 0)
158 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
159 AFI_IP6, type, 0, VRF_DEFAULT);
718e3744 160
d62a17ae 161 ripng_redistribute_withdraw(type);
718e3744 162
d62a17ae 163 return CMD_SUCCESS;
718e3744 164}
165
d62a17ae 166int ripng_redistribute_check(int type)
a94434b6 167{
d62a17ae 168 return vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT);
a94434b6 169}
170
d62a17ae 171static void ripng_redistribute_metric_set(int type, int metric)
718e3744 172{
d62a17ae 173 ripng->route_map[type].metric_config = 1;
174 ripng->route_map[type].metric = metric;
718e3744 175}
176
d62a17ae 177static int ripng_redistribute_metric_unset(int type)
718e3744 178{
d62a17ae 179 ripng->route_map[type].metric_config = 0;
180 ripng->route_map[type].metric = 0;
181 return 0;
718e3744 182}
183
d62a17ae 184static void ripng_redistribute_routemap_set(int type, const char *name)
718e3744 185{
d62a17ae 186 if (ripng->route_map[type].name)
187 free(ripng->route_map[type].name);
718e3744 188
d62a17ae 189 ripng->route_map[type].name = strdup(name);
190 ripng->route_map[type].map = route_map_lookup_by_name(name);
718e3744 191}
192
d62a17ae 193static void ripng_redistribute_routemap_unset(int type)
718e3744 194{
d62a17ae 195 if (ripng->route_map[type].name)
196 free(ripng->route_map[type].name);
718e3744 197
d62a17ae 198 ripng->route_map[type].name = NULL;
199 ripng->route_map[type].map = NULL;
718e3744 200}
6b0655a2 201
a94434b6 202/* Redistribution types */
203static struct {
d62a17ae 204 int type;
205 int str_min_len;
206 const char *str;
207} redist_type[] = {{ZEBRA_ROUTE_KERNEL, 1, "kernel"},
208 {ZEBRA_ROUTE_CONNECT, 1, "connected"},
209 {ZEBRA_ROUTE_STATIC, 1, "static"},
210 {ZEBRA_ROUTE_OSPF6, 1, "ospf6"},
211 {ZEBRA_ROUTE_BGP, 2, "bgp"},
212 {ZEBRA_ROUTE_VNC, 1, "vnc"},
213 {0, 0, NULL}};
214
215void ripng_redistribute_clean()
a94434b6 216{
d62a17ae 217 int i;
218
219 for (i = 0; redist_type[i].str; i++) {
220 if (vrf_bitmap_check(
221 zclient->redist[AFI_IP6][redist_type[i].type],
222 VRF_DEFAULT)) {
223 if (zclient->sock > 0)
224 zebra_redistribute_send(
225 ZEBRA_REDISTRIBUTE_DELETE, zclient,
226 AFI_IP6, redist_type[i].type, 0,
227 VRF_DEFAULT);
228
229 vrf_bitmap_unset(
230 zclient->redist[AFI_IP6][redist_type[i].type],
231 VRF_DEFAULT);
232
233 /* Remove the routes from RIPng table. */
234 ripng_redistribute_withdraw(redist_type[i].type);
235 }
236 }
a94434b6 237}
238
a94434b6 239DEFUN (ripng_redistribute_type,
240 ripng_redistribute_type_cmd,
40d1cbfb 241 "redistribute " FRR_REDIST_STR_RIPNGD,
93079db6 242 "Redistribute\n"
ab0181ee 243 FRR_REDIST_HELP_STR_RIPNGD)
718e3744 244{
d62a17ae 245 int type;
718e3744 246
d62a17ae 247 char *proto = argv[argc - 1]->text;
248 type = proto_redistnum(AFI_IP6, proto);
93079db6 249
d62a17ae 250 if (type < 0) {
251 vty_out(vty, "Invalid type %s\n", proto);
252 return CMD_WARNING_CONFIG_FAILED;
253 }
718e3744 254
d62a17ae 255 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
256 VRF_DEFAULT);
257 return CMD_SUCCESS;
718e3744 258}
259
a94434b6 260DEFUN (no_ripng_redistribute_type,
261 no_ripng_redistribute_type_cmd,
40d1cbfb 262 "no redistribute " FRR_REDIST_STR_RIPNGD " [metric (0-16)] [route-map WORD]",
718e3744 263 NO_STR
93079db6 264 "Redistribute\n"
3b14d86e 265 FRR_REDIST_HELP_STR_RIPNGD
55c727dd
QY
266 "Metric\n"
267 "Metric value\n"
268 "Route map reference\n"
269 "Pointer to route-map entries\n")
718e3744 270{
d62a17ae 271 int type;
6d681bd8 272
d62a17ae 273 char *proto = argv[2]->text;
274 type = proto_redistnum(AFI_IP6, proto);
93079db6 275
d62a17ae 276 if (type < 0) {
277 vty_out(vty, "Invalid type %s\n", proto);
278 return CMD_WARNING_CONFIG_FAILED;
279 }
718e3744 280
d62a17ae 281 ripng_redistribute_metric_unset(type);
282 ripng_redistribute_routemap_unset(type);
283 return ripng_redistribute_unset(type);
718e3744 284}
285
718e3744 286
a94434b6 287DEFUN (ripng_redistribute_type_metric,
288 ripng_redistribute_type_metric_cmd,
40d1cbfb 289 "redistribute " FRR_REDIST_STR_RIPNGD " metric (0-16)",
93079db6 290 "Redistribute\n"
ab0181ee 291 FRR_REDIST_HELP_STR_RIPNGD
718e3744 292 "Metric\n"
293 "Metric value\n")
294{
d62a17ae 295 int idx_protocol = 1;
296 int idx_number = 3;
297 int type;
298 int metric;
299
300 metric = atoi(argv[idx_number]->arg);
301 type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
302
303 if (type < 0) {
304 vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
305 return CMD_WARNING_CONFIG_FAILED;
306 }
307
308 ripng_redistribute_metric_set(type, metric);
309 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
310 VRF_DEFAULT);
311 return CMD_SUCCESS;
718e3744 312}
313
a94434b6 314DEFUN (ripng_redistribute_type_routemap,
315 ripng_redistribute_type_routemap_cmd,
40d1cbfb 316 "redistribute " FRR_REDIST_STR_RIPNGD " route-map WORD",
93079db6 317 "Redistribute\n"
ab0181ee 318 FRR_REDIST_HELP_STR_RIPNGD
718e3744 319 "Route map reference\n"
320 "Pointer to route-map entries\n")
321{
d62a17ae 322 int idx_protocol = 1;
323 int idx_word = 3;
324 int type;
325
326 type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
327
328 if (type < 0) {
329 vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
330 return CMD_WARNING_CONFIG_FAILED;
331 }
332
333 ripng_redistribute_routemap_set(type, argv[idx_word]->text);
334 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
335 VRF_DEFAULT);
336 return CMD_SUCCESS;
718e3744 337}
338
a94434b6 339DEFUN (ripng_redistribute_type_metric_routemap,
340 ripng_redistribute_type_metric_routemap_cmd,
40d1cbfb 341 "redistribute " FRR_REDIST_STR_RIPNGD " metric (0-16) route-map WORD",
93079db6 342 "Redistribute\n"
ab0181ee 343 FRR_REDIST_HELP_STR_RIPNGD
718e3744 344 "Metric\n"
345 "Metric value\n"
346 "Route map reference\n"
347 "Pointer to route-map entries\n")
348{
d62a17ae 349 int idx_protocol = 1;
350 int idx_number = 3;
351 int idx_word = 5;
352 int type;
353 int metric;
354
355 type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
356 metric = atoi(argv[idx_number]->arg);
357
358 if (type < 0) {
359 vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
360 return CMD_WARNING_CONFIG_FAILED;
361 }
362
363 ripng_redistribute_metric_set(type, metric);
364 ripng_redistribute_routemap_set(type, argv[idx_word]->text);
365 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
366 VRF_DEFAULT);
367 return CMD_SUCCESS;
718e3744 368}
369
d62a17ae 370void ripng_redistribute_write(struct vty *vty, int config_mode)
718e3744 371{
d62a17ae 372 int i;
373
d00061ea
RW
374 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
375 if (i == zclient->redist_default
376 || !vrf_bitmap_check(zclient->redist[AFI_IP6][i],
377 VRF_DEFAULT))
378 continue;
379
380 if (!config_mode) {
381 vty_out(vty, " %s", zebra_route_string(i));
382 continue;
d62a17ae 383 }
d00061ea
RW
384
385 if (ripng->route_map[i].metric_config) {
386 if (ripng->route_map[i].name)
387 vty_out(vty,
388 " redistribute %s metric %d route-map %s\n",
389 zebra_route_string(i),
390 ripng->route_map[i].metric,
391 ripng->route_map[i].name);
392 else
393 vty_out(vty, " redistribute %s metric %d\n",
394 zebra_route_string(i),
395 ripng->route_map[i].metric);
396 } else {
397 if (ripng->route_map[i].name)
398 vty_out(vty, " redistribute %s route-map %s\n",
399 zebra_route_string(i),
400 ripng->route_map[i].name);
401 else
402 vty_out(vty, " redistribute %s\n",
403 zebra_route_string(i));
404 }
405 }
718e3744 406}
407
d62a17ae 408static void ripng_zebra_connected(struct zclient *zclient)
7076bb2f 409{
d62a17ae 410 zclient_send_reg_requests(zclient, VRF_DEFAULT);
7076bb2f
FL
411}
412
718e3744 413/* Initialize zebra structure and it's commands. */
d62a17ae 414void zebra_init(struct thread_master *master)
718e3744 415{
d62a17ae 416 /* Allocate zebra structure. */
26f63a1e 417 zclient = zclient_new(master, &zclient_options_default);
342213ea 418 zclient_init(zclient, ZEBRA_ROUTE_RIPNG, 0, &ripngd_privs);
d62a17ae 419
420 zclient->zebra_connected = ripng_zebra_connected;
421 zclient->interface_up = ripng_interface_up;
422 zclient->interface_down = ripng_interface_down;
423 zclient->interface_add = ripng_interface_add;
424 zclient->interface_delete = ripng_interface_delete;
425 zclient->interface_address_add = ripng_interface_address_add;
426 zclient->interface_address_delete = ripng_interface_address_delete;
74489921
RW
427 zclient->redistribute_route_add = ripng_zebra_read_route;
428 zclient->redistribute_route_del = ripng_zebra_read_route;
d62a17ae 429
d62a17ae 430 /* Install command elements to ripng node */
431 install_element(RIPNG_NODE, &ripng_redistribute_type_cmd);
432 install_element(RIPNG_NODE, &ripng_redistribute_type_routemap_cmd);
433 install_element(RIPNG_NODE, &ripng_redistribute_type_metric_cmd);
434 install_element(RIPNG_NODE,
435 &ripng_redistribute_type_metric_routemap_cmd);
436 install_element(RIPNG_NODE, &no_ripng_redistribute_type_cmd);
718e3744 437}
7feb9237 438
d62a17ae 439void ripng_zebra_stop(void)
7feb9237 440{
d62a17ae 441 zclient_stop(zclient);
442 zclient_free(zclient);
7feb9237 443}