diff options
author | Brooks Davis <brooks@FreeBSD.org> | 2005-06-10 16:49:24 +0000 |
---|---|---|
committer | Brooks Davis <brooks@FreeBSD.org> | 2005-06-10 16:49:24 +0000 |
commit | fc74a9f93a5fbc83262aa12084404ac953c854b5 (patch) | |
tree | f65b6d7834b40dfcd48534829a0a1e9529ab87ee /sys/net/if.c | |
parent | 7f1d8b7517a6a93379974243551e0ec0a96cb54e (diff) | |
download | src-fc74a9f93a5fbc83262aa12084404ac953c854b5.tar.gz src-fc74a9f93a5fbc83262aa12084404ac953c854b5.zip |
Stop embedding struct ifnet at the top of driver softcs. Instead the
struct ifnet or the layer 2 common structure it was embedded in have
been replaced with a struct ifnet pointer to be filled by a call to the
new function, if_alloc(). The layer 2 common structure is also allocated
via if_alloc() based on the interface type. It is hung off the new
struct ifnet member, if_l2com.
This change removes the size of these structures from the kernel ABI and
will allow us to better manage them as interfaces come and go.
Other changes of note:
- Struct arpcom is no longer referenced in normal interface code.
Instead the Ethernet address is accessed via the IFP2ENADDR() macro.
To enforce this ac_enaddr has been renamed to _ac_enaddr.
- The second argument to ether_ifattach is now always the mac address
from driver private storage rather than sometimes being ac_enaddr.
Reviewed by: sobomax, sam
Notes
Notes:
svn path=/head/; revision=147256
Diffstat (limited to 'sys/net/if.c')
-rw-r--r-- | sys/net/if.c | 108 |
1 files changed, 94 insertions, 14 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index d2d179fc9a05..4f3082a5af8c 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -127,6 +127,8 @@ struct ifindex_entry *ifindex_table = NULL; int ifqmaxlen = IFQ_MAXLEN; struct ifnethead ifnet; /* depend on static init XXX */ struct mtx ifnet_lock; +static if_com_alloc_t *if_com_alloc[256]; +static if_com_free_t *if_com_free[256]; static int if_indexlim = 8; static struct knlist ifklist; @@ -143,6 +145,7 @@ static struct filterops netdev_filtops = SYSINIT(interfaces, SI_SUB_INIT_IF, SI_ORDER_FIRST, if_init, NULL) SYSINIT(interface_check, SI_SUB_PROTO_IF, SI_ORDER_FIRST, if_check, NULL) +MALLOC_DEFINE(M_IFNET, "ifnet", "interface internals"); MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address"); MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address"); @@ -291,10 +294,10 @@ if_grow(void) if_indexlim <<= 1; n = if_indexlim * sizeof(*e); - e = malloc(n, M_IFADDR, M_WAITOK | M_ZERO); + e = malloc(n, M_IFNET, M_WAITOK | M_ZERO); if (ifindex_table != NULL) { memcpy((caddr_t)e, (caddr_t)ifindex_table, n/2); - free((caddr_t)ifindex_table, M_IFADDR); + free((caddr_t)ifindex_table, M_IFNET); } ifindex_table = e; } @@ -325,6 +328,7 @@ if_check(void *dummy __unused) if_slowtimo(0); } +/* XXX: should be locked. */ static int if_findindex(struct ifnet *ifp) { @@ -339,7 +343,7 @@ if_findindex(struct ifnet *ifp) case IFT_ISO88025: case IFT_L2VLAN: case IFT_BRIDGE: - snprintf(eaddr, 18, "%6D", IFP2AC(ifp)->ac_enaddr, ":"); + snprintf(eaddr, 18, "%6D", IFP2ENADDR(ifp), ":"); break; default: eaddr[0] = '\0'; @@ -376,6 +380,59 @@ found: } /* + * Allocate a struct ifnet and in index for an interface. + */ +struct ifnet* +if_alloc(u_char type) +{ + struct ifnet *ifp; + + ifp = malloc(sizeof(struct ifnet), M_IFNET, M_WAITOK|M_ZERO); + + /* XXX: This should fail it index it is too big */ + ifp->if_index = if_findindex(ifp); + if (ifp->if_index > if_index) + if_index = ifp->if_index; + if (if_index >= if_indexlim) + if_grow(); + + ifnet_byindex(ifp->if_index) = ifp; + + ifp->if_type = type; + + if (if_com_alloc[type] != NULL) { + ifp->if_l2com = if_com_alloc[type](type, ifp); + if (ifp->if_l2com == NULL) + free(ifp, M_IFNET); + } + + return (ifp); +} + +void +if_free(struct ifnet *ifp) +{ + + if_free_type(ifp, ifp->if_type); +} + +void +if_free_type(struct ifnet *ifp, u_char type) +{ + + if (ifp != ifnet_byindex(ifp->if_index)) { + if_printf(ifp, "%s: value was not if_alloced, skipping\n", + __func__); + return; + } + + if (if_com_free[type] != NULL) + if_com_free[type](ifp->if_l2com, type); + + free(ifp, M_IFNET); +}; + +/* * Attach an interface to the * list of "active" interfaces. */ @@ -387,6 +444,10 @@ if_attach(struct ifnet *ifp) struct sockaddr_dl *sdl; struct ifaddr *ifa; + if (ifp->if_index == 0 || ifp != ifnet_byindex(ifp->if_index)) + panic ("%s: BUG: if_attach called without if_alloc'd input()\n", + ifp->if_xname); + TASK_INIT(&ifp->if_starttask, 0, if_start_deferred, ifp); TASK_INIT(&ifp->if_linktask, 0, do_link_state_change, ifp); IF_AFDATA_LOCK_INIT(ifp); @@ -407,20 +468,13 @@ if_attach(struct ifnet *ifp) knlist_init(&ifp->if_klist, NULL); getmicrotime(&ifp->if_lastchange); ifp->if_data.ifi_epoch = time_uptime; + ifp->if_data.ifi_datalen = sizeof(struct if_data); #ifdef MAC mac_init_ifnet(ifp); mac_create_ifnet(ifp); #endif - ifp->if_index = if_findindex(ifp); - if (ifp->if_index > if_index) - if_index = ifp->if_index; - if (if_index >= if_indexlim) - if_grow(); - ifp->if_data.ifi_datalen = sizeof(struct if_data); - - ifnet_byindex(ifp->if_index) = ifp; ifdev_byindex(ifp->if_index) = make_dev(&net_cdevsw, unit2minor(ifp->if_index), UID_ROOT, GID_WHEEL, 0600, "%s/%s", @@ -572,7 +626,7 @@ if_purgeaddrs(struct ifnet *ifp) /* * Detach an interface, removing it from the - * list of "active" interfaces. + * list of "active" interfaces and freeing the struct ifnet. */ void if_detach(struct ifnet *ifp) @@ -1942,7 +1996,7 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len) case IFT_ISO88025: case IFT_L2VLAN: case IFT_BRIDGE: - bcopy(lladdr, IFP2AC(ifp)->ac_enaddr, len); + bcopy(lladdr, IFP2ENADDR(ifp), len); /* * XXX We also need to store the lladdr in LLADDR(sdl), * which is done below. This is a pain because we must @@ -2066,7 +2120,7 @@ if_start_deferred(void *context, int pending) KASSERT(debug_mpsafenet != 0, ("if_start_deferred: debug.mpsafenet")); GIANT_REQUIRED; - ifp = (struct ifnet *)context; + ifp = context; (ifp->if_start)(ifp); } @@ -2094,3 +2148,29 @@ if_handoff(struct ifqueue *ifq, struct mbuf *m, struct ifnet *ifp, int adjust) if_start(ifp); return (1); } + +void +if_register_com_alloc(u_char type, + if_com_alloc_t *a, if_com_free_t *f) +{ + + KASSERT(if_com_alloc[type] == NULL, + ("if_register_com_alloc: %d already registered", type)); + KASSERT(if_com_free[type] == NULL, + ("if_register_com_alloc: %d free already registered", type)); + + if_com_alloc[type] = a; + if_com_free[type] = f; +} + +void +if_deregister_com_alloc(u_char type) +{ + + KASSERT(if_com_alloc[type] == NULL, + ("if_deregister_com_alloc: %d not registered", type)); + KASSERT(if_com_free[type] == NULL, + ("if_deregister_com_alloc: %d free not registered", type)); + if_com_alloc[type] = NULL; + if_com_free[type] = NULL; +} |