xref: /freebsd/tests/atf_python/sys/netlink/utils.py (revision fc2538cb7bdb8e22afc331c3733f2e306624be9e)
1#!/usr/local/bin/python3
2from enum import Enum
3from typing import Any
4from typing import Dict
5from typing import List
6from typing import NamedTuple
7
8from atf_python.sys.netlink.attrs import NlAttr
9
10
11class NlConst:
12    AF_NETLINK = 38
13    NETLINK_ROUTE = 0
14    NETLINK_GENERIC = 16
15    GENL_ID_CTRL = 16
16
17
18def roundup2(val: int, num: int) -> int:
19    if val % num:
20        return (val | (num - 1)) + 1
21    else:
22        return val
23
24
25def align4(val: int) -> int:
26    return roundup2(val, 4)
27
28
29def enum_or_int(val) -> int:
30    if isinstance(val, Enum):
31        return val.value
32    return val
33
34
35class AttrDescr(NamedTuple):
36    val: Enum
37    cls: "NlAttr"
38    child_map: Any = None
39
40
41def prepare_attrs_map(attrs: List[AttrDescr]) -> Dict[str, Dict]:
42    ret = {}
43    for ad in attrs:
44        ret[ad.val.value] = {"ad": ad}
45        if ad.child_map:
46            ret[ad.val.value]["child"] = prepare_attrs_map(ad.child_map)
47    return ret
48
49
50def build_propmap(cls):
51    ret = {}
52    for prop in dir(cls):
53        if not prop.startswith("_"):
54            ret[getattr(cls, prop).value] = prop
55    return ret
56
57
58def get_bitmask_map(propmap, val):
59    v = 1
60    ret = {}
61    while val:
62        if v & val:
63            if v in propmap:
64                ret[v] = propmap[v]
65            else:
66                ret[v] = hex(v)
67            val -= v
68        v *= 2
69    return ret
70
71
72def get_bitmask_str(cls, val):
73    if isinstance(cls, type):
74        pmap = build_propmap(cls)
75    else:
76        pmap = {}
77        for _cls in cls:
78            pmap.update(build_propmap(_cls))
79    bmap = get_bitmask_map(pmap, val)
80    return ",".join([v for k, v in bmap.items()])
81