From 19619ce40b1d1991c7b6ec92d71ae70148a8fe4c Mon Sep 17 00:00:00 2001 From: Subrat Dash Date: Fri, 25 Jun 2021 22:38:17 +0530 Subject: [PATCH] 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 --- .../mlme/dispatcher/inc/wlan_mlme_ucfg_api.h | 12 ++++ core/hdd/inc/wlan_hdd_softap_tx_rx.h | 29 ++++++++- core/hdd/src/wlan_hdd_hostapd.c | 5 ++ core/hdd/src/wlan_hdd_softap_tx_rx.c | 63 +++++++++++++++++++ 4 files changed, 108 insertions(+), 1 deletion(-) diff --git a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h index ad99a9c61e..a2a308ae7a 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h +++ b/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_ */ diff --git a/core/hdd/inc/wlan_hdd_softap_tx_rx.h b/core/hdd/inc/wlan_hdd_softap_tx_rx.h index 81bd851576..64ccc2d53c 100644 --- a/core/hdd/inc/wlan_hdd_softap_tx_rx.h +++ b/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) */ diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index e21c232854..d62ddb7a9c 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/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 */ diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c index dde09a9f1d..99e1931bc6 100644 --- a/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -51,11 +51,28 @@ #include #include "wlan_hdd_tsf.h" #include "wlan_hdd_wds.h" +#include +#ifdef FEATURE_WDS +#include +#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