diff --git a/dp/inc/cdp_txrx_ctrl.h b/dp/inc/cdp_txrx_ctrl.h index d2d86ddee6..8a7023a031 100644 --- a/dp/inc/cdp_txrx_ctrl.h +++ b/dp/inc/cdp_txrx_ctrl.h @@ -262,6 +262,24 @@ static inline void cdp_set_mesh_mode return; } +/** + * @brief set mesh rx filter + * @details based on the bits enabled in the filter packets has to be dropped. + * + * @param soc - pointer to the soc + * @param vdev - the data virtual device object + * @param val - value to be set + * @return - void + */ +static inline +void cdp_set_mesh_rx_filter(ol_txrx_soc_handle soc, + struct cdp_vdev *vdev, uint32_t val) +{ + if (soc->ops->ctrl_ops->txrx_set_mesh_rx_filter) + return soc->ops->ctrl_ops->txrx_set_mesh_rx_filter(vdev, val); + return; +} + static inline void cdp_tx_flush_buffers (ol_txrx_soc_handle soc, struct cdp_vdev *vdev) { diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 9ddf8ffd28..432ce043e1 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -329,6 +329,16 @@ struct cdp_ctrl_ops { /* Should be ol_txrx_ctrl_api.h */ void (*txrx_set_mesh_mode)(struct cdp_vdev *vdev, u_int32_t val); + /** + * @brief setting mesh rx filter + * @details + * based on the bits enabled in the filter packets has to be dropped. + * + * @param vdev - the data virtual device object + * @param val - value to set + */ + void (*txrx_set_mesh_rx_filter)(struct cdp_vdev *vdev, uint32_t val); + void (*tx_flush_buffers)(struct cdp_vdev *vdev); int (*txrx_is_target_ar900b)(struct cdp_vdev *vdev); diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index cc689928b2..88620eaedb 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -1831,7 +1831,7 @@ static struct cdp_cfg *dp_get_ctrl_pdev_from_vdev_wifi3(struct cdp_vdev *pvdev) } #ifdef MESH_MODE_SUPPORT -void dp_peer_set_mesh_mode(struct cdp_vdev *vdev_hdl, u_int32_t val) +void dp_peer_set_mesh_mode(struct cdp_vdev *vdev_hdl, uint32_t val) { struct dp_vdev *vdev = (struct dp_vdev *)vdev_hdl; @@ -1839,6 +1839,22 @@ void dp_peer_set_mesh_mode(struct cdp_vdev *vdev_hdl, u_int32_t val) FL("%s: val %d"), __func__, val); vdev->mesh_vdev = val; } + +/* + * dp_peer_set_mesh_rx_filter() - to set the mesh rx filter + * @vdev_hdl: virtual device object + * @val: value to be set + * + * Return: void + */ +void dp_peer_set_mesh_rx_filter(struct cdp_vdev *vdev_hdl, uint32_t val) +{ + struct dp_vdev *vdev = (struct dp_vdev *)vdev_hdl; + + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + FL("val %d"), val); + vdev->mesh_rx_filter = val; +} #endif static struct cdp_cmn_ops dp_ops_cmn = { @@ -1868,6 +1884,7 @@ static struct cdp_ctrl_ops dp_ops_ctrl = { .txrx_set_tx_encap_type = dp_set_vdev_tx_encap_type, #ifdef MESH_MODE_SUPPORT .txrx_set_mesh_mode = dp_peer_set_mesh_mode, + .txrx_set_mesh_rx_filter = dp_peer_set_mesh_rx_filter, #endif /* TODO: Add other functions */ }; diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 224a23fe56..9fa0e814ce 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -291,12 +291,77 @@ void dp_rx_fill_mesh_stats(struct dp_vdev *vdev, qdf_nbuf_t nbuf) rx_info->rs_keyix); } + +/** + * dp_rx_fill_mesh_stats() - Filters mesh unwanted packets + * + * @vdev: DP Virtual device handle + * @nbuf: Buffer pointer + * + * This checks if the received packet is matching any filter out + * catogery and and drop the packet if it matches. + * + * Return: status(0 indicates drop, 1 indicate to no drop) + */ + +static inline +QDF_STATUS dp_rx_filter_mesh_packets(struct dp_vdev *vdev, qdf_nbuf_t nbuf) +{ + uint8_t *rx_tlv_hdr = qdf_nbuf_data(nbuf); + union dp_align_mac_addr mac_addr; + + if (qdf_unlikely(vdev->mesh_rx_filter)) { + if (vdev->mesh_rx_filter & MESH_FILTER_OUT_FROMDS) + if (hal_rx_mpdu_get_fr_ds(rx_tlv_hdr)) + return QDF_STATUS_SUCCESS; + + if (vdev->mesh_rx_filter & MESH_FILTER_OUT_TODS) + if (hal_rx_mpdu_get_to_ds(rx_tlv_hdr)) + return QDF_STATUS_SUCCESS; + + if (vdev->mesh_rx_filter & MESH_FILTER_OUT_NODS) + if (!hal_rx_mpdu_get_fr_ds(rx_tlv_hdr) + && !hal_rx_mpdu_get_to_ds(rx_tlv_hdr)) + return QDF_STATUS_SUCCESS; + + if (vdev->mesh_rx_filter & MESH_FILTER_OUT_RA) { + if (hal_rx_mpdu_get_addr1(rx_tlv_hdr, + &mac_addr.raw[0])) + return QDF_STATUS_E_FAILURE; + + if (!qdf_mem_cmp(&mac_addr.raw[0], + &vdev->mac_addr.raw[0], + DP_MAC_ADDR_LEN)) + return QDF_STATUS_SUCCESS; + } + + if (vdev->mesh_rx_filter & MESH_FILTER_OUT_TA) { + if (hal_rx_mpdu_get_addr2(rx_tlv_hdr, + &mac_addr.raw[0])) + return QDF_STATUS_E_FAILURE; + + if (!qdf_mem_cmp(&mac_addr.raw[0], + &vdev->mac_addr.raw[0], + DP_MAC_ADDR_LEN)) + return QDF_STATUS_SUCCESS; + } + } + + return QDF_STATUS_E_FAILURE; +} + #else static void dp_rx_fill_mesh_stats(struct dp_vdev *vdev, qdf_nbuf_t nbuf) { } +static inline +QDF_STATUS dp_rx_filter_mesh_packets(struct dp_vdev *vdev, qdf_nbuf_t nbuf) +{ + return QDF_STATUS_E_FAILURE; +} + #endif @@ -541,8 +606,18 @@ done: /* Set length in nbuf */ qdf_nbuf_set_pktlen(nbuf, pkt_len); - if (qdf_unlikely(vdev->mesh_vdev)) + if (qdf_unlikely(vdev->mesh_vdev)) { + if (dp_rx_filter_mesh_packets(vdev, nbuf) + == QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_INFO_MED, + FL("mesh pkt filtered")); + + qdf_nbuf_free(nbuf); + continue; + } dp_rx_fill_mesh_stats(vdev, nbuf); + } /* * Advance the packet start pointer by total size of diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index e0e51083bc..e7162b37ab 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -578,6 +578,10 @@ union dp_align_mac_addr { uint32_t bytes_abcd; uint16_t bytes_ef; } align4; + struct { + uint16_t bytes_ab; + uint32_t bytes_cdef; + } align4_2; }; #define MAX_HTT_METADATA_LEN 32 @@ -663,6 +667,9 @@ struct dp_vdev { /* Mesh mode vdev */ uint32_t mesh_vdev; + /* Mesh mode rx filter setting */ + uint32_t mesh_rx_filter; + /* DSCP-TID mapping table ID */ uint8_t dscp_tid_map_id; diff --git a/dp/wifi3.0/hal_rx.h b/dp/wifi3.0/hal_rx.h index d0180da8b6..9320d025fc 100644 --- a/dp/wifi3.0/hal_rx.h +++ b/dp/wifi3.0/hal_rx.h @@ -990,6 +990,169 @@ hal_rx_msdu_start_nss_get(uint8_t *buf) return nss; } +#define HAL_RX_MPDU_GET_TODS(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_TO_DS_OFFSET)), \ + RX_MPDU_INFO_2_TO_DS_MASK, \ + RX_MPDU_INFO_2_TO_DS_LSB)) + +/* + * hal_rx_mpdu_get_tods(): API to get the tods info + * from rx_mpdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(to_ds) + */ + +static inline uint32_t +hal_rx_mpdu_get_to_ds(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + uint32_t to_ds; + + to_ds = HAL_RX_MPDU_GET_TODS(mpdu_info); + + return to_ds; +} + +#define HAL_RX_MPDU_GET_FROMDS(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_FR_DS_OFFSET)), \ + RX_MPDU_INFO_2_FR_DS_MASK, \ + RX_MPDU_INFO_2_FR_DS_LSB)) + +/* + * hal_rx_mpdu_get_fr_ds(): API to get the from ds info + * from rx_mpdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(fr_ds) + */ + +static inline uint32_t +hal_rx_mpdu_get_fr_ds(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + uint32_t fr_ds; + + fr_ds = HAL_RX_MPDU_GET_FROMDS(mpdu_info); + + return fr_ds; +} + +#define HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_LSB)) + +#define HAL_RX_MPDU_AD1_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_OFFSET)), \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_MASK, \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_LSB)) + +#define HAL_RX_MPDU_AD1_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_OFFSET)), \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_MASK, \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_LSB)) + +#define HAL_RX_MPDU_AD2_15_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_OFFSET)), \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_MASK, \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_LSB)) + +#define HAL_RX_MPDU_AD2_47_16_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_OFFSET)), \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_MASK, \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_LSB)) + +/* + * hal_rx_mpdu_get_addr1(): API to check get address1 of the mpdu + * + * @buf: pointer to the start of RX PKT TLV headera + * @mac_addr: pointer to mac address + * Return: sucess/failure + */ +static inline +QDF_STATUS hal_rx_mpdu_get_addr1(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr1 { + uint32_t ad1_31_0; + uint16_t ad1_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr1 *addr = (struct hal_addr1 *)mac_addr; + uint32_t mac_addr_ad1_valid; + + mac_addr_ad1_valid = HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(mpdu_info); + + if (mac_addr_ad1_valid) { + addr->ad1_31_0 = HAL_RX_MPDU_AD1_31_0_GET(mpdu_info); + addr->ad1_47_32 = HAL_RX_MPDU_AD1_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr2(): API to check get address2 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: sucess/failure + */ +static inline +QDF_STATUS hal_rx_mpdu_get_addr2(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr2 { + uint16_t ad2_15_0; + uint32_t ad2_47_16; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr2 *addr = (struct hal_addr2 *)mac_addr; + uint32_t mac_addr_ad2_valid; + + mac_addr_ad2_valid = HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(mpdu_info); + + if (mac_addr_ad2_valid) { + addr->ad2_15_0 = HAL_RX_MPDU_AD2_15_0_GET(mpdu_info); + addr->ad2_47_16 = HAL_RX_MPDU_AD2_47_16_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + /******************************************************************************* * RX ERROR APIS ******************************************************************************/