PNDIS_PACKET RTMP_AllocateRxPacketBuffer( IN PRTMP_ADAPTER pAd, IN ULONG Length, IN BOOLEAN Cached, OUT PVOID *VirtualAddress, OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) { PNDIS_PACKET pkt; pkt = RTPKT_TO_OSPKT(DEV_ALLOC_SKB(Length)); if (pkt == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("can't allocate rx %ld size packet\n",Length)); } if (pkt) { RTMP_SET_PACKET_SOURCE(pkt, PKTSRC_NDIS); *VirtualAddress = (PVOID) RTPKT_TO_OSPKT(pkt)->data; *PhysicalAddress = PCI_MAP_SINGLE(pAd, *VirtualAddress, Length, -1, PCI_DMA_FROMDEVICE); } else { *VirtualAddress = (PVOID) NULL; *PhysicalAddress = (NDIS_PHYSICAL_ADDRESS) NULL; } return (PNDIS_PACKET) pkt; }
void wlan_802_11_to_802_3_packet( IN PRTMP_ADAPTER pAd, IN RX_BLK *pRxBlk, IN PUCHAR pHeader802_3, IN UCHAR FromWhichBSSID) { struct sk_buff *pOSPkt; ASSERT(pRxBlk->pRxPacket); ASSERT(pHeader802_3); pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); pOSPkt->data = pRxBlk->pData; pOSPkt->len = pRxBlk->DataSize; pOSPkt->tail = pOSPkt->data + pOSPkt->len; // // copy 802.3 header // // #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3); #endif // CONFIG_STA_SUPPORT // }
void announce_802_3_packet( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket) { struct sk_buff *pRxPkt; ASSERT(pPacket); pRxPkt = RTPKT_TO_OSPKT(pPacket); #ifdef CONFIG_STA_SUPPORT #endif // CONFIG_STA_SUPPORT // /* Push up the protocol stack */ #ifdef IKANOS_VX_1X0 IKANOS_DataFrameRx(pAd, pRxPkt->dev, pRxPkt, pRxPkt->len); #else pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); //#ifdef CONFIG_5VT_ENHANCE // *(int*)(pRxPkt->cb) = BRIDGE_TAG; //#endif netif_rx(pRxPkt); #endif // IKANOS_VX_1X0 // }
PNDIS_PACKET ClonePacket( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket, IN PUCHAR pData, IN ULONG DataSize) { struct sk_buff *pRxPkt; struct sk_buff *pClonedPkt; ASSERT(pPacket); pRxPkt = RTPKT_TO_OSPKT(pPacket); // clone the packet pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG); if (pClonedPkt) { // set the correct dataptr and data len pClonedPkt->dev = pRxPkt->dev; pClonedPkt->data = pData; pClonedPkt->head = pClonedPkt->data; pClonedPkt->len = DataSize; skb_set_tail_pointer(pClonedPkt, pClonedPkt->len); ASSERT(DataSize < 1530); } return pClonedPkt; }
PNDIS_PACKET DuplicatePacket( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket, IN UCHAR FromWhichBSSID) { struct sk_buff *skb; PNDIS_PACKET pRetPacket = NULL; USHORT DataSize; UCHAR *pData; DataSize = (USHORT) GET_OS_PKT_LEN(pPacket); pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket); skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG); if (skb) { skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); pRetPacket = OSPKT_TO_RTPKT(skb); } #if 0 if ((skb = __dev_alloc_skb(DataSize + 2+32, MEM_ALLOC_FLAG)) != NULL) { skb_reserve(skb, 2+32); NdisMoveMemory(skb->tail, pData, DataSize); skb_put(skb, DataSize); skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); pRetPacket = OSPKT_TO_RTPKT(skb); } #endif return pRetPacket; }
void convert_reordering_packet_to_preAMSDU_or_802_3_packet(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) { void *pRxPkt; u8 Header802_3[LENGTH_802_3]; /* 1. get 802.3 Header */ /* 2. remove LLC */ /* a. pointer pRxBlk->pData to payload */ /* b. modify pRxBlk->DataSize */ RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); ASSERT(pRxBlk->pRxPacket); pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); SET_OS_PKT_NETDEV(pRxPkt, get_netdev_from_bssid(pAd, FromWhichBSSID)); SET_OS_PKT_DATAPTR(pRxPkt, pRxBlk->pData); SET_OS_PKT_LEN(pRxPkt, pRxBlk->DataSize); SET_OS_PKT_DATATAIL(pRxPkt, pRxBlk->pData, pRxBlk->DataSize); /* */ /* copy 802.3 header, if necessary */ /* */ if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) { { #ifdef LINUX NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3); #endif } } }
void wlan_802_11_to_802_3_packet( IN PRTMP_ADAPTER pAd, IN RX_BLK *pRxBlk, IN PUCHAR pHeader802_3, IN UCHAR FromWhichBSSID) { struct sk_buff *pOSPkt; ASSERT(pRxBlk->pRxPacket); ASSERT(pHeader802_3); pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); pOSPkt->data = pRxBlk->pData; pOSPkt->head = pOSPkt->data; pOSPkt->len = pRxBlk->DataSize; skb_set_tail_pointer(pOSPkt, pOSPkt->len); // // copy 802.3 header // // NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3); }
/* ======================================================================== Routine Description: Send a packet to WLAN. Arguments: pPktSrc points to our adapter pDev which WLAN network interface Return Value: 0: transmit successfully otherwise: transmit fail Note: ======================================================================== */ INT MBSS_VirtualIF_PacketSend( IN PNDIS_PACKET pPktSrc, IN PNET_DEV pDev) { RTMP_ADAPTER *pAd; MULTISSID_STRUCT *pMbss; PNDIS_PACKET pPkt = (PNDIS_PACKET)pPktSrc; INT IdBss; pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); ASSERT(pAd); #ifdef RALINK_ATE if (ATE_ON(pAd)) { RELEASE_NDIS_PACKET(pAd, pPkt, NDIS_STATUS_FAILURE); return 0; } #endif // RALINK_ATE // if ((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) { /* wlan is scanning/disabled/reset */ RELEASE_NDIS_PACKET(pAd, pPkt, NDIS_STATUS_FAILURE); return 0; } if(!(RTMP_OS_NETDEV_STATE_RUNNING(pDev))) { /* the interface is down */ RELEASE_NDIS_PACKET(pAd, pPkt, NDIS_STATUS_FAILURE); return 0; } /* 0 is main BSS, dont handle it here */ /* FIRST_MBSSID = 1 */ pMbss = pAd->ApCfg.MBSSID; for(IdBss=FIRST_MBSSID; IdBss<pAd->ApCfg.BssidNum; IdBss++) { /* find the device in our MBSS list */ if (pMbss[IdBss].MSSIDDev == pDev) { NdisZeroMemory((PUCHAR)&(RTPKT_TO_OSPKT(pPktSrc))->cb[CB_OFF], 15); RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPktSrc, IdBss); // SET_OS_PKT_NETDEV(pPktSrc, pDev); /* MBSS used original interface for TX */ /* transmit the packet */ return rt28xx_packet_xmit(pPktSrc); } } /* can not find the BSS so discard the packet */ RELEASE_NDIS_PACKET(pAd, pPkt, NDIS_STATUS_FAILURE); return 0; } /* End of MBSS_VirtualIF_PacketSend */
/* ======================================================================== Routine Description: Forward the received packet. Arguments: pPacket - the received packet Return Value: None Note: ======================================================================== */ UINT32 BG_FTPH_PacketFromApHandle( IN PNDIS_PACKET pPacket) { struct net_device *pNetDev; struct sk_buff *pRxPkt; struct net_bridge_fdb_entry *pSrcFdbEntry, *pDstFdbEntry; /* init */ pRxPkt = RTPKT_TO_OSPKT(pPacket); pNetDev = pRxPkt->dev; /* if pNetDev is promisc mode ??? */ DBGPRINT(RT_DEBUG_INFO, ("ft bg> BG_FTPH_PacketFromApHandle\n")); if (pNetDev != NULL) { if (pNetDev->br_port != NULL) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) pDstFdbEntry = br_fdb_get_hook(pNetDev->br_port->br, pRxPkt->data); pSrcFdbEntry = br_fdb_get_hook(pNetDev->br_port->br, pRxPkt->data + 6); #else /* br_fdb_get is not exported symbol, need exported in net/bridge/br.c */ pDstFdbEntry = br_fdb_get(pNetDev->br_port->br, pRxPkt->data); pSrcFdbEntry = br_fdb_get(pNetDev->br_port->br, pRxPkt->data + 6); #endif /* check destination address in bridge forwarding table */ if ((pSrcFdbEntry == NULL) || (pDstFdbEntry == NULL) || (pDstFdbEntry->is_local) || (pDstFdbEntry->dst == NULL) || (pDstFdbEntry->dst->dev == NULL) || (pDstFdbEntry->dst->dev == pNetDev) || (pNetDev->br_port->state != BR_STATE_FORWARDING) || ((pSrcFdbEntry->dst != NULL) && (pSrcFdbEntry->dst->dev != NULL) && (pSrcFdbEntry->dst->dev != pNetDev))) { goto LabelPassToUpperLayer; } /* End of if */ if ((!pDstFdbEntry->is_local) && (pDstFdbEntry->dst != NULL) && (pDstFdbEntry->dst->dev != NULL)) { pRxPkt->dev = pDstFdbEntry->dst->dev; pDstFdbEntry->dst->dev->hard_start_xmit(pRxPkt, pDstFdbEntry->dst->dev); return 0; } /* End of if */ } /* End of if */ } /* End of if */ LabelPassToUpperLayer: DBGPRINT(RT_DEBUG_TRACE, ("ft bg> Pass packet to bridge module.\n")); return 1; } /* End of BG_FTPH_PacketFromApHandle */
/* ======================================================================== Routine Description: For each out-going packet, check the upper layer protocol type if need to handled by our APCLI convert engine. If yes, call corresponding handler to handle it. Arguments: pAd =>Pointer to our adapter pPkt =>pointer to the 802.11 header of outgoing packet ifIdx =>Interface Index want to dispatch to. Return Value: Success => TRUE Mapped mac address if found, else return specific default mac address depends on the upper layer protocol type. Error => FALSE. Note: 1.the pPktHdr must be a 802.3 packet. 2.Maybe we need a TxD arguments? 3.We check every packet here including group mac address becasue we need to handle DHCP packet. ======================================================================== */ PUCHAR MATEngineTxHandle( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPkt, IN UINT ifIdx, IN UCHAR OpMode) { PUCHAR pLayerHdr = NULL, pPktHdr = NULL, pMacAddr = NULL; UINT16 protoType, protoType_ori; int i; struct _MATProtoOps *pHandle = NULL; PUCHAR retSkb = NULL; BOOLEAN bVLANPkt = FALSE; if(pAd->MatCfg.status != MAT_ENGINE_STAT_INITED) return NULL; pPktHdr = GET_OS_PKT_DATAPTR(pPkt); if (!pPktHdr) return NULL; protoType_ori = get_unaligned((PUINT16)(pPktHdr + 12)); /* Get the upper layer protocol type of this 802.3 pkt. */ protoType = OS_NTOHS(protoType_ori); /* handle 802.1q enabled packet. Skip the VLAN tag field to get the protocol type. */ if (protoType == 0x8100) { protoType_ori = get_unaligned((PUINT16)(pPktHdr + 12 + 4)); protoType = OS_NTOHS(protoType_ori); bVLANPkt = TRUE; } /* For differnet protocol, dispatch to specific handler */ for (i=0; i < MAX_MAT_SUPPORT_PROTO_NUM; i++) { if (protoType == MATProtoTb[i].protocol) { pHandle = MATProtoTb[i].pHandle; /* the pHandle must not be null! */ pLayerHdr = bVLANPkt ? (pPktHdr + MAT_VLAN_ETH_HDR_LEN) : (pPktHdr + MAT_ETHER_HDR_LEN); #ifdef CONFIG_AP_SUPPORT #ifdef APCLI_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) pMacAddr = &pAd->ApCfg.ApCliTab[ifIdx].CurrentAddress[0]; #endif /* APCLI_SUPPORT */ #endif /* CONFIG_AP_SUPPORT */ if (pHandle->tx!=NULL) retSkb = pHandle->tx((PVOID)&pAd->MatCfg, RTPKT_TO_OSPKT(pPkt), pLayerHdr, pMacAddr); return retSkb; } } return retSkb; }
VOID build_tx_packet( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket, IN PUCHAR pFrame, IN ULONG FrameLen) { struct sk_buff *pTxPkt; ASSERT(pPacket); pTxPkt = RTPKT_TO_OSPKT(pPacket); NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen); }
// // change OS packet DataPtr and DataLen // void update_os_packet_info( IN PRTMP_ADAPTER pAd, IN RX_BLK *pRxBlk, IN UCHAR FromWhichBSSID) { struct sk_buff *pOSPkt; ASSERT(pRxBlk->pRxPacket); pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); pOSPkt->data = pRxBlk->pData; pOSPkt->len = pRxBlk->DataSize; pOSPkt->tail = pOSPkt->data + pOSPkt->len; }
PNDIS_PACKET duplicate_pkt_with_TKIP_MIC( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket) { struct sk_buff *skb, *newskb; skb = RTPKT_TO_OSPKT(pPacket); if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE) { // alloc a new skb and copy the packet newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC); dev_kfree_skb_any(skb); if (newskb == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n")); return NULL; } skb = newskb; } return OSPKT_TO_RTPKT(skb); #if 0 if ((data = skb_put(skb, TKIP_TX_MIC_SIZE)) != NULL) { // If we can extend it, well, copy it first. NdisMoveMemory(data, pAd->PrivateInfo.Tx.MIC, TKIP_TX_MIC_SIZE); } else { // Otherwise, copy the packet. newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC); dev_kfree_skb_any(skb); if (newskb == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC to packet failed!, dropping packet\n")); return NULL; } skb = newskb; NdisMoveMemory(skb->tail, pAd->PrivateInfo.Tx.MIC, TKIP_TX_MIC_SIZE); skb_put(skb, TKIP_TX_MIC_SIZE); } return OSPKT_TO_RTPKT(skb); #endif }
void announce_802_3_packet( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket) { struct sk_buff *pRxPkt; ASSERT(pPacket); pRxPkt = RTPKT_TO_OSPKT(pPacket); /* Push up the protocol stack */ pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); netif_rx(pRxPkt); }
/* ======================================================================== Routine Description: Depends on the Received packet, check the upper layer protocol type and search for specific mapping table to find out the real destination MAC address. Arguments: pAd =>Pointer to our adapter pPkt =>pointer to the 802.11 header of receviced packet infIdx =>Interface Index want to dispatch to. Return Value: Success => Mapped mac address if found, else return specific default mac address depends on the upper layer protocol type. Error => NULL Note: ======================================================================== */ PUCHAR MATEngineRxHandle( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPkt, IN UINT infIdx) { PUCHAR pMacAddr = NULL; PUCHAR pLayerHdr = NULL, pPktHdr = NULL; UINT16 protoType; int i =0; struct _MATProtoOps *pHandle = NULL; if(pAd->MatCfg.status != MAT_ENGINE_STAT_INITED) return NULL; pPktHdr = GET_OS_PKT_DATAPTR(pPkt); if (!pPktHdr) return NULL; /* If it's a multicast/broadcast packet, we do nothing. */ if (IS_GROUP_MAC(pPktHdr)) return NULL; /* Get the upper layer protocol type of this 802.3 pkt and dispatch to specific handler */ protoType = OS_NTOHS(get_unaligned((PUINT16)(pPktHdr + 12))); for (i=0; i<MAX_MAT_SUPPORT_PROTO_NUM; i++) { if (protoType == MATProtoTb[i].protocol) { pHandle = MATProtoTb[i].pHandle; /* the pHandle must not be null! */ pLayerHdr = (pPktHdr + MAT_ETHER_HDR_LEN); /* RTMP_SEM_LOCK(&MATDBLock); */ if(pHandle->rx!=NULL) pMacAddr = pHandle->rx((PVOID)&pAd->MatCfg, RTPKT_TO_OSPKT(pPkt), pLayerHdr, NULL); /* RTMP_SEM_UNLOCK(&MATDBLock); */ break; } } if (pMacAddr) NdisMoveMemory(pPktHdr, pMacAddr, MAC_ADDR_LEN); return NULL; }
static INT CFG80211_PacketSend(PNDIS_PACKET pPktSrc, PNET_DEV pDev, RTMP_NET_PACKET_TRANSMIT Func) { PRTMP_ADAPTER pAd; pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); ASSERT(pAd); /* To Indicate from Which VIF */ switch (pDev->ieee80211_ptr->iftype) { case RT_CMD_80211_IFTYPE_AP: //minIdx = MIN_NET_DEVICE_FOR_CFG80211_VIF_AP; RTMP_SET_PACKET_OPMODE(pPktSrc, OPMODE_AP); break; case RT_CMD_80211_IFTYPE_P2P_GO:; //minIdx = MIN_NET_DEVICE_FOR_CFG80211_VIF_P2P_GO; if(!OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED)) { DBGPRINT(RT_DEBUG_TRACE, ("Drop the Packet due P2P GO not in ready state\n")); RELEASE_NDIS_PACKET(pAd, pPktSrc, NDIS_STATUS_FAILURE); return 0; } RTMP_SET_PACKET_OPMODE(pPktSrc, OPMODE_AP); break; case RT_CMD_80211_IFTYPE_P2P_CLIENT: //minIdx = MIN_NET_DEVICE_FOR_CFG80211_VIF_P2P_CLI; RTMP_SET_PACKET_OPMODE(pPktSrc, OPMODE_AP); break; case RT_CMD_80211_IFTYPE_STATION: default: DBGPRINT(RT_DEBUG_TRACE, ("Unknown CFG80211 I/F Type(%d)\n", pDev->ieee80211_ptr->iftype)); RELEASE_NDIS_PACKET(pAd, pPktSrc, NDIS_STATUS_FAILURE); return 0; } DBGPRINT(RT_DEBUG_INFO, ("CFG80211 Packet Type [%s](%d)\n", pDev->name, pDev->ieee80211_ptr->iftype)); RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPktSrc, MAIN_MBSSID); return Func(RTPKT_TO_OSPKT(pPktSrc)); }
static INT CFG80211_PacketSend(PNDIS_PACKET pPktSrc, PNET_DEV pDev, RTMP_NET_PACKET_TRANSMIT Func) { PRTMP_ADAPTER pAd; pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); ASSERT(pAd); /* To Indicate from Which VIF */ switch (pDev->ieee80211_ptr->iftype) { case RT_CMD_80211_IFTYPE_AP: RTMP_SET_PACKET_OPMODE(pPktSrc, OPMODE_AP); break; case RT_CMD_80211_IFTYPE_P2P_GO:; if(!OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED)) { MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("Drop the Packet due P2P GO not in ready state\n")); RELEASE_NDIS_PACKET(pAd, pPktSrc, NDIS_STATUS_FAILURE); return 0; } RTMP_SET_PACKET_OPMODE(pPktSrc, OPMODE_AP); break; case RT_CMD_80211_IFTYPE_P2P_CLIENT: case RT_CMD_80211_IFTYPE_STATION: RTMP_SET_PACKET_OPMODE(pPktSrc, OPMODE_AP); //printk("%s: tx ==> %d\n", __FUNCTION__, RTMP_GET_PACKET_OPMODE(pPktSrc)); break; default: MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("Unknown CFG80211 I/F Type(%d)\n", pDev->ieee80211_ptr->iftype)); RELEASE_NDIS_PACKET(pAd, pPktSrc, NDIS_STATUS_FAILURE); return 0; } MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_INFO, ("CFG80211 Packet Type [%s](%d)\n", pDev->name, pDev->ieee80211_ptr->iftype)); return Func(RTPKT_TO_OSPKT(pPktSrc)); }
PNDIS_PACKET duplicate_pkt_with_TKIP_MIC( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket) { struct sk_buff *skb, *newskb; skb = RTPKT_TO_OSPKT(pPacket); if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE) { // alloc a new skb and copy the packet newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC); dev_kfree_skb_any(skb); if (newskb == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n")); return NULL; } skb = newskb; } return OSPKT_TO_RTPKT(skb); }
PNDIS_PACKET DuplicatePacket( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket, IN UCHAR FromWhichBSSID) { struct sk_buff *skb; PNDIS_PACKET pRetPacket = NULL; USHORT DataSize; UCHAR *pData; DataSize = (USHORT) GET_OS_PKT_LEN(pPacket); pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket); skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG); if (skb) { skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); pRetPacket = OSPKT_TO_RTPKT(skb); } return pRetPacket; }
/* ======================================================================== Routine Description: Send a packet to WLAN. Arguments: skb_p points to our adapter dev_p which WLAN network interface Return Value: 0: transmit successfully otherwise: transmit fail Note: ======================================================================== */ INT ApCli_VirtualIF_PacketSend( IN PNDIS_PACKET skb_p, IN PNET_DEV dev_p) { RTMP_ADAPTER *ad_p; PAPCLI_STRUCT pApCli; INT apcliIndex; ad_p = RTMP_OS_NETDEV_GET_PRIV(dev_p); ASSERT(ad_p); #ifdef RALINK_ATE if (ATE_ON(ad_p)) { RELEASE_NDIS_PACKET(ad_p, skb_p, NDIS_STATUS_FAILURE); return 0; } #endif // RALINK_ATE // if ((RTMP_TEST_FLAG(ad_p, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || (RTMP_TEST_FLAG(ad_p, fRTMP_ADAPTER_RADIO_OFF)) || (RTMP_TEST_FLAG(ad_p, fRTMP_ADAPTER_RESET_IN_PROGRESS))) { /* wlan is scanning/disabled/reset */ RELEASE_NDIS_PACKET(ad_p, skb_p, NDIS_STATUS_FAILURE); return 0; } if (!(RTMP_OS_NETDEV_STATE_RUNNING(dev_p))) { /* the interface is down */ RELEASE_NDIS_PACKET(ad_p, skb_p, NDIS_STATUS_FAILURE); return 0; } pApCli = (PAPCLI_STRUCT)&ad_p->ApCfg.ApCliTab; for(apcliIndex = 0; apcliIndex < MAX_APCLI_NUM; apcliIndex++) { if (pApCli[apcliIndex].Valid != TRUE) continue; /* find the device in our ApCli list */ if (pApCli[apcliIndex].dev == dev_p) { /* ya! find it */ ad_p->RalinkCounters.PendingNdisPacketCount ++; RTMP_SET_PACKET_MOREDATA(skb_p, FALSE); RTMP_SET_PACKET_NET_DEVICE_APCLI(skb_p, apcliIndex); SET_OS_PKT_NETDEV(skb_p, ad_p->net_dev); /* transmit the packet */ return rt28xx_packet_xmit(RTPKT_TO_OSPKT(skb_p)); } } RELEASE_NDIS_PACKET(ad_p, skb_p, NDIS_STATUS_FAILURE); return 0; } /* End of ApCli_VirtualIF_PacketSend */
void send_radiotap_monitor_packets( PNET_DEV pNetDev, PNDIS_PACKET pRxPacket, VOID *dot11_hdr, UCHAR *pData, USHORT DataSize, UCHAR L2PAD, UCHAR PHYMODE, UCHAR BW, UCHAR ShortGI, UCHAR MCS, UCHAR LDPC, UCHAR LDPC_EX_SYM, UCHAR AMPDU, UCHAR STBC, UCHAR RSSI1, UCHAR *pDevName, UCHAR Channel, UCHAR CentralChannel, UCHAR sideband_index, UINT32 MaxRssi) { struct sk_buff *pOSPkt; int rate_index = 0; USHORT header_len = 0; UCHAR temp_header[40] = {0}; struct mtk_radiotap_header *mtk_rt_hdr; UINT32 varlen = 0, padding_len = 0; UINT64 tmp64; UINT32 tmp32; UINT16 tmp16; UCHAR *pos; DOT_11_HDR *pHeader = (DOT_11_HDR *)dot11_hdr; MEM_DBG_PKT_FREE_INC(pRxPacket); pOSPkt = RTPKT_TO_OSPKT(pRxPacket); pOSPkt->dev = pNetDev; if (pHeader->FC.Type == 0x2 /* FC_TYPE_DATA */) { DataSize -= LENGTH_802_11; if ((pHeader->FC.ToDs == 1) && (pHeader->FC.FrDs == 1)) header_len = LENGTH_802_11_WITH_ADDR4; else header_len = LENGTH_802_11; /* QOS */ if (pHeader->FC.SubType & 0x08) { header_len += 2; /* Data skip QOS contorl field */ DataSize -= 2; } /* Order bit: A-Ralink or HTC+ */ if (pHeader->FC.Order) { header_len += 4; /* Data skip HTC contorl field */ DataSize -= 4; } /* Copy Header */ if (header_len <= 40) NdisMoveMemory(temp_header, pData, header_len); /* skip HW padding */ if (L2PAD) pData += (header_len + 2); else pData += header_len; } if (DataSize < pOSPkt->len) { skb_trim(pOSPkt, DataSize); } else { skb_put(pOSPkt, (DataSize - pOSPkt->len)); } if ((pData - pOSPkt->data) > 0) { skb_put(pOSPkt, (pData - pOSPkt->data)); skb_pull(pOSPkt, (pData - pOSPkt->data)); } if (skb_headroom(pOSPkt) < (sizeof(*mtk_rt_hdr) + header_len)) { if (pskb_expand_head(pOSPkt, (sizeof(*mtk_rt_hdr) + header_len), 0, GFP_ATOMIC)) { DBGPRINT(RT_DEBUG_ERROR, ("%s : Reallocate header size of sk_buff fail!\n", __FUNCTION__)); goto err_free_sk_buff; } } if (header_len > 0) NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len); /* tsf */ padding_len = ((varlen % 8) == 0) ? 0 : (8 - (varlen % 8)); varlen += (8 + padding_len); /* flags */ varlen += 1; /* rate */ if (PHYMODE < MODE_HTMIX) varlen += 1; /* channel frequency */ padding_len = ((varlen % 2) == 0) ? 0 : (2 - (varlen % 2)); varlen += (2 + padding_len); /* channel flags */ varlen += 2; /* MCS */ if ((PHYMODE == MODE_HTMIX) || (PHYMODE == MODE_HTGREENFIELD)) { /* known */ varlen += 1; /* flags */ varlen += 1; /* index */ varlen += 1; } /* A-MPDU */ if (AMPDU) { /* reference number */ padding_len = ((varlen % 4) == 0) ? 0 : (4 - (varlen % 4)); varlen += (4 + padding_len); /* flags */ varlen += 2; /* delimiter crc value */ varlen += 1; /* reserved */ varlen += 1; } /* VHT */ if (PHYMODE == MODE_VHT) { /* known */ padding_len = ((varlen % 2) == 0) ? 0 : (2 - (varlen % 2)); varlen += (2 + padding_len); /* flags */ varlen += 1; /* bandwidth */ varlen += 1; /* mcs_nss */ varlen += 4; /* coding */ varlen += 1; /* group_id */ varlen += 1; /* partial_aid */ varlen += 2; } mtk_rt_hdr = (struct mtk_radiotap_header *)skb_push(pOSPkt, sizeof(*mtk_rt_hdr) + varlen); NdisZeroMemory(mtk_rt_hdr, sizeof(*mtk_rt_hdr) + varlen); mtk_rt_hdr->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; mtk_rt_hdr->rt_hdr.it_pad = 0; mtk_rt_hdr->rt_hdr.it_len = cpu2le16(sizeof(*mtk_rt_hdr) + varlen); mtk_rt_hdr->rt_hdr.it_present = cpu2le32( (1 << IEEE80211_RADIOTAP_TSFT) | (1 << IEEE80211_RADIOTAP_FLAGS)); if (PHYMODE < MODE_HTMIX) { mtk_rt_hdr->rt_hdr.it_present |= cpu2le32(1 << IEEE80211_RADIOTAP_RATE); } mtk_rt_hdr->rt_hdr.it_present |= cpu2le32(1 << IEEE80211_RADIOTAP_CHANNEL); if ((PHYMODE == MODE_HTMIX) || (PHYMODE == MODE_HTGREENFIELD)) { mtk_rt_hdr->rt_hdr.it_present |= cpu2le32(1 << IEEE80211_RADIOTAP_MCS); } if (AMPDU) { mtk_rt_hdr->rt_hdr.it_present |= cpu2le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS); } if (PHYMODE == MODE_VHT) mtk_rt_hdr->rt_hdr.it_present |= cpu2le32(1 << IEEE80211_RADIOTAP_VHT); varlen = 0; pos = mtk_rt_hdr->variable; padding_len = ((varlen % 8) == 0) ? 0 : (8 - (varlen % 8)); pos += padding_len; varlen += padding_len; /* tsf */ tmp64 = 0; NdisMoveMemory(pos, &tmp64, 8); pos += 8; varlen += 8; /* flags */ *pos = 0; pos++; varlen++; /* rate */ if (PHYMODE == MODE_OFDM) { rate_index = (UCHAR)(MCS) + 4; *pos = ralinkrate[rate_index]; pos++; varlen++; } else if (PHYMODE == MODE_CCK) { rate_index = (UCHAR)(MCS); *pos = ralinkrate[rate_index]; pos++; varlen++; } /* channel frequency */ padding_len = ((varlen % 2) == 0) ? 0 : (2 - (varlen % 2)); pos += padding_len; varlen += padding_len; #define ieee80211chan2mhz(x) \ (((x) <= 14) ? \ (((x) == 14) ? 2484 : ((x) * 5) + 2407) : \ ((x) + 1000) * 5) tmp16 = cpu2le16(ieee80211chan2mhz(Channel)); NdisMoveMemory(pos, &tmp16, 2); pos += 2; varlen += 2; if (Channel > 14) { tmp16 = cpu2le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ)); } else { if (PHYMODE == MODE_CCK) { tmp16 = cpu2le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ); } else { tmp16 = cpu2le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ); } } NdisMoveMemory(pos, &tmp16, 2); pos += 2; varlen += 2; /* HT MCS */ if ((PHYMODE == MODE_HTMIX) || (PHYMODE == MODE_HTGREENFIELD)) { *pos = (IEEE80211_RADIOTAP_MCS_HAVE_BW | IEEE80211_RADIOTAP_MCS_HAVE_MCS | IEEE80211_RADIOTAP_MCS_HAVE_GI | IEEE80211_RADIOTAP_MCS_HAVE_FMT | IEEE80211_RADIOTAP_MCS_HAVE_FEC); pos++; varlen++; /* BW */ if (BW == 0) { *pos = HT_BW(IEEE80211_RADIOTAP_MCS_BW_20); } else { *pos = HT_BW(IEEE80211_RADIOTAP_MCS_BW_40); } /* HT GI */ *pos |= HT_GI(ShortGI); /* HT format */ if (PHYMODE == MODE_HTMIX) *pos |= HT_FORMAT(0); else if (PHYMODE == MODE_HTGREENFIELD) *pos |= HT_FORMAT(1); /* HT FEC type */ *pos |= HT_FEC_TYPE(LDPC); pos++; varlen++; /* HT mcs index */ *pos = MCS; pos++; varlen++; } if (AMPDU) { /* reference number */ padding_len = ((varlen % 4) == 0) ? 0 : (4 - (varlen % 4)); varlen += padding_len; pos += padding_len; tmp32 = 0; NdisMoveMemory(pos, &tmp32, 4); pos += 4; varlen += 2; /* flags */ tmp16 = 0; NdisMoveMemory(pos, &tmp16, 2); pos += 2; varlen += 2; /* delimiter CRC value */ *pos = 0; pos++; varlen++; /* reserved */ *pos = 0; pos++; varlen++; } #ifdef DOT11_VHT_AC /* VHT */ if (PHYMODE == MODE_VHT) { /* known */ padding_len = ((varlen % 2) == 0) ? 0 : (2 - (varlen % 2)); varlen += padding_len; pos += padding_len; tmp16 = cpu2le16(IEEE80211_RADIOTAP_VHT_KNOWN_STBC | IEEE80211_RADIOTAP_VHT_KNOWN_GI | IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM | IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH); NdisMoveMemory(pos, &tmp16, 2); pos += 2; varlen += 2; /* flags */ *pos = (STBC?IEEE80211_RADIOTAP_VHT_FLAG_STBC:0); *pos |= (ShortGI?IEEE80211_RADIOTAP_VHT_FLAG_SGI:0); *pos |= (LDPC_EX_SYM?IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM:0); pos++; varlen++; /* bandwidth */ if (BW == 0) { *pos = 0; } else if (BW == 1) { *pos = 1; } else if (BW == 2) { *pos = 4; #if 0 if (sideband_index == 0) *pos = 7; /* 20LL */ else if (sideband_index == 1) *pos = 8; /* 20LU */ else if (sideband_index == 2) *pos = 9; /* 20UL */ else if (sideband_index == 3) *pos = 10; /* 20UU */ #endif } else { DBGPRINT(RT_DEBUG_ERROR, ("%s:unknow bw(%d)\n", __FUNCTION__, BW)); } /* mcs_nss */ pos++; varlen++; /* vht_mcs_nss[0] */ *pos = (GET_VHT_NSS(MCS) & 0x0f); *pos |= ((GET_VHT_MCS(MCS) & 0x0f) << 4); pos++; varlen++; /* vht_mcs_nss[1] */ *pos = 0; pos++; varlen++; /* vht_mcs_nss[2] */ *pos = 0; pos++; varlen++; /* vht_mcs_nss[3] */ *pos = 0; pos++; varlen++; /* coding */ if (LDPC) *pos = 1; else *pos = 0; pos++; varlen++; /* group_id */ *pos = 0; pos++; varlen++; /* partial aid */ tmp16 = 0; NdisMoveMemory(pos, &tmp16, 2); pos += 2; varlen += 2; } #endif /* DOT11_VHT_AC */ pOSPkt->dev = pOSPkt->dev; skb_reset_mac_header(pOSPkt); pOSPkt->pkt_type = PACKET_OTHERHOST; pOSPkt->protocol = __constant_htons(ETH_P_80211_RAW); pOSPkt->ip_summed = CHECKSUM_NONE; netif_rx_ni(pOSPkt); return; err_free_sk_buff: RELEASE_NDIS_PACKET(NULL, pRxPacket, NDIS_STATUS_FAILURE); return; }
/* ======================================================================== Description: This routine frees a miniport internally allocated NDIS_PACKET and its corresponding NDIS_BUFFER and allocated memory. ======================================================================== */ VOID RTMPFreeNdisPacket( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket) { dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket)); }
void announce_802_3_packet( IN VOID *pAdSrc, IN PNDIS_PACKET pPacket, IN UCHAR OpMode) { RTMP_ADAPTER *pAd; PNDIS_PACKET pRxPkt = pPacket; pAd = (RTMP_ADAPTER *)pAdSrc; ASSERT(pPacket); MEM_DBG_PKT_FREE_INC(pPacket); #ifdef CONFIG_AP_SUPPORT #ifdef APCLI_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { if (RTMP_MATPktRxNeedConvert(pAd, RtmpOsPktNetDevGet(pRxPkt))) RTMP_MATEngineRxHandle(pAd, pRxPkt, 0); } #endif /* APCLI_SUPPORT */ #endif /* CONFIG_AP_SUPPORT */ /* Push up the protocol stack */ #ifdef CONFIG_AP_SUPPORT #ifdef PLATFORM_BL2348 { extern int (*pToUpperLayerPktSent)(PNDIS_PACKET *pSkb); RtmpOsPktProtocolAssign(pRxPkt); pToUpperLayerPktSent(pRxPkt); return; } #endif /* PLATFORM_BL2348 */ #endif /* CONFIG_AP_SUPPORT */ #ifdef IKANOS_VX_1X0 { IKANOS_DataFrameRx(pAd, pRxPkt); return; } #endif /* IKANOS_VX_1X0 */ #ifdef INF_PPA_SUPPORT if (ppa_hook_directpath_send_fn && pAd->PPAEnable==TRUE ) { RtmpOsPktInfPpaSend(pRxPkt); pRxPkt=NULL; return; } #endif /* INF_PPA_SUPPORT */ { #ifdef CONFIG_RT2880_BRIDGING_ONLY PACKET_CB_ASSIGN(pRxPkt, 22) = 0xa8; #endif #if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE) if(ra_classifier_hook_rx!= NULL) { unsigned int flags; RTMP_IRQ_LOCK(&pAd->page_lock, flags); ra_classifier_hook_rx(pRxPkt, classifier_cur_cycle); RTMP_IRQ_UNLOCK(&pAd->page_lock, flags); } #endif /* CONFIG_RA_CLASSIFIER */ #if !defined(CONFIG_RA_NAT_NONE) #if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) { struct sk_buff *pRxPktb = RTPKT_TO_OSPKT(pRxPkt); FOE_MAGIC_TAG(pRxPktb) = FOE_MAGIC_WLAN; } #endif #ifdef RA_NAT_SUPPORT #if !defined(CONFIG_RA_NAT_NONE) /* bruce+ * ra_sw_nat_hook_rx return 1 --> continue * ra_sw_nat_hook_rx return 0 --> FWD & without netif_rx */ if (ra_sw_nat_hook_rx!= NULL) { unsigned int flags; RtmpOsPktProtocolAssign(pRxPkt); RTMP_IRQ_LOCK(&pAd->page_lock, flags); if(ra_sw_nat_hook_rx(pRxPkt)) { netif_rx(pRxPkt); } RTMP_IRQ_UNLOCK(&pAd->page_lock, flags); return; } #endif /* !CONFIG_RA_NAT_NONE */ #endif /* RA_NAT_SUPPORT */ #else { #if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) FOE_AI(((struct sk_buff *)pRxPkt)) = UN_HIT; #endif /* CONFIG_RA_HW_NAT */ } #endif /* CONFIG_RA_NAT_NONE */ } #ifdef CONFIG_AP_SUPPORT #ifdef BG_FT_SUPPORT if (BG_FTPH_PacketFromApHandle(pRxPkt) == 0) return; #endif /* BG_FT_SUPPORT */ #endif /* CONFIG_AP_SUPPORT */ RtmpOsPktProtocolAssign(pRxPkt); RtmpOsPktRcvHandle(pRxPkt); }
void send_monitor_packets( IN PRTMP_ADAPTER pAd, IN RX_BLK *pRxBlk) { struct sk_buff *pOSPkt; wlan_ng_prism2_header *ph; int rate_index = 0; USHORT header_len = 0; UCHAR temp_header[40] = {0}; u_int32_t ralinkrate[256] = {2,4,11,22, 12,18,24,36,48,72,96, 108, 109, 110, 111, 112, 13, 26, 39, 52,78,104, 117, 130, 26, 52, 78,104, 156, 208, 234, 260, 27, 54,81,108,162, 216, 243, 270, // Last 38 54, 108, 162, 216, 324, 432, 486, 540, 14, 29, 43, 57, 87, 115, 130, 144, 29, 59,87,115, 173, 230,260, 288, 30, 60,90,120,180,240,270,300,60,120,180,240,360,480,540,600, 0,1,2,3,4,5,6,7,8,9,10, 11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80}; ASSERT(pRxBlk->pRxPacket); if (pRxBlk->DataSize < 10) { DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too small! (%d)\n", __func__, pRxBlk->DataSize)); goto err_free_sk_buff; } if (pRxBlk->DataSize + sizeof(wlan_ng_prism2_header) > RX_BUFFER_AGGRESIZE) { DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%zu)\n", __func__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header))); goto err_free_sk_buff; } pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0); if (pRxBlk->pHeader->FC.Type == BTYPE_DATA) { pRxBlk->DataSize -= LENGTH_802_11; if ((pRxBlk->pHeader->FC.ToDs == 1) && (pRxBlk->pHeader->FC.FrDs == 1)) header_len = LENGTH_802_11_WITH_ADDR4; else header_len = LENGTH_802_11; // QOS if (pRxBlk->pHeader->FC.SubType & 0x08) { header_len += 2; // Data skip QOS contorl field pRxBlk->DataSize -=2; } // Order bit: A-Ralink or HTC+ if (pRxBlk->pHeader->FC.Order) { header_len += 4; // Data skip HTC contorl field pRxBlk->DataSize -= 4; } // Copy Header if (header_len <= 40) NdisMoveMemory(temp_header, pRxBlk->pData, header_len); // skip HW padding if (pRxBlk->RxD.L2PAD) pRxBlk->pData += (header_len + 2); else pRxBlk->pData += header_len; } //end if if (pRxBlk->DataSize < pOSPkt->len) { skb_trim(pOSPkt,pRxBlk->DataSize); } else { skb_put(pOSPkt,(pRxBlk->DataSize - pOSPkt->len)); } //end if if ((pRxBlk->pData - pOSPkt->data) > 0) { skb_put(pOSPkt,(pRxBlk->pData - pOSPkt->data)); skb_pull(pOSPkt,(pRxBlk->pData - pOSPkt->data)); } //end if if (skb_headroom(pOSPkt) < (sizeof(wlan_ng_prism2_header)+ header_len)) { if (pskb_expand_head(pOSPkt, (sizeof(wlan_ng_prism2_header) + header_len), 0, GFP_ATOMIC)) { DBGPRINT(RT_DEBUG_ERROR, ("%s : Reallocate header size of sk_buff fail!\n", __func__)); goto err_free_sk_buff; } //end if } //end if if (header_len > 0) NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len); ph = (wlan_ng_prism2_header *) skb_push(pOSPkt, sizeof(wlan_ng_prism2_header)); NdisZeroMemory(ph, sizeof(wlan_ng_prism2_header)); ph->msgcode = DIDmsg_lnxind_wlansniffrm; ph->msglen = sizeof(wlan_ng_prism2_header); strcpy(ph->devname, pAd->net_dev->name); ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; ph->hosttime.status = 0; ph->hosttime.len = 4; ph->hosttime.data = jiffies; ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; ph->mactime.status = 0; ph->mactime.len = 0; ph->mactime.data = 0; ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx; ph->istx.status = 0; ph->istx.len = 0; ph->istx.data = 0; ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel; ph->channel.status = 0; ph->channel.len = 4; ph->channel.data = (u_int32_t)pAd->CommonCfg.Channel; ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; ph->rssi.status = 0; ph->rssi.len = 4; ph->rssi.data = (u_int32_t)RTMPMaxRssi(pAd, ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0, RSSI_0), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI1, RSSI_1), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2, RSSI_2));; ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal; ph->signal.status = 0; ph->signal.len = 4; ph->signal.data = 0; //rssi + noise; ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise; ph->noise.status = 0; ph->noise.len = 4; ph->noise.data = 0; if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX) { rate_index = 16 + ((UCHAR)pRxBlk->pRxWI->BW *16) + ((UCHAR)pRxBlk->pRxWI->ShortGI *32) + ((UCHAR)pRxBlk->pRxWI->MCS); } else if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM) rate_index = (UCHAR)(pRxBlk->pRxWI->MCS) + 4; else rate_index = (UCHAR)(pRxBlk->pRxWI->MCS); if (rate_index < 0) rate_index = 0; if (rate_index > 255) rate_index = 255; ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate; ph->rate.status = 0; ph->rate.len = 4; ph->rate.data = ralinkrate[rate_index]; ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; ph->frmlen.status = 0; ph->frmlen.len = 4; ph->frmlen.data = (u_int32_t)pRxBlk->DataSize; pOSPkt->pkt_type = PACKET_OTHERHOST; pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev); pOSPkt->ip_summed = CHECKSUM_NONE; netif_rx(pOSPkt); return; err_free_sk_buff: RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); return; }
PNDIS_PACKET GetPacketFromRxRing( IN PRTMP_ADAPTER pAd, OUT PRT28XX_RXD_STRUC pSaveRxD, OUT BOOLEAN *pbReschedule, IN OUT UINT32 *pRxPending) { PRX_CONTEXT pRxContext; PNDIS_PACKET pSkb; PUCHAR pData; ULONG ThisFrameLen; ULONG RxBufferLength; PRXWI_STRUC pRxWI; pRxContext = &pAd->RxContext[pAd->NextRxBulkInReadIndex]; if ((pRxContext->Readable == FALSE) || (pRxContext->InUse == TRUE)) return NULL; RxBufferLength = pRxContext->BulkInOffset - pAd->ReadPosition; if (RxBufferLength < (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXWI_STRUC) + sizeof(RXINFO_STRUC))) { goto label_null; } pData = &pRxContext->TransferBuffer[pAd->ReadPosition]; /* 4KB */ // The RXDMA field is 4 bytes, now just use the first 2 bytes. The Length including the (RXWI + MSDU + Padding) ThisFrameLen = *pData + (*(pData+1)<<8); if (ThisFrameLen == 0) { DBGPRINT(RT_DEBUG_TRACE, ("BIRIdx(%d): RXDMALen is zero.[%ld], BulkInBufLen = %ld)\n", pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset)); goto label_null; } if ((ThisFrameLen&0x3) != 0) { DBGPRINT(RT_DEBUG_ERROR, ("BIRIdx(%d): RXDMALen not multiple of 4.[%ld], BulkInBufLen = %ld)\n", pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset)); goto label_null; } if ((ThisFrameLen + 8)> RxBufferLength) // 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXINFO_STRUC)) { DBGPRINT(RT_DEBUG_TRACE,("BIRIdx(%d):FrameLen(0x%lx) outranges. BulkInLen=0x%lx, remaining RxBufLen=0x%lx, ReadPos=0x%lx\n", pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset, RxBufferLength, pAd->ReadPosition)); // error frame. finish this loop goto label_null; } // skip USB frame length field pData += RT2870_RXDMALEN_FIELD_SIZE; pRxWI = (PRXWI_STRUC)pData; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pData, TYPE_RXWI); #endif // RT_BIG_ENDIAN // if (pRxWI->MPDUtotalByteCount > ThisFrameLen) { DBGPRINT(RT_DEBUG_ERROR, ("%s():pRxWIMPDUtotalByteCount(%d) large than RxDMALen(%ld)\n", __FUNCTION__, pRxWI->MPDUtotalByteCount, ThisFrameLen)); goto label_null; } #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pData, TYPE_RXWI); #endif // RT_BIG_ENDIAN // // allocate a rx packet pSkb = dev_alloc_skb(ThisFrameLen); if (pSkb == NULL) { DBGPRINT(RT_DEBUG_ERROR,("%s():Cannot Allocate sk buffer for this Bulk-In buffer!\n", __FUNCTION__)); goto label_null; } // copy the rx packet memcpy(skb_put(pSkb, ThisFrameLen), pData, ThisFrameLen); RTPKT_TO_OSPKT(pSkb)->dev = get_netdev_from_bssid(pAd, BSS0); RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pSkb), PKTSRC_NDIS); // copy RxD *pSaveRxD = *(PRXINFO_STRUC)(pData + ThisFrameLen); #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pSaveRxD, TYPE_RXINFO); #endif // RT_BIG_ENDIAN // // update next packet read position. pAd->ReadPosition += (ThisFrameLen + RT2870_RXDMALEN_FIELD_SIZE + RXINFO_SIZE); // 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXINFO_STRUC)) return pSkb; label_null: return NULL; }
/* ======================================================================== Description: This routine frees all packets in PSQ that's destined to a specific DA. BCAST/MCAST in DTIMCount=0 case is also handled here, just like a PS-POLL is received from a WSTA which has MAC address FF:FF:FF:FF:FF:FF ======================================================================== */ VOID RtmpHandleRxPsPoll(RTMP_ADAPTER *pAd, UCHAR *pAddr, USHORT wcid, BOOLEAN isActive) { QUEUE_ENTRY *pQEntry; MAC_TABLE_ENTRY *pMacEntry; unsigned long IrqFlags; /* DBGPRINT(RT_DEBUG_TRACE, ("rcv PS-POLL (AID=%d) from %02x:%02x:%02x:%02x:%02x:%02x\n", Aid, PRINT_MAC(pAddr))); */ pMacEntry = &pAd->MacTab.Content[wcid]; if (RTMPEqualMemory(pMacEntry->Addr, pAddr, MAC_ADDR_LEN)) { #ifdef DROP_MASK_SUPPORT /* Disable Drop Mask */ set_drop_mask_per_client(pAd, pMacEntry, 2, 0); #endif /* DROP_MASK_SUPPORT */ #ifdef PS_ENTRY_MAITENANCE pMacEntry->continuous_ps_count = 0; #endif /* PS_ENTRY_MAITENANCE */ /* Sta is change to Power Active stat. Reset ContinueTxFailCnt */ pMacEntry->ContinueTxFailCnt = 0; #ifdef UAPSD_SUPPORT if (UAPSD_MR_IS_ALL_AC_UAPSD(isActive, pMacEntry)) { /* IEEE802.11e spec. 11.2.1.7 Receive operation for STAs in PS mode during the CP When a non-AP QSTA that is using U-APSD and has all ACs delivery-enabled detects that the bit corresponding to its AID is set in the TIM, the non-AP QSTA shall issue a trigger frame or a PS-Poll frame to retrieve the buffered MSDU or management frames. WMM Spec. v1.1a 070601 3.6.2 U-APSD STA Operation 3.6.2.3 In case one or more ACs are not delivery-enabled ACs, the WMM STA may retrieve MSDUs and MMPDUs belonging to those ACs by sending PS-Polls to the WMM AP. In case all ACs are delivery enabled ACs, WMM STA should only use trigger frames to retrieve MSDUs and MMPDUs belonging to those ACs, and it should not send PS-Poll frames. Different definitions in IEEE802.11e and WMM spec. But we follow the WiFi WMM Spec. */ DBGPRINT(RT_DEBUG_TRACE, ("All AC are UAPSD, can not use PS-Poll\n")); return; /* all AC are U-APSD, can not use PS-Poll */ } #endif /* UAPSD_SUPPORT */ RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); if (isActive == FALSE) { if (pMacEntry->PsQueue.Head) { #ifdef UAPSD_SUPPORT UINT32 NumOfOldPsPkt; NumOfOldPsPkt = pAd->TxSwQueue[QID_AC_BE].Number; #endif /* UAPSD_SUPPORT */ pQEntry = RemoveHeadQueue(&pMacEntry->PsQueue); if ( pMacEntry->PsQueue.Number >=1 ) RTMP_SET_PACKET_MOREDATA(RTPKT_TO_OSPKT(pQEntry), TRUE); InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QID_AC_BE], pQEntry); #ifdef UAPSD_SUPPORT /* we need to call RTMPDeQueuePacket() immediately as below */ if (NumOfOldPsPkt != pAd->TxSwQueue[QID_AC_BE].Number) { if (RTMP_GET_PACKET_DHCP(RTPKT_TO_OSPKT(pQEntry)) || RTMP_GET_PACKET_EAPOL(RTPKT_TO_OSPKT(pQEntry)) || RTMP_GET_PACKET_WAI(RTPKT_TO_OSPKT(pQEntry))) { /* These packets will use 1M/6M rate to send. If you use 1M(2.4G)/6M(5G) to send, no statistics count in NICUpdateFifoStaCounters(). So we can not count it for UAPSD; Or the SP will not closed until timeout. */ } else UAPSD_MR_MIX_PS_POLL_RCV(pAd, pMacEntry); } #endif /* UAPSD_SUPPORT */ } else { /* or transmit a (QoS) Null Frame; In addtion, in Station Keep Alive mechanism, we need to send a QoS Null frame to detect the station live status. */ BOOLEAN bQosNull = FALSE; if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)) bQosNull = TRUE; RtmpEnqueueNullFrame(pAd, pMacEntry->Addr, pMacEntry->CurrTxRate, pMacEntry->Aid, pMacEntry->apidx, bQosNull, TRUE, 0); } } else { #ifdef UAPSD_SUPPORT /* deliver all queued UAPSD packets */ UAPSD_AllPacketDeliver(pAd, pMacEntry); /* end the SP if exists */ UAPSD_MR_ENTRY_RESET(pAd, pMacEntry); #endif /* UAPSD_SUPPORT */ while(pMacEntry->PsQueue.Head) { pQEntry = RemoveHeadQueue(&pMacEntry->PsQueue); InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QID_AC_BE], pQEntry); } } if ((pMacEntry->Aid > 0) && (pMacEntry->Aid < MAX_LEN_OF_MAC_TABLE) && (pMacEntry->PsQueue.Number == 0)) { /* clear corresponding TIM bit because no any PS packet */ #ifdef CONFIG_AP_SUPPORT if(pMacEntry->wdev->wdev_type == WDEV_TYPE_AP) { WLAN_MR_TIM_BIT_CLEAR(pAd, pMacEntry->apidx, pMacEntry->Aid); } #endif /* CONFIG_AP_SUPPORT */ pMacEntry->PsQIdleCount = 0; } RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); /* Dequeue outgoing frames from TxSwQueue0..3 queue and process it TODO: 2004-12-27 it's not a good idea to handle "More Data" bit here. because the RTMPDeQueue process doesn't guarantee to de-queue the desired MSDU from the corresponding TxSwQueue/PsQueue when QOS in-used. We should consider "HardTransmt" this MPDU using MGMT queue or things like that. */ RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); } else { DBGPRINT(RT_DEBUG_ERROR,("rcv PS-POLL (AID=%d not match) from %02x:%02x:%02x:%02x:%02x:%02x\n", pMacEntry->Aid, PRINT_MAC(pAddr))); } }
/* ======================================================================== Description: This routine frees all packets in PSQ that's destined to a specific DA. BCAST/MCAST in DTIMCount=0 case is also handled here, just like a PS-POLL is received from a WSTA which has MAC address FF:FF:FF:FF:FF:FF ======================================================================== */ VOID MtHandleRxPsPoll(RTMP_ADAPTER *pAd, UCHAR *pAddr, USHORT wcid, BOOLEAN isActive) { #ifdef CONFIG_AP_SUPPORT #if defined(MT_PS) || defined(UAPSD_SUPPORT) MAC_TABLE_ENTRY *pMacEntry; #endif STA_TR_ENTRY *tr_entry; BOOLEAN IsDequeu= FALSE; INT DequeuAC = QID_AC_BE; INT DequeuCOUNT; #ifdef MT_PS INT i, Total_Packet_Number = 0; #endif /* MT_PS */ //struct tx_swq_fifo *fifo_swq; ASSERT(wcid < MAX_LEN_OF_MAC_TABLE); #if defined(MT_PS) || defined(UAPSD_SUPPORT) pMacEntry = &pAd->MacTab.Content[wcid]; #endif tr_entry = &pAd->MacTab.tr_entry[wcid]; if (isActive == FALSE) /* ps poll */ { #ifdef MT_PS if (tr_entry->ps_state == APPS_RETRIEVE_DONE) /*state is finish(sleep)*/ { if (pMacEntry->i_psm == I_PSM_DISABLE) { MT_SET_IGNORE_PSM(pAd, pMacEntry, I_PSM_ENABLE); } } if(tr_entry->ps_state == APPS_RETRIEVE_DONE || tr_entry->ps_state == APPS_RETRIEVE_IDLE) { for (i = 0; i < WMM_QUE_NUM; i++) Total_Packet_Number = Total_Packet_Number + tr_entry->tx_queue[i].Number; if (Total_Packet_Number > 0) { { DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_PS, ("RtmpHandleRxPsPoll fetch tx queue tr_entry->ps_queue.Number= %x tr_entry->tx_queue[0].Number=%x Total_Packet_Number=%x\n", tr_entry->ps_queue.Number, tr_entry->tx_queue[QID_AC_BE].Number, Total_Packet_Number)); for (i = (WMM_QUE_NUM - 1); i >=0; i--) { if (tr_entry->tx_queue[i].Head) { if (Total_Packet_Number > 1) { RTMP_SET_PACKET_MOREDATA(RTPKT_TO_OSPKT(tr_entry->tx_queue[i].Head), TRUE); } RTMP_SET_PACKET_TXTYPE(RTPKT_TO_OSPKT(tr_entry->tx_queue[i].Head), TX_LEGACY_FRAME); DequeuAC = i; IsDequeu = TRUE; DequeuCOUNT = 1; tr_entry->PsQIdleCount = 0; break; } } } } else /* Recieve ps_poll but no packet==>send NULL Packet */ { BOOLEAN bQosNull = FALSE; DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("RtmpHandleRxPsPoll no packet tr_entry->ps_queue.Number= %x tr_entry->tx_queue[0].Number=%x Total_Packet_Number=%x\n" ,tr_entry->ps_queue.Number, tr_entry->tx_queue[QID_AC_BE].Number, Total_Packet_Number)); if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)) bQosNull = TRUE; RtmpEnqueueNullFrame(pAd, pMacEntry->Addr, tr_entry->CurrTxRate, pMacEntry->Aid, pMacEntry->func_tb_idx, bQosNull, TRUE, 0); } if (Total_Packet_Number >1) { WLAN_MR_TIM_BIT_SET(pAd, tr_entry->func_tb_idx, tr_entry->wcid); } else { WLAN_MR_TIM_BIT_CLEAR(pAd, tr_entry->func_tb_idx, tr_entry->wcid); } } else tr_entry->PsDeQWaitCnt = 0; #else /* Need to check !! @20140212 New architecture has per AC sw-Q for per entry. We should check packets by ACs priority --> 1. VO, 2. VI, 3. BE, 4. BK */ DequeuAC = QID_AC_BE; IsDequeu = TRUE; DequeuCOUNT = 1; tr_entry->PsQIdleCount = 0; #endif /* Ps_poll and ifndef MT_PS */ } else /* Receive Power bit 0 frame */ { WLAN_MR_TIM_BIT_CLEAR(pAd, tr_entry->func_tb_idx, tr_entry->wcid); #ifdef MT_PS if (pMacEntry->i_psm == I_PSM_ENABLE) { MT_SET_IGNORE_PSM(pAd, pMacEntry, I_PSM_DISABLE); } #endif /*Power bit is 1 and ifndef MT_PS */ DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("RtmpHandleRxPsPoll null0/1 wcid = %x mt_ps_queue.Number = %d\n", tr_entry->wcid, tr_entry->ps_queue.Number)); DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("%s(%d) tx_queue.Number = BE:%d, BK:%d, VI:%d, VO:%d, ps_state:%x, tx_queue.TokenCount = BE:%d, BK:%d, VI:%d, VO:%d\n", __FUNCTION__, __LINE__, tr_entry->tx_queue[QID_AC_BE].Number, tr_entry->tx_queue[QID_AC_BK].Number, tr_entry->tx_queue[QID_AC_VI].Number, tr_entry->tx_queue[QID_AC_VO].Number, tr_entry->ps_state, tr_entry->TokenCount[QID_AC_BE], tr_entry->TokenCount[QID_AC_BK], tr_entry->TokenCount[QID_AC_VI], tr_entry->TokenCount[QID_AC_VO])); #ifdef UAPSD_SUPPORT if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_APSD_CAPABLE)) { /* deliver all queued UAPSD packets */ UAPSD_AllPacketDeliver(pAd, pMacEntry); /* end the SP if exists */ UAPSD_MR_ENTRY_RESET(pAd, pMacEntry); } #endif /* UAPSD_SUPPORT */ if (tr_entry->enqCount > 0) { IsDequeu = TRUE; DequeuAC = NUM_OF_TX_RING; if (tr_entry->enqCount > MAX_TX_PROCESS) { DequeuCOUNT = MAX_TX_PROCESS; rtmp_ps_enq(pAd,tr_entry); } else { DequeuCOUNT = tr_entry->enqCount; } } } if (IsDequeu == TRUE) { RTMPDeQueuePacket(pAd, FALSE, DequeuAC, tr_entry->wcid, DequeuCOUNT); DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("RtmpHandleRxPsPoll IsDequeu == TRUE tr_entry->wcid=%x DequeuCOUNT=%d, ps_state=%d\n",tr_entry->wcid, DequeuCOUNT, tr_entry->ps_state)); } return; #endif /* CONFIG_AP_SUPPORT */ }
/* ======================================================================== Routine Description: Get a received packet. Arguments: pAd device control block pSaveRxD receive descriptor information *pbReschedule need reschedule flag *pRxPending pending received packet flag Return Value: the received packet Note: ======================================================================== */ void *GetPacketFromRxRing(struct rt_rtmp_adapter *pAd, OUT PRT28XX_RXD_STRUC pSaveRxD, OUT BOOLEAN * pbReschedule, IN u32 * pRxPending) { struct rt_rx_context *pRxContext; void *pSkb; u8 *pData; unsigned long ThisFrameLen; unsigned long RxBufferLength; struct rt_rxwi * pRxWI; pRxContext = &pAd->RxContext[pAd->NextRxBulkInReadIndex]; if ((pRxContext->Readable == FALSE) || (pRxContext->InUse == TRUE)) return NULL; RxBufferLength = pRxContext->BulkInOffset - pAd->ReadPosition; if (RxBufferLength < (RT2870_RXDMALEN_FIELD_SIZE + sizeof(struct rt_rxwi) + sizeof(struct rt_rxinfo))) { goto label_null; } pData = &pRxContext->TransferBuffer[pAd->ReadPosition]; /* 4KB */ /* The RXDMA field is 4 bytes, now just use the first 2 bytes. The Length including the (RXWI + MSDU + Padding) */ ThisFrameLen = *pData + (*(pData + 1) << 8); if (ThisFrameLen == 0) { DBGPRINT(RT_DEBUG_TRACE, ("BIRIdx(%d): RXDMALen is zero.[%ld], BulkInBufLen = %ld)\n", pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset)); goto label_null; } if ((ThisFrameLen & 0x3) != 0) { DBGPRINT(RT_DEBUG_ERROR, ("BIRIdx(%d): RXDMALen not multiple of 4.[%ld], BulkInBufLen = %ld)\n", pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset)); goto label_null; } if ((ThisFrameLen + 8) > RxBufferLength) /* 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(struct rt_rxinfo)) */ { DBGPRINT(RT_DEBUG_TRACE, ("BIRIdx(%d):FrameLen(0x%lx) outranges. BulkInLen=0x%lx, remaining RxBufLen=0x%lx, ReadPos=0x%lx\n", pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset, RxBufferLength, pAd->ReadPosition)); /* error frame. finish this loop */ goto label_null; } /* skip USB frame length field */ pData += RT2870_RXDMALEN_FIELD_SIZE; pRxWI = (struct rt_rxwi *) pData; if (pRxWI->MPDUtotalByteCount > ThisFrameLen) { DBGPRINT(RT_DEBUG_ERROR, ("%s():pRxWIMPDUtotalByteCount(%d) large than RxDMALen(%ld)\n", __FUNCTION__, pRxWI->MPDUtotalByteCount, ThisFrameLen)); goto label_null; } /* allocate a rx packet */ pSkb = dev_alloc_skb(ThisFrameLen); if (pSkb == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("%s():Cannot Allocate sk buffer for this Bulk-In buffer!\n", __FUNCTION__)); goto label_null; } /* copy the rx packet */ memcpy(skb_put(pSkb, ThisFrameLen), pData, ThisFrameLen); RTPKT_TO_OSPKT(pSkb)->dev = get_netdev_from_bssid(pAd, BSS0); RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pSkb), PKTSRC_NDIS); /* copy RxD */ *pSaveRxD = *(struct rt_rxinfo *) (pData + ThisFrameLen); /* update next packet read position. */ pAd->ReadPosition += (ThisFrameLen + RT2870_RXDMALEN_FIELD_SIZE + RXINFO_SIZE); /* 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(struct rt_rxinfo)) */ return pSkb; label_null: return NULL; }
/* ======================================================================== Routine Description: For each out-going packet, check the upper layer protocol type if need to handled by our APCLI convert engine. If yes, call corresponding handler to handle it. Arguments: pAd =>Pointer to our adapter pPkt =>pointer to the 802.11 header of outgoing packet ifIdx =>Interface Index want to dispatch to. Return Value: Success => TRUE Mapped mac address if found, else return specific default mac address depends on the upper layer protocol type. Error => FALSE. Note: 1.the pPktHdr must be a 802.3 packet. 2.Maybe we need a TxD arguments? 3.We check every packet here including group mac address becasue we need to handle DHCP packet. ======================================================================== */ PUCHAR MATEngineTxHandle( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPkt, IN UINT ifIdx, IN UCHAR OpMode) { PUCHAR pLayerHdr = NULL, pPktHdr = NULL, pMacAddr = NULL; UINT16 protoType, protoType_ori; INT i; struct _MATProtoOps *pHandle = NULL; PUCHAR retSkb = NULL; BOOLEAN bVLANPkt = FALSE; if(pAd->MatCfg.status != MAT_ENGINE_STAT_INITED) return NULL; pPktHdr = GET_OS_PKT_DATAPTR(pPkt); if (!pPktHdr) return NULL; protoType_ori = get_unaligned((PUINT16)(pPktHdr + 12)); /* Get the upper layer protocol type of this 802.3 pkt. */ protoType = OS_NTOHS(protoType_ori); /* handle 802.1q enabled packet. Skip the VLAN tag field to get the protocol type. */ if (protoType == 0x8100) { protoType_ori = get_unaligned((PUINT16)(pPktHdr + 12 + 4)); protoType = OS_NTOHS(protoType_ori); bVLANPkt = TRUE; } #ifdef RELEASE_EXCLUDE DBGPRINT(RT_DEBUG_INFO,("%s(): protoType=0x%04x\n", __FUNCTION__, protoType)); #endif /* RELEASE_EXCLUDE */ /* For differnet protocol, dispatch to specific handler */ for (i=0; i < MAX_MAT_SUPPORT_PROTO_NUM; i++) { if (protoType == MATProtoTb[i].protocol) { pHandle = MATProtoTb[i].pHandle; /* the pHandle must not be null! */ pLayerHdr = bVLANPkt ? (pPktHdr + MAT_VLAN_ETH_HDR_LEN) : (pPktHdr + MAT_ETHER_HDR_LEN); #ifdef CONFIG_AP_SUPPORT #ifdef APCLI_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { #ifdef MAC_REPEATER_SUPPORT UCHAR tempIdx = ifIdx; UCHAR CliIdx = 0xFF; if (tempIdx >= 64) { CliIdx = ((tempIdx - 64) % 16); tempIdx = ((tempIdx - 64) / 16); pMacAddr = &pAd->ApCfg.ApCliTab[tempIdx].RepeaterCli[CliIdx].CurrentAddress[0]; } else #endif /* MAC_REPEATER_SUPPORT */ pMacAddr = &pAd->ApCfg.ApCliTab[ifIdx].wdev.if_addr[0]; } #endif /* APCLI_SUPPORT */ #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT #ifdef ETH_CONVERT_SUPPORT #ifdef P2P_SUPPORT if (OpMode == OPMODE_STA) pMacAddr = &pAd->CurrentAddress[0]; #ifdef APCLI_SUPPORT else pMacAddr = &pAd->ApCfg.ApCliTab[ifIdx].wdev.if_addr[0]; #endif /* APCLI_SUPPORT */ #else IF_DEV_CONFIG_OPMODE_ON_STA(pAd) pMacAddr = &pAd->CurrentAddress[0]; #endif /* P2P_SUPPORT */ #endif /* ETH_CONVERT_SUPPORT */ #endif /* CONFIG_STA_SUPPORT */ if (pHandle->tx!=NULL) retSkb = pHandle->tx((PVOID)&pAd->MatCfg, RTPKT_TO_OSPKT(pPkt), pLayerHdr, pMacAddr); return retSkb; } }