qcacld-3.0: Add support to set/get timestamp for management frames

Add setter and getter function of timestamp for management frames
for the peer based on peer's mac address.

Change-Id: Iab0862eda2392bd516c8ba0b913441b8e0d4c493
CRs-Fixed: 2264667
This commit is contained in:
Alok Kumar 2018-07-05 18:48:14 +05:30 • committed by nshrivas
commit cc943caa7e
4 changed files with 128 additions and 81 deletions

View file

@ -5968,42 +5968,116 @@ static uint16_t ol_txrx_get_vdev_id(struct cdp_vdev *pvdev)
}
/**
* ol_txrx_last_assoc_received() - get time of last assoc received
* @ppeer: peer handle
* ol_txrx_get_last_mgmt_timestamp() - get timestamp of last mgmt frame
* @pdev: pdev handle
* @ppeer_addr: peer mac addr
* @subtype: management frame type
* @timestamp: last timestamp
*
* Return: pointer of the time of last assoc received
* Return: true if timestamp is retrieved for valid peer else false
*/
static qdf_time_t *ol_txrx_last_assoc_received(void *ppeer)
static bool
ol_txrx_get_last_mgmt_timestamp(struct cdp_pdev *ppdev,
u8 *peer_addr,
u8 subtype,
qdf_time_t *timestamp)
{
ol_txrx_peer_handle peer = ppeer;
/*
* Take the lock, find the peer based on peer mac addr.
* If peer is valid, retrieve the timestamp for "subtype" mgmt frame.
* release the lock
*/
union ol_txrx_align_mac_addr_t local_mac_addr_aligned, *mac_addr;
unsigned int index;
struct ol_txrx_peer_t *peer;
bool ret = false;
struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev;
return &peer->last_assoc_rcvd;
qdf_mem_copy(&local_mac_addr_aligned.raw[0],
peer_addr, OL_TXRX_MAC_ADDR_LEN);
mac_addr = &local_mac_addr_aligned;
index = ol_txrx_peer_find_hash_index(pdev, mac_addr);
qdf_spin_lock_bh(&pdev->peer_ref_mutex);
TAILQ_FOREACH(peer, &pdev->peer_hash.bins[index], hash_list_elem) {
if (ol_txrx_peer_find_mac_addr_cmp(mac_addr, &peer->mac_addr) ==
0 && (peer->valid)) {
/* found it */
switch (subtype) {
case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
*timestamp = peer->last_assoc_rcvd;
ret = true;
break;
case IEEE80211_FC0_SUBTYPE_DISASSOC:
case IEEE80211_FC0_SUBTYPE_DEAUTH:
*timestamp = peer->last_disassoc_rcvd;
ret = true;
break;
default:
break;
}
qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
return ret;
}
}
qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
return false; /* failure */
}
/**
* ol_txrx_last_disassoc_received() - get time of last disassoc received
* @ppeer: peer handle
* ol_txrx_update_last_mgmt_timestamp() - set timestamp of last mgmt frame
* @pdev: pdev handle
* @ppeer_addr: peer mac addr
* @timestamp: time to be set
* @subtype: management frame type
*
* Return: pointer of the time of last disassoc received
* Return: true if timestamp is updated for valid peer else false
*/
static qdf_time_t *ol_txrx_last_disassoc_received(void *ppeer)
static bool
ol_txrx_update_last_mgmt_timestamp(struct cdp_pdev *ppdev, u8 *peer_addr,
qdf_time_t timestamp, u8 subtype)
{
ol_txrx_peer_handle peer = ppeer;
/*
* Take the lock, find the peer based on peer mac addr.
* If peer is valid, update the timestamp for "subtype" mgmt frame.
* release the lock
*/
union ol_txrx_align_mac_addr_t local_mac_addr_aligned, *mac_addr;
bool ret = false;
unsigned int index;
struct ol_txrx_peer_t *peer;
struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)ppdev;
return &peer->last_disassoc_rcvd;
}
qdf_mem_copy(&local_mac_addr_aligned.raw[0],
peer_addr, OL_TXRX_MAC_ADDR_LEN);
mac_addr = &local_mac_addr_aligned;
/**
* ol_txrx_last_deauth_received() - get time of last deauth received
* @ppeer: peer handle
*
* Return: pointer of the time of last deauth received
*/
static qdf_time_t *ol_txrx_last_deauth_received(void *ppeer)
{
ol_txrx_peer_handle peer = ppeer;
index = ol_txrx_peer_find_hash_index(pdev, mac_addr);
qdf_spin_lock_bh(&pdev->peer_ref_mutex);
TAILQ_FOREACH(peer, &pdev->peer_hash.bins[index], hash_list_elem) {
if (ol_txrx_peer_find_mac_addr_cmp(mac_addr, &peer->mac_addr) ==
0 && (peer->valid)) {
/* found it */
switch (subtype) {
case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
peer->last_assoc_rcvd = timestamp;
ret = true;
break;
case IEEE80211_FC0_SUBTYPE_DISASSOC:
case IEEE80211_FC0_SUBTYPE_DEAUTH:
peer->last_disassoc_rcvd = timestamp;
ret = true;
break;
default:
break;
}
qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
return ret;
}
}
qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
return &peer->last_deauth_rcvd;
return false; /* failure */
}
/**
@ -6410,10 +6484,9 @@ static struct cdp_peer_ops ol_ops_peer = {
.is_vdev_restore_last_peer = is_vdev_restore_last_peer,
.update_last_real_peer = ol_txrx_update_last_real_peer,
#endif /* CONFIG_HL_SUPPORT */
.last_assoc_received = ol_txrx_last_assoc_received,
.last_disassoc_received = ol_txrx_last_disassoc_received,
.last_deauth_received = ol_txrx_last_deauth_received,
.peer_detach_force_delete = ol_txrx_peer_detach_force_delete,
.get_last_mgmt_timestamp = ol_txrx_get_last_mgmt_timestamp,
.update_last_mgmt_timestamp = ol_txrx_update_last_mgmt_timestamp,
};
static struct cdp_tx_delay_ops ol_ops_delay = {

View file

@ -145,7 +145,7 @@ static void ol_txrx_peer_find_hash_detach(struct ol_txrx_pdev_t *pdev)
qdf_mem_free(pdev->peer_hash.bins);
}
static inline unsigned int
unsigned int
ol_txrx_peer_find_hash_index(struct ol_txrx_pdev_t *pdev,
union ol_txrx_align_mac_addr_t *mac_addr)
{

View file

@ -90,6 +90,10 @@ struct ol_txrx_peer_t *ol_txrx_peer_find_by_id(struct ol_txrx_pdev_t *pdev,
return NULL;
}
unsigned int
ol_txrx_peer_find_hash_index(struct ol_txrx_pdev_t *pdev,
union ol_txrx_align_mac_addr_t *mac_addr);
void
ol_txrx_peer_find_hash_add(struct ol_txrx_pdev_t *pdev,
struct ol_txrx_peer_t *peer);

View file

@ -3707,11 +3707,10 @@ static bool wma_is_pkt_drop_candidate(tp_wma_handle wma_handle,
uint8_t *peer_addr, uint8_t *bssid,
uint8_t subtype)
{
void *peer = NULL;
struct cdp_pdev *pdev_ctx;
uint8_t peer_id;
bool should_drop = false;
qdf_time_t *ptr;
qdf_time_t timestamp;
bool ret;
void *soc = cds_get_context(QDF_MODULE_ID_SOC);
uint8_t nan_addr[] = {0x50, 0x6F, 0x9A, 0x01, 0x00, 0x00};
@ -3741,63 +3740,34 @@ static bool wma_is_pkt_drop_candidate(tp_wma_handle wma_handle,
goto end;
}
peer = cdp_peer_get_ref_by_addr(soc, pdev_ctx, peer_addr, &peer_id,
PEER_DEBUG_ID_WMA_PKT_DROP);
if (!peer) {
ret = cdp_peer_get_last_mgmt_timestamp(soc, pdev_ctx,
peer_addr, subtype,
&timestamp);
if (!ret) {
if (IEEE80211_FC0_SUBTYPE_ASSOC_REQ != subtype) {
WMA_LOGI(
FL("Received mgmt frame: %0x from unknown peer: %pM"),
subtype, peer_addr);
WMA_LOGE(FL("cdp_last_mgmt_timestamp_received %s 0x%x"),
"failed for subtype", subtype);
should_drop = true;
}
goto end;
} else if (timestamp > 0 &&
qdf_system_time_before(qdf_get_system_timestamp(),
timestamp +
WMA_MGMT_FRAME_DETECT_DOS_TIMER)) {
WMA_LOGD(FL("Dropping subtype 0x%x frame. %s %d ms %s %d ms"),
subtype, "It is received after",
(int)(qdf_get_system_timestamp() - timestamp),
"of last frame. Allow it only after",
WMA_MGMT_FRAME_DETECT_DOS_TIMER);
should_drop = true;
goto end;
}
switch (subtype) {
case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
ptr = cdp_peer_last_assoc_received(soc, peer);
if (!ptr) {
WMA_LOGE(FL("cdp_peer_last_assoc_received Failed"));
should_drop = true;
goto end;
} else if (*ptr > 0 &&
qdf_system_time_before(qdf_get_system_timestamp(),
*ptr + WMA_MGMT_FRAME_DETECT_DOS_TIMER)) {
WMA_LOGD(FL("Dropping Assoc Req as it is received after %d ms of last frame. Allow it only after %d ms"),
(int)(qdf_get_system_timestamp() - *ptr),
WMA_MGMT_FRAME_DETECT_DOS_TIMER);
should_drop = true;
break;
}
*ptr = qdf_get_system_timestamp();
break;
case IEEE80211_FC0_SUBTYPE_DISASSOC:
case IEEE80211_FC0_SUBTYPE_DEAUTH:
ptr = cdp_peer_last_disassoc_received(soc, peer);
if (!ptr) {
WMA_LOGE(FL("cdp_peer_last_disassoc_received Failed"));
should_drop = true;
goto end;
} else if (*ptr > 0 &&
qdf_system_time_before(qdf_get_system_timestamp(),
*ptr + WMA_MGMT_FRAME_DETECT_DOS_TIMER)) {
WMA_LOGD(FL("Dropping subtype %x frame as it is received after %d ms of last frame. Allow it only after %d ms"),
subtype, (int)
(qdf_get_system_timestamp() - *ptr),
WMA_MGMT_FRAME_DETECT_DOS_TIMER);
should_drop = true;
break;
}
*ptr = qdf_get_system_timestamp();
break;
default:
break;
}
if (!cdp_peer_update_last_mgmt_timestamp(soc, pdev_ctx, peer_addr,
qdf_get_system_timestamp(),
subtype))
should_drop = true;
end:
if (peer)
cdp_peer_release_ref(soc, peer, PEER_DEBUG_ID_WMA_PKT_DROP);
return should_drop;
}