mirror of
https://github.com/openvswitch/ovs
synced 2025-09-03 07:45:30 +00:00
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> Signed-off-by: Simon Horman <horms@ovn.org>
This commit is contained in:
committed by
Simon Horman
parent
120f3dc411
commit
063d784d79
@@ -320,7 +320,26 @@ def decode_nested_kv(decoders, value):
|
|||||||
return {kv.key: kv.value for kv in parser.kv()}
|
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
|
"""Helper function that creates a nested kv decoder with given
|
||||||
KVDecoders."""
|
KVDecoders."""
|
||||||
|
if is_list:
|
||||||
|
return functools.partial(decode_nested_kv_list, decoders)
|
||||||
return functools.partial(decode_nested_kv, decoders)
|
return functools.partial(decode_nested_kv, decoders)
|
||||||
|
@@ -337,7 +337,8 @@ class ODPFlow(Flow):
|
|||||||
}
|
}
|
||||||
|
|
||||||
_decoders["clone"] = nested_kv_decoder(
|
_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 {
|
return {
|
||||||
@@ -350,7 +351,8 @@ class ODPFlow(Flow):
|
|||||||
KVDecoders(
|
KVDecoders(
|
||||||
decoders=_decoders,
|
decoders=_decoders,
|
||||||
default_free=decode_free_output,
|
default_free=decode_free_output,
|
||||||
)
|
),
|
||||||
|
is_list=True,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@@ -31,7 +31,6 @@ from ovs.flow.ofp_act import (
|
|||||||
decode_dec_ttl,
|
decode_dec_ttl,
|
||||||
decode_chk_pkt_larger,
|
decode_chk_pkt_larger,
|
||||||
decode_zone,
|
decode_zone,
|
||||||
decode_exec,
|
|
||||||
decode_learn,
|
decode_learn,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -336,8 +335,7 @@ class OFPFlow(Flow):
|
|||||||
"table": decode_int,
|
"table": decode_int,
|
||||||
"nat": decode_nat,
|
"nat": decode_nat,
|
||||||
"force": decode_flag,
|
"force": decode_flag,
|
||||||
"exec": functools.partial(
|
"exec": nested_kv_decoder(
|
||||||
decode_exec,
|
|
||||||
KVDecoders(
|
KVDecoders(
|
||||||
{
|
{
|
||||||
**OFPFlow._encap_actions_decoders_args(),
|
**OFPFlow._encap_actions_decoders_args(),
|
||||||
@@ -345,6 +343,7 @@ class OFPFlow(Flow):
|
|||||||
**OFPFlow._meta_action_decoders_args(),
|
**OFPFlow._meta_action_decoders_args(),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
is_list=True,
|
||||||
),
|
),
|
||||||
"alg": decode_default,
|
"alg": decode_default,
|
||||||
}
|
}
|
||||||
@@ -359,6 +358,7 @@ class OFPFlow(Flow):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
# learn moved to _clone actions.
|
||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -400,11 +400,11 @@ class OFPFlow(Flow):
|
|||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
"learn": decode_learn(action_decoders),
|
"learn": decode_learn(action_decoders),
|
||||||
"clone": functools.partial(
|
"clone": nested_kv_decoder(
|
||||||
decode_exec, KVDecoders(action_decoders)
|
KVDecoders(action_decoders), is_list=True
|
||||||
),
|
),
|
||||||
"write_actions": functools.partial(
|
"write_actions": nested_kv_decoder(
|
||||||
decode_exec, KVDecoders(action_decoders)
|
KVDecoders(action_decoders), is_list=True
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,8 +1,5 @@
|
|||||||
"""Defines decoders for OpenFlow actions.
|
"""Defines decoders for OpenFlow actions.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import functools
|
|
||||||
|
|
||||||
from ovs.flow.decoders import (
|
from ovs.flow.decoders import (
|
||||||
decode_default,
|
decode_default,
|
||||||
decode_time,
|
decode_time,
|
||||||
@@ -258,19 +255,6 @@ def decode_zone(value):
|
|||||||
return decode_field(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):
|
def decode_learn(action_decoders):
|
||||||
"""Create the decoder to be used to decode the 'learn' action.
|
"""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,
|
default_free=learn_field_decoding_free,
|
||||||
)
|
)
|
||||||
|
|
||||||
return functools.partial(decode_exec, learn_decoder)
|
return nested_kv_decoder(learn_decoder, is_list=True)
|
||||||
|
@@ -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(
|
KeyValue(
|
||||||
"clone",
|
"clone",
|
||||||
{
|
[
|
||||||
"output": {"port": 1},
|
{
|
||||||
"clone": {
|
"clone": [
|
||||||
"push_vlan": {
|
{
|
||||||
"vid": 12,
|
"push_vlan": {
|
||||||
"pcp": 0,
|
"vid": 12,
|
||||||
},
|
"pcp": 0,
|
||||||
"output": {"port": 2},
|
},
|
||||||
|
},
|
||||||
|
{"output": {"port": 2}},
|
||||||
|
]
|
||||||
},
|
},
|
||||||
},
|
{"output": {"port": 1}},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"actions:clone(recirc(0x1),recirc(0x2))",
|
||||||
|
[
|
||||||
|
KeyValue(
|
||||||
|
"clone",
|
||||||
|
[
|
||||||
|
{"recirc": 1},
|
||||||
|
{"recirc": 2},
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
Reference in New Issue
Block a user