aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ila
diff options
context:
space:
mode:
authorTom Herbert <tom@herbertland.com>2016-06-07 19:09:44 -0400
committerDavid S. Miller <davem@davemloft.net>2016-06-08 03:40:34 -0400
commit707a2ca4870fcf6b5480cdfad563b940f56f0844 (patch)
tree1f3246877173faadbb4589af7995d2224acab189 /net/ipv6/ila
parente00431bc93bb48c650273be4a00007b2a392d32a (diff)
ila: Perform only one translation in forwarding path
When setting up ILA in a router we noticed that the the encapsulation is invoked twice: once in the route input path and again upon route output. To resolve this we add a flag set_csum_neutral for the ila_update_ipv6_locator. If this flag is set and the checksum neutral bit is also set we assume that checksum-neutral translation has already been performed and take no further action. The flag is set only in ila_output path. The flag is not set for ila_input and ila_xlat. Tested: Used 3 netns to set to emulate a router and two hosts. The router translates SIR addresses between the two destinations in other two netns. Verified ping and netperf are functional. Signed-off-by: Tom Herbert <tom@herbertland.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/ila')
-rw-r--r--net/ipv6/ila/ila.h3
-rw-r--r--net/ipv6/ila/ila_common.c6
-rw-r--r--net/ipv6/ila/ila_lwt.c4
-rw-r--r--net/ipv6/ila/ila_xlat.c8
4 files changed, 12 insertions, 9 deletions
diff --git a/net/ipv6/ila/ila.h b/net/ipv6/ila/ila.h
index d08fd2d48a78..e0170f62bc39 100644
--- a/net/ipv6/ila/ila.h
+++ b/net/ipv6/ila/ila.h
@@ -109,7 +109,8 @@ static inline bool ila_csum_neutral_set(struct ila_identifier ident)
109 return !!(ident.csum_neutral); 109 return !!(ident.csum_neutral);
110} 110}
111 111
112void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p); 112void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p,
113 bool set_csum_neutral);
113 114
114void ila_init_saved_csum(struct ila_params *p); 115void ila_init_saved_csum(struct ila_params *p);
115 116
diff --git a/net/ipv6/ila/ila_common.c b/net/ipv6/ila/ila_common.c
index 0e94042d1289..b3d00be484d4 100644
--- a/net/ipv6/ila/ila_common.c
+++ b/net/ipv6/ila/ila_common.c
@@ -103,7 +103,8 @@ static void ila_csum_adjust_transport(struct sk_buff *skb,
103 iaddr->loc = p->locator; 103 iaddr->loc = p->locator;
104} 104}
105 105
106void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p) 106void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p,
107 bool set_csum_neutral)
107{ 108{
108 struct ipv6hdr *ip6h = ipv6_hdr(skb); 109 struct ipv6hdr *ip6h = ipv6_hdr(skb);
109 struct ila_addr *iaddr = ila_a2i(&ip6h->daddr); 110 struct ila_addr *iaddr = ila_a2i(&ip6h->daddr);
@@ -114,7 +115,8 @@ void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p)
114 * is a locator being translated to a SIR address. 115 * is a locator being translated to a SIR address.
115 * Perform (receiver) checksum-neutral translation. 116 * Perform (receiver) checksum-neutral translation.
116 */ 117 */
117 ila_csum_do_neutral(iaddr, p); 118 if (!set_csum_neutral)
119 ila_csum_do_neutral(iaddr, p);
118 } else { 120 } else {
119 switch (p->csum_mode) { 121 switch (p->csum_mode) {
120 case ILA_CSUM_ADJUST_TRANSPORT: 122 case ILA_CSUM_ADJUST_TRANSPORT:
diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c
index 1dfb64166d7d..c8314c6b6154 100644
--- a/net/ipv6/ila/ila_lwt.c
+++ b/net/ipv6/ila/ila_lwt.c
@@ -26,7 +26,7 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
26 if (skb->protocol != htons(ETH_P_IPV6)) 26 if (skb->protocol != htons(ETH_P_IPV6))
27 goto drop; 27 goto drop;
28 28
29 ila_update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate)); 29 ila_update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate), true);
30 30
31 return dst->lwtstate->orig_output(net, sk, skb); 31 return dst->lwtstate->orig_output(net, sk, skb);
32 32
@@ -42,7 +42,7 @@ static int ila_input(struct sk_buff *skb)
42 if (skb->protocol != htons(ETH_P_IPV6)) 42 if (skb->protocol != htons(ETH_P_IPV6))
43 goto drop; 43 goto drop;
44 44
45 ila_update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate)); 45 ila_update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate), false);
46 46
47 return dst->lwtstate->orig_input(skb); 47 return dst->lwtstate->orig_input(skb);
48 48
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index a90e57229c6c..e6eca5fdf4c9 100644
--- a/net/ipv6/ila/ila_xlat.c
+++ b/net/ipv6/ila/ila_xlat.c
@@ -210,14 +210,14 @@ static void ila_free_cb(void *ptr, void *arg)
210 } 210 }
211} 211}
212 212
213static int ila_xlat_addr(struct sk_buff *skb); 213static int ila_xlat_addr(struct sk_buff *skb, bool set_csum_neutral);
214 214
215static unsigned int 215static unsigned int
216ila_nf_input(void *priv, 216ila_nf_input(void *priv,
217 struct sk_buff *skb, 217 struct sk_buff *skb,
218 const struct nf_hook_state *state) 218 const struct nf_hook_state *state)
219{ 219{
220 ila_xlat_addr(skb); 220 ila_xlat_addr(skb, false);
221 return NF_ACCEPT; 221 return NF_ACCEPT;
222} 222}
223 223
@@ -597,7 +597,7 @@ static struct pernet_operations ila_net_ops = {
597 .size = sizeof(struct ila_net), 597 .size = sizeof(struct ila_net),
598}; 598};
599 599
600static int ila_xlat_addr(struct sk_buff *skb) 600static int ila_xlat_addr(struct sk_buff *skb, bool set_csum_neutral)
601{ 601{
602 struct ila_map *ila; 602 struct ila_map *ila;
603 struct ipv6hdr *ip6h = ipv6_hdr(skb); 603 struct ipv6hdr *ip6h = ipv6_hdr(skb);
@@ -616,7 +616,7 @@ static int ila_xlat_addr(struct sk_buff *skb)
616 616
617 ila = ila_lookup_wildcards(iaddr, skb->dev->ifindex, ilan); 617 ila = ila_lookup_wildcards(iaddr, skb->dev->ifindex, ilan);
618 if (ila) 618 if (ila)
619 ila_update_ipv6_locator(skb, &ila->xp.ip); 619 ila_update_ipv6_locator(skb, &ila->xp.ip, set_csum_neutral);
620 620
621 rcu_read_unlock(); 621 rcu_read_unlock();
622 622