diff options
author | Jesse Gross <jesse@nicira.com> | 2014-10-03 18:35:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-10-06 00:32:20 -0400 |
commit | 6b205b2ca17e88ef5e10451b720056b790cc63a5 (patch) | |
tree | bd94053b6d8bad4ed2852daf8254a3ea45200ecb /net/openvswitch/datapath.c | |
parent | f0b128c1e2cc33ad104daf0f51a51e34f7763c5f (diff) |
openvswitch: Factor out allocation and verification of actions.
As the size of the flow key grows, it can put some pressure on the
stack. This is particularly true in ovs_flow_cmd_set(), which needs several
copies of the key on the stack. One of those uses is logically separate,
so this factors it out to reduce stack pressure and improve readibility.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Signed-off-by: Andy Zhou <azhou@nicira.com>
Acked-by: Pravin B Shelar <pshelar@nicira.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch/datapath.c')
-rw-r--r-- | net/openvswitch/datapath.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index f6bd93d5f435..010125c48244 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -933,11 +933,34 @@ error: | |||
933 | return error; | 933 | return error; |
934 | } | 934 | } |
935 | 935 | ||
936 | static struct sw_flow_actions *get_flow_actions(const struct nlattr *a, | ||
937 | const struct sw_flow_key *key, | ||
938 | const struct sw_flow_mask *mask) | ||
939 | { | ||
940 | struct sw_flow_actions *acts; | ||
941 | struct sw_flow_key masked_key; | ||
942 | int error; | ||
943 | |||
944 | acts = ovs_nla_alloc_flow_actions(nla_len(a)); | ||
945 | if (IS_ERR(acts)) | ||
946 | return acts; | ||
947 | |||
948 | ovs_flow_mask_key(&masked_key, key, mask); | ||
949 | error = ovs_nla_copy_actions(a, &masked_key, 0, &acts); | ||
950 | if (error) { | ||
951 | OVS_NLERR("Flow actions may not be safe on all matching packets.\n"); | ||
952 | kfree(acts); | ||
953 | return ERR_PTR(error); | ||
954 | } | ||
955 | |||
956 | return acts; | ||
957 | } | ||
958 | |||
936 | static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info) | 959 | static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info) |
937 | { | 960 | { |
938 | struct nlattr **a = info->attrs; | 961 | struct nlattr **a = info->attrs; |
939 | struct ovs_header *ovs_header = info->userhdr; | 962 | struct ovs_header *ovs_header = info->userhdr; |
940 | struct sw_flow_key key, masked_key; | 963 | struct sw_flow_key key; |
941 | struct sw_flow *flow; | 964 | struct sw_flow *flow; |
942 | struct sw_flow_mask mask; | 965 | struct sw_flow_mask mask; |
943 | struct sk_buff *reply = NULL; | 966 | struct sk_buff *reply = NULL; |
@@ -959,17 +982,10 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info) | |||
959 | 982 | ||
960 | /* Validate actions. */ | 983 | /* Validate actions. */ |
961 | if (a[OVS_FLOW_ATTR_ACTIONS]) { | 984 | if (a[OVS_FLOW_ATTR_ACTIONS]) { |
962 | acts = ovs_nla_alloc_flow_actions(nla_len(a[OVS_FLOW_ATTR_ACTIONS])); | 985 | acts = get_flow_actions(a[OVS_FLOW_ATTR_ACTIONS], &key, &mask); |
963 | error = PTR_ERR(acts); | 986 | if (IS_ERR(acts)) { |
964 | if (IS_ERR(acts)) | 987 | error = PTR_ERR(acts); |
965 | goto error; | 988 | goto error; |
966 | |||
967 | ovs_flow_mask_key(&masked_key, &key, &mask); | ||
968 | error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], | ||
969 | &masked_key, 0, &acts); | ||
970 | if (error) { | ||
971 | OVS_NLERR("Flow actions may not be safe on all matching packets.\n"); | ||
972 | goto err_kfree_acts; | ||
973 | } | 989 | } |
974 | } | 990 | } |
975 | 991 | ||