Whamcloud - gitweb
LU-1347 build: remove the vim/emacs modelines
[fs/lustre-release.git] / lnet / klnds / socklnd / socklnd_lib-darwin.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  */
30 /*
31  * This file is part of Lustre, http://www.lustre.org/
32  * Lustre is a trademark of Sun Microsystems, Inc.
33  *
34  * lnet/klnds/socklnd/socklnd_lib-darwin.c
35  *
36  * Darwin porting library
37  * Make things easy to port
38  *
39  * Author: Phil Schwan <phil@clusterfs.com>
40  */
41 #include <mach/mach_types.h>
42 #include <string.h>
43 #include <netinet/in.h>
44 #include <netinet/tcp.h>
45 #include <sys/file.h>
46
47 #include "socklnd.h"
48
49 # if CONFIG_SYSCTL && !CFS_SYSFS_MODULE_PARM
50
51 SYSCTL_DECL(_lnet);
52
53 SYSCTL_NODE (_lnet,           OID_AUTO,         ksocknal,        CTLFLAG_RW, 
54              0,                                 "ksocknal_sysctl");
55
56 SYSCTL_INT(_lnet_ksocknal,    OID_AUTO,         timeout, 
57            CTLTYPE_INT | CTLFLAG_RW ,           &ksocknal_tunables.ksnd_timeout, 
58            0,                                   "timeout");
59 SYSCTL_INT(_lnet_ksocknal,    OID_AUTO,         credits, 
60            CTLTYPE_INT | CTLFLAG_RW ,           &ksocknal_tunables.ksnd_credits, 
61            0,                                   "credits");
62 SYSCTL_INT(_lnet_ksocknal,    OID_AUTO,         peer_credits, 
63            CTLTYPE_INT | CTLFLAG_RW ,           &ksocknal_tunables.ksnd_peertxcredits, 
64            0,                                   "peer_credits");
65 SYSCTL_INT(_lnet_ksocknal,    OID_AUTO,         nconnds, 
66            CTLTYPE_INT | CTLFLAG_RW ,           &ksocknal_tunables.ksnd_nconnds, 
67            0,                                   "nconnds");
68 SYSCTL_INT(_lnet_ksocknal,    OID_AUTO,         min_reconnectms, 
69            CTLTYPE_INT | CTLFLAG_RW ,           &ksocknal_tunables.ksnd_min_reconnectms, 
70            0,                                   "min_reconnectms");
71 SYSCTL_INT(_lnet_ksocknal,    OID_AUTO,         max_reconnectms, 
72            CTLTYPE_INT | CTLFLAG_RW ,           &ksocknal_tunables.ksnd_max_reconnectms, 
73            0,                                   "max_reconnectms");
74 SYSCTL_INT(_lnet_ksocknal,    OID_AUTO,         eager_ack, 
75            CTLTYPE_INT | CTLFLAG_RW ,           &ksocknal_tunables.ksnd_eager_ack, 
76            0,                                   "eager_ack");
77 SYSCTL_INT(_lnet_ksocknal,    OID_AUTO,         typed, 
78            CTLTYPE_INT | CTLFLAG_RW ,           &ksocknal_tunables.ksnd_typed_conns, 
79            0,                                   "typed");
80 SYSCTL_INT(_lnet_ksocknal,    OID_AUTO,         min_bulk, 
81            CTLTYPE_INT | CTLFLAG_RW ,           &ksocknal_tunables.ksnd_min_bulk, 
82            0,                                   "min_bulk");
83 SYSCTL_INT(_lnet_ksocknal,    OID_AUTO,         rx_buffer_size, 
84            CTLTYPE_INT | CTLFLAG_RW ,           &ksocknal_tunables.ksnd_rx_buffer_size, 
85            0,                                   "rx_buffer_size");
86 SYSCTL_INT(_lnet_ksocknal,    OID_AUTO,         tx_buffer_size, 
87            CTLTYPE_INT | CTLFLAG_RW ,           &ksocknal_tunables.ksnd_tx_buffer_size, 
88            0,                                   "tx_buffer_size");
89 SYSCTL_INT(_lnet_ksocknal,    OID_AUTO,         nagle, 
90            CTLTYPE_INT | CTLFLAG_RW ,           &ksocknal_tunables.ksnd_nagle, 
91            0,                                   "nagle");
92 SYSCTL_INT(_lnet_ksocknal,    OID_AUTO,         keepalive_idle, 
93            CTLTYPE_INT | CTLFLAG_RW ,           &ksocknal_tunables.ksnd_keepalive_idle, 
94            0,                                   "keepalive_idle");
95 SYSCTL_INT(_lnet_ksocknal,    OID_AUTO,         keepalive_count, 
96            CTLTYPE_INT | CTLFLAG_RW ,           &ksocknal_tunables.ksnd_keepalive_count, 
97            0,                                   "keepalive_count");
98 SYSCTL_INT(_lnet_ksocknal,    OID_AUTO,         keepalive_intvl, 
99            CTLTYPE_INT | CTLFLAG_RW ,           &ksocknal_tunables.ksnd_keepalive_intvl, 
100            0,                                   "keepalive_intvl");
101
102 cfs_sysctl_table_t      ksocknal_top_ctl_table [] = {
103         &sysctl__lnet_ksocknal,
104         &sysctl__lnet_ksocknal_timeout,
105         &sysctl__lnet_ksocknal_credits,
106         &sysctl__lnet_ksocknal_peer_credits,
107         &sysctl__lnet_ksocknal_nconnds,
108         &sysctl__lnet_ksocknal_min_reconnectms,
109         &sysctl__lnet_ksocknal_max_reconnectms,
110         &sysctl__lnet_ksocknal_eager_ack,
111         &sysctl__lnet_ksocknal_typed,
112         &sysctl__lnet_ksocknal_min_bulk,
113         &sysctl__lnet_ksocknal_rx_buffer_size,
114         &sysctl__lnet_ksocknal_tx_buffer_size,
115         &sysctl__lnet_ksocknal_nagle,
116         &sysctl__lnet_ksocknal_keepalive_idle,
117         &sysctl__lnet_ksocknal_keepalive_count,
118         &sysctl__lnet_ksocknal_keepalive_intvl,
119         NULL
120 };
121
122 int
123 ksocknal_lib_tunables_init ()
124 {
125         ksocknal_tunables.ksnd_sysctl =
126                 cfs_register_sysctl_table (ksocknal_top_ctl_table, 0);
127
128         if (ksocknal_tunables.ksnd_sysctl == NULL)
129                 return -ENOMEM;
130
131         return 0;
132 }
133
134 void
135 ksocknal_lib_tunables_fini ()
136 {
137         if (ksocknal_tunables.ksnd_sysctl != NULL)
138                 cfs_unregister_sysctl_table (ksocknal_tunables.ksnd_sysctl);    
139 }
140 #else
141 int
142 ksocknal_lib_tunables_init ()
143 {
144         return 0;
145 }
146
147 void
148 ksocknal_lib_tunables_fini ()
149 {
150 }
151 #endif
152
153 /*
154  * To use bigger buffer for socket:
155  * 1. Increase nmbclusters (Cannot increased by sysctl because it's ready only, so
156  *    we must patch kernel).
157  * 2. Increase net.inet.tcp.reass.maxsegments
158  * 3. Increase net.inet.tcp.sendspace
159  * 4. Increase net.inet.tcp.recvspace
160  * 5. Increase kern.ipc.maxsockbuf
161  */
162 #define KSOCKNAL_MAX_BUFFER        (1152*1024)
163
164 void
165 ksocknal_lib_bind_irq (unsigned int irq)
166 {
167         return;
168 }
169
170 unsigned int
171 ksocknal_lib_sock_irq (cfs_socket_t *sock)
172 {
173         return 0;
174 }
175
176 int
177 ksocknal_lib_get_conn_addrs (ksock_conn_t *conn)
178
179         int rc = libcfs_sock_getaddr(conn->ksnc_sock, 1,
180                                      &conn->ksnc_ipaddr,
181                                      &conn->ksnc_port);
182
183         /* Didn't need the {get,put}connsock dance to deref ksnc_sock... */
184         LASSERT (!conn->ksnc_closing);
185
186         if (rc != 0) {
187                 CERROR ("Error %d getting sock peer IP\n", rc);
188                 return rc;
189         }
190
191         rc = libcfs_sock_getaddr(conn->ksnc_sock, 0,
192                                  &conn->ksnc_myipaddr, NULL);
193         if (rc != 0) {
194                 CERROR ("Error %d getting sock local IP\n", rc);
195                 return rc;
196         }
197
198         return 0;
199 }
200
201 #ifdef __DARWIN8__
202
203 int
204 ksocknal_lib_send_iov (ksock_conn_t *conn, ksock_tx_t *tx)
205 {
206         socket_t        sock = C2B_SOCK(conn->ksnc_sock);
207         size_t          sndlen;
208         int             nob;
209         int             rc;
210
211 #if SOCKNAL_SINGLE_FRAG_TX
212         struct iovec    scratch;
213         struct iovec   *scratchiov = &scratch;
214         unsigned int    niov = 1;
215 #else
216         struct iovec   *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
217         unsigned int    niov = tx->tx_niov;
218 #endif
219         struct msghdr msg = {
220                 .msg_name       = NULL,
221                 .msg_namelen    = 0,
222                 .msg_iov        = scratchiov,
223                 .msg_iovlen     = niov,
224                 .msg_control    = NULL,
225                 .msg_controllen = 0,
226                 .msg_flags      = MSG_DONTWAIT
227         };
228         
229         int  i;
230         
231         for (nob = i = 0; i < niov; i++) {
232                 scratchiov[i] = tx->tx_iov[i];
233                 nob += scratchiov[i].iov_len;
234         } 
235         
236         /* 
237          * XXX Liang:
238          * Linux has MSG_MORE, do we have anything to
239          * reduce number of partial TCP segments sent?
240          */
241         rc = -sock_send(sock, &msg, MSG_DONTWAIT, &sndlen);
242         if (rc == 0)
243                 rc = sndlen;
244         return rc;
245 }
246
247 int
248 ksocknal_lib_send_kiov (ksock_conn_t *conn, ksock_tx_t *tx)
249 {
250         socket_t       sock = C2B_SOCK(conn->ksnc_sock);
251         lnet_kiov_t   *kiov = tx->tx_kiov;
252         int            rc;
253         int            nob;
254         size_t         sndlen;
255
256 #if SOCKNAL_SINGLE_FRAG_TX
257         struct iovec  scratch;
258         struct iovec *scratchiov = &scratch;
259         unsigned int  niov = 1;
260 #else
261         struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
262         unsigned int  niov = tx->tx_nkiov;
263 #endif
264         struct msghdr msg = {
265                 .msg_name       = NULL,
266                 .msg_namelen    = 0,
267                 .msg_iov        = scratchiov,
268                 .msg_iovlen     = niov,
269                 .msg_control    = NULL,
270                 .msg_controllen = 0,
271                 .msg_flags      = MSG_DONTWAIT
272         };
273         
274         int           i;
275         
276         for (nob = i = 0; i < niov; i++) {
277                 scratchiov[i].iov_base = cfs_kmap(kiov[i].kiov_page) +
278                                          kiov[i].kiov_offset;
279                 nob += scratchiov[i].iov_len = kiov[i].kiov_len;
280         }
281
282         /* 
283          * XXX Liang:
284          * Linux has MSG_MORE, do wen have anyting to
285          * reduce number of partial TCP segments sent?
286          */
287         rc = -sock_send(sock, &msg, MSG_DONTWAIT, &sndlen);
288         for (i = 0; i < niov; i++)
289                 cfs_kunmap(kiov[i].kiov_page);
290         if (rc == 0)
291                 rc = sndlen;
292         return rc;
293 }
294
295 int
296 ksocknal_lib_recv_iov (ksock_conn_t *conn)
297 {
298 #if SOCKNAL_SINGLE_FRAG_RX
299         struct iovec  scratch;
300         struct iovec *scratchiov = &scratch;
301         unsigned int  niov = 1;
302 #else
303         struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
304         unsigned int  niov = conn->ksnc_rx_niov;
305 #endif
306         struct iovec *iov = conn->ksnc_rx_iov;
307         struct msghdr msg = {
308                 .msg_name       = NULL,
309                 .msg_namelen    = 0,
310                 .msg_iov        = scratchiov,
311                 .msg_iovlen     = niov,
312                 .msg_control    = NULL,
313                 .msg_controllen = 0,
314                 .msg_flags      = 0
315         };
316         size_t       rcvlen;
317         int          nob;
318         int          i;
319         int          rc;
320
321         LASSERT (niov > 0);
322
323         for (nob = i = 0; i < niov; i++) {
324                 scratchiov[i] = iov[i];
325                 nob += scratchiov[i].iov_len;
326         }
327         LASSERT (nob <= conn->ksnc_rx_nob_wanted); 
328         rc = -sock_receive (C2B_SOCK(conn->ksnc_sock), &msg, MSG_DONTWAIT, &rcvlen);
329         if (rc == 0)
330                 rc = rcvlen;
331
332         return rc;
333 }
334
335 int
336 ksocknal_lib_recv_kiov (ksock_conn_t *conn)
337 {
338 #if SOCKNAL_SINGLE_FRAG_RX
339         struct iovec  scratch;
340         struct iovec *scratchiov = &scratch;
341         unsigned int  niov = 1;
342 #else
343         struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
344         unsigned int  niov = conn->ksnc_rx_nkiov;
345 #endif
346         lnet_kiov_t   *kiov = conn->ksnc_rx_kiov;
347         struct msghdr msg = {
348                 .msg_name       = NULL,
349                 .msg_namelen    = 0,
350                 .msg_iov        = scratchiov,
351                 .msg_iovlen     = niov,
352                 .msg_control    = NULL,
353                 .msg_controllen = 0,
354                 .msg_flags      = 0
355         };
356         int          nob;
357         int          i;
358         size_t       rcvlen;
359         int          rc;
360
361         /* NB we can't trust socket ops to either consume our iovs
362          * or leave them alone. */
363         for (nob = i = 0; i < niov; i++) {
364                 scratchiov[i].iov_base = cfs_kmap(kiov[i].kiov_page) + \
365                                          kiov[i].kiov_offset;
366                 nob += scratchiov[i].iov_len = kiov[i].kiov_len;
367         }
368         LASSERT (nob <= conn->ksnc_rx_nob_wanted);
369         rc = -sock_receive(C2B_SOCK(conn->ksnc_sock), &msg, MSG_DONTWAIT, &rcvlen); 
370         for (i = 0; i < niov; i++)
371                 cfs_kunmap(kiov[i].kiov_page); 
372         if (rc == 0)
373                 rc = rcvlen;
374         return (rc);
375 }
376
377 void
378 ksocknal_lib_eager_ack (ksock_conn_t *conn)
379 {
380         /* XXX Liang: */
381 }
382
383 int
384 ksocknal_lib_get_conn_tunables (ksock_conn_t *conn, int *txmem, int *rxmem, int *nagle)
385 {
386         socket_t       sock = C2B_SOCK(conn->ksnc_sock);
387         int            len;
388         int            rc;
389
390         rc = ksocknal_connsock_addref(conn);
391         if (rc != 0) {
392                 LASSERT (conn->ksnc_closing);
393                 *txmem = *rxmem = *nagle = 0;
394                 return (-ESHUTDOWN);
395         }
396         rc = libcfs_sock_getbuf(conn->ksnc_sock, txmem, rxmem);
397         if (rc == 0) {
398                 len = sizeof(*nagle);
399                 rc = -sock_getsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
400                                       nagle, &len);
401         }
402         ksocknal_connsock_decref(conn);
403
404         if (rc == 0)
405                 *nagle = !*nagle;
406         else
407                 *txmem = *rxmem = *nagle = 0;
408
409         return (rc);
410 }
411
412 int
413 ksocknal_lib_setup_sock (cfs_socket_t *sock)
414 {
415         int             rc; 
416         int             option; 
417         int             keep_idle; 
418         int             keep_intvl; 
419         int             keep_count; 
420         int             do_keepalive; 
421         socket_t        so = C2B_SOCK(sock);
422         struct linger   linger;
423
424         /* Ensure this socket aborts active sends immediately when we close
425          * it. */
426         linger.l_onoff = 0;
427         linger.l_linger = 0;
428         rc = -sock_setsockopt(so, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));
429         if (rc != 0) {
430                 CERROR ("Can't set SO_LINGER: %d\n", rc);
431                 return (rc);
432         }
433
434         if (!*ksocknal_tunables.ksnd_nagle) { 
435                 option = 1; 
436                 rc = -sock_setsockopt(so, IPPROTO_TCP, TCP_NODELAY, &option, sizeof(option));
437                 if (rc != 0) { 
438                         CERROR ("Can't disable nagle: %d\n", rc); 
439                         return (rc);
440                 } 
441         } 
442
443         rc = libcfs_sock_setbuf(sock,
444                                 *ksocknal_tunables.ksnd_tx_buffer_size,
445                                 *ksocknal_tunables.ksnd_rx_buffer_size);
446         if (rc != 0) {
447                 CERROR ("Can't set buffer tx %d, rx %d buffers: %d\n",
448                         *ksocknal_tunables.ksnd_tx_buffer_size,
449                         *ksocknal_tunables.ksnd_rx_buffer_size, rc);
450                 return (rc);
451         }
452
453         /* snapshot tunables */ 
454         keep_idle  = *ksocknal_tunables.ksnd_keepalive_idle; 
455         keep_count = *ksocknal_tunables.ksnd_keepalive_count; 
456         keep_intvl = *ksocknal_tunables.ksnd_keepalive_intvl;
457
458         do_keepalive = (keep_idle > 0 && keep_count > 0 && keep_intvl > 0); 
459         option = (do_keepalive ? 1 : 0); 
460
461         rc = -sock_setsockopt(so, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option)); 
462         if (rc != 0) { 
463                 CERROR ("Can't set SO_KEEPALIVE: %d\n", rc); 
464                 return (rc);
465         }
466         
467         if (!do_keepalive)
468                 return (rc);
469         rc = -sock_setsockopt(so, IPPROTO_TCP, TCP_KEEPALIVE, 
470                               &keep_idle, sizeof(keep_idle));
471         
472         return (rc);
473 }
474
475 void
476 ksocknal_lib_push_conn(ksock_conn_t *conn)
477
478         socket_t        sock; 
479         int             val = 1; 
480         int             rc; 
481         
482         rc = ksocknal_connsock_addref(conn); 
483         if (rc != 0)            /* being shut down */ 
484                 return; 
485         sock = C2B_SOCK(conn->ksnc_sock); 
486
487         rc = -sock_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); 
488         LASSERT(rc == 0);
489
490         ksocknal_connsock_decref(conn);
491         return;
492 }
493
494 extern void ksocknal_read_callback (ksock_conn_t *conn);
495 extern void ksocknal_write_callback (ksock_conn_t *conn);
496
497 static void
498 ksocknal_upcall(socket_t so, void *arg, int waitf)
499 {
500         ksock_conn_t  *conn = (ksock_conn_t *)arg;
501         ENTRY;
502
503         read_lock (&ksocknal_data.ksnd_global_lock);
504         if (conn == NULL)
505                 goto out;
506
507         ksocknal_read_callback (conn);
508         /* XXX Liang */
509         ksocknal_write_callback (conn);
510 out:
511         read_unlock (&ksocknal_data.ksnd_global_lock);
512         EXIT;
513 }
514
515 void
516 ksocknal_lib_save_callback(cfs_socket_t *sock, ksock_conn_t *conn)
517
518         /* No callback need to save in osx */
519         return;
520 }
521
522 void
523 ksocknal_lib_set_callback(cfs_socket_t *sock, ksock_conn_t *conn)
524
525         libcfs_sock_set_cb(sock, ksocknal_upcall, (void *)conn);
526         return;
527 }
528
529 void 
530 ksocknal_lib_reset_callback(cfs_socket_t *sock, ksock_conn_t *conn)
531
532         libcfs_sock_reset_cb(sock);
533 }
534
535 #else /* !__DARWIN8__ */
536
537 int
538 ksocknal_lib_send_iov (ksock_conn_t *conn, ksock_tx_t *tx)
539
540 #if SOCKNAL_SINGLE_FRAG_TX 
541         struct iovec    scratch; 
542         struct iovec   *scratchiov = &scratch; 
543         unsigned int    niov = 1;
544 #else 
545         struct iovec   *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; 
546         unsigned int    niov = tx->tx_niov;
547 #endif
548         struct socket *sock = conn->ksnc_sock;
549         int            nob;
550         int            rc;
551         int            i;
552         struct uio  suio = {
553                 .uio_iov        = scratchiov,
554                 .uio_iovcnt     = niov,
555                 .uio_offset     = 0,
556                 .uio_resid      = 0,            /* This will be valued after a while */
557                 .uio_segflg     = UIO_SYSSPACE,
558                 .uio_rw         = UIO_WRITE,
559                 .uio_procp      = NULL
560         };
561         int  flags = MSG_DONTWAIT;
562         CFS_DECL_NET_DATA;
563
564         for (nob = i = 0; i < niov; i++) { 
565                 scratchiov[i] = tx->tx_iov[i]; 
566                 nob += scratchiov[i].iov_len; 
567         }
568         suio.uio_resid = nob;
569
570         CFS_NET_IN;
571         rc = sosend(sock, NULL, &suio, (struct mbuf *)0, (struct mbuf *)0, flags);
572         CFS_NET_EX; 
573
574         /* NB there is no return value can indicate how many 
575          * have been sent and how many resid, we have to get 
576          * sent bytes from suio. */
577         if (rc != 0) {
578                 if (suio.uio_resid != nob &&\
579                     (rc == ERESTART || rc == EINTR || rc == EWOULDBLOCK))
580                         /* We have sent something */
581                         rc = nob - suio.uio_resid;
582                 else if ( rc == EWOULDBLOCK ) 
583                         /* Actually, EAGAIN and EWOULDBLOCK have same value in OSX */
584                         rc = -EAGAIN;   
585                 else 
586                         rc = -rc;
587         } else  /* rc == 0 */
588                 rc = nob - suio.uio_resid;
589
590         return rc;
591 }
592
593 int
594 ksocknal_lib_send_kiov (ksock_conn_t *conn, ksock_tx_t *tx)
595 {
596 #if SOCKNAL_SINGLE_FRAG_TX || !SOCKNAL_RISK_KMAP_DEADLOCK 
597         struct iovec  scratch; 
598         struct iovec *scratchiov = &scratch; 
599         unsigned int  niov = 1;
600 #else
601         struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
602         unsigned int  niov = tx->tx_nkiov;
603 #endif
604         struct socket *sock = conn->ksnc_sock;
605         lnet_kiov_t    *kiov = tx->tx_kiov;
606         int            nob;
607         int            rc;
608         int            i;
609         struct  uio suio = {
610                 .uio_iov        = scratchiov,
611                 .uio_iovcnt     = niov,
612                 .uio_offset     = 0, 
613                 .uio_resid      = 0,    /* It should be valued after a while */
614                 .uio_segflg     = UIO_SYSSPACE,
615                 .uio_rw         = UIO_WRITE,
616                 .uio_procp      = NULL
617         };
618         int  flags = MSG_DONTWAIT;
619         CFS_DECL_NET_DATA; 
620         
621         for (nob = i = 0; i < niov; i++) { 
622                 scratchiov[i].iov_base = cfs_kmap(kiov[i].kiov_page) + 
623                                          kiov[i].kiov_offset; 
624                 nob += scratchiov[i].iov_len = kiov[i].kiov_len; 
625         }
626         suio.uio_resid = nob;
627
628         CFS_NET_IN;
629         rc = sosend(sock, NULL, &suio, (struct mbuf *)0, (struct mbuf *)0, flags);
630         CFS_NET_EX;
631
632         for (i = 0; i < niov; i++) 
633                 cfs_kunmap(kiov[i].kiov_page);
634
635         if (rc != 0) {
636                 if (suio.uio_resid != nob &&\
637                     (rc == ERESTART || rc == EINTR || rc == EWOULDBLOCK))
638                         /* We have sent something */
639                         rc = nob - suio.uio_resid; 
640                 else if ( rc == EWOULDBLOCK ) 
641                         /* EAGAIN and EWOULD BLOCK have same value in OSX */
642                         rc = -EAGAIN;   
643                 else 
644                         rc = -rc;
645         } else  /* rc == 0 */
646                 rc = nob - suio.uio_resid;
647
648         return rc;
649 }
650
651 /*
652  * liang: Hack of inpcb and tcpcb.
653  * To get tcpcb of a socket, and call tcp_output
654  * to send quick ack.
655  */
656 struct ks_tseg_qent{
657         int foo;
658 };
659
660 struct ks_tcptemp{
661         int foo;
662 };
663
664 LIST_HEAD(ks_tsegqe_head, ks_tseg_qent);
665
666 struct ks_tcpcb {
667         struct ks_tsegqe_head t_segq;
668         int     t_dupacks;
669         struct ks_tcptemp *unused;
670         int    t_timer[4];
671         struct inpcb *t_inpcb;
672         int    t_state;
673         u_int  t_flags;
674         /*
675          * There are more fields but we dont need
676          * ......
677          */
678 };
679
680 #define TF_ACKNOW       0x00001
681 #define TF_DELACK       0x00002
682
683 struct ks_inpcb {
684         LIST_ENTRY(ks_inpcb) inp_hash;
685         struct  in_addr reserved1;
686         struct  in_addr reserved2;
687         u_short inp_fport;
688         u_short inp_lport;
689         LIST_ENTRY(inpcb) inp_list;
690         caddr_t inp_ppcb;
691         /*
692          * There are more fields but we dont need
693          * ......
694          */
695 };
696
697 #define ks_sotoinpcb(so)   ((struct ks_inpcb *)(so)->so_pcb)
698 #define ks_intotcpcb(ip)   ((struct ks_tcpcb *)(ip)->inp_ppcb)
699 #define ks_sototcpcb(so)   (intotcpcb(sotoinpcb(so)))
700
701 void
702 ksocknal_lib_eager_ack (ksock_conn_t *conn)
703 {
704         struct socket *sock = conn->ksnc_sock;
705         struct ks_inpcb  *inp = ks_sotoinpcb(sock);
706         struct ks_tcpcb  *tp = ks_intotcpcb(inp);
707         int s;
708         CFS_DECL_NET_DATA;
709
710         extern int tcp_output(register struct ks_tcpcb *tp);
711
712         CFS_NET_IN;
713         s = splnet();
714
715         /*
716          * No TCP_QUICKACK supported in BSD, so I have to call tcp_fasttimo
717          * to send immediate ACK. 
718          */
719         if (tp && tp->t_flags & TF_DELACK){
720                 tp->t_flags &= ~TF_DELACK;
721                 tp->t_flags |= TF_ACKNOW;
722                 (void) tcp_output(tp);
723         }
724         splx(s);
725
726         CFS_NET_EX;
727
728         return;
729 }
730
731 int
732 ksocknal_lib_recv_iov (ksock_conn_t *conn)
733 {
734 #if SOCKNAL_SINGLE_FRAG_RX 
735         struct iovec  scratch; 
736         struct iovec *scratchiov = &scratch; 
737         unsigned int  niov = 1;
738 #else 
739         struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
740         unsigned int  niov = conn->ksnc_rx_niov;
741 #endif
742         struct iovec *iov = conn->ksnc_rx_iov;
743         int          nob;
744         int          rc;
745         int          i;
746         struct uio  ruio = {
747                 .uio_iov        = scratchiov,
748                 .uio_iovcnt     = niov,
749                 .uio_offset     = 0,
750                 .uio_resid      = 0,    /* It should be valued after a while */
751                 .uio_segflg     = UIO_SYSSPACE,
752                 .uio_rw         = UIO_READ,
753                 .uio_procp      = NULL
754         };
755         int         flags = MSG_DONTWAIT;
756         CFS_DECL_NET_DATA;
757
758         for (nob = i = 0; i < niov; i++) { 
759                 scratchiov[i] = iov[i]; 
760                 nob += scratchiov[i].iov_len; 
761         } 
762         LASSERT (nob <= conn->ksnc_rx_nob_wanted);
763
764         ruio.uio_resid = nob;
765
766         CFS_NET_IN;
767         rc = soreceive(conn->ksnc_sock, (struct sockaddr **)0, &ruio, (struct mbuf **)0, (struct mbuf **)0, &flags);
768         CFS_NET_EX;
769         if (rc){
770                 if (ruio.uio_resid != nob && \
771                     (rc == ERESTART || rc == EINTR || rc == EWOULDBLOCK || rc == EAGAIN))
772                         /* data particially received */
773                         rc = nob - ruio.uio_resid; 
774                 else if (rc == EWOULDBLOCK) 
775                         /* EAGAIN and EWOULD BLOCK have same value in OSX */
776                         rc = -EAGAIN; 
777                 else
778                         rc = -rc;
779         } else 
780                 rc = nob - ruio.uio_resid;
781
782         return (rc);
783 }
784
785 int
786 ksocknal_lib_recv_kiov (ksock_conn_t *conn)
787 {
788 #if SOCKNAL_SINGLE_FRAG_RX || !SOCKNAL_RISK_KMAP_DEADLOCK 
789         struct iovec  scratch; 
790         struct iovec *scratchiov = &scratch; 
791         unsigned int  niov = 1;
792 #else 
793         struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
794         unsigned int  niov = conn->ksnc_rx_nkiov;
795 #endif
796         lnet_kiov_t    *kiov = conn->ksnc_rx_kiov;
797         int           nob;
798         int           rc;
799         int           i;
800         struct uio  ruio = {
801                 .uio_iov        = scratchiov,
802                 .uio_iovcnt     = niov,
803                 .uio_offset     = 0,
804                 .uio_resid      = 0,
805                 .uio_segflg     = UIO_SYSSPACE,
806                 .uio_rw         = UIO_READ,
807                 .uio_procp      = NULL
808         };
809         int         flags = MSG_DONTWAIT;
810         CFS_DECL_NET_DATA;
811
812         for (nob = i = 0; i < niov; i++) { 
813                 scratchiov[i].iov_base = cfs_kmap(kiov[i].kiov_page) + kiov[i].kiov_offset; 
814                 nob += scratchiov[i].iov_len = kiov[i].kiov_len; 
815         } 
816         LASSERT (nob <= conn->ksnc_rx_nob_wanted);
817
818         ruio.uio_resid = nob;
819
820         CFS_NET_IN;
821         rc = soreceive(conn->ksnc_sock, (struct sockaddr **)0, &ruio, (struct mbuf **)0, NULL, &flags);
822         CFS_NET_EX;
823
824         for (i = 0; i < niov; i++) 
825                 cfs_kunmap(kiov[i].kiov_page);
826
827         if (rc){
828                 if (ruio.uio_resid != nob && \
829                     (rc == ERESTART || rc == EINTR || rc == EWOULDBLOCK))
830                         /* data particially received */
831                         rc = nob - ruio.uio_resid; 
832                 else if (rc == EWOULDBLOCK)
833                         /* receive blocked, EWOULDBLOCK == EAGAIN */ 
834                         rc = -EAGAIN; 
835                 else
836                         rc = -rc;
837         } else
838                 rc = nob - ruio.uio_resid;
839
840         return (rc);
841 }
842
843 int
844 ksocknal_lib_get_conn_tunables (ksock_conn_t *conn, int *txmem, int *rxmem, int *nagle)
845 {
846         struct socket *sock = conn->ksnc_sock;
847         int            rc;
848
849         rc = ksocknal_connsock_addref(conn);
850         if (rc != 0) {
851                 LASSERT (conn->ksnc_closing);
852                 *txmem = *rxmem = *nagle = 0;
853                 return -ESHUTDOWN;
854         }
855         rc = libcfs_sock_getbuf(sock, txmem, rxmem);
856         if (rc == 0) {
857                 struct sockopt  sopt;
858                 int            len;
859                 CFS_DECL_NET_DATA;
860
861                 len = sizeof(*nagle);
862                 bzero(&sopt, sizeof sopt);
863                 sopt.sopt_dir = SOPT_GET; 
864                 sopt.sopt_level = IPPROTO_TCP;
865                 sopt.sopt_name = TCP_NODELAY;
866                 sopt.sopt_val = nagle;
867                 sopt.sopt_valsize = len;
868
869                 CFS_NET_IN;
870                 rc = -sogetopt(sock, &sopt);
871                 CFS_NET_EX;
872         }
873
874         ksocknal_connsock_decref(conn);
875
876         if (rc == 0)
877                 *nagle = !*nagle;
878         else
879                 *txmem = *rxmem = *nagle = 0;
880         return (rc);
881 }
882
883 int
884 ksocknal_lib_setup_sock (struct socket *so)
885 {
886         struct sockopt  sopt;
887         int             rc; 
888         int             option; 
889         int             keep_idle; 
890         int             keep_intvl; 
891         int             keep_count; 
892         int             do_keepalive; 
893         struct linger   linger;
894         CFS_DECL_NET_DATA;
895
896         rc = libcfs_sock_setbuf(so,
897                                 *ksocknal_tunables.ksnd_tx_buffer_size,
898                                 *ksocknal_tunables.ksnd_rx_buffer_size);
899         if (rc != 0) {
900                 CERROR ("Can't set buffer tx %d, rx %d buffers: %d\n",
901                         *ksocknal_tunables.ksnd_tx_buffer_size,
902                         *ksocknal_tunables.ksnd_rx_buffer_size, rc);
903                 return (rc);
904         }
905
906         /* Ensure this socket aborts active sends immediately when we close
907          * it. */
908         bzero(&sopt, sizeof sopt);
909
910         linger.l_onoff = 0;
911         linger.l_linger = 0;
912         sopt.sopt_dir = SOPT_SET;
913         sopt.sopt_level = SOL_SOCKET;
914         sopt.sopt_name = SO_LINGER;
915         sopt.sopt_val = &linger;
916         sopt.sopt_valsize = sizeof(linger);
917
918         CFS_NET_IN;
919         rc = -sosetopt(so, &sopt);
920         if (rc != 0) {
921                 CERROR ("Can't set SO_LINGER: %d\n", rc);
922                 goto out;
923         }
924
925         if (!*ksocknal_tunables.ksnd_nagle) { 
926                 option = 1; 
927                 bzero(&sopt, sizeof sopt);
928                 sopt.sopt_dir = SOPT_SET; 
929                 sopt.sopt_level = IPPROTO_TCP;
930                 sopt.sopt_name = TCP_NODELAY; 
931                 sopt.sopt_val = &option; 
932                 sopt.sopt_valsize = sizeof(option);
933                 rc = -sosetopt(so, &sopt);
934                 if (rc != 0) { 
935                         CERROR ("Can't disable nagle: %d\n", rc); 
936                         goto out;
937                 } 
938         } 
939
940         /* snapshot tunables */ 
941         keep_idle  = *ksocknal_tunables.ksnd_keepalive_idle; 
942         keep_count = *ksocknal_tunables.ksnd_keepalive_count; 
943         keep_intvl = *ksocknal_tunables.ksnd_keepalive_intvl;
944
945         do_keepalive = (keep_idle > 0 && keep_count > 0 && keep_intvl > 0); 
946         option = (do_keepalive ? 1 : 0); 
947         bzero(&sopt, sizeof sopt); 
948         sopt.sopt_dir = SOPT_SET; 
949         sopt.sopt_level = SOL_SOCKET; 
950         sopt.sopt_name = SO_KEEPALIVE; 
951         sopt.sopt_val = &option; 
952         sopt.sopt_valsize = sizeof(option); 
953         rc = -sosetopt(so, &sopt); 
954         if (rc != 0) { 
955                 CERROR ("Can't set SO_KEEPALIVE: %d\n", rc); 
956                 goto out; 
957         }
958         
959         if (!do_keepalive) { 
960                 /* no more setting, just return */
961                 rc = 0;
962                 goto out;
963         } 
964         
965         bzero(&sopt, sizeof sopt); 
966         sopt.sopt_dir = SOPT_SET; 
967         sopt.sopt_level = IPPROTO_TCP; 
968         sopt.sopt_name = TCP_KEEPALIVE; 
969         sopt.sopt_val = &keep_idle; 
970         sopt.sopt_valsize = sizeof(keep_idle); 
971         rc = -sosetopt(so, &sopt); 
972         if (rc != 0) { 
973                 CERROR ("Can't set TCP_KEEPALIVE : %d\n", rc); 
974                 goto out; 
975         }
976 out:
977         CFS_NET_EX;
978         return (rc);
979 }
980
981 void
982 ksocknal_lib_push_conn(ksock_conn_t *conn)
983
984         struct socket   *sock; 
985         struct sockopt  sopt; 
986         int             val = 1; 
987         int             rc; 
988         CFS_DECL_NET_DATA; 
989         
990         rc = ksocknal_connsock_addref(conn); 
991         if (rc != 0)            /* being shut down */ 
992                 return; 
993         sock = conn->ksnc_sock; 
994         bzero(&sopt, sizeof sopt); 
995         sopt.sopt_dir = SOPT_SET; 
996         sopt.sopt_level = IPPROTO_TCP; 
997         sopt.sopt_name = TCP_NODELAY; 
998         sopt.sopt_val = &val; 
999         sopt.sopt_valsize = sizeof val; 
1000
1001         CFS_NET_IN; 
1002         sosetopt(sock, &sopt); 
1003         CFS_NET_EX; 
1004
1005         ksocknal_connsock_decref(conn);
1006         return;
1007 }
1008
1009
1010 extern void ksocknal_read_callback (ksock_conn_t *conn);
1011 extern void ksocknal_write_callback (ksock_conn_t *conn);
1012
1013 static void
1014 ksocknal_upcall(struct socket *so, caddr_t arg, int waitf)
1015 {
1016         ksock_conn_t  *conn = (ksock_conn_t *)arg;
1017         ENTRY;
1018
1019         read_lock (&ksocknal_data.ksnd_global_lock);
1020         if (conn == NULL)
1021                 goto out;
1022
1023         if (so->so_rcv.sb_flags & SB_UPCALL) {
1024                 extern int soreadable(struct socket *so);
1025                 if (conn->ksnc_rx_nob_wanted && soreadable(so))
1026                         /* To verify whether the upcall is for receive */
1027                         ksocknal_read_callback (conn);
1028         }
1029         /* go foward? */
1030         if (so->so_snd.sb_flags & SB_UPCALL){
1031                 extern int sowriteable(struct socket *so);
1032                 if (sowriteable(so))
1033                         /* socket is writable */
1034                         ksocknal_write_callback(conn);
1035         }
1036 out:
1037         read_unlock (&ksocknal_data.ksnd_global_lock);
1038
1039         EXIT;
1040 }
1041
1042 void
1043 ksocknal_lib_save_callback(struct socket *sock, ksock_conn_t *conn)
1044
1045         /* No callback need to save in osx */
1046         return;
1047 }
1048
1049 void
1050 ksocknal_lib_set_callback(struct socket *sock, ksock_conn_t *conn)
1051
1052         CFS_DECL_NET_DATA;
1053
1054         CFS_NET_IN;
1055         sock->so_upcallarg = (void *)conn;
1056         sock->so_upcall = ksocknal_upcall; 
1057         sock->so_snd.sb_timeo = 0; 
1058         sock->so_rcv.sb_timeo = cfs_time_seconds(2);
1059         sock->so_rcv.sb_flags |= SB_UPCALL; 
1060         sock->so_snd.sb_flags |= SB_UPCALL; 
1061         CFS_NET_EX;
1062         return;
1063 }
1064
1065 void
1066 ksocknal_lib_act_callback(struct socket *sock, ksock_conn_t *conn)
1067 {
1068         CFS_DECL_NET_DATA;
1069
1070         CFS_NET_IN;
1071         ksocknal_upcall (sock, (void *)conn, 0);
1072         CFS_NET_EX;
1073 }
1074
1075 void 
1076 ksocknal_lib_reset_callback(struct socket *sock, ksock_conn_t *conn)
1077
1078         CFS_DECL_NET_DATA;
1079
1080         CFS_NET_IN;
1081         sock->so_rcv.sb_flags &= ~SB_UPCALL; 
1082         sock->so_snd.sb_flags &= ~SB_UPCALL;
1083         sock->so_upcall = NULL; 
1084         sock->so_upcallarg = NULL; 
1085         CFS_NET_EX;
1086 }
1087
1088 #endif  /* !__DARWIN8__ */