On 11/23/15, 6:15 AM, Robert Shearman wrote:
> On 21/11/15 05:16, Roopa Prabhu wrote:
>> From: Roopa Prabhu <ro...@cumulusnetworks.com>
>>
>> Adds support for RTNH_F_DEAD and RTNH_F_LINKDOWN flags on mpls
>> routes due to link events. Also adds code to ignore dead
>> routes during route selection.
>>
>> Unlike ip routes, mpls routes are not deleted when the route goes
>> dead. This is current mpls behaviour and this patch does not change
>> that. With this patch however, routes will be marked dead.
>> dead routes are not notified to userspace (this is consistent with ipv4
>> routes).
>>
> ...
>> v3 - v4:
>> - removed per route rt_flags and derive it from the nh_flags during
>> dumps
>> - use kmemdup to make a copy of the route during route updates
>> due to link events
>
> Looks much better. Thanks for making those changes Roopa.
>
> I've just a couple of minor comments on this new version.
>
>> +static inline int mpls_route_alloc_size(int num_nh, u8 max_alen_aligned)
>
> I think the standard practice is to not put inline on functions declared in
> .c files, but instead to just let the compiler use its best judgement as to
> whether it's worth inlining or not.
sure, will fix it.
>
>> +{
>> + struct mpls_route *rt;
>> +
>> + return (ALIGN(sizeof(*rt) + num_nh * sizeof(*rt->rt_nh),
>> + VIA_ALEN_ALIGN) + num_nh * max_alen_aligned);
>> +}
>> +
>
>> -static void mpls_ifdown(struct net_device *dev)
>> +static inline bool mpls_route_dev_exists(struct mpls_route *rt,
>
> Ditto.
>
>> + struct net_device *dev)
>> +{
>> + for_nexthops(rt) {
>> + if (rtnl_dereference(nh->nh_dev) != dev)
>> + continue;
>> + return true;
>> + } endfor_nexthops(rt);
>> +
>> + return false;
>> +}
>> +
>> +static void mpls_ifdown(struct net_device *dev, int event)
>> {
>> struct mpls_route __rcu **platform_label;
>> struct net *net = dev_net(dev);
>> - struct mpls_dev *mdev;
>> + struct mpls_route *rt_new;
>> unsigned index;
>>
>> platform_label = rtnl_dereference(net->mpls.platform_label);
>> for (index = 0; index < net->mpls.platform_labels; index++) {
>> struct mpls_route *rt = rtnl_dereference(platform_label[index]);
>> +
>> if (!rt)
>> continue;
>> - for_nexthops(rt) {
>> +
>> + if (!mpls_route_dev_exists(rt, dev))
>> + continue;
>> +
>> + rt_new = kmemdup(rt, mpls_route_alloc_size(rt->rt_nhn,
>> + rt->rt_max_alen),
>> + GFP_KERNEL);
>
> Shouldn't the above line be indented level with the opening bracket of
> kmemdup?
yep. (looks kinda ugly though when i indent it to the opening bracket of
kmemdup)
>
>> + if (!rt_new) {
>> + pr_warn("mpls_ifdown: kmemdup failed\n");
>
> It isn't safe to leave the current route untouched if the net device is being
> deleted, since a nexthop will be left holding a stale pointer to it. Perhaps
> delete the route entirely in that case?
I would not delete the route. But, Would it be bad modifying rt in that case
(ie when rt_new is not possible) ?. It is a remote case..and the side effect
being the datapath will not see the changes atomically.
>
>> + return;
>> + }
>> +
>> + for_nexthops(rt_new) {
>
> Since the nexthop is being changed, this should be change_nexthops. I know
> this was a problem in the existing code you are changing in this patch, if it
> isn't too much trouble it would be good to fix this whilst reindenting it.
ack.
>
>> if (rtnl_dereference(nh->nh_dev) != dev)
>> continue;
>> - nh->nh_dev = NULL;
>> - } endfor_nexthops(rt);
>> + switch (event) {
>> + case NETDEV_DOWN:
>> + case NETDEV_UNREGISTER:
>> + nh->nh_flags |= RTNH_F_DEAD;
>> + /* fall through */
>> + case NETDEV_CHANGE:
>> + nh->nh_flags |= RTNH_F_LINKDOWN;
>> + rt_new->rt_nhn_alive--;
>> + break;
>> + }
>> + if (event == NETDEV_UNREGISTER)
>> + RCU_INIT_POINTER(nh->nh_dev, NULL);
>> + } endfor_nexthops(rt_new);
>> +
>> + mpls_route_update(net, index, rt_new, NULL, false);
>> }
>>
>> - mdev = mpls_dev_get(dev);
>> - if (!mdev)
>> - return;
>> + return;
>> +}
>> +
>> +static void mpls_ifup(struct net_device *dev, unsigned int nh_flags)
>> +{
>> + struct mpls_route __rcu **platform_label;
>> + struct net *net = dev_net(dev);
>> + struct mpls_route *rt_new;
>> + unsigned index;
>> + int alive;
>> +
>> + platform_label = rtnl_dereference(net->mpls.platform_label);
>> + for (index = 0; index < net->mpls.platform_labels; index++) {
>> + struct mpls_route *rt = rtnl_dereference(platform_label[index]);
>> +
>> + if (!rt)
>> + continue;
>> +
>> + if (!mpls_route_dev_exists(rt, dev))
>> + continue;
>>
>> - mpls_dev_sysctl_unregister(mdev);
>> + rt_new = kmemdup(rt, mpls_route_alloc_size(rt->rt_nhn,
>> + rt->rt_max_alen),
>> + GFP_KERNEL);
>> + if (!rt_new) {
>> + pr_warn("mpls_ifdown: kmemdup failed\n");
>> + return;
>> + }
>>
>> - RCU_INIT_POINTER(dev->mpls_ptr, NULL);
>> + alive = 0;
>> + for_nexthops(rt_new) {
>
> Ditto, this should also be change_nexthops.
>
>> + struct net_device *nh_dev =
>> + rtnl_dereference(nh->nh_dev);
>>
>> - kfree_rcu(mdev, rcu);
>> + if (!(nh->nh_flags & nh_flags)) {
>> + alive++;
>> + continue;
>> + }
>> + if (nh_dev != dev)
>> + continue;
>> + alive++;
>> + nh->nh_flags &= ~nh_flags;
>> + } endfor_nexthops(rt_new);
>> +
>> + rt_new->rt_nhn_alive = alive;
>> + mpls_route_update(net, index, rt_new, NULL, false);
>> + }
>> +
>> + return;
>> }
will post v5. thanks for the review.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html