X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fnetdev.c;h=c21afef829ca22d1bca8e475813df654dc5f9955;hb=2158888d8d8f3b4c00dcf979390a19fa7fcf7942;hp=2c7b260e1234544857083492e0a42b68b1ff3eba;hpb=c69ee87c10818267f991236201150b1fa51ae519;p=sliver-openvswitch.git diff --git a/lib/netdev.c b/lib/netdev.c index 2c7b260e1..c21afef82 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -44,6 +44,7 @@ static const struct netdev_class *base_netdev_classes[] = { &netdev_linux_class, &netdev_tap_class, + &netdev_patch_class, &netdev_gre_class, }; @@ -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. */