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
This commit is contained in:
Tallapragada Kalyan
2017-07-26 00:31:35 +05:30
committed by snandini
parent fb72b637f7
commit 1c14d5d8e9
5 changed files with 39 additions and 25 deletions

View File

@@ -1476,7 +1476,7 @@ static void dp_wds_aging_timer_fn(void *soc_hdl)
struct dp_pdev *pdev; struct dp_pdev *pdev;
struct dp_vdev *vdev; struct dp_vdev *vdev;
struct dp_peer *peer; struct dp_peer *peer;
struct dp_ast_entry *ase; struct dp_ast_entry *ase, *temp_ase;
int i; int i;
qdf_spin_lock_bh(&soc->ast_lock); 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]; pdev = soc->pdev_list[i];
DP_PDEV_ITERATE_VDEV_LIST(pdev, vdev) { DP_PDEV_ITERATE_VDEV_LIST(pdev, vdev) {
DP_VDEV_ITERATE_PEER_LIST(vdev, peer) { 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 * 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, static inline void dp_peer_delete_ast_entries(struct dp_soc *soc,
struct dp_peer *peer) 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); 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) { if (ast_entry->next_hop) {
soc->cdp_soc.ol_ops->peer_del_wds_entry( soc->cdp_soc.ol_ops->peer_del_wds_entry(
soc->osif_soc, peer->vdev->pdev->osif_pdev,
ast_entry->mac_addr.raw); ast_entry->mac_addr.raw);
} }

View File

@@ -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) { TAILQ_FOREACH(ast_entry, &peer->ast_entry_list, ase_list_elem) {
if (!(qdf_mem_cmp(mac_addr, ast_entry->mac_addr.raw, if (!(qdf_mem_cmp(mac_addr, ast_entry->mac_addr.raw,
DP_MAC_ADDR_LEN))) { DP_MAC_ADDR_LEN))) {
qdf_spin_unlock_bh(&soc->ast_lock);
ast_entry->ast_idx = hw_peer_id; ast_entry->ast_idx = hw_peer_id;
soc->ast_table[hw_peer_id] = ast_entry; soc->ast_table[hw_peer_id] = ast_entry;
ast_entry->is_active = TRUE; ast_entry->is_active = TRUE;
qdf_spin_unlock_bh(&soc->ast_lock);
return; 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); qdf_spin_lock_bh(&soc->ast_lock);
/* If AST entry already exists , just return from here */ /* 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); qdf_spin_unlock_bh(&soc->ast_lock);
return 1; return 1;
} }

View File

@@ -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, uint8_t dp_get_peer_mac_addr_frm_id(struct cdp_soc_t *soc_handle,
uint16_t peer_id, uint8_t *peer_mac); 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 #ifdef FEATURE_WDS
int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer, int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer,
uint8_t *mac_addr, uint8_t is_self); uint8_t *mac_addr, uint8_t is_self);
void dp_peer_del_ast(struct dp_soc *soc, void dp_peer_del_ast(struct dp_soc *soc,
struct dp_ast_entry *ast_entry); 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 #else
static inline int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer, static inline int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer,
uint8_t *mac_addr, uint8_t is_self) 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) 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 #endif
#ifdef DP_LFR #ifdef DP_LFR

View File

@@ -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; uint16_t peer_id = 0xFFFF;
struct dp_peer *peer = NULL; struct dp_peer *peer = NULL;
uint32_t sgi, rate_mcs, tid; uint32_t sgi, rate_mcs, tid;
struct dp_ast_entry *ase;
uint16_t sa_idx;
uint8_t *data;
rx_bufs_used++; 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 * This is a Multicast echo check, drop the pkt if we meet
* the Multicast Echo Check condition * 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)) { 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); 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))) { if ((sa_idx < 0) || (sa_idx > (WLAN_UMAC_PSOC_MAX_PEERS * 2))) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"invalid sa_idx: %d", sa_idx); "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]; ase = soc->ast_table[sa_idx];
if (ase) { } else
if (ase->is_mec || (ase->peer != peer)) { ase = dp_peer_ast_hash_find(soc, &data[DP_MAC_ADDR_LEN], 0);
QDF_TRACE(QDF_MODULE_ID_DP,
QDF_TRACE_LEVEL_INFO,
"received pkt with same src mac %pM",
&nbuf_data[DP_MAC_ADDR_LEN]);
qdf_nbuf_free(nbuf); if (ase) {
goto fail; 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 */ /* WDS Source Port Learning */
if (qdf_likely(vdev->rx_decap_type == htt_cmn_pkt_type_ethernet)) if (qdf_likely(vdev->rx_decap_type == htt_cmn_pkt_type_ethernet))

View File

@@ -105,8 +105,8 @@ union dp_rx_desc_list_elem_t;
#define DP_VDEV_ITERATE_PEER_LIST(_vdev, _peer) \ #define DP_VDEV_ITERATE_PEER_LIST(_vdev, _peer) \
TAILQ_FOREACH((_peer), &(_vdev)->peer_list, peer_list_elem) TAILQ_FOREACH((_peer), &(_vdev)->peer_list, peer_list_elem)
#define DP_PEER_ITERATE_ASE_LIST(_peer, _ase) \ #define DP_PEER_ITERATE_ASE_LIST(_peer, _ase, _temp_ase) \
TAILQ_FOREACH((_ase), &peer->ast_entry_list, ase_list_elem) TAILQ_FOREACH_SAFE((_ase), &peer->ast_entry_list, ase_list_elem, (_temp_ase))
#define DP_MUTEX_TYPE qdf_spinlock_t #define DP_MUTEX_TYPE qdf_spinlock_t