2 * WUSB Wire Adapter: WLP interface
3 * Ethernet to device address cache
5 * Copyright (C) 2005-2006 Intel Corporation
6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
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.
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.
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
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 :).
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.
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.
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.
55 #include <linux/netdevice.h>
56 #include <linux/uwb/debug.h>
57 #include <linux/etherdevice.h>
58 #include <linux/wlp.h>
59 #include "wlp-internal.h"
62 /* FIXME: cache is not purged, only on device close */
64 /* FIXME: does not scale, change to dynamic array */
67 * Initialize the EDA cache
69 * @returns 0 if ok, < 0 errno code on error
71 * Call when the interface is being brought up
73 * NOTE: Keep it as a separate function as the implementation will
74 * change and be more complex.
76 void wlp_eda_init(struct wlp_eda *eda)
78 INIT_LIST_HEAD(&eda->cache);
79 spin_lock_init(&eda->lock);
83 * Release the EDA cache
85 * @returns 0 if ok, < 0 errno code on error
87 * Called when the interface is brought down
89 void wlp_eda_release(struct wlp_eda *eda)
92 struct wlp_eda_node *itr, *next;
94 spin_lock_irqsave(&eda->lock, flags);
95 list_for_each_entry_safe(itr, next, &eda->cache, list_node) {
96 list_del(&itr->list_node);
99 spin_unlock_irqrestore(&eda->lock, flags);
103 * Add an address mapping
105 * @returns 0 if ok, < 0 errno code on error
107 * An address mapping is initially created when the neighbor device is seen
108 * for the first time (it is "onair"). At this time the neighbor is not
109 * connected or associated with a WSS so we only populate the Ethernet and
110 * Device address fields.
113 int wlp_eda_create_node(struct wlp_eda *eda,
114 const unsigned char eth_addr[ETH_ALEN],
115 const struct uwb_dev_addr *dev_addr)
118 struct wlp_eda_node *itr;
121 BUG_ON(dev_addr == NULL || eth_addr == NULL);
122 spin_lock_irqsave(&eda->lock, flags);
123 list_for_each_entry(itr, &eda->cache, list_node) {
124 if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
125 printk(KERN_ERR "EDA cache already contains entry "
126 "for neighbor %02x:%02x\n",
127 dev_addr->data[1], dev_addr->data[0]);
132 itr = kzalloc(sizeof(*itr), GFP_ATOMIC);
134 memcpy(itr->eth_addr, eth_addr, sizeof(itr->eth_addr));
135 itr->dev_addr = *dev_addr;
136 list_add(&itr->list_node, &eda->cache);
140 spin_unlock_irqrestore(&eda->lock, flags);
145 * Remove entry from EDA cache
147 * This is done when the device goes off air.
149 void wlp_eda_rm_node(struct wlp_eda *eda, const struct uwb_dev_addr *dev_addr)
151 struct wlp_eda_node *itr, *next;
154 spin_lock_irqsave(&eda->lock, flags);
155 list_for_each_entry_safe(itr, next, &eda->cache, list_node) {
156 if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
157 list_del(&itr->list_node);
162 spin_unlock_irqrestore(&eda->lock, flags);
166 * Update an address mapping
168 * @returns 0 if ok, < 0 errno code on error
170 int wlp_eda_update_node(struct wlp_eda *eda,
171 const struct uwb_dev_addr *dev_addr,
173 const unsigned char virt_addr[ETH_ALEN],
174 const u8 tag, const enum wlp_wss_connect state)
176 int result = -ENOENT;
177 struct wlp_eda_node *itr;
180 spin_lock_irqsave(&eda->lock, flags);
181 list_for_each_entry(itr, &eda->cache, list_node) {
182 if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
183 /* Found it, update it */
185 memcpy(itr->virt_addr, virt_addr,
186 sizeof(itr->virt_addr));
195 spin_unlock_irqrestore(&eda->lock, flags);
200 * Update only state field of an address mapping
202 * @returns 0 if ok, < 0 errno code on error
204 int wlp_eda_update_node_state(struct wlp_eda *eda,
205 const struct uwb_dev_addr *dev_addr,
206 const enum wlp_wss_connect state)
208 int result = -ENOENT;
209 struct wlp_eda_node *itr;
212 spin_lock_irqsave(&eda->lock, flags);
213 list_for_each_entry(itr, &eda->cache, list_node) {
214 if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
215 /* Found it, update it */
223 spin_unlock_irqrestore(&eda->lock, flags);
228 * Return contents of EDA cache entry
230 * @dev_addr: index to EDA cache
231 * @eda_entry: pointer to where contents of EDA cache will be copied
233 int wlp_copy_eda_node(struct wlp_eda *eda, struct uwb_dev_addr *dev_addr,
234 struct wlp_eda_node *eda_entry)
236 int result = -ENOENT;
237 struct wlp_eda_node *itr;
240 spin_lock_irqsave(&eda->lock, flags);
241 list_for_each_entry(itr, &eda->cache, list_node) {
242 if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
250 spin_unlock_irqrestore(&eda->lock, flags);
255 * Execute function for every element in the cache
257 * @function: function to execute on element of cache (must be atomic)
258 * @priv: private data of function
259 * @returns: result of first function that failed, or last function
260 * executed if no function failed.
262 * Stop executing when function returns error for any element in cache.
264 * IMPORTANT: We are using a spinlock here: the function executed on each
265 * element has to be atomic.
267 int wlp_eda_for_each(struct wlp_eda *eda, wlp_eda_for_each_f function,
271 struct wlp *wlp = container_of(eda, struct wlp, eda);
272 struct wlp_eda_node *entry;
275 spin_lock_irqsave(&eda->lock, flags);
276 list_for_each_entry(entry, &eda->cache, list_node) {
277 result = (*function)(wlp, entry, priv);
281 spin_unlock_irqrestore(&eda->lock, flags);
286 * Execute function for single element in the cache (return dev addr)
288 * @virt_addr: index into EDA cache used to determine which element to
289 * execute the function on
290 * @dev_addr: device address of element in cache will be returned using
292 * @function: function to execute on element of cache (must be atomic)
293 * @priv: private data of function
294 * @returns: result of function
296 * IMPORTANT: We are using a spinlock here: the function executed on the
297 * element has to be atomic.
299 int wlp_eda_for_virtual(struct wlp_eda *eda,
300 const unsigned char virt_addr[ETH_ALEN],
301 struct uwb_dev_addr *dev_addr,
302 wlp_eda_for_each_f function,
306 struct wlp *wlp = container_of(eda, struct wlp, eda);
307 struct device *dev = &wlp->rc->uwb_dev.dev;
308 struct wlp_eda_node *itr;
312 spin_lock_irqsave(&eda->lock, flags);
313 list_for_each_entry(itr, &eda->cache, list_node) {
314 if (!memcmp(itr->virt_addr, virt_addr,
315 sizeof(itr->virt_addr))) {
316 d_printf(6, dev, "EDA: looking for "
317 "%02x:%02x:%02x:%02x:%02x:%02x hit %02x:%02x "
318 "wss %p tag 0x%02x state %u\n",
319 virt_addr[0], virt_addr[1],
320 virt_addr[2], virt_addr[3],
321 virt_addr[4], virt_addr[5],
322 itr->dev_addr.data[1],
323 itr->dev_addr.data[0], itr->wss,
324 itr->tag, itr->state);
325 result = (*function)(wlp, itr, priv);
326 *dev_addr = itr->dev_addr;
330 d_printf(6, dev, "EDA: looking for "
331 "%02x:%02x:%02x:%02x:%02x:%02x "
333 "%02x:%02x:%02x:%02x:%02x:%02x miss\n",
334 virt_addr[0], virt_addr[1],
335 virt_addr[2], virt_addr[3],
336 virt_addr[4], virt_addr[5],
337 itr->virt_addr[0], itr->virt_addr[1],
338 itr->virt_addr[2], itr->virt_addr[3],
339 itr->virt_addr[4], itr->virt_addr[5]);
342 if (printk_ratelimit())
343 dev_err(dev, "EDA: Eth addr %02x:%02x:%02x"
344 ":%02x:%02x:%02x not found.\n",
345 virt_addr[0], virt_addr[1],
346 virt_addr[2], virt_addr[3],
347 virt_addr[4], virt_addr[5]);
350 spin_unlock_irqrestore(&eda->lock, flags);
354 static const char *__wlp_wss_connect_state[] = { "WLP_WSS_UNCONNECTED",
356 "WLP_WSS_CONNECT_FAILED",
359 static const char *wlp_wss_connect_state_str(unsigned id)
361 if (id >= ARRAY_SIZE(__wlp_wss_connect_state))
362 return "unknown WSS connection state";
363 return __wlp_wss_connect_state[id];
367 * View EDA cache from user space
369 * A debugging feature to give user visibility into the EDA cache. Also
370 * used to display members of WSS to user (called from wlp_wss_members_show())
372 ssize_t wlp_eda_show(struct wlp *wlp, char *buf)
375 struct wlp_eda_node *entry;
377 struct wlp_eda *eda = &wlp->eda;
378 spin_lock_irqsave(&eda->lock, flags);
379 result = scnprintf(buf, PAGE_SIZE, "#eth_addr dev_addr wss_ptr "
380 "tag state virt_addr\n");
381 list_for_each_entry(entry, &eda->cache, list_node) {
382 result += scnprintf(buf + result, PAGE_SIZE - result,
383 "%02x:%02x:%02x:%02x:%02x:%02x %02x:%02x "
385 "%02x:%02x:%02x:%02x:%02x:%02x\n",
386 entry->eth_addr[0], entry->eth_addr[1],
387 entry->eth_addr[2], entry->eth_addr[3],
388 entry->eth_addr[4], entry->eth_addr[5],
389 entry->dev_addr.data[1],
390 entry->dev_addr.data[0], entry->wss,
392 wlp_wss_connect_state_str(entry->state),
393 entry->virt_addr[0], entry->virt_addr[1],
394 entry->virt_addr[2], entry->virt_addr[3],
395 entry->virt_addr[4], entry->virt_addr[5]);
396 if (result >= PAGE_SIZE)
399 spin_unlock_irqrestore(&eda->lock, flags);
402 EXPORT_SYMBOL_GPL(wlp_eda_show);
405 * Add new EDA cache entry based on user input in sysfs
407 * Should only be used for debugging.
409 * The WSS is assumed to be the only WSS supported. This needs to be
410 * redesigned when we support more than one WSS.
412 ssize_t wlp_eda_store(struct wlp *wlp, const char *buf, size_t size)
415 struct wlp_eda *eda = &wlp->eda;
417 struct uwb_dev_addr dev_addr;
421 result = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx "
422 "%02hhx:%02hhx %02hhx %u\n",
423 ð_addr[0], ð_addr[1],
424 ð_addr[2], ð_addr[3],
425 ð_addr[4], ð_addr[5],
426 &dev_addr.data[1], &dev_addr.data[0], &tag, &state);
428 case 6: /* no dev addr specified -- remove entry NOT IMPLEMENTED */
429 /*result = wlp_eda_rm(eda, eth_addr, &dev_addr);*/
433 state = state >= 1 ? 1 : 0;
434 result = wlp_eda_create_node(eda, eth_addr, &dev_addr);
435 if (result < 0 && result != -EEXIST)
437 /* Set virtual addr to be same as MAC */
438 result = wlp_eda_update_node(eda, &dev_addr, &wlp->wss,
439 eth_addr, tag, state);
443 default: /* bad format */
447 return result < 0 ? result : size;
449 EXPORT_SYMBOL_GPL(wlp_eda_store);