[dpdk-dev,v1] net/tap: allow user MAC to be passed as args
Checks
Commit Message
Allow TAP PMD to pass user desired MAC address as argument.
The argument value is processed as string delimited by ':',
is parsed and converted to HEX MAC address after validation.
Signed-off-by: Vipin Varghese <vipin.varghese@intel.com>
Signed-off-by: Pascal Mazon <pascal.mazon@6wind.com>
---
Changes:
- seggrated the function for hex sting validation - Ferruh
- Fixed the logic lookup for MAC address
---
drivers/net/tap/rte_eth_tap.c | 75 +++++++++++++++++++++++++++++++++----------
1 file changed, 58 insertions(+), 17 deletions(-)
Comments
Acked-by: Pascal Mazon <pascal.mazon@6wind.com>
On 12/02/2018 15:44, Vipin Varghese wrote:
> Allow TAP PMD to pass user desired MAC address as argument.
> The argument value is processed as string delimited by ':',
> is parsed and converted to HEX MAC address after validation.
>
> Signed-off-by: Vipin Varghese <vipin.varghese@intel.com>
> Signed-off-by: Pascal Mazon <pascal.mazon@6wind.com>
> ---
>
> Changes:
> - seggrated the function for hex sting validation - Ferruh
> - Fixed the logic lookup for MAC address
> ---
> drivers/net/tap/rte_eth_tap.c | 75 +++++++++++++++++++++++++++++++++----------
> 1 file changed, 58 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
> index 9d39384..5f67d51 100644
> --- a/drivers/net/tap/rte_eth_tap.c
> +++ b/drivers/net/tap/rte_eth_tap.c
> @@ -48,6 +48,10 @@
> #define ETH_TAP_MAC_ARG "mac"
> #define ETH_TAP_MAC_FIXED "fixed"
>
> +#define ETH_TAP_USR_MAC_FMT "xx:xx:xx:xx:xx:xx"
> +#define ETH_TAP_CMP_MAC_FMT "0123456789ABCDEFabcdef"
> +#define ETH_TAP_MAC_ARG_FMT ETH_TAP_MAC_FIXED "|" ETH_TAP_USR_MAC_FMT
> +
> static struct rte_vdev_driver pmd_tap_drv;
>
> static const char *valid_arguments[] = {
> @@ -1335,7 +1339,7 @@ enum ioctl_mode {
>
> static int
> eth_dev_tap_create(struct rte_vdev_device *vdev, char *tap_name,
> - char *remote_iface, int fixed_mac_type)
> + char *remote_iface, struct ether_addr *mac_addr)
> {
> int numa_node = rte_socket_id();
> struct rte_eth_dev *dev;
> @@ -1397,16 +1401,10 @@ enum ioctl_mode {
> pmd->txq[i].fd = -1;
> }
>
> - if (fixed_mac_type) {
> - /* fixed mac = 00:64:74:61:70:<iface_idx> */
> - static int iface_idx;
> - char mac[ETHER_ADDR_LEN] = "\0dtap";
> -
> - mac[ETHER_ADDR_LEN - 1] = iface_idx++;
> - rte_memcpy(&pmd->eth_addr, mac, ETHER_ADDR_LEN);
> - } else {
> + if (is_zero_ether_addr(mac_addr))
> eth_random_addr((uint8_t *)&pmd->eth_addr);
> - }
> + else
> + rte_memcpy(&pmd->eth_addr, mac_addr, sizeof(mac_addr));
>
> /* Immediately create the netdevice (this will create the 1st queue). */
> /* rx queue */
> @@ -1567,15 +1565,58 @@ enum ioctl_mode {
> return 0;
> }
>
> +static int parse_user_mac(struct ether_addr *user_mac,
> + const char *value)
> +{
> + unsigned int index = 0;
> + char mac_temp[strlen(ETH_TAP_USR_MAC_FMT) + 1], *mac_byte = NULL;
> +
> + if (user_mac == NULL || value == NULL)
> + return 0;
> +
> + snprintf(mac_temp, sizeof(mac_temp), "%s", value);
> + mac_byte = strtok(mac_temp, ":");
> +
> + while ((mac_byte != NULL) &&
> + (strlen(mac_byte) <= 2) &&
> + (strlen(mac_byte) == strspn(mac_byte,
> + ETH_TAP_CMP_MAC_FMT))) {
> + user_mac->addr_bytes[index++] = strtoul(mac_byte, NULL, 16);
> + mac_byte = strtok(NULL, ":");
> + }
> +
> + return index;
> +}
> +
> static int
> set_mac_type(const char *key __rte_unused,
> const char *value,
> void *extra_args)
> {
> - if (value &&
> - !strncasecmp(ETH_TAP_MAC_FIXED, value, strlen(ETH_TAP_MAC_FIXED)))
> - *(int *)extra_args = 1;
> + struct ether_addr *user_mac = extra_args;
> +
> + if (!value)
> + return 0;
> +
> + if (!strncasecmp(ETH_TAP_MAC_FIXED, value, strlen(ETH_TAP_MAC_FIXED))) {
> + static int iface_idx;
> +
> + /* fixed mac = 00:64:74:61:70:<iface_idx> */
> + memcpy((char *)user_mac->addr_bytes, "\0dtap", ETHER_ADDR_LEN);
> + user_mac->addr_bytes[ETHER_ADDR_LEN - 1] = iface_idx++ + '0';
> + goto success;
> + }
> +
> + if (parse_user_mac(user_mac, value) != 6)
> + goto error;
> +success:
> + RTE_LOG(DEBUG, PMD, "TAP user MAC param (%s)\n", value);
> return 0;
> +
> +error:
> + RTE_LOG(ERR, PMD, "TAP user MAC (%s) is not in format (%s|%s)\n",
> + value, ETH_TAP_MAC_FIXED, ETH_TAP_USR_MAC_FMT);
> + return -1;
> }
>
> /* Open a TAP interface device.
> @@ -1589,7 +1630,7 @@ enum ioctl_mode {
> int speed;
> char tap_name[RTE_ETH_NAME_MAX_LEN];
> char remote_iface[RTE_ETH_NAME_MAX_LEN];
> - int fixed_mac_type = 0;
> + struct ether_addr user_mac;
>
> name = rte_vdev_device_name(dev);
> params = rte_vdev_device_args(dev);
> @@ -1626,7 +1667,7 @@ enum ioctl_mode {
> ret = rte_kvargs_process(kvlist,
> ETH_TAP_MAC_ARG,
> &set_mac_type,
> - &fixed_mac_type);
> + &user_mac);
> if (ret == -1)
> goto leave;
> }
> @@ -1637,7 +1678,7 @@ enum ioctl_mode {
> RTE_LOG(NOTICE, PMD, "Initializing pmd_tap for %s as %s\n",
> name, tap_name);
>
> - ret = eth_dev_tap_create(dev, tap_name, remote_iface, fixed_mac_type);
> + ret = eth_dev_tap_create(dev, tap_name, remote_iface, &user_mac);
>
> leave:
> if (ret == -1) {
> @@ -1701,5 +1742,5 @@ enum ioctl_mode {
> RTE_PMD_REGISTER_ALIAS(net_tap, eth_tap);
> RTE_PMD_REGISTER_PARAM_STRING(net_tap,
> ETH_TAP_IFACE_ARG "=<string> "
> - ETH_TAP_MAC_ARG "=" ETH_TAP_MAC_FIXED " "
> + ETH_TAP_MAC_ARG "=" ETH_TAP_MAC_ARG_FMT " "
> ETH_TAP_REMOTE_ARG "=<string>");
On 2/12/2018 2:44 PM, Vipin Varghese wrote:
> Allow TAP PMD to pass user desired MAC address as argument.
> The argument value is processed as string delimited by ':',
> is parsed and converted to HEX MAC address after validation.
>
> Signed-off-by: Vipin Varghese <vipin.varghese@intel.com>
> Signed-off-by: Pascal Mazon <pascal.mazon@6wind.com>
<...>
> @@ -1589,7 +1630,7 @@ enum ioctl_mode {
> int speed;
> char tap_name[RTE_ETH_NAME_MAX_LEN];
> char remote_iface[RTE_ETH_NAME_MAX_LEN];
> - int fixed_mac_type = 0;
> + struct ether_addr user_mac;
>
> name = rte_vdev_device_name(dev);
> params = rte_vdev_device_args(dev);
> @@ -1626,7 +1667,7 @@ enum ioctl_mode {
> ret = rte_kvargs_process(kvlist,
> ETH_TAP_MAC_ARG,
> &set_mac_type,
> - &fixed_mac_type);
> + &user_mac);
> if (ret == -1)
> goto leave;
> }
> @@ -1637,7 +1678,7 @@ enum ioctl_mode {
> RTE_LOG(NOTICE, PMD, "Initializing pmd_tap for %s as %s\n",
> name, tap_name);
>
> - ret = eth_dev_tap_create(dev, tap_name, remote_iface, fixed_mac_type);
> + ret = eth_dev_tap_create(dev, tap_name, remote_iface, &user_mac);
"user_mac" without initial value is leading error when no "mac" argument is
provided. It should be zeroed out.
Hi Ferruh,
You are correct about this, I will add initialization send a next version patch.
> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Tuesday, March 6, 2018 4:42 PM
> To: Varghese, Vipin <vipin.varghese@intel.com>; dev@dpdk.org;
> pascal.mazon@6wind.com
> Cc: Jain, Deepak K <deepak.k.jain@intel.com>
> Subject: Re: [PATCH v1] net/tap: allow user MAC to be passed as args
>
> On 2/12/2018 2:44 PM, Vipin Varghese wrote:
> > Allow TAP PMD to pass user desired MAC address as argument.
> > The argument value is processed as string delimited by ':', is parsed
> > and converted to HEX MAC address after validation.
> >
> > Signed-off-by: Vipin Varghese <vipin.varghese@intel.com>
> > Signed-off-by: Pascal Mazon <pascal.mazon@6wind.com>
>
> <...>
>
> > @@ -1589,7 +1630,7 @@ enum ioctl_mode {
> > int speed;
> > char tap_name[RTE_ETH_NAME_MAX_LEN];
> > char remote_iface[RTE_ETH_NAME_MAX_LEN];
> > - int fixed_mac_type = 0;
> > + struct ether_addr user_mac;
> >
> > name = rte_vdev_device_name(dev);
> > params = rte_vdev_device_args(dev);
> > @@ -1626,7 +1667,7 @@ enum ioctl_mode {
> > ret = rte_kvargs_process(kvlist,
> > ETH_TAP_MAC_ARG,
> > &set_mac_type,
> > - &fixed_mac_type);
> > + &user_mac);
> > if (ret == -1)
> > goto leave;
> > }
> > @@ -1637,7 +1678,7 @@ enum ioctl_mode {
> > RTE_LOG(NOTICE, PMD, "Initializing pmd_tap for %s as %s\n",
> > name, tap_name);
> >
> > - ret = eth_dev_tap_create(dev, tap_name, remote_iface,
> fixed_mac_type);
> > + ret = eth_dev_tap_create(dev, tap_name, remote_iface, &user_mac);
>
> "user_mac" without initial value is leading error when no "mac" argument is
> provided. It should be zeroed out.
@@ -48,6 +48,10 @@
#define ETH_TAP_MAC_ARG "mac"
#define ETH_TAP_MAC_FIXED "fixed"
+#define ETH_TAP_USR_MAC_FMT "xx:xx:xx:xx:xx:xx"
+#define ETH_TAP_CMP_MAC_FMT "0123456789ABCDEFabcdef"
+#define ETH_TAP_MAC_ARG_FMT ETH_TAP_MAC_FIXED "|" ETH_TAP_USR_MAC_FMT
+
static struct rte_vdev_driver pmd_tap_drv;
static const char *valid_arguments[] = {
@@ -1335,7 +1339,7 @@ enum ioctl_mode {
static int
eth_dev_tap_create(struct rte_vdev_device *vdev, char *tap_name,
- char *remote_iface, int fixed_mac_type)
+ char *remote_iface, struct ether_addr *mac_addr)
{
int numa_node = rte_socket_id();
struct rte_eth_dev *dev;
@@ -1397,16 +1401,10 @@ enum ioctl_mode {
pmd->txq[i].fd = -1;
}
- if (fixed_mac_type) {
- /* fixed mac = 00:64:74:61:70:<iface_idx> */
- static int iface_idx;
- char mac[ETHER_ADDR_LEN] = "\0dtap";
-
- mac[ETHER_ADDR_LEN - 1] = iface_idx++;
- rte_memcpy(&pmd->eth_addr, mac, ETHER_ADDR_LEN);
- } else {
+ if (is_zero_ether_addr(mac_addr))
eth_random_addr((uint8_t *)&pmd->eth_addr);
- }
+ else
+ rte_memcpy(&pmd->eth_addr, mac_addr, sizeof(mac_addr));
/* Immediately create the netdevice (this will create the 1st queue). */
/* rx queue */
@@ -1567,15 +1565,58 @@ enum ioctl_mode {
return 0;
}
+static int parse_user_mac(struct ether_addr *user_mac,
+ const char *value)
+{
+ unsigned int index = 0;
+ char mac_temp[strlen(ETH_TAP_USR_MAC_FMT) + 1], *mac_byte = NULL;
+
+ if (user_mac == NULL || value == NULL)
+ return 0;
+
+ snprintf(mac_temp, sizeof(mac_temp), "%s", value);
+ mac_byte = strtok(mac_temp, ":");
+
+ while ((mac_byte != NULL) &&
+ (strlen(mac_byte) <= 2) &&
+ (strlen(mac_byte) == strspn(mac_byte,
+ ETH_TAP_CMP_MAC_FMT))) {
+ user_mac->addr_bytes[index++] = strtoul(mac_byte, NULL, 16);
+ mac_byte = strtok(NULL, ":");
+ }
+
+ return index;
+}
+
static int
set_mac_type(const char *key __rte_unused,
const char *value,
void *extra_args)
{
- if (value &&
- !strncasecmp(ETH_TAP_MAC_FIXED, value, strlen(ETH_TAP_MAC_FIXED)))
- *(int *)extra_args = 1;
+ struct ether_addr *user_mac = extra_args;
+
+ if (!value)
+ return 0;
+
+ if (!strncasecmp(ETH_TAP_MAC_FIXED, value, strlen(ETH_TAP_MAC_FIXED))) {
+ static int iface_idx;
+
+ /* fixed mac = 00:64:74:61:70:<iface_idx> */
+ memcpy((char *)user_mac->addr_bytes, "\0dtap", ETHER_ADDR_LEN);
+ user_mac->addr_bytes[ETHER_ADDR_LEN - 1] = iface_idx++ + '0';
+ goto success;
+ }
+
+ if (parse_user_mac(user_mac, value) != 6)
+ goto error;
+success:
+ RTE_LOG(DEBUG, PMD, "TAP user MAC param (%s)\n", value);
return 0;
+
+error:
+ RTE_LOG(ERR, PMD, "TAP user MAC (%s) is not in format (%s|%s)\n",
+ value, ETH_TAP_MAC_FIXED, ETH_TAP_USR_MAC_FMT);
+ return -1;
}
/* Open a TAP interface device.
@@ -1589,7 +1630,7 @@ enum ioctl_mode {
int speed;
char tap_name[RTE_ETH_NAME_MAX_LEN];
char remote_iface[RTE_ETH_NAME_MAX_LEN];
- int fixed_mac_type = 0;
+ struct ether_addr user_mac;
name = rte_vdev_device_name(dev);
params = rte_vdev_device_args(dev);
@@ -1626,7 +1667,7 @@ enum ioctl_mode {
ret = rte_kvargs_process(kvlist,
ETH_TAP_MAC_ARG,
&set_mac_type,
- &fixed_mac_type);
+ &user_mac);
if (ret == -1)
goto leave;
}
@@ -1637,7 +1678,7 @@ enum ioctl_mode {
RTE_LOG(NOTICE, PMD, "Initializing pmd_tap for %s as %s\n",
name, tap_name);
- ret = eth_dev_tap_create(dev, tap_name, remote_iface, fixed_mac_type);
+ ret = eth_dev_tap_create(dev, tap_name, remote_iface, &user_mac);
leave:
if (ret == -1) {
@@ -1701,5 +1742,5 @@ enum ioctl_mode {
RTE_PMD_REGISTER_ALIAS(net_tap, eth_tap);
RTE_PMD_REGISTER_PARAM_STRING(net_tap,
ETH_TAP_IFACE_ARG "=<string> "
- ETH_TAP_MAC_ARG "=" ETH_TAP_MAC_FIXED " "
+ ETH_TAP_MAC_ARG "=" ETH_TAP_MAC_ARG_FMT " "
ETH_TAP_REMOTE_ARG "=<string>");