]> git.proxmox.com Git - mirror_frr.git/blob - ripd/rip_zebra.c
Merge pull request #1213 from opensourcerouting/zebra-netlink
[mirror_frr.git] / ripd / rip_zebra.c
1 /* RIPd and zebra interface.
2 * Copyright (C) 1997, 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <zebra.h>
22
23 #include "command.h"
24 #include "prefix.h"
25 #include "table.h"
26 #include "stream.h"
27 #include "memory.h"
28 #include "routemap.h"
29 #include "zclient.h"
30 #include "log.h"
31 #include "vrf.h"
32 #include "ripd/ripd.h"
33 #include "ripd/rip_debug.h"
34 #include "ripd/rip_interface.h"
35
36 /* All information about zebra. */
37 struct zclient *zclient = NULL;
38
39 /* Send ECMP routes to zebra. */
40 static void rip_zebra_ipv4_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 rip_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_RIP;
52 api.safi = SAFI_UNICAST;
53
54 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
55 for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
56 if (count >= MULTIPATH_NUM)
57 break;
58 api_nh = &api.nexthops[count];
59 api_nh->gate.ipv4 = rinfo->nexthop;
60 api_nh->type = NEXTHOP_TYPE_IPV4;
61 if (cmd == ZEBRA_ROUTE_ADD)
62 SET_FLAG(rinfo->flags, RIP_RTF_FIB);
63 else
64 UNSET_FLAG(rinfo->flags, RIP_RTF_FIB);
65 count++;
66 }
67
68 api.prefix = rp->p;
69 api.nexthop_num = count;
70
71 rinfo = listgetdata(listhead(list));
72
73 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
74 api.metric = rinfo->metric;
75
76 if (rinfo->distance && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) {
77 SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
78 api.distance = rinfo->distance;
79 }
80
81 if (rinfo->tag) {
82 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
83 api.tag = rinfo->tag;
84 }
85
86 zclient_route_send(cmd, zclient, &api);
87
88 if (IS_RIP_DEBUG_ZEBRA) {
89 if (rip->ecmp)
90 zlog_debug("%s: %s/%d nexthops %d",
91 (cmd == ZEBRA_ROUTE_ADD)
92 ? "Install into zebra"
93 : "Delete from zebra",
94 inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen,
95 count);
96 else
97 zlog_debug("%s: %s/%d",
98 (cmd == ZEBRA_ROUTE_ADD)
99 ? "Install into zebra"
100 : "Delete from zebra",
101 inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen);
102 }
103
104 rip_global_route_changes++;
105 }
106
107 /* Add/update ECMP routes to zebra. */
108 void rip_zebra_ipv4_add(struct route_node *rp)
109 {
110 rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_ADD);
111 }
112
113 /* Delete ECMP routes from zebra. */
114 void rip_zebra_ipv4_delete(struct route_node *rp)
115 {
116 rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_DELETE);
117 }
118
119 /* Zebra route add and delete treatment. */
120 static int rip_zebra_read_route(int command, struct zclient *zclient,
121 zebra_size_t length, vrf_id_t vrf_id)
122 {
123 struct zapi_route api;
124 struct in_addr nexthop;
125 unsigned long ifindex;
126
127 if (!rip)
128 return 0;
129
130 if (zapi_route_decode(zclient->ibuf, &api) < 0)
131 return -1;
132
133 nexthop = api.nexthops[0].gate.ipv4;
134 ifindex = api.nexthops[0].ifindex;
135
136 /* Then fetch IPv4 prefixes. */
137 if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
138 rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE,
139 (struct prefix_ipv4 *)&api.prefix, ifindex,
140 &nexthop, api.metric, api.distance,
141 api.tag);
142 else if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL)
143 rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE,
144 (struct prefix_ipv4 *)&api.prefix,
145 ifindex);
146
147 return 0;
148 }
149
150 void rip_zclient_reset(void)
151 {
152 zclient_reset(zclient);
153 }
154
155 /* RIP route-map set for redistribution */
156 static void rip_routemap_set(int type, const char *name)
157 {
158 if (rip->route_map[type].name)
159 free(rip->route_map[type].name);
160
161 rip->route_map[type].name = strdup(name);
162 rip->route_map[type].map = route_map_lookup_by_name(name);
163 }
164
165 static void rip_redistribute_metric_set(int type, unsigned int metric)
166 {
167 rip->route_map[type].metric_config = 1;
168 rip->route_map[type].metric = metric;
169 }
170
171 static int rip_metric_unset(int type, unsigned int metric)
172 {
173 #define DONT_CARE_METRIC_RIP 17
174 if (metric != DONT_CARE_METRIC_RIP
175 && rip->route_map[type].metric != metric)
176 return 1;
177 rip->route_map[type].metric_config = 0;
178 rip->route_map[type].metric = 0;
179 return 0;
180 }
181
182 /* RIP route-map unset for redistribution */
183 static int rip_routemap_unset(int type, const char *name)
184 {
185 if (!rip->route_map[type].name
186 || (name != NULL && strcmp(rip->route_map[type].name, name)))
187 return 1;
188
189 free(rip->route_map[type].name);
190 rip->route_map[type].name = NULL;
191 rip->route_map[type].map = NULL;
192
193 return 0;
194 }
195
196 /* Redistribution types */
197 static struct {
198 int type;
199 int str_min_len;
200 const char *str;
201 } redist_type[] = {{ZEBRA_ROUTE_KERNEL, 1, "kernel"},
202 {ZEBRA_ROUTE_CONNECT, 1, "connected"},
203 {ZEBRA_ROUTE_STATIC, 1, "static"},
204 {ZEBRA_ROUTE_OSPF, 1, "ospf"},
205 {ZEBRA_ROUTE_BGP, 2, "bgp"},
206 {ZEBRA_ROUTE_VNC, 1, "vnc"},
207 {0, 0, NULL}};
208
209 static int rip_redistribute_unset(int type)
210 {
211 if (!vrf_bitmap_check(zclient->redist[AFI_IP][type], VRF_DEFAULT))
212 return CMD_SUCCESS;
213
214 vrf_bitmap_unset(zclient->redist[AFI_IP][type], VRF_DEFAULT);
215
216 if (zclient->sock > 0)
217 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
218 AFI_IP, type, 0, VRF_DEFAULT);
219
220 /* Remove the routes from RIP table. */
221 rip_redistribute_withdraw(type);
222
223 return CMD_SUCCESS;
224 }
225
226 int rip_redistribute_check(int type)
227 {
228 return vrf_bitmap_check(zclient->redist[AFI_IP][type], VRF_DEFAULT);
229 }
230
231 void rip_redistribute_clean(void)
232 {
233 int i;
234
235 for (i = 0; redist_type[i].str; i++) {
236 if (vrf_bitmap_check(
237 zclient->redist[AFI_IP][redist_type[i].type],
238 VRF_DEFAULT)) {
239 if (zclient->sock > 0)
240 zebra_redistribute_send(
241 ZEBRA_REDISTRIBUTE_DELETE, zclient,
242 AFI_IP, redist_type[i].type, 0,
243 VRF_DEFAULT);
244
245 vrf_bitmap_unset(
246 zclient->redist[AFI_IP][redist_type[i].type],
247 VRF_DEFAULT);
248
249 /* Remove the routes from RIP table. */
250 rip_redistribute_withdraw(redist_type[i].type);
251 }
252 }
253 }
254
255 DEFUN (rip_redistribute_type,
256 rip_redistribute_type_cmd,
257 "redistribute " FRR_REDIST_STR_RIPD,
258 REDIST_STR
259 FRR_REDIST_HELP_STR_RIPD)
260 {
261 int i;
262
263 for (i = 0; redist_type[i].str; i++) {
264 if (strncmp(redist_type[i].str, argv[1]->arg,
265 redist_type[i].str_min_len)
266 == 0) {
267 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient,
268 AFI_IP, redist_type[i].type, 0,
269 VRF_DEFAULT);
270 return CMD_SUCCESS;
271 }
272 }
273
274 vty_out(vty, "Invalid type %s\n", argv[1]->arg);
275
276 return CMD_WARNING_CONFIG_FAILED;
277 }
278
279 DEFUN (no_rip_redistribute_type,
280 no_rip_redistribute_type_cmd,
281 "no redistribute " FRR_REDIST_STR_RIPD,
282 NO_STR
283 REDIST_STR
284 FRR_REDIST_HELP_STR_RIPD)
285 {
286 int i;
287
288 for (i = 0; redist_type[i].str; i++) {
289 if (strncmp(redist_type[i].str, argv[2]->arg,
290 redist_type[i].str_min_len)
291 == 0) {
292 rip_metric_unset(redist_type[i].type,
293 DONT_CARE_METRIC_RIP);
294 rip_routemap_unset(redist_type[i].type, NULL);
295 rip_redistribute_unset(redist_type[i].type);
296 return CMD_SUCCESS;
297 }
298 }
299
300 vty_out(vty, "Invalid type %s\n", argv[2]->arg);
301
302 return CMD_WARNING_CONFIG_FAILED;
303 }
304
305 DEFUN (rip_redistribute_type_routemap,
306 rip_redistribute_type_routemap_cmd,
307 "redistribute " FRR_REDIST_STR_RIPD " route-map WORD",
308 REDIST_STR
309 FRR_REDIST_HELP_STR_RIPD
310 "Route map reference\n"
311 "Pointer to route-map entries\n")
312 {
313 int idx_protocol = 1;
314 int idx_word = 3;
315 int i;
316
317 for (i = 0; redist_type[i].str; i++) {
318 if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) {
319 rip_routemap_set(redist_type[i].type,
320 argv[idx_word]->arg);
321 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient,
322 AFI_IP, redist_type[i].type, 0,
323 VRF_DEFAULT);
324 return CMD_SUCCESS;
325 }
326 }
327
328 vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
329
330 return CMD_WARNING_CONFIG_FAILED;
331 }
332
333 DEFUN (no_rip_redistribute_type_routemap,
334 no_rip_redistribute_type_routemap_cmd,
335 "no redistribute " FRR_REDIST_STR_RIPD " route-map WORD",
336 NO_STR
337 REDIST_STR
338 FRR_REDIST_HELP_STR_RIPD
339 "Route map reference\n"
340 "Pointer to route-map entries\n")
341 {
342 int idx_protocol = 2;
343 int idx_word = 4;
344 int i;
345
346 for (i = 0; redist_type[i].str; i++) {
347 if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) {
348 if (rip_routemap_unset(redist_type[i].type,
349 argv[idx_word]->arg))
350 return CMD_WARNING_CONFIG_FAILED;
351 rip_redistribute_unset(redist_type[i].type);
352 return CMD_SUCCESS;
353 }
354 }
355
356 vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
357
358 return CMD_WARNING_CONFIG_FAILED;
359 }
360
361 DEFUN (rip_redistribute_type_metric,
362 rip_redistribute_type_metric_cmd,
363 "redistribute " FRR_REDIST_STR_RIPD " metric (0-16)",
364 REDIST_STR
365 FRR_REDIST_HELP_STR_RIPD
366 "Metric\n"
367 "Metric value\n")
368 {
369 int idx_protocol = 1;
370 int idx_number = 3;
371 int i;
372 int metric;
373
374 metric = atoi(argv[idx_number]->arg);
375
376 for (i = 0; redist_type[i].str; i++) {
377 if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) {
378 rip_redistribute_metric_set(redist_type[i].type,
379 metric);
380 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient,
381 AFI_IP, redist_type[i].type, 0,
382 VRF_DEFAULT);
383 return CMD_SUCCESS;
384 }
385 }
386
387 vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
388
389 return CMD_WARNING_CONFIG_FAILED;
390 }
391
392 DEFUN (no_rip_redistribute_type_metric,
393 no_rip_redistribute_type_metric_cmd,
394 "no redistribute " FRR_REDIST_STR_RIPD " metric (0-16)",
395 NO_STR
396 REDIST_STR
397 FRR_REDIST_HELP_STR_RIPD
398 "Metric\n"
399 "Metric value\n")
400 {
401 int idx_protocol = 2;
402 int idx_number = 4;
403 int i;
404
405 for (i = 0; redist_type[i].str; i++) {
406 if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) {
407 if (rip_metric_unset(redist_type[i].type,
408 atoi(argv[idx_number]->arg)))
409 return CMD_WARNING_CONFIG_FAILED;
410 rip_redistribute_unset(redist_type[i].type);
411 return CMD_SUCCESS;
412 }
413 }
414
415 vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
416
417 return CMD_WARNING_CONFIG_FAILED;
418 }
419
420 DEFUN (rip_redistribute_type_metric_routemap,
421 rip_redistribute_type_metric_routemap_cmd,
422 "redistribute " FRR_REDIST_STR_RIPD " metric (0-16) route-map WORD",
423 REDIST_STR
424 FRR_REDIST_HELP_STR_RIPD
425 "Metric\n"
426 "Metric value\n"
427 "Route map reference\n"
428 "Pointer to route-map entries\n")
429 {
430 int idx_protocol = 1;
431 int idx_number = 3;
432 int idx_word = 5;
433 int i;
434 int metric;
435
436 metric = atoi(argv[idx_number]->arg);
437
438 for (i = 0; redist_type[i].str; i++) {
439 if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) {
440 rip_redistribute_metric_set(redist_type[i].type,
441 metric);
442 rip_routemap_set(redist_type[i].type,
443 argv[idx_word]->arg);
444 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient,
445 AFI_IP, redist_type[i].type, 0,
446 VRF_DEFAULT);
447 return CMD_SUCCESS;
448 }
449 }
450
451 vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
452
453 return CMD_WARNING_CONFIG_FAILED;
454 }
455
456
457 DEFUN (no_rip_redistribute_type_metric_routemap,
458 no_rip_redistribute_type_metric_routemap_cmd,
459 "no redistribute " FRR_REDIST_STR_RIPD " metric (0-16) route-map WORD",
460 NO_STR
461 REDIST_STR
462 FRR_REDIST_HELP_STR_RIPD
463 "Metric\n"
464 "Metric value\n"
465 "Route map reference\n"
466 "Pointer to route-map entries\n")
467 {
468 int idx_protocol = 2;
469 int idx_number = 4;
470 int idx_word = 6;
471 int i;
472
473 for (i = 0; redist_type[i].str; i++) {
474 if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) {
475 if (rip_metric_unset(redist_type[i].type,
476 atoi(argv[idx_number]->arg)))
477 return CMD_WARNING_CONFIG_FAILED;
478 if (rip_routemap_unset(redist_type[i].type,
479 argv[idx_word]->arg)) {
480 rip_redistribute_metric_set(
481 redist_type[i].type,
482 atoi(argv[idx_number]->arg));
483 return CMD_WARNING_CONFIG_FAILED;
484 }
485 rip_redistribute_unset(redist_type[i].type);
486 return CMD_SUCCESS;
487 }
488 }
489
490 vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
491
492 return CMD_WARNING_CONFIG_FAILED;
493 }
494
495 /* Default information originate. */
496
497 DEFUN (rip_default_information_originate,
498 rip_default_information_originate_cmd,
499 "default-information originate",
500 "Control distribution of default route\n"
501 "Distribute a default route\n")
502 {
503 struct prefix_ipv4 p;
504
505 if (!rip->default_information) {
506 memset(&p, 0, sizeof(struct prefix_ipv4));
507 p.family = AF_INET;
508
509 rip->default_information = 1;
510
511 rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0,
512 NULL, 0, 0, 0);
513 }
514
515 return CMD_SUCCESS;
516 }
517
518 DEFUN (no_rip_default_information_originate,
519 no_rip_default_information_originate_cmd,
520 "no default-information originate",
521 NO_STR
522 "Control distribution of default route\n"
523 "Distribute a default route\n")
524 {
525 struct prefix_ipv4 p;
526
527 if (rip->default_information) {
528 memset(&p, 0, sizeof(struct prefix_ipv4));
529 p.family = AF_INET;
530
531 rip->default_information = 0;
532
533 rip_redistribute_delete(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p,
534 0);
535 }
536
537 return CMD_SUCCESS;
538 }
539
540 int config_write_rip_redistribute(struct vty *vty, int config_mode)
541 {
542 int i;
543
544 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
545 if (i == zclient->redist_default
546 || !vrf_bitmap_check(zclient->redist[AFI_IP][i],
547 VRF_DEFAULT))
548 continue;
549
550 if (!config_mode) {
551 vty_out(vty, " %s", zebra_route_string(i));
552 continue;
553 }
554
555 if (rip->route_map[i].metric_config) {
556 if (rip->route_map[i].name)
557 vty_out(vty,
558 " redistribute %s metric %d route-map %s\n",
559 zebra_route_string(i),
560 rip->route_map[i].metric,
561 rip->route_map[i].name);
562 else
563 vty_out(vty, " redistribute %s metric %d\n",
564 zebra_route_string(i),
565 rip->route_map[i].metric);
566 } else {
567 if (rip->route_map[i].name)
568 vty_out(vty, " redistribute %s route-map %s\n",
569 zebra_route_string(i),
570 rip->route_map[i].name);
571 else
572 vty_out(vty, " redistribute %s\n",
573 zebra_route_string(i));
574 }
575 }
576
577 return 0;
578 }
579
580 static void rip_zebra_connected(struct zclient *zclient)
581 {
582 zclient_send_reg_requests(zclient, VRF_DEFAULT);
583 }
584
585 void rip_zclient_init(struct thread_master *master)
586 {
587 /* Set default value to the zebra client structure. */
588 zclient = zclient_new(master);
589 zclient_init(zclient, ZEBRA_ROUTE_RIP, 0);
590 zclient->zebra_connected = rip_zebra_connected;
591 zclient->interface_add = rip_interface_add;
592 zclient->interface_delete = rip_interface_delete;
593 zclient->interface_address_add = rip_interface_address_add;
594 zclient->interface_address_delete = rip_interface_address_delete;
595 zclient->interface_up = rip_interface_up;
596 zclient->interface_down = rip_interface_down;
597 zclient->redistribute_route_add = rip_zebra_read_route;
598 zclient->redistribute_route_del = rip_zebra_read_route;
599
600 /* Install command elements to rip node. */
601 install_element(RIP_NODE, &rip_redistribute_type_cmd);
602 install_element(RIP_NODE, &rip_redistribute_type_routemap_cmd);
603 install_element(RIP_NODE, &rip_redistribute_type_metric_cmd);
604 install_element(RIP_NODE, &rip_redistribute_type_metric_routemap_cmd);
605 install_element(RIP_NODE, &no_rip_redistribute_type_cmd);
606 install_element(RIP_NODE, &no_rip_redistribute_type_routemap_cmd);
607 install_element(RIP_NODE, &no_rip_redistribute_type_metric_cmd);
608 install_element(RIP_NODE,
609 &no_rip_redistribute_type_metric_routemap_cmd);
610 install_element(RIP_NODE, &rip_default_information_originate_cmd);
611 install_element(RIP_NODE, &no_rip_default_information_originate_cmd);
612 }
613
614 void rip_zclient_stop(void)
615 {
616 zclient_stop(zclient);
617 zclient_free(zclient);
618 }