diff options
Diffstat (limited to 'net/ipv6')
| -rw-r--r-- | net/ipv6/icmp.c | 9 | ||||
| -rw-r--r-- | net/ipv6/ip6_flowlabel.c | 2 | ||||
| -rw-r--r-- | net/ipv6/ip6_output.c | 71 | ||||
| -rw-r--r-- | net/ipv6/mcast.c | 2 | ||||
| -rw-r--r-- | net/ipv6/proc.c | 4 |
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 | ||
| 148 | int ip6_output(struct sk_buff *skb) | 148 | int 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 | } |
| 772 | inline 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 | ||
| 772 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | 832 | int 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 | } |
