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/core.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'net/tipc/core.h') diff --git a/net/tipc/core.h b/net/tipc/core.h index 84602137ce20..56fe4229fc5e 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -37,8 +37,6 @@ #ifndef _TIPC_CORE_H #define _TIPC_CORE_H -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -79,7 +77,6 @@ int tipc_snprintf(char *buf, int len, const char *fmt, ...); * Global configuration variables */ extern u32 tipc_own_addr __read_mostly; -extern int tipc_max_ports __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; -- cgit v1.2.3-70-g09d2 From 2f55c43788df7358be8c6e78ae2a3d3268e7afb6 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Fri, 9 Jan 2015 15:27:00 +0800 Subject: tipc: remove unnecessary wrapper functions of kernel timer APIs Not only some wrapper function like k_term_timer() is empty, but also some others including k_start_timer() and k_cancel_timer() don't return back any value to its caller, what's more, there is no any component in the kernel world to do such thing. Therefore, these timer interfaces defined in tipc module should be purged. Signed-off-by: Ying Xue Tested-by: Tero Aho Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/core.h | 67 ----------------------------------------------------- net/tipc/discover.c | 32 ++++++++++++++----------- net/tipc/link.c | 27 ++++++++++----------- net/tipc/link.h | 4 ++-- net/tipc/msg.h | 2 -- net/tipc/socket.c | 17 +++++++------- net/tipc/subscr.c | 17 ++++++-------- net/tipc/subscr.h | 2 +- 8 files changed, 50 insertions(+), 118 deletions(-) (limited to 'net/tipc/core.h') diff --git a/net/tipc/core.h b/net/tipc/core.h index 56fe4229fc5e..d57068961d4c 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -106,73 +106,6 @@ void tipc_unregister_sysctl(void); #define tipc_unregister_sysctl() #endif -/* - * TIPC timer code - */ -typedef void (*Handler) (unsigned long); - -/** - * k_init_timer - initialize a timer - * @timer: pointer to timer structure - * @routine: pointer to routine to invoke when timer expires - * @argument: value to pass to routine when timer expires - * - * Timer must be initialized before use (and terminated when no longer needed). - */ -static inline void k_init_timer(struct timer_list *timer, Handler routine, - unsigned long argument) -{ - setup_timer(timer, routine, argument); -} - -/** - * k_start_timer - start a timer - * @timer: pointer to timer structure - * @msec: time to delay (in ms) - * - * Schedules a previously initialized timer for later execution. - * If timer is already running, the new timeout overrides the previous request. - * - * To ensure the timer doesn't expire before the specified delay elapses, - * the amount of delay is rounded up when converting to the jiffies - * then an additional jiffy is added to account for the fact that - * the starting time may be in the middle of the current jiffy. - */ -static inline void k_start_timer(struct timer_list *timer, unsigned long msec) -{ - mod_timer(timer, jiffies + msecs_to_jiffies(msec) + 1); -} - -/** - * k_cancel_timer - cancel a timer - * @timer: pointer to timer structure - * - * Cancels a previously initialized timer. - * Can be called safely even if the timer is already inactive. - * - * WARNING: Must not be called when holding locks required by the timer's - * timeout routine, otherwise deadlock can occur on SMP systems! - */ -static inline void k_cancel_timer(struct timer_list *timer) -{ - del_timer_sync(timer); -} - -/** - * k_term_timer - terminate a timer - * @timer: pointer to timer structure - * - * Prevents further use of a previously initialized timer. - * - * WARNING: Caller must ensure timer isn't currently running. - * - * (Do not "enhance" this routine to automatically cancel an active timer, - * otherwise deadlock can arise when a timeout routine calls k_term_timer.) - */ -static inline void k_term_timer(struct timer_list *timer) -{ -} - /* * TIPC message buffer code * diff --git a/net/tipc/discover.c b/net/tipc/discover.c index aa722a42ef8b..1a3a98582034 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -38,10 +38,14 @@ #include "link.h" #include "discover.h" -#define TIPC_LINK_REQ_INIT 125 /* min delay during bearer start up */ -#define TIPC_LINK_REQ_FAST 1000 /* max delay if bearer has no links */ -#define TIPC_LINK_REQ_SLOW 60000 /* max delay if bearer has links */ -#define TIPC_LINK_REQ_INACTIVE 0xffffffff /* indicates no timer in use */ +/* min delay during bearer start up */ +#define TIPC_LINK_REQ_INIT msecs_to_jiffies(125) +/* max delay if bearer has no links */ +#define TIPC_LINK_REQ_FAST msecs_to_jiffies(1000) +/* max delay if bearer has links */ +#define TIPC_LINK_REQ_SLOW msecs_to_jiffies(60000) +/* indicates no timer in use */ +#define TIPC_LINK_REQ_INACTIVE 0xffffffff /** @@ -63,7 +67,7 @@ struct tipc_link_req { spinlock_t lock; struct sk_buff *buf; struct timer_list timer; - unsigned int timer_intv; + unsigned long timer_intv; }; /** @@ -265,7 +269,7 @@ static void disc_update(struct tipc_link_req *req) if ((req->timer_intv == TIPC_LINK_REQ_INACTIVE) || (req->timer_intv > TIPC_LINK_REQ_FAST)) { req->timer_intv = TIPC_LINK_REQ_INIT; - k_start_timer(&req->timer, req->timer_intv); + mod_timer(&req->timer, jiffies + req->timer_intv); } } } @@ -295,12 +299,13 @@ void tipc_disc_remove_dest(struct tipc_link_req *req) /** * disc_timeout - send a periodic link setup request - * @req: ptr to link request structure + * @data: ptr to link request structure * * Called whenever a link setup request timer associated with a bearer expires. */ -static void disc_timeout(struct tipc_link_req *req) +static void disc_timeout(unsigned long data) { + struct tipc_link_req *req = (struct tipc_link_req *)data; int max_delay; spin_lock_bh(&req->lock); @@ -329,7 +334,7 @@ static void disc_timeout(struct tipc_link_req *req) if (req->timer_intv > max_delay) req->timer_intv = max_delay; - k_start_timer(&req->timer, req->timer_intv); + mod_timer(&req->timer, jiffies + req->timer_intv); exit: spin_unlock_bh(&req->lock); } @@ -363,8 +368,8 @@ int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest) req->num_nodes = 0; req->timer_intv = TIPC_LINK_REQ_INIT; spin_lock_init(&req->lock); - k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); - k_start_timer(&req->timer, req->timer_intv); + 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); return 0; @@ -376,8 +381,7 @@ int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest) */ void tipc_disc_delete(struct tipc_link_req *req) { - k_cancel_timer(&req->timer); - k_term_timer(&req->timer); + del_timer_sync(&req->timer); kfree_skb(req->buf); kfree(req); } @@ -397,7 +401,7 @@ void tipc_disc_reset(struct tipc_bearer *b_ptr) req->domain = b_ptr->domain; req->num_nodes = 0; req->timer_intv = TIPC_LINK_REQ_INIT; - k_start_timer(&req->timer, req->timer_intv); + mod_timer(&req->timer, jiffies + req->timer_intv); tipc_bearer_send(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 082c3b5b32a1..f2531a8efa54 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -106,7 +106,7 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, 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, struct sk_buff **buf); -static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance); +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); static void link_reset_statistics(struct tipc_link *l_ptr); static void link_print(struct tipc_link *l_ptr, const char *str); @@ -169,8 +169,9 @@ int tipc_link_is_active(struct tipc_link *l_ptr) * link_timeout - handle expiration of link timer * @l_ptr: pointer to link */ -static void link_timeout(struct tipc_link *l_ptr) +static void link_timeout(unsigned long data) { + struct tipc_link *l_ptr = (struct tipc_link *)data; struct sk_buff *skb; tipc_node_lock(l_ptr->owner); @@ -217,9 +218,9 @@ static void link_timeout(struct tipc_link *l_ptr) tipc_node_unlock(l_ptr->owner); } -static void link_set_timer(struct tipc_link *l_ptr, u32 time) +static void link_set_timer(struct tipc_link *link, unsigned long time) { - k_start_timer(&l_ptr->timer, time); + mod_timer(&link->timer, jiffies + time); } /** @@ -299,8 +300,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, tipc_node_attach_link(n_ptr, l_ptr); - k_init_timer(&l_ptr->timer, (Handler)link_timeout, - (unsigned long)l_ptr); + setup_timer(&l_ptr->timer, link_timeout, (unsigned long)l_ptr); link_state_event(l_ptr, STARTING_EVT); @@ -479,7 +479,7 @@ static void link_activate(struct tipc_link *l_ptr) static void link_state_event(struct tipc_link *l_ptr, unsigned int event) { struct tipc_link *other; - u32 cont_intv = l_ptr->continuity_interval; + unsigned long cont_intv = l_ptr->cont_intv; if (l_ptr->flags & LINK_STOPPED) return; @@ -1880,15 +1880,16 @@ void tipc_link_bundle_rcv(struct sk_buff *buf) kfree_skb(buf); } -static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance) +static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tol) { - if ((tolerance < TIPC_MIN_LINK_TOL) || (tolerance > TIPC_MAX_LINK_TOL)) + unsigned long intv = ((tol / 4) > 500) ? 500 : tol / 4; + + if ((tol < TIPC_MIN_LINK_TOL) || (tol > TIPC_MAX_LINK_TOL)) return; - l_ptr->tolerance = tolerance; - l_ptr->continuity_interval = - ((tolerance / 4) > 500) ? 500 : tolerance / 4; - l_ptr->abort_limit = tolerance / (l_ptr->continuity_interval / 4); + l_ptr->tolerance = tol; + l_ptr->cont_intv = msecs_to_jiffies(intv); + l_ptr->abort_limit = tol / (jiffies_to_msecs(l_ptr->cont_intv) / 4); } void tipc_link_set_queue_limits(struct tipc_link *l_ptr, u32 window) diff --git a/net/tipc/link.h b/net/tipc/link.h index 55812e87ca1e..15ca850391df 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -105,7 +105,7 @@ struct tipc_stats { * @peer_bearer_id: bearer id used by link's peer endpoint * @bearer_id: local bearer id used by link * @tolerance: minimum link continuity loss needed to reset link [in ms] - * @continuity_interval: link continuity testing interval [in ms] + * @cont_intv: link continuity testing interval * @abort_limit: # of unacknowledged continuity probes needed to reset link * @state: current state of link FSM * @fsm_msg_cnt: # of protocol messages link FSM has sent in current state @@ -146,7 +146,7 @@ struct tipc_link { u32 peer_bearer_id; u32 bearer_id; u32 tolerance; - u32 continuity_interval; + unsigned long cont_intv; u32 abort_limit; int state; u32 fsm_msg_cnt; diff --git a/net/tipc/msg.h b/net/tipc/msg.h index d5c83d7ecb47..1a52f7cf3cd3 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -77,12 +77,10 @@ #define TIPC_MEDIA_ADDR_OFFSET 5 - struct tipc_msg { __be32 hdr[15]; }; - static inline u32 msg_word(struct tipc_msg *m, u32 pos) { return ntohl(m->hdr[pos]); diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 701f31bbbbfb..e16197eb7b9f 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -47,7 +47,7 @@ #define SS_READY -2 /* socket is connectionless */ #define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */ -#define CONN_PROBING_INTERVAL 3600000 /* [ms] => 1 h */ +#define CONN_PROBING_INTERVAL msecs_to_jiffies(3600000) /* [ms] => 1 h */ #define TIPC_FWD_MSG 1 #define TIPC_CONN_OK 0 #define TIPC_CONN_PROBING 1 @@ -68,7 +68,7 @@ * @publications: list of publications for port * @pub_count: total # of publications port has made during its lifetime * @probing_state: - * @probing_interval: + * @probing_intv: * @timer: * @port: port - interacts with 'sk' and with the rest of the TIPC stack * @peer_name: the peer of the connection, if any @@ -93,7 +93,7 @@ struct tipc_sock { struct list_head publications; u32 pub_count; u32 probing_state; - u32 probing_interval; + unsigned long probing_intv; struct timer_list timer; uint conn_timeout; atomic_t dupl_rcvcnt; @@ -361,7 +361,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock, return -EINVAL; } msg_set_origport(msg, tsk->portid); - k_init_timer(&tsk->timer, (Handler)tipc_sk_timeout, tsk->portid); + setup_timer(&tsk->timer, tipc_sk_timeout, tsk->portid); sk->sk_backlog_rcv = tipc_backlog_rcv; sk->sk_rcvbuf = sysctl_tipc_rmem[1]; sk->sk_data_ready = tipc_data_ready; @@ -511,7 +511,7 @@ static int tipc_release(struct socket *sock) } tipc_sk_withdraw(tsk, 0, NULL); - k_cancel_timer(&tsk->timer); + del_timer_sync(&tsk->timer); tipc_sk_remove(tsk); if (tsk->connected) { skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, @@ -522,7 +522,6 @@ static int tipc_release(struct socket *sock) tipc_link_xmit_skb(skb, dnode, tsk->portid); tipc_node_remove_conn(dnode, tsk->portid); } - k_term_timer(&tsk->timer); /* Discard any remaining (connection-based) messages in receive queue */ __skb_queue_purge(&sk->sk_receive_queue); @@ -1139,10 +1138,10 @@ static void tipc_sk_finish_conn(struct tipc_sock *tsk, u32 peer_port, msg_set_lookup_scope(msg, 0); msg_set_hdr_sz(msg, SHORT_H_SIZE); - tsk->probing_interval = CONN_PROBING_INTERVAL; + tsk->probing_intv = CONN_PROBING_INTERVAL; tsk->probing_state = TIPC_CONN_OK; tsk->connected = 1; - k_start_timer(&tsk->timer, tsk->probing_interval); + mod_timer(&tsk->timer, jiffies + tsk->probing_intv); tipc_node_add_conn(peer_node, tsk->portid, peer_port); tsk->max_pkt = tipc_node_get_mtu(peer_node, tsk->portid); } @@ -2128,7 +2127,7 @@ static void tipc_sk_timeout(unsigned long portid) 0, peer_node, tipc_own_addr, peer_port, portid, TIPC_OK); tsk->probing_state = TIPC_CONN_PROBING; - k_start_timer(&tsk->timer, tsk->probing_interval); + mod_timer(&tsk->timer, jiffies + tsk->probing_intv); } bh_unlock_sock(sk); if (skb) diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 0344206b984f..e6cb959371dc 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -141,8 +141,9 @@ void tipc_subscr_report_overlap(struct tipc_subscription *sub, u32 found_lower, subscr_send_event(sub, found_lower, found_upper, event, port_ref, node); } -static void subscr_timeout(struct tipc_subscription *sub) +static void subscr_timeout(unsigned long data) { + struct tipc_subscription *sub = (struct tipc_subscription *)data; struct tipc_subscriber *subscriber = sub->subscriber; /* The spin lock per subscriber is used to protect its members */ @@ -167,7 +168,6 @@ static void subscr_timeout(struct tipc_subscription *sub) TIPC_SUBSCR_TIMEOUT, 0, 0); /* Now destroy subscription */ - k_term_timer(&sub->timer); kfree(sub); atomic_dec(&subscription_count); } @@ -207,8 +207,7 @@ static void subscr_release(struct tipc_subscriber *subscriber) subscription_list) { if (sub->timeout != TIPC_WAIT_FOREVER) { spin_unlock_bh(&subscriber->lock); - k_cancel_timer(&sub->timer); - k_term_timer(&sub->timer); + del_timer_sync(&sub->timer); spin_lock_bh(&subscriber->lock); } subscr_del(sub); @@ -250,8 +249,7 @@ static void subscr_cancel(struct tipc_subscr *s, if (sub->timeout != TIPC_WAIT_FOREVER) { sub->timeout = TIPC_WAIT_FOREVER; spin_unlock_bh(&subscriber->lock); - k_cancel_timer(&sub->timer); - k_term_timer(&sub->timer); + del_timer_sync(&sub->timer); spin_lock_bh(&subscriber->lock); } subscr_del(sub); @@ -296,7 +294,7 @@ static int subscr_subscribe(struct tipc_subscr *s, sub->seq.type = htohl(s->seq.type, swap); sub->seq.lower = htohl(s->seq.lower, swap); sub->seq.upper = htohl(s->seq.upper, swap); - sub->timeout = htohl(s->timeout, swap); + sub->timeout = msecs_to_jiffies(htohl(s->timeout, swap)); sub->filter = htohl(s->filter, swap); if ((!(sub->filter & TIPC_SUB_PORTS) == !(sub->filter & TIPC_SUB_SERVICE)) || @@ -311,9 +309,8 @@ static int subscr_subscribe(struct tipc_subscr *s, memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); atomic_inc(&subscription_count); if (sub->timeout != TIPC_WAIT_FOREVER) { - k_init_timer(&sub->timer, - (Handler)subscr_timeout, (unsigned long)sub); - k_start_timer(&sub->timer, sub->timeout); + setup_timer(&sub->timer, subscr_timeout, (unsigned long)sub); + mod_timer(&sub->timer, jiffies + sub->timeout); } *sub_p = sub; return 0; diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index 393e417bee3f..ab01713bfe32 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h @@ -58,7 +58,7 @@ struct tipc_subscriber; struct tipc_subscription { struct tipc_subscriber *subscriber; struct tipc_name_seq seq; - u32 timeout; + unsigned long timeout; u32 filter; struct timer_list timer; struct list_head nameseq_list; -- cgit v1.2.3-70-g09d2 From 859fc7c0cedca0f84dac471fa31e9512259e1ecd Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Fri, 9 Jan 2015 15:27:01 +0800 Subject: tipc: cleanup core.c and core.h files Only the works of initializing and shutting down tipc module are done in core.h and core.c files, so all stuffs which are not closely associated with the two tasks should be moved to appropriate places. 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/config.h | 4 ++-- net/tipc/core.c | 23 ----------------------- net/tipc/core.h | 53 ----------------------------------------------------- net/tipc/link.h | 4 ++++ net/tipc/msg.c | 23 +++++++++++++++++++++++ net/tipc/msg.h | 37 +++++++++++++++++++++++++++++-------- net/tipc/netlink.h | 3 +++ net/tipc/server.c | 1 + net/tipc/server.h | 3 ++- net/tipc/socket.h | 7 +++++++ net/tipc/subscr.h | 3 +++ 12 files changed, 74 insertions(+), 89 deletions(-) (limited to 'net/tipc/core.h') diff --git a/net/tipc/addr.h b/net/tipc/addr.h index a74acf9ee804..60b00ab93d74 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h @@ -37,8 +37,6 @@ #ifndef _TIPC_ADDR_H #define _TIPC_ADDR_H -#include "core.h" - #define TIPC_ZONE_MASK 0xff000000u #define TIPC_CLUSTER_MASK 0xfffff000u diff --git a/net/tipc/config.h b/net/tipc/config.h index 47b1bf181612..a41a41c58750 100644 --- a/net/tipc/config.h +++ b/net/tipc/config.h @@ -37,10 +37,10 @@ #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); diff --git a/net/tipc/core.c b/net/tipc/core.c index 10bc0bf909e4..b6ec3d7c5f51 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -52,29 +52,6 @@ u32 tipc_own_addr __read_mostly; int tipc_net_id __read_mostly; int sysctl_tipc_rmem[3] __read_mostly; /* min/default/max */ -/** - * tipc_buf_acquire - creates a TIPC message buffer - * @size: message size (including TIPC header) - * - * Returns a new buffer with data pointers set to the specified size. - * - * NOTE: Headroom is reserved to allow prepending of a data link header. - * There may also be unrequested tailroom present at the buffer's end. - */ -struct sk_buff *tipc_buf_acquire(u32 size) -{ - struct sk_buff *skb; - unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u; - - skb = alloc_skb_fclone(buf_size, GFP_ATOMIC); - if (skb) { - skb_reserve(skb, BUF_HEADROOM); - skb_put(skb, size); - skb->next = NULL; - } - return skb; -} - static int __init tipc_init(void) { int err; diff --git a/net/tipc/core.h b/net/tipc/core.h index d57068961d4c..a5b3140f1451 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -60,19 +60,8 @@ #define TIPC_MOD_VER "2.0.0" -#define ULTRA_STRING_MAX_LEN 32768 -#define TIPC_MAX_SUBSCRIPTIONS 65535 -#define TIPC_MAX_PUBLICATIONS 65535 - -struct tipc_msg; /* msg.h */ - int tipc_snprintf(char *buf, int len, const char *fmt, ...); -/* - * TIPC-specific error codes - */ -#define ELINKCONG EAGAIN /* link congestion <=> resource unavailable */ - /* * Global configuration variables */ @@ -86,18 +75,6 @@ extern int sysctl_tipc_named_timeout __read_mostly; */ extern int tipc_random __read_mostly; -/* - * Routines available to privileged subsystems - */ -int tipc_netlink_start(void); -void tipc_netlink_stop(void); -int tipc_socket_init(void); -void tipc_socket_stop(void); -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); - #ifdef CONFIG_SYSCTL int tipc_register_sysctl(void); void tipc_unregister_sysctl(void); @@ -106,34 +83,4 @@ void tipc_unregister_sysctl(void); #define tipc_unregister_sysctl() #endif -/* - * TIPC message buffer code - * - * TIPC message buffer headroom reserves space for the worst-case - * link-level device header (in case the message is sent off-node). - * - * Note: Headroom should be a multiple of 4 to ensure the TIPC header fields - * are word aligned for quicker access - */ -#define BUF_HEADROOM LL_MAX_HEADER - -struct tipc_skb_cb { - void *handle; - struct sk_buff *tail; - bool deferred; - bool wakeup_pending; - bool bundling; - u16 chain_sz; - u16 chain_imp; -}; - -#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0])) - -static inline struct tipc_msg *buf_msg(struct sk_buff *skb) -{ - return (struct tipc_msg *)skb->data; -} - -struct sk_buff *tipc_buf_acquire(u32 size); - #endif diff --git a/net/tipc/link.h b/net/tipc/link.h index 15ca850391df..e96c318f5c73 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -41,6 +41,10 @@ #include "msg.h" #include "node.h" +/* TIPC-specific error codes +*/ +#define ELINKCONG EAGAIN /* link congestion <=> resource unavailable */ + /* Out-of-range value for link sequence numbers */ #define INVALID_LINK_SEQ 0x10000 diff --git a/net/tipc/msg.c b/net/tipc/msg.c index a687b30a699c..35523fb6668c 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -46,6 +46,29 @@ static unsigned int align(unsigned int i) return (i + 3) & ~3u; } +/** + * tipc_buf_acquire - creates a TIPC message buffer + * @size: message size (including TIPC header) + * + * Returns a new buffer with data pointers set to the specified size. + * + * NOTE: Headroom is reserved to allow prepending of a data link header. + * There may also be unrequested tailroom present at the buffer's end. + */ +struct sk_buff *tipc_buf_acquire(u32 size) +{ + struct sk_buff *skb; + unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u; + + skb = alloc_skb_fclone(buf_size, GFP_ATOMIC); + if (skb) { + skb_reserve(skb, BUF_HEADROOM); + skb_put(skb, size); + skb->next = NULL; + } + return skb; +} + void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, u32 destnode) { diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 1a52f7cf3cd3..0065a2e8ad9b 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -77,10 +77,38 @@ #define TIPC_MEDIA_ADDR_OFFSET 5 +/** + * TIPC message buffer code + * + * TIPC message buffer headroom reserves space for the worst-case + * link-level device header (in case the message is sent off-node). + * + * Note: Headroom should be a multiple of 4 to ensure the TIPC header fields + * are word aligned for quicker access + */ +#define BUF_HEADROOM LL_MAX_HEADER + +struct tipc_skb_cb { + void *handle; + struct sk_buff *tail; + bool deferred; + bool wakeup_pending; + bool bundling; + u16 chain_sz; + u16 chain_imp; +}; + +#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0])) + struct tipc_msg { __be32 hdr[15]; }; +static inline struct tipc_msg *buf_msg(struct sk_buff *skb) +{ + return (struct tipc_msg *)skb->data; +} + static inline u32 msg_word(struct tipc_msg *m, u32 pos) { return ntohl(m->hdr[pos]); @@ -719,27 +747,20 @@ static inline u32 msg_tot_origport(struct tipc_msg *m) return msg_origport(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); - 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); - 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); - struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list); #endif diff --git a/net/tipc/netlink.h b/net/tipc/netlink.h index 1425c6869de0..ae2f2d923a15 100644 --- a/net/tipc/netlink.h +++ b/net/tipc/netlink.h @@ -45,4 +45,7 @@ struct tipc_nl_msg { u32 seq; }; +int tipc_netlink_start(void); +void tipc_netlink_stop(void); + #endif diff --git a/net/tipc/server.c b/net/tipc/server.c index a538a02f869b..869eb0905754 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c @@ -35,6 +35,7 @@ #include "server.h" #include "core.h" +#include "socket.h" #include /* Number of messages to send before rescheduling */ diff --git a/net/tipc/server.h b/net/tipc/server.h index be817b0b547e..87bc05c70dce 100644 --- a/net/tipc/server.h +++ b/net/tipc/server.h @@ -36,7 +36,8 @@ #ifndef _TIPC_SERVER_H #define _TIPC_SERVER_H -#include "core.h" +#include +#include #define TIPC_SERVER_NAME_LEN 32 diff --git a/net/tipc/socket.h b/net/tipc/socket.h index c7d46d069d89..46bc370d82c7 100644 --- a/net/tipc/socket.h +++ b/net/tipc/socket.h @@ -42,6 +42,13 @@ #define TIPC_FLOWCTRL_WIN (TIPC_CONNACK_INTV * 2) #define TIPC_CONN_OVERLOAD_LIMIT ((TIPC_FLOWCTRL_WIN * 2 + 1) * \ SKB_TRUESIZE(TIPC_MAX_USER_MSG_SIZE)) + +int tipc_socket_init(void); +void tipc_socket_stop(void); +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); struct sk_buff *tipc_sk_socks_show(void); void tipc_sk_mcast_rcv(struct sk_buff *buf); diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index ab01713bfe32..0d3958956aca 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h @@ -39,6 +39,9 @@ #include "server.h" +#define TIPC_MAX_SUBSCRIPTIONS 65535 +#define TIPC_MAX_PUBLICATIONS 65535 + struct tipc_subscription; struct tipc_subscriber; -- 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/core.h') 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/core.h') 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/core.h') 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 1da465683a93142488a54a9038155f23d6349441 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Fri, 9 Jan 2015 15:27:07 +0800 Subject: tipc: make tipc broadcast link support net namespace TIPC broadcast link is statically established and its relevant states are maintained with the global variables: "bcbearer", "bclink" and "bcl". Allowing different namespace to own different broadcast link instances, these variables must be moved to tipc_net structure and broadcast link instances would be allocated and initialized when namespace is created. Signed-off-by: Ying Xue Tested-by: Tero Aho Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/addr.c | 2 +- net/tipc/addr.h | 3 + net/tipc/bcast.c | 297 ++++++++++++++++++++++++-------------------------- net/tipc/bcast.h | 97 ++++++++++++----- net/tipc/bearer.c | 7 +- net/tipc/bearer.h | 21 +++- net/tipc/core.h | 10 ++ net/tipc/link.c | 17 +-- net/tipc/msg.h | 2 +- net/tipc/name_table.c | 1 + net/tipc/net.c | 1 + net/tipc/node.c | 6 +- 12 files changed, 259 insertions(+), 205 deletions(-) (limited to 'net/tipc/core.h') diff --git a/net/tipc/addr.c b/net/tipc/addr.c index 357b74b26f9e..9e6eeb450fe1 100644 --- a/net/tipc/addr.c +++ b/net/tipc/addr.c @@ -34,7 +34,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "core.h" +#include #include "addr.h" /** diff --git a/net/tipc/addr.h b/net/tipc/addr.h index 3e1f18e29f1e..4e364c4f1359 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h @@ -37,6 +37,9 @@ #ifndef _TIPC_ADDR_H #define _TIPC_ADDR_H +#include +#include + #define TIPC_ZONE_MASK 0xff000000u #define TIPC_CLUSTER_MASK 0xfffff000u diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index e7c538304595..bc58097ebad2 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -35,77 +35,14 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "core.h" -#include "link.h" #include "socket.h" #include "msg.h" #include "bcast.h" #include "name_distr.h" +#include "core.h" #define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */ #define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */ -#define BCBEARER MAX_BEARERS - -/** - * struct tipc_bcbearer_pair - a pair of bearers used by broadcast link - * @primary: pointer to primary bearer - * @secondary: pointer to secondary bearer - * - * Bearers must have same priority and same set of reachable destinations - * to be paired. - */ - -struct tipc_bcbearer_pair { - struct tipc_bearer *primary; - struct tipc_bearer *secondary; -}; - -/** - * struct tipc_bcbearer - bearer used by broadcast link - * @bearer: (non-standard) broadcast bearer structure - * @media: (non-standard) broadcast media structure - * @bpairs: array of bearer pairs - * @bpairs_temp: temporary array of bearer pairs used by tipc_bcbearer_sort() - * @remains: temporary node map used by tipc_bcbearer_send() - * @remains_new: temporary node map used tipc_bcbearer_send() - * - * Note: The fields labelled "temporary" are incorporated into the bearer - * to avoid consuming potentially limited stack space through the use of - * large local variables within multicast routines. Concurrent access is - * prevented through use of the spinlock "bclink_lock". - */ -struct tipc_bcbearer { - struct tipc_bearer bearer; - struct tipc_media media; - struct tipc_bcbearer_pair bpairs[MAX_BEARERS]; - struct tipc_bcbearer_pair bpairs_temp[TIPC_MAX_LINK_PRI + 1]; - struct tipc_node_map remains; - struct tipc_node_map remains_new; -}; - -/** - * struct tipc_bclink - link used for broadcast messages - * @lock: spinlock governing access to structure - * @link: (non-standard) broadcast link structure - * @node: (non-standard) node structure representing b'cast link's peer node - * @flags: represent bclink states - * @bcast_nodes: map of broadcast-capable nodes - * @retransmit_to: node that most recently requested a retransmit - * - * Handles sequence numbering, fragmentation, bundling, etc. - */ -struct tipc_bclink { - spinlock_t lock; - struct tipc_link link; - struct tipc_node node; - unsigned int flags; - struct tipc_node_map bcast_nodes; - struct tipc_node *retransmit_to; -}; - -static struct tipc_bcbearer *bcbearer; -static struct tipc_bclink *bclink; -static struct tipc_link *bcl; const char tipc_bclink_name[] = "broadcast-link"; @@ -115,25 +52,28 @@ static void tipc_nmap_diff(struct tipc_node_map *nm_a, static void tipc_nmap_add(struct tipc_node_map *nm_ptr, u32 node); static void tipc_nmap_remove(struct tipc_node_map *nm_ptr, u32 node); -static void tipc_bclink_lock(void) +static void tipc_bclink_lock(struct net *net) { - spin_lock_bh(&bclink->lock); + struct tipc_net *tn = net_generic(net, tipc_net_id); + + spin_lock_bh(&tn->bclink->lock); } -static void tipc_bclink_unlock(void) +static void tipc_bclink_unlock(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_node *node = NULL; - if (likely(!bclink->flags)) { - spin_unlock_bh(&bclink->lock); + if (likely(!tn->bclink->flags)) { + spin_unlock_bh(&tn->bclink->lock); return; } - if (bclink->flags & TIPC_BCLINK_RESET) { - bclink->flags &= ~TIPC_BCLINK_RESET; - node = tipc_bclink_retransmit_to(); + if (tn->bclink->flags & TIPC_BCLINK_RESET) { + tn->bclink->flags &= ~TIPC_BCLINK_RESET; + node = tipc_bclink_retransmit_to(net); } - spin_unlock_bh(&bclink->lock); + spin_unlock_bh(&tn->bclink->lock); if (node) tipc_link_reset_all(node); @@ -144,9 +84,11 @@ uint tipc_bclink_get_mtu(void) return MAX_PKT_DEFAULT_MCAST; } -void tipc_bclink_set_flags(unsigned int flags) +void tipc_bclink_set_flags(struct net *net, unsigned int flags) { - bclink->flags |= flags; + struct tipc_net *tn = net_generic(net, tipc_net_id); + + tn->bclink->flags |= flags; } static u32 bcbuf_acks(struct sk_buff *buf) @@ -164,31 +106,40 @@ static void bcbuf_decr_acks(struct sk_buff *buf) bcbuf_set_acks(buf, bcbuf_acks(buf) - 1); } -void tipc_bclink_add_node(u32 addr) +void tipc_bclink_add_node(struct net *net, u32 addr) { - tipc_bclink_lock(); - tipc_nmap_add(&bclink->bcast_nodes, addr); - tipc_bclink_unlock(); + struct tipc_net *tn = net_generic(net, tipc_net_id); + + tipc_bclink_lock(net); + tipc_nmap_add(&tn->bclink->bcast_nodes, addr); + tipc_bclink_unlock(net); } -void tipc_bclink_remove_node(u32 addr) +void tipc_bclink_remove_node(struct net *net, u32 addr) { - tipc_bclink_lock(); - tipc_nmap_remove(&bclink->bcast_nodes, addr); - tipc_bclink_unlock(); + struct tipc_net *tn = net_generic(net, tipc_net_id); + + tipc_bclink_lock(net); + tipc_nmap_remove(&tn->bclink->bcast_nodes, addr); + tipc_bclink_unlock(net); } -static void bclink_set_last_sent(void) +static void bclink_set_last_sent(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); + struct tipc_link *bcl = tn->bcl; + if (bcl->next_out) bcl->fsm_msg_cnt = mod(buf_seqno(bcl->next_out) - 1); else bcl->fsm_msg_cnt = mod(bcl->next_out_no - 1); } -u32 tipc_bclink_get_last_sent(void) +u32 tipc_bclink_get_last_sent(struct net *net) { - return bcl->fsm_msg_cnt; + struct tipc_net *tn = net_generic(net, tipc_net_id); + + return tn->bcl->fsm_msg_cnt; } static void bclink_update_last_sent(struct tipc_node *node, u32 seqno) @@ -203,9 +154,11 @@ static void bclink_update_last_sent(struct tipc_node *node, u32 seqno) * * Called with bclink_lock locked */ -struct tipc_node *tipc_bclink_retransmit_to(void) +struct tipc_node *tipc_bclink_retransmit_to(struct net *net) { - return bclink->retransmit_to; + struct tipc_net *tn = net_generic(net, tipc_net_id); + + return tn->bclink->retransmit_to; } /** @@ -215,9 +168,10 @@ struct tipc_node *tipc_bclink_retransmit_to(void) * * Called with bclink_lock locked */ -static void bclink_retransmit_pkt(u32 after, u32 to) +static void bclink_retransmit_pkt(struct tipc_net *tn, u32 after, u32 to) { struct sk_buff *skb; + struct tipc_link *bcl = tn->bcl; skb_queue_walk(&bcl->outqueue, skb) { if (more(buf_seqno(skb), after)) { @@ -234,9 +188,10 @@ static void bclink_retransmit_pkt(u32 after, u32 to) */ void tipc_bclink_wakeup_users(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); struct sk_buff *skb; - while ((skb = skb_dequeue(&bclink->link.waiting_sks))) + while ((skb = skb_dequeue(&tn->bclink->link.waiting_sks))) tipc_sk_rcv(net, skb); } @@ -252,10 +207,12 @@ void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked) struct sk_buff *skb, *tmp; struct sk_buff *next; unsigned int released = 0; + struct net *net = n_ptr->net; + struct tipc_net *tn = net_generic(net, tipc_net_id); - tipc_bclink_lock(); + tipc_bclink_lock(net); /* Bail out if tx queue is empty (no clean up is required) */ - skb = skb_peek(&bcl->outqueue); + skb = skb_peek(&tn->bcl->outqueue); if (!skb) goto exit; @@ -266,43 +223,43 @@ void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked) * acknowledge sent messages only (if other nodes still exist) * or both sent and unsent messages (otherwise) */ - if (bclink->bcast_nodes.count) - acked = bcl->fsm_msg_cnt; + if (tn->bclink->bcast_nodes.count) + acked = tn->bcl->fsm_msg_cnt; else - acked = bcl->next_out_no; + acked = tn->bcl->next_out_no; } else { /* * Bail out if specified sequence number does not correspond * to a message that has been sent and not yet acknowledged */ if (less(acked, buf_seqno(skb)) || - less(bcl->fsm_msg_cnt, acked) || + less(tn->bcl->fsm_msg_cnt, acked) || less_eq(acked, n_ptr->bclink.acked)) goto exit; } /* Skip over packets that node has previously acknowledged */ - skb_queue_walk(&bcl->outqueue, skb) { + skb_queue_walk(&tn->bcl->outqueue, skb) { if (more(buf_seqno(skb), n_ptr->bclink.acked)) break; } /* Update packets that node is now acknowledging */ - skb_queue_walk_from_safe(&bcl->outqueue, skb, tmp) { + skb_queue_walk_from_safe(&tn->bcl->outqueue, skb, tmp) { if (more(buf_seqno(skb), acked)) break; - next = tipc_skb_queue_next(&bcl->outqueue, skb); - if (skb != bcl->next_out) { + next = tipc_skb_queue_next(&tn->bcl->outqueue, skb); + if (skb != tn->bcl->next_out) { bcbuf_decr_acks(skb); } else { bcbuf_set_acks(skb, 0); - bcl->next_out = next; - bclink_set_last_sent(); + tn->bcl->next_out = next; + bclink_set_last_sent(net); } if (bcbuf_acks(skb) == 0) { - __skb_unlink(skb, &bcl->outqueue); + __skb_unlink(skb, &tn->bcl->outqueue); kfree_skb(skb); released = 1; } @@ -310,15 +267,15 @@ void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked) n_ptr->bclink.acked = acked; /* Try resolving broadcast link congestion, if necessary */ - if (unlikely(bcl->next_out)) { - tipc_link_push_packets(bcl); - bclink_set_last_sent(); + if (unlikely(tn->bcl->next_out)) { + tipc_link_push_packets(tn->bcl); + bclink_set_last_sent(net); } - if (unlikely(released && !skb_queue_empty(&bcl->waiting_sks))) + if (unlikely(released && !skb_queue_empty(&tn->bcl->waiting_sks))) n_ptr->action_flags |= TIPC_WAKEUP_BCAST_USERS; exit: - tipc_bclink_unlock(); + tipc_bclink_unlock(net); } /** @@ -368,10 +325,10 @@ void tipc_bclink_update_link_state(struct net *net, struct tipc_node *n_ptr, msg_set_bcgap_after(msg, n_ptr->bclink.last_in); msg_set_bcgap_to(msg, to); - tipc_bclink_lock(); + tipc_bclink_lock(net); tipc_bearer_send(net, MAX_BEARERS, buf, NULL); - bcl->stats.sent_nacks++; - tipc_bclink_unlock(); + tn->bcl->stats.sent_nacks++; + tipc_bclink_unlock(net); kfree_skb(buf); n_ptr->bclink.oos_state++; @@ -410,6 +367,9 @@ static void bclink_peek_nack(struct net *net, struct tipc_msg *msg) */ int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list) { + struct tipc_net *tn = net_generic(net, tipc_net_id); + struct tipc_link *bcl = tn->bcl; + struct tipc_bclink *bclink = tn->bclink; int rc = 0; int bc = 0; struct sk_buff *skb; @@ -423,19 +383,19 @@ int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list) /* Broadcast to all other nodes */ if (likely(bclink)) { - tipc_bclink_lock(); + tipc_bclink_lock(net); if (likely(bclink->bcast_nodes.count)) { rc = __tipc_link_xmit(net, bcl, list); if (likely(!rc)) { u32 len = skb_queue_len(&bcl->outqueue); - bclink_set_last_sent(); + bclink_set_last_sent(net); bcl->stats.queue_sz_counts++; bcl->stats.accu_queue_sz += len; } bc = 1; } - tipc_bclink_unlock(); + tipc_bclink_unlock(net); } if (unlikely(!bc)) @@ -457,10 +417,12 @@ int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list) */ static void bclink_accept_pkt(struct tipc_node *node, u32 seqno) { + struct tipc_net *tn = net_generic(node->net, tipc_net_id); + bclink_update_last_sent(node, seqno); node->bclink.last_in = seqno; node->bclink.oos_state = 0; - bcl->stats.recv_info++; + tn->bcl->stats.recv_info++; /* * Unicast an ACK periodically, ensuring that @@ -469,7 +431,7 @@ static void bclink_accept_pkt(struct tipc_node *node, u32 seqno) if (((seqno - tipc_own_addr) % TIPC_MIN_LINK_WIN) == 0) { tipc_link_proto_xmit(node->active_links[node->addr & 1], STATE_MSG, 0, 0, 0, 0, 0); - bcl->stats.sent_acks++; + tn->bcl->stats.sent_acks++; } } @@ -481,6 +443,7 @@ static void bclink_accept_pkt(struct tipc_node *node, u32 seqno) void tipc_bclink_rcv(struct net *net, struct sk_buff *buf) { struct tipc_net *tn = net_generic(net, tipc_net_id); + struct tipc_link *bcl = tn->bcl; struct tipc_msg *msg = buf_msg(buf); struct tipc_node *node; u32 next_in; @@ -506,12 +469,12 @@ void tipc_bclink_rcv(struct net *net, struct sk_buff *buf) if (msg_destnode(msg) == tipc_own_addr) { tipc_bclink_acknowledge(node, msg_bcast_ack(msg)); tipc_node_unlock(node); - tipc_bclink_lock(); + tipc_bclink_lock(net); bcl->stats.recv_nacks++; - bclink->retransmit_to = node; - bclink_retransmit_pkt(msg_bcgap_after(msg), + tn->bclink->retransmit_to = node; + bclink_retransmit_pkt(tn, msg_bcgap_after(msg), msg_bcgap_to(msg)); - tipc_bclink_unlock(); + tipc_bclink_unlock(net); } else { tipc_node_unlock(node); bclink_peek_nack(net, msg); @@ -527,47 +490,47 @@ void tipc_bclink_rcv(struct net *net, struct sk_buff *buf) receive: /* Deliver message to destination */ if (likely(msg_isdata(msg))) { - tipc_bclink_lock(); + tipc_bclink_lock(net); bclink_accept_pkt(node, seqno); - tipc_bclink_unlock(); + tipc_bclink_unlock(net); tipc_node_unlock(node); if (likely(msg_mcast(msg))) tipc_sk_mcast_rcv(net, buf); else kfree_skb(buf); } else if (msg_user(msg) == MSG_BUNDLER) { - tipc_bclink_lock(); + tipc_bclink_lock(net); bclink_accept_pkt(node, seqno); bcl->stats.recv_bundles++; bcl->stats.recv_bundled += msg_msgcnt(msg); - tipc_bclink_unlock(); + tipc_bclink_unlock(net); tipc_node_unlock(node); 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)) goto unlock; - tipc_bclink_lock(); + tipc_bclink_lock(net); bclink_accept_pkt(node, seqno); bcl->stats.recv_fragments++; if (buf) { bcl->stats.recv_fragmented++; msg = buf_msg(buf); - tipc_bclink_unlock(); + tipc_bclink_unlock(net); goto receive; } - tipc_bclink_unlock(); + tipc_bclink_unlock(net); tipc_node_unlock(node); } else if (msg_user(msg) == NAME_DISTRIBUTOR) { - tipc_bclink_lock(); + tipc_bclink_lock(net); bclink_accept_pkt(node, seqno); - tipc_bclink_unlock(); + tipc_bclink_unlock(net); tipc_node_unlock(node); tipc_named_rcv(net, buf); } else { - tipc_bclink_lock(); + tipc_bclink_lock(net); bclink_accept_pkt(node, seqno); - tipc_bclink_unlock(); + tipc_bclink_unlock(net); tipc_node_unlock(node); kfree_skb(buf); } @@ -605,14 +568,14 @@ receive: buf = NULL; } - tipc_bclink_lock(); + tipc_bclink_lock(net); if (deferred) bcl->stats.deferred_recv++; else bcl->stats.duplicates++; - tipc_bclink_unlock(); + tipc_bclink_unlock(net); unlock: tipc_node_unlock(node); @@ -623,7 +586,7 @@ exit: u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr) { return (n_ptr->bclink.recv_permitted && - (tipc_bclink_get_last_sent() != n_ptr->bclink.acked)); + (tipc_bclink_get_last_sent(n_ptr->net) != n_ptr->bclink.acked)); } @@ -636,13 +599,15 @@ u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr) * Returns 0 (packet sent successfully) under all circumstances, * since the broadcast link's pseudo-bearer never blocks */ -static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1, +static int tipc_bcbearer_send(struct net *net, struct sk_buff *buf, + struct tipc_bearer *unused1, struct tipc_media_addr *unused2) { 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); + struct tipc_bcbearer *bcbearer = tn->bcbearer; + struct tipc_bclink *bclink = tn->bclink; /* Prepare broadcast link message for reliable transmission, * if first time trying to send it; @@ -653,7 +618,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1, bcbuf_set_acks(buf, bclink->bcast_nodes.count); msg_set_non_seq(msg, 1); msg_set_mc_netid(msg, tn->net_id); - bcl->stats.sent_info++; + tn->bcl->stats.sent_info++; if (WARN_ON(!bclink->bcast_nodes.count)) { dump_stack(); @@ -708,13 +673,14 @@ 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 *bcbearer = tn->bcbearer; struct tipc_bcbearer_pair *bp_temp = bcbearer->bpairs_temp; struct tipc_bcbearer_pair *bp_curr; struct tipc_bearer *b; int b_index; int pri; - tipc_bclink_lock(); + tipc_bclink_lock(net); if (action) tipc_nmap_add(nm_ptr, node); @@ -761,7 +727,7 @@ void tipc_bcbearer_sort(struct net *net, struct tipc_node_map *nm_ptr, bp_curr++; } - tipc_bclink_unlock(); + tipc_bclink_unlock(net); } static int __tipc_nl_add_bc_link_stat(struct sk_buff *skb, @@ -815,17 +781,19 @@ msg_full: return -EMSGSIZE; } -int tipc_nl_add_bc_link(struct tipc_nl_msg *msg) +int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg) { int err; void *hdr; struct nlattr *attrs; struct nlattr *prop; + struct tipc_net *tn = net_generic(net, tipc_net_id); + struct tipc_link *bcl = tn->bcl; if (!bcl) return 0; - tipc_bclink_lock(); + tipc_bclink_lock(net); hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family, NLM_F_MULTI, TIPC_NL_LINK_GET); @@ -860,7 +828,7 @@ int tipc_nl_add_bc_link(struct tipc_nl_msg *msg) if (err) goto attr_msg_full; - tipc_bclink_unlock(); + tipc_bclink_unlock(net); nla_nest_end(msg->skb, attrs); genlmsg_end(msg->skb, hdr); @@ -871,21 +839,23 @@ prop_msg_full: attr_msg_full: nla_nest_cancel(msg->skb, attrs); msg_full: - tipc_bclink_unlock(); + tipc_bclink_unlock(net); genlmsg_cancel(msg->skb, hdr); return -EMSGSIZE; } -int tipc_bclink_stats(char *buf, const u32 buf_size) +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(); + tipc_bclink_lock(net); s = &bcl->stats; @@ -914,37 +884,46 @@ int tipc_bclink_stats(char *buf, const u32 buf_size) s->queue_sz_counts ? (s->accu_queue_sz / s->queue_sz_counts) : 0); - tipc_bclink_unlock(); + tipc_bclink_unlock(net); return ret; } -int tipc_bclink_reset_stats(void) +int tipc_bclink_reset_stats(struct net *net) { + struct tipc_net *tn = net_generic(net, tipc_net_id); + struct tipc_link *bcl = tn->bcl; + if (!bcl) return -ENOPROTOOPT; - tipc_bclink_lock(); + tipc_bclink_lock(net); memset(&bcl->stats, 0, sizeof(bcl->stats)); - tipc_bclink_unlock(); + tipc_bclink_unlock(net); return 0; } -int tipc_bclink_set_queue_limits(u32 limit) +int tipc_bclink_set_queue_limits(struct net *net, u32 limit) { + struct tipc_net *tn = net_generic(net, tipc_net_id); + struct tipc_link *bcl = tn->bcl; + if (!bcl) return -ENOPROTOOPT; if ((limit < TIPC_MIN_LINK_WIN) || (limit > TIPC_MAX_LINK_WIN)) return -EINVAL; - tipc_bclink_lock(); + tipc_bclink_lock(net); tipc_link_set_queue_limits(bcl, limit); - tipc_bclink_unlock(); + tipc_bclink_unlock(net); return 0; } int tipc_bclink_init(struct net *net) { struct tipc_net *tn = net_generic(net, tipc_net_id); + struct tipc_bcbearer *bcbearer; + struct tipc_bclink *bclink; + struct tipc_link *bcl; bcbearer = kzalloc(sizeof(*bcbearer), GFP_ATOMIC); if (!bcbearer) @@ -969,12 +948,16 @@ int tipc_bclink_init(struct net *net) spin_lock_init(&bclink->node.lock); __skb_queue_head_init(&bclink->node.waiting_sks); bcl->owner = &bclink->node; + bcl->owner->net = net; bcl->max_pkt = MAX_PKT_DEFAULT_MCAST; tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT); bcl->bearer_id = MAX_BEARERS; rcu_assign_pointer(tn->bearer_list[MAX_BEARERS], &bcbearer->bearer); bcl->state = WORKING_WORKING; strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME); + tn->bcbearer = bcbearer; + tn->bclink = bclink; + tn->bcl = bcl; return 0; } @@ -982,14 +965,14 @@ 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(); + tipc_bclink_lock(net); + tipc_link_purge_queues(tn->bcl); + tipc_bclink_unlock(net); RCU_INIT_POINTER(tn->bearer_list[BCBEARER], NULL); synchronize_net(); - kfree(bcbearer); - kfree(bclink); + kfree(tn->bcbearer); + kfree(tn->bclink); } /** diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 692efb662253..a4583a109486 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h @@ -37,23 +37,13 @@ #ifndef _TIPC_BCAST_H #define _TIPC_BCAST_H -#include "netlink.h" +#include +#include "link.h" +#include "node.h" -#define MAX_NODES 4096 -#define WSIZE 32 -#define TIPC_BCLINK_RESET 1 - -/** - * struct tipc_node_map - set of node identifiers - * @count: # of nodes in set - * @map: bitmap of node identifiers that are in the set - */ -struct tipc_node_map { - u32 count; - u32 map[MAX_NODES / WSIZE]; -}; - -#define PLSIZE 32 +#define TIPC_BCLINK_RESET 1 +#define PLSIZE 32 +#define BCBEARER MAX_BEARERS /** * struct tipc_port_list - set of node local destination ports @@ -67,9 +57,64 @@ struct tipc_port_list { u32 ports[PLSIZE]; }; +/** + * struct tipc_bcbearer_pair - a pair of bearers used by broadcast link + * @primary: pointer to primary bearer + * @secondary: pointer to secondary bearer + * + * Bearers must have same priority and same set of reachable destinations + * to be paired. + */ -struct tipc_node; +struct tipc_bcbearer_pair { + struct tipc_bearer *primary; + struct tipc_bearer *secondary; +}; +/** + * struct tipc_bcbearer - bearer used by broadcast link + * @bearer: (non-standard) broadcast bearer structure + * @media: (non-standard) broadcast media structure + * @bpairs: array of bearer pairs + * @bpairs_temp: temporary array of bearer pairs used by tipc_bcbearer_sort() + * @remains: temporary node map used by tipc_bcbearer_send() + * @remains_new: temporary node map used tipc_bcbearer_send() + * + * Note: The fields labelled "temporary" are incorporated into the bearer + * to avoid consuming potentially limited stack space through the use of + * large local variables within multicast routines. Concurrent access is + * prevented through use of the spinlock "bclink_lock". + */ +struct tipc_bcbearer { + struct tipc_bearer bearer; + struct tipc_media media; + struct tipc_bcbearer_pair bpairs[MAX_BEARERS]; + struct tipc_bcbearer_pair bpairs_temp[TIPC_MAX_LINK_PRI + 1]; + struct tipc_node_map remains; + struct tipc_node_map remains_new; +}; + +/** + * struct tipc_bclink - link used for broadcast messages + * @lock: spinlock governing access to structure + * @link: (non-standard) broadcast link structure + * @node: (non-standard) node structure representing b'cast link's peer node + * @flags: represent bclink states + * @bcast_nodes: map of broadcast-capable nodes + * @retransmit_to: node that most recently requested a retransmit + * + * Handles sequence numbering, fragmentation, bundling, etc. + */ +struct tipc_bclink { + spinlock_t lock; + struct tipc_link link; + struct tipc_node node; + unsigned int flags; + struct tipc_node_map bcast_nodes; + struct tipc_node *retransmit_to; +}; + +struct tipc_node; extern const char tipc_bclink_name[]; /** @@ -86,24 +131,24 @@ void tipc_port_list_free(struct tipc_port_list *pl_ptr); 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); -struct tipc_node *tipc_bclink_retransmit_to(void); +void tipc_bclink_set_flags(struct net *tn, unsigned int flags); +void tipc_bclink_add_node(struct net *net, u32 addr); +void tipc_bclink_remove_node(struct net *net, u32 addr); +struct tipc_node *tipc_bclink_retransmit_to(struct net *tn); void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked); void tipc_bclink_rcv(struct net *net, struct sk_buff *buf); -u32 tipc_bclink_get_last_sent(void); +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 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); +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, 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); -int tipc_nl_add_bc_link(struct tipc_nl_msg *msg); +int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg); #endif diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 2fe9dcb418d4..9a0d6ed5c96c 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -40,6 +40,7 @@ #include "bearer.h" #include "link.h" #include "discover.h" +#include "bcast.h" #define MAX_ADDR_STR 60 @@ -482,8 +483,8 @@ void tipc_disable_l2_media(struct tipc_bearer *b) * @b_ptr: the bearer through which the packet is to be sent * @dest: peer destination address */ -int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b, - struct tipc_media_addr *dest) +int tipc_l2_send_msg(struct net *net, struct sk_buff *buf, + struct tipc_bearer *b, struct tipc_media_addr *dest) { struct sk_buff *clone; struct net_device *dev; @@ -528,7 +529,7 @@ void tipc_bearer_send(struct net *net, u32 bearer_id, struct sk_buff *buf, rcu_read_lock(); b_ptr = rcu_dereference_rtnl(tn->bearer_list[bearer_id]); if (likely(b_ptr)) - b_ptr->media->send_msg(buf, b_ptr, dest); + b_ptr->media->send_msg(net, buf, b_ptr, dest); rcu_read_unlock(); } diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 01722d6b2058..c035e3e24764 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -37,12 +37,13 @@ #ifndef _TIPC_BEARER_H #define _TIPC_BEARER_H -#include "bcast.h" #include "netlink.h" #include #define MAX_BEARERS 2 #define MAX_MEDIA 2 +#define MAX_NODES 4096 +#define WSIZE 32 /* Identifiers associated with TIPC message header media address info * - address info field is 32 bytes long @@ -58,6 +59,16 @@ #define TIPC_MEDIA_TYPE_ETH 1 #define TIPC_MEDIA_TYPE_IB 2 +/** + * struct tipc_node_map - set of node identifiers + * @count: # of nodes in set + * @map: bitmap of node identifiers that are in the set + */ +struct tipc_node_map { + u32 count; + u32 map[MAX_NODES / WSIZE]; +}; + /** * struct tipc_media_addr - destination address used by TIPC bearers * @value: address info (format defined by media) @@ -89,7 +100,7 @@ struct tipc_bearer; * @name: media name */ struct tipc_media { - int (*send_msg)(struct sk_buff *buf, + int (*send_msg)(struct net *net, struct sk_buff *buf, struct tipc_bearer *b_ptr, struct tipc_media_addr *dest); int (*enable_media)(struct net *net, struct tipc_bearer *b_ptr); @@ -157,8 +168,6 @@ struct tipc_bearer_names { char if_name[TIPC_MAX_IF_NAME]; }; -struct tipc_link; - /* * TIPC routines available to supported media types */ @@ -193,8 +202,8 @@ 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 sk_buff *buf, struct tipc_bearer *b, - struct tipc_media_addr *dest); +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); diff --git a/net/tipc/core.h b/net/tipc/core.h index 75a332b1968e..3f6f9e07da99 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -61,6 +61,11 @@ #include "node.h" #include "bearer.h" +#include "bcast.h" +#include "netlink.h" +#include "link.h" +#include "node.h" +#include "msg.h" #define TIPC_MOD_VER "2.0.0" @@ -91,6 +96,11 @@ struct tipc_net { /* Bearer list */ struct tipc_bearer __rcu *bearer_list[MAX_BEARERS + 1]; + + /* Broadcast link */ + struct tipc_bcbearer *bcbearer; + struct tipc_bclink *bclink; + struct tipc_link *bcl; }; #ifdef CONFIG_SYSCTL diff --git a/net/tipc/link.c b/net/tipc/link.c index be21e6ac73fe..a84d5c67997e 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -941,6 +941,7 @@ static void link_retransmit_failure(struct tipc_link *l_ptr, struct sk_buff *buf) { struct tipc_msg *msg = buf_msg(buf); + struct net *net = l_ptr->owner->net; pr_warn("Retransmission failure on link <%s>\n", l_ptr->name); @@ -958,7 +959,7 @@ static void link_retransmit_failure(struct tipc_link *l_ptr, pr_cont("Outstanding acks: %lu\n", (unsigned long) TIPC_SKB_CB(buf)->handle); - n_ptr = tipc_bclink_retransmit_to(); + n_ptr = tipc_bclink_retransmit_to(net); tipc_node_lock(n_ptr); tipc_addr_string_fill(addr_string, n_ptr->addr); @@ -973,7 +974,7 @@ static void link_retransmit_failure(struct tipc_link *l_ptr, tipc_node_unlock(n_ptr); - tipc_bclink_set_flags(TIPC_BCLINK_RESET); + tipc_bclink_set_flags(net, TIPC_BCLINK_RESET); l_ptr->stale_count = 0; } } @@ -1404,7 +1405,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg, msg_set_type(msg, msg_typ); msg_set_net_plane(msg, l_ptr->net_plane); msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); - msg_set_last_bcast(msg, tipc_bclink_get_last_sent()); + msg_set_last_bcast(msg, tipc_bclink_get_last_sent(l_ptr->owner->net)); if (msg_typ == STATE_MSG) { u32 next_sent = mod(l_ptr->next_out_no); @@ -2105,7 +2106,7 @@ struct sk_buff *tipc_link_cmd_config(struct net *net, const void *req_tlv_area, if (!strcmp(args->name, tipc_bclink_name)) { if ((cmd == TIPC_CMD_SET_LINK_WINDOW) && - (tipc_bclink_set_queue_limits(new_value) == 0)) + (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)"); @@ -2143,7 +2144,7 @@ struct sk_buff *tipc_link_cmd_reset_stats(struct net *net, link_name = (char *)TLV_DATA(req_tlv_area); if (!strcmp(link_name, tipc_bclink_name)) { - if (tipc_bclink_reset_stats()) + if (tipc_bclink_reset_stats(net)) return tipc_cfg_reply_error_string("link not found"); return tipc_cfg_reply_none(); } @@ -2191,7 +2192,7 @@ static int tipc_link_stats(struct net *net, const char *name, char *buf, int ret; if (!strcmp(name, tipc_bclink_name)) - return tipc_bclink_stats(buf, buf_size); + return tipc_bclink_stats(net, buf, buf_size); node = tipc_link_find_owner(net, name, &bearer_id); if (!node) @@ -2640,7 +2641,7 @@ int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb) prev_node = node->addr; } } else { - err = tipc_nl_add_bc_link(&msg); + err = tipc_nl_add_bc_link(net, &msg); if (err) goto out; @@ -2739,7 +2740,7 @@ int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info) link_name = nla_data(attrs[TIPC_NLA_LINK_NAME]); if (strcmp(link_name, tipc_bclink_name) == 0) { - err = tipc_bclink_reset_stats(); + err = tipc_bclink_reset_stats(net); if (err) return err; return 0; diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 0065a2e8ad9b..75f324287244 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -37,7 +37,7 @@ #ifndef _TIPC_MSG_H #define _TIPC_MSG_H -#include "bearer.h" +#include /* * Constants and routines used to read and write TIPC payload message headers diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index cf177907bb53..beed5fdda004 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -39,6 +39,7 @@ #include "name_table.h" #include "name_distr.h" #include "subscr.h" +#include "bcast.h" #define TIPC_NAMETBL_SIZE 1024 /* must be a power of 2 */ diff --git a/net/tipc/net.c b/net/tipc/net.c index 38633e5f8a7d..7548ba80d289 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -41,6 +41,7 @@ #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/node.c b/net/tipc/node.c index a0ca1ac53119..3db501260de1 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -368,8 +368,8 @@ static void node_established_contact(struct tipc_node *n_ptr) { n_ptr->action_flags |= TIPC_NOTIFY_NODE_UP; n_ptr->bclink.oos_state = 0; - n_ptr->bclink.acked = tipc_bclink_get_last_sent(); - tipc_bclink_add_node(n_ptr->addr); + n_ptr->bclink.acked = tipc_bclink_get_last_sent(n_ptr->net); + tipc_bclink_add_node(n_ptr->net, n_ptr->addr); } static void node_lost_contact(struct tipc_node *n_ptr) @@ -389,7 +389,7 @@ static void node_lost_contact(struct tipc_node *n_ptr) n_ptr->bclink.reasm_buf = NULL; } - tipc_bclink_remove_node(n_ptr->addr); + tipc_bclink_remove_node(n_ptr->net, n_ptr->addr); tipc_bclink_acknowledge(n_ptr, INVALID_LINK_SEQ); n_ptr->bclink.recv_permitted = false; -- 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/core.h') 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/core.h') 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/core.h') 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 a62fbccecd62bacb4416fc427239f5b43b25d05e Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Fri, 9 Jan 2015 15:27:11 +0800 Subject: tipc: make subscriber server support net namespace TIPC establishes one subscriber server which allows users to subscribe their interesting name service status. After tipc supports namespace, one dedicated tipc stack instance is created for each namespace, and each instance can be deemed as one independent TIPC node. As a result, subscriber server must be built for each namespace. Signed-off-by: Ying Xue Tested-by: Tero Aho Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/core.c | 24 ++++++------- net/tipc/core.h | 4 +++ net/tipc/server.c | 2 +- net/tipc/server.h | 4 ++- net/tipc/socket.c | 4 +-- net/tipc/socket.h | 2 +- net/tipc/subscr.c | 104 ++++++++++++++++++++++++++++++++---------------------- net/tipc/subscr.h | 7 ++-- 8 files changed, 86 insertions(+), 65 deletions(-) (limited to 'net/tipc/core.h') diff --git a/net/tipc/core.c b/net/tipc/core.c index 7c09670120eb..4a8b7955e0e0 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -68,8 +68,14 @@ static int __net_init tipc_init_net(struct net *net) err = tipc_nametbl_init(net); if (err) goto out_nametbl; + + err = tipc_subscr_start(net); + if (err) + goto out_subscr; return 0; +out_subscr: + tipc_nametbl_stop(net); out_nametbl: tipc_sk_rht_destroy(net); out_sk_rht: @@ -78,6 +84,7 @@ out_sk_rht: static void __net_exit tipc_exit_net(struct net *net) { + tipc_subscr_stop(net); tipc_net_stop(net); tipc_nametbl_stop(net); tipc_sk_rht_destroy(net); @@ -104,10 +111,6 @@ 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_netlink_start(); if (err) goto out_netlink; @@ -120,9 +123,9 @@ static int __init tipc_init(void) if (err) goto out_sysctl; - err = tipc_subscr_start(); + err = register_pernet_subsys(&tipc_net_ops); if (err) - goto out_subscr; + goto out_pernet; err = tipc_bearer_setup(); if (err) @@ -131,28 +134,25 @@ static int __init tipc_init(void) pr_info("Started in single node mode\n"); return 0; out_bearer: - tipc_subscr_stop(); -out_subscr: + unregister_pernet_subsys(&tipc_net_ops); +out_pernet: tipc_unregister_sysctl(); out_sysctl: tipc_socket_stop(); out_socket: tipc_netlink_stop(); out_netlink: - 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_bearer_cleanup(); tipc_netlink_stop(); - tipc_subscr_stop(); tipc_socket_stop(); tipc_unregister_sysctl(); + unregister_pernet_subsys(&tipc_net_ops); pr_info("Deactivated\n"); } diff --git a/net/tipc/core.h b/net/tipc/core.h index afabf39e801c..639f562dddf3 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -106,6 +106,10 @@ struct tipc_net { /* Name table */ spinlock_t nametbl_lock; struct name_table *nametbl; + + /* Topology subscription server */ + struct tipc_server *topsrv; + atomic_t subscription_count; }; #ifdef CONFIG_SYSCTL diff --git a/net/tipc/server.c b/net/tipc/server.c index b5bdaf721d70..eadd4ed45905 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c @@ -309,7 +309,7 @@ static struct socket *tipc_create_listen_sock(struct tipc_conn *con) struct socket *sock = NULL; int ret; - ret = tipc_sock_create_local(s->type, &sock); + ret = tipc_sock_create_local(s->net, s->type, &sock); if (ret < 0) return NULL; ret = kernel_setsockopt(sock, SOL_TIPC, TIPC_IMPORTANCE, diff --git a/net/tipc/server.h b/net/tipc/server.h index 9c979a01997c..9015faedb1b0 100644 --- a/net/tipc/server.h +++ b/net/tipc/server.h @@ -47,6 +47,7 @@ * @conn_idr: identifier set of connection * @idr_lock: protect the connection identifier set * @idr_in_use: amount of allocated identifier entry + * @net: network namspace instance * @rcvbuf_cache: memory cache of server receive buffer * @rcv_wq: receive workqueue * @send_wq: send workqueue @@ -63,6 +64,7 @@ struct tipc_server { struct idr conn_idr; spinlock_t idr_lock; int idr_in_use; + struct net *net; struct kmem_cache *rcvbuf_cache; struct workqueue_struct *rcv_wq; struct workqueue_struct *send_wq; @@ -73,7 +75,7 @@ struct tipc_server { struct sockaddr_tipc *addr, void *usr_data, void *buf, size_t len); struct sockaddr_tipc *saddr; - const char name[TIPC_SERVER_NAME_LEN]; + char name[TIPC_SERVER_NAME_LEN]; int imp; int type; }; diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 9b8470edc783..2cec496ba691 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -388,7 +388,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock, * * Returns 0 on success, errno otherwise */ -int tipc_sock_create_local(int type, struct socket **res) +int tipc_sock_create_local(struct net *net, int type, struct socket **res) { int rc; @@ -397,7 +397,7 @@ int tipc_sock_create_local(int type, struct socket **res) pr_err("Failed to create kernel socket\n"); return rc; } - tipc_sk_create(&init_net, *res, 0, 1); + tipc_sk_create(net, *res, 0, 1); return 0; } diff --git a/net/tipc/socket.h b/net/tipc/socket.h index c15c4e121fe3..f56c3fded51f 100644 --- a/net/tipc/socket.h +++ b/net/tipc/socket.h @@ -45,7 +45,7 @@ int tipc_socket_init(void); void tipc_socket_stop(void); -int tipc_sock_create_local(int type, struct socket **res); +int tipc_sock_create_local(struct net *net, 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); diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index b71dbc0ae8f9..72c339e432aa 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -50,34 +50,6 @@ struct tipc_subscriber { struct list_head subscription_list; }; -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); - -static atomic_t subscription_count = ATOMIC_INIT(0); - -static struct sockaddr_tipc topsrv_addr __read_mostly = { - .family = AF_TIPC, - .addrtype = TIPC_ADDR_NAMESEQ, - .addr.nameseq.type = TIPC_TOP_SRV, - .addr.nameseq.lower = TIPC_TOP_SRV, - .addr.nameseq.upper = TIPC_TOP_SRV, - .scope = TIPC_NODE_SCOPE -}; - -static struct tipc_server topsrv __read_mostly = { - .saddr = &topsrv_addr, - .imp = TIPC_CRITICAL_IMPORTANCE, - .type = SOCK_SEQPACKET, - .max_rcvbuf_size = sizeof(struct tipc_subscr), - .name = "topology_server", - .tipc_conn_recvmsg = subscr_conn_msg_event, - .tipc_conn_new = subscr_named_msg_event, - .tipc_conn_shutdown = subscr_conn_shutdown_event, -}; - /** * htohl - convert value to endianness used by destination * @in: value to convert @@ -94,6 +66,7 @@ static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower, u32 found_upper, u32 event, u32 port_ref, u32 node) { + struct tipc_net *tn = net_generic(sub->net, tipc_net_id); struct tipc_subscriber *subscriber = sub->subscriber; struct kvec msg_sect; @@ -104,8 +77,8 @@ static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower, sub->evt.found_upper = htohl(found_upper, sub->swap); sub->evt.port.ref = htohl(port_ref, sub->swap); sub->evt.port.node = htohl(node, sub->swap); - tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL, msg_sect.iov_base, - msg_sect.iov_len); + tipc_conn_sendmsg(tn->topsrv, subscriber->conid, NULL, + msg_sect.iov_base, msg_sect.iov_len); } /** @@ -146,6 +119,7 @@ static void subscr_timeout(unsigned long data) { struct tipc_subscription *sub = (struct tipc_subscription *)data; struct tipc_subscriber *subscriber = sub->subscriber; + struct tipc_net *tn = net_generic(sub->net, tipc_net_id); /* The spin lock per subscriber is used to protect its members */ spin_lock_bh(&subscriber->lock); @@ -170,7 +144,7 @@ static void subscr_timeout(unsigned long data) /* Now destroy subscription */ kfree(sub); - atomic_dec(&subscription_count); + atomic_dec(&tn->subscription_count); } /** @@ -180,10 +154,12 @@ static void subscr_timeout(unsigned long data) */ static void subscr_del(struct tipc_subscription *sub) { + struct tipc_net *tn = net_generic(sub->net, tipc_net_id); + tipc_nametbl_unsubscribe(sub); list_del(&sub->subscription_list); kfree(sub); - atomic_dec(&subscription_count); + atomic_dec(&tn->subscription_count); } /** @@ -191,9 +167,12 @@ static void subscr_del(struct tipc_subscription *sub) * * Note: Must call it in process context since it might sleep. */ -static void subscr_terminate(struct tipc_subscriber *subscriber) +static void subscr_terminate(struct tipc_subscription *sub) { - tipc_conn_terminate(&topsrv, subscriber->conid); + struct tipc_subscriber *subscriber = sub->subscriber; + struct tipc_net *tn = net_generic(sub->net, tipc_net_id); + + tipc_conn_terminate(tn->topsrv, subscriber->conid); } static void subscr_release(struct tipc_subscriber *subscriber) @@ -263,7 +242,9 @@ static void subscr_cancel(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_p) +{ + struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_subscription *sub; int swap; @@ -278,7 +259,7 @@ static int subscr_subscribe(struct net *net, struct tipc_subscr *s, } /* Refuse subscription if global limit exceeded */ - if (atomic_read(&subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) { + if (atomic_read(&tn->subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) { pr_warn("Subscription rejected, limit reached (%u)\n", TIPC_MAX_SUBSCRIPTIONS); return -EINVAL; @@ -309,7 +290,7 @@ static int subscr_subscribe(struct net *net, struct tipc_subscr *s, sub->subscriber = subscriber; sub->swap = swap; memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); - atomic_inc(&subscription_count); + atomic_inc(&tn->subscription_count); if (sub->timeout != TIPC_WAIT_FOREVER) { setup_timer(&sub->timer, subscr_timeout, (unsigned long)sub); mod_timer(&sub->timer, jiffies + sub->timeout); @@ -336,7 +317,7 @@ static void subscr_conn_msg_event(struct net *net, int conid, if (subscr_subscribe(net, (struct tipc_subscr *)buf, subscriber, &sub) < 0) { spin_unlock_bh(&subscriber->lock); - subscr_terminate(subscriber); + subscr_terminate(sub); return; } if (sub) @@ -344,7 +325,6 @@ static void subscr_conn_msg_event(struct net *net, int conid, spin_unlock_bh(&subscriber->lock); } - /* Handle one request to establish a new subscriber */ static void *subscr_named_msg_event(int conid) { @@ -363,12 +343,50 @@ static void *subscr_named_msg_event(int conid) return (void *)subscriber; } -int tipc_subscr_start(void) +int tipc_subscr_start(struct net *net) { - return tipc_server_start(&topsrv); + struct tipc_net *tn = net_generic(net, tipc_net_id); + const char name[] = "topology_server"; + struct tipc_server *topsrv; + struct sockaddr_tipc *saddr; + + saddr = kzalloc(sizeof(*saddr), GFP_ATOMIC); + if (!saddr) + return -ENOMEM; + saddr->family = AF_TIPC; + saddr->addrtype = TIPC_ADDR_NAMESEQ; + saddr->addr.nameseq.type = TIPC_TOP_SRV; + saddr->addr.nameseq.lower = TIPC_TOP_SRV; + saddr->addr.nameseq.upper = TIPC_TOP_SRV; + saddr->scope = TIPC_NODE_SCOPE; + + topsrv = kzalloc(sizeof(*topsrv), GFP_ATOMIC); + if (!topsrv) { + kfree(saddr); + return -ENOMEM; + } + topsrv->net = net; + topsrv->saddr = saddr; + topsrv->imp = TIPC_CRITICAL_IMPORTANCE; + topsrv->type = SOCK_SEQPACKET; + topsrv->max_rcvbuf_size = sizeof(struct tipc_subscr); + topsrv->tipc_conn_recvmsg = subscr_conn_msg_event; + topsrv->tipc_conn_new = subscr_named_msg_event; + topsrv->tipc_conn_shutdown = subscr_conn_shutdown_event; + + strncpy(topsrv->name, name, strlen(name) + 1); + tn->topsrv = topsrv; + atomic_set(&tn->subscription_count, 0); + + return tipc_server_start(topsrv); } -void tipc_subscr_stop(void) +void tipc_subscr_stop(struct net *net) { - tipc_server_stop(&topsrv); + struct tipc_net *tn = net_generic(net, tipc_net_id); + struct tipc_server *topsrv = tn->topsrv; + + tipc_server_stop(topsrv); + kfree(topsrv->saddr); + kfree(topsrv); } diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index 670f57096635..33488bd9fe3c 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h @@ -74,13 +74,10 @@ struct tipc_subscription { int tipc_subscr_overlap(struct tipc_subscription *sub, u32 found_lower, u32 found_upper); - void tipc_subscr_report_overlap(struct tipc_subscription *sub, u32 found_lower, u32 found_upper, u32 event, u32 port_ref, u32 node, int must); - -int tipc_subscr_start(void); - -void tipc_subscr_stop(void); +int tipc_subscr_start(struct net *net); +void tipc_subscr_stop(struct net *net); #endif -- cgit v1.2.3-70-g09d2 From bafa29e34185fb70496bfd604dc9e4071049f023 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Fri, 9 Jan 2015 15:27:12 +0800 Subject: tipc: make tipc random value aware of net namespace After namespace is supported, each namespace should own its private random value. So the global variable representing the random value must be moved to tipc_net structure. Signed-off-by: Ying Xue Tested-by: Tero Aho Reviewed-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/core.c | 6 +----- net/tipc/core.h | 6 +----- net/tipc/discover.c | 2 +- net/tipc/link.c | 2 +- 4 files changed, 4 insertions(+), 12 deletions(-) (limited to 'net/tipc/core.h') diff --git a/net/tipc/core.c b/net/tipc/core.c index 4a8b7955e0e0..674bd2698528 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -44,9 +44,6 @@ #include -/* global variables used by multiple sub-systems within TIPC */ -int tipc_random __read_mostly; - /* configurable TIPC parameters */ int tipc_net_id __read_mostly; int sysctl_tipc_rmem[3] __read_mostly; /* min/default/max */ @@ -58,6 +55,7 @@ static int __net_init tipc_init_net(struct net *net) tn->net_id = 4711; tn->own_addr = 0; + get_random_bytes(&tn->random, sizeof(int)); INIT_LIST_HEAD(&tn->node_list); spin_lock_init(&tn->node_list_lock); @@ -109,8 +107,6 @@ static int __init tipc_init(void) TIPC_CRITICAL_IMPORTANCE; sysctl_tipc_rmem[2] = TIPC_CONN_OVERLOAD_LIMIT; - get_random_bytes(&tipc_random, sizeof(tipc_random)); - err = tipc_netlink_start(); if (err) goto out_netlink; diff --git a/net/tipc/core.h b/net/tipc/core.h index 639f562dddf3..817b2e9d4227 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -76,14 +76,10 @@ extern int tipc_net_id __read_mostly; extern int sysctl_tipc_rmem[3] __read_mostly; extern int sysctl_tipc_named_timeout __read_mostly; -/* - * Other global variables - */ -extern int tipc_random __read_mostly; - struct tipc_net { u32 own_addr; int net_id; + int random; /* Node table and node list */ spinlock_t node_list_lock; diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 786411dea61c..5b40cb89ff0a 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -88,7 +88,7 @@ static void tipc_disc_init_msg(struct net *net, struct sk_buff *buf, u32 type, msg = buf_msg(buf); 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_node_sig(msg, tn->random); msg_set_dest_domain(msg, dest_domain); msg_set_bc_netid(msg, tn->net_id); b_ptr->media->addr2msg(msg_media_addr(msg), &b_ptr->addr); diff --git a/net/tipc/link.c b/net/tipc/link.c index 997256769065..193bc1560677 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -289,7 +289,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, 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_session(msg, (tn->random & 0xffff)); msg_set_bearer_id(msg, b_ptr->identity); strcpy((char *)msg_data(msg), if_name); -- cgit v1.2.3-70-g09d2 From bfb3e5dd8dfd84dfd13649393abab63e43267b00 Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:03 +0100 Subject: tipc: move and rename the legacy nl api to "nl compat" The new netlink API is no longer "v2" but rather the standard API and the legacy API is now "nl compat". We split them into separate start/stop and put them in different files in order to further distinguish them. 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 | 4 +- net/tipc/bcast.c | 2 +- net/tipc/bearer.c | 4 +- net/tipc/core.c | 7 ++++ net/tipc/core.h | 1 - net/tipc/link.c | 2 +- net/tipc/name_table.c | 2 +- net/tipc/net.c | 2 +- net/tipc/netlink.c | 67 ++--------------------------- net/tipc/netlink.h | 4 +- net/tipc/netlink_compat.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++ net/tipc/node.c | 2 +- net/tipc/socket.c | 4 +- 13 files changed, 130 insertions(+), 76 deletions(-) create mode 100644 net/tipc/netlink_compat.c (limited to 'net/tipc/core.h') diff --git a/net/tipc/Makefile b/net/tipc/Makefile index 333e4592772c..69b82bbc60d3 100644 --- a/net/tipc/Makefile +++ b/net/tipc/Makefile @@ -7,8 +7,8 @@ obj-$(CONFIG_TIPC) := tipc.o tipc-y += addr.o bcast.o bearer.o config.o \ core.o link.o discover.o msg.o \ name_distr.o subscr.o name_table.o net.o \ - netlink.o node.o socket.o log.o eth_media.o \ - server.o + netlink.o netlink_compat.o node.o socket.o log.o eth_media.o \ + server.o socket.o tipc-$(CONFIG_TIPC_MEDIA_IB) += ib_media.o tipc-$(CONFIG_SYSCTL) += sysctl.o diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 81b1fef1f5e0..e96fd6a6d5c2 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -810,7 +810,7 @@ int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg) tipc_bclink_lock(net); - hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family, + hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, NLM_F_MULTI, TIPC_NL_LINK_GET); if (!hdr) return -EMSGSIZE; diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 33dc3486d16c..35d400e8c2e5 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -658,7 +658,7 @@ static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg, struct nlattr *attrs; struct nlattr *prop; - hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family, + hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, NLM_F_MULTI, TIPC_NL_BEARER_GET); if (!hdr) return -EMSGSIZE; @@ -924,7 +924,7 @@ static int __tipc_nl_add_media(struct tipc_nl_msg *msg, struct nlattr *attrs; struct nlattr *prop; - hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family, + hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, NLM_F_MULTI, TIPC_NL_MEDIA_GET); if (!hdr) return -EMSGSIZE; diff --git a/net/tipc/core.c b/net/tipc/core.c index 674bd2698528..2d06d1f8b6e6 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -111,6 +111,10 @@ static int __init tipc_init(void) if (err) goto out_netlink; + err = tipc_netlink_compat_start(); + if (err) + goto out_netlink_compat; + err = tipc_socket_init(); if (err) goto out_socket; @@ -136,6 +140,8 @@ out_pernet: out_sysctl: tipc_socket_stop(); out_socket: + tipc_netlink_compat_stop(); +out_netlink_compat: tipc_netlink_stop(); out_netlink: pr_err("Unable to start in single node mode\n"); @@ -146,6 +152,7 @@ static void __exit tipc_exit(void) { tipc_bearer_cleanup(); tipc_netlink_stop(); + tipc_netlink_compat_stop(); tipc_socket_stop(); tipc_unregister_sysctl(); unregister_pernet_subsys(&tipc_net_ops); diff --git a/net/tipc/core.h b/net/tipc/core.h index 817b2e9d4227..451c346fd3cf 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -115,5 +115,4 @@ void tipc_unregister_sysctl(void); #define tipc_register_sysctl() 0 #define tipc_unregister_sysctl() #endif - #endif diff --git a/net/tipc/link.c b/net/tipc/link.c index 942491234099..466f28fcf215 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -2498,7 +2498,7 @@ static int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, 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, + hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, NLM_F_MULTI, TIPC_NL_LINK_GET); if (!hdr) return -EMSGSIZE; diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 18a3d44238bc..2251912264a2 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -1055,7 +1055,7 @@ static int __tipc_nl_add_nametable_publ(struct tipc_nl_msg *msg, *last_publ = p->key; hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, - &tipc_genl_v2_family, NLM_F_MULTI, + &tipc_genl_family, NLM_F_MULTI, TIPC_NL_NAME_TABLE_GET); if (!hdr) return -EMSGSIZE; diff --git a/net/tipc/net.c b/net/tipc/net.c index 263267e0e7fe..8b0fb0966628 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -156,7 +156,7 @@ static int __tipc_nl_add_net(struct net *net, struct tipc_nl_msg *msg) void *hdr; struct nlattr *attrs; - hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family, + hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, NLM_F_MULTI, TIPC_NL_NET_GET); if (!hdr) return -EMSGSIZE; diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index fe0f5134ce15..7f6475efc984 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -35,7 +35,6 @@ */ #include "core.h" -#include "config.h" #include "socket.h" #include "name_table.h" #include "bearer.h" @@ -44,39 +43,6 @@ #include "net.h" #include -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; -} - static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = { [TIPC_NLA_UNSPEC] = { .type = NLA_UNSPEC, }, [TIPC_NLA_BEARER] = { .type = NLA_NESTED, }, @@ -89,28 +55,10 @@ static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = { [TIPC_NLA_NAME_TABLE] = { .type = NLA_NESTED, } }; -/* Legacy ASCII API */ -static struct genl_family tipc_genl_family = { - .id = GENL_ID_GENERATE, - .name = TIPC_GENL_NAME, - .version = TIPC_GENL_VERSION, - .hdrsize = TIPC_GENL_HDRLEN, - .maxattr = 0, - .netnsok = true, -}; - -/* Legacy ASCII API */ -static struct genl_ops tipc_genl_ops[] = { - { - .cmd = TIPC_GENL_CMD, - .doit = handle_cmd, - }, -}; - /* Users of the legacy API (tipc-config) can't handle that we add operations, * so we have a separate genl handling for the new API. */ -struct genl_family tipc_genl_v2_family = { +struct genl_family tipc_genl_family = { .id = GENL_ID_GENERATE, .name = TIPC_GENL_V2_NAME, .version = TIPC_GENL_V2_VERSION, @@ -202,9 +150,9 @@ static const struct genl_ops tipc_genl_v2_ops[] = { int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***attr) { - u32 maxattr = tipc_genl_v2_family.maxattr; + u32 maxattr = tipc_genl_family.maxattr; - *attr = tipc_genl_v2_family.attrbuf; + *attr = tipc_genl_family.attrbuf; if (!*attr) return -EOPNOTSUPP; @@ -215,13 +163,7 @@ int tipc_netlink_start(void) { int res; - res = genl_register_family_with_ops(&tipc_genl_family, tipc_genl_ops); - if (res) { - pr_err("Failed to register legacy interface\n"); - return res; - } - - res = genl_register_family_with_ops(&tipc_genl_v2_family, + res = genl_register_family_with_ops(&tipc_genl_family, tipc_genl_v2_ops); if (res) { pr_err("Failed to register netlink interface\n"); @@ -233,5 +175,4 @@ int tipc_netlink_start(void) void tipc_netlink_stop(void) { genl_unregister_family(&tipc_genl_family); - genl_unregister_family(&tipc_genl_v2_family); } diff --git a/net/tipc/netlink.h b/net/tipc/netlink.h index ae2f2d923a15..08a1db67b927 100644 --- a/net/tipc/netlink.h +++ b/net/tipc/netlink.h @@ -36,7 +36,7 @@ #ifndef _TIPC_NETLINK_H #define _TIPC_NETLINK_H -extern struct genl_family tipc_genl_v2_family; +extern struct genl_family tipc_genl_family; int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***buf); struct tipc_nl_msg { @@ -46,6 +46,8 @@ struct tipc_nl_msg { }; int tipc_netlink_start(void); +int tipc_netlink_compat_start(void); void tipc_netlink_stop(void); +void tipc_netlink_compat_stop(void); #endif diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c new file mode 100644 index 000000000000..f752854c8b10 --- /dev/null +++ b/net/tipc/netlink_compat.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2014, Ericsson AB + * 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 "config.h" +#include +#include + +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; +} + +static struct genl_family tipc_genl_compat_family = { + .id = GENL_ID_GENERATE, + .name = TIPC_GENL_NAME, + .version = TIPC_GENL_VERSION, + .hdrsize = TIPC_GENL_HDRLEN, + .maxattr = 0, + .netnsok = true, +}; + +static struct genl_ops tipc_genl_compat_ops[] = { + { + .cmd = TIPC_GENL_CMD, + .doit = handle_cmd, + }, +}; + +int tipc_netlink_compat_start(void) +{ + int res; + + res = genl_register_family_with_ops(&tipc_genl_compat_family, + tipc_genl_compat_ops); + if (res) { + pr_err("Failed to register legacy compat interface\n"); + return res; + } + + return 0; +} + +void tipc_netlink_compat_stop(void) +{ + genl_unregister_family(&tipc_genl_compat_family); +} diff --git a/net/tipc/node.c b/net/tipc/node.c index 52308498f208..995618d6da9d 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -623,7 +623,7 @@ static int __tipc_nl_add_node(struct tipc_nl_msg *msg, struct tipc_node *node) void *hdr; struct nlattr *attrs; - hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family, + hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, NLM_F_MULTI, TIPC_NL_NODE_GET); if (!hdr) return -EMSGSIZE; diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 4a98d15a1323..d76c171f7b7e 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -2783,7 +2783,7 @@ static int __tipc_nl_add_sk(struct sk_buff *skb, struct netlink_callback *cb, 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); + &tipc_genl_family, NLM_F_MULTI, TIPC_NL_SOCK_GET); if (!hdr) goto msg_cancel; @@ -2864,7 +2864,7 @@ static int __tipc_nl_add_sk_publ(struct sk_buff *skb, struct nlattr *attrs; hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, - &tipc_genl_v2_family, NLM_F_MULTI, TIPC_NL_PUBL_GET); + &tipc_genl_family, NLM_F_MULTI, TIPC_NL_PUBL_GET); if (!hdr) goto msg_cancel; -- cgit v1.2.3-70-g09d2 From 941787b82982b3f33ac398c8c00035ddd0f8c514 Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 9 Feb 2015 09:50:19 +0100 Subject: tipc: remove tipc_snprintf tipc_snprintf() was heavily utilized by the old netlink API which no longer exists (now netlink compat). In this patch we swap tipc_snprintf() to the identical scnprintf() in the only remaining occurrence. 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 | 6 +++--- net/tipc/core.h | 2 -- net/tipc/log.c | 54 ------------------------------------------------------ 4 files changed, 4 insertions(+), 60 deletions(-) delete mode 100644 net/tipc/log.c (limited to 'net/tipc/core.h') diff --git a/net/tipc/Makefile b/net/tipc/Makefile index 6864b9de2404..599b1a540d2b 100644 --- a/net/tipc/Makefile +++ b/net/tipc/Makefile @@ -7,7 +7,7 @@ obj-$(CONFIG_TIPC) := tipc.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 \ + netlink.o netlink_compat.o node.o socket.o eth_media.o \ server.o socket.o tipc-$(CONFIG_TIPC_MEDIA_IB) += ib_media.o diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 858c5a6c32df..48852c2dcc03 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -111,13 +111,13 @@ void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a) m_ptr = media_find_id(a->media_id); if (m_ptr && !m_ptr->addr2str(a, addr_str, sizeof(addr_str))) - ret = tipc_snprintf(buf, len, "%s(%s)", m_ptr->name, addr_str); + ret = scnprintf(buf, len, "%s(%s)", m_ptr->name, addr_str); else { u32 i; - ret = tipc_snprintf(buf, len, "UNKNOWN(%u)", a->media_id); + ret = scnprintf(buf, len, "UNKNOWN(%u)", a->media_id); for (i = 0; i < sizeof(a->value); i++) - ret += tipc_snprintf(buf - ret, len + ret, + ret += scnprintf(buf - ret, len + ret, "-%02x", a->value[i]); } } diff --git a/net/tipc/core.h b/net/tipc/core.h index 451c346fd3cf..3dc68c7a966d 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -70,8 +70,6 @@ #define TIPC_MOD_VER "2.0.0" -int tipc_snprintf(char *buf, int len, const char *fmt, ...); - extern int tipc_net_id __read_mostly; extern int sysctl_tipc_rmem[3] __read_mostly; extern int sysctl_tipc_named_timeout __read_mostly; diff --git a/net/tipc/log.c b/net/tipc/log.c deleted file mode 100644 index b186af06e361..000000000000 --- a/net/tipc/log.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * net/tipc/log.c: TIPC print buffer routines for debugging - * - * Copyright (c) 1996-2006, Ericsson AB - * Copyright (c) 2005-2007, 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" - -/** - * tipc_snprintf - append formatted output to print buffer - * @buf: pointer to print buffer - * @len: buffer length - * @fmt: formatted info to be printed - */ -int tipc_snprintf(char *buf, int len, const char *fmt, ...) -{ - int i; - va_list args; - - va_start(args, fmt); - i = vscnprintf(buf, len, fmt, args); - va_end(args); - return i; -} -- cgit v1.2.3-70-g09d2