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