265 lines
7.9 KiB
Diff
265 lines
7.9 KiB
Diff
From e6f9b1f96a3ac4066c9d7d4c0a9da7e8abb1597f Mon Sep 17 00:00:00 2001
|
|
From: Yi Yang <yi.y.yang@intel.com>
|
|
Date: Wed, 13 Apr 2016 18:17:21 +0800
|
|
Subject: [PATCH 4/5] Fix too large stack frame size
|
|
|
|
Signed-off-by: Yi Yang <yi.y.yang@intel.com>
|
|
---
|
|
datapath/datapath.c | 92 +++++++++++++++++++++++++++++++++++++++++++++--------
|
|
1 file changed, 78 insertions(+), 14 deletions(-)
|
|
|
|
diff --git a/datapath/datapath.c b/datapath/datapath.c
|
|
index 5bec072..4baf242 100644
|
|
--- a/datapath/datapath.c
|
|
+++ b/datapath/datapath.c
|
|
@@ -928,7 +928,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
|
struct sw_flow_mask mask;
|
|
struct sk_buff *reply;
|
|
struct datapath *dp;
|
|
- struct sw_flow_key key;
|
|
+ struct sw_flow_key *key = NULL;
|
|
struct sw_flow_actions *acts;
|
|
struct sw_flow_match match;
|
|
u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
|
|
@@ -946,6 +946,12 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
|
goto error;
|
|
}
|
|
|
|
+ error = -ENOMEM;
|
|
+ key = kzalloc(sizeof(struct sw_flow_key), GFP_KERNEL);
|
|
+ if (key == NULL) {
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
/* Most of the time we need to allocate a new flow, do it before
|
|
* locking.
|
|
*/
|
|
@@ -956,17 +962,17 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
|
}
|
|
|
|
/* Extract key. */
|
|
- ovs_match_init(&match, &key, &mask);
|
|
+ ovs_match_init(&match, key, &mask);
|
|
error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
|
|
a[OVS_FLOW_ATTR_MASK], log);
|
|
if (error)
|
|
goto err_kfree_flow;
|
|
|
|
- ovs_flow_mask_key(&new_flow->key, &key, true, &mask);
|
|
+ ovs_flow_mask_key(&new_flow->key, key, true, &mask);
|
|
|
|
/* Extract flow identifier. */
|
|
error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID],
|
|
- &key, log);
|
|
+ key, log);
|
|
if (error)
|
|
goto err_kfree_flow;
|
|
|
|
@@ -996,7 +1002,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
|
if (ovs_identifier_is_ufid(&new_flow->id))
|
|
flow = ovs_flow_tbl_lookup_ufid(&dp->table, &new_flow->id);
|
|
if (!flow)
|
|
- flow = ovs_flow_tbl_lookup(&dp->table, &key);
|
|
+ flow = ovs_flow_tbl_lookup(&dp->table, key);
|
|
if (likely(!flow)) {
|
|
rcu_assign_pointer(new_flow->sf_acts, acts);
|
|
|
|
@@ -1066,6 +1072,10 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
if (reply)
|
|
ovs_notify(&dp_flow_genl_family, &ovs_dp_flow_multicast_group, reply, info);
|
|
+ if (key != NULL) {
|
|
+ kfree(key);
|
|
+ key = NULL;
|
|
+ }
|
|
return 0;
|
|
|
|
err_unlock_ovs:
|
|
@@ -1076,6 +1086,10 @@ err_kfree_acts:
|
|
err_kfree_flow:
|
|
ovs_flow_free(new_flow, false);
|
|
error:
|
|
+ if (key != NULL) {
|
|
+ kfree(key);
|
|
+ key = NULL;
|
|
+ }
|
|
return error;
|
|
}
|
|
|
|
@@ -1106,7 +1120,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
|
struct net *net = sock_net(skb->sk);
|
|
struct nlattr **a = info->attrs;
|
|
struct ovs_header *ovs_header = info->userhdr;
|
|
- struct sw_flow_key key;
|
|
+ struct sw_flow_key *key = NULL;
|
|
struct sw_flow *flow;
|
|
struct sw_flow_mask mask;
|
|
struct sk_buff *reply = NULL;
|
|
@@ -1119,6 +1133,12 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
|
bool log = !a[OVS_FLOW_ATTR_PROBE];
|
|
bool ufid_present;
|
|
|
|
+ error = -ENOMEM;
|
|
+ key = kzalloc(sizeof(struct sw_flow_key), GFP_KERNEL);
|
|
+ if (key == NULL) {
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
/* Extract key. */
|
|
error = -EINVAL;
|
|
if (!a[OVS_FLOW_ATTR_KEY]) {
|
|
@@ -1127,7 +1147,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
|
}
|
|
|
|
ufid_present = ovs_nla_get_ufid(&sfid, a[OVS_FLOW_ATTR_UFID], log);
|
|
- ovs_match_init(&match, &key, &mask);
|
|
+ ovs_match_init(&match, key, &mask);
|
|
error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
|
|
a[OVS_FLOW_ATTR_MASK], log);
|
|
if (error)
|
|
@@ -1135,7 +1155,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
/* Validate actions. */
|
|
if (a[OVS_FLOW_ATTR_ACTIONS]) {
|
|
- acts = get_flow_actions(net, a[OVS_FLOW_ATTR_ACTIONS], &key,
|
|
+ acts = get_flow_actions(net, a[OVS_FLOW_ATTR_ACTIONS], key,
|
|
&mask, log);
|
|
if (IS_ERR(acts)) {
|
|
error = PTR_ERR(acts);
|
|
@@ -1203,6 +1223,10 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
|
if (old_acts)
|
|
ovs_nla_free_flow_actions_rcu(old_acts);
|
|
|
|
+ if (key != NULL) {
|
|
+ kfree(key);
|
|
+ key = NULL;
|
|
+ }
|
|
return 0;
|
|
|
|
err_unlock_ovs:
|
|
@@ -1211,6 +1235,10 @@ err_unlock_ovs:
|
|
err_kfree_acts:
|
|
ovs_nla_free_flow_actions(acts);
|
|
error:
|
|
+ if (key != NULL) {
|
|
+ kfree(key);
|
|
+ key = NULL;
|
|
+ }
|
|
return error;
|
|
}
|
|
|
|
@@ -1219,7 +1247,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
|
|
struct nlattr **a = info->attrs;
|
|
struct ovs_header *ovs_header = info->userhdr;
|
|
struct net *net = sock_net(skb->sk);
|
|
- struct sw_flow_key key;
|
|
+ struct sw_flow_key *key = NULL;
|
|
struct sk_buff *reply;
|
|
struct sw_flow *flow;
|
|
struct datapath *dp;
|
|
@@ -1230,9 +1258,15 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
|
|
bool log = !a[OVS_FLOW_ATTR_PROBE];
|
|
bool ufid_present;
|
|
|
|
+ err = -ENOMEM;
|
|
+ key = kzalloc(sizeof(struct sw_flow_key), GFP_KERNEL);
|
|
+ if (key == NULL) {
|
|
+ return err;
|
|
+ }
|
|
+
|
|
ufid_present = ovs_nla_get_ufid(&ufid, a[OVS_FLOW_ATTR_UFID], log);
|
|
if (a[OVS_FLOW_ATTR_KEY]) {
|
|
- ovs_match_init(&match, &key, NULL);
|
|
+ ovs_match_init(&match, key, NULL);
|
|
err = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY], NULL,
|
|
log);
|
|
} else if (!ufid_present) {
|
|
@@ -1240,9 +1274,13 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
|
|
"Flow get message rejected, Key attribute missing.");
|
|
err = -EINVAL;
|
|
}
|
|
- if (err)
|
|
+ if (err) {
|
|
+ if (key != NULL) {
|
|
+ kfree(key);
|
|
+ key = NULL;
|
|
+ }
|
|
return err;
|
|
-
|
|
+ }
|
|
ovs_lock();
|
|
dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
|
|
if (!dp) {
|
|
@@ -1267,9 +1305,17 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
|
|
}
|
|
|
|
ovs_unlock();
|
|
+ if (key != NULL) {
|
|
+ kfree(key);
|
|
+ key = NULL;
|
|
+ }
|
|
return genlmsg_reply(reply, info);
|
|
unlock:
|
|
ovs_unlock();
|
|
+ if (key != NULL) {
|
|
+ kfree(key);
|
|
+ key = NULL;
|
|
+ }
|
|
return err;
|
|
}
|
|
|
|
@@ -1278,7 +1324,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
|
|
struct nlattr **a = info->attrs;
|
|
struct ovs_header *ovs_header = info->userhdr;
|
|
struct net *net = sock_net(skb->sk);
|
|
- struct sw_flow_key key;
|
|
+ struct sw_flow_key *key = NULL;
|
|
struct sk_buff *reply;
|
|
struct sw_flow *flow = NULL;
|
|
struct datapath *dp;
|
|
@@ -1289,12 +1335,22 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
|
|
bool log = !a[OVS_FLOW_ATTR_PROBE];
|
|
bool ufid_present;
|
|
|
|
+ err = -ENOMEM;
|
|
+ key = kzalloc(sizeof(struct sw_flow_key), GFP_KERNEL);
|
|
+ if (key == NULL) {
|
|
+ return err;
|
|
+ }
|
|
+
|
|
ufid_present = ovs_nla_get_ufid(&ufid, a[OVS_FLOW_ATTR_UFID], log);
|
|
if (a[OVS_FLOW_ATTR_KEY]) {
|
|
- ovs_match_init(&match, &key, NULL);
|
|
+ ovs_match_init(&match, key, NULL);
|
|
err = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
|
|
NULL, log);
|
|
if (unlikely(err))
|
|
+ if (key != NULL) {
|
|
+ kfree(key);
|
|
+ key = NULL;
|
|
+ }
|
|
return err;
|
|
}
|
|
|
|
@@ -1344,9 +1400,17 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
|
|
}
|
|
|
|
ovs_flow_free(flow, true);
|
|
+ if (key != NULL) {
|
|
+ kfree(key);
|
|
+ key = NULL;
|
|
+ }
|
|
return 0;
|
|
unlock:
|
|
ovs_unlock();
|
|
+ if (key != NULL) {
|
|
+ kfree(key);
|
|
+ key = NULL;
|
|
+ }
|
|
return err;
|
|
}
|
|
|
|
--
|
|
1.9.3
|
|
|