]> git.proxmox.com Git - mirror_frr.git/blame - staticd/static_zebra.c
Merge pull request #3506 from opensourcerouting/6.0-init-fixes
[mirror_frr.git] / staticd / static_zebra.c
CommitLineData
7e24fdf3
DS
1/*
2 * Zebra connect code.
3 * Copyright (C) 2018 Cumulus Networks, Inc.
4 * Donald Sharp
5 *
8d5cbee9
DS
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.
7e24fdf3 10 *
8d5cbee9
DS
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.
7e24fdf3
DS
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"
74f0a94e 37#include "hash.h"
31e2232b 38#include "jhash.h"
7e24fdf3
DS
39
40#include "static_vrf.h"
41#include "static_routes.h"
42#include "static_zebra.h"
43#include "static_nht.h"
44#include "static_vty.h"
45
46/* Zebra structure to hold current status. */
47struct zclient *zclient;
74f0a94e 48static struct hash *static_nht_hash;
7e24fdf3
DS
49
50static struct interface *zebra_interface_if_lookup(struct stream *s)
51{
52 char ifname_tmp[INTERFACE_NAMSIZ];
53
54 /* Read interface name. */
55 stream_get(ifname_tmp, s, INTERFACE_NAMSIZ);
56
57 /* And look it up. */
58 return if_lookup_by_name(ifname_tmp, VRF_DEFAULT);
59}
60
61/* Inteface addition message from zebra. */
62static int interface_add(int command, struct zclient *zclient,
63 zebra_size_t length, vrf_id_t vrf_id)
64{
65 struct interface *ifp;
66
67 ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
68
69 if (!ifp)
70 return 0;
71
72 static_ifindex_update(ifp, true);
73 return 0;
74}
75
76static int interface_delete(int command, struct zclient *zclient,
77 zebra_size_t length, vrf_id_t vrf_id)
78{
79 struct interface *ifp;
80 struct stream *s;
81
82 s = zclient->ibuf;
83 /* zebra_interface_state_read () updates interface structure in iflist
84 */
85 ifp = zebra_interface_state_read(s, vrf_id);
86
87 if (ifp == NULL)
88 return 0;
89
90 if_set_index(ifp, IFINDEX_INTERNAL);
91
92 static_ifindex_update(ifp, false);
93 return 0;
94}
95
96static int interface_address_add(int command, struct zclient *zclient,
97 zebra_size_t length, vrf_id_t vrf_id)
98{
99 zebra_interface_address_read(command, zclient->ibuf, vrf_id);
100
101 return 0;
102}
103
104static int interface_address_delete(int command, struct zclient *zclient,
105 zebra_size_t length, vrf_id_t vrf_id)
106{
107 struct connected *c;
108
109 c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
110
111 if (!c)
112 return 0;
113
114 connected_free(c);
115 return 0;
116}
117
118static int interface_state_up(int command, struct zclient *zclient,
119 zebra_size_t length, vrf_id_t vrf_id)
120{
121 struct interface *ifp;
122
123 ifp = zebra_interface_if_lookup(zclient->ibuf);
124
bacd8eea 125 if (ifp && if_is_vrf(ifp)) {
7e24fdf3
DS
126 struct static_vrf *svrf = static_vrf_lookup_by_id(vrf_id);
127
128 static_fixup_vrf_ids(svrf);
129 static_config_install_delayed_routes(svrf);
130 }
131
132 return 0;
133}
134
135static int interface_state_down(int command, struct zclient *zclient,
136 zebra_size_t length, vrf_id_t vrf_id)
137{
138 zebra_interface_state_read(zclient->ibuf, vrf_id);
139
140 return 0;
141}
142
143static int route_notify_owner(int command, struct zclient *zclient,
144 zebra_size_t length, vrf_id_t vrf_id)
145{
146 struct prefix p;
147 enum zapi_route_notify_owner note;
148 uint32_t table_id;
149 char buf[PREFIX_STRLEN];
150
151 prefix2str(&p, buf, sizeof(buf));
152
153 if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, &note))
154 return -1;
155
156 switch (note) {
157 case ZAPI_ROUTE_FAIL_INSTALL:
158 zlog_warn("%s: Route %s failed to install for table: %u",
159 __PRETTY_FUNCTION__, buf, table_id);
160 break;
161 case ZAPI_ROUTE_BETTER_ADMIN_WON:
162 zlog_warn("%s: Route %s over-ridden by better route for table: %u",
163 __PRETTY_FUNCTION__, buf, table_id);
164 break;
165 case ZAPI_ROUTE_INSTALLED:
166 break;
167 case ZAPI_ROUTE_REMOVED:
168 break;
169 case ZAPI_ROUTE_REMOVE_FAIL:
170 zlog_warn("%s: Route %s failure to remove for table: %u",
171 __PRETTY_FUNCTION__, buf, table_id);
172 break;
173 }
174
175 return 0;
176}
177static void zebra_connected(struct zclient *zclient)
178{
179 zclient_send_reg_requests(zclient, VRF_DEFAULT);
180}
181
74f0a94e
DS
182struct static_nht_data {
183 struct prefix *nh;
31e2232b
DS
184
185 vrf_id_t nh_vrf_id;
186
74f0a94e
DS
187 uint32_t refcount;
188 uint8_t nh_num;
189};
7e24fdf3
DS
190
191static int static_zebra_nexthop_update(int command, struct zclient *zclient,
192 zebra_size_t length, vrf_id_t vrf_id)
193{
74f0a94e 194 struct static_nht_data *nhtd, lookup;
7e24fdf3
DS
195 struct zapi_route nhr;
196 afi_t afi = AFI_IP;
197
198 if (!zapi_nexthop_update_decode(zclient->ibuf, &nhr)) {
199 zlog_warn("Failure to decode nexthop update message");
200 return 1;
201 }
202
203 if (nhr.prefix.family == AF_INET6)
204 afi = AFI_IP6;
205
74f0a94e
DS
206 memset(&lookup, 0, sizeof(lookup));
207 lookup.nh = &nhr.prefix;
31e2232b 208 lookup.nh_vrf_id = vrf_id;
74f0a94e
DS
209
210 nhtd = hash_lookup(static_nht_hash, &lookup);
31e2232b
DS
211
212 if (nhtd) {
74f0a94e
DS
213 nhtd->nh_num = nhr.nexthop_num;
214
31e2232b
DS
215 static_nht_update(&nhr.prefix, nhr.nexthop_num, afi,
216 nhtd->nh_vrf_id);
217 } else
218 zlog_err("No nhtd?");
74f0a94e 219
7e24fdf3
DS
220 return 1;
221}
222
223static void static_zebra_capabilities(struct zclient_capabilities *cap)
224{
225 mpls_enabled = cap->mpls_enabled;
226}
227
74f0a94e
DS
228static unsigned int static_nht_hash_key(void *data)
229{
230 struct static_nht_data *nhtd = data;
31e2232b 231 unsigned int key = 0;
74f0a94e 232
31e2232b
DS
233 key = prefix_hash_key(nhtd->nh);
234 return jhash_1word(nhtd->nh_vrf_id, key);
74f0a94e
DS
235}
236
237static int static_nht_hash_cmp(const void *d1, const void *d2)
238{
239 const struct static_nht_data *nhtd1 = d1;
240 const struct static_nht_data *nhtd2 = d2;
241
31e2232b
DS
242 if (nhtd1->nh_vrf_id != nhtd2->nh_vrf_id)
243 return 0;
244
74f0a94e
DS
245 return prefix_same(nhtd1->nh, nhtd2->nh);
246}
247
248static void *static_nht_hash_alloc(void *data)
249{
250 struct static_nht_data *copy = data;
251 struct static_nht_data *new;
252
253 new = XMALLOC(MTYPE_TMP, sizeof(*new));
254
255 new->nh = prefix_new();
256 prefix_copy(new->nh, copy->nh);
257 new->refcount = 0;
258 new->nh_num = 0;
31e2232b 259 new->nh_vrf_id = copy->nh_vrf_id;
74f0a94e
DS
260
261 return new;
262}
263
264static void static_nht_hash_free(void *data)
265{
266 struct static_nht_data *nhtd = data;
267
268 prefix_free(nhtd->nh);
269 XFREE(MTYPE_TMP, nhtd);
270}
271
7e24fdf3
DS
272void static_zebra_nht_register(struct static_route *si, bool reg)
273{
74f0a94e 274 struct static_nht_data *nhtd, lookup;
7e24fdf3
DS
275 uint32_t cmd;
276 struct prefix p;
74f0a94e 277 afi_t afi = AFI_IP;
7e24fdf3
DS
278
279 cmd = (reg) ?
280 ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER;
281
282 if (si->nh_registered && reg)
283 return;
284
285 if (!si->nh_registered && !reg)
286 return;
287
288 memset(&p, 0, sizeof(p));
289 switch (si->type) {
7e24fdf3
DS
290 case STATIC_IFNAME:
291 case STATIC_BLACKHOLE:
7e24fdf3
DS
292 return;
293 case STATIC_IPV4_GATEWAY:
88a90016 294 case STATIC_IPV4_GATEWAY_IFNAME:
7e24fdf3
DS
295 p.family = AF_INET;
296 p.prefixlen = IPV4_MAX_BITLEN;
297 p.u.prefix4 = si->addr.ipv4;
74f0a94e 298 afi = AFI_IP;
7e24fdf3
DS
299 break;
300 case STATIC_IPV6_GATEWAY:
88a90016 301 case STATIC_IPV6_GATEWAY_IFNAME:
7e24fdf3
DS
302 p.family = AF_INET6;
303 p.prefixlen = IPV6_MAX_BITLEN;
304 p.u.prefix6 = si->addr.ipv6;
74f0a94e 305 afi = AFI_IP6;
7e24fdf3
DS
306 break;
307 }
308
74f0a94e
DS
309 memset(&lookup, 0, sizeof(lookup));
310 lookup.nh = &p;
31e2232b 311 lookup.nh_vrf_id = si->nh_vrf_id;
74f0a94e
DS
312
313 si->nh_registered = reg;
314
315 if (reg) {
316 nhtd = hash_get(static_nht_hash, &lookup,
317 static_nht_hash_alloc);
318 nhtd->refcount++;
319
320 if (nhtd->refcount > 1) {
321 static_nht_update(nhtd->nh, nhtd->nh_num,
322 afi, si->nh_vrf_id);
323 return;
324 }
325 } else {
326 nhtd = hash_lookup(static_nht_hash, &lookup);
327 if (!nhtd)
328 return;
329
330 nhtd->refcount--;
331 if (nhtd->refcount >= 1)
332 return;
333
334 hash_release(static_nht_hash, nhtd);
335 static_nht_hash_free(nhtd);
336 }
337
7e24fdf3
DS
338 if (zclient_send_rnh(zclient, cmd, &p, false, si->nh_vrf_id) < 0)
339 zlog_warn("%s: Failure to send nexthop to zebra",
340 __PRETTY_FUNCTION__);
7e24fdf3
DS
341}
342
8bc8de2c
DS
343extern void static_zebra_route_add(struct route_node *rn,
344 struct static_route *si_changed,
345 vrf_id_t vrf_id, safi_t safi, bool install)
7e24fdf3
DS
346{
347 struct static_route *si = rn->info;
348 const struct prefix *p, *src_pp;
349 struct zapi_nexthop *api_nh;
350 struct zapi_route api;
351 uint32_t nh_num = 0;
352
353 p = src_pp = NULL;
354 srcdest_rnode_prefixes(rn, &p, &src_pp);
355
356 memset(&api, 0, sizeof(api));
357 api.vrf_id = vrf_id;
358 api.type = ZEBRA_ROUTE_STATIC;
359 api.safi = safi;
360 memcpy(&api.prefix, p, sizeof(api.prefix));
361
362 if (src_pp) {
363 SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
364 memcpy(&api.src_prefix, src_pp, sizeof(api.src_prefix));
365 }
8bc8de2c 366 SET_FLAG(api.flags, ZEBRA_FLAG_RR_USE_DISTANCE);
7e24fdf3 367 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
8bc8de2c
DS
368 if (si_changed->distance) {
369 SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
370 api.distance = si_changed->distance;
371 }
372 if (si_changed->tag) {
373 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
374 api.tag = si_changed->tag;
375 }
31d4a8e5
PG
376 if (si_changed->table_id != 0) {
377 SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
378 api.tableid = si_changed->table_id;
379 }
7e24fdf3
DS
380 for (/*loaded above*/; si; si = si->next) {
381 api_nh = &api.nexthops[nh_num];
382 if (si->nh_vrf_id == VRF_UNKNOWN)
383 continue;
384
8bc8de2c
DS
385 if (si->distance != si_changed->distance)
386 continue;
7e24fdf3
DS
387
388 api_nh->vrf_id = si->nh_vrf_id;
389 switch (si->type) {
390 case STATIC_IFNAME:
391 if (si->ifindex == IFINDEX_INTERNAL)
392 continue;
393 api_nh->ifindex = si->ifindex;
394 api_nh->type = NEXTHOP_TYPE_IFINDEX;
395 break;
396 case STATIC_IPV4_GATEWAY:
397 if (!si->nh_valid)
398 continue;
399 api_nh->type = NEXTHOP_TYPE_IPV4;
400 api_nh->gate = si->addr;
401 break;
402 case STATIC_IPV4_GATEWAY_IFNAME:
403 if (si->ifindex == IFINDEX_INTERNAL)
404 continue;
405 api_nh->ifindex = si->ifindex;
406 api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
407 api_nh->gate = si->addr;
408 break;
409 case STATIC_IPV6_GATEWAY:
410 if (!si->nh_valid)
411 continue;
412 api_nh->type = NEXTHOP_TYPE_IPV6;
413 api_nh->gate = si->addr;
414 break;
415 case STATIC_IPV6_GATEWAY_IFNAME:
416 if (si->ifindex == IFINDEX_INTERNAL)
417 continue;
418 api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
419 api_nh->ifindex = si->ifindex;
420 api_nh->gate = si->addr;
421 break;
422 case STATIC_BLACKHOLE:
423 api_nh->type = NEXTHOP_TYPE_BLACKHOLE;
424 switch (si->bh_type) {
425 case STATIC_BLACKHOLE_DROP:
426 case STATIC_BLACKHOLE_NULL:
427 api_nh->bh_type = BLACKHOLE_NULL;
428 break;
429 case STATIC_BLACKHOLE_REJECT:
430 api_nh->bh_type = BLACKHOLE_REJECT;
431 }
432 break;
433 }
434
435 if (si->snh_label.num_labels) {
436 int i;
437
438 SET_FLAG(api.message, ZAPI_MESSAGE_LABEL);
439 api_nh->label_num = si->snh_label.num_labels;
440 for (i = 0; i < api_nh->label_num; i++)
441 api_nh->labels[i] = si->snh_label.label[i];
442 }
443 nh_num++;
444 }
445
446 api.nexthop_num = nh_num;
447
448 /*
449 * If we have been given an install but nothing is valid
450 * go ahead and delete the route for double plus fun
451 */
452 if (!nh_num && install)
453 install = false;
454
455 zclient_route_send(install ?
456 ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
457 zclient, &api);
458}
459void static_zebra_init(void)
460{
461 struct zclient_options opt = { .receive_notify = true };
462
463 zclient = zclient_new_notify(master, &opt);
464
465 zclient_init(zclient, ZEBRA_ROUTE_STATIC, 0, &static_privs);
466 zclient->zebra_capabilities = static_zebra_capabilities;
467 zclient->zebra_connected = zebra_connected;
468 zclient->interface_add = interface_add;
469 zclient->interface_delete = interface_delete;
470 zclient->interface_up = interface_state_up;
471 zclient->interface_down = interface_state_down;
472 zclient->interface_address_add = interface_address_add;
473 zclient->interface_address_delete = interface_address_delete;
474 zclient->route_notify_owner = route_notify_owner;
475 zclient->nexthop_update = static_zebra_nexthop_update;
74f0a94e
DS
476
477 static_nht_hash = hash_create(static_nht_hash_key,
478 static_nht_hash_cmp,
479 "Static Nexthop Tracking hash");
7e24fdf3 480}