Currently, OVS only parses the IP protocol number for the first
IPv6 fragment, but sets the IP protocol number for the later fragments
to be NEXTHDF_FRAGMENT.  This patch tries to derive the IP protocol
number for the IPV6 later frags so that we can match that.

Signed-off-by: Yi-Hung Wei <yihung....@gmail.com>
---
 net/openvswitch/flow.c | 22 +++++++++-------------
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 56b8e7167790..35966da84769 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -254,21 +254,18 @@ static bool icmphdr_ok(struct sk_buff *skb)
 
 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;
-       uint8_t nexthdr;
-       __be16 frag_off;
-       int err;
+       int err, nexthdr, flags = 0;
 
        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);
@@ -277,10 +274,9 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct 
sw_flow_key *key)
        key->ipv6.addr.src = nh->saddr;
        key->ipv6.addr.dst = nh->daddr;
 
-       payload_ofs = ipv6_skip_exthdr(skb, payload_ofs, &nexthdr, &frag_off);
-
-       if (frag_off) {
-               if (frag_off & htons(~0x7))
+       nexthdr = ipv6_find_hdr(skb, &payload_ofs, -1, &frag_off, &flags);
+       if (flags & IP6_FH_F_FRAG) {
+               if (frag_off)
                        key->ip.frag = OVS_FRAG_TYPE_LATER;
                else
                        key->ip.frag = OVS_FRAG_TYPE_FIRST;
@@ -288,11 +284,11 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct 
sw_flow_key *key)
                key->ip.frag = OVS_FRAG_TYPE_NONE;
        }
 
-       /* Delayed handling of error in ipv6_skip_exthdr() as it
-        * always sets frag_off to a valid value which may be
+       /* Delayed handling of error in ipv6_find_hdr() as it
+        * always sets flags and frag_off to a valid value which may be
         * used to set key->ip.frag above.
         */
-       if (unlikely(payload_ofs < 0))
+       if (unlikely(nexthdr < 0))
                return -EPROTO;
 
        nh_len = payload_ofs - nh_ofs;
-- 
2.7.4

Reply via email to