#include <linux/socket.h>
 #include <linux/types.h>
 #include <linux/u64_stats_sync.h>
+#include <linux/bitops.h>
+
 #include <net/dsfield.h>
 #include <net/gro_cells.h>
 #include <net/inet_ecn.h>
 #define IP_TUNNEL_INFO_TX      0x01    /* represents tx tunnel parameters */
 #define IP_TUNNEL_INFO_IPV6    0x02    /* key contains IPv6 addresses */
 
+/* Maximum tunnel options length. */
+#define IP_TUNNEL_OPTS_MAX                                     \
+       GENMASK((FIELD_SIZEOF(struct ip_tunnel_info,            \
+                             options_len) * BITS_PER_BYTE) - 1, 0)
+
 struct ip_tunnel_info {
        struct ip_tunnel_key    key;
 #ifdef CONFIG_DST_CACHE
 
        .arg4_type      = ARG_ANYTHING,
 };
 
-#define BPF_TUNLEN_MAX 255
-
 static u64 bpf_skb_set_tunnel_opt(u64 r1, u64 r2, u64 size, u64 r4, u64 r5)
 {
        struct sk_buff *skb = (struct sk_buff *) (long) r1;
 
        if (unlikely(info != &md->u.tun_info || (size & (sizeof(u32) - 1))))
                return -EINVAL;
-       if (unlikely(size > BPF_TUNLEN_MAX))
+       if (unlikely(size > IP_TUNNEL_OPTS_MAX))
                return -ENOMEM;
 
        ip_tunnel_info_opts_set(info, from, size);
 bpf_get_skb_set_tunnel_proto(enum bpf_func_id which)
 {
        if (!md_dst) {
-               BUILD_BUG_ON(FIELD_SIZEOF(struct ip_tunnel_info,
-                                         options_len) != 1);
-
                /* Race is not possible, since it's called from verifier
                 * that is holding verifier mutex.
                 */
-               md_dst = metadata_dst_alloc_percpu(BPF_TUNLEN_MAX,
+               md_dst = metadata_dst_alloc_percpu(IP_TUNNEL_OPTS_MAX,
                                                   GFP_KERNEL);
                if (!md_dst)
                        return NULL;
 
 
 void __init ip_tunnel_core_init(void)
 {
+       /* If you land here, make sure whether increasing ip_tunnel_info's
+        * options_len is a reasonable choice with its usage in front ends
+        * (f.e., it's part of flow keys, etc).
+        */
+       BUILD_BUG_ON(IP_TUNNEL_OPTS_MAX != 255);
+
        lwtunnel_encap_add_ops(&ip_tun_lwt_ops, LWTUNNEL_ENCAP_IP);
        lwtunnel_encap_add_ops(&ip6_tun_lwt_ops, LWTUNNEL_ENCAP_IP6);
 }
 
        FIELD_SIZEOF(struct sw_flow_key, recirc_id))
 
 struct sw_flow_key {
-       u8 tun_opts[255];
+       u8 tun_opts[IP_TUNNEL_OPTS_MAX];
        u8 tun_opts_len;
        struct ip_tunnel_key tun_key;   /* Encapsulating tunnel key. */
        struct {