| @@ -47,6 +47,8 @@ static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a, · 46 unmodified lines |
| 47 | skb_set_queue_mapping(skb, d->queue_mapping); | 47 | skb_set_queue_mapping(skb, d->queue_mapping); |
| 48 | if (d->flags & SKBEDIT_F_MARK) | 48 | if (d->flags & SKBEDIT_F_MARK) |
| 49 | skb->mark = d->mark; | 49 | skb->mark = d->mark; |
| | 50 | if (d->flags & SKBEDIT_F_PTYPE) |
| | 51 | skb->pkt_type = d->ptype; |
| 50 | | 52 | |
| 51 | spin_unlock(&d->tcf_lock); | 53 | spin_unlock(&d->tcf_lock); |
| 52 | return d->tcf_action; | 54 | return d->tcf_action; |
| @@ -57,6 +59,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = { · 4 unmodified lines |
| 57 | [TCA_SKBEDIT_PRIORITY] = { .len = sizeof(u32) }, | 59 | [TCA_SKBEDIT_PRIORITY] = { .len = sizeof(u32) }, |
| 58 | [TCA_SKBEDIT_QUEUE_MAPPING] = { .len = sizeof(u16) }, | 60 | [TCA_SKBEDIT_QUEUE_MAPPING] = { .len = sizeof(u16) }, |
| 59 | [TCA_SKBEDIT_MARK] = { .len = sizeof(u32) }, | 61 | [TCA_SKBEDIT_MARK] = { .len = sizeof(u32) }, |
| | 62 | [TCA_SKBEDIT_PTYPE] = { .len = sizeof(u16) }, |
| 60 | }; | 63 | }; |
| 61 | | 64 | |
| 62 | static int tcf_skbedit_init(struct net *net, struct nlattr *nla, | 65 | 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, · 5 unmodified lines |
| 68 | struct tc_skbedit *parm; | 71 | struct tc_skbedit *parm; |
| 69 | struct tcf_skbedit *d; | 72 | struct tcf_skbedit *d; |
| 70 | u32 flags = 0, *priority = NULL, *mark = NULL; | 73 | u32 flags = 0, *priority = NULL, *mark = NULL; |
| 71 | u16 *queue_mapping = NULL; | 74 | u16 *queue_mapping = NULL, *ptype = NULL; |
| 72 | bool exists = false; | 75 | bool exists = false; |
| 73 | int ret = 0, err; | 76 | int ret = 0, err; |
| 74 | | 77 | |
| @@ -92,6 +95,13 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, · 17 unmodified lines |
| 92 | queue_mapping = nla_data(tb[TCA_SKBEDIT_QUEUE_MAPPING]); | 95 | queue_mapping = nla_data(tb[TCA_SKBEDIT_QUEUE_MAPPING]); |
| 93 | } | 96 | } |
| 94 | | 97 | |
| | 98 | if (tb[TCA_SKBEDIT_PTYPE] != NULL) { |
| | 99 | ptype = nla_data(tb[TCA_SKBEDIT_PTYPE]); |
| | 100 | if (!skb_pkt_type_ok(*ptype)) |
| | 101 | return -EINVAL; |
| | 102 | flags |= SKBEDIT_F_PTYPE; |
| | 103 | } |
| | 104 | |
| 95 | if (tb[TCA_SKBEDIT_MARK] != NULL) { | 105 | if (tb[TCA_SKBEDIT_MARK] != NULL) { |
| 96 | flags |= SKBEDIT_F_MARK; | 106 | flags |= SKBEDIT_F_MARK; |
| 97 | mark = nla_data(tb[TCA_SKBEDIT_MARK]); | 107 | mark = nla_data(tb[TCA_SKBEDIT_MARK]); |
| @@ -132,6 +142,8 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, · 34 unmodified lines |
| 132 | d->queue_mapping = *queue_mapping; | 142 | d->queue_mapping = *queue_mapping; |
| 133 | if (flags & SKBEDIT_F_MARK) | 143 | if (flags & SKBEDIT_F_MARK) |
| 134 | d->mark = *mark; | 144 | d->mark = *mark; |
| | 145 | if (flags & SKBEDIT_F_PTYPE) |
| | 146 | d->ptype = *ptype; |
| 135 | | 147 | |
| 136 | d->tcf_action = parm->action; | 148 | d->tcf_action = parm->action; |
| 137 | | 149 | |
| @@ -169,6 +181,10 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, · 31 unmodified lines |
| 169 | nla_put(skb, TCA_SKBEDIT_MARK, sizeof(d->mark), | 181 | nla_put(skb, TCA_SKBEDIT_MARK, sizeof(d->mark), |
| 170 | &d->mark)) | 182 | &d->mark)) |
| 171 | goto nla_put_failure; | 183 | goto nla_put_failure; |
| | 184 | if ((d->flags & SKBEDIT_F_PTYPE) && |
| | 185 | nla_put(skb, TCA_SKBEDIT_PTYPE, sizeof(d->ptype), |
| | 186 | &d->ptype)) |
| | 187 | goto nla_put_failure; |
| 172 | | 188 | |
| 173 | tcf_tm_dump(&t, &d->tcf_tm); | 189 | tcf_tm_dump(&t, &d->tcf_tm); |
| 174 | if (nla_put_64bit(skb, TCA_SKBEDIT_TM, sizeof(t), &t, TCA_SKBEDIT_PAD)) | 190 | if (nla_put_64bit(skb, TCA_SKBEDIT_TM, sizeof(t), &t, TCA_SKBEDIT_PAD)) |