diff options
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r-- | net/tipc/link.c | 325 |
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 | */ | ||
1969 | static 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 | */ | ||
1995 | static 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 | |||
2073 | struct 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 | ||
2116 | struct 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 | */ | ||
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) | 1971 | static 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; |