-
Notifications
You must be signed in to change notification settings - Fork 20
Bandwidth control #147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bandwidth control #147
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,238 @@ | ||
| # Egress and Ingress Bandwidth Control | ||
| The RTL8372/3 allows to control the bandwidth of data transmitted (egress) and/or | ||
| admitted (ingress) at any given port. Once admitted, packets are internally switched | ||
| at wire-speed, since the backplane of the devices has a bandwidth of 60GBit/s. | ||
|
|
||
| The devices schedules transmission of packets by assigning packets to 8 queues | ||
| implemented in hardware per port, which share a total of 8Mbit of memory internal | ||
| to the switching part of the SoCs. Packets are assigned to the respective queues | ||
| based on the priority assigned to a packet, which can be based on various | ||
| properties of a packet such as IEEE 802.1P priority, DSCP value, physical port | ||
| number, destination or source MAC, Ether-Type-based, CVID, SVID, IPv4 source or | ||
| destination IP, IPv4/IPv6 TOS field, IPv6 Flow Label and even TCP/UDP | ||
| source/destination port. Once in a queue, packets are scheduled for egress | ||
| based on differnent configurable algorithms. | ||
|
|
||
| RTLPlayground currently allows only to control the bandwidth at ingress at a port | ||
| or just before packets leave a port. There is no control of the priority assignment | ||
| or queue scheduling mechanisms. The bandwidth can be controlled in steps of 16Kbit/s | ||
| from 16Kbit/s to 10Gbp/s. | ||
|
|
||
| The bandwidth control as currently implemented allows e.g. to assign a certain | ||
| share of bandwidth to an attached device (e.g. to share an uplink), or simulate | ||
| connections with low bandwidth and even bad connectivity with packet drops when | ||
| ingress is not controlled by Flow Control but by simply droping packets. | ||
|
|
||
| ## Ingress/Egress control | ||
| The relevant registers for controlling Ingress and Egress at a port are: | ||
| ``` | ||
| #define RTL837X_IGBW_CTRL 0x4c10 | ||
| #define IGBW_INC_BYPASS_PKT 0x100 | ||
| #define IGBW_INC_IFG 0x80 | ||
| #define IGBW_ADM_DHCP 0x20 | ||
| #define IGBW_ADM_ARPREQ 0x10 | ||
| #define IGBW_ADM_RMA 0x08 | ||
| #define IGBW_ADM_BPDU 0x04 | ||
| #define IGBW_ADM_RTKPKT 0x02 | ||
| #define IGBW_ADM_IGMP 0x01 | ||
| #define RTL837X_IGBW_PORT_CTRL 0x4C18 | ||
| #define RTL837X_IGBW_PORT_FC_CTRL 0x4C8C | ||
| #define RTL837X_EGBW_PORT_CTRL 0x1c34 | ||
| #define RTL837X_EGBW_CTRL 0x447c | ||
| #define EGBW_INC_IFG 0x02 | ||
| #define EGBW_CPUMODE 0x01 | ||
| ``` | ||
| `RTL837X_IGBW_CTRL/RTL837X_EGBW_CTRL` control the behaviour of the bandwidth control | ||
| at ingress and egress. The flags such as `IGBW_ADM_DHCP`control whether certain types | ||
| of packets such as DHCP are exempt from being ingress controlled. The | ||
| `IGBW_INC_IFG/EGBW_INC_IFG` flags control whether the Inter Frame Gaps are part of | ||
| the bandwidth being controlled. `EGBW_CPUMODE` controls whether packets generated | ||
| by the internal CPU are subject to egress control. | ||
|
|
||
| `RTL837X_IGBW_PORT_CTRL/RTL837X_EGBW_PORT_CTRL` configure the bandwidth for ingress | ||
| and egress at a port. | ||
|
|
||
| `RTL837X_IGBW_PORT_FC_CTRL` configures whether packets are bandwidth-controlled using | ||
| Flow Control (port-bit set), or simply dropped (port-bit clear). | ||
|
|
||
| ## Ingress/Egress bandwidth API | ||
| The code currently provides the following functions: | ||
| ``` | ||
| void bandwidth_setup(void) __banked; | ||
| void bandwidth_ingress_set(uint8_t port, __xdata uint32_t bw) __banked; | ||
| void bandwidth_ingress_disable(uint8_t port) __banked; | ||
| void bandwidth_ingress_drop(uint8_t port) __banked; | ||
| void bandwidth_egress_set(uint8_t port, __xdata uint32_t bw) __banked; | ||
| void bandwidth_egress_disable(uint8_t port) __banked; | ||
| void bandwidth_status(uint8_t port) __banked; | ||
| ```c | ||
|
|
||
| `bandwidth_setup()` is called at boot-time and configures excluding all special packets | ||
| that may be for the CPU and packets outgoing from the CPU to be excluded from bandwidth | ||
| control. IFG is not part of the bandwidth calculation. | ||
|
|
||
| `bandwidth_ingress_set()` enables ingress bandwidth control for a particular port given | ||
| the specified bandwidth. This also enabled Flow Control at a port. | ||
|
|
||
| `bandwidth_ingress_set()` enables egress bandwidth control for a particular port given | ||
| the specified bandwidth | ||
|
|
||
| `bandwidth_ingress_disable() / bandwidth_egress_disable()` disable ingress and egress | ||
| bandwidth control at a given port | ||
|
|
||
| `bandwidth_ingress_drop(port)` configures packets exceeding bandwidth limitations to | ||
| simply be dropped | ||
|
|
||
| `bandwidth_status(port)` shows the current bandwidth control status for a given port | ||
|
|
||
| ## Bandwidth control configuration on the Serial Console | ||
| The following commands are provided on the serial console: | ||
| ``` | ||
| > bw [in|out|status] <port> [<hexvalue>|off|drop] | ||
| Configures or shows the status of bandwidth control | ||
| ``` | ||
| The bandwidth is given as the `<hexvalue>` in Kbit/s. Note that the control is only | ||
| possible at a granularity of 16 Kbit/s and the minimum value is also 16 Kbit/s. The | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's ok at the console to have this granularity of what the chip supports and the unintuitive way of using hex values.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea! In the web-interface configuring and verifying the settings is much easier. I have already a skeleton for the web-page but wanted the basics to be done, first. |
||
| hexadecimal numbers must be given in full bytes, i.e. have an even number of digits. | ||
|
|
||
| To enable bandwidth control of ingress for physical port 2 to be set to 256 Kbit/s | ||
| do: | ||
| ``` | ||
| > bw in 2 0100 | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This implictly enables flow control, which does work only if the link partner enables it too at its RX side. I would make the FlowControl feature configurable explicitly.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, this is a misunderstanding, see above. FC is neither enabled nor disabled. This would not be possible at this level. FC stays on all the time even if not used. BTW: by default it is enabled and used if the link partner enables it. There is no way currently to configure it at the link level. The idea is that like EEE if it works it is good, if not, there is nothing much you can do. So we keep the default for all involved PHYs, which enables it by default. |
||
| ``` | ||
|
|
||
| To drop packets when the bandwidth is exceeeded at port 2 do: | ||
| ``` | ||
| > bw in 2 drop | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the way back, i.e. to enable FLowControl again?
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is maybe a misunderstanding. The bandwidth control does not enable or disable FlowControl. FC is a PHY feature, here we are talking about scheduling even before the MAC layer. The bandwidth control merely uses FC or not. It is not enabling or disabling it. This would require to configure the PHY. I verified it using So drop explicitly stops usage of FC. To enable it again, one can again use Do you want an explicit command/function to enabled/disable use of FC?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, see my comment on |
||
| ``` | ||
|
|
||
| To disable bandwidth control for incoming packets on port 2 do: | ||
| ``` | ||
| > bw in 2 off | ||
| ``` | ||
|
|
||
| ## Bandwidth configuration via the Web Interface | ||
| Not implemented, yet! | ||
|
|
||
| ## A Test using iperf3 | ||
| The following is and example how to test bandwidth control with a signle Linux device using | ||
| network namespaces to route packets between a client and a server on the same Linux device | ||
| through an external switch. | ||
|
|
||
| You will need 2 network intefaces on the linux device, say, 2 USB-Ethernet controllers called | ||
| eth0 and eth1: | ||
| ``` | ||
| $ sudo ip netns add client | ||
| $ sudo ip netns add server | ||
|
|
||
| $ sudo ip link set dev eth0 netns client | ||
| $ sudo ip link set dev eth1 netns server | ||
|
|
||
| $ sudo ip netns exec client ip link set dev eth0 up | ||
| $ sudo ip netns exec server ip link set dev eth1 up | ||
|
|
||
| $ sudo ip netns exec client ip addr add dev eth0 192.168.99.1/24 | ||
| $ sudo ip netns exec server ip addr add dev eth1 192.168.99.2/24 | ||
|
|
||
| $ sudo ip netns exec server iperf3 -s | ||
| ``` | ||
| This will start an iper3 server in the above shell. | ||
|
|
||
| In a different shell you can now run the iperf3 client against your server: | ||
| ``` | ||
| $ sudo ip netns exec client iperf -c 192.168.99.2 | ||
| ``` | ||
| The LEDs on your switch where your network adapters are connected should start to flicker. | ||
| On a 1GBit connection, you should see: | ||
| ``` | ||
| $ sudo ip netns exec client iperf3 -c 192.168.99.2 | ||
| Connecting to host 192.168.99.2, port 5201 | ||
| [ 5] local 192.168.99.1 port 46776 connected to 192.168.99.2 port 5201 | ||
| [ ID] Interval Transfer Bitrate Retr Cwnd | ||
| [ 5] 0.00-1.00 sec 114 MBytes 952 Mbits/sec 0 339 KBytes | ||
| [ 5] 1.00-2.00 sec 113 MBytes 946 Mbits/sec 0 356 KBytes | ||
| [ 5] 2.00-3.00 sec 112 MBytes 937 Mbits/sec 0 390 KBytes | ||
| [ 5] 3.00-4.00 sec 112 MBytes 942 Mbits/sec 0 390 KBytes | ||
| [ 5] 4.00-5.00 sec 112 MBytes 943 Mbits/sec 0 390 KBytes | ||
| [ 5] 5.00-6.00 sec 112 MBytes 944 Mbits/sec 0 390 KBytes | ||
| [ 5] 6.00-7.00 sec 112 MBytes 938 Mbits/sec 0 390 KBytes | ||
| [ 5] 7.00-8.00 sec 112 MBytes 942 Mbits/sec 0 410 KBytes | ||
| [ 5] 8.00-9.00 sec 113 MBytes 947 Mbits/sec 0 410 KBytes | ||
| [ 5] 9.00-10.00 sec 112 MBytes 940 Mbits/sec 0 410 KBytes | ||
| - - - - - - - - - - - - - - - - - - - - - - - - - | ||
| [ ID] Interval Transfer Bitrate Retr | ||
| [ 5] 0.00-10.00 sec 1.10 GBytes 943 Mbits/sec 0 sender | ||
| [ 5] 0.00-10.00 sec 1.10 GBytes 941 Mbits/sec receiver | ||
| ``` | ||
|
|
||
| Now, we limit ingress on port 1 (connected to eth0) to 4 MBit/s: | ||
| ```> bw in 1 1000 | ||
| bandwidth_ingress_set called, port 04 | ||
| RTL837X_IGBW_PORT_CTRL:0x00100100 | ||
| RTL837X_IGBW_PORT_FC_CTRL:0x00000010 | ||
| ``` | ||
|
|
||
| We now get: | ||
| ``` | ||
| $ sudo ip netns exec client iperf3 -c 192.168.99.2 | ||
| [ 5] local 192.168.99.1 port 43324 connected to 192.168.99.2 port 5201 | ||
| [ ID] Interval Transfer Bitrate Retr Cwnd | ||
| [ 5] 0.00-1.00 sec 1.12 MBytes 9.43 Mbits/sec 0 160 KBytes | ||
| [ 5] 1.00-2.00 sec 640 KBytes 5.24 Mbits/sec 0 160 KBytes | ||
| [ 5] 2.00-3.00 sec 384 KBytes 3.15 Mbits/sec 0 160 KBytes | ||
| [ 5] 3.00-4.00 sec 384 KBytes 3.15 Mbits/sec 0 160 KBytes | ||
| [ 5] 4.00-5.00 sec 640 KBytes 5.24 Mbits/sec 0 160 KBytes | ||
| [ 5] 5.00-6.00 sec 256 KBytes 2.10 Mbits/sec 0 160 KBytes | ||
| [ 5] 6.00-7.00 sec 640 KBytes 5.24 Mbits/sec 0 160 KBytes | ||
| [ 5] 7.00-8.00 sec 384 KBytes 3.15 Mbits/sec 0 160 KBytes | ||
| [ 5] 8.00-9.00 sec 640 KBytes 5.24 Mbits/sec 0 160 KBytes | ||
| [ 5] 9.00-10.00 sec 256 KBytes 2.10 Mbits/sec 0 160 KBytes | ||
| - - - - - - - - - - - - - - - - - - - - - - - - - | ||
| [ ID] Interval Transfer Bitrate Retr | ||
| [ 5] 0.00-10.00 sec 5.25 MBytes 4.40 Mbits/sec 0 sender | ||
| [ 5] 0.00-10.16 sec 4.75 MBytes 3.92 Mbits/sec receiver | ||
|
|
||
| iperf Done. | ||
| ``` | ||
| Which is the 4Mbit/s we configured. There are no packet drops (retries) because | ||
| Flow Control is used to signal the Ethernet adapter on the incoming interface | ||
| (port 1 of the router) to slow down. | ||
|
|
||
| We can also configure a mere 256KBit/s and packet drop to simulate a bad connection: | ||
| ``` | ||
| > bw in 1 0100 | ||
| bandwidth_ingress_set called, port 04 | ||
| RTL837X_IGBW_PORT_CTRL:0x00100010 | ||
| RTL837X_IGBW_PORT_FC_CTRL:0x00000010 | ||
|
|
||
| > bw in 1 drop | ||
| RTL837X_IGBW_PORT_FC_CTRL:0x00000000 | ||
| ``` | ||
|
|
||
| We now get: | ||
| ``` | ||
| $ sudo ip netns exec client iperf3 -c 192.168.99.2 | ||
| Connecting to host 192.168.99.2, port 5201 | ||
| [ 5] local 192.168.99.1 port 46060 connected to 192.168.99.2 port 5201 | ||
| [ ID] Interval Transfer Bitrate Retr Cwnd | ||
| [ 5] 0.00-1.00 sec 384 KBytes 3.14 Mbits/sec 2 1.41 KBytes | ||
| [ 5] 1.00-2.00 sec 0.00 Bytes 0.00 bits/sec 54 1.41 KBytes | ||
| [ 5] 2.00-3.00 sec 0.00 Bytes 0.00 bits/sec 31 29.7 KBytes | ||
| [ 5] 3.00-4.00 sec 0.00 Bytes 0.00 bits/sec 2 1.41 KBytes | ||
| [ 5] 4.00-5.00 sec 0.00 Bytes 0.00 bits/sec 23 1.41 KBytes | ||
| [ 5] 5.00-6.00 sec 128 KBytes 1.05 Mbits/sec 16 14.1 KBytes | ||
| [ 5] 6.00-7.00 sec 0.00 Bytes 0.00 bits/sec 2 1.41 KBytes | ||
| [ 5] 7.00-8.00 sec 0.00 Bytes 0.00 bits/sec 11 1.41 KBytes | ||
| [ 5] 8.00-9.00 sec 128 KBytes 1.05 Mbits/sec 9 8.48 KBytes | ||
| [ 5] 9.00-10.00 sec 0.00 Bytes 0.00 bits/sec 2 1.41 KBytes | ||
| - - - - - - - - - - - - - - - - - - - - - - - - - | ||
| [ ID] Interval Transfer Bitrate Retr | ||
| [ 5] 0.00-10.00 sec 640 KBytes 524 Kbits/sec 152 sender | ||
| [ 5] 0.00-10.00 sec 256 KBytes 210 Kbits/sec receiver | ||
|
|
||
| iperf Done. | ||
| ``` | ||
| Which shows a large number of retries due to dropped packets and an average number | ||
| of received packets (the client sends the packets to the server, and they are sent | ||
| back to the client by the server) of 210 KBit/s, the number is higher for the transmitted | ||
| packets, because they may include dropped packets. | ||
Uh oh!
There was an error while loading. Please reload this page.