The INtime Multiprocess High-Performance Ethernet ("MHPE") interface extends the HPE API to allow multiple processes to share elements of the same Ethernet interface. A limitation of the HPE API is that it requires a single application to own the entire Ethernet interface and all of the resources that the Ethernet interface provides.
The MHPE architecture provides a single process which owns and manages one of more interfacEthernet devices but the API allows that process to divide the Ethernet deice into a number of separate resources which may be accessed and managed by different processes. For example, an Ethernet interface which provides multiple transmit and receive queues may now have those queues assigned to different applications and separate the traffic to and from those applications by using those queue resources.
<< add architecture diagram here >>
The same degree of control is provided by the new interface as with the HPE interface but with the additional flexibility of being able to partition the resources of the given controller between different applications.
A MHPE master process is provided which owns any Ethernet device assigned to it and directly manages any interrupts and register resources provided by that interface. However the MHPE API allows different processes to access separate resources of that device either exclusively, or in some cases sharing a resource between multiple processes.
Examples of resources provided by an Ethernet device may include the following:
A resource such as a transmit queue may be used by multiple processes to transmit packets, but a receive queue may be dedicated to a single process for its exclusive use. A timer may be read by multiple processes but one process may have exclusive access for modifying the timer.
Each resource provided by a device interface is called an endpoint. Interfaces have the same naming scheme as with HPE. Endpoints have names with consist of the interface name with a suffix to denote the endpoint for that interface.
A sample application "MHPE sample" is included with the product. It illustrates various possible operations with the MHPE API.
This lists common operations related to MHPE and the INtime calls that do the operations.
To . . . | Use this system call . . . |
---|---|
A title | |
MHPE master process calls | |
Find the location of a MHPE master process | mhpeFindMaster |
Attach to an MHPE master process | mhpeAttachMaster |
Detach from MHPE master process | mhpeDetachMaster |
Interface calls | |
Create an interface on a node | mhpeCreateInterface |
Enumerate existing interfaces on a node | mhpeEnumInterfaces |
Open an existing interface | mhpeOpenInterface |
Delete an interface | mhpeDeleteInterface |
Create an interface with options | mhpeCreateInterfaceWithOptions |
Close an interface | mhpeCloseInterface |
Configure options for an interface | mhpeConfigOptions |
Get interface information | mhpeGetInterfaceInfo |
Get interface current media status | mhpeGetMediaStatus |
Get interface MAC address | mhpeGetMacAddress |
Enable or disable receipt of all packets (promiscuous mode) at interface | mhpeSetPromiscuousMode |
Obtain a list of queue features supported by the hardware interface | mhpeGetQueueConfiguration |
Endpoint calls | |
Enumerate endpoints of an interface | mhpeEnumEndpoints |
Open an endpoint by type and index | mhpeOpenEndpoint |
Open an endpoint by name | mhpeOpenEndpointByName |
Close an endpoint | mhpeCloseEndpoint |
Get statistics for a transmit or receive endpoint | mhpeGetEndpointStats |
Transmit endpoint calls | |
Attach a set of transmit buffers to a transmit endpoint | mhpeAttachTransmitBufferSet |
Return the current state of the transmitter at endpoint | mhpeGetTransmitterState |
Sleep until the next transmit interrupt occurs for endpoint | mhpeWaitForTransmitComplete |
Set the type of transmit queue for endpoint | mhpeSetTransmitAttributes |
Start the transmitter at endpoint | mhpeStartTransmitter |
Set the transmit priority for the endpoint | mhpeSetTransmitPriority |
Set the global offset to be added to the launch time for the endpoint | mhpeSetTransmitTimeOffset |
Set the time to subtract from the launch time to be begin packet fetch on endpoint | mhpeSetTransmitFetchDelta |
Receive endpoint calls | |
Allocate a receive buffer set which is compatible with the network device | mhpeAllocateReceiveBufferSet |
Free a previously-allocated receive buffer set | mhpeFreeReceiveBufferSet |
Attach a receive buffer set to a receive endpoint | mhpeAttachReceiveBufferSet |
Sleep until the next receive interrupt occurs for the endpoint | mhpeWaitForReceiveComplete |
Return a pointer to the next receive buffer at the endpoint which has a fully-received frame in it | mhpeGetReceiveBuffer |
Returns the receive buffer obtained by mhpeGetReceiveBuffer to the endpoint | mhpeReturnReceiveBuffer |
Set the type of the receive endpoint | mhpeSetReceiveAttributes |
Set the receive endpoint to receive all packets not matched by a filter | mhpeSetDefaultReceiveEndpoint |
Enable a receive endpoint filter by settings its parameters | mhpeSetReceiveFilter |
Get receive filter | mhpeGetReceiveFilter |
1588 timer calls | |
Read the 1588 time from the timer endpoint | mhpe1588GetSystemTime |
Set the 1588 time at the timer endpoint | mhpe1588SetSystemTime |
Adjust the 1588 time at the time endpoint | mhpe1588AdjustSystemTime |
Set the byte offset at which the 1588 timestamp is written in the transmit packets | mhpe1588SetTimestampOffset |
Get the transmit timestamp for the most recently transmitted packet | mhpe1588GetTxTimestamp |
Get the receive timestamp from the receive packet buffer | mhpe1588GetRxTimestamp |
Retrieve the size of the timestamp header | mhpe1588GetRxTimestampHeaderSize |
Get the current a588 system time adjustment | mhpe1588GetSystemTimeAdjustment |
Get the current 1588 system time increment | mhpe1588GetSystemTimeIncrement |
Get the 1588 system time increment | mhpe1588SetSystemTimeIncrement |
Signal a semaphore when a target time is reached | mhpeSetTargetTimer |
Set the parameters to driver a GPIO ping from the 1588 system timer | mhpeSetClockGeneratorPin |
1588 timer arithmetic helper calls | |
Add two 1588 time values | mhpe1588TimeAdd |
Subtract a 1588 time value from another | mhpe1588TimeSubtract |
Compare two 1588 time values | mhpe1588TimeCompare |
Return the difference between two 1588 time values | mhpe1588TimeDifference |
To . . . | Use this structure . . . |
---|---|
Specify options; used by mhpeConfigOptions | HPE_CONFIG_OPTIONS |
Specify options; used by mhpeCreateInterfaceWithOptions | HPE_OPEN_OPTIONS |
Describe a queue configuration | HPE_QUEUE_CONFIG |
Describe an individual buffer to hold frame data | MHPEBUFFER |
Obtain information about the currently-connected media | HPEMEDIASTATUS |
Describe a set of receive frame buffers | MHPERXBUFFERSET |
Describe a single transmit buffer | MHPETXBUFFER |
Describe a transmit buffer set, consisting of multiple transmit buffers | MHPETXBUFFERSET |
Describe a single transmit stream buffer | HPETXSTREAMBUFFER |
Describe a transmit stream buffer set, consisting of multiple transmit stream buffers | HPETXSTREAMBUFFERSET |
Describe a IEEE1588 timestamp | HPE_1588_TIMESTAMP |
Define an Ether type filter | HPE_ETHER_FILTER |
Define a Flex Data filter | HPE_FLEX_FILTER |
Define a 2-Tuple filter | HPE_2TUPLE_FILTER |
This section contains code snippets illustrating some possible operations using this API. Refer to the sample application and specific calls for additional information.
An MHPE application may communicate with any MHPE manager ("master process") on any node on the local host. If the location of a MHPE manager is not known they may be enumerated:
HPE initialization |
Copy Code |
---|---|
LOCATION loc; NODE_INFO ni; // find and print details of all discovered management processes loc = mhpeFindMaster(0); while (loc != BAD_LOCATION) { if (GetRtNodeInfo(loc, &ni)) { printf("loc %u: %s (%s)\n", loc, ni.szNodeName, ni.NetIdType == NETID_TYPE_NONE ? "local" : "remote"); } loc = mhpeFindMaster(loc); } |
Having obtained a location for the management process, attach to the process and create or open an interface:
HPE initialization |
Copy Code |
---|---|
HPESTATUS st; MHPEHANDLE if_handle = BAD_RTHANDLE; LOCATION node_loc = THIS_LOCATION; const char *if_name = "ie1g0"; // attach to the management process at the given location st = mhpeAttachMaster(node_loc); if (st != E_OK) { fprintf(stderr, "Failed to attach to master at location %u\n", node_loc); } else { // attempt to open an interface st = mhpeOpenInterface(node_loc, if_name, &if_handle); if (st != E_OK) { // if the interface does not already exist, we may attempt to create st = mhpeCreateInterfaceWithOptions(node_loc, if_name, opts, sizeof(*opts), &if_handle); } } |
HPE initialization |
Copy Code |
---|---|
MHPESTATUS st; HPE_INTERFACE_ENDPOINTS mhpe_endp; char epname[64]; DWORD index; // Get endpoint information from the interface (count of each endpoint type) // h is the handle of an open interface st = mhpeGetInterfaceInfo(h, MHPE_INFO_INTERFACE_ENDPOINTS, (LPVOID)&mhpe_endp, sizeof(mhpe_endp)); if (st != E_OK) { mhpeCloseInterface(h); printf("mhpeGetInterfaceInfo(HPE_INFO_INTERFACE_ENDPOINTS) failed with status %04x\n", st); return 1; } printf("\t%u Endpoints: %u tx, %u rx, %u timer\n", mhpe_endp.n_endpoints, mhpe_endp.n_tx_queues, mhpe_endp.n_rx_queues, mhpe_endp.n_1588timers); // Enumerate all endpoint names for (index = 0; ; index++) { if (0 != mhpeEnumEndpoints(h, index, epname, sizeof(epname))) break; printf("Endpoint %u: %s\n", index, epname); } |
HPE initialization |
Copy Code |
---|---|
HPE initialization |
Copy Code |
---|---|
MHPESTATUS st; MHPEHANDLE tx_ep; DWORD channel = 1; // use endpoint index 1 // h is the handle of an open interface st = mhpeOpenEndpoint(h, MHPE_EP_TX_QUEUE, channel, EP_ACC_WRITE_SHARE, &tx_ep); if (st != E_OK) { printf("Failed to open Tx endpoint %u on %s\n", channel, h); return; } // Optionally call mhpeSetTransmitAttributes to change the transmit queue properties. // For example, enable transmit timestamps: st = mhpeSetTransmitAttributes(tx_ep, HPE_TX_TIMESTAMP_2STEP); if (st != E_OK) { printf("Failed to set TX timestamps\n"); } else { printf("Enabled TX timestmaps\n"); } |
Once the interface is set up, load the data, attach the transmit set and start the transmitter.
Transmit a frame |
Copy Code |
---|---|
// user function to initialize the frames to be transmitted FillTransmitPayload(tx_buffers[0].fragments[1].ptr); mhpeAttachTransmitBufferSet(tx_ep, tx_buffers); st = hpeStartTransmitter(tx_ep); // Wait for transmission to complete // 'interrupts' contains the interrupt mode that the interface was opened with if (interrupts & OUTPUT_INTERRUPT) { for (j = 0; j < (int)txs->buffer_count; j++) { if ((st = mhpeWaitForTransmitComplete(tx_ep, 1000000)) != E_OK) { printf("TX: hpeWaitForTransmitComplete failed: %04x\n", st); goto close; } } } else { // wait for transmit to complete while (mhpeGetTransmitterState(tx_ep, &txstate) == E_OK && txstate == HPE_TXBUSY) RtSleepEx(1); } |
First check to see if a buffer is available then process the data in it. Once the buffer has been received the buffer may be reused.
Receive frames |
Copy Code |
---|---|
// user function to initialize the frames to be transmitted MHPEBUFFER *rxbuffer; mhpeWaitForReceiveComplete(rx_ep, 1000000); if (mhpeGetReceiveBuffer(handle, &rxbuffer) == E_OK) process_buffer_data(rxbuffer->ptr, rxbuffer->used); // user function |