Skip to content

Commit 9b42c1f

Browse files
committed
xfrm: Extend the output_mark to support input direction and masking.
We already support setting an output mark at the xfrm_state, unfortunately this does not support the input direction and masking the marks that will be applied to the skb. This change adds support applying a masked value in both directions. The existing XFRMA_OUTPUT_MARK number is reused for this purpose and as it is now bi-directional, it is renamed to XFRMA_SET_MARK. An additional XFRMA_SET_MARK_MASK attribute is added for setting the mask. If the attribute mask not provided, it is set to 0xffffffff, keeping the XFRMA_OUTPUT_MARK existing 'full mask' semantics. Co-developed-by: Tobias Brunner <[email protected]> Co-developed-by: Eyal Birger <[email protected]> Co-developed-by: Lorenzo Colitti <[email protected]> Signed-off-by: Steffen Klassert <[email protected]> Signed-off-by: Tobias Brunner <[email protected]> Signed-off-by: Eyal Birger <[email protected]> Signed-off-by: Lorenzo Colitti <[email protected]>
1 parent dd55c4e commit 9b42c1f

File tree

7 files changed

+57
-17
lines changed

7 files changed

+57
-17
lines changed

include/net/xfrm.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ struct xfrm_state {
166166
int header_len;
167167
int trailer_len;
168168
u32 extra_flags;
169-
u32 output_mark;
169+
struct xfrm_mark smark;
170170
} props;
171171

172172
struct xfrm_lifetime_cfg lft;
@@ -2012,6 +2012,13 @@ static inline int xfrm_mark_put(struct sk_buff *skb, const struct xfrm_mark *m)
20122012
return ret;
20132013
}
20142014

2015+
static inline __u32 xfrm_smark_get(__u32 mark, struct xfrm_state *x)
2016+
{
2017+
struct xfrm_mark *m = &x->props.smark;
2018+
2019+
return (m->v & m->m) | (mark & ~m->m);
2020+
}
2021+
20152022
static inline int xfrm_tunnel_check(struct sk_buff *skb, struct xfrm_state *x,
20162023
unsigned int family)
20172024
{

include/uapi/linux/xfrm.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,11 @@ enum xfrm_attr_type_t {
305305
XFRMA_ADDRESS_FILTER, /* struct xfrm_address_filter */
306306
XFRMA_PAD,
307307
XFRMA_OFFLOAD_DEV, /* struct xfrm_state_offload */
308-
XFRMA_OUTPUT_MARK, /* __u32 */
308+
XFRMA_SET_MARK, /* __u32 */
309+
XFRMA_SET_MARK_MASK, /* __u32 */
309310
__XFRMA_MAX
310311

312+
#define XFRMA_OUTPUT_MARK XFRMA_SET_MARK /* Compatibility */
311313
#define XFRMA_MAX (__XFRMA_MAX - 1)
312314
};
313315

net/xfrm/xfrm_device.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
162162
}
163163

164164
dst = __xfrm_dst_lookup(net, 0, 0, saddr, daddr,
165-
x->props.family, x->props.output_mark);
165+
x->props.family,
166+
xfrm_smark_get(0, x));
166167
if (IS_ERR(dst))
167168
return 0;
168169

net/xfrm/xfrm_input.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
339339
goto drop;
340340
}
341341

342+
skb->mark = xfrm_smark_get(skb->mark, x);
343+
342344
skb->sp->xvec[skb->sp->len++] = x;
343345

344346
lock:

net/xfrm/xfrm_output.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
6666
goto error_nolock;
6767
}
6868

69-
if (x->props.output_mark)
70-
skb->mark = x->props.output_mark;
69+
skb->mark = xfrm_smark_get(skb->mark, x);
7170

7271
err = x->outer_mode->output(x, skb);
7372
if (err) {

net/xfrm/xfrm_policy.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,10 +1607,11 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
16071607
dst_copy_metrics(dst1, dst);
16081608

16091609
if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
1610+
__u32 mark = xfrm_smark_get(fl->flowi_mark, xfrm[i]);
1611+
16101612
family = xfrm[i]->props.family;
16111613
dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif,
1612-
&saddr, &daddr, family,
1613-
xfrm[i]->props.output_mark);
1614+
&saddr, &daddr, family, mark);
16141615
err = PTR_ERR(dst);
16151616
if (IS_ERR(dst))
16161617
goto put_states;

net/xfrm/xfrm_user.c

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,19 @@ static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs,
527527
x->replay_maxdiff = nla_get_u32(rt);
528528
}
529529

530+
static void xfrm_smark_init(struct nlattr **attrs, struct xfrm_mark *m)
531+
{
532+
if (attrs[XFRMA_SET_MARK]) {
533+
m->v = nla_get_u32(attrs[XFRMA_SET_MARK]);
534+
if (attrs[XFRMA_SET_MARK_MASK])
535+
m->m = nla_get_u32(attrs[XFRMA_SET_MARK_MASK]);
536+
else
537+
m->m = 0xffffffff;
538+
} else {
539+
m->v = m->m = 0;
540+
}
541+
}
542+
530543
static struct xfrm_state *xfrm_state_construct(struct net *net,
531544
struct xfrm_usersa_info *p,
532545
struct nlattr **attrs,
@@ -579,8 +592,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
579592

580593
xfrm_mark_get(attrs, &x->mark);
581594

582-
if (attrs[XFRMA_OUTPUT_MARK])
583-
x->props.output_mark = nla_get_u32(attrs[XFRMA_OUTPUT_MARK]);
595+
xfrm_smark_init(attrs, &x->props.smark);
584596

585597
err = __xfrm_init_state(x, false, attrs[XFRMA_OFFLOAD_DEV]);
586598
if (err)
@@ -824,6 +836,18 @@ static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb)
824836
return 0;
825837
}
826838

839+
static int xfrm_smark_put(struct sk_buff *skb, struct xfrm_mark *m)
840+
{
841+
int ret = 0;
842+
843+
if (m->v | m->m) {
844+
ret = nla_put_u32(skb, XFRMA_SET_MARK, m->v);
845+
if (!ret)
846+
ret = nla_put_u32(skb, XFRMA_SET_MARK_MASK, m->m);
847+
}
848+
return ret;
849+
}
850+
827851
/* Don't change this without updating xfrm_sa_len! */
828852
static int copy_to_user_state_extra(struct xfrm_state *x,
829853
struct xfrm_usersa_info *p,
@@ -887,6 +911,11 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
887911
ret = xfrm_mark_put(skb, &x->mark);
888912
if (ret)
889913
goto out;
914+
915+
ret = xfrm_smark_put(skb, &x->props.smark);
916+
if (ret)
917+
goto out;
918+
890919
if (x->replay_esn)
891920
ret = nla_put(skb, XFRMA_REPLAY_ESN_VAL,
892921
xfrm_replay_state_esn_len(x->replay_esn),
@@ -900,11 +929,7 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
900929
ret = copy_user_offload(&x->xso, skb);
901930
if (ret)
902931
goto out;
903-
if (x->props.output_mark) {
904-
ret = nla_put_u32(skb, XFRMA_OUTPUT_MARK, x->props.output_mark);
905-
if (ret)
906-
goto out;
907-
}
932+
908933
if (x->security)
909934
ret = copy_sec_ctx(x->security, skb);
910935
out:
@@ -2493,7 +2518,8 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
24932518
[XFRMA_PROTO] = { .type = NLA_U8 },
24942519
[XFRMA_ADDRESS_FILTER] = { .len = sizeof(struct xfrm_address_filter) },
24952520
[XFRMA_OFFLOAD_DEV] = { .len = sizeof(struct xfrm_user_offload) },
2496-
[XFRMA_OUTPUT_MARK] = { .type = NLA_U32 },
2521+
[XFRMA_SET_MARK] = { .type = NLA_U32 },
2522+
[XFRMA_SET_MARK_MASK] = { .type = NLA_U32 },
24972523
};
24982524

24992525
static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = {
@@ -2719,8 +2745,10 @@ static inline unsigned int xfrm_sa_len(struct xfrm_state *x)
27192745
l += nla_total_size(sizeof(x->props.extra_flags));
27202746
if (x->xso.dev)
27212747
l += nla_total_size(sizeof(x->xso));
2722-
if (x->props.output_mark)
2723-
l += nla_total_size(sizeof(x->props.output_mark));
2748+
if (x->props.smark.v | x->props.smark.m) {
2749+
l += nla_total_size(sizeof(x->props.smark.v));
2750+
l += nla_total_size(sizeof(x->props.smark.m));
2751+
}
27242752

27252753
/* Must count x->lastused as it may become non-zero behind our back. */
27262754
l += nla_total_size_64bit(sizeof(u64));

0 commit comments

Comments
 (0)