Source code for pathspider.chains.ecn
"""
.. module:: pathspider.chains.ecn
:synopsis: A flow analysis chain for Explicit Congestion Notification
This module contains the ECNChain flow analysis chain which can be used by
PATHspider's Observer for recording Explicit Congestion Notification [RFC3168]_
details.
.. codeauthor:: Iain R. Learmonth <irl@fsfe.org>
"""
from pathspider.chains.base import Chain
from pathspider.chains.tcp import TCP_SYN
[docs]class ECNChain(Chain):
"""
This flow analysis chain records details of ECN markings in the IP header.
+-------------------+------+----------------------------------------------------+
| Field Name | Type | Meaning |
+===================+======+====================================================+
| ecn_ect0_syn_fwd | bool | An ECT0 mark was seen in the forward direction |
| | | on a TCP SYN packet |
+-------------------+------+----------------------------------------------------+
| ecn_ect1_syn_fwd | bool | An ECT1 mark was seen in the forward direction |
| | | on a TCP SYN packet |
+-------------------+------+----------------------------------------------------+
| ecn_ce_syn_fwd | bool | An CE mark was seen in the forward direction |
| | | on a TCP SYN packet |
+-------------------+------+----------------------------------------------------+
| ecn_ect0_data_fwd | bool | An ECT0 mark was seen in the forward direction |
| | | on a TCP packet with a payload or a non-TCP packet |
+-------------------+------+----------------------------------------------------+
| ecn_ect1_data_fwd | bool | An ECT1 mark was seen in the forward direction |
| | | on a TCP packet with a payload or a non-TCP packet |
+-------------------+------+----------------------------------------------------+
| ecn_ce_data_fwd | bool | An CE mark was seen in the forward direction |
| | | on a TCP packet with a payload or a non-TCP packet |
+-------------------+------+----------------------------------------------------+
| ecn_ect0_syn_rev | bool | An ECT0 mark was seen in the reverse direction |
| | | on a TCP SYN packet |
+-------------------+------+----------------------------------------------------+
| ecn_ect1_syn_rev | bool | An ECT1 mark was seen in the reverse direction |
| | | on a TCP SYN packet |
+-------------------+------+----------------------------------------------------+
| ecn_ce_syn_rev | bool | An CE mark was seen in the reverse direction |
| | | on a TCP SYN packet |
+-------------------+------+----------------------------------------------------+
| ecn_ect0_data_rev | bool | An ECT0 mark was seen in the reverse direction |
| | | on a TCP packet with a payload or a non-TCP packet |
+-------------------+------+----------------------------------------------------+
| ecn_ect1_data_rev | bool | An ECT1 mark was seen in the reverse direction |
| | | on a TCP packet with a payload or a non-TCP packet |
+-------------------+------+----------------------------------------------------+
| ecn_ce_data_rev | bool | An CE mark was seen in the reverse direction |
| | | on a TCP packet with a payload or a non-TCP packet |
+-------------------+------+----------------------------------------------------+
"""
[docs] def new_flow(self, rec, ip): # pylint: disable=unused-argument
"""
For a new flow, all fields will be initialised to ``False``.
:param rec: the flow record
:type rec: dict
:param ip: the IP or IPv6 packet that triggered the creation of a new
flow record
:type ip: plt.ip or plt.ip6
:return: Always ``True``
:rtype: bool
"""
for d in ['fwd', 'rev']:
for t in ['syn', 'data']:
for f in ['ect0', 'ect1', 'ce']:
rec['ecn_{}_{}_{}'.format(f, t, d)] = False
return True
[docs] def ip4(self, rec, ip, rev):
"""
Records ECN markings from an IPv4 header.
ECN Marking
If an ECT0, ECT1 or CE mark is seen in the IPv4 header, the relevant
field will be set to ``True``.
:param rec: the flow record
:type rec: dict
:param ip: the IPv4 packet that was observed to be part of this flow
:type ip: plt.ip
:param rev: True if the packet was in the reverse direction, False if
in the forward direction
:type rev: bool
:return: Always ``True``
:rtype: bool
"""
return self._ecn_extract(rec, ip, rev)
[docs] def ip6(self, rec, ip, rev):
"""
Records ECN markings from an IPv6 header.
ECN Marking
If an ECT0, ECT1 or CE mark is seen in the IPv6 header, the relevant
field will be set to ``True``.
:param rec: the flow record
:type rec: dict
:param ip: the IPv6 packet that was observed to be part of this flow
:type ip: plt.ip6
:param rev: True if the packet was in the reverse direction, False if
in the forward direction
:type rev: bool
:return: Always ``True``
:rtype: bool
"""
return self._ecn_extract(rec, ip, rev)
def _ecn_extract(self, rec, ip, rev):
ECT_ZERO = 0x02
ECT_ONE = 0x01
ECT_CE = 0x03
ipmark = None
if ip.traffic_class & ECT_CE == ECT_ZERO:
ipmark = 'ecn_ect0'
if ip.traffic_class & ECT_CE == ECT_ONE:
ipmark = 'ecn_ect1'
if ip.traffic_class & ECT_CE == ECT_CE:
ipmark = 'ecn_ce'
if ipmark is not None:
if ip.tcp and ip.tcp.flags & TCP_SYN == TCP_SYN:
t = 'syn'
else:
t = 'data'
d = 'rev' if rev else 'fwd'
rec['{}_{}_{}'.format(ipmark, t, d)] = True
return True