mac802154_hwsim.c 21 KB

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