diff options
author | sam <sam@FreeBSD.org> | 2003-10-29 19:03:58 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2003-10-29 19:03:58 +0000 |
commit | f65eafde266b11dfb1c6b136829eb1c959ed5cb8 (patch) | |
tree | e41755850b559ab970c28ea6fbc9672fe9c6316d /sys/netinet/ip_dummynet.c | |
parent | 357db6acd2358a0e0e437071b8caeac4b4d92a83 (diff) | |
download | FreeBSD-src-f65eafde266b11dfb1c6b136829eb1c959ed5cb8.zip FreeBSD-src-f65eafde266b11dfb1c6b136829eb1c959ed5cb8.tar.gz |
o add locking to protect routing table refcnt manipulations
o add some more debugging help for figuring out why folks are
getting complaints about releasing routing table entries with
a zero refcnt
o fix comment that talked about spl's
o remove duplicate define of DUMMYNET_DEBUG
Supported by: FreeBSD Foundation
Diffstat (limited to 'sys/netinet/ip_dummynet.c')
-rw-r--r-- | sys/netinet/ip_dummynet.c | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/sys/netinet/ip_dummynet.c b/sys/netinet/ip_dummynet.c index 7353865..93a4899 100644 --- a/sys/netinet/ip_dummynet.c +++ b/sys/netinet/ip_dummynet.c @@ -39,10 +39,7 @@ * + scheduler and dummynet functions; * + configuration and initialization. * - * NOTA BENE: critical sections are protected by splimp()/splx() - * pairs. One would think that splnet() is enough as for most of - * the netinet code, but it is not so because when used with - * bridging, dummynet is invoked at splimp(). + * NOTA BENE: critical sections are protected by the "dummynet lock". * * Most important Changes: * @@ -152,7 +149,6 @@ SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, red_max_pkt_size, CTLFLAG_RD, &red_max_pkt_size, 0, "RED Max packet size"); #endif -#define DUMMYNET_DEBUG #ifdef DUMMYNET_DEBUG int dummynet_debug = 0; #ifdef SYSCTL_NODE @@ -180,7 +176,7 @@ static struct mtx dummynet_mtx; static int config_pipe(struct dn_pipe *p); static int ip_dn_ctl(struct sockopt *sopt); -static void rt_unref(struct rtentry *); +static void rt_unref(struct rtentry *, const char *); static void dummynet(void *); static void dummynet_flush(void); void dummynet_drain(void); @@ -190,14 +186,16 @@ static void dn_rule_delete(void *); int if_tx_rdy(struct ifnet *ifp); static void -rt_unref(struct rtentry *rt) +rt_unref(struct rtentry *rt, const char *where) { if (rt == NULL) return ; - if (rt->rt_refcnt <= 0) - printf("dummynet: warning, refcnt now %ld, decreasing\n", - rt->rt_refcnt); - RTFREE(rt); + RT_LOCK(rt); + if (rt->rt_refcnt <= 0) { + printf("dummynet: warning, refcnt now %ld, decreasing (%s)\n", + rt->rt_refcnt, where); + } + RTFREE_LOCKED(rt); } /* @@ -452,7 +450,7 @@ transmit_event(struct dn_pipe *pipe) switch (pkt->dn_dir) { case DN_TO_IP_OUT: (void)ip_output((struct mbuf *)pkt, NULL, NULL, 0, NULL, NULL); - rt_unref (pkt->ro.ro_rt) ; + rt_unref (pkt->ro.ro_rt, __func__) ; break ; case DN_TO_IP_IN : @@ -1198,11 +1196,15 @@ dummynet_io(struct mbuf *m, int pipe_nr, int dir, struct ip_fw_args *fwa) * a pointer into *ro so it needs to be updated. */ pkt->ro = *(fwa->ro); - if (fwa->ro->ro_rt) - fwa->ro->ro_rt->rt_refcnt++ ; + if (pkt->ro.ro_rt) { + RT_LOCK(pkt->ro.ro_rt); + pkt->ro.ro_rt->rt_refcnt++ ; + KASSERT(pkt->ro.ro_rt->rt_refcnt > 0, + ("bogus refcnt %ld", pkt->ro.ro_rt->rt_refcnt)); + RT_UNLOCK(pkt->ro.ro_rt); + } if (fwa->dst == (struct sockaddr_in *)&fwa->ro->ro_dst) /* dst points into ro */ fwa->dst = (struct sockaddr_in *)&(pkt->ro.ro_dst) ; - pkt->dn_dst = fwa->dst; pkt->flags = fwa->flags; } @@ -1303,7 +1305,7 @@ dropit: */ #define DN_FREE_PKT(pkt) { \ struct dn_pkt *n = pkt ; \ - rt_unref ( n->ro.ro_rt ) ; \ + rt_unref ( n->ro.ro_rt, __func__ ) ; \ m_freem(n->dn_m); \ pkt = DN_NEXT(n) ; \ free(n, M_DUMMYNET) ; } |