Hello.
In article <20040801195135.16734846.davem@xxxxxxxxxx> (at Sun, 1 Aug 2004
19:51:35 -0700), "David S. Miller" <davem@xxxxxxxxxx> says:
> On Fri, 30 Jul 2004 17:12:05 +0900
> Kazunori Miyazawa <kazunori@xxxxxxxxxxxx> wrote:
>
> > I consider copying flowi(fl_rt) uses too much stack at the moment.
> > I'll re-send the fixed patch again.
>
> I agree, and let's defer this patch until we
> resolve that.
>
> It is simple to fix, I think.
Here's the updated patch.
From: Kazunori Miyazawa <kazunori@xxxxxxxxxxxx>
(Because Miyazawa-san is very busy now,
I'm sending this patch as the proxy of him.)
Please pull from <bk://bk.skbuff.net:20609/linux-2.6-xfrm/>
Thank you.
DIFFSTAT
--------
datagram.c | 13 +++++++++++-
ip6_output.c | 4 ---
raw.c | 11 +++++++++-
tcp_ipv6.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
udp.c | 11 +++++++++-
5 files changed, 91 insertions(+), 10 deletions(-)
CHANGESET
---------
ChangeSet@xxxxxx, 2004-08-28 01:35:09+09:00, kazunori@xxxxxxxxxxxx
[IPV6] XFRM: extract xfrm_lookup() from ip6_dst_lookup() to support source
routing appropriately.
This patch extracts xfrm_lookup() from ip6_dst_lookup()
to support source routing appropriately.
This is because xfrm_lookup() should be performed with the final
destination while ip6_dst_lookup() is called with the next-hop.
Signed-off-by: Kazunori Miyazawa <kazunori@xxxxxxxxxxxx>
Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@xxxxxxxxxxxxxx>
diff -Nru a/net/ipv6/datagram.c b/net/ipv6/datagram.c
--- a/net/ipv6/datagram.c 2004-08-28 01:36:43 +09:00
+++ b/net/ipv6/datagram.c 2004-08-28 01:36:43 +09:00
@@ -38,7 +38,7 @@
struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
struct inet_opt *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
- struct in6_addr *daddr;
+ struct in6_addr *daddr, *final_p = NULL, final;
struct dst_entry *dst;
struct flowi fl;
struct ip6_flowlabel *flowlabel = NULL;
@@ -157,16 +157,27 @@
if (flowlabel) {
if (flowlabel->opt && flowlabel->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *)
flowlabel->opt->srcrt;
+ ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+ final_p = &final;
}
} else if (np->opt && np->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
+ ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+ final_p = &final;
}
err = ip6_dst_lookup(sk, &dst, &fl);
if (err)
goto out;
+ if (final_p)
+ ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+ dst_release(dst);
+ goto out;
+ }
/* source address lookup done in ip6_dst_lookup */
diff -Nru a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
--- a/net/ipv6/ip6_output.c 2004-08-28 01:36:43 +09:00
+++ b/net/ipv6/ip6_output.c 2004-08-28 01:36:43 +09:00
@@ -796,10 +796,6 @@
goto out_err_release;
}
}
- if ((err = xfrm_lookup(dst, fl, sk, 0)) < 0) {
- err = -ENETUNREACH;
- goto out_err_release;
- }
return 0;
diff -Nru a/net/ipv6/raw.c b/net/ipv6/raw.c
--- a/net/ipv6/raw.c 2004-08-28 01:36:43 +09:00
+++ b/net/ipv6/raw.c 2004-08-28 01:36:43 +09:00
@@ -606,7 +606,7 @@
{
struct ipv6_txoptions opt_space;
struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name;
- struct in6_addr *daddr;
+ struct in6_addr *daddr, *final_p = NULL, final;
struct inet_opt *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
struct raw6_opt *raw_opt = raw6_sk(sk);
@@ -729,7 +729,9 @@
/* merge ip6_build_xmit from ip6_output */
if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
+ ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+ final_p = &final;
}
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
@@ -738,6 +740,13 @@
err = ip6_dst_lookup(sk, &dst, &fl);
if (err)
goto out;
+ if (final_p)
+ ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+ dst_release(dst);
+ goto out;
+ }
if (hlimit < 0) {
if (ipv6_addr_is_multicast(&fl.fl6_dst))
diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
--- a/net/ipv6/tcp_ipv6.c 2004-08-28 01:36:43 +09:00
+++ b/net/ipv6/tcp_ipv6.c 2004-08-28 01:36:43 +09:00
@@ -549,7 +549,7 @@
struct inet_opt *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
struct tcp_opt *tp = tcp_sk(sk);
- struct in6_addr *saddr = NULL;
+ struct in6_addr *saddr = NULL, *final_p = NULL, final;
struct flowi fl;
struct dst_entry *dst;
int addr_type;
@@ -666,13 +666,21 @@
if (np->opt && np->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
+ ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+ final_p = &final;
}
err = ip6_dst_lookup(sk, &dst, &fl);
-
if (err)
goto failure;
+ if (final_p)
+ ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+ dst_release(dst);
+ goto failure;
+ }
if (saddr == NULL) {
saddr = &fl.fl6_src;
@@ -793,6 +801,12 @@
sk->sk_err_soft = -err;
goto out;
}
+
+ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+ sk->sk_err_soft = -err;
+ goto out;
+ }
+
} else
dst_hold(dst);
@@ -863,6 +877,7 @@
struct ipv6_pinfo *np = inet6_sk(sk);
struct sk_buff * skb;
struct ipv6_txoptions *opt = NULL;
+ struct in6_addr * final_p = NULL, final;
struct flowi fl;
int err = -1;
@@ -888,12 +903,18 @@
if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
+ ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+ final_p = &final;
}
err = ip6_dst_lookup(sk, &dst, &fl);
if (err)
goto done;
+ if (final_p)
+ ipv6_addr_copy(&fl.fl6_dst, final_p);
+ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+ goto done;
}
skb = tcp_make_synack(sk, dst, req);
@@ -1021,6 +1042,12 @@
/* sk = NULL, but it is safe for now. RST socket required. */
if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
+
+ if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) {
+ dst_release(buff->dst);
+ return;
+ }
+
ip6_xmit(NULL, buff, &fl, NULL, 0);
TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
@@ -1082,6 +1109,10 @@
fl.fl_ip_sport = t1->source;
if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
+ if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) {
+ dst_release(buff->dst);
+ return;
+ }
ip6_xmit(NULL, buff, &fl, NULL, 0);
TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
return;
@@ -1313,6 +1344,7 @@
}
if (dst == NULL) {
+ struct in6_addr *final_p = NULL, final;
struct flowi fl;
memset(&fl, 0, sizeof(fl));
@@ -1320,7 +1352,9 @@
ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
+ ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+ final_p = &final;
}
ipv6_addr_copy(&fl.fl6_src, &req->af.v6_req.loc_addr);
fl.oif = sk->sk_bound_dev_if;
@@ -1329,6 +1363,12 @@
if (ip6_dst_lookup(sk, &dst, &fl))
goto out;
+
+ if (final_p)
+ ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+ if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+ goto out;
}
newsk = tcp_create_openreq_child(sk, req, skb);
@@ -1710,6 +1750,7 @@
if (dst == NULL) {
struct inet_opt *inet = inet_sk(sk);
+ struct in6_addr *final_p = NULL, final;
struct flowi fl;
memset(&fl, 0, sizeof(fl));
@@ -1723,15 +1764,24 @@
if (np->opt && np->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
+ ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+ final_p = &final;
}
err = ip6_dst_lookup(sk, &dst, &fl);
-
if (err) {
sk->sk_route_caps = 0;
return err;
}
+ if (final_p)
+ ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+ sk->sk_err_soft = -err;
+ dst_release(dst);
+ return err;
+ }
ip6_dst_store(sk, dst, NULL);
sk->sk_route_caps = dst->dev->features &
@@ -1772,6 +1822,12 @@
if (err) {
sk->sk_err_soft = -err;
+ return err;
+ }
+
+ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+ sk->sk_route_caps = 0;
+ dst_release(dst);
return err;
}
diff -Nru a/net/ipv6/udp.c b/net/ipv6/udp.c
--- a/net/ipv6/udp.c 2004-08-28 01:36:43 +09:00
+++ b/net/ipv6/udp.c 2004-08-28 01:36:43 +09:00
@@ -627,7 +627,7 @@
struct inet_opt *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name;
- struct in6_addr *daddr;
+ struct in6_addr *daddr, *final_p = NULL, final;
struct ipv6_txoptions *opt = NULL;
struct ip6_flowlabel *flowlabel = NULL;
struct flowi *fl = &inet->cork.fl;
@@ -783,7 +783,9 @@
/* merge ip6_build_xmit from ip6_output */
if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
+ ipv6_addr_copy(&final, &fl->fl6_dst);
ipv6_addr_copy(&fl->fl6_dst, rt0->addr);
+ final_p = &final;
}
if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst))
@@ -792,6 +794,13 @@
err = ip6_dst_lookup(sk, &dst, fl);
if (err)
goto out;
+ if (final_p)
+ ipv6_addr_copy(&fl->fl6_dst, final_p);
+
+ if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) {
+ dst_release(dst);
+ goto out;
+ }
if (hlimit < 0) {
if (ipv6_addr_is_multicast(&fl->fl6_dst))
--
Hideaki YOSHIFUJI @ USAGI Project <yoshfuji@xxxxxxxxxxxxxx>
GPG FP: 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA
|