@@ -160,6 +160,18 @@ struct nfp_tun_mac_addr_offload {
160
160
u8 addr [ETH_ALEN ];
161
161
};
162
162
163
+ /**
164
+ * struct nfp_neigh_update_work - update neighbour information to nfp
165
+ * @work: Work queue for writing neigh to the nfp
166
+ * @n: neighbour entry
167
+ * @app: Back pointer to app
168
+ */
169
+ struct nfp_neigh_update_work {
170
+ struct work_struct work ;
171
+ struct neighbour * n ;
172
+ struct nfp_app * app ;
173
+ };
174
+
163
175
enum nfp_flower_mac_offload_cmd {
164
176
NFP_TUNNEL_MAC_OFFLOAD_ADD = 0 ,
165
177
NFP_TUNNEL_MAC_OFFLOAD_DEL = 1 ,
@@ -607,38 +619,30 @@ nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,
607
619
nfp_flower_cmsg_warn (app , "Neighbour configuration failed.\n" );
608
620
}
609
621
610
- static int
611
- nfp_tun_neigh_event_handler (struct notifier_block * nb , unsigned long event ,
612
- void * ptr )
622
+ static void
623
+ nfp_tun_release_neigh_update_work (struct nfp_neigh_update_work * update_work )
613
624
{
614
- struct nfp_flower_priv * app_priv ;
615
- struct netevent_redirect * redir ;
616
- struct neighbour * n ;
625
+ neigh_release (update_work -> n );
626
+ kfree (update_work );
627
+ }
628
+
629
+ static void nfp_tun_neigh_update (struct work_struct * work )
630
+ {
631
+ struct nfp_neigh_update_work * update_work ;
617
632
struct nfp_app * app ;
633
+ struct neighbour * n ;
618
634
bool neigh_invalid ;
619
635
int err ;
620
636
621
- switch (event ) {
622
- case NETEVENT_REDIRECT :
623
- redir = (struct netevent_redirect * )ptr ;
624
- n = redir -> neigh ;
625
- break ;
626
- case NETEVENT_NEIGH_UPDATE :
627
- n = (struct neighbour * )ptr ;
628
- break ;
629
- default :
630
- return NOTIFY_DONE ;
631
- }
632
-
633
- neigh_invalid = !(n -> nud_state & NUD_VALID ) || n -> dead ;
634
-
635
- app_priv = container_of (nb , struct nfp_flower_priv , tun .neigh_nb );
636
- app = app_priv -> app ;
637
+ update_work = container_of (work , struct nfp_neigh_update_work , work );
638
+ app = update_work -> app ;
639
+ n = update_work -> n ;
637
640
638
641
if (!nfp_flower_get_port_id_from_netdev (app , n -> dev ))
639
- return NOTIFY_DONE ;
642
+ goto out ;
640
643
641
644
#if IS_ENABLED (CONFIG_INET )
645
+ neigh_invalid = !(n -> nud_state & NUD_VALID ) || n -> dead ;
642
646
if (n -> tbl -> family == AF_INET6 ) {
643
647
#if IS_ENABLED (CONFIG_IPV6 )
644
648
struct flowi6 flow6 = {};
@@ -655,13 +659,11 @@ nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,
655
659
dst = ip6_dst_lookup_flow (dev_net (n -> dev ), NULL ,
656
660
& flow6 , NULL );
657
661
if (IS_ERR (dst ))
658
- return NOTIFY_DONE ;
662
+ goto out ;
659
663
660
664
dst_release (dst );
661
665
}
662
666
nfp_tun_write_neigh (n -> dev , app , & flow6 , n , true, false);
663
- #else
664
- return NOTIFY_DONE ;
665
667
#endif /* CONFIG_IPV6 */
666
668
} else {
667
669
struct flowi4 flow4 = {};
@@ -678,17 +680,71 @@ nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,
678
680
rt = ip_route_output_key (dev_net (n -> dev ), & flow4 );
679
681
err = PTR_ERR_OR_ZERO (rt );
680
682
if (err )
681
- return NOTIFY_DONE ;
683
+ goto out ;
682
684
683
685
ip_rt_put (rt );
684
686
}
685
687
nfp_tun_write_neigh (n -> dev , app , & flow4 , n , false, false);
686
688
}
687
- #else
688
- return NOTIFY_DONE ;
689
689
#endif /* CONFIG_INET */
690
+ out :
691
+ nfp_tun_release_neigh_update_work (update_work );
692
+ }
690
693
691
- return NOTIFY_OK ;
694
+ static struct nfp_neigh_update_work *
695
+ nfp_tun_alloc_neigh_update_work (struct nfp_app * app , struct neighbour * n )
696
+ {
697
+ struct nfp_neigh_update_work * update_work ;
698
+
699
+ update_work = kzalloc (sizeof (* update_work ), GFP_ATOMIC );
700
+ if (!update_work )
701
+ return NULL ;
702
+
703
+ INIT_WORK (& update_work -> work , nfp_tun_neigh_update );
704
+ neigh_hold (n );
705
+ update_work -> n = n ;
706
+ update_work -> app = app ;
707
+
708
+ return update_work ;
709
+ }
710
+
711
+ static int
712
+ nfp_tun_neigh_event_handler (struct notifier_block * nb , unsigned long event ,
713
+ void * ptr )
714
+ {
715
+ struct nfp_neigh_update_work * update_work ;
716
+ struct nfp_flower_priv * app_priv ;
717
+ struct netevent_redirect * redir ;
718
+ struct neighbour * n ;
719
+ struct nfp_app * app ;
720
+
721
+ switch (event ) {
722
+ case NETEVENT_REDIRECT :
723
+ redir = (struct netevent_redirect * )ptr ;
724
+ n = redir -> neigh ;
725
+ break ;
726
+ case NETEVENT_NEIGH_UPDATE :
727
+ n = (struct neighbour * )ptr ;
728
+ break ;
729
+ default :
730
+ return NOTIFY_DONE ;
731
+ }
732
+ #if IS_ENABLED (CONFIG_IPV6 )
733
+ if (n -> tbl != ipv6_stub -> nd_tbl && n -> tbl != & arp_tbl )
734
+ #else
735
+ if (n -> tbl != & arp_tbl )
736
+ #endif
737
+ return NOTIFY_DONE ;
738
+
739
+ app_priv = container_of (nb , struct nfp_flower_priv , tun .neigh_nb );
740
+ app = app_priv -> app ;
741
+ update_work = nfp_tun_alloc_neigh_update_work (app , n );
742
+ if (!update_work )
743
+ return NOTIFY_DONE ;
744
+
745
+ queue_work (system_highpri_wq , & update_work -> work );
746
+
747
+ return NOTIFY_DONE ;
692
748
}
693
749
694
750
void nfp_tunnel_request_route_v4 (struct nfp_app * app , struct sk_buff * skb )
@@ -706,6 +762,7 @@ void nfp_tunnel_request_route_v4(struct nfp_app *app, struct sk_buff *skb)
706
762
netdev = nfp_app_dev_get (app , be32_to_cpu (payload -> ingress_port ), NULL );
707
763
if (!netdev )
708
764
goto fail_rcu_unlock ;
765
+ dev_hold (netdev );
709
766
710
767
flow .daddr = payload -> ipv4_addr ;
711
768
flow .flowi4_proto = IPPROTO_UDP ;
@@ -725,13 +782,16 @@ void nfp_tunnel_request_route_v4(struct nfp_app *app, struct sk_buff *skb)
725
782
ip_rt_put (rt );
726
783
if (!n )
727
784
goto fail_rcu_unlock ;
785
+ rcu_read_unlock ();
786
+
728
787
nfp_tun_write_neigh (n -> dev , app , & flow , n , false, true);
729
788
neigh_release (n );
730
- rcu_read_unlock ( );
789
+ dev_put ( netdev );
731
790
return ;
732
791
733
792
fail_rcu_unlock :
734
793
rcu_read_unlock ();
794
+ dev_put (netdev );
735
795
nfp_flower_cmsg_warn (app , "Requested route not found.\n" );
736
796
}
737
797
@@ -749,6 +809,7 @@ void nfp_tunnel_request_route_v6(struct nfp_app *app, struct sk_buff *skb)
749
809
netdev = nfp_app_dev_get (app , be32_to_cpu (payload -> ingress_port ), NULL );
750
810
if (!netdev )
751
811
goto fail_rcu_unlock ;
812
+ dev_hold (netdev );
752
813
753
814
flow .daddr = payload -> ipv6_addr ;
754
815
flow .flowi6_proto = IPPROTO_UDP ;
@@ -766,14 +827,16 @@ void nfp_tunnel_request_route_v6(struct nfp_app *app, struct sk_buff *skb)
766
827
dst_release (dst );
767
828
if (!n )
768
829
goto fail_rcu_unlock ;
830
+ rcu_read_unlock ();
769
831
770
832
nfp_tun_write_neigh (n -> dev , app , & flow , n , true, true);
771
833
neigh_release (n );
772
- rcu_read_unlock ( );
834
+ dev_put ( netdev );
773
835
return ;
774
836
775
837
fail_rcu_unlock :
776
838
rcu_read_unlock ();
839
+ dev_put (netdev );
777
840
nfp_flower_cmsg_warn (app , "Requested IPv6 route not found.\n" );
778
841
}
779
842
0 commit comments