extern int seg6_local_init(void);
 extern void seg6_local_exit(void);
 
-extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len);
+extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len, bool reduced);
 extern int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh,
                             int proto);
 extern int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh);
 
        int err;
        struct ipv6_sr_hdr *srh = (struct ipv6_sr_hdr *)hdr;
 
-       if (!seg6_validate_srh(srh, len))
+       if (!seg6_validate_srh(srh, len, false))
                return -EINVAL;
 
        switch (type) {
 
                                struct ipv6_sr_hdr *srh = (struct ipv6_sr_hdr *)
                                                          opt->srcrt;
 
-                               if (!seg6_validate_srh(srh, optlen))
+                               if (!seg6_validate_srh(srh, optlen, false))
                                        goto sticky_done;
                                break;
                        }
 
 #include <net/seg6_hmac.h>
 #endif
 
-bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len)
+bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len, bool reduced)
 {
        unsigned int tlv_offset;
        int max_last_entry;
        if (((srh->hdrlen + 1) << 3) != len)
                return false;
 
-       max_last_entry = (srh->hdrlen / 2) - 1;
-
-       if (srh->first_segment > max_last_entry)
+       if (!reduced && srh->segments_left > srh->first_segment) {
                return false;
+       } else {
+               max_last_entry = (srh->hdrlen / 2) - 1;
 
-       if (srh->segments_left > srh->first_segment + 1)
-               return false;
+               if (srh->first_segment > max_last_entry)
+                       return false;
+
+               if (srh->segments_left > srh->first_segment + 1)
+                       return false;
+       }
 
        tlv_offset = sizeof(*srh) + ((srh->first_segment + 1) << 4);
 
 
        }
 
        /* verify that SRH is consistent */
-       if (!seg6_validate_srh(tuninfo->srh, tuninfo_len - sizeof(*tuninfo)))
+       if (!seg6_validate_srh(tuninfo->srh, tuninfo_len - sizeof(*tuninfo), false))
                return -EINVAL;
 
        newts = lwtunnel_state_alloc(tuninfo_len + sizeof(*slwt));
 
         */
        srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);
 
-       if (!seg6_validate_srh(srh, len))
+       if (!seg6_validate_srh(srh, len, true))
                return NULL;
 
        return srh;
                        return false;
 
                srh->hdrlen = (u8)(srh_state->hdrlen >> 3);
-               if (!seg6_validate_srh(srh, (srh->hdrlen + 1) << 3))
+               if (!seg6_validate_srh(srh, (srh->hdrlen + 1) << 3, true))
                        return false;
 
                srh_state->valid = true;
        if (len < sizeof(*srh) + sizeof(struct in6_addr))
                return -EINVAL;
 
-       if (!seg6_validate_srh(srh, len))
+       if (!seg6_validate_srh(srh, len, false))
                return -EINVAL;
 
        slwt->srh = kmemdup(srh, len, GFP_KERNEL);