uint16_t tp_vlan_tpid;
};
+/* Linux 2.6.27 introduced ethtool_cmd_speed
+ *
+ * To avoid revisiting problems reported with using configure to detect
+ * compatibility (see report at
+ * http://openvswitch.org/pipermail/dev/2014-October/047978.html)
+ * unconditionally replace ethtool_cmd_speed. */
+#define ethtool_cmd_speed rpl_ethtool_cmd_speed
+static inline uint32_t rpl_ethtool_cmd_speed(const struct ethtool_cmd *ep)
+{
+ return ep->speed | (ep->speed_hi << 16);
+}
+
+/* Linux 2.6.30 introduced supported and advertised flags for
+ * 1G base KX, and 10G base KX4, KR and R. */
+#ifndef SUPPORTED_1000baseKX_Full
+#define SUPPORTED_1000baseKX_Full (1 << 17)
+#define SUPPORTED_10000baseKX4_Full (1 << 18)
+#define SUPPORTED_10000baseKR_Full (1 << 19)
+#define SUPPORTED_10000baseR_FEC (1 << 20)
+#define ADVERTISED_1000baseKX_Full (1 << 17)
+#define ADVERTISED_10000baseKX4_Full (1 << 18)
+#define ADVERTISED_10000baseKR_Full (1 << 19)
+#define ADVERTISED_10000baseR_FEC (1 << 20)
+#endif
+
+/* Linux 3.5 introduced supported and advertised flags for
+ * 40G base KR4, CR4, SR4 and LR4. */
+#ifndef SUPPORTED_40000baseKR4_Full
+#define SUPPORTED_40000baseKR4_Full (1 << 23)
+#define SUPPORTED_40000baseCR4_Full (1 << 24)
+#define SUPPORTED_40000baseSR4_Full (1 << 25)
+#define SUPPORTED_40000baseLR4_Full (1 << 26)
+#define ADVERTISED_40000baseKR4_Full (1 << 23)
+#define ADVERTISED_40000baseCR4_Full (1 << 24)
+#define ADVERTISED_40000baseSR4_Full (1 << 25)
+#define ADVERTISED_40000baseLR4_Full (1 << 26)
+#endif
+
/* Linux 2.6.35 introduced IFLA_STATS64 and rtnl_link_stats64.
*
* Tests for rtnl_link_stats64 don't seem to consistently work, e.g. on
if (retval < 0) {
return errno;
- } else if (retval > size) {
- return EMSGSIZE;
}
dp_packet_set_size(buffer, dp_packet_size(buffer) + retval);
dp_packet_delete(buffer);
} else {
dp_packet_pad(buffer);
- dp_packet_set_rss_hash(buffer, 0);
+ dp_packet_rss_invalidate(buffer);
packets[0] = buffer;
*c = 1;
}
if (ecmd.supported & SUPPORTED_1000baseT_Half) {
netdev->supported |= NETDEV_F_1GB_HD;
}
- if (ecmd.supported & SUPPORTED_1000baseT_Full) {
+ if ((ecmd.supported & SUPPORTED_1000baseT_Full) ||
+ (ecmd.supported & SUPPORTED_1000baseKX_Full)) {
netdev->supported |= NETDEV_F_1GB_FD;
}
- if (ecmd.supported & SUPPORTED_10000baseT_Full) {
+ if ((ecmd.supported & SUPPORTED_10000baseT_Full) ||
+ (ecmd.supported & SUPPORTED_10000baseKX4_Full) ||
+ (ecmd.supported & SUPPORTED_10000baseKR_Full) ||
+ (ecmd.supported & SUPPORTED_10000baseR_FEC)) {
netdev->supported |= NETDEV_F_10GB_FD;
}
+ if ((ecmd.supported & SUPPORTED_40000baseKR4_Full) ||
+ (ecmd.supported & SUPPORTED_40000baseCR4_Full) ||
+ (ecmd.supported & SUPPORTED_40000baseSR4_Full) ||
+ (ecmd.supported & SUPPORTED_40000baseLR4_Full)) {
+ netdev->supported |= NETDEV_F_40GB_FD;
+ }
if (ecmd.supported & SUPPORTED_TP) {
netdev->supported |= NETDEV_F_COPPER;
}
if (ecmd.advertising & ADVERTISED_1000baseT_Half) {
netdev->advertised |= NETDEV_F_1GB_HD;
}
- if (ecmd.advertising & ADVERTISED_1000baseT_Full) {
+ if ((ecmd.advertising & ADVERTISED_1000baseT_Full) ||
+ (ecmd.advertising & ADVERTISED_1000baseKX_Full)) {
netdev->advertised |= NETDEV_F_1GB_FD;
}
- if (ecmd.advertising & ADVERTISED_10000baseT_Full) {
+ if ((ecmd.advertising & ADVERTISED_10000baseT_Full) ||
+ (ecmd.advertising & ADVERTISED_10000baseKX4_Full) ||
+ (ecmd.advertising & ADVERTISED_10000baseKR_Full) ||
+ (ecmd.advertising & ADVERTISED_10000baseR_FEC)) {
netdev->advertised |= NETDEV_F_10GB_FD;
}
+ if ((ecmd.advertising & ADVERTISED_40000baseKR4_Full) ||
+ (ecmd.advertising & ADVERTISED_40000baseCR4_Full) ||
+ (ecmd.advertising & ADVERTISED_40000baseSR4_Full) ||
+ (ecmd.advertising & ADVERTISED_40000baseLR4_Full)) {
+ netdev->advertised |= NETDEV_F_40GB_FD;
+ }
if (ecmd.advertising & ADVERTISED_TP) {
netdev->advertised |= NETDEV_F_COPPER;
}
}
/* Current settings. */
- speed = ecmd.speed;
+ speed = ethtool_cmd_speed(&ecmd);
if (speed == SPEED_10) {
netdev->current = ecmd.duplex ? NETDEV_F_10MB_FD : NETDEV_F_10MB_HD;
} else if (speed == SPEED_100) {
}
COVERAGE_INC(netdev_set_ethtool);
- evalue.data = new_flags = (evalue.data & ~flag) | (enable ? flag : 0);
+ new_flags = (evalue.data & ~flag) | (enable ? flag : 0);
+ if (new_flags == evalue.data) {
+ return 0;
+ }
+ evalue.data = new_flags;
error = netdev_linux_do_ethtool(netdev_name,
(struct ethtool_cmd *)&evalue,
ETHTOOL_SFLAGS, "ETHTOOL_SFLAGS");
}
hwaddr_family = ifr.ifr_hwaddr.sa_family;
if (hwaddr_family != AF_UNSPEC && hwaddr_family != ARPHRD_ETHER) {
- VLOG_WARN("%s device has unknown hardware address family %d",
+ VLOG_INFO("%s device has unknown hardware address family %d",
netdev_name, hwaddr_family);
+ return EINVAL;
}
memcpy(ea, ifr.ifr_hwaddr.sa_data, ETH_ADDR_LEN);
return 0;