How to use DriverKit for transmission of network data packets?

As I understand, for Network packet transmission, IOKit use the following methods:

1. IOOutputQueue calls the outputPacket() method of network driver to send packets to the device.

2. IOGateOutputQueue dequeue packets on network driver's workloop (send packets to the network driver).


And now, how does it implement using the DriverKit/NetworkingDriverKit framework?

I have seen Networking has 4 packet queues:

IOUserNetworkingRxSubmissionQueue,

IOUserNetworkingRxCompletionQueue,

IOUserNetworkingTxSubmissionQueue,

IOUserNetworkingTxCompletionQueue;

How to use them with IODispatchQueue? or IODataQueueDispatchSource?

Hi, vanillan


I have the same question about it.

Did you find the way How to use DriverKit for transmission of network data packets?


And In my code, when create IOUserNetworkRxSubmissionQueue with following code, alway occured the assertion failed.


IOUserNetworkRxSubmissionQueue::Create(ivars->networkBufferPool, this, 10, 0, ivars->defaultQueue, &ivars->rxSubmissionQueue);

ivars->networkBufferPool : Created IOUserNetworkPacketBufferPool

ivars->defaultQueue : getting default Dispatch Queue(IODispatchQueue)


Any advice is appreciated.

Here is the logging from my code. It is successful in getting the interface registered. But so far I have not been able to push any data into the Rx queues or getting anything from the Tx queues.

Code Block
[result = IOUserNetworkPacketBufferPool::Create(this, "usb_net_pool", 64, 64, 2048, &ivars->pool)] kIOReturnSuccess
[result = IODispatchQueue::Create("usb_tx_net_dq", 0, 0, &ivars->txSubmissionDispatchQueue)] kIOReturnSuccess
[result = IOUserNetworkTxSubmissionQueue::Create(ivars->pool, this, 16, 0, ivars->txSubmissionDispatchQueue, &ivars->txSubmissionQueue)] kIOReturnSuccess
[result = OSObject::SetDispatchQueue("tx_net_dq", ivars->txSubmissionDispatchQueue)] kIOReturnSuccess
[result = CreateActionTxAvailable(sizeof(void *), &ivars->txSubmitAction)] kIOReturnSuccess
[result = ivars->txSubmissionQueue->CopyDataQueue(&ivars->txDataQueueDispatchSource)] kIOReturnSuccess
[result = ivars->txDataQueueDispatchSource->SetDataAvailableHandler(ivars->txSubmitAction)] kIOReturnSuccess
[result = IODispatchQueue::Create("usb_tx_pipe_dq", 0, 0, &ivars->txCompleteDispatchQueue)] kIOReturnSuccess
[result = IOUserNetworkTxCompletionQueue::Create(ivars->pool, this, 16, 0, ivars->txCompleteDispatchQueue, &ivars->txCompletionQueue)] kIOReturnSuccess
[result = OSObject::SetDispatchQueue("tx_pipe_dq", ivars->txCompleteDispatchQueue)] kIOReturnSuccess
[result = CreateActionTxComplete(sizeof(void *), &ivars->txCompleteAction)] kIOReturnSuccess
[result = IOUserNetworkRxSubmissionQueue::Create(ivars->pool, this, 0x400, 0, 0, &ivars->rxSubmissionQueue)] kIOReturnSuccess
[result = IODispatchQueue::Create("usb_rx_pipe_dq", 0, 0, &ivars->rxCompleteDispatchQueue)] kIOReturnSuccess
[result = IOUserNetworkRxCompletionQueue::Create(ivars->pool, this, 16, 0, ivars->rxCompleteDispatchQueue, &ivars->rxCompletionQueue)] kIOReturnSuccess
[result = OSObject::SetDispatchQueue("rx_pipe_dq", ivars->rxCompleteDispatchQueue)] kIOReturnSuccess
[result = RegisterEthernetInterface(DataMacAddress, ivars->pool, ivars->queues, 4)] kIOReturnSuccess
[result = ReportAvailableMediaTypes(mediaTypes, 1)] kIOReturnSuccess


I'm also trying to make a network device driver using NetworkingDriverKit. It seems to success a making queues, but I couldn't found any packet transmissions by my driver.

Logs of my driver in initialization as following.

Code Block text
  default 10:29:43.107556+0900  kernel Found class: nictest
  default 10:29:43.109040+0900  kernel init method is called
  default 10:29:43.109380+0900  kernel Hello World at start
  default 10:29:43.114891+0900  kernel net dext: IOUserNetworkPacketBufferPool::Create(this, "pool", packet_count, buffer_count, buffer_size, &pool);
  default 10:29:43.115073+0900  kernel net dext: IOUserNetworkTxSubmissionQueue::Create(pool, this, packet_count, 0, dispatch_queue, &tx_sub_queue);
  default 10:29:43.115077+0900  kernel net dext: sub_queue->CopyDataQueue(&ivars->tx_sub_dsource)
  default 10:29:43.115098+0900  kernel net dext: CreateActionTxSubAvailable(sizeof (void*), &ivars->tx_sub_action);
  default 10:29:43.115107+0900  kernel net dext: ivars->tx_sub_dsource->SetDataAvailableHandler(ivars->tx_sub_action);
  default 10:29:43.115112+0900  kernel net dext: ivars->tx_sub_dsource->SetEnable(true);
  default 10:29:43.115119+0900  kernel net dext: tx_sub_queue->SetEnable(true)
  default 10:29:43.115226+0900  kernel net dext: IOUserNetworkTxCompletionQueue::Create(pool, this, packet_count, 0, dispatch_queue, &com_queue);
  default 10:29:43.115230+0900  kernel net dext: tx_com_queue->CopyDataQueue(&ivars->tx_com_dsource);
  default 10:29:43.115247+0900  kernel net dext: CreateActionTxComDataServiced(sizeof (void*), &ivars->tx_com_action);
  default 10:29:43.115251+0900  kernel net dext: ivars->tx_com_dsource->SetDataAvailableHandler(ivars->tx_com_action);
  default 10:29:43.115253+0900  kernel net dext: ivars->tx_com_dsource->SetEnable(true);
  default 10:29:43.115257+0900  kernel net dext: tx_com_queue->SetEnable(true);
  default 10:29:43.115381+0900  kernel net dext: IOUserNetworkRxSubmissionQueue::Create(pool, this, packet_count, 0, dispatch_queue, &rx_sub_queue);
  default 10:29:43.115385+0900  kernel net dext: rx_sub_queue->CopyDataQueue(&ivars->rx_sub_dsource);
  default 10:29:43.115401+0900  kernel net dext: CreateActionRxSubAvailable(sizeof (void*), &ivars->rx_sub_action);
  default 10:29:43.115406+0900  kernel net dext: ivars->rx_sub_dsource->SetDataAvailableHandler(ivars->rx_sub_action);
  default 10:29:43.115408+0900  kernel net dext: ivars->rx_sub_dsource->SetEnable(true);
  default 10:29:43.115416+0900  kernel net dext: rx_sub_queue->SetEnable(true);
  default 10:29:43.115709+0900  kernel net dext: IOUserNetworkRxCompletionQueue::Create(pool, this, packet_count, 0, dispatch_queue, &rx_com_queue);
  default 10:29:43.115712+0900  kernel net dext: com_queue->CopyDataQueue(&ivars->rx_sub_dsource);
  default 10:29:43.115729+0900  kernel net dext: CreateActionRxComDataServiced(sizeof (void*), &ivars->rx_com_action);
  default 10:29:43.115739+0900  kernel net dext: ivars->rx_sub_dsource->SetDataServicedHandler(ivars->rx_com_action);
  default 10:29:43.115741+0900  kernel net dext: ivars->rx_sub_dsource->SetEnable(true);
  default 10:29:43.115746+0900  kernel net dext: rx_com_queue->SetEnable(true);
  default 10:29:43.115776+0900  kernel net dext: const IOUserNetworkMediaType types[] = {    kIOUserNetworkMediaEthernetAuto,    kIOUserNetworkMediaEthernetNone,    kIOUserNetworkMediaEthernet1000BaseT | kIOUserNetworkMediaOptionFullDuplex  };
  default 10:29:43.115778+0900  kernel net dext: ret = ReportAvailableMediaTypes(types, 3);
  default 10:29:43.115806+0900  kernel net dext: ReportLinkStatus(kIOUserNetworkLinkStatusInactive, kIOUserNetworkMediaEthernetNone);
  default 10:29:43.115832+0900  kernel net dext: RegisterEthernetInterface(macAddress, pool, ivars->queues, 4);
  default 10:29:43.142245+0900  kernel net dext: GetMaxTransferUnit methos is called
  default 10:29:43.143402+0900  kernel net dext: SetInterfaceEnable method is called [isEnable == true]
  default 10:29:43.143810+0900  kernel net dext: SetInterfaceEnable method is called [isEnable == false]


I'm not sure why this driver is disabled after enabled. Do you have any solution for it?

Thank you.

Is your log showing the result from SetInterfaceEnable(true), which is being called twice?

I am getting true returned twice if I do that.

One difference is that I am doing ReportLinkStatus(kIOUserNetworkLinkStatusActive,..) after the RegisterEthernetInterface() call and RegisterService() call. And then SetInterfaceEnable().

Is your GetMaxTransferUnit() succeeding? I get kioReturnUnsupported for that and SetMTU().

I have yet to see any sign of packets arriving from the network layer on the TxSubmissionQueue.

I can get an empty packet from the RxSubmissionQueue, but only using the DequeuePackets() function, DequeuePacket() always fails. Also the DequeuePackets() function fails the first time but later (second received transfer) it succeeds, and continues to work after than.


My mistake, I thought SetInterfaceEnable() returned a boolean.

What I am seeing is kIOReturnUnsupported.
Thank you,  sl149q.

What do you mean the result from SetInterfaceEnable? According to a document (https://developer.apple.com/documentation/networkingdriverkit/iousernetworkethernet), we have to override the SetInterfaceEnable on a custom class that we define, and then the function called by system, I think. Also, GetMaxTransferUnit.

My code for these functions are following.
Code Block cpp
...
kern_return_t
IMPL(nictest, SetInterfaceEnable)
{
  if(isEnable)
  {
    log("SetInterfaceEnable method is called [isEnable == true] : Return kIOReturnSuccess");
  }
  else
  {
    log("SetInterfaceEnable method is called [isEnable == false] : Return kIOReturnSuccess");
  }
  return kIOReturnSuccess;
}
...
kern_return_t
IMPL(nictest, GetMaxTransferUnit)
{
  log("GetMaxTransferUnit method is called : return kIOReturnSuccess");
  *mtu = 1500;
  return kIOReturnSuccess;
}
...


Thanks.
How to use DriverKit for transmission of network data packets?
 
 
Q