diff options
| author | Tonghao Zhang <xiangxia.m.yue@gmail.com> | 2017-06-29 20:27:44 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2017-07-01 12:09:59 -0400 |
| commit | 9cc9a5cb176ccb4f2cda5ac34da5a659926f125f (patch) | |
| tree | 3fd2e4ecc9d5c9ef188ee1c85e25234bcde82a28 /net/openvswitch | |
| parent | 7e5988df26cdd7d823ab473ad3e3ca6623a66f21 (diff) | |
datapath: Avoid using stack larger than 1024.
When compiling OvS-master on 4.4.0-81 kernel,
there is a warning:
CC [M] /root/ovs/datapath/linux/datapath.o
/root/ovs/datapath/linux/datapath.c: In function
'ovs_flow_cmd_set':
/root/ovs/datapath/linux/datapath.c:1221:1: warning:
the frame size of 1040 bytes is larger than 1024 bytes
[-Wframe-larger-than=]
This patch factors out match-init and action-copy to avoid
"Wframe-larger-than=1024" warning. Because mask is only
used to get actions, we new a function to save some
stack space.
Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com>
Acked-by: Pravin B Shelar <pshelar@ovn.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch')
| -rw-r--r-- | net/openvswitch/datapath.c | 81 |
1 files changed, 58 insertions, 23 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index d772e9a4b4f8..45fe8c8a884d 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
| @@ -1090,6 +1090,58 @@ static struct sw_flow_actions *get_flow_actions(struct net *net, | |||
| 1090 | return acts; | 1090 | return acts; |
| 1091 | } | 1091 | } |
| 1092 | 1092 | ||
| 1093 | /* Factor out match-init and action-copy to avoid | ||
| 1094 | * "Wframe-larger-than=1024" warning. Because mask is only | ||
| 1095 | * used to get actions, we new a function to save some | ||
| 1096 | * stack space. | ||
| 1097 | * | ||
| 1098 | * If there are not key and action attrs, we return 0 | ||
| 1099 | * directly. In the case, the caller will also not use the | ||
| 1100 | * match as before. If there is action attr, we try to get | ||
| 1101 | * actions and save them to *acts. Before returning from | ||
| 1102 | * the function, we reset the match->mask pointer. Because | ||
| 1103 | * we should not to return match object with dangling reference | ||
| 1104 | * to mask. | ||
| 1105 | * */ | ||
| 1106 | static int ovs_nla_init_match_and_action(struct net *net, | ||
| 1107 | struct sw_flow_match *match, | ||
| 1108 | struct sw_flow_key *key, | ||
| 1109 | struct nlattr **a, | ||
| 1110 | struct sw_flow_actions **acts, | ||
| 1111 | bool log) | ||
| 1112 | { | ||
| 1113 | struct sw_flow_mask mask; | ||
| 1114 | int error = 0; | ||
| 1115 | |||
| 1116 | if (a[OVS_FLOW_ATTR_KEY]) { | ||
| 1117 | ovs_match_init(match, key, true, &mask); | ||
| 1118 | error = ovs_nla_get_match(net, match, a[OVS_FLOW_ATTR_KEY], | ||
| 1119 | a[OVS_FLOW_ATTR_MASK], log); | ||
| 1120 | if (error) | ||
| 1121 | goto error; | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | if (a[OVS_FLOW_ATTR_ACTIONS]) { | ||
| 1125 | if (!a[OVS_FLOW_ATTR_KEY]) { | ||
| 1126 | OVS_NLERR(log, | ||
| 1127 | "Flow key attribute not present in set flow."); | ||
| 1128 | return -EINVAL; | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | *acts = get_flow_actions(net, a[OVS_FLOW_ATTR_ACTIONS], key, | ||
| 1132 | &mask, log); | ||
| 1133 | if (IS_ERR(*acts)) { | ||
| 1134 | error = PTR_ERR(*acts); | ||
| 1135 | goto error; | ||
| 1136 | } | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | /* On success, error is 0. */ | ||
| 1140 | error: | ||
| 1141 | match->mask = NULL; | ||
| 1142 | return error; | ||
| 1143 | } | ||
| 1144 | |||
| 1093 | static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info) | 1145 | static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info) |
| 1094 | { | 1146 | { |
| 1095 | struct net *net = sock_net(skb->sk); | 1147 | struct net *net = sock_net(skb->sk); |
| @@ -1097,7 +1149,6 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info) | |||
| 1097 | struct ovs_header *ovs_header = info->userhdr; | 1149 | struct ovs_header *ovs_header = info->userhdr; |
| 1098 | struct sw_flow_key key; | 1150 | struct sw_flow_key key; |
| 1099 | struct sw_flow *flow; | 1151 | struct sw_flow *flow; |
| 1100 | struct sw_flow_mask mask; | ||
| 1101 | struct sk_buff *reply = NULL; | 1152 | struct sk_buff *reply = NULL; |
| 1102 | struct datapath *dp; | 1153 | struct datapath *dp; |
| 1103 | struct sw_flow_actions *old_acts = NULL, *acts = NULL; | 1154 | struct sw_flow_actions *old_acts = NULL, *acts = NULL; |
| @@ -1109,34 +1160,18 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info) | |||
| 1109 | bool ufid_present; | 1160 | bool ufid_present; |
| 1110 | 1161 | ||
| 1111 | ufid_present = ovs_nla_get_ufid(&sfid, a[OVS_FLOW_ATTR_UFID], log); | 1162 | ufid_present = ovs_nla_get_ufid(&sfid, a[OVS_FLOW_ATTR_UFID], log); |
| 1112 | if (a[OVS_FLOW_ATTR_KEY]) { | 1163 | if (!a[OVS_FLOW_ATTR_KEY] && !ufid_present) { |
| 1113 | ovs_match_init(&match, &key, true, &mask); | ||
| 1114 | error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY], | ||
| 1115 | a[OVS_FLOW_ATTR_MASK], log); | ||
| 1116 | } else if (!ufid_present) { | ||
| 1117 | OVS_NLERR(log, | 1164 | OVS_NLERR(log, |
| 1118 | "Flow set message rejected, Key attribute missing."); | 1165 | "Flow set message rejected, Key attribute missing."); |
| 1119 | error = -EINVAL; | 1166 | return -EINVAL; |
| 1120 | } | 1167 | } |
| 1168 | |||
| 1169 | error = ovs_nla_init_match_and_action(net, &match, &key, a, | ||
| 1170 | &acts, log); | ||
| 1121 | if (error) | 1171 | if (error) |
| 1122 | goto error; | 1172 | goto error; |
| 1123 | 1173 | ||
| 1124 | /* Validate actions. */ | 1174 | if (acts) { |
| 1125 | if (a[OVS_FLOW_ATTR_ACTIONS]) { | ||
| 1126 | if (!a[OVS_FLOW_ATTR_KEY]) { | ||
| 1127 | OVS_NLERR(log, | ||
| 1128 | "Flow key attribute not present in set flow."); | ||
| 1129 | error = -EINVAL; | ||
| 1130 | goto error; | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | acts = get_flow_actions(net, a[OVS_FLOW_ATTR_ACTIONS], &key, | ||
| 1134 | &mask, log); | ||
| 1135 | if (IS_ERR(acts)) { | ||
| 1136 | error = PTR_ERR(acts); | ||
| 1137 | goto error; | ||
| 1138 | } | ||
| 1139 | |||
| 1140 | /* Can allocate before locking if have acts. */ | 1175 | /* Can allocate before locking if have acts. */ |
| 1141 | reply = ovs_flow_cmd_alloc_info(acts, &sfid, info, false, | 1176 | reply = ovs_flow_cmd_alloc_info(acts, &sfid, info, false, |
| 1142 | ufid_flags); | 1177 | ufid_flags); |
