mac802154_hwsim.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
  1. /*
  2. * HWSIM IEEE 802.15.4 interface
  3. *
  4. * (C) 2018 Mojatau, Alexander Aring <aring@mojatau.com>
  5. * Copyright 2007-2012 Siemens AG
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2
  9. * as published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * Based on fakelb, original Written by:
  17. * Sergey Lapin <slapin@ossfans.org>
  18. * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
  19. * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
  20. */
  21. #include <linux/module.h>
  22. #include <linux/timer.h>
  23. #include <linux/platform_device.h>
  24. #include <linux/rtnetlink.h>
  25. #include <linux/netdevice.h>
  26. #include <linux/device.h>
  27. #include <linux/spinlock.h>
  28. #include <net/mac802154.h>
  29. #include <net/cfg802154.h>
  30. #include <net/genetlink.h>
  31. #include "mac802154_hwsim.h"
  32. MODULE_DESCRIPTION("Software simulator of IEEE 802.15.4 radio(s) for mac802154");
  33. MODULE_LICENSE("GPL");
  34. static LIST_HEAD(hwsim_phys);
  35. static DEFINE_MUTEX(hwsim_phys_lock);
  36. static LIST_HEAD(hwsim_ifup_phys);
  37. static struct platform_device *mac802154hwsim_dev;
  38. /* MAC802154_HWSIM netlink family */
  39. static struct genl_family hwsim_genl_family;
  40. static int hwsim_radio_idx;
  41. enum hwsim_multicast_groups {
  42. HWSIM_MCGRP_CONFIG,
  43. };
  44. static const struct genl_multicast_group hwsim_mcgrps[] = {
  45. [HWSIM_MCGRP_CONFIG] = { .name = "config", },
  46. };
  47. struct hwsim_pib {
  48. u8 page;
  49. u8 channel;
  50. struct rcu_head rcu;
  51. };
  52. struct hwsim_edge_info {
  53. u8 lqi;
  54. struct rcu_head rcu;
  55. };
  56. struct hwsim_edge {
  57. struct hwsim_phy *endpoint;
  58. struct hwsim_edge_info __rcu *info;
  59. struct list_head list;
  60. struct rcu_head rcu;
  61. };
  62. struct hwsim_phy {
  63. struct ieee802154_hw *hw;
  64. u32 idx;
  65. struct hwsim_pib __rcu *pib;
  66. bool suspended;
  67. struct list_head edges;
  68. struct list_head list;
  69. struct list_head list_ifup;
  70. };
  71. static int hwsim_add_one(struct genl_info *info, struct device *dev,
  72. bool init);
  73. static void hwsim_del(struct hwsim_phy *phy);
  74. static int hwsim_hw_ed(struct ieee802154_hw *hw, u8 *level)
  75. {
  76. *level = 0xbe;
  77. return 0;
  78. }
  79. static int hwsim_hw_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
  80. {
  81. struct hwsim_phy *phy = hw->priv;
  82. struct hwsim_pib *pib, *pib_old;
  83. pib = kzalloc(sizeof(*pib), GFP_KERNEL);
  84. if (!pib)
  85. return -ENOMEM;
  86. pib->page = page;
  87. pib->channel = channel;
  88. pib_old = rtnl_dereference(phy->pib);
  89. rcu_assign_pointer(phy->pib, pib);
  90. kfree_rcu(pib_old, rcu);
  91. return 0;
  92. }
  93. static int hwsim_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
  94. {
  95. struct hwsim_phy *current_phy = hw->priv;
  96. struct hwsim_pib *current_pib, *endpoint_pib;
  97. struct hwsim_edge_info *einfo;
  98. struct hwsim_edge *e;
  99. WARN_ON(current_phy->suspended);
  100. rcu_read_lock();
  101. current_pib = rcu_dereference(current_phy->pib);
  102. list_for_each_entry_rcu(e, &current_phy->edges, list) {
  103. /* Can be changed later in rx_irqsafe, but this is only a
  104. * performance tweak. Received radio should drop the frame
  105. * in mac802154 stack anyway... so we don't need to be
  106. * 100% of locking here to check on suspended
  107. */
  108. if (e->endpoint->suspended)
  109. continue;
  110. endpoint_pib = rcu_dereference(e->endpoint->pib);
  111. if (current_pib->page == endpoint_pib->page &&
  112. current_pib->channel == endpoint_pib->channel) {
  113. struct sk_buff *newskb = pskb_copy(skb, GFP_ATOMIC);
  114. einfo = rcu_dereference(e->info);
  115. if (newskb)
  116. ieee802154_rx_irqsafe(e->endpoint->hw, newskb,
  117. einfo->lqi);
  118. }
  119. }
  120. rcu_read_unlock();
  121. ieee802154_xmit_complete(hw, skb, false);
  122. return 0;
  123. }
  124. static int hwsim_hw_start(struct ieee802154_hw *hw)
  125. {
  126. struct hwsim_phy *phy = hw->priv;
  127. phy->suspended = false;
  128. list_add_rcu(&phy->list_ifup, &hwsim_ifup_phys);
  129. synchronize_rcu();
  130. return 0;
  131. }
  132. static void hwsim_hw_stop(struct ieee802154_hw *hw)
  133. {
  134. struct hwsim_phy *phy = hw->priv;
  135. phy->suspended = true;
  136. list_del_rcu(&phy->list_ifup);
  137. synchronize_rcu();
  138. }
  139. static int
  140. hwsim_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on)
  141. {
  142. return 0;
  143. }
  144. static const struct ieee802154_ops hwsim_ops = {
  145. .owner = THIS_MODULE,
  146. .xmit_async = hwsim_hw_xmit,
  147. .ed = hwsim_hw_ed,
  148. .set_channel = hwsim_hw_channel,
  149. .start = hwsim_hw_start,
  150. .stop = hwsim_hw_stop,
  151. .set_promiscuous_mode = hwsim_set_promiscuous_mode,
  152. };
  153. static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
  154. {
  155. return hwsim_add_one(info, &mac802154hwsim_dev->dev, false);
  156. }
  157. static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info)
  158. {
  159. struct hwsim_phy *phy, *tmp;
  160. s64 idx = -1;
  161. if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID])
  162. return -EINVAL;
  163. idx = nla_get_u32(info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID]);
  164. mutex_lock(&hwsim_phys_lock);
  165. list_for_each_entry_safe(phy, tmp, &hwsim_phys, list) {
  166. if (idx == phy->idx) {
  167. hwsim_del(phy);
  168. mutex_unlock(&hwsim_phys_lock);
  169. return 0;
  170. }
  171. }
  172. mutex_unlock(&hwsim_phys_lock);
  173. return -ENODEV;
  174. }
  175. static int append_radio_msg(struct sk_buff *skb, struct hwsim_phy *phy)
  176. {
  177. struct nlattr *nl_edges, *nl_edge;
  178. struct hwsim_edge_info *einfo;
  179. struct hwsim_edge *e;
  180. int ret;
  181. ret = nla_put_u32(skb, MAC802154_HWSIM_ATTR_RADIO_ID, phy->idx);
  182. if (ret < 0)
  183. return ret;
  184. rcu_read_lock();
  185. if (list_empty(&phy->edges)) {
  186. rcu_read_unlock();
  187. return 0;
  188. }
  189. nl_edges = nla_nest_start(skb, MAC802154_HWSIM_ATTR_RADIO_EDGES);
  190. if (!nl_edges) {
  191. rcu_read_unlock();
  192. return -ENOBUFS;
  193. }
  194. list_for_each_entry_rcu(e, &phy->edges, list) {
  195. nl_edge = nla_nest_start(skb, MAC802154_HWSIM_ATTR_RADIO_EDGE);
  196. if (!nl_edge) {
  197. rcu_read_unlock();
  198. nla_nest_cancel(skb, nl_edges);
  199. return -ENOBUFS;
  200. }
  201. ret = nla_put_u32(skb, MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID,
  202. e->endpoint->idx);
  203. if (ret < 0) {
  204. rcu_read_unlock();
  205. nla_nest_cancel(skb, nl_edge);
  206. nla_nest_cancel(skb, nl_edges);
  207. return ret;
  208. }
  209. einfo = rcu_dereference(e->info);
  210. ret = nla_put_u8(skb, MAC802154_HWSIM_EDGE_ATTR_LQI,
  211. einfo->lqi);
  212. if (ret < 0) {
  213. rcu_read_unlock();
  214. nla_nest_cancel(skb, nl_edge);
  215. nla_nest_cancel(skb, nl_edges);
  216. return ret;
  217. }
  218. nla_nest_end(skb, nl_edge);
  219. }
  220. rcu_read_unlock();
  221. nla_nest_end(skb, nl_edges);
  222. return 0;
  223. }
  224. static int hwsim_get_radio(struct sk_buff *skb, struct hwsim_phy *phy,
  225. u32 portid, u32 seq,
  226. struct netlink_callback *cb, int flags)
  227. {
  228. void *hdr;
  229. int res = -EMSGSIZE;
  230. hdr = genlmsg_put(skb, portid, seq, &hwsim_genl_family, flags,
  231. MAC802154_HWSIM_CMD_GET_RADIO);
  232. if (!hdr)
  233. return -EMSGSIZE;
  234. if (cb)
  235. genl_dump_check_consistent(cb, hdr);
  236. res = append_radio_msg(skb, phy);
  237. if (res < 0)
  238. goto out_err;
  239. genlmsg_end(skb, hdr);
  240. return 0;
  241. out_err:
  242. genlmsg_cancel(skb, hdr);
  243. return res;
  244. }
  245. static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info)
  246. {
  247. struct hwsim_phy *phy;
  248. struct sk_buff *skb;
  249. int idx, res = -ENODEV;
  250. if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID])
  251. return -EINVAL;
  252. idx = nla_get_u32(info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID]);
  253. mutex_lock(&hwsim_phys_lock);
  254. list_for_each_entry(phy, &hwsim_phys, list) {
  255. if (phy->idx != idx)
  256. continue;
  257. skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
  258. if (!skb) {
  259. res = -ENOMEM;
  260. goto out_err;
  261. }
  262. res = hwsim_get_radio(skb, phy, info->snd_portid,
  263. info->snd_seq, NULL, 0);
  264. if (res < 0) {
  265. nlmsg_free(skb);
  266. goto out_err;
  267. }
  268. genlmsg_reply(skb, info);
  269. break;
  270. }
  271. out_err:
  272. mutex_unlock(&hwsim_phys_lock);
  273. return res;
  274. }
  275. static int hwsim_dump_radio_nl(struct sk_buff *skb,
  276. struct netlink_callback *cb)
  277. {
  278. int idx = cb->args[0];
  279. struct hwsim_phy *phy;
  280. int res;
  281. mutex_lock(&hwsim_phys_lock);
  282. if (idx == hwsim_radio_idx)
  283. goto done;
  284. list_for_each_entry(phy, &hwsim_phys, list) {
  285. if (phy->idx < idx)
  286. continue;
  287. res = hwsim_get_radio(skb, phy, NETLINK_CB(cb->skb).portid,
  288. cb->nlh->nlmsg_seq, cb, NLM_F_MULTI);
  289. if (res < 0)
  290. break;
  291. idx = phy->idx + 1;
  292. }
  293. cb->args[0] = idx;
  294. done:
  295. mutex_unlock(&hwsim_phys_lock);
  296. return skb->len;
  297. }
  298. /* caller need to held hwsim_phys_lock */
  299. static struct hwsim_phy *hwsim_get_radio_by_id(uint32_t idx)
  300. {
  301. struct hwsim_phy *phy;
  302. list_for_each_entry(phy, &hwsim_phys, list) {
  303. if (phy->idx == idx)
  304. return phy;
  305. }
  306. return NULL;
  307. }
  308. static const struct nla_policy hwsim_edge_policy[MAC802154_HWSIM_EDGE_ATTR_MAX + 1] = {
  309. [MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID] = { .type = NLA_U32 },
  310. [MAC802154_HWSIM_EDGE_ATTR_LQI] = { .type = NLA_U8 },
  311. };
  312. static struct hwsim_edge *hwsim_alloc_edge(struct hwsim_phy *endpoint, u8 lqi)
  313. {
  314. struct hwsim_edge_info *einfo;
  315. struct hwsim_edge *e;
  316. e = kzalloc(sizeof(*e), GFP_KERNEL);
  317. if (!e)
  318. return NULL;
  319. einfo = kzalloc(sizeof(*einfo), GFP_KERNEL);
  320. if (!einfo) {
  321. kfree(e);
  322. return NULL;
  323. }
  324. einfo->lqi = 0xff;
  325. rcu_assign_pointer(e->info, einfo);
  326. e->endpoint = endpoint;
  327. return e;
  328. }
  329. static void hwsim_free_edge(struct hwsim_edge *e)
  330. {
  331. struct hwsim_edge_info *einfo;
  332. rcu_read_lock();
  333. einfo = rcu_dereference(e->info);
  334. rcu_read_unlock();
  335. kfree_rcu(einfo, rcu);
  336. kfree_rcu(e, rcu);
  337. }
  338. static int hwsim_new_edge_nl(struct sk_buff *msg, struct genl_info *info)
  339. {
  340. struct nlattr *edge_attrs[MAC802154_HWSIM_EDGE_ATTR_MAX + 1];
  341. struct hwsim_phy *phy_v0, *phy_v1;
  342. struct hwsim_edge *e;
  343. u32 v0, v1;
  344. if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] &&
  345. !info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE])
  346. return -EINVAL;
  347. if (nla_parse_nested(edge_attrs, MAC802154_HWSIM_EDGE_ATTR_MAX,
  348. info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE],
  349. hwsim_edge_policy, NULL))
  350. return -EINVAL;
  351. if (!edge_attrs[MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID])
  352. return -EINVAL;
  353. v0 = nla_get_u32(info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID]);
  354. v1 = nla_get_u32(edge_attrs[MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID]);
  355. if (v0 == v1)
  356. return -EINVAL;
  357. mutex_lock(&hwsim_phys_lock);
  358. phy_v0 = hwsim_get_radio_by_id(v0);
  359. if (!phy_v0) {
  360. mutex_unlock(&hwsim_phys_lock);
  361. return -ENOENT;
  362. }
  363. phy_v1 = hwsim_get_radio_by_id(v1);
  364. if (!phy_v1) {
  365. mutex_unlock(&hwsim_phys_lock);
  366. return -ENOENT;
  367. }
  368. rcu_read_lock();
  369. list_for_each_entry_rcu(e, &phy_v0->edges, list) {
  370. if (e->endpoint->idx == v1) {
  371. mutex_unlock(&hwsim_phys_lock);
  372. rcu_read_unlock();
  373. return -EEXIST;
  374. }
  375. }
  376. rcu_read_unlock();
  377. e = hwsim_alloc_edge(phy_v1, 0xff);
  378. if (!e) {
  379. mutex_unlock(&hwsim_phys_lock);
  380. return -ENOMEM;
  381. }
  382. list_add_rcu(&e->list, &phy_v0->edges);
  383. /* wait until changes are done under hwsim_phys_lock lock
  384. * should prevent of calling this function twice while
  385. * edges list has not the changes yet.
  386. */
  387. synchronize_rcu();
  388. mutex_unlock(&hwsim_phys_lock);
  389. return 0;
  390. }
  391. static int hwsim_del_edge_nl(struct sk_buff *msg, struct genl_info *info)
  392. {
  393. struct nlattr *edge_attrs[MAC802154_HWSIM_EDGE_ATTR_MAX + 1];
  394. struct hwsim_phy *phy_v0;
  395. struct hwsim_edge *e;
  396. u32 v0, v1;
  397. if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] &&
  398. !info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE])
  399. return -EINVAL;
  400. if (nla_parse_nested(edge_attrs, MAC802154_HWSIM_EDGE_ATTR_MAX + 1,
  401. info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE],
  402. hwsim_edge_policy, NULL))
  403. return -EINVAL;
  404. if (!edge_attrs[MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID])
  405. return -EINVAL;
  406. v0 = nla_get_u32(info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID]);
  407. v1 = nla_get_u32(edge_attrs[MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID]);
  408. mutex_lock(&hwsim_phys_lock);
  409. phy_v0 = hwsim_get_radio_by_id(v0);
  410. if (!phy_v0) {
  411. mutex_unlock(&hwsim_phys_lock);
  412. return -ENOENT;
  413. }
  414. rcu_read_lock();
  415. list_for_each_entry_rcu(e, &phy_v0->edges, list) {
  416. if (e->endpoint->idx == v1) {
  417. rcu_read_unlock();
  418. list_del_rcu(&e->list);
  419. hwsim_free_edge(e);
  420. /* same again - wait until list changes are done */
  421. synchronize_rcu();
  422. mutex_unlock(&hwsim_phys_lock);
  423. return 0;
  424. }
  425. }
  426. rcu_read_unlock();
  427. mutex_unlock(&hwsim_phys_lock);
  428. return -ENOENT;
  429. }
  430. static int hwsim_set_edge_lqi(struct sk_buff *msg, struct genl_info *info)
  431. {
  432. struct nlattr *edge_attrs[MAC802154_HWSIM_EDGE_ATTR_MAX + 1];
  433. struct hwsim_edge_info *einfo;
  434. struct hwsim_phy *phy_v0;
  435. struct hwsim_edge *e;
  436. u32 v0, v1;
  437. u8 lqi;
  438. if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] &&
  439. !info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE])
  440. return -EINVAL;
  441. if (nla_parse_nested(edge_attrs, MAC802154_HWSIM_EDGE_ATTR_MAX + 1,
  442. info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE],
  443. hwsim_edge_policy, NULL))
  444. return -EINVAL;
  445. if (!edge_attrs[MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID] &&
  446. !edge_attrs[MAC802154_HWSIM_EDGE_ATTR_LQI])
  447. return -EINVAL;
  448. v0 = nla_get_u32(info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID]);
  449. v1 = nla_get_u32(edge_attrs[MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID]);
  450. lqi = nla_get_u8(edge_attrs[MAC802154_HWSIM_EDGE_ATTR_LQI]);
  451. mutex_lock(&hwsim_phys_lock);
  452. phy_v0 = hwsim_get_radio_by_id(v0);
  453. if (!phy_v0) {
  454. mutex_unlock(&hwsim_phys_lock);
  455. return -ENOENT;
  456. }
  457. einfo = kzalloc(sizeof(*einfo), GFP_KERNEL);
  458. if (!einfo) {
  459. mutex_unlock(&hwsim_phys_lock);
  460. return -ENOMEM;
  461. }
  462. rcu_read_lock();
  463. list_for_each_entry_rcu(e, &phy_v0->edges, list) {
  464. if (e->endpoint->idx == v1) {
  465. einfo->lqi = lqi;
  466. rcu_assign_pointer(e->info, einfo);
  467. rcu_read_unlock();
  468. mutex_unlock(&hwsim_phys_lock);
  469. return 0;
  470. }
  471. }
  472. rcu_read_unlock();
  473. kfree(einfo);
  474. mutex_unlock(&hwsim_phys_lock);
  475. return -ENOENT;
  476. }
  477. /* MAC802154_HWSIM netlink policy */
  478. static const struct nla_policy hwsim_genl_policy[MAC802154_HWSIM_ATTR_MAX + 1] = {
  479. [MAC802154_HWSIM_ATTR_RADIO_ID] = { .type = NLA_U32 },
  480. [MAC802154_HWSIM_ATTR_RADIO_EDGE] = { .type = NLA_NESTED },
  481. [MAC802154_HWSIM_ATTR_RADIO_EDGES] = { .type = NLA_NESTED },
  482. };
  483. /* Generic Netlink operations array */
  484. static const struct genl_ops hwsim_nl_ops[] = {
  485. {
  486. .cmd = MAC802154_HWSIM_CMD_NEW_RADIO,
  487. .policy = hwsim_genl_policy,
  488. .doit = hwsim_new_radio_nl,
  489. .flags = GENL_UNS_ADMIN_PERM,
  490. },
  491. {
  492. .cmd = MAC802154_HWSIM_CMD_DEL_RADIO,
  493. .policy = hwsim_genl_policy,
  494. .doit = hwsim_del_radio_nl,
  495. .flags = GENL_UNS_ADMIN_PERM,
  496. },
  497. {
  498. .cmd = MAC802154_HWSIM_CMD_GET_RADIO,
  499. .policy = hwsim_genl_policy,
  500. .doit = hwsim_get_radio_nl,
  501. .dumpit = hwsim_dump_radio_nl,
  502. },
  503. {
  504. .cmd = MAC802154_HWSIM_CMD_NEW_EDGE,
  505. .policy = hwsim_genl_policy,
  506. .doit = hwsim_new_edge_nl,
  507. .flags = GENL_UNS_ADMIN_PERM,
  508. },
  509. {
  510. .cmd = MAC802154_HWSIM_CMD_DEL_EDGE,
  511. .policy = hwsim_genl_policy,
  512. .doit = hwsim_del_edge_nl,
  513. .flags = GENL_UNS_ADMIN_PERM,
  514. },
  515. {
  516. .cmd = MAC802154_HWSIM_CMD_SET_EDGE,
  517. .policy = hwsim_genl_policy,
  518. .doit = hwsim_set_edge_lqi,
  519. .flags = GENL_UNS_ADMIN_PERM,
  520. },
  521. };
  522. static struct genl_family hwsim_genl_family __ro_after_init = {
  523. .name = "MAC802154_HWSIM",
  524. .version = 1,
  525. .maxattr = MAC802154_HWSIM_ATTR_MAX,
  526. .module = THIS_MODULE,
  527. .ops = hwsim_nl_ops,
  528. .n_ops = ARRAY_SIZE(hwsim_nl_ops),
  529. .mcgrps = hwsim_mcgrps,
  530. .n_mcgrps = ARRAY_SIZE(hwsim_mcgrps),
  531. };
  532. static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb,
  533. struct genl_info *info)
  534. {
  535. if (info)
  536. genl_notify(&hwsim_genl_family, mcast_skb, info,
  537. HWSIM_MCGRP_CONFIG, GFP_KERNEL);
  538. else
  539. genlmsg_multicast(&hwsim_genl_family, mcast_skb, 0,
  540. HWSIM_MCGRP_CONFIG, GFP_KERNEL);
  541. }
  542. static void hwsim_mcast_new_radio(struct genl_info *info, struct hwsim_phy *phy)
  543. {
  544. struct sk_buff *mcast_skb;
  545. void *data;
  546. mcast_skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
  547. if (!mcast_skb)
  548. return;
  549. data = genlmsg_put(mcast_skb, 0, 0, &hwsim_genl_family, 0,
  550. MAC802154_HWSIM_CMD_NEW_RADIO);
  551. if (!data)
  552. goto out_err;
  553. if (append_radio_msg(mcast_skb, phy) < 0)
  554. goto out_err;
  555. genlmsg_end(mcast_skb, data);
  556. hwsim_mcast_config_msg(mcast_skb, info);
  557. return;
  558. out_err:
  559. genlmsg_cancel(mcast_skb, data);
  560. nlmsg_free(mcast_skb);
  561. }
  562. static void hwsim_edge_unsubscribe_me(struct hwsim_phy *phy)
  563. {
  564. struct hwsim_phy *tmp;
  565. struct hwsim_edge *e;
  566. rcu_read_lock();
  567. /* going to all phy edges and remove phy from it */
  568. list_for_each_entry(tmp, &hwsim_phys, list) {
  569. list_for_each_entry_rcu(e, &tmp->edges, list) {
  570. if (e->endpoint->idx == phy->idx) {
  571. list_del_rcu(&e->list);
  572. hwsim_free_edge(e);
  573. }
  574. }
  575. }
  576. rcu_read_unlock();
  577. synchronize_rcu();
  578. }
  579. static int hwsim_subscribe_all_others(struct hwsim_phy *phy)
  580. {
  581. struct hwsim_phy *sub;
  582. struct hwsim_edge *e;
  583. list_for_each_entry(sub, &hwsim_phys, list) {
  584. e = hwsim_alloc_edge(sub, 0xff);
  585. if (!e)
  586. goto me_fail;
  587. list_add_rcu(&e->list, &phy->edges);
  588. }
  589. list_for_each_entry(sub, &hwsim_phys, list) {
  590. e = hwsim_alloc_edge(phy, 0xff);
  591. if (!e)
  592. goto sub_fail;
  593. list_add_rcu(&e->list, &sub->edges);
  594. }
  595. return 0;
  596. me_fail:
  597. rcu_read_lock();
  598. list_for_each_entry_rcu(e, &phy->edges, list) {
  599. list_del_rcu(&e->list);
  600. hwsim_free_edge(e);
  601. }
  602. rcu_read_unlock();
  603. sub_fail:
  604. hwsim_edge_unsubscribe_me(phy);
  605. return -ENOMEM;
  606. }
  607. static int hwsim_add_one(struct genl_info *info, struct device *dev,
  608. bool init)
  609. {
  610. struct ieee802154_hw *hw;
  611. struct hwsim_phy *phy;
  612. struct hwsim_pib *pib;
  613. int idx;
  614. int err;
  615. idx = hwsim_radio_idx++;
  616. hw = ieee802154_alloc_hw(sizeof(*phy), &hwsim_ops);
  617. if (!hw)
  618. return -ENOMEM;
  619. phy = hw->priv;
  620. phy->hw = hw;
  621. /* 868 MHz BPSK 802.15.4-2003 */
  622. hw->phy->supported.channels[0] |= 1;
  623. /* 915 MHz BPSK 802.15.4-2003 */
  624. hw->phy->supported.channels[0] |= 0x7fe;
  625. /* 2.4 GHz O-QPSK 802.15.4-2003 */
  626. hw->phy->supported.channels[0] |= 0x7FFF800;
  627. /* 868 MHz ASK 802.15.4-2006 */
  628. hw->phy->supported.channels[1] |= 1;
  629. /* 915 MHz ASK 802.15.4-2006 */
  630. hw->phy->supported.channels[1] |= 0x7fe;
  631. /* 868 MHz O-QPSK 802.15.4-2006 */
  632. hw->phy->supported.channels[2] |= 1;
  633. /* 915 MHz O-QPSK 802.15.4-2006 */
  634. hw->phy->supported.channels[2] |= 0x7fe;
  635. /* 2.4 GHz CSS 802.15.4a-2007 */
  636. hw->phy->supported.channels[3] |= 0x3fff;
  637. /* UWB Sub-gigahertz 802.15.4a-2007 */
  638. hw->phy->supported.channels[4] |= 1;
  639. /* UWB Low band 802.15.4a-2007 */
  640. hw->phy->supported.channels[4] |= 0x1e;
  641. /* UWB High band 802.15.4a-2007 */
  642. hw->phy->supported.channels[4] |= 0xffe0;
  643. /* 750 MHz O-QPSK 802.15.4c-2009 */
  644. hw->phy->supported.channels[5] |= 0xf;
  645. /* 750 MHz MPSK 802.15.4c-2009 */
  646. hw->phy->supported.channels[5] |= 0xf0;
  647. /* 950 MHz BPSK 802.15.4d-2009 */
  648. hw->phy->supported.channels[6] |= 0x3ff;
  649. /* 950 MHz GFSK 802.15.4d-2009 */
  650. hw->phy->supported.channels[6] |= 0x3ffc00;
  651. ieee802154_random_extended_addr(&hw->phy->perm_extended_addr);
  652. /* hwsim phy channel 13 as default */
  653. hw->phy->current_channel = 13;
  654. pib = kzalloc(sizeof(*pib), GFP_KERNEL);
  655. if (!pib) {
  656. err = -ENOMEM;
  657. goto err_pib;
  658. }
  659. rcu_assign_pointer(phy->pib, pib);
  660. phy->idx = idx;
  661. INIT_LIST_HEAD(&phy->edges);
  662. hw->flags = IEEE802154_HW_PROMISCUOUS;
  663. hw->parent = dev;
  664. err = ieee802154_register_hw(hw);
  665. if (err)
  666. goto err_reg;
  667. mutex_lock(&hwsim_phys_lock);
  668. if (init) {
  669. err = hwsim_subscribe_all_others(phy);
  670. if (err < 0) {
  671. mutex_unlock(&hwsim_phys_lock);
  672. goto err_reg;
  673. }
  674. }
  675. list_add_tail(&phy->list, &hwsim_phys);
  676. mutex_unlock(&hwsim_phys_lock);
  677. hwsim_mcast_new_radio(info, phy);
  678. return idx;
  679. err_reg:
  680. kfree(pib);
  681. err_pib:
  682. ieee802154_free_hw(phy->hw);
  683. return err;
  684. }
  685. static void hwsim_del(struct hwsim_phy *phy)
  686. {
  687. struct hwsim_pib *pib;
  688. hwsim_edge_unsubscribe_me(phy);
  689. list_del(&phy->list);
  690. rcu_read_lock();
  691. pib = rcu_dereference(phy->pib);
  692. rcu_read_unlock();
  693. kfree_rcu(pib, rcu);
  694. ieee802154_unregister_hw(phy->hw);
  695. ieee802154_free_hw(phy->hw);
  696. }
  697. static int hwsim_probe(struct platform_device *pdev)
  698. {
  699. struct hwsim_phy *phy, *tmp;
  700. int err, i;
  701. for (i = 0; i < 2; i++) {
  702. err = hwsim_add_one(NULL, &pdev->dev, true);
  703. if (err < 0)
  704. goto err_slave;
  705. }
  706. dev_info(&pdev->dev, "Added 2 mac802154 hwsim hardware radios\n");
  707. return 0;
  708. err_slave:
  709. mutex_lock(&hwsim_phys_lock);
  710. list_for_each_entry_safe(phy, tmp, &hwsim_phys, list)
  711. hwsim_del(phy);
  712. mutex_unlock(&hwsim_phys_lock);
  713. return err;
  714. }
  715. static int hwsim_remove(struct platform_device *pdev)
  716. {
  717. struct hwsim_phy *phy, *tmp;
  718. mutex_lock(&hwsim_phys_lock);
  719. list_for_each_entry_safe(phy, tmp, &hwsim_phys, list)
  720. hwsim_del(phy);
  721. mutex_unlock(&hwsim_phys_lock);
  722. return 0;
  723. }
  724. static struct platform_driver mac802154hwsim_driver = {
  725. .probe = hwsim_probe,
  726. .remove = hwsim_remove,
  727. .driver = {
  728. .name = "mac802154_hwsim",
  729. },
  730. };
  731. static __init int hwsim_init_module(void)
  732. {
  733. int rc;
  734. rc = genl_register_family(&hwsim_genl_family);
  735. if (rc)
  736. return rc;
  737. mac802154hwsim_dev = platform_device_register_simple("mac802154_hwsim",
  738. -1, NULL, 0);
  739. if (IS_ERR(mac802154hwsim_dev)) {
  740. rc = PTR_ERR(mac802154hwsim_dev);
  741. goto platform_dev;
  742. }
  743. rc = platform_driver_register(&mac802154hwsim_driver);
  744. if (rc < 0)
  745. goto platform_drv;
  746. return 0;
  747. platform_drv:
  748. genl_unregister_family(&hwsim_genl_family);
  749. platform_dev:
  750. platform_device_unregister(mac802154hwsim_dev);
  751. return rc;
  752. }
  753. static __exit void hwsim_remove_module(void)
  754. {
  755. genl_unregister_family(&hwsim_genl_family);
  756. platform_driver_unregister(&mac802154hwsim_driver);
  757. platform_device_unregister(mac802154hwsim_dev);
  758. }
  759. module_init(hwsim_init_module);
  760. module_exit(hwsim_remove_module);