diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/common/basic_utils.cpp | 13 | ||||
-rwxr-xr-x | src/common/basic_utils.h | 1 | ||||
-rw-r--r-- | src/main_dpdk.cpp | 39 | ||||
-rw-r--r-- | src/rpc-server/commands/trex_rpc_cmd_general.cpp | 111 | ||||
-rw-r--r-- | src/rpc-server/commands/trex_rpc_cmds.h | 3 | ||||
-rwxr-xr-x | src/trex_port_attr.h | 149 |
6 files changed, 267 insertions, 49 deletions
diff --git a/src/common/basic_utils.cpp b/src/common/basic_utils.cpp index 52988131..dfd3b183 100755 --- a/src/common/basic_utils.cpp +++ b/src/common/basic_utils.cpp @@ -201,6 +201,19 @@ std::string utl_macaddr_to_str(const uint8_t *macaddr) { return tmp; } +bool utl_str_to_macaddr(const std::string &s, uint8_t *mac) { + int last = -1; + int rc = sscanf(s.c_str(), "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx%n", + mac + 0, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5, + &last); + + if ( (rc != 6) || (s.size() != last) ) { + return false; + } + + return true; +} + /** * generate a random connection handler * diff --git a/src/common/basic_utils.h b/src/common/basic_utils.h index fdbd2f08..ab0ff1ec 100755 --- a/src/common/basic_utils.h +++ b/src/common/basic_utils.h @@ -87,6 +87,7 @@ bool utl_is_file_exists (const std::string& name) ; void utl_macaddr_to_str(const uint8_t *macaddr, std::string &output); std::string utl_macaddr_to_str(const uint8_t *macaddr); +bool utl_str_to_macaddr(const std::string &s, uint8_t *mac); std::string utl_generate_random_str(unsigned int &seed, int len); diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 406b9c20..8f887006 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -1604,12 +1604,20 @@ bool DpdkTRexPortAttr::update_link_status_nowait(){ rte_eth_link new_link; bool changed = false; rte_eth_link_get_nowait(m_port_id, &new_link); + + /* if the link got down - update the dest atribute to move to unresolved */ + if (new_link.link_status != m_link.link_status) { + get_dest().on_link_down(); + changed = true; + } + + /* other changes */ if (new_link.link_speed != m_link.link_speed || new_link.link_duplex != m_link.link_duplex || - new_link.link_autoneg != m_link.link_autoneg || - new_link.link_status != m_link.link_status) { + new_link.link_autoneg != m_link.link_autoneg) { changed = true; } + m_link = new_link; return changed; } @@ -3101,8 +3109,7 @@ void CGlobalTRex::pre_test() { exit(1); } memcpy(CGlobalInfo::m_options.m_mac_addr[port_id].u.m_mac.dest, mac, ETHER_ADDR_LEN); - m_ports[port_id].get_port_attr()->set_next_hop_mac(mac); - + // 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); @@ -3115,6 +3122,18 @@ void CGlobalTRex::pre_test() { // Configure port back to normal mode. Only relevant packets handled by software. CTRexExtendedDriverDb::Ins()->get_drv()->set_rcv_all(pif, false); + + + /* set resolved IPv4 */ + uint32_t dg = CGlobalInfo::m_options.m_ip_cfg[port_id].get_def_gw(); + const uint8_t *dst_mac = CGlobalInfo::m_options.m_mac_addr[port_id].u.m_mac.dest; + if (dg) { + m_ports[port_id].get_port_attr()->get_dest().set_dest_ipv4(dg, dst_mac); + } else { + m_ports[port_id].get_port_attr()->get_dest().set_dest_mac(dst_mac); + } + + } } @@ -4680,8 +4699,16 @@ bool CPhyEthIF::Create(uint8_t portid) { m_port_attr = g_trex.m_drv->create_port_attr(portid); - m_port_attr->set_ipv4(CGlobalInfo::m_options.m_ip_cfg[m_port_id].get_ip()); - m_port_attr->set_default_gateway(CGlobalInfo::m_options.m_ip_cfg[m_port_id].get_def_gw()); + uint32_t src_ipv4 = CGlobalInfo::m_options.m_ip_cfg[m_port_id].get_ip(); + if (src_ipv4) { + m_port_attr->set_src_ipv4(src_ipv4); + } + + /* for now set as unresolved IPv4 destination */ + uint32_t dest_ipv4 = CGlobalInfo::m_options.m_ip_cfg[m_port_id].get_def_gw(); + if (dest_ipv4) { + m_port_attr->get_dest().set_dest_ipv4(dest_ipv4); + } return true; } diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index 5ee853b8..8d61ecba 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -368,29 +368,71 @@ TrexRpcCmdSetPortAttr::parse_ipv4(const Json::Value &msg, uint8_t port_id, Json: generate_parse_err(result, ss.str()); } - get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_ipv4(ipv4_addr); + get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_src_ipv4(ipv4_addr); + return (0); +} + +int +TrexRpcCmdSetPortAttr::parse_dest(const Json::Value &msg, uint8_t port_id, Json::Value &result) { + + /* can be either IPv4 or MAC */ + const std::string addr = parse_string(msg, "addr", result); + + TRexPortAttr *port_attr = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id); + + /* try IPv4 */ + uint32_t ipv4_addr; + uint8_t mac[6]; + + if (utl_ipv4_to_uint32(addr.c_str(), ipv4_addr)) { + if (port_attr->get_src_ipv4() == 0) { + generate_parse_err(result, "unable to configure 'dest' as IPv4 without source IPv4 address configured"); + } + port_attr->get_dest().set_dest_ipv4(ipv4_addr); + + } else if (utl_str_to_macaddr(addr, mac)) { + port_attr->get_dest().set_dest_mac(mac); + } else { + std::stringstream ss; + ss << "'dest' is not an IPv4 address or a MAC address: '" << addr << "'"; + generate_parse_err(result, ss.str()); + } + + return (0); } /** - * set port commands - * - * @author imarom (24-Feb-16) - * - * @param params - * @param result - * - * @return trex_rpc_cmd_rc_e + * attributes in the high priority pass must be handled first + * for example, IPv4 configuration should be handled before dest + * */ -trex_rpc_cmd_rc_e -TrexRpcCmdSetPortAttr::_run(const Json::Value ¶ms, Json::Value &result) { +void +TrexRpcCmdSetPortAttr::high_priority_pass(const Json::Value &attr, uint8_t port_id, Json::Value &result) { + int ret = 0; + + /* first iteration - high priority attributes */ + for (const std::string &name : attr.getMemberNames()) { + if (name == "ipv4") { + const Json::Value &ipv4 = parse_object(attr, name, result); + ret = parse_ipv4(ipv4, port_id, result); + } + + /* check error code */ + if ( ret == -ENOTSUP ) { + generate_execute_err(result, "Error applying " + name + ": operation is not supported for this NIC."); + } else if (ret) { + generate_execute_err(result, "Error applying " + name + " attribute, return value: " + to_string(ret)); + } + } +} - uint8_t port_id = parse_port(params, result); - const Json::Value &attr = parse_object(params, "attr", result); +void +TrexRpcCmdSetPortAttr::regular_priority_pass(const Json::Value &attr, uint8_t port_id, Json::Value &result) { int ret = 0; - + /* iterate over all attributes in the dict */ for (const std::string &name : attr.getMemberNames()) { @@ -407,24 +449,30 @@ TrexRpcCmdSetPortAttr::_run(const Json::Value ¶ms, Json::Value &result) { else if (name == "led_status") { bool on = parse_bool(attr[name], "on", result); ret = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_led(on); - } + } else if (name == "flow_ctrl_mode") { int mode = parse_int(attr[name], "mode", result); ret = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_flow_ctrl(mode); - } + } else if (name == "rx_filter_mode") { - ret = parse_rx_filter_mode(attr[name], port_id, result); + const Json::Value &rx = parse_object(attr, name, result); + ret = parse_rx_filter_mode(rx, port_id, result); } else if (name == "ipv4") { - ret = parse_ipv4(attr[name], port_id, result); + /* ignore - was already taken care of in the high priority pass */ } - + + else if (name == "dest") { + const Json::Value &dest = parse_object(attr, name, result); + ret = parse_dest(dest, port_id, result); + } + /* unknown attribute */ else { - generate_execute_err(result, "Not recognized attribute: " + name); + generate_execute_err(result, "unknown attribute type: '" + name + "'"); break; } @@ -435,9 +483,32 @@ TrexRpcCmdSetPortAttr::_run(const Json::Value ¶ms, Json::Value &result) { generate_execute_err(result, "Error applying " + name + " attribute, return value: " + to_string(ret)); } } +} + + +/** + * set port commands + * + * @author imarom (24-Feb-16) + * + * @param params + * @param result + * + * @return trex_rpc_cmd_rc_e + */ +trex_rpc_cmd_rc_e +TrexRpcCmdSetPortAttr::_run(const Json::Value ¶ms, Json::Value &result) { + + uint8_t port_id = parse_port(params, result); + const Json::Value &attr = parse_object(params, "attr", result); + + high_priority_pass(attr, port_id, result); + regular_priority_pass(attr, port_id, result); + result["result"] = Json::objectValue; return (TREX_RPC_CMD_OK); + } diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h index 49610eb8..9fb4d551 100644 --- a/src/rpc-server/commands/trex_rpc_cmds.h +++ b/src/rpc-server/commands/trex_rpc_cmds.h @@ -95,8 +95,11 @@ TREX_RPC_CMD_DEFINE(TrexRpcCmdGetPortXStatsNames, "get_port_xstats_names", 1, TREX_RPC_CMD_DEFINE_EXTENDED(TrexRpcCmdSetPortAttr, "set_port_attr", 2, true, APIClass::API_CLASS_TYPE_CORE, + void high_priority_pass(const Json::Value &attr, uint8 port_id, Json::Value &result); + void regular_priority_pass(const Json::Value &attr, uint8_t port_id, Json::Value &result); int parse_rx_filter_mode(const Json::Value &msg, uint8_t port_id, Json::Value &result); int parse_ipv4(const Json::Value &msg, uint8_t port_id, Json::Value &result); + int parse_dest(const Json::Value &msg, uint8_t port_id, Json::Value &result); ); diff --git a/src/trex_port_attr.h b/src/trex_port_attr.h index ccf12ae2..cdbb466c 100755 --- a/src/trex_port_attr.h +++ b/src/trex_port_attr.h @@ -23,13 +23,119 @@ limitations under the License. #include "trex_defs.h" #include "common/basic_utils.h" +/** + * destination port attribute + * + */ +class DestAttr { +public: + + DestAttr() { + /* use a dummy MAC as default */ + uint8_t dummy_mac [] = {0xff,0xff,0xff,0xff,0xff,0xff}; + set_dest_mac(dummy_mac); + } + + enum dest_type_e { + DEST_TYPE_IPV4 = 1, + DEST_TYPE_MAC = 2 + }; + + /** + * set dest as an IPv4 unresolved + */ + void set_dest_ipv4(uint32_t ipv4) { + assert(ipv4 != 0); + + m_src_ipv4 = ipv4; + memset(m_mac, 0, 6); + m_type = DEST_TYPE_IPV4; + } + + /** + * set dest as a resolved IPv4 + */ + void set_dest_ipv4(uint32_t ipv4, const uint8_t *mac) { + assert(ipv4 != 0); + + m_src_ipv4 = ipv4; + memcpy(m_mac, mac, 6); + m_type = DEST_TYPE_IPV4; + } + + /** + * dest dest as MAC + * + */ + void set_dest_mac(const uint8_t *mac) { + m_src_ipv4 = 0; + memcpy(m_mac, mac, 6); + m_type = DEST_TYPE_MAC; + } + + + bool is_resolved() const { + if (m_type == DEST_TYPE_MAC) { + return true; + } + + for (int i = 0; i < 6; i++) { + if (m_mac[i] != 0) { + return true; + } + } + + /* all zeroes - non resolved */ + return false; + } + + /** + * when link gets down - this should be called + * + */ + void on_link_down() { + if (m_type == DEST_TYPE_IPV4) { + /* reset the IPv4 dest with no resolution */ + set_dest_ipv4(m_src_ipv4); + } + } + + void to_json(Json::Value &output) { + switch (m_type) { + + case DEST_TYPE_IPV4: + output["type"] = "ipv4"; + output["addr"] = utl_uint32_to_ipv4(m_src_ipv4); + if (is_resolved()) { + output["arp"] = utl_macaddr_to_str(m_mac); + } else { + output["arp"] = "none"; + } + break; + + case DEST_TYPE_MAC: + output["type"] = "mac"; + output["addr"] = utl_macaddr_to_str(m_mac); + break; + + default: + assert(0); + } + + } + +private: + uint32_t m_src_ipv4; + uint8_t m_mac[6]; + dest_type_e m_type; +}; + + class TRexPortAttr { public: TRexPortAttr() { - m_ipv4 = 0; - m_default_gateway = 0; - memset(m_next_hop_mac, 0, sizeof(m_next_hop_mac)); + m_src_ipv4 = 0; } virtual ~TRexPortAttr(){} @@ -57,9 +163,8 @@ public: virtual bool is_link_change_supported() { return flag_is_link_change_supported; } virtual void get_description(std::string &description) { description = intf_info_st.description; } virtual void get_supported_speeds(supp_speeds_t &supp_speeds) = 0; - uint32_t get_ipv4() {return m_ipv4;} - uint32_t get_default_gateway() {return m_default_gateway;} - const uint8_t * get_next_hop_mac() {return m_next_hop_mac;} + uint32_t get_src_ipv4() {return m_src_ipv4;} + DestAttr & get_dest() {return m_dest;} virtual std::string get_rx_filter_mode() { switch (m_rx_filter_mode) { @@ -81,16 +186,8 @@ public: virtual int set_led(bool on) = 0; virtual int set_rx_filter_mode(rx_filter_mode_e mode) = 0; - void set_ipv4(uint32_t addr) { - m_ipv4 = addr; - } - - void set_default_gateway(uint32_t addr) { - m_default_gateway = addr; - } - - void set_next_hop_mac(const uint8_t *next_hop_mac) { - memcpy(m_next_hop_mac, next_hop_mac, sizeof(m_next_hop_mac)); + void set_src_ipv4(uint32_t addr) { + m_src_ipv4 = addr; } /* DUMPS */ @@ -104,28 +201,34 @@ public: uint8_t mac_addr[6]; memcpy(mac_addr, dpdk_mac_addr.addr_bytes, 6); - output["mac_addr"] = utl_macaddr_to_str(mac_addr); - output["next_hop_mac"] = utl_macaddr_to_str(m_next_hop_mac); + output["src_mac"] = utl_macaddr_to_str(mac_addr); output["promiscuous"]["enabled"] = get_promiscuous(); output["link"]["up"] = is_link_up(); output["speed"] = get_link_speed(); output["rx_filter_mode"] = get_rx_filter_mode(); - output["ipv4"] = utl_uint32_to_ipv4(get_ipv4()); - output["default_gateway"] = utl_uint32_to_ipv4(get_default_gateway()); + + if (get_src_ipv4() != 0) { + output["src_ipv4"] = utl_uint32_to_ipv4(get_src_ipv4()); + } else { + output["src_ipv4"] = "none"; + } + int mode; get_flow_ctrl(mode); output["fc"]["mode"] = mode; + m_dest.to_json(output["dest"]); + } protected: uint8_t m_port_id; rte_eth_link m_link; - uint32_t m_ipv4; - uint32_t m_default_gateway; - uint8_t m_next_hop_mac[6]; + uint32_t m_src_ipv4; + DestAttr m_dest; + struct rte_eth_dev_info dev_info; rx_filter_mode_e m_rx_filter_mode; |