Re: [ovs-dev] [PATCH v7 2/2] ofproto-dpif-mirror: Add support for pre-selection filter.

2024-03-01 Thread Ilya Maximets
On 2/26/24 22:16, Mike Pattrick wrote:
> Currently a bridge mirror will collect all packets and tools like
> ovs-tcpdump can apply additional filters after they have already been
> duplicated by vswitchd. This can result in inefficient collection.
> 
> This patch adds support to apply pre-selection to bridge mirrors, which
> can limit which packets are mirrored based on flow metadata. This
> significantly improves overall vswitchd performance during mirroring if
> only a subset of traffic is required.
> 
> Signed-off-by: Mike Pattrick 
> ---
> v7:
>  - Make sure filter mask is added to masks of non-matching flows.
>  - Added additional tests.

Hi, Mike.  Thanks for v7!

I see Elco made some comments, so I'll just throw in a few from me.
See inline.

Best regards, Ilya Maixmets.

> ---
>  Documentation/ref/ovs-tcpdump.8.rst |   8 +-
>  NEWS|   3 +
>  lib/flow.c  |  21 +++-
>  lib/flow.h  |  12 +++
>  ofproto/ofproto-dpif-mirror.c   |  78 ++-
>  ofproto/ofproto-dpif-mirror.h   |  12 ++-
>  ofproto/ofproto-dpif-xlate.c|  26 -
>  ofproto/ofproto-dpif.c  |   9 +-
>  ofproto/ofproto-dpif.h  |   6 ++
>  ofproto/ofproto.c   |   4 +-

All the changes for ofproto.c are not related to this patch.

>  ofproto/ofproto.h   |   3 +
>  tests/ofproto-dpif.at   | 142 
>  utilities/ovs-tcpdump.in|  13 ++-
>  vswitchd/bridge.c   |  13 ++-
>  vswitchd/vswitch.ovsschema  |   5 +-
>  vswitchd/vswitch.xml|  13 +++
>  16 files changed, 343 insertions(+), 25 deletions(-)
> 
> diff --git a/Documentation/ref/ovs-tcpdump.8.rst 
> b/Documentation/ref/ovs-tcpdump.8.rst
> index b9f8cdf6f..e21e61211 100644
> --- a/Documentation/ref/ovs-tcpdump.8.rst
> +++ b/Documentation/ref/ovs-tcpdump.8.rst
> @@ -61,8 +61,14 @@ Options
>  
>If specified, mirror all ports (optional).
>  
> +* ``--filter ``
> +
> +  If specified, only mirror flows that match the provided OpenFlow filter.
> +  The available fields are documented in ``ovs-fields(7)``.
> +
>  See Also
>  
>  
>  ``ovs-appctl(8)``, ``ovs-vswitchd(8)``, ``ovs-pcap(1)``,
> -``ovs-tcpundump(1)``, ``tcpdump(8)``, ``wireshark(8)``.
> +``ovs-fields(7)``, ``ovs-tcpundump(1)``, ``tcpdump(8)``,
> +``wireshark(8)``.
> diff --git a/NEWS b/NEWS
> index c9e4064e6..35f7eb0c7 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -4,6 +4,9 @@ Post-v3.3.0
>   * Conntrack now supports 'random' flag for selecting ports in a range
> while natting and 'persistent' flag for selection of the IP address
> from a range.
> +   - OVSDB:

'OVSDB' section is usually for changes in ovsdb-server itself.
OVS configuration changes can be in the ovs-vsctl section, if
you're describing a new option for a mirror in ovs-vsctl.  Or
just a separate entry outsie of any sections.  ovs-vsctl might
be a better option here, but you may want to rephrase the entry
in terms of ovs-vsctl configuration.

You may also add an entry for ovs-tcpdump since you're changing
it as well.

> + * Added a new filter column in the Mirror table which can be used to
> +   apply filters to mirror ports.
>  
>  
>  v3.3.0 - 16 Feb 2024
> diff --git a/lib/flow.c b/lib/flow.c
> index 8e3402388..a088bdc86 100644
> --- a/lib/flow.c
> +++ b/lib/flow.c
> @@ -3569,7 +3569,7 @@ miniflow_equal_in_minimask(const struct miniflow *a, 
> const struct miniflow *b,
>  return true;
>  }
>  
> -/* Returns true if 'a' and 'b' are equal at the places where there are 1-bits
> +/* Returns true if 'a' and 'b' are equal at the places where there are 0-bits
>   * in 'mask', false if they differ. */
>  bool
>  miniflow_equal_flow_in_minimask(const struct miniflow *a, const struct flow 
> *b,
> @@ -3587,6 +3587,25 @@ miniflow_equal_flow_in_minimask(const struct miniflow 
> *a, const struct flow *b,
>  return true;
>  }
>  
> +/* Returns false if 'a' and 'b' differ in places where there are 1-bits in
> + * 'wc', true otherwise. */
> +bool
> +miniflow_equal_flow_in_flow_wc(const struct miniflow *a, const struct flow 
> *b,
> +   const struct flow_wildcards *wc)
> +{
> +const struct flow *wc_masks = >masks;
> +size_t idx;
> +
> +FLOWMAP_FOR_EACH_INDEX (idx, a->map) {
> +if ((miniflow_get(a, idx) ^ flow_u64_value(b, idx)) &
> +flow_u64_value(wc_masks, idx)) {
> +return false;
> +}
> +}
> +
> +return true;
> +}

I don't see this function being used anywhere.  Do we need it?

> +
>  
>  void
>  minimask_init(struct minimask *mask, const struct flow_wildcards *wc)
> diff --git a/lib/flow.h b/lib/flow.h
> index 75a9be3c1..a644be39d 100644
> --- a/lib/flow.h
> +++ b/lib/flow.h
> @@ -748,6 +748,9 @@ bool miniflow_equal_in_minimask(const struct miniflow *a,
>  bool miniflow_equal_flow_in_minimask(const struct 

Re: [ovs-dev] [PATCH v7 2/2] ofproto-dpif-mirror: Add support for pre-selection filter.

2024-03-01 Thread Eelco Chaudron


On 26 Feb 2024, at 22:16, Mike Pattrick wrote:

> Currently a bridge mirror will collect all packets and tools like
> ovs-tcpdump can apply additional filters after they have already been
> duplicated by vswitchd. This can result in inefficient collection.
>
> This patch adds support to apply pre-selection to bridge mirrors, which
> can limit which packets are mirrored based on flow metadata. This
> significantly improves overall vswitchd performance during mirroring if
> only a subset of traffic is required.
>
> Signed-off-by: Mike Pattrick 

Hi Mike,

Thanks for the patch revision. Some small comments below.

Cheers,

Eelco

> ---
> v7:
>  - Make sure filter mask is added to masks of non-matching flows.
>  - Added additional tests.
> ---
>  Documentation/ref/ovs-tcpdump.8.rst |   8 +-
>  NEWS|   3 +
>  lib/flow.c  |  21 +++-
>  lib/flow.h  |  12 +++
>  ofproto/ofproto-dpif-mirror.c   |  78 ++-
>  ofproto/ofproto-dpif-mirror.h   |  12 ++-
>  ofproto/ofproto-dpif-xlate.c|  26 -
>  ofproto/ofproto-dpif.c  |   9 +-
>  ofproto/ofproto-dpif.h  |   6 ++
>  ofproto/ofproto.c   |   4 +-
>  ofproto/ofproto.h   |   3 +
>  tests/ofproto-dpif.at   | 142 
>  utilities/ovs-tcpdump.in|  13 ++-
>  vswitchd/bridge.c   |  13 ++-
>  vswitchd/vswitch.ovsschema  |   5 +-
>  vswitchd/vswitch.xml|  13 +++
>  16 files changed, 343 insertions(+), 25 deletions(-)
>
> diff --git a/Documentation/ref/ovs-tcpdump.8.rst 
> b/Documentation/ref/ovs-tcpdump.8.rst
> index b9f8cdf6f..e21e61211 100644
> --- a/Documentation/ref/ovs-tcpdump.8.rst
> +++ b/Documentation/ref/ovs-tcpdump.8.rst
> @@ -61,8 +61,14 @@ Options
>
>If specified, mirror all ports (optional).
>
> +* ``--filter ``
> +
> +  If specified, only mirror flows that match the provided OpenFlow filter.
> +  The available fields are documented in ``ovs-fields(7)``.
> +
>  See Also
>  
>
>  ``ovs-appctl(8)``, ``ovs-vswitchd(8)``, ``ovs-pcap(1)``,
> -``ovs-tcpundump(1)``, ``tcpdump(8)``, ``wireshark(8)``.
> +``ovs-fields(7)``, ``ovs-tcpundump(1)``, ``tcpdump(8)``,
> +``wireshark(8)``.
> diff --git a/NEWS b/NEWS
> index c9e4064e6..35f7eb0c7 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -4,6 +4,9 @@ Post-v3.3.0
>   * Conntrack now supports 'random' flag for selecting ports in a range
> while natting and 'persistent' flag for selection of the IP address
> from a range.
> +   - OVSDB:
> + * Added a new filter column in the Mirror table which can be used to
> +   apply filters to mirror ports.
>
>
>  v3.3.0 - 16 Feb 2024
> diff --git a/lib/flow.c b/lib/flow.c
> index 8e3402388..a088bdc86 100644
> --- a/lib/flow.c
> +++ b/lib/flow.c
> @@ -3569,7 +3569,7 @@ miniflow_equal_in_minimask(const struct miniflow *a, 
> const struct miniflow *b,
>  return true;
>  }
>
> -/* Returns true if 'a' and 'b' are equal at the places where there are 1-bits
> +/* Returns true if 'a' and 'b' are equal at the places where there are 0-bits

I think the logic is that only the differences on the masked data will return 
false. So the original text is right.

>   * in 'mask', false if they differ. */
>  bool
>  miniflow_equal_flow_in_minimask(const struct miniflow *a, const struct flow 
> *b,
> @@ -3587,6 +3587,25 @@ miniflow_equal_flow_in_minimask(const struct miniflow 
> *a, const struct flow *b,
>  return true;
>  }
>
> +/* Returns false if 'a' and 'b' differ in places where there are 1-bits in
> + * 'wc', true otherwise. */

Maybe wright this the same as above to avoid confusion, i.e.

Returns true if 'a' and 'b' are equal at the places where there are 1-bits in 
‘wc’, false if they differ [at the places where there are 1-bits in ‘wc’].

> +bool
> +miniflow_equal_flow_in_flow_wc(const struct miniflow *a, const struct flow 
> *b,
> +   const struct flow_wildcards *wc)
> +{
> +const struct flow *wc_masks = >masks;
> +size_t idx;
> +
> +FLOWMAP_FOR_EACH_INDEX (idx, a->map) {
> +if ((miniflow_get(a, idx) ^ flow_u64_value(b, idx)) &
> +flow_u64_value(wc_masks, idx)) {
> +return false;
> +}
> +}
> +
> +return true;
> +}
> +
>  
>  void
>  minimask_init(struct minimask *mask, const struct flow_wildcards *wc)
> diff --git a/lib/flow.h b/lib/flow.h
> index 75a9be3c1..a644be39d 100644
> --- a/lib/flow.h
> +++ b/lib/flow.h
> @@ -748,6 +748,9 @@ bool miniflow_equal_in_minimask(const struct miniflow *a,
>  bool miniflow_equal_flow_in_minimask(const struct miniflow *a,
>   const struct flow *b,
>   const struct minimask *);
> +bool miniflow_equal_flow_in_flow_wc(const struct miniflow *a,
> +const struct flow *b,
> +