]> git.proxmox.com Git - mirror_frr.git/blob - staticd/static_zebra.c
Merge pull request #2799 from adharkar/frr-zebra_cli
[mirror_frr.git] / staticd / static_zebra.c
1 /*
2 * Zebra connect code.
3 * Copyright (C) 2018 Cumulus Networks, Inc.
4 * Donald Sharp
5 *
6 * This program 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 Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * 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 #include <zebra.h>
21
22 #include "thread.h"
23 #include "command.h"
24 #include "network.h"
25 #include "prefix.h"
26 #include "routemap.h"
27 #include "table.h"
28 #include "srcdest_table.h"
29 #include "stream.h"
30 #include "memory.h"
31 #include "zclient.h"
32 #include "filter.h"
33 #include "plist.h"
34 #include "log.h"
35 #include "nexthop.h"
36 #include "nexthop_group.h"
37
38 #include "static_vrf.h"
39 #include "static_routes.h"
40 #include "static_zebra.h"
41 #include "static_nht.h"
42 #include "static_vty.h"
43
44 /* Zebra structure to hold current status. */
45 struct zclient *zclient;
46
47 static struct interface *zebra_interface_if_lookup(struct stream *s)
48 {
49 char ifname_tmp[INTERFACE_NAMSIZ];
50
51 /* Read interface name. */
52 stream_get(ifname_tmp, s, INTERFACE_NAMSIZ);
53
54 /* And look it up. */
55 return if_lookup_by_name(ifname_tmp, VRF_DEFAULT);
56 }
57
58 /* Inteface addition message from zebra. */
59 static int interface_add(int command, struct zclient *zclient,
60 zebra_size_t length, vrf_id_t vrf_id)
61 {
62 struct interface *ifp;
63
64 ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
65
66 if (!ifp)
67 return 0;
68
69 static_ifindex_update(ifp, true);
70 return 0;
71 }
72
73 static int interface_delete(int command, struct zclient *zclient,
74 zebra_size_t length, vrf_id_t vrf_id)
75 {
76 struct interface *ifp;
77 struct stream *s;
78
79 s = zclient->ibuf;
80 /* zebra_interface_state_read () updates interface structure in iflist
81 */
82 ifp = zebra_interface_state_read(s, vrf_id);
83
84 if (ifp == NULL)
85 return 0;
86
87 if_set_index(ifp, IFINDEX_INTERNAL);
88
89 static_ifindex_update(ifp, false);
90 return 0;
91 }
92
93 static int interface_address_add(int command, struct zclient *zclient,
94 zebra_size_t length, vrf_id_t vrf_id)
95 {
96 zebra_interface_address_read(command, zclient->ibuf, vrf_id);
97
98 return 0;
99 }
100
101 static int interface_address_delete(int command, struct zclient *zclient,
102 zebra_size_t length, vrf_id_t vrf_id)
103 {
104 struct connected *c;
105
106 c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
107
108 if (!c)
109 return 0;
110
111 connected_free(c);
112 return 0;
113 }
114
115 static int interface_state_up(int command, struct zclient *zclient,
116 zebra_size_t length, vrf_id_t vrf_id)
117 {
118 struct interface *ifp;
119
120 ifp = zebra_interface_if_lookup(zclient->ibuf);
121
122 if (if_is_vrf(ifp)) {
123 struct static_vrf *svrf = static_vrf_lookup_by_id(vrf_id);
124
125 static_fixup_vrf_ids(svrf);
126 static_config_install_delayed_routes(svrf);
127 }
128
129 return 0;
130 }
131
132 static int interface_state_down(int command, struct zclient *zclient,
133 zebra_size_t length, vrf_id_t vrf_id)
134 {
135 zebra_interface_state_read(zclient->ibuf, vrf_id);
136
137 return 0;
138 }
139
140 static int route_notify_owner(int command, struct zclient *zclient,
141 zebra_size_t length, vrf_id_t vrf_id)
142 {
143 struct prefix p;
144 enum zapi_route_notify_owner note;
145 uint32_t table_id;
146 char buf[PREFIX_STRLEN];
147
148 prefix2str(&p, buf, sizeof(buf));
149
150 if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, &note))
151 return -1;
152
153 switch (note) {
154 case ZAPI_ROUTE_FAIL_INSTALL:
155 zlog_warn("%s: Route %s failed to install for table: %u",
156 __PRETTY_FUNCTION__, buf, table_id);
157 break;
158 case ZAPI_ROUTE_BETTER_ADMIN_WON:
159 zlog_warn("%s: Route %s over-ridden by better route for table: %u",
160 __PRETTY_FUNCTION__, buf, table_id);
161 break;
162 case ZAPI_ROUTE_INSTALLED:
163 break;
164 case ZAPI_ROUTE_REMOVED:
165 break;
166 case ZAPI_ROUTE_REMOVE_FAIL:
167 zlog_warn("%s: Route %s failure to remove for table: %u",
168 __PRETTY_FUNCTION__, buf, table_id);
169 break;
170 }
171
172 return 0;
173 }
174 static void zebra_connected(struct zclient *zclient)
175 {
176 zclient_send_reg_requests(zclient, VRF_DEFAULT);
177 }
178
179
180 static int static_zebra_nexthop_update(int command, struct zclient *zclient,
181 zebra_size_t length, vrf_id_t vrf_id)
182 {
183 struct zapi_route nhr;
184 afi_t afi = AFI_IP;
185
186 if (!zapi_nexthop_update_decode(zclient->ibuf, &nhr)) {
187 zlog_warn("Failure to decode nexthop update message");
188 return 1;
189 }
190
191 if (nhr.prefix.family == AF_INET6)
192 afi = AFI_IP6;
193
194 static_nht_update(&nhr.prefix, nhr.nexthop_num, afi, vrf_id);
195 return 1;
196 }
197
198 static void static_zebra_capabilities(struct zclient_capabilities *cap)
199 {
200 mpls_enabled = cap->mpls_enabled;
201 }
202
203 void static_zebra_nht_register(struct static_route *si, bool reg)
204 {
205 uint32_t cmd;
206 struct prefix p;
207
208 cmd = (reg) ?
209 ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER;
210
211 if (si->nh_registered && reg)
212 return;
213
214 if (!si->nh_registered && !reg)
215 return;
216
217 memset(&p, 0, sizeof(p));
218 switch (si->type) {
219 case STATIC_IFNAME:
220 case STATIC_BLACKHOLE:
221 return;
222 case STATIC_IPV4_GATEWAY:
223 case STATIC_IPV4_GATEWAY_IFNAME:
224 p.family = AF_INET;
225 p.prefixlen = IPV4_MAX_BITLEN;
226 p.u.prefix4 = si->addr.ipv4;
227 break;
228 case STATIC_IPV6_GATEWAY:
229 case STATIC_IPV6_GATEWAY_IFNAME:
230 p.family = AF_INET6;
231 p.prefixlen = IPV6_MAX_BITLEN;
232 p.u.prefix6 = si->addr.ipv6;
233 break;
234 }
235
236 if (zclient_send_rnh(zclient, cmd, &p, false, si->nh_vrf_id) < 0)
237 zlog_warn("%s: Failure to send nexthop to zebra",
238 __PRETTY_FUNCTION__);
239
240 si->nh_registered = reg;
241 }
242
243 extern void static_zebra_route_add(struct route_node *rn,
244 struct static_route *si_changed,
245 vrf_id_t vrf_id, safi_t safi, bool install)
246 {
247 struct static_route *si = rn->info;
248 const struct prefix *p, *src_pp;
249 struct zapi_nexthop *api_nh;
250 struct zapi_route api;
251 uint32_t nh_num = 0;
252
253 p = src_pp = NULL;
254 srcdest_rnode_prefixes(rn, &p, &src_pp);
255
256 memset(&api, 0, sizeof(api));
257 api.vrf_id = vrf_id;
258 api.type = ZEBRA_ROUTE_STATIC;
259 api.safi = safi;
260 memcpy(&api.prefix, p, sizeof(api.prefix));
261
262 if (src_pp) {
263 SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
264 memcpy(&api.src_prefix, src_pp, sizeof(api.src_prefix));
265 }
266 SET_FLAG(api.flags, ZEBRA_FLAG_RR_USE_DISTANCE);
267 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
268 if (si_changed->distance) {
269 SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
270 api.distance = si_changed->distance;
271 }
272 if (si_changed->tag) {
273 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
274 api.tag = si_changed->tag;
275 }
276 api.tableid = si_changed->table_id;
277
278 zlog_debug("Distance sent down: %d %d", si_changed->distance, install);
279 for (/*loaded above*/; si; si = si->next) {
280 api_nh = &api.nexthops[nh_num];
281 if (si->nh_vrf_id == VRF_UNKNOWN)
282 continue;
283
284 if (si->distance != si_changed->distance)
285 continue;
286
287 api_nh->vrf_id = si->nh_vrf_id;
288 switch (si->type) {
289 case STATIC_IFNAME:
290 if (si->ifindex == IFINDEX_INTERNAL)
291 continue;
292 api_nh->ifindex = si->ifindex;
293 api_nh->type = NEXTHOP_TYPE_IFINDEX;
294 break;
295 case STATIC_IPV4_GATEWAY:
296 if (!si->nh_valid)
297 continue;
298 api_nh->type = NEXTHOP_TYPE_IPV4;
299 api_nh->gate = si->addr;
300 break;
301 case STATIC_IPV4_GATEWAY_IFNAME:
302 if (si->ifindex == IFINDEX_INTERNAL)
303 continue;
304 api_nh->ifindex = si->ifindex;
305 api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
306 api_nh->gate = si->addr;
307 break;
308 case STATIC_IPV6_GATEWAY:
309 if (!si->nh_valid)
310 continue;
311 api_nh->type = NEXTHOP_TYPE_IPV6;
312 api_nh->gate = si->addr;
313 break;
314 case STATIC_IPV6_GATEWAY_IFNAME:
315 if (si->ifindex == IFINDEX_INTERNAL)
316 continue;
317 api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
318 api_nh->ifindex = si->ifindex;
319 api_nh->gate = si->addr;
320 break;
321 case STATIC_BLACKHOLE:
322 api_nh->type = NEXTHOP_TYPE_BLACKHOLE;
323 switch (si->bh_type) {
324 case STATIC_BLACKHOLE_DROP:
325 case STATIC_BLACKHOLE_NULL:
326 api_nh->bh_type = BLACKHOLE_NULL;
327 break;
328 case STATIC_BLACKHOLE_REJECT:
329 api_nh->bh_type = BLACKHOLE_REJECT;
330 }
331 break;
332 }
333
334 if (si->snh_label.num_labels) {
335 int i;
336
337 SET_FLAG(api.message, ZAPI_MESSAGE_LABEL);
338 api_nh->label_num = si->snh_label.num_labels;
339 for (i = 0; i < api_nh->label_num; i++)
340 api_nh->labels[i] = si->snh_label.label[i];
341 }
342 nh_num++;
343 }
344
345 api.nexthop_num = nh_num;
346
347 /*
348 * If we have been given an install but nothing is valid
349 * go ahead and delete the route for double plus fun
350 */
351 if (!nh_num && install)
352 install = false;
353
354 zclient_route_send(install ?
355 ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
356 zclient, &api);
357 }
358 void static_zebra_init(void)
359 {
360 struct zclient_options opt = { .receive_notify = true };
361
362 zclient = zclient_new_notify(master, &opt);
363
364 zclient_init(zclient, ZEBRA_ROUTE_STATIC, 0, &static_privs);
365 zclient->zebra_capabilities = static_zebra_capabilities;
366 zclient->zebra_connected = zebra_connected;
367 zclient->interface_add = interface_add;
368 zclient->interface_delete = interface_delete;
369 zclient->interface_up = interface_state_up;
370 zclient->interface_down = interface_state_down;
371 zclient->interface_address_add = interface_address_add;
372 zclient->interface_address_delete = interface_address_delete;
373 zclient->route_notify_owner = route_notify_owner;
374 zclient->nexthop_update = static_zebra_nexthop_update;
375 }