From 07f6c4bc048a7a8939c68a668bf77474890794c5 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Wed, 7 Jan 2015 13:41:58 +0800 Subject: tipc: convert tipc reference table to use generic rhashtable As tipc reference table is statically allocated, its memory size requested on stack initialization stage is quite big even if the maximum port number is just restricted to 8191 currently, however, the number already becomes insufficient in practice. But if the maximum ports is allowed to its theory value - 2^32, its consumed memory size will reach a ridiculously unacceptable value. Apart from this, heavy tipc users spend a considerable amount of time in tipc_sk_get() due to the read-lock on ref_table_lock. If tipc reference table is converted with generic rhashtable, above mentioned both disadvantages would be resolved respectively: making use of the new resizable hash table can avoid locking on the lookup; smaller memory size is required at initial stage, for example, 256 hash bucket slots are requested at the beginning phase instead of allocating the entire 8191 slots in old mode. The hash table will grow if entries exceeds 75% of table size up to a total table size of 1M, and it will automatically shrink if usage falls below 30%, but the minimum table size is allowed down to 256. Also converts ref_table_lock to a separate mutex to protect hash table mutations on write side. Lastly defers the release of the socket reference using call_rcu() to allow using an RCU read-side protected call to rhashtable_lookup(). Signed-off-by: Ying Xue Acked-by: Jon Maloy Acked-by: Erik Hugne Cc: Thomas Graf Acked-by: Thomas Graf Signed-off-by: David S. Miller --- net/tipc/config.c | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/config.c b/net/tipc/config.c index 876f4c6a2631..0b3a90ecab6d 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -183,22 +183,6 @@ static struct sk_buff *cfg_set_own_addr(void) return tipc_cfg_reply_error_string("cannot change to network mode"); } -static struct sk_buff *cfg_set_max_ports(void) -{ - u32 value; - - if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); - if (value == tipc_max_ports) - return tipc_cfg_reply_none(); - if (value < 127 || value > 65535) - return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (max ports must be 127-65535)"); - return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (cannot change max ports while TIPC is active)"); -} - static struct sk_buff *cfg_set_netid(void) { u32 value; @@ -285,15 +269,9 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area case TIPC_CMD_SET_NODE_ADDR: rep_tlv_buf = cfg_set_own_addr(); break; - case TIPC_CMD_SET_MAX_PORTS: - rep_tlv_buf = cfg_set_max_ports(); - break; case TIPC_CMD_SET_NETID: rep_tlv_buf = cfg_set_netid(); break; - case TIPC_CMD_GET_MAX_PORTS: - rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports); - break; case TIPC_CMD_GET_NETID: rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); break; @@ -317,6 +295,8 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area case TIPC_CMD_SET_REMOTE_MNG: case TIPC_CMD_GET_REMOTE_MNG: case TIPC_CMD_DUMP_LOG: + case TIPC_CMD_SET_MAX_PORTS: + case TIPC_CMD_GET_MAX_PORTS: rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (obsolete command)"); break; -- cgit v1.2.3-70-g09d2 From c93d3baa24095887005647984cff5de8c63d3611 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Fri, 9 Jan 2015 15:27:04 +0800 Subject: tipc: involve namespace infrastructure Involve namespace infrastructure, make the "tipc_net_id" global variable aware of per namespace, and rename it to "net_id". In order that the conversion can be successfully done, an instance of networking namespace must be passed to relevant functions, allowing them to access the "net_id" variable of per namespace. Signed-off-by: Ying Xue Tested-by: Tero Aho Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/bcast.c | 15 ++++++++++----- net/tipc/bcast.h | 5 +++-- net/tipc/bearer.c | 29 ++++++++++++----------------- net/tipc/bearer.h | 5 +++-- net/tipc/config.c | 29 ++++++++++++++++------------- net/tipc/config.h | 2 +- net/tipc/core.c | 28 +++++++++++++++++++++++++++- net/tipc/core.h | 5 +++++ net/tipc/discover.c | 26 +++++++++++++++++--------- net/tipc/discover.h | 8 +++++--- net/tipc/link.c | 47 +++++++++++++++++++++++++++-------------------- net/tipc/msg.c | 4 ++++ net/tipc/net.c | 22 ++++++++++++++-------- net/tipc/net.h | 2 +- net/tipc/netlink.c | 10 ++++++---- 15 files changed, 151 insertions(+), 86 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index a9e174fc0f91..f98231138916 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -327,9 +327,11 @@ exit: * * RCU and node lock set */ -void tipc_bclink_update_link_state(struct tipc_node *n_ptr, u32 last_sent) +void tipc_bclink_update_link_state(struct net *net, struct tipc_node *n_ptr, + u32 last_sent) { struct sk_buff *buf; + struct tipc_net *tn = net_generic(net, tipc_net_id); /* Ignore "stale" link state info */ if (less_eq(last_sent, n_ptr->bclink.last_in)) @@ -362,7 +364,7 @@ void tipc_bclink_update_link_state(struct tipc_node *n_ptr, u32 last_sent) tipc_msg_init(msg, BCAST_PROTOCOL, STATE_MSG, INT_H_SIZE, n_ptr->addr); msg_set_non_seq(msg, 1); - msg_set_mc_netid(msg, tipc_net_id); + msg_set_mc_netid(msg, tn->net_id); msg_set_bcast_ack(msg, n_ptr->bclink.last_in); msg_set_bcgap_after(msg, n_ptr->bclink.last_in); msg_set_bcgap_to(msg, to); @@ -476,8 +478,9 @@ static void bclink_accept_pkt(struct tipc_node *node, u32 seqno) * * RCU is locked, no other locks set */ -void tipc_bclink_rcv(struct sk_buff *buf) +void tipc_bclink_rcv(struct net *net, struct sk_buff *buf) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_msg *msg = buf_msg(buf); struct tipc_node *node; u32 next_in; @@ -485,7 +488,7 @@ void tipc_bclink_rcv(struct sk_buff *buf) int deferred = 0; /* Screen out unwanted broadcast messages */ - if (msg_mc_netid(msg) != tipc_net_id) + if (msg_mc_netid(msg) != tn->net_id) goto exit; node = tipc_node_find(msg_prevnode(msg)); @@ -638,6 +641,8 @@ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1, { int bp_index; struct tipc_msg *msg = buf_msg(buf); + struct net *net = sock_net(buf->sk); + struct tipc_net *tn = net_generic(net, tipc_net_id); /* Prepare broadcast link message for reliable transmission, * if first time trying to send it; @@ -647,7 +652,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1, if (likely(!msg_non_seq(buf_msg(buf)))) { bcbuf_set_acks(buf, bclink->bcast_nodes.count); msg_set_non_seq(msg, 1); - msg_set_mc_netid(msg, tipc_net_id); + msg_set_mc_netid(msg, tn->net_id); bcl->stats.sent_info++; if (WARN_ON(!bclink->bcast_nodes.count)) { diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 644d79129fba..a5fd22438aed 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h @@ -91,10 +91,11 @@ void tipc_bclink_add_node(u32 addr); void tipc_bclink_remove_node(u32 addr); struct tipc_node *tipc_bclink_retransmit_to(void); void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked); -void tipc_bclink_rcv(struct sk_buff *buf); +void tipc_bclink_rcv(struct net *net, struct sk_buff *buf); u32 tipc_bclink_get_last_sent(void); u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr); -void tipc_bclink_update_link_state(struct tipc_node *n_ptr, u32 last_sent); +void tipc_bclink_update_link_state(struct net *net, struct tipc_node *n_ptr, + u32 last_sent); int tipc_bclink_stats(char *stats_buf, const u32 buf_size); int tipc_bclink_reset_stats(void); int tipc_bclink_set_queue_limits(u32 limit); diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 463db5b15b8b..cdd30337dc5e 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -260,7 +260,8 @@ void tipc_bearer_remove_dest(u32 bearer_id, u32 dest) /** * tipc_enable_bearer - enable bearer with the given name */ -int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) +int tipc_enable_bearer(struct net *net, const char *name, u32 disc_domain, + u32 priority) { struct tipc_bearer *b_ptr; struct tipc_media *m_ptr; @@ -361,7 +362,7 @@ restart: b_ptr->net_plane = bearer_id + 'A'; b_ptr->priority = priority; - res = tipc_disc_create(b_ptr, &b_ptr->bcast_addr); + res = tipc_disc_create(net, b_ptr, &b_ptr->bcast_addr); if (res) { bearer_disable(b_ptr, false); pr_warn("Bearer <%s> rejected, discovery object creation failed\n", @@ -380,11 +381,11 @@ restart: /** * tipc_reset_bearer - Reset all links established over this bearer */ -static int tipc_reset_bearer(struct tipc_bearer *b_ptr) +static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b_ptr) { pr_info("Resetting bearer <%s>\n", b_ptr->name); tipc_link_reset_list(b_ptr->identity); - tipc_disc_reset(b_ptr); + tipc_disc_reset(net, b_ptr); return 0; } @@ -539,17 +540,12 @@ static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev, { struct tipc_bearer *b_ptr; - if (!net_eq(dev_net(dev), &init_net)) { - kfree_skb(buf); - return NET_RX_DROP; - } - rcu_read_lock(); b_ptr = rcu_dereference_rtnl(dev->tipc_ptr); if (likely(b_ptr)) { if (likely(buf->pkt_type <= PACKET_BROADCAST)) { buf->next = NULL; - tipc_rcv(buf, b_ptr); + tipc_rcv(dev_net(dev), buf, b_ptr); rcu_read_unlock(); return NET_RX_SUCCESS; } @@ -572,11 +568,9 @@ static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev, static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, void *ptr) { - struct tipc_bearer *b_ptr; struct net_device *dev = netdev_notifier_info_to_dev(ptr); - - if (!net_eq(dev_net(dev), &init_net)) - return NOTIFY_DONE; + struct net *net = dev_net(dev); + struct tipc_bearer *b_ptr; b_ptr = rtnl_dereference(dev->tipc_ptr); if (!b_ptr) @@ -590,12 +584,12 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, break; case NETDEV_DOWN: case NETDEV_CHANGEMTU: - tipc_reset_bearer(b_ptr); + tipc_reset_bearer(net, b_ptr); break; case NETDEV_CHANGEADDR: b_ptr->media->raw2addr(b_ptr, &b_ptr->addr, (char *)dev->dev_addr); - tipc_reset_bearer(b_ptr); + tipc_reset_bearer(net, b_ptr); break; case NETDEV_UNREGISTER: case NETDEV_CHANGENAME: @@ -808,6 +802,7 @@ int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info) int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info) { + struct net *net = genl_info_net(info); int err; char *bearer; struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1]; @@ -847,7 +842,7 @@ int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info) } rtnl_lock(); - err = tipc_enable_bearer(bearer, domain, prio); + err = tipc_enable_bearer(net, bearer, domain, prio); if (err) { rtnl_unlock(); return err; diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 2c1230ac5dfe..43f683aebbbe 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -165,8 +165,9 @@ extern struct tipc_bearer __rcu *bearer_list[]; * TIPC routines available to supported media types */ -void tipc_rcv(struct sk_buff *skb, struct tipc_bearer *tb_ptr); -int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority); +void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr); +int tipc_enable_bearer(struct net *net, const char *bearer_name, + u32 disc_domain, u32 priority); int tipc_disable_bearer(const char *name); /* diff --git a/net/tipc/config.c b/net/tipc/config.c index 0b3a90ecab6d..28d4272803c4 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -134,7 +134,7 @@ static struct sk_buff *tipc_show_stats(void) return buf; } -static struct sk_buff *cfg_enable_bearer(void) +static struct sk_buff *cfg_enable_bearer(struct net *net) { struct tipc_bearer_config *args; @@ -142,7 +142,7 @@ static struct sk_buff *cfg_enable_bearer(void) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area); - if (tipc_enable_bearer(args->name, + if (tipc_enable_bearer(net, args->name, ntohl(args->disc_domain), ntohl(args->priority))) return tipc_cfg_reply_error_string("unable to enable bearer"); @@ -161,7 +161,7 @@ static struct sk_buff *cfg_disable_bearer(void) return tipc_cfg_reply_none(); } -static struct sk_buff *cfg_set_own_addr(void) +static struct sk_buff *cfg_set_own_addr(struct net *net) { u32 addr; @@ -177,20 +177,21 @@ static struct sk_buff *cfg_set_own_addr(void) if (tipc_own_addr) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (cannot change node address once assigned)"); - if (!tipc_net_start(addr)) + if (!tipc_net_start(net, addr)) return tipc_cfg_reply_none(); return tipc_cfg_reply_error_string("cannot change to network mode"); } -static struct sk_buff *cfg_set_netid(void) +static struct sk_buff *cfg_set_netid(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); - if (value == tipc_net_id) + if (value == tn->net_id) return tipc_cfg_reply_none(); if (value < 1 || value > 9999) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE @@ -198,14 +199,16 @@ static struct sk_buff *cfg_set_netid(void) if (tipc_own_addr) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (cannot change network id once TIPC has joined a network)"); - tipc_net_id = value; + tn->net_id = value; return tipc_cfg_reply_none(); } -struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area, - int request_space, int reply_headroom) +struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, + const void *request_area, int request_space, + int reply_headroom) { struct sk_buff *rep_tlv_buf; + struct tipc_net *tn = net_generic(net, tipc_net_id); rtnl_lock(); @@ -261,19 +264,19 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area rep_tlv_buf = tipc_link_cmd_config(req_tlv_area, req_tlv_space, cmd); break; case TIPC_CMD_ENABLE_BEARER: - rep_tlv_buf = cfg_enable_bearer(); + rep_tlv_buf = cfg_enable_bearer(net); break; case TIPC_CMD_DISABLE_BEARER: rep_tlv_buf = cfg_disable_bearer(); break; case TIPC_CMD_SET_NODE_ADDR: - rep_tlv_buf = cfg_set_own_addr(); + rep_tlv_buf = cfg_set_own_addr(net); break; case TIPC_CMD_SET_NETID: - rep_tlv_buf = cfg_set_netid(); + rep_tlv_buf = cfg_set_netid(net); break; case TIPC_CMD_GET_NETID: - rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); + rep_tlv_buf = tipc_cfg_reply_unsigned(tn->net_id); break; case TIPC_CMD_NOT_NET_ADMIN: rep_tlv_buf = diff --git a/net/tipc/config.h b/net/tipc/config.h index a41a41c58750..9e9b575fc429 100644 --- a/net/tipc/config.h +++ b/net/tipc/config.h @@ -61,7 +61,7 @@ static inline struct sk_buff *tipc_cfg_reply_ultra_string(char *string) return tipc_cfg_reply_string_type(TIPC_TLV_ULTRA_STRING, string); } -struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, +struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, const void *req_tlv_area, int req_tlv_space, int headroom); #endif diff --git a/net/tipc/core.c b/net/tipc/core.c index b6ec3d7c5f51..a2302480d8cf 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -52,6 +52,26 @@ u32 tipc_own_addr __read_mostly; int tipc_net_id __read_mostly; int sysctl_tipc_rmem[3] __read_mostly; /* min/default/max */ +static int __net_init tipc_init_net(struct net *net) +{ + struct tipc_net *tn = net_generic(net, tipc_net_id); + + tn->net_id = 4711; + + return 0; +} + +static void __net_exit tipc_exit_net(struct net *net) +{ +} + +static struct pernet_operations tipc_net_ops = { + .init = tipc_init_net, + .exit = tipc_exit_net, + .id = &tipc_net_id, + .size = sizeof(struct tipc_net), +}; + static int __init tipc_init(void) { int err; @@ -59,7 +79,6 @@ static int __init tipc_init(void) pr_info("Activated (version " TIPC_MOD_VER ")\n"); tipc_own_addr = 0; - tipc_net_id = 4711; sysctl_tipc_rmem[0] = TIPC_CONN_OVERLOAD_LIMIT >> 4 << TIPC_LOW_IMPORTANCE; @@ -69,6 +88,10 @@ static int __init tipc_init(void) get_random_bytes(&tipc_random, sizeof(tipc_random)); + err = register_pernet_subsys(&tipc_net_ops); + if (err) + goto out_pernet; + err = tipc_sk_rht_init(); if (err) goto out_reftbl; @@ -112,12 +135,15 @@ out_netlink: out_nametbl: tipc_sk_rht_destroy(); out_reftbl: + unregister_pernet_subsys(&tipc_net_ops); +out_pernet: pr_err("Unable to start in single node mode\n"); return err; } static void __exit tipc_exit(void) { + unregister_pernet_subsys(&tipc_net_ops); tipc_net_stop(); tipc_bearer_cleanup(); tipc_netlink_stop(); diff --git a/net/tipc/core.h b/net/tipc/core.h index a5b3140f1451..106e8150c3a6 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -57,6 +57,7 @@ #include #include #include +#include #define TIPC_MOD_VER "2.0.0" @@ -75,6 +76,10 @@ extern int sysctl_tipc_named_timeout __read_mostly; */ extern int tipc_random __read_mostly; +struct tipc_net { + int net_id; +}; + #ifdef CONFIG_SYSCTL int tipc_register_sysctl(void); void tipc_unregister_sysctl(void); diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 1a3a98582034..246a23788ded 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -72,12 +72,14 @@ struct tipc_link_req { /** * tipc_disc_init_msg - initialize a link setup message + * @net: the applicable net namespace * @type: message type (request or response) * @b_ptr: ptr to bearer issuing message */ -static void tipc_disc_init_msg(struct sk_buff *buf, u32 type, +static void tipc_disc_init_msg(struct net *net, struct sk_buff *buf, u32 type, struct tipc_bearer *b_ptr) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_msg *msg; u32 dest_domain = b_ptr->domain; @@ -86,7 +88,7 @@ static void tipc_disc_init_msg(struct sk_buff *buf, u32 type, msg_set_non_seq(msg, 1); msg_set_node_sig(msg, tipc_random); msg_set_dest_domain(msg, dest_domain); - msg_set_bc_netid(msg, tipc_net_id); + msg_set_bc_netid(msg, tn->net_id); b_ptr->media->addr2msg(msg_media_addr(msg), &b_ptr->addr); } @@ -111,11 +113,14 @@ static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr, /** * tipc_disc_rcv - handle incoming discovery message (request or response) + * @net: the applicable net namespace * @buf: buffer containing message * @bearer: bearer that message arrived on */ -void tipc_disc_rcv(struct sk_buff *buf, struct tipc_bearer *bearer) +void tipc_disc_rcv(struct net *net, struct sk_buff *buf, + struct tipc_bearer *bearer) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_node *node; struct tipc_link *link; struct tipc_media_addr maddr; @@ -137,7 +142,7 @@ void tipc_disc_rcv(struct sk_buff *buf, struct tipc_bearer *bearer) kfree_skb(buf); /* Ensure message from node is valid and communication is permitted */ - if (net_id != tipc_net_id) + if (net_id != tn->net_id) return; if (maddr.broadcast) return; @@ -248,7 +253,7 @@ void tipc_disc_rcv(struct sk_buff *buf, struct tipc_bearer *bearer) if (respond && (mtyp == DSC_REQ_MSG)) { rbuf = tipc_buf_acquire(INT_H_SIZE); if (rbuf) { - tipc_disc_init_msg(rbuf, DSC_RESP_MSG, bearer); + tipc_disc_init_msg(net, rbuf, DSC_RESP_MSG, bearer); tipc_bearer_send(bearer->identity, rbuf, &maddr); kfree_skb(rbuf); } @@ -341,13 +346,15 @@ exit: /** * tipc_disc_create - create object to send periodic link setup requests + * @net: the applicable net namespace * @b_ptr: ptr to bearer issuing requests * @dest: destination address for request messages * @dest_domain: network domain to which links can be established * * Returns 0 if successful, otherwise -errno. */ -int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest) +int tipc_disc_create(struct net *net, struct tipc_bearer *b_ptr, + struct tipc_media_addr *dest) { struct tipc_link_req *req; @@ -361,7 +368,7 @@ int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest) return -ENOMEM; } - tipc_disc_init_msg(req->buf, DSC_REQ_MSG, b_ptr); + tipc_disc_init_msg(net, req->buf, DSC_REQ_MSG, b_ptr); memcpy(&req->dest, dest, sizeof(*dest)); req->bearer_id = b_ptr->identity; req->domain = b_ptr->domain; @@ -388,15 +395,16 @@ void tipc_disc_delete(struct tipc_link_req *req) /** * tipc_disc_reset - reset object to send periodic link setup requests + * @net: the applicable net namespace * @b_ptr: ptr to bearer issuing requests * @dest_domain: network domain to which links can be established */ -void tipc_disc_reset(struct tipc_bearer *b_ptr) +void tipc_disc_reset(struct net *net, struct tipc_bearer *b_ptr) { struct tipc_link_req *req = b_ptr->link_req; spin_lock_bh(&req->lock); - tipc_disc_init_msg(req->buf, DSC_REQ_MSG, b_ptr); + tipc_disc_init_msg(net, req->buf, DSC_REQ_MSG, b_ptr); req->bearer_id = b_ptr->identity; req->domain = b_ptr->domain; req->num_nodes = 0; diff --git a/net/tipc/discover.h b/net/tipc/discover.h index 515b57392f4d..c9b12770c5ed 100644 --- a/net/tipc/discover.h +++ b/net/tipc/discover.h @@ -39,11 +39,13 @@ struct tipc_link_req; -int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest); +int tipc_disc_create(struct net *net, struct tipc_bearer *b_ptr, + struct tipc_media_addr *dest); void tipc_disc_delete(struct tipc_link_req *req); -void tipc_disc_reset(struct tipc_bearer *b_ptr); +void tipc_disc_reset(struct net *net, struct tipc_bearer *b_ptr); void tipc_disc_add_dest(struct tipc_link_req *req); void tipc_disc_remove_dest(struct tipc_link_req *req); -void tipc_disc_rcv(struct sk_buff *buf, struct tipc_bearer *b_ptr); +void tipc_disc_rcv(struct net *net, struct sk_buff *buf, + struct tipc_bearer *b_ptr); #endif diff --git a/net/tipc/link.c b/net/tipc/link.c index f23105852cb3..248813cb6d68 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -101,10 +101,12 @@ static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { */ #define START_CHANGEOVER 100000u -static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, +static void link_handle_out_of_seq_msg(struct net *net, + struct tipc_link *l_ptr, struct sk_buff *buf); -static void tipc_link_proto_rcv(struct tipc_link *l_ptr, struct sk_buff *buf); -static int tipc_link_tunnel_rcv(struct tipc_node *n_ptr, +static void tipc_link_proto_rcv(struct net *net, struct tipc_link *l_ptr, + struct sk_buff *buf); +static int tipc_link_tunnel_rcv(struct net *net, struct tipc_node *n_ptr, struct sk_buff **buf); static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tol); static void link_state_event(struct tipc_link *l_ptr, u32 event); @@ -113,7 +115,8 @@ static void link_print(struct tipc_link *l_ptr, const char *str); static void tipc_link_sync_xmit(struct tipc_link *l); static void tipc_link_sync_rcv(struct tipc_node *n, struct sk_buff *buf); static int tipc_link_input(struct tipc_link *l, struct sk_buff *buf); -static int tipc_link_prepare_input(struct tipc_link *l, struct sk_buff **buf); +static int tipc_link_prepare_input(struct net *net, struct tipc_link *l, + struct sk_buff **buf); /* * Simple link routines @@ -1063,13 +1066,14 @@ static int link_recv_buf_validate(struct sk_buff *buf) /** * tipc_rcv - process TIPC packets/messages arriving from off-node + * @net: net namespace handler * @skb: TIPC packet * @b_ptr: pointer to bearer message arrived on * * Invoked with no locks held. Bearer pointer must point to a valid bearer * structure (i.e. cannot be NULL), but bearer can be inactive. */ -void tipc_rcv(struct sk_buff *skb, struct tipc_bearer *b_ptr) +void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr) { struct sk_buff_head head; struct tipc_node *n_ptr; @@ -1096,9 +1100,9 @@ void tipc_rcv(struct sk_buff *skb, struct tipc_bearer *b_ptr) if (unlikely(msg_non_seq(msg))) { if (msg_user(msg) == LINK_CONFIG) - tipc_disc_rcv(skb, b_ptr); + tipc_disc_rcv(net, skb, b_ptr); else - tipc_bclink_rcv(skb); + tipc_bclink_rcv(net, skb); continue; } @@ -1159,7 +1163,7 @@ void tipc_rcv(struct sk_buff *skb, struct tipc_bearer *b_ptr) /* Process the incoming packet */ if (unlikely(!link_working_working(l_ptr))) { if (msg_user(msg) == LINK_PROTOCOL) { - tipc_link_proto_rcv(l_ptr, skb); + tipc_link_proto_rcv(net, l_ptr, skb); link_retrieve_defq(l_ptr, &head); tipc_node_unlock(n_ptr); continue; @@ -1179,7 +1183,7 @@ void tipc_rcv(struct sk_buff *skb, struct tipc_bearer *b_ptr) /* Link is now in state WORKING_WORKING */ if (unlikely(seq_no != mod(l_ptr->next_in_no))) { - link_handle_out_of_seq_msg(l_ptr, skb); + link_handle_out_of_seq_msg(net, l_ptr, skb); link_retrieve_defq(l_ptr, &head); tipc_node_unlock(n_ptr); continue; @@ -1193,7 +1197,7 @@ void tipc_rcv(struct sk_buff *skb, struct tipc_bearer *b_ptr) tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); } - if (tipc_link_prepare_input(l_ptr, &skb)) { + if (tipc_link_prepare_input(net, l_ptr, &skb)) { tipc_node_unlock(n_ptr); continue; } @@ -1216,7 +1220,8 @@ discard: * * Node lock must be held */ -static int tipc_link_prepare_input(struct tipc_link *l, struct sk_buff **buf) +static int tipc_link_prepare_input(struct net *net, struct tipc_link *l, + struct sk_buff **buf) { struct tipc_node *n; struct tipc_msg *msg; @@ -1226,7 +1231,7 @@ static int tipc_link_prepare_input(struct tipc_link *l, struct sk_buff **buf) msg = buf_msg(*buf); switch (msg_user(msg)) { case CHANGEOVER_PROTOCOL: - if (tipc_link_tunnel_rcv(n, buf)) + if (tipc_link_tunnel_rcv(net, n, buf)) res = 0; break; case MSG_FRAGMENTER: @@ -1325,13 +1330,14 @@ u32 tipc_link_defer_pkt(struct sk_buff_head *list, struct sk_buff *skb) /* * link_handle_out_of_seq_msg - handle arrival of out-of-sequence packet */ -static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, +static void link_handle_out_of_seq_msg(struct net *net, + struct tipc_link *l_ptr, struct sk_buff *buf) { u32 seq_no = buf_seqno(buf); if (likely(msg_user(buf_msg(buf)) == LINK_PROTOCOL)) { - tipc_link_proto_rcv(l_ptr, buf); + tipc_link_proto_rcv(net, l_ptr, buf); return; } @@ -1455,7 +1461,8 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg, * Note that network plane id propagates through the network, and may * change at any time. The node with lowest address rules */ -static void tipc_link_proto_rcv(struct tipc_link *l_ptr, struct sk_buff *buf) +static void tipc_link_proto_rcv(struct net *net, struct tipc_link *l_ptr, + struct sk_buff *buf) { u32 rec_gap = 0; u32 max_pkt_info; @@ -1571,7 +1578,7 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr, struct sk_buff *buf) /* Protocol message before retransmits, reduce loss risk */ if (l_ptr->owner->bclink.recv_permitted) - tipc_bclink_update_link_state(l_ptr->owner, + tipc_bclink_update_link_state(net, l_ptr->owner, msg_last_bcast(msg)); if (rec_gap || (msg_probe(msg))) { @@ -1748,7 +1755,7 @@ static struct sk_buff *buf_extract(struct sk_buff *skb, u32 from_pos) /* tipc_link_dup_rcv(): Receive a tunnelled DUPLICATE_MSG packet. * Owner node is locked. */ -static void tipc_link_dup_rcv(struct tipc_link *l_ptr, +static void tipc_link_dup_rcv(struct net *net, struct tipc_link *l_ptr, struct sk_buff *t_buf) { struct sk_buff *buf; @@ -1763,7 +1770,7 @@ static void tipc_link_dup_rcv(struct tipc_link *l_ptr, } /* Add buffer to deferred queue, if applicable: */ - link_handle_out_of_seq_msg(l_ptr, buf); + link_handle_out_of_seq_msg(net, l_ptr, buf); } /* tipc_link_failover_rcv(): Receive a tunnelled ORIGINAL_MSG packet @@ -1817,7 +1824,7 @@ exit: * returned to the active link for delivery upwards. * Owner node is locked. */ -static int tipc_link_tunnel_rcv(struct tipc_node *n_ptr, +static int tipc_link_tunnel_rcv(struct net *net, struct tipc_node *n_ptr, struct sk_buff **buf) { struct sk_buff *t_buf = *buf; @@ -1835,7 +1842,7 @@ static int tipc_link_tunnel_rcv(struct tipc_node *n_ptr, goto exit; if (msg_type(t_msg) == DUPLICATE_MSG) - tipc_link_dup_rcv(l_ptr, t_buf); + tipc_link_dup_rcv(net, l_ptr, t_buf); else if (msg_type(t_msg) == ORIGINAL_MSG) *buf = tipc_link_failover_rcv(l_ptr, t_buf); else diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 35523fb6668c..a38f6a680df1 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -34,6 +34,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include #include "core.h" #include "msg.h" #include "addr.h" @@ -214,6 +215,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, skb = tipc_buf_acquire(msz); if (unlikely(!skb)) return -ENOMEM; + skb_orphan(skb); __skb_queue_tail(list, skb); skb_copy_to_linear_data(skb, mhdr, mhsz); pktpos = skb->data + mhsz; @@ -234,6 +236,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, skb = tipc_buf_acquire(pktmax); if (!skb) return -ENOMEM; + skb_orphan(skb); __skb_queue_tail(list, skb); pktpos = skb->data; skb_copy_to_linear_data(skb, &pkthdr, INT_H_SIZE); @@ -267,6 +270,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, rc = -ENOMEM; goto error; } + skb_orphan(skb); __skb_queue_tail(list, skb); msg_set_type(&pkthdr, FRAGMENT); msg_set_size(&pkthdr, pktsz); diff --git a/net/tipc/net.c b/net/tipc/net.c index cf13df3cde8f..5ce9d628f2d0 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -108,8 +108,9 @@ static const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1] = { * - A local spin_lock protecting the queue of subscriber events. */ -int tipc_net_start(u32 addr) +int tipc_net_start(struct net *net, u32 addr) { + struct tipc_net *tn = net_generic(net, tipc_net_id); char addr_string[16]; int res; @@ -125,7 +126,8 @@ int tipc_net_start(u32 addr) pr_info("Started in network mode\n"); pr_info("Own node address %s, network identity %u\n", - tipc_addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); + tipc_addr_string_fill(addr_string, tipc_own_addr), + tn->net_id); return 0; } @@ -144,8 +146,9 @@ void tipc_net_stop(void) pr_info("Left network mode\n"); } -static int __tipc_nl_add_net(struct tipc_nl_msg *msg) +static int __tipc_nl_add_net(struct net *net, struct tipc_nl_msg *msg) { + struct tipc_net *tn = net_generic(net, tipc_net_id); void *hdr; struct nlattr *attrs; @@ -158,7 +161,7 @@ static int __tipc_nl_add_net(struct tipc_nl_msg *msg) if (!attrs) goto msg_full; - if (nla_put_u32(msg->skb, TIPC_NLA_NET_ID, tipc_net_id)) + if (nla_put_u32(msg->skb, TIPC_NLA_NET_ID, tn->net_id)) goto attr_msg_full; nla_nest_end(msg->skb, attrs); @@ -176,6 +179,7 @@ msg_full: int tipc_nl_net_dump(struct sk_buff *skb, struct netlink_callback *cb) { + struct net *net = sock_net(skb->sk); int err; int done = cb->args[0]; struct tipc_nl_msg msg; @@ -187,7 +191,7 @@ int tipc_nl_net_dump(struct sk_buff *skb, struct netlink_callback *cb) msg.portid = NETLINK_CB(cb->skb).portid; msg.seq = cb->nlh->nlmsg_seq; - err = __tipc_nl_add_net(&msg); + err = __tipc_nl_add_net(net, &msg); if (err) goto out; @@ -200,8 +204,10 @@ out: int tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info) { - int err; + struct net *net = genl_info_net(info); + struct tipc_net *tn = net_generic(net, tipc_net_id); struct nlattr *attrs[TIPC_NLA_NET_MAX + 1]; + int err; if (!info->attrs[TIPC_NLA_NET]) return -EINVAL; @@ -223,7 +229,7 @@ int tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info) if (val < 1 || val > 9999) return -EINVAL; - tipc_net_id = val; + tn->net_id = val; } if (attrs[TIPC_NLA_NET_ADDR]) { @@ -238,7 +244,7 @@ int tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info) return -EINVAL; rtnl_lock(); - tipc_net_start(addr); + tipc_net_start(net, addr); rtnl_unlock(); } diff --git a/net/tipc/net.h b/net/tipc/net.h index a81c1b9eb150..2c4812f8408f 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h @@ -39,7 +39,7 @@ #include -int tipc_net_start(u32 addr); +int tipc_net_start(struct net *net, u32 addr); void tipc_net_stop(void); diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index b891e3905bc4..282b59681484 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -46,6 +46,7 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info) { + struct net *net = genl_info_net(info); struct sk_buff *rep_buf; struct nlmsghdr *rep_nlh; struct nlmsghdr *req_nlh = info->nlhdr; @@ -58,10 +59,11 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info) else cmd = req_userhdr->cmd; - rep_buf = tipc_cfg_do_cmd(req_userhdr->dest, cmd, - nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN, - nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN), - hdr_space); + rep_buf = tipc_cfg_do_cmd(net, req_userhdr->dest, cmd, + nlmsg_data(req_nlh) + GENL_HDRLEN + + TIPC_GENL_HDRLEN, + nlmsg_attrlen(req_nlh, GENL_HDRLEN + + TIPC_GENL_HDRLEN), hdr_space); if (rep_buf) { skb_push(rep_buf, hdr_space); -- cgit v1.2.3-70-g09d2 From f2f9800d4955a96d92896841d8ba9b04201deaa1 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Fri, 9 Jan 2015 15:27:05 +0800 Subject: tipc: make tipc node table aware of net namespace Global variables associated with node table are below: - node table list (node_htable) - node hash table list (tipc_node_list) - node table lock (node_list_lock) - node number counter (tipc_num_nodes) - node link number counter (tipc_num_links) To make node table support namespace, above global variables must be moved to tipc_net structure in order to keep secret for different namespaces. As a consequence, these variables are allocated and initialized when namespace is created, and deallocated when namespace is destroyed. After the change, functions associated with these variables have to utilize a namespace pointer to access them. So adding namespace pointer as a parameter of these functions is the major change made in the commit. Signed-off-by: Ying Xue Tested-by: Tero Aho Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/addr.h | 2 + net/tipc/bcast.c | 24 +++++----- net/tipc/bcast.h | 4 +- net/tipc/bearer.c | 25 +++++----- net/tipc/bearer.h | 4 +- net/tipc/config.c | 21 ++++---- net/tipc/core.c | 4 +- net/tipc/core.h | 9 ++++ net/tipc/discover.c | 4 +- net/tipc/link.c | 107 +++++++++++++++++++++++++---------------- net/tipc/link.h | 24 ++++++---- net/tipc/name_distr.c | 57 ++++++++++++---------- net/tipc/name_distr.h | 10 ++-- net/tipc/name_table.c | 16 ++++--- net/tipc/name_table.h | 8 ++-- net/tipc/net.c | 11 +++-- net/tipc/net.h | 2 +- net/tipc/node.c | 130 +++++++++++++++++++++++++++----------------------- net/tipc/node.h | 35 +++++++------- net/tipc/socket.c | 72 +++++++++++++++++----------- net/tipc/socket.h | 4 +- 21 files changed, 329 insertions(+), 244 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/addr.h b/net/tipc/addr.h index 60b00ab93d74..3e1f18e29f1e 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h @@ -40,6 +40,8 @@ #define TIPC_ZONE_MASK 0xff000000u #define TIPC_CLUSTER_MASK 0xfffff000u +extern u32 tipc_own_addr __read_mostly; + static inline u32 tipc_zone_mask(u32 addr) { return addr & TIPC_ZONE_MASK; diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index f98231138916..816c0e49319f 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -232,13 +232,12 @@ static void bclink_retransmit_pkt(u32 after, u32 to) * * Called with no locks taken */ -void tipc_bclink_wakeup_users(void) +void tipc_bclink_wakeup_users(struct net *net) { struct sk_buff *skb; while ((skb = skb_dequeue(&bclink->link.waiting_sks))) - tipc_sk_rcv(skb); - + tipc_sk_rcv(net, skb); } /** @@ -385,9 +384,9 @@ void tipc_bclink_update_link_state(struct net *net, struct tipc_node *n_ptr, * Delay any upcoming NACK by this node if another node has already * requested the first message this node is going to ask for. */ -static void bclink_peek_nack(struct tipc_msg *msg) +static void bclink_peek_nack(struct net *net, struct tipc_msg *msg) { - struct tipc_node *n_ptr = tipc_node_find(msg_destnode(msg)); + struct tipc_node *n_ptr = tipc_node_find(net, msg_destnode(msg)); if (unlikely(!n_ptr)) return; @@ -404,11 +403,12 @@ static void bclink_peek_nack(struct tipc_msg *msg) /* tipc_bclink_xmit - broadcast buffer chain to all nodes in cluster * and to identified node local sockets + * @net: the applicable net namespace * @list: chain of buffers containing message * Consumes the buffer chain, except when returning -ELINKCONG * Returns 0 if success, otherwise errno: -ELINKCONG,-EHOSTUNREACH,-EMSGSIZE */ -int tipc_bclink_xmit(struct sk_buff_head *list) +int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list) { int rc = 0; int bc = 0; @@ -443,7 +443,7 @@ int tipc_bclink_xmit(struct sk_buff_head *list) /* Deliver message clone */ if (likely(!rc)) - tipc_sk_mcast_rcv(skb); + tipc_sk_mcast_rcv(net, skb); else kfree_skb(skb); @@ -491,7 +491,7 @@ void tipc_bclink_rcv(struct net *net, struct sk_buff *buf) if (msg_mc_netid(msg) != tn->net_id) goto exit; - node = tipc_node_find(msg_prevnode(msg)); + node = tipc_node_find(net, msg_prevnode(msg)); if (unlikely(!node)) goto exit; @@ -514,7 +514,7 @@ void tipc_bclink_rcv(struct net *net, struct sk_buff *buf) tipc_bclink_unlock(); } else { tipc_node_unlock(node); - bclink_peek_nack(msg); + bclink_peek_nack(net, msg); } goto exit; } @@ -532,7 +532,7 @@ receive: tipc_bclink_unlock(); tipc_node_unlock(node); if (likely(msg_mcast(msg))) - tipc_sk_mcast_rcv(buf); + tipc_sk_mcast_rcv(net, buf); else kfree_skb(buf); } else if (msg_user(msg) == MSG_BUNDLER) { @@ -542,7 +542,7 @@ receive: bcl->stats.recv_bundled += msg_msgcnt(msg); tipc_bclink_unlock(); tipc_node_unlock(node); - tipc_link_bundle_rcv(buf); + tipc_link_bundle_rcv(net, buf); } else if (msg_user(msg) == MSG_FRAGMENTER) { tipc_buf_append(&node->bclink.reasm_buf, &buf); if (unlikely(!buf && !node->bclink.reasm_buf)) @@ -563,7 +563,7 @@ receive: bclink_accept_pkt(node, seqno); tipc_bclink_unlock(); tipc_node_unlock(node); - tipc_named_rcv(buf); + tipc_named_rcv(net, buf); } else { tipc_bclink_lock(); bclink_accept_pkt(node, seqno); diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index a5fd22438aed..fd0d17a76493 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h @@ -101,8 +101,8 @@ int tipc_bclink_reset_stats(void); int tipc_bclink_set_queue_limits(u32 limit); void tipc_bcbearer_sort(struct tipc_node_map *nm_ptr, u32 node, bool action); uint tipc_bclink_get_mtu(void); -int tipc_bclink_xmit(struct sk_buff_head *list); -void tipc_bclink_wakeup_users(void); +int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list); +void tipc_bclink_wakeup_users(struct net *net); int tipc_nl_add_bc_link(struct tipc_nl_msg *msg); #endif diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index cdd30337dc5e..a735c08e9d90 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -69,7 +69,8 @@ static const struct nla_policy tipc_nl_media_policy[TIPC_NLA_MEDIA_MAX + 1] = { struct tipc_bearer __rcu *bearer_list[MAX_BEARERS + 1]; -static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down); +static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr, + bool shutting_down); /** * tipc_media_find - locates specified media object by name @@ -364,7 +365,7 @@ restart: res = tipc_disc_create(net, b_ptr, &b_ptr->bcast_addr); if (res) { - bearer_disable(b_ptr, false); + bearer_disable(net, b_ptr, false); pr_warn("Bearer <%s> rejected, discovery object creation failed\n", name); return -EINVAL; @@ -384,7 +385,7 @@ restart: static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b_ptr) { pr_info("Resetting bearer <%s>\n", b_ptr->name); - tipc_link_reset_list(b_ptr->identity); + tipc_link_reset_list(net, b_ptr->identity); tipc_disc_reset(net, b_ptr); return 0; } @@ -394,14 +395,15 @@ static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b_ptr) * * Note: This routine assumes caller holds RTNL lock. */ -static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down) +static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr, + bool shutting_down) { u32 i; pr_info("Disabling bearer <%s>\n", b_ptr->name); b_ptr->media->disable_media(b_ptr); - tipc_link_delete_list(b_ptr->identity, shutting_down); + tipc_link_delete_list(net, b_ptr->identity, shutting_down); if (b_ptr->link_req) tipc_disc_delete(b_ptr->link_req); @@ -414,7 +416,7 @@ static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down) kfree_rcu(b_ptr, rcu); } -int tipc_disable_bearer(const char *name) +int tipc_disable_bearer(struct net *net, const char *name) { struct tipc_bearer *b_ptr; int res; @@ -424,7 +426,7 @@ int tipc_disable_bearer(const char *name) pr_warn("Attempt to disable unknown bearer <%s>\n", name); res = -EINVAL; } else { - bearer_disable(b_ptr, false); + bearer_disable(net, b_ptr, false); res = 0; } return res; @@ -593,7 +595,7 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, break; case NETDEV_UNREGISTER: case NETDEV_CHANGENAME: - bearer_disable(b_ptr, false); + bearer_disable(dev_net(dev), b_ptr, false); break; } return NOTIFY_OK; @@ -626,7 +628,7 @@ void tipc_bearer_cleanup(void) dev_remove_pack(&tipc_packet_type); } -void tipc_bearer_stop(void) +void tipc_bearer_stop(struct net *net) { struct tipc_bearer *b_ptr; u32 i; @@ -634,7 +636,7 @@ void tipc_bearer_stop(void) for (i = 0; i < MAX_BEARERS; i++) { b_ptr = rtnl_dereference(bearer_list[i]); if (b_ptr) { - bearer_disable(b_ptr, true); + bearer_disable(net, b_ptr, true); bearer_list[i] = NULL; } } @@ -772,6 +774,7 @@ int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info) char *name; struct tipc_bearer *bearer; struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1]; + struct net *net = genl_info_net(info); if (!info->attrs[TIPC_NLA_BEARER]) return -EINVAL; @@ -794,7 +797,7 @@ int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info) return -EINVAL; } - bearer_disable(bearer, false); + bearer_disable(net, bearer, false); rtnl_unlock(); return 0; diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 43f683aebbbe..91a8eeea309c 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -168,7 +168,7 @@ extern struct tipc_bearer __rcu *bearer_list[]; void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr); int tipc_enable_bearer(struct net *net, const char *bearer_name, u32 disc_domain, u32 priority); -int tipc_disable_bearer(const char *name); +int tipc_disable_bearer(struct net *net, const char *name); /* * Routines made available to TIPC by supported media types @@ -205,7 +205,7 @@ struct tipc_bearer *tipc_bearer_find(const char *name); struct tipc_media *tipc_media_find(const char *name); int tipc_bearer_setup(void); void tipc_bearer_cleanup(void); -void tipc_bearer_stop(void); +void tipc_bearer_stop(struct net *net); void tipc_bearer_send(u32 bearer_id, struct sk_buff *buf, struct tipc_media_addr *dest); diff --git a/net/tipc/config.c b/net/tipc/config.c index 28d4272803c4..cf2d417ad488 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -150,12 +150,12 @@ static struct sk_buff *cfg_enable_bearer(struct net *net) return tipc_cfg_reply_none(); } -static struct sk_buff *cfg_disable_bearer(void) +static struct sk_buff *cfg_disable_bearer(struct net *net) { if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area))) + if (tipc_disable_bearer(net, (char *)TLV_DATA(req_tlv_area))) return tipc_cfg_reply_error_string("unable to disable bearer"); return tipc_cfg_reply_none(); @@ -232,16 +232,20 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, rep_tlv_buf = tipc_cfg_reply_none(); break; case TIPC_CMD_GET_NODES: - rep_tlv_buf = tipc_node_get_nodes(req_tlv_area, req_tlv_space); + rep_tlv_buf = tipc_node_get_nodes(net, req_tlv_area, + req_tlv_space); break; case TIPC_CMD_GET_LINKS: - rep_tlv_buf = tipc_node_get_links(req_tlv_area, req_tlv_space); + rep_tlv_buf = tipc_node_get_links(net, req_tlv_area, + req_tlv_space); break; case TIPC_CMD_SHOW_LINK_STATS: - rep_tlv_buf = tipc_link_cmd_show_stats(req_tlv_area, req_tlv_space); + rep_tlv_buf = tipc_link_cmd_show_stats(net, req_tlv_area, + req_tlv_space); break; case TIPC_CMD_RESET_LINK_STATS: - rep_tlv_buf = tipc_link_cmd_reset_stats(req_tlv_area, req_tlv_space); + rep_tlv_buf = tipc_link_cmd_reset_stats(net, req_tlv_area, + req_tlv_space); break; case TIPC_CMD_SHOW_NAME_TABLE: rep_tlv_buf = tipc_nametbl_get(req_tlv_area, req_tlv_space); @@ -261,13 +265,14 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, case TIPC_CMD_SET_LINK_TOL: case TIPC_CMD_SET_LINK_PRI: case TIPC_CMD_SET_LINK_WINDOW: - rep_tlv_buf = tipc_link_cmd_config(req_tlv_area, req_tlv_space, cmd); + rep_tlv_buf = tipc_link_cmd_config(net, req_tlv_area, + req_tlv_space, cmd); break; case TIPC_CMD_ENABLE_BEARER: rep_tlv_buf = cfg_enable_bearer(net); break; case TIPC_CMD_DISABLE_BEARER: - rep_tlv_buf = cfg_disable_bearer(); + rep_tlv_buf = cfg_disable_bearer(net); break; case TIPC_CMD_SET_NODE_ADDR: rep_tlv_buf = cfg_set_own_addr(net); diff --git a/net/tipc/core.c b/net/tipc/core.c index a2302480d8cf..7b8443938caf 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -57,12 +57,15 @@ static int __net_init tipc_init_net(struct net *net) struct tipc_net *tn = net_generic(net, tipc_net_id); tn->net_id = 4711; + INIT_LIST_HEAD(&tn->node_list); + spin_lock_init(&tn->node_list_lock); return 0; } static void __net_exit tipc_exit_net(struct net *net) { + tipc_net_stop(net); } static struct pernet_operations tipc_net_ops = { @@ -144,7 +147,6 @@ out_pernet: static void __exit tipc_exit(void) { unregister_pernet_subsys(&tipc_net_ops); - tipc_net_stop(); tipc_bearer_cleanup(); tipc_netlink_stop(); tipc_subscr_stop(); diff --git a/net/tipc/core.h b/net/tipc/core.h index 106e8150c3a6..4fb113397e7b 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -59,6 +59,8 @@ #include #include +#include "node.h" + #define TIPC_MOD_VER "2.0.0" int tipc_snprintf(char *buf, int len, const char *fmt, ...); @@ -78,6 +80,13 @@ extern int tipc_random __read_mostly; struct tipc_net { int net_id; + + /* Node table and node list */ + spinlock_t node_list_lock; + struct hlist_head node_htable[NODE_HTABLE_SIZE]; + struct list_head node_list; + u32 num_nodes; + u32 num_links; }; #ifdef CONFIG_SYSCTL diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 246a23788ded..f0fd8b449aef 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -162,9 +162,9 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf, return; /* Locate, or if necessary, create, node: */ - node = tipc_node_find(onode); + node = tipc_node_find(net, onode); if (!node) - node = tipc_node_create(onode); + node = tipc_node_create(net, onode); if (!node) return; diff --git a/net/tipc/link.c b/net/tipc/link.c index 248813cb6d68..f6505652742e 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -114,7 +114,8 @@ static void link_reset_statistics(struct tipc_link *l_ptr); static void link_print(struct tipc_link *l_ptr, const char *str); static void tipc_link_sync_xmit(struct tipc_link *l); static void tipc_link_sync_rcv(struct tipc_node *n, struct sk_buff *buf); -static int tipc_link_input(struct tipc_link *l, struct sk_buff *buf); +static int tipc_link_input(struct net *net, struct tipc_link *l, + struct sk_buff *buf); static int tipc_link_prepare_input(struct net *net, struct tipc_link *l, struct sk_buff **buf); @@ -310,13 +311,15 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, return l_ptr; } -void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down) +void tipc_link_delete_list(struct net *net, unsigned int bearer_id, + bool shutting_down) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_link *l_ptr; struct tipc_node *n_ptr; rcu_read_lock(); - list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { + list_for_each_entry_rcu(n_ptr, &tn->node_list, list) { tipc_node_lock(n_ptr); l_ptr = n_ptr->links[bearer_id]; if (l_ptr) { @@ -451,13 +454,14 @@ void tipc_link_reset(struct tipc_link *l_ptr) link_reset_statistics(l_ptr); } -void tipc_link_reset_list(unsigned int bearer_id) +void tipc_link_reset_list(struct net *net, unsigned int bearer_id) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_link *l_ptr; struct tipc_node *n_ptr; rcu_read_lock(); - list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { + list_for_each_entry_rcu(n_ptr, &tn->node_list, list) { tipc_node_lock(n_ptr); l_ptr = n_ptr->links[bearer_id]; if (l_ptr) @@ -773,16 +777,18 @@ static int __tipc_link_xmit_skb(struct tipc_link *link, struct sk_buff *skb) return __tipc_link_xmit(link, &head); } -int tipc_link_xmit_skb(struct sk_buff *skb, u32 dnode, u32 selector) +int tipc_link_xmit_skb(struct net *net, struct sk_buff *skb, u32 dnode, + u32 selector) { struct sk_buff_head head; skb2list(skb, &head); - return tipc_link_xmit(&head, dnode, selector); + return tipc_link_xmit(net, &head, dnode, selector); } /** * tipc_link_xmit() is the general link level function for message sending + * @net: the applicable net namespace * @list: chain of buffers containing message * @dsz: amount of user data to be sent * @dnode: address of destination node @@ -790,13 +796,14 @@ int tipc_link_xmit_skb(struct sk_buff *skb, u32 dnode, u32 selector) * Consumes the buffer chain, except when returning -ELINKCONG * Returns 0 if success, otherwise errno: -ELINKCONG,-EHOSTUNREACH,-EMSGSIZE */ -int tipc_link_xmit(struct sk_buff_head *list, u32 dnode, u32 selector) +int tipc_link_xmit(struct net *net, struct sk_buff_head *list, u32 dnode, + u32 selector) { struct tipc_link *link = NULL; struct tipc_node *node; int rc = -EHOSTUNREACH; - node = tipc_node_find(dnode); + node = tipc_node_find(net, dnode); if (node) { tipc_node_lock(node); link = node->active_links[selector & 1]; @@ -813,7 +820,7 @@ int tipc_link_xmit(struct sk_buff_head *list, u32 dnode, u32 selector) * buffer, we just need to dequeue one SKB buffer from the * head list. */ - return tipc_sk_rcv(__skb_dequeue(list)); + return tipc_sk_rcv(net, __skb_dequeue(list)); } __skb_queue_purge(list); @@ -1066,7 +1073,7 @@ static int link_recv_buf_validate(struct sk_buff *buf) /** * tipc_rcv - process TIPC packets/messages arriving from off-node - * @net: net namespace handler + * @net: the applicable net namespace * @skb: TIPC packet * @b_ptr: pointer to bearer message arrived on * @@ -1112,7 +1119,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr) goto discard; /* Locate neighboring node that sent message */ - n_ptr = tipc_node_find(msg_prevnode(msg)); + n_ptr = tipc_node_find(net, msg_prevnode(msg)); if (unlikely(!n_ptr)) goto discard; tipc_node_lock(n_ptr); @@ -1203,7 +1210,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr) } tipc_node_unlock(n_ptr); - if (tipc_link_input(l_ptr, skb) != 0) + if (tipc_link_input(net, l_ptr, skb) != 0) goto discard; continue; unlock_discard: @@ -1263,7 +1270,8 @@ static int tipc_link_prepare_input(struct net *net, struct tipc_link *l, /** * tipc_link_input - Deliver message too higher layers */ -static int tipc_link_input(struct tipc_link *l, struct sk_buff *buf) +static int tipc_link_input(struct net *net, struct tipc_link *l, + struct sk_buff *buf) { struct tipc_msg *msg = buf_msg(buf); int res = 0; @@ -1274,13 +1282,13 @@ static int tipc_link_input(struct tipc_link *l, struct sk_buff *buf) case TIPC_HIGH_IMPORTANCE: case TIPC_CRITICAL_IMPORTANCE: case CONN_MANAGER: - tipc_sk_rcv(buf); + tipc_sk_rcv(net, buf); break; case NAME_DISTRIBUTOR: - tipc_named_rcv(buf); + tipc_named_rcv(net, buf); break; case MSG_BUNDLER: - tipc_link_bundle_rcv(buf); + tipc_link_bundle_rcv(net, buf); break; default: res = -EINVAL; @@ -1855,7 +1863,7 @@ exit: /* * Bundler functionality: */ -void tipc_link_bundle_rcv(struct sk_buff *buf) +void tipc_link_bundle_rcv(struct net *net, struct sk_buff *buf) { u32 msgcount = msg_msgcnt(buf_msg(buf)); u32 pos = INT_H_SIZE; @@ -1872,13 +1880,13 @@ void tipc_link_bundle_rcv(struct sk_buff *buf) pos += align(msg_size(omsg)); if (msg_isdata(omsg)) { if (unlikely(msg_type(omsg) == TIPC_MCAST_MSG)) - tipc_sk_mcast_rcv(obuf); + tipc_sk_mcast_rcv(net, obuf); else - tipc_sk_rcv(obuf); + tipc_sk_rcv(net, obuf); } else if (msg_user(omsg) == CONN_MANAGER) { - tipc_sk_rcv(obuf); + tipc_sk_rcv(net, obuf); } else if (msg_user(omsg) == NAME_DISTRIBUTOR) { - tipc_named_rcv(obuf); + tipc_named_rcv(net, obuf); } else { pr_warn("Illegal bundled msg: %u\n", msg_user(omsg)); kfree_skb(obuf); @@ -1919,14 +1927,17 @@ void tipc_link_set_queue_limits(struct tipc_link *l_ptr, u32 window) } /* tipc_link_find_owner - locate owner node of link by link's name + * @net: the applicable net namespace * @name: pointer to link name string * @bearer_id: pointer to index in 'node->links' array where the link was found. * * Returns pointer to node owning the link, or 0 if no matching link is found. */ -static struct tipc_node *tipc_link_find_owner(const char *link_name, +static struct tipc_node *tipc_link_find_owner(struct net *net, + const char *link_name, unsigned int *bearer_id) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_link *l_ptr; struct tipc_node *n_ptr; struct tipc_node *found_node = NULL; @@ -1934,7 +1945,7 @@ static struct tipc_node *tipc_link_find_owner(const char *link_name, *bearer_id = 0; rcu_read_lock(); - list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { + list_for_each_entry_rcu(n_ptr, &tn->node_list, list) { tipc_node_lock(n_ptr); for (i = 0; i < MAX_BEARERS; i++) { l_ptr = n_ptr->links[i]; @@ -1978,6 +1989,7 @@ static int link_value_is_valid(u16 cmd, u32 new_value) /** * link_cmd_set_value - change priority/tolerance/window for link/bearer/media + * @net: the applicable net namespace * @name: ptr to link, bearer, or media name * @new_value: new value of link, bearer, or media setting * @cmd: which link, bearer, or media attribute to set (TIPC_CMD_SET_LINK_*) @@ -1986,7 +1998,8 @@ static int link_value_is_valid(u16 cmd, u32 new_value) * * Returns 0 if value updated and negative value on error. */ -static int link_cmd_set_value(const char *name, u32 new_value, u16 cmd) +static int link_cmd_set_value(struct net *net, const char *name, u32 new_value, + u16 cmd) { struct tipc_node *node; struct tipc_link *l_ptr; @@ -1995,7 +2008,7 @@ static int link_cmd_set_value(const char *name, u32 new_value, u16 cmd) int bearer_id; int res = 0; - node = tipc_link_find_owner(name, &bearer_id); + node = tipc_link_find_owner(net, name, &bearer_id); if (node) { tipc_node_lock(node); l_ptr = node->links[bearer_id]; @@ -2063,8 +2076,8 @@ static int link_cmd_set_value(const char *name, u32 new_value, u16 cmd) return res; } -struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space, - u16 cmd) +struct sk_buff *tipc_link_cmd_config(struct net *net, const void *req_tlv_area, + int req_tlv_space, u16 cmd) { struct tipc_link_config *args; u32 new_value; @@ -2088,7 +2101,7 @@ struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space " (cannot change setting on broadcast link)"); } - res = link_cmd_set_value(args->name, new_value, cmd); + res = link_cmd_set_value(net, args->name, new_value, cmd); if (res) return tipc_cfg_reply_error_string("cannot change link setting"); @@ -2106,7 +2119,9 @@ static void link_reset_statistics(struct tipc_link *l_ptr) l_ptr->stats.recv_info = l_ptr->next_in_no; } -struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space) +struct sk_buff *tipc_link_cmd_reset_stats(struct net *net, + const void *req_tlv_area, + int req_tlv_space) { char *link_name; struct tipc_link *l_ptr; @@ -2122,7 +2137,7 @@ struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_ return tipc_cfg_reply_error_string("link not found"); return tipc_cfg_reply_none(); } - node = tipc_link_find_owner(link_name, &bearer_id); + node = tipc_link_find_owner(net, link_name, &bearer_id); if (!node) return tipc_cfg_reply_error_string("link not found"); @@ -2147,13 +2162,15 @@ static u32 percent(u32 count, u32 total) /** * tipc_link_stats - print link statistics + * @net: the applicable net namespace * @name: link name * @buf: print buffer area * @buf_size: size of print buffer area * * Returns length of print buffer data string (or 0 if error) */ -static int tipc_link_stats(const char *name, char *buf, const u32 buf_size) +static int tipc_link_stats(struct net *net, const char *name, char *buf, + const u32 buf_size) { struct tipc_link *l; struct tipc_stats *s; @@ -2166,7 +2183,7 @@ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size) if (!strcmp(name, tipc_bclink_name)) return tipc_bclink_stats(buf, buf_size); - node = tipc_link_find_owner(name, &bearer_id); + node = tipc_link_find_owner(net, name, &bearer_id); if (!node) return 0; @@ -2243,7 +2260,9 @@ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size) return ret; } -struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space) +struct sk_buff *tipc_link_cmd_show_stats(struct net *net, + const void *req_tlv_area, + int req_tlv_space) { struct sk_buff *buf; struct tlv_desc *rep_tlv; @@ -2261,7 +2280,7 @@ struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_s rep_tlv = (struct tlv_desc *)buf->data; pb = TLV_DATA(rep_tlv); pb_len = ULTRA_STRING_MAX_LEN; - str_len = tipc_link_stats((char *)TLV_DATA(req_tlv_area), + str_len = tipc_link_stats(net, (char *)TLV_DATA(req_tlv_area), pb, pb_len); if (!str_len) { kfree_skb(buf); @@ -2343,6 +2362,7 @@ int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info) struct tipc_link *link; struct tipc_node *node; struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; + struct net *net = genl_info_net(info); if (!info->attrs[TIPC_NLA_LINK]) return -EINVAL; @@ -2358,7 +2378,7 @@ int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info) name = nla_data(attrs[TIPC_NLA_LINK_NAME]); - node = tipc_link_find_owner(name, &bearer_id); + node = tipc_link_find_owner(net, name, &bearer_id); if (!node) return -EINVAL; @@ -2567,6 +2587,8 @@ static int __tipc_nl_add_node_links(struct tipc_nl_msg *msg, int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb) { + struct net *net = sock_net(skb->sk); + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_node *node; struct tipc_nl_msg msg; u32 prev_node = cb->args[0]; @@ -2584,7 +2606,7 @@ int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb) rcu_read_lock(); if (prev_node) { - node = tipc_node_find(prev_node); + node = tipc_node_find(net, prev_node); if (!node) { /* We never set seq or call nl_dump_check_consistent() * this means that setting prev_seq here will cause the @@ -2596,7 +2618,8 @@ int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb) goto out; } - list_for_each_entry_continue_rcu(node, &tipc_node_list, list) { + list_for_each_entry_continue_rcu(node, &tn->node_list, + list) { tipc_node_lock(node); err = __tipc_nl_add_node_links(&msg, node, &prev_link); tipc_node_unlock(node); @@ -2610,7 +2633,7 @@ int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb) if (err) goto out; - list_for_each_entry_rcu(node, &tipc_node_list, list) { + list_for_each_entry_rcu(node, &tn->node_list, list) { tipc_node_lock(node); err = __tipc_nl_add_node_links(&msg, node, &prev_link); tipc_node_unlock(node); @@ -2633,6 +2656,7 @@ out: int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info) { + struct net *net = genl_info_net(info); struct sk_buff *ans_skb; struct tipc_nl_msg msg; struct tipc_link *link; @@ -2645,7 +2669,7 @@ int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info) return -EINVAL; name = nla_data(info->attrs[TIPC_NLA_LINK_NAME]); - node = tipc_link_find_owner(name, &bearer_id); + node = tipc_link_find_owner(net, name, &bearer_id); if (!node) return -EINVAL; @@ -2687,6 +2711,7 @@ int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info) struct tipc_link *link; struct tipc_node *node; struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; + struct net *net = genl_info_net(info); if (!info->attrs[TIPC_NLA_LINK]) return -EINVAL; @@ -2709,7 +2734,7 @@ int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info) return 0; } - node = tipc_link_find_owner(link_name, &bearer_id); + node = tipc_link_find_owner(net, link_name, &bearer_id); if (!node) return -EINVAL; diff --git a/net/tipc/link.h b/net/tipc/link.h index 692268dca4b9..380e27ee0f70 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -200,27 +200,31 @@ struct tipc_port; struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, struct tipc_bearer *b_ptr, const struct tipc_media_addr *media_addr); -void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down); +void tipc_link_delete_list(struct net *net, unsigned int bearer_id, + bool shutting_down); void tipc_link_failover_send_queue(struct tipc_link *l_ptr); void tipc_link_dup_queue_xmit(struct tipc_link *l_ptr, struct tipc_link *dest); void tipc_link_reset_fragments(struct tipc_link *l_ptr); int tipc_link_is_up(struct tipc_link *l_ptr); int tipc_link_is_active(struct tipc_link *l_ptr); void tipc_link_purge_queues(struct tipc_link *l_ptr); -struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, - int req_tlv_space, - u16 cmd); -struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, +struct sk_buff *tipc_link_cmd_config(struct net *net, const void *req_tlv_area, + int req_tlv_space, u16 cmd); +struct sk_buff *tipc_link_cmd_show_stats(struct net *net, + const void *req_tlv_area, int req_tlv_space); -struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, +struct sk_buff *tipc_link_cmd_reset_stats(struct net *net, + const void *req_tlv_area, int req_tlv_space); void tipc_link_reset_all(struct tipc_node *node); void tipc_link_reset(struct tipc_link *l_ptr); -void tipc_link_reset_list(unsigned int bearer_id); -int tipc_link_xmit_skb(struct sk_buff *skb, u32 dest, u32 selector); -int tipc_link_xmit(struct sk_buff_head *list, u32 dest, u32 selector); +void tipc_link_reset_list(struct net *net, unsigned int bearer_id); +int tipc_link_xmit_skb(struct net *net, struct sk_buff *skb, u32 dest, + u32 selector); +int tipc_link_xmit(struct net *net, struct sk_buff_head *list, u32 dest, + u32 selector); int __tipc_link_xmit(struct tipc_link *link, struct sk_buff_head *list); -void tipc_link_bundle_rcv(struct sk_buff *buf); +void tipc_link_bundle_rcv(struct net *net, struct sk_buff *buf); void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int prob, u32 gap, u32 tolerance, u32 priority, u32 acked_mtu); void tipc_link_push_packets(struct tipc_link *l_ptr); diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index ba6083dca95b..d40df588263e 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -81,14 +81,15 @@ static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest) return buf; } -void named_cluster_distribute(struct sk_buff *skb) +void named_cluster_distribute(struct net *net, struct sk_buff *skb) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct sk_buff *oskb; struct tipc_node *node; u32 dnode; rcu_read_lock(); - list_for_each_entry_rcu(node, &tipc_node_list, list) { + list_for_each_entry_rcu(node, &tn->node_list, list) { dnode = node->addr; if (in_own_node(dnode)) continue; @@ -98,7 +99,7 @@ void named_cluster_distribute(struct sk_buff *skb) if (!oskb) break; msg_set_destnode(buf_msg(oskb), dnode); - tipc_link_xmit_skb(oskb, dnode, dnode); + tipc_link_xmit_skb(net, oskb, dnode, dnode); } rcu_read_unlock(); @@ -160,13 +161,14 @@ struct sk_buff *tipc_named_withdraw(struct publication *publ) * @dnode: node to be updated * @pls: linked list of publication items to be packed into buffer chain */ -static void named_distribute(struct sk_buff_head *list, u32 dnode, - struct list_head *pls) +static void named_distribute(struct net *net, struct sk_buff_head *list, + u32 dnode, struct list_head *pls) { struct publication *publ; struct sk_buff *skb = NULL; struct distr_item *item = NULL; - uint msg_dsz = (tipc_node_get_mtu(dnode, 0) / ITEM_SIZE) * ITEM_SIZE; + uint msg_dsz = (tipc_node_get_mtu(net, dnode, 0) / ITEM_SIZE) * + ITEM_SIZE; uint msg_rem = msg_dsz; list_for_each_entry(publ, pls, local_list) { @@ -202,30 +204,31 @@ static void named_distribute(struct sk_buff_head *list, u32 dnode, /** * tipc_named_node_up - tell specified node about all publications by this node */ -void tipc_named_node_up(u32 dnode) +void tipc_named_node_up(struct net *net, u32 dnode) { struct sk_buff_head head; __skb_queue_head_init(&head); rcu_read_lock(); - named_distribute(&head, dnode, + named_distribute(net, &head, dnode, &tipc_nametbl->publ_list[TIPC_CLUSTER_SCOPE]); - named_distribute(&head, dnode, + named_distribute(net, &head, dnode, &tipc_nametbl->publ_list[TIPC_ZONE_SCOPE]); rcu_read_unlock(); - tipc_link_xmit(&head, dnode, dnode); + tipc_link_xmit(net, &head, dnode, dnode); } -static void tipc_publ_subscribe(struct publication *publ, u32 addr) +static void tipc_publ_subscribe(struct net *net, struct publication *publ, + u32 addr) { struct tipc_node *node; if (in_own_node(addr)) return; - node = tipc_node_find(addr); + node = tipc_node_find(net, addr); if (!node) { pr_warn("Node subscription rejected, unknown node 0x%x\n", addr); @@ -237,11 +240,12 @@ static void tipc_publ_subscribe(struct publication *publ, u32 addr) tipc_node_unlock(node); } -static void tipc_publ_unsubscribe(struct publication *publ, u32 addr) +static void tipc_publ_unsubscribe(struct net *net, struct publication *publ, + u32 addr) { struct tipc_node *node; - node = tipc_node_find(addr); + node = tipc_node_find(net, addr); if (!node) return; @@ -256,7 +260,7 @@ static void tipc_publ_unsubscribe(struct publication *publ, u32 addr) * Invoked for each publication issued by a newly failed node. * Removes publication structure from name table & deletes it. */ -static void tipc_publ_purge(struct publication *publ, u32 addr) +static void tipc_publ_purge(struct net *net, struct publication *publ, u32 addr) { struct publication *p; @@ -264,7 +268,7 @@ static void tipc_publ_purge(struct publication *publ, u32 addr) p = tipc_nametbl_remove_publ(publ->type, publ->lower, publ->node, publ->ref, publ->key); if (p) - tipc_publ_unsubscribe(p, addr); + tipc_publ_unsubscribe(net, p, addr); spin_unlock_bh(&tipc_nametbl_lock); if (p != publ) { @@ -277,12 +281,12 @@ static void tipc_publ_purge(struct publication *publ, u32 addr) kfree_rcu(p, rcu); } -void tipc_publ_notify(struct list_head *nsub_list, u32 addr) +void tipc_publ_notify(struct net *net, struct list_head *nsub_list, u32 addr) { struct publication *publ, *tmp; list_for_each_entry_safe(publ, tmp, nsub_list, nodesub_list) - tipc_publ_purge(publ, addr); + tipc_publ_purge(net, publ, addr); } /** @@ -292,7 +296,8 @@ void tipc_publ_notify(struct list_head *nsub_list, u32 addr) * tipc_nametbl_lock must be held. * Returns the publication item if successful, otherwise NULL. */ -static bool tipc_update_nametbl(struct distr_item *i, u32 node, u32 dtype) +static bool tipc_update_nametbl(struct net *net, struct distr_item *i, + u32 node, u32 dtype) { struct publication *publ = NULL; @@ -302,7 +307,7 @@ static bool tipc_update_nametbl(struct distr_item *i, u32 node, u32 dtype) TIPC_CLUSTER_SCOPE, node, ntohl(i->ref), ntohl(i->key)); if (publ) { - tipc_publ_subscribe(publ, node); + tipc_publ_subscribe(net, publ, node); return true; } } else if (dtype == WITHDRAWAL) { @@ -310,7 +315,7 @@ static bool tipc_update_nametbl(struct distr_item *i, u32 node, u32 dtype) node, ntohl(i->ref), ntohl(i->key)); if (publ) { - tipc_publ_unsubscribe(publ, node); + tipc_publ_unsubscribe(net, publ, node); kfree_rcu(publ, rcu); return true; } @@ -343,7 +348,7 @@ static void tipc_named_add_backlog(struct distr_item *i, u32 type, u32 node) * tipc_named_process_backlog - try to process any pending name table updates * from the network. */ -void tipc_named_process_backlog(void) +void tipc_named_process_backlog(struct net *net) { struct distr_queue_item *e, *tmp; char addr[16]; @@ -351,7 +356,7 @@ void tipc_named_process_backlog(void) list_for_each_entry_safe(e, tmp, &tipc_dist_queue, next) { if (time_after(e->expires, now)) { - if (!tipc_update_nametbl(&e->i, e->node, e->dtype)) + if (!tipc_update_nametbl(net, &e->i, e->node, e->dtype)) continue; } else { tipc_addr_string_fill(addr, e->node); @@ -369,7 +374,7 @@ void tipc_named_process_backlog(void) /** * tipc_named_rcv - process name table update message sent by another node */ -void tipc_named_rcv(struct sk_buff *buf) +void tipc_named_rcv(struct net *net, struct sk_buff *buf) { struct tipc_msg *msg = buf_msg(buf); struct distr_item *item = (struct distr_item *)msg_data(msg); @@ -378,11 +383,11 @@ void tipc_named_rcv(struct sk_buff *buf) spin_lock_bh(&tipc_nametbl_lock); while (count--) { - if (!tipc_update_nametbl(item, node, msg_type(msg))) + if (!tipc_update_nametbl(net, item, node, msg_type(msg))) tipc_named_add_backlog(item, msg_type(msg), node); item++; } - tipc_named_process_backlog(); + tipc_named_process_backlog(net); spin_unlock_bh(&tipc_nametbl_lock); kfree_skb(buf); } diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h index cef55cedcfb2..8039d84351b3 100644 --- a/net/tipc/name_distr.h +++ b/net/tipc/name_distr.h @@ -69,11 +69,11 @@ struct distr_item { struct sk_buff *tipc_named_publish(struct publication *publ); struct sk_buff *tipc_named_withdraw(struct publication *publ); -void named_cluster_distribute(struct sk_buff *buf); -void tipc_named_node_up(u32 dnode); -void tipc_named_rcv(struct sk_buff *buf); +void named_cluster_distribute(struct net *net, struct sk_buff *buf); +void tipc_named_node_up(struct net *net, u32 dnode); +void tipc_named_rcv(struct net *net, struct sk_buff *buf); void tipc_named_reinit(void); -void tipc_named_process_backlog(void); -void tipc_publ_notify(struct list_head *nsub_list, u32 addr); +void tipc_named_process_backlog(struct net *net); +void tipc_publ_notify(struct net *net, struct list_head *nsub_list, u32 addr); #endif diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index c8df0223371a..cf177907bb53 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -650,8 +650,9 @@ exit: /* * tipc_nametbl_publish - add name publication to network name tables */ -struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, - u32 scope, u32 port_ref, u32 key) +struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower, + u32 upper, u32 scope, u32 port_ref, + u32 key) { struct publication *publ; struct sk_buff *buf = NULL; @@ -670,19 +671,20 @@ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, tipc_nametbl->local_publ_count++; buf = tipc_named_publish(publ); /* Any pending external events? */ - tipc_named_process_backlog(); + tipc_named_process_backlog(net); } spin_unlock_bh(&tipc_nametbl_lock); if (buf) - named_cluster_distribute(buf); + named_cluster_distribute(net, buf); return publ; } /** * tipc_nametbl_withdraw - withdraw name publication from network name tables */ -int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) +int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref, + u32 key) { struct publication *publ; struct sk_buff *skb = NULL; @@ -693,7 +695,7 @@ int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) tipc_nametbl->local_publ_count--; skb = tipc_named_withdraw(publ); /* Any pending external events? */ - tipc_named_process_backlog(); + tipc_named_process_backlog(net); list_del_init(&publ->pport_list); kfree_rcu(publ, rcu); } else { @@ -704,7 +706,7 @@ int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) spin_unlock_bh(&tipc_nametbl_lock); if (skb) { - named_cluster_distribute(skb); + named_cluster_distribute(net, skb); return 1; } return 0; diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index 5f0dee92010d..efccaca7a5d5 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h @@ -104,9 +104,11 @@ struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space); u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node); int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, struct tipc_port_list *dports); -struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, - u32 scope, u32 port_ref, u32 key); -int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key); +struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower, + u32 upper, u32 scope, u32 port_ref, + u32 key); +int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref, + u32 key); struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, u32 scope, u32 node, u32 ref, u32 key); diff --git a/net/tipc/net.c b/net/tipc/net.c index 5ce9d628f2d0..de18aacf3d64 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -121,7 +121,7 @@ int tipc_net_start(struct net *net, u32 addr) if (res) return res; - tipc_nametbl_publish(TIPC_CFG_SRV, tipc_own_addr, tipc_own_addr, + tipc_nametbl_publish(net, TIPC_CFG_SRV, tipc_own_addr, tipc_own_addr, TIPC_ZONE_SCOPE, 0, tipc_own_addr); pr_info("Started in network mode\n"); @@ -131,16 +131,17 @@ int tipc_net_start(struct net *net, u32 addr) return 0; } -void tipc_net_stop(void) +void tipc_net_stop(struct net *net) { if (!tipc_own_addr) return; - tipc_nametbl_withdraw(TIPC_CFG_SRV, tipc_own_addr, 0, tipc_own_addr); + tipc_nametbl_withdraw(net, TIPC_CFG_SRV, tipc_own_addr, 0, + tipc_own_addr); rtnl_lock(); - tipc_bearer_stop(); + tipc_bearer_stop(net); tipc_bclink_stop(); - tipc_node_stop(); + tipc_node_stop(net); rtnl_unlock(); pr_info("Left network mode\n"); diff --git a/net/tipc/net.h b/net/tipc/net.h index 2c4812f8408f..77a7a118911d 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h @@ -41,7 +41,7 @@ int tipc_net_start(struct net *net, u32 addr); -void tipc_net_stop(void); +void tipc_net_stop(struct net *net); int tipc_nl_net_dump(struct sk_buff *skb, struct netlink_callback *cb); int tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info); diff --git a/net/tipc/node.c b/net/tipc/node.c index 8d353ec77a66..a0ca1ac53119 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -40,17 +40,9 @@ #include "name_distr.h" #include "socket.h" -#define NODE_HTABLE_SIZE 512 - static void node_lost_contact(struct tipc_node *n_ptr); static void node_established_contact(struct tipc_node *n_ptr); -static struct hlist_head node_htable[NODE_HTABLE_SIZE]; -LIST_HEAD(tipc_node_list); -static u32 tipc_num_nodes; -static u32 tipc_num_links; -static DEFINE_SPINLOCK(node_list_lock); - struct tipc_sock_conn { u32 port; u32 peer_port; @@ -78,15 +70,17 @@ static unsigned int tipc_hashfn(u32 addr) /* * tipc_node_find - locate specified node object, if it exists */ -struct tipc_node *tipc_node_find(u32 addr) +struct tipc_node *tipc_node_find(struct net *net, u32 addr) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_node *node; if (unlikely(!in_own_cluster_exact(addr))) return NULL; rcu_read_lock(); - hlist_for_each_entry_rcu(node, &node_htable[tipc_hashfn(addr)], hash) { + hlist_for_each_entry_rcu(node, &tn->node_htable[tipc_hashfn(addr)], + hash) { if (node->addr == addr) { rcu_read_unlock(); return node; @@ -96,20 +90,22 @@ struct tipc_node *tipc_node_find(u32 addr) return NULL; } -struct tipc_node *tipc_node_create(u32 addr) +struct tipc_node *tipc_node_create(struct net *net, u32 addr) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_node *n_ptr, *temp_node; - spin_lock_bh(&node_list_lock); + spin_lock_bh(&tn->node_list_lock); n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC); if (!n_ptr) { - spin_unlock_bh(&node_list_lock); + spin_unlock_bh(&tn->node_list_lock); pr_warn("Node creation failed, no memory\n"); return NULL; } n_ptr->addr = addr; + n_ptr->net = net; spin_lock_init(&n_ptr->lock); INIT_HLIST_NODE(&n_ptr->hash); INIT_LIST_HEAD(&n_ptr->list); @@ -118,9 +114,9 @@ struct tipc_node *tipc_node_create(u32 addr) skb_queue_head_init(&n_ptr->waiting_sks); __skb_queue_head_init(&n_ptr->bclink.deferred_queue); - hlist_add_head_rcu(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]); + hlist_add_head_rcu(&n_ptr->hash, &tn->node_htable[tipc_hashfn(addr)]); - list_for_each_entry_rcu(temp_node, &tipc_node_list, list) { + list_for_each_entry_rcu(temp_node, &tn->node_list, list) { if (n_ptr->addr < temp_node->addr) break; } @@ -128,32 +124,33 @@ struct tipc_node *tipc_node_create(u32 addr) n_ptr->action_flags = TIPC_WAIT_PEER_LINKS_DOWN; n_ptr->signature = INVALID_NODE_SIG; - tipc_num_nodes++; + tn->num_nodes++; - spin_unlock_bh(&node_list_lock); + spin_unlock_bh(&tn->node_list_lock); return n_ptr; } -static void tipc_node_delete(struct tipc_node *n_ptr) +static void tipc_node_delete(struct tipc_net *tn, struct tipc_node *n_ptr) { list_del_rcu(&n_ptr->list); hlist_del_rcu(&n_ptr->hash); kfree_rcu(n_ptr, rcu); - tipc_num_nodes--; + tn->num_nodes--; } -void tipc_node_stop(void) +void tipc_node_stop(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_node *node, *t_node; - spin_lock_bh(&node_list_lock); - list_for_each_entry_safe(node, t_node, &tipc_node_list, list) - tipc_node_delete(node); - spin_unlock_bh(&node_list_lock); + spin_lock_bh(&tn->node_list_lock); + list_for_each_entry_safe(node, t_node, &tn->node_list, list) + tipc_node_delete(tn, node); + spin_unlock_bh(&tn->node_list_lock); } -int tipc_node_add_conn(u32 dnode, u32 port, u32 peer_port) +int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port) { struct tipc_node *node; struct tipc_sock_conn *conn; @@ -161,7 +158,7 @@ int tipc_node_add_conn(u32 dnode, u32 port, u32 peer_port) if (in_own_node(dnode)) return 0; - node = tipc_node_find(dnode); + node = tipc_node_find(net, dnode); if (!node) { pr_warn("Connecting sock to node 0x%x failed\n", dnode); return -EHOSTUNREACH; @@ -179,7 +176,7 @@ int tipc_node_add_conn(u32 dnode, u32 port, u32 peer_port) return 0; } -void tipc_node_remove_conn(u32 dnode, u32 port) +void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port) { struct tipc_node *node; struct tipc_sock_conn *conn, *safe; @@ -187,7 +184,7 @@ void tipc_node_remove_conn(u32 dnode, u32 port) if (in_own_node(dnode)) return; - node = tipc_node_find(dnode); + node = tipc_node_find(net, dnode); if (!node) return; @@ -201,7 +198,7 @@ void tipc_node_remove_conn(u32 dnode, u32 port) tipc_node_unlock(node); } -void tipc_node_abort_sock_conns(struct list_head *conns) +void tipc_node_abort_sock_conns(struct net *net, struct list_head *conns) { struct tipc_sock_conn *conn, *safe; struct sk_buff *buf; @@ -212,7 +209,7 @@ void tipc_node_abort_sock_conns(struct list_head *conns) conn->peer_node, conn->port, conn->peer_port, TIPC_ERR_NO_NODE); if (likely(buf)) - tipc_sk_rcv(buf); + tipc_sk_rcv(net, buf); list_del(&conn->list); kfree(conn); } @@ -342,24 +339,27 @@ int tipc_node_is_up(struct tipc_node *n_ptr) void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) { + struct tipc_net *tn = net_generic(n_ptr->net, tipc_net_id); + n_ptr->links[l_ptr->bearer_id] = l_ptr; - spin_lock_bh(&node_list_lock); - tipc_num_links++; - spin_unlock_bh(&node_list_lock); + spin_lock_bh(&tn->node_list_lock); + tn->num_links++; + spin_unlock_bh(&tn->node_list_lock); n_ptr->link_cnt++; } void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) { + struct tipc_net *tn = net_generic(n_ptr->net, tipc_net_id); int i; for (i = 0; i < MAX_BEARERS; i++) { if (l_ptr != n_ptr->links[i]) continue; n_ptr->links[i] = NULL; - spin_lock_bh(&node_list_lock); - tipc_num_links--; - spin_unlock_bh(&node_list_lock); + spin_lock_bh(&tn->node_list_lock); + tn->num_links--; + spin_unlock_bh(&tn->node_list_lock); n_ptr->link_cnt--; } } @@ -414,8 +414,10 @@ static void node_lost_contact(struct tipc_node *n_ptr) TIPC_NOTIFY_NODE_DOWN; } -struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) +struct sk_buff *tipc_node_get_nodes(struct net *net, const void *req_tlv_area, + int req_tlv_space) { + struct tipc_net *tn = net_generic(net, tipc_net_id); u32 domain; struct sk_buff *buf; struct tipc_node *n_ptr; @@ -430,20 +432,20 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (network address)"); - spin_lock_bh(&node_list_lock); - if (!tipc_num_nodes) { - spin_unlock_bh(&node_list_lock); + spin_lock_bh(&tn->node_list_lock); + if (!tn->num_nodes) { + spin_unlock_bh(&tn->node_list_lock); return tipc_cfg_reply_none(); } /* For now, get space for all other nodes */ - payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes; + payload_size = TLV_SPACE(sizeof(node_info)) * tn->num_nodes; if (payload_size > 32768u) { - spin_unlock_bh(&node_list_lock); + spin_unlock_bh(&tn->node_list_lock); return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (too many nodes)"); } - spin_unlock_bh(&node_list_lock); + spin_unlock_bh(&tn->node_list_lock); buf = tipc_cfg_reply_alloc(payload_size); if (!buf) @@ -451,7 +453,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) /* Add TLVs for all nodes in scope */ rcu_read_lock(); - list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { + list_for_each_entry_rcu(n_ptr, &tn->node_list, list) { if (!tipc_in_scope(domain, n_ptr->addr)) continue; node_info.addr = htonl(n_ptr->addr); @@ -463,8 +465,10 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) return buf; } -struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) +struct sk_buff *tipc_node_get_links(struct net *net, const void *req_tlv_area, + int req_tlv_space) { + struct tipc_net *tn = net_generic(net, tipc_net_id); u32 domain; struct sk_buff *buf; struct tipc_node *n_ptr; @@ -482,15 +486,15 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) if (!tipc_own_addr) return tipc_cfg_reply_none(); - spin_lock_bh(&node_list_lock); + spin_lock_bh(&tn->node_list_lock); /* Get space for all unicast links + broadcast link */ - payload_size = TLV_SPACE((sizeof(link_info)) * (tipc_num_links + 1)); + payload_size = TLV_SPACE((sizeof(link_info)) * (tn->num_links + 1)); if (payload_size > 32768u) { - spin_unlock_bh(&node_list_lock); + spin_unlock_bh(&tn->node_list_lock); return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (too many links)"); } - spin_unlock_bh(&node_list_lock); + spin_unlock_bh(&tn->node_list_lock); buf = tipc_cfg_reply_alloc(payload_size); if (!buf) @@ -504,7 +508,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) /* Add TLVs for any other links in scope */ rcu_read_lock(); - list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { + list_for_each_entry_rcu(n_ptr, &tn->node_list, list) { u32 i; if (!tipc_in_scope(domain, n_ptr->addr)) @@ -534,10 +538,11 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) * * Returns 0 on success */ -int tipc_node_get_linkname(u32 bearer_id, u32 addr, char *linkname, size_t len) +int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 addr, + char *linkname, size_t len) { struct tipc_link *link; - struct tipc_node *node = tipc_node_find(addr); + struct tipc_node *node = tipc_node_find(net, addr); if ((bearer_id >= MAX_BEARERS) || !node) return -EINVAL; @@ -554,6 +559,7 @@ int tipc_node_get_linkname(u32 bearer_id, u32 addr, char *linkname, size_t len) void tipc_node_unlock(struct tipc_node *node) { + struct net *net = node->net; LIST_HEAD(nsub_list); LIST_HEAD(conn_sks); struct sk_buff_head waiting_sks; @@ -585,26 +591,26 @@ void tipc_node_unlock(struct tipc_node *node) spin_unlock_bh(&node->lock); while (!skb_queue_empty(&waiting_sks)) - tipc_sk_rcv(__skb_dequeue(&waiting_sks)); + tipc_sk_rcv(net, __skb_dequeue(&waiting_sks)); if (!list_empty(&conn_sks)) - tipc_node_abort_sock_conns(&conn_sks); + tipc_node_abort_sock_conns(net, &conn_sks); if (!list_empty(&nsub_list)) - tipc_publ_notify(&nsub_list, addr); + tipc_publ_notify(net, &nsub_list, addr); if (flags & TIPC_WAKEUP_BCAST_USERS) - tipc_bclink_wakeup_users(); + tipc_bclink_wakeup_users(net); if (flags & TIPC_NOTIFY_NODE_UP) - tipc_named_node_up(addr); + tipc_named_node_up(net, addr); if (flags & TIPC_NOTIFY_LINK_UP) - tipc_nametbl_publish(TIPC_LINK_STATE, addr, addr, + tipc_nametbl_publish(net, TIPC_LINK_STATE, addr, addr, TIPC_NODE_SCOPE, link_id, addr); if (flags & TIPC_NOTIFY_LINK_DOWN) - tipc_nametbl_withdraw(TIPC_LINK_STATE, addr, + tipc_nametbl_withdraw(net, TIPC_LINK_STATE, addr, link_id, addr); } @@ -645,6 +651,8 @@ msg_full: int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb) { int err; + struct net *net = sock_net(skb->sk); + struct tipc_net *tn = net_generic(net, tipc_net_id); int done = cb->args[0]; int last_addr = cb->args[1]; struct tipc_node *node; @@ -659,7 +667,7 @@ int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb) rcu_read_lock(); - if (last_addr && !tipc_node_find(last_addr)) { + if (last_addr && !tipc_node_find(net, last_addr)) { rcu_read_unlock(); /* We never set seq or call nl_dump_check_consistent() this * means that setting prev_seq here will cause the consistence @@ -671,7 +679,7 @@ int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb) return -EPIPE; } - list_for_each_entry_rcu(node, &tipc_node_list, list) { + list_for_each_entry_rcu(node, &tn->node_list, list) { if (last_addr) { if (node->addr == last_addr) last_addr = 0; diff --git a/net/tipc/node.h b/net/tipc/node.h index cbe0e950f1cc..43ef88ef3035 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h @@ -42,10 +42,10 @@ #include "bearer.h" #include "msg.h" -/* - * Out-of-range value for node signature - */ -#define INVALID_NODE_SIG 0x10000 +/* Out-of-range value for node signature */ +#define INVALID_NODE_SIG 0x10000 + +#define NODE_HTABLE_SIZE 512 /* Flags used to take different actions according to flag type * TIPC_WAIT_PEER_LINKS_DOWN: wait to see that peer's links are down @@ -90,6 +90,7 @@ struct tipc_node_bclink { * struct tipc_node - TIPC node structure * @addr: network address of node * @lock: spinlock governing access to structure + * @net: the applicable net namespace * @hash: links to adjacent nodes in unsorted hash chain * @active_links: pointers to active links to node * @links: pointers to all links to node @@ -106,6 +107,7 @@ struct tipc_node_bclink { struct tipc_node { u32 addr; spinlock_t lock; + struct net *net; struct hlist_node hash; struct tipc_link *active_links[2]; u32 act_mtus[2]; @@ -123,23 +125,24 @@ struct tipc_node { struct rcu_head rcu; }; -extern struct list_head tipc_node_list; - -struct tipc_node *tipc_node_find(u32 addr); -struct tipc_node *tipc_node_create(u32 addr); -void tipc_node_stop(void); +struct tipc_node *tipc_node_find(struct net *net, u32 addr); +struct tipc_node *tipc_node_create(struct net *net, u32 addr); +void tipc_node_stop(struct net *net); void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr); void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr); int tipc_node_active_links(struct tipc_node *n_ptr); int tipc_node_is_up(struct tipc_node *n_ptr); -struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space); -struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space); -int tipc_node_get_linkname(u32 bearer_id, u32 node, char *linkname, size_t len); +struct sk_buff *tipc_node_get_links(struct net *net, const void *req_tlv_area, + int req_tlv_space); +struct sk_buff *tipc_node_get_nodes(struct net *net, const void *req_tlv_area, + int req_tlv_space); +int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 node, + char *linkname, size_t len); void tipc_node_unlock(struct tipc_node *node); -int tipc_node_add_conn(u32 dnode, u32 port, u32 peer_port); -void tipc_node_remove_conn(u32 dnode, u32 port); +int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port); +void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port); int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb); @@ -154,12 +157,12 @@ static inline bool tipc_node_blocked(struct tipc_node *node) TIPC_NOTIFY_NODE_DOWN | TIPC_WAIT_OWN_LINKS_DOWN)); } -static inline uint tipc_node_get_mtu(u32 addr, u32 selector) +static inline uint tipc_node_get_mtu(struct net *net, u32 addr, u32 selector) { struct tipc_node *node; u32 mtu; - node = tipc_node_find(addr); + node = tipc_node_find(net, addr); if (likely(node)) mtu = node->act_mtus[selector & 1]; diff --git a/net/tipc/socket.c b/net/tipc/socket.c index c58f66be7e18..68831453bc0e 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -257,7 +257,7 @@ static void tsk_rej_rx_queue(struct sock *sk) while ((skb = __skb_dequeue(&sk->sk_receive_queue))) { if (tipc_msg_reverse(skb, &dnode, TIPC_ERR_NO_PORT)) - tipc_link_xmit_skb(skb, dnode, 0); + tipc_link_xmit_skb(sock_net(sk), skb, dnode, 0); } } @@ -473,6 +473,7 @@ static void tipc_sk_callback(struct rcu_head *head) static int tipc_release(struct socket *sock) { struct sock *sk = sock->sk; + struct net *net = sock_net(sk); struct tipc_sock *tsk; struct sk_buff *skb; u32 dnode, probing_state; @@ -503,10 +504,10 @@ static int tipc_release(struct socket *sock) (sock->state == SS_CONNECTED)) { sock->state = SS_DISCONNECTING; tsk->connected = 0; - tipc_node_remove_conn(dnode, tsk->portid); + tipc_node_remove_conn(net, dnode, tsk->portid); } if (tipc_msg_reverse(skb, &dnode, TIPC_ERR_NO_PORT)) - tipc_link_xmit_skb(skb, dnode, 0); + tipc_link_xmit_skb(net, skb, dnode, 0); } } @@ -521,8 +522,8 @@ static int tipc_release(struct socket *sock) tsk_peer_port(tsk), tsk->portid, TIPC_ERR_NO_PORT); if (skb) - tipc_link_xmit_skb(skb, dnode, tsk->portid); - tipc_node_remove_conn(dnode, tsk->portid); + tipc_link_xmit_skb(net, skb, dnode, tsk->portid); + tipc_node_remove_conn(net, dnode, tsk->portid); } /* Discard any remaining (connection-based) messages in receive queue */ @@ -725,6 +726,7 @@ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq, struct msghdr *msg, size_t dsz, long timeo) { struct sock *sk = sock->sk; + struct net *net = sock_net(sk); struct tipc_msg *mhdr = &tipc_sk(sk)->phdr; struct sk_buff_head head; uint mtu; @@ -747,7 +749,7 @@ new_mtu: return rc; do { - rc = tipc_bclink_xmit(&head); + rc = tipc_bclink_xmit(net, &head); if (likely(rc >= 0)) { rc = dsz; break; @@ -766,7 +768,7 @@ new_mtu: /* tipc_sk_mcast_rcv - Deliver multicast message to all destination sockets */ -void tipc_sk_mcast_rcv(struct sk_buff *buf) +void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *buf) { struct tipc_msg *msg = buf_msg(buf); struct tipc_port_list dports = {0, NULL, }; @@ -798,7 +800,7 @@ void tipc_sk_mcast_rcv(struct sk_buff *buf) continue; } msg_set_destport(msg, item->ports[i]); - tipc_sk_rcv(b); + tipc_sk_rcv(net, b); } } tipc_port_list_free(&dports); @@ -886,6 +888,7 @@ static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock, DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); struct sock *sk = sock->sk; struct tipc_sock *tsk = tipc_sk(sk); + struct net *net = sock_net(sk); struct tipc_msg *mhdr = &tsk->phdr; u32 dnode, dport; struct sk_buff_head head; @@ -960,7 +963,7 @@ static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock, } new_mtu: - mtu = tipc_node_get_mtu(dnode, tsk->portid); + mtu = tipc_node_get_mtu(net, dnode, tsk->portid); __skb_queue_head_init(&head); rc = tipc_msg_build(mhdr, m, 0, dsz, mtu, &head); if (rc < 0) @@ -969,7 +972,7 @@ new_mtu: do { skb = skb_peek(&head); TIPC_SKB_CB(skb)->wakeup_pending = tsk->link_cong; - rc = tipc_link_xmit(&head, dnode, tsk->portid); + rc = tipc_link_xmit(net, &head, dnode, tsk->portid); if (likely(rc >= 0)) { if (sock->state != SS_READY) sock->state = SS_CONNECTING; @@ -1038,6 +1041,7 @@ static int tipc_send_stream(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t dsz) { struct sock *sk = sock->sk; + struct net *net = sock_net(sk); struct tipc_sock *tsk = tipc_sk(sk); struct tipc_msg *mhdr = &tsk->phdr; struct sk_buff_head head; @@ -1081,7 +1085,7 @@ next: goto exit; do { if (likely(!tsk_conn_cong(tsk))) { - rc = tipc_link_xmit(&head, dnode, portid); + rc = tipc_link_xmit(net, &head, dnode, portid); if (likely(!rc)) { tsk->sent_unacked++; sent += send; @@ -1090,7 +1094,8 @@ next: goto next; } if (rc == -EMSGSIZE) { - tsk->max_pkt = tipc_node_get_mtu(dnode, portid); + tsk->max_pkt = tipc_node_get_mtu(net, dnode, + portid); goto next; } if (rc != -ELINKCONG) @@ -1132,6 +1137,7 @@ static int tipc_send_packet(struct kiocb *iocb, struct socket *sock, static void tipc_sk_finish_conn(struct tipc_sock *tsk, u32 peer_port, u32 peer_node) { + struct net *net = sock_net(&tsk->sk); struct tipc_msg *msg = &tsk->phdr; msg_set_destnode(msg, peer_node); @@ -1145,8 +1151,8 @@ static void tipc_sk_finish_conn(struct tipc_sock *tsk, u32 peer_port, tsk->connected = 1; if (!mod_timer(&tsk->timer, jiffies + tsk->probing_intv)) sock_hold(&tsk->sk); - tipc_node_add_conn(peer_node, tsk->portid, peer_port); - tsk->max_pkt = tipc_node_get_mtu(peer_node, tsk->portid); + tipc_node_add_conn(net, peer_node, tsk->portid, peer_port); + tsk->max_pkt = tipc_node_get_mtu(net, peer_node, tsk->portid); } /** @@ -1245,6 +1251,7 @@ static int tipc_sk_anc_data_recv(struct msghdr *m, struct tipc_msg *msg, static void tipc_sk_send_ack(struct tipc_sock *tsk, uint ack) { + struct net *net = sock_net(&tsk->sk); struct sk_buff *skb = NULL; struct tipc_msg *msg; u32 peer_port = tsk_peer_port(tsk); @@ -1258,7 +1265,7 @@ static void tipc_sk_send_ack(struct tipc_sock *tsk, uint ack) return; msg = buf_msg(skb); msg_set_msgcnt(msg, ack); - tipc_link_xmit_skb(skb, dnode, msg_link_selector(msg)); + tipc_link_xmit_skb(net, skb, dnode, msg_link_selector(msg)); } static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop) @@ -1551,6 +1558,7 @@ static void tipc_data_ready(struct sock *sk) static int filter_connect(struct tipc_sock *tsk, struct sk_buff **buf) { struct sock *sk = &tsk->sk; + struct net *net = sock_net(sk); struct socket *sock = sk->sk_socket; struct tipc_msg *msg = buf_msg(*buf); int retval = -TIPC_ERR_NO_PORT; @@ -1566,7 +1574,7 @@ static int filter_connect(struct tipc_sock *tsk, struct sk_buff **buf) sock->state = SS_DISCONNECTING; tsk->connected = 0; /* let timer expire on it's own */ - tipc_node_remove_conn(tsk_peer_node(tsk), + tipc_node_remove_conn(net, tsk_peer_node(tsk), tsk->portid); } retval = TIPC_OK; @@ -1737,7 +1745,7 @@ static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb) if ((rc < 0) && !tipc_msg_reverse(skb, &onode, -rc)) return 0; - tipc_link_xmit_skb(skb, onode, 0); + tipc_link_xmit_skb(sock_net(sk), skb, onode, 0); return 0; } @@ -1748,7 +1756,7 @@ static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb) * Consumes buffer * Returns 0 if success, or errno: -EHOSTUNREACH */ -int tipc_sk_rcv(struct sk_buff *skb) +int tipc_sk_rcv(struct net *net, struct sk_buff *skb) { struct tipc_sock *tsk; struct sock *sk; @@ -1785,7 +1793,7 @@ exit: if ((rc < 0) && !tipc_msg_reverse(skb, &dnode, -rc)) return -EHOSTUNREACH; - tipc_link_xmit_skb(skb, dnode, 0); + tipc_link_xmit_skb(net, skb, dnode, 0); return (rc < 0) ? -EHOSTUNREACH : 0; } @@ -2042,6 +2050,7 @@ exit: static int tipc_shutdown(struct socket *sock, int how) { struct sock *sk = sock->sk; + struct net *net = sock_net(sk); struct tipc_sock *tsk = tipc_sk(sk); struct sk_buff *skb; u32 dnode; @@ -2065,8 +2074,9 @@ restart: goto restart; } if (tipc_msg_reverse(skb, &dnode, TIPC_CONN_SHUTDOWN)) - tipc_link_xmit_skb(skb, dnode, tsk->portid); - tipc_node_remove_conn(dnode, tsk->portid); + tipc_link_xmit_skb(net, skb, dnode, + tsk->portid); + tipc_node_remove_conn(net, dnode, tsk->portid); } else { dnode = tsk_peer_node(tsk); skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, @@ -2074,11 +2084,11 @@ restart: 0, dnode, tipc_own_addr, tsk_peer_port(tsk), tsk->portid, TIPC_CONN_SHUTDOWN); - tipc_link_xmit_skb(skb, dnode, tsk->portid); + tipc_link_xmit_skb(net, skb, dnode, tsk->portid); } tsk->connected = 0; sock->state = SS_DISCONNECTING; - tipc_node_remove_conn(dnode, tsk->portid); + tipc_node_remove_conn(net, dnode, tsk->portid); /* fall through */ case SS_DISCONNECTING: @@ -2130,7 +2140,7 @@ static void tipc_sk_timeout(unsigned long data) } bh_unlock_sock(sk); if (skb) - tipc_link_xmit_skb(skb, peer_node, tsk->portid); + tipc_link_xmit_skb(sock_net(sk), skb, peer_node, tsk->portid); exit: sock_put(sk); } @@ -2138,6 +2148,7 @@ exit: static int tipc_sk_publish(struct tipc_sock *tsk, uint scope, struct tipc_name_seq const *seq) { + struct net *net = sock_net(&tsk->sk); struct publication *publ; u32 key; @@ -2147,7 +2158,7 @@ static int tipc_sk_publish(struct tipc_sock *tsk, uint scope, if (key == tsk->portid) return -EADDRINUSE; - publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper, + publ = tipc_nametbl_publish(net, seq->type, seq->lower, seq->upper, scope, tsk->portid, key); if (unlikely(!publ)) return -EINVAL; @@ -2161,6 +2172,7 @@ static int tipc_sk_publish(struct tipc_sock *tsk, uint scope, static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope, struct tipc_name_seq const *seq) { + struct net *net = sock_net(&tsk->sk); struct publication *publ; struct publication *safe; int rc = -EINVAL; @@ -2175,12 +2187,12 @@ static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope, continue; if (publ->upper != seq->upper) break; - tipc_nametbl_withdraw(publ->type, publ->lower, + tipc_nametbl_withdraw(net, publ->type, publ->lower, publ->ref, publ->key); rc = 0; break; } - tipc_nametbl_withdraw(publ->type, publ->lower, + tipc_nametbl_withdraw(net, publ->type, publ->lower, publ->ref, publ->key); rc = 0; } @@ -2492,8 +2504,9 @@ static int tipc_getsockopt(struct socket *sock, int lvl, int opt, return put_user(sizeof(value), ol); } -static int tipc_ioctl(struct socket *sk, unsigned int cmd, unsigned long arg) +static int tipc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { + struct sock *sk = sock->sk; struct tipc_sioc_ln_req lnr; void __user *argp = (void __user *)arg; @@ -2501,7 +2514,8 @@ static int tipc_ioctl(struct socket *sk, unsigned int cmd, unsigned long arg) case SIOCGETLINKNAME: if (copy_from_user(&lnr, argp, sizeof(lnr))) return -EFAULT; - if (!tipc_node_get_linkname(lnr.bearer_id & 0xffff, lnr.peer, + if (!tipc_node_get_linkname(sock_net(sk), + lnr.bearer_id & 0xffff, lnr.peer, lnr.linkname, TIPC_MAX_LINK_NAME)) { if (copy_to_user(argp, &lnr, sizeof(lnr))) return -EFAULT; diff --git a/net/tipc/socket.h b/net/tipc/socket.h index 46bc370d82c7..eb15c3107920 100644 --- a/net/tipc/socket.h +++ b/net/tipc/socket.h @@ -49,9 +49,9 @@ int tipc_sock_create_local(int type, struct socket **res); void tipc_sock_release_local(struct socket *sock); int tipc_sock_accept_local(struct socket *sock, struct socket **newsock, int flags); -int tipc_sk_rcv(struct sk_buff *buf); +int tipc_sk_rcv(struct net *net, struct sk_buff *buf); struct sk_buff *tipc_sk_socks_show(void); -void tipc_sk_mcast_rcv(struct sk_buff *buf); +void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *buf); void tipc_sk_reinit(void); int tipc_sk_rht_init(void); void tipc_sk_rht_destroy(void); -- cgit v1.2.3-70-g09d2 From 7f9f95d9d9bcdf253c4149a157b096958013eceb Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Fri, 9 Jan 2015 15:27:06 +0800 Subject: tipc: make bearer list support net namespace Bearer list defined as a global variable is used to store bearer instances. When tipc supports net namespace, bearers created in one namespace must be isolated with others allocated in other namespaces, which requires us that the bearer list(bearer_list) must be moved to tipc_net structure. As a result, a net namespace pointer has to be passed to functions which access the bearer list. Signed-off-by: Ying Xue Tested-by: Tero Aho Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/bcast.c | 27 +++++++++++++-------- net/tipc/bcast.h | 7 +++--- net/tipc/bearer.c | 67 +++++++++++++++++++++++++++++++---------------------- net/tipc/bearer.h | 16 ++++++------- net/tipc/config.c | 2 +- net/tipc/core.h | 4 ++++ net/tipc/discover.c | 12 ++++++---- net/tipc/link.c | 41 ++++++++++++++++++++------------ net/tipc/link.h | 3 ++- net/tipc/net.c | 4 ++-- 10 files changed, 110 insertions(+), 73 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 816c0e49319f..e7c538304595 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -369,7 +369,7 @@ void tipc_bclink_update_link_state(struct net *net, struct tipc_node *n_ptr, msg_set_bcgap_to(msg, to); tipc_bclink_lock(); - tipc_bearer_send(MAX_BEARERS, buf, NULL); + tipc_bearer_send(net, MAX_BEARERS, buf, NULL); bcl->stats.sent_nacks++; tipc_bclink_unlock(); kfree_skb(buf); @@ -425,7 +425,7 @@ int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list) if (likely(bclink)) { tipc_bclink_lock(); if (likely(bclink->bcast_nodes.count)) { - rc = __tipc_link_xmit(bcl, list); + rc = __tipc_link_xmit(net, bcl, list); if (likely(!rc)) { u32 len = skb_queue_len(&bcl->outqueue); @@ -682,13 +682,14 @@ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1, if (bp_index == 0) { /* Use original buffer for first bearer */ - tipc_bearer_send(b->identity, buf, &b->bcast_addr); + tipc_bearer_send(net, b->identity, buf, &b->bcast_addr); } else { /* Avoid concurrent buffer access */ tbuf = pskb_copy_for_clone(buf, GFP_ATOMIC); if (!tbuf) break; - tipc_bearer_send(b->identity, tbuf, &b->bcast_addr); + tipc_bearer_send(net, b->identity, tbuf, + &b->bcast_addr); kfree_skb(tbuf); /* Bearer keeps a clone */ } if (bcbearer->remains_new.count == 0) @@ -703,8 +704,10 @@ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1, /** * tipc_bcbearer_sort - create sets of bearer pairs used by broadcast bearer */ -void tipc_bcbearer_sort(struct tipc_node_map *nm_ptr, u32 node, bool action) +void tipc_bcbearer_sort(struct net *net, struct tipc_node_map *nm_ptr, + u32 node, bool action) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_bcbearer_pair *bp_temp = bcbearer->bpairs_temp; struct tipc_bcbearer_pair *bp_curr; struct tipc_bearer *b; @@ -723,7 +726,7 @@ void tipc_bcbearer_sort(struct tipc_node_map *nm_ptr, u32 node, bool action) rcu_read_lock(); for (b_index = 0; b_index < MAX_BEARERS; b_index++) { - b = rcu_dereference_rtnl(bearer_list[b_index]); + b = rcu_dereference_rtnl(tn->bearer_list[b_index]); if (!b || !b->nodes.count) continue; @@ -939,8 +942,10 @@ int tipc_bclink_set_queue_limits(u32 limit) return 0; } -int tipc_bclink_init(void) +int tipc_bclink_init(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); + bcbearer = kzalloc(sizeof(*bcbearer), GFP_ATOMIC); if (!bcbearer) return -ENOMEM; @@ -967,19 +972,21 @@ int tipc_bclink_init(void) bcl->max_pkt = MAX_PKT_DEFAULT_MCAST; tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT); bcl->bearer_id = MAX_BEARERS; - rcu_assign_pointer(bearer_list[MAX_BEARERS], &bcbearer->bearer); + rcu_assign_pointer(tn->bearer_list[MAX_BEARERS], &bcbearer->bearer); bcl->state = WORKING_WORKING; strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME); return 0; } -void tipc_bclink_stop(void) +void tipc_bclink_stop(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); + tipc_bclink_lock(); tipc_link_purge_queues(bcl); tipc_bclink_unlock(); - RCU_INIT_POINTER(bearer_list[BCBEARER], NULL); + RCU_INIT_POINTER(tn->bearer_list[BCBEARER], NULL); synchronize_net(); kfree(bcbearer); kfree(bclink); diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index fd0d17a76493..692efb662253 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h @@ -84,8 +84,8 @@ static inline int tipc_nmap_equal(struct tipc_node_map *nm_a, void tipc_port_list_add(struct tipc_port_list *pl_ptr, u32 port); void tipc_port_list_free(struct tipc_port_list *pl_ptr); -int tipc_bclink_init(void); -void tipc_bclink_stop(void); +int tipc_bclink_init(struct net *net); +void tipc_bclink_stop(struct net *net); void tipc_bclink_set_flags(unsigned int flags); void tipc_bclink_add_node(u32 addr); void tipc_bclink_remove_node(u32 addr); @@ -99,7 +99,8 @@ void tipc_bclink_update_link_state(struct net *net, struct tipc_node *n_ptr, int tipc_bclink_stats(char *stats_buf, const u32 buf_size); int tipc_bclink_reset_stats(void); int tipc_bclink_set_queue_limits(u32 limit); -void tipc_bcbearer_sort(struct tipc_node_map *nm_ptr, u32 node, bool action); +void tipc_bcbearer_sort(struct net *net, struct tipc_node_map *nm_ptr, + u32 node, bool action); uint tipc_bclink_get_mtu(void); int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list); void tipc_bclink_wakeup_users(struct net *net); diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index a735c08e9d90..2fe9dcb418d4 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -34,6 +34,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include #include "core.h" #include "config.h" #include "bearer.h" @@ -67,8 +68,6 @@ static const struct nla_policy tipc_nl_media_policy[TIPC_NLA_MEDIA_MAX + 1] = { [TIPC_NLA_MEDIA_PROP] = { .type = NLA_NESTED } }; -struct tipc_bearer __rcu *bearer_list[MAX_BEARERS + 1]; - static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr, bool shutting_down); @@ -191,13 +190,14 @@ static int bearer_name_validate(const char *name, /** * tipc_bearer_find - locates bearer object with matching bearer name */ -struct tipc_bearer *tipc_bearer_find(const char *name) +struct tipc_bearer *tipc_bearer_find(struct net *net, const char *name) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_bearer *b_ptr; u32 i; for (i = 0; i < MAX_BEARERS; i++) { - b_ptr = rtnl_dereference(bearer_list[i]); + b_ptr = rtnl_dereference(tn->bearer_list[i]); if (b_ptr && (!strcmp(b_ptr->name, name))) return b_ptr; } @@ -207,8 +207,9 @@ struct tipc_bearer *tipc_bearer_find(const char *name) /** * tipc_bearer_get_names - record names of bearers in buffer */ -struct sk_buff *tipc_bearer_get_names(void) +struct sk_buff *tipc_bearer_get_names(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct sk_buff *buf; struct tipc_bearer *b; int i, j; @@ -219,7 +220,7 @@ struct sk_buff *tipc_bearer_get_names(void) for (i = 0; media_info_array[i] != NULL; i++) { for (j = 0; j < MAX_BEARERS; j++) { - b = rtnl_dereference(bearer_list[j]); + b = rtnl_dereference(tn->bearer_list[j]); if (!b) continue; if (b->media == media_info_array[i]) { @@ -232,27 +233,29 @@ struct sk_buff *tipc_bearer_get_names(void) return buf; } -void tipc_bearer_add_dest(u32 bearer_id, u32 dest) +void tipc_bearer_add_dest(struct net *net, u32 bearer_id, u32 dest) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_bearer *b_ptr; rcu_read_lock(); - b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]); + b_ptr = rcu_dereference_rtnl(tn->bearer_list[bearer_id]); if (b_ptr) { - tipc_bcbearer_sort(&b_ptr->nodes, dest, true); + tipc_bcbearer_sort(net, &b_ptr->nodes, dest, true); tipc_disc_add_dest(b_ptr->link_req); } rcu_read_unlock(); } -void tipc_bearer_remove_dest(u32 bearer_id, u32 dest) +void tipc_bearer_remove_dest(struct net *net, u32 bearer_id, u32 dest) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_bearer *b_ptr; rcu_read_lock(); - b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]); + b_ptr = rcu_dereference_rtnl(tn->bearer_list[bearer_id]); if (b_ptr) { - tipc_bcbearer_sort(&b_ptr->nodes, dest, false); + tipc_bcbearer_sort(net, &b_ptr->nodes, dest, false); tipc_disc_remove_dest(b_ptr->link_req); } rcu_read_unlock(); @@ -264,6 +267,7 @@ void tipc_bearer_remove_dest(u32 bearer_id, u32 dest) int tipc_enable_bearer(struct net *net, const char *name, u32 disc_domain, u32 priority) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_bearer *b_ptr; struct tipc_media *m_ptr; struct tipc_bearer_names b_names; @@ -315,7 +319,7 @@ restart: bearer_id = MAX_BEARERS; with_this_prio = 1; for (i = MAX_BEARERS; i-- != 0; ) { - b_ptr = rtnl_dereference(bearer_list[i]); + b_ptr = rtnl_dereference(tn->bearer_list[i]); if (!b_ptr) { bearer_id = i; continue; @@ -349,7 +353,7 @@ restart: strcpy(b_ptr->name, name); b_ptr->media = m_ptr; - res = m_ptr->enable_media(b_ptr); + res = m_ptr->enable_media(net, b_ptr); if (res) { pr_warn("Bearer <%s> rejected, enable failure (%d)\n", name, -res); @@ -371,7 +375,7 @@ restart: return -EINVAL; } - rcu_assign_pointer(bearer_list[bearer_id], b_ptr); + rcu_assign_pointer(tn->bearer_list[bearer_id], b_ptr); pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n", name, @@ -398,6 +402,7 @@ static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b_ptr) static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr, bool shutting_down) { + struct tipc_net *tn = net_generic(net, tipc_net_id); u32 i; pr_info("Disabling bearer <%s>\n", b_ptr->name); @@ -408,8 +413,8 @@ static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr, tipc_disc_delete(b_ptr->link_req); for (i = 0; i < MAX_BEARERS; i++) { - if (b_ptr == rtnl_dereference(bearer_list[i])) { - RCU_INIT_POINTER(bearer_list[i], NULL); + if (b_ptr == rtnl_dereference(tn->bearer_list[i])) { + RCU_INIT_POINTER(tn->bearer_list[i], NULL); break; } } @@ -421,7 +426,7 @@ int tipc_disable_bearer(struct net *net, const char *name) struct tipc_bearer *b_ptr; int res; - b_ptr = tipc_bearer_find(name); + b_ptr = tipc_bearer_find(net, name); if (b_ptr == NULL) { pr_warn("Attempt to disable unknown bearer <%s>\n", name); res = -EINVAL; @@ -432,13 +437,13 @@ int tipc_disable_bearer(struct net *net, const char *name) return res; } -int tipc_enable_l2_media(struct tipc_bearer *b) +int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b) { struct net_device *dev; char *driver_name = strchr((const char *)b->name, ':') + 1; /* Find device with specified name */ - dev = dev_get_by_name(&init_net, driver_name); + dev = dev_get_by_name(net, driver_name); if (!dev) return -ENODEV; @@ -514,13 +519,14 @@ int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b, * The media send routine must not alter the buffer being passed in * as it may be needed for later retransmission! */ -void tipc_bearer_send(u32 bearer_id, struct sk_buff *buf, +void tipc_bearer_send(struct net *net, u32 bearer_id, struct sk_buff *buf, struct tipc_media_addr *dest) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_bearer *b_ptr; rcu_read_lock(); - b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]); + b_ptr = rcu_dereference_rtnl(tn->bearer_list[bearer_id]); if (likely(b_ptr)) b_ptr->media->send_msg(buf, b_ptr, dest); rcu_read_unlock(); @@ -630,14 +636,15 @@ void tipc_bearer_cleanup(void) void tipc_bearer_stop(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_bearer *b_ptr; u32 i; for (i = 0; i < MAX_BEARERS; i++) { - b_ptr = rtnl_dereference(bearer_list[i]); + b_ptr = rtnl_dereference(tn->bearer_list[i]); if (b_ptr) { bearer_disable(net, b_ptr, true); - bearer_list[i] = NULL; + tn->bearer_list[i] = NULL; } } } @@ -694,6 +701,8 @@ int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb) int i = cb->args[0]; struct tipc_bearer *bearer; struct tipc_nl_msg msg; + struct net *net = sock_net(skb->sk); + struct tipc_net *tn = net_generic(net, tipc_net_id); if (i == MAX_BEARERS) return 0; @@ -704,7 +713,7 @@ int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb) rtnl_lock(); for (i = 0; i < MAX_BEARERS; i++) { - bearer = rtnl_dereference(bearer_list[i]); + bearer = rtnl_dereference(tn->bearer_list[i]); if (!bearer) continue; @@ -726,6 +735,7 @@ int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info) struct tipc_bearer *bearer; struct tipc_nl_msg msg; struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1]; + struct net *net = genl_info_net(info); if (!info->attrs[TIPC_NLA_BEARER]) return -EINVAL; @@ -749,7 +759,7 @@ int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info) msg.seq = info->snd_seq; rtnl_lock(); - bearer = tipc_bearer_find(name); + bearer = tipc_bearer_find(net, name); if (!bearer) { err = -EINVAL; goto err_out; @@ -791,7 +801,7 @@ int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info) name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); rtnl_lock(); - bearer = tipc_bearer_find(name); + bearer = tipc_bearer_find(net, name); if (!bearer) { rtnl_unlock(); return -EINVAL; @@ -861,6 +871,7 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info) char *name; struct tipc_bearer *b; struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1]; + struct net *net = genl_info_net(info); if (!info->attrs[TIPC_NLA_BEARER]) return -EINVAL; @@ -876,7 +887,7 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info) name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); rtnl_lock(); - b = tipc_bearer_find(name); + b = tipc_bearer_find(net, name); if (!b) { rtnl_unlock(); return -EINVAL; diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 91a8eeea309c..01722d6b2058 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -92,7 +92,7 @@ struct tipc_media { int (*send_msg)(struct sk_buff *buf, struct tipc_bearer *b_ptr, struct tipc_media_addr *dest); - int (*enable_media)(struct tipc_bearer *b_ptr); + int (*enable_media)(struct net *net, struct tipc_bearer *b_ptr); void (*disable_media)(struct tipc_bearer *b_ptr); int (*addr2str)(struct tipc_media_addr *addr, char *strbuf, @@ -159,8 +159,6 @@ struct tipc_bearer_names { struct tipc_link; -extern struct tipc_bearer __rcu *bearer_list[]; - /* * TIPC routines available to supported media types */ @@ -193,20 +191,20 @@ int tipc_media_set_priority(const char *name, u32 new_value); int tipc_media_set_window(const char *name, u32 new_value); void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a); struct sk_buff *tipc_media_get_names(void); -int tipc_enable_l2_media(struct tipc_bearer *b); +int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b); void tipc_disable_l2_media(struct tipc_bearer *b); int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b, struct tipc_media_addr *dest); -struct sk_buff *tipc_bearer_get_names(void); -void tipc_bearer_add_dest(u32 bearer_id, u32 dest); -void tipc_bearer_remove_dest(u32 bearer_id, u32 dest); -struct tipc_bearer *tipc_bearer_find(const char *name); +struct sk_buff *tipc_bearer_get_names(struct net *net); +void tipc_bearer_add_dest(struct net *net, u32 bearer_id, u32 dest); +void tipc_bearer_remove_dest(struct net *net, u32 bearer_id, u32 dest); +struct tipc_bearer *tipc_bearer_find(struct net *net, const char *name); struct tipc_media *tipc_media_find(const char *name); int tipc_bearer_setup(void); void tipc_bearer_cleanup(void); void tipc_bearer_stop(struct net *net); -void tipc_bearer_send(u32 bearer_id, struct sk_buff *buf, +void tipc_bearer_send(struct net *net, u32 bearer_id, struct sk_buff *buf, struct tipc_media_addr *dest); #endif /* _TIPC_BEARER_H */ diff --git a/net/tipc/config.c b/net/tipc/config.c index cf2d417ad488..ac73291d0d32 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -251,7 +251,7 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, rep_tlv_buf = tipc_nametbl_get(req_tlv_area, req_tlv_space); break; case TIPC_CMD_GET_BEARER_NAMES: - rep_tlv_buf = tipc_bearer_get_names(); + rep_tlv_buf = tipc_bearer_get_names(net); break; case TIPC_CMD_GET_MEDIA_NAMES: rep_tlv_buf = tipc_media_get_names(); diff --git a/net/tipc/core.h b/net/tipc/core.h index 4fb113397e7b..75a332b1968e 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -60,6 +60,7 @@ #include #include "node.h" +#include "bearer.h" #define TIPC_MOD_VER "2.0.0" @@ -87,6 +88,9 @@ struct tipc_net { struct list_head node_list; u32 num_nodes; u32 num_links; + + /* Bearer list */ + struct tipc_bearer __rcu *bearer_list[MAX_BEARERS + 1]; }; #ifdef CONFIG_SYSCTL diff --git a/net/tipc/discover.c b/net/tipc/discover.c index f0fd8b449aef..f93dd3dd621b 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -51,6 +51,7 @@ /** * struct tipc_link_req - information about an ongoing link setup request * @bearer_id: identity of bearer issuing requests + * @net: network namespace instance * @dest: destination address for request messages * @domain: network domain to which links can be established * @num_nodes: number of nodes currently discovered (i.e. with an active link) @@ -62,6 +63,7 @@ struct tipc_link_req { u32 bearer_id; struct tipc_media_addr dest; + struct net *net; u32 domain; int num_nodes; spinlock_t lock; @@ -254,7 +256,7 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf, rbuf = tipc_buf_acquire(INT_H_SIZE); if (rbuf) { tipc_disc_init_msg(net, rbuf, DSC_RESP_MSG, bearer); - tipc_bearer_send(bearer->identity, rbuf, &maddr); + tipc_bearer_send(net, bearer->identity, rbuf, &maddr); kfree_skb(rbuf); } } @@ -328,7 +330,7 @@ static void disc_timeout(unsigned long data) * hold at fast polling rate if don't have any associated nodes, * otherwise hold at slow polling rate */ - tipc_bearer_send(req->bearer_id, req->buf, &req->dest); + tipc_bearer_send(req->net, req->bearer_id, req->buf, &req->dest); req->timer_intv *= 2; @@ -370,6 +372,7 @@ int tipc_disc_create(struct net *net, struct tipc_bearer *b_ptr, tipc_disc_init_msg(net, req->buf, DSC_REQ_MSG, b_ptr); memcpy(&req->dest, dest, sizeof(*dest)); + req->net = net; req->bearer_id = b_ptr->identity; req->domain = b_ptr->domain; req->num_nodes = 0; @@ -378,7 +381,7 @@ int tipc_disc_create(struct net *net, struct tipc_bearer *b_ptr, setup_timer(&req->timer, disc_timeout, (unsigned long)req); mod_timer(&req->timer, jiffies + req->timer_intv); b_ptr->link_req = req; - tipc_bearer_send(req->bearer_id, req->buf, &req->dest); + tipc_bearer_send(net, req->bearer_id, req->buf, &req->dest); return 0; } @@ -405,11 +408,12 @@ void tipc_disc_reset(struct net *net, struct tipc_bearer *b_ptr) spin_lock_bh(&req->lock); tipc_disc_init_msg(net, req->buf, DSC_REQ_MSG, b_ptr); + req->net = net; req->bearer_id = b_ptr->identity; req->domain = b_ptr->domain; req->num_nodes = 0; req->timer_intv = TIPC_LINK_REQ_INIT; mod_timer(&req->timer, jiffies + req->timer_intv); - tipc_bearer_send(req->bearer_id, req->buf, &req->dest); + tipc_bearer_send(net, req->bearer_id, req->buf, &req->dest); spin_unlock_bh(&req->lock); } diff --git a/net/tipc/link.c b/net/tipc/link.c index f6505652742e..be21e6ac73fe 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -129,11 +129,13 @@ static unsigned int align(unsigned int i) static void link_init_max_pkt(struct tipc_link *l_ptr) { + struct tipc_node *node = l_ptr->owner; + struct tipc_net *tn = net_generic(node->net, tipc_net_id); struct tipc_bearer *b_ptr; u32 max_pkt; rcu_read_lock(); - b_ptr = rcu_dereference_rtnl(bearer_list[l_ptr->bearer_id]); + b_ptr = rcu_dereference_rtnl(tn->bearer_list[l_ptr->bearer_id]); if (!b_ptr) { rcu_read_unlock(); return; @@ -431,7 +433,7 @@ void tipc_link_reset(struct tipc_link *l_ptr) return; tipc_node_link_down(l_ptr->owner, l_ptr); - tipc_bearer_remove_dest(l_ptr->bearer_id, l_ptr->addr); + tipc_bearer_remove_dest(owner->net, l_ptr->bearer_id, l_ptr->addr); if (was_active_link && tipc_node_active_links(l_ptr->owner)) { l_ptr->reset_checkpoint = checkpoint; @@ -471,11 +473,14 @@ void tipc_link_reset_list(struct net *net, unsigned int bearer_id) rcu_read_unlock(); } -static void link_activate(struct tipc_link *l_ptr) +static void link_activate(struct tipc_link *link) { - l_ptr->next_in_no = l_ptr->stats.recv_info = 1; - tipc_node_link_up(l_ptr->owner, l_ptr); - tipc_bearer_add_dest(l_ptr->bearer_id, l_ptr->addr); + struct tipc_node *node = link->owner; + + link->next_in_no = 1; + link->stats.recv_info = 1; + tipc_node_link_up(node, link); + tipc_bearer_add_dest(node->net, link->bearer_id, link->addr); } /** @@ -707,7 +712,8 @@ drop: * Only the socket functions tipc_send_stream() and tipc_send_packet() need * to act on the return value, since they may need to do more send attempts. */ -int __tipc_link_xmit(struct tipc_link *link, struct sk_buff_head *list) +int __tipc_link_xmit(struct net *net, struct tipc_link *link, + struct sk_buff_head *list) { struct tipc_msg *msg = buf_msg(skb_peek(list)); uint psz = msg_size(msg); @@ -740,7 +746,8 @@ int __tipc_link_xmit(struct tipc_link *link, struct sk_buff_head *list) if (skb_queue_len(outqueue) < sndlim) { __skb_queue_tail(outqueue, skb); - tipc_bearer_send(link->bearer_id, skb, addr); + tipc_bearer_send(net, link->bearer_id, + skb, addr); link->next_out = NULL; link->unacked_window = 0; } else if (tipc_msg_bundle(outqueue, skb, mtu)) { @@ -774,7 +781,7 @@ static int __tipc_link_xmit_skb(struct tipc_link *link, struct sk_buff *skb) struct sk_buff_head head; skb2list(skb, &head); - return __tipc_link_xmit(link, &head); + return __tipc_link_xmit(link->owner->net, link, &head); } int tipc_link_xmit_skb(struct net *net, struct sk_buff *skb, u32 dnode, @@ -808,7 +815,7 @@ int tipc_link_xmit(struct net *net, struct sk_buff_head *list, u32 dnode, tipc_node_lock(node); link = node->active_links[selector & 1]; if (link) - rc = __tipc_link_xmit(link, list); + rc = __tipc_link_xmit(net, link, list); tipc_node_unlock(node); } @@ -900,7 +907,8 @@ void tipc_link_push_packets(struct tipc_link *l_ptr) msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); if (msg_user(msg) == MSG_BUNDLER) TIPC_SKB_CB(skb)->bundling = false; - tipc_bearer_send(l_ptr->bearer_id, skb, + tipc_bearer_send(l_ptr->owner->net, + l_ptr->bearer_id, skb, &l_ptr->media_addr); l_ptr->next_out = tipc_skb_queue_next(outqueue, skb); } else { @@ -997,7 +1005,8 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *skb, msg = buf_msg(skb); msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); - tipc_bearer_send(l_ptr->bearer_id, skb, &l_ptr->media_addr); + tipc_bearer_send(l_ptr->owner->net, l_ptr->bearer_id, skb, + &l_ptr->media_addr); retransmits--; l_ptr->stats.retransmitted++; } @@ -1459,7 +1468,8 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg, skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg)); buf->priority = TC_PRIO_CONTROL; - tipc_bearer_send(l_ptr->bearer_id, buf, &l_ptr->media_addr); + tipc_bearer_send(l_ptr->owner->net, l_ptr->bearer_id, buf, + &l_ptr->media_addr); l_ptr->unacked_window = 0; kfree_skb(buf); } @@ -2037,7 +2047,7 @@ static int link_cmd_set_value(struct net *net, const char *name, u32 new_value, return res; } - b_ptr = tipc_bearer_find(name); + b_ptr = tipc_bearer_find(net, name); if (b_ptr) { switch (cmd) { case TIPC_CMD_SET_LINK_TOL: @@ -2295,10 +2305,11 @@ struct sk_buff *tipc_link_cmd_show_stats(struct net *net, static void link_print(struct tipc_link *l_ptr, const char *str) { + struct tipc_net *tn = net_generic(l_ptr->owner->net, tipc_net_id); struct tipc_bearer *b_ptr; rcu_read_lock(); - b_ptr = rcu_dereference_rtnl(bearer_list[l_ptr->bearer_id]); + b_ptr = rcu_dereference_rtnl(tn->bearer_list[l_ptr->bearer_id]); if (b_ptr) pr_info("%s Link %x<%s>:", str, l_ptr->addr, b_ptr->name); rcu_read_unlock(); diff --git a/net/tipc/link.h b/net/tipc/link.h index 380e27ee0f70..9df7fa4d3bdd 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -223,7 +223,8 @@ int tipc_link_xmit_skb(struct net *net, struct sk_buff *skb, u32 dest, u32 selector); int tipc_link_xmit(struct net *net, struct sk_buff_head *list, u32 dest, u32 selector); -int __tipc_link_xmit(struct tipc_link *link, struct sk_buff_head *list); +int __tipc_link_xmit(struct net *net, struct tipc_link *link, + struct sk_buff_head *list); void tipc_link_bundle_rcv(struct net *net, struct sk_buff *buf); void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int prob, u32 gap, u32 tolerance, u32 priority, u32 acked_mtu); diff --git a/net/tipc/net.c b/net/tipc/net.c index de18aacf3d64..38633e5f8a7d 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -117,7 +117,7 @@ int tipc_net_start(struct net *net, u32 addr) tipc_own_addr = addr; tipc_named_reinit(); tipc_sk_reinit(); - res = tipc_bclink_init(); + res = tipc_bclink_init(net); if (res) return res; @@ -140,7 +140,7 @@ void tipc_net_stop(struct net *net) tipc_own_addr); rtnl_lock(); tipc_bearer_stop(net); - tipc_bclink_stop(); + tipc_bclink_stop(net); tipc_node_stop(net); rtnl_unlock(); -- cgit v1.2.3-70-g09d2 From e05b31f4bf8994d49322e9afb004ad479a129db0 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Fri, 9 Jan 2015 15:27:08 +0800 Subject: tipc: make tipc socket support net namespace Now tipc socket table is statically allocated as a global variable. Through it, we can look up one socket instance with port ID, insert a new socket instance to the table, and delete a socket from the table. But when tipc supports net namespace, each namespace must own its specific socket table. So the global variable of socket table must be redefined in tipc_net structure. As a concequence, a new socket table will be allocated when a new namespace is created, and a socket table will be deallocated when namespace is destroyed. Signed-off-by: Ying Xue Tested-by: Tero Aho Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/config.c | 2 +- net/tipc/core.c | 12 ++++-------- net/tipc/core.h | 4 ++++ net/tipc/net.c | 2 +- net/tipc/socket.c | 48 +++++++++++++++++++++++++++++------------------- net/tipc/socket.h | 8 ++++---- 6 files changed, 43 insertions(+), 33 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/config.c b/net/tipc/config.c index ac73291d0d32..20b1c5812f00 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -257,7 +257,7 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, rep_tlv_buf = tipc_media_get_names(); break; case TIPC_CMD_SHOW_PORTS: - rep_tlv_buf = tipc_sk_socks_show(); + rep_tlv_buf = tipc_sk_socks_show(net); break; case TIPC_CMD_SHOW_STATS: rep_tlv_buf = tipc_show_stats(); diff --git a/net/tipc/core.c b/net/tipc/core.c index 7b8443938caf..23ff3caa1ce6 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -55,17 +55,20 @@ int sysctl_tipc_rmem[3] __read_mostly; /* min/default/max */ static int __net_init tipc_init_net(struct net *net) { struct tipc_net *tn = net_generic(net, tipc_net_id); + int err; tn->net_id = 4711; INIT_LIST_HEAD(&tn->node_list); spin_lock_init(&tn->node_list_lock); - return 0; + err = tipc_sk_rht_init(net); + return err; } static void __net_exit tipc_exit_net(struct net *net) { tipc_net_stop(net); + tipc_sk_rht_destroy(net); } static struct pernet_operations tipc_net_ops = { @@ -95,10 +98,6 @@ static int __init tipc_init(void) if (err) goto out_pernet; - err = tipc_sk_rht_init(); - if (err) - goto out_reftbl; - err = tipc_nametbl_init(); if (err) goto out_nametbl; @@ -136,8 +135,6 @@ out_socket: out_netlink: tipc_nametbl_stop(); out_nametbl: - tipc_sk_rht_destroy(); -out_reftbl: unregister_pernet_subsys(&tipc_net_ops); out_pernet: pr_err("Unable to start in single node mode\n"); @@ -153,7 +150,6 @@ static void __exit tipc_exit(void) tipc_nametbl_stop(); tipc_socket_stop(); tipc_unregister_sysctl(); - tipc_sk_rht_destroy(); pr_info("Deactivated\n"); } diff --git a/net/tipc/core.h b/net/tipc/core.h index 3f6f9e07da99..1a7f81643668 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -58,6 +58,7 @@ #include #include #include +#include #include "node.h" #include "bearer.h" @@ -101,6 +102,9 @@ struct tipc_net { struct tipc_bcbearer *bcbearer; struct tipc_bclink *bclink; struct tipc_link *bcl; + + /* Socket hash table */ + struct rhashtable sk_rht; }; #ifdef CONFIG_SYSCTL diff --git a/net/tipc/net.c b/net/tipc/net.c index 7548ba80d289..44ccf47c79a3 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -117,7 +117,7 @@ int tipc_net_start(struct net *net, u32 addr) tipc_own_addr = addr; tipc_named_reinit(); - tipc_sk_reinit(); + tipc_sk_reinit(net); res = tipc_bclink_init(net); if (res) return res; diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 68831453bc0e..accb02cb3527 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -115,7 +115,7 @@ static int tipc_sk_publish(struct tipc_sock *tsk, uint scope, struct tipc_name_seq const *seq); static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope, struct tipc_name_seq const *seq); -static struct tipc_sock *tipc_sk_lookup(u32 portid); +static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid); static int tipc_sk_insert(struct tipc_sock *tsk); static void tipc_sk_remove(struct tipc_sock *tsk); @@ -179,9 +179,6 @@ static const struct nla_policy tipc_nl_sock_policy[TIPC_NLA_SOCK_MAX + 1] = { * - port reference */ -/* Protects tipc socket hash table mutations */ -static struct rhashtable tipc_sk_rht; - static u32 tsk_peer_node(struct tipc_sock *tsk) { return msg_destnode(&tsk->phdr); @@ -1766,7 +1763,7 @@ int tipc_sk_rcv(struct net *net, struct sk_buff *skb) u32 dnode; /* Validate destination and message */ - tsk = tipc_sk_lookup(dport); + tsk = tipc_sk_lookup(net, dport); if (unlikely(!tsk)) { rc = tipc_msg_eval(skb, &dnode); goto exit; @@ -2245,8 +2242,9 @@ static int tipc_sk_show(struct tipc_sock *tsk, char *buf, return ret; } -struct sk_buff *tipc_sk_socks_show(void) +struct sk_buff *tipc_sk_socks_show(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); const struct bucket_table *tbl; struct rhash_head *pos; struct sk_buff *buf; @@ -2265,7 +2263,7 @@ struct sk_buff *tipc_sk_socks_show(void) pb_len = ULTRA_STRING_MAX_LEN; rcu_read_lock(); - tbl = rht_dereference_rcu((&tipc_sk_rht)->tbl, &tipc_sk_rht); + tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht); for (i = 0; i < tbl->size; i++) { rht_for_each_entry_rcu(tsk, pos, tbl, i, node) { spin_lock_bh(&tsk->sk.sk_lock.slock); @@ -2286,8 +2284,9 @@ struct sk_buff *tipc_sk_socks_show(void) /* tipc_sk_reinit: set non-zero address in all existing sockets * when we go from standalone to network mode. */ -void tipc_sk_reinit(void) +void tipc_sk_reinit(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); const struct bucket_table *tbl; struct rhash_head *pos; struct tipc_sock *tsk; @@ -2295,7 +2294,7 @@ void tipc_sk_reinit(void) int i; rcu_read_lock(); - tbl = rht_dereference_rcu((&tipc_sk_rht)->tbl, &tipc_sk_rht); + tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht); for (i = 0; i < tbl->size; i++) { rht_for_each_entry_rcu(tsk, pos, tbl, i, node) { spin_lock_bh(&tsk->sk.sk_lock.slock); @@ -2308,12 +2307,13 @@ void tipc_sk_reinit(void) rcu_read_unlock(); } -static struct tipc_sock *tipc_sk_lookup(u32 portid) +static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_sock *tsk; rcu_read_lock(); - tsk = rhashtable_lookup(&tipc_sk_rht, &portid); + tsk = rhashtable_lookup(&tn->sk_rht, &portid); if (tsk) sock_hold(&tsk->sk); rcu_read_unlock(); @@ -2323,6 +2323,9 @@ static struct tipc_sock *tipc_sk_lookup(u32 portid) static int tipc_sk_insert(struct tipc_sock *tsk) { + struct sock *sk = &tsk->sk; + struct net *net = sock_net(sk); + struct tipc_net *tn = net_generic(net, tipc_net_id); u32 remaining = (TIPC_MAX_PORT - TIPC_MIN_PORT) + 1; u32 portid = prandom_u32() % remaining + TIPC_MIN_PORT; @@ -2332,7 +2335,7 @@ static int tipc_sk_insert(struct tipc_sock *tsk) portid = TIPC_MIN_PORT; tsk->portid = portid; sock_hold(&tsk->sk); - if (rhashtable_lookup_insert(&tipc_sk_rht, &tsk->node)) + if (rhashtable_lookup_insert(&tn->sk_rht, &tsk->node)) return 0; sock_put(&tsk->sk); } @@ -2343,15 +2346,17 @@ static int tipc_sk_insert(struct tipc_sock *tsk) static void tipc_sk_remove(struct tipc_sock *tsk) { struct sock *sk = &tsk->sk; + struct tipc_net *tn = net_generic(sock_net(sk), tipc_net_id); - if (rhashtable_remove(&tipc_sk_rht, &tsk->node)) { + if (rhashtable_remove(&tn->sk_rht, &tsk->node)) { WARN_ON(atomic_read(&sk->sk_refcnt) == 1); __sock_put(sk); } } -int tipc_sk_rht_init(void) +int tipc_sk_rht_init(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct rhashtable_params rht_params = { .nelem_hint = 192, .head_offset = offsetof(struct tipc_sock, node), @@ -2364,15 +2369,17 @@ int tipc_sk_rht_init(void) .shrink_decision = rht_shrink_below_30, }; - return rhashtable_init(&tipc_sk_rht, &rht_params); + return rhashtable_init(&tn->sk_rht, &rht_params); } -void tipc_sk_rht_destroy(void) +void tipc_sk_rht_destroy(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); + /* Wait for socket readers to complete */ synchronize_net(); - rhashtable_destroy(&tipc_sk_rht); + rhashtable_destroy(&tn->sk_rht); } /** @@ -2730,10 +2737,12 @@ int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb) struct rhash_head *pos; u32 prev_portid = cb->args[0]; u32 portid = prev_portid; + struct net *net = sock_net(skb->sk); + struct tipc_net *tn = net_generic(net, tipc_net_id); int i; rcu_read_lock(); - tbl = rht_dereference_rcu((&tipc_sk_rht)->tbl, &tipc_sk_rht); + tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht); for (i = 0; i < tbl->size; i++) { rht_for_each_entry_rcu(tsk, pos, tbl, i, node) { spin_lock_bh(&tsk->sk.sk_lock.slock); @@ -2839,6 +2848,7 @@ int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb) u32 tsk_portid = cb->args[0]; u32 last_publ = cb->args[1]; u32 done = cb->args[2]; + struct net *net = sock_net(skb->sk); struct tipc_sock *tsk; if (!tsk_portid) { @@ -2864,7 +2874,7 @@ int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb) if (done) return 0; - tsk = tipc_sk_lookup(tsk_portid); + tsk = tipc_sk_lookup(net, tsk_portid); if (!tsk) return -EINVAL; diff --git a/net/tipc/socket.h b/net/tipc/socket.h index eb15c3107920..c15c4e121fe3 100644 --- a/net/tipc/socket.h +++ b/net/tipc/socket.h @@ -50,11 +50,11 @@ void tipc_sock_release_local(struct socket *sock); int tipc_sock_accept_local(struct socket *sock, struct socket **newsock, int flags); int tipc_sk_rcv(struct net *net, struct sk_buff *buf); -struct sk_buff *tipc_sk_socks_show(void); +struct sk_buff *tipc_sk_socks_show(struct net *net); void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *buf); -void tipc_sk_reinit(void); -int tipc_sk_rht_init(void); -void tipc_sk_rht_destroy(void); +void tipc_sk_reinit(struct net *net); +int tipc_sk_rht_init(struct net *net); +void tipc_sk_rht_destroy(struct net *net); int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb); int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb); -- cgit v1.2.3-70-g09d2 From 4ac1c8d0ee9faf3a4be185cc4db1381fa0d81280 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Fri, 9 Jan 2015 15:27:09 +0800 Subject: tipc: name tipc name table support net namespace TIPC name table is used to store the mapping relationship between TIPC service name and socket port ID. When tipc supports namespace, it allows users to publish service names only owned by a certain namespace. Therefore, every namespace must have its private name table to prevent service names published to one namespace from being contaminated by other service names in another namespace. Therefore, The name table global variable (ie, nametbl) and its lock must be moved to tipc_net structure, and a parameter of namespace must be added for necessary functions so that they can obtain name table variable defined in tipc_net structure. Signed-off-by: Ying Xue Tested-by: Tero Aho Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/config.c | 3 +- net/tipc/core.c | 19 +++++--- net/tipc/core.h | 4 ++ net/tipc/msg.c | 4 +- net/tipc/msg.h | 2 +- net/tipc/name_distr.c | 37 +++++++++------ net/tipc/name_distr.h | 4 +- net/tipc/name_table.c | 128 ++++++++++++++++++++++++++++---------------------- net/tipc/name_table.h | 25 +++++----- net/tipc/net.c | 2 +- net/tipc/server.c | 3 +- net/tipc/server.h | 10 ++-- net/tipc/socket.c | 11 ++--- net/tipc/subscr.c | 16 ++++--- net/tipc/subscr.h | 2 + 15 files changed, 154 insertions(+), 116 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/config.c b/net/tipc/config.c index 20b1c5812f00..974723a1e32e 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -248,7 +248,8 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, req_tlv_space); break; case TIPC_CMD_SHOW_NAME_TABLE: - rep_tlv_buf = tipc_nametbl_get(req_tlv_area, req_tlv_space); + rep_tlv_buf = tipc_nametbl_get(net, req_tlv_area, + req_tlv_space); break; case TIPC_CMD_GET_BEARER_NAMES: rep_tlv_buf = tipc_bearer_get_names(net); diff --git a/net/tipc/core.c b/net/tipc/core.c index 23ff3caa1ce6..63cde8148aaf 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -62,12 +62,24 @@ static int __net_init tipc_init_net(struct net *net) spin_lock_init(&tn->node_list_lock); err = tipc_sk_rht_init(net); + if (err) + goto out_sk_rht; + + err = tipc_nametbl_init(net); + if (err) + goto out_nametbl; + return 0; + +out_nametbl: + tipc_sk_rht_destroy(net); +out_sk_rht: return err; } static void __net_exit tipc_exit_net(struct net *net) { tipc_net_stop(net); + tipc_nametbl_stop(net); tipc_sk_rht_destroy(net); } @@ -98,10 +110,6 @@ static int __init tipc_init(void) if (err) goto out_pernet; - err = tipc_nametbl_init(); - if (err) - goto out_nametbl; - err = tipc_netlink_start(); if (err) goto out_netlink; @@ -133,8 +141,6 @@ out_sysctl: out_socket: tipc_netlink_stop(); out_netlink: - tipc_nametbl_stop(); -out_nametbl: unregister_pernet_subsys(&tipc_net_ops); out_pernet: pr_err("Unable to start in single node mode\n"); @@ -147,7 +153,6 @@ static void __exit tipc_exit(void) tipc_bearer_cleanup(); tipc_netlink_stop(); tipc_subscr_stop(); - tipc_nametbl_stop(); tipc_socket_stop(); tipc_unregister_sysctl(); diff --git a/net/tipc/core.h b/net/tipc/core.h index 1a7f81643668..893992944570 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -105,6 +105,10 @@ struct tipc_net { /* Socket hash table */ struct rhashtable sk_rht; + + /* Name table */ + spinlock_t nametbl_lock; + struct name_table *nametbl; }; #ifdef CONFIG_SYSCTL diff --git a/net/tipc/msg.c b/net/tipc/msg.c index a38f6a680df1..642fb137463c 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -426,7 +426,7 @@ exit: * Returns 0 (TIPC_OK) if message ok and we can try again, -TIPC error * code if message to be rejected */ -int tipc_msg_eval(struct sk_buff *buf, u32 *dnode) +int tipc_msg_eval(struct net *net, struct sk_buff *buf, u32 *dnode) { struct tipc_msg *msg = buf_msg(buf); u32 dport; @@ -441,7 +441,7 @@ int tipc_msg_eval(struct sk_buff *buf, u32 *dnode) return -TIPC_ERR_NO_NAME; *dnode = addr_domain(msg_lookup_scope(msg)); - dport = tipc_nametbl_translate(msg_nametype(msg), + dport = tipc_nametbl_translate(net, msg_nametype(msg), msg_nameinst(msg), dnode); if (!dport) diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 75f324287244..69f37e652a8e 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -749,7 +749,7 @@ static inline u32 msg_tot_origport(struct tipc_msg *m) struct sk_buff *tipc_buf_acquire(u32 size); bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err); -int tipc_msg_eval(struct sk_buff *buf, u32 *dnode); +int tipc_msg_eval(struct net *net, struct sk_buff *buf, u32 *dnode); void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, u32 destnode); struct sk_buff *tipc_msg_create(uint user, uint type, uint hdr_sz, diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index d40df588263e..ba421321d15d 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -109,13 +109,14 @@ void named_cluster_distribute(struct net *net, struct sk_buff *skb) /** * tipc_named_publish - tell other nodes about a new publication by this node */ -struct sk_buff *tipc_named_publish(struct publication *publ) +struct sk_buff *tipc_named_publish(struct net *net, struct publication *publ) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct sk_buff *buf; struct distr_item *item; list_add_tail_rcu(&publ->local_list, - &tipc_nametbl->publ_list[publ->scope]); + &tn->nametbl->publ_list[publ->scope]); if (publ->scope == TIPC_NODE_SCOPE) return NULL; @@ -206,15 +207,16 @@ static void named_distribute(struct net *net, struct sk_buff_head *list, */ void tipc_named_node_up(struct net *net, u32 dnode) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct sk_buff_head head; __skb_queue_head_init(&head); rcu_read_lock(); named_distribute(net, &head, dnode, - &tipc_nametbl->publ_list[TIPC_CLUSTER_SCOPE]); + &tn->nametbl->publ_list[TIPC_CLUSTER_SCOPE]); named_distribute(net, &head, dnode, - &tipc_nametbl->publ_list[TIPC_ZONE_SCOPE]); + &tn->nametbl->publ_list[TIPC_ZONE_SCOPE]); rcu_read_unlock(); tipc_link_xmit(net, &head, dnode, dnode); @@ -262,14 +264,15 @@ static void tipc_publ_unsubscribe(struct net *net, struct publication *publ, */ static void tipc_publ_purge(struct net *net, struct publication *publ, u32 addr) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct publication *p; - spin_lock_bh(&tipc_nametbl_lock); - p = tipc_nametbl_remove_publ(publ->type, publ->lower, + spin_lock_bh(&tn->nametbl_lock); + p = tipc_nametbl_remove_publ(net, publ->type, publ->lower, publ->node, publ->ref, publ->key); if (p) tipc_publ_unsubscribe(net, p, addr); - spin_unlock_bh(&tipc_nametbl_lock); + spin_unlock_bh(&tn->nametbl_lock); if (p != publ) { pr_err("Unable to remove publication from failed node\n" @@ -302,7 +305,8 @@ static bool tipc_update_nametbl(struct net *net, struct distr_item *i, struct publication *publ = NULL; if (dtype == PUBLICATION) { - publ = tipc_nametbl_insert_publ(ntohl(i->type), ntohl(i->lower), + publ = tipc_nametbl_insert_publ(net, ntohl(i->type), + ntohl(i->lower), ntohl(i->upper), TIPC_CLUSTER_SCOPE, node, ntohl(i->ref), ntohl(i->key)); @@ -311,7 +315,8 @@ static bool tipc_update_nametbl(struct net *net, struct distr_item *i, return true; } } else if (dtype == WITHDRAWAL) { - publ = tipc_nametbl_remove_publ(ntohl(i->type), ntohl(i->lower), + publ = tipc_nametbl_remove_publ(net, ntohl(i->type), + ntohl(i->lower), node, ntohl(i->ref), ntohl(i->key)); if (publ) { @@ -376,19 +381,20 @@ void tipc_named_process_backlog(struct net *net) */ void tipc_named_rcv(struct net *net, struct sk_buff *buf) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_msg *msg = buf_msg(buf); struct distr_item *item = (struct distr_item *)msg_data(msg); u32 count = msg_data_sz(msg) / ITEM_SIZE; u32 node = msg_orignode(msg); - spin_lock_bh(&tipc_nametbl_lock); + spin_lock_bh(&tn->nametbl_lock); while (count--) { if (!tipc_update_nametbl(net, item, node, msg_type(msg))) tipc_named_add_backlog(item, msg_type(msg), node); item++; } tipc_named_process_backlog(net); - spin_unlock_bh(&tipc_nametbl_lock); + spin_unlock_bh(&tn->nametbl_lock); kfree_skb(buf); } @@ -399,17 +405,18 @@ void tipc_named_rcv(struct net *net, struct sk_buff *buf) * All name table entries published by this node are updated to reflect * the node's new network address. */ -void tipc_named_reinit(void) +void tipc_named_reinit(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct publication *publ; int scope; - spin_lock_bh(&tipc_nametbl_lock); + spin_lock_bh(&tn->nametbl_lock); for (scope = TIPC_ZONE_SCOPE; scope <= TIPC_NODE_SCOPE; scope++) - list_for_each_entry_rcu(publ, &tipc_nametbl->publ_list[scope], + list_for_each_entry_rcu(publ, &tn->nametbl->publ_list[scope], local_list) publ->node = tipc_own_addr; - spin_unlock_bh(&tipc_nametbl_lock); + spin_unlock_bh(&tn->nametbl_lock); } diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h index 8039d84351b3..1ed2d7e48290 100644 --- a/net/tipc/name_distr.h +++ b/net/tipc/name_distr.h @@ -67,12 +67,12 @@ struct distr_item { __be32 key; }; -struct sk_buff *tipc_named_publish(struct publication *publ); +struct sk_buff *tipc_named_publish(struct net *net, struct publication *publ); struct sk_buff *tipc_named_withdraw(struct publication *publ); void named_cluster_distribute(struct net *net, struct sk_buff *buf); void tipc_named_node_up(struct net *net, u32 dnode); void tipc_named_rcv(struct net *net, struct sk_buff *buf); -void tipc_named_reinit(void); +void tipc_named_reinit(struct net *net); void tipc_named_process_backlog(struct net *net); void tipc_publ_notify(struct net *net, struct list_head *nsub_list, u32 addr); diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index beed5fdda004..57e39c16a8c3 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -34,6 +34,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include #include "core.h" #include "config.h" #include "name_table.h" @@ -106,9 +107,6 @@ struct name_seq { struct rcu_head rcu; }; -struct name_table *tipc_nametbl; -DEFINE_SPINLOCK(tipc_nametbl_lock); - static int hash(int x) { return x & (TIPC_NAMETBL_SIZE - 1); @@ -448,12 +446,13 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, } } -static struct name_seq *nametbl_find_seq(u32 type) +static struct name_seq *nametbl_find_seq(struct net *net, u32 type) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct hlist_head *seq_head; struct name_seq *ns; - seq_head = &tipc_nametbl->seq_hlist[hash(type)]; + seq_head = &tn->nametbl->seq_hlist[hash(type)]; hlist_for_each_entry_rcu(ns, seq_head, ns_list) { if (ns->type == type) return ns; @@ -462,11 +461,13 @@ static struct name_seq *nametbl_find_seq(u32 type) return NULL; }; -struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, - u32 scope, u32 node, u32 port, u32 key) +struct publication *tipc_nametbl_insert_publ(struct net *net, u32 type, + u32 lower, u32 upper, u32 scope, + u32 node, u32 port, u32 key) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct publication *publ; - struct name_seq *seq = nametbl_find_seq(type); + struct name_seq *seq = nametbl_find_seq(net, type); int index = hash(type); if ((scope < TIPC_ZONE_SCOPE) || (scope > TIPC_NODE_SCOPE) || @@ -477,8 +478,7 @@ struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, } if (!seq) - seq = tipc_nameseq_create(type, - &tipc_nametbl->seq_hlist[index]); + seq = tipc_nameseq_create(type, &tn->nametbl->seq_hlist[index]); if (!seq) return NULL; @@ -489,11 +489,12 @@ struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, return publ; } -struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, - u32 node, u32 ref, u32 key) +struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type, + u32 lower, u32 node, u32 ref, + u32 key) { struct publication *publ; - struct name_seq *seq = nametbl_find_seq(type); + struct name_seq *seq = nametbl_find_seq(net, type); if (!seq) return NULL; @@ -524,7 +525,8 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, * - if name translation is attempted and fails, sets 'destnode' to 0 * and returns 0 */ -u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) +u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, + u32 *destnode) { struct sub_seq *sseq; struct name_info *info; @@ -537,7 +539,7 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) return 0; rcu_read_lock(); - seq = nametbl_find_seq(type); + seq = nametbl_find_seq(net, type); if (unlikely(!seq)) goto not_found; spin_lock_bh(&seq->lock); @@ -610,8 +612,8 @@ not_found: * * Returns non-zero if any off-node ports overlap */ -int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, - struct tipc_port_list *dports) +int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper, + u32 limit, struct tipc_port_list *dports) { struct name_seq *seq; struct sub_seq *sseq; @@ -620,7 +622,7 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, int res = 0; rcu_read_lock(); - seq = nametbl_find_seq(type); + seq = nametbl_find_seq(net, type); if (!seq) goto exit; @@ -657,24 +659,25 @@ struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower, { struct publication *publ; struct sk_buff *buf = NULL; + struct tipc_net *tn = net_generic(net, tipc_net_id); - spin_lock_bh(&tipc_nametbl_lock); - if (tipc_nametbl->local_publ_count >= TIPC_MAX_PUBLICATIONS) { + spin_lock_bh(&tn->nametbl_lock); + if (tn->nametbl->local_publ_count >= TIPC_MAX_PUBLICATIONS) { pr_warn("Publication failed, local publication limit reached (%u)\n", TIPC_MAX_PUBLICATIONS); - spin_unlock_bh(&tipc_nametbl_lock); + spin_unlock_bh(&tn->nametbl_lock); return NULL; } - publ = tipc_nametbl_insert_publ(type, lower, upper, scope, - tipc_own_addr, port_ref, key); + publ = tipc_nametbl_insert_publ(net, type, lower, upper, scope, + tipc_own_addr, port_ref, key); if (likely(publ)) { - tipc_nametbl->local_publ_count++; - buf = tipc_named_publish(publ); + tn->nametbl->local_publ_count++; + buf = tipc_named_publish(net, publ); /* Any pending external events? */ tipc_named_process_backlog(net); } - spin_unlock_bh(&tipc_nametbl_lock); + spin_unlock_bh(&tn->nametbl_lock); if (buf) named_cluster_distribute(net, buf); @@ -689,11 +692,13 @@ int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref, { struct publication *publ; struct sk_buff *skb = NULL; + struct tipc_net *tn = net_generic(net, tipc_net_id); - spin_lock_bh(&tipc_nametbl_lock); - publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key); + spin_lock_bh(&tn->nametbl_lock); + publ = tipc_nametbl_remove_publ(net, type, lower, tipc_own_addr, + ref, key); if (likely(publ)) { - tipc_nametbl->local_publ_count--; + tn->nametbl->local_publ_count--; skb = tipc_named_withdraw(publ); /* Any pending external events? */ tipc_named_process_backlog(net); @@ -704,7 +709,7 @@ int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref, "(type=%u, lower=%u, ref=%u, key=%u)\n", type, lower, ref, key); } - spin_unlock_bh(&tipc_nametbl_lock); + spin_unlock_bh(&tn->nametbl_lock); if (skb) { named_cluster_distribute(net, skb); @@ -718,15 +723,15 @@ int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref, */ void tipc_nametbl_subscribe(struct tipc_subscription *s) { + struct tipc_net *tn = net_generic(s->net, tipc_net_id); u32 type = s->seq.type; int index = hash(type); struct name_seq *seq; - spin_lock_bh(&tipc_nametbl_lock); - seq = nametbl_find_seq(type); + spin_lock_bh(&tn->nametbl_lock); + seq = nametbl_find_seq(s->net, type); if (!seq) - seq = tipc_nameseq_create(type, - &tipc_nametbl->seq_hlist[index]); + seq = tipc_nameseq_create(type, &tn->nametbl->seq_hlist[index]); if (seq) { spin_lock_bh(&seq->lock); tipc_nameseq_subscribe(seq, s); @@ -735,7 +740,7 @@ void tipc_nametbl_subscribe(struct tipc_subscription *s) pr_warn("Failed to create subscription for {%u,%u,%u}\n", s->seq.type, s->seq.lower, s->seq.upper); } - spin_unlock_bh(&tipc_nametbl_lock); + spin_unlock_bh(&tn->nametbl_lock); } /** @@ -743,10 +748,11 @@ void tipc_nametbl_subscribe(struct tipc_subscription *s) */ void tipc_nametbl_unsubscribe(struct tipc_subscription *s) { + struct tipc_net *tn = net_generic(s->net, tipc_net_id); struct name_seq *seq; - spin_lock_bh(&tipc_nametbl_lock); - seq = nametbl_find_seq(s->seq.type); + spin_lock_bh(&tn->nametbl_lock); + seq = nametbl_find_seq(s->net, s->seq.type); if (seq != NULL) { spin_lock_bh(&seq->lock); list_del_init(&s->nameseq_list); @@ -759,7 +765,7 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s) spin_unlock_bh(&seq->lock); } } - spin_unlock_bh(&tipc_nametbl_lock); + spin_unlock_bh(&tn->nametbl_lock); } /** @@ -861,9 +867,10 @@ static int nametbl_header(char *buf, int len, u32 depth) /** * nametbl_list - print specified name table contents into the given buffer */ -static int nametbl_list(char *buf, int len, u32 depth_info, +static int nametbl_list(struct net *net, char *buf, int len, u32 depth_info, u32 type, u32 lowbound, u32 upbound) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct hlist_head *seq_head; struct name_seq *seq; int all_types; @@ -883,7 +890,7 @@ static int nametbl_list(char *buf, int len, u32 depth_info, lowbound = 0; upbound = ~0; for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { - seq_head = &tipc_nametbl->seq_hlist[i]; + seq_head = &tn->nametbl->seq_hlist[i]; hlist_for_each_entry_rcu(seq, seq_head, ns_list) { ret += nameseq_list(seq, buf + ret, len - ret, depth, seq->type, @@ -899,7 +906,7 @@ static int nametbl_list(char *buf, int len, u32 depth_info, } ret += nametbl_header(buf + ret, len - ret, depth); i = hash(type); - seq_head = &tipc_nametbl->seq_hlist[i]; + seq_head = &tn->nametbl->seq_hlist[i]; hlist_for_each_entry_rcu(seq, seq_head, ns_list) { if (seq->type == type) { ret += nameseq_list(seq, buf + ret, len - ret, @@ -912,7 +919,8 @@ static int nametbl_list(char *buf, int len, u32 depth_info, return ret; } -struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space) +struct sk_buff *tipc_nametbl_get(struct net *net, const void *req_tlv_area, + int req_tlv_space) { struct sk_buff *buf; struct tipc_name_table_query *argv; @@ -933,7 +941,7 @@ struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space) pb_len = ULTRA_STRING_MAX_LEN; argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area); rcu_read_lock(); - str_len = nametbl_list(pb, pb_len, ntohl(argv->depth), + str_len = nametbl_list(net, pb, pb_len, ntohl(argv->depth), ntohl(argv->type), ntohl(argv->lowbound), ntohl(argv->upbound)); rcu_read_unlock(); @@ -944,8 +952,10 @@ struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space) return buf; } -int tipc_nametbl_init(void) +int tipc_nametbl_init(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); + struct name_table *tipc_nametbl; int i; tipc_nametbl = kzalloc(sizeof(*tipc_nametbl), GFP_ATOMIC); @@ -958,6 +968,8 @@ int tipc_nametbl_init(void) INIT_LIST_HEAD(&tipc_nametbl->publ_list[TIPC_ZONE_SCOPE]); INIT_LIST_HEAD(&tipc_nametbl->publ_list[TIPC_CLUSTER_SCOPE]); INIT_LIST_HEAD(&tipc_nametbl->publ_list[TIPC_NODE_SCOPE]); + tn->nametbl = tipc_nametbl; + spin_lock_init(&tn->nametbl_lock); return 0; } @@ -966,7 +978,7 @@ int tipc_nametbl_init(void) * * tipc_nametbl_lock must be held when calling this function */ -static void tipc_purge_publications(struct name_seq *seq) +static void tipc_purge_publications(struct net *net, struct name_seq *seq) { struct publication *publ, *safe; struct sub_seq *sseq; @@ -976,8 +988,8 @@ static void tipc_purge_publications(struct name_seq *seq) sseq = seq->sseqs; info = sseq->info; list_for_each_entry_safe(publ, safe, &info->zone_list, zone_list) { - tipc_nametbl_remove_publ(publ->type, publ->lower, publ->node, - publ->ref, publ->key); + tipc_nametbl_remove_publ(net, publ->type, publ->lower, + publ->node, publ->ref, publ->key); kfree_rcu(publ, rcu); } hlist_del_init_rcu(&seq->ns_list); @@ -987,25 +999,27 @@ static void tipc_purge_publications(struct name_seq *seq) kfree_rcu(seq, rcu); } -void tipc_nametbl_stop(void) +void tipc_nametbl_stop(struct net *net) { u32 i; struct name_seq *seq; struct hlist_head *seq_head; + struct tipc_net *tn = net_generic(net, tipc_net_id); + struct name_table *tipc_nametbl = tn->nametbl; /* Verify name table is empty and purge any lingering * publications, then release the name table */ - spin_lock_bh(&tipc_nametbl_lock); + spin_lock_bh(&tn->nametbl_lock); for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { if (hlist_empty(&tipc_nametbl->seq_hlist[i])) continue; seq_head = &tipc_nametbl->seq_hlist[i]; hlist_for_each_entry_rcu(seq, seq_head, ns_list) { - tipc_purge_publications(seq); + tipc_purge_publications(net, seq); } } - spin_unlock_bh(&tipc_nametbl_lock); + spin_unlock_bh(&tn->nametbl_lock); synchronize_net(); kfree(tipc_nametbl); @@ -1109,9 +1123,10 @@ static int __tipc_nl_subseq_list(struct tipc_nl_msg *msg, struct name_seq *seq, return 0; } -static int __tipc_nl_seq_list(struct tipc_nl_msg *msg, u32 *last_type, - u32 *last_lower, u32 *last_publ) +static int tipc_nl_seq_list(struct net *net, struct tipc_nl_msg *msg, + u32 *last_type, u32 *last_lower, u32 *last_publ) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct hlist_head *seq_head; struct name_seq *seq = NULL; int err; @@ -1123,10 +1138,10 @@ static int __tipc_nl_seq_list(struct tipc_nl_msg *msg, u32 *last_type, i = 0; for (; i < TIPC_NAMETBL_SIZE; i++) { - seq_head = &tipc_nametbl->seq_hlist[i]; + seq_head = &tn->nametbl->seq_hlist[i]; if (*last_type) { - seq = nametbl_find_seq(*last_type); + seq = nametbl_find_seq(net, *last_type); if (!seq) return -EPIPE; } else { @@ -1160,6 +1175,7 @@ int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb) u32 last_type = cb->args[0]; u32 last_lower = cb->args[1]; u32 last_publ = cb->args[2]; + struct net *net = sock_net(skb->sk); struct tipc_nl_msg msg; if (done) @@ -1170,7 +1186,7 @@ int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb) msg.seq = cb->nlh->nlmsg_seq; rcu_read_lock(); - err = __tipc_nl_seq_list(&msg, &last_type, &last_lower, &last_publ); + err = tipc_nl_seq_list(net, &msg, &last_type, &last_lower, &last_publ); if (!err) { done = 1; } else if (err != -EMSGSIZE) { diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index efccaca7a5d5..f67b3d8d4b2f 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h @@ -95,28 +95,27 @@ struct name_table { u32 local_publ_count; }; -extern spinlock_t tipc_nametbl_lock; -extern struct name_table *tipc_nametbl; - int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb); -struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space); -u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node); -int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, - struct tipc_port_list *dports); +struct sk_buff *tipc_nametbl_get(struct net *net, const void *req_tlv_area, + int req_tlv_space); +u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *node); +int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper, + u32 limit, struct tipc_port_list *dports); struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower, u32 upper, u32 scope, u32 port_ref, u32 key); int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref, u32 key); -struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, - u32 scope, u32 node, u32 ref, +struct publication *tipc_nametbl_insert_publ(struct net *net, u32 type, + u32 lower, u32 upper, u32 scope, + u32 node, u32 ref, u32 key); +struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type, + u32 lower, u32 node, u32 ref, u32 key); -struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, u32 node, - u32 ref, u32 key); void tipc_nametbl_subscribe(struct tipc_subscription *s); void tipc_nametbl_unsubscribe(struct tipc_subscription *s); -int tipc_nametbl_init(void); -void tipc_nametbl_stop(void); +int tipc_nametbl_init(struct net *net); +void tipc_nametbl_stop(struct net *net); #endif diff --git a/net/tipc/net.c b/net/tipc/net.c index 44ccf47c79a3..04445d210e45 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -116,7 +116,7 @@ int tipc_net_start(struct net *net, u32 addr) int res; tipc_own_addr = addr; - tipc_named_reinit(); + tipc_named_reinit(net); tipc_sk_reinit(net); res = tipc_bclink_init(net); if (res) diff --git a/net/tipc/server.c b/net/tipc/server.c index 869eb0905754..b5bdaf721d70 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c @@ -256,7 +256,8 @@ static int tipc_receive_from_sock(struct tipc_conn *con) goto out_close; } - s->tipc_conn_recvmsg(con->conid, &addr, con->usr_data, buf, ret); + s->tipc_conn_recvmsg(sock_net(con->sock->sk), con->conid, &addr, + con->usr_data, buf, ret); kmem_cache_free(s->rcvbuf_cache, buf); diff --git a/net/tipc/server.h b/net/tipc/server.h index 87bc05c70dce..9c979a01997c 100644 --- a/net/tipc/server.h +++ b/net/tipc/server.h @@ -38,6 +38,7 @@ #include #include +#include #define TIPC_SERVER_NAME_LEN 32 @@ -66,10 +67,11 @@ struct tipc_server { struct workqueue_struct *rcv_wq; struct workqueue_struct *send_wq; int max_rcvbuf_size; - void *(*tipc_conn_new) (int conid); - void (*tipc_conn_shutdown) (int conid, void *usr_data); - void (*tipc_conn_recvmsg) (int conid, struct sockaddr_tipc *addr, - void *usr_data, void *buf, size_t len); + void *(*tipc_conn_new)(int conid); + void (*tipc_conn_shutdown)(int conid, void *usr_data); + void (*tipc_conn_recvmsg)(struct net *net, int conid, + struct sockaddr_tipc *addr, void *usr_data, + void *buf, size_t len); struct sockaddr_tipc *saddr; const char name[TIPC_SERVER_NAME_LEN]; int imp; diff --git a/net/tipc/socket.c b/net/tipc/socket.c index accb02cb3527..4670e1e46c89 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -778,11 +778,8 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *buf) scope = TIPC_NODE_SCOPE; /* Create destination port list: */ - tipc_nametbl_mc_translate(msg_nametype(msg), - msg_namelower(msg), - msg_nameupper(msg), - scope, - &dports); + tipc_nametbl_mc_translate(net, msg_nametype(msg), msg_namelower(msg), + msg_nameupper(msg), scope, &dports); last = dports.count; if (!last) { kfree_skb(buf); @@ -943,7 +940,7 @@ static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock, msg_set_nametype(mhdr, type); msg_set_nameinst(mhdr, inst); msg_set_lookup_scope(mhdr, tipc_addr_scope(domain)); - dport = tipc_nametbl_translate(type, inst, &dnode); + dport = tipc_nametbl_translate(net, type, inst, &dnode); msg_set_destnode(mhdr, dnode); msg_set_destport(mhdr, dport); if (unlikely(!dport && !dnode)) { @@ -1765,7 +1762,7 @@ int tipc_sk_rcv(struct net *net, struct sk_buff *skb) /* Validate destination and message */ tsk = tipc_sk_lookup(net, dport); if (unlikely(!tsk)) { - rc = tipc_msg_eval(skb, &dnode); + rc = tipc_msg_eval(net, skb, &dnode); goto exit; } sk = &tsk->sk; diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index e6cb959371dc..b71dbc0ae8f9 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -50,8 +50,9 @@ struct tipc_subscriber { struct list_head subscription_list; }; -static void subscr_conn_msg_event(int conid, struct sockaddr_tipc *addr, - void *usr_data, void *buf, size_t len); +static void subscr_conn_msg_event(struct net *net, int conid, + struct sockaddr_tipc *addr, void *usr_data, + void *buf, size_t len); static void *subscr_named_msg_event(int conid); static void subscr_conn_shutdown_event(int conid, void *usr_data); @@ -260,7 +261,7 @@ static void subscr_cancel(struct tipc_subscr *s, * * Called with subscriber lock held. */ -static int subscr_subscribe(struct tipc_subscr *s, +static int subscr_subscribe(struct net *net, struct tipc_subscr *s, struct tipc_subscriber *subscriber, struct tipc_subscription **sub_p) { struct tipc_subscription *sub; @@ -291,6 +292,7 @@ static int subscr_subscribe(struct tipc_subscr *s, } /* Initialize subscription object */ + sub->net = net; sub->seq.type = htohl(s->seq.type, swap); sub->seq.lower = htohl(s->seq.lower, swap); sub->seq.upper = htohl(s->seq.upper, swap); @@ -323,14 +325,16 @@ static void subscr_conn_shutdown_event(int conid, void *usr_data) } /* Handle one request to create a new subscription for the subscriber */ -static void subscr_conn_msg_event(int conid, struct sockaddr_tipc *addr, - void *usr_data, void *buf, size_t len) +static void subscr_conn_msg_event(struct net *net, int conid, + struct sockaddr_tipc *addr, void *usr_data, + void *buf, size_t len) { struct tipc_subscriber *subscriber = usr_data; struct tipc_subscription *sub = NULL; spin_lock_bh(&subscriber->lock); - if (subscr_subscribe((struct tipc_subscr *)buf, subscriber, &sub) < 0) { + if (subscr_subscribe(net, (struct tipc_subscr *)buf, subscriber, + &sub) < 0) { spin_unlock_bh(&subscriber->lock); subscr_terminate(subscriber); return; diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index 0d3958956aca..670f57096635 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h @@ -49,6 +49,7 @@ struct tipc_subscriber; * struct tipc_subscription - TIPC network topology subscription object * @subscriber: pointer to its subscriber * @seq: name sequence associated with subscription + * @net: point to network namespace * @timeout: duration of subscription (in ms) * @filter: event filtering to be done for subscription * @timer: timer governing subscription duration (optional) @@ -61,6 +62,7 @@ struct tipc_subscriber; struct tipc_subscription { struct tipc_subscriber *subscriber; struct tipc_name_seq seq; + struct net *net; unsigned long timeout; u32 filter; struct timer_list timer; -- cgit v1.2.3-70-g09d2 From 347475395434abb2b61bf59c2952470f37072567 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Fri, 9 Jan 2015 15:27:10 +0800 Subject: tipc: make tipc node address support net namespace If net namespace is supported in tipc, each namespace will be treated as a separate tipc node. Therefore, every namespace must own its private tipc node address. This means the "tipc_own_addr" global variable of node address must be moved to tipc_net structure to satisfy the requirement. It's turned out that users also can assign node address for every namespace. Signed-off-by: Ying Xue Tested-by: Tero Aho Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/addr.c | 43 ++++++++++++++++++++++++++ net/tipc/addr.h | 44 ++++---------------------- net/tipc/bcast.c | 6 ++-- net/tipc/bearer.c | 13 ++++---- net/tipc/config.c | 9 +++--- net/tipc/core.c | 4 +-- net/tipc/core.h | 5 +-- net/tipc/discover.c | 8 ++--- net/tipc/link.c | 56 +++++++++++++++++++-------------- net/tipc/msg.c | 40 +++++++++++++----------- net/tipc/msg.h | 21 +++++++------ net/tipc/name_distr.c | 21 +++++++------ net/tipc/name_distr.h | 2 +- net/tipc/name_table.c | 39 +++++++++++++---------- net/tipc/net.c | 20 ++++++------ net/tipc/node.c | 23 ++++++++------ net/tipc/socket.c | 86 ++++++++++++++++++++++++++++++--------------------- 17 files changed, 246 insertions(+), 194 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/addr.c b/net/tipc/addr.c index 9e6eeb450fe1..48fd3b5a73fb 100644 --- a/net/tipc/addr.c +++ b/net/tipc/addr.c @@ -36,6 +36,49 @@ #include #include "addr.h" +#include "core.h" + +/** + * in_own_cluster - test for cluster inclusion; <0.0.0> always matches + */ +int in_own_cluster(struct net *net, u32 addr) +{ + return in_own_cluster_exact(net, addr) || !addr; +} + +int in_own_cluster_exact(struct net *net, u32 addr) +{ + struct tipc_net *tn = net_generic(net, tipc_net_id); + + return !((addr ^ tn->own_addr) >> 12); +} + +/** + * in_own_node - test for node inclusion; <0.0.0> always matches + */ +int in_own_node(struct net *net, u32 addr) +{ + struct tipc_net *tn = net_generic(net, tipc_net_id); + + return (addr == tn->own_addr) || !addr; +} + +/** + * addr_domain - convert 2-bit scope value to equivalent message lookup domain + * + * Needed when address of a named message must be looked up a second time + * after a network hop. + */ +u32 addr_domain(struct net *net, u32 sc) +{ + struct tipc_net *tn = net_generic(net, tipc_net_id); + + if (likely(sc == TIPC_NODE_SCOPE)) + return tn->own_addr; + if (sc == TIPC_CLUSTER_SCOPE) + return tipc_cluster_mask(tn->own_addr); + return tipc_zone_mask(tn->own_addr); +} /** * tipc_addr_domain_valid - validates a network domain address diff --git a/net/tipc/addr.h b/net/tipc/addr.h index 4e364c4f1359..c700c2d28e09 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h @@ -39,12 +39,12 @@ #include #include +#include +#include #define TIPC_ZONE_MASK 0xff000000u #define TIPC_CLUSTER_MASK 0xfffff000u -extern u32 tipc_own_addr __read_mostly; - static inline u32 tipc_zone_mask(u32 addr) { return addr & TIPC_ZONE_MASK; @@ -55,42 +55,10 @@ static inline u32 tipc_cluster_mask(u32 addr) return addr & TIPC_CLUSTER_MASK; } -static inline int in_own_cluster_exact(u32 addr) -{ - return !((addr ^ tipc_own_addr) >> 12); -} - -/** - * in_own_node - test for node inclusion; <0.0.0> always matches - */ -static inline int in_own_node(u32 addr) -{ - return (addr == tipc_own_addr) || !addr; -} - -/** - * in_own_cluster - test for cluster inclusion; <0.0.0> always matches - */ -static inline int in_own_cluster(u32 addr) -{ - return in_own_cluster_exact(addr) || !addr; -} - -/** - * addr_domain - convert 2-bit scope value to equivalent message lookup domain - * - * Needed when address of a named message must be looked up a second time - * after a network hop. - */ -static inline u32 addr_domain(u32 sc) -{ - if (likely(sc == TIPC_NODE_SCOPE)) - return tipc_own_addr; - if (sc == TIPC_CLUSTER_SCOPE) - return tipc_cluster_mask(tipc_own_addr); - return tipc_zone_mask(tipc_own_addr); -} - +int in_own_cluster(struct net *net, u32 addr); +int in_own_cluster_exact(struct net *net, u32 addr); +int in_own_node(struct net *net, u32 addr); +u32 addr_domain(struct net *net, u32 sc); int tipc_addr_domain_valid(u32); int tipc_addr_node_valid(u32 addr); int tipc_in_scope(u32 domain, u32 addr); diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index bc58097ebad2..53f8bf059fec 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -317,7 +317,7 @@ void tipc_bclink_update_link_state(struct net *net, struct tipc_node *n_ptr, struct sk_buff *skb = skb_peek(&n_ptr->bclink.deferred_queue); u32 to = skb ? buf_seqno(skb) - 1 : n_ptr->bclink.last_sent; - tipc_msg_init(msg, BCAST_PROTOCOL, STATE_MSG, + tipc_msg_init(net, msg, BCAST_PROTOCOL, STATE_MSG, INT_H_SIZE, n_ptr->addr); msg_set_non_seq(msg, 1); msg_set_mc_netid(msg, tn->net_id); @@ -428,7 +428,7 @@ static void bclink_accept_pkt(struct tipc_node *node, u32 seqno) * Unicast an ACK periodically, ensuring that * all nodes in the cluster don't ACK at the same time */ - if (((seqno - tipc_own_addr) % TIPC_MIN_LINK_WIN) == 0) { + if (((seqno - tn->own_addr) % TIPC_MIN_LINK_WIN) == 0) { tipc_link_proto_xmit(node->active_links[node->addr & 1], STATE_MSG, 0, 0, 0, 0, 0); tn->bcl->stats.sent_acks++; @@ -466,7 +466,7 @@ void tipc_bclink_rcv(struct net *net, struct sk_buff *buf) if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) { if (msg_type(msg) != STATE_MSG) goto unlock; - if (msg_destnode(msg) == tipc_own_addr) { + if (msg_destnode(msg) == tn->own_addr) { tipc_bclink_acknowledge(node, msg_bcast_ack(msg)); tipc_node_unlock(node); tipc_bclink_lock(net); diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 9a0d6ed5c96c..33dc3486d16c 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -278,7 +278,7 @@ int tipc_enable_bearer(struct net *net, const char *name, u32 disc_domain, u32 i; int res = -EINVAL; - if (!tipc_own_addr) { + if (!tn->own_addr) { pr_warn("Bearer <%s> rejected, not supported in standalone mode\n", name); return -ENOPROTOOPT; @@ -288,11 +288,11 @@ int tipc_enable_bearer(struct net *net, const char *name, u32 disc_domain, return -EINVAL; } if (tipc_addr_domain_valid(disc_domain) && - (disc_domain != tipc_own_addr)) { - if (tipc_in_scope(disc_domain, tipc_own_addr)) { - disc_domain = tipc_own_addr & TIPC_CLUSTER_MASK; + (disc_domain != tn->own_addr)) { + if (tipc_in_scope(disc_domain, tn->own_addr)) { + disc_domain = tn->own_addr & TIPC_CLUSTER_MASK; res = 0; /* accept any node in own cluster */ - } else if (in_own_cluster_exact(disc_domain)) + } else if (in_own_cluster_exact(net, disc_domain)) res = 0; /* accept specified node in own cluster */ } if (res) { @@ -817,6 +817,7 @@ int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info) int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info) { struct net *net = genl_info_net(info); + struct tipc_net *tn = net_generic(net, tipc_net_id); int err; char *bearer; struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1]; @@ -824,7 +825,7 @@ int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info) u32 prio; prio = TIPC_MEDIA_LINK_PRI; - domain = tipc_own_addr & TIPC_CLUSTER_MASK; + domain = tn->own_addr & TIPC_CLUSTER_MASK; if (!info->attrs[TIPC_NLA_BEARER]) return -EINVAL; diff --git a/net/tipc/config.c b/net/tipc/config.c index 974723a1e32e..6873360cda53 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -163,18 +163,19 @@ static struct sk_buff *cfg_disable_bearer(struct net *net) static struct sk_buff *cfg_set_own_addr(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); u32 addr; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); addr = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); - if (addr == tipc_own_addr) + if (addr == tn->own_addr) return tipc_cfg_reply_none(); if (!tipc_addr_node_valid(addr)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (node address)"); - if (tipc_own_addr) + if (tn->own_addr) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (cannot change node address once assigned)"); if (!tipc_net_start(net, addr)) @@ -196,7 +197,7 @@ static struct sk_buff *cfg_set_netid(struct net *net) if (value < 1 || value > 9999) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (network id must be 1-9999)"); - if (tipc_own_addr) + if (tn->own_addr) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (cannot change network id once TIPC has joined a network)"); tn->net_id = value; @@ -218,7 +219,7 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, rep_headroom = reply_headroom; /* Check command authorization */ - if (likely(in_own_node(orig_node))) { + if (likely(in_own_node(net, orig_node))) { /* command is permitted */ } else { rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED diff --git a/net/tipc/core.c b/net/tipc/core.c index 63cde8148aaf..7c09670120eb 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -48,7 +48,6 @@ int tipc_random __read_mostly; /* configurable TIPC parameters */ -u32 tipc_own_addr __read_mostly; int tipc_net_id __read_mostly; int sysctl_tipc_rmem[3] __read_mostly; /* min/default/max */ @@ -58,6 +57,7 @@ static int __net_init tipc_init_net(struct net *net) int err; tn->net_id = 4711; + tn->own_addr = 0; INIT_LIST_HEAD(&tn->node_list); spin_lock_init(&tn->node_list_lock); @@ -96,8 +96,6 @@ static int __init tipc_init(void) pr_info("Activated (version " TIPC_MOD_VER ")\n"); - tipc_own_addr = 0; - sysctl_tipc_rmem[0] = TIPC_CONN_OVERLOAD_LIMIT >> 4 << TIPC_LOW_IMPORTANCE; sysctl_tipc_rmem[1] = TIPC_CONN_OVERLOAD_LIMIT >> 4 << diff --git a/net/tipc/core.h b/net/tipc/core.h index 893992944570..afabf39e801c 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -72,10 +72,6 @@ int tipc_snprintf(char *buf, int len, const char *fmt, ...); -/* - * Global configuration variables - */ -extern u32 tipc_own_addr __read_mostly; extern int tipc_net_id __read_mostly; extern int sysctl_tipc_rmem[3] __read_mostly; extern int sysctl_tipc_named_timeout __read_mostly; @@ -86,6 +82,7 @@ extern int sysctl_tipc_named_timeout __read_mostly; extern int tipc_random __read_mostly; struct tipc_net { + u32 own_addr; int net_id; /* Node table and node list */ diff --git a/net/tipc/discover.c b/net/tipc/discover.c index f93dd3dd621b..786411dea61c 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -86,7 +86,7 @@ static void tipc_disc_init_msg(struct net *net, struct sk_buff *buf, u32 type, u32 dest_domain = b_ptr->domain; msg = buf_msg(buf); - tipc_msg_init(msg, LINK_CONFIG, type, INT_H_SIZE, dest_domain); + tipc_msg_init(net, msg, LINK_CONFIG, type, INT_H_SIZE, dest_domain); msg_set_non_seq(msg, 1); msg_set_node_sig(msg, tipc_random); msg_set_dest_domain(msg, dest_domain); @@ -153,12 +153,12 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf, if (!tipc_addr_node_valid(onode)) return; - if (in_own_node(onode)) { + if (in_own_node(net, onode)) { if (memcmp(&maddr, &bearer->addr, sizeof(maddr))) - disc_dupl_alert(bearer, tipc_own_addr, &maddr); + disc_dupl_alert(bearer, tn->own_addr, &maddr); return; } - if (!tipc_in_scope(ddom, tipc_own_addr)) + if (!tipc_in_scope(ddom, tn->own_addr)) return; if (!tipc_in_scope(bearer->domain, onode)) return; diff --git a/net/tipc/link.c b/net/tipc/link.c index a84d5c67997e..997256769065 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -241,6 +241,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, struct tipc_bearer *b_ptr, const struct tipc_media_addr *media_addr) { + struct tipc_net *tn = net_generic(n_ptr->net, tipc_net_id); struct tipc_link *l_ptr; struct tipc_msg *msg; char *if_name; @@ -270,8 +271,8 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, l_ptr->addr = peer; if_name = strchr(b_ptr->name, ':') + 1; sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:unknown", - tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), - tipc_node(tipc_own_addr), + tipc_zone(tn->own_addr), tipc_cluster(tn->own_addr), + tipc_node(tn->own_addr), if_name, tipc_zone(peer), tipc_cluster(peer), tipc_node(peer)); /* note: peer i/f name is updated by reset/activate message */ @@ -285,7 +286,8 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg; msg = l_ptr->pmsg; - tipc_msg_init(msg, LINK_PROTOCOL, RESET_MSG, INT_H_SIZE, l_ptr->addr); + tipc_msg_init(n_ptr->net, msg, LINK_PROTOCOL, RESET_MSG, INT_H_SIZE, + l_ptr->addr); msg_set_size(msg, sizeof(l_ptr->proto_msg)); msg_set_session(msg, (tipc_random & 0xffff)); msg_set_bearer_id(msg, b_ptr->identity); @@ -358,10 +360,12 @@ void tipc_link_delete_list(struct net *net, unsigned int bearer_id, static bool link_schedule_user(struct tipc_link *link, u32 oport, uint chain_sz, uint imp) { + struct net *net = link->owner->net; + struct tipc_net *tn = net_generic(net, tipc_net_id); struct sk_buff *buf; - buf = tipc_msg_create(SOCK_WAKEUP, 0, INT_H_SIZE, 0, tipc_own_addr, - tipc_own_addr, oport, 0, 0); + buf = tipc_msg_create(net, SOCK_WAKEUP, 0, INT_H_SIZE, 0, tn->own_addr, + tn->own_addr, oport, 0, 0); if (!buf) return false; TIPC_SKB_CB(buf)->chain_sz = chain_sz; @@ -753,7 +757,7 @@ int __tipc_link_xmit(struct net *net, struct tipc_link *link, } else if (tipc_msg_bundle(outqueue, skb, mtu)) { link->stats.sent_bundled++; continue; - } else if (tipc_msg_make_bundle(outqueue, skb, mtu, + } else if (tipc_msg_make_bundle(net, outqueue, skb, mtu, link->addr)) { link->stats.sent_bundled++; link->stats.sent_bundles++; @@ -822,7 +826,7 @@ int tipc_link_xmit(struct net *net, struct sk_buff_head *list, u32 dnode, if (link) return rc; - if (likely(in_own_node(dnode))) { + if (likely(in_own_node(net, dnode))) { /* As a node local message chain never contains more than one * buffer, we just need to dequeue one SKB buffer from the * head list. @@ -852,7 +856,8 @@ static void tipc_link_sync_xmit(struct tipc_link *link) return; msg = buf_msg(skb); - tipc_msg_init(msg, BCAST_PROTOCOL, STATE_MSG, INT_H_SIZE, link->addr); + tipc_msg_init(link->owner->net, msg, BCAST_PROTOCOL, STATE_MSG, + INT_H_SIZE, link->addr); msg_set_last_bcast(msg, link->owner->bclink.acked); __tipc_link_xmit_skb(link, skb); } @@ -1092,6 +1097,7 @@ static int link_recv_buf_validate(struct sk_buff *buf) */ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct sk_buff_head head; struct tipc_node *n_ptr; struct tipc_link *l_ptr; @@ -1125,7 +1131,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr) /* Discard unicast link messages destined for another node */ if (unlikely(!msg_short(msg) && - (msg_destnode(msg) != tipc_own_addr))) + (msg_destnode(msg) != tn->own_addr))) goto discard; /* Locate neighboring node that sent message */ @@ -1483,6 +1489,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg, static void tipc_link_proto_rcv(struct net *net, struct tipc_link *l_ptr, struct sk_buff *buf) { + struct tipc_net *tn = net_generic(net, tipc_net_id); u32 rec_gap = 0; u32 max_pkt_info; u32 max_pkt_ack; @@ -1494,7 +1501,7 @@ static void tipc_link_proto_rcv(struct net *net, struct tipc_link *l_ptr, goto exit; if (l_ptr->net_plane != msg_net_plane(msg)) - if (tipc_own_addr > msg_prevnode(msg)) + if (tn->own_addr > msg_prevnode(msg)) l_ptr->net_plane = msg_net_plane(msg); switch (msg_type(msg)) { @@ -1662,8 +1669,8 @@ void tipc_link_failover_send_queue(struct tipc_link *l_ptr) if (!tunnel) return; - tipc_msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, - ORIGINAL_MSG, INT_H_SIZE, l_ptr->addr); + tipc_msg_init(l_ptr->owner->net, &tunnel_hdr, CHANGEOVER_PROTOCOL, + ORIGINAL_MSG, INT_H_SIZE, l_ptr->addr); msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); msg_set_msgcnt(&tunnel_hdr, msgcount); @@ -1720,8 +1727,8 @@ void tipc_link_dup_queue_xmit(struct tipc_link *l_ptr, struct sk_buff *skb; struct tipc_msg tunnel_hdr; - tipc_msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, - DUPLICATE_MSG, INT_H_SIZE, l_ptr->addr); + tipc_msg_init(l_ptr->owner->net, &tunnel_hdr, CHANGEOVER_PROTOCOL, + DUPLICATE_MSG, INT_H_SIZE, l_ptr->addr); msg_set_msgcnt(&tunnel_hdr, skb_queue_len(&l_ptr->outqueue)); msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); skb_queue_walk(&l_ptr->outqueue, skb) { @@ -2506,12 +2513,14 @@ msg_full: } /* Caller should hold appropriate locks to protect the link */ -static int __tipc_nl_add_link(struct tipc_nl_msg *msg, struct tipc_link *link) +static int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, + struct tipc_link *link) { int err; void *hdr; struct nlattr *attrs; struct nlattr *prop; + struct tipc_net *tn = net_generic(net, tipc_net_id); hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family, NLM_F_MULTI, TIPC_NL_LINK_GET); @@ -2525,7 +2534,7 @@ static int __tipc_nl_add_link(struct tipc_nl_msg *msg, struct tipc_link *link) if (nla_put_string(msg->skb, TIPC_NLA_LINK_NAME, link->name)) goto attr_msg_full; if (nla_put_u32(msg->skb, TIPC_NLA_LINK_DEST, - tipc_cluster_mask(tipc_own_addr))) + tipc_cluster_mask(tn->own_addr))) goto attr_msg_full; if (nla_put_u32(msg->skb, TIPC_NLA_LINK_MTU, link->max_pkt)) goto attr_msg_full; @@ -2575,9 +2584,8 @@ msg_full: } /* Caller should hold node lock */ -static int __tipc_nl_add_node_links(struct tipc_nl_msg *msg, - struct tipc_node *node, - u32 *prev_link) +static int __tipc_nl_add_node_links(struct net *net, struct tipc_nl_msg *msg, + struct tipc_node *node, u32 *prev_link) { u32 i; int err; @@ -2588,7 +2596,7 @@ static int __tipc_nl_add_node_links(struct tipc_nl_msg *msg, if (!node->links[i]) continue; - err = __tipc_nl_add_link(msg, node->links[i]); + err = __tipc_nl_add_link(net, msg, node->links[i]); if (err) return err; } @@ -2633,7 +2641,8 @@ int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb) list_for_each_entry_continue_rcu(node, &tn->node_list, list) { tipc_node_lock(node); - err = __tipc_nl_add_node_links(&msg, node, &prev_link); + err = __tipc_nl_add_node_links(net, &msg, node, + &prev_link); tipc_node_unlock(node); if (err) goto out; @@ -2647,7 +2656,8 @@ int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb) list_for_each_entry_rcu(node, &tn->node_list, list) { tipc_node_lock(node); - err = __tipc_nl_add_node_links(&msg, node, &prev_link); + err = __tipc_nl_add_node_links(net, &msg, node, + &prev_link); tipc_node_unlock(node); if (err) goto out; @@ -2700,7 +2710,7 @@ int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info) goto err_out; } - err = __tipc_nl_add_link(&msg, link); + err = __tipc_nl_add_link(net, &msg, link); if (err) goto err_out; diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 642fb137463c..18aba9e99345 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -70,25 +70,27 @@ struct sk_buff *tipc_buf_acquire(u32 size) return skb; } -void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, - u32 destnode) +void tipc_msg_init(struct net *net, struct tipc_msg *m, u32 user, u32 type, + u32 hsize, u32 destnode) { + struct tipc_net *tn = net_generic(net, tipc_net_id); + memset(m, 0, hsize); msg_set_version(m); msg_set_user(m, user); msg_set_hdr_sz(m, hsize); msg_set_size(m, hsize); - msg_set_prevnode(m, tipc_own_addr); + msg_set_prevnode(m, tn->own_addr); msg_set_type(m, type); if (hsize > SHORT_H_SIZE) { - msg_set_orignode(m, tipc_own_addr); + msg_set_orignode(m, tn->own_addr); msg_set_destnode(m, destnode); } } -struct sk_buff *tipc_msg_create(uint user, uint type, uint hdr_sz, - uint data_sz, u32 dnode, u32 onode, - u32 dport, u32 oport, int errcode) +struct sk_buff *tipc_msg_create(struct net *net, uint user, uint type, + uint hdr_sz, uint data_sz, u32 dnode, + u32 onode, u32 dport, u32 oport, int errcode) { struct tipc_msg *msg; struct sk_buff *buf; @@ -98,7 +100,7 @@ struct sk_buff *tipc_msg_create(uint user, uint type, uint hdr_sz, return NULL; msg = buf_msg(buf); - tipc_msg_init(msg, user, type, hdr_sz, dnode); + tipc_msg_init(net, msg, user, type, hdr_sz, dnode); msg_set_size(msg, hdr_sz + data_sz); msg_set_prevnode(msg, onode); msg_set_origport(msg, oport); @@ -194,8 +196,8 @@ err: * * Returns message data size or errno: -ENOMEM, -EFAULT */ -int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, - int dsz, int pktmax, struct sk_buff_head *list) +int tipc_msg_build(struct net *net, struct tipc_msg *mhdr, struct msghdr *m, + int offset, int dsz, int pktmax, struct sk_buff_head *list) { int mhsz = msg_hdr_sz(mhdr); int msz = mhsz + dsz; @@ -227,8 +229,8 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, } /* Prepare reusable fragment header */ - tipc_msg_init(&pkthdr, MSG_FRAGMENTER, FIRST_FRAGMENT, - INT_H_SIZE, msg_destnode(mhdr)); + tipc_msg_init(net, &pkthdr, MSG_FRAGMENTER, FIRST_FRAGMENT, INT_H_SIZE, + msg_destnode(mhdr)); msg_set_size(&pkthdr, pktmax); msg_set_fragm_no(&pkthdr, pktno); @@ -339,8 +341,8 @@ bool tipc_msg_bundle(struct sk_buff_head *list, struct sk_buff *skb, u32 mtu) * Replaces buffer if successful * Returns true if success, otherwise false */ -bool tipc_msg_make_bundle(struct sk_buff_head *list, struct sk_buff *skb, - u32 mtu, u32 dnode) +bool tipc_msg_make_bundle(struct net *net, struct sk_buff_head *list, + struct sk_buff *skb, u32 mtu, u32 dnode) { struct sk_buff *bskb; struct tipc_msg *bmsg; @@ -363,7 +365,7 @@ bool tipc_msg_make_bundle(struct sk_buff_head *list, struct sk_buff *skb, skb_trim(bskb, INT_H_SIZE); bmsg = buf_msg(bskb); - tipc_msg_init(bmsg, MSG_BUNDLER, 0, INT_H_SIZE, dnode); + tipc_msg_init(net, bmsg, MSG_BUNDLER, 0, INT_H_SIZE, dnode); msg_set_seqno(bmsg, msg_seqno(msg)); msg_set_ack(bmsg, msg_ack(msg)); msg_set_bcast_ack(bmsg, msg_bcast_ack(msg)); @@ -380,8 +382,10 @@ bool tipc_msg_make_bundle(struct sk_buff_head *list, struct sk_buff *skb, * Consumes buffer if failure * Returns true if success, otherwise false */ -bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err) +bool tipc_msg_reverse(struct net *net, struct sk_buff *buf, u32 *dnode, + int err) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_msg *msg = buf_msg(buf); uint imp = msg_importance(msg); struct tipc_msg ohdr; @@ -401,7 +405,7 @@ bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err) msg_set_errcode(msg, err); msg_set_origport(msg, msg_destport(&ohdr)); msg_set_destport(msg, msg_origport(&ohdr)); - msg_set_prevnode(msg, tipc_own_addr); + msg_set_prevnode(msg, tn->own_addr); if (!msg_short(msg)) { msg_set_orignode(msg, msg_destnode(&ohdr)); msg_set_destnode(msg, msg_orignode(&ohdr)); @@ -440,7 +444,7 @@ int tipc_msg_eval(struct net *net, struct sk_buff *buf, u32 *dnode) if (msg_reroute_cnt(msg) > 0) return -TIPC_ERR_NO_NAME; - *dnode = addr_domain(msg_lookup_scope(msg)); + *dnode = addr_domain(net, msg_lookup_scope(msg)); dport = tipc_nametbl_translate(net, msg_nametype(msg), msg_nameinst(msg), dnode); diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 69f37e652a8e..526ef345b70e 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -748,19 +748,20 @@ static inline u32 msg_tot_origport(struct tipc_msg *m) } struct sk_buff *tipc_buf_acquire(u32 size); -bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err); +bool tipc_msg_reverse(struct net *net, struct sk_buff *buf, u32 *dnode, + int err); int tipc_msg_eval(struct net *net, struct sk_buff *buf, u32 *dnode); -void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, - u32 destnode); -struct sk_buff *tipc_msg_create(uint user, uint type, uint hdr_sz, - uint data_sz, u32 dnode, u32 onode, - u32 dport, u32 oport, int errcode); +void tipc_msg_init(struct net *net, struct tipc_msg *m, u32 user, u32 type, + u32 hsize, u32 destnode); +struct sk_buff *tipc_msg_create(struct net *net, uint user, uint type, + uint hdr_sz, uint data_sz, u32 dnode, + u32 onode, u32 dport, u32 oport, int errcode); int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf); bool tipc_msg_bundle(struct sk_buff_head *list, struct sk_buff *skb, u32 mtu); -bool tipc_msg_make_bundle(struct sk_buff_head *list, struct sk_buff *skb, - u32 mtu, u32 dnode); -int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, - int dsz, int mtu, struct sk_buff_head *list); +bool tipc_msg_make_bundle(struct net *net, struct sk_buff_head *list, + struct sk_buff *skb, u32 mtu, u32 dnode); +int tipc_msg_build(struct net *net, struct tipc_msg *mhdr, struct msghdr *m, + int offset, int dsz, int mtu, struct sk_buff_head *list); struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list); #endif diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index ba421321d15d..7f31cd4badc4 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -68,14 +68,16 @@ static void publ_to_item(struct distr_item *i, struct publication *p) /** * named_prepare_buf - allocate & initialize a publication message */ -static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest) +static struct sk_buff *named_prepare_buf(struct net *net, u32 type, u32 size, + u32 dest) { struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE + size); struct tipc_msg *msg; if (buf != NULL) { msg = buf_msg(buf); - tipc_msg_init(msg, NAME_DISTRIBUTOR, type, INT_H_SIZE, dest); + tipc_msg_init(net, msg, NAME_DISTRIBUTOR, type, INT_H_SIZE, + dest); msg_set_size(msg, INT_H_SIZE + size); } return buf; @@ -91,7 +93,7 @@ void named_cluster_distribute(struct net *net, struct sk_buff *skb) rcu_read_lock(); list_for_each_entry_rcu(node, &tn->node_list, list) { dnode = node->addr; - if (in_own_node(dnode)) + if (in_own_node(net, dnode)) continue; if (!tipc_node_active_links(node)) continue; @@ -121,7 +123,7 @@ struct sk_buff *tipc_named_publish(struct net *net, struct publication *publ) if (publ->scope == TIPC_NODE_SCOPE) return NULL; - buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0); + buf = named_prepare_buf(net, PUBLICATION, ITEM_SIZE, 0); if (!buf) { pr_warn("Publication distribution failure\n"); return NULL; @@ -135,7 +137,7 @@ struct sk_buff *tipc_named_publish(struct net *net, struct publication *publ) /** * tipc_named_withdraw - tell other nodes about a withdrawn publication by this node */ -struct sk_buff *tipc_named_withdraw(struct publication *publ) +struct sk_buff *tipc_named_withdraw(struct net *net, struct publication *publ) { struct sk_buff *buf; struct distr_item *item; @@ -145,7 +147,7 @@ struct sk_buff *tipc_named_withdraw(struct publication *publ) if (publ->scope == TIPC_NODE_SCOPE) return NULL; - buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0); + buf = named_prepare_buf(net, WITHDRAWAL, ITEM_SIZE, 0); if (!buf) { pr_warn("Withdrawal distribution failure\n"); return NULL; @@ -175,7 +177,8 @@ static void named_distribute(struct net *net, struct sk_buff_head *list, list_for_each_entry(publ, pls, local_list) { /* Prepare next buffer: */ if (!skb) { - skb = named_prepare_buf(PUBLICATION, msg_rem, dnode); + skb = named_prepare_buf(net, PUBLICATION, msg_rem, + dnode); if (!skb) { pr_warn("Bulk publication failure\n"); return; @@ -227,7 +230,7 @@ static void tipc_publ_subscribe(struct net *net, struct publication *publ, { struct tipc_node *node; - if (in_own_node(addr)) + if (in_own_node(net, addr)) return; node = tipc_node_find(net, addr); @@ -416,7 +419,7 @@ void tipc_named_reinit(struct net *net) for (scope = TIPC_ZONE_SCOPE; scope <= TIPC_NODE_SCOPE; scope++) list_for_each_entry_rcu(publ, &tn->nametbl->publ_list[scope], local_list) - publ->node = tipc_own_addr; + publ->node = tn->own_addr; spin_unlock_bh(&tn->nametbl_lock); } diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h index 1ed2d7e48290..5ec10b59527b 100644 --- a/net/tipc/name_distr.h +++ b/net/tipc/name_distr.h @@ -68,7 +68,7 @@ struct distr_item { }; struct sk_buff *tipc_named_publish(struct net *net, struct publication *publ); -struct sk_buff *tipc_named_withdraw(struct publication *publ); +struct sk_buff *tipc_named_withdraw(struct net *net, struct publication *publ); void named_cluster_distribute(struct net *net, struct sk_buff *buf); void tipc_named_node_up(struct net *net, u32 dnode); void tipc_named_rcv(struct net *net, struct sk_buff *buf); diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 57e39c16a8c3..ce09b863528c 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -227,9 +227,11 @@ static u32 nameseq_locate_subseq(struct name_seq *nseq, u32 instance) /** * tipc_nameseq_insert_publ */ -static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, - u32 type, u32 lower, u32 upper, - u32 scope, u32 node, u32 port, u32 key) +static struct publication *tipc_nameseq_insert_publ(struct net *net, + struct name_seq *nseq, + u32 type, u32 lower, + u32 upper, u32 scope, + u32 node, u32 port, u32 key) { struct tipc_subscription *s; struct tipc_subscription *st; @@ -314,12 +316,12 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, list_add(&publ->zone_list, &info->zone_list); info->zone_list_size++; - if (in_own_cluster(node)) { + if (in_own_cluster(net, node)) { list_add(&publ->cluster_list, &info->cluster_list); info->cluster_list_size++; } - if (in_own_node(node)) { + if (in_own_node(net, node)) { list_add(&publ->node_list, &info->node_list); info->node_list_size++; } @@ -348,8 +350,10 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, * A failed withdraw request simply returns a failure indication and lets the * caller issue any error or warning messages associated with such a problem. */ -static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst, - u32 node, u32 ref, u32 key) +static struct publication *tipc_nameseq_remove_publ(struct net *net, + struct name_seq *nseq, + u32 inst, u32 node, + u32 ref, u32 key) { struct publication *publ; struct sub_seq *sseq = nameseq_find_subseq(nseq, inst); @@ -377,13 +381,13 @@ found: info->zone_list_size--; /* Remove publication from cluster scope list, if present */ - if (in_own_cluster(node)) { + if (in_own_cluster(net, node)) { list_del(&publ->cluster_list); info->cluster_list_size--; } /* Remove publication from node scope list, if present */ - if (in_own_node(node)) { + if (in_own_node(net, node)) { list_del(&publ->node_list); info->node_list_size--; } @@ -483,7 +487,7 @@ struct publication *tipc_nametbl_insert_publ(struct net *net, u32 type, return NULL; spin_lock_bh(&seq->lock); - publ = tipc_nameseq_insert_publ(seq, type, lower, upper, + publ = tipc_nameseq_insert_publ(net, seq, type, lower, upper, scope, node, port, key); spin_unlock_bh(&seq->lock); return publ; @@ -500,7 +504,7 @@ struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type, return NULL; spin_lock_bh(&seq->lock); - publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key); + publ = tipc_nameseq_remove_publ(net, seq, lower, node, ref, key); if (!seq->first_free && list_empty(&seq->subscriptions)) { hlist_del_init_rcu(&seq->ns_list); kfree(seq->sseqs); @@ -528,6 +532,7 @@ struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type, u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *destnode) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct sub_seq *sseq; struct name_info *info; struct publication *publ; @@ -535,7 +540,7 @@ u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 ref = 0; u32 node = 0; - if (!tipc_in_scope(*destnode, tipc_own_addr)) + if (!tipc_in_scope(*destnode, tn->own_addr)) return 0; rcu_read_lock(); @@ -572,13 +577,13 @@ u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, } /* Round-Robin Algorithm */ - else if (*destnode == tipc_own_addr) { + else if (*destnode == tn->own_addr) { if (list_empty(&info->node_list)) goto no_match; publ = list_first_entry(&info->node_list, struct publication, node_list); list_move_tail(&publ->node_list, &info->node_list); - } else if (in_own_cluster_exact(*destnode)) { + } else if (in_own_cluster_exact(net, *destnode)) { if (list_empty(&info->cluster_list)) goto no_match; publ = list_first_entry(&info->cluster_list, struct publication, @@ -670,7 +675,7 @@ struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower, } publ = tipc_nametbl_insert_publ(net, type, lower, upper, scope, - tipc_own_addr, port_ref, key); + tn->own_addr, port_ref, key); if (likely(publ)) { tn->nametbl->local_publ_count++; buf = tipc_named_publish(net, publ); @@ -695,11 +700,11 @@ int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref, struct tipc_net *tn = net_generic(net, tipc_net_id); spin_lock_bh(&tn->nametbl_lock); - publ = tipc_nametbl_remove_publ(net, type, lower, tipc_own_addr, + publ = tipc_nametbl_remove_publ(net, type, lower, tn->own_addr, ref, key); if (likely(publ)) { tn->nametbl->local_publ_count--; - skb = tipc_named_withdraw(publ); + skb = tipc_named_withdraw(net, publ); /* Any pending external events? */ tipc_named_process_backlog(net); list_del_init(&publ->pport_list); diff --git a/net/tipc/net.c b/net/tipc/net.c index 04445d210e45..263267e0e7fe 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -115,30 +115,32 @@ int tipc_net_start(struct net *net, u32 addr) char addr_string[16]; int res; - tipc_own_addr = addr; + tn->own_addr = addr; tipc_named_reinit(net); tipc_sk_reinit(net); res = tipc_bclink_init(net); if (res) return res; - tipc_nametbl_publish(net, TIPC_CFG_SRV, tipc_own_addr, tipc_own_addr, - TIPC_ZONE_SCOPE, 0, tipc_own_addr); + tipc_nametbl_publish(net, TIPC_CFG_SRV, tn->own_addr, tn->own_addr, + TIPC_ZONE_SCOPE, 0, tn->own_addr); pr_info("Started in network mode\n"); pr_info("Own node address %s, network identity %u\n", - tipc_addr_string_fill(addr_string, tipc_own_addr), + tipc_addr_string_fill(addr_string, tn->own_addr), tn->net_id); return 0; } void tipc_net_stop(struct net *net) { - if (!tipc_own_addr) + struct tipc_net *tn = net_generic(net, tipc_net_id); + + if (!tn->own_addr) return; - tipc_nametbl_withdraw(net, TIPC_CFG_SRV, tipc_own_addr, 0, - tipc_own_addr); + tipc_nametbl_withdraw(net, TIPC_CFG_SRV, tn->own_addr, 0, + tn->own_addr); rtnl_lock(); tipc_bearer_stop(net); tipc_bclink_stop(net); @@ -224,7 +226,7 @@ int tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info) u32 val; /* Can't change net id once TIPC has joined a network */ - if (tipc_own_addr) + if (tn->own_addr) return -EPERM; val = nla_get_u32(attrs[TIPC_NLA_NET_ID]); @@ -238,7 +240,7 @@ int tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info) u32 addr; /* Can't change net addr once TIPC has joined a network */ - if (tipc_own_addr) + if (tn->own_addr) return -EPERM; addr = nla_get_u32(attrs[TIPC_NLA_NET_ADDR]); diff --git a/net/tipc/node.c b/net/tipc/node.c index 3db501260de1..b1eb0927bac8 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -75,7 +75,7 @@ struct tipc_node *tipc_node_find(struct net *net, u32 addr) struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_node *node; - if (unlikely(!in_own_cluster_exact(addr))) + if (unlikely(!in_own_cluster_exact(net, addr))) return NULL; rcu_read_lock(); @@ -155,7 +155,7 @@ int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port) struct tipc_node *node; struct tipc_sock_conn *conn; - if (in_own_node(dnode)) + if (in_own_node(net, dnode)) return 0; node = tipc_node_find(net, dnode); @@ -181,7 +181,7 @@ void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port) struct tipc_node *node; struct tipc_sock_conn *conn, *safe; - if (in_own_node(dnode)) + if (in_own_node(net, dnode)) return; node = tipc_node_find(net, dnode); @@ -200,14 +200,16 @@ void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port) void tipc_node_abort_sock_conns(struct net *net, struct list_head *conns) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_sock_conn *conn, *safe; struct sk_buff *buf; list_for_each_entry_safe(conn, safe, conns, list) { - buf = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, - SHORT_H_SIZE, 0, tipc_own_addr, - conn->peer_node, conn->port, - conn->peer_port, TIPC_ERR_NO_NODE); + buf = tipc_msg_create(net, TIPC_CRITICAL_IMPORTANCE, + TIPC_CONN_MSG, SHORT_H_SIZE, 0, + tn->own_addr, conn->peer_node, + conn->port, conn->peer_port, + TIPC_ERR_NO_NODE); if (likely(buf)) tipc_sk_rcv(net, buf); list_del(&conn->list); @@ -287,6 +289,7 @@ static void node_select_active_links(struct tipc_node *n_ptr) */ void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr) { + struct tipc_net *tn = net_generic(n_ptr->net, tipc_net_id); struct tipc_link **active; n_ptr->working_links--; @@ -321,7 +324,7 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr) } /* Loopback link went down? No fragmentation needed from now on. */ - if (n_ptr->addr == tipc_own_addr) { + if (n_ptr->addr == tn->own_addr) { n_ptr->act_mtus[0] = MAX_MSG_SIZE; n_ptr->act_mtus[1] = MAX_MSG_SIZE; } @@ -483,7 +486,7 @@ struct sk_buff *tipc_node_get_links(struct net *net, const void *req_tlv_area, return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (network address)"); - if (!tipc_own_addr) + if (!tn->own_addr) return tipc_cfg_reply_none(); spin_lock_bh(&tn->node_list_lock); @@ -501,7 +504,7 @@ struct sk_buff *tipc_node_get_links(struct net *net, const void *req_tlv_area, return NULL; /* Add TLV for broadcast link */ - link_info.dest = htonl(tipc_cluster_mask(tipc_own_addr)); + link_info.dest = htonl(tipc_cluster_mask(tn->own_addr)); link_info.up = htonl(1); strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME); tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 4670e1e46c89..9b8470edc783 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -251,10 +251,11 @@ static void tsk_rej_rx_queue(struct sock *sk) { struct sk_buff *skb; u32 dnode; + struct net *net = sock_net(sk); while ((skb = __skb_dequeue(&sk->sk_receive_queue))) { - if (tipc_msg_reverse(skb, &dnode, TIPC_ERR_NO_PORT)) - tipc_link_xmit_skb(sock_net(sk), skb, dnode, 0); + if (tipc_msg_reverse(net, skb, &dnode, TIPC_ERR_NO_PORT)) + tipc_link_xmit_skb(net, skb, dnode, 0); } } @@ -265,6 +266,7 @@ static void tsk_rej_rx_queue(struct sock *sk) */ static bool tsk_peer_msg(struct tipc_sock *tsk, struct tipc_msg *msg) { + struct tipc_net *tn = net_generic(sock_net(&tsk->sk), tipc_net_id); u32 peer_port = tsk_peer_port(tsk); u32 orig_node; u32 peer_node; @@ -281,10 +283,10 @@ static bool tsk_peer_msg(struct tipc_sock *tsk, struct tipc_msg *msg) if (likely(orig_node == peer_node)) return true; - if (!orig_node && (peer_node == tipc_own_addr)) + if (!orig_node && (peer_node == tn->own_addr)) return true; - if (!peer_node && (orig_node == tipc_own_addr)) + if (!peer_node && (orig_node == tn->own_addr)) return true; return false; @@ -346,7 +348,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock, tsk->max_pkt = MAX_PKT_DEFAULT; INIT_LIST_HEAD(&tsk->publications); msg = &tsk->phdr; - tipc_msg_init(msg, TIPC_LOW_IMPORTANCE, TIPC_NAMED_MSG, + tipc_msg_init(net, msg, TIPC_LOW_IMPORTANCE, TIPC_NAMED_MSG, NAMED_H_SIZE, 0); /* Finish initializing socket data structures */ @@ -471,6 +473,7 @@ static int tipc_release(struct socket *sock) { struct sock *sk = sock->sk; struct net *net = sock_net(sk); + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_sock *tsk; struct sk_buff *skb; u32 dnode, probing_state; @@ -503,7 +506,8 @@ static int tipc_release(struct socket *sock) tsk->connected = 0; tipc_node_remove_conn(net, dnode, tsk->portid); } - if (tipc_msg_reverse(skb, &dnode, TIPC_ERR_NO_PORT)) + if (tipc_msg_reverse(net, skb, &dnode, + TIPC_ERR_NO_PORT)) tipc_link_xmit_skb(net, skb, dnode, 0); } } @@ -514,9 +518,9 @@ static int tipc_release(struct socket *sock) sock_put(sk); tipc_sk_remove(tsk); if (tsk->connected) { - skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, - SHORT_H_SIZE, 0, dnode, tipc_own_addr, - tsk_peer_port(tsk), + skb = tipc_msg_create(net, TIPC_CRITICAL_IMPORTANCE, + TIPC_CONN_MSG, SHORT_H_SIZE, 0, dnode, + tn->own_addr, tsk_peer_port(tsk), tsk->portid, TIPC_ERR_NO_PORT); if (skb) tipc_link_xmit_skb(net, skb, dnode, tsk->portid); @@ -614,6 +618,7 @@ static int tipc_getname(struct socket *sock, struct sockaddr *uaddr, { struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; struct tipc_sock *tsk = tipc_sk(sock->sk); + struct tipc_net *tn = net_generic(sock_net(sock->sk), tipc_net_id); memset(addr, 0, sizeof(*addr)); if (peer) { @@ -624,7 +629,7 @@ static int tipc_getname(struct socket *sock, struct sockaddr *uaddr, addr->addr.id.node = tsk_peer_node(tsk); } else { addr->addr.id.ref = tsk->portid; - addr->addr.id.node = tipc_own_addr; + addr->addr.id.node = tn->own_addr; } *uaddr_len = sizeof(*addr); @@ -741,7 +746,7 @@ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq, new_mtu: mtu = tipc_bclink_get_mtu(); __skb_queue_head_init(&head); - rc = tipc_msg_build(mhdr, msg, 0, dsz, mtu, &head); + rc = tipc_msg_build(net, mhdr, msg, 0, dsz, mtu, &head); if (unlikely(rc < 0)) return rc; @@ -774,7 +779,7 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *buf) uint i, last, dst = 0; u32 scope = TIPC_CLUSTER_SCOPE; - if (in_own_node(msg_orignode(msg))) + if (in_own_node(net, msg_orignode(msg))) scope = TIPC_NODE_SCOPE; /* Create destination port list: */ @@ -826,7 +831,7 @@ static int tipc_sk_proto_rcv(struct tipc_sock *tsk, u32 *dnode, if (conn_cong) tsk->sk.sk_write_space(&tsk->sk); } else if (msg_type(msg) == CONN_PROBE) { - if (!tipc_msg_reverse(buf, dnode, TIPC_OK)) + if (!tipc_msg_reverse(sock_net(&tsk->sk), buf, dnode, TIPC_OK)) return TIPC_OK; msg_set_type(msg, CONN_PROBE_REPLY); return TIPC_FWD_MSG; @@ -959,7 +964,7 @@ static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock, new_mtu: mtu = tipc_node_get_mtu(net, dnode, tsk->portid); __skb_queue_head_init(&head); - rc = tipc_msg_build(mhdr, m, 0, dsz, mtu, &head); + rc = tipc_msg_build(net, mhdr, m, 0, dsz, mtu, &head); if (rc < 0) goto exit; @@ -1074,7 +1079,7 @@ next: mtu = tsk->max_pkt; send = min_t(uint, dsz - sent, TIPC_MAX_USER_MSG_SIZE); __skb_queue_head_init(&head); - rc = tipc_msg_build(mhdr, m, sent, send, mtu, &head); + rc = tipc_msg_build(net, mhdr, m, sent, send, mtu, &head); if (unlikely(rc < 0)) goto exit; do { @@ -1246,6 +1251,7 @@ static int tipc_sk_anc_data_recv(struct msghdr *m, struct tipc_msg *msg, static void tipc_sk_send_ack(struct tipc_sock *tsk, uint ack) { struct net *net = sock_net(&tsk->sk); + struct tipc_net *tn = net_generic(net, tipc_net_id); struct sk_buff *skb = NULL; struct tipc_msg *msg; u32 peer_port = tsk_peer_port(tsk); @@ -1253,8 +1259,9 @@ static void tipc_sk_send_ack(struct tipc_sock *tsk, uint ack) if (!tsk->connected) return; - skb = tipc_msg_create(CONN_MANAGER, CONN_ACK, INT_H_SIZE, 0, dnode, - tipc_own_addr, peer_port, tsk->portid, TIPC_OK); + skb = tipc_msg_create(net, CONN_MANAGER, CONN_ACK, INT_H_SIZE, 0, + dnode, tn->own_addr, peer_port, tsk->portid, + TIPC_OK); if (!skb) return; msg = buf_msg(skb); @@ -1726,6 +1733,7 @@ static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb) int rc; u32 onode; struct tipc_sock *tsk = tipc_sk(sk); + struct net *net = sock_net(sk); uint truesize = skb->truesize; rc = filter_rcv(sk, skb); @@ -1736,10 +1744,10 @@ static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb) return 0; } - if ((rc < 0) && !tipc_msg_reverse(skb, &onode, -rc)) + if ((rc < 0) && !tipc_msg_reverse(net, skb, &onode, -rc)) return 0; - tipc_link_xmit_skb(sock_net(sk), skb, onode, 0); + tipc_link_xmit_skb(net, skb, onode, 0); return 0; } @@ -1784,7 +1792,7 @@ int tipc_sk_rcv(struct net *net, struct sk_buff *skb) if (likely(!rc)) return 0; exit: - if ((rc < 0) && !tipc_msg_reverse(skb, &dnode, -rc)) + if ((rc < 0) && !tipc_msg_reverse(net, skb, &dnode, -rc)) return -EHOSTUNREACH; tipc_link_xmit_skb(net, skb, dnode, 0); @@ -2045,6 +2053,7 @@ static int tipc_shutdown(struct socket *sock, int how) { struct sock *sk = sock->sk; struct net *net = sock_net(sk); + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_sock *tsk = tipc_sk(sk); struct sk_buff *skb; u32 dnode; @@ -2067,15 +2076,16 @@ restart: kfree_skb(skb); goto restart; } - if (tipc_msg_reverse(skb, &dnode, TIPC_CONN_SHUTDOWN)) + if (tipc_msg_reverse(net, skb, &dnode, + TIPC_CONN_SHUTDOWN)) tipc_link_xmit_skb(net, skb, dnode, tsk->portid); tipc_node_remove_conn(net, dnode, tsk->portid); } else { dnode = tsk_peer_node(tsk); - skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, + skb = tipc_msg_create(net, TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, SHORT_H_SIZE, - 0, dnode, tipc_own_addr, + 0, dnode, tn->own_addr, tsk_peer_port(tsk), tsk->portid, TIPC_CONN_SHUTDOWN); tipc_link_xmit_skb(net, skb, dnode, tsk->portid); @@ -2107,6 +2117,8 @@ static void tipc_sk_timeout(unsigned long data) { struct tipc_sock *tsk = (struct tipc_sock *)data; struct sock *sk = &tsk->sk; + struct net *net = sock_net(sk); + struct tipc_net *tn = net_generic(net, tipc_net_id); struct sk_buff *skb = NULL; u32 peer_port, peer_node; @@ -2120,13 +2132,13 @@ static void tipc_sk_timeout(unsigned long data) if (tsk->probing_state == TIPC_CONN_PROBING) { /* Previous probe not answered -> self abort */ - skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, - SHORT_H_SIZE, 0, tipc_own_addr, - peer_node, tsk->portid, peer_port, - TIPC_ERR_NO_PORT); + skb = tipc_msg_create(net, TIPC_CRITICAL_IMPORTANCE, + TIPC_CONN_MSG, SHORT_H_SIZE, 0, + tn->own_addr, peer_node, tsk->portid, + peer_port, TIPC_ERR_NO_PORT); } else { - skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE, INT_H_SIZE, - 0, peer_node, tipc_own_addr, + skb = tipc_msg_create(net, CONN_MANAGER, CONN_PROBE, INT_H_SIZE, + 0, peer_node, tn->own_addr, peer_port, tsk->portid, TIPC_OK); tsk->probing_state = TIPC_CONN_PROBING; if (!mod_timer(&tsk->timer, jiffies + tsk->probing_intv)) @@ -2198,14 +2210,16 @@ static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope, static int tipc_sk_show(struct tipc_sock *tsk, char *buf, int len, int full_id) { + struct net *net = sock_net(&tsk->sk); + struct tipc_net *tn = net_generic(net, tipc_net_id); struct publication *publ; int ret; if (full_id) ret = tipc_snprintf(buf, len, "<%u.%u.%u:%u>:", - tipc_zone(tipc_own_addr), - tipc_cluster(tipc_own_addr), - tipc_node(tipc_own_addr), tsk->portid); + tipc_zone(tn->own_addr), + tipc_cluster(tn->own_addr), + tipc_node(tn->own_addr), tsk->portid); else ret = tipc_snprintf(buf, len, "%-10u:", tsk->portid); @@ -2296,8 +2310,8 @@ void tipc_sk_reinit(struct net *net) rht_for_each_entry_rcu(tsk, pos, tbl, i, node) { spin_lock_bh(&tsk->sk.sk_lock.slock); msg = &tsk->phdr; - msg_set_prevnode(msg, tipc_own_addr); - msg_set_orignode(msg, tipc_own_addr); + msg_set_prevnode(msg, tn->own_addr); + msg_set_orignode(msg, tn->own_addr); spin_unlock_bh(&tsk->sk.sk_lock.slock); } } @@ -2691,6 +2705,8 @@ static int __tipc_nl_add_sk(struct sk_buff *skb, struct netlink_callback *cb, int err; void *hdr; struct nlattr *attrs; + struct net *net = sock_net(skb->sk); + struct tipc_net *tn = net_generic(net, tipc_net_id); hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, &tipc_genl_v2_family, NLM_F_MULTI, TIPC_NL_SOCK_GET); @@ -2702,7 +2718,7 @@ static int __tipc_nl_add_sk(struct sk_buff *skb, struct netlink_callback *cb, goto genlmsg_cancel; if (nla_put_u32(skb, TIPC_NLA_SOCK_REF, tsk->portid)) goto attr_msg_cancel; - if (nla_put_u32(skb, TIPC_NLA_SOCK_ADDR, tipc_own_addr)) + if (nla_put_u32(skb, TIPC_NLA_SOCK_ADDR, tn->own_addr)) goto attr_msg_cancel; if (tsk->connected) { -- cgit v1.2.3-70-g09d2 From d0796d1ef63deb38147729664691ba3090930b26 Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:04 +0100 Subject: tipc: convert legacy nl bearer dump to nl compat Introduce a framework for dumping netlink data from the new netlink API and formatting it to the old legacy API format. This is done by looping the dump data and calling a format handler for each entity, in this case a bearer. We dump until either all data is dumped or we reach the limited buffer size of the legacy API. Remember, the legacy API doesn't scale. In this commit we convert TIPC_CMD_GET_BEARER_NAMES to use the compat layer. Signed-off-by: Richard Alpe Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- include/uapi/linux/tipc_config.h | 5 + net/tipc/bearer.c | 29 ----- net/tipc/bearer.h | 1 - net/tipc/config.c | 3 - net/tipc/netlink_compat.c | 274 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 278 insertions(+), 34 deletions(-) (limited to 'net/tipc/config.c') diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h index 876d0a14863c..e1f4f05f4c5c 100644 --- a/include/uapi/linux/tipc_config.h +++ b/include/uapi/linux/tipc_config.h @@ -272,6 +272,11 @@ static inline int TLV_CHECK(const void *tlv, __u16 space, __u16 exp_type) (ntohs(((struct tlv_desc *)tlv)->tlv_type) == exp_type); } +static inline int TLV_GET_LEN(struct tlv_desc *tlv) +{ + return ntohs(tlv->tlv_len); +} + static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len) { struct tlv_desc *tlv_ptr; diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 35d400e8c2e5..7a9e29641e61 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -205,35 +205,6 @@ struct tipc_bearer *tipc_bearer_find(struct net *net, const char *name) return NULL; } -/** - * tipc_bearer_get_names - record names of bearers in buffer - */ -struct sk_buff *tipc_bearer_get_names(struct net *net) -{ - struct tipc_net *tn = net_generic(net, tipc_net_id); - struct sk_buff *buf; - struct tipc_bearer *b; - int i, j; - - buf = tipc_cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME)); - if (!buf) - return NULL; - - for (i = 0; media_info_array[i] != NULL; i++) { - for (j = 0; j < MAX_BEARERS; j++) { - b = rtnl_dereference(tn->bearer_list[j]); - if (!b) - continue; - if (b->media == media_info_array[i]) { - tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, - b->name, - strlen(b->name) + 1); - } - } - } - return buf; -} - void tipc_bearer_add_dest(struct net *net, u32 bearer_id, u32 dest) { struct tipc_net *tn = net_generic(net, tipc_net_id); diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index c035e3e24764..956858276d93 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -205,7 +205,6 @@ void tipc_disable_l2_media(struct tipc_bearer *b); int tipc_l2_send_msg(struct net *net, struct sk_buff *buf, struct tipc_bearer *b, struct tipc_media_addr *dest); -struct sk_buff *tipc_bearer_get_names(struct net *net); void tipc_bearer_add_dest(struct net *net, u32 bearer_id, u32 dest); void tipc_bearer_remove_dest(struct net *net, u32 bearer_id, u32 dest); struct tipc_bearer *tipc_bearer_find(struct net *net, const char *name); diff --git a/net/tipc/config.c b/net/tipc/config.c index 6873360cda53..52e84b0ac48a 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -252,9 +252,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, rep_tlv_buf = tipc_nametbl_get(net, req_tlv_area, req_tlv_space); break; - case TIPC_CMD_GET_BEARER_NAMES: - rep_tlv_buf = tipc_bearer_get_names(net); - break; case TIPC_CMD_GET_MEDIA_NAMES: rep_tlv_buf = tipc_media_get_names(); break; diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index f752854c8b10..bd75ea290e3a 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -33,9 +33,265 @@ #include "core.h" #include "config.h" +#include "bearer.h" #include #include +/* The legacy API had an artificial message length limit called + * ULTRA_STRING_MAX_LEN. + */ +#define ULTRA_STRING_MAX_LEN 32768 + +#define TIPC_SKB_MAX TLV_SPACE(ULTRA_STRING_MAX_LEN) + +#define REPLY_TRUNCATED "\n" + +struct tipc_nl_compat_msg { + u16 cmd; + int rep_size; + struct sk_buff *rep; + struct tlv_desc *req; + struct sock *dst_sk; +}; + +struct tipc_nl_compat_cmd_dump { + int (*dumpit)(struct sk_buff *, struct netlink_callback *); + int (*format)(struct tipc_nl_compat_msg *msg, struct nlattr **attrs); +}; + +static int tipc_skb_tailroom(struct sk_buff *skb) +{ + int tailroom; + int limit; + + tailroom = skb_tailroom(skb); + limit = TIPC_SKB_MAX - skb->len; + + if (tailroom < limit) + return tailroom; + + return limit; +} + +static int tipc_add_tlv(struct sk_buff *skb, u16 type, void *data, u16 len) +{ + struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(skb); + + if (tipc_skb_tailroom(skb) < TLV_SPACE(len)) + return -EMSGSIZE; + + skb_put(skb, TLV_SPACE(len)); + tlv->tlv_type = htons(type); + tlv->tlv_len = htons(TLV_LENGTH(len)); + if (len && data) + memcpy(TLV_DATA(tlv), data, len); + + return 0; +} + +static struct sk_buff *tipc_tlv_alloc(int size) +{ + int hdr_len; + struct sk_buff *buf; + + size = TLV_SPACE(size); + hdr_len = nlmsg_total_size(GENL_HDRLEN + TIPC_GENL_HDRLEN); + + buf = alloc_skb(hdr_len + size, GFP_KERNEL); + if (!buf) + return NULL; + + skb_reserve(buf, hdr_len); + + return buf; +} + +static struct sk_buff *tipc_get_err_tlv(char *str) +{ + int str_len = strlen(str) + 1; + struct sk_buff *buf; + + buf = tipc_tlv_alloc(TLV_SPACE(str_len)); + if (buf) + tipc_add_tlv(buf, TIPC_TLV_ERROR_STRING, str, str_len); + + return buf; +} + +static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, + struct tipc_nl_compat_msg *msg, + struct sk_buff *arg) +{ + int len = 0; + int err; + struct sk_buff *buf; + struct nlmsghdr *nlmsg; + struct netlink_callback cb; + + memset(&cb, 0, sizeof(cb)); + cb.nlh = (struct nlmsghdr *)arg->data; + cb.skb = arg; + + buf = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + buf->sk = msg->dst_sk; + + do { + int rem; + + len = (*cmd->dumpit)(buf, &cb); + + nlmsg_for_each_msg(nlmsg, nlmsg_hdr(buf), len, rem) { + struct nlattr **attrs; + + err = tipc_nlmsg_parse(nlmsg, &attrs); + if (err) + goto err_out; + + err = (*cmd->format)(msg, attrs); + if (err) + goto err_out; + + if (tipc_skb_tailroom(msg->rep) <= 1) { + err = -EMSGSIZE; + goto err_out; + } + } + + skb_reset_tail_pointer(buf); + buf->len = 0; + + } while (len); + + err = 0; + +err_out: + kfree_skb(buf); + + if (err == -EMSGSIZE) { + /* The legacy API only considered messages filling + * "ULTRA_STRING_MAX_LEN" to be truncated. + */ + if ((TIPC_SKB_MAX - msg->rep->len) <= 1) { + char *tail = skb_tail_pointer(msg->rep); + + if (*tail != '\0') + sprintf(tail - sizeof(REPLY_TRUNCATED) - 1, + REPLY_TRUNCATED); + } + + return 0; + } + + return err; +} + +static int tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, + struct tipc_nl_compat_msg *msg) +{ + int err; + struct sk_buff *arg; + + msg->rep = tipc_tlv_alloc(msg->rep_size); + if (!msg->rep) + return -ENOMEM; + + arg = nlmsg_new(0, GFP_KERNEL); + if (!arg) { + kfree_skb(msg->rep); + return -ENOMEM; + } + + err = __tipc_nl_compat_dumpit(cmd, msg, arg); + if (err) + kfree_skb(msg->rep); + + kfree_skb(arg); + + return err; +} + +static int tipc_nl_compat_bearer_dump(struct tipc_nl_compat_msg *msg, + struct nlattr **attrs) +{ + struct nlattr *bearer[TIPC_NLA_BEARER_MAX + 1]; + + nla_parse_nested(bearer, TIPC_NLA_BEARER_MAX, attrs[TIPC_NLA_BEARER], + NULL); + + return tipc_add_tlv(msg->rep, TIPC_TLV_BEARER_NAME, + nla_data(bearer[TIPC_NLA_BEARER_NAME]), + nla_len(bearer[TIPC_NLA_BEARER_NAME])); +} + +static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) +{ + struct tipc_nl_compat_cmd_dump dump; + + memset(&dump, 0, sizeof(dump)); + + switch (msg->cmd) { + case TIPC_CMD_GET_BEARER_NAMES: + msg->rep_size = MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME); + dump.dumpit = tipc_nl_bearer_dump; + dump.format = tipc_nl_compat_bearer_dump; + return tipc_nl_compat_dumpit(&dump, msg); + } + + return -EOPNOTSUPP; +} + +static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info) +{ + int err; + int len; + struct tipc_nl_compat_msg msg; + struct nlmsghdr *req_nlh; + struct nlmsghdr *rep_nlh; + struct tipc_genlmsghdr *req_userhdr = info->userhdr; + struct net *net = genl_info_net(info); + + memset(&msg, 0, sizeof(msg)); + + req_nlh = (struct nlmsghdr *)skb->data; + msg.req = nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN; + msg.cmd = req_userhdr->cmd; + msg.dst_sk = info->dst_sk; + + if ((msg.cmd & 0xC000) && (!netlink_net_capable(skb, CAP_NET_ADMIN))) { + msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_NET_ADMIN); + err = -EACCES; + goto send; + } + + len = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN); + if (TLV_GET_LEN(msg.req) && !TLV_OK(msg.req, len)) { + msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED); + err = -EOPNOTSUPP; + goto send; + } + + err = tipc_nl_compat_handle(&msg); + if (err == -EOPNOTSUPP) + msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED); + else if (err == -EINVAL) + msg.rep = tipc_get_err_tlv(TIPC_CFG_TLV_ERROR); +send: + if (!msg.rep) + return err; + + len = nlmsg_total_size(GENL_HDRLEN + TIPC_GENL_HDRLEN); + skb_push(msg.rep, len); + rep_nlh = nlmsg_hdr(msg.rep); + memcpy(rep_nlh, info->nlhdr, len); + rep_nlh->nlmsg_len = msg.rep->len; + genlmsg_unicast(net, msg.rep, NETLINK_CB(skb).portid); + + return err; +} + static int handle_cmd(struct sk_buff *skb, struct genl_info *info) { struct net *net = genl_info_net(info); @@ -69,6 +325,22 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info) return 0; } +/* Temporary function to keep functionality throughout the patchset + * without having to mess with the global variables and other trickery + * of the old API. + */ +static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) +{ + struct tipc_genlmsghdr *req = info->userhdr; + + switch (req->cmd) { + case TIPC_CMD_GET_BEARER_NAMES: + return tipc_nl_compat_recv(skb, info); + } + + return handle_cmd(skb, info); +} + static struct genl_family tipc_genl_compat_family = { .id = GENL_ID_GENERATE, .name = TIPC_GENL_NAME, @@ -81,7 +353,7 @@ static struct genl_family tipc_genl_compat_family = { static struct genl_ops tipc_genl_compat_ops[] = { { .cmd = TIPC_GENL_CMD, - .doit = handle_cmd, + .doit = tipc_nl_compat_tmp_wrap, }, }; -- cgit v1.2.3-70-g09d2 From 9ab154658a7ff2c5076607e02f18581c6859fc2a Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:05 +0100 Subject: tipc: convert legacy nl bearer enable/disable to nl compat Introduce a framework for transcoding legacy nl action into actions (.doit) calls from the new nl API. This is done by converting the incoming TLV data into netlink data with nested netlink attributes. Unfortunately due to the randomness of the legacy API we can't do this generically so each legacy netlink command requires a specific transcoding recipe. In this case for bearer enable and bearer disable. Convert TIPC_CMD_ENABLE_BEARER and TIPC_CMD_DISABLE_BEARER into doit compat calls. Signed-off-by: Richard Alpe Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- include/uapi/linux/tipc_config.h | 5 ++ net/tipc/bearer.c | 26 ++----- net/tipc/bearer.h | 3 - net/tipc/config.c | 33 --------- net/tipc/netlink_compat.c | 144 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 154 insertions(+), 57 deletions(-) (limited to 'net/tipc/config.c') diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h index e1f4f05f4c5c..f9226566c1b8 100644 --- a/include/uapi/linux/tipc_config.h +++ b/include/uapi/linux/tipc_config.h @@ -277,6 +277,11 @@ static inline int TLV_GET_LEN(struct tlv_desc *tlv) return ntohs(tlv->tlv_len); } +static inline int TLV_CHECK_TYPE(struct tlv_desc *tlv, __u16 type) +{ + return (ntohs(tlv->tlv_type) == type); +} + static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len) { struct tlv_desc *tlv_ptr; diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 7a9e29641e61..de1c800ef806 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -236,8 +236,8 @@ void tipc_bearer_remove_dest(struct net *net, u32 bearer_id, u32 dest) /** * tipc_enable_bearer - enable bearer with the given name */ -int tipc_enable_bearer(struct net *net, const char *name, u32 disc_domain, - u32 priority) +static int tipc_enable_bearer(struct net *net, const char *name, + u32 disc_domain, u32 priority) { struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_bearer *b_ptr; @@ -393,22 +393,6 @@ static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr, kfree_rcu(b_ptr, rcu); } -int tipc_disable_bearer(struct net *net, const char *name) -{ - struct tipc_bearer *b_ptr; - int res; - - b_ptr = tipc_bearer_find(net, name); - if (b_ptr == NULL) { - pr_warn("Attempt to disable unknown bearer <%s>\n", name); - res = -EINVAL; - } else { - bearer_disable(net, b_ptr, false); - res = 0; - } - return res; -} - int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b) { struct net_device *dev; @@ -756,7 +740,7 @@ int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info) char *name; struct tipc_bearer *bearer; struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1]; - struct net *net = genl_info_net(info); + struct net *net = sock_net(skb->sk); if (!info->attrs[TIPC_NLA_BEARER]) return -EINVAL; @@ -787,11 +771,11 @@ int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info) int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info) { - struct net *net = genl_info_net(info); - struct tipc_net *tn = net_generic(net, tipc_net_id); int err; char *bearer; struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1]; + struct net *net = sock_net(skb->sk); + struct tipc_net *tn = net_generic(net, tipc_net_id); u32 domain; u32 prio; diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 956858276d93..06f25d144871 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -173,9 +173,6 @@ struct tipc_bearer_names { */ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr); -int tipc_enable_bearer(struct net *net, const char *bearer_name, - u32 disc_domain, u32 priority); -int tipc_disable_bearer(struct net *net, const char *name); /* * Routines made available to TIPC by supported media types diff --git a/net/tipc/config.c b/net/tipc/config.c index 52e84b0ac48a..f8cd5e1b545f 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -134,33 +134,6 @@ static struct sk_buff *tipc_show_stats(void) return buf; } -static struct sk_buff *cfg_enable_bearer(struct net *net) -{ - struct tipc_bearer_config *args; - - if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG)) - return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - - args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area); - if (tipc_enable_bearer(net, args->name, - ntohl(args->disc_domain), - ntohl(args->priority))) - return tipc_cfg_reply_error_string("unable to enable bearer"); - - return tipc_cfg_reply_none(); -} - -static struct sk_buff *cfg_disable_bearer(struct net *net) -{ - if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME)) - return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - - if (tipc_disable_bearer(net, (char *)TLV_DATA(req_tlv_area))) - return tipc_cfg_reply_error_string("unable to disable bearer"); - - return tipc_cfg_reply_none(); -} - static struct sk_buff *cfg_set_own_addr(struct net *net) { struct tipc_net *tn = net_generic(net, tipc_net_id); @@ -267,12 +240,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, rep_tlv_buf = tipc_link_cmd_config(net, req_tlv_area, req_tlv_space, cmd); break; - case TIPC_CMD_ENABLE_BEARER: - rep_tlv_buf = cfg_enable_bearer(net); - break; - case TIPC_CMD_DISABLE_BEARER: - rep_tlv_buf = cfg_disable_bearer(net); - break; case TIPC_CMD_SET_NODE_ADDR: rep_tlv_buf = cfg_set_own_addr(net); break; diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index bd75ea290e3a..12b0f4424797 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -49,6 +49,7 @@ struct tipc_nl_compat_msg { u16 cmd; int rep_size; + int req_type; struct sk_buff *rep; struct tlv_desc *req; struct sock *dst_sk; @@ -59,6 +60,11 @@ struct tipc_nl_compat_cmd_dump { int (*format)(struct tipc_nl_compat_msg *msg, struct nlattr **attrs); }; +struct tipc_nl_compat_cmd_doit { + int (*doit)(struct sk_buff *skb, struct genl_info *info); + int (*transcode)(struct sk_buff *skb, struct tipc_nl_compat_msg *msg); +}; + static int tipc_skb_tailroom(struct sk_buff *skb) { int tailroom; @@ -213,6 +219,78 @@ static int tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, return err; } +static int __tipc_nl_compat_doit(struct tipc_nl_compat_cmd_doit *cmd, + struct tipc_nl_compat_msg *msg) +{ + int err; + struct sk_buff *doit_buf; + struct sk_buff *trans_buf; + struct nlattr **attrbuf; + struct genl_info info; + + trans_buf = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); + if (!trans_buf) + return -ENOMEM; + + err = (*cmd->transcode)(trans_buf, msg); + if (err) + goto trans_out; + + attrbuf = kmalloc((tipc_genl_family.maxattr + 1) * + sizeof(struct nlattr *), GFP_KERNEL); + if (!attrbuf) { + err = -ENOMEM; + goto trans_out; + } + + err = nla_parse(attrbuf, tipc_genl_family.maxattr, + (const struct nlattr *)trans_buf->data, + trans_buf->len, NULL); + if (err) + goto parse_out; + + doit_buf = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); + if (!doit_buf) { + err = -ENOMEM; + goto parse_out; + } + + doit_buf->sk = msg->dst_sk; + + memset(&info, 0, sizeof(info)); + info.attrs = attrbuf; + + err = (*cmd->doit)(doit_buf, &info); + + kfree_skb(doit_buf); +parse_out: + kfree(attrbuf); +trans_out: + kfree_skb(trans_buf); + + return err; +} + +static int tipc_nl_compat_doit(struct tipc_nl_compat_cmd_doit *cmd, + struct tipc_nl_compat_msg *msg) +{ + int err; + + if (msg->req_type && !TLV_CHECK_TYPE(msg->req, msg->req_type)) + return -EINVAL; + + err = __tipc_nl_compat_doit(cmd, msg); + if (err) + return err; + + /* The legacy API considered an empty message a success message */ + msg->rep = tipc_tlv_alloc(0); + if (!msg->rep) + return -ENOMEM; + + return 0; +} + static int tipc_nl_compat_bearer_dump(struct tipc_nl_compat_msg *msg, struct nlattr **attrs) { @@ -226,11 +304,65 @@ static int tipc_nl_compat_bearer_dump(struct tipc_nl_compat_msg *msg, nla_len(bearer[TIPC_NLA_BEARER_NAME])); } +static int tipc_nl_compat_bearer_enable(struct sk_buff *skb, + struct tipc_nl_compat_msg *msg) +{ + struct nlattr *prop; + struct nlattr *bearer; + struct tipc_bearer_config *b; + + b = (struct tipc_bearer_config *)TLV_DATA(msg->req); + + bearer = nla_nest_start(skb, TIPC_NLA_BEARER); + if (!bearer) + return -EMSGSIZE; + + if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, b->name)) + return -EMSGSIZE; + + if (nla_put_u32(skb, TIPC_NLA_BEARER_DOMAIN, ntohl(b->disc_domain))) + return -EMSGSIZE; + + if (ntohl(b->priority) <= TIPC_MAX_LINK_PRI) { + prop = nla_nest_start(skb, TIPC_NLA_BEARER_PROP); + if (!prop) + return -EMSGSIZE; + if (nla_put_u32(skb, TIPC_NLA_PROP_PRIO, ntohl(b->priority))) + return -EMSGSIZE; + nla_nest_end(skb, prop); + } + nla_nest_end(skb, bearer); + + return 0; +} + +static int tipc_nl_compat_bearer_disable(struct sk_buff *skb, + struct tipc_nl_compat_msg *msg) +{ + char *name; + struct nlattr *bearer; + + name = (char *)TLV_DATA(msg->req); + + bearer = nla_nest_start(skb, TIPC_NLA_BEARER); + if (!bearer) + return -EMSGSIZE; + + if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, name)) + return -EMSGSIZE; + + nla_nest_end(skb, bearer); + + return 0; +} + static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) { struct tipc_nl_compat_cmd_dump dump; + struct tipc_nl_compat_cmd_doit doit; memset(&dump, 0, sizeof(dump)); + memset(&doit, 0, sizeof(doit)); switch (msg->cmd) { case TIPC_CMD_GET_BEARER_NAMES: @@ -238,6 +370,16 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) dump.dumpit = tipc_nl_bearer_dump; dump.format = tipc_nl_compat_bearer_dump; return tipc_nl_compat_dumpit(&dump, msg); + case TIPC_CMD_ENABLE_BEARER: + msg->req_type = TIPC_TLV_BEARER_CONFIG; + doit.doit = tipc_nl_bearer_enable; + doit.transcode = tipc_nl_compat_bearer_enable; + return tipc_nl_compat_doit(&doit, msg); + case TIPC_CMD_DISABLE_BEARER: + msg->req_type = TIPC_TLV_BEARER_NAME; + doit.doit = tipc_nl_bearer_disable; + doit.transcode = tipc_nl_compat_bearer_disable; + return tipc_nl_compat_doit(&doit, msg); } return -EOPNOTSUPP; @@ -335,6 +477,8 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) switch (req->cmd) { case TIPC_CMD_GET_BEARER_NAMES: + case TIPC_CMD_ENABLE_BEARER: + case TIPC_CMD_DISABLE_BEARER: return tipc_nl_compat_recv(skb, info); } -- cgit v1.2.3-70-g09d2 From f2b3b2d4ccbf9666f5f42a21347cd1aaa532b2fa Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:06 +0100 Subject: tipc: convert legacy nl link stat to nl compat 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. Signed-off-by: Richard Alpe Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- include/uapi/linux/tipc_config.h | 10 ++ net/tipc/bcast.c | 43 -------- net/tipc/bcast.h | 1 - net/tipc/config.c | 4 - net/tipc/link.c | 141 --------------------------- net/tipc/link.h | 3 - net/tipc/netlink_compat.c | 205 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 215 insertions(+), 192 deletions(-) (limited to 'net/tipc/config.c') diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h index f9226566c1b8..087b0ef82c07 100644 --- a/include/uapi/linux/tipc_config.h +++ b/include/uapi/linux/tipc_config.h @@ -277,11 +277,21 @@ static inline int TLV_GET_LEN(struct tlv_desc *tlv) return ntohs(tlv->tlv_len); } +static inline void TLV_SET_LEN(struct tlv_desc *tlv, __u16 len) +{ + tlv->tlv_len = htons(len); +} + static inline int TLV_CHECK_TYPE(struct tlv_desc *tlv, __u16 type) { return (ntohs(tlv->tlv_type) == type); } +static inline void TLV_SET_TYPE(struct tlv_desc *tlv, __u16 type) +{ + tlv->tlv_type = htons(type); +} + static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len) { struct tlv_desc *tlv_ptr; diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index e96fd6a6d5c2..3e41704832de 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -860,49 +860,6 @@ msg_full: return -EMSGSIZE; } -int tipc_bclink_stats(struct net *net, char *buf, const u32 buf_size) -{ - int ret; - struct tipc_stats *s; - struct tipc_net *tn = net_generic(net, tipc_net_id); - struct tipc_link *bcl = tn->bcl; - - if (!bcl) - return 0; - - tipc_bclink_lock(net); - - s = &bcl->stats; - - ret = tipc_snprintf(buf, buf_size, "Link <%s>\n" - " Window:%u packets\n", - bcl->name, bcl->queue_limit[0]); - ret += tipc_snprintf(buf + ret, buf_size - ret, - " RX packets:%u fragments:%u/%u bundles:%u/%u\n", - s->recv_info, s->recv_fragments, - s->recv_fragmented, s->recv_bundles, - s->recv_bundled); - ret += tipc_snprintf(buf + ret, buf_size - ret, - " TX packets:%u fragments:%u/%u bundles:%u/%u\n", - s->sent_info, s->sent_fragments, - s->sent_fragmented, s->sent_bundles, - s->sent_bundled); - ret += tipc_snprintf(buf + ret, buf_size - ret, - " RX naks:%u defs:%u dups:%u\n", - s->recv_nacks, s->deferred_recv, s->duplicates); - ret += tipc_snprintf(buf + ret, buf_size - ret, - " TX naks:%u acks:%u dups:%u\n", - s->sent_nacks, s->sent_acks, s->retransmitted); - ret += tipc_snprintf(buf + ret, buf_size - ret, - " Congestion link:%u Send queue max:%u avg:%u\n", - s->link_congs, s->max_queue_sz, - s->queue_sz_counts ? - (s->accu_queue_sz / s->queue_sz_counts) : 0); - - tipc_bclink_unlock(net); - return ret; -} - int tipc_bclink_reset_stats(struct net *net) { struct tipc_net *tn = net_generic(net, tipc_net_id); diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index a910c0b9f249..43f397fbac55 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h @@ -127,7 +127,6 @@ u32 tipc_bclink_get_last_sent(struct net *net); u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr); void tipc_bclink_update_link_state(struct tipc_node *node, u32 last_sent); -int tipc_bclink_stats(struct net *net, char *stats_buf, const u32 buf_size); int tipc_bclink_reset_stats(struct net *net); int tipc_bclink_set_queue_limits(struct net *net, u32 limit); void tipc_bcbearer_sort(struct net *net, struct tipc_node_map *nm_ptr, diff --git a/net/tipc/config.c b/net/tipc/config.c index f8cd5e1b545f..67b76ee847f3 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -213,10 +213,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, rep_tlv_buf = tipc_node_get_links(net, req_tlv_area, req_tlv_space); break; - case TIPC_CMD_SHOW_LINK_STATS: - rep_tlv_buf = tipc_link_cmd_show_stats(net, req_tlv_area, - req_tlv_space); - break; case TIPC_CMD_RESET_LINK_STATS: rep_tlv_buf = tipc_link_cmd_reset_stats(net, req_tlv_area, req_tlv_space); diff --git a/net/tipc/link.c b/net/tipc/link.c index 466f28fcf215..2622fb99344a 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -2146,147 +2146,6 @@ struct sk_buff *tipc_link_cmd_reset_stats(struct net *net, return tipc_cfg_reply_none(); } -/** - * percent - convert count to a percentage of total (rounding up or down) - */ -static u32 percent(u32 count, u32 total) -{ - return (count * 100 + (total / 2)) / total; -} - -/** - * tipc_link_stats - print link statistics - * @net: the applicable net namespace - * @name: link name - * @buf: print buffer area - * @buf_size: size of print buffer area - * - * Returns length of print buffer data string (or 0 if error) - */ -static int tipc_link_stats(struct net *net, const char *name, char *buf, - const u32 buf_size) -{ - struct tipc_link *l; - struct tipc_stats *s; - struct tipc_node *node; - char *status; - u32 profile_total = 0; - unsigned int bearer_id; - int ret; - - if (!strcmp(name, tipc_bclink_name)) - return tipc_bclink_stats(net, buf, buf_size); - - node = tipc_link_find_owner(net, name, &bearer_id); - if (!node) - return 0; - - tipc_node_lock(node); - - l = node->links[bearer_id]; - if (!l) { - tipc_node_unlock(node); - return 0; - } - - s = &l->stats; - - if (tipc_link_is_active(l)) - status = "ACTIVE"; - else if (tipc_link_is_up(l)) - status = "STANDBY"; - else - status = "DEFUNCT"; - - ret = tipc_snprintf(buf, buf_size, "Link <%s>\n" - " %s MTU:%u Priority:%u Tolerance:%u ms" - " Window:%u packets\n", - l->name, status, l->max_pkt, l->priority, - l->tolerance, l->queue_limit[0]); - - ret += tipc_snprintf(buf + ret, buf_size - ret, - " RX packets:%u fragments:%u/%u bundles:%u/%u\n", - l->next_in_no - s->recv_info, s->recv_fragments, - s->recv_fragmented, s->recv_bundles, - s->recv_bundled); - - ret += tipc_snprintf(buf + ret, buf_size - ret, - " TX packets:%u fragments:%u/%u bundles:%u/%u\n", - l->next_out_no - s->sent_info, s->sent_fragments, - s->sent_fragmented, s->sent_bundles, - s->sent_bundled); - - profile_total = s->msg_length_counts; - if (!profile_total) - profile_total = 1; - - ret += tipc_snprintf(buf + ret, buf_size - ret, - " TX profile sample:%u packets average:%u octets\n" - " 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% " - "-16384:%u%% -32768:%u%% -66000:%u%%\n", - s->msg_length_counts, - s->msg_lengths_total / profile_total, - percent(s->msg_length_profile[0], profile_total), - percent(s->msg_length_profile[1], profile_total), - percent(s->msg_length_profile[2], profile_total), - percent(s->msg_length_profile[3], profile_total), - percent(s->msg_length_profile[4], profile_total), - percent(s->msg_length_profile[5], profile_total), - percent(s->msg_length_profile[6], profile_total)); - - ret += tipc_snprintf(buf + ret, buf_size - ret, - " RX states:%u probes:%u naks:%u defs:%u" - " dups:%u\n", s->recv_states, s->recv_probes, - s->recv_nacks, s->deferred_recv, s->duplicates); - - ret += tipc_snprintf(buf + ret, buf_size - ret, - " TX states:%u probes:%u naks:%u acks:%u" - " dups:%u\n", s->sent_states, s->sent_probes, - s->sent_nacks, s->sent_acks, s->retransmitted); - - ret += tipc_snprintf(buf + ret, buf_size - ret, - " Congestion link:%u Send queue" - " max:%u avg:%u\n", s->link_congs, - s->max_queue_sz, s->queue_sz_counts ? - (s->accu_queue_sz / s->queue_sz_counts) : 0); - - tipc_node_unlock(node); - return ret; -} - -struct sk_buff *tipc_link_cmd_show_stats(struct net *net, - const void *req_tlv_area, - int req_tlv_space) -{ - struct sk_buff *buf; - struct tlv_desc *rep_tlv; - int str_len; - int pb_len; - char *pb; - - if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) - return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - - buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN)); - if (!buf) - return NULL; - - rep_tlv = (struct tlv_desc *)buf->data; - pb = TLV_DATA(rep_tlv); - pb_len = ULTRA_STRING_MAX_LEN; - str_len = tipc_link_stats(net, (char *)TLV_DATA(req_tlv_area), - pb, pb_len); - if (!str_len) { - kfree_skb(buf); - return tipc_cfg_reply_error_string("link not found"); - } - str_len += 1; /* for "\0" */ - skb_put(buf, TLV_SPACE(str_len)); - TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); - - return buf; -} - static void link_print(struct tipc_link *l_ptr, const char *str) { struct tipc_net *tn = net_generic(l_ptr->owner->net, tipc_net_id); diff --git a/net/tipc/link.h b/net/tipc/link.h index 34d3f55c4cea..8c8340cf991f 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -217,9 +217,6 @@ int tipc_link_is_active(struct tipc_link *l_ptr); void tipc_link_purge_queues(struct tipc_link *l_ptr); struct sk_buff *tipc_link_cmd_config(struct net *net, const void *req_tlv_area, int req_tlv_space, u16 cmd); -struct sk_buff *tipc_link_cmd_show_stats(struct net *net, - const void *req_tlv_area, - int req_tlv_space); struct sk_buff *tipc_link_cmd_reset_stats(struct net *net, const void *req_tlv_area, int req_tlv_space); diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 12b0f4424797..899bd94da467 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -34,6 +34,7 @@ #include "core.h" #include "config.h" #include "bearer.h" +#include "link.h" #include #include @@ -48,6 +49,7 @@ struct tipc_nl_compat_msg { u16 cmd; + int rep_type; int rep_size; int req_type; struct sk_buff *rep; @@ -95,6 +97,40 @@ static int tipc_add_tlv(struct sk_buff *skb, u16 type, void *data, u16 len) return 0; } +static void tipc_tlv_init(struct sk_buff *skb, u16 type) +{ + struct tlv_desc *tlv = (struct tlv_desc *)skb->data; + + TLV_SET_LEN(tlv, 0); + TLV_SET_TYPE(tlv, type); + skb_put(skb, sizeof(struct tlv_desc)); +} + +static int tipc_tlv_sprintf(struct sk_buff *skb, const char *fmt, ...) +{ + int n; + u16 len; + u32 rem; + char *buf; + struct tlv_desc *tlv; + va_list args; + + rem = tipc_skb_tailroom(skb); + + tlv = (struct tlv_desc *)skb->data; + len = TLV_GET_LEN(tlv); + buf = TLV_DATA(tlv) + len; + + va_start(args, fmt); + n = vscnprintf(buf, rem, fmt, args); + va_end(args); + + TLV_SET_LEN(tlv, n + len); + skb_put(skb, n); + + return n; +} + static struct sk_buff *tipc_tlv_alloc(int size) { int hdr_len; @@ -200,10 +236,16 @@ static int tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, int err; struct sk_buff *arg; + if (msg->req_type && !TLV_CHECK_TYPE(msg->req, msg->req_type)) + return -EINVAL; + msg->rep = tipc_tlv_alloc(msg->rep_size); if (!msg->rep) return -ENOMEM; + if (msg->rep_type) + tipc_tlv_init(msg->rep, msg->rep_type); + arg = nlmsg_new(0, GFP_KERNEL); if (!arg) { kfree_skb(msg->rep); @@ -356,6 +398,161 @@ static int tipc_nl_compat_bearer_disable(struct sk_buff *skb, return 0; } +static inline u32 perc(u32 count, u32 total) +{ + return (count * 100 + (total / 2)) / total; +} + +static void __fill_bc_link_stat(struct tipc_nl_compat_msg *msg, + struct nlattr *prop[], struct nlattr *stats[]) +{ + tipc_tlv_sprintf(msg->rep, " Window:%u packets\n", + nla_get_u32(prop[TIPC_NLA_PROP_WIN])); + + tipc_tlv_sprintf(msg->rep, + " RX packets:%u fragments:%u/%u bundles:%u/%u\n", + nla_get_u32(stats[TIPC_NLA_STATS_RX_INFO]), + nla_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTS]), + nla_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTED]), + nla_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLES]), + nla_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLED])); + + tipc_tlv_sprintf(msg->rep, + " TX packets:%u fragments:%u/%u bundles:%u/%u\n", + nla_get_u32(stats[TIPC_NLA_STATS_TX_INFO]), + nla_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTS]), + nla_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTED]), + nla_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLES]), + nla_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLED])); + + tipc_tlv_sprintf(msg->rep, " RX naks:%u defs:%u dups:%u\n", + nla_get_u32(stats[TIPC_NLA_STATS_RX_NACKS]), + nla_get_u32(stats[TIPC_NLA_STATS_RX_DEFERRED]), + nla_get_u32(stats[TIPC_NLA_STATS_DUPLICATES])); + + tipc_tlv_sprintf(msg->rep, " TX naks:%u acks:%u dups:%u\n", + nla_get_u32(stats[TIPC_NLA_STATS_TX_NACKS]), + nla_get_u32(stats[TIPC_NLA_STATS_TX_ACKS]), + nla_get_u32(stats[TIPC_NLA_STATS_RETRANSMITTED])); + + tipc_tlv_sprintf(msg->rep, + " Congestion link:%u Send queue max:%u avg:%u", + nla_get_u32(stats[TIPC_NLA_STATS_LINK_CONGS]), + nla_get_u32(stats[TIPC_NLA_STATS_MAX_QUEUE]), + nla_get_u32(stats[TIPC_NLA_STATS_AVG_QUEUE])); +} + +static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg, + struct nlattr **attrs) +{ + char *name; + struct nlattr *link[TIPC_NLA_LINK_MAX + 1]; + struct nlattr *prop[TIPC_NLA_PROP_MAX + 1]; + struct nlattr *stats[TIPC_NLA_STATS_MAX + 1]; + + nla_parse_nested(link, TIPC_NLA_LINK_MAX, attrs[TIPC_NLA_LINK], NULL); + + nla_parse_nested(prop, TIPC_NLA_PROP_MAX, link[TIPC_NLA_LINK_PROP], + NULL); + + nla_parse_nested(stats, TIPC_NLA_STATS_MAX, link[TIPC_NLA_LINK_STATS], + NULL); + + name = (char *)TLV_DATA(msg->req); + if (strcmp(name, nla_data(link[TIPC_NLA_LINK_NAME])) != 0) + return 0; + + tipc_tlv_sprintf(msg->rep, "\nLink <%s>\n", + nla_data(link[TIPC_NLA_LINK_NAME])); + + if (link[TIPC_NLA_LINK_BROADCAST]) { + __fill_bc_link_stat(msg, prop, stats); + return 0; + } + + if (link[TIPC_NLA_LINK_ACTIVE]) + tipc_tlv_sprintf(msg->rep, " ACTIVE"); + else if (link[TIPC_NLA_LINK_UP]) + tipc_tlv_sprintf(msg->rep, " STANDBY"); + else + tipc_tlv_sprintf(msg->rep, " DEFUNCT"); + + tipc_tlv_sprintf(msg->rep, " MTU:%u Priority:%u", + nla_get_u32(link[TIPC_NLA_LINK_MTU]), + nla_get_u32(prop[TIPC_NLA_PROP_PRIO])); + + tipc_tlv_sprintf(msg->rep, " Tolerance:%u ms Window:%u packets\n", + nla_get_u32(prop[TIPC_NLA_PROP_TOL]), + nla_get_u32(prop[TIPC_NLA_PROP_WIN])); + + tipc_tlv_sprintf(msg->rep, + " RX packets:%u fragments:%u/%u bundles:%u/%u\n", + nla_get_u32(link[TIPC_NLA_LINK_RX]) - + nla_get_u32(stats[TIPC_NLA_STATS_RX_INFO]), + nla_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTS]), + nla_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTED]), + nla_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLES]), + nla_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLED])); + + tipc_tlv_sprintf(msg->rep, + " TX packets:%u fragments:%u/%u bundles:%u/%u\n", + nla_get_u32(link[TIPC_NLA_LINK_TX]) - + nla_get_u32(stats[TIPC_NLA_STATS_TX_INFO]), + nla_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTS]), + nla_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTED]), + nla_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLES]), + nla_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLED])); + + tipc_tlv_sprintf(msg->rep, + " TX profile sample:%u packets average:%u octets\n", + nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_CNT]), + nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_TOT]) / + nla_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT])); + + tipc_tlv_sprintf(msg->rep, + " 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% ", + perc(nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P0]), + nla_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT])), + perc(nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P1]), + nla_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT])), + perc(nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P2]), + nla_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT])), + perc(nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P3]), + nla_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT]))); + + tipc_tlv_sprintf(msg->rep, "-16384:%u%% -32768:%u%% -66000:%u%%\n", + perc(nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P4]), + nla_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT])), + perc(nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P5]), + nla_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT])), + perc(nla_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P6]), + nla_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT]))); + + tipc_tlv_sprintf(msg->rep, + " RX states:%u probes:%u naks:%u defs:%u dups:%u\n", + nla_get_u32(stats[TIPC_NLA_STATS_RX_STATES]), + nla_get_u32(stats[TIPC_NLA_STATS_RX_PROBES]), + nla_get_u32(stats[TIPC_NLA_STATS_RX_NACKS]), + nla_get_u32(stats[TIPC_NLA_STATS_RX_DEFERRED]), + nla_get_u32(stats[TIPC_NLA_STATS_DUPLICATES])); + + tipc_tlv_sprintf(msg->rep, + " TX states:%u probes:%u naks:%u acks:%u dups:%u\n", + nla_get_u32(stats[TIPC_NLA_STATS_TX_STATES]), + nla_get_u32(stats[TIPC_NLA_STATS_TX_PROBES]), + nla_get_u32(stats[TIPC_NLA_STATS_TX_NACKS]), + nla_get_u32(stats[TIPC_NLA_STATS_TX_ACKS]), + nla_get_u32(stats[TIPC_NLA_STATS_RETRANSMITTED])); + + tipc_tlv_sprintf(msg->rep, + " Congestion link:%u Send queue max:%u avg:%u", + nla_get_u32(stats[TIPC_NLA_STATS_LINK_CONGS]), + nla_get_u32(stats[TIPC_NLA_STATS_MAX_QUEUE]), + nla_get_u32(stats[TIPC_NLA_STATS_AVG_QUEUE])); + + return 0; +} + static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) { struct tipc_nl_compat_cmd_dump dump; @@ -380,6 +577,13 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) doit.doit = tipc_nl_bearer_disable; doit.transcode = tipc_nl_compat_bearer_disable; return tipc_nl_compat_doit(&doit, msg); + case TIPC_CMD_SHOW_LINK_STATS: + msg->req_type = TIPC_TLV_LINK_NAME; + msg->rep_size = ULTRA_STRING_MAX_LEN; + msg->rep_type = TIPC_TLV_ULTRA_STRING; + dump.dumpit = tipc_nl_link_dump; + dump.format = tipc_nl_compat_link_stat_dump; + return tipc_nl_compat_dumpit(&dump, msg); } return -EOPNOTSUPP; @@ -479,6 +683,7 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) case TIPC_CMD_GET_BEARER_NAMES: case TIPC_CMD_ENABLE_BEARER: case TIPC_CMD_DISABLE_BEARER: + case TIPC_CMD_SHOW_LINK_STATS: return tipc_nl_compat_recv(skb, info); } -- cgit v1.2.3-70-g09d2 From 357ebdbfca0baa9a8d8d85307393e9ec3406affc Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:07 +0100 Subject: tipc: convert legacy nl link dump to nl compat Convert TIPC_CMD_GET_LINKS to compat dumpit and remove global link counter solely used by the legacy API. Signed-off-by: Richard Alpe Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/config.c | 4 --- net/tipc/netlink_compat.c | 23 +++++++++++++++ net/tipc/node.c | 73 ----------------------------------------------- net/tipc/node.h | 2 -- 4 files changed, 23 insertions(+), 79 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/config.c b/net/tipc/config.c index 67b76ee847f3..1b17f5846e86 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -209,10 +209,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, rep_tlv_buf = tipc_node_get_nodes(net, req_tlv_area, req_tlv_space); break; - case TIPC_CMD_GET_LINKS: - rep_tlv_buf = tipc_node_get_links(net, req_tlv_area, - req_tlv_space); - break; case TIPC_CMD_RESET_LINK_STATS: rep_tlv_buf = tipc_link_cmd_reset_stats(net, req_tlv_area, req_tlv_space); diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 899bd94da467..bff9403899ed 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -553,6 +553,22 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg, return 0; } +static int tipc_nl_compat_link_dump(struct tipc_nl_compat_msg *msg, + struct nlattr **attrs) +{ + struct nlattr *link[TIPC_NLA_LINK_MAX + 1]; + struct tipc_link_info link_info; + + nla_parse_nested(link, TIPC_NLA_LINK_MAX, attrs[TIPC_NLA_LINK], NULL); + + link_info.dest = nla_get_flag(link[TIPC_NLA_LINK_DEST]); + link_info.up = htonl(nla_get_flag(link[TIPC_NLA_LINK_UP])); + strcpy(link_info.str, nla_data(link[TIPC_NLA_LINK_NAME])); + + return tipc_add_tlv(msg->rep, TIPC_TLV_LINK_INFO, + &link_info, sizeof(link_info)); +} + static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) { struct tipc_nl_compat_cmd_dump dump; @@ -584,6 +600,12 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) dump.dumpit = tipc_nl_link_dump; dump.format = tipc_nl_compat_link_stat_dump; return tipc_nl_compat_dumpit(&dump, msg); + case TIPC_CMD_GET_LINKS: + msg->req_type = TIPC_TLV_NET_ADDR; + msg->rep_size = ULTRA_STRING_MAX_LEN; + dump.dumpit = tipc_nl_link_dump; + dump.format = tipc_nl_compat_link_dump; + return tipc_nl_compat_dumpit(&dump, msg); } return -EOPNOTSUPP; @@ -684,6 +706,7 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) case TIPC_CMD_ENABLE_BEARER: case TIPC_CMD_DISABLE_BEARER: case TIPC_CMD_SHOW_LINK_STATS: + case TIPC_CMD_GET_LINKS: return tipc_nl_compat_recv(skb, info); } diff --git a/net/tipc/node.c b/net/tipc/node.c index 995618d6da9d..46b87f77d342 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -319,27 +319,18 @@ int tipc_node_is_up(struct tipc_node *n_ptr) void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) { - struct tipc_net *tn = net_generic(n_ptr->net, tipc_net_id); - n_ptr->links[l_ptr->bearer_id] = l_ptr; - spin_lock_bh(&tn->node_list_lock); - tn->num_links++; - spin_unlock_bh(&tn->node_list_lock); n_ptr->link_cnt++; } void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) { - struct tipc_net *tn = net_generic(n_ptr->net, tipc_net_id); int i; for (i = 0; i < MAX_BEARERS; i++) { if (l_ptr != n_ptr->links[i]) continue; n_ptr->links[i] = NULL; - spin_lock_bh(&tn->node_list_lock); - tn->num_links--; - spin_unlock_bh(&tn->node_list_lock); n_ptr->link_cnt--; } } @@ -467,70 +458,6 @@ struct sk_buff *tipc_node_get_nodes(struct net *net, const void *req_tlv_area, return buf; } -struct sk_buff *tipc_node_get_links(struct net *net, const void *req_tlv_area, - int req_tlv_space) -{ - struct tipc_net *tn = net_generic(net, tipc_net_id); - u32 domain; - struct sk_buff *buf; - struct tipc_node *n_ptr; - struct tipc_link_info link_info; - u32 payload_size; - - if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) - return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - - domain = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); - if (!tipc_addr_domain_valid(domain)) - return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (network address)"); - - if (!tn->own_addr) - return tipc_cfg_reply_none(); - - spin_lock_bh(&tn->node_list_lock); - /* Get space for all unicast links + broadcast link */ - payload_size = TLV_SPACE((sizeof(link_info)) * (tn->num_links + 1)); - if (payload_size > 32768u) { - spin_unlock_bh(&tn->node_list_lock); - return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (too many links)"); - } - spin_unlock_bh(&tn->node_list_lock); - - buf = tipc_cfg_reply_alloc(payload_size); - if (!buf) - return NULL; - - /* Add TLV for broadcast link */ - link_info.dest = htonl(tipc_cluster_mask(tn->own_addr)); - link_info.up = htonl(1); - strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME); - tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); - - /* Add TLVs for any other links in scope */ - rcu_read_lock(); - list_for_each_entry_rcu(n_ptr, &tn->node_list, list) { - u32 i; - - if (!tipc_in_scope(domain, n_ptr->addr)) - continue; - tipc_node_lock(n_ptr); - for (i = 0; i < MAX_BEARERS; i++) { - if (!n_ptr->links[i]) - continue; - link_info.dest = htonl(n_ptr->addr); - link_info.up = htonl(tipc_link_is_up(n_ptr->links[i])); - strcpy(link_info.str, n_ptr->links[i]->name); - tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, - &link_info, sizeof(link_info)); - } - tipc_node_unlock(n_ptr); - } - rcu_read_unlock(); - return buf; -} - /** * tipc_node_get_linkname - get the name of a link * diff --git a/net/tipc/node.h b/net/tipc/node.h index 20ec13f9bede..59dafee61aa0 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h @@ -142,8 +142,6 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr); void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr); int tipc_node_active_links(struct tipc_node *n_ptr); int tipc_node_is_up(struct tipc_node *n_ptr); -struct sk_buff *tipc_node_get_links(struct net *net, const void *req_tlv_area, - int req_tlv_space); struct sk_buff *tipc_node_get_nodes(struct net *net, const void *req_tlv_area, int req_tlv_space); int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 node, -- cgit v1.2.3-70-g09d2 From 37e2d4843f9e2f5aad6bf3be5dad174f2838f375 Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:08 +0100 Subject: tipc: convert legacy nl link prop set to nl compat Convert setting of link proprieties to compat doit calls. Commands converted in this patch: TIPC_CMD_SET_LINK_TOL TIPC_CMD_SET_LINK_PRI TIPC_CMD_SET_LINK_WINDOW Signed-off-by: Richard Alpe Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/config.c | 6 -- net/tipc/link.c | 146 +--------------------------------------------- net/tipc/link.h | 2 - net/tipc/netlink_compat.c | 47 +++++++++++++++ 4 files changed, 48 insertions(+), 153 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/config.c b/net/tipc/config.c index 1b17f5846e86..75a130e493f5 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -226,12 +226,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, case TIPC_CMD_SHOW_STATS: rep_tlv_buf = tipc_show_stats(); break; - case TIPC_CMD_SET_LINK_TOL: - case TIPC_CMD_SET_LINK_PRI: - case TIPC_CMD_SET_LINK_WINDOW: - rep_tlv_buf = tipc_link_cmd_config(net, req_tlv_area, - req_tlv_space, cmd); - break; case TIPC_CMD_SET_NODE_ADDR: rep_tlv_buf = cfg_set_own_addr(net); break; diff --git a/net/tipc/link.c b/net/tipc/link.c index 2622fb99344a..ec136b5cc339 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1958,150 +1958,6 @@ static struct tipc_node *tipc_link_find_owner(struct net *net, return found_node; } -/** - * link_value_is_valid -- validate proposed link tolerance/priority/window - * - * @cmd: value type (TIPC_CMD_SET_LINK_*) - * @new_value: the new value - * - * Returns 1 if value is within range, 0 if not. - */ -static int link_value_is_valid(u16 cmd, u32 new_value) -{ - switch (cmd) { - case TIPC_CMD_SET_LINK_TOL: - return (new_value >= TIPC_MIN_LINK_TOL) && - (new_value <= TIPC_MAX_LINK_TOL); - case TIPC_CMD_SET_LINK_PRI: - return (new_value <= TIPC_MAX_LINK_PRI); - case TIPC_CMD_SET_LINK_WINDOW: - return (new_value >= TIPC_MIN_LINK_WIN) && - (new_value <= TIPC_MAX_LINK_WIN); - } - return 0; -} - -/** - * link_cmd_set_value - change priority/tolerance/window for link/bearer/media - * @net: the applicable net namespace - * @name: ptr to link, bearer, or media name - * @new_value: new value of link, bearer, or media setting - * @cmd: which link, bearer, or media attribute to set (TIPC_CMD_SET_LINK_*) - * - * Caller must hold RTNL lock to ensure link/bearer/media is not deleted. - * - * Returns 0 if value updated and negative value on error. - */ -static int link_cmd_set_value(struct net *net, const char *name, u32 new_value, - u16 cmd) -{ - struct tipc_node *node; - struct tipc_link *l_ptr; - struct tipc_bearer *b_ptr; - struct tipc_media *m_ptr; - int bearer_id; - int res = 0; - - node = tipc_link_find_owner(net, name, &bearer_id); - if (node) { - tipc_node_lock(node); - l_ptr = node->links[bearer_id]; - - if (l_ptr) { - switch (cmd) { - case TIPC_CMD_SET_LINK_TOL: - link_set_supervision_props(l_ptr, new_value); - tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, - new_value, 0, 0); - break; - case TIPC_CMD_SET_LINK_PRI: - l_ptr->priority = new_value; - tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, - 0, new_value, 0); - break; - case TIPC_CMD_SET_LINK_WINDOW: - tipc_link_set_queue_limits(l_ptr, new_value); - break; - default: - res = -EINVAL; - break; - } - } - tipc_node_unlock(node); - return res; - } - - b_ptr = tipc_bearer_find(net, name); - if (b_ptr) { - switch (cmd) { - case TIPC_CMD_SET_LINK_TOL: - b_ptr->tolerance = new_value; - break; - case TIPC_CMD_SET_LINK_PRI: - b_ptr->priority = new_value; - break; - case TIPC_CMD_SET_LINK_WINDOW: - b_ptr->window = new_value; - break; - default: - res = -EINVAL; - break; - } - return res; - } - - m_ptr = tipc_media_find(name); - if (!m_ptr) - return -ENODEV; - switch (cmd) { - case TIPC_CMD_SET_LINK_TOL: - m_ptr->tolerance = new_value; - break; - case TIPC_CMD_SET_LINK_PRI: - m_ptr->priority = new_value; - break; - case TIPC_CMD_SET_LINK_WINDOW: - m_ptr->window = new_value; - break; - default: - res = -EINVAL; - break; - } - return res; -} - -struct sk_buff *tipc_link_cmd_config(struct net *net, const void *req_tlv_area, - int req_tlv_space, u16 cmd) -{ - struct tipc_link_config *args; - u32 new_value; - int res; - - if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_CONFIG)) - return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - - args = (struct tipc_link_config *)TLV_DATA(req_tlv_area); - new_value = ntohl(args->value); - - if (!link_value_is_valid(cmd, new_value)) - return tipc_cfg_reply_error_string( - "cannot change, value invalid"); - - if (!strcmp(args->name, tipc_bclink_name)) { - if ((cmd == TIPC_CMD_SET_LINK_WINDOW) && - (tipc_bclink_set_queue_limits(net, new_value) == 0)) - return tipc_cfg_reply_none(); - return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (cannot change setting on broadcast link)"); - } - - res = link_cmd_set_value(net, args->name, new_value, cmd); - if (res) - return tipc_cfg_reply_error_string("cannot change link setting"); - - return tipc_cfg_reply_none(); -} - /** * link_reset_statistics - reset link statistics * @l_ptr: pointer to link @@ -2216,7 +2072,7 @@ int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info) struct tipc_link *link; struct tipc_node *node; struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; - struct net *net = genl_info_net(info); + struct net *net = sock_net(skb->sk); if (!info->attrs[TIPC_NLA_LINK]) return -EINVAL; diff --git a/net/tipc/link.h b/net/tipc/link.h index 8c8340cf991f..6eb9d606063b 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -215,8 +215,6 @@ void tipc_link_reset_fragments(struct tipc_link *l_ptr); int tipc_link_is_up(struct tipc_link *l_ptr); int tipc_link_is_active(struct tipc_link *l_ptr); void tipc_link_purge_queues(struct tipc_link *l_ptr); -struct sk_buff *tipc_link_cmd_config(struct net *net, const void *req_tlv_area, - int req_tlv_space, u16 cmd); struct sk_buff *tipc_link_cmd_reset_stats(struct net *net, const void *req_tlv_area, int req_tlv_space); diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index bff9403899ed..056532b41e7e 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -569,6 +569,43 @@ static int tipc_nl_compat_link_dump(struct tipc_nl_compat_msg *msg, &link_info, sizeof(link_info)); } +static int tipc_nl_compat_link_set(struct sk_buff *skb, + struct tipc_nl_compat_msg *msg) +{ + struct nlattr *link; + struct nlattr *prop; + struct tipc_link_config *lc; + + lc = (struct tipc_link_config *)TLV_DATA(msg->req); + + link = nla_nest_start(skb, TIPC_NLA_LINK); + if (!link) + return -EMSGSIZE; + + if (nla_put_string(skb, TIPC_NLA_LINK_NAME, lc->name)) + return -EMSGSIZE; + + prop = nla_nest_start(skb, TIPC_NLA_LINK_PROP); + if (!prop) + return -EMSGSIZE; + + if (msg->cmd == TIPC_CMD_SET_LINK_PRI) { + if (nla_put_u32(skb, TIPC_NLA_PROP_PRIO, ntohl(lc->value))) + return -EMSGSIZE; + } else if (msg->cmd == TIPC_CMD_SET_LINK_TOL) { + if (nla_put_u32(skb, TIPC_NLA_PROP_TOL, ntohl(lc->value))) + return -EMSGSIZE; + } else if (msg->cmd == TIPC_CMD_SET_LINK_WINDOW) { + if (nla_put_u32(skb, TIPC_NLA_PROP_WIN, ntohl(lc->value))) + return -EMSGSIZE; + } + + nla_nest_end(skb, prop); + nla_nest_end(skb, link); + + return 0; +} + static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) { struct tipc_nl_compat_cmd_dump dump; @@ -606,6 +643,13 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) dump.dumpit = tipc_nl_link_dump; dump.format = tipc_nl_compat_link_dump; return tipc_nl_compat_dumpit(&dump, msg); + case TIPC_CMD_SET_LINK_TOL: + case TIPC_CMD_SET_LINK_PRI: + case TIPC_CMD_SET_LINK_WINDOW: + msg->req_type = TIPC_TLV_LINK_CONFIG; + doit.doit = tipc_nl_link_set; + doit.transcode = tipc_nl_compat_link_set; + return tipc_nl_compat_doit(&doit, msg); } return -EOPNOTSUPP; @@ -707,6 +751,9 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) case TIPC_CMD_DISABLE_BEARER: case TIPC_CMD_SHOW_LINK_STATS: case TIPC_CMD_GET_LINKS: + case TIPC_CMD_SET_LINK_TOL: + case TIPC_CMD_SET_LINK_PRI: + case TIPC_CMD_SET_LINK_WINDOW: return tipc_nl_compat_recv(skb, info); } -- cgit v1.2.3-70-g09d2 From 1817877b3cd7b4dc73e4a1514d5f48eaa3989ec9 Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:09 +0100 Subject: tipc: convert legacy nl link stat reset to nl compat Convert TIPC_CMD_RESET_LINK_STATS to compat doit. Signed-off-by: Richard Alpe Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/config.c | 4 ---- net/tipc/link.c | 35 +---------------------------------- net/tipc/link.h | 3 --- net/tipc/netlink_compat.c | 26 ++++++++++++++++++++++++++ 4 files changed, 27 insertions(+), 41 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/config.c b/net/tipc/config.c index 75a130e493f5..11c16d191fa2 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -209,10 +209,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, rep_tlv_buf = tipc_node_get_nodes(net, req_tlv_area, req_tlv_space); break; - case TIPC_CMD_RESET_LINK_STATS: - rep_tlv_buf = tipc_link_cmd_reset_stats(net, req_tlv_area, - req_tlv_space); - break; case TIPC_CMD_SHOW_NAME_TABLE: rep_tlv_buf = tipc_nametbl_get(net, req_tlv_area, req_tlv_space); diff --git a/net/tipc/link.c b/net/tipc/link.c index ec136b5cc339..dfe6f4d0b402 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1969,39 +1969,6 @@ static void link_reset_statistics(struct tipc_link *l_ptr) l_ptr->stats.recv_info = l_ptr->next_in_no; } -struct sk_buff *tipc_link_cmd_reset_stats(struct net *net, - const void *req_tlv_area, - int req_tlv_space) -{ - char *link_name; - struct tipc_link *l_ptr; - struct tipc_node *node; - unsigned int bearer_id; - - if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) - return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - - link_name = (char *)TLV_DATA(req_tlv_area); - if (!strcmp(link_name, tipc_bclink_name)) { - if (tipc_bclink_reset_stats(net)) - return tipc_cfg_reply_error_string("link not found"); - return tipc_cfg_reply_none(); - } - node = tipc_link_find_owner(net, link_name, &bearer_id); - if (!node) - return tipc_cfg_reply_error_string("link not found"); - - tipc_node_lock(node); - l_ptr = node->links[bearer_id]; - if (!l_ptr) { - tipc_node_unlock(node); - return tipc_cfg_reply_error_string("link not found"); - } - link_reset_statistics(l_ptr); - tipc_node_unlock(node); - return tipc_cfg_reply_none(); -} - static void link_print(struct tipc_link *l_ptr, const char *str) { struct tipc_net *tn = net_generic(l_ptr->owner->net, tipc_net_id); @@ -2424,7 +2391,7 @@ int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info) struct tipc_link *link; struct tipc_node *node; struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; - struct net *net = genl_info_net(info); + struct net *net = sock_net(skb->sk); if (!info->attrs[TIPC_NLA_LINK]) return -EINVAL; diff --git a/net/tipc/link.h b/net/tipc/link.h index 6eb9d606063b..7aeb52092bf3 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -215,9 +215,6 @@ void tipc_link_reset_fragments(struct tipc_link *l_ptr); int tipc_link_is_up(struct tipc_link *l_ptr); int tipc_link_is_active(struct tipc_link *l_ptr); void tipc_link_purge_queues(struct tipc_link *l_ptr); -struct sk_buff *tipc_link_cmd_reset_stats(struct net *net, - const void *req_tlv_area, - int req_tlv_space); void tipc_link_reset_all(struct tipc_node *node); void tipc_link_reset(struct tipc_link *l_ptr); void tipc_link_reset_list(struct net *net, unsigned int bearer_id); diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 056532b41e7e..02461233b6d8 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -606,6 +606,26 @@ static int tipc_nl_compat_link_set(struct sk_buff *skb, return 0; } +static int tipc_nl_compat_link_reset_stats(struct sk_buff *skb, + struct tipc_nl_compat_msg *msg) +{ + char *name; + struct nlattr *link; + + name = (char *)TLV_DATA(msg->req); + + link = nla_nest_start(skb, TIPC_NLA_LINK); + if (!link) + return -EMSGSIZE; + + if (nla_put_string(skb, TIPC_NLA_LINK_NAME, name)) + return -EMSGSIZE; + + nla_nest_end(skb, link); + + return 0; +} + static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) { struct tipc_nl_compat_cmd_dump dump; @@ -650,6 +670,11 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) doit.doit = tipc_nl_link_set; doit.transcode = tipc_nl_compat_link_set; return tipc_nl_compat_doit(&doit, msg); + case TIPC_CMD_RESET_LINK_STATS: + msg->req_type = TIPC_TLV_LINK_NAME; + doit.doit = tipc_nl_link_reset_stats; + doit.transcode = tipc_nl_compat_link_reset_stats; + return tipc_nl_compat_doit(&doit, msg); } return -EOPNOTSUPP; @@ -754,6 +779,7 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) case TIPC_CMD_SET_LINK_TOL: case TIPC_CMD_SET_LINK_PRI: case TIPC_CMD_SET_LINK_WINDOW: + case TIPC_CMD_RESET_LINK_STATS: return tipc_nl_compat_recv(skb, info); } -- cgit v1.2.3-70-g09d2 From 44a8ae94fd5525aa06a8c71cb52efbc418fb8b7c Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:10 +0100 Subject: tipc: convert legacy nl name table dump to nl compat Add functionality for printing a dump header and convert TIPC_CMD_SHOW_NAME_TABLE to compat dumpit. Signed-off-by: Richard Alpe Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/config.c | 4 - net/tipc/name_table.c | 184 ---------------------------------------------- net/tipc/name_table.h | 2 - net/tipc/netlink_compat.c | 101 +++++++++++++++++++++++++ 4 files changed, 101 insertions(+), 190 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/config.c b/net/tipc/config.c index 11c16d191fa2..7b053fcc4b87 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -209,10 +209,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, rep_tlv_buf = tipc_node_get_nodes(net, req_tlv_area, req_tlv_space); break; - case TIPC_CMD_SHOW_NAME_TABLE: - rep_tlv_buf = tipc_nametbl_get(net, req_tlv_area, - req_tlv_space); - break; case TIPC_CMD_GET_MEDIA_NAMES: rep_tlv_buf = tipc_media_get_names(); break; diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 2251912264a2..c8eaa2afe875 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -773,190 +773,6 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s) spin_unlock_bh(&tn->nametbl_lock); } -/** - * subseq_list - print specified sub-sequence contents into the given buffer - */ -static int subseq_list(struct sub_seq *sseq, char *buf, int len, u32 depth, - u32 index) -{ - char portIdStr[27]; - const char *scope_str[] = {"", " zone", " cluster", " node"}; - struct publication *publ; - struct name_info *info; - int ret; - - ret = tipc_snprintf(buf, len, "%-10u %-10u ", sseq->lower, sseq->upper); - - if (depth == 2) { - ret += tipc_snprintf(buf - ret, len + ret, "\n"); - return ret; - } - - info = sseq->info; - - list_for_each_entry(publ, &info->zone_list, zone_list) { - sprintf(portIdStr, "<%u.%u.%u:%u>", - tipc_zone(publ->node), tipc_cluster(publ->node), - tipc_node(publ->node), publ->ref); - ret += tipc_snprintf(buf + ret, len - ret, "%-26s ", portIdStr); - if (depth > 3) { - ret += tipc_snprintf(buf + ret, len - ret, "%-10u %s", - publ->key, scope_str[publ->scope]); - } - if (!list_is_last(&publ->zone_list, &info->zone_list)) - ret += tipc_snprintf(buf + ret, len - ret, - "\n%33s", " "); - } - - ret += tipc_snprintf(buf + ret, len - ret, "\n"); - return ret; -} - -/** - * nameseq_list - print specified name sequence contents into the given buffer - */ -static int nameseq_list(struct name_seq *seq, char *buf, int len, u32 depth, - u32 type, u32 lowbound, u32 upbound, u32 index) -{ - struct sub_seq *sseq; - char typearea[11]; - int ret = 0; - - if (seq->first_free == 0) - return 0; - - sprintf(typearea, "%-10u", seq->type); - - if (depth == 1) { - ret += tipc_snprintf(buf, len, "%s\n", typearea); - return ret; - } - - for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) { - if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) { - ret += tipc_snprintf(buf + ret, len - ret, "%s ", - typearea); - spin_lock_bh(&seq->lock); - ret += subseq_list(sseq, buf + ret, len - ret, - depth, index); - spin_unlock_bh(&seq->lock); - sprintf(typearea, "%10s", " "); - } - } - return ret; -} - -/** - * nametbl_header - print name table header into the given buffer - */ -static int nametbl_header(char *buf, int len, u32 depth) -{ - const char *header[] = { - "Type ", - "Lower Upper ", - "Port Identity ", - "Publication Scope" - }; - - int i; - int ret = 0; - - if (depth > 4) - depth = 4; - for (i = 0; i < depth; i++) - ret += tipc_snprintf(buf + ret, len - ret, header[i]); - ret += tipc_snprintf(buf + ret, len - ret, "\n"); - return ret; -} - -/** - * nametbl_list - print specified name table contents into the given buffer - */ -static int nametbl_list(struct net *net, char *buf, int len, u32 depth_info, - u32 type, u32 lowbound, u32 upbound) -{ - struct tipc_net *tn = net_generic(net, tipc_net_id); - struct hlist_head *seq_head; - struct name_seq *seq; - int all_types; - int ret = 0; - u32 depth; - u32 i; - - all_types = (depth_info & TIPC_NTQ_ALLTYPES); - depth = (depth_info & ~TIPC_NTQ_ALLTYPES); - - if (depth == 0) - return 0; - - if (all_types) { - /* display all entries in name table to specified depth */ - ret += nametbl_header(buf, len, depth); - lowbound = 0; - upbound = ~0; - for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { - seq_head = &tn->nametbl->seq_hlist[i]; - hlist_for_each_entry_rcu(seq, seq_head, ns_list) { - ret += nameseq_list(seq, buf + ret, len - ret, - depth, seq->type, - lowbound, upbound, i); - } - } - } else { - /* display only the sequence that matches the specified type */ - if (upbound < lowbound) { - ret += tipc_snprintf(buf + ret, len - ret, - "invalid name sequence specified\n"); - return ret; - } - ret += nametbl_header(buf + ret, len - ret, depth); - i = hash(type); - seq_head = &tn->nametbl->seq_hlist[i]; - hlist_for_each_entry_rcu(seq, seq_head, ns_list) { - if (seq->type == type) { - ret += nameseq_list(seq, buf + ret, len - ret, - depth, type, - lowbound, upbound, i); - break; - } - } - } - return ret; -} - -struct sk_buff *tipc_nametbl_get(struct net *net, const void *req_tlv_area, - int req_tlv_space) -{ - struct sk_buff *buf; - struct tipc_name_table_query *argv; - struct tlv_desc *rep_tlv; - char *pb; - int pb_len; - int str_len; - - if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY)) - return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - - buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN)); - if (!buf) - return NULL; - - rep_tlv = (struct tlv_desc *)buf->data; - pb = TLV_DATA(rep_tlv); - pb_len = ULTRA_STRING_MAX_LEN; - argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area); - rcu_read_lock(); - str_len = nametbl_list(net, pb, pb_len, ntohl(argv->depth), - ntohl(argv->type), - ntohl(argv->lowbound), ntohl(argv->upbound)); - rcu_read_unlock(); - str_len += 1; /* for "\0" */ - skb_put(buf, TLV_SPACE(str_len)); - TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); - - return buf; -} - int tipc_nametbl_init(struct net *net) { struct tipc_net *tn = net_generic(net, tipc_net_id); diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index 0304ddc6b101..1524a73830f7 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h @@ -97,8 +97,6 @@ struct name_table { int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb); -struct sk_buff *tipc_nametbl_get(struct net *net, const void *req_tlv_area, - int req_tlv_space); u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *node); int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper, u32 limit, struct tipc_plist *dports); diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 02461233b6d8..40c24ea31231 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -35,6 +35,7 @@ #include "config.h" #include "bearer.h" #include "link.h" +#include "name_table.h" #include #include @@ -58,6 +59,7 @@ struct tipc_nl_compat_msg { }; struct tipc_nl_compat_cmd_dump { + int (*header)(struct tipc_nl_compat_msg *); int (*dumpit)(struct sk_buff *, struct netlink_callback *); int (*format)(struct tipc_nl_compat_msg *msg, struct nlattr **attrs); }; @@ -246,6 +248,9 @@ static int tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, if (msg->rep_type) tipc_tlv_init(msg->rep, msg->rep_type); + if (cmd->header) + (*cmd->header)(msg); + arg = nlmsg_new(0, GFP_KERNEL); if (!arg) { kfree_skb(msg->rep); @@ -626,6 +631,93 @@ static int tipc_nl_compat_link_reset_stats(struct sk_buff *skb, return 0; } +static int tipc_nl_compat_name_table_dump_header(struct tipc_nl_compat_msg *msg) +{ + int i; + u32 depth; + struct tipc_name_table_query *ntq; + static const char * const header[] = { + "Type ", + "Lower Upper ", + "Port Identity ", + "Publication Scope" + }; + + ntq = (struct tipc_name_table_query *)TLV_DATA(msg->req); + + depth = ntohl(ntq->depth); + + if (depth > 4) + depth = 4; + for (i = 0; i < depth; i++) + tipc_tlv_sprintf(msg->rep, header[i]); + tipc_tlv_sprintf(msg->rep, "\n"); + + return 0; +} + +static int tipc_nl_compat_name_table_dump(struct tipc_nl_compat_msg *msg, + struct nlattr **attrs) +{ + char port_str[27]; + struct tipc_name_table_query *ntq; + struct nlattr *nt[TIPC_NLA_NAME_TABLE_MAX + 1]; + struct nlattr *publ[TIPC_NLA_PUBL_MAX + 1]; + u32 node, depth, type, lowbound, upbound; + static const char * const scope_str[] = {"", " zone", " cluster", + " node"}; + + nla_parse_nested(nt, TIPC_NLA_NAME_TABLE_MAX, + attrs[TIPC_NLA_NAME_TABLE], NULL); + + nla_parse_nested(publ, TIPC_NLA_PUBL_MAX, nt[TIPC_NLA_NAME_TABLE_PUBL], + NULL); + + ntq = (struct tipc_name_table_query *)TLV_DATA(msg->req); + + depth = ntohl(ntq->depth); + type = ntohl(ntq->type); + lowbound = ntohl(ntq->lowbound); + upbound = ntohl(ntq->upbound); + + if (!(depth & TIPC_NTQ_ALLTYPES) && + (type != nla_get_u32(publ[TIPC_NLA_PUBL_TYPE]))) + return 0; + if (lowbound && (lowbound > nla_get_u32(publ[TIPC_NLA_PUBL_UPPER]))) + return 0; + if (upbound && (upbound < nla_get_u32(publ[TIPC_NLA_PUBL_LOWER]))) + return 0; + + tipc_tlv_sprintf(msg->rep, "%-10u ", + nla_get_u32(publ[TIPC_NLA_PUBL_TYPE])); + + if (depth == 1) + goto out; + + tipc_tlv_sprintf(msg->rep, "%-10u %-10u ", + nla_get_u32(publ[TIPC_NLA_PUBL_LOWER]), + nla_get_u32(publ[TIPC_NLA_PUBL_UPPER])); + + if (depth == 2) + goto out; + + node = nla_get_u32(publ[TIPC_NLA_PUBL_NODE]); + sprintf(port_str, "<%u.%u.%u:%u>", tipc_zone(node), tipc_cluster(node), + tipc_node(node), nla_get_u32(publ[TIPC_NLA_PUBL_REF])); + tipc_tlv_sprintf(msg->rep, "%-26s ", port_str); + + if (depth == 3) + goto out; + + tipc_tlv_sprintf(msg->rep, "%-10u %s", + nla_get_u32(publ[TIPC_NLA_PUBL_REF]), + scope_str[nla_get_u32(publ[TIPC_NLA_PUBL_SCOPE])]); +out: + tipc_tlv_sprintf(msg->rep, "\n"); + + return 0; +} + static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) { struct tipc_nl_compat_cmd_dump dump; @@ -675,6 +767,14 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) doit.doit = tipc_nl_link_reset_stats; doit.transcode = tipc_nl_compat_link_reset_stats; return tipc_nl_compat_doit(&doit, msg); + case TIPC_CMD_SHOW_NAME_TABLE: + msg->req_type = TIPC_TLV_NAME_TBL_QUERY; + msg->rep_size = ULTRA_STRING_MAX_LEN; + msg->rep_type = TIPC_TLV_ULTRA_STRING; + dump.header = tipc_nl_compat_name_table_dump_header; + dump.dumpit = tipc_nl_name_table_dump; + dump.format = tipc_nl_compat_name_table_dump; + return tipc_nl_compat_dumpit(&dump, msg); } return -EOPNOTSUPP; @@ -780,6 +880,7 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) case TIPC_CMD_SET_LINK_PRI: case TIPC_CMD_SET_LINK_WINDOW: case TIPC_CMD_RESET_LINK_STATS: + case TIPC_CMD_SHOW_NAME_TABLE: return tipc_nl_compat_recv(skb, info); } -- cgit v1.2.3-70-g09d2 From 487d2a3a1326d339ce273ffbcd03247f2b7b052e Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:11 +0100 Subject: tipc: convert legacy nl socket dump to nl compat Convert socket (port) listing to compat dumpit call. If a socket (port) has publications a second dumpit call is issued to collect them and format then into the legacy buffer before continuing to process the sockets (ports). Command converted in this patch: TIPC_CMD_SHOW_PORTS Signed-off-by: Richard Alpe Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/config.c | 3 -- net/tipc/netlink_compat.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++ net/tipc/socket.c | 85 ----------------------------------- net/tipc/socket.h | 1 - 4 files changed, 111 insertions(+), 89 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/config.c b/net/tipc/config.c index 7b053fcc4b87..6e4c215879c8 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -212,9 +212,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, case TIPC_CMD_GET_MEDIA_NAMES: rep_tlv_buf = tipc_media_get_names(); break; - case TIPC_CMD_SHOW_PORTS: - rep_tlv_buf = tipc_sk_socks_show(net); - break; case TIPC_CMD_SHOW_STATS: rep_tlv_buf = tipc_show_stats(); break; diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 40c24ea31231..48e15a4a36d8 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -36,6 +36,7 @@ #include "bearer.h" #include "link.h" #include "name_table.h" +#include "socket.h" #include #include @@ -718,6 +719,109 @@ out: return 0; } +static int __tipc_nl_compat_publ_dump(struct tipc_nl_compat_msg *msg, + struct nlattr **attrs) +{ + u32 type, lower, upper; + struct nlattr *publ[TIPC_NLA_PUBL_MAX + 1]; + + nla_parse_nested(publ, TIPC_NLA_PUBL_MAX, attrs[TIPC_NLA_PUBL], NULL); + + type = nla_get_u32(publ[TIPC_NLA_PUBL_TYPE]); + lower = nla_get_u32(publ[TIPC_NLA_PUBL_LOWER]); + upper = nla_get_u32(publ[TIPC_NLA_PUBL_UPPER]); + + if (lower == upper) + tipc_tlv_sprintf(msg->rep, " {%u,%u}", type, lower); + else + tipc_tlv_sprintf(msg->rep, " {%u,%u,%u}", type, lower, upper); + + return 0; +} + +static int tipc_nl_compat_publ_dump(struct tipc_nl_compat_msg *msg, u32 sock) +{ + int err; + void *hdr; + struct nlattr *nest; + struct sk_buff *args; + struct tipc_nl_compat_cmd_dump dump; + + args = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!args) + return -ENOMEM; + + hdr = genlmsg_put(args, 0, 0, &tipc_genl_family, NLM_F_MULTI, + TIPC_NL_PUBL_GET); + + nest = nla_nest_start(args, TIPC_NLA_SOCK); + if (!nest) { + kfree_skb(args); + return -EMSGSIZE; + } + + if (nla_put_u32(args, TIPC_NLA_SOCK_REF, sock)) { + kfree_skb(args); + return -EMSGSIZE; + } + + nla_nest_end(args, nest); + genlmsg_end(args, hdr); + + dump.dumpit = tipc_nl_publ_dump; + dump.format = __tipc_nl_compat_publ_dump; + + err = __tipc_nl_compat_dumpit(&dump, msg, args); + + kfree_skb(args); + + return err; +} + +static int tipc_nl_compat_sk_dump(struct tipc_nl_compat_msg *msg, + struct nlattr **attrs) +{ + int err; + u32 sock_ref; + struct nlattr *sock[TIPC_NLA_SOCK_MAX + 1]; + + nla_parse_nested(sock, TIPC_NLA_SOCK_MAX, attrs[TIPC_NLA_SOCK], NULL); + + sock_ref = nla_get_u32(sock[TIPC_NLA_SOCK_REF]); + tipc_tlv_sprintf(msg->rep, "%u:", sock_ref); + + if (sock[TIPC_NLA_SOCK_CON]) { + u32 node; + struct nlattr *con[TIPC_NLA_CON_MAX + 1]; + + nla_parse_nested(con, TIPC_NLA_CON_MAX, sock[TIPC_NLA_SOCK_CON], + NULL); + + node = nla_get_u32(con[TIPC_NLA_CON_NODE]); + tipc_tlv_sprintf(msg->rep, " connected to <%u.%u.%u:%u>", + tipc_zone(node), + tipc_cluster(node), + tipc_node(node), + nla_get_u32(con[TIPC_NLA_CON_SOCK])); + + if (con[TIPC_NLA_CON_FLAG]) + tipc_tlv_sprintf(msg->rep, " via {%u,%u}\n", + nla_get_u32(con[TIPC_NLA_CON_TYPE]), + nla_get_u32(con[TIPC_NLA_CON_INST])); + else + tipc_tlv_sprintf(msg->rep, "\n"); + } else if (sock[TIPC_NLA_SOCK_HAS_PUBL]) { + tipc_tlv_sprintf(msg->rep, " bound to"); + + err = tipc_nl_compat_publ_dump(msg, sock_ref); + if (err) + return err; + } + tipc_tlv_sprintf(msg->rep, "\n"); + + return 0; +} + static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) { struct tipc_nl_compat_cmd_dump dump; @@ -775,6 +879,12 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) dump.dumpit = tipc_nl_name_table_dump; dump.format = tipc_nl_compat_name_table_dump; return tipc_nl_compat_dumpit(&dump, msg); + case TIPC_CMD_SHOW_PORTS: + msg->rep_size = ULTRA_STRING_MAX_LEN; + msg->rep_type = TIPC_TLV_ULTRA_STRING; + dump.dumpit = tipc_nl_sk_dump; + dump.format = tipc_nl_compat_sk_dump; + return tipc_nl_compat_dumpit(&dump, msg); } return -EOPNOTSUPP; @@ -881,6 +991,7 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) case TIPC_CMD_SET_LINK_WINDOW: case TIPC_CMD_RESET_LINK_STATS: case TIPC_CMD_SHOW_NAME_TABLE: + case TIPC_CMD_SHOW_PORTS: return tipc_nl_compat_recv(skb, info); } diff --git a/net/tipc/socket.c b/net/tipc/socket.c index d76c171f7b7e..e77d738bb771 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -2281,91 +2281,6 @@ static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope, return rc; } -static int tipc_sk_show(struct tipc_sock *tsk, char *buf, - int len, int full_id) -{ - struct net *net = sock_net(&tsk->sk); - struct tipc_net *tn = net_generic(net, tipc_net_id); - struct publication *publ; - int ret; - - if (full_id) - ret = tipc_snprintf(buf, len, "<%u.%u.%u:%u>:", - tipc_zone(tn->own_addr), - tipc_cluster(tn->own_addr), - tipc_node(tn->own_addr), tsk->portid); - else - ret = tipc_snprintf(buf, len, "%-10u:", tsk->portid); - - if (tsk->connected) { - u32 dport = tsk_peer_port(tsk); - u32 destnode = tsk_peer_node(tsk); - - ret += tipc_snprintf(buf + ret, len - ret, - " connected to <%u.%u.%u:%u>", - tipc_zone(destnode), - tipc_cluster(destnode), - tipc_node(destnode), dport); - if (tsk->conn_type != 0) - ret += tipc_snprintf(buf + ret, len - ret, - " via {%u,%u}", tsk->conn_type, - tsk->conn_instance); - } else if (tsk->published) { - ret += tipc_snprintf(buf + ret, len - ret, " bound to"); - list_for_each_entry(publ, &tsk->publications, pport_list) { - if (publ->lower == publ->upper) - ret += tipc_snprintf(buf + ret, len - ret, - " {%u,%u}", publ->type, - publ->lower); - else - ret += tipc_snprintf(buf + ret, len - ret, - " {%u,%u,%u}", publ->type, - publ->lower, publ->upper); - } - } - ret += tipc_snprintf(buf + ret, len - ret, "\n"); - return ret; -} - -struct sk_buff *tipc_sk_socks_show(struct net *net) -{ - struct tipc_net *tn = net_generic(net, tipc_net_id); - const struct bucket_table *tbl; - struct rhash_head *pos; - struct sk_buff *buf; - struct tlv_desc *rep_tlv; - char *pb; - int pb_len; - struct tipc_sock *tsk; - int str_len = 0; - int i; - - buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN)); - if (!buf) - return NULL; - rep_tlv = (struct tlv_desc *)buf->data; - pb = TLV_DATA(rep_tlv); - pb_len = ULTRA_STRING_MAX_LEN; - - rcu_read_lock(); - tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht); - for (i = 0; i < tbl->size; i++) { - rht_for_each_entry_rcu(tsk, pos, tbl, i, node) { - spin_lock_bh(&tsk->sk.sk_lock.slock); - str_len += tipc_sk_show(tsk, pb + str_len, - pb_len - str_len, 0); - spin_unlock_bh(&tsk->sk.sk_lock.slock); - } - } - rcu_read_unlock(); - - str_len += 1; /* for "\0" */ - skb_put(buf, TLV_SPACE(str_len)); - TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); - - return buf; -} - /* tipc_sk_reinit: set non-zero address in all existing sockets * when we go from standalone to network mode. */ diff --git a/net/tipc/socket.h b/net/tipc/socket.h index 8be0da7df8fc..238f1b7bd9bd 100644 --- a/net/tipc/socket.h +++ b/net/tipc/socket.h @@ -49,7 +49,6 @@ void tipc_sock_release_local(struct socket *sock); int tipc_sock_accept_local(struct socket *sock, struct socket **newsock, int flags); int tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq); -struct sk_buff *tipc_sk_socks_show(struct net *net); void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, struct sk_buff_head *inputq); void tipc_sk_reinit(struct net *net); -- cgit v1.2.3-70-g09d2 From 5bfc335a637ad4aecededb67b0075aae72a6dbb3 Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:12 +0100 Subject: tipc: convert legacy nl media dump to nl compat Convert TIPC_CMD_GET_MEDIA_NAMES to compat dumpit. Signed-off-by: Richard Alpe Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/bearer.c | 20 -------------------- net/tipc/bearer.h | 1 - net/tipc/config.c | 3 --- net/tipc/netlink_compat.c | 19 +++++++++++++++++++ 4 files changed, 19 insertions(+), 24 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index de1c800ef806..c7e3b5d3baa9 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -123,26 +123,6 @@ void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a) } } -/** - * tipc_media_get_names - record names of registered media in buffer - */ -struct sk_buff *tipc_media_get_names(void) -{ - struct sk_buff *buf; - int i; - - buf = tipc_cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME)); - if (!buf) - return NULL; - - for (i = 0; media_info_array[i] != NULL; i++) { - tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, - media_info_array[i]->name, - strlen(media_info_array[i]->name) + 1); - } - return buf; -} - /** * bearer_name_validate - validate & (optionally) deconstruct bearer name * @name: ptr to bearer name string diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 06f25d144871..6b17795ff8bc 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -196,7 +196,6 @@ int tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info); int tipc_media_set_priority(const char *name, u32 new_value); int tipc_media_set_window(const char *name, u32 new_value); void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a); -struct sk_buff *tipc_media_get_names(void); int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b); void tipc_disable_l2_media(struct tipc_bearer *b); int tipc_l2_send_msg(struct net *net, struct sk_buff *buf, diff --git a/net/tipc/config.c b/net/tipc/config.c index 6e4c215879c8..df410823e889 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -209,9 +209,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, rep_tlv_buf = tipc_node_get_nodes(net, req_tlv_area, req_tlv_space); break; - case TIPC_CMD_GET_MEDIA_NAMES: - rep_tlv_buf = tipc_media_get_names(); - break; case TIPC_CMD_SHOW_STATS: rep_tlv_buf = tipc_show_stats(); break; diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 48e15a4a36d8..d23075efaa76 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -822,6 +822,19 @@ static int tipc_nl_compat_sk_dump(struct tipc_nl_compat_msg *msg, return 0; } +static int tipc_nl_compat_media_dump(struct tipc_nl_compat_msg *msg, + struct nlattr **attrs) +{ + struct nlattr *media[TIPC_NLA_MEDIA_MAX + 1]; + + nla_parse_nested(media, TIPC_NLA_MEDIA_MAX, attrs[TIPC_NLA_MEDIA], + NULL); + + return tipc_add_tlv(msg->rep, TIPC_TLV_MEDIA_NAME, + nla_data(media[TIPC_NLA_MEDIA_NAME]), + nla_len(media[TIPC_NLA_MEDIA_NAME])); +} + static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) { struct tipc_nl_compat_cmd_dump dump; @@ -885,6 +898,11 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) dump.dumpit = tipc_nl_sk_dump; dump.format = tipc_nl_compat_sk_dump; return tipc_nl_compat_dumpit(&dump, msg); + case TIPC_CMD_GET_MEDIA_NAMES: + msg->rep_size = MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME); + dump.dumpit = tipc_nl_media_dump; + dump.format = tipc_nl_compat_media_dump; + return tipc_nl_compat_dumpit(&dump, msg); } return -EOPNOTSUPP; @@ -992,6 +1010,7 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) case TIPC_CMD_RESET_LINK_STATS: case TIPC_CMD_SHOW_NAME_TABLE: case TIPC_CMD_SHOW_PORTS: + case TIPC_CMD_GET_MEDIA_NAMES: return tipc_nl_compat_recv(skb, info); } -- cgit v1.2.3-70-g09d2 From 4b28cb581dd0df8d8ff19151f39683f641e576ba Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:13 +0100 Subject: tipc: convert legacy nl node dump to nl compat Convert TIPC_CMD_GET_NODES to compat dumpit and remove global node counter solely used by the legacy API. Signed-off-by: Richard Alpe Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/config.c | 4 ---- net/tipc/netlink_compat.c | 22 +++++++++++++++++++ net/tipc/node.c | 54 ----------------------------------------------- net/tipc/node.h | 2 -- 4 files changed, 22 insertions(+), 60 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/config.c b/net/tipc/config.c index df410823e889..74babd75c07d 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -205,10 +205,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, case TIPC_CMD_NOOP: rep_tlv_buf = tipc_cfg_reply_none(); break; - case TIPC_CMD_GET_NODES: - rep_tlv_buf = tipc_node_get_nodes(net, req_tlv_area, - req_tlv_space); - break; case TIPC_CMD_SHOW_STATS: rep_tlv_buf = tipc_show_stats(); break; diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index d23075efaa76..0dc448e77e13 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -37,6 +37,7 @@ #include "link.h" #include "name_table.h" #include "socket.h" +#include "node.h" #include #include @@ -835,6 +836,21 @@ static int tipc_nl_compat_media_dump(struct tipc_nl_compat_msg *msg, nla_len(media[TIPC_NLA_MEDIA_NAME])); } +static int tipc_nl_compat_node_dump(struct tipc_nl_compat_msg *msg, + struct nlattr **attrs) +{ + struct tipc_node_info node_info; + struct nlattr *node[TIPC_NLA_NODE_MAX + 1]; + + nla_parse_nested(node, TIPC_NLA_NODE_MAX, attrs[TIPC_NLA_NODE], NULL); + + node_info.addr = htonl(nla_get_u32(node[TIPC_NLA_NODE_ADDR])); + node_info.up = htonl(nla_get_flag(node[TIPC_NLA_NODE_UP])); + + return tipc_add_tlv(msg->rep, TIPC_TLV_NODE_INFO, &node_info, + sizeof(node_info)); +} + static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) { struct tipc_nl_compat_cmd_dump dump; @@ -903,6 +919,11 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) dump.dumpit = tipc_nl_media_dump; dump.format = tipc_nl_compat_media_dump; return tipc_nl_compat_dumpit(&dump, msg); + case TIPC_CMD_GET_NODES: + msg->rep_size = ULTRA_STRING_MAX_LEN; + dump.dumpit = tipc_nl_node_dump; + dump.format = tipc_nl_compat_node_dump; + return tipc_nl_compat_dumpit(&dump, msg); } return -EOPNOTSUPP; @@ -1011,6 +1032,7 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) case TIPC_CMD_SHOW_NAME_TABLE: case TIPC_CMD_SHOW_PORTS: case TIPC_CMD_GET_MEDIA_NAMES: + case TIPC_CMD_GET_NODES: return tipc_nl_compat_recv(skb, info); } diff --git a/net/tipc/node.c b/net/tipc/node.c index 46b87f77d342..ddaa2bbaa35d 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -120,7 +120,6 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr) list_add_tail_rcu(&n_ptr->list, &temp_node->list); n_ptr->action_flags = TIPC_WAIT_PEER_LINKS_DOWN; n_ptr->signature = INVALID_NODE_SIG; - tn->num_nodes++; exit: spin_unlock_bh(&tn->node_list_lock); return n_ptr; @@ -131,8 +130,6 @@ static void tipc_node_delete(struct tipc_net *tn, struct tipc_node *n_ptr) list_del_rcu(&n_ptr->list); hlist_del_rcu(&n_ptr->hash); kfree_rcu(n_ptr, rcu); - - tn->num_nodes--; } void tipc_node_stop(struct net *net) @@ -407,57 +404,6 @@ static void node_lost_contact(struct tipc_node *n_ptr) } } -struct sk_buff *tipc_node_get_nodes(struct net *net, const void *req_tlv_area, - int req_tlv_space) -{ - struct tipc_net *tn = net_generic(net, tipc_net_id); - u32 domain; - struct sk_buff *buf; - struct tipc_node *n_ptr; - struct tipc_node_info node_info; - u32 payload_size; - - if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) - return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - - domain = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); - if (!tipc_addr_domain_valid(domain)) - return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (network address)"); - - spin_lock_bh(&tn->node_list_lock); - if (!tn->num_nodes) { - spin_unlock_bh(&tn->node_list_lock); - return tipc_cfg_reply_none(); - } - - /* For now, get space for all other nodes */ - payload_size = TLV_SPACE(sizeof(node_info)) * tn->num_nodes; - if (payload_size > 32768u) { - spin_unlock_bh(&tn->node_list_lock); - return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (too many nodes)"); - } - spin_unlock_bh(&tn->node_list_lock); - - buf = tipc_cfg_reply_alloc(payload_size); - if (!buf) - return NULL; - - /* Add TLVs for all nodes in scope */ - rcu_read_lock(); - list_for_each_entry_rcu(n_ptr, &tn->node_list, list) { - if (!tipc_in_scope(domain, n_ptr->addr)) - continue; - node_info.addr = htonl(n_ptr->addr); - node_info.up = htonl(tipc_node_is_up(n_ptr)); - tipc_cfg_append_tlv(buf, TIPC_TLV_NODE_INFO, - &node_info, sizeof(node_info)); - } - rcu_read_unlock(); - return buf; -} - /** * tipc_node_get_linkname - get the name of a link * diff --git a/net/tipc/node.h b/net/tipc/node.h index 59dafee61aa0..3d18c66b7f78 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h @@ -142,8 +142,6 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr); void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr); int tipc_node_active_links(struct tipc_node *n_ptr); int tipc_node_is_up(struct tipc_node *n_ptr); -struct sk_buff *tipc_node_get_nodes(struct net *net, const void *req_tlv_area, - int req_tlv_space); int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 node, char *linkname, size_t len); void tipc_node_unlock(struct tipc_node *node); -- cgit v1.2.3-70-g09d2 From d7cc75d3cb6beac88a2bd041a7700154b73a989d Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:14 +0100 Subject: tipc: convert legacy nl node addr set to nl compat Convert TIPC_CMD_SET_NODE_ADDR to compat doit. Signed-off-by: Richard Alpe Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/config.c | 26 -------------------------- net/tipc/net.c | 2 +- net/tipc/netlink_compat.c | 26 ++++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 27 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/config.c b/net/tipc/config.c index 74babd75c07d..2a2d05be8a27 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -134,29 +134,6 @@ static struct sk_buff *tipc_show_stats(void) return buf; } -static struct sk_buff *cfg_set_own_addr(struct net *net) -{ - struct tipc_net *tn = net_generic(net, tipc_net_id); - u32 addr; - - if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) - return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - - addr = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); - if (addr == tn->own_addr) - return tipc_cfg_reply_none(); - if (!tipc_addr_node_valid(addr)) - return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (node address)"); - if (tn->own_addr) - return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (cannot change node address once assigned)"); - if (!tipc_net_start(net, addr)) - return tipc_cfg_reply_none(); - - return tipc_cfg_reply_error_string("cannot change to network mode"); -} - static struct sk_buff *cfg_set_netid(struct net *net) { struct tipc_net *tn = net_generic(net, tipc_net_id); @@ -208,9 +185,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, case TIPC_CMD_SHOW_STATS: rep_tlv_buf = tipc_show_stats(); break; - case TIPC_CMD_SET_NODE_ADDR: - rep_tlv_buf = cfg_set_own_addr(net); - break; case TIPC_CMD_SET_NETID: rep_tlv_buf = cfg_set_netid(net); break; diff --git a/net/tipc/net.c b/net/tipc/net.c index 8b0fb0966628..e4028f927c8a 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -208,7 +208,7 @@ out: int tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info) { - struct net *net = genl_info_net(info); + struct net *net = sock_net(skb->sk); struct tipc_net *tn = net_generic(net, tipc_net_id); struct nlattr *attrs[TIPC_NLA_NET_MAX + 1]; int err; diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 0dc448e77e13..aa0e3256ae93 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -851,6 +851,26 @@ static int tipc_nl_compat_node_dump(struct tipc_nl_compat_msg *msg, sizeof(node_info)); } +static int tipc_nl_compat_net_set(struct sk_buff *skb, + struct tipc_nl_compat_msg *msg) +{ + u32 val; + struct nlattr *net; + + val = ntohl(*(__be32 *)TLV_DATA(msg->req)); + + net = nla_nest_start(skb, TIPC_NLA_NET); + if (!net) + return -EMSGSIZE; + + if (nla_put_u32(skb, TIPC_NLA_NET_ADDR, val)) + return -EMSGSIZE; + + nla_nest_end(skb, net); + + return 0; +} + static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) { struct tipc_nl_compat_cmd_dump dump; @@ -924,6 +944,11 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) dump.dumpit = tipc_nl_node_dump; dump.format = tipc_nl_compat_node_dump; return tipc_nl_compat_dumpit(&dump, msg); + case TIPC_CMD_SET_NODE_ADDR: + msg->req_type = TIPC_TLV_NET_ADDR; + doit.doit = tipc_nl_net_set; + doit.transcode = tipc_nl_compat_net_set; + return tipc_nl_compat_doit(&doit, msg); } return -EOPNOTSUPP; @@ -1033,6 +1058,7 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) case TIPC_CMD_SHOW_PORTS: case TIPC_CMD_GET_MEDIA_NAMES: case TIPC_CMD_GET_NODES: + case TIPC_CMD_SET_NODE_ADDR: return tipc_nl_compat_recv(skb, info); } -- cgit v1.2.3-70-g09d2 From 964f9501c1910c0835eee3cf870ba5aa44db1241 Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:15 +0100 Subject: tipc: convert legacy nl net id set to nl compat Convert TIPC_CMD_SET_NETID to compat doit. Signed-off-by: Richard Alpe Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/config.c | 23 ----------------------- net/tipc/netlink_compat.c | 17 ++++++++++++++--- 2 files changed, 14 insertions(+), 26 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/config.c b/net/tipc/config.c index 2a2d05be8a27..080cc92eedca 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -134,26 +134,6 @@ static struct sk_buff *tipc_show_stats(void) return buf; } -static struct sk_buff *cfg_set_netid(struct net *net) -{ - struct tipc_net *tn = net_generic(net, tipc_net_id); - u32 value; - - if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); - if (value == tn->net_id) - return tipc_cfg_reply_none(); - if (value < 1 || value > 9999) - return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE - " (network id must be 1-9999)"); - if (tn->own_addr) - return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (cannot change network id once TIPC has joined a network)"); - tn->net_id = value; - return tipc_cfg_reply_none(); -} - struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, const void *request_area, int request_space, int reply_headroom) @@ -185,9 +165,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, case TIPC_CMD_SHOW_STATS: rep_tlv_buf = tipc_show_stats(); break; - case TIPC_CMD_SET_NETID: - rep_tlv_buf = cfg_set_netid(net); - break; case TIPC_CMD_GET_NETID: rep_tlv_buf = tipc_cfg_reply_unsigned(tn->net_id); break; diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index aa0e3256ae93..c355476a6e7c 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -38,6 +38,7 @@ #include "name_table.h" #include "socket.h" #include "node.h" +#include "net.h" #include #include @@ -863,9 +864,13 @@ static int tipc_nl_compat_net_set(struct sk_buff *skb, if (!net) return -EMSGSIZE; - if (nla_put_u32(skb, TIPC_NLA_NET_ADDR, val)) - return -EMSGSIZE; - + if (msg->cmd == TIPC_CMD_SET_NODE_ADDR) { + if (nla_put_u32(skb, TIPC_NLA_NET_ADDR, val)) + return -EMSGSIZE; + } else if (msg->cmd == TIPC_CMD_SET_NETID) { + if (nla_put_u32(skb, TIPC_NLA_NET_ID, val)) + return -EMSGSIZE; + } nla_nest_end(skb, net); return 0; @@ -949,6 +954,11 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) doit.doit = tipc_nl_net_set; doit.transcode = tipc_nl_compat_net_set; return tipc_nl_compat_doit(&doit, msg); + case TIPC_CMD_SET_NETID: + msg->req_type = TIPC_TLV_UNSIGNED; + doit.doit = tipc_nl_net_set; + doit.transcode = tipc_nl_compat_net_set; + return tipc_nl_compat_doit(&doit, msg); } return -EOPNOTSUPP; @@ -1059,6 +1069,7 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) case TIPC_CMD_GET_MEDIA_NAMES: case TIPC_CMD_GET_NODES: case TIPC_CMD_SET_NODE_ADDR: + case TIPC_CMD_SET_NETID: return tipc_nl_compat_recv(skb, info); } -- cgit v1.2.3-70-g09d2 From 3c26181c5b1b0b49e147bac8a8d012234f813a5e Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:16 +0100 Subject: tipc: convert legacy nl net id get to nl compat Convert TIPC_CMD_GET_NETID to compat dumpit. Signed-off-by: Richard Alpe Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/config.c | 23 ----------------------- net/tipc/netlink_compat.c | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 23 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/config.c b/net/tipc/config.c index 080cc92eedca..019f46c0690c 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -72,25 +72,6 @@ int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, return 1; } -static struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value) -{ - struct sk_buff *buf; - __be32 value_net; - - buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(value))); - if (buf) { - value_net = htonl(value); - tipc_cfg_append_tlv(buf, tlv_type, &value_net, - sizeof(value_net)); - } - return buf; -} - -static struct sk_buff *tipc_cfg_reply_unsigned(u32 value) -{ - return tipc_cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value); -} - struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string) { struct sk_buff *buf; @@ -139,7 +120,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, int reply_headroom) { struct sk_buff *rep_tlv_buf; - struct tipc_net *tn = net_generic(net, tipc_net_id); rtnl_lock(); @@ -165,9 +145,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, case TIPC_CMD_SHOW_STATS: rep_tlv_buf = tipc_show_stats(); break; - case TIPC_CMD_GET_NETID: - rep_tlv_buf = tipc_cfg_reply_unsigned(tn->net_id); - break; case TIPC_CMD_NOT_NET_ADMIN: rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN); diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index c355476a6e7c..415909054ec0 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -876,6 +876,18 @@ static int tipc_nl_compat_net_set(struct sk_buff *skb, return 0; } +static int tipc_nl_compat_net_dump(struct tipc_nl_compat_msg *msg, + struct nlattr **attrs) +{ + __be32 id; + struct nlattr *net[TIPC_NLA_NET_MAX + 1]; + + nla_parse_nested(net, TIPC_NLA_NET_MAX, attrs[TIPC_NLA_NET], NULL); + id = htonl(nla_get_u32(net[TIPC_NLA_NET_ID])); + + return tipc_add_tlv(msg->rep, TIPC_TLV_UNSIGNED, &id, sizeof(id)); +} + static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) { struct tipc_nl_compat_cmd_dump dump; @@ -959,6 +971,11 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) doit.doit = tipc_nl_net_set; doit.transcode = tipc_nl_compat_net_set; return tipc_nl_compat_doit(&doit, msg); + case TIPC_CMD_GET_NETID: + msg->rep_size = sizeof(u32); + dump.dumpit = tipc_nl_net_dump; + dump.format = tipc_nl_compat_net_dump; + return tipc_nl_compat_dumpit(&dump, msg); } return -EOPNOTSUPP; @@ -1070,6 +1087,7 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) case TIPC_CMD_GET_NODES: case TIPC_CMD_SET_NODE_ADDR: case TIPC_CMD_SET_NETID: + case TIPC_CMD_GET_NETID: return tipc_nl_compat_recv(skb, info); } -- cgit v1.2.3-70-g09d2 From 5a81a6377b6083fccffdfb7a21ec080b8d58475b Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:17 +0100 Subject: tipc: convert legacy nl stats show to nl compat Convert TIPC_CMD_SHOW_STATS to compat layer. This command does not have any counterpart in the new API, meaning it now solely exists as a function in the compat layer. Signed-off-by: Richard Alpe Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/config.c | 35 ----------------------------------- net/tipc/netlink_compat.c | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 35 deletions(-) (limited to 'net/tipc/config.c') diff --git a/net/tipc/config.c b/net/tipc/config.c index 019f46c0690c..c2ad2ff32a15 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -83,38 +83,6 @@ struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string) return buf; } -static struct sk_buff *tipc_show_stats(void) -{ - struct sk_buff *buf; - struct tlv_desc *rep_tlv; - char *pb; - int pb_len; - int str_len; - u32 value; - - if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) - return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); - - value = ntohl(*(u32 *)TLV_DATA(req_tlv_area)); - if (value != 0) - return tipc_cfg_reply_error_string("unsupported argument"); - - buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN)); - if (buf == NULL) - return NULL; - - rep_tlv = (struct tlv_desc *)buf->data; - pb = TLV_DATA(rep_tlv); - pb_len = ULTRA_STRING_MAX_LEN; - - str_len = tipc_snprintf(pb, pb_len, "TIPC version " TIPC_MOD_VER "\n"); - str_len += 1; /* for "\0" */ - skb_put(buf, TLV_SPACE(str_len)); - TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); - - return buf; -} - struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, const void *request_area, int request_space, int reply_headroom) @@ -142,9 +110,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, case TIPC_CMD_NOOP: rep_tlv_buf = tipc_cfg_reply_none(); break; - case TIPC_CMD_SHOW_STATS: - rep_tlv_buf = tipc_show_stats(); - break; case TIPC_CMD_NOT_NET_ADMIN: rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN); diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 415909054ec0..cb9086d259df 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -888,6 +888,18 @@ static int tipc_nl_compat_net_dump(struct tipc_nl_compat_msg *msg, return tipc_add_tlv(msg->rep, TIPC_TLV_UNSIGNED, &id, sizeof(id)); } +static int tipc_cmd_show_stats_compat(struct tipc_nl_compat_msg *msg) +{ + msg->rep = tipc_tlv_alloc(ULTRA_STRING_MAX_LEN); + if (!msg->rep) + return -ENOMEM; + + tipc_tlv_init(msg->rep, TIPC_TLV_ULTRA_STRING); + tipc_tlv_sprintf(msg->rep, "TIPC version " TIPC_MOD_VER "\n"); + + return 0; +} + static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) { struct tipc_nl_compat_cmd_dump dump; @@ -976,6 +988,8 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) dump.dumpit = tipc_nl_net_dump; dump.format = tipc_nl_compat_net_dump; return tipc_nl_compat_dumpit(&dump, msg); + case TIPC_CMD_SHOW_STATS: + return tipc_cmd_show_stats_compat(msg); } return -EOPNOTSUPP; @@ -1088,6 +1102,7 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) case TIPC_CMD_SET_NODE_ADDR: case TIPC_CMD_SET_NETID: case TIPC_CMD_GET_NETID: + case TIPC_CMD_SHOW_STATS: return tipc_nl_compat_recv(skb, info); } -- cgit v1.2.3-70-g09d2 From 22ae7cff509f3bb22caaa0003f67eeb93d338fed Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:18 +0100 Subject: tipc: nl compat add noop and remove legacy nl framework Add TIPC_CMD_NOOP to compat layer and remove the old framework. All legacy nl commands are now converted to the compat layer in netlink_compat.c. Signed-off-by: Richard Alpe Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/Makefile | 2 +- net/tipc/bearer.c | 1 - net/tipc/config.c | 157 ---------------------------------------------- net/tipc/config.h | 67 -------------------- net/tipc/core.c | 3 +- net/tipc/link.c | 1 - net/tipc/log.c | 1 - net/tipc/name_table.c | 4 +- net/tipc/net.c | 2 - net/tipc/netlink_compat.c | 73 ++------------------- net/tipc/node.c | 2 +- net/tipc/socket.c | 1 - 12 files changed, 13 insertions(+), 301 deletions(-) delete mode 100644 net/tipc/config.c delete mode 100644 net/tipc/config.h (limited to 'net/tipc/config.c') diff --git a/net/tipc/Makefile b/net/tipc/Makefile index 69b82bbc60d3..6864b9de2404 100644 --- a/net/tipc/Makefile +++ b/net/tipc/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_TIPC) := tipc.o -tipc-y += addr.o bcast.o bearer.o config.o \ +tipc-y += addr.o bcast.o bearer.o \ core.o link.o discover.o msg.o \ name_distr.o subscr.o name_table.o net.o \ netlink.o netlink_compat.o node.o socket.o log.o eth_media.o \ diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index c7e3b5d3baa9..858c5a6c32df 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -36,7 +36,6 @@ #include #include "core.h" -#include "config.h" #include "bearer.h" #include "link.h" #include "discover.h" diff --git a/net/tipc/config.c b/net/tipc/config.c deleted file mode 100644 index c2ad2ff32a15..000000000000 --- a/net/tipc/config.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * net/tipc/config.c: TIPC configuration management code - * - * Copyright (c) 2002-2006, Ericsson AB - * Copyright (c) 2004-2007, 2010-2013, Wind River Systems - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "core.h" -#include "socket.h" -#include "name_table.h" -#include "config.h" -#include "server.h" - -#define REPLY_TRUNCATED "\n" - -static const void *req_tlv_area; /* request message TLV area */ -static int req_tlv_space; /* request message TLV area size */ -static int rep_headroom; /* reply message headroom to use */ - -struct sk_buff *tipc_cfg_reply_alloc(int payload_size) -{ - struct sk_buff *buf; - - buf = alloc_skb(rep_headroom + payload_size, GFP_ATOMIC); - if (buf) - skb_reserve(buf, rep_headroom); - return buf; -} - -int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, - void *tlv_data, int tlv_data_size) -{ - struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(buf); - int new_tlv_space = TLV_SPACE(tlv_data_size); - - if (skb_tailroom(buf) < new_tlv_space) - return 0; - skb_put(buf, new_tlv_space); - tlv->tlv_type = htons(tlv_type); - tlv->tlv_len = htons(TLV_LENGTH(tlv_data_size)); - if (tlv_data_size && tlv_data) - memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size); - return 1; -} - -struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string) -{ - struct sk_buff *buf; - int string_len = strlen(string) + 1; - - buf = tipc_cfg_reply_alloc(TLV_SPACE(string_len)); - if (buf) - tipc_cfg_append_tlv(buf, tlv_type, string, string_len); - return buf; -} - -struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, - const void *request_area, int request_space, - int reply_headroom) -{ - struct sk_buff *rep_tlv_buf; - - rtnl_lock(); - - /* Save request and reply details in a well-known location */ - req_tlv_area = request_area; - req_tlv_space = request_space; - rep_headroom = reply_headroom; - - /* Check command authorization */ - if (likely(in_own_node(net, orig_node))) { - /* command is permitted */ - } else { - rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (cannot be done remotely)"); - goto exit; - } - - /* Call appropriate processing routine */ - switch (cmd) { - case TIPC_CMD_NOOP: - rep_tlv_buf = tipc_cfg_reply_none(); - break; - case TIPC_CMD_NOT_NET_ADMIN: - rep_tlv_buf = - tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN); - break; - case TIPC_CMD_SET_MAX_ZONES: - case TIPC_CMD_GET_MAX_ZONES: - case TIPC_CMD_SET_MAX_SLAVES: - case TIPC_CMD_GET_MAX_SLAVES: - case TIPC_CMD_SET_MAX_CLUSTERS: - case TIPC_CMD_GET_MAX_CLUSTERS: - case TIPC_CMD_SET_MAX_NODES: - case TIPC_CMD_GET_MAX_NODES: - case TIPC_CMD_SET_MAX_SUBSCR: - case TIPC_CMD_GET_MAX_SUBSCR: - case TIPC_CMD_SET_MAX_PUBL: - case TIPC_CMD_GET_MAX_PUBL: - case TIPC_CMD_SET_LOG_SIZE: - case TIPC_CMD_SET_REMOTE_MNG: - case TIPC_CMD_GET_REMOTE_MNG: - case TIPC_CMD_DUMP_LOG: - case TIPC_CMD_SET_MAX_PORTS: - case TIPC_CMD_GET_MAX_PORTS: - rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (obsolete command)"); - break; - default: - rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (unknown command)"); - break; - } - - WARN_ON(rep_tlv_buf->len > TLV_SPACE(ULTRA_STRING_MAX_LEN)); - - /* Append an error message if we cannot return all requested data */ - if (rep_tlv_buf->len == TLV_SPACE(ULTRA_STRING_MAX_LEN)) { - if (*(rep_tlv_buf->data + ULTRA_STRING_MAX_LEN) != '\0') - sprintf(rep_tlv_buf->data + rep_tlv_buf->len - - sizeof(REPLY_TRUNCATED) - 1, REPLY_TRUNCATED); - } - - /* Return reply buffer */ -exit: - rtnl_unlock(); - return rep_tlv_buf; -} diff --git a/net/tipc/config.h b/net/tipc/config.h deleted file mode 100644 index 9e9b575fc429..000000000000 --- a/net/tipc/config.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * net/tipc/config.h: Include file for TIPC configuration service code - * - * Copyright (c) 2003-2006, Ericsson AB - * Copyright (c) 2005, Wind River Systems - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _TIPC_CONFIG_H -#define _TIPC_CONFIG_H - -#include "link.h" - -#define ULTRA_STRING_MAX_LEN 32768 - -struct sk_buff *tipc_cfg_reply_alloc(int payload_size); -int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, - void *tlv_data, int tlv_data_size); -struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string); - -static inline struct sk_buff *tipc_cfg_reply_none(void) -{ - return tipc_cfg_reply_alloc(0); -} - -static inline struct sk_buff *tipc_cfg_reply_error_string(char *string) -{ - return tipc_cfg_reply_string_type(TIPC_TLV_ERROR_STRING, string); -} - -static inline struct sk_buff *tipc_cfg_reply_ultra_string(char *string) -{ - return tipc_cfg_reply_string_type(TIPC_TLV_ULTRA_STRING, string); -} - -struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, - const void *req_tlv_area, int req_tlv_space, - int headroom); -#endif diff --git a/net/tipc/core.c b/net/tipc/core.c index 2d06d1f8b6e6..935205e6bcfe 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -39,7 +39,8 @@ #include "core.h" #include "name_table.h" #include "subscr.h" -#include "config.h" +#include "bearer.h" +#include "net.h" #include "socket.h" #include diff --git a/net/tipc/link.c b/net/tipc/link.c index dfe6f4d0b402..a4cf364316de 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -40,7 +40,6 @@ #include "socket.h" #include "name_distr.h" #include "discover.h" -#include "config.h" #include "netlink.h" #include diff --git a/net/tipc/log.c b/net/tipc/log.c index abef644f27d8..b186af06e361 100644 --- a/net/tipc/log.c +++ b/net/tipc/log.c @@ -35,7 +35,6 @@ */ #include "core.h" -#include "config.h" /** * tipc_snprintf - append formatted output to print buffer diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index c8eaa2afe875..105ba7adf06f 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -36,11 +36,13 @@ #include #include "core.h" -#include "config.h" +#include "netlink.h" #include "name_table.h" #include "name_distr.h" #include "subscr.h" #include "bcast.h" +#include "addr.h" +#include #define TIPC_NAMETBL_SIZE 1024 /* must be a power of 2 */ diff --git a/net/tipc/net.c b/net/tipc/net.c index e4028f927c8a..a54f3cbe2246 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -40,8 +40,6 @@ #include "subscr.h" #include "socket.h" #include "node.h" -#include "config.h" -#include "bcast.h" static const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1] = { [TIPC_NLA_NET_UNSPEC] = { .type = NLA_UNSPEC }, diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index cb9086d259df..ce9121e8e990 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -32,7 +32,6 @@ */ #include "core.h" -#include "config.h" #include "bearer.h" #include "link.h" #include "name_table.h" @@ -909,6 +908,11 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) memset(&doit, 0, sizeof(doit)); switch (msg->cmd) { + case TIPC_CMD_NOOP: + msg->rep = tipc_tlv_alloc(0); + if (!msg->rep) + return -ENOMEM; + return 0; case TIPC_CMD_GET_BEARER_NAMES: msg->rep_size = MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME); dump.dumpit = tipc_nl_bearer_dump; @@ -1044,71 +1048,6 @@ send: return err; } -static int handle_cmd(struct sk_buff *skb, struct genl_info *info) -{ - struct net *net = genl_info_net(info); - struct sk_buff *rep_buf; - struct nlmsghdr *rep_nlh; - struct nlmsghdr *req_nlh = info->nlhdr; - struct tipc_genlmsghdr *req_userhdr = info->userhdr; - int hdr_space = nlmsg_total_size(GENL_HDRLEN + TIPC_GENL_HDRLEN); - u16 cmd; - - if ((req_userhdr->cmd & 0xC000) && - (!netlink_net_capable(skb, CAP_NET_ADMIN))) - cmd = TIPC_CMD_NOT_NET_ADMIN; - else - cmd = req_userhdr->cmd; - - rep_buf = tipc_cfg_do_cmd(net, req_userhdr->dest, cmd, - nlmsg_data(req_nlh) + GENL_HDRLEN + - TIPC_GENL_HDRLEN, - nlmsg_attrlen(req_nlh, GENL_HDRLEN + - TIPC_GENL_HDRLEN), hdr_space); - - if (rep_buf) { - skb_push(rep_buf, hdr_space); - rep_nlh = nlmsg_hdr(rep_buf); - memcpy(rep_nlh, req_nlh, hdr_space); - rep_nlh->nlmsg_len = rep_buf->len; - genlmsg_unicast(net, rep_buf, NETLINK_CB(skb).portid); - } - - return 0; -} - -/* Temporary function to keep functionality throughout the patchset - * without having to mess with the global variables and other trickery - * of the old API. - */ -static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) -{ - struct tipc_genlmsghdr *req = info->userhdr; - - switch (req->cmd) { - case TIPC_CMD_GET_BEARER_NAMES: - case TIPC_CMD_ENABLE_BEARER: - case TIPC_CMD_DISABLE_BEARER: - case TIPC_CMD_SHOW_LINK_STATS: - case TIPC_CMD_GET_LINKS: - case TIPC_CMD_SET_LINK_TOL: - case TIPC_CMD_SET_LINK_PRI: - case TIPC_CMD_SET_LINK_WINDOW: - case TIPC_CMD_RESET_LINK_STATS: - case TIPC_CMD_SHOW_NAME_TABLE: - case TIPC_CMD_SHOW_PORTS: - case TIPC_CMD_GET_MEDIA_NAMES: - case TIPC_CMD_GET_NODES: - case TIPC_CMD_SET_NODE_ADDR: - case TIPC_CMD_SET_NETID: - case TIPC_CMD_GET_NETID: - case TIPC_CMD_SHOW_STATS: - return tipc_nl_compat_recv(skb, info); - } - - return handle_cmd(skb, info); -} - static struct genl_family tipc_genl_compat_family = { .id = GENL_ID_GENERATE, .name = TIPC_GENL_NAME, @@ -1121,7 +1060,7 @@ static struct genl_family tipc_genl_compat_family = { static struct genl_ops tipc_genl_compat_ops[] = { { .cmd = TIPC_GENL_CMD, - .doit = tipc_nl_compat_tmp_wrap, + .doit = tipc_nl_compat_recv, }, }; diff --git a/net/tipc/node.c b/net/tipc/node.c index ddaa2bbaa35d..86152de8248d 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -35,7 +35,7 @@ */ #include "core.h" -#include "config.h" +#include "link.h" #include "node.h" #include "name_distr.h" #include "socket.h" diff --git a/net/tipc/socket.c b/net/tipc/socket.c index e77d738bb771..f73e975af80b 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -40,7 +40,6 @@ #include "name_table.h" #include "node.h" #include "link.h" -#include "config.h" #include "name_distr.h" #include "socket.h" -- cgit v1.2.3-70-g09d2