TcpOutput.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223
  1. /** @file
  2. TCP output process routines.
  3. Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "TcpMain.h"
  7. UINT8 mTcpOutFlag[] = {
  8. 0, // TCP_CLOSED
  9. 0, // TCP_LISTEN
  10. TCP_FLG_SYN, // TCP_SYN_SENT
  11. TCP_FLG_SYN | TCP_FLG_ACK, // TCP_SYN_RCVD
  12. TCP_FLG_ACK, // TCP_ESTABLISHED
  13. TCP_FLG_FIN | TCP_FLG_ACK, // TCP_FIN_WAIT_1
  14. TCP_FLG_ACK, // TCP_FIN_WAIT_2
  15. TCP_FLG_ACK | TCP_FLG_FIN, // TCP_CLOSING
  16. TCP_FLG_ACK, // TCP_TIME_WAIT
  17. TCP_FLG_ACK, // TCP_CLOSE_WAIT
  18. TCP_FLG_FIN | TCP_FLG_ACK // TCP_LAST_ACK
  19. };
  20. /**
  21. Compute the sequence space left in the old receive window.
  22. @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
  23. @return The sequence space left in the old receive window.
  24. **/
  25. UINT32
  26. TcpRcvWinOld (
  27. IN TCP_CB *Tcb
  28. )
  29. {
  30. UINT32 OldWin;
  31. OldWin = 0;
  32. if (TCP_SEQ_GT (Tcb->RcvWl2 + Tcb->RcvWnd, Tcb->RcvNxt)) {
  33. OldWin = TCP_SUB_SEQ (
  34. Tcb->RcvWl2 + Tcb->RcvWnd,
  35. Tcb->RcvNxt
  36. );
  37. }
  38. return OldWin;
  39. }
  40. /**
  41. Compute the current receive window.
  42. @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
  43. @return The size of the current receive window, in bytes.
  44. **/
  45. UINT32
  46. TcpRcvWinNow (
  47. IN TCP_CB *Tcb
  48. )
  49. {
  50. SOCKET *Sk;
  51. UINT32 Win;
  52. UINT32 Increase;
  53. UINT32 OldWin;
  54. Sk = Tcb->Sk;
  55. ASSERT (Sk != NULL);
  56. OldWin = TcpRcvWinOld (Tcb);
  57. Win = SockGetFreeSpace (Sk, SOCK_RCV_BUF);
  58. Increase = 0;
  59. if (Win > OldWin) {
  60. Increase = Win - OldWin;
  61. }
  62. //
  63. // Receiver's SWS: don't advertise a bigger window
  64. // unless it can be increased by at least one Mss or
  65. // half of the receive buffer.
  66. //
  67. if ((Increase > Tcb->SndMss) || (2 * Increase >= GET_RCV_BUFFSIZE (Sk))) {
  68. return Win;
  69. }
  70. return OldWin;
  71. }
  72. /**
  73. Compute the value to fill in the window size field of the outgoing segment.
  74. @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
  75. @param[in] Syn The flag to indicate whether the outgoing segment
  76. is a SYN segment.
  77. @return The value of the local receive window size used to fill the outgoing segment.
  78. **/
  79. UINT16
  80. TcpComputeWnd (
  81. IN OUT TCP_CB *Tcb,
  82. IN BOOLEAN Syn
  83. )
  84. {
  85. UINT32 Wnd;
  86. //
  87. // RFC requires that initial window not be scaled
  88. //
  89. if (Syn) {
  90. Wnd = GET_RCV_BUFFSIZE (Tcb->Sk);
  91. } else {
  92. Wnd = TcpRcvWinNow (Tcb);
  93. Tcb->RcvWnd = Wnd;
  94. }
  95. Wnd = MIN (Wnd >> Tcb->RcvWndScale, 0xffff);
  96. return NTOHS ((UINT16)Wnd);
  97. }
  98. /**
  99. Get the maximum SndNxt.
  100. @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
  101. @return The sequence number of the maximum SndNxt.
  102. **/
  103. TCP_SEQNO
  104. TcpGetMaxSndNxt (
  105. IN TCP_CB *Tcb
  106. )
  107. {
  108. LIST_ENTRY *Entry;
  109. NET_BUF *Nbuf;
  110. if (IsListEmpty (&Tcb->SndQue)) {
  111. return Tcb->SndNxt;
  112. }
  113. Entry = Tcb->SndQue.BackLink;
  114. Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
  115. ASSERT (TCP_SEQ_GEQ (TCPSEG_NETBUF (Nbuf)->End, Tcb->SndNxt));
  116. return TCPSEG_NETBUF (Nbuf)->End;
  117. }
  118. /**
  119. Compute how much data to send.
  120. @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
  121. @param[in] Force If TRUE, to ignore the sender's SWS avoidance algorithm and send
  122. out data by force.
  123. @return The length of the data can be sent. If 0, no data can be sent.
  124. **/
  125. UINT32
  126. TcpDataToSend (
  127. IN TCP_CB *Tcb,
  128. IN INTN Force
  129. )
  130. {
  131. SOCKET *Sk;
  132. UINT32 Win;
  133. UINT32 Len;
  134. UINT32 Left;
  135. UINT32 Limit;
  136. Sk = Tcb->Sk;
  137. ASSERT (Sk != NULL);
  138. //
  139. // TCP should NOT send data beyond the send window
  140. // and congestion window. The right edge of send
  141. // window is defined as SND.WL2 + SND.WND. The right
  142. // edge of congestion window is defined as SND.UNA +
  143. // CWND.
  144. //
  145. Win = 0;
  146. Limit = Tcb->SndWl2 + Tcb->SndWnd;
  147. if (TCP_SEQ_GT (Limit, Tcb->SndUna + Tcb->CWnd)) {
  148. Limit = Tcb->SndUna + Tcb->CWnd;
  149. }
  150. if (TCP_SEQ_GT (Limit, Tcb->SndNxt)) {
  151. Win = TCP_SUB_SEQ (Limit, Tcb->SndNxt);
  152. }
  153. //
  154. // The data to send contains two parts: the data on the
  155. // socket send queue, and the data on the TCB's send
  156. // buffer. The later can be non-zero if the peer shrinks
  157. // its advertised window.
  158. //
  159. Left = GET_SND_DATASIZE (Sk) + TCP_SUB_SEQ (TcpGetMaxSndNxt (Tcb), Tcb->SndNxt);
  160. Len = MIN (Win, Left);
  161. if (Len > Tcb->SndMss) {
  162. Len = Tcb->SndMss;
  163. }
  164. if ((Force != 0) || ((Len == 0) && (Left == 0))) {
  165. return Len;
  166. }
  167. if ((Len == 0) && (Left != 0)) {
  168. goto SetPersistTimer;
  169. }
  170. //
  171. // Sender's SWS avoidance: Don't send a small segment unless
  172. // a)A full-sized segment can be sent,
  173. // b)At least one-half of the maximum sized windows that
  174. // the other end has ever advertised.
  175. // c)It can send everything it has, and either it isn't
  176. // expecting an ACK, or the Nagle algorithm is disabled.
  177. //
  178. if ((Len == Tcb->SndMss) || (2 * Len >= Tcb->SndWndMax)) {
  179. return Len;
  180. }
  181. if ((Len == Left) &&
  182. ((Tcb->SndNxt == Tcb->SndUna) || TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE))
  183. )
  184. {
  185. return Len;
  186. }
  187. //
  188. // RFC1122 suggests to set a timer when SWSA forbids TCP
  189. // sending more data, and combines it with a probe timer.
  190. //
  191. SetPersistTimer:
  192. if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_REXMIT)) {
  193. DEBUG (
  194. (DEBUG_WARN,
  195. "TcpDataToSend: enter persistent state for TCB %p\n",
  196. Tcb)
  197. );
  198. if (!Tcb->ProbeTimerOn) {
  199. TcpSetProbeTimer (Tcb);
  200. }
  201. }
  202. return 0;
  203. }
  204. /**
  205. Build the TCP header of the TCP segment and transmit the segment by IP.
  206. @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
  207. @param[in] Nbuf Pointer to the buffer containing the segment to be
  208. sent out.
  209. @retval 0 The segment was sent out successfully.
  210. @retval -1 An error condition occurred.
  211. **/
  212. INTN
  213. TcpTransmitSegment (
  214. IN OUT TCP_CB *Tcb,
  215. IN NET_BUF *Nbuf
  216. )
  217. {
  218. UINT16 Len;
  219. TCP_HEAD *Head;
  220. TCP_SEG *Seg;
  221. BOOLEAN Syn;
  222. UINT32 DataLen;
  223. ASSERT ((Nbuf != NULL) && (Nbuf->Tcp == NULL));
  224. if (TcpVerifySegment (Nbuf) == 0) {
  225. return -1;
  226. }
  227. DataLen = Nbuf->TotalSize;
  228. Seg = TCPSEG_NETBUF (Nbuf);
  229. Syn = TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN);
  230. if (Syn) {
  231. Len = TcpSynBuildOption (Tcb, Nbuf);
  232. } else {
  233. Len = TcpBuildOption (Tcb, Nbuf);
  234. }
  235. ASSERT ((Len % 4 == 0) && (Len <= 40));
  236. Len += sizeof (TCP_HEAD);
  237. Head = (TCP_HEAD *)NetbufAllocSpace (
  238. Nbuf,
  239. sizeof (TCP_HEAD),
  240. NET_BUF_HEAD
  241. );
  242. ASSERT (Head != NULL);
  243. Nbuf->Tcp = Head;
  244. Head->SrcPort = Tcb->LocalEnd.Port;
  245. Head->DstPort = Tcb->RemoteEnd.Port;
  246. Head->Seq = NTOHL (Seg->Seq);
  247. Head->Ack = NTOHL (Tcb->RcvNxt);
  248. Head->HeadLen = (UINT8)(Len >> 2);
  249. Head->Res = 0;
  250. Head->Wnd = TcpComputeWnd (Tcb, Syn);
  251. Head->Checksum = 0;
  252. //
  253. // Check whether to set the PSH flag.
  254. //
  255. TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_PSH);
  256. if (DataLen != 0) {
  257. if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_PSH) &&
  258. TCP_SEQ_BETWEEN (Seg->Seq, Tcb->SndPsh, Seg->End)
  259. )
  260. {
  261. TCP_SET_FLG (Seg->Flag, TCP_FLG_PSH);
  262. TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH);
  263. } else if ((Seg->End == Tcb->SndNxt) && (GET_SND_DATASIZE (Tcb->Sk) == 0)) {
  264. TCP_SET_FLG (Seg->Flag, TCP_FLG_PSH);
  265. }
  266. }
  267. //
  268. // Check whether to set the URG flag and the urgent pointer.
  269. //
  270. TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_URG);
  271. if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_URG) && TCP_SEQ_LEQ (Seg->Seq, Tcb->SndUp)) {
  272. TCP_SET_FLG (Seg->Flag, TCP_FLG_URG);
  273. if (TCP_SEQ_LT (Tcb->SndUp, Seg->End)) {
  274. Seg->Urg = (UINT16)TCP_SUB_SEQ (Tcb->SndUp, Seg->Seq);
  275. } else {
  276. Seg->Urg = (UINT16)MIN (
  277. TCP_SUB_SEQ (
  278. Tcb->SndUp,
  279. Seg->Seq
  280. ),
  281. 0xffff
  282. );
  283. }
  284. }
  285. Head->Flag = Seg->Flag;
  286. Head->Urg = NTOHS (Seg->Urg);
  287. Head->Checksum = TcpChecksum (Nbuf, Tcb->HeadSum);
  288. //
  289. // Update the TCP session's control information.
  290. //
  291. Tcb->RcvWl2 = Tcb->RcvNxt;
  292. if (Syn) {
  293. Tcb->RcvWnd = NTOHS (Head->Wnd);
  294. }
  295. //
  296. // Clear the delayedack flag.
  297. //
  298. Tcb->DelayedAck = 0;
  299. return TcpSendIpPacket (Tcb, Nbuf, &Tcb->LocalEnd.Ip, &Tcb->RemoteEnd.Ip, Tcb->Sk->IpVersion);
  300. }
  301. /**
  302. Get a segment from the Tcb's SndQue.
  303. @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
  304. @param[in] Seq The sequence number of the segment.
  305. @param[in] Len The maximum length of the segment.
  306. @return Pointer to the segment. If NULL, some error occurred.
  307. **/
  308. NET_BUF *
  309. TcpGetSegmentSndQue (
  310. IN TCP_CB *Tcb,
  311. IN TCP_SEQNO Seq,
  312. IN UINT32 Len
  313. )
  314. {
  315. LIST_ENTRY *Head;
  316. LIST_ENTRY *Cur;
  317. NET_BUF *Node;
  318. TCP_SEG *Seg;
  319. NET_BUF *Nbuf;
  320. TCP_SEQNO End;
  321. UINT8 *Data;
  322. UINT8 Flag;
  323. INT32 Offset;
  324. INT32 CopyLen;
  325. ASSERT ((Tcb != NULL) && TCP_SEQ_LEQ (Seq, Tcb->SndNxt) && (Len > 0));
  326. //
  327. // Find the segment that contains the Seq.
  328. //
  329. Head = &Tcb->SndQue;
  330. Node = NULL;
  331. Seg = NULL;
  332. NET_LIST_FOR_EACH (Cur, Head) {
  333. Node = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
  334. Seg = TCPSEG_NETBUF (Node);
  335. if (TCP_SEQ_LT (Seq, Seg->End) && TCP_SEQ_LEQ (Seg->Seq, Seq)) {
  336. break;
  337. }
  338. }
  339. if ((Cur == Head) || (Seg == NULL) || (Node == NULL)) {
  340. return NULL;
  341. }
  342. //
  343. // Return the buffer if it can be returned without
  344. // adjustment:
  345. //
  346. if ((Seg->Seq == Seq) &&
  347. TCP_SEQ_LEQ (Seg->End, Seg->Seq + Len) &&
  348. !NET_BUF_SHARED (Node)
  349. )
  350. {
  351. NET_GET_REF (Node);
  352. return Node;
  353. }
  354. //
  355. // Create a new buffer and copy data there.
  356. //
  357. Nbuf = NetbufAlloc (Len + TCP_MAX_HEAD);
  358. if (Nbuf == NULL) {
  359. return NULL;
  360. }
  361. NetbufReserve (Nbuf, TCP_MAX_HEAD);
  362. Flag = Seg->Flag;
  363. End = Seg->End;
  364. if (TCP_SEQ_LT (Seq + Len, Seg->End)) {
  365. End = Seq + Len;
  366. }
  367. CopyLen = TCP_SUB_SEQ (End, Seq);
  368. Offset = TCP_SUB_SEQ (Seq, Seg->Seq);
  369. //
  370. // If SYN is set and out of the range, clear the flag.
  371. // Because the sequence of the first byte is SEG.SEQ+1,
  372. // adjust Offset by -1. If SYN is in the range, copy
  373. // one byte less.
  374. //
  375. if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
  376. if (TCP_SEQ_LT (Seg->Seq, Seq)) {
  377. TCP_CLEAR_FLG (Flag, TCP_FLG_SYN);
  378. Offset--;
  379. } else {
  380. CopyLen--;
  381. }
  382. }
  383. //
  384. // If FIN is set and in the range, copy one byte less,
  385. // and if it is out of the range, clear the flag.
  386. //
  387. if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {
  388. if (Seg->End == End) {
  389. CopyLen--;
  390. } else {
  391. TCP_CLEAR_FLG (Flag, TCP_FLG_FIN);
  392. }
  393. }
  394. ASSERT (CopyLen >= 0);
  395. //
  396. // Copy data to the segment
  397. //
  398. if (CopyLen != 0) {
  399. Data = NetbufAllocSpace (Nbuf, CopyLen, NET_BUF_TAIL);
  400. ASSERT (Data != NULL);
  401. if ((INT32)NetbufCopy (Node, Offset, CopyLen, Data) != CopyLen) {
  402. goto OnError;
  403. }
  404. }
  405. CopyMem (TCPSEG_NETBUF (Nbuf), Seg, sizeof (TCP_SEG));
  406. TCPSEG_NETBUF (Nbuf)->Seq = Seq;
  407. TCPSEG_NETBUF (Nbuf)->End = End;
  408. TCPSEG_NETBUF (Nbuf)->Flag = Flag;
  409. return Nbuf;
  410. OnError:
  411. NetbufFree (Nbuf);
  412. return NULL;
  413. }
  414. /**
  415. Get a segment from the Tcb's socket buffer.
  416. @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
  417. @param[in] Seq The sequence number of the segment.
  418. @param[in] Len The maximum length of the segment.
  419. @return Pointer to the segment. If NULL, some error occurred.
  420. **/
  421. NET_BUF *
  422. TcpGetSegmentSock (
  423. IN TCP_CB *Tcb,
  424. IN TCP_SEQNO Seq,
  425. IN UINT32 Len
  426. )
  427. {
  428. NET_BUF *Nbuf;
  429. UINT8 *Data;
  430. UINT32 DataGet;
  431. ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));
  432. Nbuf = NetbufAlloc (Len + TCP_MAX_HEAD);
  433. if (Nbuf == NULL) {
  434. DEBUG (
  435. (DEBUG_ERROR,
  436. "TcpGetSegmentSock: failed to allocate a netbuf for TCB %p\n",
  437. Tcb)
  438. );
  439. return NULL;
  440. }
  441. NetbufReserve (Nbuf, TCP_MAX_HEAD);
  442. DataGet = 0;
  443. if (Len != 0) {
  444. //
  445. // copy data to the segment.
  446. //
  447. Data = NetbufAllocSpace (Nbuf, Len, NET_BUF_TAIL);
  448. ASSERT (Data != NULL);
  449. DataGet = SockGetDataToSend (Tcb->Sk, 0, Len, Data);
  450. }
  451. NET_GET_REF (Nbuf);
  452. TCPSEG_NETBUF (Nbuf)->Seq = Seq;
  453. TCPSEG_NETBUF (Nbuf)->End = Seq + Len;
  454. InsertTailList (&(Tcb->SndQue), &(Nbuf->List));
  455. if (DataGet != 0) {
  456. SockDataSent (Tcb->Sk, DataGet);
  457. }
  458. return Nbuf;
  459. }
  460. /**
  461. Get a segment starting from sequence Seq of a maximum
  462. length of Len.
  463. @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
  464. @param[in] Seq The sequence number of the segment.
  465. @param[in] Len The maximum length of the segment.
  466. @return Pointer to the segment. If NULL, some error occurred.
  467. **/
  468. NET_BUF *
  469. TcpGetSegment (
  470. IN TCP_CB *Tcb,
  471. IN TCP_SEQNO Seq,
  472. IN UINT32 Len
  473. )
  474. {
  475. NET_BUF *Nbuf;
  476. ASSERT (Tcb != NULL);
  477. //
  478. // Compare the SndNxt with the max sequence number sent.
  479. //
  480. if ((Len != 0) && TCP_SEQ_LT (Seq, TcpGetMaxSndNxt (Tcb))) {
  481. Nbuf = TcpGetSegmentSndQue (Tcb, Seq, Len);
  482. } else {
  483. Nbuf = TcpGetSegmentSock (Tcb, Seq, Len);
  484. }
  485. if (TcpVerifySegment (Nbuf) == 0) {
  486. NetbufFree (Nbuf);
  487. return NULL;
  488. }
  489. return Nbuf;
  490. }
  491. /**
  492. Retransmit the segment from sequence Seq.
  493. @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
  494. @param[in] Seq The sequence number of the segment to be retransmitted.
  495. @retval 0 Retransmission succeeded.
  496. @retval -1 Error condition occurred.
  497. **/
  498. INTN
  499. TcpRetransmit (
  500. IN TCP_CB *Tcb,
  501. IN TCP_SEQNO Seq
  502. )
  503. {
  504. NET_BUF *Nbuf;
  505. UINT32 Len;
  506. //
  507. // Compute the maximum length of retransmission. It is
  508. // limited by three factors:
  509. // 1. Less than SndMss
  510. // 2. Must in the current send window
  511. // 3. Will not change the boundaries of queued segments.
  512. //
  513. //
  514. // Handle the Window Retraction if TCP window scale is enabled according to RFC7323:
  515. // On first retransmission, or if the sequence number is out of
  516. // window by less than 2^Rcv.Wind.Shift, then do normal
  517. // retransmission(s) without regard to the receiver window as long
  518. // as the original segment was in window when it was sent.
  519. //
  520. if ((Tcb->SndWndScale != 0) &&
  521. (TCP_SEQ_GT (Seq, Tcb->RetxmitSeqMax) || TCP_SEQ_BETWEEN (Tcb->SndWl2 + Tcb->SndWnd, Seq, Tcb->SndWl2 + Tcb->SndWnd + (1 << Tcb->SndWndScale))))
  522. {
  523. Len = TCP_SUB_SEQ (Tcb->SndNxt, Seq);
  524. DEBUG (
  525. (DEBUG_WARN,
  526. "TcpRetransmit: retransmission without regard to the receiver window for TCB %p\n",
  527. Tcb)
  528. );
  529. } else if (TCP_SEQ_GEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq)) {
  530. Len = TCP_SUB_SEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq);
  531. } else {
  532. DEBUG (
  533. (DEBUG_WARN,
  534. "TcpRetransmit: retransmission cancelled because send window too small for TCB %p\n",
  535. Tcb)
  536. );
  537. return 0;
  538. }
  539. Len = MIN (Len, Tcb->SndMss);
  540. Nbuf = TcpGetSegmentSndQue (Tcb, Seq, Len);
  541. if (Nbuf == NULL) {
  542. return -1;
  543. }
  544. if (TcpVerifySegment (Nbuf) == 0) {
  545. goto OnError;
  546. }
  547. if (TcpTransmitSegment (Tcb, Nbuf) != 0) {
  548. goto OnError;
  549. }
  550. if (TCP_SEQ_GT (Seq, Tcb->RetxmitSeqMax)) {
  551. Tcb->RetxmitSeqMax = Seq;
  552. }
  553. //
  554. // The retransmitted buffer may be on the SndQue,
  555. // trim TCP head because all the buffers on SndQue
  556. // are headless.
  557. //
  558. ASSERT (Nbuf->Tcp != NULL);
  559. NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD);
  560. Nbuf->Tcp = NULL;
  561. NetbufFree (Nbuf);
  562. return 0;
  563. OnError:
  564. if (Nbuf != NULL) {
  565. NetbufFree (Nbuf);
  566. }
  567. return -1;
  568. }
  569. /**
  570. Verify that all the segments in SndQue are in good shape.
  571. @param[in] Head Pointer to the head node of the SndQue.
  572. @retval 0 At least one segment is broken.
  573. @retval 1 All segments in the specific queue are in good shape.
  574. **/
  575. INTN
  576. TcpCheckSndQue (
  577. IN LIST_ENTRY *Head
  578. )
  579. {
  580. LIST_ENTRY *Entry;
  581. NET_BUF *Nbuf;
  582. TCP_SEQNO Seq;
  583. if (IsListEmpty (Head)) {
  584. return 1;
  585. }
  586. //
  587. // Initialize the Seq.
  588. //
  589. Entry = Head->ForwardLink;
  590. Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
  591. Seq = TCPSEG_NETBUF (Nbuf)->Seq;
  592. NET_LIST_FOR_EACH (Entry, Head) {
  593. Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
  594. if (TcpVerifySegment (Nbuf) == 0) {
  595. return 0;
  596. }
  597. //
  598. // All the node in the SndQue should has:
  599. // SEG.SEQ = LAST_SEG.END
  600. //
  601. if (Seq != TCPSEG_NETBUF (Nbuf)->Seq) {
  602. return 0;
  603. }
  604. Seq = TCPSEG_NETBUF (Nbuf)->End;
  605. }
  606. return 1;
  607. }
  608. /**
  609. Check whether to send data/SYN/FIN and piggyback an ACK.
  610. @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
  611. @param[in] Force If TRUE, ignore the sender's SWS avoidance algorithm
  612. and send out data by force.
  613. @return The number of bytes sent.
  614. **/
  615. INTN
  616. TcpToSendData (
  617. IN OUT TCP_CB *Tcb,
  618. IN INTN Force
  619. )
  620. {
  621. UINT32 Len;
  622. INTN Sent;
  623. UINT8 Flag;
  624. NET_BUF *Nbuf;
  625. TCP_SEG *Seg;
  626. TCP_SEQNO Seq;
  627. TCP_SEQNO End;
  628. ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL) && (Tcb->State != TCP_LISTEN));
  629. Sent = 0;
  630. if ((Tcb->State == TCP_CLOSED) || TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT)) {
  631. return 0;
  632. }
  633. do {
  634. //
  635. // Compute how much data can be sent
  636. //
  637. Len = TcpDataToSend (Tcb, Force);
  638. Seq = Tcb->SndNxt;
  639. ASSERT ((Tcb->State) < (ARRAY_SIZE (mTcpOutFlag)));
  640. Flag = mTcpOutFlag[Tcb->State];
  641. if ((Flag & TCP_FLG_SYN) != 0) {
  642. Seq = Tcb->Iss;
  643. Len = 0;
  644. }
  645. //
  646. // Only send a segment without data if SYN or
  647. // FIN is set.
  648. //
  649. if ((Len == 0) && ((Flag & (TCP_FLG_SYN | TCP_FLG_FIN)) == 0)) {
  650. return Sent;
  651. }
  652. Nbuf = TcpGetSegment (Tcb, Seq, Len);
  653. if (Nbuf == NULL) {
  654. DEBUG (
  655. (DEBUG_ERROR,
  656. "TcpToSendData: failed to get a segment for TCB %p\n",
  657. Tcb)
  658. );
  659. goto OnError;
  660. }
  661. Seg = TCPSEG_NETBUF (Nbuf);
  662. //
  663. // Set the TcpSeg in Nbuf.
  664. //
  665. Len = Nbuf->TotalSize;
  666. End = Seq + Len;
  667. if (TCP_FLG_ON (Flag, TCP_FLG_SYN)) {
  668. End++;
  669. }
  670. if ((Flag & TCP_FLG_FIN) != 0) {
  671. //
  672. // Send FIN if all data is sent, and FIN is
  673. // in the window
  674. //
  675. if ((TcpGetMaxSndNxt (Tcb) == Tcb->SndNxt) &&
  676. (GET_SND_DATASIZE (Tcb->Sk) == 0) &&
  677. TCP_SEQ_LT (End + 1, Tcb->SndWnd + Tcb->SndWl2)
  678. )
  679. {
  680. DEBUG (
  681. (DEBUG_NET,
  682. "TcpToSendData: send FIN to peer for TCB %p in state %s\n",
  683. Tcb,
  684. mTcpStateName[Tcb->State])
  685. );
  686. End++;
  687. } else {
  688. TCP_CLEAR_FLG (Flag, TCP_FLG_FIN);
  689. }
  690. }
  691. Seg->Seq = Seq;
  692. Seg->End = End;
  693. Seg->Flag = Flag;
  694. if ((TcpVerifySegment (Nbuf) == 0) || (TcpCheckSndQue (&Tcb->SndQue) == 0)) {
  695. DEBUG (
  696. (DEBUG_ERROR,
  697. "TcpToSendData: discard a broken segment for TCB %p\n",
  698. Tcb)
  699. );
  700. goto OnError;
  701. }
  702. //
  703. // Don't send an empty segment here.
  704. //
  705. if (Seg->End == Seg->Seq) {
  706. DEBUG (
  707. (DEBUG_WARN,
  708. "TcpToSendData: created a empty segment for TCB %p, free it now\n",
  709. Tcb)
  710. );
  711. goto OnError;
  712. }
  713. if (TcpTransmitSegment (Tcb, Nbuf) != 0) {
  714. NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD);
  715. Nbuf->Tcp = NULL;
  716. if ((Flag & TCP_FLG_FIN) != 0) {
  717. TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT);
  718. }
  719. goto OnError;
  720. }
  721. Sent += TCP_SUB_SEQ (End, Seq);
  722. //
  723. // All the buffers in the SndQue are headless.
  724. //
  725. ASSERT (Nbuf->Tcp != NULL);
  726. NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD);
  727. Nbuf->Tcp = NULL;
  728. NetbufFree (Nbuf);
  729. //
  730. // Update the status in TCB.
  731. //
  732. Tcb->DelayedAck = 0;
  733. if ((Flag & TCP_FLG_FIN) != 0) {
  734. TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT);
  735. }
  736. if (TCP_SEQ_GT (End, Tcb->SndNxt)) {
  737. Tcb->SndNxt = End;
  738. }
  739. if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_REXMIT)) {
  740. TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto);
  741. }
  742. //
  743. // Enable RTT measurement only if not in retransmit.
  744. // Karn's algorithm requires not to update RTT when in loss.
  745. //
  746. if ((Tcb->CongestState == TCP_CONGEST_OPEN) && !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {
  747. DEBUG (
  748. (DEBUG_NET,
  749. "TcpToSendData: set RTT measure sequence %d for TCB %p\n",
  750. Seq,
  751. Tcb)
  752. );
  753. TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
  754. Tcb->RttSeq = Seq;
  755. Tcb->RttMeasure = 0;
  756. }
  757. } while (Len == Tcb->SndMss);
  758. return Sent;
  759. OnError:
  760. if (Nbuf != NULL) {
  761. NetbufFree (Nbuf);
  762. }
  763. return Sent;
  764. }
  765. /**
  766. Send an ACK immediately.
  767. @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
  768. **/
  769. VOID
  770. TcpSendAck (
  771. IN OUT TCP_CB *Tcb
  772. )
  773. {
  774. NET_BUF *Nbuf;
  775. TCP_SEG *Seg;
  776. Nbuf = NetbufAlloc (TCP_MAX_HEAD);
  777. if (Nbuf == NULL) {
  778. return;
  779. }
  780. NetbufReserve (Nbuf, TCP_MAX_HEAD);
  781. Seg = TCPSEG_NETBUF (Nbuf);
  782. Seg->Seq = Tcb->SndNxt;
  783. Seg->End = Tcb->SndNxt;
  784. Seg->Flag = TCP_FLG_ACK;
  785. if (TcpTransmitSegment (Tcb, Nbuf) == 0) {
  786. TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
  787. Tcb->DelayedAck = 0;
  788. }
  789. NetbufFree (Nbuf);
  790. }
  791. /**
  792. Send a zero probe segment. It can be used by keepalive and zero window probe.
  793. @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
  794. @retval 0 The zero probe segment was sent out successfully.
  795. @retval other An error condition occurred.
  796. **/
  797. INTN
  798. TcpSendZeroProbe (
  799. IN OUT TCP_CB *Tcb
  800. )
  801. {
  802. NET_BUF *Nbuf;
  803. TCP_SEG *Seg;
  804. INTN Result;
  805. Nbuf = NetbufAlloc (TCP_MAX_HEAD);
  806. if (Nbuf == NULL) {
  807. return -1;
  808. }
  809. NetbufReserve (Nbuf, TCP_MAX_HEAD);
  810. //
  811. // SndNxt-1 is out of window. The peer should respond
  812. // with an ACK.
  813. //
  814. Seg = TCPSEG_NETBUF (Nbuf);
  815. Seg->Seq = Tcb->SndNxt - 1;
  816. Seg->End = Tcb->SndNxt - 1;
  817. Seg->Flag = TCP_FLG_ACK;
  818. Result = TcpTransmitSegment (Tcb, Nbuf);
  819. NetbufFree (Nbuf);
  820. return Result;
  821. }
  822. /**
  823. Check whether to send an ACK or delayed ACK.
  824. @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
  825. **/
  826. VOID
  827. TcpToSendAck (
  828. IN OUT TCP_CB *Tcb
  829. )
  830. {
  831. UINT32 TcpNow;
  832. //
  833. // Generally, TCP should send a delayed ACK unless:
  834. // 1. ACK at least every other FULL sized segment received.
  835. // 2. Packets received out of order.
  836. // 3. Receiving window is open.
  837. //
  838. if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW) || (Tcb->DelayedAck >= 1)) {
  839. TcpSendAck (Tcb);
  840. return;
  841. }
  842. TcpNow = TcpRcvWinNow (Tcb);
  843. if (TcpNow > TcpRcvWinOld (Tcb)) {
  844. TcpSendAck (Tcb);
  845. return;
  846. }
  847. DEBUG (
  848. (DEBUG_NET,
  849. "TcpToSendAck: scheduled a delayed ACK for TCB %p\n",
  850. Tcb)
  851. );
  852. //
  853. // Schedule a delayed ACK.
  854. //
  855. Tcb->DelayedAck++;
  856. }
  857. /**
  858. Send a RESET segment in response to the segment received.
  859. @param[in] Tcb Pointer to the TCP_CB of this TCP instance. May be NULL.
  860. @param[in] Head TCP header of the segment that triggers the reset.
  861. @param[in] Len Length of the segment that triggers the reset.
  862. @param[in] Local Local IP address.
  863. @param[in] Remote Remote peer's IP address.
  864. @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
  865. IP_VERSION_6 indicates TCP is running on IP6 stack.
  866. @retval 0 A reset was sent or there is no need to send it.
  867. @retval -1 No reset is sent.
  868. **/
  869. INTN
  870. TcpSendReset (
  871. IN TCP_CB *Tcb,
  872. IN TCP_HEAD *Head,
  873. IN INT32 Len,
  874. IN EFI_IP_ADDRESS *Local,
  875. IN EFI_IP_ADDRESS *Remote,
  876. IN UINT8 Version
  877. )
  878. {
  879. NET_BUF *Nbuf;
  880. TCP_HEAD *Nhead;
  881. UINT16 HeadSum;
  882. //
  883. // Don't respond to a Reset with reset.
  884. //
  885. if ((Head->Flag & TCP_FLG_RST) != 0) {
  886. return 0;
  887. }
  888. Nbuf = NetbufAlloc (TCP_MAX_HEAD);
  889. if (Nbuf == NULL) {
  890. return -1;
  891. }
  892. Nhead = (TCP_HEAD *)NetbufAllocSpace (
  893. Nbuf,
  894. sizeof (TCP_HEAD),
  895. NET_BUF_TAIL
  896. );
  897. ASSERT (Nhead != NULL);
  898. Nbuf->Tcp = Nhead;
  899. Nhead->Flag = TCP_FLG_RST;
  900. //
  901. // Derive Seq/ACK from the segment if no TCB
  902. // is associated with it, otherwise derive from the Tcb.
  903. //
  904. if (Tcb == NULL) {
  905. if (TCP_FLG_ON (Head->Flag, TCP_FLG_ACK)) {
  906. Nhead->Seq = Head->Ack;
  907. Nhead->Ack = 0;
  908. } else {
  909. Nhead->Seq = 0;
  910. TCP_SET_FLG (Nhead->Flag, TCP_FLG_ACK);
  911. Nhead->Ack = HTONL (NTOHL (Head->Seq) + Len);
  912. }
  913. } else {
  914. Nhead->Seq = HTONL (Tcb->SndNxt);
  915. Nhead->Ack = HTONL (Tcb->RcvNxt);
  916. TCP_SET_FLG (Nhead->Flag, TCP_FLG_ACK);
  917. }
  918. Nhead->SrcPort = Head->DstPort;
  919. Nhead->DstPort = Head->SrcPort;
  920. Nhead->HeadLen = (UINT8)(sizeof (TCP_HEAD) >> 2);
  921. Nhead->Res = 0;
  922. Nhead->Wnd = HTONS (0xFFFF);
  923. Nhead->Checksum = 0;
  924. Nhead->Urg = 0;
  925. if (Version == IP_VERSION_4) {
  926. HeadSum = NetPseudoHeadChecksum (Local->Addr[0], Remote->Addr[0], 6, 0);
  927. } else {
  928. HeadSum = NetIp6PseudoHeadChecksum (&Local->v6, &Remote->v6, 6, 0);
  929. }
  930. Nhead->Checksum = TcpChecksum (Nbuf, HeadSum);
  931. TcpSendIpPacket (Tcb, Nbuf, Local, Remote, Version);
  932. NetbufFree (Nbuf);
  933. return 0;
  934. }
  935. /**
  936. Verify that the segment is in good shape.
  937. @param[in] Nbuf The buffer that contains the segment to be checked.
  938. @retval 0 The segment is broken.
  939. @retval 1 The segment is in good shape.
  940. **/
  941. INTN
  942. TcpVerifySegment (
  943. IN NET_BUF *Nbuf
  944. )
  945. {
  946. TCP_HEAD *Head;
  947. TCP_SEG *Seg;
  948. UINT32 Len;
  949. if (Nbuf == NULL) {
  950. return 1;
  951. }
  952. NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
  953. Seg = TCPSEG_NETBUF (Nbuf);
  954. Len = Nbuf->TotalSize;
  955. Head = Nbuf->Tcp;
  956. if (Head != NULL) {
  957. if (Head->Flag != Seg->Flag) {
  958. return 0;
  959. }
  960. Len -= (Head->HeadLen << 2);
  961. }
  962. if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
  963. Len++;
  964. }
  965. if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {
  966. Len++;
  967. }
  968. if (Seg->Seq + Len != Seg->End) {
  969. return 0;
  970. }
  971. return 1;
  972. }