]> git.proxmox.com Git - mirror_frr.git/blob - ripngd/ripng_zebra.c
*: Track vrfs per nexthop not per route entry
[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 struct list *list = (struct list *)rp->info;
43 struct zapi_route api;
44 struct zapi_nexthop *api_nh;
45 struct listnode *listnode = NULL;
46 struct ripng_info *rinfo = NULL;
47 int count = 0;
48
49 memset(&api, 0, sizeof(api));
50 api.vrf_id = VRF_DEFAULT;
51 api.type = ZEBRA_ROUTE_RIPNG;
52 api.safi = SAFI_UNICAST;
53 api.prefix = rp->p;
54
55 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
56 for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
57 if (count >= MULTIPATH_NUM)
58 break;
59 api_nh = &api.nexthops[count];
60 api_nh->vrf_id = VRF_DEFAULT;
61 api_nh->gate.ipv6 = rinfo->nexthop;
62 api_nh->ifindex = rinfo->ifindex;
63 api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
64 count++;
65 if (cmd == ZEBRA_ROUTE_ADD)
66 SET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
67 else
68 UNSET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
69 }
70
71 api.nexthop_num = count;
72
73 rinfo = listgetdata(listhead(list));
74
75 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
76 api.metric = rinfo->metric;
77
78 if (rinfo->tag) {
79 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
80 api.tag = rinfo->tag;
81 }
82
83 zclient_route_send(cmd, zclient, &api);
84
85 if (IS_RIPNG_DEBUG_ZEBRA) {
86 if (ripng->ecmp)
87 zlog_debug("%s: %s/%d nexthops %d",
88 (cmd == ZEBRA_ROUTE_ADD)
89 ? "Install into zebra"
90 : "Delete from zebra",
91 inet6_ntoa(rp->p.u.prefix6), rp->p.prefixlen,
92 count);
93 else
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);
99 }
100 }
101
102 /* Add/update ECMP routes to zebra. */
103 void ripng_zebra_ipv6_add(struct route_node *rp)
104 {
105 ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_ADD);
106 }
107
108 /* Delete ECMP routes from zebra. */
109 void ripng_zebra_ipv6_delete(struct route_node *rp)
110 {
111 ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_DELETE);
112 }
113
114 /* Zebra route add and delete treatment. */
115 static int ripng_zebra_read_route(int command, struct zclient *zclient,
116 zebra_size_t length, vrf_id_t vrf_id)
117 {
118 struct zapi_route api;
119 struct in6_addr nexthop;
120 unsigned long ifindex;
121
122 if (zapi_route_decode(zclient->ibuf, &api) < 0)
123 return -1;
124
125 /* we completely ignore srcdest routes for now. */
126 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
127 return 0;
128
129 nexthop = api.nexthops[0].gate.ipv6;
130 ifindex = api.nexthops[0].ifindex;
131
132 if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
133 ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE,
134 (struct prefix_ipv6 *)&api.prefix,
135 ifindex, &nexthop, api.tag);
136 else
137 ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE,
138 (struct prefix_ipv6 *)&api.prefix,
139 ifindex);
140
141 return 0;
142 }
143
144 void ripng_zclient_reset(void)
145 {
146 zclient_reset(zclient);
147 }
148
149 static int ripng_redistribute_unset(int type)
150 {
151
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);
156
157 if (zclient->sock > 0)
158 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
159 AFI_IP6, type, 0, VRF_DEFAULT);
160
161 ripng_redistribute_withdraw(type);
162
163 return CMD_SUCCESS;
164 }
165
166 int ripng_redistribute_check(int type)
167 {
168 return vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT);
169 }
170
171 static void ripng_redistribute_metric_set(int type, int metric)
172 {
173 ripng->route_map[type].metric_config = 1;
174 ripng->route_map[type].metric = metric;
175 }
176
177 static int ripng_redistribute_metric_unset(int type)
178 {
179 ripng->route_map[type].metric_config = 0;
180 ripng->route_map[type].metric = 0;
181 return 0;
182 }
183
184 static void ripng_redistribute_routemap_set(int type, const char *name)
185 {
186 if (ripng->route_map[type].name)
187 free(ripng->route_map[type].name);
188
189 ripng->route_map[type].name = strdup(name);
190 ripng->route_map[type].map = route_map_lookup_by_name(name);
191 }
192
193 static void ripng_redistribute_routemap_unset(int type)
194 {
195 if (ripng->route_map[type].name)
196 free(ripng->route_map[type].name);
197
198 ripng->route_map[type].name = NULL;
199 ripng->route_map[type].map = NULL;
200 }
201
202 /* Redistribution types */
203 static struct {
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()
216 {
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 }
237 }
238
239 DEFUN (ripng_redistribute_type,
240 ripng_redistribute_type_cmd,
241 "redistribute " FRR_REDIST_STR_RIPNGD,
242 "Redistribute\n"
243 FRR_REDIST_HELP_STR_RIPNGD)
244 {
245 int type;
246
247 char *proto = argv[argc - 1]->text;
248 type = proto_redistnum(AFI_IP6, proto);
249
250 if (type < 0) {
251 vty_out(vty, "Invalid type %s\n", proto);
252 return CMD_WARNING_CONFIG_FAILED;
253 }
254
255 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
256 VRF_DEFAULT);
257 return CMD_SUCCESS;
258 }
259
260 DEFUN (no_ripng_redistribute_type,
261 no_ripng_redistribute_type_cmd,
262 "no redistribute " FRR_REDIST_STR_RIPNGD " [metric (0-16)] [route-map WORD]",
263 NO_STR
264 "Redistribute\n"
265 FRR_REDIST_HELP_STR_RIPNGD
266 "Metric\n"
267 "Metric value\n"
268 "Route map reference\n"
269 "Pointer to route-map entries\n")
270 {
271 int type;
272
273 char *proto = argv[2]->text;
274 type = proto_redistnum(AFI_IP6, proto);
275
276 if (type < 0) {
277 vty_out(vty, "Invalid type %s\n", proto);
278 return CMD_WARNING_CONFIG_FAILED;
279 }
280
281 ripng_redistribute_metric_unset(type);
282 ripng_redistribute_routemap_unset(type);
283 return ripng_redistribute_unset(type);
284 }
285
286
287 DEFUN (ripng_redistribute_type_metric,
288 ripng_redistribute_type_metric_cmd,
289 "redistribute " FRR_REDIST_STR_RIPNGD " metric (0-16)",
290 "Redistribute\n"
291 FRR_REDIST_HELP_STR_RIPNGD
292 "Metric\n"
293 "Metric value\n")
294 {
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;
312 }
313
314 DEFUN (ripng_redistribute_type_routemap,
315 ripng_redistribute_type_routemap_cmd,
316 "redistribute " FRR_REDIST_STR_RIPNGD " route-map WORD",
317 "Redistribute\n"
318 FRR_REDIST_HELP_STR_RIPNGD
319 "Route map reference\n"
320 "Pointer to route-map entries\n")
321 {
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;
337 }
338
339 DEFUN (ripng_redistribute_type_metric_routemap,
340 ripng_redistribute_type_metric_routemap_cmd,
341 "redistribute " FRR_REDIST_STR_RIPNGD " metric (0-16) route-map WORD",
342 "Redistribute\n"
343 FRR_REDIST_HELP_STR_RIPNGD
344 "Metric\n"
345 "Metric value\n"
346 "Route map reference\n"
347 "Pointer to route-map entries\n")
348 {
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;
368 }
369
370 void ripng_redistribute_write(struct vty *vty, int config_mode)
371 {
372 int i;
373
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;
383 }
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 }
406 }
407
408 static void ripng_zebra_connected(struct zclient *zclient)
409 {
410 zclient_send_reg_requests(zclient, VRF_DEFAULT);
411 }
412
413 /* Initialize zebra structure and it's commands. */
414 void zebra_init(struct thread_master *master)
415 {
416 /* Allocate zebra structure. */
417 zclient = zclient_new_notify(master, &zclient_options_default);
418 zclient_init(zclient, ZEBRA_ROUTE_RIPNG, 0, &ripngd_privs);
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;
427 zclient->redistribute_route_add = ripng_zebra_read_route;
428 zclient->redistribute_route_del = ripng_zebra_read_route;
429
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);
437 }
438
439 void ripng_zebra_stop(void)
440 {
441 zclient_stop(zclient);
442 zclient_free(zclient);
443 }