Skip to content

Commit

Permalink
route: Set lwtstate for local traffic and cached input dsts
Browse files Browse the repository at this point in the history
A route on the output path hitting a RTN_LOCAL route will keep the dst
associated on its way through the loopback device. On the receive path,
the dst_input() call will thus invoke the input handler of the route
created in the output path. Thus, lwt redirection for input must be done
for dsts allocated in the otuput path as well.

Also, if a route is cached in the input path, the allocated dst should
respect lwtunnel configuration on the nexthop as well.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
tgraf authored and davem330 committed Dec 2, 2016
1 parent 11b3d9c commit efd8570
Showing 1 changed file with 26 additions and 13 deletions.
39 changes: 26 additions & 13 deletions net/ipv4/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -1603,6 +1603,19 @@ static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr)
spin_unlock_bh(&fnhe_lock);
}

static void set_lwt_redirect(struct rtable *rth)
{
if (lwtunnel_output_redirect(rth->dst.lwtstate)) {
rth->dst.lwtstate->orig_output = rth->dst.output;
rth->dst.output = lwtunnel_output;
}

if (lwtunnel_input_redirect(rth->dst.lwtstate)) {
rth->dst.lwtstate->orig_input = rth->dst.input;
rth->dst.input = lwtunnel_input;
}
}

/* called in rcu_read_lock() section */
static int __mkroute_input(struct sk_buff *skb,
const struct fib_result *res,
Expand Down Expand Up @@ -1692,14 +1705,7 @@ static int __mkroute_input(struct sk_buff *skb,
rth->dst.input = ip_forward;

rt_set_nexthop(rth, daddr, res, fnhe, res->fi, res->type, itag);
if (lwtunnel_output_redirect(rth->dst.lwtstate)) {
rth->dst.lwtstate->orig_output = rth->dst.output;
rth->dst.output = lwtunnel_output;
}
if (lwtunnel_input_redirect(rth->dst.lwtstate)) {
rth->dst.lwtstate->orig_input = rth->dst.input;
rth->dst.input = lwtunnel_input;
}
set_lwt_redirect(rth);
skb_dst_set(skb, &rth->dst);
out:
err = 0;
Expand Down Expand Up @@ -1926,8 +1932,18 @@ out: return err;
rth->dst.error= -err;
rth->rt_flags &= ~RTCF_LOCAL;
}

if (do_cache) {
if (unlikely(!rt_cache_route(&FIB_RES_NH(res), rth))) {
struct fib_nh *nh = &FIB_RES_NH(res);

rth->dst.lwtstate = lwtstate_get(nh->nh_lwtstate);
if (lwtunnel_input_redirect(rth->dst.lwtstate)) {
WARN_ON(rth->dst.input == lwtunnel_input);
rth->dst.lwtstate->orig_input = rth->dst.input;
rth->dst.input = lwtunnel_input;
}

if (unlikely(!rt_cache_route(nh, rth))) {
rth->dst.flags |= DST_NOCACHE;
rt_add_uncached_list(rth);
}
Expand Down Expand Up @@ -2155,10 +2171,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
}

rt_set_nexthop(rth, fl4->daddr, res, fnhe, fi, type, 0);
if (lwtunnel_output_redirect(rth->dst.lwtstate)) {
rth->dst.lwtstate->orig_output = rth->dst.output;
rth->dst.output = lwtunnel_output;
}
set_lwt_redirect(rth);

return rth;
}
Expand Down

0 comments on commit efd8570

Please sign in to comment.