projects
/
openvswitch
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
ofp-print: Do not display flow mod cookie if it is UINT64_MAX
[openvswitch]
/
lib
/
dpif-netdev.c
diff --git
a/lib/dpif-netdev.c
b/lib/dpif-netdev.c
index e2fb816bd6126cb443c3aaaa35b466980298ffd2..c9e3210f13209ef167f1d6313057d67f044dc281 100644
(file)
--- a/
lib/dpif-netdev.c
+++ b/
lib/dpif-netdev.c
@@
-1,5
+1,5
@@
/*
/*
- * Copyright (c) 2009, 2010, 2011, 2012 Nicira
Networks
.
+ * Copyright (c) 2009, 2010, 2011, 2012 Nicira
, Inc
.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@
-49,6
+49,7
@@
#include "poll-loop.h"
#include "random.h"
#include "shash.h"
#include "poll-loop.h"
#include "random.h"
#include "shash.h"
+#include "sset.h"
#include "timeval.h"
#include "util.h"
#include "vlog.h"
#include "timeval.h"
#include "util.h"
#include "vlog.h"
@@
-69,8
+70,13
@@
enum { MAX_QUEUE_LEN = 128 }; /* Maximum number of packets per queue. */
enum { QUEUE_MASK = MAX_QUEUE_LEN - 1 };
BUILD_ASSERT_DECL(IS_POW2(MAX_QUEUE_LEN));
enum { QUEUE_MASK = MAX_QUEUE_LEN - 1 };
BUILD_ASSERT_DECL(IS_POW2(MAX_QUEUE_LEN));
+struct dp_netdev_upcall {
+ struct dpif_upcall upcall; /* Queued upcall information. */
+ struct ofpbuf buf; /* ofpbuf instance for upcall.packet. */
+};
+
struct dp_netdev_queue {
struct dp_netdev_queue {
- struct dp
if_upcall *
upcalls[MAX_QUEUE_LEN];
+ struct dp
_netdev_upcall
upcalls[MAX_QUEUE_LEN];
unsigned int head, tail;
};
unsigned int head, tail;
};
@@
-100,7
+106,7
@@
struct dp_netdev_port {
int port_no; /* Index into dp_netdev's 'ports'. */
struct list node; /* Element in dp_netdev's 'port_list'. */
struct netdev *netdev;
int port_no; /* Index into dp_netdev's 'ports'. */
struct list node; /* Element in dp_netdev's 'port_list'. */
struct netdev *netdev;
-
bool internal; /* Internal port?
*/
+
char *type; /* Port type as requested by user.
*/
};
/* A flow in dp_netdev's 'flow_table'. */
};
/* A flow in dp_netdev's 'flow_table'. */
@@
-112,7
+118,7
@@
struct dp_netdev_flow {
long long int used; /* Last used time, in monotonic msecs. */
long long int packet_count; /* Number of packets matched. */
long long int byte_count; /* Number of bytes matched. */
long long int used; /* Last used time, in monotonic msecs. */
long long int packet_count; /* Number of packets matched. */
long long int byte_count; /* Number of bytes matched. */
-
ovs_be16 tcp_ctl; /* Bitwise-OR of seen tcp_ctl
values. */
+
uint8_t tcp_flags; /* Bitwise-OR of seen tcp_flags
values. */
/* Actions. */
struct nlattr *actions;
/* Actions. */
struct nlattr *actions;
@@
-151,8
+157,6
@@
static void dp_netdev_execute_actions(struct dp_netdev *,
const struct nlattr *actions,
size_t actions_len);
const struct nlattr *actions,
size_t actions_len);
-static struct dpif_class dpif_dummy_class;
-
static struct dpif_netdev *
dpif_netdev_cast(const struct dpif *dpif)
{
static struct dpif_netdev *
dpif_netdev_cast(const struct dpif *dpif)
{
@@
-166,6
+170,17
@@
get_dp_netdev(const struct dpif *dpif)
return dpif_netdev_cast(dpif)->dp;
}
return dpif_netdev_cast(dpif)->dp;
}
+static int
+dpif_netdev_enumerate(struct sset *all_dps)
+{
+ struct shash_node *node;
+
+ SHASH_FOR_EACH(node, &dp_netdevs) {
+ sset_add(all_dps, node->name);
+ }
+ return 0;
+}
+
static struct dpif *
create_dpif_netdev(struct dp_netdev *dp)
{
static struct dpif *
create_dpif_netdev(struct dp_netdev *dp)
{
@@
-249,10
+264,8
@@
dp_netdev_purge_queues(struct dp_netdev *dp)
struct dp_netdev_queue *q = &dp->queues[i];
while (q->tail != q->head) {
struct dp_netdev_queue *q = &dp->queues[i];
while (q->tail != q->head) {
- struct dpif_upcall *upcall = q->upcalls[q->tail++ & QUEUE_MASK];
-
- ofpbuf_delete(upcall->packet);
- free(upcall);
+ struct dp_netdev_upcall *u = &q->upcalls[q->tail++ & QUEUE_MASK];
+ ofpbuf_uninit(&u->buf);
}
}
}
}
}
}
@@
-309,28
+322,17
@@
do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
{
struct dp_netdev_port *port;
struct netdev *netdev;
{
struct dp_netdev_port *port;
struct netdev *netdev;
-
bool internal
;
+
const char *open_type
;
int mtu;
int error;
/* XXX reject devices already in some dp_netdev. */
int mtu;
int error;
/* XXX reject devices already in some dp_netdev. */
- if (type[0] == '\0' || !strcmp(type, "system") || !strcmp(type, "dummy")) {
- internal = false;
- } else if (!strcmp(type, "internal")) {
- internal = true;
- } else {
- VLOG_WARN("%s: unsupported port type %s", devname, type);
- return EINVAL;
- }
/* Open and validate network device. */
/* Open and validate network device. */
- if (dp->class == &dpif_dummy_class) {
- type = "dummy";
- } else if (internal) {
- type = "tap";
- }
-
- error = netdev_open(devname, type, &netdev);
+ open_type = (strcmp(type, "internal") ? type
+ : dp->class != &dpif_netdev_class ? "dummy"
+ : "tap");
+ error = netdev_open(devname, open_type, &netdev);
if (error) {
return error;
}
if (error) {
return error;
}
@@
-354,7
+356,7
@@
do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
port = xmalloc(sizeof *port);
port->port_no = port_no;
port->netdev = netdev;
port = xmalloc(sizeof *port);
port->port_no = port_no;
port->netdev = netdev;
- port->
internal = internal
;
+ port->
type = xstrdup(type)
;
error = netdev_get_mtu(netdev, &mtu);
if (!error) {
error = netdev_get_mtu(netdev, &mtu);
if (!error) {
@@
-374,7
+376,7
@@
choose_port(struct dpif *dpif, struct netdev *netdev)
struct dp_netdev *dp = get_dp_netdev(dpif);
int port_no;
struct dp_netdev *dp = get_dp_netdev(dpif);
int port_no;
- if (dpif->dpif_class
== &dpif_dummy
_class) {
+ if (dpif->dpif_class
!= &dpif_netdev
_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. */
/* 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. */
@@
-408,7
+410,16
@@
dpif_netdev_port_add(struct dpif *dpif, struct netdev *netdev,
struct dp_netdev *dp = get_dp_netdev(dpif);
int port_no;
struct dp_netdev *dp = get_dp_netdev(dpif);
int port_no;
- port_no = choose_port(dpif, netdev);
+ if (*port_nop != UINT16_MAX) {
+ if (*port_nop >= MAX_PORTS) {
+ return EFBIG;
+ } else if (dp->ports[*port_nop]) {
+ return EBUSY;
+ }
+ port_no = *port_nop;
+ } else {
+ port_no = choose_port(dpif, netdev);
+ }
if (port_no >= 0) {
*port_nop = port_no;
return do_add_port(dp, netdev_get_name(netdev),
if (port_no >= 0) {
*port_nop = port_no;
return do_add_port(dp, netdev_get_name(netdev),
@@
-476,6
+487,7
@@
do_del_port(struct dp_netdev *dp, uint16_t port_no)
name = xstrdup(netdev_get_name(port->netdev));
netdev_close(port->netdev);
name = xstrdup(netdev_get_name(port->netdev));
netdev_close(port->netdev);
+ free(port->type);
free(name);
free(port);
free(name);
free(port);
@@
-488,8
+500,7
@@
answer_port_query(const struct dp_netdev_port *port,
struct dpif_port *dpif_port)
{
dpif_port->name = xstrdup(netdev_get_name(port->netdev));
struct dpif_port *dpif_port)
{
dpif_port->name = xstrdup(netdev_get_name(port->netdev));
- dpif_port->type = xstrdup(port->internal ? "internal"
- : netdev_get_type(port->netdev));
+ dpif_port->type = xstrdup(port->type);
dpif_port->port_no = port->port_no;
}
dpif_port->port_no = port->port_no;
}
@@
-581,8
+592,7
@@
dpif_netdev_port_dump_next(const struct dpif *dpif, void *state_,
free(state->name);
state->name = xstrdup(netdev_get_name(port->netdev));
dpif_port->name = state->name;
free(state->name);
state->name = xstrdup(netdev_get_name(port->netdev));
dpif_port->name = state->name;
- dpif_port->type = (char *) (port->internal ? "internal"
- : netdev_get_type(port->netdev));
+ dpif_port->type = port->type;
dpif_port->port_no = port->port_no;
state->port_no = port_no + 1;
return 0;
dpif_port->port_no = port->port_no;
state->port_no = port_no + 1;
return 0;
@@
-640,7
+650,7
@@
get_dpif_flow_stats(struct dp_netdev_flow *flow, struct dpif_flow_stats *stats)
stats->n_packets = flow->packet_count;
stats->n_bytes = flow->byte_count;
stats->used = flow->used;
stats->n_packets = flow->packet_count;
stats->n_bytes = flow->byte_count;
stats->used = flow->used;
- stats->tcp_flags =
TCP_FLAGS(flow->tcp_ctl)
;
+ stats->tcp_flags =
flow->tcp_flags
;
}
static int
}
static int
@@
-715,10
+725,9
@@
set_flow_actions(struct dp_netdev_flow *flow,
}
static int
}
static int
-
add_flow(struct dpif *dpif
, const struct flow *key,
- const struct nlattr *actions, size_t actions_len)
+
dp_netdev_flow_add(struct dp_netdev *dp
, const struct flow *key,
+
const struct nlattr *actions, size_t actions_len)
{
{
- struct dp_netdev *dp = get_dp_netdev(dpif);
struct dp_netdev_flow *flow;
int error;
struct dp_netdev_flow *flow;
int error;
@@
-741,33
+750,31
@@
clear_stats(struct dp_netdev_flow *flow)
flow->used = 0;
flow->packet_count = 0;
flow->byte_count = 0;
flow->used = 0;
flow->packet_count = 0;
flow->byte_count = 0;
- flow->tcp_
ctl
= 0;
+ flow->tcp_
flags
= 0;
}
static int
}
static int
-dpif_netdev_flow_put(struct dpif *dpif, enum dpif_flow_put_flags flags,
- const struct nlattr *nl_key, size_t nl_key_len,
- const struct nlattr *actions, size_t actions_len,
- struct dpif_flow_stats *stats)
+dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
struct dp_netdev_flow *flow;
struct flow key;
int error;
{
struct dp_netdev *dp = get_dp_netdev(dpif);
struct dp_netdev_flow *flow;
struct flow key;
int error;
- error = dpif_netdev_flow_from_nlattrs(
nl_key, nl_
key_len, &key);
+ error = dpif_netdev_flow_from_nlattrs(
put->key, put->
key_len, &key);
if (error) {
return error;
}
flow = dp_netdev_lookup_flow(dp, &key);
if (!flow) {
if (error) {
return error;
}
flow = dp_netdev_lookup_flow(dp, &key);
if (!flow) {
- if (flags & DPIF_FP_CREATE) {
+ if (
put->
flags & DPIF_FP_CREATE) {
if (hmap_count(&dp->flow_table) < MAX_FLOWS) {
if (hmap_count(&dp->flow_table) < MAX_FLOWS) {
- if (stats) {
- memset(
stats, 0, sizeof *
stats);
+ if (
put->
stats) {
+ memset(
put->stats, 0, sizeof *put->
stats);
}
}
- return add_flow(dpif, &key, actions, actions_len);
+ return dp_netdev_flow_add(dp, &key, put->actions,
+ put->actions_len);
} else {
return EFBIG;
}
} else {
return EFBIG;
}
@@
-775,13
+782,13
@@
dpif_netdev_flow_put(struct dpif *dpif, enum dpif_flow_put_flags flags,
return ENOENT;
}
} else {
return ENOENT;
}
} else {
- if (flags & DPIF_FP_MODIFY) {
- int error = set_flow_actions(flow,
actions,
actions_len);
+ if (
put->
flags & DPIF_FP_MODIFY) {
+ int error = set_flow_actions(flow,
put->actions, put->
actions_len);
if (!error) {
if (!error) {
- if (stats) {
- get_dpif_flow_stats(flow, stats);
+ if (
put->
stats) {
+ get_dpif_flow_stats(flow,
put->
stats);
}
}
- if (flags & DPIF_FP_ZERO_STATS) {
+ if (
put->
flags & DPIF_FP_ZERO_STATS) {
clear_stats(flow);
}
}
clear_stats(flow);
}
}
@@
-793,24
+800,22
@@
dpif_netdev_flow_put(struct dpif *dpif, enum dpif_flow_put_flags flags,
}
static int
}
static int
-dpif_netdev_flow_del(struct dpif *dpif,
- const struct nlattr *nl_key, size_t nl_key_len,
- struct dpif_flow_stats *stats)
+dpif_netdev_flow_del(struct dpif *dpif, const struct dpif_flow_del *del)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
struct dp_netdev_flow *flow;
struct flow key;
int error;
{
struct dp_netdev *dp = get_dp_netdev(dpif);
struct dp_netdev_flow *flow;
struct flow key;
int error;
- error = dpif_netdev_flow_from_nlattrs(
nl_key, nl_
key_len, &key);
+ error = dpif_netdev_flow_from_nlattrs(
del->key, del->
key_len, &key);
if (error) {
return error;
}
flow = dp_netdev_lookup_flow(dp, &key);
if (flow) {
if (error) {
return error;
}
flow = dp_netdev_lookup_flow(dp, &key);
if (flow) {
- if (stats) {
- get_dpif_flow_stats(flow, stats);
+ if (
del->
stats) {
+ get_dpif_flow_stats(flow,
del->
stats);
}
dp_netdev_free_flow(dp, flow);
return 0;
}
dp_netdev_free_flow(dp, flow);
return 0;
@@
-894,30
+899,29
@@
dpif_netdev_flow_dump_done(const struct dpif *dpif OVS_UNUSED, void *state_)
}
static int
}
static int
-dpif_netdev_execute(struct dpif *dpif,
- const struct nlattr *key_attrs, size_t key_len,
- const struct nlattr *actions, size_t actions_len,
- const struct ofpbuf *packet)
+dpif_netdev_execute(struct dpif *dpif, const struct dpif_execute *execute)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
struct ofpbuf copy;
struct flow key;
int error;
{
struct dp_netdev *dp = get_dp_netdev(dpif);
struct ofpbuf copy;
struct flow key;
int error;
- if (packet->size < ETH_HEADER_LEN || packet->size > UINT16_MAX) {
+ if (execute->packet->size < ETH_HEADER_LEN ||
+ execute->packet->size > UINT16_MAX) {
return EINVAL;
}
/* Make a deep copy of 'packet', because we might modify its data. */
return EINVAL;
}
/* Make a deep copy of 'packet', because we might modify its data. */
- ofpbuf_init(©, DP_NETDEV_HEADROOM + packet->size);
+ ofpbuf_init(©, DP_NETDEV_HEADROOM +
execute->
packet->size);
ofpbuf_reserve(©, DP_NETDEV_HEADROOM);
ofpbuf_reserve(©, DP_NETDEV_HEADROOM);
- ofpbuf_put(©,
packet->data,
packet->size);
+ ofpbuf_put(©,
execute->packet->data, execute->
packet->size);
- flow_extract(©, 0, 0, -1, &key);
- error = dpif_netdev_flow_from_nlattrs(key_attrs, key_len, &key);
+ flow_extract(©, 0, NULL, -1, &key);
+ error = dpif_netdev_flow_from_nlattrs(execute->key, execute->key_len,
+ &key);
if (!error) {
dp_netdev_execute_actions(dp, ©, &key,
if (!error) {
dp_netdev_execute_actions(dp, ©, &key,
-
actions,
actions_len);
+
execute->actions, execute->
actions_len);
}
ofpbuf_uninit(©);
}
ofpbuf_uninit(©);
@@
-954,13
+958,18
@@
find_nonempty_queue(struct dpif *dpif)
}
static int
}
static int
-dpif_netdev_recv(struct dpif *dpif, struct dpif_upcall *upcall)
+dpif_netdev_recv(struct dpif *dpif, struct dpif_upcall *upcall,
+ struct ofpbuf *buf)
{
struct dp_netdev_queue *q = find_nonempty_queue(dpif);
if (q) {
{
struct dp_netdev_queue *q = find_nonempty_queue(dpif);
if (q) {
- struct dpif_upcall *u = q->upcalls[q->tail++ & QUEUE_MASK];
- *upcall = *u;
- free(u);
+ struct dp_netdev_upcall *u = &q->upcalls[q->tail++ & QUEUE_MASK];
+
+ *upcall = u->upcall;
+ upcall->packet = buf;
+
+ ofpbuf_uninit(buf);
+ *buf = u->buf;
return 0;
} else {
return 0;
} else {
@@
-987,16
+996,12
@@
dpif_netdev_recv_purge(struct dpif *dpif)
}
\f
static void
}
\f
static void
-dp_netdev_flow_used(struct dp_netdev_flow *flow, struct flow *key,
- const struct ofpbuf *packet)
+dp_netdev_flow_used(struct dp_netdev_flow *flow, const struct ofpbuf *packet)
{
flow->used = time_msec();
flow->packet_count++;
flow->byte_count += packet->size;
{
flow->used = time_msec();
flow->packet_count++;
flow->byte_count += packet->size;
- if (key->dl_type == htons(ETH_TYPE_IP) && key->nw_proto == IPPROTO_TCP) {
- struct tcp_header *th = packet->l4;
- flow->tcp_ctl |= th->tcp_ctl;
- }
+ flow->tcp_flags |= packet_get_tcp_flags(packet, &flow->key);
}
static void
}
static void
@@
-1009,10
+1014,10
@@
dp_netdev_port_input(struct dp_netdev *dp, struct dp_netdev_port *port,
if (packet->size < ETH_HEADER_LEN) {
return;
}
if (packet->size < ETH_HEADER_LEN) {
return;
}
- flow_extract(packet, 0,
0, port->port_no
, &key);
+ flow_extract(packet, 0,
NULL, odp_port_to_ofp_port(port->port_no)
, &key);
flow = dp_netdev_lookup_flow(dp, &key);
if (flow) {
flow = dp_netdev_lookup_flow(dp, &key);
if (flow) {
- dp_netdev_flow_used(flow,
&key,
packet);
+ dp_netdev_flow_used(flow, packet);
dp_netdev_execute_actions(dp, packet, &key,
flow->actions, flow->actions_len);
dp->n_hit++;
dp_netdev_execute_actions(dp, packet, &key,
flow->actions, flow->actions_len);
dp->n_hit++;
@@
-1085,6
+1090,7
@@
dp_netdev_output_userspace(struct dp_netdev *dp, const struct ofpbuf *packet,
int queue_no, const struct flow *flow, uint64_t arg)
{
struct dp_netdev_queue *q = &dp->queues[queue_no];
int queue_no, const struct flow *flow, uint64_t arg)
{
struct dp_netdev_queue *q = &dp->queues[queue_no];
+ struct dp_netdev_upcall *u;
struct dpif_upcall *upcall;
struct ofpbuf *buf;
size_t key_len;
struct dpif_upcall *upcall;
struct ofpbuf *buf;
size_t key_len;
@@
-1094,22
+1100,23
@@
dp_netdev_output_userspace(struct dp_netdev *dp, const struct ofpbuf *packet,
return ENOBUFS;
}
return ENOBUFS;
}
- buf = ofpbuf_new(ODPUTIL_FLOW_KEY_BYTES + 2 + packet->size);
+ u = &q->upcalls[q->head++ & QUEUE_MASK];
+
+ buf = &u->buf;
+ ofpbuf_init(buf, ODPUTIL_FLOW_KEY_BYTES + 2 + packet->size);
odp_flow_key_from_flow(buf, flow);
key_len = buf->size;
ofpbuf_pull(buf, key_len);
ofpbuf_reserve(buf, 2);
ofpbuf_put(buf, packet->data, packet->size);
odp_flow_key_from_flow(buf, flow);
key_len = buf->size;
ofpbuf_pull(buf, key_len);
ofpbuf_reserve(buf, 2);
ofpbuf_put(buf, packet->data, packet->size);
- upcall =
xzalloc(sizeof *upcall)
;
+ upcall =
&u->upcall
;
upcall->type = queue_no;
upcall->packet = buf;
upcall->key = buf->base;
upcall->key_len = key_len;
upcall->userdata = arg;
upcall->type = queue_no;
upcall->packet = buf;
upcall->key = buf->base;
upcall->key_len = key_len;
upcall->userdata = arg;
- q->upcalls[q->head++ & QUEUE_MASK] = upcall;
-
return 0;
}
return 0;
}
@@
-1259,7
+1266,7
@@
dp_netdev_execute_actions(struct dp_netdev *dp,
const struct dpif_class dpif_netdev_class = {
"netdev",
const struct dpif_class dpif_netdev_class = {
"netdev",
- NULL, /* enumerate */
+ dpif_netdev_enumerate,
dpif_netdev_open,
dpif_netdev_close,
dpif_netdev_destroy,
dpif_netdev_open,
dpif_netdev_close,
dpif_netdev_destroy,
@@
-1293,12
+1300,33
@@
const struct dpif_class dpif_netdev_class = {
dpif_netdev_recv_purge,
};
dpif_netdev_recv_purge,
};
+static void
+dpif_dummy_register__(const char *type)
+{
+ struct dpif_class *class;
+
+ class = xmalloc(sizeof *class);
+ *class = dpif_netdev_class;
+ class->type = xstrdup(type);
+ dp_register_provider(class);
+}
+
void
void
-dpif_dummy_register(
void
)
+dpif_dummy_register(
bool override
)
{
{
- if (!dpif_dummy_class.type) {
- dpif_dummy_class = dpif_netdev_class;
- dpif_dummy_class.type = "dummy";
- dp_register_provider(&dpif_dummy_class);
+ if (override) {
+ struct sset types;
+ const char *type;
+
+ sset_init(&types);
+ dp_enumerate_types(&types);
+ SSET_FOR_EACH (type, &types) {
+ if (!dp_unregister_provider(type)) {
+ dpif_dummy_register__(type);
+ }
+ }
+ sset_destroy(&types);
}
}
+
+ dpif_dummy_register__("dummy");
}
}