Changeset View
Changeset View
Standalone View
Standalone View
sys/net/if.c
Show First 20 Lines • Show All 307 Lines • ▼ Show 20 Lines | |||||
int ifqmaxlen = IFQ_MAXLEN; | int ifqmaxlen = IFQ_MAXLEN; | ||||
VNET_DEFINE(struct ifnethead, ifnet); /* depend on static init XXX */ | VNET_DEFINE(struct ifnethead, ifnet); /* depend on static init XXX */ | ||||
VNET_DEFINE(struct ifgrouphead, ifg_head); | VNET_DEFINE(struct ifgrouphead, ifg_head); | ||||
/* Table of ifnet by index. */ | /* Table of ifnet by index. */ | ||||
static int if_index; | static int if_index; | ||||
static int if_indexlim = 8; | static int if_indexlim = 8; | ||||
static struct ifnet **ifindex_table; | static struct ifindex_entry { | ||||
struct ifnet *ife_ifnet; | |||||
uint16_t ife_gencnt; | |||||
} *ifindex_table; | |||||
SYSCTL_NODE(_net_link_generic, IFMIB_SYSTEM, system, | SYSCTL_NODE(_net_link_generic, IFMIB_SYSTEM, system, | ||||
CTLFLAG_RW | CTLFLAG_MPSAFE, 0, | CTLFLAG_RW | CTLFLAG_MPSAFE, 0, | ||||
"Variables global to all interfaces"); | "Variables global to all interfaces"); | ||||
static int | static int | ||||
sysctl_ifcount(SYSCTL_HANDLER_ARGS) | sysctl_ifcount(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
int rv = 0; | int rv = 0; | ||||
IFNET_RLOCK(); | IFNET_RLOCK(); | ||||
for (int i = 1; i <= if_index; i++) | for (int i = 1; i <= if_index; i++) | ||||
if (ifindex_table[i] != NULL && | if (ifindex_table[i].ife_ifnet != NULL && | ||||
ifindex_table[i]->if_vnet == curvnet) | ifindex_table[i].ife_ifnet->if_vnet == curvnet) | ||||
rv = i; | rv = i; | ||||
IFNET_RUNLOCK(); | IFNET_RUNLOCK(); | ||||
return (sysctl_handle_int(oidp, &rv, 0, req)); | return (sysctl_handle_int(oidp, &rv, 0, req)); | ||||
} | } | ||||
SYSCTL_PROC(_net_link_generic_system, IFMIB_IFCOUNT, ifcount, | SYSCTL_PROC(_net_link_generic_system, IFMIB_IFCOUNT, ifcount, | ||||
CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_RD, NULL, 0, sysctl_ifcount, "I", | CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_RD, NULL, 0, sysctl_ifcount, "I", | ||||
"Maximum known interface index"); | "Maximum known interface index"); | ||||
Show All 27 Lines | |||||
{ | { | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
NET_EPOCH_ASSERT(); | NET_EPOCH_ASSERT(); | ||||
if (__predict_false(idx > if_index)) | if (__predict_false(idx > if_index)) | ||||
return (NULL); | return (NULL); | ||||
ifp = ck_pr_load_ptr(&ifindex_table[idx]); | ifp = ck_pr_load_ptr(&ifindex_table[idx].ife_ifnet); | ||||
if (curvnet != NULL && ifp->if_vnet != curvnet) | if (curvnet != NULL && ifp->if_vnet != curvnet) | ||||
ifp = NULL; | ifp = NULL; | ||||
return (ifp); | return (ifp); | ||||
} | } | ||||
struct ifnet * | struct ifnet * | ||||
ifnet_byindex_ref(u_int idx) | ifnet_byindex_ref(u_int idx) | ||||
{ | { | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
ifp = ifnet_byindex(idx); | ifp = ifnet_byindex(idx); | ||||
if (ifp == NULL || (ifp->if_flags & IFF_DYING)) | if (ifp == NULL || (ifp->if_flags & IFF_DYING)) | ||||
return (NULL); | return (NULL); | ||||
if (!if_try_ref(ifp)) | if (!if_try_ref(ifp)) | ||||
return (NULL); | return (NULL); | ||||
return (ifp); | return (ifp); | ||||
} | } | ||||
struct ifnet * | |||||
ifnet_byindexgen(uint16_t idx, uint16_t gen) | |||||
{ | |||||
struct ifnet *ifp; | |||||
NET_EPOCH_ASSERT(); | |||||
if (__predict_false(idx > if_index)) | |||||
return (NULL); | |||||
ifp = ck_pr_load_ptr(&ifindex_table[idx].ife_ifnet); | |||||
if (ifindex_table[idx].ife_gencnt == gen) | |||||
return (ifp); | |||||
else | |||||
return (NULL); | |||||
} | |||||
struct ifaddr * | struct ifaddr * | ||||
ifaddr_byindex(u_short idx) | ifaddr_byindex(u_short idx) | ||||
{ | { | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
struct ifaddr *ifa = NULL; | struct ifaddr *ifa = NULL; | ||||
NET_EPOCH_ASSERT(); | NET_EPOCH_ASSERT(); | ||||
▲ Show 20 Lines • Show All 164 Lines • ▼ Show 20 Lines | #endif | ||||
/* Allocate an ifindex array entry. */ | /* Allocate an ifindex array entry. */ | ||||
IFNET_WLOCK(); | IFNET_WLOCK(); | ||||
/* | /* | ||||
* Try to find an empty slot below if_index. If we fail, take the | * Try to find an empty slot below if_index. If we fail, take the | ||||
* next slot. | * next slot. | ||||
*/ | */ | ||||
for (idx = 1; idx <= if_index; idx++) { | for (idx = 1; idx <= if_index; idx++) { | ||||
if (ifindex_table[idx] == NULL) | if (ifindex_table[idx].ife_ifnet == NULL) | ||||
break; | break; | ||||
} | } | ||||
/* Catch if_index overflow. */ | /* Catch if_index overflow. */ | ||||
if (idx >= if_indexlim) { | if (idx >= if_indexlim) { | ||||
struct ifnet **new, **old; | struct ifindex_entry *new, *old; | ||||
int newlim; | int newlim; | ||||
newlim = if_indexlim * 2; | newlim = if_indexlim * 2; | ||||
new = malloc(newlim * sizeof(*new), M_IFNET, M_WAITOK | M_ZERO); | new = malloc(newlim * sizeof(*new), M_IFNET, M_WAITOK | M_ZERO); | ||||
memcpy(new, ifindex_table, if_indexlim * sizeof(*new)); | memcpy(new, ifindex_table, if_indexlim * sizeof(*new)); | ||||
old = ifindex_table; | old = ifindex_table; | ||||
ck_pr_store_ptr(&ifindex_table, new); | ck_pr_store_ptr(&ifindex_table, new); | ||||
if_indexlim = newlim; | if_indexlim = newlim; | ||||
epoch_wait_preempt(net_epoch_preempt); | epoch_wait_preempt(net_epoch_preempt); | ||||
free(old, M_IFNET); | free(old, M_IFNET); | ||||
} | } | ||||
if (idx > if_index) | if (idx > if_index) | ||||
if_index = idx; | if_index = idx; | ||||
ifp->if_index = idx; | ifp->if_index = idx; | ||||
ck_pr_store_ptr(&ifindex_table[idx], ifp); | ifp->if_idxgen = ifindex_table[idx].ife_gencnt; | ||||
ck_pr_store_ptr(&ifindex_table[idx].ife_ifnet, ifp); | |||||
IFNET_WUNLOCK(); | IFNET_WUNLOCK(); | ||||
return (ifp); | return (ifp); | ||||
} | } | ||||
struct ifnet * | struct ifnet * | ||||
if_alloc_dev(u_char type, device_t dev) | if_alloc_dev(u_char type, device_t dev) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | if_free(struct ifnet *ifp) | ||||
* thread obtaining ifp via ifnet_byindex() inside the network | * thread obtaining ifp via ifnet_byindex() inside the network | ||||
* epoch and then dereferencing ifp while we peform if_free(), | * epoch and then dereferencing ifp while we peform if_free(), | ||||
* and after if_free() finished, too. | * and after if_free() finished, too. | ||||
* | * | ||||
* This early index freeing was important back when ifindex was | * This early index freeing was important back when ifindex was | ||||
* virtualized and interface would outlive the vnet. | * virtualized and interface would outlive the vnet. | ||||
*/ | */ | ||||
IFNET_WLOCK(); | IFNET_WLOCK(); | ||||
MPASS(ifindex_table[ifp->if_index] == ifp); | MPASS(ifindex_table[ifp->if_index].ife_ifnet == ifp); | ||||
ck_pr_store_ptr(&ifindex_table[ifp->if_index], NULL); | ck_pr_store_ptr(&ifindex_table[ifp->if_index].ife_ifnet, NULL); | ||||
while (if_index > 0 && ifindex_table[if_index] == NULL) | ifindex_table[ifp->if_index].ife_gencnt++; | ||||
while (if_index > 0 && ifindex_table[if_index].ife_ifnet == NULL) | |||||
if_index--; | if_index--; | ||||
IFNET_WUNLOCK(); | IFNET_WUNLOCK(); | ||||
if (refcount_release(&ifp->if_refcount)) | if (refcount_release(&ifp->if_refcount)) | ||||
NET_EPOCH_CALL(if_free_deferred, &ifp->if_epoch_ctx); | NET_EPOCH_CALL(if_free_deferred, &ifp->if_epoch_ctx); | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 132 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc) | if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc) | ||||
{ | { | ||||
unsigned socksize, ifasize; | unsigned socksize, ifasize; | ||||
int namelen, masklen; | int namelen, masklen; | ||||
struct sockaddr_dl *sdl; | struct sockaddr_dl *sdl; | ||||
struct ifaddr *ifa; | struct ifaddr *ifa; | ||||
MPASS(ifindex_table[ifp->if_index] == ifp); | MPASS(ifindex_table[ifp->if_index].ife_ifnet == ifp); | ||||
#ifdef VIMAGE | #ifdef VIMAGE | ||||
ifp->if_vnet = curvnet; | ifp->if_vnet = curvnet; | ||||
if (ifp->if_home_vnet == NULL) | if (ifp->if_home_vnet == NULL) | ||||
ifp->if_home_vnet = curvnet; | ifp->if_home_vnet = curvnet; | ||||
#endif | #endif | ||||
if_addgroup(ifp, IFG_ALL); | if_addgroup(ifp, IFG_ALL); | ||||
▲ Show 20 Lines • Show All 3,678 Lines • ▼ Show 20 Lines | if_show_ifnet(struct ifnet *ifp) | ||||
if (ifp == NULL) | if (ifp == NULL) | ||||
return; | return; | ||||
db_printf("%s:\n", ifp->if_xname); | db_printf("%s:\n", ifp->if_xname); | ||||
#define IF_DB_PRINTF(f, e) db_printf(" %s = " f "\n", #e, ifp->e); | #define IF_DB_PRINTF(f, e) db_printf(" %s = " f "\n", #e, ifp->e); | ||||
IF_DB_PRINTF("%s", if_dname); | IF_DB_PRINTF("%s", if_dname); | ||||
IF_DB_PRINTF("%d", if_dunit); | IF_DB_PRINTF("%d", if_dunit); | ||||
IF_DB_PRINTF("%s", if_description); | IF_DB_PRINTF("%s", if_description); | ||||
IF_DB_PRINTF("%u", if_index); | IF_DB_PRINTF("%u", if_index); | ||||
IF_DB_PRINTF("%d", if_idxgen); | |||||
IF_DB_PRINTF("%u", if_refcount); | IF_DB_PRINTF("%u", if_refcount); | ||||
IF_DB_PRINTF("%d", if_index_reserved); | |||||
IF_DB_PRINTF("%p", if_softc); | IF_DB_PRINTF("%p", if_softc); | ||||
IF_DB_PRINTF("%p", if_l2com); | IF_DB_PRINTF("%p", if_l2com); | ||||
IF_DB_PRINTF("%p", if_llsoftc); | IF_DB_PRINTF("%p", if_llsoftc); | ||||
IF_DB_PRINTF("%d", if_amcount); | IF_DB_PRINTF("%d", if_amcount); | ||||
IF_DB_PRINTF("%p", if_addr); | IF_DB_PRINTF("%p", if_addr); | ||||
IF_DB_PRINTF("%p", if_broadcastaddr); | IF_DB_PRINTF("%p", if_broadcastaddr); | ||||
IF_DB_PRINTF("%p", if_afdata); | IF_DB_PRINTF("%p", if_afdata); | ||||
IF_DB_PRINTF("%d", if_afdata_initialized); | IF_DB_PRINTF("%d", if_afdata_initialized); | ||||
Show All 38 Lines | |||||
} | } | ||||
DB_SHOW_ALL_COMMAND(ifnets, db_show_all_ifnets) | DB_SHOW_ALL_COMMAND(ifnets, db_show_all_ifnets) | ||||
{ | { | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
u_short idx; | u_short idx; | ||||
for (idx = 1; idx <= if_index; idx++) { | for (idx = 1; idx <= if_index; idx++) { | ||||
ifp = ifindex_table[idx]; | ifp = ifindex_table[idx].ife_ifnet; | ||||
if (ifp == NULL) | if (ifp == NULL) | ||||
continue; | continue; | ||||
db_printf( "%20s ifp=%p\n", ifp->if_xname, ifp); | db_printf( "%20s ifp=%p\n", ifp->if_xname, ifp); | ||||
if (db_pager_quit) | if (db_pager_quit) | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
#endif /* DDB */ | #endif /* DDB */ |