aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/link.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r--net/tipc/link.c325
1 files changed, 3 insertions, 322 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 942491234099..a4cf364316de 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -40,7 +40,6 @@
40#include "socket.h" 40#include "socket.h"
41#include "name_distr.h" 41#include "name_distr.h"
42#include "discover.h" 42#include "discover.h"
43#include "config.h"
44#include "netlink.h" 43#include "netlink.h"
45 44
46#include <linux/pkt_sched.h> 45#include <linux/pkt_sched.h>
@@ -1959,150 +1958,6 @@ static struct tipc_node *tipc_link_find_owner(struct net *net,
1959} 1958}
1960 1959
1961/** 1960/**
1962 * link_value_is_valid -- validate proposed link tolerance/priority/window
1963 *
1964 * @cmd: value type (TIPC_CMD_SET_LINK_*)
1965 * @new_value: the new value
1966 *
1967 * Returns 1 if value is within range, 0 if not.
1968 */
1969static int link_value_is_valid(u16 cmd, u32 new_value)
1970{
1971 switch (cmd) {
1972 case TIPC_CMD_SET_LINK_TOL:
1973 return (new_value >= TIPC_MIN_LINK_TOL) &&
1974 (new_value <= TIPC_MAX_LINK_TOL);
1975 case TIPC_CMD_SET_LINK_PRI:
1976 return (new_value <= TIPC_MAX_LINK_PRI);
1977 case TIPC_CMD_SET_LINK_WINDOW:
1978 return (new_value >= TIPC_MIN_LINK_WIN) &&
1979 (new_value <= TIPC_MAX_LINK_WIN);
1980 }
1981 return 0;
1982}
1983
1984/**
1985 * link_cmd_set_value - change priority/tolerance/window for link/bearer/media
1986 * @net: the applicable net namespace
1987 * @name: ptr to link, bearer, or media name
1988 * @new_value: new value of link, bearer, or media setting
1989 * @cmd: which link, bearer, or media attribute to set (TIPC_CMD_SET_LINK_*)
1990 *
1991 * Caller must hold RTNL lock to ensure link/bearer/media is not deleted.
1992 *
1993 * Returns 0 if value updated and negative value on error.
1994 */
1995static int link_cmd_set_value(struct net *net, const char *name, u32 new_value,
1996 u16 cmd)
1997{
1998 struct tipc_node *node;
1999 struct tipc_link *l_ptr;
2000 struct tipc_bearer *b_ptr;
2001 struct tipc_media *m_ptr;
2002 int bearer_id;
2003 int res = 0;
2004
2005 node = tipc_link_find_owner(net, name, &bearer_id);
2006 if (node) {
2007 tipc_node_lock(node);
2008 l_ptr = node->links[bearer_id];
2009
2010 if (l_ptr) {
2011 switch (cmd) {
2012 case TIPC_CMD_SET_LINK_TOL:
2013 link_set_supervision_props(l_ptr, new_value);
2014 tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0,
2015 new_value, 0, 0);
2016 break;
2017 case TIPC_CMD_SET_LINK_PRI:
2018 l_ptr->priority = new_value;
2019 tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0,
2020 0, new_value, 0);
2021 break;
2022 case TIPC_CMD_SET_LINK_WINDOW:
2023 tipc_link_set_queue_limits(l_ptr, new_value);
2024 break;
2025 default:
2026 res = -EINVAL;
2027 break;
2028 }
2029 }
2030 tipc_node_unlock(node);
2031 return res;
2032 }
2033
2034 b_ptr = tipc_bearer_find(net, name);
2035 if (b_ptr) {
2036 switch (cmd) {
2037 case TIPC_CMD_SET_LINK_TOL:
2038 b_ptr->tolerance = new_value;
2039 break;
2040 case TIPC_CMD_SET_LINK_PRI:
2041 b_ptr->priority = new_value;
2042 break;
2043 case TIPC_CMD_SET_LINK_WINDOW:
2044 b_ptr->window = new_value;
2045 break;
2046 default:
2047 res = -EINVAL;
2048 break;
2049 }
2050 return res;
2051 }
2052
2053 m_ptr = tipc_media_find(name);
2054 if (!m_ptr)
2055 return -ENODEV;
2056 switch (cmd) {
2057 case TIPC_CMD_SET_LINK_TOL:
2058 m_ptr->tolerance = new_value;
2059 break;
2060 case TIPC_CMD_SET_LINK_PRI:
2061 m_ptr->priority = new_value;
2062 break;
2063 case TIPC_CMD_SET_LINK_WINDOW:
2064 m_ptr->window = new_value;
2065 break;
2066 default:
2067 res = -EINVAL;
2068 break;
2069 }
2070 return res;
2071}
2072
2073struct sk_buff *tipc_link_cmd_config(struct net *net, const void *req_tlv_area,
2074 int req_tlv_space, u16 cmd)
2075{
2076 struct tipc_link_config *args;
2077 u32 new_value;
2078 int res;
2079
2080 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_CONFIG))
2081 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
2082
2083 args = (struct tipc_link_config *)TLV_DATA(req_tlv_area);
2084 new_value = ntohl(args->value);
2085
2086 if (!link_value_is_valid(cmd, new_value))
2087 return tipc_cfg_reply_error_string(
2088 "cannot change, value invalid");
2089
2090 if (!strcmp(args->name, tipc_bclink_name)) {
2091 if ((cmd == TIPC_CMD_SET_LINK_WINDOW) &&
2092 (tipc_bclink_set_queue_limits(net, new_value) == 0))
2093 return tipc_cfg_reply_none();
2094 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
2095 " (cannot change setting on broadcast link)");
2096 }
2097
2098 res = link_cmd_set_value(net, args->name, new_value, cmd);
2099 if (res)
2100 return tipc_cfg_reply_error_string("cannot change link setting");
2101
2102 return tipc_cfg_reply_none();
2103}
2104
2105/**
2106 * link_reset_statistics - reset link statistics 1961 * link_reset_statistics - reset link statistics
2107 * @l_ptr: pointer to link 1962 * @l_ptr: pointer to link
2108 */ 1963 */
@@ -2113,180 +1968,6 @@ static void link_reset_statistics(struct tipc_link *l_ptr)
2113 l_ptr->stats.recv_info = l_ptr->next_in_no; 1968 l_ptr->stats.recv_info = l_ptr->next_in_no;
2114} 1969}
2115 1970
2116struct sk_buff *tipc_link_cmd_reset_stats(struct net *net,
2117 const void *req_tlv_area,
2118 int req_tlv_space)
2119{
2120 char *link_name;
2121 struct tipc_link *l_ptr;
2122 struct tipc_node *node;
2123 unsigned int bearer_id;
2124
2125 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
2126 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
2127
2128 link_name = (char *)TLV_DATA(req_tlv_area);
2129 if (!strcmp(link_name, tipc_bclink_name)) {
2130 if (tipc_bclink_reset_stats(net))
2131 return tipc_cfg_reply_error_string("link not found");
2132 return tipc_cfg_reply_none();
2133 }
2134 node = tipc_link_find_owner(net, link_name, &bearer_id);
2135 if (!node)
2136 return tipc_cfg_reply_error_string("link not found");
2137
2138 tipc_node_lock(node);
2139 l_ptr = node->links[bearer_id];
2140 if (!l_ptr) {
2141 tipc_node_unlock(node);
2142 return tipc_cfg_reply_error_string("link not found");
2143 }
2144 link_reset_statistics(l_ptr);
2145 tipc_node_unlock(node);
2146 return tipc_cfg_reply_none();
2147}
2148
2149/**
2150 * percent - convert count to a percentage of total (rounding up or down)
2151 */
2152static 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 */
2166static 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
2257struct 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
2290static void link_print(struct tipc_link *l_ptr, const char *str) 1971static void link_print(struct tipc_link *l_ptr, const char *str)
2291{ 1972{
2292 struct tipc_net *tn = net_generic(l_ptr->owner->net, tipc_net_id); 1973 struct tipc_net *tn = net_generic(l_ptr->owner->net, tipc_net_id);
@@ -2357,7 +2038,7 @@ int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info)
2357 struct tipc_link *link; 2038 struct tipc_link *link;
2358 struct tipc_node *node; 2039 struct tipc_node *node;
2359 struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; 2040 struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1];
2360 struct net *net = genl_info_net(info); 2041 struct net *net = sock_net(skb->sk);
2361 2042
2362 if (!info->attrs[TIPC_NLA_LINK]) 2043 if (!info->attrs[TIPC_NLA_LINK])
2363 return -EINVAL; 2044 return -EINVAL;
@@ -2498,7 +2179,7 @@ static int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg,
2498 struct nlattr *prop; 2179 struct nlattr *prop;
2499 struct tipc_net *tn = net_generic(net, tipc_net_id); 2180 struct tipc_net *tn = net_generic(net, tipc_net_id);
2500 2181
2501 hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family, 2182 hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
2502 NLM_F_MULTI, TIPC_NL_LINK_GET); 2183 NLM_F_MULTI, TIPC_NL_LINK_GET);
2503 if (!hdr) 2184 if (!hdr)
2504 return -EMSGSIZE; 2185 return -EMSGSIZE;
@@ -2709,7 +2390,7 @@ int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info)
2709 struct tipc_link *link; 2390 struct tipc_link *link;
2710 struct tipc_node *node; 2391 struct tipc_node *node;
2711 struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; 2392 struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1];
2712 struct net *net = genl_info_net(info); 2393 struct net *net = sock_net(skb->sk);
2713 2394
2714 if (!info->attrs[TIPC_NLA_LINK]) 2395 if (!info->attrs[TIPC_NLA_LINK])
2715 return -EINVAL; 2396 return -EINVAL;