9. Pktgen How-to Guide¶
The old module etgen is only support hardward packet generator Ixia Explorer which is not friendly for users to get. So DTS community refined DTS framework to support another software packet generator Trex which is an open source project, and user can get it easily.
these definition and usage pattern come from doc pktgen-API-1.1.docx and etgen usage in dts. For trex(CISCO) rapid iterative development speed, we lack of adequate manpower to keep up with it. Here we recommend to use trex v2.41/v2.42/v2.43 to run pktgen/trex.
9.1. add stream¶
add stream in pktgen streams table.
one stream content including:
tx_port: transmit port idx in tester.ports_info.
rx_port: receive port idx in tester.ports_info.
pcap: pcap file or Packet instance, Only support one packet in it.
tx_port = self.tester.get_local_port(dut_port_index1)
rx_port = self.tester.get_local_port(dut_port_index2)
stream_id = hPktgen.add_stream(tx_port, rx_port, pcap)
9.2. config stream¶
configure a stream option.
9.2.1. definition¶
Currently pktgen support ethernet/ipv4/vlan protocol layer some field vary with increase/decrease/random value.
stream option contain:
'pcap': network packet format
'fields_config': protocol layer field behavior(optional)
'stream_config': stream transmit behavior
'flow_control': port flow control(optional)
9.2.1.1. pcap¶
It is a network packet format. It can be a absolute path of pcap file or an instance of scapy Packet. It should only contain one packet format.
Example 1:
pcap = <Ether dst=FF:FF:FF:FF:FF:FF src=00:00:00:00:00:00 type=IPv4 |<IP frag=0 proto=udp src=0.0.0.1 dst=0.0.0.255 |<UDP sport=22 dport=50 |<Raw load='xxxxxxxxxxxxxxxxxx' |>>>>
Example 2:
pcap = "/root/xxx.pcap"
9.2.1.2. field option¶
define every layer’s field behavior.
9.2.1.2.1. ‘mac’¶
‘mac’ is ethernet protocol layer name.
# field name
'src': {
# action: inc/dec/random
'action':'inc',
# field end value should be bigger than field start value
'end': '00:00:00:00:00:FF',
# field start value
'start': '00:00:00:00:00:02',
# field value vary step
'step': 1},
'dst': {
# action: inc/dec/random
'action':'inc',
# field end value should be bigger than field start value
'end': 'ff:00:00:00:00:FF',
# field start value
'start': 'ff:00:00:00:00:02',
# field value vary step
'step': 1},
9.2.1.2.2. ‘ip’¶
‘ip’ is ip protocol layer name.
# field name
'src': {
# action: inc/dec/random
'action': 'inc',
# field end value should be bigger than field start value
'end': '16.0.0.16',
# field start value
'start': '16.0.0.1',
# field value vary step
'step': 1},
# field name
'dst': {
# action: inc/dec/random
'action': 'inc',
# field end value should be bigger than field start value
'end': '48.0.0.255',
# field start value
'start': '48.0.0.1',
# field value vary step
'step': 1},
9.2.1.2.3. ‘vlan’¶
‘vlan’ is vlan protocol layer name.
# internal vlan
0: {
# action: inc/dec/random
'action': 'inc',
# field end value should be bigger than field start value
'end': 52,
# field start value
'start': 50,
# field value vary step
'step': 1},
# external vlan
1: {
# action: inc/dec/random
'action': 'inc',
# field end value should be bigger than field start value
'end': 52,
# field start value
'start': 50,
# field value vary step
'step': 1},
9.2.1.3. ‘stream_config’¶
define a stream transmit behavior.
basic content including:
'rate': 0 ~ 100 int type, port line rate should set it.
'transmit_mode': TRANSMIT_CONT/TRANSMIT_S_BURST
TRANSMIT_CONT define a continuous transmit.
TRANSMIT_S_BURST define a burst transmit with custom number of packets.
from pktgen_base import TRANSMIT_CONT, TRANSMIT_S_BURST
stream_config = {
'rate': 100,
# TRANSMIT_CONT define a continuous transmit.
# TRANSMIT_S_BURST define a burst transmit with custom number of packets.
'transmit_mode': TRANSMIT_CONT
}
9.2.2. stream option examples¶
9.2.2.1. normal stream option¶
normal stream ignore fields_config configuration option.
Example 1:
option = {
'pcap': "/root/xxx.pcap",
'stream_config': {
'rate': 100,
'transmit_mode': TRANSMIT_CONT}}
Example 2:
option = {
'pcap': <Ether dst=00:00:00:00:20:00 src=00:00:00:00:00:FF type=IPv4 |<IP frag=0 proto=udp src=0.0.0.1 dst=0.0.0.255 |<UDP sport=22 dport=50 |<Raw load='xxxxxxxxxxxxxxxxxx' |>>>>,
'stream_config': {
'rate': 100,
'transmit_mode': TRANSMIT_CONT}}
9.2.2.2. stream option with mac increase/decrease/random¶
action = 'inc' or 'dec' or 'random'
option = {
'pcap': "/root/xxx.pcap",
'fields_config': {
'mac': {
'dst': {
'action': action,
'end': '00:00:00:00:20:00',
'start': '00:00:00:00:00:FF',
'step': 1},
'src': {
'action': action,
'end': '00:00:00:00:00:FF',
'start': '00:00:00:00:00:02',
'step': 1}}},
'stream_config': {
'rate': 100,
'transmit_mode': TRANSMIT_CONT
}
}
9.2.2.3. stream option with ip increase/decrease/random¶
action = 'inc' or 'dec' or 'random'
option = {
'pcap': "/root/xxx.pcap",
'fields_config': {
'ip': {
'dst': {
'action': action,
'end': '48.0.0.255',
'start': '48.0.0.1',
'step': 1},
'src': {
'action': action,
'end': '16.0.0.16',
'start': '16.0.0.1',
'step': 1}}},
'stream_config': {
'rate': 100,
'transmit_mode': TRANSMIT_CONT,
}
}
9.2.2.4. stream option with vlan increase/decrease/random¶
action = 'inc' or 'dec' or 'random'
option = {
'pcap': "/root/xxx.pcap",
'fields_config': {
'ip': {
0: {
'action': action,
'end': 55,
'start': 50,
'step': 1},
'stream_config': {
'rate': 100,
'transmit_mode': TRANSMIT_CONT,
}
}
9.2.2.5. burst stream option¶
option = {
'pcap': "/root/xxx.pcap",
'stream_config': {
'rate': 100,
# set stream transmit mode
'transmit_mode': TRANSMIT_S_BURST,
'txmode' : {
# total packets
'total_pkts': 1000},
}
}
9.2.2.6. stream option with flow control¶
flow control open (trex not supported)
option = {
'flow_control': {
# 0: disable flow control
# 1: enable flow control
'flag': 1},
'pcap': "/root/xxx.pcap",
'stream_config': {
'rate': 100,
'transmit_mode': TRANSMIT_CONT}}
9.3. measure¶
pktgen measure_xxxx return value is the same as etgen, measure_xxxx and measure are both supported. If traffic option is not set, use default values.
9.3.1. two usage examples of pktgen measure method¶
Example 1:
from pktgen import getPacketGenerator, PKTGEN_TREX
hPktgen = getPacketGenerator(tester, PKTGEN_TREX)
traffic_option = {'rate': 100}
hPktgen.measure_throughput(stream_ids, traffic_opt)
Example 2:
from pktgen import getPacketGenerator, PKTGEN_TREX
hPktgen = getPacketGenerator(tester, PKTGEN_TREX)
traffic_option = {
'method': 'throughput',
'rate': 100
}
hPktgen.measure(stream_ids, traffic_opt)
9.3.2. throughput¶
throughput testing scenario.
9.3.2.1. option¶
traffic_option = {
# test method name, if use `measure_throughput`, ignore this key
'method': 'throughput',
# port rate percent, float(0--100), default value is 100.(reserved)
'rate': 100,
# warm up time before start main transmission. If it is set, it will start
# a custom time transmission to make sure packet generator under good
# status. It is an optional key.
'delay': 5,
# the interval time of get throughput statistic (second).
# If set this key value, pktgen will return several throughput statistic
# data in a duration. If not set this key value, only return one statistic
# data. It is used coupled with `duration` option.
'interval': 1,
# this key works with ``interval`` key. If it is set, the callback
# of suite level will be executed after getting throughput statistic.
# callback method should define as below, don't add sleep in this method.
'callback' : callback_method,
# transmission lasting time(second), default value is 10 second.
'duration': 5}
9.3.2.2. return value¶
bps_rx_total: Received bits per second pps_rx_total: Received packets per second
return_value = (bps_rx_total, pps_rx_total)
9.3.3. loss¶
loss rate testing scenario.
9.3.3.1. option¶
traffic_option = {
# test method name, if use `measure_loss`, ignore this key
'method': 'loss',
# port rate percent, float(0--100), default value is 100.(reserved)
'rate': 100,
# warm up time before start main transmission. If it is set, it will start
# a custom time transmission to make sure packet generator under good
# status. It is an optional key.
'delay': 5,
# transmission lasting time(second), default value is 10 second.
'duration': 5}
9.3.3.2. return value¶
loss_stats = (loss_rate, tx_pkts, rx_pkts)
9.3.4. latency¶
latency testing scenario.
9.3.4.1. option¶
traffic_option = {
# test method name, if use `measure_latency`, ignore this key
'method': 'latency',
# port rate percent, float(0--100), default value is 100.(reserved)
'rate': 100,
# warm up time before start main transmission. If it is set, it will start
# a custom time transmission to make sure packet generator under ready
# status. It is an optional key.
'delay': 5,
# transmission lasting time(second), default value is 10 second.
'duration': 5}
9.3.4.2. return value¶
latency_stats = { 'min': 15,
'max': 15,
'average': 15,}
9.3.5. rfc2544 option¶
rfc2544 testing scenario by decreasing step.
9.3.5.1. option¶
traffic_option = {
# test method name, if use `measure_rfc2544`, ignore this key.
'method': 'rfc2544',
# port rate percent at first round testing, 0 ~ 100, default is 100.
'rate': 100,
# permit packet drop rate, default is 0.001.
'pdr': 0.001,
# port rate percent drop step, 0 ~ 100 , default is 1.
'drop_step': 1,
# warm up time before start main transmission. If it is set, it will start
# a custom time transmission to make sure packet generator under ready
# status. It is an optional key.
'delay': 5,
# transmission lasting time(second), default value is 10 second.
'duration': 5}
9.3.5.2. return value¶
loss_stats = (loss_rate, tx_pkts, rx_pkts)
9.3.6. rfc2544_dichotomy option¶
rfc2544 testing scenario using dichotomy algorithm.
9.3.6.1. option¶
traffic_option = {
# test method name, if use `measure_rfc2544_dichotomy` method, ignore this key.
'method': 'rfc2544_dichotomy',
# dichotomy algorithm lower bound rate percent, default is 0.
'min_rate': 0,
# dichotomy algorithm upper bound rate percent, default is 100.
'max_rate': 100,
# dichotomy algorithm accuracy, default 0.001.
'accuracy': 0.001,
# permit packet drop rate, default is 0.001.
'pdr': 0.001,
# warm up time before start main transmission. If it is set, it will start
# a custom time transmission to make sure packet generator under ready
# status. It is an optional key.
'delay': 5,
# transmission lasting time(second), default value is 10 second.
'duration': 10}
9.3.6.2. return value¶
loss_stats = (loss_rate, tx_pkts, rx_pkts)
9.4. reference example¶
This example show how to use pktgen in suite script. In fact, most scenario are more simpler than this. Part of code is pseudo code and it can’t be ran directly.
testing scenario:
create four streams on two links, each link attach two streams. On one link,
one stream set mac src increase and packet format is a pcap file, the other
stream set ip src random / dst decrease and packet format is a scapy Packet
instance. All streams use continuous transmit and run rfc2544 scenario using
trex packet generator.
# import pktgen lib
from pktgen import getPacketGenerator, PKTGEN_TREX, TRANSMIT_CONT
# create a pktgen instance
hPktgen = getPacketGenerator(tester, PKTGEN_TREX)
# create packet
pcap1 = <Ether dst=FF:FF:FF:FF:FF:FF src=00:00:00:00:00:00 type=IPv4 |<IP frag=0 proto=udp src=0.0.0.1 dst=0.0.0.255 |<UDP sport=22 dport=50 |<Raw load='xxxxxxxxxxxxxxxxxx' |>>>>
pcap2 = "/root/xxx.pcap"
# attach stream to pktgen
stream_ids = []
tx_port1 = self.tester.get_local_port(dut_port_index1)
rx_port1 = self.tester.get_local_port(dut_port_index2)
stream_id_1 = hPktgen.add_stream(tx_port1, rx_port1, pcap1)
stream_id_2 = hPktgen.add_stream(tx_port1, rx_port1, pcap2)
stream_ids.append(stream_id_1)
stream_ids.append(stream_id_2)
tx_port2 = self.tester.get_local_port(dut_port_index2)
rx_port2 = self.tester.get_local_port(dut_port_index1)
stream_id_3 = hPktgen.add_stream(tx_port2, rx_port2, pcap1)
stream_id_4 = hPktgen.add_stream(tx_port2, rx_port2, pcap2)
stream_ids.append(stream_id_3)
stream_ids.append(stream_id_4)
# set pcap1 with mac protocol layer field vary configuration
stream_option1 = {
'pcap': pcap1,
'fields_config': {
'mac': {
'src': {
'action': 'inc',
'end': '00:00:00:00:00:FF',
'start': '00:00:00:00:00:00',
'step': 1}}},
'stream_config': {
'rate': 100,
'transmit_mode': TRANSMIT_CONT
}
}
# set stream option
hPktgen.config_stream(stream_id_1, stream_option1)
hPktgen.config_stream(stream_id_3, stream_option1)
# set pcap2 with ip protocol layer field vary configuration
stream_option2 = {
'pcap': pcap2,
'fields_config': {
'ip': {
'dst': {
'action': 'dec',
'end': '0.0.0.255',
'start': '0.0.0.1',
'step': 1},
'src': {
'action': 'random',
'end': '0.0.0.64',
'start': '0.0.0.1',
'step': 1}}},
'stream_config': {
'rate': 100,
'transmit_mode': TRANSMIT_CONT
}
}
# set stream option
hPktgen.config_stream(stream_id_2, stream_option2)
hPktgen.config_stream(stream_id_4, stream_option2)
# run testing scenario
traffic_option = {
'method': 'rfc2544',
'rate': 100,
'pdr': 0.001,
'drop_step': 1}
hPktgen.measure(stream_ids, traffic_opt)