aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/rds.h69
-rw-r--r--net/rds/connection.c101
-rw-r--r--net/rds/ib.c52
-rw-r--r--net/rds/ib_mr.h2
-rw-r--r--net/rds/ib_rdma.c11
-rw-r--r--net/rds/recv.c25
-rw-r--r--net/rds/tcp.c44
7 files changed, 293 insertions, 11 deletions
diff --git a/include/uapi/linux/rds.h b/include/uapi/linux/rds.h
index 20c6bd0b0007..dc520e1a4123 100644
--- a/include/uapi/linux/rds.h
+++ b/include/uapi/linux/rds.h
@@ -1,6 +1,6 @@
1/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR Linux-OpenIB) */ 1/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR Linux-OpenIB) */
2/* 2/*
3 * Copyright (c) 2008 Oracle. All rights reserved. 3 * Copyright (c) 2008, 2018 Oracle and/or its affiliates. All rights reserved.
4 * 4 *
5 * This software is available to you under a choice of one of two 5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU 6 * licenses. You may choose to be licensed under the terms of the GNU
@@ -118,7 +118,17 @@
118#define RDS_INFO_IB_CONNECTIONS 10008 118#define RDS_INFO_IB_CONNECTIONS 10008
119#define RDS_INFO_CONNECTION_STATS 10009 119#define RDS_INFO_CONNECTION_STATS 10009
120#define RDS_INFO_IWARP_CONNECTIONS 10010 120#define RDS_INFO_IWARP_CONNECTIONS 10010
121#define RDS_INFO_LAST 10010 121
122/* PF_RDS6 options */
123#define RDS6_INFO_CONNECTIONS 10011
124#define RDS6_INFO_SEND_MESSAGES 10012
125#define RDS6_INFO_RETRANS_MESSAGES 10013
126#define RDS6_INFO_RECV_MESSAGES 10014
127#define RDS6_INFO_SOCKETS 10015
128#define RDS6_INFO_TCP_SOCKETS 10016
129#define RDS6_INFO_IB_CONNECTIONS 10017
130
131#define RDS_INFO_LAST 10017
122 132
123struct rds_info_counter { 133struct rds_info_counter {
124 __u8 name[32]; 134 __u8 name[32];
@@ -140,6 +150,15 @@ struct rds_info_connection {
140 __u8 flags; 150 __u8 flags;
141} __attribute__((packed)); 151} __attribute__((packed));
142 152
153struct rds6_info_connection {
154 __u64 next_tx_seq;
155 __u64 next_rx_seq;
156 struct in6_addr laddr;
157 struct in6_addr faddr;
158 __u8 transport[TRANSNAMSIZ]; /* null term ascii */
159 __u8 flags;
160} __attribute__((packed));
161
143#define RDS_INFO_MESSAGE_FLAG_ACK 0x01 162#define RDS_INFO_MESSAGE_FLAG_ACK 0x01
144#define RDS_INFO_MESSAGE_FLAG_FAST_ACK 0x02 163#define RDS_INFO_MESSAGE_FLAG_FAST_ACK 0x02
145 164
@@ -153,6 +172,17 @@ struct rds_info_message {
153 __u8 flags; 172 __u8 flags;
154} __attribute__((packed)); 173} __attribute__((packed));
155 174
175struct rds6_info_message {
176 __u64 seq;
177 __u32 len;
178 struct in6_addr laddr;
179 struct in6_addr faddr;
180 __be16 lport;
181 __be16 fport;
182 __u8 flags;
183 __u8 tos;
184} __attribute__((packed));
185
156struct rds_info_socket { 186struct rds_info_socket {
157 __u32 sndbuf; 187 __u32 sndbuf;
158 __be32 bound_addr; 188 __be32 bound_addr;
@@ -163,6 +193,16 @@ struct rds_info_socket {
163 __u64 inum; 193 __u64 inum;
164} __attribute__((packed)); 194} __attribute__((packed));
165 195
196struct rds6_info_socket {
197 __u32 sndbuf;
198 struct in6_addr bound_addr;
199 struct in6_addr connected_addr;
200 __be16 bound_port;
201 __be16 connected_port;
202 __u32 rcvbuf;
203 __u64 inum;
204} __attribute__((packed));
205
166struct rds_info_tcp_socket { 206struct rds_info_tcp_socket {
167 __be32 local_addr; 207 __be32 local_addr;
168 __be16 local_port; 208 __be16 local_port;
@@ -175,6 +215,18 @@ struct rds_info_tcp_socket {
175 __u32 last_seen_una; 215 __u32 last_seen_una;
176} __attribute__((packed)); 216} __attribute__((packed));
177 217
218struct rds6_info_tcp_socket {
219 struct in6_addr local_addr;
220 __be16 local_port;
221 struct in6_addr peer_addr;
222 __be16 peer_port;
223 __u64 hdr_rem;
224 __u64 data_rem;
225 __u32 last_sent_nxt;
226 __u32 last_expected_una;
227 __u32 last_seen_una;
228} __attribute__((packed));
229
178#define RDS_IB_GID_LEN 16 230#define RDS_IB_GID_LEN 16
179struct rds_info_rdma_connection { 231struct rds_info_rdma_connection {
180 __be32 src_addr; 232 __be32 src_addr;
@@ -189,6 +241,19 @@ struct rds_info_rdma_connection {
189 __u32 rdma_mr_size; 241 __u32 rdma_mr_size;
190}; 242};
191 243
244struct rds6_info_rdma_connection {
245 struct in6_addr src_addr;
246 struct in6_addr dst_addr;
247 __u8 src_gid[RDS_IB_GID_LEN];
248 __u8 dst_gid[RDS_IB_GID_LEN];
249
250 __u32 max_send_wr;
251 __u32 max_recv_wr;
252 __u32 max_send_sge;
253 __u32 rdma_mr_max;
254 __u32 rdma_mr_size;
255};
256
192/* RDS message Receive Path Latency points */ 257/* RDS message Receive Path Latency points */
193enum rds_message_rxpath_latency { 258enum rds_message_rxpath_latency {
194 RDS_MSG_RX_HDR_TO_DGRAM_START = 0, 259 RDS_MSG_RX_HDR_TO_DGRAM_START = 0,
diff --git a/net/rds/connection.c b/net/rds/connection.c
index 5c9ceed55dae..051e35c1e7c6 100644
--- a/net/rds/connection.c
+++ b/net/rds/connection.c
@@ -498,16 +498,19 @@ EXPORT_SYMBOL_GPL(rds_conn_destroy);
498 498
499static void __rds_inc_msg_cp(struct rds_incoming *inc, 499static void __rds_inc_msg_cp(struct rds_incoming *inc,
500 struct rds_info_iterator *iter, 500 struct rds_info_iterator *iter,
501 void *saddr, void *daddr, int flip) 501 void *saddr, void *daddr, int flip, bool isv6)
502{ 502{
503 rds_inc_info_copy(inc, iter, *(__be32 *)saddr, 503 if (isv6)
504 *(__be32 *)daddr, flip); 504 rds6_inc_info_copy(inc, iter, saddr, daddr, flip);
505 else
506 rds_inc_info_copy(inc, iter, *(__be32 *)saddr,
507 *(__be32 *)daddr, flip);
505} 508}
506 509
507static void rds_conn_message_info_cmn(struct socket *sock, unsigned int len, 510static void rds_conn_message_info_cmn(struct socket *sock, unsigned int len,
508 struct rds_info_iterator *iter, 511 struct rds_info_iterator *iter,
509 struct rds_info_lengths *lens, 512 struct rds_info_lengths *lens,
510 int want_send) 513 int want_send, bool isv6)
511{ 514{
512 struct hlist_head *head; 515 struct hlist_head *head;
513 struct list_head *list; 516 struct list_head *list;
@@ -518,7 +521,10 @@ static void rds_conn_message_info_cmn(struct socket *sock, unsigned int len,
518 size_t i; 521 size_t i;
519 int j; 522 int j;
520 523
521 len /= sizeof(struct rds_info_message); 524 if (isv6)
525 len /= sizeof(struct rds6_info_message);
526 else
527 len /= sizeof(struct rds_info_message);
522 528
523 rcu_read_lock(); 529 rcu_read_lock();
524 530
@@ -528,6 +534,9 @@ static void rds_conn_message_info_cmn(struct socket *sock, unsigned int len,
528 struct rds_conn_path *cp; 534 struct rds_conn_path *cp;
529 int npaths; 535 int npaths;
530 536
537 if (!isv6 && conn->c_isv6)
538 continue;
539
531 npaths = (conn->c_trans->t_mp_capable ? 540 npaths = (conn->c_trans->t_mp_capable ?
532 RDS_MPATH_WORKERS : 1); 541 RDS_MPATH_WORKERS : 1);
533 542
@@ -548,7 +557,7 @@ static void rds_conn_message_info_cmn(struct socket *sock, unsigned int len,
548 iter, 557 iter,
549 &conn->c_laddr, 558 &conn->c_laddr,
550 &conn->c_faddr, 559 &conn->c_faddr,
551 0); 560 0, isv6);
552 } 561 }
553 562
554 spin_unlock_irqrestore(&cp->cp_lock, flags); 563 spin_unlock_irqrestore(&cp->cp_lock, flags);
@@ -558,7 +567,10 @@ static void rds_conn_message_info_cmn(struct socket *sock, unsigned int len,
558 rcu_read_unlock(); 567 rcu_read_unlock();
559 568
560 lens->nr = total; 569 lens->nr = total;
561 lens->each = sizeof(struct rds_info_message); 570 if (isv6)
571 lens->each = sizeof(struct rds6_info_message);
572 else
573 lens->each = sizeof(struct rds_info_message);
562} 574}
563 575
564static void rds_conn_message_info(struct socket *sock, unsigned int len, 576static void rds_conn_message_info(struct socket *sock, unsigned int len,
@@ -566,7 +578,15 @@ static void rds_conn_message_info(struct socket *sock, unsigned int len,
566 struct rds_info_lengths *lens, 578 struct rds_info_lengths *lens,
567 int want_send) 579 int want_send)
568{ 580{
569 rds_conn_message_info_cmn(sock, len, iter, lens, want_send); 581 rds_conn_message_info_cmn(sock, len, iter, lens, want_send, false);
582}
583
584static void rds6_conn_message_info(struct socket *sock, unsigned int len,
585 struct rds_info_iterator *iter,
586 struct rds_info_lengths *lens,
587 int want_send)
588{
589 rds_conn_message_info_cmn(sock, len, iter, lens, want_send, true);
570} 590}
571 591
572static void rds_conn_message_info_send(struct socket *sock, unsigned int len, 592static void rds_conn_message_info_send(struct socket *sock, unsigned int len,
@@ -576,6 +596,13 @@ static void rds_conn_message_info_send(struct socket *sock, unsigned int len,
576 rds_conn_message_info(sock, len, iter, lens, 1); 596 rds_conn_message_info(sock, len, iter, lens, 1);
577} 597}
578 598
599static void rds6_conn_message_info_send(struct socket *sock, unsigned int len,
600 struct rds_info_iterator *iter,
601 struct rds_info_lengths *lens)
602{
603 rds6_conn_message_info(sock, len, iter, lens, 1);
604}
605
579static void rds_conn_message_info_retrans(struct socket *sock, 606static void rds_conn_message_info_retrans(struct socket *sock,
580 unsigned int len, 607 unsigned int len,
581 struct rds_info_iterator *iter, 608 struct rds_info_iterator *iter,
@@ -584,6 +611,14 @@ static void rds_conn_message_info_retrans(struct socket *sock,
584 rds_conn_message_info(sock, len, iter, lens, 0); 611 rds_conn_message_info(sock, len, iter, lens, 0);
585} 612}
586 613
614static void rds6_conn_message_info_retrans(struct socket *sock,
615 unsigned int len,
616 struct rds_info_iterator *iter,
617 struct rds_info_lengths *lens)
618{
619 rds6_conn_message_info(sock, len, iter, lens, 0);
620}
621
587void rds_for_each_conn_info(struct socket *sock, unsigned int len, 622void rds_for_each_conn_info(struct socket *sock, unsigned int len,
588 struct rds_info_iterator *iter, 623 struct rds_info_iterator *iter,
589 struct rds_info_lengths *lens, 624 struct rds_info_lengths *lens,
@@ -699,6 +734,34 @@ static int rds_conn_info_visitor(struct rds_conn_path *cp, void *buffer)
699 return 1; 734 return 1;
700} 735}
701 736
737static int rds6_conn_info_visitor(struct rds_conn_path *cp, void *buffer)
738{
739 struct rds6_info_connection *cinfo6 = buffer;
740 struct rds_connection *conn = cp->cp_conn;
741
742 cinfo6->next_tx_seq = cp->cp_next_tx_seq;
743 cinfo6->next_rx_seq = cp->cp_next_rx_seq;
744 cinfo6->laddr = conn->c_laddr;
745 cinfo6->faddr = conn->c_faddr;
746 strncpy(cinfo6->transport, conn->c_trans->t_name,
747 sizeof(cinfo6->transport));
748 cinfo6->flags = 0;
749
750 rds_conn_info_set(cinfo6->flags, test_bit(RDS_IN_XMIT, &cp->cp_flags),
751 SENDING);
752 /* XXX Future: return the state rather than these funky bits */
753 rds_conn_info_set(cinfo6->flags,
754 atomic_read(&cp->cp_state) == RDS_CONN_CONNECTING,
755 CONNECTING);
756 rds_conn_info_set(cinfo6->flags,
757 atomic_read(&cp->cp_state) == RDS_CONN_UP,
758 CONNECTED);
759 /* Just return 1 as there is no error case. This is a helper function
760 * for rds_walk_conn_path_info() and it wants a return value.
761 */
762 return 1;
763}
764
702static void rds_conn_info(struct socket *sock, unsigned int len, 765static void rds_conn_info(struct socket *sock, unsigned int len,
703 struct rds_info_iterator *iter, 766 struct rds_info_iterator *iter,
704 struct rds_info_lengths *lens) 767 struct rds_info_lengths *lens)
@@ -711,6 +774,18 @@ static void rds_conn_info(struct socket *sock, unsigned int len,
711 sizeof(struct rds_info_connection)); 774 sizeof(struct rds_info_connection));
712} 775}
713 776
777static void rds6_conn_info(struct socket *sock, unsigned int len,
778 struct rds_info_iterator *iter,
779 struct rds_info_lengths *lens)
780{
781 u64 buffer[(sizeof(struct rds6_info_connection) + 7) / 8];
782
783 rds_walk_conn_path_info(sock, len, iter, lens,
784 rds6_conn_info_visitor,
785 buffer,
786 sizeof(struct rds6_info_connection));
787}
788
714int rds_conn_init(void) 789int rds_conn_init(void)
715{ 790{
716 int ret; 791 int ret;
@@ -732,6 +807,11 @@ int rds_conn_init(void)
732 rds_conn_message_info_send); 807 rds_conn_message_info_send);
733 rds_info_register_func(RDS_INFO_RETRANS_MESSAGES, 808 rds_info_register_func(RDS_INFO_RETRANS_MESSAGES,
734 rds_conn_message_info_retrans); 809 rds_conn_message_info_retrans);
810 rds_info_register_func(RDS6_INFO_CONNECTIONS, rds6_conn_info);
811 rds_info_register_func(RDS6_INFO_SEND_MESSAGES,
812 rds6_conn_message_info_send);
813 rds_info_register_func(RDS6_INFO_RETRANS_MESSAGES,
814 rds6_conn_message_info_retrans);
735 815
736 return 0; 816 return 0;
737} 817}
@@ -750,6 +830,11 @@ void rds_conn_exit(void)
750 rds_conn_message_info_send); 830 rds_conn_message_info_send);
751 rds_info_deregister_func(RDS_INFO_RETRANS_MESSAGES, 831 rds_info_deregister_func(RDS_INFO_RETRANS_MESSAGES,
752 rds_conn_message_info_retrans); 832 rds_conn_message_info_retrans);
833 rds_info_deregister_func(RDS6_INFO_CONNECTIONS, rds6_conn_info);
834 rds_info_deregister_func(RDS6_INFO_SEND_MESSAGES,
835 rds6_conn_message_info_send);
836 rds_info_deregister_func(RDS6_INFO_RETRANS_MESSAGES,
837 rds6_conn_message_info_retrans);
753} 838}
754 839
755/* 840/*
diff --git a/net/rds/ib.c b/net/rds/ib.c
index 756225c5540f..63d95ea7cdff 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -321,6 +321,43 @@ static int rds_ib_conn_info_visitor(struct rds_connection *conn,
321 return 1; 321 return 1;
322} 322}
323 323
324/* IPv6 version of rds_ib_conn_info_visitor(). */
325static int rds6_ib_conn_info_visitor(struct rds_connection *conn,
326 void *buffer)
327{
328 struct rds6_info_rdma_connection *iinfo6 = buffer;
329 struct rds_ib_connection *ic;
330
331 /* We will only ever look at IB transports */
332 if (conn->c_trans != &rds_ib_transport)
333 return 0;
334
335 iinfo6->src_addr = conn->c_laddr;
336 iinfo6->dst_addr = conn->c_faddr;
337
338 memset(&iinfo6->src_gid, 0, sizeof(iinfo6->src_gid));
339 memset(&iinfo6->dst_gid, 0, sizeof(iinfo6->dst_gid));
340
341 if (rds_conn_state(conn) == RDS_CONN_UP) {
342 struct rds_ib_device *rds_ibdev;
343 struct rdma_dev_addr *dev_addr;
344
345 ic = conn->c_transport_data;
346 dev_addr = &ic->i_cm_id->route.addr.dev_addr;
347 rdma_addr_get_sgid(dev_addr,
348 (union ib_gid *)&iinfo6->src_gid);
349 rdma_addr_get_dgid(dev_addr,
350 (union ib_gid *)&iinfo6->dst_gid);
351
352 rds_ibdev = ic->rds_ibdev;
353 iinfo6->max_send_wr = ic->i_send_ring.w_nr;
354 iinfo6->max_recv_wr = ic->i_recv_ring.w_nr;
355 iinfo6->max_send_sge = rds_ibdev->max_sge;
356 rds6_ib_get_mr_info(rds_ibdev, iinfo6);
357 }
358 return 1;
359}
360
324static void rds_ib_ic_info(struct socket *sock, unsigned int len, 361static void rds_ib_ic_info(struct socket *sock, unsigned int len,
325 struct rds_info_iterator *iter, 362 struct rds_info_iterator *iter,
326 struct rds_info_lengths *lens) 363 struct rds_info_lengths *lens)
@@ -333,6 +370,19 @@ static void rds_ib_ic_info(struct socket *sock, unsigned int len,
333 sizeof(struct rds_info_rdma_connection)); 370 sizeof(struct rds_info_rdma_connection));
334} 371}
335 372
373/* IPv6 version of rds_ib_ic_info(). */
374static void rds6_ib_ic_info(struct socket *sock, unsigned int len,
375 struct rds_info_iterator *iter,
376 struct rds_info_lengths *lens)
377{
378 u64 buffer[(sizeof(struct rds6_info_rdma_connection) + 7) / 8];
379
380 rds_for_each_conn_info(sock, len, iter, lens,
381 rds6_ib_conn_info_visitor,
382 buffer,
383 sizeof(struct rds6_info_rdma_connection));
384}
385
336/* 386/*
337 * Early RDS/IB was built to only bind to an address if there is an IPoIB 387 * Early RDS/IB was built to only bind to an address if there is an IPoIB
338 * device with that address set. 388 * device with that address set.
@@ -441,6 +491,7 @@ void rds_ib_exit(void)
441 rds_ib_set_unloading(); 491 rds_ib_set_unloading();
442 synchronize_rcu(); 492 synchronize_rcu();
443 rds_info_deregister_func(RDS_INFO_IB_CONNECTIONS, rds_ib_ic_info); 493 rds_info_deregister_func(RDS_INFO_IB_CONNECTIONS, rds_ib_ic_info);
494 rds_info_deregister_func(RDS6_INFO_IB_CONNECTIONS, rds6_ib_ic_info);
444 rds_ib_unregister_client(); 495 rds_ib_unregister_client();
445 rds_ib_destroy_nodev_conns(); 496 rds_ib_destroy_nodev_conns();
446 rds_ib_sysctl_exit(); 497 rds_ib_sysctl_exit();
@@ -502,6 +553,7 @@ int rds_ib_init(void)
502 rds_trans_register(&rds_ib_transport); 553 rds_trans_register(&rds_ib_transport);
503 554
504 rds_info_register_func(RDS_INFO_IB_CONNECTIONS, rds_ib_ic_info); 555 rds_info_register_func(RDS_INFO_IB_CONNECTIONS, rds_ib_ic_info);
556 rds_info_register_func(RDS6_INFO_IB_CONNECTIONS, rds6_ib_ic_info);
505 557
506 goto out; 558 goto out;
507 559
diff --git a/net/rds/ib_mr.h b/net/rds/ib_mr.h
index 0ea4ab017a8c..f440ace584c8 100644
--- a/net/rds/ib_mr.h
+++ b/net/rds/ib_mr.h
@@ -113,6 +113,8 @@ struct rds_ib_mr_pool *rds_ib_create_mr_pool(struct rds_ib_device *rds_dev,
113 int npages); 113 int npages);
114void rds_ib_get_mr_info(struct rds_ib_device *rds_ibdev, 114void rds_ib_get_mr_info(struct rds_ib_device *rds_ibdev,
115 struct rds_info_rdma_connection *iinfo); 115 struct rds_info_rdma_connection *iinfo);
116void rds6_ib_get_mr_info(struct rds_ib_device *rds_ibdev,
117 struct rds6_info_rdma_connection *iinfo6);
116void rds_ib_destroy_mr_pool(struct rds_ib_mr_pool *); 118void rds_ib_destroy_mr_pool(struct rds_ib_mr_pool *);
117void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents, 119void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents,
118 struct rds_sock *rs, u32 *key_ret); 120 struct rds_sock *rs, u32 *key_ret);
diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c
index 0ec9df043dd0..e3c8bbbdb43f 100644
--- a/net/rds/ib_rdma.c
+++ b/net/rds/ib_rdma.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2006, 2017 Oracle and/or its affiliates. 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
@@ -180,6 +180,15 @@ void rds_ib_get_mr_info(struct rds_ib_device *rds_ibdev, struct rds_info_rdma_co
180 iinfo->rdma_mr_size = pool_1m->fmr_attr.max_pages; 180 iinfo->rdma_mr_size = pool_1m->fmr_attr.max_pages;
181} 181}
182 182
183void rds6_ib_get_mr_info(struct rds_ib_device *rds_ibdev,
184 struct rds6_info_rdma_connection *iinfo6)
185{
186 struct rds_ib_mr_pool *pool_1m = rds_ibdev->mr_1m_pool;
187
188 iinfo6->rdma_mr_max = pool_1m->max_items;
189 iinfo6->rdma_mr_size = pool_1m->fmr_attr.max_pages;
190}
191
183struct rds_ib_mr *rds_ib_reuse_mr(struct rds_ib_mr_pool *pool) 192struct rds_ib_mr *rds_ib_reuse_mr(struct rds_ib_mr_pool *pool)
184{ 193{
185 struct rds_ib_mr *ibmr = NULL; 194 struct rds_ib_mr *ibmr = NULL;
diff --git a/net/rds/recv.c b/net/rds/recv.c
index 1402c21210b1..03cd8df54c26 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -792,3 +792,28 @@ void rds_inc_info_copy(struct rds_incoming *inc,
792 792
793 rds_info_copy(iter, &minfo, sizeof(minfo)); 793 rds_info_copy(iter, &minfo, sizeof(minfo));
794} 794}
795
796void rds6_inc_info_copy(struct rds_incoming *inc,
797 struct rds_info_iterator *iter,
798 struct in6_addr *saddr, struct in6_addr *daddr,
799 int flip)
800{
801 struct rds6_info_message minfo6;
802
803 minfo6.seq = be64_to_cpu(inc->i_hdr.h_sequence);
804 minfo6.len = be32_to_cpu(inc->i_hdr.h_len);
805
806 if (flip) {
807 minfo6.laddr = *daddr;
808 minfo6.faddr = *saddr;
809 minfo6.lport = inc->i_hdr.h_dport;
810 minfo6.fport = inc->i_hdr.h_sport;
811 } else {
812 minfo6.laddr = *saddr;
813 minfo6.faddr = *daddr;
814 minfo6.lport = inc->i_hdr.h_sport;
815 minfo6.fport = inc->i_hdr.h_dport;
816 }
817
818 rds_info_copy(iter, &minfo6, sizeof(minfo6));
819}
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index 890d0e1d8908..7028d6e51947 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -273,6 +273,48 @@ out:
273 spin_unlock_irqrestore(&rds_tcp_tc_list_lock, flags); 273 spin_unlock_irqrestore(&rds_tcp_tc_list_lock, flags);
274} 274}
275 275
276/* Handle RDS6_INFO_TCP_SOCKETS socket option. It returns both IPv4 and
277 * IPv6 connections. IPv4 connection address is returned in an IPv4 mapped
278 * address.
279 */
280static void rds6_tcp_tc_info(struct socket *sock, unsigned int len,
281 struct rds_info_iterator *iter,
282 struct rds_info_lengths *lens)
283{
284 struct rds6_info_tcp_socket tsinfo6;
285 struct rds_tcp_connection *tc;
286 unsigned long flags;
287
288 spin_lock_irqsave(&rds_tcp_tc_list_lock, flags);
289
290 if (len / sizeof(tsinfo6) < rds6_tcp_tc_count)
291 goto out;
292
293 list_for_each_entry(tc, &rds_tcp_tc_list, t_list_item) {
294 struct sock *sk = tc->t_sock->sk;
295 struct inet_sock *inet = inet_sk(sk);
296
297 tsinfo6.local_addr = sk->sk_v6_rcv_saddr;
298 tsinfo6.local_port = inet->inet_sport;
299 tsinfo6.peer_addr = sk->sk_v6_daddr;
300 tsinfo6.peer_port = inet->inet_dport;
301
302 tsinfo6.hdr_rem = tc->t_tinc_hdr_rem;
303 tsinfo6.data_rem = tc->t_tinc_data_rem;
304 tsinfo6.last_sent_nxt = tc->t_last_sent_nxt;
305 tsinfo6.last_expected_una = tc->t_last_expected_una;
306 tsinfo6.last_seen_una = tc->t_last_seen_una;
307
308 rds_info_copy(iter, &tsinfo6, sizeof(tsinfo6));
309 }
310
311out:
312 lens->nr = rds6_tcp_tc_count;
313 lens->each = sizeof(tsinfo6);
314
315 spin_unlock_irqrestore(&rds_tcp_tc_list_lock, flags);
316}
317
276static int rds_tcp_laddr_check(struct net *net, const struct in6_addr *addr, 318static int rds_tcp_laddr_check(struct net *net, const struct in6_addr *addr,
277 __u32 scope_id) 319 __u32 scope_id)
278{ 320{
@@ -628,6 +670,7 @@ static void rds_tcp_exit(void)
628 rds_tcp_set_unloading(); 670 rds_tcp_set_unloading();
629 synchronize_rcu(); 671 synchronize_rcu();
630 rds_info_deregister_func(RDS_INFO_TCP_SOCKETS, rds_tcp_tc_info); 672 rds_info_deregister_func(RDS_INFO_TCP_SOCKETS, rds_tcp_tc_info);
673 rds_info_deregister_func(RDS6_INFO_TCP_SOCKETS, rds6_tcp_tc_info);
631 unregister_pernet_device(&rds_tcp_net_ops); 674 unregister_pernet_device(&rds_tcp_net_ops);
632 rds_tcp_destroy_conns(); 675 rds_tcp_destroy_conns();
633 rds_trans_unregister(&rds_tcp_transport); 676 rds_trans_unregister(&rds_tcp_transport);
@@ -659,6 +702,7 @@ static int rds_tcp_init(void)
659 rds_trans_register(&rds_tcp_transport); 702 rds_trans_register(&rds_tcp_transport);
660 703
661 rds_info_register_func(RDS_INFO_TCP_SOCKETS, rds_tcp_tc_info); 704 rds_info_register_func(RDS_INFO_TCP_SOCKETS, rds_tcp_tc_info);
705 rds_info_register_func(RDS6_INFO_TCP_SOCKETS, rds6_tcp_tc_info);
662 706
663 goto out; 707 goto out;
664out_recv: 708out_recv: