Merge "qcacmn: Code movement to enable multipass support without WDS"

This commit is contained in:
Linux Build Service Account
2023-04-21 09:15:21 -07:00
committed by Gerrit - the friendly Code Review server
6 fájl változott, egészen pontosan 396 új sor hozzáadva és 388 régi sor törölve

Fájl megtekintése

@@ -6666,3 +6666,199 @@ void dp_pkt_get_timestamp(uint64_t *time)
}
#endif
#ifdef QCA_MULTIPASS_SUPPORT
void dp_tx_add_groupkey_metadata(struct dp_vdev *vdev,
struct dp_tx_msdu_info_s *msdu_info,
uint16_t group_key)
{
struct htt_tx_msdu_desc_ext2_t *meta_data =
(struct htt_tx_msdu_desc_ext2_t *)&msdu_info->meta_data[0];
qdf_mem_zero(meta_data, sizeof(struct htt_tx_msdu_desc_ext2_t));
/*
* When attempting to send a multicast packet with multi-passphrase,
* host shall add HTT EXT meta data "struct htt_tx_msdu_desc_ext2_t"
* ref htt.h indicating the group_id field in "key_flags" also having
* "valid_key_flags" as 1. Assign “key_flags = group_key_ix”.
*/
HTT_TX_MSDU_EXT2_DESC_FLAG_VALID_KEY_FLAGS_SET(msdu_info->meta_data[0],
1);
HTT_TX_MSDU_EXT2_DESC_KEY_FLAGS_SET(msdu_info->meta_data[2], group_key);
}
void dp_tx_remove_vlan_tag(struct dp_vdev *vdev, qdf_nbuf_t nbuf)
{
struct vlan_ethhdr veth_hdr;
struct vlan_ethhdr *veh = (struct vlan_ethhdr *)nbuf->data;
/*
* Extract VLAN header of 4 bytes:
* Frame Format : {dst_addr[6], src_addr[6], 802.1Q header[4],
* EtherType[2], Payload}
* Before Removal : xx xx xx xx xx xx xx xx xx xx xx xx 81 00 00 02
* 08 00 45 00 00...
* After Removal : xx xx xx xx xx xx xx xx xx xx xx xx 08 00 45 00
* 00...
*/
qdf_mem_copy(&veth_hdr, veh, sizeof(veth_hdr));
qdf_nbuf_pull_head(nbuf, ETHERTYPE_VLAN_LEN);
veh = (struct vlan_ethhdr *)nbuf->data;
qdf_mem_copy(veh, &veth_hdr, 2 * QDF_MAC_ADDR_SIZE);
}
#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) && \
defined(WLAN_MCAST_MLO)
/**
* dp_tx_need_mcast_reinject() - If frame needs to be processed in reinject path
* @vdev: DP vdev handle
*
* Return: true if reinject handling is required else false
*/
static inline bool
dp_tx_need_mcast_reinject(struct dp_vdev *vdev)
{
if (vdev->mlo_vdev && vdev->opmode == wlan_op_mode_ap)
return true;
return false;
}
#else
static inline bool
dp_tx_need_mcast_reinject(struct dp_vdev *vdev)
{
return false;
}
#endif
/**
* dp_tx_need_multipass_process() - If frame needs multipass phrase processing
* @soc: dp soc handle
* @vdev: DP vdev handle
* @buf: frame
* @vlan_id: vlan id of frame
*
* Return: whether peer is special or classic
*/
static
uint8_t dp_tx_need_multipass_process(struct dp_soc *soc, struct dp_vdev *vdev,
qdf_nbuf_t buf, uint16_t *vlan_id)
{
struct dp_txrx_peer *txrx_peer = NULL;
struct dp_peer *peer = NULL;
qdf_ether_header_t *eh = (qdf_ether_header_t *)qdf_nbuf_data(buf);
struct vlan_ethhdr *veh = NULL;
bool not_vlan = ((vdev->tx_encap_type == htt_cmn_pkt_type_raw) ||
(htons(eh->ether_type) != ETH_P_8021Q));
if (qdf_unlikely(not_vlan))
return DP_VLAN_UNTAGGED;
veh = (struct vlan_ethhdr *)eh;
*vlan_id = (ntohs(veh->h_vlan_TCI) & VLAN_VID_MASK);
if (qdf_unlikely(DP_FRAME_IS_MULTICAST((eh)->ether_dhost))) {
/* look for handling of multicast packets in reinject path */
if (dp_tx_need_mcast_reinject(vdev))
return DP_VLAN_UNTAGGED;
qdf_spin_lock_bh(&vdev->mpass_peer_mutex);
TAILQ_FOREACH(txrx_peer, &vdev->mpass_peer_list,
mpass_peer_list_elem) {
if (*vlan_id == txrx_peer->vlan_id) {
qdf_spin_unlock_bh(&vdev->mpass_peer_mutex);
return DP_VLAN_TAGGED_MULTICAST;
}
}
qdf_spin_unlock_bh(&vdev->mpass_peer_mutex);
return DP_VLAN_UNTAGGED;
}
peer = dp_peer_find_hash_find(soc, eh->ether_dhost, 0, DP_VDEV_ALL,
DP_MOD_ID_TX_MULTIPASS);
if (qdf_unlikely(!peer))
return DP_VLAN_UNTAGGED;
/*
* Do not drop the frame when vlan_id doesn't match.
* Send the frame as it is.
*/
if (*vlan_id == peer->txrx_peer->vlan_id) {
dp_peer_unref_delete(peer, DP_MOD_ID_TX_MULTIPASS);
return DP_VLAN_TAGGED_UNICAST;
}
dp_peer_unref_delete(peer, DP_MOD_ID_TX_MULTIPASS);
return DP_VLAN_UNTAGGED;
}
bool dp_tx_multipass_process(struct dp_soc *soc, struct dp_vdev *vdev,
qdf_nbuf_t nbuf,
struct dp_tx_msdu_info_s *msdu_info)
{
uint16_t vlan_id = 0;
uint16_t group_key = 0;
uint8_t is_spcl_peer = DP_VLAN_UNTAGGED;
qdf_nbuf_t nbuf_copy = NULL;
if (HTT_TX_MSDU_EXT2_DESC_FLAG_VALID_KEY_FLAGS_GET(msdu_info->meta_data[0]))
return true;
is_spcl_peer = dp_tx_need_multipass_process(soc, vdev, nbuf, &vlan_id);
if ((is_spcl_peer != DP_VLAN_TAGGED_MULTICAST) &&
(is_spcl_peer != DP_VLAN_TAGGED_UNICAST))
return true;
if (is_spcl_peer == DP_VLAN_TAGGED_UNICAST) {
dp_tx_remove_vlan_tag(vdev, nbuf);
return true;
}
/* AP can have classic clients, special clients &
* classic repeaters.
* 1. Classic clients & special client:
* Remove vlan header, find corresponding group key
* index, fill in metaheader and enqueue multicast
* frame to TCL.
* 2. Classic repeater:
* Pass through to classic repeater with vlan tag
* intact without any group key index. Hardware
* will know which key to use to send frame to
* repeater.
*/
nbuf_copy = qdf_nbuf_copy(nbuf);
/*
* Send multicast frame to special peers even
* if pass through to classic repeater fails.
*/
if (nbuf_copy) {
struct dp_tx_msdu_info_s msdu_info_copy;
qdf_mem_zero(&msdu_info_copy, sizeof(msdu_info_copy));
msdu_info_copy.tid = HTT_TX_EXT_TID_INVALID;
HTT_TX_MSDU_EXT2_DESC_FLAG_VALID_KEY_FLAGS_SET(msdu_info_copy.meta_data[0], 1);
nbuf_copy = dp_tx_send_msdu_single(vdev, nbuf_copy,
&msdu_info_copy,
HTT_INVALID_PEER, NULL);
if (nbuf_copy) {
qdf_nbuf_free(nbuf_copy);
qdf_err("nbuf_copy send failed");
}
}
group_key = vdev->iv_vlan_map[vlan_id];
/*
* If group key is not installed, drop the frame.
*/
if (!group_key)
return false;
dp_tx_remove_vlan_tag(vdev, nbuf);
dp_tx_add_groupkey_metadata(vdev, msdu_info, group_key);
msdu_info->exception_fw = 1;
return true;
}
#endif /* QCA_MULTIPASS_SUPPORT */