Browse Source

net: pkt_filter: Add statistics support to packet filter

As the network packet filter drops packets without any indication
that the packet is dropped, it can be difficult to monitor what
is going on in the system when receiving data. The user can
now monitor the statistics and see if packets are being dropped
because of packet filter activity.

Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
pull/88679/head
Jukka Rissanen 3 months ago committed by Benjamin Cabé
parent
commit
cde70232b9
  1. 92
      include/zephyr/net/net_stats.h
  2. 7
      subsys/net/ip/Kconfig.stats
  3. 1
      subsys/net/ip/connection.c
  4. 1
      subsys/net/ip/ipv4.c
  5. 1
      subsys/net/ip/ipv6.c
  6. 5
      subsys/net/ip/net_core.c
  7. 5
      subsys/net/ip/net_if.c
  8. 44
      subsys/net/ip/net_stats.h
  9. 15
      subsys/net/lib/shell/stats.c

92
include/zephyr/net/net_stats.h

@ -371,6 +371,34 @@ struct net_stats_pm { @@ -371,6 +371,34 @@ struct net_stats_pm {
uint32_t start_time;
};
/**
* @brief Network packet filter statistics
*/
struct net_stats_pkt_filter {
/** Network packet filter RX statistics */
struct {
/** Network packets dropped at network interface level */
net_stats_t drop;
#if defined(CONFIG_NET_PKT_FILTER_IPV4_HOOK)
/** IPv4 packets dropped at network interface level */
net_stats_t ipv4_drop;
#endif
#if defined(CONFIG_NET_PKT_FILTER_IPV6_HOOK)
/** IPv6 packets dropped at network interface level */
net_stats_t ipv6_drop;
#endif
#if defined(CONFIG_NET_PKT_FILTER_LOCAL_IN_HOOK)
/** Packets dropped at connection input */
net_stats_t local_drop;
#endif
} rx;
/** Network packet filter TX statistics */
struct {
/** Network packets dropped at network interface level */
net_stats_t drop;
} tx;
};
/**
* @brief All network statistics in one struct.
@ -388,6 +416,10 @@ struct net_stats { @@ -388,6 +416,10 @@ struct net_stats {
/** IP layer errors */
struct net_stats_ip_errors ip_errors;
#if defined(CONFIG_NET_STATISTICS_PKT_FILTER)
struct net_stats_pkt_filter pkt_filter;
#endif
#if defined(CONFIG_NET_STATISTICS_IPV6)
/** IPv6 statistics */
struct net_stats_ip ipv6;
@ -709,6 +741,7 @@ struct net_stats_wifi { @@ -709,6 +741,7 @@ struct net_stats_wifi {
enum net_request_stats_cmd {
NET_REQUEST_STATS_CMD_GET_ALL = 1,
NET_REQUEST_STATS_CMD_GET_PROCESSING_ERROR,
NET_REQUEST_STATS_CMD_GET_PKT_FILTER_DROP,
NET_REQUEST_STATS_CMD_GET_BYTES,
NET_REQUEST_STATS_CMD_GET_IP_ERRORS,
NET_REQUEST_STATS_CMD_GET_IPV4,
@ -737,6 +770,10 @@ enum net_request_stats_cmd { @@ -737,6 +770,10 @@ enum net_request_stats_cmd {
#define NET_REQUEST_STATS_GET_PROCESSING_ERROR \
(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_PROCESSING_ERROR)
/** Request all pkt_filter drop statistics */
#define NET_REQUEST_STATS_GET_PKT_FILTER_DROP \
(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_PKT_FILTER_DROP)
/** Request number of received and sent bytes */
#define NET_REQUEST_STATS_GET_BYTES \
(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_BYTES)
@ -752,6 +789,10 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PROCESSING_ERROR); @@ -752,6 +789,10 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PROCESSING_ERROR);
NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_BYTES);
NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IP_ERRORS);
#if defined(CONFIG_NET_STATISTICS_PKT_FILTER)
NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PKT_FILTER_DROP);
#endif /* CONFIG_NET_STATISTICS_PKT_FILTER */
/** @endcond */
#if defined(CONFIG_NET_STATISTICS_IPV4)
@ -1373,6 +1414,55 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_RESET_WIFI); @@ -1373,6 +1414,55 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_RESET_WIFI);
#define NET_STATS_PROMETHEUS_RX_TIME(iface, dev_id, sfx)
#endif
#define NET_STATS_PROMETHEUS_PKT_FILTER_IPV4(iface, dev_id, sfx) \
NET_STATS_PROMETHEUS_COUNTER_DEFINE( \
"Packet filter RX IPv4 drop", \
NET_STATS_GET_INSTANCE(dev_id, sfx, pkt_filter_rx_ipv4_drop), \
"packet_count", \
NET_STATS_GET_COLLECTOR_NAME(dev_id, sfx), \
NET_STATS_GET_VAR(dev_id, sfx, pkt_filter_rx_ipv4_drop),\
&(iface)->stats.pkt_filter.rx.ipv4_drop);
#define NET_STATS_PROMETHEUS_PKT_FILTER_IPV6(iface, dev_id, sfx) \
NET_STATS_PROMETHEUS_COUNTER_DEFINE( \
"Packet filter RX IPv6 drop", \
NET_STATS_GET_INSTANCE(dev_id, sfx, pkt_filter_rx_ipv6_drop), \
"packet_count", \
NET_STATS_GET_COLLECTOR_NAME(dev_id, sfx), \
NET_STATS_GET_VAR(dev_id, sfx, pkt_filter_rx_ipv6_drop),\
&(iface)->stats.pkt_filter.rx.ipv6_drop);
#define NET_STATS_PROMETHEUS_PKT_FILTER_LOCAL(iface, dev_id, sfx) \
NET_STATS_PROMETHEUS_COUNTER_DEFINE( \
"Packet filter RX local drop", \
NET_STATS_GET_INSTANCE(dev_id, sfx, pkt_filter_rx_local_drop), \
"packet_count", \
NET_STATS_GET_COLLECTOR_NAME(dev_id, sfx), \
NET_STATS_GET_VAR(dev_id, sfx, pkt_filter_rx_local_drop),\
&(iface)->stats.pkt_filter.rx.local_drop);
#define NET_STATS_PROMETHEUS_PKT_FILTER(iface, dev_id, sfx) \
NET_STATS_PROMETHEUS_COUNTER_DEFINE( \
"Packet filter RX drop", \
NET_STATS_GET_INSTANCE(dev_id, sfx, pkt_filter_rx_drop),\
"packet_count", \
NET_STATS_GET_COLLECTOR_NAME(dev_id, sfx), \
NET_STATS_GET_VAR(dev_id, sfx, pkt_filter_rx_drop), \
&(iface)->stats.pkt_filter.rx.drop); \
NET_STATS_PROMETHEUS_COUNTER_DEFINE( \
"Packet filter TX drop", \
NET_STATS_GET_INSTANCE(dev_id, sfx, pkt_filter_tx_drop),\
"packet_count", \
NET_STATS_GET_COLLECTOR_NAME(dev_id, sfx), \
NET_STATS_GET_VAR(dev_id, sfx, pkt_filter_tx_drop), \
&(iface)->stats.pkt_filter.tx.drop); \
IF_ENABLED(CONFIG_NET_PKT_FILTER_IPV4_HOOK, \
(NET_STATS_PROMETHEUS_PKT_FILTER_IPV4(iface, dev_id, sfx))) \
IF_ENABLED(CONFIG_NET_PKT_FILTER_IPV6_HOOK, \
(NET_STATS_PROMETHEUS_PKT_FILTER_IPV6(iface, dev_id, sfx))) \
IF_ENABLED(CONFIG_NET_PKT_FILTER_LOCAL_IN_HOOK, \
(NET_STATS_PROMETHEUS_PKT_FILTER_LOCAL(iface, dev_id, sfx)))
/* Per network interface statistics via Prometheus */
#define NET_STATS_PROMETHEUS(iface, dev_id, sfx) \
NET_STATS_PROMETHEUS_COUNTER_DEFINE( \
@ -1382,6 +1472,8 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_RESET_WIFI); @@ -1382,6 +1472,8 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_RESET_WIFI);
NET_STATS_GET_COLLECTOR_NAME(dev_id, sfx), \
NET_STATS_GET_VAR(dev_id, sfx, processing_error), \
&(iface)->stats.processing_error); \
IF_ENABLED(CONFIG_NET_STATISTICS_PKT_FILTER, \
(NET_STATS_PROMETHEUS_PKT_FILTER(iface, dev_id, sfx))) \
/* IP layer error statistics */ \
NET_STATS_PROMETHEUS_COUNTER_DEFINE( \
"IP proto error", \

7
subsys/net/ip/Kconfig.stats

@ -114,6 +114,13 @@ config NET_STATISTICS_DNS @@ -114,6 +114,13 @@ config NET_STATISTICS_DNS
help
Keep track of DNS related statistics
config NET_STATISTICS_PKT_FILTER
bool "Network packet filter statistics"
depends on NET_PKT_FILTER
default y
help
Keep track of network packet filter related statistics
config NET_STATISTICS_PPP
bool "Point-to-point (PPP) statistics"
depends on NET_L2_PPP

1
subsys/net/ip/connection.c

@ -676,6 +676,7 @@ enum net_verdict net_conn_input(struct net_pkt *pkt, @@ -676,6 +676,7 @@ enum net_verdict net_conn_input(struct net_pkt *pkt,
if (!net_pkt_filter_local_in_recv_ok(pkt)) {
/* drop the packet */
net_stats_update_filter_rx_local_drop(net_pkt_iface(pkt));
return NET_DROP;
}

1
subsys/net/ip/ipv4.c

@ -343,6 +343,7 @@ enum net_verdict net_ipv4_input(struct net_pkt *pkt, bool is_loopback) @@ -343,6 +343,7 @@ enum net_verdict net_ipv4_input(struct net_pkt *pkt, bool is_loopback)
if (!net_pkt_filter_ip_recv_ok(pkt)) {
/* drop the packet */
net_stats_update_filter_rx_ipv4_drop(net_pkt_iface(pkt));
return NET_DROP;
}

1
subsys/net/ip/ipv6.c

@ -584,6 +584,7 @@ enum net_verdict net_ipv6_input(struct net_pkt *pkt, bool is_loopback) @@ -584,6 +584,7 @@ enum net_verdict net_ipv6_input(struct net_pkt *pkt, bool is_loopback)
if (!net_pkt_filter_ip_recv_ok(pkt)) {
/* drop the packet */
NET_DBG("DROP: pkt filter");
net_stats_update_filter_rx_ipv6_drop(net_pkt_iface(pkt));
return NET_DROP;
}

5
subsys/net/ip/net_core.c

@ -583,7 +583,10 @@ int net_recv_data(struct net_if *iface, struct net_pkt *pkt) @@ -583,7 +583,10 @@ int net_recv_data(struct net_if *iface, struct net_pkt *pkt)
net_pkt_set_iface(pkt, iface);
if (!net_pkt_filter_recv_ok(pkt)) {
/* silently drop the packet */
/* Silently drop the packet, but update the statistics in order
* to be able to monitor filter activity.
*/
net_stats_update_filter_rx_drop(net_pkt_iface(pkt));
net_pkt_unref(pkt);
} else {
net_queue_rx(iface, pkt);

5
subsys/net/ip/net_if.c

@ -340,7 +340,10 @@ void net_process_tx_packet(struct net_pkt *pkt) @@ -340,7 +340,10 @@ void net_process_tx_packet(struct net_pkt *pkt)
void net_if_try_queue_tx(struct net_if *iface, struct net_pkt *pkt, k_timeout_t timeout)
{
if (!net_pkt_filter_send_ok(pkt)) {
/* silently drop the packet */
/* Silently drop the packet, but update the statistics in order
* to be able to monitor filter activity.
*/
net_stats_update_filter_tx_drop(net_pkt_iface(pkt));
net_pkt_unref(pkt);
return;
}

44
subsys/net/ip/net_stats.h

@ -59,12 +59,56 @@ static inline void net_stats_update_bytes_sent(struct net_if *iface, @@ -59,12 +59,56 @@ static inline void net_stats_update_bytes_sent(struct net_if *iface,
{
UPDATE_STAT(iface, stats.bytes.sent += bytes);
}
#if defined(CONFIG_NET_STATISTICS_PKT_FILTER)
static inline void net_stats_update_filter_rx_drop(struct net_if *iface)
{
UPDATE_STAT(iface, stats.pkt_filter.rx.drop++);
}
static inline void net_stats_update_filter_tx_drop(struct net_if *iface)
{
UPDATE_STAT(iface, stats.pkt_filter.tx.drop++);
}
static inline void net_stats_update_filter_rx_ipv4_drop(struct net_if *iface)
{
#if defined(CONFIG_NET_PKT_FILTER_IPV4_HOOK)
UPDATE_STAT(iface, stats.pkt_filter.rx.ipv4_drop++);
#endif
}
static inline void net_stats_update_filter_rx_ipv6_drop(struct net_if *iface)
{
#if defined(CONFIG_NET_PKT_FILTER_IPV6_HOOK)
UPDATE_STAT(iface, stats.pkt_filter.rx.ipv6_drop++);
#endif
}
static inline void net_stats_update_filter_rx_local_drop(struct net_if *iface)
{
#if defined(CONFIG_NET_PKT_FILTER_LOCAL_IN_HOOK)
UPDATE_STAT(iface, stats.pkt_filter.rx.local_drop++);
#endif
}
#else /* CONFIG_NET_STATISTICS_PKT_FILTER */
#define net_stats_update_filter_rx_drop(iface)
#define net_stats_update_filter_tx_drop(iface)
#define net_stats_update_filter_rx_ipv4_drop(iface)
#define net_stats_update_filter_rx_ipv6_drop(iface)
#define net_stats_update_filter_rx_local_drop(iface)
#endif /* CONFIG_NET_STATISTICS_PKT_FILTER */
#else
#define net_stats_update_processing_error(iface)
#define net_stats_update_ip_errors_protoerr(iface)
#define net_stats_update_ip_errors_vhlerr(iface)
#define net_stats_update_bytes_recv(iface, bytes)
#define net_stats_update_bytes_sent(iface, bytes)
#define net_stats_update_filter_rx_drop(iface)
#define net_stats_update_filter_tx_drop(iface)
#define net_stats_update_filter_rx_ipv4_drop(iface)
#define net_stats_update_filter_rx_ipv6_drop(iface)
#define net_stats_update_filter_rx_local_drop(iface)
#endif /* CONFIG_NET_STATISTICS */
#if defined(CONFIG_NET_STATISTICS_IPV6) && defined(CONFIG_NET_NATIVE_IPV6)

15
subsys/net/lib/shell/stats.c

@ -559,6 +559,21 @@ static void net_shell_print_statistics(struct net_if *iface, void *user_data) @@ -559,6 +559,21 @@ static void net_shell_print_statistics(struct net_if *iface, void *user_data)
GET_STAT(iface, dns.sent),
GET_STAT(iface, dns.drop));
#endif /* CONFIG_NET_STATISTICS_DNS */
#if defined(CONFIG_NET_STATISTICS_PKT_FILTER)
PR("Filter drop rx %d"
IF_ENABLED(CONFIG_NET_PKT_FILTER_IPV4_HOOK, ("\tIPv4\t%d"))
IF_ENABLED(CONFIG_NET_PKT_FILTER_IPV6_HOOK, ("\tIPv6\t%d"))
IF_ENABLED(CONFIG_NET_PKT_FILTER_LOCAL_IN_HOOK, ("\tlocal\t%d"))
"\ttx\t%d\n",
GET_STAT(iface, pkt_filter.rx.drop),
IF_ENABLED(CONFIG_NET_PKT_FILTER_IPV4_HOOK,
(GET_STAT(iface, pkt_filter.rx.ipv4_drop),))
IF_ENABLED(CONFIG_NET_PKT_FILTER_IPV6_HOOK,
(GET_STAT(iface, pkt_filter.rx.ipv6_drop),))
IF_ENABLED(CONFIG_NET_PKT_FILTER_LOCAL_IN_HOOK,
(GET_STAT(iface, pkt_filter.rx.local_drop),))
GET_STAT(iface, pkt_filter.tx.drop));
#endif /* CONFIG_NET_STATISTICS_DNS */
PR("Bytes received %u\n", GET_STAT(iface, bytes.received));
PR("Bytes sent %u\n", GET_STAT(iface, bytes.sent));

Loading…
Cancel
Save