4444
4545struct net_vrf {
4646 struct rtable __rcu * rth ;
47- struct rtable __rcu * rth_local ;
4847 struct rt6_info __rcu * rt6 ;
49- struct rt6_info __rcu * rt6_local ;
5048 u32 tb_id ;
5149};
5250
@@ -56,20 +54,9 @@ struct pcpu_dstats {
5654 u64 tx_drps ;
5755 u64 rx_pkts ;
5856 u64 rx_bytes ;
59- u64 rx_drps ;
6057 struct u64_stats_sync syncp ;
6158};
6259
63- static void vrf_rx_stats (struct net_device * dev , int len )
64- {
65- struct pcpu_dstats * dstats = this_cpu_ptr (dev -> dstats );
66-
67- u64_stats_update_begin (& dstats -> syncp );
68- dstats -> rx_pkts ++ ;
69- dstats -> rx_bytes += len ;
70- u64_stats_update_end (& dstats -> syncp );
71- }
72-
7360static void vrf_tx_error (struct net_device * vrf_dev , struct sk_buff * skb )
7461{
7562 vrf_dev -> stats .tx_errors ++ ;
@@ -104,34 +91,6 @@ static struct rtnl_link_stats64 *vrf_get_stats64(struct net_device *dev,
10491 return stats ;
10592}
10693
107- /* Local traffic destined to local address. Reinsert the packet to rx
108- * path, similar to loopback handling.
109- */
110- static int vrf_local_xmit (struct sk_buff * skb , struct net_device * dev ,
111- struct dst_entry * dst )
112- {
113- int len = skb -> len ;
114-
115- skb_orphan (skb );
116-
117- skb_dst_set (skb , dst );
118- skb_dst_force (skb );
119-
120- /* set pkt_type to avoid skb hitting packet taps twice -
121- * once on Tx and again in Rx processing
122- */
123- skb -> pkt_type = PACKET_LOOPBACK ;
124-
125- skb -> protocol = eth_type_trans (skb , dev );
126-
127- if (likely (netif_rx (skb ) == NET_RX_SUCCESS ))
128- vrf_rx_stats (dev , len );
129- else
130- this_cpu_inc (dev -> dstats -> rx_drps );
131-
132- return NETDEV_TX_OK ;
133- }
134-
13594#if IS_ENABLED (CONFIG_IPV6 )
13695static netdev_tx_t vrf_process_v6_outbound (struct sk_buff * skb ,
13796 struct net_device * dev )
@@ -158,51 +117,8 @@ static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb,
158117 goto err ;
159118
160119 skb_dst_drop (skb );
161-
162- /* if dst.dev is loopback or the VRF device again this is locally
163- * originated traffic destined to a local address. Short circuit
164- * to Rx path using our local dst
165- */
166- if (dst -> dev == net -> loopback_dev || dst -> dev == dev ) {
167- struct net_vrf * vrf = netdev_priv (dev );
168- struct rt6_info * rt6_local ;
169-
170- /* release looked up dst and use cached local dst */
171- dst_release (dst );
172-
173- rcu_read_lock ();
174-
175- rt6_local = rcu_dereference (vrf -> rt6_local );
176- if (unlikely (!rt6_local )) {
177- rcu_read_unlock ();
178- goto err ;
179- }
180-
181- /* Ordering issue: cached local dst is created on newlink
182- * before the IPv6 initialization. Using the local dst
183- * requires rt6i_idev to be set so make sure it is.
184- */
185- if (unlikely (!rt6_local -> rt6i_idev )) {
186- rt6_local -> rt6i_idev = in6_dev_get (dev );
187- if (!rt6_local -> rt6i_idev ) {
188- rcu_read_unlock ();
189- goto err ;
190- }
191- }
192-
193- dst = & rt6_local -> dst ;
194- dst_hold (dst );
195-
196- rcu_read_unlock ();
197-
198- return vrf_local_xmit (skb , dev , & rt6_local -> dst );
199- }
200-
201120 skb_dst_set (skb , dst );
202121
203- /* strip the ethernet header added for pass through VRF device */
204- __skb_pull (skb , skb_network_offset (skb ));
205-
206122 ret = ip6_local_out (net , skb -> sk , skb );
207123 if (unlikely (net_xmit_eval (ret )))
208124 dev -> stats .tx_errors ++ ;
@@ -223,6 +139,29 @@ static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb,
223139}
224140#endif
225141
142+ static int vrf_send_v4_prep (struct sk_buff * skb , struct flowi4 * fl4 ,
143+ struct net_device * vrf_dev )
144+ {
145+ struct rtable * rt ;
146+ int err = 1 ;
147+
148+ rt = ip_route_output_flow (dev_net (vrf_dev ), fl4 , NULL );
149+ if (IS_ERR (rt ))
150+ goto out ;
151+
152+ /* TO-DO: what about broadcast ? */
153+ if (rt -> rt_type != RTN_UNICAST && rt -> rt_type != RTN_LOCAL ) {
154+ ip_rt_put (rt );
155+ goto out ;
156+ }
157+
158+ skb_dst_drop (skb );
159+ skb_dst_set (skb , & rt -> dst );
160+ err = 0 ;
161+ out :
162+ return err ;
163+ }
164+
226165static netdev_tx_t vrf_process_v4_outbound (struct sk_buff * skb ,
227166 struct net_device * vrf_dev )
228167{
@@ -237,51 +176,9 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
237176 FLOWI_FLAG_SKIP_NH_OIF ,
238177 .daddr = ip4h -> daddr ,
239178 };
240- struct net * net = dev_net (vrf_dev );
241- struct rtable * rt ;
242-
243- rt = ip_route_output_flow (net , & fl4 , NULL );
244- if (IS_ERR (rt ))
245- goto err ;
246179
247- if (rt -> rt_type != RTN_UNICAST && rt -> rt_type != RTN_LOCAL ) {
248- ip_rt_put (rt );
180+ if (vrf_send_v4_prep (skb , & fl4 , vrf_dev ))
249181 goto err ;
250- }
251-
252- skb_dst_drop (skb );
253-
254- /* if dst.dev is loopback or the VRF device again this is locally
255- * originated traffic destined to a local address. Short circuit
256- * to Rx path using our local dst
257- */
258- if (rt -> dst .dev == net -> loopback_dev || rt -> dst .dev == vrf_dev ) {
259- struct net_vrf * vrf = netdev_priv (vrf_dev );
260- struct rtable * rth_local ;
261- struct dst_entry * dst = NULL ;
262-
263- ip_rt_put (rt );
264-
265- rcu_read_lock ();
266-
267- rth_local = rcu_dereference (vrf -> rth_local );
268- if (likely (rth_local )) {
269- dst = & rth_local -> dst ;
270- dst_hold (dst );
271- }
272-
273- rcu_read_unlock ();
274-
275- if (unlikely (!dst ))
276- goto err ;
277-
278- return vrf_local_xmit (skb , vrf_dev , dst );
279- }
280-
281- skb_dst_set (skb , & rt -> dst );
282-
283- /* strip the ethernet header added for pass through VRF device */
284- __skb_pull (skb , skb_network_offset (skb ));
285182
286183 if (!ip4h -> saddr ) {
287184 ip4h -> saddr = inet_select_addr (skb_dst (skb )-> dev , 0 ,
@@ -303,6 +200,9 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
303200
304201static netdev_tx_t is_ip_tx_frame (struct sk_buff * skb , struct net_device * dev )
305202{
203+ /* strip the ethernet header added for pass through VRF device */
204+ __skb_pull (skb , skb_network_offset (skb ));
205+
306206 switch (skb -> protocol ) {
307207 case htons (ETH_P_IP ):
308208 return vrf_process_v4_outbound (skb , dev );
@@ -377,64 +277,35 @@ static int vrf_output6(struct net *net, struct sock *sk, struct sk_buff *skb)
377277static void vrf_rt6_release (struct net_vrf * vrf )
378278{
379279 struct rt6_info * rt6 = rtnl_dereference (vrf -> rt6 );
380- struct rt6_info * rt6_local = rtnl_dereference (vrf -> rt6_local );
381280
382- RCU_INIT_POINTER (vrf -> rt6 , NULL );
383- RCU_INIT_POINTER (vrf -> rt6_local , NULL );
384- synchronize_rcu ();
281+ rcu_assign_pointer (vrf -> rt6 , NULL );
385282
386283 if (rt6 )
387284 dst_release (& rt6 -> dst );
388-
389- if (rt6_local ) {
390- if (rt6_local -> rt6i_idev )
391- in6_dev_put (rt6_local -> rt6i_idev );
392-
393- dst_release (& rt6_local -> dst );
394- }
395285}
396286
397287static int vrf_rt6_create (struct net_device * dev )
398288{
399- int flags = DST_HOST | DST_NOPOLICY | DST_NOXFRM | DST_NOCACHE ;
400289 struct net_vrf * vrf = netdev_priv (dev );
401290 struct net * net = dev_net (dev );
402291 struct fib6_table * rt6i_table ;
403- struct rt6_info * rt6 , * rt6_local ;
292+ struct rt6_info * rt6 ;
404293 int rc = - ENOMEM ;
405294
406295 rt6i_table = fib6_new_table (net , vrf -> tb_id );
407296 if (!rt6i_table )
408297 goto out ;
409298
410- /* create a dst for routing packets out a VRF device */
411- rt6 = ip6_dst_alloc ( net , dev , flags );
299+ rt6 = ip6_dst_alloc ( net , dev ,
300+ DST_HOST | DST_NOPOLICY | DST_NOXFRM | DST_NOCACHE );
412301 if (!rt6 )
413302 goto out ;
414303
415304 dst_hold (& rt6 -> dst );
416305
417306 rt6 -> rt6i_table = rt6i_table ;
418307 rt6 -> dst .output = vrf_output6 ;
419-
420- /* create a dst for local routing - packets sent locally
421- * to local address via the VRF device as a loopback
422- */
423- rt6_local = ip6_dst_alloc (net , dev , flags );
424- if (!rt6_local ) {
425- dst_release (& rt6 -> dst );
426- goto out ;
427- }
428-
429- dst_hold (& rt6_local -> dst );
430-
431- rt6_local -> rt6i_idev = in6_dev_get (dev );
432- rt6_local -> rt6i_flags = RTF_UP | RTF_NONEXTHOP | RTF_LOCAL ;
433- rt6_local -> rt6i_table = rt6i_table ;
434- rt6_local -> dst .input = ip6_input ;
435-
436308 rcu_assign_pointer (vrf -> rt6 , rt6 );
437- rcu_assign_pointer (vrf -> rt6_local , rt6_local );
438309
439310 rc = 0 ;
440311out :
@@ -513,48 +384,29 @@ static int vrf_output(struct net *net, struct sock *sk, struct sk_buff *skb)
513384static void vrf_rtable_release (struct net_vrf * vrf )
514385{
515386 struct rtable * rth = rtnl_dereference (vrf -> rth );
516- struct rtable * rth_local = rtnl_dereference (vrf -> rth_local );
517387
518- RCU_INIT_POINTER (vrf -> rth , NULL );
519- RCU_INIT_POINTER (vrf -> rth_local , NULL );
520- synchronize_rcu ();
388+ rcu_assign_pointer (vrf -> rth , NULL );
521389
522390 if (rth )
523391 dst_release (& rth -> dst );
524-
525- if (rth_local )
526- dst_release (& rth_local -> dst );
527392}
528393
529394static int vrf_rtable_create (struct net_device * dev )
530395{
531396 struct net_vrf * vrf = netdev_priv (dev );
532- struct rtable * rth , * rth_local ;
397+ struct rtable * rth ;
533398
534399 if (!fib_new_table (dev_net (dev ), vrf -> tb_id ))
535400 return - ENOMEM ;
536401
537- /* create a dst for routing packets out through a VRF device */
538402 rth = rt_dst_alloc (dev , 0 , RTN_UNICAST , 1 , 1 , 0 );
539403 if (!rth )
540404 return - ENOMEM ;
541405
542- /* create a dst for local ingress routing - packets sent locally
543- * to local address via the VRF device as a loopback
544- */
545- rth_local = rt_dst_alloc (dev , RTCF_LOCAL , RTN_LOCAL , 1 , 1 , 0 );
546- if (!rth_local ) {
547- dst_release (& rth -> dst );
548- return - ENOMEM ;
549- }
550-
551406 rth -> dst .output = vrf_output ;
552407 rth -> rt_table_id = vrf -> tb_id ;
553408
554- rth_local -> rt_table_id = vrf -> tb_id ;
555-
556409 rcu_assign_pointer (vrf -> rth , rth );
557- rcu_assign_pointer (vrf -> rth_local , rth_local );
558410
559411 return 0 ;
560412}
@@ -780,16 +632,6 @@ static bool ipv6_ndisc_frame(const struct sk_buff *skb)
780632static struct sk_buff * vrf_ip6_rcv (struct net_device * vrf_dev ,
781633 struct sk_buff * skb )
782634{
783- /* loopback traffic; do not push through packet taps again.
784- * Reset pkt_type for upper layers to process skb
785- */
786- if (skb -> pkt_type == PACKET_LOOPBACK ) {
787- skb -> dev = vrf_dev ;
788- skb -> skb_iif = vrf_dev -> ifindex ;
789- skb -> pkt_type = PACKET_HOST ;
790- goto out ;
791- }
792-
793635 /* if packet is NDISC keep the ingress interface */
794636 if (!ipv6_ndisc_frame (skb )) {
795637 skb -> dev = vrf_dev ;
@@ -802,7 +644,6 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
802644 IP6CB (skb )-> flags |= IP6SKB_L3SLAVE ;
803645 }
804646
805- out :
806647 return skb ;
807648}
808649
@@ -820,19 +661,10 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
820661 skb -> dev = vrf_dev ;
821662 skb -> skb_iif = vrf_dev -> ifindex ;
822663
823- /* loopback traffic; do not push through packet taps again.
824- * Reset pkt_type for upper layers to process skb
825- */
826- if (skb -> pkt_type == PACKET_LOOPBACK ) {
827- skb -> pkt_type = PACKET_HOST ;
828- goto out ;
829- }
830-
831664 skb_push (skb , skb -> mac_len );
832665 dev_queue_xmit_nit (skb , vrf_dev );
833666 skb_pull (skb , skb -> mac_len );
834667
835- out :
836668 return skb ;
837669}
838670
0 commit comments