summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorAdrian Moreno <amorenoz@redhat.com>2022-12-19 17:13:46 +0100
committerIlya Maximets <i.maximets@ovn.org>2022-12-21 18:36:02 +0100
commit75a6e8db9c5f9dc2887cae1555d977f0fdf08471 (patch)
tree3060f25206eedc4279bfad8590ad8704ba6874d8 /python
parentd33e548fc7d7ae03cfeba8b70ba84b5b998beca8 (diff)
downloadopenvswitch-75a6e8db9c5f9dc2887cae1555d977f0fdf08471.tar.gz
python: Return list of actions for odp action clone.
Sometimes we don't want to return the result of a nested key-value decoding as a dictionary but as a list of dictionaries. This happens when we parse actions where keys can be repeated. Refactor code that already takes that into account from ofp_act.py to kv.py and use it for datapath action "clone". Signed-off-by: Adrian Moreno <amorenoz@redhat.com> Acked-by: Mike Pattrick <mkp@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'python')
-rw-r--r--python/ovs/flow/kv.py21
-rw-r--r--python/ovs/flow/odp.py6
-rw-r--r--python/ovs/flow/ofp.py14
-rw-r--r--python/ovs/flow/ofp_act.py18
-rw-r--r--python/ovs/tests/test_odp.py38
5 files changed, 59 insertions, 38 deletions
diff --git a/python/ovs/flow/kv.py b/python/ovs/flow/kv.py
index 32463254b..3138db008 100644
--- a/python/ovs/flow/kv.py
+++ b/python/ovs/flow/kv.py
@@ -320,7 +320,26 @@ def decode_nested_kv(decoders, value):
return {kv.key: kv.value for kv in parser.kv()}
-def nested_kv_decoder(decoders=None):
+def decode_nested_kv_list(decoders, value):
+ """A key-value decoder that extracts nested key-value pairs and returns
+ them in a list of dictionary.
+
+ Args:
+ decoders (KVDecoders): The KVDecoders to use.
+ value (str): The value string to decode.
+ """
+ if not value:
+ # Mark as flag
+ return True
+
+ parser = KVParser(value, decoders)
+ parser.parse()
+ return [{kv.key: kv.value} for kv in parser.kv()]
+
+
+def nested_kv_decoder(decoders=None, is_list=False):
"""Helper function that creates a nested kv decoder with given
KVDecoders."""
+ if is_list:
+ return functools.partial(decode_nested_kv_list, decoders)
return functools.partial(decode_nested_kv, decoders)
diff --git a/python/ovs/flow/odp.py b/python/ovs/flow/odp.py
index 3bc3aec8e..db63afc8d 100644
--- a/python/ovs/flow/odp.py
+++ b/python/ovs/flow/odp.py
@@ -337,7 +337,8 @@ class ODPFlow(Flow):
}
_decoders["clone"] = nested_kv_decoder(
- KVDecoders(decoders=_decoders, default_free=decode_free_output)
+ KVDecoders(decoders=_decoders, default_free=decode_free_output),
+ is_list=True,
)
return {
@@ -350,7 +351,8 @@ class ODPFlow(Flow):
KVDecoders(
decoders=_decoders,
default_free=decode_free_output,
- )
+ ),
+ is_list=True,
),
}
)
diff --git a/python/ovs/flow/ofp.py b/python/ovs/flow/ofp.py
index 3d79ed6ad..8f2727361 100644
--- a/python/ovs/flow/ofp.py
+++ b/python/ovs/flow/ofp.py
@@ -31,7 +31,6 @@ from ovs.flow.ofp_act import (
decode_dec_ttl,
decode_chk_pkt_larger,
decode_zone,
- decode_exec,
decode_learn,
)
@@ -336,8 +335,7 @@ class OFPFlow(Flow):
"table": decode_int,
"nat": decode_nat,
"force": decode_flag,
- "exec": functools.partial(
- decode_exec,
+ "exec": nested_kv_decoder(
KVDecoders(
{
**OFPFlow._encap_actions_decoders_args(),
@@ -345,6 +343,7 @@ class OFPFlow(Flow):
**OFPFlow._meta_action_decoders_args(),
}
),
+ is_list=True,
),
"alg": decode_default,
}
@@ -359,6 +358,7 @@ class OFPFlow(Flow):
}
)
),
+ # learn moved to _clone actions.
}
@staticmethod
@@ -400,11 +400,11 @@ class OFPFlow(Flow):
"""
return {
"learn": decode_learn(action_decoders),
- "clone": functools.partial(
- decode_exec, KVDecoders(action_decoders)
+ "clone": nested_kv_decoder(
+ KVDecoders(action_decoders), is_list=True
),
- "write_actions": functools.partial(
- decode_exec, KVDecoders(action_decoders)
+ "write_actions": nested_kv_decoder(
+ KVDecoders(action_decoders), is_list=True
),
}
diff --git a/python/ovs/flow/ofp_act.py b/python/ovs/flow/ofp_act.py
index c481d6fc7..5eaf0b218 100644
--- a/python/ovs/flow/ofp_act.py
+++ b/python/ovs/flow/ofp_act.py
@@ -1,8 +1,5 @@
"""Defines decoders for OpenFlow actions.
"""
-
-import functools
-
from ovs.flow.decoders import (
decode_default,
decode_time,
@@ -258,19 +255,6 @@ def decode_zone(value):
return decode_field(value)
-def decode_exec(action_decoders, value):
- """Decodes the value of the 'exec' keyword (part of the ct action).
-
- Args:
- decode_actions (KVDecoders): The decoders to be used to decode the
- nested exec.
- value (string): The string to be decoded.
- """
- exec_parser = KVParser(value, action_decoders)
- exec_parser.parse()
- return [{kv.key: kv.value} for kv in exec_parser.kv()]
-
-
def decode_learn(action_decoders):
"""Create the decoder to be used to decode the 'learn' action.
@@ -338,4 +322,4 @@ def decode_learn(action_decoders):
default_free=learn_field_decoding_free,
)
- return functools.partial(decode_exec, learn_decoder)
+ return nested_kv_decoder(learn_decoder, is_list=True)
diff --git a/python/ovs/tests/test_odp.py b/python/ovs/tests/test_odp.py
index 715be3869..f8017ca8a 100644
--- a/python/ovs/tests/test_odp.py
+++ b/python/ovs/tests/test_odp.py
@@ -453,21 +453,37 @@ def test_odp_fields(input_string, expected):
],
),
(
- "actions:clone(1)" ",clone(clone(push_vlan(vid=12,pcp=0),2),1)",
+ "actions:clone(1),clone(clone(push_vlan(vid=12,pcp=0),2),1)",
[
- KeyValue("clone", {"output": {"port": 1}}),
+ KeyValue("clone", [{"output": {"port": 1}}]),
KeyValue(
"clone",
- {
- "output": {"port": 1},
- "clone": {
- "push_vlan": {
- "vid": 12,
- "pcp": 0,
- },
- "output": {"port": 2},
+ [
+ {
+ "clone": [
+ {
+ "push_vlan": {
+ "vid": 12,
+ "pcp": 0,
+ },
+ },
+ {"output": {"port": 2}},
+ ]
},
- },
+ {"output": {"port": 1}},
+ ],
+ ),
+ ],
+ ),
+ (
+ "actions:clone(recirc(0x1),recirc(0x2))",
+ [
+ KeyValue(
+ "clone",
+ [
+ {"recirc": 1},
+ {"recirc": 2},
+ ],
),
],
),