datapath-windows/ovsext/Vxlan.c
/*
 *----------------------------------------------------------------------------
 * OvsDecapVxlan
 *     Decapsulates to tunnel header in 'curNbl' and puts into 'tunKey'.
 *----------------------------------------------------------------------------
 */
OvsDecapVxlan
Decapsulates to tunnel header in 'curNbl' and puts into 'tunKey'.
OvsDecapVxlan Decapsulates to tunnel header in ' curNbl ' and puts into ' tunKey ' .
NDIS_STATUS
OvsDecapVxlan(POVS_SWITCH_CONTEXT switchContext,
              PNET_BUFFER_LIST curNbl,
              OvsIPv4TunnelKey *tunKey,
              PNET_BUFFER_LIST *newNbl)
{
    PNET_BUFFER curNb;
    PMDL curMdl;
    EthHdr *ethHdr;
    IPHdr *ipHdr;
    UDPHdr *udpHdr;
    VXLANHdr *vxlanHdr;
    UINT32 tunnelSize, packetLength;
    PUINT8 bufferStart;
    NDIS_STATUS status;
    OVS_PACKET_HDR_INFO layers = { 0 };
    status = OvsExtractLayers(curNbl, &layers);
    if (status != NDIS_STATUS_SUCCESS) {
        return status;
    }
    curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);
    packetLength = NET_BUFFER_DATA_LENGTH(curNb);
    tunnelSize = OvsGetVxlanTunHdrSizeFromLayers(&layers);
    if (packetLength < tunnelSize) {
        return NDIS_STATUS_INVALID_LENGTH;
    }
    *newNbl = OvsPartialCopyNBL(switchContext, curNbl,
                                tunnelSize, 0,
                                TRUE );
    if (*newNbl == NULL) {
        return NDIS_STATUS_RESOURCES;
    }
    curNbl = *newNbl;
    curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);
    curMdl = NET_BUFFER_CURRENT_MDL(curNb);
    bufferStart = (PUINT8)OvsGetMdlWithLowPriority(curMdl)
        + NET_BUFFER_CURRENT_MDL_OFFSET(curNb);
    if (!bufferStart) {
        status = NDIS_STATUS_RESOURCES;
        goto dropNbl;
    }
    ethHdr = (EthHdr *)bufferStart;
    ipHdr = (IPHdr *)(bufferStart + layers.l3Offset);
    tunKey->src = ipHdr->saddr;
    tunKey->dst = ipHdr->daddr;
    tunKey->tos = ipHdr->tos;
    tunKey->ttl = ipHdr->ttl;
    tunKey->pad = 0;
    udpHdr = (UDPHdr *)(bufferStart + layers.l4Offset);
    status = OvsValidateUDPChecksum(curNbl, udpHdr->check == 0);
    if (status != NDIS_STATUS_SUCCESS) {
        goto dropNbl;
    }
    if (udpHdr->check != 0) {
        tunKey->flags |= OVS_TNL_F_CSUM;
        status = OvsCalculateUDPChecksum(curNbl, curNb, ipHdr, udpHdr,
                                         packetLength, &layers);
        if (status != NDIS_STATUS_SUCCESS) {
            goto dropNbl;
        }
    }
    vxlanHdr = (VXLANHdr *)((PCHAR)udpHdr + sizeof *udpHdr);
    if (vxlanHdr->instanceID) {
        tunKey->flags |= OVS_TNL_F_KEY;
        tunKey->tunnelId = VXLAN_VNI_TO_TUNNELID(vxlanHdr->vxlanID);
    } else {
        tunKey->flags &= ~OVS_TNL_F_KEY;
        tunKey->tunnelId = 0;
    }
    NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = 0;
    NdisAdvanceNetBufferDataStart(curNb, tunnelSize, FALSE, NULL);
    return NDIS_STATUS_SUCCESS;
dropNbl:
    OvsCompleteNBL(switchContext, *newNbl, TRUE);
    *newNbl = NULL;
    return status;
}
NDIS_STATUS OvsDecapVxlan ( POVS_SWITCH_CONTEXT switchContext , PNET_BUFFER_LIST curNbl , OvsIPv4TunnelKey * tunKey , PNET_BUFFER_LIST * newNbl ) { PNET_BUFFER curNb ; PMDL curMdl ; EthHdr * ethHdr ; IPHdr * ipHdr ; UDPHdr * udpHdr ; VXLANHdr * vxlanHdr ; UINT32 tunnelSize , packetLength ; PUINT8 bufferStart ; NDIS_STATUS status ; OVS_PACKET_HDR_INFO layers = { 0 } ; status = OvsExtractLayers ( curNbl , & layers ) ; if ( status != NDIS_STATUS_SUCCESS ) { return status ; } curNb = NET_BUFFER_LIST_FIRST_NB ( curNbl ) ; packetLength = NET_BUFFER_DATA_LENGTH ( curNb ) ; tunnelSize = OvsGetVxlanTunHdrSizeFromLayers ( & layers ) ; if ( packetLength < tunnelSize ) { return NDIS_STATUS_INVALID_LENGTH ; } * newNbl = OvsPartialCopyNBL ( switchContext , curNbl , tunnelSize , 0 , TRUE ) ; if ( * newNbl == NULL ) { return NDIS_STATUS_RESOURCES ; } curNbl = * newNbl ; curNb = NET_BUFFER_LIST_FIRST_NB ( curNbl ) ; curMdl = NET_BUFFER_CURRENT_MDL ( curNb ) ; bufferStart = ( PUINT8 ) OvsGetMdlWithLowPriority ( curMdl ) + NET_BUFFER_CURRENT_MDL_OFFSET ( curNb ) ; if ( ! bufferStart ) { status = NDIS_STATUS_RESOURCES ; goto dropNbl ; } ethHdr = ( EthHdr * ) bufferStart ; ipHdr = ( IPHdr * ) ( bufferStart + layers . l3Offset ) ; tunKey -> src = ipHdr -> saddr ; tunKey -> dst = ipHdr -> daddr ; tunKey -> tos = ipHdr -> tos ; tunKey -> ttl = ipHdr -> ttl ; tunKey -> pad = 0 ; udpHdr = ( UDPHdr * ) ( bufferStart + layers . l4Offset ) ; status = OvsValidateUDPChecksum ( curNbl , udpHdr -> check == 0 ) ; if ( status != NDIS_STATUS_SUCCESS ) { goto dropNbl ; } if ( udpHdr -> check != 0 ) { tunKey -> flags |= OVS_TNL_F_CSUM ; status = OvsCalculateUDPChecksum ( curNbl , curNb , ipHdr , udpHdr , packetLength , & layers ) ; if ( status != NDIS_STATUS_SUCCESS ) { goto dropNbl ; } } vxlanHdr = ( VXLANHdr * ) ( ( PCHAR ) udpHdr + sizeof * udpHdr ) ; if ( vxlanHdr -> instanceID ) { tunKey -> flags |= OVS_TNL_F_KEY ; tunKey -> tunnelId = VXLAN_VNI_TO_TUNNELID ( vxlanHdr -> vxlanID ) ; } else { tunKey -> flags &= ~ OVS_TNL_F_KEY ; tunKey -> tunnelId = 0 ; } NET_BUFFER_LIST_INFO ( curNbl , TcpIpChecksumNetBufferListInfo ) = 0 ; NdisAdvanceNetBufferDataStart ( curNb , tunnelSize , FALSE , NULL ) ; return NDIS_STATUS_SUCCESS ; dropNbl : OvsCompleteNBL ( switchContext , * newNbl , TRUE ) ; * newNbl = NULL ; return status ; }
OvsDecapVxlan
     Decapsulates to tunnel header in 'curNbl' and puts into 'tunKey'.
OvsDecapVxlan Decapsulates to tunnel header in ' curNbl ' and puts into ' tunKey ' .
/* Check the length of the UDP payload */ /*
     * Create a copy of the NBL so that we have all the headers in one MDL.
     */ /*copy NBL info */ /* XXX: Handle VLAN header. */ /* XXX: Handle IP options. */ /* Validate if NIC has indicated checksum failure. */ /* Calculate and verify UDP checksum if NIC didn't do it. */ /* Clear out the receive flag for the inner packet. */