mirror of
https://github.com/openvswitch/ovs
synced 2025-10-17 14:28:02 +00:00
dpif: Support fetching flow mask via dpif_flow_get().
Change the interface to allow implementations to pass back a buffer, and allow callers to specify which of actions, mask, and stats they wish to receive. This will be used in the next commit. Signed-off-by: Joe Stringer <joestringer@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
@@ -1053,24 +1053,27 @@ dpif_linux_flow_get__(const struct dpif_linux *dpif,
|
|||||||
static int
|
static int
|
||||||
dpif_linux_flow_get(const struct dpif *dpif_,
|
dpif_linux_flow_get(const struct dpif *dpif_,
|
||||||
const struct nlattr *key, size_t key_len,
|
const struct nlattr *key, size_t key_len,
|
||||||
struct ofpbuf **actionsp, struct dpif_flow_stats *stats)
|
struct ofpbuf **bufp,
|
||||||
|
struct nlattr **maskp, size_t *mask_len,
|
||||||
|
struct nlattr **actionsp, size_t *actions_len,
|
||||||
|
struct dpif_flow_stats *stats)
|
||||||
{
|
{
|
||||||
const struct dpif_linux *dpif = dpif_linux_cast(dpif_);
|
const struct dpif_linux *dpif = dpif_linux_cast(dpif_);
|
||||||
struct dpif_linux_flow reply;
|
struct dpif_linux_flow reply;
|
||||||
struct ofpbuf *buf;
|
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = dpif_linux_flow_get__(dpif, key, key_len, &reply, &buf);
|
error = dpif_linux_flow_get__(dpif, key, key_len, &reply, bufp);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
if (stats) {
|
if (maskp) {
|
||||||
dpif_linux_flow_get_stats(&reply, stats);
|
*maskp = CONST_CAST(struct nlattr *, reply.mask);
|
||||||
|
*mask_len = reply.mask_len;
|
||||||
}
|
}
|
||||||
if (actionsp) {
|
if (actionsp) {
|
||||||
ofpbuf_set_data(buf, CONST_CAST(struct nlattr *, reply.actions));
|
*actionsp = CONST_CAST(struct nlattr *, reply.actions);
|
||||||
ofpbuf_set_size(buf, reply.actions_len);
|
*actions_len = reply.actions_len;
|
||||||
*actionsp = buf;
|
}
|
||||||
} else {
|
if (stats) {
|
||||||
ofpbuf_delete(buf);
|
dpif_linux_flow_get_stats(&reply, stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
|
@@ -1203,7 +1203,10 @@ dpif_netdev_flow_from_nlattrs(const struct nlattr *key, uint32_t key_len,
|
|||||||
static int
|
static int
|
||||||
dpif_netdev_flow_get(const struct dpif *dpif,
|
dpif_netdev_flow_get(const struct dpif *dpif,
|
||||||
const struct nlattr *nl_key, size_t nl_key_len,
|
const struct nlattr *nl_key, size_t nl_key_len,
|
||||||
struct ofpbuf **actionsp, struct dpif_flow_stats *stats)
|
struct ofpbuf **bufp,
|
||||||
|
struct nlattr **maskp, size_t *mask_len,
|
||||||
|
struct nlattr **actionsp, size_t *actions_len,
|
||||||
|
struct dpif_flow_stats *stats)
|
||||||
{
|
{
|
||||||
struct dp_netdev *dp = get_dp_netdev(dpif);
|
struct dp_netdev *dp = get_dp_netdev(dpif);
|
||||||
struct dp_netdev_flow *netdev_flow;
|
struct dp_netdev_flow *netdev_flow;
|
||||||
@@ -1222,11 +1225,23 @@ dpif_netdev_flow_get(const struct dpif *dpif,
|
|||||||
get_dpif_flow_stats(netdev_flow, stats);
|
get_dpif_flow_stats(netdev_flow, stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (maskp) {
|
||||||
|
struct flow_wildcards wc;
|
||||||
|
|
||||||
|
*bufp = ofpbuf_new(sizeof(struct odputil_keybuf));
|
||||||
|
minimask_expand(&netdev_flow->cr.match.mask, &wc);
|
||||||
|
odp_flow_key_from_mask(*bufp, &wc.masks, &netdev_flow->flow,
|
||||||
|
odp_to_u32(wc.masks.in_port.odp_port),
|
||||||
|
SIZE_MAX, true);
|
||||||
|
*maskp = ofpbuf_data(*bufp);
|
||||||
|
*mask_len = ofpbuf_size(*bufp);
|
||||||
|
}
|
||||||
if (actionsp) {
|
if (actionsp) {
|
||||||
struct dp_netdev_actions *actions;
|
struct dp_netdev_actions *actions;
|
||||||
|
|
||||||
actions = dp_netdev_flow_get_actions(netdev_flow);
|
actions = dp_netdev_flow_get_actions(netdev_flow);
|
||||||
*actionsp = ofpbuf_clone_data(actions->actions, actions->size);
|
*actionsp = actions->actions;
|
||||||
|
*actions_len = actions->size;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error = ENOENT;
|
error = ENOENT;
|
||||||
|
@@ -246,16 +246,27 @@ struct dpif_class {
|
|||||||
* Returns 0 if successful. If no flow matches, returns ENOENT. On other
|
* Returns 0 if successful. If no flow matches, returns ENOENT. On other
|
||||||
* failure, returns a positive errno value.
|
* failure, returns a positive errno value.
|
||||||
*
|
*
|
||||||
* If 'actionsp' is nonnull, then on success '*actionsp' must be set to an
|
* On success, '*bufp' will be set to an ofpbuf owned by the caller that
|
||||||
* ofpbuf owned by the caller that contains the Netlink attributes for the
|
* contains the response for 'maskp' and/or 'actionsp'. The caller must
|
||||||
* flow's actions. The caller must free the ofpbuf (with ofpbuf_delete())
|
* supply a valid pointer, and must free the ofpbuf (with ofpbuf_delete())
|
||||||
* when it is no longer needed.
|
* when it is no longer needed.
|
||||||
*
|
*
|
||||||
|
* If 'maskp' is nonnull, then on success '*maskp' will point to the
|
||||||
|
* Netlink attributes for the flow's mask. '*mask_len' will be set to the
|
||||||
|
* length of the mask attributes.
|
||||||
|
*
|
||||||
|
* If 'actionsp' is nonnull, then on success '*actionsp' will point to the
|
||||||
|
* Netlink attributes for the flow's actions. '*actions_len' will be set to
|
||||||
|
* the length of the actions attributes.
|
||||||
|
*
|
||||||
* If 'stats' is nonnull, then on success it must be updated with the
|
* If 'stats' is nonnull, then on success it must be updated with the
|
||||||
* flow's statistics. */
|
* flow's statistics. */
|
||||||
int (*flow_get)(const struct dpif *dpif,
|
int (*flow_get)(const struct dpif *dpif,
|
||||||
const struct nlattr *key, size_t key_len,
|
const struct nlattr *key, size_t key_len,
|
||||||
struct ofpbuf **actionsp, struct dpif_flow_stats *stats);
|
struct ofpbuf **bufp,
|
||||||
|
struct nlattr **maskp, size_t *mask_len,
|
||||||
|
struct nlattr **actionsp, size_t *acts_len,
|
||||||
|
struct dpif_flow_stats *stats);
|
||||||
|
|
||||||
/* Adds or modifies a flow in 'dpif'. The flow is specified by the Netlink
|
/* Adds or modifies a flow in 'dpif'. The flow is specified by the Netlink
|
||||||
* attributes with types OVS_KEY_ATTR_* in the 'put->key_len' bytes
|
* attributes with types OVS_KEY_ATTR_* in the 'put->key_len' bytes
|
||||||
|
50
lib/dpif.c
50
lib/dpif.c
@@ -834,44 +834,46 @@ dpif_flow_flush(struct dpif *dpif)
|
|||||||
* Returns 0 if successful. If no flow matches, returns ENOENT. On other
|
* Returns 0 if successful. If no flow matches, returns ENOENT. On other
|
||||||
* failure, returns a positive errno value.
|
* failure, returns a positive errno value.
|
||||||
*
|
*
|
||||||
* If 'actionsp' is nonnull, then on success '*actionsp' will be set to an
|
* On success, '*bufp' will be set to an ofpbuf owned by the caller that
|
||||||
* ofpbuf owned by the caller that contains the Netlink attributes for the
|
* contains the response for 'flow->mask' and 'flow->actions'. The caller must
|
||||||
* flow's actions. The caller must free the ofpbuf (with ofpbuf_delete()) when
|
* supply a valid pointer, and must free the ofpbuf (with ofpbuf_delete()) when
|
||||||
* it is no longer needed.
|
* it is no longer needed.
|
||||||
*
|
*
|
||||||
* If 'stats' is nonnull, then on success it will be updated with the flow's
|
* On success, 'flow' will be populated with the mask, actions and stats for
|
||||||
* statistics. */
|
* the datapath flow corresponding to 'key'. The mask and actions will point
|
||||||
|
* within '*bufp'.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
dpif_flow_get(const struct dpif *dpif,
|
dpif_flow_get(const struct dpif *dpif,
|
||||||
const struct nlattr *key, size_t key_len,
|
const struct nlattr *key, size_t key_len,
|
||||||
struct ofpbuf **actionsp, struct dpif_flow_stats *stats)
|
struct ofpbuf **bufp, struct dpif_flow *flow)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
struct nlattr *mask, *actions;
|
||||||
|
size_t mask_len, actions_len;
|
||||||
|
struct dpif_flow_stats stats;
|
||||||
|
|
||||||
COVERAGE_INC(dpif_flow_get);
|
COVERAGE_INC(dpif_flow_get);
|
||||||
|
|
||||||
error = dpif->dpif_class->flow_get(dpif, key, key_len, actionsp, stats);
|
*bufp = NULL;
|
||||||
|
error = dpif->dpif_class->flow_get(dpif, key, key_len, bufp,
|
||||||
|
&mask, &mask_len,
|
||||||
|
&actions, &actions_len, &stats);
|
||||||
if (error) {
|
if (error) {
|
||||||
if (actionsp) {
|
memset(flow, 0, sizeof *flow);
|
||||||
*actionsp = NULL;
|
ofpbuf_delete(*bufp);
|
||||||
}
|
*bufp = NULL;
|
||||||
if (stats) {
|
} else {
|
||||||
memset(stats, 0, sizeof *stats);
|
flow->mask = mask;
|
||||||
}
|
flow->mask_len = mask_len;
|
||||||
|
flow->actions = actions;
|
||||||
|
flow->actions_len = actions_len;
|
||||||
|
flow->stats = stats;
|
||||||
}
|
}
|
||||||
if (should_log_flow_message(error)) {
|
if (should_log_flow_message(error)) {
|
||||||
const struct nlattr *actions;
|
|
||||||
size_t actions_len;
|
|
||||||
|
|
||||||
if (!error && actionsp) {
|
|
||||||
actions = ofpbuf_data(*actionsp);
|
|
||||||
actions_len = ofpbuf_size(*actionsp);
|
|
||||||
} else {
|
|
||||||
actions = NULL;
|
|
||||||
actions_len = 0;
|
|
||||||
}
|
|
||||||
log_flow_message(dpif, error, "flow_get", key, key_len,
|
log_flow_message(dpif, error, "flow_get", key, key_len,
|
||||||
NULL, 0, stats, actions, actions_len);
|
NULL, 0, &flow->stats,
|
||||||
|
flow->actions, flow->actions_len);
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@@ -405,6 +405,7 @@ struct flow;
|
|||||||
struct nlattr;
|
struct nlattr;
|
||||||
struct sset;
|
struct sset;
|
||||||
struct dpif_class;
|
struct dpif_class;
|
||||||
|
struct dpif_flow;
|
||||||
|
|
||||||
int dp_register_provider(const struct dpif_class *);
|
int dp_register_provider(const struct dpif_class *);
|
||||||
int dp_unregister_provider(const char *type);
|
int dp_unregister_provider(const char *type);
|
||||||
@@ -524,7 +525,7 @@ int dpif_flow_del(struct dpif *,
|
|||||||
struct dpif_flow_stats *);
|
struct dpif_flow_stats *);
|
||||||
int dpif_flow_get(const struct dpif *,
|
int dpif_flow_get(const struct dpif *,
|
||||||
const struct nlattr *key, size_t key_len,
|
const struct nlattr *key, size_t key_len,
|
||||||
struct ofpbuf **actionsp, struct dpif_flow_stats *);
|
struct ofpbuf **, struct dpif_flow *);
|
||||||
|
|
||||||
/* Flow dumping interface
|
/* Flow dumping interface
|
||||||
* ======================
|
* ======================
|
||||||
|
Reference in New Issue
Block a user