aboutgitcodebugslistschat
path: root/udp.c
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2021-07-26 07:18:50 +0200
committerStefano Brivio <sbrivio@redhat.com>2021-07-26 07:18:50 +0200
commit17765f8de0782de09ebdf79940f934b8ccb83c41 (patch)
tree11cc42c19a2b694b66dde7e377ba78e2107fd62a /udp.c
parent0be49ccd93186600e40b8bffe867d18c4d16366a (diff)
downloadpasst-17765f8de0782de09ebdf79940f934b8ccb83c41.tar
passt-17765f8de0782de09ebdf79940f934b8ccb83c41.tar.gz
passt-17765f8de0782de09ebdf79940f934b8ccb83c41.tar.bz2
passt-17765f8de0782de09ebdf79940f934b8ccb83c41.tar.lz
passt-17765f8de0782de09ebdf79940f934b8ccb83c41.tar.xz
passt-17765f8de0782de09ebdf79940f934b8ccb83c41.tar.zst
passt-17765f8de0782de09ebdf79940f934b8ccb83c41.zip
checksum: Introduce AVX2 implementation, unify helpers
Provide an AVX2-based function using compiler intrinsics for TCP/IP-style checksums. The load/unpack/add idea and implementation is largely based on code from BESS (the Berkeley Extensible Software Switch) licensed as 3-Clause BSD, with a number of modifications to further decrease pipeline stalls and to minimise cache pollution. This speeds up considerably data paths from sockets to tap interfaces, decreasing overhead for checksum computation, with 16-64KiB packet buffers, from approximately 11% to 7%. The rest is just syscalls at this point. While at it, provide convenience targets in the Makefile for avx2, avx2_debug, and debug targets -- these simply add target-specific CFLAGS to the build. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'udp.c')
-rw-r--r--udp.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/udp.c b/udp.c
index 30659e0..00a34a9 100644
--- a/udp.c
+++ b/udp.c
@@ -110,6 +110,7 @@
#include <linux/udp.h>
#include <time.h>
+#include "checksum.h"
#include "util.h"
#include "passt.h"
#include "tap.h"
@@ -210,6 +211,11 @@ udp4_l2_buf[UDP_TAP_FRAMES] = {
*/
__extension__ struct udp6_l2_buf_t {
struct sockaddr_in6 s_in6;
+#ifdef __AVX2__
+ /* Align ip6h to 32-byte boundary. */
+ uint8_t pad[64 - (sizeof(struct sockaddr_in6) + sizeof(struct ethhdr) +
+ sizeof(uint32_t))];
+#endif
uint32_t vnet_len;
struct ethhdr eh;
@@ -217,10 +223,18 @@ __extension__ struct udp6_l2_buf_t {
struct udphdr uh;
uint8_t data[USHRT_MAX -
(sizeof(struct ipv6hdr) + sizeof(struct udphdr))];
+#ifdef __AVX2__
+} __attribute__ ((packed, aligned(32)))
+#else
} __attribute__ ((packed, aligned(__alignof__(unsigned int))))
+#endif
udp6_l2_buf[UDP_TAP_FRAMES] = {
[ 0 ... UDP_TAP_FRAMES - 1 ] = {
- { 0 }, 0, L2_BUF_ETH_IP6_INIT, L2_BUF_IP6_INIT(IPPROTO_UDP),
+ { 0 },
+#ifdef __AVX2__
+ { 0 },
+#endif
+ 0, L2_BUF_ETH_IP6_INIT, L2_BUF_IP6_INIT(IPPROTO_UDP),
{ 0 }, { 0 },
},
};
@@ -656,7 +670,7 @@ void udp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
b->ip6h.version = 0;
b->ip6h.nexthdr = 0;
b->uh.check = 0;
- b->uh.check = csum_ip4(&b->ip6h, ip_len);
+ b->uh.check = csum(&b->ip6h, ip_len, 0);
b->ip6h.version = 6;
b->ip6h.nexthdr = IPPROTO_UDP;
b->ip6h.hop_limit = 255;