diff options
author | Tom Herbert <tom@herbertland.com> | 2016-06-07 19:09:44 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-06-08 03:40:34 -0400 |
commit | 707a2ca4870fcf6b5480cdfad563b940f56f0844 (patch) | |
tree | 1f3246877173faadbb4589af7995d2224acab189 /net/ipv6/ila | |
parent | e00431bc93bb48c650273be4a00007b2a392d32a (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.h | 3 | ||||
-rw-r--r-- | net/ipv6/ila/ila_common.c | 6 | ||||
-rw-r--r-- | net/ipv6/ila/ila_lwt.c | 4 | ||||
-rw-r--r-- | net/ipv6/ila/ila_xlat.c | 8 |
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 | ||
112 | void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p); | 112 | void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p, |
113 | bool set_csum_neutral); | ||
113 | 114 | ||
114 | void ila_init_saved_csum(struct ila_params *p); | 115 | void 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 | ||
106 | void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p) | 106 | void 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 | ||
213 | static int ila_xlat_addr(struct sk_buff *skb); | 213 | static int ila_xlat_addr(struct sk_buff *skb, bool set_csum_neutral); |
214 | 214 | ||
215 | static unsigned int | 215 | static unsigned int |
216 | ila_nf_input(void *priv, | 216 | ila_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 | ||
600 | static int ila_xlat_addr(struct sk_buff *skb) | 600 | static 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 | ||