X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=lib%2Fnetdev.c;h=09c00af3f14a7bfd6e8225be2d5059e9d35a4d08;hb=7103dec49eb569c3196239da6c178a29c3003e2b;hp=78d6a9246e862bf41e6cac8ab0a593333c858b3d;hpb=7dab847a19503f537c57c2215748f0b50b94f51e;p=openvswitch diff --git a/lib/netdev.c b/lib/netdev.c index 78d6a924..09c00af3 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -45,6 +45,7 @@ static const struct netdev_class *base_netdev_classes[] = { &netdev_linux_class, &netdev_tap_class, &netdev_gre_class, + &netdev_patch_class, }; static struct shash netdev_classes = SHASH_INITIALIZER(&netdev_classes); @@ -59,7 +60,7 @@ static struct list netdev_list = LIST_INITIALIZER(&netdev_list); * additional log messages. */ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20); -static void close_all_netdevs(void *aux UNUSED); +static void close_all_netdevs(void *aux OVS_UNUSED); static int restore_flags(struct netdev *netdev); void update_device_args(struct netdev_dev *, const struct shash *args); @@ -434,6 +435,14 @@ netdev_exists(const char *name) } } +/* Returns true if a network device named 'name' is currently opened, + * otherwise false. */ +bool +netdev_is_open(const char *name) +{ + return !!shash_find_data(&netdev_dev_shash, name); +} + /* Clears 'svec' and enumerates the names of all known network devices. */ int netdev_enumerate(struct svec *svec) @@ -472,17 +481,23 @@ netdev_enumerate(struct svec *svec) * guaranteed to contain at least ETH_TOTAL_MIN bytes. Otherwise, returns a * positive errno value. Returns EAGAIN immediately if no packet is ready to * be returned. + * + * Some network devices may not implement support for this function. In such + * cases this function will always return EOPNOTSUPP. */ int netdev_recv(struct netdev *netdev, struct ofpbuf *buffer) { + int (*recv)(struct netdev *, void *, size_t); int retval; assert(buffer->size == 0); assert(ofpbuf_tailroom(buffer) >= ETH_TOTAL_MIN); - retval = netdev_get_dev(netdev)->netdev_class->recv(netdev, buffer->data, - ofpbuf_tailroom(buffer)); + recv = netdev_get_dev(netdev)->netdev_class->recv; + retval = (recv + ? (recv)(netdev, buffer->data, ofpbuf_tailroom(buffer)) + : -EOPNOTSUPP); if (retval >= 0) { COVERAGE_INC(netdev_received); buffer->size += retval; @@ -500,14 +515,22 @@ netdev_recv(struct netdev *netdev, struct ofpbuf *buffer) void netdev_recv_wait(struct netdev *netdev) { - netdev_get_dev(netdev)->netdev_class->recv_wait(netdev); + void (*recv_wait)(struct netdev *); + + recv_wait = netdev_get_dev(netdev)->netdev_class->recv_wait; + if (recv_wait) { + recv_wait(netdev); + } } /* Discards all packets waiting to be received from 'netdev'. */ int netdev_drain(struct netdev *netdev) { - return netdev_get_dev(netdev)->netdev_class->drain(netdev); + int (*drain)(struct netdev *); + + drain = netdev_get_dev(netdev)->netdev_class->drain; + return drain ? drain(netdev) : 0; } /* Sends 'buffer' on 'netdev'. Returns 0 if successful, otherwise a positive @@ -518,12 +541,18 @@ netdev_drain(struct netdev *netdev) * The caller retains ownership of 'buffer' in all cases. * * The kernel maintains a packet transmission queue, so the caller is not - * expected to do additional queuing of packets. */ + * expected to do additional queuing of packets. + * + * Some network devices may not implement support for this function. In such + * cases this function will always return EOPNOTSUPP. */ int netdev_send(struct netdev *netdev, const struct ofpbuf *buffer) { - int error = netdev_get_dev(netdev)->netdev_class->send(netdev, - buffer->data, buffer->size); + int (*send)(struct netdev *, const void *, size_t); + int error; + + send = netdev_get_dev(netdev)->netdev_class->send; + error = send ? (send)(netdev, buffer->data, buffer->size) : EOPNOTSUPP; if (!error) { COVERAGE_INC(netdev_sent); } @@ -540,7 +569,12 @@ netdev_send(struct netdev *netdev, const struct ofpbuf *buffer) void netdev_send_wait(struct netdev *netdev) { - return netdev_get_dev(netdev)->netdev_class->send_wait(netdev); + void (*send_wait)(struct netdev *); + + send_wait = netdev_get_dev(netdev)->netdev_class->send_wait; + if (send_wait) { + send_wait(netdev); + } } /* Attempts to set 'netdev''s MAC address to 'mac'. Returns 0 if successful, @@ -595,23 +629,37 @@ netdev_get_mtu(const struct netdev *netdev, int *mtup) * value should be unique within a host and remain stable at least until * reboot. SNMP says an ifindex "ranges between 1 and the value of ifNumber" * but many systems do not follow this rule anyhow. + * + * Some network devices may not implement support for this function. In such + * cases this function will always return -EOPNOTSUPP. */ int netdev_get_ifindex(const struct netdev *netdev) { - return netdev_get_dev(netdev)->netdev_class->get_ifindex(netdev); + int (*get_ifindex)(const struct netdev *); + + get_ifindex = netdev_get_dev(netdev)->netdev_class->get_ifindex; + + return get_ifindex ? get_ifindex(netdev) : -EOPNOTSUPP; } /* Stores the features supported by 'netdev' into each of '*current', * '*advertised', '*supported', and '*peer' that are non-null. Each value is a * bitmap of "enum ofp_port_features" bits, in host byte order. Returns 0 if * successful, otherwise a positive errno value. On failure, all of the - * passed-in values are set to 0. */ + * passed-in values are set to 0. + * + * Some network devices may not implement support for this function. In such + * cases this function will always return EOPNOTSUPP. + */ int netdev_get_features(struct netdev *netdev, uint32_t *current, uint32_t *advertised, uint32_t *supported, uint32_t *peer) { + int (*get_features)(struct netdev *netdev, + uint32_t *current, uint32_t *advertised, + uint32_t *supported, uint32_t *peer); uint32_t dummy[4]; int error; @@ -628,8 +676,10 @@ netdev_get_features(struct netdev *netdev, peer = &dummy[3]; } - error = netdev_get_dev(netdev)->netdev_class->get_features(netdev, current, - advertised, supported, peer); + get_features = netdev_get_dev(netdev)->netdev_class->get_features; + error = get_features + ? get_features(netdev, current, advertised, supported, peer) + : EOPNOTSUPP; if (error) { *current = *advertised = *supported = *peer = 0; } @@ -908,6 +958,19 @@ netdev_get_stats(const struct netdev *netdev, struct netdev_stats *stats) return error; } +/* Attempts to change the stats for 'netdev' to those provided in 'stats'. + * Returns 0 if successful, otherwise a positive errno value. + * + * This will probably fail for most network devices. Some devices might only + * allow setting their stats to 0. */ +int +netdev_set_stats(struct netdev *netdev, const struct netdev_stats *stats) +{ + return (netdev_get_dev(netdev)->netdev_class->set_stats + ? netdev_get_dev(netdev)->netdev_class->set_stats(netdev, stats) + : EOPNOTSUPP); +} + /* Attempts to set input rate limiting (policing) policy, such that up to * 'kbits_rate' kbps of traffic is accepted, with a maximum accumulative burst * size of 'kbits' kb. */ @@ -1017,6 +1080,13 @@ netdev_dev_get_type(const struct netdev_dev *netdev_dev) return netdev_dev->netdev_class->type; } +/* Returns the class associated with 'netdev_dev'. */ +const struct netdev_class * +netdev_dev_get_class(const struct netdev_dev *netdev_dev) +{ + return netdev_dev->netdev_class; +} + /* Returns the name of 'netdev_dev'. * * The caller must not free the returned value. */ @@ -1265,7 +1335,7 @@ restore_flags(struct netdev *netdev) /* Close all netdevs on shutdown so they can do any needed cleanup such as * destroying devices, restoring flags, etc. */ static void -close_all_netdevs(void *aux UNUSED) +close_all_netdevs(void *aux OVS_UNUSED) { struct netdev *netdev, *next; LIST_FOR_EACH_SAFE(netdev, next, struct netdev, node, &netdev_list) {