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