Skip to content

Commit 27bd9ec

Browse files
Jon Maloydavem330
authored andcommitted
tipc: introduce group unicast messaging
We now make it possible to send connectionless unicast messages within a communication group. To send a message, the sender can use either a direct port address, aka port identity, or an indirect port name to be looked up. This type of 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>
1 parent b7d4263 commit 27bd9ec

4 files changed

Lines changed: 150 additions & 13 deletions

File tree

net/tipc/group.c

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,17 @@ struct tipc_member *tipc_group_find_member(struct tipc_group *grp,
186186
return NULL;
187187
}
188188

189+
static struct tipc_member *tipc_group_find_dest(struct tipc_group *grp,
190+
u32 node, u32 port)
191+
{
192+
struct tipc_member *m;
193+
194+
m = tipc_group_find_member(grp, node, port);
195+
if (m && tipc_group_is_enabled(m))
196+
return m;
197+
return NULL;
198+
}
199+
189200
static struct tipc_member *tipc_group_find_node(struct tipc_group *grp,
190201
u32 node)
191202
{
@@ -318,9 +329,39 @@ void tipc_group_update_bc_members(struct tipc_group *grp, int len)
318329
grp->bc_snd_nxt++;
319330
}
320331

321-
bool tipc_group_bc_cong(struct tipc_group *grp, int len)
332+
bool tipc_group_cong(struct tipc_group *grp, u32 dnode, u32 dport,
333+
int len, struct tipc_member **mbr)
322334
{
335+
struct sk_buff_head xmitq;
323336
struct tipc_member *m;
337+
int adv, state;
338+
339+
m = tipc_group_find_dest(grp, dnode, dport);
340+
*mbr = m;
341+
if (!m)
342+
return false;
343+
if (m->usr_pending)
344+
return true;
345+
if (m->window >= len)
346+
return false;
347+
m->usr_pending = true;
348+
349+
/* If not fully advertised, do it now to prevent mutual blocking */
350+
adv = m->advertised;
351+
state = m->state;
352+
if (state < MBR_JOINED)
353+
return true;
354+
if (state == MBR_JOINED && adv == ADV_IDLE)
355+
return true;
356+
skb_queue_head_init(&xmitq);
357+
tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, &xmitq);
358+
tipc_node_distr_xmit(grp->net, &xmitq);
359+
return true;
360+
}
361+
362+
bool tipc_group_bc_cong(struct tipc_group *grp, int len)
363+
{
364+
struct tipc_member *m = NULL;
324365

325366
if (list_empty(&grp->congested))
326367
return false;
@@ -329,7 +370,7 @@ bool tipc_group_bc_cong(struct tipc_group *grp, int len)
329370
if (m->window >= len)
330371
return false;
331372

332-
return true;
373+
return tipc_group_cong(grp, m->node, m->port, len, &m);
333374
}
334375

335376
/* tipc_group_filter_msg() - determine if we should accept arriving message

net/tipc/group.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,12 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *wakeup,
6161
struct sk_buff_head *inputq,
6262
struct sk_buff_head *xmitq);
6363
void tipc_group_update_bc_members(struct tipc_group *grp, int len);
64+
bool tipc_group_cong(struct tipc_group *grp, u32 dnode, u32 dport,
65+
int len, struct tipc_member **m);
6466
bool tipc_group_bc_cong(struct tipc_group *grp, int len);
6567
void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node,
6668
u32 port, struct sk_buff_head *xmitq);
6769
u16 tipc_group_bc_snd_nxt(struct tipc_group *grp);
70+
void tipc_group_update_member(struct tipc_member *m, int len);
6871
int tipc_group_size(struct tipc_group *grp);
6972
#endif

net/tipc/msg.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ struct plist;
6767
#define TIPC_DIRECT_MSG 3
6868
#define TIPC_GRP_MEMBER_EVT 4
6969
#define TIPC_GRP_BCAST_MSG 5
70+
#define TIPC_GRP_UCAST_MSG 6
7071

7172
/*
7273
* Internal message users
@@ -261,7 +262,7 @@ static inline int msg_in_group(struct tipc_msg *m)
261262
{
262263
int mtyp = msg_type(m);
263264

264-
return (mtyp == TIPC_GRP_BCAST_MSG) || (mtyp == TIPC_GRP_MEMBER_EVT);
265+
return mtyp >= TIPC_GRP_MEMBER_EVT && mtyp <= TIPC_GRP_UCAST_MSG;
265266
}
266267

267268
static inline bool msg_is_grp_evt(struct tipc_msg *m)

net/tipc/socket.c

Lines changed: 102 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,93 @@ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq,
817817
return rc ? rc : dlen;
818818
}
819819

820+
/**
821+
* tipc_send_group_msg - send a message to a member in the group
822+
* @net: network namespace
823+
* @m: message to send
824+
* @mb: group member
825+
* @dnode: destination node
826+
* @dport: destination port
827+
* @dlen: total length of message data
828+
*/
829+
static int tipc_send_group_msg(struct net *net, struct tipc_sock *tsk,
830+
struct msghdr *m, struct tipc_member *mb,
831+
u32 dnode, u32 dport, int dlen)
832+
{
833+
int blks = tsk_blocks(GROUP_H_SIZE + dlen);
834+
struct tipc_msg *hdr = &tsk->phdr;
835+
struct sk_buff_head pkts;
836+
int mtu, rc;
837+
838+
/* Complete message header */
839+
msg_set_type(hdr, TIPC_GRP_UCAST_MSG);
840+
msg_set_hdr_sz(hdr, GROUP_H_SIZE);
841+
msg_set_destport(hdr, dport);
842+
msg_set_destnode(hdr, dnode);
843+
844+
/* Build message as chain of buffers */
845+
skb_queue_head_init(&pkts);
846+
mtu = tipc_node_get_mtu(net, dnode, tsk->portid);
847+
rc = tipc_msg_build(hdr, m, 0, dlen, mtu, &pkts);
848+
if (unlikely(rc != dlen))
849+
return rc;
850+
851+
/* Send message */
852+
rc = tipc_node_xmit(net, &pkts, dnode, tsk->portid);
853+
if (unlikely(rc == -ELINKCONG)) {
854+
tipc_dest_push(&tsk->cong_links, dnode, 0);
855+
tsk->cong_link_cnt++;
856+
}
857+
858+
/* Update send window and sequence number */
859+
tipc_group_update_member(mb, blks);
860+
861+
return dlen;
862+
}
863+
864+
/**
865+
* tipc_send_group_unicast - send message to a member in the group
866+
* @sock: socket structure
867+
* @m: message to send
868+
* @dlen: total length of message data
869+
* @timeout: timeout to wait for wakeup
870+
*
871+
* Called from function tipc_sendmsg(), which has done all sanity checks
872+
* Returns the number of bytes sent on success, or errno
873+
*/
874+
static int tipc_send_group_unicast(struct socket *sock, struct msghdr *m,
875+
int dlen, long timeout)
876+
{
877+
struct sock *sk = sock->sk;
878+
DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name);
879+
int blks = tsk_blocks(GROUP_H_SIZE + dlen);
880+
struct tipc_sock *tsk = tipc_sk(sk);
881+
struct tipc_group *grp = tsk->group;
882+
struct net *net = sock_net(sk);
883+
struct tipc_member *mb = NULL;
884+
u32 node, port;
885+
int rc;
886+
887+
node = dest->addr.id.node;
888+
port = dest->addr.id.ref;
889+
if (!port && !node)
890+
return -EHOSTUNREACH;
891+
892+
/* Block or return if destination link or member is congested */
893+
rc = tipc_wait_for_cond(sock, &timeout,
894+
!tipc_dest_find(&tsk->cong_links, node, 0) &&
895+
!tipc_group_cong(grp, node, port, blks, &mb));
896+
if (unlikely(rc))
897+
return rc;
898+
899+
if (unlikely(!mb))
900+
return -EHOSTUNREACH;
901+
902+
rc = tipc_send_group_msg(net, tsk, m, mb, node, port, dlen);
903+
904+
return rc ? rc : dlen;
905+
}
906+
820907
/**
821908
* tipc_send_group_bcast - send message to all members in communication group
822909
* @sk: socket structure
@@ -1030,21 +1117,27 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
10301117
if (unlikely(dlen > TIPC_MAX_USER_MSG_SIZE))
10311118
return -EMSGSIZE;
10321119

1033-
if (unlikely(grp && !dest))
1034-
return tipc_send_group_bcast(sock, m, dlen, timeout);
1120+
if (likely(dest)) {
1121+
if (unlikely(m->msg_namelen < sizeof(*dest)))
1122+
return -EINVAL;
1123+
if (unlikely(dest->family != AF_TIPC))
1124+
return -EINVAL;
1125+
}
1126+
1127+
if (grp) {
1128+
if (!dest)
1129+
return tipc_send_group_bcast(sock, m, dlen, timeout);
1130+
if (dest->addrtype == TIPC_ADDR_ID)
1131+
return tipc_send_group_unicast(sock, m, dlen, timeout);
1132+
return -EINVAL;
1133+
}
10351134

10361135
if (unlikely(!dest)) {
10371136
dest = &tsk->peer;
10381137
if (!syn || dest->family != AF_TIPC)
10391138
return -EDESTADDRREQ;
10401139
}
10411140

1042-
if (unlikely(m->msg_namelen < sizeof(*dest)))
1043-
return -EINVAL;
1044-
1045-
if (unlikely(dest->family != AF_TIPC))
1046-
return -EINVAL;
1047-
10481141
if (unlikely(syn)) {
10491142
if (sk->sk_state == TIPC_LISTEN)
10501143
return -EPIPE;
@@ -1077,7 +1170,6 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
10771170
msg_set_destport(hdr, dport);
10781171
if (unlikely(!dport && !dnode))
10791172
return -EHOSTUNREACH;
1080-
10811173
} else if (dest->addrtype == TIPC_ADDR_ID) {
10821174
dnode = dest->addr.id.node;
10831175
msg_set_type(hdr, TIPC_DIRECT_MSG);
@@ -1846,7 +1938,7 @@ static void tipc_sk_filter_rcv(struct sock *sk, struct sk_buff *skb,
18461938

18471939
if (unlikely(!msg_isdata(hdr)))
18481940
tipc_sk_proto_rcv(sk, &inputq, xmitq);
1849-
else if (unlikely(msg_type(hdr) > TIPC_GRP_BCAST_MSG))
1941+
else if (unlikely(msg_type(hdr) > TIPC_GRP_UCAST_MSG))
18501942
return kfree_skb(skb);
18511943

18521944
if (unlikely(grp))

0 commit comments

Comments
 (0)