pre test: Some small fixes
authorIdo Barnea <[email protected]>
Mon, 26 Sep 2016 13:26:37 +0000 (16:26 +0300)
committerIdo Barnea <[email protected]>
Wed, 5 Oct 2016 07:45:28 +0000 (10:45 +0300)
src/bp_sim.h
src/common/Network/Packet/Arp.h [new file with mode: 0644]
src/common/Network/Packet/MacAddress.h
src/latency.cpp
src/main_dpdk.cpp
src/pre_test.cpp
src/pre_test.h
src/test_pkt_gen.cpp

index 5f21ca2..d28968f 100755 (executable)
@@ -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 (file)
index 0000000..a16605b
--- /dev/null
@@ -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
index 6927233..7e872fd 100755 (executable)
@@ -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_
index 675cf80..76f12b4 100644 (file)
@@ -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;
index e1cbf9d..a6ea387 100644 (file)
@@ -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];
index b140111..0639d9c 100644 (file)
   limitations under the License.
 */
 
-#include <rte_arp.h>
 #include <rte_ethdev.h>
 #include <arpa/inet.h>
 #include <common/Network/Packet/EthernetHeader.h>
+#include <common/Network/Packet/Arp.h>
 #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);
         }
     }
 
index bd908cb..7bbeb40 100644 (file)
@@ -23,6 +23,7 @@
 #define __PRE_TEST_H__
 
 #include <iostream>
+#include <common/Network/Packet/Arp.h>
 #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();
     
index 14547c4..502e84d 100644 (file)
 
 #include <assert.h>
 #include <netinet/in.h>
-#include <rte_arp.h>
 #include <common/Network/Packet/TcpHeader.h>
 #include <common/Network/Packet/UdpHeader.h>
 #include <common/Network/Packet/IcmpHeader.h>
 #include <common/Network/Packet/IPHeader.h>
 #include <common/Network/Packet/IPv6Header.h>
 #include <common/Network/Packet/EthernetHeader.h>
+#include <common/Network/Packet/Arp.h>
 #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);
 }