qcacmn: MEC loopback check even when sa_is_valid not set
There is a case when the multicast/broadcast frame gets loop backed even before a MEC WDS entry gets added, in this case the MEC check based on sa_is_valid will fail, hence added another ast lookup check. Also fix the ast entry iterator to use _safe option, since we are deleting ast entries in the same iterations Change-Id: I0567893783649d991c3623a61c60fbc63d1a24ef
这个提交包含在:
@@ -1476,7 +1476,7 @@ static void dp_wds_aging_timer_fn(void *soc_hdl)
|
||||
struct dp_pdev *pdev;
|
||||
struct dp_vdev *vdev;
|
||||
struct dp_peer *peer;
|
||||
struct dp_ast_entry *ase;
|
||||
struct dp_ast_entry *ase, *temp_ase;
|
||||
int i;
|
||||
|
||||
qdf_spin_lock_bh(&soc->ast_lock);
|
||||
@@ -1485,7 +1485,7 @@ static void dp_wds_aging_timer_fn(void *soc_hdl)
|
||||
pdev = soc->pdev_list[i];
|
||||
DP_PDEV_ITERATE_VDEV_LIST(pdev, vdev) {
|
||||
DP_VDEV_ITERATE_PEER_LIST(vdev, peer) {
|
||||
DP_PEER_ITERATE_ASE_LIST(peer, ase) {
|
||||
DP_PEER_ITERATE_ASE_LIST(peer, ase, temp_ase) {
|
||||
/*
|
||||
* Do not expire static ast entries
|
||||
*/
|
||||
@@ -4730,12 +4730,12 @@ static struct cdp_wds_ops dp_ops_wds = {
|
||||
static inline void dp_peer_delete_ast_entries(struct dp_soc *soc,
|
||||
struct dp_peer *peer)
|
||||
{
|
||||
struct dp_ast_entry *ast_entry;
|
||||
struct dp_ast_entry *ast_entry, *temp_ast_entry;
|
||||
qdf_spin_lock_bh(&soc->ast_lock);
|
||||
DP_PEER_ITERATE_ASE_LIST(peer, ast_entry) {
|
||||
DP_PEER_ITERATE_ASE_LIST(peer, ast_entry, temp_ast_entry) {
|
||||
if (ast_entry->next_hop) {
|
||||
soc->cdp_soc.ol_ops->peer_del_wds_entry(
|
||||
soc->osif_soc,
|
||||
peer->vdev->pdev->osif_pdev,
|
||||
ast_entry->mac_addr.raw);
|
||||
}
|
||||
|
||||
|
@@ -375,10 +375,10 @@ static inline void dp_peer_map_ast(struct dp_soc *soc,
|
||||
TAILQ_FOREACH(ast_entry, &peer->ast_entry_list, ase_list_elem) {
|
||||
if (!(qdf_mem_cmp(mac_addr, ast_entry->mac_addr.raw,
|
||||
DP_MAC_ADDR_LEN))) {
|
||||
qdf_spin_unlock_bh(&soc->ast_lock);
|
||||
ast_entry->ast_idx = hw_peer_id;
|
||||
soc->ast_table[hw_peer_id] = ast_entry;
|
||||
ast_entry->is_active = TRUE;
|
||||
qdf_spin_unlock_bh(&soc->ast_lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -415,7 +415,11 @@ int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer,
|
||||
qdf_spin_lock_bh(&soc->ast_lock);
|
||||
|
||||
/* If AST entry already exists , just return from here */
|
||||
if (dp_peer_ast_hash_find(soc, mac_addr, 0)) {
|
||||
ast_entry = dp_peer_ast_hash_find(soc, mac_addr, 0);
|
||||
if (ast_entry) {
|
||||
if (ast_entry->is_mec)
|
||||
ast_entry->is_active = TRUE;
|
||||
|
||||
qdf_spin_unlock_bh(&soc->ast_lock);
|
||||
return 1;
|
||||
}
|
||||
|
@@ -54,14 +54,14 @@ void dp_rx_sec_ind_handler(void *soc_handle, uint16_t peer_id,
|
||||
uint8_t dp_get_peer_mac_addr_frm_id(struct cdp_soc_t *soc_handle,
|
||||
uint16_t peer_id, uint8_t *peer_mac);
|
||||
|
||||
struct dp_ast_entry *dp_peer_ast_hash_find(struct dp_soc *soc,
|
||||
uint8_t *ast_mac_addr, int mac_addr_is_aligned);
|
||||
|
||||
#ifdef FEATURE_WDS
|
||||
int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer,
|
||||
uint8_t *mac_addr, uint8_t is_self);
|
||||
void dp_peer_del_ast(struct dp_soc *soc,
|
||||
struct dp_ast_entry *ast_entry);
|
||||
struct dp_ast_entry *dp_peer_ast_hash_find(struct dp_soc *soc,
|
||||
uint8_t *ast_mac_addr, int mac_addr_is_aligned);
|
||||
#else
|
||||
static inline int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer,
|
||||
uint8_t *mac_addr, uint8_t is_self)
|
||||
@@ -72,6 +72,11 @@ static inline void dp_peer_del_ast(struct dp_soc *soc,
|
||||
struct dp_ast_entry *ast_entry)
|
||||
{
|
||||
}
|
||||
static inline struct dp_ast_entry *dp_peer_ast_hash_find(struct dp_soc *soc,
|
||||
uint8_t *ast_mac_addr, int mac_addr_is_aligned)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DP_LFR
|
||||
|
@@ -274,6 +274,9 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
|
||||
uint16_t peer_id = 0xFFFF;
|
||||
struct dp_peer *peer = NULL;
|
||||
uint32_t sgi, rate_mcs, tid;
|
||||
struct dp_ast_entry *ase;
|
||||
uint16_t sa_idx;
|
||||
uint8_t *data;
|
||||
|
||||
rx_bufs_used++;
|
||||
|
||||
@@ -353,13 +356,11 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
|
||||
* This is a Multicast echo check, drop the pkt if we meet
|
||||
* the Multicast Echo Check condition
|
||||
*/
|
||||
data = qdf_nbuf_data(nbuf);
|
||||
qdf_spin_lock_bh(&soc->ast_lock);
|
||||
if (hal_rx_msdu_end_sa_is_valid_get(rx_desc->rx_buf_start)) {
|
||||
struct dp_ast_entry *ase;
|
||||
uint16_t sa_idx;
|
||||
uint8_t *nbuf_data = NULL;
|
||||
|
||||
nbuf_data = qdf_nbuf_data(nbuf);
|
||||
sa_idx = hal_rx_msdu_end_sa_idx_get(rx_desc->rx_buf_start);
|
||||
|
||||
if ((sa_idx < 0) || (sa_idx > (WLAN_UMAC_PSOC_MAX_PEERS * 2))) {
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
"invalid sa_idx: %d", sa_idx);
|
||||
@@ -367,18 +368,22 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
|
||||
}
|
||||
|
||||
ase = soc->ast_table[sa_idx];
|
||||
if (ase) {
|
||||
if (ase->is_mec || (ase->peer != peer)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_DP,
|
||||
QDF_TRACE_LEVEL_INFO,
|
||||
"received pkt with same src mac %pM",
|
||||
&nbuf_data[DP_MAC_ADDR_LEN]);
|
||||
} else
|
||||
ase = dp_peer_ast_hash_find(soc, &data[DP_MAC_ADDR_LEN], 0);
|
||||
|
||||
qdf_nbuf_free(nbuf);
|
||||
goto fail;
|
||||
}
|
||||
if (ase) {
|
||||
if (ase->is_mec || (ase->peer != peer)) {
|
||||
qdf_spin_unlock_bh(&soc->ast_lock);
|
||||
QDF_TRACE(QDF_MODULE_ID_DP,
|
||||
QDF_TRACE_LEVEL_INFO,
|
||||
"received pkt with same src mac %pM",
|
||||
&data[DP_MAC_ADDR_LEN]);
|
||||
|
||||
qdf_nbuf_free(nbuf);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
qdf_spin_unlock_bh(&soc->ast_lock);
|
||||
|
||||
/* WDS Source Port Learning */
|
||||
if (qdf_likely(vdev->rx_decap_type == htt_cmn_pkt_type_ethernet))
|
||||
|
@@ -105,8 +105,8 @@ union dp_rx_desc_list_elem_t;
|
||||
#define DP_VDEV_ITERATE_PEER_LIST(_vdev, _peer) \
|
||||
TAILQ_FOREACH((_peer), &(_vdev)->peer_list, peer_list_elem)
|
||||
|
||||
#define DP_PEER_ITERATE_ASE_LIST(_peer, _ase) \
|
||||
TAILQ_FOREACH((_ase), &peer->ast_entry_list, ase_list_elem)
|
||||
#define DP_PEER_ITERATE_ASE_LIST(_peer, _ase, _temp_ase) \
|
||||
TAILQ_FOREACH_SAFE((_ase), &peer->ast_entry_list, ase_list_elem, (_temp_ase))
|
||||
|
||||
#define DP_MUTEX_TYPE qdf_spinlock_t
|
||||
|
||||
|
在新工单中引用
屏蔽一个用户