Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/ip_mroute.c
Show First 20 Lines • Show All 311 Lines • ▼ Show 20 Lines | |||||
static int add_vif(struct vifctl *); | static int add_vif(struct vifctl *); | ||||
static void bw_meter_prepare_upcall(struct bw_meter *, struct timeval *); | static void bw_meter_prepare_upcall(struct bw_meter *, struct timeval *); | ||||
static void bw_meter_geq_receive_packet(struct bw_meter *, int, | static void bw_meter_geq_receive_packet(struct bw_meter *, int, | ||||
struct timeval *); | struct timeval *); | ||||
static void bw_upcalls_send(void); | static void bw_upcalls_send(void); | ||||
static int del_bw_upcall(struct bw_upcall *); | static int del_bw_upcall(struct bw_upcall *); | ||||
static int del_mfc(struct mfcctl2 *); | static int del_mfc(struct mfcctl2 *); | ||||
static int del_vif(vifi_t); | static int del_vif(vifi_t); | ||||
static int del_vif_locked(vifi_t, struct ifnet **); | static int del_vif_locked(vifi_t, struct ifnet **, struct ifnet **); | ||||
static void expire_bw_upcalls_send(void *); | static void expire_bw_upcalls_send(void *); | ||||
static void expire_mfc(struct mfc *); | static void expire_mfc(struct mfc *); | ||||
static void expire_upcalls(void *); | static void expire_upcalls(void *); | ||||
static void free_bw_list(struct bw_meter *); | static void free_bw_list(struct bw_meter *); | ||||
static int get_sg_cnt(struct sioc_sg_req *); | static int get_sg_cnt(struct sioc_sg_req *); | ||||
static int get_vif_cnt(struct sioc_vif_req *); | static int get_vif_cnt(struct sioc_vif_req *); | ||||
static void if_detached_event(void *, struct ifnet *); | static void if_detached_event(void *, struct ifnet *); | ||||
static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *, vifi_t); | static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *, vifi_t); | ||||
▲ Show 20 Lines • Show All 284 Lines • ▼ Show 20 Lines | get_vif_cnt(struct sioc_vif_req *req) | ||||
return 0; | return 0; | ||||
} | } | ||||
static void | static void | ||||
if_detached_event(void *arg __unused, struct ifnet *ifp) | if_detached_event(void *arg __unused, struct ifnet *ifp) | ||||
{ | { | ||||
vifi_t vifi; | vifi_t vifi; | ||||
u_long i, vifi_cnt = 0; | u_long i, vifi_cnt = 0; | ||||
struct ifnet *free_ptr; | struct ifnet *free_ptr, *multi_leave; | ||||
MRW_WLOCK(); | MRW_WLOCK(); | ||||
if (V_ip_mrouter == NULL) { | if (V_ip_mrouter == NULL) { | ||||
MRW_WUNLOCK(); | MRW_WUNLOCK(); | ||||
return; | return; | ||||
} | } | ||||
/* | /* | ||||
* Tear down multicast forwarder state associated with this ifnet. | * Tear down multicast forwarder state associated with this ifnet. | ||||
* 1. Walk the vif list, matching vifs against this ifnet. | * 1. Walk the vif list, matching vifs against this ifnet. | ||||
* 2. Walk the multicast forwarding cache (mfc) looking for | * 2. Walk the multicast forwarding cache (mfc) looking for | ||||
* inner matches with this vif's index. | * inner matches with this vif's index. | ||||
* 3. Expire any matching multicast forwarding cache entries. | * 3. Expire any matching multicast forwarding cache entries. | ||||
* 4. Free vif state. This should disable ALLMULTI on the interface. | * 4. Free vif state. This should disable ALLMULTI on the interface. | ||||
*/ | */ | ||||
restart: | |||||
for (vifi = 0; vifi < V_numvifs; vifi++) { | for (vifi = 0; vifi < V_numvifs; vifi++) { | ||||
if (V_viftable[vifi].v_ifp != ifp) | if (V_viftable[vifi].v_ifp != ifp) | ||||
continue; | continue; | ||||
for (i = 0; i < mfchashsize; i++) { | for (i = 0; i < mfchashsize; i++) { | ||||
struct mfc *rt, *nrt; | struct mfc *rt, *nrt; | ||||
LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) { | LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) { | ||||
if (rt->mfc_parent == vifi) { | if (rt->mfc_parent == vifi) { | ||||
expire_mfc(rt); | expire_mfc(rt); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
del_vif_locked(vifi, &free_ptr); | del_vif_locked(vifi, &multi_leave, &free_ptr); | ||||
if (free_ptr != NULL) | if (free_ptr != NULL) | ||||
vifi_cnt++; | vifi_cnt++; | ||||
if (multi_leave) { | |||||
MRW_WUNLOCK(); | |||||
if_allmulti(multi_leave, 0); | |||||
MRW_WLOCK(); | |||||
goto restart; | |||||
} | } | ||||
} | |||||
MRW_WUNLOCK(); | MRW_WUNLOCK(); | ||||
/* | /* | ||||
* Free IFP. We don't have to use free_ptr here as it is the same | * Free IFP. We don't have to use free_ptr here as it is the same | ||||
* that ifp. Perform free as many times as required in case | * that ifp. Perform free as many times as required in case | ||||
* refcount is greater than 1. | * refcount is greater than 1. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 331 Lines • ▼ Show 20 Lines | add_vif(struct vifctl *vifcp) | ||||
return 0; | return 0; | ||||
} | } | ||||
/* | /* | ||||
* Delete a vif from the vif table | * Delete a vif from the vif table | ||||
*/ | */ | ||||
static int | static int | ||||
del_vif_locked(vifi_t vifi, struct ifnet **ifp_free) | del_vif_locked(vifi_t vifi, struct ifnet **ifp_multi_leave, struct ifnet **ifp_free) | ||||
{ | { | ||||
struct vif *vifp; | struct vif *vifp; | ||||
*ifp_free = NULL; | *ifp_free = NULL; | ||||
*ifp_multi_leave = NULL; | |||||
MRW_WLOCK_ASSERT(); | MRW_WLOCK_ASSERT(); | ||||
if (vifi >= V_numvifs) { | if (vifi >= V_numvifs) { | ||||
return EINVAL; | return EINVAL; | ||||
} | } | ||||
vifp = &V_viftable[vifi]; | vifp = &V_viftable[vifi]; | ||||
if (in_nullhost(vifp->v_lcl_addr)) { | if (in_nullhost(vifp->v_lcl_addr)) { | ||||
return EADDRNOTAVAIL; | return EADDRNOTAVAIL; | ||||
} | } | ||||
if (!(vifp->v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) | if (!(vifp->v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) | ||||
if_allmulti(vifp->v_ifp, 0); | *ifp_multi_leave = vifp->v_ifp; | ||||
if (vifp->v_flags & VIFF_REGISTER) { | if (vifp->v_flags & VIFF_REGISTER) { | ||||
V_reg_vif_num = VIFI_INVALID; | V_reg_vif_num = VIFI_INVALID; | ||||
if (vifp->v_ifp) { | if (vifp->v_ifp) { | ||||
if (vifp->v_ifp == V_multicast_register_if) | if (vifp->v_ifp == V_multicast_register_if) | ||||
V_multicast_register_if = NULL; | V_multicast_register_if = NULL; | ||||
*ifp_free = vifp->v_ifp; | *ifp_free = vifp->v_ifp; | ||||
} | } | ||||
Show All 13 Lines | del_vif_locked(vifi_t vifi, struct ifnet **ifp_multi_leave, struct ifnet **ifp_free) | ||||
return 0; | return 0; | ||||
} | } | ||||
static int | static int | ||||
del_vif(vifi_t vifi) | del_vif(vifi_t vifi) | ||||
{ | { | ||||
int cc; | int cc; | ||||
struct ifnet *free_ptr; | struct ifnet *free_ptr, *multi_leave; | ||||
MRW_WLOCK(); | MRW_WLOCK(); | ||||
cc = del_vif_locked(vifi, &free_ptr); | cc = del_vif_locked(vifi, &multi_leave, &free_ptr); | ||||
MRW_WUNLOCK(); | MRW_WUNLOCK(); | ||||
if (free_ptr) | if (multi_leave) | ||||
if_allmulti(multi_leave, 0); | |||||
if (free_ptr) { | |||||
if_free(free_ptr); | if_free(free_ptr); | ||||
} | |||||
return cc; | return cc; | ||||
} | } | ||||
/* | /* | ||||
* update an mfc entry without resetting counters and S,G addresses. | * update an mfc entry without resetting counters and S,G addresses. | ||||
*/ | */ | ||||
static void | static void | ||||
▲ Show 20 Lines • Show All 1,828 Lines • Show Last 20 Lines |