*
* - Do include packets and bytes that were obtained from the datapath
* when a flow was deleted (e.g. dpif_flow_del()) or when its
- * statistics were reset (e.g. dpif_flow_put() with ODPPF_ZERO_STATS).
+ * statistics were reset (e.g. dpif_flow_put() with
+ * DPIF_FP_ZERO_STATS).
*
* - Do not include any packets or bytes that can currently be obtained
* from the datapath by, e.g., dpif_flow_get().
static void facet_make_actions(struct ofproto *, struct facet *,
const struct ofpbuf *packet);
static void facet_update_stats(struct ofproto *, struct facet *,
- const struct odp_flow_stats *);
+ const struct dpif_flow_stats *);
/* ofproto supports two kinds of OpenFlow connections:
*
const struct ofhooks *ofhooks, void *aux,
struct ofproto **ofprotop)
{
- struct odp_stats stats;
struct ofproto *p;
struct dpif *dpif;
int error;
VLOG_ERR("failed to open datapath %s: %s", datapath, strerror(error));
return error;
}
- error = dpif_get_dp_stats(dpif, &stats);
- if (error) {
- VLOG_ERR("failed to obtain stats for datapath %s: %s",
- datapath, strerror(error));
- dpif_close(dpif);
- return error;
- }
error = dpif_recv_set_mask(dpif, ODPL_MISS | ODPL_ACTION | ODPL_SFLOW);
if (error) {
VLOG_ERR("failed to listen on datapath %s: %s",
p->netdev_monitor = netdev_monitor_create();
hmap_init(&p->ports);
shash_init(&p->port_by_name);
- p->max_ports = stats.max_ports;
+ p->max_ports = dpif_get_max_ports(dpif);
/* Initialize submodules. */
p->switch_status = switch_status_create(p);
struct shash_node *node;
struct shash devnames;
struct ofport *ofport;
- struct odp_port odp_port;
+ struct dpif_port dpif_port;
COVERAGE_INC(ofproto_reinit_ports);
HMAP_FOR_EACH (ofport, hmap_node, &p->ports) {
shash_add_once (&devnames, ofport->opp.name, NULL);
}
- DPIF_PORT_FOR_EACH (&odp_port, &dump, p->dpif) {
- shash_add_once (&devnames, odp_port.devname, NULL);
+ DPIF_PORT_FOR_EACH (&dpif_port, &dump, p->dpif) {
+ shash_add_once (&devnames, dpif_port.name, NULL);
}
SHASH_FOR_EACH (node, &devnames) {
}
static struct ofport *
-make_ofport(const struct odp_port *odp_port)
+make_ofport(const struct dpif_port *dpif_port)
{
struct netdev_options netdev_options;
enum netdev_flags flags;
int error;
memset(&netdev_options, 0, sizeof netdev_options);
- netdev_options.name = odp_port->devname;
- netdev_options.type = odp_port->type;
+ netdev_options.name = dpif_port->name;
+ netdev_options.type = dpif_port->type;
netdev_options.ethertype = NETDEV_ETH_TYPE_NONE;
error = netdev_open(&netdev_options, &netdev);
if (error) {
VLOG_WARN_RL(&rl, "ignoring port %s (%"PRIu16") because netdev %s "
"cannot be opened (%s)",
- odp_port->devname, odp_port->port,
- odp_port->devname, strerror(error));
+ dpif_port->name, dpif_port->port_no,
+ dpif_port->name, strerror(error));
return NULL;
}
ofport = xmalloc(sizeof *ofport);
ofport->netdev = netdev;
- ofport->odp_port = odp_port->port;
- ofport->opp.port_no = odp_port_to_ofp_port(odp_port->port);
+ ofport->odp_port = dpif_port->port_no;
+ ofport->opp.port_no = odp_port_to_ofp_port(dpif_port->port_no);
netdev_get_etheraddr(netdev, ofport->opp.hw_addr);
- memcpy(ofport->opp.name, odp_port->devname,
- MIN(sizeof ofport->opp.name, sizeof odp_port->devname));
- ofport->opp.name[sizeof ofport->opp.name - 1] = '\0';
+ ovs_strlcpy(ofport->opp.name, dpif_port->name, sizeof ofport->opp.name);
netdev_get_flags(netdev, &flags);
ofport->opp.config = flags & NETDEV_UP ? 0 : OFPPC_PORT_DOWN;
}
static bool
-ofport_conflicts(const struct ofproto *p, const struct odp_port *odp_port)
+ofport_conflicts(const struct ofproto *p, const struct dpif_port *dpif_port)
{
- if (get_port(p, odp_port->port)) {
+ if (get_port(p, dpif_port->port_no)) {
VLOG_WARN_RL(&rl, "ignoring duplicate port %"PRIu16" in datapath",
- odp_port->port);
+ dpif_port->port_no);
return true;
- } else if (shash_find(&p->port_by_name, odp_port->devname)) {
+ } else if (shash_find(&p->port_by_name, dpif_port->name)) {
VLOG_WARN_RL(&rl, "ignoring duplicate device %s in datapath",
- odp_port->devname);
+ dpif_port->name);
return true;
} else {
return false;
static void
update_port(struct ofproto *p, const char *devname)
{
- struct odp_port odp_port;
+ struct dpif_port dpif_port;
struct ofport *old_ofport;
struct ofport *new_ofport;
int error;
COVERAGE_INC(ofproto_update_port);
/* Query the datapath for port information. */
- error = dpif_port_query_by_name(p->dpif, devname, &odp_port);
+ error = dpif_port_query_by_name(p->dpif, devname, &dpif_port);
/* Find the old ofport. */
old_ofport = shash_find_data(&p->port_by_name, devname);
* reliably but more portably by comparing the old port's MAC
* against the new port's MAC. However, this code isn't that smart
* and always sends an OFPPR_MODIFY (XXX). */
- old_ofport = get_port(p, odp_port.port);
+ old_ofport = get_port(p, dpif_port.port_no);
}
} else if (error != ENOENT && error != ENODEV) {
VLOG_WARN_RL(&rl, "dpif_port_query_by_name returned unexpected error "
"%s", strerror(error));
- return;
+ goto exit;
}
/* Create a new ofport. */
- new_ofport = !error ? make_ofport(&odp_port) : NULL;
+ new_ofport = !error ? make_ofport(&dpif_port) : NULL;
/* Eliminate a few pathological cases. */
if (!old_ofport && !new_ofport) {
- return;
+ goto exit;
} else if (old_ofport && new_ofport) {
/* Most of the 'config' bits are OpenFlow soft state, but
* OFPPC_PORT_DOWN is maintained by the kernel. So transfer the
if (ofport_equal(old_ofport, new_ofport)) {
/* False alarm--no change. */
ofport_free(new_ofport);
- return;
+ goto exit;
}
}
: !new_ofport ? OFPPR_DELETE
: OFPPR_MODIFY));
ofport_free(old_ofport);
+
+exit:
+ dpif_port_destroy(&dpif_port);
}
static int
init_ports(struct ofproto *p)
{
struct dpif_port_dump dump;
- struct odp_port odp_port;
+ struct dpif_port dpif_port;
- DPIF_PORT_FOR_EACH (&odp_port, &dump, p->dpif) {
- if (!ofport_conflicts(p, &odp_port)) {
- struct ofport *ofport = make_ofport(&odp_port);
+ DPIF_PORT_FOR_EACH (&dpif_port, &dump, p->dpif) {
+ if (!ofport_conflicts(p, &dpif_port)) {
+ struct ofport *ofport = make_ofport(&dpif_port);
if (ofport) {
ofport_install(p, ofport);
}
facet_execute(struct ofproto *ofproto, struct facet *facet,
struct ofpbuf *packet)
{
- struct odp_flow_stats stats;
+ struct dpif_flow_stats stats;
assert(ofpbuf_headroom(packet) >= sizeof(struct ofp_packet_in));
}
static int
-facet_put__(struct ofproto *ofproto, struct facet *facet, int flags,
- struct odp_flow_put *put)
+facet_put__(struct ofproto *ofproto, struct facet *facet,
+ const struct nlattr *actions, size_t actions_len,
+ struct dpif_flow_stats *stats)
{
uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
+ enum dpif_flow_put_flags flags;
struct ofpbuf key;
+ flags = DPIF_FP_CREATE | DPIF_FP_MODIFY;
+ if (stats) {
+ flags |= DPIF_FP_ZERO_STATS;
+ }
+
ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
odp_flow_key_from_flow(&key, &facet->flow);
assert(key.base == keybuf);
- memset(&put->flow.stats, 0, sizeof put->flow.stats);
- put->flow.key = key.data;
- put->flow.key_len = key.size;
- put->flow.actions = facet->actions;
- put->flow.actions_len = facet->actions_len;
- put->flow.flags = 0;
- put->flags = flags;
- return dpif_flow_put(ofproto->dpif, put);
+ return dpif_flow_put(ofproto->dpif, flags, key.data, key.size,
+ actions, actions_len, stats);
}
/* If 'facet' is installable, inserts or re-inserts it into 'p''s datapath. If
static void
facet_install(struct ofproto *p, struct facet *facet, bool zero_stats)
{
- if (facet->may_install) {
- struct odp_flow_put put;
- int flags;
+ struct dpif_flow_stats stats;
- flags = ODPPF_CREATE | ODPPF_MODIFY;
- if (zero_stats) {
- flags |= ODPPF_ZERO_STATS;
- }
- if (!facet_put__(p, facet, flags, &put)) {
- facet->installed = true;
- }
+ if (facet->may_install
+ && !facet_put__(p, facet, facet->actions, facet->actions_len,
+ zero_stats ? &stats : NULL)) {
+ facet->installed = true;
}
}
{
if (facet->installed) {
uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
- struct odp_flow odp_flow;
+ struct dpif_flow_stats stats;
struct ofpbuf key;
ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
odp_flow_key_from_flow(&key, &facet->flow);
assert(key.base == keybuf);
- odp_flow.key = key.data;
- odp_flow.key_len = key.size;
- odp_flow.actions = NULL;
- odp_flow.actions_len = 0;
- odp_flow.flags = 0;
- if (!dpif_flow_del(p->dpif, &odp_flow)) {
- facet_update_stats(p, facet, &odp_flow.stats);
+ if (!dpif_flow_del(p->dpif, key.data, key.size, &stats)) {
+ facet_update_stats(p, facet, &stats);
}
facet->installed = false;
}
/* If the ODP actions changed or the installability changed, then we need
* to talk to the datapath. */
- if (actions_changed || facet->may_install != facet->installed) {
- if (facet->may_install) {
- uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
- struct odp_flow_put put;
- struct ofpbuf key;
-
- ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
- odp_flow_key_from_flow(&key, &facet->flow);
-
- memset(&put.flow.stats, 0, sizeof put.flow.stats);
- put.flow.key = key.data;
- put.flow.key_len = key.size;
- put.flow.actions = odp_actions->data;
- put.flow.actions_len = odp_actions->size;
- put.flow.flags = 0;
- put.flags = ODPPF_CREATE | ODPPF_MODIFY | ODPPF_ZERO_STATS;
- dpif_flow_put(ofproto->dpif, &put);
-
- facet_update_stats(ofproto, facet, &put.flow.stats);
+ if (actions_changed || ctx.may_set_up_flow != facet->installed) {
+ if (ctx.may_set_up_flow) {
+ struct dpif_flow_stats stats;
+
+ facet_put__(ofproto, facet,
+ odp_actions->data, odp_actions->size, &stats);
+ facet_update_stats(ofproto, facet, &stats);
} else {
facet_uninstall(ofproto, facet);
}
packet_count = rule->packet_count;
byte_count = rule->byte_count;
- /* Ask the datapath for statistics on all of the rule's facets. (We could
- * batch up statistics requests using dpif_flow_get_multiple(), but that is
- * not yet implemented.)
+ /* Ask the datapath for statistics on all of the rule's facets.
*
* Also, add any statistics that are not tracked by the datapath for each
* facet. This includes, for example, statistics for packets that were
* to a rule. */
ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
LIST_FOR_EACH (facet, list_node, &rule->facets) {
- struct odp_flow odp_flow;
+ struct dpif_flow_stats stats;
ofpbuf_clear(&key);
odp_flow_key_from_flow(&key, &facet->flow);
+ dpif_flow_get(p->dpif, key.data, key.size, NULL, &stats);
- odp_flow.key = key.data;
- odp_flow.key_len = key.size;
- odp_flow.actions = NULL;
- odp_flow.actions_len = 0;
- odp_flow.flags = 0;
- if (!dpif_flow_get(p->dpif, &odp_flow)) {
- packet_count += odp_flow.stats.n_packets;
- byte_count += odp_flow.stats.n_bytes;
- }
-
- packet_count += facet->packet_count;
- byte_count += facet->byte_count;
+ packet_count += stats.n_packets + facet->packet_count;
+ byte_count += stats.n_bytes + facet->byte_count;
}
/* Return the stats to the caller. */
return 0;
}
-static long long int
-msec_from_nsec(uint64_t sec, uint32_t nsec)
-{
- return !sec ? 0 : sec * 1000 + nsec / 1000000;
-}
-
static void
facet_update_time(struct ofproto *ofproto, struct facet *facet,
- const struct odp_flow_stats *stats)
+ const struct dpif_flow_stats *stats)
{
- long long int used = msec_from_nsec(stats->used_sec, stats->used_nsec);
+ long long int used = stats->used;
if (used > facet->used) {
facet->used = used;
if (used > facet->rule->used) {
* cleared out of the datapath. */
static void
facet_update_stats(struct ofproto *ofproto, struct facet *facet,
- const struct odp_flow_stats *stats)
+ const struct dpif_flow_stats *stats)
{
if (stats->n_packets) {
facet_update_time(ofproto, facet, stats);
static void
ofproto_update_used(struct ofproto *p)
{
+ const struct dpif_flow_stats *stats;
struct dpif_flow_dump dump;
+ const struct nlattr *key;
+ size_t key_len;
dpif_flow_dump_start(&dump, p->dpif);
- for (;;) {
- uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
+ while (dpif_flow_dump_next(&dump, &key, &key_len, NULL, NULL, &stats)) {
struct facet *facet;
- struct odp_flow f;
struct flow flow;
- memset(&f, 0, sizeof f);
- f.key = (struct nlattr *) keybuf;
- f.key_len = sizeof keybuf;
- if (!dpif_flow_dump_next(&dump, &f)) {
- break;
- }
-
- if (f.key_len > sizeof keybuf) {
- VLOG_WARN_RL(&rl, "ODP flow key overflowed buffer");
- continue;
- }
- if (odp_flow_key_to_flow(f.key, f.key_len, &flow)) {
+ if (odp_flow_key_to_flow(key, key_len, &flow)) {
struct ds s;
ds_init(&s);
- odp_flow_key_format(f.key, f.key_len, &s);
+ odp_flow_key_format(key, key_len, &s);
VLOG_WARN_RL(&rl, "failed to convert ODP flow key to flow: %s",
ds_cstr(&s));
ds_destroy(&s);
facet = facet_find(p, &flow);
if (facet && facet->installed) {
- facet_update_time(p, facet, &f.stats);
- facet_account(p, facet, f.stats.n_bytes);
+ facet_update_time(p, facet, stats);
+ facet_account(p, facet, stats->n_bytes);
} else {
/* There's a flow in the datapath that we know nothing about.
* Delete it. */
COVERAGE_INC(ofproto_unexpected_rule);
- dpif_flow_del(p->dpif, &f);
+ dpif_flow_del(p->dpif, key, key_len, NULL);
}
}
dpif_flow_dump_done(&dump);
if (ofproto->netflow && !facet_is_controller_flow(facet) &&
netflow_active_timeout_expired(ofproto->netflow, &facet->nf_flow)) {
struct ofexpired expired;
- struct odp_flow odp_flow;
- /* Get updated flow stats.
- *
- * XXX We could avoid this call entirely if (1) ofproto_update_used()
- * updated TCP flags and (2) the dpif_flow_list_all() in
- * ofproto_update_used() zeroed TCP flags. */
- memset(&odp_flow, 0, sizeof odp_flow);
if (facet->installed) {
- uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
- struct ofpbuf key;
-
- ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
- odp_flow_key_from_flow(&key, &facet->flow);
-
- odp_flow.key = key.data;
- odp_flow.key_len = key.size;
- odp_flow.flags = ODPFF_ZERO_TCP_FLAGS;
- dpif_flow_get(ofproto->dpif, &odp_flow);
+ struct dpif_flow_stats stats;
- if (odp_flow.stats.n_packets) {
- facet_update_time(ofproto, facet, &odp_flow.stats);
- netflow_flow_update_flags(&facet->nf_flow,
- odp_flow.stats.tcp_flags);
- }
+ facet_put__(ofproto, facet, facet->actions, facet->actions_len,
+ &stats);
+ facet_update_stats(ofproto, facet, &stats);
}
expired.flow = facet->flow;
- expired.packet_count = facet->packet_count +
- odp_flow.stats.n_packets;
- expired.byte_count = facet->byte_count + odp_flow.stats.n_bytes;
+ expired.packet_count = facet->packet_count;
+ expired.byte_count = facet->byte_count;
expired.used = facet->used;
-
netflow_expire(ofproto->netflow, &facet->nf_flow, &expired);
}
}