ip6_output.c (989a4222c13a3e148772730d362fceb0727852f5) | ip6_output.c (b5947e5d1e710c35ea281247bd27e6975250285c) |
---|---|
1/* 2 * IPv6 output functions 3 * Linux INET6 implementation 4 * 5 * Authors: 6 * Pedro Roque <roque@di.fc.ul.pt> 7 * 8 * Based on linux/net/ipv4/ip_output.c --- 1231 unchanged lines hidden (view full) --- 1240 struct page_frag *pfrag, 1241 int getfrag(void *from, char *to, int offset, 1242 int len, int odd, struct sk_buff *skb), 1243 void *from, int length, int transhdrlen, 1244 unsigned int flags, struct ipcm6_cookie *ipc6) 1245{ 1246 struct sk_buff *skb, *skb_prev = NULL; 1247 unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu, pmtu; | 1/* 2 * IPv6 output functions 3 * Linux INET6 implementation 4 * 5 * Authors: 6 * Pedro Roque <roque@di.fc.ul.pt> 7 * 8 * Based on linux/net/ipv4/ip_output.c --- 1231 unchanged lines hidden (view full) --- 1240 struct page_frag *pfrag, 1241 int getfrag(void *from, char *to, int offset, 1242 int len, int odd, struct sk_buff *skb), 1243 void *from, int length, int transhdrlen, 1244 unsigned int flags, struct ipcm6_cookie *ipc6) 1245{ 1246 struct sk_buff *skb, *skb_prev = NULL; 1247 unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu, pmtu; |
1248 struct ubuf_info *uarg = NULL; |
|
1248 int exthdrlen = 0; 1249 int dst_exthdrlen = 0; 1250 int hh_len; 1251 int copy; 1252 int err; 1253 int offset = 0; 1254 u32 tskey = 0; 1255 struct rt6_info *rt = (struct rt6_info *)cork->dst; --- 61 unchanged lines hidden (view full) --- 1317 */ 1318 if (transhdrlen && sk->sk_protocol == IPPROTO_UDP && 1319 headersize == sizeof(struct ipv6hdr) && 1320 length <= mtu - headersize && 1321 (!(flags & MSG_MORE) || cork->gso_size) && 1322 rt->dst.dev->features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM)) 1323 csummode = CHECKSUM_PARTIAL; 1324 | 1249 int exthdrlen = 0; 1250 int dst_exthdrlen = 0; 1251 int hh_len; 1252 int copy; 1253 int err; 1254 int offset = 0; 1255 u32 tskey = 0; 1256 struct rt6_info *rt = (struct rt6_info *)cork->dst; --- 61 unchanged lines hidden (view full) --- 1318 */ 1319 if (transhdrlen && sk->sk_protocol == IPPROTO_UDP && 1320 headersize == sizeof(struct ipv6hdr) && 1321 length <= mtu - headersize && 1322 (!(flags & MSG_MORE) || cork->gso_size) && 1323 rt->dst.dev->features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM)) 1324 csummode = CHECKSUM_PARTIAL; 1325 |
1326 if (flags & MSG_ZEROCOPY && length && sock_flag(sk, SOCK_ZEROCOPY)) { 1327 uarg = sock_zerocopy_realloc(sk, length, skb_zcopy(skb)); 1328 if (!uarg) 1329 return -ENOBUFS; 1330 if (rt->dst.dev->features & NETIF_F_SG && 1331 csummode == CHECKSUM_PARTIAL) { 1332 paged = true; 1333 } else { 1334 uarg->zerocopy = 0; 1335 skb_zcopy_set(skb, uarg); 1336 } 1337 } 1338 |
|
1325 /* 1326 * Let's try using as much space as possible. 1327 * Use MTU if total length of the message fits into the MTU. 1328 * Otherwise, we need to reserve fragment header and 1329 * fragment alignment (= 8-15 octects, in total). 1330 * 1331 * Note that we may need to "move" the data from the tail of 1332 * of the buffer to the new fragment when we split --- 107 unchanged lines hidden (view full) --- 1440 skb_reserve(skb, hh_len + sizeof(struct frag_hdr) + 1441 dst_exthdrlen); 1442 1443 /* Only the initial fragment is time stamped */ 1444 skb_shinfo(skb)->tx_flags = cork->tx_flags; 1445 cork->tx_flags = 0; 1446 skb_shinfo(skb)->tskey = tskey; 1447 tskey = 0; | 1339 /* 1340 * Let's try using as much space as possible. 1341 * Use MTU if total length of the message fits into the MTU. 1342 * Otherwise, we need to reserve fragment header and 1343 * fragment alignment (= 8-15 octects, in total). 1344 * 1345 * Note that we may need to "move" the data from the tail of 1346 * of the buffer to the new fragment when we split --- 107 unchanged lines hidden (view full) --- 1454 skb_reserve(skb, hh_len + sizeof(struct frag_hdr) + 1455 dst_exthdrlen); 1456 1457 /* Only the initial fragment is time stamped */ 1458 skb_shinfo(skb)->tx_flags = cork->tx_flags; 1459 cork->tx_flags = 0; 1460 skb_shinfo(skb)->tskey = tskey; 1461 tskey = 0; |
1462 skb_zcopy_set(skb, uarg); |
|
1448 1449 /* 1450 * Find where to start putting bytes 1451 */ 1452 data = skb_put(skb, fraglen - pagedlen); 1453 skb_set_network_header(skb, exthdrlen); 1454 data += fragheaderlen; 1455 skb->transport_header = (skb->network_header + --- 45 unchanged lines hidden (view full) --- 1501 1502 off = skb->len; 1503 if (getfrag(from, skb_put(skb, copy), 1504 offset, copy, off, skb) < 0) { 1505 __skb_trim(skb, off); 1506 err = -EFAULT; 1507 goto error; 1508 } | 1463 1464 /* 1465 * Find where to start putting bytes 1466 */ 1467 data = skb_put(skb, fraglen - pagedlen); 1468 skb_set_network_header(skb, exthdrlen); 1469 data += fragheaderlen; 1470 skb->transport_header = (skb->network_header + --- 45 unchanged lines hidden (view full) --- 1516 1517 off = skb->len; 1518 if (getfrag(from, skb_put(skb, copy), 1519 offset, copy, off, skb) < 0) { 1520 __skb_trim(skb, off); 1521 err = -EFAULT; 1522 goto error; 1523 } |
1509 } else { | 1524 } else if (!uarg || !uarg->zerocopy) { |
1510 int i = skb_shinfo(skb)->nr_frags; 1511 1512 err = -ENOMEM; 1513 if (!sk_page_frag_refill(sk, pfrag)) 1514 goto error; 1515 1516 if (!skb_can_coalesce(skb, i, pfrag->page, 1517 pfrag->offset)) { --- 13 unchanged lines hidden (view full) --- 1531 goto error_efault; 1532 1533 pfrag->offset += copy; 1534 skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy); 1535 skb->len += copy; 1536 skb->data_len += copy; 1537 skb->truesize += copy; 1538 wmem_alloc_delta += copy; | 1525 int i = skb_shinfo(skb)->nr_frags; 1526 1527 err = -ENOMEM; 1528 if (!sk_page_frag_refill(sk, pfrag)) 1529 goto error; 1530 1531 if (!skb_can_coalesce(skb, i, pfrag->page, 1532 pfrag->offset)) { --- 13 unchanged lines hidden (view full) --- 1546 goto error_efault; 1547 1548 pfrag->offset += copy; 1549 skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy); 1550 skb->len += copy; 1551 skb->data_len += copy; 1552 skb->truesize += copy; 1553 wmem_alloc_delta += copy; |
1554 } else { 1555 err = skb_zerocopy_iter_dgram(skb, from, copy); 1556 if (err < 0) 1557 goto error; |
|
1539 } 1540 offset += copy; 1541 length -= copy; 1542 } 1543 1544 if (wmem_alloc_delta) 1545 refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc); | 1558 } 1559 offset += copy; 1560 length -= copy; 1561 } 1562 1563 if (wmem_alloc_delta) 1564 refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc); |
1565 sock_zerocopy_put(uarg); |
|
1546 return 0; 1547 1548error_efault: 1549 err = -EFAULT; 1550error: | 1566 return 0; 1567 1568error_efault: 1569 err = -EFAULT; 1570error: |
1571 sock_zerocopy_put_abort(uarg); |
|
1551 cork->length -= length; 1552 IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); 1553 refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc); 1554 return err; 1555} 1556 1557int ip6_append_data(struct sock *sk, 1558 int getfrag(void *from, char *to, int offset, int len, --- 227 unchanged lines hidden --- | 1572 cork->length -= length; 1573 IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); 1574 refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc); 1575 return err; 1576} 1577 1578int ip6_append_data(struct sock *sk, 1579 int getfrag(void *from, char *to, int offset, int len, --- 227 unchanged lines hidden --- |