Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/net/npf - Add npf_tcpfl2case() and make TCP state table ...



details:   https://anonhg.NetBSD.org/src/rev/be38087a1ac1
branches:  trunk
changeset: 771874:be38087a1ac1
user:      rmind <rmind%NetBSD.org@localhost>
date:      Mon Dec 05 00:34:25 2011 +0000

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

diffstat:

 sys/net/npf/npf_state_tcp.c |  130 ++++++++++++++++++++++++-------------------
 1 files changed, 72 insertions(+), 58 deletions(-)

diffs (266 lines):

diff -r d51e4e7dc6ad -r be38087a1ac1 sys/net/npf/npf_state_tcp.c
--- a/sys/net/npf/npf_state_tcp.c       Mon Dec 05 00:13:30 2011 +0000
+++ b/sys/net/npf/npf_state_tcp.c       Mon Dec 05 00:34:25 2011 +0000
@@ -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 @@
 /*
  * 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 @@
 
 #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 @@
                 * 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 @@
                 * 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 @@
         *
         * 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 @@
 
        /* 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;



Home | Main Index | Thread Index | Old Index