]> git.proxmox.com Git - mirror_frr.git/blame - sharpd/sharp_zebra.c
zebra: skip un-installed recursive match
[mirror_frr.git] / sharpd / sharp_zebra.c
CommitLineData
8a71d93d
DS
1/*
2 * Zebra connect code.
3 * Copyright (C) Cumulus Networks, Inc.
4 * Donald Sharp
5 *
6 * This file is part of FRR.
7 *
8 * FRR is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * FRR is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22#include <zebra.h>
23
24#include "thread.h"
25#include "command.h"
26#include "network.h"
27#include "prefix.h"
8a71d93d
DS
28#include "stream.h"
29#include "memory.h"
30#include "zclient.h"
8a71d93d 31#include "nexthop.h"
694b242f 32#include "nexthop_group.h"
8a71d93d 33
547dc642 34#include "sharp_globals.h"
86da53ab 35#include "sharp_nht.h"
8a71d93d
DS
36#include "sharp_zebra.h"
37
38/* Zebra structure to hold current status. */
39struct zclient *zclient = NULL;
40
41/* For registering threads. */
2be4d61a 42struct thread_master *master;
8a71d93d 43
2be4d61a
MS
44/* Privs info */
45struct zebra_privs_t sharp_privs;
46
47DEFINE_MTYPE_STATIC(SHARPD, ZC, "Test zclients");
48
49/* Struct to hold list of test zclients */
50struct sharp_zclient {
51 struct sharp_zclient *prev;
52 struct sharp_zclient *next;
53 struct zclient *client;
54};
55
56/* Head of test zclient list */
57static struct sharp_zclient *sharp_clients_head;
58
59static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS);
60
61/* Utility to add a test zclient struct to the list */
62static void add_zclient(struct zclient *client)
63{
64 struct sharp_zclient *node;
65
66 node = XCALLOC(MTYPE_ZC, sizeof(struct sharp_zclient));
67
68 node->client = client;
69
70 node->next = sharp_clients_head;
71 if (sharp_clients_head)
72 sharp_clients_head->prev = node;
73 sharp_clients_head = node;
74}
75
76/* Interface addition message from zebra. */
ef7bd2a3 77static int sharp_ifp_create(struct interface *ifp)
8a71d93d 78{
8a71d93d
DS
79 return 0;
80}
81
3c3c3252 82static int sharp_ifp_destroy(struct interface *ifp)
8a71d93d 83{
8a71d93d
DS
84 return 0;
85}
86
121f9dee 87static int interface_address_add(ZAPI_CALLBACK_ARGS)
8a71d93d 88{
121f9dee 89 zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
8a71d93d
DS
90
91 return 0;
92}
93
121f9dee 94static int interface_address_delete(ZAPI_CALLBACK_ARGS)
8a71d93d
DS
95{
96 struct connected *c;
97
121f9dee 98 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
8a71d93d
DS
99
100 if (!c)
101 return 0;
102
721c0857 103 connected_free(&c);
8a71d93d
DS
104 return 0;
105}
106
ddbf3e60 107static int sharp_ifp_up(struct interface *ifp)
8a71d93d 108{
8a71d93d
DS
109 return 0;
110}
111
b0b69e59 112static int sharp_ifp_down(struct interface *ifp)
8a71d93d 113{
8a71d93d
DS
114 return 0;
115}
116
c9e5adba
MS
117int sharp_install_lsps_helper(bool install_p, const struct prefix *p,
118 uint8_t type, int instance, uint32_t in_label,
665edffd
MS
119 const struct nexthop_group *nhg,
120 const struct nexthop_group *backup_nhg)
c9e5adba
MS
121{
122 struct zapi_labels zl = {};
123 struct zapi_nexthop *znh;
124 const struct nexthop *nh;
125 int i, ret;
126
127 zl.type = ZEBRA_LSP_SHARP;
128 zl.local_label = in_label;
129
130 if (p) {
131 SET_FLAG(zl.message, ZAPI_LABELS_FTN);
132 prefix_copy(&zl.route.prefix, p);
133 zl.route.type = type;
134 zl.route.instance = instance;
135 }
136
665edffd 137 /* List of nexthops is optional for delete */
c9e5adba 138 i = 0;
665edffd
MS
139 if (nhg) {
140 for (ALL_NEXTHOPS_PTR(nhg, nh)) {
141 znh = &zl.nexthops[i];
142
143 /* Must have labels to be useful */
144 if (nh->nh_label == NULL ||
145 nh->nh_label->num_labels == 0)
146 continue;
147
148 if (nh->type == NEXTHOP_TYPE_IFINDEX ||
149 nh->type == NEXTHOP_TYPE_BLACKHOLE)
150 /* Hmm - can't really deal with these types */
151 continue;
152
153 ret = zapi_nexthop_from_nexthop(znh, nh);
154 if (ret < 0)
155 return -1;
156
157 i++;
158 }
159 }
c9e5adba 160
665edffd
MS
161 /* Whoops - no nexthops isn't very useful for install */
162 if (i == 0 && install_p)
163 return -1;
c9e5adba 164
665edffd 165 zl.nexthop_num = i;
c9e5adba 166
665edffd
MS
167 /* Add optional backup nexthop info. Since these are used by index,
168 * we can't just skip over an invalid backup nexthop: we will
169 * invalidate the entire operation.
170 */
171 if (backup_nhg != NULL) {
172 i = 0;
173 for (ALL_NEXTHOPS_PTR(backup_nhg, nh)) {
174 znh = &zl.backup_nexthops[i];
c9e5adba 175
665edffd
MS
176 /* Must have labels to be useful */
177 if (nh->nh_label == NULL ||
178 nh->nh_label->num_labels == 0)
179 return -1;
c9e5adba 180
665edffd
MS
181 if (nh->type == NEXTHOP_TYPE_IFINDEX ||
182 nh->type == NEXTHOP_TYPE_BLACKHOLE)
183 /* Hmm - can't really deal with these types */
184 return -1;
c9e5adba 185
665edffd
MS
186 ret = zapi_nexthop_from_nexthop(znh, nh);
187 if (ret < 0)
188 return -1;
189
190 i++;
191 }
192
193 if (i > 0)
194 SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS);
195
196 zl.backup_nexthop_num = i;
197 }
c9e5adba
MS
198
199 if (install_p)
200 ret = zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_ADD,
201 &zl);
202 else
203 ret = zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_DELETE,
204 &zl);
205
206 return ret;
207}
208
0cf08685 209void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id,
1df3b1dc
MS
210 uint8_t instance,
211 const struct nexthop_group *nhg,
212 const struct nexthop_group *backup_nhg,
6b98d34f
DS
213 uint32_t routes)
214{
215 uint32_t temp, i;
dbc1bf46 216 bool v4 = false;
6b98d34f
DS
217
218 zlog_debug("Inserting %u routes", routes);
219
dbc1bf46
DS
220 if (p->family == AF_INET) {
221 v4 = true;
222 temp = ntohl(p->u.prefix4.s_addr);
223 } else
224 temp = ntohl(p->u.val32[3]);
225
1df3b1dc
MS
226 /* Only use backup route/nexthops if present */
227 if (backup_nhg && (backup_nhg->nexthop == NULL))
228 backup_nhg = NULL;
229
547dc642 230 monotime(&sg.r.t_start);
6b98d34f 231 for (i = 0; i < routes; i++) {
1df3b1dc 232 route_add(p, vrf_id, (uint8_t)instance, nhg, backup_nhg);
dbc1bf46
DS
233 if (v4)
234 p->u.prefix4.s_addr = htonl(++temp);
235 else
236 p->u.val32[3] = htonl(++temp);
6b98d34f
DS
237 }
238}
239
0cf08685
DS
240void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id,
241 uint8_t instance, uint32_t routes)
6b98d34f
DS
242{
243 uint32_t temp, i;
dbc1bf46 244 bool v4 = false;
6b98d34f
DS
245
246 zlog_debug("Removing %u routes", routes);
247
dbc1bf46
DS
248 if (p->family == AF_INET) {
249 v4 = true;
250 temp = ntohl(p->u.prefix4.s_addr);
251 } else
252 temp = ntohl(p->u.val32[3]);
253
547dc642 254 monotime(&sg.r.t_start);
6b98d34f 255 for (i = 0; i < routes; i++) {
0cf08685 256 route_delete(p, vrf_id, (uint8_t)instance);
dbc1bf46
DS
257 if (v4)
258 p->u.prefix4.s_addr = htonl(++temp);
259 else
260 p->u.val32[3] = htonl(++temp);
6b98d34f
DS
261 }
262}
263
b939f6ff 264static void handle_repeated(bool installed)
6b98d34f 265{
547dc642
DS
266 struct prefix p = sg.r.orig_prefix;
267 sg.r.repeat--;
6b98d34f 268
547dc642 269 if (sg.r.repeat <= 0)
6b98d34f
DS
270 return;
271
272 if (installed) {
547dc642 273 sg.r.removed_routes = 0;
0cf08685
DS
274 sharp_remove_routes_helper(&p, sg.r.vrf_id,
275 sg.r.inst, sg.r.total_routes);
6b98d34f
DS
276 }
277
f54f37c1 278 if (!installed) {
547dc642 279 sg.r.installed_routes = 0;
0cf08685
DS
280 sharp_install_routes_helper(&p, sg.r.vrf_id, sg.r.inst,
281 &sg.r.nhop_group,
1df3b1dc 282 &sg.r.backup_nhop_group,
547dc642 283 sg.r.total_routes);
6b98d34f
DS
284 }
285}
286
121f9dee 287static int route_notify_owner(ZAPI_CALLBACK_ARGS)
8a71d93d 288{
25c84d86 289 struct timeval r;
8a71d93d
DS
290 struct prefix p;
291 enum zapi_route_notify_owner note;
28610f7e 292 uint32_t table;
8a71d93d 293
28610f7e 294 if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, &note))
8a71d93d
DS
295 return -1;
296
5e54c602
DS
297 switch (note) {
298 case ZAPI_ROUTE_INSTALLED:
547dc642
DS
299 sg.r.installed_routes++;
300 if (sg.r.total_routes == sg.r.installed_routes) {
301 monotime(&sg.r.t_end);
302 timersub(&sg.r.t_end, &sg.r.t_start, &r);
051a0be4
DL
303 zlog_debug("Installed All Items %jd.%ld",
304 (intmax_t)r.tv_sec, (long)r.tv_usec);
6b98d34f
DS
305 handle_repeated(true);
306 }
5e54c602
DS
307 break;
308 case ZAPI_ROUTE_FAIL_INSTALL:
309 zlog_debug("Failed install of route");
310 break;
311 case ZAPI_ROUTE_BETTER_ADMIN_WON:
312 zlog_debug("Better Admin Distance won over us");
313 break;
314 case ZAPI_ROUTE_REMOVED:
547dc642
DS
315 sg.r.removed_routes++;
316 if (sg.r.total_routes == sg.r.removed_routes) {
317 monotime(&sg.r.t_end);
318 timersub(&sg.r.t_end, &sg.r.t_start, &r);
051a0be4
DL
319 zlog_debug("Removed all Items %jd.%ld",
320 (intmax_t)r.tv_sec, (long)r.tv_usec);
6b98d34f
DS
321 handle_repeated(false);
322 }
5e54c602
DS
323 break;
324 case ZAPI_ROUTE_REMOVE_FAIL:
325 zlog_debug("Route removal Failure");
326 break;
327 }
8a71d93d
DS
328 return 0;
329}
330
331static void zebra_connected(struct zclient *zclient)
332{
333 zclient_send_reg_requests(zclient, VRF_DEFAULT);
67a9eda9
DS
334
335 /*
336 * Do not actually turn this on yet
337 * This is just the start of the infrastructure needed here
338 * This can be fixed at a later time.
339 *
340 * zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP,
341 * ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
342 */
8a71d93d
DS
343}
344
7d061b3c 345void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label)
ab18a495 346{
7d061b3c 347 zclient_send_vrf_label(zclient, vrf_id, afi, label, ZEBRA_LSP_SHARP);
ab18a495
DS
348}
349
1df3b1dc
MS
350void route_add(const struct prefix *p, vrf_id_t vrf_id,
351 uint8_t instance, const struct nexthop_group *nhg,
352 const struct nexthop_group *backup_nhg)
8a71d93d
DS
353{
354 struct zapi_route api;
355 struct zapi_nexthop *api_nh;
694b242f
DS
356 struct nexthop *nh;
357 int i = 0;
8a71d93d
DS
358
359 memset(&api, 0, sizeof(api));
0cf08685 360 api.vrf_id = vrf_id;
8a71d93d 361 api.type = ZEBRA_ROUTE_SHARP;
ae252c02 362 api.instance = instance;
8a71d93d
DS
363 api.safi = SAFI_UNICAST;
364 memcpy(&api.prefix, p, sizeof(*p));
365
a3896844 366 SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
8a71d93d
DS
367 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
368
694b242f
DS
369 for (ALL_NEXTHOPS_PTR(nhg, nh)) {
370 api_nh = &api.nexthops[i];
054af19a 371
c9e5adba 372 zapi_nexthop_from_nexthop(api_nh, nh);
1df3b1dc 373
694b242f
DS
374 i++;
375 }
376 api.nexthop_num = i;
8a71d93d 377
1df3b1dc
MS
378 /* Include backup nexthops, if present */
379 if (backup_nhg && backup_nhg->nexthop) {
380 SET_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS);
381
382 i = 0;
383 for (ALL_NEXTHOPS_PTR(backup_nhg, nh)) {
384 api_nh = &api.backup_nexthops[i];
385
386 zapi_backup_nexthop_from_nexthop(api_nh, nh);
387
388 i++;
389 }
390
391 api.backup_nexthop_num = i;
392 }
393
8a71d93d
DS
394 zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
395}
396
0cf08685 397void route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance)
8a71d93d
DS
398{
399 struct zapi_route api;
400
401 memset(&api, 0, sizeof(api));
0cf08685 402 api.vrf_id = vrf_id;
8a71d93d
DS
403 api.type = ZEBRA_ROUTE_SHARP;
404 api.safi = SAFI_UNICAST;
ae252c02 405 api.instance = instance;
8a71d93d
DS
406 memcpy(&api.prefix, p, sizeof(*p));
407 zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
408
409 return;
410}
411
91529dc8 412void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import,
b47dc61a 413 bool watch, bool connected)
0ae8130d 414{
b47dc61a 415 int command;
0ae8130d 416
b47dc61a
DS
417 if (!import) {
418 command = ZEBRA_NEXTHOP_REGISTER;
419
420 if (!watch)
421 command = ZEBRA_NEXTHOP_UNREGISTER;
422 } else {
423 command = ZEBRA_IMPORT_ROUTE_REGISTER;
424
425 if (!watch)
426 command = ZEBRA_IMPORT_ROUTE_UNREGISTER;
427 }
0ae8130d 428
91529dc8 429 if (zclient_send_rnh(zclient, command, p, connected, vrf_id) < 0)
15569c58 430 zlog_warn("%s: Failure to send nexthop to zebra", __func__);
0ae8130d
DS
431}
432
67a9eda9 433static int sharp_debug_nexthops(struct zapi_route *api)
0ae8130d 434{
0ae8130d 435 int i;
67a9eda9 436 char buf[PREFIX_STRLEN];
0ae8130d 437
67a9eda9
DS
438 for (i = 0; i < api->nexthop_num; i++) {
439 struct zapi_nexthop *znh = &api->nexthops[i];
0ae8130d
DS
440
441 switch (znh->type) {
442 case NEXTHOP_TYPE_IPV4_IFINDEX:
443 case NEXTHOP_TYPE_IPV4:
444 zlog_debug(
d6951e5e 445 " Nexthop %s, type: %d, ifindex: %d, vrf: %d, label_num: %d",
0ae8130d
DS
446 inet_ntop(AF_INET, &znh->gate.ipv4.s_addr, buf,
447 sizeof(buf)),
448 znh->type, znh->ifindex, znh->vrf_id,
449 znh->label_num);
450 break;
451 case NEXTHOP_TYPE_IPV6_IFINDEX:
452 case NEXTHOP_TYPE_IPV6:
453 zlog_debug(
d6951e5e 454 " Nexthop %s, type: %d, ifindex: %d, vrf: %d, label_num: %d",
0ae8130d
DS
455 inet_ntop(AF_INET6, &znh->gate.ipv6, buf,
456 sizeof(buf)),
457 znh->type, znh->ifindex, znh->vrf_id,
458 znh->label_num);
459 break;
460 case NEXTHOP_TYPE_IFINDEX:
d6951e5e 461 zlog_debug(" Nexthop IFINDEX: %d, ifindex: %d",
0ae8130d
DS
462 znh->type, znh->ifindex);
463 break;
464 case NEXTHOP_TYPE_BLACKHOLE:
d6951e5e 465 zlog_debug(" Nexthop blackhole");
0ae8130d
DS
466 break;
467 }
468 }
67a9eda9
DS
469
470 return i;
471}
472static int sharp_nexthop_update(ZAPI_CALLBACK_ARGS)
473{
474 struct sharp_nh_tracker *nht;
475 struct zapi_route nhr;
476
477 if (!zapi_nexthop_update_decode(zclient->ibuf, &nhr)) {
15569c58 478 zlog_warn("%s: Decode of update failed", __func__);
67a9eda9
DS
479
480 return 0;
481 }
482
483 zlog_debug("Received update for %pFX", &nhr.prefix);
484
485 nht = sharp_nh_tracker_get(&nhr.prefix);
486 nht->nhop_num = nhr.nexthop_num;
487 nht->updates++;
488
489 sharp_debug_nexthops(&nhr);
490
491 return 0;
492}
493
494static int sharp_redistribute_route(ZAPI_CALLBACK_ARGS)
495{
496 struct zapi_route api;
497
498 if (zapi_route_decode(zclient->ibuf, &api) < 0)
15569c58 499 zlog_warn("%s: Decode of redistribute failed: %d", __func__,
67a9eda9
DS
500 ZEBRA_REDISTRIBUTE_ROUTE_ADD);
501
502 zlog_debug("%s: %pFX (%s)", zserv_command_string(cmd),
503 &api.prefix, zebra_route_string(api.type));
504
505 sharp_debug_nexthops(&api);
506
0ae8130d
DS
507 return 0;
508}
509
2be4d61a
MS
510/* Add a zclient with a specified session id, for testing. */
511int sharp_zclient_create(uint32_t session_id)
512{
513 struct zclient *client;
514 struct sharp_zclient *node;
515
516 /* Check for duplicates */
517 for (node = sharp_clients_head; node != NULL; node = node->next) {
518 if (node->client->session_id == session_id)
519 return -1;
520 }
521
522 client = zclient_new(master, &zclient_options_default);
523 client->sock = -1;
524 client->session_id = session_id;
525
526 zclient_init(client, ZEBRA_ROUTE_SHARP, 0, &sharp_privs);
527
528 /* Register handlers for messages we expect this session to see */
529 client->opaque_msg_handler = sharp_opaque_handler;
530
531 /* Enqueue on the list of test clients */
532 add_zclient(client);
533
534 return 0;
535}
536
537/* Delete one of the extra test zclients */
538int sharp_zclient_delete(uint32_t session_id)
539{
540 struct sharp_zclient *node;
541
542 /* Search for session */
543 for (node = sharp_clients_head; node != NULL; node = node->next) {
544 if (node->client->session_id == session_id) {
545 /* Dequeue from list */
546 if (node->next)
547 node->next->prev = node->prev;
548 if (node->prev)
549 node->prev->next = node->next;
550 if (node == sharp_clients_head)
551 sharp_clients_head = node->next;
552
553 /* Clean up zclient */
554 zclient_stop(node->client);
555 zclient_free(node->client);
556
557 /* Free memory */
558 XFREE(MTYPE_ZC, node);
559 break;
560 }
561 }
562
563 return 0;
564}
565
7f5ac773
MS
566/* Handler for opaque messages */
567static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS)
568{
7f5ac773 569 struct stream *s;
387831ff 570 struct zapi_opaque_msg info;
7f5ac773
MS
571
572 s = zclient->ibuf;
573
387831ff
MS
574 if (zclient_opaque_decode(s, &info) != 0)
575 return -1;
7f5ac773 576
2be4d61a 577 zlog_debug("%s: [%u] received opaque type %u", __func__,
c8b27f2a 578 zclient->session_id, info.type);
7f5ac773
MS
579
580 return 0;
581}
582
2ac6c90d
MS
583/*
584 * Send OPAQUE messages, using subtype 'type'.
585 */
c8b27f2a
MS
586void sharp_opaque_send(uint32_t type, uint32_t proto, uint32_t instance,
587 uint32_t session_id, uint32_t count)
2ac6c90d 588{
7f5ac773 589 uint8_t buf[32];
2ac6c90d
MS
590 int ret;
591 uint32_t i;
592
593 /* Prepare a small payload */
594 for (i = 0; i < sizeof(buf); i++) {
595 if (type < 255)
596 buf[i] = type;
597 else
598 buf[i] = 255;
599 }
600
c8b27f2a 601 /* Send some messages - broadcast and unicast are supported */
2ac6c90d 602 for (i = 0; i < count; i++) {
c8b27f2a
MS
603 if (proto == 0)
604 ret = zclient_send_opaque(zclient, type, buf,
605 sizeof(buf));
606 else
607 ret = zclient_send_opaque_unicast(zclient, type, proto,
608 instance, session_id,
609 buf, sizeof(buf));
2ac6c90d
MS
610 if (ret < 0) {
611 zlog_debug("%s: send_opaque() failed => %d",
612 __func__, ret);
613 break;
614 }
615 }
616
617}
618
939b2339
MS
619/*
620 * Send OPAQUE registration messages, using subtype 'type'.
621 */
622void sharp_opaque_reg_send(bool is_reg, uint32_t proto, uint32_t instance,
623 uint32_t session_id, uint32_t type)
624{
625 struct stream *s;
626
627 s = zclient->obuf;
628 stream_reset(s);
629
630 if (is_reg)
631 zclient_create_header(s, ZEBRA_OPAQUE_REGISTER, VRF_DEFAULT);
632 else
633 zclient_create_header(s, ZEBRA_OPAQUE_UNREGISTER, VRF_DEFAULT);
634
635 /* Send sub-type */
636 stream_putl(s, type);
637
638 /* Add zclient info */
639 stream_putc(s, proto);
640 stream_putw(s, instance);
641 stream_putl(s, session_id);
642
643 /* Put length at the first point of the stream. */
644 stream_putw_at(s, 0, stream_get_endp(s));
645
646 (void)zclient_send_message(zclient);
647
648}
649
8a71d93d
DS
650void sharp_zebra_init(void)
651{
996c9314 652 struct zclient_options opt = {.receive_notify = true};
8a71d93d 653
138c5a74
DS
654 if_zapi_callbacks(sharp_ifp_create, sharp_ifp_up,
655 sharp_ifp_down, sharp_ifp_destroy);
656
26f63a1e 657 zclient = zclient_new(master, &opt);
8a71d93d
DS
658
659 zclient_init(zclient, ZEBRA_ROUTE_SHARP, 0, &sharp_privs);
660 zclient->zebra_connected = zebra_connected;
8a71d93d
DS
661 zclient->interface_address_add = interface_address_add;
662 zclient->interface_address_delete = interface_address_delete;
28b11f81 663 zclient->route_notify_owner = route_notify_owner;
0ae8130d 664 zclient->nexthop_update = sharp_nexthop_update;
b47dc61a 665 zclient->import_check_update = sharp_nexthop_update;
67a9eda9
DS
666
667 zclient->redistribute_route_add = sharp_redistribute_route;
668 zclient->redistribute_route_del = sharp_redistribute_route;
7f5ac773 669 zclient->opaque_msg_handler = sharp_opaque_handler;
8a71d93d 670}