struct flow_dissector_key_vlan *flow_vlan;
        u16 tmp_tci;
 
+       memset(frame, 0, sizeof(struct nfp_flower_meta_two));
        /* Populate the metadata frame. */
        frame->nfp_flow_key_layer = key_type;
        frame->mask_id = ~0;
                return;
        }
 
-       flow_vlan = skb_flow_dissector_target(flow->dissector,
-                                             FLOW_DISSECTOR_KEY_VLAN,
-                                             flow->key);
-
-       /* Populate the tci field. */
-       if (!flow_vlan->vlan_id) {
-               tmp_tci = 0;
-       } else {
-               tmp_tci = FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO,
-                                    flow_vlan->vlan_priority) |
-                         FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID,
-                                    flow_vlan->vlan_id) |
-                         NFP_FLOWER_MASK_VLAN_CFI;
+       if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
+               flow_vlan = skb_flow_dissector_target(flow->dissector,
+                                                     FLOW_DISSECTOR_KEY_VLAN,
+                                                     flow->key);
+               /* Populate the tci field. */
+               if (flow_vlan->vlan_id) {
+                       tmp_tci = FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO,
+                                            flow_vlan->vlan_priority) |
+                                 FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID,
+                                            flow_vlan->vlan_id) |
+                                 NFP_FLOWER_MASK_VLAN_CFI;
+                       frame->tci = cpu_to_be16(tmp_tci);
+               }
        }
-       frame->tci = cpu_to_be16(tmp_tci);
 }
 
 static void
                       bool mask_version)
 {
        struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
-       struct flow_dissector_key_eth_addrs *flow_mac;
-
-       flow_mac = skb_flow_dissector_target(flow->dissector,
-                                            FLOW_DISSECTOR_KEY_ETH_ADDRS,
-                                            target);
+       struct flow_dissector_key_eth_addrs *addr;
 
        memset(frame, 0, sizeof(struct nfp_flower_mac_mpls));
 
-       /* Populate mac frame. */
-       ether_addr_copy(frame->mac_dst, &flow_mac->dst[0]);
-       ether_addr_copy(frame->mac_src, &flow_mac->src[0]);
+       if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
+               addr = skb_flow_dissector_target(flow->dissector,
+                                                FLOW_DISSECTOR_KEY_ETH_ADDRS,
+                                                target);
+               /* Populate mac frame. */
+               ether_addr_copy(frame->mac_dst, &addr->dst[0]);
+               ether_addr_copy(frame->mac_src, &addr->src[0]);
+       }
 
        if (mask_version)
                frame->mpls_lse = cpu_to_be32(~0);
                         bool mask_version)
 {
        struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
-       struct flow_dissector_key_ports *flow_tp;
+       struct flow_dissector_key_ports *tp;
 
-       flow_tp = skb_flow_dissector_target(flow->dissector,
-                                           FLOW_DISSECTOR_KEY_PORTS,
-                                           target);
+       memset(frame, 0, sizeof(struct nfp_flower_tp_ports));
 
-       frame->port_src = flow_tp->src;
-       frame->port_dst = flow_tp->dst;
+       if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
+               tp = skb_flow_dissector_target(flow->dissector,
+                                              FLOW_DISSECTOR_KEY_PORTS,
+                                              target);
+               frame->port_src = tp->src;
+               frame->port_dst = tp->dst;
+       }
 }
 
 static void
                        bool mask_version)
 {
        struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
-       struct flow_dissector_key_ipv4_addrs *flow_ipv4;
-       struct flow_dissector_key_basic *flow_basic;
-
-       flow_ipv4 = skb_flow_dissector_target(flow->dissector,
-                                             FLOW_DISSECTOR_KEY_IPV4_ADDRS,
-                                             target);
+       struct flow_dissector_key_ipv4_addrs *addr;
+       struct flow_dissector_key_basic *basic;
 
-       flow_basic = skb_flow_dissector_target(flow->dissector,
-                                              FLOW_DISSECTOR_KEY_BASIC,
-                                              target);
-
-       /* Populate IPv4 frame. */
-       frame->reserved = 0;
-       frame->ipv4_src = flow_ipv4->src;
-       frame->ipv4_dst = flow_ipv4->dst;
-       frame->proto = flow_basic->ip_proto;
        /* Wildcard TOS/TTL for now. */
-       frame->tos = 0;
-       frame->ttl = 0;
+       memset(frame, 0, sizeof(struct nfp_flower_ipv4));
+
+       if (dissector_uses_key(flow->dissector,
+                              FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
+               addr = skb_flow_dissector_target(flow->dissector,
+                                                FLOW_DISSECTOR_KEY_IPV4_ADDRS,
+                                                target);
+               frame->ipv4_src = addr->src;
+               frame->ipv4_dst = addr->dst;
+       }
+
+       if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
+               basic = skb_flow_dissector_target(flow->dissector,
+                                                 FLOW_DISSECTOR_KEY_BASIC,
+                                                 target);
+               frame->proto = basic->ip_proto;
+       }
 }
 
 static void
                        bool mask_version)
 {
        struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
-       struct flow_dissector_key_ipv6_addrs *flow_ipv6;
-       struct flow_dissector_key_basic *flow_basic;
-
-       flow_ipv6 = skb_flow_dissector_target(flow->dissector,
-                                             FLOW_DISSECTOR_KEY_IPV6_ADDRS,
-                                             target);
-
-       flow_basic = skb_flow_dissector_target(flow->dissector,
-                                              FLOW_DISSECTOR_KEY_BASIC,
-                                              target);
+       struct flow_dissector_key_ipv6_addrs *addr;
+       struct flow_dissector_key_basic *basic;
 
-       /* Populate IPv6 frame. */
-       frame->reserved = 0;
-       frame->ipv6_src = flow_ipv6->src;
-       frame->ipv6_dst = flow_ipv6->dst;
-       frame->proto = flow_basic->ip_proto;
        /* Wildcard LABEL/TOS/TTL for now. */
-       frame->ipv6_flow_label_exthdr = 0;
-       frame->tos = 0;
-       frame->ttl = 0;
+       memset(frame, 0, sizeof(struct nfp_flower_ipv6));
+
+       if (dissector_uses_key(flow->dissector,
+                              FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
+               addr = skb_flow_dissector_target(flow->dissector,
+                                                FLOW_DISSECTOR_KEY_IPV6_ADDRS,
+                                                target);
+               frame->ipv6_src = addr->src;
+               frame->ipv6_dst = addr->dst;
+       }
+
+       if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
+               basic = skb_flow_dissector_target(flow->dissector,
+                                                 FLOW_DISSECTOR_KEY_BASIC,
+                                                 target);
+               frame->proto = basic->ip_proto;
+       }
 }
 
 int nfp_flower_compile_flow_match(struct tc_cls_flower_offload *flow,
 
 nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls,
                                struct tc_cls_flower_offload *flow)
 {
-       struct flow_dissector_key_control *mask_enc_ctl;
-       struct flow_dissector_key_basic *mask_basic;
-       struct flow_dissector_key_basic *key_basic;
+       struct flow_dissector_key_basic *mask_basic = NULL;
+       struct flow_dissector_key_basic *key_basic = NULL;
        u32 key_layer_two;
        u8 key_layer;
        int key_size;
 
-       mask_enc_ctl = skb_flow_dissector_target(flow->dissector,
-                                                FLOW_DISSECTOR_KEY_ENC_CONTROL,
-                                                flow->mask);
+       if (dissector_uses_key(flow->dissector,
+                              FLOW_DISSECTOR_KEY_ENC_CONTROL)) {
+               struct flow_dissector_key_control *mask_enc_ctl =
+                       skb_flow_dissector_target(flow->dissector,
+                                                 FLOW_DISSECTOR_KEY_ENC_CONTROL,
+                                                 flow->mask);
+               /* We are expecting a tunnel. For now we ignore offloading. */
+               if (mask_enc_ctl->addr_type)
+                       return -EOPNOTSUPP;
+       }
+
+       if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
+               mask_basic = skb_flow_dissector_target(flow->dissector,
+                                                      FLOW_DISSECTOR_KEY_BASIC,
+                                                      flow->mask);
 
-       mask_basic = skb_flow_dissector_target(flow->dissector,
-                                              FLOW_DISSECTOR_KEY_BASIC,
-                                              flow->mask);
+               key_basic = skb_flow_dissector_target(flow->dissector,
+                                                     FLOW_DISSECTOR_KEY_BASIC,
+                                                     flow->key);
+       }
 
-       key_basic = skb_flow_dissector_target(flow->dissector,
-                                             FLOW_DISSECTOR_KEY_BASIC,
-                                             flow->key);
        key_layer_two = 0;
        key_layer = NFP_FLOWER_LAYER_PORT | NFP_FLOWER_LAYER_MAC;
        key_size = sizeof(struct nfp_flower_meta_one) +
                   sizeof(struct nfp_flower_in_port) +
                   sizeof(struct nfp_flower_mac_mpls);
 
-       /* We are expecting a tunnel. For now we ignore offloading. */
-       if (mask_enc_ctl->addr_type)
-               return -EOPNOTSUPP;
-
-       if (mask_basic->n_proto) {
+       if (mask_basic && mask_basic->n_proto) {
                /* Ethernet type is present in the key. */
                switch (key_basic->n_proto) {
                case cpu_to_be16(ETH_P_IP):
                }
        }
 
-       if (mask_basic->ip_proto) {
+       if (mask_basic && mask_basic->ip_proto) {
                /* Ethernet type is present in the key. */
                switch (key_basic->ip_proto) {
                case IPPROTO_TCP: