brintos

brintos / linux-shallow public Read only

0
0
Text · 5.4 KiB · 63e3c04 Raw
170 lines · python
1#!/usr/bin/env python32# SPDX-License-Identifier: GPL-2.03 4import errno5from lib.py import ksft_run, ksft_exit, ksft_pr6from lib.py import ksft_ge, ksft_eq, ksft_in, ksft_true, ksft_raises, KsftSkipEx, KsftXfailEx7from lib.py import ksft_disruptive8from lib.py import EthtoolFamily, NetdevFamily, RtnlFamily, NlError9from lib.py import NetDrvEnv10from lib.py import ip, defer11 12ethnl = EthtoolFamily()13netfam = NetdevFamily()14rtnl = RtnlFamily()15 16 17def check_pause(cfg) -> None:18    global ethnl19 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        raise26 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 32def check_fec(cfg) -> None:33    global ethnl34 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        raise41 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 47def pkt_byte_sum(cfg) -> None:48    global netfam, rtnl49 50    def get_qstat(test):51        global netfam52        stats = netfam.qstats_get({}, dump=True)53        if stats:54            for qs in stats:55                if qs["ifindex"]== test.ifindex:56                    return qs57 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 dumps67    # 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 073 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 83def qstat_by_ifindex(cfg) -> None:84    global netfam85    global rtnl86 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] = entry101 102    if len(ifindexes) == 0:103        raise KsftSkipEx("No ifindex supports qstats")104 105    # Now make sure the stats match/make sense106    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 dumps114    # 0 is invalid115    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 stats121    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 0127    devs = rtnl.getlink({}, dump=True)128    all_ifindexes = set([dev["ifi-index"] for dev in devs])129    lowest = 2130    while lowest in all_ifindexes:131        lowest += 1132 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_disruptive140def 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        raise147 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" state156    # is handled correctly and doesn't crash157    netfam.qstats_get({"ifindex": cfg.ifindex, "scope": "queue"}, dump=True)158 159 160def 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 168if __name__ == "__main__":169    main()170