DESIGN \
FAQ \
INSTALL \
+ INSTALL.Debian \
INSTALL.Fedora \
INSTALL.KVM \
INSTALL.Libvirt \
INSTALL.RHEL \
INSTALL.SSL \
INSTALL.XenServer \
- INSTALL.bridge \
INSTALL.userspace \
IntegrationGuide \
NOTICE \
+ OPENFLOW-1.1+ \
PORTING \
README-gcov \
REPORTING-BUGS \
SUFFIXES += .in
.in:
+ @mkdir -p $$(dirname $@)
$(PERL) $(srcdir)/build-aux/soexpand.pl -I$(srcdir) < $< | \
sed \
-e 's,[@]PKIDIR[@],$(PKIDIR),g' \
(cd datapath && $(MAKE) distfiles); \
(cat distfiles; sed 's|^|datapath/|' datapath/distfiles) | \
sort -u > all-distfiles; \
- (cd $(srcdir) && git ls-files) | grep -v '\.gitignore$$' | \
+ (cd $(srcdir) && git ls-files) | grep -vFf $(srcdir)/.non-distfiles | \
sort -u > all-gitfiles; \
comm -1 -3 all-distfiles all-gitfiles > missing-distfiles; \
if test -s missing-distfiles; then \
endif
.PHONY: dist-hook-git
+ # Check that every .c file includes <config.h>.
+ ALL_LOCAL += config-h-check
+ config-h-check:
+ @cd $(srcdir); \
+ if test -e .git && (git --version) >/dev/null 2>&1 && \
+ git --no-pager grep -L '#include <config\.h>' `git ls-files | grep '\.c$$' | \
+ grep -vE '^datapath|^lib/sflow|^third-party'`; \
+ then \
+ echo "See above for list of violations of the rule that"; \
+ echo "every C source file must #include <config.h>."; \
+ exit 1; \
+ fi
+ .PHONY: config-h-check
+
# Check that "struct vlog_ratelimit" is always declared "static".
ALL_LOCAL += rate-limit-check
rate-limit-check:
uninstall-local: $(UNINSTALL_LOCAL)
.PHONY: $(DIST_HOOKS) $(CLEAN_LOCAL) $(INSTALL_DATA_LOCAL) $(UNINSTALL_LOCAL)
+ modules_install:
+ if LINUX_ENABLED
+ cd datapath/linux && $(MAKE) modules_install
+ endif
+
include lib/automake.mk
include ofproto/automake.mk
include utilities/automake.mk
include xenserver/automake.mk
include python/automake.mk
include python/compat/automake.mk
+include planetlab/automake.mk
lib/multipath.c \
lib/multipath.h \
lib/netdev-dummy.c \
+ lib/netdev-tunnel.c \
+ lib/netdev-pltap.c \
lib/netdev-provider.h \
lib/netdev.c \
lib/netdev.h \
lib/ofp-util.c \
lib/ofp-util.def \
lib/ofp-util.h \
+ lib/ofp-version-opt.h \
+ lib/ofp-version-opt.c \
lib/ofpbuf.c \
lib/ofpbuf.h \
lib/ovsdb-data.c \
lib/timeval.h \
lib/token-bucket.c \
lib/token-bucket.h \
+ lib/tunalloc.c \
+ lib/tunalloc.h \
lib/type-props.h \
lib/unaligned.h \
lib/unicode.c \
lib/daemon-syn.man \
lib/leak-checker.man \
lib/memory-unixctl.man \
+ lib/ofp-version.man \
lib/ovs.tmac \
lib/ssl-bootstrap.man \
lib/ssl-bootstrap-syn.man \
/* Maximum port MTU seen so far. */
static int max_mtu = ETH_PAYLOAD_MAX;
- static int get_port_by_number(struct dp_netdev *, uint16_t port_no,
+ static int get_port_by_number(struct dp_netdev *, uint32_t port_no,
struct dp_netdev_port **portp);
static int get_port_by_name(struct dp_netdev *, const char *devname,
struct dp_netdev_port **portp);
static void dp_netdev_free(struct dp_netdev *);
static void dp_netdev_flow_flush(struct dp_netdev *);
static int do_add_port(struct dp_netdev *, const char *devname,
- const char *type, uint16_t port_no);
- static int do_del_port(struct dp_netdev *, uint16_t port_no);
+ const char *type, uint32_t port_no);
+ static int do_del_port(struct dp_netdev *, uint32_t port_no);
static int dpif_netdev_open(const struct dpif_class *, const char *name,
bool create, struct dpif **);
static int dp_netdev_output_userspace(struct dp_netdev *, const struct ofpbuf *,
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 const char *
++dpif_planetlab_port_open_type(const struct dpif_class *class, const char *type)
++{
++ return strcmp(type, "internal") ? type
++ : class != &dpif_planetlab_class ? "dummy"
++ : "pltap";
++}
++
static struct dpif *
create_dpif_netdev(struct dp_netdev *dp)
{
return &dpif->dpif;
}
- if (dp->class != &dpif_netdev_class) {
+ static int
+ choose_port(struct dp_netdev *dp, const char *name)
+ {
+ int port_no;
+
++ if (dp->class != &dpif_netdev_class &&
++ dp->class != &dpif_planetlab_class) {
+ const char *p;
+ int start_no = 0;
+
+ /* If the port name begins with "br", start the number search at
+ * 100 to make writing tests easier. */
+ if (!strncmp(name, "br", 2)) {
+ start_no = 100;
+ }
+
+ /* If the port name contains a number, try to assign that port number.
+ * This can make writing unit tests easier because port numbers are
+ * predictable. */
+ for (p = name; *p != '\0'; p++) {
+ if (isdigit((unsigned char) *p)) {
+ port_no = start_no + strtol(p, NULL, 10);
+ if (port_no > 0 && port_no < MAX_PORTS
+ && !dp->ports[port_no]) {
+ return port_no;
+ }
+ break;
+ }
+ }
+ }
+
+ for (port_no = 1; port_no < MAX_PORTS; port_no++) {
+ if (!dp->ports[port_no]) {
+ return port_no;
+ }
+ }
+
+ return -1;
+ }
+
static int
create_dp_netdev(const char *name, const struct dpif_class *class,
struct dp_netdev **dpp)
}
hmap_init(&dp->flow_table);
list_init(&dp->port_list);
+
error = do_add_port(dp, name, "internal", OVSP_LOCAL);
if (error) {
dp_netdev_free(dp);
return 0;
}
- static const char* internal_port_type(const struct dp_netdev* dp)
- {
- if (dp->class == &dpif_netdev_class)
- return "tap";
- if (dp->class == &dpif_planetlab_class)
- return "pltap";
- return "dummy";
- }
-
static int
do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
- uint16_t port_no)
+ uint32_t port_no)
{
struct dp_netdev_port *port;
struct netdev *netdev;
/* XXX reject devices already in some dp_netdev. */
/* Open and validate network device. */
- open_type = (strcmp(type, "internal") ? type : internal_port_type(dp));
+ open_type = dpif_netdev_port_open_type(dp->class, type);
error = netdev_open(devname, open_type, &netdev);
if (error) {
return error;
return 0;
}
- static int
- choose_port(struct dpif *dpif, struct netdev *netdev)
- {
- struct dp_netdev *dp = get_dp_netdev(dpif);
- int port_no;
-
- if (dpif->dpif_class != &dpif_netdev_class &&
- dpif->dpif_class != &dpif_planetlab_class)
- {
- /* If the port name contains a number, try to assign that port number.
- * This can make writing unit tests easier because port numbers are
- * predictable. */
- const char *p;
-
- for (p = netdev_get_name(netdev); *p != '\0'; p++) {
- if (isdigit((unsigned char) *p)) {
- port_no = strtol(p, NULL, 10);
- if (port_no > 0 && port_no < MAX_PORTS
- && !dp->ports[port_no]) {
- return port_no;
- }
- break;
- }
- }
- }
-
- for (port_no = 0; port_no < MAX_PORTS; port_no++) {
- if (!dp->ports[port_no]) {
- return port_no;
- }
- }
-
- return -1;
- }
-
static int
dpif_netdev_port_add(struct dpif *dpif, struct netdev *netdev,
- uint16_t *port_nop)
+ uint32_t *port_nop)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
int port_no;
- if (*port_nop != UINT16_MAX) {
+ if (*port_nop != UINT32_MAX) {
if (*port_nop >= MAX_PORTS) {
return EFBIG;
} else if (dp->ports[*port_nop]) {
}
port_no = *port_nop;
} else {
- port_no = choose_port(dpif, netdev);
+ port_no = choose_port(dp, netdev_get_name(netdev));
}
if (port_no >= 0) {
*port_nop = port_no;
}
static int
- dpif_netdev_port_del(struct dpif *dpif, uint16_t port_no)
+ dpif_netdev_port_del(struct dpif *dpif, uint32_t port_no)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
return port_no == OVSP_LOCAL ? EINVAL : do_del_port(dp, port_no);
}
static bool
- is_valid_port_number(uint16_t port_no)
+ is_valid_port_number(uint32_t port_no)
{
return port_no < MAX_PORTS;
}
static int
get_port_by_number(struct dp_netdev *dp,
- uint16_t port_no, struct dp_netdev_port **portp)
+ uint32_t port_no, struct dp_netdev_port **portp)
{
if (!is_valid_port_number(port_no)) {
*portp = NULL;
}
static int
- do_del_port(struct dp_netdev *dp, uint16_t port_no)
+ do_del_port(struct dp_netdev *dp, uint32_t port_no)
{
struct dp_netdev_port *port;
char *name;
}
static int
- dpif_netdev_port_query_by_number(const struct dpif *dpif, uint16_t port_no,
+ dpif_netdev_port_query_by_number(const struct dpif *dpif, uint32_t port_no,
struct dpif_port *dpif_port)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
int error;
error = get_port_by_number(dp, port_no, &port);
- if (!error) {
+ if (!error && dpif_port) {
answer_port_query(port, dpif_port);
}
return error;
int error;
error = get_port_by_name(dp, devname, &port);
- if (!error) {
+ if (!error && dpif_port) {
answer_port_query(port, dpif_port);
}
return error;
dpif_netdev_flow_from_nlattrs(const struct nlattr *key, uint32_t key_len,
struct flow *flow)
{
- if (odp_flow_key_to_flow(key, key_len, flow)) {
+ if (odp_flow_key_to_flow(key, key_len, flow) != ODP_FIT_PERFECT) {
/* This should not happen: it indicates that odp_flow_key_from_flow()
* and odp_flow_key_to_flow() disagree on the acceptable form of a
* flow. Log the problem as an error, with enough details to enable
struct ofpbuf buf;
ofpbuf_use_stack(&buf, &state->keybuf, sizeof state->keybuf);
- odp_flow_key_from_flow(&buf, &flow->key);
+ odp_flow_key_from_flow(&buf, &flow->key, flow->key.in_port);
*key = buf.data;
*key_len = buf.size;
ofpbuf_reserve(©, DP_NETDEV_HEADROOM);
ofpbuf_put(©, execute->packet->data, execute->packet->size);
- flow_extract(©, 0, NULL, -1, &key);
+ flow_extract(©, 0, 0, NULL, -1, &key);
error = dpif_netdev_flow_from_nlattrs(execute->key, execute->key_len,
&key);
if (!error) {
if (packet->size < ETH_HEADER_LEN) {
return;
}
- flow_extract(packet, 0, NULL, odp_port_to_ofp_port(port->port_no), &key);
+ flow_extract(packet, 0, 0, NULL, port->port_no, &key);
flow = dp_netdev_lookup_flow(dp, &key);
if (flow) {
dp_netdev_flow_used(flow, packet);
static void
dp_netdev_output_port(struct dp_netdev *dp, struct ofpbuf *packet,
- uint16_t out_port)
+ uint32_t out_port)
{
struct dp_netdev_port *p = dp->ports[out_port];
if (p) {
buf = &u->buf;
ofpbuf_init(buf, ODPUTIL_FLOW_KEY_BYTES + 2 + packet->size);
- odp_flow_key_from_flow(buf, flow);
+ odp_flow_key_from_flow(buf, flow, flow->in_port);
key_len = buf->size;
ofpbuf_pull(buf, key_len);
ofpbuf_reserve(buf, 2);
{
enum ovs_key_attr type = nl_attr_type(a);
const struct ovs_key_ipv4 *ipv4_key;
+ const struct ovs_key_ipv6 *ipv6_key;
const struct ovs_key_tcp *tcp_key;
const struct ovs_key_udp *udp_key;
switch (type) {
case OVS_KEY_ATTR_TUN_ID:
case OVS_KEY_ATTR_PRIORITY:
- case OVS_KEY_ATTR_IPV6:
+ case OVS_KEY_ATTR_SKB_MARK:
case OVS_KEY_ATTR_IPV4_TUNNEL:
/* not implemented */
break;
ipv4_key->ipv4_tos, ipv4_key->ipv4_ttl);
break;
+ case OVS_KEY_ATTR_IPV6:
+ ipv6_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv6));
+ packet_set_ipv6(packet, ipv6_key->ipv6_proto, ipv6_key->ipv6_src,
+ ipv6_key->ipv6_dst, ipv6_key->ipv6_tclass,
+ ipv6_key->ipv6_label, ipv6_key->ipv6_hlimit);
+ break;
+
case OVS_KEY_ATTR_TCP:
tcp_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_tcp));
packet_set_tcp_port(packet, tcp_key->tcp_src, tcp_key->tcp_dst);
}
}
- #define DPIF_NETDEV_CLASS_FUNCTIONS \
++#define DPIF_NETDEV_CLASS_FUNCTIONS(PORT_OPEN_TYPE) \
+ dpif_netdev_enumerate, \
++ PORT_OPEN_TYPE, \
+ dpif_netdev_open, \
+ dpif_netdev_close, \
+ dpif_netdev_destroy, \
+ dpif_netdev_run, \
+ dpif_netdev_wait, \
+ dpif_netdev_get_stats, \
+ dpif_netdev_port_add, \
+ dpif_netdev_port_del, \
+ dpif_netdev_port_query_by_number, \
+ dpif_netdev_port_query_by_name, \
+ dpif_netdev_get_max_ports, \
+ NULL, /* port_get_pid */ \
+ dpif_netdev_port_dump_start, \
+ dpif_netdev_port_dump_next, \
+ dpif_netdev_port_dump_done, \
+ dpif_netdev_port_poll, \
+ dpif_netdev_port_poll_wait, \
+ dpif_netdev_flow_get, \
+ dpif_netdev_flow_put, \
+ dpif_netdev_flow_del, \
+ dpif_netdev_flow_flush, \
+ dpif_netdev_flow_dump_start, \
+ dpif_netdev_flow_dump_next, \
+ dpif_netdev_flow_dump_done, \
+ dpif_netdev_execute, \
+ NULL, /* operate */ \
+ dpif_netdev_recv_set, \
+ dpif_netdev_queue_to_priority, \
+ dpif_netdev_recv, \
+ dpif_netdev_recv_wait, \
+ dpif_netdev_recv_purge, \
+
const struct dpif_class dpif_netdev_class = {
"netdev",
- DPIF_NETDEV_CLASS_FUNCTIONS
- dpif_netdev_enumerate,
- dpif_netdev_port_open_type,
- dpif_netdev_open,
- dpif_netdev_close,
- dpif_netdev_destroy,
- dpif_netdev_run,
- dpif_netdev_wait,
- dpif_netdev_get_stats,
- dpif_netdev_port_add,
- dpif_netdev_port_del,
- dpif_netdev_port_query_by_number,
- dpif_netdev_port_query_by_name,
- dpif_netdev_get_max_ports,
- NULL, /* port_get_pid */
- dpif_netdev_port_dump_start,
- dpif_netdev_port_dump_next,
- dpif_netdev_port_dump_done,
- dpif_netdev_port_poll,
- dpif_netdev_port_poll_wait,
- dpif_netdev_flow_get,
- dpif_netdev_flow_put,
- dpif_netdev_flow_del,
- dpif_netdev_flow_flush,
- dpif_netdev_flow_dump_start,
- dpif_netdev_flow_dump_next,
- dpif_netdev_flow_dump_done,
- dpif_netdev_execute,
- NULL, /* operate */
- dpif_netdev_recv_set,
- dpif_netdev_queue_to_priority,
- dpif_netdev_recv,
- dpif_netdev_recv_wait,
- dpif_netdev_recv_purge,
++ DPIF_NETDEV_CLASS_FUNCTIONS(dpif_netdev_port_open_type)
+};
+
+const struct dpif_class dpif_planetlab_class = {
+ "planetlab",
- DPIF_NETDEV_CLASS_FUNCTIONS
++ DPIF_NETDEV_CLASS_FUNCTIONS(dpif_planetlab_port_open_type)
};
static void
dpif_dummy_register__("dummy");
}
+
* 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.
*
int (*get_stats)(const struct dpif *dpif, struct dpif_dp_stats *stats);
/* Adds 'netdev' as a new port in 'dpif'. If '*port_no' is not
- * UINT16_MAX, attempts to use that as the port's port number.
+ * UINT32_MAX, attempts to use that as the port's port number.
*
* If port is successfully added, sets '*port_no' to the new port's
* port number. Returns EBUSY if caller attempted to choose a port
* number, and it was in use. */
int (*port_add)(struct dpif *dpif, struct netdev *netdev,
- uint16_t *port_no);
+ uint32_t *port_no);
/* Removes port numbered 'port_no' from 'dpif'. */
- int (*port_del)(struct dpif *dpif, uint16_t port_no);
+ int (*port_del)(struct dpif *dpif, uint32_t port_no);
- /* Queries 'dpif' for a port with the given 'port_no' or 'devname'. Stores
- * information about the port into '*port' if successful.
+ /* Queries 'dpif' for a port with the given 'port_no' or 'devname'.
+ * If 'port' is not null, stores information about the port into
+ * '*port' if successful.
*
- * The caller takes ownership of data in 'port' and must free it with
- * dpif_port_destroy() when it is no longer needed. */
- int (*port_query_by_number)(const struct dpif *dpif, uint16_t port_no,
+ * If 'port' is not null, the caller takes ownership of data in
+ * 'port' and must free it with dpif_port_destroy() when it is no
+ * longer needed. */
+ int (*port_query_by_number)(const struct dpif *dpif, uint32_t port_no,
struct dpif_port *port);
int (*port_query_by_name)(const struct dpif *dpif, const char *devname,
struct dpif_port *port);
* actions as the OVS_USERSPACE_ATTR_PID attribute's value, for use in
* flows whose packets arrived on port 'port_no'.
*
- * A 'port_no' of UINT16_MAX should be treated as a special case. The
+ * A 'port_no' of UINT32_MAX should be treated as a special case. The
* implementation should return a reserved PID, not allocated to any port,
* that the client may use for special purposes.
*
*
* A dpif provider that doesn't have meaningful Netlink PIDs can use NULL
* for this function. This is equivalent to always returning 0. */
- uint32_t (*port_get_pid)(const struct dpif *dpif, uint16_t port_no);
+ uint32_t (*port_get_pid)(const struct dpif *dpif, uint32_t port_no);
/* Attempts to begin dumping the ports in a dpif. On success, returns 0
* and initializes '*statep' with any data needed for iteration. On
extern const struct dpif_class dpif_linux_class;
extern const struct dpif_class dpif_netdev_class;
+extern const struct dpif_class dpif_planetlab_class;
#ifdef __cplusplus
}
&dpif_linux_class,
#endif
&dpif_netdev_class,
+ &dpif_planetlab_class,
};
struct registered_dpif_class {
return dpif->base_name;
}
+ /* Returns the type of datapath 'dpif'. */
+ const char *
+ dpif_type(const struct dpif *dpif)
+ {
+ return dpif->dpif_class->type;
+ }
+
/* Returns the fully spelled out name for the given datapath 'type'.
*
* Normalized type string can be compared with strcmp(). Unnormalized type
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 UINT16_MAX, then attempts to use the
+ * non-null and its value is not UINT32_MAX, then attempts to use the
* value as the port number.
*
* If successful, returns 0 and sets '*port_nop' to the new port's port
* number (if 'port_nop' is non-null). On failure, returns a positive
- * errno value and sets '*port_nop' to UINT16_MAX (if 'port_nop' is
+ * errno value and sets '*port_nop' to UINT32_MAX (if 'port_nop' is
* non-null). */
int
- dpif_port_add(struct dpif *dpif, struct netdev *netdev, uint16_t *port_nop)
+ dpif_port_add(struct dpif *dpif, struct netdev *netdev, uint32_t *port_nop)
{
const char *netdev_name = netdev_get_name(netdev);
- uint16_t port_no = UINT16_MAX;
+ uint32_t port_no = UINT32_MAX;
int error;
COVERAGE_INC(dpif_port_add);
error = dpif->dpif_class->port_add(dpif, netdev, &port_no);
if (!error) {
- VLOG_DBG_RL(&dpmsg_rl, "%s: added %s as port %"PRIu16,
+ VLOG_DBG_RL(&dpmsg_rl, "%s: added %s as port %"PRIu32,
dpif_name(dpif), netdev_name, port_no);
} else {
VLOG_WARN_RL(&error_rl, "%s: failed to add %s as port: %s",
dpif_name(dpif), netdev_name, strerror(error));
- port_no = UINT16_MAX;
+ port_no = UINT32_MAX;
}
if (port_nop) {
*port_nop = port_no;
/* Attempts to remove 'dpif''s port number 'port_no'. Returns 0 if successful,
* otherwise a positive errno value. */
int
- dpif_port_del(struct dpif *dpif, uint16_t port_no)
+ dpif_port_del(struct dpif *dpif, uint32_t port_no)
{
int error;
error = dpif->dpif_class->port_del(dpif, port_no);
if (!error) {
- VLOG_DBG_RL(&dpmsg_rl, "%s: port_del(%"PRIu16")",
+ VLOG_DBG_RL(&dpmsg_rl, "%s: port_del(%"PRIu32")",
dpif_name(dpif), port_no);
} else {
log_operation(dpif, "port_del", error);
free(dpif_port->type);
}
+ /* Checks if port named 'devname' exists in 'dpif'. If so, returns
+ * true; otherwise, returns false. */
+ bool
+ dpif_port_exists(const struct dpif *dpif, const char *devname)
+ {
+ int error = dpif->dpif_class->port_query_by_name(dpif, devname, NULL);
+ if (error != 0 && error != ENOENT && error != ENODEV) {
+ VLOG_WARN_RL(&error_rl, "%s: failed to query port %s: %s",
+ dpif_name(dpif), devname, strerror(error));
+ }
+
+ return !error;
+ }
+
/* Looks up port number 'port_no' in 'dpif'. On success, returns 0 and
* initializes '*port' appropriately; on failure, returns a positive errno
* value.
* The caller owns the data in 'port' and must free it with
* dpif_port_destroy() when it is no longer needed. */
int
- dpif_port_query_by_number(const struct dpif *dpif, uint16_t port_no,
+ dpif_port_query_by_number(const struct dpif *dpif, uint32_t port_no,
struct dpif_port *port)
{
int error = dpif->dpif_class->port_query_by_number(dpif, port_no, port);
if (!error) {
- VLOG_DBG_RL(&dpmsg_rl, "%s: port %"PRIu16" is device %s",
+ VLOG_DBG_RL(&dpmsg_rl, "%s: port %"PRIu32" is device %s",
dpif_name(dpif), port_no, port->name);
} else {
memset(port, 0, sizeof *port);
- VLOG_WARN_RL(&error_rl, "%s: failed to query port %"PRIu16": %s",
+ VLOG_WARN_RL(&error_rl, "%s: failed to query port %"PRIu32": %s",
dpif_name(dpif), port_no, strerror(error));
}
return error;
{
int error = dpif->dpif_class->port_query_by_name(dpif, devname, port);
if (!error) {
- VLOG_DBG_RL(&dpmsg_rl, "%s: device %s is on port %"PRIu16,
+ VLOG_DBG_RL(&dpmsg_rl, "%s: device %s is on port %"PRIu32,
dpif_name(dpif), devname, port->port_no);
} else {
memset(port, 0, sizeof *port);
* as the OVS_USERSPACE_ATTR_PID attribute's value, for use in flows whose
* packets arrived on port 'port_no'.
*
- * A 'port_no' of UINT16_MAX is a special case: it returns a reserved PID, not
+ * A 'port_no' of UINT32_MAX is a special case: it returns a reserved PID, not
* allocated to any port, that the client may use for special purposes.
*
* The return value is only meaningful when DPIF_UC_ACTION has been enabled in
* update all of the flows that it installed that contain
* OVS_ACTION_ATTR_USERSPACE actions. */
uint32_t
- dpif_port_get_pid(const struct dpif *dpif, uint16_t port_no)
+ dpif_port_get_pid(const struct dpif *dpif, uint32_t port_no)
{
return (dpif->dpif_class->port_get_pid
? (dpif->dpif_class->port_get_pid)(dpif, port_no)
* result is null-terminated. On failure, returns a positive errno value and
* makes 'name' the empty string. */
int
- dpif_port_get_name(struct dpif *dpif, uint16_t port_no,
+ dpif_port_get_name(struct dpif *dpif, uint32_t port_no,
char *name, size_t name_size)
{
struct dpif_port port;
/*
- * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* pointer. */
int (*set_config)(struct netdev_dev *netdev_dev, const struct smap *args);
+ /* Returns the tunnel configuration of 'netdev_dev'. If 'netdev_dev' is
+ * not a tunnel, returns null.
+ *
+ * If this function would always return null, it may be null instead. */
+ const struct netdev_tunnel_config *
+ (*get_tunnel_config)(const struct netdev_dev *netdev_dev);
+
/* Attempts to open a network device. On success, sets 'netdevp'
* to the new network device. */
int (*open)(struct netdev_dev *netdev_dev, struct netdev **netdevp);
/* Retrieves driver information of the device.
*
- * Populates 'sh' with key-value pairs representing the status of the
- * device. Driver info is a set of key-value string pairs
- * representing netdev type specific information. For more information see
+ * Populates 'smap' with key-value pairs representing the status of the
+ * device. 'smap' is a set of key-value string pairs representing netdev
+ * type specific information. For more information see
* ovs-vswitchd.conf.db(5).
*
* The caller is responsible for destroying 'smap' and its data.
*
* This function may be set to null if it would always return EOPNOTSUPP
* anyhow. */
- int (*get_drv_info)(const struct netdev *netdev, struct smap *smap);
+ int (*get_status)(const struct netdev *netdev, struct smap *smap);
/* Looks up the ARP table entry for 'ip' on 'netdev' and stores the
* corresponding MAC address in 'mac'. A return value of ENXIO, in
extern const struct netdev_class netdev_bsd_class;
#endif
+extern const struct netdev_class netdev_tunnel_class;
+extern const struct netdev_class netdev_pltap_class;
+
#ifdef __cplusplus
}
#endif
/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
netdev_register_provider(&netdev_tap_class);
netdev_register_provider(&netdev_bsd_class);
#endif
+ netdev_register_provider(&netdev_tunnel_class);
+ netdev_register_provider(&netdev_pltap_class);
}
}
return error;
}
+ const struct netdev_tunnel_config *
+ netdev_get_tunnel_config(const struct netdev *netdev)
+ {
+ struct netdev_dev *netdev_dev = netdev_get_dev(netdev);
+
+ if (netdev_dev->netdev_class->get_tunnel_config) {
+ return netdev_dev->netdev_class->get_tunnel_config(netdev_dev);
+ } else {
+ return NULL;
+ }
+ }
+
/* Closes and destroys 'netdev'. */
void
netdev_close(struct netdev *netdev)
/* Returns the maximum speed of a network connection that has the NETDEV_F_*
* bits in 'features', in bits per second. If no bits that indicate a speed
- * are set in 'features', assumes 100Mbps. */
+ * are set in 'features', returns 'default_bps'. */
uint64_t
- netdev_features_to_bps(enum netdev_features features)
+ netdev_features_to_bps(enum netdev_features features,
+ uint64_t default_bps)
{
enum {
F_1000000MB = NETDEV_F_1TB_FD,
: features & F_1000MB ? UINT64_C(1000000000)
: features & F_100MB ? UINT64_C(100000000)
: features & F_10MB ? UINT64_C(10000000)
- : UINT64_C(100000000));
+ : default_bps);
}
/* Returns true if any of the NETDEV_F_* bits that indicate a full-duplex link
* information may be used to populate the status column of the Interface table
* as defined in ovs-vswitchd.conf.db(5). */
int
- netdev_get_drv_info(const struct netdev *netdev, struct smap *smap)
+ netdev_get_status(const struct netdev *netdev, struct smap *smap)
{
struct netdev_dev *dev = netdev_get_dev(netdev);
- return (dev->netdev_class->get_drv_info
- ? dev->netdev_class->get_drv_info(netdev, smap)
+ return (dev->netdev_class->get_status
+ ? dev->netdev_class->get_status(netdev, smap)
: EOPNOTSUPP);
}