189 lines
5.6 KiB
Python
189 lines
5.6 KiB
Python
|
#! /usr/bin/env python
|
||
|
|
||
|
# standard modules
|
||
|
import logging
|
||
|
import os
|
||
|
import sys
|
||
|
import time
|
||
|
|
||
|
# ostinato modules
|
||
|
# (user scripts using the installed package should prepend ostinato. i.e
|
||
|
# ostinato.core and ostinato.protocols)
|
||
|
from core import ost_pb, DroneProxy
|
||
|
from protocols.mac_pb2 import mac
|
||
|
from protocols.ip4_pb2 import ip4, Ip4
|
||
|
|
||
|
# initialize defaults
|
||
|
use_defaults = False
|
||
|
host_name = '127.0.0.1'
|
||
|
tx_port_number = 0
|
||
|
rx_port_number = 0
|
||
|
|
||
|
# setup logging
|
||
|
log = logging.getLogger(__name__)
|
||
|
logging.basicConfig(level=logging.INFO)
|
||
|
|
||
|
# command-line option/arg processing
|
||
|
if len(sys.argv) > 1:
|
||
|
if sys.argv[1] in ('-d', '--use-defaults'):
|
||
|
use_defaults = True
|
||
|
if sys.argv[1] in ('-h', '--help'):
|
||
|
print('%s [OPTION]...' % (sys.argv[0]))
|
||
|
print('Options:')
|
||
|
print(' -d --use-defaults run using default values')
|
||
|
print(' -h --help show this help')
|
||
|
sys.exit(0)
|
||
|
|
||
|
print('')
|
||
|
print('This example expects the following topology -')
|
||
|
print('')
|
||
|
print(' +-------+ +-------+')
|
||
|
print(' | |Tx--->----| |')
|
||
|
print(' | Drone | | DUT |')
|
||
|
print(' | |Rx---<----| |')
|
||
|
print(' +-------+ +-------+')
|
||
|
print('')
|
||
|
print('Drone has 2 ports connected to DUT. Packets sent on the Tx port')
|
||
|
print('are expected to be received back on the Rx port')
|
||
|
print('')
|
||
|
print('An easy way to simulate the above topology is to select the loopback')
|
||
|
print('port as both Tx and Rx ports')
|
||
|
print('')
|
||
|
|
||
|
if not use_defaults:
|
||
|
s = raw_input('Drone\'s Hostname/IP [%s]: ' % (host_name))
|
||
|
host_name = s or host_name
|
||
|
|
||
|
drone = DroneProxy(host_name)
|
||
|
|
||
|
try:
|
||
|
# connect to drone
|
||
|
log.info('connecting to drone(%s:%d)'
|
||
|
% (drone.hostName(), drone.portNumber()))
|
||
|
drone.connect()
|
||
|
|
||
|
# retreive port id list
|
||
|
log.info('retreiving port list')
|
||
|
port_id_list = drone.getPortIdList()
|
||
|
|
||
|
# retreive port config list
|
||
|
log.info('retreiving port config for all ports')
|
||
|
port_config_list = drone.getPortConfig(port_id_list)
|
||
|
|
||
|
if len(port_config_list.port) == 0:
|
||
|
log.warning('drone has no ports!')
|
||
|
sys.exit(1)
|
||
|
|
||
|
# print port list and get tx/rx port id
|
||
|
print('Port List')
|
||
|
print('---------')
|
||
|
for port in port_config_list.port:
|
||
|
print('%d.%s (%s)' % (port.port_id.id, port.name, port.description))
|
||
|
# use a loopback port as default tx/rx port
|
||
|
if ('lo' in port.name or 'loopback' in port.description.lower()):
|
||
|
tx_port_number = port.port_id.id
|
||
|
rx_port_number = port.port_id.id
|
||
|
|
||
|
if not use_defaults:
|
||
|
p = raw_input('Tx Port Id [%d]: ' % (tx_port_number))
|
||
|
if p:
|
||
|
tx_port_number = int(p)
|
||
|
|
||
|
p = raw_input('Rx Port Id [%d]: ' % (rx_port_number))
|
||
|
if p:
|
||
|
rx_port_number = int(p)
|
||
|
|
||
|
tx_port = ost_pb.PortIdList()
|
||
|
tx_port.port_id.add().id = tx_port_number;
|
||
|
|
||
|
rx_port = ost_pb.PortIdList()
|
||
|
rx_port.port_id.add().id = rx_port_number;
|
||
|
|
||
|
# add a stream
|
||
|
stream_id = ost_pb.StreamIdList()
|
||
|
stream_id.port_id.CopyFrom(tx_port.port_id[0])
|
||
|
stream_id.stream_id.add().id = 1
|
||
|
log.info('adding tx_stream %d' % stream_id.stream_id[0].id)
|
||
|
drone.addStream(stream_id)
|
||
|
|
||
|
# configure the stream
|
||
|
stream_cfg = ost_pb.StreamConfigList()
|
||
|
stream_cfg.port_id.CopyFrom(tx_port.port_id[0])
|
||
|
s = stream_cfg.stream.add()
|
||
|
s.stream_id.id = stream_id.stream_id[0].id
|
||
|
s.core.is_enabled = True
|
||
|
s.control.num_packets = 5
|
||
|
|
||
|
# setup stream protocols as mac:eth2:ip4:udp:payload
|
||
|
p = s.protocol.add()
|
||
|
p.protocol_id.id = ost_pb.Protocol.kMacFieldNumber
|
||
|
p.Extensions[mac].dst_mac = 0x001122334455
|
||
|
p.Extensions[mac].src_mac = 0x00aabbccddee
|
||
|
|
||
|
p = s.protocol.add()
|
||
|
p.protocol_id.id = ost_pb.Protocol.kEth2FieldNumber
|
||
|
|
||
|
p = s.protocol.add()
|
||
|
p.protocol_id.id = ost_pb.Protocol.kIp4FieldNumber
|
||
|
# reduce typing by creating a shorter reference to p.Extensions[ip4]
|
||
|
ip = p.Extensions[ip4]
|
||
|
ip.src_ip = 0x01020304
|
||
|
ip.dst_ip = 0x05060708
|
||
|
ip.dst_ip_mode = Ip4.e_im_inc_host
|
||
|
|
||
|
s.protocol.add().protocol_id.id = ost_pb.Protocol.kUdpFieldNumber
|
||
|
s.protocol.add().protocol_id.id = ost_pb.Protocol.kPayloadFieldNumber
|
||
|
|
||
|
log.info('configuring tx_stream %d' % stream_id.stream_id[0].id)
|
||
|
drone.modifyStream(stream_cfg)
|
||
|
|
||
|
# clear tx/rx stats
|
||
|
log.info('clearing tx/rx stats')
|
||
|
drone.clearStats(tx_port)
|
||
|
drone.clearStats(rx_port)
|
||
|
|
||
|
# start capture and transmit
|
||
|
log.info('starting capture')
|
||
|
drone.startCapture(rx_port)
|
||
|
log.info('starting transmit')
|
||
|
drone.startTransmit(tx_port)
|
||
|
|
||
|
# wait for transmit to finish
|
||
|
log.info('waiting for transmit to finish ...')
|
||
|
time.sleep(7)
|
||
|
|
||
|
# stop transmit and capture
|
||
|
log.info('stopping transmit')
|
||
|
drone.stopTransmit(tx_port)
|
||
|
log.info('stopping capture')
|
||
|
drone.stopCapture(rx_port)
|
||
|
|
||
|
# get tx/rx stats
|
||
|
log.info('retreiving stats')
|
||
|
tx_stats = drone.getStats(tx_port)
|
||
|
rx_stats = drone.getStats(rx_port)
|
||
|
|
||
|
#log.info('--> (tx_stats)' + tx_stats.__str__())
|
||
|
#log.info('--> (rx_stats)' + rx_stats.__str__())
|
||
|
log.info('tx pkts = %d, rx pkts = %d' %
|
||
|
(tx_stats.port_stats[0].tx_pkts, rx_stats.port_stats[0].rx_pkts))
|
||
|
|
||
|
# retrieve and dump received packets
|
||
|
log.info('getting Rx capture buffer')
|
||
|
buff = drone.getCaptureBuffer(rx_port.port_id[0])
|
||
|
drone.saveCaptureBuffer(buff, 'capture.pcap')
|
||
|
log.info('dumping Rx capture buffer')
|
||
|
os.system('tshark -r capture.pcap')
|
||
|
os.remove('capture.pcap')
|
||
|
|
||
|
# delete streams
|
||
|
log.info('deleting tx_stream %d' % stream_id.stream_id[0].id)
|
||
|
drone.deleteStream(stream_id)
|
||
|
|
||
|
# bye for now
|
||
|
drone.disconnect()
|
||
|
|
||
|
except Exception as ex:
|
||
|
log.exception(ex)
|
||
|
sys.exit(1)
|