On 12/23/21 14:08, Eelco Chaudron wrote:
Just some small comments below, and the request to fix up the comments.
Thanks.
Trying to understand why you have a special ODPFlowFactory class to return an
ODPFLow() object from a string?
Can you not just add a static method to the ODPFlow class, so it would simply
become a matter of calling:
ODPFlow.from_string(string, id=id_data)
Or probably more OOO is to override the __init__ function of ODPFlow() to take
only the string and the id.
Don’t think there is a use case to call ODPFlow() with sections and raw.
I'll implement decoders caching via static class variables in the next version.
+class ODPFlowFactory:
+ """Datapath Flow"""
+
+ def __init__(self):
+ self.info_decoders = self._info_decoders()
+ self.match_decoders = self._match_decoders()
+ self.action_decoders = self._action_decoders()
+
+ def from_string(self, odp_string, id=None):
+ """Parse a odp flow string
+
+ The string is expected to have the follwoing format:
+ [ufid], [match] [flow data] actions:[actions]
+
+ Args:
+ odp_string (str): a datapath flow string
+
+ Returns:
+ an ODPFlow instance
+ """
+
+ sections = []
+
+ # If UFID present, parse it and
+ ufid_pos = odp_string.find("ufid:")
+ if ufid_pos >= 0:
+ ufid_string = odp_string[
+ ufid_pos : (odp_string[ufid_pos:].find(",") + 1)
+ ]
+ ufid_parser = KVParser(KVDecoders({"ufid": decode_default}))
+ ufid_parser.parse(ufid_string)
+ if len(ufid_parser.kv()) != 1:
+ raise ValueError("malformed odp flow: %s" % odp_string)
+ sections.append(
+ Section("ufid", ufid_pos, ufid_string, ufid_parser.kv())
+ )
+
+ action_pos = odp_string.find("actions:")
+ if action_pos < 0:
+ raise ValueError("malformed odp flow: %s" % odp_string)
+
+ # rest of the string is between ufid and actions
+ rest = odp_string[
+ (ufid_pos + len(ufid_string) if ufid_pos >= 0 else 0) : action_pos
+ ]
+
+ action_pos += 8 # len("actions:")
+ actions = odp_string[action_pos:]
+
+ field_parts = rest.lstrip(" ").partition(" ")
+
+ if len(field_parts) != 3:
+ raise ValueError("malformed odp flow: %s" % odp_string)
+
+ match = field_parts[0]
+ info = field_parts[2]
+
+ iparser = KVParser(KVDecoders(self.info_decoders))
+ iparser.parse(info)
Looking at the two lines above, to me, it looks like the object might not have
been defined right (but I’m not an OOO expert).
I would have designed it as, KVParser(string, decoders=None), this way you
would have a single object initialization, so:
parser = KVParser(info, KVDecoders(self.info_decoders))
Also because the parse() method does not allow re-use of the object, meaning
parse another string with the same instance.
Or was there a specific reason to split this in two stages?
It's a remainder of a previous design. Right now I agree it doesn't make sense.
I'll change it in the next version.
+ isection = Section(
+ name="info",
+ pos=odp_string.find(info),
+ string=info,
+ data=iparser.kv(),
+ )
+ sections.append(isection)
+
+ mparser = KVParser(KVDecoders(self.match_decoders))
+ mparser.parse(match)
+ msection = Section(
+ name="match",
+ pos=odp_string.find(match),
+ string=match,
+ data=mparser.kv(),
+ )
+ sections.append(msection)
+
+ aparser = KVParser(
+ KVDecoders(self.action_decoders, default_free=decode_free_output)
+ )
+ aparser.parse(actions)
+ asection = Section(
+ name="actions",
+ pos=action_pos,
+ string=actions,
+ data=aparser.kv(),
+ is_list=True,
+ )
+ sections.append(asection)
+
+ return ODPFlow(sections, odp_string, id)
+
+ @classmethod
Any reason why all of these are @classmethod, and not @staticmethod, as they do
not seem to need a reference to self?
Guess this is also true in some of the previous patches, but I did not notice ;)
Right.
[...]
+
+ @classmethod
+ def _field_decoders(cls):
+ return {
+ "skb_priority": Mask32,
+ "skb_mark": Mask32,
+ "recirc_id": decode_int,
+ "dp_hash": Mask32,
+ "ct_state": decode_default, # TODO: Parse flags
Guess we might want to fix this before the merge?
Well, I've left it initially to confirm whether there is a strong need for this.
Decoding ct_state with a integer allows you to set any ct_state, only you have
to do it using the hexadecimal representation.
Do you think we'll want to use string representation of flags? Same goes for
other flags like tcp_flags.
[...]
+def decode_geneve(mask, value):
+ """
+ Decode geneve options. Used for both tnl_push(header(geneve(options())))
+ action and tunnel(geneve()) match.
+
+ It has the following format:
+
+ {class=0xffff,type=0x80,len=4,0xa}
+
+ Args:
+ mask (bool): Whether masking is supported
+ value (str): The value to decode
+ """
+ if mask:
Create some consistency around the ending of doctext and the first line of code
(in all patches).
Sometimes you have an empty line, like in decode_tnl_gre below, and sometimes
not like here.
For some reason I was expecting my formatter to do that for me, but I guess it's
not... Sure, I'll double check.
--
Adrián Moreno
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev