]> git.proxmox.com Git - mirror_frr.git/blob - eigrpd/eigrp_zebra.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / eigrpd / eigrp_zebra.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Zebra connect library for EIGRP.
4 * Copyright (C) 2013-2014
5 * Authors:
6 * Donnie Savage
7 * Jan Janovic
8 * Matej Perina
9 * Peter Orsag
10 * Peter Paluch
11 */
12
13 #include <zebra.h>
14
15 #include "frrevent.h"
16 #include "command.h"
17 #include "network.h"
18 #include "prefix.h"
19 #include "routemap.h"
20 #include "table.h"
21 #include "stream.h"
22 #include "memory.h"
23 #include "zclient.h"
24 #include "filter.h"
25 #include "plist.h"
26 #include "log.h"
27 #include "nexthop.h"
28
29 #include "eigrpd/eigrp_types.h"
30 #include "eigrpd/eigrp_structs.h"
31 #include "eigrpd/eigrpd.h"
32 #include "eigrpd/eigrp_interface.h"
33 #include "eigrpd/eigrp_neighbor.h"
34 #include "eigrpd/eigrp_packet.h"
35 #include "eigrpd/eigrp_zebra.h"
36 #include "eigrpd/eigrp_vty.h"
37 #include "eigrpd/eigrp_dump.h"
38 #include "eigrpd/eigrp_network.h"
39 #include "eigrpd/eigrp_topology.h"
40 #include "eigrpd/eigrp_fsm.h"
41 #include "eigrpd/eigrp_metric.h"
42
43 static int eigrp_interface_address_add(ZAPI_CALLBACK_ARGS);
44 static int eigrp_interface_address_delete(ZAPI_CALLBACK_ARGS);
45
46 static int eigrp_zebra_read_route(ZAPI_CALLBACK_ARGS);
47
48 /* Zebra structure to hold current status. */
49 struct zclient *zclient = NULL;
50
51 /* For registering threads. */
52 extern struct event_loop *master;
53 struct in_addr router_id_zebra;
54
55 /* Router-id update message from zebra. */
56 static int eigrp_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
57 {
58 struct eigrp *eigrp;
59 struct prefix router_id;
60 zebra_router_id_update_read(zclient->ibuf, &router_id);
61
62 router_id_zebra = router_id.u.prefix4;
63
64 eigrp = eigrp_lookup(vrf_id);
65
66 if (eigrp != NULL)
67 eigrp_router_id_update(eigrp);
68
69 return 0;
70 }
71
72 static int eigrp_zebra_route_notify_owner(ZAPI_CALLBACK_ARGS)
73 {
74 struct prefix p;
75 enum zapi_route_notify_owner note;
76 uint32_t table;
77
78 if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, &note, NULL,
79 NULL))
80 return -1;
81
82 return 0;
83 }
84
85 static void eigrp_zebra_connected(struct zclient *zclient)
86 {
87 zclient_send_reg_requests(zclient, VRF_DEFAULT);
88 }
89
90 static zclient_handler *const eigrp_handlers[] = {
91 [ZEBRA_ROUTER_ID_UPDATE] = eigrp_router_id_update_zebra,
92 [ZEBRA_INTERFACE_ADDRESS_ADD] = eigrp_interface_address_add,
93 [ZEBRA_INTERFACE_ADDRESS_DELETE] = eigrp_interface_address_delete,
94 [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = eigrp_zebra_read_route,
95 [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = eigrp_zebra_read_route,
96 [ZEBRA_ROUTE_NOTIFY_OWNER] = eigrp_zebra_route_notify_owner,
97 };
98
99 void eigrp_zebra_init(void)
100 {
101 struct zclient_options opt = {.receive_notify = false};
102
103 zclient = zclient_new(master, &opt, eigrp_handlers,
104 array_size(eigrp_handlers));
105
106 zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0, &eigrpd_privs);
107 zclient->zebra_connected = eigrp_zebra_connected;
108 }
109
110
111 /* Zebra route add and delete treatment. */
112 static int eigrp_zebra_read_route(ZAPI_CALLBACK_ARGS)
113 {
114 struct zapi_route api;
115 struct eigrp *eigrp;
116
117 if (zapi_route_decode(zclient->ibuf, &api) < 0)
118 return -1;
119
120 if (IPV4_NET127(ntohl(api.prefix.u.prefix4.s_addr)))
121 return 0;
122
123 eigrp = eigrp_lookup(vrf_id);
124 if (eigrp == NULL)
125 return 0;
126
127 if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
128
129 } else /* if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */
130 {
131 }
132
133 return 0;
134 }
135
136 static int eigrp_interface_address_add(ZAPI_CALLBACK_ARGS)
137 {
138 struct connected *c;
139
140 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
141
142 if (c == NULL)
143 return 0;
144
145 if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
146 zlog_debug("Zebra: interface %s address add %pFX", c->ifp->name,
147 c->address);
148
149 eigrp_if_update(c->ifp);
150
151 return 0;
152 }
153
154 static int eigrp_interface_address_delete(ZAPI_CALLBACK_ARGS)
155 {
156 struct connected *c;
157 struct interface *ifp;
158 struct eigrp_interface *ei;
159
160 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
161
162 if (c == NULL)
163 return 0;
164
165 if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
166 zlog_debug("Zebra: interface %s address delete %pFX",
167 c->ifp->name, c->address);
168
169 ifp = c->ifp;
170 ei = ifp->info;
171 if (!ei)
172 return 0;
173
174 /* Call interface hook functions to clean up */
175 if (prefix_cmp(&ei->address, c->address) == 0)
176 eigrp_if_free(ei, INTERFACE_DOWN_BY_ZEBRA);
177
178 connected_free(&c);
179
180 return 0;
181 }
182
183 void eigrp_zebra_route_add(struct eigrp *eigrp, struct prefix *p,
184 struct list *successors, uint32_t distance)
185 {
186 struct zapi_route api;
187 struct zapi_nexthop *api_nh;
188 struct eigrp_route_descriptor *te;
189 struct listnode *node;
190 int count = 0;
191
192 if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP])
193 return;
194
195 memset(&api, 0, sizeof(api));
196 api.vrf_id = eigrp->vrf_id;
197 api.type = ZEBRA_ROUTE_EIGRP;
198 api.safi = SAFI_UNICAST;
199 api.metric = distance;
200 memcpy(&api.prefix, p, sizeof(*p));
201
202 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
203 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
204
205 /* Nexthop, ifindex, distance and metric information. */
206 for (ALL_LIST_ELEMENTS_RO(successors, node, te)) {
207 if (count >= MULTIPATH_NUM)
208 break;
209 api_nh = &api.nexthops[count];
210 api_nh->vrf_id = eigrp->vrf_id;
211 if (te->adv_router->src.s_addr) {
212 api_nh->gate.ipv4 = te->adv_router->src;
213 api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
214 } else
215 api_nh->type = NEXTHOP_TYPE_IFINDEX;
216 api_nh->ifindex = te->ei->ifp->ifindex;
217
218 count++;
219 }
220 api.nexthop_num = count;
221
222 if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) {
223 zlog_debug("Zebra: Route add %pFX", p);
224 }
225
226 zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
227 }
228
229 void eigrp_zebra_route_delete(struct eigrp *eigrp, struct prefix *p)
230 {
231 struct zapi_route api;
232
233 if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP])
234 return;
235
236 memset(&api, 0, sizeof(api));
237 api.vrf_id = eigrp->vrf_id;
238 api.type = ZEBRA_ROUTE_EIGRP;
239 api.safi = SAFI_UNICAST;
240 memcpy(&api.prefix, p, sizeof(*p));
241 zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
242
243 if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE))
244 zlog_debug("Zebra: Route del %pFX", p);
245
246 return;
247 }
248
249 static int eigrp_is_type_redistributed(int type, vrf_id_t vrf_id)
250 {
251 return ((DEFAULT_ROUTE_TYPE(type))
252 ? vrf_bitmap_check(zclient->default_information[AFI_IP],
253 vrf_id)
254 : vrf_bitmap_check(zclient->redist[AFI_IP][type],
255 vrf_id));
256 }
257
258 int eigrp_redistribute_set(struct eigrp *eigrp, int type,
259 struct eigrp_metrics metric)
260 {
261
262 if (eigrp_is_type_redistributed(type, eigrp->vrf_id)) {
263 if (eigrp_metrics_is_same(metric, eigrp->dmetric[type])) {
264 eigrp->dmetric[type] = metric;
265 }
266
267 eigrp_external_routes_refresh(eigrp, type);
268
269 // if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE))
270 // zlog_debug ("Redistribute[%s]: Refresh Type[%d],
271 // Metric[%d]",
272 // eigrp_redist_string(type),
273 // metric_type (eigrp, type), metric_value
274 // (eigrp, type));
275 return CMD_SUCCESS;
276 }
277
278 eigrp->dmetric[type] = metric;
279
280 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type, 0,
281 eigrp->vrf_id);
282
283 ++eigrp->redistribute;
284
285 return CMD_SUCCESS;
286 }
287
288 int eigrp_redistribute_unset(struct eigrp *eigrp, int type)
289 {
290
291 if (eigrp_is_type_redistributed(type, eigrp->vrf_id)) {
292 memset(&eigrp->dmetric[type], 0, sizeof(struct eigrp_metrics));
293 zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP,
294 type, 0, eigrp->vrf_id);
295 --eigrp->redistribute;
296 }
297
298 return CMD_SUCCESS;
299 }