| 1 | Index: linux/VBoxNetFlt-linux.c
|
|---|
| 2 | ===================================================================
|
|---|
| 3 | --- linux/VBoxNetFlt-linux.c (revision 63112)
|
|---|
| 4 | +++ linux/VBoxNetFlt-linux.c (revision 63828)
|
|---|
| 5 | @@ -113,6 +113,18 @@
|
|---|
| 6 |
|
|---|
| 7 | #endif
|
|---|
| 8 |
|
|---|
| 9 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
|
|---|
| 10 | +/** This enables or disables handling of GSO frames coming from the wire (GRO). */
|
|---|
| 11 | +# define VBOXNETFLT_WITH_GRO 1
|
|---|
| 12 | +#endif
|
|---|
| 13 | +/*
|
|---|
| 14 | + * GRO support was backported to RHEL 5.4
|
|---|
| 15 | + */
|
|---|
| 16 | +#ifdef RHEL_RELEASE_CODE
|
|---|
| 17 | +# if RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(5, 4)
|
|---|
| 18 | +# define VBOXNETFLT_WITH_GRO 1
|
|---|
| 19 | +# endif
|
|---|
| 20 | +#endif
|
|---|
| 21 |
|
|---|
| 22 | /*******************************************************************************
|
|---|
| 23 | * Internal Functions *
|
|---|
| 24 | @@ -613,15 +625,6 @@
|
|---|
| 25 |
|
|---|
| 26 | Assert(!skb_shinfo(pBuf)->frag_list);
|
|---|
| 27 |
|
|---|
| 28 | - if (fSrc & INTNETTRUNKDIR_WIRE)
|
|---|
| 29 | - {
|
|---|
| 30 | - /*
|
|---|
| 31 | - * The packet came from wire, ethernet header was removed by device driver.
|
|---|
| 32 | - * Restore it.
|
|---|
| 33 | - */
|
|---|
| 34 | - skb_push(pBuf, ETH_HLEN);
|
|---|
| 35 | - }
|
|---|
| 36 | -
|
|---|
| 37 | if (!pGsoCtx)
|
|---|
| 38 | IntNetSgInitTempSegs(pSG, pBuf->len, cSegs, 0 /*cSegsUsed*/);
|
|---|
| 39 | else
|
|---|
| 40 | @@ -709,6 +712,7 @@
|
|---|
| 41 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
|
|---|
| 42 | Log3(("vboxNetFltLinuxPacketHandler: skb len=%u data_len=%u truesize=%u next=%p nr_frags=%u gso_size=%u gso_seqs=%u gso_type=%x frag_list=%p pkt_type=%x\n",
|
|---|
| 43 | pBuf->len, pBuf->data_len, pBuf->truesize, pBuf->next, skb_shinfo(pBuf)->nr_frags, skb_shinfo(pBuf)->gso_size, skb_shinfo(pBuf)->gso_segs, skb_shinfo(pBuf)->gso_type, skb_shinfo(pBuf)->frag_list, pBuf->pkt_type));
|
|---|
| 44 | + Log4(("vboxNetFltLinuxPacketHandler: packet dump follows:\n%.*Rhxd\n", pBuf->len-pBuf->data_len, skb_mac_header(pBuf)));
|
|---|
| 45 | #else
|
|---|
| 46 | Log3(("vboxNetFltLinuxPacketHandler: skb len=%u data_len=%u truesize=%u next=%p nr_frags=%u tso_size=%u tso_seqs=%u frag_list=%p pkt_type=%x\n",
|
|---|
| 47 | pBuf->len, pBuf->data_len, pBuf->truesize, pBuf->next, skb_shinfo(pBuf)->nr_frags, skb_shinfo(pBuf)->tso_size, skb_shinfo(pBuf)->tso_segs, skb_shinfo(pBuf)->frag_list, pBuf->pkt_type));
|
|---|
| 48 | @@ -751,6 +755,7 @@
|
|---|
| 49 | # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
|
|---|
| 50 | Log3(("vboxNetFltLinuxPacketHandler: skb copy len=%u data_len=%u truesize=%u next=%p nr_frags=%u gso_size=%u gso_seqs=%u gso_type=%x frag_list=%p pkt_type=%x\n",
|
|---|
| 51 | pBuf->len, pBuf->data_len, pBuf->truesize, pBuf->next, skb_shinfo(pBuf)->nr_frags, skb_shinfo(pBuf)->gso_size, skb_shinfo(pBuf)->gso_segs, skb_shinfo(pBuf)->gso_type, skb_shinfo(pBuf)->frag_list, pBuf->pkt_type));
|
|---|
| 52 | + Log4(("vboxNetFltLinuxPacketHandler: packet dump follows:\n%.*Rhxd\n", pBuf->len-pBuf->data_len, skb_mac_header(pBuf)));
|
|---|
| 53 | # else
|
|---|
| 54 | Log3(("vboxNetFltLinuxPacketHandler: skb copy len=%u data_len=%u truesize=%u next=%p nr_frags=%u tso_size=%u tso_seqs=%u frag_list=%p pkt_type=%x\n",
|
|---|
| 55 | pBuf->len, pBuf->data_len, pBuf->truesize, pBuf->next, skb_shinfo(pBuf)->nr_frags, skb_shinfo(pBuf)->tso_size, skb_shinfo(pBuf)->tso_segs, skb_shinfo(pBuf)->frag_list, pBuf->pkt_type));
|
|---|
| 56 | @@ -889,22 +894,39 @@
|
|---|
| 57 | Log5(("vboxNetFltLinuxCanForwardAsGso: gso_size=%#x skb_len=%#x (max=%#x)\n", skb_shinfo(pSkb)->gso_size, pSkb->len, VBOX_MAX_GSO_SIZE));
|
|---|
| 58 | return false;
|
|---|
| 59 | }
|
|---|
| 60 | + /*
|
|---|
| 61 | + * It is possible to receive GSO packets from wire if GRO is enabled.
|
|---|
| 62 | + */
|
|---|
| 63 | if (RT_UNLIKELY(fSrc & INTNETTRUNKDIR_WIRE))
|
|---|
| 64 | {
|
|---|
| 65 | Log5(("vboxNetFltLinuxCanForwardAsGso: fSrc=wire\n"));
|
|---|
| 66 | +#ifdef VBOXNETFLT_WITH_GRO
|
|---|
| 67 | + /*
|
|---|
| 68 | + * The packet came from the wire and the driver has already consumed
|
|---|
| 69 | + * mac header. We need to restore it back.
|
|---|
| 70 | + */
|
|---|
| 71 | + pSkb->mac_len = skb_network_header(pSkb) - skb_mac_header(pSkb);
|
|---|
| 72 | + skb_push(pSkb, pSkb->mac_len);
|
|---|
| 73 | + Log5(("vboxNetFltLinuxCanForwardAsGso: mac_len=%d data=%p mac_header=%p network_header=%p\n",
|
|---|
| 74 | + pSkb->mac_len, pSkb->data, skb_mac_header(pSkb), skb_network_header(pSkb)));
|
|---|
| 75 | +#else /* !VBOXNETFLT_WITH_GRO */
|
|---|
| 76 | + /* Older kernels didn't have GRO. */
|
|---|
| 77 | return false;
|
|---|
| 78 | +#endif /* !VBOXNETFLT_WITH_GRO */
|
|---|
| 79 | }
|
|---|
| 80 | -
|
|---|
| 81 | - /*
|
|---|
| 82 | - * skb_gso_segment does the following. Do we need to do it as well?
|
|---|
| 83 | - */
|
|---|
| 84 | + else
|
|---|
| 85 | + {
|
|---|
| 86 | + /*
|
|---|
| 87 | + * skb_gso_segment does the following. Do we need to do it as well?
|
|---|
| 88 | + */
|
|---|
| 89 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
|
|---|
| 90 | - skb_reset_mac_header(pSkb);
|
|---|
| 91 | - pSkb->mac_len = pSkb->network_header - pSkb->mac_header;
|
|---|
| 92 | + skb_reset_mac_header(pSkb);
|
|---|
| 93 | + pSkb->mac_len = pSkb->network_header - pSkb->mac_header;
|
|---|
| 94 | #else
|
|---|
| 95 | - pSkb->mac.raw = pSkb->data;
|
|---|
| 96 | - pSkb->mac_len = pSkb->nh.raw - pSkb->data;
|
|---|
| 97 | + pSkb->mac.raw = pSkb->data;
|
|---|
| 98 | + pSkb->mac_len = pSkb->nh.raw - pSkb->data;
|
|---|
| 99 | #endif
|
|---|
| 100 | + }
|
|---|
| 101 |
|
|---|
| 102 | /*
|
|---|
| 103 | * Switch on the ethertype.
|
|---|
| 104 | @@ -1102,6 +1124,15 @@
|
|---|
| 105 | PINTNETSG pSG = (PINTNETSG)alloca(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
|
|---|
| 106 | if (RT_LIKELY(pSG))
|
|---|
| 107 | {
|
|---|
| 108 | + if (fSrc & INTNETTRUNKDIR_WIRE)
|
|---|
| 109 | + {
|
|---|
| 110 | + /*
|
|---|
| 111 | + * The packet came from wire, ethernet header was removed by device driver.
|
|---|
| 112 | + * Restore it.
|
|---|
| 113 | + */
|
|---|
| 114 | + skb_push(pBuf, ETH_HLEN);
|
|---|
| 115 | + }
|
|---|
| 116 | +
|
|---|
| 117 | vboxNetFltLinuxSkBufToSG(pThis, pBuf, pSG, cSegs, fSrc, NULL /*pGsoCtx*/);
|
|---|
| 118 |
|
|---|
| 119 | vboxNetFltDumpPacket(pSG, false, (fSrc & INTNETTRUNKDIR_HOST) ? "host" : "wire", 1);
|
|---|