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