1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=4:tabstop=4:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
37 #ifndef __LIBCFS_WINNT_TCPIP_H__
38 #define __LIBCFS_WINNT_TCPIP_H__
40 #ifndef __LIBCFS_LIBCFS_H__
41 #error Do not #include this file directly. #include <libcfs/libcfs.h> instead
51 // iovec is defined in libcfs: winnt_prim.h
52 // lnetkiov_t is defined in lnet/types.h
54 typedef struct socket ks_tconn_t, cfs_socket_t;
56 // completion notification callback routine
58 typedef VOID (*ks_schedule_cb)(struct socket*, int);
60 #define SOCK_ERROR(s) ((s->kstc_state >= ksts_disconnected) ? ECONNRESET : 0)
61 #define SOCK_TEST_NOSPACE(s) (1)
69 #define KsPrint(X) KsPrintf X
76 // Socket Addresses Related ...
79 #define INADDR_ANY (ULONG)0x00000000
80 #define INADDR_LOOPBACK (ULONG)0x7f000001
81 #define INADDR_BROADCAST (ULONG)0xffffffff
82 #define INADDR_NONE (ULONG)0xffffffff
94 #define TCP_SOCKET_NODELAY 1 // disabling "Nagle"
95 #define TCP_SOCKET_KEEPALIVE 2
96 #define TCP_SOCKET_OOBINLINE 3
97 #define TCP_SOCKET_BSDURGENT 4
98 #define TCP_SOCKET_ATMARK 5
99 #define TCP_SOCKET_WINDOW 6
102 /* Flags we can use with send/ and recv.
103 Added those for 1003.1g not all are supported yet
108 #define MSG_DONTROUTE 4
109 #define MSG_TRYHARD 4 /* Synonym for MSG_DONTROUTE for DECnet */
111 #define MSG_PROBE 0x10 /* Do not send. Only probe path f.e. for MTU */
112 #define MSG_TRUNC 0x20
113 #define MSG_DONTWAIT 0x40 /* Nonblocking io */
114 #define MSG_EOR 0x80 /* End of record */
115 #define MSG_WAITALL 0x100 /* Wait for a full request */
116 #define MSG_FIN 0x200
117 #define MSG_SYN 0x400
118 #define MSG_CONFIRM 0x800 /* Confirm path validity */
119 #define MSG_RST 0x1000
120 #define MSG_ERRQUEUE 0x2000 /* Fetch message from error queue */
121 #define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE */
122 #define MSG_MORE 0x8000 /* Sender will send more */
124 #define MSG_EOF MSG_FIN
128 // Maximum TRANSPORT_ADDRESS Length
130 // it must >= FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address)
131 // + TDI_ADDRESS_LENGTH_IP
133 // I define it a little large and 16 bytes aligned to avoid possible overflow.
136 #define MAX_ADDRESS_LENGTH (0x30)
140 // Maximum Listers Children Sockets
143 #define MAX_CHILD_LISTENERS (4)
146 // Maximum EA Information Length
149 #define EA_MAX_LENGTH ( sizeof(FILE_FULL_EA_INFORMATION) - 1 + \
150 TDI_TRANSPORT_ADDRESS_LENGTH + 1 + \
154 #define UDP_DEVICE_NAME L"\\Device\\Udp"
155 #define TCP_DEVICE_NAME L"\\Device\\Tcp"
162 #define TDINAL_TSDU_DEFAULT_SIZE (0x10000)
164 #define KS_TSDU_MAGIC 'KSTD'
166 #define KS_TSDU_ATTACHED 0x00000001 // Attached to the socket receive tsdu list
168 typedef struct _KS_TSDU {
170 ULONG Magic; /* magic */
171 ULONG Flags; /* flags */
173 struct list_head Link; /* link list */
175 ULONG TotalLength; /* total size of KS_TSDU */
176 ULONG StartOffset; /* offset of the first Tsdu unit */
177 ULONG LastOffset; /* end offset of the last Tsdu unit */
187 } KS_TSDU, *PKS_TSDU;
189 #define TSDU_TYPE_BUF ((USHORT)0x5401)
190 #define TSDU_TYPE_DAT ((USHORT)0x5402)
191 #define TSDU_TYPE_MDL ((USHORT)0x5403)
193 #define KS_TSDU_COMM_PARTIAL 0x0001
195 typedef struct _KS_TSDU_BUF {
205 } KS_TSDU_BUF, *PKS_TSDU_BUF;
207 typedef struct _KS_TSDU_DAT {
220 } KS_TSDU_DAT, *PKS_TSDU_DAT;
222 #define KS_QWORD_ALIGN(x) (((x) + 0x07) & 0xFFFFFFF8)
223 #define KS_TSDU_STRU_SIZE(Len) (KS_QWORD_ALIGN((Len) + FIELD_OFFSET(KS_TSDU_DAT, Data[0])))
225 typedef struct _KS_TSDU_MDL {
226 USHORT TsduType; /* TSDU_TYPE_MDL */
227 USHORT TsduFlags; /* */
229 ULONG DataLength; /* total valid data length */
230 ULONG BaseOffset; /* payload offset in Tsdu */
231 ULONG StartOffset; /* offset in payload */
233 PVOID Descriptor; /* tdi descriptor for receiving */
235 } KS_TSDU_MDL, *PKS_TSDU_MDL;
237 typedef struct ks_engine_mgr {
242 struct list_head list;
245 typedef struct ks_engine_slot {
248 struct list_head link;
250 ks_engine_mgr_t * emgr;
253 typedef struct _KS_TSDUMGR {
254 struct list_head TsduList;
259 ks_engine_slot_t Slot;
263 } KS_TSDUMGR, *PKS_TSDUMGR;
265 #define ks_lock_tsdumgr(mgr) spin_lock(&((mgr)->Lock))
266 #define ks_unlock_tsdumgr(mgr) spin_unlock(&((mgr)->Lock))
268 typedef struct _KS_CHAIN {
269 KS_TSDUMGR Normal; /* normal queue */
270 KS_TSDUMGR Expedited; /* OOB/expedited queue */
271 } KS_CHAIN, *PKS_CHAIN;
274 #define KS_CAN_SCHED(TM) ((TM)->TotalBytes >= ((TM)->Payload >> 2))
277 // Handler Settings Indictor
280 #define TDI_EVENT_MAXIMUM_HANDLER (TDI_EVENT_ERROR_EX + 1)
283 typedef struct _KS_EVENT_HANDLERS {
284 BOOLEAN IsActive[TDI_EVENT_MAXIMUM_HANDLER];
285 PVOID Handler [TDI_EVENT_MAXIMUM_HANDLER];
286 } KS_EVENT_HANDLERS, *PKS_EVENT_HANDLERS;
288 #define SetEventHandler(ha, ht, hr) do { \
289 ha.IsActive[ht] = TRUE; \
290 ha.Handler[ht] = (PVOID) (hr); \
294 // KSock Internal Structures
297 typedef struct _KS_ADDRESS {
300 TRANSPORT_ADDRESS Tdi;
301 UCHAR Pading[MAX_ADDRESS_LENGTH];
305 PFILE_OBJECT FileObject;
307 } KS_ADDRESS, *PKS_ADDRESS;
310 // Structures for Disconnect Workitem
313 typedef struct _KS_DISCONNECT_WORKITEM {
315 WORK_QUEUE_ITEM WorkItem; // Workitem to perform disconnection
316 ks_tconn_t * tconn; // tdi connecton
317 ULONG Flags; // connection broken/discnnection flags
318 KEVENT Event; // sync event
320 } KS_DISCONNECT_WORKITEM, *PKS_DISCONNECT_WORKITEM;
323 typedef struct _KS_CONNECTION {
325 HANDLE Handle; // Handle of the tdi connection
326 PFILE_OBJECT FileObject; // FileObject if the conn object
328 PTRANSPORT_ADDRESS Remote; // the ConnectionInfo of this connection
329 PTDI_CONNECTION_INFORMATION ConnectionInfo;
331 ULONG nagle; // Tcp options
333 } KS_CONNECTION, *PKS_CONNECTION;
340 typedef MDL ks_mdl_t;
341 typedef UNICODE_STRING ks_unicode_name_t;
342 typedef WORK_QUEUE_ITEM ks_workitem_t;
345 typedef KS_CHAIN ks_chain_t;
346 typedef KS_ADDRESS ks_tdi_addr_t;
347 typedef KS_CONNECTION ks_tconn_info_t;
348 typedef KS_DISCONNECT_WORKITEM ks_disconnect_t;
352 // Structures for transmission done Workitem
355 typedef struct ks_backlogs {
357 struct list_head list; /* list to link the backlog connections */
358 int num; /* number of backlogs in the list */
363 typedef struct ks_daemon {
365 ks_tconn_t * tconn; /* the listener connection object */
366 unsigned short nbacklogs; /* number of listening backlog conns */
367 unsigned short port; /* listening port number */
368 int shutdown; /* daemon threads is to exit */
369 struct list_head list; /* to be attached into ks_nal_data_t */
375 kstt_sender = 0, // normal sending connection type, it's active connection, while
376 // child tconn is for passive connection.
378 kstt_listener, // listener daemon type, it just acts as a daemon, and it does
379 // not have real connection. It manages children tcons to accept
380 // or refuse the connecting request from remote peers.
382 kstt_child, // accepted child connection type, it's parent must be Listener
390 ksts_uninited = 0, // tconn is just allocated (zero values), not initialized yet
392 ksts_inited, // tconn structure initialized: so it now can be identified as
393 // a sender, listener or a child
395 ksts_bind, // tconn is bound: the local address object (ip/port) is created.
396 // after being bound, we must call ksocknal_put_tconn to release
397 // the tconn objects, it's not safe just to free the memory of tconn.
399 ksts_associated, // the connection object is created and associated with the address
400 // object. so it's ready for connection. only for child and sender.
402 ksts_connecting, // only used by child tconn: in the ConnectEvent handler routine,
403 // it indicts the child tconn is busy to be connected to the peer.
405 ksts_connected, // the connection is built already: for sender and child
407 ksts_listening, // listener daemon is working, only for listener tconn
409 ksts_disconnected, // disconnected by user
410 ksts_aborted, // un-exptected broken status
412 ksts_last // total number of tconn statuses
416 #define KS_TCONN_MAGIC 'KSTM'
418 #define KS_TCONN_HANDLERS_SET 0x00000001 // Conection handlers are set.
419 #define KS_TCONN_DISCONNECT_BUSY 0x00010000 // Disconnect Workitem is queued ...
420 #define KS_TCONN_DESTROY_BUSY 0x00020000 // Destory Workitem is queued ...
422 #define KS_TCONN_DAEMON_STARTED 0x00100000 // indict the daemon is started,
423 // only valid for listener
426 ulong kstc_magic; /* Magic & Flags */
429 spinlock_t kstc_lock; /* serialise lock*/
430 void * kstc_conn; /* ks_conn_t */
432 ks_tconn_type_t kstc_type; /* tdi connection Type */
433 ks_tconn_state_t kstc_state; /* tdi connection state flag */
435 ks_unicode_name_t kstc_dev; /* tcp transport device name */
437 ks_tdi_addr_t kstc_addr; /* local address handlers / Objects */
439 atomic_t kstc_refcount; /* reference count of ks_tconn_t */
441 struct list_head kstc_list; /* linked to global ksocknal_data */
446 int nbacklog; /* total number of backlog tdi connections */
447 ks_backlogs_t kstc_listening; /* listeing backlog child connections */
448 ks_backlogs_t kstc_accepted; /* connected backlog child connections */
449 event_t kstc_accept_event; /* Signaled by AcceptedHander,
450 ksocknal_wait_accpeted_conns waits on */
451 event_t kstc_destroy_event; /* Signaled when accepted child is released */
455 ks_tconn_info_t kstc_info; /* Connection Info if Connected */
456 ks_chain_t kstc_recv; /* tsdu engine for data receiving */
457 ks_chain_t kstc_send; /* tsdu engine for data sending */
459 int kstc_queued; /* Attached to Parent->ChildList ... */
460 int kstc_queueno; /* 0: Attached to Listening list
461 1: Attached to Accepted list */
463 int kstc_busy; /* referred by ConnectEventCallback ? */
464 int kstc_accepted; /* the connection is built ready ? */
466 struct list_head kstc_link; /* linked to parent tdi connection */
467 ks_tconn_t * kstc_parent; /* pointers to it's listener parent */
471 ks_tconn_info_t kstc_info; /* Connection Info if Connected */
472 ks_chain_t kstc_recv; /* tsdu engine for data receiving */
473 ks_chain_t kstc_send; /* tsdu engine for data sending */
477 ulong kstc_snd_wnd; /* Sending window size */
478 ulong kstc_rcv_wnd; /* Recving window size */
480 ks_workitem_t kstc_destroy; /* tconn destruction workitem */
481 ks_disconnect_t kstc_disconnect; /* connection disconnect workitem */
483 ks_schedule_cb kstc_sched_cb; /* notification callback routine of completion */
486 #define SOCK_WMEM_QUEUED(sock) (0)
487 #define TDINAL_WINDOW_DEFAULT_SIZE (0x100000)
488 #define TDINAL_MAX_TSDU_QUEUE_SIZE (0x200000)
490 struct _KS_UDP_COMPLETION_CONTEXT;
491 struct _KS_TCP_COMPLETION_CONTEXT;
496 (*PKS_UDP_COMPLETION_ROUTINE) (
498 IN struct _KS_UDP_COMPLETION_CONTEXT
505 (*PKS_TCP_COMPLETION_ROUTINE) (
507 IN struct _KS_TCP_COMPLETION_CONTEXT
512 // Udp Irp Completion Context
515 typedef struct _KS_UDP_COMPLETION_CONTEXT {
519 PFILE_OBJECT AddressObject;
523 PKS_UDP_COMPLETION_ROUTINE CompletionRoutine;
524 PVOID CompletionContext;
526 } KS_UDP_COMPLETION_CONTEXT, *PKS_UDP_COMPLETION_CONTEXT;
530 // Tcp Irp Completion Context (used by tcp data recv/send)
533 #define KS_TCP_CONTEXT_MAGIC 'CCTK'
535 typedef struct _KS_TCP_COMPLETION_CONTEXT {
536 PKEVENT Event; // Event to be waited on by Irp caller ...
537 ks_tconn_t * tconn; // the tdi connection
538 PKS_TCP_COMPLETION_ROUTINE CompletionRoutine;
539 PVOID CompletionContext;
540 PKS_TSDUMGR TsduMgr; // Tsdu buffer manager
541 ULONG Length; // Payload length in KsTsdu queue
542 PCHAR Buffer; // User allocated buffer
543 ULONG Magic; // Magic key
544 } KS_TCP_COMPLETION_CONTEXT, *PKS_TCP_COMPLETION_CONTEXT;
546 typedef KS_TCP_COMPLETION_CONTEXT ks_tdi_tx_t, ks_tdi_rx_t;
553 #define IOCTL_TCP_QUERY_INFORMATION_EX \
554 CTL_CODE(FILE_DEVICE_NETWORK, 0, METHOD_NEITHER, FILE_ANY_ACCESS)
555 #define IOCTL_TCP_SET_INFORMATION_EX \
556 CTL_CODE(FILE_DEVICE_NETWORK, 1, METHOD_BUFFERED, FILE_WRITE_ACCESS)
559 #define TcpBuildSetInformationEx(Irp, DevObj, FileObj, CompRoutine, Contxt, Buffer, BufferLen)\
561 PIO_STACK_LOCATION _IRPSP; \
562 if ( CompRoutine != NULL) { \
563 IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\
565 IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \
567 _IRPSP = IoGetNextIrpStackLocation (Irp); \
568 _IRPSP->MajorFunction = IRP_MJ_DEVICE_CONTROL; \
569 _IRPSP->DeviceObject = DevObj; \
570 _IRPSP->FileObject = FileObj; \
571 _IRPSP->Parameters.DeviceIoControl.OutputBufferLength = 0; \
572 _IRPSP->Parameters.DeviceIoControl.InputBufferLength = BufferLen; \
573 _IRPSP->Parameters.DeviceIoControl.IoControlCode = IOCTL_TCP_SET_INFORMATION_EX; \
574 Irp->AssociatedIrp.SystemBuffer = Buffer; \
578 #define TcpBuildQueryInformationEx(Irp, DevObj, FileObj, CompRoutine, Contxt, InBuffer, InLength, OutBuffer, OutLength)\
580 PIO_STACK_LOCATION _IRPSP; \
581 if ( CompRoutine != NULL) { \
582 IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\
584 IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \
586 _IRPSP = IoGetNextIrpStackLocation (Irp); \
587 _IRPSP->MajorFunction = IRP_MJ_DEVICE_CONTROL; \
588 _IRPSP->DeviceObject = DevObj; \
589 _IRPSP->FileObject = FileObj; \
590 _IRPSP->Parameters.DeviceIoControl.OutputBufferLength = OutLength; \
591 _IRPSP->Parameters.DeviceIoControl.InputBufferLength = InLength; \
592 _IRPSP->Parameters.DeviceIoControl.IoControlCode = IOCTL_TCP_QUERY_INFORMATION_EX; \
593 _IRPSP->Parameters.DeviceIoControl.Type3InputBuffer = InBuffer; \
594 Irp->UserBuffer = OutBuffer; \
597 typedef struct ks_addr_slot {
603 UNICODE_STRING devname;
610 * Tdi client information
613 UNICODE_STRING ksnd_client_name; /* tdi client module name */
614 HANDLE ksnd_pnp_handle; /* the handle for pnp changes */
616 spinlock_t ksnd_addrs_lock; /* serialize ip address list access */
617 LIST_ENTRY ksnd_addrs_list; /* list of the ip addresses */
618 int ksnd_naddrs; /* number of the ip addresses */
621 * Tdilnd internal defintions
624 int ksnd_init; /* initialisation state */
626 TDI_PROVIDER_INFO ksnd_provider; /* tdi tcp/ip provider's information */
628 spinlock_t ksnd_tconn_lock; /* tdi connections access serialise */
630 int ksnd_ntconns; /* number of tconns attached in list */
631 struct list_head ksnd_tconns; /* tdi connections list */
632 cfs_mem_cache_t * ksnd_tconn_slab; /* slabs for ks_tconn_t allocations */
633 event_t ksnd_tconn_exit; /* exit event to be signaled by the last tconn */
635 spinlock_t ksnd_tsdu_lock; /* tsdu access serialise */
637 int ksnd_ntsdus; /* number of tsdu buffers allocated */
638 ulong ksnd_tsdu_size; /* the size of a signel tsdu buffer */
639 cfs_mem_cache_t * ksnd_tsdu_slab; /* slab cache for tsdu buffer allocation */
641 int ksnd_nfreetsdus; /* number of tsdu buffers in the freed list */
642 struct list_head ksnd_freetsdus; /* List of the freed Tsdu buffer. */
644 int ksnd_engine_nums; /* number of tcp sending engine threads */
645 ks_engine_mgr_t * ksnd_engine_mgr; /* tcp sending engine structure */
657 ks_query_local_ipaddr(
691 IN LOCK_OPERATION Operation,
696 KsReleaseMdl (IN PMDL Mdl,
700 KsQueueTdiEngine(ks_tconn_t * tconn, PKS_TSDUMGR);
703 KsRemoveTdiEngine(PKS_TSDUMGR);
721 #endif /* __KERNEL__ */
722 #endif /* __LIBCFS_WINNT_TCPIP_H__ */
726 * c-indentation-style: "K&R"