Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/ip_fastfwd.c
Show First 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | |||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <netinet/in_kdtrace.h> | #include <netinet/in_kdtrace.h> | ||||
#include <netinet/in_systm.h> | #include <netinet/in_systm.h> | ||||
#include <netinet/in_var.h> | #include <netinet/in_var.h> | ||||
#include <netinet/ip.h> | #include <netinet/ip.h> | ||||
#include <netinet/ip_var.h> | #include <netinet/ip_var.h> | ||||
#include <netinet/ip_icmp.h> | #include <netinet/ip_icmp.h> | ||||
#include <netinet/ip_options.h> | #include <netinet/ip_options.h> | ||||
#include <netinet/tcp.h> | |||||
#include <machine/in_cksum.h> | #include <machine/in_cksum.h> | ||||
static struct sockaddr_in * | static struct sockaddr_in * | ||||
ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m) | ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m) | ||||
{ | { | ||||
struct sockaddr_in *dst; | struct sockaddr_in *dst; | ||||
struct rtentry *rt; | struct rtentry *rt; | ||||
Show All 39 Lines | |||||
ip_tryforward(struct mbuf *m) | ip_tryforward(struct mbuf *m) | ||||
{ | { | ||||
struct ip *ip; | struct ip *ip; | ||||
struct mbuf *m0 = NULL; | struct mbuf *m0 = NULL; | ||||
struct route ro; | struct route ro; | ||||
struct sockaddr_in *dst = NULL; | struct sockaddr_in *dst = NULL; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
struct in_addr odest, dest; | struct in_addr odest, dest; | ||||
uint16_t ip_len, ip_off; | uint16_t ip_len, ip_off, tcp_len; | ||||
int error = 0; | int error = 0; | ||||
int mtu; | int mtu; | ||||
struct m_tag *fwd_tag = NULL; | struct m_tag *fwd_tag = NULL; | ||||
/* | /* | ||||
* Are we active and forwarding packets? | * Are we active and forwarding packets? | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 252 Lines • ▼ Show 20 Lines | passout: | ||||
/* | /* | ||||
* Check if packet fits MTU or if hardware will fragment for us | * Check if packet fits MTU or if hardware will fragment for us | ||||
*/ | */ | ||||
if (ro.ro_rt->rt_mtu) | if (ro.ro_rt->rt_mtu) | ||||
mtu = min(ro.ro_rt->rt_mtu, ifp->if_mtu); | mtu = min(ro.ro_rt->rt_mtu, ifp->if_mtu); | ||||
else | else | ||||
mtu = ifp->if_mtu; | mtu = ifp->if_mtu; | ||||
if (ip_len <= mtu) { | /* | ||||
* Allow forwarding TSO packets directly if the outbound | |||||
* interface also supports TSO. | |||||
* | |||||
* This is very important when using VMs to perform intra-host | |||||
* packet routing. Since the packet never hits the wire the | |||||
* TCP segments are not actually generated until it reaches a | |||||
* physical interface, and thus we get to see TSO packets on | |||||
* input. | |||||
* | |||||
* Not doing this means that the backend domain (usually Dom0) | |||||
* would have to perform software TCP segmentation for us, which | |||||
* will introduce a huge performance penalty. | |||||
*/ | |||||
if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0 && | |||||
ip->ip_p == IPPROTO_TCP) { | |||||
struct tcphdr th; | |||||
gnn: Minor nit but I'd prefer an extra set of braces around the first clause, before the && | |||||
m_copydata(m, sizeof(struct ip), sizeof(struct tcphdr), | |||||
Not Done Inline ActionsIt isn't safe. There is no guarantee that mbuf's data will be contiguous more than sizeof(struct ip). ae: It isn't safe. There is no guarantee that mbuf's data will be contiguous more than sizeof… | |||||
Not Done Inline ActionsWhat's the proper way to get the TCP payload length then? royger: What's the proper way to get the TCP payload length then? | |||||
Not Done Inline ActionsThe easiest way is m_copydata() with proper offset. ae: The easiest way is m_copydata() with proper offset. | |||||
Done Inline ActionsThanks! Will update the patch shortly unless there are other comments. royger: Thanks! Will update the patch shortly unless there are other comments. | |||||
afedorovUnsubmitted Not Done Inline ActionsIs this really safe? sizeof(struct ip) == 20 bytes, but IPv4 header can be up to 60 bytes with options. I think you should use ip.ip_hl field as offset. afedorov: Is this really safe? sizeof(struct ip) == 20 bytes, but IPv4 header can be up to 60 bytes with… | |||||
gallatinUnsubmitted Not Done Inline ActionsOr check V_ip_doopts != 0, as the code above rejects packets with options if V_ip_doopts is non-zero. gallatin: Or check V_ip_doopts != 0, as the code above rejects packets with options if V_ip_doopts is non… | |||||
(caddr_t) &th); | |||||
tcp_len = ip_len - (sizeof(struct ip) + (th.th_off << 2)); | |||||
} | |||||
if ((ip_len <= mtu) || (ip->ip_p == IPPROTO_TCP && | |||||
(m->m_pkthdr.csum_flags & CSUM_TSO) != 0 && | |||||
melifaroUnsubmitted Not Done Inline ActionsCan this fancy concatenation of 8 conditions be an inline function? melifaro: Can this fancy concatenation of 8 conditions be an inline function? | |||||
rgrimesUnsubmitted Not Done Inline ActionsWhy, it isnt used in more than one place? rgrimes: Why, it isnt used in more than one place? | |||||
melifaroUnsubmitted Not Done Inline ActionsNo, I hope it will improve readability. It will also be easier to attach some comments. melifaro: No, I hope it will improve readability. It will also be easier to attach some comments. | |||||
(ifp->if_hwassist & CSUM_TSO) != 0 && | |||||
(ifp->if_capenable & IFCAP_TSO4) != 0 && | |||||
(m->m_pkthdr.tso_segsz <= ifp->if_hw_tsomaxsegsize) && | |||||
howmany(tcp_len, m->m_pkthdr.tso_segsz) <= | |||||
ifp->if_hw_tsomaxsegcount && | |||||
tcp_len <= ifp->if_hw_tsomax)) { | |||||
/* | /* | ||||
* Avoid confusing lower layers. | * Avoid confusing lower layers. | ||||
*/ | */ | ||||
m_clrprotoflags(m); | m_clrprotoflags(m); | ||||
/* | /* | ||||
* Send off the packet via outgoing interface | * Send off the packet via outgoing interface | ||||
*/ | */ | ||||
IP_PROBE(send, NULL, NULL, ip, ifp, ip, NULL); | IP_PROBE(send, NULL, NULL, ip, ifp, ip, NULL); | ||||
▲ Show 20 Lines • Show All 65 Lines • Show Last 20 Lines |
Minor nit but I'd prefer an extra set of braces around the first clause, before the &&