From 3bdad189c91426ec7b06ae03ea573e45e06b435c Mon Sep 17 00:00:00 2001 From: Joe Stringer Date: Fri, 4 Jul 2014 08:37:12 +0000 Subject: [PATCH] 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 Acked-by: Ben Pfaff --- lib/dpif-linux.c | 23 +++++++++++++---------- lib/dpif-netdev.c | 30 +++++++++++++++++++++++++++--- lib/dpif-provider.h | 21 ++++++++++++++++----- lib/dpif.c | 44 ++++++++++++++++++++++++++++++++------------ lib/dpif.h | 5 ++++- 5 files changed, 92 insertions(+), 31 deletions(-) diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c index 6a8564afd..93154a343 100644 --- a/lib/dpif-linux.c +++ b/lib/dpif-linux.c @@ -1041,24 +1041,27 @@ dpif_linux_flow_get__(const struct dpif_linux *dpif, static int dpif_linux_flow_get(const struct dpif *dpif_, 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_); struct dpif_linux_flow reply; - struct ofpbuf *buf; 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 (stats) { - dpif_linux_flow_get_stats(&reply, stats); + if (maskp) { + *maskp = CONST_CAST(struct nlattr *, reply.mask); + *mask_len = reply.mask_len; } if (actionsp) { - ofpbuf_set_data(buf, CONST_CAST(struct nlattr *, reply.actions)); - ofpbuf_set_size(buf, reply.actions_len); - *actionsp = buf; - } else { - ofpbuf_delete(buf); + *actionsp = CONST_CAST(struct nlattr *, reply.actions); + *actions_len = reply.actions_len; + } + if (stats) { + dpif_linux_flow_get_stats(&reply, stats); } } return error; diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index fdf1af4d8..fb3530671 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -1191,7 +1191,10 @@ dpif_netdev_flow_from_nlattrs(const struct nlattr *key, uint32_t key_len, static int dpif_netdev_flow_get(const struct dpif *dpif, 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_flow *netdev_flow; @@ -1212,11 +1215,32 @@ dpif_netdev_flow_get(const struct dpif *dpif, get_dpif_flow_stats(netdev_flow, stats); } - if (actionsp) { + if (maskp || actionsp) { struct dp_netdev_actions *actions; + size_t len = 0; actions = dp_netdev_flow_get_actions(netdev_flow); - *actionsp = ofpbuf_clone_data(actions->actions, actions->size); + len += maskp ? sizeof(struct odputil_keybuf) : 0; + len += actionsp ? actions->size : 0; + + *bufp = ofpbuf_new(len); + if (maskp) { + struct flow_wildcards wc; + + 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); + *maskp = ofpbuf_data(*bufp); + *mask_len = ofpbuf_size(*bufp); + } + if (actionsp) { + struct dp_netdev_actions *actions; + + actions = dp_netdev_flow_get_actions(netdev_flow); + *actionsp = ofpbuf_put(*bufp, actions->actions, actions->size); + *actions_len = actions->size; + } } } else { error = ENOENT; diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h index 615f2c680..389e84e8f 100644 --- a/lib/dpif-provider.h +++ b/lib/dpif-provider.h @@ -224,16 +224,27 @@ struct dpif_class { * Returns 0 if successful. If no flow matches, returns ENOENT. On other * failure, returns a positive errno value. * - * If 'actionsp' is nonnull, then on success '*actionsp' must be set to an - * ofpbuf owned by the caller that contains the Netlink attributes for the - * flow's actions. The caller must free the ofpbuf (with ofpbuf_delete()) - * when it is no longer needed. + * On success, '*bufp' will be set to an ofpbuf owned by the caller that + * contains the response for 'maskp' and 'actionsp'. The caller must supply + * a valid pointer, and must free the ofpbuf (with ofpbuf_delete()) 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, stored in '*bufp'. '*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, stored in '*bufp'. + * '*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 * flow's statistics. */ int (*flow_get)(const struct dpif *dpif, 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 * attributes with types OVS_KEY_ATTR_* in the 'put->key_len' bytes diff --git a/lib/dpif.c b/lib/dpif.c index 8ec8200f7..450c6c88b 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -831,44 +831,64 @@ dpif_flow_flush(struct dpif *dpif) * Returns 0 if successful. If no flow matches, returns ENOENT. On other * failure, returns a positive errno value. * - * If 'actionsp' is nonnull, then on success '*actionsp' will be set to an - * ofpbuf owned by the caller that contains the Netlink attributes for the - * flow's actions. The caller must free the ofpbuf (with ofpbuf_delete()) when - * it is no longer needed. + * On success, '*bufp' will be set to an ofpbuf owned by the caller that + * contains the response for 'maskp' and 'actionsp'. The caller must supply + * a valid pointer, and must free the ofpbuf (with ofpbuf_delete()) 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, stored in '*bufp'. '*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, stored in '*bufp'. + * '*actions_len' will be set to the length of the actions attributes. * * If 'stats' is nonnull, then on success it will be updated with the flow's * statistics. */ int dpif_flow_get(const struct dpif *dpif, - const struct nlattr *key, size_t key_len, - struct ofpbuf **actionsp, struct dpif_flow_stats *stats) + const struct nlattr *key, size_t key_len, struct ofpbuf **bufp, + struct nlattr **maskp, size_t *mask_len, + struct nlattr **actionsp, size_t *actions_len, + struct dpif_flow_stats *stats) { int error; 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, + maskp, mask_len, + actionsp, actions_len, + stats); if (error) { if (actionsp) { *actionsp = NULL; + *actions_len = 0; + } + if (maskp) { + *maskp = NULL; + *mask_len = 0; } if (stats) { memset(stats, 0, sizeof *stats); } + ofpbuf_delete(*bufp); } if (should_log_flow_message(error)) { const struct nlattr *actions; - size_t actions_len; + size_t acts_len; if (!error && actionsp) { - actions = ofpbuf_data(*actionsp); - actions_len = ofpbuf_size(*actionsp); + actions = *actionsp; + acts_len = *actions_len; } else { actions = NULL; - actions_len = 0; + acts_len = 0; } log_flow_message(dpif, error, "flow_get", key, key_len, - NULL, 0, stats, actions, actions_len); + NULL, 0, stats, actions, acts_len); } return error; } diff --git a/lib/dpif.h b/lib/dpif.h index e7aca8e41..f13cc365b 100644 --- a/lib/dpif.h +++ b/lib/dpif.h @@ -524,7 +524,10 @@ int dpif_flow_del(struct dpif *, struct dpif_flow_stats *); int dpif_flow_get(const struct dpif *, const struct nlattr *key, size_t key_len, - struct ofpbuf **actionsp, struct dpif_flow_stats *); + struct ofpbuf **bufp, + struct nlattr **maskp, size_t *mask_len, + struct nlattr **actionsp, size_t *acts_len, + struct dpif_flow_stats *stats); struct dpif_flow_dump { const struct dpif *dpif; -- 2.20.1