}
flow->dl_type = parse_ethertype(&b);
- /* Network layer. */
packet->l3 = b.data;
- if (flow->dl_type == htons(ETH_TYPE_IP)) {
+ flow_extract_l3_onwards(packet, flow, flow->dl_type);
+}
+
+/* Initializes l3 and higher 'flow' members from 'packet'
+ *
+ * This should be called by or after flow_extract()
+ *
+ * Initializes 'packet' header pointers as follows:
+ *
+ * - packet->l4 to just past the IPv4 header, if one is present and has a
+ * correct length, and otherwise NULL.
+ *
+ * - packet->l7 to just past the TCP or UDP or ICMP header, if one is
+ * present and has a correct length, and otherwise NULL.
+ */
+void
+flow_extract_l3_onwards(struct ofpbuf *packet, struct flow *flow,
+ ovs_be16 dl_type)
+{
+ struct ofpbuf b;
+
+ ofpbuf_use_const(&b, packet->l3, packet->size -
+ (size_t)((char *)packet->l3 - (char *)packet->l2));
+
+ /* Network layer. */
+ if (dl_type == htons(ETH_TYPE_IP)) {
const struct ip_header *nh = pull_ip(&b);
if (nh) {
packet->l4 = b.data;
}
}
}
- } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
+ } else if (dl_type == htons(ETH_TYPE_IPV6)) {
if (parse_ipv6(&b, flow)) {
return;
}
packet->l7 = b.data;
}
}
- } else if (flow->dl_type == htons(ETH_TYPE_ARP) ||
- flow->dl_type == htons(ETH_TYPE_RARP)) {
+ } else if (dl_type == htons(ETH_TYPE_ARP) ||
+ dl_type == htons(ETH_TYPE_RARP)) {
const struct arp_eth_header *arp = pull_arp(&b);
if (arp && arp->ar_hrd == htons(1)
&& arp->ar_pro == htons(ETH_TYPE_IP)
struct match match;
match_wc_init(&match, flow);
- match_format(&match, ds, flow->skb_priority);
+ match_format(&match, ds, OFP_DEFAULT_PRIORITY);
}
void
uint32_t
flow_wildcards_hash(const struct flow_wildcards *wc, uint32_t basis)
{
- return flow_hash(&wc->masks, basis);;
+ return flow_hash(&wc->masks, basis);
}
/* Returns true if 'a' and 'b' represent the same wildcards, false if they are