summaryrefslogtreecommitdiff
path: root/sys/netinet6/ip6_forward.c
diff options
context:
space:
mode:
authorChristopher Pascoe <pascoe@cvs.openbsd.org>2006-06-18 11:47:47 +0000
committerChristopher Pascoe <pascoe@cvs.openbsd.org>2006-06-18 11:47:47 +0000
commit7128c15b3d788036fcd81521f6defea3838851fa (patch)
treee4df6cf82b6c8f0549f702cc93db7ccce4965cc8 /sys/netinet6/ip6_forward.c
parent200b4f43933395e40b0ce709f1a210782bfaaf5f (diff)
Add support for equal-cost multipath IP.
To minimise path disruptions, this implements recommendations made in RFC2992 - the hash-threshold mechanism to select paths based on source/destination IP address pairs, and inserts multipath routes in the middle of the route table. To enable multipath distribution, use: sysctl net.inet.ip.multipath=1 and/or: sysctl net.inet6.ip6.multipath=1 testing norby@ ok claudio@ henning@ hshoexer@
Diffstat (limited to 'sys/netinet6/ip6_forward.c')
-rw-r--r--sys/netinet6/ip6_forward.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
index fb032ed174f..d5a11518ade 100644
--- a/sys/netinet6/ip6_forward.c
+++ b/sys/netinet6/ip6_forward.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip6_forward.c,v 1.34 2004/07/14 20:19:58 dhartmei Exp $ */
+/* $OpenBSD: ip6_forward.c,v 1.35 2006/06/18 11:47:46 pascoe Exp $ */
/* $KAME: ip6_forward.c,v 1.75 2001/06/29 12:42:13 jinmei Exp $ */
/*
@@ -237,7 +237,8 @@ ip6_forward(m, srcrt)
ip6_forward_rt.ro_rt = 0;
}
/* this probably fails but give it a try again */
- rtalloc((struct route *)&ip6_forward_rt);
+ rtalloc_mpath((struct route *)&ip6_forward_rt,
+ &ip6->ip6_src.s6_addr32[0], 0);
}
if (ip6_forward_rt.ro_rt == 0) {
@@ -261,7 +262,8 @@ ip6_forward(m, srcrt)
dst->sin6_family = AF_INET6;
dst->sin6_addr = ip6->ip6_dst;
- rtalloc((struct route *)&ip6_forward_rt);
+ rtalloc_mpath((struct route *)&ip6_forward_rt,
+ &ip6->ip6_src.s6_addr32[0], 0);
if (ip6_forward_rt.ro_rt == 0) {
ip6stat.ip6s_noroute++;
@@ -303,7 +305,7 @@ ip6_forward(m, srcrt)
icmp6_error(mcopy, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_BEYONDSCOPE, 0);
m_freem(m);
- return;
+ goto freert;
}
#ifdef IPSEC
@@ -330,7 +332,7 @@ ip6_forward(m, srcrt)
error = ipsp_process_packet(m, tdb, AF_INET6, 0);
splx(s);
m_freem(mcopy);
- return; /* Nothing more to be done */
+ goto freert;
}
#endif /* IPSEC */
@@ -344,7 +346,7 @@ ip6_forward(m, srcrt)
icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, mtu);
}
m_freem(m);
- return;
+ goto freert;
}
if (rt->rt_flags & RTF_GATEWAY)
@@ -381,7 +383,7 @@ ip6_forward(m, srcrt)
icmp6_error(mcopy, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_ADDR, 0);
m_freem(m);
- return;
+ goto freert;
}
type = ND_REDIRECT;
}
@@ -458,12 +460,12 @@ ip6_forward(m, srcrt)
senderr:
#endif
if (mcopy == NULL)
- return;
+ goto freert;
switch (error) {
case 0:
if (type == ND_REDIRECT) {
icmp6_redirect_output(mcopy, rt);
- return;
+ goto freert;
}
goto freecopy;
@@ -485,9 +487,17 @@ senderr:
break;
}
icmp6_error(mcopy, type, code, 0);
- return;
+ goto freert;
freecopy:
m_freem(mcopy);
+ freert:
+#ifndef SMALL_KERNEL
+ if (ip6_multipath && ip6_forward_rt.ro_rt &&
+ (ip6_forward_rt.ro_rt->rt_flags & RTF_MPATH)) {
+ RTFREE(ip6_forward_rt.ro_rt);
+ ip6_forward_rt.ro_rt = 0;
+ }
+#endif
return;
}