diff options
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 84 |
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 | */ | ||
917 | static 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; |