summaryrefslogtreecommitdiffstats
path: root/net/openvswitch/actions.c
diff options
context:
space:
mode:
authorAndy Zhou <azhou@nicira.com>2014-09-16 04:33:50 +0200
committerPravin B Shelar <pshelar@nicira.com>2014-09-16 08:28:14 +0200
commit32ae87ff795781b7ceffc44b7c694c1bb206a266 (patch)
treeca16360b437e13d4f8cf0c2440181fbffbc9cc71 /net/openvswitch/actions.c
parentopenvswitch: Use tun_key only for egress tunnel path. (diff)
downloadlinux-32ae87ff795781b7ceffc44b7c694c1bb206a266.tar.xz
linux-32ae87ff795781b7ceffc44b7c694c1bb206a266.zip
openvswitch: simplify sample action implementation
The current sample() function implementation is more complicated than necessary in handling single user space action optimization and skb reference counting. There is no functional changes. Signed-off-by: Andy Zhou <azhou@nicira.com> Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Diffstat (limited to 'net/openvswitch/actions.c')
-rw-r--r--net/openvswitch/actions.c42
1 files changed, 18 insertions, 24 deletions
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 1cdb539d05bd..c31bb80c984f 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -448,7 +448,6 @@ static int sample(struct datapath *dp, struct sk_buff *skb,
{
const struct nlattr *acts_list = NULL;
const struct nlattr *a;
- struct sk_buff *sample_skb;
int rem;
for (a = nla_data(attr), rem = nla_len(attr); rem > 0;
@@ -468,31 +467,26 @@ static int sample(struct datapath *dp, struct sk_buff *skb,
rem = nla_len(acts_list);
a = nla_data(acts_list);
- /* Actions list is either empty or only contains a single user-space
- * action, the latter being a special case as it is the only known
- * usage of the sample action.
- * In these special cases don't clone the skb as there are no
- * side-effects in the nested actions.
- * Otherwise, clone in case the nested actions have side effects.
- */
- if (likely(rem == 0 || (nla_type(a) == OVS_ACTION_ATTR_USERSPACE &&
- last_action(a, rem)))) {
- sample_skb = skb;
- skb_get(skb);
- } else {
- sample_skb = skb_clone(skb, GFP_ATOMIC);
- if (!sample_skb) /* Skip sample action when out of memory. */
- return 0;
- }
+ /* Actions list is empty, do nothing */
+ if (unlikely(!rem))
+ return 0;
- /* Note that do_execute_actions() never consumes skb.
- * In the case where skb has been cloned above it is the clone that
- * is consumed. Otherwise the skb_get(skb) call prevents
- * consumption by do_execute_actions(). Thus, it is safe to simply
- * return the error code and let the caller (also
- * do_execute_actions()) free skb on error.
+ /* The only known usage of sample action is having a single user-space
+ * action. Treat this usage as a special case.
+ * The output_userspace() should clone the skb to be sent to the
+ * user space. This skb will be consumed by its caller.
*/
- return do_execute_actions(dp, sample_skb, key, a, rem);
+ if (likely(nla_type(a) == OVS_ACTION_ATTR_USERSPACE &&
+ last_action(a, rem)))
+ return output_userspace(dp, skb, key, a);
+
+ skb = skb_clone(skb, GFP_ATOMIC);
+ if (!skb)
+ /* Skip the sample action when out of memory. */
+ return 0;
+
+ /* do_execute_actions() will consume the cloned skb. */
+ return do_execute_actions(dp, skb, key, a, rem);
}
static int execute_set_action(struct sk_buff *skb,