summaryrefslogtreecommitdiff
path: root/net/ipv6/seg6_iptunnel.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/seg6_iptunnel.c')
-rw-r--r--net/ipv6/seg6_iptunnel.c34
1 files changed, 22 insertions, 12 deletions
diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
index e76cc0cc481e..97b50d9b1365 100644
--- a/net/ipv6/seg6_iptunnel.c
+++ b/net/ipv6/seg6_iptunnel.c
@@ -48,7 +48,8 @@ static size_t seg6_lwt_headroom(struct seg6_iptunnel_encap *tuninfo)
}
struct seg6_lwt {
- struct dst_cache cache;
+ struct dst_cache cache_input;
+ struct dst_cache cache_output;
struct in6_addr tunsrc;
struct seg6_iptunnel_encap tuninfo[];
};
@@ -503,7 +504,7 @@ static int seg6_input_core(struct net *net, struct sock *sk,
slwt = seg6_lwt_lwtunnel(lwtst);
local_bh_disable();
- dst = dst_cache_get(&slwt->cache);
+ dst = dst_cache_get(&slwt->cache_input);
local_bh_enable();
err = seg6_do_srh(skb, dst);
@@ -519,7 +520,7 @@ static int seg6_input_core(struct net *net, struct sock *sk,
/* cache only if we don't create a dst reference loop */
if (!dst->error && lwtst != dst->lwtstate) {
local_bh_disable();
- dst_cache_set_ip6(&slwt->cache, dst,
+ dst_cache_set_ip6(&slwt->cache_input, dst,
&ipv6_hdr(skb)->saddr);
local_bh_enable();
}
@@ -579,7 +580,7 @@ static int seg6_output_core(struct net *net, struct sock *sk,
slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate);
local_bh_disable();
- dst = dst_cache_get(&slwt->cache);
+ dst = dst_cache_get(&slwt->cache_output);
local_bh_enable();
err = seg6_do_srh(skb, dst);
@@ -606,7 +607,7 @@ static int seg6_output_core(struct net *net, struct sock *sk,
/* cache only if we don't create a dst reference loop */
if (orig_dst->lwtstate != dst->lwtstate) {
local_bh_disable();
- dst_cache_set_ip6(&slwt->cache, dst, &fl6.saddr);
+ dst_cache_set_ip6(&slwt->cache_output, dst, &fl6.saddr);
local_bh_enable();
}
@@ -720,9 +721,13 @@ static int seg6_build_state(struct net *net, struct nlattr *nla,
slwt = seg6_lwt_lwtunnel(newts);
- err = dst_cache_init(&slwt->cache, GFP_ATOMIC);
+ err = dst_cache_init(&slwt->cache_input, GFP_ATOMIC);
if (err)
- goto free_lwt_state;
+ goto err_free_newts;
+
+ err = dst_cache_init(&slwt->cache_output, GFP_ATOMIC);
+ if (err)
+ goto err_destroy_input;
memcpy(&slwt->tuninfo, tuninfo, tuninfo_len);
@@ -734,7 +739,7 @@ static int seg6_build_state(struct net *net, struct nlattr *nla,
ipv6_addr_loopback(&slwt->tunsrc)) {
NL_SET_ERR_MSG(extack, "invalid tunsrc address");
err = -EINVAL;
- goto free_dst_cache;
+ goto err_destroy_output;
}
}
@@ -750,16 +755,21 @@ static int seg6_build_state(struct net *net, struct nlattr *nla,
return 0;
-free_dst_cache:
- dst_cache_destroy(&slwt->cache);
-free_lwt_state:
+err_destroy_output:
+ dst_cache_destroy(&slwt->cache_output);
+err_destroy_input:
+ dst_cache_destroy(&slwt->cache_input);
+err_free_newts:
kfree(newts);
return err;
}
static void seg6_destroy_state(struct lwtunnel_state *lwt)
{
- dst_cache_destroy(&seg6_lwt_lwtunnel(lwt)->cache);
+ struct seg6_lwt *slwt = seg6_lwt_lwtunnel(lwt);
+
+ dst_cache_destroy(&slwt->cache_input);
+ dst_cache_destroy(&slwt->cache_output);
}
static int seg6_fill_encap_info(struct sk_buff *skb,