INT SendPacketToFW(struct sk_buff *skb) { if(psAdaptertest) { skb->dev = psAdaptertest->dev; return bcm_transmit(skb, psAdaptertest->dev); } else { printk("Dropping as adapter is not initialized yet\n"); bcm_kfree_skb(skb); return STATUS_FAILURE; } }
VOID reply_to_arp_request(struct sk_buff *skb) { PMINI_ADAPTER Adapter; struct ArpHeader *pArpHdr = NULL; struct ethhdr *pethhdr = NULL; UCHAR uiIPHdr[4]; /* Check for valid skb */ if(skb == NULL) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid skb: Cannot reply to ARP request\n"); return; } Adapter = GET_BCM_ADAPTER(skb->dev); /* Print the ARP Request Packet */ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, "ARP Packet Dump :"); BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, (PUCHAR)(skb->data), skb->len); /* * Extract the Ethernet Header and Arp Payload including Header */ pethhdr = (struct ethhdr *)skb->data; pArpHdr = (struct ArpHeader *)(skb->data+ETH_HLEN); if(Adapter->bETHCSEnabled) { if(memcmp(pethhdr->h_source, Adapter->dev->dev_addr, ETH_ALEN)) { bcm_kfree_skb(skb); return; } } // Set the Ethernet Header First. memcpy(pethhdr->h_dest, pethhdr->h_source, ETH_ALEN); if(!memcmp(pethhdr->h_source, Adapter->dev->dev_addr, ETH_ALEN)) { pethhdr->h_source[5]++; } /* Set the reply to ARP Reply */ pArpHdr->arp.ar_op = ntohs(ARPOP_REPLY); /* Set the HW Address properly */ memcpy(pArpHdr->ar_sha, pethhdr->h_source, ETH_ALEN); memcpy(pArpHdr->ar_tha, pethhdr->h_dest, ETH_ALEN); // Swapping the IP Adddress memcpy(uiIPHdr,pArpHdr->ar_sip,4); memcpy(pArpHdr->ar_sip,pArpHdr->ar_tip,4); memcpy(pArpHdr->ar_tip,uiIPHdr,4); /* Print the ARP Reply Packet */ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, "ARP REPLY PACKET: "); /* Send the Packet to upper layer */ BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, (PUCHAR)(skb->data), skb->len); skb->protocol = eth_type_trans(skb,skb->dev); skb->pkt_type = PACKET_HOST; // skb->mac.raw=skb->data+LEADER_SIZE; skb_set_mac_header (skb, LEADER_SIZE); netif_rx(skb); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, "<=============\n"); return; }
INT bcm_transmit(struct sk_buff *skb, /**< skb */ struct net_device *dev /**< net device pointer */ ) { PMINI_ADAPTER Adapter = NULL; USHORT qindex=0; struct timeval tv; UINT pkt_type = 0; UINT calltransmit = 0; INT status = STATUS_SUCCESS; BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "\n%s====>\n",__FUNCTION__); memset(&tv, 0, sizeof(tv)); /* Check for valid parameters */ if(skb == NULL || dev==NULL) { BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX,TX_OSAL_DBG, DBG_LVL_ALL, "Got NULL skb or dev\n"); return -EINVAL; } Adapter = GET_BCM_ADAPTER(dev); if(!Adapter) { BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Got Invalid Adapter\n"); status = -EINVAL; goto exit_path; } if(Adapter->device_removed == TRUE || !Adapter->LinkUpStatus) { if(!netif_queue_stopped(dev)) { netif_carrier_off(dev); netif_stop_queue(dev); } status = STATUS_FAILURE; goto exit_path; } BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Packet size : %d\n", skb->len); /*Add Ethernet CS check here*/ if(Adapter->TransferMode == IP_PACKET_ONLY_MODE ) { pkt_type = ntohs(*(PUSHORT)(skb->data + 12)); /* Get the queue index where the packet is to be queued */ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Getting the Queue Index....."); qindex = GetPacketQueueIndex(Adapter,skb); if((SHORT)INVALID_QUEUE_INDEX==(SHORT)qindex) { if(pkt_type == ETH_ARP_FRAME) { /* Reply directly to ARP request packet ARP Spoofing only if NO ETH CS rule matches for it */ BCM_DEBUG_PRINT (Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,"ARP OPCODE = %02x", (*(PUCHAR)(skb->data + 21))); reply_to_arp_request(skb); BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX,TX_OSAL_DBG, DBG_LVL_ALL,"After reply_to_arp_request \n"); } else { BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Invalid queue index, dropping pkt\n"); status = STATUS_FAILURE; } goto exit_path; } if(Adapter->PackInfo[qindex].uiCurrentPacketsOnHost >= SF_MAX_ALLOWED_PACKETS_TO_BACKUP) { atomic_inc(&Adapter->TxDroppedPacketCount); status = STATUS_FAILURE; goto exit_path; } /* Now Enqueue the packet */ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "bcm_transmit Enqueueing the Packet To Queue %d",qindex); spin_lock(&Adapter->PackInfo[qindex].SFQueueLock); Adapter->PackInfo[qindex].uiCurrentBytesOnHost += skb->len; Adapter->PackInfo[qindex].uiCurrentPacketsOnHost++; *((B_UINT32 *)skb->cb + SKB_CB_LATENCY_OFFSET ) = jiffies; ENQUEUEPACKET(Adapter->PackInfo[qindex].FirstTxQueue, Adapter->PackInfo[qindex].LastTxQueue, skb); atomic_inc(&Adapter->TotalPacketCount); spin_unlock(&Adapter->PackInfo[qindex].SFQueueLock); do_gettimeofday(&tv); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,"ENQ: \n"); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Pkt Len = %d, sec: %ld, usec: %ld\n", (skb->len-ETH_HLEN), tv.tv_sec, tv.tv_usec); #ifdef BCM_SHM_INTERFACE spin_lock(&Adapter->txtransmitlock); if(Adapter->txtransmit_running == 0) { Adapter->txtransmit_running = 1; calltransmit = 1; } else calltransmit = 0; spin_unlock(&Adapter->txtransmitlock); #endif if(calltransmit == 1) transmit_packets(Adapter); else { if(!atomic_read(&Adapter->TxPktAvail)) { atomic_set(&Adapter->TxPktAvail, 1); #ifdef BCM_SHM_INTERFACE virtual_mail_box_interrupt(); #endif wake_up(&Adapter->tx_packet_wait_queue); } } BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "<===="); } else status = STATUS_FAILURE; exit_path: if(status != STATUS_SUCCESS) bcm_kfree_skb(skb); /* It is expected to return the correct status if running in cut-through mode */ if(Adapter->bNetworkInterfaceRegistered == FALSE) return status; /* It is expected to return as Success for Network Stack - This will ensure that the packet is owned by the driver which shall free the same*/ else return STATUS_SUCCESS; }
/** @ingroup tx_functions This function despatches the IP packets with the given vcid to the target via the host h/w interface. @return zero(success) or -ve value(failure) */ INT SetupNextSend(PMINI_ADAPTER Adapter, /**<Logical Adapter*/ struct sk_buff *Packet, /**<data buffer*/ USHORT Vcid) /**<VCID for this packet*/ { int status=0; #ifdef GDMA_INTERFACE int dontfree = 0; #endif BOOLEAN bHeaderSupressionEnabled = FALSE; B_UINT16 uiClassifierRuleID; int QueueIndex = NO_OF_QUEUES + 1; B_UINT32 time_spent_on_host = 0 ; if(!Adapter || !Packet) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Got NULL Adapter or Packet"); return -EINVAL; } if(Packet->len > MAX_DEVICE_DESC_SIZE) { status = STATUS_FAILURE; goto errExit; } /* Get the Classifier Rule ID */ uiClassifierRuleID = *((UINT32*) (Packet->cb)+SKB_CB_CLASSIFICATION_OFFSET); QueueIndex = SearchVcid( Adapter,Vcid); if(QueueIndex < NO_OF_QUEUES) { bHeaderSupressionEnabled = Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled; bHeaderSupressionEnabled = bHeaderSupressionEnabled & Adapter->bPHSEnabled; } if(Adapter->device_removed) { status = STATUS_FAILURE; goto errExit; } status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled, (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport); if(status != STATUS_SUCCESS) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n"); goto errExit; } Leader.Vcid = Vcid; if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET )) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Sending TCP ACK\n"); Leader.Status = LEADER_STATUS_TCP_ACK; } else { Leader.Status = LEADER_STATUS; } if(Adapter->PackInfo[QueueIndex].bEthCSSupport) { Leader.PLength = Packet->len; if(skb_headroom(Packet) < LEADER_SIZE) { if((status = skb_cow(Packet,LEADER_SIZE))) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"bcm_transmit : Failed To Increase headRoom\n"); goto errExit; } } skb_push(Packet, LEADER_SIZE); memcpy(Packet->data, &Leader, LEADER_SIZE); } else { Leader.PLength = Packet->len - ETH_HLEN; memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE); } BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Packet->len = %d", Packet->len); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Vcid = %d", Vcid); #ifndef BCM_SHM_INTERFACE status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter, Packet->data, (Leader.PLength + LEADER_SIZE)); #else status = tx_pkts_to_firmware(Packet,Packet->len,0); #endif if(status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Tx Failed..\n"); } else { Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength; atomic_add(Leader.PLength, &Adapter->GoodTxByteCount); atomic_inc(&Adapter->TxTotalPacketCount); #ifdef GDMA_INTERFACE dontfree = 1; #endif } time_spent_on_host = jiffies - *((UINT32*) (Packet->cb) + SKB_CB_LATENCY_OFFSET); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_TIME_SPENT_IN_HOST, DBG_LVL_ALL, "TIME SPENT ON HOST :%#X \n",time_spent_on_host); atomic_dec(&Adapter->CurrNumFreeTxDesc); errExit: if(STATUS_SUCCESS == status) { Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3; Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len); Adapter->PackInfo[QueueIndex].uiSentPackets++; Adapter->PackInfo[QueueIndex].NumOfPacketsSent++; atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount); #ifdef BCM_SHM_INTERFACE if(atomic_read(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount) < 0) { atomic_set(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount, 0); } #endif Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength; } #ifdef GDMA_INTERFACE if(!dontfree){ bcm_kfree_skb(Packet); } #else bcm_kfree_skb(Packet); #endif return status; }