summaryrefslogtreecommitdiffstats
path: root/net/rds/recv.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/rds/recv.c')
-rw-r--r--net/rds/recv.c51
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
43void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn, 43void 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,
59EXPORT_SYMBOL_GPL(rds_inc_init); 59EXPORT_SYMBOL_GPL(rds_inc_init);
60 60
61void rds_inc_path_init(struct rds_incoming *inc, struct rds_conn_path *cp, 61void 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 */
287void rds_recv_incoming(struct rds_connection *conn, __be32 saddr, __be32 daddr, 287void 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 }