qcacmn: [CRYPTO] Support word-aligned 802.11 headers

Some chipsets using Direct-attach architecture need the 802.11 header
padded to a 32-bit boundary for 4-address and QoS frames.

Change-Id: Id29c114b2246cbb1230c9b22f4d04c070069d569
CRs-Fixed: 2233228
This commit is contained in:
Padma Raghunathan
2018-04-27 15:01:25 +05:30
committed by nshrivas
parent 9492161c23
commit 6ac6143190
2 changed files with 65 additions and 9 deletions

View File

@@ -482,10 +482,10 @@ static inline bool wlan_crypto_is_data_protected(const void *data)
* *
* Return: header size of the frame * Return: header size of the frame
*/ */
static inline int ieee80211_hdrsize(const void *data) static inline uint8_t ieee80211_hdrsize(const void *data)
{ {
const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *)data; const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *)data;
int16_t size = sizeof(struct ieee80211_hdr); uint8_t size = sizeof(struct ieee80211_hdr);
if ((hdr->frame_control[1] & WLAN_FC1_DIR_MASK) if ((hdr->frame_control[1] & WLAN_FC1_DIR_MASK)
== (WLAN_FC1_DSTODS)) { == (WLAN_FC1_DSTODS)) {
@@ -502,6 +502,28 @@ static inline int ieee80211_hdrsize(const void *data)
return size; return size;
} }
/**
* ieee80211_hdrspace - calculate frame header size with padding
* @pdev: pdev
* @data: frame header
*
* This function returns the space occupied by the 802.11 header
* and any padding required by the driver. This works for a management
* or data frame.
*
* Return: header size of the frame with padding
*/
static inline uint8_t
ieee80211_hdrspace(struct wlan_objmgr_pdev *pdev, const void *data)
{
uint8_t size = ieee80211_hdrsize(data);
if (wlan_pdev_nif_feat_cap_get(pdev, WLAN_PDEV_F_DATAPAD))
size = roundup(size, sizeof(u_int32_t));
return size;
}
/** /**
* wlan_get_tid - get tid of the frame * wlan_get_tid - get tid of the frame
* @data: frame * @data: frame

View File

@@ -1051,7 +1051,10 @@ QDF_STATUS wlan_crypto_encap(struct wlan_objmgr_vdev *vdev,
struct wlan_objmgr_peer *peer; struct wlan_objmgr_peer *peer;
uint8_t bssid_mac[WLAN_ALEN]; uint8_t bssid_mac[WLAN_ALEN];
uint8_t pdev_id; uint8_t pdev_id;
uint8_t hdrlen;
enum QDF_OPMODE opmode;
opmode = wlan_vdev_mlme_get_opmode(vdev);
wlan_vdev_obj_lock(vdev); wlan_vdev_obj_lock(vdev);
qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN); qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN);
psoc = wlan_vdev_get_psoc(vdev); psoc = wlan_vdev_get_psoc(vdev);
@@ -1117,10 +1120,16 @@ QDF_STATUS wlan_crypto_encap(struct wlan_objmgr_vdev *vdev,
if (!key) if (!key)
return QDF_STATUS_E_INVAL; return QDF_STATUS_E_INVAL;
} }
if (opmode == QDF_MONITOR_MODE)
hdrlen = ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf));
else
hdrlen = ieee80211_hdrspace(wlan_vdev_get_pdev(vdev),
(uint8_t *)qdf_nbuf_data(wbuf));
/* if tkip, is counter measures enabled, then drop the frame */ /* if tkip, is counter measures enabled, then drop the frame */
cipher_table = (struct wlan_crypto_cipher *)key->cipher_table; cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
status = cipher_table->encap(key, wbuf, encapdone, status = cipher_table->encap(key, wbuf, encapdone,
ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf))); hdrlen);
return status; return status;
} }
@@ -1151,7 +1160,10 @@ QDF_STATUS wlan_crypto_decap(struct wlan_objmgr_vdev *vdev,
uint8_t bssid_mac[WLAN_ALEN]; uint8_t bssid_mac[WLAN_ALEN];
uint8_t keyid; uint8_t keyid;
uint8_t pdev_id; uint8_t pdev_id;
uint8_t hdrlen;
enum QDF_OPMODE opmode;
opmode = wlan_vdev_mlme_get_opmode(vdev);
wlan_vdev_obj_lock(vdev); wlan_vdev_obj_lock(vdev);
qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN); qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN);
psoc = wlan_vdev_get_psoc(vdev); psoc = wlan_vdev_get_psoc(vdev);
@@ -1162,6 +1174,12 @@ QDF_STATUS wlan_crypto_decap(struct wlan_objmgr_vdev *vdev,
} }
wlan_vdev_obj_unlock(vdev); wlan_vdev_obj_unlock(vdev);
if (opmode == QDF_MONITOR_MODE)
hdrlen = ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf));
else
hdrlen = ieee80211_hdrspace(wlan_vdev_get_pdev(vdev),
(uint8_t *)qdf_nbuf_data(wbuf));
keyid = wlan_crypto_get_keyid((uint8_t *)qdf_nbuf_data(wbuf)); keyid = wlan_crypto_get_keyid((uint8_t *)qdf_nbuf_data(wbuf));
if (keyid >= WLAN_CRYPTO_MAXKEYIDX) if (keyid >= WLAN_CRYPTO_MAXKEYIDX)
@@ -1223,8 +1241,7 @@ QDF_STATUS wlan_crypto_decap(struct wlan_objmgr_vdev *vdev,
} }
/* if tkip, is counter measures enabled, then drop the frame */ /* if tkip, is counter measures enabled, then drop the frame */
cipher_table = (struct wlan_crypto_cipher *)key->cipher_table; cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
status = cipher_table->decap(key, wbuf, tid, status = cipher_table->decap(key, wbuf, tid, hdrlen);
ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf)));
return status; return status;
} }
@@ -1251,6 +1268,10 @@ QDF_STATUS wlan_crypto_enmic(struct wlan_objmgr_vdev *vdev,
struct wlan_crypto_cipher *cipher_table; struct wlan_crypto_cipher *cipher_table;
struct wlan_objmgr_psoc *psoc; struct wlan_objmgr_psoc *psoc;
uint8_t bssid_mac[WLAN_ALEN]; uint8_t bssid_mac[WLAN_ALEN];
uint8_t hdrlen;
enum QDF_OPMODE opmode;
opmode = wlan_vdev_mlme_get_opmode(vdev);
wlan_vdev_obj_lock(vdev); wlan_vdev_obj_lock(vdev);
@@ -1305,10 +1326,15 @@ QDF_STATUS wlan_crypto_enmic(struct wlan_objmgr_vdev *vdev,
if (!key) if (!key)
return QDF_STATUS_E_INVAL; return QDF_STATUS_E_INVAL;
} }
if (opmode == QDF_MONITOR_MODE)
hdrlen = ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf));
else
hdrlen = ieee80211_hdrspace(wlan_vdev_get_pdev(vdev),
(uint8_t *)qdf_nbuf_data(wbuf));
/* if tkip, is counter measures enabled, then drop the frame */ /* if tkip, is counter measures enabled, then drop the frame */
cipher_table = (struct wlan_crypto_cipher *)key->cipher_table; cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
status = cipher_table->enmic(key, wbuf, encapdone, status = cipher_table->enmic(key, wbuf, encapdone, hdrlen);
ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf)));
return status; return status;
} }
@@ -1336,7 +1362,16 @@ QDF_STATUS wlan_crypto_demic(struct wlan_objmgr_vdev *vdev,
struct wlan_crypto_cipher *cipher_table; struct wlan_crypto_cipher *cipher_table;
struct wlan_objmgr_psoc *psoc; struct wlan_objmgr_psoc *psoc;
uint8_t bssid_mac[WLAN_ALEN]; uint8_t bssid_mac[WLAN_ALEN];
uint8_t hdrlen;
enum QDF_OPMODE opmode;
opmode = wlan_vdev_mlme_get_opmode(vdev);
if (opmode == QDF_MONITOR_MODE)
hdrlen = ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf));
else
hdrlen = ieee80211_hdrspace(wlan_vdev_get_pdev(vdev),
(uint8_t *)qdf_nbuf_data(wbuf));
wlan_vdev_obj_lock(vdev); wlan_vdev_obj_lock(vdev);
qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN); qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN);
@@ -1391,8 +1426,7 @@ QDF_STATUS wlan_crypto_demic(struct wlan_objmgr_vdev *vdev,
} }
/* if tkip, is counter measures enabled, then drop the frame */ /* if tkip, is counter measures enabled, then drop the frame */
cipher_table = (struct wlan_crypto_cipher *)key->cipher_table; cipher_table = (struct wlan_crypto_cipher *)key->cipher_table;
status = cipher_table->demic(key, wbuf, tid, status = cipher_table->demic(key, wbuf, tid, hdrlen);
ieee80211_hdrsize((uint8_t *)qdf_nbuf_data(wbuf)));
return status; return status;
} }