diff options
author | David S. Miller <davem@davemloft.net> | 2015-02-09 16:20:53 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-02-09 16:20:53 -0500 |
commit | 9dce285b70c157754d753203112cfef22770b1f9 (patch) | |
tree | 4859799a8311ecd637e2a582600af1057a78e08b /net/tipc/link.c | |
parent | c8ac18f2006b2926ce375c01646b2f487d1c33b2 (diff) | |
parent | 941787b82982b3f33ac398c8c00035ddd0f8c514 (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.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; |