X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/4a3eedf9ecc9bbe3f3a5c6ce5e53ad199d639d32..d1ecb069dfe24481e4a83f44cb5217a2b06746d7:/bsd/net/kpi_interface.c diff --git a/bsd/net/kpi_interface.c b/bsd/net/kpi_interface.c index d9dfca3f3..e56564c58 100644 --- a/bsd/net/kpi_interface.c +++ b/bsd/net/kpi_interface.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2007 Apple Inc. All rights reserved. + * Copyright (c) 2004-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -47,6 +47,8 @@ #include #include +#include "net/net_str_id.h" + #if IF_LASTCHANGEUPTIME #define TOUCHLASTCHANGE(__if_lastchange) microuptime(__if_lastchange) #else @@ -189,7 +191,7 @@ ifnet_reference( if (ifp == NULL) return EINVAL; - oldval = OSIncrementAtomic((SInt32 *)&ifp->if_refcnt); + oldval = OSIncrementAtomic(&ifp->if_refcnt); return 0; } @@ -202,13 +204,22 @@ ifnet_release( if (ifp == NULL) return EINVAL; - oldval = OSDecrementAtomic((SInt32*)&ifp->if_refcnt); + oldval = OSDecrementAtomic(&ifp->if_refcnt); if (oldval == 0) panic("ifnet_release - refcount decremented past zero!"); return 0; } +errno_t +ifnet_interface_family_find(const char *module_string, ifnet_family_t *family_id) +{ + if (module_string == NULL || family_id == NULL) + return EINVAL; + return net_str_id_find_internal(module_string, family_id, NSI_IF_FAM_ID, 1); + +} + void* ifnet_softc( ifnet_t interface) @@ -300,10 +311,67 @@ ifnet_eflags( return interface == NULL ? 0 : interface->if_eflags; } +errno_t +ifnet_set_idle_flags(ifnet_t ifp, u_int32_t new_flags, u_int32_t mask) +{ +#if IFNET_ROUTE_REFCNT + int lock, before, after; + + if (ifp == NULL) + return (EINVAL); + + lck_mtx_lock(rnh_lock); + + lock = (ifp->if_lock != NULL); + if (lock) + ifnet_lock_exclusive(ifp); + + before = ifp->if_idle_flags; + ifp->if_idle_flags = (new_flags & mask) | (ifp->if_idle_flags & ~mask); + after = ifp->if_idle_flags; + + if ((after - before) < 0 && ifp->if_idle_flags == 0 && + ifp->if_want_aggressive_drain != 0) { + ifp->if_want_aggressive_drain = 0; + if (ifnet_aggressive_drainers == 0) + panic("%s: ifp=%p negative aggdrain!", __func__, ifp); + if (--ifnet_aggressive_drainers == 0) + rt_aggdrain(0); + } else if ((after - before) > 0 && ifp->if_want_aggressive_drain == 0) { + ifp->if_want_aggressive_drain++; + if (++ifnet_aggressive_drainers == 0) + panic("%s: ifp=%p wraparound aggdrain!", __func__, ifp); + else if (ifnet_aggressive_drainers == 1) + rt_aggdrain(1); + } + + if (lock) + ifnet_lock_done(ifp); + + lck_mtx_unlock(rnh_lock); + + return (0); +#else +#pragma unused(ifp, new_flags, mask) + return (ENOTSUP); +#endif /* IFNET_ROUTE_REFCNT */ +} + +u_int32_t +ifnet_idle_flags(ifnet_t ifp) +{ +#if IFNET_ROUTE_REFCNT + return ((ifp == NULL) ? 0 : ifp->if_idle_flags); +#else +#pragma unused(ifp) + return (0); +#endif /* IFNET_ROUTE_REFCNT */ +} + static const ifnet_offload_t offload_mask = IFNET_CSUM_IP | IFNET_CSUM_TCP | IFNET_CSUM_UDP | IFNET_CSUM_FRAGMENT | IFNET_IP_FRAGMENT | IFNET_CSUM_SUM16 | IFNET_VLAN_TAGGING | IFNET_VLAN_MTU | - IFNET_MULTIPAGES; + IFNET_MULTIPAGES | IFNET_TSO_IPV4 | IFNET_TSO_IPV6; errno_t ifnet_set_offload( @@ -329,6 +397,127 @@ ifnet_offload( return interface == NULL ? 0 : (interface->if_hwassist & offload_mask); } +errno_t +ifnet_set_tso_mtu( + ifnet_t interface, + sa_family_t family, + u_int32_t mtuLen) +{ + errno_t error = 0; + + if (interface == NULL) return EINVAL; + + if (mtuLen < interface->if_mtu) + return EINVAL; + + + switch (family) { + + case AF_INET: + if (interface->if_hwassist & IFNET_TSO_IPV4) + interface->if_tso_v4_mtu = mtuLen; + else + error = EINVAL; + break; + + case AF_INET6: + if (interface->if_hwassist & IFNET_TSO_IPV6) + interface->if_tso_v6_mtu = mtuLen; + else + error = EINVAL; + break; + + default: + error = EPROTONOSUPPORT; + } + + return error; +} + +errno_t +ifnet_get_tso_mtu( + ifnet_t interface, + sa_family_t family, + u_int32_t *mtuLen) +{ + errno_t error = 0; + + if (interface == NULL || mtuLen == NULL) return EINVAL; + + switch (family) { + + case AF_INET: + if (interface->if_hwassist & IFNET_TSO_IPV4) + *mtuLen = interface->if_tso_v4_mtu; + else + error = EINVAL; + break; + + case AF_INET6: + if (interface->if_hwassist & IFNET_TSO_IPV6) + *mtuLen = interface->if_tso_v6_mtu; + else + error = EINVAL; + break; + default: + error = EPROTONOSUPPORT; + } + + return error; +} + +errno_t +ifnet_set_wake_flags(ifnet_t interface, u_int32_t properties, u_int32_t mask) +{ + int lock; + struct kev_msg ev_msg; + struct net_event_data ev_data; + + if (interface == NULL) + return EINVAL; + + /* Do not accept wacky values */ + if ((properties & mask) & ~IF_WAKE_VALID_FLAGS) + return EINVAL; + + lock = (interface->if_lock != 0); + + if (lock) + ifnet_lock_exclusive(interface); + + interface->if_wake_properties = (properties & mask) | (interface->if_wake_properties & ~mask); + + if (lock) + ifnet_lock_done(interface); + + (void) ifnet_touch_lastchange(interface); + + /* Notify application of the change */ + ev_msg.vendor_code = KEV_VENDOR_APPLE; + ev_msg.kev_class = KEV_NETWORK_CLASS; + ev_msg.kev_subclass = KEV_DL_SUBCLASS; + + ev_msg.event_code = KEV_DL_WAKEFLAGS_CHANGED; + strlcpy(&ev_data.if_name[0], interface->if_name, IFNAMSIZ); + ev_data.if_family = interface->if_family; + ev_data.if_unit = (u_int32_t) interface->if_unit; + ev_msg.dv[0].data_length = sizeof(struct net_event_data); + ev_msg.dv[0].data_ptr = &ev_data; + ev_msg.dv[1].data_length = 0; + kev_post_msg(&ev_msg); + + return 0; +} + +u_int32_t +ifnet_get_wake_flags(ifnet_t interface) +{ + return interface == NULL ? 0 : interface->if_wake_properties; +} + + + + /* * Should MIB data store a copy? */ @@ -1360,3 +1549,82 @@ ifmaddr_ifnet( if (ifmaddr == NULL || ifmaddr->ifma_ifp == NULL) return NULL; return ifmaddr->ifma_ifp; } + +/******************************************************************************/ +/* interface cloner */ +/******************************************************************************/ + +errno_t +ifnet_clone_attach(struct ifnet_clone_params *cloner_params, if_clone_t *ifcloner) +{ + errno_t error = 0; + struct if_clone *ifc = NULL; + size_t namelen; + + if (cloner_params == NULL || ifcloner == NULL || cloner_params->ifc_name == NULL || + cloner_params->ifc_create == NULL || cloner_params->ifc_destroy == NULL || + (namelen = strlen(cloner_params->ifc_name)) >= IFNAMSIZ) { + error = EINVAL; + goto fail; + } + + if (if_clone_lookup(cloner_params->ifc_name, NULL) != NULL) { + printf("ifnet_clone_attach: already a cloner for %s\n", cloner_params->ifc_name); + error = EEXIST; + goto fail; + } + + /* Make room for name string */ + ifc = _MALLOC(sizeof(struct if_clone) + IFNAMSIZ + 1, M_CLONE, M_WAITOK | M_ZERO); + if (ifc == NULL) { + printf("ifnet_clone_attach: _MALLOC failed\n"); + error = ENOBUFS; + goto fail; + } + strlcpy((char *)(ifc + 1), cloner_params->ifc_name, IFNAMSIZ + 1); + ifc->ifc_name = (char *)(ifc + 1); + ifc->ifc_namelen = namelen; + ifc->ifc_maxunit = IF_MAXUNIT; + ifc->ifc_create = cloner_params->ifc_create; + ifc->ifc_destroy = cloner_params->ifc_destroy; + + error = if_clone_attach(ifc); + if (error != 0) { + printf("ifnet_clone_attach: if_clone_attach failed %d\n", error); + goto fail; + } + *ifcloner = ifc; + + return 0; +fail: + if (ifc != NULL) + FREE(ifc, M_CLONE); + return error; +} + +errno_t +ifnet_clone_detach(if_clone_t ifcloner) +{ + errno_t error = 0; + struct if_clone *ifc = ifcloner; + + if (ifc == NULL || ifc->ifc_name == NULL) + return EINVAL; + + if ((if_clone_lookup(ifc->ifc_name, NULL)) == NULL) { + printf("ifnet_clone_attach: no cloner for %s\n", ifc->ifc_name); + error = EINVAL; + goto fail; + } + + if_clone_detach(ifc); + + FREE(ifc, M_CLONE); + + return 0; +fail: + return error; +} + + +