X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fnetdev.c;h=9f15b72a6de04e9b5b38b63e75f25919b92178a7;hb=dfbf7f354416264a0b84b09bf882ac0932e78c8b;hp=ec8ae4fc41a303a6f6d50c4c47f9ab2a9dd5996e;hpb=de5cdb90f7c02d22b0595c7dc311c5306291b02f;p=openvswitch diff --git a/lib/netdev.c b/lib/netdev.c index ec8ae4fc..9f15b72a 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -192,14 +192,15 @@ netdev_enumerate_types(struct sset *types) } } -/* Opens the network device named 'name' (e.g. "eth0") and returns zero if - * successful, otherwise a positive errno value. On success, sets '*netdevp' - * to the new network device, otherwise to null. +/* Opens the network device named 'name' (e.g. "eth0") of the specified 'type' + * (e.g. "system") and returns zero if successful, otherwise a positive errno + * value. On success, sets '*netdevp' to the new network device, otherwise to + * null. * * Some network devices may need to be configured (with netdev_set_config()) * before they can be used. */ int -netdev_open(struct netdev_options *options, struct netdev **netdevp) +netdev_open(const char *name, const char *type, struct netdev **netdevp) { struct netdev_dev *netdev_dev; int error; @@ -207,18 +208,18 @@ netdev_open(struct netdev_options *options, struct netdev **netdevp) *netdevp = NULL; netdev_initialize(); - netdev_dev = shash_find_data(&netdev_dev_shash, options->name); + netdev_dev = shash_find_data(&netdev_dev_shash, name); if (!netdev_dev) { const struct netdev_class *class; - class = netdev_lookup_provider(options->type); + class = netdev_lookup_provider(type); if (!class) { VLOG_WARN("could not create netdev %s of unknown type %s", - options->name, options->type); + name, type); return EAFNOSUPPORT; } - error = class->create(class, options->name, &netdev_dev); + error = class->create(class, name, &netdev_dev); if (error) { return error; } @@ -239,17 +240,6 @@ netdev_open(struct netdev_options *options, struct netdev **netdevp) return error; } -int -netdev_open_default(const char *name, struct netdev **netdevp) -{ - struct netdev_options options; - - memset(&options, 0, sizeof options); - options.name = name; - - return netdev_open(&options, netdevp); -} - /* Reconfigures the device 'netdev' with 'args'. 'args' may be empty * or NULL if none are needed. */ int @@ -321,7 +311,7 @@ netdev_exists(const char *name) struct netdev *netdev; int error; - error = netdev_open_default(name, &netdev); + error = netdev_open(name, "system", &netdev); if (!error) { netdev_close(netdev); return true; @@ -342,31 +332,23 @@ netdev_is_open(const char *name) return !!shash_find_data(&netdev_dev_shash, name); } -/* Clears 'sset' and enumerates the names of all known network devices. */ -int -netdev_enumerate(struct sset *sset) +/* Parses 'netdev_name_', which is of the form [type@]name into its component + * pieces. 'name' and 'type' must be freed by the caller. */ +void +netdev_parse_name(const char *netdev_name_, char **name, char **type) { - struct shash_node *node; - int error = 0; + char *netdev_name = xstrdup(netdev_name_); + char *separator; - netdev_initialize(); - sset_clear(sset); - - SHASH_FOR_EACH(node, &netdev_classes) { - const struct netdev_class *netdev_class = node->data; - if (netdev_class->enumerate) { - int retval = netdev_class->enumerate(sset); - if (retval) { - VLOG_WARN("failed to enumerate %s network devices: %s", - netdev_class->type, strerror(retval)); - if (!error) { - error = retval; - } - } - } + separator = strchr(netdev_name, '@'); + if (separator) { + *separator = '\0'; + *type = netdev_name; + *name = xstrdup(separator + 1); + } else { + *name = netdev_name; + *type = xstrdup("system"); } - - return error; } /* Attempts to set up 'netdev' for receiving packets with netdev_recv(). @@ -520,19 +502,45 @@ netdev_get_name(const struct netdev *netdev) * (and received) packets, in bytes, not including the hardware header; thus, * this is typically 1500 bytes for Ethernet devices. * - * If successful, returns 0 and stores the MTU size in '*mtup'. Stores INT_MAX - * in '*mtup' if 'netdev' does not have an MTU (as e.g. some tunnels do not).On - * failure, returns a positive errno value and stores ETH_PAYLOAD_MAX (1500) in - * '*mtup'. */ + * If successful, returns 0 and stores the MTU size in '*mtup'. Returns + * EOPNOTSUPP if 'netdev' does not have an MTU (as e.g. some tunnels do not). + * On other failure, returns a positive errno value. On failure, sets '*mtup' + * to 0. */ int netdev_get_mtu(const struct netdev *netdev, int *mtup) { - int error = netdev_get_dev(netdev)->netdev_class->get_mtu(netdev, mtup); + const struct netdev_class *class = netdev_get_dev(netdev)->netdev_class; + int error; + + error = class->get_mtu ? class->get_mtu(netdev, mtup) : EOPNOTSUPP; if (error) { + *mtup = 0; + if (error != EOPNOTSUPP) { + VLOG_WARN_RL(&rl, "failed to retrieve MTU for network device %s: " + "%s", netdev_get_name(netdev), strerror(error)); + } + } + return error; +} + +/* Sets the MTU of 'netdev'. The MTU is the maximum size of transmitted + * (and received) packets, in bytes. + * + * If successful, returns 0. Returns EOPNOTSUPP if 'netdev' does not have an + * MTU (as e.g. some tunnels do not). On other failure, returns a positive + * errno value. */ +int +netdev_set_mtu(const struct netdev *netdev, int mtu) +{ + const struct netdev_class *class = netdev_get_dev(netdev)->netdev_class; + int error; + + error = class->set_mtu ? class->set_mtu(netdev, mtu) : EOPNOTSUPP; + if (error && error != EOPNOTSUPP) { VLOG_WARN_RL(&rl, "failed to retrieve MTU for network device %s: %s", netdev_get_name(netdev), strerror(error)); - *mtup = ETH_PAYLOAD_MAX; } + return error; } @@ -650,7 +658,7 @@ netdev_set_advertisements(struct netdev *netdev, uint32_t advertise) * * - EOPNOTSUPP: No IPv4 network stack attached to 'netdev'. * - * 'address' or 'netmask' or both may be null, in which case the address or + * 'address' or 'netmask' or both may be null, in which case the address or * netmask is not reported. */ int netdev_get_in4(const struct netdev *netdev, @@ -884,6 +892,15 @@ netdev_get_carrier(const struct netdev *netdev) return carrier; } +/* Returns the number of times 'netdev''s carrier has changed. */ +long long int +netdev_get_carrier_resets(const struct netdev *netdev) +{ + return (netdev_get_dev(netdev)->netdev_class->get_carrier_resets + ? netdev_get_dev(netdev)->netdev_class->get_carrier_resets(netdev) + : 0); +} + /* Attempts to force netdev_get_carrier() to poll 'netdev''s MII registers for * link status instead of checking 'netdev''s carrier. 'netdev''s MII * registers will be polled once ever 'interval' milliseconds. If 'netdev' @@ -1251,33 +1268,6 @@ netdev_get_vlan_vid(const struct netdev *netdev, int *vlan_vid) } return error; } - -/* Returns a network device that has 'in4' as its IP address, if one exists, - * otherwise a null pointer. */ -struct netdev * -netdev_find_dev_by_in4(const struct in_addr *in4) -{ - struct netdev *netdev; - struct sset dev_list = SSET_INITIALIZER(&dev_list); - const char *name; - - netdev_enumerate(&dev_list); - SSET_FOR_EACH (name, &dev_list) { - struct in_addr dev_in4; - - if (!netdev_open_default(name, &netdev) - && !netdev_get_in4(netdev, &dev_in4, NULL) - && dev_in4.s_addr == in4->s_addr) { - goto exit; - } - netdev_close(netdev); - } - netdev = NULL; - -exit: - sset_destroy(&dev_list); - return netdev; -} /* Initializes 'netdev_dev' as a netdev device named 'name' of the specified * 'netdev_class'. This function is ordinarily called from a netdev provider's