aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/icmp.c9
-rw-r--r--net/ipv6/ip6_flowlabel.c2
-rw-r--r--net/ipv6/ip6_output.c71
-rw-r--r--net/ipv6/mcast.c2
-rw-r--r--net/ipv6/proc.c4
5 files changed, 75 insertions, 13 deletions
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index b7185fb3377c..23e540365a14 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -700,10 +700,7 @@ int __init icmpv6_init(struct net_proto_family *ops)
700 struct sock *sk; 700 struct sock *sk;
701 int err, i, j; 701 int err, i, j;
702 702
703 for (i = 0; i < NR_CPUS; i++) { 703 for_each_cpu(i) {
704 if (!cpu_possible(i))
705 continue;
706
707 err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, 704 err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
708 &per_cpu(__icmpv6_socket, i)); 705 &per_cpu(__icmpv6_socket, i));
709 if (err < 0) { 706 if (err < 0) {
@@ -749,9 +746,7 @@ void icmpv6_cleanup(void)
749{ 746{
750 int i; 747 int i;
751 748
752 for (i = 0; i < NR_CPUS; i++) { 749 for_each_cpu(i) {
753 if (!cpu_possible(i))
754 continue;
755 sock_release(per_cpu(__icmpv6_socket, i)); 750 sock_release(per_cpu(__icmpv6_socket, i));
756 } 751 }
757 inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); 752 inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index f841bde30c18..bbbe80cdaf72 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -483,7 +483,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
483 goto done; 483 goto done;
484 } 484 }
485 fl1 = sfl->fl; 485 fl1 = sfl->fl;
486 atomic_inc(&fl->users); 486 atomic_inc(&fl1->users);
487 break; 487 break;
488 } 488 }
489 } 489 }
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 563b442ffab8..614296a920c6 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -147,7 +147,8 @@ static int ip6_output2(struct sk_buff *skb)
147 147
148int ip6_output(struct sk_buff *skb) 148int ip6_output(struct sk_buff *skb)
149{ 149{
150 if (skb->len > dst_mtu(skb->dst) || dst_allfrag(skb->dst)) 150 if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->ufo_size) ||
151 dst_allfrag(skb->dst))
151 return ip6_fragment(skb, ip6_output2); 152 return ip6_fragment(skb, ip6_output2);
152 else 153 else
153 return ip6_output2(skb); 154 return ip6_output2(skb);
@@ -768,6 +769,65 @@ out_err_release:
768 *dst = NULL; 769 *dst = NULL;
769 return err; 770 return err;
770} 771}
772inline int ip6_ufo_append_data(struct sock *sk,
773 int getfrag(void *from, char *to, int offset, int len,
774 int odd, struct sk_buff *skb),
775 void *from, int length, int hh_len, int fragheaderlen,
776 int transhdrlen, int mtu,unsigned int flags)
777
778{
779 struct sk_buff *skb;
780 int err;
781
782 /* There is support for UDP large send offload by network
783 * device, so create one single skb packet containing complete
784 * udp datagram
785 */
786 if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) {
787 skb = sock_alloc_send_skb(sk,
788 hh_len + fragheaderlen + transhdrlen + 20,
789 (flags & MSG_DONTWAIT), &err);
790 if (skb == NULL)
791 return -ENOMEM;
792
793 /* reserve space for Hardware header */
794 skb_reserve(skb, hh_len);
795
796 /* create space for UDP/IP header */
797 skb_put(skb,fragheaderlen + transhdrlen);
798
799 /* initialize network header pointer */
800 skb->nh.raw = skb->data;
801
802 /* initialize protocol header pointer */
803 skb->h.raw = skb->data + fragheaderlen;
804
805 skb->ip_summed = CHECKSUM_HW;
806 skb->csum = 0;
807 sk->sk_sndmsg_off = 0;
808 }
809
810 err = skb_append_datato_frags(sk,skb, getfrag, from,
811 (length - transhdrlen));
812 if (!err) {
813 struct frag_hdr fhdr;
814
815 /* specify the length of each IP datagram fragment*/
816 skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen) -
817 sizeof(struct frag_hdr);
818 ipv6_select_ident(skb, &fhdr);
819 skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
820 __skb_queue_tail(&sk->sk_write_queue, skb);
821
822 return 0;
823 }
824 /* There is not enough support do UPD LSO,
825 * so follow normal path
826 */
827 kfree_skb(skb);
828
829 return err;
830}
771 831
772int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, 832int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
773 int offset, int len, int odd, struct sk_buff *skb), 833 int offset, int len, int odd, struct sk_buff *skb),
@@ -860,6 +920,15 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
860 */ 920 */
861 921
862 inet->cork.length += length; 922 inet->cork.length += length;
923 if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) &&
924 (rt->u.dst.dev->features & NETIF_F_UFO)) {
925
926 if(ip6_ufo_append_data(sk, getfrag, from, length, hh_len,
927 fragheaderlen, transhdrlen, mtu, flags))
928 goto error;
929
930 return 0;
931 }
863 932
864 if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) 933 if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
865 goto alloc_new_skb; 934 goto alloc_new_skb;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 39a96c768102..c4f2a0ef7489 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -164,7 +164,7 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
164#define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value)) 164#define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value))
165#define MLDV2_EXP(thresh, nbmant, nbexp, value) \ 165#define MLDV2_EXP(thresh, nbmant, nbexp, value) \
166 ((value) < (thresh) ? (value) : \ 166 ((value) < (thresh) ? (value) : \
167 ((MLDV2_MASK(value, nbmant) | (1<<(nbmant+nbexp))) << \ 167 ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \
168 (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) 168 (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp))))
169 169
170#define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value) 170#define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value)
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 334a5967831e..50a13e75d70e 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -140,9 +140,7 @@ fold_field(void *mib[], int offt)
140 unsigned long res = 0; 140 unsigned long res = 0;
141 int i; 141 int i;
142 142
143 for (i = 0; i < NR_CPUS; i++) { 143 for_each_cpu(i) {
144 if (!cpu_possible(i))
145 continue;
146 res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt); 144 res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt);
147 res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt); 145 res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt);
148 } 146 }