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. */
* 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)
*
* 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;
}
}
} 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;
} else {
skb_reset_transport_header(skb);
}
- return retval;
+ return 0;
}
u32 flow_hash(const struct odp_flow_key *key)