[ovs-dev] [PATCH v12] Improved Packet Drop Statistics in OVS

Eelco Chaudron echaudro at redhat.com
Thu Sep 5 07:37:20 UTC 2019


Thanks, I’ve CC’ed Ben so he can look at the comments regarding his 
earlier comment :)

Looking forward for the next version…

//Eelco


On 4 Sep 2019, at 11:24, Anju Thomas wrote:

> Hi Eelco,
> Since I have not received any more comments, let me respond to your 
> comments:
>
>
>
> -----Original Message-----
> From: Eelco Chaudron <echaudro at redhat.com>
> Sent: Tuesday, September 3, 2019 7:27 PM
> To: Anju Thomas <anju.thomas at ericsson.com>
> Cc: dev at openvswitch.org; Keshav Gupta <keshugupta1 at gmail.com>
> Subject: Re: [ovs-dev] [PATCH v12] Improved Packet Drop Statistics in 
> OVS
>
>
>
> On 20 Aug 2019, at 11:57, Anju Thomas wrote:
>
>> Thanks for the comments Eelco. I will address them in the next patch.
>>
>> On a similar note, are these the final set of comments for this patch
>> ?
>
> Did you get any update, and are you planning on sending out an update?
>
> Thanks,
>
> Eelco
>
>> Regards
>> Anju
>>
>> -----Original Message-----
>> From: Eelco Chaudron <echaudro at redhat.com>
>> Sent: Monday, August 12, 2019 5:48 PM
>> To: Anju Thomas <anju.thomas at ericsson.com>
>> Cc: dev at openvswitch.org; Keshav Gupta <keshugupta1 at gmail.com>
>> Subject: Re: [ovs-dev] [PATCH v12] Improved Packet Drop Statistics in
>> OVS
>>
>> Hi Anju,
>>
>> See comments inline…
>>
>> //Eelco
>>
>>
>> On 25 Jul 2019, at 14:16, Anju Thomas wrote:
>>
>>> Currently OVS maintains explicit packet drop/error counters only on
>>> port level. Packets that are dropped as part of normal OpenFlow
>>> processing are counted in flow stats of “drop” flows or as table
>>> misses in table stats. These can only be interpreted by controllers
>>> that know the semantics of the configured OpenFlow pipeline.
>>> Without that knowledge, it is impossible for an OVS user to obtain
>>> e.g. the total number of packets dropped due to OpenFlow rules.
>>>
>>> Furthermore, there are numerous other reasons for which packets can
>>> be dropped by OVS slow path that are not related to the OpenFlow
>>> pipeline.
>>> The generated datapath flow entries include a drop action to avoid
>>> further expensive upcalls to the slow path, but subsequent packets
>>> dropped by the datapath are not accounted anywhere.
>>>
>>> Finally, the datapath itself drops packets in certain error
>>> situations.
>>> Also, these drops are today not accounted for.This makes it 
>>> difficult
>>> for OVS users to monitor packet drop in an OVS instance and to alert
>>> a management system in case of a unexpected increase of such drops.
>>> Also OVS trouble-shooters face difficulties in analysing packet
>>> drops.
>>>
>>> With this patch we implement following changes to address the issues
>>> mentioned above.
>>>
>>> 1. Identify and account all the silent packet drop scenarios
>>>
>>> 2. Display these drops in ovs-appctl coverage/show
>>>
>>> v11->v12 Addresses comments from Ben Pfaff
>>>
>>> Co-authored-by: Rohith Basavaraja <rohith.basavaraja at gmail.com>
>>> Co-authored-by: Keshav Gupta <keshugupta1 at gmail.com>
>>> Signed-off-by: Anju Thomas <anju.thomas at ericsson.com>
>>> Signed-off-by: Rohith Basavaraja <rohith.basavaraja at gmail.com>
>>> Signed-off-by: Keshav Gupta <keshugupta1 at gmail.com>
>>> ---
>>>  datapath/linux/compat/include/linux/openvswitch.h |   1 +
>>>  lib/dpif-netdev.c                                 |  46 ++++-
>>>  lib/dpif.c                                        |   7 +
>>>  lib/dpif.h                                        |   4 +
>>>  lib/odp-execute.c                                 |  79 ++++++++
>>>  lib/odp-util.c                                    |   9 +
>>>  ofproto/ofproto-dpif-ipfix.c                      |   1 +
>>>  ofproto/ofproto-dpif-sflow.c                      |   1 +
>>>  ofproto/ofproto-dpif-xlate.c                      |  40 ++++-
>>>  ofproto/ofproto-dpif-xlate.h                      |   3 +
>>>  ofproto/ofproto-dpif.c                            |   8 +
>>>  ofproto/ofproto-dpif.h                            |   8 +-
>>>  tests/automake.mk                                 |   3 +-
>>>  tests/dpif-netdev.at                              |   8 +
>>>  tests/drop-stats.at                               | 210
>>> ++++++++++++++++++++++
>>>  tests/ofproto-dpif.at                             |   2 +-
>>>  tests/tunnel-push-pop.at                          |  29 ++-
>>>  tests/tunnel.at                                   |  16 +-
>>>  18 files changed, 464 insertions(+), 11 deletions(-)  create mode
>>> 100644 tests/drop-stats.at
>>>
>>> diff --git a/datapath/linux/compat/include/linux/openvswitch.h
>>> b/datapath/linux/compat/include/linux/openvswitch.h
>>> index 65a003a..415c053 100644
>>> --- a/datapath/linux/compat/include/linux/openvswitch.h
>>> +++ b/datapath/linux/compat/include/linux/openvswitch.h
>>> @@ -989,6 +989,7 @@ enum ovs_action_attr {  #ifndef __KERNEL__
>>>  	OVS_ACTION_ATTR_TUNNEL_PUSH,   /* struct ovs_action_push_tnl*/
>>>  	OVS_ACTION_ATTR_TUNNEL_POP,    /* u32 port number. */
>>> +	OVS_ACTION_ATTR_DROP,
>>>  #endif
>>>  	__OVS_ACTION_ATTR_MAX,	      /* Nothing past this will be accepted
>>>  				       * from userspace. */
>>> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index
>>> 6b99a3c..3878b8d 100644
>>> --- a/lib/dpif-netdev.c
>>> +++ b/lib/dpif-netdev.c
>>> @@ -101,6 +101,17 @@ enum { MAX_METERS = 65536 };    /* Maximum
>>> number
>>> of meters. */
>>>  enum { MAX_BANDS = 8 };         /* Maximum number of bands / meter.
>>> */
>>>  enum { N_METER_LOCKS = 64 };    /* Maximum number of meters. */
>>>
>>> +COVERAGE_DEFINE(datapath_drop_meter);
>>> +COVERAGE_DEFINE(datapath_drop_upcall_error);
>>> +COVERAGE_DEFINE(datapath_drop_lock_error);
>>> +COVERAGE_DEFINE(datapath_drop_userspace_action_error);
>>> +COVERAGE_DEFINE(datapath_drop_tunnel_push_error);
>>> +COVERAGE_DEFINE(datapath_drop_tunnel_pop_error);
>>> +COVERAGE_DEFINE(datapath_drop_recirc_error);
>>> +COVERAGE_DEFINE(datapath_drop_invalid_port);
>>> +COVERAGE_DEFINE(datapath_drop_invalid_tnl_port);
>>> +COVERAGE_DEFINE(datapath_drop_rx_invalid_packet);
>>> +
>>>  /* Protects against changes to 'dp_netdevs'. */  static struct
>>> ovs_mutex dp_netdev_mutex = OVS_MUTEX_INITIALIZER;
>>>
>>> @@ -5762,7 +5773,7 @@ dp_netdev_run_meter(struct dp_netdev *dp,
>>> struct dp_packet_batch *packets_,
>>>              band = &meter->bands[exceeded_band[j]];
>>>              band->packet_count += 1;
>>>              band->byte_count += dp_packet_size(packet);
>>> -
>>> +            COVERAGE_INC(datapath_drop_meter);
>>>              dp_packet_delete(packet);
>>>          } else {
>>>              /* Meter accepts packet. */ @@ -6512,6 +6523,7 @@
>>> dfc_processing(struct dp_netdev_pmd_thread *pmd,
>>>
>>>          if (OVS_UNLIKELY(dp_packet_size(packet) < ETH_HEADER_LEN)) 
>>> {
>>>              dp_packet_delete(packet);
>>> +            COVERAGE_INC(datapath_drop_rx_invalid_packet);
>>>              continue;
>>>          }
>>>
>>> @@ -6631,6 +6643,7 @@ handle_packet_upcall(struct
>>> dp_netdev_pmd_thread *pmd,
>>>                               put_actions);
>>>      if (OVS_UNLIKELY(error && error != ENOSPC)) {
>>>          dp_packet_delete(packet);
>>> +        COVERAGE_INC(datapath_drop_upcall_error);
>>>          return error;
>>>      }
>>>
>>> @@ -6761,6 +6774,7 @@ fast_path_processing(struct
>>> dp_netdev_pmd_thread *pmd,
>>>          DP_PACKET_BATCH_FOR_EACH (i, packet, packets_) {
>>>              if (OVS_UNLIKELY(!rules[i])) {
>>>                  dp_packet_delete(packet);
>>> +                COVERAGE_INC(datapath_drop_lock_error);
>>>                  upcall_fail_cnt++;
>>>              }
>>>          }
>>> @@ -7030,6 +7044,7 @@ dp_execute_userspace_action(struct
>>> dp_netdev_pmd_thread *pmd,
>>>                                    actions->data, actions->size);
>>>      } else if (should_steal) {
>>>          dp_packet_delete(packet);
>>> +        COVERAGE_INC(datapath_drop_userspace_action_error);
>>>      }
>>>  }
>>>
>>> @@ -7044,6 +7059,7 @@ dp_execute_cb(void *aux_, struct
>>> dp_packet_batch *packets_,
>>>      struct dp_netdev *dp = pmd->dp;
>>>      int type = nl_attr_type(a);
>>>      struct tx_port *p;
>>> +    uint32_t packet_count, packet_dropped;
>>
>> nit, but maybe packetS_dropped make more sense…
>
> Will change to packets_dropped
>>
>>>
>>>      switch ((enum ovs_action_attr)type) {
>>>      case OVS_ACTION_ATTR_OUTPUT:
>>> @@ -7085,6 +7101,9 @@ dp_execute_cb(void *aux_, struct
>>> dp_packet_batch *packets_,
>>>                  dp_packet_batch_add(&p->output_pkts, packet);
>>>              }
>>>              return;
>>> +        } else {
>>> +            COVERAGE_ADD(datapath_drop_invalid_port,
>>> +                         dp_packet_batch_size(packets_));
>>>          }
>>>          break;
>>>
>>> @@ -7094,10 +7113,16 @@ dp_execute_cb(void *aux_, struct
>>> dp_packet_batch *packets_,
>>>               * the ownership of these packets. Thus, we can avoid
>>> performing
>>>               * the action, because the caller will not use the
>>> result anyway.
>>>               * Just break to free the batch. */
>>> +            COVERAGE_ADD(datapath_drop_tunnel_push_error,
>>> +                         dp_packet_batch_size(packets_));
>>>              break;
>>>          }
>>>          dp_packet_batch_apply_cutlen(packets_);
>>> -        push_tnl_action(pmd, a, packets_);
>>> +        packet_count = dp_packet_batch_size(packets_);
>>> +        if (push_tnl_action(pmd, a, packets_)) {
>>> +            COVERAGE_ADD(datapath_drop_tunnel_push_error,
>>> +                         packet_count);
>>> +        }
>>>          return;
>>>
>>>      case OVS_ACTION_ATTR_TUNNEL_POP:
>>> @@ -7117,7 +7142,13 @@ dp_execute_cb(void *aux_, struct
>>> dp_packet_batch *packets_,
>>>
>>>                  dp_packet_batch_apply_cutlen(packets_);
>>>
>>> +                packet_count = dp_packet_batch_size(packets_);
>>>                  netdev_pop_header(p->port->netdev, packets_);
>>> +                packet_dropped = packet_count - packets_->count;
>>
>> Here you need to use the dp_packet_batch_size(packets_) macro also, 
>> so
>>
>> packetsCOVERAGE_INC_dropped = packet_count -
>> dp_packet_batch_size(packets_);
>
> Will use dp_packet_batch_size here as well
>>
>>> +                if (packet_dropped) {
>>> +                    COVERAGE_ADD(datapath_drop_tunnel_pop_error,
>>> +                                 packet_dropped);
>>> +                }
>>>                  if (dp_packet_batch_is_empty(packets_)) {
>>>                      return;
>>>                  }
>>> @@ -7132,6 +7163,11 @@ dp_execute_cb(void *aux_, struct
>>> dp_packet_batch *packets_,
>>>                  (*depth)--;
>>>                  return;
>>>              }
>>> +            COVERAGE_ADD(datapath_drop_invalid_tnl_port,
>>> +                         dp_packet_batch_size(packets_));
>>> +        } else {
>>> +            COVERAGE_ADD(datapath_drop_recirc_error,
>>> +                         dp_packet_batch_size(packets_));
>>>          }
>>>          break;
>>>
>>> @@ -7176,6 +7212,9 @@ dp_execute_cb(void *aux_, struct
>>> dp_packet_batch *packets_,
>>>
>>>              return;
>>>          }
>>> +        COVERAGE_ADD(datapath_drop_lock_error,
>>> +                     dp_packet_batch_size(packets_));
>>> +
>>>          break;
>>>
>>>      case OVS_ACTION_ATTR_RECIRC:
>>> @@ -7199,6 +7238,8 @@ dp_execute_cb(void *aux_, struct
>>> dp_packet_batch *packets_,
>>>              return;
>>>          }
>>>
>>> +        COVERAGE_ADD(datapath_drop_recirc_error,
>>> +                     dp_packet_batch_size(packets_));
>>>          VLOG_WARN("Packet dropped. Max recirculation depth
>>> exceeded.");
>>>          break;
>>>
>>> @@ -7352,6 +7393,7 @@ dp_execute_cb(void *aux_, struct
>>> dp_packet_batch *packets_,
>>>      case OVS_ACTION_ATTR_POP_NSH:
>>>      case OVS_ACTION_ATTR_CT_CLEAR:
>>>      case OVS_ACTION_ATTR_CHECK_PKT_LEN:
>>> +    case OVS_ACTION_ATTR_DROP:
>>>      case __OVS_ACTION_ATTR_MAX:
>>>          OVS_NOT_REACHED();
>>>      }
>>> diff --git a/lib/dpif.c b/lib/dpif.c
>>> index c88b210..5a9ff46 100644
>>> --- a/lib/dpif.c
>>> +++ b/lib/dpif.c
>>> @@ -1274,6 +1274,7 @@ dpif_execute_helper_cb(void *aux_, struct
>>> dp_packet_batch *packets_,
>>>      case OVS_ACTION_ATTR_CT_CLEAR:
>>>      case OVS_ACTION_ATTR_UNSPEC:
>>>      case OVS_ACTION_ATTR_CHECK_PKT_LEN:
>>> +    case OVS_ACTION_ATTR_DROP:
>>>      case __OVS_ACTION_ATTR_MAX:
>>>          OVS_NOT_REACHED();
>>>      }
>>> @@ -1879,6 +1880,12 @@ dpif_supports_tnl_push_pop(const struct dpif
>>> *dpif)
>>>      return dpif_is_netdev(dpif);
>>>  }
>>>
>>> +bool
>>> +dpif_supports_explicit_drop_action(const struct dpif *dpif) {
>>> +    return dpif_is_netdev(dpif);
>>> +}
>>> +
>>>  /* Meters */
>>>  void
>>>  dpif_meter_get_features(const struct dpif *dpif, diff --git
>>> a/lib/dpif.h b/lib/dpif.h index 289d574..3ac5a5a 100644
>>> --- a/lib/dpif.h
>>> +++ b/lib/dpif.h
>>> @@ -890,6 +890,10 @@ int dpif_get_pmds_for_port(const struct dpif *
>>> dpif, odp_port_t port_no,
>>>
>>>  char *dpif_get_dp_version(const struct dpif *);  bool
>>> dpif_supports_tnl_push_pop(const struct dpif *);
>>> +bool dpif_supports_explicit_drop_action(const struct dpif *); int
>>> +dpif_show_drop_stats_support(struct dpif *dpif, bool detail,
>>> +                                 struct ds *reply);
>>> +
>>>
>>>  /* Log functions. */
>>>  struct vlog_module;
>>> diff --git a/lib/odp-execute.c b/lib/odp-execute.c index
>>> 563ad1d..a4837a6 100644
>>> --- a/lib/odp-execute.c
>>> +++ b/lib/odp-execute.c
>>> @@ -25,6 +25,7 @@
>>>  #include <stdlib.h>
>>>  #include <string.h>
>>>
>>> +#include "coverage.h"
>>>  #include "dp-packet.h"
>>>  #include "dpif.h"
>>>  #include "netlink.h"
>>> @@ -36,6 +37,73 @@
>>>  #include "util.h"
>>>  #include "csum.h"
>>>  #include "conntrack.h"
>>> +#include "ofproto/ofproto-dpif-xlate.h"
>>> +#include "openvswitch/vlog.h"
>>> +
>>> +VLOG_DEFINE_THIS_MODULE(odp_execute)
>>> +COVERAGE_DEFINE(datapath_drop_sample_error);
>>> +COVERAGE_DEFINE(datapath_drop_nsh_decap_error);
>>> +COVERAGE_DEFINE(drop_action_of_pipeline);
>>> +COVERAGE_DEFINE(drop_action_bridge_not_found);
>>> +COVERAGE_DEFINE(drop_action_recursion_too_deep);
>>> +COVERAGE_DEFINE(drop_action_too_many_resubmit);
>>> +COVERAGE_DEFINE(drop_action_stack_too_deep);
>>> +COVERAGE_DEFINE(drop_action_no_recirculation_context);
>>> +COVERAGE_DEFINE(drop_action_recirculation_conflict);
>>> +COVERAGE_DEFINE(drop_action_too_many_mpls_labels);
>>> +COVERAGE_DEFINE(drop_action_invalid_tunnel_metadata);
>>> +COVERAGE_DEFINE(drop_action_unsupported_packet_type);
>>> +COVERAGE_DEFINE(drop_action_congestion);
>>> +COVERAGE_DEFINE(drop_action_forwarding_disabled);
>>> +
>>> +static void
>>> +dp_update_drop_action_counter(enum xlate_error drop_reason,
>>> +                              int delta) {
>>> +   static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
>>> +
>>> +   switch (drop_reason) {
>>> +   case XLATE_OK:
>>> +        COVERAGE_ADD(drop_action_of_pipeline, delta);
>>> +        break;
>>> +   case XLATE_BRIDGE_NOT_FOUND:
>>> +        COVERAGE_ADD(drop_action_bridge_not_found, delta);
>>> +        break;
>>> +   case XLATE_RECURSION_TOO_DEEP:
>>> +        COVERAGE_ADD(drop_action_recursion_too_deep, delta);
>>> +        break;
>>> +   case XLATE_TOO_MANY_RESUBMITS:
>>> +        COVERAGE_ADD(drop_action_too_many_resubmit, delta);
>>> +        break;
>>> +   case XLATE_STACK_TOO_DEEP:
>>> +        COVERAGE_ADD(drop_action_stack_too_deep, delta);
>>> +        break;
>>> +   case XLATE_NO_RECIRCULATION_CONTEXT:
>>> +        COVERAGE_ADD(drop_action_no_recirculation_context, delta);
>>> +        break;
>>> +   case XLATE_RECIRCULATION_CONFLICT:
>>> +        COVERAGE_ADD(drop_action_recirculation_conflict, delta);
>>> +        break;
>>> +   case XLATE_TOO_MANY_MPLS_LABELS:
>>> +        COVERAGE_ADD(drop_action_too_many_mpls_labels, delta);
>>> +        break;
>>> +   case XLATE_INVALID_TUNNEL_METADATA:
>>> +        COVERAGE_ADD(drop_action_invalid_tunnel_metadata, delta);
>>> +        break;
>>> +   case XLATE_UNSUPPORTED_PACKET_TYPE:
>>> +        COVERAGE_ADD(drop_action_unsupported_packet_type, delta);
>>> +        break;
>>> +   case XLATE_CONGESTION_DROP:
>>> +        COVERAGE_ADD(drop_action_congestion, delta);
>>> +        break;
>>> +   case XLATE_FORWARDING_DISABLED:
>>> +        COVERAGE_ADD(drop_action_forwarding_disabled, delta);
>>> +        break;
>>> +   case XLATE_MAX:
>>> +   default:
>>> +        VLOG_ERR_RL(&rl, "Invalid Drop reason type:%d",
>>> drop_reason);
>>> +   }
>>> +}
>>>
>>>  /* Masked copy of an ethernet address. 'src' is already properly
>>> masked. */  static void @@ -621,6 +689,7 @@ odp_execute_sample(void
>>> *dp, struct dp_packet *packet, bool steal,
>>>          case OVS_SAMPLE_ATTR_PROBABILITY:
>>>              if (random_uint32() >= nl_attr_get_u32(a)) {
>>>                  if (steal) {
>>> +                    COVERAGE_ADD(datapath_drop_sample_error, 1);
>>
>> Use COVERAGE_INC() here
>>
>
> Will use COVERGAE_INC here
>>>                      dp_packet_delete(packet);
>>>                  }
>>>                  return;
>>> @@ -749,6 +818,7 @@ requires_datapath_assistance(const struct nlattr
>>> *a)
>>>      case OVS_ACTION_ATTR_POP_NSH:
>>>      case OVS_ACTION_ATTR_CT_CLEAR:
>>>      case OVS_ACTION_ATTR_CHECK_PKT_LEN:
>>> +    case OVS_ACTION_ATTR_DROP:
>>>          return false;
>>>
>>>      case OVS_ACTION_ATTR_UNSPEC:
>>> @@ -965,6 +1035,7 @@ odp_execute_actions(void *dp, struct
>>> dp_packet_batch *batch, bool steal,
>>>                  if (pop_nsh(packet)) {
>>>                      dp_packet_batch_refill(batch, packet, i);
>>>                  } else {
>>> +                    COVERAGE_INC(datapath_drop_nsh_decap_error);
>>>                      dp_packet_delete(packet);
>>>                  }
>>>              }
>>> @@ -989,6 +1060,14 @@ odp_execute_actions(void *dp, struct
>>> dp_packet_batch *batch, bool steal,
>>>              }
>>>              break;
>>>
>>> +        case OVS_ACTION_ATTR_DROP:{
>>> +            const enum xlate_error *drop_reason = nl_attr_get(a);
>>> +            if (*drop_reason < XLATE_MAX) {
>>> +                 dp_update_drop_action_counter(*drop_reason,
>>> batch->count);
>>> +            }
>>> +            dp_packet_delete_batch(batch, steal);
>>> +            return;
>>> +        }
>>>          case OVS_ACTION_ATTR_OUTPUT:
>>>          case OVS_ACTION_ATTR_TUNNEL_PUSH:
>>>          case OVS_ACTION_ATTR_TUNNEL_POP:
>>> diff --git a/lib/odp-util.c b/lib/odp-util.c index 84ea4c1..5dc5bbf
>>> 100644
>>> --- a/lib/odp-util.c
>>> +++ b/lib/odp-util.c
>>> @@ -44,6 +44,7 @@
>>>  #include "openvswitch/vlog.h"
>>>  #include "openvswitch/match.h"
>>>  #include "odp-netlink-macros.h"
>>> +#include "ofproto/ofproto-dpif-xlate.h"
>>>
>>>  VLOG_DEFINE_THIS_MODULE(odp_util);
>>>
>>> @@ -140,6 +141,7 @@ odp_action_len(uint16_t type)
>>>      case OVS_ACTION_ATTR_PUSH_NSH: return ATTR_LEN_VARIABLE;
>>>      case OVS_ACTION_ATTR_POP_NSH: return 0;
>>>      case OVS_ACTION_ATTR_CHECK_PKT_LEN: return ATTR_LEN_VARIABLE;
>>> +    case OVS_ACTION_ATTR_DROP: return sizeof(enum xlate_error);
>>>
>>>      case OVS_ACTION_ATTR_UNSPEC:
>>>      case __OVS_ACTION_ATTR_MAX:
>>> @@ -1230,6 +1232,9 @@ format_odp_action(struct ds *ds, const struct
>>> nlattr *a,
>>>      case OVS_ACTION_ATTR_CHECK_PKT_LEN:
>>>          format_odp_check_pkt_len_action(ds, a, portno_names);
>>>          break;
>>> +    case OVS_ACTION_ATTR_DROP:
>>> +        ds_put_cstr(ds, "drop");
>>> +        break;
>>>      case OVS_ACTION_ATTR_UNSPEC:
>>>      case __OVS_ACTION_ATTR_MAX:
>>>      default:
>>> @@ -2547,8 +2552,12 @@ odp_actions_from_string(const char *s, const
>>> struct simap *port_names,
>>>                          struct ofpbuf *actions)  {
>>>      size_t old_size;
>>> +    enum xlate_error drop_action;
>>>
>>>      if (!strcasecmp(s, "drop")) {
>>> +        drop_action = XLATE_OK;
>>> +        nl_msg_put_u32(actions, OVS_ACTION_ATTR_DROP,
>>> +                          drop_action);
>>>          return 0;
>>>      }
>>>
>>> diff --git a/ofproto/ofproto-dpif-ipfix.c
>>> b/ofproto/ofproto-dpif-ipfix.c index b8bd1b8..b413768 100644
>>> --- a/ofproto/ofproto-dpif-ipfix.c
>>> +++ b/ofproto/ofproto-dpif-ipfix.c
>>> @@ -3016,6 +3016,7 @@ dpif_ipfix_read_actions(const struct flow
>>> *flow,
>>>          case OVS_ACTION_ATTR_POP_NSH:
>>>          case OVS_ACTION_ATTR_CHECK_PKT_LEN:
>>>          case OVS_ACTION_ATTR_UNSPEC:
>>> +        case OVS_ACTION_ATTR_DROP:
>>>          case __OVS_ACTION_ATTR_MAX:
>>>          default:
>>>              break;
>>> diff --git a/ofproto/ofproto-dpif-sflow.c
>>> b/ofproto/ofproto-dpif-sflow.c index 03bd763..387e9b5 100644
>>> --- a/ofproto/ofproto-dpif-sflow.c
>>> +++ b/ofproto/ofproto-dpif-sflow.c
>>> @@ -1224,6 +1224,7 @@ dpif_sflow_read_actions(const struct flow
>>> *flow,
>>>          case OVS_ACTION_ATTR_POP_NSH:
>>>          case OVS_ACTION_ATTR_UNSPEC:
>>>          case OVS_ACTION_ATTR_CHECK_PKT_LEN:
>>> +        case OVS_ACTION_ATTR_DROP:
>>>          case __OVS_ACTION_ATTR_MAX:
>>>          default:
>>>              break;
>>> diff --git a/ofproto/ofproto-dpif-xlate.c
>>> b/ofproto/ofproto-dpif-xlate.c index 73966a4..2b583e2 100644
>>> --- a/ofproto/ofproto-dpif-xlate.c
>>> +++ b/ofproto/ofproto-dpif-xlate.c
>>> @@ -445,6 +445,12 @@ const char *xlate_strerror(enum xlate_error
>>> error)
>>>          return "Invalid tunnel metadata";
>>>      case XLATE_UNSUPPORTED_PACKET_TYPE:
>>>          return "Unsupported packet type";
>>> +    case XLATE_CONGESTION_DROP:
>>> +        return "Congestion Drop";
>>> +    case XLATE_FORWARDING_DISABLED:
>>> +        return "Forwarding is disabled";
>>> +    case XLATE_MAX:
>>> +        break;
>>>      }
>>>      return "Unknown error";
>>>  }
>>> @@ -5955,6 +5961,14 @@ put_ct_label(const struct flow *flow, struct
>>> ofpbuf *odp_actions,  }
>>>
>>>  static void
>>> +put_drop_action(struct ofpbuf *odp_actions, enum xlate_error error)
>>> +{
>>> +    nl_msg_put_u32(odp_actions, OVS_ACTION_ATTR_DROP,
>>> +                      error);
>>> +
>>> +}
>>> +
>>> +static void
>>>  put_ct_helper(struct xlate_ctx *ctx,
>>>                struct ofpbuf *odp_actions, struct ofpact_conntrack
>>> *ofc)
>>>  {
>>> @@ -7544,8 +7558,9 @@ xlate_actions(struct xlate_in *xin, struct
>>> xlate_out *xout)
>>>              compose_ipfix_action(&ctx, ODPP_NONE);
>>>          }
>>>          size_t sample_actions_len = ctx.odp_actions->size;
>>> +        bool ecn_drop = !tnl_process_ecn(flow);
>>>
>>> -        if (tnl_process_ecn(flow)
>>> +        if (!ecn_drop
>>>              && (!in_port || may_receive(in_port, &ctx))) {
>>>              const struct ofpact *ofpacts;
>>>              size_t ofpacts_len;
>>> @@ -7577,6 +7592,7 @@ xlate_actions(struct xlate_in *xin, struct
>>> xlate_out *xout)
>>>                  ctx.odp_actions->size = sample_actions_len;
>>>                  ctx_cancel_freeze(&ctx);
>>>                  ofpbuf_clear(&ctx.action_set);
>>> +                ctx.error = XLATE_FORWARDING_DISABLED;
>>>              }
>>>
>>>              if (!ctx.freezing) {
>>> @@ -7585,6 +7601,8 @@ xlate_actions(struct xlate_in *xin, struct
>>> xlate_out *xout)
>>>              if (ctx.freezing) {
>>>                  finish_freezing(&ctx);
>>>              }
>>> +        } else if (ecn_drop) {
>>> +            ctx.error = XLATE_CONGESTION_DROP;
>>>          }
>>>
>>>          /* Output only fully processed packets. */ @@ -7690,6
>>> +7708,26 @@ exit:
>>>              ofpbuf_clear(xin->odp_actions);
>>>          }
>>>      }
>>> +
>>> +    /*
>>> +     * If we are going to install "drop" action, check whether
>>> +     * datapath supports explicit "drop"action. If datapath
>>> +     * supports explicit "drop"action then install the "drop"
>>> +     * action containing the drop reason.
>>> +     */
>>> +    if (xin->odp_actions && !xin->odp_actions->size &&
>>> +        ovs_explicit_drop_action_supported(ctx.xbridge->ofproto)) {
>>> +        put_drop_action(xin->odp_actions, ctx.error);
>>> +    }
>>> +
>>> +    /* Since congestion drop and forwarding drop are not exactly
>>> +     * translation error, we are resetting the translation error.
>>> +     */
>>> +    if (ctx.error == XLATE_CONGESTION_DROP ||
>>> +        ctx.error == XLATE_FORWARDING_DISABLED) {
>>> +       ctx.error = XLATE_OK;
>>> +    }
>>> +
>>>      return ctx.error;
>>>  }
>>>
>>> diff --git a/ofproto/ofproto-dpif-xlate.h
>>> b/ofproto/ofproto-dpif-xlate.h index f97c7c0..3105a44 100644
>>> --- a/ofproto/ofproto-dpif-xlate.h
>>> +++ b/ofproto/ofproto-dpif-xlate.h
>>> @@ -217,6 +217,9 @@ enum xlate_error {
>>>      XLATE_TOO_MANY_MPLS_LABELS,
>>>      XLATE_INVALID_TUNNEL_METADATA,
>>>      XLATE_UNSUPPORTED_PACKET_TYPE,
>>> +    XLATE_CONGESTION_DROP,
>>> +    XLATE_FORWARDING_DISABLED,
>>
>> There was a comment from Benn you did not reply to, so I leave this
>> open:
>>
>> “I'm uncomfortable with the two new errors XLATE_CONGESTION_DROP 
>> and
>> XLATE_FORWARDING_DISABLED as translation errors, since they aren't
>> translation errors and don't prevent translation from completing.”
>
> Yes.  Basically Ben wanted to not propagate ctx.error as error to the 
> datapath. Hence I have reset it to XLATE_OK after setting it as drop 
> reason above.
>>
>>> +    XLATE_MAX,
>>
>> Why did you at XLATE_MAX as it’s not used?
>>
>
> I have used XLATE_MAX because I am using this value for comparison in 
> datapath. In future if more errors are introduced we don’t need to 
> change this in comparison in future. (Ref func: odp_execute_actions 
> condition  if (*drop_reason < XLATE_MAX) )
>
>
>>>  };
>>>
>>>  const char *xlate_strerror(enum xlate_error error); diff --git
>>> a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index
>>> 7515352..358b9b8 100644
>>> --- a/ofproto/ofproto-dpif.c
>>> +++ b/ofproto/ofproto-dpif.c
>>> @@ -828,6 +828,12 @@ ovs_native_tunneling_is_on(struct ofproto_dpif
>>> *ofproto)
>>>          && atomic_count_get(&ofproto->backer->tnl_count);
>>>  }
>>>
>>> +bool
>>> +ovs_explicit_drop_action_supported(struct ofproto_dpif *ofproto) {
>>> +    return ofproto->backer->rt_support.explicit_drop_action;
>>> +}
>>> +
>>>  /* Tests whether 'backer''s datapath supports recirculation.  Only
>>> newer
>>>   * datapaths support OVS_KEY_ATTR_RECIRC_ID in keys.  We need to
>>> disable some
>>>   * features on older datapaths that don't support this feature.
>>> @@ -1441,6 +1447,8 @@ check_support(struct dpif_backer *backer)
>>>      backer->rt_support.ct_clear = check_ct_clear(backer);
>>>      backer->rt_support.max_hash_alg = 
>>> check_max_dp_hash_alg(backer);
>>>      backer->rt_support.check_pkt_len = check_check_pkt_len(backer);
>>> +    backer->rt_support.explicit_drop_action =
>>> +        dpif_supports_explicit_drop_action(backer->dpif);
>>>
>>>      /* Flow fields. */
>>>      backer->rt_support.odp.ct_state = check_ct_state(backer); diff
>>> --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h index
>>> cd5321e..f2f0f20 100644
>>> --- a/ofproto/ofproto-dpif.h
>>> +++ b/ofproto/ofproto-dpif.h
>>> @@ -195,7 +195,11 @@ struct group_dpif *group_dpif_lookup(struct
>>> ofproto_dpif *,
>>>      DPIF_SUPPORT_FIELD(size_t, max_hash_alg, "Max dp_hash
>>> algorithm")
>>>       \
>>>                                                                              \
>>>      /* True if the datapath supports OVS_ACTION_ATTR_CHECK_PKT_LEN.
>>> */   \
>>> -    DPIF_SUPPORT_FIELD(bool, check_pkt_len, "Check pkt length
>>> action")
>>> +    DPIF_SUPPORT_FIELD(bool, check_pkt_len, "Check pkt length
>>> action")     \
>>> +
>>>       \
>>> +    /* True if the datapath supports explicit drop action. */
>>>       \
>>> +    DPIF_SUPPORT_FIELD(bool, explicit_drop_action, "Explicit Drop
>>> action")
>>> +
>>>
>> Please fix alignment of trailing \, while you are at it also for the
>> line above “PIF_SUPPORT_FIELD(size_t, max_hash_alg, "Max dp_hash
>> algorithm”)”
>>
>>
>>>  /* Stores the various features which the corresponding backer
>>> supports. */  struct dpif_backer_support { @@ -364,4 +368,6 @@ int
>>> ofproto_dpif_delete_internal_flow(struct
>>> ofproto_dpif *, struct match *,
>>>
>>>  bool ovs_native_tunneling_is_on(struct ofproto_dpif *);
>>>
>>> +bool ovs_explicit_drop_action_supported(struct ofproto_dpif *);
>>> +
>>>  #endif /* ofproto-dpif.h */
>>> diff --git a/tests/automake.mk b/tests/automake.mk index
>>> 2956e68..04e67c2 100644
>>> --- a/tests/automake.mk
>>> +++ b/tests/automake.mk
>>> @@ -111,7 +111,8 @@ TESTSUITE_AT = \
>>>  	tests/mcast-snooping.at \
>>>  	tests/packet-type-aware.at \
>>>  	tests/nsh.at \
>>> -	tests/ovn-performance.at
>>> +	tests/ovn-performance.at \
>>> +	tests/drop-stats.at
>>>
>>>  EXTRA_DIST += $(FUZZ_REGRESSION_TESTS)  FUZZ_REGRESSION_TESTS = \
>>> diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at index
>>> af8a29e..b8b6296 100644
>>> --- a/tests/dpif-netdev.at
>>> +++ b/tests/dpif-netdev.at
>>> @@ -349,6 +349,14 @@ meter:2 flow_count:1 packet_in_count:10
>>> byte_in_count:600 duration:0.0s bands:
>>>  0: packet_count:5 byte_count:300
>>>  ])
>>>
>>> +ovs-appctl time/warp 5000
>>> +
>>> +AT_CHECK([
>>> +ovs-appctl coverage/show | grep "datapath_drop_meter" | cut -d':'
>>> -f2|sed 's/ //'
>>> +], [0], [dnl
>>> +14
>>> +])
>>> +
>>>  AT_CHECK([cat ovs-vswitchd.log | filter_flow_install |
>>> strip_xout_keep_actions], [0], [dnl
>>> recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(
>>> frag=no),
>>> actions:meter(0),7
>>>
>>> recirc_id(0),in_port(2),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(
>>> frag=no),
>>> actions:8
>>> diff --git a/tests/drop-stats.at b/tests/drop-stats.at new file mode
>>> 100644 index 0000000..c7f8cb7
>>> --- /dev/null
>>> +++ b/tests/drop-stats.at
>>> @@ -0,0 +1,210 @@
>>> +AT_BANNER([drop-stats])
>>> +
>>> +AT_SETUP([drop-stats - cli tests])
>>> +
>>> +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])
>>> +
>>> +AT_DATA([flows.txt], [dnl
>>> +table=0,in_port=1,actions=drop
>>> +])
>>> +
>>> +AT_CHECK([
>>> +    ovs-ofctl del-flows br0
>>> +    ovs-ofctl -Oopenflow13 add-flows br0 flows.txt
>>> +    ovs-ofctl -Oopenflow13 dump-flows br0 | ofctl_strip | sort |
>>> grep
>>> +actions ], [0], [dnl
>>> + in_port=1 actions=drop
>>> +])
>>> +
>>> +AT_CHECK([
>>> +    ovs-appctl netdev-dummy/receive p1
>>> 1e2ce92a669e3a6dd2099cab0800450000548a53400040011addc0a80a0ac0a80a1e0
>>> 8006f200a4d0001fc509a58000000002715020000000000101112131415161718191a
>>> 1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637
>>> +    ovs-appctl netdev-dummy/receive p1
>>> 1e2ce92a669e3a6dd2099cab0800450000548a53400040011addc0a80a0ac0a80a1e0
>>> 8006f200a4d0001fc509a58000000002715020000000000101112131415161718191a
>>> 1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637
>>> +    ovs-appctl netdev-dummy/receive p1
>>> +1e2ce92a669e3a6dd2099cab0800450000548a53400040011addc0a80a0ac0a80a1e
>>> +080
>>> +06f200a4d0001fc509a58000000002715020000000000101112131415161718191a1
>>> +b1c
>>> +1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637
>>> +], [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
>>> non-dpdk interfaces:
>>> +recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4
>>> +(fr ag=no), packets:2, bytes:196, used:0.0, actions:drop
>>> +])
>>> +
>>> +sleep 1
>>> +
>>> +
>>> +AT_CHECK([
>>> +ovs-appctl coverage/show | grep "drop_action_of_pipeline" | cut
>>> -d':'
>>> -f2|sed 's/ //'
>>> +], [0], [dnl
>>> +3
>>> +])
>>> +
>>> +
>>> +OVS_VSWITCHD_STOP
>>> +AT_CLEANUP
>>> +
>>> +AT_SETUP([drop-stats - pipeline and recurssion drops])
>>> +
>>> +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=drop
>>> +])
>>> +
>>> +AT_CHECK([
>>> +    ovs-ofctl del-flows br0
>>> +    ovs-ofctl -Oopenflow13 add-flows br0 flows.txt
>>> +    ovs-ofctl -Oopenflow13 dump-flows br0 | ofctl_strip | sort |
>>> grep
>>> +actions ], [0], [dnl
>>> + in_port=1 actions=drop
>>> +])
>>> +
>>> +AT_CHECK([
>>> +    ovs-appctl netdev-dummy/receive p1
>>> +1e2ce92a669e3a6dd2099cab0800450000548a53400040011addc0a80a0ac0a80a1e
>>> +080
>>> +06f200a4d0001fc509a58000000002715020000000000101112131415161718191a1
>>> +b1c
>>> +1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637
>>> +], [0], [ignore])
>>> +
>>> +sleep 1
>>> +
>>> +
>>> +AT_CHECK([
>>> +ovs-appctl coverage/show | grep "drop_action_of_pipeline" | cut
>>> -d':'
>>> -f2|sed 's/ //'
>>> +], [0], [dnl
>>> +1
>>> +])
>>> +
>>> +
>>> +AT_DATA([flows.txt], [dnl
>>> +table=0, in_port=1, actions=goto_table:1 table=1, in_port=1,
>>> +actions=goto_table:2 table=2, in_port=1, actions=resubmit(,1)
>>> +])
>>> +
>>> +AT_CHECK([
>>> +    ovs-ofctl del-flows br0
>>> +    ovs-ofctl -Oopenflow13 add-flows br0 flows.txt
>>> +    ovs-ofctl -Oopenflow13 dump-flows br0 | ofctl_strip | sort |
>>> grep
>>> +actions ], [0], [ignore])
>>> +
>>> +AT_CHECK([
>>> +    ovs-appctl netdev-dummy/receive p1
>>> +1e2ce92a669e3a6dd2099cab0800450000548a53400040011addc0a80a0ac0a80a1e
>>> +080
>>> +06f200a4d0001fc509a58000000002715020000000000101112131415161718191a1
>>> +b1c
>>> +1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637
>>> +], [0], [ignore])
>>> +
>>> +sleep 1
>>> +
>>> +AT_CHECK([
>>> +ovs-appctl coverage/show | grep "drop_action_recursion_too_deep" |
>>> cut -d':' -f2|sed 's/ //'
>>> +], [0], [dnl
>>> +1
>>> +])
>>> +
>>> +
>>> +OVS_VSWITCHD_STOP(["/|WARN|/d"])
>>> +AT_CLEANUP
>>> +
>>> +AT_SETUP([drop-stats - too many resubmit])
>>> +
>>> +OVS_VSWITCHD_START
>>> +add_of_ports br0 1
>>> +(for i in `seq 1 64`; do
>>> +     j=`expr $i + 1`
>>> +     echo "in_port=$i, actions=resubmit:$j, resubmit:$j, local"
>>> + done
>>> + echo "in_port=65, actions=local") > flows.txt
>>> +
>>> +AT_CHECK([
>>> +    ovs-ofctl del-flows br0
>>> +    ovs-ofctl -Oopenflow13 add-flows br0 flows.txt ], [0], 
>>> [ignore])
>>> +
>>> +ovs-appctl netdev-dummy/receive p1
>>> 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234)'
>>> +
>>> +
>>> +sleep 1
>>> +
>>> +AT_CHECK([
>>> +ovs-appctl coverage/show | grep "drop_action_too_many_resubmit" |
>>> cut
>>> -d':' -f2|sed 's/ //'
>>> +], [0], [dnl
>>> +1
>>> +])
>>> +
>>> +OVS_VSWITCHD_STOP(["/|WARN|/d"])
>>> +AT_CLEANUP
>>> +
>>> +
>>> +AT_SETUP([drop-stats - stack too deep]) OVS_VSWITCHD_START
>>> add_of_ports
>>> +br0 1 (for i in `seq 1 12`; do
>>> +     j=`expr $i + 1`
>>> +     echo "in_port=$i, actions=resubmit:$j, resubmit:$j, local"
>>> + done
>>> + push="push:NXM_NX_REG0[[]]"
>>> + echo "in_port=13,
>>> +actions=$push,$push,$push,$push,$push,$push,$push,$push") > flows
>>> +AT_CHECK([ovs-ofctl add-flows br0 flows])
>>> +
>>> +ovs-appctl netdev-dummy/receive p1
>>> 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234)'
>>> +
>>> +sleep 1
>>> +
>>> +AT_CHECK([
>>> +ovs-appctl coverage/show | grep "drop_action_stack_too_deep" | cut
>>> -d':' -f2|sed 's/ //'
>>> +], [0], [dnl
>>> +1
>>> +])
>>> +
>>> +
>>> +OVS_VSWITCHD_STOP(["/resubmits yielded over 64 kB of stack/d"])
>>> +AT_CLEANUP
>>> +
>>> +AT_SETUP([drop-stats - too many mpls labels])
>>> +
>>> +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=push_mpls:0x8847, resubmit:3 table=0,
>>> +in_port=3, actions=push_mpls:0x8847, set_field:10->mpls_label,
>>> +set_field:15->mpls_label,  resubmit:4 table=0, in_port=4,
>>> +actions=push_mpls:0x8847, set_field:11->mpls_label, resubmit:5
>>> table=0,
>>> +in_port=5, actions=push_mpls:0x8847, set_field:12->mpls_label,
>>> +resubmit:6 table=0, in_port=6, actions=push_mpls:0x8847,
>>> +set_field:13->mpls_label, output:2
>>> +])
>>> +
>>> +AT_CHECK([
>>> +    ovs-ofctl del-flows br0
>>> +    ovs-ofctl -Oopenflow13 add-flows br0 flows.txt
>>> +])
>>> +
>>> +AT_CHECK([
>>> +    ovs-appctl netdev-dummy/receive p1
>>> +1e2ce92a669e3a6dd2099cab0800450000548a53400040011addc0a80a0ac0a80a1e
>>> +080
>>> +06f200a4d0001fc509a58000000002715020000000000101112131415161718191a1
>>> +b1c
>>> +1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637
>>> +], [0], [ignore])
>>> +
>>> +sleep 1
>>> +
>>> +AT_CHECK([
>>> +ovs-appctl coverage/show | grep "drop_action_too_many_mpls_labels" 
>>> |
>>> cut -d':' -f2|sed 's/ //'
>>> +], [0], [dnl
>>> +1
>>> +])
>>> +
>>> +
>>> +OVS_VSWITCHD_STOP(["/|WARN|/d"])
>>> +AT_CLEANUP
>>> diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index
>>> dc21c88..e42c490 100644
>>> --- a/tests/ofproto-dpif.at
>>> +++ b/tests/ofproto-dpif.at
>>> @@ -9425,7 +9425,7 @@
>>> recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x8100),vlan(
>>> vid=99,pcp=
>>>  # are wildcarded.
>>>  AT_CHECK([grep '\(modify\)\|\(flow_add\)' ovs-vswitchd.log |
>>> strip_ufid ], [0], [dnl
>>>  dpif_netdev|DBG|flow_add:
>>> recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x1234),
>>> actions:100
>>> -dpif|DBG|dummy at ovs-dummy: put[[modify]]
>>> skb_priority(0/0),skb_mark(0/0),ct_state(0/0),ct_zone(0/0),ct_mark(0/
>>> 0),ct_label(0/0),recirc_id(0),dp_hash(0/0),in_port(1),packet_type(ns=
>>> 0,id=0),eth(src=50:54:00:00:00:09/00:00:00:00:00:00,dst=50:54:00:00:0
>>> 0:0a/00:00:00:00:00:00),eth_type(0x1234)
>>> +dpif|DBG|dummy at ovs-dummy: put[[modify]]
>>> skb_priority(0/0),skb_mark(0/0),ct_state(0/0),ct_zone(0/0),ct_mark(0/
>>> 0),ct_label(0/0),recirc_id(0),dp_hash(0/0),in_port(1),packet_type(ns=
>>> 0,id=0),eth(src=50:54:00:00:00:09/00:00:00:00:00:00,dst=50:54:00:00:0
>>> 0:0a/00:00:00:00:00:00),eth_type(0x1234),
>>> actions:drop
>>>  dpif|DBG|dummy at ovs-dummy: put[[modify]]
>>> skb_priority(0/0),skb_mark(0/0),ct_state(0/0),ct_zone(0/0),ct_mark(0/
>>> 0),ct_label(0/0),recirc_id(0),dp_hash(0/0),in_port(1),packet_type(ns=
>>> 0,id=0),eth(src=50:54:00:00:00:09/00:00:00:00:00:00,dst=50:54:00:00:0
>>> 0:0a/00:00:00:00:00:00),eth_type(0x1234),
>>> actions:100
>>>  dpif_netdev|DBG|flow_add:
>>> recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x8100),vlan(
>>> vid=99,pcp=7/0x0),encap(eth_type(0x1234)),
>>> actions:drop
>>>  ])
>>> diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
>>> index f717243..532c44e 100644
>>> --- a/tests/tunnel-push-pop.at
>>> +++ b/tests/tunnel-push-pop.at
>>> @@ -447,6 +447,28 @@ AT_CHECK([ovs-ofctl dump-ports int-br | grep
>>> 'port  7'], [0], [dnl
>>>    port  7: rx pkts=3, bytes=252, drop=?, errs=?, frame=?, over=?,
>>> crc=?
>>>  ])
>>>
>>> +AT_CHECK([ovs-appctl netdev-dummy/receive p0
>>> 'aa55aa550000001b213cab6408004500007079464000402fba600101025c01010258
>>> 20000800000001c845000054ba200000400184861e0000011e00000200004227e7540
>>> 0030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f20
>>> 2122232425262728292a2b2c2d2e2f3031323334353637'])
>>> +
>>> +ovs-appctl time/warp 5000
>>> +
>>> +AT_CHECK([
>>> +ovs-appctl coverage/show | grep "datapath_drop_tunnel_pop_error" |
>>> cut -d':' -f2|sed 's/ //'
>>> +], [0], [dnl
>>> +1
>>> +])
>>> +
>>> +sleep 1
>>> +AT_CHECK([ovs-appctl netdev-dummy/receive p0
>>> 'aa55aa550000001b213cab6408004503007079464000402fba600101025c01010258
>>> 20000800000001c845000054ba200000400184861e0000011e00000200004227e7540
>>> 0030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f20
>>> 2122232425262728292a2b2c2d2e2f3031323334353637'])
>>> +
>>> +ovs-appctl time/warp 5000
>>> +
>>> +AT_CHECK([
>>> +ovs-appctl coverage/show | grep "drop_action_congestion" | cut 
>>> -d':'
>>> -f2|sed 's/ //'
>>> +], [0], [dnl
>>> +1
>>> +])
>>> +
>>> +
>>>  dnl Check GREL3 only accepts non-fragmented packets?
>>>  AT_CHECK([ovs-appctl netdev-dummy/receive p0
>>> 'aa55aa550000001b213cab6408004500007e79464000402fba550101025c01010258
>>> 20000800000001c8fe71d883724fbeb6f4e1494a080045000054ba200000400184861
>>> e0000011e00000200004227e75400030af3195500000000f265010000000000101112
>>> 131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343
>>> 53637'])
>>>
>>> @@ -455,7 +477,7 @@ ovs-appctl time/warp 1000
>>>
>>>  AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port  [[37]]' | 
>>> sort],
>>> [0], [dnl
>>>    port  3: rx pkts=3, bytes=294, drop=?, errs=?, frame=?, over=?,
>>> crc=?
>>> -  port  7: rx pkts=4, bytes=350, drop=?, errs=?, frame=?, over=?,
>>> crc=?
>>> +  port  7: rx pkts=5, bytes=434, drop=?, errs=?, frame=?, over=?,
>>> crc=?
>>>  ])
>>>
>>>  dnl Check decapsulation of Geneve packet with options @@ -478,7
>>> +500,7 @@ AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port  5'],
>>> [0], [dnl
>>>    port  5: rx pkts=1, bytes=98, drop=?, errs=?, frame=?, over=?,
>>> crc=?
>>>  ])
>>>  AT_CHECK([ovs-appctl dpif/dump-flows int-br | grep 
>>> 'in_port(6081)'],
>>> [0], [dnl
>>> -tunnel(tun_id=0x7b,src=1.1.2.92,dst=1.1.2.88,geneve({class=0xffff,ty
>>> pe=0x80,len=4,0xa/0xf}{class=0xffff,type=0,len=4}),flags(-df-csum+key
>>> )),recirc_id(0),in_port(6081),packet_type(ns=0,id=0),eth_type(0x0800)
>>> ,ipv4(frag=no),
>>> packets:0, bytes:0, used:never,
>>> actions:userspace(pid=0,controller(reason=1,dont_send=0,continuation=
>>> 0,recirc_id=3,rule_cookie=0,controller_id=0,max_len=65535))
>>> +tunnel(tun_id=0x7b,src=1.1.2.92,dst=1.1.2.88,geneve({class=0xffff,ty
>>> +pe=0x80,len=4,0xa/0xf}{class=0xffff,type=0,len=4}),flags(-df-csum+ke
>>> +y)),recirc_id(0),in_port(6081),packet_type(ns=0,id=0),eth_type(0x080
>>> +0),ipv4(frag=no),
>>> packets:0, bytes:0, used:never,
>>> actions:userspace(pid=0,controller(reason=1,dont_send=0,continuation=
>>> 0,recirc_id=2,rule_cookie=0,controller_id=0,max_len=65535))
>>>  ])
>>>
>>>  ovs-appctl time/warp 10000
>>> @@ -510,7 +532,8 @@ AT_CHECK([ovs-appctl tnl/ports/show |sort], [0],
>>> [dnl  Listening ports:
>>>  ])
>>>
>>> -OVS_VSWITCHD_STOP
>>> +OVS_VSWITCHD_STOP(["/dropping tunnel packet marked ECN CE but is 
>>> not
>>> ECN capable/d
>>> +/ip packet has invalid checksum/d"])
>>>  AT_CLEANUP
>>>
>>>  AT_SETUP([tunnel_push_pop - packet_out]) diff --git
>>> a/tests/tunnel.at b/tests/tunnel.at index 035c54f..b0a80d5 100644
>>> --- a/tests/tunnel.at
>>> +++ b/tests/tunnel.at
>>> @@ -102,8 +102,9 @@ Datapath actions: set(ipv4(tos=0x3/0x3)),2
>>>
>>>  dnl Tunnel CE and encapsulated packet Non-ECT  AT_CHECK([ovs-appctl
>>> ofproto/trace ovs-dummy
>>> 'tunnel(src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),in_port(1),et
>>> h(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(
>>> src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src
>>> =8,dst=9)'],
>>> [0], [stdout])
>>> -AT_CHECK([tail -2 stdout], [0],
>>> -  [Megaflow:
>>> recirc_id=0,eth,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=3
>>> ,tun_flags=-df-csum-key,in_port=1,nw_ecn=0,nw_frag=no
>>> +AT_CHECK([tail -3 stdout], [0],
>>> +  [Final flow: unchanged
>>> +Megaflow:
>>> recirc_id=0,eth,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=3
>>> ,tun_flags=-df-csum-key,in_port=1,nw_ecn=0,nw_frag=no
>>>  Datapath actions: drop
>>>  ])
>>>  OVS_VSWITCHD_STOP(["/dropping tunnel packet marked ECN CE but is 
>>> not
>>> ECN capable/d"]) @@ -193,6 +194,17 @@ AT_CHECK([ovs-appctl
>>> ofproto/trace ovs-dummy
>>> 'in_port(2),eth(src=50:54:00:00:00:
>>>  AT_CHECK([tail -1 stdout], [0],
>>>    [Datapath actions:
>>> set(tunnel(tun_id=0x5,src=2.2.2.2,dst=1.1.1.1,ttl=64,flags(df|key))),
>>> set(skb_mark(0x2)),1
>>>  ])
>>> +
>>> +AT_CHECK([ovs-appctl netdev-dummy/receive p2
>>> 'aa55aa550001f8bc124434b6080045000054ba200000400184860101035801010370
>>> 01004227e75400030af3195500000000f265010000000000101112131415161718191
>>> a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
>>> +
>>> +sleep 2
>>> +
>>> +AT_CHECK([
>>> +ovs-appctl coverage/show | grep "datapath_drop_invalid_port" | cut
>>> -d':' -f2|sed 's/ //'
>>> +], [0], [dnl
>>> +1
>>> +])
>>> +
>>>  OVS_VSWITCHD_STOP
>>>  AT_CLEANUP
>>>
>>> --
>>> 1.9.1
>>>
>>> _______________________________________________
>>> dev mailing list
>>> dev at openvswitch.org
>>> https://protect2.fireeye.com/url?k=58a57294-04717fe6-58a5320f-86859b2
>>> 931b3-8b0fe0ffb85e8b17&q=1&u=https%3A%2F%2Fmail.openvswitch.org%2Fmai
>>> lman%2Flistinfo%2Fovs-dev


More information about the dev mailing list