Skip to content

Commit 14c0449

Browse files
Jon Maloydavem330
authored andcommitted
tipc: add ability to order and receive topology events in driver
As preparation for introducing communication groups, we add the ability to issue topology subscriptions and receive topology events from kernel space. This will make it possible for group member sockets to keep track of other group members. Signed-off-by: Jon Maloy <[email protected]> Acked-by: Ying Xue <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2d0d21c commit 14c0449

File tree

5 files changed

+124
-40
lines changed

5 files changed

+124
-40
lines changed

net/tipc/core.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ static inline struct list_head *tipc_nodes(struct net *net)
132132
return &tipc_net(net)->node_list;
133133
}
134134

135+
static inline struct tipc_server *tipc_topsrv(struct net *net)
136+
{
137+
return tipc_net(net)->topsrv;
138+
}
139+
135140
static inline unsigned int tipc_hashfn(u32 addr)
136141
{
137142
return addr & (NODE_HTABLE_SIZE - 1);

net/tipc/msg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ struct plist;
7878
#define MSG_FRAGMENTER 12
7979
#define LINK_CONFIG 13
8080
#define SOCK_WAKEUP 14 /* pseudo user */
81+
#define TOP_SRV 15 /* pseudo user */
8182

8283
/*
8384
* Message header sizes

net/tipc/server.c

Lines changed: 94 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
#include "server.h"
3737
#include "core.h"
3838
#include "socket.h"
39+
#include "addr.h"
40+
#include "msg.h"
3941
#include <net/sock.h>
4042
#include <linux/module.h>
4143

@@ -105,13 +107,11 @@ static void tipc_conn_kref_release(struct kref *kref)
105107
kernel_bind(sock, (struct sockaddr *)saddr, sizeof(*saddr));
106108
sock_release(sock);
107109
con->sock = NULL;
108-
109-
spin_lock_bh(&s->idr_lock);
110-
idr_remove(&s->conn_idr, con->conid);
111-
s->idr_in_use--;
112-
spin_unlock_bh(&s->idr_lock);
113110
}
114-
111+
spin_lock_bh(&s->idr_lock);
112+
idr_remove(&s->conn_idr, con->conid);
113+
s->idr_in_use--;
114+
spin_unlock_bh(&s->idr_lock);
115115
tipc_clean_outqueues(con);
116116
kfree(con);
117117
}
@@ -197,7 +197,8 @@ static void tipc_close_conn(struct tipc_conn *con)
197197
struct tipc_server *s = con->server;
198198

199199
if (test_and_clear_bit(CF_CONNECTED, &con->flags)) {
200-
tipc_unregister_callbacks(con);
200+
if (con->sock)
201+
tipc_unregister_callbacks(con);
201202

202203
if (con->conid)
203204
s->tipc_conn_release(con->conid, con->usr_data);
@@ -207,8 +208,8 @@ static void tipc_close_conn(struct tipc_conn *con)
207208
* are harmless for us here as we have already deleted this
208209
* connection from server connection list.
209210
*/
210-
kernel_sock_shutdown(con->sock, SHUT_RDWR);
211-
211+
if (con->sock)
212+
kernel_sock_shutdown(con->sock, SHUT_RDWR);
212213
conn_put(con);
213214
}
214215
}
@@ -487,38 +488,104 @@ void tipc_conn_terminate(struct tipc_server *s, int conid)
487488
}
488489
}
489490

491+
bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type,
492+
u32 lower, u32 upper, int *conid)
493+
{
494+
struct tipc_subscriber *scbr;
495+
struct tipc_subscr sub;
496+
struct tipc_server *s;
497+
struct tipc_conn *con;
498+
499+
sub.seq.type = type;
500+
sub.seq.lower = lower;
501+
sub.seq.upper = upper;
502+
sub.timeout = TIPC_WAIT_FOREVER;
503+
sub.filter = TIPC_SUB_PORTS;
504+
*(u32 *)&sub.usr_handle = port;
505+
506+
con = tipc_alloc_conn(tipc_topsrv(net));
507+
if (!con)
508+
return false;
509+
510+
*conid = con->conid;
511+
s = con->server;
512+
scbr = s->tipc_conn_new(*conid);
513+
if (!scbr) {
514+
tipc_close_conn(con);
515+
return false;
516+
}
517+
518+
con->usr_data = scbr;
519+
con->sock = NULL;
520+
s->tipc_conn_recvmsg(net, *conid, NULL, scbr, &sub, sizeof(sub));
521+
return true;
522+
}
523+
524+
void tipc_topsrv_kern_unsubscr(struct net *net, int conid)
525+
{
526+
struct tipc_conn *con;
527+
528+
con = tipc_conn_lookup(tipc_topsrv(net), conid);
529+
if (!con)
530+
return;
531+
tipc_close_conn(con);
532+
conn_put(con);
533+
}
534+
535+
static void tipc_send_kern_top_evt(struct net *net, struct tipc_event *evt)
536+
{
537+
u32 port = *(u32 *)&evt->s.usr_handle;
538+
u32 self = tipc_own_addr(net);
539+
struct sk_buff_head evtq;
540+
struct sk_buff *skb;
541+
542+
skb = tipc_msg_create(TOP_SRV, 0, INT_H_SIZE, sizeof(*evt),
543+
self, self, port, port, 0);
544+
if (!skb)
545+
return;
546+
msg_set_dest_droppable(buf_msg(skb), true);
547+
memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt));
548+
skb_queue_head_init(&evtq);
549+
__skb_queue_tail(&evtq, skb);
550+
tipc_sk_rcv(net, &evtq);
551+
}
552+
490553
static void tipc_send_to_sock(struct tipc_conn *con)
491554
{
492-
int count = 0;
493555
struct tipc_server *s = con->server;
494556
struct outqueue_entry *e;
557+
struct tipc_event *evt;
495558
struct msghdr msg;
559+
int count = 0;
496560
int ret;
497561

498562
spin_lock_bh(&con->outqueue_lock);
499563
while (test_bit(CF_CONNECTED, &con->flags)) {
500-
e = list_entry(con->outqueue.next, struct outqueue_entry,
501-
list);
564+
e = list_entry(con->outqueue.next, struct outqueue_entry, list);
502565
if ((struct list_head *) e == &con->outqueue)
503566
break;
504-
spin_unlock_bh(&con->outqueue_lock);
505567

506-
memset(&msg, 0, sizeof(msg));
507-
msg.msg_flags = MSG_DONTWAIT;
568+
spin_unlock_bh(&con->outqueue_lock);
508569

509-
if (s->type == SOCK_DGRAM || s->type == SOCK_RDM) {
510-
msg.msg_name = &e->dest;
511-
msg.msg_namelen = sizeof(struct sockaddr_tipc);
512-
}
513-
ret = kernel_sendmsg(con->sock, &msg, &e->iov, 1,
514-
e->iov.iov_len);
515-
if (ret == -EWOULDBLOCK || ret == 0) {
516-
cond_resched();
517-
goto out;
518-
} else if (ret < 0) {
519-
goto send_err;
570+
if (con->sock) {
571+
memset(&msg, 0, sizeof(msg));
572+
msg.msg_flags = MSG_DONTWAIT;
573+
if (s->type == SOCK_DGRAM || s->type == SOCK_RDM) {
574+
msg.msg_name = &e->dest;
575+
msg.msg_namelen = sizeof(struct sockaddr_tipc);
576+
}
577+
ret = kernel_sendmsg(con->sock, &msg, &e->iov, 1,
578+
e->iov.iov_len);
579+
if (ret == -EWOULDBLOCK || ret == 0) {
580+
cond_resched();
581+
goto out;
582+
} else if (ret < 0) {
583+
goto send_err;
584+
}
585+
} else {
586+
evt = e->iov.iov_base;
587+
tipc_send_kern_top_evt(s->net, evt);
520588
}
521-
522589
/* Don't starve users filling buffers */
523590
if (++count >= MAX_SEND_MSG_COUNT) {
524591
cond_resched();

net/tipc/server.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,16 @@ struct tipc_server {
8383
int tipc_conn_sendmsg(struct tipc_server *s, int conid,
8484
struct sockaddr_tipc *addr, void *data, size_t len);
8585

86+
bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type,
87+
u32 lower, u32 upper, int *conid);
88+
void tipc_topsrv_kern_unsubscr(struct net *net, int conid);
89+
8690
/**
8791
* tipc_conn_terminate - terminate connection with server
8892
*
8993
* Note: Must call it in process context since it might sleep
9094
*/
9195
void tipc_conn_terminate(struct tipc_server *s, int conid);
92-
9396
int tipc_server_start(struct tipc_server *s);
9497

9598
void tipc_server_stop(struct tipc_server *s);

net/tipc/socket.c

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,10 @@ static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb,
896896
kfree_skb(skb);
897897
}
898898

899+
static void tipc_sk_top_evt(struct tipc_sock *tsk, struct tipc_event *evt)
900+
{
901+
}
902+
899903
/**
900904
* tipc_sendmsg - send message in connectionless manner
901905
* @sock: socket structure
@@ -1671,20 +1675,24 @@ static bool filter_rcv(struct sock *sk, struct sk_buff *skb,
16711675
struct tipc_msg *hdr = buf_msg(skb);
16721676
unsigned int limit = rcvbuf_limit(sk, skb);
16731677
int err = TIPC_OK;
1674-
int usr = msg_user(hdr);
1675-
u32 onode;
1676-
1677-
if (unlikely(msg_user(hdr) == CONN_MANAGER)) {
1678-
tipc_sk_proto_rcv(tsk, skb, xmitq);
1679-
return false;
1680-
}
16811678

1682-
if (unlikely(usr == SOCK_WAKEUP)) {
1683-
onode = msg_orignode(hdr);
1679+
if (unlikely(!msg_isdata(hdr))) {
1680+
switch (msg_user(hdr)) {
1681+
case CONN_MANAGER:
1682+
tipc_sk_proto_rcv(tsk, skb, xmitq);
1683+
return false;
1684+
case SOCK_WAKEUP:
1685+
u32_del(&tsk->cong_links, msg_orignode(hdr));
1686+
tsk->cong_link_cnt--;
1687+
sk->sk_write_space(sk);
1688+
break;
1689+
case TOP_SRV:
1690+
tipc_sk_top_evt(tsk, (void *)msg_data(hdr));
1691+
break;
1692+
default:
1693+
break;
1694+
}
16841695
kfree_skb(skb);
1685-
u32_del(&tsk->cong_links, onode);
1686-
tsk->cong_link_cnt--;
1687-
sk->sk_write_space(sk);
16881696
return false;
16891697
}
16901698

0 commit comments

Comments
 (0)