2 * Copyright 2004, Instant802 Networks, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
9 #include <linux/config.h>
10 #include <linux/version.h>
11 #include <linux/netdevice.h>
12 #include <linux/skbuff.h>
13 #include <linux/module.h>
16 #include <net/ieee80211.h>
17 #include "ieee80211_i.h"
20 #define CHILD_QDISC_OPS pfifo_qdisc_ops
22 static inline int WLAN_FC_IS_QOS_DATA(u16 fc
)
24 return (fc
& 0x8C) == 0x88;
29 ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data
*rx
)
31 u8
*data
= rx
->skb
->data
;
34 /* does the frame have a qos control field? */
35 if (WLAN_FC_IS_QOS_DATA(rx
->fc
)) {
36 u8
*qc
= data
+ ieee80211_get_hdrlen(rx
->fc
) - QOS_CONTROL_LEN
;
37 /* frame has qos control */
38 tid
= qc
[0] & QOS_CONTROL_TID_MASK
;
40 if (unlikely(WLAN_FC_GET_TYPE(rx
->fc
) == WLAN_FC_TYPE_MGMT
)) {
41 /* Separate TID for management frames */
42 tid
= NUM_RX_DATA_QUEUES
- 1;
44 /* no qos control present */
45 tid
= 0; /* 802.1d - Best Effort */
48 #ifdef CONFIG_IEEE80211_DEBUG_COUNTERS
49 I802_DEBUG_INC(rx
->local
->wme_rx_queue
[tid
]);
51 I802_DEBUG_INC(rx
->sta
->wme_rx_queue
[tid
]);
53 #endif /* CONFIG_IEEE80211_DEBUG_COUNTERS */
56 /* Set skb->priority to 1d tag if highest order bit of TID is not set.
57 * For now, set skb->priority to 0 for other cases. */
58 rx
->skb
->priority
= (tid
> 7) ? 0 : tid
;
65 ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data
*rx
)
68 u8
*data
= rx
->skb
->data
;
69 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*) data
;
71 if (!WLAN_FC_IS_QOS_DATA(fc
))
74 /* remove the qos control field, update frame type and meta-data */
75 memmove(data
+ 2, data
, ieee80211_get_hdrlen(fc
) - 2);
76 hdr
= (struct ieee80211_hdr
*) skb_pull(rx
->skb
, 2);
77 /* change frame type to non QOS */
78 rx
->fc
= fc
&= ~(WLAN_FC_STYPE_QOS_DATA
<< 4);
79 hdr
->frame_control
= cpu_to_le16(fc
);
85 /* maximum number of hardware queues we support. */
86 #define TC_80211_MAX_QUEUES 8
88 struct ieee80211_sched_data
90 struct tcf_proto
*filter_list
;
91 struct Qdisc
*queues
[TC_80211_MAX_QUEUES
];
92 struct sk_buff_head requeued
[TC_80211_MAX_QUEUES
];
96 /* given a data frame determine the 802.1p/1d tag to use */
97 static inline unsigned classify_1d(struct sk_buff
*skb
, struct Qdisc
*qd
)
103 #ifdef CONFIG_NET_SCHED
104 struct ieee80211_sched_data
*q
= qdisc_priv(qd
);
105 struct tcf_result res
= { -1, 0 };
107 /* if there is a user set filter list, call out to that */
108 if (q
->filter_list
) {
109 tc_classify(skb
, q
->filter_list
, &res
);
113 #endif /* CONFIG_NET_SCHED */
115 /* skb->priority values from 256->263 are magic values to
116 * directly indicate a specific 802.1d priority.
117 * This is used to allow 802.1d priority to be passed directly in
118 * from VLAN tags, etc. */
119 if (skb
->priority
>= 256 && skb
->priority
<= 263)
120 return skb
->priority
- 256;
122 /* check there is a valid IP header present */
123 offset
= ieee80211_get_hdrlen_from_skb(skb
) + 8 /* LLC + proto */;
124 if (skb
->protocol
!= __constant_htons(ETH_P_IP
) ||
125 skb
->len
< offset
+ sizeof(*ip
))
128 ip
= (struct iphdr
*) (skb
->data
+ offset
);
130 dscp
= ip
->tos
& 0xfc;
154 static inline int wme_downgrade_ac(struct sk_buff
*skb
)
156 switch (skb
->priority
) {
159 skb
->priority
= 5; /* VO -> VI */
163 skb
->priority
= 3; /* VI -> BE */
167 skb
->priority
= 2; /* BE -> BK */
175 /* positive return value indicates which queue to use
176 * negative return value indicates to drop the frame */
177 static inline int classify80211(struct sk_buff
*skb
, struct Qdisc
*qd
)
179 struct ieee80211_local
*local
= qd
->dev
->priv
;
180 struct ieee80211_tx_packet_data
*pkt_data
=
181 (struct ieee80211_tx_packet_data
*) skb
->cb
;
182 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*) skb
->data
;
183 unsigned short fc
= le16_to_cpu(hdr
->frame_control
);
185 const int ieee802_1d_to_ac
[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
187 if (unlikely(pkt_data
->magic
!= IEEE80211_CB_MAGIC
))
190 /* see if frame is data or non data frame */
191 if (unlikely(WLAN_FC_GET_TYPE(fc
) != WLAN_FC_TYPE_DATA
)) {
192 /* management frames go on AC_VO queue, but are sent
193 * without QoS control fields */
194 return IEEE80211_TX_QUEUE_DATA0
;
197 if (unlikely(pkt_data
->sdata
->type
== IEEE80211_SUB_IF_TYPE_MGMT
)) {
198 /* Data frames from hostapd (mainly, EAPOL) use AC_VO
199 * and they will include QoS control fields if
200 * the target STA is using WME. */
202 return ieee802_1d_to_ac
[skb
->priority
];
206 /* is this a QoS frame? */
207 qos
= fc
& (WLAN_FC_STYPE_QOS_DATA
<< 4);
211 skb
->priority
= 0; /* required for correct WPA/11i MIC */
212 return ieee802_1d_to_ac
[skb
->priority
];
215 /* use the data classifier to determine what 802.1d tag the
217 skb
->priority
= classify_1d(skb
, qd
);
220 /* incase we are a client verify acm is not set for this ac */
221 for (; unlikely(local
->wmm_acm
& BIT(skb
->priority
)); )
223 if (wme_downgrade_ac(skb
)) {
224 /* No AC with lower priority has acm=0,
230 /* look up which queue to use for frames with this 1d tag */
231 return ieee802_1d_to_ac
[skb
->priority
];
235 static int wme_qdiscop_enqueue(struct sk_buff
*skb
, struct Qdisc
* qd
)
237 struct ieee80211_local
*local
= qd
->dev
->priv
;
238 struct ieee80211_sched_data
*q
= qdisc_priv(qd
);
239 struct ieee80211_tx_packet_data
*pkt_data
=
240 (struct ieee80211_tx_packet_data
*) skb
->cb
;
241 struct ieee80211_tx_control
*control
= &pkt_data
->control
;
242 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*) skb
->data
;
243 unsigned short fc
= le16_to_cpu(hdr
->frame_control
);
247 if (control
->requeue
) {
248 skb_queue_tail(&q
->requeued
[control
->queue
], skb
);
252 queue
= classify80211(skb
, qd
);
254 /* now we know the 1d priority, fill in the QoS header if there is one */
255 if (WLAN_FC_IS_QOS_DATA(fc
)) {
256 struct qos_control
*qc
= (struct qos_control
*) (skb
->data
+ ieee80211_get_hdrlen(fc
) - 2);
258 *p
++ = 0; /* do this due to gcc's lack of optimization on bitfield ops */
260 qc
->tag1d
= skb
->priority
;
261 if (local
->wifi_wme_noack_test
)
265 if (unlikely(queue
>= local
->hw
->queues
)) {
267 if (net_ratelimit()) {
268 printk(KERN_DEBUG
"%s - queue=%d (hw does not "
270 __func__
, queue
, local
->hw
->queues
- 1);
273 queue
= local
->hw
->queues
- 1;
276 if (unlikely(queue
< 0)) {
280 control
->queue
= (unsigned int) queue
;
281 qdisc
= q
->queues
[queue
];
282 err
= qdisc
->enqueue(skb
, qdisc
);
283 if (err
== NET_XMIT_SUCCESS
) {
285 qd
->bstats
.bytes
+= skb
->len
;
286 qd
->bstats
.packets
++;
287 return NET_XMIT_SUCCESS
;
295 /* TODO: clean up the cases where master_hard_start_xmit
296 * returns non 0 - it shouldn't ever do that. Once done we
297 * can remove this function */
298 static int wme_qdiscop_requeue(struct sk_buff
*skb
, struct Qdisc
* qd
)
300 struct ieee80211_sched_data
*q
= qdisc_priv(qd
);
301 struct ieee80211_tx_packet_data
*pkt_data
=
302 (struct ieee80211_tx_packet_data
*) skb
->cb
;
306 /* we recorded which queue to use earlier! */
307 qdisc
= q
->queues
[pkt_data
->control
.queue
];
309 if ((err
= qdisc
->ops
->requeue(skb
, qdisc
)) == 0) {
318 static struct sk_buff
*wme_qdiscop_dequeue(struct Qdisc
* qd
)
320 struct ieee80211_sched_data
*q
= qdisc_priv(qd
);
321 struct net_device
*dev
= qd
->dev
;
322 struct ieee80211_local
*local
= dev
->priv
;
323 struct ieee80211_hw
*hw
= local
->hw
;
324 struct ieee80211_tx_queue_stats stats
;
329 /* find which hardware queues have space in them */
330 hw
->get_tx_stats(dev
, &stats
);
332 /* check all the h/w queues in numeric/priority order */
333 for (queue
= 0; queue
< hw
->queues
; queue
++) {
334 /* see if there is room in this hardware queue */
335 if (stats
.data
[queue
].len
>= stats
.data
[queue
].limit
)
338 /* there is space - try and get a frame */
339 skb
= skb_dequeue(&q
->requeued
[queue
]);
343 qdisc
= q
->queues
[queue
];
344 skb
= qdisc
->dequeue(qdisc
);
350 /* returning a NULL here when all the h/w queues are full means we
351 * never need to call netif_stop_queue in the driver */
356 static void wme_qdiscop_reset(struct Qdisc
* qd
)
358 struct ieee80211_sched_data
*q
= qdisc_priv(qd
);
359 struct ieee80211_local
*local
= qd
->dev
->priv
;
360 struct ieee80211_hw
*hw
= local
->hw
;
363 /* QUESTION: should we have some hardware flush functionality here? */
365 for (queue
= 0; queue
< hw
->queues
; queue
++) {
366 skb_queue_purge(&q
->requeued
[queue
]);
367 qdisc_reset(q
->queues
[queue
]);
373 static void wme_qdiscop_destroy(struct Qdisc
* qd
)
375 struct ieee80211_sched_data
*q
= qdisc_priv(qd
);
376 struct ieee80211_local
*local
= qd
->dev
->priv
;
377 struct ieee80211_hw
*hw
= local
->hw
;
378 struct tcf_proto
*tp
;
381 while ((tp
= q
->filter_list
) != NULL
) {
382 q
->filter_list
= tp
->next
;
383 tp
->ops
->destroy(tp
);
386 for (queue
=0; queue
< hw
->queues
; queue
++) {
387 skb_queue_purge(&q
->requeued
[queue
]);
388 qdisc_destroy(q
->queues
[queue
]);
389 q
->queues
[queue
] = &noop_qdisc
;
394 /* called whenever parameters are updated on existing qdisc */
395 static int wme_qdiscop_tune(struct Qdisc
*qd
, struct rtattr
*opt
)
397 /* struct ieee80211_sched_data *q = qdisc_priv(qd);
399 /* check our options block is the right size */
400 /* copy any options to our local structure */
401 /* Ignore options block for now - always use static mapping
402 struct tc_ieee80211_qopt *qopt = RTA_DATA(opt);
404 if (opt->rta_len < RTA_LENGTH(sizeof(*qopt)))
406 memcpy(q->tag2queue, qopt->tag2queue, sizeof(qopt->tag2queue));
412 /* called during initial creation of qdisc on device */
413 static int wme_qdiscop_init(struct Qdisc
*qd
, struct rtattr
*opt
)
415 struct ieee80211_sched_data
*q
= qdisc_priv(qd
);
416 struct net_device
*dev
= qd
->dev
;
417 struct ieee80211_local
*local
= dev
->priv
;
418 int queues
= local
->hw
->queues
;
421 /* check this device is an ieee80211 master type device */
422 if (dev
->type
!= ARPHRD_IEEE80211
)
425 /* check that there is no qdisc currently attached to device
426 * this ensures that we will be the root qdisc. (I can't find a better
427 * way to test this explicitly) */
428 if (dev
->qdisc_sleeping
!= &noop_qdisc
)
431 if (qd
->flags
& TCQ_F_INGRESS
)
434 /* if options were passed in, set them */
436 err
= wme_qdiscop_tune(qd
, opt
);
439 /* create child queues */
440 for (i
= 0; i
< queues
; i
++) {
441 skb_queue_head_init(&q
->requeued
[i
]);
442 q
->queues
[i
] = qdisc_create_dflt(qd
->dev
, &CHILD_QDISC_OPS
);
443 if (q
->queues
[i
] == 0) {
444 q
->queues
[i
] = &noop_qdisc
;
445 printk(KERN_ERR
"%s child qdisc %i creation failed", dev
->name
, i
);
452 static int wme_qdiscop_dump(struct Qdisc
*qd
, struct sk_buff
*skb
)
454 /* struct ieee80211_sched_data *q = qdisc_priv(qd);
455 unsigned char *p = skb->tail;
456 struct tc_ieee80211_qopt opt;
458 memcpy(&opt.tag2queue, q->tag2queue, TC_80211_MAX_TAG + 1);
459 RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
463 skb_trim(skb, p - skb->data);*/
468 static int wme_classop_graft(struct Qdisc
*qd
, unsigned long arg
,
469 struct Qdisc
*new, struct Qdisc
**old
)
471 struct ieee80211_sched_data
*q
= qdisc_priv(qd
);
472 struct ieee80211_local
*local
= qd
->dev
->priv
;
473 struct ieee80211_hw
*hw
= local
->hw
;
474 unsigned long queue
= arg
- 1;
476 if (queue
>= hw
->queues
)
483 *old
= q
->queues
[queue
];
484 q
->queues
[queue
] = new;
492 static struct Qdisc
*
493 wme_classop_leaf(struct Qdisc
*qd
, unsigned long arg
)
495 struct ieee80211_sched_data
*q
= qdisc_priv(qd
);
496 struct ieee80211_local
*local
= qd
->dev
->priv
;
497 struct ieee80211_hw
*hw
= local
->hw
;
498 unsigned long queue
= arg
- 1;
500 if (queue
>= hw
->queues
)
503 return q
->queues
[queue
];
507 static unsigned long wme_classop_get(struct Qdisc
*qd
, u32 classid
)
509 struct ieee80211_local
*local
= qd
->dev
->priv
;
510 struct ieee80211_hw
*hw
= local
->hw
;
511 unsigned long queue
= TC_H_MIN(classid
);
513 if (queue
- 1 >= hw
->queues
)
520 static unsigned long wme_classop_bind(struct Qdisc
*qd
, unsigned long parent
,
523 return wme_classop_get(qd
, classid
);
527 static void wme_classop_put(struct Qdisc
*q
, unsigned long cl
)
529 /* printk(KERN_DEBUG "entering %s\n", __func__); */
533 static int wme_classop_change(struct Qdisc
*qd
, u32 handle
, u32 parent
,
534 struct rtattr
**tca
, unsigned long *arg
)
536 unsigned long cl
= *arg
;
537 struct ieee80211_local
*local
= qd
->dev
->priv
;
538 struct ieee80211_hw
*hw
= local
->hw
;
539 /* printk(KERN_DEBUG "entering %s\n", __func__); */
541 if (cl
- 1 > hw
->queues
)
544 /* TODO: put code to program hardware queue parameters here,
545 * to allow programming from tc command line */
551 /* we don't support deleting hardware queues
552 * when we add WMM-SA support - TSPECs may be deleted here */
553 static int wme_classop_delete(struct Qdisc
*qd
, unsigned long cl
)
555 struct ieee80211_local
*local
= qd
->dev
->priv
;
556 struct ieee80211_hw
*hw
= local
->hw
;
557 /* printk(KERN_DEBUG "entering %s\n", __func__); */
559 if (cl
- 1 > hw
->queues
)
565 static int wme_classop_dump_class(struct Qdisc
*qd
, unsigned long cl
,
566 struct sk_buff
*skb
, struct tcmsg
*tcm
)
568 struct ieee80211_sched_data
*q
= qdisc_priv(qd
);
569 struct ieee80211_local
*local
= qd
->dev
->priv
;
570 struct ieee80211_hw
*hw
= local
->hw
;
571 /* printk(KERN_DEBUG "entering %s\n", __func__); */
573 if (cl
- 1 > hw
->queues
)
575 tcm
->tcm_handle
= TC_H_MIN(cl
);
576 tcm
->tcm_parent
= qd
->handle
;
577 tcm
->tcm_info
= q
->queues
[cl
-1]->handle
; /* do we need this? */
582 static void wme_classop_walk(struct Qdisc
*qd
, struct qdisc_walker
*arg
)
584 struct ieee80211_local
*local
= qd
->dev
->priv
;
585 struct ieee80211_hw
*hw
= local
->hw
;
587 /* printk(KERN_DEBUG "entering %s\n", __func__); */
592 for (queue
= 0; queue
< hw
->queues
; queue
++) {
593 if (arg
->count
< arg
->skip
) {
597 /* we should return classids for our internal queues here
598 * as well as the external ones */
599 if (arg
->fn(qd
, queue
+1, arg
) < 0) {
608 static struct tcf_proto
** wme_classop_find_tcf(struct Qdisc
*qd
,
611 struct ieee80211_sched_data
*q
= qdisc_priv(qd
);
612 /* printk("entering %s\n", __func__); */
617 return &q
->filter_list
;
621 /* this qdisc is classful (i.e. has classes, some of which may have leaf qdiscs attached)
622 * - these are the operations on the classes */
623 static struct Qdisc_class_ops class_ops
=
625 .graft
= wme_classop_graft
,
626 .leaf
= wme_classop_leaf
,
628 .get
= wme_classop_get
,
629 .put
= wme_classop_put
,
630 .change
= wme_classop_change
,
631 .delete = wme_classop_delete
,
632 .walk
= wme_classop_walk
,
634 .tcf_chain
= wme_classop_find_tcf
,
635 .bind_tcf
= wme_classop_bind
,
636 .unbind_tcf
= wme_classop_put
,
638 .dump
= wme_classop_dump_class
,
642 /* queueing discipline operations */
643 static struct Qdisc_ops wme_qdisc_ops
=
646 .cl_ops
= &class_ops
,
648 .priv_size
= sizeof(struct ieee80211_sched_data
),
650 .enqueue
= wme_qdiscop_enqueue
,
651 .dequeue
= wme_qdiscop_dequeue
,
652 .requeue
= wme_qdiscop_requeue
,
653 .drop
= NULL
, /* drop not needed since we are always the root qdisc */
655 .init
= wme_qdiscop_init
,
656 .reset
= wme_qdiscop_reset
,
657 .destroy
= wme_qdiscop_destroy
,
658 .change
= wme_qdiscop_tune
,
660 .dump
= wme_qdiscop_dump
,
664 void ieee80211_install_qdisc(struct net_device
*dev
)
668 qdisc
= qdisc_create_dflt(dev
, &wme_qdisc_ops
);
670 printk(KERN_ERR
"%s: qdisc installation failed\n", dev
->name
);
674 /* same handle as would be allocated by qdisc_alloc_handle() */
675 qdisc
->handle
= 0x80010000;
677 write_lock(&qdisc_tree_lock
);
678 list_add_tail(&qdisc
->list
, &dev
->qdisc_list
);
679 dev
->qdisc_sleeping
= qdisc
;
680 write_unlock(&qdisc_tree_lock
);
684 int ieee80211_wme_register(void)
688 #ifdef CONFIG_NET_SCHED
689 err
= register_qdisc(&wme_qdisc_ops
);
695 void ieee80211_wme_unregister(void)
697 #ifdef CONFIG_NET_SCHED
698 unregister_qdisc(&wme_qdisc_ops
);