From: Justin Pettit Date: Wed, 14 Nov 2012 23:50:20 +0000 (-0800) Subject: Add functions to determine how port should be opened based on type. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0aeaabc8dbccef7593dc19e891a3f5bbef1991cd;p=openvswitch Add functions to determine how port should be opened based on type. Depending on the port and type of datapath, a port may need to be opened as a different type of device than it's configured. For example, an "internal" port on a "dummy" datapath should opened as a "dummy" port. This commit adds the ability for a dpif to provide this information to a caller. It will be used in a future commit. Signed-off-by: Justin Pettit --- diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c index 67ff805b..496230e0 100644 --- a/lib/dpif-linux.c +++ b/lib/dpif-linux.c @@ -1281,6 +1281,7 @@ dpif_linux_recv_purge(struct dpif *dpif_) const struct dpif_class dpif_linux_class = { "system", dpif_linux_enumerate, + NULL, dpif_linux_open, dpif_linux_close, dpif_linux_destroy, diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index a294ffc8..cd4ab282 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -181,6 +181,14 @@ dpif_netdev_enumerate(struct sset *all_dps) return 0; } +static const char * +dpif_netdev_port_open_type(const struct dpif_class *class, const char *type) +{ + return strcmp(type, "internal") ? type + : class != &dpif_netdev_class ? "dummy" + : "tap"; +} + static struct dpif * create_dpif_netdev(struct dp_netdev *dp) { @@ -369,9 +377,7 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type, /* XXX reject devices already in some dp_netdev. */ /* Open and validate network device. */ - open_type = (strcmp(type, "internal") ? type - : dp->class != &dpif_netdev_class ? "dummy" - : "tap"); + open_type = dpif_netdev_port_open_type(dp->class, type); error = netdev_open(devname, open_type, &netdev); if (error) { return error; @@ -1282,6 +1288,7 @@ dp_netdev_execute_actions(struct dp_netdev *dp, const struct dpif_class dpif_netdev_class = { "netdev", dpif_netdev_enumerate, + dpif_netdev_port_open_type, dpif_netdev_open, dpif_netdev_close, dpif_netdev_destroy, diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h index bc189429..74120cda 100644 --- a/lib/dpif-provider.h +++ b/lib/dpif-provider.h @@ -80,6 +80,17 @@ struct dpif_class { * case this function may be a null pointer. */ int (*enumerate)(struct sset *all_dps); + /* Returns the type to pass to netdev_open() when a dpif of class + * 'dpif_class' has a port of type 'type', for a few special cases + * when a netdev type differs from a port type. For example, when + * using the userspace datapath, a port of type "internal" needs to + * be opened as "tap". + * + * Returns either 'type' itself or a string literal, which must not + * be freed. */ + const char *(*port_open_type)(const struct dpif_class *dpif_class, + const char *type); + /* Attempts to open an existing dpif called 'name', if 'create' is false, * or to open an existing dpif or create a new one, if 'create' is true. * diff --git a/lib/dpif.c b/lib/dpif.c index 0093f614..9577e4fa 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -417,6 +417,23 @@ dpif_get_dp_stats(const struct dpif *dpif, struct dpif_dp_stats *stats) return error; } +const char * +dpif_port_open_type(const char *datapath_type, const char *port_type) +{ + struct registered_dpif_class *registered_class; + + datapath_type = dpif_normalize_type(datapath_type); + + registered_class = shash_find_data(&dpif_classes, datapath_type); + if (!registered_class + || !registered_class->dpif_class->port_open_type) { + return port_type; + } + + return registered_class->dpif_class->port_open_type( + registered_class->dpif_class, port_type); +} + /* Attempts to add 'netdev' as a port on 'dpif'. If 'port_nop' is * non-null and its value is not UINT32_MAX, then attempts to use the * value as the port number. diff --git a/lib/dpif.h b/lib/dpif.h index 7d0881fa..893338b2 100644 --- a/lib/dpif.h +++ b/lib/dpif.h @@ -73,6 +73,8 @@ int dpif_get_dp_stats(const struct dpif *, struct dpif_dp_stats *); /* Port operations. */ +const char *dpif_port_open_type(const char *datapath_type, + const char *port_type); int dpif_port_add(struct dpif *, struct netdev *, uint32_t *port_nop); int dpif_port_del(struct dpif *, uint32_t port_no); diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 283aea98..fe0aae3b 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -780,6 +780,12 @@ del(const char *type, const char *name) return error; } +static const char * +port_open_type(const char *datapath_type, const char *port_type) +{ + return dpif_port_open_type(datapath_type, port_type); +} + /* Type functions. */ static int @@ -7865,6 +7871,7 @@ const struct ofproto_class ofproto_dpif_class = { enumerate_types, enumerate_names, del, + port_open_type, type_run, type_run_fast, type_wait, diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index 26343cf0..8f6f6b1a 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -382,6 +382,17 @@ struct ofproto_class { */ int (*del)(const char *type, const char *name); + /* Returns the type to pass to netdev_open() when a datapath of type + * 'datapath_type' has a port of type 'port_type', for a few special + * cases when a netdev type differs from a port type. For example, + * when using the userspace datapath, a port of type "internal" + * needs to be opened as "tap". + * + * Returns either 'type' itself or a string literal, which must not + * be freed. */ + const char *(*port_open_type)(const char *datapath_type, + const char *port_type); + /* ## ------------------------ ## */ /* ## Top-Level type Functions ## */ /* ## ------------------------ ## */ diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 0aeb07e2..182da633 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -1433,6 +1433,30 @@ ofproto_port_dump_done(struct ofproto_port_dump *dump) return dump->error == EOF ? 0 : dump->error; } +/* Returns the type to pass to netdev_open() when a datapath of type + * 'datapath_type' has a port of type 'port_type', for a few special + * cases when a netdev type differs from a port type. For example, when + * using the userspace datapath, a port of type "internal" needs to be + * opened as "tap". + * + * Returns either 'type' itself or a string literal, which must not be + * freed. */ +const char * +ofproto_port_open_type(const char *datapath_type, const char *port_type) +{ + const struct ofproto_class *class; + + datapath_type = ofproto_normalize_type(datapath_type); + class = ofproto_class_find__(datapath_type); + if (!class) { + return port_type; + } + + return (class->port_open_type + ? class->port_open_type(datapath_type, port_type) + : port_type); +} + /* Attempts to add 'netdev' as a port on 'ofproto'. If 'ofp_portp' is * non-null and '*ofp_portp' is not OFPP_NONE, attempts to use that as * the port's OpenFlow port number. diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index 0366c89f..e4abe523 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -207,6 +207,8 @@ int ofproto_port_dump_done(struct ofproto_port_dump *); #define OFPROTO_FLOW_EVICTION_THRESHOLD_DEFAULT 1000 #define OFPROTO_FLOW_EVICTION_THRESHOLD_MIN 100 +const char *ofproto_port_open_type(const char *datapath_type, + const char *port_type); int ofproto_port_add(struct ofproto *, struct netdev *, uint16_t *ofp_portp); int ofproto_port_del(struct ofproto *, uint16_t ofp_port); int ofproto_port_get_stats(const struct ofport *, struct netdev_stats *stats);