diff --git a/include/zephyr/net/net_stats.h b/include/zephyr/net/net_stats.h index c4f39fe305510a..f41bf204e9682f 100644 --- a/include/zephyr/net/net_stats.h +++ b/include/zephyr/net/net_stats.h @@ -226,6 +226,20 @@ struct net_stats_ipv4_igmp { net_stats_t drop; }; +/** + * @brief DNS statistics + */ +struct net_stats_dns { + /** Number of received DNS queries */ + net_stats_t recv; + + /** Number of sent DNS responses */ + net_stats_t sent; + + /** Number of dropped DNS packets */ + net_stats_t drop; +}; + /** * @brief Network packet transfer times for calculating average TX time */ @@ -375,6 +389,11 @@ struct net_stats { struct net_stats_ipv4_igmp ipv4_igmp; #endif +#if defined(CONFIG_NET_STATISTICS_DNS) + /** DNS statistics */ + struct net_stats_dns dns; +#endif + #if NET_TC_COUNT > 1 /** Traffic class statistics */ struct net_stats_tc tc; diff --git a/subsys/net/ip/Kconfig.stats b/subsys/net/ip/Kconfig.stats index 53105e0d70c457..ae0d6e95e46b03 100644 --- a/subsys/net/ip/Kconfig.stats +++ b/subsys/net/ip/Kconfig.stats @@ -93,6 +93,13 @@ config NET_STATISTICS_IGMP help Keep track of IGMP related statistics +config NET_STATISTICS_DNS + bool "Domain Name Service (DNS) statistics" + depends on DNS_RESOLVER || MDNS_RESPONDER || LLMNR_RESPONDER + default y + help + Keep track of DNS related statistics + config NET_STATISTICS_PPP bool "Point-to-point (PPP) statistics" depends on NET_L2_PPP diff --git a/subsys/net/ip/net_stats.h b/subsys/net/ip/net_stats.h index 710b1d98e46d27..431461b497eeec 100644 --- a/subsys/net/ip/net_stats.h +++ b/subsys/net/ip/net_stats.h @@ -345,6 +345,27 @@ static inline void net_stats_update_ipv4_igmp_drop(struct net_if *iface) #define net_stats_update_ipv4_igmp_drop(iface) #endif /* CONFIG_NET_STATISTICS_IGMP */ +#if defined(CONFIG_NET_STATISTICS_DNS) +static inline void net_stats_update_dns_recv(struct net_if *iface) +{ + UPDATE_STAT(iface, stats.dns.recv++); +} + +static inline void net_stats_update_dns_sent(struct net_if *iface) +{ + UPDATE_STAT(iface, stats.dns.sent++); +} + +static inline void net_stats_update_dns_drop(struct net_if *iface) +{ + UPDATE_STAT(iface, stats.dns.drop++); +} +#else +#define net_stats_update_dns_recv(iface) +#define net_stats_update_dns_sent(iface) +#define net_stats_update_dns_drop(iface) +#endif /* CONFIG_NET_STATISTICS_DNS */ + #if defined(CONFIG_NET_PKT_TXTIME_STATS) && defined(CONFIG_NET_STATISTICS) static inline void net_stats_update_tx_time(struct net_if *iface, uint32_t start_time, diff --git a/subsys/net/lib/dns/dispatcher.c b/subsys/net/lib/dns/dispatcher.c index 68244b830ba2a1..674872e65ee5d6 100644 --- a/subsys/net/lib/dns/dispatcher.c +++ b/subsys/net/lib/dns/dispatcher.c @@ -11,9 +11,11 @@ LOG_MODULE_REGISTER(net_dns_dispatcher, CONFIG_DNS_SOCKET_DISPATCHER_LOG_LEVEL); #include #include #include +#include #include #include +#include "../../ip/net_stats.h" #include "dns_pack.h" static K_MUTEX_DEFINE(lock); @@ -95,6 +97,24 @@ static int dns_dispatch(struct dns_socket_dispatcher *dispatcher, } done: + if (IS_ENABLED(CONFIG_NET_STATISTICS_DNS)) { + struct net_if *iface = NULL; + + if (IS_ENABLED(CONFIG_NET_IPV6) && addr->sa_family == AF_INET6) { + iface = net_if_ipv6_select_src_iface(&net_sin6(addr)->sin6_addr); + } else if (IS_ENABLED(CONFIG_NET_IPV4) && addr->sa_family == AF_INET) { + iface = net_if_ipv4_select_src_iface(&net_sin(addr)->sin_addr); + } + + if (iface != NULL) { + if (ret < 0) { + net_stats_update_dns_drop(iface); + } else { + net_stats_update_dns_recv(iface); + } + } + } + return ret; } diff --git a/subsys/net/lib/dns/llmnr_responder.c b/subsys/net/lib/dns/llmnr_responder.c index 21832efdf670cc..bc56cbb149007f 100644 --- a/subsys/net/lib/dns/llmnr_responder.c +++ b/subsys/net/lib/dns/llmnr_responder.c @@ -30,6 +30,7 @@ LOG_MODULE_REGISTER(net_llmnr_responder, CONFIG_LLMNR_RESPONDER_LOG_LEVEL); #include "dns_pack.h" #include "ipv6.h" +#include "../../ip/net_stats.h" #include "net_private.h" @@ -401,6 +402,19 @@ static int send_response(int sock, net_sprint_ipv4_addr(&net_sin((struct sockaddr *)&dst)->sin_addr) : net_sprint_ipv6_addr(&net_sin6((struct sockaddr *)&dst)->sin6_addr), ret); + } else { + struct net_if *iface = NULL; + struct sockaddr *addr = (struct sockaddr *)&dst; + + if (IS_ENABLED(CONFIG_NET_IPV6) && src_addr->sa_family == AF_INET6) { + iface = net_if_ipv6_select_src_iface(&net_sin6(addr)->sin6_addr); + } else if (IS_ENABLED(CONFIG_NET_IPV4) && src_addr->sa_family == AF_INET) { + iface = net_if_ipv4_select_src_iface(&net_sin(addr)->sin_addr); + } + + if (iface != NULL) { + net_stats_update_dns_sent(iface); + } } return ret; diff --git a/subsys/net/lib/dns/mdns_responder.c b/subsys/net/lib/dns/mdns_responder.c index f9a3b75bd47cf2..ab8977d1c72b59 100644 --- a/subsys/net/lib/dns/mdns_responder.c +++ b/subsys/net/lib/dns/mdns_responder.c @@ -32,6 +32,7 @@ LOG_MODULE_REGISTER(net_mdns_responder, CONFIG_MDNS_RESPONDER_LOG_LEVEL); #include "dns_sd.h" #include "dns_pack.h" #include "ipv6.h" +#include "../../ip/net_stats.h" #include "net_private.h" @@ -336,6 +337,8 @@ static int send_response(int sock, (struct sockaddr *)&dst, dst_len); if (ret < 0) { NET_DBG("Cannot send %s reply (%d)", "mDNS", ret); + } else { + net_stats_update_dns_sent(iface); } return ret; @@ -496,6 +499,8 @@ static void send_sd_response(int sock, if (ret < 0) { NET_DBG("Cannot send %s reply (%d)", "mDNS", ret); continue; + } else { + net_stats_update_dns_sent(iface); } } } diff --git a/subsys/net/lib/dns/resolve.c b/subsys/net/lib/dns/resolve.c index 9aa296e89fd398..14cd6890541ade 100644 --- a/subsys/net/lib/dns/resolve.c +++ b/subsys/net/lib/dns/resolve.c @@ -29,6 +29,7 @@ LOG_MODULE_REGISTER(net_dns_resolve, CONFIG_DNS_RESOLVER_LOG_LEVEL); #include "dns_pack.h" #include "dns_internal.h" #include "dns_cache.h" +#include "../../ip/net_stats.h" #define DNS_SERVER_COUNT CONFIG_DNS_RESOLVER_MAX_SERVERS #define SERVER_COUNT (DNS_SERVER_COUNT + DNS_MAX_MCAST_SERVERS) @@ -1041,6 +1042,20 @@ static int dns_write(struct dns_resolve_context *ctx, if (ret < 0) { NET_DBG("Cannot send query (%d)", -errno); return ret; + } else { + if (IS_ENABLED(CONFIG_NET_STATISTICS_DNS)) { + struct net_if *iface = NULL; + + if (IS_ENABLED(CONFIG_NET_IPV6) && server->sa_family == AF_INET6) { + iface = net_if_ipv6_select_src_iface(&net_sin6(server)->sin6_addr); + } else if (IS_ENABLED(CONFIG_NET_IPV4) && server->sa_family == AF_INET) { + iface = net_if_ipv4_select_src_iface(&net_sin(server)->sin_addr); + } + + if (iface != NULL) { + net_stats_update_dns_sent(iface); + } + } } return 0; diff --git a/subsys/net/lib/shell/stats.c b/subsys/net/lib/shell/stats.c index 7e38cf48594994..0896add25f997a 100644 --- a/subsys/net/lib/shell/stats.c +++ b/subsys/net/lib/shell/stats.c @@ -537,6 +537,12 @@ static void net_shell_print_statistics(struct net_if *iface, void *user_data) GET_STAT(iface, tcp.connrst)); PR("TCP pkt drop %d\n", GET_STAT(iface, tcp.drop)); #endif +#if defined(CONFIG_NET_STATISTICS_DNS) + PR("DNS recv %d\tsent\t%d\tdrop\t%d\n", + GET_STAT(iface, dns.recv), + GET_STAT(iface, dns.sent), + GET_STAT(iface, dns.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));