pop_mpls->ethtype = act->mpls_pop.proto;
 }
 
+static void
+nfp_fl_set_mpls(struct nfp_fl_set_mpls *set_mpls,
+               const struct flow_action_entry *act)
+{
+       size_t act_size = sizeof(struct nfp_fl_set_mpls);
+       u32 mpls_lse = 0, mpls_mask = 0;
+
+       set_mpls->head.jump_id = NFP_FL_ACTION_OPCODE_SET_MPLS;
+       set_mpls->head.len_lw = act_size >> NFP_FL_LW_SIZ;
+
+       if (act->mpls_mangle.label != ACT_MPLS_LABEL_NOT_SET) {
+               mpls_lse |= act->mpls_mangle.label << MPLS_LS_LABEL_SHIFT;
+               mpls_mask |= MPLS_LS_LABEL_MASK;
+       }
+       if (act->mpls_mangle.tc != ACT_MPLS_TC_NOT_SET) {
+               mpls_lse |= act->mpls_mangle.tc << MPLS_LS_TC_SHIFT;
+               mpls_mask |= MPLS_LS_TC_MASK;
+       }
+       if (act->mpls_mangle.bos != ACT_MPLS_BOS_NOT_SET) {
+               mpls_lse |= act->mpls_mangle.bos << MPLS_LS_S_SHIFT;
+               mpls_mask |= MPLS_LS_S_MASK;
+       }
+       if (act->mpls_mangle.ttl) {
+               mpls_lse |= act->mpls_mangle.ttl << MPLS_LS_TTL_SHIFT;
+               mpls_mask |= MPLS_LS_TTL_MASK;
+       }
+
+       set_mpls->lse = cpu_to_be32(mpls_lse);
+       set_mpls->lse_mask = cpu_to_be32(mpls_mask);
+}
+
 static void nfp_fl_pop_vlan(struct nfp_fl_pop_vlan *pop_vlan)
 {
        size_t act_size = sizeof(struct nfp_fl_pop_vlan);
        struct nfp_fl_push_mpls *psh_m;
        struct nfp_fl_pop_vlan *pop_v;
        struct nfp_fl_pop_mpls *pop_m;
+       struct nfp_fl_set_mpls *set_m;
        int err;
 
        switch (act->id) {
                nfp_fl_pop_mpls(pop_m, act);
                *a_len += sizeof(struct nfp_fl_pop_mpls);
                break;
+       case FLOW_ACTION_MPLS_MANGLE:
+               if (*a_len +
+                   sizeof(struct nfp_fl_set_mpls) > NFP_FL_MAX_A_SIZ) {
+                       NL_SET_ERR_MSG_MOD(extack, "unsupported offload: maximum allowed action list size exceeded at set MPLS");
+                       return -EOPNOTSUPP;
+               }
+
+               set_m = (struct nfp_fl_set_mpls *)&nfp_fl->action_data[*a_len];
+               nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL);
+
+               nfp_fl_set_mpls(set_m, act);
+               *a_len += sizeof(struct nfp_fl_set_mpls);
+               break;
        default:
                /* Currently we do not handle any other actions. */
                NL_SET_ERR_MSG_MOD(extack, "unsupported offload: unsupported action in action list");
 
 #define NFP_FL_ACTION_OPCODE_POP_MPLS          4
 #define NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL   6
 #define NFP_FL_ACTION_OPCODE_SET_ETHERNET      7
+#define NFP_FL_ACTION_OPCODE_SET_MPLS          8
 #define NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS    9
 #define NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS  10
 #define NFP_FL_ACTION_OPCODE_SET_IPV6_SRC      11
        __be16 ethtype;
 };
 
+struct nfp_fl_set_mpls {
+       struct nfp_fl_act_head head;
+       __be16 reserved;
+       __be32 lse_mask;
+       __be32 lse;
+};
+
 /* Metadata with L2 (1W/4B)
  * ----------------------------------------------------------------
  *    3                   2                   1