datapath: Free up flow_extract() return value for reporting errors.
authorBen Pfaff <blp@nicira.com>
Thu, 12 Aug 2010 22:12:28 +0000 (15:12 -0700)
committerBen Pfaff <blp@nicira.com>
Thu, 26 Aug 2010 16:15:42 +0000 (09:15 -0700)
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@nicira.com>
datapath/datapath.c
datapath/datapath.h
datapath/flow.c

index 32572c6..e8b2976 100644 (file)
@@ -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. */
index fd81dfb..abc6aea 100644 (file)
@@ -150,11 +150,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)
 
index 7b1f23b..5e362e3 100644 (file)
@@ -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)