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