Commit cb30a633 authored by Jon Maloy's avatar Jon Maloy Committed by David S. Miller

tipc: refactor function tipc_enable_bearer()

As a preparation for the next commits we try to reduce the footprint of
the function tipc_enable_bearer(), while hopefully making is simpler to
follow.
Acked-by: default avatarYing Xue <ying.xue@windriver.com>
Signed-off-by: default avatarJon Maloy <jon.maloy@ericsson.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 59461949
...@@ -230,88 +230,90 @@ void tipc_bearer_remove_dest(struct net *net, u32 bearer_id, u32 dest) ...@@ -230,88 +230,90 @@ void tipc_bearer_remove_dest(struct net *net, u32 bearer_id, u32 dest)
* tipc_enable_bearer - enable bearer with the given name * tipc_enable_bearer - enable bearer with the given name
*/ */
static int tipc_enable_bearer(struct net *net, const char *name, static int tipc_enable_bearer(struct net *net, const char *name,
u32 disc_domain, u32 priority, u32 disc_domain, u32 prio,
struct nlattr *attr[]) struct nlattr *attr[])
{ {
struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_net *tn = tipc_net(net);
struct tipc_bearer_names b_names;
u32 self = tipc_own_addr(net);
int with_this_prio = 1;
struct tipc_bearer *b; struct tipc_bearer *b;
struct tipc_media *m; struct tipc_media *m;
struct tipc_bearer_names b_names;
struct sk_buff *skb; struct sk_buff *skb;
char addr_string[16]; char addr_string[16];
u32 bearer_id; int bearer_id = 0;
u32 with_this_prio;
u32 i;
int res = -EINVAL; int res = -EINVAL;
char *errstr = "";
if (!tn->own_addr) { if (!self) {
pr_warn("Bearer <%s> rejected, not supported in standalone mode\n", errstr = "not supported in standalone mode";
name); res = -ENOPROTOOPT;
return -ENOPROTOOPT; goto rejected;
} }
if (!bearer_name_validate(name, &b_names)) { if (!bearer_name_validate(name, &b_names)) {
pr_warn("Bearer <%s> rejected, illegal name\n", name); errstr = "illegal name";
return -EINVAL; goto rejected;
}
if (tipc_addr_domain_valid(disc_domain) && disc_domain != self) {
if (tipc_in_scope(disc_domain, self)) {
/* Accept any node in own cluster */
disc_domain = self & TIPC_ZONE_CLUSTER_MASK;
res = 0;
} else if (in_own_cluster_exact(net, disc_domain)) {
/* Accept specified node in own cluster */
res = 0;
} }
if (tipc_addr_domain_valid(disc_domain) &&
(disc_domain != tn->own_addr)) {
if (tipc_in_scope(disc_domain, tn->own_addr)) {
disc_domain = tn->own_addr & TIPC_ZONE_CLUSTER_MASK;
res = 0; /* accept any node in own cluster */
} else if (in_own_cluster_exact(net, disc_domain))
res = 0; /* accept specified node in own cluster */
} }
if (res) { if (res) {
pr_warn("Bearer <%s> rejected, illegal discovery domain\n", errstr = "illegal discovery domain";
name); goto rejected;
return -EINVAL;
} }
if ((priority > TIPC_MAX_LINK_PRI) &&
(priority != TIPC_MEDIA_LINK_PRI)) { if (prio > TIPC_MAX_LINK_PRI && prio != TIPC_MEDIA_LINK_PRI) {
pr_warn("Bearer <%s> rejected, illegal priority\n", name); errstr = "illegal priority";
return -EINVAL; goto rejected;
} }
m = tipc_media_find(b_names.media_name); m = tipc_media_find(b_names.media_name);
if (!m) { if (!m) {
pr_warn("Bearer <%s> rejected, media <%s> not registered\n", errstr = "media not registered";
name, b_names.media_name); goto rejected;
return -EINVAL;
} }
if (priority == TIPC_MEDIA_LINK_PRI) if (prio == TIPC_MEDIA_LINK_PRI)
priority = m->priority; prio = m->priority;
restart: /* Check new bearer vs existing ones and find free bearer id if any */
bearer_id = MAX_BEARERS; while (bearer_id < MAX_BEARERS) {
with_this_prio = 1; b = rtnl_dereference(tn->bearer_list[bearer_id]);
for (i = MAX_BEARERS; i-- != 0; ) { if (!b)
b = rtnl_dereference(tn->bearer_list[i]); break;
if (!b) {
bearer_id = i;
continue;
}
if (!strcmp(name, b->name)) { if (!strcmp(name, b->name)) {
pr_warn("Bearer <%s> rejected, already enabled\n", errstr = "already enabled";
name); goto rejected;
return -EINVAL;
}
if ((b->priority == priority) &&
(++with_this_prio > 2)) {
if (priority-- == 0) {
pr_warn("Bearer <%s> rejected, duplicate priority\n",
name);
return -EINVAL;
} }
pr_warn("Bearer <%s> priority adjustment required %u->%u\n", bearer_id++;
name, priority + 1, priority); if (b->priority != prio)
goto restart; continue;
if (++with_this_prio <= 2)
continue;
pr_warn("Bearer <%s>: already 2 bearers with priority %u\n",
name, prio);
if (prio == TIPC_MIN_LINK_PRI) {
errstr = "cannot adjust to lower";
goto rejected;
} }
pr_warn("Bearer <%s>: trying with adjusted priority\n", name);
prio--;
bearer_id = 0;
with_this_prio = 1;
} }
if (bearer_id >= MAX_BEARERS) { if (bearer_id >= MAX_BEARERS) {
pr_warn("Bearer <%s> rejected, bearer limit reached (%u)\n", errstr = "max 3 bearers permitted";
name, MAX_BEARERS); goto rejected;
return -EINVAL;
} }
b = kzalloc(sizeof(*b), GFP_ATOMIC); b = kzalloc(sizeof(*b), GFP_ATOMIC);
...@@ -322,10 +324,9 @@ static int tipc_enable_bearer(struct net *net, const char *name, ...@@ -322,10 +324,9 @@ static int tipc_enable_bearer(struct net *net, const char *name,
b->media = m; b->media = m;
res = m->enable_media(net, b, attr); res = m->enable_media(net, b, attr);
if (res) { if (res) {
pr_warn("Bearer <%s> rejected, enable failure (%d)\n",
name, -res);
kfree(b); kfree(b);
return -EINVAL; errstr = "failed to enable media";
goto rejected;
} }
b->identity = bearer_id; b->identity = bearer_id;
...@@ -333,15 +334,15 @@ static int tipc_enable_bearer(struct net *net, const char *name, ...@@ -333,15 +334,15 @@ static int tipc_enable_bearer(struct net *net, const char *name,
b->window = m->window; b->window = m->window;
b->domain = disc_domain; b->domain = disc_domain;
b->net_plane = bearer_id + 'A'; b->net_plane = bearer_id + 'A';
b->priority = priority; b->priority = prio;
test_and_set_bit_lock(0, &b->up); test_and_set_bit_lock(0, &b->up);
res = tipc_disc_create(net, b, &b->bcast_addr, &skb); res = tipc_disc_create(net, b, &b->bcast_addr, &skb);
if (res) { if (res) {
bearer_disable(net, b); bearer_disable(net, b);
pr_warn("Bearer <%s> rejected, discovery object creation failed\n", kfree(b);
name); errstr = "failed to create discoverer";
return -EINVAL; goto rejected;
} }
rcu_assign_pointer(tn->bearer_list[bearer_id], b); rcu_assign_pointer(tn->bearer_list[bearer_id], b);
...@@ -353,9 +354,12 @@ static int tipc_enable_bearer(struct net *net, const char *name, ...@@ -353,9 +354,12 @@ static int tipc_enable_bearer(struct net *net, const char *name,
return -ENOMEM; return -ENOMEM;
} }
pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n", tipc_addr_string_fill(addr_string, disc_domain);
name, pr_info("Enabled bearer <%s>, discovery scope %s, priority %u\n",
tipc_addr_string_fill(addr_string, disc_domain), priority); name, addr_string, prio);
return res;
rejected:
pr_warn("Bearer <%s> rejected, %s\n", name, errstr);
return res; return res;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment