I've been toying with using IPDIVERT to adjust values in an IPv4 header. When adjusting an incoming IP header, the man page for divert(4) says:
My main issue was with trying to leverage the optimised kernel functions for checksumming an IP header, for example in_cksum_hdr(). Processes that connect to DIVERT sockets are based in user-land so in_cksum_hdr() isn't readily available during compile.
Eventually the thought hit me that if some part of the kernel has to validate checksums (to decide whether to drop a packet) AND if my user-land process has to calculate a checksum to avoid its packet being dropped THEN surely there are two wasted checksum calculations going on?
If a root-owned process, root needed for RAW socket, can be trusted to inject packets back into the IP stack then surely we can skip the checksum test and save a few CPU cycles plus a bit of latency.
Very simple patch for /usr/src/sys/netinet/ip_divert.c (based on rev 224575):
Packets written as incoming and having incorrect checksums will be dropped.
My main issue was with trying to leverage the optimised kernel functions for checksumming an IP header, for example in_cksum_hdr(). Processes that connect to DIVERT sockets are based in user-land so in_cksum_hdr() isn't readily available during compile.
Eventually the thought hit me that if some part of the kernel has to validate checksums (to decide whether to drop a packet) AND if my user-land process has to calculate a checksum to avoid its packet being dropped THEN surely there are two wasted checksum calculations going on?
If a root-owned process, root needed for RAW socket, can be trusted to inject packets back into the IP stack then surely we can skip the checksum test and save a few CPU cycles plus a bit of latency.
Very simple patch for /usr/src/sys/netinet/ip_divert.c (based on rev 224575):
Code:
--- ip_divert.c.orig 2013-08-26 20:52:18.000000000 +0100
+++ ip_divert.c 2013-08-26 20:52:44.000000000 +0100
@@ -496,6 +496,12 @@
/* Send packet to input processing via netisr */
switch (ip->ip_v) {
case IPVERSION:
+ /* mark mbuf as having valid checksum
+ to save userland divert process from
+ calculating checksum, and kernel having
+ to check it */
+ m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED |
+ CSUM_IP_VALID;
netisr_queue_src(NETISR_IP, (uintptr_t)so, m);
break;
#ifdef INET6