Plugin flow timeout

plugin development

Introduction

This tutorial introduces the flexible timeout programming of T2. As outlined in the Flow mode tutorial, the flow timeouts can be altered in a diverse way changing constants in tranalyzer.h preferably via t2conf. Sometimes it is preferable to change the timeout depending on a state of a protocol, like in, e.g., tcpStates, which follows the TCP state machine of the sender and receiver. Nevertheless, you can change timeouts of flows for any reason you like.

To facilitate the understanding of the subject we will implement a rudimentary version of tcpStates.

Getting started

Create folders for your data and results

If you have not created a separate data and results directory yet, please do it now. This will greatly facilitate your workflow:

mkdir ~/data ~/results

Reset tranalyzer2 and the plugins configuration

If you have followed the other tutorials, you may have modified some of the core and plugins configuration. To ensure your results match those in this tutorial, make sure to reset everything:

t2conf -a --reset

You can also clean all build files:

t2build -a -c

Empty the plugin folder

To ensure we are not left with some unneeded plugins or plugins which were built using different core configuration, it is safer to empty the plugins folder:

t2build -e -y

Are you sure you want to empty the plugin folder '/home/user/.tranalyzer/plugins' (y/N)? yes
Plugin folder emptied

Download the PCAP file

The PCAP file used in this tutorial can be downloaded here:

Please save it in your ~/data folder:

wget --no-check-certificate -P ~/data https://tranalyzer.com/download/data/faf-exercise.pcap

Build tranalyzer2 and the required plugins

For this tutorial, we will need to build the core (tranalyzer2) and the following plugins:

As you may have modified some of the automatically generated files, it is safer to use the -r and -f options.

t2build -r -f tranalyzer2 basicFlow basicStats txtSink

...

BUILDING SUCCESSFUL

Source code

In this tutorial, we will extend tcpWin13.tar.gz, the final version of the previous tutorial (Plugin PCAP extraction).

If you are impatient, you can download the final version of the tcpWin plugin we will develop in this tutorial.

To use one of those plugins, just unpack it in the plugins folder of your T2 installation.

tranpl

tar -xf ~/Downloads/tcpWin13.tar.gz

And let t2_aliases know about it:

source "$T2HOME/scripts/t2_aliases"

Adding timeout handlers in packet interrupt

In this tutorial. we build on the original window size counter, used in the previous plugin coding tutorials. I will talk you through all important elements.

First you need to implement a state machine following the protocol TCP. Sure, you could just use the flags from the TCP header which are copied into the variable tcpFlags below and program the state machine depending on that information. But then you need to add tcpFlags as a dependent plugin, and that add unnecessary complexity.

To make it simpler we define internal rudimentary states stored in tcpWinFlowP->state which is an extract of the actual flags. Have a look at the state machine in the L4 packet interrupt below.

At the beginning of a new flow we are in state TCPWIN_STATE_NEW. If we do not see a SYN flag (TH_SYN) we will directly move to the established TCPWIN_STATE_EST state with a timeout TCPWIN_TMT_EST. TH_SYN is defined in the core in tranalyzer2/src/proto/tcp.h. Otherwise, a TCPWIN_STATE_BGN state is entered with a different flow timeout. If a flow is terminated via FIN or RST we move to state TCPWIN_STATE_ABRT but leave the timeout at TCPWIN_TMT_EST to capture packets coming after the RST.

So this is all about handling timeouts with TCP. Now we want to terminate a flow if he exceeds a certain count of window size below threshold counts.

So if the windows zero count hits TCPWIN_THRES in the TCPWIN_STATE_EST state the flow timeout is greatly reduced in the flow and its reverse flow, hence leading to a new flow for the next packet.

If you do not change the timeout of the reverse flow, it could be that the flow does not get removed, because always both flows have to meet the timeout criteria.

To allow better understanding of the core’s operation, I also added some packet mode output for certain variables.

So open tcpWin.c and start coding!

tcpWin

vi src/tcpWin.c

...

/*
 * Static variables are only visible in this file
 */

// window size counts
static gwz_t  gwz;                      // global window size structure

#if ALARM_MODE == 1
static uint32_t winAlarms;              // Number of alarms
static uint32_t winThFlows;             // Number of flows which created an alarm
#endif // ALARM_MODE == 1

static uint32_t winThCntG, winThCntG0;  // Aggregated win threshold count and variable for the last threshold count
static uint8_t  tcpWinStat;             // Aggregated status
static uint8_t  tcpWinState;            // <--- Aggregated state.

...

/*
 * Macros
 */

#define TCPWIN_SPKTMD_PRI_NONE() \
    if (sPktFile) { \
        fputs("0x%00" /* tcpWinStat     */ SEP_CHR \  /* <-- */
              "0x%00" /* tcpWinState    */ SEP_CHR \  /* <-- */
                      /* tcpWinSize     */ SEP_CHR \  /* <-- */
                      /* tcpWinThPktCnt */ SEP_CHR \  /* <-- */
                      /* tcpWinTimeout  */ SEP_CHR \  /* <-- */
              , sPktFile); \
    }

...
void t2Init() {
    // allocate struct for all flows and initialize to 0
    T2_PLUGIN_STRUCT_NEW(tcpWinFlows);

    // Packet mode
    if (sPktFile) {
        // Note the trailing separators (SEP_CHR)  // <--
        fputs("tcpWinStat"     SEP_CHR             // <--
              "tcpWinState"    SEP_CHR             // <--
              "tcpWinSize"     SEP_CHR             // <--
              "tcpWinThPktCnt" SEP_CHR             // <--
              "tcpWinTimeout"  SEP_CHR             // <--
              , sPktFile);
    }

    // Global pointer for plugin dependencies
    gwzP = &gwz;
}

...
void t2OnLayer4(packet_t *packet, unsigned long flowIndex) {
    flow_t *flowP = &flows[flowIndex];          // <-- Removed const keyword

    if (flowP->l4Proto != L3_TCP) {             // process only TCP
        TCPWIN_SPKTMD_PRI_NONE();               // Packet mode
        return;                                 // go back to core
    }

    // only 1. frag packet will be processed
    if (!t2_is_first_fragment(packet)) {
        TCPWIN_SPKTMD_PRI_NONE();               // Packet mode
        return;                                 // go back to core
    }

    // get the reverse flow if it exists                             // <--
    flow_t *revFlowP = NULL;                                         // <--
    tcpWinFlow_t *revTcpWinFlowP = NULL;                             // <--
                                                                     // <--
    if (FLOW_HAS_OPPOSITE(flowP)) {                                  // <--
        const unsigned long oppFlowIndex = flowP->oppositeFlowIndex; // <--
        revFlowP = &flows[oppFlowIndex];                             // <--
        revTcpWinFlowP = &tcpWinFlows[oppFlowIndex];                 // <--
    }                                                                // <--

    tcpWinFlow_t * const tcpWinFlowP = &tcpWinFlows[flowIndex];
    const tcpHeader_t * const tcpHeader = TCP_HEADER(packet);
    const uint32_t tcpWin = ntohs(tcpHeader->window);

    if (tcpWin < TCPWIN_THRES) {              // is the window size below the threshold?
        tcpWinFlowP->winThCnt++;              // count the packet / flow
        winThCntG++;                          // increment global packet counter
        T2_SET_STATUS(flowP, FL_ALARM);       // Set the alarm bit in flow and global
                                              // <-- Aggregation of tcpWinStat moved below
#if FORCE_MODE == 1
        if (tcpWinFlowP->winThCnt > 1) T2_RM_FLOW(flowP);
#endif // FORCE_MODE == 1
    }

    // <-- Replace the remainder of the t2OnLayer4() callback with the code below

    const uint8_t tcpFlags = tcpHeader->flags; // copy all TCP flags
    tcpWinFlowP->stat |= (tcpFlags & 0x1f);    // extract only the main TCP flags (FIN, SYN, RST, PSH and ACK)

    switch (tcpWinFlowP->state) { // internal simplified TCP connection state machine
        case TCPWIN_STATE_NEW: // new flow
            if (tcpFlags & TH_SYN) {
                flowP->timeout = TCPWIN_TMT_BGN;
                tcpWinFlowP->state = TCPWIN_STATE_BGN;
                break;
            }

            if (!(tcpFlags & TH_ACK)) {
                break;
            }

            tcpWinFlowP->state = TCPWIN_STATE_EST;
            /*FALLTHRU*/
        case TCPWIN_STATE_BGN: // begin state after 1. packet
            flowP->timeout = TCPWIN_TMT_EST;
            /*FALLTHRU*/
        case TCPWIN_STATE_EST: // or established connection
            if (tcpWinFlowP->stat & (TH_FIN | TH_RST)) {
                tcpWinFlowP->state = TCPWIN_STATE_ABRT;
                flowP->timeout = TCPWIN_TMT_EST;
                break;
            }

            if (tcpWinFlowP->winThCnt < TCPWIN_FLWPRG) {  // is wincount above threshold?
                break;
            }

            // if win count threshold met, set abort conditions for flow and reverse flow
            tcpWinFlowP->stat |= TCPWIN_STAT_ABNRM; // set abort state
            tcpWinFlowP->state = TCPWIN_STATE_ABRT; // set abort status flag
            flowP->timeout = TCPWIN_TMT_ABRT;       // set abort timeout

            // do the same for the reverse flow if it exists
            if (revFlowP) {
                revTcpWinFlowP->state = TCPWIN_STATE_ABRT;
                revFlowP->timeout = TCPWIN_TMT_ABRT;
            }
            /*FALLTHRU*/
        case TCPWIN_STATE_ABRT: // abort either FIN or RST
            flowP->timeout = TCPWIN_TMT_ABRT;
            break;

        default: // anything else do nothing
            break;
    }

    tcpWinFlowP->stat |= TCPWIN_STAT_THU; // set the status bit
    tcpWinStat  |= tcpWinFlowP->stat;     // Aggregate all status
    tcpWinState |= tcpWinFlowP->state;    // Aggregate all states

    // Packet mode
    if (sPktFile) {
        fprintf(sPktFile,
                "0x%02" B2T_PRIX8 /* tcpWinStat     */ SEP_CHR
                "0x%02" B2T_PRIX8 /* tcpWinState    */ SEP_CHR
                "%"     PRIu32    /* tcpWinSize     */ SEP_CHR
                "%"     PRIu32    /* tcpWinThPktCnt */ SEP_CHR
                "%f"              /* tcpWinTimeout  */ SEP_CHR
                , tcpWinFlowP->stat
                , tcpWinFlowP->state
                , tcpWin
                , tcpWinFlowP->winThCnt
                , flowP->timeout);
    }
}

...

Note the assignment of the reverse flowP, revTcpWinFlowP. Always use the FLOW_HAS_OPPOSITE(flowP) macro and assign only values to a reverse flow if it actually exists.

Defining flags, states and timeouts

If the window size hits zero for two times the timeout is set to TCPWIN_TMT_ABRT = 1ms, which mostly timeouts flows in our pcap. The other states have timeouts above 1s, which might affect one flow, as we already know from earlier experiments in the Flow Mode tutorial that the traffic is bursty with interruptions for 3 seconds. Open tcpWin.h in an editor now.

vi src/tcpWin.h

...
/* ========================================================================== */
/* ------------------------ USER CONFIGURATION FLAGS ------------------------ */
/* ========================================================================== */

#define TCPWIN_THRES      1 // TCP window size threshold undershoot flag
#define TCPWIN_FLWPRG     2 // <-- Threshold to abort a flow
#define TCPWIN_MINPKTS   50 // Summary file: minimal TCP packets seen to start saving process
#define TCPWIN_MAXWSCNT 100 // Summary file: maximal number of window size threshold count array elements

/* ========================================================================== */
/* ------------------------- DO NOT EDIT BELOW HERE ------------------------- */
/* ========================================================================== */


// plugin defines

// tcpWinStat status variable
// 0x01: FIN                   // <--
// 0x02: SYN                   // <--
// 0x04: RST                   // <--
// 0x08: PSH                   // <--
// 0x10: ACK                   // <--
#define TCPWIN_STAT_THU   0x40 // <-- TCP window size threshold undershoot
#define TCPWIN_STAT_ABNRM 0x80 // <--

// tcpWinState
#define TCPWIN_STATE_NEW  0x00 // <--
#define TCPWIN_STATE_BGN  0x01 // <--
#define TCPWIN_STATE_EST  0x02 // <--
#define TCPWIN_STATE_ABRT 0x04 // <--

// timeouts @ states
#define TCPWIN_TMT_NEW  10.0f   // <-- 10 s
#define TCPWIN_TMT_BGN   2.2f   // <-- 2.2 s
#define TCPWIN_TMT_EST   1.0f   // <-- 1.0 s
#define TCPWIN_TMT_ABRT  0.001f // <-- 1 ms


// Structure

typedef struct {
    ipAddr_t wzip  [TCPWIN_MAXWSCNT]; // IP address array
#if SUBNET_ON != 0 && (AGGREGATIONFLAG & SUBNET) == 0
    uint32_t sID   [TCPWIN_MAXWSCNT]; // subnetID
#endif // SUBNET_ON != 0 && (AGGREGATIONFLAG & SUBNET) == 0
    uint32_t tcpCnt[TCPWIN_MAXWSCNT]; // TCP packet count
    float    wzCnt [TCPWIN_MAXWSCNT]; // window size count
    int      wzi;                     // window size index
} gwz_t;


// Plugin structure

typedef struct { // always large variables first to limit memory fragmentation
    uint32_t tcpWinInit; // initial window size
    uint32_t winThCnt;   // win undershoot count
    uint8_t  ttl;        // TTL
    uint8_t  stat;       // plugin flow status
    uint8_t  state;      // <-- plugin flow state
} tcpWinFlow_t;


// plugin struct pointer for potential dependencies
extern tcpWinFlow_t *tcpWinFlows;
extern gwz_t *gwzP;

#endif // T2_TCPWIN_H_INCLUDED

Register timeouts with the core

At startup your timeouts have to be registered with the core, so that every flow is tested at each packet being received from an interface or the pcap. I also added some output for the packet mode that you can watch the timeouts controlling the flows. The code is shown below:

vi src/tcpWin.c

...
void t2Init() {
    // allocate struct for all flows and initialize to 0
    T2_PLUGIN_STRUCT_NEW(tcpWinFlows);

    // register timeouts                   // <--
    timeout_handler_add(TCPWIN_TMT_NEW);   // <--
    timeout_handler_add(TCPWIN_TMT_BGN);   // <--
    timeout_handler_add(TCPWIN_TMT_EST);   // <--
    timeout_handler_add(TCPWIN_TMT_ABRT);  // <--

    // Packet mode
    if (sPktFile) {
        fputs("tcpWinStat"     SEP_CHR // Note the trailing separators (SEP_CHR)
              "tcpWinState"    SEP_CHR
              "tcpWinSize"     SEP_CHR
              "tcpWinThPktCnt" SEP_CHR
              "tcpWinTimeout"  SEP_CHR
              , sPktFile);
    }

    // Global pointer for plugin dependencies
    gwzP = &gwz;
}

...

So that is it, define timeouts, add timeout handlers, program your state machine and set flow timeouts appropriately. The rest is flow and packet mode output.

Adding flow output and plugin report

Now I’m adding some global variables allowing us to assess the pcap from the end report and the flow file.

vi src/tcpWin.c

binary_value_t* t2PrintHeader() {
    binary_value_t *bv = NULL;

    BV_APPEND_H8(bv, "tcpWinStat", "TCP window size threshold status");
    BV_APPEND_H8(bv, "tcpWinState", "TCP window size state");            // <--
    BV_APPEND_U8(bv, "tcpWinIpTTL" , "IP TTL");
    BV_APPEND_U32(bv, "tcpInitWinSz", "TCP initial effective window size");
    BV_APPEND_U32(bv, "tcpWinThCnt", "TCP window size threshold count");
    BV_APPEND_FLT(bv, "tcpWinSzThRt", "TCP packet count ratio below window size WINMIN threshold");

    return bv;
}

...
void t2OnFlowTerminate(unsigned long flowIndex, outputBuffer_t *buf) {
    const tcpWinFlow_t * const tcpWinFlowP = &tcpWinFlows[flowIndex];
    bSFlow_t * const bSFlowP = &bSFlow[flowIndex];

    float f = 0.0;
    if (bSFlowP->numTPkts) {
        f = (float)tcpWinFlowP->winThCnt/(float)bSFlowP->numTPkts;
    }

    OUTBUF_APPEND_U8(buf, tcpWinFlowP->stat);
    OUTBUF_APPEND_U8(buf, tcpWinFlowP->state); // <--
    OUTBUF_APPEND_U8(buf, tcpWinFlowP->ttl);

    ...
}
...

Finally a line for the internal aggregated state is added in the end report, see // <--.

// add a endreport
void t2PluginReport(FILE *stream) {
    if (winThCntG) {
        T2_FPLOG_AGGR_HEX(stream, plugin_name, tcpWinStat);
        T2_FPLOG_AGGR_HEX(stream, plugin_name, tcpWinState); // <--

        ...
    }
}

After you edited the skeleton code you should compare your implementation with tcpWin14.tar.gz. Now you are all set, compile tcpWin and invoke T2, also in packet mode.

t2build tcpWin

t2 -r ~/data/faf-exercise.pcap -w ~/results -s

================================================================================
Tranalyzer 0.9.0 (Anteater), Cobra. PID: 98035, SID: 666
================================================================================
[INF] Creating flows for L2, IPv4, IPv6
Active plugins:
    01: basicFlow, 0.9.0
    02: basicStats, 0.9.0
    03: tcpWin, 0.9.0
    04: txtSink, 0.9.0
[INF] IPv4 Ver: 5, Rev: 09082023, Range Mode: 0, subnet ranges loaded: 481663 (481.66 K)
[INF] IPv6 Ver: 5, Rev: 09082023, Range Mode: 0, subnet ranges loaded: 41533 (41.53 K)
Processing file: /home/wurst/data/faf-exercise.pcap
Link layer type: Ethernet [EN10MB/1]
Snapshot length: 65535
Dump start: 1258544215.37210000 sec (Wed 18 Nov 2009 11:36:55 UTC)
Dump stop : 1258594491.683288000 sec (Thu 19 Nov 2009 01:34:51 UTC)
Total dump duration: 50276.646078000 sec (13h 57m 56s)
Finished processing. Elapsed time: 0.007994000 sec
Finished unloading flow memory. Time: 0.008013000 sec
Percentage completed: 100.00%
Number of processed packets: 5902 (5.90 K)
Number of processed bytes: 4993414 (4.99 M)
Number of raw bytes: 4993414 (4.99 M)
Number of pcap bytes: 5087870 (5.09 M)
Number of IPv4 packets: 5902 (5.90 K) [100.00%]
Number of A packets: 3534 (3.53 K) [59.88%]
Number of B packets: 2368 (2.37 K) [40.12%]
Number of A bytes: 4423242 (4.42 M) [88.58%]
Number of B bytes: 570172 (570.17 K) [11.42%]
Average A packet load: 1251.62 (1.25 K)
Average B packet load: 240.78
--------------------------------------------------------------------------------
basicStats: Biggest L3 flow talker: 143.166.11.10 (US): 3012 (3.01 K) [51.03%] packets
basicStats: Biggest L3 flow talker: 143.166.11.10 (US): 4148797 (4.15 M) [83.09%] bytes
tcpWin: Aggregated tcpWinStat=0xdf
tcpWin: Aggregated tcpWinState=0x07
tcpWin: Number of TCP winsize packets below threshold 1: 4 [0.07%]
tcpWin: IP: 192.168.1.105, country: 07, org: Private network
--------------------------------------------------------------------------------
Headers count: min: 3, max: 3, average: 3.00
Number of TCP packets: 5902 (5.90 K) [100.00%]
Number of TCP bytes: 4993414 (4.99 M) [100.00%]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Number of processed      flows: 94
Number of processed IPv4 flows: 94 [100.00%]
Number of processed A    flows: 48 [51.06%]
Number of processed B    flows: 46 [48.94%]
Number of request        flows: 47 [50.00%]
Number of reply          flows: 47 [50.00%]
Total   A/B    flow asymmetry: 0.02
Total req/rply flow asymmetry: 0.00
Number of processed   packets/flows: 62.79
Number of processed A packets/flows: 73.62
Number of processed B packets/flows: 51.48
Number of processed total packets/s: 0.12
Number of processed A+B   packets/s: 0.12
Number of processed A     packets/s: 0.07
Number of processed   B   packets/s: 0.05
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Number of average processed flows/s: 0.00
Average full raw bandwidth: 795 b/s
Average full bandwidth : 792 b/s
Max number of flows in memory: 12 [0.00%]
Memory usage: 0.01 GB [0.12%]
Aggregated flowStat=0x0402000000004000
[WRN] 1 alarms in 1 flows [1.06%]
[INF] IPv4 flows
[INF] IPAlarm

94 flows, normally the pcap produces 73 flows, so we see some effect of our dynamic timeout changes.

We have 4 events of window size hitting 0, and tcpWinStat set to that effect: TCPWIN_ABNRM & TCPWIN_THU both set, so count hit the threshold 2. Flow 44 was aborted with timeout value 1ms. flow 45 was terminated because he passed the timeout=1.0s. And flow 47 contains the rest. The flow listing below shows you the split of the original flow into three sub flows:

tawk 'port(49330)' ~/results/faf-exercise_flows.txt | tcol

%dir  flowInd  flowStat            timeFirst          timeLast           duration   numHdrDesc  numHdrs  hdrDesc       srcMac             dstMac             ethType  ethVlanID  srcIP          srcIPCC  srcIPOrg           srcPort  dstIP          dstIPCC  dstIPOrg           dstPort  l4Proto  tcpWinStat  tcpWinState  tcpWinThCnt
A     44       0x0400000000004000  1258594163.408285  1258594164.647755  1.239470   1           3        eth:ipv4:tcp  00:08:74:38:01:b4  00:19:e3:e7:5d:23  0x0800              192.168.1.105  07       "Private network"  49330    143.166.11.10  us       "Dell"             64334    6        0xd2        0x04         2
B     44       0x0400000000004001  1258594163.487027  1258594164.647545  1.160518   1           3        eth:ipv4:tcp  00:19:e3:e7:5d:23  00:08:74:38:01:b4  0x0800              143.166.11.10  us       "Dell"             64334    192.168.1.105  07       "Private network"  49330    6        0x1a        0x04         0
A     45       0x0400000000004000  1258594165.318635  1258594185.427506  20.108871  1           3        eth:ipv4:tcp  00:19:e3:e7:5d:23  00:08:74:38:01:b4  0x0800              143.166.11.10  us       "Dell"             64334    192.168.1.105  07       "Private network"  49330    6        0x19        0x04         0
B     45       0x0400000000004001  1258594165.319087  1258594185.427968  20.108881  1           3        eth:ipv4:tcp  00:08:74:38:01:b4  00:19:e3:e7:5d:23  0x0800              192.168.1.105  07       "Private network"  49330    143.166.11.10  us       "Dell"             64334    6        0x90        0x02         1
A     47       0x0400000000004000  1258594191.015208  1258594191.015208  0.000000   1           3        eth:ipv4:tcp  00:08:74:38:01:b4  00:19:e3:e7:5d:23  0x0800              192.168.1.105  07       "Private network"  49330    143.166.11.10  us       "Dell"             64334    6        0x94        0x04         1

Extract the packets from flow 44 around the win count hit 2. In packet 1422 the tcpWinThCnt reaches two, the timeout is set to 1ms and both A/B flows are removed. The next packet starts with findex 45 and detects another tcpWin zero event.

tawk 'packet("1418-1426")' ~/results/faf-exercise_packets.txt | tcol

%dir  flowInd  flowStat            timeFirst             timeLast              duration      numHdrDesc  numHdrs  hdrDesc       srcMac             dstMac             ethType  vlanID         srcIP  srcIPCC              srcIPOrg  srcPort        dstIP  dstIPCC              dstIPOrg  dstPort  l4Proto  numPktsSnt  numPktsRcvd  numBytesSnt  numBytesRcvd  minPktSz  maxPktSz  avePktSize  stdPktSize  minIAT    maxIAT       aveIAT      stdIAT    pktps     bytps       pktAsm  bytAsm  tcpWinStat  tcpWinIpTTL  tcpInitWinSz  tcpWinThCnt   tcpWinSzThRt
A     44       0x0402000000004000  1258594163.408285000  1258594164.647755000  1.239470000   1           3        eth:ipv4:tcp  00:08:74:38:01:b4  00:19:e3:e7:5d:23  0x0800   192.168.1.105  07     "Private network"    49330     143.166.11.10  us     "Dell Technologies"  64334     6        49       89          0            120061       0             0         0         0           0           0.363767  0.02529531   0.05806321  39.53303  0         -0.2898551  -1      0xd2    128         8192         2             0.04081633
B     44       0x0400000000004001  1258594163.487027000  1258594164.647545000  1.160518000   1           3        eth:ipv4:tcp  00:19:e3:e7:5d:23  00:08:74:38:01:b4  0x0800   143.166.11.10  us     "Dell Technologies"  64334     192.168.1.105  07     "Private network"    49330     6        89       49          120061       0            0             1380      1349      184.3238    0           0.363978  0.01303953   0.04444404  76.68989  103454.7  0.2898551   1       0x5a    111         8192         0             0
A     45       0x0400000000004000  1258594165.318635000  1258594185.427506000  20.108871000  1           3        eth:ipv4:tcp  00:19:e3:e7:5d:23  00:08:74:38:01:b4  0x0800   143.166.11.10  us     "Dell Technologies"  64334     192.168.1.105  07     "Private network"    49330     6        3012     1464        4148797      0            0             1380      1377.423  49.75706    0           0.607386  0.006676252  0.02300617  149.7846  206316.8  0.3458445   1       0x59    111         64860        0             0
B     45       0x0402000000004001  1258594165.319087000  1258594185.427968000  20.108881000  1           3        eth:ipv4:tcp  00:08:74:38:01:b4  00:19:e3:e7:5d:23  0x0800   192.168.1.105  07     "Private network"    49330     143.166.11.10  us     "Dell Technologies"  64334     6        1464     3012        0            4148797      0             0         0         0           0           0.529166  0.01373558   0.03084774  72.80365  0         -0.3458445  -1      0x50    128         0            1             0.0006830601
A     47       0x0402000000004000  1258594191.015208000  1258594191.015208000  0.000000000   1           3        eth:ipv4:tcp  00:08:74:38:01:b4  00:19:e3:e7:5d:23  0x0800   192.168.1.105  07     "Private network"    49330     143.166.11.10  us     "Dell Technologies"  64334     6        1        0           0            0            0             0         0         0           0           0         0            0           0         0         1           0       0x54    128         0            1             1

Flow 10 with default timeout, see: flow mode tutorial got split into four flows 10, 11, 13 and 16 because the EST state timeout=1.0s was exceeded.

tawk 'port(1379)' ~/results/faf-exercise_flows.txt | tcol

%dir  flowInd  flowStat            timeFirst             timeLast              duration     numHdrDesc  numHdrs  hdrDesc       srcMac             dstMac             ethType  vlanID         srcIP  srcIPCC            srcIPOrg  srcPort        dstIP  dstIPCC            dstIPOrg  dstPort  l4Proto  numPktsSnt  numPktsRcvd  numBytesSnt  numBytesRcvd  minPktSz  maxPktSz  avePktSize  stdPktSize  minIAT    maxIAT       aveIAT       stdIAT    pktps     bytps       pktAsm        bytAsm  tcpWinStat  tcpWinIpTTL  tcpInitWinSz  tcpWinThCnt  tcpWinSzThRt
A     10       0x0400000000004000  1258562467.749142000  1258562467.900050000  0.150908000  1           3        eth:ipv4:tcp  00:0b:db:4f:6b:10  00:19:e3:e7:5d:23  0x0800   192.168.1.104  07     "Private network"  1379      63.245.221.11  us     "Mozilla"          80        6        4        3           449          444          0             449       112.25    159.8441    0           0.144417  0.037727     0.05336915   26.50622  2975.323  0.1428571   0.005599104   0x5a    128         65535        0             0
B     10       0x0400000000004001  1258562467.754689000  1258562467.761692000  0.007003000  1           3        eth:ipv4:tcp  00:19:e3:e7:5d:23  00:0b:db:4f:6b:10  0x0800   63.245.221.11  us     "Mozilla"          80        192.168.1.104  07     "Private network"  1379      6        3        4           444          449          0             444       148       170.8957    0           0.006751  0.002334333  0.002289841  428.3878  63401.4   -0.1428571  -0.005599104  0x5a    52          5840         0             0
A     11       0x0400000000004000  1258562477.713894000  1258562478.454425000  0.740531000  1           3        eth:ipv4:tcp  00:0b:db:4f:6b:10  00:19:e3:e7:5d:23  0x0800   192.168.1.104  07     "Private network"  1379      63.245.221.11  us     "Mozilla"          80        6        8        13          1352         15162        0             455       169       185.5386    0           0.380024  0.09256638   0.09487616   10.80306  1825.717  -0.2380952  -0.8362601    0x58    128         65091        0             0
B     11       0x0400000000004001  1258562477.772691000  1258562478.454017000  0.681326000  1           3        eth:ipv4:tcp  00:19:e3:e7:5d:23  00:0b:db:4f:6b:10  0x0800   63.245.221.11  us     "Mozilla"          80        192.168.1.104  07     "Private network"  1379      6        13       8           15162        1352         10            1380      1166.308  353.6241    0           0.426916  0.05240969   0.09705759   19.08044  22253.67  0.2380952   0.8362601     0x58    52          7504         0             0
A     13       0x0400000000004000  1258562501.432514000  1258562501.432514000  0.000000000  1           3        eth:ipv4:tcp  00:0b:db:4f:6b:10  00:19:e3:e7:5d:23  0x0800   192.168.1.104  07     "Private network"  1379      63.245.221.11  us     "Mozilla"          80        6        1        1           0            0            0             0         0         0           0           0         0            0            0         0         0           0             0x50    128         65535        0             0
B     13       0x0400000000004001  1258562501.432305000  1258562501.432305000  0.000000000  1           3        eth:ipv4:tcp  00:19:e3:e7:5d:23  00:0b:db:4f:6b:10  0x0800   63.245.221.11  us     "Mozilla"          80        192.168.1.104  07     "Private network"  1379      6        1        1           0            0            0             0         0         0           0           0         0            0            0         0         0           0             0x51    52          9648         0             0
A     16       0x0400000000004000  1258562509.633370000  1258562509.633370000  0.000000000  1           3        eth:ipv4:tcp  00:0b:db:4f:6b:10  00:19:e3:e7:5d:23  0x0800   192.168.1.104  07     "Private network"  1379      63.245.221.11  us     "Mozilla"          80        6        1        1           0            0            0             0         0         0           0           0         0            0            0         0         0           0             0x51    128         65535        0             0
B     16       0x0400000000004001  1258562509.653962000  1258562509.653962000  0.000000000  1           3        eth:ipv4:tcp  00:19:e3:e7:5d:23  00:0b:db:4f:6b:10  0x0800   63.245.221.11  us     "Mozilla"          80        192.168.1.104  07     "Private network"  1379      6        1        1           0            0            0             0         0         0           0           0         0            0            0         0         0           0             0x50    52          9648         0             0

As an exercise, change the TCPWIN_TMT_EST to 4.0, what do you expect? Then change the TCPWIN_FLWPRG to 3. What do you expect?

Conclusion

You can download the final version of the tcpWin plugin.

The next tutorial will teach you how to implement a sink plugin.

Have fun experimenting!

See also