]> git.proxmox.com Git - mirror_frr.git/blob - staticd/static_zebra.c
Merge pull request #10017 from AnuradhaKaruppiah/evpn-pim-register
[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 #include "hash.h"
38 #include "jhash.h"
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 #include "static_debug.h"
46
47 /* Zebra structure to hold current status. */
48 struct zclient *zclient;
49 static struct hash *static_nht_hash;
50
51 /* Inteface addition message from zebra. */
52 static int static_ifp_create(struct interface *ifp)
53 {
54 static_ifindex_update(ifp, true);
55
56 return 0;
57 }
58
59 static int static_ifp_destroy(struct interface *ifp)
60 {
61 static_ifindex_update(ifp, false);
62 return 0;
63 }
64
65 static int interface_address_add(ZAPI_CALLBACK_ARGS)
66 {
67 zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
68
69 return 0;
70 }
71
72 static int interface_address_delete(ZAPI_CALLBACK_ARGS)
73 {
74 struct connected *c;
75
76 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
77
78 if (!c)
79 return 0;
80
81 connected_free(&c);
82 return 0;
83 }
84
85 static int static_ifp_up(struct interface *ifp)
86 {
87 /* Install any static reliant on this interface coming up */
88 static_install_intf_nh(ifp);
89 static_ifindex_update(ifp, true);
90
91 return 0;
92 }
93
94 static int static_ifp_down(struct interface *ifp)
95 {
96 static_ifindex_update(ifp, false);
97
98 return 0;
99 }
100
101 static int route_notify_owner(ZAPI_CALLBACK_ARGS)
102 {
103 struct prefix p;
104 enum zapi_route_notify_owner note;
105 uint32_t table_id;
106
107 if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, &note,
108 NULL, NULL))
109 return -1;
110
111 switch (note) {
112 case ZAPI_ROUTE_FAIL_INSTALL:
113 static_nht_mark_state(&p, vrf_id, STATIC_NOT_INSTALLED);
114 zlog_warn("%s: Route %pFX failed to install for table: %u",
115 __func__, &p, table_id);
116 break;
117 case ZAPI_ROUTE_BETTER_ADMIN_WON:
118 static_nht_mark_state(&p, vrf_id, STATIC_NOT_INSTALLED);
119 zlog_warn(
120 "%s: Route %pFX over-ridden by better route for table: %u",
121 __func__, &p, table_id);
122 break;
123 case ZAPI_ROUTE_INSTALLED:
124 static_nht_mark_state(&p, vrf_id, STATIC_INSTALLED);
125 break;
126 case ZAPI_ROUTE_REMOVED:
127 static_nht_mark_state(&p, vrf_id, STATIC_NOT_INSTALLED);
128 break;
129 case ZAPI_ROUTE_REMOVE_FAIL:
130 static_nht_mark_state(&p, vrf_id, STATIC_INSTALLED);
131 zlog_warn("%s: Route %pFX failure to remove for table: %u",
132 __func__, &p, table_id);
133 break;
134 }
135
136 return 0;
137 }
138 static void zebra_connected(struct zclient *zclient)
139 {
140 zclient_send_reg_requests(zclient, VRF_DEFAULT);
141 }
142
143 struct static_nht_data {
144 struct prefix *nh;
145
146 vrf_id_t nh_vrf_id;
147
148 uint32_t refcount;
149 uint8_t nh_num;
150 };
151
152 /* API to check whether the configured nexthop address is
153 * one of its local connected address or not.
154 */
155 static bool
156 static_nexthop_is_local(vrf_id_t vrfid, struct prefix *addr, int family)
157 {
158 if (family == AF_INET) {
159 if (if_address_is_local(&addr->u.prefix4, AF_INET, vrfid))
160 return true;
161 } else if (family == AF_INET6) {
162 if (if_address_is_local(&addr->u.prefix6, AF_INET6, vrfid))
163 return true;
164 }
165 return false;
166 }
167 static int static_zebra_nexthop_update(ZAPI_CALLBACK_ARGS)
168 {
169 struct static_nht_data *nhtd, lookup;
170 struct zapi_route nhr;
171 afi_t afi = AFI_IP;
172
173 if (!zapi_nexthop_update_decode(zclient->ibuf, &nhr)) {
174 zlog_err("Failure to decode nexthop update message");
175 return 1;
176 }
177
178 if (nhr.prefix.family == AF_INET6)
179 afi = AFI_IP6;
180
181 if (nhr.type == ZEBRA_ROUTE_CONNECT) {
182 if (static_nexthop_is_local(vrf_id, &nhr.prefix,
183 nhr.prefix.family))
184 nhr.nexthop_num = 0;
185 }
186
187 memset(&lookup, 0, sizeof(lookup));
188 lookup.nh = &nhr.prefix;
189 lookup.nh_vrf_id = vrf_id;
190
191 nhtd = hash_lookup(static_nht_hash, &lookup);
192
193 if (nhtd) {
194 nhtd->nh_num = nhr.nexthop_num;
195
196 static_nht_reset_start(&nhr.prefix, afi, nhtd->nh_vrf_id);
197 static_nht_update(NULL, &nhr.prefix, nhr.nexthop_num, afi,
198 nhtd->nh_vrf_id);
199 } else
200 zlog_err("No nhtd?");
201
202 return 1;
203 }
204
205 static void static_zebra_capabilities(struct zclient_capabilities *cap)
206 {
207 mpls_enabled = cap->mpls_enabled;
208 }
209
210 static unsigned int static_nht_hash_key(const void *data)
211 {
212 const struct static_nht_data *nhtd = data;
213 unsigned int key = 0;
214
215 key = prefix_hash_key(nhtd->nh);
216 return jhash_1word(nhtd->nh_vrf_id, key);
217 }
218
219 static bool static_nht_hash_cmp(const void *d1, const void *d2)
220 {
221 const struct static_nht_data *nhtd1 = d1;
222 const struct static_nht_data *nhtd2 = d2;
223
224 if (nhtd1->nh_vrf_id != nhtd2->nh_vrf_id)
225 return false;
226
227 return prefix_same(nhtd1->nh, nhtd2->nh);
228 }
229
230 static void *static_nht_hash_alloc(void *data)
231 {
232 struct static_nht_data *copy = data;
233 struct static_nht_data *new;
234
235 new = XMALLOC(MTYPE_TMP, sizeof(*new));
236
237 new->nh = prefix_new();
238 prefix_copy(new->nh, copy->nh);
239 new->refcount = 0;
240 new->nh_num = 0;
241 new->nh_vrf_id = copy->nh_vrf_id;
242
243 return new;
244 }
245
246 static void static_nht_hash_free(void *data)
247 {
248 struct static_nht_data *nhtd = data;
249
250 prefix_free(&nhtd->nh);
251 XFREE(MTYPE_TMP, nhtd);
252 }
253
254 void static_zebra_nht_register(struct static_nexthop *nh, bool reg)
255 {
256 struct static_path *pn = nh->pn;
257 struct route_node *rn = pn->rn;
258 struct static_nht_data *nhtd, lookup;
259 uint32_t cmd;
260 struct prefix p;
261 afi_t afi = AFI_IP;
262
263 cmd = (reg) ?
264 ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER;
265
266 if (nh->nh_registered && reg)
267 return;
268
269 if (!nh->nh_registered && !reg)
270 return;
271
272 memset(&p, 0, sizeof(p));
273 switch (nh->type) {
274 case STATIC_IFNAME:
275 case STATIC_BLACKHOLE:
276 return;
277 case STATIC_IPV4_GATEWAY:
278 case STATIC_IPV4_GATEWAY_IFNAME:
279 p.family = AF_INET;
280 p.prefixlen = IPV4_MAX_BITLEN;
281 p.u.prefix4 = nh->addr.ipv4;
282 afi = AFI_IP;
283 break;
284 case STATIC_IPV6_GATEWAY:
285 case STATIC_IPV6_GATEWAY_IFNAME:
286 p.family = AF_INET6;
287 p.prefixlen = IPV6_MAX_BITLEN;
288 p.u.prefix6 = nh->addr.ipv6;
289 afi = AFI_IP6;
290 break;
291 }
292
293 memset(&lookup, 0, sizeof(lookup));
294 lookup.nh = &p;
295 lookup.nh_vrf_id = nh->nh_vrf_id;
296
297 nh->nh_registered = reg;
298
299 if (reg) {
300 nhtd = hash_get(static_nht_hash, &lookup,
301 static_nht_hash_alloc);
302 nhtd->refcount++;
303
304 DEBUGD(&static_dbg_route,
305 "Registered nexthop(%pFX) for %pRN %d", &p, rn,
306 nhtd->nh_num);
307 if (nhtd->refcount > 1 && nhtd->nh_num) {
308 static_nht_update(&rn->p, nhtd->nh, nhtd->nh_num, afi,
309 nh->nh_vrf_id);
310 return;
311 }
312 } else {
313 nhtd = hash_lookup(static_nht_hash, &lookup);
314 if (!nhtd)
315 return;
316
317 nhtd->refcount--;
318 if (nhtd->refcount >= 1)
319 return;
320
321 hash_release(static_nht_hash, nhtd);
322 static_nht_hash_free(nhtd);
323 }
324
325 if (zclient_send_rnh(zclient, cmd, &p, false, false, nh->nh_vrf_id)
326 == ZCLIENT_SEND_FAILURE)
327 zlog_warn("%s: Failure to send nexthop to zebra", __func__);
328 }
329 /*
330 * When nexthop gets updated via configuration then use the
331 * already registered NH and resend the route to zebra
332 */
333 int static_zebra_nh_update(struct static_nexthop *nh)
334 {
335 struct static_path *pn = nh->pn;
336 struct route_node *rn = pn->rn;
337 struct static_nht_data *nhtd, lookup = {};
338 struct prefix p = {};
339 afi_t afi = AFI_IP;
340
341 if (!nh->nh_registered)
342 return 0;
343
344 switch (nh->type) {
345 case STATIC_IFNAME:
346 case STATIC_BLACKHOLE:
347 return 0;
348 case STATIC_IPV4_GATEWAY:
349 case STATIC_IPV4_GATEWAY_IFNAME:
350 p.family = AF_INET;
351 p.prefixlen = IPV4_MAX_BITLEN;
352 p.u.prefix4 = nh->addr.ipv4;
353 afi = AFI_IP;
354 break;
355 case STATIC_IPV6_GATEWAY:
356 case STATIC_IPV6_GATEWAY_IFNAME:
357 p.family = AF_INET6;
358 p.prefixlen = IPV6_MAX_BITLEN;
359 p.u.prefix6 = nh->addr.ipv6;
360 afi = AFI_IP6;
361 break;
362 }
363
364 lookup.nh = &p;
365 lookup.nh_vrf_id = nh->nh_vrf_id;
366
367 nhtd = hash_lookup(static_nht_hash, &lookup);
368 if (nhtd && nhtd->nh_num) {
369 nh->state = STATIC_START;
370 static_nht_update(&rn->p, nhtd->nh, nhtd->nh_num, afi,
371 nh->nh_vrf_id);
372 return 1;
373 }
374 return 0;
375 }
376
377 extern void static_zebra_route_add(struct static_path *pn, bool install)
378 {
379 struct route_node *rn = pn->rn;
380 struct static_route_info *si = rn->info;
381 struct static_nexthop *nh;
382 const struct prefix *p, *src_pp;
383 struct zapi_nexthop *api_nh;
384 struct zapi_route api;
385 uint32_t nh_num = 0;
386
387 p = src_pp = NULL;
388 srcdest_rnode_prefixes(rn, &p, &src_pp);
389
390 memset(&api, 0, sizeof(api));
391 api.vrf_id = si->svrf->vrf->vrf_id;
392 api.type = ZEBRA_ROUTE_STATIC;
393 api.safi = si->safi;
394 memcpy(&api.prefix, p, sizeof(api.prefix));
395
396 if (src_pp) {
397 SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
398 memcpy(&api.src_prefix, src_pp, sizeof(api.src_prefix));
399 }
400 SET_FLAG(api.flags, ZEBRA_FLAG_RR_USE_DISTANCE);
401 SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
402 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
403 if (pn->distance) {
404 SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
405 api.distance = pn->distance;
406 }
407 if (pn->tag) {
408 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
409 api.tag = pn->tag;
410 }
411 if (pn->table_id != 0) {
412 SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
413 api.tableid = pn->table_id;
414 }
415 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
416 api_nh = &api.nexthops[nh_num];
417 if (nh->nh_vrf_id == VRF_UNKNOWN)
418 continue;
419
420 api_nh->vrf_id = nh->nh_vrf_id;
421 if (nh->onlink)
422 SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK);
423 if (nh->color != 0) {
424 SET_FLAG(api.message, ZAPI_MESSAGE_SRTE);
425 api_nh->srte_color = nh->color;
426 }
427
428 nh->state = STATIC_SENT_TO_ZEBRA;
429
430 switch (nh->type) {
431 case STATIC_IFNAME:
432 if (nh->ifindex == IFINDEX_INTERNAL)
433 continue;
434 api_nh->ifindex = nh->ifindex;
435 api_nh->type = NEXTHOP_TYPE_IFINDEX;
436 break;
437 case STATIC_IPV4_GATEWAY:
438 if (!nh->nh_valid)
439 continue;
440 api_nh->type = NEXTHOP_TYPE_IPV4;
441 api_nh->gate = nh->addr;
442 break;
443 case STATIC_IPV4_GATEWAY_IFNAME:
444 if (nh->ifindex == IFINDEX_INTERNAL)
445 continue;
446 api_nh->ifindex = nh->ifindex;
447 api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
448 api_nh->gate = nh->addr;
449 break;
450 case STATIC_IPV6_GATEWAY:
451 if (!nh->nh_valid)
452 continue;
453 api_nh->type = NEXTHOP_TYPE_IPV6;
454 api_nh->gate = nh->addr;
455 break;
456 case STATIC_IPV6_GATEWAY_IFNAME:
457 if (nh->ifindex == IFINDEX_INTERNAL)
458 continue;
459 api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
460 api_nh->ifindex = nh->ifindex;
461 api_nh->gate = nh->addr;
462 break;
463 case STATIC_BLACKHOLE:
464 api_nh->type = NEXTHOP_TYPE_BLACKHOLE;
465 switch (nh->bh_type) {
466 case STATIC_BLACKHOLE_DROP:
467 case STATIC_BLACKHOLE_NULL:
468 api_nh->bh_type = BLACKHOLE_NULL;
469 break;
470 case STATIC_BLACKHOLE_REJECT:
471 api_nh->bh_type = BLACKHOLE_REJECT;
472 }
473 break;
474 }
475
476 if (nh->snh_label.num_labels) {
477 int i;
478
479 SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL);
480 api_nh->label_num = nh->snh_label.num_labels;
481 for (i = 0; i < api_nh->label_num; i++)
482 api_nh->labels[i] = nh->snh_label.label[i];
483 }
484 nh_num++;
485 }
486
487 api.nexthop_num = nh_num;
488
489 /*
490 * If we have been given an install but nothing is valid
491 * go ahead and delete the route for double plus fun
492 */
493 if (!nh_num && install)
494 install = false;
495
496 zclient_route_send(install ?
497 ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
498 zclient, &api);
499 }
500
501 static zclient_handler *const static_handlers[] = {
502 [ZEBRA_INTERFACE_ADDRESS_ADD] = interface_address_add,
503 [ZEBRA_INTERFACE_ADDRESS_DELETE] = interface_address_delete,
504 [ZEBRA_ROUTE_NOTIFY_OWNER] = route_notify_owner,
505 [ZEBRA_NEXTHOP_UPDATE] = static_zebra_nexthop_update,
506 };
507
508 void static_zebra_init(void)
509 {
510 struct zclient_options opt = { .receive_notify = true };
511
512 if_zapi_callbacks(static_ifp_create, static_ifp_up,
513 static_ifp_down, static_ifp_destroy);
514
515 zclient = zclient_new(master, &opt, static_handlers,
516 array_size(static_handlers));
517
518 zclient_init(zclient, ZEBRA_ROUTE_STATIC, 0, &static_privs);
519 zclient->zebra_capabilities = static_zebra_capabilities;
520 zclient->zebra_connected = zebra_connected;
521
522 static_nht_hash = hash_create(static_nht_hash_key,
523 static_nht_hash_cmp,
524 "Static Nexthop Tracking hash");
525 }
526
527 /* static_zebra_stop used by tests/lib/test_grpc.cpp */
528 void static_zebra_stop(void)
529 {
530 if (!zclient)
531 return;
532 zclient_stop(zclient);
533 zclient_free(zclient);
534 zclient = NULL;
535 }
536
537 void static_zebra_vrf_register(struct vrf *vrf)
538 {
539 if (vrf->vrf_id == VRF_DEFAULT)
540 return;
541 zclient_send_reg_requests(zclient, vrf->vrf_id);
542 }
543
544 void static_zebra_vrf_unregister(struct vrf *vrf)
545 {
546 if (vrf->vrf_id == VRF_DEFAULT)
547 return;
548 zclient_send_dereg_requests(zclient, vrf->vrf_id);
549 }