diff mbox

[net-next,8/8] net: ipv6: RTM_GETROUTE: return matched fib result when requested

Message ID 1495649951-30417-9-git-send-email-roopa@cumulusnetworks.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Roopa Prabhu May 24, 2017, 6:19 p.m. UTC
From: Roopa Prabhu <roopa@cumulusnetworks.com>

This patch adds support to return matched fib result when RTM_F_FIB_MATCH
flag is specified in RTM_GETROUTE request. This is useful for user-space
applications/controllers wanting to query a matching route.

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
 net/ipv6/route.c | 36 +++++++++++++++++++++++++++++-------
 1 file changed, 29 insertions(+), 7 deletions(-)

Comments

David Ahern May 25, 2017, 2:35 a.m. UTC | #1
Since you have to do a v2 ...

On 5/24/17 12:19 PM, Roopa Prabhu wrote:
> @@ -3622,6 +3623,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
>  	memset(&fl6, 0, sizeof(fl6));
>  	rtm = nlmsg_data(nlh);
>  	fl6.flowlabel = ip6_make_flowinfo(rtm->rtm_tos, 0);
> +	fibmatch = (rtm->rtm_flags & RTM_F_FIB_MATCH) ? true : false;
this is typically done as !!(rtm->rtm_flags & RTM_F_FIB_MATCH)
>  
>  	if (tb[RTA_SRC]) {
>  		if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
> @@ -3667,12 +3669,27 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
>  		if (!ipv6_addr_any(&fl6.saddr))
>  			flags |= RT6_LOOKUP_F_HAS_SADDR;
>  
> -		rt = (struct rt6_info *)ip6_route_input_lookup(net, dev, &fl6,
> -							       flags);
> +		if (!fibmatch)
> +			rt = (struct rt6_info *)ip6_route_input_lookup(net, dev,
> +								       &fl6,
> +								       flags);
>  	} else {
>  		fl6.flowi6_oif = oif;
>  
> -		rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6);
> +		if (!fibmatch)
> +			rt = (struct rt6_info *)ip6_route_output_flags(net,
> +								       NULL,
> +								       &fl6, 0);
> +	}
> +
> +	if (fibmatch) {
> +		rt = (struct rt6_info *)ip6_route_lookup(net, &fl6, 0);
> +		if (rt->dst.error) {
> +			err = rt->dst.error;
> +			ip6_rt_put(rt);
> +			goto errout;
> +		}
> +

I'd prefer to see the typecasts go away and use container_of to go from
dst_entry to rt6_info. I realize some of this is movement of existing
code, but better to clean up as we go.
Roopa Prabhu May 25, 2017, 3:54 p.m. UTC | #2
On Wed, May 24, 2017 at 7:35 PM, David Ahern <dsahern@gmail.com> wrote:
> Since you have to do a v2 ...
>
> On 5/24/17 12:19 PM, Roopa Prabhu wrote:
>> @@ -3622,6 +3623,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
>>       memset(&fl6, 0, sizeof(fl6));
>>       rtm = nlmsg_data(nlh);
>>       fl6.flowlabel = ip6_make_flowinfo(rtm->rtm_tos, 0);
>> +     fibmatch = (rtm->rtm_flags & RTM_F_FIB_MATCH) ? true : false;
> this is typically done as !!(rtm->rtm_flags & RTM_F_FIB_MATCH)

ack,


>>
>>       if (tb[RTA_SRC]) {
>>               if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
>> @@ -3667,12 +3669,27 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
>>               if (!ipv6_addr_any(&fl6.saddr))
>>                       flags |= RT6_LOOKUP_F_HAS_SADDR;
>>
>> -             rt = (struct rt6_info *)ip6_route_input_lookup(net, dev, &fl6,
>> -                                                            flags);
>> +             if (!fibmatch)
>> +                     rt = (struct rt6_info *)ip6_route_input_lookup(net, dev,
>> +                                                                    &fl6,
>> +                                                                    flags);
>>       } else {
>>               fl6.flowi6_oif = oif;
>>
>> -             rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6);
>> +             if (!fibmatch)
>> +                     rt = (struct rt6_info *)ip6_route_output_flags(net,
>> +                                                                    NULL,
>> +                                                                    &fl6, 0);
>> +     }
>> +
>> +     if (fibmatch) {
>> +             rt = (struct rt6_info *)ip6_route_lookup(net, &fl6, 0);
>> +             if (rt->dst.error) {
>> +                     err = rt->dst.error;
>> +                     ip6_rt_put(rt);
>> +                     goto errout;
>> +             }
>> +
>
> I'd prefer to see the typecasts go away and use container_of to go from
> dst_entry to rt6_info. I realize some of this is movement of existing
> code, but better to clean up as we go.
>

ack. But that is pretty much all of ipv6 code. so, seems better done
with an incremental cleanup patch.


thanks for the review.
David Ahern May 25, 2017, 4 p.m. UTC | #3
> On May 25, 2017, at 9:54 AM, Roopa Prabhu <roopa@cumulusnetworks.com> wrote:
> 
>> 
>> I'd prefer to see the typecasts go away and use container_of to go from
>> dst_entry to rt6_info. I realize some of this is movement of existing
>> code, but better to clean up as we go.
>> 
> 
> ack. But that is pretty much all of ipv6 code. so, seems better done
> with an incremental cleanup patch.
> 

For the rest of the ipv6 code, yes. We can do the right thing now for new code and changes to existing code.
diff mbox

Patch

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 80bda31..c4d6da9 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -3612,6 +3612,7 @@  static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 	struct rtmsg *rtm;
 	struct flowi6 fl6;
 	int err, iif = 0, oif = 0;
+	bool fibmatch;
 
 	err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy,
 			  extack);
@@ -3622,6 +3623,7 @@  static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 	memset(&fl6, 0, sizeof(fl6));
 	rtm = nlmsg_data(nlh);
 	fl6.flowlabel = ip6_make_flowinfo(rtm->rtm_tos, 0);
+	fibmatch = (rtm->rtm_flags & RTM_F_FIB_MATCH) ? true : false;
 
 	if (tb[RTA_SRC]) {
 		if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
@@ -3667,12 +3669,27 @@  static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 		if (!ipv6_addr_any(&fl6.saddr))
 			flags |= RT6_LOOKUP_F_HAS_SADDR;
 
-		rt = (struct rt6_info *)ip6_route_input_lookup(net, dev, &fl6,
-							       flags);
+		if (!fibmatch)
+			rt = (struct rt6_info *)ip6_route_input_lookup(net, dev,
+								       &fl6,
+								       flags);
 	} else {
 		fl6.flowi6_oif = oif;
 
-		rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6);
+		if (!fibmatch)
+			rt = (struct rt6_info *)ip6_route_output_flags(net,
+								       NULL,
+								       &fl6, 0);
+	}
+
+	if (fibmatch) {
+		rt = (struct rt6_info *)ip6_route_lookup(net, &fl6, 0);
+		if (rt->dst.error) {
+			err = rt->dst.error;
+			ip6_rt_put(rt);
+			goto errout;
+		}
+
 	}
 
 	if (rt == net->ipv6.ip6_null_entry) {
@@ -3689,10 +3706,15 @@  static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 	}
 
 	skb_dst_set(skb, &rt->dst);
-
-	err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif,
-			    RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
-			    nlh->nlmsg_seq, 0);
+	if (fibmatch) {
+		err = rt6_fill_node(net, skb, rt, NULL, NULL, iif,
+				    RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
+				    nlh->nlmsg_seq, 0);
+	} else {
+		err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif,
+				    RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
+				    nlh->nlmsg_seq, 0);
+	}
 	if (err < 0) {
 		kfree_skb(skb);
 		goto errout;