On 12.03.2019 19:18, Ophir Munk wrote:
> 
>>>
>>> Not sure if I understand your point correctly, but isn't it expected
>>> that if flow is offloaded than all the packets through the flow had flow
>> mark?
> 
> Not always. For fully HW offloaded traffic - packets will not be marked.
> It is planned to have another HW offload counter (which is different from the 
> mark counter).

Is it possible for one flow to be fully and partially offloaded at the
same time? Seems strange.
In case of full offloading you don't need a separate counter, you just
need to retrieve stats.n_packets from the HW.

> 
>>> In case of a bug it's most likely that it happened after the flow mark
>>> association and your flow stats will be wrong anyway.
>>> The only trusted source of the number of "offloaded" packets could be
>>> the number of real packets that had flow mark set on receive. And
>>> these stats should be displayed by PMD stats.
>>>
> 
> Not sure about that. It seems there is no one to one relationship between a 
> PMD and a flow.

There is. You may get per-PMD flow stats by 'ovs-appctl dpctl/dump-flows'.
And you may compare them with PMD hit stats.

> In order to correctly debug (how many offloaded packets actually got a mark)

Current patch will not help with issues like this where some packets of one
flow has marks and other packets from the same flow has not.
 
> I think you need a flow resolution statistics.
> 
>>> If everything works as expected, all the packets for offloaded flow
>>> will be marked (except first few of them).
>>> If something will go wrong, we can't trust these flow stats. We can
>>> rely only
>> Why you can't trust the flow stats? This is the only point in the code where
>> you know that the flow was really handled by hardware.
>>
>>> on PMD stats.
>>> So, I don't see the profit from having these special flow stats.
>>>
>> I'm looking at it from the OVS user point of view. I have thousands of flows
>> running.
>> If the statistics is only in the PMD I can see how many packets were marked
>> and how many we're not. Let's say the ratio is not that good, how do I look
>> deeper?
>> Is it because for some flows there is bug on matching? Is it because of the
>> latency in adding flows?
>> Is it because some flow pattern is not supported at all?
>> Agree this is only needed for debugging, but I don't see other way user can
>> get this information.
>>
> 
> Do we agree that knowing how many marked packets per flow were received is 
> something valuable?

Not sure. At least not in current implementation.

> It should be used to confirm correct functionality and improve performance 
> for offloaded traffic.
> If we agree then we should discuss how to implement it. 
> I don't think that PMD level statistics can be used.

See above.

> Any other ideas? 
> Adding a debug flag "-d" to the dpif dump-flow? 
> Creating a new command for dpif-netdev?
> Please advise.
> 
>>>>
>>>> Thanks
>>>>>
>>>>>>  lib/dpif-netdev.c      | 16 ++++++++++++++++
>>>>>>  lib/dpif.c             |  9 +++++++++
>>>>>>  lib/dpif.h             |  3 +++
>>>>>>  ofproto/ofproto-dpif.c |  4 ++++
>>>>>>  4 files changed, 32 insertions(+)
>>>>>>
>>>>>> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index
>>>>>> 4d6d0c3..ef2f8f1 100644
>>>>>> --- a/lib/dpif-netdev.c
>>>>>> +++ b/lib/dpif-netdev.c
>>>>>> @@ -486,6 +486,8 @@ struct dp_netdev_flow_stats {
>>>>>>      atomic_ullong packet_count;    /* Number of packets matched. */
>>>>>>      atomic_ullong byte_count;      /* Number of bytes matched. */
>>>>>>      atomic_uint16_t tcp_flags;     /* Bitwise-OR of seen tcp_flags 
>>>>>> values.
>>> */
>>>>>> +    /* Offload stats. */
>>>>>> +    atomic_ullong mark_count;      /* Number of marked packets
>>> matched.
>>>>> */
>>>>>>  };
>>>>>>
>>>>>>  /* A flow in 'dp_netdev_pmd_thread's 'flow_table'.
>>>>>> @@ -3008,6 +3010,9 @@ get_dpif_flow_stats(const struct
>>>>> dp_netdev_flow *netdev_flow_,
>>>>>>      stats->used = used;
>>>>>>      atomic_read_relaxed(&netdev_flow->stats.tcp_flags, &flags);
>>>>>>      stats->tcp_flags = flags;
>>>>>> +    /* Offload stats. */
>>>>>> +    atomic_read_relaxed(&netdev_flow->stats.mark_count, &n);
>>>>>> +    stats->n_marked = n;
>>>>>>  }
>>>>>>
>>>>>>  /* Converts to the dpif_flow format, using 'key_buf' and
>>>>>> 'mask_buf' for @@ -6124,6 +6129,15 @@
>> dp_netdev_flow_used(struct
>>> dp_netdev_flow
>>>>> *netdev_flow, int cnt, int size,
>>>>>>      atomic_store_relaxed(&netdev_flow->stats.tcp_flags, flags);
>>>>>> }
>>>>>>
>>>>>> +static void
>>>>>> +dp_netdev_flow_marked(struct dp_netdev_flow *netdev_flow,
>>>>> uint32_t mark,
>>>>>> +                    int count)
>>>>>> +{
>>>>>> +    if (mark != INVALID_FLOW_MARK) {
>>>>>> +        non_atomic_ullong_add(&netdev_flow->stats.mark_count,
>>> count);
>>>>>> +    }
>>>>>> +}
>>>>>> +
>>>>>>  static int
>>>>>>  dp_netdev_upcall(struct dp_netdev_pmd_thread *pmd, struct
>>> dp_packet
>>>>> *packet_,
>>>>>>                   struct flow *flow, struct flow_wildcards *wc,
>>>>>> ovs_u128 *ufid, @@ -6244,6 +6258,8 @@
>>>>>> packet_batch_per_flow_execute(struct
>>>>> packet_batch_per_flow *batch,
>>>>>>      dp_netdev_flow_used(flow, batch->array.count, batch-
>>> byte_count,
>>>>>>                          batch->tcp_flags, pmd->ctx.now / 1000);
>>>>>>
>>>>>> +    dp_netdev_flow_marked(flow, batch->flow->mark, batch-
>>>>>> array.count);
>>>>>> +
>>>>>>      actions = dp_netdev_flow_get_actions(flow);
>>>>>>
>>>>>>      dp_netdev_execute_actions(pmd, &batch->array, true,
>>>>>> &flow->flow, diff --git a/lib/dpif.c b/lib/dpif.c index
>>>>>> 457c9bf..bb077a5 100644
>>>>>> --- a/lib/dpif.c
>>>>>> +++ b/lib/dpif.c
>>>>>> @@ -880,9 +880,18 @@ dpif_flow_stats_extract(const struct flow
>>>>>> *flow,
>>>>> const struct dp_packet *packet,
>>>>>>      stats->tcp_flags = ntohs(flow->tcp_flags);
>>>>>>      stats->n_bytes = dp_packet_size(packet);
>>>>>>      stats->n_packets = 1;
>>>>>> +    stats->n_marked = 0;
>>>>>>      stats->used = used;
>>>>>>  }
>>>>>>
>>>>>> +void
>>>>>> +dpif_offload_stats_format(const struct dpif_flow_stats *stats,
>>>>>> +struct
>>> ds
>>>>> *s)
>>>>>> +{
>>>>>> +    if (stats->n_marked) {
>>>>>> +        ds_put_format(s, "marked:%"PRIu64", ", stats->n_marked);
>>>>>> +    }
>>>>>> +}
>>>>>> +
>>>>>>  /* Appends a human-readable representation of 'stats' to 's'. */
>>>>>> void  dpif_flow_stats_format(const struct dpif_flow_stats *stats,
>>>>>> struct ds
>>> *s)
>>>>>> diff --git a/lib/dpif.h b/lib/dpif.h index 475d5a6..7c22afd 100644
>>>>>> --- a/lib/dpif.h
>>>>>> +++ b/lib/dpif.h
>>>>>> @@ -492,6 +492,8 @@ struct dpif_flow_stats {
>>>>>>      uint64_t n_bytes;
>>>>>>      long long int used;
>>>>>>      uint16_t tcp_flags;
>>>>>> +    /* Offload stats. */
>>>>>> +    uint64_t n_marked;
>>>>>>  };
>>>>>>
>>>>>>  struct dpif_flow_attrs {
>>>>>> @@ -507,6 +509,7 @@ struct dpif_flow_dump_types {  void
>>>>>> dpif_flow_stats_extract(const struct flow *, const struct
>>>>>> dp_packet
>>>>> *packet,
>>>>>>                               long long int used, struct
>>>>>> dpif_flow_stats *);  void dpif_flow_stats_format(const struct
>>>>>> dpif_flow_stats *, struct ds *);
>>>>>> +void dpif_offload_stats_format(const struct dpif_flow_stats *,
>>>>>> +struct
>>> ds
>>>>> *);
>>>>>>
>>>>>>  enum dpif_flow_put_flags {
>>>>>>      DPIF_FP_CREATE = 1 << 0,    /* Allow creating a new flow. */
>>>>>> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index
>>>>>> 21dd54b..af37ecb 100644
>>>>>> --- a/ofproto/ofproto-dpif.c
>>>>>> +++ b/ofproto/ofproto-dpif.c
>>>>>> @@ -4416,6 +4416,7 @@ rule_construct(struct rule *rule_)
>>>>>>      rule->stats.n_packets = 0;
>>>>>>      rule->stats.n_bytes = 0;
>>>>>>      rule->stats.used = rule->up.modified;
>>>>>> +    rule->stats.n_marked = 0;
>>>>>>      rule->recirc_id = 0;
>>>>>>      rule->new_rule = NULL;
>>>>>>      rule->forward_counts = false; @@ -5709,6 +5710,9 @@
>>>>>> ofproto_unixctl_dpif_dump_flows(struct
>>>>> unixctl_conn *conn,
>>>>>>          odp_flow_format(f.key, f.key_len, f.mask, f.mask_len,
>>>>>>                          portno_names, &ds, verbosity);
>>>>>>          ds_put_cstr(&ds, ", ");
>>>>>> +        if (verbosity) {
>>>>>> +            dpif_offload_stats_format(&f.stats, &ds);
>>>>>> +        }
>>>>>>          dpif_flow_stats_format(&f.stats, &ds);
>>>>>>          ds_put_cstr(&ds, ", actions:");
>>>>>>          format_odp_actions(&ds, f.actions, f.actions_len,
>>>>>> portno_names);
>>>>>>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to