Allow to use adler32 for SCTP
Subsystems (2)
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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
holgerPS: While adding my field to struct
sctp_sockI 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
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.