}
}
+static void
+odp_flow_stats_to_dpif_flow_stats(const struct odp_flow_stats *ofs,
+ struct dpif_flow_stats *dfs)
+{
+ dfs->n_packets = ofs->n_packets;
+ dfs->n_bytes = ofs->n_bytes;
+ dfs->used = ofs->used_sec * 1000 + ofs->used_nsec / 1000000;
+ dfs->tcp_flags = ofs->tcp_flags;
+}
+
static int
dpif_linux_flow_get(const struct dpif *dpif_, int flags,
const struct nlattr *key, size_t key_len,
- struct ofpbuf **actionsp, struct odp_flow_stats *stats)
+ struct ofpbuf **actionsp, struct dpif_flow_stats *stats)
{
struct ofpbuf *actions = NULL;
struct odp_flow odp_flow;
error = do_ioctl(dpif_, ODP_FLOW_GET, &odp_flow);
if (!error) {
if (stats) {
- *stats = odp_flow.stats;
+ odp_flow_stats_to_dpif_flow_stats(&odp_flow.stats, stats);
}
if (actions) {
actions->size = odp_flow.actions_len;
dpif_linux_flow_put(struct dpif *dpif_, int flags,
const struct nlattr *key, size_t key_len,
const struct nlattr *actions, size_t actions_len,
- struct odp_flow_stats *stats)
+ struct dpif_flow_stats *stats)
{
struct odp_flow_put put;
int error;
put.flags = flags;
error = do_ioctl(dpif_, ODP_FLOW_PUT, &put);
if (!error && stats) {
- *stats = put.flow.stats;
+ odp_flow_stats_to_dpif_flow_stats(&put.flow.stats, stats);
}
return error;
}
static int
dpif_linux_flow_del(struct dpif *dpif_,
const struct nlattr *key, size_t key_len,
- struct odp_flow_stats *stats)
+ struct dpif_flow_stats *stats)
{
struct odp_flow odp_flow;
int error;
odp_flow.key_len = key_len;
error = do_ioctl(dpif_, ODP_FLOW_DEL, &odp_flow);
if (!error && stats) {
- *stats = odp_flow.stats;
+ odp_flow_stats_to_dpif_flow_stats(&odp_flow.stats, stats);
}
return error;
}
struct odp_flow flow;
uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
uint32_t actionsbuf[65536 / sizeof(uint32_t)];
+ struct dpif_flow_stats stats;
};
static int
dpif_linux_flow_dump_next(const struct dpif *dpif, void *state_,
const struct nlattr **key, size_t *key_len,
const struct nlattr **actions, size_t *actions_len,
- const struct odp_flow_stats **stats)
+ const struct dpif_flow_stats **stats)
{
struct dpif_linux_flow_state *state = state_;
int error;
*actions_len = state->flow.actions_len;
}
if (stats) {
- *stats = &state->flow.stats;
+ odp_flow_stats_to_dpif_flow_stats(&state->flow.stats,
+ &state->stats);
+ *stats = &state->stats;
}
}
return error;
struct flow key;
/* Statistics. */
- struct timespec used; /* Last used time. */
+ 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. */
uint16_t tcp_ctl; /* Bitwise-OR of seen tcp_ctl values. */
}
static void
-get_odp_flow_stats(struct dp_netdev_flow *flow, struct odp_flow_stats *stats)
+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_sec = flow->used.tv_sec;
- stats->used_nsec = flow->used.tv_nsec;
+ stats->used = flow->used;
stats->tcp_flags = TCP_FLAGS(flow->tcp_ctl);
- stats->reserved = 0;
}
static int
static int
dpif_netdev_flow_get(const struct dpif *dpif, int flags,
const struct nlattr *nl_key, size_t nl_key_len,
- struct ofpbuf **actionsp, struct odp_flow_stats *stats)
+ struct ofpbuf **actionsp, struct dpif_flow_stats *stats)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
struct dp_netdev_flow *flow;
}
if (stats) {
- get_odp_flow_stats(flow, stats);
+ get_dpif_flow_stats(flow, stats);
}
if (actionsp) {
*actionsp = ofpbuf_clone_data(flow->actions, flow->actions_len);
static void
clear_stats(struct dp_netdev_flow *flow)
{
- flow->used.tv_sec = 0;
- flow->used.tv_nsec = 0;
+ flow->used = 0;
flow->packet_count = 0;
flow->byte_count = 0;
flow->tcp_ctl = 0;
dpif_netdev_flow_put(struct dpif *dpif, int flags,
const struct nlattr *nl_key, size_t nl_key_len,
const struct nlattr *actions, size_t actions_len,
- struct odp_flow_stats *stats)
+ struct dpif_flow_stats *stats)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
struct dp_netdev_flow *flow;
int error = set_flow_actions(flow, actions, actions_len);
if (!error) {
if (stats) {
- get_odp_flow_stats(flow, stats);
+ get_dpif_flow_stats(flow, stats);
}
if (flags & ODPPF_ZERO_STATS) {
clear_stats(flow);
static int
dpif_netdev_flow_del(struct dpif *dpif,
const struct nlattr *nl_key, size_t nl_key_len,
- struct odp_flow_stats *stats)
+ struct dpif_flow_stats *stats)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
struct dp_netdev_flow *flow;
flow = dp_netdev_lookup_flow(dp, &key);
if (flow) {
if (stats) {
- get_odp_flow_stats(flow, stats);
+ get_dpif_flow_stats(flow, stats);
}
dp_netdev_free_flow(dp, flow);
return 0;
uint32_t offset;
struct nlattr *actions;
uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
- struct odp_flow_stats stats;
+ struct dpif_flow_stats stats;
};
static int
dpif_netdev_flow_dump_next(const struct dpif *dpif, void *state_,
const struct nlattr **key, size_t *key_len,
const struct nlattr **actions, size_t *actions_len,
- const struct odp_flow_stats **stats)
+ const struct dpif_flow_stats **stats)
{
struct dp_netdev_flow_state *state = state_;
struct dp_netdev *dp = get_dp_netdev(dpif);
}
if (stats) {
- get_odp_flow_stats(flow, &state->stats);
+ get_dpif_flow_stats(flow, &state->stats);
*stats = &state->stats;
}
dp_netdev_flow_used(struct dp_netdev_flow *flow, struct flow *key,
const struct ofpbuf *packet)
{
- time_timespec(&flow->used);
+ 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) {
* flow's statistics. */
int (*flow_get)(const struct dpif *dpif, int flags,
const struct nlattr *key, size_t key_len,
- struct ofpbuf **actionsp, struct odp_flow_stats *stats);
+ struct ofpbuf **actionsp, struct dpif_flow_stats *stats);
/* Adds or modifies a flow in 'dpif'. The flow is specified by the Netlink
* attributes with types ODP_KEY_ATTR_* in the 'key_len' bytes starting at
int (*flow_put)(struct dpif *dpif, int flags,
const struct nlattr *key, size_t key_len,
const struct nlattr *actions, size_t actions_len,
- struct odp_flow_stats *stats);
+ struct dpif_flow_stats *stats);
/* Deletes a flow from 'dpif' and returns 0, or returns ENOENT if 'dpif'
* does not contain such a flow. The flow is specified by the Netlink
* flow's statistics before its deletion. */
int (*flow_del)(struct dpif *dpif,
const struct nlattr *key, size_t key_len,
- struct odp_flow_stats *stats);
+ struct dpif_flow_stats *stats);
/* Deletes all flows from 'dpif' and clears all of its queues of received
* packets. */
int (*flow_dump_next)(const struct dpif *dpif, void *state,
const struct nlattr **key, size_t *key_len,
const struct nlattr **actions, size_t *actions_len,
- const struct odp_flow_stats **stats);
+ const struct dpif_flow_stats **stats);
/* Releases resources from 'dpif' for 'state', which was initialized by a
* successful call to the 'flow_dump_start' function for 'dpif'. */
#include "poll-loop.h"
#include "shash.h"
#include "svec.h"
+#include "timeval.h"
#include "util.h"
#include "valgrind.h"
#include "vlog.h"
static void log_flow_message(const struct dpif *dpif, int error,
const char *operation,
const struct nlattr *key, size_t key_len,
- const struct odp_flow_stats *stats,
+ const struct dpif_flow_stats *stats,
const struct nlattr *actions, size_t actions_len);
static void log_operation(const struct dpif *, const char *operation,
int error);
dpif->dpif_class->port_poll_wait(dpif);
}
+/* Appends a human-readable representation of 'stats' to 's'. */
+void
+dpif_flow_stats_format(const struct dpif_flow_stats *stats, struct ds *s)
+{
+ ds_put_format(s, "packets:%"PRIu64", bytes:%"PRIu64", used:",
+ stats->n_packets, stats->n_bytes);
+ if (stats->used) {
+ ds_put_format(s, "%.3fs", (time_msec() - stats->used) / 1000.0);
+ } else {
+ ds_put_format(s, "never");
+ }
+ /* XXX tcp_flags? */
+}
+
/* Deletes all flows from 'dpif'. Returns 0 if successful, otherwise a
* positive errno value. */
int
int
dpif_flow_get(const struct dpif *dpif, int flags,
const struct nlattr *key, size_t key_len,
- struct ofpbuf **actionsp, struct odp_flow_stats *stats)
+ struct ofpbuf **actionsp, struct dpif_flow_stats *stats)
{
int error;
dpif_flow_put(struct dpif *dpif, int flags,
const struct nlattr *key, size_t key_len,
const struct nlattr *actions, size_t actions_len,
- struct odp_flow_stats *stats)
+ struct dpif_flow_stats *stats)
{
int error;
int
dpif_flow_del(struct dpif *dpif,
const struct nlattr *key, size_t key_len,
- struct odp_flow_stats *stats)
+ struct dpif_flow_stats *stats)
{
int error;
dpif_flow_dump_next(struct dpif_flow_dump *dump,
const struct nlattr **key, size_t *key_len,
const struct nlattr **actions, size_t *actions_len,
- const struct odp_flow_stats **stats)
+ const struct dpif_flow_stats **stats)
{
const struct dpif *dpif = dump->dpif;
int error = dump->error;
static void
log_flow_message(const struct dpif *dpif, int error, const char *operation,
const struct nlattr *key, size_t key_len,
- const struct odp_flow_stats *stats,
+ const struct dpif_flow_stats *stats,
const struct nlattr *actions, size_t actions_len)
{
struct ds ds = DS_EMPTY_INITIALIZER;
odp_flow_key_format(key, key_len, &ds);
if (stats) {
ds_put_cstr(&ds, ", ");
- format_odp_flow_stats(&ds, stats);
+ dpif_flow_stats_format(stats, &ds);
}
if (actions || actions_len) {
ds_put_cstr(&ds, ", actions:");
#endif
struct dpif;
+struct ds;
struct netdev;
struct nlattr;
struct ofpbuf;
int dpif_port_poll(const struct dpif *, char **devnamep);
void dpif_port_poll_wait(const struct dpif *);
+struct dpif_flow_stats {
+ uint64_t n_packets;
+ uint64_t n_bytes;
+ long long int used;
+ uint8_t tcp_flags;
+};
+
+void dpif_flow_stats_format(const struct dpif_flow_stats *, struct ds *);
+
int dpif_flow_flush(struct dpif *);
int dpif_flow_put(struct dpif *, int flags,
const struct nlattr *key, size_t key_len,
const struct nlattr *actions, size_t actions_len,
- struct odp_flow_stats *);
+ struct dpif_flow_stats *);
int dpif_flow_del(struct dpif *,
const struct nlattr *key, size_t key_len,
- struct odp_flow_stats *);
+ struct dpif_flow_stats *);
int dpif_flow_get(const struct dpif *, int flags,
const struct nlattr *key, size_t key_len,
- struct ofpbuf **actionsp, struct odp_flow_stats *);
+ struct ofpbuf **actionsp, struct dpif_flow_stats *);
struct dpif_flow_dump {
const struct dpif *dpif;
bool dpif_flow_dump_next(struct dpif_flow_dump *,
const struct nlattr **key, size_t *key_len,
const struct nlattr **actions, size_t *actions_len,
- const struct odp_flow_stats **);
+ const struct dpif_flow_stats **);
int dpif_flow_dump_done(struct dpif_flow_dump *);
int dpif_execute(struct dpif *, const struct nlattr *actions,
#include <string.h>
#include "byte-order.h"
#include "coverage.h"
+#include "dpif.h"
#include "dynamic-string.h"
#include "hash.h"
-#include "ofp-util.h"
#include "ofpbuf.h"
#include "openflow/openflow.h"
#include "openvswitch/datapath-protocol.h"
*/
void
flow_extract_stats(const struct flow *flow, struct ofpbuf *packet,
- struct odp_flow_stats *stats)
+ struct dpif_flow_stats *stats)
{
- memset(stats, '\0', sizeof(*stats));
+ memset(stats, 0, sizeof(*stats));
if ((flow->dl_type == htons(ETH_TYPE_IP)) && packet->l4) {
if ((flow->nw_proto == IP_TYPE_TCP) && packet->l7) {
#include "openvswitch/datapath-protocol.h"
#include "util.h"
+struct dpif_flow_stats;
struct ds;
struct flow_wildcards;
struct ofp_match;
int flow_extract(struct ofpbuf *, uint64_t tun_id, uint16_t in_port,
struct flow *);
void flow_extract_stats(const struct flow *flow, struct ofpbuf *packet,
- struct odp_flow_stats *stats);
+ struct dpif_flow_stats *);
char *flow_to_string(const struct flow *);
void flow_format(struct ds *, const struct flow *);
void flow_print(FILE *, const struct flow *);
ds_put_cstr(ds, "drop");
}
}
-
-void
-format_odp_flow_stats(struct ds *ds, const struct odp_flow_stats *s)
-{
- ds_put_format(ds, "packets:%llu, bytes:%llu, used:",
- (unsigned long long int) s->n_packets,
- (unsigned long long int) s->n_bytes);
- if (s->used_sec) {
- long long int used = s->used_sec * 1000 + s->used_nsec / 1000000;
- ds_put_format(ds, "%.3fs", (time_msec() - used) / 1000.0);
- } else {
- ds_put_format(ds, "never");
- }
-}
\f
/* Returns the correct length of the payload for a flow key attribute of the
* specified 'type', or -1 if 'type' is unknown. */
void format_odp_action(struct ds *, const struct nlattr *);
void format_odp_actions(struct ds *, const struct nlattr *odp_actions,
size_t actions_len);
-void format_odp_flow_stats(struct ds *, const struct odp_flow_stats *);
/* By my calculations currently the longest valid nlattr-formatted flow key is
* 80 bytes long, so this leaves some safety margin.
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:
*
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));
{
if (facet->installed) {
uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
- struct odp_flow_stats stats;
+ struct dpif_flow_stats stats;
struct ofpbuf key;
ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
if (actions_changed || facet->may_install != facet->installed) {
if (facet->may_install) {
uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
- struct odp_flow_stats stats;
+ struct dpif_flow_stats stats;
struct ofpbuf key;
ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
* to a rule. */
ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
LIST_FOR_EACH (facet, list_node, &rule->facets) {
- struct odp_flow_stats stats;
+ struct dpif_flow_stats stats;
ofpbuf_clear(&key);
odp_flow_key_from_flow(&key, &facet->flow);
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 odp_flow_stats *stats;
+ const struct dpif_flow_stats *stats;
struct dpif_flow_dump dump;
const struct nlattr *key;
size_t key_len;
* ofproto_update_used() zeroed TCP flags. */
if (facet->installed) {
uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
- struct odp_flow_stats stats;
+ struct dpif_flow_stats stats;
struct ofpbuf key;
ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
static void
do_dump_flows(int argc OVS_UNUSED, char *argv[])
{
- const struct odp_flow_stats *stats;
+ const struct dpif_flow_stats *stats;
const struct nlattr *actions;
struct dpif_flow_dump dump;
const struct nlattr *key;
ds_clear(&ds);
odp_flow_key_format(key, key_len, &ds);
ds_put_cstr(&ds, ", ");
- format_odp_flow_stats(&ds, stats);
+ dpif_flow_stats_format(stats, &ds);
ds_put_cstr(&ds, ", actions:");
format_odp_actions(&ds, actions, actions_len);
printf("%s\n", ds_cstr(&ds));