]>
Commit | Line | Data |
---|---|---|
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. */ | |
37 | struct zclient *zclient = NULL; | |
38 | ||
c880b636 | 39 | /* Send ECMP routes to zebra. */ |
d7c0a89a | 40 | static void ripng_zebra_ipv6_send(struct route_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. */ |
d62a17ae | 103 | void ripng_zebra_ipv6_add(struct route_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. */ |
d62a17ae | 109 | void ripng_zebra_ipv6_delete(struct route_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 |
115 | static 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 | 144 | void ripng_zclient_reset(void) |
a94434b6 | 145 | { |
d62a17ae | 146 | zclient_reset(zclient); |
a94434b6 | 147 | } |
148 | ||
d62a17ae | 149 | static 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 | 166 | int ripng_redistribute_check(int type) |
a94434b6 | 167 | { |
d62a17ae | 168 | return vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT); |
a94434b6 | 169 | } |
170 | ||
d62a17ae | 171 | static 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 | 177 | static 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 | 184 | static 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 | 193 | static 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 */ |
203 | static 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 | ||
215 | void 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 | 239 | DEFUN (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 | 260 | DEFUN (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 | 287 | DEFUN (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 | 314 | DEFUN (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 | 339 | DEFUN (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 | 370 | void 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 | 408 | static 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 | 414 | void zebra_init(struct thread_master *master) |
718e3744 | 415 | { |
d62a17ae | 416 | /* Allocate zebra structure. */ |
e1a1880d | 417 | zclient = zclient_new_notify(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 | 439 | void ripng_zebra_stop(void) |
7feb9237 | 440 | { |
d62a17ae | 441 | zclient_stop(zclient); |
442 | zclient_free(zclient); | |
7feb9237 | 443 | } |