1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
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 ksock_tconn_t;
55 typedef struct socket cfs_socket_t;
57 // completion notification callback routine
59 typedef VOID (*ksock_schedule_cb)(struct socket*, int, void *, ulong_ptr);
61 /* completion routine to update tx structure for async sending */
62 typedef PVOID (*ksock_update_tx)(struct socket*, PVOID tx, ulong_ptr);
70 #define KsPrint(X) KsPrintf X
77 // Socket Addresses Related ...
80 #define INADDR_ANY (ULONG)0x00000000
81 #define INADDR_LOOPBACK (ULONG)0x7f000001
82 #define INADDR_BROADCAST (ULONG)0xffffffff
83 #define INADDR_NONE (ULONG)0xffffffff
95 #define TCP_SOCKET_NODELAY 1 // disabling "Nagle"
96 #define TCP_SOCKET_KEEPALIVE 2
97 #define TCP_SOCKET_OOBINLINE 3
98 #define TCP_SOCKET_BSDURGENT 4
99 #define TCP_SOCKET_ATMARK 5
100 #define TCP_SOCKET_WINDOW 6
103 /* Flags we can use with send/ and recv.
104 Added those for 1003.1g not all are supported yet
109 #define MSG_DONTROUTE 4
110 #define MSG_TRYHARD 4 /* Synonym for MSG_DONTROUTE for DECnet */
112 #define MSG_PROBE 0x10 /* Do not send. Only probe path f.e. for MTU */
113 #define MSG_TRUNC 0x20
114 #define MSG_DONTWAIT 0x40 /* Nonblocking io */
115 #define MSG_EOR 0x80 /* End of record */
116 #define MSG_WAITALL 0x100 /* Wait for a full request */
117 #define MSG_FIN 0x200
118 #define MSG_SYN 0x400
119 #define MSG_CONFIRM 0x800 /* Confirm path validity */
120 #define MSG_RST 0x1000
121 #define MSG_ERRQUEUE 0x2000 /* Fetch message from error queue */
122 #define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE */
123 #define MSG_MORE 0x8000 /* Sender will send more */
125 #define MSG_EOF MSG_FIN
129 // Maximum TRANSPORT_ADDRESS Length
131 // it must >= FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address)
132 // + TDI_ADDRESS_LENGTH_IP
134 // I define it a little large and 16 bytes aligned to avoid possible overflow.
137 #define MAX_ADDRESS_LENGTH (0x30)
141 // Maximum Listers Children Sockets
144 #define MAX_CHILD_LISTENERS (4)
147 // Maximum EA Information Length
150 #define EA_MAX_LENGTH ( sizeof(FILE_FULL_EA_INFORMATION) - 1 + \
151 TDI_TRANSPORT_ADDRESS_LENGTH + 1 + \
155 #define UDP_DEVICE_NAME L"\\Device\\Udp"
156 #define TCP_DEVICE_NAME L"\\Device\\Tcp"
163 #define TDINAL_TSDU_DEFAULT_SIZE (0x10000)
165 #define KS_TSDU_MAGIC 'KSTD'
167 #define KS_TSDU_ATTACHED 0x00000001 // Attached to the socket receive tsdu list
169 typedef struct _KS_TSDU {
174 struct list_head Link;
176 ULONG TotalLength; // Total size of KS_TSDU
178 ULONG StartOffset; // Start offset of the first Tsdu unit
179 ULONG LastOffset; // End offset of the last Tsdu unit
189 } KS_TSDU, *PKS_TSDU;
191 #define TSDU_TYPE_BUF ((USHORT)0x5401)
192 #define TSDU_TYPE_DAT ((USHORT)0x5402)
193 #define TSDU_TYPE_MDL ((USHORT)0x5403)
195 #define KS_TSDU_BUF_RECEIVING 0x0001
196 typedef struct _KS_TSDU_BUF {
206 } KS_TSDU_BUF, *PKS_TSDU_BUF;
208 #define KS_TSDU_DAT_RECEIVING 0x0001
210 typedef struct _KS_TSDU_DAT {
222 } KS_TSDU_DAT, *PKS_TSDU_DAT;
224 #define KS_DWORD_ALIGN(x) (((x) + 0x03) & (~(0x03)))
225 #define KS_TSDU_STRU_SIZE(Len) (KS_DWORD_ALIGN((Len) + FIELD_OFFSET(KS_TSDU_DAT, Data)))
227 typedef struct _KS_TSDU_MDL {
238 } KS_TSDU_MDL, *PKS_TSDU_MDL;
241 typedef struct _KS_TSDUMGR {
243 struct list_head TsduList;
248 } KS_TSDUMGR, *PKS_TSDUMGR;
251 typedef struct _KS_CHAIN {
254 KS_TSDUMGR Expedited;
256 } KS_CHAIN, *PKS_CHAIN;
259 #define TDINAL_SCHED_FACTOR (1)
260 #define CAN_BE_SCHED(Len, Limit) (Len >= ((Limit) >> TDINAL_SCHED_FACTOR))
263 // Handler Settings Indictor
266 #define TDI_EVENT_MAXIMUM_HANDLER (TDI_EVENT_ERROR_EX + 1)
269 typedef struct _KS_EVENT_HANDLERS {
270 BOOLEAN IsActive[TDI_EVENT_MAXIMUM_HANDLER];
271 PVOID Handler [TDI_EVENT_MAXIMUM_HANDLER];
272 } KS_EVENT_HANDLERS, *PKS_EVENT_HANDLERS;
274 #define SetEventHandler(ha, ht, hr) do { \
275 ha.IsActive[ht] = TRUE; \
276 ha.Handler[ht] = (PVOID) (hr); \
280 // KSock Internal Structures
283 typedef struct _KS_ADDRESS {
286 TRANSPORT_ADDRESS Tdi;
287 UCHAR Pading[MAX_ADDRESS_LENGTH];
291 PFILE_OBJECT FileObject;
293 } KS_ADDRESS, *PKS_ADDRESS;
296 // Structures for Disconnect Workitem
299 typedef struct _KS_DISCONNECT_WORKITEM {
301 WORK_QUEUE_ITEM WorkItem; // Workitem to perform disconnection
302 ksock_tconn_t * tconn; // tdi connecton
303 ULONG Flags; // connection broken/discnnection flags
304 KEVENT Event; // sync event
306 } KS_DISCONNECT_WORKITEM, *PKS_DISCONNECT_WORKITEM;
309 typedef struct _KS_CONNECTION {
311 HANDLE Handle; // Handle of the tdi connection
312 PFILE_OBJECT FileObject; // FileObject if the conn object
314 PTRANSPORT_ADDRESS Remote; // the ConnectionInfo of this connection
315 PTDI_CONNECTION_INFORMATION ConnectionInfo;
317 ULONG nagle; // Tcp options
319 } KS_CONNECTION, *PKS_CONNECTION;
326 typedef MDL ksock_mdl_t;
327 typedef UNICODE_STRING ksock_unicode_name_t;
328 typedef WORK_QUEUE_ITEM ksock_workitem_t;
331 typedef KS_CHAIN ksock_chain_t;
332 typedef KS_ADDRESS ksock_tdi_addr_t;
333 typedef KS_CONNECTION ksock_tconn_info_t;
334 typedef KS_DISCONNECT_WORKITEM ksock_disconnect_workitem_t;
338 // Structures for transmission done Workitem
341 typedef struct _KS_TCPX_FINILIZE {
342 ksock_workitem_t item;
347 typedef struct ksock_backlogs {
349 struct list_head list; /* list to link the backlog connections */
350 int num; /* number of backlogs in the list */
355 typedef struct ksock_daemon {
357 ksock_tconn_t * tconn; /* the listener connection object */
358 unsigned short nbacklogs; /* number of listening backlog conns */
359 unsigned short port; /* listening port number */
360 int shutdown; /* daemon threads is to exit */
361 struct list_head list; /* to be attached into ksock_nal_data_t*/
368 kstt_sender = 0, // normal sending connection type, it's active connection, while
369 // child tconn is for passive connection.
371 kstt_listener, // listener daemon type, it just acts as a daemon, and it does
372 // not have real connection. It manages children tcons to accept
373 // or refuse the connecting request from remote peers.
375 kstt_child, // accepted child connection type, it's parent must be Listener
381 ksts_uninited = 0, // tconn is just allocated (zero values), not initialized yet
383 ksts_inited, // tconn structure initialized: so it now can be identified as
384 // a sender, listener or a child
386 ksts_bind, // tconn is bound: the local address object (ip/port) is created.
387 // after being bound, we must call ksocknal_put_tconn to release
388 // the tconn objects, it's not safe just to free the memory of tconn.
390 ksts_associated, // the connection object is created and associated with the address
391 // object. so it's ready for connection. only for child and sender.
393 ksts_connecting, // only used by child tconn: in the ConnectEvent handler routine,
394 // it indicts the child tconn is busy to be connected to the peer.
396 ksts_connected, // the connection is built already: for sender and child
398 ksts_listening, // listener daemon is working, only for listener tconn
400 ksts_disconnected, // disconnected by user
401 ksts_aborted, // un-exptected broken status
403 ksts_last // total number of tconn statuses
406 #define KS_TCONN_MAGIC 'KSTM'
408 #define KS_TCONN_HANDLERS_SET 0x00000001 // Conection handlers are set.
409 #define KS_TCONN_DISCONNECT_BUSY 0x00010000 // Disconnect Workitem is queued ...
410 #define KS_TCONN_DESTROY_BUSY 0x00020000 // Destory Workitem is queued ...
412 #define KS_TCONN_DAEMON_STARTED 0x00100000 // indict the daemon is started,
413 // only valid for listener
417 ulong_ptr kstc_magic; /* Magic & Flags */
418 ulong_ptr kstc_flags;
420 spinlock_t kstc_lock; /* serialise lock*/
421 void * kstc_conn; /* ksock_conn_t */
423 ksock_tconn_type kstc_type; /* tdi connection Type */
424 ksock_tconn_state kstc_state; /* tdi connection state flag */
426 ksock_unicode_name_t kstc_dev; /* tcp transport device name */
428 ksock_tdi_addr_t kstc_addr; /* local address handlers / Objects */
430 atomic_t kstc_refcount; /* reference count of ksock_tconn */
432 struct list_head kstc_list; /* linked to global ksocknal_data */
437 int nbacklog; /* total number of backlog tdi connections */
438 ksock_backlogs_t kstc_listening; /* listeing backlog child connections */
439 ksock_backlogs_t kstc_accepted; /* connected backlog child connections */
440 event_t kstc_accept_event; /* Signaled by AcceptedHander,
441 ksocknal_wait_accpeted_conns waits on */
442 event_t kstc_destroy_event; /* Signaled when accepted child is released */
446 ksock_tconn_info_t kstc_info; /* Connection Info if Connected */
447 ksock_chain_t kstc_recv; /* tsdu engine for data receiving */
448 ksock_chain_t kstc_send; /* tsdu engine for data sending */
450 int kstc_queued; /* Attached to Parent->ChildList ... */
451 int kstc_queueno; /* 0: Attached to Listening list
452 1: Attached to Accepted list */
454 int kstc_busy; /* referred by ConnectEventCallback ? */
455 int kstc_accepted; /* the connection is built ready ? */
457 struct list_head kstc_link; /* linked to parent tdi connection */
458 ksock_tconn_t * kstc_parent; /* pointers to it's listener parent */
462 ksock_tconn_info_t kstc_info; /* Connection Info if Connected */
463 ksock_chain_t kstc_recv; /* tsdu engine for data receiving */
464 ksock_chain_t kstc_send; /* tsdu engine for data sending */
468 ulong_ptr kstc_snd_wnd; /* Sending window size */
469 ulong_ptr kstc_rcv_wnd; /* Recving window size */
471 ksock_workitem_t kstc_destroy; /* tconn destruction workitem */
472 ksock_disconnect_workitem_t kstc_disconnect; /* connection disconnect workitem */
474 ksock_schedule_cb kstc_sched_cb; /* notification callback routine of completion */
475 ksock_update_tx kstc_update_tx; /* aync sending callback to update tx */
478 #define SOCK_WMEM_QUEUED(sock) (0)
480 #define TDINAL_WINDOW_DEFAULT_SIZE (0x100000)
483 struct _KS_UDP_COMPLETION_CONTEXT;
484 struct _KS_TCP_COMPLETION_CONTEXT;
489 (*PKS_UDP_COMPLETION_ROUTINE) (
491 IN struct _KS_UDP_COMPLETION_CONTEXT
498 (*PKS_TCP_COMPLETION_ROUTINE) (
500 IN struct _KS_TCP_COMPLETION_CONTEXT
505 // Udp Irp Completion Context
508 typedef struct _KS_UDP_COMPLETION_CONTEXT {
512 PFILE_OBJECT AddressObject;
513 ksock_tconn_t * tconn;
516 PKS_UDP_COMPLETION_ROUTINE CompletionRoutine;
517 PVOID CompletionContext;
519 } KS_UDP_COMPLETION_CONTEXT, *PKS_UDP_COMPLETION_CONTEXT;
523 // Tcp Irp Completion Context (used by tcp data recv/send)
526 typedef struct _KS_TCP_COMPLETION_CONTEXT {
528 PKEVENT Event; // Event to be waited on by Irp caller ...
530 ksock_tconn_t * tconn; // the tdi connection
532 PKS_TCP_COMPLETION_ROUTINE CompletionRoutine;
533 PVOID CompletionContext;
534 PVOID CompletionContext2;
536 PKS_TSDUMGR KsTsduMgr; // Tsdu buffer manager
539 // These tow new members are for NON_BLOCKING transmission
542 BOOLEAN bCounted; // To indict needing refcount to
543 // execute CompetionRoutine
544 ULONG ReferCount; // Refer count of this structure
546 } KS_TCP_COMPLETION_CONTEXT, *PKS_TCP_COMPLETION_CONTEXT;
548 typedef KS_TCP_COMPLETION_CONTEXT ksock_tdi_tx_t, ksock_tdi_rx_t;
555 #define IOCTL_TCP_QUERY_INFORMATION_EX \
556 CTL_CODE(FILE_DEVICE_NETWORK, 0, METHOD_NEITHER, FILE_ANY_ACCESS)
557 #define IOCTL_TCP_SET_INFORMATION_EX \
558 CTL_CODE(FILE_DEVICE_NETWORK, 1, METHOD_BUFFERED, FILE_WRITE_ACCESS)
561 #define TcpBuildSetInformationEx(Irp, DevObj, FileObj, CompRoutine, Contxt, Buffer, BufferLen)\
563 PIO_STACK_LOCATION _IRPSP; \
564 if ( CompRoutine != NULL) { \
565 IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\
567 IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \
569 _IRPSP = IoGetNextIrpStackLocation (Irp); \
570 _IRPSP->MajorFunction = IRP_MJ_DEVICE_CONTROL; \
571 _IRPSP->DeviceObject = DevObj; \
572 _IRPSP->FileObject = FileObj; \
573 _IRPSP->Parameters.DeviceIoControl.OutputBufferLength = 0; \
574 _IRPSP->Parameters.DeviceIoControl.InputBufferLength = BufferLen; \
575 _IRPSP->Parameters.DeviceIoControl.IoControlCode = IOCTL_TCP_SET_INFORMATION_EX; \
576 Irp->AssociatedIrp.SystemBuffer = Buffer; \
580 #define TcpBuildQueryInformationEx(Irp, DevObj, FileObj, CompRoutine, Contxt, InBuffer, InLength, OutBuffer, OutLength)\
582 PIO_STACK_LOCATION _IRPSP; \
583 if ( CompRoutine != NULL) { \
584 IoSetCompletionRoutine( Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE);\
586 IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE); \
588 _IRPSP = IoGetNextIrpStackLocation (Irp); \
589 _IRPSP->MajorFunction = IRP_MJ_DEVICE_CONTROL; \
590 _IRPSP->DeviceObject = DevObj; \
591 _IRPSP->FileObject = FileObj; \
592 _IRPSP->Parameters.DeviceIoControl.OutputBufferLength = OutLength; \
593 _IRPSP->Parameters.DeviceIoControl.InputBufferLength = InLength; \
594 _IRPSP->Parameters.DeviceIoControl.IoControlCode = IOCTL_TCP_QUERY_INFORMATION_EX; \
595 _IRPSP->Parameters.DeviceIoControl.Type3InputBuffer = InBuffer; \
596 Irp->UserBuffer = OutBuffer; \
600 typedef struct ks_addr_slot {
606 UNICODE_STRING devname;
613 * Tdi client information
616 UNICODE_STRING ksnd_client_name; /* tdi client module name */
617 HANDLE ksnd_pnp_handle; /* the handle for pnp changes */
619 spinlock_t ksnd_addrs_lock; /* serialize ip address list access */
620 LIST_ENTRY ksnd_addrs_list; /* list of the ip addresses */
621 int ksnd_naddrs; /* number of the ip addresses */
624 * Tdilnd internal defintions
627 int ksnd_init; /* initialisation state */
629 TDI_PROVIDER_INFO ksnd_provider; /* tdi tcp/ip provider's information */
631 spinlock_t ksnd_tconn_lock; /* tdi connections access serialise */
633 int ksnd_ntconns; /* number of tconns attached in list */
634 struct list_head ksnd_tconns; /* tdi connections list */
635 cfs_mem_cache_t * ksnd_tconn_slab; /* slabs for ksock_tconn_t allocations */
636 event_t ksnd_tconn_exit; /* exit event to be signaled by the last tconn */
638 spinlock_t ksnd_tsdu_lock; /* tsdu access serialise */
640 int ksnd_ntsdus; /* number of tsdu buffers allocated */
641 ulong_ptr ksnd_tsdu_size; /* the size of a signel tsdu buffer */
642 cfs_mem_cache_t * ksnd_tsdu_slab; /* slab cache for tsdu buffer allocation */
644 int ksnd_nfreetsdus; /* number of tsdu buffers in the freed list */
645 struct list_head ksnd_freetsdus; /* List of the freed Tsdu buffer. */
647 spinlock_t ksnd_daemon_lock; /* stabilize daemon ops */
648 int ksnd_ndaemons; /* number of listening daemons */
649 struct list_head ksnd_daemons; /* listening daemon list */
650 event_t ksnd_daemon_exit; /* the last daemon quiting should singal it */
661 #endif /* __KERNEL__ */
662 #endif /* __LIBCFS_WINNT_TCPIP_H__ */
666 * c-indentation-style: "K&R"