&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,
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) {