From aa4404c6818cf3559282d5f4e80b0d9f39a54b95 Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Mon, 22 Jun 2015 16:04:29 +0200 Subject: [PATCH] dummynet: ipnat patch solves traffic shaper issues with wan interfaces Taken from: m0n0wall Modified by: franco@opnsense.org --- sys/netinet/ip_input.c | 45 ++++++++++++++++++++++++++++--------- sys/netpfil/ipfw/ip_dn_io.c | 1 + 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 2dc080f1310..e34cebab212 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -420,20 +420,25 @@ ip_input(struct mbuf *m) } } - if (m->m_pkthdr.csum_flags & CSUM_IP_CHECKED) { - sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID); - } else { - if (hlen == sizeof(struct ip)) { - sum = in_cksum_hdr(ip); + /* + * Skip checksum checks if we came from dummynet, + * since we'll already have been here in that case. + */ + if (!(m->m_flags & M_PROTO12)) { + if (m->m_pkthdr.csum_flags & CSUM_IP_CHECKED) { + sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID); } else { - sum = in_cksum(m, hlen); + if (hlen == sizeof(struct ip)) { + sum = in_cksum_hdr(ip); + } else { + sum = in_cksum(m, hlen); + } + } + if (sum) { + IPSTAT_INC(ips_badsum); + goto bad; } } - if (sum) { - IPSTAT_INC(ips_badsum); - goto bad; - } - #ifdef ALTQ if (altq_input != NULL && (*altq_input)(m, AF_INET) == 0) /* packet is dropped by traffic conditioner */ @@ -483,6 +488,24 @@ tooshort: /* Jump over all PFIL processing if hooks are not active. */ if (!PFIL_HOOKED(&V_inet_pfil_hook)) goto passin; + if (m->m_flags & M_PROTO12) { + /* + * Packet has already been through dummynet, and + * therefore also through ipnat (reversed processing + * order); we skip the pfil hooks to avoid ipnat being + * called again on this packet (this implicitly assumes + * that one_pass=1). However, we need to remove the + * ipfw tag, otherwise the packet will be treated + * improperly in ip_output. + */ + struct m_tag *ipfw_tag; + ipfw_tag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL); + if (ipfw_tag != NULL) { + m_tag_delete(m, ipfw_tag); + } + m->m_flags &= ~M_PROTO12; + goto passin; + } odst = ip->ip_dst; if (pfil_run_hooks(&V_inet_pfil_hook, &m, ifp, PFIL_IN, NULL) != 0) diff --git a/sys/netpfil/ipfw/ip_dn_io.c b/sys/netpfil/ipfw/ip_dn_io.c index 9a4b4867d3f..ad8ceda5c62 100644 --- a/sys/netpfil/ipfw/ip_dn_io.c +++ b/sys/netpfil/ipfw/ip_dn_io.c @@ -662,6 +662,7 @@ dummynet_send(struct mbuf *m) break ; case DIR_IN : + m->m_flags |= M_PROTO12; netisr_dispatch(NETISR_IP, m); break;