Add functionality for safely appending string data to a TLV without keeping write count in the caller. Convert TIPC_CMD_SHOW_LINK_STATS to compat dumpit.
Unified · Split
| @@ -277,11 +277,21 @@ static inline int TLV_GET_LEN(struct tlv_desc *tlv) · 276 unmodified lines | ||
| 277 | 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 | 285 | static inline int TLV_CHECK_TYPE(struct tlv_desc *tlv, __u16 type) |
| 281 | 286 | { |
| 282 | 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 | 295 | static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len) |
| 286 | 296 | { |
| 287 | 297 | struct tlv_desc *tlv_ptr; |
| @@ -860,49 +860,6 @@ msg_full: · 859 unmodified lines | ||
| 860 | 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 | 863 | int tipc_bclink_reset_stats(struct net *net) |
| 907 | 864 | { |
| 908 | 865 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
| @@ -127,7 +127,6 @@ u32 tipc_bclink_get_last_sent(struct net *net); · 126 unmodified lines | ||
| 127 | 127 | u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr); |
| 128 | 128 | void tipc_bclink_update_link_state(struct tipc_node *node, |
| 129 | 129 | u32 last_sent); |
| 130 | −int tipc_bclink_stats(struct net *net, char *stats_buf, const u32 buf_size); | |
| 131 | 130 | int tipc_bclink_reset_stats(struct net *net); |
| 132 | 131 | int tipc_bclink_set_queue_limits(struct net *net, u32 limit); |
| 133 | 132 | void tipc_bcbearer_sort(struct net *net, struct tipc_node_map *nm_ptr, |
| @@ -213,10 +213,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, · 212 unmodified lines | ||
| 213 | 213 | rep_tlv_buf = tipc_node_get_links(net, req_tlv_area, |
| 214 | 214 | req_tlv_space); |
| 215 | 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 | 216 | case TIPC_CMD_RESET_LINK_STATS: |
| 221 | 217 | rep_tlv_buf = tipc_link_cmd_reset_stats(net, req_tlv_area, |
| 222 | 218 | req_tlv_space); |
| @@ -2146,147 +2146,6 @@ struct sk_buff *tipc_link_cmd_reset_stats(struct net *net, · 2145 unmodified lines | ||
| 2146 | 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 | 2149 | static void link_print(struct tipc_link *l_ptr, const char *str) |
| 2291 | 2150 | { |
| 2292 | 2151 | struct tipc_net *tn = net_generic(l_ptr->owner->net, tipc_net_id); |
| @@ -217,9 +217,6 @@ int tipc_link_is_active(struct tipc_link *l_ptr); · 216 unmodified lines | ||
| 217 | 217 | void tipc_link_purge_queues(struct tipc_link *l_ptr); |
| 218 | 218 | struct sk_buff *tipc_link_cmd_config(struct net *net, const void *req_tlv_area, |
| 219 | 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 | 220 | struct sk_buff *tipc_link_cmd_reset_stats(struct net *net, |
| 224 | 221 | const void *req_tlv_area, |
| 225 | 222 | int req_tlv_space); |
| @@ -34,6 +34,7 @@ · 33 unmodified lines | ||
| 34 | 34 | #include "core.h" |
| 35 | 35 | #include "config.h" |
| 36 | 36 | #include "bearer.h" |
| 37 | +#include "link.h" | |
| 37 | 38 | #include <net/genetlink.h> |
| 38 | 39 | #include <linux/tipc_config.h> |
| 39 | 40 | |
| @@ -48,6 +49,7 @@ · 8 unmodified lines | ||
| 48 | 49 | |
| 49 | 50 | struct tipc_nl_compat_msg { |
| 50 | 51 | u16 cmd; |
| 52 | + int rep_type; | |
| 51 | 53 | int rep_size; |
| 52 | 54 | int req_type; |
| 53 | 55 | struct sk_buff *rep; |
| @@ -95,6 +97,40 @@ static int tipc_add_tlv(struct sk_buff *skb, u16 type, void *data, u16 len) · 41 unmodified lines | ||
| 95 | 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 | 134 | static struct sk_buff *tipc_tlv_alloc(int size) |
| 99 | 135 | { |
| 100 | 136 | int hdr_len; |
| @@ -200,10 +236,16 @@ static int tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, · 99 unmodified lines | ||
| 200 | 236 | int err; |
| 201 | 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 | 242 | msg->rep = tipc_tlv_alloc(msg->rep_size); |
| 204 | 243 | if (!msg->rep) |
| 205 | 244 | return -ENOMEM; |
| 206 | 245 | |
| 246 | + if (msg->rep_type) | |
| 247 | + tipc_tlv_init(msg->rep, msg->rep_type); | |
| 248 | + | |
| 207 | 249 | arg = nlmsg_new(0, GFP_KERNEL); |
| 208 | 250 | if (!arg) { |
| 209 | 251 | kfree_skb(msg->rep); |
| @@ -356,6 +398,161 @@ static int tipc_nl_compat_bearer_disable(struct sk_buff *skb, · 146 unmodified lines | ||
| 356 | 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 | 556 | static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) |
| 360 | 557 | { |
| 361 | 558 | struct tipc_nl_compat_cmd_dump dump; |
| @@ -380,6 +577,13 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) · 18 unmodified lines | ||
| 380 | 577 | doit.doit = tipc_nl_bearer_disable; |
| 381 | 578 | doit.transcode = tipc_nl_compat_bearer_disable; |
| 382 | 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 | 589 | return -EOPNOTSUPP; |
| @@ -479,6 +683,7 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) · 93 unmodified lines | ||
| 479 | 683 | case TIPC_CMD_GET_BEARER_NAMES: |
| 480 | 684 | case TIPC_CMD_ENABLE_BEARER: |
| 481 | 685 | case TIPC_CMD_DISABLE_BEARER: |
| 686 | + case TIPC_CMD_SHOW_LINK_STATS: | |
| 482 | 687 | return tipc_nl_compat_recv(skb, info); |
| 483 | 688 | } |
| 484 | 689 | |