eda.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /*
  2. * WUSB Wire Adapter: WLP interface
  3. * Ethernet to device address cache
  4. *
  5. * Copyright (C) 2005-2006 Intel Corporation
  6. * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License version
  10. * 2 as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20. * 02110-1301, USA.
  21. *
  22. *
  23. * We need to be able to map ethernet addresses to device addresses
  24. * and back because there is not explicit relationship between the eth
  25. * addresses used in the ETH frames and the device addresses (no, it
  26. * would not have been simpler to force as ETH address the MBOA MAC
  27. * address...no, not at all :).
  28. *
  29. * A device has one MBOA MAC address and one device address. It is possible
  30. * for a device to have more than one virtual MAC address (although a
  31. * virtual address can be the same as the MBOA MAC address). The device
  32. * address is guaranteed to be unique among the devices in the extended
  33. * beacon group (see ECMA 17.1.1). We thus use the device address as index
  34. * to this cache. We do allow searching based on virtual address as this
  35. * is how Ethernet frames will be addressed.
  36. *
  37. * We need to support virtual EUI-48. Although, right now the virtual
  38. * EUI-48 will always be the same as the MAC SAP address. The EDA cache
  39. * entry thus contains a MAC SAP address as well as the virtual address
  40. * (used to map the network stack address to a neighbor). When we move
  41. * to support more than one virtual MAC on a host then this organization
  42. * will have to change. Perhaps a neighbor has a list of WSSs, each with a
  43. * tag and virtual EUI-48.
  44. *
  45. * On data transmission
  46. * it is used to determine if the neighbor is connected and what WSS it
  47. * belongs to. With this we know what tag to add to the WLP frame. Storing
  48. * the WSS in the EDA cache may be overkill because we only support one
  49. * WSS. Hopefully we will support more than one WSS at some point.
  50. * On data reception it is used to determine the WSS based on
  51. * the tag and address of the transmitting neighbor.
  52. */
  53. #define D_LOCAL 5
  54. #include <linux/netdevice.h>
  55. #include <linux/uwb/debug.h>
  56. #include <linux/etherdevice.h>
  57. #include <linux/wlp.h>
  58. #include "wlp-internal.h"
  59. /* FIXME: cache is not purged, only on device close */
  60. /* FIXME: does not scale, change to dynamic array */
  61. /*
  62. * Initialize the EDA cache
  63. *
  64. * @returns 0 if ok, < 0 errno code on error
  65. *
  66. * Call when the interface is being brought up
  67. *
  68. * NOTE: Keep it as a separate function as the implementation will
  69. * change and be more complex.
  70. */
  71. void wlp_eda_init(struct wlp_eda *eda)
  72. {
  73. INIT_LIST_HEAD(&eda->cache);
  74. spin_lock_init(&eda->lock);
  75. }
  76. /*
  77. * Release the EDA cache
  78. *
  79. * @returns 0 if ok, < 0 errno code on error
  80. *
  81. * Called when the interface is brought down
  82. */
  83. void wlp_eda_release(struct wlp_eda *eda)
  84. {
  85. unsigned long flags;
  86. struct wlp_eda_node *itr, *next;
  87. spin_lock_irqsave(&eda->lock, flags);
  88. list_for_each_entry_safe(itr, next, &eda->cache, list_node) {
  89. list_del(&itr->list_node);
  90. kfree(itr);
  91. }
  92. spin_unlock_irqrestore(&eda->lock, flags);
  93. }
  94. /*
  95. * Add an address mapping
  96. *
  97. * @returns 0 if ok, < 0 errno code on error
  98. *
  99. * An address mapping is initially created when the neighbor device is seen
  100. * for the first time (it is "onair"). At this time the neighbor is not
  101. * connected or associated with a WSS so we only populate the Ethernet and
  102. * Device address fields.
  103. *
  104. */
  105. int wlp_eda_create_node(struct wlp_eda *eda,
  106. const unsigned char eth_addr[ETH_ALEN],
  107. const struct uwb_dev_addr *dev_addr)
  108. {
  109. int result = 0;
  110. struct wlp_eda_node *itr;
  111. unsigned long flags;
  112. BUG_ON(dev_addr == NULL || eth_addr == NULL);
  113. spin_lock_irqsave(&eda->lock, flags);
  114. list_for_each_entry(itr, &eda->cache, list_node) {
  115. if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
  116. printk(KERN_ERR "EDA cache already contains entry "
  117. "for neighbor %02x:%02x\n",
  118. dev_addr->data[1], dev_addr->data[0]);
  119. result = -EEXIST;
  120. goto out_unlock;
  121. }
  122. }
  123. itr = kzalloc(sizeof(*itr), GFP_ATOMIC);
  124. if (itr != NULL) {
  125. memcpy(itr->eth_addr, eth_addr, sizeof(itr->eth_addr));
  126. itr->dev_addr = *dev_addr;
  127. list_add(&itr->list_node, &eda->cache);
  128. } else
  129. result = -ENOMEM;
  130. out_unlock:
  131. spin_unlock_irqrestore(&eda->lock, flags);
  132. return result;
  133. }
  134. /*
  135. * Remove entry from EDA cache
  136. *
  137. * This is done when the device goes off air.
  138. */
  139. void wlp_eda_rm_node(struct wlp_eda *eda, const struct uwb_dev_addr *dev_addr)
  140. {
  141. struct wlp_eda_node *itr, *next;
  142. unsigned long flags;
  143. spin_lock_irqsave(&eda->lock, flags);
  144. list_for_each_entry_safe(itr, next, &eda->cache, list_node) {
  145. if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
  146. list_del(&itr->list_node);
  147. kfree(itr);
  148. break;
  149. }
  150. }
  151. spin_unlock_irqrestore(&eda->lock, flags);
  152. }
  153. /*
  154. * Update an address mapping
  155. *
  156. * @returns 0 if ok, < 0 errno code on error
  157. */
  158. int wlp_eda_update_node(struct wlp_eda *eda,
  159. const struct uwb_dev_addr *dev_addr,
  160. struct wlp_wss *wss,
  161. const unsigned char virt_addr[ETH_ALEN],
  162. const u8 tag, const enum wlp_wss_connect state)
  163. {
  164. int result = -ENOENT;
  165. struct wlp_eda_node *itr;
  166. unsigned long flags;
  167. spin_lock_irqsave(&eda->lock, flags);
  168. list_for_each_entry(itr, &eda->cache, list_node) {
  169. if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
  170. /* Found it, update it */
  171. itr->wss = wss;
  172. memcpy(itr->virt_addr, virt_addr,
  173. sizeof(itr->virt_addr));
  174. itr->tag = tag;
  175. itr->state = state;
  176. result = 0;
  177. goto out_unlock;
  178. }
  179. }
  180. /* Not found */
  181. out_unlock:
  182. spin_unlock_irqrestore(&eda->lock, flags);
  183. return result;
  184. }
  185. /*
  186. * Update only state field of an address mapping
  187. *
  188. * @returns 0 if ok, < 0 errno code on error
  189. */
  190. int wlp_eda_update_node_state(struct wlp_eda *eda,
  191. const struct uwb_dev_addr *dev_addr,
  192. const enum wlp_wss_connect state)
  193. {
  194. int result = -ENOENT;
  195. struct wlp_eda_node *itr;
  196. unsigned long flags;
  197. spin_lock_irqsave(&eda->lock, flags);
  198. list_for_each_entry(itr, &eda->cache, list_node) {
  199. if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
  200. /* Found it, update it */
  201. itr->state = state;
  202. result = 0;
  203. goto out_unlock;
  204. }
  205. }
  206. /* Not found */
  207. out_unlock:
  208. spin_unlock_irqrestore(&eda->lock, flags);
  209. return result;
  210. }
  211. /*
  212. * Return contents of EDA cache entry
  213. *
  214. * @dev_addr: index to EDA cache
  215. * @eda_entry: pointer to where contents of EDA cache will be copied
  216. */
  217. int wlp_copy_eda_node(struct wlp_eda *eda, struct uwb_dev_addr *dev_addr,
  218. struct wlp_eda_node *eda_entry)
  219. {
  220. int result = -ENOENT;
  221. struct wlp_eda_node *itr;
  222. unsigned long flags;
  223. spin_lock_irqsave(&eda->lock, flags);
  224. list_for_each_entry(itr, &eda->cache, list_node) {
  225. if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
  226. *eda_entry = *itr;
  227. result = 0;
  228. goto out_unlock;
  229. }
  230. }
  231. /* Not found */
  232. out_unlock:
  233. spin_unlock_irqrestore(&eda->lock, flags);
  234. return result;
  235. }
  236. /*
  237. * Execute function for every element in the cache
  238. *
  239. * @function: function to execute on element of cache (must be atomic)
  240. * @priv: private data of function
  241. * @returns: result of first function that failed, or last function
  242. * executed if no function failed.
  243. *
  244. * Stop executing when function returns error for any element in cache.
  245. *
  246. * IMPORTANT: We are using a spinlock here: the function executed on each
  247. * element has to be atomic.
  248. */
  249. int wlp_eda_for_each(struct wlp_eda *eda, wlp_eda_for_each_f function,
  250. void *priv)
  251. {
  252. int result = 0;
  253. struct wlp *wlp = container_of(eda, struct wlp, eda);
  254. struct wlp_eda_node *entry;
  255. unsigned long flags;
  256. spin_lock_irqsave(&eda->lock, flags);
  257. list_for_each_entry(entry, &eda->cache, list_node) {
  258. result = (*function)(wlp, entry, priv);
  259. if (result < 0)
  260. break;
  261. }
  262. spin_unlock_irqrestore(&eda->lock, flags);
  263. return result;
  264. }
  265. /*
  266. * Execute function for single element in the cache (return dev addr)
  267. *
  268. * @virt_addr: index into EDA cache used to determine which element to
  269. * execute the function on
  270. * @dev_addr: device address of element in cache will be returned using
  271. * @dev_addr
  272. * @function: function to execute on element of cache (must be atomic)
  273. * @priv: private data of function
  274. * @returns: result of function
  275. *
  276. * IMPORTANT: We are using a spinlock here: the function executed on the
  277. * element has to be atomic.
  278. */
  279. int wlp_eda_for_virtual(struct wlp_eda *eda,
  280. const unsigned char virt_addr[ETH_ALEN],
  281. struct uwb_dev_addr *dev_addr,
  282. wlp_eda_for_each_f function,
  283. void *priv)
  284. {
  285. int result = 0;
  286. struct wlp *wlp = container_of(eda, struct wlp, eda);
  287. struct device *dev = &wlp->rc->uwb_dev.dev;
  288. struct wlp_eda_node *itr;
  289. unsigned long flags;
  290. int found = 0;
  291. spin_lock_irqsave(&eda->lock, flags);
  292. list_for_each_entry(itr, &eda->cache, list_node) {
  293. if (!memcmp(itr->virt_addr, virt_addr,
  294. sizeof(itr->virt_addr))) {
  295. d_printf(6, dev, "EDA: looking for "
  296. "%02x:%02x:%02x:%02x:%02x:%02x hit %02x:%02x "
  297. "wss %p tag 0x%02x state %u\n",
  298. virt_addr[0], virt_addr[1],
  299. virt_addr[2], virt_addr[3],
  300. virt_addr[4], virt_addr[5],
  301. itr->dev_addr.data[1],
  302. itr->dev_addr.data[0], itr->wss,
  303. itr->tag, itr->state);
  304. result = (*function)(wlp, itr, priv);
  305. *dev_addr = itr->dev_addr;
  306. found = 1;
  307. break;
  308. } else
  309. d_printf(6, dev, "EDA: looking for "
  310. "%02x:%02x:%02x:%02x:%02x:%02x "
  311. "against "
  312. "%02x:%02x:%02x:%02x:%02x:%02x miss\n",
  313. virt_addr[0], virt_addr[1],
  314. virt_addr[2], virt_addr[3],
  315. virt_addr[4], virt_addr[5],
  316. itr->virt_addr[0], itr->virt_addr[1],
  317. itr->virt_addr[2], itr->virt_addr[3],
  318. itr->virt_addr[4], itr->virt_addr[5]);
  319. }
  320. if (!found) {
  321. if (printk_ratelimit())
  322. dev_err(dev, "EDA: Eth addr %02x:%02x:%02x"
  323. ":%02x:%02x:%02x not found.\n",
  324. virt_addr[0], virt_addr[1],
  325. virt_addr[2], virt_addr[3],
  326. virt_addr[4], virt_addr[5]);
  327. result = -ENODEV;
  328. }
  329. spin_unlock_irqrestore(&eda->lock, flags);
  330. return result;
  331. }
  332. static const char *__wlp_wss_connect_state[] = { "WLP_WSS_UNCONNECTED",
  333. "WLP_WSS_CONNECTED",
  334. "WLP_WSS_CONNECT_FAILED",
  335. };
  336. static const char *wlp_wss_connect_state_str(unsigned id)
  337. {
  338. if (id >= ARRAY_SIZE(__wlp_wss_connect_state))
  339. return "unknown WSS connection state";
  340. return __wlp_wss_connect_state[id];
  341. }
  342. /*
  343. * View EDA cache from user space
  344. *
  345. * A debugging feature to give user visibility into the EDA cache. Also
  346. * used to display members of WSS to user (called from wlp_wss_members_show())
  347. */
  348. ssize_t wlp_eda_show(struct wlp *wlp, char *buf)
  349. {
  350. ssize_t result = 0;
  351. struct wlp_eda_node *entry;
  352. unsigned long flags;
  353. struct wlp_eda *eda = &wlp->eda;
  354. spin_lock_irqsave(&eda->lock, flags);
  355. result = scnprintf(buf, PAGE_SIZE, "#eth_addr dev_addr wss_ptr "
  356. "tag state virt_addr\n");
  357. list_for_each_entry(entry, &eda->cache, list_node) {
  358. result += scnprintf(buf + result, PAGE_SIZE - result,
  359. "%02x:%02x:%02x:%02x:%02x:%02x %02x:%02x "
  360. "%p 0x%02x %s "
  361. "%02x:%02x:%02x:%02x:%02x:%02x\n",
  362. entry->eth_addr[0], entry->eth_addr[1],
  363. entry->eth_addr[2], entry->eth_addr[3],
  364. entry->eth_addr[4], entry->eth_addr[5],
  365. entry->dev_addr.data[1],
  366. entry->dev_addr.data[0], entry->wss,
  367. entry->tag,
  368. wlp_wss_connect_state_str(entry->state),
  369. entry->virt_addr[0], entry->virt_addr[1],
  370. entry->virt_addr[2], entry->virt_addr[3],
  371. entry->virt_addr[4], entry->virt_addr[5]);
  372. if (result >= PAGE_SIZE)
  373. break;
  374. }
  375. spin_unlock_irqrestore(&eda->lock, flags);
  376. return result;
  377. }
  378. EXPORT_SYMBOL_GPL(wlp_eda_show);
  379. /*
  380. * Add new EDA cache entry based on user input in sysfs
  381. *
  382. * Should only be used for debugging.
  383. *
  384. * The WSS is assumed to be the only WSS supported. This needs to be
  385. * redesigned when we support more than one WSS.
  386. */
  387. ssize_t wlp_eda_store(struct wlp *wlp, const char *buf, size_t size)
  388. {
  389. ssize_t result;
  390. struct wlp_eda *eda = &wlp->eda;
  391. u8 eth_addr[6];
  392. struct uwb_dev_addr dev_addr;
  393. u8 tag;
  394. unsigned state;
  395. result = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx "
  396. "%02hhx:%02hhx %02hhx %u\n",
  397. &eth_addr[0], &eth_addr[1],
  398. &eth_addr[2], &eth_addr[3],
  399. &eth_addr[4], &eth_addr[5],
  400. &dev_addr.data[1], &dev_addr.data[0], &tag, &state);
  401. switch (result) {
  402. case 6: /* no dev addr specified -- remove entry NOT IMPLEMENTED */
  403. /*result = wlp_eda_rm(eda, eth_addr, &dev_addr);*/
  404. result = -ENOSYS;
  405. break;
  406. case 10:
  407. state = state >= 1 ? 1 : 0;
  408. result = wlp_eda_create_node(eda, eth_addr, &dev_addr);
  409. if (result < 0 && result != -EEXIST)
  410. goto error;
  411. /* Set virtual addr to be same as MAC */
  412. result = wlp_eda_update_node(eda, &dev_addr, &wlp->wss,
  413. eth_addr, tag, state);
  414. if (result < 0)
  415. goto error;
  416. break;
  417. default: /* bad format */
  418. result = -EINVAL;
  419. }
  420. error:
  421. return result < 0 ? result : size;
  422. }
  423. EXPORT_SYMBOL_GPL(wlp_eda_store);