diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h index d90181d6ee7a..4fb7272b69d8 100644 --- a/dp/inc/cdp_txrx_cmn.h +++ b/dp/inc/cdp_txrx_cmn.h @@ -270,7 +270,7 @@ cdp_pdev_detach(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, int force) static inline void *cdp_peer_create (ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - uint8_t *peer_mac_addr) + uint8_t *peer_mac_addr, void *ol_peer) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -284,7 +284,7 @@ static inline void *cdp_peer_create return NULL; return soc->ops->cmn_drv_ops->txrx_peer_create(vdev, - peer_mac_addr); + peer_mac_addr, ol_peer); } static inline void cdp_peer_setup @@ -1237,6 +1237,26 @@ static inline int cdp_set_pn_check(ol_txrx_soc_handle soc, return 0; } +static inline int cdp_set_key(ol_txrx_soc_handle soc, + struct cdp_peer *peer_handle, + bool is_unicast, uint32_t *key) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return 0; + } + + if (!soc->ops->ctrl_ops || + !soc->ops->ctrl_ops->set_key) + return 0; + + soc->ops->ctrl_ops->set_key(peer_handle, + is_unicast, key); + return 0; +} + /** * cdp_update_config_parameters(): function to propagate configuration * parameters to datapath diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 8dfaf6a98723..c08526810e31 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -85,7 +85,8 @@ struct cdp_cmn_ops { void (*txrx_pdev_detach)(struct cdp_pdev *pdev, int force); void *(*txrx_peer_create) - (struct cdp_vdev *vdev, uint8_t *peer_mac_addr); + (struct cdp_vdev *vdev, uint8_t *peer_mac_addr, + void *ol_peer); void (*txrx_peer_setup) (struct cdp_vdev *vdev_hdl, void *peer_hdl); @@ -520,6 +521,8 @@ struct cdp_ctrl_ops { enum cdp_nac_param_cmd cmd, char *bssid, char *client_macaddr, uint8_t chan_num); #endif + void (*set_key)(struct cdp_peer *peer_handle, + bool is_unicast, uint32_t *key); }; struct cdp_me_ops { @@ -742,6 +745,8 @@ struct ol_if_ops { void (*rx_mic_error)(void *ol_soc_handle, uint16_t vdev_id, void *wh); + bool (*rx_frag_tkip_demic)(void *ol_peer, qdf_nbuf_t nbuf, + uint16_t hdr_space); uint8_t (*freq_to_channel)(void *ol_soc_handle, uint16_t vdev_id); void (*record_act_change)(struct wlan_objmgr_pdev *pdev, diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index df9384fab8be..2ae2a8c5d589 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -422,6 +422,8 @@ void dp_set_overload(struct cdp_pdev *pdev_handle, bool overload); bool dp_peer_is_inact(void *peer_handle); void dp_init_inact_timer(struct dp_soc *soc); void dp_free_inact_timer(struct dp_soc *soc); +void dp_set_michael_key(struct cdp_peer *peer_handle, + bool is_unicast, uint32_t *key); /* * dp_get_mac_id_for_pdev() - Return mac corresponding to pdev for mac diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 6de1477985e5..8f04b4dc5eef 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -62,7 +62,7 @@ static void dp_pkt_log_con_service(struct cdp_pdev *ppdev, void *scn); #endif static void dp_pktlogmod_exit(struct dp_pdev *handle); static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, - uint8_t *peer_mac_addr); + uint8_t *peer_mac_addr, void *ol_peer); static void dp_peer_delete_wifi3(void *peer_handle, uint32_t bitmap); #define DP_INTR_POLL_TIMER_MS 10 @@ -3356,7 +3356,7 @@ static struct cdp_vdev *dp_vdev_attach_wifi3(struct cdp_pdev *txrx_pdev, if (wlan_op_mode_sta == vdev->opmode) dp_peer_create_wifi3((struct cdp_vdev *)vdev, - vdev->mac_addr.raw); + vdev->mac_addr.raw, NULL); return (struct cdp_vdev *)vdev; @@ -3543,7 +3543,7 @@ static inline void dp_peer_delete_ast_entries(struct dp_soc *soc, * Return: DP peeer handle on success, NULL on failure */ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, - uint8_t *peer_mac_addr) + uint8_t *peer_mac_addr, void *ol_peer) { struct dp_peer *peer; int i; @@ -3664,6 +3664,7 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, dp_local_peer_id_alloc(pdev, peer); #endif DP_STATS_INIT(peer); + peer->ol_peer = ol_peer; return (void *)peer; } @@ -7111,6 +7112,7 @@ static struct cdp_ctrl_ops dp_ops_ctrl = { #ifdef ATH_SUPPORT_NAC_RSSI .txrx_vdev_config_for_nac_rssi = dp_config_for_nac_rssi, #endif + .set_key = dp_set_michael_key, }; static struct cdp_me_ops dp_ops_me = { diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 9452fda4fa30..c653be5644b8 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -2378,3 +2378,18 @@ void dp_peer_rxtid_stats(struct dp_peer *peer, void (*dp_stats_cmd_cb), } } +void dp_set_michael_key(struct cdp_peer *peer_handle, + bool is_unicast, uint32_t *key) +{ + struct dp_peer *peer = (struct dp_peer *)peer_handle; + uint8_t sec_index = is_unicast ? 1 : 0; + + if (!peer) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "peer not found "); + return; + } + + qdf_mem_copy(&peer->security[sec_index].michael_key[0], + key, IEEE80211_WEP_MICLEN); +} diff --git a/dp/wifi3.0/dp_rx_defrag.c b/dp/wifi3.0/dp_rx_defrag.c index 437fd748302e..ae3aac1ab087 100644 --- a/dp/wifi3.0/dp_rx_defrag.c +++ b/dp/wifi3.0/dp_rx_defrag.c @@ -97,12 +97,12 @@ static void dp_rx_return_head_frag_desc(struct dp_peer *peer, pdev = peer->vdev->pdev; soc = pdev->soc; dp_rxdma_srng = &pdev->rx_refill_buf_ring; - rx_desc_pool = &soc->rx_desc_buf[0]; + rx_desc_pool = &soc->rx_desc_buf[pdev->pdev_id]; dp_rx_add_to_free_desc_list(&head, &tail, peer->rx_tid[tid].head_frag_desc); dp_rx_buffers_replenish(soc, 0, dp_rxdma_srng, rx_desc_pool, - 1, &head, &tail, HAL_RX_BUF_RBM_SW3_BM); + 1, &head, &tail); } } @@ -412,9 +412,6 @@ static QDF_STATUS dp_rx_defrag_tkip_decap(qdf_nbuf_t msdu, uint16_t hdrlen) return QDF_STATUS_E_DEFRAG_ERROR; } - qdf_mem_move(orig_hdr + dp_f_tkip.ic_header, orig_hdr, hdrlen); - - qdf_nbuf_pull_head(msdu, dp_f_tkip.ic_header); qdf_nbuf_trim_tail(msdu, dp_f_tkip.ic_trailer); return QDF_STATUS_SUCCESS; @@ -611,6 +608,7 @@ static QDF_STATUS dp_rx_defrag_mic(const uint8_t *key, qdf_nbuf_t wbuf, dp_rx_defrag_michdr((struct ieee80211_frame *)(qdf_nbuf_data(wbuf) + rx_desc_len), hdr); + l = dp_rx_get_le32(key); r = dp_rx_get_le32(key + 4); @@ -625,8 +623,8 @@ static QDF_STATUS dp_rx_defrag_mic(const uint8_t *key, qdf_nbuf_t wbuf, dp_rx_michael_block(l, r); /* first buffer has special handling */ - data = (uint8_t *) qdf_nbuf_data(wbuf) + rx_desc_len + off; - space = qdf_nbuf_len(wbuf) - rx_desc_len - off; + data = (uint8_t *)qdf_nbuf_data(wbuf) + off; + space = qdf_nbuf_len(wbuf) - off; for (;; ) { if (space > data_len) @@ -653,8 +651,8 @@ static QDF_STATUS dp_rx_defrag_mic(const uint8_t *key, qdf_nbuf_t wbuf, * Block straddles buffers, split references. */ data_next = - (uint8_t *) qdf_nbuf_data(wbuf) + rx_desc_len; - if ((qdf_nbuf_len(wbuf) - rx_desc_len) < + (uint8_t *)qdf_nbuf_data(wbuf) + off; + if ((qdf_nbuf_len(wbuf)) < sizeof(uint32_t) - space) { return QDF_STATUS_E_DEFRAG_ERROR; } @@ -664,22 +662,19 @@ static QDF_STATUS dp_rx_defrag_mic(const uint8_t *key, qdf_nbuf_t wbuf, data_next[0], data_next[1], data_next[2]); data = data_next + 3; - space = (qdf_nbuf_len(wbuf) - rx_desc_len) - - 3; + space = (qdf_nbuf_len(wbuf) - off) - 3; break; case 2: l ^= dp_rx_get_le32_split(data[0], data[1], data_next[0], data_next[1]); data = data_next + 2; - space = (qdf_nbuf_len(wbuf) - rx_desc_len) - - 2; + space = (qdf_nbuf_len(wbuf) - off) - 2; break; case 3: l ^= dp_rx_get_le32_split(data[0], data[1], data[2], data_next[0]); data = data_next + 1; - space = (qdf_nbuf_len(wbuf) - rx_desc_len) - - 1; + space = (qdf_nbuf_len(wbuf) - off) - 1; break; } dp_rx_michael_block(l, r); @@ -688,8 +683,8 @@ static QDF_STATUS dp_rx_defrag_mic(const uint8_t *key, qdf_nbuf_t wbuf, /* * Setup for next buffer. */ - data = (uint8_t *) qdf_nbuf_data(wbuf) + rx_desc_len; - space = qdf_nbuf_len(wbuf) - rx_desc_len; + data = (uint8_t *)qdf_nbuf_data(wbuf) + off; + space = qdf_nbuf_len(wbuf) - off; } } /* Last block and padding (0x5a, 4..7 x 0) */ @@ -729,27 +724,35 @@ static QDF_STATUS dp_rx_defrag_tkip_demic(const uint8_t *key, qdf_nbuf_t msdu, uint16_t hdrlen) { QDF_STATUS status; - uint32_t pktlen; + uint32_t pktlen = 0; uint8_t mic[IEEE80211_WEP_MICLEN]; uint8_t mic0[IEEE80211_WEP_MICLEN]; - int rx_desc_len = sizeof(struct rx_pkt_tlvs); + qdf_nbuf_t prev = NULL, next; - pktlen = qdf_nbuf_len(msdu) - rx_desc_len; + next = msdu; + while (next) { + pktlen += (qdf_nbuf_len(next) - hdrlen); + prev = next; + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s pktlen %ld\n", __func__, + qdf_nbuf_len(next) - hdrlen); + next = qdf_nbuf_next(next); + } + + qdf_nbuf_copy_bits(prev, qdf_nbuf_len(prev) - dp_f_tkip.ic_miclen, + dp_f_tkip.ic_miclen, (caddr_t)mic0); + qdf_nbuf_trim_tail(prev, dp_f_tkip.ic_miclen); + pktlen -= dp_f_tkip.ic_miclen; status = dp_rx_defrag_mic(key, msdu, hdrlen, - pktlen - (hdrlen + dp_f_tkip.ic_miclen), mic); + pktlen, mic); if (QDF_IS_STATUS_ERROR(status)) return status; - qdf_nbuf_copy_bits(msdu, pktlen - dp_f_tkip.ic_miclen + rx_desc_len, - dp_f_tkip.ic_miclen, (caddr_t)mic0); - - if (!qdf_mem_cmp(mic, mic0, dp_f_tkip.ic_miclen)) + if (qdf_mem_cmp(mic, mic0, dp_f_tkip.ic_miclen)) return QDF_STATUS_E_DEFRAG_ERROR; - qdf_nbuf_trim_tail(msdu, dp_f_tkip.ic_miclen); - return QDF_STATUS_SUCCESS; } @@ -824,11 +827,20 @@ dp_rx_construct_fraglist(struct dp_peer *peer, * * Return: None */ -static void dp_rx_defrag_err(uint8_t vdev_id, uint8_t *peer_mac_addr, - int tid, uint32_t tsf32, uint32_t err_type, qdf_nbuf_t rx_frame, - uint64_t *pn, uint8_t key_id) +static void dp_rx_defrag_err(struct dp_vdev *vdev, qdf_nbuf_t nbuf) { - /* TODO: Who needs to know about the TKIP MIC error */ + struct ol_if_ops *tops = NULL; + struct dp_pdev *pdev = vdev->pdev; + int rx_desc_len = sizeof(struct rx_pkt_tlvs); + uint8_t *orig_hdr; + struct ieee80211_frame *wh; + + orig_hdr = (uint8_t *)(qdf_nbuf_data(nbuf) + rx_desc_len); + wh = (struct ieee80211_frame *)orig_hdr; + + tops = pdev->soc->cdp_soc.ol_ops; + if (tops->rx_mic_error) + tops->rx_mic_error(pdev->osif_pdev, vdev->vdev_id, wh); } @@ -1117,6 +1129,8 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid, uint16_t hdr_space; uint8_t key[DEFRAG_IEEE80211_KEY_LEN]; struct dp_vdev *vdev = peer->vdev; + struct dp_soc *soc = vdev->pdev->soc; + uint8_t status = 0; hdr_space = dp_rx_defrag_hdrsize(cur); index = hal_rx_msdu_is_wlan_mcast(cur) ? @@ -1134,14 +1148,8 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid, cur = frag_list_head; QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO, - "%s: Security type: %d\n", __func__, - peer->security[index].sec_type); - - /* Temporary fix to drop TKIP encrypted packets */ - if (peer->security[index].sec_type == - htt_sec_type_tkip) { - return QDF_STATUS_E_DEFRAG_ERROR; - } + "%s: index %d Security type: %d\n", __func__, + index, peer->security[index].sec_type); switch (peer->security[index].sec_type) { case htt_sec_type_tkip: @@ -1152,9 +1160,6 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid, tmp_next = qdf_nbuf_next(cur); if (dp_rx_defrag_tkip_decap(cur, hdr_space)) { - /* TKIP decap failed, discard frags */ - dp_rx_defrag_frames_free(frag_list_head); - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "dp_rx_defrag: TKIP decap failed"); @@ -1163,6 +1168,9 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid, } cur = tmp_next; } + + /* If success, increment header to be stripped later */ + hdr_space += dp_f_tkip.ic_header; break; case htt_sec_type_aes_ccmp: @@ -1170,9 +1178,6 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid, tmp_next = qdf_nbuf_next(cur); if (dp_rx_defrag_ccmp_demic(cur, hdr_space)) { - /* CCMP demic failed, discard frags */ - dp_rx_defrag_frames_free(frag_list_head); - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "dp_rx_defrag: CCMP demic failed"); @@ -1181,9 +1186,6 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid, } if (dp_rx_defrag_ccmp_decap(cur, hdr_space)) { - /* CCMP decap failed, discard frags */ - dp_rx_defrag_frames_free(frag_list_head); - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "dp_rx_defrag: CCMP decap failed"); @@ -1196,6 +1198,7 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid, /* If success, increment header to be stripped later */ hdr_space += dp_f_ccmp.ic_header; break; + case htt_sec_type_wep40: case htt_sec_type_wep104: case htt_sec_type_wep128: @@ -1203,9 +1206,6 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid, tmp_next = qdf_nbuf_next(cur); if (dp_rx_defrag_wep_decap(cur, hdr_space)) { - /* WEP decap failed, discard frags */ - dp_rx_defrag_frames_free(frag_list_head); - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "dp_rx_defrag: WEP decap failed"); @@ -1226,19 +1226,28 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid, } if (tkip_demic) { - msdu = frag_list_tail; /* Only last fragment has the MIC */ + msdu = frag_list_head; + if (soc->cdp_soc.ol_ops->rx_frag_tkip_demic) { + status = soc->cdp_soc.ol_ops->rx_frag_tkip_demic( + peer->ol_peer, msdu, hdr_space); + } else { + qdf_mem_copy(key, + &peer->security[index].michael_key[0], + IEEE80211_WEP_MICLEN); + status = dp_rx_defrag_tkip_demic(key, msdu, + RX_PKT_TLVS_LEN + + hdr_space); - qdf_mem_copy(key, - peer->security[index].michael_key, - sizeof(peer->security[index].michael_key)); - if (dp_rx_defrag_tkip_demic(key, msdu, hdr_space)) { - qdf_nbuf_free(msdu); - dp_rx_defrag_err(vdev->vdev_id, peer->mac_addr.raw, - tid, 0, QDF_STATUS_E_DEFRAG_ERROR, msdu, - NULL, 0); - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - "dp_rx_defrag: TKIP demic failed"); - return QDF_STATUS_E_DEFRAG_ERROR; + if (status) { + dp_rx_defrag_err(vdev, frag_list_head); + + QDF_TRACE(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_ERROR, + "%s: TKIP demic failed status %d\n", + __func__, status); + + return QDF_STATUS_E_DEFRAG_ERROR; + } } } @@ -1663,6 +1672,7 @@ QDF_STATUS dp_rx_defrag_add_last_frag(struct dp_soc *soc, struct dp_rx_tid *rx_tid = &peer->rx_tid[tid]; struct dp_rx_reorder_array_elem *rx_reorder_array_elem; uint8_t all_frag_present; + uint32_t msdu_len; QDF_STATUS status; rx_reorder_array_elem = peer->rx_tid[tid].array; @@ -1676,6 +1686,10 @@ QDF_STATUS dp_rx_defrag_add_last_frag(struct dp_soc *soc, goto fail; } + msdu_len = hal_rx_msdu_start_msdu_len_get(qdf_nbuf_data(nbuf)); + + qdf_nbuf_set_pktlen(nbuf, (msdu_len + RX_PKT_TLVS_LEN)); + status = dp_rx_defrag_fraglist_insert(peer, tid, &rx_reorder_array_elem->head, &rx_reorder_array_elem->tail, nbuf, diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index e36ad2eaf7ea..f31dcc10bbca 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -1421,6 +1421,9 @@ struct dp_peer { dp_ecm_policy wds_ecm; #endif bool delete_in_progress; + + /* Opaque handle to node */ + void *ol_peer; }; #ifdef CONFIG_WIN