22/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. */
33
44#include "macsec.h"
5+ #include <linux/mlx5/macsec.h>
56
67struct mlx5_reserved_gids {
78 int macsec_index ;
89 const struct ib_gid_attr * physical_gid ;
910};
1011
11- int mlx5r_macsec_alloc_gids (struct mlx5_ib_dev * dev )
12+ struct mlx5_roce_gids {
13+ struct list_head roce_gid_list_entry ;
14+ u16 gid_idx ;
15+ union {
16+ struct sockaddr_in sockaddr_in ;
17+ struct sockaddr_in6 sockaddr_in6 ;
18+ } addr ;
19+ };
20+
21+ struct mlx5_macsec_device {
22+ struct list_head macsec_devices_list_entry ;
23+ void * macdev ;
24+ struct list_head macsec_roce_gids ;
25+ struct list_head tx_rules_list ;
26+ struct list_head rx_rules_list ;
27+ };
28+
29+ static void cleanup_macsec_device (struct mlx5_macsec_device * macsec_device )
30+ {
31+ if (!list_empty (& macsec_device -> tx_rules_list ) ||
32+ !list_empty (& macsec_device -> rx_rules_list ) ||
33+ !list_empty (& macsec_device -> macsec_roce_gids ))
34+ return ;
35+
36+ list_del (& macsec_device -> macsec_devices_list_entry );
37+ kfree (macsec_device );
38+ }
39+
40+ static struct mlx5_macsec_device * get_macsec_device (void * macdev ,
41+ struct list_head * macsec_devices_list )
42+ {
43+ struct mlx5_macsec_device * iter , * macsec_device = NULL ;
44+
45+ list_for_each_entry (iter , macsec_devices_list , macsec_devices_list_entry ) {
46+ if (iter -> macdev == macdev ) {
47+ macsec_device = iter ;
48+ break ;
49+ }
50+ }
51+
52+ if (macsec_device )
53+ return macsec_device ;
54+
55+ macsec_device = kzalloc (sizeof (* macsec_device ), GFP_KERNEL );
56+ if (!macsec_device )
57+ return NULL ;
58+
59+ macsec_device -> macdev = macdev ;
60+ INIT_LIST_HEAD (& macsec_device -> tx_rules_list );
61+ INIT_LIST_HEAD (& macsec_device -> rx_rules_list );
62+ INIT_LIST_HEAD (& macsec_device -> macsec_roce_gids );
63+ list_add (& macsec_device -> macsec_devices_list_entry , macsec_devices_list );
64+
65+ return macsec_device ;
66+ }
67+
68+ static void mlx5_macsec_del_roce_gid (struct mlx5_macsec_device * macsec_device , u16 gid_idx )
69+ {
70+ struct mlx5_roce_gids * current_gid , * next_gid ;
71+
72+ list_for_each_entry_safe (current_gid , next_gid , & macsec_device -> macsec_roce_gids ,
73+ roce_gid_list_entry )
74+ if (current_gid -> gid_idx == gid_idx ) {
75+ list_del (& current_gid -> roce_gid_list_entry );
76+ kfree (current_gid );
77+ }
78+ }
79+
80+ static void mlx5_macsec_save_roce_gid (struct mlx5_macsec_device * macsec_device ,
81+ const struct sockaddr * addr , u16 gid_idx )
82+ {
83+ struct mlx5_roce_gids * roce_gids ;
84+
85+ roce_gids = kzalloc (sizeof (* roce_gids ), GFP_KERNEL );
86+ if (!roce_gids )
87+ return ;
88+
89+ roce_gids -> gid_idx = gid_idx ;
90+ if (addr -> sa_family == AF_INET )
91+ memcpy (& roce_gids -> addr .sockaddr_in , addr , sizeof (roce_gids -> addr .sockaddr_in ));
92+ else
93+ memcpy (& roce_gids -> addr .sockaddr_in6 , addr , sizeof (roce_gids -> addr .sockaddr_in6 ));
94+
95+ list_add_tail (& roce_gids -> roce_gid_list_entry , & macsec_device -> macsec_roce_gids );
96+ }
97+
98+ static void handle_macsec_gids (struct list_head * macsec_devices_list ,
99+ struct mlx5_macsec_event_data * data )
100+ {
101+ struct mlx5_macsec_device * macsec_device ;
102+ struct mlx5_roce_gids * gid ;
103+
104+ macsec_device = get_macsec_device (data -> macdev , macsec_devices_list );
105+ if (!macsec_device )
106+ return ;
107+
108+ list_for_each_entry (gid , & macsec_device -> macsec_roce_gids , roce_gid_list_entry ) {
109+ mlx5_macsec_add_roce_sa_rules (data -> fs_id , (struct sockaddr * )& gid -> addr ,
110+ gid -> gid_idx , & macsec_device -> tx_rules_list ,
111+ & macsec_device -> rx_rules_list , data -> macsec_fs ,
112+ data -> is_tx );
113+ }
114+ }
115+
116+ static void del_sa_roce_rule (struct list_head * macsec_devices_list ,
117+ struct mlx5_macsec_event_data * data )
118+ {
119+ struct mlx5_macsec_device * macsec_device ;
120+
121+ macsec_device = get_macsec_device (data -> macdev , macsec_devices_list );
122+ WARN_ON (!macsec_device );
123+
124+ mlx5_macsec_del_roce_sa_rules (data -> fs_id , data -> macsec_fs ,
125+ & macsec_device -> tx_rules_list ,
126+ & macsec_device -> rx_rules_list , data -> is_tx );
127+ }
128+
129+ static int macsec_event (struct notifier_block * nb , unsigned long event , void * data )
130+ {
131+ struct mlx5_macsec * macsec = container_of (nb , struct mlx5_macsec , blocking_events_nb );
132+
133+ mutex_lock (& macsec -> lock );
134+ switch (event ) {
135+ case MLX5_DRIVER_EVENT_MACSEC_SA_ADDED :
136+ handle_macsec_gids (& macsec -> macsec_devices_list , data );
137+ break ;
138+ case MLX5_DRIVER_EVENT_MACSEC_SA_DELETED :
139+ del_sa_roce_rule (& macsec -> macsec_devices_list , data );
140+ break ;
141+ default :
142+ mutex_unlock (& macsec -> lock );
143+ return NOTIFY_DONE ;
144+ }
145+ mutex_unlock (& macsec -> lock );
146+ return NOTIFY_OK ;
147+ }
148+
149+ void mlx5r_macsec_event_register (struct mlx5_ib_dev * dev )
150+ {
151+ if (!mlx5_is_macsec_roce_supported (dev -> mdev )) {
152+ mlx5_ib_dbg (dev , "RoCE MACsec not supported due to capabilities\n" );
153+ return ;
154+ }
155+
156+ dev -> macsec .blocking_events_nb .notifier_call = macsec_event ;
157+ blocking_notifier_chain_register (& dev -> mdev -> macsec_nh ,
158+ & dev -> macsec .blocking_events_nb );
159+ }
160+
161+ void mlx5r_macsec_event_unregister (struct mlx5_ib_dev * dev )
162+ {
163+ if (!mlx5_is_macsec_roce_supported (dev -> mdev )) {
164+ mlx5_ib_dbg (dev , "RoCE MACsec not supported due to capabilities\n" );
165+ return ;
166+ }
167+
168+ blocking_notifier_chain_unregister (& dev -> mdev -> macsec_nh ,
169+ & dev -> macsec .blocking_events_nb );
170+ }
171+
172+ int mlx5r_macsec_init_gids_and_devlist (struct mlx5_ib_dev * dev )
12173{
13174 int i , j , max_gids ;
14175
@@ -29,6 +190,9 @@ int mlx5r_macsec_alloc_gids(struct mlx5_ib_dev *dev)
29190 dev -> port [i ].reserved_gids [j ].macsec_index = -1 ;
30191 }
31192
193+ INIT_LIST_HEAD (& dev -> macsec .macsec_devices_list );
194+ mutex_init (& dev -> macsec .lock );
195+
32196 return 0 ;
33197err :
34198 while (i >= 0 ) {
@@ -47,15 +211,22 @@ void mlx5r_macsec_dealloc_gids(struct mlx5_ib_dev *dev)
47211
48212 for (i = 0 ; i < dev -> num_ports ; i ++ )
49213 kfree (dev -> port [i ].reserved_gids );
214+
215+ mutex_destroy (& dev -> macsec .lock );
50216}
51217
52218int mlx5r_add_gid_macsec_operations (const struct ib_gid_attr * attr )
53219{
54220 struct mlx5_ib_dev * dev = to_mdev (attr -> device );
221+ struct mlx5_macsec_device * macsec_device ;
55222 const struct ib_gid_attr * physical_gid ;
56223 struct mlx5_reserved_gids * mgids ;
57224 struct net_device * ndev ;
58225 int ret = 0 ;
226+ union {
227+ struct sockaddr_in sockaddr_in ;
228+ struct sockaddr_in6 sockaddr_in6 ;
229+ } addr ;
59230
60231 if (attr -> gid_type != IB_GID_TYPE_ROCE_UDP_ENCAP )
61232 return 0 ;
@@ -76,34 +247,62 @@ int mlx5r_add_gid_macsec_operations(const struct ib_gid_attr *attr)
76247 rcu_read_unlock ();
77248 return 0 ;
78249 }
250+ dev_hold (ndev );
79251 rcu_read_unlock ();
80252
253+ mutex_lock (& dev -> macsec .lock );
254+ macsec_device = get_macsec_device (ndev , & dev -> macsec .macsec_devices_list );
255+ if (!macsec_device ) {
256+ ret = - ENOMEM ;
257+ goto dev_err ;
258+ }
259+
81260 physical_gid = rdma_find_gid (attr -> device , & attr -> gid ,
82261 attr -> gid_type , NULL );
83- if (IS_ERR (physical_gid ))
84- return 0 ;
262+ if (!IS_ERR (physical_gid )) {
263+ ret = set_roce_addr (to_mdev (physical_gid -> device ),
264+ physical_gid -> port_num ,
265+ physical_gid -> index , NULL ,
266+ physical_gid );
267+ if (ret )
268+ goto gid_err ;
85269
86- ret = set_roce_addr (to_mdev (physical_gid -> device ),
87- physical_gid -> port_num ,
88- physical_gid -> index , NULL ,
89- physical_gid );
90- if (ret )
91- goto gid_err ;
270+ mgids = & dev -> port [attr -> port_num - 1 ].reserved_gids [physical_gid -> index ];
271+ mgids -> macsec_index = attr -> index ;
272+ mgids -> physical_gid = physical_gid ;
273+ }
92274
93- mgids = & dev -> port [attr -> port_num - 1 ].reserved_gids [physical_gid -> index ];
94- mgids -> macsec_index = attr -> index ;
95- mgids -> physical_gid = physical_gid ;
275+ /* Proceed with adding steering rules, regardless if there was gid ambiguity or not.*/
276+ rdma_gid2ip ((struct sockaddr * )& addr , & attr -> gid );
277+ ret = mlx5_macsec_add_roce_rule (ndev , (struct sockaddr * )& addr , attr -> index ,
278+ & macsec_device -> tx_rules_list ,
279+ & macsec_device -> rx_rules_list , dev -> mdev -> macsec_fs );
280+ if (ret && !IS_ERR (physical_gid ))
281+ goto rule_err ;
96282
97- return 0 ;
283+ mlx5_macsec_save_roce_gid (macsec_device , (struct sockaddr * )& addr , attr -> index );
284+
285+ dev_put (ndev );
286+ mutex_unlock (& dev -> macsec .lock );
287+ return ret ;
98288
289+ rule_err :
290+ set_roce_addr (to_mdev (physical_gid -> device ), physical_gid -> port_num ,
291+ physical_gid -> index , & physical_gid -> gid , physical_gid );
292+ mgids -> macsec_index = -1 ;
99293gid_err :
100294 rdma_put_gid_attr (physical_gid );
295+ cleanup_macsec_device (macsec_device );
296+ dev_err :
297+ dev_put (ndev );
298+ mutex_unlock (& dev -> macsec .lock );
101299 return ret ;
102300}
103301
104302void mlx5r_del_gid_macsec_operations (const struct ib_gid_attr * attr )
105303{
106304 struct mlx5_ib_dev * dev = to_mdev (attr -> device );
305+ struct mlx5_macsec_device * macsec_device ;
107306 struct mlx5_reserved_gids * mgids ;
108307 struct net_device * ndev ;
109308 int i , max_gids ;
@@ -134,8 +333,10 @@ void mlx5r_del_gid_macsec_operations(const struct ib_gid_attr *attr)
134333 rcu_read_unlock ();
135334 return ;
136335 }
336+ dev_hold (ndev );
137337 rcu_read_unlock ();
138338
339+ mutex_lock (& dev -> macsec .lock );
139340 max_gids = MLX5_CAP_ROCE (dev -> mdev , roce_address_table_size );
140341 for (i = 0 ; i < max_gids ; i ++ ) { /* Checking if macsec gid has ambiguous IP */
141342 mgids = & dev -> port [attr -> port_num - 1 ].reserved_gids [i ];
@@ -152,4 +353,12 @@ void mlx5r_del_gid_macsec_operations(const struct ib_gid_attr *attr)
152353 break ;
153354 }
154355 }
356+ macsec_device = get_macsec_device (ndev , & dev -> macsec .macsec_devices_list );
357+ mlx5_macsec_del_roce_rule (attr -> index , dev -> mdev -> macsec_fs ,
358+ & macsec_device -> tx_rules_list , & macsec_device -> rx_rules_list );
359+ mlx5_macsec_del_roce_gid (macsec_device , attr -> index );
360+ cleanup_macsec_device (macsec_device );
361+
362+ dev_put (ndev );
363+ mutex_unlock (& dev -> macsec .lock );
155364}
0 commit comments