On 5/21/24 20:56, amore...@redhat.com wrote:
> On Tue, May 21, 2024 at 08:03:49PM GMT, Ilya Maximets wrote:
>> On 5/21/24 18:13, amore...@redhat.com wrote:
>>> On Tue, May 21, 2024 at 03:49:03PM GMT, amore...@redhat.com wrote:
>>>> 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
>>
>> <snip>
>>
>>>>>
>>>>> 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.
>>>>
>>>
>>> If you still have the original flowdump handy, could you please try this
>>> patch?
>>>
>>> ---
>>> diff --git a/python/ovs/flow/odp.py b/python/ovs/flow/odp.py
>>> index 7d9b165d4..a8f8c067a 100644
>>> --- a/python/ovs/flow/odp.py
>>> +++ b/python/ovs/flow/odp.py
>>> @@ -365,29 +365,30 @@ class ODPFlow(Flow):
>>
>> <snip>
>>
>> Yeah, that worked.  I'm not sure if the result is more readbale than it was 
>> in a plain
>> text, but it worked. :)
>>
> 
> Sorry it didn't help.

It's about 500 flows and they are not pretty as seen above.  So, it's hard to
make them look good.

> Do you have any suggestion (apart from the one
> below)?
> 
>> The 'tree' view is a bit confusing because it only takes into account 
>> recirculation id
>> and doesn't care about other fields being completely different.  So, it 
>> draws a tree
>> with a lot of impossible branches...  Do you think there is a way to fix 
>> that?
>>
> 
> Without implementing a matching engine, getting 100% accuracy is tough.
> I added filtering and highlighting to assist but at the end it's true you have
> to mentally do the matching.

Yeah.  In general case for a 100% accuracy we would have to implement parts
of the datapath, e.g. execute the actions.

However, some things are immutable and do not support masked matches.  Some
of these are also always present.  For example, in_port() is always there
and it cannot be changed by actions, so we can avoid trees like this:

│   ├── recirc_id(0x1c43aff),in_port(18)...
│   │   actions:...recirc(0x204b096)
│   │   └── recirc_id(0x204b096),in_port(18),
│   │       actions:set(ipv4(ttl=62)),hash(l4(0)),recirc(0x204b097)
│   │       ├── recirc_id(0x204b097),dp_hash(0x8/0xf),in_port(18)...
│   │       │   actions:...recirc(0x1c2f203)
│   │       │   ├── recirc_id(0x1c2f203),in_port(14)...
│   │       │   ├── recirc_id(0x1c2f203),in_port(19)...
│   │       │   ├── recirc_id(0x1c2f203),in_port(23)...
│   │       │   ├── recirc_id(0x1c2f203),in_port(18)...
│   │       │   ├── recirc_id(0x1c2f203),in_port(19)...
│   │       │   ├── recirc_id(0x1c2f203),in_port(14)...
│   │       │   ├── recirc_id(0x1c2f203),in_port(18)...
│   │       │   ├── recirc_id(0x1c2f203),in_port(14)...
│   │       │   └── recirc_id(0x1c2f203),in_port(18)...
│   │       ├── recirc_id(0x204b097),dp_hash(0x4/0xf),in_port(18)
│   │       │   ├── recirc_id(0x1c2f203),in_port(14)...
│   │       │   ├── recirc_id(0x1c2f203),in_port(19)...
│   │       │   ├── recirc_id(0x1c2f203),in_port(23)...
│   │       │   ├── recirc_id(0x1c2f203),in_port(18)...
│   │       │   ├── recirc_id(0x1c2f203),in_port(19)...
│   │       │   ├── recirc_id(0x1c2f203),in_port(14)...
│   │       │   ├── recirc_id(0x1c2f203),in_port(18)...
│   │       │   ├── recirc_id(0x1c2f203),in_port(14)...
│   │       │   └── recirc_id(0x1c2f203),in_port(18)...


Above is heavily abridged, but yo can see that only 4 out of 18 flows
at the last level match on the same input port.  This may be optimized.

In general it just blows out the total output from 500 flows into 18000
lines of a tree output in my case.

There are trees where on some level many flows have exact same actions
with slightly different matches.  I wonder if these can be groupped to
only list the actions once.  This is beneficial especially if those
actions have reirculation in them, so it will also not be repeated.

> 
> I also thought of having some interactivity (I added some very basic one
> in the html format) so you could manually remove the branches you're not
> interested in. But that's the only thin

Yeah, I'd really like interactive filtering... maybe even not interactive for
the starters.  Maybe just a string match or regex instead of packet-aware
filtering.  The way it should work is to go through the tree and print out
only paths that contain a match, i.e. all parents of the matching flow
and children.  Basically, cut out the siblings.  For exmaple, something like
--filter="in_port(18)" should only print trees that match on port 18.
This is an easy one, since input port is always in the flow.

A big problem I'm also facing is that grep doesn't work due to coloring.
And if I remove the colors for grep I will not be able to add them back,
so grep filtering kind of has to be supported natively in ovs-flowviz.

All in all, what we all want is just have retis print out datapath flows as
packets match them. :D  So, we can pcap-filter a TCP stream and see all
the datapath flows it matched and actions executed.

Best regards, Ilya Maximets.

> 
> BTW. Thanks for trying it out and giving feedback.
> 
> --
> Adrián
> 

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to