@@ -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*/
@@ -102,6 +102,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;
@@ -5650,7 +5661,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. */
@@ -6406,6 +6417,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;
}
@@ -6525,6 +6537,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;
}
@@ -6655,6 +6668,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++;
}
}
@@ -6924,6 +6938,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);
}
}
@@ -6938,6 +6953,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:
@@ -6979,6 +6995,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;
@@ -6988,10 +7007,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:
@@ -7011,7 +7036,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;
}
@@ -7026,6 +7057,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;
@@ -7070,6 +7106,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:
@@ -7093,6 +7132,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;
@@ -7246,6 +7287,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();
}
@@ -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,
@@ -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;
@@ -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);
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:
@@ -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;
}
@@ -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;
@@ -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;
@@ -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_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)
{
@@ -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;
@@ -7585,6 +7600,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 +7707,18 @@ 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;
}
@@ -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);
@@ -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);
@@ -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 */
@@ -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 = \
@@ -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
new file mode 100644
@@ -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 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
@@ -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@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@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@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
])
@@ -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])
@@ -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