eda.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  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. #include <linux/netdevice.h>
  54. #include <linux/etherdevice.h>
  55. #include <linux/slab.h>
  56. #include <linux/wlp.h>
  57. #include "wlp-internal.h"
  58. /* FIXME: cache is not purged, only on device close */
  59. /* FIXME: does not scale, change to dynamic array */
  60. /*
  61. * Initialize the EDA cache
  62. *
  63. * @returns 0 if ok, < 0 errno code on error
  64. *
  65. * Call when the interface is being brought up
  66. *
  67. * NOTE: Keep it as a separate function as the implementation will
  68. * change and be more complex.
  69. */
  70. void wlp_eda_init(struct wlp_eda *eda)
  71. {
  72. INIT_LIST_HEAD(&eda->cache);
  73. spin_lock_init(&eda->lock);
  74. }
  75. /*
  76. * Release the EDA cache
  77. *
  78. * @returns 0 if ok, < 0 errno code on error
  79. *
  80. * Called when the interface is brought down
  81. */
  82. void wlp_eda_release(struct wlp_eda *eda)
  83. {
  84. unsigned long flags;
  85. struct wlp_eda_node *itr, *next;
  86. spin_lock_irqsave(&eda->lock, flags);
  87. list_for_each_entry_safe(itr, next, &eda->cache, list_node) {
  88. list_del(&itr->list_node);
  89. kfree(itr);
  90. }
  91. spin_unlock_irqrestore(&eda->lock, flags);
  92. }
  93. /*
  94. * Add an address mapping
  95. *
  96. * @returns 0 if ok, < 0 errno code on error
  97. *
  98. * An address mapping is initially created when the neighbor device is seen
  99. * for the first time (it is "onair"). At this time the neighbor is not
  100. * connected or associated with a WSS so we only populate the Ethernet and
  101. * Device address fields.
  102. *
  103. */
  104. int wlp_eda_create_node(struct wlp_eda *eda,
  105. const unsigned char eth_addr[ETH_ALEN],
  106. const struct uwb_dev_addr *dev_addr)
  107. {
  108. int result = 0;
  109. struct wlp_eda_node *itr;
  110. unsigned long flags;
  111. BUG_ON(dev_addr == NULL || eth_addr == NULL);
  112. spin_lock_irqsave(&eda->lock, flags);
  113. list_for_each_entry(itr, &eda->cache, list_node) {
  114. if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
  115. printk(KERN_ERR "EDA cache already contains entry "
  116. "for neighbor %02x:%02x\n",
  117. dev_addr->data[1], dev_addr->data[0]);
  118. result = -EEXIST;
  119. goto out_unlock;
  120. }
  121. }
  122. itr = kzalloc(sizeof(*itr), GFP_ATOMIC);
  123. if (itr != NULL) {
  124. memcpy(itr->eth_addr, eth_addr, sizeof(itr->eth_addr));
  125. itr->dev_addr = *dev_addr;
  126. list_add(&itr->list_node, &eda->cache);
  127. } else
  128. result = -ENOMEM;
  129. out_unlock:
  130. spin_unlock_irqrestore(&eda->lock, flags);
  131. return result;
  132. }
  133. /*
  134. * Remove entry from EDA cache
  135. *
  136. * This is done when the device goes off air.
  137. */
  138. void wlp_eda_rm_node(struct wlp_eda *eda, const struct uwb_dev_addr *dev_addr)
  139. {
  140. struct wlp_eda_node *itr, *next;
  141. unsigned long flags;
  142. spin_lock_irqsave(&eda->lock, flags);
  143. list_for_each_entry_safe(itr, next, &eda->cache, list_node) {
  144. if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
  145. list_del(&itr->list_node);
  146. kfree(itr);
  147. break;
  148. }
  149. }
  150. spin_unlock_irqrestore(&eda->lock, flags);
  151. }
  152. /*
  153. * Update an address mapping
  154. *
  155. * @returns 0 if ok, < 0 errno code on error
  156. */
  157. int wlp_eda_update_node(struct wlp_eda *eda,
  158. const struct uwb_dev_addr *dev_addr,
  159. struct wlp_wss *wss,
  160. const unsigned char virt_addr[ETH_ALEN],
  161. const u8 tag, const enum wlp_wss_connect state)
  162. {
  163. int result = -ENOENT;
  164. struct wlp_eda_node *itr;
  165. unsigned long flags;
  166. spin_lock_irqsave(&eda->lock, flags);
  167. list_for_each_entry(itr, &eda->cache, list_node) {
  168. if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
  169. /* Found it, update it */
  170. itr->wss = wss;
  171. memcpy(itr->virt_addr, virt_addr,
  172. sizeof(itr->virt_addr));
  173. itr->tag = tag;
  174. itr->state = state;
  175. result = 0;
  176. goto out_unlock;
  177. }
  178. }
  179. /* Not found */
  180. out_unlock:
  181. spin_unlock_irqrestore(&eda->lock, flags);
  182. return result;
  183. }
  184. /*
  185. * Update only state field of an address mapping
  186. *
  187. * @returns 0 if ok, < 0 errno code on error
  188. */
  189. int wlp_eda_update_node_state(struct wlp_eda *eda,
  190. const struct uwb_dev_addr *dev_addr,
  191. const enum wlp_wss_connect state)
  192. {
  193. int result = -ENOENT;
  194. struct wlp_eda_node *itr;
  195. unsigned long flags;
  196. spin_lock_irqsave(&eda->lock, flags);
  197. list_for_each_entry(itr, &eda->cache, list_node) {
  198. if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
  199. /* Found it, update it */
  200. itr->state = state;
  201. result = 0;
  202. goto out_unlock;
  203. }
  204. }
  205. /* Not found */
  206. out_unlock:
  207. spin_unlock_irqrestore(&eda->lock, flags);
  208. return result;
  209. }
  210. /*
  211. * Return contents of EDA cache entry
  212. *
  213. * @dev_addr: index to EDA cache
  214. * @eda_entry: pointer to where contents of EDA cache will be copied
  215. */
  216. int wlp_copy_eda_node(struct wlp_eda *eda, struct uwb_dev_addr *dev_addr,
  217. struct wlp_eda_node *eda_entry)
  218. {
  219. int result = -ENOENT;
  220. struct wlp_eda_node *itr;
  221. unsigned long flags;
  222. spin_lock_irqsave(&eda->lock, flags);
  223. list_for_each_entry(itr, &eda->cache, list_node) {
  224. if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
  225. *eda_entry = *itr;
  226. result = 0;
  227. goto out_unlock;
  228. }
  229. }
  230. /* Not found */
  231. out_unlock:
  232. spin_unlock_irqrestore(&eda->lock, flags);
  233. return result;
  234. }
  235. /*
  236. * Execute function for every element in the cache
  237. *
  238. * @function: function to execute on element of cache (must be atomic)
  239. * @priv: private data of function
  240. * @returns: result of first function that failed, or last function
  241. * executed if no function failed.
  242. *
  243. * Stop executing when function returns error for any element in cache.
  244. *
  245. * IMPORTANT: We are using a spinlock here: the function executed on each
  246. * element has to be atomic.
  247. */
  248. int wlp_eda_for_each(struct wlp_eda *eda, wlp_eda_for_each_f function,
  249. void *priv)
  250. {
  251. int result = 0;
  252. struct wlp *wlp = container_of(eda, struct wlp, eda);
  253. struct wlp_eda_node *entry;
  254. unsigned long flags;
  255. spin_lock_irqsave(&eda->lock, flags);
  256. list_for_each_entry(entry, &eda->cache, list_node) {
  257. result = (*function)(wlp, entry, priv);
  258. if (result < 0)
  259. break;
  260. }
  261. spin_unlock_irqrestore(&eda->lock, flags);
  262. return result;
  263. }
  264. /*
  265. * Execute function for single element in the cache (return dev addr)
  266. *
  267. * @virt_addr: index into EDA cache used to determine which element to
  268. * execute the function on
  269. * @dev_addr: device address of element in cache will be returned using
  270. * @dev_addr
  271. * @function: function to execute on element of cache (must be atomic)
  272. * @priv: private data of function
  273. * @returns: result of function
  274. *
  275. * IMPORTANT: We are using a spinlock here: the function executed on the
  276. * element has to be atomic.
  277. */
  278. int wlp_eda_for_virtual(struct wlp_eda *eda,
  279. const unsigned char virt_addr[ETH_ALEN],
  280. struct uwb_dev_addr *dev_addr,
  281. wlp_eda_for_each_f function,
  282. void *priv)
  283. {
  284. int result = 0;
  285. struct wlp *wlp = container_of(eda, struct wlp, eda);
  286. struct wlp_eda_node *itr;
  287. unsigned long flags;
  288. int found = 0;
  289. spin_lock_irqsave(&eda->lock, flags);
  290. list_for_each_entry(itr, &eda->cache, list_node) {
  291. if (!memcmp(itr->virt_addr, virt_addr,
  292. sizeof(itr->virt_addr))) {
  293. result = (*function)(wlp, itr, priv);
  294. *dev_addr = itr->dev_addr;
  295. found = 1;
  296. break;
  297. }
  298. }
  299. if (!found)
  300. result = -ENODEV;
  301. spin_unlock_irqrestore(&eda->lock, flags);
  302. return result;
  303. }
  304. static const char *__wlp_wss_connect_state[] = { "WLP_WSS_UNCONNECTED",
  305. "WLP_WSS_CONNECTED",
  306. "WLP_WSS_CONNECT_FAILED",
  307. };
  308. static const char *wlp_wss_connect_state_str(unsigned id)
  309. {
  310. if (id >= ARRAY_SIZE(__wlp_wss_connect_state))
  311. return "unknown WSS connection state";
  312. return __wlp_wss_connect_state[id];
  313. }
  314. /*
  315. * View EDA cache from user space
  316. *
  317. * A debugging feature to give user visibility into the EDA cache. Also
  318. * used to display members of WSS to user (called from wlp_wss_members_show())
  319. */
  320. ssize_t wlp_eda_show(struct wlp *wlp, char *buf)
  321. {
  322. ssize_t result = 0;
  323. struct wlp_eda_node *entry;
  324. unsigned long flags;
  325. struct wlp_eda *eda = &wlp->eda;
  326. spin_lock_irqsave(&eda->lock, flags);
  327. result = scnprintf(buf, PAGE_SIZE, "#eth_addr dev_addr wss_ptr "
  328. "tag state virt_addr\n");
  329. list_for_each_entry(entry, &eda->cache, list_node) {
  330. result += scnprintf(buf + result, PAGE_SIZE - result,
  331. "%pM %02x:%02x %p 0x%02x %s %pM\n",
  332. entry->eth_addr,
  333. entry->dev_addr.data[1],
  334. entry->dev_addr.data[0], entry->wss,
  335. entry->tag,
  336. wlp_wss_connect_state_str(entry->state),
  337. entry->virt_addr);
  338. if (result >= PAGE_SIZE)
  339. break;
  340. }
  341. spin_unlock_irqrestore(&eda->lock, flags);
  342. return result;
  343. }
  344. EXPORT_SYMBOL_GPL(wlp_eda_show);
  345. /*
  346. * Add new EDA cache entry based on user input in sysfs
  347. *
  348. * Should only be used for debugging.
  349. *
  350. * The WSS is assumed to be the only WSS supported. This needs to be
  351. * redesigned when we support more than one WSS.
  352. */
  353. ssize_t wlp_eda_store(struct wlp *wlp, const char *buf, size_t size)
  354. {
  355. ssize_t result;
  356. struct wlp_eda *eda = &wlp->eda;
  357. u8 eth_addr[6];
  358. struct uwb_dev_addr dev_addr;
  359. u8 tag;
  360. unsigned state;
  361. result = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx "
  362. "%02hhx:%02hhx %02hhx %u\n",
  363. &eth_addr[0], &eth_addr[1],
  364. &eth_addr[2], &eth_addr[3],
  365. &eth_addr[4], &eth_addr[5],
  366. &dev_addr.data[1], &dev_addr.data[0], &tag, &state);
  367. switch (result) {
  368. case 6: /* no dev addr specified -- remove entry NOT IMPLEMENTED */
  369. /*result = wlp_eda_rm(eda, eth_addr, &dev_addr);*/
  370. result = -ENOSYS;
  371. break;
  372. case 10:
  373. state = state >= 1 ? 1 : 0;
  374. result = wlp_eda_create_node(eda, eth_addr, &dev_addr);
  375. if (result < 0 && result != -EEXIST)
  376. goto error;
  377. /* Set virtual addr to be same as MAC */
  378. result = wlp_eda_update_node(eda, &dev_addr, &wlp->wss,
  379. eth_addr, tag, state);
  380. if (result < 0)
  381. goto error;
  382. break;
  383. default: /* bad format */
  384. result = -EINVAL;
  385. }
  386. error:
  387. return result < 0 ? result : size;
  388. }
  389. EXPORT_SYMBOL_GPL(wlp_eda_store);