aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r--net/ipv6/ip6_output.c44
1 files changed, 15 insertions, 29 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 87f8419a68fd..cd48801a8d6f 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -57,18 +57,6 @@
57 57
58static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); 58static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
59 59
60static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *fhdr)
61{
62 static u32 ipv6_fragmentation_id = 1;
63 static DEFINE_SPINLOCK(ip6_id_lock);
64
65 spin_lock_bh(&ip6_id_lock);
66 fhdr->identification = htonl(ipv6_fragmentation_id);
67 if (++ipv6_fragmentation_id == 0)
68 ipv6_fragmentation_id = 1;
69 spin_unlock_bh(&ip6_id_lock);
70}
71
72int __ip6_local_out(struct sk_buff *skb) 60int __ip6_local_out(struct sk_buff *skb)
73{ 61{
74 int len; 62 int len;
@@ -206,7 +194,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
206 struct ipv6hdr *hdr; 194 struct ipv6hdr *hdr;
207 u8 proto = fl->proto; 195 u8 proto = fl->proto;
208 int seg_len = skb->len; 196 int seg_len = skb->len;
209 int hlimit, tclass; 197 int hlimit = -1;
198 int tclass = 0;
210 u32 mtu; 199 u32 mtu;
211 200
212 if (opt) { 201 if (opt) {
@@ -249,19 +238,13 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
249 /* 238 /*
250 * Fill in the IPv6 header 239 * Fill in the IPv6 header
251 */ 240 */
252 241 if (np) {
253 hlimit = -1; 242 tclass = np->tclass;
254 if (np)
255 hlimit = np->hop_limit; 243 hlimit = np->hop_limit;
244 }
256 if (hlimit < 0) 245 if (hlimit < 0)
257 hlimit = ip6_dst_hoplimit(dst); 246 hlimit = ip6_dst_hoplimit(dst);
258 247
259 tclass = -1;
260 if (np)
261 tclass = np->tclass;
262 if (tclass < 0)
263 tclass = 0;
264
265 *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel; 248 *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel;
266 249
267 hdr->payload_len = htons(seg_len); 250 hdr->payload_len = htons(seg_len);
@@ -706,7 +689,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
706 skb_reset_network_header(skb); 689 skb_reset_network_header(skb);
707 memcpy(skb_network_header(skb), tmp_hdr, hlen); 690 memcpy(skb_network_header(skb), tmp_hdr, hlen);
708 691
709 ipv6_select_ident(skb, fh); 692 ipv6_select_ident(fh);
710 fh->nexthdr = nexthdr; 693 fh->nexthdr = nexthdr;
711 fh->reserved = 0; 694 fh->reserved = 0;
712 fh->frag_off = htons(IP6_MF); 695 fh->frag_off = htons(IP6_MF);
@@ -844,7 +827,7 @@ slow_path:
844 fh->nexthdr = nexthdr; 827 fh->nexthdr = nexthdr;
845 fh->reserved = 0; 828 fh->reserved = 0;
846 if (!frag_id) { 829 if (!frag_id) {
847 ipv6_select_ident(skb, fh); 830 ipv6_select_ident(fh);
848 frag_id = fh->identification; 831 frag_id = fh->identification;
849 } else 832 } else
850 fh->identification = frag_id; 833 fh->identification = frag_id;
@@ -1087,11 +1070,13 @@ static inline int ip6_ufo_append_data(struct sock *sk,
1087 if (!err) { 1070 if (!err) {
1088 struct frag_hdr fhdr; 1071 struct frag_hdr fhdr;
1089 1072
1090 /* specify the length of each IP datagram fragment*/ 1073 /* Specify the length of each IPv6 datagram fragment.
1091 skb_shinfo(skb)->gso_size = mtu - fragheaderlen - 1074 * It has to be a multiple of 8.
1092 sizeof(struct frag_hdr); 1075 */
1076 skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
1077 sizeof(struct frag_hdr)) & ~7;
1093 skb_shinfo(skb)->gso_type = SKB_GSO_UDP; 1078 skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
1094 ipv6_select_ident(skb, &fhdr); 1079 ipv6_select_ident(&fhdr);
1095 skb_shinfo(skb)->ip6_frag_id = fhdr.identification; 1080 skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
1096 __skb_queue_tail(&sk->sk_write_queue, skb); 1081 __skb_queue_tail(&sk->sk_write_queue, skb);
1097 1082
@@ -1526,7 +1511,7 @@ int ip6_push_pending_frames(struct sock *sk)
1526 err = ip6_local_out(skb); 1511 err = ip6_local_out(skb);
1527 if (err) { 1512 if (err) {
1528 if (err > 0) 1513 if (err > 0)
1529 err = np->recverr ? net_xmit_errno(err) : 0; 1514 err = net_xmit_errno(err);
1530 if (err) 1515 if (err)
1531 goto error; 1516 goto error;
1532 } 1517 }
@@ -1535,6 +1520,7 @@ out:
1535 ip6_cork_release(inet, np); 1520 ip6_cork_release(inet, np);
1536 return err; 1521 return err;
1537error: 1522error:
1523 IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
1538 goto out; 1524 goto out;
1539} 1525}
1540 1526