Module Name:    src
Committed By:   rmind
Date:           Mon Dec  5 00:34:25 UTC 2011

Modified Files:
        src/sys/net/npf: npf_state_tcp.c

Log Message:
- Add npf_tcpfl2case() and make TCP state table more compact.
- Adjust the state for FIN case on sim-SYN and SYN-RECEIVED.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/net/npf/npf_state_tcp.c

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

Modified files:

Index: src/sys/net/npf/npf_state_tcp.c
diff -u src/sys/net/npf/npf_state_tcp.c:1.1 src/sys/net/npf/npf_state_tcp.c:1.2
--- src/sys/net/npf/npf_state_tcp.c:1.1	Tue Nov 29 20:05:30 2011
+++ src/sys/net/npf/npf_state_tcp.c	Mon Dec  5 00:34:25 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_state_tcp.c,v 1.1 2011/11/29 20:05:30 rmind Exp $	*/
+/*	$NetBSD: npf_state_tcp.c,v 1.2 2011/12/05 00:34:25 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2010-2011 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_state_tcp.c,v 1.1 2011/11/29 20:05:30 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_state_tcp.c,v 1.2 2011/12/05 00:34:25 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -79,7 +79,7 @@ void	npf_state_sample(npf_state_t *);
 /*
  * TCP connection timeout table (in seconds).
  */
-static const u_int npf_tcp_timeouts[] __read_mostly = {
+static u_int npf_tcp_timeouts[] __read_mostly = {
 	/* Closed, timeout nearly immediately. */
 	[NPF_TCPS_CLOSED]	= 10,
 	/* Unsynchronised states. */
@@ -99,71 +99,92 @@ static const u_int npf_tcp_timeouts[] __
 
 #define	NPF_TCP_MAXACKWIN	66000
 
-#define	TH_STATE_MASK		(TH_SYN | TH_ACK | TH_FIN)
-#define	TH_SYNACK		(TH_SYN | TH_ACK)
-#define	TH_FINACK		(TH_FIN | TH_ACK)
+/*
+ * List of TCP flag cases and conversion of flags to a case (index).
+ */
+
+#define	TCPFC_INVALID		0
+#define	TCPFC_SYN		1
+#define	TCPFC_SYNACK		2
+#define	TCPFC_ACK		3
+#define	TCPFC_FIN		4
+#define	TCPFC_COUNT		5
+
+static inline u_int
+npf_tcpfl2case(const int tcpfl)
+{
+	u_int i, c;
+
+	/*
+	 * Magic value maps flag combinations to TCPFC case numbers.
+	 * Other cases are zero.  Note: FIN-ACK is mapped to FIN.
+	 */
+	i = (tcpfl & (TH_SYN | TH_FIN)) | ((tcpfl & TH_ACK) >> 2);
+	c = (0x2430140 >> (i << 2)) & 7;
+
+	KASSERT(c < TCPFC_COUNT);
+	return c;
+}
 
 /*
  * NPF transition table of a tracked TCP connection.
  *
  * There is a single state, which is changed in the following way:
  *
- * new_state = npf_tcp_fsm[old_state][direction][tcp_flags & TH_STATE_MASK];
+ * new_state = npf_tcp_fsm[old_state][direction][npf_tcpfl2case(tcp_flags)];
  *
  * Note that this state is different from the state in each end (host).
  */
 
-static const int npf_tcp_fsm[NPF_TCP_NSTATES][2][TH_STATE_MASK + 1]
-    __read_mostly = {
+static const int npf_tcp_fsm[NPF_TCP_NSTATES][2][TCPFC_COUNT] = {
 	[NPF_TCPS_CLOSED] = {
 		[NPF_FLOW_FORW] = {
 			/* Handshake (1): initial SYN. */
-			[TH_SYN]	= NPF_TCPS_SYN_SENT,
+			[TCPFC_SYN]	= NPF_TCPS_SYN_SENT,
 		},
 	},
 	[NPF_TCPS_SYN_SENT] = {
 		[NPF_FLOW_FORW] = {
 			/* SYN may be retransmitted. */
-			[TH_SYN]	= NPF_TCPS_OK,
+			[TCPFC_SYN]	= NPF_TCPS_OK,
 		},
 		[NPF_FLOW_BACK] = {
 			/* Handshake (2): SYN-ACK is expected. */
-			[TH_SYNACK]	= NPF_TCPS_SYN_RECEIVED,
+			[TCPFC_SYNACK]	= NPF_TCPS_SYN_RECEIVED,
 			/* Simultaneous initiation - SYN. */
-			[TH_SYN]	= NPF_TCPS_SIMSYN_SENT,
+			[TCPFC_SYN]	= NPF_TCPS_SIMSYN_SENT,
 		},
 	},
 	[NPF_TCPS_SIMSYN_SENT] = {
 		[NPF_FLOW_FORW] = {
 			/* Original SYN re-transmission. */
-			[TH_SYN]	= NPF_TCPS_OK,
+			[TCPFC_SYN]	= NPF_TCPS_OK,
 			/* SYN-ACK response to simultaneous SYN. */
-			[TH_SYNACK]	= NPF_TCPS_SYN_RECEIVED,
+			[TCPFC_SYNACK]	= NPF_TCPS_SYN_RECEIVED,
 		},
 		[NPF_FLOW_BACK] = {
 			/* Simultaneous SYN re-transmission.*/
-			[TH_SYN]	= NPF_TCPS_OK,
+			[TCPFC_SYN]	= NPF_TCPS_OK,
 			/* SYN-ACK response to original SYN. */
-			[TH_SYNACK]	= NPF_TCPS_SYN_RECEIVED,
-			/* FIN may be sent at this point. */
-			[TH_FIN]	= NPF_TCPS_FIN_SEEN,
-			[TH_FINACK]	= NPF_TCPS_FIN_SEEN,
+			[TCPFC_SYNACK]	= NPF_TCPS_SYN_RECEIVED,
+			/* FIN may be sent early. */
+			[TCPFC_FIN]	= NPF_TCPS_FIN_SEEN,
 		},
 	},
 	[NPF_TCPS_SYN_RECEIVED] = {
 		[NPF_FLOW_FORW] = {
 			/* Handshake (3): ACK is expected. */
-			[TH_ACK]	= NPF_TCPS_ESTABLISHED,
-			[TH_FIN]	= NPF_TCPS_CLOSING,
-			[TH_FINACK]	= NPF_TCPS_CLOSING,
+			[TCPFC_ACK]	= NPF_TCPS_ESTABLISHED,
+			/* FIN may be sent early. */
+			[TCPFC_FIN]	= NPF_TCPS_FIN_SEEN,
 		},
 		[NPF_FLOW_BACK] = {
 			/* SYN-ACK may be retransmitted. */
-			[TH_SYNACK]	= NPF_TCPS_OK,
+			[TCPFC_SYNACK]	= NPF_TCPS_OK,
 			/* XXX: ACK of late SYN in simultaneous case? */
-			[TH_ACK]	= NPF_TCPS_OK,
-			/* XXX: Can this happen?
-			[TH_FIN]	= NPF_TCPS_CLOSING, */
+			[TCPFC_ACK]	= NPF_TCPS_OK,
+			/* FIN may be sent early. */
+			[TCPFC_FIN]	= NPF_TCPS_FIN_SEEN,
 		},
 	},
 	[NPF_TCPS_ESTABLISHED] = {
@@ -172,16 +193,14 @@ static const int npf_tcp_fsm[NPF_TCP_NST
 		 * FIN packets may have ACK set.
 		 */
 		[NPF_FLOW_FORW] = {
-			[TH_ACK]	= NPF_TCPS_OK,
+			[TCPFC_ACK]	= NPF_TCPS_OK,
 			/* FIN by the sender. */
-			[TH_FIN]	= NPF_TCPS_FIN_SEEN,
-			[TH_FINACK]	= NPF_TCPS_FIN_SEEN,
+			[TCPFC_FIN]	= NPF_TCPS_FIN_SEEN,
 		},
 		[NPF_FLOW_BACK] = {
-			[TH_ACK]	= NPF_TCPS_OK,
+			[TCPFC_ACK]	= NPF_TCPS_OK,
 			/* FIN by the receiver. */
-			[TH_FIN]	= NPF_TCPS_FIN_SEEN,
-			[TH_FINACK]	= NPF_TCPS_FIN_SEEN,
+			[TCPFC_FIN]	= NPF_TCPS_FIN_SEEN,
 		},
 	},
 	[NPF_TCPS_FIN_SEEN] = {
@@ -192,64 +211,58 @@ static const int npf_tcp_fsm[NPF_TCP_NST
 		 * case we are closing immediately.
 		 */
 		[NPF_FLOW_FORW] = {
-			[TH_ACK]	= NPF_TCPS_CLOSE_WAIT,
-			[TH_FIN]	= NPF_TCPS_CLOSING,
-			[TH_FINACK]	= NPF_TCPS_CLOSING,
+			[TCPFC_ACK]	= NPF_TCPS_CLOSE_WAIT,
+			[TCPFC_FIN]	= NPF_TCPS_CLOSING,
 		},
 		[NPF_FLOW_BACK] = {
-			[TH_ACK]	= NPF_TCPS_FIN_WAIT,
-			[TH_FIN]	= NPF_TCPS_CLOSING,
-			[TH_FINACK]	= NPF_TCPS_CLOSING,
+			[TCPFC_ACK]	= NPF_TCPS_FIN_WAIT,
+			[TCPFC_FIN]	= NPF_TCPS_CLOSING,
 		},
 	},
 	[NPF_TCPS_CLOSE_WAIT] = {
 		/* Sender has sent the FIN and closed its end. */
 		[NPF_FLOW_FORW] = {
-			[TH_ACK]	= NPF_TCPS_OK,
-			[TH_FIN]	= NPF_TCPS_LAST_ACK,
-			[TH_FINACK]	= NPF_TCPS_LAST_ACK,
+			[TCPFC_ACK]	= NPF_TCPS_OK,
+			[TCPFC_FIN]	= NPF_TCPS_LAST_ACK,
 		},
 		[NPF_FLOW_BACK] = {
-			[TH_ACK]	= NPF_TCPS_OK,
-			[TH_FIN]	= NPF_TCPS_LAST_ACK,
-			[TH_FINACK]	= NPF_TCPS_LAST_ACK,
+			[TCPFC_ACK]	= NPF_TCPS_OK,
+			[TCPFC_FIN]	= NPF_TCPS_LAST_ACK,
 		},
 	},
 	[NPF_TCPS_FIN_WAIT] = {
 		/* Receiver has closed its end. */
 		[NPF_FLOW_FORW] = {
-			[TH_ACK]	= NPF_TCPS_OK,
-			[TH_FIN]	= NPF_TCPS_LAST_ACK,
-			[TH_FINACK]	= NPF_TCPS_LAST_ACK,
+			[TCPFC_ACK]	= NPF_TCPS_OK,
+			[TCPFC_FIN]	= NPF_TCPS_LAST_ACK,
 		},
 		[NPF_FLOW_BACK] = {
-			[TH_ACK]	= NPF_TCPS_OK,
-			[TH_FIN]	= NPF_TCPS_LAST_ACK,
-			[TH_FINACK]	= NPF_TCPS_LAST_ACK,
+			[TCPFC_ACK]	= NPF_TCPS_OK,
+			[TCPFC_FIN]	= NPF_TCPS_LAST_ACK,
 		},
 	},
 	[NPF_TCPS_CLOSING] = {
 		/* Race of FINs - expecting ACK. */
 		[NPF_FLOW_FORW] = {
-			[TH_ACK]	= NPF_TCPS_LAST_ACK,
+			[TCPFC_ACK]	= NPF_TCPS_LAST_ACK,
 		},
 		[NPF_FLOW_BACK] = {
-			[TH_ACK]	= NPF_TCPS_LAST_ACK,
+			[TCPFC_ACK]	= NPF_TCPS_LAST_ACK,
 		},
 	},
 	[NPF_TCPS_LAST_ACK] = {
 		/* FINs exchanged - expecting last ACK. */
 		[NPF_FLOW_FORW] = {
-			[TH_ACK]	= NPF_TCPS_TIME_WAIT,
+			[TCPFC_ACK]	= NPF_TCPS_TIME_WAIT,
 		},
 		[NPF_FLOW_BACK] = {
-			[TH_ACK]	= NPF_TCPS_TIME_WAIT,
+			[TCPFC_ACK]	= NPF_TCPS_TIME_WAIT,
 		},
 	},
 	[NPF_TCPS_TIME_WAIT] = {
 		/* May re-open the connection as per RFC 1122. */
 		[NPF_FLOW_FORW] = {
-			[TH_SYN]	= NPF_TCPS_SYN_SENT,
+			[TCPFC_SYN]	= NPF_TCPS_SYN_SENT,
 		},
 	},
 };
@@ -280,7 +293,7 @@ npf_tcp_inwindow(const npf_cache_t *npc,
 	 *
 	 * There four boundaries are defined as following:
 	 *	I)   SEQ + LEN	<= MAX { SND.ACK + MAX(SND.WIN, 1) }
-	 *	II)  SEQ	>= MAX { SND.SEQ + SND.LEN }
+	 *	II)  SEQ	>= MAX { SND.SEQ + SND.LEN - MAX(RCV.WIN, 1) }
 	 *	III) ACK	<= MAX { RCV.SEQ + RCV.LEN }
 	 *	IV)  ACK	>= MAX { RCV.SEQ + RCV.LEN } - MAXACKWIN
 	 *
@@ -427,7 +440,8 @@ npf_state_tcp(const npf_cache_t *npc, nb
 
 	/* Look for a transition to a new state. */
 	if (__predict_true((tcpfl & TH_RST) == 0)) {
-		nstate = npf_tcp_fsm[state][di][tcpfl & TH_STATE_MASK];
+		const int flagcase = npf_tcpfl2case(tcpfl);
+		nstate = npf_tcp_fsm[state][di][flagcase];
 	} else if (state == NPF_TCPS_TIME_WAIT) {
 		/* Prevent TIME-WAIT assassination (RFC 1337). */
 		nstate = NPF_TCPS_OK;

Reply via email to