diff options
| author | Ethan Jackson <ethan@nicira.com> | 2011-01-07 16:22:34 -0800 |
|---|---|---|
| committer | Ethan Jackson <ethan@nicira.com> | 2011-01-12 15:50:20 -0800 |
| commit | 6333182946ffd368eb7623d7408185a521058b46 (patch) | |
| tree | 25f2cbd8b7641343d25a5e003b4f12d179d1f9c0 /lib/netdev-linux.c | |
| parent | d90611f14dfd9660e7f5eef5bf27a71003e61174 (diff) | |
| download | openvswitch-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.c | 45 |
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, \ \ |
