@@ -1250,6 +1250,20 @@ struct cfg80211_tid_stats {
#define IEEE80211_MAX_CHAINS 4
/**
+ * struct mc_bc_stats - per STA multicast/broadcast data packets
+ * @mc_pkts: number of multicast packets
+ * @mc_bytes: number of bytes of multicast
+ * @bc_pkts: number of broadcast packets
+ * @bc_bytes: number of bytes of broadcast
+ */
+struct mc_bc_stats {
+ u64 mc_pkts;
+ u64 mc_bytes;
+ u64 bc_pkts;
+ u64 bc_bytes;
+};
+
+/**
* struct station_info - station information
*
* Station information filled by driver for get_station() and dump_station.
@@ -1311,6 +1325,7 @@ struct cfg80211_tid_stats {
* an FCS error. This counter should be incremented only when TA of the
* received packet with an FCS error matches the peer MAC address.
* @airtime_link_metric: mesh airtime link metric.
+ * @mc_bc_stat: per STA rx mcast/bcast count stats.
*/
struct station_info {
u64 filled;
@@ -1364,6 +1379,8 @@ struct station_info {
u32 fcs_err_count;
u32 airtime_link_metric;
+
+ struct mc_bc_stats mc_bc_stat;
};
#if IS_ENABLED(CONFIG_CFG80211)
@@ -3054,6 +3054,32 @@ enum nl80211_sta_bss_param {
};
/**
+ * enum nl80211_rx_mcast_bcast - per sta received mc/bc packet count information
+ *
+ * These attribute types are used with %NL80211_STA_INFO_RX_MCAST_BCAST
+ * when getting information about a station's received mcast/bcast packets.
+ *
+ * __NL80211_RX_MCAST_BCAST_INVALID: attribute number 0 is reserved
+ * @NL80211_RX_MCAST_PACKETS: number of received multicast packets
+ * @NL80211_RX_MCAST_BYTES: number of received multicast bytes
+ * @NL80211_RX_BCAST_PACKETS: number of received broadcast packets
+ * @NL80211_RX_BCAST_BYTES: number of received broadcast bytes
+ * @_NL80211_RX_MCAST_BCAST_AFTER_LAST: internal use
+ * @NL80211_RX_MCAST_BCAST_MAX: highest rx mcast_bcast info number
+ */
+enum nl80211_rx_mcast_bcast {
+ __NL80211_RX_MCAST_BCAST_INVALID,
+ NL80211_RX_MCAST_PACKETS,
+ NL80211_RX_MCAST_BYTES,
+ NL80211_RX_BCAST_PACKETS,
+ NL80211_RX_BCAST_BYTES,
+
+ /* keep last */
+ __NL80211_RX_MCAST_BCAST_AFTER_LAST,
+ NL80211_RX_MCAST_BCAST_MAX = __NL80211_RX_MCAST_BCAST_AFTER_LAST - 1
+};
+
+/**
* enum nl80211_sta_info - station information
*
* These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -3126,6 +3152,7 @@ enum nl80211_sta_bss_param {
* @NL80211_STA_INFO_CONNECTED_TO_GATE: set to true if STA has a path to a
* mesh gate (u8, 0 or 1)
* @NL80211_STA_INFO_AIRTIME_LINK_METRIC: airtime link metric for mesh station
+ * @NL80211_STA_INFO_RX_MCAST_BCAST: per station rx mcast/bcast count stats.
* @__NL80211_STA_INFO_AFTER_LAST: internal
* @NL80211_STA_INFO_MAX: highest possible station info attribute
*/
@@ -3170,6 +3197,7 @@ enum nl80211_sta_info {
NL80211_STA_INFO_FCS_ERROR_COUNT,
NL80211_STA_INFO_CONNECTED_TO_GATE,
NL80211_STA_INFO_AIRTIME_LINK_METRIC,
+ NL80211_STA_INFO_RX_MCAST_BCAST,
/* keep last */
__NL80211_STA_INFO_AFTER_LAST,
@@ -2772,6 +2772,20 @@ static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb,
}
#endif
+static inline void ieee80211_mc_bc_stats(char *dst,
+ struct ieee80211_rx_data *rx)
+{
+ if (is_multicast_ether_addr(dst) && rx->sta) {
+ if (is_broadcast_ether_addr(dst)) {
+ rx->sta->mc_bc_stat.bc_pkts++;
+ rx->sta->mc_bc_stat.bc_bytes += rx->skb->len;
+ } else {
+ rx->sta->mc_bc_stat.mc_pkts++;
+ rx->sta->mc_bc_stat.mc_bytes += rx->skb->len;
+ }
+ }
+}
+
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
{
@@ -2806,6 +2820,9 @@ static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb,
if (unlikely(err))
return RX_DROP_UNUSABLE;
+ /* Get the multicat broadcast stats */
+ ieee80211_mc_bc_stats(((struct ethhdr *)rx->skb->data)->h_dest, rx);
+
if (!ieee80211_frame_allowed(rx, fc))
return RX_DROP_MONITOR;
@@ -2341,6 +2341,18 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
sinfo->airtime_link_metric =
airtime_link_metric_get(local, sta);
}
+
+ sta_get_rx_multicast_broadcast_info(sta, &sinfo->mc_bc_stat);
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_MCAST_BCAST);
+}
+
+void sta_get_rx_multicast_broadcast_info(struct sta_info *sta,
+ struct mc_bc_stats *stats)
+{
+ stats->mc_pkts = sta->mc_bc_stat.mc_pkts;
+ stats->mc_bytes = sta->mc_bc_stat.mc_bytes;
+ stats->bc_pkts = sta->mc_bc_stat.bc_pkts;
+ stats->bc_bytes = sta->mc_bc_stat.bc_bytes;
}
u32 sta_get_expected_throughput(struct sta_info *sta)
@@ -479,6 +479,7 @@ struct ieee80211_sta_rx_stats {
* @fast_rx: RX fastpath information
* @tdls_chandef: a TDLS peer can have a wider chandef that is compatible to
* the BSS one.
+ * @mc_bc_stat: per STA rx mcast/bcast count stats.
* @tx_stats: TX statistics
* @rx_stats: RX statistics
* @pcpu_rx_stats: per-CPU RX statistics, assigned only if the driver needs
@@ -585,6 +586,8 @@ struct sta_info {
struct cfg80211_chan_def tdls_chandef;
+ struct mc_bc_stats mc_bc_stat;
+
/* keep last! */
struct ieee80211_sta sta;
};
@@ -749,6 +752,9 @@ void sta_set_rate_info_tx(struct sta_info *sta,
void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
bool tidstats);
+void sta_get_rx_multicast_broadcast_info(struct sta_info *sta,
+ struct mc_bc_stats *stats);
+
u32 sta_get_expected_throughput(struct sta_info *sta);
void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
@@ -4981,6 +4981,29 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
nla_nest_end(msg, tidsattr);
}
+ if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_MCAST_BCAST)) {
+ struct nlattr *packetsattr;
+
+ packetsattr = nla_nest_start(msg,
+ NL80211_STA_INFO_RX_MCAST_BCAST);
+ if (!packetsattr)
+ goto nla_put_failure;
+
+#define PUT_MC_BC_VAL_U64(attr, memb) do { \
+ if (nla_put_u64_64bit(msg, NL80211_RX_ ## attr, \
+ sinfo->mc_bc_stat.memb, NL80211_STA_INFO_PAD)) \
+ goto nla_put_failure; \
+ } while (0)
+
+ PUT_MC_BC_VAL_U64(MCAST_PACKETS, mc_pkts);
+ PUT_MC_BC_VAL_U64(MCAST_BYTES, mc_bytes);
+ PUT_MC_BC_VAL_U64(BCAST_PACKETS, bc_pkts);
+ PUT_MC_BC_VAL_U64(BCAST_BYTES, bc_bytes);
+
+#undef PUT_MC_BC_VAL_U64
+ nla_nest_end(msg, packetsattr);
+ }
+
nla_nest_end(msg, sinfoattr);
if (sinfo->assoc_req_ies_len &&
Add support to collect per STA mcast/bcast packet information attribute NL80211_STA_INFO_RX_MCAST_BCAST. Signed-off-by: Narayanraddi Masti <team.nmasti@gmail.com> --- include/net/cfg80211.h | 17 +++++++++++++++++ include/uapi/linux/nl80211.h | 28 ++++++++++++++++++++++++++++ net/mac80211/rx.c | 17 +++++++++++++++++ net/mac80211/sta_info.c | 12 ++++++++++++ net/mac80211/sta_info.h | 6 ++++++ net/wireless/nl80211.c | 23 +++++++++++++++++++++++ 6 files changed, 103 insertions(+)