2 Network library functions providing net buffer operation support.
4 Copyright (c) 2005 - 2017, 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
== 0 || Nbuf
->TotalSize
== 0) {
1182 if (Len
> Nbuf
->TotalSize
) {
1183 Len
= Nbuf
->TotalSize
;
1187 // If FromTail is true, iterate backward. That
1188 // is, init Index to NBuf->BlockNum - 1, and
1189 // decrease it by 1 during each loop. Otherwise,
1190 // iterate forward. That is, init Index to 0, and
1191 // increase it by 1 during each loop.
1194 Nbuf
->TotalSize
-= Len
;
1196 Index
= (FromHead
? 0 : Nbuf
->BlockOpNum
- 1);
1197 BlockOp
= Nbuf
->BlockOp
;
1200 if (BlockOp
[Index
].Size
== 0) {
1201 Index
+= (FromHead
? 1 : -1);
1205 if (Len
> BlockOp
[Index
].Size
) {
1206 Len
-= BlockOp
[Index
].Size
;
1207 Trimmed
+= BlockOp
[Index
].Size
;
1208 NetblockTrim (&BlockOp
[Index
], BlockOp
[Index
].Size
, FromHead
);
1211 NetblockTrim (&BlockOp
[Index
], Len
, FromHead
);
1215 Index
+= (FromHead
? 1 : -1);
1223 Copy Len bytes of data from the specific offset of the net buffer to the
1226 The Len bytes of data may cross the several fragments of the net buffer.
1228 @param[in] Nbuf Pointer to the net buffer.
1229 @param[in] Offset The sequence number of the first byte to copy.
1230 @param[in] Len Length of the data to copy.
1231 @param[in] Dest The destination of the data to copy to.
1233 @return The length of the actual copied data, or 0 if the offset
1234 specified exceeds the total size of net buffer.
1246 NET_BLOCK_OP
*BlockOp
;
1253 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1256 if ((Len
== 0) || (Nbuf
->TotalSize
<= Offset
)) {
1260 if (Nbuf
->TotalSize
- Offset
< Len
) {
1261 Len
= Nbuf
->TotalSize
- Offset
;
1264 BlockOp
= Nbuf
->BlockOp
;
1267 // Skip to the offset. Don't make "Offset-By-One" error here.
1268 // Cur + BLOCK.SIZE is the first sequence number of next block.
1269 // So, (Offset < Cur + BLOCK.SIZE) means that the first byte
1270 // is in the current block. if (Offset == Cur + BLOCK.SIZE), the
1271 // first byte is the next block's first byte.
1275 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1276 if (BlockOp
[Index
].Size
== 0) {
1280 if (Offset
< Cur
+ BlockOp
[Index
].Size
) {
1284 Cur
+= BlockOp
[Index
].Size
;
1288 // Cur is the sequence number of the first byte in the block
1289 // Offset - Cur is the number of bytes before first byte to
1290 // to copy in the current block.
1292 Skip
= Offset
- Cur
;
1293 Left
= BlockOp
[Index
].Size
- Skip
;
1296 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Len
);
1300 CopyMem (Dest
, BlockOp
[Index
].Head
+ Skip
, Left
);
1308 for (; Index
< Nbuf
->BlockOpNum
; Index
++) {
1309 if (Len
> BlockOp
[Index
].Size
) {
1310 Len
-= BlockOp
[Index
].Size
;
1311 Copied
+= BlockOp
[Index
].Size
;
1313 CopyMem (Dest
, BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1314 Dest
+= BlockOp
[Index
].Size
;
1317 CopyMem (Dest
, BlockOp
[Index
].Head
, Len
);
1327 Initiate the net buffer queue.
1329 @param[in, out] NbufQue Pointer to the net buffer queue to be initialized.
1335 IN OUT NET_BUF_QUEUE
*NbufQue
1338 NbufQue
->Signature
= NET_QUE_SIGNATURE
;
1339 NbufQue
->RefCnt
= 1;
1340 InitializeListHead (&NbufQue
->List
);
1342 InitializeListHead (&NbufQue
->BufList
);
1343 NbufQue
->BufSize
= 0;
1344 NbufQue
->BufNum
= 0;
1349 Allocate and initialize a net buffer queue.
1351 @return Pointer to the allocated net buffer queue, or NULL if the
1352 allocation failed due to resource limit.
1361 NET_BUF_QUEUE
*NbufQue
;
1363 NbufQue
= AllocatePool (sizeof (NET_BUF_QUEUE
));
1364 if (NbufQue
== NULL
) {
1368 NetbufQueInit (NbufQue
);
1375 Free a net buffer queue.
1377 Decrease the reference count of the net buffer queue by one. The real resource
1378 free operation isn't performed until the reference count of the net buffer
1379 queue is decreased to 0.
1381 @param[in] NbufQue Pointer to the net buffer queue to be freed.
1387 IN NET_BUF_QUEUE
*NbufQue
1390 ASSERT (NbufQue
!= NULL
);
1391 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1395 if (NbufQue
->RefCnt
== 0) {
1396 NetbufQueFlush (NbufQue
);
1403 Append a net buffer to the net buffer queue.
1405 @param[in, out] NbufQue Pointer to the net buffer queue.
1406 @param[in, out] Nbuf Pointer to the net buffer to be appended.
1412 IN OUT NET_BUF_QUEUE
*NbufQue
,
1413 IN OUT NET_BUF
*Nbuf
1416 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1417 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1419 InsertTailList (&NbufQue
->BufList
, &Nbuf
->List
);
1421 NbufQue
->BufSize
+= Nbuf
->TotalSize
;
1427 Remove a net buffer from the head in the specific queue and return it.
1429 @param[in, out] NbufQue Pointer to the net buffer queue.
1431 @return Pointer to the net buffer removed from the specific queue,
1432 or NULL if there is no net buffer in the specific queue.
1438 IN OUT NET_BUF_QUEUE
*NbufQue
1443 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1445 if (NbufQue
->BufNum
== 0) {
1449 First
= NET_LIST_USER_STRUCT (NbufQue
->BufList
.ForwardLink
, NET_BUF
, List
);
1451 NetListRemoveHead (&NbufQue
->BufList
);
1453 NbufQue
->BufSize
-= First
->TotalSize
;
1460 Copy Len bytes of data from the net buffer queue at the specific offset to the
1463 The copying operation is the same as NetbufCopy but applies to the net buffer
1464 queue instead of the net buffer.
1466 @param[in] NbufQue Pointer to the net buffer queue.
1467 @param[in] Offset The sequence number of the first byte to copy.
1468 @param[in] Len Length of the data to copy.
1469 @param[out] Dest The destination of the data to copy to.
1471 @return The length of the actual copied data, or 0 if the offset
1472 specified exceeds the total size of net buffer queue.
1478 IN NET_BUF_QUEUE
*NbufQue
,
1491 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1492 ASSERT (Dest
!= NULL
);
1494 if ((Len
== 0) || (NbufQue
->BufSize
<= Offset
)) {
1498 if (NbufQue
->BufSize
- Offset
< Len
) {
1499 Len
= NbufQue
->BufSize
- Offset
;
1503 // skip to the Offset
1508 NET_LIST_FOR_EACH (Entry
, &NbufQue
->BufList
) {
1509 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1511 if (Offset
< Cur
+ Nbuf
->TotalSize
) {
1515 Cur
+= Nbuf
->TotalSize
;
1518 ASSERT (Nbuf
!= NULL
);
1521 // Copy the data in the first buffer.
1523 Skip
= Offset
- Cur
;
1524 Left
= Nbuf
->TotalSize
- Skip
;
1527 return NetbufCopy (Nbuf
, Skip
, Len
, Dest
);
1530 NetbufCopy (Nbuf
, Skip
, Left
, Dest
);
1536 // Iterate over the others
1538 Entry
= Entry
->ForwardLink
;
1540 while ((Len
> 0) && (Entry
!= &NbufQue
->BufList
)) {
1541 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1543 if (Len
> Nbuf
->TotalSize
) {
1544 Len
-= Nbuf
->TotalSize
;
1545 Copied
+= Nbuf
->TotalSize
;
1547 NetbufCopy (Nbuf
, 0, Nbuf
->TotalSize
, Dest
);
1548 Dest
+= Nbuf
->TotalSize
;
1551 NetbufCopy (Nbuf
, 0, Len
, Dest
);
1556 Entry
= Entry
->ForwardLink
;
1564 Trim Len bytes of data from the buffer queue and free any net buffer
1565 that is completely trimmed.
1567 The trimming operation is the same as NetbufTrim but applies to the net buffer
1568 queue instead of the net buffer.
1570 @param[in, out] NbufQue Pointer to the net buffer queue.
1571 @param[in] Len Length of the data to trim.
1573 @return The actual length of the data trimmed.
1579 IN OUT NET_BUF_QUEUE
*NbufQue
,
1588 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1594 if (Len
> NbufQue
->BufSize
) {
1595 Len
= NbufQue
->BufSize
;
1598 NbufQue
->BufSize
-= Len
;
1601 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &NbufQue
->BufList
) {
1602 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1604 if (Len
>= Nbuf
->TotalSize
) {
1605 Trimmed
+= Nbuf
->TotalSize
;
1606 Len
-= Nbuf
->TotalSize
;
1608 RemoveEntryList (Entry
);
1618 Trimmed
+= NetbufTrim (Nbuf
, Len
, NET_BUF_HEAD
);
1628 Flush the net buffer queue.
1630 @param[in, out] NbufQue Pointer to the queue to be flushed.
1636 IN OUT NET_BUF_QUEUE
*NbufQue
1639 NET_CHECK_SIGNATURE (NbufQue
, NET_QUE_SIGNATURE
);
1641 NetbufFreeList (&NbufQue
->BufList
);
1643 NbufQue
->BufNum
= 0;
1644 NbufQue
->BufSize
= 0;
1649 Compute the checksum for a bulk of data.
1651 @param[in] Bulk Pointer to the data.
1652 @param[in] Len Length of the data, in bytes.
1654 @return The computed checksum.
1664 register UINT32 Sum
;
1669 // Add left-over byte, if any
1672 Sum
+= *(Bulk
+ Len
- 1);
1676 Sum
+= *(UINT16
*) Bulk
;
1682 // Fold 32-bit sum to 16 bits
1684 while ((Sum
>> 16) != 0) {
1685 Sum
= (Sum
& 0xffff) + (Sum
>> 16);
1689 return (UINT16
) Sum
;
1696 @param[in] Checksum1 The first checksum to be added.
1697 @param[in] Checksum2 The second checksum to be added.
1699 @return The new checksum.
1705 IN UINT16 Checksum1
,
1711 Sum
= Checksum1
+ Checksum2
;
1714 // two UINT16 can only add up to a carry of 1.
1716 if ((Sum
>> 16) != 0) {
1717 Sum
= (Sum
& 0xffff) + 1;
1721 return (UINT16
) Sum
;
1726 Compute the checksum for a NET_BUF.
1728 @param[in] Nbuf Pointer to the net buffer.
1730 @return The computed checksum.
1739 NET_BLOCK_OP
*BlockOp
;
1745 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1749 BlockOp
= Nbuf
->BlockOp
;
1751 for (Index
= 0; Index
< Nbuf
->BlockOpNum
; Index
++) {
1752 if (BlockOp
[Index
].Size
== 0) {
1756 BlockSum
= NetblockChecksum (BlockOp
[Index
].Head
, BlockOp
[Index
].Size
);
1758 if ((Offset
& 0x01) != 0) {
1760 // The checksum starts with an odd byte, swap
1761 // the checksum before added to total checksum
1763 BlockSum
= SwapBytes16 (BlockSum
);
1766 TotalSum
= NetAddChecksum (BlockSum
, TotalSum
);
1767 Offset
+= BlockOp
[Index
].Size
;
1775 Compute the checksum for TCP/UDP pseudo header.
1777 Src and Dst are in network byte order, and Len is in host byte order.
1779 @param[in] Src The source address of the packet.
1780 @param[in] Dst The destination address of the packet.
1781 @param[in] Proto The protocol type of the packet.
1782 @param[in] Len The length of the packet.
1784 @return The computed checksum.
1789 NetPseudoHeadChecksum (
1799 // Zero the memory to relieve align problems
1801 ZeroMem (&Hdr
, sizeof (Hdr
));
1805 Hdr
.Protocol
= Proto
;
1806 Hdr
.Len
= HTONS (Len
);
1808 return NetblockChecksum ((UINT8
*) &Hdr
, sizeof (Hdr
));
1812 Compute the checksum for TCP6/UDP6 pseudo header.
1814 Src and Dst are in network byte order, and Len is in host byte order.
1816 @param[in] Src The source address of the packet.
1817 @param[in] Dst The destination address of the packet.
1818 @param[in] NextHeader The protocol type of the packet.
1819 @param[in] Len The length of the packet.
1821 @return The computed checksum.
1826 NetIp6PseudoHeadChecksum (
1827 IN EFI_IPv6_ADDRESS
*Src
,
1828 IN EFI_IPv6_ADDRESS
*Dst
,
1829 IN UINT8 NextHeader
,
1833 NET_IP6_PSEUDO_HDR Hdr
;
1836 // Zero the memory to relieve align problems
1838 ZeroMem (&Hdr
, sizeof (Hdr
));
1840 IP6_COPY_ADDRESS (&Hdr
.SrcIp
, Src
);
1841 IP6_COPY_ADDRESS (&Hdr
.DstIp
, Dst
);
1843 Hdr
.NextHeader
= NextHeader
;
1844 Hdr
.Len
= HTONL (Len
);
1846 return NetblockChecksum ((UINT8
*) &Hdr
, sizeof (Hdr
));
1850 The function frees the net buffer which allocated by the IP protocol. It releases
1851 only the net buffer and doesn't call the external free function.
1853 This function should be called after finishing the process of mIpSec->ProcessExt()
1854 for outbound traffic. The (EFI_IPSEC2_PROTOCOL)->ProcessExt() allocates a new
1855 buffer for the ESP, so there needs a function to free the old net buffer.
1857 @param[in] Nbuf The network buffer to be freed.
1861 NetIpSecNetbufFree (
1865 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1866 ASSERT (Nbuf
->RefCnt
> 0);
1870 if (Nbuf
->RefCnt
== 0) {
1873 // Update Vector only when NBuf is to be released. That is,
1874 // all the sharing of Nbuf increse Vector's RefCnt by one
1876 NET_CHECK_SIGNATURE (Nbuf
->Vector
, NET_VECTOR_SIGNATURE
);
1877 ASSERT (Nbuf
->Vector
->RefCnt
> 0);
1879 Nbuf
->Vector
->RefCnt
--;
1881 if (Nbuf
->Vector
->RefCnt
> 0) {
1886 // If NET_VECTOR_OWN_FIRST is set, release the first block since it is
1889 if ((Nbuf
->Vector
->Flag
& NET_VECTOR_OWN_FIRST
) != 0) {
1890 FreePool (Nbuf
->Vector
->Block
[0].Bulk
);
1892 FreePool (Nbuf
->Vector
);