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>
19 Allocate and build up the sketch for a NET_BUF.
21 The net buffer allocated has the BlockOpNum's NET_BLOCK_OP, and its associated
22 NET_VECTOR has the BlockNum's NET_BLOCK. But all the NET_BLOCK_OP and
23 NET_BLOCK remain un-initialized.
25 @param[in] BlockNum The number of NET_BLOCK in the vector of net buffer
26 @param[in] BlockOpNum The number of NET_BLOCK_OP in the net buffer
28 @return Pointer to the allocated NET_BUF, or NULL if the
29 allocation failed due to resource limit.
41 ASSERT (BlockOpNum
>= 1);
44 // Allocate three memory blocks.
46 Nbuf
= AllocateZeroPool (NET_BUF_SIZE (BlockOpNum
));
52 Nbuf
->Signature
= NET_BUF_SIGNATURE
;
54 Nbuf
->BlockOpNum
= BlockOpNum
;
55 InitializeListHead (&Nbuf
->List
);
58 Vector
= AllocateZeroPool (NET_VECTOR_SIZE (BlockNum
));
64 Vector
->Signature
= NET_VECTOR_SIGNATURE
;
66 Vector
->BlockNum
= BlockNum
;
67 Nbuf
->Vector
= Vector
;
80 Allocate a single block NET_BUF. Upon allocation, all the
81 free space is in the tail room.
83 @param[in] Len The length of the block.
85 @return Pointer to the allocated NET_BUF, or NULL if the
86 allocation failed due to resource limit.
101 Nbuf
= NetbufAllocStruct (1, 1);
107 Bulk
= AllocatePool (Len
);
113 Vector
= Nbuf
->Vector
;
116 Vector
->Block
[0].Bulk
= Bulk
;
117 Vector
->Block
[0].Len
= Len
;
119 Nbuf
->BlockOp
[0].BlockHead
= Bulk
;
120 Nbuf
->BlockOp
[0].BlockTail
= Bulk
+ Len
;
122 Nbuf
->BlockOp
[0].Head
= Bulk
;
123 Nbuf
->BlockOp
[0].Tail
= Bulk
;
124 Nbuf
->BlockOp
[0].Size
= 0;
136 Decrease the reference count of the net vector by one. The real resource free
137 operation isn't performed until the reference count of the net vector is
140 @param[in] Vector Pointer to the NET_VECTOR to be freed.
145 IN NET_VECTOR
*Vector
150 ASSERT (Vector
!= NULL
);
151 NET_CHECK_SIGNATURE (Vector
, NET_VECTOR_SIGNATURE
);
152 ASSERT (Vector
->RefCnt
> 0);
156 if (Vector
->RefCnt
> 0) {
160 if (Vector
->Free
!= NULL
) {
162 // Call external free function to free the vector if it
163 // isn't NULL. If NET_VECTOR_OWN_FIRST is set, release the
164 // first block since it is allocated by us
166 if ((Vector
->Flag
& NET_VECTOR_OWN_FIRST
) != 0) {
167 gBS
->FreePool (Vector
->Block
[0].Bulk
);
170 Vector
->Free (Vector
->Arg
);
174 // Free each memory block associated with the Vector
176 for (Index
= 0; Index
< Vector
->BlockNum
; Index
++) {
177 gBS
->FreePool (Vector
->Block
[Index
].Bulk
);
186 Free the net buffer and its associated NET_VECTOR.
188 Decrease the reference count of the net buffer by one. Free the associated net
189 vector and itself if the reference count of the net buffer is decreased to 0.
190 The net vector free operation just decrease the reference count of the net
191 vector by one and do the real resource free operation when the reference count
192 of the net vector is 0.
194 @param[in] Nbuf Pointer to the NET_BUF to be freed.
203 ASSERT (Nbuf
!= NULL
);
204 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
205 ASSERT (Nbuf
->RefCnt
> 0);
209 if (Nbuf
->RefCnt
== 0) {
211 // Update Vector only when NBuf is to be released. That is,
212 // all the sharing of Nbuf increse Vector's RefCnt by one
214 NetbufFreeVector (Nbuf
->Vector
);
221 Create a copy of the net buffer that shares the associated net vector.
223 The reference count of the newly created net buffer is set to 1. The reference
224 count of the associated net vector is increased by one.
226 @param[in] Nbuf Pointer to the net buffer to be cloned.
228 @return Pointer to the cloned net buffer, or NULL if the
229 allocation failed due to resource limit.
240 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
242 Clone
= AllocatePool (NET_BUF_SIZE (Nbuf
->BlockOpNum
));
248 Clone
->Signature
= NET_BUF_SIGNATURE
;
250 InitializeListHead (&Clone
->List
);
252 Clone
->Ip
= Nbuf
->Ip
;
253 Clone
->Tcp
= Nbuf
->Tcp
;
255 CopyMem (Clone
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
257 NET_GET_REF (Nbuf
->Vector
);
259 Clone
->Vector
= Nbuf
->Vector
;
260 Clone
->BlockOpNum
= Nbuf
->BlockOpNum
;
261 Clone
->TotalSize
= Nbuf
->TotalSize
;
262 CopyMem (Clone
->BlockOp
, Nbuf
->BlockOp
, sizeof (NET_BLOCK_OP
) * Nbuf
->BlockOpNum
);
269 Create a duplicated copy of the net buffer with data copied and HeadSpace
270 bytes of head space reserved.
272 The duplicated net buffer will allocate its own memory to hold the data of the
275 @param[in] Nbuf Pointer to the net buffer to be duplicated from.
276 @param[in, out] Duplicate Pointer to the net buffer to duplicate to, if
277 NULL a new net buffer is allocated.
278 @param[in] HeadSpace Length of the head space to reserve.
280 @return Pointer to the duplicated net buffer, or NULL if
281 the allocation failed due to resource limit.
288 IN OUT NET_BUF
*Duplicate OPTIONAL
,
294 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
296 if (Duplicate
== NULL
) {
297 Duplicate
= NetbufAlloc (Nbuf
->TotalSize
+ HeadSpace
);
300 if (Duplicate
== NULL
) {
305 // Don't set the IP and TCP head point, since it is most
306 // like that they are pointing to the memory of Nbuf.
308 CopyMem (Duplicate
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
309 NetbufReserve (Duplicate
, HeadSpace
);
311 Dst
= NetbufAllocSpace (Duplicate
, Nbuf
->TotalSize
, NET_BUF_TAIL
);
312 NetbufCopy (Nbuf
, 0, Nbuf
->TotalSize
, Dst
);
319 Free a list of net buffers.
321 @param[in, out] Head Pointer to the head of linked net buffers.
327 IN OUT LIST_ENTRY
*Head
334 Entry
= Head
->ForwardLink
;
336 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Head
) {
337 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
338 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
340 RemoveEntryList (Entry
);
344 ASSERT (IsListEmpty (Head
));
349 Get the index of NET_BLOCK_OP that contains the byte at Offset in the net
352 This can be used to, for example, retrieve the IP header in the packet. It
353 also can be used to get the fragment that contains the byte which is used
354 mainly by the library implementation itself.
356 @param[in] Nbuf Pointer to the net buffer.
357 @param[in] Offset The offset of the byte.
358 @param[out] Index Index of the NET_BLOCK_OP that contains the byte at
361 @return Pointer to the Offset'th byte of data in the net buffer, or NULL
362 if there is no such data in the net buffer.
370 OUT UINT32
*Index OPTIONAL
373 NET_BLOCK_OP
*BlockOp
;
377 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
379 if (Offset
>= Nbuf
->TotalSize
) {
383 BlockOp
= Nbuf
->BlockOp
;
386 for (Loop
= 0; Loop
< Nbuf
->BlockOpNum
; Loop
++) {
388 if (Len
+ BlockOp
[Loop
].Size
<= Offset
) {
389 Len
+= BlockOp
[Loop
].Size
;
397 return BlockOp
[Loop
].Head
+ (Offset
- Len
);
406 Set the NET_BLOCK and corresponding NET_BLOCK_OP in the net buffer and
407 corresponding net vector according to the bulk pointer and bulk length.
409 All the pointers in the Index'th NET_BLOCK and NET_BLOCK_OP are set to the
410 bulk's head and tail respectively. So, this function alone can't be used by
413 @param[in, out] Nbuf Pointer to the net buffer.
414 @param[in] Bulk Pointer to the data.
415 @param[in] Len Length of the bulk data.
416 @param[in] Index The data block index in the net buffer the bulk
417 data should belong to.
422 IN OUT NET_BUF
*Nbuf
,
428 NET_BLOCK_OP
*BlockOp
;
431 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
432 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
433 ASSERT (Index
< Nbuf
->BlockOpNum
);
435 Block
= &(Nbuf
->Vector
->Block
[Index
]);
436 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
439 BlockOp
->BlockHead
= Bulk
;
440 BlockOp
->BlockTail
= Bulk
+ Len
;
441 BlockOp
->Head
= Bulk
;
442 BlockOp
->Tail
= Bulk
+ Len
;
449 Set the NET_BLOCK_OP in the net buffer. The corresponding NET_BLOCK
450 structure is left untouched.
452 Some times, there is no 1:1 relationship between NET_BLOCK and NET_BLOCK_OP.
453 For example, that in NetbufGetFragment.
455 @param[in, out] Nbuf Pointer to the net buffer.
456 @param[in] Bulk Pointer to the data.
457 @param[in] Len Length of the bulk data.
458 @param[in] Index The data block index in the net buffer the bulk
459 data should belong to.
464 IN OUT NET_BUF
*Nbuf
,
470 NET_BLOCK_OP
*BlockOp
;
472 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
473 ASSERT (Index
< Nbuf
->BlockOpNum
);
475 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
476 BlockOp
->BlockHead
= Bulk
;
477 BlockOp
->BlockTail
= Bulk
+ Len
;
478 BlockOp
->Head
= Bulk
;
479 BlockOp
->Tail
= Bulk
+ Len
;
485 Helper function for NetbufGetFragment. NetbufGetFragment may allocate the
486 first block to reserve HeadSpace bytes header space. So it needs to create a
487 new net vector for the first block and can avoid copy for the remaining data
488 by sharing the old net vector.
490 @param[in] Arg Point to the old NET_VECTOR.
495 NetbufGetFragmentFree (
501 Vector
= (NET_VECTOR
*)Arg
;
502 NetbufFreeVector (Vector
);
507 Create a NET_BUF structure which contains Len byte data of Nbuf starting from
510 A new NET_BUF structure will be created but the associated data in NET_VECTOR
511 is shared. This function exists to do IP packet fragmentation.
513 @param[in] Nbuf Pointer to the net buffer to be extracted.
514 @param[in] Offset Starting point of the data to be included in the new
516 @param[in] Len Bytes of data to be included in the new net buffer.
517 @param[in] HeadSpace Bytes of head space to reserve for protocol header.
519 @return Pointer to the cloned net buffer, or NULL if the
520 allocation failed due to resource limit.
534 NET_BLOCK_OP
*BlockOp
;
546 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
548 if ((Len
== 0) || (Offset
+ Len
> Nbuf
->TotalSize
)) {
553 // First find the first and last BlockOp that contains
554 // the valid data, and compute the offset of the first
555 // BlockOp and length of the last BlockOp
557 BlockOp
= Nbuf
->BlockOp
;
560 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
561 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
565 Cur
+= BlockOp
[Index
].Size
;
569 // First is the index of the first BlockOp, FirstSkip is
570 // the offset of the first byte in the first BlockOp.
573 FirstSkip
= Offset
- Cur
;
574 FirstLen
= BlockOp
[Index
].Size
- FirstSkip
;
579 if (Len
> FirstLen
) {
580 Cur
+= BlockOp
[Index
].Size
;
583 for (; Index
< Nbuf
->BlockOpNum
; Index
++) {
584 if (Offset
+ Len
<= Cur
+ BlockOp
[Index
].Size
) {
586 LastLen
= Offset
+ Len
- Cur
;
590 Cur
+= BlockOp
[Index
].Size
;
599 ASSERT (Last
>= First
);
600 BlockOpNum
= Last
- First
+ 1;
603 if (HeadSpace
!= 0) {
605 // Allocate an extra block to accomdate the head space.
609 Child
= NetbufAllocStruct (1, BlockOpNum
);
615 FirstBulk
= AllocatePool (HeadSpace
);
617 if (FirstBulk
== NULL
) {
621 Vector
= Child
->Vector
;
622 Vector
->Free
= NetbufGetFragmentFree
;
623 Vector
->Arg
= Nbuf
->Vector
;
624 Vector
->Flag
= NET_VECTOR_OWN_FIRST
;
625 Vector
->Len
= HeadSpace
;
628 // Reserve the head space in the first block
630 NetbufSetBlock (Child
, FirstBulk
, HeadSpace
, 0);
631 Child
->BlockOp
[0].Head
+= HeadSpace
;
632 Child
->BlockOp
[0].Size
= 0;
636 Child
= NetbufAllocStruct (0, BlockOpNum
);
642 Child
->Vector
= Nbuf
->Vector
;
645 NET_GET_REF (Nbuf
->Vector
);
646 Child
->TotalSize
= Len
;
649 // Set all the BlockOp up, the first and last one are special
650 // and need special process.
654 Nbuf
->BlockOp
[First
].Head
+ FirstSkip
,
659 for (Index
= First
+ 1; Index
< Last
; Index
++) {
677 CopyMem (Child
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
689 Build a NET_BUF from external blocks.
691 A new NET_BUF structure will be created from external blocks. Additional block
692 of memory will be allocated to hold reserved HeadSpace bytes of header room
693 and existing HeadLen bytes of header but the external blocks are shared by the
694 net buffer to avoid data copying.
696 @param[in] ExtFragment Pointer to the data block.
697 @param[in] ExtNum The number of the data blocks.
698 @param[in] HeadSpace The head space to be reserved.
699 @param[in] HeadLen The length of the protocol header, This function
700 will pull that number of data into a linear block.
701 @param[in] ExtFree Pointer to the caller provided free function.
702 @param[in] Arg The argument passed to ExtFree when ExtFree is
705 @return Pointer to the net buffer built from the data blocks,
706 or NULL if the allocation failed due to resource
713 IN NET_FRAGMENT
*ExtFragment
,
717 IN NET_VECTOR_EXT_FREE ExtFree
,
718 IN VOID
*Arg OPTIONAL
723 NET_FRAGMENT SavedFragment
;
728 UINT32 FirstBlockLen
;
735 ASSERT ((ExtFragment
!= NULL
) && (ExtNum
> 0) && (ExtFree
!= NULL
));
737 SavedFragment
.Bulk
= NULL
;
738 SavedFragment
.Len
= 0;
750 // No need to consolidate the header if the first block is
751 // longer than the header length or there is only one block.
753 if ((ExtFragment
[0].Len
>= HeadLen
) || (ExtNum
== 1)) {
758 // Allocate an extra block if we need to:
759 // 1. Allocate some header space
760 // 2. aggreate the packet header
762 if ((HeadSpace
!= 0) || (HeadLen
!= 0)) {
763 FirstBlockLen
= HeadLen
+ HeadSpace
;
764 FirstBlock
= AllocatePool (FirstBlockLen
);
766 if (FirstBlock
== NULL
) {
774 // Copy the header to the first block, reduce the NET_BLOCK
775 // to allocate by one for each block that is completely covered
776 // by the first bulk.
780 Header
= FirstBlock
+ HeadSpace
;
782 for (Index
= 0; Index
< ExtNum
; Index
++) {
783 if (Len
>= ExtFragment
[Index
].Len
) {
784 CopyMem (Header
, ExtFragment
[Index
].Bulk
, ExtFragment
[Index
].Len
);
786 Copied
+= ExtFragment
[Index
].Len
;
787 Len
-= ExtFragment
[Index
].Len
;
788 Header
+= ExtFragment
[Index
].Len
;
789 TotalLen
+= ExtFragment
[Index
].Len
;
794 // Increament the index number to point to the next
795 // non-empty fragment.
802 CopyMem (Header
, ExtFragment
[Index
].Bulk
, Len
);
808 // Adjust the block structure to exclude the data copied,
809 // So, the left-over block can be processed as other blocks.
810 // But it must be recovered later. (SavedIndex > 0) always
811 // holds since we don't aggreate the header if the first block
812 // is bigger enough that the header is continuous
815 SavedFragment
= ExtFragment
[Index
];
816 ExtFragment
[Index
].Bulk
+= Len
;
817 ExtFragment
[Index
].Len
-= Len
;
823 Nbuf
= NetbufAllocStruct (BlockNum
, BlockNum
);
829 Vector
= Nbuf
->Vector
;
830 Vector
->Free
= ExtFree
;
832 Vector
->Flag
= ((FirstBlockLen
!= 0) ? NET_VECTOR_OWN_FIRST
: 0);
835 // Set the first block up which may contain
836 // some head space and aggregated header
840 if (FirstBlockLen
!= 0) {
841 NetbufSetBlock (Nbuf
, FirstBlock
, HeadSpace
+ Copied
, 0);
842 Nbuf
->BlockOp
[0].Head
+= HeadSpace
;
843 Nbuf
->BlockOp
[0].Size
= Copied
;
848 for (; Index
< ExtNum
; Index
++) {
849 NetbufSetBlock (Nbuf
, ExtFragment
[Index
].Bulk
, ExtFragment
[Index
].Len
, CurBlock
);
850 TotalLen
+= ExtFragment
[Index
].Len
;
854 Vector
->Len
= TotalLen
+ HeadSpace
;
855 Nbuf
->TotalSize
= TotalLen
;
857 if (SavedIndex
!= 0) {
858 ExtFragment
[SavedIndex
] = SavedFragment
;
864 if (FirstBlock
!= NULL
) {
865 FreePool (FirstBlock
);
872 Build a fragment table to contain the fragments in the net buffer. This is the
873 opposite operation of the NetbufFromExt.
875 @param[in] Nbuf Point to the net buffer.
876 @param[in, out] ExtFragment Pointer to the data block.
877 @param[in, out] ExtNum The number of the data blocks.
879 @retval EFI_BUFFER_TOO_SMALL The number of non-empty block is bigger than
881 @retval EFI_SUCCESS Fragment table is built successfully.
888 IN OUT NET_FRAGMENT
*ExtFragment
,
889 IN OUT UINT32
*ExtNum
897 for (Index
= 0; (Index
< Nbuf
->BlockOpNum
); Index
++) {
898 if (Nbuf
->BlockOp
[Index
].Size
== 0) {
902 if (Current
< *ExtNum
) {
903 ExtFragment
[Current
].Bulk
= Nbuf
->BlockOp
[Index
].Head
;
904 ExtFragment
[Current
].Len
= Nbuf
->BlockOp
[Index
].Size
;
907 return EFI_BUFFER_TOO_SMALL
;
917 Build a net buffer from a list of net buffers.
919 All the fragments will be collected from the list of NEW_BUF and then a new
920 net buffer will be created through NetbufFromExt.
922 @param[in] BufList A List of the net buffer.
923 @param[in] HeadSpace The head space to be reserved.
924 @param[in] HeaderLen The length of the protocol header, This function
925 will pull that number of data into a linear block.
926 @param[in] ExtFree Pointer to the caller provided free function.
927 @param[in] Arg The argument passed to ExtFree when ExtFree is called.
929 @return Pointer to the net buffer built from the list of net
936 IN LIST_ENTRY
*BufList
,
939 IN NET_VECTOR_EXT_FREE ExtFree
,
940 IN VOID
*Arg OPTIONAL
943 NET_FRAGMENT
*Fragment
;
951 //Compute how many blocks are there
955 NET_LIST_FOR_EACH (Entry
, BufList
) {
956 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
957 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
958 FragmentNum
+= Nbuf
->BlockOpNum
;
962 //Allocate and copy block points
964 Fragment
= AllocatePool (sizeof (NET_FRAGMENT
) * FragmentNum
);
966 if (Fragment
== NULL
) {
972 NET_LIST_FOR_EACH (Entry
, BufList
) {
973 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
974 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
976 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
977 if (Nbuf
->BlockOp
[Index
].Size
!= 0) {
978 Fragment
[Current
].Bulk
= Nbuf
->BlockOp
[Index
].Head
;
979 Fragment
[Current
].Len
= Nbuf
->BlockOp
[Index
].Size
;
985 Nbuf
= NetbufFromExt (Fragment
, Current
, HeadSpace
, HeaderLen
, ExtFree
, Arg
);
993 Reserve some space in the header room of the net buffer.
995 Upon allocation, all the space are in the tail room of the buffer. Call this
996 function to move some space to the header room. This function is quite limited
997 in that it can only reserve space from the first block of an empty NET_BUF not
998 built from the external. But it should be enough for the network stack.
1000 @param[in, out] Nbuf Pointer to the net buffer.
1001 @param[in] Len The length of buffer to be reserved from the header.
1007 IN OUT NET_BUF
*Nbuf
,
1011 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1012 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1014 ASSERT ((Nbuf
->BlockOpNum
== 1) && (Nbuf
->TotalSize
== 0));
1015 ASSERT ((Nbuf
->Vector
->Free
== NULL
) && (Nbuf
->Vector
->Len
>= Len
));
1017 Nbuf
->BlockOp
[0].Head
+= Len
;
1018 Nbuf
->BlockOp
[0].Tail
+= Len
;
1020 ASSERT (Nbuf
->BlockOp
[0].Tail
<= Nbuf
->BlockOp
[0].BlockTail
);
1025 Allocate Len bytes of space from the header or tail of the buffer.
1027 @param[in, out] Nbuf Pointer to the net buffer.
1028 @param[in] Len The length of the buffer to be allocated.
1029 @param[in] FromHead The flag to indicate whether reserve the data
1030 from head (TRUE) or tail (FALSE).
1032 @return Pointer to the first byte of the allocated buffer,
1033 or NULL if there is no sufficient space.
1039 IN OUT NET_BUF
*Nbuf
,
1044 NET_BLOCK_OP
*BlockOp
;
1050 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1051 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1057 // Allocate some space from head. If the buffer is empty,
1058 // allocate from the first block. If it isn't, allocate
1059 // from the first non-empty block, or the block before that.
1061 if (Nbuf
->TotalSize
== 0) {
1064 NetbufGetByte (Nbuf
, 0, &Index
);
1066 if ((NET_HEADSPACE(&(Nbuf
->BlockOp
[Index
])) < Len
) && (Index
> 0)) {
1071 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
1073 if (NET_HEADSPACE (BlockOp
) < Len
) {
1077 BlockOp
->Head
-= Len
;
1078 BlockOp
->Size
+= Len
;
1079 Nbuf
->TotalSize
+= Len
;
1081 return BlockOp
->Head
;
1085 // Allocate some space from the tail. If the buffer is empty,
1086 // allocate from the first block. If it isn't, allocate
1087 // from the last non-empty block, or the block after that.
1089 if (Nbuf
->TotalSize
== 0) {
1092 NetbufGetByte (Nbuf
, Nbuf
->TotalSize
- 1, &Index
);
1094 if ((NET_TAILSPACE(&(Nbuf
->BlockOp
[Index
])) < Len
) &&
1095 (Index
< Nbuf
->BlockOpNum
- 1)) {
1101 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
1103 if (NET_TAILSPACE (BlockOp
) < Len
) {
1107 SavedTail
= BlockOp
->Tail
;
1109 BlockOp
->Tail
+= Len
;
1110 BlockOp
->Size
+= Len
;
1111 Nbuf
->TotalSize
+= Len
;
1119 Trim a single NET_BLOCK by Len bytes from the header or tail.
1121 @param[in, out] BlockOp Pointer to the NET_BLOCK.
1122 @param[in] Len The length of the data to be trimmed.
1123 @param[in] FromHead The flag to indicate whether trim data from head
1124 (TRUE) or tail (FALSE).
1129 IN OUT NET_BLOCK_OP
*BlockOp
,
1134 ASSERT ((BlockOp
!= NULL
) && (BlockOp
->Size
>= Len
));
1136 BlockOp
->Size
-= Len
;
1139 BlockOp
->Head
+= Len
;
1141 BlockOp
->Tail
-= Len
;
1147 Trim Len bytes from the header or tail of the net buffer.
1149 @param[in, out] Nbuf Pointer to the net buffer.
1150 @param[in] Len The length of the data to be trimmed.
1151 @param[in] FromHead The flag to indicate whether trim data from head
1152 (TRUE) or tail (FALSE).
1154 @return Length of the actually trimmed data, which is possible to be less
1155 than Len because the TotalSize of Nbuf is less than Len.
1161 IN OUT NET_BUF
*Nbuf
,
1166 NET_BLOCK_OP
*BlockOp
;
1170 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1172 if (Len
== 0 || Nbuf
->TotalSize
== 0) {
1176 if (Len
> Nbuf
->TotalSize
) {
1177 Len
= Nbuf
->TotalSize
;
1181 // If FromTail is true, iterate backward. That
1182 // is, init Index to NBuf->BlockNum - 1, and
1183 // decrease it by 1 during each loop. Otherwise,
1184 // iterate forward. That is, init Index to 0, and
1185 // increase it by 1 during each loop.
1188 Nbuf
->TotalSize
-= Len
;
1190 Index
= (FromHead
? 0 : Nbuf
->BlockOpNum
- 1);
1191 BlockOp
= Nbuf
->BlockOp
;
1194 if (BlockOp
[Index
].Size
== 0) {
1195 Index
+= (FromHead
? 1 : -1);
1199 if (Len
> BlockOp
[Index
].Size
) {
1200 Len
-= BlockOp
[Index
].Size
;
1201 Trimmed
+= BlockOp
[Index
].Size
;
1202 NetblockTrim (&BlockOp
[Index
], BlockOp
[Index
].Size
, FromHead
);
1205 NetblockTrim (&BlockOp
[Index
], Len
, FromHead
);
1209 Index
+= (FromHead
? 1 : -1);
1217 Copy Len bytes of data from the specific offset of the net buffer to the
1220 The Len bytes of data may cross the several fragments of the net buffer.
1222 @param[in] Nbuf Pointer to the net buffer.
1223 @param[in] Offset The sequence number of the first byte to copy.
1224 @param[in] Len Length of the data to copy.
1225 @param[in] Dest The destination of the data to copy to.
1227 @return The length of the actual copied data, or 0 if the offset
1228 specified exceeds the total size of net buffer.
1240 NET_BLOCK_OP
*BlockOp
;
1247 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1250 if ((Len
== 0) || (Nbuf
->TotalSize
<= Offset
)) {
1254 if (Nbuf
->TotalSize
- Offset
< Len
) {
1255 Len
= Nbuf
->TotalSize
- Offset
;
1258 BlockOp
= Nbuf
->BlockOp
;
1261 // Skip to the offset. Don't make "Offset-By-One" error here.
1262 // Cur + BLOCK.SIZE is the first sequence number of next block.
1263 // So, (Offset < Cur + BLOCK.SIZE) means that the first byte
1264 // is in the current block. if (Offset == Cur + BLOCK.SIZE), the
1265 // first byte is the next block's first byte.
1269 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1270 if (BlockOp
[Index
].Size
== 0) {
1274 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
1278 Cur
+= BlockOp
[Index
].Size
;
1282 // Cur is the sequence number of the first byte in the block
1283 // Offset - Cur is the number of bytes before first byte to
1284 // to copy in the current block.
1286 Skip
= Offset
- Cur
;
1287 Left
= BlockOp
[Index
].Size
- Skip
;
1290 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Len
);
1294 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Left
);
1302 for (; Index
< Nbuf
->BlockOpNum
; Index
++) {
1303 if (Len
> BlockOp
[Index
].Size
) {
1304 Len
-= BlockOp
[Index
].Size
;
1305 Copied
+= BlockOp
[Index
].Size
;
1307 CopyMem (Dest
, BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1308 Dest
+= BlockOp
[Index
].Size
;
1311 CopyMem (Dest
, BlockOp
[Index
].Head
, Len
);
1321 Initiate the net buffer queue.
1323 @param[in, out] NbufQue Pointer to the net buffer queue to be initialized.
1329 IN OUT NET_BUF_QUEUE
*NbufQue
1332 NbufQue
->Signature
= NET_QUE_SIGNATURE
;
1333 NbufQue
->RefCnt
= 1;
1334 InitializeListHead (&NbufQue
->List
);
1336 InitializeListHead (&NbufQue
->BufList
);
1337 NbufQue
->BufSize
= 0;
1338 NbufQue
->BufNum
= 0;
1343 Allocate and initialize a net buffer queue.
1345 @return Pointer to the allocated net buffer queue, or NULL if the
1346 allocation failed due to resource limit.
1355 NET_BUF_QUEUE
*NbufQue
;
1357 NbufQue
= AllocatePool (sizeof (NET_BUF_QUEUE
));
1358 if (NbufQue
== NULL
) {
1362 NetbufQueInit (NbufQue
);
1369 Free a net buffer queue.
1371 Decrease the reference count of the net buffer queue by one. The real resource
1372 free operation isn't performed until the reference count of the net buffer
1373 queue is decreased to 0.
1375 @param[in] NbufQue Pointer to the net buffer queue to be freed.
1381 IN NET_BUF_QUEUE
*NbufQue
1384 ASSERT (NbufQue
!= NULL
);
1385 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1389 if (NbufQue
->RefCnt
== 0) {
1390 NetbufQueFlush (NbufQue
);
1397 Append a net buffer to the net buffer queue.
1399 @param[in, out] NbufQue Pointer to the net buffer queue.
1400 @param[in, out] Nbuf Pointer to the net buffer to be appended.
1406 IN OUT NET_BUF_QUEUE
*NbufQue
,
1407 IN OUT NET_BUF
*Nbuf
1410 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1411 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1413 InsertTailList (&NbufQue
->BufList
, &Nbuf
->List
);
1415 NbufQue
->BufSize
+= Nbuf
->TotalSize
;
1421 Remove a net buffer from the head in the specific queue and return it.
1423 @param[in, out] NbufQue Pointer to the net buffer queue.
1425 @return Pointer to the net buffer removed from the specific queue,
1426 or NULL if there is no net buffer in the specific queue.
1432 IN OUT NET_BUF_QUEUE
*NbufQue
1437 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1439 if (NbufQue
->BufNum
== 0) {
1443 First
= NET_LIST_USER_STRUCT (NbufQue
->BufList
.ForwardLink
, NET_BUF
, List
);
1445 NetListRemoveHead (&NbufQue
->BufList
);
1447 NbufQue
->BufSize
-= First
->TotalSize
;
1454 Copy Len bytes of data from the net buffer queue at the specific offset to the
1457 The copying operation is the same as NetbufCopy but applies to the net buffer
1458 queue instead of the net buffer.
1460 @param[in] NbufQue Pointer to the net buffer queue.
1461 @param[in] Offset The sequence number of the first byte to copy.
1462 @param[in] Len Length of the data to copy.
1463 @param[out] Dest The destination of the data to copy to.
1465 @return The length of the actual copied data, or 0 if the offset
1466 specified exceeds the total size of net buffer queue.
1472 IN NET_BUF_QUEUE
*NbufQue
,
1485 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1486 ASSERT (Dest
!= NULL
);
1488 if ((Len
== 0) || (NbufQue
->BufSize
<= Offset
)) {
1492 if (NbufQue
->BufSize
- Offset
< Len
) {
1493 Len
= NbufQue
->BufSize
- Offset
;
1497 // skip to the Offset
1502 NET_LIST_FOR_EACH (Entry
, &NbufQue
->BufList
) {
1503 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1505 if (Offset
< Cur
+ Nbuf
->TotalSize
) {
1509 Cur
+= Nbuf
->TotalSize
;
1512 ASSERT (Nbuf
!= NULL
);
1515 // Copy the data in the first buffer.
1517 Skip
= Offset
- Cur
;
1518 Left
= Nbuf
->TotalSize
- Skip
;
1521 return NetbufCopy (Nbuf
, Skip
, Len
, Dest
);
1524 NetbufCopy (Nbuf
, Skip
, Left
, Dest
);
1530 // Iterate over the others
1532 Entry
= Entry
->ForwardLink
;
1534 while ((Len
> 0) && (Entry
!= &NbufQue
->BufList
)) {
1535 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1537 if (Len
> Nbuf
->TotalSize
) {
1538 Len
-= Nbuf
->TotalSize
;
1539 Copied
+= Nbuf
->TotalSize
;
1541 NetbufCopy (Nbuf
, 0, Nbuf
->TotalSize
, Dest
);
1542 Dest
+= Nbuf
->TotalSize
;
1545 NetbufCopy (Nbuf
, 0, Len
, Dest
);
1550 Entry
= Entry
->ForwardLink
;
1558 Trim Len bytes of data from the buffer queue and free any net buffer
1559 that is completely trimmed.
1561 The trimming operation is the same as NetbufTrim but applies to the net buffer
1562 queue instead of the net buffer.
1564 @param[in, out] NbufQue Pointer to the net buffer queue.
1565 @param[in] Len Length of the data to trim.
1567 @return The actual length of the data trimmed.
1573 IN OUT NET_BUF_QUEUE
*NbufQue
,
1582 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1588 if (Len
> NbufQue
->BufSize
) {
1589 Len
= NbufQue
->BufSize
;
1592 NbufQue
->BufSize
-= Len
;
1595 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &NbufQue
->BufList
) {
1596 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1598 if (Len
>= Nbuf
->TotalSize
) {
1599 Trimmed
+= Nbuf
->TotalSize
;
1600 Len
-= Nbuf
->TotalSize
;
1602 RemoveEntryList (Entry
);
1612 Trimmed
+= NetbufTrim (Nbuf
, Len
, NET_BUF_HEAD
);
1622 Flush the net buffer queue.
1624 @param[in, out] NbufQue Pointer to the queue to be flushed.
1630 IN OUT NET_BUF_QUEUE
*NbufQue
1633 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1635 NetbufFreeList (&NbufQue
->BufList
);
1637 NbufQue
->BufNum
= 0;
1638 NbufQue
->BufSize
= 0;
1643 Compute the checksum for a bulk of data.
1645 @param[in] Bulk Pointer to the data.
1646 @param[in] Len Length of the data, in bytes.
1648 @return The computed checksum.
1658 register UINT32 Sum
;
1663 // Add left-over byte, if any
1666 Sum
+= *(Bulk
+ Len
- 1);
1670 Sum
+= *(UINT16
*) Bulk
;
1676 // Fold 32-bit sum to 16 bits
1678 while ((Sum
>> 16) != 0) {
1679 Sum
= (Sum
& 0xffff) + (Sum
>> 16);
1683 return (UINT16
) Sum
;
1690 @param[in] Checksum1 The first checksum to be added.
1691 @param[in] Checksum2 The second checksum to be added.
1693 @return The new checksum.
1699 IN UINT16 Checksum1
,
1705 Sum
= Checksum1
+ Checksum2
;
1708 // two UINT16 can only add up to a carry of 1.
1710 if ((Sum
>> 16) != 0) {
1711 Sum
= (Sum
& 0xffff) + 1;
1715 return (UINT16
) Sum
;
1720 Compute the checksum for a NET_BUF.
1722 @param[in] Nbuf Pointer to the net buffer.
1724 @return The computed checksum.
1733 NET_BLOCK_OP
*BlockOp
;
1739 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1743 BlockOp
= Nbuf
->BlockOp
;
1745 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1746 if (BlockOp
[Index
].Size
== 0) {
1750 BlockSum
= NetblockChecksum (BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1752 if ((Offset
& 0x01) != 0) {
1754 // The checksum starts with an odd byte, swap
1755 // the checksum before added to total checksum
1757 BlockSum
= SwapBytes16 (BlockSum
);
1760 TotalSum
= NetAddChecksum (BlockSum
, TotalSum
);
1761 Offset
+= BlockOp
[Index
].Size
;
1769 Compute the checksum for TCP/UDP pseudo header.
1771 Src and Dst are in network byte order, and Len is in host byte order.
1773 @param[in] Src The source address of the packet.
1774 @param[in] Dst The destination address of the packet.
1775 @param[in] Proto The protocol type of the packet.
1776 @param[in] Len The length of the packet.
1778 @return The computed checksum.
1783 NetPseudoHeadChecksum (
1793 // Zero the memory to relieve align problems
1795 ZeroMem (&Hdr
, sizeof (Hdr
));
1799 Hdr
.Protocol
= Proto
;
1800 Hdr
.Len
= HTONS (Len
);
1802 return NetblockChecksum ((UINT8
*) &Hdr
, sizeof (Hdr
));
1806 Compute the checksum for TCP6/UDP6 pseudo header.
1808 Src and Dst are in network byte order, and Len is in host byte order.
1810 @param[in] Src The source address of the packet.
1811 @param[in] Dst The destination address of the packet.
1812 @param[in] NextHeader The protocol type of the packet.
1813 @param[in] Len The length of the packet.
1815 @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
));
1844 The function frees the net buffer which allocated by the IP protocol. It releases
1845 only the net buffer and doesn't call the external free function.
1847 This function should be called after finishing the process of mIpSec->ProcessExt()
1848 for outbound traffic. The (EFI_IPSEC2_PROTOCOL)->ProcessExt() allocates a new
1849 buffer for the ESP, so there needs a function to free the old net buffer.
1851 @param[in] Nbuf The network buffer to be freed.
1855 NetIpSecNetbufFree (
1859 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1860 ASSERT (Nbuf
->RefCnt
> 0);
1864 if (Nbuf
->RefCnt
== 0) {
1867 // Update Vector only when NBuf is to be released. That is,
1868 // all the sharing of Nbuf increse Vector's RefCnt by one
1870 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1871 ASSERT (Nbuf
->Vector
->RefCnt
> 0);
1873 Nbuf
->Vector
->RefCnt
--;
1875 if (Nbuf
->Vector
->RefCnt
> 0) {
1880 // If NET_VECTOR_OWN_FIRST is set, release the first block since it is
1883 if ((Nbuf
->Vector
->Flag
& NET_VECTOR_OWN_FIRST
) != 0) {
1884 FreePool (Nbuf
->Vector
->Block
[0].Bulk
);
1886 FreePool (Nbuf
->Vector
);