Commit 68a5e3dd authored by David S. Miller's avatar David S. Miller

ipv4: Use struct flowi4 internally in routing lookups.

We will change the externally visible APIs next.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 22bd5b9b
...@@ -109,8 +109,8 @@ ...@@ -109,8 +109,8 @@
#include <linux/sysctl.h> #include <linux/sysctl.h>
#endif #endif
#define RT_FL_TOS(oldflp) \ #define RT_FL_TOS(oldflp4) \
((u32)(oldflp->fl4_tos & (IPTOS_RT_MASK | RTO_ONLINK))) ((u32)(oldflp4->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK)))
#define IP_MAX_MTU 0xFFF0 #define IP_MAX_MTU 0xFFF0
...@@ -1697,17 +1697,17 @@ void ip_rt_get_source(u8 *addr, struct rtable *rt) ...@@ -1697,17 +1697,17 @@ void ip_rt_get_source(u8 *addr, struct rtable *rt)
if (rt_is_output_route(rt)) if (rt_is_output_route(rt))
src = rt->rt_src; src = rt->rt_src;
else { else {
struct flowi fl = { struct flowi4 fl4 = {
.fl4_dst = rt->rt_key_dst, .daddr = rt->rt_key_dst,
.fl4_src = rt->rt_key_src, .saddr = rt->rt_key_src,
.fl4_tos = rt->rt_tos, .flowi4_tos = rt->rt_tos,
.flowi_oif = rt->rt_oif, .flowi4_oif = rt->rt_oif,
.flowi_iif = rt->rt_iif, .flowi4_iif = rt->rt_iif,
.flowi_mark = rt->rt_mark, .flowi4_mark = rt->rt_mark,
}; };
rcu_read_lock(); rcu_read_lock();
if (fib_lookup(dev_net(rt->dst.dev), &fl.u.ip4, &res) == 0) if (fib_lookup(dev_net(rt->dst.dev), &fl4, &res) == 0)
src = FIB_RES_PREFSRC(res); src = FIB_RES_PREFSRC(res);
else else
src = inet_select_addr(rt->dst.dev, rt->rt_gateway, src = inet_select_addr(rt->dst.dev, rt->rt_gateway,
...@@ -1757,7 +1757,7 @@ static unsigned int ipv4_default_mtu(const struct dst_entry *dst) ...@@ -1757,7 +1757,7 @@ static unsigned int ipv4_default_mtu(const struct dst_entry *dst)
return mtu; return mtu;
} }
static void rt_init_metrics(struct rtable *rt, const struct flowi *oldflp, static void rt_init_metrics(struct rtable *rt, const struct flowi4 *oldflp4,
struct fib_info *fi) struct fib_info *fi)
{ {
struct inet_peer *peer; struct inet_peer *peer;
...@@ -1766,7 +1766,7 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi *oldflp, ...@@ -1766,7 +1766,7 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi *oldflp,
/* If a peer entry exists for this destination, we must hook /* If a peer entry exists for this destination, we must hook
* it up in order to get at cached metrics. * it up in order to get at cached metrics.
*/ */
if (oldflp && (oldflp->flowi_flags & FLOWI_FLAG_PRECOW_METRICS)) if (oldflp4 && (oldflp4->flowi4_flags & FLOWI_FLAG_PRECOW_METRICS))
create = 1; create = 1;
rt->peer = peer = inet_getpeer_v4(rt->rt_dst, create); rt->peer = peer = inet_getpeer_v4(rt->rt_dst, create);
...@@ -1793,7 +1793,7 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi *oldflp, ...@@ -1793,7 +1793,7 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi *oldflp,
} }
} }
static void rt_set_nexthop(struct rtable *rt, const struct flowi *oldflp, static void rt_set_nexthop(struct rtable *rt, const struct flowi4 *oldflp4,
const struct fib_result *res, const struct fib_result *res,
struct fib_info *fi, u16 type, u32 itag) struct fib_info *fi, u16 type, u32 itag)
{ {
...@@ -1803,7 +1803,7 @@ static void rt_set_nexthop(struct rtable *rt, const struct flowi *oldflp, ...@@ -1803,7 +1803,7 @@ static void rt_set_nexthop(struct rtable *rt, const struct flowi *oldflp,
if (FIB_RES_GW(*res) && if (FIB_RES_GW(*res) &&
FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
rt->rt_gateway = FIB_RES_GW(*res); rt->rt_gateway = FIB_RES_GW(*res);
rt_init_metrics(rt, oldflp, fi); rt_init_metrics(rt, oldflp4, fi);
#ifdef CONFIG_IP_ROUTE_CLASSID #ifdef CONFIG_IP_ROUTE_CLASSID
dst->tclassid = FIB_RES_NH(*res).nh_tclassid; dst->tclassid = FIB_RES_NH(*res).nh_tclassid;
#endif #endif
...@@ -2038,7 +2038,7 @@ static int __mkroute_input(struct sk_buff *skb, ...@@ -2038,7 +2038,7 @@ static int __mkroute_input(struct sk_buff *skb,
static int ip_mkroute_input(struct sk_buff *skb, static int ip_mkroute_input(struct sk_buff *skb,
struct fib_result *res, struct fib_result *res,
const struct flowi *fl, const struct flowi4 *fl4,
struct in_device *in_dev, struct in_device *in_dev,
__be32 daddr, __be32 saddr, u32 tos) __be32 daddr, __be32 saddr, u32 tos)
{ {
...@@ -2057,9 +2057,9 @@ static int ip_mkroute_input(struct sk_buff *skb, ...@@ -2057,9 +2057,9 @@ static int ip_mkroute_input(struct sk_buff *skb,
return err; return err;
/* put it into the cache */ /* put it into the cache */
hash = rt_hash(daddr, saddr, fl->flowi_iif, hash = rt_hash(daddr, saddr, fl4->flowi4_iif,
rt_genid(dev_net(rth->dst.dev))); rt_genid(dev_net(rth->dst.dev)));
rth = rt_intern_hash(hash, rth, skb, fl->flowi_iif); rth = rt_intern_hash(hash, rth, skb, fl4->flowi4_iif);
if (IS_ERR(rth)) if (IS_ERR(rth))
return PTR_ERR(rth); return PTR_ERR(rth);
return 0; return 0;
...@@ -2081,7 +2081,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, ...@@ -2081,7 +2081,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
{ {
struct fib_result res; struct fib_result res;
struct in_device *in_dev = __in_dev_get_rcu(dev); struct in_device *in_dev = __in_dev_get_rcu(dev);
struct flowi fl; struct flowi4 fl4;
unsigned flags = 0; unsigned flags = 0;
u32 itag = 0; u32 itag = 0;
struct rtable * rth; struct rtable * rth;
...@@ -2118,14 +2118,14 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, ...@@ -2118,14 +2118,14 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
/* /*
* Now we are ready to route packet. * Now we are ready to route packet.
*/ */
fl.flowi_oif = 0; fl4.flowi4_oif = 0;
fl.flowi_iif = dev->ifindex; fl4.flowi4_iif = dev->ifindex;
fl.flowi_mark = skb->mark; fl4.flowi4_mark = skb->mark;
fl.fl4_dst = daddr; fl4.flowi4_tos = tos;
fl.fl4_src = saddr; fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
fl.fl4_tos = tos; fl4.daddr = daddr;
fl.fl4_scope = RT_SCOPE_UNIVERSE; fl4.saddr = saddr;
err = fib_lookup(net, &fl.u.ip4, &res); err = fib_lookup(net, &fl4, &res);
if (err != 0) { if (err != 0) {
if (!IN_DEV_FORWARD(in_dev)) if (!IN_DEV_FORWARD(in_dev))
goto e_hostunreach; goto e_hostunreach;
...@@ -2154,7 +2154,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, ...@@ -2154,7 +2154,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
if (res.type != RTN_UNICAST) if (res.type != RTN_UNICAST)
goto martian_destination; goto martian_destination;
err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos); err = ip_mkroute_input(skb, &res, &fl4, in_dev, daddr, saddr, tos);
out: return err; out: return err;
brd_input: brd_input:
...@@ -2205,8 +2205,8 @@ out: return err; ...@@ -2205,8 +2205,8 @@ out: return err;
rth->rt_flags &= ~RTCF_LOCAL; rth->rt_flags &= ~RTCF_LOCAL;
} }
rth->rt_type = res.type; rth->rt_type = res.type;
hash = rt_hash(daddr, saddr, fl.flowi_iif, rt_genid(net)); hash = rt_hash(daddr, saddr, fl4.flowi4_iif, rt_genid(net));
rth = rt_intern_hash(hash, rth, skb, fl.flowi_iif); rth = rt_intern_hash(hash, rth, skb, fl4.flowi4_iif);
err = 0; err = 0;
if (IS_ERR(rth)) if (IS_ERR(rth))
err = PTR_ERR(rth); err = PTR_ERR(rth);
...@@ -2335,25 +2335,25 @@ EXPORT_SYMBOL(ip_route_input_common); ...@@ -2335,25 +2335,25 @@ EXPORT_SYMBOL(ip_route_input_common);
/* called with rcu_read_lock() */ /* called with rcu_read_lock() */
static struct rtable *__mkroute_output(const struct fib_result *res, static struct rtable *__mkroute_output(const struct fib_result *res,
const struct flowi *fl, const struct flowi4 *fl4,
const struct flowi *oldflp, const struct flowi4 *oldflp4,
struct net_device *dev_out, struct net_device *dev_out,
unsigned int flags) unsigned int flags)
{ {
struct fib_info *fi = res->fi; struct fib_info *fi = res->fi;
u32 tos = RT_FL_TOS(oldflp); u32 tos = RT_FL_TOS(oldflp4);
struct in_device *in_dev; struct in_device *in_dev;
u16 type = res->type; u16 type = res->type;
struct rtable *rth; struct rtable *rth;
if (ipv4_is_loopback(fl->fl4_src) && !(dev_out->flags & IFF_LOOPBACK)) if (ipv4_is_loopback(fl4->saddr) && !(dev_out->flags & IFF_LOOPBACK))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
if (ipv4_is_lbcast(fl->fl4_dst)) if (ipv4_is_lbcast(fl4->daddr))
type = RTN_BROADCAST; type = RTN_BROADCAST;
else if (ipv4_is_multicast(fl->fl4_dst)) else if (ipv4_is_multicast(fl4->daddr))
type = RTN_MULTICAST; type = RTN_MULTICAST;
else if (ipv4_is_zeronet(fl->fl4_dst)) else if (ipv4_is_zeronet(fl4->daddr))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
if (dev_out->flags & IFF_LOOPBACK) if (dev_out->flags & IFF_LOOPBACK)
...@@ -2368,8 +2368,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res, ...@@ -2368,8 +2368,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
fi = NULL; fi = NULL;
} else if (type == RTN_MULTICAST) { } else if (type == RTN_MULTICAST) {
flags |= RTCF_MULTICAST | RTCF_LOCAL; flags |= RTCF_MULTICAST | RTCF_LOCAL;
if (!ip_check_mc_rcu(in_dev, oldflp->fl4_dst, oldflp->fl4_src, if (!ip_check_mc_rcu(in_dev, oldflp4->daddr, oldflp4->saddr,
oldflp->flowi_proto)) oldflp4->flowi4_proto))
flags &= ~RTCF_LOCAL; flags &= ~RTCF_LOCAL;
/* If multicast route do not exist use /* If multicast route do not exist use
* default one, but do not gateway in this case. * default one, but do not gateway in this case.
...@@ -2384,20 +2384,20 @@ static struct rtable *__mkroute_output(const struct fib_result *res, ...@@ -2384,20 +2384,20 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
if (!rth) if (!rth)
return ERR_PTR(-ENOBUFS); return ERR_PTR(-ENOBUFS);
rth->rt_key_dst = oldflp->fl4_dst; rth->rt_key_dst = oldflp4->daddr;
rth->rt_tos = tos; rth->rt_tos = tos;
rth->rt_key_src = oldflp->fl4_src; rth->rt_key_src = oldflp4->saddr;
rth->rt_oif = oldflp->flowi_oif; rth->rt_oif = oldflp4->flowi4_oif;
rth->rt_mark = oldflp->flowi_mark; rth->rt_mark = oldflp4->flowi4_mark;
rth->rt_dst = fl->fl4_dst; rth->rt_dst = fl4->daddr;
rth->rt_src = fl->fl4_src; rth->rt_src = fl4->saddr;
rth->rt_iif = 0; rth->rt_iif = 0;
/* get references to the devices that are to be hold by the routing /* get references to the devices that are to be hold by the routing
cache entry */ cache entry */
rth->dst.dev = dev_out; rth->dst.dev = dev_out;
dev_hold(dev_out); dev_hold(dev_out);
rth->rt_gateway = fl->fl4_dst; rth->rt_gateway = fl4->daddr;
rth->rt_spec_dst= fl->fl4_src; rth->rt_spec_dst= fl4->saddr;
rth->dst.output=ip_output; rth->dst.output=ip_output;
rth->rt_genid = rt_genid(dev_net(dev_out)); rth->rt_genid = rt_genid(dev_net(dev_out));
...@@ -2406,10 +2406,10 @@ static struct rtable *__mkroute_output(const struct fib_result *res, ...@@ -2406,10 +2406,10 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
if (flags & RTCF_LOCAL) { if (flags & RTCF_LOCAL) {
rth->dst.input = ip_local_deliver; rth->dst.input = ip_local_deliver;
rth->rt_spec_dst = fl->fl4_dst; rth->rt_spec_dst = fl4->daddr;
} }
if (flags & (RTCF_BROADCAST | RTCF_MULTICAST)) { if (flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {
rth->rt_spec_dst = fl->fl4_src; rth->rt_spec_dst = fl4->saddr;
if (flags & RTCF_LOCAL && if (flags & RTCF_LOCAL &&
!(dev_out->flags & IFF_LOOPBACK)) { !(dev_out->flags & IFF_LOOPBACK)) {
rth->dst.output = ip_mc_output; rth->dst.output = ip_mc_output;
...@@ -2418,7 +2418,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, ...@@ -2418,7 +2418,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
#ifdef CONFIG_IP_MROUTE #ifdef CONFIG_IP_MROUTE
if (type == RTN_MULTICAST) { if (type == RTN_MULTICAST) {
if (IN_DEV_MFORWARD(in_dev) && if (IN_DEV_MFORWARD(in_dev) &&
!ipv4_is_local_multicast(oldflp->fl4_dst)) { !ipv4_is_local_multicast(oldflp4->daddr)) {
rth->dst.input = ip_mr_input; rth->dst.input = ip_mr_input;
rth->dst.output = ip_mc_output; rth->dst.output = ip_mc_output;
} }
...@@ -2426,7 +2426,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, ...@@ -2426,7 +2426,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
#endif #endif
} }
rt_set_nexthop(rth, oldflp, res, fi, type, 0); rt_set_nexthop(rth, oldflp4, res, fi, type, 0);
rth->rt_flags = flags; rth->rt_flags = flags;
return rth; return rth;
...@@ -2438,10 +2438,10 @@ static struct rtable *__mkroute_output(const struct fib_result *res, ...@@ -2438,10 +2438,10 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
*/ */
static struct rtable *ip_route_output_slow(struct net *net, static struct rtable *ip_route_output_slow(struct net *net,
const struct flowi *oldflp) const struct flowi4 *oldflp4)
{ {
u32 tos = RT_FL_TOS(oldflp); u32 tos = RT_FL_TOS(oldflp4);
struct flowi fl; struct flowi4 fl4;
struct fib_result res; struct fib_result res;
unsigned int flags = 0; unsigned int flags = 0;
struct net_device *dev_out = NULL; struct net_device *dev_out = NULL;
...@@ -2452,21 +2452,21 @@ static struct rtable *ip_route_output_slow(struct net *net, ...@@ -2452,21 +2452,21 @@ static struct rtable *ip_route_output_slow(struct net *net,
res.r = NULL; res.r = NULL;
#endif #endif
fl.flowi_oif = oldflp->flowi_oif; fl4.flowi4_oif = oldflp4->flowi4_oif;
fl.flowi_iif = net->loopback_dev->ifindex; fl4.flowi4_iif = net->loopback_dev->ifindex;
fl.flowi_mark = oldflp->flowi_mark; fl4.flowi4_mark = oldflp4->flowi4_mark;
fl.fl4_dst = oldflp->fl4_dst; fl4.daddr = oldflp4->daddr;
fl.fl4_src = oldflp->fl4_src; fl4.saddr = oldflp4->saddr;
fl.fl4_tos = tos & IPTOS_RT_MASK; fl4.flowi4_tos = tos & IPTOS_RT_MASK;
fl.fl4_scope = ((tos & RTO_ONLINK) ? fl4.flowi4_scope = ((tos & RTO_ONLINK) ?
RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
rcu_read_lock(); rcu_read_lock();
if (oldflp->fl4_src) { if (oldflp4->saddr) {
rth = ERR_PTR(-EINVAL); rth = ERR_PTR(-EINVAL);
if (ipv4_is_multicast(oldflp->fl4_src) || if (ipv4_is_multicast(oldflp4->saddr) ||
ipv4_is_lbcast(oldflp->fl4_src) || ipv4_is_lbcast(oldflp4->saddr) ||
ipv4_is_zeronet(oldflp->fl4_src)) ipv4_is_zeronet(oldflp4->saddr))
goto out; goto out;
/* I removed check for oif == dev_out->oif here. /* I removed check for oif == dev_out->oif here.
...@@ -2477,11 +2477,11 @@ static struct rtable *ip_route_output_slow(struct net *net, ...@@ -2477,11 +2477,11 @@ static struct rtable *ip_route_output_slow(struct net *net,
of another iface. --ANK of another iface. --ANK
*/ */
if (oldflp->flowi_oif == 0 && if (oldflp4->flowi4_oif == 0 &&
(ipv4_is_multicast(oldflp->fl4_dst) || (ipv4_is_multicast(oldflp4->daddr) ||
ipv4_is_lbcast(oldflp->fl4_dst))) { ipv4_is_lbcast(oldflp4->daddr))) {
/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
dev_out = __ip_dev_find(net, oldflp->fl4_src, false); dev_out = __ip_dev_find(net, oldflp4->saddr, false);
if (dev_out == NULL) if (dev_out == NULL)
goto out; goto out;
...@@ -2500,20 +2500,20 @@ static struct rtable *ip_route_output_slow(struct net *net, ...@@ -2500,20 +2500,20 @@ static struct rtable *ip_route_output_slow(struct net *net,
Luckily, this hack is good workaround. Luckily, this hack is good workaround.
*/ */
fl.flowi_oif = dev_out->ifindex; fl4.flowi4_oif = dev_out->ifindex;
goto make_route; goto make_route;
} }
if (!(oldflp->flowi_flags & FLOWI_FLAG_ANYSRC)) { if (!(oldflp4->flowi4_flags & FLOWI_FLAG_ANYSRC)) {
/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
if (!__ip_dev_find(net, oldflp->fl4_src, false)) if (!__ip_dev_find(net, oldflp4->saddr, false))
goto out; goto out;
} }
} }
if (oldflp->flowi_oif) { if (oldflp4->flowi4_oif) {
dev_out = dev_get_by_index_rcu(net, oldflp->flowi_oif); dev_out = dev_get_by_index_rcu(net, oldflp4->flowi4_oif);
rth = ERR_PTR(-ENODEV); rth = ERR_PTR(-ENODEV);
if (dev_out == NULL) if (dev_out == NULL)
goto out; goto out;
...@@ -2523,37 +2523,37 @@ static struct rtable *ip_route_output_slow(struct net *net, ...@@ -2523,37 +2523,37 @@ static struct rtable *ip_route_output_slow(struct net *net,
rth = ERR_PTR(-ENETUNREACH); rth = ERR_PTR(-ENETUNREACH);
goto out; goto out;
} }
if (ipv4_is_local_multicast(oldflp->fl4_dst) || if (ipv4_is_local_multicast(oldflp4->daddr) ||
ipv4_is_lbcast(oldflp->fl4_dst)) { ipv4_is_lbcast(oldflp4->daddr)) {
if (!fl.fl4_src) if (!fl4.saddr)
fl.fl4_src = inet_select_addr(dev_out, 0, fl4.saddr = inet_select_addr(dev_out, 0,
RT_SCOPE_LINK); RT_SCOPE_LINK);
goto make_route; goto make_route;
} }
if (!fl.fl4_src) { if (!fl4.saddr) {
if (ipv4_is_multicast(oldflp->fl4_dst)) if (ipv4_is_multicast(oldflp4->daddr))
fl.fl4_src = inet_select_addr(dev_out, 0, fl4.saddr = inet_select_addr(dev_out, 0,
fl.fl4_scope); fl4.flowi4_scope);
else if (!oldflp->fl4_dst) else if (!oldflp4->daddr)
fl.fl4_src = inet_select_addr(dev_out, 0, fl4.saddr = inet_select_addr(dev_out, 0,
RT_SCOPE_HOST); RT_SCOPE_HOST);
} }
} }
if (!fl.fl4_dst) { if (!fl4.daddr) {
fl.fl4_dst = fl.fl4_src; fl4.daddr = fl4.saddr;
if (!fl.fl4_dst) if (!fl4.daddr)
fl.fl4_dst = fl.fl4_src = htonl(INADDR_LOOPBACK); fl4.daddr = fl4.saddr = htonl(INADDR_LOOPBACK);
dev_out = net->loopback_dev; dev_out = net->loopback_dev;
fl.flowi_oif = net->loopback_dev->ifindex; fl4.flowi4_oif = net->loopback_dev->ifindex;
res.type = RTN_LOCAL; res.type = RTN_LOCAL;
flags |= RTCF_LOCAL; flags |= RTCF_LOCAL;
goto make_route; goto make_route;
} }
if (fib_lookup(net, &fl.u.ip4, &res)) { if (fib_lookup(net, &fl4, &res)) {
res.fi = NULL; res.fi = NULL;
if (oldflp->flowi_oif) { if (oldflp4->flowi4_oif) {
/* Apparently, routing tables are wrong. Assume, /* Apparently, routing tables are wrong. Assume,
that the destination is on link. that the destination is on link.
...@@ -2572,9 +2572,9 @@ static struct rtable *ip_route_output_slow(struct net *net, ...@@ -2572,9 +2572,9 @@ static struct rtable *ip_route_output_slow(struct net *net,
likely IPv6, but we do not. likely IPv6, but we do not.
*/ */
if (fl.fl4_src == 0) if (fl4.saddr == 0)
fl.fl4_src = inet_select_addr(dev_out, 0, fl4.saddr = inet_select_addr(dev_out, 0,
RT_SCOPE_LINK); RT_SCOPE_LINK);
res.type = RTN_UNICAST; res.type = RTN_UNICAST;
goto make_route; goto make_route;
} }
...@@ -2583,42 +2583,42 @@ static struct rtable *ip_route_output_slow(struct net *net, ...@@ -2583,42 +2583,42 @@ static struct rtable *ip_route_output_slow(struct net *net,
} }
if (res.type == RTN_LOCAL) { if (res.type == RTN_LOCAL) {
if (!fl.fl4_src) { if (!fl4.saddr) {
if (res.fi->fib_prefsrc) if (res.fi->fib_prefsrc)
fl.fl4_src = res.fi->fib_prefsrc; fl4.saddr = res.fi->fib_prefsrc;
else else
fl.fl4_src = fl.fl4_dst; fl4.saddr = fl4.daddr;
} }
dev_out = net->loopback_dev; dev_out = net->loopback_dev;
fl.flowi_oif = dev_out->ifindex; fl4.flowi4_oif = dev_out->ifindex;
res.fi = NULL; res.fi = NULL;
flags |= RTCF_LOCAL; flags |= RTCF_LOCAL;
goto make_route; goto make_route;
} }
#ifdef CONFIG_IP_ROUTE_MULTIPATH #ifdef CONFIG_IP_ROUTE_MULTIPATH
if (res.fi->fib_nhs > 1 && fl.flowi_oif == 0) if (res.fi->fib_nhs > 1 && fl4.flowi4_oif == 0)
fib_select_multipath(&res); fib_select_multipath(&res);
else else
#endif #endif
if (!res.prefixlen && res.type == RTN_UNICAST && !fl.flowi_oif) if (!res.prefixlen && res.type == RTN_UNICAST && !fl4.flowi4_oif)
fib_select_default(&res); fib_select_default(&res);
if (!fl.fl4_src) if (!fl4.saddr)
fl.fl4_src = FIB_RES_PREFSRC(res); fl4.saddr = FIB_RES_PREFSRC(res);
dev_out = FIB_RES_DEV(res); dev_out = FIB_RES_DEV(res);
fl.flowi_oif = dev_out->ifindex; fl4.flowi4_oif = dev_out->ifindex;
make_route: make_route:
rth = __mkroute_output(&res, &fl, oldflp, dev_out, flags); rth = __mkroute_output(&res, &fl4, oldflp4, dev_out, flags);
if (!IS_ERR(rth)) { if (!IS_ERR(rth)) {
unsigned int hash; unsigned int hash;
hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->flowi_oif, hash = rt_hash(oldflp4->daddr, oldflp4->saddr, oldflp4->flowi4_oif,
rt_genid(dev_net(dev_out))); rt_genid(dev_net(dev_out)));
rth = rt_intern_hash(hash, rth, NULL, oldflp->flowi_oif); rth = rt_intern_hash(hash, rth, NULL, oldflp4->flowi4_oif);
} }
out: out:
...@@ -2658,7 +2658,7 @@ struct rtable *__ip_route_output_key(struct net *net, const struct flowi *flp) ...@@ -2658,7 +2658,7 @@ struct rtable *__ip_route_output_key(struct net *net, const struct flowi *flp)
rcu_read_unlock_bh(); rcu_read_unlock_bh();
slow_output: slow_output:
return ip_route_output_slow(net, flp); return ip_route_output_slow(net, &flp->u.ip4);
} }
EXPORT_SYMBOL_GPL(__ip_route_output_key); EXPORT_SYMBOL_GPL(__ip_route_output_key);
...@@ -2913,14 +2913,14 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void ...@@ -2913,14 +2913,14 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
if (err == 0 && rt->dst.error) if (err == 0 && rt->dst.error)
err = -rt->dst.error; err = -rt->dst.error;
} else { } else {
struct flowi fl = { struct flowi4 fl4 = {
.fl4_dst = dst, .daddr = dst,
.fl4_src = src, .saddr = src,
.fl4_tos = rtm->rtm_tos, .flowi4_tos = rtm->rtm_tos,
.flowi_oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0, .flowi4_oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0,
.flowi_mark = mark, .flowi4_mark = mark,
}; };
rt = ip_route_output_key(net, &fl); rt = ip_route_output_key(net, flowi4_to_flowi(&fl4));
err = 0; err = 0;
if (IS_ERR(rt)) if (IS_ERR(rt))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment