All Classes Namespaces Files Functions Pages
Higher-layer Tcl API

The higher-layer Tcl API introduces the concept of flows (familiar from the GUI) to the ByteBlower Tcl API.

It basically allows a user to set up his or her scenario in a declarative way, in the form of a scenario configuration. At execution time, such configurations are parsed by the higher-layer API and the relevant lower-layer API methods are called.

It is important to note that the higher-layer API is a simple usability layer on top of the lower-layer API. Users are free to work directly with the lower-layer API, customize the higher-layer API to their needs or even create their own Tcl library on top of the lower-layer API, if this better suits their needs.

The source code of the higher-layer API is freely available to the user. So if you have any questions about the API internals or want to use the implementation as a basis for your own Tcl framework, you can find the source in your install directory! It is also available in this documentation.

Structure of the higher-layer API

At the center of the higher-layer API is the execute scenario module. The main method, excentis::ByteBlower::ExecuteScenario, takes a scenario configuration as input, executes it and returns the relevant results.

The structure of a scenario configuration is outlined below. It takes the form of a structure of nested lists: a scenario is a list of flows, a flow is a list of TX and RX configurations, etc. See the composing section for more info.

The ExecuteScenario method returns the scenario results, which are also structured as nested lists. These nested lists are composed in the same way as the scenario configuration. For example, if a scenario configuration is composed as a list of 2 flow configurations, the scenario result will be a list of 2 flow results. The same goes for the TX and RX results within a flow. See the results section for more info.

Apart from ExecuteScenario, the higher-layer API contains some other modules, such as flow latency . The main method of these modules, such as excentis::ByteBlower::FlowLatency, are wrappers of ExecuteScenario. The purpose of these wrappers is to easy the configuration of specific setups. The wrapper functionality includes:

  • Placing restrictions on the scenario configuration and printing clear and scenario-specific error messages if those restrictions are not met.
    • The wrapper will pre-parse the provided configuration and throw specific error messages if a wrong configuration is provided.
    • This simplifies the creation and debugging of simple scenario configurations, especially for novice users.
    • For example, a flow within a latency scenario must have exactly one latency-enabled TX part and one latency RX part.
  • Provide limited but setup-specific results.
    • The wrapper will perform pre-processing of the scenario results. It knows the result structure because of the restrictions on the scenario configuration.
    • Typically the relevant results are extracted from the result data structure and passed on in a simpler format.
    • This simplifies the result for the user and limits the parsing required in the script.
    • For example, the results of a latency flow will simply return four values per flow: minimum, maximum and average latency and the jitter.
tcl-api-hl-overview.png

The ByteBlower higher-layer API becomes available in a Tcl shell by loading the following package:

1 package require ByteBlowerHL

Scenario and flow configurations

The scenario configuration defines what the higher-layer API needs to execute. A scenario configuration consists of a hierarchy of structured lists.

At the highest level a scenario configuration is nothing more than a list of flow configurations:

  • Syntax:
    '<flow-configuration>' {0..n}
    A flow configuration describes a single traffic flow.
  • The scenario combines multiple flows that should be executed together.
  • Example:
    1 set scenarioConfig [ list $flow1Config $flow2Config ]

A flow configuration consists of a list of transmitting (TX) and receiving (RX) components.

  • Syntax:
    '-tx <tx-component>' {0..n}
    A TX component describes the origin and characteristics of the traffic that must be transmitted in the flow. See TX Configuration below.
    '-rx <rx-component>' {0..n}
    An RX component describes the location and configuration of a traffic receiver. Traffic receivers come in multiple forms. See RX configuration below.
  • A flow may contain 0, 1 or more TX components and 0, 1 or more RX components.
  • Flows without a TX component can act as sniffers. Flows without an RX component can act as background traffic.
  • Example:
    1 set flow1Config [ list -tx $flow1TxConfig1 -rx $flow1RxConfig1 -rx $flow1RxConfig2 ]

TX Configuration

A TX component consists of a list of key-value pairs that define the traffic stream:

  • Syntax:
    '-port $txPortObject' {1}
    The TX port is a mandatory option and has the transmitting ByteBlowerPort object as value.
    '-frame [ list <frame-config> ]' {0..1}
    A TX frame config option provides the frame content with options.
    '-numberofframes <integer>' {0..1}
    The number of frames to be sent in the stream. Integer value;
    Default: 100.
    '-interframegap <integer>' {0..1}
    The time in ns between the transmission of two consecutive frames in the stream. Integer value;
    Default: 10000000 (10 ms).
    '-initialtimetowait <integer>' {0..1}
    The time to wait in ms (within the scenario) before the first frame is sent. Integer value;
    Default: 0ms.
    '-timingmodifier <timingmod-configuration>' {0..1}
    A timing modifier configuration that should be applied to the stream.
    Default: "none".
    '-latency <boolean>' {0..1}
    Boolean flag indicating if a timestamp must be inserted into the sent frames; used for latency measurements. Boolean value (0 or 1),
    Default: 0.
    '-outofsequence <boolean>' {0..1}
    Boolean flag indicating if a sequence number must be inserted into the sent frames; used for out of sequence detection. Boolean value (0 or 1),
    Default: 0.
    '-scoutingframe [ list <scouting-frame-config> ]' {0..1}
    A TX scouting frame config option provides the scouting frame content with options.
    '-scoutinginterframegap <integer>' {0..1}
    The time in ns between the transmission of two consecutive scouting frames in the stream. Integer value;
    Default: 10000000 (10 ms). Please note that only one frame is sent per stream. This option is therefor only relevant when multiple scouting frames are transmitted.
  • A TX component contains the transmitting port and 0, 1 or more traffic stream characteristics.
  • Example:
    1 set flow1TxConfig1 [ list -port $portObject -latency 1 -initialtimetowait 5000

A Frame size modifier consists of a list of key-value pairs that define the modifier or a "none"-string to stay disabled and is configured on the frame:

  • Syntax:
    '-type <framemod-type>' {1}
    The type of the frame size modifier. Must be either "random" or "growing". Mandatory value.
    '-minimum <integer>' {0..1}
    The minimum frame size used in this frame size modifier in bytes (layer 2, excluding CRC). Integer value;
    Default: 60.
    '-maximum <integer>' {0..1}
    The maximum frame size used in this frame size modifier in bytes (layer 2, excluding CRC). Integer value;
    Default: 1514.
    '-step <integer>' {0..1}
    The increment step size in bytes for a growing frame size modifier. Ignored by random modifier. Integer value;
    Default: 1.
    '-iteration <integer>' {0..1}
    The amount of frames of a specific size used in a growing frame size modifier before incrementing with the step size. Ignored by random modifier. Integer value;
    Default: 1.
  • A frame size modifier is either the "none"-string or contains a type parameter with 0, 1 or more frame size modifier characteristics.
  • The "none" configuration is only provided for consistency, since one may just as easily omit the framemodifier key from the TX frame component.
  • Example:
    1 set flow1TxConfig1FrameMod [ list -type random -minimum 100 -maximum 120 ]
    Configure none:
    1 set flow1TxConfig1FrameMod "none"

A Frame field modifier consists of a list of key-value pairs that define the modifier or a "none"-string to stay disabled and is configured on the frame:

  • Syntax:
    '-type <framefieldmod-type>' {1}
    The type of the frame size modifier. Must be either "random" or "incremental". Mandatory value.
    '-offset <integer>' {0..1}
    The offset in the frame where the field starts. Integer value;
    Default: 60.
    '-length <integer>' {0..1}
    The length in bytes of the field specified. Accepted values are 1, 2, 4 and 8 Integer value;
    Default: 2.
    '-minimum <integer>' {0..1}
    The minimum value of the field. Integer value;
    Default: 0.
    '-maximum <integer>' {0..1}
    The minimum value of the field. Integer value;
    Default: 2^(length * 8) - 1.
    '-step <integer>' {0..1}
    The increment step size for the field. Ignored by random modifier. Integer value;
    Default: 1.
    '-initialvalue <integer>' {0..1}
    The inital value for the field. Ignored by random modifier. Integer value;
    Default: 1.
  • A frame field modifier is either the "none"-string or contains a type parameter with 0, 1 or more frame field modifier characteristics.
  • The "none" configuration is only provided for consistency, since one may just as easily omit the framemodifier key from the TX frame component.
  • Example:
    1 set flow1TxConfig1FrameMod [ list -type random -minimum 100 -maximum 120 ]
    Configure none:
    1 set flow1TxConfig1FrameMod "none"

A Timing modifier may be configured by some key-value characteristics or be 'none' to stay disabled.:

  • Syntax:
    '-type <timingmod-type>' {1}
    The type of the timing modifier. Currently only supports "multiburst", which alternates between traffic and quiet periods. Mandatory value.
    '-burstsize <integer>' {0..1}
    The number of frames in the burst part of a multiburst modifier. The frame rate within this burst is the configured frame rate of the flow. Integer value;
    Default: 100.
    '-interburstgap <integer>' {0..1}
    The silent time in ns between two consecutive bursts of a multiburst modifier. Integer value;
    Default: 1000000000 (1s).
  • A timing modifier component is either the "none"-string or contains a type parameter with 0, 1 or more timing modifier characteristics.
  • The "none" configuration is only provided for consistency, since one may just as easily omit the timingmodifier key from the TX component.
  • Example:
    1 set flow1TxConfig1TimingMod [ list -type multiburst -burstsize 100 -interburstgap 20000000 ]
    Configure none:
    1 set flow1TxConfig1TimingMod "none"

RX configuration

A RX component consists of a list of key-value pairs that define the incoming traffic processor:

  • Syntax:
    '-port $rxPortObject' {1}
    The RX port is mandatory option and has the receiving ByteBlowerPort object as value.
    '-trigger <trigger-configuration>' {0..1}
    Adds a trigger to the port. A trigger updates counter values when incoming frames match a specified filter.
    '-latency <latency-configuration>' {0..1}
    Adds a latency calculator to the port. A latency calculator computes latency values using the timestamp tags in incoming frames.
    '-outofsequence <outofsequence-configuration>' {0..1}
    Adds an out of sequence counter to the port. This counter detects packets arriving out of sequence using the sequence number tags in incoming frames.
    '-capture <capture-configuration>' {0..1}
    Adds an incoming traffic processor to the port that simply captures all frames matching matching a filter.
  • A TX compontent contains the transmitting port and 0 or 1 incoming packet processors.
  • To use multiple incoming traffic processors on a port, multiple RX components must be configured.
  • Example:
    1 set flow1RxConfig1 [ list -port $portObject -capture $flow1RxConfig1Capture ]

A trigger consists of a list of key-value pairs that determines both the processing and the result values. The result is also affected by the extended flag of the scenario:

  • Syntax:
    '-type <trigger-type>' {1}
    The type of trigger. Supported values are 'basic' or 'sizedistribution'. Default value is 'basic', but becomes 'sizedistribution' when the extended flag is passed to the scenario execution.
    '-filter <filter>' {0..1}
    The trigger filter. Only matching packets will be counted. Must be a valid DisplayFilter or BPF filter, based on the filterFormat argument. Default is an empty filter that matches all frames.
    '-filterFormat <filterformat-type>' {0..1}
    The type of filter. Supported values are are 'display' for DisplayFilter, 'bpf' for BPF and 'tuple' for the tuple-syntax. The tuple syntax is only valid when used with a ByteBlower Wireless Endpoint. Default is 'display'.
    '-duration <duration>' {0..1}
    The duration for the trigger. Only valid when used on a ByteBlower Wireless Endpoint. The default unit is nanoseconds
  • A trigger configuration contains 0, 1 or more characteristics.
  • Example:
    1 set flow1RxConfig1Trigger [ list ]
    2 set flow1RxConfig1Trigger [ list -filter "(ipv6.src == fdec:5ef9:84b5:4100:0000:ffff:0000:f65d) and (ipv6.nxt == 17) and (eth.len == 124)" ]
    3 set flow1RxConfig1Trigger [ list -filterFormat bpf -filter "(ip6 src fdec:5ef9:84b5:4100:0000:ffff:0000:f65d) and (ip6[6] = 17) and (len = 124)" ]
    4 set flow1RxConfig1Trigger [ list -filterFormat tuple -filter "-srcAddress 10.8.3.4 -udpSourcePort 5000 -udpDestinationPort 7000" -duration 14000000000 ]

A latency calculator consists of a list of key-value pairs that determines both the processing and the result values. The result is also affected by the extended flag of the scenario:

  • Syntax:
    '-type <latency-type>' {0..1}
    The type of latency calculator. Supported values are 'basic' or 'distribution'. Default value is 'basic', but becomes 'distribution' when the extended flag is passed to the scenario execution.
    '-filter <filter>' {0..1}
    The calculator's filter. Only matching packets will be processed. Must be a valid BPF filter. Default is an empty filter that matches all frames.
  • A latency configuration contains 0, 1 or more characteristics.
  • Example:
    1 set flow1RxConfig1Latency [ list ]
    2 set flow1RxConfig1Latency [ list -type distribution -filter "eth.len == 124" ]

An out of sequence detector consists of a list of key-value pairs that determines both the processing and the result values:

  • Syntax:
    '-type <outofsequence-type>' {0..1}
    The type of outofsequence calculator. Only 'basic' is supported for now and is the default value.
    '-filter <filter>' {0..1}
    The detector's filter. Only matching packets will be processed. Must be a valid BPF filter. Default is an empty filter that matches all frames.
  • A trigger configuration contains 0, 1 or more characteristics.
  • Example:
    1 set flow1RxConfig1Sequence [ list ]
    2 set flow1RxConfig1Sequence [ list -filter "eth.len == 124" ]

A capture consists of a list of key-value pairs that determines both the processing and the result values:

  • Syntax:
    '-pcap <pcap-filepath>' {0..1}
    The path where the capture must be saved after the scenario or an empty path ('') to disable saving the capture. Default value is the empty path ('').
    '-filter <filter>' {0..1}
    The capture's filter. Only matching packets will be processed. Must be a valid BPF filter. Default is an empty filter that matches all frames.
  • A trigger configuration contains 0, 1 or more characteristics.
  • Example:
    1 set flow1RxConfig1Capture [ list -pcap "/home/excentis/captures/hl.pcap" ]

Composing a configuration

A scenario configuration can be composed directly as a structure of nested lists. As an example, see the following configuration:

1 set scenarioConfig [ list [ list \
2  -tx [ list -port $srcPort \
3  -frame [ list -bytes $srcFrame1 ] \
4  -numberofframes 10000 \
5  -interframegap 1000000 \
6  -latency 1 \
7  ] \
8  -rx [ list -port $dstPort \
9  -latency [ list -filter "(ip.src == [ [ $srcPort Layer3.IPv4.Get ] Ip.Get ]) and \
10  (ip.dst == [ [ $dstPort Layer3.IPv4.Get ] Ip.Get ]) and \
11  (eth.len == $ethLength)" ] \
12  ] \
13  ]\
14  [ list \
15  -tx [ list -port $srcPort \
16  -frame [ list -bytes $srcFrame2 ] \
17  -numberofframes 1000000 \
18  -interframegap 10000 \
19  ] \
20  ]\
21  ]

This scenario contains two flows. The first flow measures the latency of the flow. The strict filter makes sure that only frames of that flow, that contain a timestamp tag, are taken into account. The second flow acts as background traffic so it does not contain receive-side processing.

When sending traffic from and to a ByteBlower Wireless Endpoint, the same scenario configuration can be configured like this:

1 set scenarioConfig [ list [ list \
2  -tx [ list -port $srcPort \
3  -frame [ list -bytes $srcFrame1 ] \
4  -numberofframes 10000 \
5  -interframegap 1000000 \
6  -latency 1 \
7  ] \
8  -rx [ list -port $wirelessEndpoint \
9  -latency [ list \
10  -filterFormat "tuple"
11  -filter "-srcAddress [ [ $srcPort Layer3.Get ] Ip.Get ] -udpSourcePort $udpSourcePort -udpDestinationPort $udpDestinationPort" \
12  ] \
13  ] \
14  ]\
15  [ list \
16  -tx [ list -port $wirelssEndpoint \
17  -frame [ list -payload $payload1 -localPort $udpSourcePort -remotePort $udpDestinationPort -remoteAddress [ [ $dstPort Layer3.Get ] Ip.Get ] \
18  -numberofframes 1000000 \
19  -interframegap 10000 \
20  ] \
21  ]\
22  ]

Parsing the results

The excentis::ByteBlower::ExecuteScenario method returns a data structure of nested lists with the various results. The exact content is defined by the scenario configuration itself and the scenario execution parameters (e.g. extended).

Until the level of TX and RX components, there is a 1-on-1 mapping between configuration structure and results structure. For the example configuration above, the base result structure will be:

Returns:

{ { -tx { <txresult> } -rx { <rxresult> } } { -tx { <txresult> } } } 

The TX and RX component results correspond with the result values of the lower-layer API calls:

For the example configuration above, the return value would be something like this:

Returns:

{ 
  { 
    -tx { NrOfFramesSent 10000 ByteBlowerObject_1392967743_16 10000 } 
    -rx { NrOfFrames 10000 MinLatency 2733 AvgLatency 3023 MaxLatency 3337 Jitter 190 } 
  } 
  { 
    -tx { NrOfFramesSent 1000000 ByteBlowerObject_1392967743_18 1000000 } 
  }
}

The wrappers around ExecuteScenario may greatly simplify the result structure. Since they place limitations on the structure of the scenario configuration, they are able to pre-parse the generic result and only return the relevant values to the script.

For example, if we would pass our example configuration to FlowLatency instead of ExecuteScenario , the result would become:

Returns:

{ -tx 10000 -rx { 10000 2733 3023 3337 190 } } { -tx 10000 }