NetBSD Documentation: Converting ancient BSD Ethernet drivers to NetBSD


With NetBSD-1.2D and later, the traditional IPv4-over-Ethernet-only ARP subsystem was modified to allow IPv4 over any hardware medium. While all NetBSD Ethernet drivers were converted, you might want to contribute a new one, based on some other BSD's code who did not yet make this change. This document outlines the steps necessary to convert your driver to NetBSD.

Naming Conventions

Throughout this document,

 struct ifnet *ifp;

is a pointer to the interface structure of "our" device and

 struct foo_softc *sc;

is a pointer to our softc structure.

Include Files Needed

Instead of

#include <netinet/if_ether.h>


#include <net/if_dl.h>		/* for the LLADDR macro */
#include <net/if_ether.h>	/* for real Ethernet stuff */
#include <netinet/if_inarp.h>	/* for IP-specific ARP stuff. */

Sometimes you also need

#include <net/if_arp.h>

Softc Structure

  • Remove struct arpcom from the beginning of the softc definition. In most drivers it is called

     struct arpcom sc_ac;


     struct arpcom sc_arpcom;

    Throughout this text, we assume the former.

  • Add struct ethercom instead. Throughout this text, we assume you called it

    	struct ethercom sc_ec;
  • In all references to the multicast list, use the struct ethercom, that is replace sc->sc_ac by sc->sc_ec.

  • Replace all reference to sc_ac.ac_if by sc_ec.ec_if.

[While you are here: I've seen lots of places, where, at the beginning of a function, a struct ifnet * parameter is converted to a struct foo_softc *, and later there are lots of sc-> or &sc->sc_if accesses. This is ugly, confusing and unnecessary. Depending on the nature of the driver you might want to change this while you're at it.]

Changed functions

  • arp_ifinit() (there is a man page on this) takes a struct ifnet * as the first parameter, instead of a struct arpcom *.

You may have noticed by now, that you don't have a hardware address any longer in the softc.

There are two types of accesses to it. One is initialization, in the foo_attach() function (if this is done in the fooprobe()/foomatch() function, your driver is broken for other reasons and should be fixed); the other is runtime reads, and for less common protocols like XNS, OSI, DECnet, even writes

  • Initialization: you call ether_ifattach() (there should be a man page on this) with a 2nd parameter, a u_int8_t * pointing to the address. ether_ifattach() will create (as before) a struct sockaddr_dl in the interface address list, copy (among other initialization) the address there, and makes ifp->if_sadl point to it.

  • Run-time: use LLADDR(ifp->if_sadl) as a caddr_t pointing to our Ethernet address. If you need the address length, you should probably use ETHER_ADDR_LEN.

Back to NetBSD Documentation: Kernel