50
50
51
51
#include <rdma/iw_cm.h>
52
52
#include <rdma/ib_addr.h>
53
+ #include <rdma/iw_portmap.h>
54
+ #include <rdma/rdma_netlink.h>
53
55
54
56
#include "iwcm.h"
55
57
56
58
MODULE_AUTHOR ("Tom Tucker" );
57
59
MODULE_DESCRIPTION ("iWARP CM" );
58
60
MODULE_LICENSE ("Dual BSD/GPL" );
59
61
62
+ static struct ibnl_client_cbs iwcm_nl_cb_table [] = {
63
+ [RDMA_NL_IWPM_REG_PID ] = {.dump = iwpm_register_pid_cb },
64
+ [RDMA_NL_IWPM_ADD_MAPPING ] = {.dump = iwpm_add_mapping_cb },
65
+ [RDMA_NL_IWPM_QUERY_MAPPING ] = {.dump = iwpm_add_and_query_mapping_cb },
66
+ [RDMA_NL_IWPM_REMOTE_INFO ] = {.dump = iwpm_remote_info_cb },
67
+ [RDMA_NL_IWPM_HANDLE_ERR ] = {.dump = iwpm_mapping_error_cb },
68
+ [RDMA_NL_IWPM_MAPINFO ] = {.dump = iwpm_mapping_info_cb },
69
+ [RDMA_NL_IWPM_MAPINFO_NUM ] = {.dump = iwpm_ack_mapping_info_cb }
70
+ };
71
+
60
72
static struct workqueue_struct * iwcm_wq ;
61
73
struct iwcm_work {
62
74
struct work_struct work ;
@@ -402,6 +414,11 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
402
414
}
403
415
spin_unlock_irqrestore (& cm_id_priv -> lock , flags );
404
416
417
+ if (cm_id -> mapped ) {
418
+ iwpm_remove_mapinfo (& cm_id -> local_addr , & cm_id -> m_local_addr );
419
+ iwpm_remove_mapping (& cm_id -> local_addr , RDMA_NL_IWCM );
420
+ }
421
+
405
422
(void )iwcm_deref_id (cm_id_priv );
406
423
}
407
424
@@ -426,6 +443,97 @@ void iw_destroy_cm_id(struct iw_cm_id *cm_id)
426
443
}
427
444
EXPORT_SYMBOL (iw_destroy_cm_id );
428
445
446
+ /**
447
+ * iw_cm_check_wildcard - If IP address is 0 then use original
448
+ * @pm_addr: sockaddr containing the ip to check for wildcard
449
+ * @cm_addr: sockaddr containing the actual IP address
450
+ * @cm_outaddr: sockaddr to set IP addr which leaving port
451
+ *
452
+ * Checks the pm_addr for wildcard and then sets cm_outaddr's
453
+ * IP to the actual (cm_addr).
454
+ */
455
+ static void iw_cm_check_wildcard (struct sockaddr_storage * pm_addr ,
456
+ struct sockaddr_storage * cm_addr ,
457
+ struct sockaddr_storage * cm_outaddr )
458
+ {
459
+ if (pm_addr -> ss_family == AF_INET ) {
460
+ struct sockaddr_in * pm4_addr = (struct sockaddr_in * )pm_addr ;
461
+
462
+ if (pm4_addr -> sin_addr .s_addr == INADDR_ANY ) {
463
+ struct sockaddr_in * cm4_addr =
464
+ (struct sockaddr_in * )cm_addr ;
465
+ struct sockaddr_in * cm4_outaddr =
466
+ (struct sockaddr_in * )cm_outaddr ;
467
+
468
+ cm4_outaddr -> sin_addr = cm4_addr -> sin_addr ;
469
+ }
470
+ } else {
471
+ struct sockaddr_in6 * pm6_addr = (struct sockaddr_in6 * )pm_addr ;
472
+
473
+ if (ipv6_addr_type (& pm6_addr -> sin6_addr ) == IPV6_ADDR_ANY ) {
474
+ struct sockaddr_in6 * cm6_addr =
475
+ (struct sockaddr_in6 * )cm_addr ;
476
+ struct sockaddr_in6 * cm6_outaddr =
477
+ (struct sockaddr_in6 * )cm_outaddr ;
478
+
479
+ cm6_outaddr -> sin6_addr = cm6_addr -> sin6_addr ;
480
+ }
481
+ }
482
+ }
483
+
484
+ /**
485
+ * iw_cm_map - Use portmapper to map the ports
486
+ * @cm_id: connection manager pointer
487
+ * @active: Indicates the active side when true
488
+ * returns nonzero for error only if iwpm_create_mapinfo() fails
489
+ *
490
+ * Tries to add a mapping for a port using the Portmapper. If
491
+ * successful in mapping the IP/Port it will check the remote
492
+ * mapped IP address for a wildcard IP address and replace the
493
+ * zero IP address with the remote_addr.
494
+ */
495
+ static int iw_cm_map (struct iw_cm_id * cm_id , bool active )
496
+ {
497
+ struct iwpm_dev_data pm_reg_msg ;
498
+ struct iwpm_sa_data pm_msg ;
499
+ int status ;
500
+
501
+ cm_id -> m_local_addr = cm_id -> local_addr ;
502
+ cm_id -> m_remote_addr = cm_id -> remote_addr ;
503
+
504
+ memcpy (pm_reg_msg .dev_name , cm_id -> device -> name ,
505
+ sizeof (pm_reg_msg .dev_name ));
506
+ memcpy (pm_reg_msg .if_name , cm_id -> device -> iwcm -> ifname ,
507
+ sizeof (pm_reg_msg .if_name ));
508
+
509
+ if (iwpm_register_pid (& pm_reg_msg , RDMA_NL_IWCM ) ||
510
+ !iwpm_valid_pid ())
511
+ return 0 ;
512
+
513
+ cm_id -> mapped = true;
514
+ pm_msg .loc_addr = cm_id -> local_addr ;
515
+ pm_msg .rem_addr = cm_id -> remote_addr ;
516
+ if (active )
517
+ status = iwpm_add_and_query_mapping (& pm_msg ,
518
+ RDMA_NL_IWCM );
519
+ else
520
+ status = iwpm_add_mapping (& pm_msg , RDMA_NL_IWCM );
521
+
522
+ if (!status ) {
523
+ cm_id -> m_local_addr = pm_msg .mapped_loc_addr ;
524
+ if (active ) {
525
+ cm_id -> m_remote_addr = pm_msg .mapped_rem_addr ;
526
+ iw_cm_check_wildcard (& pm_msg .mapped_rem_addr ,
527
+ & cm_id -> remote_addr ,
528
+ & cm_id -> m_remote_addr );
529
+ }
530
+ }
531
+
532
+ return iwpm_create_mapinfo (& cm_id -> local_addr ,
533
+ & cm_id -> m_local_addr ,
534
+ RDMA_NL_IWCM );
535
+ }
536
+
429
537
/*
430
538
* CM_ID <-- LISTEN
431
539
*
@@ -452,7 +560,9 @@ int iw_cm_listen(struct iw_cm_id *cm_id, int backlog)
452
560
case IW_CM_STATE_IDLE :
453
561
cm_id_priv -> state = IW_CM_STATE_LISTEN ;
454
562
spin_unlock_irqrestore (& cm_id_priv -> lock , flags );
455
- ret = cm_id -> device -> iwcm -> create_listen (cm_id , backlog );
563
+ ret = iw_cm_map (cm_id , false);
564
+ if (!ret )
565
+ ret = cm_id -> device -> iwcm -> create_listen (cm_id , backlog );
456
566
if (ret )
457
567
cm_id_priv -> state = IW_CM_STATE_IDLE ;
458
568
spin_lock_irqsave (& cm_id_priv -> lock , flags );
@@ -582,39 +692,37 @@ int iw_cm_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
582
692
spin_lock_irqsave (& cm_id_priv -> lock , flags );
583
693
584
694
if (cm_id_priv -> state != IW_CM_STATE_IDLE ) {
585
- spin_unlock_irqrestore (& cm_id_priv -> lock , flags );
586
- clear_bit (IWCM_F_CONNECT_WAIT , & cm_id_priv -> flags );
587
- wake_up_all (& cm_id_priv -> connect_wait );
588
- return - EINVAL ;
695
+ ret = - EINVAL ;
696
+ goto err ;
589
697
}
590
698
591
699
/* Get the ib_qp given the QPN */
592
700
qp = cm_id -> device -> iwcm -> get_qp (cm_id -> device , iw_param -> qpn );
593
701
if (!qp ) {
594
- spin_unlock_irqrestore (& cm_id_priv -> lock , flags );
595
- clear_bit (IWCM_F_CONNECT_WAIT , & cm_id_priv -> flags );
596
- wake_up_all (& cm_id_priv -> connect_wait );
597
- return - EINVAL ;
702
+ ret = - EINVAL ;
703
+ goto err ;
598
704
}
599
705
cm_id -> device -> iwcm -> add_ref (qp );
600
706
cm_id_priv -> qp = qp ;
601
707
cm_id_priv -> state = IW_CM_STATE_CONN_SENT ;
602
708
spin_unlock_irqrestore (& cm_id_priv -> lock , flags );
603
709
604
- ret = cm_id -> device -> iwcm -> connect (cm_id , iw_param );
605
- if (ret ) {
606
- spin_lock_irqsave (& cm_id_priv -> lock , flags );
607
- if (cm_id_priv -> qp ) {
608
- cm_id -> device -> iwcm -> rem_ref (qp );
609
- cm_id_priv -> qp = NULL ;
610
- }
611
- spin_unlock_irqrestore (& cm_id_priv -> lock , flags );
612
- BUG_ON (cm_id_priv -> state != IW_CM_STATE_CONN_SENT );
613
- cm_id_priv -> state = IW_CM_STATE_IDLE ;
614
- clear_bit (IWCM_F_CONNECT_WAIT , & cm_id_priv -> flags );
615
- wake_up_all (& cm_id_priv -> connect_wait );
616
- }
710
+ ret = iw_cm_map (cm_id , true);
711
+ if (!ret )
712
+ ret = cm_id -> device -> iwcm -> connect (cm_id , iw_param );
713
+ if (!ret )
714
+ return 0 ; /* success */
617
715
716
+ spin_lock_irqsave (& cm_id_priv -> lock , flags );
717
+ if (cm_id_priv -> qp ) {
718
+ cm_id -> device -> iwcm -> rem_ref (qp );
719
+ cm_id_priv -> qp = NULL ;
720
+ }
721
+ cm_id_priv -> state = IW_CM_STATE_IDLE ;
722
+ err :
723
+ spin_unlock_irqrestore (& cm_id_priv -> lock , flags );
724
+ clear_bit (IWCM_F_CONNECT_WAIT , & cm_id_priv -> flags );
725
+ wake_up_all (& cm_id_priv -> connect_wait );
618
726
return ret ;
619
727
}
620
728
EXPORT_SYMBOL (iw_cm_connect );
@@ -656,8 +764,23 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv,
656
764
goto out ;
657
765
658
766
cm_id -> provider_data = iw_event -> provider_data ;
659
- cm_id -> local_addr = iw_event -> local_addr ;
660
- cm_id -> remote_addr = iw_event -> remote_addr ;
767
+ cm_id -> m_local_addr = iw_event -> local_addr ;
768
+ cm_id -> m_remote_addr = iw_event -> remote_addr ;
769
+ cm_id -> local_addr = listen_id_priv -> id .local_addr ;
770
+
771
+ ret = iwpm_get_remote_info (& listen_id_priv -> id .m_local_addr ,
772
+ & iw_event -> remote_addr ,
773
+ & cm_id -> remote_addr ,
774
+ RDMA_NL_IWCM );
775
+ if (ret ) {
776
+ cm_id -> remote_addr = iw_event -> remote_addr ;
777
+ } else {
778
+ iw_cm_check_wildcard (& listen_id_priv -> id .m_local_addr ,
779
+ & iw_event -> local_addr ,
780
+ & cm_id -> local_addr );
781
+ iw_event -> local_addr = cm_id -> local_addr ;
782
+ iw_event -> remote_addr = cm_id -> remote_addr ;
783
+ }
661
784
662
785
cm_id_priv = container_of (cm_id , struct iwcm_id_private , id );
663
786
cm_id_priv -> state = IW_CM_STATE_CONN_RECV ;
@@ -753,8 +876,10 @@ static int cm_conn_rep_handler(struct iwcm_id_private *cm_id_priv,
753
876
clear_bit (IWCM_F_CONNECT_WAIT , & cm_id_priv -> flags );
754
877
BUG_ON (cm_id_priv -> state != IW_CM_STATE_CONN_SENT );
755
878
if (iw_event -> status == 0 ) {
756
- cm_id_priv -> id .local_addr = iw_event -> local_addr ;
757
- cm_id_priv -> id .remote_addr = iw_event -> remote_addr ;
879
+ cm_id_priv -> id .m_local_addr = iw_event -> local_addr ;
880
+ cm_id_priv -> id .m_remote_addr = iw_event -> remote_addr ;
881
+ iw_event -> local_addr = cm_id_priv -> id .local_addr ;
882
+ iw_event -> remote_addr = cm_id_priv -> id .remote_addr ;
758
883
cm_id_priv -> state = IW_CM_STATE_ESTABLISHED ;
759
884
} else {
760
885
/* REJECTED or RESET */
@@ -1044,6 +1169,17 @@ EXPORT_SYMBOL(iw_cm_init_qp_attr);
1044
1169
1045
1170
static int __init iw_cm_init (void )
1046
1171
{
1172
+ int ret ;
1173
+
1174
+ ret = iwpm_init (RDMA_NL_IWCM );
1175
+ if (ret )
1176
+ pr_err ("iw_cm: couldn't init iwpm\n" );
1177
+
1178
+ ret = ibnl_add_client (RDMA_NL_IWCM , RDMA_NL_IWPM_NUM_OPS ,
1179
+ iwcm_nl_cb_table );
1180
+ if (ret )
1181
+ pr_err ("iw_cm: couldn't register netlink callbacks\n" );
1182
+
1047
1183
iwcm_wq = create_singlethread_workqueue ("iw_cm_wq" );
1048
1184
if (!iwcm_wq )
1049
1185
return - ENOMEM ;
@@ -1063,6 +1199,8 @@ static void __exit iw_cm_cleanup(void)
1063
1199
{
1064
1200
unregister_net_sysctl_table (iwcm_ctl_table_hdr );
1065
1201
destroy_workqueue (iwcm_wq );
1202
+ ibnl_remove_client (RDMA_NL_IWCM );
1203
+ iwpm_exit (RDMA_NL_IWCM );
1066
1204
}
1067
1205
1068
1206
module_init (iw_cm_init );
0 commit comments