|
@@ -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] = {
|
|
[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,
|
|
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,
|
|
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,
|
|
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,
|
|
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))
|