aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c84
1 files changed, 84 insertions, 0 deletions
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;