Commit e2dafe87 authored by Jon Paul Maloy's avatar Jon Paul Maloy Committed by David S. Miller

tipc: RDM/DGRAM transport uses new fragmenting and sending functions

We merge the code for sending port name and port identity addressed
messages into the corresponding send functions in socket.c, and start
using the new fragmenting and transmit functions we just have introduced.

This saves a call level and quite a few code lines, as well as making
this part of the code easier to follow. As a consequence, the functions
tipc_send2name() and tipc_send2port() in port.c can be removed.

For practical reasons, we break out the code for sending multicast messages
from tipc_sendmsg() and move it into a separate function, tipc_sendmcast(),
but we do not yet convert it into using the new build/send functions.
Signed-off-by: default avatarJon Maloy <jon.maloy@ericsson.com>
Reviewed-by: default avatarErik Hugne <erik.hugne@ericsson.com>
Reviewed-by: default avatarYing Xue <ying.xue@windriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5a379074
...@@ -806,93 +806,3 @@ int tipc_send(struct tipc_port *p_ptr, ...@@ -806,93 +806,3 @@ int tipc_send(struct tipc_port *p_ptr,
} }
return -ELINKCONG; return -ELINKCONG;
} }
/**
* tipc_send2name - send message sections to port name
*/
int tipc_send2name(struct tipc_port *p_ptr,
struct tipc_name const *name,
unsigned int domain,
struct iovec const *msg_sect,
unsigned int len)
{
struct tipc_msg *msg;
u32 destnode = domain;
u32 destport;
int res;
if (p_ptr->connected)
return -EINVAL;
msg = &p_ptr->phdr;
msg_set_type(msg, TIPC_NAMED_MSG);
msg_set_hdr_sz(msg, NAMED_H_SIZE);
msg_set_nametype(msg, name->type);
msg_set_nameinst(msg, name->instance);
msg_set_lookup_scope(msg, tipc_addr_scope(domain));
destport = tipc_nametbl_translate(name->type, name->instance, &destnode);
msg_set_destnode(msg, destnode);
msg_set_destport(msg, destport);
if (likely(destport || destnode)) {
if (likely(in_own_node(destnode)))
res = tipc_port_iovec_rcv(p_ptr, msg_sect, len);
else if (tipc_own_addr)
res = tipc_link_iovec_xmit_fast(p_ptr, msg_sect, len,
destnode);
else
res = tipc_port_iovec_reject(p_ptr, msg, msg_sect,
len, TIPC_ERR_NO_NODE);
if (likely(res != -ELINKCONG)) {
if (res > 0)
p_ptr->sent++;
return res;
}
if (tipc_port_unreliable(p_ptr))
return len;
return -ELINKCONG;
}
return tipc_port_iovec_reject(p_ptr, msg, msg_sect, len,
TIPC_ERR_NO_NAME);
}
/**
* tipc_send2port - send message sections to port identity
*/
int tipc_send2port(struct tipc_port *p_ptr,
struct tipc_portid const *dest,
struct iovec const *msg_sect,
unsigned int len)
{
struct tipc_msg *msg;
int res;
if (p_ptr->connected)
return -EINVAL;
msg = &p_ptr->phdr;
msg_set_type(msg, TIPC_DIRECT_MSG);
msg_set_lookup_scope(msg, 0);
msg_set_destnode(msg, dest->node);
msg_set_destport(msg, dest->ref);
msg_set_hdr_sz(msg, BASIC_H_SIZE);
if (in_own_node(dest->node))
res = tipc_port_iovec_rcv(p_ptr, msg_sect, len);
else if (tipc_own_addr)
res = tipc_link_iovec_xmit_fast(p_ptr, msg_sect, len,
dest->node);
else
res = tipc_port_iovec_reject(p_ptr, msg, msg_sect, len,
TIPC_ERR_NO_NODE);
if (likely(res != -ELINKCONG)) {
if (res > 0)
p_ptr->sent++;
return res;
}
if (tipc_port_unreliable(p_ptr))
return len;
return -ELINKCONG;
}
...@@ -140,17 +140,6 @@ int tipc_send(struct tipc_port *port, ...@@ -140,17 +140,6 @@ int tipc_send(struct tipc_port *port,
struct iovec const *msg_sect, struct iovec const *msg_sect,
unsigned int len); unsigned int len);
int tipc_send2name(struct tipc_port *port,
struct tipc_name const *name,
u32 domain,
struct iovec const *msg_sect,
unsigned int len);
int tipc_send2port(struct tipc_port *port,
struct tipc_portid const *dest,
struct iovec const *msg_sect,
unsigned int len);
int tipc_port_mcast_xmit(struct tipc_port *port, int tipc_port_mcast_xmit(struct tipc_port *port,
struct tipc_name_seq const *seq, struct tipc_name_seq const *seq,
struct iovec const *msg, struct iovec const *msg,
......
...@@ -36,8 +36,9 @@ ...@@ -36,8 +36,9 @@
#include "core.h" #include "core.h"
#include "port.h" #include "port.h"
#include "name_table.h"
#include "node.h" #include "node.h"
#include "link.h"
#include <linux/export.h> #include <linux/export.h>
#include "link.h" #include "link.h"
...@@ -545,6 +546,8 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) ...@@ -545,6 +546,8 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
{ {
struct tipc_cfg_msg_hdr hdr; struct tipc_cfg_msg_hdr hdr;
if (unlikely(dest->addrtype == TIPC_ADDR_ID))
return 0;
if (likely(dest->addr.name.name.type >= TIPC_RESERVED_TYPES)) if (likely(dest->addr.name.name.type >= TIPC_RESERVED_TYPES))
return 0; return 0;
if (likely(dest->addr.name.name.type == TIPC_TOP_SRV)) if (likely(dest->addr.name.name.type == TIPC_TOP_SRV))
...@@ -587,13 +590,49 @@ static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p) ...@@ -587,13 +590,49 @@ static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p)
return 0; return 0;
} }
/**
* tipc_sendmcast - send multicast message
* @sock: socket structure
* @seq: destination address
* @iov: message data to send
* @dsz: total length of message data
* @timeo: timeout to wait for wakeup
*
* Called from function tipc_sendmsg(), which has done all sanity checks
* Returns the number of bytes sent on success, or errno
*/
static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq,
struct iovec *iov, size_t dsz, long timeo)
{
struct sock *sk = sock->sk;
struct tipc_sock *tsk = tipc_sk(sk);
int rc;
do {
if (sock->state != SS_READY) {
rc = -EOPNOTSUPP;
break;
}
rc = tipc_port_mcast_xmit(&tsk->port, seq, iov, dsz);
if (likely(rc >= 0)) {
if (sock->state != SS_READY)
sock->state = SS_CONNECTING;
break;
}
if (rc != -ELINKCONG)
break;
rc = tipc_wait_for_sndmsg(sock, &timeo);
} while (!rc);
return rc;
}
/** /**
* tipc_sendmsg - send message in connectionless manner * tipc_sendmsg - send message in connectionless manner
* @iocb: if NULL, indicates that socket lock is already held * @iocb: if NULL, indicates that socket lock is already held
* @sock: socket structure * @sock: socket structure
* @m: message to send * @m: message to send
* @total_len: length of message * @dsz: amount of user data to be sent
* *
* Message must have an destination specified explicitly. * Message must have an destination specified explicitly.
* Used for SOCK_RDM and SOCK_DGRAM messages, * Used for SOCK_RDM and SOCK_DGRAM messages,
...@@ -603,93 +642,116 @@ static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p) ...@@ -603,93 +642,116 @@ static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p)
* Returns the number of bytes sent on success, or errno otherwise * Returns the number of bytes sent on success, or errno otherwise
*/ */
static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock, static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *m, size_t total_len) struct msghdr *m, size_t dsz)
{ {
DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name);
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct tipc_sock *tsk = tipc_sk(sk); struct tipc_sock *tsk = tipc_sk(sk);
struct tipc_port *port = &tsk->port; struct tipc_port *port = &tsk->port;
DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); struct tipc_msg *mhdr = &port->phdr;
int needs_conn; struct iovec *iov = m->msg_iov;
u32 dnode, dport;
struct sk_buff *buf;
struct tipc_name_seq *seq = &dest->addr.nameseq;
u32 mtu;
long timeo; long timeo;
int res = -EINVAL; int rc = -EINVAL;
if (unlikely(!dest)) if (unlikely(!dest))
return -EDESTADDRREQ; return -EDESTADDRREQ;
if (unlikely((m->msg_namelen < sizeof(*dest)) || if (unlikely((m->msg_namelen < sizeof(*dest)) ||
(dest->family != AF_TIPC))) (dest->family != AF_TIPC)))
return -EINVAL; return -EINVAL;
if (total_len > TIPC_MAX_USER_MSG_SIZE)
if (dsz > TIPC_MAX_USER_MSG_SIZE)
return -EMSGSIZE; return -EMSGSIZE;
if (iocb) if (iocb)
lock_sock(sk); lock_sock(sk);
needs_conn = (sock->state != SS_READY); if (unlikely(sock->state != SS_READY)) {
if (unlikely(needs_conn)) {
if (sock->state == SS_LISTENING) { if (sock->state == SS_LISTENING) {
res = -EPIPE; rc = -EPIPE;
goto exit; goto exit;
} }
if (sock->state != SS_UNCONNECTED) { if (sock->state != SS_UNCONNECTED) {
res = -EISCONN; rc = -EISCONN;
goto exit; goto exit;
} }
if (tsk->port.published) { if (tsk->port.published) {
res = -EOPNOTSUPP; rc = -EOPNOTSUPP;
goto exit; goto exit;
} }
if (dest->addrtype == TIPC_ADDR_NAME) { if (dest->addrtype == TIPC_ADDR_NAME) {
tsk->port.conn_type = dest->addr.name.name.type; tsk->port.conn_type = dest->addr.name.name.type;
tsk->port.conn_instance = dest->addr.name.name.instance; tsk->port.conn_instance = dest->addr.name.name.instance;
} }
/* Abort any pending connection attempts (very unlikely) */
reject_rx_queue(sk);
} }
rc = dest_name_check(dest, m);
if (rc)
goto exit;
timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
do {
if (dest->addrtype == TIPC_ADDR_NAME) { if (dest->addrtype == TIPC_ADDR_MCAST) {
res = dest_name_check(dest, m); rc = tipc_sendmcast(sock, seq, iov, dsz, timeo);
if (res) goto exit;
break; } else if (dest->addrtype == TIPC_ADDR_NAME) {
res = tipc_send2name(port, u32 type = dest->addr.name.name.type;
&dest->addr.name.name, u32 inst = dest->addr.name.name.instance;
dest->addr.name.domain, u32 domain = dest->addr.name.domain;
m->msg_iov,
total_len); dnode = domain;
} else if (dest->addrtype == TIPC_ADDR_ID) { msg_set_type(mhdr, TIPC_NAMED_MSG);
res = tipc_send2port(port, msg_set_hdr_sz(mhdr, NAMED_H_SIZE);
&dest->addr.id, msg_set_nametype(mhdr, type);
m->msg_iov, msg_set_nameinst(mhdr, inst);
total_len); msg_set_lookup_scope(mhdr, tipc_addr_scope(domain));
} else if (dest->addrtype == TIPC_ADDR_MCAST) { dport = tipc_nametbl_translate(type, inst, &dnode);
if (needs_conn) { msg_set_destnode(mhdr, dnode);
res = -EOPNOTSUPP; msg_set_destport(mhdr, dport);
break; if (unlikely(!dport && !dnode)) {
} rc = -EHOSTUNREACH;
res = dest_name_check(dest, m); goto exit;
if (res)
break;
res = tipc_port_mcast_xmit(port,
&dest->addr.nameseq,
m->msg_iov,
total_len);
} }
if (likely(res != -ELINKCONG)) { } else if (dest->addrtype == TIPC_ADDR_ID) {
if (needs_conn && (res >= 0)) dnode = dest->addr.id.node;
msg_set_type(mhdr, TIPC_DIRECT_MSG);
msg_set_lookup_scope(mhdr, 0);
msg_set_destnode(mhdr, dnode);
msg_set_destport(mhdr, dest->addr.id.ref);
msg_set_hdr_sz(mhdr, BASIC_H_SIZE);
}
new_mtu:
mtu = tipc_node_get_mtu(dnode, tsk->port.ref);
rc = tipc_msg_build2(mhdr, iov, 0, dsz, mtu, &buf);
if (rc < 0)
goto exit;
do {
rc = tipc_link_xmit2(buf, dnode, tsk->port.ref);
if (likely(rc >= 0)) {
if (sock->state != SS_READY)
sock->state = SS_CONNECTING; sock->state = SS_CONNECTING;
rc = dsz;
break; break;
} }
res = tipc_wait_for_sndmsg(sock, &timeo); if (rc == -EMSGSIZE)
if (res) goto new_mtu;
if (rc != -ELINKCONG)
break; break;
} while (1);
rc = tipc_wait_for_sndmsg(sock, &timeo);
} while (!rc);
exit: exit:
if (iocb) if (iocb)
release_sock(sk); release_sock(sk);
return res;
return rc;
} }
static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p) static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p)
......
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