2 Network library functions providing net buffer operation support.
4 Copyright (c) 2005 - 2010, Intel Corporation.<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/NetLib.h>
17 #include <Library/BaseLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/UefiBootServicesTableLib.h>
21 #include <Library/MemoryAllocationLib.h>
25 Allocate and build up the sketch for a NET_BUF.
27 The net buffer allocated has the BlockOpNum's NET_BLOCK_OP, and its associated
28 NET_VECTOR has the BlockNum's NET_BLOCK. But all the NET_BLOCK_OP and
29 NET_BLOCK remain un-initialized.
31 @param[in] BlockNum The number of NET_BLOCK in the vector of net buffer
32 @param[in] BlockOpNum The number of NET_BLOCK_OP in the net buffer
34 @return Pointer to the allocated NET_BUF, or NULL if the
35 allocation failed due to resource limit.
47 ASSERT (BlockOpNum
>= 1);
50 // Allocate three memory blocks.
52 Nbuf
= AllocateZeroPool (NET_BUF_SIZE (BlockOpNum
));
58 Nbuf
->Signature
= NET_BUF_SIGNATURE
;
60 Nbuf
->BlockOpNum
= BlockOpNum
;
61 InitializeListHead (&Nbuf
->List
);
64 Vector
= AllocateZeroPool (NET_VECTOR_SIZE (BlockNum
));
70 Vector
->Signature
= NET_VECTOR_SIGNATURE
;
72 Vector
->BlockNum
= BlockNum
;
73 Nbuf
->Vector
= Vector
;
86 Allocate a single block NET_BUF. Upon allocation, all the
87 free space is in the tail room.
89 @param[in] Len The length of the block.
91 @return Pointer to the allocated NET_BUF, or NULL if the
92 allocation failed due to resource limit.
107 Nbuf
= NetbufAllocStruct (1, 1);
113 Bulk
= AllocatePool (Len
);
119 Vector
= Nbuf
->Vector
;
122 Vector
->Block
[0].Bulk
= Bulk
;
123 Vector
->Block
[0].Len
= Len
;
125 Nbuf
->BlockOp
[0].BlockHead
= Bulk
;
126 Nbuf
->BlockOp
[0].BlockTail
= Bulk
+ Len
;
128 Nbuf
->BlockOp
[0].Head
= Bulk
;
129 Nbuf
->BlockOp
[0].Tail
= Bulk
;
130 Nbuf
->BlockOp
[0].Size
= 0;
142 Decrease the reference count of the net vector by one. The real resource free
143 operation isn't performed until the reference count of the net vector is
146 @param[in] Vector Pointer to the NET_VECTOR to be freed.
151 IN NET_VECTOR
*Vector
156 ASSERT (Vector
!= NULL
);
157 NET_CHECK_SIGNATURE (Vector
, NET_VECTOR_SIGNATURE
);
158 ASSERT (Vector
->RefCnt
> 0);
162 if (Vector
->RefCnt
> 0) {
166 if (Vector
->Free
!= NULL
) {
168 // Call external free function to free the vector if it
169 // isn't NULL. If NET_VECTOR_OWN_FIRST is set, release the
170 // first block since it is allocated by us
172 if ((Vector
->Flag
& NET_VECTOR_OWN_FIRST
) != 0) {
173 gBS
->FreePool (Vector
->Block
[0].Bulk
);
176 Vector
->Free (Vector
->Arg
);
180 // Free each memory block associated with the Vector
182 for (Index
= 0; Index
< Vector
->BlockNum
; Index
++) {
183 gBS
->FreePool (Vector
->Block
[Index
].Bulk
);
192 Free the net buffer and its associated NET_VECTOR.
194 Decrease the reference count of the net buffer by one. Free the associated net
195 vector and itself if the reference count of the net buffer is decreased to 0.
196 The net vector free operation just decrease the reference count of the net
197 vector by one and do the real resource free operation when the reference count
198 of the net vector is 0.
200 @param[in] Nbuf Pointer to the NET_BUF to be freed.
209 ASSERT (Nbuf
!= NULL
);
210 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
211 ASSERT (Nbuf
->RefCnt
> 0);
215 if (Nbuf
->RefCnt
== 0) {
217 // Update Vector only when NBuf is to be released. That is,
218 // all the sharing of Nbuf increse Vector's RefCnt by one
220 NetbufFreeVector (Nbuf
->Vector
);
227 Create a copy of the net buffer that shares the associated net vector.
229 The reference count of the newly created net buffer is set to 1. The reference
230 count of the associated net vector is increased by one.
232 @param[in] Nbuf Pointer to the net buffer to be cloned.
234 @return Pointer to the cloned net buffer, or NULL if the
235 allocation failed due to resource limit.
246 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
248 Clone
= AllocatePool (NET_BUF_SIZE (Nbuf
->BlockOpNum
));
254 Clone
->Signature
= NET_BUF_SIGNATURE
;
256 InitializeListHead (&Clone
->List
);
258 Clone
->Ip
= Nbuf
->Ip
;
259 Clone
->Tcp
= Nbuf
->Tcp
;
261 CopyMem (Clone
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
263 NET_GET_REF (Nbuf
->Vector
);
265 Clone
->Vector
= Nbuf
->Vector
;
266 Clone
->BlockOpNum
= Nbuf
->BlockOpNum
;
267 Clone
->TotalSize
= Nbuf
->TotalSize
;
268 CopyMem (Clone
->BlockOp
, Nbuf
->BlockOp
, sizeof (NET_BLOCK_OP
) * Nbuf
->BlockOpNum
);
275 Create a duplicated copy of the net buffer with data copied and HeadSpace
276 bytes of head space reserved.
278 The duplicated net buffer will allocate its own memory to hold the data of the
281 @param[in] Nbuf Pointer to the net buffer to be duplicated from.
282 @param[in, out] Duplicate Pointer to the net buffer to duplicate to, if
283 NULL a new net buffer is allocated.
284 @param[in] HeadSpace Length of the head space to reserve.
286 @return Pointer to the duplicated net buffer, or NULL if
287 the allocation failed due to resource limit.
294 IN OUT NET_BUF
*Duplicate OPTIONAL
,
300 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
302 if (Duplicate
== NULL
) {
303 Duplicate
= NetbufAlloc (Nbuf
->TotalSize
+ HeadSpace
);
306 if (Duplicate
== NULL
) {
311 // Don't set the IP and TCP head point, since it is most
312 // like that they are pointing to the memory of Nbuf.
314 CopyMem (Duplicate
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
315 NetbufReserve (Duplicate
, HeadSpace
);
317 Dst
= NetbufAllocSpace (Duplicate
, Nbuf
->TotalSize
, NET_BUF_TAIL
);
318 NetbufCopy (Nbuf
, 0, Nbuf
->TotalSize
, Dst
);
325 Free a list of net buffers.
327 @param[in, out] Head Pointer to the head of linked net buffers.
333 IN OUT LIST_ENTRY
*Head
340 Entry
= Head
->ForwardLink
;
342 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Head
) {
343 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
344 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
346 RemoveEntryList (Entry
);
350 ASSERT (IsListEmpty (Head
));
355 Get the index of NET_BLOCK_OP that contains the byte at Offset in the net
358 This can be used to, for example, retrieve the IP header in the packet. It
359 also can be used to get the fragment that contains the byte which is used
360 mainly by the library implementation itself.
362 @param[in] Nbuf Pointer to the net buffer.
363 @param[in] Offset The offset of the byte.
364 @param[out] Index Index of the NET_BLOCK_OP that contains the byte at
367 @return Pointer to the Offset'th byte of data in the net buffer, or NULL
368 if there is no such data in the net buffer.
376 OUT UINT32
*Index OPTIONAL
379 NET_BLOCK_OP
*BlockOp
;
383 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
385 if (Offset
>= Nbuf
->TotalSize
) {
389 BlockOp
= Nbuf
->BlockOp
;
392 for (Loop
= 0; Loop
< Nbuf
->BlockOpNum
; Loop
++) {
394 if (Len
+ BlockOp
[Loop
].Size
<= Offset
) {
395 Len
+= BlockOp
[Loop
].Size
;
403 return BlockOp
[Loop
].Head
+ (Offset
- Len
);
412 Set the NET_BLOCK and corresponding NET_BLOCK_OP in the net buffer and
413 corresponding net vector according to the bulk pointer and bulk length.
415 All the pointers in the Index'th NET_BLOCK and NET_BLOCK_OP are set to the
416 bulk's head and tail respectively. So, this function alone can't be used by
419 @param[in, out] Nbuf Pointer to the net buffer.
420 @param[in] Bulk Pointer to the data.
421 @param[in] Len Length of the bulk data.
422 @param[in] Index The data block index in the net buffer the bulk
423 data should belong to.
428 IN OUT NET_BUF
*Nbuf
,
434 NET_BLOCK_OP
*BlockOp
;
437 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
438 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
439 ASSERT (Index
< Nbuf
->BlockOpNum
);
441 Block
= &(Nbuf
->Vector
->Block
[Index
]);
442 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
445 BlockOp
->BlockHead
= Bulk
;
446 BlockOp
->BlockTail
= Bulk
+ Len
;
447 BlockOp
->Head
= Bulk
;
448 BlockOp
->Tail
= Bulk
+ Len
;
455 Set the NET_BLOCK_OP in the net buffer. The corresponding NET_BLOCK
456 structure is left untouched.
458 Some times, there is no 1:1 relationship between NET_BLOCK and NET_BLOCK_OP.
459 For example, that in NetbufGetFragment.
461 @param[in, out] Nbuf Pointer to the net buffer.
462 @param[in] Bulk Pointer to the data.
463 @param[in] Len Length of the bulk data.
464 @param[in] Index The data block index in the net buffer the bulk
465 data should belong to.
470 IN OUT NET_BUF
*Nbuf
,
476 NET_BLOCK_OP
*BlockOp
;
478 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
479 ASSERT (Index
< Nbuf
->BlockOpNum
);
481 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
482 BlockOp
->BlockHead
= Bulk
;
483 BlockOp
->BlockTail
= Bulk
+ Len
;
484 BlockOp
->Head
= Bulk
;
485 BlockOp
->Tail
= Bulk
+ Len
;
491 Helper function for NetbufGetFragment. NetbufGetFragment may allocate the
492 first block to reserve HeadSpace bytes header space. So it needs to create a
493 new net vector for the first block and can avoid copy for the remaining data
494 by sharing the old net vector.
496 @param[in] Arg Point to the old NET_VECTOR.
500 NetbufGetFragmentFree (
506 Vector
= (NET_VECTOR
*)Arg
;
507 NetbufFreeVector (Vector
);
512 Create a NET_BUF structure which contains Len byte data of Nbuf starting from
515 A new NET_BUF structure will be created but the associated data in NET_VECTOR
516 is shared. This function exists to do IP packet fragmentation.
518 @param[in] Nbuf Pointer to the net buffer to be extracted.
519 @param[in] Offset Starting point of the data to be included in the new
521 @param[in] Len Bytes of data to be included in the new net buffer.
522 @param[in] HeadSpace Bytes of head space to reserve for protocol header.
524 @return Pointer to the cloned net buffer, or NULL if the
525 allocation failed due to resource limit.
539 NET_BLOCK_OP
*BlockOp
;
551 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
553 if ((Len
== 0) || (Offset
+ Len
> Nbuf
->TotalSize
)) {
558 // First find the first and last BlockOp that contains
559 // the valid data, and compute the offset of the first
560 // BlockOp and length of the last BlockOp
562 BlockOp
= Nbuf
->BlockOp
;
565 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
566 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
570 Cur
+= BlockOp
[Index
].Size
;
574 // First is the index of the first BlockOp, FirstSkip is
575 // the offset of the first byte in the first BlockOp.
578 FirstSkip
= Offset
- Cur
;
579 FirstLen
= BlockOp
[Index
].Size
- FirstSkip
;
584 if (Len
> FirstLen
) {
585 Cur
+= BlockOp
[Index
].Size
;
588 for (; Index
< Nbuf
->BlockOpNum
; Index
++) {
589 if (Offset
+ Len
<= Cur
+ BlockOp
[Index
].Size
) {
591 LastLen
= Offset
+ Len
- Cur
;
595 Cur
+= BlockOp
[Index
].Size
;
604 ASSERT (Last
>= First
);
605 BlockOpNum
= Last
- First
+ 1;
608 if (HeadSpace
!= 0) {
610 // Allocate an extra block to accomdate the head space.
614 Child
= NetbufAllocStruct (1, BlockOpNum
);
620 FirstBulk
= AllocatePool (HeadSpace
);
622 if (FirstBulk
== NULL
) {
626 Vector
= Child
->Vector
;
627 Vector
->Free
= NetbufGetFragmentFree
;
628 Vector
->Arg
= Nbuf
->Vector
;
629 Vector
->Flag
= NET_VECTOR_OWN_FIRST
;
630 Vector
->Len
= HeadSpace
;
633 // Reserve the head space in the first block
635 NetbufSetBlock (Child
, FirstBulk
, HeadSpace
, 0);
636 Child
->BlockOp
[0].Head
+= HeadSpace
;
637 Child
->BlockOp
[0].Size
= 0;
641 Child
= NetbufAllocStruct (0, BlockOpNum
);
647 Child
->Vector
= Nbuf
->Vector
;
650 NET_GET_REF (Nbuf
->Vector
);
651 Child
->TotalSize
= Len
;
654 // Set all the BlockOp up, the first and last one are special
655 // and need special process.
659 Nbuf
->BlockOp
[First
].Head
+ FirstSkip
,
664 for (Index
= First
+ 1; Index
< Last
; Index
++) {
682 CopyMem (Child
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
694 Build a NET_BUF from external blocks.
696 A new NET_BUF structure will be created from external blocks. Additional block
697 of memory will be allocated to hold reserved HeadSpace bytes of header room
698 and existing HeadLen bytes of header but the external blocks are shared by the
699 net buffer to avoid data copying.
701 @param[in] ExtFragment Pointer to the data block.
702 @param[in] ExtNum The number of the data blocks.
703 @param[in] HeadSpace The head space to be reserved.
704 @param[in] HeadLen The length of the protocol header, This function
705 will pull that number of data into a linear block.
706 @param[in] ExtFree Pointer to the caller provided free function.
707 @param[in] Arg The argument passed to ExtFree when ExtFree is
710 @return Pointer to the net buffer built from the data blocks,
711 or NULL if the allocation failed due to resource
718 IN NET_FRAGMENT
*ExtFragment
,
722 IN NET_VECTOR_EXT_FREE ExtFree
,
723 IN VOID
*Arg OPTIONAL
728 NET_FRAGMENT SavedFragment
;
733 UINT32 FirstBlockLen
;
740 ASSERT ((ExtFragment
!= NULL
) && (ExtNum
> 0) && (ExtFree
!= NULL
));
742 SavedFragment
.Bulk
= NULL
;
743 SavedFragment
.Len
= 0;
755 // No need to consolidate the header if the first block is
756 // longer than the header length or there is only one block.
758 if ((ExtFragment
[0].Len
>= HeadLen
) || (ExtNum
== 1)) {
763 // Allocate an extra block if we need to:
764 // 1. Allocate some header space
765 // 2. aggreate the packet header
767 if ((HeadSpace
!= 0) || (HeadLen
!= 0)) {
768 FirstBlockLen
= HeadLen
+ HeadSpace
;
769 FirstBlock
= AllocatePool (FirstBlockLen
);
771 if (FirstBlock
== NULL
) {
779 // Copy the header to the first block, reduce the NET_BLOCK
780 // to allocate by one for each block that is completely covered
781 // by the first bulk.
785 Header
= FirstBlock
+ HeadSpace
;
787 for (Index
= 0; Index
< ExtNum
; Index
++) {
788 if (Len
>= ExtFragment
[Index
].Len
) {
789 CopyMem (Header
, ExtFragment
[Index
].Bulk
, ExtFragment
[Index
].Len
);
791 Copied
+= ExtFragment
[Index
].Len
;
792 Len
-= ExtFragment
[Index
].Len
;
793 Header
+= ExtFragment
[Index
].Len
;
794 TotalLen
+= ExtFragment
[Index
].Len
;
799 // Increament the index number to point to the next
800 // non-empty fragment.
807 CopyMem (Header
, ExtFragment
[Index
].Bulk
, Len
);
813 // Adjust the block structure to exclude the data copied,
814 // So, the left-over block can be processed as other blocks.
815 // But it must be recovered later. (SavedIndex > 0) always
816 // holds since we don't aggreate the header if the first block
817 // is bigger enough that the header is continuous
820 SavedFragment
= ExtFragment
[Index
];
821 ExtFragment
[Index
].Bulk
+= Len
;
822 ExtFragment
[Index
].Len
-= Len
;
828 Nbuf
= NetbufAllocStruct (BlockNum
, BlockNum
);
834 Vector
= Nbuf
->Vector
;
835 Vector
->Free
= ExtFree
;
837 Vector
->Flag
= ((FirstBlockLen
!= 0) ? NET_VECTOR_OWN_FIRST
: 0);
840 // Set the first block up which may contain
841 // some head space and aggregated header
845 if (FirstBlockLen
!= 0) {
846 NetbufSetBlock (Nbuf
, FirstBlock
, HeadSpace
+ Copied
, 0);
847 Nbuf
->BlockOp
[0].Head
+= HeadSpace
;
848 Nbuf
->BlockOp
[0].Size
= Copied
;
853 for (; Index
< ExtNum
; Index
++) {
854 NetbufSetBlock (Nbuf
, ExtFragment
[Index
].Bulk
, ExtFragment
[Index
].Len
, CurBlock
);
855 TotalLen
+= ExtFragment
[Index
].Len
;
859 Vector
->Len
= TotalLen
+ HeadSpace
;
860 Nbuf
->TotalSize
= TotalLen
;
862 if (SavedIndex
!= 0) {
863 ExtFragment
[SavedIndex
] = SavedFragment
;
869 if (FirstBlock
!= NULL
) {
870 FreePool (FirstBlock
);
877 Build a fragment table to contain the fragments in the net buffer. This is the
878 opposite operation of the NetbufFromExt.
880 @param[in] Nbuf Point to the net buffer.
881 @param[in, out] ExtFragment Pointer to the data block.
882 @param[in, out] ExtNum The number of the data blocks.
884 @retval EFI_BUFFER_TOO_SMALL The number of non-empty block is bigger than
886 @retval EFI_SUCCESS Fragment table is built successfully.
893 IN OUT NET_FRAGMENT
*ExtFragment
,
894 IN OUT UINT32
*ExtNum
902 for (Index
= 0; (Index
< Nbuf
->BlockOpNum
); Index
++) {
903 if (Nbuf
->BlockOp
[Index
].Size
== 0) {
907 if (Current
< *ExtNum
) {
908 ExtFragment
[Current
].Bulk
= Nbuf
->BlockOp
[Index
].Head
;
909 ExtFragment
[Current
].Len
= Nbuf
->BlockOp
[Index
].Size
;
912 return EFI_BUFFER_TOO_SMALL
;
922 Build a net buffer from a list of net buffers.
924 All the fragments will be collected from the list of NEW_BUF and then a new
925 net buffer will be created through NetbufFromExt.
927 @param[in] BufList A List of the net buffer.
928 @param[in] HeadSpace The head space to be reserved.
929 @param[in] HeaderLen The length of the protocol header, This function
930 will pull that number of data into a linear block.
931 @param[in] ExtFree Pointer to the caller provided free function.
932 @param[in] Arg The argument passed to ExtFree when ExtFree is called.
934 @return Pointer to the net buffer built from the list of net
941 IN LIST_ENTRY
*BufList
,
944 IN NET_VECTOR_EXT_FREE ExtFree
,
945 IN VOID
*Arg OPTIONAL
948 NET_FRAGMENT
*Fragment
;
956 //Compute how many blocks are there
960 NET_LIST_FOR_EACH (Entry
, BufList
) {
961 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
962 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
963 FragmentNum
+= Nbuf
->BlockOpNum
;
967 //Allocate and copy block points
969 Fragment
= AllocatePool (sizeof (NET_FRAGMENT
) * FragmentNum
);
971 if (Fragment
== NULL
) {
977 NET_LIST_FOR_EACH (Entry
, BufList
) {
978 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
979 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
981 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
982 if (Nbuf
->BlockOp
[Index
].Size
!= 0) {
983 Fragment
[Current
].Bulk
= Nbuf
->BlockOp
[Index
].Head
;
984 Fragment
[Current
].Len
= Nbuf
->BlockOp
[Index
].Size
;
990 Nbuf
= NetbufFromExt (Fragment
, Current
, HeadSpace
, HeaderLen
, ExtFree
, Arg
);
998 Reserve some space in the header room of the net buffer.
1000 Upon allocation, all the space are in the tail room of the buffer. Call this
1001 function to move some space to the header room. This function is quite limited
1002 in that it can only reserve space from the first block of an empty NET_BUF not
1003 built from the external. But it should be enough for the network stack.
1005 @param[in, out] Nbuf Pointer to the net buffer.
1006 @param[in] Len The length of buffer to be reserved from the header.
1012 IN OUT NET_BUF
*Nbuf
,
1016 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1017 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1019 ASSERT ((Nbuf
->BlockOpNum
== 1) && (Nbuf
->TotalSize
== 0));
1020 ASSERT ((Nbuf
->Vector
->Free
== NULL
) && (Nbuf
->Vector
->Len
>= Len
));
1022 Nbuf
->BlockOp
[0].Head
+= Len
;
1023 Nbuf
->BlockOp
[0].Tail
+= Len
;
1025 ASSERT (Nbuf
->BlockOp
[0].Tail
<= Nbuf
->BlockOp
[0].BlockTail
);
1030 Allocate Len bytes of space from the header or tail of the buffer.
1032 @param[in, out] Nbuf Pointer to the net buffer.
1033 @param[in] Len The length of the buffer to be allocated.
1034 @param[in] FromHead The flag to indicate whether reserve the data
1035 from head (TRUE) or tail (FALSE).
1037 @return Pointer to the first byte of the allocated buffer,
1038 or NULL if there is no sufficient space.
1044 IN OUT NET_BUF
*Nbuf
,
1049 NET_BLOCK_OP
*BlockOp
;
1055 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1056 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1062 // Allocate some space from head. If the buffer is empty,
1063 // allocate from the first block. If it isn't, allocate
1064 // from the first non-empty block, or the block before that.
1066 if (Nbuf
->TotalSize
== 0) {
1069 NetbufGetByte (Nbuf
, 0, &Index
);
1071 if ((NET_HEADSPACE(&(Nbuf
->BlockOp
[Index
])) < Len
) && (Index
> 0)) {
1076 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
1078 if (NET_HEADSPACE (BlockOp
) < Len
) {
1082 BlockOp
->Head
-= Len
;
1083 BlockOp
->Size
+= Len
;
1084 Nbuf
->TotalSize
+= Len
;
1086 return BlockOp
->Head
;
1090 // Allocate some space from the tail. If the buffer is empty,
1091 // allocate from the first block. If it isn't, allocate
1092 // from the last non-empty block, or the block after that.
1094 if (Nbuf
->TotalSize
== 0) {
1097 NetbufGetByte (Nbuf
, Nbuf
->TotalSize
- 1, &Index
);
1099 if ((NET_TAILSPACE(&(Nbuf
->BlockOp
[Index
])) < Len
) &&
1100 (Index
< Nbuf
->BlockOpNum
- 1)) {
1106 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
1108 if (NET_TAILSPACE (BlockOp
) < Len
) {
1112 SavedTail
= BlockOp
->Tail
;
1114 BlockOp
->Tail
+= Len
;
1115 BlockOp
->Size
+= Len
;
1116 Nbuf
->TotalSize
+= Len
;
1124 Trim a single NET_BLOCK by Len bytes from the header or tail.
1126 @param[in, out] BlockOp Pointer to the NET_BLOCK.
1127 @param[in] Len The length of the data to be trimmed.
1128 @param[in] FromHead The flag to indicate whether trim data from head
1129 (TRUE) or tail (FALSE).
1134 IN OUT NET_BLOCK_OP
*BlockOp
,
1139 ASSERT ((BlockOp
!= NULL
) && (BlockOp
->Size
>= Len
));
1141 BlockOp
->Size
-= Len
;
1144 BlockOp
->Head
+= Len
;
1146 BlockOp
->Tail
-= Len
;
1152 Trim Len bytes from the header or tail of the net buffer.
1154 @param[in, out] Nbuf Pointer to the net buffer.
1155 @param[in] Len The length of the data to be trimmed.
1156 @param[in] FromHead The flag to indicate whether trim data from head
1157 (TRUE) or tail (FALSE).
1159 @return Length of the actually trimmed data, which is possible to be less
1160 than Len because the TotalSize of Nbuf is less than Len.
1166 IN OUT NET_BUF
*Nbuf
,
1171 NET_BLOCK_OP
*BlockOp
;
1175 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1177 if (Len
> Nbuf
->TotalSize
) {
1178 Len
= Nbuf
->TotalSize
;
1182 // If FromTail is true, iterate backward. That
1183 // is, init Index to NBuf->BlockNum - 1, and
1184 // decrease it by 1 during each loop. Otherwise,
1185 // iterate forward. That is, init Index to 0, and
1186 // increase it by 1 during each loop.
1189 Nbuf
->TotalSize
-= Len
;
1191 Index
= (FromHead
? 0 : Nbuf
->BlockOpNum
- 1);
1192 BlockOp
= Nbuf
->BlockOp
;
1195 if (BlockOp
[Index
].Size
== 0) {
1196 Index
+= (FromHead
? 1 : -1);
1200 if (Len
> BlockOp
[Index
].Size
) {
1201 Len
-= BlockOp
[Index
].Size
;
1202 Trimmed
+= BlockOp
[Index
].Size
;
1203 NetblockTrim (&BlockOp
[Index
], BlockOp
[Index
].Size
, FromHead
);
1206 NetblockTrim (&BlockOp
[Index
], Len
, FromHead
);
1210 Index
+= (FromHead
? 1 : -1);
1218 Copy Len bytes of data from the specific offset of the net buffer to the
1221 The Len bytes of data may cross the several fragments of the net buffer.
1223 @param[in] Nbuf Pointer to the net buffer.
1224 @param[in] Offset The sequence number of the first byte to copy.
1225 @param[in] Len Length of the data to copy.
1226 @param[in] Dest The destination of the data to copy to.
1228 @return The length of the actual copied data, or 0 if the offset
1229 specified exceeds the total size of net buffer.
1241 NET_BLOCK_OP
*BlockOp
;
1248 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1251 if ((Len
== 0) || (Nbuf
->TotalSize
<= Offset
)) {
1255 if (Nbuf
->TotalSize
- Offset
< Len
) {
1256 Len
= Nbuf
->TotalSize
- Offset
;
1259 BlockOp
= Nbuf
->BlockOp
;
1262 // Skip to the offset. Don't make "Offset-By-One" error here.
1263 // Cur + BLOCK.SIZE is the first sequence number of next block.
1264 // So, (Offset < Cur + BLOCK.SIZE) means that the first byte
1265 // is in the current block. if (Offset == Cur + BLOCK.SIZE), the
1266 // first byte is the next block's first byte.
1270 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1271 if (BlockOp
[Index
].Size
== 0) {
1275 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
1279 Cur
+= BlockOp
[Index
].Size
;
1283 // Cur is the sequence number of the first byte in the block
1284 // Offset - Cur is the number of bytes before first byte to
1285 // to copy in the current block.
1287 Skip
= Offset
- Cur
;
1288 Left
= BlockOp
[Index
].Size
- Skip
;
1291 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Len
);
1295 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Left
);
1303 for (; Index
< Nbuf
->BlockOpNum
; Index
++) {
1304 if (Len
> BlockOp
[Index
].Size
) {
1305 Len
-= BlockOp
[Index
].Size
;
1306 Copied
+= BlockOp
[Index
].Size
;
1308 CopyMem (Dest
, BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1309 Dest
+= BlockOp
[Index
].Size
;
1312 CopyMem (Dest
, BlockOp
[Index
].Head
, Len
);
1322 Initiate the net buffer queue.
1324 @param[in, out] NbufQue Pointer to the net buffer queue to be initialized.
1330 IN OUT NET_BUF_QUEUE
*NbufQue
1333 NbufQue
->Signature
= NET_QUE_SIGNATURE
;
1334 NbufQue
->RefCnt
= 1;
1335 InitializeListHead (&NbufQue
->List
);
1337 InitializeListHead (&NbufQue
->BufList
);
1338 NbufQue
->BufSize
= 0;
1339 NbufQue
->BufNum
= 0;
1344 Allocate and initialize a net buffer queue.
1346 @return Pointer to the allocated net buffer queue, or NULL if the
1347 allocation failed due to resource limit.
1356 NET_BUF_QUEUE
*NbufQue
;
1358 NbufQue
= AllocatePool (sizeof (NET_BUF_QUEUE
));
1359 if (NbufQue
== NULL
) {
1363 NetbufQueInit (NbufQue
);
1370 Free a net buffer queue.
1372 Decrease the reference count of the net buffer queue by one. The real resource
1373 free operation isn't performed until the reference count of the net buffer
1374 queue is decreased to 0.
1376 @param[in] NbufQue Pointer to the net buffer queue to be freed.
1382 IN NET_BUF_QUEUE
*NbufQue
1385 ASSERT (NbufQue
!= NULL
);
1386 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1390 if (NbufQue
->RefCnt
== 0) {
1391 NetbufQueFlush (NbufQue
);
1398 Append a net buffer to the net buffer queue.
1400 @param[in, out] NbufQue Pointer to the net buffer queue.
1401 @param[in, out] Nbuf Pointer to the net buffer to be appended.
1407 IN OUT NET_BUF_QUEUE
*NbufQue
,
1408 IN OUT NET_BUF
*Nbuf
1411 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1412 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1414 InsertTailList (&NbufQue
->BufList
, &Nbuf
->List
);
1416 NbufQue
->BufSize
+= Nbuf
->TotalSize
;
1422 Remove a net buffer from the head in the specific queue and return it.
1424 @param[in, out] NbufQue Pointer to the net buffer queue.
1426 @return Pointer to the net buffer removed from the specific queue,
1427 or NULL if there is no net buffer in the specific queue.
1433 IN OUT NET_BUF_QUEUE
*NbufQue
1438 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1440 if (NbufQue
->BufNum
== 0) {
1444 First
= NET_LIST_USER_STRUCT (NbufQue
->BufList
.ForwardLink
, NET_BUF
, List
);
1446 NetListRemoveHead (&NbufQue
->BufList
);
1448 NbufQue
->BufSize
-= First
->TotalSize
;
1455 Copy Len bytes of data from the net buffer queue at the specific offset to the
1458 The copying operation is the same as NetbufCopy but applies to the net buffer
1459 queue instead of the net buffer.
1461 @param[in] NbufQue Pointer to the net buffer queue.
1462 @param[in] Offset The sequence number of the first byte to copy.
1463 @param[in] Len Length of the data to copy.
1464 @param[out] Dest The destination of the data to copy to.
1466 @return The length of the actual copied data, or 0 if the offset
1467 specified exceeds the total size of net buffer queue.
1473 IN NET_BUF_QUEUE
*NbufQue
,
1486 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1487 ASSERT (Dest
!= NULL
);
1489 if ((Len
== 0) || (NbufQue
->BufSize
<= Offset
)) {
1493 if (NbufQue
->BufSize
- Offset
< Len
) {
1494 Len
= NbufQue
->BufSize
- Offset
;
1498 // skip to the Offset
1503 NET_LIST_FOR_EACH (Entry
, &NbufQue
->BufList
) {
1504 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1506 if (Offset
< Cur
+ Nbuf
->TotalSize
) {
1510 Cur
+= Nbuf
->TotalSize
;
1513 ASSERT (Nbuf
!= NULL
);
1516 // Copy the data in the first buffer.
1518 Skip
= Offset
- Cur
;
1519 Left
= Nbuf
->TotalSize
- Skip
;
1522 return NetbufCopy (Nbuf
, Skip
, Len
, Dest
);
1525 NetbufCopy (Nbuf
, Skip
, Left
, Dest
);
1531 // Iterate over the others
1533 Entry
= Entry
->ForwardLink
;
1535 while ((Len
> 0) && (Entry
!= &NbufQue
->BufList
)) {
1536 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1538 if (Len
> Nbuf
->TotalSize
) {
1539 Len
-= Nbuf
->TotalSize
;
1540 Copied
+= Nbuf
->TotalSize
;
1542 NetbufCopy (Nbuf
, 0, Nbuf
->TotalSize
, Dest
);
1543 Dest
+= Nbuf
->TotalSize
;
1546 NetbufCopy (Nbuf
, 0, Len
, Dest
);
1551 Entry
= Entry
->ForwardLink
;
1559 Trim Len bytes of data from the buffer queue and free any net buffer
1560 that is completely trimmed.
1562 The trimming operation is the same as NetbufTrim but applies to the net buffer
1563 queue instead of the net buffer.
1565 @param[in, out] NbufQue Pointer to the net buffer queue.
1566 @param[in] Len Length of the data to trim.
1568 @return The actual length of the data trimmed.
1574 IN OUT NET_BUF_QUEUE
*NbufQue
,
1583 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1589 if (Len
> NbufQue
->BufSize
) {
1590 Len
= NbufQue
->BufSize
;
1593 NbufQue
->BufSize
-= Len
;
1596 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &NbufQue
->BufList
) {
1597 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1599 if (Len
>= Nbuf
->TotalSize
) {
1600 Trimmed
+= Nbuf
->TotalSize
;
1601 Len
-= Nbuf
->TotalSize
;
1603 RemoveEntryList (Entry
);
1613 Trimmed
+= NetbufTrim (Nbuf
, Len
, NET_BUF_HEAD
);
1623 Flush the net buffer queue.
1625 @param[in, out] NbufQue Pointer to the queue to be flushed.
1631 IN OUT NET_BUF_QUEUE
*NbufQue
1634 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1636 NetbufFreeList (&NbufQue
->BufList
);
1638 NbufQue
->BufNum
= 0;
1639 NbufQue
->BufSize
= 0;
1644 Compute the checksum for a bulk of data.
1646 @param[in] Bulk Pointer to the data.
1647 @param[in] Len Length of the data, in bytes.
1649 @return The computed checksum.
1659 register UINT32 Sum
;
1664 Sum
+= *(UINT16
*) Bulk
;
1670 // Add left-over byte, if any
1673 Sum
+= *(UINT8
*) Bulk
;
1677 // Fold 32-bit sum to 16 bits
1679 while ((Sum
>> 16) != 0) {
1680 Sum
= (Sum
& 0xffff) + (Sum
>> 16);
1684 return (UINT16
) Sum
;
1691 @param[in] Checksum1 The first checksum to be added.
1692 @param[in] Checksum2 The second checksum to be added.
1694 @return The new checksum.
1700 IN UINT16 Checksum1
,
1706 Sum
= Checksum1
+ Checksum2
;
1709 // two UINT16 can only add up to a carry of 1.
1711 if ((Sum
>> 16) != 0) {
1712 Sum
= (Sum
& 0xffff) + 1;
1716 return (UINT16
) Sum
;
1721 Compute the checksum for a NET_BUF.
1723 @param[in] Nbuf Pointer to the net buffer.
1725 @return The computed checksum.
1734 NET_BLOCK_OP
*BlockOp
;
1740 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1744 BlockOp
= Nbuf
->BlockOp
;
1746 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1747 if (BlockOp
[Index
].Size
== 0) {
1751 BlockSum
= NetblockChecksum (BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1753 if ((Offset
& 0x01) != 0) {
1755 // The checksum starts with an odd byte, swap
1756 // the checksum before added to total checksum
1758 BlockSum
= SwapBytes16 (BlockSum
);
1761 TotalSum
= NetAddChecksum (BlockSum
, TotalSum
);
1762 Offset
+= BlockOp
[Index
].Size
;
1770 Compute the checksum for TCP/UDP pseudo header.
1772 Src and Dst are in network byte order, and Len is in host byte order.
1774 @param[in] Src The source address of the packet.
1775 @param[in] Dst The destination address of the packet.
1776 @param[in] Proto The protocol type of the packet.
1777 @param[in] Len The length of the packet.
1779 @return The computed checksum.
1784 NetPseudoHeadChecksum (
1794 // Zero the memory to relieve align problems
1796 ZeroMem (&Hdr
, sizeof (Hdr
));
1800 Hdr
.Protocol
= Proto
;
1801 Hdr
.Len
= HTONS (Len
);
1803 return NetblockChecksum ((UINT8
*) &Hdr
, sizeof (Hdr
));
1807 Compute the checksum for TCP6/UDP6 pseudo header.
1809 Src and Dst are in network byte order, and Len is in host byte order.
1811 @param[in] Src The source address of the packet.
1812 @param[in] Dst The destination address of the packet.
1813 @param[in] NextHeader The protocol type of the packet.
1814 @param[in] Len The length of the packet.
1816 @return The computed checksum.
1820 NetIp6PseudoHeadChecksum (
1821 IN EFI_IPv6_ADDRESS
*Src
,
1822 IN EFI_IPv6_ADDRESS
*Dst
,
1823 IN UINT8 NextHeader
,
1827 NET_IP6_PSEUDO_HDR Hdr
;
1830 // Zero the memory to relieve align problems
1832 ZeroMem (&Hdr
, sizeof (Hdr
));
1834 IP6_COPY_ADDRESS (&Hdr
.SrcIp
, Src
);
1835 IP6_COPY_ADDRESS (&Hdr
.DstIp
, Dst
);
1837 Hdr
.NextHeader
= NextHeader
;
1838 Hdr
.Len
= HTONL (Len
);
1840 return NetblockChecksum ((UINT8
*) &Hdr
, sizeof (Hdr
));