Which Process?

Patrick Schaaf bof@bof.de
Wed, 1 Aug 2001 00:23:30 +0200


> In other words, it is unlikely that you need to worry about it.

I fully agree with this general characterization.

As the topic piqued my interest for a short time, I made a dirty hack
to measure ipt_do_table() latency. Using rdtsc() amortized over 1000
packets, I find that a simple nontaken ruleset line (simple meaning
IP checks only), takes roughly 75 clock cycles on my 500 Mhz P-III.

regards
  Patrick

Here's the diff, but be careful. This is a hack, non-smp-safe,
heavily performance impacting (50% performance loss - on my
160000 pps silly flood test.) I consciously leave applying this patch,
and finding and understanding its output, as an exercize to the readers.

--- ../dl360/linux-2.4.8-pre3-vlan-pom/net/ipv4/netfilter/Config.in	Fri Jul 27 08:40:17 2001
+++ ./linux-2.4.8-pre3-vlan-pom/net/ipv4/netfilter/Config.in	Tue Jul 31 21:23:57 2001
@@ -14,6 +14,13 @@
 fi
 tristate 'IP tables support (required for filtering/masq/NAT)' CONFIG_IP_NF_IPTABLES
 if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
+  bool '  time ipt_do_table' CONFIG_NETFILTER_TIME_DO_TABLE n
+  if [ "$CONFIG_NETFILTER_TIME_DO_TABLE" = "y" ]; then
+    if [ "$CONFIG_NETFILTER_TIME_DO_TABLE_MASK" = "" ]; then
+      CONFIG_NETFILTER_TIME_DO_TABLE_MASK=1023
+    fi
+    int '    take time every N+1 packets' CONFIG_NETFILTER_TIME_DO_TABLE_MASK
+  fi
 # The simple matches.
   dep_tristate '  limit match support' CONFIG_IP_NF_MATCH_LIMIT $CONFIG_IP_NF_IPTABLES
 
--- ../dl360/linux-2.4.8-pre3-vlan-pom/net/ipv4/netfilter/ip_tables.c	Tue May 15 08:29:35 2001
+++ ./linux-2.4.8-pre3-vlan-pom/net/ipv4/netfilter/ip_tables.c	Tue Jul 31 21:30:05 2001
@@ -243,6 +243,38 @@
 	return (struct ipt_entry *)(base + offset);
 }
 
+#if defined(CONFIG_NETFILTER_TIME_DO_TABLE)
+
+#include <asm/msr.h>
+
+static unsigned long long tdt_count = 1;
+static unsigned long long tdt_count_last = 1;
+static unsigned long long tdt_cyclesum;
+static unsigned long long tdt_cyclesum_last;
+
+static void tdt__output(void)
+{
+	unsigned long long countdiff = tdt_count - tdt_count_last;
+	unsigned long long sumdiff = tdt_cyclesum - tdt_cyclesum_last;
+
+	printk("TDT-TOTAL %Ld %Ld\n", tdt_count, tdt_cyclesum);
+	printk("TDT-RECENT %Ld %Ld\n", countdiff, sumdiff);
+	tdt_count_last = tdt_count;
+	tdt_cyclesum_last = tdt_cyclesum;
+}
+
+#if !defined(CONFIG_NETFILTER_TIME_DO_TABLE_MASK)
+#define CONFIG_NETFILTER_TIME_DO_TABLE_MASK 255
+#endif
+
+static inline void tdt_output(void)
+{
+	if ((tdt_count & CONFIG_NETFILTER_TIME_DO_TABLE_MASK) == 0)
+		tdt__output();
+}
+
+#endif
+
 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
 unsigned int
 ipt_do_table(struct sk_buff **pskb,
@@ -263,6 +295,12 @@
 	const char *indev, *outdev;
 	void *table_base;
 	struct ipt_entry *e, *back;
+#if defined(CONFIG_NETFILTER_TIME_DO_TABLE)
+	unsigned long long stamp_start;
+	unsigned long long stamp_end;
+	
+	rdtscll(stamp_start);
+#endif
 
 	/* Initialization */
 	ip = (*pskb)->nh.iph;
@@ -392,6 +430,13 @@
 	((struct ipt_entry *)table_base)->comefrom = 0xdead57ac;
 #endif
 	read_unlock_bh(&table->lock);
+
+#if defined(CONFIG_NETFILTER_TIME_DO_TABLE)
+	rdtscll(stamp_end);
+	tdt_count++;
+	tdt_cyclesum += (stamp_end - stamp_start);
+	tdt_output();
+#endif
 
 #ifdef DEBUG_ALLOW_ALL
 	return NF_ACCEPT;