diff options
Diffstat (limited to 'include/net/udplite.h')
| -rw-r--r-- | include/net/udplite.h | 77 | 
1 files changed, 44 insertions, 33 deletions
diff --git a/include/net/udplite.h b/include/net/udplite.h index afdffe607b2..2caadabcd07 100644 --- a/include/net/udplite.h +++ b/include/net/udplite.h @@ -40,7 +40,7 @@ static inline int udplite_checksum_init(struct sk_buff *skb, struct udphdr *uh)           * checksum. UDP-Lite (like IPv6) mandates checksums, hence packets           * with a zero checksum field are illegal.                            */  	if (uh->check == 0) { -		LIMIT_NETDEBUG(KERN_DEBUG "UDPLITE: zeroed checksum field\n"); +		LIMIT_NETDEBUG(KERN_DEBUG "UDPLite: zeroed checksum field\n");  		return 1;  	} @@ -52,7 +52,7 @@ static inline int udplite_checksum_init(struct sk_buff *skb, struct udphdr *uh)  		/*  		 * Coverage length violates RFC 3828: log and discard silently.  		 */ -		LIMIT_NETDEBUG(KERN_DEBUG "UDPLITE: bad csum coverage %d/%d\n", +		LIMIT_NETDEBUG(KERN_DEBUG "UDPLite: bad csum coverage %d/%d\n",  			       cscov, skb->len);  		return 1; @@ -66,40 +66,34 @@ static inline int udplite_checksum_init(struct sk_buff *skb, struct udphdr *uh)  	return 0;  } -static inline int udplite_sender_cscov(struct udp_sock *up, struct udphdr *uh) +/* Slow-path computation of checksum. Socket is locked. */ +static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb)  { +	const struct udp_sock *up = udp_sk(skb->sk);  	int cscov = up->len; +	__wsum csum = 0; -	/* -	 * Sender has set `partial coverage' option on UDP-Lite socket -	 */ -	if (up->pcflag & UDPLITE_SEND_CC)    { +	if (up->pcflag & UDPLITE_SEND_CC) { +		/* +		 * Sender has set `partial coverage' option on UDP-Lite socket. +		 * The special case "up->pcslen == 0" signifies full coverage. +		 */  		if (up->pcslen < up->len) { -		/* up->pcslen == 0 means that full coverage is required, -		 * partial coverage only if  0 < up->pcslen < up->len */ -			if (0 < up->pcslen) { -			       cscov = up->pcslen; -			} -			uh->len = htons(up->pcslen); +			if (0 < up->pcslen) +				cscov = up->pcslen; +			udp_hdr(skb)->len = htons(up->pcslen);  		} -	/* -	 * NOTE: Causes for the error case  `up->pcslen > up->len': -	 *        (i)  Application error (will not be penalized). -	 *       (ii)  Payload too big for send buffer: data is split -	 *             into several packets, each with its own header. -	 *             In this case (e.g. last segment), coverage may -	 *             exceed packet length. -	 *       Since packets with coverage length > packet length are -	 *       illegal, we fall back to the defaults here. -	 */ +		/* +		 * NOTE: Causes for the error case  `up->pcslen > up->len': +		 *        (i)  Application error (will not be penalized). +		 *       (ii)  Payload too big for send buffer: data is split +		 *             into several packets, each with its own header. +		 *             In this case (e.g. last segment), coverage may +		 *             exceed packet length. +		 *       Since packets with coverage length > packet length are +		 *       illegal, we fall back to the defaults here. +		 */  	} -	return cscov; -} - -static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb) -{ -	int cscov = udplite_sender_cscov(udp_sk(sk), udp_hdr(skb)); -	__wsum csum = 0;  	skb->ip_summed = CHECKSUM_NONE;     /* no HW support for checksumming */ @@ -115,7 +109,24 @@ static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb)  	return csum;  } -extern void	udplite4_register(void); -extern int 	udplite_get_port(struct sock *sk, unsigned short snum, -			int (*scmp)(const struct sock *, const struct sock *)); +/* Fast-path computation of checksum. Socket may not be locked. */ +static inline __wsum udplite_csum(struct sk_buff *skb) +{ +	const struct udp_sock *up = udp_sk(skb->sk); +	const int off = skb_transport_offset(skb); +	int len = skb->len - off; + +	if ((up->pcflag & UDPLITE_SEND_CC) && up->pcslen < len) { +		if (0 < up->pcslen) +			len = up->pcslen; +		udp_hdr(skb)->len = htons(up->pcslen); +	} +	skb->ip_summed = CHECKSUM_NONE;     /* no HW support for checksumming */ + +	return skb_checksum(skb, off, len, 0); +} + +void udplite4_register(void); +int udplite_get_port(struct sock *sk, unsigned short snum, +		     int (*scmp)(const struct sock *, const struct sock *));  #endif	/* _UDPLITE_H */  | 
