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.
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.
157 IN NET_VECTOR
*Vector
162 NET_CHECK_SIGNATURE (Vector
, NET_VECTOR_SIGNATURE
);
163 ASSERT (Vector
->RefCnt
> 0);
167 if (Vector
->RefCnt
> 0) {
171 if (Vector
->Free
!= NULL
) {
173 // Call external free function to free the vector if it
174 // isn't NULL. If NET_VECTOR_OWN_FIRST is set, release the
175 // first block since it is allocated by us
177 if (Vector
->Flag
& NET_VECTOR_OWN_FIRST
) {
178 gBS
->FreePool (Vector
->Block
[0].Bulk
);
181 Vector
->Free (Vector
->Arg
);
185 // Free each memory block associated with the Vector
187 for (Index
= 0; Index
< Vector
->BlockNum
; Index
++) {
188 gBS
->FreePool (Vector
->Block
[Index
].Bulk
);
192 gBS
->FreePool (Vector
);
197 Free the buffer and its associated NET_VECTOR.
199 @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.
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 Nbuf, data is copied. Also leave some
270 head space before the data.
272 @param Nbuf Pointer to the net buffer to be cloned.
273 @param Duplicate Pointer to the net buffer to duplicate to, if NULL
274 a new net buffer is allocated.
275 @param HeadSpace Length of the head space to reserve
277 @retval * Pointer to the duplicated net buffer.
283 IN NET_BUF
*Duplicate OPTIONAL
,
289 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
291 if (Duplicate
== NULL
) {
292 Duplicate
= NetbufAlloc (Nbuf
->TotalSize
+ HeadSpace
);
295 if (Duplicate
== NULL
) {
300 // Don't set the IP and TCP head point, since it is most
301 // like that they are pointing to the memory of Nbuf.
303 CopyMem (Duplicate
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
304 NetbufReserve (Duplicate
, HeadSpace
);
306 Dst
= NetbufAllocSpace (Duplicate
, Nbuf
->TotalSize
, NET_BUF_TAIL
);
307 NetbufCopy (Nbuf
, 0, Nbuf
->TotalSize
, Dst
);
314 Free a list of net buffers.
316 @param Head Pointer to the head of linked net buffers.
330 Entry
= Head
->ForwardLink
;
332 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Head
) {
333 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
334 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
336 RemoveEntryList (Entry
);
340 ASSERT (IsListEmpty (Head
));
345 Get the position of some byte in the net buffer. This can be used
346 to, for example, retrieve the IP header in the packet. It also
347 returns the fragment that contains the byte which is used mainly by
348 the buffer implementation itself.
350 @param Nbuf Pointer to the net buffer.
351 @param Offset The index or offset of the byte
352 @param Index Index of the fragment that contains the block
354 @retval * Pointer to the nth byte of data in the net buffer.
355 If NULL, 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
++) {
380 if (Len
+ BlockOp
[Loop
].Size
<= Offset
) {
381 Len
+= BlockOp
[Loop
].Size
;
389 return BlockOp
[Loop
].Head
+ (Offset
- Len
);
398 Set the NET_BLOCK and corresponding NET_BLOCK_OP in
399 the buffer. All the pointers in NET_BLOCK and NET_BLOCK_OP
400 are set to the bulk's head and tail respectively. So, this
401 function alone can't be used by NetbufAlloc.
403 @param Nbuf Pointer to the net buffer.
404 @param Bulk Pointer to the data.
405 @param Len Length of the bulk data.
406 @param Index The data block index in the net buffer the bulk
407 data should belong to.
421 NET_BLOCK_OP
*BlockOp
;
424 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
425 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
426 ASSERT (Index
< Nbuf
->BlockOpNum
);
428 Block
= &(Nbuf
->Vector
->Block
[Index
]);
429 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
432 BlockOp
->BlockHead
= Bulk
;
433 BlockOp
->BlockTail
= Bulk
+ Len
;
434 BlockOp
->Head
= Bulk
;
435 BlockOp
->Tail
= Bulk
+ Len
;
442 Set the NET_BLOCK_OP in the buffer. The corresponding NET_BLOCK
443 structure is left untouched. Some times, there is no 1:1 relationship
444 between NET_BLOCK and NET_BLOCK_OP. For example, that in NetbufGetFragment.
446 @param Nbuf Pointer to the net buffer.
447 @param Bulk Pointer to the data.
448 @param Len Length of the bulk data.
449 @param Index The data block index in the net buffer the bulk
450 data should belong to.
464 NET_BLOCK_OP
*BlockOp
;
466 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
467 ASSERT (Index
< Nbuf
->BlockOpNum
);
469 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
470 BlockOp
->BlockHead
= Bulk
;
471 BlockOp
->BlockTail
= Bulk
+ Len
;
472 BlockOp
->Head
= Bulk
;
473 BlockOp
->Tail
= Bulk
+ Len
;
479 Helper function for NetbufClone. It is necessary because NetbufGetFragment
480 may allocate the first block to accomodate the HeadSpace and HeadLen. So, it
481 need to create a new NET_VECTOR. But, we want to avoid data copy by sharing
484 @param Arg Point to the old NET_VECTOR
491 NetbufGetFragmentFree (
497 Vector
= (NET_VECTOR
*)Arg
;
498 NetbufFreeVector (Vector
);
504 Create a NET_BUF structure which contains Len byte data of
505 Nbuf starting from Offset. A new NET_BUF structure will be
506 created but the associated data in NET_VECTOR is shared.
507 This function exists to do IP packet fragmentation.
509 @param Nbuf Pointer to the net buffer to be cloned.
510 @param Offset Starting point of the data to be included in new
512 @param Len How many data to include in new data
513 @param HeadSpace How many bytes of head space to reserve for
516 @retval * Pointer to the cloned net buffer.
529 NET_BLOCK_OP
*BlockOp
;
541 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
543 if ((Len
== 0) || (Offset
+ Len
> Nbuf
->TotalSize
)) {
548 // First find the first and last BlockOp that contains
549 // the valid data, and compute the offset of the first
550 // BlockOp and length of the last BlockOp
552 BlockOp
= Nbuf
->BlockOp
;
555 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
556 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
560 Cur
+= BlockOp
[Index
].Size
;
564 // First is the index of the first BlockOp, FirstSkip is
565 // the offset of the first byte in the first BlockOp.
568 FirstSkip
= Offset
- Cur
;
569 FirstLen
= BlockOp
[Index
].Size
- FirstSkip
;
572 //redundant assignment to make compiler happy.
577 if (Len
> FirstLen
) {
578 Cur
+= BlockOp
[Index
].Size
;
581 for (; Index
< Nbuf
->BlockOpNum
; Index
++) {
582 if (Offset
+ Len
<= Cur
+ BlockOp
[Index
].Size
) {
584 LastLen
= Offset
+ Len
- Cur
;
588 Cur
+= BlockOp
[Index
].Size
;
597 BlockOpNum
= Last
- First
+ 1;
600 if (HeadSpace
!= 0) {
602 // Allocate an extra block to accomdate the head space.
606 Child
= NetbufAllocStruct (1, BlockOpNum
);
612 FirstBulk
= AllocatePool (HeadSpace
);
614 if (FirstBulk
== NULL
) {
618 Vector
= Child
->Vector
;
619 Vector
->Free
= NetbufGetFragmentFree
;
620 Vector
->Arg
= Nbuf
->Vector
;
621 Vector
->Flag
= NET_VECTOR_OWN_FIRST
;
622 Vector
->Len
= HeadSpace
;
625 //Reserve the head space in the first block
627 NetbufSetBlock (Child
, FirstBulk
, HeadSpace
, 0);
628 Child
->BlockOp
[0].Head
+= HeadSpace
;
629 Child
->BlockOp
[0].Size
= 0;
633 Child
= NetbufAllocStruct (0, BlockOpNum
);
639 Child
->Vector
= Nbuf
->Vector
;
642 NET_GET_REF (Nbuf
->Vector
);
643 Child
->TotalSize
= Len
;
646 // Set all the BlockOp up, the first and last one are special
647 // and need special process.
651 Nbuf
->BlockOp
[First
].Head
+ FirstSkip
,
656 for (Index
= First
+ 1; Index
< Last
; Index
++) {
674 CopyMem (Child
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
679 gBS
->FreePool (Child
);
686 Build a NET_BUF from external blocks.
688 @param ExtFragment Pointer to the data block.
689 @param ExtNum The number of the data block.
690 @param HeadSpace The head space to be reserved.
691 @param HeadLen The length of the protocol header, This function
692 will pull that number of data into a linear block.
693 @param ExtFree Pointer to the caller provided free function.
694 @param Arg The argument passed to ExtFree when ExtFree is
697 @retval * Pointer to the net buffer built from the data
703 IN NET_FRAGMENT
*ExtFragment
,
707 IN NET_VECTOR_EXT_FREE ExtFree
,
708 IN VOID
*Arg OPTIONAL
713 NET_FRAGMENT SavedFragment
;
718 UINT32 FirstBlockLen
;
725 ASSERT ((ExtFragment
!= NULL
) && (ExtNum
> 0) && (ExtFree
!= NULL
));
727 SavedFragment
.Bulk
= NULL
;
728 SavedFragment
.Len
= 0;
740 // No need to consolidate the header if the first block is
741 // longer than the header length or there is only one block.
743 if ((ExtFragment
[0].Len
>= HeadLen
) || (ExtNum
== 1)) {
748 // Allocate an extra block if we need to:
749 // 1. Allocate some header space
750 // 2. aggreate the packet header
752 if ((HeadSpace
!= 0) || (HeadLen
!= 0)) {
753 FirstBlockLen
= HeadLen
+ HeadSpace
;
754 FirstBlock
= AllocatePool (FirstBlockLen
);
756 if (FirstBlock
== NULL
) {
764 // Copy the header to the first block, reduce the NET_BLOCK
765 // to allocate by one for each block that is completely covered
766 // by the first bulk.
770 Header
= FirstBlock
+ HeadSpace
;
772 for (Index
= 0; Index
< ExtNum
; Index
++) {
773 if (Len
>= ExtFragment
[Index
].Len
) {
774 CopyMem (Header
, ExtFragment
[Index
].Bulk
, ExtFragment
[Index
].Len
);
776 Copied
+= ExtFragment
[Index
].Len
;
777 Len
-= ExtFragment
[Index
].Len
;
778 Header
+= ExtFragment
[Index
].Len
;
779 TotalLen
+= ExtFragment
[Index
].Len
;
784 // Increament the index number to point to the next
785 // non-empty fragment.
792 CopyMem (Header
, ExtFragment
[Index
].Bulk
, Len
);
798 // Adjust the block structure to exclude the data copied,
799 // So, the left-over block can be processed as other blocks.
800 // But it must be recovered later. (SavedIndex > 0) always
801 // holds since we don't aggreate the header if the first block
802 // is bigger enough that the header is continuous
805 SavedFragment
= ExtFragment
[Index
];
806 ExtFragment
[Index
].Bulk
+= Len
;
807 ExtFragment
[Index
].Len
-= Len
;
813 Nbuf
= NetbufAllocStruct (BlockNum
, BlockNum
);
819 Vector
= Nbuf
->Vector
;
820 Vector
->Free
= ExtFree
;
822 Vector
->Flag
= (FirstBlockLen
? NET_VECTOR_OWN_FIRST
: 0);
825 // Set the first block up which may contain
826 // some head space and aggregated header
830 if (FirstBlockLen
!= 0) {
831 NetbufSetBlock (Nbuf
, FirstBlock
, HeadSpace
+ Copied
, 0);
832 Nbuf
->BlockOp
[0].Head
+= HeadSpace
;
833 Nbuf
->BlockOp
[0].Size
= Copied
;
838 for (; Index
< ExtNum
; Index
++) {
839 NetbufSetBlock (Nbuf
, ExtFragment
[Index
].Bulk
, ExtFragment
[Index
].Len
, CurBlock
);
840 TotalLen
+= ExtFragment
[Index
].Len
;
844 Vector
->Len
= TotalLen
+ HeadSpace
;
845 Nbuf
->TotalSize
= TotalLen
;
848 ExtFragment
[SavedIndex
] = SavedFragment
;
854 gBS
->FreePool (FirstBlock
);
860 Build a fragment table to contain the fragments in the
861 buffer. This is the opposite of the NetbufFromExt.
863 @param Nbuf Point to the net buffer
864 @param ExtFragment Pointer to the data block.
865 @param ExtNum The number of the data block.
867 @retval EFI_BUFFER_TOO_SMALL The number of non-empty block is bigger than ExtNum
868 @retval EFI_SUCCESS Fragment table built.
874 IN NET_FRAGMENT
*ExtFragment
,
883 for (Index
= 0; (Index
< Nbuf
->BlockOpNum
); Index
++) {
884 if (Nbuf
->BlockOp
[Index
].Size
== 0) {
888 if (Current
< *ExtNum
) {
889 ExtFragment
[Current
].Bulk
= Nbuf
->BlockOp
[Index
].Head
;
890 ExtFragment
[Current
].Len
= Nbuf
->BlockOp
[Index
].Size
;
893 return EFI_BUFFER_TOO_SMALL
;
903 Build a NET_BUF from a list of NET_BUF.
905 @param BufList A List of NET_BUF.
906 @param HeadSpace The head space to be reserved.
907 @param HeaderLen The length of the protocol header, This function
908 will pull that number of data into a linear block.
909 @param ExtFree Pointer to the caller provided free function.
910 @param Arg The argument passed to ExtFree when ExtFree is
913 @retval * Pointer to the net buffer built from the data
919 IN LIST_ENTRY
*BufList
,
922 IN NET_VECTOR_EXT_FREE ExtFree
,
923 IN VOID
*Arg OPTIONAL
926 NET_FRAGMENT
*Fragment
;
934 //Compute how many blocks are there
938 NET_LIST_FOR_EACH (Entry
, BufList
) {
939 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
940 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
941 FragmentNum
+= Nbuf
->BlockOpNum
;
945 //Allocate and copy block points
947 Fragment
= AllocatePool (sizeof (NET_FRAGMENT
) * FragmentNum
);
949 if (Fragment
== NULL
) {
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
);
959 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
960 if (Nbuf
->BlockOp
[Index
].Size
) {
961 Fragment
[Current
].Bulk
= Nbuf
->BlockOp
[Index
].Head
;
962 Fragment
[Current
].Len
= Nbuf
->BlockOp
[Index
].Size
;
968 Nbuf
= NetbufFromExt (Fragment
, Current
, HeadSpace
, HeaderLen
, ExtFree
, Arg
);
969 gBS
->FreePool (Fragment
);
976 Reserve some space in the header room of the buffer.
977 Upon allocation, all the space are in the tail room
978 of the buffer. Call this function to move some space
979 to the header room. This function is quite limited in
980 that it can only reserver space from the first block
981 of an empty NET_BUF not built from the external. But
982 it should be enough for the network stack.
984 @param Nbuf Pointer to the net buffer.
985 @param Len The length of buffer to be reserverd.
996 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
997 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
999 ASSERT ((Nbuf
->BlockOpNum
== 1) && (Nbuf
->TotalSize
== 0));
1000 ASSERT ((Nbuf
->Vector
->Free
== NULL
) && (Nbuf
->Vector
->Len
>= Len
));
1002 Nbuf
->BlockOp
[0].Head
+= Len
;
1003 Nbuf
->BlockOp
[0].Tail
+= Len
;
1005 ASSERT (Nbuf
->BlockOp
[0].Tail
<= Nbuf
->BlockOp
[0].BlockTail
);
1010 Allocate some space from the header or tail of the buffer.
1012 @param Nbuf Pointer to the net buffer.
1013 @param Len The length of the buffer to be allocated.
1014 @param FromHead The flag to indicate whether reserve the data from
1015 head or tail. TRUE for from head, and FALSE for
1018 @retval * Pointer to the first byte of the allocated buffer.
1028 NET_BLOCK_OP
*BlockOp
;
1032 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1033 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1039 // Allocate some space from head. If the buffer is empty,
1040 // allocate from the first block. If it isn't, allocate
1041 // from the first non-empty block, or the block before that.
1043 if (Nbuf
->TotalSize
== 0) {
1046 NetbufGetByte (Nbuf
, 0, &Index
);
1048 if ((NET_HEADSPACE(&(Nbuf
->BlockOp
[Index
])) < Len
) && (Index
> 0)) {
1053 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
1055 if (NET_HEADSPACE (BlockOp
) < Len
) {
1059 BlockOp
->Head
-= Len
;
1060 BlockOp
->Size
+= Len
;
1061 Nbuf
->TotalSize
+= Len
;
1063 return BlockOp
->Head
;
1067 // Allocate some space from the tail. If the buffer is empty,
1068 // allocate from the first block. If it isn't, allocate
1069 // from the last non-empty block, or the block after that.
1071 if (Nbuf
->TotalSize
== 0) {
1074 NetbufGetByte (Nbuf
, Nbuf
->TotalSize
- 1, &Index
);
1076 if ((NET_TAILSPACE(&(Nbuf
->BlockOp
[Index
])) < Len
) &&
1077 (Index
< Nbuf
->BlockOpNum
- 1)) {
1083 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
1085 if (NET_TAILSPACE (BlockOp
) < Len
) {
1089 SavedTail
= BlockOp
->Tail
;
1091 BlockOp
->Tail
+= Len
;
1092 BlockOp
->Size
+= Len
;
1093 Nbuf
->TotalSize
+= Len
;
1101 Trim a single NET_BLOCK.
1103 @param BlockOp Pointer to the NET_BLOCK.
1104 @param Len The length of the data to be trimmed.
1105 @param FromHead The flag to indicate whether trim data from head or
1106 tail. TRUE for from head, and FALSE for from tail.
1114 IN NET_BLOCK_OP
*BlockOp
,
1119 ASSERT (BlockOp
&& (BlockOp
->Size
>= Len
));
1121 BlockOp
->Size
-= Len
;
1124 BlockOp
->Head
+= Len
;
1126 BlockOp
->Tail
-= Len
;
1132 Trim some data from the header or tail of the buffer.
1134 @param Nbuf Pointer to the net buffer.
1135 @param Len The length of the data to be trimmed.
1136 @param FromHead The flag to indicate whether trim data from head or
1137 tail. TRUE for from head, and FALSE for from tail.
1139 @retval UINTN Length of the actually trimmed data.
1149 NET_BLOCK_OP
*BlockOp
;
1153 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1155 if (Len
> Nbuf
->TotalSize
) {
1156 Len
= Nbuf
->TotalSize
;
1160 // If FromTail is true, iterate backward. That
1161 // is, init Index to NBuf->BlockNum - 1, and
1162 // decrease it by 1 during each loop. Otherwise,
1163 // iterate forward. That is, init Index to 0, and
1164 // increase it by 1 during each loop.
1167 Nbuf
->TotalSize
-= Len
;
1169 Index
= (FromHead
? 0 : Nbuf
->BlockOpNum
- 1);
1170 BlockOp
= Nbuf
->BlockOp
;
1173 if (BlockOp
[Index
].Size
== 0) {
1174 Index
+= (FromHead
? 1 : -1);
1178 if (Len
> BlockOp
[Index
].Size
) {
1179 Len
-= BlockOp
[Index
].Size
;
1180 Trimmed
+= BlockOp
[Index
].Size
;
1181 NetblockTrim (&BlockOp
[Index
], BlockOp
[Index
].Size
, FromHead
);
1184 NetblockTrim (&BlockOp
[Index
], Len
, FromHead
);
1188 Index
+= (FromHead
? 1 : -1);
1196 Copy the data from the specific offset to the destination.
1198 @param Nbuf Pointer to the net buffer.
1199 @param Offset The sequence number of the first byte to copy.
1200 @param Len Length of the data to copy.
1201 @param Dest The destination of the data to copy to.
1203 @retval UINTN The length of the copied data.
1214 NET_BLOCK_OP
*BlockOp
;
1221 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1224 if ((Len
== 0) || (Nbuf
->TotalSize
<= Offset
)) {
1228 if (Nbuf
->TotalSize
- Offset
< Len
) {
1229 Len
= Nbuf
->TotalSize
- Offset
;
1232 BlockOp
= Nbuf
->BlockOp
;
1235 // Skip to the offset. Don't make "Offset-By-One" error here.
1236 // Cur + BLOCK.SIZE is the first sequence number of next block.
1237 // So, (Offset < Cur + BLOCK.SIZE) means that the first byte
1238 // is in the current block. if (Offset == Cur + BLOCK.SIZE), the
1239 // first byte is the next block's first byte.
1243 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1244 if (BlockOp
[Index
].Size
== 0) {
1248 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
1252 Cur
+= BlockOp
[Index
].Size
;
1256 // Cur is the sequence number of the first byte in the block
1257 // Offset - Cur is the number of bytes before first byte to
1258 // to copy in the current block.
1260 Skip
= Offset
- Cur
;
1261 Left
= BlockOp
[Index
].Size
- Skip
;
1264 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Len
);
1268 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Left
);
1276 for (; Index
< Nbuf
->BlockOpNum
; Index
++) {
1277 if (Len
> BlockOp
[Index
].Size
) {
1278 Len
-= BlockOp
[Index
].Size
;
1279 Copied
+= BlockOp
[Index
].Size
;
1281 CopyMem (Dest
, BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1282 Dest
+= BlockOp
[Index
].Size
;
1285 CopyMem (Dest
, BlockOp
[Index
].Head
, Len
);
1295 Initiate the net buffer queue.
1297 @param NbufQue Pointer to the net buffer queue to be initiated.
1304 IN NET_BUF_QUEUE
*NbufQue
1307 NbufQue
->Signature
= NET_QUE_SIGNATURE
;
1308 NbufQue
->RefCnt
= 1;
1309 InitializeListHead (&NbufQue
->List
);
1311 InitializeListHead (&NbufQue
->BufList
);
1312 NbufQue
->BufSize
= 0;
1313 NbufQue
->BufNum
= 0;
1318 Allocate an initialized net buffer queue.
1322 @retval * Pointer to the allocated net buffer queue.
1330 NET_BUF_QUEUE
*NbufQue
;
1332 NbufQue
= AllocatePool (sizeof (NET_BUF_QUEUE
));
1333 if (NbufQue
== NULL
) {
1337 NetbufQueInit (NbufQue
);
1344 Free a net buffer queue.
1346 @param NbufQue Poitner to the net buffer queue to be freed.
1353 IN NET_BUF_QUEUE
*NbufQue
1356 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1360 if (NbufQue
->RefCnt
== 0) {
1361 NetbufQueFlush (NbufQue
);
1362 gBS
->FreePool (NbufQue
);
1368 Append a buffer to the end of the queue.
1370 @param NbufQue Pointer to the net buffer queue.
1371 @param Nbuf Pointer to the net buffer to be appended.
1378 IN NET_BUF_QUEUE
*NbufQue
,
1382 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1383 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1385 InsertTailList (&NbufQue
->BufList
, &Nbuf
->List
);
1387 NbufQue
->BufSize
+= Nbuf
->TotalSize
;
1393 Remove a net buffer from head in the specific queue.
1395 @param NbufQue Pointer to the net buffer queue.
1397 @retval * Pointer to the net buffer removed from the specific
1403 IN NET_BUF_QUEUE
*NbufQue
1408 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1410 if (NbufQue
->BufNum
== 0) {
1414 First
= NET_LIST_USER_STRUCT (NbufQue
->BufList
.ForwardLink
, NET_BUF
, List
);
1416 NetListRemoveHead (&NbufQue
->BufList
);
1418 NbufQue
->BufSize
-= First
->TotalSize
;
1425 Copy some data from the buffer queue to the destination.
1427 @param NbufQue Pointer to the net buffer queue.
1428 @param Offset The sequence number of the first byte to copy.
1429 @param Len Length of the data to copy.
1430 @param Dest The destination of the data to copy to.
1432 @retval UINTN The length of the copied data.
1437 IN NET_BUF_QUEUE
*NbufQue
,
1450 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1451 ASSERT (Dest
!= NULL
);
1453 if ((Len
== 0) || (NbufQue
->BufSize
<= Offset
)) {
1457 if (NbufQue
->BufSize
- Offset
< Len
) {
1458 Len
= NbufQue
->BufSize
- Offset
;
1462 // skip to the Offset
1467 NET_LIST_FOR_EACH (Entry
, &NbufQue
->BufList
) {
1468 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1470 if (Offset
< Cur
+ Nbuf
->TotalSize
) {
1474 Cur
+= Nbuf
->TotalSize
;
1478 // Copy the data in the first buffer.
1480 Skip
= Offset
- Cur
;
1481 Left
= Nbuf
->TotalSize
- Skip
;
1484 return NetbufCopy (Nbuf
, Skip
, Len
, Dest
);
1487 NetbufCopy (Nbuf
, Skip
, Left
, Dest
);
1493 // Iterate over the others
1495 Entry
= Entry
->ForwardLink
;
1497 while ((Len
> 0) && (Entry
!= &NbufQue
->BufList
)) {
1498 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1500 if (Len
> Nbuf
->TotalSize
) {
1501 Len
-= Nbuf
->TotalSize
;
1502 Copied
+= Nbuf
->TotalSize
;
1504 NetbufCopy (Nbuf
, 0, Nbuf
->TotalSize
, Dest
);
1505 Dest
+= Nbuf
->TotalSize
;
1508 NetbufCopy (Nbuf
, 0, Len
, Dest
);
1513 Entry
= Entry
->ForwardLink
;
1521 Trim some data from the queue header, release the buffer if
1522 whole buffer is trimmed.
1524 @param NbufQue Pointer to the net buffer queue.
1525 @param Len Length of the data to trim.
1527 @retval UINTN The length of the data trimmed.
1532 IN NET_BUF_QUEUE
*NbufQue
,
1541 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1547 if (Len
> NbufQue
->BufSize
) {
1548 Len
= NbufQue
->BufSize
;
1551 NbufQue
->BufSize
-= Len
;
1554 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &NbufQue
->BufList
) {
1555 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1557 if (Len
>= Nbuf
->TotalSize
) {
1558 Trimmed
+= Nbuf
->TotalSize
;
1559 Len
-= Nbuf
->TotalSize
;
1561 RemoveEntryList (Entry
);
1571 Trimmed
+= NetbufTrim (Nbuf
, Len
, NET_BUF_HEAD
);
1581 Flush the net buffer queue.
1583 @param NbufQue Pointer to the queue to be flushed.
1590 IN NET_BUF_QUEUE
*NbufQue
1593 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1595 NetbufFreeList (&NbufQue
->BufList
);
1597 NbufQue
->BufNum
= 0;
1598 NbufQue
->BufSize
= 0;
1603 Compute checksum for a bulk of data.
1605 @param Bulk Pointer to the data.
1606 @param Len Length of the data, in bytes.
1608 @retval UINT16 The computed checksum.
1617 register UINT32 Sum
;
1622 Sum
+= *(UINT16
*) Bulk
;
1628 // Add left-over byte, if any
1631 Sum
+= *(UINT8
*) Bulk
;
1635 // Fold 32-bit sum to 16 bits
1638 Sum
= (Sum
& 0xffff) + (Sum
>> 16);
1642 return (UINT16
) Sum
;
1649 @param Checksum1 The first checksum to be added.
1650 @param Checksum2 The second checksum to be added.
1652 @retval UINT16 The new checksum.
1657 IN UINT16 Checksum1
,
1663 Sum
= Checksum1
+ Checksum2
;
1666 // two UINT16 can only add up to a carry of 1.
1669 Sum
= (Sum
& 0xffff) + 1;
1673 return (UINT16
) Sum
;
1678 Compute the checksum for a NET_BUF.
1680 @param Nbuf Pointer to the net buffer.
1682 @retval UINT16 The computed checksum.
1690 NET_BLOCK_OP
*BlockOp
;
1696 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1700 BlockOp
= Nbuf
->BlockOp
;
1702 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1703 if (BlockOp
[Index
].Size
== 0) {
1707 BlockSum
= NetblockChecksum (BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1709 if (Offset
& 0x01) {
1711 // The checksum starts with an odd byte, swap
1712 // the checksum before added to total checksum
1714 BlockSum
= (UINT16
) NET_SWAP_SHORT (BlockSum
);
1717 TotalSum
= NetAddChecksum (BlockSum
, TotalSum
);
1718 Offset
+= BlockOp
[Index
].Size
;
1726 Compute the checksum for TCP/UDP pseudo header.
1727 Src, Dst are in network byte order. and Len is
1730 @param Src The source address of the packet.
1731 @param Dst The destination address of the packet.
1732 @param Proto The protocol type of the packet.
1733 @param Len The length of the packet.
1735 @retval UINT16 The computed checksum.
1739 NetPseudoHeadChecksum (
1749 // Zero the memory to relieve align problems
1751 ZeroMem (&Hdr
, sizeof (Hdr
));
1755 Hdr
.Protocol
= Proto
;
1756 Hdr
.Len
= HTONS (Len
);
1758 return NetblockChecksum ((UINT8
*) &Hdr
, sizeof (Hdr
));