ip_dummynet.c (201122) | ip_dummynet.c (201527) |
---|---|
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: --- 12 unchanged lines hidden (view full) --- 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 28#include <sys/cdefs.h> | 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: --- 12 unchanged lines hidden (view full) --- 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 28#include <sys/cdefs.h> |
29__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_dummynet.c 201122 2009-12-28 10:47:04Z luigi $"); | 29__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_dummynet.c 201527 2010-01-04 19:01:22Z luigi $"); |
30 31#define DUMMYNET_DEBUG 32 33#include "opt_inet6.h" 34 35/* 36 * This module implements IP dummynet, a bandwidth limiter/delay emulator 37 * used in conjunction with the ipfw package. --- 419 unchanged lines hidden (view full) --- 457 bzero(h, sizeof(*h) ); 458} 459 460/* 461 * --- end of heap management functions --- 462 */ 463 464/* | 30 31#define DUMMYNET_DEBUG 32 33#include "opt_inet6.h" 34 35/* 36 * This module implements IP dummynet, a bandwidth limiter/delay emulator 37 * used in conjunction with the ipfw package. --- 419 unchanged lines hidden (view full) --- 457 bzero(h, sizeof(*h) ); 458} 459 460/* 461 * --- end of heap management functions --- 462 */ 463 464/* |
465 * Dispose a packet in dummynet. Use an inline functions so if we | 465 * Dispose a list of packet. Use an inline functions so if we |
466 * need to free extra state associated to a packet, this is a 467 * central point to do it. 468 */ | 466 * need to free extra state associated to a packet, this is a 467 * central point to do it. 468 */ |
469static __inline void *dn_free_pkt(struct mbuf *m) 470{ 471 m_freem(m); 472 return NULL; 473} | |
474 475static __inline void dn_free_pkts(struct mbuf *mnext) 476{ 477 struct mbuf *m; 478 479 while ((m = mnext) != NULL) { 480 mnext = m->m_nextpkt; | 469 470static __inline void dn_free_pkts(struct mbuf *mnext) 471{ 472 struct mbuf *m; 473 474 while ((m = mnext) != NULL) { 475 mnext = m->m_nextpkt; |
481 dn_free_pkt(m); | 476 FREE_PKT(m); |
482 } 483} 484 485/* 486 * Return the mbuf tag holding the dummynet state. As an optimization 487 * this is assumed to be the first tag on the list. If this turns out 488 * wrong we'll need to search the list. 489 */ --- 473 unchanged lines hidden (view full) --- 963static void 964dummynet_send(struct mbuf *m) 965{ 966 struct mbuf *n; 967 968 for (; m != NULL; m = n) { 969 struct ifnet *ifp; 970 int dst; | 477 } 478} 479 480/* 481 * Return the mbuf tag holding the dummynet state. As an optimization 482 * this is assumed to be the first tag on the list. If this turns out 483 * wrong we'll need to search the list. 484 */ --- 473 unchanged lines hidden (view full) --- 958static void 959dummynet_send(struct mbuf *m) 960{ 961 struct mbuf *n; 962 963 for (; m != NULL; m = n) { 964 struct ifnet *ifp; 965 int dst; |
966 struct m_tag *tag; |
|
971 972 n = m->m_nextpkt; 973 m->m_nextpkt = NULL; | 967 968 n = m->m_nextpkt; 969 m->m_nextpkt = NULL; |
974 if (m_tag_first(m) == NULL) { | 970 tag = m_tag_first(m); 971 if (tag == NULL) { |
975 dst = DIR_DROP; 976 } else { 977 struct dn_pkt_tag *pkt = dn_tag_get(m); | 972 dst = DIR_DROP; 973 } else { 974 struct dn_pkt_tag *pkt = dn_tag_get(m); |
975 /* extract the dummynet info, rename the tag */ |
|
978 dst = pkt->dn_dir; 979 ifp = pkt->ifp; | 976 dst = pkt->dn_dir; 977 ifp = pkt->ifp; |
978 /* rename the tag so it carries reinject info */ 979 tag->m_tag_cookie = MTAG_IPFW_RULE; 980 tag->m_tag_id = 0; |
|
980 } 981 982 switch (dst) { 983 case DIR_OUT: | 981 } 982 983 switch (dst) { 984 case DIR_OUT: |
985 SET_HOST_IPLEN(mtod(m, struct ip *)); |
|
984 ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); 985 break ; 986 case DIR_IN : 987 /* put header in network format for ip_input() */ | 986 ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); 987 break ; 988 case DIR_IN : 989 /* put header in network format for ip_input() */ |
988 SET_NET_IPLEN(mtod(m, struct ip *)); | 990 //SET_NET_IPLEN(mtod(m, struct ip *)); |
989 netisr_dispatch(NETISR_IP, m); 990 break; 991#ifdef INET6 992 case DIR_IN | PROTO_IPV6: 993 netisr_dispatch(NETISR_IPV6, m); 994 break; 995 996 case DIR_OUT | PROTO_IPV6: | 991 netisr_dispatch(NETISR_IP, m); 992 break; 993#ifdef INET6 994 case DIR_IN | PROTO_IPV6: 995 netisr_dispatch(NETISR_IPV6, m); 996 break; 997 998 case DIR_OUT | PROTO_IPV6: |
999 SET_HOST_IPLEN(mtod(m, struct ip *)); |
|
997 ip6_output(m, NULL, NULL, IPV6_FORWARDING, NULL, NULL, NULL); 998 break; 999#endif 1000 case DIR_FWD | PROTO_IFB: /* DN_TO_IFB_FWD: */ 1001 if (bridge_dn_p != NULL) 1002 ((*bridge_dn_p)(m, ifp)); 1003 else 1004 printf("dummynet: if_bridge not loaded\n"); --- 14 unchanged lines hidden (view full) --- 1019 ether_demux(m->m_pkthdr.rcvif, m); 1020 break; 1021 case DIR_OUT | PROTO_LAYER2: /* N_TO_ETH_OUT: */ 1022 ether_output_frame(ifp, m); 1023 break; 1024 1025 case DIR_DROP: 1026 /* drop the packet after some time */ | 1000 ip6_output(m, NULL, NULL, IPV6_FORWARDING, NULL, NULL, NULL); 1001 break; 1002#endif 1003 case DIR_FWD | PROTO_IFB: /* DN_TO_IFB_FWD: */ 1004 if (bridge_dn_p != NULL) 1005 ((*bridge_dn_p)(m, ifp)); 1006 else 1007 printf("dummynet: if_bridge not loaded\n"); --- 14 unchanged lines hidden (view full) --- 1022 ether_demux(m->m_pkthdr.rcvif, m); 1023 break; 1024 case DIR_OUT | PROTO_LAYER2: /* N_TO_ETH_OUT: */ 1025 ether_output_frame(ifp, m); 1026 break; 1027 1028 case DIR_DROP: 1029 /* drop the packet after some time */ |
1027 dn_free_pkt(m); | 1030 FREE_PKT(m); |
1028 break; 1029 1030 default: 1031 printf("dummynet: bad switch %d!\n", dst); | 1031 break; 1032 1033 default: 1034 printf("dummynet: bad switch %d!\n", dst); |
1032 dn_free_pkt(m); | 1035 FREE_PKT(m); |
1033 break; 1034 } 1035 } 1036} 1037 1038/* 1039 * Unconditionally expire empty queues in case of shortage. 1040 * Returns the number of queues freed. --- 316 unchanged lines hidden (view full) --- 1357{ 1358 struct mbuf *m = *m0, *head = NULL, *tail = NULL; 1359 struct dn_pkt_tag *pkt; 1360 struct m_tag *mtag; 1361 struct dn_flow_set *fs = NULL; 1362 struct dn_pipe *pipe; 1363 uint64_t len = m->m_pkthdr.len; 1364 struct dn_flow_queue *q = NULL; | 1036 break; 1037 } 1038 } 1039} 1040 1041/* 1042 * Unconditionally expire empty queues in case of shortage. 1043 * Returns the number of queues freed. --- 316 unchanged lines hidden (view full) --- 1360{ 1361 struct mbuf *m = *m0, *head = NULL, *tail = NULL; 1362 struct dn_pkt_tag *pkt; 1363 struct m_tag *mtag; 1364 struct dn_flow_set *fs = NULL; 1365 struct dn_pipe *pipe; 1366 uint64_t len = m->m_pkthdr.len; 1367 struct dn_flow_queue *q = NULL; |
1365 int is_pipe = fwa->cookie & 0x8000000 ? 0 : 1; | 1368 int is_pipe = fwa->rule.info & IPFW_IS_PIPE; |
1366 1367 KASSERT(m->m_nextpkt == NULL, 1368 ("dummynet_io: mbuf queue passed to dummynet")); 1369 1370 DUMMYNET_LOCK(); 1371 io_pkt++; 1372 /* 1373 * This is a dummynet rule, so we expect an O_PIPE or O_QUEUE rule. | 1369 1370 KASSERT(m->m_nextpkt == NULL, 1371 ("dummynet_io: mbuf queue passed to dummynet")); 1372 1373 DUMMYNET_LOCK(); 1374 io_pkt++; 1375 /* 1376 * This is a dummynet rule, so we expect an O_PIPE or O_QUEUE rule. |
1374 * 1375 * XXXGL: probably the pipe->fs and fs->pipe logic here 1376 * below can be simplified. | |
1377 */ 1378 if (is_pipe) { | 1377 */ 1378 if (is_pipe) { |
1379 pipe = locate_pipe(fwa->cookie & 0xffff); | 1379 pipe = locate_pipe(fwa->rule.info & IPFW_INFO_MASK); |
1380 if (pipe != NULL) 1381 fs = &(pipe->fs); 1382 } else | 1380 if (pipe != NULL) 1381 fs = &(pipe->fs); 1382 } else |
1383 fs = locate_flowset(fwa->cookie & 0xffff); | 1383 fs = locate_flowset(fwa->rule.info & IPFW_INFO_MASK); |
1384 1385 if (fs == NULL) 1386 goto dropit; /* This queue/pipe does not exist! */ 1387 pipe = fs->pipe; 1388 if (pipe == NULL) { /* Must be a queue, try find a matching pipe. */ 1389 pipe = locate_pipe(fs->parent_nr); 1390 if (pipe != NULL) 1391 fs->pipe = pipe; --- 29 unchanged lines hidden (view full) --- 1421 goto dropit; /* Cannot allocate packet header. */ 1422 m_tag_prepend(m, mtag); /* Attach to mbuf chain. */ 1423 1424 pkt = (struct dn_pkt_tag *)(mtag + 1); 1425 /* 1426 * Ok, i can handle the pkt now... 1427 * Build and enqueue packet + parameters. 1428 */ | 1384 1385 if (fs == NULL) 1386 goto dropit; /* This queue/pipe does not exist! */ 1387 pipe = fs->pipe; 1388 if (pipe == NULL) { /* Must be a queue, try find a matching pipe. */ 1389 pipe = locate_pipe(fs->parent_nr); 1390 if (pipe != NULL) 1391 fs->pipe = pipe; --- 29 unchanged lines hidden (view full) --- 1421 goto dropit; /* Cannot allocate packet header. */ 1422 m_tag_prepend(m, mtag); /* Attach to mbuf chain. */ 1423 1424 pkt = (struct dn_pkt_tag *)(mtag + 1); 1425 /* 1426 * Ok, i can handle the pkt now... 1427 * Build and enqueue packet + parameters. 1428 */ |
1429 pkt->slot = fwa->slot; 1430 pkt->rulenum = fwa->rulenum; 1431 pkt->rule_id = fwa->rule_id; 1432 pkt->chain_id = fwa->chain_id; | 1429 pkt->rule = fwa->rule; 1430 pkt->rule.info &= IPFW_ONEPASS; /* only keep this info */ |
1433 pkt->dn_dir = dir; | 1431 pkt->dn_dir = dir; |
1434 | |
1435 pkt->ifp = fwa->oif; 1436 1437 if (q->head == NULL) 1438 q->head = m; 1439 else 1440 q->tail->m_nextpkt = m; 1441 q->tail = m; 1442 q->len++; --- 114 unchanged lines hidden (view full) --- 1557 dummynet_send(head); 1558 return (0); 1559 1560dropit: 1561 io_pkt_drop++; 1562 if (q) 1563 q->drops++; 1564 DUMMYNET_UNLOCK(); | 1432 pkt->ifp = fwa->oif; 1433 1434 if (q->head == NULL) 1435 q->head = m; 1436 else 1437 q->tail->m_nextpkt = m; 1438 q->tail = m; 1439 q->len++; --- 114 unchanged lines hidden (view full) --- 1554 dummynet_send(head); 1555 return (0); 1556 1557dropit: 1558 io_pkt_drop++; 1559 if (q) 1560 q->drops++; 1561 DUMMYNET_UNLOCK(); |
1565 *m0 = dn_free_pkt(m); | 1562 FREE_PKT(m); 1563 *m0 = NULL; |
1566 return ((fs && (fs->flags_fs & DN_NOERROR)) ? 0 : ENOBUFS); 1567} 1568 1569/* 1570 * Dispose all packets and flow_queues on a flow_set. 1571 * If all=1, also remove red lookup table and other storage, 1572 * including the descriptor itself. 1573 * For the one in dn_pipe MUST also cleanup ready_heap... --- 789 unchanged lines hidden --- | 1564 return ((fs && (fs->flags_fs & DN_NOERROR)) ? 0 : ENOBUFS); 1565} 1566 1567/* 1568 * Dispose all packets and flow_queues on a flow_set. 1569 * If all=1, also remove red lookup table and other storage, 1570 * including the descriptor itself. 1571 * For the one in dn_pipe MUST also cleanup ready_heap... --- 789 unchanged lines hidden --- |