diff options
author | Florian Westphal <fw@strlen.de> | 2015-05-22 10:32:50 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-05-27 13:03:30 -0400 |
commit | c5501eb3406d0f88b3efb2c437c4c40b35f865d8 (patch) | |
tree | 5ac451351462b0afb2a5d405a817b89e374afafe | |
parent | 8c0ce7705ee6ad5a98a715a6b8f0766433cb8388 (diff) |
net: ipv4: avoid repeated calls to ip_skb_dst_mtu helper
ip_skb_dst_mtu is small inline helper, but its called in several places.
before: 17061 44 0 17105 42d1 net/ipv4/ip_output.o
after: 16805 44 0 16849 41d1 net/ipv4/ip_output.o
Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/ip_output.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 451b009dae75..d6dd8ba04441 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -84,6 +84,7 @@ int sysctl_ip_default_ttl __read_mostly = IPDEFTTL; | |||
84 | EXPORT_SYMBOL(sysctl_ip_default_ttl); | 84 | EXPORT_SYMBOL(sysctl_ip_default_ttl); |
85 | 85 | ||
86 | static int ip_fragment(struct sock *sk, struct sk_buff *skb, | 86 | static int ip_fragment(struct sock *sk, struct sk_buff *skb, |
87 | unsigned int mtu, | ||
87 | int (*output)(struct sock *, struct sk_buff *)); | 88 | int (*output)(struct sock *, struct sk_buff *)); |
88 | 89 | ||
89 | /* Generate a checksum for an outgoing IP datagram. */ | 90 | /* Generate a checksum for an outgoing IP datagram. */ |
@@ -219,7 +220,8 @@ static inline int ip_finish_output2(struct sock *sk, struct sk_buff *skb) | |||
219 | return -EINVAL; | 220 | return -EINVAL; |
220 | } | 221 | } |
221 | 222 | ||
222 | static int ip_finish_output_gso(struct sock *sk, struct sk_buff *skb) | 223 | static int ip_finish_output_gso(struct sock *sk, struct sk_buff *skb, |
224 | unsigned int mtu) | ||
223 | { | 225 | { |
224 | netdev_features_t features; | 226 | netdev_features_t features; |
225 | struct sk_buff *segs; | 227 | struct sk_buff *segs; |
@@ -227,7 +229,7 @@ static int ip_finish_output_gso(struct sock *sk, struct sk_buff *skb) | |||
227 | 229 | ||
228 | /* common case: locally created skb or seglen is <= mtu */ | 230 | /* common case: locally created skb or seglen is <= mtu */ |
229 | if (((IPCB(skb)->flags & IPSKB_FORWARDED) == 0) || | 231 | if (((IPCB(skb)->flags & IPSKB_FORWARDED) == 0) || |
230 | skb_gso_network_seglen(skb) <= ip_skb_dst_mtu(skb)) | 232 | skb_gso_network_seglen(skb) <= mtu) |
231 | return ip_finish_output2(sk, skb); | 233 | return ip_finish_output2(sk, skb); |
232 | 234 | ||
233 | /* Slowpath - GSO segment length is exceeding the dst MTU. | 235 | /* Slowpath - GSO segment length is exceeding the dst MTU. |
@@ -251,7 +253,7 @@ static int ip_finish_output_gso(struct sock *sk, struct sk_buff *skb) | |||
251 | int err; | 253 | int err; |
252 | 254 | ||
253 | segs->next = NULL; | 255 | segs->next = NULL; |
254 | err = ip_fragment(sk, segs, ip_finish_output2); | 256 | err = ip_fragment(sk, segs, mtu, ip_finish_output2); |
255 | 257 | ||
256 | if (err && ret == 0) | 258 | if (err && ret == 0) |
257 | ret = err; | 259 | ret = err; |
@@ -263,6 +265,8 @@ static int ip_finish_output_gso(struct sock *sk, struct sk_buff *skb) | |||
263 | 265 | ||
264 | static int ip_finish_output(struct sock *sk, struct sk_buff *skb) | 266 | static int ip_finish_output(struct sock *sk, struct sk_buff *skb) |
265 | { | 267 | { |
268 | unsigned int mtu; | ||
269 | |||
266 | #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) | 270 | #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) |
267 | /* Policy lookup after SNAT yielded a new policy */ | 271 | /* Policy lookup after SNAT yielded a new policy */ |
268 | if (skb_dst(skb)->xfrm) { | 272 | if (skb_dst(skb)->xfrm) { |
@@ -270,11 +274,12 @@ static int ip_finish_output(struct sock *sk, struct sk_buff *skb) | |||
270 | return dst_output_sk(sk, skb); | 274 | return dst_output_sk(sk, skb); |
271 | } | 275 | } |
272 | #endif | 276 | #endif |
277 | mtu = ip_skb_dst_mtu(skb); | ||
273 | if (skb_is_gso(skb)) | 278 | if (skb_is_gso(skb)) |
274 | return ip_finish_output_gso(sk, skb); | 279 | return ip_finish_output_gso(sk, skb, mtu); |
275 | 280 | ||
276 | if (skb->len > ip_skb_dst_mtu(skb)) | 281 | if (skb->len > mtu) |
277 | return ip_fragment(sk, skb, ip_finish_output2); | 282 | return ip_fragment(sk, skb, mtu, ip_finish_output2); |
278 | 283 | ||
279 | return ip_finish_output2(sk, skb); | 284 | return ip_finish_output2(sk, skb); |
280 | } | 285 | } |
@@ -482,10 +487,10 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
482 | } | 487 | } |
483 | 488 | ||
484 | static int ip_fragment(struct sock *sk, struct sk_buff *skb, | 489 | static int ip_fragment(struct sock *sk, struct sk_buff *skb, |
490 | unsigned int mtu, | ||
485 | int (*output)(struct sock *, struct sk_buff *)) | 491 | int (*output)(struct sock *, struct sk_buff *)) |
486 | { | 492 | { |
487 | struct iphdr *iph = ip_hdr(skb); | 493 | struct iphdr *iph = ip_hdr(skb); |
488 | unsigned int mtu = ip_skb_dst_mtu(skb); | ||
489 | 494 | ||
490 | if (unlikely(((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) || | 495 | if (unlikely(((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) || |
491 | (IPCB(skb)->frag_max_size && | 496 | (IPCB(skb)->frag_max_size && |