// Analysis computes the aggregate packet-level data for a TCPFlow.  This does
// not take into account packets that may have been dropped by the pcap trace
// and the analysis of such traces will be less accurate than those without any
// missing packets.
Analysis computes the aggregate packet-level data for a TCPFlow.  This does
not take into account packets that may have been dropped by the pcap trace
and the analysis of such traces will be less accurate than those without any
missing packets.
// Analysis computes the aggregate packet - level data for a TCPFlow . This does // not take into account packets that may have been dropped by the pcap trace // and the analysis of such traces will be less accurate than those without any // missing packets .
func TCPFlowAnalysis(d []*pkt.Packet, t *TCPTuple) (*TCPFlowStats, error) {
	var (
		ip           pkt.InetProtoHdr 
		tcp          *pkt.TcpHdr      
		ok           bool             
		pl           uint16           
		srcSeq       uint32           
		dstSeq       uint32           
		srcAck       uint32           
		dstAck       uint32           
		srcDupAckCnt int              
		dstDupAckCnt int              
	)
	fs := &TCPFlowStats{}           
	srcLoss := make(map[uint32]int) 
	dstLoss := make(map[uint32]int) 
	for i := range d {
		ip, ok = d[i].Headers[pkt.NetworkLayer].(pkt.InetProtoHdr)
		if !ok || ip == nil {
			return fs, ErrNetworkLayerHeader
		}
		tcp, ok = d[i].Headers[pkt.TransportLayer].(*pkt.TcpHdr)
		if !ok || tcp == nil {
			return fs, ErrTransportLayerHeader
		}
		pl = tcp.PayloadLen(ip.PL())
		if int(tcp.Source) == t.Src.Port {
			if tcp.AckSeq > srcAck {
				srcAck = tcp.AckSeq
				srcDupAckCnt = 0
			} else if tcp.AckSeq == srcAck {
				srcDupAckCnt++
				fs.SrcDupAck++
				if srcDupAckCnt == 3 && srcAck != dstSeq {
					dstLoss[srcAck] = i
				}
			}
			if tcp.Seq >= srcSeq {
				srcSeq = tcp.Seq + uint32(pl)
			} else {
				_, ok = srcLoss[tcp.Seq]
				if ok {
					fs.SrcLoss++
					fs.SrcLossBytes += uint32(pl)
					delete(srcLoss, tcp.Seq)
				} else {
					if dstDupAckCnt < 3 {
						fs.SrcOrder++
					} else {
						fs.SrcOther++
					}
				}
			}
		} else {
			if tcp.AckSeq > dstAck {
				dstAck = tcp.AckSeq
				dstDupAckCnt = 0
			} else if tcp.AckSeq == dstAck {
				dstDupAckCnt++
				fs.DstDupAck++
				if dstDupAckCnt == 3 && dstAck != srcSeq {
					srcLoss[dstAck] = i
				}
			}
			if tcp.Seq >= dstSeq {
				dstSeq = tcp.Seq + uint32(pl)
			} else {
				_, ok = dstLoss[tcp.Seq]
				if ok {
					fs.DstLoss++
					fs.DstLossBytes += uint32(pl)
					delete(dstLoss, tcp.Seq)
				} else {
					if srcDupAckCnt < 3 {
						fs.DstOrder++
					} else {
						fs.DstOther++
					}
				}
			}
		}
	}
	fs.DstOther += len(dstLoss)
	fs.SrcOther += len(srcLoss)
	return fs, nil
}
func TCPFlowAnalysis ( d [ ] * pkt . Packet , t * TCPTuple ) ( * TCPFlowStats , error ) { var ( ip pkt . InetProtoHdr tcp * pkt . TcpHdr ok bool pl uint16 srcSeq uint32 dstSeq uint32 srcAck uint32 dstAck uint32 srcDupAckCnt int dstDupAckCnt int ) fs := & TCPFlowStats { } srcLoss := make ( map [ uint32 ] int ) dstLoss := make ( map [ uint32 ] int ) for i := range d { ip , ok = d [ i ] . Headers [ pkt . NetworkLayer ] . ( pkt . InetProtoHdr ) if ! ok || ip == nil { return fs , ErrNetworkLayerHeader } tcp , ok = d [ i ] . Headers [ pkt . TransportLayer ] . ( * pkt . TcpHdr ) if ! ok || tcp == nil { return fs , ErrTransportLayerHeader } pl = tcp . PayloadLen ( ip . PL ( ) ) if int ( tcp . Source ) == t . Src . Port { if tcp . AckSeq > srcAck { srcAck = tcp . AckSeq srcDupAckCnt = 0 } else if tcp . AckSeq == srcAck { srcDupAckCnt ++ fs . SrcDupAck ++ if srcDupAckCnt == 3 && srcAck != dstSeq { dstLoss [ srcAck ] = i } } if tcp . Seq >= srcSeq { srcSeq = tcp . Seq + uint32 ( pl ) } else { _ , ok = srcLoss [ tcp . Seq ] if ok { fs . SrcLoss ++ fs . SrcLossBytes += uint32 ( pl ) delete ( srcLoss , tcp . Seq ) } else { if dstDupAckCnt < 3 { fs . SrcOrder ++ } else { fs . SrcOther ++ } } } } else { if tcp . AckSeq > dstAck { dstAck = tcp . AckSeq dstDupAckCnt = 0 } else if tcp . AckSeq == dstAck { dstDupAckCnt ++ fs . DstDupAck ++ if dstDupAckCnt == 3 && dstAck != srcSeq { srcLoss [ dstAck ] = i } } if tcp . Seq >= dstSeq { dstSeq = tcp . Seq + uint32 ( pl ) } else { _ , ok = dstLoss [ tcp . Seq ] if ok { fs . DstLoss ++ fs . DstLossBytes += uint32 ( pl ) delete ( dstLoss , tcp . Seq ) } else { if srcDupAckCnt < 3 { fs . DstOrder ++ } else { fs . DstOther ++ } } } } } fs . DstOther += len ( dstLoss ) fs . SrcOther += len ( srcLoss ) return fs , nil }
Analysis computes the aggregate packet-level data for a TCPFlow.
Analysis computes the aggregate packet - level data for a TCPFlow .
// IP header - to access the IP payload length // TCP header - to gather per-packet tcp data // caste success indicator // TCP payload length // the expected Dst sequence number // the expected Dst sequence number // the last Src ACK sequence number // the last Dst ACK sequence number // count of Src ACK duplicates // count of Dst ACK duplicates // accumulation of stats // accumulation of Src losses // accumulation of Dst losses