Skip to content

Commit a13a020

Browse files
Anju Thomasrohbaskeshugupta1
authored andcommitted
userspace: Improved packet drop statistics.
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 Co-authored-by: Rohith Basavaraja <rohith.basavaraja@gmail.com> Co-authored-by: Keshav Gupta <keshugupta1@gmail.com> Signed-off-by: Anju Thomas <anju.thomas@ericsson.com> Signed-off-by: Rohith Basavaraja <rohith.basavaraja@gmail.com> Signed-off-by: Keshav Gupta <keshugupta1@gmail.com> Acked-by: Eelco Chaudron <echaudro@redhat.com Acked-by: Ben Pfaff <blp@ovn.org> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
1 parent 924d94a commit a13a020

20 files changed

+454
-24
lines changed

datapath/linux/compat/include/linux/openvswitch.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,28 @@ enum ovs_tunnel_key_attr {
409409

410410
#define OVS_TUNNEL_KEY_ATTR_MAX (__OVS_TUNNEL_KEY_ATTR_MAX - 1)
411411

412+
/**
413+
* enum xlate_error - Different types of error during translation
414+
*/
415+
416+
#ifndef __KERNEL__
417+
enum xlate_error {
418+
XLATE_OK = 0,
419+
XLATE_BRIDGE_NOT_FOUND,
420+
XLATE_RECURSION_TOO_DEEP,
421+
XLATE_TOO_MANY_RESUBMITS,
422+
XLATE_STACK_TOO_DEEP,
423+
XLATE_NO_RECIRCULATION_CONTEXT,
424+
XLATE_RECIRCULATION_CONFLICT,
425+
XLATE_TOO_MANY_MPLS_LABELS,
426+
XLATE_INVALID_TUNNEL_METADATA,
427+
XLATE_UNSUPPORTED_PACKET_TYPE,
428+
XLATE_CONGESTION_DROP,
429+
XLATE_FORWARDING_DISABLED,
430+
XLATE_MAX,
431+
};
432+
#endif
433+
412434
/**
413435
* enum ovs_frag_type - IPv4 and IPv6 fragment type
414436
* @OVS_FRAG_TYPE_NONE: Packet is not a fragment.
@@ -965,6 +987,7 @@ struct check_pkt_len_arg {
965987
* @OVS_ACTION_ATTR_CHECK_PKT_LEN: Check the packet length and execute a set
966988
* of actions if greater than the specified packet length, else execute
967989
* another set of actions.
990+
* @OVS_ACTION_ATTR_DROP: Explicit drop action.
968991
*/
969992

970993
enum ovs_action_attr {
@@ -997,6 +1020,7 @@ enum ovs_action_attr {
9971020
#ifndef __KERNEL__
9981021
OVS_ACTION_ATTR_TUNNEL_PUSH, /* struct ovs_action_push_tnl*/
9991022
OVS_ACTION_ATTR_TUNNEL_POP, /* u32 port number. */
1023+
OVS_ACTION_ATTR_DROP, /* u32 xlate_error. */
10001024
#endif
10011025
__OVS_ACTION_ATTR_MAX, /* Nothing past this will be accepted
10021026
* from userspace. */

lib/dpif-netdev.c

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,17 @@ enum { MAX_METERS = 65536 }; /* Maximum number of meters. */
102102
enum { MAX_BANDS = 8 }; /* Maximum number of bands / meter. */
103103
enum { N_METER_LOCKS = 64 }; /* Maximum number of meters. */
104104

105+
COVERAGE_DEFINE(datapath_drop_meter);
106+
COVERAGE_DEFINE(datapath_drop_upcall_error);
107+
COVERAGE_DEFINE(datapath_drop_lock_error);
108+
COVERAGE_DEFINE(datapath_drop_userspace_action_error);
109+
COVERAGE_DEFINE(datapath_drop_tunnel_push_error);
110+
COVERAGE_DEFINE(datapath_drop_tunnel_pop_error);
111+
COVERAGE_DEFINE(datapath_drop_recirc_error);
112+
COVERAGE_DEFINE(datapath_drop_invalid_port);
113+
COVERAGE_DEFINE(datapath_drop_invalid_tnl_port);
114+
COVERAGE_DEFINE(datapath_drop_rx_invalid_packet);
115+
105116
/* Protects against changes to 'dp_netdevs'. */
106117
static struct ovs_mutex dp_netdev_mutex = OVS_MUTEX_INITIALIZER;
107118

@@ -5770,7 +5781,7 @@ dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_,
57705781
band = &meter->bands[exceeded_band[j]];
57715782
band->packet_count += 1;
57725783
band->byte_count += dp_packet_size(packet);
5773-
5784+
COVERAGE_INC(datapath_drop_meter);
57745785
dp_packet_delete(packet);
57755786
} else {
57765787
/* Meter accepts packet. */
@@ -6520,6 +6531,7 @@ dfc_processing(struct dp_netdev_pmd_thread *pmd,
65206531

65216532
if (OVS_UNLIKELY(dp_packet_size(packet) < ETH_HEADER_LEN)) {
65226533
dp_packet_delete(packet);
6534+
COVERAGE_INC(datapath_drop_rx_invalid_packet);
65236535
continue;
65246536
}
65256537

@@ -6640,6 +6652,7 @@ handle_packet_upcall(struct dp_netdev_pmd_thread *pmd,
66406652
put_actions);
66416653
if (OVS_UNLIKELY(error && error != ENOSPC)) {
66426654
dp_packet_delete(packet);
6655+
COVERAGE_INC(datapath_drop_upcall_error);
66436656
return error;
66446657
}
66456658

@@ -6770,6 +6783,7 @@ fast_path_processing(struct dp_netdev_pmd_thread *pmd,
67706783
DP_PACKET_BATCH_FOR_EACH (i, packet, packets_) {
67716784
if (OVS_UNLIKELY(!rules[i])) {
67726785
dp_packet_delete(packet);
6786+
COVERAGE_INC(datapath_drop_lock_error);
67736787
upcall_fail_cnt++;
67746788
}
67756789
}
@@ -7039,6 +7053,7 @@ dp_execute_userspace_action(struct dp_netdev_pmd_thread *pmd,
70397053
actions->data, actions->size);
70407054
} else if (should_steal) {
70417055
dp_packet_delete(packet);
7056+
COVERAGE_INC(datapath_drop_userspace_action_error);
70427057
}
70437058
}
70447059

@@ -7053,6 +7068,7 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
70537068
struct dp_netdev *dp = pmd->dp;
70547069
int type = nl_attr_type(a);
70557070
struct tx_port *p;
7071+
uint32_t packet_count, packets_dropped;
70567072

70577073
switch ((enum ovs_action_attr)type) {
70587074
case OVS_ACTION_ATTR_OUTPUT:
@@ -7094,6 +7110,9 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
70947110
dp_packet_batch_add(&p->output_pkts, packet);
70957111
}
70967112
return;
7113+
} else {
7114+
COVERAGE_ADD(datapath_drop_invalid_port,
7115+
dp_packet_batch_size(packets_));
70977116
}
70987117
break;
70997118

@@ -7106,7 +7125,11 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
71067125
break;
71077126
}
71087127
dp_packet_batch_apply_cutlen(packets_);
7109-
push_tnl_action(pmd, a, packets_);
7128+
packet_count = dp_packet_batch_size(packets_);
7129+
if (push_tnl_action(pmd, a, packets_)) {
7130+
COVERAGE_ADD(datapath_drop_tunnel_push_error,
7131+
packet_count);
7132+
}
71107133
return;
71117134

71127135
case OVS_ACTION_ATTR_TUNNEL_POP:
@@ -7126,7 +7149,14 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
71267149

71277150
dp_packet_batch_apply_cutlen(packets_);
71287151

7152+
packet_count = dp_packet_batch_size(packets_);
71297153
netdev_pop_header(p->port->netdev, packets_);
7154+
packets_dropped =
7155+
packet_count - dp_packet_batch_size(packets_);
7156+
if (packets_dropped) {
7157+
COVERAGE_ADD(datapath_drop_tunnel_pop_error,
7158+
packets_dropped);
7159+
}
71307160
if (dp_packet_batch_is_empty(packets_)) {
71317161
return;
71327162
}
@@ -7141,6 +7171,11 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
71417171
(*depth)--;
71427172
return;
71437173
}
7174+
COVERAGE_ADD(datapath_drop_invalid_tnl_port,
7175+
dp_packet_batch_size(packets_));
7176+
} else {
7177+
COVERAGE_ADD(datapath_drop_recirc_error,
7178+
dp_packet_batch_size(packets_));
71447179
}
71457180
break;
71467181

@@ -7185,6 +7220,8 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
71857220

71867221
return;
71877222
}
7223+
COVERAGE_ADD(datapath_drop_lock_error,
7224+
dp_packet_batch_size(packets_));
71887225
break;
71897226

71907227
case OVS_ACTION_ATTR_RECIRC:
@@ -7208,6 +7245,8 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
72087245
return;
72097246
}
72107247

7248+
COVERAGE_ADD(datapath_drop_recirc_error,
7249+
dp_packet_batch_size(packets_));
72117250
VLOG_WARN("Packet dropped. Max recirculation depth exceeded.");
72127251
break;
72137252

@@ -7365,6 +7404,7 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
73657404
case OVS_ACTION_ATTR_POP_NSH:
73667405
case OVS_ACTION_ATTR_CT_CLEAR:
73677406
case OVS_ACTION_ATTR_CHECK_PKT_LEN:
7407+
case OVS_ACTION_ATTR_DROP:
73687408
case __OVS_ACTION_ATTR_MAX:
73697409
OVS_NOT_REACHED();
73707410
}

lib/dpif.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,7 @@ dpif_execute_helper_cb(void *aux_, struct dp_packet_batch *packets_,
12831283
case OVS_ACTION_ATTR_CT_CLEAR:
12841284
case OVS_ACTION_ATTR_UNSPEC:
12851285
case OVS_ACTION_ATTR_CHECK_PKT_LEN:
1286+
case OVS_ACTION_ATTR_DROP:
12861287
case __OVS_ACTION_ATTR_MAX:
12871288
OVS_NOT_REACHED();
12881289
}
@@ -1888,6 +1889,12 @@ dpif_supports_tnl_push_pop(const struct dpif *dpif)
18881889
return dpif_is_netdev(dpif);
18891890
}
18901891

1892+
bool
1893+
dpif_supports_explicit_drop_action(const struct dpif *dpif)
1894+
{
1895+
return dpif_is_netdev(dpif);
1896+
}
1897+
18911898
/* Meters */
18921899
void
18931900
dpif_meter_get_features(const struct dpif *dpif,

lib/dpif.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,7 @@ int dpif_get_pmds_for_port(const struct dpif * dpif, odp_port_t port_no,
906906

907907
char *dpif_get_dp_version(const struct dpif *);
908908
bool dpif_supports_tnl_push_pop(const struct dpif *);
909+
bool dpif_supports_explicit_drop_action(const struct dpif *);
909910

910911
/* Log functions. */
911912
struct vlog_module;

lib/odp-execute.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <stdlib.h>
2626
#include <string.h>
2727

28+
#include "coverage.h"
2829
#include "dp-packet.h"
2930
#include "dpif.h"
3031
#include "netlink.h"
@@ -36,6 +37,72 @@
3637
#include "util.h"
3738
#include "csum.h"
3839
#include "conntrack.h"
40+
#include "openvswitch/vlog.h"
41+
42+
VLOG_DEFINE_THIS_MODULE(odp_execute);
43+
COVERAGE_DEFINE(datapath_drop_sample_error);
44+
COVERAGE_DEFINE(datapath_drop_nsh_decap_error);
45+
COVERAGE_DEFINE(drop_action_of_pipeline);
46+
COVERAGE_DEFINE(drop_action_bridge_not_found);
47+
COVERAGE_DEFINE(drop_action_recursion_too_deep);
48+
COVERAGE_DEFINE(drop_action_too_many_resubmit);
49+
COVERAGE_DEFINE(drop_action_stack_too_deep);
50+
COVERAGE_DEFINE(drop_action_no_recirculation_context);
51+
COVERAGE_DEFINE(drop_action_recirculation_conflict);
52+
COVERAGE_DEFINE(drop_action_too_many_mpls_labels);
53+
COVERAGE_DEFINE(drop_action_invalid_tunnel_metadata);
54+
COVERAGE_DEFINE(drop_action_unsupported_packet_type);
55+
COVERAGE_DEFINE(drop_action_congestion);
56+
COVERAGE_DEFINE(drop_action_forwarding_disabled);
57+
58+
static void
59+
dp_update_drop_action_counter(enum xlate_error drop_reason,
60+
int delta)
61+
{
62+
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
63+
64+
switch (drop_reason) {
65+
case XLATE_OK:
66+
COVERAGE_ADD(drop_action_of_pipeline, delta);
67+
break;
68+
case XLATE_BRIDGE_NOT_FOUND:
69+
COVERAGE_ADD(drop_action_bridge_not_found, delta);
70+
break;
71+
case XLATE_RECURSION_TOO_DEEP:
72+
COVERAGE_ADD(drop_action_recursion_too_deep, delta);
73+
break;
74+
case XLATE_TOO_MANY_RESUBMITS:
75+
COVERAGE_ADD(drop_action_too_many_resubmit, delta);
76+
break;
77+
case XLATE_STACK_TOO_DEEP:
78+
COVERAGE_ADD(drop_action_stack_too_deep, delta);
79+
break;
80+
case XLATE_NO_RECIRCULATION_CONTEXT:
81+
COVERAGE_ADD(drop_action_no_recirculation_context, delta);
82+
break;
83+
case XLATE_RECIRCULATION_CONFLICT:
84+
COVERAGE_ADD(drop_action_recirculation_conflict, delta);
85+
break;
86+
case XLATE_TOO_MANY_MPLS_LABELS:
87+
COVERAGE_ADD(drop_action_too_many_mpls_labels, delta);
88+
break;
89+
case XLATE_INVALID_TUNNEL_METADATA:
90+
COVERAGE_ADD(drop_action_invalid_tunnel_metadata, delta);
91+
break;
92+
case XLATE_UNSUPPORTED_PACKET_TYPE:
93+
COVERAGE_ADD(drop_action_unsupported_packet_type, delta);
94+
break;
95+
case XLATE_CONGESTION_DROP:
96+
COVERAGE_ADD(drop_action_congestion, delta);
97+
break;
98+
case XLATE_FORWARDING_DISABLED:
99+
COVERAGE_ADD(drop_action_forwarding_disabled, delta);
100+
break;
101+
case XLATE_MAX:
102+
default:
103+
VLOG_ERR_RL(&rl, "Invalid Drop reason type: %d", drop_reason);
104+
}
105+
}
39106

40107
/* Masked copy of an ethernet address. 'src' is already properly masked. */
41108
static void
@@ -621,6 +688,7 @@ odp_execute_sample(void *dp, struct dp_packet *packet, bool steal,
621688
case OVS_SAMPLE_ATTR_PROBABILITY:
622689
if (random_uint32() >= nl_attr_get_u32(a)) {
623690
if (steal) {
691+
COVERAGE_INC(datapath_drop_sample_error);
624692
dp_packet_delete(packet);
625693
}
626694
return;
@@ -749,6 +817,7 @@ requires_datapath_assistance(const struct nlattr *a)
749817
case OVS_ACTION_ATTR_POP_NSH:
750818
case OVS_ACTION_ATTR_CT_CLEAR:
751819
case OVS_ACTION_ATTR_CHECK_PKT_LEN:
820+
case OVS_ACTION_ATTR_DROP:
752821
return false;
753822

754823
case OVS_ACTION_ATTR_UNSPEC:
@@ -965,6 +1034,7 @@ odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
9651034
if (pop_nsh(packet)) {
9661035
dp_packet_batch_refill(batch, packet, i);
9671036
} else {
1037+
COVERAGE_INC(datapath_drop_nsh_decap_error);
9681038
dp_packet_delete(packet);
9691039
}
9701040
}
@@ -989,6 +1059,14 @@ odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
9891059
}
9901060
break;
9911061

1062+
case OVS_ACTION_ATTR_DROP:{
1063+
const enum xlate_error *drop_reason = nl_attr_get(a);
1064+
1065+
dp_update_drop_action_counter(*drop_reason,
1066+
dp_packet_batch_size(batch));
1067+
dp_packet_delete_batch(batch, steal);
1068+
return;
1069+
}
9921070
case OVS_ACTION_ATTR_OUTPUT:
9931071
case OVS_ACTION_ATTR_TUNNEL_PUSH:
9941072
case OVS_ACTION_ATTR_TUNNEL_POP:

lib/odp-util.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ odp_action_len(uint16_t type)
141141
case OVS_ACTION_ATTR_PUSH_NSH: return ATTR_LEN_VARIABLE;
142142
case OVS_ACTION_ATTR_POP_NSH: return 0;
143143
case OVS_ACTION_ATTR_CHECK_PKT_LEN: return ATTR_LEN_VARIABLE;
144+
case OVS_ACTION_ATTR_DROP: return sizeof(uint32_t);
144145

145146
case OVS_ACTION_ATTR_UNSPEC:
146147
case __OVS_ACTION_ATTR_MAX:
@@ -1238,6 +1239,9 @@ format_odp_action(struct ds *ds, const struct nlattr *a,
12381239
case OVS_ACTION_ATTR_CHECK_PKT_LEN:
12391240
format_odp_check_pkt_len_action(ds, a, portno_names);
12401241
break;
1242+
case OVS_ACTION_ATTR_DROP:
1243+
ds_put_cstr(ds, "drop");
1244+
break;
12411245
case OVS_ACTION_ATTR_UNSPEC:
12421246
case __OVS_ACTION_ATTR_MAX:
12431247
default:
@@ -2575,6 +2579,7 @@ odp_actions_from_string(const char *s, const struct simap *port_names,
25752579
size_t old_size;
25762580

25772581
if (!strcasecmp(s, "drop")) {
2582+
nl_msg_put_u32(actions, OVS_ACTION_ATTR_DROP, XLATE_OK);
25782583
return 0;
25792584
}
25802585

ofproto/ofproto-dpif-ipfix.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3016,6 +3016,7 @@ dpif_ipfix_read_actions(const struct flow *flow,
30163016
case OVS_ACTION_ATTR_POP_NSH:
30173017
case OVS_ACTION_ATTR_CHECK_PKT_LEN:
30183018
case OVS_ACTION_ATTR_UNSPEC:
3019+
case OVS_ACTION_ATTR_DROP:
30193020
case __OVS_ACTION_ATTR_MAX:
30203021
default:
30213022
break;

ofproto/ofproto-dpif-sflow.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,7 @@ dpif_sflow_read_actions(const struct flow *flow,
12241224
case OVS_ACTION_ATTR_POP_NSH:
12251225
case OVS_ACTION_ATTR_UNSPEC:
12261226
case OVS_ACTION_ATTR_CHECK_PKT_LEN:
1227+
case OVS_ACTION_ATTR_DROP:
12271228
case __OVS_ACTION_ATTR_MAX:
12281229
default:
12291230
break;

0 commit comments

Comments
 (0)