diff mbox

net: fix bogus cast in skb_pagelen() and use unsigned variables

Message ID 20161119010808.GF1200@avx2
State Accepted, archived
Delegated to: David Miller
Headers show

Commit Message

Alexey Dobriyan Nov. 19, 2016, 1:08 a.m. UTC
1) cast to "int" is unnecessary:
   u8 will be promoted to int before decrementing,
   small positive numbers fit into "int", so their values won't be changed
   during promotion.

   Once everything is int including loop counters, signedness doesn't
   matter: 32-bit operations will stay 32-bit operations.

   But! Someone tried to make this loop smart by making everything of
   the same type apparently in an attempt to optimise it.
   Do the optimization, just differently.
   Do the cast where it matters. :^)

2) frag size is unsigned entity and sum of fragments sizes is also
   unsigned.

Make everything unsigned, leave no MOVSX instruction behind.


	add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-4 (-4)
	function                                     old     new   delta
	skb_cow_data                                 835     834      -1
	ip_do_fragment                              2549    2548      -1
	ip6_fragment                                3130    3128      -2
	Total: Before=154865032, After=154865028, chg -0.00%


Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---

 include/linux/skbuff.h |    6 +++---
 net/ipv4/ip_output.c   |    2 +-
 net/ipv6/ip6_output.c  |    2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

Comments

David Miller Nov. 20, 2016, 3:12 a.m. UTC | #1
From: Alexey Dobriyan <adobriyan@gmail.com>
Date: Sat, 19 Nov 2016 04:08:08 +0300

> 1) cast to "int" is unnecessary:
>    u8 will be promoted to int before decrementing,
>    small positive numbers fit into "int", so their values won't be changed
>    during promotion.
> 
>    Once everything is int including loop counters, signedness doesn't
>    matter: 32-bit operations will stay 32-bit operations.
> 
>    But! Someone tried to make this loop smart by making everything of
>    the same type apparently in an attempt to optimise it.
>    Do the optimization, just differently.
>    Do the cast where it matters. :^)
> 
> 2) frag size is unsigned entity and sum of fragments sizes is also
>    unsigned.
> 
> Make everything unsigned, leave no MOVSX instruction behind.
 ...
> Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>

Applied to net-next.
David Laight Nov. 23, 2016, 12:49 p.m. UTC | #2
From: Alexey Dobriyan
> Sent: 19 November 2016 01:08
...
> -	for (i = (int)skb_shinfo(skb)->nr_frags - 1; i >= 0; i--)
> +	for (i = skb_shinfo(skb)->nr_frags - 1; (int)i >= 0; i--)
>  		len += skb_frag_size(&skb_shinfo(skb)->frags[i]);

Think I'd use:
	for (i = skb_shinfo(skb)->nr_frags; i-- != 0; )

	David
Alexey Dobriyan Nov. 23, 2016, 3:35 p.m. UTC | #3
On Wed, Nov 23, 2016 at 3:49 PM, David Laight <David.Laight@aculab.com> wrote:
> From: Alexey Dobriyan
>> Sent: 19 November 2016 01:08
> ...
>> -     for (i = (int)skb_shinfo(skb)->nr_frags - 1; i >= 0; i--)
>> +     for (i = skb_shinfo(skb)->nr_frags - 1; (int)i >= 0; i--)
>>               len += skb_frag_size(&skb_shinfo(skb)->frags[i]);
>
> Think I'd use:
>         for (i = skb_shinfo(skb)->nr_frags; i-- != 0; )

This kind of diverges from canonical loop form:

  for (init; temination condition: iterator)

by shifting everything into termination part.

  A
diff mbox

Patch

--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1799,11 +1799,11 @@  static inline unsigned int skb_headlen(const struct sk_buff *skb)
 	return skb->len - skb->data_len;
 }
 
-static inline int skb_pagelen(const struct sk_buff *skb)
+static inline unsigned int skb_pagelen(const struct sk_buff *skb)
 {
-	int i, len = 0;
+	unsigned int i, len = 0;
 
-	for (i = (int)skb_shinfo(skb)->nr_frags - 1; i >= 0; i--)
+	for (i = skb_shinfo(skb)->nr_frags - 1; (int)i >= 0; i--)
 		len += skb_frag_size(&skb_shinfo(skb)->frags[i]);
 	return len + skb_headlen(skb);
 }
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -581,7 +581,7 @@  int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
 	 */
 	if (skb_has_frag_list(skb)) {
 		struct sk_buff *frag, *frag2;
-		int first_len = skb_pagelen(skb);
+		unsigned int first_len = skb_pagelen(skb);
 
 		if (first_len - hlen > mtu ||
 		    ((first_len - hlen) & 7) ||
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -625,7 +625,7 @@  int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
 
 	hroom = LL_RESERVED_SPACE(rt->dst.dev);
 	if (skb_has_frag_list(skb)) {
-		int first_len = skb_pagelen(skb);
+		unsigned int first_len = skb_pagelen(skb);
 		struct sk_buff *frag2;
 
 		if (first_len - hlen > mtu ||