void sendDataPacket (TI_HANDLE hOs) { TI_UINT32 i; TTxCtrlBlk * pPktCtrlBlk; TI_UINT8 * pPktBuf; TEthernetHeader tEthHeader; char SrcBssid[6] = {0x88,0x88,0x88,0x88,0x88,0x88}; char DesBssid[6] = {0x22,0x22,0x22,0x22,0x22,0x22}; /* Allocate a TxCtrlBlk for the Tx packet and save timestamp, length and packet handle */ pPktCtrlBlk = TWD_txCtrlBlk_Alloc (tmp_hTWD); if( NULL == pPktCtrlBlk ) { os_printf("\n sendDataPacket() : pPktCtrlBlk returned as NULL from TWD_txCtrlBlk_Alloc() "); return; } pPktCtrlBlk->tTxDescriptor.startTime = os_timeStampMs (hOs); pPktCtrlBlk->tTxDescriptor.length = (TI_UINT16)packetLength + ETHERNET_HDR_LEN; pPktCtrlBlk->tTxDescriptor.tid = 0; pPktCtrlBlk->tTxPktParams.uPktType = TX_PKT_TYPE_ETHER; /* Allocate buffer with headroom for getting the IP header in a 4-byte aligned address */ pPktBuf = txCtrl_AllocPacketBuffer (tmp_hTxCtrl, pPktCtrlBlk, packetLength + ETHERNET_HDR_LEN + 2); /* Prepare Ethernet header */ tEthHeader.type = HTOWLANS(ETHERTYPE_IP); MAC_COPY (tEthHeader.src, SrcBssid); MAC_COPY (tEthHeader.dst, DesBssid); if( pPktBuf ) { os_memoryCopy (hOs, pPktBuf + 2, &tEthHeader, ETHERNET_HDR_LEN); /* Build BDL */ BUILD_TX_TWO_BUF_PKT_BDL (pPktCtrlBlk, pPktBuf + 2, ETHERNET_HDR_LEN, pPktBuf + 2 + ETHERNET_HDR_LEN, packetLength) /* Fill data buffer with incremented numbers */ for (i = 0; i < packetLength; i++) { *(pPktBuf + 2 + ETHERNET_HDR_LEN + i) = i; } } else {
TI_STATUS txDataQ_InsertPacket (TI_HANDLE hTxDataQ, TTxCtrlBlk *pPktCtrlBlk, TI_UINT8 uPacketDtag) { TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ; TEthernetHeader *pEthHead = (TEthernetHeader *)(pPktCtrlBlk->tTxnStruct.aBuf[0]); TI_STATUS eStatus; TI_UINT32 uQueId; TI_UINT32 uQueSize; txCtrl_t *pTxCtrl = (txCtrl_t *)(pTxDataQ->hTxCtrl); TI_BOOL bRequestSchedule = TI_FALSE; TI_BOOL bStopNetStack = TI_FALSE; CL_TRACE_START_L3(); /* If packet is EAPOL or from the generic Ethertype, forward it to the Mgmt-Queue and exit */ if ((HTOWLANS(pEthHead->type) == ETHERTYPE_EAPOL) || (HTOWLANS(pEthHead->type) == pTxCtrl->genericEthertype)) { pPktCtrlBlk->tTxPktParams.uPktType = TX_PKT_TYPE_EAPOL; return txMgmtQ_Xmit (pTxDataQ->hTxMgmtQ, pPktCtrlBlk, TI_TRUE); /* Note: The last parameter indicates that we are running in external context */ } pPktCtrlBlk->tTxPktParams.uPktType = TX_PKT_TYPE_ETHER; /* Enter critical section to protect classifier data and queue access */ context_EnterCriticalSection (pTxDataQ->hContext); /* Call the Classify function to set the TID field */ if (txDataClsfr_ClassifyTxPacket (hTxDataQ, pPktCtrlBlk, uPacketDtag) != TI_OK) { #ifdef TI_DBG pTxDataQ->uClsfrMismatchCount++; TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_WARNING, "txDataQueue_xmit: No matching classifier found \n"); #endif /* TI_DBG */ } /* Enqueue the packet in the appropriate Queue */ uQueId = aTidToQueueTable[pPktCtrlBlk->tTxDescriptor.tid]; eStatus = que_Enqueue (pTxDataQ->aQueues[uQueId], (TI_HANDLE)pPktCtrlBlk); /* Get number of packets in current queue */ uQueSize = que_Size (pTxDataQ->aQueues[uQueId]); /* If the current queue is not stopped */ if (pTxDataQ->aQueueBusy[uQueId] == TI_FALSE) { /* If the queue has the desired number of packets, request switch to driver context for handling them */ if (uQueSize == pTxDataQ->aTxSendPaceThresh[uQueId]) { tmr_StopTimer (pTxDataQ->hTxSendPaceTimer); bRequestSchedule = TI_TRUE; } /* If below Tx-Send pacing threshold, start timer to trigger packets handling if expired */ else if (uQueSize < pTxDataQ->aTxSendPaceThresh[uQueId]) { tmr_StartTimer (pTxDataQ->hTxSendPaceTimer, txDataQ_TxSendPaceTimeout, hTxDataQ, TX_SEND_PACE_TIMEOUT_MSEC, TI_FALSE); } } /* If allowed to stop network stack and the queue is full, indicate to stop network and to schedule Tx handling (both are executed below, outside the critical section!) */ if ((pTxDataQ->bStopNetStackTx) && (uQueSize == pTxDataQ->aQueueMaxSize[uQueId])) { pTxDataQ->aNetStackQueueStopped[uQueId] = TI_TRUE; bRequestSchedule = TI_TRUE; bStopNetStack = TI_TRUE; } /* Leave critical section */ context_LeaveCriticalSection (pTxDataQ->hContext); /* If needed, schedule Tx handling */ if (bRequestSchedule) { context_RequestSchedule (pTxDataQ->hContext, pTxDataQ->uContextId); } /* If needed, stop the network stack Tx */ if (bStopNetStack) { /* Stop the network stack from sending Tx packets as we have at least one date queue full. Note that in some of the OS's (e.g Win Mobile) it is implemented by blocking the thread*/ wlanDrvIf_StopTx (pTxDataQ->hOs); } if (eStatus != TI_OK) { /* If the packet can't be queued drop it */ txCtrl_FreePacket (pTxDataQ->hTxCtrl, pPktCtrlBlk, TI_NOK); #ifdef TI_DBG pTxDataQ->aQueueCounters[uQueId].uDroppedPacket++; #endif /* TI_DBG */ } else { #ifdef TI_DBG pTxDataQ->aQueueCounters[uQueId].uEnqueuePacket++; #endif /* TI_DBG */ } CL_TRACE_END_L3 ("tiwlan_drv.ko", "INHERIT", "TX", ""); return eStatus; }
TI_STATUS txDataQ_InsertPacket (TI_HANDLE hTxDataQ, TTxCtrlBlk *pPktCtrlBlk, TI_UINT8 uPacketDtag, TIntraBssBridge *pIntraBssBridgeParam) { TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ; TEthernetHeader *pEthHead = (TEthernetHeader *)(pPktCtrlBlk->tTxnStruct.aBuf[0]); TI_STATUS eStatus; TI_UINT32 uQueId; TI_UINT32 uQueSize; txCtrl_t *pTxCtrl = (txCtrl_t *)(pTxDataQ->hTxCtrl); TI_BOOL bRequestSchedule = TI_FALSE; TI_BOOL bStopNetStack = TI_FALSE; TDataLinkQ *pLinkQ; TI_UINT32 uHlid; /* If packet is EAPOL or from the generic Ethertype, forward it to the Mgmt-Queue and exit */ if ((HTOWLANS(pEthHead->type) == ETHERTYPE_EAPOL) || (HTOWLANS(pEthHead->type) == pTxCtrl->genericEthertype)) { pPktCtrlBlk->tTxPktParams.uPktType = TX_PKT_TYPE_EAPOL; return txMgmtQ_Xmit (pTxDataQ->hTxMgmtQ, pPktCtrlBlk, TI_TRUE); /* Note: The last parameter indicates that we are running in external context */ } /* Find link id by destination MAC address, if not found drop the packet */ /* use Intra Bss bridge params*/ if(!pIntraBssBridgeParam) { if (TI_UNLIKELY(MAC_MULTICAST(pEthHead->dst))) { uHlid = pTxDataQ->uBcastHlid; } else { if (txDataQ_LinkMacFind( hTxDataQ, &uHlid, pEthHead->dst) != TI_OK) { /* If the packet can't be queued drop it */ txCtrl_FreePacket (pTxDataQ->hTxCtrl, pPktCtrlBlk, TI_NOK); pTxDataQ->uLinkNotFoundCount++; return TI_NOK; } } } else { uHlid = pIntraBssBridgeParam->uParam; } pPktCtrlBlk->tTxDescriptor.hlid = uHlid; pLinkQ = &pTxDataQ->aDataLinkQ[uHlid]; /* Link queues */ pPktCtrlBlk->tTxPktParams.uPktType = TX_PKT_TYPE_ETHER; /* set encryption bit */ if (pLinkQ->bEncrypt) { SET_PKT_TYPE_ENCRYPT(pPktCtrlBlk); } /* Enter critical section to protect classifier data and queue access */ context_EnterCriticalSection (pTxDataQ->hContext); /* Call the Classify function to set the TID field */ if (txDataClsfr_ClassifyTxPacket (hTxDataQ, pPktCtrlBlk, uPacketDtag) != TI_OK) { #ifdef TI_DBG pTxDataQ->uClsfrMismatchCount++; #endif /* TI_DBG */ } uQueId = aTidToQueueTable[pPktCtrlBlk->tTxDescriptor.tid]; /* Check resources per LINK and per AC */ if (txDataQ_AllocCheckResources( hTxDataQ, pPktCtrlBlk) != TI_OK) { #ifdef TI_DBG pLinkQ->aQueueCounters[uQueId].uDroppedPacket++; pTxDataQ->uNoResourcesCount++; #endif /* TI_DBG */ /* Leave critical section */ context_LeaveCriticalSection (pTxDataQ->hContext); /* If the packet can't be queued drop it - Should be out of the critical section */ /* !!! This call should be out of the critical section */ txCtrl_FreePacket (pTxDataQ->hTxCtrl, pPktCtrlBlk, TI_NOK); return TI_NOK; } /* Enqueue the packet in the appropriate Queue */ eStatus = que_Enqueue (pLinkQ->aQueues[uQueId], (TI_HANDLE)pPktCtrlBlk); /* Get number of packets in current queue */ uQueSize = que_Size (pLinkQ->aQueues[uQueId]); /* If the current queue is not stopped */ if (pTxDataQ->aQueueBusy[uQueId] == TI_FALSE) { /* If the queue has the desired number of packets, request switch to driver context for handling them */ if (uQueSize == pTxDataQ->aTxSendPaceThresh[uQueId]) { tmr_StopTimer (pTxDataQ->hTxSendPaceTimer); bRequestSchedule = TI_TRUE; } /* If below Tx-Send pacing threshold, start timer to trigger packets handling if expired */ else if (uQueSize < pTxDataQ->aTxSendPaceThresh[uQueId]) { tmr_StartTimer (pTxDataQ->hTxSendPaceTimer, txDataQ_TxSendPaceTimeout, hTxDataQ, TX_SEND_PACE_TIMEOUT_MSEC, TI_FALSE); } } /* If allowed to stop network stack and the queue is full, indicate to stop network and to schedule Tx handling (both are executed below, outside the critical section!) */ if ((pTxDataQ->bStopNetStackTx) && (uQueSize == pTxDataQ->aQueueMaxSize[uQueId])) { pLinkQ->aNetStackQueueStopped[uQueId] = TI_TRUE; bRequestSchedule = TI_TRUE; bStopNetStack = TI_TRUE; } /* Leave critical section */ context_LeaveCriticalSection (pTxDataQ->hContext); /* If needed, schedule Tx handling */ if (bRequestSchedule) { context_RequestSchedule (pTxDataQ->hContext, pTxDataQ->uContextId); } /* If needed, stop the network stack Tx */ if (bStopNetStack) { /* Stop the network stack from sending Tx packets as we have at least one date queue full. Note that in some of the OS's (e.g Win Mobile) it is implemented by blocking the thread! */ wlanDrvIf_StopTx (pTxDataQ->hOs); } if (eStatus != TI_OK) { /* If the packet can't be queued drop it */ txCtrl_FreePacket (pTxDataQ->hTxCtrl, pPktCtrlBlk, TI_NOK); #ifdef TI_DBG pLinkQ->aQueueCounters[uQueId].uDroppedPacket++; #endif /* TI_DBG */ } else { #ifdef TI_DBG pLinkQ->aQueueCounters[uQueId].uEnqueuePacket++; #endif /* TI_DBG */ } return eStatus; }
/*********************************************************************** * txCtrlServ_buildWlanHeader *********************************************************************** DESCRIPTION: Build WLAN header from Ethernet header. INPUT: hTxCtrl - Tx Ctrl module handle (the txServ uses the txCtrl object!!). pFrame - A pointer to a buffer where the frame should be stored pLength - A pointer to a placeholder for the frame length ************************************************************************/ TI_STATUS txCtrlServ_buildWlanHeader(TI_HANDLE hTxCtrl, TI_UINT8* pFrame, TI_UINT32* pLength) { txCtrl_t *pTxCtrl = (txCtrl_t *)hTxCtrl; TI_STATUS status; TMacAddr daBssid; TMacAddr saBssid; EQosProtocol qosProt; ScanBssType_e currBssType; TMacAddr currBssId; TI_UINT32 headerLength; TI_UINT16 headerFlags; TI_BOOL currentPrivacyInvokedMode; TI_UINT8 encryptionFieldSize; TTxCtrlBlk tPktCtrlBlk; dot11_header_t *pDot11Header = (dot11_header_t*)(tPktCtrlBlk.aPktHdr); Wlan_LlcHeader_T *pWlanSnapHeader; /* * If QoS is used, add two bytes padding before the header for 4-bytes alignment. * Note that the header length doesn't include it, so the txCtrl detects the pad existence * by checking if the header-length is a multiple of 4. */ qosMngr_getParamsActiveProtocol(pTxCtrl->hQosMngr, &qosProt); if (qosProt == QOS_WME) { headerLength = WLAN_QOS_HDR_LEN; headerFlags = DOT11_FC_DATA_QOS | DOT11_FC_TO_DS; pDot11Header->qosControl = 0; } else { headerLength = WLAN_HDR_LEN; headerFlags = DOT11_FC_DATA | DOT11_FC_TO_DS; } /* * Handle encryption if needed (decision was done at RSN and is provided by TxCtrl): * - Set WEP bit in header. * - Add padding for FW security overhead: 4 bytes for TKIP, 8 for AES. */ txCtrlParams_getCurrentEncryptionInfo (hTxCtrl, ¤tPrivacyInvokedMode, &encryptionFieldSize); if (currentPrivacyInvokedMode) { headerFlags |= DOT11_FC_WEP; headerLength += encryptionFieldSize; } COPY_WLAN_WORD (&pDot11Header->fc, &headerFlags); /* copy with endianess handling. */ /* Get the Destination MAC address */ status = ctrlData_getParamBssid (pTxCtrl->hCtrlData, CTRL_DATA_CURRENT_BSSID_PARAM, daBssid); if (status != TI_OK) { return TI_NOK; } /* Get the Source MAC address */ status = ctrlData_getParamBssid (pTxCtrl->hCtrlData, CTRL_DATA_MAC_ADDRESS, saBssid); if (status != TI_OK) { return TI_NOK; } /* receive BssId and Bss Type from control module */ ctrlData_getCurrBssTypeAndCurrBssId (pTxCtrl->hCtrlData, &currBssId, &currBssType); if (currBssType != BSS_INFRASTRUCTURE) { return TI_NOK; } /* copy BSSID */ MAC_COPY (pDot11Header->address1, currBssId); /* copy source mac address */ MAC_COPY (pDot11Header->address2, saBssid); /* copy destination mac address*/ MAC_COPY (pDot11Header->address3, daBssid); /* Set the SNAP header pointer right after the other header parts handled above. */ pWlanSnapHeader = (Wlan_LlcHeader_T *)&(tPktCtrlBlk.aPktHdr[headerLength]); pWlanSnapHeader->DSAP = SNAP_CHANNEL_ID; pWlanSnapHeader->SSAP = SNAP_CHANNEL_ID; pWlanSnapHeader->Control = LLC_CONTROL_UNNUMBERED_INFORMATION; /* add RFC1042. */ pWlanSnapHeader->OUI[0] = SNAP_OUI_RFC1042_BYTE0; pWlanSnapHeader->OUI[1] = SNAP_OUI_RFC1042_BYTE1; pWlanSnapHeader->OUI[2] = SNAP_OUI_RFC1042_BYTE2; /* set ETH type to IP */ pWlanSnapHeader->Type = HTOWLANS(ETHERTYPE_IP); /* Add the SNAP length to the total header length. */ headerLength += sizeof(Wlan_LlcHeader_T); /* copy WLAN header */ os_memoryCopy (pTxCtrl->hOs, pFrame, tPktCtrlBlk.aPktHdr, headerLength); *pLength = headerLength; return TI_OK; }
static int xmit_Bridge (struct sk_buff *skb, struct net_device *dev, TIntraBssBridge *pBssBridgeParam) { TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); TTxCtrlBlk * pPktCtrlBlk; TEthernetHeader *pEthHead = (TEthernetHeader *)(skb->data); int status; CL_TRACE_START_L1(); os_profile (drv, 0, 0); drv->stats.tx_packets++; drv->stats.tx_bytes += skb->len; /* Allocate a TxCtrlBlk for the Tx packet and save timestamp, length and packet handle */ pPktCtrlBlk = TWD_txCtrlBlk_Alloc (drv->tCommon.hTWD); if (pPktCtrlBlk == NULL) { drv->stats.tx_errors++; os_profile (drv, 1, 0); CL_TRACE_END_L1("tiwlan_drv.ko", "OS", "TX", ""); return 0; } /* Set interface type according to net device interface number */ if (drv->tCommon.eIfRole == IF_ROLE_TYPE_AP) SET_PKT_TYPE_IF_ROLE_AP(pPktCtrlBlk); else SET_PKT_TYPE_IF_ROLE_STA(pPktCtrlBlk); pPktCtrlBlk->tTxDescriptor.startTime = os_timeStampMs(drv); /* remove use of skb->tstamp.off_usec */ pPktCtrlBlk->tTxDescriptor.length = skb->len; pPktCtrlBlk->tTxPktParams.pInputPkt = skb; /* Check MGMT packet from hostapd, forward it to the Mgmt-Queue and exit without ethernet header */ if (HTOWLANS(pEthHead->type) == AP_MGMT_ETH_TYPE) { /* Copy WLAN header into aPktHdr - format for MGMT packets */ memcpy (pPktCtrlBlk->aPktHdr, skb->data + ETHERNET_HDR_LEN , WLAN_HDR_LEN ); /* Skip ethernet header, send as management frame */ pPktCtrlBlk->tTxPktParams.uPktType = TX_PKT_TYPE_MGMT; pPktCtrlBlk->tTxnStruct.aBuf[0] = (TI_UINT8 *)pPktCtrlBlk->aPktHdr; pPktCtrlBlk->tTxnStruct.aLen[0] = WLAN_HDR_LEN; pPktCtrlBlk->tTxnStruct.aBuf[1] = skb->data + ETHERNET_HDR_LEN + WLAN_HDR_LEN; pPktCtrlBlk->tTxnStruct.aLen[1] = (TI_UINT16)skb->len - ETHERNET_HDR_LEN - WLAN_HDR_LEN; pPktCtrlBlk->tTxnStruct.aLen[2] = 0; pPktCtrlBlk->tTxPktParams.uInputPktLen = skb->len; pPktCtrlBlk->tTxDescriptor.length = (TI_UINT16)((pPktCtrlBlk->tTxnStruct.aLen[0]) + (pPktCtrlBlk->tTxnStruct.aLen[1])); status = txMgmtQ_Xmit (drv->tCommon.hTxMgmtQ, pPktCtrlBlk, TI_TRUE); } else { /* Point the first BDL buffer to the Ethernet header, and the second buffer to the rest of the packet */ pPktCtrlBlk->tTxnStruct.aBuf[0] = skb->data; pPktCtrlBlk->tTxnStruct.aLen[0] = ETHERNET_HDR_LEN; pPktCtrlBlk->tTxnStruct.aBuf[1] = skb->data + ETHERNET_HDR_LEN; pPktCtrlBlk->tTxnStruct.aLen[1] = (TI_UINT16)skb->len - ETHERNET_HDR_LEN; pPktCtrlBlk->tTxnStruct.aLen[2] = 0; /* Send the packet to the driver for transmission. */ status = txDataQ_InsertPacket (drv->tCommon.hTxDataQ, pPktCtrlBlk,(TI_UINT8)skb->priority, pBssBridgeParam); } /* If failed (queue full or driver not running), drop the packet. */ if (status != TI_OK) { drv->stats.tx_errors++; } os_profile (drv, 1, 0); CL_TRACE_END_L1("tiwlan_drv.ko", "OS", "TX", ""); return 0; }