diff mbox series

[ovs-dev,v1,10/13] tests: Test local sampling.

Message ID 20240707200905.2719071-11-amorenoz@redhat.com
State Changes Requested
Delegated to: Eelco Chaudron
Headers show
Series Introduce local sampling with NXAST_SAMPLE action. | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/intel-ovs-compilation fail test: fail

Commit Message

Adrián Moreno July 7, 2024, 8:09 p.m. UTC
Test simultaneous IPFIX and local sampling including slow-path.

Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
---
 tests/system-common-macros.at |   4 +
 tests/system-traffic.at       | 285 ++++++++++++++++++++++++++++++++++
 2 files changed, 289 insertions(+)

Comments

Eelco Chaudron July 9, 2024, 9:46 a.m. UTC | #1
On 7 Jul 2024, at 22:09, Adrian Moreno wrote:

> Test simultaneous IPFIX and local sampling including slow-path.

See comments below.

Cheers,

Eelco

> Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
> ---
>  tests/system-common-macros.at |   4 +
>  tests/system-traffic.at       | 285 ++++++++++++++++++++++++++++++++++
>  2 files changed, 289 insertions(+)
>
> diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at
> index 2a68cd664..860d6a8c9 100644
> --- a/tests/system-common-macros.at
> +++ b/tests/system-common-macros.at
> @@ -378,3 +378,7 @@ m4_define([OVS_CHECK_GITHUB_ACTION],
>  # OVS_CHECK_DROP_ACTION()
>  m4_define([OVS_CHECK_DROP_ACTION],
>      [AT_SKIP_IF([! grep -q "Datapath supports explicit drop action" ovs-vswitchd.log])])
> +
> +# OVS_CHECK_PSAMPLE()
> +m4_define([OVS_CHECK_PSAMPLE],
> +    [AT_SKIP_IF([! grep -q "Datapath supports psample" ovs-vswitchd.log])])
> diff --git a/tests/system-traffic.at b/tests/system-traffic.at
> index 3f1a15445..ddab4ece3 100644
> --- a/tests/system-traffic.at
> +++ b/tests/system-traffic.at
> @@ -9103,3 +9103,288 @@ OVS_WAIT_UNTIL([ovs-pcap p2.pcap | grep -q "m4_join([], [^],
>
>  OVS_TRAFFIC_VSWITCHD_STOP
>  AT_CLEANUP
> +
> +AT_BANNER([local-sampling])
> +
> +m4_define([SAMPLE_ACTION],
> +    [sample(probability=65535,collector_set_id=$1,obs_domain_id=$2,obs_point_id=$3)]dnl
> +)
> +
> +AT_SETUP([psample - sanity check])

Maybe call it '- ipv4' as it's equal to ipv6, or rename the IPv6 one to
'sanity check IPv6'

> +OVS_TRAFFIC_VSWITCHD_START()
> +OVS_CHECK_PSAMPLE()
> +
> +ADD_NAMESPACES(at_ns0, at_ns1)
> +
> +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
> +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
> +
> +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
> +                    -- create Flow_Sample_Collector_Set id=1 bridge=@br0 local_group_id=10 \
> +                    -- create Flow_Sample_Collector_Set id=2 bridge=@br0 local_group_id=12],
> +         [0], [ignore])

Maybe wrap to stay <80 chars?

AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
                    -- create Flow_Sample_Collector_Set id=1 bridge=@br0 \
                       local_group_id=10 \
                    -- create Flow_Sample_Collector_Set id=2 bridge=@br0 \
                       local_group_id=12],
         [0], [ignore])

> +
> +AT_DATA([flows.txt], [dnl
> +arp actions=NORMAL
> +in_port=ovs-p0,ip actions=SAMPLE_ACTION(1, 2853183536, 2856341600),ovs-p1
> +in_port=ovs-p1,ip actions=SAMPLE_ACTION(2, 3138396208, 3141554272),ovs-p0
> +])
> +
> +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
> +
> +OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample.pid])
> +OVS_WAIT_UNTIL([grep -q "Listening for psample events" psample.out])
> +
> +NS_CHECK_EXEC([at_ns0], [ping -q -c 1 10.1.1.2 | FORMAT_PING], [0], [dnl
> +1 packets transmitted, 1 received, 0% packet loss, time 0ms
> +])
> +
> +AT_CHECK([ovs-appctl dpctl/dump-flows -m --names], [0], [stdout])
> +AT_CHECK([grep -q 'actions:psample(group=10,cookie=0xaa102030aa405060),ovs-p1' stdout])
> +AT_CHECK([grep -q 'actions:psample(group=12,cookie=0xbb102030bb405060),ovs-p0' stdout])
> +
> +m4_define([SAMPLE1], [m4_join([ ],
> +    [group_id=0xa],
> +    [obs_domain=0xaa102030,obs_point=0xaa405060],
> +    [.*icmp.*nw_src=10.1.1.1,nw_dst=10.1.1.2])])
> +
> +m4_define([SAMPLE2], [m4_join([ ],
> +    [group_id=0xc],
> +    [obs_domain=0xbb102030,obs_point=0xbb405060],
> +    [.*icmp.*nw_src=10.1.1.2,nw_dst=10.1.1.1])])
> +
> +OVS_WAIT_UNTIL([grep -qE 'SAMPLE1' psample.out])
> +OVS_WAIT_UNTIL([grep -qE 'SAMPLE2' psample.out])
> +
> +AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl
> +Local sample statistics for bridge "br0":
> +Collector Set ID: 1:
> +  Group ID     : 10
> +  Total packets: 1
> +  Total bytes  : 98
> +
> +Collector Set ID: 2:
> +  Group ID     : 12
> +  Total packets: 1
> +  Total bytes  : 98
> +])
> +

We miss OVS_TRAFFIC_VSWITCHD_STOP() here.

> +AT_CLEANUP
> +
> +AT_SETUP([psample - ipv6])

See comment above, if you decide to keep it ipv6, please change it to IPv6.

> +OVS_TRAFFIC_VSWITCHD_START()
> +OVS_CHECK_PSAMPLE()
> +
> +ADD_NAMESPACES(at_ns0, at_ns1)
> +
> +ADD_VETH(p0, at_ns0, br0, "fc00::1/96")
> +ADD_VETH(p1, at_ns1, br0, "fc00::2/96")
> +
> +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
> +                    -- create Flow_Sample_Collector_Set id=1 bridge=@br0 local_group_id=10 \
> +                    -- create Flow_Sample_Collector_Set id=2 bridge=@br0 local_group_id=12],
> +         [0], [ignore])
> +
> +AT_DATA([flows.txt], [dnl
> +priority=100,in_port=ovs-p0,ip6,icmp6,icmpv6_type=128 actions=SAMPLE_ACTION(1, 2853183536, 2856341600),ovs-p1
> +priority=100,in_port=ovs-p1,ip6,icmp6,icmpv6_type=129 actions=SAMPLE_ACTION(2, 3138396208, 3141554272),ovs-p0
> +priority=0 actions=NORMAL
> +])
> +
> +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
> +
> +OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample.pid])
> +OVS_WAIT_UNTIL([grep -q "Listening for psample events" psample.out])
> +
> +OVS_WAIT_UNTIL_EQUAL([ip netns exec at_ns0 ping6 -I fc00::1 -q -W 2 -c 1 fc00::2 | FORMAT_PING], [dnl
> +1 packets transmitted, 1 received, 0% packet loss, time 0ms])
> +

Maybe:

OVS_WAIT_UNTIL_EQUAL(
    [ip netns exec at_ns0 ping6 -I fc00::1 -q -W 2 -c 1 fc00::2 | FORMAT_PING],
    [dnl
1 packets transmitted, 1 received, 0% packet loss, time 0ms])


> +AT_CHECK([ovs-appctl dpctl/dump-flows -m --names], [0], [stdout])
> +AT_CHECK([grep -q 'actions:psample(group=10,cookie=0xaa102030aa405060),ovs-p1' stdout])
> +AT_CHECK([grep -q 'actions:psample(group=12,cookie=0xbb102030bb405060),ovs-p0' stdout])
> +
> +m4_define([SAMPLE1], [m4_join([ ],
> +    [group_id=0xa],
> +    [obs_domain=0xaa102030,obs_point=0xaa405060],
> +    [.*icmp6.*ipv6_src=fc00::1,ipv6_dst=fc00::2])])
> +m4_define([SAMPLE2], [m4_join([ ],
> +    [group_id=0xc],
> +    [obs_domain=0xbb102030,obs_point=0xbb405060],
> +    [.*icmp6.*ipv6_src=fc00::2,ipv6_dst=fc00::1])])
> +
> +OVS_WAIT_UNTIL([grep -qE 'SAMPLE1' psample.out])
> +OVS_WAIT_UNTIL([grep -qE 'SAMPLE2' psample.out])
> +
> +AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl
> +Local sample statistics for bridge "br0":
> +Collector Set ID: 1:
> +  Group ID     : 10
> +  Total packets: 1
> +  Total bytes  : 118
> +
> +Collector Set ID: 2:
> +  Group ID     : 12
> +  Total packets: 1
> +  Total bytes  : 118
> +])
> +

We miss OVS_TRAFFIC_VSWITCHD_STOP() here.

> +AT_CLEANUP
> +
> +AT_SETUP([psample - slow])

What are you trying to do with this test? It looks the same as the sanity one,
or I might just need more Coffee.

> +OVS_TRAFFIC_VSWITCHD_START()
> +OVS_CHECK_PSAMPLE()
> +
> +ADD_NAMESPACES(at_ns0, at_ns1)
> +
> +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
> +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
> +
> +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
> +                    -- create Flow_Sample_Collector_Set id=1 bridge=@br0 local_group_id=10 \
> +                    -- create Flow_Sample_Collector_Set id=2 bridge=@br0 local_group_id=12],
> +         [0], [ignore])
> +
> +
> +AT_DATA([flows.txt], [dnl
> +arp actions=NORMAL
> +in_port=ovs-p0,ip actions=SAMPLE_ACTION(1, 2853183536, 2856341600),ovs-p1
> +in_port=ovs-p1,ip actions=SAMPLE_ACTION(2, 3138396208, 3141554272),ovs-p0
> +])

New line

> +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
> +
> +AT_CHECK([ovs-appctl ofproto/trace br0 \
> +    'in_port=ovs-p0,dl_src=e4:11:22:33:44:55,dl_dst=e4:11:22:33:44:66,dl_type=0x0800,nw_src=10.1.1.1,nw_dst=10.1.1.12'],
> +    [0], [stdout])
> +
> +AT_CHECK([tail -1 stdout], [0], [dnl
> +Datapath actions: psample(group=10,cookie=0xaa102030aa405060),3
> +])
> +
> +OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample.pid])
> +

Do we need:
  OVS_WAIT_UNTIL([grep -q "Listening for psample events" psample.out])


> +NS_CHECK_EXEC([at_ns0], [ping -q -c 1 10.1.1.2 | FORMAT_PING], [0], [dnl
> +1 packets transmitted, 1 received, 0% packet loss, time 0ms
> +])
> +
> +m4_define([SAMPLE1], [m4_join([ ],
> +    [group_id=0xa],
> +    [obs_domain=0xaa102030,obs_point=0xaa405060],
> +    [.*icmp.*nw_src=10.1.1.1,nw_dst=10.1.1.2])])
> +
> +m4_define([SAMPLE2], [m4_join([ ],
> +    [group_id=0xc],
> +    [obs_domain=0xbb102030,obs_point=0xbb405060],
> +    [.*icmp.*nw_src=10.1.1.2,nw_dst=10.1.1.1])])
> +
> +AT_CHECK([grep -qE 'SAMPLE1' psample.out])
> +AT_CHECK([grep -qE 'SAMPLE2' psample.out])
> +
> +AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl
> +Local sample statistics for bridge "br0":
> +Collector Set ID: 1:
> +  Group ID     : 10
> +  Total packets: 1
> +  Total bytes  : 98
> +
> +Collector Set ID: 2:
> +  Group ID     : 12
> +  Total packets: 1
> +  Total bytes  : 98
> +])
> +
> +OVS_TRAFFIC_VSWITCHD_STOP(["/sending to collector failed/d"])
> +AT_CLEANUP
> +
> +AT_SETUP([psample - with IPFIX])
> +OVS_TRAFFIC_VSWITCHD_START()
> +OVS_CHECK_PSAMPLE()
> +
> +ADD_NAMESPACES(at_ns0, at_ns1)
> +
> +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
> +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
> +
> +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
> +                    -- --id=@i create IPFIX targets=\"127.0.0.1:4739\" \
> +                    -- create Flow_Sample_Collector_Set id=1 ipfix=@i bridge=@br0 local_group_id=10 \
> +                    -- create Flow_Sample_Collector_Set id=2 ipfix=@i bridge=@br0 local_group_id=12],
> +         [0], [ignore])
> +
> +AT_DATA([flows.txt], [dnl
> +arp actions=NORMAL
> +in_port=ovs-p0,ip actions=SAMPLE_ACTION(1, 2853183536, 2856341600),ovs-p1
> +in_port=ovs-p1,ip actions=SAMPLE_ACTION(2, 3138396208, 3141554272),ovs-p0
> +])
> +
> +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
> +
> +
> +AT_CHECK([ovs-appctl ofproto/trace br0 \
> +    'in_port=ovs-p0,dl_src=e4:11:22:33:44:55,dl_dst=e4:11:22:33:44:66,dl_type=0x0800,nw_src=10.1.1.1,nw_dst=10.1.1.12'],
> +    [0], [stdout])
> +
> +
> +m4_define([ACTIONS], [m4_join([],
> +    [psample(group=10,cookie=0xaa102030aa405060),],
> +    [userspace(pid=4294967295,],
> +        [flow_sample(probability=65535,],
> +        [collector_set_id=1,],
> +        [obs_domain_id=2853183536,],
> +        [obs_point_id=2856341600,],
> +        [output_port=4294967295)),],
> +    [3])])
> +
> +AT_CHECK([tail -1 stdout], [0], [dnl
> +Datapath actions: ACTIONS
> +])
> +
> +OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample.pid])
> +OVS_WAIT_UNTIL([grep -q "Listening for psample events" psample.out])
> +
> +NS_CHECK_EXEC([at_ns0], [ping -q -c 1 10.1.1.2 | FORMAT_PING], [0], [dnl
> +1 packets transmitted, 1 received, 0% packet loss, time 0ms
> +])
> +
> +m4_define([SAMPLE1], [m4_join([ ],
> +    [group_id=0xa],
> +    [obs_domain=0xaa102030,obs_point=0xaa405060],
> +    [.*icmp.*nw_src=10.1.1.1,nw_dst=10.1.1.2])])
> +
> +m4_define([SAMPLE2], [m4_join([ ],
> +    [group_id=0xc],
> +    [obs_domain=0xbb102030,obs_point=0xbb405060],
> +    [.*icmp.*nw_src=10.1.1.2,nw_dst=10.1.1.1])])
> +
> +OVS_WAIT_UNTIL([grep -qE 'SAMPLE1' psample.out])
> +OVS_WAIT_UNTIL([grep -qE 'SAMPLE2' psample.out])
> +
> +dnl Check IPFIX samples have been received.
> +dnl Entries can be unsorted and IFPIX packets might not have been sent (or
> +dnl at least tried to be sent) yet.
> +OVS_WAIT_UNTIL_EQUAL([ovs-ofctl dump-ipfix-flow br0 | \
> +                sed 's/tx pkts=[[0-9]]*/tx pkts=24/' | \
> +                sed 's/tx errs=[[0-9]]*/tx errs=0/' | \
> +                sed 's/id   [[1-2]]:/id   ?:/'], [dnl
> +NXST_IPFIX_FLOW reply (xid=0x2): 2 ids
> +  id   ?: flows=1, current flows=0, sampled pkts=1, ipv4 ok=1, ipv6 ok=0, tx pkts=24
> +          pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
> +  id   ?: flows=1, current flows=0, sampled pkts=1, ipv4 ok=1, ipv6 ok=0, tx pkts=24
> +          pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0])
> +
> +AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl
> +Local sample statistics for bridge "br0":
> +Collector Set ID: 1:
> +  Group ID     : 10
> +  Total packets: 1
> +  Total bytes  : 98
> +
> +Collector Set ID: 2:
> +  Group ID     : 12
> +  Total packets: 1
> +  Total bytes  : 98
> +])
> +
> +dnl OVS will fail to send IPFIX packets because the target is localhost
> +dnl and the port is closed. Ignore the message it generates.
> +OVS_TRAFFIC_VSWITCHD_STOP(["/sending to collector failed/d"])
> +AT_CLEANUP
> -- 
> 2.45.2
Adrián Moreno July 9, 2024, 1:56 p.m. UTC | #2
On Tue, Jul 09, 2024 at 11:46:03AM GMT, Eelco Chaudron wrote:
> On 7 Jul 2024, at 22:09, Adrian Moreno wrote:
>
> > Test simultaneous IPFIX and local sampling including slow-path.
>
> See comments below.
>
> Cheers,
>
> Eelco
>
> > Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
> > ---
> >  tests/system-common-macros.at |   4 +
> >  tests/system-traffic.at       | 285 ++++++++++++++++++++++++++++++++++
> >  2 files changed, 289 insertions(+)
> >
> > diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at
> > index 2a68cd664..860d6a8c9 100644
> > --- a/tests/system-common-macros.at
> > +++ b/tests/system-common-macros.at
> > @@ -378,3 +378,7 @@ m4_define([OVS_CHECK_GITHUB_ACTION],
> >  # OVS_CHECK_DROP_ACTION()
> >  m4_define([OVS_CHECK_DROP_ACTION],
> >      [AT_SKIP_IF([! grep -q "Datapath supports explicit drop action" ovs-vswitchd.log])])
> > +
> > +# OVS_CHECK_PSAMPLE()
> > +m4_define([OVS_CHECK_PSAMPLE],
> > +    [AT_SKIP_IF([! grep -q "Datapath supports psample" ovs-vswitchd.log])])
> > diff --git a/tests/system-traffic.at b/tests/system-traffic.at
> > index 3f1a15445..ddab4ece3 100644
> > --- a/tests/system-traffic.at
> > +++ b/tests/system-traffic.at
> > @@ -9103,3 +9103,288 @@ OVS_WAIT_UNTIL([ovs-pcap p2.pcap | grep -q "m4_join([], [^],
> >
> >  OVS_TRAFFIC_VSWITCHD_STOP
> >  AT_CLEANUP
> > +
> > +AT_BANNER([local-sampling])
> > +
> > +m4_define([SAMPLE_ACTION],
> > +    [sample(probability=65535,collector_set_id=$1,obs_domain_id=$2,obs_point_id=$3)]dnl
> > +)
> > +
> > +AT_SETUP([psample - sanity check])
>
> Maybe call it '- ipv4' as it's equal to ipv6, or rename the IPv6 one to
> 'sanity check IPv6'

Ack.

>
> > +OVS_TRAFFIC_VSWITCHD_START()
> > +OVS_CHECK_PSAMPLE()
> > +
> > +ADD_NAMESPACES(at_ns0, at_ns1)
> > +
> > +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
> > +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
> > +
> > +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
> > +                    -- create Flow_Sample_Collector_Set id=1 bridge=@br0 local_group_id=10 \
> > +                    -- create Flow_Sample_Collector_Set id=2 bridge=@br0 local_group_id=12],
> > +         [0], [ignore])
>
> Maybe wrap to stay <80 chars?
>
> AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
>                     -- create Flow_Sample_Collector_Set id=1 bridge=@br0 \
>                        local_group_id=10 \
>                     -- create Flow_Sample_Collector_Set id=2 bridge=@br0 \
>                        local_group_id=12],
>          [0], [ignore])
>

Ack.

> > +
> > +AT_DATA([flows.txt], [dnl
> > +arp actions=NORMAL
> > +in_port=ovs-p0,ip actions=SAMPLE_ACTION(1, 2853183536, 2856341600),ovs-p1
> > +in_port=ovs-p1,ip actions=SAMPLE_ACTION(2, 3138396208, 3141554272),ovs-p0
> > +])
> > +
> > +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
> > +
> > +OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample.pid])
> > +OVS_WAIT_UNTIL([grep -q "Listening for psample events" psample.out])
> > +
> > +NS_CHECK_EXEC([at_ns0], [ping -q -c 1 10.1.1.2 | FORMAT_PING], [0], [dnl
> > +1 packets transmitted, 1 received, 0% packet loss, time 0ms
> > +])
> > +
> > +AT_CHECK([ovs-appctl dpctl/dump-flows -m --names], [0], [stdout])
> > +AT_CHECK([grep -q 'actions:psample(group=10,cookie=0xaa102030aa405060),ovs-p1' stdout])
> > +AT_CHECK([grep -q 'actions:psample(group=12,cookie=0xbb102030bb405060),ovs-p0' stdout])
> > +
> > +m4_define([SAMPLE1], [m4_join([ ],
> > +    [group_id=0xa],
> > +    [obs_domain=0xaa102030,obs_point=0xaa405060],
> > +    [.*icmp.*nw_src=10.1.1.1,nw_dst=10.1.1.2])])
> > +
> > +m4_define([SAMPLE2], [m4_join([ ],
> > +    [group_id=0xc],
> > +    [obs_domain=0xbb102030,obs_point=0xbb405060],
> > +    [.*icmp.*nw_src=10.1.1.2,nw_dst=10.1.1.1])])
> > +
> > +OVS_WAIT_UNTIL([grep -qE 'SAMPLE1' psample.out])
> > +OVS_WAIT_UNTIL([grep -qE 'SAMPLE2' psample.out])
> > +
> > +AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl
> > +Local sample statistics for bridge "br0":
> > +Collector Set ID: 1:
> > +  Group ID     : 10
> > +  Total packets: 1
> > +  Total bytes  : 98
> > +
> > +Collector Set ID: 2:
> > +  Group ID     : 12
> > +  Total packets: 1
> > +  Total bytes  : 98
> > +])
> > +
>
> We miss OVS_TRAFFIC_VSWITCHD_STOP() here.
>

Yes!

> > +AT_CLEANUP
> > +
> > +AT_SETUP([psample - ipv6])
>
> See comment above, if you decide to keep it ipv6, please change it to IPv6.
>
> > +OVS_TRAFFIC_VSWITCHD_START()
> > +OVS_CHECK_PSAMPLE()
> > +
> > +ADD_NAMESPACES(at_ns0, at_ns1)
> > +
> > +ADD_VETH(p0, at_ns0, br0, "fc00::1/96")
> > +ADD_VETH(p1, at_ns1, br0, "fc00::2/96")
> > +
> > +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
> > +                    -- create Flow_Sample_Collector_Set id=1 bridge=@br0 local_group_id=10 \
> > +                    -- create Flow_Sample_Collector_Set id=2 bridge=@br0 local_group_id=12],
> > +         [0], [ignore])
> > +
> > +AT_DATA([flows.txt], [dnl
> > +priority=100,in_port=ovs-p0,ip6,icmp6,icmpv6_type=128 actions=SAMPLE_ACTION(1, 2853183536, 2856341600),ovs-p1
> > +priority=100,in_port=ovs-p1,ip6,icmp6,icmpv6_type=129 actions=SAMPLE_ACTION(2, 3138396208, 3141554272),ovs-p0
> > +priority=0 actions=NORMAL
> > +])
> > +
> > +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
> > +
> > +OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample.pid])
> > +OVS_WAIT_UNTIL([grep -q "Listening for psample events" psample.out])
> > +
> > +OVS_WAIT_UNTIL_EQUAL([ip netns exec at_ns0 ping6 -I fc00::1 -q -W 2 -c 1 fc00::2 | FORMAT_PING], [dnl
> > +1 packets transmitted, 1 received, 0% packet loss, time 0ms])
> > +
>
> Maybe:
>
> OVS_WAIT_UNTIL_EQUAL(
>     [ip netns exec at_ns0 ping6 -I fc00::1 -q -W 2 -c 1 fc00::2 | FORMAT_PING],
>     [dnl
> 1 packets transmitted, 1 received, 0% packet loss, time 0ms])
>

Ack.

>
> > +AT_CHECK([ovs-appctl dpctl/dump-flows -m --names], [0], [stdout])
> > +AT_CHECK([grep -q 'actions:psample(group=10,cookie=0xaa102030aa405060),ovs-p1' stdout])
> > +AT_CHECK([grep -q 'actions:psample(group=12,cookie=0xbb102030bb405060),ovs-p0' stdout])
> > +
> > +m4_define([SAMPLE1], [m4_join([ ],
> > +    [group_id=0xa],
> > +    [obs_domain=0xaa102030,obs_point=0xaa405060],
> > +    [.*icmp6.*ipv6_src=fc00::1,ipv6_dst=fc00::2])])
> > +m4_define([SAMPLE2], [m4_join([ ],
> > +    [group_id=0xc],
> > +    [obs_domain=0xbb102030,obs_point=0xbb405060],
> > +    [.*icmp6.*ipv6_src=fc00::2,ipv6_dst=fc00::1])])
> > +
> > +OVS_WAIT_UNTIL([grep -qE 'SAMPLE1' psample.out])
> > +OVS_WAIT_UNTIL([grep -qE 'SAMPLE2' psample.out])
> > +
> > +AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl
> > +Local sample statistics for bridge "br0":
> > +Collector Set ID: 1:
> > +  Group ID     : 10
> > +  Total packets: 1
> > +  Total bytes  : 118
> > +
> > +Collector Set ID: 2:
> > +  Group ID     : 12
> > +  Total packets: 1
> > +  Total bytes  : 118
> > +])
> > +
>
> We miss OVS_TRAFFIC_VSWITCHD_STOP() here.
>

Ack

> > +AT_CLEANUP
> > +
> > +AT_SETUP([psample - slow])
>
> What are you trying to do with this test? It looks the same as the sanity one,
> or I might just need more Coffee.
>

OMG!
I would swear I had added "debug_slow" to the flows to force it to go
though slow path but somehow it has disappeared!

Thanks for catching this.

> > +OVS_TRAFFIC_VSWITCHD_START()
> > +OVS_CHECK_PSAMPLE()
> > +
> > +ADD_NAMESPACES(at_ns0, at_ns1)
> > +
> > +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
> > +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
> > +
> > +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
> > +                    -- create Flow_Sample_Collector_Set id=1 bridge=@br0 local_group_id=10 \
> > +                    -- create Flow_Sample_Collector_Set id=2 bridge=@br0 local_group_id=12],
> > +         [0], [ignore])
> > +
> > +
> > +AT_DATA([flows.txt], [dnl
> > +arp actions=NORMAL
> > +in_port=ovs-p0,ip actions=SAMPLE_ACTION(1, 2853183536, 2856341600),ovs-p1
> > +in_port=ovs-p1,ip actions=SAMPLE_ACTION(2, 3138396208, 3141554272),ovs-p0
> > +])
>
> New line
>
> > +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
> > +
> > +AT_CHECK([ovs-appctl ofproto/trace br0 \
> > +    'in_port=ovs-p0,dl_src=e4:11:22:33:44:55,dl_dst=e4:11:22:33:44:66,dl_type=0x0800,nw_src=10.1.1.1,nw_dst=10.1.1.12'],
> > +    [0], [stdout])
> > +
> > +AT_CHECK([tail -1 stdout], [0], [dnl
> > +Datapath actions: psample(group=10,cookie=0xaa102030aa405060),3
> > +])
> > +
> > +OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample.pid])
> > +
>
> Do we need:
>   OVS_WAIT_UNTIL([grep -q "Listening for psample events" psample.out])
>
>
> > +NS_CHECK_EXEC([at_ns0], [ping -q -c 1 10.1.1.2 | FORMAT_PING], [0], [dnl
> > +1 packets transmitted, 1 received, 0% packet loss, time 0ms
> > +])
> > +
> > +m4_define([SAMPLE1], [m4_join([ ],
> > +    [group_id=0xa],
> > +    [obs_domain=0xaa102030,obs_point=0xaa405060],
> > +    [.*icmp.*nw_src=10.1.1.1,nw_dst=10.1.1.2])])
> > +
> > +m4_define([SAMPLE2], [m4_join([ ],
> > +    [group_id=0xc],
> > +    [obs_domain=0xbb102030,obs_point=0xbb405060],
> > +    [.*icmp.*nw_src=10.1.1.2,nw_dst=10.1.1.1])])
> > +
> > +AT_CHECK([grep -qE 'SAMPLE1' psample.out])
> > +AT_CHECK([grep -qE 'SAMPLE2' psample.out])
> > +
> > +AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl
> > +Local sample statistics for bridge "br0":
> > +Collector Set ID: 1:
> > +  Group ID     : 10
> > +  Total packets: 1
> > +  Total bytes  : 98
> > +
> > +Collector Set ID: 2:
> > +  Group ID     : 12
> > +  Total packets: 1
> > +  Total bytes  : 98
> > +])
> > +
> > +OVS_TRAFFIC_VSWITCHD_STOP(["/sending to collector failed/d"])
> > +AT_CLEANUP
> > +
> > +AT_SETUP([psample - with IPFIX])
> > +OVS_TRAFFIC_VSWITCHD_START()
> > +OVS_CHECK_PSAMPLE()
> > +
> > +ADD_NAMESPACES(at_ns0, at_ns1)
> > +
> > +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
> > +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
> > +
> > +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
> > +                    -- --id=@i create IPFIX targets=\"127.0.0.1:4739\" \
> > +                    -- create Flow_Sample_Collector_Set id=1 ipfix=@i bridge=@br0 local_group_id=10 \
> > +                    -- create Flow_Sample_Collector_Set id=2 ipfix=@i bridge=@br0 local_group_id=12],
> > +         [0], [ignore])
> > +
> > +AT_DATA([flows.txt], [dnl
> > +arp actions=NORMAL
> > +in_port=ovs-p0,ip actions=SAMPLE_ACTION(1, 2853183536, 2856341600),ovs-p1
> > +in_port=ovs-p1,ip actions=SAMPLE_ACTION(2, 3138396208, 3141554272),ovs-p0
> > +])
> > +
> > +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
> > +
> > +
> > +AT_CHECK([ovs-appctl ofproto/trace br0 \
> > +    'in_port=ovs-p0,dl_src=e4:11:22:33:44:55,dl_dst=e4:11:22:33:44:66,dl_type=0x0800,nw_src=10.1.1.1,nw_dst=10.1.1.12'],
> > +    [0], [stdout])
> > +
> > +
> > +m4_define([ACTIONS], [m4_join([],
> > +    [psample(group=10,cookie=0xaa102030aa405060),],
> > +    [userspace(pid=4294967295,],
> > +        [flow_sample(probability=65535,],
> > +        [collector_set_id=1,],
> > +        [obs_domain_id=2853183536,],
> > +        [obs_point_id=2856341600,],
> > +        [output_port=4294967295)),],
> > +    [3])])
> > +
> > +AT_CHECK([tail -1 stdout], [0], [dnl
> > +Datapath actions: ACTIONS
> > +])
> > +
> > +OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample.pid])
> > +OVS_WAIT_UNTIL([grep -q "Listening for psample events" psample.out])
> > +
> > +NS_CHECK_EXEC([at_ns0], [ping -q -c 1 10.1.1.2 | FORMAT_PING], [0], [dnl
> > +1 packets transmitted, 1 received, 0% packet loss, time 0ms
> > +])
> > +
> > +m4_define([SAMPLE1], [m4_join([ ],
> > +    [group_id=0xa],
> > +    [obs_domain=0xaa102030,obs_point=0xaa405060],
> > +    [.*icmp.*nw_src=10.1.1.1,nw_dst=10.1.1.2])])
> > +
> > +m4_define([SAMPLE2], [m4_join([ ],
> > +    [group_id=0xc],
> > +    [obs_domain=0xbb102030,obs_point=0xbb405060],
> > +    [.*icmp.*nw_src=10.1.1.2,nw_dst=10.1.1.1])])
> > +
> > +OVS_WAIT_UNTIL([grep -qE 'SAMPLE1' psample.out])
> > +OVS_WAIT_UNTIL([grep -qE 'SAMPLE2' psample.out])
> > +
> > +dnl Check IPFIX samples have been received.
> > +dnl Entries can be unsorted and IFPIX packets might not have been sent (or
> > +dnl at least tried to be sent) yet.
> > +OVS_WAIT_UNTIL_EQUAL([ovs-ofctl dump-ipfix-flow br0 | \
> > +                sed 's/tx pkts=[[0-9]]*/tx pkts=24/' | \
> > +                sed 's/tx errs=[[0-9]]*/tx errs=0/' | \
> > +                sed 's/id   [[1-2]]:/id   ?:/'], [dnl
> > +NXST_IPFIX_FLOW reply (xid=0x2): 2 ids
> > +  id   ?: flows=1, current flows=0, sampled pkts=1, ipv4 ok=1, ipv6 ok=0, tx pkts=24
> > +          pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
> > +  id   ?: flows=1, current flows=0, sampled pkts=1, ipv4 ok=1, ipv6 ok=0, tx pkts=24
> > +          pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0])
> > +
> > +AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl
> > +Local sample statistics for bridge "br0":
> > +Collector Set ID: 1:
> > +  Group ID     : 10
> > +  Total packets: 1
> > +  Total bytes  : 98
> > +
> > +Collector Set ID: 2:
> > +  Group ID     : 12
> > +  Total packets: 1
> > +  Total bytes  : 98
> > +])
> > +
> > +dnl OVS will fail to send IPFIX packets because the target is localhost
> > +dnl and the port is closed. Ignore the message it generates.
> > +OVS_TRAFFIC_VSWITCHD_STOP(["/sending to collector failed/d"])
> > +AT_CLEANUP
> > --
> > 2.45.2
>
diff mbox series

Patch

diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at
index 2a68cd664..860d6a8c9 100644
--- a/tests/system-common-macros.at
+++ b/tests/system-common-macros.at
@@ -378,3 +378,7 @@  m4_define([OVS_CHECK_GITHUB_ACTION],
 # OVS_CHECK_DROP_ACTION()
 m4_define([OVS_CHECK_DROP_ACTION],
     [AT_SKIP_IF([! grep -q "Datapath supports explicit drop action" ovs-vswitchd.log])])
+
+# OVS_CHECK_PSAMPLE()
+m4_define([OVS_CHECK_PSAMPLE],
+    [AT_SKIP_IF([! grep -q "Datapath supports psample" ovs-vswitchd.log])])
diff --git a/tests/system-traffic.at b/tests/system-traffic.at
index 3f1a15445..ddab4ece3 100644
--- a/tests/system-traffic.at
+++ b/tests/system-traffic.at
@@ -9103,3 +9103,288 @@  OVS_WAIT_UNTIL([ovs-pcap p2.pcap | grep -q "m4_join([], [^],
 
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
+
+AT_BANNER([local-sampling])
+
+m4_define([SAMPLE_ACTION],
+    [sample(probability=65535,collector_set_id=$1,obs_domain_id=$2,obs_point_id=$3)]dnl
+)
+
+AT_SETUP([psample - sanity check])
+OVS_TRAFFIC_VSWITCHD_START()
+OVS_CHECK_PSAMPLE()
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
+
+AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
+                    -- create Flow_Sample_Collector_Set id=1 bridge=@br0 local_group_id=10 \
+                    -- create Flow_Sample_Collector_Set id=2 bridge=@br0 local_group_id=12],
+         [0], [ignore])
+
+AT_DATA([flows.txt], [dnl
+arp actions=NORMAL
+in_port=ovs-p0,ip actions=SAMPLE_ACTION(1, 2853183536, 2856341600),ovs-p1
+in_port=ovs-p1,ip actions=SAMPLE_ACTION(2, 3138396208, 3141554272),ovs-p0
+])
+
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample.pid])
+OVS_WAIT_UNTIL([grep -q "Listening for psample events" psample.out])
+
+NS_CHECK_EXEC([at_ns0], [ping -q -c 1 10.1.1.2 | FORMAT_PING], [0], [dnl
+1 packets transmitted, 1 received, 0% packet loss, time 0ms
+])
+
+AT_CHECK([ovs-appctl dpctl/dump-flows -m --names], [0], [stdout])
+AT_CHECK([grep -q 'actions:psample(group=10,cookie=0xaa102030aa405060),ovs-p1' stdout])
+AT_CHECK([grep -q 'actions:psample(group=12,cookie=0xbb102030bb405060),ovs-p0' stdout])
+
+m4_define([SAMPLE1], [m4_join([ ],
+    [group_id=0xa],
+    [obs_domain=0xaa102030,obs_point=0xaa405060],
+    [.*icmp.*nw_src=10.1.1.1,nw_dst=10.1.1.2])])
+
+m4_define([SAMPLE2], [m4_join([ ],
+    [group_id=0xc],
+    [obs_domain=0xbb102030,obs_point=0xbb405060],
+    [.*icmp.*nw_src=10.1.1.2,nw_dst=10.1.1.1])])
+
+OVS_WAIT_UNTIL([grep -qE 'SAMPLE1' psample.out])
+OVS_WAIT_UNTIL([grep -qE 'SAMPLE2' psample.out])
+
+AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl
+Local sample statistics for bridge "br0":
+Collector Set ID: 1:
+  Group ID     : 10
+  Total packets: 1
+  Total bytes  : 98
+
+Collector Set ID: 2:
+  Group ID     : 12
+  Total packets: 1
+  Total bytes  : 98
+])
+
+AT_CLEANUP
+
+AT_SETUP([psample - ipv6])
+OVS_TRAFFIC_VSWITCHD_START()
+OVS_CHECK_PSAMPLE()
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "fc00::1/96")
+ADD_VETH(p1, at_ns1, br0, "fc00::2/96")
+
+AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
+                    -- create Flow_Sample_Collector_Set id=1 bridge=@br0 local_group_id=10 \
+                    -- create Flow_Sample_Collector_Set id=2 bridge=@br0 local_group_id=12],
+         [0], [ignore])
+
+AT_DATA([flows.txt], [dnl
+priority=100,in_port=ovs-p0,ip6,icmp6,icmpv6_type=128 actions=SAMPLE_ACTION(1, 2853183536, 2856341600),ovs-p1
+priority=100,in_port=ovs-p1,ip6,icmp6,icmpv6_type=129 actions=SAMPLE_ACTION(2, 3138396208, 3141554272),ovs-p0
+priority=0 actions=NORMAL
+])
+
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample.pid])
+OVS_WAIT_UNTIL([grep -q "Listening for psample events" psample.out])
+
+OVS_WAIT_UNTIL_EQUAL([ip netns exec at_ns0 ping6 -I fc00::1 -q -W 2 -c 1 fc00::2 | FORMAT_PING], [dnl
+1 packets transmitted, 1 received, 0% packet loss, time 0ms])
+
+AT_CHECK([ovs-appctl dpctl/dump-flows -m --names], [0], [stdout])
+AT_CHECK([grep -q 'actions:psample(group=10,cookie=0xaa102030aa405060),ovs-p1' stdout])
+AT_CHECK([grep -q 'actions:psample(group=12,cookie=0xbb102030bb405060),ovs-p0' stdout])
+
+m4_define([SAMPLE1], [m4_join([ ],
+    [group_id=0xa],
+    [obs_domain=0xaa102030,obs_point=0xaa405060],
+    [.*icmp6.*ipv6_src=fc00::1,ipv6_dst=fc00::2])])
+m4_define([SAMPLE2], [m4_join([ ],
+    [group_id=0xc],
+    [obs_domain=0xbb102030,obs_point=0xbb405060],
+    [.*icmp6.*ipv6_src=fc00::2,ipv6_dst=fc00::1])])
+
+OVS_WAIT_UNTIL([grep -qE 'SAMPLE1' psample.out])
+OVS_WAIT_UNTIL([grep -qE 'SAMPLE2' psample.out])
+
+AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl
+Local sample statistics for bridge "br0":
+Collector Set ID: 1:
+  Group ID     : 10
+  Total packets: 1
+  Total bytes  : 118
+
+Collector Set ID: 2:
+  Group ID     : 12
+  Total packets: 1
+  Total bytes  : 118
+])
+
+AT_CLEANUP
+
+AT_SETUP([psample - slow])
+OVS_TRAFFIC_VSWITCHD_START()
+OVS_CHECK_PSAMPLE()
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
+
+AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
+                    -- create Flow_Sample_Collector_Set id=1 bridge=@br0 local_group_id=10 \
+                    -- create Flow_Sample_Collector_Set id=2 bridge=@br0 local_group_id=12],
+         [0], [ignore])
+
+
+AT_DATA([flows.txt], [dnl
+arp actions=NORMAL
+in_port=ovs-p0,ip actions=SAMPLE_ACTION(1, 2853183536, 2856341600),ovs-p1
+in_port=ovs-p1,ip actions=SAMPLE_ACTION(2, 3138396208, 3141554272),ovs-p0
+])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+AT_CHECK([ovs-appctl ofproto/trace br0 \
+    'in_port=ovs-p0,dl_src=e4:11:22:33:44:55,dl_dst=e4:11:22:33:44:66,dl_type=0x0800,nw_src=10.1.1.1,nw_dst=10.1.1.12'],
+    [0], [stdout])
+
+AT_CHECK([tail -1 stdout], [0], [dnl
+Datapath actions: psample(group=10,cookie=0xaa102030aa405060),3
+])
+
+OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample.pid])
+
+NS_CHECK_EXEC([at_ns0], [ping -q -c 1 10.1.1.2 | FORMAT_PING], [0], [dnl
+1 packets transmitted, 1 received, 0% packet loss, time 0ms
+])
+
+m4_define([SAMPLE1], [m4_join([ ],
+    [group_id=0xa],
+    [obs_domain=0xaa102030,obs_point=0xaa405060],
+    [.*icmp.*nw_src=10.1.1.1,nw_dst=10.1.1.2])])
+
+m4_define([SAMPLE2], [m4_join([ ],
+    [group_id=0xc],
+    [obs_domain=0xbb102030,obs_point=0xbb405060],
+    [.*icmp.*nw_src=10.1.1.2,nw_dst=10.1.1.1])])
+
+AT_CHECK([grep -qE 'SAMPLE1' psample.out])
+AT_CHECK([grep -qE 'SAMPLE2' psample.out])
+
+AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl
+Local sample statistics for bridge "br0":
+Collector Set ID: 1:
+  Group ID     : 10
+  Total packets: 1
+  Total bytes  : 98
+
+Collector Set ID: 2:
+  Group ID     : 12
+  Total packets: 1
+  Total bytes  : 98
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP(["/sending to collector failed/d"])
+AT_CLEANUP
+
+AT_SETUP([psample - with IPFIX])
+OVS_TRAFFIC_VSWITCHD_START()
+OVS_CHECK_PSAMPLE()
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
+
+AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
+                    -- --id=@i create IPFIX targets=\"127.0.0.1:4739\" \
+                    -- create Flow_Sample_Collector_Set id=1 ipfix=@i bridge=@br0 local_group_id=10 \
+                    -- create Flow_Sample_Collector_Set id=2 ipfix=@i bridge=@br0 local_group_id=12],
+         [0], [ignore])
+
+AT_DATA([flows.txt], [dnl
+arp actions=NORMAL
+in_port=ovs-p0,ip actions=SAMPLE_ACTION(1, 2853183536, 2856341600),ovs-p1
+in_port=ovs-p1,ip actions=SAMPLE_ACTION(2, 3138396208, 3141554272),ovs-p0
+])
+
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+
+AT_CHECK([ovs-appctl ofproto/trace br0 \
+    'in_port=ovs-p0,dl_src=e4:11:22:33:44:55,dl_dst=e4:11:22:33:44:66,dl_type=0x0800,nw_src=10.1.1.1,nw_dst=10.1.1.12'],
+    [0], [stdout])
+
+
+m4_define([ACTIONS], [m4_join([],
+    [psample(group=10,cookie=0xaa102030aa405060),],
+    [userspace(pid=4294967295,],
+        [flow_sample(probability=65535,],
+        [collector_set_id=1,],
+        [obs_domain_id=2853183536,],
+        [obs_point_id=2856341600,],
+        [output_port=4294967295)),],
+    [3])])
+
+AT_CHECK([tail -1 stdout], [0], [dnl
+Datapath actions: ACTIONS
+])
+
+OVS_DAEMONIZE([ovstest test-psample > psample.out], [psample.pid])
+OVS_WAIT_UNTIL([grep -q "Listening for psample events" psample.out])
+
+NS_CHECK_EXEC([at_ns0], [ping -q -c 1 10.1.1.2 | FORMAT_PING], [0], [dnl
+1 packets transmitted, 1 received, 0% packet loss, time 0ms
+])
+
+m4_define([SAMPLE1], [m4_join([ ],
+    [group_id=0xa],
+    [obs_domain=0xaa102030,obs_point=0xaa405060],
+    [.*icmp.*nw_src=10.1.1.1,nw_dst=10.1.1.2])])
+
+m4_define([SAMPLE2], [m4_join([ ],
+    [group_id=0xc],
+    [obs_domain=0xbb102030,obs_point=0xbb405060],
+    [.*icmp.*nw_src=10.1.1.2,nw_dst=10.1.1.1])])
+
+OVS_WAIT_UNTIL([grep -qE 'SAMPLE1' psample.out])
+OVS_WAIT_UNTIL([grep -qE 'SAMPLE2' psample.out])
+
+dnl Check IPFIX samples have been received.
+dnl Entries can be unsorted and IFPIX packets might not have been sent (or
+dnl at least tried to be sent) yet.
+OVS_WAIT_UNTIL_EQUAL([ovs-ofctl dump-ipfix-flow br0 | \
+                sed 's/tx pkts=[[0-9]]*/tx pkts=24/' | \
+                sed 's/tx errs=[[0-9]]*/tx errs=0/' | \
+                sed 's/id   [[1-2]]:/id   ?:/'], [dnl
+NXST_IPFIX_FLOW reply (xid=0x2): 2 ids
+  id   ?: flows=1, current flows=0, sampled pkts=1, ipv4 ok=1, ipv6 ok=0, tx pkts=24
+          pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
+  id   ?: flows=1, current flows=0, sampled pkts=1, ipv4 ok=1, ipv6 ok=0, tx pkts=24
+          pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0])
+
+AT_CHECK([ovs-appctl lsample/show br0], [0], [dnl
+Local sample statistics for bridge "br0":
+Collector Set ID: 1:
+  Group ID     : 10
+  Total packets: 1
+  Total bytes  : 98
+
+Collector Set ID: 2:
+  Group ID     : 12
+  Total packets: 1
+  Total bytes  : 98
+])
+
+dnl OVS will fail to send IPFIX packets because the target is localhost
+dnl and the port is closed. Ignore the message it generates.
+OVS_TRAFFIC_VSWITCHD_STOP(["/sending to collector failed/d"])
+AT_CLEANUP