Commit 946588e5 authored by kfox's avatar kfox

Renamed 1990 fragmenter to BEFS (Begin End Fragmentation Scheme - DRAFT)

parent cd071261
......@@ -63,8 +63,8 @@ set(LIBATHENA_ETH_SOURCE_FILES
athena_TransportLinkModuleETH.c
)
set(LIBATHENA_ETHFRAGMENT_1990_SOURCE_FILES
athena_TransportLinkModuleETHFragmenter_1990.c
set(LIBATHENA_ETHFRAGMENT_BEFS_SOURCE_FILES
athena_TransportLinkModuleETHFragmenter_BEFS.c
)
set(LIBATHENA_TEMPLATE_SOURCE_FILES
......@@ -92,7 +92,7 @@ source_group(Sources FILES ${ATHENA_SOURCE_FILES})
source_group(Sources FILES ${LIBATHENA_TCP_SOURCE_FILES})
source_group(Sources FILES ${LIBATHENA_UDP_SOURCE_FILES})
source_group(Sources FILES ${LIBATHENA_ETH_SOURCE_FILES})
source_group(Sources FILES ${LIBATHENA_ETHFRAGMENT_1990_SOURCE_FILES})
source_group(Sources FILES ${LIBATHENA_ETHFRAGMENT_BEFS_SOURCE_FILES})
source_group(Sources FILES ${LIBATHENA_TEMPLATE_SOURCE_FILES})
add_library(athena_ETH.shared SHARED ${LIBATHENA_ETH_SOURCE_FILES})
......@@ -102,12 +102,12 @@ set_target_properties(athena_ETH.shared PROPERTIES
VERSION 1.0
OUTPUT_NAME athena_ETH )
add_library(athena_ETHFragment_1990.shared SHARED ${LIBATHENA_ETHFRAGMENT_1990_SOURCE_FILES})
set_target_properties(athena_ETHFragment_1990.shared PROPERTIES
add_library(athena_ETHFragmenter_BEFS.shared SHARED ${LIBATHENA_ETHFRAGMENT_BEFS_SOURCE_FILES})
set_target_properties(athena_ETHFragmenter_BEFS.shared PROPERTIES
C_STANDARD 99
SOVERSION 1
VERSION 1.0
OUTPUT_NAME athena_ETHFragment_1990 )
OUTPUT_NAME athena_ETHFragmenter_BEFS )
add_library(athena_TEMPLATE.shared SHARED ${LIBATHENA_TEMPLATE_SOURCE_FILES})
set_target_properties(athena_TEMPLATE.shared PROPERTIES
......@@ -121,7 +121,7 @@ set(athena_libraries
athena_TCP.shared
athena_UDP.shared
athena_ETH.shared
athena_ETHFragment_1990.shared
athena_ETHFragmenter_BEFS.shared
athena_TEMPLATE.shared
)
......
......@@ -28,6 +28,13 @@
* @author Kevin Fox, Palo Alto Research Center (Xerox PARC)
* @copyright 2016, Xerox Corporation (Xerox)and Palo Alto Research Center (PARC). All rights reserved.
*/
/*
* Provide support for loadable ethernet fragmentation modules. The fragmenter library is named
* libathena_ETHFragmenter_<name>, and must contain an initialization routine that is named
* athenaEthernetFrabmenter_<name>_Init, which is provided an allocated AthenaEthernetFragmenter instance
* that is used to maintain private instance state for the fragmentation module.
*/
#include <config.h>
#include <LongBow/runtime.h>
......
......@@ -34,38 +34,144 @@
#include <parc/algol/parc_Deque.h>
#include <ccnx/forwarder/athena/athena_Ethernet.h>
/**
* @typedef AthenaEthernetFragmenter
* @brief Ethernet fragmenter instance private data
*/
typedef struct AthenaEthernetFragmenter AthenaEthernetFragmenter;
/**
* @typedef AthenaEthernetFragmenter_Send
* @brief Ethernet fragmenter send method
*/
typedef int (AthenaEthernetFragmenter_Send)(AthenaEthernetFragmenter *athenaEthernetFragmenter,
AthenaEthernet *athenaEthernet,
size_t mtu, struct ether_header *etherHeader,
CCNxMetaMessage *ccnxMetaMessage);
/**
* @typedef AthenaEthernetFragmenter_Receive
* @brief Ethernet fragmenter receive method
*/
typedef PARCBuffer *(AthenaEthernetFragmenter_Receive)(AthenaEthernetFragmenter *athenaEthernetFragmenter,
PARCBuffer *wireFormatBuffer);
/**
* @typedef AthenaEthernetFragmenter_Init
* @brief Ethernet fragmenter initialization method
*/
typedef AthenaEthernetFragmenter *(AthenaEthernetFragmenter_Init)(AthenaEthernetFragmenter *athenaEthernetFragmenter);
/**
* @typedef AthenaEthernetFragmenter_Init
* @brief Ethernet fragmenter initialization method
*/
typedef void (AthenaEthernetFragmenter_Fini)(AthenaEthernetFragmenter *athenaEthernetFragmenter);
//
// Private data for each fragmented connection
//
struct AthenaEthernetFragmenter {
void *module;
uint32_t sendSequenceNumber;
uint32_t receiveSequenceNumber;
PARCDeque *fragments;
void *module; // so library can be unloaded
//uint32_t sendSequenceNumber;
//uint32_t receiveSequenceNumber;
//PARCDeque *fragments;
AthenaEthernetFragmenter_Send *send;
AthenaEthernetFragmenter_Receive *receive;
AthenaEthernetFragmenter_Fini *fini;
void *fragmenterData;
};
typedef AthenaEthernetFragmenter *(AthenaEthernetFragmenter_Init)();
/**
* @abstract create a new fragmenter instance
* @discussion
*
* @param [in] name of new fragmenter
* @return pointer to new instance
*
* Example:
* @code
* void
* {
* AthenaEthernetFragmenter *athenaEthernetFragmenter = athenaEthernetFragmenter_Create("BEFS");
* }
* @endcode
*/
AthenaEthernetFragmenter *athenaEthernetFragmenter_Create(const char *fragmenterName);
AthenaEthernetFragmenter *athenaEthernetFragmenter_Acquire(const AthenaEthernetFragmenter *);
/**
* @abstract obtain a new reference to a fragmenter instance
* @discussion
*
* @param [in] athenaEthernetFragmenter instance to acquire a reference to
* @return pointer to new reference
*
* Example:
* @code
* void
* {
* AthenaEthernetFragmenter *newReference = athenaEthernetFragmenter_Acquire(athenaEthernetFragmenter);
* }
* @endcode
*/
AthenaEthernetFragmenter *athenaEthernetFragmenter_Acquire(const AthenaEthernetFragmenter *athenaEthernetFragmenter);
/**
* @abstract release a fragmenter reference
* @discussion
*
* @param [in] athenaEthernetFragmenter instance to release
*
* Example:
* @code
* void
* {
* athenaEthernetFragmenter_Release(&athenaEthernetFragmenter);
* }
* @endcode
*/
void athenaEthernetFragmenter_Release(AthenaEthernetFragmenter **);
/**
* @abstract send a message fragmenting it by the provided mtu size
* @discussion
*
* @param [in] athenaEthernetFragmenter
* @param [in] athenaEthernet
* @param [in] mtu
* @param [in] header
* @param [in] ccnxMetaMessage
* @return 0 on success, -1 on failure with errno set to indicate failure
*
* Example:
* @code
* void
* {
* int result = athenaEthernetFragmenter_Send(athenaEthernetFragmenter, athenaEthernet, mtu, header, ccnxMetaMessage);
* }
* @endcode
*/
int athenaEthernetFragmenter_Send(AthenaEthernetFragmenter *athenaEthernetFragmenter,
AthenaEthernet *athenaEthernet, size_t mtu,
struct ether_header *header, CCNxMetaMessage *ccnxMetaMessage);
/**
* @abstract construct a message from received fragments
* @discussion
*
* @param [in] athenaEthernetFragmenter
* @param [in] wireFormatBuffer
* @return pointer to reassembled message,
* NULL if waiting for more fragments,
* or original inputWireFormatBuffer if it was not recognized as a fragment.
*
* Example:
* @code
* void
* {
* PARCBuffer *wireFormatBuffer = athenaEthernetFragmenter_Receive(athenaEthernetFragmenter, inputWireFormatBuffer);
* }
* @endcode
*/
PARCBuffer *athenaEthernetFragmenter_Receive(AthenaEthernetFragmenter *athenaEthernetFragmenter,
PARCBuffer *wireFormatBuffer);
......
......@@ -204,8 +204,8 @@ _ETHSend(AthenaTransportLink *athenaTransportLink, CCNxMetaMessage *ccnxMetaMess
// If we we're setup to fragment, and the message would exceed our MTU size,
// fragment it and send the messages out.
if ((ccnxCodecNetworkBufferIoVec_Length(iovec) + sizeof(struct ether_header)) > linkData->link.mtu) {
ccnxCodecNetworkBufferIoVec_Release(&iovec);
if (linkData->fragmenter) {
ccnxCodecNetworkBufferIoVec_Release(&iovec);
return athenaEthernetFragmenter_Send(linkData->fragmenter,
linkData->athenaEthernet,
linkData->link.mtu, &header,
......
......@@ -61,6 +61,12 @@
#define METIS_PACKET_TYPE_HOPFRAG 4
#define T_HOPFRAG_PAYLOAD 0x0005
typedef struct _BEFS_private {
uint32_t sendSequenceNumber;
uint32_t receiveSequenceNumber;
PARCDeque *fragments;
} _BEFS_private;
typedef struct hopbyhop_header {
uint8_t version;
uint8_t packetType;
......@@ -91,8 +97,14 @@ typedef struct hopbyhop_header {
*/
#define _hopByHopHeader_SetEFlag(header) ((header)->blob[0] |= EMASK)
_BEFS_private *
_ETH_BEFS_GetFragmenterData(AthenaEthernetFragmenter *athenaEthernetFragmenter)
{
return (_BEFS_private*)athenaEthernetFragmenter->fragmenterData;
}
bool
_ETH1990_IsFragment(PARCBuffer *wireFormatBuffer)
_ETH_BEFS_IsFragment(PARCBuffer *wireFormatBuffer)
{
bool result = false;
_HopByHopHeader *header = parcBuffer_Overlay(wireFormatBuffer, 0);
......@@ -143,68 +155,70 @@ _hopByHopHeader_SetSequenceNumber(_HopByHopHeader *header, uint32_t seqnum)
#define _hopByHopHeader_GetEFlag(header) ((header)->blob[0] & EMASK)
PARCBuffer *
_ETH1990_ReceiveAndReassemble(AthenaEthernetFragmenter *athenaEthernetFragmenter, PARCBuffer *wireFormatBuffer)
_ETH_BEFS_ReceiveAndReassemble(AthenaEthernetFragmenter *athenaEthernetFragmenter, PARCBuffer *wireFormatBuffer)
{
_BEFS_private *fragmenterData = _ETH_BEFS_GetFragmenterData(athenaEthernetFragmenter);
assertTrue(wireFormatBuffer != NULL, "Fragmenter reassembly called with a null buffer");
// If it's not our fragment, send it back
if (!_ETH1990_IsFragment(wireFormatBuffer)) {
if (!_ETH_BEFS_IsFragment(wireFormatBuffer)) {
return wireFormatBuffer;
}
// Verify the type, and move the buffer beyond the header.
_HopByHopHeader *header = parcBuffer_Overlay(wireFormatBuffer, sizeof(_HopByHopHeader));
assertTrue(header->packetType == METIS_PACKET_TYPE_HOPFRAG, "ETH1990 Unknown fragment type (%d)", header->packetType);
assertTrue(header->packetType == METIS_PACKET_TYPE_HOPFRAG, "ETH_BEFS Unknown fragment type (%d)", header->packetType);
// If it's not a sequence number we were expecting, clean everything out and start over.
uint32_t seqnum = _hopByHopHeader_GetSeqnum(header);
if (seqnum != athenaEthernetFragmenter->receiveSequenceNumber) {
if (seqnum != fragmenterData->receiveSequenceNumber) {
parcBuffer_Release(&wireFormatBuffer);
while (parcDeque_Size(athenaEthernetFragmenter->fragments) > 0) {
wireFormatBuffer = parcDeque_RemoveFirst(athenaEthernetFragmenter->fragments);
while (parcDeque_Size(fragmenterData->fragments) > 0) {
wireFormatBuffer = parcDeque_RemoveFirst(fragmenterData->fragments);
parcBuffer_Release(&wireFormatBuffer);
}
athenaEthernetFragmenter->receiveSequenceNumber = 0;
fragmenterData->receiveSequenceNumber = 0;
return NULL;
}
assertTrue(parcDeque_Size(athenaEthernetFragmenter->fragments) == seqnum, "Queue size, sequence number mis-match");
assertTrue(parcDeque_Size(fragmenterData->fragments) == seqnum, "Queue size, sequence number mis-match");
// Gather buffers until we receive an end frame
parcDeque_Append(athenaEthernetFragmenter->fragments, wireFormatBuffer);
parcDeque_Append(fragmenterData->fragments, wireFormatBuffer);
if (_hopByHopHeader_GetBFlag(header)) {
athenaEthernetFragmenter->receiveSequenceNumber++;
fragmenterData->receiveSequenceNumber++;
}
if (_hopByHopHeader_GetEFlag(header)) {
PARCBuffer *reassembledBuffer = parcBuffer_Allocate(0);
while (parcDeque_Size(athenaEthernetFragmenter->fragments) > 0) {
wireFormatBuffer = parcDeque_RemoveFirst(athenaEthernetFragmenter->fragments);
while (parcDeque_Size(fragmenterData->fragments) > 0) {
wireFormatBuffer = parcDeque_RemoveFirst(fragmenterData->fragments);
const uint8_t *array = parcBuffer_Overlay(wireFormatBuffer, 0);
size_t arrayLength = parcBuffer_Remaining(wireFormatBuffer);
parcBuffer_Resize(reassembledBuffer, parcBuffer_Capacity(reassembledBuffer) + arrayLength);
parcBuffer_PutArray(reassembledBuffer, arrayLength, array);
parcBuffer_Release(&wireFormatBuffer);
}
athenaEthernetFragmenter->receiveSequenceNumber = 0;
fragmenterData->receiveSequenceNumber = 0;
return reassembledBuffer;
} else if (!_hopByHopHeader_GetBFlag(header)) {
while (parcDeque_Size(athenaEthernetFragmenter->fragments) > 0) {
wireFormatBuffer = parcDeque_RemoveFirst(athenaEthernetFragmenter->fragments);
while (parcDeque_Size(fragmenterData->fragments) > 0) {
wireFormatBuffer = parcDeque_RemoveFirst(fragmenterData->fragments);
parcBuffer_Release(&wireFormatBuffer);
}
athenaEthernetFragmenter->receiveSequenceNumber = 0;
fragmenterData->receiveSequenceNumber = 0;
}
return NULL;
}
static int
_ETH1990_FragmentAndSend(AthenaEthernetFragmenter *athenaEthernetFragmenter,
_ETH_BEFS_FragmentAndSend(AthenaEthernetFragmenter *athenaEthernetFragmenter,
AthenaEthernet *athenaEthernet,
size_t mtu, struct ether_header *etherHeader,
CCNxMetaMessage *ccnxMetaMessage)
{
_BEFS_private *fragmenterData = _ETH_BEFS_GetFragmenterData(athenaEthernetFragmenter);
_HopByHopHeader fragmentHeader = {0};
const size_t maxPayload = mtu - sizeof(_HopByHopHeader);
_hopByHopHeader_SetBFlag(&fragmentHeader);
......@@ -212,7 +226,7 @@ _ETH1990_FragmentAndSend(AthenaEthernetFragmenter *athenaEthernetFragmenter,
PARCBuffer *wireFormatBuffer = athenaTransportLinkModule_GetMessageBuffer(ccnxMetaMessage);
size_t length = parcBuffer_Remaining(wireFormatBuffer);
size_t offset = 0;
athenaEthernetFragmenter->sendSequenceNumber = 0;
fragmenterData->sendSequenceNumber = 0;
while (offset < length) {
struct iovec iov[3];
......@@ -221,7 +235,7 @@ _ETH1990_FragmentAndSend(AthenaEthernetFragmenter *athenaEthernetFragmenter,
size_t payloadLength = maxPayload;
const size_t remaining = length - offset;
_hopByHopHeader_SetSequenceNumber(&fragmentHeader, athenaEthernetFragmenter->sendSequenceNumber++);
_hopByHopHeader_SetSequenceNumber(&fragmentHeader, fragmenterData->sendSequenceNumber++);
if (remaining < maxPayload) {
payloadLength = remaining;
......@@ -230,12 +244,12 @@ _ETH1990_FragmentAndSend(AthenaEthernetFragmenter *athenaEthernetFragmenter,
_hopByHopHeader_SetPayloadLength(&fragmentHeader, payloadLength);
iov[0].iov_base = &etherHeader;
iov[0].iov_len = sizeof(etherHeader);
iov[1].iov_base = &fragmentHeader;
iov[0].iov_len = sizeof(struct ether_header);
iov[0].iov_base = etherHeader;
iov[1].iov_len = sizeof(_HopByHopHeader);
iov[2].iov_base = parcBuffer_Overlay(wireFormatBuffer, payloadLength);
iov[1].iov_base = &fragmentHeader;
iov[2].iov_len = payloadLength;
iov[2].iov_base = parcBuffer_Overlay(wireFormatBuffer, payloadLength);
ssize_t writeCount = athenaEthernet_Send(athenaEthernet, iov, iovcnt);
......@@ -254,21 +268,25 @@ _ETH1990_FragmentAndSend(AthenaEthernetFragmenter *athenaEthernetFragmenter,
}
static void
_athenaEthernetFragmenter_1990_Fini(AthenaEthernetFragmenter *athenaEthernetFragmenter)
_athenaEthernetFragmenter_BEFS_Fini(AthenaEthernetFragmenter *athenaEthernetFragmenter)
{
while (parcDeque_Size(athenaEthernetFragmenter->fragments) > 0) {
PARCBuffer *wireFormatBuffer = parcDeque_RemoveFirst(athenaEthernetFragmenter->fragments);
_BEFS_private *fragmenterData = _ETH_BEFS_GetFragmenterData(athenaEthernetFragmenter);
while (parcDeque_Size(fragmenterData->fragments) > 0) {
PARCBuffer *wireFormatBuffer = parcDeque_RemoveFirst(fragmenterData->fragments);
parcBuffer_Release(&wireFormatBuffer);
}
parcDeque_Release(&(athenaEthernetFragmenter->fragments));
parcDeque_Release(&(fragmenterData->fragments));
parcMemory_Deallocate(&(fragmenterData));
}
AthenaEthernetFragmenter *
athenaEthernetFragmenter_1990_Init(AthenaEthernetFragmenter *athenaEthernetFragmenter)
athenaEthernetFragmenter_BEFS_Init(AthenaEthernetFragmenter *athenaEthernetFragmenter)
{
athenaEthernetFragmenter->fragments = parcDeque_Create();
athenaEthernetFragmenter->send = (AthenaEthernetFragmenter_Send *)_ETH1990_FragmentAndSend;
athenaEthernetFragmenter->receive = (AthenaEthernetFragmenter_Receive *)_ETH1990_ReceiveAndReassemble;
athenaEthernetFragmenter->fini = (AthenaEthernetFragmenter_Fini *)_athenaEthernetFragmenter_1990_Fini;
athenaEthernetFragmenter->fragmenterData = parcMemory_Allocate(sizeof(_BEFS_private));
_BEFS_private *fragmenterData = _ETH_BEFS_GetFragmenterData(athenaEthernetFragmenter);
fragmenterData->fragments = parcDeque_Create();
athenaEthernetFragmenter->send = (AthenaEthernetFragmenter_Send *)_ETH_BEFS_FragmentAndSend;
athenaEthernetFragmenter->receive = (AthenaEthernetFragmenter_Receive *)_ETH_BEFS_ReceiveAndReassemble;
athenaEthernetFragmenter->fini = (AthenaEthernetFragmenter_Fini *)_athenaEthernetFragmenter_BEFS_Fini;
return athenaEthernetFragmenter;
}
......@@ -351,7 +351,7 @@ LONGBOW_TEST_CASE(Global, athenaTransportLinkModuleETH_SendReceiveFragments)
myAddress.ether_addr_octet[2], myAddress.ether_addr_octet[3],
myAddress.ether_addr_octet[4], myAddress.ether_addr_octet[5]);
sprintf(linkSpecificationURI, "eth://%s/Listener/name=ETHListener/fragmenter=1990", device);
sprintf(linkSpecificationURI, "eth://%s/Listener/name=ETHListener/fragmenter=BEFS", device);
connectionURI = parcURI_Parse(linkSpecificationURI);
result = athenaTransportLinkAdapter_Open(athenaTransportLinkAdapter, connectionURI);
......@@ -365,7 +365,7 @@ LONGBOW_TEST_CASE(Global, athenaTransportLinkModuleETH_SendReceiveFragments)
parcURI_Release(&connectionURI);
// Open a link we can send messages on
sprintf(linkSpecificationURI, "eth1990://%s/name=ETH_1/fragmenter=1990", device);
sprintf(linkSpecificationURI, "eth://%s/name=ETH_1/fragmenter=BEFS", device);
connectionURI = parcURI_Parse(linkSpecificationURI);
result = athenaTransportLinkAdapter_Open(athenaTransportLinkAdapter, connectionURI);
assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment