1 /*
2 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3 */
4
5 /*
6 * This file contains code imported from the OFED rds source file stats.c
7 * Oracle elects to have and use the contents of stats.c under and governed
8 * by the OpenIB.org BSD license (see below for full license text). However,
9 * the following notice accompanied the original version of this file:
10 */
11
12 /*
13 * Copyright (c) 2006 Oracle. All rights reserved.
14 *
15 * This software is available to you under a choice of one of two
16 * licenses. You may choose to be licensed under the terms of the GNU
17 * General Public License (GPL) Version 2, available from the file
18 * COPYING in the main directory of this source tree, or the
19 * OpenIB.org BSD license below:
20 *
21 * Redistribution and use in source and binary forms, with or
22 * without modification, are permitted provided that the following
23 * conditions are met:
24 *
25 * - Redistributions of source code must retain the above
26 * copyright notice, this list of conditions and the following
27 * disclaimer.
28 *
29 * - Redistributions in binary form must reproduce the above
30 * copyright notice, this list of conditions and the following
31 * disclaimer in the documentation and/or other materials
32 * provided with the distribution.
33 *
34 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
35 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
37 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
38 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
39 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
40 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
41 * SOFTWARE.
42 *
43 */
44 #include <sys/rds.h>
45
46 #include <sys/ib/clients/rdsv3/rdsv3.h>
47
48 struct rdsv3_statistics *rdsv3_stats = NULL;
49 uint_t nr_cpus;
50
51 static char *rdsv3_stat_names[] = {
52 "conn_reset",
53 "recv_drop_bad_checksum",
54 "recv_drop_old_seq",
55 "recv_drop_no_sock",
56 "recv_drop_dead_sock",
57 "recv_deliver_raced",
58 "recv_delivered",
59 "recv_queued",
60 "recv_immediate_retry",
61 "recv_delayed_retry",
62 "recv_ack_required",
63 "recv_rdma_bytes",
64 "recv_ping",
65 "send_queue_empty",
66 "send_queue_full",
67 "send_sem_contention",
68 "send_sem_queue_raced",
69 "send_immediate_retry",
70 "send_delayed_retry",
71 "send_drop_acked",
72 "send_ack_required",
73 "send_queued",
74 "send_rdma",
75 "send_rdma_bytes",
76 "send_pong",
77 "page_remainder_hit",
78 "page_remainder_miss",
79 "copy_to_user",
80 "copy_from_user",
81 "cong_update_queued",
82 "cong_update_received",
83 "cong_send_error",
84 "cong_send_blocked",
85 };
86
87 void
rdsv3_stats_info_copy(struct rdsv3_info_iterator * iter,uint64_t * values,char ** names,size_t nr)88 rdsv3_stats_info_copy(struct rdsv3_info_iterator *iter,
89 uint64_t *values, char **names, size_t nr)
90 {
91 struct rds_info_counter ctr;
92 size_t i;
93
94 for (i = 0; i < nr; i++) {
95 ASSERT(!(strlen(names[i]) >= sizeof (ctr.name)));
96 (void) strncpy((char *)ctr.name, names[i],
97 sizeof (ctr.name) - 1);
98 ctr.value = values[i];
99
100 rdsv3_info_copy(iter, &ctr, sizeof (ctr));
101 }
102 }
103
104 /*
105 * This gives global counters across all the transports. The strings
106 * are copied in so that the tool doesn't need knowledge of the specific
107 * stats that we're exporting. Some are pretty implementation dependent
108 * and may change over time. That doesn't stop them from being useful.
109 *
110 * This is the only function in the chain that knows about the byte granular
111 * length in userspace. It converts it to number of stat entries that the
112 * rest of the functions operate in.
113 */
114 /* ARGSUSED */
115 static void
rdsv3_stats_info(struct rsock * sock,unsigned int len,struct rdsv3_info_iterator * iter,struct rdsv3_info_lengths * lens)116 rdsv3_stats_info(struct rsock *sock, unsigned int len,
117 struct rdsv3_info_iterator *iter,
118 struct rdsv3_info_lengths *lens)
119 {
120 struct rdsv3_statistics stats;
121 uint64_t *src;
122 uint64_t *sum;
123 size_t i;
124 int cpu;
125 unsigned int avail;
126
127 avail = len / sizeof (struct rds_info_counter);
128
129 if (avail < ARRAY_SIZE(rdsv3_stat_names)) {
130 avail = 0;
131 goto trans;
132 }
133
134 bzero(&stats, sizeof (struct rdsv3_statistics));
135
136 for (cpu = 0; cpu < nr_cpus; cpu++) {
137 src = (uint64_t *)&(rdsv3_per_cpu(rdsv3_stats, cpu));
138 sum = (uint64_t *)&stats;
139 for (i = 0;
140 i < sizeof (struct rdsv3_statistics) / sizeof (uint64_t);
141 i++)
142 *(sum++) += *(src++);
143 }
144
145 rdsv3_stats_info_copy(iter, (uint64_t *)&stats, rdsv3_stat_names,
146 ARRAY_SIZE(rdsv3_stat_names));
147 avail -= ARRAY_SIZE(rdsv3_stat_names);
148
149 trans:
150 lens->each = sizeof (struct rds_info_counter);
151 lens->nr = rdsv3_trans_stats_info_copy(iter, avail) +
152 ARRAY_SIZE(rdsv3_stat_names);
153 }
154
155 void
rdsv3_stats_exit(void)156 rdsv3_stats_exit(void)
157 {
158 rdsv3_info_deregister_func(RDS_INFO_COUNTERS, rdsv3_stats_info);
159
160 ASSERT(rdsv3_stats);
161 kmem_free(rdsv3_stats,
162 nr_cpus * sizeof (struct rdsv3_statistics));
163 rdsv3_stats = NULL;
164 }
165
166 int
rdsv3_stats_init(void)167 rdsv3_stats_init(void)
168 {
169 /*
170 * Note the max number of cpus that this system can have at most.
171 */
172 nr_cpus = max_ncpus;
173 ASSERT(rdsv3_stats == NULL);
174 rdsv3_stats = kmem_zalloc(nr_cpus *
175 sizeof (struct rdsv3_statistics), KM_SLEEP);
176
177 rdsv3_info_register_func(RDS_INFO_COUNTERS, rdsv3_stats_info);
178 return (0);
179 }
180