Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f36c23bb authored by Gerrit Renker's avatar Gerrit Renker Committed by David S. Miller
Browse files

udplite: fast-path computation of checksum coverage



Commit 903ab86d of 1 March this year ("udp: Add
lockless transmit path") introduced a new fast TX path that broke the checksum
coverage computation of UDP-lite, which so far depended on up->len (only set
if the socket is locked and 0 in the fast path).

Fixed by providing both fast- and slow-path computation of checksum coverage.
The latter can be removed when UDP(-lite)v6 also uses a lockless transmit path.
 
Reported-by: default avatarThomas Volkert <thomas@homer-conferencing.com>
Signed-off-by: default avatarGerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4c41042d
Loading
Loading
Loading
Loading
+31 −32
Original line number Diff line number Diff line
@@ -66,21 +66,22 @@ 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;

	if (up->pcflag & UDPLITE_SEND_CC) {
		/*
	 * Sender has set `partial coverage' option on UDP-Lite socket
		 * Sender has set `partial coverage' option on UDP-Lite socket.
		 * The special case "up->pcslen == 0" signifies full coverage.
		 */
	if (up->pcflag & UDPLITE_SEND_CC)    {
		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) {
			if (0 < up->pcslen)
				cscov = up->pcslen;
			}
			uh->len = htons(up->pcslen);
			udp_hdr(skb)->len = htons(up->pcslen);
		}
		/*
		 * NOTE: Causes for the error case  `up->pcslen > up->len':
@@ -93,13 +94,6 @@ static inline int udplite_sender_cscov(struct udp_sock *up, struct udphdr *uh)
		 *       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,16 +109,21 @@ static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb)
	return csum;
}

/* Fast-path computation of checksum. Socket may not be locked. */
static inline __wsum udplite_csum(struct sk_buff *skb)
{
	struct sock *sk = skb->sk;
	int cscov = udplite_sender_cscov(udp_sk(sk), udp_hdr(skb));
	const struct udp_sock *up = udp_sk(skb->sk);
	const int off = skb_transport_offset(skb);
	const int len = skb->len - off;
	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, min(cscov, len), 0);
	return skb_checksum(skb, off, len, 0);
}

extern void	udplite4_register(void);