This command could be useful to inc/dec fields. For example, to forward any TCP packet and decrease its TTL: $ tc filter add dev enp0s9 protocol ip parent ffff: \ flower ip_proto tcp \ action pedit munge ip ttl add 0xff pipe \ action mirred egress redirect dev veth0
In the example above, adding 0xff to this u8 field is actually decreasing it by one, since the operation is masked. Signed-off-by: Amir Vadai <a...@vadai.me> --- include/uapi/linux/tc_act/tc_pedit.h | 10 ++++++++++ net/sched/act_pedit.c | 16 +++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/tc_act/tc_pedit.h b/include/uapi/linux/tc_act/tc_pedit.h index 604e6729ad38..80028cd0bb1b 100644 --- a/include/uapi/linux/tc_act/tc_pedit.h +++ b/include/uapi/linux/tc_act/tc_pedit.h @@ -35,8 +35,13 @@ struct tc_pedit_sel { #define PEDIT_TYPE_SHIFT 24 #define PEDIT_TYPE_MASK 0xff +#define PEDIT_CMD_SHIFT 16 +#define PEDIT_CMD_MASK 0xff + #define PEDIT_TYPE_GET(_val) \ (((_val) >> PEDIT_TYPE_SHIFT) & PEDIT_TYPE_MASK) +#define PEDIT_CMD_GET(_val) \ + (((_val) >> PEDIT_CMD_SHIFT) & PEDIT_CMD_MASK) #define PEDIT_SHIFT_GET(_val) ((_val) & 0xff) enum pedit_header_type { @@ -49,4 +54,9 @@ enum pedit_header_type { PEDIT_HDR_TYPE_UDP = 5, }; +enum pedit_cmd { + PEDIT_CMD_SET = 0, + PEDIT_CMD_ADD = 1, +}; + #endif diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 4b9c7184c752..aa137d51bf7f 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -169,6 +169,7 @@ static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a, u32 *ptr, _data; int offset = tkey->off; int hoffset; + u32 val; int rc; enum pedit_header_type htype = PEDIT_TYPE_GET(tkey->shift); @@ -214,7 +215,20 @@ static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a, if (!ptr) goto bad; /* just do it, baby */ - *ptr = ((*ptr & tkey->mask) ^ tkey->val); + switch (PEDIT_CMD_GET(tkey->shift)) { + case PEDIT_CMD_SET: + val = tkey->val; + break; + case PEDIT_CMD_ADD: + val = (*ptr + tkey->val) & ~tkey->mask; + break; + default: + pr_info("tc filter pedit bad command (%d)\n", + PEDIT_CMD_GET(tkey->shift)); + goto bad; + } + + *ptr = ((*ptr & tkey->mask) ^ val); if (ptr == &_data) skb_store_bits(skb, hoffset + offset, ptr, 4); } -- 2.10.2