On Tue, May 21, 2024 at 01:51:33PM GMT, Ilya Maximets wrote: > On 5/7/24 16:30, Adrian Moreno wrote: > > The goal of this utility is to read both datapath and Openflow flows > > (using the flow library already available) and print them in different > > formats and styles to make it easier to understand them and troubleshoot > > issues. > > > > The formats are quite opinionated and so are the colors chosen so I'm > > eager to hear what is the impression caused to the community. > > > > Here is a summary of the formats and features supported: > > > > - Openflow > > - Console: Prints flows back to the console allowing filtering and > > extensive formatting. > > - Cookie: Arranges flows based on cookie (instead of table) to ease > > visualization of OVN-generated flows. > > - HTML: Prints an HTML file that shows the flows arranged by tables. > > resubmit actions have a hyperlinke to the target table to ease > > navegation. > > - Logic: Many times OVN generates many "logically-equivalent" flows. > > These are flows that have the same structure: match on the same > > values and have the same actions. The only thing that changes is > > the actual value they match against and maybe the arguments of the > > actions. This format collapses these flows so you can visualize the > > logical pipeline easier. > > - JSON: JSON format. > > > > More OpenFlow features: > > - OVN metadata: Both the "cookie" and the "logic" format allow to > > connect to a running OVN NB/SB databases and enrich the flows with > > OVN context based on the flow's cookie. > > > > - Datapath: > > - Console: Prints flows back to the console allowing filtering and > > extensive formatting. > > - Tree: Datapath flows use recirculation to further execute > > additional actions. This format builds a tree of flows following > > the recirculation identifiers and prints it in the console. > > - HTML: Prints the datapath flow tree in HTML. It includes some > > minimal JS to support expanding and collapsing of entire branches. > > - Graph: Following the "tree" format, this one prints the tree in > > graphviz format. > > - JSON: JSON format. > > > > Additional datapath features: > > - Many datapath formats are based on the tree flow hierarchy. An > > interesting feature of this structure is that filtering is done at > > the branch level. This means that when a flow satisfies the filter, > > the entire sub-tree leading to that flow is shown. > > > > Additional common features: > > - Styling: Styles for both console and HTML formats can be defined > > using a configuration file. > > - Heat maps: Some formats support heat-maps. A color pallete ranging > > from blue (cold) to red (hot) is used to print the number of > > packets and bytes of the flows. That way, the flows that are > > handling more traffic are much easier to spot > > > > -- > > V3 -> V4: > > - Add manpage to rpm package > > - Fix Eelco's comments > > V2 -> V3: > > - Fix grammar thanks to Eelco's review > > V1 -> V2: > > - Fix typos and nits on documentation > > - Split documentation in two: ovs-flowviz.8 man page and a topic > > article with more detailed examples. > > RFC -> V1: > > - Addressed Eelco's comments > > - Added a documentation page > > - Added support for dark style HTML pages > > - Patch 3. Small fix in the way a style is looked up. Use the key in > > the KV instead of the metadata string. This helps with "free" values > > such as "output". > > > > Adrian Moreno (12): > > python: ovs: Add flowviz scheleton. > > python: ovs: flowviz: Add file processing infra. > > python: ovs: flowviz: Add console formatting. > > python: ovs: flowviz: Add default config file. > > python: ovs: flowviz: Add html formatting. > > python: ovs: flowviz: Add datapath tree format. > > python: ovs: flowviz: Add OpenFlow logical view. > > python: ovs: flowviz: Add Openflow cookie format. > > python: ovs: flowviz: Add datapath html format. > > python: ovs: flowviz: Add datapath graph format. > > python: ovs: flowviz: Support html dark style. > > documentation: Document ovs-flowviz. > > > > Documentation/automake.mk | 4 +- > > Documentation/conf.py | 2 + > > Documentation/ref/index.rst | 1 + > > Documentation/ref/ovs-flowviz.8.rst | 531 ++++++++++++++++++++ > > Documentation/topics/flow-visualization.rst | 271 ++++++++++ > > Documentation/topics/index.rst | 1 + > > python/automake.mk | 32 +- > > python/ovs/flowviz/__init__.py | 2 + > > python/ovs/flowviz/console.py | 196 ++++++++ > > python/ovs/flowviz/format.py | 371 ++++++++++++++ > > python/ovs/flowviz/html_format.py | 138 +++++ > > python/ovs/flowviz/main.py | 196 ++++++++ > > python/ovs/flowviz/odp/__init__.py | 0 > > python/ovs/flowviz/odp/cli.py | 116 +++++ > > python/ovs/flowviz/odp/graph.py | 418 +++++++++++++++ > > python/ovs/flowviz/odp/html.py | 279 ++++++++++ > > python/ovs/flowviz/odp/tree.py | 303 +++++++++++ > > python/ovs/flowviz/ofp/__init__.py | 0 > > python/ovs/flowviz/ofp/cli.py | 246 +++++++++ > > python/ovs/flowviz/ofp/html.py | 98 ++++ > > python/ovs/flowviz/ofp/logic.py | 364 ++++++++++++++ > > python/ovs/flowviz/ovs-flowviz | 20 + > > python/ovs/flowviz/ovs-flowviz.conf | 128 +++++ > > python/ovs/flowviz/process.py | 263 ++++++++++ > > python/setup.py | 14 +- > > rhel/openvswitch-fedora.spec.in | 1 + > > rhel/openvswitch.spec.in | 1 + > > 27 files changed, 3986 insertions(+), 10 deletions(-) > > create mode 100644 Documentation/ref/ovs-flowviz.8.rst > > create mode 100644 Documentation/topics/flow-visualization.rst > > create mode 100644 python/ovs/flowviz/__init__.py > > create mode 100644 python/ovs/flowviz/console.py > > create mode 100644 python/ovs/flowviz/format.py > > create mode 100644 python/ovs/flowviz/html_format.py > > create mode 100644 python/ovs/flowviz/main.py > > create mode 100644 python/ovs/flowviz/odp/__init__.py > > create mode 100644 python/ovs/flowviz/odp/cli.py > > create mode 100644 python/ovs/flowviz/odp/graph.py > > create mode 100644 python/ovs/flowviz/odp/html.py > > create mode 100644 python/ovs/flowviz/odp/tree.py > > create mode 100644 python/ovs/flowviz/ofp/__init__.py > > create mode 100644 python/ovs/flowviz/ofp/cli.py > > create mode 100644 python/ovs/flowviz/ofp/html.py > > create mode 100644 python/ovs/flowviz/ofp/logic.py > > create mode 100755 python/ovs/flowviz/ovs-flowviz > > create mode 100644 python/ovs/flowviz/ovs-flowviz.conf > > create mode 100644 python/ovs/flowviz/process.py > > > > Hi, Adrian. Thanks for v4! > > Not a full review, but I was trying to use this version of flowviz today > on a real flow dump from an ovn-kubernetes cluster and it crashes unable > to parse check_pkt_len datapath actions: > > # ovs-flowviz -i snippet1.txt datapath tree > > Traceback (most recent call last): > File "/python/ovs/flow/kv.py", line 294, in parse > key, val = self._decoders.decode(keyword, value_str) > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/python/ovs/flow/kv.py", line 150, in decode > raise ParseError( > ovs.flow.kv.ParseError: Cannot parse key check_pkt_len: No decoder found > > The above exception was the direct cause of the following exception: > > Traceback (most recent call last): > File "/python/ovs/flow/kv.py", line 294, in parse > key, val = self._decoders.decode(keyword, value_str) > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/python/ovs/flow/kv.py", line 137, in decode > result = decoder(value_str) > ^^^^^^^^^^^^^^^^^^ > File "/python/ovs/flow/kv.py", line 347, in decode_nested_kv_list > parser.parse() > File "/python/ovs/flow/kv.py", line 296, in parse > raise ParseError( > ovs.flow.kv.ParseError: Error parsing key-value (check_pkt_len, > size=8514,gt(sample(sample=100.0%,actions(meter(4),userspace(pid=4294967295,controller(reason=1,dont_send=0,c > ontinuation=0,recirc_id=33861757,rule_cookie=0x9ac6aa33,controller_id=0,max_len=65535))))),le(ct(zone=12,nat),recirc(0x204b07e))) > > The above exception was the direct cause of the following exception: > > The above exception was the direct cause of the following exception: > > Traceback (most recent call last): > File "/python/ovs/flow/kv.py", line 294, in parse > key, val = self._decoders.decode(keyword, value_str) > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/python/ovs/flow/kv.py", line 137, in decode > result = decoder(value_str) > ^^^^^^^^^^^^^^^^^^ > File "/python/ovs/flow/kv.py", line 330, in decode_nested_kv > parser.parse() > File "/python/ovs/flow/kv.py", line 296, in parse > raise ParseError( > ovs.flow.kv.ParseError: Error parsing key-value (le, > set(eth(src=0a:0b:0c:0d:08:08,dst=aa:bb:cc:dd:ee:ff)),set(ipv4(ttl=62)),check_pkt_len(size=8514,gt(sample(sample=100.0%, > actions(meter(4),userspace(pid=4294967295,controller(reason=1,dont_send=0,continuation=0,recirc_id=33861757,rule_cookie=0x9ac6aa33,controller_id=0,max_len=65535))))),le(ct(z > one=12,nat),recirc(0x204b07e)))) > > The above exception was the direct cause of the following exception: > > Traceback (most recent call last): > File "/venv/bin/ovs-flowviz", line 20, in <module> > main.main() > File "/python/ovs/flowviz/main.py", line 196, in main > maincli() > File "/venv/lib64/python3.12/site-packages/click/core.py", line 1157, in > __call__ > return self.main(*args, **kwargs) > ^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/venv/lib64/python3.12/site-packages/click/core.py", line 1078, in > main > rv = self.invoke(ctx) > ^^^^^^^^^^^^^^^^ > File "/venv/lib64/python3.12/site-packages/click/core.py", line 1688, in > invoke > return _process_result(sub_ctx.command.invoke(sub_ctx)) > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/venv/lib64/python3.12/site-packages/click/core.py", line 1688, in > invoke > return _process_result(sub_ctx.command.invoke(sub_ctx)) > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/venv/lib64/python3.12/site-packages/click/core.py", line 1434, in > invoke > return ctx.invoke(self.callback, **ctx.params) > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/venv/lib64/python3.12/site-packages/click/core.py", line 783, in > invoke > return __callback(*args, **kwargs) > ^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/venv/lib64/python3.12/site-packages/click/decorators.py", line 45, > in new_func > return f(get_current_context().obj, *args, **kwargs) > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/python/ovs/flowviz/odp/cli.py", line 85, in tree > processor.process() > File "/python/ovs/flowviz/odp/tree.py", line 233, in process > super().process(False) > File "/python/ovs/flowviz/process.py", line 113, in process > flow = self.create_flow(line, idx) > ^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/python/ovs/flowviz/process.py", line 158, in create_flow > return ODPFlow(line, idx) > ^^^^^^^^^^^^^^^^^^ > File "/python/ovs/flow/odp.py", line 153, in __init__ > aparser.parse() > File "/python/ovs/flow/kv.py", line 296, in parse > raise ParseError( > ovs.flow.kv.ParseError: Error parsing key-value (check_pkt_len, > size=8514,gt(sample(sample=100.0%,actions(meter(4),userspace(pid=4294967295,controller(reason=1,dont_send=0,continuation=0,recirc_id=29551991,rule_cookie=0x769b5340,controller_id=0,max_len=65535))))),le(set(eth(src=0a:0b:0c:0d:08:08,dst=aa:bb:cc:dd:ee:ff)),set(ipv4(ttl=62)),check_pkt_len(size=8514,gt(sample(sample=100.0%,actions(meter(4),userspace(pid=4294967295,controller(reason=1,dont_send=0,continuation=0,recirc_id=33861757,rule_cookie=0x9ac6aa33,controller_id=0,max_len=65535))))),le(ct(zone=12,nat),recirc(0x204b07e))))) > > > Not the exact same line, but a similar crash happens while parsing: > > recirc_id(0x204ae73),in_port(20),ct_state(+new-est-rel-rpl-inv+trk),ct_mark(0/0xffff000f),eth(src=1a:1b:1c:1d:18:18,dst=2a:2b:2c:2d:2e:2f),eth_type(0x0800),ipv4(src=192.168.10.1/255.255.255.254,dst=10.64.0.0/255.192.0.0,proto=6,ttl=64,frag=no), > packets:7, bytes:518, used:9.077s, flags:S, > actions:ct(commit,zone=269,mark=0/0x1,nat(src)),set(eth(src=3a:3b:3c:3d:3e:3f,dst=4a:4b:4c:4d:4e:4f)),set(ipv4(ttl=63)),check_pkt_len(size=8514,gt(sample(sample=100.0%,actions(meter(4),userspace(pid=4294967295,controller(reason=1,dont_send=0,continuation=0,recirc_id=29551991,rule_cookie=0x769b5340,controller_id=0,max_len=65535))))),le(set(eth(src=0a:0b:0c:0d:08:08,dst=aa:bb:cc:dd:ee:ff)),set(ipv4(ttl=62)),check_pkt_len(size=8514,gt(sample(sample=100.0%,actions(meter(4),userspace(pid=4294967295,controller(reason=1,dont_send=0,continuation=0,recirc_id=33861236,rule_cookie=0x9ac6aa33,controller_id=0,max_len=65535))))),le(ct(zone=12,nat),recirc(0x204ae75))))) > > My guess is that it has some trouble with nested check_pkt_len. >
Thanks. I'll take a look. > Best regards, Ilya Maximets. > _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
