Skip to content

Commit

Permalink
selftests: openvswitch: support key masks
Browse files Browse the repository at this point in the history
The default value for the mask actually depends on the value (e.g: if
the value is non-null, the default is full-mask), so change the convert
functions to accept the full, possibly masked string and let them figure
out how to parse the different values.

Also, implement size-aware int parsing.

With this patch we can now express flows such as the following:
"eth(src=0a:ca:fe:ca:fe:0a/ff:ff:00:00:ff:00)"
"eth(src=0a:ca:fe:ca:fe:0a)" -> mask = ff:ff:ff:ff:ff:ff
"ipv4(src=192.168.1.1)" -> mask = 255.255.255.255
"ipv4(src=192.168.1.1/24)"
"ipv4(src=192.168.1.1/255.255.255.0)"
"tcp(src=8080)" -> mask = 0xffff
"tcp(src=8080/0xf0f0)"

Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
Acked-by: Aaron Conole <aconole@redhat.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Adrian Moreno authored and Paolo Abeni committed Aug 3, 2023
1 parent 918423f commit 9f1179f
Showing 1 changed file with 64 additions and 32 deletions.
96 changes: 64 additions & 32 deletions tools/testing/selftests/net/openvswitch/ovs-dpctl.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,25 +160,45 @@ def parse_ct_state(statestr):
return parse_flags(statestr, ct_flags)


def convert_mac(mac_str, mask=False):
if mac_str is None or mac_str == "":
mac_str = "00:00:00:00:00:00"
if mask is True and mac_str != "00:00:00:00:00:00":
mac_str = "FF:FF:FF:FF:FF:FF"
mac_split = mac_str.split(":")
ret = bytearray([int(i, 16) for i in mac_split])
return bytes(ret)
def convert_mac(data):
def to_bytes(mac):
mac_split = mac.split(":")
ret = bytearray([int(i, 16) for i in mac_split])
return bytes(ret)

mac_str, _, mask_str = data.partition('/')

def convert_ipv4(ip, mask=False):
if ip is None:
ip = 0
if mask is True:
if ip != 0:
ip = int(ipaddress.IPv4Address(ip)) & 0xFFFFFFFF
if not mac_str:
mac_str = mask_str = "00:00:00:00:00:00"
elif not mask_str:
mask_str = "FF:FF:FF:FF:FF:FF"

return int(ipaddress.IPv4Address(ip))
return to_bytes(mac_str), to_bytes(mask_str)

def convert_ipv4(data):
ip, _, mask = data.partition('/')

if not ip:
ip = mask = 0
elif not mask:
mask = 0xFFFFFFFF
elif mask.isdigit():
mask = (0xFFFFFFFF << (32 - int(mask))) & 0xFFFFFFFF

return int(ipaddress.IPv4Address(ip)), int(ipaddress.IPv4Address(mask))

def convert_int(size):
def convert_int_sized(data):
value, _, mask = data.partition('/')

if not value:
return 0, 0
elif not mask:
return int(value, 0), pow(2, size) - 1
else:
return int(value, 0), int(mask, 0)

return convert_int_sized

def parse_starts_block(block_str, scanstr, returnskipped, scanregex=False):
if scanregex:
Expand Down Expand Up @@ -525,8 +545,10 @@ class ovs_key_proto(nla):
)

fields_map = (
("src", "src", "%d", lambda x: int(x) if x is not None else 0),
("dst", "dst", "%d", lambda x: int(x) if x is not None else 0),
("src", "src", "%d", lambda x: int(x) if x else 0,
convert_int(16)),
("dst", "dst", "%d", lambda x: int(x) if x else 0,
convert_int(16)),
)

def __init__(
Expand Down Expand Up @@ -575,17 +597,13 @@ def parse(self, flowstr, typeInst):
data = flowstr[:splitchar]
flowstr = flowstr[splitchar:]
else:
data = None
data = ""

if len(f) > 4:
func = f[4]
else:
func = f[3]
k[f[0]] = func(data)
if len(f) > 4:
m[f[0]] = func(data, True)
k[f[0]], m[f[0]] = f[4](data)
else:
m[f[0]] = func(data)
k[f[0]] = f[3](data)
m[f[0]] = f[3](data)

flowstr = flowstr[strspn(flowstr, ", ") :]
if len(flowstr) == 0:
Expand Down Expand Up @@ -689,10 +707,14 @@ class ovs_key_ipv4(ovs_key_proto):
int,
convert_ipv4,
),
("proto", "proto", "%d", lambda x: int(x) if x is not None else 0),
("tos", "tos", "%d", lambda x: int(x) if x is not None else 0),
("ttl", "ttl", "%d", lambda x: int(x) if x is not None else 0),
("frag", "frag", "%d", lambda x: int(x) if x is not None else 0),
("proto", "proto", "%d", lambda x: int(x) if x else 0,
convert_int(8)),
("tos", "tos", "%d", lambda x: int(x) if x else 0,
convert_int(8)),
("ttl", "ttl", "%d", lambda x: int(x) if x else 0,
convert_int(8)),
("frag", "frag", "%d", lambda x: int(x) if x else 0,
convert_int(8)),
)

def __init__(
Expand Down Expand Up @@ -828,8 +850,8 @@ class ovs_key_icmp(ovs_key_proto):
)

fields_map = (
("type", "type", "%d", int),
("code", "code", "%d", int),
("type", "type", "%d", lambda x: int(x) if x else 0),
("code", "code", "%d", lambda x: int(x) if x else 0),
)

def __init__(
Expand Down Expand Up @@ -894,7 +916,7 @@ class ovs_key_arp(ovs_key_proto):
int,
convert_ipv4,
),
("op", "op", "%d", lambda x: int(x) if x is not None else 0),
("op", "op", "%d", lambda x: int(x) if x else 0),
(
"sha",
"sha",
Expand Down Expand Up @@ -1098,6 +1120,16 @@ def parse(self, flowstr, mask=None):
"tcp",
ovskey.ovs_key_tcp,
),
(
"OVS_KEY_ATTR_UDP",
"udp",
ovskey.ovs_key_udp,
),
(
"OVS_KEY_ATTR_ICMP",
"icmp",
ovskey.ovs_key_icmp,
),
(
"OVS_KEY_ATTR_TCP_FLAGS",
"tcp_flags",
Expand Down

0 comments on commit 9f1179f

Please sign in to comment.