diff options
-rwxr-xr-x | linux_dpdk/ws_main.py | 1 | ||||
-rwxr-xr-x | src/bp_sim.cpp | 24 | ||||
-rw-r--r-- | src/main_dpdk.cpp | 10 | ||||
-rw-r--r-- | src/trex_client_config.cpp | 66 | ||||
-rw-r--r-- | src/trex_client_config.h | 159 | ||||
-rwxr-xr-x | src/utl_yaml.cpp | 26 | ||||
-rwxr-xr-x | src/utl_yaml.h | 3 |
7 files changed, 210 insertions, 79 deletions
diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py index dde94dc4..5bc00719 100755 --- a/linux_dpdk/ws_main.py +++ b/linux_dpdk/ws_main.py @@ -100,6 +100,7 @@ main_src = SrcGroup(dir='src', 'global_io_mode.cpp', 'main_dpdk.cpp', 'trex_watchdog.cpp', + 'trex_client_config.cpp', 'debug.cpp', 'flow_stat.cpp', 'flow_stat_parser.cpp', diff --git a/src/bp_sim.cpp b/src/bp_sim.cpp index 2ebffb0d..95f9e2fa 100755 --- a/src/bp_sim.cpp +++ b/src/bp_sim.cpp @@ -5049,17 +5049,25 @@ void CErfIF::add_vlan(uint16_t vlan_id) { void CErfIF::apply_client_config(CGenNode *node, pkt_dir_t dir) { uint8_t *p =(uint8_t *)m_raw->raw; - uint16_t vlan_id; - if (dir == CLIENT_SIDE) { - memcpy(p, node->m_client_cfg->m_initiator.m_dst_mac, 6); - vlan_id = node->m_client_cfg->m_responder.m_vlan; - } else { - memcpy(p, node->m_client_cfg->m_responder.m_dst_mac, 6); - vlan_id = node->m_client_cfg->m_responder.m_vlan; + ClientCfgDir &cfg_dir = ( (dir == CLIENT_SIDE) ? node->m_client_cfg->m_initiator : node->m_client_cfg->m_responder); + + /* dst mac */ + if (cfg_dir.has_dst_mac_addr()) { + memcpy(p, cfg_dir.get_dst_mac_addr(), 6); + } + + /* src mac */ + if (cfg_dir.has_src_mac_addr()) { + memcpy(p + 6, cfg_dir.get_src_mac_addr(), 6); } - add_vlan(vlan_id); + /* VLAN */ + if (cfg_dir.has_vlan()) { + add_vlan(cfg_dir.get_vlan()); + } + + } diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 0200df92..21612901 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -1016,7 +1016,7 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t "if you think it is important,open a defect \n"); } - if (CGlobalInfo::get_vlan_mode_enable() && (po->client_cfg_file != "") ) { + if (po->preview.get_vlan_mode_enable() && (po->client_cfg_file != "") ) { parse_err("--vlan and --client_cfg cannot be combined"); } @@ -4204,12 +4204,10 @@ int CGlobalTRex::start_master_statefull() { m_fl.Create(); m_fl.load_from_yaml(CGlobalInfo::m_options.cfg_file,get_cores_tx()); - if (CGlobalInfo::m_options.mac_file != "") { + + if (CGlobalInfo::m_options.client_cfg_file != "") { + m_fl.load_client_config_file(CGlobalInfo::m_options.client_cfg_file); CGlobalInfo::m_options.preview.set_mac_ip_mapping_enable(true); - m_fl.load_from_mac_file(CGlobalInfo::m_options.mac_file); - m_fl.m_mac_info.set_configured(true); - } else { - m_fl.m_mac_info.set_configured(false); } m_expected_pps = m_fl.get_total_pps(); diff --git a/src/trex_client_config.cpp b/src/trex_client_config.cpp index e726d47d..bb2b7772 100644 --- a/src/trex_client_config.cpp +++ b/src/trex_client_config.cpp @@ -36,6 +36,9 @@ ClientCfgEntry::dump() const { std::cout << "IP start: " << ip_to_str(m_ip_start) << "\n"; std::cout << "IP end: " << ip_to_str(m_ip_end) << "\n"; + //m_cfg.dump(); + + #if 0 std::cout << "Init. MAC addr: "; for (int i = 0; i < 6; i++) { printf("%lx:", ( (m_initiator.m_dst_mac >> ( (6-i) * 8)) & 0xFF ) ); @@ -51,6 +54,7 @@ ClientCfgEntry::dump() const { std::cout << "\n"; std::cout << "Res. VLAN: " << m_responder.m_vlan << "\n"; + #endif } @@ -69,7 +73,7 @@ ClientCfgDB::load_yaml_file(const std::string &filename) { m_filename = filename; if (!utl_is_file_exists(filename)){ - ss << "file does not exists"; + ss << "*** file '" << filename << "' does not exists"; throw std::runtime_error(ss.str()); } @@ -98,7 +102,7 @@ ClientCfgDB::load_yaml_file(const std::string &filename) { parse_single_group(parser, groups[i]); } - verify(); + verify(parser); m_is_empty = false; @@ -126,37 +130,43 @@ ClientCfgDB::parse_single_group(YAMLParserWrapper &parser, const YAML::Node &nod const YAML::Node &init = parser.parse_map(node, "initiator"); const YAML::Node &resp = parser.parse_map(node, "responder"); - /* parse MACs */ - group.m_initiator.m_dst_mac = parser.parse_mac_addr(init, "dst_mac"); - group.m_responder.m_dst_mac = parser.parse_mac_addr(resp, "dst_mac"); + parse_dir(parser, init, group.m_cfg.m_initiator); + parse_dir(parser, resp, group.m_cfg.m_responder); - if (m_under_vlan) { - group.m_initiator.m_vlan = parser.parse_uint(init, "vlan", 0, 0xfff); - group.m_responder.m_vlan = parser.parse_uint(resp, "vlan", 0, 0xfff); - } else { - if (init.FindValue("vlan")) { - parser.parse_err("VLAN config was disabled", init["vlan"]); - } - if (resp.FindValue("vlan")) { - parser.parse_err("VLAN config was disabled", resp["vlan"]); - } - } - - - group.m_count = parser.parse_uint(node, "count"); + + group.m_count = parser.parse_uint(node, "count", 0, UINT64_MAX, 1); /* add to map with copying */ m_groups[group.m_ip_start] = group; } +void +ClientCfgDB::parse_dir(YAMLParserWrapper &parser, const YAML::Node &node, ClientCfgDir &dir) { + if (node.FindValue("src_mac")) { + dir.set_dst_mac_addr(parser.parse_mac_addr(node, "src_mac")); + } + + if (node.FindValue("dst_mac")) { + dir.set_dst_mac_addr(parser.parse_mac_addr(node, "dst_mac")); + } + + if (m_under_vlan) { + dir.set_vlan(parser.parse_uint(node, "vlan", 0, 0xfff)); + } else { + if (node.FindValue("vlan")) { + parser.parse_err("VLAN config was disabled", node["vlan"]); + } + } +} + /** * sanity checks * * @author imarom (28-Jun-16) */ void -ClientCfgDB::verify() const { +ClientCfgDB::verify(const YAMLParserWrapper &parser) const { std::stringstream ss; uint32_t monotonic = 0; @@ -168,7 +178,7 @@ ClientCfgDB::verify() const { if ( (monotonic > 0 ) && (group.m_ip_start <= monotonic) ) { ss << "IP '" << ip_to_str(group.m_ip_start) << "' - '" << ip_to_str(group.m_ip_end) << "' overlaps with other groups"; - yaml_parse_err(ss.str()); + parser.parse_err(ss.str()); } monotonic = group.m_ip_end; @@ -240,17 +250,3 @@ ClientCfgDB::lookup(const std::string &ip) { } -void -ClientCfgDB::yaml_parse_err(const std::string &err, const YAML::Mark *mark) const { - std::stringstream ss; - - if (mark) { - ss << "\n*** '" << m_filename << "' - YAML parsing error at line " << mark->line << ": "; - } else { - ss << "\n*** '" << m_filename << "' - YAML parsing error: "; - } - - ss << err; - throw std::runtime_error(ss.str()); -} - diff --git a/src/trex_client_config.h b/src/trex_client_config.h index b6e7d32d..a0c883d8 100644 --- a/src/trex_client_config.h +++ b/src/trex_client_config.h @@ -27,27 +27,138 @@ limitations under the License. class YAMLParserWrapper; + +/** + * client configuration per direction + * + * @author imarom (29-Jun-16) + */ +class ClientCfgDir { + +private: + enum { + HAS_SRC_MAC = 0x1, + HAS_DST_MAC = 0x2, + HAS_VLAN = 0x4, + }; + + uint8_t m_src_mac[6]; + uint8_t m_dst_mac[6]; + uint16_t m_vlan; + uint8_t m_bitfield; + + +public: + ClientCfgDir() { + m_bitfield = 0; + } + + bool has_src_mac_addr() const { + return (m_bitfield & HAS_SRC_MAC); + } + + bool has_dst_mac_addr() const { + return (m_bitfield & HAS_DST_MAC); + } + bool has_vlan() const { + return (m_bitfield & HAS_VLAN); + } + + void set_src_mac_addr(uint64_t mac_addr) { + for (int i = 0; i < 6; i++) { + m_src_mac[i] = ( mac_addr >> ((5 - i) * 8) ) & 0xFF; + } + m_bitfield |= HAS_SRC_MAC; + } + + void set_dst_mac_addr(uint64_t mac_addr) { + for (int i = 0; i < 6; i++) { + m_dst_mac[i] = ( mac_addr >> ((5 - i) * 8) ) & 0xFF; + } + m_bitfield |= HAS_DST_MAC; + } + + void set_vlan(uint16_t vlan_id) { + m_vlan = vlan_id; + m_bitfield |= HAS_VLAN; + } + + /* updates a configuration with a group index member */ + + void update(uint32_t index) { + if (has_src_mac_addr()) { + mac_add(m_src_mac, index); + } + + if (has_dst_mac_addr()) { + mac_add(m_dst_mac, index); + } + } + + const uint8_t *get_src_mac_addr() { + assert(has_src_mac_addr()); + return m_src_mac; + } + + const uint8_t *get_dst_mac_addr() { + assert(has_dst_mac_addr()); + return m_dst_mac; + } + + uint16_t get_vlan() { + assert(has_vlan()); + return m_vlan; + } + +private: + /** + * transform MAC address to uint64_t + * performs add and return to MAC format + * + */ + void mac_add(uint8_t *mac, uint32_t i) { + uint64_t tmp = 0; + + for (int i = 0; i < 6; i++) { + tmp <<= 8; + tmp |= mac[i]; + } + + tmp += i; + + for (int i = 0; i < 6; i++) { + mac[i] = ( tmp >> ((5 - i) * 8) ) & 0xFF; + } + + } +}; + /** * single client config * */ class ClientCfg { + public: - struct dir_st { - uint8_t m_dst_mac[6]; - uint16_t m_vlan; - }; - - dir_st m_initiator; - dir_st m_responder; + + void update(uint32_t index) { + m_initiator.update(index); + m_responder.update(index); + } + + ClientCfgDir m_initiator; + ClientCfgDir m_responder; }; +/******************************** internal section ********************************/ + /** * describes a single client config * entry loaded from the config file * */ class ClientCfgEntry { + public: ClientCfgEntry() { @@ -65,6 +176,7 @@ public: m_iterator = 0; } + /** * assings a client config from the group * it will advance MAC addresses andf etc. @@ -74,37 +186,23 @@ public: * @param info */ void assign(ClientCfg &info) { - - /* assigns MAC addrs as big endian */ - for (int i = 0; i < 6; i++) { - info.m_initiator.m_dst_mac[i] = ( (m_initiator.m_dst_mac + m_iterator) >> ((5 - i) * 8) ) & 0xFF; - info.m_responder.m_dst_mac[i] = ( (m_responder.m_dst_mac + m_iterator) >> ((5 - i) * 8) ) & 0xFF; - } - - info.m_initiator.m_vlan = m_initiator.m_vlan; - info.m_responder.m_vlan = m_responder.m_vlan; - + info = m_cfg; + info.update(m_iterator); + /* advance for the next assign */ m_iterator = (m_iterator + 1) % m_count; } public: - uint32_t m_ip_start; - uint32_t m_ip_end; - - struct cfg_dir_st { - //uint64_t m_src_mac; - uint64_t m_dst_mac; - uint16_t m_vlan; - }; + uint32_t m_ip_start; + uint32_t m_ip_end; - cfg_dir_st m_initiator; - cfg_dir_st m_responder; + ClientCfg m_cfg; uint32_t m_count; private: - uint32_t m_iterator; + uint32_t m_iterator; }; /** @@ -147,13 +245,13 @@ public: private: void parse_single_group(YAMLParserWrapper &parser, const YAML::Node &node); - void yaml_parse_err(const std::string &err, const YAML::Mark *mark = NULL) const; + void parse_dir(YAMLParserWrapper &parser, const YAML::Node &node, ClientCfgDir &dir); /** * verify the YAML file loaded in valid * */ - void verify() const; + void verify(const YAMLParserWrapper &parser) const; /* maps the IP start value to client groups */ std::map<uint32_t, ClientCfgEntry> m_groups; @@ -165,3 +263,4 @@ private: }; #endif /* __TREX_CLIENT_CONFIG_H__ */ + diff --git a/src/utl_yaml.cpp b/src/utl_yaml.cpp index 22772ffe..444031c6 100755 --- a/src/utl_yaml.cpp +++ b/src/utl_yaml.cpp @@ -250,6 +250,15 @@ YAMLParserWrapper::parse_ip(const YAML::Node &node, const std::string &name) { } uint64_t +YAMLParserWrapper::parse_mac_addr(const YAML::Node &node, const std::string &name, uint64_t def) { + if (!node.FindValue(name)) { + return def; + } + + return parse_mac_addr(node, name); +} + +uint64_t YAMLParserWrapper::parse_mac_addr(const YAML::Node &node, const std::string &name) { std::string mac_str; @@ -275,6 +284,15 @@ YAMLParserWrapper::parse_mac_addr(const YAML::Node &node, const std::string &nam } uint64_t +YAMLParserWrapper::parse_uint(const YAML::Node &node, const std::string &name, uint64_t low, uint64_t high, uint64_t def) { + if (!node.FindValue(name)) { + return def; + } + + return parse_uint(node, name, low, high); +} + +uint64_t YAMLParserWrapper::parse_uint(const YAML::Node &node, const std::string &name, uint64_t low, uint64_t high) { try { @@ -310,3 +328,11 @@ YAMLParserWrapper::parse_err(const std::string &err, const YAML::Node &node) con throw std::runtime_error(ss.str()); } +void +YAMLParserWrapper::parse_err(const std::string &err) const { + std::stringstream ss; + + ss << "\n*** '" << m_header << "' - YAML parsing error: " << err; + + throw std::runtime_error(ss.str()); +} diff --git a/src/utl_yaml.h b/src/utl_yaml.h index 8088c497..2547b666 100755 --- a/src/utl_yaml.h +++ b/src/utl_yaml.h @@ -57,12 +57,15 @@ public: uint32_t parse_ip(const YAML::Node &node, const std::string &name); uint64_t parse_mac_addr(const YAML::Node &node, const std::string &name); + uint64_t parse_mac_addr(const YAML::Node &node, const std::string &name, uint64_t def); uint64_t parse_uint(const YAML::Node &node, const std::string &name, uint64_t low = 0, uint64_t high = UINT64_MAX); + uint64_t parse_uint(const YAML::Node &node, const std::string &name, uint64_t low, uint64_t high, uint64_t def); public: void parse_err(const std::string &err, const YAML::Node &node) const; + void parse_err(const std::string &err) const; private: |