Porting a NAL Driver to the NL2
For information on NL2 NIC drivers, see Creating a NIC Driver.
In this section:
- Header and Library Requirements
- Rework the Startup Logic
- Rework the Shutdown Logic
- Use NL2 Function Pointers instead of Direct Function Calls
- Rework the Interrupts Handling
- Rework the Link Status Monitoring Logic
- Rework the Frame Transmission Logic
- Rework the Frame Reception Logic
- Remove Unnecessary Locks
- Replace the RtndIoctl Function
- Replace the RtndRequest function
- Implement Frame Buffer Allocation Functions
Header and Library Requirements
To integrate your driver with the NL2, include the Rtnd.h header file. Do not use Rtnl2Api.h to prevent errors.
If your driver uses only a limited subset of the C standard library (e.g., memset, memcpy, memcmp, strlen, strcmp, strcpy, strncpy, strcat, itoa), you can replace the Microsoft C runtime libraries with the startupDll.lib and RtCruntime.lib libraries.
Additionally, remove the following header files and library from your driver if they were previously referenced:
- Headers: rtNalApi.h, rtnapi.h, winsock2.h, ws2tcpip.h
- Library: RTX64Nal.lib
Rework the Startup Logic
During its startup phase, the NAL loads the NIC drivers and calls the following functions for each enabled NIC:
- RtndInitDriverializeInterface
- RtndConfigure
- RtndUpDown
In contrast, the NL2 calls these functions:
- RtndInitDriver
- RtndManageInterface
- RtndQueryInterfaceCapability
- RtndSetInterface
- RtndStartInterface
- RtndQueryMacAddress
- RtndQueryInterfaceFeature
Rework the Shutdown Logic
During its shutdown phase, the NAL calls this function:
- RtndUpDown
In contrast, the NL2 calls these functions:
Use NL2 Function Pointers instead of Direct Function Calls
NAL NIC drivers link with RTX64Nal.lib and request NAL services by calling the following functions exported by the NAL process:
- RtnEnumPciCards
- RtnGetDeviceName
- RtnSetLinkAddress
- RtnGetMcastCount
- RtnIndicateStatus
- RtnNotifyTransmitQueue
- RtnTransmitCompleteCallback
- RtnNotifyRecvQueue
- RtnSetDataLong
- RtnGetDataLong
- RtnGetPacket
- RtnDecodePacket
- RtnIntializeCriticalLock
- RtnDeleteCriticalLock
- RtnEnterCriticalLock
- RtnLeaveCriticalLock
In contrast, NL2 NIC drivers request NL2 services using the function pointers supplied by the NL2 in the call to RtndInitDriver:
- GetVerbose
- NotifyLinkStatusChange
- NotifyTxInterrupt
- NotifyRxInterrupt
- NotifyEgressTimestamp
- CreateTxBuffers
- DestroyTxBuffers
- CreateRxBuffers
- DestroyRxBuffers
Rework the Interrupts Handling
Interrupts Enabling
NAL NIC drivers are expected to enable the following interrupts at startup and keep them enabled until the NAL shuts down:
- Link Status Change interrupt
- Transmit interrupt
- Receive interrupt
NL2 NIC drivers are expected to enable the following interrupts at startup:
- Link Status Change interrupt
- Egress Timestamp interrupt (if the hardware supports Egress Timestamping)
The NL2 determines whether Transmit and Receive interrupts should be enabled by calling the following functions at runtime:
Interrupts Servicing
In NAL NIC drivers, an IST typically does the following work:
- In case of a Link Status Change interrupt:
- Set an event to wake up the Line Status thread
- In case of a Transmit interrupt:
- Call RtnNotifyTransmitQueue (which wakes up the application’s Transmit Complete thread) or set an event to wake up the driver’s Transmit Complete thread
- In case of a Receive interrupt:
- If the queue is attached to an application, update the count of received frames and call RtnNotifyRecvQueue (which signals the application’s Receive event), otherwise, flush the queue (extract the filled buffers and re-submit them immediately)
Note: NAL NIC drivers ignore Egress Timestamp interrupts.
In NL2 NIC drivers, an IST should typically do the following work:
- In case of a Link Status Change interrupt:
- Call RTND_CALLBACKS.NotifyLinkStatusChange
- In case of a Transmit interrupt:
- Call RTND_CALLBACKS.NotifyTxInterrupt
- In case of a Receive interrupt:
- Call RTND_CALLBACKS.NotifyRxInterrupt
- In case of an Egress Timestamp interrupt:
- Call RTND_CALLBACKS.NotifyEgressTimestamp
Note: NL2 drivers should not access the DMA rings or use a lock in their ISTs.
Rework the Link Status Monitoring Logic
NAL NIC drivers have their Line Status Monitoring thread, which awakes every time a Link Status Change interrupt occurs. The thread performs the following tasks:
- Reads the new link status from the NIC registers
- Reconfigures some of the NIC registers, if required
- Calls RtnIndicateStatus
NL2 NIC drivers don't need to have their Line Status Monitoring thread because the NL2 itself implements the monitoring logic. NL2 NIC drivers only need to provide the RtndQueryLinkStatus function, which should do the following:
- Read the new link status from the NIC registers
- Reconfigure some of the NIC registers, if required
- Return the new link status to the NL2
Rework the Frame Transmission Logic
About Frame Transmission
In the NAL, the general rule is that frame transmission is serviced by a dedicated Transmit Complete thread. Depending on the application’s request, this thread can run within the context of the application process or the context of the driver (i.e. the context of the NAL process). When running in the application context, the Transmit Complete thread calls a callback provided by the application every time a buffer in the queue is consumed. When running in the context of the driver, the Transmit Complete thread simply extracts the consumed buffer and makes it available for future transmission.
In the NL2, frame transmission is always serviced at the initiative of the NL2, which calls RtndExtractTxBuffer.
Attach Transmit Queues
When an application acquires a Transmit Queue and enables the Transmit Complete callback functionality, the NAL calls the following function of the NIC driver:
- RtndAttachToTransmitQueue
This function notifies the driver that Transmit interrupts for this queue should be serviced by the application’s Transmit Complete thread rather than the driver’s Transmit Complete thread.
For NL2 NIC drivers, the equivalent function is RtndAttachTxQueue, which is called from the context of any process that plans to use this queue.
Submit Buffers
When the application provides a buffer containing a frame to transmit, the NAL calls the following functions of the NIC driver:
- RtndTransmit
- RtndTransmitEx
In contrast, the NL2 calls these functions:
Extract Buffers
When a Transmit Queue is acquired by an application that enabled the Transmit Complete Callback functionality, the NAL calls the following function from the application’s Transmit Complete thread to extract the consumed buffers:
- RtndServiceTransmitQueue
In other cases, the NAL driver is responsible for automatically extracting the consumed buffers using its Transmit Complete thread.
In contrast, the extraction of consumed buffers by the NL2 NIC drivers is always done upon request from the NL2 using the following function:
Detach Transmit Queues
When an application releases a Transmit Queue that had the Transmit Complete callback functionality enabled, the NAL calls the following function of the NIC driver:
- RtndDetachTransmitQueue
This function notifies the driver that Transmit interrupts for this queue should now be serviced by the driver’s Transmit Complete thread rather than the application’s Transmit Complete thread.
For NL2 NIC drivers, the equivalent function is RtndDetachTxQueue, which is called from the context of any process that previously called RtndAttachTxQueue.
Rework the Frame Reception Logic
About Frame Reception
In the NAL, frame reception is serviced either by the application that acquired the queue or by the driver’s IST when no application has acquired the queue.
In the NL2, frame reception is always serviced at the initiative of the NL2, which calls RtndExtractRxBuffer.
Start/Stop the Queue
This is an optional feature that doesn’t exist in NAL NIC drivers.
If a NIC supports dynamically starting/stopping a Receive Queue independently of the other Receive Queues, the NL2 NIC driver should implement the following functions:
The NL2 will call these functions to ensure that a Receive Queue is in the same initial state each time a new application acquires it.
Attach Receive Queues
When an application acquires a Receive Queue, the NAL calls the following function of the NIC driver:
- RtndAttachToReceiveQueue
This function notifies the driver that Receive interrupts for this queue need to be serviced by the application rather than the driver’s IST.
For NL2 NIC drivers, the equivalent function is RtndAttachRxQueue, which is called from the context of any process that plans to use this queue.
Extract Buffers
When an application acquires a Receive Queue, the NAL calls the following functions from the application’s process to extract the filled buffers:
- RtndReceive
- RtndReceiveWithCallback
In other cases, the NAL driver is responsible for automatically extracting the filled buffers in the IST and re-submitting them immediately to the queue.
For NL2 NIC drivers, buffer extraction is always done upon request from the NL2 using the following function:
Submit Buffers
NAL NIC drivers automatically re-submit the extracted buffers after they have been processed (either after they have been copied to the application’s buffer by RtndReceive or after they have been supplied to the application through the Receive Callback function).
In contrast, NL2 NIC drivers do not re-submit automatically, they wait for the NL2 to call the following functions:
Detach Receive Queues
When an application releases a Receive Queue, the NAL calls the following function of the NIC driver:
- RtndDetachReceiveQueue
This function notifies the driver that Receive interrupts for this queue should now be serviced by the driver’s IST rather than the application.
For NL2 NIC drivers, the equivalent function is RtndDetachRxQueue, which is called from the context of any process that previously called RtndAttachRxQueue.
Remove Unnecessary Locks
NAL NIC drivers generally need to use their locks for at least the following purposes:
- One lock per Transmit Queue, used by the driver’s Transmit Complete thread and by the following functions to protect concurrent access to the queue registers: RtndAttachToTransmitQueue, RtndDetachTransmitQueue, RtndTransmit, RtndTransmitEx, RtndServiceTransmitQueue.
- One lock per Receive Queue, used by the IST and by the following functions to protect concurrent access to the queue registers: RtndAttachToReceiveQueue, RtndDetachReceiveQueue, RtndReceive, RtndReceiveWithCallback, RtndIoctl.
- One general lock, used by the following function to protect concurrent access to the general NIC registers: RtndIoctl.
The NL2 implements its locks and ensures that specific functions are called from within a single thread only. Therefore, NL2 NIC drivers don't require additional locks.
Replace the RtndIoctl Function
The NAL calls the RtndIoctl function for different purposes as specified by the command code. The table below lists the equivalent functions of the NL2 NIC driver that provide the same services:
RtndIoctl command code | NL2 NIC driver equivalent function |
---|---|
ENIOCPROMISC |
|
ENIOCALL, ENIOCNORMAL |
|
ENIOADDMULTI, ENIODELMULTI |
RtndSetMulticastFilter |
ENIOLINKSTATUS |
|
RTNAL_IOCTL_RX_MONITOR |
There is no equivalent; this functionality doesn’t exist in the NL2. |
RTNAL_IOCTL_TX_MONITOR |
There is no equivalent; this functionality doesn’t exist in the NL2. |
RTNAL_IOCTL_READ_TX_HW_TIMESTAMP |
RtndExtractLastTxTimestamp |
RTNAL_IOCTL_READ_RX_HW_TIMESTAMP |
There is no equivalent; this functionality doesn’t exist in the NL2. |
RTNAL_IOCTL_READ_HW_TIMER |
There is no equivalent; this functionality doesn’t exist in the NL2. |
RTNAL_IOCTL_READ32_REG |
There is no equivalent; this functionality doesn’t exist in the NL2. |
RTNAL_IOCTL_WRITE32_REG |
There is no equivalent; this functionality doesn’t exist in the NL2. |
RTNAL_IOCTL_READ_RX_PACKET_COUNT |
There is no equivalent; this functionality doesn’t exist in the NL2. |
RTNAL_IOCTL_READ_TX_PACKET_COUNT |
There is no equivalent; this functionality doesn’t exist in the NL2. |
RTNAL_IOCTL_USE_RX_NOTIFICATIONS |
There is no equivalent; this functionality doesn’t exist in the NL2. |
RTNAL_IOCTL_SET_RX_POLLING |
There is no equivalent; this functionality doesn’t exist in the NL2. |
RTNAL_IOCTL_CLEAR_RX_POLLING |
There is no equivalent; this functionality doesn’t exist in the NL2. |
RTNAL_IOCTL_GET_RX_ETHERTYPE_FILTER |
|
RTNAL_IOCTL_SET_RX_ETHERTYPE_FILTER, RTNAL_IOCTL_CLEAR_RX_ETHERTYPE_FILTER |
|
RTNAL_IOCTL_SET_RX_MESSAGE_TYPE_TO_TIMESTAMP |
There is no equivalent; this functionality doesn’t exist in the NL2. |
RTNAL_IOCTL_SET_TX_MESSAGE_TYPE_TO_TIMESTAMP |
There is no equivalent; this functionality doesn’t exist in the NL2. |
RTNAL_IOCTL_GET_SYSTEM_TIMER |
RtndGetClockTime |
RTNAL_IOCTL_SET_INTERRUPT_MODERATION |
|
RTNAL_IOCTL_GET_PCI_BUS_LOCATION |
There is no equivalent; this functionality doesn’t exist in the NL2. |
Replace the RtndRequest function
The NAL calls the RtndRequest function for different purposes as specified by the OID. The table below lists the equivalent functions of the NL2 NIC driver that provide the same services:
RtndRequest OID | NL2 NIC driver equivalent function |
---|---|
RTND_OID_GEN_MAC_ADDRESS |
|
RTND_OID_GEN_MEDIA_CONNECT_STATUS, RTND_OID_GEN_MEDIA_DUPLEX_STATE, RTND_OID_GEN_LINK_SPEED |
|
All other OIDs |
There is no equivalent; these functionalities don’t exist in the NL2. |
Implement Frame Buffer Allocation Functions
The following functions are specific to the NL2 and need to be implemented only in NL2 NIC drivers. They allow the NL2 to allocate or release a batch of buffers used to hold Ethernet frames for a specific Transmit or Receive Queue. These functions are necessary because each NIC may have special requirements for allocating frame buffers, making it the driver's responsibility to handle these allocations.
The functions to implement are as follows: