2 Network library functions providing net buffer operation support.
4 Copyright (c) 2005 - 2010, Intel Corporation.<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/NetLib.h>
17 #include <Library/BaseLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/UefiBootServicesTableLib.h>
21 #include <Library/MemoryAllocationLib.h>
25 Allocate and build up the sketch for a NET_BUF.
27 The net buffer allocated has the BlockOpNum's NET_BLOCK_OP, and its associated
28 NET_VECTOR has the BlockNum's NET_BLOCK. But all the NET_BLOCK_OP and
29 NET_BLOCK remain un-initialized.
31 @param[in] BlockNum The number of NET_BLOCK in the vector of net buffer
32 @param[in] BlockOpNum The number of NET_BLOCK_OP in the net buffer
34 @return Pointer to the allocated NET_BUF, or NULL if the
35 allocation failed due to resource limit.
47 ASSERT (BlockOpNum
>= 1);
50 // Allocate three memory blocks.
52 Nbuf
= AllocateZeroPool (NET_BUF_SIZE (BlockOpNum
));
58 Nbuf
->Signature
= NET_BUF_SIGNATURE
;
60 Nbuf
->BlockOpNum
= BlockOpNum
;
61 InitializeListHead (&Nbuf
->List
);
64 Vector
= AllocateZeroPool (NET_VECTOR_SIZE (BlockNum
));
70 Vector
->Signature
= NET_VECTOR_SIGNATURE
;
72 Vector
->BlockNum
= BlockNum
;
73 Nbuf
->Vector
= Vector
;
86 Allocate a single block NET_BUF. Upon allocation, all the
87 free space is in the tail room.
89 @param[in] Len The length of the block.
91 @return Pointer to the allocated NET_BUF, or NULL if the
92 allocation failed due to resource limit.
107 Nbuf
= NetbufAllocStruct (1, 1);
113 Bulk
= AllocatePool (Len
);
119 Vector
= Nbuf
->Vector
;
122 Vector
->Block
[0].Bulk
= Bulk
;
123 Vector
->Block
[0].Len
= Len
;
125 Nbuf
->BlockOp
[0].BlockHead
= Bulk
;
126 Nbuf
->BlockOp
[0].BlockTail
= Bulk
+ Len
;
128 Nbuf
->BlockOp
[0].Head
= Bulk
;
129 Nbuf
->BlockOp
[0].Tail
= Bulk
;
130 Nbuf
->BlockOp
[0].Size
= 0;
142 Decrease the reference count of the net vector by one. The real resource free
143 operation isn't performed until the reference count of the net vector is
146 @param[in] Vector Pointer to the NET_VECTOR to be freed.
151 IN NET_VECTOR
*Vector
156 ASSERT (Vector
!= NULL
);
157 NET_CHECK_SIGNATURE (Vector
, NET_VECTOR_SIGNATURE
);
158 ASSERT (Vector
->RefCnt
> 0);
162 if (Vector
->RefCnt
> 0) {
166 if (Vector
->Free
!= NULL
) {
168 // Call external free function to free the vector if it
169 // isn't NULL. If NET_VECTOR_OWN_FIRST is set, release the
170 // first block since it is allocated by us
172 if ((Vector
->Flag
& NET_VECTOR_OWN_FIRST
) != 0) {
173 gBS
->FreePool (Vector
->Block
[0].Bulk
);
176 Vector
->Free (Vector
->Arg
);
180 // Free each memory block associated with the Vector
182 for (Index
= 0; Index
< Vector
->BlockNum
; Index
++) {
183 gBS
->FreePool (Vector
->Block
[Index
].Bulk
);
192 Free the net buffer and its associated NET_VECTOR.
194 Decrease the reference count of the net buffer by one. Free the associated net
195 vector and itself if the reference count of the net buffer is decreased to 0.
196 The net vector free operation just decrease the reference count of the net
197 vector by one and do the real resource free operation when the reference count
198 of the net vector is 0.
200 @param[in] Nbuf Pointer to the NET_BUF to be freed.
209 ASSERT (Nbuf
!= NULL
);
210 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
211 ASSERT (Nbuf
->RefCnt
> 0);
215 if (Nbuf
->RefCnt
== 0) {
217 // Update Vector only when NBuf is to be released. That is,
218 // all the sharing of Nbuf increse Vector's RefCnt by one
220 NetbufFreeVector (Nbuf
->Vector
);
227 Create a copy of the net buffer that shares the associated net vector.
229 The reference count of the newly created net buffer is set to 1. The reference
230 count of the associated net vector is increased by one.
232 @param[in] Nbuf Pointer to the net buffer to be cloned.
234 @return Pointer to the cloned net buffer, or NULL if the
235 allocation failed due to resource limit.
246 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
248 Clone
= AllocatePool (NET_BUF_SIZE (Nbuf
->BlockOpNum
));
254 Clone
->Signature
= NET_BUF_SIGNATURE
;
256 InitializeListHead (&Clone
->List
);
258 Clone
->Ip
= Nbuf
->Ip
;
259 Clone
->Tcp
= Nbuf
->Tcp
;
261 CopyMem (Clone
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
263 NET_GET_REF (Nbuf
->Vector
);
265 Clone
->Vector
= Nbuf
->Vector
;
266 Clone
->BlockOpNum
= Nbuf
->BlockOpNum
;
267 Clone
->TotalSize
= Nbuf
->TotalSize
;
268 CopyMem (Clone
->BlockOp
, Nbuf
->BlockOp
, sizeof (NET_BLOCK_OP
) * Nbuf
->BlockOpNum
);
275 Create a duplicated copy of the net buffer with data copied and HeadSpace
276 bytes of head space reserved.
278 The duplicated net buffer will allocate its own memory to hold the data of the
281 @param[in] Nbuf Pointer to the net buffer to be duplicated from.
282 @param[in, out] Duplicate Pointer to the net buffer to duplicate to, if
283 NULL a new net buffer is allocated.
284 @param[in] HeadSpace Length of the head space to reserve.
286 @return Pointer to the duplicated net buffer, or NULL if
287 the allocation failed due to resource limit.
294 IN OUT NET_BUF
*Duplicate OPTIONAL
,
300 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
302 if (Duplicate
== NULL
) {
303 Duplicate
= NetbufAlloc (Nbuf
->TotalSize
+ HeadSpace
);
306 if (Duplicate
== NULL
) {
311 // Don't set the IP and TCP head point, since it is most
312 // like that they are pointing to the memory of Nbuf.
314 CopyMem (Duplicate
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
315 NetbufReserve (Duplicate
, HeadSpace
);
317 Dst
= NetbufAllocSpace (Duplicate
, Nbuf
->TotalSize
, NET_BUF_TAIL
);
318 NetbufCopy (Nbuf
, 0, Nbuf
->TotalSize
, Dst
);
325 Free a list of net buffers.
327 @param[in, out] Head Pointer to the head of linked net buffers.
333 IN OUT LIST_ENTRY
*Head
340 Entry
= Head
->ForwardLink
;
342 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Head
) {
343 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
344 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
346 RemoveEntryList (Entry
);
350 ASSERT (IsListEmpty (Head
));
355 Get the index of NET_BLOCK_OP that contains the byte at Offset in the net
358 This can be used to, for example, retrieve the IP header in the packet. It
359 also can be used to get the fragment that contains the byte which is used
360 mainly by the library implementation itself.
362 @param[in] Nbuf Pointer to the net buffer.
363 @param[in] Offset The offset of the byte.
364 @param[out] Index Index of the NET_BLOCK_OP that contains the byte at
367 @return Pointer to the Offset'th byte of data in the net buffer, or NULL
368 if there is no such data in the net buffer.
376 OUT UINT32
*Index OPTIONAL
379 NET_BLOCK_OP
*BlockOp
;
383 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
385 if (Offset
>= Nbuf
->TotalSize
) {
389 BlockOp
= Nbuf
->BlockOp
;
392 for (Loop
= 0; Loop
< Nbuf
->BlockOpNum
; Loop
++) {
394 if (Len
+ BlockOp
[Loop
].Size
<= Offset
) {
395 Len
+= BlockOp
[Loop
].Size
;
403 return BlockOp
[Loop
].Head
+ (Offset
- Len
);
412 Set the NET_BLOCK and corresponding NET_BLOCK_OP in the net buffer and
413 corresponding net vector according to the bulk pointer and bulk length.
415 All the pointers in the Index'th NET_BLOCK and NET_BLOCK_OP are set to the
416 bulk's head and tail respectively. So, this function alone can't be used by
419 @param[in, out] Nbuf Pointer to the net buffer.
420 @param[in] Bulk Pointer to the data.
421 @param[in] Len Length of the bulk data.
422 @param[in] Index The data block index in the net buffer the bulk
423 data should belong to.
428 IN OUT NET_BUF
*Nbuf
,
434 NET_BLOCK_OP
*BlockOp
;
437 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
438 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
439 ASSERT (Index
< Nbuf
->BlockOpNum
);
441 Block
= &(Nbuf
->Vector
->Block
[Index
]);
442 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
445 BlockOp
->BlockHead
= Bulk
;
446 BlockOp
->BlockTail
= Bulk
+ Len
;
447 BlockOp
->Head
= Bulk
;
448 BlockOp
->Tail
= Bulk
+ Len
;
455 Set the NET_BLOCK_OP in the net buffer. The corresponding NET_BLOCK
456 structure is left untouched.
458 Some times, there is no 1:1 relationship between NET_BLOCK and NET_BLOCK_OP.
459 For example, that in NetbufGetFragment.
461 @param[in, out] Nbuf Pointer to the net buffer.
462 @param[in] Bulk Pointer to the data.
463 @param[in] Len Length of the bulk data.
464 @param[in] Index The data block index in the net buffer the bulk
465 data should belong to.
470 IN OUT NET_BUF
*Nbuf
,
476 NET_BLOCK_OP
*BlockOp
;
478 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
479 ASSERT (Index
< Nbuf
->BlockOpNum
);
481 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
482 BlockOp
->BlockHead
= Bulk
;
483 BlockOp
->BlockTail
= Bulk
+ Len
;
484 BlockOp
->Head
= Bulk
;
485 BlockOp
->Tail
= Bulk
+ Len
;
491 Helper function for NetbufGetFragment. NetbufGetFragment may allocate the
492 first block to reserve HeadSpace bytes header space. So it needs to create a
493 new net vector for the first block and can avoid copy for the remaining data
494 by sharing the old net vector.
496 @param[in] Arg Point to the old NET_VECTOR.
500 NetbufGetFragmentFree (
506 Vector
= (NET_VECTOR
*)Arg
;
507 NetbufFreeVector (Vector
);
512 Create a NET_BUF structure which contains Len byte data of Nbuf starting from
515 A new NET_BUF structure will be created but the associated data in NET_VECTOR
516 is shared. This function exists to do IP packet fragmentation.
518 @param[in] Nbuf Pointer to the net buffer to be extracted.
519 @param[in] Offset Starting point of the data to be included in the new
521 @param[in] Len Bytes of data to be included in the new net buffer.
522 @param[in] HeadSpace Bytes of head space to reserve for protocol header.
524 @return Pointer to the cloned net buffer, or NULL if the
525 allocation failed due to resource limit.
539 NET_BLOCK_OP
*BlockOp
;
551 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
553 if ((Len
== 0) || (Offset
+ Len
> Nbuf
->TotalSize
)) {
558 // First find the first and last BlockOp that contains
559 // the valid data, and compute the offset of the first
560 // BlockOp and length of the last BlockOp
562 BlockOp
= Nbuf
->BlockOp
;
565 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
566 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
570 Cur
+= BlockOp
[Index
].Size
;
574 // First is the index of the first BlockOp, FirstSkip is
575 // the offset of the first byte in the first BlockOp.
578 FirstSkip
= Offset
- Cur
;
579 FirstLen
= BlockOp
[Index
].Size
- FirstSkip
;
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 ASSERT (Last
>= First
);
605 BlockOpNum
= Last
- First
+ 1;
608 if (HeadSpace
!= 0) {
610 // Allocate an extra block to accomdate the head space.
614 Child
= NetbufAllocStruct (1, BlockOpNum
);
620 FirstBulk
= AllocatePool (HeadSpace
);
622 if (FirstBulk
== NULL
) {
626 Vector
= Child
->Vector
;
627 Vector
->Free
= NetbufGetFragmentFree
;
628 Vector
->Arg
= Nbuf
->Vector
;
629 Vector
->Flag
= NET_VECTOR_OWN_FIRST
;
630 Vector
->Len
= HeadSpace
;
633 // Reserve the head space in the first block
635 NetbufSetBlock (Child
, FirstBulk
, HeadSpace
, 0);
636 Child
->BlockOp
[0].Head
+= HeadSpace
;
637 Child
->BlockOp
[0].Size
= 0;
641 Child
= NetbufAllocStruct (0, BlockOpNum
);
647 Child
->Vector
= Nbuf
->Vector
;
650 NET_GET_REF (Nbuf
->Vector
);
651 Child
->TotalSize
= Len
;
654 // Set all the BlockOp up, the first and last one are special
655 // and need special process.
659 Nbuf
->BlockOp
[First
].Head
+ FirstSkip
,
664 for (Index
= First
+ 1; Index
< Last
; Index
++) {
682 CopyMem (Child
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
694 Build a NET_BUF from external blocks.
696 A new NET_BUF structure will be created from external blocks. Additional block
697 of memory will be allocated to hold reserved HeadSpace bytes of header room
698 and existing HeadLen bytes of header but the external blocks are shared by the
699 net buffer to avoid data copying.
701 @param[in] ExtFragment Pointer to the data block.
702 @param[in] ExtNum The number of the data blocks.
703 @param[in] HeadSpace The head space to be reserved.
704 @param[in] HeadLen The length of the protocol header, This function
705 will pull that number of data into a linear block.
706 @param[in] ExtFree Pointer to the caller provided free function.
707 @param[in] Arg The argument passed to ExtFree when ExtFree is
710 @return Pointer to the net buffer built from the data blocks,
711 or NULL if the allocation failed due to resource
718 IN NET_FRAGMENT
*ExtFragment
,
722 IN NET_VECTOR_EXT_FREE ExtFree
,
723 IN VOID
*Arg OPTIONAL
728 NET_FRAGMENT SavedFragment
;
733 UINT32 FirstBlockLen
;
740 ASSERT ((ExtFragment
!= NULL
) && (ExtNum
> 0) && (ExtFree
!= NULL
));
742 SavedFragment
.Bulk
= NULL
;
743 SavedFragment
.Len
= 0;
755 // No need to consolidate the header if the first block is
756 // longer than the header length or there is only one block.
758 if ((ExtFragment
[0].Len
>= HeadLen
) || (ExtNum
== 1)) {
763 // Allocate an extra block if we need to:
764 // 1. Allocate some header space
765 // 2. aggreate the packet header
767 if ((HeadSpace
!= 0) || (HeadLen
!= 0)) {
768 FirstBlockLen
= HeadLen
+ HeadSpace
;
769 FirstBlock
= AllocatePool (FirstBlockLen
);
771 if (FirstBlock
== NULL
) {
779 // Copy the header to the first block, reduce the NET_BLOCK
780 // to allocate by one for each block that is completely covered
781 // by the first bulk.
785 Header
= FirstBlock
+ HeadSpace
;
787 for (Index
= 0; Index
< ExtNum
; Index
++) {
788 if (Len
>= ExtFragment
[Index
].Len
) {
789 CopyMem (Header
, ExtFragment
[Index
].Bulk
, ExtFragment
[Index
].Len
);
791 Copied
+= ExtFragment
[Index
].Len
;
792 Len
-= ExtFragment
[Index
].Len
;
793 Header
+= ExtFragment
[Index
].Len
;
794 TotalLen
+= ExtFragment
[Index
].Len
;
799 // Increament the index number to point to the next
800 // non-empty fragment.
807 CopyMem (Header
, ExtFragment
[Index
].Bulk
, Len
);
813 // Adjust the block structure to exclude the data copied,
814 // So, the left-over block can be processed as other blocks.
815 // But it must be recovered later. (SavedIndex > 0) always
816 // holds since we don't aggreate the header if the first block
817 // is bigger enough that the header is continuous
820 SavedFragment
= ExtFragment
[Index
];
821 ExtFragment
[Index
].Bulk
+= Len
;
822 ExtFragment
[Index
].Len
-= Len
;
828 Nbuf
= NetbufAllocStruct (BlockNum
, BlockNum
);
834 Vector
= Nbuf
->Vector
;
835 Vector
->Free
= ExtFree
;
837 Vector
->Flag
= ((FirstBlockLen
!= 0) ? NET_VECTOR_OWN_FIRST
: 0);
840 // Set the first block up which may contain
841 // some head space and aggregated header
845 if (FirstBlockLen
!= 0) {
846 NetbufSetBlock (Nbuf
, FirstBlock
, HeadSpace
+ Copied
, 0);
847 Nbuf
->BlockOp
[0].Head
+= HeadSpace
;
848 Nbuf
->BlockOp
[0].Size
= Copied
;
853 for (; Index
< ExtNum
; Index
++) {
854 NetbufSetBlock (Nbuf
, ExtFragment
[Index
].Bulk
, ExtFragment
[Index
].Len
, CurBlock
);
855 TotalLen
+= ExtFragment
[Index
].Len
;
859 Vector
->Len
= TotalLen
+ HeadSpace
;
860 Nbuf
->TotalSize
= TotalLen
;
862 if (SavedIndex
!= 0) {
863 ExtFragment
[SavedIndex
] = SavedFragment
;
869 if (FirstBlock
!= NULL
) {
870 FreePool (FirstBlock
);
877 Build a fragment table to contain the fragments in the net buffer. This is the
878 opposite operation of the NetbufFromExt.
880 @param[in] Nbuf Point to the net buffer.
881 @param[in, out] ExtFragment Pointer to the data block.
882 @param[in, out] ExtNum The number of the data blocks.
884 @retval EFI_BUFFER_TOO_SMALL The number of non-empty block is bigger than
886 @retval EFI_SUCCESS Fragment table is built successfully.
893 IN OUT NET_FRAGMENT
*ExtFragment
,
894 IN OUT UINT32
*ExtNum
902 for (Index
= 0; (Index
< Nbuf
->BlockOpNum
); Index
++) {
903 if (Nbuf
->BlockOp
[Index
].Size
== 0) {
907 if (Current
< *ExtNum
) {
908 ExtFragment
[Current
].Bulk
= Nbuf
->BlockOp
[Index
].Head
;
909 ExtFragment
[Current
].Len
= Nbuf
->BlockOp
[Index
].Size
;
912 return EFI_BUFFER_TOO_SMALL
;
922 Build a net buffer from a list of net buffers.
924 All the fragments will be collected from the list of NEW_BUF and then a new
925 net buffer will be created through NetbufFromExt.
927 @param[in] BufList A List of the net buffer.
928 @param[in] HeadSpace The head space to be reserved.
929 @param[in] HeaderLen The length of the protocol header, This function
930 will pull that number of data into a linear block.
931 @param[in] ExtFree Pointer to the caller provided free function.
932 @param[in] Arg The argument passed to ExtFree when ExtFree is called.
934 @return Pointer to the net buffer built from the list of net
941 IN LIST_ENTRY
*BufList
,
944 IN NET_VECTOR_EXT_FREE ExtFree
,
945 IN VOID
*Arg OPTIONAL
948 NET_FRAGMENT
*Fragment
;
956 //Compute how many blocks are there
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
);
963 FragmentNum
+= Nbuf
->BlockOpNum
;
967 //Allocate and copy block points
969 Fragment
= AllocatePool (sizeof (NET_FRAGMENT
) * FragmentNum
);
971 if (Fragment
== NULL
) {
977 NET_LIST_FOR_EACH (Entry
, BufList
) {
978 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
979 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
981 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
982 if (Nbuf
->BlockOp
[Index
].Size
!= 0) {
983 Fragment
[Current
].Bulk
= Nbuf
->BlockOp
[Index
].Head
;
984 Fragment
[Current
].Len
= Nbuf
->BlockOp
[Index
].Size
;
990 Nbuf
= NetbufFromExt (Fragment
, Current
, HeadSpace
, HeaderLen
, ExtFree
, Arg
);
998 Reserve some space in the header room of the net buffer.
1000 Upon allocation, all the space are in the tail room of the buffer. Call this
1001 function to move some space to the header room. This function is quite limited
1002 in that it can only reserve space from the first block of an empty NET_BUF not
1003 built from the external. But it should be enough for the network stack.
1005 @param[in, out] Nbuf Pointer to the net buffer.
1006 @param[in] Len The length of buffer to be reserved from the header.
1012 IN OUT NET_BUF
*Nbuf
,
1016 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1017 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1019 ASSERT ((Nbuf
->BlockOpNum
== 1) && (Nbuf
->TotalSize
== 0));
1020 ASSERT ((Nbuf
->Vector
->Free
== NULL
) && (Nbuf
->Vector
->Len
>= Len
));
1022 Nbuf
->BlockOp
[0].Head
+= Len
;
1023 Nbuf
->BlockOp
[0].Tail
+= Len
;
1025 ASSERT (Nbuf
->BlockOp
[0].Tail
<= Nbuf
->BlockOp
[0].BlockTail
);
1030 Allocate Len bytes of space from the header or tail of the buffer.
1032 @param[in, out] Nbuf Pointer to the net buffer.
1033 @param[in] Len The length of the buffer to be allocated.
1034 @param[in] FromHead The flag to indicate whether reserve the data
1035 from head (TRUE) or tail (FALSE).
1037 @return Pointer to the first byte of the allocated buffer,
1038 or NULL if there is no sufficient space.
1044 IN OUT NET_BUF
*Nbuf
,
1049 NET_BLOCK_OP
*BlockOp
;
1053 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1054 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1060 // Allocate some space from head. If the buffer is empty,
1061 // allocate from the first block. If it isn't, allocate
1062 // from the first non-empty block, or the block before that.
1064 if (Nbuf
->TotalSize
== 0) {
1067 NetbufGetByte (Nbuf
, 0, &Index
);
1069 if ((NET_HEADSPACE(&(Nbuf
->BlockOp
[Index
])) < Len
) && (Index
> 0)) {
1074 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
1076 if (NET_HEADSPACE (BlockOp
) < Len
) {
1080 BlockOp
->Head
-= Len
;
1081 BlockOp
->Size
+= Len
;
1082 Nbuf
->TotalSize
+= Len
;
1084 return BlockOp
->Head
;
1088 // Allocate some space from the tail. If the buffer is empty,
1089 // allocate from the first block. If it isn't, allocate
1090 // from the last non-empty block, or the block after that.
1092 if (Nbuf
->TotalSize
== 0) {
1095 NetbufGetByte (Nbuf
, Nbuf
->TotalSize
- 1, &Index
);
1097 if ((NET_TAILSPACE(&(Nbuf
->BlockOp
[Index
])) < Len
) &&
1098 (Index
< Nbuf
->BlockOpNum
- 1)) {
1104 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
1106 if (NET_TAILSPACE (BlockOp
) < Len
) {
1110 SavedTail
= BlockOp
->Tail
;
1112 BlockOp
->Tail
+= Len
;
1113 BlockOp
->Size
+= Len
;
1114 Nbuf
->TotalSize
+= Len
;
1122 Trim a single NET_BLOCK by Len bytes from the header or tail.
1124 @param[in, out] BlockOp Pointer to the NET_BLOCK.
1125 @param[in] Len The length of the data to be trimmed.
1126 @param[in] FromHead The flag to indicate whether trim data from head
1127 (TRUE) or tail (FALSE).
1132 IN OUT NET_BLOCK_OP
*BlockOp
,
1137 ASSERT ((BlockOp
!= NULL
) && (BlockOp
->Size
>= Len
));
1139 BlockOp
->Size
-= Len
;
1142 BlockOp
->Head
+= Len
;
1144 BlockOp
->Tail
-= Len
;
1150 Trim Len bytes from the header or tail of the net buffer.
1152 @param[in, out] Nbuf Pointer to the net buffer.
1153 @param[in] Len The length of the data to be trimmed.
1154 @param[in] FromHead The flag to indicate whether trim data from head
1155 (TRUE) or tail (FALSE).
1157 @return Length of the actually trimmed data, which is possible to be less
1158 than Len because the TotalSize of Nbuf is less than Len.
1164 IN OUT NET_BUF
*Nbuf
,
1169 NET_BLOCK_OP
*BlockOp
;
1173 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1175 if (Len
> Nbuf
->TotalSize
) {
1176 Len
= Nbuf
->TotalSize
;
1180 // If FromTail is true, iterate backward. That
1181 // is, init Index to NBuf->BlockNum - 1, and
1182 // decrease it by 1 during each loop. Otherwise,
1183 // iterate forward. That is, init Index to 0, and
1184 // increase it by 1 during each loop.
1187 Nbuf
->TotalSize
-= Len
;
1189 Index
= (FromHead
? 0 : Nbuf
->BlockOpNum
- 1);
1190 BlockOp
= Nbuf
->BlockOp
;
1193 if (BlockOp
[Index
].Size
== 0) {
1194 Index
+= (FromHead
? 1 : -1);
1198 if (Len
> BlockOp
[Index
].Size
) {
1199 Len
-= BlockOp
[Index
].Size
;
1200 Trimmed
+= BlockOp
[Index
].Size
;
1201 NetblockTrim (&BlockOp
[Index
], BlockOp
[Index
].Size
, FromHead
);
1204 NetblockTrim (&BlockOp
[Index
], Len
, FromHead
);
1208 Index
+= (FromHead
? 1 : -1);
1216 Copy Len bytes of data from the specific offset of the net buffer to the
1219 The Len bytes of data may cross the several fragments of the net buffer.
1221 @param[in] Nbuf Pointer to the net buffer.
1222 @param[in] Offset The sequence number of the first byte to copy.
1223 @param[in] Len Length of the data to copy.
1224 @param[in] Dest The destination of the data to copy to.
1226 @return The length of the actual copied data, or 0 if the offset
1227 specified exceeds the total size of net buffer.
1239 NET_BLOCK_OP
*BlockOp
;
1246 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1249 if ((Len
== 0) || (Nbuf
->TotalSize
<= Offset
)) {
1253 if (Nbuf
->TotalSize
- Offset
< Len
) {
1254 Len
= Nbuf
->TotalSize
- Offset
;
1257 BlockOp
= Nbuf
->BlockOp
;
1260 // Skip to the offset. Don't make "Offset-By-One" error here.
1261 // Cur + BLOCK.SIZE is the first sequence number of next block.
1262 // So, (Offset < Cur + BLOCK.SIZE) means that the first byte
1263 // is in the current block. if (Offset == Cur + BLOCK.SIZE), the
1264 // first byte is the next block's first byte.
1268 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1269 if (BlockOp
[Index
].Size
== 0) {
1273 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
1277 Cur
+= BlockOp
[Index
].Size
;
1281 // Cur is the sequence number of the first byte in the block
1282 // Offset - Cur is the number of bytes before first byte to
1283 // to copy in the current block.
1285 Skip
= Offset
- Cur
;
1286 Left
= BlockOp
[Index
].Size
- Skip
;
1289 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Len
);
1293 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Left
);
1301 for (; Index
< Nbuf
->BlockOpNum
; Index
++) {
1302 if (Len
> BlockOp
[Index
].Size
) {
1303 Len
-= BlockOp
[Index
].Size
;
1304 Copied
+= BlockOp
[Index
].Size
;
1306 CopyMem (Dest
, BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1307 Dest
+= BlockOp
[Index
].Size
;
1310 CopyMem (Dest
, BlockOp
[Index
].Head
, Len
);
1320 Initiate the net buffer queue.
1322 @param[in, out] NbufQue Pointer to the net buffer queue to be initialized.
1328 IN OUT NET_BUF_QUEUE
*NbufQue
1331 NbufQue
->Signature
= NET_QUE_SIGNATURE
;
1332 NbufQue
->RefCnt
= 1;
1333 InitializeListHead (&NbufQue
->List
);
1335 InitializeListHead (&NbufQue
->BufList
);
1336 NbufQue
->BufSize
= 0;
1337 NbufQue
->BufNum
= 0;
1342 Allocate and initialize a net buffer queue.
1344 @return Pointer to the allocated net buffer queue, or NULL if the
1345 allocation failed due to resource limit.
1354 NET_BUF_QUEUE
*NbufQue
;
1356 NbufQue
= AllocatePool (sizeof (NET_BUF_QUEUE
));
1357 if (NbufQue
== NULL
) {
1361 NetbufQueInit (NbufQue
);
1368 Free a net buffer queue.
1370 Decrease the reference count of the net buffer queue by one. The real resource
1371 free operation isn't performed until the reference count of the net buffer
1372 queue is decreased to 0.
1374 @param[in] NbufQue Pointer to the net buffer queue to be freed.
1380 IN NET_BUF_QUEUE
*NbufQue
1383 ASSERT (NbufQue
!= NULL
);
1384 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1388 if (NbufQue
->RefCnt
== 0) {
1389 NetbufQueFlush (NbufQue
);
1396 Append a net buffer to the net buffer queue.
1398 @param[in, out] NbufQue Pointer to the net buffer queue.
1399 @param[in, out] Nbuf Pointer to the net buffer to be appended.
1405 IN OUT NET_BUF_QUEUE
*NbufQue
,
1406 IN OUT NET_BUF
*Nbuf
1409 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1410 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1412 InsertTailList (&NbufQue
->BufList
, &Nbuf
->List
);
1414 NbufQue
->BufSize
+= Nbuf
->TotalSize
;
1420 Remove a net buffer from the head in the specific queue and return it.
1422 @param[in, out] NbufQue Pointer to the net buffer queue.
1424 @return Pointer to the net buffer removed from the specific queue,
1425 or NULL if there is no net buffer in the specific queue.
1431 IN OUT NET_BUF_QUEUE
*NbufQue
1436 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1438 if (NbufQue
->BufNum
== 0) {
1442 First
= NET_LIST_USER_STRUCT (NbufQue
->BufList
.ForwardLink
, NET_BUF
, List
);
1444 NetListRemoveHead (&NbufQue
->BufList
);
1446 NbufQue
->BufSize
-= First
->TotalSize
;
1453 Copy Len bytes of data from the net buffer queue at the specific offset to the
1456 The copying operation is the same as NetbufCopy but applies to the net buffer
1457 queue instead of the net buffer.
1459 @param[in] NbufQue Pointer to the net buffer queue.
1460 @param[in] Offset The sequence number of the first byte to copy.
1461 @param[in] Len Length of the data to copy.
1462 @param[out] Dest The destination of the data to copy to.
1464 @return The length of the actual copied data, or 0 if the offset
1465 specified exceeds the total size of net buffer queue.
1471 IN NET_BUF_QUEUE
*NbufQue
,
1484 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1485 ASSERT (Dest
!= NULL
);
1487 if ((Len
== 0) || (NbufQue
->BufSize
<= Offset
)) {
1491 if (NbufQue
->BufSize
- Offset
< Len
) {
1492 Len
= NbufQue
->BufSize
- Offset
;
1496 // skip to the Offset
1501 NET_LIST_FOR_EACH (Entry
, &NbufQue
->BufList
) {
1502 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1504 if (Offset
< Cur
+ Nbuf
->TotalSize
) {
1508 Cur
+= Nbuf
->TotalSize
;
1511 ASSERT (Nbuf
!= NULL
);
1514 // Copy the data in the first buffer.
1516 Skip
= Offset
- Cur
;
1517 Left
= Nbuf
->TotalSize
- Skip
;
1520 return NetbufCopy (Nbuf
, Skip
, Len
, Dest
);
1523 NetbufCopy (Nbuf
, Skip
, Left
, Dest
);
1529 // Iterate over the others
1531 Entry
= Entry
->ForwardLink
;
1533 while ((Len
> 0) && (Entry
!= &NbufQue
->BufList
)) {
1534 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1536 if (Len
> Nbuf
->TotalSize
) {
1537 Len
-= Nbuf
->TotalSize
;
1538 Copied
+= Nbuf
->TotalSize
;
1540 NetbufCopy (Nbuf
, 0, Nbuf
->TotalSize
, Dest
);
1541 Dest
+= Nbuf
->TotalSize
;
1544 NetbufCopy (Nbuf
, 0, Len
, Dest
);
1549 Entry
= Entry
->ForwardLink
;
1557 Trim Len bytes of data from the queue header, release any of the net buffer
1558 whom is trimmed wholely.
1560 The trimming operation is the same as NetbufTrim but applies to the net buffer
1561 queue instead of the net buffer.
1563 @param[in, out] NbufQue Pointer to the net buffer queue.
1564 @param[in] Len Length of the data to trim.
1566 @return The actual length of the data trimmed.
1572 IN OUT NET_BUF_QUEUE
*NbufQue
,
1581 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1587 if (Len
> NbufQue
->BufSize
) {
1588 Len
= NbufQue
->BufSize
;
1591 NbufQue
->BufSize
-= Len
;
1594 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &NbufQue
->BufList
) {
1595 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1597 if (Len
>= Nbuf
->TotalSize
) {
1598 Trimmed
+= Nbuf
->TotalSize
;
1599 Len
-= Nbuf
->TotalSize
;
1601 RemoveEntryList (Entry
);
1611 Trimmed
+= NetbufTrim (Nbuf
, Len
, NET_BUF_HEAD
);
1621 Flush the net buffer queue.
1623 @param[in, out] NbufQue Pointer to the queue to be flushed.
1629 IN OUT NET_BUF_QUEUE
*NbufQue
1632 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1634 NetbufFreeList (&NbufQue
->BufList
);
1636 NbufQue
->BufNum
= 0;
1637 NbufQue
->BufSize
= 0;
1642 Compute the checksum for a bulk of data.
1644 @param[in] Bulk Pointer to the data.
1645 @param[in] Len Length of the data, in bytes.
1647 @return The computed checksum.
1657 register UINT32 Sum
;
1662 Sum
+= *(UINT16
*) Bulk
;
1668 // Add left-over byte, if any
1671 Sum
+= *(UINT8
*) Bulk
;
1675 // Fold 32-bit sum to 16 bits
1677 while ((Sum
>> 16) != 0) {
1678 Sum
= (Sum
& 0xffff) + (Sum
>> 16);
1682 return (UINT16
) Sum
;
1689 @param[in] Checksum1 The first checksum to be added.
1690 @param[in] Checksum2 The second checksum to be added.
1692 @return The new checksum.
1698 IN UINT16 Checksum1
,
1704 Sum
= Checksum1
+ Checksum2
;
1707 // two UINT16 can only add up to a carry of 1.
1709 if ((Sum
>> 16) != 0) {
1710 Sum
= (Sum
& 0xffff) + 1;
1714 return (UINT16
) Sum
;
1719 Compute the checksum for a NET_BUF.
1721 @param[in] Nbuf Pointer to the net buffer.
1723 @return The computed checksum.
1732 NET_BLOCK_OP
*BlockOp
;
1738 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1742 BlockOp
= Nbuf
->BlockOp
;
1744 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1745 if (BlockOp
[Index
].Size
== 0) {
1749 BlockSum
= NetblockChecksum (BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1751 if ((Offset
& 0x01) != 0) {
1753 // The checksum starts with an odd byte, swap
1754 // the checksum before added to total checksum
1756 BlockSum
= SwapBytes16 (BlockSum
);
1759 TotalSum
= NetAddChecksum (BlockSum
, TotalSum
);
1760 Offset
+= BlockOp
[Index
].Size
;
1768 Compute the checksum for TCP/UDP pseudo header.
1770 Src and Dst are in network byte order, and Len is in host byte order.
1772 @param[in] Src The source address of the packet.
1773 @param[in] Dst The destination address of the packet.
1774 @param[in] Proto The protocol type of the packet.
1775 @param[in] Len The length of the packet.
1777 @return The computed checksum.
1782 NetPseudoHeadChecksum (
1792 // Zero the memory to relieve align problems
1794 ZeroMem (&Hdr
, sizeof (Hdr
));
1798 Hdr
.Protocol
= Proto
;
1799 Hdr
.Len
= HTONS (Len
);
1801 return NetblockChecksum ((UINT8
*) &Hdr
, sizeof (Hdr
));
1805 Compute the checksum for TCP6/UDP6 pseudo header.
1807 Src and Dst are in network byte order, and Len is in host byte order.
1809 @param[in] Src The source address of the packet.
1810 @param[in] Dst The destination address of the packet.
1811 @param[in] NextHeader The protocol type of the packet.
1812 @param[in] Len The length of the packet.
1814 @return The computed checksum.
1818 NetIp6PseudoHeadChecksum (
1819 IN EFI_IPv6_ADDRESS
*Src
,
1820 IN EFI_IPv6_ADDRESS
*Dst
,
1821 IN UINT8 NextHeader
,
1825 NET_IP6_PSEUDO_HDR Hdr
;
1828 // Zero the memory to relieve align problems
1830 ZeroMem (&Hdr
, sizeof (Hdr
));
1832 IP6_COPY_ADDRESS (&Hdr
.SrcIp
, Src
);
1833 IP6_COPY_ADDRESS (&Hdr
.DstIp
, Dst
);
1835 Hdr
.NextHeader
= NextHeader
;
1836 Hdr
.Len
= HTONL (Len
);
1838 return NetblockChecksum ((UINT8
*) &Hdr
, sizeof (Hdr
));