ip_dummynet.c (132199) | ip_dummynet.c (133920) |
---|---|
1/* 2 * Copyright (c) 1998-2002 Luigi Rizzo, Universita` di Pisa 3 * Portions Copyright (c) 2000 Akamba Corp. 4 * All rights reserved 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 10 unchanged lines hidden (view full) --- 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * | 1/* 2 * Copyright (c) 1998-2002 Luigi Rizzo, Universita` di Pisa 3 * Portions Copyright (c) 2000 Akamba Corp. 4 * All rights reserved 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 10 unchanged lines hidden (view full) --- 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * |
27 * $FreeBSD: head/sys/netinet/ip_dummynet.c 132199 2004-07-15 08:26:07Z phk $ | 27 * $FreeBSD: head/sys/netinet/ip_dummynet.c 133920 2004-08-17 22:05:54Z andre $ |
28 */ 29 30#define DUMMYNET_DEBUG 31 32/* 33 * This module implements IP dummynet, a bandwidth limiter/delay emulator 34 * used in conjunction with the ipfw package. 35 * Description of the data structures used is in ip_dummynet.h --- 138 unchanged lines hidden (view full) --- 174#define DUMMYNET_LOCK_ASSERT() do { \ 175 mtx_assert(&dummynet_mtx, MA_OWNED); \ 176 NET_ASSERT_GIANT(); \ 177} while (0) 178 179static int config_pipe(struct dn_pipe *p); 180static int ip_dn_ctl(struct sockopt *sopt); 181 | 28 */ 29 30#define DUMMYNET_DEBUG 31 32/* 33 * This module implements IP dummynet, a bandwidth limiter/delay emulator 34 * used in conjunction with the ipfw package. 35 * Description of the data structures used is in ip_dummynet.h --- 138 unchanged lines hidden (view full) --- 174#define DUMMYNET_LOCK_ASSERT() do { \ 175 mtx_assert(&dummynet_mtx, MA_OWNED); \ 176 NET_ASSERT_GIANT(); \ 177} while (0) 178 179static int config_pipe(struct dn_pipe *p); 180static int ip_dn_ctl(struct sockopt *sopt); 181 |
182static void rt_unref(struct rtentry *, const char *); | |
183static void dummynet(void *); 184static void dummynet_flush(void); 185void dummynet_drain(void); 186static ip_dn_io_t dummynet_io; 187static void dn_rule_delete(void *); 188 189int if_tx_rdy(struct ifnet *ifp); 190 | 182static void dummynet(void *); 183static void dummynet_flush(void); 184void dummynet_drain(void); 185static ip_dn_io_t dummynet_io; 186static void dn_rule_delete(void *); 187 188int if_tx_rdy(struct ifnet *ifp); 189 |
191static void 192rt_unref(struct rtentry *rt, const char *where) 193{ 194 if (rt == NULL) 195 return ; 196 RT_LOCK(rt); 197 if (rt->rt_refcnt <= 0) { 198 printf("dummynet: warning, refcnt now %ld, decreasing (%s)\n", 199 rt->rt_refcnt, where); 200 } 201 RTFREE_LOCKED(rt); 202} 203 | |
204/* 205 * Heap management functions. 206 * 207 * In the heap, first node is element 0. Children of i are 2i+1 and 2i+2. 208 * Some macros help finding parent/children so we can optimize them. 209 * 210 * heap_init() is called to expand the heap when needed. 211 * Increment size in blocks of 16 entries. --- 229 unchanged lines hidden (view full) --- 441 * before passing pkts out, because this might trigger recursive 442 * invocations of the procedures. 443 */ 444static void 445transmit_event(struct dn_pipe *pipe) 446{ 447 struct mbuf *m ; 448 struct dn_pkt_tag *pkt ; | 190/* 191 * Heap management functions. 192 * 193 * In the heap, first node is element 0. Children of i are 2i+1 and 2i+2. 194 * Some macros help finding parent/children so we can optimize them. 195 * 196 * heap_init() is called to expand the heap when needed. 197 * Increment size in blocks of 16 entries. --- 229 unchanged lines hidden (view full) --- 427 * before passing pkts out, because this might trigger recursive 428 * invocations of the procedures. 429 */ 430static void 431transmit_event(struct dn_pipe *pipe) 432{ 433 struct mbuf *m ; 434 struct dn_pkt_tag *pkt ; |
435 struct ip *ip; |
|
449 450 DUMMYNET_LOCK_ASSERT(); 451 452 while ( (m = pipe->head) ) { 453 pkt = dn_tag_get(m); 454 if ( !DN_KEY_LEQ(pkt->output_time, curr_time) ) 455 break; 456 /* --- 6 unchanged lines hidden (view full) --- 463 /* XXX: drop the lock for now to avoid LOR's */ 464 DUMMYNET_UNLOCK(); 465 switch (pkt->dn_dir) { 466 case DN_TO_IP_OUT: 467 (void)ip_output(m, NULL, NULL, pkt->flags, NULL, NULL); 468 break ; 469 470 case DN_TO_IP_IN : | 436 437 DUMMYNET_LOCK_ASSERT(); 438 439 while ( (m = pipe->head) ) { 440 pkt = dn_tag_get(m); 441 if ( !DN_KEY_LEQ(pkt->output_time, curr_time) ) 442 break; 443 /* --- 6 unchanged lines hidden (view full) --- 450 /* XXX: drop the lock for now to avoid LOR's */ 451 DUMMYNET_UNLOCK(); 452 switch (pkt->dn_dir) { 453 case DN_TO_IP_OUT: 454 (void)ip_output(m, NULL, NULL, pkt->flags, NULL, NULL); 455 break ; 456 457 case DN_TO_IP_IN : |
458 ip = mtod(m, struct ip *); 459 ip->ip_len = htons(ip->ip_len); 460 ip->ip_off = htons(ip->ip_off); |
|
471 ip_input(m) ; 472 break ; 473 474 case DN_TO_BDG_FWD : 475 /* 476 * The bridge requires/assumes the Ethernet header is 477 * contiguous in the first mbuf header. Insure this is true. 478 */ --- 643 unchanged lines hidden (view full) --- 1122 * depending on whether WF2Q or fixed bw is used. 1123 * 1124 * pipe_nr pipe or queue the packet is destined for. 1125 * dir where shall we send the packet after dummynet. 1126 * m the mbuf with the packet 1127 * ifp the 'ifp' parameter from the caller. 1128 * NULL in ip_input, destination interface in ip_output, 1129 * real_dst in bdg_forward | 461 ip_input(m) ; 462 break ; 463 464 case DN_TO_BDG_FWD : 465 /* 466 * The bridge requires/assumes the Ethernet header is 467 * contiguous in the first mbuf header. Insure this is true. 468 */ --- 643 unchanged lines hidden (view full) --- 1112 * depending on whether WF2Q or fixed bw is used. 1113 * 1114 * pipe_nr pipe or queue the packet is destined for. 1115 * dir where shall we send the packet after dummynet. 1116 * m the mbuf with the packet 1117 * ifp the 'ifp' parameter from the caller. 1118 * NULL in ip_input, destination interface in ip_output, 1119 * real_dst in bdg_forward |
1130 * ro route parameter (only used in ip_output, NULL otherwise) 1131 * dst destination address, only used by ip_output | |
1132 * rule matching rule, in case of multiple passes 1133 * flags flags from the caller, only used in ip_output 1134 * 1135 */ 1136static int 1137dummynet_io(struct mbuf *m, int pipe_nr, int dir, struct ip_fw_args *fwa) 1138{ 1139 struct dn_pkt_tag *pkt; --- 69 unchanged lines hidden (view full) --- 1209 1210 pkt = (struct dn_pkt_tag *)(mtag+1); 1211 /* ok, i can handle the pkt now... */ 1212 /* build and enqueue packet + parameters */ 1213 pkt->rule = fwa->rule ; 1214 pkt->dn_dir = dir ; 1215 1216 pkt->ifp = fwa->oif; | 1120 * rule matching rule, in case of multiple passes 1121 * flags flags from the caller, only used in ip_output 1122 * 1123 */ 1124static int 1125dummynet_io(struct mbuf *m, int pipe_nr, int dir, struct ip_fw_args *fwa) 1126{ 1127 struct dn_pkt_tag *pkt; --- 69 unchanged lines hidden (view full) --- 1197 1198 pkt = (struct dn_pkt_tag *)(mtag+1); 1199 /* ok, i can handle the pkt now... */ 1200 /* build and enqueue packet + parameters */ 1201 pkt->rule = fwa->rule ; 1202 pkt->dn_dir = dir ; 1203 1204 pkt->ifp = fwa->oif; |
1217 if (dir == DN_TO_IP_OUT) { 1218 /* 1219 * We need to copy *ro because for ICMP pkts (and maybe others) 1220 * the caller passed a pointer into the stack; dst might also be 1221 * a pointer into *ro so it needs to be updated. 1222 */ 1223 pkt->ro = *(fwa->ro); 1224 if (pkt->ro.ro_rt) { 1225 RT_LOCK(pkt->ro.ro_rt); 1226 RT_ADDREF(pkt->ro.ro_rt) ; 1227 RT_UNLOCK(pkt->ro.ro_rt); 1228 } 1229 if (fwa->dst == (struct sockaddr_in *)&fwa->ro->ro_dst) /* dst points into ro */ 1230 fwa->dst = (struct sockaddr_in *)&(pkt->ro.ro_dst) ; 1231 pkt->dn_dst = fwa->dst; | 1205 if (dir == DN_TO_IP_OUT) |
1232 pkt->flags = fwa->flags; | 1206 pkt->flags = fwa->flags; |
1233 } | |
1234 if (q->head == NULL) 1235 q->head = m; 1236 else 1237 q->tail->m_nextpkt = m; 1238 q->tail = m; 1239 q->len++; 1240 q->len_bytes += len ; 1241 --- 80 unchanged lines hidden (view full) --- 1322 return ( (fs && (fs->flags_fs & DN_NOERROR)) ? 0 : ENOBUFS); 1323} 1324 1325/* 1326 * Below, the rt_unref is only needed when (pkt->dn_dir == DN_TO_IP_OUT) 1327 * Doing this would probably save us the initial bzero of dn_pkt 1328 */ 1329#define DN_FREE_PKT(_m) do { \ | 1207 if (q->head == NULL) 1208 q->head = m; 1209 else 1210 q->tail->m_nextpkt = m; 1211 q->tail = m; 1212 q->len++; 1213 q->len_bytes += len ; 1214 --- 80 unchanged lines hidden (view full) --- 1295 return ( (fs && (fs->flags_fs & DN_NOERROR)) ? 0 : ENOBUFS); 1296} 1297 1298/* 1299 * Below, the rt_unref is only needed when (pkt->dn_dir == DN_TO_IP_OUT) 1300 * Doing this would probably save us the initial bzero of dn_pkt 1301 */ 1302#define DN_FREE_PKT(_m) do { \ |
1330 rt_unref(dn_tag_get(_m)->ro.ro_rt, __func__); \ | |
1331 m_freem(_m); \ 1332} while (0) 1333 1334/* 1335 * Dispose all packets and flow_queues on a flow_set. 1336 * If all=1, also remove red lookup table and other storage, 1337 * including the descriptor itself. 1338 * For the one in dn_pipe MUST also cleanup ready_heap... --- 747 unchanged lines hidden (view full) --- 2086 return 0 ; 2087} 2088 2089static moduledata_t dummynet_mod = { 2090 "dummynet", 2091 dummynet_modevent, 2092 NULL 2093}; | 1303 m_freem(_m); \ 1304} while (0) 1305 1306/* 1307 * Dispose all packets and flow_queues on a flow_set. 1308 * If all=1, also remove red lookup table and other storage, 1309 * including the descriptor itself. 1310 * For the one in dn_pipe MUST also cleanup ready_heap... --- 747 unchanged lines hidden (view full) --- 2058 return 0 ; 2059} 2060 2061static moduledata_t dummynet_mod = { 2062 "dummynet", 2063 dummynet_modevent, 2064 NULL 2065}; |
2094DECLARE_MODULE(dummynet, dummynet_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 2095MODULE_DEPEND(dummynet, ipfw, 1, 1, 1); | 2066DECLARE_MODULE(dummynet, dummynet_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); 2067MODULE_DEPEND(dummynet, ipfw, 2, 2, 2); |
2096MODULE_VERSION(dummynet, 1); | 2068MODULE_VERSION(dummynet, 1); |