2 Network library functions providing net buffer operation support.
4 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/NetLib.h>
11 #include <Library/BaseLib.h>
12 #include <Library/DebugLib.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/UefiBootServicesTableLib.h>
15 #include <Library/MemoryAllocationLib.h>
18 Allocate and build up the sketch for a NET_BUF.
20 The net buffer allocated has the BlockOpNum's NET_BLOCK_OP, and its associated
21 NET_VECTOR has the BlockNum's NET_BLOCK. But all the NET_BLOCK_OP and
22 NET_BLOCK remain un-initialized.
24 @param[in] BlockNum The number of NET_BLOCK in the vector of net buffer
25 @param[in] BlockOpNum The number of NET_BLOCK_OP in the net buffer
27 @return Pointer to the allocated NET_BUF, or NULL if the
28 allocation failed due to resource limit.
40 ASSERT (BlockOpNum
>= 1);
43 // Allocate three memory blocks.
45 Nbuf
= AllocateZeroPool (NET_BUF_SIZE (BlockOpNum
));
51 Nbuf
->Signature
= NET_BUF_SIGNATURE
;
53 Nbuf
->BlockOpNum
= BlockOpNum
;
54 InitializeListHead (&Nbuf
->List
);
57 Vector
= AllocateZeroPool (NET_VECTOR_SIZE (BlockNum
));
63 Vector
->Signature
= NET_VECTOR_SIGNATURE
;
65 Vector
->BlockNum
= BlockNum
;
66 Nbuf
->Vector
= Vector
;
78 Allocate a single block NET_BUF. Upon allocation, all the
79 free space is in the tail room.
81 @param[in] Len The length of the block.
83 @return Pointer to the allocated NET_BUF, or NULL if the
84 allocation failed due to resource limit.
99 Nbuf
= NetbufAllocStruct (1, 1);
105 Bulk
= AllocatePool (Len
);
111 Vector
= Nbuf
->Vector
;
114 Vector
->Block
[0].Bulk
= Bulk
;
115 Vector
->Block
[0].Len
= Len
;
117 Nbuf
->BlockOp
[0].BlockHead
= Bulk
;
118 Nbuf
->BlockOp
[0].BlockTail
= Bulk
+ Len
;
120 Nbuf
->BlockOp
[0].Head
= Bulk
;
121 Nbuf
->BlockOp
[0].Tail
= Bulk
;
122 Nbuf
->BlockOp
[0].Size
= 0;
134 Decrease the reference count of the net vector by one. The real resource free
135 operation isn't performed until the reference count of the net vector is
138 @param[in] Vector Pointer to the NET_VECTOR to be freed.
143 IN NET_VECTOR
*Vector
148 ASSERT (Vector
!= NULL
);
149 NET_CHECK_SIGNATURE (Vector
, NET_VECTOR_SIGNATURE
);
150 ASSERT (Vector
->RefCnt
> 0);
154 if (Vector
->RefCnt
> 0) {
158 if (Vector
->Free
!= NULL
) {
160 // Call external free function to free the vector if it
161 // isn't NULL. If NET_VECTOR_OWN_FIRST is set, release the
162 // first block since it is allocated by us
164 if ((Vector
->Flag
& NET_VECTOR_OWN_FIRST
) != 0) {
165 gBS
->FreePool (Vector
->Block
[0].Bulk
);
168 Vector
->Free (Vector
->Arg
);
171 // Free each memory block associated with the Vector
173 for (Index
= 0; Index
< Vector
->BlockNum
; Index
++) {
174 gBS
->FreePool (Vector
->Block
[Index
].Bulk
);
182 Free the net buffer and its associated NET_VECTOR.
184 Decrease the reference count of the net buffer by one. Free the associated net
185 vector and itself if the reference count of the net buffer is decreased to 0.
186 The net vector free operation just decrease the reference count of the net
187 vector by one and do the real resource free operation when the reference count
188 of the net vector is 0.
190 @param[in] Nbuf Pointer to the NET_BUF to be freed.
199 ASSERT (Nbuf
!= NULL
);
200 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
201 ASSERT (Nbuf
->RefCnt
> 0);
205 if (Nbuf
->RefCnt
== 0) {
207 // Update Vector only when NBuf is to be released. That is,
208 // all the sharing of Nbuf increse Vector's RefCnt by one
210 NetbufFreeVector (Nbuf
->Vector
);
216 Create a copy of the net buffer that shares the associated net vector.
218 The reference count of the newly created net buffer is set to 1. The reference
219 count of the associated net vector is increased by one.
221 @param[in] Nbuf Pointer to the net buffer to be cloned.
223 @return Pointer to the cloned net buffer, or NULL if the
224 allocation failed due to resource limit.
235 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
237 Clone
= AllocatePool (NET_BUF_SIZE (Nbuf
->BlockOpNum
));
243 Clone
->Signature
= NET_BUF_SIGNATURE
;
245 InitializeListHead (&Clone
->List
);
247 Clone
->Ip
= Nbuf
->Ip
;
248 Clone
->Tcp
= Nbuf
->Tcp
;
250 CopyMem (Clone
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
252 NET_GET_REF (Nbuf
->Vector
);
254 Clone
->Vector
= Nbuf
->Vector
;
255 Clone
->BlockOpNum
= Nbuf
->BlockOpNum
;
256 Clone
->TotalSize
= Nbuf
->TotalSize
;
257 CopyMem (Clone
->BlockOp
, Nbuf
->BlockOp
, sizeof (NET_BLOCK_OP
) * Nbuf
->BlockOpNum
);
263 Create a duplicated copy of the net buffer with data copied and HeadSpace
264 bytes of head space reserved.
266 The duplicated net buffer will allocate its own memory to hold the data of the
269 @param[in] Nbuf Pointer to the net buffer to be duplicated from.
270 @param[in, out] Duplicate Pointer to the net buffer to duplicate to, if
271 NULL a new net buffer is allocated.
272 @param[in] HeadSpace Length of the head space to reserve.
274 @return Pointer to the duplicated net buffer, or NULL if
275 the allocation failed due to resource limit.
282 IN OUT NET_BUF
*Duplicate OPTIONAL
,
288 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
290 if (Duplicate
== NULL
) {
291 Duplicate
= NetbufAlloc (Nbuf
->TotalSize
+ HeadSpace
);
294 if (Duplicate
== NULL
) {
299 // Don't set the IP and TCP head point, since it is most
300 // like that they are pointing to the memory of Nbuf.
302 CopyMem (Duplicate
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
303 NetbufReserve (Duplicate
, HeadSpace
);
305 Dst
= NetbufAllocSpace (Duplicate
, Nbuf
->TotalSize
, NET_BUF_TAIL
);
306 NetbufCopy (Nbuf
, 0, Nbuf
->TotalSize
, Dst
);
312 Free a list of net buffers.
314 @param[in, out] Head Pointer to the head of linked net buffers.
320 IN OUT LIST_ENTRY
*Head
327 Entry
= Head
->ForwardLink
;
329 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Head
) {
330 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
331 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
333 RemoveEntryList (Entry
);
337 ASSERT (IsListEmpty (Head
));
341 Get the index of NET_BLOCK_OP that contains the byte at Offset in the net
344 This can be used to, for example, retrieve the IP header in the packet. It
345 also can be used to get the fragment that contains the byte which is used
346 mainly by the library implementation itself.
348 @param[in] Nbuf Pointer to the net buffer.
349 @param[in] Offset The offset of the byte.
350 @param[out] Index Index of the NET_BLOCK_OP that contains the byte at
353 @return Pointer to the Offset'th byte of data in the net buffer, or NULL
354 if there is no such data in the net buffer.
362 OUT UINT32
*Index OPTIONAL
365 NET_BLOCK_OP
*BlockOp
;
369 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
371 if (Offset
>= Nbuf
->TotalSize
) {
375 BlockOp
= Nbuf
->BlockOp
;
378 for (Loop
= 0; Loop
< Nbuf
->BlockOpNum
; Loop
++) {
379 if (Len
+ BlockOp
[Loop
].Size
<= Offset
) {
380 Len
+= BlockOp
[Loop
].Size
;
388 return BlockOp
[Loop
].Head
+ (Offset
- Len
);
395 Set the NET_BLOCK and corresponding NET_BLOCK_OP in the net buffer and
396 corresponding net vector according to the bulk pointer and bulk length.
398 All the pointers in the Index'th NET_BLOCK and NET_BLOCK_OP are set to the
399 bulk's head and tail respectively. So, this function alone can't be used by
402 @param[in, out] Nbuf Pointer to the net buffer.
403 @param[in] Bulk Pointer to the data.
404 @param[in] Len Length of the bulk data.
405 @param[in] Index The data block index in the net buffer the bulk
406 data should belong to.
411 IN OUT NET_BUF
*Nbuf
,
417 NET_BLOCK_OP
*BlockOp
;
420 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
421 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
422 ASSERT (Index
< Nbuf
->BlockOpNum
);
424 Block
= &(Nbuf
->Vector
->Block
[Index
]);
425 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
428 BlockOp
->BlockHead
= Bulk
;
429 BlockOp
->BlockTail
= Bulk
+ Len
;
430 BlockOp
->Head
= Bulk
;
431 BlockOp
->Tail
= Bulk
+ Len
;
436 Set the NET_BLOCK_OP in the net buffer. The corresponding NET_BLOCK
437 structure is left untouched.
439 Some times, there is no 1:1 relationship between NET_BLOCK and NET_BLOCK_OP.
440 For example, that in NetbufGetFragment.
442 @param[in, out] Nbuf Pointer to the net buffer.
443 @param[in] Bulk Pointer to the data.
444 @param[in] Len Length of the bulk data.
445 @param[in] Index The data block index in the net buffer the bulk
446 data should belong to.
451 IN OUT NET_BUF
*Nbuf
,
457 NET_BLOCK_OP
*BlockOp
;
459 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
460 ASSERT (Index
< Nbuf
->BlockOpNum
);
462 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
463 BlockOp
->BlockHead
= Bulk
;
464 BlockOp
->BlockTail
= Bulk
+ Len
;
465 BlockOp
->Head
= Bulk
;
466 BlockOp
->Tail
= Bulk
+ Len
;
471 Helper function for NetbufGetFragment. NetbufGetFragment may allocate the
472 first block to reserve HeadSpace bytes header space. So it needs to create a
473 new net vector for the first block and can avoid copy for the remaining data
474 by sharing the old net vector.
476 @param[in] Arg Point to the old NET_VECTOR.
481 NetbufGetFragmentFree (
487 Vector
= (NET_VECTOR
*)Arg
;
488 NetbufFreeVector (Vector
);
492 Create a NET_BUF structure which contains Len byte data of Nbuf starting from
495 A new NET_BUF structure will be created but the associated data in NET_VECTOR
496 is shared. This function exists to do IP packet fragmentation.
498 @param[in] Nbuf Pointer to the net buffer to be extracted.
499 @param[in] Offset Starting point of the data to be included in the new
501 @param[in] Len Bytes of data to be included in the new net buffer.
502 @param[in] HeadSpace Bytes of head space to reserve for protocol header.
504 @return Pointer to the cloned net buffer, or NULL if the
505 allocation failed due to resource limit.
519 NET_BLOCK_OP
*BlockOp
;
531 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
533 if ((Len
== 0) || (Offset
+ Len
> Nbuf
->TotalSize
)) {
538 // First find the first and last BlockOp that contains
539 // the valid data, and compute the offset of the first
540 // BlockOp and length of the last BlockOp
542 BlockOp
= Nbuf
->BlockOp
;
545 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
546 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
550 Cur
+= BlockOp
[Index
].Size
;
554 // First is the index of the first BlockOp, FirstSkip is
555 // the offset of the first byte in the first BlockOp.
558 FirstSkip
= Offset
- Cur
;
559 FirstLen
= BlockOp
[Index
].Size
- FirstSkip
;
564 if (Len
> FirstLen
) {
565 Cur
+= BlockOp
[Index
].Size
;
568 for ( ; Index
< Nbuf
->BlockOpNum
; Index
++) {
569 if (Offset
+ Len
<= Cur
+ BlockOp
[Index
].Size
) {
571 LastLen
= Offset
+ Len
- Cur
;
575 Cur
+= BlockOp
[Index
].Size
;
583 ASSERT (Last
>= First
);
584 BlockOpNum
= Last
- First
+ 1;
587 if (HeadSpace
!= 0) {
589 // Allocate an extra block to accommodate the head space.
593 Child
= NetbufAllocStruct (1, BlockOpNum
);
599 FirstBulk
= AllocatePool (HeadSpace
);
601 if (FirstBulk
== NULL
) {
605 Vector
= Child
->Vector
;
606 Vector
->Free
= NetbufGetFragmentFree
;
607 Vector
->Arg
= Nbuf
->Vector
;
608 Vector
->Flag
= NET_VECTOR_OWN_FIRST
;
609 Vector
->Len
= HeadSpace
;
612 // Reserve the head space in the first block
614 NetbufSetBlock (Child
, FirstBulk
, HeadSpace
, 0);
615 Child
->BlockOp
[0].Head
+= HeadSpace
;
616 Child
->BlockOp
[0].Size
= 0;
619 Child
= NetbufAllocStruct (0, BlockOpNum
);
625 Child
->Vector
= Nbuf
->Vector
;
628 NET_GET_REF (Nbuf
->Vector
);
629 Child
->TotalSize
= Len
;
632 // Set all the BlockOp up, the first and last one are special
633 // and need special process.
637 Nbuf
->BlockOp
[First
].Head
+ FirstSkip
,
642 for (Index
= First
+ 1; Index
< Last
; Index
++) {
660 CopyMem (Child
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
670 Build a NET_BUF from external blocks.
672 A new NET_BUF structure will be created from external blocks. Additional block
673 of memory will be allocated to hold reserved HeadSpace bytes of header room
674 and existing HeadLen bytes of header but the external blocks are shared by the
675 net buffer to avoid data copying.
677 @param[in] ExtFragment Pointer to the data block.
678 @param[in] ExtNum The number of the data blocks.
679 @param[in] HeadSpace The head space to be reserved.
680 @param[in] HeadLen The length of the protocol header, This function
681 will pull that number of data into a linear block.
682 @param[in] ExtFree Pointer to the caller provided free function.
683 @param[in] Arg The argument passed to ExtFree when ExtFree is
686 @return Pointer to the net buffer built from the data blocks,
687 or NULL if the allocation failed due to resource
694 IN NET_FRAGMENT
*ExtFragment
,
698 IN NET_VECTOR_EXT_FREE ExtFree
,
699 IN VOID
*Arg OPTIONAL
704 NET_FRAGMENT SavedFragment
;
709 UINT32 FirstBlockLen
;
716 ASSERT ((ExtFragment
!= NULL
) && (ExtNum
> 0) && (ExtFree
!= NULL
));
718 SavedFragment
.Bulk
= NULL
;
719 SavedFragment
.Len
= 0;
731 // No need to consolidate the header if the first block is
732 // longer than the header length or there is only one block.
734 if ((ExtFragment
[0].Len
>= HeadLen
) || (ExtNum
== 1)) {
739 // Allocate an extra block if we need to:
740 // 1. Allocate some header space
741 // 2. aggreate the packet header
743 if ((HeadSpace
!= 0) || (HeadLen
!= 0)) {
744 FirstBlockLen
= HeadLen
+ HeadSpace
;
745 FirstBlock
= AllocatePool (FirstBlockLen
);
747 if (FirstBlock
== NULL
) {
755 // Copy the header to the first block, reduce the NET_BLOCK
756 // to allocate by one for each block that is completely covered
757 // by the first bulk.
761 Header
= FirstBlock
+ HeadSpace
;
763 for (Index
= 0; Index
< ExtNum
; Index
++) {
764 if (Len
>= ExtFragment
[Index
].Len
) {
765 CopyMem (Header
, ExtFragment
[Index
].Bulk
, ExtFragment
[Index
].Len
);
767 Copied
+= ExtFragment
[Index
].Len
;
768 Len
-= ExtFragment
[Index
].Len
;
769 Header
+= ExtFragment
[Index
].Len
;
770 TotalLen
+= ExtFragment
[Index
].Len
;
775 // Increment the index number to point to the next
776 // non-empty fragment.
782 CopyMem (Header
, ExtFragment
[Index
].Bulk
, Len
);
788 // Adjust the block structure to exclude the data copied,
789 // So, the left-over block can be processed as other blocks.
790 // But it must be recovered later. (SavedIndex > 0) always
791 // holds since we don't aggreate the header if the first block
792 // is bigger enough that the header is continuous
795 SavedFragment
= ExtFragment
[Index
];
796 ExtFragment
[Index
].Bulk
+= Len
;
797 ExtFragment
[Index
].Len
-= Len
;
803 Nbuf
= NetbufAllocStruct (BlockNum
, BlockNum
);
809 Vector
= Nbuf
->Vector
;
810 Vector
->Free
= ExtFree
;
812 Vector
->Flag
= ((FirstBlockLen
!= 0) ? NET_VECTOR_OWN_FIRST
: 0);
815 // Set the first block up which may contain
816 // some head space and aggregated header
820 if (FirstBlockLen
!= 0) {
821 NetbufSetBlock (Nbuf
, FirstBlock
, HeadSpace
+ Copied
, 0);
822 Nbuf
->BlockOp
[0].Head
+= HeadSpace
;
823 Nbuf
->BlockOp
[0].Size
= Copied
;
828 for ( ; Index
< ExtNum
; Index
++) {
829 NetbufSetBlock (Nbuf
, ExtFragment
[Index
].Bulk
, ExtFragment
[Index
].Len
, CurBlock
);
830 TotalLen
+= ExtFragment
[Index
].Len
;
834 Vector
->Len
= TotalLen
+ HeadSpace
;
835 Nbuf
->TotalSize
= TotalLen
;
837 if (SavedIndex
!= 0) {
838 ExtFragment
[SavedIndex
] = SavedFragment
;
844 if (FirstBlock
!= NULL
) {
845 FreePool (FirstBlock
);
852 Build a fragment table to contain the fragments in the net buffer. This is the
853 opposite operation of the NetbufFromExt.
855 @param[in] Nbuf Point to the net buffer.
856 @param[in, out] ExtFragment Pointer to the data block.
857 @param[in, out] ExtNum The number of the data blocks.
859 @retval EFI_BUFFER_TOO_SMALL The number of non-empty block is bigger than
861 @retval EFI_SUCCESS Fragment table is built successfully.
868 IN OUT NET_FRAGMENT
*ExtFragment
,
869 IN OUT UINT32
*ExtNum
877 for (Index
= 0; (Index
< Nbuf
->BlockOpNum
); Index
++) {
878 if (Nbuf
->BlockOp
[Index
].Size
== 0) {
882 if (Current
< *ExtNum
) {
883 ExtFragment
[Current
].Bulk
= Nbuf
->BlockOp
[Index
].Head
;
884 ExtFragment
[Current
].Len
= Nbuf
->BlockOp
[Index
].Size
;
887 return EFI_BUFFER_TOO_SMALL
;
896 Build a net buffer from a list of net buffers.
898 All the fragments will be collected from the list of NEW_BUF and then a new
899 net buffer will be created through NetbufFromExt.
901 @param[in] BufList A List of the net buffer.
902 @param[in] HeadSpace The head space to be reserved.
903 @param[in] HeaderLen The length of the protocol header, This function
904 will pull that number of data into a linear block.
905 @param[in] ExtFree Pointer to the caller provided free function.
906 @param[in] Arg The argument passed to ExtFree when ExtFree is called.
908 @return Pointer to the net buffer built from the list of net
915 IN LIST_ENTRY
*BufList
,
918 IN NET_VECTOR_EXT_FREE ExtFree
,
919 IN VOID
*Arg OPTIONAL
922 NET_FRAGMENT
*Fragment
;
930 // Compute how many blocks are there
934 NET_LIST_FOR_EACH (Entry
, BufList
) {
935 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
936 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
937 FragmentNum
+= Nbuf
->BlockOpNum
;
941 // Allocate and copy block points
943 Fragment
= AllocatePool (sizeof (NET_FRAGMENT
) * FragmentNum
);
945 if (Fragment
== NULL
) {
951 NET_LIST_FOR_EACH (Entry
, BufList
) {
952 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
953 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
955 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
956 if (Nbuf
->BlockOp
[Index
].Size
!= 0) {
957 Fragment
[Current
].Bulk
= Nbuf
->BlockOp
[Index
].Head
;
958 Fragment
[Current
].Len
= Nbuf
->BlockOp
[Index
].Size
;
964 Nbuf
= NetbufFromExt (Fragment
, Current
, HeadSpace
, HeaderLen
, ExtFree
, Arg
);
971 Reserve some space in the header room of the net buffer.
973 Upon allocation, all the space are in the tail room of the buffer. Call this
974 function to move some space to the header room. This function is quite limited
975 in that it can only reserve space from the first block of an empty NET_BUF not
976 built from the external. But it should be enough for the network stack.
978 @param[in, out] Nbuf Pointer to the net buffer.
979 @param[in] Len The length of buffer to be reserved from the header.
985 IN OUT NET_BUF
*Nbuf
,
989 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
990 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
992 ASSERT ((Nbuf
->BlockOpNum
== 1) && (Nbuf
->TotalSize
== 0));
993 ASSERT ((Nbuf
->Vector
->Free
== NULL
) && (Nbuf
->Vector
->Len
>= Len
));
995 Nbuf
->BlockOp
[0].Head
+= Len
;
996 Nbuf
->BlockOp
[0].Tail
+= Len
;
998 ASSERT (Nbuf
->BlockOp
[0].Tail
<= Nbuf
->BlockOp
[0].BlockTail
);
1002 Allocate Len bytes of space from the header or tail of the buffer.
1004 @param[in, out] Nbuf Pointer to the net buffer.
1005 @param[in] Len The length of the buffer to be allocated.
1006 @param[in] FromHead The flag to indicate whether reserve the data
1007 from head (TRUE) or tail (FALSE).
1009 @return Pointer to the first byte of the allocated buffer,
1010 or NULL if there is no sufficient space.
1016 IN OUT NET_BUF
*Nbuf
,
1021 NET_BLOCK_OP
*BlockOp
;
1027 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1028 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1034 // Allocate some space from head. If the buffer is empty,
1035 // allocate from the first block. If it isn't, allocate
1036 // from the first non-empty block, or the block before that.
1038 if (Nbuf
->TotalSize
== 0) {
1041 NetbufGetByte (Nbuf
, 0, &Index
);
1043 if ((Index
!= 0) && (NET_HEADSPACE (&(Nbuf
->BlockOp
[Index
])) < Len
)) {
1048 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
1050 if (NET_HEADSPACE (BlockOp
) < Len
) {
1054 BlockOp
->Head
-= Len
;
1055 BlockOp
->Size
+= Len
;
1056 Nbuf
->TotalSize
+= Len
;
1058 return BlockOp
->Head
;
1061 // Allocate some space from the tail. If the buffer is empty,
1062 // allocate from the first block. If it isn't, allocate
1063 // from the last non-empty block, or the block after that.
1065 if (Nbuf
->TotalSize
== 0) {
1068 NetbufGetByte (Nbuf
, Nbuf
->TotalSize
- 1, &Index
);
1070 if ((NET_TAILSPACE (&(Nbuf
->BlockOp
[Index
])) < Len
) &&
1071 (Index
< Nbuf
->BlockOpNum
- 1))
1077 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
1079 if (NET_TAILSPACE (BlockOp
) < Len
) {
1083 SavedTail
= BlockOp
->Tail
;
1085 BlockOp
->Tail
+= Len
;
1086 BlockOp
->Size
+= Len
;
1087 Nbuf
->TotalSize
+= Len
;
1094 Trim a single NET_BLOCK by Len bytes from the header or tail.
1096 @param[in, out] BlockOp Pointer to the NET_BLOCK.
1097 @param[in] Len The length of the data to be trimmed.
1098 @param[in] FromHead The flag to indicate whether trim data from head
1099 (TRUE) or tail (FALSE).
1104 IN OUT NET_BLOCK_OP
*BlockOp
,
1109 ASSERT ((BlockOp
!= NULL
) && (BlockOp
->Size
>= Len
));
1111 BlockOp
->Size
-= Len
;
1114 BlockOp
->Head
+= Len
;
1116 BlockOp
->Tail
-= Len
;
1121 Trim Len bytes from the header or tail of the net buffer.
1123 @param[in, out] Nbuf Pointer to the net buffer.
1124 @param[in] Len The length of the data to be trimmed.
1125 @param[in] FromHead The flag to indicate whether trim data from head
1126 (TRUE) or tail (FALSE).
1128 @return Length of the actually trimmed data, which is possible to be less
1129 than Len because the TotalSize of Nbuf is less than Len.
1135 IN OUT NET_BUF
*Nbuf
,
1140 NET_BLOCK_OP
*BlockOp
;
1144 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1146 if ((Len
== 0) || (Nbuf
->TotalSize
== 0)) {
1150 if (Len
> Nbuf
->TotalSize
) {
1151 Len
= Nbuf
->TotalSize
;
1155 // If FromTail is true, iterate backward. That
1156 // is, init Index to NBuf->BlockNum - 1, and
1157 // decrease it by 1 during each loop. Otherwise,
1158 // iterate forward. That is, init Index to 0, and
1159 // increase it by 1 during each loop.
1162 Nbuf
->TotalSize
-= Len
;
1164 Index
= (FromHead
? 0 : Nbuf
->BlockOpNum
- 1);
1165 BlockOp
= Nbuf
->BlockOp
;
1168 if (BlockOp
[Index
].Size
== 0) {
1169 Index
+= (FromHead
? 1 : -1);
1173 if (Len
> BlockOp
[Index
].Size
) {
1174 Len
-= BlockOp
[Index
].Size
;
1175 Trimmed
+= BlockOp
[Index
].Size
;
1176 NetblockTrim (&BlockOp
[Index
], BlockOp
[Index
].Size
, FromHead
);
1179 NetblockTrim (&BlockOp
[Index
], Len
, FromHead
);
1183 Index
+= (FromHead
? 1 : -1);
1190 Copy Len bytes of data from the specific offset of the net buffer to the
1193 The Len bytes of data may cross the several fragments of the net buffer.
1195 @param[in] Nbuf Pointer to the net buffer.
1196 @param[in] Offset The sequence number of the first byte to copy.
1197 @param[in] Len Length of the data to copy.
1198 @param[in] Dest The destination of the data to copy to.
1200 @return The length of the actual copied data, or 0 if the offset
1201 specified exceeds the total size of net buffer.
1213 NET_BLOCK_OP
*BlockOp
;
1220 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1223 if ((Len
== 0) || (Nbuf
->TotalSize
<= Offset
)) {
1227 if (Nbuf
->TotalSize
- Offset
< Len
) {
1228 Len
= Nbuf
->TotalSize
- Offset
;
1231 BlockOp
= Nbuf
->BlockOp
;
1234 // Skip to the offset. Don't make "Offset-By-One" error here.
1235 // Cur + BLOCK.SIZE is the first sequence number of next block.
1236 // So, (Offset < Cur + BLOCK.SIZE) means that the first byte
1237 // is in the current block. if (Offset == Cur + BLOCK.SIZE), the
1238 // first byte is the next block's first byte.
1242 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1243 if (BlockOp
[Index
].Size
== 0) {
1247 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
1251 Cur
+= BlockOp
[Index
].Size
;
1255 // Cur is the sequence number of the first byte in the block
1256 // Offset - Cur is the number of bytes before first byte to
1257 // to copy in the current block.
1259 Skip
= Offset
- Cur
;
1260 Left
= BlockOp
[Index
].Size
- Skip
;
1263 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Len
);
1267 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Left
);
1275 for ( ; Index
< Nbuf
->BlockOpNum
; Index
++) {
1276 if (Len
> BlockOp
[Index
].Size
) {
1277 Len
-= BlockOp
[Index
].Size
;
1278 Copied
+= BlockOp
[Index
].Size
;
1280 CopyMem (Dest
, BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1281 Dest
+= BlockOp
[Index
].Size
;
1284 CopyMem (Dest
, BlockOp
[Index
].Head
, Len
);
1293 Initiate the net buffer queue.
1295 @param[in, out] NbufQue Pointer to the net buffer queue to be initialized.
1301 IN OUT NET_BUF_QUEUE
*NbufQue
1304 NbufQue
->Signature
= NET_QUE_SIGNATURE
;
1305 NbufQue
->RefCnt
= 1;
1306 InitializeListHead (&NbufQue
->List
);
1308 InitializeListHead (&NbufQue
->BufList
);
1309 NbufQue
->BufSize
= 0;
1310 NbufQue
->BufNum
= 0;
1314 Allocate and initialize a net buffer queue.
1316 @return Pointer to the allocated net buffer queue, or NULL if the
1317 allocation failed due to resource limit.
1326 NET_BUF_QUEUE
*NbufQue
;
1328 NbufQue
= AllocatePool (sizeof (NET_BUF_QUEUE
));
1329 if (NbufQue
== NULL
) {
1333 NetbufQueInit (NbufQue
);
1339 Free a net buffer queue.
1341 Decrease the reference count of the net buffer queue by one. The real resource
1342 free operation isn't performed until the reference count of the net buffer
1343 queue is decreased to 0.
1345 @param[in] NbufQue Pointer to the net buffer queue to be freed.
1351 IN NET_BUF_QUEUE
*NbufQue
1354 ASSERT (NbufQue
!= NULL
);
1355 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1359 if (NbufQue
->RefCnt
== 0) {
1360 NetbufQueFlush (NbufQue
);
1366 Append a net buffer to the net buffer queue.
1368 @param[in, out] NbufQue Pointer to the net buffer queue.
1369 @param[in, out] Nbuf Pointer to the net buffer to be appended.
1375 IN OUT NET_BUF_QUEUE
*NbufQue
,
1376 IN OUT NET_BUF
*Nbuf
1379 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1380 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1382 InsertTailList (&NbufQue
->BufList
, &Nbuf
->List
);
1384 NbufQue
->BufSize
+= Nbuf
->TotalSize
;
1389 Remove a net buffer from the head in the specific queue and return it.
1391 @param[in, out] NbufQue Pointer to the net buffer queue.
1393 @return Pointer to the net buffer removed from the specific queue,
1394 or NULL if there is no net buffer in the specific queue.
1400 IN OUT NET_BUF_QUEUE
*NbufQue
1405 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1407 if (NbufQue
->BufNum
== 0) {
1411 First
= NET_LIST_USER_STRUCT (NbufQue
->BufList
.ForwardLink
, NET_BUF
, List
);
1413 NetListRemoveHead (&NbufQue
->BufList
);
1415 NbufQue
->BufSize
-= First
->TotalSize
;
1421 Copy Len bytes of data from the net buffer queue at the specific offset to the
1424 The copying operation is the same as NetbufCopy but applies to the net buffer
1425 queue instead of the net buffer.
1427 @param[in] NbufQue Pointer to the net buffer queue.
1428 @param[in] Offset The sequence number of the first byte to copy.
1429 @param[in] Len Length of the data to copy.
1430 @param[out] Dest The destination of the data to copy to.
1432 @return The length of the actual copied data, or 0 if the offset
1433 specified exceeds the total size of net buffer queue.
1439 IN NET_BUF_QUEUE
*NbufQue
,
1452 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1453 ASSERT (Dest
!= NULL
);
1455 if ((Len
== 0) || (NbufQue
->BufSize
<= Offset
)) {
1459 if (NbufQue
->BufSize
- Offset
< Len
) {
1460 Len
= NbufQue
->BufSize
- Offset
;
1464 // skip to the Offset
1469 NET_LIST_FOR_EACH (Entry
, &NbufQue
->BufList
) {
1470 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1472 if (Offset
< Cur
+ Nbuf
->TotalSize
) {
1476 Cur
+= Nbuf
->TotalSize
;
1479 ASSERT (Nbuf
!= NULL
);
1482 // Copy the data in the first buffer.
1484 Skip
= Offset
- Cur
;
1485 Left
= Nbuf
->TotalSize
- Skip
;
1488 return NetbufCopy (Nbuf
, Skip
, Len
, Dest
);
1491 NetbufCopy (Nbuf
, Skip
, Left
, Dest
);
1497 // Iterate over the others
1499 Entry
= Entry
->ForwardLink
;
1501 while ((Len
> 0) && (Entry
!= &NbufQue
->BufList
)) {
1502 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1504 if (Len
> Nbuf
->TotalSize
) {
1505 Len
-= Nbuf
->TotalSize
;
1506 Copied
+= Nbuf
->TotalSize
;
1508 NetbufCopy (Nbuf
, 0, Nbuf
->TotalSize
, Dest
);
1509 Dest
+= Nbuf
->TotalSize
;
1511 NetbufCopy (Nbuf
, 0, Len
, Dest
);
1516 Entry
= Entry
->ForwardLink
;
1523 Trim Len bytes of data from the buffer queue and free any net buffer
1524 that is completely trimmed.
1526 The trimming operation is the same as NetbufTrim but applies to the net buffer
1527 queue instead of the net buffer.
1529 @param[in, out] NbufQue Pointer to the net buffer queue.
1530 @param[in] Len Length of the data to trim.
1532 @return The actual length of the data trimmed.
1538 IN OUT NET_BUF_QUEUE
*NbufQue
,
1547 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1553 if (Len
> NbufQue
->BufSize
) {
1554 Len
= NbufQue
->BufSize
;
1557 NbufQue
->BufSize
-= Len
;
1560 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &NbufQue
->BufList
) {
1561 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1563 if (Len
>= Nbuf
->TotalSize
) {
1564 Trimmed
+= Nbuf
->TotalSize
;
1565 Len
-= Nbuf
->TotalSize
;
1567 RemoveEntryList (Entry
);
1576 Trimmed
+= NetbufTrim (Nbuf
, Len
, NET_BUF_HEAD
);
1585 Flush the net buffer queue.
1587 @param[in, out] NbufQue Pointer to the queue to be flushed.
1593 IN OUT NET_BUF_QUEUE
*NbufQue
1596 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1598 NetbufFreeList (&NbufQue
->BufList
);
1600 NbufQue
->BufNum
= 0;
1601 NbufQue
->BufSize
= 0;
1605 Compute the checksum for a bulk of data.
1607 @param[in] Bulk Pointer to the data.
1608 @param[in] Len Length of the data, in bytes.
1610 @return The computed checksum.
1620 register UINT32 Sum
;
1625 // Add left-over byte, if any
1628 Sum
+= *(Bulk
+ Len
- 1);
1632 Sum
+= *(UINT16
*)Bulk
;
1638 // Fold 32-bit sum to 16 bits
1640 while ((Sum
>> 16) != 0) {
1641 Sum
= (Sum
& 0xffff) + (Sum
>> 16);
1650 @param[in] Checksum1 The first checksum to be added.
1651 @param[in] Checksum2 The second checksum to be added.
1653 @return The new checksum.
1659 IN UINT16 Checksum1
,
1665 Sum
= Checksum1
+ Checksum2
;
1668 // two UINT16 can only add up to a carry of 1.
1670 if ((Sum
>> 16) != 0) {
1671 Sum
= (Sum
& 0xffff) + 1;
1678 Compute the checksum for a NET_BUF.
1680 @param[in] Nbuf Pointer to the net buffer.
1682 @return The computed checksum.
1691 NET_BLOCK_OP
*BlockOp
;
1697 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1701 BlockOp
= Nbuf
->BlockOp
;
1703 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1704 if (BlockOp
[Index
].Size
== 0) {
1708 BlockSum
= NetblockChecksum (BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1710 if ((Offset
& 0x01) != 0) {
1712 // The checksum starts with an odd byte, swap
1713 // the checksum before added to total checksum
1715 BlockSum
= SwapBytes16 (BlockSum
);
1718 TotalSum
= NetAddChecksum (BlockSum
, TotalSum
);
1719 Offset
+= BlockOp
[Index
].Size
;
1726 Compute the checksum for TCP/UDP pseudo header.
1728 Src and Dst are in network byte order, and Len is in host byte order.
1730 @param[in] Src The source address of the packet.
1731 @param[in] Dst The destination address of the packet.
1732 @param[in] Proto The protocol type of the packet.
1733 @param[in] Len The length of the packet.
1735 @return The computed checksum.
1740 NetPseudoHeadChecksum (
1750 // Zero the memory to relieve align problems
1752 ZeroMem (&Hdr
, sizeof (Hdr
));
1756 Hdr
.Protocol
= Proto
;
1757 Hdr
.Len
= HTONS (Len
);
1759 return NetblockChecksum ((UINT8
*)&Hdr
, sizeof (Hdr
));
1763 Compute the checksum for TCP6/UDP6 pseudo header.
1765 Src and Dst are in network byte order, and Len is in host byte order.
1767 @param[in] Src The source address of the packet.
1768 @param[in] Dst The destination address of the packet.
1769 @param[in] NextHeader The protocol type of the packet.
1770 @param[in] Len The length of the packet.
1772 @return The computed checksum.
1777 NetIp6PseudoHeadChecksum (
1778 IN EFI_IPv6_ADDRESS
*Src
,
1779 IN EFI_IPv6_ADDRESS
*Dst
,
1780 IN UINT8 NextHeader
,
1784 NET_IP6_PSEUDO_HDR Hdr
;
1787 // Zero the memory to relieve align problems
1789 ZeroMem (&Hdr
, sizeof (Hdr
));
1791 IP6_COPY_ADDRESS (&Hdr
.SrcIp
, Src
);
1792 IP6_COPY_ADDRESS (&Hdr
.DstIp
, Dst
);
1794 Hdr
.NextHeader
= NextHeader
;
1795 Hdr
.Len
= HTONL (Len
);
1797 return NetblockChecksum ((UINT8
*)&Hdr
, sizeof (Hdr
));
1801 The function frees the net buffer which allocated by the IP protocol. It releases
1802 only the net buffer and doesn't call the external free function.
1804 This function should be called after finishing the process of mIpSec->ProcessExt()
1805 for outbound traffic. The (EFI_IPSEC2_PROTOCOL)->ProcessExt() allocates a new
1806 buffer for the ESP, so there needs a function to free the old net buffer.
1808 @param[in] Nbuf The network buffer to be freed.
1812 NetIpSecNetbufFree (
1816 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1817 ASSERT (Nbuf
->RefCnt
> 0);
1821 if (Nbuf
->RefCnt
== 0) {
1823 // Update Vector only when NBuf is to be released. That is,
1824 // all the sharing of Nbuf increse Vector's RefCnt by one
1826 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1827 ASSERT (Nbuf
->Vector
->RefCnt
> 0);
1829 Nbuf
->Vector
->RefCnt
--;
1831 if (Nbuf
->Vector
->RefCnt
> 0) {
1836 // If NET_VECTOR_OWN_FIRST is set, release the first block since it is
1839 if ((Nbuf
->Vector
->Flag
& NET_VECTOR_OWN_FIRST
) != 0) {
1840 FreePool (Nbuf
->Vector
->Block
[0].Bulk
);
1843 FreePool (Nbuf
->Vector
);