[NPC_DPORT_UDP] = "udp destination port",
        [NPC_SPORT_SCTP] = "sctp source port",
        [NPC_DPORT_SCTP] = "sctp destination port",
+       [NPC_LXMB]      = "Mcast/Bcast header ",
        [NPC_UNKNOWN]   = "unknown",
 };
 
        vlan_tag2 = &key_fields[NPC_VLAN_TAG2];
 
        /* if key profile programmed does not extract Ethertype at all */
-       if (!etype_ether->nr_kws && !etype_tag1->nr_kws && !etype_tag2->nr_kws)
+       if (!etype_ether->nr_kws && !etype_tag1->nr_kws && !etype_tag2->nr_kws) {
+               dev_err(rvu->dev, "mkex: Ethertype is not extracted.\n");
                goto vlan_tci;
+       }
 
        /* if key profile programmed extracts Ethertype from one layer */
        if (etype_ether->nr_kws && !etype_tag1->nr_kws && !etype_tag2->nr_kws)
        /* if key profile programmed extracts Ethertype from multiple layers */
        if (etype_ether->nr_kws && etype_tag1->nr_kws) {
                for (i = 0; i < NPC_MAX_KWS_IN_KEY; i++) {
-                       if (etype_ether->kw_mask[i] != etype_tag1->kw_mask[i])
+                       if (etype_ether->kw_mask[i] != etype_tag1->kw_mask[i]) {
+                               dev_err(rvu->dev, "mkex: Etype pos is different for untagged and tagged pkts.\n");
                                goto vlan_tci;
+                       }
                }
                key_fields[NPC_ETYPE] = *etype_tag1;
        }
        if (etype_ether->nr_kws && etype_tag2->nr_kws) {
                for (i = 0; i < NPC_MAX_KWS_IN_KEY; i++) {
-                       if (etype_ether->kw_mask[i] != etype_tag2->kw_mask[i])
+                       if (etype_ether->kw_mask[i] != etype_tag2->kw_mask[i]) {
+                               dev_err(rvu->dev, "mkex: Etype pos is different for untagged and double tagged pkts.\n");
                                goto vlan_tci;
+                       }
                }
                key_fields[NPC_ETYPE] = *etype_tag2;
        }
        if (etype_tag1->nr_kws && etype_tag2->nr_kws) {
                for (i = 0; i < NPC_MAX_KWS_IN_KEY; i++) {
-                       if (etype_tag1->kw_mask[i] != etype_tag2->kw_mask[i])
+                       if (etype_tag1->kw_mask[i] != etype_tag2->kw_mask[i]) {
+                               dev_err(rvu->dev, "mkex: Etype pos is different for tagged and double tagged pkts.\n");
                                goto vlan_tci;
+                       }
                }
                key_fields[NPC_ETYPE] = *etype_tag2;
        }
 
        /* check none of higher layers overwrite Ethertype */
        start_lid = key_fields[NPC_ETYPE].layer_mdata.lid + 1;
-       if (npc_check_overlap(rvu, blkaddr, NPC_ETYPE, start_lid, intf))
+       if (npc_check_overlap(rvu, blkaddr, NPC_ETYPE, start_lid, intf)) {
+               dev_err(rvu->dev, "mkex: Ethertype is overwritten by higher layers.\n");
                goto vlan_tci;
+       }
        *features |= BIT_ULL(NPC_ETYPE);
 vlan_tci:
        /* if key profile does not extract outer vlan tci at all */
-       if (!vlan_tag1->nr_kws && !vlan_tag2->nr_kws)
+       if (!vlan_tag1->nr_kws && !vlan_tag2->nr_kws) {
+               dev_err(rvu->dev, "mkex: Outer vlan tci is not extracted.\n");
                goto done;
+       }
 
        /* if key profile extracts outer vlan tci from one layer */
        if (vlan_tag1->nr_kws && !vlan_tag2->nr_kws)
        /* if key profile extracts outer vlan tci from multiple layers */
        if (vlan_tag1->nr_kws && vlan_tag2->nr_kws) {
                for (i = 0; i < NPC_MAX_KWS_IN_KEY; i++) {
-                       if (vlan_tag1->kw_mask[i] != vlan_tag2->kw_mask[i])
+                       if (vlan_tag1->kw_mask[i] != vlan_tag2->kw_mask[i]) {
+                               dev_err(rvu->dev, "mkex: Out vlan tci pos is different for tagged and double tagged pkts.\n");
                                goto done;
+                       }
                }
                key_fields[NPC_OUTER_VID] = *vlan_tag2;
        }
        /* check none of higher layers overwrite outer vlan tci */
        start_lid = key_fields[NPC_OUTER_VID].layer_mdata.lid + 1;
-       if (npc_check_overlap(rvu, blkaddr, NPC_OUTER_VID, start_lid, intf))
+       if (npc_check_overlap(rvu, blkaddr, NPC_OUTER_VID, start_lid, intf)) {
+               dev_err(rvu->dev, "mkex: Outer vlan tci is overwritten by higher layers.\n");
                goto done;
+       }
        *features |= BIT_ULL(NPC_OUTER_VID);
 done:
        return;
        if (npc_check_field(rvu, blkaddr, NPC_LB, intf))
                *features |= BIT_ULL(NPC_VLAN_ETYPE_CTAG) |
                             BIT_ULL(NPC_VLAN_ETYPE_STAG);
+
+       /* for L2M/L2B/L3M/L3B, check if the type is present in the key */
+       if (npc_check_field(rvu, blkaddr, NPC_LXMB, intf))
+               *features |= BIT_ULL(NPC_LXMB);
 }
 
 /* Scan key extraction profile and record how fields of our interest
                dev_err(rvu->dev, "Channel cannot be overwritten\n");
                return -EINVAL;
        }
-       /* DMAC should be present in key for unicast filter to work */
-       if (!npc_is_field_present(rvu, NPC_DMAC, NIX_INTF_RX)) {
-               dev_err(rvu->dev, "DMAC not present in Key\n");
-               return -EINVAL;
-       }
-       /* check that none of the fields overwrite DMAC */
-       if (npc_check_overlap(rvu, blkaddr, NPC_DMAC, 0, NIX_INTF_RX)) {
-               dev_err(rvu->dev, "DMAC cannot be overwritten\n");
-               return -EINVAL;
-       }
 
        npc_set_features(rvu, blkaddr, NIX_INTF_TX);
        npc_set_features(rvu, blkaddr, NIX_INTF_RX);
                npc_update_entry(rvu, NPC_LE, entry, NPC_LT_LE_ESP,
                                 0, ~0ULL, 0, intf);
 
+       if (features & BIT_ULL(NPC_LXMB)) {
+               output->lxmb = is_broadcast_ether_addr(pkt->dmac) ? 2 : 1;
+               npc_update_entry(rvu, NPC_LXMB, entry, output->lxmb, 0,
+                                output->lxmb, 0, intf);
+       }
 #define NPC_WRITE_FLOW(field, member, val_lo, val_hi, mask_lo, mask_hi)              \
 do {                                                                         \
        if (features & BIT_ULL((field))) {                                    \
        rule->chan_mask = write_req.entry_data.kw_mask[0] & NPC_KEX_CHAN_MASK;
        rule->chan = write_req.entry_data.kw[0] & NPC_KEX_CHAN_MASK;
        rule->chan &= rule->chan_mask;
+       rule->lxmb = dummy.lxmb;
        if (is_npc_intf_tx(req->intf))
                rule->intf = pfvf->nix_tx_intf;
        else
        if (!is_npc_interface_valid(rvu, req->intf))
                return NPC_FLOW_INTF_INVALID;
 
+       /* If DMAC is not extracted in MKEX, rules installed by AF
+        * can rely on L2MB bit set by hardware protocol checker for
+        * broadcast and multicast addresses.
+        */
+       if (npc_check_field(rvu, blkaddr, NPC_DMAC, req->intf))
+               goto process_flow;
+
+       if (is_pffunc_af(req->hdr.pcifunc)) {
+               if (is_unicast_ether_addr(req->packet.dmac)) {
+                       dev_err(rvu->dev,
+                               "%s: mkex profile does not support ucast flow\n",
+                               __func__);
+                       return NPC_FLOW_NOT_SUPPORTED;
+               }
+
+               if (!npc_is_field_present(rvu, NPC_LXMB, req->intf)) {
+                       dev_err(rvu->dev,
+                               "%s: mkex profile does not support bcast/mcast flow",
+                               __func__);
+                       return NPC_FLOW_NOT_SUPPORTED;
+               }
+
+               /* Modify feature to use LXMB instead of DMAC */
+               req->features &= ~BIT_ULL(NPC_DMAC);
+               req->features |= BIT_ULL(NPC_LXMB);
+       }
+
+process_flow:
        if (from_vf && req->default_rule)
                return NPC_FLOW_VF_PERM_DENIED;