This is page about subversion branch projects/ifnet, or "opaque ifnet" project.

Introduction: why do we need it, what's already in head

The ifnet(9) structure represents a network interface. Right now, it is exported across all NIC drivers and all protocols. Hence, whenever we change the structure, we are forced at least to recompile all drivers that generally involves changing the drivers' code. This significantly slows downs the development in this area and also makes it hard or sometimes even impossible to merge changes back to the stable branches.

After years of development, it becomes clear that the structure should be opaque to drivers and, in theory, to the network protocols. Such an opaqueness could be achieved in two ways:

The disadvantage of the quick way is that despite of avoiding recompilation when adding fields to the struct, the KPI actually forces the structure's layout. Anyway, the quick way has been already committed to FreeBSD as Juniper's drvapi patch:

Nevertheless, the long term plan is to go the proper way. The proper way is going in the subversion repository:

General ideas for new ''struct ifnet''

Header purity

Structure layout

Historically, the struct ifnet is a storage for all kind of stuff that applies to a network interface. Therefore, struct ifnet has grown over 1 Kbyte on 64-bit platforms. However, the most of information containing in this structure is not specific for an interface instance being driver-specific instead. Another portion of structure concludes pointers to software contexts of various networking facilities that are normally not used. All these parts could be removed from the structure. The softc pointers could be optimized later when the structure is already opaque. In contrast, the driver-specific fields should be removed early at the stage of KPI redesign. Here is the approximate list of driver-specific fields:

All this stuff should be moved into struct ifdriver that is allocated statically by a NIC driver with all the instances of given driver point at the same struct ifdriver.

We want to extract interface methods (or operations) from the struct ifdriver into a separate struct ifops. Our goal here is to make operations overloadable for lagg(4) and for the purposes of the proper ALTQ integration into the stack.

struct ifdriver, struct ifops are going to be declared in <net/if.h> and thus is visible to drivers. These structures will have spare fields.

Structure allocation and initialization

Drivers call if_attach() in their device_attach driver(9) DEVMETHOD. The context allows to sleep, therefore if_attach() cannot fail. Note: the only reason for it to fail is interface name conflict, but the vast majority of drivers do not request the specific name. If the name constraint is required, then a driver must be prepared for the possible error returned from if_attach().

The only argument to if_attach() is a pointer to the struct if_attach_args. This structure points to struct ifdriver and also contains all information specific to the instance of an interface being attached. struct ifdriver has a field ifat_version that specifies the version of the KPI at compile time. This allows the kernel to understand what version of KPI the driver uses and optionally fix the driver's struct ifdriver to make it compatible with new network stack.

The if_attach returns pointer of if_t type which is actually an opaque pointer to struct ifnet.

Converting drivers to new KPI

Normal converting procedure

The vast majority of Ethernet drivers in FreeBSD are copy-pasted from each other, so the procedure is quite common for them. The typical TODO list includes the following steps:

miibus(4) changes

So far, miibus(4) is no longer aware about struct ifnet that was a layering violation between device layer and network stack. This change requires a few extra changes to the NIC drivers that use miibus(4).

Conversion progress

Tracked at separate page projects/ifnet/progress.

Heavy tasks, not yet done, but must be done

Apart from tons of drivers, there are more things to be done:

Maintaining compat shims in the future

Since struct if_attach_args begins with version field, we can differentiate a driver compiled for older kernel. We can keep compat shims in net/if_compat.c, where we will keep the history of older struct if_attach_args, struct ifaddr, struct ifops and all the compat shims required to convert them to newer, allowing for older drivers to attach.


projects/ifnet (last edited 2018-07-21T03:51:53+0000 by MarkLinimon)