Process ethtool messages and rend response back to kernel.

Signed-off-by: Ferruh Yigit <ferruh.yi...@intel.com>
---
 lib/librte_ctrl_if/rte_ctrl_process.c | 223 ++++++++++++++++++++++++++++++++++
 lib/librte_ctrl_if/rte_ctrl_process.h |   4 +
 lib/librte_ctrl_if/rte_nl.c           |   4 +
 3 files changed, 231 insertions(+)

diff --git a/lib/librte_ctrl_if/rte_ctrl_process.c 
b/lib/librte_ctrl_if/rte_ctrl_process.c
index cfb243f64..55fd54351 100644
--- a/lib/librte_ctrl_if/rte_ctrl_process.c
+++ b/lib/librte_ctrl_if/rte_ctrl_process.c
@@ -38,8 +38,231 @@
 
 #include <rte_version.h>
 #include <rte_ethdev.h>
+#include <rte_ethtool.h>
 #include "rte_ctrl_process.h"
 
+#define ETHTOOL_GEEPROM_LEN 99
+#define ETHTOOL_GREGS_LEN 98
+#define ETHTOOL_GSSET_COUNT 97
+
+static int
+get_settings(uint8_t port_id __rte_unused, void *data, size_t *data_len)
+{
+       struct ethtool_cmd *ecmd = data;
+
+       /* No PMD equivalent, added to make get pauseparam work */
+       memset(ecmd, 0, sizeof(struct ethtool_cmd));
+
+       *data_len = sizeof(struct ethtool_cmd);
+       return 0;
+}
+
+static int
+get_drvinfo(uint8_t port_id, void *data, size_t *data_len)
+{
+       struct ethtool_drvinfo *info = data;
+       int ret;
+
+       ret = rte_ethtool_get_drvinfo(port_id, info);
+       if (ret < 0)
+               return ret;
+
+       *data_len = sizeof(struct ethtool_drvinfo);
+
+       return 0;
+}
+
+static int
+get_reg_len(uint8_t port_id, void *data, size_t *data_len)
+{
+       int reg_length = 0;
+
+       reg_length = rte_ethtool_get_regs_len(port_id);
+       if (reg_length < 0)
+               return reg_length;
+
+       *(int *)data = reg_length;
+       *data_len = sizeof(int);
+
+       return 0;
+}
+
+static int
+get_reg_len_internal(uint8_t port_id, size_t *reg_length)
+{
+       size_t reg_length_out_len;
+
+       return get_reg_len(port_id, reg_length, &reg_length_out_len);
+}
+
+static int
+get_reg(uint8_t port_id, void *in_data, void *out_data, size_t *out_data_len)
+{
+       size_t reg_length;
+       struct ethtool_regs *ethtool_regs = in_data;
+       int ret;
+
+       ret = get_reg_len_internal(port_id, &reg_length);
+       /* not enough space in out data buffer */
+       if (ret < 0 || reg_length > ethtool_regs->len)
+               return -1;
+
+       ret = rte_ethtool_get_regs(port_id, ethtool_regs, out_data);
+       if (ret < 0)
+               return ret;
+
+       *out_data_len = reg_length;
+
+       return 0;
+}
+
+static int
+get_link(uint8_t port_id, void *data, size_t *data_len)
+{
+       int ret;
+
+       ret = rte_ethtool_get_link(port_id);
+
+       *(int *)data = ret;
+       *data_len = sizeof(size_t);
+
+       return 0;
+}
+
+static int
+get_eeprom_length(uint8_t port_id, void *data, size_t *data_len)
+{
+       int eeprom_length = 0;
+
+       eeprom_length = rte_ethtool_get_eeprom_len(port_id);
+       if (eeprom_length < 0)
+               return eeprom_length;
+
+       *(int *)data = eeprom_length;
+       *data_len = sizeof(int);
+
+       return 0;
+}
+
+static int
+get_eeprom(uint8_t port_id, void *in_data, void *out_data,
+               size_t *out_data_len)
+{
+       struct ethtool_eeprom *eeprom = in_data;
+       int ret;
+
+       ret = rte_ethtool_get_eeprom(port_id, eeprom, out_data);
+       if (ret < 0)
+               return ret;
+
+       *out_data_len = eeprom->len;
+
+       return 0;
+}
+
+static int
+set_eeprom(uint8_t port_id, void *in_data)
+{
+       struct ethtool_eeprom *eeprom = in_data;
+       int ret;
+
+       ret = rte_ethtool_set_eeprom(port_id, eeprom, eeprom->data);
+       if (ret != 0)
+               return -1;
+
+       return 0;
+}
+
+static int
+get_ringparam(uint8_t port_id, void *data, size_t *data_len)
+{
+       struct ethtool_ringparam *ringparam = data;
+       int ret;
+
+       ret = rte_ethtool_get_ringparam(port_id, ringparam);
+       if (ret < 0)
+               return ret;
+
+       *data_len = sizeof(struct ethtool_ringparam);
+
+       return 0;
+}
+
+static int
+set_ringparam(uint8_t port_id, void *data)
+{
+       struct ethtool_ringparam *ringparam = data;
+       int ret;
+
+       ret = rte_ethtool_set_ringparam(port_id, ringparam);
+       if (ret != 0)
+               return -1;
+
+       return 0;
+}
+
+static int
+get_pauseparam(uint8_t port_id, void *data, size_t *data_len)
+{
+       struct ethtool_pauseparam *pauseparam = data;
+       int ret;
+
+       ret = rte_ethtool_get_pauseparam(port_id, pauseparam);
+       if (ret < 0)
+               return ret;
+
+       *data_len = sizeof(struct ethtool_pauseparam);
+
+       return 0;
+}
+
+static int
+set_pauseparam(uint8_t port_id, void *data)
+{
+       struct ethtool_pauseparam *pauseparam = data;
+
+       return rte_ethtool_set_pauseparam(port_id, pauseparam);
+}
+
+int
+rte_eth_dev_ethtool_process(uint32_t cmd_id, uint8_t port_id, void *in_data,
+               void *out_data, size_t *out_data_len)
+{
+       if (!rte_eth_dev_is_valid_port(port_id))
+               return -ENODEV;
+
+       switch (cmd_id) {
+       case ETHTOOL_GSET:
+               return get_settings(port_id, out_data, out_data_len);
+       case ETHTOOL_GDRVINFO:
+               return get_drvinfo(port_id, out_data, out_data_len);
+       case ETHTOOL_GREGS_LEN:
+               return get_reg_len(port_id, out_data, out_data_len);
+       case ETHTOOL_GREGS:
+               return get_reg(port_id, in_data, out_data, out_data_len);
+       case ETHTOOL_GLINK:
+               return get_link(port_id, out_data, out_data_len);
+       case ETHTOOL_GEEPROM_LEN:
+               return get_eeprom_length(port_id, out_data, out_data_len);
+       case ETHTOOL_GEEPROM:
+               return get_eeprom(port_id, in_data, out_data, out_data_len);
+       case ETHTOOL_SEEPROM:
+               return set_eeprom(port_id, in_data);
+       case ETHTOOL_GRINGPARAM:
+               return get_ringparam(port_id, out_data, out_data_len);
+       case ETHTOOL_SRINGPARAM:
+               return set_ringparam(port_id, in_data);
+       case ETHTOOL_GPAUSEPARAM:
+               return get_pauseparam(port_id, out_data, out_data_len);
+       case ETHTOOL_SPAUSEPARAM:
+               return set_pauseparam(port_id, in_data);
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
 static int
 set_mtu(uint8_t port_id, void *in_data)
 {
diff --git a/lib/librte_ctrl_if/rte_ctrl_process.h 
b/lib/librte_ctrl_if/rte_ctrl_process.h
index f67c60107..caa4f15f3 100644
--- a/lib/librte_ctrl_if/rte_ctrl_process.h
+++ b/lib/librte_ctrl_if/rte_ctrl_process.h
@@ -38,8 +38,12 @@
 extern "C" {
 #endif
 
+#include <linux/ethtool.h>
+
 #include <exec-env/rte_unci_common.h>
 
+int rte_eth_dev_ethtool_process(uint32_t cmd_id, uint8_t port_id, void 
*in_data,
+               void *out_data, size_t *out_data_len);
 int rte_eth_dev_control_process(uint32_t cmd_id, uint8_t port_id, void 
*in_data,
                void *out_data, size_t *out_data_len);
 
diff --git a/lib/librte_ctrl_if/rte_nl.c b/lib/librte_ctrl_if/rte_nl.c
index 920d123a9..d00a242d2 100644
--- a/lib/librte_ctrl_if/rte_nl.c
+++ b/lib/librte_ctrl_if/rte_nl.c
@@ -123,6 +123,10 @@ process_msg(struct unci_nl_msg *msg)
                msg->err = rte_eth_dev_control_process(msg->cmd_id,
                                msg->port_id, msg->input_buffer,
                                msg->output_buffer, &msg->output_buffer_len);
+       } else {
+               msg->err = rte_eth_dev_ethtool_process(msg->cmd_id,
+                               msg->port_id, msg->input_buffer,
+                               msg->output_buffer, &msg->output_buffer_len);
        }
 
        if (msg->err)
-- 
2.13.0

Reply via email to