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