diff options
Diffstat (limited to 'net/ipv4/af_inet.c')
-rw-r--r-- | net/ipv4/af_inet.c | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index f71357422380..551ce564b035 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -154,7 +154,7 @@ void inet_sock_destruct(struct sock *sk) | |||
154 | WARN_ON(sk->sk_forward_alloc); | 154 | WARN_ON(sk->sk_forward_alloc); |
155 | 155 | ||
156 | kfree(inet->opt); | 156 | kfree(inet->opt); |
157 | dst_release(sk->sk_dst_cache); | 157 | dst_release(rcu_dereference_check(sk->sk_dst_cache, 1)); |
158 | sk_refcnt_debug_dec(sk); | 158 | sk_refcnt_debug_dec(sk); |
159 | } | 159 | } |
160 | EXPORT_SYMBOL(inet_sock_destruct); | 160 | EXPORT_SYMBOL(inet_sock_destruct); |
@@ -419,6 +419,8 @@ int inet_release(struct socket *sock) | |||
419 | if (sk) { | 419 | if (sk) { |
420 | long timeout; | 420 | long timeout; |
421 | 421 | ||
422 | sock_rps_reset_flow(sk); | ||
423 | |||
422 | /* Applications forget to leave groups before exiting */ | 424 | /* Applications forget to leave groups before exiting */ |
423 | ip_mc_drop_socket(sk); | 425 | ip_mc_drop_socket(sk); |
424 | 426 | ||
@@ -546,7 +548,7 @@ static long inet_wait_for_connect(struct sock *sk, long timeo) | |||
546 | { | 548 | { |
547 | DEFINE_WAIT(wait); | 549 | DEFINE_WAIT(wait); |
548 | 550 | ||
549 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 551 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
550 | 552 | ||
551 | /* Basic assumption: if someone sets sk->sk_err, he _must_ | 553 | /* Basic assumption: if someone sets sk->sk_err, he _must_ |
552 | * change state of the socket from TCP_SYN_*. | 554 | * change state of the socket from TCP_SYN_*. |
@@ -559,9 +561,9 @@ static long inet_wait_for_connect(struct sock *sk, long timeo) | |||
559 | lock_sock(sk); | 561 | lock_sock(sk); |
560 | if (signal_pending(current) || !timeo) | 562 | if (signal_pending(current) || !timeo) |
561 | break; | 563 | break; |
562 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 564 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
563 | } | 565 | } |
564 | finish_wait(sk->sk_sleep, &wait); | 566 | finish_wait(sk_sleep(sk), &wait); |
565 | return timeo; | 567 | return timeo; |
566 | } | 568 | } |
567 | 569 | ||
@@ -720,6 +722,8 @@ int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
720 | { | 722 | { |
721 | struct sock *sk = sock->sk; | 723 | struct sock *sk = sock->sk; |
722 | 724 | ||
725 | sock_rps_record_flow(sk); | ||
726 | |||
723 | /* We may need to bind the socket. */ | 727 | /* We may need to bind the socket. */ |
724 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) | 728 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) |
725 | return -EAGAIN; | 729 | return -EAGAIN; |
@@ -728,12 +732,13 @@ int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
728 | } | 732 | } |
729 | EXPORT_SYMBOL(inet_sendmsg); | 733 | EXPORT_SYMBOL(inet_sendmsg); |
730 | 734 | ||
731 | |||
732 | static ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, | 735 | static ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, |
733 | size_t size, int flags) | 736 | size_t size, int flags) |
734 | { | 737 | { |
735 | struct sock *sk = sock->sk; | 738 | struct sock *sk = sock->sk; |
736 | 739 | ||
740 | sock_rps_record_flow(sk); | ||
741 | |||
737 | /* We may need to bind the socket. */ | 742 | /* We may need to bind the socket. */ |
738 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) | 743 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) |
739 | return -EAGAIN; | 744 | return -EAGAIN; |
@@ -743,6 +748,22 @@ static ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, | |||
743 | return sock_no_sendpage(sock, page, offset, size, flags); | 748 | return sock_no_sendpage(sock, page, offset, size, flags); |
744 | } | 749 | } |
745 | 750 | ||
751 | int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | ||
752 | size_t size, int flags) | ||
753 | { | ||
754 | struct sock *sk = sock->sk; | ||
755 | int addr_len = 0; | ||
756 | int err; | ||
757 | |||
758 | sock_rps_record_flow(sk); | ||
759 | |||
760 | err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT, | ||
761 | flags & ~MSG_DONTWAIT, &addr_len); | ||
762 | if (err >= 0) | ||
763 | msg->msg_namelen = addr_len; | ||
764 | return err; | ||
765 | } | ||
766 | EXPORT_SYMBOL(inet_recvmsg); | ||
746 | 767 | ||
747 | int inet_shutdown(struct socket *sock, int how) | 768 | int inet_shutdown(struct socket *sock, int how) |
748 | { | 769 | { |
@@ -872,7 +893,7 @@ const struct proto_ops inet_stream_ops = { | |||
872 | .setsockopt = sock_common_setsockopt, | 893 | .setsockopt = sock_common_setsockopt, |
873 | .getsockopt = sock_common_getsockopt, | 894 | .getsockopt = sock_common_getsockopt, |
874 | .sendmsg = tcp_sendmsg, | 895 | .sendmsg = tcp_sendmsg, |
875 | .recvmsg = sock_common_recvmsg, | 896 | .recvmsg = inet_recvmsg, |
876 | .mmap = sock_no_mmap, | 897 | .mmap = sock_no_mmap, |
877 | .sendpage = tcp_sendpage, | 898 | .sendpage = tcp_sendpage, |
878 | .splice_read = tcp_splice_read, | 899 | .splice_read = tcp_splice_read, |
@@ -899,7 +920,7 @@ const struct proto_ops inet_dgram_ops = { | |||
899 | .setsockopt = sock_common_setsockopt, | 920 | .setsockopt = sock_common_setsockopt, |
900 | .getsockopt = sock_common_getsockopt, | 921 | .getsockopt = sock_common_getsockopt, |
901 | .sendmsg = inet_sendmsg, | 922 | .sendmsg = inet_sendmsg, |
902 | .recvmsg = sock_common_recvmsg, | 923 | .recvmsg = inet_recvmsg, |
903 | .mmap = sock_no_mmap, | 924 | .mmap = sock_no_mmap, |
904 | .sendpage = inet_sendpage, | 925 | .sendpage = inet_sendpage, |
905 | #ifdef CONFIG_COMPAT | 926 | #ifdef CONFIG_COMPAT |
@@ -929,7 +950,7 @@ static const struct proto_ops inet_sockraw_ops = { | |||
929 | .setsockopt = sock_common_setsockopt, | 950 | .setsockopt = sock_common_setsockopt, |
930 | .getsockopt = sock_common_getsockopt, | 951 | .getsockopt = sock_common_getsockopt, |
931 | .sendmsg = inet_sendmsg, | 952 | .sendmsg = inet_sendmsg, |
932 | .recvmsg = sock_common_recvmsg, | 953 | .recvmsg = inet_recvmsg, |
933 | .mmap = sock_no_mmap, | 954 | .mmap = sock_no_mmap, |
934 | .sendpage = inet_sendpage, | 955 | .sendpage = inet_sendpage, |
935 | #ifdef CONFIG_COMPAT | 956 | #ifdef CONFIG_COMPAT |
@@ -1302,8 +1323,8 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
1302 | if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) | 1323 | if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) |
1303 | goto out_unlock; | 1324 | goto out_unlock; |
1304 | 1325 | ||
1305 | id = ntohl(*(u32 *)&iph->id); | 1326 | id = ntohl(*(__be32 *)&iph->id); |
1306 | flush = (u16)((ntohl(*(u32 *)iph) ^ skb_gro_len(skb)) | (id ^ IP_DF)); | 1327 | flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id ^ IP_DF)); |
1307 | id >>= 16; | 1328 | id >>= 16; |
1308 | 1329 | ||
1309 | for (p = *head; p; p = p->next) { | 1330 | for (p = *head; p; p = p->next) { |
@@ -1316,8 +1337,8 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
1316 | 1337 | ||
1317 | if ((iph->protocol ^ iph2->protocol) | | 1338 | if ((iph->protocol ^ iph2->protocol) | |
1318 | (iph->tos ^ iph2->tos) | | 1339 | (iph->tos ^ iph2->tos) | |
1319 | (iph->saddr ^ iph2->saddr) | | 1340 | ((__force u32)iph->saddr ^ (__force u32)iph2->saddr) | |
1320 | (iph->daddr ^ iph2->daddr)) { | 1341 | ((__force u32)iph->daddr ^ (__force u32)iph2->daddr)) { |
1321 | NAPI_GRO_CB(p)->same_flow = 0; | 1342 | NAPI_GRO_CB(p)->same_flow = 0; |
1322 | continue; | 1343 | continue; |
1323 | } | 1344 | } |
@@ -1407,10 +1428,10 @@ EXPORT_SYMBOL_GPL(snmp_fold_field); | |||
1407 | int snmp_mib_init(void __percpu *ptr[2], size_t mibsize) | 1428 | int snmp_mib_init(void __percpu *ptr[2], size_t mibsize) |
1408 | { | 1429 | { |
1409 | BUG_ON(ptr == NULL); | 1430 | BUG_ON(ptr == NULL); |
1410 | ptr[0] = __alloc_percpu(mibsize, __alignof__(unsigned long long)); | 1431 | ptr[0] = __alloc_percpu(mibsize, __alignof__(unsigned long)); |
1411 | if (!ptr[0]) | 1432 | if (!ptr[0]) |
1412 | goto err0; | 1433 | goto err0; |
1413 | ptr[1] = __alloc_percpu(mibsize, __alignof__(unsigned long long)); | 1434 | ptr[1] = __alloc_percpu(mibsize, __alignof__(unsigned long)); |
1414 | if (!ptr[1]) | 1435 | if (!ptr[1]) |
1415 | goto err1; | 1436 | goto err1; |
1416 | return 0; | 1437 | return 0; |
@@ -1552,9 +1573,13 @@ static int __init inet_init(void) | |||
1552 | 1573 | ||
1553 | BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)); | 1574 | BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)); |
1554 | 1575 | ||
1576 | sysctl_local_reserved_ports = kzalloc(65536 / 8, GFP_KERNEL); | ||
1577 | if (!sysctl_local_reserved_ports) | ||
1578 | goto out; | ||
1579 | |||
1555 | rc = proto_register(&tcp_prot, 1); | 1580 | rc = proto_register(&tcp_prot, 1); |
1556 | if (rc) | 1581 | if (rc) |
1557 | goto out; | 1582 | goto out_free_reserved_ports; |
1558 | 1583 | ||
1559 | rc = proto_register(&udp_prot, 1); | 1584 | rc = proto_register(&udp_prot, 1); |
1560 | if (rc) | 1585 | if (rc) |
@@ -1653,6 +1678,8 @@ out_unregister_udp_proto: | |||
1653 | proto_unregister(&udp_prot); | 1678 | proto_unregister(&udp_prot); |
1654 | out_unregister_tcp_proto: | 1679 | out_unregister_tcp_proto: |
1655 | proto_unregister(&tcp_prot); | 1680 | proto_unregister(&tcp_prot); |
1681 | out_free_reserved_ports: | ||
1682 | kfree(sysctl_local_reserved_ports); | ||
1656 | goto out; | 1683 | goto out; |
1657 | } | 1684 | } |
1658 | 1685 | ||