On Tue, Jul 09, 2024 at 04:22:04PM GMT, Eelco Chaudron wrote:
>
>
> On 9 Jul 2024, at 16:00, Adrián Moreno wrote:
>
> > On Tue, Jul 09, 2024 at 11:46:06AM GMT, Eelco Chaudron wrote:
> >> On 7 Jul 2024, at 22:09, Adrian Moreno wrote:
> >>
> >>> When an action set ends in a an OFP_SAMPLE action, it means the packet
> >>> will be dropped and sampled. Make the drop explicit in this case so that
> >>> drop statistics remain accurate.
> >>>
> >>> This could be done outside of the sample action, i.e: "sample(...),drop"
> >>> but datapaths optimize sample actions that are found in the last
> >>> position. So, taking into account that datapaths already report when the
> >>> last sample probability fails, it is safe to put the drop inside the
> >>> sample, i.e: "sample(...,drop)".
> >>
> >> Some style comments below, as this was discussed with Ilya, I let him 
> >> comment
> >> on the feature side.
> >>
> >>> Signed-off-by: Adrian Moreno <amore...@redhat.com>
> >>> ---
> >>>  ofproto/ofproto-dpif-xlate.c | 16 +++++++--
> >>>  tests/drop-stats.at          | 65 ++++++++++++++++++++++++++++++++++++
> >>>  tests/ofproto-dpif.at        | 44 ++++++++++++++++++++++++
> >>>  3 files changed, 123 insertions(+), 2 deletions(-)
> >>>
> >>> diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
> >>> index b9546dc5b..094fe5d72 100644
> >>> --- a/ofproto/ofproto-dpif-xlate.c
> >>> +++ b/ofproto/ofproto-dpif-xlate.c
> >>> @@ -715,6 +715,7 @@ static void xlate_xbundle_copy(struct xbridge *, 
> >>> struct xbundle *);
> >>>  static void xlate_xport_copy(struct xbridge *, struct xbundle *,
> >>>                               struct xport *);
> >>>  static void xlate_xcfg_free(struct xlate_cfg *);
> >>> +static void put_drop_action(struct ofpbuf *, enum xlate_error);
> >>>  
> >>>  /* Tracing helpers. */
> >>>
> >>> @@ -3392,6 +3393,8 @@ struct sample_userspace_args {
> >>>  struct compose_sample_args {
> >>>      uint32_t probability;                     /* Number of packets out of
> >>>                                                 * UINT32_MAX to sample. */
> >>> +    bool last;                                /* If it's the last action 
> >>> and a
> >>> +                                               * drop action must be 
> >>> added. */
> >>
> >> Should describing this means this is the last action not be enough?
> >> Maybe also rename it to be last_action, so it's more clear what this means.
> >>
> >
> > Sure "last_action" is pretty much self-explanatory.
> >
> >>>      struct sample_userspace_args *userspace;  /* Optional,
> >>>                                                 * arguments for 
> >>> userspace. */
> >>>      struct sample_psample_args *psample;      /* Optional,
> >>> @@ -3456,6 +3459,11 @@ compose_sample_action(struct xlate_ctx *ctx,
> >>>          ovs_assert(res == 0);
> >>>      }
> >>>
> >>> +    if (args->last &&
> >>> +        ovs_explicit_drop_action_supported(ctx->xbridge->ofproto)) {
> >>> +        put_drop_action(ctx->odp_actions, ctx->error);
> >>
> >> Any reason why we use ctx->error here? Should we just not use XLATE_OK?
> >>
> >
> > I was trying to thing in a case where ctx->error would not be XLATE_OK
> > but I couldn't. Nevertheless I thought if there is such case, we should
> > definitely report the right error code, right?
>
> Well, in case of an error all actions are deleted, and only an explicit drop 
> (or no) actions are added.
>
> For the sample() action, the drop reason should always be ok, or else the 
> action should not be there. So I would prefer to make this clear by using 
> XLATE_OK.

OK. I'll change that.

>
> >>> +    }
> >>> +
> >>>      if (is_sample) {
> >>>          nl_msg_end_nested(ctx->odp_actions, actions_offset);
> >>>          nl_msg_end_nested(ctx->odp_actions, sample_offset);
> >>> @@ -3490,6 +3498,7 @@ compose_sflow_action(struct xlate_ctx *ctx)
> >>>
> >>>      args.probability = dpif_sflow_get_probability(sflow);
> >>>      args.userspace = &userspace;
> >>> +    args.last = false;
> >>>
> >>>      return compose_sample_action(ctx, &args);
> >>>  }
> >>> @@ -3542,6 +3551,7 @@ compose_ipfix_action(struct xlate_ctx *ctx, 
> >>> odp_port_t output_odp_port)
> >>>
> >>>      args.probability = dpif_ipfix_get_bridge_exporter_probability(ipfix);
> >>>      args.userspace = &userspace;
> >>> +    args.last = false;
> >>>
> >>>      compose_sample_action(ctx, &args);
> >>>  }
> >>> @@ -5974,7 +5984,8 @@ xlate_fill_ipfix_sample(struct xlate_ctx *ctx,
> >>>
> >>>  static void
> >>>  xlate_sample_action(struct xlate_ctx *ctx,
> >>> -                    const struct ofpact_sample *os)
> >>> +                    const struct ofpact_sample *os,
> >>> +                    bool last)
> >>>  {
> >>>      uint8_t cookie_buf[sizeof(os->obs_domain_id) + 
> >>> sizeof(os->obs_point_id)];
> >>>      struct dpif_lsample *lsample = ctx->xbridge->lsample;
> >>> @@ -5991,6 +6002,7 @@ xlate_sample_action(struct xlate_ctx *ctx,
> >>>       * the same percentage. */
> >>>      compose_args.probability =
> >>>          ((uint32_t) os->probability << 16) | os->probability;
> >>> +    compose_args.last = last;
> >>>
> >>>      if (ipfix) {
> >>>          xlate_fill_ipfix_sample(ctx, os, ipfix, &userspace);
> >>> @@ -7726,7 +7738,7 @@ do_xlate_actions(const struct ofpact *ofpacts, 
> >>> size_t ofpacts_len,
> >>>              break;
> >>>
> >>>          case OFPACT_SAMPLE:
> >>> -            xlate_sample_action(ctx, ofpact_get_SAMPLE(a));
> >>> +            xlate_sample_action(ctx, ofpact_get_SAMPLE(a), last);
> >>>              break;
> >>>
> >>>          case OFPACT_CLONE:
> >>> diff --git a/tests/drop-stats.at b/tests/drop-stats.at
> >>> index 1d3af98da..44c5cc35b 100644
> >>> --- a/tests/drop-stats.at
> >>> +++ b/tests/drop-stats.at
> >>> @@ -191,3 +191,68 @@ ovs-appctl coverage/read-counter 
> >>> drop_action_too_many_mpls_labels
> >>>
> >>>  OVS_VSWITCHD_STOP(["/|WARN|/d"])
> >>>  AT_CLEANUP
> >>> +
> >>> +AT_SETUP([drop-stats - sampling action])
> >>> +
> >>> +OVS_VSWITCHD_START([dnl
> >>> +    set bridge br0 datapath_type=dummy \
> >>> +        protocols=OpenFlow10,OpenFlow13,OpenFlow14,OpenFlow15 -- \
> >>> +    add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 -- \
> >>> +    add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2])
> >>> +
> >>> +AT_DATA([flows.txt], [dnl
> >>> +table=0,in_port=1,actions=sample(probability=65535,collector_set_id=1)
> >>> +table=0,in_port=2,actions=sample(probability=32767,collector_set_id=1)
> >>> +])
> >>> +
> >>> +AT_CHECK([
> >>> +    ovs-ofctl del-flows br0
> >>> +    ovs-ofctl -Oopenflow13 add-flows br0 flows.txt
> >>> +])
> >>> +
> >>> +AT_CHECK([ovs-vsctl --id=@br0 get Bridge br0 \
> >>> +                    -- --id=@ipfix create IPFIX 
> >>> targets=\"127.0.0.1:4739\" \
> >>> +                    -- create Flow_Sample_Collector_Set id=1 bridge=@br0 
> >>> ipfix=@ipfix],
> >>> +         [0], [ignore])
> >>
> >> Maybe we can try this and other places to be more <80 friendly?
> >>
> >
> > Ack.
> >
> >>> +
> >>> +AT_CHECK([
> >>> +    ovs-appctl netdev-dummy/receive p1 
> >>> 'in_port(1),packet_type(ns=0,id=0),eth(src=3a:6d:d2:09:9c:ab,dst=1e:2c:e9:2a:66:9e),ipv4(src=192.168.10.10,dst=192.168.10.30,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
> >>> +    ovs-appctl netdev-dummy/receive p1 
> >>> 'in_port(1),packet_type(ns=0,id=0),eth(src=3a:6d:d2:09:9c:ab,dst=1e:2c:e9:2a:66:9e),ipv4(src=192.168.10.10,dst=192.168.10.30,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
> >>> +    ovs-appctl netdev-dummy/receive p1 
> >>> 'in_port(1),packet_type(ns=0,id=0),eth(src=3a:6d:d2:09:9c:ab,dst=1e:2c:e9:2a:66:9e),ipv4(src=192.168.10.10,dst=192.168.10.30,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
> >>> +], [0], [ignore])
> >>
> >> Maybe a for loop?
> >>
> >
> > Ack.
> >
> >>> +
> >>> +AT_CHECK([ovs-appctl dpctl/dump-flows | sed 
> >>> 's/used:[[0-9]].[[0-9]]*s/used:0.0/' | sort], [0], [flow-dump from the 
> >>> main thread:
> >>> +recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no),
> >>>  packets:2, bytes:212, used:0.0, 
> >>> actions:userspace(pid=0,flow_sample(probability=65535,collector_set_id=1,obs_domain_id=0,obs_point_id=0,output_port=4294967295)),drop
> >>> +])
> >>> +
> >>> +ovs-appctl time/warp 5000
> >>> +
> >>> +AT_CHECK([
> >>> +ovs-appctl coverage/read-counter drop_action_of_pipeline
> >>> +], [0], [dnl
> >>> +3
> >>> +])
> >>> +
> >>> +AT_CHECK([ovs-appctl dpctl/del-flows])
> >>> +
> >>> +AT_CHECK([
> >>> +    ovs-appctl netdev-dummy/receive p2 
> >>> 'in_port(2),packet_type(ns=0,id=0),eth(src=3a:6d:d2:09:9c:ab,dst=1e:2c:e9:2a:66:9e),ipv4(src=192.168.10.10,dst=192.168.10.30,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
> >>> +    ovs-appctl netdev-dummy/receive p2 
> >>> 'in_port(2),packet_type(ns=0,id=0),eth(src=3a:6d:d2:09:9c:ab,dst=1e:2c:e9:2a:66:9e),ipv4(src=192.168.10.10,dst=192.168.10.30,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
> >>> +    ovs-appctl netdev-dummy/receive p2 
> >>> 'in_port(2),packet_type(ns=0,id=0),eth(src=3a:6d:d2:09:9c:ab,dst=1e:2c:e9:2a:66:9e),ipv4(src=192.168.10.10,dst=192.168.10.30,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
> >>> +], [0], [ignore])
> >>> +
> >>> +AT_CHECK([ovs-appctl dpctl/dump-flows | sed 
> >>> 's/used:[[0-9]].[[0-9]]*s/used:0.0/' | sort], [0], [flow-dump from the 
> >>> main thread:
> >>> +recirc_id(0),in_port(2),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no),
> >>>  packets:2, bytes:212, used:0.0, 
> >>> actions:sample(sample=50.0%,actions(userspace(pid=0,flow_sample(probability=32767,collector_set_id=1,obs_domain_id=0,obs_point_id=0,output_port=4294967295)),drop))
> >>> +])
> >>> +
> >>> +ovs-appctl time/warp 5000
> >>> +
> >>> +AT_CHECK([ovs-appctl coverage/read-counter drop_action_of_pipeline > 
> >>> explicit_drops])
> >>> +AT_CHECK([ovs-appctl coverage/read-counter datapath_drop_sample_error > 
> >>> sample_drops])
> >>> +
> >>> +AT_CHECK([expr $(cat sample_drops) + $(cat explicit_drops)], [0], [dnl
> >>> +6
> >>> +])
> >>> +
> >>> +OVS_VSWITCHD_STOP(["/sending to collector failed/d"])
> >>> +AT_CLEANUP
> >>> diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
> >>> index 2a04977a7..701b8a851 100644
> >>> --- a/tests/ofproto-dpif.at
> >>> +++ b/tests/ofproto-dpif.at
> >>> @@ -12282,3 +12282,47 @@ Datapath actions: EXPECTED_ACT
> >>>
> >>>  OVS_VSWITCHD_STOP()
> >>>  AT_CLEANUP
> >>> +
> >>> +AT_SETUP([ofproto-dpif - Local sampling - drop])
> >>> +OVS_VSWITCHD_START
> >>> +add_of_ports br0 1 2
> >>> +
> >>> +AT_CHECK([ovs-appctl dpif/set-dp-features --force br0 psample true], 
> >>> [0], [ignore])
> >>> +
> >>> +AT_CHECK([ovs-vsctl -- --id=@br0 get Bridge br0 \
> >>> +                    -- create Flow_Sample_Collector_Set id=1 bridge=@br0 
> >>> local_group_id=42],
> >>> +         [0], [ignore])
> >>> +
> >>> +AT_CHECK([ovs-ofctl -O OpenFlow13 add-meter br0 'meter=slowpath pktps 
> >>> stats bands=type=drop rate=2'])
> >>> +
> >>> +AT_DATA([flows.txt], [dnl
> >>> +in_port=1, 
> >>> actions=sample(probability=32767,collector_set_id=1,obs_domain_id=100,obs_point_id=200)
> >>> +in_port=2, 
> >>> actions=sample(probability=65535,collector_set_id=1,obs_domain_id=100,obs_point_id=200)
> >>> +])
> >>> +
> >>> +AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flows br0 flows.txt])
> >>> +
> >>> +m4_define([TRACE_PKT], [m4_join([,],
> >>> +    [eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)],
> >>> +    [ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no)],
> >>> +    [icmp(type=8,code=0)])])
> >>> +
> >>> +m4_define([EXPECTED_ACT1], [m4_join([],
> >>> +    [sample(sample=50.0%,actions(],
> >>> +    [psample(group=42,cookie=0x64000000c8),],
> >>> +    [drop],
> >>> +    [))],
> >>> +)])
> >>> +
> >>> +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1) TRACE_PKT'], 
> >>> [0], [stdout])
> >>> +AT_CHECK([tail -1 stdout], [0], [dnl
> >>> +Datapath actions: EXPECTED_ACT1
> >>> +])
> >>> +
> >>> +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2) TRACE_PKT'], 
> >>> [0], [stdout])
> >>> +AT_CHECK([tail -1 stdout], [0], [dnl
> >>> +Datapath actions: psample(group=42,cookie=0x64000000c8),drop
> >>> +])
> >>> +
> >>> +OVS_VSWITCHD_STOP()
> >>> +AT_CLEANUP
> >>> --
> >>> 2.45.2
> >>
>

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

Reply via email to