static BOOLEAN IsValidHashInfo(ULONG HashInformation) { #define HASH_FLAGS_COMBINATION(Type, Flags) ( ((Type) & (Flags)) && !((Type) & ~(Flags)) ) ULONG ulHashType = NDIS_RSS_HASH_TYPE_FROM_HASH_INFO(HashInformation); ULONG ulHashFunction = NDIS_RSS_HASH_FUNC_FROM_HASH_INFO(HashInformation); if (HashInformation == 0) return TRUE; if (HASH_FLAGS_COMBINATION(ulHashType, NDIS_HASH_IPV4 | NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 | NDIS_HASH_TCP_IPV6 | NDIS_HASH_IPV6_EX | NDIS_HASH_TCP_IPV6_EX)) return ulHashFunction == NdisHashFunctionToeplitz; return FALSE; }
NDIS_STATUS xmpSetInformation( IN xmpNicCtx_t *pNicCtx, IN PNDIS_OID_REQUEST NdisRequest ) { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; NDIS_OID Oid; PVOID InformationBuffer; ULONG InformationBufferLength; ULONG BytesRead; ULONG BytesNeeded; ULONG PacketFilter; ULONG MCastCnt; ULONG HashType; ULONG validBits; USHORT i; xge_hal_device_t *pHalDev; NDIS_RECEIVE_SCALE_PARAMETERS *pRssParam; xmpSetRssContext SetRssCtx = {0}; static ULONG setRssCount = 10; pHalDev = XMP_NIC_GET_DEV(pNicCtx); Oid = NdisRequest->DATA.SET_INFORMATION.Oid; InformationBuffer = NdisRequest->DATA.SET_INFORMATION.InformationBuffer; InformationBufferLength = NdisRequest->DATA.SET_INFORMATION.InformationBufferLength; XMPTRACE(XMP_DBG_REQ, ("==> xmpSetInformation %x\n", Oid)); BytesRead = 0; BytesNeeded = 0; switch(Oid) { case OID_802_3_MULTICAST_LIST: XMPTRACE(XMP_DBG_REQ, ("xmpSetInformation Multicast list\n")); if ( InformationBufferLength % ETH_LENGTH_OF_ADDRESS != 0 ) return(NDIS_STATUS_INVALID_LENGTH); MCastCnt = InformationBufferLength / ETH_LENGTH_OF_ADDRESS; xmpHalMcastFilterClr(pNicCtx); Status = xmpHalSetMcastList(pNicCtx, (UCHAR *) InformationBuffer, &MCastCnt); BytesRead = MCastCnt * ETH_LENGTH_OF_ADDRESS; break; case OID_GEN_CURRENT_PACKET_FILTER: XMPTRACE(XMP_DBG_REQ, ("xmpSetInformation: packet filter\n")); if ( InformationBufferLength != sizeof (ULONG) ) return ( NDIS_STATUS_INVALID_LENGTH ); BytesRead = InformationBufferLength; PacketFilter = *((PULONG) InformationBuffer); Status = xmpSetFilter(pNicCtx, PacketFilter); break; case OID_GEN_CURRENT_LOOKAHEAD: XMPTRACE(XMP_DBG_REQ, ("xmpSetInformation: current lookahead\n")); if( InformationBufferLength < sizeof(ULONG) ) { BytesNeeded = sizeof(ULONG); Status = NDIS_STATUS_INVALID_LENGTH; break; } pNicCtx->LookAheadSz = *((PULONG) InformationBuffer); BytesRead = sizeof(ULONG); Status = NDIS_STATUS_SUCCESS; break; case OID_GEN_RECEIVE_SCALE_PARAMETERS: XMPTRACE(XMP_DBG_INFO, ("xmpSetInformation: OID_GEN_RECEIVE_SCALE_PARAMETERS\n")); if ( !(XMP_NIC_RSS_IN_CONFIG(pNicCtx)) ) { Status = NDIS_STATUS_NOT_SUPPORTED; break; } if ( InformationBufferLength < sizeof(NDIS_RECEIVE_SCALE_PARAMETERS) ) { BytesNeeded = sizeof(NDIS_RECEIVE_SCALE_PARAMETERS); Status = NDIS_STATUS_INVALID_LENGTH; break; } pRssParam = (PNDIS_RECEIVE_SCALE_PARAMETERS)InformationBuffer; #ifdef NDISTEST_BUG if ( !XENAMP_NDIS_OBJECT_VALID(&pRssParam->Header, NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_1, NDIS_OBJECT_TYPE_RSS_PARAMETERS, sizeof(NDIS_RECEIVE_SCALE_PARAMETERS)) ) { XMPTRACE(XMP_DBG_WRN, ("xmpSetInformation:RSS_PARAMETERS invalid!!" " Revision=%d Type=%d Size=%d\n", pRssParam->Header.Revision, pRssParam->Header.Type, pRssParam->Header.Size)); BytesRead = sizeof(NDIS_OBJECT_HEADER); Status = NDIS_STATUS_INVALID_PARAMETER; break; } #endif BytesRead = sizeof(NDIS_RECEIVE_SCALE_PARAMETERS); if ( (InformationBufferLength < (pRssParam->IndirectionTableSize + pRssParam->IndirectionTableOffset)) || (InformationBufferLength < (pRssParam->HashSecretKeySize + pRssParam->HashSecretKeyOffset)) ) { BytesNeeded = sizeof(NDIS_RECEIVE_SCALE_PARAMETERS); Status = NDIS_STATUS_INVALID_LENGTH; break; } HashType = NDIS_RSS_HASH_TYPE_FROM_HASH_INFO(pRssParam->HashInformation); /*if ( HashType != 0 || NDIS_RSS_HASH_FUNC_FROM_HASH_INFO(pRssParam->HashInformation) != 0) */ validBits = (NDIS_HASH_IPV4 | NDIS_HASH_TCP_IPV4 #ifndef XMP_RSS_IPV4_ONLY | NDIS_HASH_IPV6 | NDIS_HASH_TCP_IPV6 | NDIS_HASH_IPV6_EX | NDIS_HASH_TCP_IPV6_EX #endif ); if ( ((NDIS_RSS_HASH_FUNC_FROM_HASH_INFO(pRssParam->HashInformation) != NdisHashFunctionToeplitz) || /* the only hash function supported */ !bit(HashType, validBits) || /* at least one type should be set */ (HashType & ~validBits)) && /* no other type should be set */ (!(bit(pRssParam->Flags, NDIS_RSS_PARAM_FLAG_DISABLE_RSS)) && NDIS_RSS_HASH_FUNC_FROM_HASH_INFO(pRssParam->HashInformation) != 0) ) { Status = NDIS_STATUS_INVALID_PARAMETER; break; } if ( /*(pRssParam->IndirectionTableSize < (1 << pRssParam->NumberOfLsbs)) || */ (pRssParam->HashSecretKeySize & 0x7) || /* must be 8-bytes align */ (pRssParam->HashSecretKeySize > 40) || /* max secret key size */ (pRssParam->BaseCpuNumber & (pRssParam->BaseCpuNumber - 1)) )/*pow2 */ { XMPTRACE(XMP_DBG_WRN, ("xmpReqSetRss:Invalid settings: Key Size=%d" " IDT size=%d BaseCpu=%d\n", pRssParam->HashSecretKeySize, pRssParam->IndirectionTableSize, pRssParam->BaseCpuNumber)); Status = NDIS_STATUS_INVALID_PARAMETER; break; } if ((pRssParam->IndirectionTableSize + pRssParam->IndirectionTableOffset) > (pRssParam->HashSecretKeySize + pRssParam->HashSecretKeyOffset)) BytesRead = (pRssParam->IndirectionTableSize + pRssParam->IndirectionTableOffset); else BytesRead = (pRssParam->HashSecretKeySize + pRssParam->HashSecretKeyOffset); SetRssCtx.pNicCtx = pNicCtx; SetRssCtx.pParams = pRssParam; #if 0 if(NdisMSynchronizeWithInterruptEx(pNicCtx->hInterrupt, 0, xmpReqSetRss, &SetRssCtx)) #endif if ( NDIS_RSS_HASH_FUNC_FROM_HASH_INFO(pRssParam->HashInformation) == 0 ) bis(pRssParam->Flags, NDIS_RSS_PARAM_FLAG_DISABLE_RSS); if ( bit(pRssParam->Flags, NDIS_RSS_PARAM_FLAG_DISABLE_RSS) ) { pNicCtx->ndisRssSet.size = sizeof(NDIS_RECEIVE_SCALE_PARAMETERS); pNicCtx->ndisRssSet.params.BaseCpuNumber = 0; pNicCtx->ndisRssSet.params.Flags = 0; pNicCtx->ndisRssSet.params.HashInformation = 0; pNicCtx->ndisRssSet.params.IndirectionTableSize = 0; pNicCtx->ndisRssSet.params.IndirectionTableOffset = 0; pNicCtx->ndisRssSet.params.HashSecretKeySize = 0; pNicCtx->ndisRssSet.params.HashSecretKeyOffset = 0; } else { NdisMoveMemory(&pNicCtx->ndisRssSet.params, pRssParam, BytesRead); pNicCtx->ndisRssSet.size = BytesRead; } xmpReqSetRss(pNicCtx); #if 0 if ( !(setRssCount % 10) ) { xmpReqSetRss(pNicCtx); } setRssCount++; #endif Status = NDIS_STATUS_SUCCESS; break; case OID_OFFLOAD_ENCAPSULATION: XMPTRACE(XMP_DBG_OFLD, ("xmpSetInformation: offload encapsulation\n")); if ( InformationBufferLength < sizeof(NDIS_OFFLOAD_ENCAPSULATION) ) { BytesNeeded = sizeof(NDIS_OFFLOAD_ENCAPSULATION); Status = NDIS_STATUS_INVALID_LENGTH; break; } NdisMoveMemory(&pNicCtx->OffloadEncapsulation, InformationBuffer, sizeof(NDIS_OFFLOAD_ENCAPSULATION)); BytesRead = sizeof(NDIS_OFFLOAD_ENCAPSULATION); Status = NDIS_STATUS_SUCCESS; break; case OID_GEN_INTERRUPT_MODERATION: { NDIS_INTERRUPT_MODERATION_PARAMETERS *pIntrModr; if ( InformationBufferLength < sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS) ) { BytesNeeded = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS); Status = NDIS_STATUS_INVALID_LENGTH; break; } pIntrModr = (NDIS_INTERRUPT_MODERATION_PARAMETERS *) InformationBuffer; if ( !XENAMP_NDIS_OBJECT_VALID(&pIntrModr->Header, NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1, NDIS_OBJECT_TYPE_DEFAULT, sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS)) ) { BytesRead = sizeof(NDIS_OBJECT_HEADER); Status = NDIS_STATUS_INVALID_DATA; break; } break; } case OID_TCP_OFFLOAD_PARAMETERS: { NDIS_OFFLOAD_PARAMETERS *pAdmin; NDIS_STATUS_INDICATION StatusIndication; ULONG size; pAdmin = (NDIS_OFFLOAD_PARAMETERS *) InformationBuffer; if ( InformationBufferLength < NDIS_SIZEOF_OFFLOAD_PARAMETERS_REVISION_1 ) { BytesNeeded = NDIS_SIZEOF_OFFLOAD_PARAMETERS_REVISION_1; Status = NDIS_STATUS_INVALID_LENGTH; break; } if ( !XENAMP_NDIS_OBJECT_VALID(&pAdmin->Header, NDIS_OFFLOAD_PARAMETERS_REVISION_1, NDIS_OBJECT_TYPE_DEFAULT, NDIS_SIZEOF_OFFLOAD_PARAMETERS_REVISION_1 )) { BytesRead = sizeof(NDIS_OBJECT_HEADER); Status = NDIS_STATUS_INVALID_DATA; break; } XMP_NIC_SET_ADMIN_OFFLOADS(pNicCtx, pAdmin); xmpNicSetCkoFlags(pNicCtx); xmpNicInitOffloadCapabilities(pNicCtx, &pNicCtx->OffloadCapabilities); /* TODO: Generate event */ BytesRead = NDIS_SIZEOF_OFFLOAD_PARAMETERS_REVISION_1; Status = NDIS_STATUS_SUCCESS; XENAMP_NDIS_OBJECT_INIT(&StatusIndication.Header, NDIS_OBJECT_TYPE_STATUS_INDICATION, NDIS_STATUS_INDICATION_REVISION_1, sizeof(NDIS_STATUS_INDICATION)); StatusIndication.SourceHandle = pNicCtx->hMPAdapter; StatusIndication.PortNumber = 0; StatusIndication.StatusCode = NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG; StatusIndication.Flags = 0; StatusIndication.DestinationHandle = NULL; StatusIndication.RequestId = NdisRequest->RequestId; StatusIndication.StatusBuffer = &pNicCtx->OffloadCapabilities; StatusIndication.StatusBufferSize = sizeof(NDIS_OFFLOAD); NdisMIndicateStatusEx(pNicCtx->hMPAdapter, &StatusIndication); } break; case OID_GEN_HD_SPLIT_PARAMETERS: { NDIS_HD_SPLIT_PARAMETERS *pHdSplit; pHdSplit = (NDIS_HD_SPLIT_PARAMETERS *) InformationBuffer; if ( InformationBufferLength < NDIS_SIZEOF_HD_SPLIT_PARAMETERS_REVISION_1 ) { BytesNeeded = NDIS_SIZEOF_HD_SPLIT_PARAMETERS_REVISION_1; Status = NDIS_STATUS_INVALID_LENGTH; break; } if ( !XENAMP_NDIS_OBJECT_VALID(&pHdSplit->Header, NDIS_HD_SPLIT_PARAMETERS_REVISION_1, NDIS_OBJECT_TYPE_DEFAULT, NDIS_SIZEOF_HD_SPLIT_PARAMETERS_REVISION_1 )) { BytesRead = sizeof(NDIS_OBJECT_HEADER); Status = NDIS_STATUS_INVALID_DATA; break; } if( bit(pHdSplit->HDSplitCombineFlags, NDIS_HD_SPLIT_COMBINE_ALL_HEADERS) ) bis( pNicCtx->Flags, XMP_NIC_FLAGS_RX_SPLIT_COMBINE ); else bic( pNicCtx->Flags, XMP_NIC_FLAGS_RX_SPLIT_COMBINE ); } break; default: XMPTRACE(XMP_DBG_INFO, ("xmpSetInformation: unsupported OID=%lx\n", Oid)); Status = xmpDiagSetInformation( pNicCtx, Oid, InformationBuffer, InformationBufferLength, &BytesRead, &BytesNeeded); break; } NdisRequest->DATA.SET_INFORMATION.BytesRead = BytesRead; NdisRequest->DATA.SET_INFORMATION.BytesNeeded = BytesNeeded; XMPTRACE(XMP_DBG_REQ, ("<== xmpSetInformation: Status=%x\n", Status)); return Status; }
BOOLEAN xmpReqSetRss( __in NDIS_HANDLE SynchronizeContext ) { USHORT i; UCHAR *pSecretKey; UCHAR *pTable; BOOLEAN bTable, bKey, bCpu, bHashInfo; BOOLEAN bQueue = FALSE; KIRQL OldIrql; xmpNicCtx_t *pNicCtx = SynchronizeContext; NDIS_RECEIVE_SCALE_PARAMETERS *pParams = &pNicCtx->ndisRssSet.params; static int count = 0; XMPTRACE(XMP_DBG_WRN, ("==> xmpReqSetRss Count = %d Flags = 0x%8.8lx\n", ++count, pParams->Flags)); XF_GET_SLOCK(&pNicCtx->lock); pSecretKey = ((UCHAR *) pParams) + pParams->HashSecretKeyOffset; pTable = ((UCHAR *) pParams) + pParams->IndirectionTableOffset; bTable = bKey = bCpu = bHashInfo = FALSE; if ( XMP_NIC_RSS_IS_ENABLED(pNicCtx) && !(bit(pParams->Flags, NDIS_RSS_PARAM_FLAG_DISABLE_RSS)) ) { if ( !(bit(pParams->Flags, NDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED)) ) bKey = TRUE; if ( !(bit(pParams->Flags, NDIS_RSS_PARAM_FLAG_ITABLE_UNCHANGED)) ) bTable = TRUE; if ( !(bit(pParams->Flags, NDIS_RSS_PARAM_FLAG_BASE_CPU_UNCHANGED )) ) bCpu = TRUE; } else { bTable = bKey = bCpu = bHashInfo = TRUE; pNicCtx->RssParamsReq.HashFunction = 0; } /* Enable RTH_CFG, RTS_ENHANCED and RMAC_STRIP_FCS to 0 */ if ( bHashInfo ) { pNicCtx->RssParamsReq.HashType = NDIS_RSS_HASH_TYPE_FROM_HASH_INFO(pParams->HashInformation); pNicCtx->RssParamsReq.HashFunction = NDIS_RSS_HASH_FUNC_FROM_HASH_INFO(pParams->HashInformation); } if ( NDIS_RSS_HASH_FUNC_FROM_HASH_INFO(pParams->HashInformation) != 0 ) { if( bCpu ) pNicCtx->RssParamsReq.BaseCpuNum = pParams->BaseCpuNumber; if ( bTable ) { pNicCtx->RssParamsReq.TableSz = pParams->IndirectionTableSize > XMP_NIC_RSS_MAX_TABLE_SZ ? XMP_NIC_RSS_MAX_TABLE_SZ : pParams->IndirectionTableSize; { ULONG TableSz = pNicCtx->RssParamsReq.TableSz; USHORT NumLsbs = 0; while (TableSz != 1) { TableSz = TableSz>>1; NumLsbs++; } pNicCtx->RssParamsReq.HashBitsSz = NumLsbs; } NdisMoveMemory(pNicCtx->RssParamsReq.Table, pTable, pNicCtx->RssParamsReq.TableSz); } if ( bKey ) { pNicCtx->RssParamsReq.SecretKeySz = pParams->HashSecretKeySize; NdisMoveMemory(pNicCtx->RssParamsReq.SecretKey, pSecretKey, pNicCtx->RssParamsReq.SecretKeySz); } } pNicCtx->RssParamsReq.Flags = pParams->Flags; KeMemoryBarrier(); if ( !pNicCtx->wiQueued ) { pNicCtx->wiQueued = TRUE; if ( !pNicCtx->wiRunning ) bQueue = TRUE; } XF_FREE_SLOCK(&pNicCtx->lock); #ifdef XMP_SET_RSS_IN_WORKER if ( bQueue ) NdisQueueIoWorkItem(pNicCtx->hSetRssWI, (NDIS_IO_WORKITEM_ROUTINE)xmpNicSetRssParameters, pNicCtx); #else xmpNicSetRssParameters(pNicCtx, NULL); #endif XMPTRACE(XMP_DBG_WRN, ("<== xmpReqSetRss\n")); return TRUE; }