bool mpls_push;
        bool ptype_host;
        const struct ip_tunnel_info *tun_info;
+       struct mlx5e_mpls_info mpls_info;
        struct pedit_headers_action hdrs[__PEDIT_CMD_MAX];
        int ifindexes[MLX5_MAX_FLOW_FWD_VPORTS];
        int if_count;
 
                return -ENOMEM;
 
        parse_state->encap = false;
+
+       if (parse_state->mpls_push) {
+               memcpy(&parse_attr->mpls_info[esw_attr->out_count],
+                      &parse_state->mpls_info, sizeof(parse_state->mpls_info));
+               parse_state->mpls_push = false;
+       }
        esw_attr->dests[esw_attr->out_count].flags |= MLX5_ESW_DEST_ENCAP;
        esw_attr->out_count++;
        /* attr->dests[].rep is resolved when we handle encap */
 
        return true;
 }
 
+static void
+copy_mpls_info(struct mlx5e_mpls_info *mpls_info,
+              const struct flow_action_entry *act)
+{
+       mpls_info->label = act->mpls_push.label;
+       mpls_info->tc = act->mpls_push.tc;
+       mpls_info->bos = act->mpls_push.bos;
+       mpls_info->ttl = act->mpls_push.ttl;
+}
+
 static int
 tc_act_parse_mpls_push(struct mlx5e_tc_act_parse_state *parse_state,
                       const struct flow_action_entry *act,
                       struct mlx5_flow_attr *attr)
 {
        parse_state->mpls_push = true;
+       copy_mpls_info(&parse_state->mpls_info, act);
 
        return 0;
 }
 
 
 struct mlx5e_tc_flow_parse_attr {
        const struct ip_tunnel_info *tun_info[MLX5_MAX_FLOW_FWD_VPORTS];
+       struct mlx5e_mpls_info mpls_info[MLX5_MAX_FLOW_FWD_VPORTS];
        struct net_device *filter_dev;
        struct mlx5_flow_spec spec;
        struct mlx5e_tc_mod_hdr_acts mod_hdr_acts;
 
        struct mlx5e_tc_flow_parse_attr *parse_attr;
        struct mlx5_flow_attr *attr = flow->attr;
        const struct ip_tunnel_info *tun_info;
+       const struct mlx5e_mpls_info *mpls_info;
        unsigned long tbl_time_before = 0;
        struct mlx5e_encap_entry *e;
        struct mlx5e_encap_key key;
 
        parse_attr = attr->parse_attr;
        tun_info = parse_attr->tun_info[out_index];
+       mpls_info = &parse_attr->mpls_info[out_index];
        family = ip_tunnel_info_af(tun_info);
        key.ip_tun_key = &tun_info->key;
        key.tc_tunnel = mlx5e_get_tc_tun(mirred_dev);
                goto out_err_init;
        }
        e->tun_info = tun_info;
+       memcpy(&e->mpls_info, mpls_info, sizeof(*mpls_info));
        err = mlx5e_tc_tun_init_encap_attr(mirred_dev, priv, e, extack);
        if (err)
                goto out_err_init;
 
                               struct mlx5e_encap_entry *r)
 {
        const struct ip_tunnel_key *tun_key = &r->tun_info->key;
+       const struct mlx5e_mpls_info *mpls_info = &r->mpls_info;
        struct udphdr *udp = (struct udphdr *)(buf);
        struct mpls_shim_hdr *mpls;
-       u32 tun_id;
 
-       tun_id = be32_to_cpu(tunnel_id_to_key32(tun_key->tun_id));
        mpls = (struct mpls_shim_hdr *)(udp + 1);
        *ip_proto = IPPROTO_UDP;
 
        udp->dest = tun_key->tp_dst;
-       *mpls = mpls_entry_encode(tun_id, tun_key->ttl, tun_key->tos, true);
+       *mpls = mpls_entry_encode(mpls_info->label, mpls_info->ttl, mpls_info->tc, mpls_info->bos);
 
        return 0;
 }
 
        struct rcu_head rcu;
 };
 
+struct mlx5e_mpls_info {
+       u32             label;
+       u8              tc;
+       u8              bos;
+       u8              ttl;
+};
+
 struct mlx5e_encap_entry {
        /* attached neigh hash entry */
        struct mlx5e_neigh_hash_entry *nhe;
        struct list_head route_list;
        struct mlx5_pkt_reformat *pkt_reformat;
        const struct ip_tunnel_info *tun_info;
+       struct mlx5e_mpls_info mpls_info;
        unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
 
        struct net_device *out_dev;