]> git.puffer.fish Git - mirror/frr.git/commitdiff
*: use zapi_route to send/receive redistributed routes as well
authorRenato Westphal <renato@opensourcerouting.org>
Mon, 21 Aug 2017 01:10:50 +0000 (22:10 -0300)
committerRenato Westphal <renato@opensourcerouting.org>
Wed, 23 Aug 2017 23:25:45 +0000 (20:25 -0300)
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>
20 files changed:
babeld/babel_zebra.c
babeld/xroute.c
babeld/xroute.h
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_zebra.c
bgpd/rfapi/vnc_zebra.c
eigrpd/eigrp_zebra.c
isisd/isis_zebra.c
ldpd/ldp_zebra.c
lib/log.c
lib/zclient.c
lib/zclient.h
nhrpd/nhrp_route.c
ospf6d/ospf6_zebra.c
ospfd/ospf_zebra.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/zserv.c

index 2b998940d74f03c1eaefc1f63e4d6185f08183a9..337b7b3927163e40a52e998aa6484b302b9188d0 100644 (file)
@@ -54,119 +54,24 @@ static struct {
     {0, 0, NULL}
 };
 
-/* Zebra route add and delete treatment (ipv6). */
+/* Zebra route add and delete treatment. */
 static int
-babel_zebra_read_ipv6 (int command, struct zclient *zclient,
-                      zebra_size_t length, vrf_id_t vrf)
+babel_zebra_read_route (int command, struct zclient *zclient,
+                       zebra_size_t length, vrf_id_t vrf)
 {
-    struct stream *s;
-    struct zapi_ipv6 api;
-    unsigned long ifindex = -1;
-    struct in6_addr nexthop;
-    struct prefix_ipv6 prefix, src_p;
-
-    s = zclient->ibuf;
-    ifindex = 0;
-    memset (&nexthop, 0, sizeof (struct in6_addr));
-    memset (&api, 0, sizeof(struct zapi_ipv6));
-    memset (&prefix, 0, sizeof (struct prefix_ipv6));
-
-    /* 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. */
-    prefix.family = AF_INET6;
-    prefix.prefixlen = MIN (IPV6_MAX_PREFIXLEN, stream_getc (s));
-    stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen));
-
-    memset(&src_p, 0, sizeof(src_p));
-    if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
-        src_p.family = AF_INET6;
-        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, sizeof(nexthop));
-    }
-    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) {
-        api.ifindex_num = stream_getc (s);
-        ifindex = 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);
-    else
-        api.metric = 0;
-
-    if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
-        babel_ipv6_route_add(&api, &prefix, ifindex, &nexthop);
-    else
-        babel_ipv6_route_delete(&api, &prefix, ifindex);
+    struct zapi_route api;
 
-    return 0;
-}
+    if (zapi_route_decode(zclient->ibuf, &api) < 0)
+        return -1;
 
-static int
-babel_zebra_read_ipv4 (int command, struct zclient *zclient,
-                      zebra_size_t length, vrf_id_t vrf)
-{
-    struct stream *s;
-    struct zapi_ipv4 api;
-    unsigned long ifindex = -1;
-    struct in_addr nexthop;
-    struct prefix_ipv4 prefix;
-
-    s = zclient->ibuf;
-    ifindex = 0;
-    memset (&nexthop, 0, sizeof (struct in_addr));
-    memset (&api, 0, sizeof(struct zapi_ipv4));
-    memset (&prefix, 0, sizeof (struct prefix_ipv4));
-
-    /* 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. */
-    prefix.family = AF_INET;
-    prefix.prefixlen = MIN (IPV4_MAX_PREFIXLEN, stream_getc (s));
-    stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen));
-
-    /* Nexthop, ifindex, distance, metric. */
-    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) {
-        api.nexthop_num = stream_getc (s);
-        stream_get (&nexthop, s, sizeof(nexthop));
-    }
-    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) {
-        api.ifindex_num = stream_getc (s);
-        ifindex = 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);
-    else
-        api.metric = 0;
+    /* we completely ignore srcdest routes for now. */
+    if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
+        return 0;
 
-    if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) {
-        babel_ipv4_route_add(&api, &prefix, ifindex, &nexthop);
+    if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
+        babel_route_add(&api);
     } else {
-        babel_ipv4_route_delete(&api, &prefix, ifindex);
+        babel_route_delete(&api);
     }
 
     return 0;
@@ -342,10 +247,8 @@ void babelz_zebra_init(void)
     zclient->interface_down = babel_interface_down;
     zclient->interface_address_add = babel_interface_address_add;
     zclient->interface_address_delete = babel_interface_address_delete;
-    zclient->redistribute_route_ipv4_add = babel_zebra_read_ipv4;
-    zclient->redistribute_route_ipv4_del = babel_zebra_read_ipv4;
-    zclient->redistribute_route_ipv6_add = babel_zebra_read_ipv6;
-    zclient->redistribute_route_ipv6_del = babel_zebra_read_ipv6;
+    zclient->redistribute_route_add = babel_zebra_read_route;
+    zclient->redistribute_route_del = babel_zebra_read_route;
 
     install_element(BABEL_NODE, &babel_redistribute_type_cmd);
     install_element(ENABLE_NODE, &debug_babel_cmd);
index 2e123564ea267dcc13fe5940411a06591d2bd341..88e9479e4b868f27440c2d7b5eff18085a28cc55 100644 (file)
@@ -43,63 +43,54 @@ static int numxroutes = 0, maxxroutes = 0;
 
 /* Add redistributed route to Babel table. */
 int
-babel_ipv4_route_add (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix,
-                      unsigned int ifindex, struct in_addr *nexthop)
+babel_route_add (struct zapi_route *api)
 {
     unsigned char uchar_prefix[16];
 
-    inaddr_to_uchar(uchar_prefix, &prefix->prefix);
-    debugf(BABEL_DEBUG_ROUTE, "Adding new ipv4 route coming from Zebra.");
-    xroute_add_new_route(uchar_prefix, prefix->prefixlen + 96,
-                         api->metric, ifindex, 0, 1);
-    return 0;
-}
-
-/* Remove redistributed route from Babel table. */
-int
-babel_ipv4_route_delete (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix,
-                         unsigned int ifindex)
-{
-    unsigned char uchar_prefix[16];
-    struct xroute *xroute = NULL;
-
-    inaddr_to_uchar(uchar_prefix, &prefix->prefix);
-    xroute = find_xroute(uchar_prefix, prefix->prefixlen + 96);
-    if (xroute != NULL) {
-        debugf(BABEL_DEBUG_ROUTE, "Removing ipv4 route (from zebra).");
-        flush_xroute(xroute);
+    switch (api->prefix.family) {
+    case AF_INET:
+        inaddr_to_uchar(uchar_prefix, &api->prefix.u.prefix4);
+        debugf(BABEL_DEBUG_ROUTE, "Adding new ipv4 route coming from Zebra.");
+        xroute_add_new_route(uchar_prefix, api->prefix.prefixlen + 96,
+                             api->metric, api->nexthops[0].ifindex, 0, 1);
+        break;
+    case AF_INET6:
+        in6addr_to_uchar(uchar_prefix, &api->prefix.u.prefix6);
+        debugf(BABEL_DEBUG_ROUTE, "Adding new ipv6 route coming from Zebra.");
+        xroute_add_new_route(uchar_prefix, api->prefix.prefixlen,
+                             api->metric, api->nexthops[0].ifindex, 0, 1);
+        break;
     }
-    return 0;
-}
 
-/* Add redistributed route to Babel table. */
-int
-babel_ipv6_route_add (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix,
-                      unsigned int ifindex, struct in6_addr *nexthop)
-{
-    unsigned char uchar_prefix[16];
-
-    in6addr_to_uchar(uchar_prefix, &prefix->prefix);
-    debugf(BABEL_DEBUG_ROUTE, "Adding new route coming from Zebra.");
-    xroute_add_new_route(uchar_prefix, prefix->prefixlen, api->metric, ifindex,
-                         0, 1);
     return 0;
 }
 
 /* Remove redistributed route from Babel table. */
 int
-babel_ipv6_route_delete (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix,
-                         unsigned int ifindex)
+babel_route_delete (struct zapi_route *api)
 {
     unsigned char uchar_prefix[16];
     struct xroute *xroute = NULL;
 
-    in6addr_to_uchar(uchar_prefix, &prefix->prefix);
-    xroute = find_xroute(uchar_prefix, prefix->prefixlen);
-    if (xroute != NULL) {
-        debugf(BABEL_DEBUG_ROUTE, "Removing route (from zebra).");
-        flush_xroute(xroute);
+    switch (api->prefix.family) {
+    case AF_INET:
+        inaddr_to_uchar(uchar_prefix, &api->prefix.u.prefix4);
+        xroute = find_xroute(uchar_prefix, api->prefix.prefixlen + 96);
+        if (xroute != NULL) {
+            debugf(BABEL_DEBUG_ROUTE, "Removing ipv4 route (from zebra).");
+            flush_xroute(xroute);
+        }
+        break;
+    case AF_INET6:
+        in6addr_to_uchar(uchar_prefix, &api->prefix.u.prefix6);
+        xroute = find_xroute(uchar_prefix, api->prefix.prefixlen);
+        if (xroute != NULL) {
+            debugf(BABEL_DEBUG_ROUTE, "Removing ipv6 route (from zebra).");
+            flush_xroute(xroute);
+        }
+        break;
     }
+
     return 0;
 }
 
index 27899e62a1a9055e142f5f1c6e4acc472815a336..59afccb5904f2de673e29b3a2bbc3c8a39237606 100644 (file)
@@ -36,14 +36,8 @@ struct xroute_stream;
 
 struct xroute *find_xroute(const unsigned char *prefix, unsigned char plen);
 void flush_xroute(struct xroute *xroute);
-int babel_ipv4_route_add (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix,
-                          unsigned int ifindex, struct in_addr *nexthop);
-int babel_ipv4_route_delete (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix,
-                             unsigned int ifindex);
-int babel_ipv6_route_add (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix,
-                          unsigned int ifindex, struct in6_addr *nexthop);
-int babel_ipv6_route_delete (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix,
-                             unsigned int ifindex);
+int babel_route_add (struct zapi_route *api);
+int babel_route_delete (struct zapi_route *api);
 int xroutes_estimate(void);
 struct xroute_stream *xroute_stream(void);
 struct xroute *xroute_stream_next(struct xroute_stream *stream);
index bb204b01f1265784e4d3ecee1a46ad98a10a7b98..2256b069cbf7bbac97273211cd29bb268de42ac3 100644 (file)
@@ -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);
index 1a1817bad35642410d83b8b13e4049be4a57b175..55f812d4a08d9b677f2b7380de90352a652425f7 100644 (file)
@@ -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);
index 1796975ad31b8100fd665981a4774e065ac1d9f4..9a092404d58297b539508a0c0e9452c09b9fa5f8 100644 (file)
@@ -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;
index 06dff27b583f599642d16f364c8797fe6bde9ad7..d472e06fa5abdfa7c89fdad0c0dbb1cf97aa7958 100644 (file)
@@ -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)
index 2e386fbf2e7d58b905cb8d3ea289eafbae3a4ec2..5aa7821e18d97af06f97a5f183763c5b408a4c6c 100644 (file)
@@ -66,8 +66,8 @@ static int eigrp_interface_state_down(int, struct zclient *, zebra_size_t,
                                      vrf_id_t vrf_id);
 static struct interface *zebra_interface_if_lookup(struct stream *);
 
-static int eigrp_zebra_read_ipv4(int, struct zclient *, zebra_size_t,
-                                vrf_id_t vrf_id);
+static int eigrp_zebra_read_route(int, struct zclient *, zebra_size_t,
+                                 vrf_id_t vrf_id);
 
 /* Zebra structure to hold current status. */
 struct zclient *zclient = NULL;
@@ -112,59 +112,31 @@ void eigrp_zebra_init(void)
        zclient->interface_down = eigrp_interface_state_down;
        zclient->interface_address_add = eigrp_interface_address_add;
        zclient->interface_address_delete = eigrp_interface_address_delete;
-       zclient->redistribute_route_ipv4_add = eigrp_zebra_read_ipv4;
-       zclient->redistribute_route_ipv4_del = eigrp_zebra_read_ipv4;
+       zclient->redistribute_route_add = eigrp_zebra_read_route;
+       zclient->redistribute_route_del = eigrp_zebra_read_route;
 }
 
 
 /* Zebra route add and delete treatment. */
-static int eigrp_zebra_read_ipv4(int command, struct zclient *zclient,
-                                zebra_size_t length, vrf_id_t vrf_id)
+static int eigrp_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 prefix_ipv4 p;
+       struct zapi_route api;
        struct eigrp *eigrp;
 
-       s = zclient->ibuf;
-
-       /* Type, flags, message. */
-       api.type = stream_getc(s);
-       api.instance = stream_getw(s);
-       api.flags = stream_getc(s);
-       api.message = stream_getc(s);
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
 
-       /* 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));
-
-       if (IPV4_NET127(ntohl(p.prefix.s_addr)))
+       if (IPV4_NET127(ntohl(api.prefix.u.prefix4.s_addr)))
                return 0;
 
-       /* Nexthop, ifindex, distance, metric. */
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
-               api.nexthop_num = stream_getc(s);
-               stream_get_ipv4(s);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
-               api.ifindex_num = stream_getc(s);
-               /* XXX assert(api.ifindex_num == 1); */
-               stream_getl(s); /* ifindex, unused */
-       }
-       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);
-
        eigrp = eigrp_lookup();
        if (eigrp == NULL)
                return 0;
 
-       if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) {
+       if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
 
-       } else /* if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) */
+       } else /* if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */
        {
        }
 
index e3537e2a0cdcea007a7767efaa213ca41374c5ce..ed96bd31c29867d17e40d3b53d8343ce1fc7c8fe 100644 (file)
@@ -344,122 +344,32 @@ void isis_zebra_route_update(struct prefix *prefix,
                isis_zebra_route_del_route(prefix, route_info);
 }
 
-static int isis_zebra_read_ipv4(int command, struct zclient *zclient,
-                               zebra_size_t length, vrf_id_t vrf_id)
+static int isis_zebra_read(int command, struct zclient *zclient,
+                          zebra_size_t length, vrf_id_t vrf_id)
 {
-       struct stream *stream;
-       struct zapi_ipv4 api;
-       struct prefix_ipv4 p;
-       struct prefix *p_generic = (struct prefix *)&p;
-
-       stream = zclient->ibuf;
-       memset(&api, 0, sizeof(api));
-       memset(&p, 0, sizeof(struct prefix_ipv4));
-
-       api.type = stream_getc(stream);
-       api.instance = stream_getw(stream);
-       api.flags = stream_getl(stream);
-       api.message = stream_getc(stream);
-
-       p.family = AF_INET;
-       p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(stream));
-       stream_get(&p.prefix, stream, PSIZE(p.prefixlen));
-
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
-               api.nexthop_num = stream_getc(stream);
-               (void)stream_get_ipv4(stream);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
-               api.ifindex_num = stream_getc(stream);
-               stream_getl(stream);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
-               api.distance = stream_getc(stream);
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
-               api.metric = stream_getl(stream);
-
-       /*
-        * Avoid advertising a false default reachability. (A default
-        * route installed by IS-IS gets redistributed from zebra back
-        * into IS-IS causing us to start advertising default reachabity
-        * without this check)
-        */
-       if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS)
-               command = ZEBRA_REDISTRIBUTE_IPV4_DEL;
+       struct zapi_route api;
 
-       if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD)
-               isis_redist_add(api.type, p_generic, api.distance, api.metric);
-       else
-               isis_redist_delete(api.type, p_generic);
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
 
-       return 0;
-}
-
-static int isis_zebra_read_ipv6(int command, struct zclient *zclient,
-                               zebra_size_t length, vrf_id_t vrf_id)
-{
-       struct stream *stream;
-       struct zapi_ipv6 api;
-       struct prefix_ipv6 p;
-       struct prefix src_p;
-       struct prefix *p_generic = (struct prefix *)&p;
-       struct in6_addr nexthop;
-       unsigned long ifindex __attribute__((unused));
-
-       stream = zclient->ibuf;
-       memset(&api, 0, sizeof(api));
-       memset(&p, 0, sizeof(struct prefix_ipv6));
-       memset(&nexthop, 0, sizeof(nexthop));
-       ifindex = 0;
-
-       api.type = stream_getc(stream);
-       api.instance = stream_getw(stream);
-       api.flags = stream_getl(stream);
-       api.message = stream_getc(stream);
-
-       p.family = AF_INET6;
-       p.prefixlen = stream_getc(stream);
-       stream_get(&p.prefix, stream, PSIZE(p.prefixlen));
-
-       memset(&src_p, 0, sizeof(struct prefix));
-       src_p.family = AF_INET6;
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
-               src_p.prefixlen = stream_getc(stream);
-               stream_get(&src_p.u.prefix6, stream, 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;
 
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
-               api.nexthop_num = stream_getc(stream); /* this is always 1 */
-               stream_get(&nexthop, stream, sizeof(nexthop));
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
-               api.ifindex_num = stream_getc(stream);
-               ifindex = stream_getl(stream);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
-               api.distance = stream_getc(stream);
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
-               api.metric = stream_getl(stream);
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
-               api.tag = stream_getl(stream);
-
        /*
         * Avoid advertising a false default reachability. (A default
         * route installed by IS-IS gets redistributed from zebra back
         * into IS-IS causing us to start advertising default reachabity
         * without this check)
         */
-       if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS)
-               command = ZEBRA_REDISTRIBUTE_IPV6_DEL;
+       if (api.prefix.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS)
+               command = ZEBRA_REDISTRIBUTE_ROUTE_DEL;
 
-       if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
-               isis_redist_add(api.type, p_generic, api.distance, api.metric);
+       if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
+               isis_redist_add(api.type, &api.prefix, api.distance,
+                               api.metric);
        else
-               isis_redist_delete(api.type, p_generic);
+               isis_redist_delete(api.type, &api.prefix);
 
        return 0;
 }
@@ -507,10 +417,8 @@ void isis_zebra_init(struct thread_master *master)
        zclient->interface_address_add = isis_zebra_if_address_add;
        zclient->interface_address_delete = isis_zebra_if_address_del;
        zclient->interface_link_params = isis_zebra_link_params;
-       zclient->redistribute_route_ipv4_add = isis_zebra_read_ipv4;
-       zclient->redistribute_route_ipv4_del = isis_zebra_read_ipv4;
-       zclient->redistribute_route_ipv6_add = isis_zebra_read_ipv6;
-       zclient->redistribute_route_ipv6_del = isis_zebra_read_ipv6;
+       zclient->redistribute_route_add = isis_zebra_read;
+       zclient->redistribute_route_del = isis_zebra_read;
 
        return;
 }
index 54c5af62a4e1d52d44f0d6043de758e684292402..c50cc0fda2e2227306f0598bd33ef3ad37e0e43a 100644 (file)
@@ -396,19 +396,34 @@ static int
 ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length,
     vrf_id_t vrf_id)
 {
-       struct stream           *s;
-       u_char                   type;
-       u_char                   message_flags;
+       struct zapi_route        api;
+       struct zapi_nexthop     *api_nh;
        struct kroute            kr;
-       int                      nhnum = 0, nhlen;
-       size_t                   nhmark;
-       int                      add = 0;
+       int                      i, add = 0;
+
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
+
+       /* we completely ignore srcdest routes for now. */
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
+               return (0);
 
        memset(&kr, 0, sizeof(kr));
-       s = zclient->ibuf;
+       kr.af = api.prefix.family;
+       switch (kr.af) {
+       case AF_INET:
+               kr.prefix.v4 = api.prefix.u.prefix4;
+               break;
+       case AF_INET6:
+               kr.prefix.v6 = api.prefix.u.prefix6;
+               break;
+       default:
+               break;
+       }
+       kr.prefixlen = api.prefix.prefixlen;
+       kr.priority = api.distance;
 
-       type = stream_getc(s);
-       switch (type) {
+       switch (api.type) {
        case ZEBRA_ROUTE_CONNECT:
                kr.flags |= F_CONNECTED;
                break;
@@ -419,85 +434,38 @@ ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length,
                break;
        }
 
-       stream_getl(s); /* flags, unused */
-       stream_getw(s); /* instance, unused */
-       message_flags = stream_getc(s);
-
-       switch (command) {
-       case ZEBRA_REDISTRIBUTE_IPV4_ADD:
-       case ZEBRA_REDISTRIBUTE_IPV4_DEL:
-               kr.af = AF_INET;
-               kr.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s));
-               nhlen = sizeof(struct in_addr);
-               break;
-       case ZEBRA_REDISTRIBUTE_IPV6_ADD:
-       case ZEBRA_REDISTRIBUTE_IPV6_DEL:
-               kr.af = AF_INET6;
-               kr.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s));
-               nhlen = sizeof(struct in6_addr);
-               break;
-       default:
-               fatalx("ldp_zebra_read_route: unknown command");
-       }
-       stream_get(&kr.prefix, s, PSIZE(kr.prefixlen));
-
        if (bad_addr(kr.af, &kr.prefix) ||
            (kr.af == AF_INET6 && IN6_IS_SCOPE_EMBED(&kr.prefix.v6)))
                return (0);
 
-       if (kr.af == AF_INET6 &&
-           CHECK_FLAG(message_flags, ZAPI_MESSAGE_SRCPFX)) {
-               uint8_t src_prefixlen;
-
-               src_prefixlen = stream_getc(s);
-
-               /* we completely ignore srcdest routes for now. */
-               if (src_prefixlen)
-                       return (0);
-       }
-
-       if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_NEXTHOP)) {
-               nhnum = stream_getc(s);
-               nhmark = stream_get_getp(s);
-               stream_set_getp(s, nhmark + nhnum * (nhlen + 5));
-       }
-
-       if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_DISTANCE))
-               kr.priority = stream_getc(s);
-       if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_METRIC))
-               stream_getl(s); /* metric, not used */
-
-       if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_NEXTHOP))
-               stream_set_getp(s, nhmark);
-
-       if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD ||
-           command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
+       if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
                add = 1;
 
-       if (nhnum == 0)
+       if (api.nexthop_num == 0)
                debug_zebra_in("route %s %s/%d (%s)", (add) ? "add" : "delete",
                    log_addr(kr.af, &kr.prefix), kr.prefixlen,
-                   zebra_route_string(type));
+                   zebra_route_string(api.type));
 
        /* loop through all the nexthops */
-       for (; nhnum > 0; nhnum--) {
+       for (i = 0; i < api.nexthop_num; i++) {
+               api_nh = &api.nexthops[i];
+
                switch (kr.af) {
                case AF_INET:
-                       kr.nexthop.v4.s_addr = stream_get_ipv4(s);
+                       kr.nexthop.v4 = api_nh->gate.ipv4;
                        break;
                case AF_INET6:
-                       stream_get(&kr.nexthop.v6, s, sizeof(kr.nexthop.v6));
+                       kr.nexthop.v6 = api_nh->gate.ipv6;
                        break;
                default:
                        break;
                }
-               stream_getc(s); /* ifindex_num, unused. */
-               kr.ifindex = stream_getl(s);
+               kr.ifindex = api_nh->ifindex;;
 
                debug_zebra_in("route %s %s/%d nexthop %s ifindex %u (%s)",
                    (add) ? "add" : "delete", log_addr(kr.af, &kr.prefix),
                    kr.prefixlen, log_addr(kr.af, &kr.nexthop), kr.ifindex,
-                   zebra_route_string(type));
+                   zebra_route_string(api.type));
 
                if (add)
                        main_imsg_compose_lde(IMSG_NETWORK_ADD, 0, &kr,
@@ -554,10 +522,8 @@ ldp_zebra_init(struct thread_master *master)
        zclient->interface_down = ldp_interface_status_change;
        zclient->interface_address_add = ldp_interface_address_add;
        zclient->interface_address_delete = ldp_interface_address_delete;
-       zclient->redistribute_route_ipv4_add = ldp_zebra_read_route;
-       zclient->redistribute_route_ipv4_del = ldp_zebra_read_route;
-       zclient->redistribute_route_ipv6_add = ldp_zebra_read_route;
-       zclient->redistribute_route_ipv6_del = ldp_zebra_read_route;
+       zclient->redistribute_route_add = ldp_zebra_read_route;
+       zclient->redistribute_route_del = ldp_zebra_read_route;
        zclient->pw_status_update = ldp_zebra_read_pw_status_update;
 }
 
index 92b2d3b66b25abfcfe0bff97c31a3a474d943c37..0ea52ed401ebb357a101f4c87cbdef3472fbf119 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -895,10 +895,8 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_BFD_DEST_DEREGISTER),
        DESC_ENTRY(ZEBRA_BFD_DEST_UPDATE),
        DESC_ENTRY(ZEBRA_BFD_DEST_REPLAY),
-       DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV4_ADD),
-       DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV4_DEL),
-       DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV6_ADD),
-       DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV6_DEL),
+       DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_ADD),
+       DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_DEL),
        DESC_ENTRY(ZEBRA_VRF_UNREGISTER),
        DESC_ENTRY(ZEBRA_VRF_ADD),
        DESC_ENTRY(ZEBRA_VRF_DELETE),
index e063c7151f8252ae95d549955c4d8a8118e9cf4b..75005d656b066336a1c7d29ab8f5fac749923032 100644 (file)
@@ -2112,25 +2112,15 @@ static int zclient_read(struct thread *thread)
                        (*zclient->bfd_dest_replay)(command, zclient, length,
                                                    vrf_id);
                break;
-       case ZEBRA_REDISTRIBUTE_IPV4_ADD:
-               if (zclient->redistribute_route_ipv4_add)
-                       (*zclient->redistribute_route_ipv4_add)(
-                               command, zclient, length, vrf_id);
-               break;
-       case ZEBRA_REDISTRIBUTE_IPV4_DEL:
-               if (zclient->redistribute_route_ipv4_del)
-                       (*zclient->redistribute_route_ipv4_del)(
-                               command, zclient, length, vrf_id);
+       case ZEBRA_REDISTRIBUTE_ROUTE_ADD:
+               if (zclient->redistribute_route_add)
+                       (*zclient->redistribute_route_add)(command, zclient,
+                                                          length, vrf_id);
                break;
-       case ZEBRA_REDISTRIBUTE_IPV6_ADD:
-               if (zclient->redistribute_route_ipv6_add)
-                       (*zclient->redistribute_route_ipv6_add)(
-                               command, zclient, length, vrf_id);
-               break;
-       case ZEBRA_REDISTRIBUTE_IPV6_DEL:
-               if (zclient->redistribute_route_ipv6_del)
-                       (*zclient->redistribute_route_ipv6_del)(
-                               command, zclient, length, vrf_id);
+       case ZEBRA_REDISTRIBUTE_ROUTE_DEL:
+               if (zclient->redistribute_route_del)
+                       (*zclient->redistribute_route_del)(command, zclient,
+                                                          length, vrf_id);
                break;
        case ZEBRA_INTERFACE_LINK_PARAMS:
                if (zclient->interface_link_params)
index 40ddbf62df2d121337fe05b39840db37fcd0b780..f454a9d8ac77170320c8896cfa57744a79c3d7ff 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef _ZEBRA_ZCLIENT_H
 #define _ZEBRA_ZCLIENT_H
 
-/* For struct zapi_ipv{4,6}. */
+/* For struct zapi_route. */
 #include "prefix.h"
 
 /* For struct interface and struct connected. */
@@ -87,10 +87,8 @@ typedef enum {
        ZEBRA_BFD_DEST_DEREGISTER,
        ZEBRA_BFD_DEST_UPDATE,
        ZEBRA_BFD_DEST_REPLAY,
-       ZEBRA_REDISTRIBUTE_IPV4_ADD,
-       ZEBRA_REDISTRIBUTE_IPV4_DEL,
-       ZEBRA_REDISTRIBUTE_IPV6_ADD,
-       ZEBRA_REDISTRIBUTE_IPV6_DEL,
+       ZEBRA_REDISTRIBUTE_ROUTE_ADD,
+       ZEBRA_REDISTRIBUTE_ROUTE_DEL,
        ZEBRA_VRF_UNREGISTER,
        ZEBRA_VRF_ADD,
        ZEBRA_VRF_DELETE,
@@ -188,14 +186,10 @@ struct zclient {
        int (*nexthop_update)(int, struct zclient *, uint16_t, vrf_id_t);
        int (*import_check_update)(int, struct zclient *, uint16_t, vrf_id_t);
        int (*bfd_dest_replay)(int, struct zclient *, uint16_t, vrf_id_t);
-       int (*redistribute_route_ipv4_add)(int, struct zclient *, uint16_t,
-                                          vrf_id_t);
-       int (*redistribute_route_ipv4_del)(int, struct zclient *, uint16_t,
-                                          vrf_id_t);
-       int (*redistribute_route_ipv6_add)(int, struct zclient *, uint16_t,
-                                          vrf_id_t);
-       int (*redistribute_route_ipv6_del)(int, struct zclient *, uint16_t,
-                                          vrf_id_t);
+       int (*redistribute_route_add)(int, struct zclient *, uint16_t,
+                                     vrf_id_t);
+       int (*redistribute_route_del)(int, struct zclient *, uint16_t,
+                                     vrf_id_t);
        int (*fec_update)(int, struct zclient *, uint16_t);
        int (*local_vni_add)(int, struct zclient *, uint16_t, vrf_id_t);
        int (*local_vni_del)(int, struct zclient *, uint16_t, vrf_id_t);
@@ -206,13 +200,12 @@ struct zclient {
 
 /* Zebra API message flag. */
 #define ZAPI_MESSAGE_NEXTHOP  0x01
-#define ZAPI_MESSAGE_IFINDEX  0x02
-#define ZAPI_MESSAGE_DISTANCE 0x04
-#define ZAPI_MESSAGE_METRIC   0x08
-#define ZAPI_MESSAGE_TAG      0x10
-#define ZAPI_MESSAGE_MTU      0x20
-#define ZAPI_MESSAGE_SRCPFX   0x40
-#define ZAPI_MESSAGE_LABEL    0x80
+#define ZAPI_MESSAGE_DISTANCE 0x02
+#define ZAPI_MESSAGE_METRIC   0x04
+#define ZAPI_MESSAGE_TAG      0x08
+#define ZAPI_MESSAGE_MTU      0x10
+#define ZAPI_MESSAGE_SRCPFX   0x20
+#define ZAPI_MESSAGE_LABEL    0x40
 
 /* Zserv protocol message header */
 struct zserv_header {
index b744218c9a04379f3873f183cded8783d0fcb86f..4b86bca5f75b1dbd311cf8a9c9bb08a25931a7e7 100644 (file)
@@ -167,83 +167,47 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix
 
 int nhrp_route_read(int cmd, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id)
 {
-       struct stream *s;
+       struct zapi_route api;
+       struct zapi_nexthop *api_nh;
        struct interface *ifp = NULL;
-       struct prefix prefix;
-       struct prefix_ipv6 src_p;
        union sockunion nexthop_addr;
-       unsigned char message, nexthop_num, ifindex_num;
-       unsigned ifindex;
        char buf[2][PREFIX_STRLEN];
-       int i, afaddrlen, added;
+       int added;
 
-       s = zclient->ibuf;
-       memset(&prefix, 0, sizeof(prefix));
-       sockunion_family(&nexthop_addr) = AF_UNSPEC;
-
-       /* Type, flags, message. */
-       /*type =*/ stream_getc(s);
-       /*instance =*/ stream_getw(s);
-       /*flags =*/ stream_getl(s);
-       message = stream_getc(s);
-
-       /* Prefix */
-       switch (cmd) {
-       case ZEBRA_REDISTRIBUTE_IPV4_ADD:
-       case ZEBRA_REDISTRIBUTE_IPV4_DEL:
-               prefix.family = AF_INET;
-               prefix.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s));
-               break;
-       case ZEBRA_REDISTRIBUTE_IPV6_ADD:
-       case ZEBRA_REDISTRIBUTE_IPV6_DEL:
-               prefix.family = AF_INET6;
-               prefix.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s));
-               break;
-       default:
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
                return -1;
-       }
-       afaddrlen = family2addrsize(prefix.family);
-       stream_get(&prefix.u.val, s, PSIZE(prefix.prefixlen));
-
-       memset(&src_p, 0, sizeof(src_p));
-       if (prefix.family == AF_INET6 &&
-           CHECK_FLAG(message, ZAPI_MESSAGE_SRCPFX)) {
-               src_p.family = AF_INET6;
-               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(message, ZAPI_MESSAGE_NEXTHOP|ZAPI_MESSAGE_IFINDEX)) {
-               nexthop_num = stream_getc(s);
-               for (i = 0; i < nexthop_num; i++) {
-                       stream_get(buf[0], s, afaddrlen);
-                       if (i == 0) sockunion_set(&nexthop_addr, prefix.family, (u_char*) buf[0], afaddrlen);
-               }
-               ifindex_num = stream_getc(s);
-               for (i = 0; i < ifindex_num; i++) {
-                       ifindex = stream_getl(s);
-                       if (i == 0 && ifindex != IFINDEX_INTERNAL)
-                          ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
+       sockunion_family(&nexthop_addr) = AF_UNSPEC;
+       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
+               api_nh = &api.nexthops[0];
+
+               nexthop_addr.sa.sa_family = api.prefix.family;
+               switch (nexthop_addr.sa.sa_family) {
+               case AF_INET:
+                       nexthop_addr.sin.sin_addr = api_nh->gate.ipv4;
+                       break;
+               case AF_INET6:
+                       nexthop_addr.sin6.sin6_addr = api_nh->gate.ipv6;
+                       break;
                }
+
+               if (api_nh->ifindex != IFINDEX_INTERNAL)
+                               ifp = if_lookup_by_index(api_nh->ifindex, VRF_DEFAULT);
        }
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
-               /*distance =*/ stream_getc(s);
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
-               /*metric =*/ stream_getl(s);
 
-       added = (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD || cmd == ZEBRA_REDISTRIBUTE_IPV6_ADD);
+       added = (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
        debugf(NHRP_DEBUG_ROUTE, "if-route-%s: %s via %s dev %s",
                added ? "add" : "del",
-               prefix2str(&prefix, buf[0], sizeof buf[0]),
+               prefix2str(&api.prefix, buf[0], sizeof buf[0]),
                sockunion2str(&nexthop_addr, buf[1], sizeof buf[1]),
                ifp ? ifp->name : "(none)");
 
-       nhrp_route_update_zebra(&prefix, &nexthop_addr, ifp);
-       nhrp_shortcut_prefix_change(&prefix, !added);
+       nhrp_route_update_zebra(&api.prefix, &nexthop_addr, ifp);
+       nhrp_shortcut_prefix_change(&api.prefix, !added);
 
        return 0;
 }
@@ -356,10 +320,8 @@ void nhrp_zebra_init(void)
        zclient->interface_down = nhrp_interface_down;
        zclient->interface_address_add = nhrp_interface_address_add;
        zclient->interface_address_delete = nhrp_interface_address_delete;
-       zclient->redistribute_route_ipv4_add = nhrp_route_read;
-       zclient->redistribute_route_ipv4_del = nhrp_route_read;
-       zclient->redistribute_route_ipv6_add = nhrp_route_read;
-       zclient->redistribute_route_ipv6_del = nhrp_route_read;
+       zclient->redistribute_route_add = nhrp_route_read;
+       zclient->redistribute_route_del = nhrp_route_read;
 
        zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0);
 }
@@ -371,4 +333,3 @@ void nhrp_zebra_terminate(void)
        route_table_finish(zebra_rib[AFI_IP]);
        route_table_finish(zebra_rib[AFI_IP6]);
 }
-
index 565550287963986665fe5742160d8506be9b3b07..3443bc47b616acd3900294bbc4c3e1b4daeb71e7 100644 (file)
@@ -207,75 +207,30 @@ static int ospf6_zebra_if_address_update_delete(int command,
        return 0;
 }
 
-static int ospf6_zebra_read_ipv6(int command, struct zclient *zclient,
-                                zebra_size_t length, vrf_id_t vrf_id)
+static int ospf6_zebra_read_route(int command, struct zclient *zclient,
+                                 zebra_size_t length, vrf_id_t vrf_id)
 {
-       struct stream *s;
-       struct zapi_ipv6 api;
+       struct zapi_route api;
        unsigned long ifindex;
-       struct prefix p, src_p;
        struct in6_addr *nexthop;
 
        if (ospf6 == NULL)
                return 0;
 
-       s = zclient->ibuf;
-       ifindex = 0;
-       nexthop = NULL;
-       memset(&api, 0, sizeof(api));
-
-       /* 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));
-       p.family = AF_INET6;
-       p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s));
-       stream_get(&p.u.prefix6, s, PSIZE(p.prefixlen));
-
-       memset(&src_p, 0, sizeof(struct prefix));
-       src_p.family = AF_INET6;
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
-               src_p.prefixlen = stream_getc(s);
-               stream_get(&src_p.u.prefix6, s, PSIZE(src_p.prefixlen));
-       }
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
 
-       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);
-               nexthop = (struct in6_addr *)malloc(api.nexthop_num
-                                                   * sizeof(struct in6_addr));
-               stream_get(nexthop, s,
-                          api.nexthop_num * sizeof(struct in6_addr));
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
-               api.ifindex_num = stream_getc(s);
-               ifindex = 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);
-       else
-               api.metric = 0;
-
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
-               api.tag = stream_getl(s);
-       else
-               api.tag = 0;
+       ifindex = api.nexthops[0].ifindex;
+       nexthop = &api.nexthops[0].gate.ipv6;
 
        if (IS_OSPF6_DEBUG_ZEBRA(RECV)) {
                char prefixstr[PREFIX2STR_BUFFER], nexthopstr[128];
-               prefix2str((struct prefix *)&p, prefixstr, sizeof(prefixstr));
+               prefix2str((struct prefix *)&api.prefix, prefixstr,
+                          sizeof(prefixstr));
                if (nexthop)
                        inet_ntop(AF_INET6, nexthop, nexthopstr,
                                  sizeof(nexthopstr));
@@ -284,20 +239,17 @@ static int ospf6_zebra_read_ipv6(int command, struct zclient *zclient,
 
                zlog_debug(
                        "Zebra Receive route %s: %s %s nexthop %s ifindex %ld tag %" ROUTE_TAG_PRI,
-                       (command == ZEBRA_REDISTRIBUTE_IPV6_ADD ? "add"
-                                                               : "delete"),
+                       (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD ? "add"
+                                                                : "delete"),
                        zebra_route_string(api.type), prefixstr, nexthopstr,
                        ifindex, api.tag);
        }
 
-       if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
-               ospf6_asbr_redistribute_add(api.type, ifindex, &p,
+       if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
+               ospf6_asbr_redistribute_add(api.type, ifindex, &api.prefix,
                                            api.nexthop_num, nexthop, api.tag);
        else
-               ospf6_asbr_redistribute_remove(api.type, ifindex, &p);
-
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP))
-               free(nexthop);
+               ospf6_asbr_redistribute_remove(api.type, ifindex, &api.prefix);
 
        return 0;
 }
@@ -646,10 +598,8 @@ void ospf6_zebra_init(struct thread_master *master)
        zclient->interface_address_add = ospf6_zebra_if_address_update_add;
        zclient->interface_address_delete =
                ospf6_zebra_if_address_update_delete;
-       zclient->redistribute_route_ipv4_add = NULL;
-       zclient->redistribute_route_ipv4_del = NULL;
-       zclient->redistribute_route_ipv6_add = ospf6_zebra_read_ipv6;
-       zclient->redistribute_route_ipv6_del = ospf6_zebra_read_ipv6;
+       zclient->redistribute_route_add = ospf6_zebra_read_route;
+       zclient->redistribute_route_del = ospf6_zebra_read_route;
 
        /* Install command element for zebra node. */
        install_element(VIEW_NODE, &show_ospf6_zebra_cmd);
index 53b68a022b5cb836b33597b6546aca281c953db7..dcb392f1add5129ba9411e7fa64ae6448117ab75 100644 (file)
@@ -873,61 +873,32 @@ void ospf_routemap_unset(struct ospf_redist *red)
 }
 
 /* Zebra route add and delete treatment. */
-static int ospf_zebra_read_ipv4(int command, struct zclient *zclient,
-                               zebra_size_t length, vrf_id_t vrf_id)
+static int ospf_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 zapi_route api;
+       struct prefix_ipv4 p;
        unsigned long ifindex;
        struct in_addr nexthop;
-       struct prefix_ipv4 p;
        struct external_info *ei;
        struct ospf *ospf;
        int i;
 
-       s = zclient->ibuf;
-       ifindex = 0;
-       nexthop.s_addr = 0;
+       ospf = ospf_lookup();
+       if (ospf == NULL)
+               return 0;
 
-       /* Type, flags, message. */
-       api.type = stream_getc(s);
-       api.instance = stream_getw(s);
-       api.flags = stream_getl(s);
-       api.message = stream_getc(s);
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
 
-       /* 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));
+       ifindex = api.nexthops[0].ifindex;
+       nexthop = api.nexthops[0].gate.ipv4;
 
+       memcpy(&p, &api.prefix, sizeof(p));
        if (IPV4_NET127(ntohl(p.prefix.s_addr)))
                return 0;
 
-       /* 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);
-               /* XXX assert(api.ifindex_num == 1); */
-               ifindex = 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);
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
-               api.tag = stream_getl(s);
-       else
-               api.tag = 0;
-
-       ospf = ospf_lookup();
-       if (ospf == NULL)
-               return 0;
-
-       if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) {
+       if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
                /* XXX|HACK|TODO|FIXME:
                 * Maybe we should ignore reject/blackhole routes? Testing shows
                 * that
@@ -942,7 +913,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient,
                 * return 0;
                 */
 
-               /* Protocol tag overwrites all other tag value send by zebra */
+               /* Protocol tag overwrites all other tag value sent by zebra */
                if (ospf->dtag[api.type] > 0)
                        api.tag = ospf->dtag[api.type];
 
@@ -984,7 +955,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient,
                                                            zebra,
                                                            ZEBRA_REDISTRIBUTE))
                                                        zlog_debug(
-                                                               "ospf_zebra_read_ipv4() : %s refreshing LSA",
+                                                               "ospf_zebra_read_route() : %s refreshing LSA",
                                                                inet_ntoa(
                                                                        p.prefix));
                                                ospf_external_lsa_refresh(
@@ -994,7 +965,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient,
                                }
                        }
                }
-       } else /* if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) */
+       } else /* if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */
        {
                ospf_external_info_delete(api.type, api.instance, p);
                if (is_prefix_default(&p))
@@ -1410,8 +1381,8 @@ void ospf_zebra_init(struct thread_master *master, u_short instance)
        zclient->interface_address_delete = ospf_interface_address_delete;
        zclient->interface_link_params = ospf_interface_link_params;
 
-       zclient->redistribute_route_ipv4_add = ospf_zebra_read_ipv4;
-       zclient->redistribute_route_ipv4_del = ospf_zebra_read_ipv4;
+       zclient->redistribute_route_add = ospf_zebra_read_route;
+       zclient->redistribute_route_del = ospf_zebra_read_route;
 
        access_list_add_hook(ospf_filter_update);
        access_list_delete_hook(ospf_filter_update);
index 9a9bac51e09074ef0c3a6d1e8608c61bc392d7be..2140e8b1101df96748c04e6e44604cda0c3269e5 100644 (file)
@@ -115,64 +115,31 @@ void rip_zebra_ipv4_delete(struct route_node *rp)
 }
 
 /* Zebra route add and delete treatment. */
-static int rip_zebra_read_ipv4(int command, struct zclient *zclient,
-                              zebra_size_t length, vrf_id_t vrf_id)
+static int rip_zebra_read_route(int command, struct zclient *zclient,
+                               zebra_size_t length, vrf_id_t vrf_id)
 {
-       struct stream *s;
-       struct zapi_ipv4 api;
-       unsigned long ifindex;
+       struct zapi_route api;
        struct in_addr nexthop;
-       struct prefix_ipv4 p;
+       unsigned long ifindex;
 
        if (!rip)
                return 0;
 
-       s = zclient->ibuf;
-       ifindex = 0;
-       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);
-       }
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
-               api.distance = stream_getc(s);
-       else
-               api.distance = 255;
-       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;
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
+
+       nexthop = api.nexthops[0].gate.ipv4;
+       ifindex = api.nexthops[0].ifindex;
 
        /* Then fetch IPv4 prefixes. */
-       if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD)
-               rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE, &p,
-                                    ifindex, &nexthop, api.metric,
-                                    api.distance, api.tag);
-       else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL)
-               rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE, &p,
+       if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
+               rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE,
+                                    (struct prefix_ipv4 *)&api.prefix, ifindex,
+                                    &nexthop, api.metric, api.distance,
+                                    api.tag);
+       else if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL)
+               rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE,
+                                       (struct prefix_ipv4 *)&api.prefix,
                                        ifindex);
 
        return 0;
@@ -625,8 +592,8 @@ void rip_zclient_init(struct thread_master *master)
        zclient->interface_address_delete = rip_interface_address_delete;
        zclient->interface_up = rip_interface_up;
        zclient->interface_down = rip_interface_down;
-       zclient->redistribute_route_ipv4_add = rip_zebra_read_ipv4;
-       zclient->redistribute_route_ipv4_del = rip_zebra_read_ipv4;
+       zclient->redistribute_route_add = rip_zebra_read_route;
+       zclient->redistribute_route_del = rip_zebra_read_route;
 
        /* Install command elements to rip node. */
        install_element(RIP_NODE, &rip_redistribute_type_cmd);
index a5ed5c7b2c507b78d99f03a9626e2b1a46ab3385..283d8691a3db243ffc4596a4c243b545d03df8c6 100644 (file)
@@ -109,71 +109,31 @@ void ripng_zebra_ipv6_delete(struct route_node *rp)
 }
 
 /* Zebra route add and delete treatment. */
-static int ripng_zebra_read_ipv6(int command, struct zclient *zclient,
-                                zebra_size_t length, vrf_id_t vrf_id)
+static int ripng_zebra_read_route(int command, struct zclient *zclient,
+                                 zebra_size_t length, vrf_id_t vrf_id)
 {
-       struct stream *s;
-       struct zapi_ipv6 api;
-       unsigned long ifindex;
+       struct zapi_route api;
        struct in6_addr nexthop;
-       struct prefix_ipv6 p, src_p;
-
-       s = zclient->ibuf;
-       ifindex = 0;
-       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));
-       }
+       unsigned long ifindex;
 
-       if (src_p.prefixlen)
-               /* we completely ignore srcdest routes for now. */
-               return 0;
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
 
-       /* 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);
-       }
-       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;
+       /* 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;
+       nexthop = api.nexthops[0].gate.ipv6;
+       ifindex = api.nexthops[0].ifindex;
 
-       if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
-               ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE, &p,
+       if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
+               ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE,
+                                      (struct prefix_ipv6 *)&api.prefix,
                                       ifindex, &nexthop, api.tag);
        else
                ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE,
-                                         &p, ifindex);
+                                         (struct prefix_ipv6 *)&api.prefix,
+                                         ifindex);
 
        return 0;
 }
@@ -461,8 +421,8 @@ void zebra_init(struct thread_master *master)
        zclient->interface_delete = ripng_interface_delete;
        zclient->interface_address_add = ripng_interface_address_add;
        zclient->interface_address_delete = ripng_interface_address_delete;
-       zclient->redistribute_route_ipv6_add = ripng_zebra_read_ipv6;
-       zclient->redistribute_route_ipv6_del = ripng_zebra_read_ipv6;
+       zclient->redistribute_route_add = ripng_zebra_read_route;
+       zclient->redistribute_route_del = ripng_zebra_read_route;
 
        /* Install command elements to ripng node */
        install_element(RIPNG_NODE, &ripng_redistribute_type_cmd);
index 410ddcd4a00c783cb13726ef364d7a3af12f992c..9b21eb4d8c1a9c0b81daa353240c6a589a474c39 100644 (file)
@@ -95,8 +95,8 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id)
                RNODE_FOREACH_RE(rn, newre)
                if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED)
                    && newre->distance != DISTANCE_INFINITY)
-                       zsend_redistribute_route(1, client, &rn->p, NULL,
-                                                newre);
+                       zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
+                                                client, &rn->p, NULL, newre);
 
                route_unlock_node(rn);
        }
@@ -141,8 +141,8 @@ static void zebra_redistribute(struct zserv *client, int type, u_short instance,
                        if (!zebra_check_addr(dst_p))
                                continue;
 
-                       zsend_redistribute_route(1, client, dst_p, src_p,
-                                                newre);
+                       zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
+                                                client, dst_p, src_p, newre);
                }
 }
 
@@ -191,7 +191,8 @@ void redistribute_update(struct prefix *p, struct prefix *src_p,
                        send_redistribute = 1;
 
                if (send_redistribute) {
-                       zsend_redistribute_route(1, client, p, src_p, re);
+                       zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
+                                                client, p, src_p, re);
                } else if (prev_re
                           && ((re->instance
                                && redist_check_instance(
@@ -201,7 +202,8 @@ void redistribute_update(struct prefix *p, struct prefix *src_p,
                               || vrf_bitmap_check(
                                          client->redist[afi][prev_re->type],
                                          re->vrf_id))) {
-                       zsend_redistribute_route(0, client, p, src_p, prev_re);
+                       zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
+                                                client, p, src_p, prev_re);
                }
        }
 }
@@ -242,7 +244,8 @@ void redistribute_delete(struct prefix *p, struct prefix *src_p,
                                   re->instance))
                    || vrf_bitmap_check(client->redist[afi][re->type],
                                        re->vrf_id)) {
-                       zsend_redistribute_route(0, client, p, src_p, re);
+                       zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
+                                                client, p, src_p, re);
                }
        }
 }
index de475dccfdd2cf824908af5d780c95c9760cd1df..56cca10654d59ce795b602e46d79135e447baa9c 100644 (file)
@@ -592,193 +592,76 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp)
        return zebra_server_send_message(client);
 }
 
-/*
- * This is the new function to announce and withdraw redistributed routes, used
- * by Zebra. This is the old zsend_route_multipath() function. That function
- * was duplicating code to send a lot of information that was essentially thrown
- * away or ignored by the receiver. This is the leaner function that is not a
- * duplicate of the zapi_ipv4_route_add/del.
- *
- * The primary difference is that this function merely sends a single NH instead
- * of
- * all the nexthops.
- */
-int zsend_redistribute_route(int add, struct zserv *client, struct prefix *p,
+int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
                             struct prefix *src_p, struct route_entry *re)
 {
-       afi_t afi;
-       int cmd;
-       int psize;
-       struct stream *s;
+       struct zapi_route api;
+       struct zapi_nexthop *api_nh;
        struct nexthop *nexthop;
-       unsigned long nhnummark = 0, messmark = 0;
-       int nhnum = 0;
-       u_char zapi_flags = 0;
-       struct nexthop dummy_nh;
-
-       afi = family2afi(p->family);
-       if (add) {
-               switch (afi) {
-               case AFI_IP:
-                       cmd = ZEBRA_REDISTRIBUTE_IPV4_ADD;
-                       client->redist_v4_add_cnt++;
-                       break;
-               case AFI_IP6:
-                       cmd = ZEBRA_REDISTRIBUTE_IPV6_ADD;
-                       client->redist_v6_add_cnt++;
-                       break;
-               default:
-                       return -1;
-               }
-       } else {
-               switch (afi) {
-               case AFI_IP:
-                       cmd = ZEBRA_REDISTRIBUTE_IPV4_DEL;
-                       client->redist_v4_del_cnt++;
-                       break;
-               case AFI_IP6:
-                       cmd = ZEBRA_REDISTRIBUTE_IPV6_DEL;
-                       client->redist_v6_del_cnt++;
-                       break;
-               default:
-                       return -1;
-               }
-       }
-
-       s = client->obuf;
-       stream_reset(s);
-       memset(&dummy_nh, 0, sizeof(struct nexthop));
+       int count = 0;
 
-       zserv_create_header(s, cmd, re->vrf_id);
-
-       /* Put type and nexthop. */
-       stream_putc(s, re->type);
-       stream_putw(s, re->instance);
-       stream_putl(s, re->flags);
-
-       /* marker for message flags field */
-       messmark = stream_get_endp(s);
-       stream_putc(s, 0);
+       memset(&api, 0, sizeof(api));
+       api.vrf_id = VRF_DEFAULT;
+       api.type = re->type;
+       api.instance = re->instance;
+       api.flags = re->flags;
 
        /* Prefix. */
-       psize = PSIZE(p->prefixlen);
-       stream_putc(s, p->prefixlen);
-       stream_write(s, (u_char *)&p->u.prefix, psize);
-
+       api.prefix = *p;
        if (src_p) {
-               SET_FLAG(zapi_flags, ZAPI_MESSAGE_SRCPFX);
-               psize = PSIZE(src_p->prefixlen);
-               stream_putc(s, src_p->prefixlen);
-               stream_write(s, (u_char *)&src_p->u.prefix, psize);
+               SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
+               memcpy(&api.src_prefix, src_p, sizeof(api.src_prefix));
        }
 
+       /* Nexthops. */
+       if (re->nexthop_active_num) {
+               SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+               api.nexthop_num = re->nexthop_active_num;
+       }
        for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) {
-               /* We don't send any nexthops when there's a multipath */
-               if (re->nexthop_active_num > 1
-                   && client->proto != ZEBRA_ROUTE_LDP) {
-                       SET_FLAG(zapi_flags, ZAPI_MESSAGE_NEXTHOP);
-                       SET_FLAG(zapi_flags, ZAPI_MESSAGE_IFINDEX);
-
-                       stream_putc(s, 1);
-                       if (p->family == AF_INET) {
-                               stream_put_in_addr(s, &dummy_nh.gate.ipv4);
-                       } else if (p->family == AF_INET6) {
-                               stream_write(s, (u_char *)&dummy_nh.gate.ipv6,
-                                            16);
-                       } else {
-                               /* We don't handle anything else now, abort */
-                               zlog_err(
-                                       "%s: Unable to redistribute route of unknown family, %d\n",
-                                       __func__, p->family);
-                               return -1;
-                       }
-                       stream_putc(s, 1);
-                       stream_putl(s, 0); /* dummy ifindex */
-                       break;
-               }
-
-               if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) {
-                       SET_FLAG(zapi_flags, ZAPI_MESSAGE_NEXTHOP);
-                       SET_FLAG(zapi_flags, ZAPI_MESSAGE_IFINDEX);
-                       if (nhnummark == 0) {
-                               nhnummark = stream_get_endp(s);
-                               stream_putc(s, 1); /* placeholder */
-                       }
-                       nhnum++;
-
-                       switch (nexthop->type) {
-                       case NEXTHOP_TYPE_IPV4:
-                       case NEXTHOP_TYPE_IPV4_IFINDEX:
-                               stream_put_in_addr(s, &nexthop->gate.ipv4);
-                               break;
-                       case NEXTHOP_TYPE_IPV6:
-                       case NEXTHOP_TYPE_IPV6_IFINDEX:
-                               /* Only BGP supports IPv4 prefix with IPv6 NH,
-                                * so kill this */
-                               if (p->family == AF_INET)
-                                       stream_put_in_addr(s,
-                                                          &dummy_nh.gate.ipv4);
-                               else
-                                       stream_write(
-                                               s,
-                                               (u_char *)&nexthop->gate.ipv6,
-                                               16);
-                               break;
-                       default:
-                               if (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD
-                                   || cmd == ZEBRA_REDISTRIBUTE_IPV4_DEL) {
-                                       struct in_addr empty;
-                                       memset(&empty, 0,
-                                              sizeof(struct in_addr));
-                                       stream_write(s, (u_char *)&empty,
-                                                    IPV4_MAX_BYTELEN);
-                               } else {
-                                       struct in6_addr empty;
-                                       memset(&empty, 0,
-                                              sizeof(struct in6_addr));
-                                       stream_write(s, (u_char *)&empty,
-                                                    IPV6_MAX_BYTELEN);
-                               }
-                       }
-
-                       /* Interface index. */
-                       stream_putc(s, 1);
-                       stream_putl(s, nexthop->ifindex);
+               if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+                       continue;
 
-                       /* ldpd needs all nexthops */
-                       if (client->proto != ZEBRA_ROUTE_LDP)
-                               break;
+               api_nh = &api.nexthops[count];
+               api_nh->type = nexthop->type;
+               switch (nexthop->type) {
+               case NEXTHOP_TYPE_BLACKHOLE:
+                       break;
+               case NEXTHOP_TYPE_IPV4:
+                       api_nh->gate.ipv4 = nexthop->gate.ipv4;
+                       break;
+               case NEXTHOP_TYPE_IPV4_IFINDEX:
+                       api_nh->gate.ipv4 = nexthop->gate.ipv4;
+                       api_nh->ifindex = nexthop->ifindex;
+                       break;
+               case NEXTHOP_TYPE_IFINDEX:
+                       api_nh->ifindex = nexthop->ifindex;
+                       break;
+               case NEXTHOP_TYPE_IPV6:
+                       api_nh->gate.ipv6 = nexthop->gate.ipv6;
+                       break;
+               case NEXTHOP_TYPE_IPV6_IFINDEX:
+                       api_nh->gate.ipv6 = nexthop->gate.ipv6;
+                       api_nh->ifindex = nexthop->ifindex;
                }
+               count++;
        }
 
-       /* Distance */
-       SET_FLAG(zapi_flags, ZAPI_MESSAGE_DISTANCE);
-       stream_putc(s, re->distance);
-
-       /* Metric */
-       SET_FLAG(zapi_flags, ZAPI_MESSAGE_METRIC);
-       stream_putl(s, re->metric);
-
-       /* Tag */
+       /* Attributes. */
+       SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
+       api.distance = re->distance;
+       SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
+       api.metric = re->metric;
        if (re->tag) {
-               SET_FLAG(zapi_flags, ZAPI_MESSAGE_TAG);
-               stream_putl(s, re->tag);
+               SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
+               api.tag = re->tag;
        }
+       SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
+       api.mtu = re->mtu;
 
-       /* MTU */
-       SET_FLAG(zapi_flags, ZAPI_MESSAGE_MTU);
-       stream_putl(s, re->mtu);
-
-       /* write real message flags value */
-       stream_putc_at(s, messmark, zapi_flags);
-
-       /* Write next-hop number */
-       if (nhnummark)
-               stream_putc_at(s, nhnummark, nhnum);
-
-       /* Write packet size. */
-       stream_putw_at(s, 0, stream_get_endp(s));
-
+       /* Encode route and send. */
+       if (zapi_route_encode(cmd, client->obuf, &api) < 0)
+               return -1;
        return zebra_server_send_message(client);
 }