diff options
| -rw-r--r-- | include/uapi/linux/tipc_config.h | 10 | ||||
| -rw-r--r-- | net/tipc/bcast.c | 43 | ||||
| -rw-r--r-- | net/tipc/bcast.h | 1 | ||||
| -rw-r--r-- | net/tipc/config.c | 4 | ||||
| -rw-r--r-- | net/tipc/link.c | 141 | ||||
| -rw-r--r-- | net/tipc/link.h | 3 | ||||
| -rw-r--r-- | net/tipc/netlink_compat.c | 205 |
7 files changed, 215 insertions, 192 deletions
diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h index f9226566c1b8..087b0ef82c07 100644 --- a/include/uapi/linux/tipc_config.h +++ b/include/uapi/linux/tipc_config.h | |||
| @@ -277,11 +277,21 @@ static inline int TLV_GET_LEN(struct tlv_desc *tlv) | |||
| 277 | return ntohs(tlv->tlv_len); | 277 | return ntohs(tlv->tlv_len); |
| 278 | } | 278 | } |
| 279 | 279 | ||
| 280 | static inline void TLV_SET_LEN(struct tlv_desc *tlv, __u16 len) | ||
| 281 | { | ||
| 282 | tlv->tlv_len = htons(len); | ||
| 283 | } | ||
| 284 | |||
| 280 | static inline int TLV_CHECK_TYPE(struct tlv_desc *tlv, __u16 type) | 285 | static inline int TLV_CHECK_TYPE(struct tlv_desc *tlv, __u16 type) |
| 281 | { | 286 | { |
| 282 | return (ntohs(tlv->tlv_type) == type); | 287 | return (ntohs(tlv->tlv_type) == type); |
| 283 | } | 288 | } |
| 284 | 289 | ||
| 290 | static inline void TLV_SET_TYPE(struct tlv_desc *tlv, __u16 type) | ||
| 291 | { | ||
| 292 | tlv->tlv_type = htons(type); | ||
| 293 | } | ||
| 294 | |||
| 285 | static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len) | 295 | static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len) |
| 286 | { | 296 | { |
| 287 | struct tlv_desc *tlv_ptr; | 297 | struct tlv_desc *tlv_ptr; |
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index e96fd6a6d5c2..3e41704832de 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
| @@ -860,49 +860,6 @@ msg_full: | |||
| 860 | return -EMSGSIZE; | 860 | return -EMSGSIZE; |
| 861 | } | 861 | } |
| 862 | 862 | ||
| 863 | int tipc_bclink_stats(struct net *net, char *buf, const u32 buf_size) | ||
| 864 | { | ||
| 865 | int ret; | ||
| 866 | struct tipc_stats *s; | ||
| 867 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
| 868 | struct tipc_link *bcl = tn->bcl; | ||
| 869 | |||
| 870 | if (!bcl) | ||
| 871 | return 0; | ||
| 872 | |||
| 873 | tipc_bclink_lock(net); | ||
| 874 | |||
| 875 | s = &bcl->stats; | ||
| 876 | |||
| 877 | ret = tipc_snprintf(buf, buf_size, "Link <%s>\n" | ||
| 878 | " Window:%u packets\n", | ||
| 879 | bcl->name, bcl->queue_limit[0]); | ||
| 880 | ret += tipc_snprintf(buf + ret, buf_size - ret, | ||
| 881 | " RX packets:%u fragments:%u/%u bundles:%u/%u\n", | ||
| 882 | s->recv_info, s->recv_fragments, | ||
| 883 | s->recv_fragmented, s->recv_bundles, | ||
| 884 | s->recv_bundled); | ||
| 885 | ret += tipc_snprintf(buf + ret, buf_size - ret, | ||
| 886 | " TX packets:%u fragments:%u/%u bundles:%u/%u\n", | ||
| 887 | s->sent_info, s->sent_fragments, | ||
| 888 | s->sent_fragmented, s->sent_bundles, | ||
| 889 | s->sent_bundled); | ||
| 890 | ret += tipc_snprintf(buf + ret, buf_size - ret, | ||
| 891 | " RX naks:%u defs:%u dups:%u\n", | ||
| 892 | s->recv_nacks, s->deferred_recv, s->duplicates); | ||
| 893 | ret += tipc_snprintf(buf + ret, buf_size - ret, | ||
| 894 | " TX naks:%u acks:%u dups:%u\n", | ||
| 895 | s->sent_nacks, s->sent_acks, s->retransmitted); | ||
| 896 | ret += tipc_snprintf(buf + ret, buf_size - ret, | ||
| 897 | " Congestion link:%u Send queue max:%u avg:%u\n", | ||
| 898 | s->link_congs, s->max_queue_sz, | ||
| 899 | s->queue_sz_counts ? | ||
| 900 | (s->accu_queue_sz / s->queue_sz_counts) : 0); | ||
| 901 | |||
| 902 | tipc_bclink_unlock(net); | ||
| 903 | return ret; | ||
| 904 | } | ||
| 905 | |||
| 906 | int tipc_bclink_reset_stats(struct net *net) | 863 | int tipc_bclink_reset_stats(struct net *net) |
| 907 | { | 864 | { |
| 908 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 865 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index a910c0b9f249..43f397fbac55 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h | |||
| @@ -127,7 +127,6 @@ u32 tipc_bclink_get_last_sent(struct net *net); | |||
| 127 | u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr); | 127 | u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr); |
| 128 | void tipc_bclink_update_link_state(struct tipc_node *node, | 128 | void tipc_bclink_update_link_state(struct tipc_node *node, |
| 129 | u32 last_sent); | 129 | u32 last_sent); |
| 130 | int tipc_bclink_stats(struct net *net, char *stats_buf, const u32 buf_size); | ||
| 131 | int tipc_bclink_reset_stats(struct net *net); | 130 | int tipc_bclink_reset_stats(struct net *net); |
| 132 | int tipc_bclink_set_queue_limits(struct net *net, u32 limit); | 131 | int tipc_bclink_set_queue_limits(struct net *net, u32 limit); |
| 133 | void tipc_bcbearer_sort(struct net *net, struct tipc_node_map *nm_ptr, | 132 | void tipc_bcbearer_sort(struct net *net, struct tipc_node_map *nm_ptr, |
diff --git a/net/tipc/config.c b/net/tipc/config.c index f8cd5e1b545f..67b76ee847f3 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c | |||
| @@ -213,10 +213,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, | |||
| 213 | rep_tlv_buf = tipc_node_get_links(net, req_tlv_area, | 213 | rep_tlv_buf = tipc_node_get_links(net, req_tlv_area, |
| 214 | req_tlv_space); | 214 | req_tlv_space); |
| 215 | break; | 215 | break; |
| 216 | case TIPC_CMD_SHOW_LINK_STATS: | ||
| 217 | rep_tlv_buf = tipc_link_cmd_show_stats(net, req_tlv_area, | ||
| 218 | req_tlv_space); | ||
| 219 | break; | ||
| 220 | case TIPC_CMD_RESET_LINK_STATS: | 216 | case TIPC_CMD_RESET_LINK_STATS: |
| 221 | rep_tlv_buf = tipc_link_cmd_reset_stats(net, req_tlv_area, | 217 | rep_tlv_buf = tipc_link_cmd_reset_stats(net, req_tlv_area, |
| 222 | req_tlv_space); | 218 | req_tlv_space); |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 466f28fcf215..2622fb99344a 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
| @@ -2146,147 +2146,6 @@ struct sk_buff *tipc_link_cmd_reset_stats(struct net *net, | |||
| 2146 | return tipc_cfg_reply_none(); | 2146 | return tipc_cfg_reply_none(); |
| 2147 | } | 2147 | } |
| 2148 | 2148 | ||
| 2149 | /** | ||
| 2150 | * percent - convert count to a percentage of total (rounding up or down) | ||
| 2151 | */ | ||
| 2152 | static u32 percent(u32 count, u32 total) | ||
| 2153 | { | ||
| 2154 | return (count * 100 + (total / 2)) / total; | ||
| 2155 | } | ||
| 2156 | |||
| 2157 | /** | ||
| 2158 | * tipc_link_stats - print link statistics | ||
| 2159 | * @net: the applicable net namespace | ||
| 2160 | * @name: link name | ||
| 2161 | * @buf: print buffer area | ||
| 2162 | * @buf_size: size of print buffer area | ||
| 2163 | * | ||
| 2164 | * Returns length of print buffer data string (or 0 if error) | ||
| 2165 | */ | ||
| 2166 | static int tipc_link_stats(struct net *net, const char *name, char *buf, | ||
| 2167 | const u32 buf_size) | ||
| 2168 | { | ||
| 2169 | struct tipc_link *l; | ||
| 2170 | struct tipc_stats *s; | ||
| 2171 | struct tipc_node *node; | ||
| 2172 | char *status; | ||
| 2173 | u32 profile_total = 0; | ||
| 2174 | unsigned int bearer_id; | ||
| 2175 | int ret; | ||
| 2176 | |||
| 2177 | if (!strcmp(name, tipc_bclink_name)) | ||
| 2178 | return tipc_bclink_stats(net, buf, buf_size); | ||
| 2179 | |||
| 2180 | node = tipc_link_find_owner(net, name, &bearer_id); | ||
| 2181 | if (!node) | ||
| 2182 | return 0; | ||
| 2183 | |||
| 2184 | tipc_node_lock(node); | ||
| 2185 | |||
| 2186 | l = node->links[bearer_id]; | ||
| 2187 | if (!l) { | ||
| 2188 | tipc_node_unlock(node); | ||
| 2189 | return 0; | ||
| 2190 | } | ||
| 2191 | |||
| 2192 | s = &l->stats; | ||
| 2193 | |||
| 2194 | if (tipc_link_is_active(l)) | ||
| 2195 | status = "ACTIVE"; | ||
| 2196 | else if (tipc_link_is_up(l)) | ||
| 2197 | status = "STANDBY"; | ||
| 2198 | else | ||
| 2199 | status = "DEFUNCT"; | ||
| 2200 | |||
| 2201 | ret = tipc_snprintf(buf, buf_size, "Link <%s>\n" | ||
| 2202 | " %s MTU:%u Priority:%u Tolerance:%u ms" | ||
| 2203 | " Window:%u packets\n", | ||
| 2204 | l->name, status, l->max_pkt, l->priority, | ||
| 2205 | l->tolerance, l->queue_limit[0]); | ||
| 2206 | |||
| 2207 | ret += tipc_snprintf(buf + ret, buf_size - ret, | ||
| 2208 | " RX packets:%u fragments:%u/%u bundles:%u/%u\n", | ||
| 2209 | l->next_in_no - s->recv_info, s->recv_fragments, | ||
| 2210 | s->recv_fragmented, s->recv_bundles, | ||
| 2211 | s->recv_bundled); | ||
| 2212 | |||
| 2213 | ret += tipc_snprintf(buf + ret, buf_size - ret, | ||
| 2214 | " TX packets:%u fragments:%u/%u bundles:%u/%u\n", | ||
| 2215 | l->next_out_no - s->sent_info, s->sent_fragments, | ||
| 2216 | s->sent_fragmented, s->sent_bundles, | ||
| 2217 | s->sent_bundled); | ||
| 2218 | |||
| 2219 | profile_total = s->msg_length_counts; | ||
| 2220 | if (!profile_total) | ||
| 2221 | profile_total = 1; | ||
| 2222 | |||
| 2223 | ret += tipc_snprintf(buf + ret, buf_size - ret, | ||
| 2224 | " TX profile sample:%u packets average:%u octets\n" | ||
| 2225 | " 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% " | ||
| 2226 | "-16384:%u%% -32768:%u%% -66000:%u%%\n", | ||
| 2227 | s->msg_length_counts, | ||
| 2228 | s->msg_lengths_total / profile_total, | ||
| 2229 | percent(s->msg_length_profile[0], profile_total), | ||
| 2230 | percent(s->msg_length_profile[1], profile_total), | ||
| 2231 | percent(s->msg_length_profile[2], profile_total), | ||
| 2232 | percent(s->msg_length_profile[3], profile_total), | ||
| 2233 | percent(s->msg_length_profile[4], profile_total), | ||
| 2234 | percent(s->msg_length_profile[5], profile_total), | ||
| 2235 | percent(s->msg_length_profile[6], profile_total)); | ||
| 2236 | |||
| 2237 | ret += tipc_snprintf(buf + ret, buf_size - ret, | ||
| 2238 | " RX states:%u probes:%u naks:%u defs:%u" | ||
| 2239 | " dups:%u\n", s->recv_states, s->recv_probes, | ||
| 2240 | s->recv_nacks, s->deferred_recv, s->duplicates); | ||
| 2241 | |||
| 2242 | ret += tipc_snprintf(buf + ret, buf_size - ret, | ||
| 2243 | " TX states:%u probes:%u naks:%u acks:%u" | ||
| 2244 | " dups:%u\n", s->sent_states, s->sent_probes, | ||
| 2245 | s->sent_nacks, s->sent_acks, s->retransmitted); | ||
| 2246 | |||
| 2247 | ret += tipc_snprintf(buf + ret, buf_size - ret, | ||
| 2248 | " Congestion link:%u Send queue" | ||
| 2249 | " max:%u avg:%u\n", s->link_congs, | ||
| 2250 | s->max_queue_sz, s->queue_sz_counts ? | ||
| 2251 | (s->accu_queue_sz / s->queue_sz_counts) : 0); | ||
| 2252 | |||
| 2253 | tipc_node_unlock(node); | ||
| 2254 | return ret; | ||
| 2255 | } | ||
| 2256 | |||
| 2257 | struct sk_buff *tipc_link_cmd_show_stats(struct net *net, | ||
| 2258 | const void *req_tlv_area, | ||
| 2259 | int req_tlv_space) | ||
| 2260 | { | ||
| 2261 | struct sk_buff *buf; | ||
| 2262 | struct tlv_desc *rep_tlv; | ||
| 2263 | int str_len; | ||
| 2264 | int pb_len; | ||
| 2265 | char *pb; | ||
| 2266 | |||
| 2267 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) | ||
| 2268 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
| 2269 | |||
| 2270 | buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN)); | ||
| 2271 | if (!buf) | ||
| 2272 | return NULL; | ||
| 2273 | |||
| 2274 | rep_tlv = (struct tlv_desc *)buf->data; | ||
| 2275 | pb = TLV_DATA(rep_tlv); | ||
| 2276 | pb_len = ULTRA_STRING_MAX_LEN; | ||
| 2277 | str_len = tipc_link_stats(net, (char *)TLV_DATA(req_tlv_area), | ||
| 2278 | pb, pb_len); | ||
| 2279 | if (!str_len) { | ||
| 2280 | kfree_skb(buf); | ||
| 2281 | return tipc_cfg_reply_error_string("link not found"); | ||
| 2282 | } | ||
| 2283 | str_len += 1; /* for "\0" */ | ||
| 2284 | skb_put(buf, TLV_SPACE(str_len)); | ||
| 2285 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); | ||
| 2286 | |||
| 2287 | return buf; | ||
| 2288 | } | ||
| 2289 | |||
| 2290 | static void link_print(struct tipc_link *l_ptr, const char *str) | 2149 | static void link_print(struct tipc_link *l_ptr, const char *str) |
| 2291 | { | 2150 | { |
| 2292 | struct tipc_net *tn = net_generic(l_ptr->owner->net, tipc_net_id); | 2151 | struct tipc_net *tn = net_generic(l_ptr->owner->net, tipc_net_id); |
diff --git a/net/tipc/link.h b/net/tipc/link.h index 34d3f55c4cea..8c8340cf991f 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h | |||
| @@ -217,9 +217,6 @@ int tipc_link_is_active(struct tipc_link *l_ptr); | |||
| 217 | void tipc_link_purge_queues(struct tipc_link *l_ptr); | 217 | void tipc_link_purge_queues(struct tipc_link *l_ptr); |
| 218 | struct sk_buff *tipc_link_cmd_config(struct net *net, const void *req_tlv_area, | 218 | struct sk_buff *tipc_link_cmd_config(struct net *net, const void *req_tlv_area, |
| 219 | int req_tlv_space, u16 cmd); | 219 | int req_tlv_space, u16 cmd); |
| 220 | struct sk_buff *tipc_link_cmd_show_stats(struct net *net, | ||
| 221 | const void *req_tlv_area, | ||
| 222 | int req_tlv_space); | ||
| 223 | struct sk_buff *tipc_link_cmd_reset_stats(struct net *net, | 220 | struct sk_buff *tipc_link_cmd_reset_stats(struct net *net, |
| 224 | const void *req_tlv_area, | 221 | const void *req_tlv_area, |
| 225 | int req_tlv_space); | 222 | int req_tlv_space); |
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 12b0f4424797..899bd94da467 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include "core.h" | 34 | #include "core.h" |
| 35 | #include "config.h" | 35 | #include "config.h" |
| 36 | #include "bearer.h" | 36 | #include "bearer.h" |
| 37 | #include "link.h" | ||
| 37 | #include <net/genetlink.h> | 38 | #include <net/genetlink.h> |
| 38 | #include <linux/tipc_config.h> | 39 | #include <linux/tipc_config.h> |
| 39 | 40 | ||
| @@ -48,6 +49,7 @@ | |||
| 48 | 49 | ||
| 49 | struct tipc_nl_compat_msg { | 50 | struct tipc_nl_compat_msg { |
| 50 | u16 cmd; | 51 | u16 cmd; |
| 52 | int rep_type; | ||
| 51 | int rep_size; | 53 | int rep_size; |
| 52 | int req_type; | 54 | int req_type; |
| 53 | struct sk_buff *rep; | 55 | struct sk_buff *rep; |
| @@ -95,6 +97,40 @@ static int tipc_add_tlv(struct sk_buff *skb, u16 type, void *data, u16 len) | |||
| 95 | return 0; | 97 | return 0; |
| 96 | } | 98 | } |
| 97 | 99 | ||
| 100 | static void tipc_tlv_init(struct sk_buff *skb, u16 type) | ||
| 101 | { | ||
| 102 | struct tlv_desc *tlv = (struct tlv_desc *)skb->data; | ||
| 103 | |||
| 104 | TLV_SET_LEN(tlv, 0); | ||
| 105 | TLV_SET_TYPE(tlv, type); | ||
| 106 | skb_put(skb, sizeof(struct tlv_desc)); | ||
| 107 | } | ||
| 108 | |||
| 109 | static int tipc_tlv_sprintf(struct sk_buff *skb, const char *fmt, ...) | ||
| 110 | { | ||
| 111 | int n; | ||
| 112 | u16 len; | ||
| 113 | u32 rem; | ||
| 114 | char *buf; | ||
| 115 | struct tlv_desc *tlv; | ||
| 116 | va_list args; | ||
| 117 | |||
| 118 | rem = tipc_skb_tailroom(skb); | ||
| 119 | |||
| 120 | tlv = (struct tlv_desc *)skb->data; | ||
| 121 | len = TLV_GET_LEN(tlv); | ||
| 122 | buf = TLV_DATA(tlv) + len; | ||
| 123 | |||
| 124 | va_start(args, fmt); | ||
| 125 | n = vscnprintf(buf, rem, fmt, args); | ||
| 126 | va_end(args); | ||
| 127 | |||
| 128 | TLV_SET_LEN(tlv, n + len); | ||
| 129 | skb_put(skb, n); | ||
| 130 | |||
| 131 | return n; | ||
| 132 | } | ||
| 133 | |||
| 98 | static struct sk_buff *tipc_tlv_alloc(int size) | 134 | static struct sk_buff *tipc_tlv_alloc(int size) |
| 99 | { | 135 | { |
| 100 | int hdr_len; | 136 | int hdr_len; |
| @@ -200,10 +236,16 @@ static int tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, | |||
| 200 | int err; | 236 | int err; |
| 201 | struct sk_buff *arg; | 237 | struct sk_buff *arg; |
| 202 | 238 | ||
| 239 | if (msg->req_type && !TLV_CHECK_TYPE(msg->req, msg->req_type)) | ||
| 240 | return -EINVAL; | ||
| 241 | |||
| 203 | msg->rep = tipc_tlv_alloc(msg->rep_size); | 242 | msg->rep = tipc_tlv_alloc(msg->rep_size); |
| 204 | if (!msg->rep) | 243 | if (!msg->rep) |
| 205 | return -ENOMEM; | 244 | return -ENOMEM; |
| 206 | 245 | ||
| 246 | if (msg->rep_type) | ||
| 247 | tipc_tlv_init(msg->rep, msg->rep_type); | ||
| 248 | |||
| 207 | arg = nlmsg_new(0, GFP_KERNEL); | 249 | arg = nlmsg_new(0, GFP_KERNEL); |
| 208 | if (!arg) { | 250 | if (!arg) { |
| 209 | kfree_skb(msg->rep); | 251 | kfree_skb(msg->rep); |
| @@ -356,6 +398,161 @@ static int tipc_nl_compat_bearer_disable(struct sk_buff *skb, | |||
| 356 | return 0; | 398 | return 0; |
| 357 | } | 399 | } |
| 358 | 400 | ||
| 401 | static inline u32 perc(u32 count, u32 total) | ||
| 402 | { | ||
| 403 | return (count * 100 + (total / 2)) / total; | ||
| 404 | } | ||
| 405 | |||
| 406 | static void __fill_bc_link_stat(struct tipc_nl_compat_msg *msg, | ||
| 407 | struct nlattr *prop[], struct nlattr *stats[]) | ||
| 408 | { | ||
| 409 | tipc_tlv_sprintf(msg->rep, " Window:%u packets\n", | ||
| 410 | nla_get_u32(prop[TIPC_NLA_PROP_WIN])); | ||
| 411 | |||
| 412 | tipc_tlv_sprintf(msg->rep, | ||
| 413 | " RX packets:%u fragments:%u/%u bundles:%u/%u\n", | ||
| 414 | nla_get_u32(stats[TIPC_NLA_STATS_RX_INFO]), | ||
| 415 | nla_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTS]), | ||
| 416 | nla_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTED]), | ||
| 417 | nla_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLES]), | ||
| 418 | nla_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLED])); | ||
| 419 | |||
| 420 | tipc_tlv_sprintf(msg->rep, | ||
| 421 | " TX packets:%u fragments:%u/%u bundles:%u/%u\n", | ||
| 422 | nla_get_u32(stats[TIPC_NLA_STATS_TX_INFO]), | ||
| 423 | nla_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTS]), | ||
| 424 | nla_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTED]), | ||
| 425 | nla_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLES]), | ||
| 426 | nla_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLED])); | ||
| 427 | |||
| 428 | tipc_tlv_sprintf(msg->rep, " RX naks:%u defs:%u dups:%u\n", | ||
| 429 | nla_get_u32(stats[TIPC_NLA_STATS_RX_NACKS]), | ||
| 430 | nla_get_u32(stats[TIPC_NLA_STATS_RX_DEFERRED]), | ||
| 431 | nla_get_u32(stats[TIPC_NLA_STATS_DUPLICATES])); | ||
| 432 | |||
| 433 | tipc_tlv_sprintf(msg->rep, " TX naks:%u acks:%u dups:%u\n", | ||
| 434 | nla_get_u32(stats[TIPC_NLA_STATS_TX_NACKS]), | ||
| 435 | nla_get_u32(stats[TIPC_NLA_STATS_TX_ACKS]), | ||
| 436 | nla_get_u32(stats[TIPC_NLA_STATS_RETRANSMITTED])); | ||
| 437 | |||
| 438 | tipc_tlv_sprintf(msg->rep, | ||
| 439 | " Congestion link:%u Send queue max:%u avg:%u", | ||
| 440 | nla_get_u32(stats[TIPC_NLA_STATS_LINK_CONGS]), | ||
| 441 | nla_get_u32(stats[TIPC_NLA_STATS_MAX_QUEUE]), | ||
| 442 | nla_get_u32(stats[TIPC_NLA_STATS_AVG_QUEUE])); | ||
| 443 | } | ||
| 444 | |||
| 445 | static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg, | ||
| 446 | struct nlattr **attrs) | ||
| 447 | { | ||
| 448 | char *name; | ||
| 449 | struct nlattr *link[TIPC_NLA_LINK_MAX + 1]; | ||
| 450 | struct nlattr *prop[TIPC_NLA_PROP_MAX + 1]; | ||
| 451 | struct nlattr *stats[TIPC_NLA_STATS_MAX + 1]; | ||
| 452 | |||
| 453 | nla_parse_nested(link, TIPC_NLA_LINK_MAX, attrs[TIPC_NLA_LINK], NULL); | ||
| 454 | |||
| 455 | nla_parse_nested(prop, TIPC_NLA_PROP_MAX, link[TIPC_NLA_LINK_PROP], | ||
| 456 | NULL); | ||
| 457 | |||
| 458 | nla_parse_nested(stats, TIPC_NLA_STATS_MAX, link[TIPC_NLA_LINK_STATS], | ||
| 459 | NULL); | ||
| 460 | |||
| 461 | name = (char *)TLV_DATA(msg->req); | ||
| 462 | if (strcmp(name, nla_data(link[TIPC_NLA_LINK_NAME])) != 0) | ||
| 463 | return 0; | ||
| 464 | |||
| 465 | tipc_tlv_sprintf(msg->rep, "\nLink <%s>\n", | ||
| 466 | nla_data(link[TIPC_NLA_LINK_NAME])); | ||
| 467 | |||
| 468 | if (link[TIPC_NLA_LINK_BROADCAST]) { | ||
| 469 | __fill_bc_link_stat(msg, prop, stats); | ||
| 470 | return 0; | ||
| 471 | } | ||
| 472 | |||
| 473 | if (link[TIPC_NLA_LINK_ACTIVE]) | ||
| 474 | tipc_tlv_sprintf(msg->rep, " ACTIVE"); | ||
| 475 | else if (link[TIPC_NLA_LINK_UP]) | ||
| 476 | tipc_tlv_sprintf(msg->rep, " STANDBY"); | ||
| 477 | else | ||
| 478 | tipc_tlv_sprintf(msg->rep, " DEFUNCT"); | ||
| 479 | |||
| 480 | tipc_tlv_sprintf(msg->rep, " MTU:%u Priority:%u", | ||
| 481 | nla_get_u32(link[TIPC_NLA_LINK_MTU]), | ||
| 482 | nla_get_u32(prop[TIPC_NLA_PROP_PRIO])); | ||
| 483 | |||
| 484 | tipc_tlv_sprintf(msg->rep, " Tolerance:%u ms Window:%u packets\n", | ||
| 485 | nla_get_u32(prop[TIPC_NLA_PROP_TOL]), | ||
| 486 | nla_get_u32(prop[TIPC_NLA_PROP_WIN])); | ||
| 487 | |||
| 488 | tipc_tlv_sprintf(msg->rep, | ||
| 489 | " RX packets:%u fragments:%u/%u bundles:%u/%u\n", | ||
| 490 | nla_get_u32(link[TIPC_NLA_LINK_RX]) - | ||
| 491 | nla_get_u32(stats[TIPC_NLA_STATS_RX_INFO]), | ||
| 492 | nla_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTS]), | ||
| 493 | nla_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTED]), | ||
| 494 | nla_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLES]), | ||
| 495 | nla_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLED])); | ||
| 496 | |||
| 497 | tipc_tlv_sprintf(msg->rep, | ||
| 498 | " TX packets:%u fragments:%u/%u bundles:%u/%u\n", | ||
| 499 | nla_get_u32(link[TIPC_NLA_LINK_TX]) - | ||
| 500 | nla_get_u32(stats[TIPC_NLA_STATS_TX_INFO]), | ||
| 501 | nla_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTS]), | ||
| 502 | nla_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTED]), | ||
| 503 | nla_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLES]), | ||
| 504 | nla_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLED])); | ||
| 505 | |||
| 506 | tipc_tlv_sprintf(msg->rep, | ||
| 507 | " TX profile sample:%u packets average:%u octets\n", | ||
| 508 | nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_CNT]), | ||
| 509 | nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_TOT]) / | ||
| 510 | nla_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT])); | ||
| 511 | |||
| 512 | tipc_tlv_sprintf(msg->rep, | ||
| 513 | " 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% ", | ||
| 514 | perc(nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P0]), | ||
| 515 | nla_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT])), | ||
| 516 | perc(nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P1]), | ||
| 517 | nla_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT])), | ||
| 518 | perc(nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P2]), | ||
| 519 | nla_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT])), | ||
| 520 | perc(nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P3]), | ||
| 521 | nla_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT]))); | ||
| 522 | |||
| 523 | tipc_tlv_sprintf(msg->rep, "-16384:%u%% -32768:%u%% -66000:%u%%\n", | ||
| 524 | perc(nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P4]), | ||
| 525 | nla_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT])), | ||
| 526 | perc(nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P5]), | ||
| 527 | nla_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT])), | ||
| 528 | perc(nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P6]), | ||
| 529 | nla_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT]))); | ||
| 530 | |||
| 531 | tipc_tlv_sprintf(msg->rep, | ||
| 532 | " RX states:%u probes:%u naks:%u defs:%u dups:%u\n", | ||
| 533 | nla_get_u32(stats[TIPC_NLA_STATS_RX_STATES]), | ||
| 534 | nla_get_u32(stats[TIPC_NLA_STATS_RX_PROBES]), | ||
| 535 | nla_get_u32(stats[TIPC_NLA_STATS_RX_NACKS]), | ||
| 536 | nla_get_u32(stats[TIPC_NLA_STATS_RX_DEFERRED]), | ||
| 537 | nla_get_u32(stats[TIPC_NLA_STATS_DUPLICATES])); | ||
| 538 | |||
| 539 | tipc_tlv_sprintf(msg->rep, | ||
| 540 | " TX states:%u probes:%u naks:%u acks:%u dups:%u\n", | ||
| 541 | nla_get_u32(stats[TIPC_NLA_STATS_TX_STATES]), | ||
| 542 | nla_get_u32(stats[TIPC_NLA_STATS_TX_PROBES]), | ||
| 543 | nla_get_u32(stats[TIPC_NLA_STATS_TX_NACKS]), | ||
| 544 | nla_get_u32(stats[TIPC_NLA_STATS_TX_ACKS]), | ||
| 545 | nla_get_u32(stats[TIPC_NLA_STATS_RETRANSMITTED])); | ||
| 546 | |||
| 547 | tipc_tlv_sprintf(msg->rep, | ||
| 548 | " Congestion link:%u Send queue max:%u avg:%u", | ||
| 549 | nla_get_u32(stats[TIPC_NLA_STATS_LINK_CONGS]), | ||
| 550 | nla_get_u32(stats[TIPC_NLA_STATS_MAX_QUEUE]), | ||
| 551 | nla_get_u32(stats[TIPC_NLA_STATS_AVG_QUEUE])); | ||
| 552 | |||
| 553 | return 0; | ||
| 554 | } | ||
| 555 | |||
| 359 | static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) | 556 | static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) |
| 360 | { | 557 | { |
| 361 | struct tipc_nl_compat_cmd_dump dump; | 558 | struct tipc_nl_compat_cmd_dump dump; |
| @@ -380,6 +577,13 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) | |||
| 380 | doit.doit = tipc_nl_bearer_disable; | 577 | doit.doit = tipc_nl_bearer_disable; |
| 381 | doit.transcode = tipc_nl_compat_bearer_disable; | 578 | doit.transcode = tipc_nl_compat_bearer_disable; |
| 382 | return tipc_nl_compat_doit(&doit, msg); | 579 | return tipc_nl_compat_doit(&doit, msg); |
| 580 | case TIPC_CMD_SHOW_LINK_STATS: | ||
| 581 | msg->req_type = TIPC_TLV_LINK_NAME; | ||
| 582 | msg->rep_size = ULTRA_STRING_MAX_LEN; | ||
| 583 | msg->rep_type = TIPC_TLV_ULTRA_STRING; | ||
| 584 | dump.dumpit = tipc_nl_link_dump; | ||
| 585 | dump.format = tipc_nl_compat_link_stat_dump; | ||
| 586 | return tipc_nl_compat_dumpit(&dump, msg); | ||
| 383 | } | 587 | } |
| 384 | 588 | ||
| 385 | return -EOPNOTSUPP; | 589 | return -EOPNOTSUPP; |
| @@ -479,6 +683,7 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) | |||
| 479 | case TIPC_CMD_GET_BEARER_NAMES: | 683 | case TIPC_CMD_GET_BEARER_NAMES: |
| 480 | case TIPC_CMD_ENABLE_BEARER: | 684 | case TIPC_CMD_ENABLE_BEARER: |
| 481 | case TIPC_CMD_DISABLE_BEARER: | 685 | case TIPC_CMD_DISABLE_BEARER: |
| 686 | case TIPC_CMD_SHOW_LINK_STATS: | ||
| 482 | return tipc_nl_compat_recv(skb, info); | 687 | return tipc_nl_compat_recv(skb, info); |
| 483 | } | 688 | } |
| 484 | 689 | ||
