]> git.proxmox.com Git - mirror_frr.git/commitdiff
zebra: rib: use nexthop ptr in rib_add/delete
authorDavid Lamparter <equinox@opensourcerouting.org>
Sun, 27 Aug 2017 23:30:16 +0000 (01:30 +0200)
committerDavid Lamparter <equinox@opensourcerouting.org>
Mon, 28 Aug 2017 02:17:22 +0000 (04:17 +0200)
This simplifies the API for the following blackhole rework.

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
lib/nexthop.c
lib/nexthop.h
zebra/connected.c
zebra/kernel_socket.c
zebra/redistribute.c
zebra/rib.h
zebra/rt_netlink.c
zebra/rtread_getmsg.c
zebra/zebra_rib.c

index 7180be33dd852ab0bdccdcddefbc9e53c0fd446b..2dba412f452b1140b2fbba5280ab56d1a74a8a2f 100644 (file)
@@ -36,7 +36,8 @@ DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop")
 DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label")
 
 /* check if nexthops are same, non-recursive */
-int nexthop_same_no_recurse(struct nexthop *next1, struct nexthop *next2)
+int nexthop_same_no_recurse(const struct nexthop *next1,
+                           const struct nexthop *next2)
 {
        if (next1->type != next2->type)
                return 0;
index 12a1203a8fa7c47199386a42daa8632068a18867..7cfba5c5b693a698c1b6f2e2d2c0731e052be5f2 100644 (file)
@@ -135,8 +135,8 @@ void nexthop_add_labels(struct nexthop *, enum lsp_types_t, u_int8_t,
 void nexthop_del_labels(struct nexthop *);
 
 extern const char *nexthop_type_to_str(enum nexthop_types_t nh_type);
-extern int nexthop_same_no_recurse(struct nexthop *next1,
-                                  struct nexthop *next2);
+extern int nexthop_same_no_recurse(const struct nexthop *next1,
+                                  const struct nexthop *next2);
 extern int nexthop_labels_match(struct nexthop *nh1, struct nexthop *nh2);
 
 extern const char *nexthop2str(struct nexthop *nexthop, char *str, int size);
index 701314f2461acd56423217b842712ecd3d7577b1..3f8b80b97b42728580c3f5c1622d8a0c1626692a 100644 (file)
@@ -177,6 +177,10 @@ static void connected_update(struct interface *ifp, struct connected *ifc)
 void connected_up_ipv4(struct interface *ifp, struct connected *ifc)
 {
        struct prefix p;
+       struct nexthop nh = {
+               .type = NEXTHOP_TYPE_IFINDEX,
+               .ifindex = ifp->ifindex,
+       };
 
        if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
                return;
@@ -192,12 +196,10 @@ void connected_up_ipv4(struct interface *ifp, struct connected *ifc)
                return;
 
        rib_add(AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
-               &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric,
-               0, 0);
+               &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0);
 
        rib_add(AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
-               &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric,
-               0, 0);
+               &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0);
 
        if (IS_ZEBRA_DEBUG_RIB_DETAILED)
                zlog_debug(
@@ -306,6 +308,10 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
 void connected_down_ipv4(struct interface *ifp, struct connected *ifc)
 {
        struct prefix p;
+       struct nexthop nh = {
+               .type = NEXTHOP_TYPE_IFINDEX,
+               .ifindex = ifp->ifindex,
+       };
 
        if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
                return;
@@ -323,10 +329,10 @@ void connected_down_ipv4(struct interface *ifp, struct connected *ifc)
        /* Same logic as for connected_up_ipv4(): push the changes into the
         * head. */
        rib_delete(AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
-                  &p, NULL, NULL, ifp->ifindex, 0, 0);
+                  &p, NULL, &nh, 0, 0);
 
        rib_delete(AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
-                  0, &p, NULL, NULL, ifp->ifindex, 0, 0);
+                  0, &p, NULL, &nh, 0, 0);
 
        if (IS_ZEBRA_DEBUG_RIB_DETAILED)
                zlog_debug(
@@ -384,6 +390,10 @@ void connected_delete_ipv4(struct interface *ifp, int flags,
 void connected_up_ipv6(struct interface *ifp, struct connected *ifc)
 {
        struct prefix p;
+       struct nexthop nh = {
+               .type = NEXTHOP_TYPE_IFINDEX,
+               .ifindex = ifp->ifindex,
+       };
 
        if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
                return;
@@ -400,8 +410,7 @@ void connected_up_ipv6(struct interface *ifp, struct connected *ifc)
 #endif
 
        rib_add(AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
-               &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric,
-               0, 0);
+               &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0);
 
        if (IS_ZEBRA_DEBUG_RIB_DETAILED)
                zlog_debug(
@@ -489,6 +498,10 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
 void connected_down_ipv6(struct interface *ifp, struct connected *ifc)
 {
        struct prefix p;
+       struct nexthop nh = {
+               .type = NEXTHOP_TYPE_IFINDEX,
+               .ifindex = ifp->ifindex,
+       };
 
        if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
                return;
@@ -501,7 +514,7 @@ void connected_down_ipv6(struct interface *ifp, struct connected *ifc)
                return;
 
        rib_delete(AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
-                  0, &p, NULL, NULL, ifp->ifindex, 0, 0);
+                  0, &p, NULL, &nh, 0, 0);
 
        if (IS_ZEBRA_DEBUG_RIB_DETAILED)
                zlog_debug(
index e2a1deb9ac691e11d16fe08446250e2f0c6a1166..ee21e61fe726dae0cf8c6e4c6a6a9b841a2c4dca 100644 (file)
@@ -849,6 +849,7 @@ void rtm_read(struct rt_msghdr *rtm)
        union sockunion dest, mask, gate;
        char ifname[INTERFACE_NAMSIZ + 1];
        short ifnlen = 0;
+       struct nexthop nh;
 
        zebra_flags = 0;
 
@@ -1015,19 +1016,22 @@ void rtm_read(struct rt_msghdr *rtm)
                 */
                if (rtm->rtm_type == RTM_CHANGE)
                        rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
-                                  ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
-                                  NULL, 0, 0, 0);
+                                  ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p,
+                                  NULL, 0, 0);
+
+               memset(&nh, 0, sizeof(nh));
+               nh.type = NEXTHOP_TYPE_IPV4;
+               nh.gate.ipv4 = gate.sin;
 
-               union g_addr ggate = {.ipv4 = gate.sin.sin_addr};
                if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
                    || rtm->rtm_type == RTM_CHANGE)
                        rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
                                ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
-                               &ggate, NULL, 0, 0, 0, 0, 0);
+                               &nh, 0, 0, 0, 0);
                else
                        rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
                                   ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
-                                  &ggate, 0, 0, 0);
+                                  &nh, 0, 0);
        }
        if (dest.sa.sa_family == AF_INET6) {
                /* One day we might have a debug section here like one in the
@@ -1057,19 +1061,24 @@ void rtm_read(struct rt_msghdr *rtm)
                 */
                if (rtm->rtm_type == RTM_CHANGE)
                        rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
-                                  ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
-                                  NULL, 0, 0, 0);
+                                  ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p,
+                                  NULL, NULL, 0, 0);
+
+               memset(&nh, 0, sizeof(nh));
+               nh.type = ifindex ? NEXTHOP_TYPE_IPV6_IFINDEX
+                                 : NEXTHOP_TYPE_IPV6;
+               nh.gate.ipv6 = gate.sin6;
+               nh.ifindex = ifindex;
 
-               union g_addr ggate = {.ipv6 = gate.sin6.sin6_addr};
                if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
                    || rtm->rtm_type == RTM_CHANGE)
                        rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
                                ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
-                               &ggate, NULL, ifindex, 0, 0, 0, 0);
+                               &nh, 0, 0, 0, 0);
                else
                        rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
                                   ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
-                                  &ggate, ifindex, 0, 0);
+                                  &nh, 0, 0);
        }
 }
 
index 9b21eb4d8c1a9c0b81daa353240c6a589a474c39..39083ad3b7e7384cf6ec52d9faa606c3ab5db1a7 100644 (file)
@@ -496,8 +496,6 @@ int zebra_add_import_table_entry(struct route_node *rn, struct route_entry *re,
        struct route_entry *newre;
        struct route_entry *same;
        struct prefix p;
-       struct nexthop *nhop;
-       union g_addr *gate;
        route_map_result_t ret = RMAP_MATCH;
 
        if (rmap_name)
@@ -529,17 +527,10 @@ int zebra_add_import_table_entry(struct route_node *rn, struct route_entry *re,
 
 
                        if (re->nexthop_num == 1) {
-                               nhop = re->nexthop;
-                               if (nhop->type == NEXTHOP_TYPE_IFINDEX)
-                                       gate = NULL;
-                               else
-                                       gate = (union g_addr *)&nhop->gate.ipv4;
-
                                rib_add(AFI_IP, SAFI_UNICAST, re->vrf_id,
                                        ZEBRA_ROUTE_TABLE, re->table, 0, &p,
-                                       NULL, gate,
-                                       (union g_addr *)&nhop->src.ipv4,
-                                       nhop->ifindex, zebrad.rtm_table_default,
+                                       NULL, re->nexthop,
+                                       zebrad.rtm_table_default,
                                        re->metric, re->mtu,
                                        zebra_import_table_distance[AFI_IP]
                                                                   [re->table]);
@@ -580,7 +571,7 @@ int zebra_del_import_table_entry(struct route_node *rn, struct route_entry *re)
                p.u.prefix4 = rn->p.u.prefix4;
 
                rib_delete(AFI_IP, SAFI_UNICAST, re->vrf_id, ZEBRA_ROUTE_TABLE,
-                          re->table, re->flags, &p, NULL, NULL, 0,
+                          re->table, re->flags, &p, NULL, NULL,
                           zebrad.rtm_table_default, re->metric);
        }
        /* DD: Add IPv6 code */
index 495b731e885a973a28cafce6246e66e50da7ec91..9e456e436f09bb3ce30fb39dfd7b9542b9477d46 100644 (file)
@@ -294,18 +294,17 @@ extern int rib_uninstall_kernel(struct route_node *rn, struct route_entry *re);
  * also implicitly withdraw equal prefix of same type. */
 extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                   u_short instance, int flags, struct prefix *p,
-                  struct prefix_ipv6 *src_p, union g_addr *gate,
-                  union g_addr *src, ifindex_t ifindex, u_int32_t table_id,
-                  u_int32_t metric, u_int32_t mtu, u_char distance);
+                  struct prefix_ipv6 *src_p, const struct nexthop *nh,
+                  u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
+                  u_char distance);
 
 extern int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *,
                             struct prefix_ipv6 *src_p, struct route_entry *);
 
 extern void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                       u_short instance, int flags, struct prefix *p,
-                      struct prefix_ipv6 *src_p, union g_addr *gate,
-                      ifindex_t ifindex, u_int32_t table_id,
-                      u_int32_t metric);
+                      struct prefix_ipv6 *src_p, const struct nexthop *nh,
+                      u_int32_t table_id, u_int32_t metric);
 
 extern struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t,
                                     union g_addr *,
index e28fe5630aeeb53360bc073599f099e2259c498b..ec19c53b7350dbac33eca0f93affa76c78d23d90 100644 (file)
@@ -365,11 +365,31 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
                afi = AFI_IP6;
 
        if (h->nlmsg_type == RTM_NEWROUTE) {
-               if (!tb[RTA_MULTIPATH])
+               if (!tb[RTA_MULTIPATH]) {
+                       struct nexthop nh;
+                       size_t sz = (afi == AFI_IP) ? 4 : 16;
+
+                       memset(&nh, 0, sizeof(nh));
+                       if (index && !gate)
+                               nh.type = NEXTHOP_TYPE_IFINDEX;
+                       else if (index && gate)
+                               nh.type = (afi == AFI_IP)
+                                       ? NEXTHOP_TYPE_IPV4_IFINDEX
+                                       : NEXTHOP_TYPE_IPV6_IFINDEX;
+                       else if (!index && gate)
+                               nh.type = (afi == AFI_IP)
+                                       ? NEXTHOP_TYPE_IPV4
+                                       : NEXTHOP_TYPE_IPV6;
+                       else
+                               nh.type = NEXTHOP_TYPE_BLACKHOLE;
+                       nh.ifindex = index;
+                       if (prefsrc)
+                               memcpy(&nh.src, prefsrc, sz);
+                       if (gate)
+                               memcpy(&nh.gate, gate, sz);
                        rib_add(afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
-                               0, flags, &p, NULL, gate, prefsrc, index, table,
-                               metric, mtu, 0);
-               else {
+                               0, flags, &p, NULL, &nh, table, metric, mtu, 0);
+               } else {
                        /* This is a multipath route */
 
                        struct route_entry *re;
@@ -444,41 +464,35 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
                                                  NULL, re);
                }
        } else {
-               if (!tb[RTA_MULTIPATH])
+               if (!tb[RTA_MULTIPATH]) {
+                       struct nexthop nh;
+                       size_t sz = (afi == AFI_IP) ? 4 : 16;
+
+                       memset(&nh, 0, sizeof(nh));
+                       if (index && !gate)
+                               nh.type = NEXTHOP_TYPE_IFINDEX;
+                       else if (index && gate)
+                               nh.type = (afi == AFI_IP)
+                                       ? NEXTHOP_TYPE_IPV4_IFINDEX
+                                       : NEXTHOP_TYPE_IPV6_IFINDEX;
+                       else if (!index && gate)
+                               nh.type = (afi == AFI_IP)
+                                       ? NEXTHOP_TYPE_IPV4
+                                       : NEXTHOP_TYPE_IPV6;
+                       else
+                               nh.type = NEXTHOP_TYPE_BLACKHOLE;
+                       nh.ifindex = index;
+                       if (gate)
+                               memcpy(&nh.gate, gate, sz);
                        rib_delete(afi, SAFI_UNICAST, vrf_id,
-                                  ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL, gate,
-                                  index, table, metric);
-               else {
-                       struct rtnexthop *rtnh =
-                               (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
-
-                       len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
-
-                       for (;;) {
-                               if (len < (int)sizeof(*rtnh)
-                                   || rtnh->rtnh_len > len)
-                                       break;
-
-                               gate = NULL;
-                               if (rtnh->rtnh_len > sizeof(*rtnh)) {
-                                       memset(tb, 0, sizeof(tb));
-                                       netlink_parse_rtattr(
-                                               tb, RTA_MAX, RTNH_DATA(rtnh),
-                                               rtnh->rtnh_len - sizeof(*rtnh));
-                                       if (tb[RTA_GATEWAY])
-                                               gate = RTA_DATA(
-                                                       tb[RTA_GATEWAY]);
-                               }
-
-                               if (gate)
-                                       rib_delete(afi, SAFI_UNICAST, vrf_id,
-                                                  ZEBRA_ROUTE_KERNEL, 0, flags,
-                                                  &p, NULL, gate, index,
-                                                  table, metric);
-
-                               len -= NLMSG_ALIGN(rtnh->rtnh_len);
-                               rtnh = RTNH_NEXT(rtnh);
-                       }
+                                  ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL, &nh,
+                                  table, metric);
+               } else {
+                       /* XXX: need to compare the entire list of nexthops
+                        * here for NLM_F_APPEND stupidity */
+                       rib_delete(afi, SAFI_UNICAST, vrf_id,
+                                  ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL,
+                                  NULL, table, metric);
                }
        }
 
index 1bba003a0a084820637d5b813cbc73706d0362a7..62f3224b6e874db7c120b91dbb352dcb9b6a0b99 100644 (file)
@@ -75,8 +75,8 @@
 static void handle_route_entry(mib2_ipRouteEntry_t *routeEntry)
 {
        struct prefix prefix;
-       struct in_addr tmpaddr, gateway;
-       union g_addr *ggateway;
+       struct in_addr tmpaddr;
+       struct nexthop nh;
        u_char zebra_flags = 0;
 
        if (routeEntry->ipRouteInfo.re_ire_type & IRE_CACHETABLE)
@@ -93,11 +93,12 @@ static void handle_route_entry(mib2_ipRouteEntry_t *routeEntry)
        tmpaddr.s_addr = routeEntry->ipRouteMask;
        prefix.prefixlen = ip_masklen(tmpaddr);
 
-       gateway.s_addr = routeEntry->ipRouteNextHop;
-       ggateway = (union g_addr *)&gateway;
+       memset(&nh, 0, sizeof(nh));
+       nh.type = NEXTHOP_TYPE_IPV4;
+       nh.gate.ipv4.s_addr = routeEntry->ipRouteNextHop;
 
        rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0,
-               zebra_flags, &prefix, NULL, ggateway, NULL, 0, 0, 0, 0, 0);
+               zebra_flags, &prefix, NULL, &nh, 0, 0, 0, 0);
 }
 
 void route_read(struct zebra_ns *zns)
index dc61ea5e40c14a3211c89af7b8ba7393071af4e0..644f48793ab627582a060459c0d8c9c40537747e 100644 (file)
@@ -2273,16 +2273,15 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
 
 void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                u_short instance, int flags, struct prefix *p,
-               struct prefix_ipv6 *src_p, union g_addr *gate,
-               ifindex_t ifindex, u_int32_t table_id,
-               u_int32_t metric)
+               struct prefix_ipv6 *src_p, const struct nexthop *nh,
+               u_int32_t table_id, u_int32_t metric)
 {
        struct route_table *table;
        struct route_node *rn;
        struct route_entry *re;
        struct route_entry *fib = NULL;
        struct route_entry *same = NULL;
-       struct nexthop *nexthop;
+       struct nexthop *rtnh;
        char buf2[INET6_ADDRSTRLEN];
 
        assert(!src_p || afi == AFI_IP6);
@@ -2332,9 +2331,9 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                if (re->type == ZEBRA_ROUTE_KERNEL &&
                    re->metric != metric)
                        continue;
-               if (re->type == ZEBRA_ROUTE_CONNECT && (nexthop = re->nexthop)
-                   && nexthop->type == NEXTHOP_TYPE_IFINDEX) {
-                       if (nexthop->ifindex != ifindex)
+               if (re->type == ZEBRA_ROUTE_CONNECT && (rtnh = re->nexthop)
+                   && rtnh->type == NEXTHOP_TYPE_IFINDEX && nh) {
+                       if (rtnh->ifindex != nh->ifindex)
                                continue;
                        if (re->refcnt) {
                                re->refcnt--;
@@ -2347,14 +2346,12 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                }
                /* Make sure that the route found has the same gateway. */
                else {
-                       if (gate == NULL) {
+                       if (nh == NULL) {
                                same = re;
                                break;
                        }
-                       for (ALL_NEXTHOPS(re->nexthop, nexthop))
-                               if (IPV4_ADDR_SAME(&nexthop->gate.ipv4, &gate->ipv4)
-                                   || IPV6_ADDR_SAME(&nexthop->gate.ipv6,
-                                                     gate)) {
+                       for (ALL_NEXTHOPS(re->nexthop, rtnh))
+                               if (nexthop_same_no_recurse(rtnh, nh)) {
                                        same = re;
                                        break;
                                }
@@ -2375,9 +2372,9 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                        }
                        if (allow_delete) {
                                /* Unset flags. */
-                               for (nexthop = fib->nexthop; nexthop;
-                                    nexthop = nexthop->next)
-                                       UNSET_FLAG(nexthop->flags,
+                               for (rtnh = fib->nexthop; rtnh;
+                                    rtnh = rtnh->next)
+                                       UNSET_FLAG(rtnh->flags,
                                                   NEXTHOP_FLAG_FIB);
 
                                UNSET_FLAG(fib->status,
@@ -2391,22 +2388,22 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                        }
                } else {
                        if (IS_ZEBRA_DEBUG_RIB) {
-                               if (gate)
+                               if (nh)
                                        rnode_debug(
                                                rn, vrf_id,
                                                "via %s ifindex %d type %d "
                                                "doesn't exist in rib",
                                                inet_ntop(
-                                                       family2afi(afi), gate,
+                                                       family2afi(afi), &nh->gate,
                                                        buf2,
                                                        INET_ADDRSTRLEN), /* FIXME
                                                                             */
-                                               ifindex, type);
+                                               nh->ifindex, type);
                                else
                                        rnode_debug(
                                                rn, vrf_id,
-                                               "ifindex %d type %d doesn't exist in rib",
-                                               ifindex, type);
+                                               "type %d doesn't exist in rib",
+                                               type);
                        }
                        route_unlock_node(rn);
                        return;
@@ -2423,15 +2420,14 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
 
 int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
            int flags, struct prefix *p, struct prefix_ipv6 *src_p,
-           union g_addr *gate, union g_addr *src, ifindex_t ifindex,
-           u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
-           u_char distance)
+           const struct nexthop *nh, u_int32_t table_id, u_int32_t metric,
+           u_int32_t mtu, u_char distance)
 {
        struct route_entry *re;
        struct route_entry *same = NULL;
        struct route_table *table;
        struct route_node *rn;
-       struct nexthop *nexthop;
+       struct nexthop *rtnh;
 
        assert(!src_p || afi == AFI_IP6);
 
@@ -2480,9 +2476,9 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
                        break;
                }
                /* Duplicate system route comes in. */
-               else if ((nexthop = re->nexthop)
-                        && nexthop->type == NEXTHOP_TYPE_IFINDEX
-                        && nexthop->ifindex == ifindex
+               else if ((rtnh = re->nexthop)
+                        && rtnh->type == NEXTHOP_TYPE_IFINDEX
+                        && rtnh->ifindex == nh->ifindex
                         && !CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) {
                        re->refcnt++;
                        return 0;
@@ -2503,29 +2499,14 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
        re->nexthop_num = 0;
        re->uptime = time(NULL);
 
-       /* Nexthop settings. */
-       if (gate) {
-               if (afi == AFI_IP6) {
-                       if (ifindex)
-                               route_entry_nexthop_ipv6_ifindex_add(
-                                       re, &gate->ipv6, ifindex);
-                       else
-                               route_entry_nexthop_ipv6_add(re, &gate->ipv6);
-               } else {
-                       if (ifindex)
-                               route_entry_nexthop_ipv4_ifindex_add(
-                                       re, &gate->ipv4, &src->ipv4, ifindex);
-                       else
-                               route_entry_nexthop_ipv4_add(re, &gate->ipv4,
-                                                            &src->ipv4);
-               }
-       } else
-               route_entry_nexthop_ifindex_add(re, ifindex);
+       rtnh = nexthop_new();
+       *rtnh = *nh;
+       route_entry_nexthop_add(re, rtnh);
 
        /* If this route is kernel route, set FIB flag to the route. */
        if (RIB_SYSTEM_ROUTE(re))
-               for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next)
-                       SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+               for (rtnh = re->nexthop; rtnh; rtnh = rtnh->next)
+                       SET_FLAG(rtnh->flags, NEXTHOP_FLAG_FIB);
 
        /* Link new rib to node.*/
        if (IS_ZEBRA_DEBUG_RIB) {