From 769f8ccd5fe0cbfbf85fb41c42e6c164e21352be Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 12 Aug 2010 15:12:28 -0700 Subject: [PATCH] datapath: Free up flow_extract() return value for reporting errors. 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 --- 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 32572c6f9..e8b2976e0 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 fd81dfbad..abc6aeab2 100644 --- a/datapath/datapath.h +++ b/datapath/datapath.h @@ -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) diff --git a/datapath/flow.c b/datapath/flow.c index 7b1f23bdb..5e362e300 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) -- 2.43.0