From 88b9c87a72360abe56ec9d5d17b30759a5ef5951 Mon Sep 17 00:00:00 2001 From: tzachid Date: Tue, 26 Aug 2008 17:37:19 +0000 Subject: [PATCH] [ipoib] Add support for large send offload in ipoib. (mlnx 3044) git-svn-id: svn://openib.tc.cornell.edu/gen1@1515 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86 --- trunk/inc/kernel/ip_packet.h | 9 + trunk/ulp/ipoib/kernel/ipoib_adapter.h | 10 + trunk/ulp/ipoib/kernel/ipoib_driver.c | 42 +++- trunk/ulp/ipoib/kernel/ipoib_port.c | 284 ++++++++++++++++++++++--- trunk/ulp/ipoib/kernel/ipoib_port.h | 18 +- trunk/ulp/ipoib/kernel/offload.h | 47 ++++ 6 files changed, 376 insertions(+), 34 deletions(-) create mode 100644 trunk/ulp/ipoib/kernel/offload.h diff --git a/trunk/inc/kernel/ip_packet.h b/trunk/inc/kernel/ip_packet.h index cb887b7a..d8f08c8a 100644 --- a/trunk/inc/kernel/ip_packet.h +++ b/trunk/inc/kernel/ip_packet.h @@ -356,6 +356,15 @@ typedef struct _udp_hdr *********/ #include +#define IP_HEADER_LENGTH(pIpHdr) \ + ( (ULONG)((pIpHdr->ver_hl & 0x0F) << 2) ) + +#define TCP_HEADER_LENGTH(pTcpHdr) \ + ((pTcpHdr->offset & 0xF0) >> 2) + +#define PROTOCOL_TCP 6 + + #define IGMP_V2_MEMBERSHIP_QUERY 0x11 #define IGMP_V2_MEMBERSHIP_REPORT 0x16 #define IGMP_V1_MEMBERSHIP_REPORT 0x12 // for backward compatibility with IGMPv1 diff --git a/trunk/ulp/ipoib/kernel/ipoib_adapter.h b/trunk/ulp/ipoib/kernel/ipoib_adapter.h index c23a342a..d59e958f 100644 --- a/trunk/ulp/ipoib/kernel/ipoib_adapter.h +++ b/trunk/ulp/ipoib/kernel/ipoib_adapter.h @@ -73,6 +73,7 @@ typedef struct _ipoib_params uint32_t sa_retry_cnt; uint32_t recv_pool_ratio; uint32_t payload_mtu; + boolean_t lso; uint32_t xfer_block_size; mac_addr_t conf_mac; uint32_t mc_leave_rescan; @@ -120,6 +121,15 @@ typedef struct _ipoib_params * powers of 2, excluding 1. When zero, grows only when the pool is * exhausted. Other values indicate fractional values * (i.e. 2 indicates 1/2, 4 indicates 1/4, etc.) +* +* payload_mtu +* The maximum available size of IPoIB transfer unit. +* It should be lower by size of IPoIB header (==4B) +* For example, if the HCA support 4K MTU, +* upper threshold for payload mtu is 4092B and not 4096B +* lso +* It indicates if there's a support for hardware large/giant send offload +* *********/ diff --git a/trunk/ulp/ipoib/kernel/ipoib_driver.c b/trunk/ulp/ipoib/kernel/ipoib_driver.c index 3d1056ff..0cbf2839 100644 --- a/trunk/ulp/ipoib/kernel/ipoib_driver.c +++ b/trunk/ulp/ipoib/kernel/ipoib_driver.c @@ -50,6 +50,8 @@ #include #include "ntstrsafe.h" #include "strsafe.h" +#include + @@ -154,6 +156,7 @@ IPOIB_REG_ENTRY HCARegTable[] = { {NDIS_STRING_CONST("SaRetries"), 1, IPOIB_OFFSET(sa_retry_cnt), IPOIB_SIZE(sa_retry_cnt), 10, 1, UINT_MAX}, {NDIS_STRING_CONST("RecvRatio"), 1, IPOIB_OFFSET(recv_pool_ratio), IPOIB_SIZE(recv_pool_ratio), 1, 1, 10}, {NDIS_STRING_CONST("PayloadMtu"), 1, IPOIB_OFFSET(payload_mtu), IPOIB_SIZE(payload_mtu), 2044, 60, 4092}, + {NDIS_STRING_CONST("lso"), 0, IPOIB_OFFSET(lso), IPOIB_SIZE(lso), 0, 0, 1}, {NDIS_STRING_CONST("MCLeaveRescan"), 1, IPOIB_OFFSET(mc_leave_rescan), IPOIB_SIZE(mc_leave_rescan), 260, 1, 3600} }; @@ -848,6 +851,9 @@ ipoib_check_for_hang( IPOIB_EXIT( IPOIB_DBG_INIT ); return FALSE; } + if (p_adapter->hung) { + ipoib_resume_oids(p_adapter); + } IPOIB_EXIT( IPOIB_DBG_INIT ); return (p_adapter->hung? TRUE:FALSE); @@ -1405,6 +1411,8 @@ __ipoib_get_tcp_task_offload( NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr; NDIS_TASK_OFFLOAD *p_offload_task; NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum; + + NDIS_TASK_TCP_LARGE_SEND *p_offload_lso; ULONG buf_len; IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, @@ -1413,7 +1421,10 @@ __ipoib_get_tcp_task_offload( buf_len = sizeof(NDIS_TASK_OFFLOAD_HEADER) + offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) + - sizeof(NDIS_TASK_TCP_IP_CHECKSUM); + sizeof(NDIS_TASK_TCP_IP_CHECKSUM) + + (p_adapter->params.lso ? + sizeof(NDIS_TASK_OFFLOAD) + sizeof(NDIS_TASK_TCP_LARGE_SEND) + : 0); *(p_oid_info->p_bytes_needed) = buf_len; @@ -1472,6 +1483,33 @@ __ipoib_get_tcp_task_offload( p_offload_chksum->V6Receive.TcpChecksum = FALSE; p_offload_chksum->V6Receive.UdpChecksum = FALSE; + + if (p_adapter->params.lso) { + // set the previous pointer to the correct place + p_offload_task->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + + p_offload_task->TaskBufferLength; + // set the LSO packet + p_offload_task = (PNDIS_TASK_OFFLOAD) + ((PUCHAR)p_offload_task + p_offload_task->OffsetNextTask); + + p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION; + p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD); + p_offload_task->Task = TcpLargeSendNdisTask; + p_offload_task->OffsetNextTask = 0; + p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND); + + p_offload_lso = (PNDIS_TASK_TCP_LARGE_SEND) p_offload_task->TaskBuffer; + + p_offload_lso->Version = 0; + //TODO optimal size: 60000, 64000 or 65536 + //TODO LSO_MIN_SEG_COUNT to be 1 + p_offload_lso->MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; +#define LSO_MIN_SEG_COUNT 2 + p_offload_lso->MinSegmentCount = LSO_MIN_SEG_COUNT; + p_offload_lso->TcpOptions = TRUE; + p_offload_lso->IpOptions = TRUE; + } + *(p_oid_info->p_bytes_used) = buf_len; return NDIS_STATUS_SUCCESS; @@ -1878,7 +1916,7 @@ ipoib_send_packets( for( packet_num = 0; packet_num < num_packets; ++packet_num ) { ipoib_inc_send_stat( p_adapter, IP_STAT_DROPPED, 0 ); - NdisMSendComplete( p_adapter->h_adapter, + NdisMSendCompleteX( p_adapter->h_adapter, packet_array[packet_num], NDIS_STATUS_ADAPTER_NOT_READY ); } IPOIB_EXIT( IPOIB_DBG_SEND ); diff --git a/trunk/ulp/ipoib/kernel/ipoib_port.c b/trunk/ulp/ipoib/kernel/ipoib_port.c index ad772edb..2799cb6b 100644 --- a/trunk/ulp/ipoib/kernel/ipoib_port.c +++ b/trunk/ulp/ipoib/kernel/ipoib_port.c @@ -42,6 +42,7 @@ #endif #include "ipoib_port.tmh" #endif +#include /* Amount of physical memory to register. */ @@ -281,7 +282,8 @@ __send_mgr_destroy( static NDIS_STATUS __send_gen( IN ipoib_port_t* const p_port, - IN ipoib_send_desc_t* const p_desc ); + IN ipoib_send_desc_t* const p_desc, + IN INT lso_data_index); static NDIS_STATUS __send_mgr_filter_ip( @@ -334,6 +336,14 @@ __send_cb( IN const ib_cq_handle_t h_cq, IN void *cq_context ); +static NDIS_STATUS GetLsoHeaderSize( + IN ipoib_port_t* const pPort, + IN PNDIS_BUFFER CurrBuffer, + IN LsoData *pLsoData, + OUT uint16_t *pSize, + OUT INT *IndexOfData, + IN ipoib_hdr_t *ipoib_hdr + ); /****************************************************************************** * @@ -2679,7 +2689,7 @@ __pending_list_destroy( p_item = cl_qlist_remove_head( &p_port->send_mgr.pending_list ) ) { p_packet = IPOIB_PACKET_FROM_LIST_ITEM( p_item ); - NdisMSendComplete( p_port->p_adapter->h_adapter, p_packet, + NdisMSendCompleteX( p_port->p_adapter->h_adapter, p_packet, NDIS_STATUS_RESET_IN_PROGRESS ); } cl_spinlock_release( &p_port->send_lock ); @@ -2740,7 +2750,7 @@ __send_mgr_filter( * Just send the payload and hope for the best. */ cl_perf_start( SendGen ); - status = __send_gen( p_port, p_desc ); + status = __send_gen( p_port, p_desc, 0 ); cl_perf_stop( &p_port->p_adapter->perf, SendGen ); break; } @@ -2967,7 +2977,8 @@ __send_gen( static NDIS_STATUS __send_gen( IN ipoib_port_t* const p_port, - IN ipoib_send_desc_t* const p_desc ) + IN ipoib_send_desc_t* const p_desc, + IN INT lso_data_index) { ib_api_status_t status; SCATTER_GATHER_LIST *p_sgl; @@ -3007,9 +3018,13 @@ __send_gen( * or part of it. */ i = 0; - while( offset ) + if (lso_data_index) { //we have an LSO packet + i = lso_data_index; + j = 0; + } + else while( offset ) { - if( p_sgl->Elements[i].Length <= sizeof(eth_hdr_t) ) + if( p_sgl->Elements[i].Length <= offset ) { offset -= p_sgl->Elements[i++].Length; } @@ -3117,7 +3132,7 @@ __send_mgr_filter_ip( } /* Not a UDP packet. */ cl_perf_start( SendTcp ); - status = __send_gen( p_port, p_desc ); + status = __send_gen( p_port, p_desc,0 ); cl_perf_stop( &p_port->p_adapter->perf, SendTcp ); IPOIB_EXIT( IPOIB_DBG_SEND ); return status; @@ -3316,7 +3331,7 @@ __send_mgr_filter_udp( { /* Not a DHCP packet. */ cl_perf_start( SendUdp ); - status = __send_gen( p_port, p_desc ); + status = __send_gen( p_port, p_desc,0 ); cl_perf_stop( &p_port->p_adapter->perf, SendUdp ); IPOIB_EXIT( IPOIB_DBG_SEND ); return status; @@ -3758,6 +3773,14 @@ __build_send_desc( int32_t hdr_idx; PNDIS_PACKET_EXTENSION PktExt; PNDIS_TCP_IP_CHECKSUM_PACKET_INFO pChecksumPktInfo; //NDIS 5.1 + ULONG mss; + LsoData TheLsoData; + INT IndexOfData = 0; + ULONG PhysBufCount; + ULONG PacketLength; + PNDIS_BUFFER FirstBuffer; + uint16_t lso_header_size; + PERF_DECLARE( SendMgrFilter ); @@ -3765,15 +3788,12 @@ __build_send_desc( /* Format the send descriptor. */ cl_perf_start( SendMgrFilter ); - status = __send_mgr_filter( - p_port, p_eth_hdr, p_buf, buf_len, p_desc ); - cl_perf_stop( &p_port->p_adapter->perf, SendMgrFilter ); - if( status != NDIS_STATUS_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__send_mgr_filter returned 0x%08X.\n", status) ); - return status; - } + + PktExt = NDIS_PACKET_EXTENSION_FROM_PACKET(p_desc->p_pkt); + pChecksumPktInfo = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&PktExt->NdisPacketInfo[TcpIpChecksumPacketInfo]; + mss = PtrToUlong(PktExt->NdisPacketInfo[TcpLargeSendPacketInfo]); + //TODO: optimization: we already got total length from NdisGetFirstBufferFromPacketSafe before + NdisQueryPacket(p_desc->p_pkt, (PUINT)&PhysBufCount, NULL, &FirstBuffer,(PUINT)&PacketLength); /* Format the send descriptor. */ hdr_idx = cl_atomic_inc( &p_port->hdr_idx ); @@ -3782,19 +3802,66 @@ __build_send_desc( p_port->hdr[hdr_idx].type = p_eth_hdr->type; p_port->hdr[hdr_idx].resv = 0; - /* Setup the first local data segment (used for the IPoIB header). */ - p_desc->local_ds[0].vaddr = cl_get_physaddr( &p_port->hdr[hdr_idx] ); - p_desc->local_ds[0].length = sizeof(ipoib_hdr_t); - p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey; + if (mss) + { + memset(&TheLsoData, 0, sizeof TheLsoData ); + status = GetLsoHeaderSize( + p_port, + FirstBuffer, + &TheLsoData, + &lso_header_size, + &IndexOfData, + &p_port->hdr[hdr_idx] + + ); + if ((status != NDIS_STATUS_SUCCESS ) || + (TheLsoData.FullBuffers != TheLsoData.UsedBuffers)) { + ASSERT(FALSE); + + IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("<-- Throwing this packet\n")); + + //NdisReleaseSpinLock(&Port->SendLock); + //MP_ASSERT_NDIS_PACKET_TYPE(Packet); + //SendComplete(Port, Packet, NDIS_STATUS_INVALID_PACKET); + //NdisAcquireSpinLock(&Port->SendLock); + //IPOIB_PRINT_EXIT + return status; + } + ASSERT(lso_header_size > 0); + p_desc->wr.dgrm.ud.mss = mss; + p_desc->wr.dgrm.ud.header = TheLsoData.LsoBuffers[0].pData; + p_desc->wr.dgrm.ud.hlen = lso_header_size; + // Tell NDIS how much we will send. + PktExt->NdisPacketInfo[TcpLargeSendPacketInfo] = UlongToPtr(PacketLength); + p_desc->wr.send_opt |= (IB_SEND_OPT_TX_IP_CSUM | IB_SEND_OPT_TX_TCP_UDP_CSUM); + __send_gen(p_port, p_desc, IndexOfData); + p_desc->wr.wr_type = ( WR_LSO | IB_SEND_OPT_SIGNALED); + } else { + + /* Setup the first local data segment (used for the IPoIB header). */ + p_desc->local_ds[0].vaddr = cl_get_physaddr( &p_port->hdr[hdr_idx] ); + p_desc->local_ds[0].length = sizeof(ipoib_hdr_t); + p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey; + + status = __send_mgr_filter( + p_port, p_eth_hdr, p_buf, buf_len, p_desc); + cl_perf_stop( &p_port->p_adapter->perf, SendMgrFilter ); + if( status != NDIS_STATUS_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__send_mgr_filter returned 0x%08X.\n", status) ); + return status; + } + p_desc->wr.wr_type = WR_SEND; + p_desc->wr.send_opt = IB_SEND_OPT_SIGNALED; + } + + /* Setup the work request. */ p_desc->wr.p_next = NULL; p_desc->wr.wr_id = (uintn_t)p_desc->p_pkt; - p_desc->wr.wr_type = WR_SEND; - p_desc->wr.send_opt = IB_SEND_OPT_SIGNALED; - - PktExt = NDIS_PACKET_EXTENSION_FROM_PACKET(p_desc->p_pkt); - pChecksumPktInfo = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&PktExt->NdisPacketInfo[TcpIpChecksumPacketInfo]; + if(p_port->p_adapter->params.send_chksum_offload & (pChecksumPktInfo->Transmit.NdisPacketChecksumV4 || pChecksumPktInfo->Transmit.NdisPacketChecksumV6)) { @@ -3836,7 +3903,7 @@ __process_failed_send( IPOIB_ENTER( IPOIB_DBG_SEND ); /* Complete the packet. */ - NdisMSendComplete( p_port->p_adapter->h_adapter, + NdisMSendCompleteX( p_port->p_adapter->h_adapter, p_desc->p_pkt, status ); ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_ERROR, 0 ); /* Deref the endpoint. */ @@ -3885,7 +3952,7 @@ ipoib_port_send( { ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_DROPPED, 0 ); /* Complete the packet. */ - NdisMSendComplete( p_port->p_adapter->h_adapter, + NdisMSendCompleteX( p_port->p_adapter->h_adapter, p_packet_array[i], NDIS_STATUS_ADAPTER_NOT_READY ); } @@ -4203,7 +4270,9 @@ __send_cb( while( p_wc ) { cl_perf_start( SendComp ); - CL_ASSERT( p_wc->status != IB_WCS_SUCCESS || p_wc->wc_type == IB_WC_SEND ); + CL_ASSERT( p_wc->status != IB_WCS_SUCCESS + || p_wc->wc_type == IB_WC_SEND + || p_wc->wc_type == IB_WC_LSO); p_packet = (NDIS_PACKET*)(uintn_t)p_wc->wr_id; CL_ASSERT( p_packet ); CL_ASSERT( IPOIB_PORT_FROM_PACKET( p_packet ) == p_port ); @@ -4241,7 +4310,7 @@ __send_cb( IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND, ("Flushed send completion.\n") ); ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_DROPPED, 0 ); - NdisMSendComplete( p_port->p_adapter->h_adapter, + NdisMSendCompleteX( p_port->p_adapter->h_adapter, p_packet, NDIS_STATUS_RESET_IN_PROGRESS ); break; @@ -4251,7 +4320,7 @@ __send_cb( p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ), (int)p_wc->vendor_specific) ); ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_ERROR, 0 ); - NdisMSendComplete( p_port->p_adapter->h_adapter, + NdisMSendCompleteX( p_port->p_adapter->h_adapter, p_packet, NDIS_STATUS_FAILURE ); break; } @@ -5945,6 +6014,159 @@ __leave_error_mcast_cb( IPOIB_EXIT( IPOIB_DBG_MCAST ); } + +NDIS_STATUS GetLsoHeaderSize( + IN ipoib_port_t* const pPort, + IN PNDIS_BUFFER CurrBuffer, + IN LsoData *pLsoData, + OUT uint16_t *pSize, + OUT INT *IndexOfData, + IN ipoib_hdr_t *ipoib_hdr + ) + { + UINT CurrLength; + PUCHAR pSrc; + PUCHAR pCopiedData = pLsoData->coppied_data; + ip_hdr_t UNALIGNED *IpHdr; + tcp_hdr_t UNALIGNED *TcpHdr; + uint16_t TcpHeaderLen; + uint16_t IpHeaderLen; + uint16_t IpOffset; + INT FullBuffers = 0; + NDIS_STATUS status = NDIS_STATUS_INVALID_PACKET; + // + // This Flag indicates the way we gets the headers + // RegularFlow = we get the headers (ETH+IP+TCP) in the same Buffer + // in sequence. + // +#define IP_OFFSET 14; + boolean_t IsRegularFlow = TRUE; + const uint16_t ETH_OFFSET = IP_OFFSET; + *pSize = 0; + UNUSED_PARAM(pPort); + IpOffset = IP_OFFSET; //(uint16_t)pPort->EncapsulationFormat.EncapsulationHeaderSize; + *IndexOfData = 0; + NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority ); + if (pSrc == NULL) { + IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Error processing packets\n")); + return status; + } + // We start by looking for the ethernet and the IP + if (CurrLength < ETH_OFFSET) { + IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Error porcessing packets\n")); + return status; + } + //*pSize = *pSize + ETH_OFFSET; + if (CurrLength == ETH_OFFSET) { + ASSERT(FALSE); + IsRegularFlow = FALSE; + memcpy(pCopiedData, pSrc, ETH_OFFSET); + pCopiedData += ETH_OFFSET; + FullBuffers++; + // First buffer was only ethernet + NdisGetNextBuffer( CurrBuffer, &CurrBuffer); + NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority ); + if (pSrc == NULL) { + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n")); + return status; + } + } else { + // This is ETH + IP together (at least) + pLsoData->LsoBuffers[0].pData = pSrc + (ETH_OFFSET - sizeof (ipoib_hdr_t)); + memcpy (pLsoData->LsoBuffers[0].pData, ipoib_hdr, sizeof (ipoib_hdr_t)); + CurrLength -= ETH_OFFSET; + pSrc = pSrc + ETH_OFFSET; + *pSize = *pSize + sizeof (ipoib_hdr_t); + } + // we should now be having at least the size of ethernet data + if (CurrLength < sizeof (ip_hdr_t)) { + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n")); + return status; + } + IpHdr = (ip_hdr_t UNALIGNED*)pSrc; + IpHeaderLen = (uint16_t)IP_HEADER_LENGTH(IpHdr); + ASSERT(IpHdr->prot == PROTOCOL_TCP); + if (CurrLength < IpHeaderLen) { + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error processing packets\n")); + return status; + } + *pSize = *pSize + IpHeaderLen; + // We now start to find where the TCP header starts + if (CurrLength == IpHeaderLen) { + ASSERT(FALSE); + // two options : + // if(IsRegularFlow = FALSE) ==> ETH and IP seperated in two buffers + // if(IsRegularFlow = TRUE ) ==> ETH and IP in the same buffer + // TCP will start at next buffer + if(IsRegularFlow){ + memcpy(pCopiedData, pSrc-ETH_OFFSET ,ETH_OFFSET+IpHeaderLen); + pCopiedData += (ETH_OFFSET + IpHeaderLen); + } else { + memcpy(pCopiedData, pSrc,IpHeaderLen); + pCopiedData += IpHeaderLen; + } + + FullBuffers++; + IsRegularFlow = FALSE; + NdisGetNextBuffer( CurrBuffer, &CurrBuffer); + NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority ); + + if (pSrc == NULL) { + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n")); + return status; + } + } else { + // if(IsRegularFlow = TRUE ) ==> the ETH and IP and TCP in the same buffer + // if(IsRegularFlow = FLASE ) ==> ETH in one buffer , IP+TCP together in the same buffer + if (IsRegularFlow) { + pLsoData->LsoBuffers[0].Len += IpHeaderLen; + } else { + memcpy(pCopiedData, pSrc, IpHeaderLen); + pCopiedData += IpHeaderLen; + } + + CurrLength -= IpHeaderLen; + pSrc = pSrc + IpHeaderLen; + } + if (CurrLength < sizeof (tcp_hdr_t)) { + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n")); + return status; + } + // We have finaly found the TCP header + TcpHdr = (tcp_hdr_t UNALIGNED *)pSrc; + TcpHeaderLen = TCP_HEADER_LENGTH(TcpHdr); + + ASSERT(TcpHeaderLen == 20); + + if (CurrLength < TcpHeaderLen) { + //IPOIB_PRINT(TRACE_LEVEL_VERBOSE, ETH, ("Error porcessing packets\n")); + return status; + } + *pSize = *pSize + TcpHeaderLen; + if(IsRegularFlow){ + pLsoData->LsoBuffers[0].Len += TcpHeaderLen; + } + else{ + memcpy(pCopiedData, pSrc, TcpHeaderLen); + pCopiedData += TcpHeaderLen; + } + if (CurrLength == TcpHeaderLen) { + FullBuffers++; + pLsoData->UsedBuffers = FullBuffers; + *IndexOfData = FullBuffers ; + } else { + pLsoData->UsedBuffers = FullBuffers + 1; + *IndexOfData = FullBuffers - 1; + } + pLsoData->FullBuffers = FullBuffers; + if (!IsRegularFlow){ + pLsoData->LsoBuffers[0].pData = pLsoData->coppied_data; + pLsoData->LsoBuffers[0].Len = ETH_OFFSET + IpHeaderLen + TcpHeaderLen; + ASSERT(pLsoData->LsoBuffers[0].Len <= LSO_MAX_HEADER); + } + return NDIS_STATUS_SUCCESS; +} + static void __port_do_mcast_garbage(ipoib_port_t* const p_port) { const mac_addr_t DEFAULT_MCAST_GROUP = {0x01, 0x00, 0x5E, 0x00, 0x00, 0x01}; diff --git a/trunk/ulp/ipoib/kernel/ipoib_port.h b/trunk/ulp/ipoib/kernel/ipoib_port.h index bc295041..4c8d6a22 100644 --- a/trunk/ulp/ipoib/kernel/ipoib_port.h +++ b/trunk/ulp/ipoib/kernel/ipoib_port.h @@ -53,7 +53,7 @@ /* Max send data segment list size. */ -#define MAX_SEND_SGE 8 +#define MAX_SEND_SGE 30 //TODO optimize this value /* @@ -626,5 +626,21 @@ inline void ipoib_port_deref( IN ipoib_port_t * p_port, IN int type); +#if DBG +// This function is only used to monitor send failures +static inline VOID NdisMSendCompleteX( + IN NDIS_HANDLE MiniportAdapterHandle, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status + ) { + if (Status != NDIS_STATUS_SUCCESS) { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Sending status other than Success to NDIS\n")); + } + NdisMSendComplete(MiniportAdapterHandle,Packet,Status); +} +#else +#define NdisMSendCompleteX NdisMSendComplete +#endif #endif /* _IPOIB_PORT_H_ */ diff --git a/trunk/ulp/ipoib/kernel/offload.h b/trunk/ulp/ipoib/kernel/offload.h new file mode 100644 index 00000000..de696c6a --- /dev/null +++ b/trunk/ulp/ipoib/kernel/offload.h @@ -0,0 +1,47 @@ +/*++ + +Copyright (c) 2005-2008 Mellanox Technologies. All rights reserved. + +Module Name: + offload.h + +Abstract: + Task offloading header file + +Revision History: + +Notes: + +--*/ + +// +// Define the maximum size of large TCP packets the driver can offload. +// This sample driver uses shared memory to map the large packets, +// LARGE_SEND_OFFLOAD_SIZE is useless in this case, so we just define +// it as NIC_MAX_PACKET_SIZE. But shipping drivers should define +// LARGE_SEND_OFFLOAD_SIZE if they support LSO, and use it as +// MaximumPhysicalMapping when they call NdisMInitializeScatterGatherDma +// if they use ScatterGather method. If the drivers don't support +// LSO, then MaximumPhysicalMapping is NIC_MAX_PACKET_SIZE. +// + +#define LSO_MAX_HEADER 136 +#define LARGE_SEND_OFFLOAD_SIZE 60000 + +// This struct is being used in order to pass data about the GSO buffers if they +// are present +typedef struct LsoBuffer_ { + PUCHAR pData; + UINT Len; +} LsoBuffer; + +typedef struct LsoData_ { + LsoBuffer LsoBuffers[1]; + UINT UsedBuffers; + UINT FullBuffers; + UINT LsoHeaderSize; + UINT IndexOfData; + UCHAR coppied_data[LSO_MAX_HEADER]; +} LsoData; + + -- 2.46.0