On 2/26/18 12:17 PM, David Miller wrote:
> From: David Ahern <dsah...@gmail.com>
> Date: Sun, 25 Feb 2018 11:47:18 -0800
> 
>> +static void ip6_rt_init_dst(struct rt6_info *rt, struct rt6_info *ort)
>> +{
>  ...
>> +    rt->dst.error = 0;
>> +    rt->dst.output = ip6_output;
>  ...
>> @@ -930,14 +999,12 @@ static void rt6_set_from(struct rt6_info *rt, struct 
>> rt6_info *from)
>>  
>>  static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort)
>>  {
>> -    rt->dst.input = ort->dst.input;
>> -    rt->dst.output = ort->dst.output;
>> +    ip6_rt_init_dst(rt, ort);
>> +
>>      rt->rt6i_dst = ort->rt6i_dst;
>> -    rt->dst.error = ort->dst.error;
>>      rt->rt6i_idev = ort->rt6i_idev;
>>      if (rt->rt6i_idev)
>>              in6_dev_hold(rt->rt6i_idev);
>> -    rt->dst.lastuse = jiffies;
>>      rt->rt6i_gateway = ort->fib6_nh.nh_gw;
>>      rt->rt6i_flags = ort->rt6i_flags;
>>      rt6_set_from(rt, ort);
> 
> This seems to change behavior.
> 
> In the old code, the dst error value is propagated from 'ort' into 'rt'.
> 
> Here you set it to zero and that's it.
> 
> Is it set somewhere else?
> 
> I don't think you can assume that all routes that go via this copy
> path are not reject routes or other kinds that need the error code
> set, if that is what you were thinking.

Only REJECT routes have dst->error set and the only place that happens
is ip6_route_info_create:

$ egrep -r 'dst.error = |dst->error = ' include net
net/core/dst.c: dst->error = 0;
net/ipv6/route.c:                       rt->dst.error = -EINVAL;
net/ipv6/route.c:                       rt->dst.error = -EACCES;
net/ipv6/route.c:                       rt->dst.error = (cfg->fc_type == 
RTN_THROW) ? -EAGAIN
net/ipv6/route.c:       rt->dst.error = ort->dst.error;


You cut the context, so I will add the diff here:

+static void ip6_rt_init_dst_reject(struct rt6_info *rt, struct rt6_info
*ort)
+{
+       rt->dst.error = ip6_rt_type_to_error(ort->fib6_type);
+
+       switch (ort->fib6_type) {
+       case RTN_BLACKHOLE:
+               rt->dst.output = dst_discard_out;
+               rt->dst.input = dst_discard;
+               break;
+       case RTN_PROHIBIT:
+               rt->dst.output = ip6_pkt_prohibit_out;
+               rt->dst.input = ip6_pkt_prohibit;
+               break;
+       case RTN_THROW:
+       case RTN_UNREACHABLE:
+       default:
+               rt->dst.output = ip6_pkt_discard_out;
+               rt->dst.input = ip6_pkt_discard;
+               break;
+       }
+}
+
+static void ip6_rt_init_dst(struct rt6_info *rt, struct rt6_info *ort)
+{
+       if (ort->rt6i_flags & RTF_REJECT) {
+               ip6_rt_init_dst_reject(rt, ort);
+               return;
+       }
+
+       rt->dst.error = 0;
+       rt->dst.output = ip6_output;
+
+...

So for reject routes we have the above helper which is basically a code
move from ip6_route_info_create.

For non-reject routes dst.error is 0 which is the rest of ip6_rt_init_dst.


Reply via email to