[ovs-dev] [PATCH v8 4/5] datapath-windows: Updated OvsTcpSegmentNBL to handle IP fragments.

Alin Serdean aserdean at cloudbasesolutions.com
Sat May 6 01:45:06 UTC 2017


Acked-by: Alin Gabriel Serdean <aserdean at cloudbasesolutions.com>

> -----Original Message-----
> From: ovs-dev-bounces at openvswitch.org [mailto:ovs-dev-
> bounces at openvswitch.org] On Behalf Of Anand Kumar
> Sent: Friday, May 5, 2017 1:13 AM
> To: dev at openvswitch.org
> Subject: [ovs-dev] [PATCH v8 4/5] datapath-windows: Updated
> OvsTcpSegmentNBL to handle IP fragments.
> 
> With this patch, OvsTcpSegmentNBL not only supports fragmenting NBL to
> TCP segments but also Ipv4 fragments.
> 
> To reflect the new changes, renamed function name from
> OvsTcpSegmentNBL to OvsFragmentNBL and created a wrapper for
> OvsTcpSegmentNBL.
> 
> Signed-off-by: Anand Kumar <kumaranand at vmware.com>
> ---
> v7->v8: No change
> v6->v7: As per Alins suggesstion, leaving FixSegmentHeader as it is
> 		and introdude new function FixFragmentHeader to make it
> look
> 		simple and clean.
> v5->v6: No Change
> v4->v5: Changed a variable mss to fragmentSize.
> v3->v4: No Change
> v2->v3:
> 	- Updated log message and function summary
> v1->v2:
> 	- Fix compile error for release mode
> ---
>  datapath-windows/ovsext/BufferMgmt.c | 171
> ++++++++++++++++++++++++++++++-----
>  datapath-windows/ovsext/BufferMgmt.h |  10 +-
>  datapath-windows/ovsext/Geneve.c     |   2 +-
>  datapath-windows/ovsext/Gre.c        |   2 +-
>  datapath-windows/ovsext/Stt.c        |   2 +-
>  datapath-windows/ovsext/User.c       |   2 +-
>  datapath-windows/ovsext/Vxlan.c      |   2 +-
>  7 files changed, 164 insertions(+), 27 deletions(-)
> 
> diff --git a/datapath-windows/ovsext/BufferMgmt.c b/datapath-
> windows/ovsext/BufferMgmt.c
> index d99052d..5048ada 100644
> --- a/datapath-windows/ovsext/BufferMgmt.c
> +++ b/datapath-windows/ovsext/BufferMgmt.c
> @@ -1084,6 +1084,31 @@ nblcopy_error:
>      return NULL;
>  }
> 
> +NDIS_STATUS
> +GetIpHeaderInfo(PNET_BUFFER_LIST curNbl,
> +                UINT32 *hdrSize)
> +{
> +    CHAR *ethBuf[sizeof(EthHdr)];
> +    EthHdr *eth;
> +    IPHdr *ipHdr;
> +    PNET_BUFFER curNb;
> +
> +    curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);
> +    ASSERT(NET_BUFFER_NEXT_NB(curNb) == NULL);
> +
> +    eth = (EthHdr *)NdisGetDataBuffer(curNb, ETH_HEADER_LENGTH,
> +                                      (PVOID)&ethBuf, 1, 0);
> +    if (eth == NULL) {
> +        return NDIS_STATUS_INVALID_PACKET;
> +    }
> +    ipHdr = (IPHdr *)((PCHAR)eth + ETH_HEADER_LENGTH);
> +    if (ipHdr == NULL) {
> +        return NDIS_STATUS_INVALID_PACKET;
> +    }
> +    *hdrSize = (UINT32)(ETH_HEADER_LENGTH + (ipHdr->ihl * 4));
> +    return NDIS_STATUS_SUCCESS;
> +}
> +
>  /*
>   * --------------------------------------------------------------------------
>   * GetSegmentHeaderInfo
> @@ -1110,6 +1135,62 @@ GetSegmentHeaderInfo(PNET_BUFFER_LIST nbl,
>      return NDIS_STATUS_SUCCESS;
>  }
> 
> +/*
> + *
> +-----------------------------------------------------------------------
> +---
> + * FixFragmentHeader
> + *
> + *    Fix IP length, Offset, IP checksum.
> + *    XXX - Support IpV6 Fragments
> + *
> +-----------------------------------------------------------------------
> +---
> + */
> +static NDIS_STATUS
> +FixFragmentHeader(PNET_BUFFER nb, UINT16 fragmentSize,
> +                  BOOLEAN lastPacket, UINT16 offset) {
> +    EthHdr *dstEth = NULL;
> +    PMDL mdl = NULL;
> +    PUINT8 bufferStart = NULL;
> +
> +    mdl = NET_BUFFER_FIRST_MDL(nb);
> +
> +    bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(mdl,
> LowPagePriority);
> +    if (!bufferStart) {
> +        return NDIS_STATUS_RESOURCES;
> +    }
> +    dstEth = (EthHdr *)(bufferStart +
> + NET_BUFFER_CURRENT_MDL_OFFSET(nb));
> +
> +    switch (dstEth->Type) {
> +    case ETH_TYPE_IPV4_NBO:
> +    {
> +        IPHdr *dstIP = NULL;
> +        ASSERT((INT)MmGetMdlByteCount(mdl) -
> NET_BUFFER_CURRENT_MDL_OFFSET(nb)
> +            >= sizeof(EthHdr) + sizeof(IPHdr));
> +
> +        dstIP = (IPHdr *)((PCHAR)dstEth + sizeof(*dstEth));
> +        ASSERT((INT)MmGetMdlByteCount(mdl) -
> NET_BUFFER_CURRENT_MDL_OFFSET(nb)
> +            >= sizeof(EthHdr) + dstIP->ihl * 4);
> +        dstIP->tot_len = htons(fragmentSize + dstIP->ihl * 4);
> +        if (lastPacket) {
> +            dstIP->frag_off = htons(offset & IP_OFFSET);
> +        } else {
> +            dstIP->frag_off = htons((offset & IP_OFFSET) | IP_MF);
> +        }
> +
> +        dstIP->check = 0;
> +        dstIP->check = IPChecksum((UINT8 *)dstIP, dstIP->ihl * 4, 0);
> +        break;
> +    }
> +    case ETH_TYPE_IPV6_NBO:
> +    {
> +        return NDIS_STATUS_NOT_SUPPORTED;
> +    }
> +    default:
> +        OVS_LOG_ERROR("Invalid eth type: %d\n", dstEth->Type);
> +        ASSERT(! "Invalid eth type");
> +    }
> +
> +    return STATUS_SUCCESS;
> +}
> 
>  /*
>   * --------------------------------------------------------------------------
> @@ -1217,12 +1298,29 @@ FixSegmentHeader(PNET_BUFFER nb, UINT16
> segmentSize, UINT32 seqNumber,
> 
>      return STATUS_SUCCESS;
>  }
> + /*
> +  *
> +-----------------------------------------------------------------------
> +---
> + * OvsTcpSegmentNBL --
> + *    Wrapper function to Fragment a given NBL based on MSS
> + *
> +-----------------------------------------------------------------------
> +---
> + */
> +PNET_BUFFER_LIST
> +OvsTcpSegmentNBL(PVOID ovsContext,
> +                 PNET_BUFFER_LIST nbl,
> +                 POVS_PACKET_HDR_INFO hdrInfo,
> +                 UINT32 mss,
> +                 UINT32 headRoom,
> +                 BOOLEAN isIpFragment)
> +{
> +    return OvsFragmentNBL(ovsContext, nbl, hdrInfo, mss, headRoom,
> +isIpFragment); }
> +
> 
>  /*
>   * --------------------------------------------------------------------------
> - * OvsTcpSegmentNBL --
> + * OvsFragmentNBL --
>   *
> - *    Segment TCP payload, and prepend each segment with ether/IP/TCP
> header.
> + *    Fragment NBL payload, and prepend each segment with Ether/IP/TCP
> header.
>   *    Leave headRoom for additional encap.
>   *
>   *    Please note,
> @@ -1235,24 +1333,25 @@ FixSegmentHeader(PNET_BUFFER nb, UINT16
> segmentSize, UINT32 seqNumber,
>   * --------------------------------------------------------------------------
>   */
>  PNET_BUFFER_LIST
> -OvsTcpSegmentNBL(PVOID ovsContext,
> -                 PNET_BUFFER_LIST nbl,
> -                 POVS_PACKET_HDR_INFO hdrInfo,
> -                 UINT32 mss,
> -                 UINT32 headRoom)
> +OvsFragmentNBL(PVOID ovsContext,
> +               PNET_BUFFER_LIST nbl,
> +               POVS_PACKET_HDR_INFO hdrInfo,
> +               UINT32 fragmentSize,
> +               UINT32 headRoom,
> +               BOOLEAN isIpFragment)
>  {
>      POVS_SWITCH_CONTEXT context =
> (POVS_SWITCH_CONTEXT)ovsContext;  #ifdef DBG
>      POVS_NBL_POOL ovsPool = &context->ovsPool;  #endif
>      POVS_BUFFER_CONTEXT dstCtx, srcCtx;
> -    UINT32 size, hdrSize, seqNumber;
> +    UINT32 size, hdrSize, nblSize, seqNumber = 0;
>      PNET_BUFFER_LIST newNbl;
>      PNET_BUFFER nb, newNb;
>      NDIS_STATUS status;
>      UINT16 segmentSize;
>      ULONG copiedSize;
> -    UINT16 packetCounter = 0;
> +    UINT16 offset = 0, packetCounter = 0;
> 
>      srcCtx =
> (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);
>      if (srcCtx == NULL || srcCtx->magic != OVS_CTX_MAGIC) { @@ -1264,18
> +1363,28 @@ OvsTcpSegmentNBL(PVOID ovsContext,
>      nb = NET_BUFFER_LIST_FIRST_NB(nbl);
>      ASSERT(NET_BUFFER_NEXT_NB(nb) == NULL);
> 
> -    /* Figure out the segment header size */
> -    status = GetSegmentHeaderInfo(nbl, hdrInfo, &hdrSize, &seqNumber);
> +    /* Figure out the header size */
> +    if (isIpFragment) {
> +        status = GetIpHeaderInfo(nbl, &hdrSize);
> +    } else {
> +        status = GetSegmentHeaderInfo(nbl, hdrInfo, &hdrSize, &seqNumber);
> +    }
>      if (status != NDIS_STATUS_SUCCESS) {
>          OVS_LOG_INFO("Cannot parse NBL header");
>          return NULL;
>      }
> -
> +    /* Get the NBL size. */
> +    if (isIpFragment) {
> +        nblSize = fragmentSize - hdrSize;
> +    } else {
> +        nblSize = fragmentSize;
> +    }
>      size = NET_BUFFER_DATA_LENGTH(nb) - hdrSize;
> 
>      /* XXX add to ovsPool counters? */
> -    newNbl = NdisAllocateFragmentNetBufferList(nbl, NULL,
> -            NULL, hdrSize, mss, hdrSize + headRoom , 0, 0);
> +    newNbl = NdisAllocateFragmentNetBufferList(nbl, NULL, NULL, hdrSize,
> +                                               nblSize, hdrSize + headRoom ,
> +                                               0, 0);
>      if (newNbl == NULL) {
>          return NULL;
>      }
> @@ -1283,7 +1392,7 @@ OvsTcpSegmentNBL(PVOID ovsContext,
>      /* Now deal with TCP payload */
>      for (newNb = NET_BUFFER_LIST_FIRST_NB(newNbl); newNb != NULL;
>              newNb = NET_BUFFER_NEXT_NB(newNb)) {
> -        segmentSize = (size > mss ? mss : size) & 0xffff;
> +        segmentSize = (size > nblSize ? nblSize : size) & 0xffff;
>          if (headRoom) {
>              NdisAdvanceNetBufferDataStart(newNb, headRoom, FALSE, NULL);
>          }
> @@ -1295,17 +1404,27 @@ OvsTcpSegmentNBL(PVOID ovsContext,
>              goto nblcopy_error;
>          }
> 
> -        status = FixSegmentHeader(newNb, segmentSize, seqNumber,
> -                                  NET_BUFFER_NEXT_NB(newNb) == NULL,
> -                                  packetCounter);
> +        if (isIpFragment) {
> +            status = FixFragmentHeader(newNb, segmentSize,
> +                                       NET_BUFFER_NEXT_NB(newNb) == NULL,
> +                                       offset);
> +        } else {
> +            status = FixSegmentHeader(newNb, segmentSize, seqNumber,
> +                                      NET_BUFFER_NEXT_NB(newNb) == NULL,
> +                                      packetCounter);
> +        }
> +
>          if (status != NDIS_STATUS_SUCCESS) {
>              goto nblcopy_error;
>          }
> 
> -
>          /* Move on to the next segment */
> +        if (isIpFragment) {
> +            offset += (segmentSize) / 8;
> +        } else {
> +            seqNumber += segmentSize;
> +        }
>          size -= segmentSize;
> -        seqNumber += segmentSize;
>          packetCounter++;
>      }
> 
> @@ -1319,6 +1438,15 @@ OvsTcpSegmentNBL(PVOID ovsContext,
>          goto nbl_context_error;
>      }
> 
> +    if (isIpFragment) {
> +    /*Copy with Flag -
> NDIS_SWITCH_COPY_NBL_INFO_FLAGS_PRESERVE_DESTINATIONS.*/
> +        status = context->NdisSwitchHandlers.
> +            CopyNetBufferListInfo(context->ovsPool.ndisContext, newNbl,
> + nbl, 1);
> +
> +        if (status != NDIS_STATUS_SUCCESS) {
> +            goto nbl_context_error;
> +        }
> +    }
>      newNbl->ParentNetBufferList = nbl;
> 
>      /* Remember it's a fragment NBL so we can free it properly */ @@ -1329,6
> +1457,7 @@ OvsTcpSegmentNBL(PVOID ovsContext,
>      dstCtx->refCount = 1;
>      dstCtx->magic = OVS_CTX_MAGIC;
>      dstCtx->dataOffsetDelta = hdrSize + headRoom;
> +    dstCtx->mru = 0;
> 
>      InterlockedIncrement((LONG volatile *)&srcCtx->refCount);  #ifdef DBG
> @@ -1340,7 +1469,7 @@ OvsTcpSegmentNBL(PVOID ovsContext,
>      OvsDumpNetBufferList(newNbl);
>      OvsDumpForwardingDetails(newNbl);
>  #endif
> -    OVS_LOG_TRACE("Segment nbl %p to newNbl: %p", nbl, newNbl);
> +    OVS_LOG_TRACE("Fragment nbl %p to newNbl: %p", nbl, newNbl);
>      return newNbl;
> 
>  nbl_context_error:
> diff --git a/datapath-windows/ovsext/BufferMgmt.h b/datapath-
> windows/ovsext/BufferMgmt.h
> index 294d40a..e6cc0fe 100644
> --- a/datapath-windows/ovsext/BufferMgmt.h
> +++ b/datapath-windows/ovsext/BufferMgmt.h
> @@ -116,7 +116,15 @@ PNET_BUFFER_LIST OvsTcpSegmentNBL(PVOID
> context,
>                                    PNET_BUFFER_LIST nbl,
>                                    POVS_PACKET_HDR_INFO hdrInfo,
>                                    UINT32 MSS,
> -                                  UINT32 headRoom);
> +                                  UINT32 headRoom,
> +                                  BOOLEAN isIpFragment);
> +
> +PNET_BUFFER_LIST OvsFragmentNBL(PVOID context,
> +                                PNET_BUFFER_LIST nbl,
> +                                POVS_PACKET_HDR_INFO hdrInfo,
> +                                UINT32 MSS,
> +                                UINT32 headRoom,
> +                                BOOLEAN isIpFragment);
> 
>  PNET_BUFFER_LIST OvsAllocateNBLFromBuffer(PVOID context,
>                                            PVOID buffer, diff --git a/datapath-
> windows/ovsext/Geneve.c b/datapath-windows/ovsext/Geneve.c
> index 1938aaa..43374e2 100644
> --- a/datapath-windows/ovsext/Geneve.c
> +++ b/datapath-windows/ovsext/Geneve.c
> @@ -118,7 +118,7 @@ NDIS_STATUS
> OvsEncapGeneve(POVS_VPORT_ENTRY vport,
>          if (mss) {
>              OVS_LOG_TRACE("l4Offset %d", layers->l4Offset);
>              *newNbl = OvsTcpSegmentNBL(switchContext, curNbl, layers,
> -                                       mss, headRoom);
> +                                       mss, headRoom, FALSE);
>              if (*newNbl == NULL) {
>                  OVS_LOG_ERROR("Unable to segment NBL");
>                  return NDIS_STATUS_FAILURE; diff --git a/datapath-
> windows/ovsext/Gre.c b/datapath-windows/ovsext/Gre.c index
> c5da064..f095742 100644
> --- a/datapath-windows/ovsext/Gre.c
> +++ b/datapath-windows/ovsext/Gre.c
> @@ -158,7 +158,7 @@ OvsDoEncapGre(POVS_VPORT_ENTRY vport,
>          if (mss) {
>              OVS_LOG_TRACE("l4Offset %d", layers->l4Offset);
>              *newNbl = OvsTcpSegmentNBL(switchContext, curNbl, layers,
> -                                       mss, headRoom);
> +                                       mss, headRoom, FALSE);
>              if (*newNbl == NULL) {
>                  OVS_LOG_ERROR("Unable to segment NBL");
>                  return NDIS_STATUS_FAILURE; diff --git a/datapath-
> windows/ovsext/Stt.c b/datapath-windows/ovsext/Stt.c index
> 5aa8652..1f36835 100644
> --- a/datapath-windows/ovsext/Stt.c
> +++ b/datapath-windows/ovsext/Stt.c
> @@ -185,7 +185,7 @@ OvsDoEncapStt(POVS_VPORT_ENTRY vport,
>          if ((innerFrameLen > OVS_MAX_STT_PACKET_LENGTH) ||
>              (layers->l4Offset > OVS_MAX_STT_L4_OFFSET_LENGTH)) {
>              *newNbl = OvsTcpSegmentNBL(switchContext, curNbl, layers,
> -                mss - headRoom, headRoom);
> +                                       mss - headRoom, headRoom,
> + FALSE);
>              if (*newNbl == NULL) {
>                  OVS_LOG_ERROR("Unable to segment NBL");
>                  return NDIS_STATUS_FAILURE; diff --git a/datapath-
> windows/ovsext/User.c b/datapath-windows/ovsext/User.c index
> 3154640..7880220 100644
> --- a/datapath-windows/ovsext/User.c
> +++ b/datapath-windows/ovsext/User.c
> @@ -787,7 +787,7 @@ OvsCreateAndAddPackets(PVOID userData,
>          if (tsoInfo.LsoV1Transmit.MSS) {
>              OVS_LOG_TRACE("l4Offset %d", hdrInfo->l4Offset);
>              newNbl = OvsTcpSegmentNBL(switchContext, nbl, hdrInfo,
> -                    tsoInfo.LsoV1Transmit.MSS , 0);
> +                                      tsoInfo.LsoV1Transmit.MSS , 0,
> + FALSE);
>              if (newNbl == NULL) {
>                  return NDIS_STATUS_FAILURE;
>              }
> diff --git a/datapath-windows/ovsext/Vxlan.c b/datapath-
> windows/ovsext/Vxlan.c index 84c2f2f..427f31c 100644
> --- a/datapath-windows/ovsext/Vxlan.c
> +++ b/datapath-windows/ovsext/Vxlan.c
> @@ -205,7 +205,7 @@ OvsDoEncapVxlan(POVS_VPORT_ENTRY vport,
>          if (mss) {
>              OVS_LOG_TRACE("l4Offset %d", layers->l4Offset);
>              *newNbl = OvsTcpSegmentNBL(switchContext, curNbl, layers,
> -                                       mss, headRoom);
> +                                       mss, headRoom, FALSE);
>              if (*newNbl == NULL) {
>                  OVS_LOG_ERROR("Unable to segment NBL");
>                  return NDIS_STATUS_FAILURE;
> --
> 2.9.3.windows.1
> 
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev


More information about the dev mailing list