1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (c) 2002 Cray Inc.
5 * Copyright (c) 2003 Cluster File Systems, Inc.
7 * This file is part of Lustre, http://www.lustre.org.
9 * Lustre is free software; you can redistribute it and/or
10 * modify it under the terms of version 2 of the GNU General Public
11 * License as published by the Free Software Foundation.
13 * Lustre is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Lustre; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This file implements the TCP-based nal by providing glue
25 between the connection service and the generic NAL implementation */
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
38 #include <connection.h>
45 /* Function: tcpnal_send
46 * Arguments: nal: pointer to my nal control block
48 * cookie: passed back to the portals library
49 * hdr: pointer to the portals header
50 * nid: destination node
51 * pid: destination process
52 * data: body of the message
53 * len: length of the body
54 * Returns: zero on success
56 * sends a packet to the peer, after insuring that a connection exists
58 int tcpnal_send(nal_cb_t *n,
70 bridge b=(bridge)n->nal_data;
71 struct iovec tiov[257];
72 static pthread_mutex_t send_lock = PTHREAD_MUTEX_INITIALIZER;
77 if (!(c=force_tcp_connection((manager)b->lower,
83 /* TODO: these results should be checked. furthermore, provision
84 must be made for the SIGPIPE which is delivered when
85 writing on a tcp socket which has closed underneath
86 the application. there is a linux flag in the sendmsg
87 call which turns off the signally behaviour, but its
89 syscall(SYS_write, c->fd,hdr,sizeof(ptl_hdr_t));
91 if (len) syscall(SYS_write, c->fd,iov[0].iov_base,len);
93 LASSERT (niov <= 256);
95 tiov[0].iov_base = hdr;
96 tiov[0].iov_len = sizeof(ptl_hdr_t);
99 memcpy(&tiov[1], iov, niov * sizeof(struct iovec));
100 pthread_mutex_lock(&send_lock);
102 for (i = total = 0; i <= niov; i++)
103 total += tiov[i].iov_len;
105 rc = syscall(SYS_writev, c->fd, tiov, niov+1);
107 fprintf (stderr, "BAD SEND rc %d != %d, errno %d\n",
112 for (i = total = 0; i <= niov; i++) {
113 rc = send(c->fd, tiov[i].iov_base, tiov[i].iov_len, 0);
115 if (rc != tiov[i].iov_len) {
116 fprintf (stderr, "BAD SEND rc %d != %d, errno %d\n",
117 rc, tiov[i].iov_len, errno);
124 fprintf (stderr, "sent %s total %d in %d frags\n",
125 hdr->type == PTL_MSG_ACK ? "ACK" :
126 hdr->type == PTL_MSG_PUT ? "PUT" :
127 hdr->type == PTL_MSG_GET ? "GET" :
128 hdr->type == PTL_MSG_REPLY ? "REPLY" :
129 hdr->type == PTL_MSG_HELLO ? "HELLO" : "UNKNOWN",
132 pthread_mutex_unlock(&send_lock);
134 lib_finalize(n, private, cookie);
140 /* Function: tcpnal_recv
141 * Arguments: nal_cb_t *nal: pointer to my nal control block
142 * void *private: connection pointer passed through
144 * lib_msg_t *cookie: passed back to portals library
145 * user_ptr data: pointer to the destination buffer
146 * size_t mlen: length of the body
147 * size_t rlen: length of data in the network
148 * Returns: zero on success
150 * blocking read of the requested data. must drain out the
151 * difference of mainpulated and requested lengths from the network
153 int tcpnal_recv(nal_cb_t *n,
169 LASSERT(rlen >= mlen);
172 * 1. Is this effecient enough? change to use readv() directly?
173 * 2. need check return from read_connection()
176 for (i = 0; i < niov; i++)
177 read_connection(private, iov[i].iov_base, iov[i].iov_len);
180 lib_finalize(n, private, cookie);
183 char *trash=malloc(rlen-mlen);
185 /*TODO: check error status*/
186 read_connection(private,trash,rlen-mlen);
194 /* Function: from_connection:
195 * Arguments: c: the connection to read from
196 * Returns: whether or not to continue reading from this connection,
197 * expressed as a 1 to continue, and a 0 to not
199 * from_connection() is called from the select loop when i/o is
200 * available. It attempts to read the portals header and
201 * pass it to the generic library for processing.
203 static int from_connection(void *a, void *d)
209 if (read_connection(c, (unsigned char *)&hdr, sizeof(hdr))){
210 lib_parse(b->nal_cb, &hdr, c);
217 static void tcpnal_shutdown(bridge b)
219 shutdown_connections(b->lower);
222 /* Function: PTL_IFACE_TCP
223 * Arguments: pid_request: desired port number to bind to
224 * desired: passed NAL limits structure
225 * actual: returned NAL limits structure
226 * Returns: a nal structure on success, or null on failure
228 int tcpnal_init(bridge b)
232 b->nal_cb->cb_send=tcpnal_send;
233 b->nal_cb->cb_recv=tcpnal_recv;
234 b->shutdown=tcpnal_shutdown;
236 if (!(m=init_connections(PNAL_PORT(b->nal_cb->ni.nid,
238 from_connection,b))){
239 /* TODO: this needs to shut down the
240 newly created junk */
241 return(PTL_NAL_FAILED);