# Per connection byte and packet counting

**URL:** <https://community.zeek.org/t/per-connection-byte-and-packet-counting/1768>\
**Category:** Development\
**Tags:** development\
**Created:** [December 15, 2010, 12:03am UTC](https://community.zeek.org/t/per-connection-byte-and-packet-counting/1768 "2010-12-15T00:03:34Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Gregor\_Maier](https://avatars.discourse-cdn.com/v4/letter/g/94ad74/32.png) [@Gregor\_Maier](https://community.zeek.org/u/Gregor_Maier)\
**Post date:** [December 15, 2010, 12:03am UTC](https://community.zeek.org/t/per-connection-byte-and-packet-counting/1768/1 "2010-12-15T00:03:34Z")

</div>

Hi,

I've played around with packet and byte counting for connections some  
more. I think I've got a pretty neat version:

\* Counting is done in a separate analyzer that can be added to the  
&nbsp;&nbsp;initial analyzer tree based on a global boolean const.

\* Reporting is done via the endpoint records in the connection record (  
&nbsp;&nbsp;c$orig, c$resp). The endpoint records have to new &optional fields for  
&nbsp;&nbsp;number of packets and number of bytes.

\* Updating the counters in the endpoint is done by:  
&nbsp;&nbsp;+ Removing UpdateEndpointVal() from TransportAnalyzer  
&nbsp;&nbsp;+ Adding a UpdateConnVal(conn\_val) to Analyzer.cc. When a Conn object  
&nbsp;&nbsp;&nbsp;&nbsp;needs to update the conn\_val (e.g., to generate an event) it calls  
&nbsp;&nbsp;&nbsp;&nbsp;the root analyzer's UpdateConnVal(). This call is then "forwarded"  
&nbsp;&nbsp;&nbsp;&nbsp;to every analyzer in the tree. I.e., every analyzer could update the  
&nbsp;&nbsp;&nbsp;&nbsp;conn\_val, e.g., by adding additional, optional fields to the  
&nbsp;&nbsp;&nbsp;&nbsp;connection record.

In terms of speed and memory consumption this is surprisingly  
lightweight. Runtime as reported by time, memory consumption from top.  
I've only loaded conn and weird:

\* Baseline. Current git master: (3 runs)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2m42s 900MB  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2m37s 900MB  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2m37s 900MB

\* My version, with counting disabled (i.e., counting analyzer not  
&nbsp;&nbsp;instantiated, no the optional fields in endpoint are NULL):  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2m34s 898MB  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2m36s 898MB  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2m36s 898MB  
&nbsp;&nbsp;It seems to be faster and using less memory(!). There is an  
&nbsp;&nbsp;explanation why it needs slightly less memory: the git-master Conn.cc  
&nbsp;&nbsp;had two RecordVal\* for orig\_endp, and resp\_endp that were passed to  
&nbsp;&nbsp;UpdateEndpointVal. Since I now only pass the conn\_val to  
&nbsp;&nbsp;UpdateConnVal, I don't need these pointers in Conn.cc anymore.  
&nbsp;&nbsp;I've checked the testsuite it my version passes it.

\* My version with counting enabled:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2m40s 1000MB  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2m41s 1000MB  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2m41s 1000MB  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2m41s 1000MB  
&nbsp;&nbsp;So: no speed penalty and about 100MB for the analyzer instance and  
&nbsp;&nbsp;the additional fields in endpoint (these are responsible for most of  
&nbsp;&nbsp;the memory. Vals are expensive memory-wise).

\* As an additional experiment, I made the history field in conn\_val  
&nbsp;&nbsp;&optional, so that it's only allocated, if record\_state\_history=T.  
&nbsp;&nbsp;Results:  
&nbsp;&nbsp;&nbsp;&nbsp;with counting: 2m39s 862MB  
&nbsp;&nbsp;&nbsp;&nbsp;wihtout counting: 2m33s 962MB  
&nbsp;&nbsp;So I think it might make sense to also integrate this change.  
&nbsp;&nbsp;(Currently the history is always tracked and always part of the  
&nbsp;&nbsp;connection record, but it is only logged in conn.log if  
&nbsp;&nbsp;record\_state\_history=T).

Finally, a longer trace with way more data and more policy scripts (conn  
weird dpd http-request htt-reply dns):  
&nbsp;&nbsp;&nbsp;&nbsp;master / baseline 88m38 2906MB  
&nbsp;&nbsp;&nbsp;&nbsp;no counting 88m37 2907MB  
&nbsp;&nbsp;&nbsp;&nbsp;with counting 87m47 2963MB

So, all in all I would say: we should go with this version, as this  
seems to be the ideal solution: overhead when disabled, only memory  
overhead when enabled (and this overhead is inevitable!).

In addition, I would suggest to make c$history &optional and only  
allocate and assign a Val\* to it if record\_state\_history=T, since this  
seems to safe quite a bit of memory!

cu  
Gregor

---

<div class="post-metadata">

**Author:** ![Seth\_Hall3](https://avatars.discourse-cdn.com/v4/letter/s/d6d6ee/32.png) [@Seth\_Hall3](https://community.zeek.org/u/Seth_Hall3)\
**Post date:** [December 15, 2010, 5:06am UTC](https://community.zeek.org/t/per-connection-byte-and-packet-counting/1768/2 "2010-12-15T05:06:17Z")

</div>

This sounds awesome!

The only question I have is what is the $history field used for? This is second time I've seen it referred to today, but I have no idea what it's for. 🙂

&nbsp;&nbsp;.Seth

---

<div class="post-metadata">

**Author:** ![Gregor\_Maier](https://avatars.discourse-cdn.com/v4/letter/g/94ad74/32.png) [@Gregor\_Maier](https://community.zeek.org/u/Gregor_Maier)\
**Post date:** [December 15, 2010, 3:43pm UTC](https://community.zeek.org/t/per-connection-byte-and-packet-counting/1768/3 "2010-12-15T15:43:28Z")

</div>

It records the state history of (TCP) connections. When  
record\_state\_history=T it will add an additional column to conn.log.  
It's probably mostly used for measurements rather than live security  
deployment. The "history" is a string of letters:

-8\<------  
s == a SYN w/o the ACK bit set  
h == a SYN+ACK ("handshake")  
a == a pure ACK  
d == packet with payload ("data")  
f == packet with FIN bit set  
r == packet with RST bit set

I also think there is a "c" which means we saw a packet with a bad  
checksum and "i" for "inconsistent" packets---basically just weird crap  
like both SYN and RST bits lit up.

If the code is in upper case it means the event comes from the  
originator and lower case then means the responder.

Also, there is compression. We only record one "d" in each direction,  
for instance. I.e., we just record that data went in that direction.  
This history is not meant to encode how much data that happened to be.  
-\>8------

cu  
Gregor

---

<div class="post-metadata">

**Author:** ![robin](https://yyz1.discourse-cdn.com/flex011/user_avatar/community.zeek.org/robin/32/599_2.png) [@robin](https://community.zeek.org/u/robin)\
**Post date:** [December 17, 2010, 7:10am UTC](https://community.zeek.org/t/per-connection-byte-and-packet-counting/1768/4 "2010-12-17T07:10:48Z")

</div>

Yes, this all sounds really good.

One more thought: does expect\_connection() work with this (see,  
e.g., ftp.bro for how it's used). Then one could enable it for  
individual future sessions (like file transfers).

In principle, it seems an enable\_analyzer() function (which we still  
don't have; there's just disable\_analyzer()) could be nice for this  
too. However, it would only get a chance to add the counting once a  
few packets have already passed so not sure how useful it would  
really be.

Robin

---

<div class="post-metadata">

**Author:** ![Gregor\_Maier](https://avatars.discourse-cdn.com/v4/letter/g/94ad74/32.png) [@Gregor\_Maier](https://community.zeek.org/u/Gregor_Maier)\
**Post date:** [December 17, 2010, 3:30pm UTC](https://community.zeek.org/t/per-connection-byte-and-packet-counting/1768/5 "2010-12-17T15:30:15Z")

</div>

> One more thought: does expect\_connection() work with this (see,  
> e.g., ftp.bro for how it's used). Then one could enable it for  
> individual future sessions (like file transfers).

Don't think so, since it needs to be a child \*packet\* analyzer of  
TCP\_Analyzer.

> In principle, it seems an enable\_analyzer() function (which we still  
> don't have; there's just disable\_analyzer()) could be nice for this  
> too. However, it would only get a chance to add the counting once a  
> few packets have already passed so not sure how useful it would  
> really be.

In addition to enable\_analyzer() and add\_to\_initial\_tree() function  
would also be nice, so that users can select analyzers that they want to  
run on all connections.

---

<div class="post-metadata">

**Author:** ![Gregor\_Maier](https://avatars.discourse-cdn.com/v4/letter/g/94ad74/32.png) [@Gregor\_Maier](https://community.zeek.org/u/Gregor_Maier)\
**Post date:** [January 18, 2011, 4:50pm UTC](https://community.zeek.org/t/per-connection-byte-and-packet-counting/1768/6 "2011-01-18T16:50:45Z")

</div>

Hi,

since there were no more comments. I'll wrap up these changes and make  
them ready for a merge.

I will also make the connection history in the conn record an optional  
field, since this will save quite a bit of memory.

cu  
Gregor

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex011/uploads/zeek/original/1X/f09d732bc2cc7c7cc7e35db67cf4e1d5233ce7a7.png) [@system](https://community.zeek.org/u/system)\
**Post date:** [May 6, 2022, 3:39pm UTC](https://community.zeek.org/t/per-connection-byte-and-packet-counting/1768/7 "2022-05-06T15:39:22Z")

</div>


