summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
authorRenato Westphal <renato@opensourcerouting.org>2017-08-21 03:10:50 +0200
committerRenato Westphal <renato@opensourcerouting.org>2017-08-24 01:25:45 +0200
commit744899219f4214398a3078874a341000a372e29d (patch)
treeb33edf26332d87c734bb68f19efb3b4d37fd5a4f /bgpd
parentbgpd: unify ipv4/ipv6 zebra-tx functions (diff)
downloadfrr-744899219f4214398a3078874a341000a372e29d.tar.xz
frr-744899219f4214398a3078874a341000a372e29d.zip
*: use zapi_route to send/receive redistributed routes as well
Some differences compared to the old API: * Now the redistributed routes are sent using address-family independent messages (ZEBRA_REDISTRIBUTE_ROUTE_ADD and ZEBRA_REDISTRIBUTE_ROUTE_DEL). This allows us to unify the ipv4/ipv6 zclient callbacks in the client daemons and thus remove a lot of duplicate code; * Now zebra sends all nexthops of the redistributed routes to the client daemons, not only the first one. This shouldn't have any noticeable performance implications and will allow us to remove an ugly exception we had for ldpd (which needs to know all nexthops of the redistributed routes). The other client daemons can simply ignore the nexthops if they want or consult just the first one (e.g. ospfd/ospf6d/ripd/ripngd). Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_route.c20
-rw-r--r--bgpd/bgp_route.h4
-rw-r--r--bgpd/bgp_zebra.c241
-rw-r--r--bgpd/rfapi/vnc_zebra.c171
4 files changed, 73 insertions, 363 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index bb204b01f..2256b069c 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -6086,8 +6086,7 @@ DEFUN (no_ipv6_aggregate_address,
/* Redistribute route treatment. */
void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
- const struct in_addr *nexthop,
- const struct in6_addr *nexthop6, unsigned int ifindex,
+ const union g_addr *nexthop, unsigned int ifindex,
u_int32_t metric, u_char type, u_short instance,
route_tag_t tag)
{
@@ -6103,14 +6102,17 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
/* Make default attribute. */
bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
- if (nexthop)
- attr.nexthop = *nexthop;
- attr.nh_ifindex = ifindex;
-
- if (nexthop6) {
- attr.mp_nexthop_global = *nexthop6;
- attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
+ if (nexthop) {
+ switch (p->family) {
+ case AF_INET:
+ attr.nexthop = nexthop->ipv4;
+ break;
+ case AF_INET6:
+ attr.mp_nexthop_global = nexthop->ipv6;
+ attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
+ }
}
+ attr.nh_ifindex = ifindex;
attr.med = metric;
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 1a1817bad..55f812d4a 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -22,6 +22,7 @@
#define _QUAGGA_BGP_ROUTE_H
#include "queue.h"
+#include "nexthop.h"
#include "bgp_table.h"
struct bgp_nexthop_cache;
@@ -326,8 +327,7 @@ extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *);
extern int bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int);
extern void bgp_redistribute_add(struct bgp *, struct prefix *,
- const struct in_addr *,
- const struct in6_addr *, unsigned int ifindex,
+ const union g_addr *, unsigned int ifindex,
u_int32_t, u_char, u_short, route_tag_t);
extern void bgp_redistribute_delete(struct bgp *, struct prefix *, u_char,
u_short);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 1796975ad..9a092404d 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -554,75 +554,36 @@ static int bgp_interface_vrf_update(int command, struct zclient *zclient,
}
/* Zebra route add and delete treatment. */
-static int zebra_read_ipv4(int command, struct zclient *zclient,
- zebra_size_t length, vrf_id_t vrf_id)
+static int zebra_read_route(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
{
- struct stream *s;
- struct zapi_ipv4 api;
- struct in_addr nexthop;
- struct prefix_ipv4 p;
+ struct zapi_route api;
+ union g_addr nexthop;
unsigned int ifindex;
- int i;
+ int add, i;
struct bgp *bgp;
bgp = bgp_lookup_by_vrf_id(vrf_id);
if (!bgp)
return 0;
- s = zclient->ibuf;
- nexthop.s_addr = 0;
-
- /* Type, flags, message. */
- api.type = stream_getc(s);
- api.instance = stream_getw(s);
- api.flags = stream_getl(s);
- api.message = stream_getc(s);
-
- /* IPv4 prefix. */
- memset(&p, 0, sizeof(struct prefix_ipv4));
- p.family = AF_INET;
- p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s));
- stream_get(&p.prefix, s, PSIZE(p.prefixlen));
-
- /* Nexthop, ifindex, distance, metric. */
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
- api.nexthop_num = stream_getc(s);
- nexthop.s_addr = stream_get_ipv4(s);
- }
-
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
- api.ifindex_num = stream_getc(s);
- ifindex = stream_getl(s); /* ifindex, unused */
- } else {
- ifindex = 0;
- }
-
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
- api.distance = stream_getc(s);
+ if (zapi_route_decode(zclient->ibuf, &api) < 0)
+ return -1;
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
- api.metric = stream_getl(s);
- else
- api.metric = 0;
+ /* we completely ignore srcdest routes for now. */
+ if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
+ return 0;
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
- api.tag = stream_getl(s);
- else
- api.tag = 0;
+ /* ignore link-local address. */
+ if (api.prefix.family == AF_INET6
+ && IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6))
+ return 0;
- if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) {
- if (bgp_debug_zebra((struct prefix *)&p)) {
- char buf[2][INET_ADDRSTRLEN];
- zlog_debug(
- "Rx IPv4 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %" ROUTE_TAG_PRI,
- vrf_id, zebra_route_string(api.type),
- api.instance, inet_ntop(AF_INET, &p.prefix,
- buf[0], sizeof(buf[0])),
- p.prefixlen, inet_ntop(AF_INET, &nexthop,
- buf[1], sizeof(buf[1])),
- api.metric, api.tag);
- }
+ nexthop = api.nexthops[0].gate;
+ ifindex = api.nexthops[0].ifindex;
+ add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
+ if (add) {
/*
* The ADD message is actually an UPDATE and there is no
* explicit DEL
@@ -634,156 +595,30 @@ static int zebra_read_ipv4(int command, struct zclient *zclient,
*/
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (i != api.type)
- bgp_redistribute_delete(bgp,
- (struct prefix *)&p, i,
+ bgp_redistribute_delete(bgp, &api.prefix, i,
api.instance);
}
/* Now perform the add/update. */
- bgp_redistribute_add(bgp, (struct prefix *)&p, &nexthop, NULL,
- ifindex, api.metric, api.type,
- api.instance, api.tag);
- } else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) {
- if (bgp_debug_zebra((struct prefix *)&p)) {
- char buf[2][INET_ADDRSTRLEN];
- zlog_debug(
- "Rx IPv4 route delete VRF %u %s[%d] %s/%d "
- "nexthop %s metric %u tag %" ROUTE_TAG_PRI,
- vrf_id, zebra_route_string(api.type),
- api.instance, inet_ntop(AF_INET, &p.prefix,
- buf[0], sizeof(buf[0])),
- p.prefixlen, inet_ntop(AF_INET, &nexthop,
- buf[1], sizeof(buf[1])),
- api.metric, api.tag);
- }
- bgp_redistribute_delete(bgp, (struct prefix *)&p, api.type,
- api.instance);
- }
-
- return 0;
-}
-
-/* Zebra route add and delete treatment. */
-static int zebra_read_ipv6(int command, struct zclient *zclient,
- zebra_size_t length, vrf_id_t vrf_id)
-{
- struct stream *s;
- struct zapi_ipv6 api;
- struct in6_addr nexthop;
- struct prefix_ipv6 p, src_p;
- unsigned int ifindex;
- int i;
- struct bgp *bgp;
-
- bgp = bgp_lookup_by_vrf_id(vrf_id);
- if (!bgp)
- return 0;
-
- s = zclient->ibuf;
- memset(&nexthop, 0, sizeof(struct in6_addr));
-
- /* Type, flags, message. */
- api.type = stream_getc(s);
- api.instance = stream_getw(s);
- api.flags = stream_getl(s);
- api.message = stream_getc(s);
-
- /* IPv6 prefix. */
- memset(&p, 0, sizeof(struct prefix_ipv6));
- p.family = AF_INET6;
- p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s));
- stream_get(&p.prefix, s, PSIZE(p.prefixlen));
-
- memset(&src_p, 0, sizeof(struct prefix_ipv6));
- src_p.family = AF_INET6;
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
- src_p.prefixlen = stream_getc(s);
- stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen));
- }
-
- if (src_p.prefixlen)
- /* we completely ignore srcdest routes for now. */
- return 0;
-
- /* Nexthop, ifindex, distance, metric. */
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
- api.nexthop_num = stream_getc(s);
- stream_get(&nexthop, s, 16);
- }
-
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
- api.ifindex_num = stream_getc(s);
- ifindex = stream_getl(s); /* ifindex, unused */
+ bgp_redistribute_add(bgp, &api.prefix, &nexthop, ifindex,
+ api.metric, api.type, api.instance,
+ api.tag);
} else {
- ifindex = 0;
+ bgp_redistribute_delete(bgp, &api.prefix, api.type,
+ api.instance);
}
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
- api.distance = stream_getc(s);
- else
- api.distance = 0;
-
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
- api.metric = stream_getl(s);
- else
- api.metric = 0;
-
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
- api.tag = stream_getl(s);
- else
- api.tag = 0;
-
- /* Simply ignore link-local address. */
- if (IN6_IS_ADDR_LINKLOCAL(&p.prefix))
- return 0;
-
- if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) {
- if (bgp_debug_zebra((struct prefix *)&p)) {
- char buf[2][INET6_ADDRSTRLEN];
- zlog_debug(
- "Rx IPv6 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %" ROUTE_TAG_PRI,
- vrf_id, zebra_route_string(api.type),
- api.instance, inet_ntop(AF_INET6, &p.prefix,
- buf[0], sizeof(buf[0])),
- p.prefixlen, inet_ntop(AF_INET, &nexthop,
- buf[1], sizeof(buf[1])),
- api.metric, api.tag);
- }
-
- /*
- * The ADD message is actually an UPDATE and there is no
- * explicit DEL
- * for a prior redistributed route, if any. So, perform an
- * implicit
- * DEL processing for the same redistributed route from any
- * other
- * source type.
- */
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
- if (i != api.type)
- bgp_redistribute_delete(bgp,
- (struct prefix *)&p, i,
- api.instance);
- }
-
- bgp_redistribute_add(bgp, (struct prefix *)&p, NULL, &nexthop,
- ifindex, api.metric, api.type,
- api.instance, api.tag);
- } else if (command == ZEBRA_REDISTRIBUTE_IPV6_DEL) {
- if (bgp_debug_zebra((struct prefix *)&p)) {
- char buf[2][INET6_ADDRSTRLEN];
- zlog_debug(
- "Rx IPv6 route delete VRF %u %s[%d] %s/%d "
- "nexthop %s metric %u tag %" ROUTE_TAG_PRI,
- vrf_id, zebra_route_string(api.type),
- api.instance, inet_ntop(AF_INET6, &p.prefix,
- buf[0], sizeof(buf[0])),
- p.prefixlen, inet_ntop(AF_INET6, &nexthop,
- buf[1], sizeof(buf[1])),
- api.metric, api.tag);
- }
- bgp_redistribute_delete(bgp, (struct prefix *)&p, api.type,
- api.instance);
+ if (bgp_debug_zebra(&api.prefix)) {
+ char buf[2][PREFIX_STRLEN];
+
+ prefix2str(&api.prefix, buf[0], sizeof(buf[0]));
+ inet_ntop(api.prefix.family, &nexthop, buf[1], sizeof(buf[1]));
+ zlog_debug(
+ "Rx route %s VRF %u %s[%d] %s "
+ "nexthop %s metric %u tag %" ROUTE_TAG_PRI,
+ (add) ? "add" : "delete", vrf_id,
+ zebra_route_string(api.type), api.instance, buf[0],
+ buf[1], api.metric, api.tag);
}
return 0;
@@ -1942,12 +1777,10 @@ void bgp_zebra_init(struct thread_master *master)
zclient->interface_nbr_address_delete =
bgp_interface_nbr_address_delete;
zclient->interface_vrf_update = bgp_interface_vrf_update;
- zclient->redistribute_route_ipv4_add = zebra_read_ipv4;
- zclient->redistribute_route_ipv4_del = zebra_read_ipv4;
+ zclient->redistribute_route_add = zebra_read_route;
+ zclient->redistribute_route_del = zebra_read_route;
zclient->interface_up = bgp_interface_up;
zclient->interface_down = bgp_interface_down;
- zclient->redistribute_route_ipv6_add = zebra_read_ipv6;
- zclient->redistribute_route_ipv6_del = zebra_read_ipv6;
zclient->nexthop_update = bgp_read_nexthop_update;
zclient->import_check_update = bgp_read_import_check_update;
zclient->fec_update = bgp_read_fec_update;
diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c
index 06dff27b5..d472e06fa 100644
--- a/bgpd/rfapi/vnc_zebra.c
+++ b/bgpd/rfapi/vnc_zebra.c
@@ -57,8 +57,8 @@ static struct zclient *zclient_vnc = NULL;
/*
* Routes coming from zebra get added to VNC here
*/
-static void vnc_redistribute_add(struct prefix *p, struct in_addr *nexthop,
- u_int32_t metric, uint8_t type)
+static void vnc_redistribute_add(struct prefix *p, u_int32_t metric,
+ uint8_t type)
{
struct bgp *bgp = bgp_get_default();
struct prefix_rd prd;
@@ -329,156 +329,33 @@ static void vnc_redistribute_withdraw(struct bgp *bgp, afi_t afi, uint8_t type)
*
* Assumes 1 nexthop
*/
-static int vnc_zebra_read_ipv4(int command, struct zclient *zclient,
- zebra_size_t length, vrf_id_t vrf_id)
+static int vnc_zebra_read_route(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
{
- struct stream *s;
- struct zapi_ipv4 api;
- struct in_addr nexthop;
- struct prefix_ipv4 p;
-
- s = zclient->ibuf;
- nexthop.s_addr = 0;
-
- /* Type, flags, message. */
- api.type = stream_getc(s);
- api.flags = stream_getc(s);
- api.message = stream_getc(s);
-
- /* IPv4 prefix. */
- memset(&p, 0, sizeof(struct prefix_ipv4));
- p.family = AF_INET;
- p.prefixlen = stream_getc(s);
- stream_get(&p.prefix, s, PSIZE(p.prefixlen));
-
- /* Nexthop, ifindex, distance, metric. */
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
- api.nexthop_num = stream_getc(s);
- nexthop.s_addr = stream_get_ipv4(s);
- }
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
- api.ifindex_num = stream_getc(s);
- stream_getl(s);
- }
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
- api.distance = stream_getc(s);
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
- api.metric = stream_getl(s);
- else
- api.metric = 0;
-
- if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) {
- if (BGP_DEBUG(zebra, ZEBRA)) {
- char buf[2][INET_ADDRSTRLEN];
- vnc_zlog_debug_verbose(
- "%s: Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u",
- __func__, zebra_route_string(api.type),
- inet_ntop(AF_INET, &p.prefix, buf[0],
- sizeof(buf[0])),
- p.prefixlen, inet_ntop(AF_INET, &nexthop,
- buf[1], sizeof(buf[1])),
- api.metric);
- }
- vnc_redistribute_add((struct prefix *)&p, &nexthop, api.metric,
- api.type);
- } else {
- if (BGP_DEBUG(zebra, ZEBRA)) {
- char buf[2][INET_ADDRSTRLEN];
- vnc_zlog_debug_verbose(
- "%s: Zebra rcvd: IPv4 route delete %s %s/%d "
- "nexthop %s metric %u",
- __func__, zebra_route_string(api.type),
- inet_ntop(AF_INET, &p.prefix, buf[0],
- sizeof(buf[0])),
- p.prefixlen, inet_ntop(AF_INET, &nexthop,
- buf[1], sizeof(buf[1])),
- api.metric);
- }
- vnc_redistribute_delete((struct prefix *)&p, api.type);
- }
+ struct zapi_route api;
+ int add;
- return 0;
-}
+ if (zapi_route_decode(zclient->ibuf, &api) < 0)
+ return -1;
-/* Zebra route add and delete treatment. */
-static int vnc_zebra_read_ipv6(int command, struct zclient *zclient,
- zebra_size_t length, vrf_id_t vrf_id)
-{
- struct stream *s;
- struct zapi_ipv6 api;
- struct in6_addr nexthop;
- struct prefix_ipv6 p, src_p;
-
- s = zclient->ibuf;
- memset(&nexthop, 0, sizeof(struct in6_addr));
-
- /* Type, flags, message. */
- api.type = stream_getc(s);
- api.flags = stream_getc(s);
- api.message = stream_getc(s);
-
- /* IPv6 prefix. */
- memset(&p, 0, sizeof(struct prefix_ipv6));
- p.family = AF_INET6;
- p.prefixlen = stream_getc(s);
- stream_get(&p.prefix, s, PSIZE(p.prefixlen));
-
- memset(&src_p, 0, sizeof(struct prefix_ipv6));
- src_p.family = AF_INET6;
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
- src_p.prefixlen = stream_getc(s);
- stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen));
- }
-
- if (src_p.prefixlen)
- /* we completely ignore srcdest routes for now. */
+ /* we completely ignore srcdest routes for now. */
+ if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
return 0;
- /* Nexthop, ifindex, distance, metric. */
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
- api.nexthop_num = stream_getc(s);
- stream_get(&nexthop, s, 16);
- }
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
- api.ifindex_num = stream_getc(s);
- stream_getl(s);
- }
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
- api.distance = stream_getc(s);
- else
- api.distance = 0;
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
- api.metric = stream_getl(s);
+ add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
+ if (add)
+ vnc_redistribute_add(&api.prefix, api.metric, api.type);
else
- api.metric = 0;
+ vnc_redistribute_delete(&api.prefix, api.type);
- /* Simply ignore link-local address. */
- if (IN6_IS_ADDR_LINKLOCAL(&p.prefix))
- return 0;
+ if (BGP_DEBUG(zebra, ZEBRA)) {
+ char buf[PREFIX_STRLEN];
- if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) {
- if (BGP_DEBUG(zebra, ZEBRA)) {
- char buf[INET6_ADDRSTRLEN];
- vnc_zlog_debug_verbose(
- "Zebra rcvd: IPv6 route add %s %s/%d metric %u",
- zebra_route_string(api.type),
- inet_ntop(AF_INET6, &p.prefix, buf,
- sizeof(buf)),
- p.prefixlen, api.metric);
- }
- vnc_redistribute_add((struct prefix *)&p, NULL, api.metric,
- api.type);
- } else {
- if (BGP_DEBUG(zebra, ZEBRA)) {
- char buf[INET6_ADDRSTRLEN];
- vnc_zlog_debug_verbose(
- "Zebra rcvd: IPv6 route delete %s %s/%d metric %u",
- zebra_route_string(api.type),
- inet_ntop(AF_INET6, &p.prefix, buf,
- sizeof(buf)),
- p.prefixlen, api.metric);
- }
- vnc_redistribute_delete((struct prefix *)&p, api.type);
+ prefix2str(&api.prefix, buf, sizeof(buf));
+ vnc_zlog_debug_verbose(
+ "%s: Zebra rcvd: route delete %s %s metric %u",
+ __func__, zebra_route_string(api.type), buf,
+ api.metric);
}
return 0;
@@ -1016,10 +893,8 @@ void vnc_zebra_init(struct thread_master *master)
zclient_vnc = zclient_new(master);
zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0);
- zclient_vnc->redistribute_route_ipv4_add = vnc_zebra_read_ipv4;
- zclient_vnc->redistribute_route_ipv4_del = vnc_zebra_read_ipv4;
- zclient_vnc->redistribute_route_ipv6_add = vnc_zebra_read_ipv6;
- zclient_vnc->redistribute_route_ipv6_del = vnc_zebra_read_ipv6;
+ zclient_vnc->redistribute_route_add = vnc_zebra_read_route;
+ zclient_vnc->redistribute_route_del = vnc_zebra_read_route;
}
void vnc_zebra_destroy(void)