Changeset View
Changeset View
Standalone View
Standalone View
sys/net/if.c
Show First 20 Lines • Show All 1,494 Lines • ▼ Show 20 Lines | if_addgroup(struct ifnet *ifp, const char *groupname) | ||||
if (new) | if (new) | ||||
EVENTHANDLER_INVOKE(group_attach_event, ifg); | EVENTHANDLER_INVOKE(group_attach_event, ifg); | ||||
EVENTHANDLER_INVOKE(group_change_event, groupname); | EVENTHANDLER_INVOKE(group_change_event, groupname); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Remove a group from an interface | * Helper function to release group memory in if_delgroup and if_delgroups. | ||||
* Note this function assumes the IFNET lock is held, and will release it in | |||||
jhb: Better to add an IFNET_WLOCK_ASSERT() or some such than to just document it in a comment. | |||||
* order to call group event handlers. | |||||
*/ | */ | ||||
int | static void | ||||
if_delgroup(struct ifnet *ifp, const char *groupname) | if_freegroup(struct ifnet *ifp, struct ifg_list *ifgl, const char *groupname) | ||||
{ | { | ||||
struct ifg_list *ifgl; | |||||
struct ifg_member *ifgm; | struct ifg_member *ifgm; | ||||
int freeifgl; | int freeifgl; | ||||
IFNET_WLOCK(); | /* Ensure we have the IFNET lock */ | ||||
CK_STAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) | IFNET_WLOCK_ASSERT(); | ||||
if (!strcmp(ifgl->ifgl_group->ifg_group, groupname)) | |||||
break; | |||||
if (ifgl == NULL) { | |||||
IFNET_WUNLOCK(); | |||||
return (ENOENT); | |||||
} | |||||
freeifgl = 0; | freeifgl = 0; | ||||
IF_ADDR_WLOCK(ifp); | IF_ADDR_WLOCK(ifp); | ||||
CK_STAILQ_REMOVE(&ifp->if_groups, ifgl, ifg_list, ifgl_next); | CK_STAILQ_REMOVE(&ifp->if_groups, ifgl, ifg_list, ifgl_next); | ||||
IF_ADDR_WUNLOCK(ifp); | IF_ADDR_WUNLOCK(ifp); | ||||
CK_STAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next) | CK_STAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next) | ||||
if (ifgm->ifgm_ifp == ifp) | if (ifgm->ifgm_ifp == ifp) | ||||
break; | break; | ||||
if (ifgm != NULL) | if (ifgm != NULL) | ||||
CK_STAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifg_member, ifgm_next); | CK_STAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifg_member, ifgm_next); | ||||
if (--ifgl->ifgl_group->ifg_refcnt == 0) { | if (--ifgl->ifgl_group->ifg_refcnt == 0) { | ||||
CK_STAILQ_REMOVE(&V_ifg_head, ifgl->ifgl_group, ifg_group, ifg_next); | CK_STAILQ_REMOVE(&V_ifg_head, ifgl->ifgl_group, ifg_group, ifg_next); | ||||
freeifgl = 1; | freeifgl = 1; | ||||
} | } | ||||
/* Drop the lock so that the event handler can be called */ | |||||
IFNET_WUNLOCK(); | IFNET_WUNLOCK(); | ||||
epoch_wait_preempt(net_epoch_preempt); | epoch_wait_preempt(net_epoch_preempt); | ||||
if (freeifgl) { | if (freeifgl) { | ||||
EVENTHANDLER_INVOKE(group_detach_event, ifgl->ifgl_group); | EVENTHANDLER_INVOKE(group_detach_event, ifgl->ifgl_group); | ||||
free(ifgl->ifgl_group, M_TEMP); | free(ifgl->ifgl_group, M_TEMP); | ||||
} | } | ||||
free(ifgm, M_TEMP); | free(ifgm, M_TEMP); | ||||
free(ifgl, M_TEMP); | free(ifgl, M_TEMP); | ||||
EVENTHANDLER_INVOKE(group_change_event, groupname); | EVENTHANDLER_INVOKE(group_change_event, groupname); | ||||
} | |||||
/* | |||||
* Remove a group from an interface | |||||
*/ | |||||
int | |||||
if_delgroup(struct ifnet *ifp, const char *groupname) | |||||
{ | |||||
struct ifg_list *ifgl; | |||||
IFNET_WLOCK(); | |||||
CK_STAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) | |||||
if (!strcmp(ifgl->ifgl_group->ifg_group, groupname)) | |||||
break; | |||||
if (ifgl == NULL) { | |||||
IFNET_WUNLOCK(); | |||||
return (ENOENT); | |||||
} | |||||
/* if_freegroup will call IFNET_WUNLOCK() */ | |||||
if_freegroup(ifp, ifgl, groupname); | |||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Remove an interface from all groups | * Remove an interface from all groups | ||||
*/ | */ | ||||
static void | static void | ||||
if_delgroups(struct ifnet *ifp) | if_delgroups(struct ifnet *ifp) | ||||
{ | { | ||||
struct ifg_list *ifgl; | struct ifg_list *ifgl; | ||||
struct ifg_member *ifgm; | |||||
char groupname[IFNAMSIZ]; | char groupname[IFNAMSIZ]; | ||||
int ifglfree; | |||||
IFNET_WLOCK(); | IFNET_WLOCK(); | ||||
while (!CK_STAILQ_EMPTY(&ifp->if_groups)) { | while (!CK_STAILQ_EMPTY(&ifp->if_groups)) { | ||||
ifgl = CK_STAILQ_FIRST(&ifp->if_groups); | ifgl = CK_STAILQ_FIRST(&ifp->if_groups); | ||||
strlcpy(groupname, ifgl->ifgl_group->ifg_group, IFNAMSIZ); | strlcpy(groupname, ifgl->ifgl_group->ifg_group, IFNAMSIZ); | ||||
IF_ADDR_WLOCK(ifp); | /* if_freegroup calls IFNET_WUNLOCK() */ | ||||
CK_STAILQ_REMOVE(&ifp->if_groups, ifgl, ifg_list, ifgl_next); | if_freegroup(ifp, ifgl, groupname); | ||||
IF_ADDR_WUNLOCK(ifp); | |||||
CK_STAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next) | |||||
if (ifgm->ifgm_ifp == ifp) | |||||
break; | |||||
if (ifgm != NULL) | |||||
CK_STAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifg_member, | |||||
ifgm_next); | |||||
ifglfree = 0; | |||||
if (--ifgl->ifgl_group->ifg_refcnt == 0) { | |||||
CK_STAILQ_REMOVE(&V_ifg_head, ifgl->ifgl_group, ifg_group, ifg_next); | |||||
ifglfree = 1; | |||||
} | |||||
IFNET_WUNLOCK(); | |||||
epoch_wait_preempt(net_epoch_preempt); | |||||
free(ifgm, M_TEMP); | |||||
if (ifglfree) { | |||||
EVENTHANDLER_INVOKE(group_detach_event, | |||||
ifgl->ifgl_group); | |||||
free(ifgl->ifgl_group, M_TEMP); | |||||
} | |||||
EVENTHANDLER_INVOKE(group_change_event, groupname); | |||||
IFNET_WLOCK(); | IFNET_WLOCK(); | ||||
} | } | ||||
IFNET_WUNLOCK(); | IFNET_WUNLOCK(); | ||||
} | } | ||||
static char * | static char * | ||||
ifgr_group_get(void *ifgrp) | ifgr_group_get(void *ifgrp) | ||||
▲ Show 20 Lines • Show All 2,955 Lines • Show Last 20 Lines |
Better to add an IFNET_WLOCK_ASSERT() or some such than to just document it in a comment.