X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fnetdev-linux.c;h=72541c7978c08cce05654d7902da687c2df8c862;hb=a46c577af5c5855939ca3192a56396e15bebf0f8;hp=f953cfc7505fb01f3f3d269420f5436c6b9caa4a;hpb=6333182946ffd368eb7623d7408185a521058b46;p=openvswitch diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index f953cfc7..72541c79 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010 Nicira Networks. + * Copyright (c) 2009, 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -1009,31 +1009,45 @@ exit: } static int -netdev_linux_get_miimon(const struct netdev *netdev_, bool *miimon) +netdev_linux_do_miimon(const struct netdev *netdev, int cmd, + const char *cmd_name, struct mii_ioctl_data *data) { - int error; struct ifreq ifr; - const char *name = netdev_get_name(netdev_); + int error; - *miimon = false; memset(&ifr, 0, sizeof ifr); + memcpy(&ifr.ifr_data, data, sizeof *data); + error = netdev_linux_do_ioctl(netdev_get_name(netdev), + &ifr, cmd, cmd_name); + memcpy(data, &ifr.ifr_data, sizeof *data); - error = netdev_linux_do_ioctl(name, &ifr, SIOCGMIIPHY, "SIOCGMIIPHY"); - if (!error) { - struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr.ifr_data; + return error; +} + +static int +netdev_linux_get_miimon(const struct netdev *netdev, bool *miimon) +{ + const char *name = netdev_get_name(netdev); + struct mii_ioctl_data data; + int error; + + *miimon = false; - /* 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"); + memset(&data, 0, sizeof data); + error = netdev_linux_do_miimon(netdev, SIOCGMIIPHY, "SIOCGMIIPHY", &data); + if (!error) { + /* data.phy_id is filled out by previous SIOCGMIIPHY miimon call. */ + data.reg_num = MII_BMSR; + error = netdev_linux_do_miimon(netdev, SIOCGMIIREG, "SIOCGMIIREG", + &data); if (!error) { - *miimon = !!(data->val_out & BMSR_LSTATUS); + *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); @@ -1042,7 +1056,10 @@ netdev_linux_get_miimon(const struct netdev *netdev_, bool *miimon) error = netdev_linux_do_ethtool(name, &ecmd, ETHTOOL_GLINK, "ETHTOOL_GLINK"); if (!error) { - *miimon = !!eval->data; + struct ethtool_value eval; + + memcpy(&eval, &ecmd, sizeof eval); + *miimon = !!eval.data; } else { VLOG_WARN_RL(&rl, "%s: ethtool link status failed", name); } @@ -1184,7 +1201,7 @@ netdev_linux_get_stats(const struct netdev *netdev_, * bitmap of "enum ofp_port_features" bits, in host byte order. Returns 0 if * successful, otherwise a positive errno value. */ static int -netdev_linux_get_features(struct netdev *netdev, +netdev_linux_get_features(const struct netdev *netdev, uint32_t *current, uint32_t *advertised, uint32_t *supported, uint32_t *peer) { @@ -2008,6 +2025,26 @@ netdev_linux_get_next_hop(const struct in_addr *host, struct in_addr *next_hop, return ENXIO; } +static int +netdev_linux_get_status(const struct netdev *netdev, struct shash *sh) +{ + struct ethtool_drvinfo drvinfo; + int error; + + memset(&drvinfo, 0, sizeof drvinfo); + error = netdev_linux_do_ethtool(netdev_get_name(netdev), + (struct ethtool_cmd *)&drvinfo, + ETHTOOL_GDRVINFO, + "ETHTOOL_GDRVINFO"); + if (!error) { + shash_add(sh, "driver_name", xstrdup(drvinfo.driver)); + shash_add(sh, "driver_version", xstrdup(drvinfo.version)); + shash_add(sh, "firmware_version", xstrdup(drvinfo.fw_version)); + } + + return error; +} + /* Looks up the ARP table entry for 'ip' on 'netdev'. If one exists and can be * successfully retrieved, it stores the corresponding MAC address in 'mac' and * returns 0. Otherwise, it returns a positive errno value; in particular, @@ -2221,7 +2258,7 @@ netdev_linux_poll_remove(struct netdev_notifier *notifier_) netdev_linux_get_in6, \ netdev_linux_add_router, \ netdev_linux_get_next_hop, \ - NULL, /* get_status */ \ + netdev_linux_get_status, \ netdev_linux_arp_lookup, \ \ netdev_linux_update_flags, \