Name: Fragmentation and Re

advertisement
Name: Fragmentation and Re-assembly
Description:
Given a payload that exceeds a certain length MAX_FRAGMENT_LENGTH, the
send side of this component splits the payload into more than one fragment such that the
length of none of the fragments exceeds MAX_FRAGMENT_LENGTH. The receive
side of this component reassembles all fragments of a particular payload into the original
payload. Delivery of reassembled payload is not guaranteed. On arrival of the first
fragment of a payload, a timer is started. If all fragments of this payload do not arrive
before the expiration of the timer, all received fragments of this payload are discarded.
Constraints:
1. Values for “payload identifier” do not wrap around.
2. Transmitted fragments of a particular payload are numbered in a monotonically
increasing manner, starting at 1 and leaving no gaps.
3. The transmit state machine handles one payload fragmentation at a time.
4. Hop-by-hop re-assembly of fragments is supported (required??).
Properties:
1. Length of none of the transmitted fragments exceeds
MAX_FRAGMENT_LENGTH.
2. Delivered payload is identical to transmitted payload.
3. No more than one copy of the transmitted payload is delivered.
4. Delivery of the transmitted payload is not guaranteed.
5. Receive side of component never consumes more than MAX_BUFFER_LENGTH of
memory for buffering fragments.
Assumptions:
1. Received fragments have no bit errors.
Parameters:
Name:
Type:
Description:
Required?
Default Value:
(SEND) MAX_FRAGMENT_LENGTH
int
The maximum size of any transmitted fragment.
Yes
None
Name:
Type:
Description:
(SEND) PayloadIdentifierKey
int
Key to make generated “payload identifier” globally
unique. (unique per stack per node)
Required?
Default Value:
Yes
None
Note: All values of the “payload identifier” tagged by all sender components (on same or
different hosts) are unique. (In conventional protocols, the source address of the fragment
is used to distinguish fragments from different hosts that carry the same “payload
identifier”. The same technique (requires access to the “source address” header field) or
some other mechanism to ensure uniqueness of “payload identifier” shall be used.)
Name:
Type:
Description:
Required?
Default Value:
Name:
Type:
Description:
Required?
Default Value:
(RECEIVE) TimeoutLimit
int
Timeout value to start garbage collection of buffered
fragments, which could not be reassembled.
Yes
None
(RECEIVE) MAX_BUFFER_LENGTH
int
Maximum memory that the receive state machine
shall use to buffer fragments received out of order.
Yes
None
Local Memory:
type RcvdFragments = record of
MaxFragmentNum : int
BufferedFragments : indexed collection of byte arrays
end record
This record is meant to hold all received fragments that have the same ‘Payload
Identifier’. The member ‘MaxFragmentNum’ will be set to
pktComponentMemory.FragmentNum of the fragment whose
pktComponentMemory.LastFragment is TRUE and is used to retrieve all buffered
fragments from the member ‘BufferedFragments’. The member ‘BufferedFragments’ is
indexed by pktComponentMemory.FragmentNum.
1.
2.
3.
4.
(SEND) var locmem_NextPayloadIdentifer : int
(SEND) var locmem_NumberOfFrag : int
(SEND) var locmem_LastSentFragment : int
(RECEIVE) var locmem_BufferedFragments : indexed collection of RcvdFragments
Note: This collection holds fragments received from all sources and is indexed by
pktComponentMemory.PayloadIdentifier
5. (RECEIVE) var locmem_MemUsed : int
6. (RECEIVE) const locmem_MaxFragmentLength : int
7. (RECEIVE) const locmem_GCTimeout : int
8. (RECEIVE) const locmem_MaxBufferLength : int
Global Memory:
None
Protocol Memory:
None
Packet Memory:
type FragHeader = record of
PayloadIdentifier : int
/* corresponds to UID field of IP */
FragmentNum : int
/* analogous to ‘Fragmentation Offset’ field of IP) */
LastFragment : boolean /* corresponds to one of the bits in the ‘Flags’ field of IP */
FragmentDataLen : int
FragmentData : byte[]
end record
/*length of fragmented data , 0 for unfragmented packets */
/*Data of this fragment, empty for unfragmented packets */
Transmit State Machine:
1
2
3
Wait
Send
Fragments
4
Transition No. 1
Event:
Guard:
Comment:
Action:
Packet Arrival
pktPayload.length <= locmem_MaxFragmentLength
Payload need not be fragmented. Pass the payload along using PktSend().
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
pktComponentMemory.PayloadIdentifier <- locmem_NextPayloadIdentifier;
pktComponentMemory.FragmentNum <- 1;
pktComponentMemory.LastFragment <- TRUE;
PktSend( pktComponentMemory );
Inc(locmem_NextPayloadIdentifier);
}
Transition No. 2
Event:
Guard:
Comment:
Action:
Packet Arrival
pktPayload.length > locmem_MaxFragmentLength
Payload should be fragmented. Calculate the number of fragments
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
locmem_NumberOfFrag = pktPayload.length DIV locmem_MaxFragmentLength;
if ( pktPayload.length MOD locmem_MaxFragmentLength != 0 )
Inc ( locmem_NumberOfFrag );
fi
locmem_LastSentFragment <- 0;
}
Transition No. 3
Event:
Guard:
Comment:
Action:
None
locmem_LastSentFragment < locmem_NumberOfFrag
Send the ith fragment
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
pktComponentMemory.PayloadIdentifier <-locmem_NextPayloadIdentifier;
pktComponentMemory.FragmentNum <- locmem_LastSentFragment + 1;
if ( locmem_LastSentFragment + 1 == locmem_NumberOfFrag )
pktComponentMemory.LastFragment <- TRUE
else
pktComponentMemory.LastFragment <- FALSE
fi
/* Copy bytes numbered from (locmem_LastSentFragment *
locmem_MaxFragmentLength) to ((locmem_LastSentFragment + 1) *
locmem_MaxFragmentLength – 1) of pktPayload into
pktComponentMemory.FragmentData */
/* First byte of pktPayload is numbered zero */
/* Set pktComponentMemory.FragmentDataLen to the size of the byte array
pktComponentMemory.FragmentData */
NewPktSend(pktComponentMemory);
Inc(locmem_LastSentFragment);
}
Transition No. 4
Event:
Guard:
Comment:
Action:
None
locmem_LastSentFragment >= locmem_NumberOfFrag
All fragments sent. Return to wait state
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
Inc(locmem_NextPayloadIdentifier);
}
Receive State Machine – Version 1:
(Fewer states and complex guard conditions)
1, 2, 3, 4, 6
8, 9
WAIT
???
5, 7
Transition No. 1
Event:
Guard:
Comment:
Action:
Timeout
None
Garbage collect fragments of payload whose timer expired
fn (timerID : timerHandle)
{
/* Free fragments in locmem_BufferedFragments whose ‘PayloadIdentifier’ is
‘timerID’ */
}
Transition No. 2
Event:
Guard:
Comment:
Action:
Packet Arrival
locmem_MemUsed >= locmem_MaxBufferLength
No more memory to buffer fragments. Drop the packet
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
DropPacket();
}
Transition No. 3
Event:
Guard:
Comment:
Packet Arrival
locmem_MemUsed < locmem_MaxBufferLength AND
pktComponentMemory.LastFragment == TRUE AND
pktComponentMemory.FragmentNum == 1
Result of PayloadIdentifierNotSeenYet(pktComponentMemory) does not
matter. Unfragmented payload, deliver to upper component.
Action:
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
PktDeliver(pktPayload);
}
Transition No. 4
Event:
Guard:
Comment:
Packet Arrival
locmem_MemUsed < locmem_MaxBufferLength AND
pktComponentMemory.LastFragment == TRUE AND
pktComponentMemory.FragmentNum != 1 AND
PayloadIdentifierNotSeenYet(pktComponentMemory) == TRUE
Length of fragmented payload now known and this is the first received
fragment with this ‘PayloadIdentifier’
Action:
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
AddToCollection(pktComponentMemory);
locmem_BufferedFragments[pktComponentMemory.PayloadIdentifier].
MaxFragmentNum <- pktComponentMemory.FragmentNum;
SetTimeout(pktComponentMemory.PayloadIdentifier, locmem_GCTimeout)
}
Transition No. 5
Event:
Guard:
Comment:
Packet Arrival
locmem_MemUsed < locmem_MaxBufferLength AND
pktComponentMemory.LastFragment == TRUE AND
pktComponentMemory.FragmentNum != 1 AND
PayloadIdentifierNotSeenYet(pktComponentMemory) == FALSE
Length of fragmented payload now known and this is not the first received
fragment with this ‘PayloadIdenitfier’
Action:
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
AddToCollection(pktComponentMemory);
locmem_BufferedFragments[pktComponentMemory.PayloadIdentifier].
MaxFragmentNum <- pktComponentMemory.FragmentNum;
}
Transition No. 6
Event:
Guard:
Comment:
Packet Arrival
locmem_MemUsed < locmem_MaxBufferLength AND
pktComponentMemory.LastFragment == FALSE AND
PayloadIdentifierNotSeenYet(pktComponentMemory) == TRUE
Value of pktComponentMemory.FragmentNum does not matter.
This is the first received fragment with this ‘PayloadIdentifier’
Action:
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
AddToCollection(pktComponentMemory);
SetTimeout(pktComponentMemory.PayloadIdentifier, locmem_GCTimeout)
}
Transition No. 7
Event:
Guard:
Comment:
Packet Arrival
locmem_MemUsed < locmem_MaxBufferLength AND
pktComponentMemory.LastFragment == FALSE AND
PayloadIdentifierNotSeenYet(pktComponentMemory) == FALSE
Value of pktComponentMemory.FragmentNum does not matter.
This is not the first received fragment with this ‘PayloadIdentifier’
Action:
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
AddToCollection(pktComponentMemory);
}
Transition No. 8
Event:
Guard:
Comment:
Action:
None
IsPayloadComplete(pktComponentMemory) == TRUE
Reassemble and deliver the payload to upper component.
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
var ReassembledPayload : byte array;
/* Concatenate all elements from the collection
locmem_BufferedFragments[pktComponentMemory.PayloadIdentifier].BufferedFragme
nts into ReassembledPayload */
NewPktDeliver(ReassembledPayload);
CancelTimeout(pktComponentMemory.PayloadIdentifier);
}
Transition No. 9
Event:
Guard:
Comment:
Action:
None
IsPayloadComplete(pktComponentMemory) == FALSE
More fragments are needed to reassemble this payload
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
}
Helper functions:
function PayloadIdentifierNotSeenYet(var header : FragHeader) : boolean
/* Return FALSE if
locmem_BufferedFragments[header.PayloadIdentifier].BufferedFragments has
atleast one of its byte arrays filled, else return TRUE. */
end PayloadIdentifierNotSeenYet
Note: PayloadIdentifierNotSeenYet() == TRUE does not imply that a fragment carrying
this ‘PayloadIdentifier’ was NEVER received by this state machine. If all fragments of a
payload were duplicated at an intermediate router and the first copy of all fragments
reached this state machine en masse and some time later, the second copy of all
fragments also arrived, then two copies of the reassembled payload will be delivered to
the upper component. If the two copies of the fragments reached this state machine
intermingled, then only one copy of the reassembled payload will be delivered. This is
because the receive state machine does not remember the values for ‘PayloadIdentifier’
of fragments that have been received so far.
procedure AddToCollection(var header : FragHeader)
/* Insert header.FragmentData into
locmem_BufferedFragments[header.PayloadIdentifier].BufferedFragments[heade
r.FragmentNum] */
end AddToCollection
function IsPayloadComplete(var header : FragHeader)
/* Return TRUE if the collection
locmem_BufferedFragments[header.PayloadIdentifier].BufferedFragments has all
its byte arrays filled from 1 to
locmem_BufferedFragments[header.PayloadIdentifier].MaxFragmentNum, else
return FALSE */
end IsPayloadComplete
Receive State Machine – Version 2:
(More states and simpler guard conditions)
5
1, 2, 3
4
Collect
Wait
6
7, 8
???
Transition No. 1
Event:
Guard:
Comment:
Action:
Timeout
None
Garbage collect fragments of payload whose timer expired
fn (timerID : timerHandle)
{
/* Free fragments in locmem_BufferedFragments whose ‘PayloadIdentifier’ is
‘timerID’ */
}
Transition No. 2
Event:
Guard:
Comment:
Action:
Packet Arrival
locmem_MemUsed >= locmem_MaxBufferLength
No more memory to buffer fragments. Drop the packet
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
DropPacket();
}
Transition No. 3
Event:
Guard:
Comment:
Action:
Packet Arrival
locmem_MemUsed < locmem_MaxBufferLength AND
(pktComponentMemory.FragmentNum == 1 AND
pktComponentMemory.LastFragment == TRUE)
Unfragmented payload, deliver to upper component
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
PktDeliver(pktPayload);
}
Transition No. 4
Event:
Guard:
Comment:
Packet Arrival
locmem_MemUsed < locmem_MaxBufferLength AND
NOT (pktComponentMemory.FragmentNum == 1 AND
pktComponentMemory.LastFragment == TRUE)
Add this fragment to the local buffer
Action:
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
AddToCollection(pktComponentMemory);
}
Transition No. 5
Event:
Guard:
Comment:
timer
Action:
None
PayloadIdentifierNotSeenYet(pktComponentMemory) == TRUE
This is the first received fragment with this ‘PayloadIdentifier’, start a
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
SetTimeout(pktComponentMemory.PayloadIdentifier, locmem_GCTimeout);
}
Transition No. 6
Event:
Guard:
Comment:
Action:
None
PayloadIdentifierNotSeenYet(pktComponentMemory) == FALSE
This is not the first received fragment with this ‘PayloadIdentifier’
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
}
Transition No. 7
Event:
Guard:
Comment:
Action:
None
IsPayloadComplete(pktComponentMemory) == TRUE
All fragments of this payload have been received. Deliver to upper comp.
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
var ReassembledPayload : byte array;
/* Concatenate all elements from the collection
locmem_BufferedFragments[pktComponentMemory.PayloadIdentifier].BufferedFragme
nts into ReassembledPayload */
NewPktDeliver(ReassembledPayload);
CancelTimeout(pktComponentMemory.PayloadIdentifier);
}
Transition No. 8
Event:
Guard:
Comment:
Action:
None
IsPayloadComplete(pktComponentMemory) == FALSE
More fragments are needed to reassemble this payload.
fn (pktComponentMemory: FragHeader, pktPayload : byte[], pktLowerMemory : byte[])
{
}
Initialization Function:
procedure init ( PayloadIdentifierKey: int, MaxFragmentLength: int,
MaxBufferLength: int, Timeout: int )
// Initial value of locmem_NextPayloadIdentifier is derived from
PayloadIdentifierKey;
locmem_MaxFragmentLength <- MaxFragmentLength;
locmem_MaxBufferLength <- MaxBufferLength;
locmem_GCTimeout <- Timeout;
end init;
Pseudo Code:
procedure transmit( )
var NumberOfFragments : int;
var CurrentSentFragmentNum : int;
var FragmentData : byte array;
NumberOfFragments <- // No. of fragments depending on
UpperPayload.length and locmem_MaxFragmentLength
CurrentSentFragmentNum <- 1;
while (CurrentSentFragmentNum <= NumberOfFragments) do
TxHeader.PayloadIdentifier <- locmem_NextPayloadIdentifier;
TxHeader.LastFragment <( CurrentSentFragmentNum == NumberOfFragments )
TxHeader.FragmentNum <- CurrentSentFragmentNum;
// FragmentData holds currently sent fragment
PktSend(TxHeader, FragmentData, NULL);
Inc( CurrentSentFragmentNum );
done
Inc( locmem_NextPayloadIdentifier );
end transmit
procedure receive()
var ReassembledPayload : byte array;
if ( Memory is still available to buffer the incoming fragment )
if ( This is the first received fragment with this
‘PayloadIdentifier’ )
SetTimeout( RcvdHeader.PayloadIdentifier, locmem_GCTimeout)
fi
// Insert UpperPayload into
locmem_BufferedFragments[RcvdHeader.PayloadIdentifier].
BufferedFragments[RcvdHeader.FragmentNum]
if ( RcvdHeader.LastFragment == TRUE )
locmem_BufferedFragments[RcvdHeader.PayloadIdentifier].
MaxFragmentNum <- RcvdHeader.FragmentNum
fi
if ( All fragments of this ‘PayloadIdentifier’ are received )
// Reassemble all fragments into ReassembledPayload
NewPktDeliver(ReassembledPayload);
CancelTimeout( RcvdHeader.PayloadIdentifier );
// Free memory used by fragments with this ‘PayloadIdentifier’
fi
else
// Drop incoming fragment
fi
end receive
procedure timeout( var TimerID: int )
// TimerID passed to this procedure is the ‘PayloadIdentifier’, whose
fragments are to be garbage collected.
// Free all memory used by all buffered fragments with this
‘PayloadIdentifier’
end timeout
Implications of hop-by-hop re-assembly:
The individual fragments do not make any sense even to the component that is
immediately “above” the FR component (whose data was fragmented). So when a
fragment is received by the FR component, it does not help to deliver the individual
fragment to the “upper” layer. (without reassembly) If only end-to-end reassembly is
supported, then the above restriction implies that a component like ‘Routing’ (that turns
packets around) cannot be placed above the FR component in a stack in a network node.
If the routing component is placed below the FR component, then the FR component will
never be reached by most packets. So hop-by-hop reassembly is supported.
Download