Blame view

net/sched/sch_dsmark.c 11.9 KB
09c434b8a   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
  /* net/sched/sch_dsmark.c - Differentiated Services field marker */
  
  /* Written 1998-2000 by Werner Almesberger, EPFL ICA */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
  #include <linux/module.h>
  #include <linux/init.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
7
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
  #include <linux/types.h>
  #include <linux/string.h>
  #include <linux/errno.h>
  #include <linux/skbuff.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
  #include <linux/rtnetlink.h>
5b0ac72bc   David S. Miller   [PKT_SCHED] dsmar...
13
  #include <linux/bitops.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
  #include <net/pkt_sched.h>
cf1facda2   Jiri Pirko   sched: move tcf_p...
15
  #include <net/pkt_cls.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
  #include <net/dsfield.h>
  #include <net/inet_ecn.h>
  #include <asm/byteorder.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  /*
   * classid	class		marking
   * -------	-----		-------
   *   n/a	  0		n/a
   *   x:0	  1		use entry [0]
   *   ...	 ...		...
   *   x:y y>0	 y+1		use entry [y]
   *   ...	 ...		...
   * x:indices-1	indices		use entry [indices-1]
   *   ...	 ...		...
   *   x:y	 y+1		use entry [y & (indices-1)]
   *   ...	 ...		...
   * 0xffff	0x10000		use entry [indices-1]
   */
  
  
  #define NO_DEFAULT_INDEX	(1 << 16)
47bbbb30b   Eric Dumazet   sch_dsmark: impro...
36
37
38
39
  struct mask_value {
  	u8			mask;
  	u8			value;
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
  struct dsmark_qdisc_data {
  	struct Qdisc		*q;
25d8c0d55   John Fastabend   net: rcu-ify tcf_...
42
  	struct tcf_proto __rcu	*filter_list;
6529eaba3   Jiri Pirko   net: sched: intro...
43
  	struct tcf_block	*block;
47bbbb30b   Eric Dumazet   sch_dsmark: impro...
44
  	struct mask_value	*mv;
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
45
  	u16			indices;
47bbbb30b   Eric Dumazet   sch_dsmark: impro...
46
  	u8			set_tc_index;
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
47
  	u32			default_index;	/* index range is 0...0xffff */
47bbbb30b   Eric Dumazet   sch_dsmark: impro...
48
49
  #define DSMARK_EMBEDDED_SZ	16
  	struct mask_value	embedded[DSMARK_EMBEDDED_SZ];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
  };
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
51
52
  static inline int dsmark_valid_index(struct dsmark_qdisc_data *p, u16 index)
  {
17569faed   Yang Yingliang   net_sched: remove...
53
  	return index <= p->indices && index > 0;
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
54
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
  
  /* ------------------------- Class/flow operations ------------------------- */
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
57
  static int dsmark_graft(struct Qdisc *sch, unsigned long arg,
653d6fd68   Alexander Aring   net: sched: sch: ...
58
59
  			struct Qdisc *new, struct Qdisc **old,
  			struct netlink_ext_ack *extack)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
  {
81da99ed7   Stephen Hemminger   [PKT_SCHED] dsmar...
61
  	struct dsmark_qdisc_data *p = qdisc_priv(sch);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62

c76f2a2c4   Yang Yingliang   sch_dsmark: use c...
63
64
65
  	pr_debug("%s(sch %p,[qdisc %p],new %p,old %p)
  ",
  		 __func__, sch, p, new, old);
486b53e59   Thomas Graf   [PKT_SCHED]: make...
66
67
  
  	if (new == NULL) {
3511c9132   Changli Gao   net_sched: remove...
68
  		new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
a38a98821   Alexander Aring   net: sch: api: ad...
69
  					sch->handle, NULL);
486b53e59   Thomas Graf   [PKT_SCHED]: make...
70
71
72
  		if (new == NULL)
  			new = &noop_qdisc;
  	}
86a7996cc   WANG Cong   net_sched: introd...
73
  	*old = qdisc_replace(sch, new, &p->q);
10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
74
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
77
  static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg)
  {
81da99ed7   Stephen Hemminger   [PKT_SCHED] dsmar...
78
79
  	struct dsmark_qdisc_data *p = qdisc_priv(sch);
  	return p->q;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
  }
143976ce9   WANG Cong   net_sched: remove...
81
  static unsigned long dsmark_find(struct Qdisc *sch, u32 classid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
  {
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
83
  	return TC_H_MIN(classid) + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
  static unsigned long dsmark_bind_filter(struct Qdisc *sch,
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
86
  					unsigned long parent, u32 classid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
  {
143976ce9   WANG Cong   net_sched: remove...
88
89
90
91
92
  	pr_debug("%s(sch %p,[qdisc %p],classid %x)
  ",
  		 __func__, sch, qdisc_priv(sch), classid);
  
  	return dsmark_find(sch, classid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
  }
143976ce9   WANG Cong   net_sched: remove...
94
  static void dsmark_unbind_filter(struct Qdisc *sch, unsigned long cl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
  {
  }
27a3421e4   Patrick McHardy   [NET_SCHED]: Use ...
97
98
99
100
101
102
103
  static const struct nla_policy dsmark_policy[TCA_DSMARK_MAX + 1] = {
  	[TCA_DSMARK_INDICES]		= { .type = NLA_U16 },
  	[TCA_DSMARK_DEFAULT_INDEX]	= { .type = NLA_U16 },
  	[TCA_DSMARK_SET_TC_INDEX]	= { .type = NLA_FLAG },
  	[TCA_DSMARK_MASK]		= { .type = NLA_U8 },
  	[TCA_DSMARK_VALUE]		= { .type = NLA_U8 },
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
793d81d6a   Alexander Aring   net: sched: sch: ...
105
106
  			 struct nlattr **tca, unsigned long *arg,
  			 struct netlink_ext_ack *extack)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
  {
81da99ed7   Stephen Hemminger   [PKT_SCHED] dsmar...
108
  	struct dsmark_qdisc_data *p = qdisc_priv(sch);
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
109
110
  	struct nlattr *opt = tca[TCA_OPTIONS];
  	struct nlattr *tb[TCA_DSMARK_MAX + 1];
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
111
  	int err = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112

c76f2a2c4   Yang Yingliang   sch_dsmark: use c...
113
114
115
  	pr_debug("%s(sch %p,[qdisc %p],classid %x,parent %x), arg 0x%lx
  ",
  		 __func__, sch, p, classid, parent, *arg);
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
116
117
118
  
  	if (!dsmark_valid_index(p, *arg)) {
  		err = -ENOENT;
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
119
  		goto errout;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121

cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
122
  	if (!opt)
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
123
  		goto errout;
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
124

8cb081746   Johannes Berg   netlink: make val...
125
126
  	err = nla_parse_nested_deprecated(tb, TCA_DSMARK_MAX, opt,
  					  dsmark_policy, NULL);
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
127
  	if (err < 0)
27a3421e4   Patrick McHardy   [NET_SCHED]: Use ...
128
  		goto errout;
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
129

27a3421e4   Patrick McHardy   [NET_SCHED]: Use ...
130
  	if (tb[TCA_DSMARK_VALUE])
47bbbb30b   Eric Dumazet   sch_dsmark: impro...
131
  		p->mv[*arg - 1].value = nla_get_u8(tb[TCA_DSMARK_VALUE]);
10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
132

1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
133
  	if (tb[TCA_DSMARK_MASK])
47bbbb30b   Eric Dumazet   sch_dsmark: impro...
134
  		p->mv[*arg - 1].mask = nla_get_u8(tb[TCA_DSMARK_MASK]);
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
135
136
  
  	err = 0;
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
137
  errout:
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
138
139
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140

af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
141
  static int dsmark_delete(struct Qdisc *sch, unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
  {
81da99ed7   Stephen Hemminger   [PKT_SCHED] dsmar...
143
  	struct dsmark_qdisc_data *p = qdisc_priv(sch);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144

af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
145
  	if (!dsmark_valid_index(p, arg))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
  		return -EINVAL;
10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
147

47bbbb30b   Eric Dumazet   sch_dsmark: impro...
148
149
  	p->mv[arg - 1].mask = 0xff;
  	p->mv[arg - 1].value = 0;
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
150

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
152
  	return 0;
  }
9d127fbdd   Stephen Hemminger   [PKT_SCHED] dsmar...
153
  static void dsmark_walk(struct Qdisc *sch, struct qdisc_walker *walker)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
  {
81da99ed7   Stephen Hemminger   [PKT_SCHED] dsmar...
155
  	struct dsmark_qdisc_data *p = qdisc_priv(sch);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
  	int i;
c76f2a2c4   Yang Yingliang   sch_dsmark: use c...
157
158
159
  	pr_debug("%s(sch %p,[qdisc %p],walker %p)
  ",
  		 __func__, sch, p, walker);
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
160

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
  	if (walker->stop)
  		return;
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
163

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
  	for (i = 0; i < p->indices; i++) {
47bbbb30b   Eric Dumazet   sch_dsmark: impro...
165
  		if (p->mv[i].mask == 0xff && !p->mv[i].value)
0451eb074   Thomas Graf   [PKT_SCHED]: Fix ...
166
  			goto ignore;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
  		if (walker->count >= walker->skip) {
cc7ec456f   Eric Dumazet   net_sched: cleanups
168
  			if (walker->fn(sch, i + 1, walker) < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
170
171
172
  				walker->stop = 1;
  				break;
  			}
  		}
10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
173
  ignore:
0451eb074   Thomas Graf   [PKT_SCHED]: Fix ...
174
  		walker->count++;
10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
175
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  }
cbaacc4e8   Alexander Aring   net: sched: sch: ...
177
178
  static struct tcf_block *dsmark_tcf_block(struct Qdisc *sch, unsigned long cl,
  					  struct netlink_ext_ack *extack)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  {
81da99ed7   Stephen Hemminger   [PKT_SCHED] dsmar...
180
  	struct dsmark_qdisc_data *p = qdisc_priv(sch);
6529eaba3   Jiri Pirko   net: sched: intro...
181
182
  
  	return p->block;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
  /* --------------------------- Qdisc operations ---------------------------- */
520ac30f4   Eric Dumazet   net_sched: drop p...
185
186
  static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch,
  			  struct sk_buff **to_free)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
  {
f6bab1993   Toke Høiland-Jørgensen   sched: Avoid dere...
188
  	unsigned int len = qdisc_pkt_len(skb);
81da99ed7   Stephen Hemminger   [PKT_SCHED] dsmar...
189
  	struct dsmark_qdisc_data *p = qdisc_priv(sch);
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
190
  	int err;
c76f2a2c4   Yang Yingliang   sch_dsmark: use c...
191
192
  	pr_debug("%s(skb %p,sch %p,[qdisc %p])
  ", __func__, skb, sch, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
  	if (p->set_tc_index) {
aea92fb2e   Eric Dumazet   sch_dsmark: fix i...
195
  		int wlen = skb_network_offset(skb);
d7bf2ebeb   Toke Høiland-Jørgensen   sched: consistent...
196
  		switch (skb_protocol(skb, true)) {
606780404   Arnaldo Carvalho de Melo   net: Use hton[sl]...
197
  		case htons(ETH_P_IP):
aea92fb2e   Eric Dumazet   sch_dsmark: fix i...
198
199
200
  			wlen += sizeof(struct iphdr);
  			if (!pskb_may_pull(skb, wlen) ||
  			    skb_try_make_writable(skb, wlen))
9d127fbdd   Stephen Hemminger   [PKT_SCHED] dsmar...
201
  				goto drop;
4c30719f4   Stephen Hemminger   [PKT_SCHED] dsmar...
202

9d127fbdd   Stephen Hemminger   [PKT_SCHED] dsmar...
203
204
205
  			skb->tc_index = ipv4_get_dsfield(ip_hdr(skb))
  				& ~INET_ECN_MASK;
  			break;
4c30719f4   Stephen Hemminger   [PKT_SCHED] dsmar...
206

606780404   Arnaldo Carvalho de Melo   net: Use hton[sl]...
207
  		case htons(ETH_P_IPV6):
aea92fb2e   Eric Dumazet   sch_dsmark: fix i...
208
209
210
  			wlen += sizeof(struct ipv6hdr);
  			if (!pskb_may_pull(skb, wlen) ||
  			    skb_try_make_writable(skb, wlen))
9d127fbdd   Stephen Hemminger   [PKT_SCHED] dsmar...
211
  				goto drop;
4c30719f4   Stephen Hemminger   [PKT_SCHED] dsmar...
212

9d127fbdd   Stephen Hemminger   [PKT_SCHED] dsmar...
213
214
215
216
217
218
  			skb->tc_index = ipv6_get_dsfield(ipv6_hdr(skb))
  				& ~INET_ECN_MASK;
  			break;
  		default:
  			skb->tc_index = 0;
  			break;
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
219
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
  	}
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
221
222
  
  	if (TC_H_MAJ(skb->priority) == sch->handle)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
  		skb->tc_index = TC_H_MIN(skb->priority);
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
224
225
  	else {
  		struct tcf_result res;
25d8c0d55   John Fastabend   net: rcu-ify tcf_...
226
  		struct tcf_proto *fl = rcu_dereference_bh(p->filter_list);
87d83093b   Jiri Pirko   net: sched: move ...
227
  		int result = tcf_classify(skb, fl, &res, false);
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
228

81da99ed7   Stephen Hemminger   [PKT_SCHED] dsmar...
229
230
  		pr_debug("result %d class 0x%04x
  ", result, res.classid);
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
231

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
  		switch (result) {
f6853e2df   Patrick McHardy   [NET_SCHED]: sch_...
233
234
235
  #ifdef CONFIG_NET_CLS_ACT
  		case TC_ACT_QUEUED:
  		case TC_ACT_STOLEN:
e25ea21ff   Jiri Pirko   net: sched: intro...
236
  		case TC_ACT_TRAP:
520ac30f4   Eric Dumazet   net_sched: drop p...
237
  			__qdisc_drop(skb, to_free);
378a2f090   Jarek Poplawski   net_sched: Add qd...
238
  			return NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
4c30719f4   Stephen Hemminger   [PKT_SCHED] dsmar...
239

f6853e2df   Patrick McHardy   [NET_SCHED]: sch_...
240
  		case TC_ACT_SHOT:
4c30719f4   Stephen Hemminger   [PKT_SCHED] dsmar...
241
  			goto drop;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
  #endif
c3bc7cff8   Patrick McHardy   [NET_SCHED]: Kill...
243
  		case TC_ACT_OK:
f6853e2df   Patrick McHardy   [NET_SCHED]: sch_...
244
245
  			skb->tc_index = TC_H_MIN(res.classid);
  			break;
4c30719f4   Stephen Hemminger   [PKT_SCHED] dsmar...
246

f6853e2df   Patrick McHardy   [NET_SCHED]: sch_...
247
248
249
250
  		default:
  			if (p->default_index != NO_DEFAULT_INDEX)
  				skb->tc_index = p->default_index;
  			break;
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
251
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253

520ac30f4   Eric Dumazet   net_sched: drop p...
254
  	err = qdisc_enqueue(skb, p->q, to_free);
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
255
  	if (err != NET_XMIT_SUCCESS) {
378a2f090   Jarek Poplawski   net_sched: Add qd...
256
  		if (net_xmit_drop_count(err))
25331d6ce   John Fastabend   net: sched: imple...
257
  			qdisc_qstats_drop(sch);
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
258
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
  	}
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
260

f6bab1993   Toke Høiland-Jørgensen   sched: Avoid dere...
261
  	sch->qstats.backlog += len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
  	sch->q.qlen++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263

af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
264
  	return NET_XMIT_SUCCESS;
4c30719f4   Stephen Hemminger   [PKT_SCHED] dsmar...
265
266
  
  drop:
520ac30f4   Eric Dumazet   net_sched: drop p...
267
  	qdisc_drop(skb, sch, to_free);
c27f339af   Jarek Poplawski   net_sched: Add qd...
268
  	return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
269
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
271
272
  
  static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
  {
81da99ed7   Stephen Hemminger   [PKT_SCHED] dsmar...
273
  	struct dsmark_qdisc_data *p = qdisc_priv(sch);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
  	struct sk_buff *skb;
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
275
  	u32 index;
c76f2a2c4   Yang Yingliang   sch_dsmark: use c...
276
277
  	pr_debug("%s(sch %p,[qdisc %p])
  ", __func__, sch, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278

f8b33d8e8   Kyeong Yoo   net_sched: dsmark...
279
  	skb = qdisc_dequeue_peeked(p->q);
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
280
  	if (skb == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
  		return NULL;
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
282

9190b3b32   Eric Dumazet   net_sched: accura...
283
  	qdisc_bstats_update(sch, skb);
bdf17661f   WANG Cong   sch_dsmark: updat...
284
  	qdisc_qstats_backlog_dec(sch, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
  	sch->q.qlen--;
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
286
287
  
  	index = skb->tc_index & (p->indices - 1);
81da99ed7   Stephen Hemminger   [PKT_SCHED] dsmar...
288
289
  	pr_debug("index %d->%d
  ", skb->tc_index, index);
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
290

d7bf2ebeb   Toke Høiland-Jørgensen   sched: consistent...
291
  	switch (skb_protocol(skb, true)) {
606780404   Arnaldo Carvalho de Melo   net: Use hton[sl]...
292
  	case htons(ETH_P_IP):
47bbbb30b   Eric Dumazet   sch_dsmark: impro...
293
294
  		ipv4_change_dsfield(ip_hdr(skb), p->mv[index].mask,
  				    p->mv[index].value);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
  			break;
606780404   Arnaldo Carvalho de Melo   net: Use hton[sl]...
296
  	case htons(ETH_P_IPV6):
47bbbb30b   Eric Dumazet   sch_dsmark: impro...
297
298
  		ipv6_change_dsfield(ipv6_hdr(skb), p->mv[index].mask,
  				    p->mv[index].value);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
  			break;
9d127fbdd   Stephen Hemminger   [PKT_SCHED] dsmar...
300
301
302
303
304
305
  	default:
  		/*
  		 * Only complain if a change was actually attempted.
  		 * This way, we can send non-IP traffic through dsmark
  		 * and don't need yet another qdisc as a bypass.
  		 */
47bbbb30b   Eric Dumazet   sch_dsmark: impro...
306
  		if (p->mv[index].mask != 0xff || p->mv[index].value)
c76f2a2c4   Yang Yingliang   sch_dsmark: use c...
307
308
  			pr_warn("%s: unsupported protocol %d
  ",
d7bf2ebeb   Toke Høiland-Jørgensen   sched: consistent...
309
  				__func__, ntohs(skb_protocol(skb, true)));
9d127fbdd   Stephen Hemminger   [PKT_SCHED] dsmar...
310
  		break;
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
311
  	}
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
312

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
314
  	return skb;
  }
8e3af9789   Jarek Poplawski   pkt_sched: Add qd...
315
316
317
  static struct sk_buff *dsmark_peek(struct Qdisc *sch)
  {
  	struct dsmark_qdisc_data *p = qdisc_priv(sch);
c76f2a2c4   Yang Yingliang   sch_dsmark: use c...
318
319
  	pr_debug("%s(sch %p,[qdisc %p])
  ", __func__, sch, p);
8e3af9789   Jarek Poplawski   pkt_sched: Add qd...
320
321
322
  
  	return p->q->ops->peek(p->q);
  }
e63d7dfd2   Alexander Aring   net: sched: sch: ...
323
324
  static int dsmark_init(struct Qdisc *sch, struct nlattr *opt,
  		       struct netlink_ext_ack *extack)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  {
81da99ed7   Stephen Hemminger   [PKT_SCHED] dsmar...
326
  	struct dsmark_qdisc_data *p = qdisc_priv(sch);
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
327
  	struct nlattr *tb[TCA_DSMARK_MAX + 1];
9d4f97f97   David S. Miller   sch_dsmark: Fix u...
328
  	int err = -EINVAL;
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
329
330
  	u32 default_index = NO_DEFAULT_INDEX;
  	u16 indices;
47bbbb30b   Eric Dumazet   sch_dsmark: impro...
331
  	int i;
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
332

c76f2a2c4   Yang Yingliang   sch_dsmark: use c...
333
334
  	pr_debug("%s(sch %p,[qdisc %p],opt %p)
  ", __func__, sch, p, opt);
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
335

cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
336
337
  	if (!opt)
  		goto errout;
8d1a77f97   Alexander Aring   net: sch: api: ad...
338
  	err = tcf_block_get(&p->block, &p->filter_list, sch, extack);
6529eaba3   Jiri Pirko   net: sched: intro...
339
340
  	if (err)
  		return err;
8cb081746   Johannes Berg   netlink: make val...
341
342
  	err = nla_parse_nested_deprecated(tb, TCA_DSMARK_MAX, opt,
  					  dsmark_policy, NULL);
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
343
  	if (err < 0)
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
344
  		goto errout;
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
345
  	err = -EINVAL;
474f0813a   Eric Dumazet   sch_dsmark: fix p...
346
347
  	if (!tb[TCA_DSMARK_INDICES])
  		goto errout;
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
348
  	indices = nla_get_u16(tb[TCA_DSMARK_INDICES]);
5b0ac72bc   David S. Miller   [PKT_SCHED] dsmar...
349
350
  
  	if (hweight32(indices) != 1)
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
351
  		goto errout;
27a3421e4   Patrick McHardy   [NET_SCHED]: Use ...
352
  	if (tb[TCA_DSMARK_DEFAULT_INDEX])
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
353
  		default_index = nla_get_u16(tb[TCA_DSMARK_DEFAULT_INDEX]);
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
354

47bbbb30b   Eric Dumazet   sch_dsmark: impro...
355
356
357
358
359
  	if (indices <= DSMARK_EMBEDDED_SZ)
  		p->mv = p->embedded;
  	else
  		p->mv = kmalloc_array(indices, sizeof(*p->mv), GFP_KERNEL);
  	if (!p->mv) {
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
360
361
  		err = -ENOMEM;
  		goto errout;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
  	}
47bbbb30b   Eric Dumazet   sch_dsmark: impro...
363
364
365
366
  	for (i = 0; i < indices; i++) {
  		p->mv[i].mask = 0xff;
  		p->mv[i].value = 0;
  	}
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
367
368
  	p->indices = indices;
  	p->default_index = default_index;
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
369
  	p->set_tc_index = nla_get_flag(tb[TCA_DSMARK_SET_TC_INDEX]);
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
370

a38a98821   Alexander Aring   net: sch: api: ad...
371
372
  	p->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, sch->handle,
  				 NULL);
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
373
  	if (p->q == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
  		p->q = &noop_qdisc;
49b499718   Jiri Kosina   net: sched: make ...
375
376
  	else
  		qdisc_hash_add(p->q, true);
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
377

c76f2a2c4   Yang Yingliang   sch_dsmark: use c...
378
379
  	pr_debug("%s: qdisc %p
  ", __func__, p->q);
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
380
381
382
  
  	err = 0;
  errout:
758cc43c6   Thomas Graf   [PKT_SCHED]: Fix ...
383
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385
386
  static void dsmark_reset(struct Qdisc *sch)
  {
81da99ed7   Stephen Hemminger   [PKT_SCHED] dsmar...
387
  	struct dsmark_qdisc_data *p = qdisc_priv(sch);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388

c76f2a2c4   Yang Yingliang   sch_dsmark: use c...
389
390
  	pr_debug("%s(sch %p,[qdisc %p])
  ", __func__, sch, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
  	qdisc_reset(p->q);
bdf17661f   WANG Cong   sch_dsmark: updat...
392
  	sch->qstats.backlog = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
  	sch->q.qlen = 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
396
  static void dsmark_destroy(struct Qdisc *sch)
  {
81da99ed7   Stephen Hemminger   [PKT_SCHED] dsmar...
397
  	struct dsmark_qdisc_data *p = qdisc_priv(sch);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398

c76f2a2c4   Yang Yingliang   sch_dsmark: use c...
399
400
  	pr_debug("%s(sch %p,[qdisc %p])
  ", __func__, sch, p);
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
401

6529eaba3   Jiri Pirko   net: sched: intro...
402
  	tcf_block_put(p->block);
86bd446b5   Vlad Buslov   net: sched: renam...
403
  	qdisc_put(p->q);
47bbbb30b   Eric Dumazet   sch_dsmark: impro...
404
405
  	if (p->mv != p->embedded)
  		kfree(p->mv);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
  static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl,
02f23f095   Thomas Graf   [PKT_SCHED]: Make...
408
  			     struct sk_buff *skb, struct tcmsg *tcm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
  {
81da99ed7   Stephen Hemminger   [PKT_SCHED] dsmar...
410
  	struct dsmark_qdisc_data *p = qdisc_priv(sch);
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
411
  	struct nlattr *opts = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412

c76f2a2c4   Yang Yingliang   sch_dsmark: use c...
413
414
  	pr_debug("%s(sch %p,[qdisc %p],class %ld
  ", __func__, sch, p, cl);
02f23f095   Thomas Graf   [PKT_SCHED]: Make...
415
416
  
  	if (!dsmark_valid_index(p, cl))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
  		return -EINVAL;
02f23f095   Thomas Graf   [PKT_SCHED]: Make...
418

cc7ec456f   Eric Dumazet   net_sched: cleanups
419
  	tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl - 1);
cdc7f8e36   Patrick McHardy   [PKT_SCHED]: Dump...
420
  	tcm->tcm_info = p->q->handle;
02f23f095   Thomas Graf   [PKT_SCHED]: Make...
421

ae0be8de9   Michal Kubecek   netlink: make nla...
422
  	opts = nla_nest_start_noflag(skb, TCA_OPTIONS);
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
423
424
  	if (opts == NULL)
  		goto nla_put_failure;
47bbbb30b   Eric Dumazet   sch_dsmark: impro...
425
426
  	if (nla_put_u8(skb, TCA_DSMARK_MASK, p->mv[cl - 1].mask) ||
  	    nla_put_u8(skb, TCA_DSMARK_VALUE, p->mv[cl - 1].value))
1b34ec43c   David S. Miller   pkt_sched: Stop u...
427
  		goto nla_put_failure;
02f23f095   Thomas Graf   [PKT_SCHED]: Make...
428

1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
429
  	return nla_nest_end(skb, opts);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430

1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
431
  nla_put_failure:
bc3ed28ca   Thomas Graf   netlink: Improve ...
432
433
  	nla_nest_cancel(skb, opts);
  	return -EMSGSIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
435
436
437
  }
  
  static int dsmark_dump(struct Qdisc *sch, struct sk_buff *skb)
  {
81da99ed7   Stephen Hemminger   [PKT_SCHED] dsmar...
438
  	struct dsmark_qdisc_data *p = qdisc_priv(sch);
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
439
  	struct nlattr *opts = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440

ae0be8de9   Michal Kubecek   netlink: make nla...
441
  	opts = nla_nest_start_noflag(skb, TCA_OPTIONS);
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
442
443
  	if (opts == NULL)
  		goto nla_put_failure;
1b34ec43c   David S. Miller   pkt_sched: Stop u...
444
445
  	if (nla_put_u16(skb, TCA_DSMARK_INDICES, p->indices))
  		goto nla_put_failure;
02f23f095   Thomas Graf   [PKT_SCHED]: Make...
446

1b34ec43c   David S. Miller   pkt_sched: Stop u...
447
448
449
  	if (p->default_index != NO_DEFAULT_INDEX &&
  	    nla_put_u16(skb, TCA_DSMARK_DEFAULT_INDEX, p->default_index))
  		goto nla_put_failure;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450

1b34ec43c   David S. Miller   pkt_sched: Stop u...
451
452
453
  	if (p->set_tc_index &&
  	    nla_put_flag(skb, TCA_DSMARK_SET_TC_INDEX))
  		goto nla_put_failure;
02f23f095   Thomas Graf   [PKT_SCHED]: Make...
454

1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
455
  	return nla_nest_end(skb, opts);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456

1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
457
  nla_put_failure:
bc3ed28ca   Thomas Graf   netlink: Improve ...
458
459
  	nla_nest_cancel(skb, opts);
  	return -EMSGSIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
  }
20fea08b5   Eric Dumazet   [NET]: Move Qdisc...
461
  static const struct Qdisc_class_ops dsmark_class_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
463
  	.graft		=	dsmark_graft,
  	.leaf		=	dsmark_leaf,
143976ce9   WANG Cong   net_sched: remove...
464
  	.find		=	dsmark_find,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
467
  	.change		=	dsmark_change,
  	.delete		=	dsmark_delete,
  	.walk		=	dsmark_walk,
6529eaba3   Jiri Pirko   net: sched: intro...
468
  	.tcf_block	=	dsmark_tcf_block,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
  	.bind_tcf	=	dsmark_bind_filter,
143976ce9   WANG Cong   net_sched: remove...
470
  	.unbind_tcf	=	dsmark_unbind_filter,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
471
472
  	.dump		=	dsmark_dump_class,
  };
20fea08b5   Eric Dumazet   [NET]: Move Qdisc...
473
  static struct Qdisc_ops dsmark_qdisc_ops __read_mostly = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
476
477
478
479
  	.next		=	NULL,
  	.cl_ops		=	&dsmark_class_ops,
  	.id		=	"dsmark",
  	.priv_size	=	sizeof(struct dsmark_qdisc_data),
  	.enqueue	=	dsmark_enqueue,
  	.dequeue	=	dsmark_dequeue,
8e3af9789   Jarek Poplawski   pkt_sched: Add qd...
480
  	.peek		=	dsmark_peek,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
483
484
485
486
487
488
489
490
491
492
  	.init		=	dsmark_init,
  	.reset		=	dsmark_reset,
  	.destroy	=	dsmark_destroy,
  	.change		=	NULL,
  	.dump		=	dsmark_dump,
  	.owner		=	THIS_MODULE,
  };
  
  static int __init dsmark_module_init(void)
  {
  	return register_qdisc(&dsmark_qdisc_ops);
  }
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
493

10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
494
  static void __exit dsmark_module_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495
496
497
  {
  	unregister_qdisc(&dsmark_qdisc_ops);
  }
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
498

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
500
  module_init(dsmark_module_init)
  module_exit(dsmark_module_exit)
af0d11417   Thomas Graf   [PKT_SCHED]: Logi...
501

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
  MODULE_LICENSE("GPL");