What's new

FlexQoS FlexQoS 1.2.4 - Flexible QoS Enhancement Script for Adaptive QoS

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

dave14305

Part of the Furniture
Version 1.2.5 released in this new thread!

FlexQoS Version 1.2.4 - Released 11-Apr-2021

CHANGED

  • Improved webui mounting during startup, adopting community locking standard.
FIXED
  • iptables rules were not properly evaluated in the connection list when a rule contained multiple ports for both local and remote ports.
  • Hide last update check result when initiating new check for update.
FlexQoS Version 1.2.3 - Released 21-Mar-2021

NEW

  • Added ability to remember filter settings between sessions. See the Remember checkbox in the Filter Connections header. Saved filters are stored as browser cookies and not as a configuration setting.
CHANGED
  • Made fq_codel the default qdisc option. Can be disabled by choosing "ASUS" as the QoS Mode.
  • Delay FlexQoS startup until all qdiscs are created by Adaptive QoS, since we now replace them with fq_codel by default.
  • During startup check, if QoS fails to initialize, only attempt to restart qos one time before erroring out. This avoids endless qos restart loops from happening if an unrecoverable error happens with Adaptive QoS.
  • Adopt sqm-scripts minimum quantum/burst/cburst of 1749 based on worst-case ATM overhead for one packet of MTU size.
  • Renamed File Downloads to File Transfers to more closely resemble the stock File Transferring label.
  • Renamed Game Downloads category back to Learn-From-Home. Changed built-in Game Downloads rule to use File Transferring category for new rules. Existing Game Downloads rules will still direct to the Learn-From-Home priority level.
  • Show full stock category names in CLI appdb command output.
  • Moved FlexQoS tab to the third tab between QoS and Classification.
  • All Class dropdowns are now listed in the user-defined priority order.
  • Moved version number and update check under Options panel
  • Moved graph scale option to the main page under the refresh dropdown
FIXED
  • When disabling Refresh in the WebUI, don't refresh one last time.
  • Fixed Overhead dropdown display issue when using 384 firmware.
FlexQoS Version 1.2.2 - Released 07-Mar-2021

NEW

  • Add well-known rule for Google Meet.
  • Add overhead and ATM settings to WebUI Options panel.
  • Add user-defined iptables rules to well-known rules dropdown to enable re-ordering of iptables rules via delete and add.
  • Add WebUI mounting lock mechanism being adopted by handsome addon developers everywhere (courtesy of @Martineau).
CHANGED
  • Don't write default settings to custom_settings.txt when saving.
  • Remove extra IPv6 syslog message during startup.
  • In fq_codel mode, make better optimizations for low-bandwidth links.
  • Removed legacy 500 kbps threshold for applying custom rates.
  • Support exact matches in IP fields in Tracked Connections filter. Append $ to indicate exact match syntax (e.g. 192.168.1.10$).
FIXED
  • Don't print custom rate info in debug mode when Automatic Bandwidth is selected on QoS page.
  • Moved iptables Reset link to accommodate changes in 386.1 tableApi.js.
FlexQoS Version 1.2.1 - Released 12-Feb-2021

NEW:

  • Users can now customize the QoS class used for outbound traffic generated locally by the router (excluding DNS and NTP). Default is File Downloads. This was previously a hard-coded rule in the script.
  • The trimphant return of fq_codel to FlexQoS! This is an optional queue discipline choice (you must opt-in under Customize / Options).
In 384.x firmware, the Default choice respects the Queue Discipline chosen on the main QoS page.
In 386.x firmware, the Default choice implies Stochastic Fair Queuing (sfq), since there is no longer a choice in the firmware.
In all firmware, the fq_codel choice replaces the secondary htb queue discipline used to manage per-device traffic within an application category.

CHANGED:
  • HTB burst parameter now is based on "burst by duration" concept borrowed from SQM scripts @ OpenWRT. Burst is now defined as the number of bytes that can be sent at line speed in 1 millisecond.
  • Improved local client name mapping in the Tracked connections table, including IPv6 connections.
  • Reorganized bandwidth rates settings with new name and ordering
  • Reinstate firewall restart as the trigger for FlexQoS startup
  • Add custom rate commands and fq_codel qdisc commands to debug output
  • Changed wording of backup deletion prompt (contributed by @maghuro)
  • Removed Advertisements from default appdb rules (rarely seen in the wild)
  • Added additional debug logging during startup while waiting for Adaptive QoS setup
  • Reduced startup wait time from 5 to 3 minutes
  • Force QoS restart after 3-minute startup delay to work around 386.1 Adaptive QoS startup issues on some models
  • Refactored code into more discrete functions to avoid repetition
FIXED:
  • Page title now conforms to firmware standard title wording
  • Properly parsed integers in comma function
  • Cleaned up temporary file left behind during an update download
  • 5-minute Cronjob might fail if Entware coreutils-date is also installed
FlexQoS Version 1.1.0 - Released 13-Dec-2020

NEW:

  • Replaced total data transferred pie charts and Bandwidth Util bars with running rate line charts. Available with regular linear y-axis scale or logarithmic scale for dealing with large rate differences among classes.
CHANGED:
  • Added support for user locale number formatting (1,000.00 or 1 000,00 or 1.000,00 depending on where you live).
  • Added WebUI Options panel for changing line chart graph scale and conntrack flushing.
  • Reworked shell script functions for simplicity (debatable) and added comments to document the logic wherever possible.
  • Explicitly call tc or realtc from /usr/sbin to avoid conflicts with tc-adv installed by CakeQOS-Merlin (tc-adv has bugs affecting htb class output).
  • Converted echo output to printf wherever possible.
  • Moved FlexQoS iptables rules to a dedicated chain in the mangle table.
REMOVED:
  • Removed support for Traditional QoS or Bandwidth Limiter QoS modes in WebUI. Please use Merlin's Classification page for those modes.
Update via the WebUI, amtm, or the command line with flexqos update

1607908023456.png


Requirements:
  • ASUSWRT-Merlin 384.15 or higher
  • SSH, JFFS scripts enabled
  • Adaptive QoS enabled
Installation:
The simplest method for installation is to use amtm, option i, option 3.

For manual installation, paste the following command into your SSH terminal session:
Code:
/usr/sbin/curl "https://raw.githubusercontent.com/dave14305/FlexQoS/master/flexqos.sh" -o /jffs/addons/flexqos/flexqos.sh --create-dirs && chmod +x /jffs/addons/flexqos/flexqos.sh && sh /jffs/addons/flexqos/flexqos.sh -install
Source: https://github.com/dave14305/FlexQoS

Updates:
Code:
flexqos -update
# or
sh /jffs/addons/flexqos/flexqos.sh -update
You can also update via the "Check for Update" button in the WebUI.

User documentation available on Github:
 
Last edited:
FlexQoS Version 1.1.0 - Released 13-Dec-2020

NEW:

  • Replaced total data transferred pie charts and Bandwidth Util bars with running rate line charts. Available with regular linear y-axis scale or logarithmic scale for dealing with large rate differences among classes.
CHANGED:
  • Added support for user locale number formatting (1,000.00 or 1 000,00 or 1.000,00 depending on where you live).
  • Added WebUI Options panel for changing line chart graph scale and conntrack flushing.
  • Reworked shell script functions for simplicity (debatable) and added comments to document the logic wherever possible.
  • Explicitly call tc or realtc from /usr/sbin to avoid conflicts with tc-adv installed by CakeQOS-Merlin (tc-adv has bugs affecting htb class output).
  • Converted echo output to printf wherever possible.
  • Moved FlexQoS iptables rules to a dedicated chain in the mangle table.
REMOVED:
  • Removed support for Traditional QoS or Bandwidth Limiter QoS modes in WebUI. Please use Merlin's Classification page for those modes.
Update via the WebUI, amtm, or the command line with flexqos update

View attachment 28457
new graphs are cool. Thanks Dave, your the reason I need merlin (Also thanks to rmerlin for that). I did just realize I shouldnt be drinking a beer while staring at them.
 
Wow....we appreciate all you do here @dave14305 ! It seems I keep going back and forth between cake and Flex haha. Decisions....decisions!!!
 
new graphs are cool. Thanks Dave, your the reason I need merlin (Also thanks to rmerlin for that). I did just realize I shouldnt be drinking a beer while staring at them.
That sounds like the tail wagging the dog, but I appreciate the thought. :)
Wow....we appreciate all you do here @dave14305 ! It seems I keep going back and forth between cake and Flex haha. Decisions....decisions!!!
Yes, me too. I've been spending hours reading about CAKE and sqm-scripts over at the OpenWRT forums. So many possibilities.
 
@dave14305 thank you for another great release!!!

I would like to ask you, is there any way to activate / deactivate specific rules or the Adaptive QoS through scripts?
 
@dave14305 thank you for another great release!!!

I would like to ask you, is there any way to activate / deactivate specific rules or the Adaptive QoS through scripts?
You can disable Adaptive QoS with these commands (taken from CakeQOS):
Bash:
    if [ "$(nvram get qos_enable)" = "1" ]; then
        nvram set qos_enable="0"
        nvram commit
        service "restart_qos;restart_firewall" >/dev/null 2>&1
    fi
There’s no simple way to disable individual rules. How would you use that feature if it existed?
 
Hi Dave,
many thanks for your quick answer and help. Enabling/Disabling the QoS is also fine.

By the way, I really enjoyed the new graphs, very very helpful!

In my case, I have a very limited ADSL line with upload speed at around 0.8-0.9Mbps. I sense that QoS keeps some BW reserved so effectively I get maximum upload somewhere near to 0.7M-0.8M with QoS on.

Although I am fine with that, there are occasions that I need that extra juice, for example when both my wife and I work from home. Therefore, If such a function was possible, I could have a script setting up a different priorities based on my needs on the time of day. I could run the script directly from my phone using shortcuts in ios. Even someone without the technical expertise could do that if the shortcut is already preinstalled on their phone.

Right now, I have a script which effectively restrict wan access to some specific IPs (NAS, IP cameras). If that function was true, I could keep NAS using lower BW during day and allow it run at full speed during night.

May I ask something more? I have set up a site to site VPN between my two homes. I have seen that due to some kind of limitation, upload traffic that goes to VPN is counted as downloaded and vice versa.
My connection is asynchronous (10M / 1M down / up) .

How is FlexQoS managing VPN traffic?
 
Upgrading from V1.0.6 to V1.1.0 and everything is running smoothly, thanks @dave14305.
 
May I ask something more? I have set up a site to site VPN between my two homes. I have seen that due to some kind of limitation, upload traffic that goes to VPN is counted as downloaded and vice versa.
My connection is asynchronous (10M / 1M down / up) .

How is FlexQoS managing VPN traffic?
I don't use any VPN, so I don't know how it should behave. There is a hardcoded iptables rule in the script that is supposed to mark outgoing traffic as Downloads, but I've never tested it with a VPN. What is the output of iptables -t mangle -nvL

EDIT: I've pushed a minor change to the develop branch to see if it helps. You can test it by updating with flexqos develop

I wasn't fully erasing the download bits in the mask when setting the upload bits. Maybe this will help.
 
Last edited:
Hi Dave, here is the output:

The router's iP is 192.168.177.1 . It's connected as client to another Asus RT-AC68 which holds the IP of 192.168.179.1



Code:
Chain PREROUTING (policy ACCEPT 1468K packets, 505M bytes)
 pkts bytes target     prot opt in     out     source               destination
 100K   44M BWDPI_FILTER  udp  --  ppp0   *       0.0.0.0/0            0.0.0.0/0

Chain INPUT (policy ACCEPT 714K packets, 135M bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 753K packets, 370M bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 MARK       all  --  *      br0     192.168.177.0/24     192.168.177.0/24     MARK xset 0x1/0x7

Chain OUTPUT (policy ACCEPT 677K packets, 223M bytes)
 pkts bytes target     prot opt in     out     source               destination
    5   222 MARK       udp  --  *      ppp0    0.0.0.0/0            0.0.0.0/0            multiport dports  !53,123 MARK xset 0x4003ffff/0x403fffff
 2183  157K MARK       tcp  --  *      ppp0    0.0.0.0/0            0.0.0.0/0            multiport dports  !53,123,853 MARK xset 0x4003ffff/0x403fffff

Chain POSTROUTING (policy ACCEPT 1432K packets, 593M bytes)
 pkts bytes target     prot opt in     out     source               destination
1432K  593M FlexQoS    all  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain BWDPI_FILTER (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DROP       udp  --  ppp0   *       0.0.0.0/0            0.0.0.0/0            udp spt:68 dpt:67
    0     0 DROP       udp  --  ppp0   *       0.0.0.0/0            0.0.0.0/0            udp spt:67 dpt:68

Chain FlexQoS (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 MARK       udp  --  *      br0     0.0.0.0/0            0.0.0.0/0            multiport sports 500,4500 MARK xset 0x8006ffff/0x803fffff
    0     0 MARK       udp  --  *      ppp0    0.0.0.0/0            0.0.0.0/0            multiport dports 500,4500 MARK xset 0x4006ffff/0x403fffff
 9995 1753K MARK       udp  --  *      br0     0.0.0.0/0            0.0.0.0/0            multiport dports 16384:16415 MARK xset 0x8006ffff/0x803fffff
10794 1812K MARK       udp  --  *      ppp0    0.0.0.0/0            0.0.0.0/0            multiport sports 16384:16415 MARK xset 0x4006ffff/0x403fffff
    0     0 MARK       tcp  --  *      br0     0.0.0.0/0            0.0.0.0/0            multiport sports 119,563 MARK xset 0x8003ffff/0x803fffff
    0     0 MARK       tcp  --  *      ppp0    0.0.0.0/0            0.0.0.0/0            multiport dports 119,563 MARK xset 0x4003ffff/0x403fffff
  202  295K MARK       tcp  --  *      br0     0.0.0.0/0            0.0.0.0/0            multiport sports 80,443 mark match 0x80080000/0xc03f0000 MARK or 0x803fffff
   88  4025 MARK       tcp  --  *      ppp0    0.0.0.0/0            0.0.0.0/0            multiport dports 80,443 mark match 0x40080000/0xc03f0000 MARK or 0x403fffff
75874   42M MARK       all  --  *      br0     0.0.0.0/0            192.168.177.99       MARK xset 0x8009ffff/0x803fffff
 101K   21M MARK       all  --  *      ppp0    192.168.177.99       0.0.0.0/0            MARK xset 0x4009ffff/0x403fffff
    0     0 MARK       udp  --  *      br0     0.0.0.0/0            0.0.0.0/0            multiport sports 3478:3481 mark match 0x80000000/0xc03fffff MARK xset 0x8006ffff/0x803fffff
    0     0 MARK       udp  --  *      ppp0    0.0.0.0/0            0.0.0.0/0            multiport dports 3478:3481 mark match 0x40000000/0xc03fffff MARK xset 0x4006ffff/0x403fffff
    0     0 MARK       all  --  *      br0     192.168.179.1        0.0.0.0/0            MARK xset 0x8009ffff/0x803fffff
   10   640 MARK       all  --  *      ppp0    0.0.0.0/0            192.168.179.1        MARK xset 0x4009ffff/0x403fffff
 284K   78M MARK       all  --  *      br0     0.0.0.0/0            192.168.177.24       MARK xset 0x8003ffff/0x803fffff
 126K  209M MARK       all  --  *      ppp0    192.168.177.24       0.0.0.0/0            MARK xset 0x4003ffff/0x403fffff
    0     0 MARK       all  --  *      br0     192.168.179.24       0.0.0.0/0            MARK xset 0x8003ffff/0x803fffff
10863  654K MARK       all  --  *      ppp0    0.0.0.0/0            192.168.179.24       MARK xset 0x4003ffff/0x403fffff
 
Although I am fine with that, there are occasions that I need that extra juice, for example when both my wife and I work from home. Therefore, If such a function was possible, I could have a script setting up a different priorities based on my needs on the time of day.
If you are doing such a thing, you may find that you end up with worse performance than you had with the lower limit.
If you need that "extra juice" then it means you are maxing out your link, and you will end up with the problem that QoS aims to fix (dropped packets, out of control pings etc).
Having that limit set would be preferable, especially for your typical WfH use cases.
 
Was just about to post about the inverted vpn traffic issue as well as it is happening for me too. The 'Bandwidth Monitor' tab has always been inverted due to a long standing issue but the 'Classification' and 'FlexQoS' tabs have always been correct until recently. I first noticed the problem in version 1.0.6 and it is present on this latest version too. The classification tab is also incorrect now fyi.

I'll try the development branch and see if that helps.

*edit - Still an issue with the development branch unfortunately.
 
Last edited:
Hi Dave, here is the output:

The router's iP is 192.168.177.1 . It's connected as client to another Asus RT-AC68 which holds the IP of 192.168.179.1



Code:
Chain PREROUTING (policy ACCEPT 1468K packets, 505M bytes)
pkts bytes target     prot opt in     out     source               destination
100K   44M BWDPI_FILTER  udp  --  ppp0   *       0.0.0.0/0            0.0.0.0/0

Chain INPUT (policy ACCEPT 714K packets, 135M bytes)
pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 753K packets, 370M bytes)
pkts bytes target     prot opt in     out     source               destination
    0     0 MARK       all  --  *      br0     192.168.177.0/24     192.168.177.0/24     MARK xset 0x1/0x7

Chain OUTPUT (policy ACCEPT 677K packets, 223M bytes)
pkts bytes target     prot opt in     out     source               destination
    5   222 MARK       udp  --  *      ppp0    0.0.0.0/0            0.0.0.0/0            multiport dports  !53,123 MARK xset 0x4003ffff/0x403fffff
2183  157K MARK       tcp  --  *      ppp0    0.0.0.0/0            0.0.0.0/0            multiport dports  !53,123,853 MARK xset 0x4003ffff/0x403fffff

Chain POSTROUTING (policy ACCEPT 1432K packets, 593M bytes)
pkts bytes target     prot opt in     out     source               destination
1432K  593M FlexQoS    all  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain BWDPI_FILTER (1 references)
pkts bytes target     prot opt in     out     source               destination
    0     0 DROP       udp  --  ppp0   *       0.0.0.0/0            0.0.0.0/0            udp spt:68 dpt:67
    0     0 DROP       udp  --  ppp0   *       0.0.0.0/0            0.0.0.0/0            udp spt:67 dpt:68

Chain FlexQoS (1 references)
pkts bytes target     prot opt in     out     source               destination
    0     0 MARK       udp  --  *      br0     0.0.0.0/0            0.0.0.0/0            multiport sports 500,4500 MARK xset 0x8006ffff/0x803fffff
    0     0 MARK       udp  --  *      ppp0    0.0.0.0/0            0.0.0.0/0            multiport dports 500,4500 MARK xset 0x4006ffff/0x403fffff
9995 1753K MARK       udp  --  *      br0     0.0.0.0/0            0.0.0.0/0            multiport dports 16384:16415 MARK xset 0x8006ffff/0x803fffff
10794 1812K MARK       udp  --  *      ppp0    0.0.0.0/0            0.0.0.0/0            multiport sports 16384:16415 MARK xset 0x4006ffff/0x403fffff
    0     0 MARK       tcp  --  *      br0     0.0.0.0/0            0.0.0.0/0            multiport sports 119,563 MARK xset 0x8003ffff/0x803fffff
    0     0 MARK       tcp  --  *      ppp0    0.0.0.0/0            0.0.0.0/0            multiport dports 119,563 MARK xset 0x4003ffff/0x403fffff
  202  295K MARK       tcp  --  *      br0     0.0.0.0/0            0.0.0.0/0            multiport sports 80,443 mark match 0x80080000/0xc03f0000 MARK or 0x803fffff
   88  4025 MARK       tcp  --  *      ppp0    0.0.0.0/0            0.0.0.0/0            multiport dports 80,443 mark match 0x40080000/0xc03f0000 MARK or 0x403fffff
75874   42M MARK       all  --  *      br0     0.0.0.0/0            192.168.177.99       MARK xset 0x8009ffff/0x803fffff
101K   21M MARK       all  --  *      ppp0    192.168.177.99       0.0.0.0/0            MARK xset 0x4009ffff/0x403fffff
    0     0 MARK       udp  --  *      br0     0.0.0.0/0            0.0.0.0/0            multiport sports 3478:3481 mark match 0x80000000/0xc03fffff MARK xset 0x8006ffff/0x803fffff
    0     0 MARK       udp  --  *      ppp0    0.0.0.0/0            0.0.0.0/0            multiport dports 3478:3481 mark match 0x40000000/0xc03fffff MARK xset 0x4006ffff/0x403fffff
    0     0 MARK       all  --  *      br0     192.168.179.1        0.0.0.0/0            MARK xset 0x8009ffff/0x803fffff
   10   640 MARK       all  --  *      ppp0    0.0.0.0/0            192.168.179.1        MARK xset 0x4009ffff/0x403fffff
284K   78M MARK       all  --  *      br0     0.0.0.0/0            192.168.177.24       MARK xset 0x8003ffff/0x803fffff
126K  209M MARK       all  --  *      ppp0    192.168.177.24       0.0.0.0/0            MARK xset 0x4003ffff/0x403fffff
    0     0 MARK       all  --  *      br0     192.168.179.24       0.0.0.0/0            MARK xset 0x8003ffff/0x803fffff
10863  654K MARK       all  --  *      ppp0    0.0.0.0/0            192.168.179.24       MARK xset 0x4003ffff/0x403fffff
You don't have the rule from the OpenVPN client up that I would have expected in POSTROUTING based on @RMerlin's code:
I have no VPN expertise, so if it's perhaps a beta issue, you might want to post in the beta thread, or else maybe Merlin can explain if this is working as intended.
 
Was just about to post about the inverted vpn traffic issue as well as it is happening for me too. The 'Bandwidth Monitor' tab has always been inverted due to a long standing issue but the 'Classification' and 'FlexQoS' tabs have always been correct until recently. I first noticed the problem in version 1.0.6 and it is present on this latest version too. The classification tab is also incorrect now fyi.

I'll try the development branch and see if that helps.

*edit - Still an issue with the development branch unfortunately.
Does it change at all if you add this rule via ssh?
Bash:
iptables -A POSTROUTING -t mangle -o br0 -m mark --mark 0x40000000/0xc0000000 -j MARK --set-xmark 0x80000000/0xC0000000
 
In regards to the VPN, there was a discussion happening in this point of forum . Maybe it can provide some more information.

I asked previously about the VPN topic because I noticed that latest FlexQoS did not cap my VPN down speed based on WAN's UP limit (as it used to be in 1.0.6). Although it still identifies traffic incorrectly (VPN down traffic shows as UP in graphs) it seems to work as intended in terms of speed limits.
 
Pertaining to VPN, it might not necessarily be OpenVPN. I use a Cisco VPN client for work, and it gets marked as SSL, so I've created a custom category "Work VPN" and by the IPs I have moved the priority to "Work from Home" - Pretty slick!
 
Does it change at all if you add this rule via ssh?
Bash:
iptables -A POSTROUTING -t mangle -o br0 -m mark --mark 0x40000000/0xc0000000 -j MARK --set-xmark 0x80000000/0xC0000000

Just to confirm, adding the above in via SSH does not resolve the problem.

I have also posted the issue to the beta thread just now. I suspect that it is related to the beta as the classification tab is also broken now where it never was before. I only just noticed the issue on 1.0.6 but this is probably around the time I switch to the alpha (and now the beta) version of 386.1.
 
Last edited:
Question:

Does FlexQos play nice with higher throughputs?
Currently have a 100/40 connection, but I have the option of a 1000/50 plan, can FlexQos deal with that?
 
Question:

Does FlexQos play nice with higher throughputs?
Currently have a 100/40 connection, but I have the option of a 1000/50 plan, can FlexQos deal with that?
I don’t know the answer since I don’t have those speeds, but I’m currently unhappy with the bursting in FlexQoS at my own speeds (400/25). Been studying burst theory for htb over at OpenWRT (how come no QoS dorks hang out here?).
 

Support SNBForums w/ Amazon

If you'd like to support SNBForums, just use this link and buy anything on Amazon. Thanks!

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top