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_TEST_NOSPACE(s) (1)
68 #define KsPrint(X) KsPrintf X
75 // Socket Addresses Related ...
78 #define INADDR_ANY (ULONG)0x00000000
79 #define INADDR_LOOPBACK (ULONG)0x7f000001
80 #define INADDR_BROADCAST (ULONG)0xffffffff
81 #define INADDR_NONE (ULONG)0xffffffff
93 #define TCP_SOCKET_NODELAY 1 // disabling "Nagle"
94 #define TCP_SOCKET_KEEPALIVE 2
95 #define TCP_SOCKET_OOBINLINE 3
96 #define TCP_SOCKET_BSDURGENT 4
97 #define TCP_SOCKET_ATMARK 5
98 #define TCP_SOCKET_WINDOW 6
101 /* Flags we can use with send/ and recv.
102 Added those for 1003.1g not all are supported yet
107 #define MSG_DONTROUTE 4
108 #define MSG_TRYHARD 4 /* Synonym for MSG_DONTROUTE for DECnet */
110 #define MSG_PROBE 0x10 /* Do not send. Only probe path f.e. for MTU */
111 #define MSG_TRUNC 0x20
112 #define MSG_DONTWAIT 0x40 /* Nonblocking io */
113 #define MSG_EOR 0x80 /* End of record */
114 #define MSG_WAITALL 0x100 /* Wait for a full request */
115 #define MSG_FIN 0x200
116 #define MSG_SYN 0x400
117 #define MSG_CONFIRM 0x800 /* Confirm path validity */
118 #define MSG_RST 0x1000
119 #define MSG_ERRQUEUE 0x2000 /* Fetch message from error queue */
120 #define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE */
121 #define MSG_MORE 0x8000 /* Sender will send more */
123 #define MSG_EOF MSG_FIN
127 // Maximum TRANSPORT_ADDRESS Length
129 // it must >= FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address)
130 // + TDI_ADDRESS_LENGTH_IP
132 // I define it a little large and 16 bytes aligned to avoid possible overflow.
135 #define MAX_ADDRESS_LENGTH (0x30)
139 // Maximum Listers Children Sockets
142 #define MAX_CHILD_LISTENERS (4)
145 // Maximum EA Information Length
148 #define EA_MAX_LENGTH ( sizeof(FILE_FULL_EA_INFORMATION) - 1 + \
149 TDI_TRANSPORT_ADDRESS_LENGTH + 1 + \
153 #define UDP_DEVICE_NAME L"\\Device\\Udp"
154 #define TCP_DEVICE_NAME L"\\Device\\Tcp"
161 #define TDINAL_TSDU_DEFAULT_SIZE (0x10000)
163 #define KS_TSDU_MAGIC 'KSTD'
165 #define KS_TSDU_ATTACHED 0x00000001 // Attached to the socket receive tsdu list
167 typedef struct _KS_TSDU {
169 ULONG Magic; /* magic */
170 ULONG Flags; /* flags */
172 struct list_head Link; /* link list */
174 ULONG TotalLength; /* total size of KS_TSDU */
175 ULONG StartOffset; /* offset of the first Tsdu unit */
176 ULONG LastOffset; /* end offset of the last Tsdu unit */
186 } KS_TSDU, *PKS_TSDU;
188 #define TSDU_TYPE_BUF ((USHORT)0x5401)
189 #define TSDU_TYPE_DAT ((USHORT)0x5402)
190 #define TSDU_TYPE_MDL ((USHORT)0x5403)
192 #define KS_TSDU_COMM_PARTIAL 0x0001
194 typedef struct _KS_TSDU_BUF {
204 } KS_TSDU_BUF, *PKS_TSDU_BUF;
206 typedef struct _KS_TSDU_DAT {
219 } KS_TSDU_DAT, *PKS_TSDU_DAT;
221 #define KS_QWORD_ALIGN(x) (((x) + 0x07) & 0xFFFFFFF8)
222 #define KS_TSDU_STRU_SIZE(Len) (KS_QWORD_ALIGN((Len) + FIELD_OFFSET(KS_TSDU_DAT, Data[0])))
224 typedef struct _KS_TSDU_MDL {
225 USHORT TsduType; /* TSDU_TYPE_MDL */
226 USHORT TsduFlags; /* */
228 ULONG DataLength; /* total valid data length */
229 ULONG BaseOffset; /* payload offset in Tsdu */
230 ULONG StartOffset; /* offset in payload */
232 PVOID Descriptor; /* tdi descriptor for receiving */
234 } KS_TSDU_MDL, *PKS_TSDU_MDL;
236 typedef struct ks_engine_mgr {
241 struct list_head list;
244 typedef struct ks_engine_slot {
247 struct list_head link;
249 ks_engine_mgr_t * emgr;
252 typedef struct _KS_TSDUMGR {
253 struct list_head TsduList;
258 ks_engine_slot_t Slot;
262 } KS_TSDUMGR, *PKS_TSDUMGR;
264 #define ks_lock_tsdumgr(mgr) spin_lock(&((mgr)->Lock))
265 #define ks_unlock_tsdumgr(mgr) spin_unlock(&((mgr)->Lock))
267 typedef struct _KS_CHAIN {
268 KS_TSDUMGR Normal; /* normal queue */
269 KS_TSDUMGR Expedited; /* OOB/expedited queue */
270 } KS_CHAIN, *PKS_CHAIN;
273 #define KS_CAN_SCHED(TM) ((TM)->TotalBytes >= ((TM)->Payload >> 2))
276 // Handler Settings Indictor
279 #define TDI_EVENT_MAXIMUM_HANDLER (TDI_EVENT_ERROR_EX + 1)
282 typedef struct _KS_EVENT_HANDLERS {
283 BOOLEAN IsActive[TDI_EVENT_MAXIMUM_HANDLER];
284 PVOID Handler [TDI_EVENT_MAXIMUM_HANDLER];
285 } KS_EVENT_HANDLERS, *PKS_EVENT_HANDLERS;
287 #define SetEventHandler(ha, ht, hr) do { \
288 ha.IsActive[ht] = TRUE; \
289 ha.Handler[ht] = (PVOID) (hr); \
293 // KSock Internal Structures
296 typedef struct _KS_ADDRESS {
299 TRANSPORT_ADDRESS Tdi;
300 UCHAR Pading[MAX_ADDRESS_LENGTH];
304 PFILE_OBJECT FileObject;
306 } KS_ADDRESS, *PKS_ADDRESS;
309 // Structures for Disconnect Workitem
312 typedef struct _KS_DISCONNECT_WORKITEM {
314 WORK_QUEUE_ITEM WorkItem; // Workitem to perform disconnection
315 ks_tconn_t * tconn; // tdi connecton
316 ULONG Flags; // connection broken/discnnection flags
317 KEVENT Event; // sync event
319 } KS_DISCONNECT_WORKITEM, *PKS_DISCONNECT_WORKITEM;
322 typedef struct _KS_CONNECTION {
324 HANDLE Handle; // Handle of the tdi connection
325 PFILE_OBJECT FileObject; // FileObject if the conn object
327 PTRANSPORT_ADDRESS Remote; // the ConnectionInfo of this connection
328 PTDI_CONNECTION_INFORMATION ConnectionInfo;
330 ULONG nagle; // Tcp options
332 } KS_CONNECTION, *PKS_CONNECTION;
339 typedef MDL ks_mdl_t;
340 typedef UNICODE_STRING ks_unicode_name_t;
341 typedef WORK_QUEUE_ITEM ks_workitem_t;
344 typedef KS_CHAIN ks_chain_t;
345 typedef KS_ADDRESS ks_tdi_addr_t;
346 typedef KS_CONNECTION ks_tconn_info_t;
347 typedef KS_DISCONNECT_WORKITEM ks_disconnect_t;
351 // Structures for transmission done Workitem
354 typedef struct ks_backlogs {
356 struct list_head list; /* list to link the backlog connections */
357 int num; /* number of backlogs in the list */
362 typedef struct ks_daemon {
364 ks_tconn_t * tconn; /* the listener connection object */
365 unsigned short nbacklogs; /* number of listening backlog conns */
366 unsigned short port; /* listening port number */
367 int shutdown; /* daemon threads is to exit */
368 struct list_head list; /* to be attached into ks_nal_data_t */
374 kstt_sender = 0, // normal sending connection type, it's active connection, while
375 // child tconn is for passive connection.
377 kstt_listener, // listener daemon type, it just acts as a daemon, and it does
378 // not have real connection. It manages children tcons to accept
379 // or refuse the connecting request from remote peers.
381 kstt_child, // accepted child connection type, it's parent must be Listener
389 ksts_uninited = 0, // tconn is just allocated (zero values), not initialized yet
391 ksts_inited, // tconn structure initialized: so it now can be identified as
392 // a sender, listener or a child
394 ksts_bind, // tconn is bound: the local address object (ip/port) is created.
395 // after being bound, we must call ksocknal_put_tconn to release
396 // the tconn objects, it's not safe just to free the memory of tconn.
398 ksts_associated, // the connection object is created and associated with the address
399 // object. so it's ready for connection. only for child and sender.
401 ksts_connecting, // only used by child tconn: in the ConnectEvent handler routine,
402 // it indicts the child tconn is busy to be connected to the peer.
404 ksts_connected, // the connection is built already: for sender and child
406 ksts_listening, // listener daemon is working, only for listener tconn
408 ksts_disconnected, // disconnected by user
409 ksts_aborted, // un-exptected broken status
411 ksts_last // total number of tconn statuses
415 #define KS_TCONN_MAGIC 'KSTM'
417 #define KS_TCONN_HANDLERS_SET 0x00000001 // Conection handlers are set.
418 #define KS_TCONN_DISCONNECT_BUSY 0x00010000 // Disconnect Workitem is queued ...
419 #define KS_TCONN_DESTROY_BUSY 0x00020000 // Destory Workitem is queued ...
421 #define KS_TCONN_DAEMON_STARTED 0x00100000 // indict the daemon is started,
422 // only valid for listener
425 ulong kstc_magic; /* Magic & Flags */
428 spinlock_t kstc_lock; /* serialise lock*/
429 void * kstc_conn; /* ks_conn_t */
431 ks_tconn_type_t kstc_type; /* tdi connection Type */
432 ks_tconn_state_t kstc_state; /* tdi connection state flag */
434 ks_unicode_name_t kstc_dev; /* tcp transport device name */
436 ks_tdi_addr_t kstc_addr; /* local address handlers / Objects */
438 atomic_t kstc_refcount; /* reference count of ks_tconn_t */
440 struct list_head kstc_list; /* linked to global ksocknal_data */
445 int nbacklog; /* total number of backlog tdi connections */
446 ks_backlogs_t kstc_listening; /* listeing backlog child connections */
447 ks_backlogs_t kstc_accepted; /* connected backlog child connections */
448 event_t kstc_accept_event; /* Signaled by AcceptedHander,
449 ksocknal_wait_accpeted_conns waits on */
450 event_t kstc_destroy_event; /* Signaled when accepted child is released */
454 ks_tconn_info_t kstc_info; /* Connection Info if Connected */
455 ks_chain_t kstc_recv; /* tsdu engine for data receiving */
456 ks_chain_t kstc_send; /* tsdu engine for data sending */
458 int kstc_queued; /* Attached to Parent->ChildList ... */
459 int kstc_queueno; /* 0: Attached to Listening list
460 1: Attached to Accepted list */
462 int kstc_busy; /* referred by ConnectEventCallback ? */
463 int kstc_accepted; /* the connection is built ready ? */
465 struct list_head kstc_link; /* linked to parent tdi connection */
466 ks_tconn_t * kstc_parent; /* pointers to it's listener parent */
470 ks_tconn_info_t kstc_info; /* Connection Info if Connected */
471 ks_chain_t kstc_recv; /* tsdu engine for data receiving */
472 ks_chain_t kstc_send; /* tsdu engine for data sending */
476 ulong kstc_snd_wnd; /* Sending window size */
477 ulong kstc_rcv_wnd; /* Recving window size */
479 ks_workitem_t kstc_destroy; /* tconn destruction workitem */
480 ks_disconnect_t kstc_disconnect; /* connection disconnect workitem */
482 ks_schedule_cb kstc_sched_cb; /* notification callback routine of completion */
486 libcfs_sock_error(struct socket *sock)
488 return (sock->kstc_state >= ksts_disconnected) ? ECONNRESET : 0;
493 libcfs_sock_wmem_queued(struct socket *sock)
498 #define TDINAL_WINDOW_DEFAULT_SIZE (0x100000)
499 #define TDINAL_MAX_TSDU_QUEUE_SIZE (0x200000)
501 struct _KS_UDP_COMPLETION_CONTEXT;
502 struct _KS_TCP_COMPLETION_CONTEXT;
507 (*PKS_UDP_COMPLETION_ROUTINE) (
509 IN struct _KS_UDP_COMPLETION_CONTEXT
516 (*PKS_TCP_COMPLETION_ROUTINE) (
518 IN struct _KS_TCP_COMPLETION_CONTEXT
523 // Udp Irp Completion Context
526 typedef struct _KS_UDP_COMPLETION_CONTEXT {
530 PFILE_OBJECT AddressObject;
534 PKS_UDP_COMPLETION_ROUTINE CompletionRoutine;
535 PVOID CompletionContext;
537 } KS_UDP_COMPLETION_CONTEXT, *PKS_UDP_COMPLETION_CONTEXT;
541 // Tcp Irp Completion Context (used by tcp data recv/send)
544 #define KS_TCP_CONTEXT_MAGIC 'CCTK'
546 typedef struct _KS_TCP_COMPLETION_CONTEXT {
547 PKEVENT Event; // Event to be waited on by Irp caller ...
548 ks_tconn_t * tconn; // the tdi connection
549 PKS_TCP_COMPLETION_ROUTINE CompletionRoutine;
550 PVOID CompletionContext;
551 PKS_TSDUMGR TsduMgr; // Tsdu buffer manager
552 ULONG Length; // Payload length in KsTsdu queue
553 PCHAR Buffer; // User allocated buffer
554 ULONG Magic; // Magic key
555 } KS_TCP_COMPLETION_CONTEXT, *PKS_TCP_COMPLETION_CONTEXT;
557 typedef KS_TCP_COMPLETION_CONTEXT ks_tdi_tx_t, ks_tdi_rx_t;
564 #define IOCTL_TCP_QUERY_INFORMATION_EX \
565 CTL_CODE(FILE_DEVICE_NETWORK, 0, METHOD_NEITHER, FILE_ANY_ACCESS)
566 #define IOCTL_TCP_SET_INFORMATION_EX \
567 CTL_CODE(FILE_DEVICE_NETWORK, 1, METHOD_BUFFERED, FILE_WRITE_ACCESS)
570 #define TcpBuildSetInformationEx(Irp, DevObj, FileObj, CompRoutine, Contxt, Buffer, BufferLen)\
572 PIO_STACK_LOCATION _IRPSP; \
573 if ( CompRoutine != NULL) { \
574 IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\
576 IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \
578 _IRPSP = IoGetNextIrpStackLocation (Irp); \
579 _IRPSP->MajorFunction = IRP_MJ_DEVICE_CONTROL; \
580 _IRPSP->DeviceObject = DevObj; \
581 _IRPSP->FileObject = FileObj; \
582 _IRPSP->Parameters.DeviceIoControl.OutputBufferLength = 0; \
583 _IRPSP->Parameters.DeviceIoControl.InputBufferLength = BufferLen; \
584 _IRPSP->Parameters.DeviceIoControl.IoControlCode = IOCTL_TCP_SET_INFORMATION_EX; \
585 Irp->AssociatedIrp.SystemBuffer = Buffer; \
589 #define TcpBuildQueryInformationEx(Irp, DevObj, FileObj, CompRoutine, Contxt, InBuffer, InLength, OutBuffer, OutLength)\
591 PIO_STACK_LOCATION _IRPSP; \
592 if ( CompRoutine != NULL) { \
593 IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\
595 IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \
597 _IRPSP = IoGetNextIrpStackLocation (Irp); \
598 _IRPSP->MajorFunction = IRP_MJ_DEVICE_CONTROL; \
599 _IRPSP->DeviceObject = DevObj; \
600 _IRPSP->FileObject = FileObj; \
601 _IRPSP->Parameters.DeviceIoControl.OutputBufferLength = OutLength; \
602 _IRPSP->Parameters.DeviceIoControl.InputBufferLength = InLength; \
603 _IRPSP->Parameters.DeviceIoControl.IoControlCode = IOCTL_TCP_QUERY_INFORMATION_EX; \
604 _IRPSP->Parameters.DeviceIoControl.Type3InputBuffer = InBuffer; \
605 Irp->UserBuffer = OutBuffer; \
608 typedef struct ks_addr_slot {
614 UNICODE_STRING devname;
621 * Tdi client information
624 UNICODE_STRING ksnd_client_name; /* tdi client module name */
625 HANDLE ksnd_pnp_handle; /* the handle for pnp changes */
627 spinlock_t ksnd_addrs_lock; /* serialize ip address list access */
628 LIST_ENTRY ksnd_addrs_list; /* list of the ip addresses */
629 int ksnd_naddrs; /* number of the ip addresses */
632 * Tdilnd internal defintions
635 int ksnd_init; /* initialisation state */
637 TDI_PROVIDER_INFO ksnd_provider; /* tdi tcp/ip provider's information */
639 spinlock_t ksnd_tconn_lock; /* tdi connections access serialise */
641 int ksnd_ntconns; /* number of tconns attached in list */
642 struct list_head ksnd_tconns; /* tdi connections list */
643 cfs_mem_cache_t * ksnd_tconn_slab; /* slabs for ks_tconn_t allocations */
644 event_t ksnd_tconn_exit; /* exit event to be signaled by the last tconn */
646 spinlock_t ksnd_tsdu_lock; /* tsdu access serialise */
648 int ksnd_ntsdus; /* number of tsdu buffers allocated */
649 ulong ksnd_tsdu_size; /* the size of a signel tsdu buffer */
650 cfs_mem_cache_t * ksnd_tsdu_slab; /* slab cache for tsdu buffer allocation */
652 int ksnd_nfreetsdus; /* number of tsdu buffers in the freed list */
653 struct list_head ksnd_freetsdus; /* List of the freed Tsdu buffer. */
655 int ksnd_engine_nums; /* number of tcp sending engine threads */
656 ks_engine_mgr_t * ksnd_engine_mgr; /* tcp sending engine structure */
668 ks_query_local_ipaddr(
702 IN LOCK_OPERATION Operation,
707 KsReleaseMdl (IN PMDL Mdl,
711 KsQueueTdiEngine(ks_tconn_t * tconn, PKS_TSDUMGR);
714 KsRemoveTdiEngine(PKS_TSDUMGR);
732 #endif /* __KERNEL__ */
733 #endif /* __LIBCFS_WINNT_TCPIP_H__ */
737 * c-indentation-style: "K&R"