Hi Sam, Thanks for the clarification about the need to update the pipeline to handle NBs. I'll review the patch and get back. I don't think it is necessary to spin up a v2 patch. You can do that with any review comments I have.
I'll get back early next week. I'm on vacation today. Just wanted to let you know since Alin and you were shooting to get this in by this weekend. Thanks, -- Nithin - sent from mobile - > On Aug 22, 2014, at 11:06, "Samuel Ghinet" <sghi...@cloudbasesolutions.com> > wrote: > > Nithin, > > Regarding > "is it required to update many of the functions to process an NB instead of > an NBL" > I could try to preserve NBL wherever it was a NBL, even though the > functionality requires an NB only. > The worry I have here is, having the parameter "NET_BUFFER_LIST" gives no > assurance that it has only one NET_BUFFER - neither as inherent check, nor as > making it clear that it is so. > Using the param as NET_BUFFER struct resolves these. It makes the code > clearer, and perhaps more manageable, e.g. an "OvsGetTcp" inherently means > that it operates upon one packet buffer, while a NET_BUFFER_LIST as param > constraints the use of an OvsGetTcp call to a specific scenario / usage only. > > Regarding braces, sorry for that. It will be fixed. > > Sam > ________________________________________ > From: Nithin Raju [nit...@vmware.com] > Sent: Thursday, August 21, 2014 7:35 PM > To: Alin Serdean > Cc: dev@openvswitch.org; Samuel Ghinet > Subject: Re: [ovs-dev] [PATCH] Create a NBL for each NB when required > > hi Alin/Sam, > Like I said earlier, this is a critical fix, and thanks for working on this. > > I started looking at OvsPacketIO.c, and you are right in using the > OvsPartialCopyToMultipleNBLs() API. However, is it required to update many of > the functions to process an NB instead of an NBL? From my understanding > OvsPartialCopyToMultipleNBLs() returns you a fully formed NBL. Why cannot we > carry this through the pipeline, instead of updating the pipeline to process > NBs? > > I am yet to look at the complete patch. > > Also, I know we have been discussing about the coding style in another > thread. The new code added seems to be a little off w.r.t coding style. Eg. > if () > { > // > } > else > { > // > } > > I'll get back with more comments, but if you think some explanation for > updating the pipeline to process NB instead of NBL, pls. go ahead and provide > it. > > thanks, > Nithin > > >> On Aug 19, 2014, at 5:31 AM, Alin Serdean <aserd...@cloudbasesolutions.com> >> wrote: >> >> ovs/ovs-issues#15 >> >> All NET_BUFFERs of a NET_BUFFER_LIST must go through >> the pipeline: extract, find flow, execute. Previously, >> only the first NET_BUFFER of a NET_BUFFER_LIST was going >> through this pipeline, which was erroneous. >> >> OvsPartialCopyToMultipleNBLs is used to make each NET_BUFFER >> have its own NET_BUFFER_LIST. >> >> Some functions that used to take as argument a NET_BUFFER_LIST >> now take as argument a NET_BUFFER. I have also added a few >> ASSERTs where the NET_BUFFER_LIST is expected to have >> only one NET_BUFFER." >> >> Signed-off-by: Samuel Ghinet <sghinet at cloudbasesolutions.com> >> Co-authored-by: Alin Gabriel Serdean <aserd...@cloudbasesolutions.com> >> --- >> datapath-windows/ovsext/OvsActions.c | 20 ++++- >> datapath-windows/ovsext/OvsBufferMgmt.c | 8 +- >> datapath-windows/ovsext/OvsBufferMgmt.h | 5 ++ >> datapath-windows/ovsext/OvsChecksum.c | 3 +- >> datapath-windows/ovsext/OvsFlow.c | 44 +++++---- >> datapath-windows/ovsext/OvsFlow.h | 6 +- >> datapath-windows/ovsext/OvsPacketIO.c | 143 >> +++++++++++++++++++----------- >> datapath-windows/ovsext/OvsPacketParser.c | 24 ++--- >> datapath-windows/ovsext/OvsPacketParser.h | 30 ++++--- >> datapath-windows/ovsext/OvsTunnel.c | 12 ++- >> datapath-windows/ovsext/OvsUser.c | 19 +++- >> datapath-windows/ovsext/OvsVxlan.c | 37 ++++++-- >> 12 files changed, 221 insertions(+), 130 deletions(-) >> >> diff --git a/datapath-windows/ovsext/OvsActions.c >> b/datapath-windows/ovsext/OvsActions.c >> index 635becc..c5c5116 100644 >> --- a/datapath-windows/ovsext/OvsActions.c >> +++ b/datapath-windows/ovsext/OvsActions.c >> @@ -517,6 +517,9 @@ OvsDoFlowLookupOutput(OvsForwardingContext *ovsFwdCtx) >> OvsFlow *flow; >> UINT64 hash; >> NDIS_STATUS status; >> + VOID* vlanTagValue; >> + NET_BUFFER* pNb; >> + >> POVS_VPORT_ENTRY vport = >> OvsFindVportByPortNo(ovsFwdCtx->switchContext, ovsFwdCtx->srcVportNo); >> if (vport == NULL || vport->ovsState != OVS_STATE_CONNECTED) { >> @@ -527,12 +530,19 @@ OvsDoFlowLookupOutput(OvsForwardingContext *ovsFwdCtx) >> return NDIS_STATUS_SUCCESS; >> } >> ASSERT(vport->nicState == NdisSwitchNicStateConnected); >> + ASSERT(ovsFwdCtx->curNbl->FirstNetBuffer->Next == NULL); >> >> /* Assert that in the Rx direction, key is always setup. */ >> ASSERT(ovsFwdCtx->tunnelRxNic == NULL || ovsFwdCtx->tunKey.dst != 0); >> - status = OvsExtractFlow(ovsFwdCtx->curNbl, ovsFwdCtx->srcVportNo, >> - &key, &ovsFwdCtx->layers, ovsFwdCtx->tunKey.dst >> != 0 ? >> - &ovsFwdCtx->tunKey : NULL); >> + vlanTagValue = NET_BUFFER_LIST_INFO(ovsFwdCtx->curNbl, >> + Ieee8021QNetBufferListInfo); >> + >> + pNb = NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl); >> + >> + status = OvsExtractFlow(pNb, ovsFwdCtx->srcVportNo, >> + &key, &ovsFwdCtx->layers, >> + ovsFwdCtx->tunKey.dst != 0 ? >> + &ovsFwdCtx->tunKey : NULL, vlanTagValue); >> if (status != NDIS_STATUS_SUCCESS) { >> OvsCompleteNBLForwardingCtx(ovsFwdCtx, >> L"OVS-Flow extract failed"); >> @@ -542,7 +552,7 @@ OvsDoFlowLookupOutput(OvsForwardingContext *ovsFwdCtx) >> >> flow = OvsLookupFlow(&ovsFwdCtx->switchContext->datapath, &key, &hash, >> FALSE); >> if (flow) { >> - OvsFlowUsed(flow, ovsFwdCtx->curNbl, &ovsFwdCtx->layers); >> + OvsFlowUsed(flow, pNb, &ovsFwdCtx->layers); >> ovsFwdCtx->switchContext->datapath.hits++; >> status = OvsActionsExecute(ovsFwdCtx->switchContext, >> ovsFwdCtx->completionList, ovsFwdCtx->curNbl, >> @@ -1370,6 +1380,8 @@ OvsActionsExecute(POVS_SWITCH_CONTEXT switchContext, >> PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail = >> NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl); >> >> + ASSERT(curNbl->FirstNetBuffer->Next == NULL); >> + >> /* XXX: ASSERT that the flow table lock is held. */ >> status = OvsInitForwardingCtx(&ovsFwdCtx, switchContext, curNbl, portNo, >> sendFlags, fwdDetail, completionList, >> diff --git a/datapath-windows/ovsext/OvsBufferMgmt.c >> b/datapath-windows/ovsext/OvsBufferMgmt.c >> index 8aa8060..c367d2f 100644 >> --- a/datapath-windows/ovsext/OvsBufferMgmt.c >> +++ b/datapath-windows/ovsext/OvsBufferMgmt.c >> @@ -863,7 +863,7 @@ OvsPartialCopyToMultipleNBLs(PVOID ovsContext, >> if (prevNbl == NULL) { >> firstNbl = newNbl; >> } else { >> - NET_BUFFER_LIST_NEXT_NBL(prevNbl) = nbl; >> + NET_BUFFER_LIST_NEXT_NBL(prevNbl) = newNbl; >> NET_BUFFER_NEXT_NB(prevNb) = nb; >> } >> prevNbl = newNbl; >> @@ -1085,7 +1085,7 @@ nblcopy_error: >> * -------------------------------------------------------------------------- >> */ >> static NDIS_STATUS >> -GetSegmentHeaderInfo(PNET_BUFFER_LIST nbl, >> +GetSegmentHeaderInfo(PNET_BUFFER nb, >> const POVS_PACKET_HDR_INFO hdrInfo, >> UINT32 *hdrSize, UINT32 *seqNumber) >> { >> @@ -1093,7 +1093,7 @@ GetSegmentHeaderInfo(PNET_BUFFER_LIST nbl, >> const TCPHdr *tcp; >> >> /* Parse the orginal Eth/IP/TCP header */ >> - tcp = OvsGetPacketBytes(nbl, sizeof *tcp, hdrInfo->l4Offset, >> &tcpStorage); >> + tcp = OvsGetPacketBytes(nb, sizeof *tcp, hdrInfo->l4Offset, >> &tcpStorage); >> if (tcp == NULL) { >> return NDIS_STATUS_FAILURE; >> } >> @@ -1199,7 +1199,7 @@ OvsTcpSegmentNBL(PVOID ovsContext, >> ASSERT(NET_BUFFER_NEXT_NB(nb) == NULL); >> >> /* Figure out the segment header size */ >> - status = GetSegmentHeaderInfo(nbl, hdrInfo, &hdrSize, &seqNumber); >> + status = GetSegmentHeaderInfo(nb, hdrInfo, &hdrSize, &seqNumber); >> if (status != NDIS_STATUS_SUCCESS) { >> OVS_LOG_INFO("Cannot parse NBL header"); >> return NULL; >> diff --git a/datapath-windows/ovsext/OvsBufferMgmt.h >> b/datapath-windows/ovsext/OvsBufferMgmt.h >> index 9c00b1b..8e822e0 100644 >> --- a/datapath-windows/ovsext/OvsBufferMgmt.h >> +++ b/datapath-windows/ovsext/OvsBufferMgmt.h >> @@ -81,6 +81,11 @@ typedef struct _OVS_NBL_POOL { >> #endif >> } OVS_NBL_POOL, *POVS_NBL_POOL; >> >> +#define OVS_NBL_FOR_EACH(pCurNbl, nblList) \ >> +for (NET_BUFFER_LIST* pCurNbl = nblList; \ >> + pCurNbl != NULL; \ >> + pCurNbl = NET_BUFFER_LIST_NEXT_NBL(pCurNbl)) >> + >> >> NDIS_STATUS OvsInitBufferPool(PVOID context); >> VOID OvsCleanupBufferPool(PVOID context); >> diff --git a/datapath-windows/ovsext/OvsChecksum.c >> b/datapath-windows/ovsext/OvsChecksum.c >> index e192373..0c65221 100644 >> --- a/datapath-windows/ovsext/OvsChecksum.c >> +++ b/datapath-windows/ovsext/OvsChecksum.c >> @@ -536,7 +536,8 @@ OvsValidateIPChecksum(PNET_BUFFER_LIST curNbl, >> >> /* Next, check if the NIC did not validate the RX checksum. */ >> if (!csumInfo.Receive.IpChecksumSucceeded) { >> - ipHdr = OvsGetIp(curNbl, hdrInfo->l3Offset, &ip_storage); >> + ipHdr = OvsGetIp(NET_BUFFER_LIST_FIRST_NB(curNbl), >> + hdrInfo->l3Offset, &ip_storage); >> if (ipHdr) { >> ip_storage = *ipHdr; >> hdrChecksum = ipHdr->check; >> diff --git a/datapath-windows/ovsext/OvsFlow.c >> b/datapath-windows/ovsext/OvsFlow.c >> index daa64e0..19f6b2a 100644 >> --- a/datapath-windows/ovsext/OvsFlow.c >> +++ b/datapath-windows/ovsext/OvsFlow.c >> @@ -104,7 +104,7 @@ OvsAllocateFlowTable(OVS_DATAPATH *datapath, >> >> /* >> *---------------------------------------------------------------------------- >> - * GetStartAddrNBL -- >> + * GetStartAddrNB -- >> * Get the virtual address of the frame. >> * >> * Results: >> @@ -112,7 +112,7 @@ OvsAllocateFlowTable(OVS_DATAPATH *datapath, >> *---------------------------------------------------------------------------- >> */ >> static __inline VOID * >> -GetStartAddrNBL(const NET_BUFFER_LIST *_pNB) >> +GetStartAddrNB(const NET_BUFFER *_pNB) >> { >> PMDL curMdl; >> PUINT8 curBuffer; >> @@ -121,21 +121,21 @@ GetStartAddrNBL(const NET_BUFFER_LIST *_pNB) >> ASSERT(_pNB); >> >> // Ethernet Header is a guaranteed safe access. >> - curMdl = (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdl; >> + curMdl = (_pNB)->CurrentMdl; >> curBuffer = MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority); >> if (!curBuffer) { >> return NULL; >> } >> >> curHeader = (PEthHdr) >> - (curBuffer + (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdlOffset); >> + (curBuffer + (_pNB)->CurrentMdlOffset); >> >> return (VOID *) curHeader; >> } >> >> VOID >> OvsFlowUsed(OvsFlow *flow, >> - const NET_BUFFER_LIST *packet, >> + const NET_BUFFER *packet, >> const POVS_PACKET_HDR_INFO layers) >> { >> LARGE_INTEGER tickCount; >> @@ -144,7 +144,7 @@ OvsFlowUsed(OvsFlow *flow, >> flow->used = tickCount.QuadPart * ovsTimeIncrementPerTick; >> flow->used += ovsUserTimestampDelta; >> flow->packetCount++; >> - flow->byteCount += OvsPacketLenNBL(packet); >> + flow->byteCount += NET_BUFFER_DATA_LENGTH(packet); >> flow->tcpFlags |= OvsGetTcpFlags(packet, &flow->key, layers); >> } >> >> @@ -191,15 +191,14 @@ DeleteAllFlows(OVS_DATAPATH *datapath) >> *---------------------------------------------------------------------------- >> */ >> NDIS_STATUS >> -OvsExtractFlow(const NET_BUFFER_LIST *packet, >> +OvsExtractFlow(const NET_BUFFER* pNb, >> UINT32 inPort, >> OvsFlowKey *flow, >> POVS_PACKET_HDR_INFO layers, >> - OvsIPv4TunnelKey *tunKey) >> + OvsIPv4TunnelKey *tunKey, VOID* vlanTagValue) >> { >> struct Eth_Header *eth; >> UINT8 offset = 0; >> - PVOID vlanTagValue; >> >> layers->value = 0; >> >> @@ -214,20 +213,19 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet, >> >> flow->l2.inPort = inPort; >> >> - if ( OvsPacketLenNBL(packet) < ETH_HEADER_LEN_DIX) { >> + if (NET_BUFFER_DATA_LENGTH(pNb) < ETH_HEADER_LEN_DIX) { >> flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + 8 - flow->l2.offset; >> return NDIS_STATUS_SUCCESS; >> } >> >> /* Link layer. */ >> - eth = (Eth_Header *)GetStartAddrNBL((NET_BUFFER_LIST *)packet); >> + eth = (Eth_Header *)GetStartAddrNB(pNb); >> memcpy(flow->l2.dlSrc, eth->src, ETH_ADDR_LENGTH); >> memcpy(flow->l2.dlDst, eth->dst, ETH_ADDR_LENGTH); >> >> /* >> * vlan_tci. >> */ >> - vlanTagValue = NET_BUFFER_LIST_INFO(packet, Ieee8021QNetBufferListInfo); >> if (vlanTagValue) { >> PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag = >> (PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue; >> @@ -262,7 +260,7 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet, >> if (ETH_TYPENOT8023(eth->dix.typeNBO)) { >> flow->l2.dlType = eth->dix.typeNBO; >> layers->l3Offset = ETH_HEADER_LEN_DIX + offset; >> - } else if (OvsPacketLenNBL(packet) >= ETH_HEADER_LEN_802_3 && >> + } else if (NET_BUFFER_DATA_LENGTH(pNb) >= ETH_HEADER_LEN_802_3 && >> eth->e802_3.llc.dsap == 0xaa && >> eth->e802_3.llc.ssap == 0xaa && >> eth->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME && >> @@ -285,7 +283,7 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet, >> >> flow->l2.keyLen += OVS_IP_KEY_SIZE; >> layers->isIPv4 = 1; >> - nh = OvsGetIp(packet, layers->l3Offset, &ip_storage); >> + nh = OvsGetIp(pNb, layers->l3Offset, &ip_storage); >> if (nh) { >> layers->l4Offset = layers->l3Offset + nh->ihl * 4; >> >> @@ -309,14 +307,14 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet, >> >> if (!(nh->frag_off & htons(IP_OFFSET))) { >> if (ipKey->nwProto == SOCKET_IPPROTO_TCP) { >> - OvsParseTcp(packet, &ipKey->l4, layers); >> + OvsParseTcp(pNb, &ipKey->l4, layers); >> } else if (ipKey->nwProto == SOCKET_IPPROTO_UDP) { >> - OvsParseUdp(packet, &ipKey->l4, layers); >> + OvsParseUdp(pNb, &ipKey->l4, layers); >> } else if (ipKey->nwProto == SOCKET_IPPROTO_ICMP) { >> ICMPHdr icmpStorage; >> const ICMPHdr *icmp; >> >> - icmp = OvsGetIcmp(packet, layers->l4Offset, >> &icmpStorage); >> + icmp = OvsGetIcmp(pNb, layers->l4Offset, &icmpStorage); >> if (icmp) { >> ipKey->l4.tpSrc = htons(icmp->type); >> ipKey->l4.tpDst = htons(icmp->code); >> @@ -331,7 +329,7 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet, >> } else if (flow->l2.dlType == htons(ETH_TYPE_IPV6)) { >> NDIS_STATUS status; >> flow->l2.keyLen += OVS_IPV6_KEY_SIZE; >> - status = OvsParseIPv6(packet, flow, layers); >> + status = OvsParseIPv6(pNb, flow, layers); >> if (status != NDIS_STATUS_SUCCESS) { >> memset(&flow->ipv6Key, 0, sizeof (Ipv6Key)); >> return status; >> @@ -342,11 +340,11 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet, >> flow->ipv6Key.pad = 0; >> >> if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_TCP) { >> - OvsParseTcp(packet, &(flow->ipv6Key.l4), layers); >> + OvsParseTcp(pNb, &(flow->ipv6Key.l4), layers); >> } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_UDP) { >> - OvsParseUdp(packet, &(flow->ipv6Key.l4), layers); >> + OvsParseUdp(pNb, &(flow->ipv6Key.l4), layers); >> } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_ICMPV6) { >> - OvsParseIcmpV6(packet, flow, layers); >> + OvsParseIcmpV6(pNb, flow, layers); >> flow->l2.keyLen += (OVS_ICMPV6_KEY_SIZE - OVS_IPV6_KEY_SIZE); >> } >> } else if (flow->l2.dlType == htons(ETH_TYPE_ARP)) { >> @@ -357,7 +355,7 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet, >> ((UINT64 *)arpKey)[1] = 0; >> ((UINT64 *)arpKey)[2] = 0; >> flow->l2.keyLen += OVS_ARP_KEY_SIZE; >> - arp = OvsGetArp(packet, layers->l3Offset, &arpStorage); >> + arp = OvsGetArp(pNb, layers->l3Offset, &arpStorage); >> if (arp && arp->ea_hdr.ar_hrd == htons(1) && >> arp->ea_hdr.ar_pro == htons(ETH_TYPE_IPV4) && >> arp->ea_hdr.ar_hln == ETH_ADDR_LENGTH && >> @@ -420,9 +418,7 @@ AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow) >> */ >> KeMemoryBarrier(); >> >> - //KeAcquireSpinLock(&FilterDeviceExtension->NblQueueLock, &oldIrql); >> InsertTailList(head, &flow->ListEntry); >> - //KeReleaseSpinLock(&FilterDeviceExtension->NblQueueLock, oldIrql); >> >> datapath->nFlows++; >> >> diff --git a/datapath-windows/ovsext/OvsFlow.h >> b/datapath-windows/ovsext/OvsFlow.h >> index 93368b3..aeec803 100644 >> --- a/datapath-windows/ovsext/OvsFlow.h >> +++ b/datapath-windows/ovsext/OvsFlow.h >> @@ -50,13 +50,13 @@ NDIS_STATUS OvsDeleteFlowTable(OVS_DATAPATH *datapath); >> NDIS_STATUS OvsAllocateFlowTable(OVS_DATAPATH *datapath, >> POVS_SWITCH_CONTEXT switchContext); >> >> -NDIS_STATUS OvsExtractFlow(const NET_BUFFER_LIST *pkt, UINT32 inPort, >> +NDIS_STATUS OvsExtractFlow(const NET_BUFFER *pNb, UINT32 inPort, >> OvsFlowKey *flow, POVS_PACKET_HDR_INFO layers, >> - OvsIPv4TunnelKey *tunKey); >> + OvsIPv4TunnelKey *tunKey, VOID* vlanTagValue); >> OvsFlow *OvsLookupFlow(OVS_DATAPATH *datapath, const OvsFlowKey *key, >> UINT64 *hash, BOOLEAN hashValid); >> UINT64 OvsHashFlow(const OvsFlowKey *key); >> -VOID OvsFlowUsed(OvsFlow *flow, const NET_BUFFER_LIST *pkt, >> +VOID OvsFlowUsed(OvsFlow *flow, const NET_BUFFER *pkt, >> const POVS_PACKET_HDR_INFO layers); >> >> NTSTATUS OvsDumpFlowIoctl(PVOID inputBuffer, UINT32 inputLength, >> diff --git a/datapath-windows/ovsext/OvsPacketIO.c >> b/datapath-windows/ovsext/OvsPacketIO.c >> index 39e5703..d6d2e0e 100644 >> --- a/datapath-windows/ovsext/OvsPacketIO.c >> +++ b/datapath-windows/ovsext/OvsPacketIO.c >> @@ -211,61 +211,97 @@ OvsStartNBLIngress(POVS_SWITCH_CONTEXT switchContext, >> OvsFlowKey key; >> UINT64 hash; >> PNET_BUFFER curNb; >> + VOID* vlanTagValue; >> + NET_BUFFER_LIST* pNextNbl; >> >> nextNbl = curNbl->Next; >> curNbl->Next = NULL; >> >> /* Ethernet Header is a guaranteed safe access. */ >> - curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); >> - if (curNb->Next != NULL) { >> - /* XXX: This case is not handled yet. */ >> - ASSERT(FALSE); >> + POVS_BUFFER_CONTEXT ctx; >> + OvsFlow *flow; >> + NET_BUFFER_LIST* pNewNbl; >> + BOOLEAN dropNbl; >> + >> + fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl); >> + sourcePort = fwdDetail->SourcePortId; >> + sourceIndex = (NDIS_SWITCH_NIC_INDEX)fwdDetail->SourceNicIndex; >> + >> + /* Take the DispatchLock so none of the VPORTs disconnect while >> + * we are setting destination ports. >> + * >> + * XXX: acquire/release the dispatch lock for a "batch" of packets >> + * rather than for each packet. */ >> + NdisAcquireRWLockRead(switchContext->dispatchLock, &lockState, >> + dispatch); >> + >> + ctx = OvsInitExternalNBLContext(switchContext, curNbl, >> + sourcePort == switchContext->externalPortId); >> + if (ctx == NULL) { >> + RtlInitUnicodeString(&filterReason, >> + L"Cannot allocate external NBL context."); >> + >> + OvsStartNBLIngressError(switchContext, curNbl, >> + sendCompleteFlags, &filterReason, >> + NDIS_STATUS_RESOURCES); >> + NdisReleaseRWLock(switchContext->dispatchLock, &lockState); >> + continue; >> + } >> + >> + vport = OvsFindVportByPortIdAndNicIndex(switchContext, sourcePort, >> + sourceIndex); >> + if (vport == NULL || vport->ovsState != OVS_STATE_CONNECTED) { >> + RtlInitUnicodeString(&filterReason, >> + L"OVS-Cannot forward packet from unknown source port"); >> + goto dropit; >> } else { >> - POVS_BUFFER_CONTEXT ctx; >> - OvsFlow *flow; >> - >> - fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl); >> - sourcePort = fwdDetail->SourcePortId; >> - sourceIndex = (NDIS_SWITCH_NIC_INDEX)fwdDetail->SourceNicIndex; >> - >> - /* Take the DispatchLock so none of the VPORTs disconnect while >> - * we are setting destination ports. >> - * >> - * XXX: acquire/release the dispatch lock for a "batch" of >> packets >> - * rather than for each packet. */ >> - NdisAcquireRWLockRead(switchContext->dispatchLock, &lockState, >> - dispatch); >> - >> - ctx = OvsInitExternalNBLContext(switchContext, curNbl, >> - sourcePort == >> switchContext->externalPortId); >> - if (ctx == NULL) { >> + portNo = vport->portNo; >> + } >> + >> + curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); >> + vport->stats.rxPackets++; >> + vport->stats.rxBytes += NET_BUFFER_DATA_LENGTH(curNb); >> + vlanTagValue = NET_BUFFER_LIST_INFO(curNbl, >> + Ieee8021QNetBufferListInfo); >> + >> + if (curNb->Next == NULL) >> + { >> + pNewNbl = curNbl; >> + } >> + else >> + { >> + InterlockedDecrement((volatile LONG*)&ctx->refCount); >> + pNewNbl = OvsPartialCopyToMultipleNBLs(switchContext, curNbl, >> + 0, 0, TRUE); >> + if (!pNewNbl) { >> RtlInitUnicodeString(&filterReason, >> - L"Cannot allocate external NBL >> context."); >> + L"Cannot allocate new NBL: partial copy NB to " >> + L"multiple NBLs."); >> >> OvsStartNBLIngressError(switchContext, curNbl, >> sendCompleteFlags, &filterReason, >> NDIS_STATUS_RESOURCES); >> + >> NdisReleaseRWLock(switchContext->dispatchLock, &lockState); >> continue; >> } >> + } >> >> - vport = OvsFindVportByPortIdAndNicIndex(switchContext, >> sourcePort, >> - sourceIndex); >> - if (vport == NULL || vport->ovsState != OVS_STATE_CONNECTED) { >> - RtlInitUnicodeString(&filterReason, >> - L"OVS-Cannot forward packet from unknown source port"); >> - goto dropit; >> - } else { >> - portNo = vport->portNo; >> - } >> - >> - vport->stats.rxPackets++; >> - vport->stats.rxBytes += NET_BUFFER_DATA_LENGTH(curNb); >> + dropNbl = FALSE; >> + for (NET_BUFFER_LIST* pCurNbl = pNewNbl; pCurNbl != NULL; pCurNbl = >> pNextNbl) >> + { >> + pNextNbl = NET_BUFFER_LIST_NEXT_NBL(pCurNbl); >> + NET_BUFFER_LIST_NEXT_NBL(pCurNbl) = NULL; >> >> - status = OvsExtractFlow(curNbl, vport->portNo, &key, &layers, >> NULL); >> + status = OvsExtractFlow(NET_BUFFER_LIST_FIRST_NB(pCurNbl), >> + vport->portNo, &key, &layers, >> + NULL, vlanTagValue); >> if (status != NDIS_STATUS_SUCCESS) { >> RtlInitUnicodeString(&filterReason, L"OVS-Flow extract >> failed"); >> - goto dropit; >> + dropNbl = TRUE; >> + OvsAddPktCompletionList(&completionList, TRUE, sourcePort, >> + pCurNbl, 0, &filterReason); >> + continue; >> } >> >> ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); >> @@ -273,16 +309,17 @@ OvsStartNBLIngress(POVS_SWITCH_CONTEXT switchContext, >> >> flow = OvsLookupFlow(datapath, &key, &hash, FALSE); >> if (flow) { >> - OvsFlowUsed(flow, curNbl, &layers); >> + OvsFlowUsed(flow, NET_BUFFER_LIST_FIRST_NB(pCurNbl), >> &layers); >> datapath->hits++; >> + >> /* If successful, OvsActionsExecute() consumes the NBL. >> - * Otherwise, it adds it to the completionList. No need to >> - * check the return value. */ >> - OvsActionsExecute(switchContext, &completionList, curNbl, >> - portNo, SendFlags, &key, &hash, &layers, >> - flow->actions, flow->actionsLen); >> + * Otherwise, it adds it to the completionList. No need to >> + * check the return value. */ >> + OvsActionsExecute(switchContext, &completionList, pCurNbl, >> + portNo, SendFlags, &key, &hash, &layers, >> + flow->actions, flow->actionsLen); >> + >> OvsReleaseDatapath(datapath, &dpLockState); >> - NdisReleaseRWLock(switchContext->dispatchLock, &lockState); >> continue; >> } else { >> OvsReleaseDatapath(datapath, &dpLockState); >> @@ -293,28 +330,30 @@ OvsStartNBLIngress(POVS_SWITCH_CONTEXT switchContext, >> portNo, >> key.tunKey.dst != 0 ? >> (OvsIPv4TunnelKey >> *)&key.tunKey : >> - NULL, curNbl, >> + NULL, pCurNbl, >> sourcePort == >> switchContext->externalPortId, >> &layers, switchContext, >> &missedPackets, &num); >> if (status == NDIS_STATUS_SUCCESS) { >> /* Complete the packet since it was copied to user >> - * buffer. */ >> + * buffer. >> + */ >> RtlInitUnicodeString(&filterReason, >> L"OVS-Dropped since packet was copied to userspace"); >> } else { >> RtlInitUnicodeString(&filterReason, >> L"OVS-Dropped due to failure to queue to userspace"); >> } >> - goto dropit; >> + dropNbl = TRUE; >> + OvsAddPktCompletionList(&completionList, TRUE, sourcePort, >> + pCurNbl, 0, &filterReason); >> + continue; >> } >> - >> -dropit: >> - OvsAddPktCompletionList(&completionList, TRUE, sourcePort, >> curNbl, 0, >> - &filterReason); >> - NdisReleaseRWLock(switchContext->dispatchLock, &lockState); >> } >> + >> + dropit: >> + NdisReleaseRWLock(switchContext->dispatchLock, &lockState); >> } >> >> /* Queue the missed packets. */ >> diff --git a/datapath-windows/ovsext/OvsPacketParser.c >> b/datapath-windows/ovsext/OvsPacketParser.c >> index 0a93435..0b971a7 100644 >> --- a/datapath-windows/ovsext/OvsPacketParser.c >> +++ b/datapath-windows/ovsext/OvsPacketParser.c >> @@ -18,13 +18,12 @@ >> >> //XXX consider moving to NdisGetDataBuffer. >> const VOID * >> -OvsGetPacketBytes(const NET_BUFFER_LIST *nbl, >> +OvsGetPacketBytes(const NET_BUFFER *netBuffer, >> UINT32 len, >> UINT32 srcOffset, >> VOID *storage) >> { >> NDIS_STATUS status = NDIS_STATUS_SUCCESS; >> - PNET_BUFFER netBuffer = NET_BUFFER_LIST_FIRST_NB(nbl); >> PMDL currentMdl; >> BOOLEAN firstMDL = TRUE; >> ULONG destOffset = 0; >> @@ -83,7 +82,7 @@ OvsGetPacketBytes(const NET_BUFFER_LIST *nbl, >> } >> >> NDIS_STATUS >> -OvsParseIPv6(const NET_BUFFER_LIST *packet, >> +OvsParseIPv6(const NET_BUFFER *packet, >> OvsFlowKey *key, >> POVS_PACKET_HDR_INFO layers) >> { >> @@ -134,7 +133,8 @@ OvsParseIPv6(const NET_BUFFER_LIST *packet, >> const IPv6ExtHdr *extHdr; >> UINT8 len; >> >> - extHdr = OvsGetPacketBytes(packet, sizeof *extHdr, ofs, >> &extHdrStorage); >> + extHdr = OvsGetPacketBytes(packet, sizeof *extHdr, ofs, >> + &extHdrStorage); >> if (!extHdr) { >> return NDIS_STATUS_FAILURE; >> } >> @@ -142,7 +142,7 @@ OvsParseIPv6(const NET_BUFFER_LIST *packet, >> len = extHdr->hdrExtLen; >> ofs += nextHdr == SOCKET_IPPROTO_AH ? (len + 2) * 4 : (len + 1) * >> 8; >> nextHdr = extHdr->nextHeader; >> - if (OvsPacketLenNBL(packet) < ofs) { >> + if (NET_BUFFER_DATA_LENGTH(packet) < ofs) { >> return NDIS_STATUS_FAILURE; >> } >> } else if (nextHdr == SOCKET_IPPROTO_FRAGMENT) { >> @@ -177,7 +177,7 @@ OvsParseIPv6(const NET_BUFFER_LIST *packet, >> } >> >> VOID >> -OvsParseTcp(const NET_BUFFER_LIST *packet, >> +OvsParseTcp(const NET_BUFFER *packet, >> L4Key *flow, >> POVS_PACKET_HDR_INFO layers) >> { >> @@ -192,7 +192,7 @@ OvsParseTcp(const NET_BUFFER_LIST *packet, >> } >> >> VOID >> -OvsParseUdp(const NET_BUFFER_LIST *packet, >> +OvsParseUdp(const NET_BUFFER *packet, >> L4Key *flow, >> POVS_PACKET_HDR_INFO layers) >> { >> @@ -210,7 +210,7 @@ OvsParseUdp(const NET_BUFFER_LIST *packet, >> } >> >> NDIS_STATUS >> -OvsParseIcmpV6(const NET_BUFFER_LIST *packet, >> +OvsParseIcmpV6(const NET_BUFFER *packet, >> OvsFlowKey *key, >> POVS_PACKET_HDR_INFO layers) >> { >> @@ -249,7 +249,7 @@ OvsParseIcmpV6(const NET_BUFFER_LIST *packet, >> } >> flow->ndTarget = *ndTarget; >> >> - while ((UINT32)(ofs + 8) <= OvsPacketLenNBL(packet)) { >> + while ((UINT32)(ofs + 8) <= NET_BUFFER_DATA_LENGTH(packet)) { >> /* >> * The minimum size of an option is 8 bytes, which also is >> * the size of Ethernet link-layer options. >> @@ -258,13 +258,15 @@ OvsParseIcmpV6(const NET_BUFFER_LIST *packet, >> const IPv6NdOptHdr *ndOpt; >> UINT16 optLen; >> >> - ndOpt = OvsGetPacketBytes(packet, sizeof *ndOpt, ofs, >> &ndOptStorage); >> + ndOpt = OvsGetPacketBytes(packet, sizeof *ndOpt, ofs, >> + &ndOptStorage); >> if (!ndOpt) { >> return NDIS_STATUS_FAILURE; >> } >> >> optLen = ndOpt->len * 8; >> - if (!optLen || (UINT32)(ofs + optLen) > >> OvsPacketLenNBL(packet)) { >> + if (!optLen || (UINT32)(ofs + optLen) > >> + NET_BUFFER_DATA_LENGTH(packet)) { >> goto invalid; >> } >> >> diff --git a/datapath-windows/ovsext/OvsPacketParser.h >> b/datapath-windows/ovsext/OvsPacketParser.h >> index ab3c613..0928932 100644 >> --- a/datapath-windows/ovsext/OvsPacketParser.h >> +++ b/datapath-windows/ovsext/OvsPacketParser.h >> @@ -20,15 +20,15 @@ >> #include "precomp.h" >> #include "OvsNetProto.h" >> >> -const VOID* OvsGetPacketBytes(const NET_BUFFER_LIST *_pNB, UINT32 len, >> +const VOID* OvsGetPacketBytes(const NET_BUFFER *_pNB, UINT32 len, >> UINT32 SrcOffset, VOID *storage); >> -NDIS_STATUS OvsParseIPv6(const NET_BUFFER_LIST *packet, OvsFlowKey *key, >> +NDIS_STATUS OvsParseIPv6(const NET_BUFFER *packet, OvsFlowKey *key, >> POVS_PACKET_HDR_INFO layers); >> -VOID OvsParseTcp(const NET_BUFFER_LIST *packet, L4Key *flow, >> +VOID OvsParseTcp(const NET_BUFFER *packet, L4Key *flow, >> POVS_PACKET_HDR_INFO layers); >> -VOID OvsParseUdp(const NET_BUFFER_LIST *packet, L4Key *flow, >> +VOID OvsParseUdp(const NET_BUFFER *packet, L4Key *flow, >> POVS_PACKET_HDR_INFO layers); >> -NDIS_STATUS OvsParseIcmpV6(const NET_BUFFER_LIST *packet, OvsFlowKey *key, >> +NDIS_STATUS OvsParseIcmpV6(const NET_BUFFER *packet, OvsFlowKey *key, >> POVS_PACKET_HDR_INFO layers); >> >> static __inline ULONG >> @@ -58,7 +58,7 @@ OvsPacketLenNBL(const NET_BUFFER_LIST *_pNB) >> * which C does not allow. >> */ >> static UINT16 >> -OvsGetTcpCtl(const NET_BUFFER_LIST *packet, // IN >> +OvsGetTcpCtl(const NET_BUFFER *packet, // IN >> const POVS_PACKET_HDR_INFO layers) // IN >> { >> #define TCP_CTL_OFS 12 // Offset of "ctl" field in TCP header. >> @@ -74,7 +74,7 @@ OvsGetTcpCtl(const NET_BUFFER_LIST *packet, // IN >> >> >> static UINT8 >> -OvsGetTcpFlags(const NET_BUFFER_LIST *packet, // IN >> +OvsGetTcpFlags(const NET_BUFFER *packet, // IN >> const OvsFlowKey *key, // IN >> const POVS_PACKET_HDR_INFO layers) // IN >> { >> @@ -88,7 +88,7 @@ OvsGetTcpFlags(const NET_BUFFER_LIST *packet, // IN >> } >> >> static const EtherArp * >> -OvsGetArp(const NET_BUFFER_LIST *packet, >> +OvsGetArp(const NET_BUFFER *packet, >> UINT32 ofs, >> EtherArp *storage) >> { >> @@ -96,14 +96,15 @@ OvsGetArp(const NET_BUFFER_LIST *packet, >> } >> >> static const IPHdr * >> -OvsGetIp(const NET_BUFFER_LIST *packet, >> +OvsGetIp(const NET_BUFFER *packet, >> UINT32 ofs, >> IPHdr *storage) >> { >> const IPHdr *ip = OvsGetPacketBytes(packet, sizeof *ip, ofs, storage); >> if (ip) { >> int ipLen = ip->ihl * 4; >> - if (ipLen >= sizeof *ip && OvsPacketLenNBL(packet) >= ofs + ipLen) { >> + if (ipLen >= sizeof *ip && >> + NET_BUFFER_DATA_LENGTH(packet) >= ofs + ipLen) { >> return ip; >> } >> } >> @@ -111,14 +112,15 @@ OvsGetIp(const NET_BUFFER_LIST *packet, >> } >> >> static const TCPHdr * >> -OvsGetTcp(const NET_BUFFER_LIST *packet, >> +OvsGetTcp(const NET_BUFFER *packet, >> UINT32 ofs, >> TCPHdr *storage) >> { >> const TCPHdr *tcp = OvsGetPacketBytes(packet, sizeof *tcp, ofs, storage); >> if (tcp) { >> int tcpLen = tcp->doff * 4; >> - if (tcpLen >= sizeof *tcp && OvsPacketLenNBL(packet) >= ofs + >> tcpLen) { >> + if (tcpLen >= sizeof *tcp && >> + NET_BUFFER_DATA_LENGTH(packet) >= ofs + tcpLen) { >> return tcp; >> } >> } >> @@ -126,7 +128,7 @@ OvsGetTcp(const NET_BUFFER_LIST *packet, >> } >> >> static const UDPHdr * >> -OvsGetUdp(const NET_BUFFER_LIST *packet, >> +OvsGetUdp(const NET_BUFFER *packet, >> UINT32 ofs, >> UDPHdr *storage) >> { >> @@ -134,7 +136,7 @@ OvsGetUdp(const NET_BUFFER_LIST *packet, >> } >> >> static const ICMPHdr * >> -OvsGetIcmp(const NET_BUFFER_LIST *packet, >> +OvsGetIcmp(const NET_BUFFER *packet, >> UINT32 ofs, >> ICMPHdr *storage) >> { >> diff --git a/datapath-windows/ovsext/OvsTunnel.c >> b/datapath-windows/ovsext/OvsTunnel.c >> index b5a369a..9c96aec 100644 >> --- a/datapath-windows/ovsext/OvsTunnel.c >> +++ b/datapath-windows/ovsext/OvsTunnel.c >> @@ -228,6 +228,7 @@ OvsInjectPacketThroughActions(PNET_BUFFER_LIST pNbl, >> OVS_DATAPATH *datapath = &gOvsSwitchContext->datapath; >> >> ASSERT(gOvsSwitchContext); >> + ASSERT(pNbl->FirstNetBuffer->Next == NULL); >> >> /* Fill the tunnel key */ >> status = OvsSlowPathDecapVxlan(pNbl, &tunnelKey); >> @@ -265,6 +266,7 @@ OvsInjectPacketThroughActions(PNET_BUFFER_LIST pNbl, >> UINT64 hash; >> PNET_BUFFER curNb; >> OvsFlow *flow; >> + VOID* vlanTagValue; >> >> fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(pNbl); >> >> @@ -295,20 +297,22 @@ OvsInjectPacketThroughActions(PNET_BUFFER_LIST pNbl, >> ASSERT(vport->ovsType == OVSWIN_VPORT_TYPE_VXLAN); >> >> portNo = vport->portNo; >> + vlanTagValue = NET_BUFFER_LIST_INFO(pNbl, >> Ieee8021QNetBufferListInfo); >> >> - status = OvsExtractFlow(pNbl, portNo, &key, &layers, &tunnelKey); >> + status = OvsExtractFlow(curNb, portNo, &key, &layers, >> + &tunnelKey, vlanTagValue); >> if (status != NDIS_STATUS_SUCCESS) { >> goto unlockAndDrop; >> } >> >> flow = OvsLookupFlow(datapath, &key, &hash, FALSE); >> if (flow) { >> - OvsFlowUsed(flow, pNbl, &layers); >> + OvsFlowUsed(flow, curNb, &layers); >> datapath->hits++; >> >> OvsActionsExecute(gOvsSwitchContext, &completionList, pNbl, >> - portNo, SendFlags, &key, &hash, &layers, >> - flow->actions, flow->actionsLen); >> + portNo, SendFlags, &key, &hash, &layers, >> + flow->actions, flow->actionsLen); >> >> OvsReleaseDatapath(datapath, &dpLockState); >> } else { >> diff --git a/datapath-windows/ovsext/OvsUser.c >> b/datapath-windows/ovsext/OvsUser.c >> index 5093f20..9f717ee 100644 >> --- a/datapath-windows/ovsext/OvsUser.c >> +++ b/datapath-windows/ovsext/OvsUser.c >> @@ -315,6 +315,7 @@ OvsExecuteDpIoctl(PVOID inputBuffer, >> OvsFlowKey key; >> OVS_PACKET_HDR_INFO layers; >> POVS_VPORT_ENTRY vport; >> + VOID* vlanTagValue; >> >> if (inputLength < sizeof(*execute) || outputLength != 0) { >> return STATUS_INFO_LENGTH_MISMATCH; >> @@ -360,14 +361,22 @@ OvsExecuteDpIoctl(PVOID inputBuffer, >> fwdDetail->SourcePortId = NDIS_SWITCH_DEFAULT_PORT_ID; >> fwdDetail->SourceNicIndex = 0; >> } >> - // XXX: Figure out if any of the other members of fwdDetail need to be >> set. >> + /* >> + * XXX: Figure out if any of the other members of fwdDetail need to be >> + * set. >> + */ >> + >> + ASSERT(pNbl->FirstNetBuffer->Next == NULL); >> >> - ndisStatus = OvsExtractFlow(pNbl, fwdDetail->SourcePortId, &key, >> &layers, >> - NULL); >> + vlanTagValue = NET_BUFFER_LIST_INFO(pNbl, Ieee8021QNetBufferListInfo); >> + >> + ndisStatus = OvsExtractFlow(NET_BUFFER_LIST_FIRST_NB(pNbl), >> + fwdDetail->SourcePortId, &key, &layers, >> NULL, >> + vlanTagValue); >> if (ndisStatus == NDIS_STATUS_SUCCESS) { >> ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); >> NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState, >> - NDIS_RWL_AT_DISPATCH_LEVEL); >> + NDIS_RWL_AT_DISPATCH_LEVEL); >> ndisStatus = OvsActionsExecute(gOvsSwitchContext, NULL, pNbl, >> vport ? vport->portNo : 0, >> >> NDIS_SEND_FLAGS_SWITCH_DESTINATION_GROUP, >> @@ -827,6 +836,8 @@ OvsCreateAndAddPackets(UINT32 queueId, >> PNET_BUFFER_LIST newNbl = NULL; >> PNET_BUFFER nb; >> >> + ASSERT(nbl->FirstNetBuffer->Next == NULL); >> + >> if (hdrInfo->isTcp) { >> NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO tsoInfo; >> UINT32 packetLength; >> diff --git a/datapath-windows/ovsext/OvsVxlan.c >> b/datapath-windows/ovsext/OvsVxlan.c >> index 63909ae..c50d2d9 100644 >> --- a/datapath-windows/ovsext/OvsVxlan.c >> +++ b/datapath-windows/ovsext/OvsVxlan.c >> @@ -116,6 +116,8 @@ OvsDoEncapVxlan(PNET_BUFFER_LIST curNbl, >> UINT32 headRoom = OvsGetVxlanTunHdrSize(); >> UINT32 packetLength; >> >> + ASSERT(curNbl->FirstNetBuffer->Next == NULL); >> + >> /* >> * XXX: the assumption currently is that the NBL is owned by OVS, and >> * headroom has already been allocated as part of allocating the NBL and >> @@ -286,13 +288,19 @@ OvsIpHlprCbVxlan(PNET_BUFFER_LIST curNbl, >> OvsFlowKey key; >> NDIS_STATUS status; >> UNREFERENCED_PARAMETER(inPort); >> - >> - status = OvsExtractFlow(curNbl, inPort, &key, &layers, NULL); >> - if (result == STATUS_SUCCESS) { >> - status = OvsDoEncapVxlan(curNbl, tunKey, fwdInfo, &layers, >> + VOID* vlanTagValue; >> + >> + vlanTagValue = NET_BUFFER_LIST_INFO(curNbl, Ieee8021QNetBufferListInfo); >> + for (NET_BUFFER* pNb = NET_BUFFER_LIST_FIRST_NB(curNbl); >> + pNb != NULL; pNb = NET_BUFFER_NEXT_NB(pNb)) { >> + status = OvsExtractFlow(pNb, inPort, &key, &layers, NULL, >> + vlanTagValue); >> + if (result == STATUS_SUCCESS) { >> + status = OvsDoEncapVxlan(curNbl, tunKey, fwdInfo, &layers, >> (POVS_SWITCH_CONTEXT)cbData1, NULL); >> - } else { >> - status = NDIS_STATUS_FAILURE; >> + } else { >> + status = NDIS_STATUS_FAILURE; >> + } >> } >> >> if (status != NDIS_STATUS_SUCCESS) { >> @@ -457,9 +465,16 @@ OvsSlowPathDecapVxlan(const PNET_BUFFER_LIST packet, >> OVS_PACKET_HDR_INFO layers; >> >> layers.value = 0; >> + ASSERT(packet->FirstNetBuffer->Next == NULL); >> >> do { >> - nh = OvsGetIp(packet, layers.l3Offset, &ip_storage); >> + NET_BUFFER* pNb = NET_BUFFER_LIST_FIRST_NB(packet); >> + >> + /* >> + * It is an encapsulated packet (UDP), we can use the first NB >> + * to start the check >> + */ >> + nh = OvsGetIp(pNb, layers.l3Offset, &ip_storage); >> if (nh) { >> layers.l4Offset = layers.l3Offset + nh->ihl * 4; >> } else { >> @@ -467,7 +482,7 @@ OvsSlowPathDecapVxlan(const PNET_BUFFER_LIST packet, >> } >> >> /* make sure it's a VXLAN packet */ >> - udp = OvsGetUdp(packet, layers.l4Offset, &udpStorage); >> + udp = OvsGetUdp(pNb, layers.l4Offset, &udpStorage); >> if (udp) { >> layers.l7Offset = layers.l4Offset + sizeof *udp; >> } else { >> @@ -477,7 +492,11 @@ OvsSlowPathDecapVxlan(const PNET_BUFFER_LIST packet, >> /* XXX Should be tested against the dynamic port # in the VXLAN vport >> */ >> ASSERT(udp->dest == RtlUshortByteSwap(VXLAN_UDP_PORT)); >> >> - VxlanHeader = (VXLANHdr *)OvsGetPacketBytes(packet, >> + /* >> + * We may have multiple VXLAN packets here that need to be >> decapsulated >> + * For the VXLAN header, we need only the first NET_BUFFER >> + */ >> + VxlanHeader = (VXLANHdr *)OvsGetPacketBytes(pNb, >> sizeof(*VxlanHeader), >> layers.l7Offset, >> &VxlanHeaderBuffer); >> -- >> 1.9.0.msysgit.0 > > > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev