[dpdk-dev,v2] 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>
Acked-by: Pascal Mazon <pascal.mazon@6wind.com>
---
Changes in V2:
- updated the auto variable for user_mac - Ferruh
- added documentation update - Vipin
---
doc/guides/nics/tap.rst | 6 ++++
drivers/net/tap/rte_eth_tap.c | 75 +++++++++++++++++++++++++++++++++----------
2 files changed, 64 insertions(+), 17 deletions(-)
Comments
On 3/12/2018 8:21 PM, Vipin Varghese wrote:
> @@ -1591,7 +1632,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 = { .addr_bytes = {0, 0, 0, 0, 0, 0} };
A single '0' will do the job J
struct ether_addr user_mac = { .addr_bytes = {0} };
Would you mind sending a new version?
Sure Ferruh, I will spin a new one.
> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Monday, March 12, 2018 8:39 PM
> To: Varghese, Vipin <vipin.varghese@intel.com>; dev@dpdk.org;
> pascal.mazon@6wind.com
> Subject: Re: [PATCH v2] net/tap: allow user MAC to be passed as args
>
> On 3/12/2018 8:21 PM, Vipin Varghese wrote:
> > @@ -1591,7 +1632,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 = { .addr_bytes = {0, 0, 0, 0, 0, 0} };
>
> A single '0' will do the job J
> struct ether_addr user_mac = { .addr_bytes = {0} };
>
> Would you mind sending a new version?
On Tue, 13 Mar 2018 01:51:34 +0530
Vipin Varghese <vipin.varghese@intel.com> wrote:
> +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;
> +}
We need rte_ether_aton or better yet replace the DPDK custom definition of
"struct ether_addr" with the with the one from Linux/BSD <netinet/ether.h>
There is no value in having a private version of all these routines...
@@ -37,6 +37,12 @@ for each interface string containing ``mac=fixed``. The MAC address is formatted
as 00:'d':'t':'a':'p':[00-FF]. Convert the characters to hex and you get the
actual MAC address: ``00:64:74:61:70:[00-FF]``.
+ --vdev=net_tap0,mac="00:64:74:61:70:11"
+
+The MAC address will have a user value passed as string. The MAC address is in
+format with delimeter ``:``. The string is byte converted to hex and you get
+the actual MAC address: ``00:64:74:61:70:11``.
+
It is possible to specify a remote netdevice to capture packets from by adding
``remote=foo1``, for example::
@@ -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[] = {
@@ -1337,7 +1341,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;
@@ -1399,16 +1403,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 */
@@ -1569,15 +1567,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.
@@ -1591,7 +1632,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 = { .addr_bytes = {0, 0, 0, 0, 0, 0} };
name = rte_vdev_device_name(dev);
params = rte_vdev_device_args(dev);
@@ -1628,7 +1669,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;
}
@@ -1639,7 +1680,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) {
@@ -1703,5 +1744,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>");