Skip to content

Commit

Permalink
ovs-dpctl: Add mega flow support
Browse files Browse the repository at this point in the history
Added support to allow mega flow specified and displayed. ovs-dpctl tool
is mainly used as debugging tool.

This patch also implements the low level user space routines to send
and receive mega flow netlink messages. Those netlink suppor
routines are required for forthcoming user space mega flow patches.

Added a unit test to test parsing and display of mega flows.

Ethan contributed the ovs-dpctl mega flow output function.

Co-authored-by: Ethan Jackson <[email protected]>
Signed-off-by: Ethan Jackson <[email protected]>
Signed-off-by: Andy Zhou <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
  • Loading branch information
2 people authored and blp committed Jun 20, 2013
1 parent a1c564b commit e6cc0ba
Show file tree
Hide file tree
Showing 13 changed files with 1,063 additions and 206 deletions.
19 changes: 19 additions & 0 deletions lib/dpif-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ struct dpif_linux_flow {
* the Netlink version of the command, even if actions_len is zero. */
const struct nlattr *key; /* OVS_FLOW_ATTR_KEY. */
size_t key_len;
const struct nlattr *mask; /* OVS_FLOW_ATTR_MASK. */
size_t mask_len;
const struct nlattr *actions; /* OVS_FLOW_ATTR_ACTIONS. */
size_t actions_len;
const struct ovs_flow_stats *stats; /* OVS_FLOW_ATTR_STATS. */
Expand Down Expand Up @@ -807,6 +809,8 @@ dpif_linux_init_flow_put(struct dpif *dpif_, const struct dpif_flow_put *put,
request->dp_ifindex = dpif->dp_ifindex;
request->key = put->key;
request->key_len = put->key_len;
request->mask = put->mask;
request->mask_len = put->mask_len;
/* Ensure that OVS_FLOW_ATTR_ACTIONS will always be included. */
request->actions = (put->actions
? put->actions
Expand Down Expand Up @@ -901,6 +905,7 @@ dpif_linux_flow_dump_start(const struct dpif *dpif_, void **statep)
static int
dpif_linux_flow_dump_next(const struct dpif *dpif_ OVS_UNUSED, void *state_,
const struct nlattr **key, size_t *key_len,
const struct nlattr **mask, size_t *mask_len,
const struct nlattr **actions, size_t *actions_len,
const struct dpif_flow_stats **stats)
{
Expand Down Expand Up @@ -941,6 +946,10 @@ dpif_linux_flow_dump_next(const struct dpif *dpif_ OVS_UNUSED, void *state_,
*key = state->flow.key;
*key_len = state->flow.key_len;
}
if (mask) {
*mask = state->flow.mask;
*mask_len = state->flow.mask ? state->flow.mask_len : 0;
}
if (stats) {
dpif_linux_flow_get_stats(&state->flow, &state->stats);
*stats = &state->stats;
Expand Down Expand Up @@ -1832,6 +1841,7 @@ dpif_linux_flow_from_ofpbuf(struct dpif_linux_flow *flow,
{
static const struct nl_policy ovs_flow_policy[] = {
[OVS_FLOW_ATTR_KEY] = { .type = NL_A_NESTED },
[OVS_FLOW_ATTR_MASK] = { .type = NL_A_NESTED, .optional = true },
[OVS_FLOW_ATTR_ACTIONS] = { .type = NL_A_NESTED, .optional = true },
[OVS_FLOW_ATTR_STATS] = { NL_POLICY_FOR(struct ovs_flow_stats),
.optional = true },
Expand Down Expand Up @@ -1863,6 +1873,11 @@ dpif_linux_flow_from_ofpbuf(struct dpif_linux_flow *flow,
flow->dp_ifindex = ovs_header->dp_ifindex;
flow->key = nl_attr_get(a[OVS_FLOW_ATTR_KEY]);
flow->key_len = nl_attr_get_size(a[OVS_FLOW_ATTR_KEY]);

if (a[OVS_FLOW_ATTR_MASK]) {
flow->mask = nl_attr_get(a[OVS_FLOW_ATTR_MASK]);
flow->mask_len = nl_attr_get_size(a[OVS_FLOW_ATTR_MASK]);
}
if (a[OVS_FLOW_ATTR_ACTIONS]) {
flow->actions = nl_attr_get(a[OVS_FLOW_ATTR_ACTIONS]);
flow->actions_len = nl_attr_get_size(a[OVS_FLOW_ATTR_ACTIONS]);
Expand Down Expand Up @@ -1898,6 +1913,10 @@ dpif_linux_flow_to_ofpbuf(const struct dpif_linux_flow *flow,
nl_msg_put_unspec(buf, OVS_FLOW_ATTR_KEY, flow->key, flow->key_len);
}

if (flow->mask_len) {
nl_msg_put_unspec(buf, OVS_FLOW_ATTR_MASK, flow->mask, flow->mask_len);
}

if (flow->actions || flow->actions_len) {
nl_msg_put_unspec(buf, OVS_FLOW_ATTR_ACTIONS,
flow->actions, flow->actions_len);
Expand Down
6 changes: 6 additions & 0 deletions lib/dpif-netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,7 @@ dpif_netdev_flow_dump_start(const struct dpif *dpif OVS_UNUSED, void **statep)
static int
dpif_netdev_flow_dump_next(const struct dpif *dpif, void *state_,
const struct nlattr **key, size_t *key_len,
const struct nlattr **mask, size_t *mask_len,
const struct nlattr **actions, size_t *actions_len,
const struct dpif_flow_stats **stats)
{
Expand All @@ -904,6 +905,11 @@ dpif_netdev_flow_dump_next(const struct dpif *dpif, void *state_,
*key_len = buf.size;
}

if (mask) {
*mask = NULL;
*mask_len = 0;
}

if (actions) {
free(state->actions);
state->actions = xmemdup(flow->actions, flow->actions_len);
Expand Down
25 changes: 18 additions & 7 deletions lib/dpif-provider.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* 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.
Expand Down Expand Up @@ -279,19 +279,30 @@ struct dpif_class {
* called again once it returns nonzero within a given iteration (but the
* 'flow_dump_done' function will be called afterward).
*
* On success, if 'key' and 'key_len' are nonnull then '*key' and
* '*key_len' must be set to Netlink attributes with types OVS_KEY_ATTR_*
* representing the dumped flow's key. If 'actions' and 'actions_len' are
* nonnull then they should be set to Netlink attributes with types
* OVS_ACTION_ATTR_* representing the dumped flow's actions. If 'stats'
* is nonnull then it should be set to the dumped flow's statistics.
* On success:
*
* - If 'key' and 'key_len' are nonnull, then '*key' and '*key_len'
* must be set to Netlink attributes with types OVS_KEY_ATTR_*
* representing the dumped flow's key.
*
* - If 'mask' and 'mask_len' are nonnull then '*mask' and '*mask_len'
* must be set to Netlink attributes with types of OVS_KEY_ATTR_*
* representing the dumped flow's mask.
*
* - If 'actions' and 'actions_len' are nonnull then they should be set
* to Netlink attributes with types OVS_ACTION_ATTR_* representing
* the dumped flow's actions.
*
* - If 'stats' is nonnull then it should be set to the dumped flow's
* statistics.
*
* All of the returned data is owned by 'dpif', not by the caller, and the
* caller must not modify or free it. 'dpif' must guarantee that it
* remains accessible and unchanging until at least the next call to
* 'flow_dump_next' or 'flow_dump_done' for 'state'. */
int (*flow_dump_next)(const struct dpif *dpif, void *state,
const struct nlattr **key, size_t *key_len,
const struct nlattr **mask, size_t *mask_len,
const struct nlattr **actions, size_t *actions_len,
const struct dpif_flow_stats **stats);

Expand Down
17 changes: 14 additions & 3 deletions lib/dpif.c
Original file line number Diff line number Diff line change
Expand Up @@ -832,9 +832,11 @@ dpif_flow_put__(struct dpif *dpif, const struct dpif_flow_put *put)
}

/* Adds or modifies a flow in 'dpif'. The flow is specified by the Netlink
* attributes with types OVS_KEY_ATTR_* in the 'key_len' bytes starting at
* 'key'. The associated actions are specified by the Netlink attributes with
* types OVS_ACTION_ATTR_* in the 'actions_len' bytes starting at 'actions'.
* attribute OVS_FLOW_ATTR_KEY with types OVS_KEY_ATTR_* in the 'key_len' bytes
* starting at 'key', and OVS_FLOW_ATTR_MASK with types of OVS_KEY_ATTR_* in the
* 'mask_len' bytes starting at 'mask'. The associated actions are specified by
* the Netlink attributes with types OVS_ACTION_ATTR_* in the 'actions_len'
* bytes starting at 'actions'.
*
* - If the flow's key does not exist in 'dpif', then the flow will be added if
* 'flags' includes DPIF_FP_CREATE. Otherwise the operation will fail with
Expand All @@ -854,6 +856,7 @@ dpif_flow_put__(struct dpif *dpif, const struct dpif_flow_put *put)
int
dpif_flow_put(struct dpif *dpif, enum dpif_flow_put_flags flags,
const struct nlattr *key, size_t key_len,
const struct nlattr *mask, size_t mask_len,
const struct nlattr *actions, size_t actions_len,
struct dpif_flow_stats *stats)
{
Expand All @@ -862,6 +865,8 @@ dpif_flow_put(struct dpif *dpif, enum dpif_flow_put_flags flags,
put.flags = flags;
put.key = key;
put.key_len = key_len;
put.mask = mask;
put.mask_len = mask_len;
put.actions = actions;
put.actions_len = actions_len;
put.stats = stats;
Expand Down Expand Up @@ -937,6 +942,7 @@ dpif_flow_dump_start(struct dpif_flow_dump *dump, const struct dpif *dpif)
bool
dpif_flow_dump_next(struct dpif_flow_dump *dump,
const struct nlattr **key, size_t *key_len,
const struct nlattr **mask, size_t *mask_len,
const struct nlattr **actions, size_t *actions_len,
const struct dpif_flow_stats **stats)
{
Expand All @@ -946,6 +952,7 @@ dpif_flow_dump_next(struct dpif_flow_dump *dump,
if (!error) {
error = dpif->dpif_class->flow_dump_next(dpif, dump->state,
key, key_len,
mask, mask_len,
actions, actions_len,
stats);
if (error) {
Expand All @@ -957,6 +964,10 @@ dpif_flow_dump_next(struct dpif_flow_dump *dump,
*key = NULL;
*key_len = 0;
}
if (mask) {
*mask = NULL;
*mask_len = 0;
}
if (actions) {
*actions = NULL;
*actions_len = 0;
Expand Down
4 changes: 4 additions & 0 deletions lib/dpif.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ enum dpif_flow_put_flags {
int dpif_flow_flush(struct dpif *);
int dpif_flow_put(struct dpif *, enum dpif_flow_put_flags,
const struct nlattr *key, size_t key_len,
const struct nlattr *mask, size_t mask_len,
const struct nlattr *actions, size_t actions_len,
struct dpif_flow_stats *);
int dpif_flow_del(struct dpif *,
Expand All @@ -464,6 +465,7 @@ struct dpif_flow_dump {
void dpif_flow_dump_start(struct dpif_flow_dump *, const struct dpif *);
bool dpif_flow_dump_next(struct dpif_flow_dump *,
const struct nlattr **key, size_t *key_len,
const struct nlattr **mask, size_t *mask_len,
const struct nlattr **actions, size_t *actions_len,
const struct dpif_flow_stats **);
int dpif_flow_dump_done(struct dpif_flow_dump *);
Expand Down Expand Up @@ -492,6 +494,8 @@ struct dpif_flow_put {
enum dpif_flow_put_flags flags; /* DPIF_FP_*. */
const struct nlattr *key; /* Flow to put. */
size_t key_len; /* Length of 'key' in bytes. */
const struct nlattr *mask; /* Mask to put. */
size_t mask_len; /* Length of 'mask' in bytes. */
const struct nlattr *actions; /* Actions to perform on flow. */
size_t actions_len; /* Length of 'actions' in bytes. */

Expand Down
2 changes: 1 addition & 1 deletion lib/netdev-dummy.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ eth_from_packet_or_flow(const char *s)
* settle for parsing a datapath key for now.
*/
ofpbuf_init(&odp_key, 0);
error = odp_flow_key_from_string(s, NULL, &odp_key);
error = odp_flow_from_string(s, NULL, &odp_key, NULL);
if (error) {
ofpbuf_uninit(&odp_key);
return NULL;
Expand Down
Loading

0 comments on commit e6cc0ba

Please sign in to comment.