for x in os.listdir(d):
if os.path.isdir(os.path.join(d, x)):
files.append(x + '/')
- elif x.endswith('.py') or x.endswith('yaml') or x.endswith('pcap') or x.endswith('cap'):
+ elif x.endswith( ('.py', 'yaml', 'pcap', 'cap', 'erf') ):
files.append(x)
# dir might not have the files
return rc
- def __push_remote (self, pcap_filename, port_id_list, ipg_usec, speedup, count, duration):
+ def __push_remote (self, pcap_filename, port_id_list, ipg_usec, speedup, count, duration, is_dual):
port_id_list = self.__ports(port_id_list)
rc = RC()
for port_id in port_id_list:
- rc.add(self.ports[port_id].push_remote(pcap_filename, ipg_usec, speedup, count, duration))
+
+ # for dual, provide the slave handler as well
+ slave_handler = self.ports[port_id ^ 0x1].handler if is_dual else ""
+
+ rc.add(self.ports[port_id].push_remote(pcap_filename, ipg_usec, speedup, count, duration, is_dual, slave_handler))
return rc
ipg_usec = None,
speedup = 1.0,
count = 1,
- duration = -1):
+ duration = -1,
+ is_dual = False):
"""
Push a remote server-reachable PCAP file
the path must be fullpath accessible to the server
duration: float
Limit runtime by duration in seconds
+
+ is_dual: bool
+ Inject from both directions.
+ requires ERF file with meta data for direction.
+ also requires that all the ports will be in master mode
+ with their adjacent ports as slaves
+
:raises:
+ :exc:`STLError`
validate_type('speedup', speedup, (float, int))
validate_type('count', count, int)
validate_type('duration', duration, (float, int))
+ validate_type('is_dual', is_dual, bool)
+
+ # for dual mode check that all are masters
+ if is_dual:
+ for port in ports:
+ master = port
+ slave = port ^ 0x1
+
+ if slave in ports:
+ raise STLError("dual mode: cannot provide adjacent ports ({0}, {1}) in a batch".format(master, slave))
+
+ if not slave in self.get_acquired_ports():
+ raise STLError("dual mode: port {0} must be owned as well".format(slave))
+
self.logger.pre_cmd("Pushing remote PCAP on port(s) {0}:".format(ports))
- rc = self.__push_remote(pcap_filename, ports, ipg_usec, speedup, count, duration)
+ rc = self.__push_remote(pcap_filename, ports, ipg_usec, speedup, count, duration, is_dual)
self.logger.post_cmd(rc)
if not rc:
parsing_opts.DURATION,
parsing_opts.IPG,
parsing_opts.SPEEDUP,
- parsing_opts.FORCE)
+ parsing_opts.FORCE,
+ parsing_opts.DUAL)
opts = parser.parse_args(line.split())
if not opts:
ipg_usec = opts.ipg_usec,
speedup = opts.speedup,
count = opts.count,
- duration = opts.duration)
+ duration = opts.duration,
+ is_dual = opts.dual)
else:
self.push_pcap(opts.file[0],
return self.ok()
@writeable
- def push_remote (self, pcap_filename, ipg_usec, speedup, count, duration):
+ def push_remote (self, pcap_filename, ipg_usec, speedup, count, duration, is_dual, slave_handler):
params = {"handler": self.handler,
"port_id": self.port_id,
"ipg_usec": ipg_usec if ipg_usec is not None else -1,
"speedup": speedup,
"count": count,
- "duration": duration}
+ "duration": duration,
+ "is_dual": is_dual,
+ "slave_handler": slave_handler}
rc = self.transmit("push_remote", params)
if rc.bad():
bps_L1 = calc_bps_L1(bps, pps)
bps_rx_L1 = calc_bps_L1(rx_bps, rx_pps)
snapshot['m_total_tx_bps_L1'] = bps_L1
- snapshot['m_percentage'] = (bps_L1 / self._port_obj.get_speed_bps()) * 100
+ snapshot['m_percentage'] = (bps_L1 / self._port_obj.get_speed_bps()) * 100.0
# TX line util not smoothed
diff_tx_pkts = snapshot.get('opackets', 0) - self.latest_stats.get('opackets', 0)
LOCKED = 24
PIN_CORES = 25
CORE_MASK = 26
+DUAL = 28
GLOBAL_STATS = 50
PORT_STATS = 51
'default': False,
'help': "file path should be interpeted by the server (remote file)"}),
+ DUAL: ArgumentPack(['--dual'],
+ {"action": "store_true",
+ 'default': False,
+ 'help': "Transmit in a dual mode - requires a slave attached to the port"}),
+
FILE_PATH: ArgumentPack(['-f'],
{'metavar': 'FILE',
'dest': 'file',
memset(&prevts, 0, sizeof(prevts));
- int records_for_erf_check = 10;
+ long records_for_erf_check = 10;
/* ERF is a little hard because there's no magic number */
}
-int erf_read(wtap *wth,char *p,uint32_t *sec,uint32_t *nsec)
+int erf_read(wtap *wth,char *p,uint32_t *sec,uint32_t *nsec, uint8_t *interface)
{
erf_header_t header;
int common_type = 0;
uint32_t frac =(ts &0xffffffff);
double usec_frac =(double)frac*(1000000000.0/(4294967296.0));
*nsec = (uint32_t) (usec_frac);
+ *interface = header.flags & 0x3;
return (g_ntohs(header.wlen));
}else{
return (-1);
bool CErfFileReader::ReadPacket(CCapPktRaw * lpPacket){
+ uint8_t interface;
wtap wth;
+
wth.fh = m_handle;
- int length;
- length=erf_read(&wth,lpPacket->raw,&lpPacket->time_sec,
- &lpPacket->time_nsec
- );
+ int length = erf_read(&wth,
+ lpPacket->raw,
+ &lpPacket->time_sec,
+ &lpPacket->time_nsec,
+ &interface);
if ( length >0 ) {
lpPacket->pkt_len =(uint16_t)length;
lpPacket->pkt_cnt++;
+ lpPacket->setInterface(interface);
return (true);
}
return (false);
TrexRpcCmdPushRemote::_run(const Json::Value ¶ms, Json::Value &result) {
uint8_t port_id = parse_port(params, result);
- std::string pcap_filename = parse_string(params, "pcap_filename", result);
- double ipg_usec = parse_double(params, "ipg_usec", result);
- double speedup = parse_double(params, "speedup", result);
- uint32_t count = parse_uint32(params, "count", result);
- double duration = parse_double(params, "duration", result);
+ std::string pcap_filename = parse_string(params, "pcap_filename", result);
+ double ipg_usec = parse_double(params, "ipg_usec", result);
+ double speedup = parse_double(params, "speedup", result);
+ uint32_t count = parse_uint32(params, "count", result);
+ double duration = parse_double(params, "duration", result);
+ bool is_dual = parse_bool(params, "is_dual", result, false);
+ std::string slave_handler = parse_string(params, "slave_handler", result, "");
TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
+ if (is_dual) {
+ TrexStatelessPort *slave = get_stateless_obj()->get_port_by_id(port_id ^ 0x1);
+
+ if (!slave->get_owner().verify(slave_handler)) {
+ generate_execute_err(result, "incorrect or missing slave port handler");
+ }
+ }
+
try {
- port->push_remote(pcap_filename, ipg_usec, speedup, count, duration);
+ port->push_remote(pcap_filename, ipg_usec, speedup, count, duration, is_dual);
} catch (const TrexException &ex) {
generate_execute_err(result, ex.what());
}
TrexStatelessPort::start_traffic(const TrexPortMultiplier &mul, double duration, bool force, uint64_t core_mask) {
/* command allowed only on state stream */
- verify_state(PORT_STATE_STREAMS);
+ verify_state(PORT_STATE_STREAMS, "start");
/* just making sure no leftovers... */
delete_streams_graph();
void
TrexStatelessPort::remove_rx_filters(void) {
/* only valid when IDLE or with streams and not TXing */
- verify_state(PORT_STATE_STREAMS);
+ verify_state(PORT_STATE_STREAMS, "remove_rx_filters");
for (auto entry : m_stream_table) {
get_stateless_obj()->m_rx_flow_stat.stop_stream(entry.second);
void
TrexStatelessPort::pause_traffic(void) {
- verify_state(PORT_STATE_TX);
+ verify_state(PORT_STATE_TX, "pause");
if (m_last_all_streams_continues == false) {
throw TrexException(" pause is supported when all streams are in continues mode ");
void
TrexStatelessPort::resume_traffic(void) {
- verify_state(PORT_STATE_PAUSE);
+ verify_state(PORT_STATE_PAUSE, "resume");
/* generate a message to all the relevant DP cores to start transmitting */
TrexStatelessCpToDpMsgBase *resume_msg = new TrexStatelessDpResume(m_port_id);
double factor;
- verify_state(PORT_STATE_TX | PORT_STATE_PAUSE);
+ verify_state(PORT_STATE_TX | PORT_STATE_PAUSE, "update");
/* generate a message to all the relevant DP cores to start transmitting */
double new_factor = calculate_effective_factor(mul, force);
double ipg_usec,
double speedup,
uint32_t count,
- double duration) {
+ double duration,
+ bool is_dual) {
/* command allowed only on state stream */
- verify_state(PORT_STATE_IDLE | PORT_STATE_STREAMS);
+ verify_state(PORT_STATE_IDLE | PORT_STATE_STREAMS, "push_remote");
/* check that file exists */
CCapReaderBase *reader;
ipg_usec,
speedup,
count,
- duration);
+ duration,
+ is_dual);
send_message_to_dp(tx_core, push_msg);
/* update subscribers */
}
bool
-TrexStatelessPort::verify_state(int state, bool should_throw) const {
+TrexStatelessPort::verify_state(int state, const char *cmd_name, bool should_throw) const {
if ( (state & m_port_state) == 0 ) {
if (should_throw) {
- throw TrexException("command cannot be executed on current state: '" + get_state_as_string() + "'");
+ std::stringstream ss;
+ ss << "command '" << cmd_name << "' cannot be executed on current state: '" << get_state_as_string() << "'";
+ throw TrexException(ss.str());
} else {
return false;
}
void
TrexStatelessPort::add_stream(TrexStream *stream) {
- verify_state(PORT_STATE_IDLE | PORT_STATE_STREAMS);
+ verify_state(PORT_STATE_IDLE | PORT_STATE_STREAMS, "add_stream");
get_stateless_obj()->m_rx_flow_stat.add_stream(stream);
void
TrexStatelessPort::remove_stream(TrexStream *stream) {
- verify_state(PORT_STATE_STREAMS);
+ verify_state(PORT_STATE_STREAMS, "remove_stream");
get_stateless_obj()->m_rx_flow_stat.del_stream(stream);
void
TrexStatelessPort::remove_and_delete_all_streams() {
- verify_state(PORT_STATE_IDLE | PORT_STATE_STREAMS);
+ verify_state(PORT_STATE_IDLE | PORT_STATE_STREAMS, "remove_and_delete_all_streams");
vector<TrexStream *> streams;
get_object_list(streams);
*
*/
void push_remote(const std::string &pcap_filename,
- double ipg_usec,
- double speedup,
- uint32_t count,
- double duration);
+ double ipg_usec,
+ double speedup,
+ uint32_t count,
+ double duration,
+ bool is_dual);
/**
* get the port state
return m_cores_id_list;
}
- bool verify_state(int state, bool should_throw = true) const;
+ bool verify_state(int state, const char *cmd_name, bool should_throw = true) const;
void change_state(port_state_e new_state);
const std::string &pcap_filename,
double ipg_usec,
double speedup,
- uint32_t count) {
+ uint32_t count,
+ bool is_dual) {
/* push pcap can only happen on an idle port from the core prespective */
assert(m_state == TrexStatelessDpPerPort::ppSTATE_IDLE);
pcap_filename,
ipg_usec,
speedup,
- count);
+ count,
+ is_dual);
if (!rc) {
m_core->free_node((CGenNode *)pcap_node);
return (false);
double ipg_usec,
double speedup,
uint32_t count,
- double duration) {
+ double duration,
+ bool is_dual) {
TrexStatelessDpPerPort * lp_port = get_port_db(port_id);
lp_port->set_event_id(event_id);
/* delegate the command to the port */
- bool rc = lp_port->push_pcap(port_id, pcap_filename, ipg_usec, speedup, count);
+ bool rc = lp_port->push_pcap(port_id, pcap_filename, ipg_usec, speedup, count, is_dual);
if (!rc) {
/* report back that we stopped */
CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingDpToCp(m_core->m_thread_id);
const std::string &pcap_filename,
double ipg_usec,
double speedup,
- uint32_t count) {
+ uint32_t count,
+ bool is_dual) {
std::stringstream ss;
m_type = CGenNode::PCAP_PKT;
m_src_port = 0;
m_port_id = port_id;
m_count = count;
-
+ m_is_dual = is_dual;
+
/* mark this node as slow path */
set_slow_path(true);
const std::string &pcap_filename,
double ipg_usec,
double speedup,
- uint32_t count);
+ uint32_t count,
+ bool is_dual);
bool stop_traffic(uint8_t port_id,
bool stop_on_id,
double ipg_usec,
double speedup,
uint32_t count,
- double duration);
+ double duration,
+ bool is_dual);
/**
const std::string &pcap_filename,
double ipg_usec,
double speedup,
- uint32_t count);
+ uint32_t count,
+ bool is_dual);
/**
* destroy the node cleaning up any data
*/
void destroy();
+ bool is_dual() const {
+ return m_is_dual;
+ }
+
/**
* advance - will read the next packet
*
}
}
+ if (is_dual()) {
+ uint8_t dir = m_raw_packet->getInterface() & 0x1;
+ set_mbuf_dir(dir);
+ }
}
/**
uint8_t m_port_id;
+ bool m_is_dual;
+
/* pad to match the size of CGenNode */
- uint8_t m_pad_end[33];
+ uint8_t m_pad_end[32];
} __rte_cache_aligned;
m_ipg_usec,
m_speedup,
m_count,
- m_duration);
+ m_duration,
+ m_is_dual);
return true;
}
m_ipg_usec,
m_speedup,
m_count,
- m_duration);
+ m_duration,
+ m_is_dual);
return new_msg;
}
double ipg_usec,
double speedup,
uint32_t count,
- double duration) : m_pcap_filename(pcap_filename) {
+ double duration,
+ bool is_dual) : m_pcap_filename(pcap_filename) {
+
m_port_id = port_id;
m_event_id = event_id;
m_ipg_usec = ipg_usec;
m_speedup = speedup;
m_count = count;
m_duration = duration;
+ m_is_dual = is_dual;
}
virtual bool handle(TrexStatelessDpCore *dp_core);
double m_duration;
uint32_t m_count;
uint8_t m_port_id;
+ bool m_is_dual;
};