mirror of https://github.com/acidanthera/audk.git
OvmfPkg: VirtioNetDxe: adapt virtio-net packet header size to virtio-1.0
In virtio-0.9.5, the size of the virtio-net packet header depends on whether the VIRTIO_NET_F_MRG_RXBUF feature is negotiated -- the "num_buffers" field is only appended to the header if the feature is negotiated. Since we never negotiate this feature, VirtioNetDxe never allocates room for the "num_buffers" field. With virtio-1.0, the "num_buffers" field is always there (although it doesn't carry useful information without VIRTIO_NET_F_MRG_RXBUF). Adapt the buffers that depend on the virtio-net header size (otherwise we have skewed / truncated packets). Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Jordan Justen <jordan.l.justen@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
This commit is contained in:
parent
39c2d33962
commit
c6e2d064ab
|
@ -138,6 +138,7 @@ VirtioNetInitTx (
|
|||
IN OUT VNET_DEV *Dev
|
||||
)
|
||||
{
|
||||
UINTN TxSharedReqSize;
|
||||
UINTN PktIdx;
|
||||
|
||||
Dev->TxMaxPending = (UINT16) MIN (Dev->TxRing.QueueSize / 2,
|
||||
|
@ -149,6 +150,14 @@ VirtioNetInitTx (
|
|||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on
|
||||
// VIRTIO_NET_F_MRG_RXBUF, which we never negotiate.
|
||||
//
|
||||
TxSharedReqSize = (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) ?
|
||||
sizeof Dev->TxSharedReq.V0_9_5 :
|
||||
sizeof Dev->TxSharedReq;
|
||||
|
||||
for (PktIdx = 0; PktIdx < Dev->TxMaxPending; ++PktIdx) {
|
||||
UINT16 DescIdx;
|
||||
|
||||
|
@ -160,7 +169,7 @@ VirtioNetInitTx (
|
|||
// (unmodified by the host) virtio-net request header.
|
||||
//
|
||||
Dev->TxRing.Desc[DescIdx].Addr = (UINTN) &Dev->TxSharedReq;
|
||||
Dev->TxRing.Desc[DescIdx].Len = sizeof Dev->TxSharedReq;
|
||||
Dev->TxRing.Desc[DescIdx].Len = (UINT32) TxSharedReqSize;
|
||||
Dev->TxRing.Desc[DescIdx].Flags = VRING_DESC_F_NEXT;
|
||||
Dev->TxRing.Desc[DescIdx].Next = (UINT16) (DescIdx + 1);
|
||||
|
||||
|
@ -174,8 +183,13 @@ VirtioNetInitTx (
|
|||
//
|
||||
// virtio-0.9.5, Appendix C, Packet Transmission
|
||||
//
|
||||
Dev->TxSharedReq.Flags = 0;
|
||||
Dev->TxSharedReq.GsoType = VIRTIO_NET_HDR_GSO_NONE;
|
||||
Dev->TxSharedReq.V0_9_5.Flags = 0;
|
||||
Dev->TxSharedReq.V0_9_5.GsoType = VIRTIO_NET_HDR_GSO_NONE;
|
||||
|
||||
//
|
||||
// For VirtIo 1.0 only -- the field exists, but it is unused
|
||||
//
|
||||
Dev->TxSharedReq.NumBuffers = 0;
|
||||
|
||||
//
|
||||
// virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device
|
||||
|
@ -223,19 +237,28 @@ VirtioNetInitRx (
|
|||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN VirtioNetReqSize;
|
||||
UINTN RxBufSize;
|
||||
UINT16 RxAlwaysPending;
|
||||
UINTN PktIdx;
|
||||
UINT16 DescIdx;
|
||||
UINT8 *RxPtr;
|
||||
|
||||
//
|
||||
// In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on
|
||||
// VIRTIO_NET_F_MRG_RXBUF, which we never negotiate.
|
||||
//
|
||||
VirtioNetReqSize = (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) ?
|
||||
sizeof (VIRTIO_NET_REQ) :
|
||||
sizeof (VIRTIO_1_0_NET_REQ);
|
||||
|
||||
//
|
||||
// For each incoming packet we must supply two descriptors:
|
||||
// - the recipient for the virtio-net request header, plus
|
||||
// - the recipient for the network data (which consists of Ethernet header
|
||||
// and Ethernet payload).
|
||||
//
|
||||
RxBufSize = sizeof (VIRTIO_NET_REQ) +
|
||||
RxBufSize = VirtioNetReqSize +
|
||||
(Dev->Snm.MediaHeaderSize + Dev->Snm.MaxPacketSize);
|
||||
|
||||
//
|
||||
|
@ -280,14 +303,13 @@ VirtioNetInitRx (
|
|||
// virtio-0.9.5, 2.4.1.1 Placing Buffers into the Descriptor Table
|
||||
//
|
||||
Dev->RxRing.Desc[DescIdx].Addr = (UINTN) RxPtr;
|
||||
Dev->RxRing.Desc[DescIdx].Len = sizeof (VIRTIO_NET_REQ);
|
||||
Dev->RxRing.Desc[DescIdx].Len = (UINT32) VirtioNetReqSize;
|
||||
Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE | VRING_DESC_F_NEXT;
|
||||
Dev->RxRing.Desc[DescIdx].Next = (UINT16) (DescIdx + 1);
|
||||
RxPtr += Dev->RxRing.Desc[DescIdx++].Len;
|
||||
|
||||
Dev->RxRing.Desc[DescIdx].Addr = (UINTN) RxPtr;
|
||||
Dev->RxRing.Desc[DescIdx].Len = (UINT32) (RxBufSize -
|
||||
sizeof (VIRTIO_NET_REQ));
|
||||
Dev->RxRing.Desc[DescIdx].Len = (UINT32) (RxBufSize - VirtioNetReqSize);
|
||||
Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE;
|
||||
RxPtr += Dev->RxRing.Desc[DescIdx++].Len;
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ typedef struct {
|
|||
UINT16 TxMaxPending; // VirtioNetInitTx
|
||||
UINT16 TxCurPending; // VirtioNetInitTx
|
||||
UINT16 *TxFreeStack; // VirtioNetInitTx
|
||||
VIRTIO_NET_REQ TxSharedReq; // VirtioNetInitTx
|
||||
VIRTIO_1_0_NET_REQ TxSharedReq; // VirtioNetInitTx
|
||||
UINT16 TxLastUsed; // VirtioNetInitTx
|
||||
} VNET_DEV;
|
||||
|
||||
|
|
Loading…
Reference in New Issue