Merge branch 'drop_monitor-Convert-to-use-devlink-tracepoint'

Ido Schimmel says:

====================
drop_monitor: Convert to use devlink tracepoint

Drop monitor is able to monitor both software and hardware originated
drops. Software drops are monitored by having drop monitor register its
probe on the 'kfree_skb' tracepoint. Hardware originated drops are
monitored by having devlink call into drop monitor whenever it receives
a dropped packet from the underlying hardware.

This patch set converts drop monitor to monitor both software and
hardware originated drops in the same way - by registering its probe on
the relevant tracepoint.

In addition to drop monitor being more consistent, it is now also
possible to build drop monitor as module instead of as a builtin and
still monitor hardware originated drops. Initially, CONFIG_NET_DEVLINK
implied CONFIG_NET_DROP_MONITOR, but after commit def2fbffe6
("kconfig: allow symbols implied by y to become m") we can have
CONFIG_NET_DEVLINK=y and CONFIG_NET_DROP_MONITOR=m and hardware
originated drops will not be monitored.

Patch set overview:

Patch #1 adds a tracepoint in devlink for trap reports.

Patch #2 prepares probe functions in drop monitor for the new
tracepoint.

Patch #3 converts drop monitor to use the new tracepoint.

Patches #4-#6 perform cleanups after the conversion.

Patch #7 adds a test case for drop monitor. Both software originated
drops and hardware originated drops (using netdevsim) are tested.

Tested:

| CONFIG_NET_DEVLINK | CONFIG_NET_DROP_MONITOR | Build | SW drops | HW drops |
| -------------------|-------------------------|-------|----------|----------|
|          y         |            y            |   v   |     v    |     v    |
|          y         |            m            |   v   |     v    |     v    |
|          y         |            n            |   v   |     x    |     x    |
|          n         |            y            |   v   |     v    |     x    |
|          n         |            m            |   v   |     v    |     x    |
|          n         |            n            |   v   |     x    |     x    |
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2020-09-30 18:01:27 -07:00
commit f2e834694b
10 changed files with 370 additions and 114 deletions

View File

@ -12065,7 +12065,6 @@ M: Neil Horman <nhorman@tuxdriver.com>
L: netdev@vger.kernel.org
S: Maintained
W: https://fedorahosted.org/dropwatch/
F: include/net/drop_monitor.h
F: include/uapi/linux/net_dropmon.h
F: net/core/drop_monitor.c

View File

@ -624,6 +624,22 @@ struct devlink_health_reporter_ops {
struct netlink_ext_ack *extack);
};
/**
* struct devlink_trap_metadata - Packet trap metadata.
* @trap_name: Trap name.
* @trap_group_name: Trap group name.
* @input_dev: Input netdevice.
* @fa_cookie: Flow action user cookie.
* @trap_type: Trap type.
*/
struct devlink_trap_metadata {
const char *trap_name;
const char *trap_group_name;
struct net_device *input_dev;
const struct flow_action_cookie *fa_cookie;
enum devlink_trap_type trap_type;
};
/**
* struct devlink_trap_policer - Immutable packet trap policer attributes.
* @id: Policer identifier.

View File

@ -1,36 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _NET_DROP_MONITOR_H_
#define _NET_DROP_MONITOR_H_
#include <linux/ktime.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/flow_offload.h>
/**
* struct net_dm_hw_metadata - Hardware-supplied packet metadata.
* @trap_group_name: Hardware trap group name.
* @trap_name: Hardware trap name.
* @input_dev: Input netdevice.
* @fa_cookie: Flow action user cookie.
*/
struct net_dm_hw_metadata {
const char *trap_group_name;
const char *trap_name;
struct net_device *input_dev;
const struct flow_action_cookie *fa_cookie;
};
#if IS_REACHABLE(CONFIG_NET_DROP_MONITOR)
void net_dm_hw_report(struct sk_buff *skb,
const struct net_dm_hw_metadata *hw_metadata);
#else
static inline void
net_dm_hw_report(struct sk_buff *skb,
const struct net_dm_hw_metadata *hw_metadata)
{
}
#endif
#endif /* _NET_DROP_MONITOR_H_ */

View File

@ -171,6 +171,43 @@ TRACE_EVENT(devlink_health_reporter_state_update,
__entry->new_state)
);
/*
* Tracepoint for devlink packet trap:
*/
TRACE_EVENT(devlink_trap_report,
TP_PROTO(const struct devlink *devlink, struct sk_buff *skb,
const struct devlink_trap_metadata *metadata),
TP_ARGS(devlink, skb, metadata),
TP_STRUCT__entry(
__string(bus_name, devlink->dev->bus->name)
__string(dev_name, dev_name(devlink->dev))
__string(driver_name, devlink->dev->driver->name)
__string(trap_name, metadata->trap_name)
__string(trap_group_name, metadata->trap_group_name)
__dynamic_array(char, input_dev_name, IFNAMSIZ)
),
TP_fast_assign(
struct net_device *input_dev = metadata->input_dev;
__assign_str(bus_name, devlink->dev->bus->name);
__assign_str(dev_name, dev_name(devlink->dev));
__assign_str(driver_name, devlink->dev->driver->name);
__assign_str(trap_name, metadata->trap_name);
__assign_str(trap_group_name, metadata->trap_group_name);
__assign_str(input_dev_name,
(input_dev ? input_dev->name : "NULL"));
),
TP_printk("bus_name=%s dev_name=%s driver_name=%s trap_name=%s "
"trap_group_name=%s input_dev_name=%s", __get_str(bus_name),
__get_str(dev_name), __get_str(driver_name),
__get_str(trap_name), __get_str(trap_group_name),
__get_str(input_dev_name))
);
#endif /* _TRACE_DEVLINK_H */
/* This part must be outside protection */

View File

@ -434,7 +434,6 @@ config NET_SOCK_MSG
config NET_DEVLINK
bool
default n
imply NET_DROP_MONITOR
config PAGE_POOL
bool

View File

@ -27,7 +27,6 @@
#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/devlink.h>
#include <net/drop_monitor.h>
#define CREATE_TRACE_POINTS
#include <trace/events/devlink.h>
@ -84,6 +83,7 @@ EXPORT_SYMBOL(devlink_dpipe_header_ipv6);
EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg);
EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwerr);
EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_trap_report);
static const struct nla_policy devlink_function_nl_policy[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1] = {
[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR] = { .type = NLA_BINARY },
@ -9261,20 +9261,19 @@ devlink_trap_stats_update(struct devlink_stats __percpu *trap_stats,
}
static void
devlink_trap_report_metadata_fill(struct net_dm_hw_metadata *hw_metadata,
const struct devlink_trap_item *trap_item,
struct devlink_port *in_devlink_port,
const struct flow_action_cookie *fa_cookie)
devlink_trap_report_metadata_set(struct devlink_trap_metadata *metadata,
const struct devlink_trap_item *trap_item,
struct devlink_port *in_devlink_port,
const struct flow_action_cookie *fa_cookie)
{
struct devlink_trap_group_item *group_item = trap_item->group_item;
hw_metadata->trap_group_name = group_item->group->name;
hw_metadata->trap_name = trap_item->trap->name;
hw_metadata->fa_cookie = fa_cookie;
metadata->trap_name = trap_item->trap->name;
metadata->trap_group_name = trap_item->group_item->group->name;
metadata->fa_cookie = fa_cookie;
metadata->trap_type = trap_item->trap->type;
spin_lock(&in_devlink_port->type_lock);
if (in_devlink_port->type == DEVLINK_PORT_TYPE_ETH)
hw_metadata->input_dev = in_devlink_port->type_dev;
metadata->input_dev = in_devlink_port->type_dev;
spin_unlock(&in_devlink_port->type_lock);
}
@ -9292,21 +9291,17 @@ void devlink_trap_report(struct devlink *devlink, struct sk_buff *skb,
{
struct devlink_trap_item *trap_item = trap_ctx;
struct net_dm_hw_metadata hw_metadata = {};
devlink_trap_stats_update(trap_item->stats, skb->len);
devlink_trap_stats_update(trap_item->group_item->stats, skb->len);
/* Control packets were not dropped by the device or encountered an
* exception during forwarding and therefore should not be reported to
* the kernel's drop monitor.
*/
if (trap_item->trap->type == DEVLINK_TRAP_TYPE_CONTROL)
return;
if (trace_devlink_trap_report_enabled()) {
struct devlink_trap_metadata metadata = {};
devlink_trap_report_metadata_fill(&hw_metadata, trap_item,
in_devlink_port, fa_cookie);
net_dm_hw_report(skb, &hw_metadata);
devlink_trap_report_metadata_set(&metadata, trap_item,
in_devlink_port, fa_cookie);
trace_devlink_trap_report(devlink, skb, &metadata);
}
}
EXPORT_SYMBOL_GPL(devlink_trap_report);

View File

@ -26,13 +26,14 @@
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <net/drop_monitor.h>
#include <net/genetlink.h>
#include <net/netevent.h>
#include <net/flow_offload.h>
#include <net/devlink.h>
#include <trace/events/skb.h>
#include <trace/events/napi.h>
#include <trace/events/devlink.h>
#include <asm/unaligned.h>
@ -114,13 +115,14 @@ struct net_dm_alert_ops {
int work, int budget);
void (*work_item_func)(struct work_struct *work);
void (*hw_work_item_func)(struct work_struct *work);
void (*hw_probe)(struct sk_buff *skb,
const struct net_dm_hw_metadata *hw_metadata);
void (*hw_trap_probe)(void *ignore, const struct devlink *devlink,
struct sk_buff *skb,
const struct devlink_trap_metadata *metadata);
};
struct net_dm_skb_cb {
union {
struct net_dm_hw_metadata *hw_metadata;
struct devlink_trap_metadata *hw_metadata;
void *pc;
};
};
@ -432,8 +434,9 @@ out:
}
static void
net_dm_hw_summary_probe(struct sk_buff *skb,
const struct net_dm_hw_metadata *hw_metadata)
net_dm_hw_trap_summary_probe(void *ignore, const struct devlink *devlink,
struct sk_buff *skb,
const struct devlink_trap_metadata *metadata)
{
struct net_dm_hw_entries *hw_entries;
struct net_dm_hw_entry *hw_entry;
@ -441,6 +444,9 @@ net_dm_hw_summary_probe(struct sk_buff *skb,
unsigned long flags;
int i;
if (metadata->trap_type == DEVLINK_TRAP_TYPE_CONTROL)
return;
hw_data = this_cpu_ptr(&dm_hw_cpu_data);
spin_lock_irqsave(&hw_data->lock, flags);
hw_entries = hw_data->hw_entries;
@ -450,7 +456,7 @@ net_dm_hw_summary_probe(struct sk_buff *skb,
for (i = 0; i < hw_entries->num_entries; i++) {
hw_entry = &hw_entries->entries[i];
if (!strncmp(hw_entry->trap_name, hw_metadata->trap_name,
if (!strncmp(hw_entry->trap_name, metadata->trap_name,
NET_DM_MAX_HW_TRAP_NAME_LEN - 1)) {
hw_entry->count++;
goto out;
@ -460,7 +466,7 @@ net_dm_hw_summary_probe(struct sk_buff *skb,
goto out;
hw_entry = &hw_entries->entries[hw_entries->num_entries];
strlcpy(hw_entry->trap_name, hw_metadata->trap_name,
strlcpy(hw_entry->trap_name, metadata->trap_name,
NET_DM_MAX_HW_TRAP_NAME_LEN - 1);
hw_entry->count = 1;
hw_entries->num_entries++;
@ -479,7 +485,7 @@ static const struct net_dm_alert_ops net_dm_alert_summary_ops = {
.napi_poll_probe = trace_napi_poll_hit,
.work_item_func = send_dm_alert,
.hw_work_item_func = net_dm_hw_summary_work,
.hw_probe = net_dm_hw_summary_probe,
.hw_trap_probe = net_dm_hw_trap_summary_probe,
};
static void net_dm_packet_trace_kfree_skb_hit(void *ignore,
@ -705,7 +711,7 @@ static void net_dm_packet_work(struct work_struct *work)
}
static size_t
net_dm_flow_action_cookie_size(const struct net_dm_hw_metadata *hw_metadata)
net_dm_flow_action_cookie_size(const struct devlink_trap_metadata *hw_metadata)
{
return hw_metadata->fa_cookie ?
nla_total_size(hw_metadata->fa_cookie->cookie_len) : 0;
@ -713,7 +719,7 @@ net_dm_flow_action_cookie_size(const struct net_dm_hw_metadata *hw_metadata)
static size_t
net_dm_hw_packet_report_size(size_t payload_len,
const struct net_dm_hw_metadata *hw_metadata)
const struct devlink_trap_metadata *hw_metadata)
{
size_t size;
@ -743,7 +749,7 @@ net_dm_hw_packet_report_size(size_t payload_len,
static int net_dm_hw_packet_report_fill(struct sk_buff *msg,
struct sk_buff *skb, size_t payload_len)
{
struct net_dm_hw_metadata *hw_metadata;
struct devlink_trap_metadata *hw_metadata;
struct nlattr *attr;
void *hdr;
@ -810,56 +816,56 @@ nla_put_failure:
return -EMSGSIZE;
}
static struct net_dm_hw_metadata *
net_dm_hw_metadata_clone(const struct net_dm_hw_metadata *hw_metadata)
static struct devlink_trap_metadata *
net_dm_hw_metadata_copy(const struct devlink_trap_metadata *metadata)
{
const struct flow_action_cookie *fa_cookie;
struct net_dm_hw_metadata *n_hw_metadata;
struct devlink_trap_metadata *hw_metadata;
const char *trap_group_name;
const char *trap_name;
n_hw_metadata = kzalloc(sizeof(*hw_metadata), GFP_ATOMIC);
if (!n_hw_metadata)
hw_metadata = kzalloc(sizeof(*hw_metadata), GFP_ATOMIC);
if (!hw_metadata)
return NULL;
trap_group_name = kstrdup(hw_metadata->trap_group_name, GFP_ATOMIC);
trap_group_name = kstrdup(metadata->trap_group_name, GFP_ATOMIC);
if (!trap_group_name)
goto free_hw_metadata;
n_hw_metadata->trap_group_name = trap_group_name;
hw_metadata->trap_group_name = trap_group_name;
trap_name = kstrdup(hw_metadata->trap_name, GFP_ATOMIC);
trap_name = kstrdup(metadata->trap_name, GFP_ATOMIC);
if (!trap_name)
goto free_trap_group;
n_hw_metadata->trap_name = trap_name;
hw_metadata->trap_name = trap_name;
if (hw_metadata->fa_cookie) {
if (metadata->fa_cookie) {
size_t cookie_size = sizeof(*fa_cookie) +
hw_metadata->fa_cookie->cookie_len;
metadata->fa_cookie->cookie_len;
fa_cookie = kmemdup(hw_metadata->fa_cookie, cookie_size,
fa_cookie = kmemdup(metadata->fa_cookie, cookie_size,
GFP_ATOMIC);
if (!fa_cookie)
goto free_trap_name;
n_hw_metadata->fa_cookie = fa_cookie;
hw_metadata->fa_cookie = fa_cookie;
}
n_hw_metadata->input_dev = hw_metadata->input_dev;
if (n_hw_metadata->input_dev)
dev_hold(n_hw_metadata->input_dev);
hw_metadata->input_dev = metadata->input_dev;
if (hw_metadata->input_dev)
dev_hold(hw_metadata->input_dev);
return n_hw_metadata;
return hw_metadata;
free_trap_name:
kfree(trap_name);
free_trap_group:
kfree(trap_group_name);
free_hw_metadata:
kfree(n_hw_metadata);
kfree(hw_metadata);
return NULL;
}
static void
net_dm_hw_metadata_free(const struct net_dm_hw_metadata *hw_metadata)
net_dm_hw_metadata_free(const struct devlink_trap_metadata *hw_metadata)
{
if (hw_metadata->input_dev)
dev_put(hw_metadata->input_dev);
@ -871,7 +877,7 @@ net_dm_hw_metadata_free(const struct net_dm_hw_metadata *hw_metadata)
static void net_dm_hw_packet_report(struct sk_buff *skb)
{
struct net_dm_hw_metadata *hw_metadata;
struct devlink_trap_metadata *hw_metadata;
struct sk_buff *msg;
size_t payload_len;
int rc;
@ -924,15 +930,19 @@ static void net_dm_hw_packet_work(struct work_struct *work)
}
static void
net_dm_hw_packet_probe(struct sk_buff *skb,
const struct net_dm_hw_metadata *hw_metadata)
net_dm_hw_trap_packet_probe(void *ignore, const struct devlink *devlink,
struct sk_buff *skb,
const struct devlink_trap_metadata *metadata)
{
struct net_dm_hw_metadata *n_hw_metadata;
struct devlink_trap_metadata *n_hw_metadata;
ktime_t tstamp = ktime_get_real();
struct per_cpu_dm_data *hw_data;
struct sk_buff *nskb;
unsigned long flags;
if (metadata->trap_type == DEVLINK_TRAP_TYPE_CONTROL)
return;
if (!skb_mac_header_was_set(skb))
return;
@ -940,7 +950,7 @@ net_dm_hw_packet_probe(struct sk_buff *skb,
if (!nskb)
return;
n_hw_metadata = net_dm_hw_metadata_clone(hw_metadata);
n_hw_metadata = net_dm_hw_metadata_copy(metadata);
if (!n_hw_metadata)
goto free;
@ -975,7 +985,7 @@ static const struct net_dm_alert_ops net_dm_alert_packet_ops = {
.napi_poll_probe = net_dm_packet_trace_napi_poll_hit,
.work_item_func = net_dm_packet_work,
.hw_work_item_func = net_dm_hw_packet_work,
.hw_probe = net_dm_hw_packet_probe,
.hw_trap_probe = net_dm_hw_trap_packet_probe,
};
static const struct net_dm_alert_ops *net_dm_alert_ops_arr[] = {
@ -983,25 +993,32 @@ static const struct net_dm_alert_ops *net_dm_alert_ops_arr[] = {
[NET_DM_ALERT_MODE_PACKET] = &net_dm_alert_packet_ops,
};
void net_dm_hw_report(struct sk_buff *skb,
const struct net_dm_hw_metadata *hw_metadata)
#if IS_ENABLED(CONFIG_NET_DEVLINK)
static int net_dm_hw_probe_register(const struct net_dm_alert_ops *ops)
{
rcu_read_lock();
if (!monitor_hw)
goto out;
net_dm_alert_ops_arr[net_dm_alert_mode]->hw_probe(skb, hw_metadata);
out:
rcu_read_unlock();
return register_trace_devlink_trap_report(ops->hw_trap_probe, NULL);
}
EXPORT_SYMBOL_GPL(net_dm_hw_report);
static void net_dm_hw_probe_unregister(const struct net_dm_alert_ops *ops)
{
unregister_trace_devlink_trap_report(ops->hw_trap_probe, NULL);
tracepoint_synchronize_unregister();
}
#else
static int net_dm_hw_probe_register(const struct net_dm_alert_ops *ops)
{
return -EOPNOTSUPP;
}
static void net_dm_hw_probe_unregister(const struct net_dm_alert_ops *ops)
{
}
#endif
static int net_dm_hw_monitor_start(struct netlink_ext_ack *extack)
{
const struct net_dm_alert_ops *ops;
int cpu;
int cpu, rc;
if (monitor_hw) {
NL_SET_ERR_MSG_MOD(extack, "Hardware monitoring already enabled");
@ -1025,13 +1042,24 @@ static int net_dm_hw_monitor_start(struct netlink_ext_ack *extack)
kfree(hw_entries);
}
rc = net_dm_hw_probe_register(ops);
if (rc) {
NL_SET_ERR_MSG_MOD(extack, "Failed to connect probe to devlink_trap_probe() tracepoint");
goto err_module_put;
}
monitor_hw = true;
return 0;
err_module_put:
module_put(THIS_MODULE);
return rc;
}
static void net_dm_hw_monitor_stop(struct netlink_ext_ack *extack)
{
const struct net_dm_alert_ops *ops;
int cpu;
if (!monitor_hw) {
@ -1039,12 +1067,11 @@ static void net_dm_hw_monitor_stop(struct netlink_ext_ack *extack)
return;
}
ops = net_dm_alert_ops_arr[net_dm_alert_mode];
monitor_hw = false;
/* After this call returns we are guaranteed that no CPU is processing
* any hardware drops.
*/
synchronize_rcu();
net_dm_hw_probe_unregister(ops);
for_each_possible_cpu(cpu) {
struct per_cpu_dm_data *hw_data = &per_cpu(dm_hw_cpu_data, cpu);
@ -1053,7 +1080,7 @@ static void net_dm_hw_monitor_stop(struct netlink_ext_ack *extack)
del_timer_sync(&hw_data->send_timer);
cancel_work_sync(&hw_data->dm_alert_work);
while ((skb = __skb_dequeue(&hw_data->drop_queue))) {
struct net_dm_hw_metadata *hw_metadata;
struct devlink_trap_metadata *hw_metadata;
hw_metadata = NET_DM_SKB_CB(skb)->hw_metadata;
net_dm_hw_metadata_free(hw_metadata);

View File

@ -19,6 +19,7 @@ TEST_PROGS += txtimestamp.sh
TEST_PROGS += vrf-xfrm-tests.sh
TEST_PROGS += rxtimestamp.sh
TEST_PROGS += devlink_port_split.py
TEST_PROGS += drop_monitor_tests.sh
TEST_PROGS_EXTENDED := in_netns.sh
TEST_GEN_FILES = socket nettest
TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy reuseport_addr_any

View File

@ -30,3 +30,6 @@ CONFIG_NET_SCH_ETF=m
CONFIG_NET_SCH_NETEM=y
CONFIG_TEST_BLACKHOLE_DEV=m
CONFIG_KALLSYMS=y
CONFIG_TRACEPOINTS=y
CONFIG_NET_DROP_MONITOR=m
CONFIG_NETDEVSIM=m

View File

@ -0,0 +1,215 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# This test is for checking drop monitor functionality.
ret=0
# Kselftest framework requirement - SKIP code is 4.
ksft_skip=4
# all tests in this script. Can be overridden with -t option
TESTS="
sw_drops
hw_drops
"
IP="ip -netns ns1"
TC="tc -netns ns1"
DEVLINK="devlink -N ns1"
NS_EXEC="ip netns exec ns1"
NETDEVSIM_PATH=/sys/bus/netdevsim/
DEV_ADDR=1337
DEV=netdevsim${DEV_ADDR}
DEVLINK_DEV=netdevsim/${DEV}
log_test()
{
local rc=$1
local expected=$2
local msg="$3"
if [ ${rc} -eq ${expected} ]; then
printf " TEST: %-60s [ OK ]\n" "${msg}"
nsuccess=$((nsuccess+1))
else
ret=1
nfail=$((nfail+1))
printf " TEST: %-60s [FAIL]\n" "${msg}"
fi
}
setup()
{
modprobe netdevsim &> /dev/null
set -e
ip netns add ns1
$IP link add dummy10 up type dummy
$NS_EXEC echo "$DEV_ADDR 1" > ${NETDEVSIM_PATH}/new_device
udevadm settle
local netdev=$($NS_EXEC ls ${NETDEVSIM_PATH}/devices/${DEV}/net/)
$IP link set dev $netdev up
set +e
}
cleanup()
{
$NS_EXEC echo "$DEV_ADDR" > ${NETDEVSIM_PATH}/del_device
ip netns del ns1
}
sw_drops_test()
{
echo
echo "Software drops test"
setup
local dir=$(mktemp -d)
$TC qdisc add dev dummy10 clsact
$TC filter add dev dummy10 egress pref 1 handle 101 proto ip \
flower dst_ip 192.0.2.10 action drop
$NS_EXEC mausezahn dummy10 -a 00:11:22:33:44:55 -b 00:aa:bb:cc:dd:ee \
-A 192.0.2.1 -B 192.0.2.10 -t udp sp=12345,dp=54321 -c 0 -q \
-d 100msec &
timeout 5 dwdump -o sw -w ${dir}/packets.pcap
(( $(tshark -r ${dir}/packets.pcap \
-Y 'ip.dst == 192.0.2.10' 2> /dev/null | wc -l) != 0))
log_test $? 0 "Capturing active software drops"
rm ${dir}/packets.pcap
{ kill %% && wait %%; } 2>/dev/null
timeout 5 dwdump -o sw -w ${dir}/packets.pcap
(( $(tshark -r ${dir}/packets.pcap \
-Y 'ip.dst == 192.0.2.10' 2> /dev/null | wc -l) == 0))
log_test $? 0 "Capturing inactive software drops"
rm -r $dir
cleanup
}
hw_drops_test()
{
echo
echo "Hardware drops test"
setup
local dir=$(mktemp -d)
$DEVLINK trap set $DEVLINK_DEV trap blackhole_route action trap
timeout 5 dwdump -o hw -w ${dir}/packets.pcap
(( $(tshark -r ${dir}/packets.pcap \
-Y 'net_dm.hw_trap_name== blackhole_route' 2> /dev/null \
| wc -l) != 0))
log_test $? 0 "Capturing active hardware drops"
rm ${dir}/packets.pcap
$DEVLINK trap set $DEVLINK_DEV trap blackhole_route action drop
timeout 5 dwdump -o hw -w ${dir}/packets.pcap
(( $(tshark -r ${dir}/packets.pcap \
-Y 'net_dm.hw_trap_name== blackhole_route' 2> /dev/null \
| wc -l) == 0))
log_test $? 0 "Capturing inactive hardware drops"
rm -r $dir
cleanup
}
################################################################################
# usage
usage()
{
cat <<EOF
usage: ${0##*/} OPTS
-t <test> Test(s) to run (default: all)
(options: $TESTS)
EOF
}
################################################################################
# main
while getopts ":t:h" opt; do
case $opt in
t) TESTS=$OPTARG;;
h) usage; exit 0;;
*) usage; exit 1;;
esac
done
if [ "$(id -u)" -ne 0 ];then
echo "SKIP: Need root privileges"
exit $ksft_skip;
fi
if [ ! -x "$(command -v ip)" ]; then
echo "SKIP: Could not run test without ip tool"
exit $ksft_skip
fi
if [ ! -x "$(command -v devlink)" ]; then
echo "SKIP: Could not run test without devlink tool"
exit $ksft_skip
fi
if [ ! -x "$(command -v tshark)" ]; then
echo "SKIP: Could not run test without tshark tool"
exit $ksft_skip
fi
if [ ! -x "$(command -v dwdump)" ]; then
echo "SKIP: Could not run test without dwdump tool"
exit $ksft_skip
fi
if [ ! -x "$(command -v udevadm)" ]; then
echo "SKIP: Could not run test without udevadm tool"
exit $ksft_skip
fi
if [ ! -x "$(command -v timeout)" ]; then
echo "SKIP: Could not run test without timeout tool"
exit $ksft_skip
fi
if [ ! -x "$(command -v mausezahn)" ]; then
echo "SKIP: Could not run test without mausezahn tool"
exit $ksft_skip
fi
tshark -G fields 2> /dev/null | grep -q net_dm
if [ $? -ne 0 ]; then
echo "SKIP: tshark too old, missing net_dm dissector"
exit $ksft_skip
fi
# start clean
cleanup &> /dev/null
for t in $TESTS
do
case $t in
sw_drops|sw) sw_drops_test;;
hw_drops|hw) hw_drops_test;;
help) echo "Test names: $TESTS"; exit 0;;
esac
done
if [ "$TESTS" != "none" ]; then
printf "\nTests passed: %3d\n" ${nsuccess}
printf "Tests failed: %3d\n" ${nfail}
fi
exit $ret