1111#include <linux/in6.h>
1212#include <linux/mutex.h>
1313#include <linux/random.h>
14+ #include <linux/rbtree.h>
1415#include <linux/igmp.h>
1516#include <linux/xarray.h>
1617#include <linux/inetdevice.h>
2021
2122#include <net/net_namespace.h>
2223#include <net/netns/generic.h>
24+ #include <net/netevent.h>
2325#include <net/tcp.h>
2426#include <net/ipv6.h>
2527#include <net/ip_fib.h>
@@ -168,6 +170,9 @@ static struct ib_sa_client sa_client;
168170static LIST_HEAD (dev_list );
169171static LIST_HEAD (listen_any_list );
170172static DEFINE_MUTEX (lock );
173+ static struct rb_root id_table = RB_ROOT ;
174+ /* Serialize operations of id_table tree */
175+ static DEFINE_SPINLOCK (id_table_lock );
171176static struct workqueue_struct * cma_wq ;
172177static unsigned int cma_pernet_id ;
173178
@@ -202,6 +207,11 @@ struct xarray *cma_pernet_xa(struct net *net, enum rdma_ucm_port_space ps)
202207 }
203208}
204209
210+ struct id_table_entry {
211+ struct list_head id_list ;
212+ struct rb_node rb_node ;
213+ };
214+
205215struct cma_device {
206216 struct list_head list ;
207217 struct ib_device * device ;
@@ -420,11 +430,21 @@ static inline u8 cma_get_ip_ver(const struct cma_hdr *hdr)
420430 return hdr -> ip_version >> 4 ;
421431}
422432
423- static inline void cma_set_ip_ver (struct cma_hdr * hdr , u8 ip_ver )
433+ static void cma_set_ip_ver (struct cma_hdr * hdr , u8 ip_ver )
424434{
425435 hdr -> ip_version = (ip_ver << 4 ) | (hdr -> ip_version & 0xF );
426436}
427437
438+ static struct sockaddr * cma_src_addr (struct rdma_id_private * id_priv )
439+ {
440+ return (struct sockaddr * )& id_priv -> id .route .addr .src_addr ;
441+ }
442+
443+ static inline struct sockaddr * cma_dst_addr (struct rdma_id_private * id_priv )
444+ {
445+ return (struct sockaddr * )& id_priv -> id .route .addr .dst_addr ;
446+ }
447+
428448static int cma_igmp_send (struct net_device * ndev , union ib_gid * mgid , bool join )
429449{
430450 struct in_device * in_dev = NULL ;
@@ -445,6 +465,117 @@ static int cma_igmp_send(struct net_device *ndev, union ib_gid *mgid, bool join)
445465 return (in_dev ) ? 0 : - ENODEV ;
446466}
447467
468+ static int compare_netdev_and_ip (int ifindex_a , struct sockaddr * sa ,
469+ struct id_table_entry * entry_b )
470+ {
471+ struct rdma_id_private * id_priv = list_first_entry (
472+ & entry_b -> id_list , struct rdma_id_private , id_list_entry );
473+ int ifindex_b = id_priv -> id .route .addr .dev_addr .bound_dev_if ;
474+ struct sockaddr * sb = cma_dst_addr (id_priv );
475+
476+ if (ifindex_a != ifindex_b )
477+ return (ifindex_a > ifindex_b ) ? 1 : -1 ;
478+
479+ if (sa -> sa_family != sb -> sa_family )
480+ return sa -> sa_family - sb -> sa_family ;
481+
482+ if (sa -> sa_family == AF_INET )
483+ return memcmp ((char * )& ((struct sockaddr_in * )sa )-> sin_addr ,
484+ (char * )& ((struct sockaddr_in * )sb )-> sin_addr ,
485+ sizeof (((struct sockaddr_in * )sa )-> sin_addr ));
486+
487+ return ipv6_addr_cmp (& ((struct sockaddr_in6 * )sa )-> sin6_addr ,
488+ & ((struct sockaddr_in6 * )sb )-> sin6_addr );
489+ }
490+
491+ static int cma_add_id_to_tree (struct rdma_id_private * node_id_priv )
492+ {
493+ struct rb_node * * new , * parent = NULL ;
494+ struct id_table_entry * this , * node ;
495+ unsigned long flags ;
496+ int result ;
497+
498+ node = kzalloc (sizeof (* node ), GFP_KERNEL );
499+ if (!node )
500+ return - ENOMEM ;
501+
502+ spin_lock_irqsave (& id_table_lock , flags );
503+ new = & id_table .rb_node ;
504+ while (* new ) {
505+ this = container_of (* new , struct id_table_entry , rb_node );
506+ result = compare_netdev_and_ip (
507+ node_id_priv -> id .route .addr .dev_addr .bound_dev_if ,
508+ cma_dst_addr (node_id_priv ), this );
509+
510+ parent = * new ;
511+ if (result < 0 )
512+ new = & ((* new )-> rb_left );
513+ else if (result > 0 )
514+ new = & ((* new )-> rb_right );
515+ else {
516+ list_add_tail (& node_id_priv -> id_list_entry ,
517+ & this -> id_list );
518+ kfree (node );
519+ goto unlock ;
520+ }
521+ }
522+
523+ INIT_LIST_HEAD (& node -> id_list );
524+ list_add_tail (& node_id_priv -> id_list_entry , & node -> id_list );
525+
526+ rb_link_node (& node -> rb_node , parent , new );
527+ rb_insert_color (& node -> rb_node , & id_table );
528+
529+ unlock :
530+ spin_unlock_irqrestore (& id_table_lock , flags );
531+ return 0 ;
532+ }
533+
534+ static struct id_table_entry *
535+ node_from_ndev_ip (struct rb_root * root , int ifindex , struct sockaddr * sa )
536+ {
537+ struct rb_node * node = root -> rb_node ;
538+ struct id_table_entry * data ;
539+ int result ;
540+
541+ while (node ) {
542+ data = container_of (node , struct id_table_entry , rb_node );
543+ result = compare_netdev_and_ip (ifindex , sa , data );
544+ if (result < 0 )
545+ node = node -> rb_left ;
546+ else if (result > 0 )
547+ node = node -> rb_right ;
548+ else
549+ return data ;
550+ }
551+
552+ return NULL ;
553+ }
554+
555+ static void cma_remove_id_from_tree (struct rdma_id_private * id_priv )
556+ {
557+ struct id_table_entry * data ;
558+ unsigned long flags ;
559+
560+ spin_lock_irqsave (& id_table_lock , flags );
561+ if (list_empty (& id_priv -> id_list_entry ))
562+ goto out ;
563+
564+ data = node_from_ndev_ip (& id_table ,
565+ id_priv -> id .route .addr .dev_addr .bound_dev_if ,
566+ cma_dst_addr (id_priv ));
567+ if (!data )
568+ goto out ;
569+
570+ list_del_init (& id_priv -> id_list_entry );
571+ if (list_empty (& data -> id_list )) {
572+ rb_erase (& data -> rb_node , & id_table );
573+ kfree (data );
574+ }
575+ out :
576+ spin_unlock_irqrestore (& id_table_lock , flags );
577+ }
578+
448579static void _cma_attach_to_dev (struct rdma_id_private * id_priv ,
449580 struct cma_device * cma_dev )
450581{
@@ -481,16 +612,6 @@ static void cma_release_dev(struct rdma_id_private *id_priv)
481612 mutex_unlock (& lock );
482613}
483614
484- static inline struct sockaddr * cma_src_addr (struct rdma_id_private * id_priv )
485- {
486- return (struct sockaddr * ) & id_priv -> id .route .addr .src_addr ;
487- }
488-
489- static inline struct sockaddr * cma_dst_addr (struct rdma_id_private * id_priv )
490- {
491- return (struct sockaddr * ) & id_priv -> id .route .addr .dst_addr ;
492- }
493-
494615static inline unsigned short cma_family (struct rdma_id_private * id_priv )
495616{
496617 return id_priv -> id .route .addr .src_addr .ss_family ;
@@ -861,6 +982,7 @@ __rdma_create_id(struct net *net, rdma_cm_event_handler event_handler,
861982 refcount_set (& id_priv -> refcount , 1 );
862983 mutex_init (& id_priv -> handler_mutex );
863984 INIT_LIST_HEAD (& id_priv -> device_item );
985+ INIT_LIST_HEAD (& id_priv -> id_list_entry );
864986 INIT_LIST_HEAD (& id_priv -> listen_list );
865987 INIT_LIST_HEAD (& id_priv -> mc_list );
866988 get_random_bytes (& id_priv -> seq_num , sizeof id_priv -> seq_num );
@@ -1883,6 +2005,7 @@ static void _destroy_id(struct rdma_id_private *id_priv,
18832005 cma_cancel_operation (id_priv , state );
18842006
18852007 rdma_restrack_del (& id_priv -> res );
2008+ cma_remove_id_from_tree (id_priv );
18862009 if (id_priv -> cma_dev ) {
18872010 if (rdma_cap_ib_cm (id_priv -> id .device , 1 )) {
18882011 if (id_priv -> cm_id .ib )
@@ -3172,8 +3295,11 @@ int rdma_resolve_route(struct rdma_cm_id *id, unsigned long timeout_ms)
31723295 cma_id_get (id_priv );
31733296 if (rdma_cap_ib_sa (id -> device , id -> port_num ))
31743297 ret = cma_resolve_ib_route (id_priv , timeout_ms );
3175- else if (rdma_protocol_roce (id -> device , id -> port_num ))
3298+ else if (rdma_protocol_roce (id -> device , id -> port_num )) {
31763299 ret = cma_resolve_iboe_route (id_priv );
3300+ if (!ret )
3301+ cma_add_id_to_tree (id_priv );
3302+ }
31773303 else if (rdma_protocol_iwarp (id -> device , id -> port_num ))
31783304 ret = cma_resolve_iw_route (id_priv );
31793305 else
@@ -4922,10 +5048,87 @@ static int cma_netdev_callback(struct notifier_block *self, unsigned long event,
49225048 return ret ;
49235049}
49245050
5051+ static void cma_netevent_work_handler (struct work_struct * _work )
5052+ {
5053+ struct rdma_id_private * id_priv =
5054+ container_of (_work , struct rdma_id_private , id .net_work );
5055+ struct rdma_cm_event event = {};
5056+
5057+ mutex_lock (& id_priv -> handler_mutex );
5058+
5059+ if (READ_ONCE (id_priv -> state ) == RDMA_CM_DESTROYING ||
5060+ READ_ONCE (id_priv -> state ) == RDMA_CM_DEVICE_REMOVAL )
5061+ goto out_unlock ;
5062+
5063+ event .event = RDMA_CM_EVENT_UNREACHABLE ;
5064+ event .status = - ETIMEDOUT ;
5065+
5066+ if (cma_cm_event_handler (id_priv , & event )) {
5067+ __acquire (& id_priv -> handler_mutex );
5068+ id_priv -> cm_id .ib = NULL ;
5069+ cma_id_put (id_priv );
5070+ destroy_id_handler_unlock (id_priv );
5071+ return ;
5072+ }
5073+
5074+ out_unlock :
5075+ mutex_unlock (& id_priv -> handler_mutex );
5076+ cma_id_put (id_priv );
5077+ }
5078+
5079+ static int cma_netevent_callback (struct notifier_block * self ,
5080+ unsigned long event , void * ctx )
5081+ {
5082+ struct id_table_entry * ips_node = NULL ;
5083+ struct rdma_id_private * current_id ;
5084+ struct neighbour * neigh = ctx ;
5085+ unsigned long flags ;
5086+
5087+ if (event != NETEVENT_NEIGH_UPDATE )
5088+ return NOTIFY_DONE ;
5089+
5090+ spin_lock_irqsave (& id_table_lock , flags );
5091+ if (neigh -> tbl -> family == AF_INET6 ) {
5092+ struct sockaddr_in6 neigh_sock_6 ;
5093+
5094+ neigh_sock_6 .sin6_family = AF_INET6 ;
5095+ neigh_sock_6 .sin6_addr = * (struct in6_addr * )neigh -> primary_key ;
5096+ ips_node = node_from_ndev_ip (& id_table , neigh -> dev -> ifindex ,
5097+ (struct sockaddr * )& neigh_sock_6 );
5098+ } else if (neigh -> tbl -> family == AF_INET ) {
5099+ struct sockaddr_in neigh_sock_4 ;
5100+
5101+ neigh_sock_4 .sin_family = AF_INET ;
5102+ neigh_sock_4 .sin_addr .s_addr = * (__be32 * )(neigh -> primary_key );
5103+ ips_node = node_from_ndev_ip (& id_table , neigh -> dev -> ifindex ,
5104+ (struct sockaddr * )& neigh_sock_4 );
5105+ } else
5106+ goto out ;
5107+
5108+ if (!ips_node )
5109+ goto out ;
5110+
5111+ list_for_each_entry (current_id , & ips_node -> id_list , id_list_entry ) {
5112+ if (!memcmp (current_id -> id .route .addr .dev_addr .dst_dev_addr ,
5113+ neigh -> ha , ETH_ALEN ))
5114+ continue ;
5115+ INIT_WORK (& current_id -> id .net_work , cma_netevent_work_handler );
5116+ cma_id_get (current_id );
5117+ queue_work (cma_wq , & current_id -> id .net_work );
5118+ }
5119+ out :
5120+ spin_unlock_irqrestore (& id_table_lock , flags );
5121+ return NOTIFY_DONE ;
5122+ }
5123+
49255124static struct notifier_block cma_nb = {
49265125 .notifier_call = cma_netdev_callback
49275126};
49285127
5128+ static struct notifier_block cma_netevent_cb = {
5129+ .notifier_call = cma_netevent_callback
5130+ };
5131+
49295132static void cma_send_device_removal_put (struct rdma_id_private * id_priv )
49305133{
49315134 struct rdma_cm_event event = { .event = RDMA_CM_EVENT_DEVICE_REMOVAL };
@@ -5148,6 +5351,7 @@ static int __init cma_init(void)
51485351
51495352 ib_sa_register_client (& sa_client );
51505353 register_netdevice_notifier (& cma_nb );
5354+ register_netevent_notifier (& cma_netevent_cb );
51515355
51525356 ret = ib_register_client (& cma_client );
51535357 if (ret )
@@ -5162,6 +5366,7 @@ static int __init cma_init(void)
51625366err_ib :
51635367 ib_unregister_client (& cma_client );
51645368err :
5369+ unregister_netevent_notifier (& cma_netevent_cb );
51655370 unregister_netdevice_notifier (& cma_nb );
51665371 ib_sa_unregister_client (& sa_client );
51675372 unregister_pernet_subsys (& cma_pernet_operations );
@@ -5174,6 +5379,7 @@ static void __exit cma_cleanup(void)
51745379{
51755380 cma_configfs_exit ();
51765381 ib_unregister_client (& cma_client );
5382+ unregister_netevent_notifier (& cma_netevent_cb );
51775383 unregister_netdevice_notifier (& cma_nb );
51785384 ib_sa_unregister_client (& sa_client );
51795385 unregister_pernet_subsys (& cma_pernet_operations );
0 commit comments