diff options
author | Eric Dumazet <edumazet@google.com> | 2012-07-04 18:30:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-05 06:03:32 -0400 |
commit | bf5e53e3717ed28be69d0663c65962d1731e7ee4 (patch) | |
tree | 7211c0114426ece185d27e3d7c637ecf354fba72 /net | |
parent | 36bdbcae2fa2a6dfa99344d4190fcea0aa7b7c25 (diff) |
ipv4: defer fib_compute_spec_dst() call
ip_options_compile() can avoid calling fib_compute_spec_dst()
by default, and perform the call only if needed.
David suggested to add a helper to make the call only once.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/ip_options.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 1f022510abe3..a19d6471a318 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c | |||
@@ -242,6 +242,15 @@ void ip_options_fragment(struct sk_buff *skb) | |||
242 | opt->ts_needtime = 0; | 242 | opt->ts_needtime = 0; |
243 | } | 243 | } |
244 | 244 | ||
245 | /* helper used by ip_options_compile() to call fib_compute_spec_dst() | ||
246 | * at most one time. | ||
247 | */ | ||
248 | static void spec_dst_fill(__be32 *spec_dst, struct sk_buff *skb) | ||
249 | { | ||
250 | if (*spec_dst == htonl(INADDR_ANY)) | ||
251 | *spec_dst = fib_compute_spec_dst(skb); | ||
252 | } | ||
253 | |||
245 | /* | 254 | /* |
246 | * Verify options and fill pointers in struct options. | 255 | * Verify options and fill pointers in struct options. |
247 | * Caller should clear *opt, and set opt->data. | 256 | * Caller should clear *opt, and set opt->data. |
@@ -251,7 +260,7 @@ void ip_options_fragment(struct sk_buff *skb) | |||
251 | int ip_options_compile(struct net *net, | 260 | int ip_options_compile(struct net *net, |
252 | struct ip_options *opt, struct sk_buff *skb) | 261 | struct ip_options *opt, struct sk_buff *skb) |
253 | { | 262 | { |
254 | __be32 spec_dst = (__force __be32) 0; | 263 | __be32 spec_dst = htonl(INADDR_ANY); |
255 | unsigned char *pp_ptr = NULL; | 264 | unsigned char *pp_ptr = NULL; |
256 | struct rtable *rt = NULL; | 265 | struct rtable *rt = NULL; |
257 | unsigned char *optptr; | 266 | unsigned char *optptr; |
@@ -260,8 +269,6 @@ int ip_options_compile(struct net *net, | |||
260 | 269 | ||
261 | if (skb != NULL) { | 270 | if (skb != NULL) { |
262 | rt = skb_rtable(skb); | 271 | rt = skb_rtable(skb); |
263 | if (rt) | ||
264 | spec_dst = fib_compute_spec_dst(skb); | ||
265 | optptr = (unsigned char *)&(ip_hdr(skb)[1]); | 272 | optptr = (unsigned char *)&(ip_hdr(skb)[1]); |
266 | } else | 273 | } else |
267 | optptr = opt->__data; | 274 | optptr = opt->__data; |
@@ -334,6 +341,7 @@ int ip_options_compile(struct net *net, | |||
334 | goto error; | 341 | goto error; |
335 | } | 342 | } |
336 | if (rt) { | 343 | if (rt) { |
344 | spec_dst_fill(&spec_dst, skb); | ||
337 | memcpy(&optptr[optptr[2]-1], &spec_dst, 4); | 345 | memcpy(&optptr[optptr[2]-1], &spec_dst, 4); |
338 | opt->is_changed = 1; | 346 | opt->is_changed = 1; |
339 | } | 347 | } |
@@ -376,6 +384,7 @@ int ip_options_compile(struct net *net, | |||
376 | } | 384 | } |
377 | opt->ts = optptr - iph; | 385 | opt->ts = optptr - iph; |
378 | if (rt) { | 386 | if (rt) { |
387 | spec_dst_fill(&spec_dst, skb); | ||
379 | memcpy(&optptr[optptr[2]-1], &spec_dst, 4); | 388 | memcpy(&optptr[optptr[2]-1], &spec_dst, 4); |
380 | timeptr = &optptr[optptr[2]+3]; | 389 | timeptr = &optptr[optptr[2]+3]; |
381 | } | 390 | } |