static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
{
- unsigned short frag_off;
- unsigned int payload_ofs = 0;
unsigned int nh_ofs = skb_network_offset(skb);
unsigned int nh_len;
+ int payload_ofs;
struct ipv6hdr *nh;
- int err, nexthdr, flags = 0;
+ uint8_t nexthdr;
+ __be16 frag_off;
+ int err;
err = check_header(skb, nh_ofs + sizeof(*nh));
if (unlikely(err))
return err;
nh = ipv6_hdr(skb);
+ nexthdr = nh->nexthdr;
+ payload_ofs = (u8 *)(nh + 1) - skb->data;
key->ip.proto = NEXTHDR_NONE;
key->ip.tos = ipv6_get_dsfield(nh);
key->ipv6.addr.src = nh->saddr;
key->ipv6.addr.dst = nh->daddr;
- nexthdr = ipv6_find_hdr(skb, &payload_ofs, -1, &frag_off, &flags);
- if (flags & IP6_FH_F_FRAG) {
- if (frag_off)
+ payload_ofs = ipv6_skip_exthdr(skb, payload_ofs, &nexthdr, &frag_off);
+
+ if (frag_off) {
+ if (frag_off & htons(~0x7))
key->ip.frag = OVS_FRAG_TYPE_LATER;
else
key->ip.frag = OVS_FRAG_TYPE_FIRST;
key->ip.frag = OVS_FRAG_TYPE_NONE;
}
- /* Delayed handling of error in ipv6_find_hdr() as it
- * always sets flags and frag_off to a valid value which may be
+ /* Delayed handling of error in ipv6_skip_exthdr() as it
+ * always sets frag_off to a valid value which may be
* used to set key->ip.frag above.
*/
- if (unlikely(nexthdr < 0))
+ if (unlikely(payload_ofs < 0))
return -EPROTO;
nh_len = payload_ofs - nh_ofs;