eda.c 12 KB

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