int             header_len;
                int             trailer_len;
                u32             extra_flags;
+               u32             output_mark;
        } props;
 
        struct xfrm_lifetime_cfg lft;
        struct dst_entry        *(*dst_lookup)(struct net *net,
                                               int tos, int oif,
                                               const xfrm_address_t *saddr,
-                                              const xfrm_address_t *daddr);
+                                              const xfrm_address_t *daddr,
+                                              u32 mark);
        int                     (*get_saddr)(struct net *net, int oif,
                                             xfrm_address_t *saddr,
-                                            xfrm_address_t *daddr);
+                                            xfrm_address_t *daddr,
+                                            u32 mark);
        void                    (*decode_session)(struct sk_buff *skb,
                                                  struct flowi *fl,
                                                  int reverse);
 struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,
                                    const xfrm_address_t *saddr,
                                    const xfrm_address_t *daddr,
-                                   int family);
+                                   int family, u32 mark);
 
 struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp);
 
 
        XFRMA_ADDRESS_FILTER,   /* struct xfrm_address_filter */
        XFRMA_PAD,
        XFRMA_OFFLOAD_DEV,      /* struct xfrm_state_offload */
+       XFRMA_OUTPUT_MARK,      /* __u32 */
        __XFRMA_MAX
 
 #define XFRMA_MAX (__XFRMA_MAX - 1)
 
 static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
                                            int tos, int oif,
                                            const xfrm_address_t *saddr,
-                                           const xfrm_address_t *daddr)
+                                           const xfrm_address_t *daddr,
+                                           u32 mark)
 {
        struct rtable *rt;
 
        fl4->daddr = daddr->a4;
        fl4->flowi4_tos = tos;
        fl4->flowi4_oif = l3mdev_master_ifindex_by_index(net, oif);
+       fl4->flowi4_mark = mark;
        if (saddr)
                fl4->saddr = saddr->a4;
 
 
 static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, int oif,
                                          const xfrm_address_t *saddr,
-                                         const xfrm_address_t *daddr)
+                                         const xfrm_address_t *daddr,
+                                         u32 mark)
 {
        struct flowi4 fl4;
 
-       return __xfrm4_dst_lookup(net, &fl4, tos, oif, saddr, daddr);
+       return __xfrm4_dst_lookup(net, &fl4, tos, oif, saddr, daddr, mark);
 }
 
 static int xfrm4_get_saddr(struct net *net, int oif,
-                          xfrm_address_t *saddr, xfrm_address_t *daddr)
+                          xfrm_address_t *saddr, xfrm_address_t *daddr,
+                          u32 mark)
 {
        struct dst_entry *dst;
        struct flowi4 fl4;
 
-       dst = __xfrm4_dst_lookup(net, &fl4, 0, oif, NULL, daddr);
+       dst = __xfrm4_dst_lookup(net, &fl4, 0, oif, NULL, daddr, mark);
        if (IS_ERR(dst))
                return -EHOSTUNREACH;
 
 
 
 static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,
                                          const xfrm_address_t *saddr,
-                                         const xfrm_address_t *daddr)
+                                         const xfrm_address_t *daddr,
+                                         u32 mark)
 {
        struct flowi6 fl6;
        struct dst_entry *dst;
        memset(&fl6, 0, sizeof(fl6));
        fl6.flowi6_oif = l3mdev_master_ifindex_by_index(net, oif);
        fl6.flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF;
+       fl6.flowi6_mark = mark;
        memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));
        if (saddr)
                memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr));
 }
 
 static int xfrm6_get_saddr(struct net *net, int oif,
-                          xfrm_address_t *saddr, xfrm_address_t *daddr)
+                          xfrm_address_t *saddr, xfrm_address_t *daddr,
+                          u32 mark)
 {
        struct dst_entry *dst;
        struct net_device *dev;
 
-       dst = xfrm6_dst_lookup(net, 0, oif, NULL, daddr);
+       dst = xfrm6_dst_lookup(net, 0, oif, NULL, daddr, mark);
        if (IS_ERR(dst))
                return -EHOSTUNREACH;
 
 
                        daddr = &x->props.saddr;
                }
 
-               dst = __xfrm_dst_lookup(net, 0, 0, saddr, daddr, x->props.family);
+               dst = __xfrm_dst_lookup(net, 0, 0, saddr, daddr,
+                                       x->props.family, x->props.output_mark);
                if (IS_ERR(dst))
                        return 0;
 
 
                        goto error_nolock;
                }
 
+               if (x->props.output_mark)
+                       skb->mark = x->props.output_mark;
+
                err = x->outer_mode->output(x, skb);
                if (err) {
                        XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEMODEERROR);
 
 struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,
                                    const xfrm_address_t *saddr,
                                    const xfrm_address_t *daddr,
-                                   int family)
+                                   int family, u32 mark)
 {
        const struct xfrm_policy_afinfo *afinfo;
        struct dst_entry *dst;
        if (unlikely(afinfo == NULL))
                return ERR_PTR(-EAFNOSUPPORT);
 
-       dst = afinfo->dst_lookup(net, tos, oif, saddr, daddr);
+       dst = afinfo->dst_lookup(net, tos, oif, saddr, daddr, mark);
 
        rcu_read_unlock();
 
                                                int tos, int oif,
                                                xfrm_address_t *prev_saddr,
                                                xfrm_address_t *prev_daddr,
-                                               int family)
+                                               int family, u32 mark)
 {
        struct net *net = xs_net(x);
        xfrm_address_t *saddr = &x->props.saddr;
                daddr = x->coaddr;
        }
 
-       dst = __xfrm_dst_lookup(net, tos, oif, saddr, daddr, family);
+       dst = __xfrm_dst_lookup(net, tos, oif, saddr, daddr, family, mark);
 
        if (!IS_ERR(dst)) {
                if (prev_saddr != saddr)
 
 static int
 xfrm_get_saddr(struct net *net, int oif, xfrm_address_t *local,
-              xfrm_address_t *remote, unsigned short family)
+              xfrm_address_t *remote, unsigned short family, u32 mark)
 {
        int err;
        const struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
 
        if (unlikely(afinfo == NULL))
                return -EINVAL;
-       err = afinfo->get_saddr(net, oif, local, remote);
+       err = afinfo->get_saddr(net, oif, local, remote, mark);
        rcu_read_unlock();
        return err;
 }
                        if (xfrm_addr_any(local, tmpl->encap_family)) {
                                error = xfrm_get_saddr(net, fl->flowi_oif,
                                                       &tmp, remote,
-                                                      tmpl->encap_family);
+                                                      tmpl->encap_family, 0);
                                if (error)
                                        goto fail;
                                local = &tmp;
                if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
                        family = xfrm[i]->props.family;
                        dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif,
-                                             &saddr, &daddr, family);
+                                             &saddr, &daddr, family,
+                                             xfrm[i]->props.output_mark);
                        err = PTR_ERR(dst);
                        if (IS_ERR(dst))
                                goto put_states;
 
 
        xfrm_mark_get(attrs, &x->mark);
 
+       if (attrs[XFRMA_OUTPUT_MARK])
+               x->props.output_mark = nla_get_u32(attrs[XFRMA_OUTPUT_MARK]);
+
        err = __xfrm_init_state(x, false, attrs[XFRMA_OFFLOAD_DEV]);
        if (err)
                goto error;
                goto out;
        if (x->security)
                ret = copy_sec_ctx(x->security, skb);
+       if (x->props.output_mark) {
+               ret = nla_put_u32(skb, XFRMA_OUTPUT_MARK, x->props.output_mark);
+               if (ret)
+                       goto out;
+       }
 out:
        return ret;
 }
        [XFRMA_PROTO]           = { .type = NLA_U8 },
        [XFRMA_ADDRESS_FILTER]  = { .len = sizeof(struct xfrm_address_filter) },
        [XFRMA_OFFLOAD_DEV]     = { .len = sizeof(struct xfrm_user_offload) },
+       [XFRMA_OUTPUT_MARK]     = { .len = NLA_U32 },
 };
 
 static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = {
                l += nla_total_size(sizeof(x->props.extra_flags));
        if (x->xso.dev)
                 l += nla_total_size(sizeof(x->xso));
+       if (x->props.output_mark)
+               l += nla_total_size(sizeof(x->props.output_mark));
 
        /* Must count x->lastused as it may become non-zero behind our back. */
        l += nla_total_size_64bit(sizeof(u64));