@@ -639,6 +639,58 @@ static void cma_bind_sgid_attr(struct rdma_id_private *id_priv,
639639 id_priv -> id .route .addr .dev_addr .sgid_attr = sgid_attr ;
640640}
641641
642+ /**
643+ * cma_acquire_dev_by_src_ip - Acquire cma device, port, gid attribute
644+ * based on source ip address.
645+ * @id_priv: cm_id which should be bound to cma device
646+ *
647+ * cma_acquire_dev_by_src_ip() binds cm id to cma device, port and GID attribute
648+ * based on source IP address. It returns 0 on success or error code otherwise.
649+ * It is applicable to active and passive side cm_id.
650+ */
651+ static int cma_acquire_dev_by_src_ip (struct rdma_id_private * id_priv )
652+ {
653+ struct rdma_dev_addr * dev_addr = & id_priv -> id .route .addr .dev_addr ;
654+ const struct ib_gid_attr * sgid_attr ;
655+ union ib_gid gid , iboe_gid , * gidp ;
656+ struct cma_device * cma_dev ;
657+ enum ib_gid_type gid_type ;
658+ int ret = - ENODEV ;
659+ u8 port ;
660+
661+ if (dev_addr -> dev_type != ARPHRD_INFINIBAND &&
662+ id_priv -> id .ps == RDMA_PS_IPOIB )
663+ return - EINVAL ;
664+
665+ rdma_ip2gid ((struct sockaddr * )& id_priv -> id .route .addr .src_addr ,
666+ & iboe_gid );
667+
668+ memcpy (& gid , dev_addr -> src_dev_addr +
669+ rdma_addr_gid_offset (dev_addr ), sizeof (gid ));
670+
671+ mutex_lock (& lock );
672+ list_for_each_entry (cma_dev , & dev_list , list ) {
673+ for (port = rdma_start_port (cma_dev -> device );
674+ port <= rdma_end_port (cma_dev -> device ); port ++ ) {
675+ gidp = rdma_protocol_roce (cma_dev -> device , port ) ?
676+ & iboe_gid : & gid ;
677+ gid_type = cma_dev -> default_gid_type [port - 1 ];
678+ sgid_attr = cma_validate_port (cma_dev -> device , port ,
679+ gid_type , gidp , id_priv );
680+ if (!IS_ERR (sgid_attr )) {
681+ id_priv -> id .port_num = port ;
682+ cma_bind_sgid_attr (id_priv , sgid_attr );
683+ cma_attach_to_dev (id_priv , cma_dev );
684+ ret = 0 ;
685+ goto out ;
686+ }
687+ }
688+ }
689+ out :
690+ mutex_unlock (& lock );
691+ return ret ;
692+ }
693+
642694static int cma_acquire_dev (struct rdma_id_private * id_priv ,
643695 const struct rdma_id_private * listen_id_priv )
644696{
@@ -661,26 +713,22 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv,
661713 memcpy (& gid , dev_addr -> src_dev_addr +
662714 rdma_addr_gid_offset (dev_addr ), sizeof gid );
663715
664- if (listen_id_priv ) {
665- cma_dev = listen_id_priv -> cma_dev ;
666- port = listen_id_priv -> id .port_num ;
667- gidp = rdma_protocol_roce (cma_dev -> device , port ) ?
668- & iboe_gid : & gid ;
669- gid_type = listen_id_priv -> gid_type ;
670- sgid_attr = cma_validate_port (cma_dev -> device , port ,
671- gid_type , gidp , id_priv );
672- if (!IS_ERR (sgid_attr )) {
673- id_priv -> id .port_num = port ;
674- cma_bind_sgid_attr (id_priv , sgid_attr );
675- ret = 0 ;
676- goto out ;
677- }
716+ cma_dev = listen_id_priv -> cma_dev ;
717+ port = listen_id_priv -> id .port_num ;
718+ gidp = rdma_protocol_roce (cma_dev -> device , port ) ? & iboe_gid : & gid ;
719+ gid_type = listen_id_priv -> gid_type ;
720+ sgid_attr = cma_validate_port (cma_dev -> device , port ,
721+ gid_type , gidp , id_priv );
722+ if (!IS_ERR (sgid_attr )) {
723+ id_priv -> id .port_num = port ;
724+ cma_bind_sgid_attr (id_priv , sgid_attr );
725+ ret = 0 ;
726+ goto out ;
678727 }
679728
680729 list_for_each_entry (cma_dev , & dev_list , list ) {
681730 for (port = 1 ; port <= cma_dev -> device -> phys_port_cnt ; ++ port ) {
682- if (listen_id_priv &&
683- listen_id_priv -> cma_dev == cma_dev &&
731+ if (listen_id_priv -> cma_dev == cma_dev &&
684732 listen_id_priv -> id .port_num == port )
685733 continue ;
686734
@@ -2878,7 +2926,7 @@ static void addr_handler(int status, struct sockaddr *src_addr,
28782926
28792927 memcpy (cma_src_addr (id_priv ), src_addr , rdma_addr_size (src_addr ));
28802928 if (!status && !id_priv -> cma_dev ) {
2881- status = cma_acquire_dev (id_priv , NULL );
2929+ status = cma_acquire_dev_by_src_ip (id_priv );
28822930 if (status )
28832931 pr_debug_ratelimited ("RDMA CM: ADDR_ERROR: failed to acquire device. status %d\n" ,
28842932 status );
@@ -3427,7 +3475,7 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
34273475 if (ret )
34283476 goto err1 ;
34293477
3430- ret = cma_acquire_dev (id_priv , NULL );
3478+ ret = cma_acquire_dev_by_src_ip (id_priv );
34313479 if (ret )
34323480 goto err1 ;
34333481 }
0 commit comments