1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=4:tabstop=4:
4 * Copyright (C) 2004 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
8 * Lustre is free software; you can redistribute it and/or modify it under the
9 * terms of version 2 of the GNU General Public License as published by the
10 * Free Software Foundation.
12 * Lustre is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along
18 * with Lustre; if not, write to the Free Software Foundation, Inc., 675 Mass
19 * Ave, Cambridge, MA 02139, USA.
21 * Implementation of portable time API for Winnt (kernel and user-level).
25 #ifndef __LIBCFS_WINNT_TCPIP_H__
26 #define __LIBCFS_WINNT_TCPIP_H__
28 #ifndef __LIBCFS_LIBCFS_H__
29 #error Do not #include this file directly. #include <libcfs/libcfs.h> instead
39 // iovec is defined in libcfs: winnt_prim.h
40 // lnetkiov_t is defined in lnet/types.h
42 typedef struct socket ksock_tconn_t;
43 typedef struct socket cfs_socket_t;
45 // completion notification callback routine
47 typedef VOID (*ksock_schedule_cb)(struct socket*, int, void *, ulong_ptr);
49 /* completion routine to update tx structure for async sending */
50 typedef PVOID (*ksock_update_tx)(struct socket*, PVOID tx, ulong_ptr);
58 #define KsPrint(X) KsPrintf X
65 // Socket Addresses Related ...
68 #define INADDR_ANY (ULONG)0x00000000
69 #define INADDR_LOOPBACK (ULONG)0x7f000001
70 #define INADDR_BROADCAST (ULONG)0xffffffff
71 #define INADDR_NONE (ULONG)0xffffffff
83 #define TCP_SOCKET_NODELAY 1 // disabling "Nagle"
84 #define TCP_SOCKET_KEEPALIVE 2
85 #define TCP_SOCKET_OOBINLINE 3
86 #define TCP_SOCKET_BSDURGENT 4
87 #define TCP_SOCKET_ATMARK 5
88 #define TCP_SOCKET_WINDOW 6
91 /* Flags we can use with send/ and recv.
92 Added those for 1003.1g not all are supported yet
97 #define MSG_DONTROUTE 4
98 #define MSG_TRYHARD 4 /* Synonym for MSG_DONTROUTE for DECnet */
100 #define MSG_PROBE 0x10 /* Do not send. Only probe path f.e. for MTU */
101 #define MSG_TRUNC 0x20
102 #define MSG_DONTWAIT 0x40 /* Nonblocking io */
103 #define MSG_EOR 0x80 /* End of record */
104 #define MSG_WAITALL 0x100 /* Wait for a full request */
105 #define MSG_FIN 0x200
106 #define MSG_SYN 0x400
107 #define MSG_CONFIRM 0x800 /* Confirm path validity */
108 #define MSG_RST 0x1000
109 #define MSG_ERRQUEUE 0x2000 /* Fetch message from error queue */
110 #define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE */
111 #define MSG_MORE 0x8000 /* Sender will send more */
113 #define MSG_EOF MSG_FIN
117 // Maximum TRANSPORT_ADDRESS Length
119 // it must >= FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address)
120 // + TDI_ADDRESS_LENGTH_IP
122 // I define it a little large and 16 bytes aligned to avoid possible overflow.
125 #define MAX_ADDRESS_LENGTH (0x30)
129 // Maximum Listers Children Sockets
132 #define MAX_CHILD_LISTENERS (4)
135 // Maximum EA Information Length
138 #define EA_MAX_LENGTH ( sizeof(FILE_FULL_EA_INFORMATION) - 1 + \
139 TDI_TRANSPORT_ADDRESS_LENGTH + 1 + \
143 #define UDP_DEVICE_NAME L"\\Device\\Udp"
144 #define TCP_DEVICE_NAME L"\\Device\\Tcp"
151 #define TDINAL_TSDU_DEFAULT_SIZE (0x10000)
153 #define KS_TSDU_MAGIC 'KSTD'
155 #define KS_TSDU_ATTACHED 0x00000001 // Attached to the socket receive tsdu list
157 typedef struct _KS_TSDU {
162 struct list_head Link;
164 ULONG TotalLength; // Total size of KS_TSDU
166 ULONG StartOffset; // Start offset of the first Tsdu unit
167 ULONG LastOffset; // End offset of the last Tsdu unit
177 } KS_TSDU, *PKS_TSDU;
179 #define TSDU_TYPE_BUF ((USHORT)0x5401)
180 #define TSDU_TYPE_DAT ((USHORT)0x5402)
181 #define TSDU_TYPE_MDL ((USHORT)0x5403)
183 #define KS_TSDU_BUF_RECEIVING 0x0001
184 typedef struct _KS_TSDU_BUF {
194 } KS_TSDU_BUF, *PKS_TSDU_BUF;
196 #define KS_TSDU_DAT_RECEIVING 0x0001
198 typedef struct _KS_TSDU_DAT {
210 } KS_TSDU_DAT, *PKS_TSDU_DAT;
212 #define KS_DWORD_ALIGN(x) (((x) + 0x03) & (~(0x03)))
213 #define KS_TSDU_STRU_SIZE(Len) (KS_DWORD_ALIGN((Len) + FIELD_OFFSET(KS_TSDU_DAT, Data)))
215 typedef struct _KS_TSDU_MDL {
226 } KS_TSDU_MDL, *PKS_TSDU_MDL;
229 typedef struct _KS_TSDUMGR {
231 struct list_head TsduList;
236 } KS_TSDUMGR, *PKS_TSDUMGR;
239 typedef struct _KS_CHAIN {
242 KS_TSDUMGR Expedited;
244 } KS_CHAIN, *PKS_CHAIN;
247 #define TDINAL_SCHED_FACTOR (1)
248 #define CAN_BE_SCHED(Len, Limit) (Len >= ((Limit) >> TDINAL_SCHED_FACTOR))
251 // Handler Settings Indictor
254 #define TDI_EVENT_MAXIMUM_HANDLER (TDI_EVENT_ERROR_EX + 1)
257 typedef struct _KS_EVENT_HANDLERS {
258 BOOLEAN IsActive[TDI_EVENT_MAXIMUM_HANDLER];
259 PVOID Handler [TDI_EVENT_MAXIMUM_HANDLER];
260 } KS_EVENT_HANDLERS, *PKS_EVENT_HANDLERS;
262 #define SetEventHandler(ha, ht, hr) do { \
263 ha.IsActive[ht] = TRUE; \
264 ha.Handler[ht] = (PVOID) (hr); \
268 // KSock Internal Structures
271 typedef struct _KS_ADDRESS {
274 TRANSPORT_ADDRESS Tdi;
275 UCHAR Pading[MAX_ADDRESS_LENGTH];
279 PFILE_OBJECT FileObject;
281 } KS_ADDRESS, *PKS_ADDRESS;
284 // Structures for Disconnect Workitem
287 typedef struct _KS_DISCONNECT_WORKITEM {
289 WORK_QUEUE_ITEM WorkItem; // Workitem to perform disconnection
290 ksock_tconn_t * tconn; // tdi connecton
291 ULONG Flags; // connection broken/discnnection flags
292 KEVENT Event; // sync event
294 } KS_DISCONNECT_WORKITEM, *PKS_DISCONNECT_WORKITEM;
297 typedef struct _KS_CONNECTION {
299 HANDLE Handle; // Handle of the tdi connection
300 PFILE_OBJECT FileObject; // FileObject if the conn object
302 PTRANSPORT_ADDRESS Remote; // the ConnectionInfo of this connection
303 PTDI_CONNECTION_INFORMATION ConnectionInfo;
305 ULONG nagle; // Tcp options
307 } KS_CONNECTION, *PKS_CONNECTION;
314 typedef MDL ksock_mdl_t;
315 typedef UNICODE_STRING ksock_unicode_name_t;
316 typedef WORK_QUEUE_ITEM ksock_workitem_t;
319 typedef KS_CHAIN ksock_chain_t;
320 typedef KS_ADDRESS ksock_tdi_addr_t;
321 typedef KS_CONNECTION ksock_tconn_info_t;
322 typedef KS_DISCONNECT_WORKITEM ksock_disconnect_workitem_t;
326 // Structures for transmission done Workitem
329 typedef struct _KS_TCPX_FINILIZE {
330 ksock_workitem_t item;
335 typedef struct ksock_backlogs {
337 struct list_head list; /* list to link the backlog connections */
338 int num; /* number of backlogs in the list */
343 typedef struct ksock_daemon {
345 ksock_tconn_t * tconn; /* the listener connection object */
346 unsigned short nbacklogs; /* number of listening backlog conns */
347 unsigned short port; /* listening port number */
348 int shutdown; /* daemon threads is to exit */
349 struct list_head list; /* to be attached into ksock_nal_data_t*/
356 kstt_sender = 0, // normal sending connection type, it's active connection, while
357 // child tconn is for passive connection.
359 kstt_listener, // listener daemon type, it just acts as a daemon, and it does
360 // not have real connection. It manages children tcons to accept
361 // or refuse the connecting request from remote peers.
363 kstt_child, // accepted child connection type, it's parent must be Listener
369 ksts_uninited = 0, // tconn is just allocated (zero values), not initialized yet
371 ksts_inited, // tconn structure initialized: so it now can be identified as
372 // a sender, listener or a child
374 ksts_bind, // tconn is bound: the local address object (ip/port) is created.
375 // after being bound, we must call ksocknal_put_tconn to release
376 // the tconn objects, it's not safe just to free the memory of tconn.
378 ksts_associated, // the connection object is created and associated with the address
379 // object. so it's ready for connection. only for child and sender.
381 ksts_connecting, // only used by child tconn: in the ConnectEvent handler routine,
382 // it indicts the child tconn is busy to be connected to the peer.
384 ksts_connected, // the connection is built already: for sender and child
386 ksts_listening, // listener daemon is working, only for listener tconn
388 ksts_disconnected, // disconnected by user
389 ksts_aborted, // un-exptected broken status
391 ksts_last // total number of tconn statuses
394 #define KS_TCONN_MAGIC 'KSTM'
396 #define KS_TCONN_HANDLERS_SET 0x00000001 // Conection handlers are set.
397 #define KS_TCONN_DISCONNECT_BUSY 0x00010000 // Disconnect Workitem is queued ...
398 #define KS_TCONN_DESTROY_BUSY 0x00020000 // Destory Workitem is queued ...
400 #define KS_TCONN_DAEMON_STARTED 0x00100000 // indict the daemon is started,
401 // only valid for listener
405 ulong_ptr kstc_magic; /* Magic & Flags */
406 ulong_ptr kstc_flags;
408 spinlock_t kstc_lock; /* serialise lock*/
409 void * kstc_conn; /* ksock_conn_t */
411 ksock_tconn_type kstc_type; /* tdi connection Type */
412 ksock_tconn_state kstc_state; /* tdi connection state flag */
414 ksock_unicode_name_t kstc_dev; /* tcp transport device name */
416 ksock_tdi_addr_t kstc_addr; /* local address handlers / Objects */
418 atomic_t kstc_refcount; /* reference count of ksock_tconn */
420 struct list_head kstc_list; /* linked to global ksocknal_data */
425 int nbacklog; /* total number of backlog tdi connections */
426 ksock_backlogs_t kstc_listening; /* listeing backlog child connections */
427 ksock_backlogs_t kstc_accepted; /* connected backlog child connections */
428 event_t kstc_accept_event; /* Signaled by AcceptedHander,
429 ksocknal_wait_accpeted_conns waits on */
430 event_t kstc_destroy_event; /* Signaled when accepted child is released */
434 ksock_tconn_info_t kstc_info; /* Connection Info if Connected */
435 ksock_chain_t kstc_recv; /* tsdu engine for data receiving */
436 ksock_chain_t kstc_send; /* tsdu engine for data sending */
438 int kstc_queued; /* Attached to Parent->ChildList ... */
439 int kstc_queueno; /* 0: Attached to Listening list
440 1: Attached to Accepted list */
442 int kstc_busy; /* referred by ConnectEventCallback ? */
443 int kstc_accepted; /* the connection is built ready ? */
445 struct list_head kstc_link; /* linked to parent tdi connection */
446 ksock_tconn_t * kstc_parent; /* pointers to it's listener parent */
450 ksock_tconn_info_t kstc_info; /* Connection Info if Connected */
451 ksock_chain_t kstc_recv; /* tsdu engine for data receiving */
452 ksock_chain_t kstc_send; /* tsdu engine for data sending */
456 ulong_ptr kstc_snd_wnd; /* Sending window size */
457 ulong_ptr kstc_rcv_wnd; /* Recving window size */
459 ksock_workitem_t kstc_destroy; /* tconn destruction workitem */
460 ksock_disconnect_workitem_t kstc_disconnect; /* connection disconnect workitem */
462 ksock_schedule_cb kstc_sched_cb; /* notification callback routine of completion */
463 ksock_update_tx kstc_update_tx; /* aync sending callback to update tx */
466 #define SOCK_WMEM_QUEUED(sock) (0)
468 #define TDINAL_WINDOW_DEFAULT_SIZE (0x100000)
471 struct _KS_UDP_COMPLETION_CONTEXT;
472 struct _KS_TCP_COMPLETION_CONTEXT;
477 (*PKS_UDP_COMPLETION_ROUTINE) (
479 IN struct _KS_UDP_COMPLETION_CONTEXT
486 (*PKS_TCP_COMPLETION_ROUTINE) (
488 IN struct _KS_TCP_COMPLETION_CONTEXT
493 // Udp Irp Completion Context
496 typedef struct _KS_UDP_COMPLETION_CONTEXT {
500 PFILE_OBJECT AddressObject;
501 ksock_tconn_t * tconn;
504 PKS_UDP_COMPLETION_ROUTINE CompletionRoutine;
505 PVOID CompletionContext;
507 } KS_UDP_COMPLETION_CONTEXT, *PKS_UDP_COMPLETION_CONTEXT;
511 // Tcp Irp Completion Context (used by tcp data recv/send)
514 typedef struct _KS_TCP_COMPLETION_CONTEXT {
516 PKEVENT Event; // Event to be waited on by Irp caller ...
518 ksock_tconn_t * tconn; // the tdi connection
520 PKS_TCP_COMPLETION_ROUTINE CompletionRoutine;
521 PVOID CompletionContext;
522 PVOID CompletionContext2;
524 PKS_TSDUMGR KsTsduMgr; // Tsdu buffer manager
527 // These tow new members are for NON_BLOCKING transmission
530 BOOLEAN bCounted; // To indict needing refcount to
531 // execute CompetionRoutine
532 ULONG ReferCount; // Refer count of this structure
534 } KS_TCP_COMPLETION_CONTEXT, *PKS_TCP_COMPLETION_CONTEXT;
536 typedef KS_TCP_COMPLETION_CONTEXT ksock_tdi_tx_t, ksock_tdi_rx_t;
543 #define IOCTL_TCP_QUERY_INFORMATION_EX \
544 CTL_CODE(FILE_DEVICE_NETWORK, 0, METHOD_NEITHER, FILE_ANY_ACCESS)
545 #define IOCTL_TCP_SET_INFORMATION_EX \
546 CTL_CODE(FILE_DEVICE_NETWORK, 1, METHOD_BUFFERED, FILE_WRITE_ACCESS)
549 #define TcpBuildSetInformationEx(Irp, DevObj, FileObj, CompRoutine, Contxt, Buffer, BufferLen)\
551 PIO_STACK_LOCATION _IRPSP; \
552 if ( CompRoutine != NULL) { \
553 IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\
555 IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \
557 _IRPSP = IoGetNextIrpStackLocation (Irp); \
558 _IRPSP->MajorFunction = IRP_MJ_DEVICE_CONTROL; \
559 _IRPSP->DeviceObject = DevObj; \
560 _IRPSP->FileObject = FileObj; \
561 _IRPSP->Parameters.DeviceIoControl.OutputBufferLength = 0; \
562 _IRPSP->Parameters.DeviceIoControl.InputBufferLength = BufferLen; \
563 _IRPSP->Parameters.DeviceIoControl.IoControlCode = IOCTL_TCP_SET_INFORMATION_EX; \
564 Irp->AssociatedIrp.SystemBuffer = Buffer; \
568 #define TcpBuildQueryInformationEx(Irp, DevObj, FileObj, CompRoutine, Contxt, InBuffer, InLength, OutBuffer, OutLength)\
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 = OutLength; \
581 _IRPSP->Parameters.DeviceIoControl.InputBufferLength = InLength; \
582 _IRPSP->Parameters.DeviceIoControl.IoControlCode = IOCTL_TCP_QUERY_INFORMATION_EX; \
583 _IRPSP->Parameters.DeviceIoControl.Type3InputBuffer = InBuffer; \
584 Irp->UserBuffer = OutBuffer; \
588 typedef struct ks_addr_slot {
594 UNICODE_STRING devname;
601 * Tdi client information
604 UNICODE_STRING ksnd_client_name; /* tdi client module name */
605 HANDLE ksnd_pnp_handle; /* the handle for pnp changes */
607 spinlock_t ksnd_addrs_lock; /* serialize ip address list access */
608 LIST_ENTRY ksnd_addrs_list; /* list of the ip addresses */
609 int ksnd_naddrs; /* number of the ip addresses */
612 * Tdilnd internal defintions
615 int ksnd_init; /* initialisation state */
617 TDI_PROVIDER_INFO ksnd_provider; /* tdi tcp/ip provider's information */
619 spinlock_t ksnd_tconn_lock; /* tdi connections access serialise */
621 int ksnd_ntconns; /* number of tconns attached in list */
622 struct list_head ksnd_tconns; /* tdi connections list */
623 cfs_mem_cache_t * ksnd_tconn_slab; /* slabs for ksock_tconn_t allocations */
624 event_t ksnd_tconn_exit; /* exit event to be signaled by the last tconn */
626 spinlock_t ksnd_tsdu_lock; /* tsdu access serialise */
628 int ksnd_ntsdus; /* number of tsdu buffers allocated */
629 ulong_ptr ksnd_tsdu_size; /* the size of a signel tsdu buffer */
630 cfs_mem_cache_t * ksnd_tsdu_slab; /* slab cache for tsdu buffer allocation */
632 int ksnd_nfreetsdus; /* number of tsdu buffers in the freed list */
633 struct list_head ksnd_freetsdus; /* List of the freed Tsdu buffer. */
635 spinlock_t ksnd_daemon_lock; /* stabilize daemon ops */
636 int ksnd_ndaemons; /* number of listening daemons */
637 struct list_head ksnd_daemons; /* listening daemon list */
638 event_t ksnd_daemon_exit; /* the last daemon quiting should singal it */
649 #endif /* __KERNEL__ */
650 #endif /* __LIBCFS_WINNT_TCPIP_H__ */
654 * c-indentation-style: "K&R"