[dpdk-dev,v2,3/4] net/tap: use the remote MAC address if available

Message ID 1aefeb7b85a62236b650c0baf11a261ae9b7c3bd.1488904606.git.pascal.mazon@6wind.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail apply patch file failure

Commit Message

Pascal Mazon March 7, 2017, 4:38 p.m. UTC
  The remote on a tap is most likely used with netdevices that are not
under DPDK control. Outgoing traffic is supposed to use the source MAC
address of the remote netdevice.

This commit synchronizes the MAC address of the local tap netdevice with
the remote one.

Of course, it is still possible to change the tap MAC address, using
standard DPDK APIs. It sets that MAC address on the tap PMD and redirect
any packets matching that destination MAC to the tap PMD. It also tries
setting the MAC address directly on the remote, if supported, through
ioctl() calls.

Signed-off-by: Pascal Mazon <pascal.mazon@6wind.com>
Acked-by: Olga Shern <olgas@mellanox.com>
---
 drivers/net/tap/rte_eth_tap.c | 77 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 65 insertions(+), 12 deletions(-)
  

Patch

diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index ded8bb0f18d9..ed71cddfe0b3 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -529,6 +529,65 @@  tap_allmulti_disable(struct rte_eth_dev *dev)
 	}
 }
 
+static int
+tap_netdev_set_mac(const char *iface, struct ether_addr *mac_addr)
+{
+	struct ifreq ifr;
+	int err, s;
+
+	s = socket(AF_INET, SOCK_DGRAM, 0);
+	if (s < 0) {
+		RTE_LOG(ERR, PMD,
+			"Unable to get a socket to get MAC: %s\n",
+			strerror(errno));
+		return -1;
+	}
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, iface, IFNAMSIZ);
+	err = ioctl(s, SIOCGIFHWADDR, &ifr);
+	if (err < 0) {
+		RTE_LOG(ERR, PMD, "%s: couldn't get current MAC address (%s)\n",
+			iface, strerror(errno));
+		close(s);
+		return -1;
+	}
+	rte_memcpy(ifr.ifr_hwaddr.sa_data, mac_addr, ETHER_ADDR_LEN);
+	err = ioctl(s, SIOCSIFHWADDR, &ifr) == -1;
+	close(s);
+	if (err < 0) {
+		RTE_LOG(ERR, PMD, "%s: couldn't set current MAC address (%s)\n",
+			iface, strerror(errno));
+		return -1;
+	}
+	return 0;
+}
+
+static int
+tap_netdev_get_mac(const char *iface, struct ether_addr *mac_addr)
+{
+	struct ifreq ifr;
+	int err, s;
+
+	s = socket(AF_INET, SOCK_DGRAM, 0);
+	if (s < 0) {
+		RTE_LOG(ERR, PMD,
+			"Unable to get a socket to get MAC: %s\n",
+			strerror(errno));
+		return -1;
+	}
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, iface, IFNAMSIZ);
+	err = ioctl(s, SIOCGIFHWADDR, &ifr);
+	close(s);
+	if (err < 0) {
+		RTE_LOG(ERR, PMD, "%s: couldn't get MAC address (%s)\n",
+			iface, strerror(errno));
+		return -1;
+	}
+	rte_memcpy(mac_addr, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
+	return 0;
+}
+
 static void
 tap_mac_remove(struct rte_eth_dev *dev __rte_unused,
 	       uint32_t index __rte_unused)
@@ -545,7 +604,6 @@  tap_mac_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
 {
 	struct pmd_internals *internals = dev->data->dev_private;
 	int fd = internals->rxq[0].fd;
-	struct ifreq ifr;
 
 	if (index > RTE_PMD_TAP_MAX_MAC_ADDRS - 1) {
 		RTE_LOG(ERR, PMD,
@@ -565,19 +623,11 @@  tap_mac_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
 			dev->data->name);
 		return;
 	}
-	memset(&ifr, 0, sizeof(struct ifreq));
-	if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
-		RTE_LOG(ERR, PMD, "%s: couldn't get current MAC address (%s)\n",
-			dev->data->name, strerror(errno));
+	if (tap_netdev_set_mac(internals->name, mac_addr) < 0)
 		return;
-	}
-	rte_memcpy(ifr.ifr_hwaddr.sa_data, mac_addr, ETHER_ADDR_LEN);
-	if (ioctl(fd, SIOCSIFHWADDR, &ifr) == -1) {
-		RTE_LOG(ERR, PMD, "%s: couldn't set current MAC address (%s)\n",
-			dev->data->name, strerror(errno));
-		return;
-	}
 	rte_memcpy(&dev->data->mac_addrs[index], mac_addr, ETHER_ADDR_LEN);
+	if (internals->remote_if_index)
+		tap_netdev_set_mac(internals->remote_iface, mac_addr);
 }
 
 static void
@@ -977,6 +1027,9 @@  eth_dev_tap_create(const char *name, char *tap_name, char *remote_iface)
 			RTE_LOG(ERR, PMD, "Could not find %s ifindex: "
 				"remote interface will remain unconfigured\n",
 				remote_iface);
+		else
+			/* Set the local mac address to the remote mac */
+			tap_netdev_get_mac(remote_iface, &pmd->eth_addr);
 	}
 
 	return 0;