summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2016-11-13 17:17:36 +0200
committerimarom <imarom@cisco.com>2016-11-13 17:17:36 +0200
commit6e1919c3aebabc0977a8ab40b5c60cbd0e7114d0 (patch)
tree502aa78527ee4de1723e4a32c291dfcdb71cea23 /src
parentab28fccc187c6134eeb0400ce0b113a77e498bb2 (diff)
RX features - pre-resolve stage
Signed-off-by: imarom <imarom@cisco.com>
Diffstat (limited to 'src')
-rwxr-xr-xsrc/common/basic_utils.cpp13
-rwxr-xr-xsrc/common/basic_utils.h1
-rw-r--r--src/main_dpdk.cpp39
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_general.cpp111
-rw-r--r--src/rpc-server/commands/trex_rpc_cmds.h3
-rwxr-xr-xsrc/trex_port_attr.h149
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 &params, 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 &params, 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 &params, 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 &params, 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;