]> git.proxmox.com Git - mirror_frr.git/blob - ripd/rip_zebra.c
Merge pull request #13578 from opensourcerouting/fix/ripd_argv_find
[mirror_frr.git] / ripd / rip_zebra.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* RIPd and zebra interface.
3 * Copyright (C) 1997, 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
4 */
5
6 #include <zebra.h>
7
8 #include "command.h"
9 #include "prefix.h"
10 #include "table.h"
11 #include "stream.h"
12 #include "memory.h"
13 #include "zclient.h"
14 #include "log.h"
15 #include "vrf.h"
16 #include "bfd.h"
17 #include "ripd/ripd.h"
18 #include "ripd/rip_debug.h"
19 #include "ripd/rip_interface.h"
20
21 /* All information about zebra. */
22 struct zclient *zclient = NULL;
23 uint32_t zebra_ecmp_count = MULTIPATH_NUM;
24
25 /* Send ECMP routes to zebra. */
26 static void rip_zebra_ipv4_send(struct rip *rip, struct route_node *rp,
27 uint8_t cmd)
28 {
29 struct list *list = (struct list *)rp->info;
30 struct zapi_route api;
31 struct zapi_nexthop *api_nh;
32 struct listnode *listnode = NULL;
33 struct rip_info *rinfo = NULL;
34 uint32_t count = 0;
35
36 memset(&api, 0, sizeof(api));
37 api.vrf_id = rip->vrf->vrf_id;
38 api.type = ZEBRA_ROUTE_RIP;
39 api.safi = SAFI_UNICAST;
40
41 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
42 for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
43 if (count >= zebra_ecmp_count)
44 break;
45 api_nh = &api.nexthops[count];
46 api_nh->vrf_id = rip->vrf->vrf_id;
47 api_nh->gate = rinfo->nh.gate;
48 api_nh->type = NEXTHOP_TYPE_IPV4;
49 if (cmd == ZEBRA_ROUTE_ADD)
50 SET_FLAG(rinfo->flags, RIP_RTF_FIB);
51 else
52 UNSET_FLAG(rinfo->flags, RIP_RTF_FIB);
53 count++;
54 }
55
56 api.prefix = rp->p;
57 api.nexthop_num = count;
58
59 rinfo = listgetdata(listhead(list));
60
61 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
62 api.metric = rinfo->metric;
63
64 if (rinfo->distance && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) {
65 SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
66 api.distance = rinfo->distance;
67 }
68
69 if (rinfo->tag) {
70 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
71 api.tag = rinfo->tag;
72 }
73
74 zclient_route_send(cmd, zclient, &api);
75
76 if (IS_RIP_DEBUG_ZEBRA) {
77 if (rip->ecmp)
78 zlog_debug("%s: %pFX nexthops %d",
79 (cmd == ZEBRA_ROUTE_ADD)
80 ? "Install into zebra"
81 : "Delete from zebra",
82 &rp->p, count);
83 else
84 zlog_debug("%s: %pFX",
85 (cmd == ZEBRA_ROUTE_ADD)
86 ? "Install into zebra"
87 : "Delete from zebra", &rp->p);
88 }
89
90 rip->counters.route_changes++;
91 }
92
93 /* Add/update ECMP routes to zebra. */
94 void rip_zebra_ipv4_add(struct rip *rip, struct route_node *rp)
95 {
96 rip_zebra_ipv4_send(rip, rp, ZEBRA_ROUTE_ADD);
97 }
98
99 /* Delete ECMP routes from zebra. */
100 void rip_zebra_ipv4_delete(struct rip *rip, struct route_node *rp)
101 {
102 rip_zebra_ipv4_send(rip, rp, ZEBRA_ROUTE_DELETE);
103 }
104
105 /* Zebra route add and delete treatment. */
106 static int rip_zebra_read_route(ZAPI_CALLBACK_ARGS)
107 {
108 struct rip *rip;
109 struct zapi_route api;
110 struct nexthop nh;
111
112 rip = rip_lookup_by_vrf_id(vrf_id);
113 if (!rip)
114 return 0;
115
116 if (zapi_route_decode(zclient->ibuf, &api) < 0)
117 return -1;
118
119 memset(&nh, 0, sizeof(nh));
120 nh.type = api.nexthops[0].type;
121 nh.gate.ipv4 = api.nexthops[0].gate.ipv4;
122 nh.ifindex = api.nexthops[0].ifindex;
123
124 /* Then fetch IPv4 prefixes. */
125 if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
126 rip_redistribute_add(rip, api.type, RIP_ROUTE_REDISTRIBUTE,
127 (struct prefix_ipv4 *)&api.prefix, &nh,
128 api.metric, api.distance, api.tag);
129 else if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL)
130 rip_redistribute_delete(rip, api.type, RIP_ROUTE_REDISTRIBUTE,
131 (struct prefix_ipv4 *)&api.prefix,
132 nh.ifindex);
133
134 return 0;
135 }
136
137 void rip_redistribute_conf_update(struct rip *rip, int type)
138 {
139 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP,
140 type, 0, rip->vrf->vrf_id);
141 }
142
143 void rip_redistribute_conf_delete(struct rip *rip, int type)
144 {
145 if (zclient->sock > 0)
146 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
147 AFI_IP, type, 0, rip->vrf->vrf_id);
148
149 /* Remove the routes from RIP table. */
150 rip_redistribute_withdraw(rip, type);
151 }
152
153 int rip_redistribute_check(struct rip *rip, int type)
154 {
155 return rip->redist[type].enabled;
156 }
157
158 void rip_redistribute_enable(struct rip *rip)
159 {
160 for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
161 if (!rip_redistribute_check(rip, i))
162 continue;
163
164 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP,
165 i, 0, rip->vrf->vrf_id);
166 }
167 }
168
169 void rip_redistribute_disable(struct rip *rip)
170 {
171 for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
172 if (!rip_redistribute_check(rip, i))
173 continue;
174
175 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
176 AFI_IP, i, 0, rip->vrf->vrf_id);
177 }
178 }
179
180 void rip_show_redistribute_config(struct vty *vty, struct rip *rip)
181 {
182 for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
183 if (i == zclient->redist_default
184 || !rip_redistribute_check(rip, i))
185 continue;
186
187 vty_out(vty, " %s", zebra_route_string(i));
188 }
189 }
190
191 void rip_zebra_vrf_register(struct vrf *vrf)
192 {
193 if (vrf->vrf_id == VRF_DEFAULT)
194 return;
195
196 if (IS_RIP_DEBUG_EVENT)
197 zlog_debug("%s: register VRF %s(%u) to zebra", __func__,
198 vrf->name, vrf->vrf_id);
199
200 zclient_send_reg_requests(zclient, vrf->vrf_id);
201 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, vrf->vrf_id);
202 }
203
204 void rip_zebra_vrf_deregister(struct vrf *vrf)
205 {
206 if (vrf->vrf_id == VRF_DEFAULT)
207 return;
208
209 if (IS_RIP_DEBUG_EVENT)
210 zlog_debug("%s: deregister VRF %s(%u) from zebra.", __func__,
211 vrf->name, vrf->vrf_id);
212
213 zclient_send_dereg_requests(zclient, vrf->vrf_id);
214 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_DEREGISTER, vrf->vrf_id);
215 }
216
217 static void rip_zebra_connected(struct zclient *zclient)
218 {
219 zclient_send_reg_requests(zclient, VRF_DEFAULT);
220 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);
221 }
222
223 zclient_handler *const rip_handlers[] = {
224 [ZEBRA_INTERFACE_ADDRESS_ADD] = rip_interface_address_add,
225 [ZEBRA_INTERFACE_ADDRESS_DELETE] = rip_interface_address_delete,
226 [ZEBRA_INTERFACE_VRF_UPDATE] = rip_interface_vrf_update,
227 [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = rip_zebra_read_route,
228 [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = rip_zebra_read_route,
229 };
230
231 static void rip_zebra_capabilities(struct zclient_capabilities *cap)
232 {
233 zebra_ecmp_count = MIN(cap->ecmp, zebra_ecmp_count);
234 }
235
236 void rip_zclient_init(struct event_loop *master)
237 {
238 /* Set default value to the zebra client structure. */
239 zclient = zclient_new(master, &zclient_options_default, rip_handlers,
240 array_size(rip_handlers));
241 zclient_init(zclient, ZEBRA_ROUTE_RIP, 0, &ripd_privs);
242 zclient->zebra_connected = rip_zebra_connected;
243 zclient->zebra_capabilities = rip_zebra_capabilities;
244 }
245
246 void rip_zclient_stop(void)
247 {
248 zclient_stop(zclient);
249 zclient_free(zclient);
250 }