/*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 2010 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/* Generic interface to network devices. */
#include <assert.h>
+
#include "netdev.h"
#include "list.h"
#include "shash.h"
-/* A network device object that was created through the netdev_create()
- * call.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct arg {
+ char *key;
+ char *value;
+};
+
+/* A network device (e.g. an Ethernet device).
*
* This structure should be treated as opaque by network device
* implementations. */
-struct netdev_obj {
- const struct netdev_class *class;
- int ref_cnt;
- bool created; /* Was netdev_create() called? */
+struct netdev_dev {
+ char *name; /* Name of network device. */
+ const struct netdev_class *netdev_class; /* Functions to control
+ this device. */
+ int ref_cnt; /* Times this devices was opened. */
+ struct shash_node *node; /* Pointer to element in global map. */
+ struct arg *args; /* Argument list from last config. */
+ int n_args; /* Number of arguments in 'args'. */
};
-void netdev_obj_init(struct netdev_obj *, const char *name,
- const struct netdev_class *, bool created);
-static inline void netdev_obj_assert_class(const struct netdev_obj *netdev_obj,
- const struct netdev_class *class)
+void netdev_dev_init(struct netdev_dev *, const char *name,
+ const struct netdev_class *);
+void netdev_dev_uninit(struct netdev_dev *, bool destroy);
+const char *netdev_dev_get_type(const struct netdev_dev *);
+const struct netdev_class *netdev_dev_get_class(const struct netdev_dev *);
+const char *netdev_dev_get_name(const struct netdev_dev *);
+struct netdev_dev *netdev_dev_from_name(const char *name);
+void netdev_dev_get_devices(const struct netdev_class *,
+ struct shash *device_list);
+
+static inline void netdev_dev_assert_class(const struct netdev_dev *netdev_dev,
+ const struct netdev_class *class_)
{
- assert(netdev_obj->class == class);
+ assert(netdev_dev->netdev_class == class_);
}
-/* A network device (e.g. an Ethernet device).
+/* A instance of an open network device.
*
* This structure should be treated as opaque by network device
* implementations. */
struct netdev {
- const struct netdev_class *class;
- char *name; /* e.g. "eth0" */
+ struct netdev_dev *netdev_dev; /* Parent netdev_dev. */
+ struct list node; /* Element in global list. */
enum netdev_flags save_flags; /* Initial device flags. */
enum netdev_flags changed_flags; /* Flags that we changed. */
- struct list node; /* Element in global list. */
};
-void netdev_init(struct netdev *, const char *name,
- const struct netdev_class *);
+void netdev_init(struct netdev *, struct netdev_dev *);
+void netdev_uninit(struct netdev *, bool close);
+struct netdev_dev *netdev_get_dev(const struct netdev *);
+
static inline void netdev_assert_class(const struct netdev *netdev,
- const struct netdev_class *class)
+ const struct netdev_class *netdev_class)
{
- assert(netdev->class == class);
+ netdev_dev_assert_class(netdev_get_dev(netdev), netdev_class);
}
-const char *netdev_get_type(const struct netdev *netdev);
/* A network device notifier.
*
/* Type of netdevs in this class, e.g. "system", "tap", "gre", etc.
*
* One of the providers should supply a "system" type, since this is
- * the type assumed when a device name was not bound through the
- * netdev_create() call. The "system" type corresponds to an
- * existing network device on the system. */
+ * the type assumed if no type is specified when opening a netdev.
+ * The "system" type corresponds to an existing network device on
+ * the system. */
const char *type;
- /* Called only once, at program startup. Returning an error from this
- * function will prevent any network device in this class from being
- * opened.
+ /* Called when the netdev provider is registered, typically at program
+ * startup. Returning an error from this function will prevent any network
+ * device in this class from being opened.
*
* This function may be set to null if a network device class needs no
- * initialization at program startup. */
+ * initialization at registration time. */
int (*init)(void);
/* Performs periodic work needed by netdevs of this class. May be null if
* to be called. May be null if nothing is needed here. */
void (*wait)(void);
- /* Attempts to create a network device object of 'type' with 'name'.
+ /* Attempts to create a network device of 'type' with 'name'.
* 'type' corresponds to the 'type' field used in the netdev_class
- * structure.
- *
- * The 'created' flag indicates that the user called netdev_create()
- * and thus will eventually call netdev_destroy(). If the flag is
- * false, then the object was dynamically created based on a call to
- * netdev_open() without first calling netdev_create() and will be
- * automatically destroyed when no more netdevs have 'name' open. A
- * provider implementation should pass this flag to netdev_obj_init(). */
- int (*create)(const char *name, const char *type,
- const struct shash *args, bool created);
-
- /* Destroys 'netdev_obj'.
- *
- * Netdev objects maintain a reference count that is incremented on
- * netdev_open() and decremented on netdev_close(). If 'netdev_obj'
- * has a non-zero reference count, then this function will not be
+ * structure. On success sets 'netdev_devp' to the newly created device. */
+ int (*create)(const char *name, const char *type, const struct shash *args,
+ struct netdev_dev **netdev_devp);
+
+ /* Destroys 'netdev_dev'.
+ *
+ * Netdev devices maintain a reference count that is incremented on
+ * netdev_open() and decremented on netdev_close(). If 'netdev_dev'
+ * has a non-zero reference count, then this function will not be
* called. */
- void (*destroy)(struct netdev_obj *netdev_obj);
+ void (*destroy)(struct netdev_dev *netdev_dev);
- /* Reconfigures the device object 'netdev_obj' with 'args'.
+ /* Reconfigures the device 'netdev_dev' with 'args'.
*
* If this netdev class does not support reconfiguring a netdev
- * object, this may be a null pointer.
+ * device, this may be a null pointer.
*/
- int (*reconfigure)(struct netdev_obj *netdev_obj,
- const struct shash *args);
+ int (*reconfigure)(struct netdev_dev *netdev_dev, const struct shash *args);
- /* Attempts to open a network device. On success, sets '*netdevp' to the
- * new network device. 'name' is the network device name provided by
- * the user. This name is useful for error messages but must not be
- * modified.
+ /* Attempts to open a network device. On success, sets 'netdevp'
+ * to the new network device.
*
* 'ethertype' may be a 16-bit Ethernet protocol value in host byte order
* to capture frames of that type received on the device. It may also be
* one of the 'enum netdev_pseudo_ethertype' values to receive frames in
* one of those categories. */
- int (*open)(const char *name, int ethertype, struct netdev **netdevp);
+ int (*open)(struct netdev_dev *netdev_dev, int ethertype,
+ struct netdev **netdevp);
/* Closes 'netdev'. */
void (*close)(struct netdev *netdev);
/* Attempts to receive a packet from 'netdev' into the 'size' bytes in
* 'buffer'. If successful, returns the number of bytes in the received
* packet, otherwise a negative errno value. Returns -EAGAIN immediately
- * if no packet is ready to be received. */
+ * if no packet is ready to be received.
+ *
+ * May return -EOPNOTSUPP if a network device does not implement packet
+ * reception through this interface. This function may be set to null if
+ * it would always return -EOPNOTSUPP anyhow. (This will disable the OVS
+ * integrated DHCP client and OpenFlow controller discovery, and prevent
+ * the network device from being usefully used by the netdev-based
+ * "userspace datapath".) */
int (*recv)(struct netdev *netdev, void *buffer, size_t size);
/* Registers with the poll loop to wake up from the next call to
* poll_block() when a packet is ready to be received with netdev_recv() on
- * 'netdev'. */
+ * 'netdev'.
+ *
+ * May be null if not needed, such as for a network device that does not
+ * implement packet reception through the 'recv' member function. */
void (*recv_wait)(struct netdev *netdev);
- /* Discards all packets waiting to be received from 'netdev'. */
+ /* Discards all packets waiting to be received from 'netdev'.
+ *
+ * May be null if not needed, such as for a network device that does not
+ * implement packet reception through the 'recv' member function. */
int (*drain)(struct netdev *netdev);
/* Sends the 'size'-byte packet in 'buffer' on 'netdev'. Returns 0 if
*
* The network device is expected to maintain a packet transmission queue,
* so that the caller does not ordinarily have to do additional queuing of
- * packets. */
+ * packets.
+ *
+ * May return EOPNOTSUPP if a network device does not implement packet
+ * transmission through this interface. This function may be set to null
+ * if it would always return EOPNOTSUPP anyhow. (This will disable the OVS
+ * integrated DHCP client and OpenFlow controller discovery, and prevent
+ * the network device from being usefully used by the netdev-based
+ * "userspace datapath".) */
int (*send)(struct netdev *netdev, const void *buffer, size_t size);
/* Registers with the poll loop to wake up from the next call to
*
* The network device is expected to maintain a packet transmission queue,
* so that the caller does not ordinarily have to do additional queuing of
- * packets. Thus, this function is unlikely to ever be useful. */
+ * packets. Thus, this function is unlikely to ever be useful.
+ *
+ * May be null if not needed, such as for a network device that does not
+ * implement packet transmission through the 'send' member function. */
void (*send_wait)(struct netdev *netdev);
/* Sets 'netdev''s Ethernet address to 'mac' */
* The MTU is the maximum size of transmitted (and received) packets, in
* bytes, not including the hardware header; thus, this is typically 1500
* bytes for Ethernet devices.*/
- int (*get_mtu)(const struct netdev *, int *mtup);
+ int (*get_mtu)(const struct netdev *netdev, int *mtup);
/* Returns the ifindex of 'netdev', if successful, as a positive number.
* On failure, returns a negative errno value.
* ifindex 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. */
- int (*get_ifindex)(const struct netdev *);
+ int (*get_ifindex)(const struct netdev *netdev);
/* Sets 'carrier' to true if carrier is active (link light is on) on
* 'netdev'. */
* A network device that supports some statistics but not others, it should
* set the values of the unsupported statistics to all-1-bits
* (UINT64_MAX). */
- int (*get_stats)(const struct netdev *netdev, struct netdev_stats *stats);
+ int (*get_stats)(const struct netdev *netdev, struct netdev_stats *);
/* Stores the features supported by 'netdev' into each of '*current',
* '*advertised', '*supported', and '*peer'. Each value is a bitmap of
*
* This function may be set to null for a network device that does not
* support configuring advertisements. */
- int (*set_advertisements)(struct netdev *, uint32_t advertise);
+ int (*set_advertisements)(struct netdev *netdev, uint32_t advertise);
/* If 'netdev' is a VLAN network device (e.g. one created with vconfig(8)),
* sets '*vlan_vid' to the VLAN VID associated with that device and returns
* 0.
*
- * Returns ENOENT if 'netdev_name' is the name of a network device that is
- * not a VLAN device.
+ * Returns ENOENT if 'netdev' is a network device that is not a
+ * VLAN device.
*
* This function should be set to null if it doesn't make any sense for
* your network device (it probably doesn't). */
*
* This function may be set to null if it would always return EOPNOTSUPP
* anyhow. */
- int (*set_in4)(struct netdev *, struct in_addr addr, struct in_addr mask);
+ int (*set_in4)(struct netdev *netdev, struct in_addr addr,
+ struct in_addr mask);
/* If 'netdev' has an assigned IPv6 address, sets '*in6' to that address.
*
*
* This function may be set to null if it would always return EOPNOTSUPP
* anyhow. */
- int (*arp_lookup)(const struct netdev *, uint32_t ip, uint8_t mac[6]);
+ int (*arp_lookup)(const struct netdev *netdev, uint32_t ip, uint8_t mac[6]);
- /* Retrieves the current set of flags on 'netdev' into '*old_flags'. Then,
- * turns off the flags that are set to 1 in 'off' and turns on the flags
- * that are set to 1 in 'on'. (No bit will be set to 1 in both 'off' and
- * 'on'; that is, off & on == 0.)
+ /* Retrieves the current set of flags on 'netdev' into '*old_flags'.
+ * Then, turns off the flags that are set to 1 in 'off' and turns on the
+ * flags that are set to 1 in 'on'. (No bit will be set to 1 in both 'off'
+ * and 'on'; that is, off & on == 0.)
*
* This function may be invoked from a signal handler. Therefore, it
* should not do anything that is not signal-safe (such as logging). */
* will have its 'netdev', 'cb', and 'aux' members set to the values of the
* corresponding parameters. */
int (*poll_add)(struct netdev *netdev,
- void (*cb)(struct netdev_notifier *), void *aux,
+ void (*cb)(struct netdev_notifier *notifier), void *aux,
struct netdev_notifier **notifierp);
/* Cancels poll notification for 'notifier'. */
extern const struct netdev_class netdev_linux_class;
extern const struct netdev_class netdev_tap_class;
+extern const struct netdev_class netdev_gre_class;
+extern const struct netdev_class netdev_patch_class;
+
+#ifdef __cplusplus
+}
+#endif
#endif /* netdev.h */