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