Module Name:    src
Committed By:   rmind
Date:           Mon Jun  4 00:28:34 UTC 2012

Modified Files:
        src/usr.sbin/npf/npftest: npftest.c npftest.h
        src/usr.sbin/npf/npftest/libnpftest: Makefile npf_test.h
Added Files:
        src/usr.sbin/npf/npftest/libnpftest: npf_state_test.c

Log Message:
npftest: add a module for TCP state tracking and add few test cases.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/usr.sbin/npf/npftest/npftest.c \
    src/usr.sbin/npf/npftest/npftest.h
cvs rdiff -u -r1.2 -r1.3 src/usr.sbin/npf/npftest/libnpftest/Makefile \
    src/usr.sbin/npf/npftest/libnpftest/npf_test.h
cvs rdiff -u -r0 -r1.1 src/usr.sbin/npf/npftest/libnpftest/npf_state_test.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.sbin/npf/npftest/npftest.c
diff -u src/usr.sbin/npf/npftest/npftest.c:1.2 src/usr.sbin/npf/npftest/npftest.c:1.3
--- src/usr.sbin/npf/npftest/npftest.c:1.2	Wed May 30 21:38:04 2012
+++ src/usr.sbin/npf/npftest/npftest.c	Mon Jun  4 00:28:34 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: npftest.c,v 1.2 2012/05/30 21:38:04 rmind Exp $	*/
+/*	$NetBSD: npftest.c,v 1.3 2012/06/04 00:28:34 rmind Exp $	*/
 
 /*
  * NPF testing framework.
@@ -179,6 +179,9 @@ main(int argc, char **argv)
 
 		ok = rumpns_npf_table_test(verbose);
 		result("table", ok);
+
+		ok = rumpns_npf_state_test(verbose);
+		result("state", ok);
 	}
 
 	if (stream) {
Index: src/usr.sbin/npf/npftest/npftest.h
diff -u src/usr.sbin/npf/npftest/npftest.h:1.2 src/usr.sbin/npf/npftest/npftest.h:1.3
--- src/usr.sbin/npf/npftest/npftest.h:1.2	Wed May 30 21:38:04 2012
+++ src/usr.sbin/npf/npftest/npftest.h	Mon Jun  4 00:28:34 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: npftest.h,v 1.2 2012/05/30 21:38:04 rmind Exp $	*/
+/*	$NetBSD: npftest.h,v 1.3 2012/06/04 00:28:34 rmind Exp $	*/
 
 /*
  * Public Domain.
@@ -17,6 +17,7 @@ int		rumpns_npf_test_handlepkt(const voi
 bool		rumpns_npf_nbuf_test(bool);
 bool		rumpns_npf_processor_test(bool);
 bool		rumpns_npf_table_test(bool);
+bool		rumpns_npf_state_test(bool);
 
 int		process_stream(const char *, const char *, unsigned);
 

Index: src/usr.sbin/npf/npftest/libnpftest/Makefile
diff -u src/usr.sbin/npf/npftest/libnpftest/Makefile:1.2 src/usr.sbin/npf/npftest/libnpftest/Makefile:1.3
--- src/usr.sbin/npf/npftest/libnpftest/Makefile:1.2	Wed May 30 21:38:04 2012
+++ src/usr.sbin/npf/npftest/libnpftest/Makefile	Mon Jun  4 00:28:34 2012
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.2 2012/05/30 21:38:04 rmind Exp $
+# $NetBSD: Makefile,v 1.3 2012/06/04 00:28:34 rmind Exp $
 #
 # Public Domain
 #
@@ -14,6 +14,7 @@ SRCS+=		npf_mbuf_subr.c
 SRCS+=		npf_nbuf_test.c
 SRCS+=		npf_processor_test.c
 SRCS+=		npf_table_test.c
+SRCS+=		npf_state_test.c
 
 CPPFLAGS+=	-D_NPF_TESTING
 CPPFLAGS+=	-I${.CURDIR}/../../../../sys/net/npf
Index: src/usr.sbin/npf/npftest/libnpftest/npf_test.h
diff -u src/usr.sbin/npf/npftest/libnpftest/npf_test.h:1.2 src/usr.sbin/npf/npftest/libnpftest/npf_test.h:1.3
--- src/usr.sbin/npf/npftest/libnpftest/npf_test.h:1.2	Wed May 30 21:38:04 2012
+++ src/usr.sbin/npf/npftest/libnpftest/npf_test.h	Mon Jun  4 00:28:34 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_test.h,v 1.2 2012/05/30 21:38:04 rmind Exp $	*/
+/*	$NetBSD: npf_test.h,v 1.3 2012/06/04 00:28:34 rmind Exp $	*/
 
 /*
  * Public Domain.
@@ -37,5 +37,6 @@ void		mbuf_icmp_append(struct mbuf *, st
 bool		npf_nbuf_test(bool);
 bool		npf_processor_test(bool);
 bool		npf_table_test(bool);
+bool		npf_state_test(bool);
 
 #endif

Added files:

Index: src/usr.sbin/npf/npftest/libnpftest/npf_state_test.c
diff -u /dev/null src/usr.sbin/npf/npftest/libnpftest/npf_state_test.c:1.1
--- /dev/null	Mon Jun  4 00:28:34 2012
+++ src/usr.sbin/npf/npftest/libnpftest/npf_state_test.c	Mon Jun  4 00:28:34 2012
@@ -0,0 +1,165 @@
+/*	$NetBSD: npf_state_test.c,v 1.1 2012/06/04 00:28:34 rmind Exp $	*/
+
+/*
+ * NPF state tracking test.
+ *
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/kmem.h>
+
+#include "npf_impl.h"
+#include "npf_test.h"
+
+typedef struct {
+	int		tcpfl;		/* TCP flags. */
+	int		tlen;		/* TCP data length. */
+	uint32_t	seq;		/* SEQ number. */
+	uint32_t	ack;		/* ACK number. */
+	uint32_t	win;		/* TCP Window. */
+	int		flags;		/* Direction et al. */
+} tcp_meta_t;
+
+#define	S	TH_SYN
+#define	A	TH_ACK
+#define	F	TH_FIN
+#define	OUT	0x1
+#define	IN	0x2
+#define	ERR	0x4
+#define	CLEAR	.flags = 0
+
+static const tcp_meta_t packet_sequence[] = {
+	/*
+	 *	TCP data	SEQ	ACK		WIN
+	 */
+
+	/* Out of order ACK. */
+	{ S,	0,		9999,	0,		4096,	OUT	},
+	{ S|A,	0,		9,	10000,		2048,	IN	},
+	{ A,	0,		10000,	10,		4096,	OUT	},
+	/* --- */
+	{ A,	0,		10,	10000,		2048,	IN	},
+	{ A,	1000,		10000,	10,		4096,	OUT	},
+	{ A,	1000,		11000,	10,		4096,	OUT	},
+	{ A,	0,		10,	12000,		2048,	IN	},
+	{ A,	0,		10,	13000,		2048,	IN	},
+	{ A,	1000,		12000,	10,		4096,	OUT	},
+	{ A,	0,		10,	11000,		1048,	IN	},
+	/* --- */
+	{ A,	1000,		14000,	10,		4096,	OUT	},
+	{ A,	0,		10,	13000,		2048,	IN	},
+	{ CLEAR },
+
+	/* Retransmission after out of order ACK and missing ACK. */
+	{ S,	0,		9999,	0,		1000,	OUT	},
+	{ S|A,	0,		9,	10000,		4000,	IN	},
+	{ A,	0,		10000,	10,		1000,	OUT	},
+	/* --- */
+	{ A,	1000,		10000,	10,		1000,	OUT	},
+	{ A,	0,		10,	11000,		4000,	IN	},
+	{ A,	1000,		11000,	10,		1000,	OUT	},
+	{ A,	1000,		12000,	10,		1000,	OUT	},
+	{ A,	1000,		13000,	10,		1000,	OUT	},
+	{ A,	1000,		14000,	10,		1000,	OUT	},
+	/* --- Assume the first was delayed; second was lost after us. */
+	{ A,	0,		10,	15000,		4000,	IN	},
+	{ A,	0,		10,	15000,		2000,	IN	},
+	/* --- */
+	{ A,	1000,		12000,	10,		1000,	OUT	},
+	{ CLEAR },
+
+	/* Out of window. */
+	{ S,	0,		9,	0,		8760,	OUT	},
+	{ S|A,	0,		9999,	10,		1000,	IN	},
+	{ A,	0,		10,	10000,		8760,	OUT	},
+	/* --- */
+	{ A,	1460,		10000,	10,		1000,	IN	},
+	{ A,	1460,		11460,	10,		1000,	IN	},
+	{ A,	0,		10,	12920,		8760,	OUT	},
+	{ A,	1460,		12920,	10,		1000,	IN	},
+	{ A,	0,		10,	14380,		8760,	OUT	},
+	{ A,	1460,		17300,	10,		1000,	IN	},
+	{ A,	0,		10,	14380,		8760,	OUT	},
+	{ A,	1460,		18760,	10,		1000,	IN	},
+	{ A,	0,		10,	14380,		8760,	OUT	},
+	{ A,	1460,		20220,	10,		1000,	IN	},
+	{ A,	0,		10,	14380,		8760,	OUT	},
+	{ A,	1460,		21680,	10,		1000,	IN	},
+	{ A,	0,		10,	14380,		8760,	OUT	},
+	/* --- */
+	{ A,	1460,		14380,	10,		1000,	IN	},
+	{ A,	1460,		23140,	10,		1000,	IN|ERR	},
+	{ CLEAR },
+
+};
+
+#undef S
+#undef A
+#undef F
+
+static struct mbuf *
+construct_packet(const tcp_meta_t *p)
+{
+	struct mbuf *m = mbuf_construct(IPPROTO_TCP);
+	struct ip *ip;
+	struct tcphdr *th;
+
+	th = mbuf_return_hdrs(m, false, &ip);
+
+	/* Imitate TCP payload, set TCP sequence numbers, flags and window. */
+	ip->ip_len = htons(sizeof(struct ip) + sizeof(struct tcphdr) + p->tlen);
+	th->th_seq = htonl(p->seq);
+	th->th_ack = htonl(p->ack);
+	th->th_flags = p->tcpfl;
+	th->th_win = htons(p->win);
+	return m;
+}
+
+static bool
+process_packet(const int i, npf_state_t *nst, bool *snew)
+{
+	const tcp_meta_t *p = &packet_sequence[i];
+	npf_cache_t npc = { .npc_info = 0 };
+	nbuf_t *nbuf;
+	int ret;
+
+	if (p->flags == 0) {
+		npf_state_destroy(nst);
+		*snew = true;
+		return true;
+	}
+
+	nbuf = (nbuf_t *)construct_packet(p);
+	ret = npf_cache_all(&npc, nbuf);
+	KASSERT((ret & NPC_IPFRAG) == 0);
+
+	if (*snew) {
+		ret = npf_state_init(&npc, nbuf, nst);
+		KASSERT(ret == true);
+		*snew = false;
+	}
+	ret = npf_state_inspect(&npc, nbuf, nst, p->flags == OUT);
+	m_freem(nbuf);
+
+	return ret ? true : (p->flags & ERR) != 0;
+}
+
+bool
+npf_state_test(bool verbose)
+{
+	npf_state_t nst;
+	bool snew = true;
+
+	for (u_int i = 0; i < __arraycount(packet_sequence); i++) {
+		if (process_packet(i, &nst, &snew)) {
+			continue;
+		}
+		if (verbose) {
+			printf("Failed on packet %d, state dump:\n", i);
+			npf_state_dump(&nst);
+		}
+		return false;
+	}
+	return true;
+}

Reply via email to