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

Gregory Rose gvrose8192 at gmail.com
Fri Jun 7 21:55:27 UTC 2019



On 6/7/2019 2:31 PM, Gregory Rose wrote:
>
> On 6/6/2019 10:27 PM, 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
>>
>> A detailed presentation on this was presented at OvS conference 2017 
>> and link for the corresponding presentation is available at:
>>
>> https://www.slideshare.net/LF_OpenvSwitch/lfovs17troubleshooting-the-data-plane-in-ovs-82280329 
>>
>>
>> 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>
>
> Hi Anju et al,
>
> I am going to review and test this patch, however, I do have a request 
> just below...

I attempted to apply the patch and got the following errors:

Applying patch #1111568 using 'git am'
Description: [ovs-dev,v10] Improved Packet Drop Statistics in OVS
Applying: Improved Packet Drop Statistics in OVS
error: patch failed: tests/automake.mk:109
error: tests/automake.mk: patch does not apply
/home/gvrose/prj/ovs-experimental/.git/rebase-apply/patch:804: new blank 
line at EOF.
+
Patch failed at 0001 Improved Packet Drop Statistics in OVS
The copy of the patch that failed is found in:
    /home/gvrose/prj/ovs-experimental/.git/rebase-apply/patch
When you have resolved this problem, run "git am --resolved".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
'git am' failed with exit status 1

Please rebase to current master and I can give it another try.

Thanks,

- Greg


>
>> ---
>
> Here, below the three dash line just above, there should be an 
> accounting of all changes from version 1 of
> this patch set to version 10.  Something like this:
>
> v9 -> v10 Changed something due to review comments etc...
> v8 -> v9 Describe changes from v8 to v9 etc...
>
> I think it's essential to reviewers to understand the previous patches 
> and their evolution to the current patch.
>
> Thanks,
>
> - Greg
>
>> 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                                 |  78 ++++++++
>>   lib/odp-util.c                                    |   9 +
>>   ofproto/ofproto-dpif-ipfix.c                      |   1 +
>>   ofproto/ofproto-dpif-sflow.c                      |   1 +
>>   ofproto/ofproto-dpif-xlate.c                      |  34 +++-
>>   ofproto/ofproto-dpif-xlate.h                      |   3 +
>>   ofproto/ofproto-dpif.c                            |   7 +
>>   ofproto/ofproto-dpif.h                            |   8 +-
>>   tests/automake.mk                                 |   3 +-
>>   tests/dpif-netdev.at                              |   8 +
>>   tests/drop-stats.at                               | 211 
>> ++++++++++++++++++++++
>>   tests/ofproto-dpif.at                             |   2 +-
>>   tests/tunnel-push-pop.at                          |  29 ++-
>>   tests/tunnel.at                                   |  14 +-
>>   18 files changed, 455 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..2de702e 100644
>> --- a/datapath/linux/compat/include/linux/openvswitch.h
>> +++ b/datapath/linux/compat/include/linux/openvswitch.h
>> @@ -985,6 +985,7 @@ enum ovs_action_attr {
>>       OVS_ACTION_ATTR_METER,        /* u32 meter number. */
>>       OVS_ACTION_ATTR_CLONE,        /* Nested OVS_CLONE_ATTR_*. */
>>       OVS_ACTION_ATTR_CHECK_PKT_LEN, /* Nested 
>> OVS_CHECK_PKT_LEN_ATTR_*. */
>> +    OVS_ACTION_ATTR_DROP,
>>     #ifndef __KERNEL__
>>       OVS_ACTION_ATTR_TUNNEL_PUSH,   /* struct ovs_action_push_tnl*/
>> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
>> index 5a6f2ab..ec72403 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;
>>   @@ -5646,7 +5657,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. */
>> @@ -6402,6 +6413,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;
>>           }
>>   @@ -6521,6 +6533,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;
>>       }
>>   @@ -6651,6 +6664,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++;
>>               }
>>           }
>> @@ -6920,6 +6934,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);
>>       }
>>   }
>>   @@ -6934,6 +6949,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;
>>         switch ((enum ovs_action_attr)type) {
>>       case OVS_ACTION_ATTR_OUTPUT:
>> @@ -6975,6 +6991,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;
>>   @@ -6984,10 +7003,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:
>> @@ -7007,7 +7032,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;
>> +                if (packet_dropped) {
>> + COVERAGE_ADD(datapath_drop_tunnel_pop_error,
>> +                                     packet_dropped);
>> +                }
>>                   if (dp_packet_batch_is_empty(packets_)) {
>>                       return;
>>                   }
>> @@ -7022,6 +7053,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;
>>   @@ -7066,6 +7102,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:
>> @@ -7089,6 +7128,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;
>>   @@ -7242,6 +7283,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 a18fb1b..112e9d1 100644
>> --- a/lib/dpif.c
>> +++ b/lib/dpif.c
>> @@ -1267,6 +1267,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();
>>       }
>> @@ -1872,6 +1873,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 475d5a6..4b9a434 100644
>> --- a/lib/dpif.h
>> +++ b/lib/dpif.h
>> @@ -888,6 +888,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..e243e89 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,72 @@
>>   #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 +688,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);
>>                       dp_packet_delete(packet);
>>                   }
>>                   return;
>> @@ -749,6 +817,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 +1034,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 +1059,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 3a28877..0dbb6d9 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_unspec(actions, OVS_ACTION_ATTR_DROP,
>> +                          &drop_action, sizeof 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 5cee37f..1a9c6fe 100644
>> --- a/ofproto/ofproto-dpif-xlate.c
>> +++ b/ofproto/ofproto-dpif-xlate.c
>> @@ -444,6 +444,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";
>>   }
>> @@ -5943,6 +5949,13 @@ 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_unspec(odp_actions, OVS_ACTION_ATTR_DROP,
>> +                      &error, sizeof error);
>> +
>> +}
>> +
>> +static void
>>   put_ct_helper(struct xlate_ctx *ctx,
>>                 struct ofpbuf *odp_actions, struct ofpact_conntrack 
>> *ofc)
>>   {
>> @@ -7532,9 +7545,10 @@ 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)
>> -            && (!in_port || may_receive(in_port, &ctx))) {
>> +        if (!ecn_drop &&
>> +                (!in_port || may_receive(in_port, &ctx))) {
>>               const struct ofpact *ofpacts;
>>               size_t ofpacts_len;
>>   @@ -7573,6 +7587,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. */
>> @@ -7672,6 +7688,20 @@ 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);
>> +    }
>> +
>> +
>>       return ctx.error;
>>   }
>>   diff --git a/ofproto/ofproto-dpif-xlate.h 
>> b/ofproto/ofproto-dpif-xlate.h
>> index 5a51d7b..69b758b 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,
>> +    XLATE_MAX,
>>   };
>>     const char *xlate_strerror(enum xlate_error error);
>> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
>> index db461ac..884ef52 100644
>> --- a/ofproto/ofproto-dpif.c
>> +++ b/ofproto/ofproto-dpif.c
>> @@ -827,6 +827,11 @@ 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.
>> @@ -1440,6 +1445,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")
>> +
>>     /* 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 ea16532..dd67b57 100644
>> --- a/tests/automake.mk
>> +++ b/tests/automake.mk
>> @@ -109,7 +109,8 @@ TESTSUITE_AT = \
>>       tests/ovn-controller-vtep.at \
>>       tests/mcast-snooping.at \
>>       tests/packet-type-aware.at \
>> -    tests/nsh.at
>> +    tests/nsh.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 039ee97..e6e0ed8 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..b94354d
>> --- /dev/null
>> +++ b/tests/drop-stats.at
>> @@ -0,0 +1,211 @@
>> +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 
>> 1e2ce92a669e3a6dd2099cab0800450000548a53400040011addc0a80a0ac0a80a1e08006f200a4d0001fc509a58000000002715020000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637
>> +    ovs-appctl netdev-dummy/receive p1 
>> 1e2ce92a669e3a6dd2099cab0800450000548a53400040011addc0a80a0ac0a80a1e08006f200a4d0001fc509a58000000002715020000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637
>> +    ovs-appctl netdev-dummy/receive p1
>> +1e2ce92a669e3a6dd2099cab0800450000548a53400040011addc0a80a0ac0a80a1e080
>> +06f200a4d0001fc509a58000000002715020000000000101112131415161718191a1b1c
>> +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
>> +1e2ce92a669e3a6dd2099cab0800450000548a53400040011addc0a80a0ac0a80a1e080
>> +06f200a4d0001fc509a58000000002715020000000000101112131415161718191a1b1c
>> +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
>> +1e2ce92a669e3a6dd2099cab0800450000548a53400040011addc0a80a0ac0a80a1e080
>> +06f200a4d0001fc509a58000000002715020000000000101112131415161718191a1b1c
>> +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
>> +1e2ce92a669e3a6dd2099cab0800450000548a53400040011addc0a80a0ac0a80a1e080
>> +06f200a4d0001fc509a58000000002715020000000000101112131415161718191a1b1c
>> +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 9b0231b..5e776a6 100644
>> --- a/tests/ofproto-dpif.at
>> +++ b/tests/ofproto-dpif.at
>> @@ -9384,7 +9384,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:00: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:00: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:00: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 
>> 'aa55aa550000001b213cab6408004500007079464000402fba600101025c0101025820000800000001c845000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
>> +
>> +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 
>> 'aa55aa550000001b213cab6408004503007079464000402fba600101025c0101025820000800000001c845000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
>> +
>> +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 
>> 'aa55aa550000001b213cab6408004500007e79464000402fba550101025c0101025820000800000001c8fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
>>   @@ -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,type=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,type=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=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..8b663e9 100644
>> --- a/tests/tunnel.at
>> +++ b/tests/tunnel.at
>> @@ -102,9 +102,10 @@ 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),eth(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],
>> +AT_CHECK([tail -3 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
>>   Datapath actions: drop
>> +Translation failed (Congestion Drop), packet is dropped.
>>   ])
>>   OVS_VSWITCHD_STOP(["/dropping tunnel packet marked ECN CE but is 
>> not ECN capable/d"])
>>   AT_CLEANUP
>> @@ -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 
>> 'aa55aa550001f8bc124434b6080045000054ba20000040018486010103580101037001004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
>> +
>> +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
>



More information about the dev mailing list