aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei Yongjun <yongjun_wei@trendmicro.com.cn>2012-02-01 15:17:23 -0500
committerDavid S. Miller <davem@davemloft.net>2012-02-02 14:35:12 -0500
commit4b8a8bc9249f144803d840f2f7608ee9bbf1ea51 (patch)
tree90bd914ae5b4216a161db4cd52dedaa9bb16e6f9
parentc43b874d5d714f271b80d4c3f49e05d0cbf51ed2 (diff)
net/hyperv: fix the issue that large packets be dropped under bridge
The packets with size larger than 1452 will be dropped by bridge which with two hyperv netdevice ports. This cause by hyperv netvsc driver always copy the trailer padding to the data packet, and then the skb received from netdevice may include wrong skb->len (20 bytes larger than the real size normally). The captured packet may like this: Ethernet II, Src: Microsof_00:00:07 (00:15:5d:00:00:07), Dst: HewlettP_00:00:4e (00:1f:29:00:00:4e) Destination: HewlettP_e6:00:4e (00:1f:29:00:00:4e) Source: Microsof_f6:6d:07 (00:15:5d:f6:6d:07) Type: IP (0x0800) Trailer: 1415161718191A1B1C1D1E1F20212223 Frame check sequence: 0x24252627 [incorrect, should be 0x7c2e5a5e] The following command help to reproduction it, and the ping ICMP packets will be dropped by bridge. $ ping ip -s 1453 This patch fixed it by removing the trailer padding from the data packet. Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/hyperv/rndis_filter.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index da181f9a49d..dc2e3849573 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -321,6 +321,25 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
321 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset; 321 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
322 322
323 pkt->total_data_buflen -= data_offset; 323 pkt->total_data_buflen -= data_offset;
324
325 /*
326 * Make sure we got a valid RNDIS message, now total_data_buflen
327 * should be the data packet size plus the trailer padding size
328 */
329 if (pkt->total_data_buflen < rndis_pkt->data_len) {
330 netdev_err(dev->net_dev->ndev, "rndis message buffer "
331 "overflow detected (got %u, min %u)"
332 "...dropping this message!\n",
333 pkt->total_data_buflen, rndis_pkt->data_len);
334 return;
335 }
336
337 /*
338 * Remove the rndis trailer padding from rndis packet message
339 * rndis_pkt->data_len tell us the real data length, we only copy
340 * the data packet to the stack, without the rndis trailer padding
341 */
342 pkt->total_data_buflen = rndis_pkt->data_len;
324 pkt->data = (void *)((unsigned long)pkt->data + data_offset); 343 pkt->data = (void *)((unsigned long)pkt->data + data_offset);
325 344
326 pkt->is_data_pkt = true; 345 pkt->is_data_pkt = true;