summaryrefslogtreecommitdiff
path: root/datapath
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2011-02-01 09:25:26 -0800
committerBen Pfaff <blp@nicira.com>2011-02-01 09:25:26 -0800
commit3005302426764a2f701bb3507ad9602e3fe2dbb9 (patch)
tree1aff57f294aca72c3901e091138d59e1f85d92fb /datapath
parent0700107651b6a774f8f7ba873259a5d5011e3cb0 (diff)
downloadopenvswitch-3005302426764a2f701bb3507ad9602e3fe2dbb9.tar.gz
datapath: Dump flow actions only if there is room.
Expanding an skbuff in a netlink dump handler doesn't work well. We weren't updating the truesize of the skb or the allocation within the socket that netlink_dump() had put the skb in. The code had other bugs too. This commit fixes the problem (in my tests, anyway) by avoiding expanding the reply skbuff to fill in the actions. Instead, in such a case the userspace client has to do a separate "get" action to get the actions. This commit also updates userspace to do this automatically for dumps in the cases where the caller cares (only "ovs-dpctl dump-flows" currently cares). Signed-off-by: Ben Pfaff <blp@nicira.com> Acked-by: Jesse Gross <jesse@nicira.com> Bug #4520.
Diffstat (limited to 'datapath')
-rw-r--r--datapath/datapath.c32
1 files changed, 14 insertions, 18 deletions
diff --git a/datapath/datapath.c b/datapath/datapath.c
index babe63c07..74f276b55 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -827,7 +827,6 @@ static int odp_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
struct nlattr *nla;
unsigned long used;
u8 tcp_flags;
- int nla_len;
int err;
sf_acts = rcu_dereference_protected(flow->sf_acts,
@@ -863,23 +862,20 @@ static int odp_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
if (tcp_flags)
NLA_PUT_U8(skb, ODP_FLOW_ATTR_TCP_FLAGS, tcp_flags);
- /* If ODP_FLOW_ATTR_ACTIONS doesn't fit, and this is the first flow to
- * be dumped into 'skb', then expand the skb. This is unusual for
- * Netlink but individual action lists can be longer than a page and
- * thus entirely undumpable if we didn't do this. */
- nla_len = nla_total_size(sf_acts->actions_len);
- if (nla_len > skb_tailroom(skb) && !skb_orig_len) {
- int hdr_off = (unsigned char *)odp_header - skb->data;
-
- err = pskb_expand_head(skb, 0, nla_len - skb_tailroom(skb), GFP_KERNEL);
- if (err)
- goto error;
-
- odp_header = (struct odp_header *)(skb->data + hdr_off);
- }
- nla = nla_nest_start(skb, ODP_FLOW_ATTR_ACTIONS);
- memcpy(__skb_put(skb, sf_acts->actions_len), sf_acts->actions, sf_acts->actions_len);
- nla_nest_end(skb, nla);
+ /* If ODP_FLOW_ATTR_ACTIONS doesn't fit, skip dumping the actions if
+ * this is the first flow to be dumped into 'skb'. This is unusual for
+ * Netlink but individual action lists can be longer than
+ * NLMSG_GOODSIZE and thus entirely undumpable if we didn't do this.
+ * The userspace caller can always fetch the actions separately if it
+ * really wants them. (Most userspace callers in fact don't care.)
+ *
+ * This can only fail for dump operations because the skb is always
+ * properly sized for single flows.
+ */
+ err = nla_put(skb, ODP_FLOW_ATTR_ACTIONS, sf_acts->actions_len,
+ sf_acts->actions);
+ if (err < 0 && skb_orig_len)
+ goto error;
return genlmsg_end(skb, odp_header);