2005-04-17 00:20:36 +02:00
|
|
|
/*
|
|
|
|
* ip_vs_xmit.c: various packet transmitters for IPVS
|
|
|
|
*
|
|
|
|
* Authors: Wensong Zhang <wensong@linuxvirtualserver.org>
|
|
|
|
* Julian Anastasov <ja@ssi.bg>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version
|
|
|
|
* 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* Changes:
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2009-07-30 23:29:44 +02:00
|
|
|
#define KMSG_COMPONENT "IPVS"
|
|
|
|
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
|
|
|
|
|
2005-04-17 00:20:36 +02:00
|
|
|
#include <linux/kernel.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 09:04:11 +01:00
|
|
|
#include <linux/slab.h>
|
2005-04-17 00:20:36 +02:00
|
|
|
#include <linux/tcp.h> /* for tcphdr */
|
2008-01-12 04:14:00 +01:00
|
|
|
#include <net/ip.h>
|
2005-04-17 00:20:36 +02:00
|
|
|
#include <net/tcp.h> /* for csum_tcpudp_magic */
|
|
|
|
#include <net/udp.h>
|
|
|
|
#include <net/icmp.h> /* for icmp_send */
|
|
|
|
#include <net/route.h> /* for ip_route_output */
|
2008-09-02 15:55:44 +02:00
|
|
|
#include <net/ipv6.h>
|
|
|
|
#include <net/ip6_route.h>
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
#include <net/addrconf.h>
|
2008-09-02 15:55:44 +02:00
|
|
|
#include <linux/icmpv6.h>
|
2005-04-17 00:20:36 +02:00
|
|
|
#include <linux/netfilter.h>
|
|
|
|
#include <linux/netfilter_ipv4.h>
|
|
|
|
|
|
|
|
#include <net/ip_vs.h>
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Destination cache to speed up outgoing route lookup
|
|
|
|
*/
|
|
|
|
static inline void
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
__ip_vs_dst_set(struct ip_vs_dest *dest, u32 rtos, struct dst_entry *dst,
|
|
|
|
u32 dst_cookie)
|
2005-04-17 00:20:36 +02:00
|
|
|
{
|
|
|
|
struct dst_entry *old_dst;
|
|
|
|
|
|
|
|
old_dst = dest->dst_cache;
|
|
|
|
dest->dst_cache = dst;
|
|
|
|
dest->dst_rtos = rtos;
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
dest->dst_cookie = dst_cookie;
|
2005-04-17 00:20:36 +02:00
|
|
|
dst_release(old_dst);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct dst_entry *
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
__ip_vs_dst_check(struct ip_vs_dest *dest, u32 rtos)
|
2005-04-17 00:20:36 +02:00
|
|
|
{
|
|
|
|
struct dst_entry *dst = dest->dst_cache;
|
|
|
|
|
|
|
|
if (!dst)
|
|
|
|
return NULL;
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
if ((dst->obsolete || rtos != dest->dst_rtos) &&
|
|
|
|
dst->ops->check(dst, dest->dst_cookie) == NULL) {
|
2005-04-17 00:20:36 +02:00
|
|
|
dest->dst_cache = NULL;
|
|
|
|
dst_release(dst);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
dst_hold(dst);
|
|
|
|
return dst;
|
|
|
|
}
|
|
|
|
|
[IPVS]: Kill some bloat
net/ipv4/ipvs/ip_vs_xmit.c:
ip_vs_icmp_xmit | -638
ip_vs_tunnel_xmit | -674
ip_vs_nat_xmit | -716
ip_vs_dr_xmit | -682
4 functions changed, 2710 bytes removed, diff: -2710
net/ipv4/ipvs/ip_vs_xmit.c:
__ip_vs_get_out_rt | +595
1 function changed, 595 bytes added, diff: +595
net/ipv4/ipvs/ip_vs_xmit.o:
5 functions changed, 595 bytes added, 2710 bytes removed, diff: -2115
Without some CONFIG.*DEBUGs:
net/ipv4/ipvs/ip_vs_xmit.o:
5 functions changed, 383 bytes added, 1513 bytes removed, diff: -1130
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-01-06 08:12:40 +01:00
|
|
|
static struct rtable *
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
__ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_conn *cp, u32 rtos)
|
2005-04-17 00:20:36 +02:00
|
|
|
{
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
struct net *net = dev_net(skb->dev);
|
2005-04-17 00:20:36 +02:00
|
|
|
struct rtable *rt; /* Route to the other host */
|
|
|
|
struct ip_vs_dest *dest = cp->dest;
|
|
|
|
|
|
|
|
if (dest) {
|
|
|
|
spin_lock(&dest->dst_lock);
|
|
|
|
if (!(rt = (struct rtable *)
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
__ip_vs_dst_check(dest, rtos))) {
|
2005-04-17 00:20:36 +02:00
|
|
|
struct flowi fl = {
|
|
|
|
.oif = 0,
|
|
|
|
.nl_u = {
|
|
|
|
.ip4_u = {
|
2008-09-02 15:55:33 +02:00
|
|
|
.daddr = dest->addr.ip,
|
2005-04-17 00:20:36 +02:00
|
|
|
.saddr = 0,
|
|
|
|
.tos = rtos, } },
|
|
|
|
};
|
|
|
|
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
if (ip_route_output_key(net, &rt, &fl)) {
|
2005-04-17 00:20:36 +02:00
|
|
|
spin_unlock(&dest->dst_lock);
|
2008-10-31 08:54:29 +01:00
|
|
|
IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n",
|
|
|
|
&dest->addr.ip);
|
2005-04-17 00:20:36 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
__ip_vs_dst_set(dest, rtos, dst_clone(&rt->dst), 0);
|
2008-10-31 08:54:29 +01:00
|
|
|
IP_VS_DBG(10, "new dst %pI4, refcnt=%d, rtos=%X\n",
|
|
|
|
&dest->addr.ip,
|
2010-06-11 08:31:35 +02:00
|
|
|
atomic_read(&rt->dst.__refcnt), rtos);
|
2005-04-17 00:20:36 +02:00
|
|
|
}
|
|
|
|
spin_unlock(&dest->dst_lock);
|
|
|
|
} else {
|
|
|
|
struct flowi fl = {
|
|
|
|
.oif = 0,
|
|
|
|
.nl_u = {
|
|
|
|
.ip4_u = {
|
2008-09-02 15:55:33 +02:00
|
|
|
.daddr = cp->daddr.ip,
|
2005-04-17 00:20:36 +02:00
|
|
|
.saddr = 0,
|
|
|
|
.tos = rtos, } },
|
|
|
|
};
|
|
|
|
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
if (ip_route_output_key(net, &rt, &fl)) {
|
2008-10-31 08:54:29 +01:00
|
|
|
IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n",
|
|
|
|
&cp->daddr.ip);
|
2005-04-17 00:20:36 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rt;
|
|
|
|
}
|
|
|
|
|
2008-09-02 15:55:44 +02:00
|
|
|
#ifdef CONFIG_IP_VS_IPV6
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
|
|
|
|
static struct dst_entry *
|
|
|
|
__ip_vs_route_output_v6(struct net *net, struct in6_addr *daddr,
|
|
|
|
struct in6_addr *ret_saddr, int do_xfrm)
|
|
|
|
{
|
|
|
|
struct dst_entry *dst;
|
|
|
|
struct flowi fl = {
|
|
|
|
.oif = 0,
|
|
|
|
.nl_u = {
|
|
|
|
.ip6_u = {
|
|
|
|
.daddr = *daddr,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
dst = ip6_route_output(net, NULL, &fl);
|
|
|
|
if (dst->error)
|
|
|
|
goto out_err;
|
|
|
|
if (!ret_saddr)
|
|
|
|
return dst;
|
|
|
|
if (ipv6_addr_any(&fl.fl6_src) &&
|
|
|
|
ipv6_dev_get_saddr(net, ip6_dst_idev(dst)->dev,
|
|
|
|
&fl.fl6_dst, 0, &fl.fl6_src) < 0)
|
|
|
|
goto out_err;
|
|
|
|
if (do_xfrm && xfrm_lookup(net, &dst, &fl, NULL, 0) < 0)
|
|
|
|
goto out_err;
|
|
|
|
ipv6_addr_copy(ret_saddr, &fl.fl6_src);
|
|
|
|
return dst;
|
|
|
|
|
|
|
|
out_err:
|
|
|
|
dst_release(dst);
|
|
|
|
IP_VS_DBG_RL("ip6_route_output error, dest: %pI6\n", daddr);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-09-02 15:55:44 +02:00
|
|
|
static struct rt6_info *
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
__ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|
|
|
struct in6_addr *ret_saddr, int do_xfrm)
|
2008-09-02 15:55:44 +02:00
|
|
|
{
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
struct net *net = dev_net(skb->dev);
|
2008-09-02 15:55:44 +02:00
|
|
|
struct rt6_info *rt; /* Route to the other host */
|
|
|
|
struct ip_vs_dest *dest = cp->dest;
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
struct dst_entry *dst;
|
2008-09-02 15:55:44 +02:00
|
|
|
|
|
|
|
if (dest) {
|
|
|
|
spin_lock(&dest->dst_lock);
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
rt = (struct rt6_info *)__ip_vs_dst_check(dest, 0);
|
2008-09-02 15:55:44 +02:00
|
|
|
if (!rt) {
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
u32 cookie;
|
2008-09-02 15:55:44 +02:00
|
|
|
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
dst = __ip_vs_route_output_v6(net, &dest->addr.in6,
|
|
|
|
&dest->dst_saddr,
|
|
|
|
do_xfrm);
|
|
|
|
if (!dst) {
|
2008-09-02 15:55:44 +02:00
|
|
|
spin_unlock(&dest->dst_lock);
|
|
|
|
return NULL;
|
|
|
|
}
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
rt = (struct rt6_info *) dst;
|
|
|
|
cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0;
|
|
|
|
__ip_vs_dst_set(dest, 0, dst_clone(&rt->dst), cookie);
|
|
|
|
IP_VS_DBG(10, "new dst %pI6, src %pI6, refcnt=%d\n",
|
|
|
|
&dest->addr.in6, &dest->dst_saddr,
|
2010-06-11 08:31:35 +02:00
|
|
|
atomic_read(&rt->dst.__refcnt));
|
2008-09-02 15:55:44 +02:00
|
|
|
}
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
if (ret_saddr)
|
|
|
|
ipv6_addr_copy(ret_saddr, &dest->dst_saddr);
|
2008-09-02 15:55:44 +02:00
|
|
|
spin_unlock(&dest->dst_lock);
|
|
|
|
} else {
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
dst = __ip_vs_route_output_v6(net, &cp->daddr.in6, ret_saddr,
|
|
|
|
do_xfrm);
|
|
|
|
if (!dst)
|
2008-09-02 15:55:44 +02:00
|
|
|
return NULL;
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
rt = (struct rt6_info *) dst;
|
2008-09-02 15:55:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return rt;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Release dest->dst_cache before a dest is removed
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ip_vs_dst_reset(struct ip_vs_dest *dest)
|
|
|
|
{
|
|
|
|
struct dst_entry *old_dst;
|
|
|
|
|
|
|
|
old_dst = dest->dst_cache;
|
|
|
|
dest->dst_cache = NULL;
|
|
|
|
dst_release(old_dst);
|
|
|
|
}
|
|
|
|
|
2010-09-21 17:35:41 +02:00
|
|
|
#define IP_VS_XMIT_TUNNEL(skb, cp) \
|
|
|
|
({ \
|
|
|
|
int __ret = NF_ACCEPT; \
|
|
|
|
\
|
2010-10-17 15:21:07 +02:00
|
|
|
(skb)->ipvs_property = 1; \
|
2010-09-21 17:35:41 +02:00
|
|
|
if (unlikely((cp)->flags & IP_VS_CONN_F_NFCT)) \
|
|
|
|
__ret = ip_vs_confirm_conntrack(skb, cp); \
|
|
|
|
if (__ret == NF_ACCEPT) { \
|
|
|
|
nf_reset(skb); \
|
2010-10-17 15:29:40 +02:00
|
|
|
skb_forward_csum(skb); \
|
2010-09-21 17:35:41 +02:00
|
|
|
} \
|
|
|
|
__ret; \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define IP_VS_XMIT_NAT(pf, skb, cp) \
|
2005-04-17 00:20:36 +02:00
|
|
|
do { \
|
2010-10-17 15:21:07 +02:00
|
|
|
(skb)->ipvs_property = 1; \
|
2010-09-21 17:35:41 +02:00
|
|
|
if (likely(!((cp)->flags & IP_VS_CONN_F_NFCT))) \
|
2010-10-17 15:21:07 +02:00
|
|
|
ip_vs_notrack(skb); \
|
2010-09-21 17:35:41 +02:00
|
|
|
else \
|
|
|
|
ip_vs_update_conntrack(skb, cp, 1); \
|
2007-07-31 01:20:12 +02:00
|
|
|
skb_forward_csum(skb); \
|
2008-09-02 15:55:44 +02:00
|
|
|
NF_HOOK(pf, NF_INET_LOCAL_OUT, (skb), NULL, \
|
2010-09-21 17:35:41 +02:00
|
|
|
skb_dst(skb)->dev, dst_output); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define IP_VS_XMIT(pf, skb, cp) \
|
|
|
|
do { \
|
2010-10-17 15:21:07 +02:00
|
|
|
(skb)->ipvs_property = 1; \
|
2010-09-21 17:35:41 +02:00
|
|
|
if (likely(!((cp)->flags & IP_VS_CONN_F_NFCT))) \
|
2010-10-17 15:21:07 +02:00
|
|
|
ip_vs_notrack(skb); \
|
2010-09-21 17:35:41 +02:00
|
|
|
skb_forward_csum(skb); \
|
|
|
|
NF_HOOK(pf, NF_INET_LOCAL_OUT, (skb), NULL, \
|
|
|
|
skb_dst(skb)->dev, dst_output); \
|
2005-04-17 00:20:36 +02:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NULL transmitter (do nothing except return NF_ACCEPT)
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|
|
|
struct ip_vs_protocol *pp)
|
|
|
|
{
|
|
|
|
/* we do not touch skb and do not need pskb ptr */
|
|
|
|
return NF_ACCEPT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Bypass transmitter
|
|
|
|
* Let packets bypass the destination when the destination is not
|
|
|
|
* available, it may be only used in transparent cache cluster.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|
|
|
struct ip_vs_protocol *pp)
|
|
|
|
{
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
struct net *net = dev_net(skb->dev);
|
2005-04-17 00:20:36 +02:00
|
|
|
struct rtable *rt; /* Route to the other host */
|
2007-04-21 07:47:35 +02:00
|
|
|
struct iphdr *iph = ip_hdr(skb);
|
2005-04-17 00:20:36 +02:00
|
|
|
u8 tos = iph->tos;
|
|
|
|
int mtu;
|
|
|
|
struct flowi fl = {
|
|
|
|
.oif = 0,
|
|
|
|
.nl_u = {
|
|
|
|
.ip4_u = {
|
|
|
|
.daddr = iph->daddr,
|
|
|
|
.saddr = 0,
|
|
|
|
.tos = RT_TOS(tos), } },
|
|
|
|
};
|
|
|
|
|
|
|
|
EnterFunction(10);
|
|
|
|
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
if (ip_route_output_key(net, &rt, &fl)) {
|
2009-08-02 13:05:41 +02:00
|
|
|
IP_VS_DBG_RL("%s(): ip_route_output error, dest: %pI4\n",
|
|
|
|
__func__, &iph->daddr);
|
2005-04-17 00:20:36 +02:00
|
|
|
goto tx_error_icmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* MTU checking */
|
2010-06-11 08:31:35 +02:00
|
|
|
mtu = dst_mtu(&rt->dst);
|
2007-03-07 06:19:10 +01:00
|
|
|
if ((skb->len > mtu) && (iph->frag_off & htons(IP_DF))) {
|
2005-04-17 00:20:36 +02:00
|
|
|
ip_rt_put(rt);
|
|
|
|
icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
|
2009-08-02 13:05:41 +02:00
|
|
|
IP_VS_DBG_RL("%s(): frag needed\n", __func__);
|
2005-04-17 00:20:36 +02:00
|
|
|
goto tx_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Call ip_send_check because we are not sure it is called
|
|
|
|
* after ip_defrag. Is copy-on-write needed?
|
|
|
|
*/
|
|
|
|
if (unlikely((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)) {
|
|
|
|
ip_rt_put(rt);
|
|
|
|
return NF_STOLEN;
|
|
|
|
}
|
2007-04-21 07:47:35 +02:00
|
|
|
ip_send_check(ip_hdr(skb));
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
/* drop old route */
|
2009-06-02 07:19:30 +02:00
|
|
|
skb_dst_drop(skb);
|
2010-06-11 08:31:35 +02:00
|
|
|
skb_dst_set(skb, &rt->dst);
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
/* Another hack: avoid icmp_send in ip_fragment */
|
|
|
|
skb->local_df = 1;
|
|
|
|
|
2010-09-21 17:35:41 +02:00
|
|
|
IP_VS_XMIT(NFPROTO_IPV4, skb, cp);
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
LeaveFunction(10);
|
|
|
|
return NF_STOLEN;
|
|
|
|
|
|
|
|
tx_error_icmp:
|
|
|
|
dst_link_failure(skb);
|
|
|
|
tx_error:
|
|
|
|
kfree_skb(skb);
|
|
|
|
LeaveFunction(10);
|
|
|
|
return NF_STOLEN;
|
|
|
|
}
|
|
|
|
|
2008-09-02 15:55:45 +02:00
|
|
|
#ifdef CONFIG_IP_VS_IPV6
|
|
|
|
int
|
|
|
|
ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|
|
|
struct ip_vs_protocol *pp)
|
|
|
|
{
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
struct net *net = dev_net(skb->dev);
|
|
|
|
struct dst_entry *dst;
|
2008-09-02 15:55:45 +02:00
|
|
|
struct rt6_info *rt; /* Route to the other host */
|
|
|
|
struct ipv6hdr *iph = ipv6_hdr(skb);
|
|
|
|
int mtu;
|
|
|
|
|
|
|
|
EnterFunction(10);
|
|
|
|
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
dst = __ip_vs_route_output_v6(net, &iph->daddr, NULL, 0);
|
|
|
|
if (!dst)
|
2008-09-02 15:55:45 +02:00
|
|
|
goto tx_error_icmp;
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
rt = (struct rt6_info *) dst;
|
2008-09-02 15:55:45 +02:00
|
|
|
|
|
|
|
/* MTU checking */
|
2010-06-11 08:31:35 +02:00
|
|
|
mtu = dst_mtu(&rt->dst);
|
2008-09-02 15:55:45 +02:00
|
|
|
if (skb->len > mtu) {
|
2010-06-11 08:31:35 +02:00
|
|
|
dst_release(&rt->dst);
|
2010-02-18 09:25:24 +01:00
|
|
|
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
|
2009-08-02 13:05:41 +02:00
|
|
|
IP_VS_DBG_RL("%s(): frag needed\n", __func__);
|
2008-09-02 15:55:45 +02:00
|
|
|
goto tx_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Call ip_send_check because we are not sure it is called
|
|
|
|
* after ip_defrag. Is copy-on-write needed?
|
|
|
|
*/
|
|
|
|
skb = skb_share_check(skb, GFP_ATOMIC);
|
|
|
|
if (unlikely(skb == NULL)) {
|
2010-06-11 08:31:35 +02:00
|
|
|
dst_release(&rt->dst);
|
2008-09-02 15:55:45 +02:00
|
|
|
return NF_STOLEN;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* drop old route */
|
2009-06-02 07:19:30 +02:00
|
|
|
skb_dst_drop(skb);
|
2010-06-11 08:31:35 +02:00
|
|
|
skb_dst_set(skb, &rt->dst);
|
2008-09-02 15:55:45 +02:00
|
|
|
|
|
|
|
/* Another hack: avoid icmp_send in ip_fragment */
|
|
|
|
skb->local_df = 1;
|
|
|
|
|
2010-09-21 17:35:41 +02:00
|
|
|
IP_VS_XMIT(NFPROTO_IPV6, skb, cp);
|
2008-09-02 15:55:45 +02:00
|
|
|
|
|
|
|
LeaveFunction(10);
|
|
|
|
return NF_STOLEN;
|
|
|
|
|
|
|
|
tx_error_icmp:
|
|
|
|
dst_link_failure(skb);
|
|
|
|
tx_error:
|
|
|
|
kfree_skb(skb);
|
|
|
|
LeaveFunction(10);
|
|
|
|
return NF_STOLEN;
|
|
|
|
}
|
|
|
|
#endif
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* NAT transmitter (only for outside-to-inside nat forwarding)
|
|
|
|
* Not used for related ICMP
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|
|
|
struct ip_vs_protocol *pp)
|
|
|
|
{
|
|
|
|
struct rtable *rt; /* Route to the other host */
|
|
|
|
int mtu;
|
2007-04-21 07:47:35 +02:00
|
|
|
struct iphdr *iph = ip_hdr(skb);
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
EnterFunction(10);
|
|
|
|
|
|
|
|
/* check if it is a connection of no-client-port */
|
|
|
|
if (unlikely(cp->flags & IP_VS_CONN_F_NO_CPORT)) {
|
2006-09-28 23:29:52 +02:00
|
|
|
__be16 _pt, *p;
|
2005-04-17 00:20:36 +02:00
|
|
|
p = skb_header_pointer(skb, iph->ihl*4, sizeof(_pt), &_pt);
|
|
|
|
if (p == NULL)
|
|
|
|
goto tx_error;
|
|
|
|
ip_vs_conn_fill_cport(cp, *p);
|
|
|
|
IP_VS_DBG(10, "filled cport=%d\n", ntohs(*p));
|
|
|
|
}
|
|
|
|
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
if (!(rt = __ip_vs_get_out_rt(skb, cp, RT_TOS(iph->tos))))
|
2005-04-17 00:20:36 +02:00
|
|
|
goto tx_error_icmp;
|
|
|
|
|
|
|
|
/* MTU checking */
|
2010-06-11 08:31:35 +02:00
|
|
|
mtu = dst_mtu(&rt->dst);
|
2007-03-07 06:19:10 +01:00
|
|
|
if ((skb->len > mtu) && (iph->frag_off & htons(IP_DF))) {
|
2005-04-17 00:20:36 +02:00
|
|
|
ip_rt_put(rt);
|
|
|
|
icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
|
|
|
|
IP_VS_DBG_RL_PKT(0, pp, skb, 0, "ip_vs_nat_xmit(): frag needed for");
|
|
|
|
goto tx_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy-on-write the packet before mangling it */
|
2007-10-14 09:39:33 +02:00
|
|
|
if (!skb_make_writable(skb, sizeof(struct iphdr)))
|
2005-04-17 00:20:36 +02:00
|
|
|
goto tx_error_put;
|
|
|
|
|
2010-06-11 08:31:35 +02:00
|
|
|
if (skb_cow(skb, rt->dst.dev->hard_header_len))
|
2005-04-17 00:20:36 +02:00
|
|
|
goto tx_error_put;
|
|
|
|
|
|
|
|
/* drop old route */
|
2009-06-02 07:19:30 +02:00
|
|
|
skb_dst_drop(skb);
|
2010-06-11 08:31:35 +02:00
|
|
|
skb_dst_set(skb, &rt->dst);
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
/* mangle the packet */
|
2007-10-15 09:53:15 +02:00
|
|
|
if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp))
|
2005-04-17 00:20:36 +02:00
|
|
|
goto tx_error;
|
2008-09-02 15:55:33 +02:00
|
|
|
ip_hdr(skb)->daddr = cp->daddr.ip;
|
2007-04-21 07:47:35 +02:00
|
|
|
ip_send_check(ip_hdr(skb));
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT");
|
|
|
|
|
|
|
|
/* FIXME: when application helper enlarges the packet and the length
|
|
|
|
is larger than the MTU of outgoing device, there will be still
|
|
|
|
MTU problem. */
|
|
|
|
|
|
|
|
/* Another hack: avoid icmp_send in ip_fragment */
|
|
|
|
skb->local_df = 1;
|
|
|
|
|
2010-09-21 17:35:41 +02:00
|
|
|
IP_VS_XMIT_NAT(NFPROTO_IPV4, skb, cp);
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
LeaveFunction(10);
|
|
|
|
return NF_STOLEN;
|
|
|
|
|
|
|
|
tx_error_icmp:
|
|
|
|
dst_link_failure(skb);
|
|
|
|
tx_error:
|
|
|
|
kfree_skb(skb);
|
2010-09-21 17:35:41 +02:00
|
|
|
LeaveFunction(10);
|
2005-04-17 00:20:36 +02:00
|
|
|
return NF_STOLEN;
|
|
|
|
tx_error_put:
|
|
|
|
ip_rt_put(rt);
|
|
|
|
goto tx_error;
|
|
|
|
}
|
|
|
|
|
2008-09-02 15:55:45 +02:00
|
|
|
#ifdef CONFIG_IP_VS_IPV6
|
|
|
|
int
|
|
|
|
ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|
|
|
struct ip_vs_protocol *pp)
|
|
|
|
{
|
|
|
|
struct rt6_info *rt; /* Route to the other host */
|
|
|
|
int mtu;
|
|
|
|
|
|
|
|
EnterFunction(10);
|
|
|
|
|
|
|
|
/* check if it is a connection of no-client-port */
|
|
|
|
if (unlikely(cp->flags & IP_VS_CONN_F_NO_CPORT)) {
|
|
|
|
__be16 _pt, *p;
|
|
|
|
p = skb_header_pointer(skb, sizeof(struct ipv6hdr),
|
|
|
|
sizeof(_pt), &_pt);
|
|
|
|
if (p == NULL)
|
|
|
|
goto tx_error;
|
|
|
|
ip_vs_conn_fill_cport(cp, *p);
|
|
|
|
IP_VS_DBG(10, "filled cport=%d\n", ntohs(*p));
|
|
|
|
}
|
|
|
|
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
rt = __ip_vs_get_out_rt_v6(skb, cp, NULL, 0);
|
2008-09-02 15:55:45 +02:00
|
|
|
if (!rt)
|
|
|
|
goto tx_error_icmp;
|
|
|
|
|
|
|
|
/* MTU checking */
|
2010-06-11 08:31:35 +02:00
|
|
|
mtu = dst_mtu(&rt->dst);
|
2008-09-02 15:55:45 +02:00
|
|
|
if (skb->len > mtu) {
|
2010-06-11 08:31:35 +02:00
|
|
|
dst_release(&rt->dst);
|
2010-02-18 09:25:24 +01:00
|
|
|
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
|
2008-09-02 15:55:45 +02:00
|
|
|
IP_VS_DBG_RL_PKT(0, pp, skb, 0,
|
|
|
|
"ip_vs_nat_xmit_v6(): frag needed for");
|
|
|
|
goto tx_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy-on-write the packet before mangling it */
|
|
|
|
if (!skb_make_writable(skb, sizeof(struct ipv6hdr)))
|
|
|
|
goto tx_error_put;
|
|
|
|
|
2010-06-11 08:31:35 +02:00
|
|
|
if (skb_cow(skb, rt->dst.dev->hard_header_len))
|
2008-09-02 15:55:45 +02:00
|
|
|
goto tx_error_put;
|
|
|
|
|
|
|
|
/* drop old route */
|
2009-06-02 07:19:30 +02:00
|
|
|
skb_dst_drop(skb);
|
2010-06-11 08:31:35 +02:00
|
|
|
skb_dst_set(skb, &rt->dst);
|
2008-09-02 15:55:45 +02:00
|
|
|
|
|
|
|
/* mangle the packet */
|
|
|
|
if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp))
|
|
|
|
goto tx_error;
|
|
|
|
ipv6_hdr(skb)->daddr = cp->daddr.in6;
|
|
|
|
|
|
|
|
IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT");
|
|
|
|
|
|
|
|
/* FIXME: when application helper enlarges the packet and the length
|
|
|
|
is larger than the MTU of outgoing device, there will be still
|
|
|
|
MTU problem. */
|
|
|
|
|
|
|
|
/* Another hack: avoid icmp_send in ip_fragment */
|
|
|
|
skb->local_df = 1;
|
|
|
|
|
2010-09-21 17:35:41 +02:00
|
|
|
IP_VS_XMIT_NAT(NFPROTO_IPV6, skb, cp);
|
2008-09-02 15:55:45 +02:00
|
|
|
|
|
|
|
LeaveFunction(10);
|
|
|
|
return NF_STOLEN;
|
|
|
|
|
|
|
|
tx_error_icmp:
|
|
|
|
dst_link_failure(skb);
|
|
|
|
tx_error:
|
|
|
|
LeaveFunction(10);
|
|
|
|
kfree_skb(skb);
|
|
|
|
return NF_STOLEN;
|
|
|
|
tx_error_put:
|
2010-06-11 08:31:35 +02:00
|
|
|
dst_release(&rt->dst);
|
2008-09-02 15:55:45 +02:00
|
|
|
goto tx_error;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* IP Tunneling transmitter
|
|
|
|
*
|
|
|
|
* This function encapsulates the packet in a new IP packet, its
|
|
|
|
* destination will be set to cp->daddr. Most code of this function
|
|
|
|
* is taken from ipip.c.
|
|
|
|
*
|
|
|
|
* It is used in VS/TUN cluster. The load balancer selects a real
|
|
|
|
* server from a cluster based on a scheduling algorithm,
|
|
|
|
* encapsulates the request packet and forwards it to the selected
|
|
|
|
* server. For example, all real servers are configured with
|
|
|
|
* "ifconfig tunl0 <Virtual IP Address> up". When the server receives
|
|
|
|
* the encapsulated packet, it will decapsulate the packet, processe
|
|
|
|
* the request and return the response packets directly to the client
|
|
|
|
* without passing the load balancer. This can greatly increase the
|
|
|
|
* scalability of virtual server.
|
|
|
|
*
|
|
|
|
* Used for ANY protocol
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|
|
|
struct ip_vs_protocol *pp)
|
|
|
|
{
|
|
|
|
struct rtable *rt; /* Route to the other host */
|
|
|
|
struct net_device *tdev; /* Device to other host */
|
2007-04-21 07:47:35 +02:00
|
|
|
struct iphdr *old_iph = ip_hdr(skb);
|
2005-04-17 00:20:36 +02:00
|
|
|
u8 tos = old_iph->tos;
|
2006-01-06 22:24:29 +01:00
|
|
|
__be16 df = old_iph->frag_off;
|
2005-04-17 00:20:36 +02:00
|
|
|
struct iphdr *iph; /* Our new IP header */
|
2007-10-24 06:07:32 +02:00
|
|
|
unsigned int max_headroom; /* The extra header space needed */
|
2005-04-17 00:20:36 +02:00
|
|
|
int mtu;
|
2010-09-21 17:35:41 +02:00
|
|
|
int ret;
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
EnterFunction(10);
|
|
|
|
|
2007-03-07 06:19:10 +01:00
|
|
|
if (skb->protocol != htons(ETH_P_IP)) {
|
2009-08-02 13:05:41 +02:00
|
|
|
IP_VS_DBG_RL("%s(): protocol error, "
|
2005-04-17 00:20:36 +02:00
|
|
|
"ETH_P_IP: %d, skb protocol: %d\n",
|
2009-08-02 13:05:41 +02:00
|
|
|
__func__, htons(ETH_P_IP), skb->protocol);
|
2005-04-17 00:20:36 +02:00
|
|
|
goto tx_error;
|
|
|
|
}
|
|
|
|
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
if (!(rt = __ip_vs_get_out_rt(skb, cp, RT_TOS(tos))))
|
2005-04-17 00:20:36 +02:00
|
|
|
goto tx_error_icmp;
|
|
|
|
|
2010-06-11 08:31:35 +02:00
|
|
|
tdev = rt->dst.dev;
|
2005-04-17 00:20:36 +02:00
|
|
|
|
2010-06-11 08:31:35 +02:00
|
|
|
mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr);
|
2005-04-17 00:20:36 +02:00
|
|
|
if (mtu < 68) {
|
|
|
|
ip_rt_put(rt);
|
2009-08-02 13:05:41 +02:00
|
|
|
IP_VS_DBG_RL("%s(): mtu less than 68\n", __func__);
|
2005-04-17 00:20:36 +02:00
|
|
|
goto tx_error;
|
|
|
|
}
|
2009-06-02 07:19:30 +02:00
|
|
|
if (skb_dst(skb))
|
|
|
|
skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu);
|
2005-04-17 00:20:36 +02:00
|
|
|
|
2007-03-07 06:19:10 +01:00
|
|
|
df |= (old_iph->frag_off & htons(IP_DF));
|
2005-04-17 00:20:36 +02:00
|
|
|
|
2007-03-07 06:19:10 +01:00
|
|
|
if ((old_iph->frag_off & htons(IP_DF))
|
2005-04-17 00:20:36 +02:00
|
|
|
&& mtu < ntohs(old_iph->tot_len)) {
|
|
|
|
icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
|
|
|
|
ip_rt_put(rt);
|
2009-08-02 13:05:41 +02:00
|
|
|
IP_VS_DBG_RL("%s(): frag needed\n", __func__);
|
2005-04-17 00:20:36 +02:00
|
|
|
goto tx_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Okay, now see if we can stuff it in the buffer as-is.
|
|
|
|
*/
|
|
|
|
max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct iphdr);
|
|
|
|
|
|
|
|
if (skb_headroom(skb) < max_headroom
|
|
|
|
|| skb_cloned(skb) || skb_shared(skb)) {
|
|
|
|
struct sk_buff *new_skb =
|
|
|
|
skb_realloc_headroom(skb, max_headroom);
|
|
|
|
if (!new_skb) {
|
|
|
|
ip_rt_put(rt);
|
|
|
|
kfree_skb(skb);
|
2009-08-02 13:05:41 +02:00
|
|
|
IP_VS_ERR_RL("%s(): no memory\n", __func__);
|
2005-04-17 00:20:36 +02:00
|
|
|
return NF_STOLEN;
|
|
|
|
}
|
|
|
|
kfree_skb(skb);
|
|
|
|
skb = new_skb;
|
2007-04-21 07:47:35 +02:00
|
|
|
old_iph = ip_hdr(skb);
|
2005-04-17 00:20:36 +02:00
|
|
|
}
|
|
|
|
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
skb->transport_header = skb->network_header;
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
/* fix old IP header checksum */
|
|
|
|
ip_send_check(old_iph);
|
|
|
|
|
2007-04-11 05:46:21 +02:00
|
|
|
skb_push(skb, sizeof(struct iphdr));
|
|
|
|
skb_reset_network_header(skb);
|
2005-04-17 00:20:36 +02:00
|
|
|
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
|
|
|
|
|
|
|
|
/* drop old route */
|
2009-06-02 07:19:30 +02:00
|
|
|
skb_dst_drop(skb);
|
2010-06-11 08:31:35 +02:00
|
|
|
skb_dst_set(skb, &rt->dst);
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Push down and install the IPIP header.
|
|
|
|
*/
|
2007-04-21 07:47:35 +02:00
|
|
|
iph = ip_hdr(skb);
|
2005-04-17 00:20:36 +02:00
|
|
|
iph->version = 4;
|
|
|
|
iph->ihl = sizeof(struct iphdr)>>2;
|
|
|
|
iph->frag_off = df;
|
|
|
|
iph->protocol = IPPROTO_IPIP;
|
|
|
|
iph->tos = tos;
|
|
|
|
iph->daddr = rt->rt_dst;
|
|
|
|
iph->saddr = rt->rt_src;
|
|
|
|
iph->ttl = old_iph->ttl;
|
2010-06-11 08:31:35 +02:00
|
|
|
ip_select_ident(iph, &rt->dst, NULL);
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
/* Another hack: avoid icmp_send in ip_fragment */
|
|
|
|
skb->local_df = 1;
|
|
|
|
|
2010-09-21 17:35:41 +02:00
|
|
|
ret = IP_VS_XMIT_TUNNEL(skb, cp);
|
|
|
|
if (ret == NF_ACCEPT)
|
|
|
|
ip_local_out(skb);
|
|
|
|
else if (ret == NF_DROP)
|
|
|
|
kfree_skb(skb);
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
LeaveFunction(10);
|
|
|
|
|
|
|
|
return NF_STOLEN;
|
|
|
|
|
|
|
|
tx_error_icmp:
|
|
|
|
dst_link_failure(skb);
|
|
|
|
tx_error:
|
|
|
|
kfree_skb(skb);
|
|
|
|
LeaveFunction(10);
|
|
|
|
return NF_STOLEN;
|
|
|
|
}
|
|
|
|
|
2008-09-02 15:55:45 +02:00
|
|
|
#ifdef CONFIG_IP_VS_IPV6
|
|
|
|
int
|
|
|
|
ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|
|
|
struct ip_vs_protocol *pp)
|
|
|
|
{
|
|
|
|
struct rt6_info *rt; /* Route to the other host */
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
struct in6_addr saddr; /* Source for tunnel */
|
2008-09-02 15:55:45 +02:00
|
|
|
struct net_device *tdev; /* Device to other host */
|
|
|
|
struct ipv6hdr *old_iph = ipv6_hdr(skb);
|
|
|
|
struct ipv6hdr *iph; /* Our new IP header */
|
|
|
|
unsigned int max_headroom; /* The extra header space needed */
|
|
|
|
int mtu;
|
2010-09-21 17:35:41 +02:00
|
|
|
int ret;
|
2008-09-02 15:55:45 +02:00
|
|
|
|
|
|
|
EnterFunction(10);
|
|
|
|
|
|
|
|
if (skb->protocol != htons(ETH_P_IPV6)) {
|
2009-08-02 13:05:41 +02:00
|
|
|
IP_VS_DBG_RL("%s(): protocol error, "
|
2008-09-02 15:55:45 +02:00
|
|
|
"ETH_P_IPV6: %d, skb protocol: %d\n",
|
2009-08-02 13:05:41 +02:00
|
|
|
__func__, htons(ETH_P_IPV6), skb->protocol);
|
2008-09-02 15:55:45 +02:00
|
|
|
goto tx_error;
|
|
|
|
}
|
|
|
|
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
rt = __ip_vs_get_out_rt_v6(skb, cp, &saddr, 1);
|
2008-09-02 15:55:45 +02:00
|
|
|
if (!rt)
|
|
|
|
goto tx_error_icmp;
|
|
|
|
|
2010-06-11 08:31:35 +02:00
|
|
|
tdev = rt->dst.dev;
|
2008-09-02 15:55:45 +02:00
|
|
|
|
2010-06-11 08:31:35 +02:00
|
|
|
mtu = dst_mtu(&rt->dst) - sizeof(struct ipv6hdr);
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
if (mtu < IPV6_MIN_MTU) {
|
2010-06-11 08:31:35 +02:00
|
|
|
dst_release(&rt->dst);
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
IP_VS_DBG_RL("%s(): mtu less than %d\n", __func__,
|
|
|
|
IPV6_MIN_MTU);
|
2008-09-02 15:55:45 +02:00
|
|
|
goto tx_error;
|
|
|
|
}
|
2009-06-02 07:19:30 +02:00
|
|
|
if (skb_dst(skb))
|
|
|
|
skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu);
|
2008-09-02 15:55:45 +02:00
|
|
|
|
|
|
|
if (mtu < ntohs(old_iph->payload_len) + sizeof(struct ipv6hdr)) {
|
2010-02-18 09:25:24 +01:00
|
|
|
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
|
2010-06-11 08:31:35 +02:00
|
|
|
dst_release(&rt->dst);
|
2009-08-02 13:05:41 +02:00
|
|
|
IP_VS_DBG_RL("%s(): frag needed\n", __func__);
|
2008-09-02 15:55:45 +02:00
|
|
|
goto tx_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Okay, now see if we can stuff it in the buffer as-is.
|
|
|
|
*/
|
|
|
|
max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct ipv6hdr);
|
|
|
|
|
|
|
|
if (skb_headroom(skb) < max_headroom
|
|
|
|
|| skb_cloned(skb) || skb_shared(skb)) {
|
|
|
|
struct sk_buff *new_skb =
|
|
|
|
skb_realloc_headroom(skb, max_headroom);
|
|
|
|
if (!new_skb) {
|
2010-06-11 08:31:35 +02:00
|
|
|
dst_release(&rt->dst);
|
2008-09-02 15:55:45 +02:00
|
|
|
kfree_skb(skb);
|
2009-08-02 13:05:41 +02:00
|
|
|
IP_VS_ERR_RL("%s(): no memory\n", __func__);
|
2008-09-02 15:55:45 +02:00
|
|
|
return NF_STOLEN;
|
|
|
|
}
|
|
|
|
kfree_skb(skb);
|
|
|
|
skb = new_skb;
|
|
|
|
old_iph = ipv6_hdr(skb);
|
|
|
|
}
|
|
|
|
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
skb->transport_header = skb->network_header;
|
2008-09-02 15:55:45 +02:00
|
|
|
|
|
|
|
skb_push(skb, sizeof(struct ipv6hdr));
|
|
|
|
skb_reset_network_header(skb);
|
|
|
|
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
|
|
|
|
|
|
|
|
/* drop old route */
|
2009-06-02 07:19:30 +02:00
|
|
|
skb_dst_drop(skb);
|
2010-06-11 08:31:35 +02:00
|
|
|
skb_dst_set(skb, &rt->dst);
|
2008-09-02 15:55:45 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Push down and install the IPIP header.
|
|
|
|
*/
|
|
|
|
iph = ipv6_hdr(skb);
|
|
|
|
iph->version = 6;
|
|
|
|
iph->nexthdr = IPPROTO_IPV6;
|
2008-11-11 01:46:06 +01:00
|
|
|
iph->payload_len = old_iph->payload_len;
|
|
|
|
be16_add_cpu(&iph->payload_len, sizeof(*old_iph));
|
2008-09-02 15:55:45 +02:00
|
|
|
iph->priority = old_iph->priority;
|
|
|
|
memset(&iph->flow_lbl, 0, sizeof(iph->flow_lbl));
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
ipv6_addr_copy(&iph->daddr, &cp->daddr.in6);
|
|
|
|
ipv6_addr_copy(&iph->saddr, &saddr);
|
2008-09-02 15:55:45 +02:00
|
|
|
iph->hop_limit = old_iph->hop_limit;
|
|
|
|
|
|
|
|
/* Another hack: avoid icmp_send in ip_fragment */
|
|
|
|
skb->local_df = 1;
|
|
|
|
|
2010-09-21 17:35:41 +02:00
|
|
|
ret = IP_VS_XMIT_TUNNEL(skb, cp);
|
|
|
|
if (ret == NF_ACCEPT)
|
|
|
|
ip6_local_out(skb);
|
|
|
|
else if (ret == NF_DROP)
|
|
|
|
kfree_skb(skb);
|
2008-09-02 15:55:45 +02:00
|
|
|
|
|
|
|
LeaveFunction(10);
|
|
|
|
|
|
|
|
return NF_STOLEN;
|
|
|
|
|
|
|
|
tx_error_icmp:
|
|
|
|
dst_link_failure(skb);
|
|
|
|
tx_error:
|
|
|
|
kfree_skb(skb);
|
|
|
|
LeaveFunction(10);
|
|
|
|
return NF_STOLEN;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Direct Routing transmitter
|
|
|
|
* Used for ANY protocol
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|
|
|
struct ip_vs_protocol *pp)
|
|
|
|
{
|
|
|
|
struct rtable *rt; /* Route to the other host */
|
2007-04-21 07:47:35 +02:00
|
|
|
struct iphdr *iph = ip_hdr(skb);
|
2005-04-17 00:20:36 +02:00
|
|
|
int mtu;
|
|
|
|
|
|
|
|
EnterFunction(10);
|
|
|
|
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
if (!(rt = __ip_vs_get_out_rt(skb, cp, RT_TOS(iph->tos))))
|
2005-04-17 00:20:36 +02:00
|
|
|
goto tx_error_icmp;
|
|
|
|
|
|
|
|
/* MTU checking */
|
2010-06-11 08:31:35 +02:00
|
|
|
mtu = dst_mtu(&rt->dst);
|
2007-03-07 06:19:10 +01:00
|
|
|
if ((iph->frag_off & htons(IP_DF)) && skb->len > mtu) {
|
2005-04-17 00:20:36 +02:00
|
|
|
icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
|
|
|
|
ip_rt_put(rt);
|
2009-08-02 13:05:41 +02:00
|
|
|
IP_VS_DBG_RL("%s(): frag needed\n", __func__);
|
2005-04-17 00:20:36 +02:00
|
|
|
goto tx_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Call ip_send_check because we are not sure it is called
|
|
|
|
* after ip_defrag. Is copy-on-write needed?
|
|
|
|
*/
|
|
|
|
if (unlikely((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)) {
|
|
|
|
ip_rt_put(rt);
|
|
|
|
return NF_STOLEN;
|
|
|
|
}
|
2007-04-21 07:47:35 +02:00
|
|
|
ip_send_check(ip_hdr(skb));
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
/* drop old route */
|
2009-06-02 07:19:30 +02:00
|
|
|
skb_dst_drop(skb);
|
2010-06-11 08:31:35 +02:00
|
|
|
skb_dst_set(skb, &rt->dst);
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
/* Another hack: avoid icmp_send in ip_fragment */
|
|
|
|
skb->local_df = 1;
|
|
|
|
|
2010-09-21 17:35:41 +02:00
|
|
|
IP_VS_XMIT(NFPROTO_IPV4, skb, cp);
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
LeaveFunction(10);
|
|
|
|
return NF_STOLEN;
|
|
|
|
|
|
|
|
tx_error_icmp:
|
|
|
|
dst_link_failure(skb);
|
|
|
|
tx_error:
|
|
|
|
kfree_skb(skb);
|
|
|
|
LeaveFunction(10);
|
|
|
|
return NF_STOLEN;
|
|
|
|
}
|
|
|
|
|
2008-09-02 15:55:45 +02:00
|
|
|
#ifdef CONFIG_IP_VS_IPV6
|
|
|
|
int
|
|
|
|
ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|
|
|
struct ip_vs_protocol *pp)
|
|
|
|
{
|
|
|
|
struct rt6_info *rt; /* Route to the other host */
|
|
|
|
int mtu;
|
|
|
|
|
|
|
|
EnterFunction(10);
|
|
|
|
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
rt = __ip_vs_get_out_rt_v6(skb, cp, NULL, 0);
|
2008-09-02 15:55:45 +02:00
|
|
|
if (!rt)
|
|
|
|
goto tx_error_icmp;
|
|
|
|
|
|
|
|
/* MTU checking */
|
2010-06-11 08:31:35 +02:00
|
|
|
mtu = dst_mtu(&rt->dst);
|
2008-09-02 15:55:45 +02:00
|
|
|
if (skb->len > mtu) {
|
2010-02-18 09:25:24 +01:00
|
|
|
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
|
2010-06-11 08:31:35 +02:00
|
|
|
dst_release(&rt->dst);
|
2009-08-02 13:05:41 +02:00
|
|
|
IP_VS_DBG_RL("%s(): frag needed\n", __func__);
|
2008-09-02 15:55:45 +02:00
|
|
|
goto tx_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Call ip_send_check because we are not sure it is called
|
|
|
|
* after ip_defrag. Is copy-on-write needed?
|
|
|
|
*/
|
|
|
|
skb = skb_share_check(skb, GFP_ATOMIC);
|
|
|
|
if (unlikely(skb == NULL)) {
|
2010-06-11 08:31:35 +02:00
|
|
|
dst_release(&rt->dst);
|
2008-09-02 15:55:45 +02:00
|
|
|
return NF_STOLEN;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* drop old route */
|
2009-06-02 07:19:30 +02:00
|
|
|
skb_dst_drop(skb);
|
2010-06-11 08:31:35 +02:00
|
|
|
skb_dst_set(skb, &rt->dst);
|
2008-09-02 15:55:45 +02:00
|
|
|
|
|
|
|
/* Another hack: avoid icmp_send in ip_fragment */
|
|
|
|
skb->local_df = 1;
|
|
|
|
|
2010-09-21 17:35:41 +02:00
|
|
|
IP_VS_XMIT(NFPROTO_IPV6, skb, cp);
|
2008-09-02 15:55:45 +02:00
|
|
|
|
|
|
|
LeaveFunction(10);
|
|
|
|
return NF_STOLEN;
|
|
|
|
|
|
|
|
tx_error_icmp:
|
|
|
|
dst_link_failure(skb);
|
|
|
|
tx_error:
|
|
|
|
kfree_skb(skb);
|
|
|
|
LeaveFunction(10);
|
|
|
|
return NF_STOLEN;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* ICMP packet transmitter
|
|
|
|
* called by the ip_vs_in_icmp
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|
|
|
struct ip_vs_protocol *pp, int offset)
|
|
|
|
{
|
|
|
|
struct rtable *rt; /* Route to the other host */
|
|
|
|
int mtu;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
EnterFunction(10);
|
|
|
|
|
|
|
|
/* The ICMP packet for VS/TUN, VS/DR and LOCALNODE will be
|
|
|
|
forwarded directly here, because there is no need to
|
|
|
|
translate address/port back */
|
|
|
|
if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) {
|
|
|
|
if (cp->packet_xmit)
|
|
|
|
rc = cp->packet_xmit(skb, cp, pp);
|
|
|
|
else
|
|
|
|
rc = NF_ACCEPT;
|
|
|
|
/* do not touch skb anymore */
|
|
|
|
atomic_inc(&cp->in_pkts);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* mangle and send the packet here (only for VS/NAT)
|
|
|
|
*/
|
|
|
|
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
if (!(rt = __ip_vs_get_out_rt(skb, cp, RT_TOS(ip_hdr(skb)->tos))))
|
2005-04-17 00:20:36 +02:00
|
|
|
goto tx_error_icmp;
|
|
|
|
|
|
|
|
/* MTU checking */
|
2010-06-11 08:31:35 +02:00
|
|
|
mtu = dst_mtu(&rt->dst);
|
2007-04-21 07:47:35 +02:00
|
|
|
if ((skb->len > mtu) && (ip_hdr(skb)->frag_off & htons(IP_DF))) {
|
2005-04-17 00:20:36 +02:00
|
|
|
ip_rt_put(rt);
|
|
|
|
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
|
2009-08-02 13:05:41 +02:00
|
|
|
IP_VS_DBG_RL("%s(): frag needed\n", __func__);
|
2005-04-17 00:20:36 +02:00
|
|
|
goto tx_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy-on-write the packet before mangling it */
|
2007-10-14 09:39:33 +02:00
|
|
|
if (!skb_make_writable(skb, offset))
|
2005-04-17 00:20:36 +02:00
|
|
|
goto tx_error_put;
|
|
|
|
|
2010-06-11 08:31:35 +02:00
|
|
|
if (skb_cow(skb, rt->dst.dev->hard_header_len))
|
2005-04-17 00:20:36 +02:00
|
|
|
goto tx_error_put;
|
|
|
|
|
|
|
|
/* drop the old route when skb is not shared */
|
2009-06-02 07:19:30 +02:00
|
|
|
skb_dst_drop(skb);
|
2010-06-11 08:31:35 +02:00
|
|
|
skb_dst_set(skb, &rt->dst);
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
ip_vs_nat_icmp(skb, pp, cp, 0);
|
|
|
|
|
|
|
|
/* Another hack: avoid icmp_send in ip_fragment */
|
|
|
|
skb->local_df = 1;
|
|
|
|
|
2010-09-21 17:35:41 +02:00
|
|
|
IP_VS_XMIT(NFPROTO_IPV4, skb, cp);
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
rc = NF_STOLEN;
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
tx_error_icmp:
|
|
|
|
dst_link_failure(skb);
|
|
|
|
tx_error:
|
|
|
|
dev_kfree_skb(skb);
|
|
|
|
rc = NF_STOLEN;
|
|
|
|
out:
|
|
|
|
LeaveFunction(10);
|
|
|
|
return rc;
|
|
|
|
tx_error_put:
|
|
|
|
ip_rt_put(rt);
|
|
|
|
goto tx_error;
|
|
|
|
}
|
2008-09-02 15:55:45 +02:00
|
|
|
|
|
|
|
#ifdef CONFIG_IP_VS_IPV6
|
|
|
|
int
|
|
|
|
ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|
|
|
struct ip_vs_protocol *pp, int offset)
|
|
|
|
{
|
|
|
|
struct rt6_info *rt; /* Route to the other host */
|
|
|
|
int mtu;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
EnterFunction(10);
|
|
|
|
|
|
|
|
/* The ICMP packet for VS/TUN, VS/DR and LOCALNODE will be
|
|
|
|
forwarded directly here, because there is no need to
|
|
|
|
translate address/port back */
|
|
|
|
if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) {
|
|
|
|
if (cp->packet_xmit)
|
|
|
|
rc = cp->packet_xmit(skb, cp, pp);
|
|
|
|
else
|
|
|
|
rc = NF_ACCEPT;
|
|
|
|
/* do not touch skb anymore */
|
|
|
|
atomic_inc(&cp->in_pkts);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* mangle and send the packet here (only for VS/NAT)
|
|
|
|
*/
|
|
|
|
|
ipvs: IPv6 tunnel mode
IPv6 encapsulation uses a bad source address for the tunnel.
i.e. VIP will be used as local-addr and encap. dst addr.
Decapsulation will not accept this.
Example
LVS (eth1 2003::2:0:1/96, VIP 2003::2:0:100)
(eth0 2003::1:0:1/96)
RS (ethX 2003::1:0:5/96)
tcpdump
2003::2:0:100 > 2003::1:0:5: IP6 (hlim 63, next-header TCP (6) payload length: 40) 2003::3:0:10.50991 > 2003::2:0:100.http: Flags [S], cksum 0x7312 (correct), seq 3006460279, win 5760, options [mss 1440,sackOK,TS val 1904932 ecr 0,nop,wscale 3], length 0
In Linux IPv6 impl. you can't have a tunnel with an any cast address
receiving packets (I have not tried to interpret RFC 2473)
To have receive capabilities the tunnel must have:
- Local address set as multicast addr or an unicast addr
- Remote address set as an unicast addr.
- Loop back addres or Link local address are not allowed.
This causes us to setup a tunnel in the Real Server with the
LVS as the remote address, here you can't use the VIP address since it's
used inside the tunnel.
Solution
Use outgoing interface IPv6 address (match against the destination).
i.e. use ip6_route_output() to look up the route cache and
then use ipv6_dev_get_saddr(...) to set the source address of the
encapsulated packet.
Additionally, cache the results in new destination
fields: dst_cookie and dst_saddr and properly check the
returned dst from ip6_route_output. We now add xfrm_lookup
call only for the tunneling method where the source address
is a local one.
Signed-off-by:Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-19 10:38:48 +02:00
|
|
|
rt = __ip_vs_get_out_rt_v6(skb, cp, NULL, 0);
|
2008-09-02 15:55:45 +02:00
|
|
|
if (!rt)
|
|
|
|
goto tx_error_icmp;
|
|
|
|
|
|
|
|
/* MTU checking */
|
2010-06-11 08:31:35 +02:00
|
|
|
mtu = dst_mtu(&rt->dst);
|
2008-09-02 15:55:45 +02:00
|
|
|
if (skb->len > mtu) {
|
2010-06-11 08:31:35 +02:00
|
|
|
dst_release(&rt->dst);
|
2010-02-18 09:25:24 +01:00
|
|
|
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
|
2009-08-02 13:05:41 +02:00
|
|
|
IP_VS_DBG_RL("%s(): frag needed\n", __func__);
|
2008-09-02 15:55:45 +02:00
|
|
|
goto tx_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy-on-write the packet before mangling it */
|
|
|
|
if (!skb_make_writable(skb, offset))
|
|
|
|
goto tx_error_put;
|
|
|
|
|
2010-06-11 08:31:35 +02:00
|
|
|
if (skb_cow(skb, rt->dst.dev->hard_header_len))
|
2008-09-02 15:55:45 +02:00
|
|
|
goto tx_error_put;
|
|
|
|
|
|
|
|
/* drop the old route when skb is not shared */
|
2009-06-02 07:19:30 +02:00
|
|
|
skb_dst_drop(skb);
|
2010-06-11 08:31:35 +02:00
|
|
|
skb_dst_set(skb, &rt->dst);
|
2008-09-02 15:55:45 +02:00
|
|
|
|
|
|
|
ip_vs_nat_icmp_v6(skb, pp, cp, 0);
|
|
|
|
|
|
|
|
/* Another hack: avoid icmp_send in ip_fragment */
|
|
|
|
skb->local_df = 1;
|
|
|
|
|
2010-09-21 17:35:41 +02:00
|
|
|
IP_VS_XMIT(NFPROTO_IPV6, skb, cp);
|
2008-09-02 15:55:45 +02:00
|
|
|
|
|
|
|
rc = NF_STOLEN;
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
tx_error_icmp:
|
|
|
|
dst_link_failure(skb);
|
|
|
|
tx_error:
|
|
|
|
dev_kfree_skb(skb);
|
|
|
|
rc = NF_STOLEN;
|
|
|
|
out:
|
|
|
|
LeaveFunction(10);
|
|
|
|
return rc;
|
|
|
|
tx_error_put:
|
2010-06-11 08:31:35 +02:00
|
|
|
dst_release(&rt->dst);
|
2008-09-02 15:55:45 +02:00
|
|
|
goto tx_error;
|
|
|
|
}
|
|
|
|
#endif
|