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