2 Network library functions providing net buffer operation support.
4 Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
5 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.
501 NetbufGetFragmentFree (
507 Vector
= (NET_VECTOR
*)Arg
;
508 NetbufFreeVector (Vector
);
513 Create a NET_BUF structure which contains Len byte data of Nbuf starting from
516 A new NET_BUF structure will be created but the associated data in NET_VECTOR
517 is shared. This function exists to do IP packet fragmentation.
519 @param[in] Nbuf Pointer to the net buffer to be extracted.
520 @param[in] Offset Starting point of the data to be included in the new
522 @param[in] Len Bytes of data to be included in the new net buffer.
523 @param[in] HeadSpace Bytes of head space to reserve for protocol header.
525 @return Pointer to the cloned net buffer, or NULL if the
526 allocation failed due to resource limit.
540 NET_BLOCK_OP
*BlockOp
;
552 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
554 if ((Len
== 0) || (Offset
+ Len
> Nbuf
->TotalSize
)) {
559 // First find the first and last BlockOp that contains
560 // the valid data, and compute the offset of the first
561 // BlockOp and length of the last BlockOp
563 BlockOp
= Nbuf
->BlockOp
;
566 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
567 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
571 Cur
+= BlockOp
[Index
].Size
;
575 // First is the index of the first BlockOp, FirstSkip is
576 // the offset of the first byte in the first BlockOp.
579 FirstSkip
= Offset
- Cur
;
580 FirstLen
= BlockOp
[Index
].Size
- FirstSkip
;
585 if (Len
> FirstLen
) {
586 Cur
+= BlockOp
[Index
].Size
;
589 for (; Index
< Nbuf
->BlockOpNum
; Index
++) {
590 if (Offset
+ Len
<= Cur
+ BlockOp
[Index
].Size
) {
592 LastLen
= Offset
+ Len
- Cur
;
596 Cur
+= BlockOp
[Index
].Size
;
605 ASSERT (Last
>= First
);
606 BlockOpNum
= Last
- First
+ 1;
609 if (HeadSpace
!= 0) {
611 // Allocate an extra block to accomdate the head space.
615 Child
= NetbufAllocStruct (1, BlockOpNum
);
621 FirstBulk
= AllocatePool (HeadSpace
);
623 if (FirstBulk
== NULL
) {
627 Vector
= Child
->Vector
;
628 Vector
->Free
= NetbufGetFragmentFree
;
629 Vector
->Arg
= Nbuf
->Vector
;
630 Vector
->Flag
= NET_VECTOR_OWN_FIRST
;
631 Vector
->Len
= HeadSpace
;
634 // Reserve the head space in the first block
636 NetbufSetBlock (Child
, FirstBulk
, HeadSpace
, 0);
637 Child
->BlockOp
[0].Head
+= HeadSpace
;
638 Child
->BlockOp
[0].Size
= 0;
642 Child
= NetbufAllocStruct (0, BlockOpNum
);
648 Child
->Vector
= Nbuf
->Vector
;
651 NET_GET_REF (Nbuf
->Vector
);
652 Child
->TotalSize
= Len
;
655 // Set all the BlockOp up, the first and last one are special
656 // and need special process.
660 Nbuf
->BlockOp
[First
].Head
+ FirstSkip
,
665 for (Index
= First
+ 1; Index
< Last
; Index
++) {
683 CopyMem (Child
->ProtoData
, Nbuf
->ProtoData
, NET_PROTO_DATA
);
695 Build a NET_BUF from external blocks.
697 A new NET_BUF structure will be created from external blocks. Additional block
698 of memory will be allocated to hold reserved HeadSpace bytes of header room
699 and existing HeadLen bytes of header but the external blocks are shared by the
700 net buffer to avoid data copying.
702 @param[in] ExtFragment Pointer to the data block.
703 @param[in] ExtNum The number of the data blocks.
704 @param[in] HeadSpace The head space to be reserved.
705 @param[in] HeadLen The length of the protocol header, This function
706 will pull that number of data into a linear block.
707 @param[in] ExtFree Pointer to the caller provided free function.
708 @param[in] Arg The argument passed to ExtFree when ExtFree is
711 @return Pointer to the net buffer built from the data blocks,
712 or NULL if the allocation failed due to resource
719 IN NET_FRAGMENT
*ExtFragment
,
723 IN NET_VECTOR_EXT_FREE ExtFree
,
724 IN VOID
*Arg OPTIONAL
729 NET_FRAGMENT SavedFragment
;
734 UINT32 FirstBlockLen
;
741 ASSERT ((ExtFragment
!= NULL
) && (ExtNum
> 0) && (ExtFree
!= NULL
));
743 SavedFragment
.Bulk
= NULL
;
744 SavedFragment
.Len
= 0;
756 // No need to consolidate the header if the first block is
757 // longer than the header length or there is only one block.
759 if ((ExtFragment
[0].Len
>= HeadLen
) || (ExtNum
== 1)) {
764 // Allocate an extra block if we need to:
765 // 1. Allocate some header space
766 // 2. aggreate the packet header
768 if ((HeadSpace
!= 0) || (HeadLen
!= 0)) {
769 FirstBlockLen
= HeadLen
+ HeadSpace
;
770 FirstBlock
= AllocatePool (FirstBlockLen
);
772 if (FirstBlock
== NULL
) {
780 // Copy the header to the first block, reduce the NET_BLOCK
781 // to allocate by one for each block that is completely covered
782 // by the first bulk.
786 Header
= FirstBlock
+ HeadSpace
;
788 for (Index
= 0; Index
< ExtNum
; Index
++) {
789 if (Len
>= ExtFragment
[Index
].Len
) {
790 CopyMem (Header
, ExtFragment
[Index
].Bulk
, ExtFragment
[Index
].Len
);
792 Copied
+= ExtFragment
[Index
].Len
;
793 Len
-= ExtFragment
[Index
].Len
;
794 Header
+= ExtFragment
[Index
].Len
;
795 TotalLen
+= ExtFragment
[Index
].Len
;
800 // Increament the index number to point to the next
801 // non-empty fragment.
808 CopyMem (Header
, ExtFragment
[Index
].Bulk
, Len
);
814 // Adjust the block structure to exclude the data copied,
815 // So, the left-over block can be processed as other blocks.
816 // But it must be recovered later. (SavedIndex > 0) always
817 // holds since we don't aggreate the header if the first block
818 // is bigger enough that the header is continuous
821 SavedFragment
= ExtFragment
[Index
];
822 ExtFragment
[Index
].Bulk
+= Len
;
823 ExtFragment
[Index
].Len
-= Len
;
829 Nbuf
= NetbufAllocStruct (BlockNum
, BlockNum
);
835 Vector
= Nbuf
->Vector
;
836 Vector
->Free
= ExtFree
;
838 Vector
->Flag
= ((FirstBlockLen
!= 0) ? NET_VECTOR_OWN_FIRST
: 0);
841 // Set the first block up which may contain
842 // some head space and aggregated header
846 if (FirstBlockLen
!= 0) {
847 NetbufSetBlock (Nbuf
, FirstBlock
, HeadSpace
+ Copied
, 0);
848 Nbuf
->BlockOp
[0].Head
+= HeadSpace
;
849 Nbuf
->BlockOp
[0].Size
= Copied
;
854 for (; Index
< ExtNum
; Index
++) {
855 NetbufSetBlock (Nbuf
, ExtFragment
[Index
].Bulk
, ExtFragment
[Index
].Len
, CurBlock
);
856 TotalLen
+= ExtFragment
[Index
].Len
;
860 Vector
->Len
= TotalLen
+ HeadSpace
;
861 Nbuf
->TotalSize
= TotalLen
;
863 if (SavedIndex
!= 0) {
864 ExtFragment
[SavedIndex
] = SavedFragment
;
870 if (FirstBlock
!= NULL
) {
871 FreePool (FirstBlock
);
878 Build a fragment table to contain the fragments in the net buffer. This is the
879 opposite operation of the NetbufFromExt.
881 @param[in] Nbuf Point to the net buffer.
882 @param[in, out] ExtFragment Pointer to the data block.
883 @param[in, out] ExtNum The number of the data blocks.
885 @retval EFI_BUFFER_TOO_SMALL The number of non-empty block is bigger than
887 @retval EFI_SUCCESS Fragment table is built successfully.
894 IN OUT NET_FRAGMENT
*ExtFragment
,
895 IN OUT UINT32
*ExtNum
903 for (Index
= 0; (Index
< Nbuf
->BlockOpNum
); Index
++) {
904 if (Nbuf
->BlockOp
[Index
].Size
== 0) {
908 if (Current
< *ExtNum
) {
909 ExtFragment
[Current
].Bulk
= Nbuf
->BlockOp
[Index
].Head
;
910 ExtFragment
[Current
].Len
= Nbuf
->BlockOp
[Index
].Size
;
913 return EFI_BUFFER_TOO_SMALL
;
923 Build a net buffer from a list of net buffers.
925 All the fragments will be collected from the list of NEW_BUF and then a new
926 net buffer will be created through NetbufFromExt.
928 @param[in] BufList A List of the net buffer.
929 @param[in] HeadSpace The head space to be reserved.
930 @param[in] HeaderLen The length of the protocol header, This function
931 will pull that number of data into a linear block.
932 @param[in] ExtFree Pointer to the caller provided free function.
933 @param[in] Arg The argument passed to ExtFree when ExtFree is called.
935 @return Pointer to the net buffer built from the list of net
942 IN LIST_ENTRY
*BufList
,
945 IN NET_VECTOR_EXT_FREE ExtFree
,
946 IN VOID
*Arg OPTIONAL
949 NET_FRAGMENT
*Fragment
;
957 //Compute how many blocks are there
961 NET_LIST_FOR_EACH (Entry
, BufList
) {
962 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
963 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
964 FragmentNum
+= Nbuf
->BlockOpNum
;
968 //Allocate and copy block points
970 Fragment
= AllocatePool (sizeof (NET_FRAGMENT
) * FragmentNum
);
972 if (Fragment
== NULL
) {
978 NET_LIST_FOR_EACH (Entry
, BufList
) {
979 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
980 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
982 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
983 if (Nbuf
->BlockOp
[Index
].Size
!= 0) {
984 Fragment
[Current
].Bulk
= Nbuf
->BlockOp
[Index
].Head
;
985 Fragment
[Current
].Len
= Nbuf
->BlockOp
[Index
].Size
;
991 Nbuf
= NetbufFromExt (Fragment
, Current
, HeadSpace
, HeaderLen
, ExtFree
, Arg
);
999 Reserve some space in the header room of the net buffer.
1001 Upon allocation, all the space are in the tail room of the buffer. Call this
1002 function to move some space to the header room. This function is quite limited
1003 in that it can only reserve space from the first block of an empty NET_BUF not
1004 built from the external. But it should be enough for the network stack.
1006 @param[in, out] Nbuf Pointer to the net buffer.
1007 @param[in] Len The length of buffer to be reserved from the header.
1013 IN OUT NET_BUF
*Nbuf
,
1017 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1018 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1020 ASSERT ((Nbuf
->BlockOpNum
== 1) && (Nbuf
->TotalSize
== 0));
1021 ASSERT ((Nbuf
->Vector
->Free
== NULL
) && (Nbuf
->Vector
->Len
>= Len
));
1023 Nbuf
->BlockOp
[0].Head
+= Len
;
1024 Nbuf
->BlockOp
[0].Tail
+= Len
;
1026 ASSERT (Nbuf
->BlockOp
[0].Tail
<= Nbuf
->BlockOp
[0].BlockTail
);
1031 Allocate Len bytes of space from the header or tail of the buffer.
1033 @param[in, out] Nbuf Pointer to the net buffer.
1034 @param[in] Len The length of the buffer to be allocated.
1035 @param[in] FromHead The flag to indicate whether reserve the data
1036 from head (TRUE) or tail (FALSE).
1038 @return Pointer to the first byte of the allocated buffer,
1039 or NULL if there is no sufficient space.
1045 IN OUT NET_BUF
*Nbuf
,
1050 NET_BLOCK_OP
*BlockOp
;
1056 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1057 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1063 // Allocate some space from head. If the buffer is empty,
1064 // allocate from the first block. If it isn't, allocate
1065 // from the first non-empty block, or the block before that.
1067 if (Nbuf
->TotalSize
== 0) {
1070 NetbufGetByte (Nbuf
, 0, &Index
);
1072 if ((NET_HEADSPACE(&(Nbuf
->BlockOp
[Index
])) < Len
) && (Index
> 0)) {
1077 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
1079 if (NET_HEADSPACE (BlockOp
) < Len
) {
1083 BlockOp
->Head
-= Len
;
1084 BlockOp
->Size
+= Len
;
1085 Nbuf
->TotalSize
+= Len
;
1087 return BlockOp
->Head
;
1091 // Allocate some space from the tail. If the buffer is empty,
1092 // allocate from the first block. If it isn't, allocate
1093 // from the last non-empty block, or the block after that.
1095 if (Nbuf
->TotalSize
== 0) {
1098 NetbufGetByte (Nbuf
, Nbuf
->TotalSize
- 1, &Index
);
1100 if ((NET_TAILSPACE(&(Nbuf
->BlockOp
[Index
])) < Len
) &&
1101 (Index
< Nbuf
->BlockOpNum
- 1)) {
1107 BlockOp
= &(Nbuf
->BlockOp
[Index
]);
1109 if (NET_TAILSPACE (BlockOp
) < Len
) {
1113 SavedTail
= BlockOp
->Tail
;
1115 BlockOp
->Tail
+= Len
;
1116 BlockOp
->Size
+= Len
;
1117 Nbuf
->TotalSize
+= Len
;
1125 Trim a single NET_BLOCK by Len bytes from the header or tail.
1127 @param[in, out] BlockOp Pointer to the NET_BLOCK.
1128 @param[in] Len The length of the data to be trimmed.
1129 @param[in] FromHead The flag to indicate whether trim data from head
1130 (TRUE) or tail (FALSE).
1135 IN OUT NET_BLOCK_OP
*BlockOp
,
1140 ASSERT ((BlockOp
!= NULL
) && (BlockOp
->Size
>= Len
));
1142 BlockOp
->Size
-= Len
;
1145 BlockOp
->Head
+= Len
;
1147 BlockOp
->Tail
-= Len
;
1153 Trim Len bytes from the header or tail of the net buffer.
1155 @param[in, out] Nbuf Pointer to the net buffer.
1156 @param[in] Len The length of the data to be trimmed.
1157 @param[in] FromHead The flag to indicate whether trim data from head
1158 (TRUE) or tail (FALSE).
1160 @return Length of the actually trimmed data, which is possible to be less
1161 than Len because the TotalSize of Nbuf is less than Len.
1167 IN OUT NET_BUF
*Nbuf
,
1172 NET_BLOCK_OP
*BlockOp
;
1176 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1178 if (Len
> Nbuf
->TotalSize
) {
1179 Len
= Nbuf
->TotalSize
;
1183 // If FromTail is true, iterate backward. That
1184 // is, init Index to NBuf->BlockNum - 1, and
1185 // decrease it by 1 during each loop. Otherwise,
1186 // iterate forward. That is, init Index to 0, and
1187 // increase it by 1 during each loop.
1190 Nbuf
->TotalSize
-= Len
;
1192 Index
= (FromHead
? 0 : Nbuf
->BlockOpNum
- 1);
1193 BlockOp
= Nbuf
->BlockOp
;
1196 if (BlockOp
[Index
].Size
== 0) {
1197 Index
+= (FromHead
? 1 : -1);
1201 if (Len
> BlockOp
[Index
].Size
) {
1202 Len
-= BlockOp
[Index
].Size
;
1203 Trimmed
+= BlockOp
[Index
].Size
;
1204 NetblockTrim (&BlockOp
[Index
], BlockOp
[Index
].Size
, FromHead
);
1207 NetblockTrim (&BlockOp
[Index
], Len
, FromHead
);
1211 Index
+= (FromHead
? 1 : -1);
1219 Copy Len bytes of data from the specific offset of the net buffer to the
1222 The Len bytes of data may cross the several fragments of the net buffer.
1224 @param[in] Nbuf Pointer to the net buffer.
1225 @param[in] Offset The sequence number of the first byte to copy.
1226 @param[in] Len Length of the data to copy.
1227 @param[in] Dest The destination of the data to copy to.
1229 @return The length of the actual copied data, or 0 if the offset
1230 specified exceeds the total size of net buffer.
1242 NET_BLOCK_OP
*BlockOp
;
1249 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1252 if ((Len
== 0) || (Nbuf
->TotalSize
<= Offset
)) {
1256 if (Nbuf
->TotalSize
- Offset
< Len
) {
1257 Len
= Nbuf
->TotalSize
- Offset
;
1260 BlockOp
= Nbuf
->BlockOp
;
1263 // Skip to the offset. Don't make "Offset-By-One" error here.
1264 // Cur + BLOCK.SIZE is the first sequence number of next block.
1265 // So, (Offset < Cur + BLOCK.SIZE) means that the first byte
1266 // is in the current block. if (Offset == Cur + BLOCK.SIZE), the
1267 // first byte is the next block's first byte.
1271 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1272 if (BlockOp
[Index
].Size
== 0) {
1276 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
1280 Cur
+= BlockOp
[Index
].Size
;
1284 // Cur is the sequence number of the first byte in the block
1285 // Offset - Cur is the number of bytes before first byte to
1286 // to copy in the current block.
1288 Skip
= Offset
- Cur
;
1289 Left
= BlockOp
[Index
].Size
- Skip
;
1292 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Len
);
1296 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Left
);
1304 for (; Index
< Nbuf
->BlockOpNum
; Index
++) {
1305 if (Len
> BlockOp
[Index
].Size
) {
1306 Len
-= BlockOp
[Index
].Size
;
1307 Copied
+= BlockOp
[Index
].Size
;
1309 CopyMem (Dest
, BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1310 Dest
+= BlockOp
[Index
].Size
;
1313 CopyMem (Dest
, BlockOp
[Index
].Head
, Len
);
1323 Initiate the net buffer queue.
1325 @param[in, out] NbufQue Pointer to the net buffer queue to be initialized.
1331 IN OUT NET_BUF_QUEUE
*NbufQue
1334 NbufQue
->Signature
= NET_QUE_SIGNATURE
;
1335 NbufQue
->RefCnt
= 1;
1336 InitializeListHead (&NbufQue
->List
);
1338 InitializeListHead (&NbufQue
->BufList
);
1339 NbufQue
->BufSize
= 0;
1340 NbufQue
->BufNum
= 0;
1345 Allocate and initialize a net buffer queue.
1347 @return Pointer to the allocated net buffer queue, or NULL if the
1348 allocation failed due to resource limit.
1357 NET_BUF_QUEUE
*NbufQue
;
1359 NbufQue
= AllocatePool (sizeof (NET_BUF_QUEUE
));
1360 if (NbufQue
== NULL
) {
1364 NetbufQueInit (NbufQue
);
1371 Free a net buffer queue.
1373 Decrease the reference count of the net buffer queue by one. The real resource
1374 free operation isn't performed until the reference count of the net buffer
1375 queue is decreased to 0.
1377 @param[in] NbufQue Pointer to the net buffer queue to be freed.
1383 IN NET_BUF_QUEUE
*NbufQue
1386 ASSERT (NbufQue
!= NULL
);
1387 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1391 if (NbufQue
->RefCnt
== 0) {
1392 NetbufQueFlush (NbufQue
);
1399 Append a net buffer to the net buffer queue.
1401 @param[in, out] NbufQue Pointer to the net buffer queue.
1402 @param[in, out] Nbuf Pointer to the net buffer to be appended.
1408 IN OUT NET_BUF_QUEUE
*NbufQue
,
1409 IN OUT NET_BUF
*Nbuf
1412 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1413 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1415 InsertTailList (&NbufQue
->BufList
, &Nbuf
->List
);
1417 NbufQue
->BufSize
+= Nbuf
->TotalSize
;
1423 Remove a net buffer from the head in the specific queue and return it.
1425 @param[in, out] NbufQue Pointer to the net buffer queue.
1427 @return Pointer to the net buffer removed from the specific queue,
1428 or NULL if there is no net buffer in the specific queue.
1434 IN OUT NET_BUF_QUEUE
*NbufQue
1439 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1441 if (NbufQue
->BufNum
== 0) {
1445 First
= NET_LIST_USER_STRUCT (NbufQue
->BufList
.ForwardLink
, NET_BUF
, List
);
1447 NetListRemoveHead (&NbufQue
->BufList
);
1449 NbufQue
->BufSize
-= First
->TotalSize
;
1456 Copy Len bytes of data from the net buffer queue at the specific offset to the
1459 The copying operation is the same as NetbufCopy but applies to the net buffer
1460 queue instead of the net buffer.
1462 @param[in] NbufQue Pointer to the net buffer queue.
1463 @param[in] Offset The sequence number of the first byte to copy.
1464 @param[in] Len Length of the data to copy.
1465 @param[out] Dest The destination of the data to copy to.
1467 @return The length of the actual copied data, or 0 if the offset
1468 specified exceeds the total size of net buffer queue.
1474 IN NET_BUF_QUEUE
*NbufQue
,
1487 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1488 ASSERT (Dest
!= NULL
);
1490 if ((Len
== 0) || (NbufQue
->BufSize
<= Offset
)) {
1494 if (NbufQue
->BufSize
- Offset
< Len
) {
1495 Len
= NbufQue
->BufSize
- Offset
;
1499 // skip to the Offset
1504 NET_LIST_FOR_EACH (Entry
, &NbufQue
->BufList
) {
1505 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1507 if (Offset
< Cur
+ Nbuf
->TotalSize
) {
1511 Cur
+= Nbuf
->TotalSize
;
1514 ASSERT (Nbuf
!= NULL
);
1517 // Copy the data in the first buffer.
1519 Skip
= Offset
- Cur
;
1520 Left
= Nbuf
->TotalSize
- Skip
;
1523 return NetbufCopy (Nbuf
, Skip
, Len
, Dest
);
1526 NetbufCopy (Nbuf
, Skip
, Left
, Dest
);
1532 // Iterate over the others
1534 Entry
= Entry
->ForwardLink
;
1536 while ((Len
> 0) && (Entry
!= &NbufQue
->BufList
)) {
1537 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1539 if (Len
> Nbuf
->TotalSize
) {
1540 Len
-= Nbuf
->TotalSize
;
1541 Copied
+= Nbuf
->TotalSize
;
1543 NetbufCopy (Nbuf
, 0, Nbuf
->TotalSize
, Dest
);
1544 Dest
+= Nbuf
->TotalSize
;
1547 NetbufCopy (Nbuf
, 0, Len
, Dest
);
1552 Entry
= Entry
->ForwardLink
;
1560 Trim Len bytes of data from the buffer queue and free any net buffer
1561 that is completely trimmed.
1563 The trimming operation is the same as NetbufTrim but applies to the net buffer
1564 queue instead of the net buffer.
1566 @param[in, out] NbufQue Pointer to the net buffer queue.
1567 @param[in] Len Length of the data to trim.
1569 @return The actual length of the data trimmed.
1575 IN OUT NET_BUF_QUEUE
*NbufQue
,
1584 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1590 if (Len
> NbufQue
->BufSize
) {
1591 Len
= NbufQue
->BufSize
;
1594 NbufQue
->BufSize
-= Len
;
1597 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &NbufQue
->BufList
) {
1598 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1600 if (Len
>= Nbuf
->TotalSize
) {
1601 Trimmed
+= Nbuf
->TotalSize
;
1602 Len
-= Nbuf
->TotalSize
;
1604 RemoveEntryList (Entry
);
1614 Trimmed
+= NetbufTrim (Nbuf
, Len
, NET_BUF_HEAD
);
1624 Flush the net buffer queue.
1626 @param[in, out] NbufQue Pointer to the queue to be flushed.
1632 IN OUT NET_BUF_QUEUE
*NbufQue
1635 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1637 NetbufFreeList (&NbufQue
->BufList
);
1639 NbufQue
->BufNum
= 0;
1640 NbufQue
->BufSize
= 0;
1645 Compute the checksum for a bulk of data.
1647 @param[in] Bulk Pointer to the data.
1648 @param[in] Len Length of the data, in bytes.
1650 @return The computed checksum.
1660 register UINT32 Sum
;
1665 Sum
+= *(UINT16
*) Bulk
;
1671 // Add left-over byte, if any
1674 Sum
+= *(UINT8
*) Bulk
;
1678 // Fold 32-bit sum to 16 bits
1680 while ((Sum
>> 16) != 0) {
1681 Sum
= (Sum
& 0xffff) + (Sum
>> 16);
1685 return (UINT16
) Sum
;
1692 @param[in] Checksum1 The first checksum to be added.
1693 @param[in] Checksum2 The second checksum to be added.
1695 @return The new checksum.
1701 IN UINT16 Checksum1
,
1707 Sum
= Checksum1
+ Checksum2
;
1710 // two UINT16 can only add up to a carry of 1.
1712 if ((Sum
>> 16) != 0) {
1713 Sum
= (Sum
& 0xffff) + 1;
1717 return (UINT16
) Sum
;
1722 Compute the checksum for a NET_BUF.
1724 @param[in] Nbuf Pointer to the net buffer.
1726 @return The computed checksum.
1735 NET_BLOCK_OP
*BlockOp
;
1741 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1745 BlockOp
= Nbuf
->BlockOp
;
1747 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1748 if (BlockOp
[Index
].Size
== 0) {
1752 BlockSum
= NetblockChecksum (BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1754 if ((Offset
& 0x01) != 0) {
1756 // The checksum starts with an odd byte, swap
1757 // the checksum before added to total checksum
1759 BlockSum
= SwapBytes16 (BlockSum
);
1762 TotalSum
= NetAddChecksum (BlockSum
, TotalSum
);
1763 Offset
+= BlockOp
[Index
].Size
;
1771 Compute the checksum for TCP/UDP pseudo header.
1773 Src and Dst are in network byte order, and Len is in host byte order.
1775 @param[in] Src The source address of the packet.
1776 @param[in] Dst The destination address of the packet.
1777 @param[in] Proto The protocol type of the packet.
1778 @param[in] Len The length of the packet.
1780 @return The computed checksum.
1785 NetPseudoHeadChecksum (
1795 // Zero the memory to relieve align problems
1797 ZeroMem (&Hdr
, sizeof (Hdr
));
1801 Hdr
.Protocol
= Proto
;
1802 Hdr
.Len
= HTONS (Len
);
1804 return NetblockChecksum ((UINT8
*) &Hdr
, sizeof (Hdr
));
1808 Compute the checksum for TCP6/UDP6 pseudo header.
1810 Src and Dst are in network byte order, and Len is in host byte order.
1812 @param[in] Src The source address of the packet.
1813 @param[in] Dst The destination address of the packet.
1814 @param[in] NextHeader The protocol type of the packet.
1815 @param[in] Len The length of the packet.
1817 @return The computed checksum.
1822 NetIp6PseudoHeadChecksum (
1823 IN EFI_IPv6_ADDRESS
*Src
,
1824 IN EFI_IPv6_ADDRESS
*Dst
,
1825 IN UINT8 NextHeader
,
1829 NET_IP6_PSEUDO_HDR Hdr
;
1832 // Zero the memory to relieve align problems
1834 ZeroMem (&Hdr
, sizeof (Hdr
));
1836 IP6_COPY_ADDRESS (&Hdr
.SrcIp
, Src
);
1837 IP6_COPY_ADDRESS (&Hdr
.DstIp
, Dst
);
1839 Hdr
.NextHeader
= NextHeader
;
1840 Hdr
.Len
= HTONL (Len
);
1842 return NetblockChecksum ((UINT8
*) &Hdr
, sizeof (Hdr
));
1846 The function frees the net buffer which allocated by the IP protocol. It releases
1847 only the net buffer and doesn't call the external free function.
1849 This function should be called after finishing the process of mIpSec->ProcessExt()
1850 for outbound traffic. The (EFI_IPSEC2_PROTOCOL)->ProcessExt() allocates a new
1851 buffer for the ESP, so there needs a function to free the old net buffer.
1853 @param[in] Nbuf The network buffer to be freed.
1857 NetIpSecNetbufFree (
1861 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1862 ASSERT (Nbuf
->RefCnt
> 0);
1866 if (Nbuf
->RefCnt
== 0) {
1869 // Update Vector only when NBuf is to be released. That is,
1870 // all the sharing of Nbuf increse Vector's RefCnt by one
1872 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1873 ASSERT (Nbuf
->Vector
->RefCnt
> 0);
1875 Nbuf
->Vector
->RefCnt
--;
1877 if (Nbuf
->Vector
->RefCnt
> 0) {
1882 // If NET_VECTOR_OWN_FIRST is set, release the first block since it is
1885 if ((Nbuf
->Vector
->Flag
& NET_VECTOR_OWN_FIRST
) != 0) {
1886 FreePool (Nbuf
->Vector
->Block
[0].Bulk
);
1888 FreePool (Nbuf
->Vector
);