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> --- datapath/datapath.c | 2 +- lib/flow.c | 50 ++++++++++++++++++++++++++++++-------------------- lib/flow.h | 1 + 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index 17d5cb5..bc740b4 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 1424e39..9a86c7d 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -368,7 +368,6 @@ flow_extract(struct ofpbuf *packet, uint32_t skb_priority, uint32_t skb_mark, { struct ofpbuf b = *packet; struct eth_header *eth; - ovs_be16 dl_type; COVERAGE_INC(flow_extract); @@ -402,35 +401,46 @@ flow_extract(struct ofpbuf *packet, uint32_t skb_priority, uint32_t skb_mark, if (eth->eth_type == htons(ETH_TYPE_VLAN)) { parse_vlan(&b, flow); } - dl_type = flow->dl_type = parse_ethertype(&b); + flow->dl_type = parse_ethertype(&b); /* Parse mpls, copy l3 ttl. */ - if (dl_type == htons(ETH_TYPE_MPLS) || - dl_type == htons(ETH_TYPE_MPLS_MCAST)) { - struct ip_header *ih; - struct ip6_hdr *ih6; - + if (flow->dl_type == htons(ETH_TYPE_MPLS) || + flow->dl_type == htons(ETH_TYPE_MPLS_MCAST)) { packet->l2_5 = b.data; parse_mpls(&b, flow); if (!(flow->mpls_lse & htonl(MPLS_BOS_MASK))) { parse_remaining_mpls(&b, flow); } - - ih = b.data; - ih6 = b.data; - if (packet->size >= sizeof *ih && - IP_VER(ih->ip_ihl_ver) == IP_VERSION) { - flow->nw_ttl = ih->ip_ttl; - dl_type = htons(ETH_TYPE_IP); - } else if (packet->size >= sizeof *ih6 && - IP6_VER(ih6->ip6_vfc) == IP6_VERSION) { - flow->nw_ttl = ih6->ip6_hlim; - dl_type = htons(ETH_TYPE_IPV6); - } } - /* Network layer. */ packet->l3 = b.data; + flow_extract_l3_onwards(packet, flow); +} + +/* 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) +{ + struct ofpbuf b; + ovs_be16 dl_type = flow->encap_dl_type + ? flow->encap_dl_type + : flow->dl_type; + + 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) { diff --git a/lib/flow.h b/lib/flow.h index 4e4a03c..c048c2c 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -127,6 +127,7 @@ 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 *); 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