ip6_output.c (b75ec3af27bf011a760e2f44eb25a99b6fbb0fb3) | ip6_output.c (682b1a9d3f9686ee43fd66b48605daff00522157) |
---|---|
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 --- 1256 unchanged lines hidden (view full) --- 1265 int copy; 1266 int err; 1267 int offset = 0; 1268 __u8 tx_flags = 0; 1269 u32 tskey = 0; 1270 struct rt6_info *rt = (struct rt6_info *)cork->dst; 1271 struct ipv6_txoptions *opt = v6_cork->opt; 1272 int csummode = CHECKSUM_NONE; | 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 --- 1256 unchanged lines hidden (view full) --- 1265 int copy; 1266 int err; 1267 int offset = 0; 1268 __u8 tx_flags = 0; 1269 u32 tskey = 0; 1270 struct rt6_info *rt = (struct rt6_info *)cork->dst; 1271 struct ipv6_txoptions *opt = v6_cork->opt; 1272 int csummode = CHECKSUM_NONE; |
1273 unsigned int maxnonfragsize, headersize; |
|
1273 1274 skb = skb_peek_tail(queue); 1275 if (!skb) { 1276 exthdrlen = opt ? opt->opt_flen : 0; 1277 dst_exthdrlen = rt->dst.header_len - rt->rt6i_nfheader_len; 1278 } 1279 1280 mtu = cork->fragsize; 1281 orig_mtu = mtu; 1282 1283 hh_len = LL_RESERVED_SPACE(rt->dst.dev); 1284 1285 fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len + 1286 (opt ? opt->opt_nflen : 0); 1287 maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - 1288 sizeof(struct frag_hdr); 1289 | 1274 1275 skb = skb_peek_tail(queue); 1276 if (!skb) { 1277 exthdrlen = opt ? opt->opt_flen : 0; 1278 dst_exthdrlen = rt->dst.header_len - rt->rt6i_nfheader_len; 1279 } 1280 1281 mtu = cork->fragsize; 1282 orig_mtu = mtu; 1283 1284 hh_len = LL_RESERVED_SPACE(rt->dst.dev); 1285 1286 fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len + 1287 (opt ? opt->opt_nflen : 0); 1288 maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - 1289 sizeof(struct frag_hdr); 1290 |
1290 if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { 1291 unsigned int maxnonfragsize, headersize; | 1291 headersize = sizeof(struct ipv6hdr) + 1292 (opt ? opt->opt_flen + opt->opt_nflen : 0) + 1293 (dst_allfrag(&rt->dst) ? 1294 sizeof(struct frag_hdr) : 0) + 1295 rt->rt6i_nfheader_len; |
1292 | 1296 |
1293 headersize = sizeof(struct ipv6hdr) + 1294 (opt ? opt->opt_flen + opt->opt_nflen : 0) + 1295 (dst_allfrag(&rt->dst) ? 1296 sizeof(struct frag_hdr) : 0) + 1297 rt->rt6i_nfheader_len; | 1297 if (cork->length + length > mtu - headersize && dontfrag && 1298 (sk->sk_protocol == IPPROTO_UDP || 1299 sk->sk_protocol == IPPROTO_RAW)) { 1300 ipv6_local_rxpmtu(sk, fl6, mtu - headersize + 1301 sizeof(struct ipv6hdr)); 1302 goto emsgsize; 1303 } |
1298 | 1304 |
1299 if (ip6_sk_ignore_df(sk)) 1300 maxnonfragsize = sizeof(struct ipv6hdr) + IPV6_MAXPLEN; 1301 else 1302 maxnonfragsize = mtu; | 1305 if (ip6_sk_ignore_df(sk)) 1306 maxnonfragsize = sizeof(struct ipv6hdr) + IPV6_MAXPLEN; 1307 else 1308 maxnonfragsize = mtu; |
1303 | 1309 |
1304 /* dontfrag active */ 1305 if ((cork->length + length > mtu - headersize) && dontfrag && 1306 (sk->sk_protocol == IPPROTO_UDP || 1307 sk->sk_protocol == IPPROTO_RAW)) { 1308 ipv6_local_rxpmtu(sk, fl6, mtu - headersize + 1309 sizeof(struct ipv6hdr)); 1310 goto emsgsize; 1311 } 1312 1313 if (cork->length + length > maxnonfragsize - headersize) { | 1310 if (cork->length + length > maxnonfragsize - headersize) { |
1314emsgsize: | 1311emsgsize: |
1315 ipv6_local_error(sk, EMSGSIZE, fl6, 1316 mtu - headersize + 1317 sizeof(struct ipv6hdr)); 1318 return -EMSGSIZE; 1319 } | 1312 ipv6_local_error(sk, EMSGSIZE, fl6, 1313 mtu - headersize + 1314 sizeof(struct ipv6hdr)); 1315 return -EMSGSIZE; |
1320 } 1321 | 1316 } 1317 |
1318 /* CHECKSUM_PARTIAL only with no extension headers and when 1319 * we are not going to fragment 1320 */ 1321 if (transhdrlen && sk->sk_protocol == IPPROTO_UDP && 1322 headersize == sizeof(struct ipv6hdr) && 1323 length < mtu - headersize && 1324 !(flags & MSG_MORE) && 1325 rt->dst.dev->features & NETIF_F_V6_CSUM) 1326 csummode = CHECKSUM_PARTIAL; 1327 |
|
1322 if (sk->sk_type == SOCK_DGRAM || sk->sk_type == SOCK_RAW) { 1323 sock_tx_timestamp(sk, &tx_flags); 1324 if (tx_flags & SKBTX_ANY_SW_TSTAMP && 1325 sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) 1326 tskey = sk->sk_tskey++; 1327 } 1328 | 1328 if (sk->sk_type == SOCK_DGRAM || sk->sk_type == SOCK_RAW) { 1329 sock_tx_timestamp(sk, &tx_flags); 1330 if (tx_flags & SKBTX_ANY_SW_TSTAMP && 1331 sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) 1332 tskey = sk->sk_tskey++; 1333 } 1334 |
1329 /* If this is the first and only packet and device 1330 * supports checksum offloading, let's use it. 1331 * Use transhdrlen, same as IPv4, because partial 1332 * sums only work when transhdrlen is set. 1333 */ 1334 if (transhdrlen && sk->sk_protocol == IPPROTO_UDP && 1335 length + fragheaderlen < mtu && 1336 rt->dst.dev->features & NETIF_F_V6_CSUM && 1337 !exthdrlen) 1338 csummode = CHECKSUM_PARTIAL; | |
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 --- 444 unchanged lines hidden --- | 1335 /* 1336 * Let's try using as much space as possible. 1337 * Use MTU if total length of the message fits into the MTU. 1338 * Otherwise, we need to reserve fragment header and 1339 * fragment alignment (= 8-15 octects, in total). 1340 * 1341 * Note that we may need to "move" the data from the tail of 1342 * of the buffer to the new fragment when we split --- 444 unchanged lines hidden --- |