svinota / pyroute2

Python Netlink and PF_ROUTE library — network configuration and monitoring
https://pyroute2.org/
Other
930 stars 244 forks source link

`IPRoute2.tc` 'flow' filter buggy when in map mode #1195

Open mossblaser opened 2 months ago

mossblaser commented 2 months ago

When adding the "flow" traffic control filter in 'map' mode, the key parameter is processed incorrectly resulting in a NetlinkError: (22, 'Invalid argument') exception in many cases.

For example, the following invocation:

ipr.tc(
    "add-filter",
    index=ifb_index,
    parent="1000:",
    handle=1,
    kind="flow",
    mode="map",
    key="proto-src",
    baseclass=0x1000_0001,
)

Internally, this function uses get_tca_keys to convert the 'key' parameter into a bit-mask. For convenience, the implementation is reproduced below:

def get_tca_keys(kwarg, name):
    if name not in kwarg:
        raise ValueError('Missing attribute: {0}'.format(name))

    res = 0
    keys = kwarg[name]
    if name == 'hash':
        keys = keys.split(',')

    for key, value in tc_flow_keys.items():
        if key in keys:
            res |= value

    return res

The problem is that in map mode (rather than hash mode), this function leaves keys as a plain string. When used with a value like "proto-src" this leads to the bits for both "proto-src" and "src" being combined rather than just "proto-src" since in will do a substring test when both its arguments are strings.

A potential fix would be:

     if name == 'hash':
         keys = keys.split(',')
+    else:
+        keys = [keys]