diff options
author | YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org> | 2013-01-21 06:49:03 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-01-21 13:33:17 -0500 |
commit | f4de84c64e3d801965ee4c6dadd19b76b9424bbf (patch) | |
tree | 0f502d604d5b53901c5a95842e12a018fefec914 /net/ipv6/ndisc.c | |
parent | aa4bdd4b3f43274252c1280f6464850b0f004fc8 (diff) | |
download | op-kernel-dev-f4de84c64e3d801965ee4c6dadd19b76b9424bbf.zip op-kernel-dev-f4de84c64e3d801965ee4c6dadd19b76b9424bbf.tar.gz |
ndisc: Use ndisc_send_skb() for redirect.
Reuse dst if one is attached with skb.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/ndisc.c')
-rw-r--r-- | net/ipv6/ndisc.c | 37 |
1 files changed, 14 insertions, 23 deletions
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index f0c436b..437781c 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -467,10 +467,8 @@ static void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr, const struct in6_addr *saddr) { - struct flowi6 fl6; - struct dst_entry *dst; + struct dst_entry *dst = skb_dst(skb); struct net *net = dev_net(skb->dev); - struct sock *sk = net->ipv6.ndisc_sk; struct inet6_dev *idev; int err; struct icmp6hdr *icmp6h = icmp6_hdr(skb); @@ -478,14 +476,19 @@ static void ndisc_send_skb(struct sk_buff *skb, type = icmp6h->icmp6_type; - icmpv6_flow_init(sk, &fl6, type, saddr, daddr, skb->dev->ifindex); - dst = icmp6_dst_alloc(skb->dev, &fl6); - if (IS_ERR(dst)) { - kfree_skb(skb); - return; - } + if (!dst) { + struct sock *sk = net->ipv6.ndisc_sk; + struct flowi6 fl6; - skb_dst_set(skb, dst); + icmpv6_flow_init(sk, &fl6, type, saddr, daddr, skb->dev->ifindex); + dst = icmp6_dst_alloc(skb->dev, &fl6); + if (IS_ERR(dst)) { + kfree_skb(skb); + return; + } + + skb_dst_set(skb, dst); + } rcu_read_lock(); idev = __in6_dev_get(dst->dev); @@ -1404,10 +1407,8 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) struct in6_addr saddr_buf; struct rt6_info *rt; struct dst_entry *dst; - struct inet6_dev *idev; struct flowi6 fl6; int rd_len; - int err; u8 ha_buf[MAX_ADDR_LEN], *ha = NULL; bool ret; @@ -1515,17 +1516,7 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) inet6_sk(sk)->hop_limit, buff->len); skb_dst_set(buff, dst); - rcu_read_lock(); - idev = __in6_dev_get(dst->dev); - IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); - err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev, - dst_output); - if (!err) { - ICMP6MSGOUT_INC_STATS(net, idev, NDISC_REDIRECT); - ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); - } - - rcu_read_unlock(); + ndisc_send_skb(buff, &ipv6_hdr(skb)->saddr, &saddr_buf); return; release: |