Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'multi-queue-aware-sch_cake'

says:

====================
Multi-queue aware sch_cake

This series adds a multi-queue aware variant of the sch_cake scheduler,
called 'cake_mq'. Using this makes it possible to scale the rate shaper
of sch_cake across multiple CPUs, while still enforcing a single global
rate on the interface.

The approach taken in this patch series is to implement a separate qdisc
called 'cake_mq', which is based on the existing 'mq' qdisc, but differs
in a couple of aspects:

- It will always install a cake instance on each hardware queue (instead
of using the default qdisc for each queue like 'mq' does).

- The cake instances on the queues will share their configuration, which
can only be modified through the parent cake_mq instance.

Doing things this way simplifies user configuration by centralising
all configuration through the cake_mq qdisc (which also serves as an
obvious way of opting into the multi-queue aware behaviour). The cake_mq
qdisc takes all the same configuration parameters as the cake qdisc.

An earlier version of this work was presented at this year's Netdevconf:
https://netdevconf.info/0x19/sessions/talk/mq-cake-scaling-software-rate-limiting-across-cpu-cores.html

The patch series is structured as follows:

- Patch 1 exports the mq qdisc functions for reuse.

- Patch 2 factors out the sch_cake configuration variables into a
separate struct that can be shared between instances.

- Patch 3 adds the basic cake_mq qdisc, reusing the exported mq code

- Patch 4 adds configuration sharing across the cake instances installed
under cake_mq

- Patch 5 adds the shared shaper state that enables the multi-core rate
shaping

- Patch 6 adds selftests for cake_mq

A patch to iproute2 to make it aware of the cake_mq qdisc were submitted
separately with a previous patch version:

https://lore.kernel.org/r/20260105162902.1432940-1-toke@redhat.com
====================

Link: https://patch.msgid.link/20260109-mq-cake-sub-qdisc-v8-0-8d613fece5d8@redhat.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+1018 -158
+3
Documentation/netlink/specs/tc.yaml
··· 2207 2207 - 2208 2208 name: blue-timer-us 2209 2209 type: s32 2210 + - 2211 + name: active-queues 2212 + type: u32 2210 2213 - 2211 2214 name: cake-tin-stats-attrs 2212 2215 name-prefix: tca-cake-tin-stats-
+1
MAINTAINERS
··· 25454 25454 S: Maintained 25455 25455 F: include/net/pkt_cls.h 25456 25456 F: include/net/pkt_sched.h 25457 + F: include/net/sch_priv.h 25457 25458 F: include/net/tc_act/ 25458 25459 F: include/uapi/linux/pkt_cls.h 25459 25460 F: include/uapi/linux/pkt_sched.h
+27
include/net/sch_priv.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __NET_SCHED_PRIV_H 3 + #define __NET_SCHED_PRIV_H 4 + 5 + #include <net/sch_generic.h> 6 + 7 + struct mq_sched { 8 + struct Qdisc **qdiscs; 9 + }; 10 + 11 + int mq_init_common(struct Qdisc *sch, struct nlattr *opt, 12 + struct netlink_ext_ack *extack, 13 + const struct Qdisc_ops *qdisc_ops); 14 + void mq_destroy_common(struct Qdisc *sch); 15 + void mq_attach(struct Qdisc *sch); 16 + void mq_dump_common(struct Qdisc *sch, struct sk_buff *skb); 17 + struct netdev_queue *mq_select_queue(struct Qdisc *sch, 18 + struct tcmsg *tcm); 19 + struct Qdisc *mq_leaf(struct Qdisc *sch, unsigned long cl); 20 + unsigned long mq_find(struct Qdisc *sch, u32 classid); 21 + int mq_dump_class(struct Qdisc *sch, unsigned long cl, 22 + struct sk_buff *skb, struct tcmsg *tcm); 23 + int mq_dump_class_stats(struct Qdisc *sch, unsigned long cl, 24 + struct gnet_dump *d); 25 + void mq_walk(struct Qdisc *sch, struct qdisc_walker *arg); 26 + 27 + #endif
+1
include/uapi/linux/pkt_sched.h
··· 1036 1036 TCA_CAKE_STATS_DROP_NEXT_US, 1037 1037 TCA_CAKE_STATS_P_DROP, 1038 1038 TCA_CAKE_STATS_BLUE_TIMER_US, 1039 + TCA_CAKE_STATS_ACTIVE_QUEUES, 1039 1040 __TCA_CAKE_STATS_MAX 1040 1041 }; 1041 1042 #define TCA_CAKE_STATS_MAX (__TCA_CAKE_STATS_MAX - 1)
+378 -136
net/sched/sch_cake.c
··· 67 67 #include <linux/if_vlan.h> 68 68 #include <net/gso.h> 69 69 #include <net/pkt_sched.h> 70 + #include <net/sch_priv.h> 70 71 #include <net/pkt_cls.h> 71 72 #include <net/tcp.h> 72 73 #include <net/flow_dissector.h> ··· 198 197 u32 way_collisions; 199 198 }; /* number of tins is small, so size of this struct doesn't matter much */ 200 199 200 + struct cake_sched_config { 201 + u64 rate_bps; 202 + u64 interval; 203 + u64 target; 204 + u64 sync_time; 205 + u32 buffer_config_limit; 206 + u32 fwmark_mask; 207 + u16 fwmark_shft; 208 + s16 rate_overhead; 209 + u16 rate_mpu; 210 + u16 rate_flags; 211 + u8 tin_mode; 212 + u8 flow_mode; 213 + u8 atm_mode; 214 + u8 ack_filter; 215 + u8 is_shared; 216 + }; 217 + 201 218 struct cake_sched_data { 202 219 struct tcf_proto __rcu *filter_list; /* optional external classifier */ 203 220 struct tcf_block *block; 204 221 struct cake_tin_data *tins; 222 + struct cake_sched_config *config; 205 223 206 224 struct cake_heap_entry overflow_heap[CAKE_QUEUES * CAKE_MAX_TINS]; 207 - u16 overflow_timeout; 208 - 209 - u16 tin_cnt; 210 - u8 tin_mode; 211 - u8 flow_mode; 212 - u8 ack_filter; 213 - u8 atm_mode; 214 - 215 - u32 fwmark_mask; 216 - u16 fwmark_shft; 217 225 218 226 /* time_next = time_this + ((len * rate_ns) >> rate_shft) */ 219 - u16 rate_shft; 220 227 ktime_t time_next_packet; 221 228 ktime_t failsafe_next_packet; 222 229 u64 rate_ns; 223 - u64 rate_bps; 224 - u16 rate_flags; 225 - s16 rate_overhead; 226 - u16 rate_mpu; 227 - u64 interval; 228 - u64 target; 230 + u16 rate_shft; 231 + u16 overflow_timeout; 232 + u16 tin_cnt; 229 233 230 234 /* resource tracking */ 231 235 u32 buffer_used; 232 236 u32 buffer_max_used; 233 237 u32 buffer_limit; 234 - u32 buffer_config_limit; 235 238 236 239 /* indices for dequeue */ 237 240 u16 cur_tin; ··· 259 254 u16 max_adjlen; 260 255 u16 min_netlen; 261 256 u16 min_adjlen; 257 + 258 + /* mq sync state */ 259 + u64 last_checked_active; 260 + u64 last_active; 261 + u32 active_queues; 262 262 }; 263 263 264 264 enum { ··· 390 380 1239850263, 1191209601, 1147878294, 1108955788 391 381 }; 392 382 383 + static void cake_set_rate(struct cake_tin_data *b, u64 rate, u32 mtu, 384 + u64 target_ns, u64 rtt_est_ns); 393 385 /* http://en.wikipedia.org/wiki/Methods_of_computing_square_roots 394 386 * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2) 395 387 * ··· 1210 1198 static struct sk_buff *cake_ack_filter(struct cake_sched_data *q, 1211 1199 struct cake_flow *flow) 1212 1200 { 1213 - bool aggressive = q->ack_filter == CAKE_ACK_AGGRESSIVE; 1201 + bool aggressive = q->config->ack_filter == CAKE_ACK_AGGRESSIVE; 1214 1202 struct sk_buff *elig_ack = NULL, *elig_ack_prev = NULL; 1215 1203 struct sk_buff *skb_check, *skb_prev = NULL; 1216 1204 const struct ipv6hdr *ipv6h, *ipv6h_check; ··· 1370 1358 return avg; 1371 1359 } 1372 1360 1373 - static u32 cake_calc_overhead(struct cake_sched_data *q, u32 len, u32 off) 1361 + static u32 cake_calc_overhead(struct cake_sched_data *qd, u32 len, u32 off) 1374 1362 { 1363 + struct cake_sched_config *q = qd->config; 1364 + 1375 1365 if (q->rate_flags & CAKE_FLAG_OVERHEAD) 1376 1366 len -= off; 1377 1367 1378 - if (q->max_netlen < len) 1379 - q->max_netlen = len; 1380 - if (q->min_netlen > len) 1381 - q->min_netlen = len; 1368 + if (qd->max_netlen < len) 1369 + qd->max_netlen = len; 1370 + if (qd->min_netlen > len) 1371 + qd->min_netlen = len; 1382 1372 1383 1373 len += q->rate_overhead; 1384 1374 ··· 1399 1385 len += (len + 63) / 64; 1400 1386 } 1401 1387 1402 - if (q->max_adjlen < len) 1403 - q->max_adjlen = len; 1404 - if (q->min_adjlen > len) 1405 - q->min_adjlen = len; 1388 + if (qd->max_adjlen < len) 1389 + qd->max_adjlen = len; 1390 + if (qd->min_adjlen > len) 1391 + qd->min_adjlen = len; 1406 1392 1407 1393 return len; 1408 1394 } ··· 1600 1586 flow->dropped++; 1601 1587 b->tin_dropped++; 1602 1588 1603 - if (q->rate_flags & CAKE_FLAG_INGRESS) 1589 + if (q->config->rate_flags & CAKE_FLAG_INGRESS) 1604 1590 cake_advance_shaper(q, b, skb, now, true); 1605 1591 1606 1592 qdisc_drop_reason(skb, sch, to_free, SKB_DROP_REASON_QDISC_OVERLIMIT); ··· 1670 1656 static struct cake_tin_data *cake_select_tin(struct Qdisc *sch, 1671 1657 struct sk_buff *skb) 1672 1658 { 1673 - struct cake_sched_data *q = qdisc_priv(sch); 1659 + struct cake_sched_data *qd = qdisc_priv(sch); 1660 + struct cake_sched_config *q = qd->config; 1674 1661 u32 tin, mark; 1675 1662 bool wash; 1676 1663 u8 dscp; ··· 1688 1673 if (q->tin_mode == CAKE_DIFFSERV_BESTEFFORT) 1689 1674 tin = 0; 1690 1675 1691 - else if (mark && mark <= q->tin_cnt) 1692 - tin = q->tin_order[mark - 1]; 1676 + else if (mark && mark <= qd->tin_cnt) 1677 + tin = qd->tin_order[mark - 1]; 1693 1678 1694 1679 else if (TC_H_MAJ(skb->priority) == sch->handle && 1695 1680 TC_H_MIN(skb->priority) > 0 && 1696 - TC_H_MIN(skb->priority) <= q->tin_cnt) 1697 - tin = q->tin_order[TC_H_MIN(skb->priority) - 1]; 1681 + TC_H_MIN(skb->priority) <= qd->tin_cnt) 1682 + tin = qd->tin_order[TC_H_MIN(skb->priority) - 1]; 1698 1683 1699 1684 else { 1700 1685 if (!wash) 1701 1686 dscp = cake_handle_diffserv(skb, wash); 1702 - tin = q->tin_index[dscp]; 1687 + tin = qd->tin_index[dscp]; 1703 1688 1704 - if (unlikely(tin >= q->tin_cnt)) 1689 + if (unlikely(tin >= qd->tin_cnt)) 1705 1690 tin = 0; 1706 1691 } 1707 1692 1708 - return &q->tins[tin]; 1693 + return &qd->tins[tin]; 1709 1694 } 1710 1695 1711 1696 static u32 cake_classify(struct Qdisc *sch, struct cake_tin_data **t, ··· 1761 1746 bool same_flow = false; 1762 1747 1763 1748 /* choose flow to insert into */ 1764 - idx = cake_classify(sch, &b, skb, q->flow_mode, &ret); 1749 + idx = cake_classify(sch, &b, skb, q->config->flow_mode, &ret); 1765 1750 if (idx == 0) { 1766 1751 if (ret & __NET_XMIT_BYPASS) 1767 1752 qdisc_qstats_drop(sch); ··· 1796 1781 if (unlikely(len > b->max_skblen)) 1797 1782 b->max_skblen = len; 1798 1783 1799 - if (qdisc_pkt_segs(skb) > 1 && q->rate_flags & CAKE_FLAG_SPLIT_GSO) { 1784 + if (qdisc_pkt_segs(skb) > 1 && q->config->rate_flags & CAKE_FLAG_SPLIT_GSO) { 1800 1785 struct sk_buff *segs, *nskb; 1801 1786 netdev_features_t features = netif_skb_features(skb); 1802 1787 unsigned int slen = 0, numsegs = 0; ··· 1838 1823 get_cobalt_cb(skb)->adjusted_len = cake_overhead(q, skb); 1839 1824 flow_queue_add(flow, skb); 1840 1825 1841 - if (q->ack_filter) 1826 + if (q->config->ack_filter) 1842 1827 ack = cake_ack_filter(q, flow); 1843 1828 1844 1829 if (ack) { ··· 1847 1832 ack_pkt_len = qdisc_pkt_len(ack); 1848 1833 b->bytes += ack_pkt_len; 1849 1834 q->buffer_used += skb->truesize - ack->truesize; 1850 - if (q->rate_flags & CAKE_FLAG_INGRESS) 1835 + if (q->config->rate_flags & CAKE_FLAG_INGRESS) 1851 1836 cake_advance_shaper(q, b, ack, now, true); 1852 1837 1853 1838 qdisc_tree_reduce_backlog(sch, 1, ack_pkt_len); ··· 1870 1855 cake_heapify_up(q, b->overflow_idx[idx]); 1871 1856 1872 1857 /* incoming bandwidth capacity estimate */ 1873 - if (q->rate_flags & CAKE_FLAG_AUTORATE_INGRESS) { 1858 + if (q->config->rate_flags & CAKE_FLAG_AUTORATE_INGRESS) { 1874 1859 u64 packet_interval = \ 1875 1860 ktime_to_ns(ktime_sub(now, q->last_packet_time)); 1876 1861 ··· 1902 1887 if (ktime_after(now, 1903 1888 ktime_add_ms(q->last_reconfig_time, 1904 1889 250))) { 1905 - q->rate_bps = (q->avg_peak_bandwidth * 15) >> 4; 1890 + q->config->rate_bps = (q->avg_peak_bandwidth * 15) >> 4; 1906 1891 cake_reconfigure(sch); 1907 1892 } 1908 1893 } ··· 1922 1907 flow->set = CAKE_SET_SPARSE; 1923 1908 b->sparse_flow_count++; 1924 1909 1925 - flow->deficit = cake_get_flow_quantum(b, flow, q->flow_mode); 1910 + flow->deficit = cake_get_flow_quantum(b, flow, q->config->flow_mode); 1926 1911 } else if (flow->set == CAKE_SET_SPARSE_WAIT) { 1927 1912 /* this flow was empty, accounted as a sparse flow, but actually 1928 1913 * in the bulk rotation. ··· 1931 1916 b->sparse_flow_count--; 1932 1917 b->bulk_flow_count++; 1933 1918 1934 - cake_inc_srchost_bulk_flow_count(b, flow, q->flow_mode); 1935 - cake_inc_dsthost_bulk_flow_count(b, flow, q->flow_mode); 1919 + cake_inc_srchost_bulk_flow_count(b, flow, q->config->flow_mode); 1920 + cake_inc_dsthost_bulk_flow_count(b, flow, q->config->flow_mode); 1936 1921 } 1937 1922 1938 1923 if (q->buffer_used > q->buffer_max_used) ··· 2011 1996 struct sk_buff *skb; 2012 1997 u64 delay; 2013 1998 u32 len; 1999 + 2000 + if (q->config->is_shared && now - q->last_checked_active >= q->config->sync_time) { 2001 + struct net_device *dev = qdisc_dev(sch); 2002 + struct cake_sched_data *other_priv; 2003 + u64 new_rate = q->config->rate_bps; 2004 + u64 other_qlen, other_last_active; 2005 + struct Qdisc *other_sch; 2006 + u32 num_active_qs = 1; 2007 + unsigned int ntx; 2008 + 2009 + for (ntx = 0; ntx < dev->num_tx_queues; ntx++) { 2010 + other_sch = rcu_dereference(netdev_get_tx_queue(dev, ntx)->qdisc_sleeping); 2011 + other_priv = qdisc_priv(other_sch); 2012 + 2013 + if (other_priv == q) 2014 + continue; 2015 + 2016 + other_qlen = READ_ONCE(other_sch->q.qlen); 2017 + other_last_active = READ_ONCE(other_priv->last_active); 2018 + 2019 + if (other_qlen || other_last_active > q->last_checked_active) 2020 + num_active_qs++; 2021 + } 2022 + 2023 + if (num_active_qs > 1) 2024 + new_rate = div64_u64(q->config->rate_bps, num_active_qs); 2025 + 2026 + /* mtu = 0 is used to only update the rate and not mess with cobalt params */ 2027 + cake_set_rate(b, new_rate, 0, 0, 0); 2028 + q->last_checked_active = now; 2029 + q->active_queues = num_active_qs; 2030 + q->rate_ns = b->tin_rate_ns; 2031 + q->rate_shft = b->tin_rate_shft; 2032 + } 2014 2033 2015 2034 begin: 2016 2035 if (!sch->q.qlen) ··· 2153 2104 b->sparse_flow_count--; 2154 2105 b->bulk_flow_count++; 2155 2106 2156 - cake_inc_srchost_bulk_flow_count(b, flow, q->flow_mode); 2157 - cake_inc_dsthost_bulk_flow_count(b, flow, q->flow_mode); 2107 + cake_inc_srchost_bulk_flow_count(b, flow, q->config->flow_mode); 2108 + cake_inc_dsthost_bulk_flow_count(b, flow, q->config->flow_mode); 2158 2109 2159 2110 flow->set = CAKE_SET_BULK; 2160 2111 } else { ··· 2166 2117 } 2167 2118 } 2168 2119 2169 - flow->deficit += cake_get_flow_quantum(b, flow, q->flow_mode); 2120 + flow->deficit += cake_get_flow_quantum(b, flow, q->config->flow_mode); 2170 2121 list_move_tail(&flow->flowchain, &b->old_flows); 2171 2122 2172 2123 goto retry; ··· 2190 2141 if (flow->set == CAKE_SET_BULK) { 2191 2142 b->bulk_flow_count--; 2192 2143 2193 - cake_dec_srchost_bulk_flow_count(b, flow, q->flow_mode); 2194 - cake_dec_dsthost_bulk_flow_count(b, flow, q->flow_mode); 2144 + cake_dec_srchost_bulk_flow_count(b, flow, q->config->flow_mode); 2145 + cake_dec_dsthost_bulk_flow_count(b, flow, q->config->flow_mode); 2195 2146 2196 2147 b->decaying_flow_count++; 2197 2148 } else if (flow->set == CAKE_SET_SPARSE || ··· 2209 2160 else if (flow->set == CAKE_SET_BULK) { 2210 2161 b->bulk_flow_count--; 2211 2162 2212 - cake_dec_srchost_bulk_flow_count(b, flow, q->flow_mode); 2213 - cake_dec_dsthost_bulk_flow_count(b, flow, q->flow_mode); 2163 + cake_dec_srchost_bulk_flow_count(b, flow, q->config->flow_mode); 2164 + cake_dec_dsthost_bulk_flow_count(b, flow, q->config->flow_mode); 2214 2165 } else 2215 2166 b->decaying_flow_count--; 2216 2167 ··· 2221 2172 2222 2173 reason = cobalt_should_drop(&flow->cvars, &b->cparams, now, skb, 2223 2174 (b->bulk_flow_count * 2224 - !!(q->rate_flags & 2175 + !!(q->config->rate_flags & 2225 2176 CAKE_FLAG_INGRESS))); 2226 2177 /* Last packet in queue may be marked, shouldn't be dropped */ 2227 2178 if (reason == SKB_NOT_DROPPED_YET || !flow->head) 2228 2179 break; 2229 2180 2230 2181 /* drop this packet, get another one */ 2231 - if (q->rate_flags & CAKE_FLAG_INGRESS) { 2182 + if (q->config->rate_flags & CAKE_FLAG_INGRESS) { 2232 2183 len = cake_advance_shaper(q, b, skb, 2233 2184 now, true); 2234 2185 flow->deficit -= len; ··· 2239 2190 qdisc_tree_reduce_backlog(sch, 1, qdisc_pkt_len(skb)); 2240 2191 qdisc_qstats_drop(sch); 2241 2192 qdisc_dequeue_drop(sch, skb, reason); 2242 - if (q->rate_flags & CAKE_FLAG_INGRESS) 2193 + if (q->config->rate_flags & CAKE_FLAG_INGRESS) 2243 2194 goto retry; 2244 2195 } 2245 2196 2246 2197 b->tin_ecn_mark += !!flow->cvars.ecn_marked; 2247 2198 qdisc_bstats_update(sch, skb); 2199 + WRITE_ONCE(q->last_active, now); 2248 2200 2249 2201 /* collect delay stats */ 2250 2202 delay = ktime_to_ns(ktime_sub(now, cobalt_get_enqueue_time(skb))); ··· 2346 2296 b->tin_rate_ns = rate_ns; 2347 2297 b->tin_rate_shft = rate_shft; 2348 2298 2299 + if (mtu == 0) 2300 + return; 2301 + 2349 2302 byte_target_ns = (byte_target * rate_ns) >> rate_shft; 2350 2303 2351 2304 b->cparams.target = max((byte_target_ns * 3) / 2, target_ns); ··· 2365 2312 struct cake_sched_data *q = qdisc_priv(sch); 2366 2313 struct cake_tin_data *b = &q->tins[0]; 2367 2314 u32 mtu = psched_mtu(qdisc_dev(sch)); 2368 - u64 rate = q->rate_bps; 2315 + u64 rate = q->config->rate_bps; 2369 2316 2370 2317 q->tin_cnt = 1; 2371 2318 ··· 2373 2320 q->tin_order = normal_order; 2374 2321 2375 2322 cake_set_rate(b, rate, mtu, 2376 - us_to_ns(q->target), us_to_ns(q->interval)); 2323 + us_to_ns(q->config->target), us_to_ns(q->config->interval)); 2377 2324 b->tin_quantum = 65535; 2378 2325 2379 2326 return 0; ··· 2384 2331 /* convert high-level (user visible) parameters into internal format */ 2385 2332 struct cake_sched_data *q = qdisc_priv(sch); 2386 2333 u32 mtu = psched_mtu(qdisc_dev(sch)); 2387 - u64 rate = q->rate_bps; 2334 + u64 rate = q->config->rate_bps; 2388 2335 u32 quantum = 256; 2389 2336 u32 i; 2390 2337 ··· 2395 2342 for (i = 0; i < q->tin_cnt; i++) { 2396 2343 struct cake_tin_data *b = &q->tins[i]; 2397 2344 2398 - cake_set_rate(b, rate, mtu, us_to_ns(q->target), 2399 - us_to_ns(q->interval)); 2345 + cake_set_rate(b, rate, mtu, us_to_ns(q->config->target), 2346 + us_to_ns(q->config->interval)); 2400 2347 2401 2348 b->tin_quantum = max_t(u16, 1U, quantum); 2402 2349 ··· 2473 2420 2474 2421 struct cake_sched_data *q = qdisc_priv(sch); 2475 2422 u32 mtu = psched_mtu(qdisc_dev(sch)); 2476 - u64 rate = q->rate_bps; 2423 + u64 rate = q->config->rate_bps; 2477 2424 u32 quantum = 256; 2478 2425 u32 i; 2479 2426 ··· 2487 2434 for (i = 0; i < q->tin_cnt; i++) { 2488 2435 struct cake_tin_data *b = &q->tins[i]; 2489 2436 2490 - cake_set_rate(b, rate, mtu, us_to_ns(q->target), 2491 - us_to_ns(q->interval)); 2437 + cake_set_rate(b, rate, mtu, us_to_ns(q->config->target), 2438 + us_to_ns(q->config->interval)); 2492 2439 2493 2440 b->tin_quantum = max_t(u16, 1U, quantum); 2494 2441 ··· 2517 2464 2518 2465 struct cake_sched_data *q = qdisc_priv(sch); 2519 2466 u32 mtu = psched_mtu(qdisc_dev(sch)); 2520 - u64 rate = q->rate_bps; 2467 + u64 rate = q->config->rate_bps; 2521 2468 u32 quantum = 1024; 2522 2469 2523 2470 q->tin_cnt = 4; ··· 2528 2475 2529 2476 /* class characteristics */ 2530 2477 cake_set_rate(&q->tins[0], rate, mtu, 2531 - us_to_ns(q->target), us_to_ns(q->interval)); 2478 + us_to_ns(q->config->target), us_to_ns(q->config->interval)); 2532 2479 cake_set_rate(&q->tins[1], rate >> 4, mtu, 2533 - us_to_ns(q->target), us_to_ns(q->interval)); 2480 + us_to_ns(q->config->target), us_to_ns(q->config->interval)); 2534 2481 cake_set_rate(&q->tins[2], rate >> 1, mtu, 2535 - us_to_ns(q->target), us_to_ns(q->interval)); 2482 + us_to_ns(q->config->target), us_to_ns(q->config->interval)); 2536 2483 cake_set_rate(&q->tins[3], rate >> 2, mtu, 2537 - us_to_ns(q->target), us_to_ns(q->interval)); 2484 + us_to_ns(q->config->target), us_to_ns(q->config->interval)); 2538 2485 2539 2486 /* bandwidth-sharing weights */ 2540 2487 q->tins[0].tin_quantum = quantum; ··· 2554 2501 */ 2555 2502 struct cake_sched_data *q = qdisc_priv(sch); 2556 2503 u32 mtu = psched_mtu(qdisc_dev(sch)); 2557 - u64 rate = q->rate_bps; 2504 + u64 rate = q->config->rate_bps; 2558 2505 u32 quantum = 1024; 2559 2506 2560 2507 q->tin_cnt = 3; ··· 2565 2512 2566 2513 /* class characteristics */ 2567 2514 cake_set_rate(&q->tins[0], rate, mtu, 2568 - us_to_ns(q->target), us_to_ns(q->interval)); 2515 + us_to_ns(q->config->target), us_to_ns(q->config->interval)); 2569 2516 cake_set_rate(&q->tins[1], rate >> 4, mtu, 2570 - us_to_ns(q->target), us_to_ns(q->interval)); 2517 + us_to_ns(q->config->target), us_to_ns(q->config->interval)); 2571 2518 cake_set_rate(&q->tins[2], rate >> 2, mtu, 2572 - us_to_ns(q->target), us_to_ns(q->interval)); 2519 + us_to_ns(q->config->target), us_to_ns(q->config->interval)); 2573 2520 2574 2521 /* bandwidth-sharing weights */ 2575 2522 q->tins[0].tin_quantum = quantum; ··· 2581 2528 2582 2529 static void cake_reconfigure(struct Qdisc *sch) 2583 2530 { 2584 - struct cake_sched_data *q = qdisc_priv(sch); 2531 + struct cake_sched_data *qd = qdisc_priv(sch); 2532 + struct cake_sched_config *q = qd->config; 2585 2533 int c, ft; 2586 2534 2587 2535 switch (q->tin_mode) { ··· 2608 2554 break; 2609 2555 } 2610 2556 2611 - for (c = q->tin_cnt; c < CAKE_MAX_TINS; c++) { 2557 + for (c = qd->tin_cnt; c < CAKE_MAX_TINS; c++) { 2612 2558 cake_clear_tin(sch, c); 2613 - q->tins[c].cparams.mtu_time = q->tins[ft].cparams.mtu_time; 2559 + qd->tins[c].cparams.mtu_time = qd->tins[ft].cparams.mtu_time; 2614 2560 } 2615 2561 2616 - q->rate_ns = q->tins[ft].tin_rate_ns; 2617 - q->rate_shft = q->tins[ft].tin_rate_shft; 2562 + qd->rate_ns = qd->tins[ft].tin_rate_ns; 2563 + qd->rate_shft = qd->tins[ft].tin_rate_shft; 2618 2564 2619 2565 if (q->buffer_config_limit) { 2620 - q->buffer_limit = q->buffer_config_limit; 2566 + qd->buffer_limit = q->buffer_config_limit; 2621 2567 } else if (q->rate_bps) { 2622 2568 u64 t = q->rate_bps * q->interval; 2623 2569 2624 2570 do_div(t, USEC_PER_SEC / 4); 2625 - q->buffer_limit = max_t(u32, t, 4U << 20); 2571 + qd->buffer_limit = max_t(u32, t, 4U << 20); 2626 2572 } else { 2627 - q->buffer_limit = ~0; 2573 + qd->buffer_limit = ~0; 2628 2574 } 2629 2575 2630 2576 sch->flags &= ~TCQ_F_CAN_BYPASS; 2631 2577 2632 - q->buffer_limit = min(q->buffer_limit, 2633 - max(sch->limit * psched_mtu(qdisc_dev(sch)), 2634 - q->buffer_config_limit)); 2578 + qd->buffer_limit = min(qd->buffer_limit, 2579 + max(sch->limit * psched_mtu(qdisc_dev(sch)), 2580 + q->buffer_config_limit)); 2635 2581 } 2636 2582 2637 - static int cake_change(struct Qdisc *sch, struct nlattr *opt, 2638 - struct netlink_ext_ack *extack) 2583 + static int cake_config_change(struct cake_sched_config *q, struct nlattr *opt, 2584 + struct netlink_ext_ack *extack, bool *overhead_changed) 2639 2585 { 2640 - struct cake_sched_data *q = qdisc_priv(sch); 2641 2586 struct nlattr *tb[TCA_CAKE_MAX + 1]; 2642 - u16 rate_flags; 2643 - u8 flow_mode; 2587 + u16 rate_flags = q->rate_flags; 2588 + u8 flow_mode = q->flow_mode; 2644 2589 int err; 2645 2590 2646 2591 err = nla_parse_nested_deprecated(tb, TCA_CAKE_MAX, opt, cake_policy, ··· 2647 2594 if (err < 0) 2648 2595 return err; 2649 2596 2650 - flow_mode = q->flow_mode; 2651 2597 if (tb[TCA_CAKE_NAT]) { 2652 2598 #if IS_ENABLED(CONFIG_NF_CONNTRACK) 2653 2599 flow_mode &= ~CAKE_FLOW_NAT_FLAG; ··· 2659 2607 #endif 2660 2608 } 2661 2609 2610 + if (tb[TCA_CAKE_AUTORATE]) { 2611 + if (!!nla_get_u32(tb[TCA_CAKE_AUTORATE])) { 2612 + if (q->is_shared) { 2613 + NL_SET_ERR_MSG_ATTR(extack, tb[TCA_CAKE_AUTORATE], 2614 + "Can't use autorate-ingress with cake_mq"); 2615 + return -EOPNOTSUPP; 2616 + } 2617 + rate_flags |= CAKE_FLAG_AUTORATE_INGRESS; 2618 + } else { 2619 + rate_flags &= ~CAKE_FLAG_AUTORATE_INGRESS; 2620 + } 2621 + } 2622 + 2662 2623 if (tb[TCA_CAKE_BASE_RATE64]) 2663 2624 WRITE_ONCE(q->rate_bps, 2664 2625 nla_get_u64(tb[TCA_CAKE_BASE_RATE64])); ··· 2680 2615 WRITE_ONCE(q->tin_mode, 2681 2616 nla_get_u32(tb[TCA_CAKE_DIFFSERV_MODE])); 2682 2617 2683 - rate_flags = q->rate_flags; 2684 2618 if (tb[TCA_CAKE_WASH]) { 2685 2619 if (!!nla_get_u32(tb[TCA_CAKE_WASH])) 2686 2620 rate_flags |= CAKE_FLAG_WASH; ··· 2700 2636 WRITE_ONCE(q->rate_overhead, 2701 2637 nla_get_s32(tb[TCA_CAKE_OVERHEAD])); 2702 2638 rate_flags |= CAKE_FLAG_OVERHEAD; 2703 - 2704 - q->max_netlen = 0; 2705 - q->max_adjlen = 0; 2706 - q->min_netlen = ~0; 2707 - q->min_adjlen = ~0; 2639 + *overhead_changed = true; 2708 2640 } 2709 2641 2710 2642 if (tb[TCA_CAKE_RAW]) { 2711 2643 rate_flags &= ~CAKE_FLAG_OVERHEAD; 2712 - 2713 - q->max_netlen = 0; 2714 - q->max_adjlen = 0; 2715 - q->min_netlen = ~0; 2716 - q->min_adjlen = ~0; 2644 + *overhead_changed = true; 2717 2645 } 2718 2646 2719 2647 if (tb[TCA_CAKE_MPU]) ··· 2722 2666 u32 target = nla_get_u32(tb[TCA_CAKE_TARGET]); 2723 2667 2724 2668 WRITE_ONCE(q->target, max(target, 1U)); 2725 - } 2726 - 2727 - if (tb[TCA_CAKE_AUTORATE]) { 2728 - if (!!nla_get_u32(tb[TCA_CAKE_AUTORATE])) 2729 - rate_flags |= CAKE_FLAG_AUTORATE_INGRESS; 2730 - else 2731 - rate_flags &= ~CAKE_FLAG_AUTORATE_INGRESS; 2732 2669 } 2733 2670 2734 2671 if (tb[TCA_CAKE_INGRESS]) { ··· 2754 2705 2755 2706 WRITE_ONCE(q->rate_flags, rate_flags); 2756 2707 WRITE_ONCE(q->flow_mode, flow_mode); 2757 - if (q->tins) { 2708 + 2709 + return 0; 2710 + } 2711 + 2712 + static int cake_change(struct Qdisc *sch, struct nlattr *opt, 2713 + struct netlink_ext_ack *extack) 2714 + { 2715 + struct cake_sched_data *qd = qdisc_priv(sch); 2716 + struct cake_sched_config *q = qd->config; 2717 + bool overhead_changed = false; 2718 + int ret; 2719 + 2720 + if (q->is_shared) { 2721 + NL_SET_ERR_MSG(extack, "can't reconfigure cake_mq sub-qdiscs"); 2722 + return -EOPNOTSUPP; 2723 + } 2724 + 2725 + ret = cake_config_change(q, opt, extack, &overhead_changed); 2726 + if (ret) 2727 + return ret; 2728 + 2729 + if (overhead_changed) { 2730 + qd->max_netlen = 0; 2731 + qd->max_adjlen = 0; 2732 + qd->min_netlen = ~0; 2733 + qd->min_adjlen = ~0; 2734 + } 2735 + 2736 + if (qd->tins) { 2758 2737 sch_tree_lock(sch); 2759 2738 cake_reconfigure(sch); 2760 2739 sch_tree_unlock(sch); ··· 2798 2721 qdisc_watchdog_cancel(&q->watchdog); 2799 2722 tcf_block_put(q->block); 2800 2723 kvfree(q->tins); 2724 + if (q->config && !q->config->is_shared) 2725 + kvfree(q->config); 2801 2726 } 2802 2727 2803 - static int cake_init(struct Qdisc *sch, struct nlattr *opt, 2804 - struct netlink_ext_ack *extack) 2728 + static void cake_config_init(struct cake_sched_config *q, bool is_shared) 2805 2729 { 2806 - struct cake_sched_data *q = qdisc_priv(sch); 2807 - int i, j, err; 2808 - 2809 - sch->limit = 10240; 2810 - sch->flags |= TCQ_F_DEQUEUE_DROPS; 2811 - 2812 2730 q->tin_mode = CAKE_DIFFSERV_DIFFSERV3; 2813 2731 q->flow_mode = CAKE_FLOW_TRIPLE; 2814 2732 ··· 2814 2742 * for 5 to 10% of interval 2815 2743 */ 2816 2744 q->rate_flags |= CAKE_FLAG_SPLIT_GSO; 2817 - q->cur_tin = 0; 2818 - q->cur_flow = 0; 2745 + q->is_shared = is_shared; 2746 + q->sync_time = 200 * NSEC_PER_USEC; 2747 + } 2819 2748 2820 - qdisc_watchdog_init(&q->watchdog, sch); 2749 + static int cake_init(struct Qdisc *sch, struct nlattr *opt, 2750 + struct netlink_ext_ack *extack) 2751 + { 2752 + struct cake_sched_data *qd = qdisc_priv(sch); 2753 + struct cake_sched_config *q; 2754 + int i, j, err; 2755 + 2756 + q = kzalloc(sizeof(*q), GFP_KERNEL); 2757 + if (!q) 2758 + return -ENOMEM; 2759 + 2760 + cake_config_init(q, false); 2761 + 2762 + sch->limit = 10240; 2763 + sch->flags |= TCQ_F_DEQUEUE_DROPS; 2764 + 2765 + qd->cur_tin = 0; 2766 + qd->cur_flow = 0; 2767 + qd->config = q; 2768 + 2769 + qdisc_watchdog_init(&qd->watchdog, sch); 2821 2770 2822 2771 if (opt) { 2823 2772 err = cake_change(sch, opt, extack); 2824 2773 2825 2774 if (err) 2826 - return err; 2775 + goto err; 2827 2776 } 2828 2777 2829 - err = tcf_block_get(&q->block, &q->filter_list, sch, extack); 2778 + err = tcf_block_get(&qd->block, &qd->filter_list, sch, extack); 2830 2779 if (err) 2831 - return err; 2780 + goto err; 2832 2781 2833 2782 quantum_div[0] = ~0; 2834 2783 for (i = 1; i <= CAKE_QUEUES; i++) 2835 2784 quantum_div[i] = 65535 / i; 2836 2785 2837 - q->tins = kvcalloc(CAKE_MAX_TINS, sizeof(struct cake_tin_data), 2838 - GFP_KERNEL); 2839 - if (!q->tins) 2840 - return -ENOMEM; 2786 + qd->tins = kvcalloc(CAKE_MAX_TINS, sizeof(struct cake_tin_data), 2787 + GFP_KERNEL); 2788 + if (!qd->tins) { 2789 + err = -ENOMEM; 2790 + goto err; 2791 + } 2841 2792 2842 2793 for (i = 0; i < CAKE_MAX_TINS; i++) { 2843 - struct cake_tin_data *b = q->tins + i; 2794 + struct cake_tin_data *b = qd->tins + i; 2844 2795 2845 2796 INIT_LIST_HEAD(&b->new_flows); 2846 2797 INIT_LIST_HEAD(&b->old_flows); ··· 2879 2784 INIT_LIST_HEAD(&flow->flowchain); 2880 2785 cobalt_vars_init(&flow->cvars); 2881 2786 2882 - q->overflow_heap[k].t = i; 2883 - q->overflow_heap[k].b = j; 2787 + qd->overflow_heap[k].t = i; 2788 + qd->overflow_heap[k].b = j; 2884 2789 b->overflow_idx[j] = k; 2885 2790 } 2886 2791 } 2887 2792 2888 2793 cake_reconfigure(sch); 2889 - q->avg_peak_bandwidth = q->rate_bps; 2890 - q->min_netlen = ~0; 2891 - q->min_adjlen = ~0; 2794 + qd->avg_peak_bandwidth = q->rate_bps; 2795 + qd->min_netlen = ~0; 2796 + qd->min_adjlen = ~0; 2797 + qd->active_queues = 0; 2798 + qd->last_checked_active = 0; 2799 + 2892 2800 return 0; 2801 + err: 2802 + kvfree(qd->config); 2803 + qd->config = NULL; 2804 + return err; 2893 2805 } 2894 2806 2895 - static int cake_dump(struct Qdisc *sch, struct sk_buff *skb) 2807 + static void cake_config_replace(struct Qdisc *sch, struct cake_sched_config *cfg) 2896 2808 { 2897 - struct cake_sched_data *q = qdisc_priv(sch); 2809 + struct cake_sched_data *qd = qdisc_priv(sch); 2810 + struct cake_sched_config *q = qd->config; 2811 + 2812 + qd->config = cfg; 2813 + 2814 + if (!q->is_shared) 2815 + kvfree(q); 2816 + 2817 + cake_reconfigure(sch); 2818 + } 2819 + 2820 + static int cake_config_dump(struct cake_sched_config *q, struct sk_buff *skb) 2821 + { 2898 2822 struct nlattr *opts; 2899 2823 u16 rate_flags; 2900 2824 u8 flow_mode; ··· 2989 2875 return -1; 2990 2876 } 2991 2877 2878 + static int cake_dump(struct Qdisc *sch, struct sk_buff *skb) 2879 + { 2880 + struct cake_sched_data *qd = qdisc_priv(sch); 2881 + 2882 + return cake_config_dump(qd->config, skb); 2883 + } 2884 + 2992 2885 static int cake_dump_stats(struct Qdisc *sch, struct gnet_dump *d) 2993 2886 { 2994 2887 struct nlattr *stats = nla_nest_start_noflag(d->skb, TCA_STATS_APP); ··· 3024 2903 PUT_STAT_U32(MAX_ADJLEN, q->max_adjlen); 3025 2904 PUT_STAT_U32(MIN_NETLEN, q->min_netlen); 3026 2905 PUT_STAT_U32(MIN_ADJLEN, q->min_adjlen); 2906 + PUT_STAT_U32(ACTIVE_QUEUES, q->active_queues); 3027 2907 3028 2908 #undef PUT_STAT_U32 3029 2909 #undef PUT_STAT_U64 ··· 3258 3136 }; 3259 3137 MODULE_ALIAS_NET_SCH("cake"); 3260 3138 3139 + struct cake_mq_sched { 3140 + struct mq_sched mq_priv; /* must be first */ 3141 + struct cake_sched_config cake_config; 3142 + }; 3143 + 3144 + static void cake_mq_destroy(struct Qdisc *sch) 3145 + { 3146 + mq_destroy_common(sch); 3147 + } 3148 + 3149 + static int cake_mq_init(struct Qdisc *sch, struct nlattr *opt, 3150 + struct netlink_ext_ack *extack) 3151 + { 3152 + struct cake_mq_sched *priv = qdisc_priv(sch); 3153 + struct net_device *dev = qdisc_dev(sch); 3154 + int ret, ntx; 3155 + bool _unused; 3156 + 3157 + cake_config_init(&priv->cake_config, true); 3158 + if (opt) { 3159 + ret = cake_config_change(&priv->cake_config, opt, extack, &_unused); 3160 + if (ret) 3161 + return ret; 3162 + } 3163 + 3164 + ret = mq_init_common(sch, opt, extack, &cake_qdisc_ops); 3165 + if (ret) 3166 + return ret; 3167 + 3168 + for (ntx = 0; ntx < dev->num_tx_queues; ntx++) 3169 + cake_config_replace(priv->mq_priv.qdiscs[ntx], &priv->cake_config); 3170 + 3171 + return 0; 3172 + } 3173 + 3174 + static int cake_mq_dump(struct Qdisc *sch, struct sk_buff *skb) 3175 + { 3176 + struct cake_mq_sched *priv = qdisc_priv(sch); 3177 + 3178 + mq_dump_common(sch, skb); 3179 + return cake_config_dump(&priv->cake_config, skb); 3180 + } 3181 + 3182 + static int cake_mq_change(struct Qdisc *sch, struct nlattr *opt, 3183 + struct netlink_ext_ack *extack) 3184 + { 3185 + struct cake_mq_sched *priv = qdisc_priv(sch); 3186 + struct net_device *dev = qdisc_dev(sch); 3187 + bool overhead_changed = false; 3188 + unsigned int ntx; 3189 + int ret; 3190 + 3191 + ret = cake_config_change(&priv->cake_config, opt, extack, &overhead_changed); 3192 + if (ret) 3193 + return ret; 3194 + 3195 + for (ntx = 0; ntx < dev->num_tx_queues; ntx++) { 3196 + struct Qdisc *chld = rtnl_dereference(netdev_get_tx_queue(dev, ntx)->qdisc_sleeping); 3197 + struct cake_sched_data *qd = qdisc_priv(chld); 3198 + 3199 + if (overhead_changed) { 3200 + qd->max_netlen = 0; 3201 + qd->max_adjlen = 0; 3202 + qd->min_netlen = ~0; 3203 + qd->min_adjlen = ~0; 3204 + } 3205 + 3206 + if (qd->tins) { 3207 + sch_tree_lock(chld); 3208 + cake_reconfigure(chld); 3209 + sch_tree_unlock(chld); 3210 + } 3211 + } 3212 + 3213 + return 0; 3214 + } 3215 + 3216 + static int cake_mq_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new, 3217 + struct Qdisc **old, struct netlink_ext_ack *extack) 3218 + { 3219 + NL_SET_ERR_MSG(extack, "can't replace cake_mq sub-qdiscs"); 3220 + return -EOPNOTSUPP; 3221 + } 3222 + 3223 + static const struct Qdisc_class_ops cake_mq_class_ops = { 3224 + .select_queue = mq_select_queue, 3225 + .graft = cake_mq_graft, 3226 + .leaf = mq_leaf, 3227 + .find = mq_find, 3228 + .walk = mq_walk, 3229 + .dump = mq_dump_class, 3230 + .dump_stats = mq_dump_class_stats, 3231 + }; 3232 + 3233 + static struct Qdisc_ops cake_mq_qdisc_ops __read_mostly = { 3234 + .cl_ops = &cake_mq_class_ops, 3235 + .id = "cake_mq", 3236 + .priv_size = sizeof(struct cake_mq_sched), 3237 + .init = cake_mq_init, 3238 + .destroy = cake_mq_destroy, 3239 + .attach = mq_attach, 3240 + .change = cake_mq_change, 3241 + .change_real_num_tx = mq_change_real_num_tx, 3242 + .dump = cake_mq_dump, 3243 + .owner = THIS_MODULE, 3244 + }; 3245 + MODULE_ALIAS_NET_SCH("cake_mq"); 3246 + 3261 3247 static int __init cake_module_init(void) 3262 3248 { 3263 - return register_qdisc(&cake_qdisc_ops); 3249 + int ret; 3250 + 3251 + ret = register_qdisc(&cake_qdisc_ops); 3252 + if (ret) 3253 + return ret; 3254 + 3255 + ret = register_qdisc(&cake_mq_qdisc_ops); 3256 + if (ret) 3257 + unregister_qdisc(&cake_qdisc_ops); 3258 + 3259 + return ret; 3264 3260 } 3265 3261 3266 3262 static void __exit cake_module_exit(void) 3267 3263 { 3268 3264 unregister_qdisc(&cake_qdisc_ops); 3265 + unregister_qdisc(&cake_mq_qdisc_ops); 3269 3266 } 3270 3267 3271 3268 module_init(cake_module_init) ··· 3392 3151 MODULE_AUTHOR("Jonathan Morton"); 3393 3152 MODULE_LICENSE("Dual BSD/GPL"); 3394 3153 MODULE_DESCRIPTION("The CAKE shaper."); 3154 + MODULE_IMPORT_NS("NET_SCHED_INTERNAL");
+49 -22
net/sched/sch_mq.c
··· 15 15 #include <net/netlink.h> 16 16 #include <net/pkt_cls.h> 17 17 #include <net/pkt_sched.h> 18 - #include <net/sch_generic.h> 19 - 20 - struct mq_sched { 21 - struct Qdisc **qdiscs; 22 - }; 18 + #include <net/sch_priv.h> 23 19 24 20 static int mq_offload(struct Qdisc *sch, enum tc_mq_command cmd) 25 21 { ··· 45 49 return qdisc_offload_dump_helper(sch, TC_SETUP_QDISC_MQ, &opt); 46 50 } 47 51 48 - static void mq_destroy(struct Qdisc *sch) 52 + void mq_destroy_common(struct Qdisc *sch) 49 53 { 50 54 struct net_device *dev = qdisc_dev(sch); 51 55 struct mq_sched *priv = qdisc_priv(sch); 52 56 unsigned int ntx; 53 - 54 - mq_offload(sch, TC_MQ_DESTROY); 55 57 56 58 if (!priv->qdiscs) 57 59 return; ··· 57 63 qdisc_put(priv->qdiscs[ntx]); 58 64 kfree(priv->qdiscs); 59 65 } 66 + EXPORT_SYMBOL_NS_GPL(mq_destroy_common, "NET_SCHED_INTERNAL"); 60 67 61 - static int mq_init(struct Qdisc *sch, struct nlattr *opt, 62 - struct netlink_ext_ack *extack) 68 + static void mq_destroy(struct Qdisc *sch) 69 + { 70 + mq_offload(sch, TC_MQ_DESTROY); 71 + mq_destroy_common(sch); 72 + } 73 + 74 + int mq_init_common(struct Qdisc *sch, struct nlattr *opt, 75 + struct netlink_ext_ack *extack, 76 + const struct Qdisc_ops *qdisc_ops) 63 77 { 64 78 struct net_device *dev = qdisc_dev(sch); 65 79 struct mq_sched *priv = qdisc_priv(sch); ··· 89 87 90 88 for (ntx = 0; ntx < dev->num_tx_queues; ntx++) { 91 89 dev_queue = netdev_get_tx_queue(dev, ntx); 92 - qdisc = qdisc_create_dflt(dev_queue, get_default_qdisc_ops(dev, ntx), 90 + qdisc = qdisc_create_dflt(dev_queue, 91 + qdisc_ops ?: get_default_qdisc_ops(dev, ntx), 93 92 TC_H_MAKE(TC_H_MAJ(sch->handle), 94 93 TC_H_MIN(ntx + 1)), 95 94 extack); ··· 101 98 } 102 99 103 100 sch->flags |= TCQ_F_MQROOT; 101 + return 0; 102 + } 103 + EXPORT_SYMBOL_NS_GPL(mq_init_common, "NET_SCHED_INTERNAL"); 104 + 105 + static int mq_init(struct Qdisc *sch, struct nlattr *opt, 106 + struct netlink_ext_ack *extack) 107 + { 108 + int ret; 109 + 110 + ret = mq_init_common(sch, opt, extack, NULL); 111 + if (ret) 112 + return ret; 104 113 105 114 mq_offload(sch, TC_MQ_CREATE); 106 115 return 0; 107 116 } 108 117 109 - static void mq_attach(struct Qdisc *sch) 118 + void mq_attach(struct Qdisc *sch) 110 119 { 111 120 struct net_device *dev = qdisc_dev(sch); 112 121 struct mq_sched *priv = qdisc_priv(sch); ··· 139 124 kfree(priv->qdiscs); 140 125 priv->qdiscs = NULL; 141 126 } 127 + EXPORT_SYMBOL_NS_GPL(mq_attach, "NET_SCHED_INTERNAL"); 142 128 143 - static int mq_dump(struct Qdisc *sch, struct sk_buff *skb) 129 + void mq_dump_common(struct Qdisc *sch, struct sk_buff *skb) 144 130 { 145 131 struct net_device *dev = qdisc_dev(sch); 146 132 struct Qdisc *qdisc; ··· 168 152 169 153 spin_unlock_bh(qdisc_lock(qdisc)); 170 154 } 155 + } 156 + EXPORT_SYMBOL_NS_GPL(mq_dump_common, "NET_SCHED_INTERNAL"); 171 157 158 + static int mq_dump(struct Qdisc *sch, struct sk_buff *skb) 159 + { 160 + mq_dump_common(sch, skb); 172 161 return mq_offload_stats(sch); 173 162 } 174 163 ··· 187 166 return netdev_get_tx_queue(dev, ntx); 188 167 } 189 168 190 - static struct netdev_queue *mq_select_queue(struct Qdisc *sch, 191 - struct tcmsg *tcm) 169 + struct netdev_queue *mq_select_queue(struct Qdisc *sch, 170 + struct tcmsg *tcm) 192 171 { 193 172 return mq_queue_get(sch, TC_H_MIN(tcm->tcm_parent)); 194 173 } 174 + EXPORT_SYMBOL_NS_GPL(mq_select_queue, "NET_SCHED_INTERNAL"); 195 175 196 176 static int mq_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new, 197 177 struct Qdisc **old, struct netlink_ext_ack *extack) ··· 220 198 return 0; 221 199 } 222 200 223 - static struct Qdisc *mq_leaf(struct Qdisc *sch, unsigned long cl) 201 + struct Qdisc *mq_leaf(struct Qdisc *sch, unsigned long cl) 224 202 { 225 203 struct netdev_queue *dev_queue = mq_queue_get(sch, cl); 226 204 227 205 return rtnl_dereference(dev_queue->qdisc_sleeping); 228 206 } 207 + EXPORT_SYMBOL_NS_GPL(mq_leaf, "NET_SCHED_INTERNAL"); 229 208 230 - static unsigned long mq_find(struct Qdisc *sch, u32 classid) 209 + unsigned long mq_find(struct Qdisc *sch, u32 classid) 231 210 { 232 211 unsigned int ntx = TC_H_MIN(classid); 233 212 ··· 236 213 return 0; 237 214 return ntx; 238 215 } 216 + EXPORT_SYMBOL_NS_GPL(mq_find, "NET_SCHED_INTERNAL"); 239 217 240 - static int mq_dump_class(struct Qdisc *sch, unsigned long cl, 241 - struct sk_buff *skb, struct tcmsg *tcm) 218 + int mq_dump_class(struct Qdisc *sch, unsigned long cl, 219 + struct sk_buff *skb, struct tcmsg *tcm) 242 220 { 243 221 struct netdev_queue *dev_queue = mq_queue_get(sch, cl); 244 222 ··· 248 224 tcm->tcm_info = rtnl_dereference(dev_queue->qdisc_sleeping)->handle; 249 225 return 0; 250 226 } 227 + EXPORT_SYMBOL_NS_GPL(mq_dump_class, "NET_SCHED_INTERNAL"); 251 228 252 - static int mq_dump_class_stats(struct Qdisc *sch, unsigned long cl, 253 - struct gnet_dump *d) 229 + int mq_dump_class_stats(struct Qdisc *sch, unsigned long cl, 230 + struct gnet_dump *d) 254 231 { 255 232 struct netdev_queue *dev_queue = mq_queue_get(sch, cl); 256 233 ··· 261 236 return -1; 262 237 return 0; 263 238 } 239 + EXPORT_SYMBOL_NS_GPL(mq_dump_class_stats, "NET_SCHED_INTERNAL"); 264 240 265 - static void mq_walk(struct Qdisc *sch, struct qdisc_walker *arg) 241 + void mq_walk(struct Qdisc *sch, struct qdisc_walker *arg) 266 242 { 267 243 struct net_device *dev = qdisc_dev(sch); 268 244 unsigned int ntx; ··· 277 251 break; 278 252 } 279 253 } 254 + EXPORT_SYMBOL_NS_GPL(mq_walk, "NET_SCHED_INTERNAL"); 280 255 281 256 static const struct Qdisc_class_ops mq_class_ops = { 282 257 .select_queue = mq_select_queue,
+559
tools/testing/selftests/tc-testing/tc-tests/qdiscs/cake_mq.json
··· 1 + [ 2 + { 3 + "id": "684b", 4 + "name": "Create CAKE_MQ with default setting (4 queues)", 5 + "category": [ 6 + "qdisc", 7 + "cake_mq" 8 + ], 9 + "plugins": { 10 + "requires": "nsPlugin" 11 + }, 12 + "setup": [ 13 + "echo \"1\" > /sys/bus/netdevsim/del_device || true", 14 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 15 + ], 16 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq", 17 + "expExitCode": "0", 18 + "verifyCmd": "$TC qdisc show dev $ETH", 19 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", 20 + "matchCount": "5", 21 + "teardown": [ 22 + "echo \"1\" > /sys/bus/netdevsim/del_device" 23 + ] 24 + }, 25 + { 26 + "id": "7ee8", 27 + "name": "Create CAKE_MQ with bandwidth limit (4 queues)", 28 + "category": [ 29 + "qdisc", 30 + "cake_mq" 31 + ], 32 + "plugins": { 33 + "requires": "nsPlugin" 34 + }, 35 + "setup": [ 36 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 37 + ], 38 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq bandwidth 1000", 39 + "expExitCode": "0", 40 + "verifyCmd": "$TC qdisc show dev $ETH", 41 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth 1Kbit diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", 42 + "matchCount": "5", 43 + "teardown": [ 44 + "echo \"1\" > /sys/bus/netdevsim/del_device" 45 + ] 46 + }, 47 + { 48 + "id": "1f87", 49 + "name": "Create CAKE_MQ with rtt time (4 queues)", 50 + "category": [ 51 + "qdisc", 52 + "cake_mq" 53 + ], 54 + "plugins": { 55 + "requires": "nsPlugin" 56 + }, 57 + "setup": [ 58 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 59 + ], 60 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq rtt 200", 61 + "expExitCode": "0", 62 + "verifyCmd": "$TC qdisc show dev $ETH", 63 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 200us raw overhead 0 ", 64 + "matchCount": "5", 65 + "teardown": [ 66 + "echo \"1\" > /sys/bus/netdevsim/del_device" 67 + ] 68 + }, 69 + { 70 + "id": "e9cf", 71 + "name": "Create CAKE_MQ with besteffort flag (4 queues)", 72 + "category": [ 73 + "qdisc", 74 + "cake_mq" 75 + ], 76 + "plugins": { 77 + "requires": "nsPlugin" 78 + }, 79 + "setup": [ 80 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 81 + ], 82 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq besteffort", 83 + "expExitCode": "0", 84 + "verifyCmd": "$TC qdisc show dev $ETH", 85 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited besteffort triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", 86 + "matchCount": "5", 87 + "teardown": [ 88 + "echo \"1\" > /sys/bus/netdevsim/del_device" 89 + ] 90 + }, 91 + { 92 + "id": "7c05", 93 + "name": "Create CAKE_MQ with diffserv8 flag (4 queues)", 94 + "category": [ 95 + "qdisc", 96 + "cake_mq" 97 + ], 98 + "plugins": { 99 + "requires": "nsPlugin" 100 + }, 101 + "setup": [ 102 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 103 + ], 104 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq diffserv8", 105 + "expExitCode": "0", 106 + "verifyCmd": "$TC qdisc show dev $ETH", 107 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv8 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", 108 + "matchCount": "5", 109 + "teardown": [ 110 + "echo \"1\" > /sys/bus/netdevsim/del_device" 111 + ] 112 + }, 113 + { 114 + "id": "5a77", 115 + "name": "Create CAKE_MQ with diffserv4 flag (4 queues)", 116 + "category": [ 117 + "qdisc", 118 + "cake_mq" 119 + ], 120 + "plugins": { 121 + "requires": "nsPlugin" 122 + }, 123 + "setup": [ 124 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 125 + ], 126 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq diffserv4", 127 + "expExitCode": "0", 128 + "verifyCmd": "$TC qdisc show dev $ETH", 129 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv4 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", 130 + "matchCount": "5", 131 + "teardown": [ 132 + "echo \"1\" > /sys/bus/netdevsim/del_device" 133 + ] 134 + }, 135 + { 136 + "id": "8f7a", 137 + "name": "Create CAKE_MQ with flowblind flag (4 queues)", 138 + "category": [ 139 + "qdisc", 140 + "cake_mq" 141 + ], 142 + "plugins": { 143 + "requires": "nsPlugin" 144 + }, 145 + "setup": [ 146 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 147 + ], 148 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq flowblind", 149 + "expExitCode": "0", 150 + "verifyCmd": "$TC qdisc show dev $ETH", 151 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 flowblind nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", 152 + "matchCount": "5", 153 + "teardown": [ 154 + "echo \"1\" > /sys/bus/netdevsim/del_device" 155 + ] 156 + }, 157 + { 158 + "id": "7ef7", 159 + "name": "Create CAKE_MQ with dsthost and nat flag (4 queues)", 160 + "category": [ 161 + "qdisc", 162 + "cake_mq" 163 + ], 164 + "plugins": { 165 + "requires": "nsPlugin" 166 + }, 167 + "setup": [ 168 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 169 + ], 170 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq dsthost nat", 171 + "expExitCode": "0", 172 + "verifyCmd": "$TC qdisc show dev $ETH", 173 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 dsthost nat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", 174 + "matchCount": "5", 175 + "teardown": [ 176 + "echo \"1\" > /sys/bus/netdevsim/del_device" 177 + ] 178 + }, 179 + { 180 + "id": "2e4d", 181 + "name": "Create CAKE_MQ with wash flag (4 queues)", 182 + "category": [ 183 + "qdisc", 184 + "cake_mq" 185 + ], 186 + "plugins": { 187 + "requires": "nsPlugin" 188 + }, 189 + "setup": [ 190 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 191 + ], 192 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq hosts wash", 193 + "expExitCode": "0", 194 + "verifyCmd": "$TC qdisc show dev $ETH", 195 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 hosts nonat wash no-ack-filter split-gso rtt 100ms raw overhead 0 ", 196 + "matchCount": "5", 197 + "teardown": [ 198 + "echo \"1\" > /sys/bus/netdevsim/del_device" 199 + ] 200 + }, 201 + { 202 + "id": "b3e6", 203 + "name": "Create CAKE_MQ with flowblind and no-split-gso flag (4 queues)", 204 + "category": [ 205 + "qdisc", 206 + "cake_mq" 207 + ], 208 + "plugins": { 209 + "requires": "nsPlugin" 210 + }, 211 + "setup": [ 212 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 213 + ], 214 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq flowblind no-split-gso", 215 + "expExitCode": "0", 216 + "verifyCmd": "$TC qdisc show dev $ETH", 217 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 flowblind nonat nowash no-ack-filter no-split-gso rtt 100ms raw overhead 0 ", 218 + "matchCount": "5", 219 + "teardown": [ 220 + "echo \"1\" > /sys/bus/netdevsim/del_device" 221 + ] 222 + }, 223 + { 224 + "id": "62cd", 225 + "name": "Create CAKE_MQ with dual-srchost and ack-filter flag (4 queues)", 226 + "category": [ 227 + "qdisc", 228 + "cake_mq" 229 + ], 230 + "plugins": { 231 + "requires": "nsPlugin" 232 + }, 233 + "setup": [ 234 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 235 + ], 236 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq dual-srchost ack-filter", 237 + "expExitCode": "0", 238 + "verifyCmd": "$TC qdisc show dev $ETH", 239 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 dual-srchost nonat nowash ack-filter split-gso rtt 100ms raw overhead 0 ", 240 + "matchCount": "5", 241 + "teardown": [ 242 + "echo \"1\" > /sys/bus/netdevsim/del_device" 243 + ] 244 + }, 245 + { 246 + "id": "0df3", 247 + "name": "Create CAKE_MQ with dual-dsthost and ack-filter-aggressive flag (4 queues)", 248 + "category": [ 249 + "qdisc", 250 + "cake_mq" 251 + ], 252 + "plugins": { 253 + "requires": "nsPlugin" 254 + }, 255 + "setup": [ 256 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 257 + ], 258 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq dual-dsthost ack-filter-aggressive", 259 + "expExitCode": "0", 260 + "verifyCmd": "$TC qdisc show dev $ETH", 261 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 dual-dsthost nonat nowash ack-filter-aggressive split-gso rtt 100ms raw overhead 0 ", 262 + "matchCount": "5", 263 + "teardown": [ 264 + "echo \"1\" > /sys/bus/netdevsim/del_device" 265 + ] 266 + }, 267 + { 268 + "id": "9a75", 269 + "name": "Create CAKE_MQ with memlimit and ptm flag (4 queues)", 270 + "category": [ 271 + "qdisc", 272 + "cake_mq" 273 + ], 274 + "plugins": { 275 + "requires": "nsPlugin" 276 + }, 277 + "setup": [ 278 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 279 + ], 280 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq memlimit 10000 ptm", 281 + "expExitCode": "0", 282 + "verifyCmd": "$TC qdisc show dev $ETH", 283 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw ptm overhead 0 memlimit 10000b ", 284 + "matchCount": "5", 285 + "teardown": [ 286 + "echo \"1\" > /sys/bus/netdevsim/del_device" 287 + ] 288 + }, 289 + { 290 + "id": "cdef", 291 + "name": "Create CAKE_MQ with fwmark and atm flag (4 queues)", 292 + "category": [ 293 + "qdisc", 294 + "cake_mq" 295 + ], 296 + "plugins": { 297 + "requires": "nsPlugin" 298 + }, 299 + "setup": [ 300 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 301 + ], 302 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq fwmark 8 atm", 303 + "expExitCode": "0", 304 + "verifyCmd": "$TC qdisc show dev $ETH", 305 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw atm overhead 0 fwmark 0x8 ", 306 + "matchCount": "5", 307 + "teardown": [ 308 + "echo \"1\" > /sys/bus/netdevsim/del_device" 309 + ] 310 + }, 311 + { 312 + "id": "93dd", 313 + "name": "Create CAKE_MQ with overhead 0 and mpu (4 queues)", 314 + "category": [ 315 + "qdisc", 316 + "cake_mq" 317 + ], 318 + "plugins": { 319 + "requires": "nsPlugin" 320 + }, 321 + "setup": [ 322 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 323 + ], 324 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq overhead 128 mpu 256", 325 + "expExitCode": "0", 326 + "verifyCmd": "$TC qdisc show dev $ETH", 327 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms noatm overhead 128 mpu 256 ", 328 + "matchCount": "5", 329 + "teardown": [ 330 + "echo \"1\" > /sys/bus/netdevsim/del_device" 331 + ] 332 + }, 333 + { 334 + "id": "1475", 335 + "name": "Create CAKE_MQ with conservative and ingress flag (4 queues)", 336 + "category": [ 337 + "qdisc", 338 + "cake_mq" 339 + ], 340 + "plugins": { 341 + "requires": "nsPlugin" 342 + }, 343 + "setup": [ 344 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 345 + ], 346 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq conservative ingress", 347 + "expExitCode": "0", 348 + "verifyCmd": "$TC qdisc show dev $ETH", 349 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash ingress no-ack-filter split-gso rtt 100ms atm overhead 48 ", 350 + "matchCount": "5", 351 + "teardown": [ 352 + "echo \"1\" > /sys/bus/netdevsim/del_device" 353 + ] 354 + }, 355 + { 356 + "id": "7bf1", 357 + "name": "Delete CAKE_MQ with conservative and ingress flag (4 queues)", 358 + "category": [ 359 + "qdisc", 360 + "cake_mq" 361 + ], 362 + "plugins": { 363 + "requires": "nsPlugin" 364 + }, 365 + "setup": [ 366 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device", 367 + "$TC qdisc add dev $ETH handle 1: root cake_mq conservative ingress" 368 + ], 369 + "cmdUnderTest": "$TC qdisc del dev $ETH handle 1: root", 370 + "expExitCode": "0", 371 + "verifyCmd": "$TC qdisc show dev $ETH", 372 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash ingress no-ack-filter split-gso rtt 100ms atm overhead 48 ", 373 + "matchCount": "0", 374 + "teardown": [ 375 + "echo \"1\" > /sys/bus/netdevsim/del_device" 376 + ] 377 + }, 378 + { 379 + "id": "ee55", 380 + "name": "Replace CAKE_MQ with mpu (4 queues)", 381 + "category": [ 382 + "qdisc", 383 + "cake_mq" 384 + ], 385 + "plugins": { 386 + "requires": "nsPlugin" 387 + }, 388 + "setup": [ 389 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device", 390 + "$TC qdisc add dev $ETH handle 1: root cake_mq overhead 128 mpu 256" 391 + ], 392 + "cmdUnderTest": "$TC qdisc replace dev $ETH handle 1: root cake_mq mpu 128", 393 + "expExitCode": "0", 394 + "verifyCmd": "$TC qdisc show dev $ETH", 395 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms noatm overhead 128 mpu 128 ", 396 + "matchCount": "5", 397 + "teardown": [ 398 + "echo \"1\" > /sys/bus/netdevsim/del_device" 399 + ] 400 + }, 401 + { 402 + "id": "6df9", 403 + "name": "Change CAKE_MQ with mpu (4 queues)", 404 + "category": [ 405 + "qdisc", 406 + "cake_mq" 407 + ], 408 + "plugins": { 409 + "requires": "nsPlugin" 410 + }, 411 + "setup": [ 412 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device", 413 + "$TC qdisc add dev $ETH handle 1: root cake_mq overhead 128 mpu 256" 414 + ], 415 + "cmdUnderTest": "$TC qdisc change dev $ETH handle 1: root cake_mq mpu 128", 416 + "expExitCode": "0", 417 + "verifyCmd": "$TC qdisc show dev $ETH", 418 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms noatm overhead 128 mpu 128 ", 419 + "matchCount": "5", 420 + "teardown": [ 421 + "echo \"1\" > /sys/bus/netdevsim/del_device" 422 + ] 423 + }, 424 + { 425 + "id": "67e2", 426 + "name": "Show CAKE_MQ class (4 queues)", 427 + "category": [ 428 + "qdisc", 429 + "cake_mq" 430 + ], 431 + "plugins": { 432 + "requires": "nsPlugin" 433 + }, 434 + "setup": [ 435 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 436 + ], 437 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq", 438 + "expExitCode": "0", 439 + "verifyCmd": "$TC class show dev $ETH", 440 + "matchPattern": "class cake_mq", 441 + "matchCount": "4", 442 + "teardown": [ 443 + "echo \"1\" > /sys/bus/netdevsim/del_device" 444 + ] 445 + }, 446 + { 447 + "id": "2de4", 448 + "name": "Change bandwidth of CAKE_MQ (4 queues)", 449 + "category": [ 450 + "qdisc", 451 + "cake_mq" 452 + ], 453 + "plugins": { 454 + "requires": "nsPlugin" 455 + }, 456 + "setup": [ 457 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device", 458 + "$TC qdisc add dev $ETH handle 1: root cake_mq" 459 + ], 460 + "cmdUnderTest": "$TC qdisc replace dev $ETH handle 1: root cake_mq bandwidth 1000", 461 + "expExitCode": "0", 462 + "verifyCmd": "$TC qdisc show dev $ETH", 463 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth 1Kbit diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", 464 + "matchCount": "5", 465 + "teardown": [ 466 + "echo \"1\" > /sys/bus/netdevsim/del_device" 467 + ] 468 + }, 469 + { 470 + "id": "5f62", 471 + "name": "Fail to create CAKE_MQ with autorate-ingress flag (4 queues)", 472 + "category": [ 473 + "qdisc", 474 + "cake_mq" 475 + ], 476 + "plugins": { 477 + "requires": "nsPlugin" 478 + }, 479 + "setup": [ 480 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" 481 + ], 482 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq autorate-ingress", 483 + "expExitCode": "2", 484 + "verifyCmd": "$TC qdisc show dev $ETH", 485 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited autorate-ingress diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", 486 + "matchCount": "0", 487 + "teardown": [ 488 + "echo \"1\" > /sys/bus/netdevsim/del_device" 489 + ] 490 + }, 491 + { 492 + "id": "038e", 493 + "name": "Fail to change setting of sub-qdisc under CAKE_MQ", 494 + "category": [ 495 + "qdisc", 496 + "cake_mq" 497 + ], 498 + "plugins": { 499 + "requires": "nsPlugin" 500 + }, 501 + "setup": [ 502 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device", 503 + "$TC qdisc add dev $ETH handle 1: root cake_mq" 504 + ], 505 + "cmdUnderTest": "$TC qdisc add dev $ETH parent 1:1 cake besteffort flows", 506 + "expExitCode": "2", 507 + "verifyCmd": "$TC qdisc show dev $ETH", 508 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", 509 + "matchCount": "5", 510 + "teardown": [ 511 + "echo \"1\" > /sys/bus/netdevsim/del_device" 512 + ] 513 + }, 514 + { 515 + "id": "7bdc", 516 + "name": "Fail to replace sub-qdisc under CAKE_MQ", 517 + "category": [ 518 + "qdisc", 519 + "cake_mq" 520 + ], 521 + "plugins": { 522 + "requires": "nsPlugin" 523 + }, 524 + "setup": [ 525 + "echo \"1 1 4\" > /sys/bus/netdevsim/new_device", 526 + "$TC qdisc add dev $ETH handle 1: root cake_mq" 527 + ], 528 + "cmdUnderTest": "$TC qdisc add dev $ETH parent 1:1 fq", 529 + "expExitCode": "2", 530 + "verifyCmd": "$TC qdisc show dev $ETH", 531 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", 532 + "matchCount": "5", 533 + "teardown": [ 534 + "echo \"1\" > /sys/bus/netdevsim/del_device" 535 + ] 536 + }, 537 + { 538 + "id": "18e0", 539 + "name": "Fail to install CAKE_MQ on single queue device", 540 + "category": [ 541 + "qdisc", 542 + "cake_mq" 543 + ], 544 + "plugins": { 545 + "requires": "nsPlugin" 546 + }, 547 + "setup": [ 548 + "echo \"1 1 1\" > /sys/bus/netdevsim/new_device" 549 + ], 550 + "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq", 551 + "expExitCode": "2", 552 + "verifyCmd": "$TC qdisc show dev $ETH", 553 + "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", 554 + "matchCount": "0", 555 + "teardown": [ 556 + "echo \"1\" > /sys/bus/netdevsim/del_device" 557 + ] 558 + } 559 + ]