diff mbox series

iw: scan: Add partial Multi-Link element printing

Message ID 20250528041330.83464-1-alex.gavin@candelatech.com
State New
Headers show
Series iw: scan: Add partial Multi-Link element printing | expand

Commit Message

Alex Gavin May 28, 2025, 4:13 a.m. UTC
Only print some basic items to start.

Minimum and maximum length values are computed from the
specification. Maximum only includes Common Info and
does not consider Link Info.

Signed-off-by: Alex Gavin <alex.gavin@candelatech.com>
---
 ieee80211.h |  1 +
 iw.h        |  1 +
 scan.c      |  8 ++++++++
 util.c      | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 69 insertions(+)
diff mbox series

Patch

diff --git a/ieee80211.h b/ieee80211.h
index c31041e..2e6b68b 100644
--- a/ieee80211.h
+++ b/ieee80211.h
@@ -100,6 +100,7 @@  enum elem_id_ext {
 	EID_EXT_HE_CAPABILITY		= 35,
 	EID_EXT_HE_OPERATION		= 36,
 	EID_EXT_EHT_OPERATION		= 106,
+	EID_EXT_MULTI_LINK     		= 107,
 	EID_EXT_EHT_CAPABILITY		= 108,
 };
 
diff --git a/iw.h b/iw.h
index a423431..145b058 100644
--- a/iw.h
+++ b/iw.h
@@ -247,6 +247,7 @@  void print_he_operation(const uint8_t *ie, int len);
 void print_he_info(struct nlattr *nl_iftype);
 void print_eht_capability(const uint8_t *ie, int len, const uint8_t *he_cap,
 			  bool from_ap);
+void print_multi_link(const uint8_t *ie, int len);
 void print_eht_operation(const uint8_t *ie, int len);
 void print_eht_info(struct nlattr *nl_iftype, int band);
 void print_s1g_capability(const uint8_t *caps);
diff --git a/scan.c b/scan.c
index 263d2e3..c1255f7 100644
--- a/scan.c
+++ b/scan.c
@@ -2426,6 +2426,13 @@  static void print_eht_capa(const uint8_t type, uint8_t len,
 	print_eht_capability(data, len, ctx->he_cap, ctx->from_ap);
 }
 
+static void _print_multi_link(const uint8_t type, uint8_t len, const uint8_t *data,
+			   const struct ie_context *ctx)
+{
+	printf("\n");
+	print_multi_link(data, len);
+}
+
 static void print_eht_oper(const uint8_t type, uint8_t len, const uint8_t *data,
 			   const struct ie_context *ctx)
 {
@@ -2437,6 +2444,7 @@  static const struct ie_print ext_printers[] = {
 	[EID_EXT_HE_CAPABILITY] = { "HE capabilities", print_he_capa, 21, 54, BIT(PRINT_SCAN), },
 	[EID_EXT_HE_OPERATION] = { "HE Operation", print_he_oper, 6, 15, BIT(PRINT_SCAN), },
 	[EID_EXT_EHT_CAPABILITY] = { "EHT capabilities", print_eht_capa, 13, 30, BIT(PRINT_SCAN), },
+	[EID_EXT_MULTI_LINK] = { "Multi-Link", _print_multi_link, 5, 23, BIT(PRINT_SCAN), },
 	[EID_EXT_EHT_OPERATION] = { "EHT Operation", print_eht_oper, 5, 10, BIT(PRINT_SCAN), },
 };
 
diff --git a/util.c b/util.c
index 3345d95..34acf48 100644
--- a/util.c
+++ b/util.c
@@ -1934,6 +1934,65 @@  void print_he_operation(const uint8_t *ie, int len)
 	}
 }
 
+void print_multi_link(const uint8_t *ie, int len)
+{
+	uint16_t eml_capa = 0;
+	uint16_t mld_capa = 0;
+
+	uint16_t presence_bitmap = (ie[1] << 8) | ie[0];
+	bool link_id_info_present      = presence_bitmap & 0x0010;
+	bool bss_param_change_present  = presence_bitmap & 0x0020;
+	bool medium_sync_delay_present = presence_bitmap & 0x0040;
+	bool eml_capabilities_present  = presence_bitmap & 0x0080;
+	bool mld_capabilities_present  = presence_bitmap & 0x0100;
+
+	uint8_t common_info_len = ie[2] - 1;  // Account for length value includes byte storing length
+	uint8_t offset = 3;
+
+	char mld_mac[20];
+	mac_addr_n2a(mld_mac, (void*)ie+offset);
+	printf("\t\tMLD MAC: %s\n", mld_mac);
+	offset += 6;
+
+	// Link ID Info
+	if (offset < common_info_len && link_id_info_present) {
+		printf("\t\tLink ID: %d\n", ie[offset] & 0xF);
+		offset += 1;
+	}
+
+	// BSS Parameters Change Count
+	if (offset < common_info_len && bss_param_change_present)
+		offset += 1;
+
+	// Medium Synchronization Delay Information
+	if (offset < common_info_len && medium_sync_delay_present)
+		offset += 2;
+
+	// EML Capabilities
+	if (offset < common_info_len && eml_capabilities_present) {
+		eml_capa = (ie[offset+1] << 8) | ie[offset];
+		printf("\t\t\tEML Capabilities: 0x%04x\n", eml_capa);
+
+		if (eml_capa & 0x0001)
+			printf("\t\t\t\tEMLSR Support\n");
+		if (eml_capa & 0x0080)
+			printf("\t\t\t\tEMLMR Support\n");
+
+		offset += 2;
+	}
+
+	// MLD Capabilities and Operations
+	if (offset < common_info_len && mld_capabilities_present) {
+		mld_capa = (ie[offset+1] << 8) | ie[offset];
+		printf("\t\t\tMLD Capabilities and Operations: 0x%04x\n", mld_capa);
+
+		// This is zero-indexed (i.e. 0 means 1 simulataneous link, 1 means 2, etc)
+		printf("\t\t\t\tMaximum Number of Simulatenous Links: %d\n", mld_capa & 0xF);
+
+		offset += 2;
+	}
+}
+
 void print_eht_operation(const uint8_t *ie, int len)
 {
 	uint8_t oper_parameters = ie[0];