#include <assert.h>
#include "netdev.h"
#include "list.h"
+#include "shash.h"
+
+/* A network device object that was created through the netdev_create()
+ * call.
+ *
+ * This structure should be treated as opaque by network device
+ * implementations. */
+struct netdev_obj {
+ const struct netdev_class *class;
+ int ref_cnt;
+ char *name;
+ bool created; /* Was netdev_create() called? */
+};
+
+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)
+{
+ assert(netdev_obj->class == class);
+}
+const char *netdev_obj_get_type(const struct netdev_obj *netdev_obj);
+const char *netdev_obj_get_name(const struct netdev_obj *netdev_obj);
/* A network device (e.g. an Ethernet device).
*
struct netdev {
const struct netdev_class *class;
char *name; /* e.g. "eth0" */
+
enum netdev_flags save_flags; /* Initial device flags. */
enum netdev_flags changed_flags; /* Flags that we changed. */
struct list node; /* Element in global list. */
{
assert(netdev->class == class);
}
+const char *netdev_get_type(const struct netdev *netdev);
/* A network device notifier.
*
* These functions return 0 if successful or a positive errno value on failure,
* except where otherwise noted. */
struct netdev_class {
- /* Prefix for names of netdevs in this class, e.g. "ndunix:".
+ /* Type of netdevs in this class, e.g. "system", "tap", "gre", etc.
*
- * One netdev class may have the empty string "" as its prefix, in which
- * case that netdev class is associated with netdev names that do not
- * contain a colon. */
- const char *prefix;
-
- /* Class name, for use in error messages. */
- const char *name;
+ * 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. */
+ 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
* 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'.
+ * '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
+ * called. */
+ void (*destroy)(struct netdev_obj *netdev_obj);
+
+ /* Reconfigures the device object 'netdev_obj' with 'args'.
+ *
+ * If this netdev class does not support reconfiguring a netdev
+ * object, this may be a null pointer.
+ */
+ int (*reconfigure)(struct netdev_obj *netdev_obj,
+ const struct shash *args);
+
/* Attempts to open a network device. On success, sets '*netdevp' to the
- * new network device. 'name' is the full network device name provided by
+ * 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.
*
- * 'suffix' is a copy of 'name' following the netdev's 'prefix'.
- *
* '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, char *suffix, int ethertype,
- struct netdev **netdevp);
+ int (*open)(const char *name, int ethertype, struct netdev **netdevp);
/* Closes 'netdev'. */
void (*close)(struct netdev *netdev);
*
* If this netdev class does not support enumeration, this may be a null
* pointer. */
- int (*enumerate)(struct svec *all_anmes);
+ int (*enumerate)(struct svec *all_names);
/* Attempts to receive a packet from 'netdev' into the 'size' bytes in
* 'buffer'. If successful, returns the number of bytes in the received
* bytes for Ethernet devices.*/
int (*get_mtu)(const struct netdev *, int *mtup);
+ /* Returns the ifindex of 'netdev', if successful, as a positive number.
+ * On failure, returns a negative errno value.
+ *
+ * The desired semantics of the ifindex value are a combination of those
+ * specified by POSIX for if_nametoindex() and by SNMP for ifIndex. An
+ * 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 *);
+
/* Sets 'carrier' to true if carrier is active (link light is on) on
* 'netdev'. */
int (*get_carrier)(const struct netdev *netdev, bool *carrier);
int (*set_policing)(struct netdev *netdev, unsigned int kbits_rate,
unsigned int kbits_burst);
- /* If 'netdev' has an assigned IPv4 address, sets '*in4' to that address.
+ /* If 'netdev' has an assigned IPv4 address, sets '*address' to that
+ * address and '*netmask' to the associated netmask.
*
* The following error values have well-defined meanings:
*
*
* This function may be set to null if it would always return EOPNOTSUPP
* anyhow. */
- int (*get_in4)(const struct netdev *netdev, struct in_addr *in4);
+ int (*get_in4)(const struct netdev *netdev, struct in_addr *address,
+ struct in_addr *netmask);
/* Assigns 'addr' as 'netdev''s IPv4 address and 'mask' as its netmask. If
* 'addr' is INADDR_ANY, 'netdev''s IPv4 address is cleared.
* anyhow. */
int (*add_router)(struct netdev *netdev, struct in_addr router);
+ /* Looks up the next hop for 'host'. If succesful, stores the next hop
+ * gateway's address (0 if 'host' is on a directly connected network) in
+ * '*next_hop' and a copy of the name of the device to reach 'host' in
+ * '*netdev_name', and returns 0. The caller is responsible for freeing
+ * '*netdev_name' (by calling free()).
+ *
+ * This function may be set to null if it would always return EOPNOTSUPP
+ * anyhow. */
+ int (*get_next_hop)(const struct in_addr *host, struct in_addr *next_hop,
+ char **netdev_name);
+
/* Looks up the ARP table entry for 'ip' on 'netdev' and stores the
* corresponding MAC address in 'mac'. A return value of ENXIO, in
* particular, indicates that there is no ARP table entry for 'ip' on
extern const struct netdev_class netdev_linux_class;
extern const struct netdev_class netdev_tap_class;
+extern const struct netdev_class netdev_gre_class;
#endif /* netdev.h */