[NETFILTER]: nf_nat: use HW checksumming when possible
When mangling packets forwarded to a HW checksumming capable device, offload recalculation of the checksum instead of doing it in software. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c15bf6e699
commit
fe6092ea00
@ -153,6 +153,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
|
|||||||
const char *rep_buffer,
|
const char *rep_buffer,
|
||||||
unsigned int rep_len)
|
unsigned int rep_len)
|
||||||
{
|
{
|
||||||
|
struct rtable *rt = (struct rtable *)(*pskb)->dst;
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
struct tcphdr *tcph;
|
struct tcphdr *tcph;
|
||||||
int oldlen, datalen;
|
int oldlen, datalen;
|
||||||
@ -176,11 +177,22 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
|
|||||||
|
|
||||||
datalen = (*pskb)->len - iph->ihl*4;
|
datalen = (*pskb)->len - iph->ihl*4;
|
||||||
if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
|
if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
|
||||||
tcph->check = 0;
|
if (!(rt->rt_flags & RTCF_LOCAL) &&
|
||||||
tcph->check = tcp_v4_check(datalen,
|
(*pskb)->dev->features & NETIF_F_ALL_CSUM) {
|
||||||
iph->saddr, iph->daddr,
|
(*pskb)->ip_summed = CHECKSUM_PARTIAL;
|
||||||
csum_partial((char *)tcph,
|
(*pskb)->csum_start = skb_headroom(*pskb) +
|
||||||
datalen, 0));
|
skb_network_offset(*pskb) +
|
||||||
|
iph->ihl * 4;
|
||||||
|
(*pskb)->csum_offset = offsetof(struct tcphdr, check);
|
||||||
|
tcph->check = ~tcp_v4_check(datalen,
|
||||||
|
iph->saddr, iph->daddr, 0);
|
||||||
|
} else {
|
||||||
|
tcph->check = 0;
|
||||||
|
tcph->check = tcp_v4_check(datalen,
|
||||||
|
iph->saddr, iph->daddr,
|
||||||
|
csum_partial((char *)tcph,
|
||||||
|
datalen, 0));
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
nf_proto_csum_replace2(&tcph->check, *pskb,
|
nf_proto_csum_replace2(&tcph->check, *pskb,
|
||||||
htons(oldlen), htons(datalen), 1);
|
htons(oldlen), htons(datalen), 1);
|
||||||
@ -217,6 +229,7 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb,
|
|||||||
const char *rep_buffer,
|
const char *rep_buffer,
|
||||||
unsigned int rep_len)
|
unsigned int rep_len)
|
||||||
{
|
{
|
||||||
|
struct rtable *rt = (struct rtable *)(*pskb)->dst;
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
struct udphdr *udph;
|
struct udphdr *udph;
|
||||||
int datalen, oldlen;
|
int datalen, oldlen;
|
||||||
@ -251,13 +264,25 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb,
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
|
if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
|
||||||
udph->check = 0;
|
if (!(rt->rt_flags & RTCF_LOCAL) &&
|
||||||
udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
|
(*pskb)->dev->features & NETIF_F_ALL_CSUM) {
|
||||||
datalen, IPPROTO_UDP,
|
(*pskb)->ip_summed = CHECKSUM_PARTIAL;
|
||||||
csum_partial((char *)udph,
|
(*pskb)->csum_start = skb_headroom(*pskb) +
|
||||||
datalen, 0));
|
skb_network_offset(*pskb) +
|
||||||
if (!udph->check)
|
iph->ihl * 4;
|
||||||
udph->check = CSUM_MANGLED_0;
|
(*pskb)->csum_offset = offsetof(struct udphdr, check);
|
||||||
|
udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
|
||||||
|
datalen, IPPROTO_UDP,
|
||||||
|
0);
|
||||||
|
} else {
|
||||||
|
udph->check = 0;
|
||||||
|
udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
|
||||||
|
datalen, IPPROTO_UDP,
|
||||||
|
csum_partial((char *)udph,
|
||||||
|
datalen, 0));
|
||||||
|
if (!udph->check)
|
||||||
|
udph->check = CSUM_MANGLED_0;
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
nf_proto_csum_replace2(&udph->check, *pskb,
|
nf_proto_csum_replace2(&udph->check, *pskb,
|
||||||
htons(oldlen), htons(datalen), 1);
|
htons(oldlen), htons(datalen), 1);
|
||||||
|
Loading…
Reference in New Issue
Block a user