# 實驗: 封包排程與 QoS

這個實驗的目標是希望可以得到目前封包的排程狀況，因此，我們就可以知道下一個要傳出去的封包是要傳送給哪一個裝置。不過，一直沒有找到相關的資訊，倒是找到 Linux 中如何管理資料封包排程的資訊，記錄在此，作為之後參考。

從 Linux 的角度出發，說到封包排程直覺會想到 Queueing Discipline (QDisc) 這個指令，不過，查詢該指令和 OpenWRT 相關的資料後，多數的應用都在 QoS 的控制以及流量限制。在 OpenWRT 官方網站上可以找到以下兩篇資訊:

1. <https://wiki.openwrt.org/doc/howto/packet.scheduler/packet.scheduler.theory>
2. <https://wiki.openwrt.org/doc/howto/packet.scheduler/packet.scheduler>

按照所提供的資訊，我們可以先查看 OpenWRT 上的 QDisc 設定，如下所示:

```
root@GL-AR750S:~# tc qdisc show
qdisc noqueue 0: dev lo root refcnt 2
qdisc fq_codel 0: dev eth0 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 4Mb ecn
qdisc noqueue 0: dev br-lan root refcnt 2
qdisc noqueue 0: dev eth0.1 root refcnt 2
qdisc noqueue 0: dev eth0.2 root refcnt 2
qdisc noqueue 0: dev wlan1-2 root refcnt 2
qdisc noqueue 0: dev wlan0-2 root refcnt 2
qdisc noqueue 0: dev wlan1 root refcnt 2
qdisc noqueue 0: dev wlan0 root refcnt 2
```

看起來的確可以看到所有有限和無線的介面，同時，我們可以注意`eth0`的設定，在`eth0`上設定了額外的流量限制，這也是 QDisc 在 OpenWRT 上常見的應用。然而，若我們進一步去查詢每一個裝置的資訊，我們可以得到以下的成果:

```
root@GL-AR750S:~# tc -s qdisc show dev eth0
qdisc fq_codel 0: root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 4Mb ecn
 Sent 1922621977 bytes 15414519 pkts (dropped 0, overlimits 0)
  maxpacket 1456 drop_overlimit 0 new_flow_count 447 ecn_mark 0
  new_flows_len 0 old_flows_len 0
root@GL-AR750S:~# tc -s qdisc show dev wlan0
qdisc noqueue 0: root refcnt 2
 Sent 0 bytes 0 pkts (dropped 0, overlimits 0)
root@GL-AR750S:~# tc -s qdisc show dev wlan1
qdisc noqueue 0: root refcnt 2
 Sent 0 bytes 0 pkts (dropped 0, overlimits 0)
```

對`eth0`而言，可以看到封包的統計量，但仍然看不到詳細的封包排程，而對 `wlan0` 和 `wlan1` 兩張網卡而言，卻沒有任何資訊，這是因為在這兩張網卡上並沒有定義相對應的規則。我們先在`wlan0`上加上一個 QDisc 試試看，指令為:

```
tc qdisc add dev wlan0 root handle 1: htb default 20
```

此時，再執行查詢，可以得到以下的結果:

```
root@GL-AR750S:~# tc qdisc show
qdisc noqueue 0: dev lo root refcnt 2
qdisc fq_codel 0: dev eth0 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 4Mb ecn
qdisc noqueue 0: dev br-lan root refcnt 2
qdisc noqueue 0: dev eth0.1 root refcnt 2
qdisc noqueue 0: dev eth0.2 root refcnt 2
qdisc noqueue 0: dev wlan1-2 root refcnt 2
qdisc noqueue 0: dev wlan0-2 root refcnt 2
qdisc noqueue 0: dev wlan1 root refcnt 2
qdisc htb 1: dev wlan0 root refcnt 5 r2q 10 default 32 direct_packets_stat 0 direct_qlen 1000
```

可以看到此時`wlan0`已經連上一個 QDisc 物件 (`htb1`)，我們可以藉由更改此物件，來對網路進行限流或是塑型，當一個 WiFi AP 服務多個無線網路時，這是十分好用的功能。同時，當我們查詢`wlan0`的資訊時，就可以看到查詢的結果。

```
root@GL-AR750S:~# tc -s qdisc show dev wlan0
qdisc htb 1: root refcnt 5 r2q 10 default 32 direct_packets_stat 201 direct_qlen 1000
 Sent 31945 bytes 201 pkts (dropped 0, overlimits 0)
```

此時，我們可以看到封包的統計量，但仍然看不到詳細的封包排程。若有興趣進行 QDisc 的設計，可以進一步參考以下資訊:

* <http://puremonkey2010.blogspot.com/2015/01/linux-tc-traffic-control.html>
* <http://shofan.blogspot.com/2017/08/linux-tctraffic-control.html>
* <http://shofan.blogspot.com/2017/08/linux-tctraffic-control2.html>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://openwrt-nctu.gitbook.io/project/openwrt-functions/openwrt-qos-scheduling.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
