[NPC_IPPROTO_TCP] = "ip proto tcp",
        [NPC_IPPROTO_UDP] = "ip proto udp",
        [NPC_IPPROTO_SCTP] = "ip proto sctp",
+       [NPC_IPPROTO_ICMP] = "ip proto icmp",
+       [NPC_IPPROTO_ICMP6] = "ip proto icmp6",
        [NPC_IPPROTO_AH] = "ip proto AH",
        [NPC_IPPROTO_ESP] = "ip proto ESP",
        [NPC_SPORT_TCP] = "tcp source port",
         * packet header fields below.
         * Example: Source IP is 4 bytes and starts at 12th byte of IP header
         */
+       NPC_SCAN_HDR(NPC_TOS, NPC_LID_LC, NPC_LT_LC_IP, 1, 1);
        NPC_SCAN_HDR(NPC_SIP_IPV4, NPC_LID_LC, NPC_LT_LC_IP, 12, 4);
        NPC_SCAN_HDR(NPC_DIP_IPV4, NPC_LID_LC, NPC_LT_LC_IP, 16, 4);
        NPC_SCAN_HDR(NPC_SIP_IPV6, NPC_LID_LC, NPC_LT_LC_IP6, 8, 16);
                                     BIT_ULL(NPC_IPPROTO_SCTP);
        }
 
-       /* for AH, check if corresponding layer type is present in the key */
-       if (npc_check_field(rvu, blkaddr, NPC_LD, intf))
+       /* for AH/ICMP/ICMPv6/, check if corresponding layer type is present in the key */
+       if (npc_check_field(rvu, blkaddr, NPC_LD, intf)) {
                *features |= BIT_ULL(NPC_IPPROTO_AH);
+               *features |= BIT_ULL(NPC_IPPROTO_ICMP);
+               *features |= BIT_ULL(NPC_IPPROTO_ICMP6);
+       }
 
        /* for ESP, check if corresponding layer type is present in the key */
        if (npc_check_field(rvu, blkaddr, NPC_LE, intf))
        if (features & BIT_ULL(NPC_IPPROTO_SCTP))
                npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_SCTP,
                                 0, ~0ULL, 0, intf);
+       if (features & BIT_ULL(NPC_IPPROTO_ICMP))
+               npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_ICMP,
+                                0, ~0ULL, 0, intf);
+       if (features & BIT_ULL(NPC_IPPROTO_ICMP6))
+               npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_ICMP6,
+                                0, ~0ULL, 0, intf);
 
        if (features & BIT_ULL(NPC_OUTER_VID))
                npc_update_entry(rvu, NPC_LB, entry,
        NPC_WRITE_FLOW(NPC_SMAC, smac, smac_val, 0, smac_mask, 0);
        NPC_WRITE_FLOW(NPC_ETYPE, etype, ntohs(pkt->etype), 0,
                       ntohs(mask->etype), 0);
+       NPC_WRITE_FLOW(NPC_TOS, tos, pkt->tos, 0, mask->tos, 0);
        NPC_WRITE_FLOW(NPC_SIP_IPV4, ip4src, ntohl(pkt->ip4src), 0,
                       ntohl(mask->ip4src), 0);
        NPC_WRITE_FLOW(NPC_DIP_IPV4, ip4dst, ntohl(pkt->ip4dst), 0,
 
                               sizeof(pmask->ip4dst));
                        req->features |= BIT_ULL(NPC_DIP_IPV4);
                }
+               if (ipv4_usr_mask->tos) {
+                       pkt->tos = ipv4_usr_hdr->tos;
+                       pmask->tos = ipv4_usr_mask->tos;
+                       req->features |= BIT_ULL(NPC_TOS);
+               }
+               if (ipv4_usr_mask->proto) {
+                       switch (ipv4_usr_hdr->proto) {
+                       case IPPROTO_ICMP:
+                               req->features |= BIT_ULL(NPC_IPPROTO_ICMP);
+                               break;
+                       case IPPROTO_TCP:
+                               req->features |= BIT_ULL(NPC_IPPROTO_TCP);
+                               break;
+                       case IPPROTO_UDP:
+                               req->features |= BIT_ULL(NPC_IPPROTO_UDP);
+                               break;
+                       case IPPROTO_SCTP:
+                               req->features |= BIT_ULL(NPC_IPPROTO_SCTP);
+                               break;
+                       case IPPROTO_AH:
+                               req->features |= BIT_ULL(NPC_IPPROTO_AH);
+                               break;
+                       case IPPROTO_ESP:
+                               req->features |= BIT_ULL(NPC_IPPROTO_ESP);
+                               break;
+                       default:
+                               return -EOPNOTSUPP;
+                       }
+               }
                pkt->etype = cpu_to_be16(ETH_P_IP);
                pmask->etype = cpu_to_be16(0xFFFF);
                req->features |= BIT_ULL(NPC_ETYPE);
                               sizeof(pmask->ip4dst));
                        req->features |= BIT_ULL(NPC_DIP_IPV4);
                }
+               if (ipv4_l4_mask->tos) {
+                       pkt->tos = ipv4_l4_hdr->tos;
+                       pmask->tos = ipv4_l4_mask->tos;
+                       req->features |= BIT_ULL(NPC_TOS);
+               }
                if (ipv4_l4_mask->psrc) {
                        memcpy(&pkt->sport, &ipv4_l4_hdr->psrc,
                               sizeof(pkt->sport));
                               sizeof(pmask->ip4dst));
                        req->features |= BIT_ULL(NPC_DIP_IPV4);
                }
+               if (ah_esp_mask->tos) {
+                       pkt->tos = ah_esp_hdr->tos;
+                       pmask->tos = ah_esp_mask->tos;
+                       req->features |= BIT_ULL(NPC_TOS);
+               }
 
                /* NPC profile doesn't extract AH/ESP header fields */
-               if ((ah_esp_mask->spi & ah_esp_hdr->spi) ||
-                   (ah_esp_mask->tos & ah_esp_mask->tos))
+               if (ah_esp_mask->spi & ah_esp_hdr->spi)
                        return -EOPNOTSUPP;
 
                if (flow_type == AH_V4_FLOW)