Skip to content

Commit

Permalink
tipc: make bearer list support net namespace
Browse files Browse the repository at this point in the history
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 <ying.xue@windriver.com>
Tested-by: Tero Aho <Tero.Aho@coriant.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ying Xue authored and David S. Miller committed Jan 12, 2015
1 parent f2f9800 commit 7f9f95d
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 73 deletions.
27 changes: 17 additions & 10 deletions net/tipc/bcast.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down
7 changes: 4 additions & 3 deletions net/tipc/bcast.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
67 changes: 39 additions & 28 deletions net/tipc/bearer.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/

#include <net/sock.h>
#include "core.h"
#include "config.h"
#include "bearer.h"
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
Expand All @@ -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]) {
Expand All @@ -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();
Expand All @@ -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;
Expand Down Expand Up @@ -315,7 +319,7 @@ int tipc_enable_bearer(struct net *net, const char *name, u32 disc_domain,
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;
Expand Down Expand Up @@ -349,7 +353,7 @@ int tipc_enable_bearer(struct net *net, const char *name, u32 disc_domain,

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);
Expand All @@ -371,7 +375,7 @@ int tipc_enable_bearer(struct net *net, const char *name, u32 disc_domain,
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,
Expand All @@ -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);
Expand All @@ -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;
}
}
Expand All @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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;
}
}
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
Loading

0 comments on commit 7f9f95d

Please sign in to comment.