};
struct net_vrf {
- struct rtable __rcu *rth;
- struct rt6_info __rcu *rt6;
+ struct rtable *rth;
+ struct rt6_info *rt6;
#if IS_ENABLED(CONFIG_IPV6)
struct fib6_table *fib6_table;
#endif
struct sk_buff *skb)
{
struct net_vrf *vrf = netdev_priv(vrf_dev);
- struct dst_entry *dst = NULL;
struct rt6_info *rt6;
- rcu_read_lock();
-
- rt6 = rcu_dereference(vrf->rt6);
- if (likely(rt6)) {
- dst = &rt6->dst;
- dst_hold(dst);
- }
-
- rcu_read_unlock();
-
- if (unlikely(!dst)) {
- vrf_tx_error(vrf_dev, skb);
- return NULL;
- }
+ rt6 = vrf->rt6;
+ dst_hold(&rt6->dst);
skb_dst_drop(skb);
- skb_dst_set(skb, dst);
+ skb_dst_set(skb, &rt6->dst);
return skb;
}
/* holding rtnl */
static void vrf_rt6_release(struct net_device *dev, struct net_vrf *vrf)
{
- struct rt6_info *rt6 = rtnl_dereference(vrf->rt6);
-
- RCU_INIT_POINTER(vrf->rt6, NULL);
- synchronize_rcu();
+ struct rt6_info *rt6 = vrf->rt6;
if (rt6) {
dst_dev_put(&rt6->dst);
rt6->dst.output = vrf_output6;
- rcu_assign_pointer(vrf->rt6, rt6);
+ vrf->rt6 = rt6;
rc = 0;
out:
struct sk_buff *skb)
{
struct net_vrf *vrf = netdev_priv(vrf_dev);
- struct dst_entry *dst = NULL;
struct rtable *rth;
- rcu_read_lock();
-
- rth = rcu_dereference(vrf->rth);
- if (likely(rth)) {
- dst = &rth->dst;
- dst_hold(dst);
- }
-
- rcu_read_unlock();
-
- if (unlikely(!dst)) {
- vrf_tx_error(vrf_dev, skb);
- return NULL;
- }
+ rth = vrf->rth;
+ dst_hold(&rth->dst);
skb_dst_drop(skb);
- skb_dst_set(skb, dst);
+ skb_dst_set(skb, &rth->dst);
return skb;
}
/* holding rtnl */
static void vrf_rtable_release(struct net_device *dev, struct net_vrf *vrf)
{
- struct rtable *rth = rtnl_dereference(vrf->rth);
-
- RCU_INIT_POINTER(vrf->rth, NULL);
- synchronize_rcu();
+ struct rtable *rth = vrf->rth;
dst_dev_put(&rth->dst);
dst_release(&rth->dst);
rth->dst.output = vrf_output;
- rcu_assign_pointer(vrf->rth, rth);
+ vrf->rth = rth;
return 0;
}