|
@@ -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;
|
|
|
}
|