diff --git a/package/iw/patches/100-rx_rate.patch b/package/iw/patches/100-rx_rate.patch
new file mode 100644
index 0000000000000000000000000000000000000000..e3df6ca0923bcc538dc8f92caf4dae35988f8de1
--- /dev/null
+++ b/package/iw/patches/100-rx_rate.patch
@@ -0,0 +1,97 @@
+--- a/station.c
++++ b/station.c
+@@ -29,13 +29,43 @@ enum plink_actions {
+ 	PLINK_ACTION_BLOCK,
+ };
+ 
++static void print_sta_bitrate(struct nlattr *nla, const char *name)
++{
++	struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
++
++	static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
++		[NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
++		[NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
++		[NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
++		[NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
++	};
++
++	if (!nla)
++		return;
++
++	if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, nla, rate_policy)) {
++		fprintf(stderr, "failed to parse nested rate attributes!\n");
++	} else {
++		printf("\n\t%s:\t", name);
++		if (rinfo[NL80211_RATE_INFO_BITRATE]) {
++			int rate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
++			printf("%d.%d MBit/s", rate / 10, rate % 10);
++		}
++
++		if (rinfo[NL80211_RATE_INFO_MCS])
++			printf(" MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]));
++		if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
++			printf(" 40Mhz");
++		if (rinfo[NL80211_RATE_INFO_SHORT_GI])
++			printf(" short GI");
++	}
++}
+ 
+ static int print_sta_handler(struct nl_msg *msg, void *arg)
+ {
+ 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ 	struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
+-	struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
+ 	char mac_addr[20], state_name[10], dev[20];
+ 	static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
+ 		[NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
+@@ -45,6 +75,7 @@ static int print_sta_handler(struct nl_m
+ 		[NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
+ 		[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
+ 		[NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
++		[NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
+ 		[NL80211_STA_INFO_LLID] = { .type = NLA_U16 },
+ 		[NL80211_STA_INFO_PLID] = { .type = NLA_U16 },
+ 		[NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 },
+@@ -52,13 +83,6 @@ static int print_sta_handler(struct nl_m
+ 		[NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
+ 	};
+ 
+-	static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
+-		[NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
+-		[NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
+-		[NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
+-		[NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
+-	};
+-
+ 	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ 		  genlmsg_attrlen(gnlh, 0), NULL);
+ 
+@@ -111,25 +135,8 @@ static int print_sta_handler(struct nl_m
+ 		printf("\n\tsignal avg:\t%d dBm",
+ 			(int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]));
+ 
+-	if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
+-		if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
+-				     sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
+-			fprintf(stderr, "failed to parse nested rate attributes!\n");
+-		} else {
+-			printf("\n\ttx bitrate:\t");
+-			if (rinfo[NL80211_RATE_INFO_BITRATE]) {
+-				int rate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
+-				printf("%d.%d MBit/s", rate / 10, rate % 10);
+-			}
+-
+-			if (rinfo[NL80211_RATE_INFO_MCS])
+-				printf(" MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]));
+-			if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
+-				printf(" 40Mhz");
+-			if (rinfo[NL80211_RATE_INFO_SHORT_GI])
+-				printf(" short GI");
+-		}
+-	}
++	print_sta_bitrate(sinfo[NL80211_STA_INFO_TX_BITRATE], "tx bitrate");
++	print_sta_bitrate(sinfo[NL80211_STA_INFO_RX_BITRATE], "rx bitrate");
+ 
+ 	if (sinfo[NL80211_STA_INFO_LLID])
+ 		printf("\n\tmesh llid:\t%d",