aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-04-13 01:15:50 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:28:59 -0400
commitfe6092ea0019cbba5263a915c9ce9f2bf383209e (patch)
tree0da8554466720878ce6fec639eebe7ea2e7ec96e /net/ipv4
parentc15bf6e699f4c366f2d1e19ac5d7add21c6b5a19 (diff)
[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>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter/nf_nat_helper.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
index 8a40fbe842b7..15b6e5ce3a04 100644
--- a/net/ipv4/netfilter/nf_nat_helper.c
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -153,6 +153,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
153 const char *rep_buffer, 153 const char *rep_buffer,
154 unsigned int rep_len) 154 unsigned int rep_len)
155{ 155{
156 struct rtable *rt = (struct rtable *)(*pskb)->dst;
156 struct iphdr *iph; 157 struct iphdr *iph;
157 struct tcphdr *tcph; 158 struct tcphdr *tcph;
158 int oldlen, datalen; 159 int oldlen, datalen;
@@ -176,11 +177,22 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
176 177
177 datalen = (*pskb)->len - iph->ihl*4; 178 datalen = (*pskb)->len - iph->ihl*4;
178 if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { 179 if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
179 tcph->check = 0; 180 if (!(rt->rt_flags & RTCF_LOCAL) &&
180 tcph->check = tcp_v4_check(datalen, 181 (*pskb)->dev->features & NETIF_F_ALL_CSUM) {
181 iph->saddr, iph->daddr, 182 (*pskb)->ip_summed = CHECKSUM_PARTIAL;
182 csum_partial((char *)tcph, 183 (*pskb)->csum_start = skb_headroom(*pskb) +
183 datalen, 0)); 184 skb_network_offset(*pskb) +
185 iph->ihl * 4;
186 (*pskb)->csum_offset = offsetof(struct tcphdr, check);
187 tcph->check = ~tcp_v4_check(datalen,
188 iph->saddr, iph->daddr, 0);
189 } else {
190 tcph->check = 0;
191 tcph->check = tcp_v4_check(datalen,
192 iph->saddr, iph->daddr,
193 csum_partial((char *)tcph,
194 datalen, 0));
195 }
184 } else 196 } else
185 nf_proto_csum_replace2(&tcph->check, *pskb, 197 nf_proto_csum_replace2(&tcph->check, *pskb,
186 htons(oldlen), htons(datalen), 1); 198 htons(oldlen), htons(datalen), 1);
@@ -217,6 +229,7 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb,
217 const char *rep_buffer, 229 const char *rep_buffer,
218 unsigned int rep_len) 230 unsigned int rep_len)
219{ 231{
232 struct rtable *rt = (struct rtable *)(*pskb)->dst;
220 struct iphdr *iph; 233 struct iphdr *iph;
221 struct udphdr *udph; 234 struct udphdr *udph;
222 int datalen, oldlen; 235 int datalen, oldlen;
@@ -251,13 +264,25 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb,
251 return 1; 264 return 1;
252 265
253 if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { 266 if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
254 udph->check = 0; 267 if (!(rt->rt_flags & RTCF_LOCAL) &&
255 udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, 268 (*pskb)->dev->features & NETIF_F_ALL_CSUM) {
256 datalen, IPPROTO_UDP, 269 (*pskb)->ip_summed = CHECKSUM_PARTIAL;
257 csum_partial((char *)udph, 270 (*pskb)->csum_start = skb_headroom(*pskb) +
258 datalen, 0)); 271 skb_network_offset(*pskb) +
259 if (!udph->check) 272 iph->ihl * 4;
260 udph->check = CSUM_MANGLED_0; 273 (*pskb)->csum_offset = offsetof(struct udphdr, check);
274 udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
275 datalen, IPPROTO_UDP,
276 0);
277 } else {
278 udph->check = 0;
279 udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
280 datalen, IPPROTO_UDP,
281 csum_partial((char *)udph,
282 datalen, 0));
283 if (!udph->check)
284 udph->check = CSUM_MANGLED_0;
285 }
261 } else 286 } else
262 nf_proto_csum_replace2(&udph->check, *pskb, 287 nf_proto_csum_replace2(&udph->check, *pskb,
263 htons(oldlen), htons(datalen), 1); 288 htons(oldlen), htons(datalen), 1);