Jason Thorpe
2020-01-20 22:48:31 UTC
Folks --
The legacy (*if_watchdog)() interface has a couple of problems:
1- It does not have any way to represent multiple hardware-managed transmit queues.
2- It's not easy to make MP-safe because it relies on modifying the ifnet structure periodically outside of the normal locking mechanisms.
The wm(4) driver solved the problem in a reasonable way, and to make it easier for the other drivers in the tree to adopt it's strategy, I re-factored it into a new if_txtimer structure and API.
So save typing, I'll paste the relevant section of <net/if.h>:
/*
* if_txtimer --
*
* Transmission timer (to replace the legacy ifnet watchdog timer).
*
* The driver should allocate one if_txtimer per hardware-managed
* transmission queue and initialize it with if_txtimer_init(). The
* driver should also arrange to have a callout invoked at a regular
* interval (this may be coindidental with a timer used to check
* link status).
*
* When the driver gives packets to the hardware to transmit, it should
* arm the timer by calling if_txtimer_arm(). When it is sweeping up
* completed transmit jobs, it should disarm the timer by calling
* if_txtimer_disarm() if there are no outstanding jobs remaining.
*
* In the periodic callout, the driver should check if the timer has
* expired by calling if_txtimer_is_expired(). It is not necessary to
* check if the timer is armed when checking for expiration. If the
* timer has is expired, then the transmission has timed out and the
* driver should take corrective action to recover from the error.
*
* If the driver needs to check multiple transmission queues, an
* optimization is available that avoids repeated calls to fetch
* the compare time. In this case, the driver can get the compare
* time by calling if_txtimer_now() and can check for timer expiration
* using if_txtimer_is_expired_explicit().
*
* The granularity of the if_txtimer is 1 second.
*
* Locking: All locking of the if_txtimer is the responsibility of
* the driver. The if_txtimer should be protected by the same lock
* that protects the associated transmission queue.
*/
See the diff for complete details. Included is a conversion of wm(4) (which uses the if_txtimer_is_expired_explicit() variant), and pcn(4) (which uses the simpler if_txtimer_is_expired() variant). The diff for pcn(4) looks artificially large because I relocated to pcn_txtimer_check() its sole call site after I renamed it from pcn_watchdog().
My plan is to get the new API in and start updating drivers to use the new mechanism. The changes will be basically mechanical. Before I get started on that, I'd like feedback on the proposed API.
Thx.
The legacy (*if_watchdog)() interface has a couple of problems:
1- It does not have any way to represent multiple hardware-managed transmit queues.
2- It's not easy to make MP-safe because it relies on modifying the ifnet structure periodically outside of the normal locking mechanisms.
The wm(4) driver solved the problem in a reasonable way, and to make it easier for the other drivers in the tree to adopt it's strategy, I re-factored it into a new if_txtimer structure and API.
So save typing, I'll paste the relevant section of <net/if.h>:
/*
* if_txtimer --
*
* Transmission timer (to replace the legacy ifnet watchdog timer).
*
* The driver should allocate one if_txtimer per hardware-managed
* transmission queue and initialize it with if_txtimer_init(). The
* driver should also arrange to have a callout invoked at a regular
* interval (this may be coindidental with a timer used to check
* link status).
*
* When the driver gives packets to the hardware to transmit, it should
* arm the timer by calling if_txtimer_arm(). When it is sweeping up
* completed transmit jobs, it should disarm the timer by calling
* if_txtimer_disarm() if there are no outstanding jobs remaining.
*
* In the periodic callout, the driver should check if the timer has
* expired by calling if_txtimer_is_expired(). It is not necessary to
* check if the timer is armed when checking for expiration. If the
* timer has is expired, then the transmission has timed out and the
* driver should take corrective action to recover from the error.
*
* If the driver needs to check multiple transmission queues, an
* optimization is available that avoids repeated calls to fetch
* the compare time. In this case, the driver can get the compare
* time by calling if_txtimer_now() and can check for timer expiration
* using if_txtimer_is_expired_explicit().
*
* The granularity of the if_txtimer is 1 second.
*
* Locking: All locking of the if_txtimer is the responsibility of
* the driver. The if_txtimer should be protected by the same lock
* that protects the associated transmission queue.
*/
See the diff for complete details. Included is a conversion of wm(4) (which uses the if_txtimer_is_expired_explicit() variant), and pcn(4) (which uses the simpler if_txtimer_is_expired() variant). The diff for pcn(4) looks artificially large because I relocated to pcn_txtimer_check() its sole call site after I renamed it from pcn_watchdog().
My plan is to get the new API in and start updating drivers to use the new mechanism. The changes will be basically mechanical. Before I get started on that, I'd like feedback on the proposed API.
Thx.