summaryrefslogtreecommitdiff
path: root/lib/netdev-linux.c
diff options
context:
space:
mode:
authorEthan Jackson <ethan@nicira.com>2011-01-07 16:22:34 -0800
committerEthan Jackson <ethan@nicira.com>2011-01-12 15:50:20 -0800
commit6333182946ffd368eb7623d7408185a521058b46 (patch)
tree25f2cbd8b7641343d25a5e003b4f12d179d1f9c0 /lib/netdev-linux.c
parentd90611f14dfd9660e7f5eef5bf27a71003e61174 (diff)
downloadopenvswitch-6333182946ffd368eb7623d7408185a521058b46.tar.gz
vswitchd: Add miimon support.
This commit allows users to check link status in bonded ports using MII instead of carrier.
Diffstat (limited to 'lib/netdev-linux.c')
-rw-r--r--lib/netdev-linux.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 97f9a647f..f953cfc75 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -25,6 +25,7 @@
#include <linux/ip.h>
#include <linux/types.h>
#include <linux/ethtool.h>
+#include <linux/mii.h>
#include <linux/pkt_sched.h>
#include <linux/rtnetlink.h>
#include <linux/sockios.h>
@@ -1007,6 +1008,49 @@ exit:
return error;
}
+static int
+netdev_linux_get_miimon(const struct netdev *netdev_, bool *miimon)
+{
+ int error;
+ struct ifreq ifr;
+ const char *name = netdev_get_name(netdev_);
+
+ *miimon = false;
+ memset(&ifr, 0, sizeof ifr);
+
+ error = netdev_linux_do_ioctl(name, &ifr, SIOCGMIIPHY, "SIOCGMIIPHY");
+ if (!error) {
+ struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr.ifr_data;
+
+ /* data->phy_id is filled out by previous SIOCGMIIPHY ioctl call. */
+ data->reg_num = MII_BMSR;
+ error = netdev_linux_do_ioctl(name, &ifr, SIOCGMIIREG, "SIOCGMIIREG");
+
+ if (!error) {
+ *miimon = !!(data->val_out & BMSR_LSTATUS);
+ } else {
+ VLOG_WARN_RL(&rl, "%s: failed to query MII", name);
+ }
+ } else {
+ struct ethtool_cmd ecmd;
+ struct ethtool_value *eval = (struct ethtool_value *) &ecmd;
+
+ VLOG_DBG_RL(&rl, "%s: failed to query MII, falling back to ethtool",
+ name);
+
+ memset(&ecmd, 0, sizeof ecmd);
+ error = netdev_linux_do_ethtool(name, &ecmd, ETHTOOL_GLINK,
+ "ETHTOOL_GLINK");
+ if (!error) {
+ *miimon = !!eval->data;
+ } else {
+ VLOG_WARN_RL(&rl, "%s: ethtool link status failed", name);
+ }
+ }
+
+ return error;
+}
+
/* Check whether we can we use RTM_GETLINK to get network device statistics.
* In pre-2.6.19 kernels, this was only available if wireless extensions were
* enabled. */
@@ -2152,6 +2196,7 @@ netdev_linux_poll_remove(struct netdev_notifier *notifier_)
netdev_linux_get_mtu, \
netdev_linux_get_ifindex, \
netdev_linux_get_carrier, \
+ netdev_linux_get_miimon, \
netdev_linux_get_stats, \
SET_STATS, \
\