~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/drivers/net/stats.py

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #!/usr/bin/env python3
  2 # SPDX-License-Identifier: GPL-2.0
  3 
  4 import errno
  5 from lib.py import ksft_run, ksft_exit, ksft_pr
  6 from lib.py import ksft_ge, ksft_eq, ksft_in, ksft_true, ksft_raises, KsftSkipEx, KsftXfailEx
  7 from lib.py import ksft_disruptive
  8 from lib.py import EthtoolFamily, NetdevFamily, RtnlFamily, NlError
  9 from lib.py import NetDrvEnv
 10 from lib.py import ip, defer
 11 
 12 ethnl = EthtoolFamily()
 13 netfam = NetdevFamily()
 14 rtnl = RtnlFamily()
 15 
 16 
 17 def check_pause(cfg) -> None:
 18     global ethnl
 19 
 20     try:
 21         ethnl.pause_get({"header": {"dev-index": cfg.ifindex}})
 22     except NlError as e:
 23         if e.error == errno.EOPNOTSUPP:
 24             raise KsftXfailEx("pause not supported by the device")
 25         raise
 26 
 27     data = ethnl.pause_get({"header": {"dev-index": cfg.ifindex,
 28                                        "flags": {'stats'}}})
 29     ksft_true(data['stats'], "driver does not report stats")
 30 
 31 
 32 def check_fec(cfg) -> None:
 33     global ethnl
 34 
 35     try:
 36         ethnl.fec_get({"header": {"dev-index": cfg.ifindex}})
 37     except NlError as e:
 38         if e.error == errno.EOPNOTSUPP:
 39             raise KsftXfailEx("FEC not supported by the device")
 40         raise
 41 
 42     data = ethnl.fec_get({"header": {"dev-index": cfg.ifindex,
 43                                      "flags": {'stats'}}})
 44     ksft_true(data['stats'], "driver does not report stats")
 45 
 46 
 47 def pkt_byte_sum(cfg) -> None:
 48     global netfam, rtnl
 49 
 50     def get_qstat(test):
 51         global netfam
 52         stats = netfam.qstats_get({}, dump=True)
 53         if stats:
 54             for qs in stats:
 55                 if qs["ifindex"]== test.ifindex:
 56                     return qs
 57 
 58     qstat = get_qstat(cfg)
 59     if qstat is None:
 60         raise KsftSkipEx("qstats not supported by the device")
 61 
 62     for key in ['tx-packets', 'tx-bytes', 'rx-packets', 'rx-bytes']:
 63         ksft_in(key, qstat, "Drivers should always report basic keys")
 64 
 65     # Compare stats, rtnl stats and qstats must match,
 66     # but the interface may be up, so do a series of dumps
 67     # each time the more "recent" stats must be higher or same.
 68     def stat_cmp(rstat, qstat):
 69         for key in ['tx-packets', 'tx-bytes', 'rx-packets', 'rx-bytes']:
 70             if rstat[key] != qstat[key]:
 71                 return rstat[key] - qstat[key]
 72         return 0
 73 
 74     for _ in range(10):
 75         rtstat = rtnl.getlink({"ifi-index": cfg.ifindex})['stats64']
 76         if stat_cmp(rtstat, qstat) < 0:
 77             raise Exception("RTNL stats are lower, fetched later")
 78         qstat = get_qstat(cfg)
 79         if stat_cmp(rtstat, qstat) > 0:
 80             raise Exception("Qstats are lower, fetched later")
 81 
 82 
 83 def qstat_by_ifindex(cfg) -> None:
 84     global netfam
 85     global rtnl
 86 
 87     # Construct a map ifindex -> [dump, by-index, dump]
 88     ifindexes = {}
 89     stats = netfam.qstats_get({}, dump=True)
 90     for entry in stats:
 91         ifindexes[entry['ifindex']] = [entry, None, None]
 92 
 93     for ifindex in ifindexes.keys():
 94         entry = netfam.qstats_get({"ifindex": ifindex}, dump=True)
 95         ksft_eq(len(entry), 1)
 96         ifindexes[entry[0]['ifindex']][1] = entry[0]
 97 
 98     stats = netfam.qstats_get({}, dump=True)
 99     for entry in stats:
100         ifindexes[entry['ifindex']][2] = entry
101 
102     if len(ifindexes) == 0:
103         raise KsftSkipEx("No ifindex supports qstats")
104 
105     # Now make sure the stats match/make sense
106     for ifindex, triple in ifindexes.items():
107         all_keys = triple[0].keys() | triple[1].keys() | triple[2].keys()
108 
109         for key in all_keys:
110             ksft_ge(triple[1][key], triple[0][key], comment="bad key: " + key)
111             ksft_ge(triple[2][key], triple[1][key], comment="bad key: " + key)
112 
113     # Test invalid dumps
114     # 0 is invalid
115     with ksft_raises(NlError) as cm:
116         netfam.qstats_get({"ifindex": 0}, dump=True)
117     ksft_eq(cm.exception.nl_msg.error, -34)
118     ksft_eq(cm.exception.nl_msg.extack['bad-attr'], '.ifindex')
119 
120     # loopback has no stats
121     with ksft_raises(NlError) as cm:
122         netfam.qstats_get({"ifindex": 1}, dump=True)
123     ksft_eq(cm.exception.nl_msg.error, -errno.EOPNOTSUPP)
124     ksft_eq(cm.exception.nl_msg.extack['bad-attr'], '.ifindex')
125 
126     # Try to get stats for lowest unused ifindex but not 0
127     devs = rtnl.getlink({}, dump=True)
128     all_ifindexes = set([dev["ifi-index"] for dev in devs])
129     lowest = 2
130     while lowest in all_ifindexes:
131         lowest += 1
132 
133     with ksft_raises(NlError) as cm:
134         netfam.qstats_get({"ifindex": lowest}, dump=True)
135     ksft_eq(cm.exception.nl_msg.error, -19)
136     ksft_eq(cm.exception.nl_msg.extack['bad-attr'], '.ifindex')
137 
138 
139 @ksft_disruptive
140 def check_down(cfg) -> None:
141     try:
142         qstat = netfam.qstats_get({"ifindex": cfg.ifindex}, dump=True)[0]
143     except NlError as e:
144         if e.error == errno.EOPNOTSUPP:
145             raise KsftSkipEx("qstats not supported by the device")
146         raise
147 
148     ip(f"link set dev {cfg.dev['ifname']} down")
149     defer(ip, f"link set dev {cfg.dev['ifname']} up")
150 
151     qstat2 = netfam.qstats_get({"ifindex": cfg.ifindex}, dump=True)[0]
152     for k, v in qstat.items():
153         ksft_ge(qstat2[k], qstat[k], comment=f"{k} went backwards on device down")
154 
155     # exercise per-queue API to make sure that "device down" state
156     # is handled correctly and doesn't crash
157     netfam.qstats_get({"ifindex": cfg.ifindex, "scope": "queue"}, dump=True)
158 
159 
160 def main() -> None:
161     with NetDrvEnv(__file__) as cfg:
162         ksft_run([check_pause, check_fec, pkt_byte_sum, qstat_by_ifindex,
163                   check_down],
164                  args=(cfg, ))
165     ksft_exit()
166 
167 
168 if __name__ == "__main__":
169     main()

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php