Browse Source

qcacld-3.0: Send L2UF frame to update bridge forwarding table

Generate a Level 2 update frame and send it to the bridge in SAP
mode when a new station connects.

It will update the forwarding table of all the bridge devices
through source port learning.

Change-Id: Ia804968453c051e4c8322d3735506a912c0d963d
CRs-Fixed: 2997409
Subrat Dash 3 years ago
parent
commit
19619ce40b

+ 12 - 0
components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h

@@ -4501,4 +4501,16 @@ uint32_t ucfg_mlme_get_user_mcc_quota_percentage(struct wlan_objmgr_psoc *psoc)
 {
 	return  wlan_mlme_get_user_mcc_duty_cycle_percentage(psoc);
 }
+
+/**
+ * ucfg_mlme_get_wds_mode() - Get the configured WDS mode
+ * @psoc: pointer to psoc object
+ *
+ * Return: supported wds mode from enum wlan_wds_mode
+ */
+static inline uint32_t
+ucfg_mlme_get_wds_mode(struct wlan_objmgr_psoc *psoc)
+{
+	return wlan_mlme_get_wds_mode(psoc);
+}
 #endif /* _WLAN_MLME_UCFG_API_H_ */

+ 28 - 1
core/hdd/inc/wlan_hdd_softap_tx_rx.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -324,4 +324,31 @@ int hdd_softap_inspect_dhcp_packet(struct hdd_adapter *adapter,
  */
 void hdd_softap_check_wait_for_tx_eap_pkt(struct hdd_adapter *adapter,
 					  struct qdf_mac_addr *mac_addr);
+
+#ifdef FEATURE_WDS
+/**
+ * hdd_softap_ind_l2_update() - Send L2 update frame to bridge
+ * @adapter: pointer to adapter context
+ * @sta_mac: pointer to the MAC address of the station
+ *
+ * The layer-2 update frame is an 802.2 type LLC exchange identifier (XID)
+ * update response frame. This frame is sent using a MAC source address of
+ * the newly associated station. Upon the reception of this frame,
+ * all the layer-2 devices update their forwarding tables with the correct
+ * port to reach the new location of the station according to the ieee802.1d
+ * bridge table self learning procedure.
+ *
+ * Return: QDF_STATUS_E_FAILURE if any errors encountered,
+ *	   QDF_STATUS_SUCCESS otherwise
+ */
+QDF_STATUS hdd_softap_ind_l2_update(struct hdd_adapter *adapter,
+				    struct qdf_mac_addr *sta_mac);
+#else
+static inline
+QDF_STATUS hdd_softap_ind_l2_update(struct hdd_adapter *adapter,
+				    struct qdf_mac_addr *sta_mac)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
 #endif /* end #if !defined(WLAN_HDD_SOFTAP_TX_RX_H) */

+ 5 - 0
core/hdd/src/wlan_hdd_hostapd.c

@@ -2567,6 +2567,11 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event,
 						 (const u8 *)&event->
 						 staMac.bytes[0],
 						 sta_info, GFP_KERNEL);
+
+			if (adapter->device_mode == QDF_SAP_MODE &&
+			    ucfg_mlme_get_wds_mode(hdd_ctx->psoc))
+				hdd_softap_ind_l2_update(adapter,
+							 &event->staMac);
 			qdf_mem_free(sta_info);
 		}
 		/* Lets abort scan to ensure smooth authentication for client */

+ 63 - 0
core/hdd/src/wlan_hdd_softap_tx_rx.c

@@ -51,11 +51,28 @@
 #include <wlan_hdd_sar_limits.h>
 #include "wlan_hdd_tsf.h"
 #include "wlan_hdd_wds.h"
+#include <cdp_txrx_ctrl.h>
+#ifdef FEATURE_WDS
+#include <net/llc_pdu.h>
+#endif
 
 /* Preprocessor definitions and constants */
 #undef QCA_HDD_SAP_DUMP_SK_BUFF
 
 /* Type declarations */
+#ifdef FEATURE_WDS
+/**
+ * Layer-2 update frame format
+ * @eh: ethernet header
+ * @l2_update_pdu: llc pdu format
+ * @l2_update_xid_info: xid command information field
+ */
+struct l2_update_frame {
+	struct ethhdr eh;
+	struct llc_pdu_un l2_update_pdu;
+	struct llc_xid_info l2_update_xid_info;
+} qdf_packed;
+#endif
 
 /* Function definitions and documenation */
 #ifdef QCA_HDD_SAP_DUMP_SK_BUFF
@@ -1649,3 +1666,49 @@ QDF_STATUS hdd_softap_change_sta_state(struct hdd_adapter *adapter,
 
 	return status;
 }
+
+#ifdef FEATURE_WDS
+QDF_STATUS hdd_softap_ind_l2_update(struct hdd_adapter *adapter,
+				    struct qdf_mac_addr *sta_mac)
+{
+	qdf_nbuf_t nbuf;
+	struct l2_update_frame *msg;
+
+	nbuf = qdf_nbuf_alloc(NULL, sizeof(*msg), 0, 4, false);
+	if (!nbuf)
+		return QDF_STATUS_E_FAILURE;
+
+	msg = (struct l2_update_frame *)qdf_nbuf_data(nbuf);
+
+	/* 802.2 LLC XID update frame carried over 802.3 */
+	ether_addr_copy(msg->eh.h_source, sta_mac->bytes);
+	eth_broadcast_addr(msg->eh.h_dest);
+	/* packet length - dummy 802.3 packet */
+	msg->eh.h_proto = htons(sizeof(*msg) - sizeof(struct ethhdr));
+
+	/* null DSAP and a null SSAP is a way to solicit a response from any
+	 * station (i.e., any DA)
+	 */
+	msg->l2_update_pdu.dsap = LLC_NULL_SAP;
+	msg->l2_update_pdu.ssap = LLC_NULL_SAP;
+
+	/*
+	 * unsolicited XID response frame to announce presence.
+	 * lsb.11110101.
+	 */
+	msg->l2_update_pdu.ctrl_1 = LLC_PDU_TYPE_U | LLC_1_PDU_CMD_XID;
+
+	/* XID information field 129.1.0 to indicate connectionless service */
+	msg->l2_update_xid_info.fmt_id = LLC_XID_FMT_ID;
+	msg->l2_update_xid_info.type = LLC_XID_NULL_CLASS_1;
+	msg->l2_update_xid_info.rw = 0;
+
+	qdf_nbuf_set_pktlen(nbuf, sizeof(*msg));
+	nbuf->dev = adapter->dev;
+	nbuf->protocol = eth_type_trans(nbuf, adapter->dev);
+	qdf_net_buf_debug_release_skb(nbuf);
+	netif_rx_ni(nbuf);
+
+	return QDF_STATUS_SUCCESS;
+}
+#endif