Commit ff202ee1 authored by Jamal Hadi Salim's avatar Jamal Hadi Salim Committed by David S. Miller

net sched actions: skbedit add support for mod-ing skb pkt_type

Extremely useful for setting packet type to host so i dont
have to modify the dst mac address using pedit (which requires
that i know the mac address)

Example usage:
tc filter add dev eth0 parent ffff: protocol ip pref 9 u32 \
match ip src 5.5.5.5/32 \
flowid 1:5 action skbedit ptype host

This will tag all packets incoming from 5.5.5.5 with type
PACKET_HOST
Signed-off-by: default avatarJamal Hadi Salim <jhs@mojatatu.com>
Acked-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8b10cab6
...@@ -24,11 +24,11 @@ ...@@ -24,11 +24,11 @@
struct tcf_skbedit { struct tcf_skbedit {
struct tcf_common common; struct tcf_common common;
u32 flags; u32 flags;
u32 priority; u32 priority;
u32 mark; u32 mark;
u16 queue_mapping; u16 queue_mapping;
/* XXX: 16-bit pad here? */ u16 ptype;
}; };
#define to_skbedit(a) \ #define to_skbedit(a) \
container_of(a->priv, struct tcf_skbedit, common) container_of(a->priv, struct tcf_skbedit, common)
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define SKBEDIT_F_PRIORITY 0x1 #define SKBEDIT_F_PRIORITY 0x1
#define SKBEDIT_F_QUEUE_MAPPING 0x2 #define SKBEDIT_F_QUEUE_MAPPING 0x2
#define SKBEDIT_F_MARK 0x4 #define SKBEDIT_F_MARK 0x4
#define SKBEDIT_F_PTYPE 0x8
struct tc_skbedit { struct tc_skbedit {
tc_gen; tc_gen;
...@@ -40,6 +41,7 @@ enum { ...@@ -40,6 +41,7 @@ enum {
TCA_SKBEDIT_QUEUE_MAPPING, TCA_SKBEDIT_QUEUE_MAPPING,
TCA_SKBEDIT_MARK, TCA_SKBEDIT_MARK,
TCA_SKBEDIT_PAD, TCA_SKBEDIT_PAD,
TCA_SKBEDIT_PTYPE,
__TCA_SKBEDIT_MAX __TCA_SKBEDIT_MAX
}; };
#define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1) #define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
......
...@@ -47,6 +47,8 @@ static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a, ...@@ -47,6 +47,8 @@ static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
skb_set_queue_mapping(skb, d->queue_mapping); skb_set_queue_mapping(skb, d->queue_mapping);
if (d->flags & SKBEDIT_F_MARK) if (d->flags & SKBEDIT_F_MARK)
skb->mark = d->mark; skb->mark = d->mark;
if (d->flags & SKBEDIT_F_PTYPE)
skb->pkt_type = d->ptype;
spin_unlock(&d->tcf_lock); spin_unlock(&d->tcf_lock);
return d->tcf_action; return d->tcf_action;
...@@ -57,6 +59,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = { ...@@ -57,6 +59,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
[TCA_SKBEDIT_PRIORITY] = { .len = sizeof(u32) }, [TCA_SKBEDIT_PRIORITY] = { .len = sizeof(u32) },
[TCA_SKBEDIT_QUEUE_MAPPING] = { .len = sizeof(u16) }, [TCA_SKBEDIT_QUEUE_MAPPING] = { .len = sizeof(u16) },
[TCA_SKBEDIT_MARK] = { .len = sizeof(u32) }, [TCA_SKBEDIT_MARK] = { .len = sizeof(u32) },
[TCA_SKBEDIT_PTYPE] = { .len = sizeof(u16) },
}; };
static int tcf_skbedit_init(struct net *net, struct nlattr *nla, static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
...@@ -68,7 +71,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, ...@@ -68,7 +71,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
struct tc_skbedit *parm; struct tc_skbedit *parm;
struct tcf_skbedit *d; struct tcf_skbedit *d;
u32 flags = 0, *priority = NULL, *mark = NULL; u32 flags = 0, *priority = NULL, *mark = NULL;
u16 *queue_mapping = NULL; u16 *queue_mapping = NULL, *ptype = NULL;
bool exists = false; bool exists = false;
int ret = 0, err; int ret = 0, err;
...@@ -92,6 +95,13 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, ...@@ -92,6 +95,13 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
queue_mapping = nla_data(tb[TCA_SKBEDIT_QUEUE_MAPPING]); queue_mapping = nla_data(tb[TCA_SKBEDIT_QUEUE_MAPPING]);
} }
if (tb[TCA_SKBEDIT_PTYPE] != NULL) {
ptype = nla_data(tb[TCA_SKBEDIT_PTYPE]);
if (!skb_pkt_type_ok(*ptype))
return -EINVAL;
flags |= SKBEDIT_F_PTYPE;
}
if (tb[TCA_SKBEDIT_MARK] != NULL) { if (tb[TCA_SKBEDIT_MARK] != NULL) {
flags |= SKBEDIT_F_MARK; flags |= SKBEDIT_F_MARK;
mark = nla_data(tb[TCA_SKBEDIT_MARK]); mark = nla_data(tb[TCA_SKBEDIT_MARK]);
...@@ -132,6 +142,8 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, ...@@ -132,6 +142,8 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
d->queue_mapping = *queue_mapping; d->queue_mapping = *queue_mapping;
if (flags & SKBEDIT_F_MARK) if (flags & SKBEDIT_F_MARK)
d->mark = *mark; d->mark = *mark;
if (flags & SKBEDIT_F_PTYPE)
d->ptype = *ptype;
d->tcf_action = parm->action; d->tcf_action = parm->action;
...@@ -169,6 +181,10 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -169,6 +181,10 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
nla_put(skb, TCA_SKBEDIT_MARK, sizeof(d->mark), nla_put(skb, TCA_SKBEDIT_MARK, sizeof(d->mark),
&d->mark)) &d->mark))
goto nla_put_failure; goto nla_put_failure;
if ((d->flags & SKBEDIT_F_PTYPE) &&
nla_put(skb, TCA_SKBEDIT_PTYPE, sizeof(d->ptype),
&d->ptype))
goto nla_put_failure;
tcf_tm_dump(&t, &d->tcf_tm); tcf_tm_dump(&t, &d->tcf_tm);
if (nla_put_64bit(skb, TCA_SKBEDIT_TM, sizeof(t), &t, TCA_SKBEDIT_PAD)) if (nla_put_64bit(skb, TCA_SKBEDIT_TM, sizeof(t), &t, TCA_SKBEDIT_PAD))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment