[IPFW] [DIVERT] IP header checksums - why calculate twice?
Dom F
misc+freebsd at talk2dom.com
Wed Aug 28 10:45:50 UTC 2013
[Copy of my post to FreeBSD Firewalls forum sent here by suggestion from
moderator]
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:
Quote:
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
More information about the freebsd-net
mailing list