Commit fdb533c3 authored by David S. Miller's avatar David S. Miller

Merge branch 'tipc-improvements-to-group-messaging'

Jon Maloy says:

====================
tipc: improvements to group messaging

We make a number of simplifications and improvements to the group
messaging service. They aim at readability/maintainability of the code
as well as scalability.

The series is based on commit f9c935db ("tipc: fix problems with
multipoint-to-point flow control) which has been applied to 'net' but
not yet to 'net-next'.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a67c01e2 eb929a91
...@@ -117,7 +117,6 @@ static inline unsigned int tipc_node(__u32 addr) ...@@ -117,7 +117,6 @@ static inline unsigned int tipc_node(__u32 addr)
/* /*
* Publication scopes when binding port names and port name sequences * Publication scopes when binding port names and port name sequences
*/ */
#define TIPC_ZONE_SCOPE 1 #define TIPC_ZONE_SCOPE 1
#define TIPC_CLUSTER_SCOPE 2 #define TIPC_CLUSTER_SCOPE 2
#define TIPC_NODE_SCOPE 3 #define TIPC_NODE_SCOPE 3
......
This diff is collapsed.
...@@ -44,8 +44,10 @@ struct tipc_msg; ...@@ -44,8 +44,10 @@ struct tipc_msg;
struct tipc_group *tipc_group_create(struct net *net, u32 portid, struct tipc_group *tipc_group_create(struct net *net, u32 portid,
struct tipc_group_req *mreq); struct tipc_group_req *mreq);
void tipc_group_join(struct net *net, struct tipc_group *grp, int *sk_rcv_buf);
void tipc_group_delete(struct net *net, struct tipc_group *grp); void tipc_group_delete(struct net *net, struct tipc_group *grp);
void tipc_group_add_member(struct tipc_group *grp, u32 node, u32 port); void tipc_group_add_member(struct tipc_group *grp, u32 node,
u32 port, u32 instance);
struct tipc_nlist *tipc_group_dests(struct tipc_group *grp); struct tipc_nlist *tipc_group_dests(struct tipc_group *grp);
void tipc_group_self(struct tipc_group *grp, struct tipc_name_seq *seq, void tipc_group_self(struct tipc_group *grp, struct tipc_name_seq *seq,
int *scope); int *scope);
...@@ -54,7 +56,7 @@ void tipc_group_filter_msg(struct tipc_group *grp, ...@@ -54,7 +56,7 @@ void tipc_group_filter_msg(struct tipc_group *grp,
struct sk_buff_head *inputq, struct sk_buff_head *inputq,
struct sk_buff_head *xmitq); struct sk_buff_head *xmitq);
void tipc_group_member_evt(struct tipc_group *grp, bool *wakeup, void tipc_group_member_evt(struct tipc_group *grp, bool *wakeup,
int *sk_rcvbuf, struct sk_buff *skb, int *sk_rcvbuf, struct tipc_msg *hdr,
struct sk_buff_head *inputq, struct sk_buff_head *inputq,
struct sk_buff_head *xmitq); struct sk_buff_head *xmitq);
void tipc_group_proto_rcv(struct tipc_group *grp, bool *wakeup, void tipc_group_proto_rcv(struct tipc_group *grp, bool *wakeup,
...@@ -65,9 +67,9 @@ void tipc_group_update_bc_members(struct tipc_group *grp, int len, bool ack); ...@@ -65,9 +67,9 @@ void tipc_group_update_bc_members(struct tipc_group *grp, int len, bool ack);
bool tipc_group_cong(struct tipc_group *grp, u32 dnode, u32 dport, bool tipc_group_cong(struct tipc_group *grp, u32 dnode, u32 dport,
int len, struct tipc_member **m); int len, struct tipc_member **m);
bool tipc_group_bc_cong(struct tipc_group *grp, int len); bool tipc_group_bc_cong(struct tipc_group *grp, int len);
bool tipc_group_is_open(struct tipc_group *grp);
void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node, void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node,
u32 port, struct sk_buff_head *xmitq); u32 port, struct sk_buff_head *xmitq);
u16 tipc_group_bc_snd_nxt(struct tipc_group *grp); u16 tipc_group_bc_snd_nxt(struct tipc_group *grp);
void tipc_group_update_member(struct tipc_member *m, int len); void tipc_group_update_member(struct tipc_member *m, int len);
int tipc_group_size(struct tipc_group *grp);
#endif #endif
...@@ -328,7 +328,8 @@ static struct publication *tipc_nameseq_insert_publ(struct net *net, ...@@ -328,7 +328,8 @@ static struct publication *tipc_nameseq_insert_publ(struct net *net,
list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
tipc_subscrp_report_overlap(s, publ->lower, publ->upper, tipc_subscrp_report_overlap(s, publ->lower, publ->upper,
TIPC_PUBLISHED, publ->ref, TIPC_PUBLISHED, publ->ref,
publ->node, created_subseq); publ->node, publ->scope,
created_subseq);
} }
return publ; return publ;
} }
...@@ -398,19 +399,21 @@ static struct publication *tipc_nameseq_remove_publ(struct net *net, ...@@ -398,19 +399,21 @@ static struct publication *tipc_nameseq_remove_publ(struct net *net,
list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
tipc_subscrp_report_overlap(s, publ->lower, publ->upper, tipc_subscrp_report_overlap(s, publ->lower, publ->upper,
TIPC_WITHDRAWN, publ->ref, TIPC_WITHDRAWN, publ->ref,
publ->node, removed_subseq); publ->node, publ->scope,
removed_subseq);
} }
return publ; return publ;
} }
/** /**
* tipc_nameseq_subscribe - attach a subscription, and issue * tipc_nameseq_subscribe - attach a subscription, and optionally
* the prescribed number of events if there is any sub- * issue the prescribed number of events if there is any sub-
* sequence overlapping with the requested sequence * sequence overlapping with the requested sequence
*/ */
static void tipc_nameseq_subscribe(struct name_seq *nseq, static void tipc_nameseq_subscribe(struct name_seq *nseq,
struct tipc_subscription *s) struct tipc_subscription *s,
bool status)
{ {
struct sub_seq *sseq = nseq->sseqs; struct sub_seq *sseq = nseq->sseqs;
struct tipc_name_seq ns; struct tipc_name_seq ns;
...@@ -420,7 +423,7 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, ...@@ -420,7 +423,7 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq,
tipc_subscrp_get(s); tipc_subscrp_get(s);
list_add(&s->nameseq_list, &nseq->subscriptions); list_add(&s->nameseq_list, &nseq->subscriptions);
if (!sseq) if (!status || !sseq)
return; return;
while (sseq != &nseq->sseqs[nseq->first_free]) { while (sseq != &nseq->sseqs[nseq->first_free]) {
...@@ -434,6 +437,7 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, ...@@ -434,6 +437,7 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq,
sseq->upper, sseq->upper,
TIPC_PUBLISHED, TIPC_PUBLISHED,
crs->ref, crs->node, crs->ref, crs->node,
crs->scope,
must_report); must_report);
must_report = 0; must_report = 0;
} }
...@@ -597,7 +601,7 @@ u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, ...@@ -597,7 +601,7 @@ u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance,
return ref; return ref;
} }
bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 domain, bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 scope,
struct list_head *dsts, int *dstcnt, u32 exclude, struct list_head *dsts, int *dstcnt, u32 exclude,
bool all) bool all)
{ {
...@@ -607,9 +611,6 @@ bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 domain, ...@@ -607,9 +611,6 @@ bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 domain,
struct name_seq *seq; struct name_seq *seq;
struct sub_seq *sseq; struct sub_seq *sseq;
if (!tipc_in_scope(domain, self))
return false;
*dstcnt = 0; *dstcnt = 0;
rcu_read_lock(); rcu_read_lock();
seq = nametbl_find_seq(net, type); seq = nametbl_find_seq(net, type);
...@@ -620,7 +621,7 @@ bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 domain, ...@@ -620,7 +621,7 @@ bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 domain,
if (likely(sseq)) { if (likely(sseq)) {
info = sseq->info; info = sseq->info;
list_for_each_entry(publ, &info->zone_list, zone_list) { list_for_each_entry(publ, &info->zone_list, zone_list) {
if (!tipc_in_scope(domain, publ->node)) if (publ->scope != scope)
continue; continue;
if (publ->ref == exclude && publ->node == self) if (publ->ref == exclude && publ->node == self)
continue; continue;
...@@ -638,13 +639,14 @@ bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 domain, ...@@ -638,13 +639,14 @@ bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 domain,
return !list_empty(dsts); return !list_empty(dsts);
} }
int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper, int tipc_nametbl_mc_lookup(struct net *net, u32 type, u32 lower, u32 upper,
u32 limit, struct list_head *dports) u32 scope, bool exact, struct list_head *dports)
{ {
struct name_seq *seq;
struct sub_seq *sseq;
struct sub_seq *sseq_stop; struct sub_seq *sseq_stop;
struct name_info *info; struct name_info *info;
struct publication *p;
struct name_seq *seq;
struct sub_seq *sseq;
int res = 0; int res = 0;
rcu_read_lock(); rcu_read_lock();
...@@ -656,15 +658,12 @@ int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper, ...@@ -656,15 +658,12 @@ int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper,
sseq = seq->sseqs + nameseq_locate_subseq(seq, lower); sseq = seq->sseqs + nameseq_locate_subseq(seq, lower);
sseq_stop = seq->sseqs + seq->first_free; sseq_stop = seq->sseqs + seq->first_free;
for (; sseq != sseq_stop; sseq++) { for (; sseq != sseq_stop; sseq++) {
struct publication *publ;
if (sseq->lower > upper) if (sseq->lower > upper)
break; break;
info = sseq->info; info = sseq->info;
list_for_each_entry(publ, &info->node_list, node_list) { list_for_each_entry(p, &info->node_list, node_list) {
if (publ->scope <= limit) if (p->scope == scope || (!exact && p->scope < scope))
tipc_dest_push(dports, 0, publ->ref); tipc_dest_push(dports, 0, p->ref);
} }
if (info->cluster_list_size != info->node_list_size) if (info->cluster_list_size != info->node_list_size)
...@@ -681,7 +680,7 @@ int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper, ...@@ -681,7 +680,7 @@ int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper,
* - Determines if any node local ports overlap * - Determines if any node local ports overlap
*/ */
void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower, void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower,
u32 upper, u32 domain, u32 upper, u32 scope,
struct tipc_nlist *nodes) struct tipc_nlist *nodes)
{ {
struct sub_seq *sseq, *stop; struct sub_seq *sseq, *stop;
...@@ -700,7 +699,7 @@ void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower, ...@@ -700,7 +699,7 @@ void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower,
for (; sseq != stop && sseq->lower <= upper; sseq++) { for (; sseq != stop && sseq->lower <= upper; sseq++) {
info = sseq->info; info = sseq->info;
list_for_each_entry(publ, &info->zone_list, zone_list) { list_for_each_entry(publ, &info->zone_list, zone_list) {
if (tipc_in_scope(domain, publ->node)) if (publ->scope == scope)
tipc_nlist_add(nodes, publ->node); tipc_nlist_add(nodes, publ->node);
} }
} }
...@@ -712,7 +711,7 @@ void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower, ...@@ -712,7 +711,7 @@ void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower,
/* tipc_nametbl_build_group - build list of communication group members /* tipc_nametbl_build_group - build list of communication group members
*/ */
void tipc_nametbl_build_group(struct net *net, struct tipc_group *grp, void tipc_nametbl_build_group(struct net *net, struct tipc_group *grp,
u32 type, u32 domain) u32 type, u32 scope)
{ {
struct sub_seq *sseq, *stop; struct sub_seq *sseq, *stop;
struct name_info *info; struct name_info *info;
...@@ -730,9 +729,9 @@ void tipc_nametbl_build_group(struct net *net, struct tipc_group *grp, ...@@ -730,9 +729,9 @@ void tipc_nametbl_build_group(struct net *net, struct tipc_group *grp,
for (; sseq != stop; sseq++) { for (; sseq != stop; sseq++) {
info = sseq->info; info = sseq->info;
list_for_each_entry(p, &info->zone_list, zone_list) { list_for_each_entry(p, &info->zone_list, zone_list) {
if (!tipc_in_scope(domain, p->node)) if (p->scope != scope)
continue; continue;
tipc_group_add_member(grp, p->node, p->ref); tipc_group_add_member(grp, p->node, p->ref, p->lower);
} }
} }
spin_unlock_bh(&seq->lock); spin_unlock_bh(&seq->lock);
...@@ -811,7 +810,7 @@ int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref, ...@@ -811,7 +810,7 @@ int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref,
/** /**
* tipc_nametbl_subscribe - add a subscription object to the name table * tipc_nametbl_subscribe - add a subscription object to the name table
*/ */
void tipc_nametbl_subscribe(struct tipc_subscription *s) void tipc_nametbl_subscribe(struct tipc_subscription *s, bool status)
{ {
struct tipc_net *tn = net_generic(s->net, tipc_net_id); struct tipc_net *tn = net_generic(s->net, tipc_net_id);
u32 type = tipc_subscrp_convert_seq_type(s->evt.s.seq.type, s->swap); u32 type = tipc_subscrp_convert_seq_type(s->evt.s.seq.type, s->swap);
...@@ -825,7 +824,7 @@ void tipc_nametbl_subscribe(struct tipc_subscription *s) ...@@ -825,7 +824,7 @@ void tipc_nametbl_subscribe(struct tipc_subscription *s)
seq = tipc_nameseq_create(type, &tn->nametbl->seq_hlist[index]); seq = tipc_nameseq_create(type, &tn->nametbl->seq_hlist[index]);
if (seq) { if (seq) {
spin_lock_bh(&seq->lock); spin_lock_bh(&seq->lock);
tipc_nameseq_subscribe(seq, s); tipc_nameseq_subscribe(seq, s, status);
spin_unlock_bh(&seq->lock); spin_unlock_bh(&seq->lock);
} else { } else {
tipc_subscrp_convert_seq(&s->evt.s.seq, s->swap, &ns); tipc_subscrp_convert_seq(&s->evt.s.seq, s->swap, &ns);
......
...@@ -100,8 +100,8 @@ struct name_table { ...@@ -100,8 +100,8 @@ struct name_table {
int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb); int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb);
u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *node); 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, int tipc_nametbl_mc_lookup(struct net *net, u32 type, u32 lower, u32 upper,
u32 limit, struct list_head *dports); u32 scope, bool exact, struct list_head *dports);
void tipc_nametbl_build_group(struct net *net, struct tipc_group *grp, void tipc_nametbl_build_group(struct net *net, struct tipc_group *grp,
u32 type, u32 domain); u32 type, u32 domain);
void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower, void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower,
...@@ -121,7 +121,7 @@ struct publication *tipc_nametbl_insert_publ(struct net *net, u32 type, ...@@ -121,7 +121,7 @@ struct publication *tipc_nametbl_insert_publ(struct net *net, u32 type,
struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type, struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type,
u32 lower, u32 node, u32 ref, u32 lower, u32 node, u32 ref,
u32 key); u32 key);
void tipc_nametbl_subscribe(struct tipc_subscription *s); void tipc_nametbl_subscribe(struct tipc_subscription *s, bool status);
void tipc_nametbl_unsubscribe(struct tipc_subscription *s); void tipc_nametbl_unsubscribe(struct tipc_subscription *s);
int tipc_nametbl_init(struct net *net); int tipc_nametbl_init(struct net *net);
void tipc_nametbl_stop(struct net *net); void tipc_nametbl_stop(struct net *net);
......
...@@ -489,8 +489,8 @@ void tipc_conn_terminate(struct tipc_server *s, int conid) ...@@ -489,8 +489,8 @@ void tipc_conn_terminate(struct tipc_server *s, int conid)
} }
} }
bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type, bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type, u32 lower,
u32 lower, u32 upper, int *conid) u32 upper, u32 filter, int *conid)
{ {
struct tipc_subscriber *scbr; struct tipc_subscriber *scbr;
struct tipc_subscr sub; struct tipc_subscr sub;
...@@ -501,7 +501,7 @@ bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type, ...@@ -501,7 +501,7 @@ bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type,
sub.seq.lower = lower; sub.seq.lower = lower;
sub.seq.upper = upper; sub.seq.upper = upper;
sub.timeout = TIPC_WAIT_FOREVER; sub.timeout = TIPC_WAIT_FOREVER;
sub.filter = TIPC_SUB_PORTS; sub.filter = filter;
*(u32 *)&sub.usr_handle = port; *(u32 *)&sub.usr_handle = port;
con = tipc_alloc_conn(tipc_topsrv(net)); con = tipc_alloc_conn(tipc_topsrv(net));
......
...@@ -41,6 +41,9 @@ ...@@ -41,6 +41,9 @@
#include <net/net_namespace.h> #include <net/net_namespace.h>
#define TIPC_SERVER_NAME_LEN 32 #define TIPC_SERVER_NAME_LEN 32
#define TIPC_SUB_CLUSTER_SCOPE 0x20
#define TIPC_SUB_NODE_SCOPE 0x40
#define TIPC_SUB_NO_STATUS 0x80
/** /**
* struct tipc_server - TIPC server structure * struct tipc_server - TIPC server structure
...@@ -83,8 +86,8 @@ struct tipc_server { ...@@ -83,8 +86,8 @@ struct tipc_server {
int tipc_conn_sendmsg(struct tipc_server *s, int conid, int tipc_conn_sendmsg(struct tipc_server *s, int conid,
struct sockaddr_tipc *addr, void *data, size_t len); struct sockaddr_tipc *addr, void *data, size_t len);
bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type, bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type, u32 lower,
u32 lower, u32 upper, int *conid); u32 upper, u32 filter, int *conid);
void tipc_topsrv_kern_unsubscr(struct net *net, int conid); void tipc_topsrv_kern_unsubscr(struct net *net, int conid);
/** /**
......
...@@ -715,7 +715,7 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock, ...@@ -715,7 +715,7 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct tipc_sock *tsk = tipc_sk(sk); struct tipc_sock *tsk = tipc_sk(sk);
struct tipc_group *grp = tsk->group; struct tipc_group *grp;
u32 revents = 0; u32 revents = 0;
sock_poll_wait(file, sk_sleep(sk), wait); sock_poll_wait(file, sk_sleep(sk), wait);
...@@ -736,8 +736,8 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock, ...@@ -736,8 +736,8 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
revents |= POLLIN | POLLRDNORM; revents |= POLLIN | POLLRDNORM;
break; break;
case TIPC_OPEN: case TIPC_OPEN:
if (!grp || tipc_group_size(grp)) grp = tsk->group;
if (!tsk->cong_link_cnt) if ((!grp || tipc_group_is_open(grp)) && !tsk->cong_link_cnt)
revents |= POLLOUT; revents |= POLLOUT;
if (!tipc_sk_type_connectionless(sk)) if (!tipc_sk_type_connectionless(sk))
break; break;
...@@ -928,21 +928,22 @@ static int tipc_send_group_anycast(struct socket *sock, struct msghdr *m, ...@@ -928,21 +928,22 @@ static int tipc_send_group_anycast(struct socket *sock, struct msghdr *m,
struct list_head *cong_links = &tsk->cong_links; struct list_head *cong_links = &tsk->cong_links;
int blks = tsk_blocks(GROUP_H_SIZE + dlen); int blks = tsk_blocks(GROUP_H_SIZE + dlen);
struct tipc_group *grp = tsk->group; struct tipc_group *grp = tsk->group;
struct tipc_msg *hdr = &tsk->phdr;
struct tipc_member *first = NULL; struct tipc_member *first = NULL;
struct tipc_member *mbr = NULL; struct tipc_member *mbr = NULL;
struct net *net = sock_net(sk); struct net *net = sock_net(sk);
u32 node, port, exclude; u32 node, port, exclude;
u32 type, inst, domain;
struct list_head dsts; struct list_head dsts;
u32 type, inst, scope;
int lookups = 0; int lookups = 0;
int dstcnt, rc; int dstcnt, rc;
bool cong; bool cong;
INIT_LIST_HEAD(&dsts); INIT_LIST_HEAD(&dsts);
type = dest->addr.name.name.type; type = msg_nametype(hdr);
inst = dest->addr.name.name.instance; inst = dest->addr.name.name.instance;
domain = addr_domain(net, dest->scope); scope = msg_lookup_scope(hdr);
exclude = tipc_group_exclude(grp); exclude = tipc_group_exclude(grp);
while (++lookups < 4) { while (++lookups < 4) {
...@@ -950,7 +951,7 @@ static int tipc_send_group_anycast(struct socket *sock, struct msghdr *m, ...@@ -950,7 +951,7 @@ static int tipc_send_group_anycast(struct socket *sock, struct msghdr *m,
/* Look for a non-congested destination member, if any */ /* Look for a non-congested destination member, if any */
while (1) { while (1) {
if (!tipc_nametbl_lookup(net, type, inst, domain, &dsts, if (!tipc_nametbl_lookup(net, type, inst, scope, &dsts,
&dstcnt, exclude, false)) &dstcnt, exclude, false))
return -EHOSTUNREACH; return -EHOSTUNREACH;
tipc_dest_pop(&dsts, &node, &port); tipc_dest_pop(&dsts, &node, &port);
...@@ -1079,22 +1080,23 @@ static int tipc_send_group_mcast(struct socket *sock, struct msghdr *m, ...@@ -1079,22 +1080,23 @@ static int tipc_send_group_mcast(struct socket *sock, struct msghdr *m,
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name);
struct tipc_name_seq *seq = &dest->addr.nameseq;
struct tipc_sock *tsk = tipc_sk(sk); struct tipc_sock *tsk = tipc_sk(sk);
struct tipc_group *grp = tsk->group; struct tipc_group *grp = tsk->group;
struct tipc_msg *hdr = &tsk->phdr;
struct net *net = sock_net(sk); struct net *net = sock_net(sk);
u32 domain, exclude, dstcnt; u32 type, inst, scope, exclude;
struct list_head dsts; struct list_head dsts;
u32 dstcnt;
INIT_LIST_HEAD(&dsts); INIT_LIST_HEAD(&dsts);
if (seq->lower != seq->upper) type = msg_nametype(hdr);
return -ENOTSUPP; inst = dest->addr.name.name.instance;
scope = msg_lookup_scope(hdr);
domain = addr_domain(net, dest->scope);
exclude = tipc_group_exclude(grp); exclude = tipc_group_exclude(grp);
if (!tipc_nametbl_lookup(net, seq->type, seq->lower, domain,
&dsts, &dstcnt, exclude, true)) if (!tipc_nametbl_lookup(net, type, inst, scope, &dsts,
&dstcnt, exclude, true))
return -EHOSTUNREACH; return -EHOSTUNREACH;
if (dstcnt == 1) { if (dstcnt == 1) {
...@@ -1116,24 +1118,29 @@ static int tipc_send_group_mcast(struct socket *sock, struct msghdr *m, ...@@ -1116,24 +1118,29 @@ static int tipc_send_group_mcast(struct socket *sock, struct msghdr *m,
void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
struct sk_buff_head *inputq) struct sk_buff_head *inputq)
{ {
u32 scope = TIPC_CLUSTER_SCOPE;
u32 self = tipc_own_addr(net); u32 self = tipc_own_addr(net);
u32 type, lower, upper, scope;
struct sk_buff *skb, *_skb; struct sk_buff *skb, *_skb;
u32 lower = 0, upper = ~0;
struct sk_buff_head tmpq;
u32 portid, oport, onode; u32 portid, oport, onode;
struct sk_buff_head tmpq;
struct list_head dports; struct list_head dports;
struct tipc_msg *msg; struct tipc_msg *hdr;
int user, mtyp, hsz; int user, mtyp, hlen;
bool exact;
__skb_queue_head_init(&tmpq); __skb_queue_head_init(&tmpq);
INIT_LIST_HEAD(&dports); INIT_LIST_HEAD(&dports);
skb = tipc_skb_peek(arrvq, &inputq->lock); skb = tipc_skb_peek(arrvq, &inputq->lock);
for (; skb; skb = tipc_skb_peek(arrvq, &inputq->lock)) { for (; skb; skb = tipc_skb_peek(arrvq, &inputq->lock)) {
msg = buf_msg(skb); hdr = buf_msg(skb);
user = msg_user(msg); user = msg_user(hdr);
mtyp = msg_type(msg); mtyp = msg_type(hdr);
hlen = skb_headroom(skb) + msg_hdr_sz(hdr);
oport = msg_origport(hdr);
onode = msg_orignode(hdr);
type = msg_nametype(hdr);
if (mtyp == TIPC_GRP_UCAST_MSG || user == GROUP_PROTOCOL) { if (mtyp == TIPC_GRP_UCAST_MSG || user == GROUP_PROTOCOL) {
spin_lock_bh(&inputq->lock); spin_lock_bh(&inputq->lock);
if (skb_peek(arrvq) == skb) { if (skb_peek(arrvq) == skb) {
...@@ -1144,21 +1151,31 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, ...@@ -1144,21 +1151,31 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
spin_unlock_bh(&inputq->lock); spin_unlock_bh(&inputq->lock);
continue; continue;
} }
hsz = skb_headroom(skb) + msg_hdr_sz(msg);
oport = msg_origport(msg); /* Group messages require exact scope match */
onode = msg_orignode(msg); if (msg_in_group(hdr)) {
lower = 0;
upper = ~0;
scope = msg_lookup_scope(hdr);
exact = true;
} else {
/* TIPC_NODE_SCOPE means "any scope" in this context */
if (onode == self) if (onode == self)
scope = TIPC_NODE_SCOPE; scope = TIPC_NODE_SCOPE;
else
/* Create destination port list and message clones: */ scope = TIPC_CLUSTER_SCOPE;
if (!msg_in_group(msg)) { exact = false;
lower = msg_namelower(msg); lower = msg_namelower(hdr);
upper = msg_nameupper(msg); upper = msg_nameupper(hdr);
} }
tipc_nametbl_mc_translate(net, msg_nametype(msg), lower, upper,
scope, &dports); /* Create destination port list: */
tipc_nametbl_mc_lookup(net, type, lower, upper,
scope, exact, &dports);
/* Clone message per destination */
while (tipc_dest_pop(&dports, NULL, &portid)) { while (tipc_dest_pop(&dports, NULL, &portid)) {
_skb = __pskb_copy(skb, hsz, GFP_ATOMIC); _skb = __pskb_copy(skb, hlen, GFP_ATOMIC);
if (_skb) { if (_skb) {
msg_set_destport(buf_msg(_skb), portid); msg_set_destport(buf_msg(_skb), portid);
__skb_queue_tail(&tmpq, _skb); __skb_queue_tail(&tmpq, _skb);
...@@ -1933,8 +1950,7 @@ static void tipc_sk_proto_rcv(struct sock *sk, ...@@ -1933,8 +1950,7 @@ static void tipc_sk_proto_rcv(struct sock *sk,
break; break;
case TOP_SRV: case TOP_SRV:
tipc_group_member_evt(tsk->group, &wakeup, &sk->sk_rcvbuf, tipc_group_member_evt(tsk->group, &wakeup, &sk->sk_rcvbuf,
skb, inputq, xmitq); hdr, inputq, xmitq);
skb = NULL;
break; break;
default: default:
break; break;
...@@ -2732,7 +2748,6 @@ void tipc_sk_rht_destroy(struct net *net) ...@@ -2732,7 +2748,6 @@ void tipc_sk_rht_destroy(struct net *net)
static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq) static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq)
{ {
struct net *net = sock_net(&tsk->sk); struct net *net = sock_net(&tsk->sk);
u32 domain = addr_domain(net, mreq->scope);
struct tipc_group *grp = tsk->group; struct tipc_group *grp = tsk->group;
struct tipc_msg *hdr = &tsk->phdr; struct tipc_msg *hdr = &tsk->phdr;
struct tipc_name_seq seq; struct tipc_name_seq seq;
...@@ -2740,6 +2755,8 @@ static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq) ...@@ -2740,6 +2755,8 @@ static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq)
if (mreq->type < TIPC_RESERVED_TYPES) if (mreq->type < TIPC_RESERVED_TYPES)
return -EACCES; return -EACCES;
if (mreq->scope > TIPC_NODE_SCOPE)
return -EINVAL;
if (grp) if (grp)
return -EACCES; return -EACCES;
grp = tipc_group_create(net, tsk->portid, mreq); grp = tipc_group_create(net, tsk->portid, mreq);
...@@ -2752,16 +2769,16 @@ static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq) ...@@ -2752,16 +2769,16 @@ static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq)
seq.type = mreq->type; seq.type = mreq->type;
seq.lower = mreq->instance; seq.lower = mreq->instance;
seq.upper = seq.lower; seq.upper = seq.lower;
tipc_nametbl_build_group(net, grp, mreq->type, domain); tipc_nametbl_build_group(net, grp, mreq->type, mreq->scope);
rc = tipc_sk_publish(tsk, mreq->scope, &seq); rc = tipc_sk_publish(tsk, mreq->scope, &seq);
if (rc) { if (rc) {
tipc_group_delete(net, grp); tipc_group_delete(net, grp);
tsk->group = NULL; tsk->group = NULL;
} }
/* Eliminate any risk that a broadcast overtakes sent JOINs */
/* Eliminate any risk that a broadcast overtakes the sent JOIN */
tsk->mc_method.rcast = true; tsk->mc_method.rcast = true;
tsk->mc_method.mandatory = true; tsk->mc_method.mandatory = true;
tipc_group_join(net, grp, &tsk->sk.sk_rcvbuf);
return rc; return rc;
} }
......
...@@ -118,15 +118,19 @@ void tipc_subscrp_convert_seq(struct tipc_name_seq *in, int swap, ...@@ -118,15 +118,19 @@ void tipc_subscrp_convert_seq(struct tipc_name_seq *in, int swap,
void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower, void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower,
u32 found_upper, u32 event, u32 port_ref, u32 found_upper, u32 event, u32 port_ref,
u32 node, int must) u32 node, u32 scope, int must)
{ {
u32 filter = htohl(sub->evt.s.filter, sub->swap);
struct tipc_name_seq seq; struct tipc_name_seq seq;
tipc_subscrp_convert_seq(&sub->evt.s.seq, sub->swap, &seq); tipc_subscrp_convert_seq(&sub->evt.s.seq, sub->swap, &seq);
if (!tipc_subscrp_check_overlap(&seq, found_lower, found_upper)) if (!tipc_subscrp_check_overlap(&seq, found_lower, found_upper))
return; return;
if (!must && if (!must && !(filter & TIPC_SUB_PORTS))
!(htohl(sub->evt.s.filter, sub->swap) & TIPC_SUB_PORTS)) return;
if (filter & TIPC_SUB_CLUSTER_SCOPE && scope == TIPC_NODE_SCOPE)
return;
if (filter & TIPC_SUB_NODE_SCOPE && scope != TIPC_NODE_SCOPE)
return; return;
tipc_subscrp_send_event(sub, found_lower, found_upper, event, port_ref, tipc_subscrp_send_event(sub, found_lower, found_upper, event, port_ref,
...@@ -286,7 +290,8 @@ static struct tipc_subscription *tipc_subscrp_create(struct net *net, ...@@ -286,7 +290,8 @@ static struct tipc_subscription *tipc_subscrp_create(struct net *net,
} }
static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s, static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s,
struct tipc_subscriber *subscriber, int swap) struct tipc_subscriber *subscriber, int swap,
bool status)
{ {
struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_net *tn = net_generic(net, tipc_net_id);
struct tipc_subscription *sub = NULL; struct tipc_subscription *sub = NULL;
...@@ -299,7 +304,7 @@ static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s, ...@@ -299,7 +304,7 @@ static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s,
spin_lock_bh(&subscriber->lock); spin_lock_bh(&subscriber->lock);
list_add(&sub->subscrp_list, &subscriber->subscrp_list); list_add(&sub->subscrp_list, &subscriber->subscrp_list);
sub->subscriber = subscriber; sub->subscriber = subscriber;
tipc_nametbl_subscribe(sub); tipc_nametbl_subscribe(sub, status);
tipc_subscrb_get(subscriber); tipc_subscrb_get(subscriber);
spin_unlock_bh(&subscriber->lock); spin_unlock_bh(&subscriber->lock);
...@@ -323,6 +328,7 @@ static void tipc_subscrb_rcv_cb(struct net *net, int conid, ...@@ -323,6 +328,7 @@ static void tipc_subscrb_rcv_cb(struct net *net, int conid,
{ {
struct tipc_subscriber *subscriber = usr_data; struct tipc_subscriber *subscriber = usr_data;
struct tipc_subscr *s = (struct tipc_subscr *)buf; struct tipc_subscr *s = (struct tipc_subscr *)buf;
bool status;
int swap; int swap;
/* Determine subscriber's endianness */ /* Determine subscriber's endianness */
...@@ -334,8 +340,8 @@ static void tipc_subscrb_rcv_cb(struct net *net, int conid, ...@@ -334,8 +340,8 @@ static void tipc_subscrb_rcv_cb(struct net *net, int conid,
s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); s->filter &= ~htohl(TIPC_SUB_CANCEL, swap);
return tipc_subscrp_cancel(s, subscriber); return tipc_subscrp_cancel(s, subscriber);
} }
status = !(s->filter & htohl(TIPC_SUB_NO_STATUS, swap));
tipc_subscrp_subscribe(net, s, subscriber, swap); tipc_subscrp_subscribe(net, s, subscriber, swap, status);
} }
/* Handle one request to establish a new subscriber */ /* Handle one request to establish a new subscriber */
......
...@@ -71,7 +71,7 @@ int tipc_subscrp_check_overlap(struct tipc_name_seq *seq, u32 found_lower, ...@@ -71,7 +71,7 @@ int tipc_subscrp_check_overlap(struct tipc_name_seq *seq, u32 found_lower,
u32 found_upper); u32 found_upper);
void tipc_subscrp_report_overlap(struct tipc_subscription *sub, void tipc_subscrp_report_overlap(struct tipc_subscription *sub,
u32 found_lower, u32 found_upper, u32 event, u32 found_lower, u32 found_upper, u32 event,
u32 port_ref, u32 node, int must); u32 port_ref, u32 node, u32 scope, int must);
void tipc_subscrp_convert_seq(struct tipc_name_seq *in, int swap, void tipc_subscrp_convert_seq(struct tipc_name_seq *in, int swap,
struct tipc_name_seq *out); struct tipc_name_seq *out);
u32 tipc_subscrp_convert_seq_type(u32 type, int swap); u32 tipc_subscrp_convert_seq_type(u32 type, int swap);
......
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