Skip to content

Commit 4f04256

Browse files
dsaherndavem330
authored andcommitted
net: vrf: Drop local rtable and rt6_info
The VRF cached rtable and rt6_info for local traffic are no longer needed and actually prevent local traffic through enslaved devices. Remove them. Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 9438c87 commit 4f04256

File tree

1 file changed

+8
-114
lines changed

1 file changed

+8
-114
lines changed

drivers/net/vrf.c

Lines changed: 8 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,7 @@ static unsigned int vrf_net_id;
4747

4848
struct net_vrf {
4949
struct rtable __rcu *rth;
50-
struct rtable __rcu *rth_local;
5150
struct rt6_info __rcu *rt6;
52-
struct rt6_info __rcu *rt6_local;
5351
u32 tb_id;
5452
};
5553

@@ -194,42 +192,10 @@ static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb,
194192

195193
/* if dst.dev is loopback or the VRF device again this is locally
196194
* originated traffic destined to a local address. Short circuit
197-
* to Rx path using our local dst
195+
* to Rx path
198196
*/
199-
if (dst->dev == net->loopback_dev || dst->dev == dev) {
200-
struct net_vrf *vrf = netdev_priv(dev);
201-
struct rt6_info *rt6_local;
202-
203-
/* release looked up dst and use cached local dst */
204-
dst_release(dst);
205-
206-
rcu_read_lock();
207-
208-
rt6_local = rcu_dereference(vrf->rt6_local);
209-
if (unlikely(!rt6_local)) {
210-
rcu_read_unlock();
211-
goto err;
212-
}
213-
214-
/* Ordering issue: cached local dst is created on newlink
215-
* before the IPv6 initialization. Using the local dst
216-
* requires rt6i_idev to be set so make sure it is.
217-
*/
218-
if (unlikely(!rt6_local->rt6i_idev)) {
219-
rt6_local->rt6i_idev = in6_dev_get(dev);
220-
if (!rt6_local->rt6i_idev) {
221-
rcu_read_unlock();
222-
goto err;
223-
}
224-
}
225-
226-
dst = &rt6_local->dst;
227-
dst_hold(dst);
228-
229-
rcu_read_unlock();
230-
231-
return vrf_local_xmit(skb, dev, &rt6_local->dst);
232-
}
197+
if (dst->dev == dev)
198+
return vrf_local_xmit(skb, dev, dst);
233199

234200
skb_dst_set(skb, dst);
235201

@@ -296,30 +262,10 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
296262

297263
/* if dst.dev is loopback or the VRF device again this is locally
298264
* originated traffic destined to a local address. Short circuit
299-
* to Rx path using our local dst
265+
* to Rx path
300266
*/
301-
if (rt->dst.dev == net->loopback_dev || rt->dst.dev == vrf_dev) {
302-
struct net_vrf *vrf = netdev_priv(vrf_dev);
303-
struct rtable *rth_local;
304-
struct dst_entry *dst = NULL;
305-
306-
ip_rt_put(rt);
307-
308-
rcu_read_lock();
309-
310-
rth_local = rcu_dereference(vrf->rth_local);
311-
if (likely(rth_local)) {
312-
dst = &rth_local->dst;
313-
dst_hold(dst);
314-
}
315-
316-
rcu_read_unlock();
317-
318-
if (unlikely(!dst))
319-
goto err;
320-
321-
return vrf_local_xmit(skb, vrf_dev, dst);
322-
}
267+
if (rt->dst.dev == vrf_dev)
268+
return vrf_local_xmit(skb, vrf_dev, &rt->dst);
323269

324270
skb_dst_set(skb, &rt->dst);
325271

@@ -528,12 +474,10 @@ static struct sk_buff *vrf_ip6_out(struct net_device *vrf_dev,
528474
static void vrf_rt6_release(struct net_device *dev, struct net_vrf *vrf)
529475
{
530476
struct rt6_info *rt6 = rtnl_dereference(vrf->rt6);
531-
struct rt6_info *rt6_local = rtnl_dereference(vrf->rt6_local);
532477
struct net *net = dev_net(dev);
533478
struct dst_entry *dst;
534479

535480
RCU_INIT_POINTER(vrf->rt6, NULL);
536-
RCU_INIT_POINTER(vrf->rt6_local, NULL);
537481
synchronize_rcu();
538482

539483
/* move dev in dst's to loopback so this VRF device can be deleted
@@ -546,19 +490,6 @@ static void vrf_rt6_release(struct net_device *dev, struct net_vrf *vrf)
546490
dev_hold(dst->dev);
547491
dst_release(dst);
548492
}
549-
550-
if (rt6_local) {
551-
if (rt6_local->rt6i_idev) {
552-
in6_dev_put(rt6_local->rt6i_idev);
553-
rt6_local->rt6i_idev = NULL;
554-
}
555-
556-
dst = &rt6_local->dst;
557-
dev_put(dst->dev);
558-
dst->dev = net->loopback_dev;
559-
dev_hold(dst->dev);
560-
dst_release(dst);
561-
}
562493
}
563494

564495
static int vrf_rt6_create(struct net_device *dev)
@@ -567,7 +498,7 @@ static int vrf_rt6_create(struct net_device *dev)
567498
struct net_vrf *vrf = netdev_priv(dev);
568499
struct net *net = dev_net(dev);
569500
struct fib6_table *rt6i_table;
570-
struct rt6_info *rt6, *rt6_local;
501+
struct rt6_info *rt6;
571502
int rc = -ENOMEM;
572503

573504
/* IPv6 can be CONFIG enabled and then disabled runtime */
@@ -586,22 +517,7 @@ static int vrf_rt6_create(struct net_device *dev)
586517
rt6->rt6i_table = rt6i_table;
587518
rt6->dst.output = vrf_output6;
588519

589-
/* create a dst for local routing - packets sent locally
590-
* to local address via the VRF device as a loopback
591-
*/
592-
rt6_local = ip6_dst_alloc(net, dev, flags);
593-
if (!rt6_local) {
594-
dst_release(&rt6->dst);
595-
goto out;
596-
}
597-
598-
rt6_local->rt6i_idev = in6_dev_get(dev);
599-
rt6_local->rt6i_flags = RTF_UP | RTF_NONEXTHOP | RTF_LOCAL;
600-
rt6_local->rt6i_table = rt6i_table;
601-
rt6_local->dst.input = ip6_input;
602-
603520
rcu_assign_pointer(vrf->rt6, rt6);
604-
rcu_assign_pointer(vrf->rt6_local, rt6_local);
605521

606522
rc = 0;
607523
out:
@@ -788,12 +704,10 @@ static struct sk_buff *vrf_l3_out(struct net_device *vrf_dev,
788704
static void vrf_rtable_release(struct net_device *dev, struct net_vrf *vrf)
789705
{
790706
struct rtable *rth = rtnl_dereference(vrf->rth);
791-
struct rtable *rth_local = rtnl_dereference(vrf->rth_local);
792707
struct net *net = dev_net(dev);
793708
struct dst_entry *dst;
794709

795710
RCU_INIT_POINTER(vrf->rth, NULL);
796-
RCU_INIT_POINTER(vrf->rth_local, NULL);
797711
synchronize_rcu();
798712

799713
/* move dev in dst's to loopback so this VRF device can be deleted
@@ -806,20 +720,12 @@ static void vrf_rtable_release(struct net_device *dev, struct net_vrf *vrf)
806720
dev_hold(dst->dev);
807721
dst_release(dst);
808722
}
809-
810-
if (rth_local) {
811-
dst = &rth_local->dst;
812-
dev_put(dst->dev);
813-
dst->dev = net->loopback_dev;
814-
dev_hold(dst->dev);
815-
dst_release(dst);
816-
}
817723
}
818724

819725
static int vrf_rtable_create(struct net_device *dev)
820726
{
821727
struct net_vrf *vrf = netdev_priv(dev);
822-
struct rtable *rth, *rth_local;
728+
struct rtable *rth;
823729

824730
if (!fib_new_table(dev_net(dev), vrf->tb_id))
825731
return -ENOMEM;
@@ -829,22 +735,10 @@ static int vrf_rtable_create(struct net_device *dev)
829735
if (!rth)
830736
return -ENOMEM;
831737

832-
/* create a dst for local ingress routing - packets sent locally
833-
* to local address via the VRF device as a loopback
834-
*/
835-
rth_local = rt_dst_alloc(dev, RTCF_LOCAL, RTN_LOCAL, 1, 1, 0);
836-
if (!rth_local) {
837-
dst_release(&rth->dst);
838-
return -ENOMEM;
839-
}
840-
841738
rth->dst.output = vrf_output;
842739
rth->rt_table_id = vrf->tb_id;
843740

844-
rth_local->rt_table_id = vrf->tb_id;
845-
846741
rcu_assign_pointer(vrf->rth, rth);
847-
rcu_assign_pointer(vrf->rth_local, rth_local);
848742

849743
return 0;
850744
}

0 commit comments

Comments
 (0)