diff options
Diffstat (limited to 'net/rds/recv.c')
-rw-r--r-- | net/rds/recv.c | 51 |
1 files changed, 34 insertions, 17 deletions
diff --git a/net/rds/recv.c b/net/rds/recv.c index 192ac6f78ded..4217961fd130 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 Oracle. All rights reserved. | 2 | * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -41,14 +41,14 @@ | |||
41 | #include "rds.h" | 41 | #include "rds.h" |
42 | 42 | ||
43 | void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn, | 43 | void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn, |
44 | __be32 saddr) | 44 | struct in6_addr *saddr) |
45 | { | 45 | { |
46 | int i; | 46 | int i; |
47 | 47 | ||
48 | refcount_set(&inc->i_refcount, 1); | 48 | refcount_set(&inc->i_refcount, 1); |
49 | INIT_LIST_HEAD(&inc->i_item); | 49 | INIT_LIST_HEAD(&inc->i_item); |
50 | inc->i_conn = conn; | 50 | inc->i_conn = conn; |
51 | inc->i_saddr = saddr; | 51 | inc->i_saddr = *saddr; |
52 | inc->i_rdma_cookie = 0; | 52 | inc->i_rdma_cookie = 0; |
53 | inc->i_rx_tstamp.tv_sec = 0; | 53 | inc->i_rx_tstamp.tv_sec = 0; |
54 | inc->i_rx_tstamp.tv_usec = 0; | 54 | inc->i_rx_tstamp.tv_usec = 0; |
@@ -59,13 +59,13 @@ void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn, | |||
59 | EXPORT_SYMBOL_GPL(rds_inc_init); | 59 | EXPORT_SYMBOL_GPL(rds_inc_init); |
60 | 60 | ||
61 | void rds_inc_path_init(struct rds_incoming *inc, struct rds_conn_path *cp, | 61 | void rds_inc_path_init(struct rds_incoming *inc, struct rds_conn_path *cp, |
62 | __be32 saddr) | 62 | struct in6_addr *saddr) |
63 | { | 63 | { |
64 | refcount_set(&inc->i_refcount, 1); | 64 | refcount_set(&inc->i_refcount, 1); |
65 | INIT_LIST_HEAD(&inc->i_item); | 65 | INIT_LIST_HEAD(&inc->i_item); |
66 | inc->i_conn = cp->cp_conn; | 66 | inc->i_conn = cp->cp_conn; |
67 | inc->i_conn_path = cp; | 67 | inc->i_conn_path = cp; |
68 | inc->i_saddr = saddr; | 68 | inc->i_saddr = *saddr; |
69 | inc->i_rdma_cookie = 0; | 69 | inc->i_rdma_cookie = 0; |
70 | inc->i_rx_tstamp.tv_sec = 0; | 70 | inc->i_rx_tstamp.tv_sec = 0; |
71 | inc->i_rx_tstamp.tv_usec = 0; | 71 | inc->i_rx_tstamp.tv_usec = 0; |
@@ -110,7 +110,7 @@ static void rds_recv_rcvbuf_delta(struct rds_sock *rs, struct sock *sk, | |||
110 | 110 | ||
111 | now_congested = rs->rs_rcv_bytes > rds_sk_rcvbuf(rs); | 111 | now_congested = rs->rs_rcv_bytes > rds_sk_rcvbuf(rs); |
112 | 112 | ||
113 | rdsdebug("rs %p (%pI4:%u) recv bytes %d buf %d " | 113 | rdsdebug("rs %p (%pI6c:%u) recv bytes %d buf %d " |
114 | "now_cong %d delta %d\n", | 114 | "now_cong %d delta %d\n", |
115 | rs, &rs->rs_bound_addr, | 115 | rs, &rs->rs_bound_addr, |
116 | ntohs(rs->rs_bound_port), rs->rs_rcv_bytes, | 116 | ntohs(rs->rs_bound_port), rs->rs_rcv_bytes, |
@@ -260,7 +260,7 @@ static void rds_start_mprds(struct rds_connection *conn) | |||
260 | struct rds_conn_path *cp; | 260 | struct rds_conn_path *cp; |
261 | 261 | ||
262 | if (conn->c_npaths > 1 && | 262 | if (conn->c_npaths > 1 && |
263 | IS_CANONICAL(conn->c_laddr, conn->c_faddr)) { | 263 | rds_addr_cmp(&conn->c_laddr, &conn->c_faddr) < 0) { |
264 | for (i = 0; i < conn->c_npaths; i++) { | 264 | for (i = 0; i < conn->c_npaths; i++) { |
265 | cp = &conn->c_path[i]; | 265 | cp = &conn->c_path[i]; |
266 | rds_conn_path_connect_if_down(cp); | 266 | rds_conn_path_connect_if_down(cp); |
@@ -284,7 +284,8 @@ static void rds_start_mprds(struct rds_connection *conn) | |||
284 | * conn. This lets loopback, who only has one conn for both directions, | 284 | * conn. This lets loopback, who only has one conn for both directions, |
285 | * tell us which roles the addrs in the conn are playing for this message. | 285 | * tell us which roles the addrs in the conn are playing for this message. |
286 | */ | 286 | */ |
287 | void rds_recv_incoming(struct rds_connection *conn, __be32 saddr, __be32 daddr, | 287 | void rds_recv_incoming(struct rds_connection *conn, struct in6_addr *saddr, |
288 | struct in6_addr *daddr, | ||
288 | struct rds_incoming *inc, gfp_t gfp) | 289 | struct rds_incoming *inc, gfp_t gfp) |
289 | { | 290 | { |
290 | struct rds_sock *rs = NULL; | 291 | struct rds_sock *rs = NULL; |
@@ -339,7 +340,8 @@ void rds_recv_incoming(struct rds_connection *conn, __be32 saddr, __be32 daddr, | |||
339 | 340 | ||
340 | if (rds_sysctl_ping_enable && inc->i_hdr.h_dport == 0) { | 341 | if (rds_sysctl_ping_enable && inc->i_hdr.h_dport == 0) { |
341 | if (inc->i_hdr.h_sport == 0) { | 342 | if (inc->i_hdr.h_sport == 0) { |
342 | rdsdebug("ignore ping with 0 sport from 0x%x\n", saddr); | 343 | rdsdebug("ignore ping with 0 sport from %pI6c\n", |
344 | saddr); | ||
343 | goto out; | 345 | goto out; |
344 | } | 346 | } |
345 | rds_stats_inc(s_recv_ping); | 347 | rds_stats_inc(s_recv_ping); |
@@ -362,7 +364,7 @@ void rds_recv_incoming(struct rds_connection *conn, __be32 saddr, __be32 daddr, | |||
362 | goto out; | 364 | goto out; |
363 | } | 365 | } |
364 | 366 | ||
365 | rs = rds_find_bound(daddr, inc->i_hdr.h_dport); | 367 | rs = rds_find_bound(daddr, inc->i_hdr.h_dport, conn->c_dev_if); |
366 | if (!rs) { | 368 | if (!rs) { |
367 | rds_stats_inc(s_recv_drop_no_sock); | 369 | rds_stats_inc(s_recv_drop_no_sock); |
368 | goto out; | 370 | goto out; |
@@ -625,6 +627,7 @@ int rds_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, | |||
625 | struct rds_sock *rs = rds_sk_to_rs(sk); | 627 | struct rds_sock *rs = rds_sk_to_rs(sk); |
626 | long timeo; | 628 | long timeo; |
627 | int ret = 0, nonblock = msg_flags & MSG_DONTWAIT; | 629 | int ret = 0, nonblock = msg_flags & MSG_DONTWAIT; |
630 | DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name); | ||
628 | DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name); | 631 | DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name); |
629 | struct rds_incoming *inc = NULL; | 632 | struct rds_incoming *inc = NULL; |
630 | 633 | ||
@@ -673,7 +676,7 @@ int rds_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, | |||
673 | break; | 676 | break; |
674 | } | 677 | } |
675 | 678 | ||
676 | rdsdebug("copying inc %p from %pI4:%u to user\n", inc, | 679 | rdsdebug("copying inc %p from %pI6c:%u to user\n", inc, |
677 | &inc->i_conn->c_faddr, | 680 | &inc->i_conn->c_faddr, |
678 | ntohs(inc->i_hdr.h_sport)); | 681 | ntohs(inc->i_hdr.h_sport)); |
679 | ret = inc->i_conn->c_trans->inc_copy_to_user(inc, &msg->msg_iter); | 682 | ret = inc->i_conn->c_trans->inc_copy_to_user(inc, &msg->msg_iter); |
@@ -707,12 +710,26 @@ int rds_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, | |||
707 | 710 | ||
708 | rds_stats_inc(s_recv_delivered); | 711 | rds_stats_inc(s_recv_delivered); |
709 | 712 | ||
710 | if (sin) { | 713 | if (msg->msg_name) { |
711 | sin->sin_family = AF_INET; | 714 | if (ipv6_addr_v4mapped(&inc->i_saddr)) { |
712 | sin->sin_port = inc->i_hdr.h_sport; | 715 | sin = (struct sockaddr_in *)msg->msg_name; |
713 | sin->sin_addr.s_addr = inc->i_saddr; | 716 | |
714 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | 717 | sin->sin_family = AF_INET; |
715 | msg->msg_namelen = sizeof(*sin); | 718 | sin->sin_port = inc->i_hdr.h_sport; |
719 | sin->sin_addr.s_addr = | ||
720 | inc->i_saddr.s6_addr32[3]; | ||
721 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
722 | msg->msg_namelen = sizeof(*sin); | ||
723 | } else { | ||
724 | sin6 = (struct sockaddr_in6 *)msg->msg_name; | ||
725 | |||
726 | sin6->sin6_family = AF_INET6; | ||
727 | sin6->sin6_port = inc->i_hdr.h_sport; | ||
728 | sin6->sin6_addr = inc->i_saddr; | ||
729 | sin6->sin6_flowinfo = 0; | ||
730 | sin6->sin6_scope_id = rs->rs_bound_scope_id; | ||
731 | msg->msg_namelen = sizeof(*sin6); | ||
732 | } | ||
716 | } | 733 | } |
717 | break; | 734 | break; |
718 | } | 735 | } |