netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/7] openvswitch: add drop reasons
@ 2023-07-22  9:42 Adrian Moreno
  2023-07-22  9:42 ` [PATCH net-next 1/7] net: openvswitch: add datapath flow drop reason Adrian Moreno
                   ` (7 more replies)
  0 siblings, 8 replies; 15+ messages in thread
From: Adrian Moreno @ 2023-07-22  9:42 UTC (permalink / raw)
  To: netdev; +Cc: Adrian Moreno, dev, aconole, i.maximets, eric

There is currently a gap in drop visibility in the openvswitch module.
This series tries to improve this by adding a new drop reason subsystem
for OVS.

Apart from adding a new drop reasson subsystem and some common drop
reasons, this series takes Eric's preliminary work [1] on adding an
explicit drop action and integrates it into the same subsystem.

This series also adds some selftests and so it requires [2] to be
applied first.

A limitation of this series is that it does not report upcall errors.
The reason is that there could be many sources of upcall drops and the
most common one, which is the netlink buffer overflow, cannot be
reported via kfree_skb() because the skb is freed in the netlink layer
(see [3]). Therefore, using a reason for the rare events and not the
common one would be even more misleading. I'd propose we add (in a
follow up patch) a tracepoint to better report upcall errors.

[1] https://lore.kernel.org/netdev/202306300609.tdRdZscy-lkp@intel.com/T/
[2] https://lore.kernel.org/all/9375ccbc-dd40-9998-dde5-c94e4e28f4f1@redhat.com/T/ 
[3] commit 1100248a5c5c ("openvswitch: Fix double reporting of drops in dropwatch")

Adrian Moreno (6):
  net: openvswitch: add datapath flow drop reason
  net: openvswitch: add meter drop reason
  net: openvswitch: add misc error drop reasons
  selftests: openvswitch: support key masks
  selftests: openvswitch: add drop reason testcase
  selftests: openvswitch: add explicit drop testcase

Eric Garver (1):
  net: openvswitch: add explicit drop action

 include/net/dropreason.h                      |   6 +
 include/uapi/linux/openvswitch.h              |   2 +
 net/openvswitch/actions.c                     |  40 ++++--
 net/openvswitch/conntrack.c                   |   3 +-
 net/openvswitch/datapath.c                    |  16 +++
 net/openvswitch/drop.h                        |  33 +++++
 net/openvswitch/flow_netlink.c                |   8 +-
 .../selftests/net/openvswitch/openvswitch.sh  |  92 +++++++++++++-
 .../selftests/net/openvswitch/ovs-dpctl.py    | 115 ++++++++++++------
 9 files changed, 267 insertions(+), 48 deletions(-)
 create mode 100644 net/openvswitch/drop.h

-- 
2.41.0


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH net-next 1/7] net: openvswitch: add datapath flow drop reason
  2023-07-22  9:42 [PATCH net-next 0/7] openvswitch: add drop reasons Adrian Moreno
@ 2023-07-22  9:42 ` Adrian Moreno
  2023-07-22  9:42 ` [PATCH net-next 2/7] net: openvswitch: add explicit drop action Adrian Moreno
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Adrian Moreno @ 2023-07-22  9:42 UTC (permalink / raw)
  To: netdev; +Cc: Adrian Moreno, dev, aconole, i.maximets, eric

Create a new drop reason subsystem for openvswitch and add the first
drop reason to represent flow drops.

A flow drop happens when a flow has an empty action-set or there is no
action that consumes the packet (output, userspace, recirc, etc).

Implementation-wise, most of these skb-consuming actions already call
"consume_skb" internally and return directly from within the
do_execute_actions() loop so with minimal changes we can assume that
any skb that exits the loop normally is a packet drop.

Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
---
 include/net/dropreason.h   |  6 ++++++
 net/openvswitch/actions.c  | 12 ++++++++++--
 net/openvswitch/datapath.c | 16 ++++++++++++++++
 net/openvswitch/drop.h     | 24 ++++++++++++++++++++++++
 4 files changed, 56 insertions(+), 2 deletions(-)
 create mode 100644 net/openvswitch/drop.h

diff --git a/include/net/dropreason.h b/include/net/dropreason.h
index 685fb37df8e8..56cb7be92244 100644
--- a/include/net/dropreason.h
+++ b/include/net/dropreason.h
@@ -23,6 +23,12 @@ enum skb_drop_reason_subsys {
 	 */
 	SKB_DROP_REASON_SUBSYS_MAC80211_MONITOR,
 
+	/**
+	 * @SKB_DROP_REASON_SUBSYS_OPENVSWITCH: openvswitch drop reasons,
+	 * see net/openvswitch/drop.h
+	 */
+	SKB_DROP_REASON_SUBSYS_OPENVSWITCH,
+
 	/** @SKB_DROP_REASON_SUBSYS_NUM: number of subsystems defined */
 	SKB_DROP_REASON_SUBSYS_NUM
 };
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index cab1e02b63e0..af676dcac2b4 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -27,6 +27,7 @@
 #include <net/sctp/checksum.h>
 
 #include "datapath.h"
+#include "drop.h"
 #include "flow.h"
 #include "conntrack.h"
 #include "vport.h"
@@ -1036,7 +1037,7 @@ static int sample(struct datapath *dp, struct sk_buff *skb,
 	if ((arg->probability != U32_MAX) &&
 	    (!arg->probability || get_random_u32() > arg->probability)) {
 		if (last)
-			consume_skb(skb);
+			kfree_skb_reason(skb, OVS_DROP_FLOW);
 		return 0;
 	}
 
@@ -1297,6 +1298,9 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
 		if (trace_ovs_do_execute_action_enabled())
 			trace_ovs_do_execute_action(dp, skb, key, a, rem);
 
+		/* Actions that rightfully have to consume the skb should do it
+		 * and return directly.
+		 */
 		switch (nla_type(a)) {
 		case OVS_ACTION_ATTR_OUTPUT: {
 			int port = nla_get_u32(a);
@@ -1332,6 +1336,10 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
 			output_userspace(dp, skb, key, a, attr,
 						     len, OVS_CB(skb)->cutlen);
 			OVS_CB(skb)->cutlen = 0;
+			if (nla_is_last(a, rem)) {
+				consume_skb(skb);
+				return 0;
+			}
 			break;
 
 		case OVS_ACTION_ATTR_HASH:
@@ -1485,7 +1493,7 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
 		}
 	}
 
-	consume_skb(skb);
+	kfree_skb_reason(skb, OVS_DROP_FLOW);
 	return 0;
 }
 
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index a6d2a0b1aa21..f21ee771a4b3 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -41,6 +41,7 @@
 #include <net/pkt_cls.h>
 
 #include "datapath.h"
+#include "drop.h"
 #include "flow.h"
 #include "flow_table.h"
 #include "flow_netlink.h"
@@ -2702,6 +2703,17 @@ static struct pernet_operations ovs_net_ops = {
 	.size = sizeof(struct ovs_net),
 };
 
+static const char * const ovs_drop_reasons[] = {
+#define S(x)	#x,
+	OVS_DROP_REASONS(S)
+#undef S
+};
+
+static struct drop_reason_list drop_reason_list_ovs = {
+	.reasons = ovs_drop_reasons,
+	.n_reasons = ARRAY_SIZE(ovs_drop_reasons),
+};
+
 static int __init dp_init(void)
 {
 	int err;
@@ -2743,6 +2755,9 @@ static int __init dp_init(void)
 	if (err < 0)
 		goto error_unreg_netdev;
 
+	drop_reasons_register_subsys(SKB_DROP_REASON_SUBSYS_OPENVSWITCH,
+				     &drop_reason_list_ovs);
+
 	return 0;
 
 error_unreg_netdev:
@@ -2769,6 +2784,7 @@ static void dp_cleanup(void)
 	ovs_netdev_exit();
 	unregister_netdevice_notifier(&ovs_dp_device_notifier);
 	unregister_pernet_device(&ovs_net_ops);
+	drop_reasons_unregister_subsys(SKB_DROP_REASON_SUBSYS_OPENVSWITCH);
 	rcu_barrier();
 	ovs_vport_exit();
 	ovs_flow_exit();
diff --git a/net/openvswitch/drop.h b/net/openvswitch/drop.h
new file mode 100644
index 000000000000..cdd10629c6be
--- /dev/null
+++ b/net/openvswitch/drop.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * OpenvSwitch drop reason list.
+ */
+
+#ifndef OPENVSWITCH_DROP_H
+#define OPENVSWITCH_DROP_H
+#include <net/dropreason.h>
+
+#define OVS_DROP_REASONS(R)			\
+	R(OVS_DROP_FLOW)		        \
+	/* deliberate comment for trailing \ */
+
+enum ovs_drop_reason {
+	__OVS_DROP_REASON = SKB_DROP_REASON_SUBSYS_OPENVSWITCH <<
+				SKB_DROP_REASON_SUBSYS_SHIFT,
+#define ENUM(x) x,
+	OVS_DROP_REASONS(ENUM)
+#undef ENUM
+
+	OVS_DROP_MAX,
+};
+
+#endif /* OPENVSWITCH_DROP_H */
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 2/7] net: openvswitch: add explicit drop action
  2023-07-22  9:42 [PATCH net-next 0/7] openvswitch: add drop reasons Adrian Moreno
  2023-07-22  9:42 ` [PATCH net-next 1/7] net: openvswitch: add datapath flow drop reason Adrian Moreno
@ 2023-07-22  9:42 ` Adrian Moreno
  2023-07-24 14:47   ` Aaron Conole
  2023-07-22  9:42 ` [PATCH net-next 3/7] net: openvswitch: add meter drop reason Adrian Moreno
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Adrian Moreno @ 2023-07-22  9:42 UTC (permalink / raw)
  To: netdev; +Cc: Eric Garver, dev, aconole, i.maximets, Adrian Moreno

From: Eric Garver <eric@garver.life>

This adds an explicit drop action. This is used by OVS to drop packets
for which it cannot determine what to do. An explicit action in the
kernel allows passing the reason _why_ the packet is being dropped or
zero to indicate no particular error happened (i.e: OVS intentionally
dropped the packet).

Since the error codes coming from userspace mean nothing for the kernel,
we squash all of them into only two drop reasons:
- OVS_DROP_EXPLICIT_ACTION_ERROR to indicate a non-zero value was passed
- OVS_DROP_EXPLICIT_ACTION to indicate a zero value was passed (no
  error)

e.g. trace all OVS dropped skbs

 # perf trace -e skb:kfree_skb --filter="reason >= 0x30000"
 [..]
 106.023 ping/2465 skb:kfree_skb(skbaddr: 0xffffa0e8765f2000, \
  location:0xffffffffc0d9b462, protocol: 2048, reason: 196610)

reason: 196610 --> 0x30002 (OVS_DROP_EXPLICIT_ACTION)

Signed-off-by: Eric Garver <eric@garver.life>
Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
---
 include/uapi/linux/openvswitch.h                     | 2 ++
 net/openvswitch/actions.c                            | 9 +++++++++
 net/openvswitch/drop.h                               | 2 ++
 net/openvswitch/flow_netlink.c                       | 8 +++++++-
 tools/testing/selftests/net/openvswitch/ovs-dpctl.py | 3 +++
 5 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index e94870e77ee9..efc82c318fa2 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -965,6 +965,7 @@ struct check_pkt_len_arg {
  * start of the packet or at the start of the l3 header depending on the value
  * of l3 tunnel flag in the tun_flags field of OVS_ACTION_ATTR_ADD_MPLS
  * argument.
+ * @OVS_ACTION_ATTR_DROP: Explicit drop action.
  *
  * Only a single header can be set with a single %OVS_ACTION_ATTR_SET.  Not all
  * fields within a header are modifiable, e.g. the IPv4 protocol and fragment
@@ -1002,6 +1003,7 @@ enum ovs_action_attr {
 	OVS_ACTION_ATTR_CHECK_PKT_LEN, /* Nested OVS_CHECK_PKT_LEN_ATTR_*. */
 	OVS_ACTION_ATTR_ADD_MPLS,     /* struct ovs_action_add_mpls. */
 	OVS_ACTION_ATTR_DEC_TTL,      /* Nested OVS_DEC_TTL_ATTR_*. */
+	OVS_ACTION_ATTR_DROP,         /* u32 error code. */
 
 	__OVS_ACTION_ATTR_MAX,	      /* Nothing past this will be accepted
 				       * from userspace. */
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index af676dcac2b4..194379d58b62 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -1485,6 +1485,15 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
 				return dec_ttl_exception_handler(dp, skb,
 								 key, a);
 			break;
+
+		case OVS_ACTION_ATTR_DROP: {
+			enum ovs_drop_reason reason = nla_get_u32(a)
+				? OVS_DROP_EXPLICIT_ACTION_ERROR
+				: OVS_DROP_EXPLICIT_ACTION;
+
+			kfree_skb_reason(skb, reason);
+			return 0;
+		}
 		}
 
 		if (unlikely(err)) {
diff --git a/net/openvswitch/drop.h b/net/openvswitch/drop.h
index cdd10629c6be..f9e9c1610f6b 100644
--- a/net/openvswitch/drop.h
+++ b/net/openvswitch/drop.h
@@ -9,6 +9,8 @@
 
 #define OVS_DROP_REASONS(R)			\
 	R(OVS_DROP_FLOW)		        \
+	R(OVS_DROP_EXPLICIT_ACTION)		\
+	R(OVS_DROP_EXPLICIT_ACTION_ERROR)	\
 	/* deliberate comment for trailing \ */
 
 enum ovs_drop_reason {
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 41116361433d..244280922a14 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -38,6 +38,7 @@
 #include <net/tun_proto.h>
 #include <net/erspan.h>
 
+#include "drop.h"
 #include "flow_netlink.h"
 
 struct ovs_len_tbl {
@@ -61,6 +62,7 @@ static bool actions_may_change_flow(const struct nlattr *actions)
 		case OVS_ACTION_ATTR_RECIRC:
 		case OVS_ACTION_ATTR_TRUNC:
 		case OVS_ACTION_ATTR_USERSPACE:
+		case OVS_ACTION_ATTR_DROP:
 			break;
 
 		case OVS_ACTION_ATTR_CT:
@@ -2394,7 +2396,7 @@ static void ovs_nla_free_nested_actions(const struct nlattr *actions, int len)
 	/* Whenever new actions are added, the need to update this
 	 * function should be considered.
 	 */
-	BUILD_BUG_ON(OVS_ACTION_ATTR_MAX != 23);
+	BUILD_BUG_ON(OVS_ACTION_ATTR_MAX != 24);
 
 	if (!actions)
 		return;
@@ -3182,6 +3184,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
 			[OVS_ACTION_ATTR_CHECK_PKT_LEN] = (u32)-1,
 			[OVS_ACTION_ATTR_ADD_MPLS] = sizeof(struct ovs_action_add_mpls),
 			[OVS_ACTION_ATTR_DEC_TTL] = (u32)-1,
+			[OVS_ACTION_ATTR_DROP] = sizeof(u32),
 		};
 		const struct ovs_action_push_vlan *vlan;
 		int type = nla_type(a);
@@ -3453,6 +3456,9 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
 			skip_copy = true;
 			break;
 
+		case OVS_ACTION_ATTR_DROP:
+			break;
+
 		default:
 			OVS_NLERR(log, "Unknown Action type %d", type);
 			return -EINVAL;
diff --git a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
index 12ba5265b88f..61c4d7b75261 100644
--- a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
+++ b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
@@ -280,6 +280,7 @@ class ovsactions(nla):
         ("OVS_ACTION_ATTR_CHECK_PKT_LEN", "none"),
         ("OVS_ACTION_ATTR_ADD_MPLS", "none"),
         ("OVS_ACTION_ATTR_DEC_TTL", "none"),
+        ("OVS_ACTION_ATTR_DROP", "uint32"),
     )
 
     class ctact(nla):
@@ -426,6 +427,8 @@ class ovsactions(nla):
                     print_str += "recirc(0x%x)" % int(self.get_attr(field[0]))
                 elif field[0] == "OVS_ACTION_ATTR_TRUNC":
                     print_str += "trunc(%d)" % int(self.get_attr(field[0]))
+                elif field[0] == "OVS_ACTION_ATTR_DROP":
+                    print_str += "drop"
             elif field[1] == "flag":
                 if field[0] == "OVS_ACTION_ATTR_CT_CLEAR":
                     print_str += "ct_clear"
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 3/7] net: openvswitch: add meter drop reason
  2023-07-22  9:42 [PATCH net-next 0/7] openvswitch: add drop reasons Adrian Moreno
  2023-07-22  9:42 ` [PATCH net-next 1/7] net: openvswitch: add datapath flow drop reason Adrian Moreno
  2023-07-22  9:42 ` [PATCH net-next 2/7] net: openvswitch: add explicit drop action Adrian Moreno
@ 2023-07-22  9:42 ` Adrian Moreno
  2023-07-22  9:42 ` [PATCH net-next 4/7] net: openvswitch: add misc error drop reasons Adrian Moreno
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Adrian Moreno @ 2023-07-22  9:42 UTC (permalink / raw)
  To: netdev; +Cc: Adrian Moreno, dev, aconole, i.maximets, eric

By using an independent drop reason it makes it easy to ditinguish
between QoS-triggered or flow-triggered drop.

Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
---
 net/openvswitch/actions.c | 2 +-
 net/openvswitch/drop.h    | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 194379d58b62..9279bb186e9f 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -1454,7 +1454,7 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
 
 		case OVS_ACTION_ATTR_METER:
 			if (ovs_meter_execute(dp, skb, key, nla_get_u32(a))) {
-				consume_skb(skb);
+				kfree_skb_reason(skb, OVS_DROP_METER);
 				return 0;
 			}
 			break;
diff --git a/net/openvswitch/drop.h b/net/openvswitch/drop.h
index f9e9c1610f6b..2440c836727f 100644
--- a/net/openvswitch/drop.h
+++ b/net/openvswitch/drop.h
@@ -11,6 +11,7 @@
 	R(OVS_DROP_FLOW)		        \
 	R(OVS_DROP_EXPLICIT_ACTION)		\
 	R(OVS_DROP_EXPLICIT_ACTION_ERROR)	\
+	R(OVS_DROP_METER)			\
 	/* deliberate comment for trailing \ */
 
 enum ovs_drop_reason {
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 4/7] net: openvswitch: add misc error drop reasons
  2023-07-22  9:42 [PATCH net-next 0/7] openvswitch: add drop reasons Adrian Moreno
                   ` (2 preceding siblings ...)
  2023-07-22  9:42 ` [PATCH net-next 3/7] net: openvswitch: add meter drop reason Adrian Moreno
@ 2023-07-22  9:42 ` Adrian Moreno
  2023-07-24 15:23   ` Aaron Conole
  2023-07-22  9:42 ` [PATCH net-next 5/7] selftests: openvswitch: support key masks Adrian Moreno
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Adrian Moreno @ 2023-07-22  9:42 UTC (permalink / raw)
  To: netdev; +Cc: Adrian Moreno, dev, aconole, i.maximets, eric

Use drop reasons from include/net/dropreason-core.h when a reasonable
candidate exists.

Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
---
 net/openvswitch/actions.c   | 17 ++++++++++-------
 net/openvswitch/conntrack.c |  3 ++-
 net/openvswitch/drop.h      |  6 ++++++
 3 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 9279bb186e9f..42fa1e7eb912 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -782,7 +782,7 @@ static int ovs_vport_output(struct net *net, struct sock *sk,
 	struct vport *vport = data->vport;
 
 	if (skb_cow_head(skb, data->l2_len) < 0) {
-		kfree_skb(skb);
+		kfree_skb_reason(skb, SKB_DROP_REASON_NOMEM);
 		return -ENOMEM;
 	}
 
@@ -853,6 +853,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
 			 struct sk_buff *skb, u16 mru,
 			 struct sw_flow_key *key)
 {
+	enum ovs_drop_reason reason;
 	u16 orig_network_offset = 0;
 
 	if (eth_p_mpls(skb->protocol)) {
@@ -862,6 +863,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
 
 	if (skb_network_offset(skb) > MAX_L2_LEN) {
 		OVS_NLERR(1, "L2 header too long to fragment");
+		reason = OVS_DROP_FRAG_L2_TOO_LONG;
 		goto err;
 	}
 
@@ -902,12 +904,13 @@ static void ovs_fragment(struct net *net, struct vport *vport,
 		WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
 			  ovs_vport_name(vport), ntohs(key->eth.type), mru,
 			  vport->dev->mtu);
+		reason = OVS_DROP_FRAG_INVALID_PROTO;
 		goto err;
 	}
 
 	return;
 err:
-	kfree_skb(skb);
+	kfree_skb_reason(skb, reason);
 }
 
 static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
@@ -934,10 +937,10 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
 
 			ovs_fragment(net, vport, skb, mru, key);
 		} else {
-			kfree_skb(skb);
+			kfree_skb_reason(skb, SKB_DROP_REASON_PKT_TOO_BIG);
 		}
 	} else {
-		kfree_skb(skb);
+		kfree_skb_reason(skb, SKB_DROP_REASON_DEV_READY);
 	}
 }
 
@@ -1011,7 +1014,7 @@ static int dec_ttl_exception_handler(struct datapath *dp, struct sk_buff *skb,
 		return clone_execute(dp, skb, key, 0, nla_data(actions),
 				     nla_len(actions), true, false);
 
-	consume_skb(skb);
+	kfree_skb_reason(skb, OVS_DROP_IP_TTL);
 	return 0;
 }
 
@@ -1564,7 +1567,7 @@ static int clone_execute(struct datapath *dp, struct sk_buff *skb,
 		/* Out of per CPU action FIFO space. Drop the 'skb' and
 		 * log an error.
 		 */
-		kfree_skb(skb);
+		kfree_skb_reason(skb, OVS_DROP_DEFERRED_LIMIT);
 
 		if (net_ratelimit()) {
 			if (actions) { /* Sample action */
@@ -1616,7 +1619,7 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
 	if (unlikely(level > OVS_RECURSION_LIMIT)) {
 		net_crit_ratelimited("ovs: recursion limit reached on datapath %s, probable configuration error\n",
 				     ovs_dp_name(dp));
-		kfree_skb(skb);
+		kfree_skb_reason(skb, OVS_DROP_RECURSION_LIMIT);
 		err = -ENETDOWN;
 		goto out;
 	}
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index fa955e892210..b03ebd4a8fae 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -29,6 +29,7 @@
 #include <net/netfilter/nf_conntrack_act_ct.h>
 
 #include "datapath.h"
+#include "drop.h"
 #include "conntrack.h"
 #include "flow.h"
 #include "flow_netlink.h"
@@ -1035,7 +1036,7 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
 
 	skb_push_rcsum(skb, nh_ofs);
 	if (err)
-		kfree_skb(skb);
+		kfree_skb_reason(skb, OVS_DROP_CONNTRACK);
 	return err;
 }
 
diff --git a/net/openvswitch/drop.h b/net/openvswitch/drop.h
index 2440c836727f..744b8d1b93a3 100644
--- a/net/openvswitch/drop.h
+++ b/net/openvswitch/drop.h
@@ -12,6 +12,12 @@
 	R(OVS_DROP_EXPLICIT_ACTION)		\
 	R(OVS_DROP_EXPLICIT_ACTION_ERROR)	\
 	R(OVS_DROP_METER)			\
+	R(OVS_DROP_RECURSION_LIMIT)		\
+	R(OVS_DROP_DEFERRED_LIMIT)		\
+	R(OVS_DROP_FRAG_L2_TOO_LONG)		\
+	R(OVS_DROP_FRAG_INVALID_PROTO)		\
+	R(OVS_DROP_CONNTRACK)			\
+	R(OVS_DROP_IP_TTL)			\
 	/* deliberate comment for trailing \ */
 
 enum ovs_drop_reason {
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 5/7] selftests: openvswitch: support key masks
  2023-07-22  9:42 [PATCH net-next 0/7] openvswitch: add drop reasons Adrian Moreno
                   ` (3 preceding siblings ...)
  2023-07-22  9:42 ` [PATCH net-next 4/7] net: openvswitch: add misc error drop reasons Adrian Moreno
@ 2023-07-22  9:42 ` Adrian Moreno
  2023-07-22  9:42 ` [PATCH net-next 6/7] selftests: openvswitch: add drop reason testcase Adrian Moreno
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Adrian Moreno @ 2023-07-22  9:42 UTC (permalink / raw)
  To: netdev; +Cc: Adrian Moreno, dev, aconole, i.maximets, eric

The default value for the mask actually depends on the value (e.g: if
the value is non-null, the default is full-mask), so change the convert
functions to accept the full, possibly masked string and let them figure
out how to parse the differnt values.

Also, implement size-aware int parsing.

With this patch we can now express flows such as the following:
"eth(src=0a:ca:fe:ca:fe:0a/ff:ff:00:00:ff:00)"
"eth(src=0a:ca:fe:ca:fe:0a)" -> mask = ff:ff:ff:ff:ff:ff
"ipv4(src=192.168.1.1)" -> mask = 255.255.255.255
"ipv4(src=192.168.1.1/24)"
"ipv4(src=192.168.1.1/255.255.255.0)"
"tcp(src=8080)" -> mask = 0xffff
"tcp(src=8080/0xf0f0)"

Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
---
 .../selftests/net/openvswitch/ovs-dpctl.py    | 96 ++++++++++++-------
 1 file changed, 64 insertions(+), 32 deletions(-)

diff --git a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
index 61c4d7b75261..0bc944f36e02 100644
--- a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
+++ b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
@@ -169,25 +169,45 @@ def parse_ct_state(statestr):
     return parse_flags(statestr, ct_flags)
 
 
-def convert_mac(mac_str, mask=False):
-    if mac_str is None or mac_str == "":
-        mac_str = "00:00:00:00:00:00"
-    if mask is True and mac_str != "00:00:00:00:00:00":
-        mac_str = "FF:FF:FF:FF:FF:FF"
-    mac_split = mac_str.split(":")
-    ret = bytearray([int(i, 16) for i in mac_split])
-    return bytes(ret)
+def convert_mac(data):
+    def to_bytes(mac):
+        mac_split = mac.split(":")
+        ret = bytearray([int(i, 16) for i in mac_split])
+        return bytes(ret)
 
+    mac_str, _, mask_str = data.partition('/')
 
-def convert_ipv4(ip, mask=False):
-    if ip is None:
-        ip = 0
-    if mask is True:
-        if ip != 0:
-            ip = int(ipaddress.IPv4Address(ip)) & 0xFFFFFFFF
+    if not mac_str:
+        mac_str = mask_str = "00:00:00:00:00:00"
+    elif not mask_str:
+        mask_str = "FF:FF:FF:FF:FF:FF"
 
-    return int(ipaddress.IPv4Address(ip))
+    return to_bytes(mac_str), to_bytes(mask_str)
 
+def convert_ipv4(data):
+    ip, _, mask = data.partition('/')
+
+    if not ip:
+        ip = mask = 0
+    elif not mask:
+        mask = 0xFFFFFFFF
+    elif mask.isdigit():
+        mask = (0xFFFFFFFF << (32 - int(mask))) & 0xFFFFFFFF
+
+    return int(ipaddress.IPv4Address(ip)), int(ipaddress.IPv4Address(mask))
+
+def convert_int(size):
+    def convert_int_sized(data):
+        value, _, mask = data.partition('/')
+
+        if not value:
+            return 0, 0
+        elif not mask:
+            return int(value, 0), pow(2, size) - 1
+        else:
+            return int(value, 0), int(mask, 0)
+
+    return convert_int_sized
 
 def parse_starts_block(block_str, scanstr, returnskipped, scanregex=False):
     if scanregex:
@@ -628,8 +648,10 @@ class ovskey(nla):
         )
 
         fields_map = (
-            ("src", "src", "%d", lambda x: int(x) if x is not None else 0),
-            ("dst", "dst", "%d", lambda x: int(x) if x is not None else 0),
+            ("src", "src", "%d", lambda x: int(x) if x else 0,
+                convert_int(16)),
+            ("dst", "dst", "%d", lambda x: int(x) if x else 0,
+                convert_int(16)),
         )
 
         def __init__(
@@ -678,17 +700,13 @@ class ovskey(nla):
                     data = flowstr[:splitchar]
                     flowstr = flowstr[splitchar:]
                 else:
-                    data = None
+                    data = ""
 
                 if len(f) > 4:
-                    func = f[4]
-                else:
-                    func = f[3]
-                k[f[0]] = func(data)
-                if len(f) > 4:
-                    m[f[0]] = func(data, True)
+                    k[f[0]], m[f[0]] = f[4](data)
                 else:
-                    m[f[0]] = func(data)
+                    k[f[0]] = f[3](data)
+                    m[f[0]] = f[3](data)
 
                 flowstr = flowstr[strspn(flowstr, ", ") :]
                 if len(flowstr) == 0:
@@ -792,10 +810,14 @@ class ovskey(nla):
                 int,
                 convert_ipv4,
             ),
-            ("proto", "proto", "%d", lambda x: int(x) if x is not None else 0),
-            ("tos", "tos", "%d", lambda x: int(x) if x is not None else 0),
-            ("ttl", "ttl", "%d", lambda x: int(x) if x is not None else 0),
-            ("frag", "frag", "%d", lambda x: int(x) if x is not None else 0),
+            ("proto", "proto", "%d", lambda x: int(x) if x else 0,
+                convert_int(8)),
+            ("tos", "tos", "%d", lambda x: int(x) if x else 0,
+                convert_int(8)),
+            ("ttl", "ttl", "%d", lambda x: int(x) if x else 0,
+                convert_int(8)),
+            ("frag", "frag", "%d", lambda x: int(x) if x else 0,
+                convert_int(8)),
         )
 
         def __init__(
@@ -931,8 +953,8 @@ class ovskey(nla):
         )
 
         fields_map = (
-            ("type", "type", "%d", int),
-            ("code", "code", "%d", int),
+            ("type", "type", "%d", lambda x: int(x) if x else 0),
+            ("code", "code", "%d", lambda x: int(x) if x else 0),
         )
 
         def __init__(
@@ -997,7 +1019,7 @@ class ovskey(nla):
                 int,
                 convert_ipv4,
             ),
-            ("op", "op", "%d", lambda x: int(x) if x is not None else 0),
+            ("op", "op", "%d", lambda x: int(x) if x else 0),
             (
                 "sha",
                 "sha",
@@ -1201,6 +1223,16 @@ class ovskey(nla):
                 "tcp",
                 ovskey.ovs_key_tcp,
             ),
+            (
+                "OVS_KEY_ATTR_UDP",
+                "udp",
+                ovskey.ovs_key_udp,
+            ),
+            (
+                "OVS_KEY_ATTR_ICMP",
+                "icmp",
+                ovskey.ovs_key_icmp,
+            ),
             (
                 "OVS_KEY_ATTR_TCP_FLAGS",
                 "tcp_flags",
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 6/7] selftests: openvswitch: add drop reason testcase
  2023-07-22  9:42 [PATCH net-next 0/7] openvswitch: add drop reasons Adrian Moreno
                   ` (4 preceding siblings ...)
  2023-07-22  9:42 ` [PATCH net-next 5/7] selftests: openvswitch: support key masks Adrian Moreno
@ 2023-07-22  9:42 ` Adrian Moreno
  2023-07-22  9:42 ` [PATCH net-next 7/7] selftests: openvswitch: add explicit drop testcase Adrian Moreno
  2023-07-24 14:34 ` [PATCH net-next 0/7] openvswitch: add drop reasons Aaron Conole
  7 siblings, 0 replies; 15+ messages in thread
From: Adrian Moreno @ 2023-07-22  9:42 UTC (permalink / raw)
  To: netdev; +Cc: Adrian Moreno, dev, aconole, i.maximets, eric

Test if the correct drop reason is reported when OVS drops a packet due
to an explicit flow.

Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
---
 .../selftests/net/openvswitch/openvswitch.sh  | 67 ++++++++++++++++++-
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/net/openvswitch/openvswitch.sh b/tools/testing/selftests/net/openvswitch/openvswitch.sh
index dced4f612a78..a10c345f40ef 100755
--- a/tools/testing/selftests/net/openvswitch/openvswitch.sh
+++ b/tools/testing/selftests/net/openvswitch/openvswitch.sh
@@ -16,7 +16,8 @@ tests="
 	connect_v4				ip4-xon: Basic ipv4 ping between two NS
 	nat_connect_v4				ip4-nat-xon: Basic ipv4 tcp connection via NAT
 	netlink_checks				ovsnl: validate netlink attrs and settings
-	upcall_interfaces			ovs: test the upcall interfaces"
+	upcall_interfaces			ovs: test the upcall interfaces
+	drop_reason				drop: test drop reasons are emitted"
 
 info() {
     [ $VERBOSE = 0 ] || echo $*
@@ -141,6 +142,25 @@ ovs_add_flow () {
 	return 0
 }
 
+ovs_drop_record_and_run () {
+	local sbx=$1
+	shift
+
+	perf record -a -q -e skb:kfree_skb -o ${ovs_dir}/perf.data $* \
+		>> ${ovs_dir}/stdout 2>> ${ovs_dir}/stderr
+	return $?
+}
+
+ovs_drop_reason_count()
+{
+	local reason=$1
+
+	local perf_output=`perf script -i ${ovs_dir}/perf.data -F trace:event,trace`
+	local pattern="skb:kfree_skb:.*reason: $reason"
+
+	return `echo "$perf_output" | grep "$pattern" | wc -l`
+}
+
 usage() {
 	echo
 	echo "$0 [OPTIONS] [TEST]..."
@@ -155,6 +175,51 @@ usage() {
 	exit 1
 }
 
+# drop_reason test
+# - drop packets and verify the right drop reason is reported
+test_drop_reason() {
+	which perf >/dev/null 2>&1 || return $ksft_skip
+
+	sbx_add "test_drop_reason" || return $?
+
+	ovs_add_dp "test_drop_reason" dropreason || return 1
+
+	info "create namespaces"
+	for ns in client server; do
+		ovs_add_netns_and_veths "test_drop_reason" "dropreason" "$ns" \
+			"${ns:0:1}0" "${ns:0:1}1" || return 1
+	done
+
+	# Setup client namespace
+	ip netns exec client ip addr add 172.31.110.10/24 dev c1
+	ip netns exec client ip link set c1 up
+
+	# Setup server namespace
+	ip netns exec server ip addr add 172.31.110.20/24 dev s1
+	ip netns exec server ip link set s1 up
+
+	# Allow ARP
+	ovs_add_flow "test_drop_reason" dropreason \
+		'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
+	ovs_add_flow "test_drop_reason" dropreason \
+		'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
+
+	# Allow client ICMP traffic but drop return path
+	ovs_add_flow "test_drop_reason" dropreason \
+		"in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10,proto=1),icmp()" '2'
+	ovs_add_flow "test_drop_reason" dropreason \
+		"in_port(2),eth(),eth_type(0x0800),ipv4(src=172.31.110.20,proto=1),icmp()" 'drop'
+
+	ovs_drop_record_and_run "test_drop_reason" ip netns exec client ping -c 2 172.31.110.20
+	ovs_drop_reason_count 0x30001 # OVS_DROP_FLOW_ACTION
+	if [[ "$?" -ne "2" ]]; then
+		info "Did not detect expected drops: $?"
+		return 1
+	fi
+
+	return 0
+}
+
 # arp_ping test
 # - client has 1500 byte MTU
 # - server has 1500 byte MTU
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 7/7] selftests: openvswitch: add explicit drop testcase
  2023-07-22  9:42 [PATCH net-next 0/7] openvswitch: add drop reasons Adrian Moreno
                   ` (5 preceding siblings ...)
  2023-07-22  9:42 ` [PATCH net-next 6/7] selftests: openvswitch: add drop reason testcase Adrian Moreno
@ 2023-07-22  9:42 ` Adrian Moreno
  2023-07-24 14:49   ` Aaron Conole
  2023-07-24 14:34 ` [PATCH net-next 0/7] openvswitch: add drop reasons Aaron Conole
  7 siblings, 1 reply; 15+ messages in thread
From: Adrian Moreno @ 2023-07-22  9:42 UTC (permalink / raw)
  To: netdev; +Cc: Adrian Moreno, dev, aconole, i.maximets, eric

Make ovs-dpctl.py support explicit drops as:
"drop" -> implicit empty-action drop
"drop(0)" -> explicit non-error action drop
"drop(42)" -> explicit error action drop

Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
---
 .../selftests/net/openvswitch/openvswitch.sh  | 25 +++++++++++++++++++
 .../selftests/net/openvswitch/ovs-dpctl.py    | 18 ++++++++++---
 2 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/tools/testing/selftests/net/openvswitch/openvswitch.sh b/tools/testing/selftests/net/openvswitch/openvswitch.sh
index a10c345f40ef..398a69f1c923 100755
--- a/tools/testing/selftests/net/openvswitch/openvswitch.sh
+++ b/tools/testing/selftests/net/openvswitch/openvswitch.sh
@@ -217,6 +217,31 @@ test_drop_reason() {
 		return 1
 	fi
 
+	# Drop UDP 6000 traffic with an explicit action and an error code.
+	ovs_add_flow "test_drop_reason" dropreason \
+		"in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10,proto=17),udp(dst=6000)" \
+                'drop(42)'
+	# Drop UDP 7000 traffic with an explicit action with no error code.
+	ovs_add_flow "test_drop_reason" dropreason \
+		"in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10,proto=17),udp(dst=7000)" \
+                'drop(0)'
+
+	ovs_drop_record_and_run \
+            "test_drop_reason" ip netns exec client nc -i 1 -zuv 172.31.110.20 6000
+	ovs_drop_reason_count 0x30003 # OVS_DROP_EXPLICIT_ACTION_ERROR
+	if [[ "$?" -ne "1" ]]; then
+		info "Did not detect expected explicit error drops: $?"
+		return 1
+	fi
+
+	ovs_drop_record_and_run \
+            "test_drop_reason" ip netns exec client nc -i 1 -zuv 172.31.110.20 7000
+	ovs_drop_reason_count 0x30002 # OVS_DROP_EXPLICIT_ACTION
+	if [[ "$?" -ne "1" ]]; then
+		info "Did not detect expected explicit drops: $?"
+		return 1
+	fi
+
 	return 0
 }
 
diff --git a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
index 0bc944f36e02..de6db59ab115 100644
--- a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
+++ b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
@@ -448,7 +448,7 @@ class ovsactions(nla):
                 elif field[0] == "OVS_ACTION_ATTR_TRUNC":
                     print_str += "trunc(%d)" % int(self.get_attr(field[0]))
                 elif field[0] == "OVS_ACTION_ATTR_DROP":
-                    print_str += "drop"
+                    print_str += "drop(%d)" % int(self.get_attr(field[0]))
             elif field[1] == "flag":
                 if field[0] == "OVS_ACTION_ATTR_CT_CLEAR":
                     print_str += "ct_clear"
@@ -470,9 +470,19 @@ class ovsactions(nla):
         parsed = False
         while len(actstr) != 0:
             if actstr.startswith("drop"):
-                # for now, drops have no explicit action, so we
-                # don't need to set any attributes.  The final
-                # act of the processing chain will just drop the packet
+                # If no reason is provided, the implicit drop is used (i.e no
+                # action). If some reason is given, an explicit action is used.
+                actstr, reason = parse_extract_field(
+                    actstr,
+                    "drop(",
+                    "([0-9]+)",
+                    lambda x: int(x, 0),
+                    False,
+                    None,
+                )
+                if reason is not None:
+                    self["attrs"].append(["OVS_ACTION_ATTR_DROP", reason])
+
                 return
 
             elif parse_starts_block(actstr, "^(\d+)", False, True):
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next 0/7] openvswitch: add drop reasons
  2023-07-22  9:42 [PATCH net-next 0/7] openvswitch: add drop reasons Adrian Moreno
                   ` (6 preceding siblings ...)
  2023-07-22  9:42 ` [PATCH net-next 7/7] selftests: openvswitch: add explicit drop testcase Adrian Moreno
@ 2023-07-24 14:34 ` Aaron Conole
  2023-07-26  8:34   ` Adrian Moreno
  7 siblings, 1 reply; 15+ messages in thread
From: Aaron Conole @ 2023-07-24 14:34 UTC (permalink / raw)
  To: Adrian Moreno
  Cc: netdev, dev, i.maximets, eric, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni

Adrian Moreno <amorenoz@redhat.com> writes:

> There is currently a gap in drop visibility in the openvswitch module.
> This series tries to improve this by adding a new drop reason subsystem
> for OVS.
>
> Apart from adding a new drop reasson subsystem and some common drop
> reasons, this series takes Eric's preliminary work [1] on adding an
> explicit drop action and integrates it into the same subsystem.
>
> This series also adds some selftests and so it requires [2] to be
> applied first.
>
> A limitation of this series is that it does not report upcall errors.
> The reason is that there could be many sources of upcall drops and the
> most common one, which is the netlink buffer overflow, cannot be
> reported via kfree_skb() because the skb is freed in the netlink layer
> (see [3]). Therefore, using a reason for the rare events and not the
> common one would be even more misleading. I'd propose we add (in a
> follow up patch) a tracepoint to better report upcall errors.

I guess you meant to add RFC tag to this, since it depends on other
series that aren't accepted yet.

If it's okay, I will pull in your patch 5/7 when I re-post my flow
additions series, since it will need to be added there at some point
anyway.

> [1] https://lore.kernel.org/netdev/202306300609.tdRdZscy-lkp@intel.com/T/
> [2] https://lore.kernel.org/all/9375ccbc-dd40-9998-dde5-c94e4e28f4f1@redhat.com/T/ 
> [3] commit 1100248a5c5c ("openvswitch: Fix double reporting of drops in dropwatch")
>
> Adrian Moreno (6):
>   net: openvswitch: add datapath flow drop reason
>   net: openvswitch: add meter drop reason
>   net: openvswitch: add misc error drop reasons
>   selftests: openvswitch: support key masks
>   selftests: openvswitch: add drop reason testcase
>   selftests: openvswitch: add explicit drop testcase
>
> Eric Garver (1):
>   net: openvswitch: add explicit drop action
>
>  include/net/dropreason.h                      |   6 +
>  include/uapi/linux/openvswitch.h              |   2 +
>  net/openvswitch/actions.c                     |  40 ++++--
>  net/openvswitch/conntrack.c                   |   3 +-
>  net/openvswitch/datapath.c                    |  16 +++
>  net/openvswitch/drop.h                        |  33 +++++
>  net/openvswitch/flow_netlink.c                |   8 +-
>  .../selftests/net/openvswitch/openvswitch.sh  |  92 +++++++++++++-
>  .../selftests/net/openvswitch/ovs-dpctl.py    | 115 ++++++++++++------
>  9 files changed, 267 insertions(+), 48 deletions(-)
>  create mode 100644 net/openvswitch/drop.h


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next 2/7] net: openvswitch: add explicit drop action
  2023-07-22  9:42 ` [PATCH net-next 2/7] net: openvswitch: add explicit drop action Adrian Moreno
@ 2023-07-24 14:47   ` Aaron Conole
  2023-07-26  8:31     ` Adrian Moreno
  0 siblings, 1 reply; 15+ messages in thread
From: Aaron Conole @ 2023-07-24 14:47 UTC (permalink / raw)
  To: Adrian Moreno; +Cc: netdev, Eric Garver, dev, i.maximets

Adrian Moreno <amorenoz@redhat.com> writes:

> From: Eric Garver <eric@garver.life>
>
> This adds an explicit drop action. This is used by OVS to drop packets
> for which it cannot determine what to do. An explicit action in the
> kernel allows passing the reason _why_ the packet is being dropped or
> zero to indicate no particular error happened (i.e: OVS intentionally
> dropped the packet).
>
> Since the error codes coming from userspace mean nothing for the kernel,
> we squash all of them into only two drop reasons:
> - OVS_DROP_EXPLICIT_ACTION_ERROR to indicate a non-zero value was passed
> - OVS_DROP_EXPLICIT_ACTION to indicate a zero value was passed (no
>   error)
>
> e.g. trace all OVS dropped skbs
>
>  # perf trace -e skb:kfree_skb --filter="reason >= 0x30000"
>  [..]
>  106.023 ping/2465 skb:kfree_skb(skbaddr: 0xffffa0e8765f2000, \
>   location:0xffffffffc0d9b462, protocol: 2048, reason: 196610)
>
> reason: 196610 --> 0x30002 (OVS_DROP_EXPLICIT_ACTION)
>
> Signed-off-by: Eric Garver <eric@garver.life>
> Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
> ---
>  include/uapi/linux/openvswitch.h                     | 2 ++
>  net/openvswitch/actions.c                            | 9 +++++++++
>  net/openvswitch/drop.h                               | 2 ++
>  net/openvswitch/flow_netlink.c                       | 8 +++++++-
>  tools/testing/selftests/net/openvswitch/ovs-dpctl.py | 3 +++
>  5 files changed, 23 insertions(+), 1 deletion(-)
>
> diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
> index e94870e77ee9..efc82c318fa2 100644
> --- a/include/uapi/linux/openvswitch.h
> +++ b/include/uapi/linux/openvswitch.h
> @@ -965,6 +965,7 @@ struct check_pkt_len_arg {
>   * start of the packet or at the start of the l3 header depending on the value
>   * of l3 tunnel flag in the tun_flags field of OVS_ACTION_ATTR_ADD_MPLS
>   * argument.
> + * @OVS_ACTION_ATTR_DROP: Explicit drop action.
>   *
>   * Only a single header can be set with a single %OVS_ACTION_ATTR_SET.  Not all
>   * fields within a header are modifiable, e.g. the IPv4 protocol and fragment
> @@ -1002,6 +1003,7 @@ enum ovs_action_attr {
>  	OVS_ACTION_ATTR_CHECK_PKT_LEN, /* Nested OVS_CHECK_PKT_LEN_ATTR_*. */
>  	OVS_ACTION_ATTR_ADD_MPLS,     /* struct ovs_action_add_mpls. */
>  	OVS_ACTION_ATTR_DEC_TTL,      /* Nested OVS_DEC_TTL_ATTR_*. */
> +	OVS_ACTION_ATTR_DROP,         /* u32 error code. */
>  
>  	__OVS_ACTION_ATTR_MAX,	      /* Nothing past this will be accepted
>  				       * from userspace. */
> diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
> index af676dcac2b4..194379d58b62 100644
> --- a/net/openvswitch/actions.c
> +++ b/net/openvswitch/actions.c
> @@ -1485,6 +1485,15 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
>  				return dec_ttl_exception_handler(dp, skb,
>  								 key, a);
>  			break;
> +
> +		case OVS_ACTION_ATTR_DROP: {
> +			enum ovs_drop_reason reason = nla_get_u32(a)
> +				? OVS_DROP_EXPLICIT_ACTION_ERROR
> +				: OVS_DROP_EXPLICIT_ACTION;
> +
> +			kfree_skb_reason(skb, reason);
> +			return 0;
> +		}
>  		}
>  
>  		if (unlikely(err)) {
> diff --git a/net/openvswitch/drop.h b/net/openvswitch/drop.h
> index cdd10629c6be..f9e9c1610f6b 100644
> --- a/net/openvswitch/drop.h
> +++ b/net/openvswitch/drop.h
> @@ -9,6 +9,8 @@
>  
>  #define OVS_DROP_REASONS(R)			\
>  	R(OVS_DROP_FLOW)		        \
> +	R(OVS_DROP_EXPLICIT_ACTION)		\
> +	R(OVS_DROP_EXPLICIT_ACTION_ERROR)	\
>  	/* deliberate comment for trailing \ */
>  
>  enum ovs_drop_reason {
> diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
> index 41116361433d..244280922a14 100644
> --- a/net/openvswitch/flow_netlink.c
> +++ b/net/openvswitch/flow_netlink.c
> @@ -38,6 +38,7 @@
>  #include <net/tun_proto.h>
>  #include <net/erspan.h>
>  
> +#include "drop.h"
>  #include "flow_netlink.h"
>  
>  struct ovs_len_tbl {
> @@ -61,6 +62,7 @@ static bool actions_may_change_flow(const struct nlattr *actions)
>  		case OVS_ACTION_ATTR_RECIRC:
>  		case OVS_ACTION_ATTR_TRUNC:
>  		case OVS_ACTION_ATTR_USERSPACE:
> +		case OVS_ACTION_ATTR_DROP:
>  			break;
>  
>  		case OVS_ACTION_ATTR_CT:
> @@ -2394,7 +2396,7 @@ static void ovs_nla_free_nested_actions(const struct nlattr *actions, int len)
>  	/* Whenever new actions are added, the need to update this
>  	 * function should be considered.
>  	 */
> -	BUILD_BUG_ON(OVS_ACTION_ATTR_MAX != 23);
> +	BUILD_BUG_ON(OVS_ACTION_ATTR_MAX != 24);
>  
>  	if (!actions)
>  		return;
> @@ -3182,6 +3184,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
>  			[OVS_ACTION_ATTR_CHECK_PKT_LEN] = (u32)-1,
>  			[OVS_ACTION_ATTR_ADD_MPLS] = sizeof(struct ovs_action_add_mpls),
>  			[OVS_ACTION_ATTR_DEC_TTL] = (u32)-1,
> +			[OVS_ACTION_ATTR_DROP] = sizeof(u32),
>  		};
>  		const struct ovs_action_push_vlan *vlan;
>  		int type = nla_type(a);
> @@ -3453,6 +3456,9 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
>  			skip_copy = true;
>  			break;
>  
> +		case OVS_ACTION_ATTR_DROP:
> +			break;
> +

We may want to have an explicit check in this area to warn about an
action list like:

  output:1,drop(something),output:2

I see the action handling code will correctly return when we encounter
drop action, so it should stop the current skb context from being
accessed further.  But it may also be good to prevent extra actions from
being attempted in the first place.

>  		default:
>  			OVS_NLERR(log, "Unknown Action type %d", type);
>  			return -EINVAL;
> diff --git a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
> index 12ba5265b88f..61c4d7b75261 100644
> --- a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
> +++ b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
> @@ -280,6 +280,7 @@ class ovsactions(nla):
>          ("OVS_ACTION_ATTR_CHECK_PKT_LEN", "none"),
>          ("OVS_ACTION_ATTR_ADD_MPLS", "none"),
>          ("OVS_ACTION_ATTR_DEC_TTL", "none"),
> +        ("OVS_ACTION_ATTR_DROP", "uint32"),
>      )
>  
>      class ctact(nla):
> @@ -426,6 +427,8 @@ class ovsactions(nla):
>                      print_str += "recirc(0x%x)" % int(self.get_attr(field[0]))
>                  elif field[0] == "OVS_ACTION_ATTR_TRUNC":
>                      print_str += "trunc(%d)" % int(self.get_attr(field[0]))
> +                elif field[0] == "OVS_ACTION_ATTR_DROP":
> +                    print_str += "drop"
>              elif field[1] == "flag":
>                  if field[0] == "OVS_ACTION_ATTR_CT_CLEAR":
>                      print_str += "ct_clear"


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next 7/7] selftests: openvswitch: add explicit drop testcase
  2023-07-22  9:42 ` [PATCH net-next 7/7] selftests: openvswitch: add explicit drop testcase Adrian Moreno
@ 2023-07-24 14:49   ` Aaron Conole
  0 siblings, 0 replies; 15+ messages in thread
From: Aaron Conole @ 2023-07-24 14:49 UTC (permalink / raw)
  To: Adrian Moreno; +Cc: netdev, dev, i.maximets, eric

Adrian Moreno <amorenoz@redhat.com> writes:

> Make ovs-dpctl.py support explicit drops as:
> "drop" -> implicit empty-action drop
> "drop(0)" -> explicit non-error action drop
> "drop(42)" -> explicit error action drop
>
> Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
> ---
>  .../selftests/net/openvswitch/openvswitch.sh  | 25 +++++++++++++++++++
>  .../selftests/net/openvswitch/ovs-dpctl.py    | 18 ++++++++++---
>  2 files changed, 39 insertions(+), 4 deletions(-)
>
> diff --git a/tools/testing/selftests/net/openvswitch/openvswitch.sh b/tools/testing/selftests/net/openvswitch/openvswitch.sh
> index a10c345f40ef..398a69f1c923 100755
> --- a/tools/testing/selftests/net/openvswitch/openvswitch.sh
> +++ b/tools/testing/selftests/net/openvswitch/openvswitch.sh
> @@ -217,6 +217,31 @@ test_drop_reason() {
>  		return 1
>  	fi
>  
> +	# Drop UDP 6000 traffic with an explicit action and an error code.
> +	ovs_add_flow "test_drop_reason" dropreason \
> +		"in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10,proto=17),udp(dst=6000)" \
> +                'drop(42)'
> +	# Drop UDP 7000 traffic with an explicit action with no error code.
> +	ovs_add_flow "test_drop_reason" dropreason \
> +		"in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10,proto=17),udp(dst=7000)" \
> +                'drop(0)'
> +
> +	ovs_drop_record_and_run \
> +            "test_drop_reason" ip netns exec client nc -i 1 -zuv 172.31.110.20 6000
> +	ovs_drop_reason_count 0x30003 # OVS_DROP_EXPLICIT_ACTION_ERROR
> +	if [[ "$?" -ne "1" ]]; then
> +		info "Did not detect expected explicit error drops: $?"
> +		return 1
> +	fi
> +
> +	ovs_drop_record_and_run \
> +            "test_drop_reason" ip netns exec client nc -i 1 -zuv 172.31.110.20 7000
> +	ovs_drop_reason_count 0x30002 # OVS_DROP_EXPLICIT_ACTION
> +	if [[ "$?" -ne "1" ]]; then
> +		info "Did not detect expected explicit drops: $?"
> +		return 1
> +	fi
> +
>  	return 0
>  }
>  
> diff --git a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
> index 0bc944f36e02..de6db59ab115 100644
> --- a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
> +++ b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
> @@ -448,7 +448,7 @@ class ovsactions(nla):
>                  elif field[0] == "OVS_ACTION_ATTR_TRUNC":
>                      print_str += "trunc(%d)" % int(self.get_attr(field[0]))
>                  elif field[0] == "OVS_ACTION_ATTR_DROP":
> -                    print_str += "drop"
> +                    print_str += "drop(%d)" % int(self.get_attr(field[0]))
>              elif field[1] == "flag":
>                  if field[0] == "OVS_ACTION_ATTR_CT_CLEAR":
>                      print_str += "ct_clear"
> @@ -470,9 +470,19 @@ class ovsactions(nla):
>          parsed = False
>          while len(actstr) != 0:
>              if actstr.startswith("drop"):
> -                # for now, drops have no explicit action, so we
> -                # don't need to set any attributes.  The final
> -                # act of the processing chain will just drop the packet
> +                # If no reason is provided, the implicit drop is used (i.e no
> +                # action). If some reason is given, an explicit action is used.
> +                actstr, reason = parse_extract_field(
> +                    actstr,
> +                    "drop(",
> +                    "([0-9]+)",
> +                    lambda x: int(x, 0),
> +                    False,
> +                    None,
> +                )
> +                if reason is not None:
> +                    self["attrs"].append(["OVS_ACTION_ATTR_DROP", reason])
> +
>                  return

If we decide to validate that drop() action is the last one, we can
probably also remove this return.

>  
>              elif parse_starts_block(actstr, "^(\d+)", False, True):


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next 4/7] net: openvswitch: add misc error drop reasons
  2023-07-22  9:42 ` [PATCH net-next 4/7] net: openvswitch: add misc error drop reasons Adrian Moreno
@ 2023-07-24 15:23   ` Aaron Conole
  2023-07-26  8:32     ` Adrian Moreno
  0 siblings, 1 reply; 15+ messages in thread
From: Aaron Conole @ 2023-07-24 15:23 UTC (permalink / raw)
  To: Adrian Moreno; +Cc: netdev, dev, i.maximets, eric

Adrian Moreno <amorenoz@redhat.com> writes:

> Use drop reasons from include/net/dropreason-core.h when a reasonable
> candidate exists.
>
> Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
> ---
>  net/openvswitch/actions.c   | 17 ++++++++++-------
>  net/openvswitch/conntrack.c |  3 ++-
>  net/openvswitch/drop.h      |  6 ++++++
>  3 files changed, 18 insertions(+), 8 deletions(-)
>
> diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
> index 9279bb186e9f..42fa1e7eb912 100644
> --- a/net/openvswitch/actions.c
> +++ b/net/openvswitch/actions.c

Did you consider putting in a drop reason when one of the actions fails
setting err?  For example, if dec_ttl fails with some error other than
EHOSTUNREACH, it will drop into the kfree_skb() case... maybe we should
have an action_failed drop reason that can be passed there.

> @@ -782,7 +782,7 @@ static int ovs_vport_output(struct net *net, struct sock *sk,
>  	struct vport *vport = data->vport;
>  
>  	if (skb_cow_head(skb, data->l2_len) < 0) {
> -		kfree_skb(skb);
> +		kfree_skb_reason(skb, SKB_DROP_REASON_NOMEM);
>  		return -ENOMEM;
>  	}
>  
> @@ -853,6 +853,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
>  			 struct sk_buff *skb, u16 mru,
>  			 struct sw_flow_key *key)
>  {
> +	enum ovs_drop_reason reason;
>  	u16 orig_network_offset = 0;
>  
>  	if (eth_p_mpls(skb->protocol)) {
> @@ -862,6 +863,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
>  
>  	if (skb_network_offset(skb) > MAX_L2_LEN) {
>  		OVS_NLERR(1, "L2 header too long to fragment");
> +		reason = OVS_DROP_FRAG_L2_TOO_LONG;
>  		goto err;
>  	}
>  
> @@ -902,12 +904,13 @@ static void ovs_fragment(struct net *net, struct vport *vport,
>  		WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
>  			  ovs_vport_name(vport), ntohs(key->eth.type), mru,
>  			  vport->dev->mtu);
> +		reason = OVS_DROP_FRAG_INVALID_PROTO;
>  		goto err;
>  	}
>  
>  	return;
>  err:
> -	kfree_skb(skb);
> +	kfree_skb_reason(skb, reason);
>  }
>  
>  static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
> @@ -934,10 +937,10 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
>  
>  			ovs_fragment(net, vport, skb, mru, key);
>  		} else {
> -			kfree_skb(skb);
> +			kfree_skb_reason(skb, SKB_DROP_REASON_PKT_TOO_BIG);
>  		}
>  	} else {
> -		kfree_skb(skb);
> +		kfree_skb_reason(skb, SKB_DROP_REASON_DEV_READY);
>  	}
>  }
>  
> @@ -1011,7 +1014,7 @@ static int dec_ttl_exception_handler(struct datapath *dp, struct sk_buff *skb,
>  		return clone_execute(dp, skb, key, 0, nla_data(actions),
>  				     nla_len(actions), true, false);
>  
> -	consume_skb(skb);
> +	kfree_skb_reason(skb, OVS_DROP_IP_TTL);
>  	return 0;
>  }
>  
> @@ -1564,7 +1567,7 @@ static int clone_execute(struct datapath *dp, struct sk_buff *skb,
>  		/* Out of per CPU action FIFO space. Drop the 'skb' and
>  		 * log an error.
>  		 */
> -		kfree_skb(skb);
> +		kfree_skb_reason(skb, OVS_DROP_DEFERRED_LIMIT);
>  
>  		if (net_ratelimit()) {
>  			if (actions) { /* Sample action */
> @@ -1616,7 +1619,7 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
>  	if (unlikely(level > OVS_RECURSION_LIMIT)) {
>  		net_crit_ratelimited("ovs: recursion limit reached on datapath %s, probable configuration error\n",
>  				     ovs_dp_name(dp));
> -		kfree_skb(skb);
> +		kfree_skb_reason(skb, OVS_DROP_RECURSION_LIMIT);
>  		err = -ENETDOWN;
>  		goto out;
>  	}
> diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
> index fa955e892210..b03ebd4a8fae 100644
> --- a/net/openvswitch/conntrack.c
> +++ b/net/openvswitch/conntrack.c
> @@ -29,6 +29,7 @@
>  #include <net/netfilter/nf_conntrack_act_ct.h>
>  
>  #include "datapath.h"
> +#include "drop.h"
>  #include "conntrack.h"
>  #include "flow.h"
>  #include "flow_netlink.h"
> @@ -1035,7 +1036,7 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
>  
>  	skb_push_rcsum(skb, nh_ofs);
>  	if (err)
> -		kfree_skb(skb);
> +		kfree_skb_reason(skb, OVS_DROP_CONNTRACK);
>  	return err;
>  }
>  
> diff --git a/net/openvswitch/drop.h b/net/openvswitch/drop.h
> index 2440c836727f..744b8d1b93a3 100644
> --- a/net/openvswitch/drop.h
> +++ b/net/openvswitch/drop.h
> @@ -12,6 +12,12 @@
>  	R(OVS_DROP_EXPLICIT_ACTION)		\
>  	R(OVS_DROP_EXPLICIT_ACTION_ERROR)	\
>  	R(OVS_DROP_METER)			\
> +	R(OVS_DROP_RECURSION_LIMIT)		\
> +	R(OVS_DROP_DEFERRED_LIMIT)		\
> +	R(OVS_DROP_FRAG_L2_TOO_LONG)		\
> +	R(OVS_DROP_FRAG_INVALID_PROTO)		\
> +	R(OVS_DROP_CONNTRACK)			\
> +	R(OVS_DROP_IP_TTL)			\
>  	/* deliberate comment for trailing \ */
>  
>  enum ovs_drop_reason {


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next 2/7] net: openvswitch: add explicit drop action
  2023-07-24 14:47   ` Aaron Conole
@ 2023-07-26  8:31     ` Adrian Moreno
  0 siblings, 0 replies; 15+ messages in thread
From: Adrian Moreno @ 2023-07-26  8:31 UTC (permalink / raw)
  To: Aaron Conole; +Cc: netdev, Eric Garver, dev, i.maximets



On 7/24/23 16:47, Aaron Conole wrote:
> Adrian Moreno <amorenoz@redhat.com> writes:
> 
>> From: Eric Garver <eric@garver.life>
>>
>> This adds an explicit drop action. This is used by OVS to drop packets
>> for which it cannot determine what to do. An explicit action in the
>> kernel allows passing the reason _why_ the packet is being dropped or
>> zero to indicate no particular error happened (i.e: OVS intentionally
>> dropped the packet).
>>
>> Since the error codes coming from userspace mean nothing for the kernel,
>> we squash all of them into only two drop reasons:
>> - OVS_DROP_EXPLICIT_ACTION_ERROR to indicate a non-zero value was passed
>> - OVS_DROP_EXPLICIT_ACTION to indicate a zero value was passed (no
>>    error)
>>
>> e.g. trace all OVS dropped skbs
>>
>>   # perf trace -e skb:kfree_skb --filter="reason >= 0x30000"
>>   [..]
>>   106.023 ping/2465 skb:kfree_skb(skbaddr: 0xffffa0e8765f2000, \
>>    location:0xffffffffc0d9b462, protocol: 2048, reason: 196610)
>>
>> reason: 196610 --> 0x30002 (OVS_DROP_EXPLICIT_ACTION)
>>
>> Signed-off-by: Eric Garver <eric@garver.life>
>> Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
>> ---
>>   include/uapi/linux/openvswitch.h                     | 2 ++
>>   net/openvswitch/actions.c                            | 9 +++++++++
>>   net/openvswitch/drop.h                               | 2 ++
>>   net/openvswitch/flow_netlink.c                       | 8 +++++++-
>>   tools/testing/selftests/net/openvswitch/ovs-dpctl.py | 3 +++
>>   5 files changed, 23 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
>> index e94870e77ee9..efc82c318fa2 100644
>> --- a/include/uapi/linux/openvswitch.h
>> +++ b/include/uapi/linux/openvswitch.h
>> @@ -965,6 +965,7 @@ struct check_pkt_len_arg {
>>    * start of the packet or at the start of the l3 header depending on the value
>>    * of l3 tunnel flag in the tun_flags field of OVS_ACTION_ATTR_ADD_MPLS
>>    * argument.
>> + * @OVS_ACTION_ATTR_DROP: Explicit drop action.
>>    *
>>    * Only a single header can be set with a single %OVS_ACTION_ATTR_SET.  Not all
>>    * fields within a header are modifiable, e.g. the IPv4 protocol and fragment
>> @@ -1002,6 +1003,7 @@ enum ovs_action_attr {
>>   	OVS_ACTION_ATTR_CHECK_PKT_LEN, /* Nested OVS_CHECK_PKT_LEN_ATTR_*. */
>>   	OVS_ACTION_ATTR_ADD_MPLS,     /* struct ovs_action_add_mpls. */
>>   	OVS_ACTION_ATTR_DEC_TTL,      /* Nested OVS_DEC_TTL_ATTR_*. */
>> +	OVS_ACTION_ATTR_DROP,         /* u32 error code. */
>>   
>>   	__OVS_ACTION_ATTR_MAX,	      /* Nothing past this will be accepted
>>   				       * from userspace. */
>> diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
>> index af676dcac2b4..194379d58b62 100644
>> --- a/net/openvswitch/actions.c
>> +++ b/net/openvswitch/actions.c
>> @@ -1485,6 +1485,15 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
>>   				return dec_ttl_exception_handler(dp, skb,
>>   								 key, a);
>>   			break;
>> +
>> +		case OVS_ACTION_ATTR_DROP: {
>> +			enum ovs_drop_reason reason = nla_get_u32(a)
>> +				? OVS_DROP_EXPLICIT_ACTION_ERROR
>> +				: OVS_DROP_EXPLICIT_ACTION;
>> +
>> +			kfree_skb_reason(skb, reason);
>> +			return 0;
>> +		}
>>   		}
>>   
>>   		if (unlikely(err)) {
>> diff --git a/net/openvswitch/drop.h b/net/openvswitch/drop.h
>> index cdd10629c6be..f9e9c1610f6b 100644
>> --- a/net/openvswitch/drop.h
>> +++ b/net/openvswitch/drop.h
>> @@ -9,6 +9,8 @@
>>   
>>   #define OVS_DROP_REASONS(R)			\
>>   	R(OVS_DROP_FLOW)		        \
>> +	R(OVS_DROP_EXPLICIT_ACTION)		\
>> +	R(OVS_DROP_EXPLICIT_ACTION_ERROR)	\
>>   	/* deliberate comment for trailing \ */
>>   
>>   enum ovs_drop_reason {
>> diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
>> index 41116361433d..244280922a14 100644
>> --- a/net/openvswitch/flow_netlink.c
>> +++ b/net/openvswitch/flow_netlink.c
>> @@ -38,6 +38,7 @@
>>   #include <net/tun_proto.h>
>>   #include <net/erspan.h>
>>   
>> +#include "drop.h"
>>   #include "flow_netlink.h"
>>   
>>   struct ovs_len_tbl {
>> @@ -61,6 +62,7 @@ static bool actions_may_change_flow(const struct nlattr *actions)
>>   		case OVS_ACTION_ATTR_RECIRC:
>>   		case OVS_ACTION_ATTR_TRUNC:
>>   		case OVS_ACTION_ATTR_USERSPACE:
>> +		case OVS_ACTION_ATTR_DROP:
>>   			break;
>>   
>>   		case OVS_ACTION_ATTR_CT:
>> @@ -2394,7 +2396,7 @@ static void ovs_nla_free_nested_actions(const struct nlattr *actions, int len)
>>   	/* Whenever new actions are added, the need to update this
>>   	 * function should be considered.
>>   	 */
>> -	BUILD_BUG_ON(OVS_ACTION_ATTR_MAX != 23);
>> +	BUILD_BUG_ON(OVS_ACTION_ATTR_MAX != 24);
>>   
>>   	if (!actions)
>>   		return;
>> @@ -3182,6 +3184,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
>>   			[OVS_ACTION_ATTR_CHECK_PKT_LEN] = (u32)-1,
>>   			[OVS_ACTION_ATTR_ADD_MPLS] = sizeof(struct ovs_action_add_mpls),
>>   			[OVS_ACTION_ATTR_DEC_TTL] = (u32)-1,
>> +			[OVS_ACTION_ATTR_DROP] = sizeof(u32),
>>   		};
>>   		const struct ovs_action_push_vlan *vlan;
>>   		int type = nla_type(a);
>> @@ -3453,6 +3456,9 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
>>   			skip_copy = true;
>>   			break;
>>   
>> +		case OVS_ACTION_ATTR_DROP:
>> +			break;
>> +
> 
> We may want to have an explicit check in this area to warn about an
> action list like:
> 
>    output:1,drop(something),output:2
> 
> I see the action handling code will correctly return when we encounter
> drop action, so it should stop the current skb context from being
> accessed further.  But it may also be good to prevent extra actions from
> being attempted in the first place.
> 

Sounds like a good idea! Thanks. I'll add it in the next version.

>>   		default:
>>   			OVS_NLERR(log, "Unknown Action type %d", type);
>>   			return -EINVAL;
>> diff --git a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
>> index 12ba5265b88f..61c4d7b75261 100644
>> --- a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
>> +++ b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
>> @@ -280,6 +280,7 @@ class ovsactions(nla):
>>           ("OVS_ACTION_ATTR_CHECK_PKT_LEN", "none"),
>>           ("OVS_ACTION_ATTR_ADD_MPLS", "none"),
>>           ("OVS_ACTION_ATTR_DEC_TTL", "none"),
>> +        ("OVS_ACTION_ATTR_DROP", "uint32"),
>>       )
>>   
>>       class ctact(nla):
>> @@ -426,6 +427,8 @@ class ovsactions(nla):
>>                       print_str += "recirc(0x%x)" % int(self.get_attr(field[0]))
>>                   elif field[0] == "OVS_ACTION_ATTR_TRUNC":
>>                       print_str += "trunc(%d)" % int(self.get_attr(field[0]))
>> +                elif field[0] == "OVS_ACTION_ATTR_DROP":
>> +                    print_str += "drop"
>>               elif field[1] == "flag":
>>                   if field[0] == "OVS_ACTION_ATTR_CT_CLEAR":
>>                       print_str += "ct_clear"
> 

-- 
Adrián Moreno


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next 4/7] net: openvswitch: add misc error drop reasons
  2023-07-24 15:23   ` Aaron Conole
@ 2023-07-26  8:32     ` Adrian Moreno
  0 siblings, 0 replies; 15+ messages in thread
From: Adrian Moreno @ 2023-07-26  8:32 UTC (permalink / raw)
  To: Aaron Conole; +Cc: netdev, dev, i.maximets, eric



On 7/24/23 17:23, Aaron Conole wrote:
> Adrian Moreno <amorenoz@redhat.com> writes:
> 
>> Use drop reasons from include/net/dropreason-core.h when a reasonable
>> candidate exists.
>>
>> Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
>> ---
>>   net/openvswitch/actions.c   | 17 ++++++++++-------
>>   net/openvswitch/conntrack.c |  3 ++-
>>   net/openvswitch/drop.h      |  6 ++++++
>>   3 files changed, 18 insertions(+), 8 deletions(-)
>>
>> diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
>> index 9279bb186e9f..42fa1e7eb912 100644
>> --- a/net/openvswitch/actions.c
>> +++ b/net/openvswitch/actions.c
> 
> Did you consider putting in a drop reason when one of the actions fails
> setting err?  For example, if dec_ttl fails with some error other than
> EHOSTUNREACH, it will drop into the kfree_skb() case... maybe we should
> have an action_failed drop reason that can be passed there.
> 

Another good idea! Thanks Aaron.


>> @@ -782,7 +782,7 @@ static int ovs_vport_output(struct net *net, struct sock *sk,
>>   	struct vport *vport = data->vport;
>>   
>>   	if (skb_cow_head(skb, data->l2_len) < 0) {
>> -		kfree_skb(skb);
>> +		kfree_skb_reason(skb, SKB_DROP_REASON_NOMEM);
>>   		return -ENOMEM;
>>   	}
>>   
>> @@ -853,6 +853,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
>>   			 struct sk_buff *skb, u16 mru,
>>   			 struct sw_flow_key *key)
>>   {
>> +	enum ovs_drop_reason reason;
>>   	u16 orig_network_offset = 0;
>>   
>>   	if (eth_p_mpls(skb->protocol)) {
>> @@ -862,6 +863,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
>>   
>>   	if (skb_network_offset(skb) > MAX_L2_LEN) {
>>   		OVS_NLERR(1, "L2 header too long to fragment");
>> +		reason = OVS_DROP_FRAG_L2_TOO_LONG;
>>   		goto err;
>>   	}
>>   
>> @@ -902,12 +904,13 @@ static void ovs_fragment(struct net *net, struct vport *vport,
>>   		WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
>>   			  ovs_vport_name(vport), ntohs(key->eth.type), mru,
>>   			  vport->dev->mtu);
>> +		reason = OVS_DROP_FRAG_INVALID_PROTO;
>>   		goto err;
>>   	}
>>   
>>   	return;
>>   err:
>> -	kfree_skb(skb);
>> +	kfree_skb_reason(skb, reason);
>>   }
>>   
>>   static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
>> @@ -934,10 +937,10 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
>>   
>>   			ovs_fragment(net, vport, skb, mru, key);
>>   		} else {
>> -			kfree_skb(skb);
>> +			kfree_skb_reason(skb, SKB_DROP_REASON_PKT_TOO_BIG);
>>   		}
>>   	} else {
>> -		kfree_skb(skb);
>> +		kfree_skb_reason(skb, SKB_DROP_REASON_DEV_READY);
>>   	}
>>   }
>>   
>> @@ -1011,7 +1014,7 @@ static int dec_ttl_exception_handler(struct datapath *dp, struct sk_buff *skb,
>>   		return clone_execute(dp, skb, key, 0, nla_data(actions),
>>   				     nla_len(actions), true, false);
>>   
>> -	consume_skb(skb);
>> +	kfree_skb_reason(skb, OVS_DROP_IP_TTL);
>>   	return 0;
>>   }
>>   
>> @@ -1564,7 +1567,7 @@ static int clone_execute(struct datapath *dp, struct sk_buff *skb,
>>   		/* Out of per CPU action FIFO space. Drop the 'skb' and
>>   		 * log an error.
>>   		 */
>> -		kfree_skb(skb);
>> +		kfree_skb_reason(skb, OVS_DROP_DEFERRED_LIMIT);
>>   
>>   		if (net_ratelimit()) {
>>   			if (actions) { /* Sample action */
>> @@ -1616,7 +1619,7 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
>>   	if (unlikely(level > OVS_RECURSION_LIMIT)) {
>>   		net_crit_ratelimited("ovs: recursion limit reached on datapath %s, probable configuration error\n",
>>   				     ovs_dp_name(dp));
>> -		kfree_skb(skb);
>> +		kfree_skb_reason(skb, OVS_DROP_RECURSION_LIMIT);
>>   		err = -ENETDOWN;
>>   		goto out;
>>   	}
>> diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
>> index fa955e892210..b03ebd4a8fae 100644
>> --- a/net/openvswitch/conntrack.c
>> +++ b/net/openvswitch/conntrack.c
>> @@ -29,6 +29,7 @@
>>   #include <net/netfilter/nf_conntrack_act_ct.h>
>>   
>>   #include "datapath.h"
>> +#include "drop.h"
>>   #include "conntrack.h"
>>   #include "flow.h"
>>   #include "flow_netlink.h"
>> @@ -1035,7 +1036,7 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
>>   
>>   	skb_push_rcsum(skb, nh_ofs);
>>   	if (err)
>> -		kfree_skb(skb);
>> +		kfree_skb_reason(skb, OVS_DROP_CONNTRACK);
>>   	return err;
>>   }
>>   
>> diff --git a/net/openvswitch/drop.h b/net/openvswitch/drop.h
>> index 2440c836727f..744b8d1b93a3 100644
>> --- a/net/openvswitch/drop.h
>> +++ b/net/openvswitch/drop.h
>> @@ -12,6 +12,12 @@
>>   	R(OVS_DROP_EXPLICIT_ACTION)		\
>>   	R(OVS_DROP_EXPLICIT_ACTION_ERROR)	\
>>   	R(OVS_DROP_METER)			\
>> +	R(OVS_DROP_RECURSION_LIMIT)		\
>> +	R(OVS_DROP_DEFERRED_LIMIT)		\
>> +	R(OVS_DROP_FRAG_L2_TOO_LONG)		\
>> +	R(OVS_DROP_FRAG_INVALID_PROTO)		\
>> +	R(OVS_DROP_CONNTRACK)			\
>> +	R(OVS_DROP_IP_TTL)			\
>>   	/* deliberate comment for trailing \ */
>>   
>>   enum ovs_drop_reason {
> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next 0/7] openvswitch: add drop reasons
  2023-07-24 14:34 ` [PATCH net-next 0/7] openvswitch: add drop reasons Aaron Conole
@ 2023-07-26  8:34   ` Adrian Moreno
  0 siblings, 0 replies; 15+ messages in thread
From: Adrian Moreno @ 2023-07-26  8:34 UTC (permalink / raw)
  To: Aaron Conole
  Cc: netdev, dev, i.maximets, eric, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni



On 7/24/23 16:34, Aaron Conole wrote:
> Adrian Moreno <amorenoz@redhat.com> writes:
> 
>> There is currently a gap in drop visibility in the openvswitch module.
>> This series tries to improve this by adding a new drop reason subsystem
>> for OVS.
>>
>> Apart from adding a new drop reasson subsystem and some common drop
>> reasons, this series takes Eric's preliminary work [1] on adding an
>> explicit drop action and integrates it into the same subsystem.
>>
>> This series also adds some selftests and so it requires [2] to be
>> applied first.
>>
>> A limitation of this series is that it does not report upcall errors.
>> The reason is that there could be many sources of upcall drops and the
>> most common one, which is the netlink buffer overflow, cannot be
>> reported via kfree_skb() because the skb is freed in the netlink layer
>> (see [3]). Therefore, using a reason for the rare events and not the
>> common one would be even more misleading. I'd propose we add (in a
>> follow up patch) a tracepoint to better report upcall errors.
> 
> I guess you meant to add RFC tag to this, since it depends on other
> series that aren't accepted yet.
> 

Yep, sorry I should have added RFC tag.

> If it's okay, I will pull in your patch 5/7 when I re-post my flow
> additions series, since it will need to be added there at some point
> anyway.
> 

Sure, please go ahead.

>> [1] https://lore.kernel.org/netdev/202306300609.tdRdZscy-lkp@intel.com/T/
>> [2] https://lore.kernel.org/all/9375ccbc-dd40-9998-dde5-c94e4e28f4f1@redhat.com/T/
>> [3] commit 1100248a5c5c ("openvswitch: Fix double reporting of drops in dropwatch")
>>
>> Adrian Moreno (6):
>>    net: openvswitch: add datapath flow drop reason
>>    net: openvswitch: add meter drop reason
>>    net: openvswitch: add misc error drop reasons
>>    selftests: openvswitch: support key masks
>>    selftests: openvswitch: add drop reason testcase
>>    selftests: openvswitch: add explicit drop testcase
>>
>> Eric Garver (1):
>>    net: openvswitch: add explicit drop action
>>
>>   include/net/dropreason.h                      |   6 +
>>   include/uapi/linux/openvswitch.h              |   2 +
>>   net/openvswitch/actions.c                     |  40 ++++--
>>   net/openvswitch/conntrack.c                   |   3 +-
>>   net/openvswitch/datapath.c                    |  16 +++
>>   net/openvswitch/drop.h                        |  33 +++++
>>   net/openvswitch/flow_netlink.c                |   8 +-
>>   .../selftests/net/openvswitch/openvswitch.sh  |  92 +++++++++++++-
>>   .../selftests/net/openvswitch/ovs-dpctl.py    | 115 ++++++++++++------
>>   9 files changed, 267 insertions(+), 48 deletions(-)
>>   create mode 100644 net/openvswitch/drop.h
> 

-- 
Adrián Moreno


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2023-07-26  8:34 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-22  9:42 [PATCH net-next 0/7] openvswitch: add drop reasons Adrian Moreno
2023-07-22  9:42 ` [PATCH net-next 1/7] net: openvswitch: add datapath flow drop reason Adrian Moreno
2023-07-22  9:42 ` [PATCH net-next 2/7] net: openvswitch: add explicit drop action Adrian Moreno
2023-07-24 14:47   ` Aaron Conole
2023-07-26  8:31     ` Adrian Moreno
2023-07-22  9:42 ` [PATCH net-next 3/7] net: openvswitch: add meter drop reason Adrian Moreno
2023-07-22  9:42 ` [PATCH net-next 4/7] net: openvswitch: add misc error drop reasons Adrian Moreno
2023-07-24 15:23   ` Aaron Conole
2023-07-26  8:32     ` Adrian Moreno
2023-07-22  9:42 ` [PATCH net-next 5/7] selftests: openvswitch: support key masks Adrian Moreno
2023-07-22  9:42 ` [PATCH net-next 6/7] selftests: openvswitch: add drop reason testcase Adrian Moreno
2023-07-22  9:42 ` [PATCH net-next 7/7] selftests: openvswitch: add explicit drop testcase Adrian Moreno
2023-07-24 14:49   ` Aaron Conole
2023-07-24 14:34 ` [PATCH net-next 0/7] openvswitch: add drop reasons Aaron Conole
2023-07-26  8:34   ` Adrian Moreno

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).