Split the L3 and above portion of flow_extract() out into flow_extract_l3_onwards() and call flow_extract_l3_onwards() from flow_extract().
This is to allow re-extraction of l3 and higher information using flow->encap_dl_type which may be set using information contained in actions. Signed-off-by: Simon Horman <ho...@verge.net.au> --- v2.12 * Rebase * Add dl_type parameter to flow_extract_l3_onwards, allowing this patch to be applied independently of the rest of the MPLS patch-set. v2.11 * First post --- datapath/datapath.c | 2 +- lib/flow.c | 34 +++++++++++++++++++++++++++++----- lib/flow.h | 2 ++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index d902c16..101ee37 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -344,7 +344,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb) struct sw_flow *flow, *outer_flow = NULL; struct dp_stats_percpu *stats; u64 *stats_counter; - __be16 encap_eth_type; + __be16 encap_eth_type = 0; int error; stats = this_cpu_ptr(dp->stats_percpu); diff --git a/lib/flow.c b/lib/flow.c index ce9e6c6..a13519e 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -375,9 +375,33 @@ flow_extract(struct ofpbuf *packet, uint32_t skb_priority, uint32_t skb_mark, } 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; @@ -410,7 +434,7 @@ flow_extract(struct ofpbuf *packet, uint32_t skb_priority, uint32_t skb_mark, } } } - } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) { + } else if (dl_type == htons(ETH_TYPE_IPV6)) { if (parse_ipv6(&b, flow)) { return; } @@ -425,8 +449,8 @@ flow_extract(struct ofpbuf *packet, uint32_t skb_priority, uint32_t skb_mark, 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) diff --git a/lib/flow.h b/lib/flow.h index ca41439..8e79e62 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -123,6 +123,8 @@ struct flow_metadata { void flow_extract(struct ofpbuf *, uint32_t priority, uint32_t mark, const struct flow_tnl *, uint16_t in_port, struct flow *); +void flow_extract_l3_onwards(struct ofpbuf *, struct flow *, + ovs_be16 dl_type); void flow_zero_wildcards(struct flow *, const struct flow_wildcards *); void flow_get_metadata(const struct flow *, struct flow_metadata *); -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev