From 2223955b8eb3b378c1ab79e3735ed340852b04b9 Mon Sep 17 00:00:00 2001 From: Ido Barnea Date: Mon, 26 Sep 2016 16:26:37 +0300 Subject: pre test: Some small fixes --- src/bp_sim.h | 8 ++++-- src/common/Network/Packet/Arp.h | 46 +++++++++++++++++++++++++++++++ src/common/Network/Packet/MacAddress.h | 11 +++++--- src/latency.cpp | 15 +++++----- src/main_dpdk.cpp | 32 ++++++++++++++++------ src/pre_test.cpp | 50 +++++++++++++++++----------------- src/pre_test.h | 3 +- src/test_pkt_gen.cpp | 24 ++++++++-------- 8 files changed, 128 insertions(+), 61 deletions(-) create mode 100644 src/common/Network/Packet/Arp.h diff --git a/src/bp_sim.h b/src/bp_sim.h index 5f21ca26..d28968f6 100755 --- a/src/bp_sim.h +++ b/src/bp_sim.h @@ -701,19 +701,19 @@ class CPerPortIPCfg { uint32_t get_mask() {return m_mask;} uint32_t get_def_gw() {return m_def_gw;} uint32_t get_vlan() {return m_vlan;} - bool is_loopback() {return m_is_loopback;} + bool grat_arp_needed() {return m_grat_arp_needed;} void set_ip(uint32_t val) {m_ip = val;} void set_mask(uint32_t val) {m_mask = val;} void set_def_gw(uint32_t val) {m_def_gw = val;} void set_vlan(uint16_t val) {m_vlan = val;} - void set_loopback(bool val) {m_is_loopback = val;} + void set_grat_arp_needed(bool val) {m_grat_arp_needed = val;} private: uint32_t m_def_gw; uint32_t m_ip; uint32_t m_mask; uint16_t m_vlan; - bool m_is_loopback; + bool m_grat_arp_needed; }; class CParserOption { @@ -767,6 +767,7 @@ public: m_run_mode = RUN_MODE_INVALID; m_l_pkt_mode = 0; m_rx_thread_enabled = false; + m_arp_ref_per = 120; // in seconds } @@ -793,6 +794,7 @@ public: uint8_t m_l_pkt_mode; uint8_t m_learn_mode; uint16_t m_debug_pkt_proto; + uint16_t m_arp_ref_per; bool m_rx_thread_enabled; trex_run_mode_e m_run_mode; diff --git a/src/common/Network/Packet/Arp.h b/src/common/Network/Packet/Arp.h new file mode 100644 index 00000000..a16605bd --- /dev/null +++ b/src/common/Network/Packet/Arp.h @@ -0,0 +1,46 @@ +/* +Copyright (c) 2016-2016 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#ifndef _ARP_H_ +#define _ARP_H_ +#include "MacAddress.h" + +#pragma pack(push, 1) +class ArpHdr { + public: + enum arp_hdr_enum_e { + ARP_HDR_HRD_ETHER = 1, + ARP_HDR_OP_REQUEST = 1, /* request to resolve address */ + ARP_HDR_OP_REPLY = 2, /* response to previous request */ + ARP_HDR_OP_REVREQUEST = 3, /* request proto addr given hardware */ + ARP_HDR_OP_REVREPLY = 4, /* response giving protocol address */ + ARP_HDR_OP_INVREQUEST = 5, /* request to identify peer */ + ARP_HDR_OP_INVREPLY = 6, /* response identifying peer */ + }; + + public: + uint16_t m_arp_hrd; /* format of hardware address */ + uint16_t m_arp_pro; /* format of protocol address */ + uint8_t m_arp_hln; /* length of hardware address */ + uint8_t m_arp_pln; /* length of protocol address */ + uint16_t m_arp_op; /* ARP opcode (command) */ + MacAddress m_arp_sha; /**< sender hardware address */ + uint32_t m_arp_sip; /**< sender IP address */ + MacAddress m_arp_tha; /**< target hardware address */ + uint32_t m_arp_tip; /**< target IP address */ +}; +#pragma pack(pop) + +#endif diff --git a/src/common/Network/Packet/MacAddress.h b/src/common/Network/Packet/MacAddress.h index 69272339..7e872fd6 100755 --- a/src/common/Network/Packet/MacAddress.h +++ b/src/common/Network/Packet/MacAddress.h @@ -19,7 +19,10 @@ limitations under the License. #include "CPktCmn.h" - +#ifndef ETHER_ADDR_LEN +#define ETHER_ADDR_LEN 6 /**< Length of Ethernet address. */ +#endif + class MacAddress { public: @@ -44,7 +47,7 @@ public: a5); }; - MacAddress(uint8_t macAddr[6]) + MacAddress(uint8_t macAddr[ETHER_ADDR_LEN]) { set(macAddr[0], macAddr[1], @@ -97,7 +100,7 @@ public: bool operator == (const MacAddress& rhs) const { - for(int i=0; i<6; i++) + for(int i = 0; i < ETHER_ADDR_LEN; i++) { if(data[i] != rhs.data[i]) return false; @@ -124,7 +127,7 @@ public: } public: - uint8_t data[6]; + uint8_t data[ETHER_ADDR_LEN]; }; #endif //_MAC_ADDRESS_H_ diff --git a/src/latency.cpp b/src/latency.cpp index 675cf80a..76f12b46 100644 --- a/src/latency.cpp +++ b/src/latency.cpp @@ -583,8 +583,7 @@ void CLatencyManager::send_pkt_all_ports(){ void CLatencyManager::send_grat_arp_all_ports() { for (int port_id = 0; port_id < m_max_ports; port_id++) { - // if port is connected in loopback, no need to send. It will only confuse our ingress counters. - if (CGlobalInfo::m_options.m_ip_cfg[port_id].is_loopback()) + if (! CGlobalInfo::m_options.m_ip_cfg[port_id].grat_arp_needed()) continue; CLatencyManagerPerPort * lp = &m_ports[port_id]; @@ -750,10 +749,12 @@ void CLatencyManager::start(int iter, bool activate_watchdog) { node->m_time = now_sec(); /* 1/cps rate */ m_p_queue.push(node); - node = new CGenNode(); - node->m_type = CGenNode::GRAT_ARP; /* gratuitous ARP */ - node->m_time = now_sec() + 120; - m_p_queue.push(node); + if (CGlobalInfo::m_options.m_arp_ref_per > 0) { + node = new CGenNode(); + node->m_type = CGenNode::GRAT_ARP; /* gratuitous ARP */ + node->m_time = now_sec() + CGlobalInfo::m_options.m_arp_ref_per; + m_p_queue.push(node); + } bool do_try_rx_queue = CGlobalInfo::m_options.preview.get_vm_one_queue_enable() ? true : false; @@ -806,7 +807,7 @@ void CLatencyManager::start(int iter, bool activate_watchdog) { m_cpu_dp_u.start_work1(); send_grat_arp_all_ports(); m_p_queue.pop(); - node->m_time += 120; // every two minutes + node->m_time += CGlobalInfo::m_options.m_arp_ref_per; m_p_queue.push(node); m_cpu_dp_u.commit1(); break; diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index e1cbf9de..a6ea3876 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -544,6 +544,7 @@ enum { OPT_HELP, OPT_ALLOW_COREDUMP, OPT_CHECKSUM_OFFLOAD, OPT_CLOSE, + OPT_ARP_REF_PER, }; /* these are the argument types: @@ -601,6 +602,7 @@ static CSimpleOpt::SOption parser_options[] = { OPT_ALLOW_COREDUMP , "--allow-coredump", SO_NONE }, { OPT_CHECKSUM_OFFLOAD, "--checksum-offload", SO_NONE }, { OPT_CLOSE, "--close-at-end", SO_NONE }, + { OPT_ARP_REF_PER, "--arp-refresh-period", SO_REQ_SEP }, SO_END_OF_OPTIONS }; @@ -619,7 +621,7 @@ static int usage(){ printf(" --client_cfg [file] : YAML file which describes clients configuration\n"); printf(" \n\n"); - printf(" -c [number of threads] : default is 1. number of threads to allocate for each dual ports. \n"); + printf(" -c [number of threads] : Default is 1. Number of threads to allocate for each port pair. \n"); printf(" \n"); printf(" -s : run only one data path core. for debug\n"); printf(" \n"); @@ -697,16 +699,17 @@ static int usage(){ printf(" This it temporary option. Will be removed in the future.\n"); printf(" --no-key : daemon mode, don't get input from keyboard \n"); printf(" --no-flow-control-change : By default TRex disables flow-control. If this option is given, it does not touch it\n"); - printf(" --prefix : for multi trex, each instance should have a different name \n"); - printf(" --mbuf-factor : factor for packet memory \n"); + printf(" --prefix : For multi trex, each instance should have a different name \n"); + printf(" --mbuf-factor : Factor for packet memory \n"); printf(" \n"); - printf(" --no-watchdog : disable watchdog \n"); + printf(" --no-watchdog : Disable watchdog \n"); printf(" \n"); - printf(" --allow-coredump : allow a creation of core dump \n"); + printf(" --allow-coredump : Allow a creation of core dump \n"); printf(" \n"); - printf(" --vm-sim : simulate vm with driver of one input queue and one output queue \n"); + printf(" --vm-sim : Simulate vm with driver of one input queue and one output queue \n"); printf(" \n"); - printf(" --checksum-offload : enable IP, TCP and UDP tx checksum offloading with DPDK. This requires all used interfaces to support this \n"); + printf(" --checksum-offload : Enable IP, TCP and UDP tx checksum offloading with DPDK. This requires all used interfaces to support this \n"); + printf(" --arp-refresh-period : Period in seconds between sending of gratuitous ARP for out addresses. Value of 0, means 'never send'\n"); printf(" \n"); printf(" Examples: "); printf(" basic trex run for 10 sec and multiplier of x10 \n"); @@ -984,6 +987,10 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t case OPT_CLOSE: po->preview.setCloseEnable(true); break; + case OPT_ARP_REF_PER: + sscanf(args.OptionArg(),"%d", &tmp_data); + po->m_arp_ref_per=(uint16_t)tmp_data; + break; default: usage(); @@ -2975,7 +2982,7 @@ public: }; -// Before starting, send gratitues ARP on our addresses, and try to resolve dst MAC addresses. +// Before starting, send gratuitous ARP on our addresses, and try to resolve dst MAC addresses. void CGlobalTRex::pre_test() { CPretest pretest(m_max_ports); bool resolve_needed = false; @@ -2993,6 +3000,10 @@ void CGlobalTRex::pre_test() { if (! memcmp( CGlobalInfo::m_options.m_mac_addr[port_id].u.m_mac.src, empty_mac, ETHER_ADDR_LEN)) { rte_eth_macaddr_get(port_id, (struct ether_addr *)&CGlobalInfo::m_options.m_mac_addr[port_id].u.m_mac.src); + CGlobalInfo::m_options.m_ip_cfg[port_id].set_grat_arp_needed(true); + } else { + // If we got src MAC from config file, do not send gratuitous ARP for it (for compatibility with old behaviour) + CGlobalInfo::m_options.m_ip_cfg[port_id].set_grat_arp_needed(false); } pretest.set_port_params(port_id, CGlobalInfo::m_options.m_ip_cfg[port_id] , CGlobalInfo::m_options.m_mac_addr[port_id].u.m_mac.src @@ -3007,6 +3018,7 @@ void CGlobalTRex::pre_test() { uint8_t mac[ETHER_ADDR_LEN]; for (int port_id = 0; port_id < m_max_ports; port_id++) { if (! memcmp(CGlobalInfo::m_options.m_mac_addr[port_id].u.m_mac.dest, empty_mac, ETHER_ADDR_LEN)) { + // we don't have dest MAC. Get it from what we resolved. uint32_t ip = CGlobalInfo::m_options.m_ip_cfg[port_id].get_def_gw(); if (! pretest.get_mac(port_id, ip, mac)) { fprintf(stderr, "Failed resolving dest MAC for default gateway:%d.%d.%d.%d on port %d\n" @@ -3014,7 +3026,9 @@ void CGlobalTRex::pre_test() { exit(1); } memcpy(CGlobalInfo::m_options.m_mac_addr[port_id].u.m_mac.dest, mac, ETHER_ADDR_LEN); - CGlobalInfo::m_options.m_ip_cfg[port_id].set_loopback(pretest.is_loopback(port_id)); + // if port is connected in loopback, no need to send gratuitous ARP. It will only confuse our ingress counters. + if (pretest.is_loopback(port_id)) + CGlobalInfo::m_options.m_ip_cfg[port_id].set_grat_arp_needed(false); } CPhyEthIF *pif = &m_ports[port_id]; diff --git a/src/pre_test.cpp b/src/pre_test.cpp index b1401112..0639d9c8 100644 --- a/src/pre_test.cpp +++ b/src/pre_test.cpp @@ -19,10 +19,10 @@ limitations under the License. */ -#include #include #include #include +#include #include "common/basic_utils.h" #include "bp_sim.h" #include "main_dpdk.h" @@ -111,22 +111,22 @@ int CPretest::handle_rx(int port_id, int queue_id) { rte_mbuf_t * m = rx_pkts[i]; int pkt_size = rte_pktmbuf_pkt_len(m); uint8_t *p = rte_pktmbuf_mtod(m, uint8_t *); - struct arp_hdr *arp; + ArpHdr *arp; CPretestPortInfo *port = &m_port_info[port_id]; if (is_arp(p, pkt_size, arp)) { - if (arp->arp_op == htons(ARP_OP_REQUEST)) { - if (verbose >= 3) { - fprintf(stdout, "RX ARP request on port %d queue %d sip:0x%08x tip:0x%08x\n", port_id, queue_id - , ntohl(arp->arp_data.arp_sip) - , ntohl(arp->arp_data.arp_tip)); - } + if (arp->m_arp_op == htons(ArpHdr::ARP_HDR_OP_REQUEST)) { + if (verbose >= 3) { + fprintf(stdout, "RX ARP request on port %d queue %d sip:0x%08x tip:0x%08x\n", port_id, queue_id + , ntohl(arp->m_arp_sip) + , ntohl(arp->m_arp_tip)); + } // is this request for our IP? - if (ntohl(arp->arp_data.arp_tip) == port->m_ip) { + if (ntohl(arp->m_arp_tip) == port->m_ip) { // If our request(i.e. we are connected in loopback) // , do a shortcut, and write info directly to asking port uint8_t magic[5] = {0x1, 0x3, 0x5, 0x7, 0x9}; - if (! memcmp((uint8_t *)&arp->arp_data.arp_tha, magic, 5)) { - uint8_t sent_port_id = arp->arp_data.arp_tha.addr_bytes[5]; + if (! memcmp((uint8_t *)&arp->m_arp_tha.data, magic, 5)) { + uint8_t sent_port_id = arp->m_arp_tha.data[5]; if ((sent_port_id < m_max_ports) && (m_port_info[sent_port_id].m_def_gw == port->m_ip)) { memcpy(m_port_info[sent_port_id].m_dst_mac, port->m_src_mac, ETHER_ADDR_LEN); @@ -137,19 +137,19 @@ int CPretest::handle_rx(int port_id, int queue_id) { } else { // ARP request not to our IP. At the moment, we ignore this. } - } else { - if (arp->arp_op == htons(ARP_OP_REPLY)) { - if (verbose >= 3) { - fprintf(stdout, "RX ARP response on port %d queue %d sip:0x%08x tip:0x%08x\n", port_id, queue_id - , ntohl(arp->arp_data.arp_sip) - , ntohl(arp->arp_data.arp_tip)); - } - // If this is response to our request, update our tables - if (port->m_def_gw == ntohl(arp->arp_data.arp_sip)) { - port->set_dst_mac((uint8_t *)&arp->arp_data.arp_sha); - } + } else { + if (arp->m_arp_op == htons(ArpHdr::ARP_HDR_OP_REPLY)) { + if (verbose >= 3) { + fprintf(stdout, "RX ARP response on port %d queue %d sip:0x%08x tip:0x%08x\n", port_id, queue_id + , ntohl(arp->m_arp_sip) + , ntohl(arp->m_arp_tip)); + } + // If this is response to our request, update our tables + if (port->m_def_gw == ntohl(arp->m_arp_sip)) { + port->set_dst_mac((uint8_t *)&arp->m_arp_sha); } } + } } rte_pktmbuf_free(m); @@ -256,7 +256,7 @@ void CPretest::send_grat_arp_all() { } } -bool CPretest::is_arp(const uint8_t *p, uint16_t pkt_size, struct arp_hdr *&arp) { +bool CPretest::is_arp(const uint8_t *p, uint16_t pkt_size, ArpHdr *&arp) { EthernetHeader *m_ether = (EthernetHeader *)p; if ((pkt_size < 60) || @@ -265,12 +265,12 @@ bool CPretest::is_arp(const uint8_t *p, uint16_t pkt_size, struct arp_hdr *&arp) return false; if (m_ether->getNextProtocol() == EthernetHeader::Protocol::ARP) { - arp = (struct arp_hdr *)(p + 14); + arp = (ArpHdr *)(p + 14); } else { if (m_ether->getVlanProtocol() != EthernetHeader::Protocol::ARP) { return false; } else { - arp = (struct arp_hdr *)(p + 18); + arp = (ArpHdr *)(p + 18); } } diff --git a/src/pre_test.h b/src/pre_test.h index bd908cbb..7bbeb40d 100644 --- a/src/pre_test.h +++ b/src/pre_test.h @@ -23,6 +23,7 @@ #define __PRE_TEST_H__ #include +#include #include "bp_sim.h" #include "trex_defs.h" @@ -68,7 +69,7 @@ class CPretest { bool resolve_all(); void send_arp_req(uint16_t port, bool is_grat); void send_grat_arp_all(); - bool is_arp(const uint8_t *p, uint16_t pkt_size, struct arp_hdr *&arp); + bool is_arp(const uint8_t *p, uint16_t pkt_size, ArpHdr *&arp); void dump(FILE *fd); void test(); diff --git a/src/test_pkt_gen.cpp b/src/test_pkt_gen.cpp index 14547c41..502e84dc 100644 --- a/src/test_pkt_gen.cpp +++ b/src/test_pkt_gen.cpp @@ -21,13 +21,13 @@ #include #include -#include #include #include #include #include #include #include +#include #include "rx_check_header.h" #include "test_pkt_gen.h" @@ -267,18 +267,18 @@ void CTestPktGen::create_arp_req(uint8_t *pkt, uint32_t sip, uint32_t tip, uint8 memcpy(pkt, &l2_proto, sizeof(l2_proto)); pkt += 2; - struct arp_hdr *arp = (struct arp_hdr *)pkt; - arp->arp_hrd = htons(ARP_HRD_ETHER); // Format of hardware address - arp->arp_pro = htons(EthernetHeader::Protocol::IP); // Format of protocol address - arp->arp_hln = ETHER_ADDR_LEN; // Length of hardware address - arp->arp_pln = 4; // Length of protocol address - arp->arp_op = htons(ARP_OP_REQUEST); // ARP opcode (command) + ArpHdr *arp = (ArpHdr *)pkt; + arp->m_arp_hrd = htons(ArpHdr::ARP_HDR_HRD_ETHER); // Format of hardware address + arp->m_arp_pro = htons(EthernetHeader::Protocol::IP); // Format of protocol address + arp->m_arp_hln = ETHER_ADDR_LEN; // Length of hardware address + arp->m_arp_pln = 4; // Length of protocol address + arp->m_arp_op = htons(ArpHdr::ARP_HDR_OP_REQUEST); // ARP opcode (command) - memcpy(&arp->arp_data.arp_sha, src_mac, ETHER_ADDR_LEN); // Sender MAC address - arp->arp_data.arp_sip = htonl(sip); // Sender IP address + memcpy(&arp->m_arp_sha.data, src_mac, ETHER_ADDR_LEN); // Sender MAC address + arp->m_arp_sip = htonl(sip); // Sender IP address uint8_t magic[5] = {0x1, 0x3, 0x5, 0x7, 0x9}; - memcpy(&arp->arp_data.arp_tha, magic, 5); // Target MAC address - arp->arp_data.arp_tha.addr_bytes[5] = port; - arp->arp_data.arp_tip = htonl(tip); + memcpy(&arp->m_arp_tha.data, magic, 5); // Target MAC address + arp->m_arp_tha.data[5] = port; + arp->m_arp_tip = htonl(tip); } -- cgit 1.2.3-korg