1 /*
2 * Copyright (c) 2018 Cumulus Networks. All rights reserved.
3 * Copyright (c) 2018 David Ahern <dsa@cumulusnetworks.com>
4 * Copyright (c) 2019 Mellanox Technologies. All rights reserved.
5 *
6 * This software is licensed under the GNU General License Version 2,
7 * June 1991 as shown in the file COPYING in the top-level directory of this
8 * source tree.
9 *
10 * THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS"
11 * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
12 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13 * FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
14 * OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
15 * THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16 */
17
18 #include <linux/debugfs.h>
19 #include <linux/device.h>
20 #include <linux/etherdevice.h>
21 #include <linux/inet.h>
22 #include <linux/jiffies.h>
23 #include <linux/kernel.h>
24 #include <linux/list.h>
25 #include <linux/mutex.h>
26 #include <linux/random.h>
27 #include <linux/rtnetlink.h>
28 #include <linux/workqueue.h>
29 #include <net/devlink.h>
30 #include <net/ip.h>
31 #include <net/flow_offload.h>
32 #include <uapi/linux/devlink.h>
33 #include <uapi/linux/ip.h>
34 #include <uapi/linux/udp.h>
35
36 #include "netdevsim.h"
37
38 static struct dentry *nsim_dev_ddir;
39
40 #define NSIM_DEV_DUMMY_REGION_SIZE (1024 * 32)
41
42 static int
nsim_dev_take_snapshot(struct devlink * devlink,const struct devlink_region_ops * ops,struct netlink_ext_ack * extack,u8 ** data)43 nsim_dev_take_snapshot(struct devlink *devlink,
44 const struct devlink_region_ops *ops,
45 struct netlink_ext_ack *extack,
46 u8 **data)
47 {
48 void *dummy_data;
49
50 dummy_data = kmalloc(NSIM_DEV_DUMMY_REGION_SIZE, GFP_KERNEL);
51 if (!dummy_data)
52 return -ENOMEM;
53
54 get_random_bytes(dummy_data, NSIM_DEV_DUMMY_REGION_SIZE);
55
56 *data = dummy_data;
57
58 return 0;
59 }
60
nsim_dev_take_snapshot_write(struct file * file,const char __user * data,size_t count,loff_t * ppos)61 static ssize_t nsim_dev_take_snapshot_write(struct file *file,
62 const char __user *data,
63 size_t count, loff_t *ppos)
64 {
65 struct nsim_dev *nsim_dev = file->private_data;
66 struct devlink *devlink;
67 u8 *dummy_data;
68 int err;
69 u32 id;
70
71 devlink = priv_to_devlink(nsim_dev);
72
73 err = nsim_dev_take_snapshot(devlink, NULL, NULL, &dummy_data);
74 if (err)
75 return err;
76
77 err = devlink_region_snapshot_id_get(devlink, &id);
78 if (err) {
79 pr_err("Failed to get snapshot id\n");
80 kfree(dummy_data);
81 return err;
82 }
83 err = devlink_region_snapshot_create(nsim_dev->dummy_region,
84 dummy_data, id);
85 devlink_region_snapshot_id_put(devlink, id);
86 if (err) {
87 pr_err("Failed to create region snapshot\n");
88 kfree(dummy_data);
89 return err;
90 }
91
92 return count;
93 }
94
95 static const struct file_operations nsim_dev_take_snapshot_fops = {
96 .open = simple_open,
97 .write = nsim_dev_take_snapshot_write,
98 .llseek = generic_file_llseek,
99 .owner = THIS_MODULE,
100 };
101
nsim_dev_trap_fa_cookie_read(struct file * file,char __user * data,size_t count,loff_t * ppos)102 static ssize_t nsim_dev_trap_fa_cookie_read(struct file *file,
103 char __user *data,
104 size_t count, loff_t *ppos)
105 {
106 struct nsim_dev *nsim_dev = file->private_data;
107 struct flow_action_cookie *fa_cookie;
108 unsigned int buf_len;
109 ssize_t ret;
110 char *buf;
111
112 spin_lock(&nsim_dev->fa_cookie_lock);
113 fa_cookie = nsim_dev->fa_cookie;
114 if (!fa_cookie) {
115 ret = -EINVAL;
116 goto errout;
117 }
118 buf_len = fa_cookie->cookie_len * 2;
119 buf = kmalloc(buf_len, GFP_ATOMIC);
120 if (!buf) {
121 ret = -ENOMEM;
122 goto errout;
123 }
124 bin2hex(buf, fa_cookie->cookie, fa_cookie->cookie_len);
125 spin_unlock(&nsim_dev->fa_cookie_lock);
126
127 ret = simple_read_from_buffer(data, count, ppos, buf, buf_len);
128
129 kfree(buf);
130 return ret;
131
132 errout:
133 spin_unlock(&nsim_dev->fa_cookie_lock);
134 return ret;
135 }
136
nsim_dev_trap_fa_cookie_write(struct file * file,const char __user * data,size_t count,loff_t * ppos)137 static ssize_t nsim_dev_trap_fa_cookie_write(struct file *file,
138 const char __user *data,
139 size_t count, loff_t *ppos)
140 {
141 struct nsim_dev *nsim_dev = file->private_data;
142 struct flow_action_cookie *fa_cookie;
143 size_t cookie_len;
144 ssize_t ret;
145 char *buf;
146
147 if (*ppos != 0)
148 return -EINVAL;
149 cookie_len = (count - 1) / 2;
150 if ((count - 1) % 2)
151 return -EINVAL;
152 buf = kmalloc(count, GFP_KERNEL | __GFP_NOWARN);
153 if (!buf)
154 return -ENOMEM;
155
156 ret = simple_write_to_buffer(buf, count, ppos, data, count);
157 if (ret < 0)
158 goto free_buf;
159
160 fa_cookie = kmalloc(sizeof(*fa_cookie) + cookie_len,
161 GFP_KERNEL | __GFP_NOWARN);
162 if (!fa_cookie) {
163 ret = -ENOMEM;
164 goto free_buf;
165 }
166
167 fa_cookie->cookie_len = cookie_len;
168 ret = hex2bin(fa_cookie->cookie, buf, cookie_len);
169 if (ret)
170 goto free_fa_cookie;
171 kfree(buf);
172
173 spin_lock(&nsim_dev->fa_cookie_lock);
174 kfree(nsim_dev->fa_cookie);
175 nsim_dev->fa_cookie = fa_cookie;
176 spin_unlock(&nsim_dev->fa_cookie_lock);
177
178 return count;
179
180 free_fa_cookie:
181 kfree(fa_cookie);
182 free_buf:
183 kfree(buf);
184 return ret;
185 }
186
187 static const struct file_operations nsim_dev_trap_fa_cookie_fops = {
188 .open = simple_open,
189 .read = nsim_dev_trap_fa_cookie_read,
190 .write = nsim_dev_trap_fa_cookie_write,
191 .llseek = generic_file_llseek,
192 .owner = THIS_MODULE,
193 };
194
nsim_dev_debugfs_init(struct nsim_dev * nsim_dev)195 static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev)
196 {
197 char dev_ddir_name[sizeof(DRV_NAME) + 10];
198
199 sprintf(dev_ddir_name, DRV_NAME "%u", nsim_dev->nsim_bus_dev->dev.id);
200 nsim_dev->ddir = debugfs_create_dir(dev_ddir_name, nsim_dev_ddir);
201 if (IS_ERR(nsim_dev->ddir))
202 return PTR_ERR(nsim_dev->ddir);
203 nsim_dev->ports_ddir = debugfs_create_dir("ports", nsim_dev->ddir);
204 if (IS_ERR(nsim_dev->ports_ddir))
205 return PTR_ERR(nsim_dev->ports_ddir);
206 debugfs_create_bool("fw_update_status", 0600, nsim_dev->ddir,
207 &nsim_dev->fw_update_status);
208 debugfs_create_u32("fw_update_overwrite_mask", 0600, nsim_dev->ddir,
209 &nsim_dev->fw_update_overwrite_mask);
210 debugfs_create_u32("max_macs", 0600, nsim_dev->ddir,
211 &nsim_dev->max_macs);
212 debugfs_create_bool("test1", 0600, nsim_dev->ddir,
213 &nsim_dev->test1);
214 nsim_dev->take_snapshot = debugfs_create_file("take_snapshot",
215 0200,
216 nsim_dev->ddir,
217 nsim_dev,
218 &nsim_dev_take_snapshot_fops);
219 debugfs_create_bool("dont_allow_reload", 0600, nsim_dev->ddir,
220 &nsim_dev->dont_allow_reload);
221 debugfs_create_bool("fail_reload", 0600, nsim_dev->ddir,
222 &nsim_dev->fail_reload);
223 debugfs_create_file("trap_flow_action_cookie", 0600, nsim_dev->ddir,
224 nsim_dev, &nsim_dev_trap_fa_cookie_fops);
225 debugfs_create_bool("fail_trap_group_set", 0600,
226 nsim_dev->ddir,
227 &nsim_dev->fail_trap_group_set);
228 debugfs_create_bool("fail_trap_policer_set", 0600,
229 nsim_dev->ddir,
230 &nsim_dev->fail_trap_policer_set);
231 debugfs_create_bool("fail_trap_policer_counter_get", 0600,
232 nsim_dev->ddir,
233 &nsim_dev->fail_trap_policer_counter_get);
234 nsim_udp_tunnels_debugfs_create(nsim_dev);
235 return 0;
236 }
237
nsim_dev_debugfs_exit(struct nsim_dev * nsim_dev)238 static void nsim_dev_debugfs_exit(struct nsim_dev *nsim_dev)
239 {
240 debugfs_remove_recursive(nsim_dev->ports_ddir);
241 debugfs_remove_recursive(nsim_dev->ddir);
242 }
243
nsim_dev_port_debugfs_init(struct nsim_dev * nsim_dev,struct nsim_dev_port * nsim_dev_port)244 static int nsim_dev_port_debugfs_init(struct nsim_dev *nsim_dev,
245 struct nsim_dev_port *nsim_dev_port)
246 {
247 char port_ddir_name[16];
248 char dev_link_name[32];
249
250 sprintf(port_ddir_name, "%u", nsim_dev_port->port_index);
251 nsim_dev_port->ddir = debugfs_create_dir(port_ddir_name,
252 nsim_dev->ports_ddir);
253 if (IS_ERR(nsim_dev_port->ddir))
254 return PTR_ERR(nsim_dev_port->ddir);
255
256 sprintf(dev_link_name, "../../../" DRV_NAME "%u",
257 nsim_dev->nsim_bus_dev->dev.id);
258 debugfs_create_symlink("dev", nsim_dev_port->ddir, dev_link_name);
259
260 return 0;
261 }
262
nsim_dev_port_debugfs_exit(struct nsim_dev_port * nsim_dev_port)263 static void nsim_dev_port_debugfs_exit(struct nsim_dev_port *nsim_dev_port)
264 {
265 debugfs_remove_recursive(nsim_dev_port->ddir);
266 }
267
nsim_dev_resources_register(struct devlink * devlink)268 static int nsim_dev_resources_register(struct devlink *devlink)
269 {
270 struct devlink_resource_size_params params = {
271 .size_max = (u64)-1,
272 .size_granularity = 1,
273 .unit = DEVLINK_RESOURCE_UNIT_ENTRY
274 };
275 int err;
276
277 /* Resources for IPv4 */
278 err = devlink_resource_register(devlink, "IPv4", (u64)-1,
279 NSIM_RESOURCE_IPV4,
280 DEVLINK_RESOURCE_ID_PARENT_TOP,
281 ¶ms);
282 if (err) {
283 pr_err("Failed to register IPv4 top resource\n");
284 goto out;
285 }
286
287 err = devlink_resource_register(devlink, "fib", (u64)-1,
288 NSIM_RESOURCE_IPV4_FIB,
289 NSIM_RESOURCE_IPV4, ¶ms);
290 if (err) {
291 pr_err("Failed to register IPv4 FIB resource\n");
292 return err;
293 }
294
295 err = devlink_resource_register(devlink, "fib-rules", (u64)-1,
296 NSIM_RESOURCE_IPV4_FIB_RULES,
297 NSIM_RESOURCE_IPV4, ¶ms);
298 if (err) {
299 pr_err("Failed to register IPv4 FIB rules resource\n");
300 return err;
301 }
302
303 /* Resources for IPv6 */
304 err = devlink_resource_register(devlink, "IPv6", (u64)-1,
305 NSIM_RESOURCE_IPV6,
306 DEVLINK_RESOURCE_ID_PARENT_TOP,
307 ¶ms);
308 if (err) {
309 pr_err("Failed to register IPv6 top resource\n");
310 goto out;
311 }
312
313 err = devlink_resource_register(devlink, "fib", (u64)-1,
314 NSIM_RESOURCE_IPV6_FIB,
315 NSIM_RESOURCE_IPV6, ¶ms);
316 if (err) {
317 pr_err("Failed to register IPv6 FIB resource\n");
318 return err;
319 }
320
321 err = devlink_resource_register(devlink, "fib-rules", (u64)-1,
322 NSIM_RESOURCE_IPV6_FIB_RULES,
323 NSIM_RESOURCE_IPV6, ¶ms);
324 if (err) {
325 pr_err("Failed to register IPv6 FIB rules resource\n");
326 return err;
327 }
328
329 out:
330 return err;
331 }
332
333 enum nsim_devlink_param_id {
334 NSIM_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
335 NSIM_DEVLINK_PARAM_ID_TEST1,
336 };
337
338 static const struct devlink_param nsim_devlink_params[] = {
339 DEVLINK_PARAM_GENERIC(MAX_MACS,
340 BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
341 NULL, NULL, NULL),
342 DEVLINK_PARAM_DRIVER(NSIM_DEVLINK_PARAM_ID_TEST1,
343 "test1", DEVLINK_PARAM_TYPE_BOOL,
344 BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
345 NULL, NULL, NULL),
346 };
347
nsim_devlink_set_params_init_values(struct nsim_dev * nsim_dev,struct devlink * devlink)348 static void nsim_devlink_set_params_init_values(struct nsim_dev *nsim_dev,
349 struct devlink *devlink)
350 {
351 union devlink_param_value value;
352
353 value.vu32 = nsim_dev->max_macs;
354 devlink_param_driverinit_value_set(devlink,
355 DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
356 value);
357 value.vbool = nsim_dev->test1;
358 devlink_param_driverinit_value_set(devlink,
359 NSIM_DEVLINK_PARAM_ID_TEST1,
360 value);
361 }
362
nsim_devlink_param_load_driverinit_values(struct devlink * devlink)363 static void nsim_devlink_param_load_driverinit_values(struct devlink *devlink)
364 {
365 struct nsim_dev *nsim_dev = devlink_priv(devlink);
366 union devlink_param_value saved_value;
367 int err;
368
369 err = devlink_param_driverinit_value_get(devlink,
370 DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
371 &saved_value);
372 if (!err)
373 nsim_dev->max_macs = saved_value.vu32;
374 err = devlink_param_driverinit_value_get(devlink,
375 NSIM_DEVLINK_PARAM_ID_TEST1,
376 &saved_value);
377 if (!err)
378 nsim_dev->test1 = saved_value.vbool;
379 }
380
381 #define NSIM_DEV_DUMMY_REGION_SNAPSHOT_MAX 16
382
383 static const struct devlink_region_ops dummy_region_ops = {
384 .name = "dummy",
385 .destructor = &kfree,
386 .snapshot = nsim_dev_take_snapshot,
387 };
388
nsim_dev_dummy_region_init(struct nsim_dev * nsim_dev,struct devlink * devlink)389 static int nsim_dev_dummy_region_init(struct nsim_dev *nsim_dev,
390 struct devlink *devlink)
391 {
392 nsim_dev->dummy_region =
393 devlink_region_create(devlink, &dummy_region_ops,
394 NSIM_DEV_DUMMY_REGION_SNAPSHOT_MAX,
395 NSIM_DEV_DUMMY_REGION_SIZE);
396 return PTR_ERR_OR_ZERO(nsim_dev->dummy_region);
397 }
398
nsim_dev_dummy_region_exit(struct nsim_dev * nsim_dev)399 static void nsim_dev_dummy_region_exit(struct nsim_dev *nsim_dev)
400 {
401 devlink_region_destroy(nsim_dev->dummy_region);
402 }
403
404 struct nsim_trap_item {
405 void *trap_ctx;
406 enum devlink_trap_action action;
407 };
408
409 struct nsim_trap_data {
410 struct delayed_work trap_report_dw;
411 struct nsim_trap_item *trap_items_arr;
412 u64 *trap_policers_cnt_arr;
413 struct nsim_dev *nsim_dev;
414 spinlock_t trap_lock; /* Protects trap_items_arr */
415 };
416
417 /* All driver-specific traps must be documented in
418 * Documentation/networking/devlink/netdevsim.rst
419 */
420 enum {
421 NSIM_TRAP_ID_BASE = DEVLINK_TRAP_GENERIC_ID_MAX,
422 NSIM_TRAP_ID_FID_MISS,
423 };
424
425 #define NSIM_TRAP_NAME_FID_MISS "fid_miss"
426
427 #define NSIM_TRAP_METADATA DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT
428
429 #define NSIM_TRAP_DROP(_id, _group_id) \
430 DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \
431 DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
432 NSIM_TRAP_METADATA)
433 #define NSIM_TRAP_DROP_EXT(_id, _group_id, _metadata) \
434 DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \
435 DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
436 NSIM_TRAP_METADATA | (_metadata))
437 #define NSIM_TRAP_EXCEPTION(_id, _group_id) \
438 DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id, \
439 DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
440 NSIM_TRAP_METADATA)
441 #define NSIM_TRAP_CONTROL(_id, _group_id, _action) \
442 DEVLINK_TRAP_GENERIC(CONTROL, _action, _id, \
443 DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
444 NSIM_TRAP_METADATA)
445 #define NSIM_TRAP_DRIVER_EXCEPTION(_id, _group_id) \
446 DEVLINK_TRAP_DRIVER(EXCEPTION, TRAP, NSIM_TRAP_ID_##_id, \
447 NSIM_TRAP_NAME_##_id, \
448 DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
449 NSIM_TRAP_METADATA)
450
451 #define NSIM_DEV_TRAP_POLICER_MIN_RATE 1
452 #define NSIM_DEV_TRAP_POLICER_MAX_RATE 8000
453 #define NSIM_DEV_TRAP_POLICER_MIN_BURST 8
454 #define NSIM_DEV_TRAP_POLICER_MAX_BURST 65536
455
456 #define NSIM_TRAP_POLICER(_id, _rate, _burst) \
457 DEVLINK_TRAP_POLICER(_id, _rate, _burst, \
458 NSIM_DEV_TRAP_POLICER_MAX_RATE, \
459 NSIM_DEV_TRAP_POLICER_MIN_RATE, \
460 NSIM_DEV_TRAP_POLICER_MAX_BURST, \
461 NSIM_DEV_TRAP_POLICER_MIN_BURST)
462
463 static const struct devlink_trap_policer nsim_trap_policers_arr[] = {
464 NSIM_TRAP_POLICER(1, 1000, 128),
465 NSIM_TRAP_POLICER(2, 2000, 256),
466 NSIM_TRAP_POLICER(3, 3000, 512),
467 };
468
469 static const struct devlink_trap_group nsim_trap_groups_arr[] = {
470 DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0),
471 DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS, 1),
472 DEVLINK_TRAP_GROUP_GENERIC(L3_EXCEPTIONS, 1),
473 DEVLINK_TRAP_GROUP_GENERIC(BUFFER_DROPS, 2),
474 DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS, 3),
475 DEVLINK_TRAP_GROUP_GENERIC(MC_SNOOPING, 3),
476 };
477
478 static const struct devlink_trap nsim_traps_arr[] = {
479 NSIM_TRAP_DROP(SMAC_MC, L2_DROPS),
480 NSIM_TRAP_DROP(VLAN_TAG_MISMATCH, L2_DROPS),
481 NSIM_TRAP_DROP(INGRESS_VLAN_FILTER, L2_DROPS),
482 NSIM_TRAP_DROP(INGRESS_STP_FILTER, L2_DROPS),
483 NSIM_TRAP_DROP(EMPTY_TX_LIST, L2_DROPS),
484 NSIM_TRAP_DROP(PORT_LOOPBACK_FILTER, L2_DROPS),
485 NSIM_TRAP_DRIVER_EXCEPTION(FID_MISS, L2_DROPS),
486 NSIM_TRAP_DROP(BLACKHOLE_ROUTE, L3_DROPS),
487 NSIM_TRAP_EXCEPTION(TTL_ERROR, L3_EXCEPTIONS),
488 NSIM_TRAP_DROP(TAIL_DROP, BUFFER_DROPS),
489 NSIM_TRAP_DROP_EXT(INGRESS_FLOW_ACTION_DROP, ACL_DROPS,
490 DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE),
491 NSIM_TRAP_DROP_EXT(EGRESS_FLOW_ACTION_DROP, ACL_DROPS,
492 DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE),
493 NSIM_TRAP_CONTROL(IGMP_QUERY, MC_SNOOPING, MIRROR),
494 NSIM_TRAP_CONTROL(IGMP_V1_REPORT, MC_SNOOPING, TRAP),
495 };
496
497 #define NSIM_TRAP_L4_DATA_LEN 100
498
nsim_dev_trap_skb_build(void)499 static struct sk_buff *nsim_dev_trap_skb_build(void)
500 {
501 int tot_len, data_len = NSIM_TRAP_L4_DATA_LEN;
502 struct sk_buff *skb;
503 struct udphdr *udph;
504 struct ethhdr *eth;
505 struct iphdr *iph;
506
507 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
508 if (!skb)
509 return NULL;
510 tot_len = sizeof(struct iphdr) + sizeof(struct udphdr) + data_len;
511
512 skb_reset_mac_header(skb);
513 eth = skb_put(skb, sizeof(struct ethhdr));
514 eth_random_addr(eth->h_dest);
515 eth_random_addr(eth->h_source);
516 eth->h_proto = htons(ETH_P_IP);
517 skb->protocol = htons(ETH_P_IP);
518
519 skb_set_network_header(skb, skb->len);
520 iph = skb_put(skb, sizeof(struct iphdr));
521 iph->protocol = IPPROTO_UDP;
522 iph->saddr = in_aton("192.0.2.1");
523 iph->daddr = in_aton("198.51.100.1");
524 iph->version = 0x4;
525 iph->frag_off = 0;
526 iph->ihl = 0x5;
527 iph->tot_len = htons(tot_len);
528 iph->ttl = 100;
529 iph->check = 0;
530 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
531
532 skb_set_transport_header(skb, skb->len);
533 udph = skb_put_zero(skb, sizeof(struct udphdr) + data_len);
534 get_random_bytes(&udph->source, sizeof(u16));
535 get_random_bytes(&udph->dest, sizeof(u16));
536 udph->len = htons(sizeof(struct udphdr) + data_len);
537
538 return skb;
539 }
540
nsim_dev_trap_report(struct nsim_dev_port * nsim_dev_port)541 static void nsim_dev_trap_report(struct nsim_dev_port *nsim_dev_port)
542 {
543 struct nsim_dev *nsim_dev = nsim_dev_port->ns->nsim_dev;
544 struct devlink *devlink = priv_to_devlink(nsim_dev);
545 struct nsim_trap_data *nsim_trap_data;
546 int i;
547
548 nsim_trap_data = nsim_dev->trap_data;
549
550 spin_lock(&nsim_trap_data->trap_lock);
551 for (i = 0; i < ARRAY_SIZE(nsim_traps_arr); i++) {
552 struct flow_action_cookie *fa_cookie = NULL;
553 struct nsim_trap_item *nsim_trap_item;
554 struct sk_buff *skb;
555 bool has_fa_cookie;
556
557 has_fa_cookie = nsim_traps_arr[i].metadata_cap &
558 DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE;
559
560 nsim_trap_item = &nsim_trap_data->trap_items_arr[i];
561 if (nsim_trap_item->action == DEVLINK_TRAP_ACTION_DROP)
562 continue;
563
564 skb = nsim_dev_trap_skb_build();
565 if (!skb)
566 continue;
567 skb->dev = nsim_dev_port->ns->netdev;
568
569 /* Trapped packets are usually passed to devlink in softIRQ,
570 * but in this case they are generated in a workqueue. Disable
571 * softIRQs to prevent lockdep from complaining about
572 * "incosistent lock state".
573 */
574
575 spin_lock_bh(&nsim_dev->fa_cookie_lock);
576 fa_cookie = has_fa_cookie ? nsim_dev->fa_cookie : NULL;
577 devlink_trap_report(devlink, skb, nsim_trap_item->trap_ctx,
578 &nsim_dev_port->devlink_port, fa_cookie);
579 spin_unlock_bh(&nsim_dev->fa_cookie_lock);
580 consume_skb(skb);
581 }
582 spin_unlock(&nsim_trap_data->trap_lock);
583 }
584
585 #define NSIM_TRAP_REPORT_INTERVAL_MS 100
586
nsim_dev_trap_report_work(struct work_struct * work)587 static void nsim_dev_trap_report_work(struct work_struct *work)
588 {
589 struct nsim_trap_data *nsim_trap_data;
590 struct nsim_dev_port *nsim_dev_port;
591 struct nsim_dev *nsim_dev;
592
593 nsim_trap_data = container_of(work, struct nsim_trap_data,
594 trap_report_dw.work);
595 nsim_dev = nsim_trap_data->nsim_dev;
596
597 /* For each running port and enabled packet trap, generate a UDP
598 * packet with a random 5-tuple and report it.
599 */
600 mutex_lock(&nsim_dev->port_list_lock);
601 list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list) {
602 if (!netif_running(nsim_dev_port->ns->netdev))
603 continue;
604
605 nsim_dev_trap_report(nsim_dev_port);
606 }
607 mutex_unlock(&nsim_dev->port_list_lock);
608
609 schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw,
610 msecs_to_jiffies(NSIM_TRAP_REPORT_INTERVAL_MS));
611 }
612
nsim_dev_traps_init(struct devlink * devlink)613 static int nsim_dev_traps_init(struct devlink *devlink)
614 {
615 size_t policers_count = ARRAY_SIZE(nsim_trap_policers_arr);
616 struct nsim_dev *nsim_dev = devlink_priv(devlink);
617 struct nsim_trap_data *nsim_trap_data;
618 int err;
619
620 nsim_trap_data = kzalloc(sizeof(*nsim_trap_data), GFP_KERNEL);
621 if (!nsim_trap_data)
622 return -ENOMEM;
623
624 nsim_trap_data->trap_items_arr = kcalloc(ARRAY_SIZE(nsim_traps_arr),
625 sizeof(struct nsim_trap_item),
626 GFP_KERNEL);
627 if (!nsim_trap_data->trap_items_arr) {
628 err = -ENOMEM;
629 goto err_trap_data_free;
630 }
631
632 nsim_trap_data->trap_policers_cnt_arr = kcalloc(policers_count,
633 sizeof(u64),
634 GFP_KERNEL);
635 if (!nsim_trap_data->trap_policers_cnt_arr) {
636 err = -ENOMEM;
637 goto err_trap_items_free;
638 }
639
640 /* The lock is used to protect the action state of the registered
641 * traps. The value is written by user and read in delayed work when
642 * iterating over all the traps.
643 */
644 spin_lock_init(&nsim_trap_data->trap_lock);
645 nsim_trap_data->nsim_dev = nsim_dev;
646 nsim_dev->trap_data = nsim_trap_data;
647
648 err = devlink_trap_policers_register(devlink, nsim_trap_policers_arr,
649 policers_count);
650 if (err)
651 goto err_trap_policers_cnt_free;
652
653 err = devlink_trap_groups_register(devlink, nsim_trap_groups_arr,
654 ARRAY_SIZE(nsim_trap_groups_arr));
655 if (err)
656 goto err_trap_policers_unregister;
657
658 err = devlink_traps_register(devlink, nsim_traps_arr,
659 ARRAY_SIZE(nsim_traps_arr), NULL);
660 if (err)
661 goto err_trap_groups_unregister;
662
663 INIT_DELAYED_WORK(&nsim_dev->trap_data->trap_report_dw,
664 nsim_dev_trap_report_work);
665 schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw,
666 msecs_to_jiffies(NSIM_TRAP_REPORT_INTERVAL_MS));
667
668 return 0;
669
670 err_trap_groups_unregister:
671 devlink_trap_groups_unregister(devlink, nsim_trap_groups_arr,
672 ARRAY_SIZE(nsim_trap_groups_arr));
673 err_trap_policers_unregister:
674 devlink_trap_policers_unregister(devlink, nsim_trap_policers_arr,
675 ARRAY_SIZE(nsim_trap_policers_arr));
676 err_trap_policers_cnt_free:
677 kfree(nsim_trap_data->trap_policers_cnt_arr);
678 err_trap_items_free:
679 kfree(nsim_trap_data->trap_items_arr);
680 err_trap_data_free:
681 kfree(nsim_trap_data);
682 return err;
683 }
684
nsim_dev_traps_exit(struct devlink * devlink)685 static void nsim_dev_traps_exit(struct devlink *devlink)
686 {
687 struct nsim_dev *nsim_dev = devlink_priv(devlink);
688
689 cancel_delayed_work_sync(&nsim_dev->trap_data->trap_report_dw);
690 devlink_traps_unregister(devlink, nsim_traps_arr,
691 ARRAY_SIZE(nsim_traps_arr));
692 devlink_trap_groups_unregister(devlink, nsim_trap_groups_arr,
693 ARRAY_SIZE(nsim_trap_groups_arr));
694 devlink_trap_policers_unregister(devlink, nsim_trap_policers_arr,
695 ARRAY_SIZE(nsim_trap_policers_arr));
696 kfree(nsim_dev->trap_data->trap_policers_cnt_arr);
697 kfree(nsim_dev->trap_data->trap_items_arr);
698 kfree(nsim_dev->trap_data);
699 }
700
701 static int nsim_dev_reload_create(struct nsim_dev *nsim_dev,
702 struct netlink_ext_ack *extack);
703 static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev);
704
nsim_dev_reload_down(struct devlink * devlink,bool netns_change,enum devlink_reload_action action,enum devlink_reload_limit limit,struct netlink_ext_ack * extack)705 static int nsim_dev_reload_down(struct devlink *devlink, bool netns_change,
706 enum devlink_reload_action action, enum devlink_reload_limit limit,
707 struct netlink_ext_ack *extack)
708 {
709 struct nsim_dev *nsim_dev = devlink_priv(devlink);
710
711 if (nsim_dev->dont_allow_reload) {
712 /* For testing purposes, user set debugfs dont_allow_reload
713 * value to true. So forbid it.
714 */
715 NL_SET_ERR_MSG_MOD(extack, "User forbid the reload for testing purposes");
716 return -EOPNOTSUPP;
717 }
718
719 nsim_dev_reload_destroy(nsim_dev);
720 return 0;
721 }
722
nsim_dev_reload_up(struct devlink * devlink,enum devlink_reload_action action,enum devlink_reload_limit limit,u32 * actions_performed,struct netlink_ext_ack * extack)723 static int nsim_dev_reload_up(struct devlink *devlink, enum devlink_reload_action action,
724 enum devlink_reload_limit limit, u32 *actions_performed,
725 struct netlink_ext_ack *extack)
726 {
727 struct nsim_dev *nsim_dev = devlink_priv(devlink);
728
729 if (nsim_dev->fail_reload) {
730 /* For testing purposes, user set debugfs fail_reload
731 * value to true. Fail right away.
732 */
733 NL_SET_ERR_MSG_MOD(extack, "User setup the reload to fail for testing purposes");
734 return -EINVAL;
735 }
736
737 *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
738 return nsim_dev_reload_create(nsim_dev, extack);
739 }
740
nsim_dev_info_get(struct devlink * devlink,struct devlink_info_req * req,struct netlink_ext_ack * extack)741 static int nsim_dev_info_get(struct devlink *devlink,
742 struct devlink_info_req *req,
743 struct netlink_ext_ack *extack)
744 {
745 return devlink_info_driver_name_put(req, DRV_NAME);
746 }
747
748 #define NSIM_DEV_FLASH_SIZE 500000
749 #define NSIM_DEV_FLASH_CHUNK_SIZE 1000
750 #define NSIM_DEV_FLASH_CHUNK_TIME_MS 10
751
nsim_dev_flash_update(struct devlink * devlink,struct devlink_flash_update_params * params,struct netlink_ext_ack * extack)752 static int nsim_dev_flash_update(struct devlink *devlink,
753 struct devlink_flash_update_params *params,
754 struct netlink_ext_ack *extack)
755 {
756 struct nsim_dev *nsim_dev = devlink_priv(devlink);
757 int i;
758
759 if ((params->overwrite_mask & ~nsim_dev->fw_update_overwrite_mask) != 0)
760 return -EOPNOTSUPP;
761
762 if (nsim_dev->fw_update_status) {
763 devlink_flash_update_begin_notify(devlink);
764 devlink_flash_update_status_notify(devlink,
765 "Preparing to flash",
766 params->component, 0, 0);
767 }
768
769 for (i = 0; i < NSIM_DEV_FLASH_SIZE / NSIM_DEV_FLASH_CHUNK_SIZE; i++) {
770 if (nsim_dev->fw_update_status)
771 devlink_flash_update_status_notify(devlink, "Flashing",
772 params->component,
773 i * NSIM_DEV_FLASH_CHUNK_SIZE,
774 NSIM_DEV_FLASH_SIZE);
775 msleep(NSIM_DEV_FLASH_CHUNK_TIME_MS);
776 }
777
778 if (nsim_dev->fw_update_status) {
779 devlink_flash_update_status_notify(devlink, "Flashing",
780 params->component,
781 NSIM_DEV_FLASH_SIZE,
782 NSIM_DEV_FLASH_SIZE);
783 devlink_flash_update_timeout_notify(devlink, "Flash select",
784 params->component, 81);
785 devlink_flash_update_status_notify(devlink, "Flashing done",
786 params->component, 0, 0);
787 devlink_flash_update_end_notify(devlink);
788 }
789
790 return 0;
791 }
792
793 static struct nsim_trap_item *
nsim_dev_trap_item_lookup(struct nsim_dev * nsim_dev,u16 trap_id)794 nsim_dev_trap_item_lookup(struct nsim_dev *nsim_dev, u16 trap_id)
795 {
796 struct nsim_trap_data *nsim_trap_data = nsim_dev->trap_data;
797 int i;
798
799 for (i = 0; i < ARRAY_SIZE(nsim_traps_arr); i++) {
800 if (nsim_traps_arr[i].id == trap_id)
801 return &nsim_trap_data->trap_items_arr[i];
802 }
803
804 return NULL;
805 }
806
nsim_dev_devlink_trap_init(struct devlink * devlink,const struct devlink_trap * trap,void * trap_ctx)807 static int nsim_dev_devlink_trap_init(struct devlink *devlink,
808 const struct devlink_trap *trap,
809 void *trap_ctx)
810 {
811 struct nsim_dev *nsim_dev = devlink_priv(devlink);
812 struct nsim_trap_item *nsim_trap_item;
813
814 nsim_trap_item = nsim_dev_trap_item_lookup(nsim_dev, trap->id);
815 if (WARN_ON(!nsim_trap_item))
816 return -ENOENT;
817
818 nsim_trap_item->trap_ctx = trap_ctx;
819 nsim_trap_item->action = trap->init_action;
820
821 return 0;
822 }
823
824 static int
nsim_dev_devlink_trap_action_set(struct devlink * devlink,const struct devlink_trap * trap,enum devlink_trap_action action,struct netlink_ext_ack * extack)825 nsim_dev_devlink_trap_action_set(struct devlink *devlink,
826 const struct devlink_trap *trap,
827 enum devlink_trap_action action,
828 struct netlink_ext_ack *extack)
829 {
830 struct nsim_dev *nsim_dev = devlink_priv(devlink);
831 struct nsim_trap_item *nsim_trap_item;
832
833 nsim_trap_item = nsim_dev_trap_item_lookup(nsim_dev, trap->id);
834 if (WARN_ON(!nsim_trap_item))
835 return -ENOENT;
836
837 spin_lock(&nsim_dev->trap_data->trap_lock);
838 nsim_trap_item->action = action;
839 spin_unlock(&nsim_dev->trap_data->trap_lock);
840
841 return 0;
842 }
843
844 static int
nsim_dev_devlink_trap_group_set(struct devlink * devlink,const struct devlink_trap_group * group,const struct devlink_trap_policer * policer,struct netlink_ext_ack * extack)845 nsim_dev_devlink_trap_group_set(struct devlink *devlink,
846 const struct devlink_trap_group *group,
847 const struct devlink_trap_policer *policer,
848 struct netlink_ext_ack *extack)
849 {
850 struct nsim_dev *nsim_dev = devlink_priv(devlink);
851
852 if (nsim_dev->fail_trap_group_set)
853 return -EINVAL;
854
855 return 0;
856 }
857
858 static int
nsim_dev_devlink_trap_policer_set(struct devlink * devlink,const struct devlink_trap_policer * policer,u64 rate,u64 burst,struct netlink_ext_ack * extack)859 nsim_dev_devlink_trap_policer_set(struct devlink *devlink,
860 const struct devlink_trap_policer *policer,
861 u64 rate, u64 burst,
862 struct netlink_ext_ack *extack)
863 {
864 struct nsim_dev *nsim_dev = devlink_priv(devlink);
865
866 if (nsim_dev->fail_trap_policer_set) {
867 NL_SET_ERR_MSG_MOD(extack, "User setup the operation to fail for testing purposes");
868 return -EINVAL;
869 }
870
871 return 0;
872 }
873
874 static int
nsim_dev_devlink_trap_policer_counter_get(struct devlink * devlink,const struct devlink_trap_policer * policer,u64 * p_drops)875 nsim_dev_devlink_trap_policer_counter_get(struct devlink *devlink,
876 const struct devlink_trap_policer *policer,
877 u64 *p_drops)
878 {
879 struct nsim_dev *nsim_dev = devlink_priv(devlink);
880 u64 *cnt;
881
882 if (nsim_dev->fail_trap_policer_counter_get)
883 return -EINVAL;
884
885 cnt = &nsim_dev->trap_data->trap_policers_cnt_arr[policer->id - 1];
886 *p_drops = (*cnt)++;
887
888 return 0;
889 }
890
891 static const struct devlink_ops nsim_dev_devlink_ops = {
892 .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT |
893 DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
894 .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT),
895 .reload_down = nsim_dev_reload_down,
896 .reload_up = nsim_dev_reload_up,
897 .info_get = nsim_dev_info_get,
898 .flash_update = nsim_dev_flash_update,
899 .trap_init = nsim_dev_devlink_trap_init,
900 .trap_action_set = nsim_dev_devlink_trap_action_set,
901 .trap_group_set = nsim_dev_devlink_trap_group_set,
902 .trap_policer_set = nsim_dev_devlink_trap_policer_set,
903 .trap_policer_counter_get = nsim_dev_devlink_trap_policer_counter_get,
904 };
905
906 #define NSIM_DEV_MAX_MACS_DEFAULT 32
907 #define NSIM_DEV_TEST1_DEFAULT true
908
__nsim_dev_port_add(struct nsim_dev * nsim_dev,unsigned int port_index)909 static int __nsim_dev_port_add(struct nsim_dev *nsim_dev,
910 unsigned int port_index)
911 {
912 struct devlink_port_attrs attrs = {};
913 struct nsim_dev_port *nsim_dev_port;
914 struct devlink_port *devlink_port;
915 int err;
916
917 nsim_dev_port = kzalloc(sizeof(*nsim_dev_port), GFP_KERNEL);
918 if (!nsim_dev_port)
919 return -ENOMEM;
920 nsim_dev_port->port_index = port_index;
921
922 devlink_port = &nsim_dev_port->devlink_port;
923 attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
924 attrs.phys.port_number = port_index + 1;
925 memcpy(attrs.switch_id.id, nsim_dev->switch_id.id, nsim_dev->switch_id.id_len);
926 attrs.switch_id.id_len = nsim_dev->switch_id.id_len;
927 devlink_port_attrs_set(devlink_port, &attrs);
928 err = devlink_port_register(priv_to_devlink(nsim_dev), devlink_port,
929 port_index);
930 if (err)
931 goto err_port_free;
932
933 err = nsim_dev_port_debugfs_init(nsim_dev, nsim_dev_port);
934 if (err)
935 goto err_dl_port_unregister;
936
937 nsim_dev_port->ns = nsim_create(nsim_dev, nsim_dev_port);
938 if (IS_ERR(nsim_dev_port->ns)) {
939 err = PTR_ERR(nsim_dev_port->ns);
940 goto err_port_debugfs_exit;
941 }
942
943 devlink_port_type_eth_set(devlink_port, nsim_dev_port->ns->netdev);
944 list_add(&nsim_dev_port->list, &nsim_dev->port_list);
945
946 return 0;
947
948 err_port_debugfs_exit:
949 nsim_dev_port_debugfs_exit(nsim_dev_port);
950 err_dl_port_unregister:
951 devlink_port_unregister(devlink_port);
952 err_port_free:
953 kfree(nsim_dev_port);
954 return err;
955 }
956
__nsim_dev_port_del(struct nsim_dev_port * nsim_dev_port)957 static void __nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port)
958 {
959 struct devlink_port *devlink_port = &nsim_dev_port->devlink_port;
960
961 list_del(&nsim_dev_port->list);
962 devlink_port_type_clear(devlink_port);
963 nsim_destroy(nsim_dev_port->ns);
964 nsim_dev_port_debugfs_exit(nsim_dev_port);
965 devlink_port_unregister(devlink_port);
966 kfree(nsim_dev_port);
967 }
968
nsim_dev_port_del_all(struct nsim_dev * nsim_dev)969 static void nsim_dev_port_del_all(struct nsim_dev *nsim_dev)
970 {
971 struct nsim_dev_port *nsim_dev_port, *tmp;
972
973 mutex_lock(&nsim_dev->port_list_lock);
974 list_for_each_entry_safe(nsim_dev_port, tmp,
975 &nsim_dev->port_list, list)
976 __nsim_dev_port_del(nsim_dev_port);
977 mutex_unlock(&nsim_dev->port_list_lock);
978 }
979
nsim_dev_port_add_all(struct nsim_dev * nsim_dev,unsigned int port_count)980 static int nsim_dev_port_add_all(struct nsim_dev *nsim_dev,
981 unsigned int port_count)
982 {
983 int i, err;
984
985 for (i = 0; i < port_count; i++) {
986 err = __nsim_dev_port_add(nsim_dev, i);
987 if (err)
988 goto err_port_del_all;
989 }
990 return 0;
991
992 err_port_del_all:
993 nsim_dev_port_del_all(nsim_dev);
994 return err;
995 }
996
nsim_dev_reload_create(struct nsim_dev * nsim_dev,struct netlink_ext_ack * extack)997 static int nsim_dev_reload_create(struct nsim_dev *nsim_dev,
998 struct netlink_ext_ack *extack)
999 {
1000 struct nsim_bus_dev *nsim_bus_dev = nsim_dev->nsim_bus_dev;
1001 struct devlink *devlink;
1002 int err;
1003
1004 devlink = priv_to_devlink(nsim_dev);
1005 nsim_dev = devlink_priv(devlink);
1006 INIT_LIST_HEAD(&nsim_dev->port_list);
1007 mutex_init(&nsim_dev->port_list_lock);
1008 nsim_dev->fw_update_status = true;
1009 nsim_dev->fw_update_overwrite_mask = 0;
1010
1011 nsim_devlink_param_load_driverinit_values(devlink);
1012
1013 err = nsim_dev_dummy_region_init(nsim_dev, devlink);
1014 if (err)
1015 return err;
1016
1017 err = nsim_dev_traps_init(devlink);
1018 if (err)
1019 goto err_dummy_region_exit;
1020
1021 nsim_dev->fib_data = nsim_fib_create(devlink, extack);
1022 if (IS_ERR(nsim_dev->fib_data)) {
1023 err = PTR_ERR(nsim_dev->fib_data);
1024 goto err_traps_exit;
1025 }
1026
1027 err = nsim_dev_health_init(nsim_dev, devlink);
1028 if (err)
1029 goto err_fib_destroy;
1030
1031 err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count);
1032 if (err)
1033 goto err_health_exit;
1034
1035 nsim_dev->take_snapshot = debugfs_create_file("take_snapshot",
1036 0200,
1037 nsim_dev->ddir,
1038 nsim_dev,
1039 &nsim_dev_take_snapshot_fops);
1040 return 0;
1041
1042 err_health_exit:
1043 nsim_dev_health_exit(nsim_dev);
1044 err_fib_destroy:
1045 nsim_fib_destroy(devlink, nsim_dev->fib_data);
1046 err_traps_exit:
1047 nsim_dev_traps_exit(devlink);
1048 err_dummy_region_exit:
1049 nsim_dev_dummy_region_exit(nsim_dev);
1050 return err;
1051 }
1052
nsim_dev_probe(struct nsim_bus_dev * nsim_bus_dev)1053 int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
1054 {
1055 struct nsim_dev *nsim_dev;
1056 struct devlink *devlink;
1057 int err;
1058
1059 devlink = devlink_alloc(&nsim_dev_devlink_ops, sizeof(*nsim_dev));
1060 if (!devlink)
1061 return -ENOMEM;
1062 devlink_net_set(devlink, nsim_bus_dev->initial_net);
1063 nsim_dev = devlink_priv(devlink);
1064 nsim_dev->nsim_bus_dev = nsim_bus_dev;
1065 nsim_dev->switch_id.id_len = sizeof(nsim_dev->switch_id.id);
1066 get_random_bytes(nsim_dev->switch_id.id, nsim_dev->switch_id.id_len);
1067 INIT_LIST_HEAD(&nsim_dev->port_list);
1068 mutex_init(&nsim_dev->port_list_lock);
1069 nsim_dev->fw_update_status = true;
1070 nsim_dev->fw_update_overwrite_mask = 0;
1071 nsim_dev->max_macs = NSIM_DEV_MAX_MACS_DEFAULT;
1072 nsim_dev->test1 = NSIM_DEV_TEST1_DEFAULT;
1073 spin_lock_init(&nsim_dev->fa_cookie_lock);
1074
1075 dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev);
1076
1077 err = nsim_dev_resources_register(devlink);
1078 if (err)
1079 goto err_devlink_free;
1080
1081 err = devlink_register(devlink, &nsim_bus_dev->dev);
1082 if (err)
1083 goto err_resources_unregister;
1084
1085 err = devlink_params_register(devlink, nsim_devlink_params,
1086 ARRAY_SIZE(nsim_devlink_params));
1087 if (err)
1088 goto err_dl_unregister;
1089 nsim_devlink_set_params_init_values(nsim_dev, devlink);
1090
1091 err = nsim_dev_dummy_region_init(nsim_dev, devlink);
1092 if (err)
1093 goto err_params_unregister;
1094
1095 err = nsim_dev_traps_init(devlink);
1096 if (err)
1097 goto err_dummy_region_exit;
1098
1099 err = nsim_dev_debugfs_init(nsim_dev);
1100 if (err)
1101 goto err_traps_exit;
1102
1103 nsim_dev->fib_data = nsim_fib_create(devlink, NULL);
1104 if (IS_ERR(nsim_dev->fib_data)) {
1105 err = PTR_ERR(nsim_dev->fib_data);
1106 goto err_debugfs_exit;
1107 }
1108
1109 err = nsim_dev_health_init(nsim_dev, devlink);
1110 if (err)
1111 goto err_fib_destroy;
1112
1113 err = nsim_bpf_dev_init(nsim_dev);
1114 if (err)
1115 goto err_health_exit;
1116
1117 err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count);
1118 if (err)
1119 goto err_bpf_dev_exit;
1120
1121 devlink_params_publish(devlink);
1122 devlink_reload_enable(devlink);
1123 return 0;
1124
1125 err_bpf_dev_exit:
1126 nsim_bpf_dev_exit(nsim_dev);
1127 err_health_exit:
1128 nsim_dev_health_exit(nsim_dev);
1129 err_fib_destroy:
1130 nsim_fib_destroy(devlink, nsim_dev->fib_data);
1131 err_debugfs_exit:
1132 nsim_dev_debugfs_exit(nsim_dev);
1133 err_traps_exit:
1134 nsim_dev_traps_exit(devlink);
1135 err_dummy_region_exit:
1136 nsim_dev_dummy_region_exit(nsim_dev);
1137 err_params_unregister:
1138 devlink_params_unregister(devlink, nsim_devlink_params,
1139 ARRAY_SIZE(nsim_devlink_params));
1140 err_dl_unregister:
1141 devlink_unregister(devlink);
1142 err_resources_unregister:
1143 devlink_resources_unregister(devlink, NULL);
1144 err_devlink_free:
1145 devlink_free(devlink);
1146 return err;
1147 }
1148
nsim_dev_reload_destroy(struct nsim_dev * nsim_dev)1149 static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev)
1150 {
1151 struct devlink *devlink = priv_to_devlink(nsim_dev);
1152
1153 if (devlink_is_reload_failed(devlink))
1154 return;
1155 debugfs_remove(nsim_dev->take_snapshot);
1156 nsim_dev_port_del_all(nsim_dev);
1157 nsim_dev_health_exit(nsim_dev);
1158 nsim_fib_destroy(devlink, nsim_dev->fib_data);
1159 nsim_dev_traps_exit(devlink);
1160 nsim_dev_dummy_region_exit(nsim_dev);
1161 mutex_destroy(&nsim_dev->port_list_lock);
1162 }
1163
nsim_dev_remove(struct nsim_bus_dev * nsim_bus_dev)1164 void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev)
1165 {
1166 struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
1167 struct devlink *devlink = priv_to_devlink(nsim_dev);
1168
1169 devlink_reload_disable(devlink);
1170
1171 nsim_dev_reload_destroy(nsim_dev);
1172
1173 nsim_bpf_dev_exit(nsim_dev);
1174 nsim_dev_debugfs_exit(nsim_dev);
1175 devlink_params_unregister(devlink, nsim_devlink_params,
1176 ARRAY_SIZE(nsim_devlink_params));
1177 devlink_unregister(devlink);
1178 devlink_resources_unregister(devlink, NULL);
1179 devlink_free(devlink);
1180 }
1181
1182 static struct nsim_dev_port *
__nsim_dev_port_lookup(struct nsim_dev * nsim_dev,unsigned int port_index)1183 __nsim_dev_port_lookup(struct nsim_dev *nsim_dev, unsigned int port_index)
1184 {
1185 struct nsim_dev_port *nsim_dev_port;
1186
1187 list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list)
1188 if (nsim_dev_port->port_index == port_index)
1189 return nsim_dev_port;
1190 return NULL;
1191 }
1192
nsim_dev_port_add(struct nsim_bus_dev * nsim_bus_dev,unsigned int port_index)1193 int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev,
1194 unsigned int port_index)
1195 {
1196 struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
1197 int err;
1198
1199 mutex_lock(&nsim_dev->port_list_lock);
1200 if (__nsim_dev_port_lookup(nsim_dev, port_index))
1201 err = -EEXIST;
1202 else
1203 err = __nsim_dev_port_add(nsim_dev, port_index);
1204 mutex_unlock(&nsim_dev->port_list_lock);
1205 return err;
1206 }
1207
nsim_dev_port_del(struct nsim_bus_dev * nsim_bus_dev,unsigned int port_index)1208 int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev,
1209 unsigned int port_index)
1210 {
1211 struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
1212 struct nsim_dev_port *nsim_dev_port;
1213 int err = 0;
1214
1215 mutex_lock(&nsim_dev->port_list_lock);
1216 nsim_dev_port = __nsim_dev_port_lookup(nsim_dev, port_index);
1217 if (!nsim_dev_port)
1218 err = -ENOENT;
1219 else
1220 __nsim_dev_port_del(nsim_dev_port);
1221 mutex_unlock(&nsim_dev->port_list_lock);
1222 return err;
1223 }
1224
nsim_dev_init(void)1225 int nsim_dev_init(void)
1226 {
1227 nsim_dev_ddir = debugfs_create_dir(DRV_NAME, NULL);
1228 return PTR_ERR_OR_ZERO(nsim_dev_ddir);
1229 }
1230
nsim_dev_exit(void)1231 void nsim_dev_exit(void)
1232 {
1233 debugfs_remove_recursive(nsim_dev_ddir);
1234 }
1235