aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/group.c7
-rw-r--r--net/tipc/group.h3
-rw-r--r--net/tipc/name_table.c41
-rw-r--r--net/tipc/name_table.h3
-rw-r--r--net/tipc/socket.c84
5 files changed, 138 insertions, 0 deletions
diff --git a/net/tipc/group.c b/net/tipc/group.c
index 18440be5b5fc..16aaaa97a005 100644
--- a/net/tipc/group.c
+++ b/net/tipc/group.c
@@ -116,6 +116,13 @@ static bool tipc_group_is_receiver(struct tipc_member *m)
116 return m && m->state >= MBR_JOINED; 116 return m && m->state >= MBR_JOINED;
117} 117}
118 118
119u32 tipc_group_exclude(struct tipc_group *grp)
120{
121 if (!grp->loopback)
122 return grp->portid;
123 return 0;
124}
125
119int tipc_group_size(struct tipc_group *grp) 126int tipc_group_size(struct tipc_group *grp)
120{ 127{
121 return grp->member_cnt; 128 return grp->member_cnt;
diff --git a/net/tipc/group.h b/net/tipc/group.h
index 8f77290bb415..e432066a211e 100644
--- a/net/tipc/group.h
+++ b/net/tipc/group.h
@@ -49,6 +49,7 @@ void tipc_group_add_member(struct tipc_group *grp, u32 node, u32 port);
49struct tipc_nlist *tipc_group_dests(struct tipc_group *grp); 49struct tipc_nlist *tipc_group_dests(struct tipc_group *grp);
50void tipc_group_self(struct tipc_group *grp, struct tipc_name_seq *seq, 50void tipc_group_self(struct tipc_group *grp, struct tipc_name_seq *seq,
51 int *scope); 51 int *scope);
52u32 tipc_group_exclude(struct tipc_group *grp);
52void tipc_group_filter_msg(struct tipc_group *grp, 53void tipc_group_filter_msg(struct tipc_group *grp,
53 struct sk_buff_head *inputq, 54 struct sk_buff_head *inputq,
54 struct sk_buff_head *xmitq); 55 struct sk_buff_head *xmitq);
@@ -68,5 +69,7 @@ void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node,
68 u32 port, struct sk_buff_head *xmitq); 69 u32 port, struct sk_buff_head *xmitq);
69u16 tipc_group_bc_snd_nxt(struct tipc_group *grp); 70u16 tipc_group_bc_snd_nxt(struct tipc_group *grp);
70void tipc_group_update_member(struct tipc_member *m, int len); 71void tipc_group_update_member(struct tipc_member *m, int len);
72struct tipc_member *tipc_group_find_sender(struct tipc_group *grp,
73 u32 node, u32 port);
71int tipc_group_size(struct tipc_group *grp); 74int tipc_group_size(struct tipc_group *grp);
72#endif 75#endif
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 114d72bab827..2856e19e036e 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -597,6 +597,47 @@ not_found:
597 return ref; 597 return ref;
598} 598}
599 599
600bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 domain,
601 struct list_head *dsts, int *dstcnt, u32 exclude,
602 bool all)
603{
604 u32 self = tipc_own_addr(net);
605 struct publication *publ;
606 struct name_info *info;
607 struct name_seq *seq;
608 struct sub_seq *sseq;
609
610 if (!tipc_in_scope(domain, self))
611 return false;
612
613 *dstcnt = 0;
614 rcu_read_lock();
615 seq = nametbl_find_seq(net, type);
616 if (unlikely(!seq))
617 goto exit;
618 spin_lock_bh(&seq->lock);
619 sseq = nameseq_find_subseq(seq, instance);
620 if (likely(sseq)) {
621 info = sseq->info;
622 list_for_each_entry(publ, &info->zone_list, zone_list) {
623 if (!tipc_in_scope(domain, publ->node))
624 continue;
625 if (publ->ref == exclude && publ->node == self)
626 continue;
627 tipc_dest_push(dsts, publ->node, publ->ref);
628 (*dstcnt)++;
629 if (all)
630 continue;
631 list_move_tail(&publ->zone_list, &info->zone_list);
632 break;
633 }
634 }
635 spin_unlock_bh(&seq->lock);
636exit:
637 rcu_read_unlock();
638 return !list_empty(dsts);
639}
640
600int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper, 641int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper,
601 u32 limit, struct list_head *dports) 642 u32 limit, struct list_head *dports)
602{ 643{
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
index 97646b17a4a2..71926e429446 100644
--- a/net/tipc/name_table.h
+++ b/net/tipc/name_table.h
@@ -107,6 +107,9 @@ void tipc_nametbl_build_group(struct net *net, struct tipc_group *grp,
107void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower, 107void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower,
108 u32 upper, u32 domain, 108 u32 upper, u32 domain,
109 struct tipc_nlist *nodes); 109 struct tipc_nlist *nodes);
110bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 domain,
111 struct list_head *dsts, int *dstcnt, u32 exclude,
112 bool all);
110struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower, 113struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower,
111 u32 upper, u32 scope, u32 port_ref, 114 u32 upper, u32 scope, u32 port_ref,
112 u32 key); 115 u32 key);
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index e71c8d23acb9..66165e12d2f4 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -905,6 +905,88 @@ static int tipc_send_group_unicast(struct socket *sock, struct msghdr *m,
905} 905}
906 906
907/** 907/**
908 * tipc_send_group_anycast - send message to any member with given identity
909 * @sock: socket structure
910 * @m: message to send
911 * @dlen: total length of message data
912 * @timeout: timeout to wait for wakeup
913 *
914 * Called from function tipc_sendmsg(), which has done all sanity checks
915 * Returns the number of bytes sent on success, or errno
916 */
917static int tipc_send_group_anycast(struct socket *sock, struct msghdr *m,
918 int dlen, long timeout)
919{
920 DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name);
921 struct sock *sk = sock->sk;
922 struct tipc_sock *tsk = tipc_sk(sk);
923 struct list_head *cong_links = &tsk->cong_links;
924 int blks = tsk_blocks(GROUP_H_SIZE + dlen);
925 struct tipc_group *grp = tsk->group;
926 struct tipc_member *first = NULL;
927 struct tipc_member *mbr = NULL;
928 struct net *net = sock_net(sk);
929 u32 node, port, exclude;
930 u32 type, inst, domain;
931 struct list_head dsts;
932 int lookups = 0;
933 int dstcnt, rc;
934 bool cong;
935
936 INIT_LIST_HEAD(&dsts);
937
938 type = dest->addr.name.name.type;
939 inst = dest->addr.name.name.instance;
940 domain = addr_domain(net, dest->scope);
941 exclude = tipc_group_exclude(grp);
942
943 while (++lookups < 4) {
944 first = NULL;
945
946 /* Look for a non-congested destination member, if any */
947 while (1) {
948 if (!tipc_nametbl_lookup(net, type, inst, domain, &dsts,
949 &dstcnt, exclude, false))
950 return -EHOSTUNREACH;
951 tipc_dest_pop(&dsts, &node, &port);
952 cong = tipc_group_cong(grp, node, port, blks, &mbr);
953 if (!cong)
954 break;
955 if (mbr == first)
956 break;
957 if (!first)
958 first = mbr;
959 }
960
961 /* Start over if destination was not in member list */
962 if (unlikely(!mbr))
963 continue;
964
965 if (likely(!cong && !tipc_dest_find(cong_links, node, 0)))
966 break;
967
968 /* Block or return if destination link or member is congested */
969 rc = tipc_wait_for_cond(sock, &timeout,
970 !tipc_dest_find(cong_links, node, 0) &&
971 !tipc_group_cong(grp, node, port,
972 blks, &mbr));
973 if (unlikely(rc))
974 return rc;
975
976 /* Send, unless destination disappeared while waiting */
977 if (likely(mbr))
978 break;
979 }
980
981 if (unlikely(lookups >= 4))
982 return -EHOSTUNREACH;
983
984 rc = tipc_send_group_msg(net, tsk, m, mbr, node, port, dlen);
985
986 return rc ? rc : dlen;
987}
988
989/**
908 * tipc_send_group_bcast - send message to all members in communication group 990 * tipc_send_group_bcast - send message to all members in communication group
909 * @sk: socket structure 991 * @sk: socket structure
910 * @m: message to send 992 * @m: message to send
@@ -1127,6 +1209,8 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
1127 if (grp) { 1209 if (grp) {
1128 if (!dest) 1210 if (!dest)
1129 return tipc_send_group_bcast(sock, m, dlen, timeout); 1211 return tipc_send_group_bcast(sock, m, dlen, timeout);
1212 if (dest->addrtype == TIPC_ADDR_NAME)
1213 return tipc_send_group_anycast(sock, m, dlen, timeout);
1130 if (dest->addrtype == TIPC_ADDR_ID) 1214 if (dest->addrtype == TIPC_ADDR_ID)
1131 return tipc_send_group_unicast(sock, m, dlen, timeout); 1215 return tipc_send_group_unicast(sock, m, dlen, timeout);
1132 return -EINVAL; 1216 return -EINVAL;