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.
53 ASSERT (BlockOpNum
>= 1);
56 // Allocate three memory blocks.
58 Nbuf
= AllocateZeroPool (NET_BUF_SIZE (BlockOpNum
));
64 Nbuf
->Signature
= NET_BUF_SIGNATURE
;
66 Nbuf
->BlockOpNum
= BlockOpNum
;
67 InitializeListHead (&Nbuf
->List
);
70 Vector
= AllocateZeroPool (NET_VECTOR_SIZE (BlockNum
));
76 Vector
->Signature
= NET_VECTOR_SIGNATURE
;
78 Vector
->BlockNum
= BlockNum
;
79 Nbuf
->Vector
= Vector
;
92 Allocate a single block NET_BUF. Upon allocation, all the
93 free space is in the tail room.
95 @param Len The length of the block.
97 @retval * Pointer to the allocated NET_BUF. If NULL the
98 allocation failed due to resource limit.
113 Nbuf
= NetbufAllocStruct (1, 1);
119 Bulk
= AllocatePool (Len
);
125 Vector
= Nbuf
->Vector
;
128 Vector
->Block
[0].Bulk
= Bulk
;
129 Vector
->Block
[0].Len
= Len
;
131 Nbuf
->BlockOp
[0].BlockHead
= Bulk
;
132 Nbuf
->BlockOp
[0].BlockTail
= Bulk
+ Len
;
134 Nbuf
->BlockOp
[0].Head
= Bulk
;
135 Nbuf
->BlockOp
[0].Tail
= Bulk
;
136 Nbuf
->BlockOp
[0].Size
= 0;
141 gBS
->FreePool (Nbuf
);
149 @param Vector Pointer to the NET_VECTOR to be freed.
156 IN NET_VECTOR
*Vector
161 NET_CHECK_SIGNATURE (Vector
, NET_VECTOR_SIGNATURE
);
162 ASSERT (Vector
->RefCnt
> 0);
166 if (Vector
->RefCnt
> 0) {
170 if (Vector
->Free
!= NULL
) {
172 // Call external free function to free the vector if it
173 // isn't NULL. If NET_VECTOR_OWN_FIRST is set, release the
174 // first block since it is allocated by us
176 if (Vector
->Flag
& NET_VECTOR_OWN_FIRST
) {
177 gBS
->FreePool (Vector
->Block
[0].Bulk
);
180 Vector
->Free (Vector
->Arg
);
184 // Free each memory block associated with the Vector
186 for (Index
= 0; Index
< Vector
->BlockNum
; Index
++) {
187 gBS
->FreePool (Vector
->Block
[Index
].Bulk
);
191 gBS
->FreePool (Vector
);
196 Free the buffer and its associated NET_VECTOR.
198 @param Nbuf Pointer to the NET_BUF to be freed.
209 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
210 ASSERT (Nbuf
->RefCnt
> 0);
214 if (Nbuf
->RefCnt
== 0) {
216 // Update Vector only when NBuf is to be released. That is,
217 // all the sharing of Nbuf increse Vector's RefCnt by one
219 NetbufFreeVector (Nbuf
->Vector
);
220 gBS
->FreePool (Nbuf
);
226 Create a copy of NET_BUF that share the associated NET_DATA.
228 @param Nbuf Pointer to the net buffer to be cloned.
230 @retval * Pointer to the cloned net buffer.
241 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
243 Clone
= AllocatePool (NET_BUF_SIZE (Nbuf
->BlockOpNum
));
249 Clone
->Signature
= NET_BUF_SIGNATURE
;
251 InitializeListHead (&Clone
->List
);
253 Clone
->Ip
= Nbuf
->Ip
;
254 Clone
->Tcp
= Nbuf
->Tcp
;
256 CopyMem (Clone
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
258 NET_GET_REF (Nbuf
->Vector
);
260 Clone
->Vector
= Nbuf
->Vector
;
261 Clone
->BlockOpNum
= Nbuf
->BlockOpNum
;
262 Clone
->TotalSize
= Nbuf
->TotalSize
;
263 CopyMem (Clone
->BlockOp
, Nbuf
->BlockOp
, sizeof (NET_BLOCK_OP
) * Nbuf
->BlockOpNum
);
270 Create a duplicated copy of Nbuf, data is copied. Also leave some
271 head space before the data.
273 @param Nbuf Pointer to the net buffer to be cloned.
274 @param Duplicate Pointer to the net buffer to duplicate to, if NULL
275 a new net buffer is allocated.
276 @param HeadSpace Length of the head space to reserve
278 @retval * Pointer to the duplicated net buffer.
285 IN NET_BUF
*Duplicate OPTIONAL
,
291 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
293 if (Duplicate
== NULL
) {
294 Duplicate
= NetbufAlloc (Nbuf
->TotalSize
+ HeadSpace
);
297 if (Duplicate
== NULL
) {
302 // Don't set the IP and TCP head point, since it is most
303 // like that they are pointing to the memory of Nbuf.
305 CopyMem (Duplicate
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
306 NetbufReserve (Duplicate
, HeadSpace
);
308 Dst
= NetbufAllocSpace (Duplicate
, Nbuf
->TotalSize
, NET_BUF_TAIL
);
309 NetbufCopy (Nbuf
, 0, Nbuf
->TotalSize
, Dst
);
316 Free a list of net buffers.
318 @param Head Pointer to the head of linked net buffers.
333 Entry
= Head
->ForwardLink
;
335 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Head
) {
336 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
337 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
339 RemoveEntryList (Entry
);
343 ASSERT (IsListEmpty (Head
));
348 Get the position of some byte in the net buffer. This can be used
349 to, for example, retrieve the IP header in the packet. It also
350 returns the fragment that contains the byte which is used mainly by
351 the buffer implementation itself.
353 @param Nbuf Pointer to the net buffer.
354 @param Offset The index or offset of the byte
355 @param Index Index of the fragment that contains the block
357 @retval * Pointer to the nth byte of data in the net buffer.
358 If NULL, there is no such data in the net buffer.
366 OUT UINT32
*Index OPTIONAL
369 NET_BLOCK_OP
*BlockOp
;
373 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
375 if (Offset
>= Nbuf
->TotalSize
) {
379 BlockOp
= Nbuf
->BlockOp
;
382 for (Loop
= 0; Loop
< Nbuf
->BlockOpNum
; Loop
++) {
384 if (Len
+ BlockOp
[Loop
].Size
<= Offset
) {
385 Len
+= BlockOp
[Loop
].Size
;
393 return BlockOp
[Loop
].Head
+ (Offset
- Len
);
402 Set the NET_BLOCK and corresponding NET_BLOCK_OP in
403 the buffer. All the pointers in NET_BLOCK and NET_BLOCK_OP
404 are set to the bulk's head and tail respectively. So, this
405 function alone can't be used by NetbufAlloc.
407 @param Nbuf Pointer to the net buffer.
408 @param Bulk Pointer to the data.
409 @param Len Length of the bulk data.
410 @param Index The data block index in the net buffer the bulk
411 data should belong to.
424 NET_BLOCK_OP
*BlockOp
;
427 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
428 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
429 ASSERT (Index
< Nbuf
->BlockOpNum
);
431 Block
= &(Nbuf
->Vector
->Block
[Index
]);
432 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
435 BlockOp
->BlockHead
= Bulk
;
436 BlockOp
->BlockTail
= Bulk
+ Len
;
437 BlockOp
->Head
= Bulk
;
438 BlockOp
->Tail
= Bulk
+ Len
;
445 Set the NET_BLOCK_OP in the buffer. The corresponding NET_BLOCK
446 structure is left untouched. Some times, there is no 1:1 relationship
447 between NET_BLOCK and NET_BLOCK_OP. For example, that in NetbufGetFragment.
449 @param Nbuf Pointer to the net buffer.
450 @param Bulk Pointer to the data.
451 @param Len Length of the bulk data.
452 @param Index The data block index in the net buffer the bulk
453 data should belong to.
466 NET_BLOCK_OP
*BlockOp
;
468 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
469 ASSERT (Index
< Nbuf
->BlockOpNum
);
471 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
472 BlockOp
->BlockHead
= Bulk
;
473 BlockOp
->BlockTail
= Bulk
+ Len
;
474 BlockOp
->Head
= Bulk
;
475 BlockOp
->Tail
= Bulk
+ Len
;
481 Helper function for NetbufClone. It is necessary because NetbufGetFragment
482 may allocate the first block to accomodate the HeadSpace and HeadLen. So, it
483 need to create a new NET_VECTOR. But, we want to avoid data copy by sharing
486 @param Arg Point to the old NET_VECTOR
492 NetbufGetFragmentFree (
498 Vector
= (NET_VECTOR
*)Arg
;
499 NetbufFreeVector (Vector
);
505 Create a NET_BUF structure which contains Len byte data of
506 Nbuf starting from Offset. A new NET_BUF structure will be
507 created but the associated data in NET_VECTOR is shared.
508 This function exists to do IP packet fragmentation.
510 @param Nbuf Pointer to the net buffer to be cloned.
511 @param Offset Starting point of the data to be included in new
513 @param Len How many data to include in new data
514 @param HeadSpace How many bytes of head space to reserve for
517 @retval * Pointer to the cloned net buffer.
531 NET_BLOCK_OP
*BlockOp
;
543 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
545 if ((Len
== 0) || (Offset
+ Len
> Nbuf
->TotalSize
)) {
550 // First find the first and last BlockOp that contains
551 // the valid data, and compute the offset of the first
552 // BlockOp and length of the last BlockOp
554 BlockOp
= Nbuf
->BlockOp
;
557 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
558 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
562 Cur
+= BlockOp
[Index
].Size
;
566 // First is the index of the first BlockOp, FirstSkip is
567 // the offset of the first byte in the first BlockOp.
570 FirstSkip
= Offset
- Cur
;
571 FirstLen
= BlockOp
[Index
].Size
- FirstSkip
;
574 //redundant assignment to make compiler happy.
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 BlockOpNum
= Last
- First
+ 1;
602 if (HeadSpace
!= 0) {
604 // Allocate an extra block to accomdate the head space.
608 Child
= NetbufAllocStruct (1, BlockOpNum
);
614 FirstBulk
= AllocatePool (HeadSpace
);
616 if (FirstBulk
== NULL
) {
620 Vector
= Child
->Vector
;
621 Vector
->Free
= NetbufGetFragmentFree
;
622 Vector
->Arg
= Nbuf
->Vector
;
623 Vector
->Flag
= NET_VECTOR_OWN_FIRST
;
624 Vector
->Len
= HeadSpace
;
627 //Reserve the head space in the first block
629 NetbufSetBlock (Child
, FirstBulk
, HeadSpace
, 0);
630 Child
->BlockOp
[0].Head
+= HeadSpace
;
631 Child
->BlockOp
[0].Size
= 0;
635 Child
= NetbufAllocStruct (0, BlockOpNum
);
641 Child
->Vector
= Nbuf
->Vector
;
644 NET_GET_REF (Nbuf
->Vector
);
645 Child
->TotalSize
= Len
;
648 // Set all the BlockOp up, the first and last one are special
649 // and need special process.
653 Nbuf
->BlockOp
[First
].Head
+ FirstSkip
,
658 for (Index
= First
+ 1; Index
<= Last
- 1 ; Index
++) {
676 CopyMem (Child
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
681 gBS
->FreePool (Child
);
688 Build a NET_BUF from external blocks.
690 @param ExtFragment Pointer to the data block.
691 @param ExtNum The number of the data block.
692 @param HeadSpace The head space to be reserved.
693 @param HeadLen The length of the protocol header, This function
694 will pull that number of data into a linear block.
695 @param ExtFree Pointer to the caller provided free function.
696 @param Arg The argument passed to ExtFree when ExtFree is
699 @retval * Pointer to the net buffer built from the data
706 IN NET_FRAGMENT
*ExtFragment
,
710 IN NET_VECTOR_EXT_FREE ExtFree
,
711 IN VOID
*Arg OPTIONAL
716 NET_FRAGMENT SavedFragment
;
721 UINT32 FirstBlockLen
;
728 ASSERT ((ExtFragment
!= NULL
) && (ExtNum
> 0) && (ExtFree
!= NULL
));
730 SavedFragment
.Bulk
= NULL
;
731 SavedFragment
.Len
= 0;
743 // No need to consolidate the header if the first block is
744 // longer than the header length or there is only one block.
746 if ((ExtFragment
[0].Len
>= HeadLen
) || (ExtNum
== 1)) {
751 // Allocate an extra block if we need to:
752 // 1. Allocate some header space
753 // 2. aggreate the packet header
755 if ((HeadSpace
!= 0) || (HeadLen
!= 0)) {
756 FirstBlockLen
= HeadLen
+ HeadSpace
;
757 FirstBlock
= AllocatePool (FirstBlockLen
);
759 if (FirstBlock
== NULL
) {
767 // Copy the header to the first block, reduce the NET_BLOCK
768 // to allocate by one for each block that is completely covered
769 // by the first bulk.
773 Header
= FirstBlock
+ HeadSpace
;
775 for (Index
= 0; Index
< ExtNum
; Index
++) {
776 if (Len
>= ExtFragment
[Index
].Len
) {
777 CopyMem (Header
, ExtFragment
[Index
].Bulk
, ExtFragment
[Index
].Len
);
779 Copied
+= ExtFragment
[Index
].Len
;
780 Len
-= ExtFragment
[Index
].Len
;
781 Header
+= ExtFragment
[Index
].Len
;
782 TotalLen
+= ExtFragment
[Index
].Len
;
787 // Increament the index number to point to the next
788 // non-empty fragment.
795 CopyMem (Header
, ExtFragment
[Index
].Bulk
, Len
);
801 // Adjust the block structure to exclude the data copied,
802 // So, the left-over block can be processed as other blocks.
803 // But it must be recovered later. (SavedIndex > 0) always
804 // holds since we don't aggreate the header if the first block
805 // is bigger enough that the header is continuous
808 SavedFragment
= ExtFragment
[Index
];
809 ExtFragment
[Index
].Bulk
+= Len
;
810 ExtFragment
[Index
].Len
-= Len
;
816 Nbuf
= NetbufAllocStruct (BlockNum
, BlockNum
);
822 Vector
= Nbuf
->Vector
;
823 Vector
->Free
= ExtFree
;
825 Vector
->Flag
= (FirstBlockLen
? NET_VECTOR_OWN_FIRST
: 0);
828 // Set the first block up which may contain
829 // some head space and aggregated header
833 if (FirstBlockLen
!= 0) {
834 NetbufSetBlock (Nbuf
, FirstBlock
, HeadSpace
+ Copied
, 0);
835 Nbuf
->BlockOp
[0].Head
+= HeadSpace
;
836 Nbuf
->BlockOp
[0].Size
= Copied
;
841 for (; Index
< ExtNum
; Index
++) {
842 NetbufSetBlock (Nbuf
, ExtFragment
[Index
].Bulk
, ExtFragment
[Index
].Len
, CurBlock
);
843 TotalLen
+= ExtFragment
[Index
].Len
;
847 Vector
->Len
= TotalLen
+ HeadSpace
;
848 Nbuf
->TotalSize
= TotalLen
;
851 ExtFragment
[SavedIndex
] = SavedFragment
;
857 gBS
->FreePool (FirstBlock
);
863 Build a fragment table to contain the fragments in the
864 buffer. This is the opposite of the NetbufFromExt.
866 @param Nbuf Point to the net buffer
867 @param ExtFragment Pointer to the data block.
868 @param ExtNum The number of the data block.
870 @retval EFI_BUFFER_TOO_SMALL The number of non-empty block is bigger than ExtNum
871 @retval EFI_SUCCESS Fragment table built.
878 IN NET_FRAGMENT
*ExtFragment
,
887 for (Index
= 0; (Index
< Nbuf
->BlockOpNum
); Index
++) {
888 if (Nbuf
->BlockOp
[Index
].Size
== 0) {
892 if (Current
< *ExtNum
) {
893 ExtFragment
[Current
].Bulk
= Nbuf
->BlockOp
[Index
].Head
;
894 ExtFragment
[Current
].Len
= Nbuf
->BlockOp
[Index
].Size
;
897 return EFI_BUFFER_TOO_SMALL
;
907 Build a NET_BUF from a list of NET_BUF.
909 @param BufList A List of NET_BUF.
910 @param HeadSpace The head space to be reserved.
911 @param HeaderLen The length of the protocol header, This function
912 will pull that number of data into a linear block.
913 @param ExtFree Pointer to the caller provided free function.
914 @param Arg The argument passed to ExtFree when ExtFree is
917 @retval * Pointer to the net buffer built from the data
924 IN LIST_ENTRY
*BufList
,
927 IN NET_VECTOR_EXT_FREE ExtFree
,
928 IN VOID
*Arg OPTIONAL
931 NET_FRAGMENT
*Fragment
;
939 //Compute how many blocks are there
943 NET_LIST_FOR_EACH (Entry
, BufList
) {
944 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
945 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
946 FragmentNum
+= Nbuf
->BlockOpNum
;
950 //Allocate and copy block points
952 Fragment
= AllocatePool (sizeof (NET_FRAGMENT
) * FragmentNum
);
954 if (Fragment
== NULL
) {
960 NET_LIST_FOR_EACH (Entry
, BufList
) {
961 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
962 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
964 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
965 if (Nbuf
->BlockOp
[Index
].Size
) {
966 Fragment
[Current
].Bulk
= Nbuf
->BlockOp
[Index
].Head
;
967 Fragment
[Current
].Len
= Nbuf
->BlockOp
[Index
].Size
;
973 Nbuf
= NetbufFromExt (Fragment
, Current
, HeadSpace
, HeaderLen
, ExtFree
, Arg
);
974 gBS
->FreePool (Fragment
);
981 Reserve some space in the header room of the buffer.
982 Upon allocation, all the space are in the tail room
983 of the buffer. Call this function to move some space
984 to the header room. This function is quite limited in
985 that it can only reserver space from the first block
986 of an empty NET_BUF not built from the external. But
987 it should be enough for the network stack.
989 @param Nbuf Pointer to the net buffer.
990 @param Len The length of buffer to be reserverd.
1002 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1003 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1005 ASSERT ((Nbuf
->BlockOpNum
== 1) && (Nbuf
->TotalSize
== 0));
1006 ASSERT ((Nbuf
->Vector
->Free
== NULL
) && (Nbuf
->Vector
->Len
>= Len
));
1008 Nbuf
->BlockOp
[0].Head
+= Len
;
1009 Nbuf
->BlockOp
[0].Tail
+= Len
;
1011 ASSERT (Nbuf
->BlockOp
[0].Tail
<= Nbuf
->BlockOp
[0].BlockTail
);
1016 Allocate some space from the header or tail of the buffer.
1018 @param Nbuf Pointer to the net buffer.
1019 @param Len The length of the buffer to be allocated.
1020 @param FromHead The flag to indicate whether reserve the data from
1021 head or tail. TRUE for from head, and FALSE for
1024 @retval * Pointer to the first byte of the allocated buffer.
1035 NET_BLOCK_OP
*BlockOp
;
1039 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1040 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1046 // Allocate some space from head. If the buffer is empty,
1047 // allocate from the first block. If it isn't, allocate
1048 // from the first non-empty block, or the block before that.
1050 if (Nbuf
->TotalSize
== 0) {
1053 NetbufGetByte (Nbuf
, 0, &Index
);
1055 if ((NET_HEADSPACE(&(Nbuf
->BlockOp
[Index
])) < Len
) && (Index
> 0)) {
1060 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
1062 if (NET_HEADSPACE (BlockOp
) < Len
) {
1066 BlockOp
->Head
-= Len
;
1067 BlockOp
->Size
+= Len
;
1068 Nbuf
->TotalSize
+= Len
;
1070 return BlockOp
->Head
;
1074 // Allocate some space from the tail. If the buffer is empty,
1075 // allocate from the first block. If it isn't, allocate
1076 // from the last non-empty block, or the block after that.
1078 if (Nbuf
->TotalSize
== 0) {
1081 NetbufGetByte (Nbuf
, Nbuf
->TotalSize
- 1, &Index
);
1083 if ((NET_TAILSPACE(&(Nbuf
->BlockOp
[Index
])) < Len
) &&
1084 (Index
< Nbuf
->BlockOpNum
- 1)) {
1090 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
1092 if (NET_TAILSPACE (BlockOp
) < Len
) {
1096 SavedTail
= BlockOp
->Tail
;
1098 BlockOp
->Tail
+= Len
;
1099 BlockOp
->Size
+= Len
;
1100 Nbuf
->TotalSize
+= Len
;
1108 Trim a single NET_BLOCK.
1110 @param BlockOp Pointer to the NET_BLOCK.
1111 @param Len The length of the data to be trimmed.
1112 @param FromHead The flag to indicate whether trim data from head or
1113 tail. TRUE for from head, and FALSE for from tail.
1120 IN NET_BLOCK_OP
*BlockOp
,
1125 ASSERT (BlockOp
&& (BlockOp
->Size
>= Len
));
1127 BlockOp
->Size
-= Len
;
1130 BlockOp
->Head
+= Len
;
1132 BlockOp
->Tail
-= Len
;
1138 Trim some data from the header or tail of the buffer.
1140 @param Nbuf Pointer to the net buffer.
1141 @param Len The length of the data to be trimmed.
1142 @param FromHead The flag to indicate whether trim data from head or
1143 tail. TRUE for from head, and FALSE for from tail.
1145 @retval UINTN Length of the actually trimmed data.
1156 NET_BLOCK_OP
*BlockOp
;
1160 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1162 if (Len
> Nbuf
->TotalSize
) {
1163 Len
= Nbuf
->TotalSize
;
1167 // If FromTail is true, iterate backward. That
1168 // is, init Index to NBuf->BlockNum - 1, and
1169 // decrease it by 1 during each loop. Otherwise,
1170 // iterate forward. That is, init Index to 0, and
1171 // increase it by 1 during each loop.
1174 Nbuf
->TotalSize
-= Len
;
1176 Index
= (FromHead
? 0 : Nbuf
->BlockOpNum
- 1);
1177 BlockOp
= Nbuf
->BlockOp
;
1180 if (BlockOp
[Index
].Size
== 0) {
1181 Index
+= (FromHead
? 1 : -1);
1185 if (Len
> BlockOp
[Index
].Size
) {
1186 Len
-= BlockOp
[Index
].Size
;
1187 Trimmed
+= BlockOp
[Index
].Size
;
1188 NetblockTrim (&BlockOp
[Index
], BlockOp
[Index
].Size
, FromHead
);
1191 NetblockTrim (&BlockOp
[Index
], Len
, FromHead
);
1195 Index
+= (FromHead
? 1 : -1);
1203 Copy the data from the specific offset to the destination.
1205 @param Nbuf Pointer to the net buffer.
1206 @param Offset The sequence number of the first byte to copy.
1207 @param Len Length of the data to copy.
1208 @param Dest The destination of the data to copy to.
1210 @retval UINTN The length of the copied data.
1222 NET_BLOCK_OP
*BlockOp
;
1229 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1232 if ((Len
== 0) || (Nbuf
->TotalSize
<= Offset
)) {
1236 if (Nbuf
->TotalSize
- Offset
< Len
) {
1237 Len
= Nbuf
->TotalSize
- Offset
;
1240 BlockOp
= Nbuf
->BlockOp
;
1243 // Skip to the offset. Don't make "Offset-By-One" error here.
1244 // Cur + BLOCK.SIZE is the first sequence number of next block.
1245 // So, (Offset < Cur + BLOCK.SIZE) means that the first byte
1246 // is in the current block. if (Offset == Cur + BLOCK.SIZE), the
1247 // first byte is the next block's first byte.
1251 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1252 if (BlockOp
[Index
].Size
== 0) {
1256 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
1260 Cur
+= BlockOp
[Index
].Size
;
1264 // Cur is the sequence number of the first byte in the block
1265 // Offset - Cur is the number of bytes before first byte to
1266 // to copy in the current block.
1268 Skip
= Offset
- Cur
;
1269 Left
= BlockOp
[Index
].Size
- Skip
;
1272 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Len
);
1276 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Left
);
1284 for (; Index
< Nbuf
->BlockOpNum
; Index
++) {
1285 if (Len
> BlockOp
[Index
].Size
) {
1286 Len
-= BlockOp
[Index
].Size
;
1287 Copied
+= BlockOp
[Index
].Size
;
1289 CopyMem (Dest
, BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1290 Dest
+= BlockOp
[Index
].Size
;
1293 CopyMem (Dest
, BlockOp
[Index
].Head
, Len
);
1303 Initiate the net buffer queue.
1305 @param NbufQue Pointer to the net buffer queue to be initiated.
1313 IN NET_BUF_QUEUE
*NbufQue
1316 NbufQue
->Signature
= NET_QUE_SIGNATURE
;
1317 NbufQue
->RefCnt
= 1;
1318 InitializeListHead (&NbufQue
->List
);
1320 InitializeListHead (&NbufQue
->BufList
);
1321 NbufQue
->BufSize
= 0;
1322 NbufQue
->BufNum
= 0;
1327 Allocate an initialized net buffer queue.
1331 @retval * Pointer to the allocated net buffer queue.
1340 NET_BUF_QUEUE
*NbufQue
;
1342 NbufQue
= AllocatePool (sizeof (NET_BUF_QUEUE
));
1343 if (NbufQue
== NULL
) {
1347 NetbufQueInit (NbufQue
);
1354 Free a net buffer queue.
1356 @param NbufQue Poitner to the net buffer queue to be freed.
1364 IN NET_BUF_QUEUE
*NbufQue
1367 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1371 if (NbufQue
->RefCnt
== 0) {
1372 NetbufQueFlush (NbufQue
);
1373 gBS
->FreePool (NbufQue
);
1379 Append a buffer to the end of the queue.
1381 @param NbufQue Pointer to the net buffer queue.
1382 @param Nbuf Pointer to the net buffer to be appended.
1390 IN NET_BUF_QUEUE
*NbufQue
,
1394 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1395 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1397 InsertTailList (&NbufQue
->BufList
, &Nbuf
->List
);
1399 NbufQue
->BufSize
+= Nbuf
->TotalSize
;
1405 Remove a net buffer from head in the specific queue.
1407 @param NbufQue Pointer to the net buffer queue.
1409 @retval * Pointer to the net buffer removed from the specific
1416 IN NET_BUF_QUEUE
*NbufQue
1421 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1423 if (NbufQue
->BufNum
== 0) {
1427 First
= NET_LIST_USER_STRUCT (NbufQue
->BufList
.ForwardLink
, NET_BUF
, List
);
1429 NetListRemoveHead (&NbufQue
->BufList
);
1431 NbufQue
->BufSize
-= First
->TotalSize
;
1438 Copy some data from the buffer queue to the destination.
1440 @param NbufQue Pointer to the net buffer queue.
1441 @param Offset The sequence number of the first byte to copy.
1442 @param Len Length of the data to copy.
1443 @param Dest The destination of the data to copy to.
1445 @retval UINTN The length of the copied data.
1450 IN NET_BUF_QUEUE
*NbufQue
,
1463 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1464 ASSERT (Dest
!= NULL
);
1466 if ((Len
== 0) || (NbufQue
->BufSize
<= Offset
)) {
1470 if (NbufQue
->BufSize
- Offset
< Len
) {
1471 Len
= NbufQue
->BufSize
- Offset
;
1475 // skip to the Offset
1480 NET_LIST_FOR_EACH (Entry
, &NbufQue
->BufList
) {
1481 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1483 if (Offset
< Cur
+ Nbuf
->TotalSize
) {
1487 Cur
+= Nbuf
->TotalSize
;
1491 // Copy the data in the first buffer.
1493 Skip
= Offset
- Cur
;
1494 Left
= Nbuf
->TotalSize
- Skip
;
1497 return NetbufCopy (Nbuf
, Skip
, Len
, Dest
);
1500 NetbufCopy (Nbuf
, Skip
, Left
, Dest
);
1506 // Iterate over the others
1508 Entry
= Entry
->ForwardLink
;
1510 while ((Len
> 0) && (Entry
!= &NbufQue
->BufList
)) {
1511 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1513 if (Len
> Nbuf
->TotalSize
) {
1514 Len
-= Nbuf
->TotalSize
;
1515 Copied
+= Nbuf
->TotalSize
;
1517 NetbufCopy (Nbuf
, 0, Nbuf
->TotalSize
, Dest
);
1518 Dest
+= Nbuf
->TotalSize
;
1521 NetbufCopy (Nbuf
, 0, Len
, Dest
);
1526 Entry
= Entry
->ForwardLink
;
1534 Trim some data from the queue header, release the buffer if
1535 whole buffer is trimmed.
1537 @param NbufQue Pointer to the net buffer queue.
1538 @param Len Length of the data to trim.
1540 @retval UINTN The length of the data trimmed.
1546 IN NET_BUF_QUEUE
*NbufQue
,
1555 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1561 if (Len
> NbufQue
->BufSize
) {
1562 Len
= NbufQue
->BufSize
;
1565 NbufQue
->BufSize
-= Len
;
1568 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &NbufQue
->BufList
) {
1569 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1571 if (Len
>= Nbuf
->TotalSize
) {
1572 Trimmed
+= Nbuf
->TotalSize
;
1573 Len
-= Nbuf
->TotalSize
;
1575 RemoveEntryList (Entry
);
1585 Trimmed
+= NetbufTrim (Nbuf
, Len
, NET_BUF_HEAD
);
1595 Flush the net buffer queue.
1597 @param NbufQue Pointer to the queue to be flushed.
1605 IN NET_BUF_QUEUE
*NbufQue
1608 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1610 NetbufFreeList (&NbufQue
->BufList
);
1612 NbufQue
->BufNum
= 0;
1613 NbufQue
->BufSize
= 0;
1618 Compute checksum for a bulk of data.
1620 @param Bulk Pointer to the data.
1621 @param Len Length of the data, in bytes.
1623 @retval UINT16 The computed checksum.
1633 register UINT32 Sum
;
1638 Sum
+= *(UINT16
*) Bulk
;
1644 // Add left-over byte, if any
1647 Sum
+= *(UINT8
*) Bulk
;
1651 // Fold 32-bit sum to 16 bits
1654 Sum
= (Sum
& 0xffff) + (Sum
>> 16);
1658 return (UINT16
) Sum
;
1665 @param Checksum1 The first checksum to be added.
1666 @param Checksum2 The second checksum to be added.
1668 @retval UINT16 The new checksum.
1674 IN UINT16 Checksum1
,
1680 Sum
= Checksum1
+ Checksum2
;
1683 // two UINT16 can only add up to a carry of 1.
1686 Sum
= (Sum
& 0xffff) + 1;
1690 return (UINT16
) Sum
;
1695 Compute the checksum for a NET_BUF.
1697 @param Nbuf Pointer to the net buffer.
1699 @retval UINT16 The computed checksum.
1708 NET_BLOCK_OP
*BlockOp
;
1714 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1718 BlockOp
= Nbuf
->BlockOp
;
1720 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1721 if (BlockOp
[Index
].Size
== 0) {
1725 BlockSum
= NetblockChecksum (BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1727 if (Offset
& 0x01) {
1729 // The checksum starts with an odd byte, swap
1730 // the checksum before added to total checksum
1732 BlockSum
= (UINT16
) NET_SWAP_SHORT (BlockSum
);
1735 TotalSum
= NetAddChecksum (BlockSum
, TotalSum
);
1736 Offset
+= BlockOp
[Index
].Size
;
1744 Compute the checksum for TCP/UDP pseudo header.
1745 Src, Dst are in network byte order. and Len is
1748 @param Src The source address of the packet.
1749 @param Dst The destination address of the packet.
1750 @param Proto The protocol type of the packet.
1751 @param Len The length of the packet.
1753 @retval UINT16 The computed checksum.
1758 NetPseudoHeadChecksum (
1768 // Zero the memory to relieve align problems
1770 ZeroMem (&Hdr
, sizeof (Hdr
));
1774 Hdr
.Protocol
= Proto
;
1775 Hdr
.Len
= HTONS (Len
);
1777 return NetblockChecksum ((UINT8
*) &Hdr
, sizeof (Hdr
));