Deleted Added
full compact
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 ---