diff mbox series

[OpenWrt-Devel,2/2] add channel information for scan results

Message ID 20180713085738.25259-2-yshvedov@wimarksystems.com
State Changes Requested
Delegated to: John Crispin
Headers show
Series [OpenWrt-Devel,1/2] add htmodelist for scan results | expand

Commit Message

Yury Shvedov July 13, 2018, 8:57 a.m. UTC
Besides channel number the secondary channel for HT40 and center idx0
and idx1 gives full understanding about real channel position and width
on the spectra. So grab it via nl80211 and make it available in both C
and LUA APIs, and show detailed channel information on CLI scan results.
---
 include/iwinfo.h | 21 ++++++++++++++++++++-
 iwinfo_cli.c     | 10 ++++++++++
 iwinfo_lua.c     | 11 +++++++++++
 iwinfo_nl80211.c | 32 ++++++++++++++++++++++++++++++--
 4 files changed, 71 insertions(+), 3 deletions(-)

Comments

Yury Shvedov July 13, 2018, 9:03 a.m. UTC | #1
Hi!

This patches are for iwinfo repo. I think I sent them to the wrong 
place. Please, say me so.

This patches add extra information to scan list. I've made them for my 
own usage. But they may be useful for someone.


On 07/13/2018 11:57 AM, Yury Shvedov wrote:
> Besides channel number the secondary channel for HT40 and center idx0
> and idx1 gives full understanding about real channel position and width
> on the spectra. So grab it via nl80211 and make it available in both C
> and LUA APIs, and show detailed channel information on CLI scan results.
> ---
>   include/iwinfo.h | 21 ++++++++++++++++++++-
>   iwinfo_cli.c     | 10 ++++++++++
>   iwinfo_lua.c     | 11 +++++++++++
>   iwinfo_nl80211.c | 32 ++++++++++++++++++++++++++++++--
>   4 files changed, 71 insertions(+), 3 deletions(-)
>
> diff --git a/include/iwinfo.h b/include/iwinfo.h
> index c3c25ff..b1b39a1 100644
> --- a/include/iwinfo.h
> +++ b/include/iwinfo.h
> @@ -145,6 +145,24 @@ struct iwinfo_crypto_entry {
>   	uint8_t auth_suites;
>   	uint8_t auth_algs;
>   };
> +struct iwinfo_channel_info_entry {
> +	/**
> +	 * sec_channel_offset - Secondary channel offset for HT40
> +	 *
> +	 * 0 = HT40 disabled,
> +	 * -1 = HT40 enabled, secondary channel below primary,
> +	 * 1 = HT40 enabled, secondary channel above primary
> +	 */
> +	int sec_channel_offset;
> +	/**
> +	 * Center channel for VHT80
> +	 */
> +	int center_idx0;
> +	/**
> +	 * Center channel for VHT160
> +	 */
> +	int center_idx1;
> +};
>   
>   struct iwinfo_scanlist_entry {
>   	uint8_t mac[6];
> @@ -154,8 +172,9 @@ struct iwinfo_scanlist_entry {
>   	uint8_t signal;
>   	uint8_t quality;
>   	uint8_t quality_max;
> -    int htmodelist;
> +	int htmodelist;
>   	struct iwinfo_crypto_entry crypto;
> +	struct iwinfo_channel_info_entry channel_info;
>   };
>   
>   struct iwinfo_country_entry {
> diff --git a/iwinfo_cli.c b/iwinfo_cli.c
> index 2d58020..0d899e0 100644
> --- a/iwinfo_cli.c
> +++ b/iwinfo_cli.c
> @@ -612,6 +612,16 @@ static void print_scanlist(const struct iwinfo_ops *iw, const char *ifname)
>   				if (e->htmodelist & (1 << h))
>   					printf("%s ", IWINFO_HTMODE_NAMES[h]);
>   			printf ("\n");
> +			if (e->channel_info.sec_channel_offset)
> +				printf ("              HT secondary channel is %s\n",
> +						e->channel_info.sec_channel_offset < 0 ? "below" :
> +							"above");
> +			if (e->channel_info.center_idx0)
> +				printf ("              VHT Center IDX0: %d\n",
> +						e->channel_info.center_idx0);
> +			if (e->channel_info.center_idx1)
> +				printf ("              VHT Center IDX1: %d\n",
> +						e->channel_info.center_idx1);
>   		}
>   		printf ("\n");
>   	}
> diff --git a/iwinfo_lua.c b/iwinfo_lua.c
> index 01581a3..bd7f0d3 100644
> --- a/iwinfo_lua.c
> +++ b/iwinfo_lua.c
> @@ -446,6 +446,17 @@ static int iwinfo_L_scanlist(lua_State *L, int (*func)(const char *, char *, int
>   				lua_pushnil(L);
>   			lua_setfield(L, -2, "htmodelist");
>   
> +			lua_pushinteger(L, e->channel_info.sec_channel_offset);
> +			lua_setfield(L, -2, "sec_channel_offset");
> +			if (e->channel_info.center_idx0) {
> +				lua_pushinteger(L, e->channel_info.center_idx0);
> +				lua_setfield(L, -2, "center_idx0");
> +			}
> +			if (e->channel_info.center_idx1) {
> +				lua_pushinteger(L, e->channel_info.center_idx1);
> +				lua_setfield(L, -2, "center_idx1");
> +			}
> +
>   			lua_rawseti(L, -2, x);
>   		}
>   	}
> diff --git a/iwinfo_nl80211.c b/iwinfo_nl80211.c
> index 542ac7d..fb137b2 100644
> --- a/iwinfo_nl80211.c
> +++ b/iwinfo_nl80211.c
> @@ -1996,6 +1996,27 @@ static void nl80211_parse_ht_capa(struct iwinfo_scanlist_entry *e,
>   			e->htmodelist |= IWINFO_HTMODE_VHT40;
>   	}
>   }
> +static void nl80211_parse_ht_oper(struct iwinfo_scanlist_entry *e,
> +								  unsigned char *ie,
> +								  int len)
> +{
> +	uint8_t oper_info;
> +
> +	if (len < 6)
> +		return;
> +	oper_info = ie[1];
> +	switch (oper_info & 3) {
> +	case 0:
> +		e->channel_info.sec_channel_offset = 0;
> +		break;
> +	case 1:
> +		e->channel_info.sec_channel_offset = 1;
> +		break;
> +	case 3:
> +		e->channel_info.sec_channel_offset = -1;
> +		break;
> +	}
> +}
>   static void nl80211_parse_vht_capa(struct iwinfo_scanlist_entry *e,
>   								   unsigned char *ie,
>   								   int len)
> @@ -2024,7 +2045,7 @@ static void nl80211_parse_vht_oper(struct iwinfo_scanlist_entry *e,
>   								   int len)
>   {
>   	int chanwidth;
> -	if (len < 1)
> +	if (len < 3)
>   		return;
>   	chanwidth = ie[0];
>   
> @@ -2036,6 +2057,7 @@ static void nl80211_parse_vht_oper(struct iwinfo_scanlist_entry *e,
>   	/*case 0: 20 or 40 MHz */
>   	case 1:
>   		e->htmodelist |= IWINFO_HTMODE_VHT80;
> +		e->channel_info.center_idx0 = ie[1];
>   		break;
>   	case 2:
>   		e->htmodelist |= IWINFO_HTMODE_VHT160;
> @@ -2044,10 +2066,12 @@ static void nl80211_parse_vht_oper(struct iwinfo_scanlist_entry *e,
>   		e->htmodelist |= IWINFO_HTMODE_VHT80_80;
>   		break;
>   	}
> +	e->channel_info.center_idx0 = ie[1];
> +	e->channel_info.center_idx1 = ie[2];
>   }
>   
>   static void nl80211_get_scanlist_ie(struct nlattr **bss,
> -                                    struct iwinfo_scanlist_entry *e)
> +									struct iwinfo_scanlist_entry *e)
>   {
>   	int ielen = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
>   	unsigned char *ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
> @@ -2073,6 +2097,10 @@ static void nl80211_get_scanlist_ie(struct nlattr **bss,
>   			                 IWINFO_CIPHER_CCMP, IWINFO_KMGMT_8021x);
>   			break;
>   
> +		case 61: /* HT Operation */
> +			nl80211_parse_ht_oper(e, ie + 2, ie[1]);
> +			break;
> +
>   		case 191: /* VHT Capabilities */
>   			nl80211_parse_vht_capa(e, ie + 2, ie[1]);
>   			break;
Jo-Philipp Wich July 15, 2018, 6:59 p.m. UTC | #2
Hi,

comments inline.

~ Jo

> diff --git a/include/iwinfo.h b/include/iwinfo.h
> index c3c25ff..b1b39a1 100644
> --- a/include/iwinfo.h
> +++ b/include/iwinfo.h
> @@ -145,6 +145,24 @@ struct iwinfo_crypto_entry {
>  	uint8_t auth_suites;
>  	uint8_t auth_algs;
>  };
> +struct iwinfo_channel_info_entry {
> +	/**
> +	 * sec_channel_offset - Secondary channel offset for HT40
> +	 *
> +	 * 0 = HT40 disabled,
> +	 * -1 = HT40 enabled, secondary channel below primary,
> +	 * 1 = HT40 enabled, secondary channel above primary
> +	 */
> +	int sec_channel_offset;
> +	/**
> +	 * Center channel for VHT80
> +	 */
> +	int center_idx0;
> +	/**
> +	 * Center channel for VHT160
> +	 */
> +	int center_idx1;
> +};

Do we really need three ints? I think the sec_channel_offset could be an
u8 and the channel indexes u8 or u16 values.

>  
>  struct iwinfo_scanlist_entry {
>  	uint8_t mac[6];
> @@ -154,8 +172,9 @@ struct iwinfo_scanlist_entry {
>  	uint8_t signal;
>  	uint8_t quality;
>  	uint8_t quality_max;
> -    int htmodelist;
> +	int htmodelist;

Please use an u8 here.

>  	struct iwinfo_crypto_entry crypto;
> +	struct iwinfo_channel_info_entry channel_info;
>  };
>  
>  struct iwinfo_country_entry {
> diff --git a/iwinfo_cli.c b/iwinfo_cli.c
> index 2d58020..0d899e0 100644
> --- a/iwinfo_cli.c
> +++ b/iwinfo_cli.c
> @@ -612,6 +612,16 @@ static void print_scanlist(const struct iwinfo_ops *iw, const char *ifname)
>  				if (e->htmodelist & (1 << h))
>  					printf("%s ", IWINFO_HTMODE_NAMES[h]);
>  			printf ("\n");
> +			if (e->channel_info.sec_channel_offset)
> +				printf ("              HT secondary channel is %s\n",
> +						e->channel_info.sec_channel_offset < 0 ? "below" :
> +							"above");
> +			if (e->channel_info.center_idx0)
> +				printf ("              VHT Center IDX0: %d\n",
> +						e->channel_info.center_idx0);
> +			if (e->channel_info.center_idx1)
> +				printf ("              VHT Center IDX1: %d\n",
> +						e->channel_info.center_idx1);
>  		}
>  		printf ("\n");
>  	}
> diff --git a/iwinfo_lua.c b/iwinfo_lua.c
> index 01581a3..bd7f0d3 100644
> --- a/iwinfo_lua.c
> +++ b/iwinfo_lua.c
> @@ -446,6 +446,17 @@ static int iwinfo_L_scanlist(lua_State *L, int (*func)(const char *, char *, int
>  				lua_pushnil(L);
>  			lua_setfield(L, -2, "htmodelist");
>  
> +			lua_pushinteger(L, e->channel_info.sec_channel_offset);
> +			lua_setfield(L, -2, "sec_channel_offset");
> +			if (e->channel_info.center_idx0) {
> +				lua_pushinteger(L, e->channel_info.center_idx0);
> +				lua_setfield(L, -2, "center_idx0");
> +			}
> +			if (e->channel_info.center_idx1) {
> +				lua_pushinteger(L, e->channel_info.center_idx1);
> +				lua_setfield(L, -2, "center_idx1");
> +			}
> +
>  			lua_rawseti(L, -2, x);
>  		}
>  	}
> diff --git a/iwinfo_nl80211.c b/iwinfo_nl80211.c
> index 542ac7d..fb137b2 100644
> --- a/iwinfo_nl80211.c
> +++ b/iwinfo_nl80211.c
> @@ -1996,6 +1996,27 @@ static void nl80211_parse_ht_capa(struct iwinfo_scanlist_entry *e,
>  			e->htmodelist |= IWINFO_HTMODE_VHT40;
>  	}
>  }
> +static void nl80211_parse_ht_oper(struct iwinfo_scanlist_entry *e,
> +								  unsigned char *ie,
> +								  int len)
> +{
> +	uint8_t oper_info;
> +
> +	if (len < 6)
> +		return;
> +	oper_info = ie[1];
> +	switch (oper_info & 3) {
> +	case 0:
> +		e->channel_info.sec_channel_offset = 0;
> +		break;
> +	case 1:
> +		e->channel_info.sec_channel_offset = 1;
> +		break;
> +	case 3:
> +		e->channel_info.sec_channel_offset = -1;
> +		break;
> +	}
> +}
>  static void nl80211_parse_vht_capa(struct iwinfo_scanlist_entry *e,
>  								   unsigned char *ie,
>  								   int len)
> @@ -2024,7 +2045,7 @@ static void nl80211_parse_vht_oper(struct iwinfo_scanlist_entry *e,
>  								   int len)
>  {
>  	int chanwidth;
> -	if (len < 1)
> +	if (len < 3)
>  		return;
>  	chanwidth = ie[0];
>  
> @@ -2036,6 +2057,7 @@ static void nl80211_parse_vht_oper(struct iwinfo_scanlist_entry *e,
>  	/*case 0: 20 or 40 MHz */
>  	case 1:
>  		e->htmodelist |= IWINFO_HTMODE_VHT80;
> +		e->channel_info.center_idx0 = ie[1];
>  		break;
>  	case 2:
>  		e->htmodelist |= IWINFO_HTMODE_VHT160;
> @@ -2044,10 +2066,12 @@ static void nl80211_parse_vht_oper(struct iwinfo_scanlist_entry *e,
>  		e->htmodelist |= IWINFO_HTMODE_VHT80_80;
>  		break;
>  	}
> +	e->channel_info.center_idx0 = ie[1];
> +	e->channel_info.center_idx1 = ie[2];
>  }
>  
>  static void nl80211_get_scanlist_ie(struct nlattr **bss,
> -                                    struct iwinfo_scanlist_entry *e)
> +									struct iwinfo_scanlist_entry *e)
>  {
>  	int ielen = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
>  	unsigned char *ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
> @@ -2073,6 +2097,10 @@ static void nl80211_get_scanlist_ie(struct nlattr **bss,
>  			                 IWINFO_CIPHER_CCMP, IWINFO_KMGMT_8021x);
>  			break;
>  
> +		case 61: /* HT Operation */
> +			nl80211_parse_ht_oper(e, ie + 2, ie[1]);
> +			break;
> +
>  		case 191: /* VHT Capabilities */
>  			nl80211_parse_vht_capa(e, ie + 2, ie[1]);
>  			break;
>
diff mbox series

Patch

diff --git a/include/iwinfo.h b/include/iwinfo.h
index c3c25ff..b1b39a1 100644
--- a/include/iwinfo.h
+++ b/include/iwinfo.h
@@ -145,6 +145,24 @@  struct iwinfo_crypto_entry {
 	uint8_t auth_suites;
 	uint8_t auth_algs;
 };
+struct iwinfo_channel_info_entry {
+	/**
+	 * sec_channel_offset - Secondary channel offset for HT40
+	 *
+	 * 0 = HT40 disabled,
+	 * -1 = HT40 enabled, secondary channel below primary,
+	 * 1 = HT40 enabled, secondary channel above primary
+	 */
+	int sec_channel_offset;
+	/**
+	 * Center channel for VHT80
+	 */
+	int center_idx0;
+	/**
+	 * Center channel for VHT160
+	 */
+	int center_idx1;
+};
 
 struct iwinfo_scanlist_entry {
 	uint8_t mac[6];
@@ -154,8 +172,9 @@  struct iwinfo_scanlist_entry {
 	uint8_t signal;
 	uint8_t quality;
 	uint8_t quality_max;
-    int htmodelist;
+	int htmodelist;
 	struct iwinfo_crypto_entry crypto;
+	struct iwinfo_channel_info_entry channel_info;
 };
 
 struct iwinfo_country_entry {
diff --git a/iwinfo_cli.c b/iwinfo_cli.c
index 2d58020..0d899e0 100644
--- a/iwinfo_cli.c
+++ b/iwinfo_cli.c
@@ -612,6 +612,16 @@  static void print_scanlist(const struct iwinfo_ops *iw, const char *ifname)
 				if (e->htmodelist & (1 << h))
 					printf("%s ", IWINFO_HTMODE_NAMES[h]);
 			printf ("\n");
+			if (e->channel_info.sec_channel_offset)
+				printf ("              HT secondary channel is %s\n",
+						e->channel_info.sec_channel_offset < 0 ? "below" :
+							"above");
+			if (e->channel_info.center_idx0)
+				printf ("              VHT Center IDX0: %d\n",
+						e->channel_info.center_idx0);
+			if (e->channel_info.center_idx1)
+				printf ("              VHT Center IDX1: %d\n",
+						e->channel_info.center_idx1);
 		}
 		printf ("\n");
 	}
diff --git a/iwinfo_lua.c b/iwinfo_lua.c
index 01581a3..bd7f0d3 100644
--- a/iwinfo_lua.c
+++ b/iwinfo_lua.c
@@ -446,6 +446,17 @@  static int iwinfo_L_scanlist(lua_State *L, int (*func)(const char *, char *, int
 				lua_pushnil(L);
 			lua_setfield(L, -2, "htmodelist");
 
+			lua_pushinteger(L, e->channel_info.sec_channel_offset);
+			lua_setfield(L, -2, "sec_channel_offset");
+			if (e->channel_info.center_idx0) {
+				lua_pushinteger(L, e->channel_info.center_idx0);
+				lua_setfield(L, -2, "center_idx0");
+			}
+			if (e->channel_info.center_idx1) {
+				lua_pushinteger(L, e->channel_info.center_idx1);
+				lua_setfield(L, -2, "center_idx1");
+			}
+
 			lua_rawseti(L, -2, x);
 		}
 	}
diff --git a/iwinfo_nl80211.c b/iwinfo_nl80211.c
index 542ac7d..fb137b2 100644
--- a/iwinfo_nl80211.c
+++ b/iwinfo_nl80211.c
@@ -1996,6 +1996,27 @@  static void nl80211_parse_ht_capa(struct iwinfo_scanlist_entry *e,
 			e->htmodelist |= IWINFO_HTMODE_VHT40;
 	}
 }
+static void nl80211_parse_ht_oper(struct iwinfo_scanlist_entry *e,
+								  unsigned char *ie,
+								  int len)
+{
+	uint8_t oper_info;
+
+	if (len < 6)
+		return;
+	oper_info = ie[1];
+	switch (oper_info & 3) {
+	case 0:
+		e->channel_info.sec_channel_offset = 0;
+		break;
+	case 1:
+		e->channel_info.sec_channel_offset = 1;
+		break;
+	case 3:
+		e->channel_info.sec_channel_offset = -1;
+		break;
+	}
+}
 static void nl80211_parse_vht_capa(struct iwinfo_scanlist_entry *e,
 								   unsigned char *ie,
 								   int len)
@@ -2024,7 +2045,7 @@  static void nl80211_parse_vht_oper(struct iwinfo_scanlist_entry *e,
 								   int len)
 {
 	int chanwidth;
-	if (len < 1)
+	if (len < 3)
 		return;
 	chanwidth = ie[0];
 
@@ -2036,6 +2057,7 @@  static void nl80211_parse_vht_oper(struct iwinfo_scanlist_entry *e,
 	/*case 0: 20 or 40 MHz */
 	case 1:
 		e->htmodelist |= IWINFO_HTMODE_VHT80;
+		e->channel_info.center_idx0 = ie[1];
 		break;
 	case 2:
 		e->htmodelist |= IWINFO_HTMODE_VHT160;
@@ -2044,10 +2066,12 @@  static void nl80211_parse_vht_oper(struct iwinfo_scanlist_entry *e,
 		e->htmodelist |= IWINFO_HTMODE_VHT80_80;
 		break;
 	}
+	e->channel_info.center_idx0 = ie[1];
+	e->channel_info.center_idx1 = ie[2];
 }
 
 static void nl80211_get_scanlist_ie(struct nlattr **bss,
-                                    struct iwinfo_scanlist_entry *e)
+									struct iwinfo_scanlist_entry *e)
 {
 	int ielen = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
 	unsigned char *ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
@@ -2073,6 +2097,10 @@  static void nl80211_get_scanlist_ie(struct nlattr **bss,
 			                 IWINFO_CIPHER_CCMP, IWINFO_KMGMT_8021x);
 			break;
 
+		case 61: /* HT Operation */
+			nl80211_parse_ht_oper(e, ie + 2, ie[1]);
+			break;
+
 		case 191: /* VHT Capabilities */
 			nl80211_parse_vht_capa(e, ie + 2, ie[1]);
 			break;