diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 23 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 36 | ||||
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 21 | ||||
-rw-r--r-- | net/ipv6/ip6_vti.c | 30 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_SYNPROXY.c | 1 | ||||
-rw-r--r-- | net/ipv6/route.c | 4 | ||||
-rw-r--r-- | net/ipv6/sit.c | 8 |
7 files changed, 76 insertions, 47 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index d5fa5b8c443e..abe46a4228ce 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1671,7 +1671,7 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) | |||
1671 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) | 1671 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) |
1672 | { | 1672 | { |
1673 | struct in6_addr addr; | 1673 | struct in6_addr addr; |
1674 | if (ifp->prefix_len == 127) /* RFC 6164 */ | 1674 | if (ifp->prefix_len >= 127) /* RFC 6164 */ |
1675 | return; | 1675 | return; |
1676 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1676 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
1677 | if (ipv6_addr_any(&addr)) | 1677 | if (ipv6_addr_any(&addr)) |
@@ -1682,7 +1682,7 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp) | |||
1682 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) | 1682 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) |
1683 | { | 1683 | { |
1684 | struct in6_addr addr; | 1684 | struct in6_addr addr; |
1685 | if (ifp->prefix_len == 127) /* RFC 6164 */ | 1685 | if (ifp->prefix_len >= 127) /* RFC 6164 */ |
1686 | return; | 1686 | return; |
1687 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1687 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
1688 | if (ipv6_addr_any(&addr)) | 1688 | if (ipv6_addr_any(&addr)) |
@@ -2509,7 +2509,8 @@ static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr, | |||
2509 | struct inet6_ifaddr *ifp; | 2509 | struct inet6_ifaddr *ifp; |
2510 | 2510 | ||
2511 | ifp = ipv6_add_addr(idev, addr, NULL, plen, | 2511 | ifp = ipv6_add_addr(idev, addr, NULL, plen, |
2512 | scope, IFA_F_PERMANENT, 0, 0); | 2512 | scope, IFA_F_PERMANENT, |
2513 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); | ||
2513 | if (!IS_ERR(ifp)) { | 2514 | if (!IS_ERR(ifp)) { |
2514 | spin_lock_bh(&ifp->lock); | 2515 | spin_lock_bh(&ifp->lock); |
2515 | ifp->flags &= ~IFA_F_TENTATIVE; | 2516 | ifp->flags &= ~IFA_F_TENTATIVE; |
@@ -2637,7 +2638,8 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr | |||
2637 | #endif | 2638 | #endif |
2638 | 2639 | ||
2639 | 2640 | ||
2640 | ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags, 0, 0); | 2641 | ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags, |
2642 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); | ||
2641 | if (!IS_ERR(ifp)) { | 2643 | if (!IS_ERR(ifp)) { |
2642 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0); | 2644 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0); |
2643 | addrconf_dad_start(ifp); | 2645 | addrconf_dad_start(ifp); |
@@ -3456,7 +3458,12 @@ restart: | |||
3456 | &inet6_addr_lst[i], addr_lst) { | 3458 | &inet6_addr_lst[i], addr_lst) { |
3457 | unsigned long age; | 3459 | unsigned long age; |
3458 | 3460 | ||
3459 | if (ifp->flags & IFA_F_PERMANENT) | 3461 | /* When setting preferred_lft to a value not zero or |
3462 | * infinity, while valid_lft is infinity | ||
3463 | * IFA_F_PERMANENT has a non-infinity life time. | ||
3464 | */ | ||
3465 | if ((ifp->flags & IFA_F_PERMANENT) && | ||
3466 | (ifp->prefered_lft == INFINITY_LIFE_TIME)) | ||
3460 | continue; | 3467 | continue; |
3461 | 3468 | ||
3462 | spin_lock(&ifp->lock); | 3469 | spin_lock(&ifp->lock); |
@@ -3481,7 +3488,8 @@ restart: | |||
3481 | ifp->flags |= IFA_F_DEPRECATED; | 3488 | ifp->flags |= IFA_F_DEPRECATED; |
3482 | } | 3489 | } |
3483 | 3490 | ||
3484 | if (time_before(ifp->tstamp + ifp->valid_lft * HZ, next)) | 3491 | if ((ifp->valid_lft != INFINITY_LIFE_TIME) && |
3492 | (time_before(ifp->tstamp + ifp->valid_lft * HZ, next))) | ||
3485 | next = ifp->tstamp + ifp->valid_lft * HZ; | 3493 | next = ifp->tstamp + ifp->valid_lft * HZ; |
3486 | 3494 | ||
3487 | spin_unlock(&ifp->lock); | 3495 | spin_unlock(&ifp->lock); |
@@ -3761,7 +3769,8 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, | |||
3761 | put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope), | 3769 | put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope), |
3762 | ifa->idev->dev->ifindex); | 3770 | ifa->idev->dev->ifindex); |
3763 | 3771 | ||
3764 | if (!(ifa->flags&IFA_F_PERMANENT)) { | 3772 | if (!((ifa->flags&IFA_F_PERMANENT) && |
3773 | (ifa->prefered_lft == INFINITY_LIFE_TIME))) { | ||
3765 | preferred = ifa->prefered_lft; | 3774 | preferred = ifa->prefered_lft; |
3766 | valid = ifa->valid_lft; | 3775 | valid = ifa->valid_lft; |
3767 | if (preferred != INFINITY_LIFE_TIME) { | 3776 | if (preferred != INFINITY_LIFE_TIME) { |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 4acdb63495db..e6f931997996 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -1193,11 +1193,35 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1193 | 1193 | ||
1194 | fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len + | 1194 | fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len + |
1195 | (opt ? opt->opt_nflen : 0); | 1195 | (opt ? opt->opt_nflen : 0); |
1196 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr); | 1196 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - |
1197 | sizeof(struct frag_hdr); | ||
1197 | 1198 | ||
1198 | if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { | 1199 | if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { |
1199 | if (cork->length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) { | 1200 | unsigned int maxnonfragsize, headersize; |
1200 | ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen); | 1201 | |
1202 | headersize = sizeof(struct ipv6hdr) + | ||
1203 | (opt ? opt->tot_len : 0) + | ||
1204 | (dst_allfrag(&rt->dst) ? | ||
1205 | sizeof(struct frag_hdr) : 0) + | ||
1206 | rt->rt6i_nfheader_len; | ||
1207 | |||
1208 | maxnonfragsize = (np->pmtudisc >= IPV6_PMTUDISC_DO) ? | ||
1209 | mtu : sizeof(struct ipv6hdr) + IPV6_MAXPLEN; | ||
1210 | |||
1211 | /* dontfrag active */ | ||
1212 | if ((cork->length + length > mtu - headersize) && dontfrag && | ||
1213 | (sk->sk_protocol == IPPROTO_UDP || | ||
1214 | sk->sk_protocol == IPPROTO_RAW)) { | ||
1215 | ipv6_local_rxpmtu(sk, fl6, mtu - headersize + | ||
1216 | sizeof(struct ipv6hdr)); | ||
1217 | goto emsgsize; | ||
1218 | } | ||
1219 | |||
1220 | if (cork->length + length > maxnonfragsize - headersize) { | ||
1221 | emsgsize: | ||
1222 | ipv6_local_error(sk, EMSGSIZE, fl6, | ||
1223 | mtu - headersize + | ||
1224 | sizeof(struct ipv6hdr)); | ||
1201 | return -EMSGSIZE; | 1225 | return -EMSGSIZE; |
1202 | } | 1226 | } |
1203 | } | 1227 | } |
@@ -1222,12 +1246,6 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1222 | * --yoshfuji | 1246 | * --yoshfuji |
1223 | */ | 1247 | */ |
1224 | 1248 | ||
1225 | if ((length > mtu) && dontfrag && (sk->sk_protocol == IPPROTO_UDP || | ||
1226 | sk->sk_protocol == IPPROTO_RAW)) { | ||
1227 | ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen); | ||
1228 | return -EMSGSIZE; | ||
1229 | } | ||
1230 | |||
1231 | skb = skb_peek_tail(&sk->sk_write_queue); | 1249 | skb = skb_peek_tail(&sk->sk_write_queue); |
1232 | cork->length += length; | 1250 | cork->length += length; |
1233 | if (((length > mtu) || | 1251 | if (((length > mtu) || |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index d6062325db08..7881965a8248 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -103,16 +103,25 @@ struct ip6_tnl_net { | |||
103 | 103 | ||
104 | static struct net_device_stats *ip6_get_stats(struct net_device *dev) | 104 | static struct net_device_stats *ip6_get_stats(struct net_device *dev) |
105 | { | 105 | { |
106 | struct pcpu_tstats sum = { 0 }; | 106 | struct pcpu_tstats tmp, sum = { 0 }; |
107 | int i; | 107 | int i; |
108 | 108 | ||
109 | for_each_possible_cpu(i) { | 109 | for_each_possible_cpu(i) { |
110 | unsigned int start; | ||
110 | const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i); | 111 | const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i); |
111 | 112 | ||
112 | sum.rx_packets += tstats->rx_packets; | 113 | do { |
113 | sum.rx_bytes += tstats->rx_bytes; | 114 | start = u64_stats_fetch_begin_bh(&tstats->syncp); |
114 | sum.tx_packets += tstats->tx_packets; | 115 | tmp.rx_packets = tstats->rx_packets; |
115 | sum.tx_bytes += tstats->tx_bytes; | 116 | tmp.rx_bytes = tstats->rx_bytes; |
117 | tmp.tx_packets = tstats->tx_packets; | ||
118 | tmp.tx_bytes = tstats->tx_bytes; | ||
119 | } while (u64_stats_fetch_retry_bh(&tstats->syncp, start)); | ||
120 | |||
121 | sum.rx_packets += tmp.rx_packets; | ||
122 | sum.rx_bytes += tmp.rx_bytes; | ||
123 | sum.tx_packets += tmp.tx_packets; | ||
124 | sum.tx_bytes += tmp.tx_bytes; | ||
116 | } | 125 | } |
117 | dev->stats.rx_packets = sum.rx_packets; | 126 | dev->stats.rx_packets = sum.rx_packets; |
118 | dev->stats.rx_bytes = sum.rx_bytes; | 127 | dev->stats.rx_bytes = sum.rx_bytes; |
@@ -824,8 +833,10 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, | |||
824 | } | 833 | } |
825 | 834 | ||
826 | tstats = this_cpu_ptr(t->dev->tstats); | 835 | tstats = this_cpu_ptr(t->dev->tstats); |
836 | u64_stats_update_begin(&tstats->syncp); | ||
827 | tstats->rx_packets++; | 837 | tstats->rx_packets++; |
828 | tstats->rx_bytes += skb->len; | 838 | tstats->rx_bytes += skb->len; |
839 | u64_stats_update_end(&tstats->syncp); | ||
829 | 840 | ||
830 | netif_rx(skb); | 841 | netif_rx(skb); |
831 | 842 | ||
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index ed94ba61dda0..7b42d5ef868d 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c | |||
@@ -75,26 +75,6 @@ struct vti6_net { | |||
75 | struct ip6_tnl __rcu **tnls[2]; | 75 | struct ip6_tnl __rcu **tnls[2]; |
76 | }; | 76 | }; |
77 | 77 | ||
78 | static struct net_device_stats *vti6_get_stats(struct net_device *dev) | ||
79 | { | ||
80 | struct pcpu_tstats sum = { 0 }; | ||
81 | int i; | ||
82 | |||
83 | for_each_possible_cpu(i) { | ||
84 | const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i); | ||
85 | |||
86 | sum.rx_packets += tstats->rx_packets; | ||
87 | sum.rx_bytes += tstats->rx_bytes; | ||
88 | sum.tx_packets += tstats->tx_packets; | ||
89 | sum.tx_bytes += tstats->tx_bytes; | ||
90 | } | ||
91 | dev->stats.rx_packets = sum.rx_packets; | ||
92 | dev->stats.rx_bytes = sum.rx_bytes; | ||
93 | dev->stats.tx_packets = sum.tx_packets; | ||
94 | dev->stats.tx_bytes = sum.tx_bytes; | ||
95 | return &dev->stats; | ||
96 | } | ||
97 | |||
98 | #define for_each_vti6_tunnel_rcu(start) \ | 78 | #define for_each_vti6_tunnel_rcu(start) \ |
99 | for (t = rcu_dereference(start); t; t = rcu_dereference(t->next)) | 79 | for (t = rcu_dereference(start); t; t = rcu_dereference(t->next)) |
100 | 80 | ||
@@ -331,8 +311,10 @@ static int vti6_rcv(struct sk_buff *skb) | |||
331 | } | 311 | } |
332 | 312 | ||
333 | tstats = this_cpu_ptr(t->dev->tstats); | 313 | tstats = this_cpu_ptr(t->dev->tstats); |
314 | u64_stats_update_begin(&tstats->syncp); | ||
334 | tstats->rx_packets++; | 315 | tstats->rx_packets++; |
335 | tstats->rx_bytes += skb->len; | 316 | tstats->rx_bytes += skb->len; |
317 | u64_stats_update_end(&tstats->syncp); | ||
336 | 318 | ||
337 | skb->mark = 0; | 319 | skb->mark = 0; |
338 | secpath_reset(skb); | 320 | secpath_reset(skb); |
@@ -716,7 +698,7 @@ static const struct net_device_ops vti6_netdev_ops = { | |||
716 | .ndo_start_xmit = vti6_tnl_xmit, | 698 | .ndo_start_xmit = vti6_tnl_xmit, |
717 | .ndo_do_ioctl = vti6_ioctl, | 699 | .ndo_do_ioctl = vti6_ioctl, |
718 | .ndo_change_mtu = vti6_change_mtu, | 700 | .ndo_change_mtu = vti6_change_mtu, |
719 | .ndo_get_stats = vti6_get_stats, | 701 | .ndo_get_stats64 = ip_tunnel_get_stats64, |
720 | }; | 702 | }; |
721 | 703 | ||
722 | /** | 704 | /** |
@@ -750,12 +732,18 @@ static void vti6_dev_setup(struct net_device *dev) | |||
750 | static inline int vti6_dev_init_gen(struct net_device *dev) | 732 | static inline int vti6_dev_init_gen(struct net_device *dev) |
751 | { | 733 | { |
752 | struct ip6_tnl *t = netdev_priv(dev); | 734 | struct ip6_tnl *t = netdev_priv(dev); |
735 | int i; | ||
753 | 736 | ||
754 | t->dev = dev; | 737 | t->dev = dev; |
755 | t->net = dev_net(dev); | 738 | t->net = dev_net(dev); |
756 | dev->tstats = alloc_percpu(struct pcpu_tstats); | 739 | dev->tstats = alloc_percpu(struct pcpu_tstats); |
757 | if (!dev->tstats) | 740 | if (!dev->tstats) |
758 | return -ENOMEM; | 741 | return -ENOMEM; |
742 | for_each_possible_cpu(i) { | ||
743 | struct pcpu_tstats *stats; | ||
744 | stats = per_cpu_ptr(dev->tstats, i); | ||
745 | u64_stats_init(&stats->syncp); | ||
746 | } | ||
759 | return 0; | 747 | return 0; |
760 | } | 748 | } |
761 | 749 | ||
diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c index f78f41aca8e9..a0d17270117c 100644 --- a/net/ipv6/netfilter/ip6t_SYNPROXY.c +++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c | |||
@@ -446,6 +446,7 @@ static void synproxy_tg6_destroy(const struct xt_tgdtor_param *par) | |||
446 | static struct xt_target synproxy_tg6_reg __read_mostly = { | 446 | static struct xt_target synproxy_tg6_reg __read_mostly = { |
447 | .name = "SYNPROXY", | 447 | .name = "SYNPROXY", |
448 | .family = NFPROTO_IPV6, | 448 | .family = NFPROTO_IPV6, |
449 | .hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD), | ||
449 | .target = synproxy_tg6, | 450 | .target = synproxy_tg6, |
450 | .targetsize = sizeof(struct xt_synproxy_info), | 451 | .targetsize = sizeof(struct xt_synproxy_info), |
451 | .checkentry = synproxy_tg6_check, | 452 | .checkentry = synproxy_tg6_check, |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index a0a48ac3403f..4b4944c3e4c4 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -1905,9 +1905,7 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort, | |||
1905 | else | 1905 | else |
1906 | rt->rt6i_gateway = *dest; | 1906 | rt->rt6i_gateway = *dest; |
1907 | rt->rt6i_flags = ort->rt6i_flags; | 1907 | rt->rt6i_flags = ort->rt6i_flags; |
1908 | if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) == | 1908 | rt6_set_from(rt, ort); |
1909 | (RTF_DEFAULT | RTF_ADDRCONF)) | ||
1910 | rt6_set_from(rt, ort); | ||
1911 | rt->rt6i_metric = 0; | 1909 | rt->rt6i_metric = 0; |
1912 | 1910 | ||
1913 | #ifdef CONFIG_IPV6_SUBTREES | 1911 | #ifdef CONFIG_IPV6_SUBTREES |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 366fbba3359a..d3005b34476a 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -702,8 +702,10 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
702 | } | 702 | } |
703 | 703 | ||
704 | tstats = this_cpu_ptr(tunnel->dev->tstats); | 704 | tstats = this_cpu_ptr(tunnel->dev->tstats); |
705 | u64_stats_update_begin(&tstats->syncp); | ||
705 | tstats->rx_packets++; | 706 | tstats->rx_packets++; |
706 | tstats->rx_bytes += skb->len; | 707 | tstats->rx_bytes += skb->len; |
708 | u64_stats_update_end(&tstats->syncp); | ||
707 | 709 | ||
708 | netif_rx(skb); | 710 | netif_rx(skb); |
709 | 711 | ||
@@ -924,7 +926,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
924 | if (tunnel->parms.iph.daddr && skb_dst(skb)) | 926 | if (tunnel->parms.iph.daddr && skb_dst(skb)) |
925 | skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); | 927 | skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); |
926 | 928 | ||
927 | if (skb->len > mtu) { | 929 | if (skb->len > mtu && !skb_is_gso(skb)) { |
928 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | 930 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
929 | ip_rt_put(rt); | 931 | ip_rt_put(rt); |
930 | goto tx_error; | 932 | goto tx_error; |
@@ -966,8 +968,10 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
966 | tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); | 968 | tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); |
967 | 969 | ||
968 | skb = iptunnel_handle_offloads(skb, false, SKB_GSO_SIT); | 970 | skb = iptunnel_handle_offloads(skb, false, SKB_GSO_SIT); |
969 | if (IS_ERR(skb)) | 971 | if (IS_ERR(skb)) { |
972 | ip_rt_put(rt); | ||
970 | goto out; | 973 | goto out; |
974 | } | ||
971 | 975 | ||
972 | err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, IPPROTO_IPV6, tos, | 976 | err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, IPPROTO_IPV6, tos, |
973 | ttl, df, !net_eq(tunnel->net, dev_net(dev))); | 977 | ttl, df, !net_eq(tunnel->net, dev_net(dev))); |