summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorAdrian Moreno <amorenoz@redhat.com>2022-07-08 20:03:05 +0200
committerIlya Maximets <i.maximets@ovn.org>2022-07-15 20:13:48 +0200
commit1215cf13346aeaf92f7a861b105b9d562b889ecc (patch)
treea37e4e0e41c1ac8f77123a21a26acc03fe46c971 /python
parent61e040fc23a8e2baed7ae94e105510e144f608cc (diff)
downloadopenvswitch-1215cf13346aeaf92f7a861b105b9d562b889ecc.tar.gz
python: Add flow base class.
It simplifies the implementation of different types of flows by creating the concept of Section (e.g: match, action) and automatic accessors for all the provided Sections Acked-by: Eelco Chaudron <echaudro@redhat.com> Signed-off-by: Adrian Moreno <amorenoz@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'python')
-rw-r--r--python/automake.mk1
-rw-r--r--python/ovs/flow/flow.py125
2 files changed, 126 insertions, 0 deletions
diff --git a/python/automake.mk b/python/automake.mk
index 72516d0dd..0a0a479a4 100644
--- a/python/automake.mk
+++ b/python/automake.mk
@@ -28,6 +28,7 @@ ovs_pyfiles = \
python/ovs/fcntl_win.py \
python/ovs/flow/__init__.py \
python/ovs/flow/decoders.py \
+ python/ovs/flow/flow.py \
python/ovs/flow/kv.py \
python/ovs/flow/list.py \
python/ovs/flow/ofp_fields.py \
diff --git a/python/ovs/flow/flow.py b/python/ovs/flow/flow.py
new file mode 100644
index 000000000..2f053e77d
--- /dev/null
+++ b/python/ovs/flow/flow.py
@@ -0,0 +1,125 @@
+""" Defines the Flow class.
+"""
+
+
+class Section(object):
+ """A flow can be seen as composed of different sections, e.g:
+
+ [info] [match] actions=[actions]
+
+ This class represents each of those sections.
+
+ A section is basically a set of Key-Value pairs. Typically, they can be
+ expressed as a dictionary, for instance the "match" part of a flow can be
+ expressed as:
+ {
+ "nw_src": "192.168.1.1",
+ "nw_dst": "192.168.1.2",
+ }
+ However, some of them must be expressed as a list which allows for
+ duplicated keys. For instance, the "actions" section could be:
+ [
+ {
+ "output": 32
+ },
+ {
+ "output": 33
+ }
+ ]
+
+ The is_list flag is used to discriminate this.
+
+ Attributes:
+ name (str): Name of the section.
+ pos (int): Position within the overall flow string.
+ string (str): Section string.
+ data (list[KeyValue]): Parsed data of the section.
+ is_list (bool): Whether the key-values shall be expressed as a list
+ (i.e: it allows repeated keys).
+ """
+
+ def __init__(self, name, pos, string, data, is_list=False):
+ self.name = name
+ self.pos = pos
+ self.string = string
+ self.data = data
+ self.is_list = is_list
+
+ def __str__(self):
+ return "{} (at {}): {}".format(self.name, self.pos, self.string)
+
+ def __repr__(self):
+ return "%s('%s')" % (self.__class__.__name__, self)
+
+ def dict(self):
+ return {self.name: self.format_data()}
+
+ def format_data(self):
+ """Returns the section's key-values formatted in a dictionary or list
+ depending on the value of is_list flag.
+ """
+ if self.is_list:
+ return [{item.key: item.value} for item in self.data]
+ else:
+ return {item.key: item.value for item in self.data}
+
+
+class Flow(object):
+ """The Flow class is a base class for other types of concrete flows
+ (such as OFproto Flows or DPIF Flows).
+
+ A flow is basically comprised of a number of sections.
+ For each section named {section_name}, the flow object will have the
+ following attributes:
+ - {section_name} will return the sections data in a formatted way.
+ - {section_name}_kv will return the sections data as a list of KeyValues.
+
+ Args:
+ sections (list[Section]): List of sections that comprise the flow
+ orig (str): Original flow string.
+ id (Any): Optional; identifier that clients can use to uniquely
+ identify this flow.
+ """
+
+ def __init__(self, sections, orig="", id=None):
+ self._sections = sections
+ self._orig = orig
+ self._id = id
+ for section in sections:
+ setattr(
+ self, section.name, self.section(section.name).format_data()
+ )
+ setattr(
+ self,
+ "{}_kv".format(section.name),
+ self.section(section.name).data,
+ )
+
+ def section(self, name):
+ """Return the section by name."""
+ return next(
+ (sect for sect in self._sections if sect.name == name), None
+ )
+
+ @property
+ def id(self):
+ """Return the Flow ID."""
+ return self._id
+
+ @property
+ def sections(self):
+ """Return the all the sections in a list."""
+ return self._sections
+
+ @property
+ def orig(self):
+ """Return the original flow string."""
+ return self._orig
+
+ def dict(self):
+ """Returns the Flow information in a dictionary."""
+ flow_dict = {"orig": self.orig}
+ for section in self.sections:
+ flow_dict.update(section.dict())
+
+ return flow_dict