openvswitch: Derive IP protocol number for IPv6 later frags
authorYi-Hung Wei <yihung.wei@gmail.com>
Tue, 4 Sep 2018 22:33:41 +0000 (15:33 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 7 Sep 2018 04:47:49 +0000 (21:47 -0700)
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.wei@gmail.com>
Acked-by: Pravin B Shelar <pshelar@ovn.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/openvswitch/flow.c

index 56b8e7167790fe3f240cc5120889a67ba37c168d..35966da8476967cd072278d54a870733ca39c40e 100644 (file)
@@ -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;