Skip to contentSkip to conversation

Allow to use adler32 for SCTP

RFC PATCH In review Holger Hans Peter Freyther 2 participants 3 messages Jan 12, 2011 – Jan 14, 2011

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 Allow to use adler32 for SCTP

Hi,

with OpenBSC I have to connect to some equipment that is configured to use adler32 as the checksum. I wonder if something a long the lines of this patch is acceptable? It adds a module parameter that globally allows to use adler32 and then there is a sockopt to enable adler32 on a per process basis. For the receive path I have to decode both checksums.

I could probably just use the code to disable checksums for rx but I will need to generate them on tx to make the other equipment accept these.

regards
holger

PS: While adding my field to struct sctp_sock I saw that there are quite some holes (on both ia32,x86_64) in the struct and that one can save 16byte by re-ordering. I am not sure how to and if to benchmark such a change. Does it make sense to re-order those?

PPS: This was sent to netdev first, so sorry if people see it twice

From bc332df3e078e4ddac93415a4e11de018604537a Mon Sep 17 00:00:00 2001
From: Holger Hans Peter Freyther <[email protected]>
Date: Sun, 9 Jan 2011 21:18:04 +0100
Subject: [PATCH] sctp: Allow to use adler32 as checksum for old equipment

Make it possible to use adler32 for outgoing packets. For incoming packets add an option to determine the crc32 and adler32. Discard the packet if the socket was not using the adler32 checksum.

---
 include/net/sctp/checksum.h |   35 ++++++++++++++++++++++++++++++++
 include/net/sctp/structs.h  |    6 +++++
 include/net/sctp/user.h     |    1 +
 net/sctp/input.c            |   46 +++++++++++++++++++++++++++++++++++++++---
 net/sctp/output.c           |   17 +++++++++++++--
 net/sctp/protocol.c         |    3 ++
 net/sctp/socket.c           |   23 +++++++++++++++++++++
 7 files changed, 124 insertions(+), 7 deletions(-)
include/net/sctp/checksum.h +35 -0
index befc8d2..9111f52 100644
@@ -1,6 +1,7 @@
 /* SCTP kernel reference Implementation
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001-2003 International Business Machines, Corp.
+ * Copyright (c) 2011 Holger Hans Peter Freyther
  *
  * This file is part of the SCTP kernel reference Implementation
  *
@@ -34,6 +35,7 @@
  *    Dinakaran Joseph
  *    Jon Grimm <[email protected]>
  *    Sridhar Samudrala <[email protected]>
+ *    Holger Hans Peter Freyther <[email protected]>
  *
  * Rewritten to use libcrc32c by:
  *    Vlad Yasevich <[email protected]>
@@ -45,6 +47,7 @@
 #include <linux/types.h>
 #include <net/sctp/sctp.h>
 #include <linux/crc32c.h>
+#include <linux/zutil.h>
 
 static inline __u32 sctp_crc32c(__u32 crc, u8 *buffer, u16 length)
 {
@@ -81,3 +84,35 @@ static inline __le32 sctp_end_cksum(__be32 crc32)
 {
 	return cpu_to_le32(~crc32);
 }
+
+static inline __u32 sctp_start_cksum_adler(__u8 *buffer, __u16 length)
+{
+	__u32 adler = 1;
+	__u8  zero[sizeof(__u32)] = {0};
+
+	/* Optimize this routine to be SCTP specific, knowing how
+	 * to skip the checksum field of the SCTP header.
+	 */
+
+	/* Calculate adler32 up to the checksum. */
+	adler = zlib_adler32(adler, buffer,
+				sizeof(struct sctphdr) -sizeof(__u32));
+
+	/* Skip checksum field of the header. */
+	adler = zlib_adler32(adler, zero, sizeof(__u32));
+
+	/* Calculate the rest of the adler32. */
+	adler = zlib_adler32(adler, &buffer[sizeof(struct sctphdr)],
+				length - sizeof(struct sctphdr));
+	return adler;
+}
+
+static inline __u32 sctp_update_cksum_adler(__u8 *buffer, __u16 len, __u32 a32)
+{
+	return zlib_adler32(a32, buffer, len);
+}
+
+static inline __u32 sctp_end_cksum_adler(__u32 a32)
+{
+	return htonl(a32);
+}
include/net/sctp/structs.h +6 -0
index cc9185c..d44eb7a 100644
@@ -236,6 +236,9 @@ extern struct sctp_globals {
 	 * bits is an indicator of when to send and window update SACK.
 	 */
 	int rwnd_update_shift;
+
+	/* Allow Adler32 as Checksum fallback */
+	int allow_adler32;
 } sctp_globals;
 
 #define sctp_rto_initial		(sctp_globals.rto_initial)
@@ -271,6 +274,7 @@ extern struct sctp_globals {
 #define sctp_auth_enable		(sctp_globals.auth_enable)
 #define sctp_checksum_disable		(sctp_globals.checksum_disable)
 #define sctp_rwnd_upd_shift		(sctp_globals.rwnd_update_shift)
+#define sctp_allow_adler32_csum		(sctp_globals.allow_adler32)
 
 /* SCTP Socket type: UDP or TCP style. */
 typedef enum {
@@ -338,6 +342,8 @@ struct sctp_sock {
 	__u32 adaptation_ind;
 	__u32 pd_point;
 
+	__u8 cksum_adler;
+
 	atomic_t pd_mode;
 	/* Receive to here while partial delivery is in effect. */
 	struct sk_buff_head pd_lobby;
include/net/sctp/user.h +1 -0
index 2b2769c..427da93 100644
@@ -103,6 +103,7 @@ typedef __s32 sctp_assoc_t;
 #define SCTP_GET_LOCAL_ADDRS	109		/* Get all local addresss. */
 #define SCTP_SOCKOPT_CONNECTX	110		/* CONNECTX requests. */
 #define SCTP_SOCKOPT_CONNECTX3	111	/* CONNECTX requests (updated) */
+#define SCTP_COMPAT_ADLER_CRC	112	/* User ADLER32 for the checksum. */
 
 /*
  * 5.2.1 SCTP Initiation Structure (SCTP_INIT)
net/sctp/input.c +42 -4

88 lines not on this page · raw message

net/sctp/output.c +14 -3
index 60600d3..02b2f26 100644
@@ -2,6 +2,7 @@
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
+ * Copyright (c) 2011 Holger Hans Peter Freyther
  *
  * This file is part of the SCTP kernel implementation
  *
@@ -36,6 +37,7 @@
  *    Karl Knutson          <[email protected]>
  *    Jon Grimm             <[email protected]>
  *    Sridhar Samudrala     <[email protected]>
+ *    Holger Freyther       <[email protected]>
  *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
@@ -502,12 +504,21 @@ int sctp_packet_transmit(struct sctp_packet *packet)
 	 */
 	if (!sctp_checksum_disable &&
 	    !(dst->dev->features & (NETIF_F_NO_CSUM | NETIF_F_SCTP_CSUM))) {
-		__u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len);
-
 		/* 3) Put the resultant value into the checksum field in the
 		 *    common header, and leave the rest of the bits unchanged.
 		 */
-		sh->checksum = sctp_end_cksum(crc32);
+		__u32 crc32;
+
+		if (sctp_sk(sk)->cksum_adler && sctp_allow_adler32_csum) {
+			crc32 = sctp_start_cksum_adler((__u8 *)sh,
+							cksum_buf_len);
+			crc32 = sctp_end_cksum_adler(crc32);
+		} else {
+			crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len);
+			crc32 = sctp_end_cksum(crc32);
+		}
+
+		sh->checksum = crc32;
 	} else {
 		if (dst->dev->features & NETIF_F_SCTP_CSUM) {
 			/* no need to seed psuedo checksum for SCTP */
net/sctp/protocol.c +3 -0
index e58f947..f078ef6 100644
@@ -1397,4 +1397,7 @@ MODULE_AUTHOR("Linux Kernel SCTP developers <[email protected]
 MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)");
 module_param_named(no_checksums, sctp_checksum_disable, bool, 0644);
 MODULE_PARM_DESC(no_checksums, "Disable checksums computing and verification");
+module_param_named(adler_checksums, sctp_allow_adler32_csum, bool, 0644);
+MODULE_PARM_DESC(adler_checksums,
+		"Allow to use adler32 checksums for historic reasons.");
 MODULE_LICENSE("GPL");
net/sctp/socket.c +23 -0
index a09b0dd..e47e39e 100644
@@ -5,6 +5,7 @@
  * Copyright (c) 2001-2003 Intel Corp.
  * Copyright (c) 2001-2002 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
+ * Copyright (c) 2011 Holger Hans Peter Freyther
  *
  * This file is part of the SCTP kernel implementation
  *
@@ -52,6 +53,7 @@
  *    Ryan Layer	    <[email protected]>
  *    Anup Pemmaiah         <[email protected]>
  *    Kevin Gao             <[email protected]>
+ *    Holger Freyther       <[email protected]>
  *
  * Any bugs reported given to us we will try to fix... any fixes shared will
  * be incorporated into the next SCTP release.
@@ -3343,6 +3345,23 @@ static int sctp_setsockopt_del_key(struct sock *sk,
 
 }
 
+static int sctp_setsockopt_adler_crc(struct sock *sk,
+					char __user *optval,
+					int optlen)
+{
+	int val;
+
+	if (optlen < sizeof(int))
+		return -EINVAL;
+	if (get_user(val, (int __user *)optval))
+		return -EFAULT;
+	if (!sctp_allow_adler32_csum)
+		return -EACCES;
+
+	sctp_sk(sk)->cksum_adler = 1;
+	return 0;
+}
+
 
 /* API 6.2 setsockopt(), getsockopt()
  *
@@ -3490,6 +3509,9 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
 	case SCTP_AUTH_DELETE_KEY:
 		retval = sctp_setsockopt_del_key(sk, optval, optlen);
 		break;
+	case SCTP_COMPAT_ADLER_CRC:
+		retval = sctp_setsockopt_adler_crc(sk, optval, optlen);
+		break;
 	default:
 		retval = -ENOPROTOOPT;
 		break;
@@ -6490,6 +6512,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
 	pp = sctp_sk(oldsk)->bind_hash;
 	sk_add_bind_node(newsk, &pp->owner);
 	sctp_sk(newsk)->bind_hash = pp;
+	sctp_sk(newsk)->cksum_adler = sctp_sk(oldsk)->cksum_adler;
 	inet_sk(newsk)->inet_num = inet_sk(oldsk)->inet_num;
 	sctp_spin_unlock(&head->lock);
 	sctp_local_bh_enable();
Signature · 1 line
1.7.3.4
#1 lore raw
Quoted 9 lines

Hi,

with OpenBSC I have to connect to some equipment that is configured to use adler32 as the checksum. I wonder if something a long the lines of this patch is acceptable? It adds a module parameter that globally allows to use adler32 and then there is a sockopt to enable adler32 on a per process basis. For the receive path I have to decode both checksums.

decode both checksums by default will cause performance lost. Why not change this to kernel config, and disable it by default since most people do not need this?

Other question: why not just update your box which only support adler32 to support new crc32 checksums? Linux and Freebsd etc. do not using adler32, but using crc32.

Quoted 12 lines

I could probably just use the code to disable checksums for rx but I will need to generate them on tx to make the other equipment accept these.

regards
holger

PS: While adding my field to struct sctp_sock I saw that there are quite some holes (on both ia32,x86_64) in the struct and that one can save 16byte by re-ordering. I am not sure how to and if to benchmark such a change. Does it make sense to re-order those?

PPS: This was sent to netdev first, so sorry if people see it twice

#2 lore raw
In reply to Holger Hans Peter Freyther
Quoted 4 lines · Wei Yongjun

decode both checksums by default will cause performance lost. Why not change this to kernel config, and disable it by default since most people do not need this?

Well, by default I am only checking the CRC32 checksum and have a test and a branch for a global variable. So the question is what is the impact of the extra load of the global variable?

Do you have a benchmark in mind? Something as simple as one connection and sending messages between two machines? Or should I guard this whole config with a kernel config right away?

Quoted 5 lines

Other question: why not just update your box which only support adler32 to support new crc32 checksums? Linux and Freebsd etc. do not using adler32, but using crc32.

I wish I could, the machine is on the edge of the network and not in my control.