[ovs-dev] [netlink 09/16] datapath: Always use GFP_ATOMIC to execute actions.

Ben Pfaff blp at nicira.com
Fri Sep 10 22:55:09 UTC 2010


These functions run 99% of the time in atomic context and the benefit of
passing along the 'gfp' argument for the other 1% doesn't seem to outweigh
the cost.

Suggested-by: Stephen Hemminger <shemminger at vyatta.com>
Signed-off-by: Ben Pfaff <blp at nicira.com>
---
 datapath/actions.c  |   65 ++++++++++++++++++++++----------------------------
 datapath/actions.h  |    4 +--
 datapath/datapath.c |    5 +--
 datapath/flow.h     |    1 -
 4 files changed, 32 insertions(+), 43 deletions(-)

diff --git a/datapath/actions.c b/datapath/actions.c
index 961a0dc..5ec7061 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -25,13 +25,13 @@
 #include "openvswitch/datapath-protocol.h"
 #include "vport.h"
 
-static struct sk_buff *make_writable(struct sk_buff *skb, unsigned min_headroom, gfp_t gfp)
+static struct sk_buff *make_writable(struct sk_buff *skb, unsigned min_headroom)
 {
 	if (skb_cloned(skb)) {
 		struct sk_buff *nskb;
 		unsigned headroom = max(min_headroom, skb_headroom(skb));
 
-		nskb = skb_copy_expand(skb, headroom, skb_tailroom(skb), gfp);
+		nskb = skb_copy_expand(skb, headroom, skb_tailroom(skb), GFP_ATOMIC);
 		if (nskb) {
 			set_skb_csum_bits(skb, nskb);
 			kfree_skb(skb);
@@ -72,13 +72,12 @@ static struct sk_buff *vlan_pull_tag(struct sk_buff *skb)
 
 static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb,
 				       const struct odp_flow_key *key,
-				       const union odp_action *a, int n_actions,
-				       gfp_t gfp)
+				       const union odp_action *a, int n_actions)
 {
 	__be16 mask = a->dl_tci.mask;
 	__be16 tci = a->dl_tci.tci;
 
-	skb = make_writable(skb, VLAN_HLEN, gfp);
+	skb = make_writable(skb, VLAN_HLEN);
 	if (!skb)
 		return ERR_PTR(-ENOMEM);
 
@@ -154,8 +153,7 @@ static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb,
 				if (segs) {
 					err = execute_actions(dp, segs,
 							      key, a + 1,
-							      n_actions - 1,
-							      gfp);
+							      n_actions - 1);
 				}
 
 				if (unlikely(err)) {
@@ -193,19 +191,18 @@ static struct sk_buff *modify_vlan_tci(struct datapath *dp, struct sk_buff *skb,
 	return skb;
 }
 
-static struct sk_buff *strip_vlan(struct sk_buff *skb, gfp_t gfp)
+static struct sk_buff *strip_vlan(struct sk_buff *skb)
 {
-	skb = make_writable(skb, 0, gfp);
+	skb = make_writable(skb, 0);
 	if (skb)
 		vlan_pull_tag(skb);
 	return skb;
 }
 
 static struct sk_buff *set_dl_addr(struct sk_buff *skb,
-				   const struct odp_action_dl_addr *a,
-				   gfp_t gfp)
+				   const struct odp_action_dl_addr *a)
 {
-	skb = make_writable(skb, 0, gfp);
+	skb = make_writable(skb, 0);
 	if (skb) {
 		struct ethhdr *eh = eth_hdr(skb);
 		if (a->type == ODPAT_SET_DL_SRC)
@@ -257,8 +254,7 @@ static __sum16 *get_l4_checksum(struct sk_buff *skb, const struct odp_flow_key *
 
 static struct sk_buff *set_nw_addr(struct sk_buff *skb,
 				   const struct odp_flow_key *key,
-				   const struct odp_action_nw_addr *a,
-				   gfp_t gfp)
+				   const struct odp_action_nw_addr *a)
 {
 	struct iphdr *nh;
 	__sum16 *check;
@@ -267,7 +263,7 @@ static struct sk_buff *set_nw_addr(struct sk_buff *skb,
 	if (unlikely(!is_ip(skb, key)))
 		return skb;
 
-	skb = make_writable(skb, 0, gfp);
+	skb = make_writable(skb, 0);
 	if (unlikely(!skb))
 		return NULL;
 
@@ -286,13 +282,12 @@ static struct sk_buff *set_nw_addr(struct sk_buff *skb,
 
 static struct sk_buff *set_nw_tos(struct sk_buff *skb,
 				   const struct odp_flow_key *key,
-				   const struct odp_action_nw_tos *a,
-				   gfp_t gfp)
+				   const struct odp_action_nw_tos *a)
 {
 	if (unlikely(!is_ip(skb, key)))
 		return skb;
 
-	skb = make_writable(skb, 0, gfp);
+	skb = make_writable(skb, 0);
 	if (skb) {
 		struct iphdr *nh = ip_hdr(skb);
 		u8 *f = &nh->tos;
@@ -310,7 +305,7 @@ static struct sk_buff *set_nw_tos(struct sk_buff *skb,
 
 static struct sk_buff *set_tp_port(struct sk_buff *skb,
 				   const struct odp_flow_key *key,
-				   const struct odp_action_tp_port *a, gfp_t gfp)
+				   const struct odp_action_tp_port *a)
 {
 	struct udphdr *th;
 	__sum16 *check;
@@ -319,7 +314,7 @@ static struct sk_buff *set_tp_port(struct sk_buff *skb,
 	if (unlikely(!is_ip(skb, key)))
 		return skb;
 
-	skb = make_writable(skb, 0, gfp);
+	skb = make_writable(skb, 0);
 	if (unlikely(!skb))
 		return NULL;
 
@@ -390,10 +385,9 @@ error:
 	kfree_skb(skb);
 }
 
-static int output_control(struct datapath *dp, struct sk_buff *skb, u32 arg,
-			  gfp_t gfp)
+static int output_control(struct datapath *dp, struct sk_buff *skb, u32 arg)
 {
-	skb = skb_clone(skb, gfp);
+	skb = skb_clone(skb, GFP_ATOMIC);
 	if (!skb)
 		return -ENOMEM;
 	return dp_output_control(dp, skb, _ODPL_ACTION_NR, arg);
@@ -403,14 +397,14 @@ static int output_control(struct datapath *dp, struct sk_buff *skb, u32 arg,
  * information about what happened to it. */
 static void sflow_sample(struct datapath *dp, struct sk_buff *skb,
 			 const union odp_action *a, int n_actions,
-			 gfp_t gfp, struct vport *vport)
+			 struct vport *vport)
 {
 	struct odp_sflow_sample_header *hdr;
 	unsigned int actlen = n_actions * sizeof(union odp_action);
 	unsigned int hdrlen = sizeof(struct odp_sflow_sample_header);
 	struct sk_buff *nskb;
 
-	nskb = skb_copy_expand(skb, actlen + hdrlen, 0, gfp);
+	nskb = skb_copy_expand(skb, actlen + hdrlen, 0, GFP_ATOMIC);
 	if (!nskb)
 		return;
 
@@ -424,8 +418,7 @@ static void sflow_sample(struct datapath *dp, struct sk_buff *skb,
 /* Execute a list of actions against 'skb'. */
 int execute_actions(struct datapath *dp, struct sk_buff *skb,
 		    const struct odp_flow_key *key,
-		    const union odp_action *a, int n_actions,
-		    gfp_t gfp)
+		    const union odp_action *a, int n_actions)
 {
 	/* Every output action needs a separate clone of 'skb', but the common
 	 * case is just a single output action, so that doing a clone and
@@ -441,7 +434,7 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb,
 			atomic_inc(&p->sflow_pool);
 			if (dp->sflow_probability == UINT_MAX ||
 			    net_random() < dp->sflow_probability)
-				sflow_sample(dp, skb, a, n_actions, gfp, p);
+				sflow_sample(dp, skb, a, n_actions, p);
 		}
 	}
 
@@ -449,7 +442,7 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb,
 
 	for (; n_actions > 0; a++, n_actions--) {
 		if (prev_port != -1) {
-			do_output(dp, skb_clone(skb, gfp), prev_port);
+			do_output(dp, skb_clone(skb, GFP_ATOMIC), prev_port);
 			prev_port = -1;
 		}
 
@@ -459,7 +452,7 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb,
 			break;
 
 		case ODPAT_CONTROLLER:
-			err = output_control(dp, skb, a->controller.arg, gfp);
+			err = output_control(dp, skb, a->controller.arg);
 			if (err) {
 				kfree_skb(skb);
 				return err;
@@ -471,32 +464,32 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb,
 			break;
 
 		case ODPAT_SET_DL_TCI:
-			skb = modify_vlan_tci(dp, skb, key, a, n_actions, gfp);
+			skb = modify_vlan_tci(dp, skb, key, a, n_actions);
 			if (IS_ERR(skb))
 				return PTR_ERR(skb);
 			break;
 
 		case ODPAT_STRIP_VLAN:
-			skb = strip_vlan(skb, gfp);
+			skb = strip_vlan(skb);
 			break;
 
 		case ODPAT_SET_DL_SRC:
 		case ODPAT_SET_DL_DST:
-			skb = set_dl_addr(skb, &a->dl_addr, gfp);
+			skb = set_dl_addr(skb, &a->dl_addr);
 			break;
 
 		case ODPAT_SET_NW_SRC:
 		case ODPAT_SET_NW_DST:
-			skb = set_nw_addr(skb, key, &a->nw_addr, gfp);
+			skb = set_nw_addr(skb, key, &a->nw_addr);
 			break;
 
 		case ODPAT_SET_NW_TOS:
-			skb = set_nw_tos(skb, key, &a->nw_tos, gfp);
+			skb = set_nw_tos(skb, key, &a->nw_tos);
 			break;
 
 		case ODPAT_SET_TP_SRC:
 		case ODPAT_SET_TP_DST:
-			skb = set_tp_port(skb, key, &a->tp_port, gfp);
+			skb = set_tp_port(skb, key, &a->tp_port);
 			break;
 
 		case ODPAT_SET_PRIORITY:
diff --git a/datapath/actions.h b/datapath/actions.h
index da4f4bf..f2962a7 100644
--- a/datapath/actions.h
+++ b/datapath/actions.h
@@ -9,7 +9,6 @@
 #ifndef ACTIONS_H
 #define ACTIONS_H 1
 
-#include <linux/gfp.h>
 #include <linux/skbuff.h>
 #include <linux/version.h>
 
@@ -20,8 +19,7 @@ union odp_action;
 
 int execute_actions(struct datapath *dp, struct sk_buff *skb,
 		    const struct odp_flow_key *key,
-		    const union odp_action *, int n_actions,
-		    gfp_t gfp);
+		    const union odp_action *, int n_actions);
 
 static inline void set_skb_csum_bits(const struct sk_buff *old_skb,
 				     struct sk_buff *new_skb)
diff --git a/datapath/datapath.c b/datapath/datapath.c
index 066308a..f0c6833 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -545,7 +545,7 @@ void dp_process_received_packet(struct vport *p, struct sk_buff *skb)
 	}
 
 	/* Execute actions. */
-	execute_actions(dp, skb, &key, acts->actions, acts->n_actions, GFP_ATOMIC);
+	execute_actions(dp, skb, &key, acts->actions, acts->n_actions);
 	stats_counter_off = offsetof(struct dp_stats_percpu, n_hit);
 
 	/* Check whether sub-actions looped too much. */
@@ -1329,8 +1329,7 @@ static int do_execute(struct datapath *dp, const struct odp_execute *execute)
 		goto error_free_skb;
 
 	rcu_read_lock();
-	err = execute_actions(dp, skb, &key, actions->actions,
-			      actions->n_actions, GFP_KERNEL);
+	err = execute_actions(dp, skb, &key, actions->actions, actions->n_actions);
 	rcu_read_unlock();
 
 	kfree(actions);
diff --git a/datapath/flow.h b/datapath/flow.h
index 80a5b66..a4f116e 100644
--- a/datapath/flow.h
+++ b/datapath/flow.h
@@ -13,7 +13,6 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/rcupdate.h>
-#include <linux/gfp.h>
 #include <linux/if_ether.h>
 #include <linux/jiffies.h>
 #include <linux/time.h>
-- 
1.7.1





More information about the dev mailing list