X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fnetdev.c;h=d5a51fa0ea90b91b4524c47859cf8105776bac73;hb=7aaeab4df24b7e9460705b1dad1010eef0354c50;hp=5aae01c6c21ba03a73ef9f70f980d6e14d76d637;hpb=0bb0393a0b274776ebd61ca2265a252ac8dfbe2a;p=sliver-openvswitch.git diff --git a/lib/netdev.c b/lib/netdev.c index 5aae01c6c..d5a51fa0e 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -85,10 +85,12 @@ netdev_initialize(void) netdev_register_provider(&netdev_tap_class); netdev_vport_tunnel_register(); #endif -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__NetBSD__) netdev_register_provider(&netdev_tap_class); netdev_register_provider(&netdev_bsd_class); #endif + netdev_register_provider(&netdev_tunnel_class); + netdev_register_provider(&netdev_pltap_class); } } @@ -139,7 +141,7 @@ netdev_register_provider(const struct netdev_class *new_class) int error = new_class->init(); if (error) { VLOG_ERR("failed to initialize %s network device class: %s", - new_class->type, strerror(error)); + new_class->type, ovs_strerror(error)); return error; } } @@ -277,14 +279,17 @@ netdev_open(const char *name, const char *type, struct netdev **netdevp) return 0; } -/* Returns a reference to 'netdev_' for the caller to own. */ +/* Returns a reference to 'netdev_' for the caller to own. Returns null if + * 'netdev_' is null. */ struct netdev * netdev_ref(const struct netdev *netdev_) { struct netdev *netdev = CONST_CAST(struct netdev *, netdev_); - ovs_assert(netdev->ref_cnt > 0); - netdev->ref_cnt++; + if (netdev) { + ovs_assert(netdev->ref_cnt > 0); + netdev->ref_cnt++; + } return netdev; } @@ -523,7 +528,7 @@ netdev_get_mtu(const struct netdev *netdev, int *mtup) *mtup = 0; if (error != EOPNOTSUPP) { VLOG_DBG_RL(&rl, "failed to retrieve MTU for network device %s: " - "%s", netdev_get_name(netdev), strerror(error)); + "%s", netdev_get_name(netdev), ovs_strerror(error)); } } return error; @@ -544,7 +549,7 @@ netdev_set_mtu(const struct netdev *netdev, int mtu) error = class->set_mtu ? class->set_mtu(netdev, mtu) : EOPNOTSUPP; if (error && error != EOPNOTSUPP) { VLOG_DBG_RL(&rl, "failed to set MTU for network device %s: %s", - netdev_get_name(netdev), strerror(error)); + netdev_get_name(netdev), ovs_strerror(error)); } return error; @@ -822,7 +827,7 @@ do_update_flags(struct netdev *netdev, enum netdev_flags off, if (error) { VLOG_WARN_RL(&rl, "failed to %s flags for network device %s: %s", off || on ? "set" : "get", netdev_get_name(netdev), - strerror(error)); + ovs_strerror(error)); old_flags = 0; } else if ((off || on) && sfp) { enum netdev_flags new_flags = (old_flags & ~off) | on; @@ -923,8 +928,7 @@ netdev_arp_lookup(const struct netdev *netdev, ovs_be32 ip, uint8_t mac[ETH_ADDR_LEN]) { int error = (netdev->netdev_class->arp_lookup - ? netdev->netdev_class->arp_lookup(netdev, - ip, mac) + ? netdev->netdev_class->arp_lookup(netdev, ip, mac) : EOPNOTSUPP); if (error) { memset(mac, 0, ETH_ADDR_LEN); @@ -949,11 +953,10 @@ netdev_get_carrier(const struct netdev *netdev) return true; } - error = netdev->netdev_class->get_carrier(netdev, - &carrier); + error = netdev->netdev_class->get_carrier(netdev, &carrier); if (error) { VLOG_DBG("%s: failed to get network device carrier status, assuming " - "down: %s", netdev_get_name(netdev), strerror(error)); + "down: %s", netdev_get_name(netdev), ovs_strerror(error)); carrier = false; } @@ -1243,7 +1246,8 @@ netdev_delete_queue(struct netdev *netdev, unsigned int queue_id) /* Obtains statistics about 'queue_id' on 'netdev'. On success, returns 0 and * fills 'stats' with the queue's statistics; individual members of 'stats' may * be set to all-1-bits if the statistic is unavailable. On failure, returns a - * positive errno value and fills 'stats' with all-1-bits. */ + * positive errno value and fills 'stats' with values indicating unsupported + * statistics. */ int netdev_get_queue_stats(const struct netdev *netdev, unsigned int queue_id, struct netdev_queue_stats *stats) @@ -1255,7 +1259,10 @@ netdev_get_queue_stats(const struct netdev *netdev, unsigned int queue_id, ? class->get_queue_stats(netdev, queue_id, stats) : EOPNOTSUPP); if (retval) { - memset(stats, 0xff, sizeof *stats); + stats->tx_bytes = UINT64_MAX; + stats->tx_packets = UINT64_MAX; + stats->tx_errors = UINT64_MAX; + stats->created = LLONG_MIN; } return retval; } @@ -1381,17 +1388,24 @@ netdev_get_class(const struct netdev *netdev) /* Returns the netdev with 'name' or NULL if there is none. * - * The caller must not free the returned value. */ + * The caller must free the returned netdev with netdev_close(). */ struct netdev * netdev_from_name(const char *name) { - return shash_find_data(&netdev_shash, name); + struct netdev *netdev; + + netdev = shash_find_data(&netdev_shash, name); + if (netdev) { + netdev_ref(netdev); + } + + return netdev; } /* Fills 'device_list' with devices that match 'netdev_class'. * - * The caller is responsible for initializing and destroying 'device_list' - * but the contained netdevs must not be freed. */ + * The caller is responsible for initializing and destroying 'device_list' and + * must close each device on the list. */ void netdev_get_devices(const struct netdev_class *netdev_class, struct shash *device_list) @@ -1401,6 +1415,7 @@ netdev_get_devices(const struct netdev_class *netdev_class, struct netdev *dev = node->data; if (dev->netdev_class == netdev_class) { + dev->ref_cnt++; shash_add(device_list, node->name, node->data); } } @@ -1409,8 +1424,10 @@ netdev_get_devices(const struct netdev_class *netdev_class, const char * netdev_get_type_from_name(const char *name) { - const struct netdev *dev = netdev_from_name(name); - return dev ? netdev_get_type(dev) : NULL; + struct netdev *dev = netdev_from_name(name); + const char *type = dev ? netdev_get_type(dev) : NULL; + netdev_close(dev); + return type; } void