Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758824Ab1DNOBa (ORCPT ); Thu, 14 Apr 2011 10:01:30 -0400 Received: from elasmtp-scoter.atl.sa.earthlink.net ([209.86.89.67]:52344 "EHLO elasmtp-scoter.atl.sa.earthlink.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758813Ab1DNOBL (ORCPT ); Thu, 14 Apr 2011 10:01:11 -0400 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=dk20050327; d=earthlink.net; b=aMx+lTOoPL7w0zjTsay+Bf9bBiN59npn1utGnNC9uKw1pinzK2USQlfmb5rt+0wp; h=Received:Message-ID:Date:From:Reply-To:User-Agent:MIME-Version:To:CC:Subject:References:In-Reply-To:Content-Type:Content-Transfer-Encoding:X-ELNK-Trace:X-Originating-IP; Message-ID: <4DA6FE25.70608@earthlink.net> Date: Thu, 14 Apr 2011 10:01:09 -0400 From: Stephen Clark Reply-To: sclark46@earthlink.net User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.15) Gecko/20101027 Fedora/3.0.10-1.fc12 Thunderbird/3.0.10 MIME-Version: 1.0 To: Daniel Walter CC: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, davem@davemloft.net Subject: Re: [PATCH 1/1] ipv6: RTA_PREFSRC support for ipv6 route source address selection References: <20110414071057.GB78446@0x90.at> In-Reply-To: <20110414071057.GB78446@0x90.at> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-ELNK-Trace: a437fbc6971e80f61aa676d7e74259b7b3291a7d08dfec795c78f841d0f32331ac9751958821d143350badd9bab72f9c350badd9bab72f9c350badd9bab72f9c X-Originating-IP: 69.22.83.66 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 7045 Lines: 213 On 04/14/2011 03:10 AM, Daniel Walter wrote: > [ipv6] Add support for RTA_PREFSRC > > This patch allows a user to select the preferred source address > for a specific IPv6-Route. It can be set via a netlink message > setting RTA_PREFSRC to a valid IPv6 address which must be > up on the device the route will be bound to. > > > Signed-off-by: Daniel Walter > --- > Repost patch, after fixing some warnings pointed out on netdev@ > applies clean against current linux-2.6 HEAD > > include/net/ip6_fib.h | 2 + > include/net/ip6_route.h | 7 ++++ > net/ipv6/addrconf.c | 2 + > net/ipv6/ip6_output.c | 8 ++-- > net/ipv6/route.c | 72 +++++++++++++++++++++++++++++++++++++++++++++-- > 5 files changed, 84 insertions(+), 7 deletions(-) > > --- > diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h > index bc3cde0..98348d5 100644 > --- a/include/net/ip6_fib.h > +++ b/include/net/ip6_fib.h > @@ -42,6 +42,7 @@ struct fib6_config { > > struct in6_addr fc_dst; > struct in6_addr fc_src; > + struct in6_addr fc_prefsrc; > struct in6_addr fc_gateway; > > unsigned long fc_expires; > @@ -107,6 +108,7 @@ struct rt6_info { > struct rt6key rt6i_dst ____cacheline_aligned_in_smp; > u32 rt6i_flags; > struct rt6key rt6i_src; > + struct rt6key rt6i_prefsrc; > u32 rt6i_metric; > u32 rt6i_peer_genid; > > diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h > index c850e5f..86b1cb4 100644 > --- a/include/net/ip6_route.h > +++ b/include/net/ip6_route.h > @@ -84,6 +84,12 @@ extern int ip6_route_add(struct fib6_config *cfg); > extern int ip6_ins_rt(struct rt6_info *); > extern int ip6_del_rt(struct rt6_info *); > > +extern int ip6_route_get_saddr(struct net *net, > + struct rt6_info *rt, > + struct in6_addr *daddr, > + unsigned int prefs, > + struct in6_addr *saddr); > + > extern struct rt6_info *rt6_lookup(struct net *net, > const struct in6_addr *daddr, > const struct in6_addr *saddr, > @@ -141,6 +147,7 @@ struct rt6_rtnl_dump_arg { > extern int rt6_dump_route(struct rt6_info *rt, void *p_arg); > extern void rt6_ifdown(struct net *net, struct net_device *dev); > extern void rt6_mtu_change(struct net_device *dev, unsigned mtu); > +extern void rt6_remove_prefsrc(struct inet6_ifaddr *ifp); > > > /* > diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c > index 1493534..129d7e1 100644 > --- a/net/ipv6/addrconf.c > +++ b/net/ipv6/addrconf.c > @@ -825,6 +825,8 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) > dst_release(&rt->dst); > } > > + /* clean up prefsrc entries */ > + rt6_remove_prefsrc(ifp); > out: > in6_ifa_put(ifp); > } > diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c > index 46cf7be..1f4c096 100644 > --- a/net/ipv6/ip6_output.c > +++ b/net/ipv6/ip6_output.c > @@ -930,10 +930,10 @@ static int ip6_dst_lookup_tail(struct sock *sk, > goto out_err_release; > > if (ipv6_addr_any(&fl6->saddr)) { > - err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev, > - &fl6->daddr, > - sk ? inet6_sk(sk)->srcprefs : 0, > - &fl6->saddr); > + struct rt6_info *rt = (struct rt6_info *) *dst; > + err = ip6_route_get_saddr(net, rt,&fl6->daddr, > + sk ? inet6_sk(sk)->srcprefs : 0, > + &fl6->saddr); > if (err) > goto out_err_release; > } > diff --git a/net/ipv6/route.c b/net/ipv6/route.c > index 843406f..af26cc10 100644 > --- a/net/ipv6/route.c > +++ b/net/ipv6/route.c > @@ -1325,6 +1325,16 @@ int ip6_route_add(struct fib6_config *cfg) > if (dev == NULL) > goto out; > > + if (!ipv6_addr_any(&cfg->fc_prefsrc)) { > + if (!ipv6_chk_addr(net,&cfg->fc_prefsrc, dev, 0)) { > + err = -EINVAL; > + goto out; > + } > + ipv6_addr_copy(&rt->rt6i_prefsrc.addr,&cfg->fc_prefsrc); > + rt->rt6i_prefsrc.plen = 128; > + } else > + rt->rt6i_prefsrc.plen = 0; > + > if (cfg->fc_flags& (RTF_GATEWAY | RTF_NONEXTHOP)) { > rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl,&rt->rt6i_gateway, dev); > if (IS_ERR(rt->rt6i_nexthop)) { > @@ -2037,6 +2047,55 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, > return rt; > } > > +int ip6_route_get_saddr(struct net *net, > + struct rt6_info *rt, > + struct in6_addr *daddr, > + unsigned int prefs, > + struct in6_addr *saddr) > +{ > + struct inet6_dev *idev = ip6_dst_idev((struct dst_entry*)rt); > + int err = 0; > + if (rt->rt6i_prefsrc.plen) > + ipv6_addr_copy(saddr,&rt->rt6i_prefsrc.addr); > + else > + err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, > + daddr, prefs, saddr); > + return err; > +} > + > +/* remove deleted ip from prefsrc entries */ > +struct arg_dev_net_ip { > + struct net_device *dev; > + struct net *net; > + struct in6_addr *addr; > +}; > + > +static int fib6_remove_prefsrc(struct rt6_info *rt, void *arg) > +{ > + struct net_device *dev = ((struct arg_dev_net_ip *)arg)->dev; > + struct net *net = ((struct arg_dev_net_ip *)arg)->net; > + struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr; > + > + if (((void *)rt->rt6i_dev == dev || dev == NULL)&& > + rt != net->ipv6.ip6_null_entry&& > + ipv6_addr_equal(addr,&rt->rt6i_prefsrc.addr)) { > + /* remove prefsrc entry */ > + rt->rt6i_prefsrc.plen = 0; > + } > + return 0; > +} > + > +void rt6_remove_prefsrc(struct inet6_ifaddr *ifp) > +{ > + struct net *net = dev_net(ifp->idev->dev); > + struct arg_dev_net_ip adni = { > + .dev = ifp->idev->dev, > + .net = net, > + .addr =&ifp->addr, > + }; > + fib6_clean_all(net, fib6_remove_prefsrc, 0,&adni); > +} > + > struct arg_dev_net { > struct net_device *dev; > struct net *net; > @@ -2183,6 +2242,9 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, > nla_memcpy(&cfg->fc_src, tb[RTA_SRC], plen); > } > > + if (tb[RTA_PREFSRC]) > + nla_memcpy(&cfg->fc_prefsrc, tb[RTA_PREFSRC], 16); > + > if (tb[RTA_OIF]) > cfg->fc_ifindex = nla_get_u32(tb[RTA_OIF]); > > @@ -2325,13 +2387,17 @@ static int rt6_fill_node(struct net *net, > #endif > NLA_PUT_U32(skb, RTA_IIF, iif); > } else if (dst) { > - struct inet6_dev *idev = ip6_dst_idev(&rt->dst); > struct in6_addr saddr_buf; > - if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, > - dst, 0,&saddr_buf) == 0) > + if (ip6_route_get_saddr(net, rt, dst, 0,&saddr_buf) == 0) > NLA_PUT(skb, RTA_PREFSRC, 16,&saddr_buf); > } > > + if (rt->rt6i_prefsrc.plen) { > + struct in6_addr saddr_buf; > + ipv6_addr_copy(&saddr_buf,&rt->rt6i_prefsrc.addr); > + NLA_PUT(skb, RTA_PREFSRC, 16,&saddr_buf); > + } > + > if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst))< 0) > goto nla_put_failure; What userspace application will be used to set this? -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/