aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/link.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-02-09 16:20:53 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-09 16:20:53 -0500
commit9dce285b70c157754d753203112cfef22770b1f9 (patch)
tree4859799a8311ecd637e2a582600af1057a78e08b /net/tipc/link.c
parentc8ac18f2006b2926ce375c01646b2f487d1c33b2 (diff)
parent941787b82982b3f33ac398c8c00035ddd0f8c514 (diff)
Merge branch 'tipc-next'
Richard Alpe says: ==================== tipc: new compat layer for the legacy NL API This is a compatibility / transcoding layer for the old netlink API. It relies on the new netlink API to collect data or perform actions (dumpit / doit). The main benefit of this compat layer is that it removes a lot of complex code from the tipc core as only the new API needs to be able harness data or perform actions. I.e. the compat layer isn't concerned with locking or how the internal data-structures look. As long as the new API stays relatively intact the compat layer should be fine. The main challenge in this compat layer is the randomness of the legacy API. Some commands send binary data and some send ASCII data, some are very picky in optimizing there buffer sizes and some just don't care. Most legacy commands put there data in a single TLV (data container) but some segment the data into multiple TLV's. This list of randomness goes on and on.. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
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;