route: Set lwtstate for local traffic and cached input dsts
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>
This commit is contained in:
Родитель
11b3d9c586
Коммит
efd8570081
|
@ -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,
|
||||
|
@ -1692,14 +1705,7 @@ rt_cache:
|
|||
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;
|
||||
|
@ -1926,8 +1932,18 @@ local_input:
|
|||
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);
|
||||
}
|
||||
|
@ -2155,10 +2171,7 @@ add:
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче