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