&netdev_linux_class,
&netdev_tap_class,
&netdev_gre_class,
+ &netdev_patch_class,
};
static struct shash netdev_classes = SHASH_INITIALIZER(&netdev_classes);
* 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);
}
}
+/* 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)
* 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;
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
* 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);
}
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,
* 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;
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;
}
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. */
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. */
/* 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) {