ip_fastfwd.c (125952) | ip_fastfwd.c (126239) |
---|---|
1/* 2 * Copyright (c) 2003 Andre Oppermann, Internet Business Solutions AG 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 12 unchanged lines hidden (view full) --- 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * | 1/* 2 * Copyright (c) 2003 Andre Oppermann, Internet Business Solutions AG 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 12 unchanged lines hidden (view full) --- 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * |
29 * $FreeBSD: head/sys/netinet/ip_fastfwd.c 125952 2004-02-18 00:04:52Z mlaier $ | 29 * $FreeBSD: head/sys/netinet/ip_fastfwd.c 126239 2004-02-25 19:55:29Z mlaier $ |
30 */ 31 32/* 33 * ip_fastforward gets its speed from processing the forwarded packet to 34 * completion (if_output on the other side) without any queues or netisr's. 35 * The receiving interface DMAs the packet into memory, the upper half of 36 * driver calls ip_fastforward, we do our routing table lookup and directly 37 * send it off to the outgoing interface which DMAs the packet to the --- 67 unchanged lines hidden (view full) --- 105#include <netinet/in_var.h> 106#include <netinet/ip.h> 107#include <netinet/ip_var.h> 108#include <netinet/ip_icmp.h> 109 110#include <machine/in_cksum.h> 111 112#include <netinet/ip_fw.h> | 30 */ 31 32/* 33 * ip_fastforward gets its speed from processing the forwarded packet to 34 * completion (if_output on the other side) without any queues or netisr's. 35 * The receiving interface DMAs the packet into memory, the upper half of 36 * driver calls ip_fastforward, we do our routing table lookup and directly 37 * send it off to the outgoing interface which DMAs the packet to the --- 67 unchanged lines hidden (view full) --- 105#include <netinet/in_var.h> 106#include <netinet/ip.h> 107#include <netinet/ip_var.h> 108#include <netinet/ip_icmp.h> 109 110#include <machine/in_cksum.h> 111 112#include <netinet/ip_fw.h> |
113#include <netinet/ip_divert.h> |
|
113#include <netinet/ip_dummynet.h> 114 115static int ipfastforward_active = 0; 116SYSCTL_INT(_net_inet_ip, OID_AUTO, fastforwarding, CTLFLAG_RW, 117 &ipfastforward_active, 0, "Enable fast IP forwarding"); 118 119/* 120 * Try to forward a packet based on the destination address. --- 4 unchanged lines hidden (view full) --- 125 */ 126int 127ip_fastforward(struct mbuf *m) 128{ 129 struct ip *ip; 130 struct mbuf *m0 = NULL; 131#ifdef IPDIVERT 132 struct ip *tip; | 114#include <netinet/ip_dummynet.h> 115 116static int ipfastforward_active = 0; 117SYSCTL_INT(_net_inet_ip, OID_AUTO, fastforwarding, CTLFLAG_RW, 118 &ipfastforward_active, 0, "Enable fast IP forwarding"); 119 120/* 121 * Try to forward a packet based on the destination address. --- 4 unchanged lines hidden (view full) --- 126 */ 127int 128ip_fastforward(struct mbuf *m) 129{ 130 struct ip *ip; 131 struct mbuf *m0 = NULL; 132#ifdef IPDIVERT 133 struct ip *tip; |
133 struct mbuf *teem = NULL; | 134 struct mbuf *clone = NULL; |
134#endif | 135#endif |
135 struct mbuf *tag = NULL; | |
136 struct route ro; 137 struct sockaddr_in *dst = NULL; 138 struct in_ifaddr *ia = NULL; 139 struct ifaddr *ifa = NULL; 140 struct ifnet *ifp = NULL; 141 struct ip_fw_args args; 142 in_addr_t odest, dest; 143 u_short sum; 144 int error = 0; 145 int hlen, ipfw, mtu; 146 147 /* 148 * Are we active and forwarding packets? 149 */ 150 if (!ipfastforward_active || !ipforwarding) 151 return 0; 152 | 136 struct route ro; 137 struct sockaddr_in *dst = NULL; 138 struct in_ifaddr *ia = NULL; 139 struct ifaddr *ifa = NULL; 140 struct ifnet *ifp = NULL; 141 struct ip_fw_args args; 142 in_addr_t odest, dest; 143 u_short sum; 144 int error = 0; 145 int hlen, ipfw, mtu; 146 147 /* 148 * Are we active and forwarding packets? 149 */ 150 if (!ipfastforward_active || !ipforwarding) 151 return 0; 152 |
153 /* 154 * If there is any MT_TAG we fall back to ip_input because we can't 155 * handle TAGs here. Should never happen as we get directly called 156 * from the if_output routines. 157 */ 158 if (m->m_type == MT_TAG) { 159 KASSERT(0, ("%s: packet with MT_TAG not expected", __func__)); 160 return 0; 161 } 162 | |
163 M_ASSERTVALID(m); 164 M_ASSERTPKTHDR(m); 165 166 /* 167 * Step 1: check for packet drop conditions (and sanity checks) 168 */ 169 170 /* --- 197 unchanged lines hidden (view full) --- 368#ifdef IPDIVERT 369 /* 370 * Divert packet 371 */ 372 if (ipfw != 0 && (ipfw & IP_FW_PORT_DYNT_FLAG) == 0) { 373 /* 374 * See if this is a fragment 375 */ | 153 M_ASSERTVALID(m); 154 M_ASSERTPKTHDR(m); 155 156 /* 157 * Step 1: check for packet drop conditions (and sanity checks) 158 */ 159 160 /* --- 197 unchanged lines hidden (view full) --- 358#ifdef IPDIVERT 359 /* 360 * Divert packet 361 */ 362 if (ipfw != 0 && (ipfw & IP_FW_PORT_DYNT_FLAG) == 0) { 363 /* 364 * See if this is a fragment 365 */ |
376 if (ip->ip_off & (IP_MF | IP_OFFMASK)) { 377 MGETHDR(tag, M_DONTWAIT, MT_TAG); 378 if (tag == NULL) 379 goto drop; 380 tag->m_flags = PACKET_TAG_DIVERT; 381 tag->m_data = (caddr_t)(intptr_t)args.divert_rule; 382 tag->m_next = m; 383 /* XXX: really bloody hack, see ip_input */ 384 tag->m_nextpkt = (struct mbuf *)1; 385 m = tag; 386 tag = NULL; 387 | 366 if (ip->ip_off & (IP_MF | IP_OFFMASK)) |
388 goto droptoours; | 367 goto droptoours; |
389 } | |
390 /* 391 * Tee packet 392 */ 393 if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0) | 368 /* 369 * Tee packet 370 */ 371 if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0) |
394 teem = m_dup(m, M_DONTWAIT); | 372 clone = divert_clone(m); |
395 else | 373 else |
396 teem = m; 397 if (teem == NULL) | 374 clone = m; 375 if (clone == NULL) |
398 goto passin; 399 400 /* 401 * Delayed checksums are not compatible 402 */ | 376 goto passin; 377 378 /* 379 * Delayed checksums are not compatible 380 */ |
403 if (teem->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 404 in_delayed_cksum(teem); 405 teem->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; | 381 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 382 in_delayed_cksum(m); 383 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; |
406 } 407 /* 408 * Restore packet header fields to original values 409 */ | 384 } 385 /* 386 * Restore packet header fields to original values 387 */ |
410 tip = mtod(teem, struct ip *); | 388 tip = mtod(m, struct ip *); |
411 tip->ip_len = htons(tip->ip_len); 412 tip->ip_off = htons(tip->ip_off); 413 /* 414 * Deliver packet to divert input routine 415 */ | 389 tip->ip_len = htons(tip->ip_len); 390 tip->ip_off = htons(tip->ip_off); 391 /* 392 * Deliver packet to divert input routine 393 */ |
416 divert_packet(teem, 0, ipfw & 0xffff, args.divert_rule); | 394 divert_packet(m, 0); |
417 /* 418 * If this was not tee, we are done 419 */ | 395 /* 396 * If this was not tee, we are done 397 */ |
398 m = clone; |
|
420 if ((ipfw & IP_FW_PORT_TEE_FLAG) == 0) 421 return 1; 422 /* Continue if it was tee */ 423 goto passin; 424 } 425#endif 426 if (ipfw == 0 && args.next_hop != NULL) { 427 dest = args.next_hop->sin_addr.s_addr; --- 127 unchanged lines hidden (view full) --- 555 RTFREE(ro.ro_rt); 556 return 1; 557 } 558#ifdef IPDIVERT 559 if (ipfw != 0 && (ipfw & IP_FW_PORT_DYNT_FLAG) == 0) { 560 /* 561 * See if this is a fragment 562 */ | 399 if ((ipfw & IP_FW_PORT_TEE_FLAG) == 0) 400 return 1; 401 /* Continue if it was tee */ 402 goto passin; 403 } 404#endif 405 if (ipfw == 0 && args.next_hop != NULL) { 406 dest = args.next_hop->sin_addr.s_addr; --- 127 unchanged lines hidden (view full) --- 534 RTFREE(ro.ro_rt); 535 return 1; 536 } 537#ifdef IPDIVERT 538 if (ipfw != 0 && (ipfw & IP_FW_PORT_DYNT_FLAG) == 0) { 539 /* 540 * See if this is a fragment 541 */ |
563 if (ip->ip_off & (IP_MF | IP_OFFMASK)) { 564 MGETHDR(tag, M_DONTWAIT, MT_TAG); 565 if (tag == NULL) { 566 RTFREE(ro.ro_rt); 567 goto drop; 568 } 569 tag->m_flags = PACKET_TAG_DIVERT; 570 tag->m_data = (caddr_t)(intptr_t)args.divert_rule; 571 tag->m_next = m; 572 /* XXX: really bloody hack, see ip_input */ 573 tag->m_nextpkt = (struct mbuf *)1; 574 m = tag; 575 tag = NULL; 576 | 542 if (ip->ip_off & (IP_MF | IP_OFFMASK)) |
577 goto droptoours; | 543 goto droptoours; |
578 } | |
579 /* 580 * Tee packet 581 */ 582 if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0) | 544 /* 545 * Tee packet 546 */ 547 if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0) |
583 teem = m_dup(m, M_DONTWAIT); | 548 clone = divert_clone(m); |
584 else | 549 else |
585 teem = m; 586 if (teem == NULL) | 550 clone = m; 551 if (clone == NULL) |
587 goto passout; 588 589 /* 590 * Delayed checksums are not compatible with divert 591 */ | 552 goto passout; 553 554 /* 555 * Delayed checksums are not compatible with divert 556 */ |
592 if (teem->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 593 in_delayed_cksum(teem); 594 teem->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; | 557 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 558 in_delayed_cksum(m); 559 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; |
595 } 596 /* 597 * Restore packet header fields to original values 598 */ | 560 } 561 /* 562 * Restore packet header fields to original values 563 */ |
599 tip = mtod(teem, struct ip *); | 564 tip = mtod(m, struct ip *); |
600 tip->ip_len = htons(tip->ip_len); 601 tip->ip_off = htons(tip->ip_off); 602 /* 603 * Deliver packet to divert input routine 604 */ | 565 tip->ip_len = htons(tip->ip_len); 566 tip->ip_off = htons(tip->ip_off); 567 /* 568 * Deliver packet to divert input routine 569 */ |
605 divert_packet(teem, 0, ipfw & 0xffff, args.divert_rule); | 570 divert_packet(m, 0); |
606 /* 607 * If this was not tee, we are done 608 */ | 571 /* 572 * If this was not tee, we are done 573 */ |
574 m = clone; |
|
609 if ((ipfw & IP_FW_PORT_TEE_FLAG) == 0) { 610 RTFREE(ro.ro_rt); 611 return 1; 612 } 613 /* Continue if it was tee */ 614 goto passout; 615 } 616#endif --- 16 unchanged lines hidden (view full) --- 633 if (odest != dest) { 634 /* 635 * Is it now for a local address on this host? 636 */ 637 LIST_FOREACH(ia, INADDR_HASH(ip->ip_dst.s_addr), ia_hash) { 638 if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr) { 639forwardlocal: 640 if (args.next_hop) { | 575 if ((ipfw & IP_FW_PORT_TEE_FLAG) == 0) { 576 RTFREE(ro.ro_rt); 577 return 1; 578 } 579 /* Continue if it was tee */ 580 goto passout; 581 } 582#endif --- 16 unchanged lines hidden (view full) --- 599 if (odest != dest) { 600 /* 601 * Is it now for a local address on this host? 602 */ 603 LIST_FOREACH(ia, INADDR_HASH(ip->ip_dst.s_addr), ia_hash) { 604 if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr) { 605forwardlocal: 606 if (args.next_hop) { |
641 /* XXX leak */ 642 MGETHDR(tag, M_DONTWAIT, MT_TAG); 643 if (tag == NULL) { | 607 struct m_tag *mtag = m_tag_get( 608 PACKET_TAG_IPFORWARD, 609 sizeof(struct sockaddr_in *), 610 M_NOWAIT); 611 if (mtag == NULL) { |
644 if (ro.ro_rt) 645 RTFREE(ro.ro_rt); 646 goto drop; 647 } | 612 if (ro.ro_rt) 613 RTFREE(ro.ro_rt); 614 goto drop; 615 } |
648 tag->m_flags = PACKET_TAG_IPFORWARD; 649 tag->m_data = (caddr_t)args.next_hop; 650 tag->m_next = m; 651 /* XXX: really bloody hack, 652 * see ip_input */ 653 tag->m_nextpkt = (struct mbuf *)1; 654 m = tag; 655 tag = NULL; | 616 *(struct sockaddr_in **)(mtag+1) = 617 args.next_hop; 618 m_tag_prepend(m, mtag); |
656 } 657#ifdef IPDIVERT 658droptoours: /* Used for DIVERT */ 659#endif | 619 } 620#ifdef IPDIVERT 621droptoours: /* Used for DIVERT */ 622#endif |
660 MGETHDR(tag, M_DONTWAIT, MT_TAG); 661 if (tag == NULL) { 662 if (ro.ro_rt) 663 RTFREE(ro.ro_rt); 664 goto drop; 665 } 666 tag->m_flags = PACKET_TAG_IPFASTFWD_OURS; 667 tag->m_data = NULL; 668 tag->m_next = m; 669 /* XXX: really bloody hack, see ip_input */ 670 tag->m_nextpkt = (struct mbuf *)1; 671 m = tag; 672 tag = NULL; | 623 /* for ip_input */ 624 m->m_flags |= M_FASTFWD_OURS; |
673 674 /* ip still points to the real packet */ 675 ip->ip_len = htons(ip->ip_len); 676 ip->ip_off = htons(ip->ip_off); 677 678 /* 679 * Return packet for processing by ip_input 680 */ --- 125 unchanged lines hidden --- | 625 626 /* ip still points to the real packet */ 627 ip->ip_len = htons(ip->ip_len); 628 ip->ip_off = htons(ip->ip_off); 629 630 /* 631 * Return packet for processing by ip_input 632 */ --- 125 unchanged lines hidden --- |