[ovs-dev] [runt-flows 4/8] datapath: Free up flow_extract() return value for reporting errors.

Ben Pfaff blp at nicira.com
Fri Aug 13 17:55:43 UTC 2010


flow_extract() can fail due to memory allocation errors in pskb_may_pull().
Currently it doesn't return those properly, instead just reporting a bogus
flow to the caller.  But its return value is currently in use for reporting
whether the packet was an IPv4 fragment.  This commit switches to reporting
that in the skb itself so that the return value can be reused to report
errors.

Signed-off-by: Ben Pfaff <blp at nicira.com>
---
 datapath/datapath.c |   11 +++++------
 datapath/datapath.h |    2 ++
 datapath/flow.c     |    9 +++++----
 3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/datapath/datapath.c b/datapath/datapath.c
index e468198..8bf394f 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -551,12 +551,11 @@ void dp_process_received_packet(struct dp_port *p, struct sk_buff *skb)
 	OVS_CB(skb)->dp_port = p;
 
 	/* Extract flow from 'skb' into 'key'. */
-	if (flow_extract(skb, p ? p->port_no : ODPP_NONE, &key)) {
-		if (dp->drop_frags) {
-			kfree_skb(skb);
-			stats_counter_off = offsetof(struct dp_stats_percpu, n_frags);
-			goto out;
-		}
+	flow_extract(skb, p ? p->port_no : ODPP_NONE, &key);
+	if (OVS_CB(skb)->is_frag && dp->drop_frags) {
+		kfree_skb(skb);
+		stats_counter_off = offsetof(struct dp_stats_percpu, n_frags);
+		goto out;
 	}
 
 	/* Look up flow. */
diff --git a/datapath/datapath.h b/datapath/datapath.h
index 8e27283..bbcc289 100644
--- a/datapath/datapath.h
+++ b/datapath/datapath.h
@@ -148,11 +148,13 @@ enum csum_type {
  * kernel versions.
  * @tun_id: ID (in network byte order) of the tunnel that encapsulated this
  * packet. It is 0 if the packet was not received on a tunnel.
+ * @is_frag: %true if this packet is an IPv4 fragment, %false otherwise.
  */
 struct ovs_skb_cb {
 	struct dp_port		*dp_port;
 	enum csum_type		ip_summed;
 	__be32			tun_id;
+	bool			is_frag;
 };
 #define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
 
diff --git a/datapath/flow.c b/datapath/flow.c
index 7b1f23b..5e362e3 100644
--- a/datapath/flow.c
+++ b/datapath/flow.c
@@ -228,17 +228,18 @@ static __be16 parse_ethertype(struct sk_buff *skb)
  *
  * The caller must ensure that skb->len >= ETH_HLEN.
  *
- * Returns 1 if @skb contains an IPv4 fragment, 0 otherwise.
+ * Sets OVS_CB(skb)->is_frag to %true if @skb is an IPv4 fragment, otherwise to
+ * %false.
  */
 int flow_extract(struct sk_buff *skb, u16 in_port, struct odp_flow_key *key)
 {
 	struct ethhdr *eth;
-	int retval = 0;
 
 	memset(key, 0, sizeof *key);
 	key->tun_id = OVS_CB(skb)->tun_id;
 	key->in_port = in_port;
 	key->dl_vlan = htons(ODP_VLAN_NONE);
+	OVS_CB(skb)->is_frag = false;
 
 	if (!pskb_may_pull(skb, min(skb->len, 64u)))
 		return 0;
@@ -308,7 +309,7 @@ int flow_extract(struct sk_buff *skb, u16 in_port, struct odp_flow_key *key)
 				}
 			}
 		} else {
-			retval = 1;
+			OVS_CB(skb)->is_frag = true;
 		}
 	} else if (key->dl_type == htons(ETH_P_ARP) && arphdr_ok(skb)) {
 		struct arp_eth_header *arp;
@@ -334,7 +335,7 @@ int flow_extract(struct sk_buff *skb, u16 in_port, struct odp_flow_key *key)
 	} else {
 		skb_reset_transport_header(skb);
 	}
-	return retval;
+	return 0;
 }
 
 u32 flow_hash(const struct odp_flow_key *key)
-- 
1.7.1





More information about the dev mailing list