4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
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
27 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
31 * This file is part of Lustre, http://www.lustre.org/
32 * Lustre is a trademark of Sun Microsystems, Inc.
35 #ifndef __LIBCFS_WINNT_TCPIP_H__
36 #define __LIBCFS_WINNT_TCPIP_H__
38 #ifndef __LIBCFS_LIBCFS_H__
39 #error Do not #include this file directly. #include <libcfs/libcfs.h> instead
49 // iovec is defined in libcfs: winnt_prim.h
50 // lnetkiov_t is defined in lnet/types.h
52 typedef struct socket ks_tconn_t, cfs_socket_t;
54 // completion notification callback routine
56 typedef VOID (*ks_schedule_cb)(struct socket*, int);
58 #define SOCK_TEST_NOSPACE(s) (1)
66 #define KsPrint(X) KsPrintf X
73 // Socket Addresses Related ...
76 #define INADDR_ANY (ULONG)0x00000000
77 #define INADDR_LOOPBACK (ULONG)0x7f000001
78 #define INADDR_BROADCAST (ULONG)0xffffffff
79 #define INADDR_NONE (ULONG)0xffffffff
91 #define TCP_SOCKET_NODELAY 1 // disabling "Nagle"
92 #define TCP_SOCKET_KEEPALIVE 2
93 #define TCP_SOCKET_OOBINLINE 3
94 #define TCP_SOCKET_BSDURGENT 4
95 #define TCP_SOCKET_ATMARK 5
96 #define TCP_SOCKET_WINDOW 6
99 /* Flags we can use with send/ and recv.
100 Added those for 1003.1g not all are supported yet
105 #define MSG_DONTROUTE 4
106 #define MSG_TRYHARD 4 /* Synonym for MSG_DONTROUTE for DECnet */
108 #define MSG_PROBE 0x10 /* Do not send. Only probe path f.e. for MTU */
109 #define MSG_TRUNC 0x20
110 #define MSG_DONTWAIT 0x40 /* Nonblocking io */
111 #define MSG_EOR 0x80 /* End of record */
112 #define MSG_WAITALL 0x100 /* Wait for a full request */
113 #define MSG_FIN 0x200
114 #define MSG_SYN 0x400
115 #define MSG_CONFIRM 0x800 /* Confirm path validity */
116 #define MSG_RST 0x1000
117 #define MSG_ERRQUEUE 0x2000 /* Fetch message from error queue */
118 #define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE */
119 #define MSG_MORE 0x8000 /* Sender will send more */
121 #define MSG_EOF MSG_FIN
125 // Maximum TRANSPORT_ADDRESS Length
127 // it must >= FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address)
128 // + TDI_ADDRESS_LENGTH_IP
130 // I define it a little large and 16 bytes aligned to avoid possible overflow.
133 #define MAX_ADDRESS_LENGTH (0x30)
137 // Maximum Listers Children Sockets
140 #define MAX_CHILD_LISTENERS (4)
143 // Maximum EA Information Length
146 #define EA_MAX_LENGTH ( sizeof(FILE_FULL_EA_INFORMATION) - 1 + \
147 TDI_TRANSPORT_ADDRESS_LENGTH + 1 + \
151 #define UDP_DEVICE_NAME L"\\Device\\Udp"
152 #define TCP_DEVICE_NAME L"\\Device\\Tcp"
159 #define TDINAL_TSDU_DEFAULT_SIZE (0x10000)
161 #define KS_TSDU_MAGIC 'KSTD'
163 #define KS_TSDU_ATTACHED 0x00000001 // Attached to the socket receive tsdu list
165 typedef struct _KS_TSDU {
167 ULONG Magic; /* magic */
168 ULONG Flags; /* flags */
170 cfs_list_t Link; /* link list */
172 ULONG TotalLength; /* total size of KS_TSDU */
173 ULONG StartOffset; /* offset of the first Tsdu unit */
174 ULONG LastOffset; /* end offset of the last Tsdu unit */
184 } KS_TSDU, *PKS_TSDU;
186 #define TSDU_TYPE_BUF ((USHORT)0x5401)
187 #define TSDU_TYPE_DAT ((USHORT)0x5402)
188 #define TSDU_TYPE_MDL ((USHORT)0x5403)
190 #define KS_TSDU_COMM_PARTIAL 0x0001
192 typedef struct _KS_TSDU_BUF {
202 } KS_TSDU_BUF, *PKS_TSDU_BUF;
204 typedef struct _KS_TSDU_DAT {
217 } KS_TSDU_DAT, *PKS_TSDU_DAT;
219 #define KS_QWORD_ALIGN(x) (((x) + 0x07) & 0xFFFFFFF8)
220 #define KS_TSDU_STRU_SIZE(Len) (KS_QWORD_ALIGN((Len) + FIELD_OFFSET(KS_TSDU_DAT, Data[0])))
222 typedef struct _KS_TSDU_MDL {
223 USHORT TsduType; /* TSDU_TYPE_MDL */
224 USHORT TsduFlags; /* */
226 ULONG DataLength; /* total valid data length */
227 ULONG BaseOffset; /* payload offset in Tsdu */
228 ULONG StartOffset; /* offset in payload */
230 PVOID Descriptor; /* tdi descriptor for receiving */
232 } KS_TSDU_MDL, *PKS_TSDU_MDL;
234 typedef struct ks_engine_mgr {
242 typedef struct ks_engine_slot {
247 ks_engine_mgr_t * emgr;
250 typedef struct _KS_TSDUMGR {
256 ks_engine_slot_t Slot;
260 } KS_TSDUMGR, *PKS_TSDUMGR;
262 #define ks_lock_tsdumgr(mgr) spin_lock(&((mgr)->Lock))
263 #define ks_unlock_tsdumgr(mgr) spin_unlock(&((mgr)->Lock))
265 typedef struct _KS_CHAIN {
266 KS_TSDUMGR Normal; /* normal queue */
267 KS_TSDUMGR Expedited; /* OOB/expedited queue */
268 } KS_CHAIN, *PKS_CHAIN;
271 #define KS_CAN_SCHED(TM) ((TM)->TotalBytes >= ((TM)->Payload >> 2))
274 // Handler Settings Indictor
277 #define TDI_EVENT_MAXIMUM_HANDLER (TDI_EVENT_ERROR_EX + 1)
280 typedef struct _KS_EVENT_HANDLERS {
281 BOOLEAN IsActive[TDI_EVENT_MAXIMUM_HANDLER];
282 PVOID Handler [TDI_EVENT_MAXIMUM_HANDLER];
283 } KS_EVENT_HANDLERS, *PKS_EVENT_HANDLERS;
285 #define SetEventHandler(ha, ht, hr) do { \
286 ha.IsActive[ht] = TRUE; \
287 ha.Handler[ht] = (PVOID) (hr); \
291 // KSock Internal Structures
294 typedef struct _KS_ADDRESS {
297 TRANSPORT_ADDRESS Tdi;
298 UCHAR Pading[MAX_ADDRESS_LENGTH];
302 PFILE_OBJECT FileObject;
304 } KS_ADDRESS, *PKS_ADDRESS;
307 // Structures for Disconnect Workitem
310 typedef struct _KS_DISCONNECT_WORKITEM {
312 WORK_QUEUE_ITEM WorkItem; // Workitem to perform disconnection
313 ks_tconn_t * tconn; // tdi connecton
314 ULONG Flags; // connection broken/discnnection flags
315 KEVENT Event; // sync event
317 } KS_DISCONNECT_WORKITEM, *PKS_DISCONNECT_WORKITEM;
320 typedef struct _KS_CONNECTION {
322 HANDLE Handle; // Handle of the tdi connection
323 PFILE_OBJECT FileObject; // FileObject if the conn object
325 PTRANSPORT_ADDRESS Remote; // the ConnectionInfo of this connection
326 PTDI_CONNECTION_INFORMATION ConnectionInfo;
328 ULONG nagle; // Tcp options
330 } KS_CONNECTION, *PKS_CONNECTION;
337 typedef MDL ks_mdl_t;
338 typedef UNICODE_STRING ks_unicode_name_t;
339 typedef WORK_QUEUE_ITEM ks_workitem_t;
342 typedef KS_CHAIN ks_chain_t;
343 typedef KS_ADDRESS ks_tdi_addr_t;
344 typedef KS_CONNECTION ks_tconn_info_t;
345 typedef KS_DISCONNECT_WORKITEM ks_disconnect_t;
349 // Structures for transmission done Workitem
352 typedef struct ks_backlogs {
354 cfs_list_t list; /* list to link the backlog connections */
355 int num; /* number of backlogs in the list */
360 typedef struct ks_daemon {
362 ks_tconn_t * tconn; /* the listener connection object */
363 unsigned short nbacklogs; /* number of listening backlog conns */
364 unsigned short port; /* listening port number */
365 int shutdown; /* daemon threads is to exit */
366 cfs_list_t list; /* to be attached into ks_nal_data_t */
372 kstt_sender = 0, // normal sending connection type, it's active connection, while
373 // child tconn is for passive connection.
375 kstt_listener, // listener daemon type, it just acts as a daemon, and it does
376 // not have real connection. It manages children tcons to accept
377 // or refuse the connecting request from remote peers.
379 kstt_child, // accepted child connection type, it's parent must be Listener
387 ksts_uninited = 0, // tconn is just allocated (zero values), not initialized yet
389 ksts_inited, // tconn structure initialized: so it now can be identified as
390 // a sender, listener or a child
392 ksts_bind, // tconn is bound: the local address object (ip/port) is created.
393 // after being bound, we must call ksocknal_put_tconn to release
394 // the tconn objects, it's not safe just to free the memory of tconn.
396 ksts_associated, // the connection object is created and associated with the address
397 // object. so it's ready for connection. only for child and sender.
399 ksts_connecting, // only used by child tconn: in the ConnectEvent handler routine,
400 // it indicts the child tconn is busy to be connected to the peer.
402 ksts_connected, // the connection is built already: for sender and child
404 ksts_listening, // listener daemon is working, only for listener tconn
406 ksts_disconnected, // disconnected by user
407 ksts_aborted, // un-exptected broken status
409 ksts_last // total number of tconn statuses
413 #define KS_TCONN_MAGIC 'KSTM'
415 #define KS_TCONN_HANDLERS_SET 0x00000001 // Conection handlers are set.
416 #define KS_TCONN_DISCONNECT_BUSY 0x00010000 // Disconnect Workitem is queued ...
417 #define KS_TCONN_DESTROY_BUSY 0x00020000 // Destory Workitem is queued ...
419 #define KS_TCONN_DAEMON_STARTED 0x00100000 // indict the daemon is started,
420 // only valid for listener
423 ulong kstc_magic; /* Magic & Flags */
426 spinlock_t kstc_lock; /* serialise lock*/
427 void * kstc_conn; /* ks_conn_t */
429 ks_tconn_type_t kstc_type; /* tdi connection Type */
430 ks_tconn_state_t kstc_state; /* tdi connection state flag */
432 ks_unicode_name_t kstc_dev; /* tcp transport device name */
434 ks_tdi_addr_t kstc_addr; /* local address handlers / Objects */
436 cfs_atomic_t kstc_refcount; /* reference count of ks_tconn_t */
438 cfs_list_t kstc_list; /* linked to global ksocknal_data */
443 int nbacklog; /* total number of backlog tdi connections */
444 ks_backlogs_t kstc_listening; /* listeing backlog child connections */
445 ks_backlogs_t kstc_accepted; /* connected backlog child connections */
446 event_t kstc_accept_event; /* Signaled by AcceptedHander,
447 ksocknal_wait_accpeted_conns waits on */
448 event_t kstc_destroy_event; /* Signaled when accepted child is released */
452 ks_tconn_info_t kstc_info; /* Connection Info if Connected */
453 ks_chain_t kstc_recv; /* tsdu engine for data receiving */
454 ks_chain_t kstc_send; /* tsdu engine for data sending */
456 int kstc_queued; /* Attached to Parent->ChildList ... */
457 int kstc_queueno; /* 0: Attached to Listening list
458 1: Attached to Accepted list */
460 int kstc_busy; /* referred by ConnectEventCallback ? */
461 int kstc_accepted; /* the connection is built ready ? */
463 cfs_list_t kstc_link; /* linked to parent tdi connection */
464 ks_tconn_t * kstc_parent; /* pointers to it's listener parent */
468 ks_tconn_info_t kstc_info; /* Connection Info if Connected */
469 ks_chain_t kstc_recv; /* tsdu engine for data receiving */
470 ks_chain_t kstc_send; /* tsdu engine for data sending */
474 ulong kstc_snd_wnd; /* Sending window size */
475 ulong kstc_rcv_wnd; /* Recving window size */
477 ks_workitem_t kstc_destroy; /* tconn destruction workitem */
478 ks_disconnect_t kstc_disconnect; /* connection disconnect workitem */
480 ks_schedule_cb kstc_sched_cb; /* notification callback routine of completion */
484 libcfs_sock_error(struct socket *sock)
486 return (sock->kstc_state >= ksts_disconnected) ? ECONNRESET : 0;
491 libcfs_sock_wmem_queued(struct socket *sock)
496 #define TDINAL_WINDOW_DEFAULT_SIZE (0x100000)
497 #define TDINAL_MAX_TSDU_QUEUE_SIZE (0x200000)
499 struct _KS_UDP_COMPLETION_CONTEXT;
500 struct _KS_TCP_COMPLETION_CONTEXT;
505 (*PKS_UDP_COMPLETION_ROUTINE) (
507 IN struct _KS_UDP_COMPLETION_CONTEXT
514 (*PKS_TCP_COMPLETION_ROUTINE) (
516 IN struct _KS_TCP_COMPLETION_CONTEXT
521 // Udp Irp Completion Context
524 typedef struct _KS_UDP_COMPLETION_CONTEXT {
528 PFILE_OBJECT AddressObject;
532 PKS_UDP_COMPLETION_ROUTINE CompletionRoutine;
533 PVOID CompletionContext;
535 } KS_UDP_COMPLETION_CONTEXT, *PKS_UDP_COMPLETION_CONTEXT;
539 // Tcp Irp Completion Context (used by tcp data recv/send)
542 #define KS_TCP_CONTEXT_MAGIC 'CCTK'
544 typedef struct _KS_TCP_COMPLETION_CONTEXT {
545 PKEVENT Event; // Event to be waited on by Irp caller ...
546 ks_tconn_t * tconn; // the tdi connection
547 PKS_TCP_COMPLETION_ROUTINE CompletionRoutine;
548 PVOID CompletionContext;
549 PKS_TSDUMGR TsduMgr; // Tsdu buffer manager
550 ULONG Length; // Payload length in KsTsdu queue
551 PCHAR Buffer; // User allocated buffer
552 ULONG Magic; // Magic key
553 } KS_TCP_COMPLETION_CONTEXT, *PKS_TCP_COMPLETION_CONTEXT;
555 typedef KS_TCP_COMPLETION_CONTEXT ks_tdi_tx_t, ks_tdi_rx_t;
562 #define IOCTL_TCP_QUERY_INFORMATION_EX \
563 CTL_CODE(FILE_DEVICE_NETWORK, 0, METHOD_NEITHER, FILE_ANY_ACCESS)
564 #define IOCTL_TCP_SET_INFORMATION_EX \
565 CTL_CODE(FILE_DEVICE_NETWORK, 1, METHOD_BUFFERED, FILE_WRITE_ACCESS)
568 #define TcpBuildSetInformationEx(Irp, DevObj, FileObj, CompRoutine, Contxt, Buffer, BufferLen)\
570 PIO_STACK_LOCATION _IRPSP; \
571 if ( CompRoutine != NULL) { \
572 IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\
574 IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \
576 _IRPSP = IoGetNextIrpStackLocation (Irp); \
577 _IRPSP->MajorFunction = IRP_MJ_DEVICE_CONTROL; \
578 _IRPSP->DeviceObject = DevObj; \
579 _IRPSP->FileObject = FileObj; \
580 _IRPSP->Parameters.DeviceIoControl.OutputBufferLength = 0; \
581 _IRPSP->Parameters.DeviceIoControl.InputBufferLength = BufferLen; \
582 _IRPSP->Parameters.DeviceIoControl.IoControlCode = IOCTL_TCP_SET_INFORMATION_EX; \
583 Irp->AssociatedIrp.SystemBuffer = Buffer; \
587 #define TcpBuildQueryInformationEx(Irp, DevObj, FileObj, CompRoutine, Contxt, InBuffer, InLength, OutBuffer, OutLength)\
589 PIO_STACK_LOCATION _IRPSP; \
590 if ( CompRoutine != NULL) { \
591 IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\
593 IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \
595 _IRPSP = IoGetNextIrpStackLocation (Irp); \
596 _IRPSP->MajorFunction = IRP_MJ_DEVICE_CONTROL; \
597 _IRPSP->DeviceObject = DevObj; \
598 _IRPSP->FileObject = FileObj; \
599 _IRPSP->Parameters.DeviceIoControl.OutputBufferLength = OutLength; \
600 _IRPSP->Parameters.DeviceIoControl.InputBufferLength = InLength; \
601 _IRPSP->Parameters.DeviceIoControl.IoControlCode = IOCTL_TCP_QUERY_INFORMATION_EX; \
602 _IRPSP->Parameters.DeviceIoControl.Type3InputBuffer = InBuffer; \
603 Irp->UserBuffer = OutBuffer; \
606 typedef struct ks_addr_slot {
612 UNICODE_STRING devname;
618 * Tdi client information
621 UNICODE_STRING ksnd_client_name; /* tdi client module name */
622 HANDLE ksnd_pnp_handle; /* the handle for pnp changes */
624 spinlock_t ksnd_addrs_lock; /* serialize ip address list */
625 LIST_ENTRY ksnd_addrs_list; /* list of the ip addresses */
626 int ksnd_naddrs; /* number of the ip addresses */
629 * Tdilnd internal defintions
632 int ksnd_init; /* initialisation state */
634 TDI_PROVIDER_INFO ksnd_provider; /* tdi tcp/ip provider's information */
636 spinlock_t ksnd_tconn_lock; /* tdi connections access lock*/
638 int ksnd_ntconns; /* number of tconns in list */
639 cfs_list_t ksnd_tconns; /* tdi connections list */
640 cfs_mem_cache_t *ksnd_tconn_slab; /* ks_tconn_t allocation slabs*/
641 event_t ksnd_tconn_exit; /* event signal by last tconn */
643 spinlock_t ksnd_tsdu_lock; /* tsdu access serialise */
645 int ksnd_ntsdus; /* number of tsdu buffers allocated */
646 ulong ksnd_tsdu_size; /* the size of a signel tsdu buffer */
647 cfs_mem_cache_t *ksnd_tsdu_slab; /* slab cache for tsdu buffer allocation */
649 int ksnd_nfreetsdus; /* number of tsdu buffers in the freed list */
650 cfs_list_t ksnd_freetsdus; /* List of the freed Tsdu buffer. */
652 int ksnd_engine_nums; /* number of tcp sending engine threads */
653 ks_engine_mgr_t *ksnd_engine_mgr; /* tcp sending engine structure */
665 ks_query_local_ipaddr(
699 IN LOCK_OPERATION Operation,
704 KsReleaseMdl (IN PMDL Mdl,
708 KsQueueTdiEngine(ks_tconn_t * tconn, PKS_TSDUMGR);
711 KsRemoveTdiEngine(PKS_TSDUMGR);
729 #endif /* __KERNEL__ */
730 #endif /* __LIBCFS_WINNT_TCPIP_H__ */
734 * c-indentation-style: "K&R"