diff options
author | Ben Greear <greearb@candelatech.com> | 2012-02-11 10:39:30 -0500 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2012-02-24 04:37:35 -0500 |
commit | 3bdc0eba0b8b47797f4a76e377dd8360f317450f (patch) | |
tree | da6bd907f599402bc8db0a2484997fd4d3e06f7b /net/packet/af_packet.c | |
parent | 0184039a4b6727d6efd545919c773ef141090ae7 (diff) |
net: Add framework to allow sending packets with customized CRC.
This is useful for testing RX handling of frames with bad
CRCs.
Requires driver support to actually put the packet on the
wire properly.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r-- | net/packet/af_packet.c | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 2dbb32b988c4..ae2d484416dd 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -1459,6 +1459,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock, | |||
1459 | struct net_device *dev; | 1459 | struct net_device *dev; |
1460 | __be16 proto = 0; | 1460 | __be16 proto = 0; |
1461 | int err; | 1461 | int err; |
1462 | int extra_len = 0; | ||
1462 | 1463 | ||
1463 | /* | 1464 | /* |
1464 | * Get and verify the address. | 1465 | * Get and verify the address. |
@@ -1493,8 +1494,16 @@ retry: | |||
1493 | * raw protocol and you must do your own fragmentation at this level. | 1494 | * raw protocol and you must do your own fragmentation at this level. |
1494 | */ | 1495 | */ |
1495 | 1496 | ||
1497 | if (unlikely(sock_flag(sk, SOCK_NOFCS))) { | ||
1498 | if (!netif_supports_nofcs(dev)) { | ||
1499 | err = -EPROTONOSUPPORT; | ||
1500 | goto out_unlock; | ||
1501 | } | ||
1502 | extra_len = 4; /* We're doing our own CRC */ | ||
1503 | } | ||
1504 | |||
1496 | err = -EMSGSIZE; | 1505 | err = -EMSGSIZE; |
1497 | if (len > dev->mtu + dev->hard_header_len + VLAN_HLEN) | 1506 | if (len > dev->mtu + dev->hard_header_len + VLAN_HLEN + extra_len) |
1498 | goto out_unlock; | 1507 | goto out_unlock; |
1499 | 1508 | ||
1500 | if (!skb) { | 1509 | if (!skb) { |
@@ -1526,7 +1535,7 @@ retry: | |||
1526 | goto retry; | 1535 | goto retry; |
1527 | } | 1536 | } |
1528 | 1537 | ||
1529 | if (len > (dev->mtu + dev->hard_header_len)) { | 1538 | if (len > (dev->mtu + dev->hard_header_len + extra_len)) { |
1530 | /* Earlier code assumed this would be a VLAN pkt, | 1539 | /* Earlier code assumed this would be a VLAN pkt, |
1531 | * double-check this now that we have the actual | 1540 | * double-check this now that we have the actual |
1532 | * packet in hand. | 1541 | * packet in hand. |
@@ -1548,6 +1557,9 @@ retry: | |||
1548 | if (err < 0) | 1557 | if (err < 0) |
1549 | goto out_unlock; | 1558 | goto out_unlock; |
1550 | 1559 | ||
1560 | if (unlikely(extra_len == 4)) | ||
1561 | skb->no_fcs = 1; | ||
1562 | |||
1551 | dev_queue_xmit(skb); | 1563 | dev_queue_xmit(skb); |
1552 | rcu_read_unlock(); | 1564 | rcu_read_unlock(); |
1553 | return len; | 1565 | return len; |
@@ -2209,6 +2221,7 @@ static int packet_snd(struct socket *sock, | |||
2209 | struct packet_sock *po = pkt_sk(sk); | 2221 | struct packet_sock *po = pkt_sk(sk); |
2210 | unsigned short gso_type = 0; | 2222 | unsigned short gso_type = 0; |
2211 | int hlen, tlen; | 2223 | int hlen, tlen; |
2224 | int extra_len = 0; | ||
2212 | 2225 | ||
2213 | /* | 2226 | /* |
2214 | * Get and verify the address. | 2227 | * Get and verify the address. |
@@ -2288,8 +2301,16 @@ static int packet_snd(struct socket *sock, | |||
2288 | } | 2301 | } |
2289 | } | 2302 | } |
2290 | 2303 | ||
2304 | if (unlikely(sock_flag(sk, SOCK_NOFCS))) { | ||
2305 | if (!netif_supports_nofcs(dev)) { | ||
2306 | err = -EPROTONOSUPPORT; | ||
2307 | goto out_unlock; | ||
2308 | } | ||
2309 | extra_len = 4; /* We're doing our own CRC */ | ||
2310 | } | ||
2311 | |||
2291 | err = -EMSGSIZE; | 2312 | err = -EMSGSIZE; |
2292 | if (!gso_type && (len > dev->mtu + reserve + VLAN_HLEN)) | 2313 | if (!gso_type && (len > dev->mtu + reserve + VLAN_HLEN + extra_len)) |
2293 | goto out_unlock; | 2314 | goto out_unlock; |
2294 | 2315 | ||
2295 | err = -ENOBUFS; | 2316 | err = -ENOBUFS; |
@@ -2315,7 +2336,7 @@ static int packet_snd(struct socket *sock, | |||
2315 | if (err < 0) | 2336 | if (err < 0) |
2316 | goto out_free; | 2337 | goto out_free; |
2317 | 2338 | ||
2318 | if (!gso_type && (len > dev->mtu + reserve)) { | 2339 | if (!gso_type && (len > dev->mtu + reserve + extra_len)) { |
2319 | /* Earlier code assumed this would be a VLAN pkt, | 2340 | /* Earlier code assumed this would be a VLAN pkt, |
2320 | * double-check this now that we have the actual | 2341 | * double-check this now that we have the actual |
2321 | * packet in hand. | 2342 | * packet in hand. |
@@ -2353,6 +2374,9 @@ static int packet_snd(struct socket *sock, | |||
2353 | len += vnet_hdr_len; | 2374 | len += vnet_hdr_len; |
2354 | } | 2375 | } |
2355 | 2376 | ||
2377 | if (unlikely(extra_len == 4)) | ||
2378 | skb->no_fcs = 1; | ||
2379 | |||
2356 | /* | 2380 | /* |
2357 | * Now send it | 2381 | * Now send it |
2358 | */ | 2382 | */ |