]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeNetLib/NetBuffer.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Library / DxeNetLib / NetBuffer.c
CommitLineData
cbf316f2 1/** @file\r
32cf7c73 2 Network library functions providing net buffer operation support.\r
1204fe83 3\r
d1102dba 4Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 5This program and the accompanying materials\r
cbf316f2 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
cbf316f2 12**/\r
13\r
3e7104c2 14#include <Uefi.h>\r
f5acf5c6 15\r
16#include <Library/NetLib.h>\r
17#include <Library/BaseLib.h>\r
18#include <Library/DebugLib.h>\r
19#include <Library/BaseMemoryLib.h>\r
20#include <Library/UefiBootServicesTableLib.h>\r
cbf316f2 21#include <Library/MemoryAllocationLib.h>\r
22\r
23\r
24/**\r
1204fe83 25 Allocate and build up the sketch for a NET_BUF.\r
26\r
27 The net buffer allocated has the BlockOpNum's NET_BLOCK_OP, and its associated\r
32cf7c73 28 NET_VECTOR has the BlockNum's NET_BLOCK. But all the NET_BLOCK_OP and\r
29 NET_BLOCK remain un-initialized.\r
cbf316f2 30\r
32cf7c73 31 @param[in] BlockNum The number of NET_BLOCK in the vector of net buffer\r
32 @param[in] BlockOpNum The number of NET_BLOCK_OP in the net buffer\r
cbf316f2 33\r
1204fe83 34 @return Pointer to the allocated NET_BUF, or NULL if the\r
32cf7c73 35 allocation failed due to resource limit.\r
cbf316f2 36\r
37**/\r
cbf316f2 38NET_BUF *\r
39NetbufAllocStruct (\r
40 IN UINT32 BlockNum,\r
41 IN UINT32 BlockOpNum\r
42 )\r
43{\r
44 NET_BUF *Nbuf;\r
45 NET_VECTOR *Vector;\r
46\r
47 ASSERT (BlockOpNum >= 1);\r
48\r
49 //\r
50 // Allocate three memory blocks.\r
51 //\r
e48e37fc 52 Nbuf = AllocateZeroPool (NET_BUF_SIZE (BlockOpNum));\r
cbf316f2 53\r
54 if (Nbuf == NULL) {\r
55 return NULL;\r
56 }\r
57\r
58 Nbuf->Signature = NET_BUF_SIGNATURE;\r
59 Nbuf->RefCnt = 1;\r
60 Nbuf->BlockOpNum = BlockOpNum;\r
e48e37fc 61 InitializeListHead (&Nbuf->List);\r
cbf316f2 62\r
63 if (BlockNum != 0) {\r
e48e37fc 64 Vector = AllocateZeroPool (NET_VECTOR_SIZE (BlockNum));\r
cbf316f2 65\r
66 if (Vector == NULL) {\r
67 goto FreeNbuf;\r
68 }\r
69\r
70 Vector->Signature = NET_VECTOR_SIGNATURE;\r
71 Vector->RefCnt = 1;\r
72 Vector->BlockNum = BlockNum;\r
73 Nbuf->Vector = Vector;\r
74 }\r
75\r
76 return Nbuf;\r
77\r
78FreeNbuf:\r
79\r
7b0ae7e8 80 FreePool (Nbuf);\r
cbf316f2 81 return NULL;\r
82}\r
83\r
84\r
85/**\r
86 Allocate a single block NET_BUF. Upon allocation, all the\r
87 free space is in the tail room.\r
88\r
3e7104c2 89 @param[in] Len The length of the block.\r
cbf316f2 90\r
1204fe83 91 @return Pointer to the allocated NET_BUF, or NULL if the\r
32cf7c73 92 allocation failed due to resource limit.\r
cbf316f2 93\r
94**/\r
95NET_BUF *\r
7b414b4e 96EFIAPI\r
cbf316f2 97NetbufAlloc (\r
98 IN UINT32 Len\r
99 )\r
100{\r
101 NET_BUF *Nbuf;\r
102 NET_VECTOR *Vector;\r
103 UINT8 *Bulk;\r
104\r
105 ASSERT (Len > 0);\r
106\r
107 Nbuf = NetbufAllocStruct (1, 1);\r
108\r
109 if (Nbuf == NULL) {\r
110 return NULL;\r
111 }\r
112\r
e48e37fc 113 Bulk = AllocatePool (Len);\r
cbf316f2 114\r
115 if (Bulk == NULL) {\r
116 goto FreeNBuf;\r
117 }\r
118\r
119 Vector = Nbuf->Vector;\r
120 Vector->Len = Len;\r
121\r
122 Vector->Block[0].Bulk = Bulk;\r
123 Vector->Block[0].Len = Len;\r
124\r
125 Nbuf->BlockOp[0].BlockHead = Bulk;\r
126 Nbuf->BlockOp[0].BlockTail = Bulk + Len;\r
127\r
128 Nbuf->BlockOp[0].Head = Bulk;\r
129 Nbuf->BlockOp[0].Tail = Bulk;\r
130 Nbuf->BlockOp[0].Size = 0;\r
131\r
132 return Nbuf;\r
133\r
134FreeNBuf:\r
7b0ae7e8 135 FreePool (Nbuf);\r
cbf316f2 136 return NULL;\r
137}\r
138\r
cbf316f2 139/**\r
1204fe83 140 Free the net vector.\r
141\r
142 Decrease the reference count of the net vector by one. The real resource free\r
143 operation isn't performed until the reference count of the net vector is\r
144 decreased to 0.\r
cbf316f2 145\r
3e7104c2 146 @param[in] Vector Pointer to the NET_VECTOR to be freed.\r
cbf316f2 147\r
148**/\r
cbf316f2 149VOID\r
150NetbufFreeVector (\r
151 IN NET_VECTOR *Vector\r
152 )\r
153{\r
154 UINT32 Index;\r
155\r
7b0ae7e8 156 ASSERT (Vector != NULL);\r
cbf316f2 157 NET_CHECK_SIGNATURE (Vector, NET_VECTOR_SIGNATURE);\r
158 ASSERT (Vector->RefCnt > 0);\r
159\r
160 Vector->RefCnt--;\r
161\r
162 if (Vector->RefCnt > 0) {\r
163 return;\r
164 }\r
165\r
166 if (Vector->Free != NULL) {\r
167 //\r
168 // Call external free function to free the vector if it\r
169 // isn't NULL. If NET_VECTOR_OWN_FIRST is set, release the\r
170 // first block since it is allocated by us\r
171 //\r
8de75da2 172 if ((Vector->Flag & NET_VECTOR_OWN_FIRST) != 0) {\r
e48e37fc 173 gBS->FreePool (Vector->Block[0].Bulk);\r
cbf316f2 174 }\r
175\r
176 Vector->Free (Vector->Arg);\r
177\r
178 } else {\r
179 //\r
180 // Free each memory block associated with the Vector\r
181 //\r
182 for (Index = 0; Index < Vector->BlockNum; Index++) {\r
e48e37fc 183 gBS->FreePool (Vector->Block[Index].Bulk);\r
cbf316f2 184 }\r
185 }\r
186\r
7b0ae7e8 187 FreePool (Vector);\r
cbf316f2 188}\r
189\r
190\r
191/**\r
32cf7c73 192 Free the net buffer and its associated NET_VECTOR.\r
1204fe83 193\r
9bc4edf2 194 Decrease the reference count of the net buffer by one. Free the associated net\r
1204fe83 195 vector and itself if the reference count of the net buffer is decreased to 0.\r
196 The net vector free operation just decrease the reference count of the net\r
9bc4edf2 197 vector by one and do the real resource free operation when the reference count\r
1204fe83 198 of the net vector is 0.\r
199\r
3e7104c2 200 @param[in] Nbuf Pointer to the NET_BUF to be freed.\r
cbf316f2 201\r
202**/\r
203VOID\r
7b414b4e 204EFIAPI\r
cbf316f2 205NetbufFree (\r
206 IN NET_BUF *Nbuf\r
207 )\r
208{\r
7b0ae7e8 209 ASSERT (Nbuf != NULL);\r
cbf316f2 210 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
211 ASSERT (Nbuf->RefCnt > 0);\r
212\r
213 Nbuf->RefCnt--;\r
214\r
215 if (Nbuf->RefCnt == 0) {\r
216 //\r
217 // Update Vector only when NBuf is to be released. That is,\r
218 // all the sharing of Nbuf increse Vector's RefCnt by one\r
219 //\r
220 NetbufFreeVector (Nbuf->Vector);\r
7b0ae7e8 221 FreePool (Nbuf);\r
cbf316f2 222 }\r
223}\r
224\r
225\r
226/**\r
1204fe83 227 Create a copy of the net buffer that shares the associated net vector.\r
228\r
229 The reference count of the newly created net buffer is set to 1. The reference\r
230 count of the associated net vector is increased by one.\r
cbf316f2 231\r
3e7104c2 232 @param[in] Nbuf Pointer to the net buffer to be cloned.\r
cbf316f2 233\r
32cf7c73 234 @return Pointer to the cloned net buffer, or NULL if the\r
3e7104c2 235 allocation failed due to resource limit.\r
cbf316f2 236\r
237**/\r
32cf7c73 238NET_BUF *\r
7b414b4e 239EFIAPI\r
cbf316f2 240NetbufClone (\r
241 IN NET_BUF *Nbuf\r
242 )\r
243{\r
244 NET_BUF *Clone;\r
245\r
246 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
247\r
e48e37fc 248 Clone = AllocatePool (NET_BUF_SIZE (Nbuf->BlockOpNum));\r
cbf316f2 249\r
250 if (Clone == NULL) {\r
251 return NULL;\r
252 }\r
253\r
254 Clone->Signature = NET_BUF_SIGNATURE;\r
255 Clone->RefCnt = 1;\r
e48e37fc 256 InitializeListHead (&Clone->List);\r
cbf316f2 257\r
258 Clone->Ip = Nbuf->Ip;\r
259 Clone->Tcp = Nbuf->Tcp;\r
260\r
e48e37fc 261 CopyMem (Clone->ProtoData, Nbuf->ProtoData, NET_PROTO_DATA);\r
cbf316f2 262\r
263 NET_GET_REF (Nbuf->Vector);\r
264\r
265 Clone->Vector = Nbuf->Vector;\r
266 Clone->BlockOpNum = Nbuf->BlockOpNum;\r
267 Clone->TotalSize = Nbuf->TotalSize;\r
e48e37fc 268 CopyMem (Clone->BlockOp, Nbuf->BlockOp, sizeof (NET_BLOCK_OP) * Nbuf->BlockOpNum);\r
cbf316f2 269\r
270 return Clone;\r
271}\r
272\r
273\r
274/**\r
32cf7c73 275 Create a duplicated copy of the net buffer with data copied and HeadSpace\r
276 bytes of head space reserved.\r
1204fe83 277\r
32cf7c73 278 The duplicated net buffer will allocate its own memory to hold the data of the\r
279 source net buffer.\r
1204fe83 280\r
32cf7c73 281 @param[in] Nbuf Pointer to the net buffer to be duplicated from.\r
1204fe83 282 @param[in, out] Duplicate Pointer to the net buffer to duplicate to, if\r
32cf7c73 283 NULL a new net buffer is allocated.\r
284 @param[in] HeadSpace Length of the head space to reserve.\r
285\r
286 @return Pointer to the duplicated net buffer, or NULL if\r
287 the allocation failed due to resource limit.\r
cbf316f2 288\r
289**/\r
290NET_BUF *\r
7b414b4e 291EFIAPI\r
cbf316f2 292NetbufDuplicate (\r
293 IN NET_BUF *Nbuf,\r
3e7104c2 294 IN OUT NET_BUF *Duplicate OPTIONAL,\r
cbf316f2 295 IN UINT32 HeadSpace\r
296 )\r
297{\r
298 UINT8 *Dst;\r
299\r
300 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
301\r
302 if (Duplicate == NULL) {\r
303 Duplicate = NetbufAlloc (Nbuf->TotalSize + HeadSpace);\r
304 }\r
305\r
306 if (Duplicate == NULL) {\r
307 return NULL;\r
308 }\r
309\r
310 //\r
311 // Don't set the IP and TCP head point, since it is most\r
312 // like that they are pointing to the memory of Nbuf.\r
313 //\r
e48e37fc 314 CopyMem (Duplicate->ProtoData, Nbuf->ProtoData, NET_PROTO_DATA);\r
cbf316f2 315 NetbufReserve (Duplicate, HeadSpace);\r
316\r
317 Dst = NetbufAllocSpace (Duplicate, Nbuf->TotalSize, NET_BUF_TAIL);\r
318 NetbufCopy (Nbuf, 0, Nbuf->TotalSize, Dst);\r
319\r
320 return Duplicate;\r
321}\r
322\r
323\r
324/**\r
325 Free a list of net buffers.\r
326\r
3e7104c2 327 @param[in, out] Head Pointer to the head of linked net buffers.\r
9bc4edf2 328\r
cbf316f2 329**/\r
330VOID\r
7b414b4e 331EFIAPI\r
cbf316f2 332NetbufFreeList (\r
3e7104c2 333 IN OUT LIST_ENTRY *Head\r
cbf316f2 334 )\r
335{\r
e48e37fc 336 LIST_ENTRY *Entry;\r
337 LIST_ENTRY *Next;\r
cbf316f2 338 NET_BUF *Nbuf;\r
339\r
340 Entry = Head->ForwardLink;\r
341\r
342 NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {\r
343 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);\r
344 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
345\r
e48e37fc 346 RemoveEntryList (Entry);\r
cbf316f2 347 NetbufFree (Nbuf);\r
348 }\r
349\r
e48e37fc 350 ASSERT (IsListEmpty (Head));\r
cbf316f2 351}\r
352\r
353\r
354/**\r
1204fe83 355 Get the index of NET_BLOCK_OP that contains the byte at Offset in the net\r
356 buffer.\r
357\r
358 This can be used to, for example, retrieve the IP header in the packet. It\r
359 also can be used to get the fragment that contains the byte which is used\r
360 mainly by the library implementation itself.\r
cbf316f2 361\r
32cf7c73 362 @param[in] Nbuf Pointer to the net buffer.\r
363 @param[in] Offset The offset of the byte.\r
1204fe83 364 @param[out] Index Index of the NET_BLOCK_OP that contains the byte at\r
32cf7c73 365 Offset.\r
cbf316f2 366\r
9bc4edf2 367 @return Pointer to the Offset'th byte of data in the net buffer, or NULL\r
368 if there is no such data in the net buffer.\r
cbf316f2 369\r
370**/\r
371UINT8 *\r
7b414b4e 372EFIAPI\r
cbf316f2 373NetbufGetByte (\r
374 IN NET_BUF *Nbuf,\r
375 IN UINT32 Offset,\r
376 OUT UINT32 *Index OPTIONAL\r
377 )\r
378{\r
379 NET_BLOCK_OP *BlockOp;\r
380 UINT32 Loop;\r
381 UINT32 Len;\r
382\r
383 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
384\r
385 if (Offset >= Nbuf->TotalSize) {\r
386 return NULL;\r
387 }\r
388\r
389 BlockOp = Nbuf->BlockOp;\r
390 Len = 0;\r
391\r
392 for (Loop = 0; Loop < Nbuf->BlockOpNum; Loop++) {\r
393\r
394 if (Len + BlockOp[Loop].Size <= Offset) {\r
395 Len += BlockOp[Loop].Size;\r
396 continue;\r
397 }\r
398\r
399 if (Index != NULL) {\r
400 *Index = Loop;\r
401 }\r
402\r
403 return BlockOp[Loop].Head + (Offset - Len);\r
404 }\r
405\r
406 return NULL;\r
407}\r
408\r
409\r
410\r
411/**\r
1204fe83 412 Set the NET_BLOCK and corresponding NET_BLOCK_OP in the net buffer and\r
32cf7c73 413 corresponding net vector according to the bulk pointer and bulk length.\r
1204fe83 414\r
415 All the pointers in the Index'th NET_BLOCK and NET_BLOCK_OP are set to the\r
416 bulk's head and tail respectively. So, this function alone can't be used by\r
417 NetbufAlloc.\r
32cf7c73 418\r
419 @param[in, out] Nbuf Pointer to the net buffer.\r
420 @param[in] Bulk Pointer to the data.\r
421 @param[in] Len Length of the bulk data.\r
422 @param[in] Index The data block index in the net buffer the bulk\r
423 data should belong to.\r
424\r
cbf316f2 425**/\r
cbf316f2 426VOID\r
427NetbufSetBlock (\r
3e7104c2 428 IN OUT NET_BUF *Nbuf,\r
cbf316f2 429 IN UINT8 *Bulk,\r
430 IN UINT32 Len,\r
431 IN UINT32 Index\r
432 )\r
433{\r
434 NET_BLOCK_OP *BlockOp;\r
435 NET_BLOCK *Block;\r
436\r
437 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
438 NET_CHECK_SIGNATURE (Nbuf->Vector, NET_VECTOR_SIGNATURE);\r
439 ASSERT (Index < Nbuf->BlockOpNum);\r
440\r
441 Block = &(Nbuf->Vector->Block[Index]);\r
442 BlockOp = &(Nbuf->BlockOp[Index]);\r
443 Block->Len = Len;\r
444 Block->Bulk = Bulk;\r
445 BlockOp->BlockHead = Bulk;\r
446 BlockOp->BlockTail = Bulk + Len;\r
447 BlockOp->Head = Bulk;\r
448 BlockOp->Tail = Bulk + Len;\r
449 BlockOp->Size = Len;\r
450}\r
451\r
452\r
453\r
454/**\r
32cf7c73 455 Set the NET_BLOCK_OP in the net buffer. The corresponding NET_BLOCK\r
1204fe83 456 structure is left untouched.\r
457\r
458 Some times, there is no 1:1 relationship between NET_BLOCK and NET_BLOCK_OP.\r
459 For example, that in NetbufGetFragment.\r
32cf7c73 460\r
461 @param[in, out] Nbuf Pointer to the net buffer.\r
462 @param[in] Bulk Pointer to the data.\r
463 @param[in] Len Length of the bulk data.\r
1204fe83 464 @param[in] Index The data block index in the net buffer the bulk\r
32cf7c73 465 data should belong to.\r
cbf316f2 466\r
467**/\r
cbf316f2 468VOID\r
469NetbufSetBlockOp (\r
3e7104c2 470 IN OUT NET_BUF *Nbuf,\r
cbf316f2 471 IN UINT8 *Bulk,\r
472 IN UINT32 Len,\r
473 IN UINT32 Index\r
474 )\r
475{\r
476 NET_BLOCK_OP *BlockOp;\r
477\r
478 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
479 ASSERT (Index < Nbuf->BlockOpNum);\r
480\r
481 BlockOp = &(Nbuf->BlockOp[Index]);\r
482 BlockOp->BlockHead = Bulk;\r
483 BlockOp->BlockTail = Bulk + Len;\r
484 BlockOp->Head = Bulk;\r
485 BlockOp->Tail = Bulk + Len;\r
486 BlockOp->Size = Len;\r
487}\r
488\r
489\r
490/**\r
1204fe83 491 Helper function for NetbufGetFragment. NetbufGetFragment may allocate the\r
492 first block to reserve HeadSpace bytes header space. So it needs to create a\r
493 new net vector for the first block and can avoid copy for the remaining data\r
494 by sharing the old net vector.\r
cbf316f2 495\r
3e7104c2 496 @param[in] Arg Point to the old NET_VECTOR.\r
9bc4edf2 497\r
cbf316f2 498**/\r
cbf316f2 499VOID\r
e798cd87 500EFIAPI\r
cbf316f2 501NetbufGetFragmentFree (\r
502 IN VOID *Arg\r
503 )\r
504{\r
505 NET_VECTOR *Vector;\r
506\r
507 Vector = (NET_VECTOR *)Arg;\r
508 NetbufFreeVector (Vector);\r
509}\r
510\r
511\r
cbf316f2 512/**\r
1204fe83 513 Create a NET_BUF structure which contains Len byte data of Nbuf starting from\r
514 Offset.\r
515\r
516 A new NET_BUF structure will be created but the associated data in NET_VECTOR\r
517 is shared. This function exists to do IP packet fragmentation.\r
32cf7c73 518\r
519 @param[in] Nbuf Pointer to the net buffer to be extracted.\r
1204fe83 520 @param[in] Offset Starting point of the data to be included in the new\r
32cf7c73 521 net buffer.\r
1204fe83 522 @param[in] Len Bytes of data to be included in the new net buffer.\r
523 @param[in] HeadSpace Bytes of head space to reserve for protocol header.\r
32cf7c73 524\r
1204fe83 525 @return Pointer to the cloned net buffer, or NULL if the\r
9bc4edf2 526 allocation failed due to resource limit.\r
cbf316f2 527\r
528**/\r
529NET_BUF *\r
7b414b4e 530EFIAPI\r
cbf316f2 531NetbufGetFragment (\r
532 IN NET_BUF *Nbuf,\r
533 IN UINT32 Offset,\r
534 IN UINT32 Len,\r
535 IN UINT32 HeadSpace\r
536 )\r
537{\r
538 NET_BUF *Child;\r
539 NET_VECTOR *Vector;\r
540 NET_BLOCK_OP *BlockOp;\r
541 UINT32 CurBlockOp;\r
542 UINT32 BlockOpNum;\r
543 UINT8 *FirstBulk;\r
544 UINT32 Index;\r
545 UINT32 First;\r
546 UINT32 Last;\r
547 UINT32 FirstSkip;\r
548 UINT32 FirstLen;\r
549 UINT32 LastLen;\r
550 UINT32 Cur;\r
551\r
552 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
553\r
554 if ((Len == 0) || (Offset + Len > Nbuf->TotalSize)) {\r
555 return NULL;\r
556 }\r
557\r
558 //\r
559 // First find the first and last BlockOp that contains\r
560 // the valid data, and compute the offset of the first\r
561 // BlockOp and length of the last BlockOp\r
562 //\r
563 BlockOp = Nbuf->BlockOp;\r
564 Cur = 0;\r
565\r
566 for (Index = 0; Index < Nbuf->BlockOpNum; Index++) {\r
567 if (Offset < Cur + BlockOp[Index].Size) {\r
568 break;\r
569 }\r
570\r
571 Cur += BlockOp[Index].Size;\r
572 }\r
573\r
574 //\r
575 // First is the index of the first BlockOp, FirstSkip is\r
576 // the offset of the first byte in the first BlockOp.\r
577 //\r
578 First = Index;\r
579 FirstSkip = Offset - Cur;\r
580 FirstLen = BlockOp[Index].Size - FirstSkip;\r
581\r
cbf316f2 582 Last = 0;\r
583 LastLen = 0;\r
584\r
585 if (Len > FirstLen) {\r
586 Cur += BlockOp[Index].Size;\r
587 Index++;\r
588\r
589 for (; Index < Nbuf->BlockOpNum; Index++) {\r
590 if (Offset + Len <= Cur + BlockOp[Index].Size) {\r
591 Last = Index;\r
592 LastLen = Offset + Len - Cur;\r
593 break;\r
594 }\r
595\r
596 Cur += BlockOp[Index].Size;\r
597 }\r
598\r
599 } else {\r
600 Last = First;\r
601 LastLen = Len;\r
602 FirstLen = Len;\r
603 }\r
604\r
90f1486c 605 ASSERT (Last >= First);\r
cbf316f2 606 BlockOpNum = Last - First + 1;\r
607 CurBlockOp = 0;\r
608\r
609 if (HeadSpace != 0) {\r
610 //\r
611 // Allocate an extra block to accomdate the head space.\r
612 //\r
613 BlockOpNum++;\r
614\r
615 Child = NetbufAllocStruct (1, BlockOpNum);\r
616\r
617 if (Child == NULL) {\r
618 return NULL;\r
619 }\r
620\r
e48e37fc 621 FirstBulk = AllocatePool (HeadSpace);\r
cbf316f2 622\r
623 if (FirstBulk == NULL) {\r
624 goto FreeChild;\r
625 }\r
626\r
627 Vector = Child->Vector;\r
628 Vector->Free = NetbufGetFragmentFree;\r
629 Vector->Arg = Nbuf->Vector;\r
630 Vector->Flag = NET_VECTOR_OWN_FIRST;\r
631 Vector->Len = HeadSpace;\r
632\r
633 //\r
9bc4edf2 634 // Reserve the head space in the first block\r
cbf316f2 635 //\r
636 NetbufSetBlock (Child, FirstBulk, HeadSpace, 0);\r
637 Child->BlockOp[0].Head += HeadSpace;\r
638 Child->BlockOp[0].Size = 0;\r
639 CurBlockOp++;\r
640\r
90f1486c 641 } else {\r
cbf316f2 642 Child = NetbufAllocStruct (0, BlockOpNum);\r
643\r
644 if (Child == NULL) {\r
645 return NULL;\r
646 }\r
647\r
648 Child->Vector = Nbuf->Vector;\r
649 }\r
650\r
651 NET_GET_REF (Nbuf->Vector);\r
652 Child->TotalSize = Len;\r
653\r
654 //\r
655 // Set all the BlockOp up, the first and last one are special\r
656 // and need special process.\r
657 //\r
658 NetbufSetBlockOp (\r
659 Child,\r
660 Nbuf->BlockOp[First].Head + FirstSkip,\r
661 FirstLen,\r
662 CurBlockOp++\r
663 );\r
664\r
90f1486c 665 for (Index = First + 1; Index < Last; Index++) {\r
cbf316f2 666 NetbufSetBlockOp (\r
667 Child,\r
668 BlockOp[Index].Head,\r
669 BlockOp[Index].Size,\r
670 CurBlockOp++\r
671 );\r
672 }\r
673\r
674 if (First != Last) {\r
675 NetbufSetBlockOp (\r
676 Child,\r
677 BlockOp[Last].Head,\r
678 LastLen,\r
679 CurBlockOp\r
680 );\r
681 }\r
682\r
e48e37fc 683 CopyMem (Child->ProtoData, Nbuf->ProtoData, NET_PROTO_DATA);\r
cbf316f2 684 return Child;\r
685\r
686FreeChild:\r
687\r
7b0ae7e8 688 FreePool (Child);\r
cbf316f2 689 return NULL;\r
690}\r
691\r
692\r
693\r
694/**\r
1204fe83 695 Build a NET_BUF from external blocks.\r
696\r
32cf7c73 697 A new NET_BUF structure will be created from external blocks. Additional block\r
698 of memory will be allocated to hold reserved HeadSpace bytes of header room\r
699 and existing HeadLen bytes of header but the external blocks are shared by the\r
700 net buffer to avoid data copying.\r
cbf316f2 701\r
3e7104c2 702 @param[in] ExtFragment Pointer to the data block.\r
32cf7c73 703 @param[in] ExtNum The number of the data blocks.\r
3e7104c2 704 @param[in] HeadSpace The head space to be reserved.\r
705 @param[in] HeadLen The length of the protocol header, This function\r
706 will pull that number of data into a linear block.\r
707 @param[in] ExtFree Pointer to the caller provided free function.\r
708 @param[in] Arg The argument passed to ExtFree when ExtFree is\r
709 called.\r
cbf316f2 710\r
1204fe83 711 @return Pointer to the net buffer built from the data blocks,\r
9bc4edf2 712 or NULL if the allocation failed due to resource\r
713 limit.\r
cbf316f2 714\r
715**/\r
716NET_BUF *\r
7b414b4e 717EFIAPI\r
cbf316f2 718NetbufFromExt (\r
719 IN NET_FRAGMENT *ExtFragment,\r
720 IN UINT32 ExtNum,\r
721 IN UINT32 HeadSpace,\r
722 IN UINT32 HeadLen,\r
723 IN NET_VECTOR_EXT_FREE ExtFree,\r
724 IN VOID *Arg OPTIONAL\r
725 )\r
726{\r
727 NET_BUF *Nbuf;\r
728 NET_VECTOR *Vector;\r
729 NET_FRAGMENT SavedFragment;\r
730 UINT32 SavedIndex;\r
731 UINT32 TotalLen;\r
732 UINT32 BlockNum;\r
733 UINT8 *FirstBlock;\r
734 UINT32 FirstBlockLen;\r
735 UINT8 *Header;\r
736 UINT32 CurBlock;\r
737 UINT32 Index;\r
738 UINT32 Len;\r
739 UINT32 Copied;\r
740\r
741 ASSERT ((ExtFragment != NULL) && (ExtNum > 0) && (ExtFree != NULL));\r
742\r
743 SavedFragment.Bulk = NULL;\r
744 SavedFragment.Len = 0;\r
745\r
746 FirstBlockLen = 0;\r
747 FirstBlock = NULL;\r
748 BlockNum = ExtNum;\r
749 Index = 0;\r
750 TotalLen = 0;\r
751 SavedIndex = 0;\r
752 Len = 0;\r
753 Copied = 0;\r
754\r
755 //\r
756 // No need to consolidate the header if the first block is\r
757 // longer than the header length or there is only one block.\r
758 //\r
759 if ((ExtFragment[0].Len >= HeadLen) || (ExtNum == 1)) {\r
760 HeadLen = 0;\r
761 }\r
762\r
763 //\r
764 // Allocate an extra block if we need to:\r
765 // 1. Allocate some header space\r
766 // 2. aggreate the packet header\r
767 //\r
768 if ((HeadSpace != 0) || (HeadLen != 0)) {\r
769 FirstBlockLen = HeadLen + HeadSpace;\r
e48e37fc 770 FirstBlock = AllocatePool (FirstBlockLen);\r
cbf316f2 771\r
772 if (FirstBlock == NULL) {\r
773 return NULL;\r
774 }\r
775\r
776 BlockNum++;\r
777 }\r
778\r
779 //\r
780 // Copy the header to the first block, reduce the NET_BLOCK\r
781 // to allocate by one for each block that is completely covered\r
782 // by the first bulk.\r
783 //\r
784 if (HeadLen != 0) {\r
785 Len = HeadLen;\r
786 Header = FirstBlock + HeadSpace;\r
787\r
788 for (Index = 0; Index < ExtNum; Index++) {\r
789 if (Len >= ExtFragment[Index].Len) {\r
e48e37fc 790 CopyMem (Header, ExtFragment[Index].Bulk, ExtFragment[Index].Len);\r
cbf316f2 791\r
792 Copied += ExtFragment[Index].Len;\r
793 Len -= ExtFragment[Index].Len;\r
794 Header += ExtFragment[Index].Len;\r
795 TotalLen += ExtFragment[Index].Len;\r
796 BlockNum--;\r
797\r
798 if (Len == 0) {\r
799 //\r
800 // Increament the index number to point to the next\r
801 // non-empty fragment.\r
802 //\r
803 Index++;\r
804 break;\r
805 }\r
806\r
807 } else {\r
e48e37fc 808 CopyMem (Header, ExtFragment[Index].Bulk, Len);\r
cbf316f2 809\r
810 Copied += Len;\r
811 TotalLen += Len;\r
812\r
813 //\r
814 // Adjust the block structure to exclude the data copied,\r
815 // So, the left-over block can be processed as other blocks.\r
816 // But it must be recovered later. (SavedIndex > 0) always\r
817 // holds since we don't aggreate the header if the first block\r
818 // is bigger enough that the header is continuous\r
819 //\r
820 SavedIndex = Index;\r
821 SavedFragment = ExtFragment[Index];\r
822 ExtFragment[Index].Bulk += Len;\r
823 ExtFragment[Index].Len -= Len;\r
824 break;\r
825 }\r
826 }\r
827 }\r
828\r
829 Nbuf = NetbufAllocStruct (BlockNum, BlockNum);\r
830\r
831 if (Nbuf == NULL) {\r
832 goto FreeFirstBlock;\r
833 }\r
834\r
835 Vector = Nbuf->Vector;\r
836 Vector->Free = ExtFree;\r
837 Vector->Arg = Arg;\r
3e7104c2 838 Vector->Flag = ((FirstBlockLen != 0) ? NET_VECTOR_OWN_FIRST : 0);\r
cbf316f2 839\r
840 //\r
841 // Set the first block up which may contain\r
842 // some head space and aggregated header\r
843 //\r
844 CurBlock = 0;\r
845\r
846 if (FirstBlockLen != 0) {\r
847 NetbufSetBlock (Nbuf, FirstBlock, HeadSpace + Copied, 0);\r
848 Nbuf->BlockOp[0].Head += HeadSpace;\r
849 Nbuf->BlockOp[0].Size = Copied;\r
850\r
851 CurBlock++;\r
852 }\r
853\r
854 for (; Index < ExtNum; Index++) {\r
855 NetbufSetBlock (Nbuf, ExtFragment[Index].Bulk, ExtFragment[Index].Len, CurBlock);\r
856 TotalLen += ExtFragment[Index].Len;\r
857 CurBlock++;\r
858 }\r
859\r
860 Vector->Len = TotalLen + HeadSpace;\r
861 Nbuf->TotalSize = TotalLen;\r
862\r
3e7104c2 863 if (SavedIndex != 0) {\r
cbf316f2 864 ExtFragment[SavedIndex] = SavedFragment;\r
865 }\r
866\r
867 return Nbuf;\r
868\r
869FreeFirstBlock:\r
7b0ae7e8 870 if (FirstBlock != NULL) {\r
871 FreePool (FirstBlock);\r
872 }\r
cbf316f2 873 return NULL;\r
874}\r
875\r
876\r
877/**\r
32cf7c73 878 Build a fragment table to contain the fragments in the net buffer. This is the\r
1204fe83 879 opposite operation of the NetbufFromExt.\r
880\r
3e7104c2 881 @param[in] Nbuf Point to the net buffer.\r
882 @param[in, out] ExtFragment Pointer to the data block.\r
32cf7c73 883 @param[in, out] ExtNum The number of the data blocks.\r
cbf316f2 884\r
1204fe83 885 @retval EFI_BUFFER_TOO_SMALL The number of non-empty block is bigger than\r
32cf7c73 886 ExtNum.\r
887 @retval EFI_SUCCESS Fragment table is built successfully.\r
cbf316f2 888\r
889**/\r
890EFI_STATUS\r
7b414b4e 891EFIAPI\r
cbf316f2 892NetbufBuildExt (\r
893 IN NET_BUF *Nbuf,\r
3e7104c2 894 IN OUT NET_FRAGMENT *ExtFragment,\r
895 IN OUT UINT32 *ExtNum\r
cbf316f2 896 )\r
897{\r
898 UINT32 Index;\r
899 UINT32 Current;\r
900\r
901 Current = 0;\r
902\r
903 for (Index = 0; (Index < Nbuf->BlockOpNum); Index++) {\r
904 if (Nbuf->BlockOp[Index].Size == 0) {\r
905 continue;\r
906 }\r
907\r
908 if (Current < *ExtNum) {\r
909 ExtFragment[Current].Bulk = Nbuf->BlockOp[Index].Head;\r
910 ExtFragment[Current].Len = Nbuf->BlockOp[Index].Size;\r
911 Current++;\r
912 } else {\r
913 return EFI_BUFFER_TOO_SMALL;\r
914 }\r
915 }\r
916\r
917 *ExtNum = Current;\r
918 return EFI_SUCCESS;\r
919}\r
920\r
921\r
922/**\r
32cf7c73 923 Build a net buffer from a list of net buffers.\r
1204fe83 924\r
925 All the fragments will be collected from the list of NEW_BUF and then a new\r
926 net buffer will be created through NetbufFromExt.\r
927\r
32cf7c73 928 @param[in] BufList A List of the net buffer.\r
929 @param[in] HeadSpace The head space to be reserved.\r
930 @param[in] HeaderLen The length of the protocol header, This function\r
931 will pull that number of data into a linear block.\r
932 @param[in] ExtFree Pointer to the caller provided free function.\r
933 @param[in] Arg The argument passed to ExtFree when ExtFree is called.\r
934\r
1204fe83 935 @return Pointer to the net buffer built from the list of net\r
32cf7c73 936 buffers.\r
cbf316f2 937\r
938**/\r
939NET_BUF *\r
7b414b4e 940EFIAPI\r
cbf316f2 941NetbufFromBufList (\r
e48e37fc 942 IN LIST_ENTRY *BufList,\r
cbf316f2 943 IN UINT32 HeadSpace,\r
944 IN UINT32 HeaderLen,\r
945 IN NET_VECTOR_EXT_FREE ExtFree,\r
946 IN VOID *Arg OPTIONAL\r
947 )\r
948{\r
949 NET_FRAGMENT *Fragment;\r
950 UINT32 FragmentNum;\r
e48e37fc 951 LIST_ENTRY *Entry;\r
cbf316f2 952 NET_BUF *Nbuf;\r
953 UINT32 Index;\r
954 UINT32 Current;\r
955\r
956 //\r
957 //Compute how many blocks are there\r
958 //\r
959 FragmentNum = 0;\r
960\r
961 NET_LIST_FOR_EACH (Entry, BufList) {\r
962 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);\r
963 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
964 FragmentNum += Nbuf->BlockOpNum;\r
965 }\r
966\r
967 //\r
968 //Allocate and copy block points\r
969 //\r
e48e37fc 970 Fragment = AllocatePool (sizeof (NET_FRAGMENT) * FragmentNum);\r
cbf316f2 971\r
972 if (Fragment == NULL) {\r
973 return NULL;\r
974 }\r
975\r
976 Current = 0;\r
977\r
978 NET_LIST_FOR_EACH (Entry, BufList) {\r
979 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);\r
980 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
981\r
982 for (Index = 0; Index < Nbuf->BlockOpNum; Index++) {\r
8de75da2 983 if (Nbuf->BlockOp[Index].Size != 0) {\r
cbf316f2 984 Fragment[Current].Bulk = Nbuf->BlockOp[Index].Head;\r
985 Fragment[Current].Len = Nbuf->BlockOp[Index].Size;\r
986 Current++;\r
987 }\r
988 }\r
989 }\r
990\r
991 Nbuf = NetbufFromExt (Fragment, Current, HeadSpace, HeaderLen, ExtFree, Arg);\r
7b0ae7e8 992 FreePool (Fragment);\r
cbf316f2 993\r
994 return Nbuf;\r
995}\r
996\r
997\r
998/**\r
32cf7c73 999 Reserve some space in the header room of the net buffer.\r
cbf316f2 1000\r
1204fe83 1001 Upon allocation, all the space are in the tail room of the buffer. Call this\r
32cf7c73 1002 function to move some space to the header room. This function is quite limited\r
1204fe83 1003 in that it can only reserve space from the first block of an empty NET_BUF not\r
1004 built from the external. But it should be enough for the network stack.\r
32cf7c73 1005\r
1006 @param[in, out] Nbuf Pointer to the net buffer.\r
1007 @param[in] Len The length of buffer to be reserved from the header.\r
cbf316f2 1008\r
1009**/\r
1010VOID\r
7b414b4e 1011EFIAPI\r
cbf316f2 1012NetbufReserve (\r
3e7104c2 1013 IN OUT NET_BUF *Nbuf,\r
cbf316f2 1014 IN UINT32 Len\r
1015 )\r
1016{\r
1017 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
1018 NET_CHECK_SIGNATURE (Nbuf->Vector, NET_VECTOR_SIGNATURE);\r
1019\r
1020 ASSERT ((Nbuf->BlockOpNum == 1) && (Nbuf->TotalSize == 0));\r
1021 ASSERT ((Nbuf->Vector->Free == NULL) && (Nbuf->Vector->Len >= Len));\r
1022\r
1023 Nbuf->BlockOp[0].Head += Len;\r
1024 Nbuf->BlockOp[0].Tail += Len;\r
1025\r
1026 ASSERT (Nbuf->BlockOp[0].Tail <= Nbuf->BlockOp[0].BlockTail);\r
1027}\r
1028\r
1029\r
1030/**\r
1204fe83 1031 Allocate Len bytes of space from the header or tail of the buffer.\r
cbf316f2 1032\r
32cf7c73 1033 @param[in, out] Nbuf Pointer to the net buffer.\r
1034 @param[in] Len The length of the buffer to be allocated.\r
1204fe83 1035 @param[in] FromHead The flag to indicate whether reserve the data\r
32cf7c73 1036 from head (TRUE) or tail (FALSE).\r
cbf316f2 1037\r
1204fe83 1038 @return Pointer to the first byte of the allocated buffer,\r
9bc4edf2 1039 or NULL if there is no sufficient space.\r
cbf316f2 1040\r
1041**/\r
32cf7c73 1042UINT8*\r
7b414b4e 1043EFIAPI\r
cbf316f2 1044NetbufAllocSpace (\r
3e7104c2 1045 IN OUT NET_BUF *Nbuf,\r
cbf316f2 1046 IN UINT32 Len,\r
1047 IN BOOLEAN FromHead\r
1048 )\r
1049{\r
1050 NET_BLOCK_OP *BlockOp;\r
1051 UINT32 Index;\r
1052 UINT8 *SavedTail;\r
1053\r
9c1ca96e 1054 Index = 0;\r
1055\r
cbf316f2 1056 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
1057 NET_CHECK_SIGNATURE (Nbuf->Vector, NET_VECTOR_SIGNATURE);\r
1058\r
1059 ASSERT (Len > 0);\r
1060\r
1061 if (FromHead) {\r
1062 //\r
1063 // Allocate some space from head. If the buffer is empty,\r
1064 // allocate from the first block. If it isn't, allocate\r
1065 // from the first non-empty block, or the block before that.\r
1066 //\r
1067 if (Nbuf->TotalSize == 0) {\r
1068 Index = 0;\r
1069 } else {\r
1070 NetbufGetByte (Nbuf, 0, &Index);\r
1071\r
1072 if ((NET_HEADSPACE(&(Nbuf->BlockOp[Index])) < Len) && (Index > 0)) {\r
1073 Index--;\r
1074 }\r
1075 }\r
1076\r
1077 BlockOp = &(Nbuf->BlockOp[Index]);\r
1078\r
1079 if (NET_HEADSPACE (BlockOp) < Len) {\r
1080 return NULL;\r
1081 }\r
1082\r
1083 BlockOp->Head -= Len;\r
1084 BlockOp->Size += Len;\r
1085 Nbuf->TotalSize += Len;\r
1086\r
1087 return BlockOp->Head;\r
1088\r
1089 } else {\r
1090 //\r
1091 // Allocate some space from the tail. If the buffer is empty,\r
1092 // allocate from the first block. If it isn't, allocate\r
1093 // from the last non-empty block, or the block after that.\r
1094 //\r
1095 if (Nbuf->TotalSize == 0) {\r
1096 Index = 0;\r
1097 } else {\r
1098 NetbufGetByte (Nbuf, Nbuf->TotalSize - 1, &Index);\r
1099\r
1100 if ((NET_TAILSPACE(&(Nbuf->BlockOp[Index])) < Len) &&\r
1101 (Index < Nbuf->BlockOpNum - 1)) {\r
1102\r
1103 Index++;\r
1104 }\r
1105 }\r
1106\r
1107 BlockOp = &(Nbuf->BlockOp[Index]);\r
1108\r
1109 if (NET_TAILSPACE (BlockOp) < Len) {\r
1110 return NULL;\r
1111 }\r
1112\r
1113 SavedTail = BlockOp->Tail;\r
1114\r
1115 BlockOp->Tail += Len;\r
1116 BlockOp->Size += Len;\r
1117 Nbuf->TotalSize += Len;\r
1118\r
1119 return SavedTail;\r
1120 }\r
1121}\r
1122\r
1123\r
1124/**\r
32cf7c73 1125 Trim a single NET_BLOCK by Len bytes from the header or tail.\r
cbf316f2 1126\r
32cf7c73 1127 @param[in, out] BlockOp Pointer to the NET_BLOCK.\r
1128 @param[in] Len The length of the data to be trimmed.\r
1204fe83 1129 @param[in] FromHead The flag to indicate whether trim data from head\r
32cf7c73 1130 (TRUE) or tail (FALSE).\r
cbf316f2 1131\r
1132**/\r
cbf316f2 1133VOID\r
1134NetblockTrim (\r
3e7104c2 1135 IN OUT NET_BLOCK_OP *BlockOp,\r
cbf316f2 1136 IN UINT32 Len,\r
1137 IN BOOLEAN FromHead\r
1138 )\r
1139{\r
32cf7c73 1140 ASSERT ((BlockOp != NULL) && (BlockOp->Size >= Len));\r
cbf316f2 1141\r
1142 BlockOp->Size -= Len;\r
1143\r
1144 if (FromHead) {\r
1145 BlockOp->Head += Len;\r
1146 } else {\r
1147 BlockOp->Tail -= Len;\r
1148 }\r
1149}\r
1150\r
1151\r
1152/**\r
1204fe83 1153 Trim Len bytes from the header or tail of the net buffer.\r
cbf316f2 1154\r
32cf7c73 1155 @param[in, out] Nbuf Pointer to the net buffer.\r
1156 @param[in] Len The length of the data to be trimmed.\r
1204fe83 1157 @param[in] FromHead The flag to indicate whether trim data from head\r
32cf7c73 1158 (TRUE) or tail (FALSE).\r
cbf316f2 1159\r
1204fe83 1160 @return Length of the actually trimmed data, which is possible to be less\r
32cf7c73 1161 than Len because the TotalSize of Nbuf is less than Len.\r
cbf316f2 1162\r
1163**/\r
1164UINT32\r
7b414b4e 1165EFIAPI\r
cbf316f2 1166NetbufTrim (\r
3e7104c2 1167 IN OUT NET_BUF *Nbuf,\r
cbf316f2 1168 IN UINT32 Len,\r
1169 IN BOOLEAN FromHead\r
1170 )\r
1171{\r
1172 NET_BLOCK_OP *BlockOp;\r
1173 UINT32 Index;\r
1174 UINT32 Trimmed;\r
1175\r
1176 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
1177\r
b07bbb4f
FS
1178 if (Len == 0 || Nbuf->TotalSize == 0) {\r
1179 return 0;\r
1180 }\r
1181\r
cbf316f2 1182 if (Len > Nbuf->TotalSize) {\r
1183 Len = Nbuf->TotalSize;\r
1184 }\r
1185\r
1186 //\r
1187 // If FromTail is true, iterate backward. That\r
1188 // is, init Index to NBuf->BlockNum - 1, and\r
1189 // decrease it by 1 during each loop. Otherwise,\r
1190 // iterate forward. That is, init Index to 0, and\r
1191 // increase it by 1 during each loop.\r
1192 //\r
1193 Trimmed = 0;\r
1194 Nbuf->TotalSize -= Len;\r
1195\r
1196 Index = (FromHead ? 0 : Nbuf->BlockOpNum - 1);\r
1197 BlockOp = Nbuf->BlockOp;\r
1198\r
1199 for (;;) {\r
1200 if (BlockOp[Index].Size == 0) {\r
1201 Index += (FromHead ? 1 : -1);\r
1202 continue;\r
1203 }\r
1204\r
1205 if (Len > BlockOp[Index].Size) {\r
1206 Len -= BlockOp[Index].Size;\r
1207 Trimmed += BlockOp[Index].Size;\r
1208 NetblockTrim (&BlockOp[Index], BlockOp[Index].Size, FromHead);\r
1209 } else {\r
1210 Trimmed += Len;\r
1211 NetblockTrim (&BlockOp[Index], Len, FromHead);\r
1212 break;\r
1213 }\r
1214\r
1215 Index += (FromHead ? 1 : -1);\r
1216 }\r
1217\r
1218 return Trimmed;\r
1219}\r
1220\r
1221\r
1222/**\r
1204fe83 1223 Copy Len bytes of data from the specific offset of the net buffer to the\r
32cf7c73 1224 destination memory.\r
1204fe83 1225\r
32cf7c73 1226 The Len bytes of data may cross the several fragments of the net buffer.\r
1204fe83 1227\r
32cf7c73 1228 @param[in] Nbuf Pointer to the net buffer.\r
1229 @param[in] Offset The sequence number of the first byte to copy.\r
1230 @param[in] Len Length of the data to copy.\r
1231 @param[in] Dest The destination of the data to copy to.\r
1232\r
1233 @return The length of the actual copied data, or 0 if the offset\r
e3c8c68a 1234 specified exceeds the total size of net buffer.\r
cbf316f2 1235\r
1236**/\r
1237UINT32\r
7b414b4e 1238EFIAPI\r
cbf316f2 1239NetbufCopy (\r
1240 IN NET_BUF *Nbuf,\r
1241 IN UINT32 Offset,\r
1242 IN UINT32 Len,\r
1243 IN UINT8 *Dest\r
1244 )\r
1245{\r
1246 NET_BLOCK_OP *BlockOp;\r
1247 UINT32 Skip;\r
1248 UINT32 Left;\r
1249 UINT32 Copied;\r
1250 UINT32 Index;\r
1251 UINT32 Cur;\r
1252\r
1253 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
1254 ASSERT (Dest);\r
1255\r
1256 if ((Len == 0) || (Nbuf->TotalSize <= Offset)) {\r
1257 return 0;\r
1258 }\r
1259\r
1260 if (Nbuf->TotalSize - Offset < Len) {\r
1261 Len = Nbuf->TotalSize - Offset;\r
1262 }\r
1263\r
1264 BlockOp = Nbuf->BlockOp;\r
1265\r
1266 //\r
1267 // Skip to the offset. Don't make "Offset-By-One" error here.\r
1268 // Cur + BLOCK.SIZE is the first sequence number of next block.\r
1269 // So, (Offset < Cur + BLOCK.SIZE) means that the first byte\r
1270 // is in the current block. if (Offset == Cur + BLOCK.SIZE), the\r
1271 // first byte is the next block's first byte.\r
1272 //\r
1273 Cur = 0;\r
1274\r
1275 for (Index = 0; Index < Nbuf->BlockOpNum; Index++) {\r
1276 if (BlockOp[Index].Size == 0) {\r
1277 continue;\r
1278 }\r
1279\r
1280 if (Offset < Cur + BlockOp[Index].Size) {\r
1281 break;\r
1282 }\r
1283\r
1284 Cur += BlockOp[Index].Size;\r
1285 }\r
1286\r
1287 //\r
1288 // Cur is the sequence number of the first byte in the block\r
1289 // Offset - Cur is the number of bytes before first byte to\r
1290 // to copy in the current block.\r
1291 //\r
1292 Skip = Offset - Cur;\r
1293 Left = BlockOp[Index].Size - Skip;\r
1294\r
1295 if (Len <= Left) {\r
e48e37fc 1296 CopyMem (Dest, BlockOp[Index].Head + Skip, Len);\r
cbf316f2 1297 return Len;\r
1298 }\r
1299\r
e48e37fc 1300 CopyMem (Dest, BlockOp[Index].Head + Skip, Left);\r
cbf316f2 1301\r
1302 Dest += Left;\r
1303 Len -= Left;\r
1304 Copied = Left;\r
1305\r
1306 Index++;\r
1307\r
1308 for (; Index < Nbuf->BlockOpNum; Index++) {\r
1309 if (Len > BlockOp[Index].Size) {\r
1310 Len -= BlockOp[Index].Size;\r
1311 Copied += BlockOp[Index].Size;\r
1312\r
e48e37fc 1313 CopyMem (Dest, BlockOp[Index].Head, BlockOp[Index].Size);\r
cbf316f2 1314 Dest += BlockOp[Index].Size;\r
1315 } else {\r
1316 Copied += Len;\r
e48e37fc 1317 CopyMem (Dest, BlockOp[Index].Head, Len);\r
cbf316f2 1318 break;\r
1319 }\r
1320 }\r
1321\r
1322 return Copied;\r
1323}\r
1324\r
1325\r
1326/**\r
1327 Initiate the net buffer queue.\r
1328\r
32cf7c73 1329 @param[in, out] NbufQue Pointer to the net buffer queue to be initialized.\r
cbf316f2 1330\r
1331**/\r
1332VOID\r
7b414b4e 1333EFIAPI\r
cbf316f2 1334NetbufQueInit (\r
3e7104c2 1335 IN OUT NET_BUF_QUEUE *NbufQue\r
cbf316f2 1336 )\r
1337{\r
1338 NbufQue->Signature = NET_QUE_SIGNATURE;\r
1339 NbufQue->RefCnt = 1;\r
e48e37fc 1340 InitializeListHead (&NbufQue->List);\r
cbf316f2 1341\r
e48e37fc 1342 InitializeListHead (&NbufQue->BufList);\r
cbf316f2 1343 NbufQue->BufSize = 0;\r
1344 NbufQue->BufNum = 0;\r
1345}\r
1346\r
1347\r
1348/**\r
32cf7c73 1349 Allocate and initialize a net buffer queue.\r
cbf316f2 1350\r
32cf7c73 1351 @return Pointer to the allocated net buffer queue, or NULL if the\r
1352 allocation failed due to resource limit.\r
cbf316f2 1353\r
1354**/\r
1355NET_BUF_QUEUE *\r
7b414b4e 1356EFIAPI\r
cbf316f2 1357NetbufQueAlloc (\r
1358 VOID\r
1359 )\r
1360{\r
1361 NET_BUF_QUEUE *NbufQue;\r
1362\r
e48e37fc 1363 NbufQue = AllocatePool (sizeof (NET_BUF_QUEUE));\r
cbf316f2 1364 if (NbufQue == NULL) {\r
1365 return NULL;\r
1366 }\r
1367\r
1368 NetbufQueInit (NbufQue);\r
1369\r
1370 return NbufQue;\r
1371}\r
1372\r
1373\r
1374/**\r
1204fe83 1375 Free a net buffer queue.\r
1376\r
32cf7c73 1377 Decrease the reference count of the net buffer queue by one. The real resource\r
1204fe83 1378 free operation isn't performed until the reference count of the net buffer\r
32cf7c73 1379 queue is decreased to 0.\r
cbf316f2 1380\r
32cf7c73 1381 @param[in] NbufQue Pointer to the net buffer queue to be freed.\r
cbf316f2 1382\r
1383**/\r
1384VOID\r
7b414b4e 1385EFIAPI\r
cbf316f2 1386NetbufQueFree (\r
1387 IN NET_BUF_QUEUE *NbufQue\r
1388 )\r
1389{\r
7b0ae7e8 1390 ASSERT (NbufQue != NULL);\r
cbf316f2 1391 NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);\r
1392\r
1393 NbufQue->RefCnt--;\r
1394\r
1395 if (NbufQue->RefCnt == 0) {\r
1396 NetbufQueFlush (NbufQue);\r
7b0ae7e8 1397 FreePool (NbufQue);\r
cbf316f2 1398 }\r
1399}\r
1400\r
1401\r
1402/**\r
32cf7c73 1403 Append a net buffer to the net buffer queue.\r
cbf316f2 1404\r
32cf7c73 1405 @param[in, out] NbufQue Pointer to the net buffer queue.\r
1406 @param[in, out] Nbuf Pointer to the net buffer to be appended.\r
cbf316f2 1407\r
1408**/\r
1409VOID\r
7b414b4e 1410EFIAPI\r
cbf316f2 1411NetbufQueAppend (\r
3e7104c2 1412 IN OUT NET_BUF_QUEUE *NbufQue,\r
1413 IN OUT NET_BUF *Nbuf\r
cbf316f2 1414 )\r
1415{\r
1416 NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);\r
1417 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
1418\r
e48e37fc 1419 InsertTailList (&NbufQue->BufList, &Nbuf->List);\r
cbf316f2 1420\r
1421 NbufQue->BufSize += Nbuf->TotalSize;\r
1422 NbufQue->BufNum++;\r
1423}\r
1424\r
1425\r
1426/**\r
32cf7c73 1427 Remove a net buffer from the head in the specific queue and return it.\r
cbf316f2 1428\r
3e7104c2 1429 @param[in, out] NbufQue Pointer to the net buffer queue.\r
cbf316f2 1430\r
1204fe83 1431 @return Pointer to the net buffer removed from the specific queue,\r
9bc4edf2 1432 or NULL if there is no net buffer in the specific queue.\r
cbf316f2 1433\r
1434**/\r
1435NET_BUF *\r
7b414b4e 1436EFIAPI\r
cbf316f2 1437NetbufQueRemove (\r
3e7104c2 1438 IN OUT NET_BUF_QUEUE *NbufQue\r
cbf316f2 1439 )\r
1440{\r
1441 NET_BUF *First;\r
1442\r
1443 NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);\r
1444\r
1445 if (NbufQue->BufNum == 0) {\r
1446 return NULL;\r
1447 }\r
1448\r
1449 First = NET_LIST_USER_STRUCT (NbufQue->BufList.ForwardLink, NET_BUF, List);\r
1450\r
1451 NetListRemoveHead (&NbufQue->BufList);\r
1452\r
1453 NbufQue->BufSize -= First->TotalSize;\r
1454 NbufQue->BufNum--;\r
1455 return First;\r
1456}\r
1457\r
1458\r
1459/**\r
32cf7c73 1460 Copy Len bytes of data from the net buffer queue at the specific offset to the\r
1461 destination memory.\r
1204fe83 1462\r
32cf7c73 1463 The copying operation is the same as NetbufCopy but applies to the net buffer\r
1464 queue instead of the net buffer.\r
1204fe83 1465\r
32cf7c73 1466 @param[in] NbufQue Pointer to the net buffer queue.\r
1467 @param[in] Offset The sequence number of the first byte to copy.\r
1468 @param[in] Len Length of the data to copy.\r
1469 @param[out] Dest The destination of the data to copy to.\r
1470\r
1204fe83 1471 @return The length of the actual copied data, or 0 if the offset\r
32cf7c73 1472 specified exceeds the total size of net buffer queue.\r
cbf316f2 1473\r
1474**/\r
1475UINT32\r
3e7104c2 1476EFIAPI\r
cbf316f2 1477NetbufQueCopy (\r
1478 IN NET_BUF_QUEUE *NbufQue,\r
1479 IN UINT32 Offset,\r
1480 IN UINT32 Len,\r
3e7104c2 1481 OUT UINT8 *Dest\r
cbf316f2 1482 )\r
1483{\r
e48e37fc 1484 LIST_ENTRY *Entry;\r
cbf316f2 1485 NET_BUF *Nbuf;\r
1486 UINT32 Skip;\r
1487 UINT32 Left;\r
1488 UINT32 Cur;\r
1489 UINT32 Copied;\r
1490\r
1491 NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);\r
1492 ASSERT (Dest != NULL);\r
1493\r
1494 if ((Len == 0) || (NbufQue->BufSize <= Offset)) {\r
1495 return 0;\r
1496 }\r
1497\r
1498 if (NbufQue->BufSize - Offset < Len) {\r
1499 Len = NbufQue->BufSize - Offset;\r
1500 }\r
1501\r
1502 //\r
1503 // skip to the Offset\r
1504 //\r
1505 Cur = 0;\r
1506 Nbuf = NULL;\r
1507\r
1508 NET_LIST_FOR_EACH (Entry, &NbufQue->BufList) {\r
1509 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);\r
1510\r
1511 if (Offset < Cur + Nbuf->TotalSize) {\r
1512 break;\r
1513 }\r
1514\r
1515 Cur += Nbuf->TotalSize;\r
1516 }\r
1517\r
894d038a 1518 ASSERT (Nbuf != NULL);\r
1519\r
cbf316f2 1520 //\r
1521 // Copy the data in the first buffer.\r
1522 //\r
1523 Skip = Offset - Cur;\r
1524 Left = Nbuf->TotalSize - Skip;\r
1525\r
1526 if (Len < Left) {\r
1527 return NetbufCopy (Nbuf, Skip, Len, Dest);\r
1528 }\r
1529\r
1530 NetbufCopy (Nbuf, Skip, Left, Dest);\r
1531 Dest += Left;\r
1532 Len -= Left;\r
1533 Copied = Left;\r
1534\r
1535 //\r
1536 // Iterate over the others\r
1537 //\r
1538 Entry = Entry->ForwardLink;\r
1539\r
1540 while ((Len > 0) && (Entry != &NbufQue->BufList)) {\r
1541 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);\r
1542\r
1543 if (Len > Nbuf->TotalSize) {\r
1544 Len -= Nbuf->TotalSize;\r
1545 Copied += Nbuf->TotalSize;\r
1546\r
1547 NetbufCopy (Nbuf, 0, Nbuf->TotalSize, Dest);\r
1548 Dest += Nbuf->TotalSize;\r
1549\r
1550 } else {\r
1551 NetbufCopy (Nbuf, 0, Len, Dest);\r
1552 Copied += Len;\r
1553 break;\r
1554 }\r
1555\r
1556 Entry = Entry->ForwardLink;\r
1557 }\r
1558\r
1559 return Copied;\r
1560}\r
1561\r
1562\r
1563/**\r
3b1464d5 1564 Trim Len bytes of data from the buffer queue and free any net buffer\r
1565 that is completely trimmed.\r
1204fe83 1566\r
32cf7c73 1567 The trimming operation is the same as NetbufTrim but applies to the net buffer\r
1568 queue instead of the net buffer.\r
cbf316f2 1569\r
3e7104c2 1570 @param[in, out] NbufQue Pointer to the net buffer queue.\r
1571 @param[in] Len Length of the data to trim.\r
cbf316f2 1572\r
32cf7c73 1573 @return The actual length of the data trimmed.\r
cbf316f2 1574\r
1575**/\r
1576UINT32\r
7b414b4e 1577EFIAPI\r
cbf316f2 1578NetbufQueTrim (\r
3e7104c2 1579 IN OUT NET_BUF_QUEUE *NbufQue,\r
cbf316f2 1580 IN UINT32 Len\r
1581 )\r
1582{\r
e48e37fc 1583 LIST_ENTRY *Entry;\r
1584 LIST_ENTRY *Next;\r
cbf316f2 1585 NET_BUF *Nbuf;\r
1586 UINT32 Trimmed;\r
1587\r
1588 NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);\r
1589\r
1590 if (Len == 0) {\r
1591 return 0;\r
1592 }\r
1593\r
1594 if (Len > NbufQue->BufSize) {\r
1595 Len = NbufQue->BufSize;\r
1596 }\r
1597\r
1598 NbufQue->BufSize -= Len;\r
1599 Trimmed = 0;\r
1600\r
1601 NET_LIST_FOR_EACH_SAFE (Entry, Next, &NbufQue->BufList) {\r
1602 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);\r
1603\r
1604 if (Len >= Nbuf->TotalSize) {\r
1605 Trimmed += Nbuf->TotalSize;\r
1606 Len -= Nbuf->TotalSize;\r
1607\r
e48e37fc 1608 RemoveEntryList (Entry);\r
cbf316f2 1609 NetbufFree (Nbuf);\r
1610\r
1611 NbufQue->BufNum--;\r
1612\r
1613 if (Len == 0) {\r
1614 break;\r
1615 }\r
1616\r
1617 } else {\r
1618 Trimmed += NetbufTrim (Nbuf, Len, NET_BUF_HEAD);\r
1619 break;\r
1620 }\r
1621 }\r
1622\r
1623 return Trimmed;\r
1624}\r
1625\r
1626\r
1627/**\r
1628 Flush the net buffer queue.\r
1629\r
3e7104c2 1630 @param[in, out] NbufQue Pointer to the queue to be flushed.\r
cbf316f2 1631\r
1632**/\r
1633VOID\r
7b414b4e 1634EFIAPI\r
cbf316f2 1635NetbufQueFlush (\r
3e7104c2 1636 IN OUT NET_BUF_QUEUE *NbufQue\r
cbf316f2 1637 )\r
1638{\r
1639 NET_CHECK_SIGNATURE (NbufQue, NET_QUE_SIGNATURE);\r
1640\r
1641 NetbufFreeList (&NbufQue->BufList);\r
1642\r
1643 NbufQue->BufNum = 0;\r
1644 NbufQue->BufSize = 0;\r
1645}\r
1646\r
1647\r
1648/**\r
32cf7c73 1649 Compute the checksum for a bulk of data.\r
cbf316f2 1650\r
3e7104c2 1651 @param[in] Bulk Pointer to the data.\r
1652 @param[in] Len Length of the data, in bytes.\r
cbf316f2 1653\r
3e7104c2 1654 @return The computed checksum.\r
cbf316f2 1655\r
1656**/\r
1657UINT16\r
7b414b4e 1658EFIAPI\r
cbf316f2 1659NetblockChecksum (\r
1660 IN UINT8 *Bulk,\r
1661 IN UINT32 Len\r
1662 )\r
1663{\r
1664 register UINT32 Sum;\r
1665\r
1666 Sum = 0;\r
1667\r
69e856df
HW
1668 //\r
1669 // Add left-over byte, if any\r
1670 //\r
1671 if (Len % 2 != 0) {\r
1672 Sum += *(Bulk + Len - 1);\r
1673 }\r
1674\r
cbf316f2 1675 while (Len > 1) {\r
1676 Sum += *(UINT16 *) Bulk;\r
1677 Bulk += 2;\r
1678 Len -= 2;\r
1679 }\r
1680\r
cbf316f2 1681 //\r
1682 // Fold 32-bit sum to 16 bits\r
1683 //\r
3e7104c2 1684 while ((Sum >> 16) != 0) {\r
cbf316f2 1685 Sum = (Sum & 0xffff) + (Sum >> 16);\r
1686\r
1687 }\r
1688\r
1689 return (UINT16) Sum;\r
1690}\r
1691\r
1692\r
1693/**\r
1694 Add two checksums.\r
1695\r
3e7104c2 1696 @param[in] Checksum1 The first checksum to be added.\r
1697 @param[in] Checksum2 The second checksum to be added.\r
cbf316f2 1698\r
3e7104c2 1699 @return The new checksum.\r
cbf316f2 1700\r
1701**/\r
1702UINT16\r
7b414b4e 1703EFIAPI\r
cbf316f2 1704NetAddChecksum (\r
1705 IN UINT16 Checksum1,\r
1706 IN UINT16 Checksum2\r
1707 )\r
1708{\r
1709 UINT32 Sum;\r
1710\r
1711 Sum = Checksum1 + Checksum2;\r
1712\r
1713 //\r
1714 // two UINT16 can only add up to a carry of 1.\r
1715 //\r
3e7104c2 1716 if ((Sum >> 16) != 0) {\r
cbf316f2 1717 Sum = (Sum & 0xffff) + 1;\r
1718\r
1719 }\r
1720\r
1721 return (UINT16) Sum;\r
1722}\r
1723\r
1724\r
1725/**\r
1726 Compute the checksum for a NET_BUF.\r
1727\r
3e7104c2 1728 @param[in] Nbuf Pointer to the net buffer.\r
cbf316f2 1729\r
3e7104c2 1730 @return The computed checksum.\r
cbf316f2 1731\r
1732**/\r
1733UINT16\r
7b414b4e 1734EFIAPI\r
cbf316f2 1735NetbufChecksum (\r
1736 IN NET_BUF *Nbuf\r
1737 )\r
1738{\r
1739 NET_BLOCK_OP *BlockOp;\r
1740 UINT32 Offset;\r
1741 UINT16 TotalSum;\r
1742 UINT16 BlockSum;\r
1743 UINT32 Index;\r
1744\r
1745 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
1746\r
1747 TotalSum = 0;\r
1748 Offset = 0;\r
1749 BlockOp = Nbuf->BlockOp;\r
1750\r
1751 for (Index = 0; Index < Nbuf->BlockOpNum; Index++) {\r
1752 if (BlockOp[Index].Size == 0) {\r
1753 continue;\r
1754 }\r
1755\r
1756 BlockSum = NetblockChecksum (BlockOp[Index].Head, BlockOp[Index].Size);\r
1757\r
3e7104c2 1758 if ((Offset & 0x01) != 0) {\r
cbf316f2 1759 //\r
1760 // The checksum starts with an odd byte, swap\r
1761 // the checksum before added to total checksum\r
1762 //\r
1204fe83 1763 BlockSum = SwapBytes16 (BlockSum);\r
cbf316f2 1764 }\r
1765\r
1766 TotalSum = NetAddChecksum (BlockSum, TotalSum);\r
1767 Offset += BlockOp[Index].Size;\r
1768 }\r
1769\r
1770 return TotalSum;\r
1771}\r
1772\r
1773\r
1774/**\r
1204fe83 1775 Compute the checksum for TCP/UDP pseudo header.\r
1776\r
32cf7c73 1777 Src and Dst are in network byte order, and Len is in host byte order.\r
cbf316f2 1778\r
3e7104c2 1779 @param[in] Src The source address of the packet.\r
1780 @param[in] Dst The destination address of the packet.\r
1781 @param[in] Proto The protocol type of the packet.\r
1782 @param[in] Len The length of the packet.\r
cbf316f2 1783\r
3e7104c2 1784 @return The computed checksum.\r
cbf316f2 1785\r
1786**/\r
1787UINT16\r
7b414b4e 1788EFIAPI\r
cbf316f2 1789NetPseudoHeadChecksum (\r
1790 IN IP4_ADDR Src,\r
1791 IN IP4_ADDR Dst,\r
1792 IN UINT8 Proto,\r
1793 IN UINT16 Len\r
1794 )\r
1795{\r
1796 NET_PSEUDO_HDR Hdr;\r
1797\r
1798 //\r
1799 // Zero the memory to relieve align problems\r
1800 //\r
e48e37fc 1801 ZeroMem (&Hdr, sizeof (Hdr));\r
cbf316f2 1802\r
1803 Hdr.SrcIp = Src;\r
1804 Hdr.DstIp = Dst;\r
1805 Hdr.Protocol = Proto;\r
1806 Hdr.Len = HTONS (Len);\r
1807\r
1808 return NetblockChecksum ((UINT8 *) &Hdr, sizeof (Hdr));\r
1809}\r
f6b7393c 1810\r
1811/**\r
1204fe83 1812 Compute the checksum for TCP6/UDP6 pseudo header.\r
1813\r
f6b7393c 1814 Src and Dst are in network byte order, and Len is in host byte order.\r
1815\r
1816 @param[in] Src The source address of the packet.\r
1817 @param[in] Dst The destination address of the packet.\r
1818 @param[in] NextHeader The protocol type of the packet.\r
1819 @param[in] Len The length of the packet.\r
1820\r
1821 @return The computed checksum.\r
1822\r
1823**/\r
1824UINT16\r
e798cd87 1825EFIAPI\r
f6b7393c 1826NetIp6PseudoHeadChecksum (\r
1827 IN EFI_IPv6_ADDRESS *Src,\r
1828 IN EFI_IPv6_ADDRESS *Dst,\r
1829 IN UINT8 NextHeader,\r
1830 IN UINT32 Len\r
1831 )\r
1832{\r
1833 NET_IP6_PSEUDO_HDR Hdr;\r
1834\r
1835 //\r
1836 // Zero the memory to relieve align problems\r
1837 //\r
1838 ZeroMem (&Hdr, sizeof (Hdr));\r
1839\r
1840 IP6_COPY_ADDRESS (&Hdr.SrcIp, Src);\r
1841 IP6_COPY_ADDRESS (&Hdr.DstIp, Dst);\r
1842\r
1843 Hdr.NextHeader = NextHeader;\r
1204fe83 1844 Hdr.Len = HTONL (Len);\r
f6b7393c 1845\r
1846 return NetblockChecksum ((UINT8 *) &Hdr, sizeof (Hdr));\r
1847}\r
1848\r
705f53a9 1849/**\r
d1102dba
LG
1850 The function frees the net buffer which allocated by the IP protocol. It releases\r
1851 only the net buffer and doesn't call the external free function.\r
705f53a9 1852\r
d1102dba
LG
1853 This function should be called after finishing the process of mIpSec->ProcessExt()\r
1854 for outbound traffic. The (EFI_IPSEC2_PROTOCOL)->ProcessExt() allocates a new\r
705f53a9 1855 buffer for the ESP, so there needs a function to free the old net buffer.\r
1856\r
1857 @param[in] Nbuf The network buffer to be freed.\r
1858\r
1859**/\r
1860VOID\r
1861NetIpSecNetbufFree (\r
1862 NET_BUF *Nbuf\r
1863 )\r
1864{\r
1865 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
1866 ASSERT (Nbuf->RefCnt > 0);\r
1867\r
1868 Nbuf->RefCnt--;\r
1869\r
1870 if (Nbuf->RefCnt == 0) {\r
d1102dba 1871\r
705f53a9 1872 //\r
1873 // Update Vector only when NBuf is to be released. That is,\r
1874 // all the sharing of Nbuf increse Vector's RefCnt by one\r
1875 //\r
1876 NET_CHECK_SIGNATURE (Nbuf->Vector, NET_VECTOR_SIGNATURE);\r
1877 ASSERT (Nbuf->Vector->RefCnt > 0);\r
1878\r
1879 Nbuf->Vector->RefCnt--;\r
1880\r
1881 if (Nbuf->Vector->RefCnt > 0) {\r
1882 return;\r
1883 }\r
1884\r
1885 //\r
d1102dba 1886 // If NET_VECTOR_OWN_FIRST is set, release the first block since it is\r
705f53a9 1887 // allocated by us\r
1888 //\r
1889 if ((Nbuf->Vector->Flag & NET_VECTOR_OWN_FIRST) != 0) {\r
1890 FreePool (Nbuf->Vector->Block[0].Bulk);\r
1891 }\r
1892 FreePool (Nbuf->Vector);\r
d1102dba
LG
1893 FreePool (Nbuf);\r
1894 }\r
705f53a9 1895}\r
1896\r