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