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 ---