aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/xen-netback/netback.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/xen-netback/netback.c')
-rw-r--r--drivers/net/xen-netback/netback.c288
1 files changed, 167 insertions, 121 deletions
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 919b6509455c..78425554a537 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -39,6 +39,7 @@
39#include <linux/udp.h> 39#include <linux/udp.h>
40 40
41#include <net/tcp.h> 41#include <net/tcp.h>
42#include <net/ip6_checksum.h>
42 43
43#include <xen/xen.h> 44#include <xen/xen.h>
44#include <xen/events.h> 45#include <xen/events.h>
@@ -451,7 +452,7 @@ static int xenvif_gop_skb(struct sk_buff *skb,
451 } 452 }
452 453
453 /* Set up a GSO prefix descriptor, if necessary */ 454 /* Set up a GSO prefix descriptor, if necessary */
454 if ((1 << skb_shinfo(skb)->gso_type) & vif->gso_prefix_mask) { 455 if ((1 << gso_type) & vif->gso_prefix_mask) {
455 req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++); 456 req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++);
456 meta = npo->meta + npo->meta_prod++; 457 meta = npo->meta + npo->meta_prod++;
457 meta->gso_type = gso_type; 458 meta->gso_type = gso_type;
@@ -607,7 +608,7 @@ void xenvif_rx_action(struct xenvif *vif)
607 if (!npo.copy_prod) 608 if (!npo.copy_prod)
608 return; 609 return;
609 610
610 BUG_ON(npo.copy_prod > ARRAY_SIZE(vif->grant_copy_op)); 611 BUG_ON(npo.copy_prod > MAX_GRANT_COPY_OPS);
611 gnttab_batch_copy(vif->grant_copy_op, npo.copy_prod); 612 gnttab_batch_copy(vif->grant_copy_op, npo.copy_prod);
612 613
613 while ((skb = __skb_dequeue(&rxq)) != NULL) { 614 while ((skb = __skb_dequeue(&rxq)) != NULL) {
@@ -1148,75 +1149,99 @@ static int xenvif_set_skb_gso(struct xenvif *vif,
1148 return 0; 1149 return 0;
1149} 1150}
1150 1151
1151static inline void maybe_pull_tail(struct sk_buff *skb, unsigned int len) 1152static inline int maybe_pull_tail(struct sk_buff *skb, unsigned int len,
1153 unsigned int max)
1152{ 1154{
1153 if (skb_is_nonlinear(skb) && skb_headlen(skb) < len) { 1155 if (skb_headlen(skb) >= len)
1154 /* If we need to pullup then pullup to the max, so we 1156 return 0;
1155 * won't need to do it again. 1157
1156 */ 1158 /* If we need to pullup then pullup to the max, so we
1157 int target = min_t(int, skb->len, MAX_TCP_HEADER); 1159 * won't need to do it again.
1158 __pskb_pull_tail(skb, target - skb_headlen(skb)); 1160 */
1159 } 1161 if (max > skb->len)
1162 max = skb->len;
1163
1164 if (__pskb_pull_tail(skb, max - skb_headlen(skb)) == NULL)
1165 return -ENOMEM;
1166
1167 if (skb_headlen(skb) < len)
1168 return -EPROTO;
1169
1170 return 0;
1160} 1171}
1161 1172
1173/* This value should be large enough to cover a tagged ethernet header plus
1174 * maximally sized IP and TCP or UDP headers.
1175 */
1176#define MAX_IP_HDR_LEN 128
1177
1162static int checksum_setup_ip(struct xenvif *vif, struct sk_buff *skb, 1178static int checksum_setup_ip(struct xenvif *vif, struct sk_buff *skb,
1163 int recalculate_partial_csum) 1179 int recalculate_partial_csum)
1164{ 1180{
1165 struct iphdr *iph = (void *)skb->data;
1166 unsigned int header_size;
1167 unsigned int off; 1181 unsigned int off;
1168 int err = -EPROTO; 1182 bool fragment;
1183 int err;
1169 1184
1170 off = sizeof(struct iphdr); 1185 fragment = false;
1171 1186
1172 header_size = skb->network_header + off + MAX_IPOPTLEN; 1187 err = maybe_pull_tail(skb,
1173 maybe_pull_tail(skb, header_size); 1188 sizeof(struct iphdr),
1189 MAX_IP_HDR_LEN);
1190 if (err < 0)
1191 goto out;
1174 1192
1175 off = iph->ihl * 4; 1193 if (ip_hdr(skb)->frag_off & htons(IP_OFFSET | IP_MF))
1194 fragment = true;
1176 1195
1177 switch (iph->protocol) { 1196 off = ip_hdrlen(skb);
1178 case IPPROTO_TCP:
1179 if (!skb_partial_csum_set(skb, off,
1180 offsetof(struct tcphdr, check)))
1181 goto out;
1182 1197
1183 if (recalculate_partial_csum) { 1198 err = -EPROTO;
1184 struct tcphdr *tcph = tcp_hdr(skb); 1199
1200 if (fragment)
1201 goto out;
1185 1202
1186 header_size = skb->network_header + 1203 switch (ip_hdr(skb)->protocol) {
1187 off + 1204 case IPPROTO_TCP:
1188 sizeof(struct tcphdr); 1205 err = maybe_pull_tail(skb,
1189 maybe_pull_tail(skb, header_size); 1206 off + sizeof(struct tcphdr),
1207 MAX_IP_HDR_LEN);
1208 if (err < 0)
1209 goto out;
1190 1210
1191 tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, 1211 if (!skb_partial_csum_set(skb, off,
1192 skb->len - off, 1212 offsetof(struct tcphdr, check))) {
1193 IPPROTO_TCP, 0); 1213 err = -EPROTO;
1214 goto out;
1194 } 1215 }
1216
1217 if (recalculate_partial_csum)
1218 tcp_hdr(skb)->check =
1219 ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
1220 ip_hdr(skb)->daddr,
1221 skb->len - off,
1222 IPPROTO_TCP, 0);
1195 break; 1223 break;
1196 case IPPROTO_UDP: 1224 case IPPROTO_UDP:
1197 if (!skb_partial_csum_set(skb, off, 1225 err = maybe_pull_tail(skb,
1198 offsetof(struct udphdr, check))) 1226 off + sizeof(struct udphdr),
1227 MAX_IP_HDR_LEN);
1228 if (err < 0)
1199 goto out; 1229 goto out;
1200 1230
1201 if (recalculate_partial_csum) { 1231 if (!skb_partial_csum_set(skb, off,
1202 struct udphdr *udph = udp_hdr(skb); 1232 offsetof(struct udphdr, check))) {
1203 1233 err = -EPROTO;
1204 header_size = skb->network_header + 1234 goto out;
1205 off +
1206 sizeof(struct udphdr);
1207 maybe_pull_tail(skb, header_size);
1208
1209 udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
1210 skb->len - off,
1211 IPPROTO_UDP, 0);
1212 } 1235 }
1236
1237 if (recalculate_partial_csum)
1238 udp_hdr(skb)->check =
1239 ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
1240 ip_hdr(skb)->daddr,
1241 skb->len - off,
1242 IPPROTO_UDP, 0);
1213 break; 1243 break;
1214 default: 1244 default:
1215 if (net_ratelimit())
1216 netdev_err(vif->dev,
1217 "Attempting to checksum a non-TCP/UDP packet, "
1218 "dropping a protocol %d packet\n",
1219 iph->protocol);
1220 goto out; 1245 goto out;
1221 } 1246 }
1222 1247
@@ -1226,121 +1251,142 @@ out:
1226 return err; 1251 return err;
1227} 1252}
1228 1253
1254/* This value should be large enough to cover a tagged ethernet header plus
1255 * an IPv6 header, all options, and a maximal TCP or UDP header.
1256 */
1257#define MAX_IPV6_HDR_LEN 256
1258
1259#define OPT_HDR(type, skb, off) \
1260 (type *)(skb_network_header(skb) + (off))
1261
1229static int checksum_setup_ipv6(struct xenvif *vif, struct sk_buff *skb, 1262static int checksum_setup_ipv6(struct xenvif *vif, struct sk_buff *skb,
1230 int recalculate_partial_csum) 1263 int recalculate_partial_csum)
1231{ 1264{
1232 int err = -EPROTO; 1265 int err;
1233 struct ipv6hdr *ipv6h = (void *)skb->data;
1234 u8 nexthdr; 1266 u8 nexthdr;
1235 unsigned int header_size;
1236 unsigned int off; 1267 unsigned int off;
1268 unsigned int len;
1237 bool fragment; 1269 bool fragment;
1238 bool done; 1270 bool done;
1239 1271
1272 fragment = false;
1240 done = false; 1273 done = false;
1241 1274
1242 off = sizeof(struct ipv6hdr); 1275 off = sizeof(struct ipv6hdr);
1243 1276
1244 header_size = skb->network_header + off; 1277 err = maybe_pull_tail(skb, off, MAX_IPV6_HDR_LEN);
1245 maybe_pull_tail(skb, header_size); 1278 if (err < 0)
1279 goto out;
1246 1280
1247 nexthdr = ipv6h->nexthdr; 1281 nexthdr = ipv6_hdr(skb)->nexthdr;
1248 1282
1249 while ((off <= sizeof(struct ipv6hdr) + ntohs(ipv6h->payload_len)) && 1283 len = sizeof(struct ipv6hdr) + ntohs(ipv6_hdr(skb)->payload_len);
1250 !done) { 1284 while (off <= len && !done) {
1251 switch (nexthdr) { 1285 switch (nexthdr) {
1252 case IPPROTO_DSTOPTS: 1286 case IPPROTO_DSTOPTS:
1253 case IPPROTO_HOPOPTS: 1287 case IPPROTO_HOPOPTS:
1254 case IPPROTO_ROUTING: { 1288 case IPPROTO_ROUTING: {
1255 struct ipv6_opt_hdr *hp = (void *)(skb->data + off); 1289 struct ipv6_opt_hdr *hp;
1256 1290
1257 header_size = skb->network_header + 1291 err = maybe_pull_tail(skb,
1258 off + 1292 off +
1259 sizeof(struct ipv6_opt_hdr); 1293 sizeof(struct ipv6_opt_hdr),
1260 maybe_pull_tail(skb, header_size); 1294 MAX_IPV6_HDR_LEN);
1295 if (err < 0)
1296 goto out;
1261 1297
1298 hp = OPT_HDR(struct ipv6_opt_hdr, skb, off);
1262 nexthdr = hp->nexthdr; 1299 nexthdr = hp->nexthdr;
1263 off += ipv6_optlen(hp); 1300 off += ipv6_optlen(hp);
1264 break; 1301 break;
1265 } 1302 }
1266 case IPPROTO_AH: { 1303 case IPPROTO_AH: {
1267 struct ip_auth_hdr *hp = (void *)(skb->data + off); 1304 struct ip_auth_hdr *hp;
1268 1305
1269 header_size = skb->network_header + 1306 err = maybe_pull_tail(skb,
1270 off + 1307 off +
1271 sizeof(struct ip_auth_hdr); 1308 sizeof(struct ip_auth_hdr),
1272 maybe_pull_tail(skb, header_size); 1309 MAX_IPV6_HDR_LEN);
1310 if (err < 0)
1311 goto out;
1273 1312
1313 hp = OPT_HDR(struct ip_auth_hdr, skb, off);
1274 nexthdr = hp->nexthdr; 1314 nexthdr = hp->nexthdr;
1275 off += (hp->hdrlen+2)<<2; 1315 off += ipv6_authlen(hp);
1316 break;
1317 }
1318 case IPPROTO_FRAGMENT: {
1319 struct frag_hdr *hp;
1320
1321 err = maybe_pull_tail(skb,
1322 off +
1323 sizeof(struct frag_hdr),
1324 MAX_IPV6_HDR_LEN);
1325 if (err < 0)
1326 goto out;
1327
1328 hp = OPT_HDR(struct frag_hdr, skb, off);
1329
1330 if (hp->frag_off & htons(IP6_OFFSET | IP6_MF))
1331 fragment = true;
1332
1333 nexthdr = hp->nexthdr;
1334 off += sizeof(struct frag_hdr);
1276 break; 1335 break;
1277 } 1336 }
1278 case IPPROTO_FRAGMENT:
1279 fragment = true;
1280 /* fall through */
1281 default: 1337 default:
1282 done = true; 1338 done = true;
1283 break; 1339 break;
1284 } 1340 }
1285 } 1341 }
1286 1342
1287 if (!done) { 1343 err = -EPROTO;
1288 if (net_ratelimit())
1289 netdev_err(vif->dev, "Failed to parse packet header\n");
1290 goto out;
1291 }
1292 1344
1293 if (fragment) { 1345 if (!done || fragment)
1294 if (net_ratelimit())
1295 netdev_err(vif->dev, "Packet is a fragment!\n");
1296 goto out; 1346 goto out;
1297 }
1298 1347
1299 switch (nexthdr) { 1348 switch (nexthdr) {
1300 case IPPROTO_TCP: 1349 case IPPROTO_TCP:
1301 if (!skb_partial_csum_set(skb, off, 1350 err = maybe_pull_tail(skb,
1302 offsetof(struct tcphdr, check))) 1351 off + sizeof(struct tcphdr),
1352 MAX_IPV6_HDR_LEN);
1353 if (err < 0)
1303 goto out; 1354 goto out;
1304 1355
1305 if (recalculate_partial_csum) { 1356 if (!skb_partial_csum_set(skb, off,
1306 struct tcphdr *tcph = tcp_hdr(skb); 1357 offsetof(struct tcphdr, check))) {
1307 1358 err = -EPROTO;
1308 header_size = skb->network_header + 1359 goto out;
1309 off +
1310 sizeof(struct tcphdr);
1311 maybe_pull_tail(skb, header_size);
1312
1313 tcph->check = ~csum_ipv6_magic(&ipv6h->saddr,
1314 &ipv6h->daddr,
1315 skb->len - off,
1316 IPPROTO_TCP, 0);
1317 } 1360 }
1361
1362 if (recalculate_partial_csum)
1363 tcp_hdr(skb)->check =
1364 ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
1365 &ipv6_hdr(skb)->daddr,
1366 skb->len - off,
1367 IPPROTO_TCP, 0);
1318 break; 1368 break;
1319 case IPPROTO_UDP: 1369 case IPPROTO_UDP:
1320 if (!skb_partial_csum_set(skb, off, 1370 err = maybe_pull_tail(skb,
1321 offsetof(struct udphdr, check))) 1371 off + sizeof(struct udphdr),
1372 MAX_IPV6_HDR_LEN);
1373 if (err < 0)
1322 goto out; 1374 goto out;
1323 1375
1324 if (recalculate_partial_csum) { 1376 if (!skb_partial_csum_set(skb, off,
1325 struct udphdr *udph = udp_hdr(skb); 1377 offsetof(struct udphdr, check))) {
1326 1378 err = -EPROTO;
1327 header_size = skb->network_header + 1379 goto out;
1328 off +
1329 sizeof(struct udphdr);
1330 maybe_pull_tail(skb, header_size);
1331
1332 udph->check = ~csum_ipv6_magic(&ipv6h->saddr,
1333 &ipv6h->daddr,
1334 skb->len - off,
1335 IPPROTO_UDP, 0);
1336 } 1380 }
1381
1382 if (recalculate_partial_csum)
1383 udp_hdr(skb)->check =
1384 ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
1385 &ipv6_hdr(skb)->daddr,
1386 skb->len - off,
1387 IPPROTO_UDP, 0);
1337 break; 1388 break;
1338 default: 1389 default:
1339 if (net_ratelimit())
1340 netdev_err(vif->dev,
1341 "Attempting to checksum a non-TCP/UDP packet, "
1342 "dropping a protocol %d packet\n",
1343 nexthdr);
1344 goto out; 1390 goto out;
1345 } 1391 }
1346 1392
@@ -1410,14 +1456,15 @@ static bool tx_credit_exceeded(struct xenvif *vif, unsigned size)
1410 return false; 1456 return false;
1411} 1457}
1412 1458
1413static unsigned xenvif_tx_build_gops(struct xenvif *vif) 1459static unsigned xenvif_tx_build_gops(struct xenvif *vif, int budget)
1414{ 1460{
1415 struct gnttab_copy *gop = vif->tx_copy_ops, *request_gop; 1461 struct gnttab_copy *gop = vif->tx_copy_ops, *request_gop;
1416 struct sk_buff *skb; 1462 struct sk_buff *skb;
1417 int ret; 1463 int ret;
1418 1464
1419 while ((nr_pending_reqs(vif) + XEN_NETBK_LEGACY_SLOTS_MAX 1465 while ((nr_pending_reqs(vif) + XEN_NETBK_LEGACY_SLOTS_MAX
1420 < MAX_PENDING_REQS)) { 1466 < MAX_PENDING_REQS) &&
1467 (skb_queue_len(&vif->tx_queue) < budget)) {
1421 struct xen_netif_tx_request txreq; 1468 struct xen_netif_tx_request txreq;
1422 struct xen_netif_tx_request txfrags[XEN_NETBK_LEGACY_SLOTS_MAX]; 1469 struct xen_netif_tx_request txfrags[XEN_NETBK_LEGACY_SLOTS_MAX];
1423 struct page *page; 1470 struct page *page;
@@ -1439,7 +1486,7 @@ static unsigned xenvif_tx_build_gops(struct xenvif *vif)
1439 continue; 1486 continue;
1440 } 1487 }
1441 1488
1442 RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do); 1489 work_to_do = RING_HAS_UNCONSUMED_REQUESTS(&vif->tx);
1443 if (!work_to_do) 1490 if (!work_to_do)
1444 break; 1491 break;
1445 1492
@@ -1579,14 +1626,13 @@ static unsigned xenvif_tx_build_gops(struct xenvif *vif)
1579} 1626}
1580 1627
1581 1628
1582static int xenvif_tx_submit(struct xenvif *vif, int budget) 1629static int xenvif_tx_submit(struct xenvif *vif)
1583{ 1630{
1584 struct gnttab_copy *gop = vif->tx_copy_ops; 1631 struct gnttab_copy *gop = vif->tx_copy_ops;
1585 struct sk_buff *skb; 1632 struct sk_buff *skb;
1586 int work_done = 0; 1633 int work_done = 0;
1587 1634
1588 while (work_done < budget && 1635 while ((skb = __skb_dequeue(&vif->tx_queue)) != NULL) {
1589 (skb = __skb_dequeue(&vif->tx_queue)) != NULL) {
1590 struct xen_netif_tx_request *txp; 1636 struct xen_netif_tx_request *txp;
1591 u16 pending_idx; 1637 u16 pending_idx;
1592 unsigned data_len; 1638 unsigned data_len;
@@ -1661,14 +1707,14 @@ int xenvif_tx_action(struct xenvif *vif, int budget)
1661 if (unlikely(!tx_work_todo(vif))) 1707 if (unlikely(!tx_work_todo(vif)))
1662 return 0; 1708 return 0;
1663 1709
1664 nr_gops = xenvif_tx_build_gops(vif); 1710 nr_gops = xenvif_tx_build_gops(vif, budget);
1665 1711
1666 if (nr_gops == 0) 1712 if (nr_gops == 0)
1667 return 0; 1713 return 0;
1668 1714
1669 gnttab_batch_copy(vif->tx_copy_ops, nr_gops); 1715 gnttab_batch_copy(vif->tx_copy_ops, nr_gops);
1670 1716
1671 work_done = xenvif_tx_submit(vif, nr_gops); 1717 work_done = xenvif_tx_submit(vif);
1672 1718
1673 return work_done; 1719 return work_done;
1674} 1720}