Changeset View
Changeset View
Standalone View
Standalone View
head/sys/net/if_vlan.c
Show First 20 Lines • Show All 147 Lines • ▼ Show 20 Lines | for (_i = 0; \ | ||||
_i = (_touch && ((_trunk) != NULL) ? 0 : _i + 1), _touch = false) \ | _i = (_touch && ((_trunk) != NULL) ? 0 : _i + 1), _touch = false) \ | ||||
if (((_ifv) = CK_SLIST_FIRST(&(_trunk)->hash[_i])) != NULL && \ | if (((_ifv) = CK_SLIST_FIRST(&(_trunk)->hash[_i])) != NULL && \ | ||||
(_touch = true)) | (_touch = true)) | ||||
#endif /* VLAN_ARRAY */ | #endif /* VLAN_ARRAY */ | ||||
struct vlan_mc_entry { | struct vlan_mc_entry { | ||||
struct sockaddr_dl mc_addr; | struct sockaddr_dl mc_addr; | ||||
CK_SLIST_ENTRY(vlan_mc_entry) mc_entries; | CK_SLIST_ENTRY(vlan_mc_entry) mc_entries; | ||||
struct epoch_context mc_epoch_ctx; | |||||
}; | }; | ||||
struct ifvlan { | struct ifvlan { | ||||
struct ifvlantrunk *ifv_trunk; | struct ifvlantrunk *ifv_trunk; | ||||
struct ifnet *ifv_ifp; | struct ifnet *ifv_ifp; | ||||
#define TRUNK(ifv) ((ifv)->ifv_trunk) | #define TRUNK(ifv) ((ifv)->ifv_trunk) | ||||
#define PARENT(ifv) ((ifv)->ifv_trunk->parent) | #define PARENT(ifv) ((ifv)->ifv_trunk->parent) | ||||
void *ifv_cookie; | void *ifv_cookie; | ||||
▲ Show 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | |||||
VNET_DEFINE_STATIC(struct if_clone *, vlan_cloner); | VNET_DEFINE_STATIC(struct if_clone *, vlan_cloner); | ||||
#define V_vlan_cloner VNET(vlan_cloner) | #define V_vlan_cloner VNET(vlan_cloner) | ||||
#endif | #endif | ||||
#ifndef VLAN_ARRAY | #ifndef VLAN_ARRAY | ||||
#define HASH(n, m) ((((n) >> 8) ^ ((n) >> 4) ^ (n)) & (m)) | #define HASH(n, m) ((((n) >> 8) ^ ((n) >> 4) ^ (n)) & (m)) | ||||
static void | static void | ||||
vlan_mc_free(struct epoch_context *ctx) | |||||
{ | |||||
struct vlan_mc_entry *mc = __containerof(ctx, struct vlan_mc_entry, mc_epoch_ctx); | |||||
free(mc, M_VLAN); | |||||
} | |||||
static void | |||||
vlan_inithash(struct ifvlantrunk *trunk) | vlan_inithash(struct ifvlantrunk *trunk) | ||||
{ | { | ||||
int i, n; | int i, n; | ||||
/* | /* | ||||
* The trunk must not be locked here since we call malloc(M_WAITOK). | * The trunk must not be locked here since we call malloc(M_WAITOK). | ||||
* It is OK in case this function is called before the trunk struct | * It is OK in case this function is called before the trunk struct | ||||
* gets hooked up and becomes visible from other threads. | * gets hooked up and becomes visible from other threads. | ||||
▲ Show 20 Lines • Show All 239 Lines • ▼ Show 20 Lines | vlan_setmulti(struct ifnet *ifp) | ||||
ifp_p = PARENT(sc); | ifp_p = PARENT(sc); | ||||
CURVNET_SET_QUIET(ifp_p->if_vnet); | CURVNET_SET_QUIET(ifp_p->if_vnet); | ||||
/* First, remove any existing filter entries. */ | /* First, remove any existing filter entries. */ | ||||
while ((mc = CK_SLIST_FIRST(&sc->vlan_mc_listhead)) != NULL) { | while ((mc = CK_SLIST_FIRST(&sc->vlan_mc_listhead)) != NULL) { | ||||
CK_SLIST_REMOVE_HEAD(&sc->vlan_mc_listhead, mc_entries); | CK_SLIST_REMOVE_HEAD(&sc->vlan_mc_listhead, mc_entries); | ||||
(void)if_delmulti(ifp_p, (struct sockaddr *)&mc->mc_addr); | (void)if_delmulti(ifp_p, (struct sockaddr *)&mc->mc_addr); | ||||
NET_EPOCH_WAIT(); | epoch_call(net_epoch_preempt, &mc->mc_epoch_ctx, vlan_mc_free); | ||||
free(mc, M_VLAN); | |||||
} | } | ||||
/* Now program new ones. */ | /* Now program new ones. */ | ||||
IF_ADDR_WLOCK(ifp); | IF_ADDR_WLOCK(ifp); | ||||
CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { | CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { | ||||
if (ifma->ifma_addr->sa_family != AF_LINK) | if (ifma->ifma_addr->sa_family != AF_LINK) | ||||
continue; | continue; | ||||
mc = malloc(sizeof(struct vlan_mc_entry), M_VLAN, M_NOWAIT); | mc = malloc(sizeof(struct vlan_mc_entry), M_VLAN, M_NOWAIT); | ||||
▲ Show 20 Lines • Show All 895 Lines • ▼ Show 20 Lines | while ((mc = CK_SLIST_FIRST(&ifv->vlan_mc_listhead)) != NULL) { | ||||
error = if_delmulti(parent, | error = if_delmulti(parent, | ||||
(struct sockaddr *)&mc->mc_addr); | (struct sockaddr *)&mc->mc_addr); | ||||
if (error) | if (error) | ||||
if_printf(ifp, | if_printf(ifp, | ||||
"Failed to delete multicast address from parent: %d\n", | "Failed to delete multicast address from parent: %d\n", | ||||
error); | error); | ||||
} | } | ||||
CK_SLIST_REMOVE_HEAD(&ifv->vlan_mc_listhead, mc_entries); | CK_SLIST_REMOVE_HEAD(&ifv->vlan_mc_listhead, mc_entries); | ||||
NET_EPOCH_WAIT(); | epoch_call(net_epoch_preempt, &mc->mc_epoch_ctx, vlan_mc_free); | ||||
free(mc, M_VLAN); | |||||
} | } | ||||
vlan_setflags(ifp, 0); /* clear special flags on parent */ | vlan_setflags(ifp, 0); /* clear special flags on parent */ | ||||
vlan_remhash(trunk, ifv); | vlan_remhash(trunk, ifv); | ||||
ifv->ifv_trunk = NULL; | ifv->ifv_trunk = NULL; | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 439 Lines • Show Last 20 Lines |