diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/icmp.c | 3 | ||||
-rw-r--r-- | net/ipv4/inet_diag.c | 5 | ||||
-rw-r--r-- | net/ipv4/ip_sockglue.c | 35 | ||||
-rw-r--r-- | net/ipv4/ip_vti.c | 5 | ||||
-rw-r--r-- | net/ipv4/ipmr.c | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_nat.c | 4 | ||||
-rw-r--r-- | net/ipv4/route.c | 9 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 19 | ||||
-rw-r--r-- | net/ipv4/tcp_illinois.c | 8 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 18 | ||||
-rw-r--r-- | net/ipv4/tcp_metrics.c | 14 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 4 | ||||
-rw-r--r-- | net/ipv4/xfrm4_policy.c | 13 |
13 files changed, 87 insertions, 54 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index f2eccd531746..17ff9fd7cdda 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -257,7 +257,8 @@ static inline bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt, | |||
257 | struct inet_peer *peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr, 1); | 257 | struct inet_peer *peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr, 1); |
258 | rc = inet_peer_xrlim_allow(peer, | 258 | rc = inet_peer_xrlim_allow(peer, |
259 | net->ipv4.sysctl_icmp_ratelimit); | 259 | net->ipv4.sysctl_icmp_ratelimit); |
260 | inet_putpeer(peer); | 260 | if (peer) |
261 | inet_putpeer(peer); | ||
261 | } | 262 | } |
262 | out: | 263 | out: |
263 | return rc; | 264 | return rc; |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 535584c00f91..0c34bfabc11f 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -892,13 +892,16 @@ static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, | |||
892 | struct inet_diag_req_v2 *r, struct nlattr *bc) | 892 | struct inet_diag_req_v2 *r, struct nlattr *bc) |
893 | { | 893 | { |
894 | const struct inet_diag_handler *handler; | 894 | const struct inet_diag_handler *handler; |
895 | int err = 0; | ||
895 | 896 | ||
896 | handler = inet_diag_lock_handler(r->sdiag_protocol); | 897 | handler = inet_diag_lock_handler(r->sdiag_protocol); |
897 | if (!IS_ERR(handler)) | 898 | if (!IS_ERR(handler)) |
898 | handler->dump(skb, cb, r, bc); | 899 | handler->dump(skb, cb, r, bc); |
900 | else | ||
901 | err = PTR_ERR(handler); | ||
899 | inet_diag_unlock_handler(handler); | 902 | inet_diag_unlock_handler(handler); |
900 | 903 | ||
901 | return skb->len; | 904 | return err ? : skb->len; |
902 | } | 905 | } |
903 | 906 | ||
904 | static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) | 907 | static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 5eea4a811042..14bbfcf717ac 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -457,19 +457,28 @@ static int do_ip_setsockopt(struct sock *sk, int level, | |||
457 | struct inet_sock *inet = inet_sk(sk); | 457 | struct inet_sock *inet = inet_sk(sk); |
458 | int val = 0, err; | 458 | int val = 0, err; |
459 | 459 | ||
460 | if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) | | 460 | switch (optname) { |
461 | (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) | | 461 | case IP_PKTINFO: |
462 | (1<<IP_RETOPTS) | (1<<IP_TOS) | | 462 | case IP_RECVTTL: |
463 | (1<<IP_TTL) | (1<<IP_HDRINCL) | | 463 | case IP_RECVOPTS: |
464 | (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) | | 464 | case IP_RECVTOS: |
465 | (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) | | 465 | case IP_RETOPTS: |
466 | (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT) | | 466 | case IP_TOS: |
467 | (1<<IP_MINTTL) | (1<<IP_NODEFRAG))) || | 467 | case IP_TTL: |
468 | optname == IP_UNICAST_IF || | 468 | case IP_HDRINCL: |
469 | optname == IP_MULTICAST_TTL || | 469 | case IP_MTU_DISCOVER: |
470 | optname == IP_MULTICAST_ALL || | 470 | case IP_RECVERR: |
471 | optname == IP_MULTICAST_LOOP || | 471 | case IP_ROUTER_ALERT: |
472 | optname == IP_RECVORIGDSTADDR) { | 472 | case IP_FREEBIND: |
473 | case IP_PASSSEC: | ||
474 | case IP_TRANSPARENT: | ||
475 | case IP_MINTTL: | ||
476 | case IP_NODEFRAG: | ||
477 | case IP_UNICAST_IF: | ||
478 | case IP_MULTICAST_TTL: | ||
479 | case IP_MULTICAST_ALL: | ||
480 | case IP_MULTICAST_LOOP: | ||
481 | case IP_RECVORIGDSTADDR: | ||
473 | if (optlen >= sizeof(int)) { | 482 | if (optlen >= sizeof(int)) { |
474 | if (get_user(val, (int __user *) optval)) | 483 | if (get_user(val, (int __user *) optval)) |
475 | return -EFAULT; | 484 | return -EFAULT; |
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 1831092f999f..858fddf6482a 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c | |||
@@ -338,12 +338,17 @@ static int vti_rcv(struct sk_buff *skb) | |||
338 | if (tunnel != NULL) { | 338 | if (tunnel != NULL) { |
339 | struct pcpu_tstats *tstats; | 339 | struct pcpu_tstats *tstats; |
340 | 340 | ||
341 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) | ||
342 | return -1; | ||
343 | |||
341 | tstats = this_cpu_ptr(tunnel->dev->tstats); | 344 | tstats = this_cpu_ptr(tunnel->dev->tstats); |
342 | u64_stats_update_begin(&tstats->syncp); | 345 | u64_stats_update_begin(&tstats->syncp); |
343 | tstats->rx_packets++; | 346 | tstats->rx_packets++; |
344 | tstats->rx_bytes += skb->len; | 347 | tstats->rx_bytes += skb->len; |
345 | u64_stats_update_end(&tstats->syncp); | 348 | u64_stats_update_end(&tstats->syncp); |
346 | 349 | ||
350 | skb->mark = 0; | ||
351 | secpath_reset(skb); | ||
347 | skb->dev = tunnel->dev; | 352 | skb->dev = tunnel->dev; |
348 | return 1; | 353 | return 1; |
349 | } | 354 | } |
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 6168c4dc58b1..3eab2b2ffd34 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -1318,6 +1318,10 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi | |||
1318 | if (get_user(v, (u32 __user *)optval)) | 1318 | if (get_user(v, (u32 __user *)optval)) |
1319 | return -EFAULT; | 1319 | return -EFAULT; |
1320 | 1320 | ||
1321 | /* "pimreg%u" should not exceed 16 bytes (IFNAMSIZ) */ | ||
1322 | if (v != RT_TABLE_DEFAULT && v >= 1000000000) | ||
1323 | return -EINVAL; | ||
1324 | |||
1321 | rtnl_lock(); | 1325 | rtnl_lock(); |
1322 | ret = 0; | 1326 | ret = 0; |
1323 | if (sk == rtnl_dereference(mrt->mroute_sk)) { | 1327 | if (sk == rtnl_dereference(mrt->mroute_sk)) { |
diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c index 9e0ffaf1d942..a82047282dbb 100644 --- a/net/ipv4/netfilter/iptable_nat.c +++ b/net/ipv4/netfilter/iptable_nat.c | |||
@@ -184,7 +184,8 @@ nf_nat_ipv4_out(unsigned int hooknum, | |||
184 | 184 | ||
185 | if ((ct->tuplehash[dir].tuple.src.u3.ip != | 185 | if ((ct->tuplehash[dir].tuple.src.u3.ip != |
186 | ct->tuplehash[!dir].tuple.dst.u3.ip) || | 186 | ct->tuplehash[!dir].tuple.dst.u3.ip) || |
187 | (ct->tuplehash[dir].tuple.src.u.all != | 187 | (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && |
188 | ct->tuplehash[dir].tuple.src.u.all != | ||
188 | ct->tuplehash[!dir].tuple.dst.u.all)) | 189 | ct->tuplehash[!dir].tuple.dst.u.all)) |
189 | if (nf_xfrm_me_harder(skb, AF_INET) < 0) | 190 | if (nf_xfrm_me_harder(skb, AF_INET) < 0) |
190 | ret = NF_DROP; | 191 | ret = NF_DROP; |
@@ -221,6 +222,7 @@ nf_nat_ipv4_local_fn(unsigned int hooknum, | |||
221 | } | 222 | } |
222 | #ifdef CONFIG_XFRM | 223 | #ifdef CONFIG_XFRM |
223 | else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && | 224 | else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && |
225 | ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && | ||
224 | ct->tuplehash[dir].tuple.dst.u.all != | 226 | ct->tuplehash[dir].tuple.dst.u.all != |
225 | ct->tuplehash[!dir].tuple.src.u.all) | 227 | ct->tuplehash[!dir].tuple.src.u.all) |
226 | if (nf_xfrm_me_harder(skb, AF_INET) < 0) | 228 | if (nf_xfrm_me_harder(skb, AF_INET) < 0) |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index a8c651216fa6..df251424d816 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1785,6 +1785,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, | |||
1785 | if (dev_out->flags & IFF_LOOPBACK) | 1785 | if (dev_out->flags & IFF_LOOPBACK) |
1786 | flags |= RTCF_LOCAL; | 1786 | flags |= RTCF_LOCAL; |
1787 | 1787 | ||
1788 | do_cache = true; | ||
1788 | if (type == RTN_BROADCAST) { | 1789 | if (type == RTN_BROADCAST) { |
1789 | flags |= RTCF_BROADCAST | RTCF_LOCAL; | 1790 | flags |= RTCF_BROADCAST | RTCF_LOCAL; |
1790 | fi = NULL; | 1791 | fi = NULL; |
@@ -1793,6 +1794,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res, | |||
1793 | if (!ip_check_mc_rcu(in_dev, fl4->daddr, fl4->saddr, | 1794 | if (!ip_check_mc_rcu(in_dev, fl4->daddr, fl4->saddr, |
1794 | fl4->flowi4_proto)) | 1795 | fl4->flowi4_proto)) |
1795 | flags &= ~RTCF_LOCAL; | 1796 | flags &= ~RTCF_LOCAL; |
1797 | else | ||
1798 | do_cache = false; | ||
1796 | /* If multicast route do not exist use | 1799 | /* If multicast route do not exist use |
1797 | * default one, but do not gateway in this case. | 1800 | * default one, but do not gateway in this case. |
1798 | * Yes, it is hack. | 1801 | * Yes, it is hack. |
@@ -1802,8 +1805,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res, | |||
1802 | } | 1805 | } |
1803 | 1806 | ||
1804 | fnhe = NULL; | 1807 | fnhe = NULL; |
1805 | do_cache = fi != NULL; | 1808 | do_cache &= fi != NULL; |
1806 | if (fi) { | 1809 | if (do_cache) { |
1807 | struct rtable __rcu **prth; | 1810 | struct rtable __rcu **prth; |
1808 | struct fib_nh *nh = &FIB_RES_NH(*res); | 1811 | struct fib_nh *nh = &FIB_RES_NH(*res); |
1809 | 1812 | ||
@@ -2597,7 +2600,7 @@ int __init ip_rt_init(void) | |||
2597 | pr_err("Unable to create route proc files\n"); | 2600 | pr_err("Unable to create route proc files\n"); |
2598 | #ifdef CONFIG_XFRM | 2601 | #ifdef CONFIG_XFRM |
2599 | xfrm_init(); | 2602 | xfrm_init(); |
2600 | xfrm4_init(ip_rt_max_size); | 2603 | xfrm4_init(); |
2601 | #endif | 2604 | #endif |
2602 | rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL, NULL); | 2605 | rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL, NULL); |
2603 | 2606 | ||
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 197c0008503c..e457c7ab2e28 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -830,8 +830,8 @@ static int tcp_send_mss(struct sock *sk, int *size_goal, int flags) | |||
830 | return mss_now; | 830 | return mss_now; |
831 | } | 831 | } |
832 | 832 | ||
833 | static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, | 833 | static ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset, |
834 | size_t psize, int flags) | 834 | size_t size, int flags) |
835 | { | 835 | { |
836 | struct tcp_sock *tp = tcp_sk(sk); | 836 | struct tcp_sock *tp = tcp_sk(sk); |
837 | int mss_now, size_goal; | 837 | int mss_now, size_goal; |
@@ -858,12 +858,9 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse | |||
858 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) | 858 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) |
859 | goto out_err; | 859 | goto out_err; |
860 | 860 | ||
861 | while (psize > 0) { | 861 | while (size > 0) { |
862 | struct sk_buff *skb = tcp_write_queue_tail(sk); | 862 | struct sk_buff *skb = tcp_write_queue_tail(sk); |
863 | struct page *page = pages[poffset / PAGE_SIZE]; | ||
864 | int copy, i; | 863 | int copy, i; |
865 | int offset = poffset % PAGE_SIZE; | ||
866 | int size = min_t(size_t, psize, PAGE_SIZE - offset); | ||
867 | bool can_coalesce; | 864 | bool can_coalesce; |
868 | 865 | ||
869 | if (!tcp_send_head(sk) || (copy = size_goal - skb->len) <= 0) { | 866 | if (!tcp_send_head(sk) || (copy = size_goal - skb->len) <= 0) { |
@@ -912,8 +909,8 @@ new_segment: | |||
912 | TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_PSH; | 909 | TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_PSH; |
913 | 910 | ||
914 | copied += copy; | 911 | copied += copy; |
915 | poffset += copy; | 912 | offset += copy; |
916 | if (!(psize -= copy)) | 913 | if (!(size -= copy)) |
917 | goto out; | 914 | goto out; |
918 | 915 | ||
919 | if (skb->len < size_goal || (flags & MSG_OOB)) | 916 | if (skb->len < size_goal || (flags & MSG_OOB)) |
@@ -960,7 +957,7 @@ int tcp_sendpage(struct sock *sk, struct page *page, int offset, | |||
960 | flags); | 957 | flags); |
961 | 958 | ||
962 | lock_sock(sk); | 959 | lock_sock(sk); |
963 | res = do_tcp_sendpages(sk, &page, offset, size, flags); | 960 | res = do_tcp_sendpages(sk, page, offset, size, flags); |
964 | release_sock(sk); | 961 | release_sock(sk); |
965 | return res; | 962 | return res; |
966 | } | 963 | } |
@@ -1212,7 +1209,7 @@ new_segment: | |||
1212 | wait_for_sndbuf: | 1209 | wait_for_sndbuf: |
1213 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | 1210 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); |
1214 | wait_for_memory: | 1211 | wait_for_memory: |
1215 | if (copied && likely(!tp->repair)) | 1212 | if (copied) |
1216 | tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH); | 1213 | tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH); |
1217 | 1214 | ||
1218 | if ((err = sk_stream_wait_memory(sk, &timeo)) != 0) | 1215 | if ((err = sk_stream_wait_memory(sk, &timeo)) != 0) |
@@ -1223,7 +1220,7 @@ wait_for_memory: | |||
1223 | } | 1220 | } |
1224 | 1221 | ||
1225 | out: | 1222 | out: |
1226 | if (copied && likely(!tp->repair)) | 1223 | if (copied) |
1227 | tcp_push(sk, flags, mss_now, tp->nonagle); | 1224 | tcp_push(sk, flags, mss_now, tp->nonagle); |
1228 | release_sock(sk); | 1225 | release_sock(sk); |
1229 | return copied + copied_syn; | 1226 | return copied + copied_syn; |
diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c index 813b43a76fec..834857f3c871 100644 --- a/net/ipv4/tcp_illinois.c +++ b/net/ipv4/tcp_illinois.c | |||
@@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext, | |||
313 | .tcpv_rttcnt = ca->cnt_rtt, | 313 | .tcpv_rttcnt = ca->cnt_rtt, |
314 | .tcpv_minrtt = ca->base_rtt, | 314 | .tcpv_minrtt = ca->base_rtt, |
315 | }; | 315 | }; |
316 | u64 t = ca->sum_rtt; | ||
317 | 316 | ||
318 | do_div(t, ca->cnt_rtt); | 317 | if (info.tcpv_rttcnt > 0) { |
319 | info.tcpv_rtt = t; | 318 | u64 t = ca->sum_rtt; |
320 | 319 | ||
320 | do_div(t, info.tcpv_rttcnt); | ||
321 | info.tcpv_rtt = t; | ||
322 | } | ||
321 | nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info); | 323 | nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info); |
322 | } | 324 | } |
323 | } | 325 | } |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 1db663983587..609ff98aeb47 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -4529,6 +4529,9 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) | |||
4529 | struct tcphdr *th; | 4529 | struct tcphdr *th; |
4530 | bool fragstolen; | 4530 | bool fragstolen; |
4531 | 4531 | ||
4532 | if (size == 0) | ||
4533 | return 0; | ||
4534 | |||
4532 | skb = alloc_skb(size + sizeof(*th), sk->sk_allocation); | 4535 | skb = alloc_skb(size + sizeof(*th), sk->sk_allocation); |
4533 | if (!skb) | 4536 | if (!skb) |
4534 | goto err; | 4537 | goto err; |
@@ -5310,11 +5313,6 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, | |||
5310 | goto discard; | 5313 | goto discard; |
5311 | } | 5314 | } |
5312 | 5315 | ||
5313 | /* ts_recent update must be made after we are sure that the packet | ||
5314 | * is in window. | ||
5315 | */ | ||
5316 | tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); | ||
5317 | |||
5318 | /* step 3: check security and precedence [ignored] */ | 5316 | /* step 3: check security and precedence [ignored] */ |
5319 | 5317 | ||
5320 | /* step 4: Check for a SYN | 5318 | /* step 4: Check for a SYN |
@@ -5549,6 +5547,11 @@ step5: | |||
5549 | if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) | 5547 | if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) |
5550 | goto discard; | 5548 | goto discard; |
5551 | 5549 | ||
5550 | /* ts_recent update must be made after we are sure that the packet | ||
5551 | * is in window. | ||
5552 | */ | ||
5553 | tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); | ||
5554 | |||
5552 | tcp_rcv_rtt_measure_ts(sk, skb); | 5555 | tcp_rcv_rtt_measure_ts(sk, skb); |
5553 | 5556 | ||
5554 | /* Process urgent data. */ | 5557 | /* Process urgent data. */ |
@@ -6127,6 +6130,11 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
6127 | } else | 6130 | } else |
6128 | goto discard; | 6131 | goto discard; |
6129 | 6132 | ||
6133 | /* ts_recent update must be made after we are sure that the packet | ||
6134 | * is in window. | ||
6135 | */ | ||
6136 | tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); | ||
6137 | |||
6130 | /* step 6: check the URG bit */ | 6138 | /* step 6: check the URG bit */ |
6131 | tcp_urg(sk, skb, th); | 6139 | tcp_urg(sk, skb, th); |
6132 | 6140 | ||
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 4c752a6e0bcd..f696d7c2e9fa 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c | |||
@@ -1,7 +1,6 @@ | |||
1 | #include <linux/rcupdate.h> | 1 | #include <linux/rcupdate.h> |
2 | #include <linux/spinlock.h> | 2 | #include <linux/spinlock.h> |
3 | #include <linux/jiffies.h> | 3 | #include <linux/jiffies.h> |
4 | #include <linux/bootmem.h> | ||
5 | #include <linux/module.h> | 4 | #include <linux/module.h> |
6 | #include <linux/cache.h> | 5 | #include <linux/cache.h> |
7 | #include <linux/slab.h> | 6 | #include <linux/slab.h> |
@@ -9,6 +8,7 @@ | |||
9 | #include <linux/tcp.h> | 8 | #include <linux/tcp.h> |
10 | #include <linux/hash.h> | 9 | #include <linux/hash.h> |
11 | #include <linux/tcp_metrics.h> | 10 | #include <linux/tcp_metrics.h> |
11 | #include <linux/vmalloc.h> | ||
12 | 12 | ||
13 | #include <net/inet_connection_sock.h> | 13 | #include <net/inet_connection_sock.h> |
14 | #include <net/net_namespace.h> | 14 | #include <net/net_namespace.h> |
@@ -864,7 +864,7 @@ static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr, | |||
864 | } | 864 | } |
865 | a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6]; | 865 | a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6]; |
866 | if (a) { | 866 | if (a) { |
867 | if (nla_len(a) != sizeof(sizeof(struct in6_addr))) | 867 | if (nla_len(a) != sizeof(struct in6_addr)) |
868 | return -EINVAL; | 868 | return -EINVAL; |
869 | addr->family = AF_INET6; | 869 | addr->family = AF_INET6; |
870 | memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6)); | 870 | memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6)); |
@@ -1034,7 +1034,10 @@ static int __net_init tcp_net_metrics_init(struct net *net) | |||
1034 | net->ipv4.tcp_metrics_hash_log = order_base_2(slots); | 1034 | net->ipv4.tcp_metrics_hash_log = order_base_2(slots); |
1035 | size = sizeof(struct tcpm_hash_bucket) << net->ipv4.tcp_metrics_hash_log; | 1035 | size = sizeof(struct tcpm_hash_bucket) << net->ipv4.tcp_metrics_hash_log; |
1036 | 1036 | ||
1037 | net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL); | 1037 | net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); |
1038 | if (!net->ipv4.tcp_metrics_hash) | ||
1039 | net->ipv4.tcp_metrics_hash = vzalloc(size); | ||
1040 | |||
1038 | if (!net->ipv4.tcp_metrics_hash) | 1041 | if (!net->ipv4.tcp_metrics_hash) |
1039 | return -ENOMEM; | 1042 | return -ENOMEM; |
1040 | 1043 | ||
@@ -1055,7 +1058,10 @@ static void __net_exit tcp_net_metrics_exit(struct net *net) | |||
1055 | tm = next; | 1058 | tm = next; |
1056 | } | 1059 | } |
1057 | } | 1060 | } |
1058 | kfree(net->ipv4.tcp_metrics_hash); | 1061 | if (is_vmalloc_addr(net->ipv4.tcp_metrics_hash)) |
1062 | vfree(net->ipv4.tcp_metrics_hash); | ||
1063 | else | ||
1064 | kfree(net->ipv4.tcp_metrics_hash); | ||
1059 | } | 1065 | } |
1060 | 1066 | ||
1061 | static __net_initdata struct pernet_operations tcp_net_metrics_ops = { | 1067 | static __net_initdata struct pernet_operations tcp_net_metrics_ops = { |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index cfe6ffe1c177..2798706cb063 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -1986,6 +1986,9 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, | |||
1986 | tso_segs = tcp_init_tso_segs(sk, skb, mss_now); | 1986 | tso_segs = tcp_init_tso_segs(sk, skb, mss_now); |
1987 | BUG_ON(!tso_segs); | 1987 | BUG_ON(!tso_segs); |
1988 | 1988 | ||
1989 | if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE) | ||
1990 | goto repair; /* Skip network transmission */ | ||
1991 | |||
1989 | cwnd_quota = tcp_cwnd_test(tp, skb); | 1992 | cwnd_quota = tcp_cwnd_test(tp, skb); |
1990 | if (!cwnd_quota) | 1993 | if (!cwnd_quota) |
1991 | break; | 1994 | break; |
@@ -2026,6 +2029,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, | |||
2026 | if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp))) | 2029 | if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp))) |
2027 | break; | 2030 | break; |
2028 | 2031 | ||
2032 | repair: | ||
2029 | /* Advance the send_head. This one is sent out. | 2033 | /* Advance the send_head. This one is sent out. |
2030 | * This call will increment packets_out. | 2034 | * This call will increment packets_out. |
2031 | */ | 2035 | */ |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 05c5ab8d983c..3be0ac2c1920 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -279,19 +279,8 @@ static void __exit xfrm4_policy_fini(void) | |||
279 | xfrm_policy_unregister_afinfo(&xfrm4_policy_afinfo); | 279 | xfrm_policy_unregister_afinfo(&xfrm4_policy_afinfo); |
280 | } | 280 | } |
281 | 281 | ||
282 | void __init xfrm4_init(int rt_max_size) | 282 | void __init xfrm4_init(void) |
283 | { | 283 | { |
284 | /* | ||
285 | * Select a default value for the gc_thresh based on the main route | ||
286 | * table hash size. It seems to me the worst case scenario is when | ||
287 | * we have ipsec operating in transport mode, in which we create a | ||
288 | * dst_entry per socket. The xfrm gc algorithm starts trying to remove | ||
289 | * entries at gc_thresh, and prevents new allocations as 2*gc_thresh | ||
290 | * so lets set an initial xfrm gc_thresh value at the rt_max_size/2. | ||
291 | * That will let us store an ipsec connection per route table entry, | ||
292 | * and start cleaning when were 1/2 full | ||
293 | */ | ||
294 | xfrm4_dst_ops.gc_thresh = rt_max_size/2; | ||
295 | dst_entries_init(&xfrm4_dst_ops); | 284 | dst_entries_init(&xfrm4_dst_ops); |
296 | 285 | ||
297 | xfrm4_state_init(); | 286 | xfrm4_state_init(); |