struct kmem_cache *flow_cache;
static unsigned int hash_seed;
-struct arp_eth_header
-{
- __be16 ar_hrd; /* format of hardware address */
- __be16 ar_pro; /* format of protocol address */
- unsigned char ar_hln; /* length of hardware address */
- unsigned char ar_pln; /* length of protocol address */
- __be16 ar_op; /* ARP opcode (command) */
-
- /* Ethernet+IPv4 specific members. */
- unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
- unsigned char ar_sip[4]; /* sender IP address */
- unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
- unsigned char ar_tip[4]; /* target IP address */
-} __attribute__((packed));
-
-static inline int arphdr_ok(struct sk_buff *skb)
+static inline bool arphdr_ok(struct sk_buff *skb)
{
int nh_ofs = skb_network_offset(skb);
return pskb_may_pull(skb, nh_ofs + sizeof(struct arp_eth_header));
}
-static inline int iphdr_ok(struct sk_buff *skb)
+static inline bool iphdr_ok(struct sk_buff *skb)
{
int nh_ofs = skb_network_offset(skb);
if (skb->len >= nh_ofs + sizeof(struct iphdr)) {
return (ip_len >= sizeof(struct iphdr)
&& pskb_may_pull(skb, nh_ofs + ip_len));
}
- return 0;
+ return false;
}
-static inline int tcphdr_ok(struct sk_buff *skb)
+static inline bool tcphdr_ok(struct sk_buff *skb)
{
int th_ofs = skb_transport_offset(skb);
if (pskb_may_pull(skb, th_ofs + sizeof(struct tcphdr))) {
return (tcp_len >= sizeof(struct tcphdr)
&& skb->len >= th_ofs + tcp_len);
}
- return 0;
+ return false;
}
-static inline int udphdr_ok(struct sk_buff *skb)
+static inline bool udphdr_ok(struct sk_buff *skb)
{
int th_ofs = skb_transport_offset(skb);
return pskb_may_pull(skb, th_ofs + sizeof(struct udphdr));
}
-static inline int icmphdr_ok(struct sk_buff *skb)
+static inline bool icmphdr_ok(struct sk_buff *skb)
{
int th_ofs = skb_transport_offset(skb);
return pskb_may_pull(skb, th_ofs + sizeof(struct icmphdr));
return llc->ethertype;
}
-/* Parses the Ethernet frame in 'skb', which was received on 'in_port',
- * and initializes 'key' to match. Returns 1 if 'skb' contains an IP
- * fragment, 0 otherwise. */
+/**
+ * flow_extract - extracts a flow key from an Ethernet frame.
+ * @skb: sk_buff that contains the frame, with skb->data pointing to the
+ * Ethernet header
+ * @in_port: port number on which @skb was received.
+ * @key: output flow key
+ *
+ * The caller must ensure that skb->len >= ETH_HLEN.
+ *
+ * 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 (skb->len < sizeof *eth)
- return 0;
- if (!pskb_may_pull(skb, skb->len >= 64 ? 64 : skb->len))
+ if (!pskb_may_pull(skb, min(skb->len, 64u)))
return 0;
skb_reset_mac_header(skb);
}
}
} 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)