summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/tipc/name_table.c42
-rw-r--r--net/tipc/name_table.h2
-rw-r--r--net/tipc/server.c25
-rw-r--r--net/tipc/subscr.c83
-rw-r--r--net/tipc/subscr.h36
5 files changed, 86 insertions, 102 deletions
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index c0ca7be46f7a..2fbd0a20a958 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -412,18 +412,22 @@ found:
* sequence overlapping with the requested sequence
*/
static void tipc_nameseq_subscribe(struct name_seq *nseq,
- struct tipc_subscription *s,
- bool status)
+ struct tipc_subscription *sub)
{
struct sub_seq *sseq = nseq->sseqs;
struct tipc_name_seq ns;
+ struct tipc_subscr *s = &sub->evt.s;
+ bool no_status;
- tipc_subscrp_convert_seq(&s->evt.s.seq, s->swap, &ns);
+ ns.type = tipc_sub_read(s, seq.type);
+ ns.lower = tipc_sub_read(s, seq.lower);
+ ns.upper = tipc_sub_read(s, seq.upper);
+ no_status = tipc_sub_read(s, filter) & TIPC_SUB_NO_STATUS;
- tipc_subscrp_get(s);
- list_add(&s->nameseq_list, &nseq->subscriptions);
+ tipc_subscrp_get(sub);
+ list_add(&sub->nameseq_list, &nseq->subscriptions);
- if (!status || !sseq)
+ if (no_status || !sseq)
return;
while (sseq != &nseq->sseqs[nseq->first_free]) {
@@ -433,7 +437,7 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq,
int must_report = 1;
list_for_each_entry(crs, &info->zone_list, zone_list) {
- tipc_subscrp_report_overlap(s, sseq->lower,
+ tipc_subscrp_report_overlap(sub, sseq->lower,
sseq->upper,
TIPC_PUBLISHED,
crs->ref, crs->node,
@@ -808,11 +812,12 @@ int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref,
/**
* tipc_nametbl_subscribe - add a subscription object to the name table
*/
-void tipc_nametbl_subscribe(struct tipc_subscription *s, bool status)
+void tipc_nametbl_subscribe(struct tipc_subscription *sub)
{
- struct tipc_server *srv = s->server;
+ struct tipc_server *srv = sub->server;
struct tipc_net *tn = tipc_net(srv->net);
- u32 type = tipc_subscrp_convert_seq_type(s->evt.s.seq.type, s->swap);
+ struct tipc_subscr *s = &sub->evt.s;
+ u32 type = tipc_sub_read(s, seq.type);
int index = hash(type);
struct name_seq *seq;
struct tipc_name_seq ns;
@@ -823,10 +828,12 @@ void tipc_nametbl_subscribe(struct tipc_subscription *s, bool status)
seq = tipc_nameseq_create(type, &tn->nametbl->seq_hlist[index]);
if (seq) {
spin_lock_bh(&seq->lock);
- tipc_nameseq_subscribe(seq, s, status);
+ tipc_nameseq_subscribe(seq, sub);
spin_unlock_bh(&seq->lock);
} else {
- tipc_subscrp_convert_seq(&s->evt.s.seq, s->swap, &ns);
+ ns.type = tipc_sub_read(s, seq.type);
+ ns.lower = tipc_sub_read(s, seq.lower);
+ ns.upper = tipc_sub_read(s, seq.upper);
pr_warn("Failed to create subscription for {%u,%u,%u}\n",
ns.type, ns.lower, ns.upper);
}
@@ -836,19 +843,20 @@ void tipc_nametbl_subscribe(struct tipc_subscription *s, bool status)
/**
* tipc_nametbl_unsubscribe - remove a subscription object from name table
*/
-void tipc_nametbl_unsubscribe(struct tipc_subscription *s)
+void tipc_nametbl_unsubscribe(struct tipc_subscription *sub)
{
- struct tipc_server *srv = s->server;
+ struct tipc_server *srv = sub->server;
+ struct tipc_subscr *s = &sub->evt.s;
struct tipc_net *tn = tipc_net(srv->net);
struct name_seq *seq;
- u32 type = tipc_subscrp_convert_seq_type(s->evt.s.seq.type, s->swap);
+ u32 type = tipc_sub_read(s, seq.type);
spin_lock_bh(&tn->nametbl_lock);
seq = nametbl_find_seq(srv->net, type);
if (seq != NULL) {
spin_lock_bh(&seq->lock);
- list_del_init(&s->nameseq_list);
- tipc_subscrp_put(s);
+ list_del_init(&sub->nameseq_list);
+ tipc_subscrp_put(sub);
if (!seq->first_free && list_empty(&seq->subscriptions)) {
hlist_del_init_rcu(&seq->ns_list);
kfree(seq->sseqs);
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
index f56e7cb3d436..17652602d5e2 100644
--- a/net/tipc/name_table.h
+++ b/net/tipc/name_table.h
@@ -120,7 +120,7 @@ struct publication *tipc_nametbl_insert_publ(struct net *net, u32 type,
struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type,
u32 lower, u32 node, u32 ref,
u32 key);
-void tipc_nametbl_subscribe(struct tipc_subscription *s, bool status);
+void tipc_nametbl_subscribe(struct tipc_subscription *s);
void tipc_nametbl_unsubscribe(struct tipc_subscription *s);
int tipc_nametbl_init(struct net *net);
void tipc_nametbl_stop(struct net *net);
diff --git a/net/tipc/server.c b/net/tipc/server.c
index 7933fb92d852..5d231fa8e4b5 100644
--- a/net/tipc/server.c
+++ b/net/tipc/server.c
@@ -98,18 +98,6 @@ static bool connected(struct tipc_conn *con)
return con && test_bit(CF_CONNECTED, &con->flags);
}
-/**
- * htohl - convert value to endianness used by destination
- * @in: value to convert
- * @swap: non-zero if endianness must be reversed
- *
- * Returns converted value
- */
-static u32 htohl(u32 in, int swap)
-{
- return swap ? swab32(in) : in;
-}
-
static void tipc_conn_kref_release(struct kref *kref)
{
struct tipc_conn *con = container_of(kref, struct tipc_conn, kref);
@@ -285,21 +273,12 @@ static int tipc_con_rcv_sub(struct tipc_server *srv,
struct tipc_subscr *s)
{
struct tipc_subscription *sub;
- bool status;
- int swap;
-
- /* Determine subscriber's endianness */
- swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE |
- TIPC_SUB_CANCEL));
- /* Detect & process a subscription cancellation request */
- if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) {
- s->filter &= ~htohl(TIPC_SUB_CANCEL, swap);
+ if (tipc_sub_read(s, filter) & TIPC_SUB_CANCEL) {
tipc_con_delete_sub(con, s);
return 0;
}
- status = !(s->filter & htohl(TIPC_SUB_NO_STATUS, swap));
- sub = tipc_subscrp_subscribe(srv, s, con->conid, swap, status);
+ sub = tipc_subscrp_subscribe(srv, s, con->conid);
if (!sub)
return -1;
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index c3e0b924e8c2..406b09fc227b 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -38,32 +38,19 @@
#include "name_table.h"
#include "subscr.h"
-/**
- * htohl - convert value to endianness used by destination
- * @in: value to convert
- * @swap: non-zero if endianness must be reversed
- *
- * Returns converted value
- */
-static u32 htohl(u32 in, int swap)
-{
- return swap ? swab32(in) : in;
-}
-
static void tipc_subscrp_send_event(struct tipc_subscription *sub,
u32 found_lower, u32 found_upper,
u32 event, u32 port, u32 node)
{
struct tipc_event *evt = &sub->evt;
- bool swap = sub->swap;
if (sub->inactive)
return;
- evt->event = htohl(event, swap);
- evt->found_lower = htohl(found_lower, swap);
- evt->found_upper = htohl(found_upper, swap);
- evt->port.ref = htohl(port, swap);
- evt->port.node = htohl(node, swap);
+ tipc_evt_write(evt, event, event);
+ tipc_evt_write(evt, found_lower, found_lower);
+ tipc_evt_write(evt, found_upper, found_upper);
+ tipc_evt_write(evt, port.ref, port);
+ tipc_evt_write(evt, port.node, node);
tipc_conn_queue_evt(sub->server, sub->conid, event, evt);
}
@@ -85,29 +72,22 @@ int tipc_subscrp_check_overlap(struct tipc_name_seq *seq, u32 found_lower,
return 1;
}
-u32 tipc_subscrp_convert_seq_type(u32 type, int swap)
+void tipc_subscrp_report_overlap(struct tipc_subscription *sub,
+ u32 found_lower, u32 found_upper,
+ u32 event, u32 port, u32 node,
+ u32 scope, int must)
{
- return htohl(type, swap);
-}
-
-void tipc_subscrp_convert_seq(struct tipc_name_seq *in, int swap,
- struct tipc_name_seq *out)
-{
- out->type = htohl(in->type, swap);
- out->lower = htohl(in->lower, swap);
- out->upper = htohl(in->upper, swap);
-}
-
-void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower,
- u32 found_upper, u32 event, u32 port_ref,
- u32 node, u32 scope, int must)
-{
- u32 filter = htohl(sub->evt.s.filter, sub->swap);
struct tipc_name_seq seq;
+ struct tipc_subscr *s = &sub->evt.s;
+ u32 filter = tipc_sub_read(s, filter);
+
+ seq.type = tipc_sub_read(s, seq.type);
+ seq.lower = tipc_sub_read(s, seq.lower);
+ seq.upper = tipc_sub_read(s, seq.upper);
- tipc_subscrp_convert_seq(&sub->evt.s.seq, sub->swap, &seq);
if (!tipc_subscrp_check_overlap(&seq, found_lower, found_upper))
return;
+
if (!must && !(filter & TIPC_SUB_PORTS))
return;
if (filter & TIPC_SUB_CLUSTER_SCOPE && scope == TIPC_NODE_SCOPE)
@@ -116,7 +96,7 @@ void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower,
return;
spin_lock(&sub->lock);
tipc_subscrp_send_event(sub, found_lower, found_upper,
- event, port_ref, node);
+ event, port, node);
spin_unlock(&sub->lock);
}
@@ -156,11 +136,11 @@ void tipc_subscrp_get(struct tipc_subscription *subscription)
static struct tipc_subscription *tipc_subscrp_create(struct tipc_server *srv,
struct tipc_subscr *s,
- int conid, bool swap)
+ int conid)
{
struct tipc_net *tn = tipc_net(srv->net);
struct tipc_subscription *sub;
- u32 filter = htohl(s->filter, swap);
+ u32 filter = tipc_sub_read(s, filter);
/* Refuse subscription if global limit exceeded */
if (atomic_read(&tn->subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) {
@@ -177,39 +157,38 @@ static struct tipc_subscription *tipc_subscrp_create(struct tipc_server *srv,
}
/* Initialize subscription object */
+ if (filter & TIPC_SUB_PORTS && filter & TIPC_SUB_SERVICE)
+ goto err;
+ if (tipc_sub_read(s, seq.lower) > tipc_sub_read(s, seq.upper))
+ goto err;
sub->server = srv;
sub->conid = conid;
sub->inactive = false;
- if (((filter & TIPC_SUB_PORTS) && (filter & TIPC_SUB_SERVICE)) ||
- (htohl(s->seq.lower, swap) > htohl(s->seq.upper, swap))) {
- pr_warn("Subscription rejected, illegal request\n");
- kfree(sub);
- return NULL;
- }
-
- sub->swap = swap;
memcpy(&sub->evt.s, s, sizeof(*s));
spin_lock_init(&sub->lock);
atomic_inc(&tn->subscription_count);
kref_init(&sub->kref);
return sub;
+err:
+ pr_warn("Subscription rejected, illegal request\n");
+ kfree(sub);
+ return NULL;
}
struct tipc_subscription *tipc_subscrp_subscribe(struct tipc_server *srv,
struct tipc_subscr *s,
- int conid, bool swap,
- bool status)
+ int conid)
{
struct tipc_subscription *sub = NULL;
u32 timeout;
- sub = tipc_subscrp_create(srv, s, conid, swap);
+ sub = tipc_subscrp_create(srv, s, conid);
if (!sub)
return NULL;
- tipc_nametbl_subscribe(sub, status);
+ tipc_nametbl_subscribe(sub);
timer_setup(&sub->timer, tipc_subscrp_timeout, 0);
- timeout = htohl(sub->evt.s.timeout, swap);
+ timeout = tipc_sub_read(&sub->evt.s, timeout);
if (timeout != TIPC_WAIT_FOREVER)
mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout));
return sub;
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h
index 64ffd32d15e6..db80e41bba08 100644
--- a/net/tipc/subscr.h
+++ b/net/tipc/subscr.h
@@ -52,7 +52,6 @@ struct tipc_conn;
* @timer: timer governing subscription duration (optional)
* @nameseq_list: adjacent subscriptions in name sequence's subscription list
* @subscrp_list: adjacent subscriptions in subscriber's subscription list
- * @swap: indicates if subscriber uses opposite endianness in its messages
* @evt: template for events generated by subscription
*/
struct tipc_subscription {
@@ -63,28 +62,47 @@ struct tipc_subscription {
struct list_head subscrp_list;
struct tipc_event evt;
int conid;
- bool swap;
bool inactive;
spinlock_t lock; /* serialize up/down and timer events */
};
struct tipc_subscription *tipc_subscrp_subscribe(struct tipc_server *srv,
struct tipc_subscr *s,
- int conid, bool swap,
- bool status);
+ int conid);
void tipc_sub_delete(struct tipc_subscription *sub);
+
int tipc_subscrp_check_overlap(struct tipc_name_seq *seq, u32 found_lower,
u32 found_upper);
void tipc_subscrp_report_overlap(struct tipc_subscription *sub,
- u32 found_lower, u32 found_upper, u32 event,
- u32 port_ref, u32 node, u32 scope, int must);
-void tipc_subscrp_convert_seq(struct tipc_name_seq *in, int swap,
- struct tipc_name_seq *out);
-u32 tipc_subscrp_convert_seq_type(u32 type, int swap);
+ u32 found_lower, u32 found_upper,
+ u32 event, u32 port, u32 node,
+ u32 scope, int must);
int tipc_topsrv_start(struct net *net);
void tipc_topsrv_stop(struct net *net);
void tipc_subscrp_put(struct tipc_subscription *subscription);
void tipc_subscrp_get(struct tipc_subscription *subscription);
+#define TIPC_FILTER_MASK (TIPC_SUB_PORTS | TIPC_SUB_SERVICE | TIPC_SUB_CANCEL)
+
+/* tipc_sub_read - return field_ of struct sub_ in host endian format
+ */
+#define tipc_sub_read(sub_, field_) \
+ ({ \
+ struct tipc_subscr *sub__ = sub_; \
+ u32 val__ = (sub__)->field_; \
+ int swap_ = !((sub__)->filter & TIPC_FILTER_MASK); \
+ (swap_ ? swab32(val__) : val__); \
+ })
+
+/* tipc_evt_write - write val_ to field_ of struct evt_ in user endian format
+ */
+#define tipc_evt_write(evt_, field_, val_) \
+ ({ \
+ struct tipc_event *evt__ = evt_; \
+ u32 val__ = val_; \
+ int swap_ = !((evt__)->s.filter & (TIPC_FILTER_MASK)); \
+ (evt__)->field_ = swap_ ? swab32(val__) : val__; \
+ })
+
#endif