3 Copyright (c) 2005 - 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
24 #include <Library/NetLib.h>
25 #include <Library/BaseLib.h>
26 #include <Library/DebugLib.h>
27 #include <Library/BaseMemoryLib.h>
28 #include <Library/UefiBootServicesTableLib.h>
29 #include <Library/MemoryAllocationLib.h>
33 Allocate and build up the sketch for a NET_BUF. The net buffer allocated
34 has the BlockOpNum's NET_BLOCK_OP, and its associated NET_VECTOR has the
37 @param BlockNum The number of NET_BLOCK in the Vector of net buffer
38 @param BlockOpNum The number of NET_BLOCK_OP in the net buffer
40 @retval * Pointer to the allocated NET_BUF. If NULL the
41 allocation failed due to resource limit.
54 ASSERT (BlockOpNum
>= 1);
57 // Allocate three memory blocks.
59 Nbuf
= AllocateZeroPool (NET_BUF_SIZE (BlockOpNum
));
65 Nbuf
->Signature
= NET_BUF_SIGNATURE
;
67 Nbuf
->BlockOpNum
= BlockOpNum
;
68 InitializeListHead (&Nbuf
->List
);
71 Vector
= AllocateZeroPool (NET_VECTOR_SIZE (BlockNum
));
77 Vector
->Signature
= NET_VECTOR_SIGNATURE
;
79 Vector
->BlockNum
= BlockNum
;
80 Nbuf
->Vector
= Vector
;
93 Allocate a single block NET_BUF. Upon allocation, all the
94 free space is in the tail room.
96 @param Len The length of the block.
98 @retval * Pointer to the allocated NET_BUF. If NULL the
99 allocation failed due to resource limit.
114 Nbuf
= NetbufAllocStruct (1, 1);
120 Bulk
= AllocatePool (Len
);
126 Vector
= Nbuf
->Vector
;
129 Vector
->Block
[0].Bulk
= Bulk
;
130 Vector
->Block
[0].Len
= Len
;
132 Nbuf
->BlockOp
[0].BlockHead
= Bulk
;
133 Nbuf
->BlockOp
[0].BlockTail
= Bulk
+ Len
;
135 Nbuf
->BlockOp
[0].Head
= Bulk
;
136 Nbuf
->BlockOp
[0].Tail
= Bulk
;
137 Nbuf
->BlockOp
[0].Size
= 0;
142 gBS
->FreePool (Nbuf
);
150 @param Vector Pointer to the NET_VECTOR to be freed.
158 IN NET_VECTOR
*Vector
163 NET_CHECK_SIGNATURE (Vector
, NET_VECTOR_SIGNATURE
);
164 ASSERT (Vector
->RefCnt
> 0);
168 if (Vector
->RefCnt
> 0) {
172 if (Vector
->Free
!= NULL
) {
174 // Call external free function to free the vector if it
175 // isn't NULL. If NET_VECTOR_OWN_FIRST is set, release the
176 // first block since it is allocated by us
178 if (Vector
->Flag
& NET_VECTOR_OWN_FIRST
) {
179 gBS
->FreePool (Vector
->Block
[0].Bulk
);
182 Vector
->Free (Vector
->Arg
);
186 // Free each memory block associated with the Vector
188 for (Index
= 0; Index
< Vector
->BlockNum
; Index
++) {
189 gBS
->FreePool (Vector
->Block
[Index
].Bulk
);
193 gBS
->FreePool (Vector
);
198 Free the buffer and its associated NET_VECTOR.
200 @param Nbuf Pointer to the NET_BUF to be freed.
211 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
212 ASSERT (Nbuf
->RefCnt
> 0);
216 if (Nbuf
->RefCnt
== 0) {
218 // Update Vector only when NBuf is to be released. That is,
219 // all the sharing of Nbuf increse Vector's RefCnt by one
221 NetbufFreeVector (Nbuf
->Vector
);
222 gBS
->FreePool (Nbuf
);
228 Create a copy of NET_BUF that share the associated NET_DATA.
230 @param Nbuf Pointer to the net buffer to be cloned.
232 @retval * Pointer to the cloned net buffer.
243 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
245 Clone
= AllocatePool (NET_BUF_SIZE (Nbuf
->BlockOpNum
));
251 Clone
->Signature
= NET_BUF_SIGNATURE
;
253 InitializeListHead (&Clone
->List
);
255 Clone
->Ip
= Nbuf
->Ip
;
256 Clone
->Tcp
= Nbuf
->Tcp
;
258 CopyMem (Clone
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
260 NET_GET_REF (Nbuf
->Vector
);
262 Clone
->Vector
= Nbuf
->Vector
;
263 Clone
->BlockOpNum
= Nbuf
->BlockOpNum
;
264 Clone
->TotalSize
= Nbuf
->TotalSize
;
265 CopyMem (Clone
->BlockOp
, Nbuf
->BlockOp
, sizeof (NET_BLOCK_OP
) * Nbuf
->BlockOpNum
);
272 Create a duplicated copy of Nbuf, data is copied. Also leave some
273 head space before the data.
275 @param Nbuf Pointer to the net buffer to be cloned.
276 @param Duplicate Pointer to the net buffer to duplicate to, if NULL
277 a new net buffer is allocated.
278 @param HeadSpace Length of the head space to reserve
280 @retval * Pointer to the duplicated net buffer.
287 IN NET_BUF
*Duplicate OPTIONAL
,
293 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
295 if (Duplicate
== NULL
) {
296 Duplicate
= NetbufAlloc (Nbuf
->TotalSize
+ HeadSpace
);
299 if (Duplicate
== NULL
) {
304 // Don't set the IP and TCP head point, since it is most
305 // like that they are pointing to the memory of Nbuf.
307 CopyMem (Duplicate
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
308 NetbufReserve (Duplicate
, HeadSpace
);
310 Dst
= NetbufAllocSpace (Duplicate
, Nbuf
->TotalSize
, NET_BUF_TAIL
);
311 NetbufCopy (Nbuf
, 0, Nbuf
->TotalSize
, Dst
);
318 Free a list of net buffers.
320 @param Head Pointer to the head of linked net buffers.
335 Entry
= Head
->ForwardLink
;
337 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Head
) {
338 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
339 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
341 RemoveEntryList (Entry
);
345 ASSERT (IsListEmpty (Head
));
350 Get the position of some byte in the net buffer. This can be used
351 to, for example, retrieve the IP header in the packet. It also
352 returns the fragment that contains the byte which is used mainly by
353 the buffer implementation itself.
355 @param Nbuf Pointer to the net buffer.
356 @param Offset The index or offset of the byte
357 @param Index Index of the fragment that contains the block
359 @retval * Pointer to the nth byte of data in the net buffer.
360 If NULL, there is no such data in the net buffer.
368 OUT UINT32
*Index OPTIONAL
371 NET_BLOCK_OP
*BlockOp
;
375 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
377 if (Offset
>= Nbuf
->TotalSize
) {
381 BlockOp
= Nbuf
->BlockOp
;
384 for (Loop
= 0; Loop
< Nbuf
->BlockOpNum
; Loop
++) {
386 if (Len
+ BlockOp
[Loop
].Size
<= Offset
) {
387 Len
+= BlockOp
[Loop
].Size
;
395 return BlockOp
[Loop
].Head
+ (Offset
- Len
);
404 Set the NET_BLOCK and corresponding NET_BLOCK_OP in
405 the buffer. All the pointers in NET_BLOCK and NET_BLOCK_OP
406 are set to the bulk's head and tail respectively. So, this
407 function alone can't be used by NetbufAlloc.
409 @param Nbuf Pointer to the net buffer.
410 @param Bulk Pointer to the data.
411 @param Len Length of the bulk data.
412 @param Index The data block index in the net buffer the bulk
413 data should belong to.
427 NET_BLOCK_OP
*BlockOp
;
430 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
431 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
432 ASSERT (Index
< Nbuf
->BlockOpNum
);
434 Block
= &(Nbuf
->Vector
->Block
[Index
]);
435 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
438 BlockOp
->BlockHead
= Bulk
;
439 BlockOp
->BlockTail
= Bulk
+ Len
;
440 BlockOp
->Head
= Bulk
;
441 BlockOp
->Tail
= Bulk
+ Len
;
448 Set the NET_BLOCK_OP in the buffer. The corresponding NET_BLOCK
449 structure is left untouched. Some times, there is no 1:1 relationship
450 between NET_BLOCK and NET_BLOCK_OP. For example, that in NetbufGetFragment.
452 @param Nbuf Pointer to the net buffer.
453 @param Bulk Pointer to the data.
454 @param Len Length of the bulk data.
455 @param Index The data block index in the net buffer the bulk
456 data should belong to.
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 NetbufClone. It is necessary because NetbufGetFragment
486 may allocate the first block to accomodate the HeadSpace and HeadLen. So, it
487 need to create a new NET_VECTOR. But, we want to avoid data copy by sharing
490 @param Arg Point to the old NET_VECTOR
497 NetbufGetFragmentFree (
503 Vector
= (NET_VECTOR
*)Arg
;
504 NetbufFreeVector (Vector
);
510 Create a NET_BUF structure which contains Len byte data of
511 Nbuf starting from Offset. A new NET_BUF structure will be
512 created but the associated data in NET_VECTOR is shared.
513 This function exists to do IP packet fragmentation.
515 @param Nbuf Pointer to the net buffer to be cloned.
516 @param Offset Starting point of the data to be included in new
518 @param Len How many data to include in new data
519 @param HeadSpace How many bytes of head space to reserve for
522 @retval * Pointer to the cloned net buffer.
536 NET_BLOCK_OP
*BlockOp
;
548 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
550 if ((Len
== 0) || (Offset
+ Len
> Nbuf
->TotalSize
)) {
555 // First find the first and last BlockOp that contains
556 // the valid data, and compute the offset of the first
557 // BlockOp and length of the last BlockOp
559 BlockOp
= Nbuf
->BlockOp
;
562 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
563 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
567 Cur
+= BlockOp
[Index
].Size
;
571 // First is the index of the first BlockOp, FirstSkip is
572 // the offset of the first byte in the first BlockOp.
575 FirstSkip
= Offset
- Cur
;
576 FirstLen
= BlockOp
[Index
].Size
- FirstSkip
;
579 //redundant assignment to make compiler happy.
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 BlockOpNum
= Last
- First
+ 1;
607 if (HeadSpace
!= 0) {
609 // Allocate an extra block to accomdate the head space.
613 Child
= NetbufAllocStruct (1, BlockOpNum
);
619 FirstBulk
= AllocatePool (HeadSpace
);
621 if (FirstBulk
== NULL
) {
625 Vector
= Child
->Vector
;
626 Vector
->Free
= NetbufGetFragmentFree
;
627 Vector
->Arg
= Nbuf
->Vector
;
628 Vector
->Flag
= NET_VECTOR_OWN_FIRST
;
629 Vector
->Len
= HeadSpace
;
632 //Reserve the head space in the first block
634 NetbufSetBlock (Child
, FirstBulk
, HeadSpace
, 0);
635 Child
->BlockOp
[0].Head
+= HeadSpace
;
636 Child
->BlockOp
[0].Size
= 0;
640 Child
= NetbufAllocStruct (0, BlockOpNum
);
646 Child
->Vector
= Nbuf
->Vector
;
649 NET_GET_REF (Nbuf
->Vector
);
650 Child
->TotalSize
= Len
;
653 // Set all the BlockOp up, the first and last one are special
654 // and need special process.
658 Nbuf
->BlockOp
[First
].Head
+ FirstSkip
,
663 for (Index
= First
+ 1; Index
<= Last
- 1 ; Index
++) {
681 CopyMem (Child
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
686 gBS
->FreePool (Child
);
693 Build a NET_BUF from external blocks.
695 @param ExtFragment Pointer to the data block.
696 @param ExtNum The number of the data block.
697 @param HeadSpace The head space to be reserved.
698 @param HeadLen The length of the protocol header, This function
699 will pull that number of data into a linear block.
700 @param ExtFree Pointer to the caller provided free function.
701 @param Arg The argument passed to ExtFree when ExtFree is
704 @retval * Pointer to the net buffer built from the data
711 IN NET_FRAGMENT
*ExtFragment
,
715 IN NET_VECTOR_EXT_FREE ExtFree
,
716 IN VOID
*Arg OPTIONAL
721 NET_FRAGMENT SavedFragment
;
726 UINT32 FirstBlockLen
;
733 ASSERT ((ExtFragment
!= NULL
) && (ExtNum
> 0) && (ExtFree
!= NULL
));
735 SavedFragment
.Bulk
= NULL
;
736 SavedFragment
.Len
= 0;
748 // No need to consolidate the header if the first block is
749 // longer than the header length or there is only one block.
751 if ((ExtFragment
[0].Len
>= HeadLen
) || (ExtNum
== 1)) {
756 // Allocate an extra block if we need to:
757 // 1. Allocate some header space
758 // 2. aggreate the packet header
760 if ((HeadSpace
!= 0) || (HeadLen
!= 0)) {
761 FirstBlockLen
= HeadLen
+ HeadSpace
;
762 FirstBlock
= AllocatePool (FirstBlockLen
);
764 if (FirstBlock
== NULL
) {
772 // Copy the header to the first block, reduce the NET_BLOCK
773 // to allocate by one for each block that is completely covered
774 // by the first bulk.
778 Header
= FirstBlock
+ HeadSpace
;
780 for (Index
= 0; Index
< ExtNum
; Index
++) {
781 if (Len
>= ExtFragment
[Index
].Len
) {
782 CopyMem (Header
, ExtFragment
[Index
].Bulk
, ExtFragment
[Index
].Len
);
784 Copied
+= ExtFragment
[Index
].Len
;
785 Len
-= ExtFragment
[Index
].Len
;
786 Header
+= ExtFragment
[Index
].Len
;
787 TotalLen
+= ExtFragment
[Index
].Len
;
792 // Increament the index number to point to the next
793 // non-empty fragment.
800 CopyMem (Header
, ExtFragment
[Index
].Bulk
, Len
);
806 // Adjust the block structure to exclude the data copied,
807 // So, the left-over block can be processed as other blocks.
808 // But it must be recovered later. (SavedIndex > 0) always
809 // holds since we don't aggreate the header if the first block
810 // is bigger enough that the header is continuous
813 SavedFragment
= ExtFragment
[Index
];
814 ExtFragment
[Index
].Bulk
+= Len
;
815 ExtFragment
[Index
].Len
-= Len
;
821 Nbuf
= NetbufAllocStruct (BlockNum
, BlockNum
);
827 Vector
= Nbuf
->Vector
;
828 Vector
->Free
= ExtFree
;
830 Vector
->Flag
= (FirstBlockLen
? NET_VECTOR_OWN_FIRST
: 0);
833 // Set the first block up which may contain
834 // some head space and aggregated header
838 if (FirstBlockLen
!= 0) {
839 NetbufSetBlock (Nbuf
, FirstBlock
, HeadSpace
+ Copied
, 0);
840 Nbuf
->BlockOp
[0].Head
+= HeadSpace
;
841 Nbuf
->BlockOp
[0].Size
= Copied
;
846 for (; Index
< ExtNum
; Index
++) {
847 NetbufSetBlock (Nbuf
, ExtFragment
[Index
].Bulk
, ExtFragment
[Index
].Len
, CurBlock
);
848 TotalLen
+= ExtFragment
[Index
].Len
;
852 Vector
->Len
= TotalLen
+ HeadSpace
;
853 Nbuf
->TotalSize
= TotalLen
;
856 ExtFragment
[SavedIndex
] = SavedFragment
;
862 gBS
->FreePool (FirstBlock
);
868 Build a fragment table to contain the fragments in the
869 buffer. This is the opposite of the NetbufFromExt.
871 @param Nbuf Point to the net buffer
872 @param ExtFragment Pointer to the data block.
873 @param ExtNum The number of the data block.
875 @retval EFI_BUFFER_TOO_SMALL The number of non-empty block is bigger than ExtNum
876 @retval EFI_SUCCESS Fragment table built.
883 IN NET_FRAGMENT
*ExtFragment
,
892 for (Index
= 0; (Index
< Nbuf
->BlockOpNum
); Index
++) {
893 if (Nbuf
->BlockOp
[Index
].Size
== 0) {
897 if (Current
< *ExtNum
) {
898 ExtFragment
[Current
].Bulk
= Nbuf
->BlockOp
[Index
].Head
;
899 ExtFragment
[Current
].Len
= Nbuf
->BlockOp
[Index
].Size
;
902 return EFI_BUFFER_TOO_SMALL
;
912 Build a NET_BUF from a list of NET_BUF.
914 @param BufList A List of NET_BUF.
915 @param HeadSpace The head space to be reserved.
916 @param HeaderLen The length of the protocol header, This function
917 will pull that number of data into a linear block.
918 @param ExtFree Pointer to the caller provided free function.
919 @param Arg The argument passed to ExtFree when ExtFree is
922 @retval * Pointer to the net buffer built from the data
929 IN LIST_ENTRY
*BufList
,
932 IN NET_VECTOR_EXT_FREE ExtFree
,
933 IN VOID
*Arg OPTIONAL
936 NET_FRAGMENT
*Fragment
;
944 //Compute how many blocks are there
948 NET_LIST_FOR_EACH (Entry
, BufList
) {
949 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
950 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
951 FragmentNum
+= Nbuf
->BlockOpNum
;
955 //Allocate and copy block points
957 Fragment
= AllocatePool (sizeof (NET_FRAGMENT
) * FragmentNum
);
959 if (Fragment
== NULL
) {
965 NET_LIST_FOR_EACH (Entry
, BufList
) {
966 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
967 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
969 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
970 if (Nbuf
->BlockOp
[Index
].Size
) {
971 Fragment
[Current
].Bulk
= Nbuf
->BlockOp
[Index
].Head
;
972 Fragment
[Current
].Len
= Nbuf
->BlockOp
[Index
].Size
;
978 Nbuf
= NetbufFromExt (Fragment
, Current
, HeadSpace
, HeaderLen
, ExtFree
, Arg
);
979 gBS
->FreePool (Fragment
);
986 Reserve some space in the header room of the buffer.
987 Upon allocation, all the space are in the tail room
988 of the buffer. Call this function to move some space
989 to the header room. This function is quite limited in
990 that it can only reserver space from the first block
991 of an empty NET_BUF not built from the external. But
992 it should be enough for the network stack.
994 @param Nbuf Pointer to the net buffer.
995 @param Len The length of buffer to be reserverd.
1007 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1008 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1010 ASSERT ((Nbuf
->BlockOpNum
== 1) && (Nbuf
->TotalSize
== 0));
1011 ASSERT ((Nbuf
->Vector
->Free
== NULL
) && (Nbuf
->Vector
->Len
>= Len
));
1013 Nbuf
->BlockOp
[0].Head
+= Len
;
1014 Nbuf
->BlockOp
[0].Tail
+= Len
;
1016 ASSERT (Nbuf
->BlockOp
[0].Tail
<= Nbuf
->BlockOp
[0].BlockTail
);
1021 Allocate some space from the header or tail of the buffer.
1023 @param Nbuf Pointer to the net buffer.
1024 @param Len The length of the buffer to be allocated.
1025 @param FromHead The flag to indicate whether reserve the data from
1026 head or tail. TRUE for from head, and FALSE for
1029 @retval * Pointer to the first byte of the allocated buffer.
1040 NET_BLOCK_OP
*BlockOp
;
1044 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1045 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1051 // Allocate some space from head. If the buffer is empty,
1052 // allocate from the first block. If it isn't, allocate
1053 // from the first non-empty block, or the block before that.
1055 if (Nbuf
->TotalSize
== 0) {
1058 NetbufGetByte (Nbuf
, 0, &Index
);
1060 if ((NET_HEADSPACE(&(Nbuf
->BlockOp
[Index
])) < Len
) && (Index
> 0)) {
1065 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
1067 if (NET_HEADSPACE (BlockOp
) < Len
) {
1071 BlockOp
->Head
-= Len
;
1072 BlockOp
->Size
+= Len
;
1073 Nbuf
->TotalSize
+= Len
;
1075 return BlockOp
->Head
;
1079 // Allocate some space from the tail. If the buffer is empty,
1080 // allocate from the first block. If it isn't, allocate
1081 // from the last non-empty block, or the block after that.
1083 if (Nbuf
->TotalSize
== 0) {
1086 NetbufGetByte (Nbuf
, Nbuf
->TotalSize
- 1, &Index
);
1088 if ((NET_TAILSPACE(&(Nbuf
->BlockOp
[Index
])) < Len
) &&
1089 (Index
< Nbuf
->BlockOpNum
- 1)) {
1095 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
1097 if (NET_TAILSPACE (BlockOp
) < Len
) {
1101 SavedTail
= BlockOp
->Tail
;
1103 BlockOp
->Tail
+= Len
;
1104 BlockOp
->Size
+= Len
;
1105 Nbuf
->TotalSize
+= Len
;
1113 Trim a single NET_BLOCK.
1115 @param BlockOp Pointer to the NET_BLOCK.
1116 @param Len The length of the data to be trimmed.
1117 @param FromHead The flag to indicate whether trim data from head or
1118 tail. TRUE for from head, and FALSE for from tail.
1126 IN NET_BLOCK_OP
*BlockOp
,
1131 ASSERT (BlockOp
&& (BlockOp
->Size
>= Len
));
1133 BlockOp
->Size
-= Len
;
1136 BlockOp
->Head
+= Len
;
1138 BlockOp
->Tail
-= Len
;
1144 Trim some data from the header or tail of the buffer.
1146 @param Nbuf Pointer to the net buffer.
1147 @param Len The length of the data to be trimmed.
1148 @param FromHead The flag to indicate whether trim data from head or
1149 tail. TRUE for from head, and FALSE for from tail.
1151 @retval UINTN Length of the actually trimmed data.
1162 NET_BLOCK_OP
*BlockOp
;
1166 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1168 if (Len
> Nbuf
->TotalSize
) {
1169 Len
= Nbuf
->TotalSize
;
1173 // If FromTail is true, iterate backward. That
1174 // is, init Index to NBuf->BlockNum - 1, and
1175 // decrease it by 1 during each loop. Otherwise,
1176 // iterate forward. That is, init Index to 0, and
1177 // increase it by 1 during each loop.
1180 Nbuf
->TotalSize
-= Len
;
1182 Index
= (FromHead
? 0 : Nbuf
->BlockOpNum
- 1);
1183 BlockOp
= Nbuf
->BlockOp
;
1186 if (BlockOp
[Index
].Size
== 0) {
1187 Index
+= (FromHead
? 1 : -1);
1191 if (Len
> BlockOp
[Index
].Size
) {
1192 Len
-= BlockOp
[Index
].Size
;
1193 Trimmed
+= BlockOp
[Index
].Size
;
1194 NetblockTrim (&BlockOp
[Index
], BlockOp
[Index
].Size
, FromHead
);
1197 NetblockTrim (&BlockOp
[Index
], Len
, FromHead
);
1201 Index
+= (FromHead
? 1 : -1);
1209 Copy the data from the specific offset to the destination.
1211 @param Nbuf Pointer to the net buffer.
1212 @param Offset The sequence number of the first byte to copy.
1213 @param Len Length of the data to copy.
1214 @param Dest The destination of the data to copy to.
1216 @retval UINTN The length of the copied data.
1228 NET_BLOCK_OP
*BlockOp
;
1235 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1238 if ((Len
== 0) || (Nbuf
->TotalSize
<= Offset
)) {
1242 if (Nbuf
->TotalSize
- Offset
< Len
) {
1243 Len
= Nbuf
->TotalSize
- Offset
;
1246 BlockOp
= Nbuf
->BlockOp
;
1249 // Skip to the offset. Don't make "Offset-By-One" error here.
1250 // Cur + BLOCK.SIZE is the first sequence number of next block.
1251 // So, (Offset < Cur + BLOCK.SIZE) means that the first byte
1252 // is in the current block. if (Offset == Cur + BLOCK.SIZE), the
1253 // first byte is the next block's first byte.
1257 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1258 if (BlockOp
[Index
].Size
== 0) {
1262 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
1266 Cur
+= BlockOp
[Index
].Size
;
1270 // Cur is the sequence number of the first byte in the block
1271 // Offset - Cur is the number of bytes before first byte to
1272 // to copy in the current block.
1274 Skip
= Offset
- Cur
;
1275 Left
= BlockOp
[Index
].Size
- Skip
;
1278 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Len
);
1282 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Left
);
1290 for (; Index
< Nbuf
->BlockOpNum
; Index
++) {
1291 if (Len
> BlockOp
[Index
].Size
) {
1292 Len
-= BlockOp
[Index
].Size
;
1293 Copied
+= BlockOp
[Index
].Size
;
1295 CopyMem (Dest
, BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1296 Dest
+= BlockOp
[Index
].Size
;
1299 CopyMem (Dest
, BlockOp
[Index
].Head
, Len
);
1309 Initiate the net buffer queue.
1311 @param NbufQue Pointer to the net buffer queue to be initiated.
1319 IN NET_BUF_QUEUE
*NbufQue
1322 NbufQue
->Signature
= NET_QUE_SIGNATURE
;
1323 NbufQue
->RefCnt
= 1;
1324 InitializeListHead (&NbufQue
->List
);
1326 InitializeListHead (&NbufQue
->BufList
);
1327 NbufQue
->BufSize
= 0;
1328 NbufQue
->BufNum
= 0;
1333 Allocate an initialized net buffer queue.
1337 @retval * Pointer to the allocated net buffer queue.
1346 NET_BUF_QUEUE
*NbufQue
;
1348 NbufQue
= AllocatePool (sizeof (NET_BUF_QUEUE
));
1349 if (NbufQue
== NULL
) {
1353 NetbufQueInit (NbufQue
);
1360 Free a net buffer queue.
1362 @param NbufQue Poitner to the net buffer queue to be freed.
1370 IN NET_BUF_QUEUE
*NbufQue
1373 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1377 if (NbufQue
->RefCnt
== 0) {
1378 NetbufQueFlush (NbufQue
);
1379 gBS
->FreePool (NbufQue
);
1385 Append a buffer to the end of the queue.
1387 @param NbufQue Pointer to the net buffer queue.
1388 @param Nbuf Pointer to the net buffer to be appended.
1396 IN NET_BUF_QUEUE
*NbufQue
,
1400 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1401 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1403 InsertTailList (&NbufQue
->BufList
, &Nbuf
->List
);
1405 NbufQue
->BufSize
+= Nbuf
->TotalSize
;
1411 Remove a net buffer from head in the specific queue.
1413 @param NbufQue Pointer to the net buffer queue.
1415 @retval * Pointer to the net buffer removed from the specific
1422 IN NET_BUF_QUEUE
*NbufQue
1427 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1429 if (NbufQue
->BufNum
== 0) {
1433 First
= NET_LIST_USER_STRUCT (NbufQue
->BufList
.ForwardLink
, NET_BUF
, List
);
1435 NetListRemoveHead (&NbufQue
->BufList
);
1437 NbufQue
->BufSize
-= First
->TotalSize
;
1444 Copy some data from the buffer queue to the destination.
1446 @param NbufQue Pointer to the net buffer queue.
1447 @param Offset The sequence number of the first byte to copy.
1448 @param Len Length of the data to copy.
1449 @param Dest The destination of the data to copy to.
1451 @retval UINTN The length of the copied data.
1456 IN NET_BUF_QUEUE
*NbufQue
,
1469 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1470 ASSERT (Dest
!= NULL
);
1472 if ((Len
== 0) || (NbufQue
->BufSize
<= Offset
)) {
1476 if (NbufQue
->BufSize
- Offset
< Len
) {
1477 Len
= NbufQue
->BufSize
- Offset
;
1481 // skip to the Offset
1486 NET_LIST_FOR_EACH (Entry
, &NbufQue
->BufList
) {
1487 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1489 if (Offset
< Cur
+ Nbuf
->TotalSize
) {
1493 Cur
+= Nbuf
->TotalSize
;
1497 // Copy the data in the first buffer.
1499 Skip
= Offset
- Cur
;
1500 Left
= Nbuf
->TotalSize
- Skip
;
1503 return NetbufCopy (Nbuf
, Skip
, Len
, Dest
);
1506 NetbufCopy (Nbuf
, Skip
, Left
, Dest
);
1512 // Iterate over the others
1514 Entry
= Entry
->ForwardLink
;
1516 while ((Len
> 0) && (Entry
!= &NbufQue
->BufList
)) {
1517 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1519 if (Len
> Nbuf
->TotalSize
) {
1520 Len
-= Nbuf
->TotalSize
;
1521 Copied
+= Nbuf
->TotalSize
;
1523 NetbufCopy (Nbuf
, 0, Nbuf
->TotalSize
, Dest
);
1524 Dest
+= Nbuf
->TotalSize
;
1527 NetbufCopy (Nbuf
, 0, Len
, Dest
);
1532 Entry
= Entry
->ForwardLink
;
1540 Trim some data from the queue header, release the buffer if
1541 whole buffer is trimmed.
1543 @param NbufQue Pointer to the net buffer queue.
1544 @param Len Length of the data to trim.
1546 @retval UINTN The length of the data trimmed.
1552 IN NET_BUF_QUEUE
*NbufQue
,
1561 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1567 if (Len
> NbufQue
->BufSize
) {
1568 Len
= NbufQue
->BufSize
;
1571 NbufQue
->BufSize
-= Len
;
1574 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &NbufQue
->BufList
) {
1575 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1577 if (Len
>= Nbuf
->TotalSize
) {
1578 Trimmed
+= Nbuf
->TotalSize
;
1579 Len
-= Nbuf
->TotalSize
;
1581 RemoveEntryList (Entry
);
1591 Trimmed
+= NetbufTrim (Nbuf
, Len
, NET_BUF_HEAD
);
1601 Flush the net buffer queue.
1603 @param NbufQue Pointer to the queue to be flushed.
1611 IN NET_BUF_QUEUE
*NbufQue
1614 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1616 NetbufFreeList (&NbufQue
->BufList
);
1618 NbufQue
->BufNum
= 0;
1619 NbufQue
->BufSize
= 0;
1624 Compute checksum for a bulk of data.
1626 @param Bulk Pointer to the data.
1627 @param Len Length of the data, in bytes.
1629 @retval UINT16 The computed checksum.
1639 register UINT32 Sum
;
1644 Sum
+= *(UINT16
*) Bulk
;
1650 // Add left-over byte, if any
1653 Sum
+= *(UINT8
*) Bulk
;
1657 // Fold 32-bit sum to 16 bits
1660 Sum
= (Sum
& 0xffff) + (Sum
>> 16);
1664 return (UINT16
) Sum
;
1671 @param Checksum1 The first checksum to be added.
1672 @param Checksum2 The second checksum to be added.
1674 @retval UINT16 The new checksum.
1680 IN UINT16 Checksum1
,
1686 Sum
= Checksum1
+ Checksum2
;
1689 // two UINT16 can only add up to a carry of 1.
1692 Sum
= (Sum
& 0xffff) + 1;
1696 return (UINT16
) Sum
;
1701 Compute the checksum for a NET_BUF.
1703 @param Nbuf Pointer to the net buffer.
1705 @retval UINT16 The computed checksum.
1714 NET_BLOCK_OP
*BlockOp
;
1720 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1724 BlockOp
= Nbuf
->BlockOp
;
1726 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1727 if (BlockOp
[Index
].Size
== 0) {
1731 BlockSum
= NetblockChecksum (BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1733 if (Offset
& 0x01) {
1735 // The checksum starts with an odd byte, swap
1736 // the checksum before added to total checksum
1738 BlockSum
= (UINT16
) NET_SWAP_SHORT (BlockSum
);
1741 TotalSum
= NetAddChecksum (BlockSum
, TotalSum
);
1742 Offset
+= BlockOp
[Index
].Size
;
1750 Compute the checksum for TCP/UDP pseudo header.
1751 Src, Dst are in network byte order. and Len is
1754 @param Src The source address of the packet.
1755 @param Dst The destination address of the packet.
1756 @param Proto The protocol type of the packet.
1757 @param Len The length of the packet.
1759 @retval UINT16 The computed checksum.
1764 NetPseudoHeadChecksum (
1774 // Zero the memory to relieve align problems
1776 ZeroMem (&Hdr
, sizeof (Hdr
));
1780 Hdr
.Protocol
= Proto
;
1781 Hdr
.Len
= HTONS (Len
);
1783 return NetblockChecksum ((UINT8
*) &Hdr
, sizeof (Hdr
));