print_bool_feature(feat_name, plain_desc, res);
 }
 
+static void probe_map_type(enum bpf_map_type map_type)
+{
+       const char *plain_comment = "eBPF map_type ";
+       char feat_name[128], plain_desc[128];
+       size_t maxlen;
+       bool res;
+
+       res = bpf_probe_map_type(map_type, 0);
+
+       maxlen = sizeof(plain_desc) - strlen(plain_comment) - 1;
+       if (strlen(map_type_name[map_type]) > maxlen) {
+               p_info("map type name too long");
+               return;
+       }
+
+       sprintf(feat_name, "have_%s_map_type", map_type_name[map_type]);
+       sprintf(plain_desc, "%s%s", plain_comment, map_type_name[map_type]);
+       print_bool_feature(feat_name, plain_desc, res);
+}
+
 static int do_probe(int argc, char **argv)
 {
        enum probe_component target = COMPONENT_UNSPEC;
        for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++)
                probe_prog_type(i, supported_types);
 
+       print_end_then_start_section("map_types",
+                                    "Scanning eBPF map types...");
+
+       for (i = BPF_MAP_TYPE_UNSPEC + 1; i < map_type_name_size; i++)
+               probe_map_type(i);
+
 exit_close_json:
        if (json_output) {
                /* End current "section" of probes */
 
 #include "json_writer.h"
 #include "main.h"
 
-static const char * const map_type_name[] = {
+const char * const map_type_name[] = {
        [BPF_MAP_TYPE_UNSPEC]                   = "unspec",
        [BPF_MAP_TYPE_HASH]                     = "hash",
        [BPF_MAP_TYPE_ARRAY]                    = "array",
        [BPF_MAP_TYPE_STACK]                    = "stack",
 };
 
+const size_t map_type_name_size = ARRAY_SIZE(map_type_name);
+
 static bool map_is_per_cpu(__u32 type)
 {
        return type == BPF_MAP_TYPE_PERCPU_HASH ||
 
 
        return errno != EINVAL && errno != EOPNOTSUPP;
 }
+
+bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
+{
+       int key_size, value_size, max_entries, map_flags;
+       struct bpf_create_map_attr attr = {};
+       int fd = -1, fd_inner;
+
+       key_size        = sizeof(__u32);
+       value_size      = sizeof(__u32);
+       max_entries     = 1;
+       map_flags       = 0;
+
+       switch (map_type) {
+       case BPF_MAP_TYPE_STACK_TRACE:
+               value_size      = sizeof(__u64);
+               break;
+       case BPF_MAP_TYPE_LPM_TRIE:
+               key_size        = sizeof(__u64);
+               value_size      = sizeof(__u64);
+               map_flags       = BPF_F_NO_PREALLOC;
+               break;
+       case BPF_MAP_TYPE_CGROUP_STORAGE:
+       case BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE:
+               key_size        = sizeof(struct bpf_cgroup_storage_key);
+               value_size      = sizeof(__u64);
+               max_entries     = 0;
+               break;
+       case BPF_MAP_TYPE_QUEUE:
+       case BPF_MAP_TYPE_STACK:
+               key_size        = 0;
+               break;
+       case BPF_MAP_TYPE_UNSPEC:
+       case BPF_MAP_TYPE_HASH:
+       case BPF_MAP_TYPE_ARRAY:
+       case BPF_MAP_TYPE_PROG_ARRAY:
+       case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
+       case BPF_MAP_TYPE_PERCPU_HASH:
+       case BPF_MAP_TYPE_PERCPU_ARRAY:
+       case BPF_MAP_TYPE_CGROUP_ARRAY:
+       case BPF_MAP_TYPE_LRU_HASH:
+       case BPF_MAP_TYPE_LRU_PERCPU_HASH:
+       case BPF_MAP_TYPE_ARRAY_OF_MAPS:
+       case BPF_MAP_TYPE_HASH_OF_MAPS:
+       case BPF_MAP_TYPE_DEVMAP:
+       case BPF_MAP_TYPE_SOCKMAP:
+       case BPF_MAP_TYPE_CPUMAP:
+       case BPF_MAP_TYPE_XSKMAP:
+       case BPF_MAP_TYPE_SOCKHASH:
+       case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY:
+       default:
+               break;
+       }
+
+       if (map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
+           map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
+               /* TODO: probe for device, once libbpf has a function to create
+                * map-in-map for offload
+                */
+               if (ifindex)
+                       return false;
+
+               fd_inner = bpf_create_map(BPF_MAP_TYPE_HASH,
+                                         sizeof(__u32), sizeof(__u32), 1, 0);
+               if (fd_inner < 0)
+                       return false;
+               fd = bpf_create_map_in_map(map_type, NULL, sizeof(__u32),
+                                          fd_inner, 1, 0);
+               close(fd_inner);
+       } else {
+               /* Note: No other restriction on map type probes for offload */
+               attr.map_type = map_type;
+               attr.key_size = key_size;
+               attr.value_size = value_size;
+               attr.max_entries = max_entries;
+               attr.map_flags = map_flags;
+               attr.map_ifindex = ifindex;
+
+               fd = bpf_create_map_xattr(&attr);
+       }
+       if (fd >= 0)
+               close(fd);
+
+       return fd >= 0;
+}