Commit 908148bc authored by Jon Maloy's avatar Jon Maloy Committed by David S. Miller

tipc: refactor tipc_sendmsg() and tipc_lookup_anycast()

We simplify the signature if function tipc_nametbl_lookup_anycast(),
using address structures instead of discrete integers.

This also makes it possible to make some improvements to the functions
__tipc_sendmsg() in socket.c and tipc_msg_lookup_dest() in msg.c.
Signed-off-by: default avatarJon Maloy <jmaloy@redhat.com>
Acked-by: default avatarYing Xue <ying.xue@windriver.com>
Acked-by: default avatarHoang Le <hoang.h.le@dektech.com.au>
Acked-by: default avatarTung Nguyen <tung.q.nguyen@dektech.com.au>
Acked-by: default avatarXin Long <lucien.xin@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 66db239c
...@@ -707,8 +707,11 @@ bool tipc_msg_skb_clone(struct sk_buff_head *msg, struct sk_buff_head *cpy) ...@@ -707,8 +707,11 @@ bool tipc_msg_skb_clone(struct sk_buff_head *msg, struct sk_buff_head *cpy)
bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err) bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err)
{ {
struct tipc_msg *msg = buf_msg(skb); struct tipc_msg *msg = buf_msg(skb);
u32 dport, dnode; u32 scope = msg_lookup_scope(msg);
u32 onode = tipc_own_addr(net); u32 self = tipc_own_addr(net);
u32 inst = msg_nameinst(msg);
struct tipc_socket_addr sk;
struct tipc_uaddr ua;
if (!msg_isdata(msg)) if (!msg_isdata(msg))
return false; return false;
...@@ -722,16 +725,16 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err) ...@@ -722,16 +725,16 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err)
msg = buf_msg(skb); msg = buf_msg(skb);
if (msg_reroute_cnt(msg)) if (msg_reroute_cnt(msg))
return false; return false;
dnode = tipc_scope2node(net, msg_lookup_scope(msg)); tipc_uaddr(&ua, TIPC_SERVICE_RANGE, scope,
dport = tipc_nametbl_lookup_anycast(net, msg_nametype(msg), msg_nametype(msg), inst, inst);
msg_nameinst(msg), &dnode); sk.node = tipc_scope2node(net, scope);
if (!dport) if (!tipc_nametbl_lookup_anycast(net, &ua, &sk))
return false; return false;
msg_incr_reroute_cnt(msg); msg_incr_reroute_cnt(msg);
if (dnode != onode) if (sk.node != self)
msg_set_prevnode(msg, onode); msg_set_prevnode(msg, self);
msg_set_destnode(msg, dnode); msg_set_destnode(msg, sk.node);
msg_set_destport(msg, dport); msg_set_destport(msg, sk.ref);
*err = TIPC_OK; *err = TIPC_OK;
return true; return true;
......
...@@ -546,66 +546,64 @@ struct publication *tipc_nametbl_remove_publ(struct net *net, ...@@ -546,66 +546,64 @@ struct publication *tipc_nametbl_remove_publ(struct net *net,
/** /**
* tipc_nametbl_lookup_anycast - perform service instance to socket translation * tipc_nametbl_lookup_anycast - perform service instance to socket translation
* @net: network namespace * @net: network namespace
* @type: message type * @ua: service address to look up
* @instance: message instance * @sk: address to socket we want to find
* @dnode: the search domain used during translation
*
* On entry, 'dnode' is the search domain used during the lookup
* *
* On entry, a non-zero 'sk->node' indicates the node where we want lookup to be
* performed, which may not be this one.
* On exit: * On exit:
* - if lookup is deferred to another node, leave 'dnode' unchanged and return 0 * - If lookup is deferred to another node, leave 'sk->node' unchanged and
* - if lookup is attempted and succeeds, set 'dnode' to the publishing node and * return 'true'.
* return the published (non-zero) port number * - If lookup is successful, set the 'sk->node' and 'sk->ref' (== portid) which
* - if lookup is attempted and fails, set 'dnode' to 0 and return 0 * represent the bound socket and return 'true'.
* - If lookup fails, return 'false'
* *
* Note that for legacy users (node configured with Z.C.N address format) the * Note that for legacy users (node configured with Z.C.N address format) the
* 'closest-first' lookup algorithm must be maintained, i.e., if dnode is 0 * 'closest-first' lookup algorithm must be maintained, i.e., if sk.node is 0
* we must look in the local binding list first * we must look in the local binding list first
*/ */
u32 tipc_nametbl_lookup_anycast(struct net *net, u32 type, bool tipc_nametbl_lookup_anycast(struct net *net,
u32 instance, u32 *dnode) struct tipc_uaddr *ua,
struct tipc_socket_addr *sk)
{ {
struct tipc_net *tn = tipc_net(net); struct tipc_net *tn = tipc_net(net);
bool legacy = tn->legacy_addr_format; bool legacy = tn->legacy_addr_format;
u32 self = tipc_own_addr(net); u32 self = tipc_own_addr(net);
struct service_range *sr; u32 inst = ua->sa.instance;
struct service_range *r;
struct tipc_service *sc; struct tipc_service *sc;
struct list_head *list;
struct publication *p; struct publication *p;
u32 port = 0; struct list_head *l;
u32 node = 0; bool res = false;
if (!tipc_in_scope(legacy, *dnode, self)) if (!tipc_in_scope(legacy, sk->node, self))
return 0; return true;
rcu_read_lock(); rcu_read_lock();
sc = tipc_service_find(net, type); sc = tipc_service_find(net, ua->sr.type);
if (unlikely(!sc)) if (unlikely(!sc))
goto exit; goto exit;
spin_lock_bh(&sc->lock); spin_lock_bh(&sc->lock);
service_range_foreach_match(sr, sc, instance, instance) { service_range_foreach_match(r, sc, inst, inst) {
/* Select lookup algo: local, closest-first or round-robin */ /* Select lookup algo: local, closest-first or round-robin */
if (*dnode == self) { if (sk->node == self) {
list = &sr->local_publ; l = &r->local_publ;
if (list_empty(list)) if (list_empty(l))
continue; continue;
p = list_first_entry(list, struct publication, p = list_first_entry(l, struct publication, local_publ);
local_publ); list_move_tail(&p->local_publ, &r->local_publ);
list_move_tail(&p->local_publ, &sr->local_publ); } else if (legacy && !sk->node && !list_empty(&r->local_publ)) {
} else if (legacy && !*dnode && !list_empty(&sr->local_publ)) { l = &r->local_publ;
list = &sr->local_publ; p = list_first_entry(l, struct publication, local_publ);
p = list_first_entry(list, struct publication, list_move_tail(&p->local_publ, &r->local_publ);
local_publ);
list_move_tail(&p->local_publ, &sr->local_publ);
} else { } else {
list = &sr->all_publ; l = &r->all_publ;
p = list_first_entry(list, struct publication, p = list_first_entry(l, struct publication, all_publ);
all_publ); list_move_tail(&p->all_publ, &r->all_publ);
list_move_tail(&p->all_publ, &sr->all_publ);
} }
port = p->sk.ref; *sk = p->sk;
node = p->sk.node; res = true;
/* Todo: as for legacy, pick the first matching range only, a /* Todo: as for legacy, pick the first matching range only, a
* "true" round-robin will be performed as needed. * "true" round-robin will be performed as needed.
*/ */
...@@ -615,8 +613,7 @@ u32 tipc_nametbl_lookup_anycast(struct net *net, u32 type, ...@@ -615,8 +613,7 @@ u32 tipc_nametbl_lookup_anycast(struct net *net, u32 type,
exit: exit:
rcu_read_unlock(); rcu_read_unlock();
*dnode = node; return res;
return port;
} }
/* tipc_nametbl_lookup_group(): lookup destinaton(s) in a communication group /* tipc_nametbl_lookup_group(): lookup destinaton(s) in a communication group
......
...@@ -110,9 +110,8 @@ struct name_table { ...@@ -110,9 +110,8 @@ struct name_table {
}; };
int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb); int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb);
bool tipc_nametbl_lookup_anycast(struct net *net, struct tipc_uaddr *ua,
u32 tipc_nametbl_lookup_anycast(struct net *net, u32 type, u32 instance, struct tipc_socket_addr *sk);
u32 *node);
void tipc_nametbl_lookup_mcast_sockets(struct net *net, u32 type, u32 lower, void tipc_nametbl_lookup_mcast_sockets(struct net *net, u32 type, u32 lower,
u32 upper, u32 scope, bool exact, u32 upper, u32 scope, bool exact,
struct list_head *dports); struct list_head *dports);
......
...@@ -1424,44 +1424,43 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen) ...@@ -1424,44 +1424,43 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct net *net = sock_net(sk); struct net *net = sock_net(sk);
struct tipc_sock *tsk = tipc_sk(sk); struct tipc_sock *tsk = tipc_sk(sk);
DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); struct tipc_uaddr *ua = (struct tipc_uaddr *)m->msg_name;
long timeout = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); long timeout = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
struct list_head *clinks = &tsk->cong_links; struct list_head *clinks = &tsk->cong_links;
bool syn = !tipc_sk_type_connectionless(sk); bool syn = !tipc_sk_type_connectionless(sk);
struct tipc_group *grp = tsk->group; struct tipc_group *grp = tsk->group;
struct tipc_msg *hdr = &tsk->phdr; struct tipc_msg *hdr = &tsk->phdr;
struct tipc_service_range *seq; struct tipc_socket_addr skaddr;
struct sk_buff_head pkts; struct sk_buff_head pkts;
u32 dport = 0, dnode = 0; int atype, mtu, rc;
u32 type = 0, inst = 0;
int mtu, rc;
if (unlikely(dlen > TIPC_MAX_USER_MSG_SIZE)) if (unlikely(dlen > TIPC_MAX_USER_MSG_SIZE))
return -EMSGSIZE; return -EMSGSIZE;
if (likely(dest)) { if (ua) {
if (unlikely(m->msg_namelen < sizeof(*dest))) if (!tipc_uaddr_valid(ua, m->msg_namelen))
return -EINVAL;
if (unlikely(dest->family != AF_TIPC))
return -EINVAL; return -EINVAL;
atype = ua->addrtype;
} }
/* If socket belongs to a communication group follow other paths */
if (grp) { if (grp) {
if (!dest) if (!ua)
return tipc_send_group_bcast(sock, m, dlen, timeout); return tipc_send_group_bcast(sock, m, dlen, timeout);
if (dest->addrtype == TIPC_SERVICE_ADDR) if (atype == TIPC_SERVICE_ADDR)
return tipc_send_group_anycast(sock, m, dlen, timeout); return tipc_send_group_anycast(sock, m, dlen, timeout);
if (dest->addrtype == TIPC_SOCKET_ADDR) if (atype == TIPC_SOCKET_ADDR)
return tipc_send_group_unicast(sock, m, dlen, timeout); return tipc_send_group_unicast(sock, m, dlen, timeout);
if (dest->addrtype == TIPC_ADDR_MCAST) if (atype == TIPC_SERVICE_RANGE)
return tipc_send_group_mcast(sock, m, dlen, timeout); return tipc_send_group_mcast(sock, m, dlen, timeout);
return -EINVAL; return -EINVAL;
} }
if (unlikely(!dest)) { if (!ua) {
dest = &tsk->peer; ua = (struct tipc_uaddr *)&tsk->peer;
if (!syn && dest->family != AF_TIPC) if (!syn && ua->family != AF_TIPC)
return -EDESTADDRREQ; return -EDESTADDRREQ;
atype = ua->addrtype;
} }
if (unlikely(syn)) { if (unlikely(syn)) {
...@@ -1471,54 +1470,51 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen) ...@@ -1471,54 +1470,51 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
return -EISCONN; return -EISCONN;
if (tsk->published) if (tsk->published)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (dest->addrtype == TIPC_SERVICE_ADDR) { if (atype == TIPC_SERVICE_ADDR) {
tsk->conn_type = dest->addr.name.name.type; tsk->conn_type = ua->sa.type;
tsk->conn_instance = dest->addr.name.name.instance; tsk->conn_instance = ua->sa.instance;
} }
msg_set_syn(hdr, 1); msg_set_syn(hdr, 1);
} }
seq = &dest->addr.nameseq; /* Determine destination */
if (dest->addrtype == TIPC_ADDR_MCAST) if (atype == TIPC_SERVICE_RANGE) {
return tipc_sendmcast(sock, seq, m, dlen, timeout); return tipc_sendmcast(sock, &ua->sr, m, dlen, timeout);
} else if (atype == TIPC_SERVICE_ADDR) {
if (dest->addrtype == TIPC_SERVICE_ADDR) { skaddr.node = ua->lookup_node;
type = dest->addr.name.name.type; ua->scope = tipc_node2scope(skaddr.node);
inst = dest->addr.name.name.instance; if (!tipc_nametbl_lookup_anycast(net, ua, &skaddr))
dnode = dest->addr.name.domain;
dport = tipc_nametbl_lookup_anycast(net, type, inst, &dnode);
if (unlikely(!dport && !dnode))
return -EHOSTUNREACH; return -EHOSTUNREACH;
} else if (dest->addrtype == TIPC_SOCKET_ADDR) { } else if (atype == TIPC_SOCKET_ADDR) {
dnode = dest->addr.id.node; skaddr = ua->sk;
} else { } else {
return -EINVAL; return -EINVAL;
} }
/* Block or return if destination link is congested */ /* Block or return if destination link is congested */
rc = tipc_wait_for_cond(sock, &timeout, rc = tipc_wait_for_cond(sock, &timeout,
!tipc_dest_find(clinks, dnode, 0)); !tipc_dest_find(clinks, skaddr.node, 0));
if (unlikely(rc)) if (unlikely(rc))
return rc; return rc;
if (dest->addrtype == TIPC_SERVICE_ADDR) { /* Finally build message header */
msg_set_destnode(hdr, skaddr.node);
msg_set_destport(hdr, skaddr.ref);
if (atype == TIPC_SERVICE_ADDR) {
msg_set_type(hdr, TIPC_NAMED_MSG); msg_set_type(hdr, TIPC_NAMED_MSG);
msg_set_hdr_sz(hdr, NAMED_H_SIZE); msg_set_hdr_sz(hdr, NAMED_H_SIZE);
msg_set_nametype(hdr, type); msg_set_nametype(hdr, ua->sa.type);
msg_set_nameinst(hdr, inst); msg_set_nameinst(hdr, ua->sa.instance);
msg_set_lookup_scope(hdr, tipc_node2scope(dnode)); msg_set_lookup_scope(hdr, ua->scope);
msg_set_destnode(hdr, dnode);
msg_set_destport(hdr, dport);
} else { /* TIPC_SOCKET_ADDR */ } else { /* TIPC_SOCKET_ADDR */
msg_set_type(hdr, TIPC_DIRECT_MSG); msg_set_type(hdr, TIPC_DIRECT_MSG);
msg_set_lookup_scope(hdr, 0); msg_set_lookup_scope(hdr, 0);
msg_set_destnode(hdr, dnode);
msg_set_destport(hdr, dest->addr.id.ref);
msg_set_hdr_sz(hdr, BASIC_H_SIZE); msg_set_hdr_sz(hdr, BASIC_H_SIZE);
} }
/* Add message body */
__skb_queue_head_init(&pkts); __skb_queue_head_init(&pkts);
mtu = tipc_node_get_mtu(net, dnode, tsk->portid, true); mtu = tipc_node_get_mtu(net, skaddr.node, tsk->portid, true);
rc = tipc_msg_build(hdr, m, 0, dlen, mtu, &pkts); rc = tipc_msg_build(hdr, m, 0, dlen, mtu, &pkts);
if (unlikely(rc != dlen)) if (unlikely(rc != dlen))
return rc; return rc;
...@@ -1527,10 +1523,11 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen) ...@@ -1527,10 +1523,11 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
return -ENOMEM; return -ENOMEM;
} }
/* Send message */
trace_tipc_sk_sendmsg(sk, skb_peek(&pkts), TIPC_DUMP_SK_SNDQ, " "); trace_tipc_sk_sendmsg(sk, skb_peek(&pkts), TIPC_DUMP_SK_SNDQ, " ");
rc = tipc_node_xmit(net, &pkts, dnode, tsk->portid); rc = tipc_node_xmit(net, &pkts, skaddr.node, tsk->portid);
if (unlikely(rc == -ELINKCONG)) { if (unlikely(rc == -ELINKCONG)) {
tipc_dest_push(clinks, dnode, 0); tipc_dest_push(clinks, skaddr.node, 0);
tsk->cong_link_cnt++; tsk->cong_link_cnt++;
rc = 0; rc = 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment