aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
authorJon Maloy <jon.maloy@ericsson.com>2017-10-13 05:04:28 -0400
committerDavid S. Miller <davem@davemloft.net>2017-10-13 11:46:00 -0400
commitee106d7f942dabce1352e01c6fe9ca4a720c2331 (patch)
tree411914c242c51f520229cb4506680be7b6c56872 /net/tipc/socket.c
parent27bd9ec027f396457d1a147043c92ff22fc4c71e (diff)
tipc: introduce group anycast messaging
In this commit, we make it possible to send connectionless unicast messages to any member corresponding to the given member identity, when there is more than one such member. The sender must use a TIPC_ADDR_NAME address to achieve this effect. We also perform load balancing between the destinations, i.e., we primarily select one which has advertised sufficient send window to not cause a block/EAGAIN delay, if any. This mechanism is overlayed on the always present round-robin selection. Anycast messages are subject to the same start synchronization and flow control mechanism as group broadcast messages. Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Acked-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
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;