wwan_hwsim.c (14233B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * WWAN device simulator for WWAN framework testing. 4 * 5 * Copyright (c) 2021, Sergey Ryazanov <ryazanov.s.a@gmail.com> 6 */ 7 8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 10#include <linux/kernel.h> 11#include <linux/module.h> 12#include <linux/slab.h> 13#include <linux/device.h> 14#include <linux/spinlock.h> 15#include <linux/list.h> 16#include <linux/skbuff.h> 17#include <linux/netdevice.h> 18#include <linux/wwan.h> 19#include <linux/debugfs.h> 20#include <linux/workqueue.h> 21 22#include <net/arp.h> 23 24static int wwan_hwsim_devsnum = 2; 25module_param_named(devices, wwan_hwsim_devsnum, int, 0444); 26MODULE_PARM_DESC(devices, "Number of simulated devices"); 27 28static struct class *wwan_hwsim_class; 29 30static struct dentry *wwan_hwsim_debugfs_topdir; 31static struct dentry *wwan_hwsim_debugfs_devcreate; 32 33static DEFINE_SPINLOCK(wwan_hwsim_devs_lock); 34static LIST_HEAD(wwan_hwsim_devs); 35static unsigned int wwan_hwsim_dev_idx; 36static struct workqueue_struct *wwan_wq; 37 38struct wwan_hwsim_dev { 39 struct list_head list; 40 unsigned int id; 41 struct device dev; 42 struct work_struct del_work; 43 struct dentry *debugfs_topdir; 44 struct dentry *debugfs_portcreate; 45 spinlock_t ports_lock; /* Serialize ports creation/deletion */ 46 unsigned int port_idx; 47 struct list_head ports; 48}; 49 50struct wwan_hwsim_port { 51 struct list_head list; 52 unsigned int id; 53 struct wwan_hwsim_dev *dev; 54 struct wwan_port *wwan; 55 struct work_struct del_work; 56 struct dentry *debugfs_topdir; 57 enum { /* AT command parser state */ 58 AT_PARSER_WAIT_A, 59 AT_PARSER_WAIT_T, 60 AT_PARSER_WAIT_TERM, 61 AT_PARSER_SKIP_LINE, 62 } pstate; 63}; 64 65static const struct file_operations wwan_hwsim_debugfs_portdestroy_fops; 66static const struct file_operations wwan_hwsim_debugfs_portcreate_fops; 67static const struct file_operations wwan_hwsim_debugfs_devdestroy_fops; 68static void wwan_hwsim_port_del_work(struct work_struct *work); 69static void wwan_hwsim_dev_del_work(struct work_struct *work); 70 71static netdev_tx_t wwan_hwsim_netdev_xmit(struct sk_buff *skb, 72 struct net_device *ndev) 73{ 74 ndev->stats.tx_packets++; 75 ndev->stats.tx_bytes += skb->len; 76 consume_skb(skb); 77 return NETDEV_TX_OK; 78} 79 80static const struct net_device_ops wwan_hwsim_netdev_ops = { 81 .ndo_start_xmit = wwan_hwsim_netdev_xmit, 82}; 83 84static void wwan_hwsim_netdev_setup(struct net_device *ndev) 85{ 86 ndev->netdev_ops = &wwan_hwsim_netdev_ops; 87 ndev->needs_free_netdev = true; 88 89 ndev->mtu = ETH_DATA_LEN; 90 ndev->min_mtu = ETH_MIN_MTU; 91 ndev->max_mtu = ETH_MAX_MTU; 92 93 ndev->type = ARPHRD_NONE; 94 ndev->flags = IFF_POINTOPOINT | IFF_NOARP; 95} 96 97static const struct wwan_ops wwan_hwsim_wwan_rtnl_ops = { 98 .priv_size = 0, /* No private data */ 99 .setup = wwan_hwsim_netdev_setup, 100}; 101 102static int wwan_hwsim_port_start(struct wwan_port *wport) 103{ 104 struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport); 105 106 port->pstate = AT_PARSER_WAIT_A; 107 108 return 0; 109} 110 111static void wwan_hwsim_port_stop(struct wwan_port *wport) 112{ 113} 114 115/* Implements a minimalistic AT commands parser that echo input back and 116 * reply with 'OK' to each input command. See AT command protocol details in the 117 * ITU-T V.250 recomendations document. 118 * 119 * Be aware that this processor is not fully V.250 compliant. 120 */ 121static int wwan_hwsim_port_tx(struct wwan_port *wport, struct sk_buff *in) 122{ 123 struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport); 124 struct sk_buff *out; 125 int i, n, s; 126 127 /* Estimate a max possible number of commands by counting the number of 128 * termination chars (S3 param, CR by default). And then allocate the 129 * output buffer that will be enough to fit the echo and result codes of 130 * all commands. 131 */ 132 for (i = 0, n = 0; i < in->len; ++i) 133 if (in->data[i] == '\r') 134 n++; 135 n = in->len + n * (2 + 2 + 2); /* Output buffer size */ 136 out = alloc_skb(n, GFP_KERNEL); 137 if (!out) 138 return -ENOMEM; 139 140 for (i = 0, s = 0; i < in->len; ++i) { 141 char c = in->data[i]; 142 143 if (port->pstate == AT_PARSER_WAIT_A) { 144 if (c == 'A' || c == 'a') 145 port->pstate = AT_PARSER_WAIT_T; 146 else if (c != '\n') /* Ignore formating char */ 147 port->pstate = AT_PARSER_SKIP_LINE; 148 } else if (port->pstate == AT_PARSER_WAIT_T) { 149 if (c == 'T' || c == 't') 150 port->pstate = AT_PARSER_WAIT_TERM; 151 else 152 port->pstate = AT_PARSER_SKIP_LINE; 153 } else if (port->pstate == AT_PARSER_WAIT_TERM) { 154 if (c != '\r') 155 continue; 156 /* Consume the trailing formatting char as well */ 157 if ((i + 1) < in->len && in->data[i + 1] == '\n') 158 i++; 159 n = i - s + 1; 160 memcpy(skb_put(out, n), &in->data[s], n);/* Echo */ 161 memcpy(skb_put(out, 6), "\r\nOK\r\n", 6); 162 s = i + 1; 163 port->pstate = AT_PARSER_WAIT_A; 164 } else if (port->pstate == AT_PARSER_SKIP_LINE) { 165 if (c != '\r') 166 continue; 167 port->pstate = AT_PARSER_WAIT_A; 168 } 169 } 170 171 if (i > s) { 172 /* Echo the processed portion of a not yet completed command */ 173 n = i - s; 174 memcpy(skb_put(out, n), &in->data[s], n); 175 } 176 177 consume_skb(in); 178 179 wwan_port_rx(wport, out); 180 181 return 0; 182} 183 184static const struct wwan_port_ops wwan_hwsim_port_ops = { 185 .start = wwan_hwsim_port_start, 186 .stop = wwan_hwsim_port_stop, 187 .tx = wwan_hwsim_port_tx, 188}; 189 190static struct wwan_hwsim_port *wwan_hwsim_port_new(struct wwan_hwsim_dev *dev) 191{ 192 struct wwan_hwsim_port *port; 193 char name[0x10]; 194 int err; 195 196 port = kzalloc(sizeof(*port), GFP_KERNEL); 197 if (!port) 198 return ERR_PTR(-ENOMEM); 199 200 port->dev = dev; 201 202 spin_lock(&dev->ports_lock); 203 port->id = dev->port_idx++; 204 spin_unlock(&dev->ports_lock); 205 206 port->wwan = wwan_create_port(&dev->dev, WWAN_PORT_AT, 207 &wwan_hwsim_port_ops, 208 port); 209 if (IS_ERR(port->wwan)) { 210 err = PTR_ERR(port->wwan); 211 goto err_free_port; 212 } 213 214 INIT_WORK(&port->del_work, wwan_hwsim_port_del_work); 215 216 snprintf(name, sizeof(name), "port%u", port->id); 217 port->debugfs_topdir = debugfs_create_dir(name, dev->debugfs_topdir); 218 debugfs_create_file("destroy", 0200, port->debugfs_topdir, port, 219 &wwan_hwsim_debugfs_portdestroy_fops); 220 221 return port; 222 223err_free_port: 224 kfree(port); 225 226 return ERR_PTR(err); 227} 228 229static void wwan_hwsim_port_del(struct wwan_hwsim_port *port) 230{ 231 debugfs_remove(port->debugfs_topdir); 232 233 /* Make sure that there is no pending deletion work */ 234 if (current_work() != &port->del_work) 235 cancel_work_sync(&port->del_work); 236 237 wwan_remove_port(port->wwan); 238 kfree(port); 239} 240 241static void wwan_hwsim_port_del_work(struct work_struct *work) 242{ 243 struct wwan_hwsim_port *port = 244 container_of(work, typeof(*port), del_work); 245 struct wwan_hwsim_dev *dev = port->dev; 246 247 spin_lock(&dev->ports_lock); 248 if (list_empty(&port->list)) { 249 /* Someone else deleting port at the moment */ 250 spin_unlock(&dev->ports_lock); 251 return; 252 } 253 list_del_init(&port->list); 254 spin_unlock(&dev->ports_lock); 255 256 wwan_hwsim_port_del(port); 257} 258 259static void wwan_hwsim_dev_release(struct device *sysdev) 260{ 261 struct wwan_hwsim_dev *dev = container_of(sysdev, typeof(*dev), dev); 262 263 kfree(dev); 264} 265 266static struct wwan_hwsim_dev *wwan_hwsim_dev_new(void) 267{ 268 struct wwan_hwsim_dev *dev; 269 int err; 270 271 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 272 if (!dev) 273 return ERR_PTR(-ENOMEM); 274 275 spin_lock(&wwan_hwsim_devs_lock); 276 dev->id = wwan_hwsim_dev_idx++; 277 spin_unlock(&wwan_hwsim_devs_lock); 278 279 dev->dev.release = wwan_hwsim_dev_release; 280 dev->dev.class = wwan_hwsim_class; 281 dev_set_name(&dev->dev, "hwsim%u", dev->id); 282 283 spin_lock_init(&dev->ports_lock); 284 INIT_LIST_HEAD(&dev->ports); 285 286 err = device_register(&dev->dev); 287 if (err) 288 goto err_free_dev; 289 290 INIT_WORK(&dev->del_work, wwan_hwsim_dev_del_work); 291 292 err = wwan_register_ops(&dev->dev, &wwan_hwsim_wwan_rtnl_ops, dev, 1); 293 if (err) 294 goto err_unreg_dev; 295 296 dev->debugfs_topdir = debugfs_create_dir(dev_name(&dev->dev), 297 wwan_hwsim_debugfs_topdir); 298 debugfs_create_file("destroy", 0200, dev->debugfs_topdir, dev, 299 &wwan_hwsim_debugfs_devdestroy_fops); 300 dev->debugfs_portcreate = 301 debugfs_create_file("portcreate", 0200, 302 dev->debugfs_topdir, dev, 303 &wwan_hwsim_debugfs_portcreate_fops); 304 305 return dev; 306 307err_unreg_dev: 308 device_unregister(&dev->dev); 309 /* Memory will be freed in the device release callback */ 310 311 return ERR_PTR(err); 312 313err_free_dev: 314 kfree(dev); 315 316 return ERR_PTR(err); 317} 318 319static void wwan_hwsim_dev_del(struct wwan_hwsim_dev *dev) 320{ 321 debugfs_remove(dev->debugfs_portcreate); /* Avoid new ports */ 322 323 spin_lock(&dev->ports_lock); 324 while (!list_empty(&dev->ports)) { 325 struct wwan_hwsim_port *port; 326 327 port = list_first_entry(&dev->ports, struct wwan_hwsim_port, 328 list); 329 list_del_init(&port->list); 330 spin_unlock(&dev->ports_lock); 331 wwan_hwsim_port_del(port); 332 spin_lock(&dev->ports_lock); 333 } 334 spin_unlock(&dev->ports_lock); 335 336 debugfs_remove(dev->debugfs_topdir); 337 338 /* This will remove all child netdev(s) */ 339 wwan_unregister_ops(&dev->dev); 340 341 /* Make sure that there is no pending deletion work */ 342 if (current_work() != &dev->del_work) 343 cancel_work_sync(&dev->del_work); 344 345 device_unregister(&dev->dev); 346 /* Memory will be freed in the device release callback */ 347} 348 349static void wwan_hwsim_dev_del_work(struct work_struct *work) 350{ 351 struct wwan_hwsim_dev *dev = container_of(work, typeof(*dev), del_work); 352 353 spin_lock(&wwan_hwsim_devs_lock); 354 if (list_empty(&dev->list)) { 355 /* Someone else deleting device at the moment */ 356 spin_unlock(&wwan_hwsim_devs_lock); 357 return; 358 } 359 list_del_init(&dev->list); 360 spin_unlock(&wwan_hwsim_devs_lock); 361 362 wwan_hwsim_dev_del(dev); 363} 364 365static ssize_t wwan_hwsim_debugfs_portdestroy_write(struct file *file, 366 const char __user *usrbuf, 367 size_t count, loff_t *ppos) 368{ 369 struct wwan_hwsim_port *port = file->private_data; 370 371 /* We can not delete port here since it will cause a deadlock due to 372 * waiting this callback to finish in the debugfs_remove() call. So, 373 * use workqueue. 374 */ 375 queue_work(wwan_wq, &port->del_work); 376 377 return count; 378} 379 380static const struct file_operations wwan_hwsim_debugfs_portdestroy_fops = { 381 .write = wwan_hwsim_debugfs_portdestroy_write, 382 .open = simple_open, 383 .llseek = noop_llseek, 384}; 385 386static ssize_t wwan_hwsim_debugfs_portcreate_write(struct file *file, 387 const char __user *usrbuf, 388 size_t count, loff_t *ppos) 389{ 390 struct wwan_hwsim_dev *dev = file->private_data; 391 struct wwan_hwsim_port *port; 392 393 port = wwan_hwsim_port_new(dev); 394 if (IS_ERR(port)) 395 return PTR_ERR(port); 396 397 spin_lock(&dev->ports_lock); 398 list_add_tail(&port->list, &dev->ports); 399 spin_unlock(&dev->ports_lock); 400 401 return count; 402} 403 404static const struct file_operations wwan_hwsim_debugfs_portcreate_fops = { 405 .write = wwan_hwsim_debugfs_portcreate_write, 406 .open = simple_open, 407 .llseek = noop_llseek, 408}; 409 410static ssize_t wwan_hwsim_debugfs_devdestroy_write(struct file *file, 411 const char __user *usrbuf, 412 size_t count, loff_t *ppos) 413{ 414 struct wwan_hwsim_dev *dev = file->private_data; 415 416 /* We can not delete device here since it will cause a deadlock due to 417 * waiting this callback to finish in the debugfs_remove() call. So, 418 * use workqueue. 419 */ 420 queue_work(wwan_wq, &dev->del_work); 421 422 return count; 423} 424 425static const struct file_operations wwan_hwsim_debugfs_devdestroy_fops = { 426 .write = wwan_hwsim_debugfs_devdestroy_write, 427 .open = simple_open, 428 .llseek = noop_llseek, 429}; 430 431static ssize_t wwan_hwsim_debugfs_devcreate_write(struct file *file, 432 const char __user *usrbuf, 433 size_t count, loff_t *ppos) 434{ 435 struct wwan_hwsim_dev *dev; 436 437 dev = wwan_hwsim_dev_new(); 438 if (IS_ERR(dev)) 439 return PTR_ERR(dev); 440 441 spin_lock(&wwan_hwsim_devs_lock); 442 list_add_tail(&dev->list, &wwan_hwsim_devs); 443 spin_unlock(&wwan_hwsim_devs_lock); 444 445 return count; 446} 447 448static const struct file_operations wwan_hwsim_debugfs_devcreate_fops = { 449 .write = wwan_hwsim_debugfs_devcreate_write, 450 .open = simple_open, 451 .llseek = noop_llseek, 452}; 453 454static int __init wwan_hwsim_init_devs(void) 455{ 456 struct wwan_hwsim_dev *dev; 457 int i, j; 458 459 for (i = 0; i < wwan_hwsim_devsnum; ++i) { 460 dev = wwan_hwsim_dev_new(); 461 if (IS_ERR(dev)) 462 return PTR_ERR(dev); 463 464 spin_lock(&wwan_hwsim_devs_lock); 465 list_add_tail(&dev->list, &wwan_hwsim_devs); 466 spin_unlock(&wwan_hwsim_devs_lock); 467 468 /* Create a couple of ports per each device to accelerate 469 * the simulator readiness time. 470 */ 471 for (j = 0; j < 2; ++j) { 472 struct wwan_hwsim_port *port; 473 474 port = wwan_hwsim_port_new(dev); 475 if (IS_ERR(port)) 476 return PTR_ERR(port); 477 478 spin_lock(&dev->ports_lock); 479 list_add_tail(&port->list, &dev->ports); 480 spin_unlock(&dev->ports_lock); 481 } 482 } 483 484 return 0; 485} 486 487static void wwan_hwsim_free_devs(void) 488{ 489 struct wwan_hwsim_dev *dev; 490 491 spin_lock(&wwan_hwsim_devs_lock); 492 while (!list_empty(&wwan_hwsim_devs)) { 493 dev = list_first_entry(&wwan_hwsim_devs, struct wwan_hwsim_dev, 494 list); 495 list_del_init(&dev->list); 496 spin_unlock(&wwan_hwsim_devs_lock); 497 wwan_hwsim_dev_del(dev); 498 spin_lock(&wwan_hwsim_devs_lock); 499 } 500 spin_unlock(&wwan_hwsim_devs_lock); 501} 502 503static int __init wwan_hwsim_init(void) 504{ 505 int err; 506 507 if (wwan_hwsim_devsnum < 0 || wwan_hwsim_devsnum > 128) 508 return -EINVAL; 509 510 wwan_wq = alloc_workqueue("wwan_wq", 0, 0); 511 if (!wwan_wq) 512 return -ENOMEM; 513 514 wwan_hwsim_class = class_create(THIS_MODULE, "wwan_hwsim"); 515 if (IS_ERR(wwan_hwsim_class)) { 516 err = PTR_ERR(wwan_hwsim_class); 517 goto err_wq_destroy; 518 } 519 520 wwan_hwsim_debugfs_topdir = debugfs_create_dir("wwan_hwsim", NULL); 521 wwan_hwsim_debugfs_devcreate = 522 debugfs_create_file("devcreate", 0200, 523 wwan_hwsim_debugfs_topdir, NULL, 524 &wwan_hwsim_debugfs_devcreate_fops); 525 526 err = wwan_hwsim_init_devs(); 527 if (err) 528 goto err_clean_devs; 529 530 return 0; 531 532err_clean_devs: 533 debugfs_remove(wwan_hwsim_debugfs_devcreate); /* Avoid new devs */ 534 wwan_hwsim_free_devs(); 535 flush_workqueue(wwan_wq); /* Wait deletion works completion */ 536 debugfs_remove(wwan_hwsim_debugfs_topdir); 537 class_destroy(wwan_hwsim_class); 538err_wq_destroy: 539 destroy_workqueue(wwan_wq); 540 541 return err; 542} 543 544static void __exit wwan_hwsim_exit(void) 545{ 546 debugfs_remove(wwan_hwsim_debugfs_devcreate); /* Avoid new devs */ 547 wwan_hwsim_free_devs(); 548 flush_workqueue(wwan_wq); /* Wait deletion works completion */ 549 debugfs_remove(wwan_hwsim_debugfs_topdir); 550 class_destroy(wwan_hwsim_class); 551 destroy_workqueue(wwan_wq); 552} 553 554module_init(wwan_hwsim_init); 555module_exit(wwan_hwsim_exit); 556 557MODULE_AUTHOR("Sergey Ryazanov"); 558MODULE_DESCRIPTION("Device simulator for WWAN framework"); 559MODULE_LICENSE("GPL");