ip_output.c (989a4222c13a3e148772730d362fceb0727852f5) | ip_output.c (b5947e5d1e710c35ea281247bd27e6975250285c) |
---|---|
1/* 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 3 * operating system. INET is implemented using the BSD Socket 4 * interface as the means of communication with the user level. 5 * 6 * The Internet Protocol (IP) output module. 7 * 8 * Authors: Ross Biro --- 853 unchanged lines hidden (view full) --- 862 struct inet_cork *cork, 863 struct page_frag *pfrag, 864 int getfrag(void *from, char *to, int offset, 865 int len, int odd, struct sk_buff *skb), 866 void *from, int length, int transhdrlen, 867 unsigned int flags) 868{ 869 struct inet_sock *inet = inet_sk(sk); | 1/* 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 3 * operating system. INET is implemented using the BSD Socket 4 * interface as the means of communication with the user level. 5 * 6 * The Internet Protocol (IP) output module. 7 * 8 * Authors: Ross Biro --- 853 unchanged lines hidden (view full) --- 862 struct inet_cork *cork, 863 struct page_frag *pfrag, 864 int getfrag(void *from, char *to, int offset, 865 int len, int odd, struct sk_buff *skb), 866 void *from, int length, int transhdrlen, 867 unsigned int flags) 868{ 869 struct inet_sock *inet = inet_sk(sk); |
870 struct ubuf_info *uarg = NULL; |
|
870 struct sk_buff *skb; 871 872 struct ip_options *opt = cork->opt; 873 int hh_len; 874 int exthdrlen; 875 int mtu; 876 int copy; 877 int err; --- 33 unchanged lines hidden (view full) --- 911 */ 912 if (transhdrlen && 913 length + fragheaderlen <= mtu && 914 rt->dst.dev->features & (NETIF_F_HW_CSUM | NETIF_F_IP_CSUM) && 915 (!(flags & MSG_MORE) || cork->gso_size) && 916 (!exthdrlen || (rt->dst.dev->features & NETIF_F_HW_ESP_TX_CSUM))) 917 csummode = CHECKSUM_PARTIAL; 918 | 871 struct sk_buff *skb; 872 873 struct ip_options *opt = cork->opt; 874 int hh_len; 875 int exthdrlen; 876 int mtu; 877 int copy; 878 int err; --- 33 unchanged lines hidden (view full) --- 912 */ 913 if (transhdrlen && 914 length + fragheaderlen <= mtu && 915 rt->dst.dev->features & (NETIF_F_HW_CSUM | NETIF_F_IP_CSUM) && 916 (!(flags & MSG_MORE) || cork->gso_size) && 917 (!exthdrlen || (rt->dst.dev->features & NETIF_F_HW_ESP_TX_CSUM))) 918 csummode = CHECKSUM_PARTIAL; 919 |
920 if (flags & MSG_ZEROCOPY && length && sock_flag(sk, SOCK_ZEROCOPY)) { 921 uarg = sock_zerocopy_realloc(sk, length, skb_zcopy(skb)); 922 if (!uarg) 923 return -ENOBUFS; 924 if (rt->dst.dev->features & NETIF_F_SG && 925 csummode == CHECKSUM_PARTIAL) { 926 paged = true; 927 } else { 928 uarg->zerocopy = 0; 929 skb_zcopy_set(skb, uarg); 930 } 931 } 932 |
|
919 cork->length += length; 920 921 /* So, what's going on in the loop below? 922 * 923 * We use calculated fragment length to generate chained skb, 924 * each of segments is IP fragment ready for sending to network after 925 * adding appropriate IP header. 926 */ --- 74 unchanged lines hidden (view full) --- 1001 skb->csum = 0; 1002 skb_reserve(skb, hh_len); 1003 1004 /* only the initial fragment is time stamped */ 1005 skb_shinfo(skb)->tx_flags = cork->tx_flags; 1006 cork->tx_flags = 0; 1007 skb_shinfo(skb)->tskey = tskey; 1008 tskey = 0; | 933 cork->length += length; 934 935 /* So, what's going on in the loop below? 936 * 937 * We use calculated fragment length to generate chained skb, 938 * each of segments is IP fragment ready for sending to network after 939 * adding appropriate IP header. 940 */ --- 74 unchanged lines hidden (view full) --- 1015 skb->csum = 0; 1016 skb_reserve(skb, hh_len); 1017 1018 /* only the initial fragment is time stamped */ 1019 skb_shinfo(skb)->tx_flags = cork->tx_flags; 1020 cork->tx_flags = 0; 1021 skb_shinfo(skb)->tskey = tskey; 1022 tskey = 0; |
1023 skb_zcopy_set(skb, uarg); |
|
1009 1010 /* 1011 * Find where to start putting bytes. 1012 */ 1013 data = skb_put(skb, fraglen + exthdrlen - pagedlen); 1014 skb_set_network_header(skb, exthdrlen); 1015 skb->transport_header = (skb->network_header + 1016 fragheaderlen); --- 46 unchanged lines hidden (view full) --- 1063 1064 off = skb->len; 1065 if (getfrag(from, skb_put(skb, copy), 1066 offset, copy, off, skb) < 0) { 1067 __skb_trim(skb, off); 1068 err = -EFAULT; 1069 goto error; 1070 } | 1024 1025 /* 1026 * Find where to start putting bytes. 1027 */ 1028 data = skb_put(skb, fraglen + exthdrlen - pagedlen); 1029 skb_set_network_header(skb, exthdrlen); 1030 skb->transport_header = (skb->network_header + 1031 fragheaderlen); --- 46 unchanged lines hidden (view full) --- 1078 1079 off = skb->len; 1080 if (getfrag(from, skb_put(skb, copy), 1081 offset, copy, off, skb) < 0) { 1082 __skb_trim(skb, off); 1083 err = -EFAULT; 1084 goto error; 1085 } |
1071 } else { | 1086 } else if (!uarg || !uarg->zerocopy) { |
1072 int i = skb_shinfo(skb)->nr_frags; 1073 1074 err = -ENOMEM; 1075 if (!sk_page_frag_refill(sk, pfrag)) 1076 goto error; 1077 1078 if (!skb_can_coalesce(skb, i, pfrag->page, 1079 pfrag->offset)) { --- 13 unchanged lines hidden (view full) --- 1093 goto error_efault; 1094 1095 pfrag->offset += copy; 1096 skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy); 1097 skb->len += copy; 1098 skb->data_len += copy; 1099 skb->truesize += copy; 1100 wmem_alloc_delta += copy; | 1087 int i = skb_shinfo(skb)->nr_frags; 1088 1089 err = -ENOMEM; 1090 if (!sk_page_frag_refill(sk, pfrag)) 1091 goto error; 1092 1093 if (!skb_can_coalesce(skb, i, pfrag->page, 1094 pfrag->offset)) { --- 13 unchanged lines hidden (view full) --- 1108 goto error_efault; 1109 1110 pfrag->offset += copy; 1111 skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy); 1112 skb->len += copy; 1113 skb->data_len += copy; 1114 skb->truesize += copy; 1115 wmem_alloc_delta += copy; |
1116 } else { 1117 err = skb_zerocopy_iter_dgram(skb, from, copy); 1118 if (err < 0) 1119 goto error; |
|
1101 } 1102 offset += copy; 1103 length -= copy; 1104 } 1105 1106 if (wmem_alloc_delta) 1107 refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc); | 1120 } 1121 offset += copy; 1122 length -= copy; 1123 } 1124 1125 if (wmem_alloc_delta) 1126 refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc); |
1127 sock_zerocopy_put(uarg); |
|
1108 return 0; 1109 1110error_efault: 1111 err = -EFAULT; 1112error: | 1128 return 0; 1129 1130error_efault: 1131 err = -EFAULT; 1132error: |
1133 sock_zerocopy_put_abort(uarg); |
|
1113 cork->length -= length; 1114 IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS); 1115 refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc); 1116 return err; 1117} 1118 1119static int ip_setup_cork(struct sock *sk, struct inet_cork *cork, 1120 struct ipcm_cookie *ipc, struct rtable **rtp) --- 496 unchanged lines hidden --- | 1134 cork->length -= length; 1135 IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS); 1136 refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc); 1137 return err; 1138} 1139 1140static int ip_setup_cork(struct sock *sk, struct inet_cork *cork, 1141 struct ipcm_cookie *ipc, struct rtable **rtp) --- 496 unchanged lines hidden --- |