3 Copyright (c) 2005 - 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23 #define TCP_COMP_VAL(Min, Max, Default, Val) \
24 ((((Val) <= (Max)) && ((Val) >= (Min))) ? (Val) : (Default))
27 Add or remove a route entry in the IP route table associated with this TCP instance.
29 @param Tcb Pointer to the TCP_CB of this TCP instance.
30 @param RouteInfo Pointer to the route info to be processed.
32 @retval EFI_SUCCESS The operation completed successfully.
33 @retval EFI_NOT_STARTED The driver instance has not been started.
34 @retval EFI_NO_MAPPING When using the default address, configuration(DHCP,
35 BOOTP, RARP, etc.) is not finished yet.
36 @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table.
37 @retval EFI_NOT_FOUND This route is not in the routing table
38 (when RouteInfo->DeleteRoute is TRUE).
39 @retval EFI_ACCESS_DENIED The route is already defined in the routing table
40 (when RouteInfo->DeleteRoute is FALSE).
45 IN TCP4_ROUTE_INFO
*RouteInfo
56 RouteInfo
->DeleteRoute
,
57 RouteInfo
->SubnetAddress
,
58 RouteInfo
->SubnetMask
,
59 RouteInfo
->GatewayAddress
66 Get the operational settings of this TCP instance.
68 @param Tcb Pointer to the TCP_CB of this TCP instance.
69 @param Mode Pointer to the buffer to store the operational
72 @retval EFI_SUCCESS The mode data is read.
73 @retval EFI_NOT_STARTED No configuration data is available because this
74 instance hasn't been started.
80 IN TCP4_MODE_DATA
*Mode
84 EFI_TCP4_CONFIG_DATA
*ConfigData
;
85 EFI_TCP4_ACCESS_POINT
*AccessPoint
;
86 EFI_TCP4_OPTION
*Option
;
91 if (!SOCK_IS_CONFIGURED (Sock
) && (Mode
->Tcp4ConfigData
!= NULL
)) {
92 return EFI_NOT_STARTED
;
95 if (Mode
->Tcp4State
!= NULL
) {
96 *(Mode
->Tcp4State
) = (EFI_TCP4_CONNECTION_STATE
) Tcb
->State
;
99 if (Mode
->Tcp4ConfigData
!= NULL
) {
101 ConfigData
= Mode
->Tcp4ConfigData
;
102 AccessPoint
= &(ConfigData
->AccessPoint
);
103 Option
= ConfigData
->ControlOption
;
105 ConfigData
->TypeOfService
= Tcb
->TOS
;
106 ConfigData
->TimeToLive
= Tcb
->TTL
;
108 AccessPoint
->UseDefaultAddress
= Tcb
->UseDefaultAddr
;
110 CopyMem (&AccessPoint
->StationAddress
, &Tcb
->LocalEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
111 AccessPoint
->SubnetMask
= Tcb
->SubnetMask
;
112 AccessPoint
->StationPort
= NTOHS (Tcb
->LocalEnd
.Port
);
114 CopyMem (&AccessPoint
->RemoteAddress
, &Tcb
->RemoteEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
115 AccessPoint
->RemotePort
= NTOHS (Tcb
->RemoteEnd
.Port
);
116 AccessPoint
->ActiveFlag
= (BOOLEAN
) (Tcb
->State
!= TCP_LISTEN
);
118 if (Option
!= NULL
) {
119 Option
->ReceiveBufferSize
= GET_RCV_BUFFSIZE (Tcb
->Sk
);
120 Option
->SendBufferSize
= GET_SND_BUFFSIZE (Tcb
->Sk
);
121 Option
->MaxSynBackLog
= GET_BACKLOG (Tcb
->Sk
);
123 Option
->ConnectionTimeout
= Tcb
->ConnectTimeout
/ TCP_TICK_HZ
;
124 Option
->DataRetries
= Tcb
->MaxRexmit
;
125 Option
->FinTimeout
= Tcb
->FinWait2Timeout
/ TCP_TICK_HZ
;
126 Option
->TimeWaitTimeout
= Tcb
->TimeWaitTimeout
/ TCP_TICK_HZ
;
127 Option
->KeepAliveProbes
= Tcb
->MaxKeepAlive
;
128 Option
->KeepAliveTime
= Tcb
->KeepAliveIdle
/ TCP_TICK_HZ
;
129 Option
->KeepAliveInterval
= Tcb
->KeepAlivePeriod
/ TCP_TICK_HZ
;
131 Option
->EnableNagle
= (BOOLEAN
) (!TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_NAGLE
));
132 Option
->EnableTimeStamp
= (BOOLEAN
) (!TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_TS
));
133 Option
->EnableWindowScaling
= (BOOLEAN
) (!TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_WS
));
135 Option
->EnableSelectiveAck
= FALSE
;
136 Option
->EnablePathMtuDiscovery
= FALSE
;
140 Ip
= Tcb
->IpInfo
->Ip
;
143 return Ip
->GetModeData (Ip
, Mode
->Ip4ModeData
, Mode
->MnpConfigData
, Mode
->SnpModeData
);
148 If AP->StationPort isn't zero, check whether the access point
149 is registered, else generate a random station port for this
152 @param AP Pointer to the access point.
154 @retval EFI_SUCCESS The check is passed or the port is assigned.
155 @retval EFI_INVALID_PARAMETER The non-zero station port is already used.
156 @retval EFI_OUT_OF_RESOURCES No port can be allocated.
161 IN EFI_TCP4_ACCESS_POINT
*AP
166 if (0 != AP
->StationPort
) {
168 // check if a same endpoint is bound
170 if (TcpFindTcbByPeer (&AP
->StationAddress
, AP
->StationPort
)) {
172 return EFI_INVALID_PARAMETER
;
176 // generate a random port
180 if (TCP4_PORT_USER_RESERVED
== mTcp4RandomPort
) {
181 mTcp4RandomPort
= TCP4_PORT_KNOWN
;
186 while (TcpFindTcbByPeer (&AP
->StationAddress
, mTcp4RandomPort
)) {
190 if (mTcp4RandomPort
<= TCP4_PORT_KNOWN
) {
193 DEBUG ((EFI_D_ERROR
, "Tcp4Bind: no port can be allocated "
196 return EFI_OUT_OF_RESOURCES
;
199 mTcp4RandomPort
= TCP4_PORT_KNOWN
+ 1;
206 AP
->StationPort
= mTcp4RandomPort
;
214 Flush the Tcb add its associated protocols.
216 @param Tcb Pointer to the TCP_CB to be flushed.
225 TCP4_PROTO_DATA
*TcpProto
;
227 IpIoConfigIp (Tcb
->IpInfo
, NULL
);
230 TcpProto
= (TCP4_PROTO_DATA
*) Sock
->ProtoReserved
;
232 if (SOCK_IS_CONFIGURED (Sock
)) {
233 RemoveEntryList (&Tcb
->List
);
236 // Uninstall the device path protocl.
238 gBS
->UninstallProtocolInterface (
240 &gEfiDevicePathProtocolGuid
,
243 gBS
->FreePool (Sock
->DevicePath
);
245 TcpSetVariableData (TcpProto
->TcpService
);
248 NetbufFreeList (&Tcb
->SndQue
);
249 NetbufFreeList (&Tcb
->RcvQue
);
253 Attach a Tcb to the socket.
255 @param Sk Pointer to the socket of this TCP instance.
257 @retval EFI_SUCCESS The operation is completed successfully.
258 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
267 TCP4_PROTO_DATA
*ProtoData
;
270 Tcb
= AllocateZeroPool (sizeof (TCP_CB
));
274 DEBUG ((EFI_D_ERROR
, "Tcp4ConfigurePcb: failed to allocate a TCB\n"));
276 return EFI_OUT_OF_RESOURCES
;
279 ProtoData
= (TCP4_PROTO_DATA
*) Sk
->ProtoReserved
;
280 IpIo
= ProtoData
->TcpService
->IpIo
;
283 // Create an IpInfo for this Tcb.
285 Tcb
->IpInfo
= IpIoAddIp (IpIo
);
286 if (Tcb
->IpInfo
== NULL
) {
289 return EFI_OUT_OF_RESOURCES
;
292 InitializeListHead (&Tcb
->List
);
293 InitializeListHead (&Tcb
->SndQue
);
294 InitializeListHead (&Tcb
->RcvQue
);
296 Tcb
->State
= TCP_CLOSED
;
298 ProtoData
->TcpPcb
= Tcb
;
304 Detach the Tcb of the socket.
306 @param Sk Pointer to the socket of this TCP instance.
314 TCP4_PROTO_DATA
*ProtoData
;
317 ProtoData
= (TCP4_PROTO_DATA
*) Sk
->ProtoReserved
;
318 Tcb
= ProtoData
->TcpPcb
;
320 ASSERT (Tcb
!= NULL
);
324 IpIoRemoveIp (ProtoData
->TcpService
->IpIo
, Tcb
->IpInfo
);
328 ProtoData
->TcpPcb
= NULL
;
333 Configure the Tcb using CfgData.
335 @param Sk Pointer to the socket of this TCP instance.
336 @param CfgData Pointer to the TCP configuration data.
338 @retval EFI_SUCCESS The operation is completed successfully.
339 @retval EFI_INVALID_PARAMETER A same access point has been configured in
340 another TCP instance.
341 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
347 IN EFI_TCP4_CONFIG_DATA
*CfgData
350 EFI_IP4_CONFIG_DATA IpCfgData
;
352 EFI_TCP4_OPTION
*Option
;
353 TCP4_PROTO_DATA
*TcpProto
;
356 ASSERT ((CfgData
!= NULL
) && (Sk
!= NULL
) && (Sk
->SockHandle
!= NULL
));
358 TcpProto
= (TCP4_PROTO_DATA
*) Sk
->ProtoReserved
;
359 Tcb
= TcpProto
->TcpPcb
;
361 ASSERT (Tcb
!= NULL
);
364 // Add Ip for send pkt to the peer
366 CopyMem (&IpCfgData
, &mIpIoDefaultIpConfigData
, sizeof (IpCfgData
));
367 IpCfgData
.DefaultProtocol
= EFI_IP_PROTO_TCP
;
368 IpCfgData
.UseDefaultAddress
= CfgData
->AccessPoint
.UseDefaultAddress
;
369 IpCfgData
.StationAddress
= CfgData
->AccessPoint
.StationAddress
;
370 IpCfgData
.SubnetMask
= CfgData
->AccessPoint
.SubnetMask
;
371 IpCfgData
.ReceiveTimeout
= (UINT32
) (-1);
374 // Configure the IP instance this Tcb consumes.
376 Status
= IpIoConfigIp (Tcb
->IpInfo
, &IpCfgData
);
377 if (EFI_ERROR (Status
)) {
382 // Get the default address info if the instance is configured to use default address.
384 if (CfgData
->AccessPoint
.UseDefaultAddress
) {
385 CfgData
->AccessPoint
.StationAddress
= IpCfgData
.StationAddress
;
386 CfgData
->AccessPoint
.SubnetMask
= IpCfgData
.SubnetMask
;
390 // check if we can bind this endpoint in CfgData
392 Status
= Tcp4Bind (&(CfgData
->AccessPoint
));
394 if (EFI_ERROR (Status
)) {
395 DEBUG ((EFI_D_ERROR
, "Tcp4ConfigurePcb: Bind endpoint failed "
396 "with %r\n", Status
));
402 // Initalize the operating information in this Tcb
404 ASSERT (Tcb
->State
== TCP_CLOSED
&&
405 IsListEmpty (&Tcb
->SndQue
) &&
406 IsListEmpty (&Tcb
->RcvQue
));
408 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_NO_KEEPALIVE
);
409 Tcb
->State
= TCP_CLOSED
;
412 Tcb
->RcvMss
= TcpGetRcvMss (Sk
);
415 Tcb
->Rto
= 3 * TCP_TICK_HZ
;
417 Tcb
->CWnd
= Tcb
->SndMss
;
418 Tcb
->Ssthresh
= 0xffffffff;
420 Tcb
->CongestState
= TCP_CONGEST_OPEN
;
422 Tcb
->KeepAliveIdle
= TCP_KEEPALIVE_IDLE_MIN
;
423 Tcb
->KeepAlivePeriod
= TCP_KEEPALIVE_PERIOD
;
424 Tcb
->MaxKeepAlive
= TCP_MAX_KEEPALIVE
;
425 Tcb
->MaxRexmit
= TCP_MAX_LOSS
;
426 Tcb
->FinWait2Timeout
= TCP_FIN_WAIT2_TIME
;
427 Tcb
->TimeWaitTimeout
= TCP_TIME_WAIT_TIME
;
428 Tcb
->ConnectTimeout
= TCP_CONNECT_TIME
;
431 // initialize Tcb in the light of CfgData
433 Tcb
->TTL
= CfgData
->TimeToLive
;
434 Tcb
->TOS
= CfgData
->TypeOfService
;
436 Tcb
->UseDefaultAddr
= CfgData
->AccessPoint
.UseDefaultAddress
;
438 CopyMem (&Tcb
->LocalEnd
.Ip
, &CfgData
->AccessPoint
.StationAddress
, sizeof (IP4_ADDR
));
439 Tcb
->LocalEnd
.Port
= HTONS (CfgData
->AccessPoint
.StationPort
);
440 Tcb
->SubnetMask
= CfgData
->AccessPoint
.SubnetMask
;
442 if (CfgData
->AccessPoint
.ActiveFlag
) {
443 CopyMem (&Tcb
->RemoteEnd
.Ip
, &CfgData
->AccessPoint
.RemoteAddress
, sizeof (IP4_ADDR
));
444 Tcb
->RemoteEnd
.Port
= HTONS (CfgData
->AccessPoint
.RemotePort
);
446 Tcb
->RemoteEnd
.Ip
= 0;
447 Tcb
->RemoteEnd
.Port
= 0;
450 Option
= CfgData
->ControlOption
;
452 if (Option
!= NULL
) {
455 (UINT32
) (TCP_COMP_VAL (
456 TCP_RCV_BUF_SIZE_MIN
,
459 Option
->ReceiveBufferSize
465 (UINT32
) (TCP_COMP_VAL (
466 TCP_SND_BUF_SIZE_MIN
,
469 Option
->SendBufferSize
476 (UINT32
) (TCP_COMP_VAL (
480 Option
->MaxSynBackLog
485 Tcb
->MaxRexmit
= (UINT16
) TCP_COMP_VAL (
491 Tcb
->FinWait2Timeout
= TCP_COMP_VAL (
493 TCP_FIN_WAIT2_TIME_MAX
,
495 (UINT32
) (Option
->FinTimeout
* TCP_TICK_HZ
)
498 if (Option
->TimeWaitTimeout
!= 0) {
499 Tcb
->TimeWaitTimeout
= TCP_COMP_VAL (
501 TCP_TIME_WAIT_TIME_MAX
,
503 (UINT32
) (Option
->TimeWaitTimeout
* TCP_TICK_HZ
)
506 Tcb
->TimeWaitTimeout
= 0;
509 if (Option
->KeepAliveProbes
!= 0) {
510 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_NO_KEEPALIVE
);
512 Tcb
->MaxKeepAlive
= (UINT8
) TCP_COMP_VAL (
513 TCP_MAX_KEEPALIVE_MIN
,
516 Option
->KeepAliveProbes
518 Tcb
->KeepAliveIdle
= TCP_COMP_VAL (
519 TCP_KEEPALIVE_IDLE_MIN
,
520 TCP_KEEPALIVE_IDLE_MAX
,
521 TCP_KEEPALIVE_IDLE_MIN
,
522 (UINT32
) (Option
->KeepAliveTime
* TCP_TICK_HZ
)
524 Tcb
->KeepAlivePeriod
= TCP_COMP_VAL (
525 TCP_KEEPALIVE_PERIOD_MIN
,
526 TCP_KEEPALIVE_PERIOD
,
527 TCP_KEEPALIVE_PERIOD
,
528 (UINT32
) (Option
->KeepAliveInterval
* TCP_TICK_HZ
)
532 Tcb
->ConnectTimeout
= TCP_COMP_VAL (
533 TCP_CONNECT_TIME_MIN
,
536 (UINT32
) (Option
->ConnectionTimeout
* TCP_TICK_HZ
)
539 if (Option
->EnableNagle
== FALSE
) {
540 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_NO_NAGLE
);
543 if (Option
->EnableTimeStamp
== FALSE
) {
544 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_NO_TS
);
547 if (Option
->EnableWindowScaling
== FALSE
) {
548 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_NO_WS
);
553 // The socket is bound, the <SrcIp, SrcPort, DstIp, DstPort> is
554 // determined, construct the IP device path and install it.
556 Status
= TcpInstallDevicePath (Sk
);
557 if (EFI_ERROR (Status
)) {
562 // update state of Tcb and socket
564 if (CfgData
->AccessPoint
.ActiveFlag
== FALSE
) {
566 TcpSetState (Tcb
, TCP_LISTEN
);
567 SockSetState (Sk
, SO_LISTENING
);
569 Sk
->ConfigureState
= SO_CONFIGURED_PASSIVE
;
572 Sk
->ConfigureState
= SO_CONFIGURED_ACTIVE
;
584 The procotol handler provided to the socket layer, used to
585 dispatch the socket level requests by calling the corresponding
588 @param Sock Pointer to the socket of this TCP instance.
589 @param Request The code of this operation request.
590 @param Data Pointer to the operation specific data passed in
591 together with the operation request.
593 @retval EFI_SUCCESS The socket request is completed successfully.
594 @retval other The error status returned by the corresponding TCP
601 IN SOCK_REQUEST Request
,
602 IN VOID
*Data OPTIONAL
606 TCP4_PROTO_DATA
*ProtoData
;
607 EFI_IP4_PROTOCOL
*Ip
;
609 ProtoData
= (TCP4_PROTO_DATA
*) Sock
->ProtoReserved
;
610 Tcb
= ProtoData
->TcpPcb
;
614 Ip
= ProtoData
->TcpService
->IpIo
->Ip
;
620 // After user received data from socket buffer, socket will
621 // notify TCP using this message to give it a chance to send out
622 // window update information
624 ASSERT (Tcb
!= NULL
);
625 TcpOnAppConsume (Tcb
);
630 ASSERT (Tcb
!= NULL
);
647 Tcb
->SndPsh
= TcpGetMaxSndNxt (Tcb
) + GET_SND_DATASIZE (Tcb
->Sk
);
648 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_SND_PSH
);
653 Tcb
->SndUp
= TcpGetMaxSndNxt (Tcb
) + GET_SND_DATASIZE (Tcb
->Sk
) - 1;
654 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_SND_URG
);
660 TcpOnAppConnect (Tcb
);
666 return Tcp4AttachPcb (Sock
);
678 Tcp4DetachPcb (Sock
);
684 return Tcp4ConfigurePcb (
686 (EFI_TCP4_CONFIG_DATA
*) Data
693 ASSERT ((Data
!= NULL
) && (Tcb
!= NULL
));
695 return Tcp4GetMode (Tcb
, (TCP4_MODE_DATA
*) Data
);
701 ASSERT ((Data
!= NULL
) && (Tcb
!= NULL
));
703 return Tcp4Route (Tcb
, (TCP4_ROUTE_INFO
*) Data
);
706 return EFI_UNSUPPORTED
;