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.
54 #include <linux/netdevice.h>
55 #include <linux/etherdevice.h>
56 #include <linux/slab.h>
57 #include <linux/wlp.h>
58 #include "wlp-internal.h"
61 /* FIXME: cache is not purged, only on device close */
63 /* FIXME: does not scale, change to dynamic array */
66 * Initialize the EDA cache
68 * @returns 0 if ok, < 0 errno code on error
70 * Call when the interface is being brought up
72 * NOTE: Keep it as a separate function as the implementation will
73 * change and be more complex.
75 void wlp_eda_init(struct wlp_eda
*eda
)
77 INIT_LIST_HEAD(&eda
->cache
);
78 spin_lock_init(&eda
->lock
);
82 * Release the EDA cache
84 * @returns 0 if ok, < 0 errno code on error
86 * Called when the interface is brought down
88 void wlp_eda_release(struct wlp_eda
*eda
)
91 struct wlp_eda_node
*itr
, *next
;
93 spin_lock_irqsave(&eda
->lock
, flags
);
94 list_for_each_entry_safe(itr
, next
, &eda
->cache
, list_node
) {
95 list_del(&itr
->list_node
);
98 spin_unlock_irqrestore(&eda
->lock
, flags
);
102 * Add an address mapping
104 * @returns 0 if ok, < 0 errno code on error
106 * An address mapping is initially created when the neighbor device is seen
107 * for the first time (it is "onair"). At this time the neighbor is not
108 * connected or associated with a WSS so we only populate the Ethernet and
109 * Device address fields.
112 int wlp_eda_create_node(struct wlp_eda
*eda
,
113 const unsigned char eth_addr
[ETH_ALEN
],
114 const struct uwb_dev_addr
*dev_addr
)
117 struct wlp_eda_node
*itr
;
120 BUG_ON(dev_addr
== NULL
|| eth_addr
== NULL
);
121 spin_lock_irqsave(&eda
->lock
, flags
);
122 list_for_each_entry(itr
, &eda
->cache
, list_node
) {
123 if (!memcmp(&itr
->dev_addr
, dev_addr
, sizeof(itr
->dev_addr
))) {
124 printk(KERN_ERR
"EDA cache already contains entry "
125 "for neighbor %02x:%02x\n",
126 dev_addr
->data
[1], dev_addr
->data
[0]);
131 itr
= kzalloc(sizeof(*itr
), GFP_ATOMIC
);
133 memcpy(itr
->eth_addr
, eth_addr
, sizeof(itr
->eth_addr
));
134 itr
->dev_addr
= *dev_addr
;
135 list_add(&itr
->list_node
, &eda
->cache
);
139 spin_unlock_irqrestore(&eda
->lock
, flags
);
144 * Remove entry from EDA cache
146 * This is done when the device goes off air.
148 void wlp_eda_rm_node(struct wlp_eda
*eda
, const struct uwb_dev_addr
*dev_addr
)
150 struct wlp_eda_node
*itr
, *next
;
153 spin_lock_irqsave(&eda
->lock
, flags
);
154 list_for_each_entry_safe(itr
, next
, &eda
->cache
, list_node
) {
155 if (!memcmp(&itr
->dev_addr
, dev_addr
, sizeof(itr
->dev_addr
))) {
156 list_del(&itr
->list_node
);
161 spin_unlock_irqrestore(&eda
->lock
, flags
);
165 * Update an address mapping
167 * @returns 0 if ok, < 0 errno code on error
169 int wlp_eda_update_node(struct wlp_eda
*eda
,
170 const struct uwb_dev_addr
*dev_addr
,
172 const unsigned char virt_addr
[ETH_ALEN
],
173 const u8 tag
, const enum wlp_wss_connect state
)
175 int result
= -ENOENT
;
176 struct wlp_eda_node
*itr
;
179 spin_lock_irqsave(&eda
->lock
, flags
);
180 list_for_each_entry(itr
, &eda
->cache
, list_node
) {
181 if (!memcmp(&itr
->dev_addr
, dev_addr
, sizeof(itr
->dev_addr
))) {
182 /* Found it, update it */
184 memcpy(itr
->virt_addr
, virt_addr
,
185 sizeof(itr
->virt_addr
));
194 spin_unlock_irqrestore(&eda
->lock
, flags
);
199 * Update only state field of an address mapping
201 * @returns 0 if ok, < 0 errno code on error
203 int wlp_eda_update_node_state(struct wlp_eda
*eda
,
204 const struct uwb_dev_addr
*dev_addr
,
205 const enum wlp_wss_connect state
)
207 int result
= -ENOENT
;
208 struct wlp_eda_node
*itr
;
211 spin_lock_irqsave(&eda
->lock
, flags
);
212 list_for_each_entry(itr
, &eda
->cache
, list_node
) {
213 if (!memcmp(&itr
->dev_addr
, dev_addr
, sizeof(itr
->dev_addr
))) {
214 /* Found it, update it */
222 spin_unlock_irqrestore(&eda
->lock
, flags
);
227 * Return contents of EDA cache entry
229 * @dev_addr: index to EDA cache
230 * @eda_entry: pointer to where contents of EDA cache will be copied
232 int wlp_copy_eda_node(struct wlp_eda
*eda
, struct uwb_dev_addr
*dev_addr
,
233 struct wlp_eda_node
*eda_entry
)
235 int result
= -ENOENT
;
236 struct wlp_eda_node
*itr
;
239 spin_lock_irqsave(&eda
->lock
, flags
);
240 list_for_each_entry(itr
, &eda
->cache
, list_node
) {
241 if (!memcmp(&itr
->dev_addr
, dev_addr
, sizeof(itr
->dev_addr
))) {
249 spin_unlock_irqrestore(&eda
->lock
, flags
);
254 * Execute function for every element in the cache
256 * @function: function to execute on element of cache (must be atomic)
257 * @priv: private data of function
258 * @returns: result of first function that failed, or last function
259 * executed if no function failed.
261 * Stop executing when function returns error for any element in cache.
263 * IMPORTANT: We are using a spinlock here: the function executed on each
264 * element has to be atomic.
266 int wlp_eda_for_each(struct wlp_eda
*eda
, wlp_eda_for_each_f function
,
270 struct wlp
*wlp
= container_of(eda
, struct wlp
, eda
);
271 struct wlp_eda_node
*entry
;
274 spin_lock_irqsave(&eda
->lock
, flags
);
275 list_for_each_entry(entry
, &eda
->cache
, list_node
) {
276 result
= (*function
)(wlp
, entry
, priv
);
280 spin_unlock_irqrestore(&eda
->lock
, flags
);
285 * Execute function for single element in the cache (return dev addr)
287 * @virt_addr: index into EDA cache used to determine which element to
288 * execute the function on
289 * @dev_addr: device address of element in cache will be returned using
291 * @function: function to execute on element of cache (must be atomic)
292 * @priv: private data of function
293 * @returns: result of function
295 * IMPORTANT: We are using a spinlock here: the function executed on the
296 * element has to be atomic.
298 int wlp_eda_for_virtual(struct wlp_eda
*eda
,
299 const unsigned char virt_addr
[ETH_ALEN
],
300 struct uwb_dev_addr
*dev_addr
,
301 wlp_eda_for_each_f function
,
305 struct wlp
*wlp
= container_of(eda
, struct wlp
, eda
);
306 struct wlp_eda_node
*itr
;
310 spin_lock_irqsave(&eda
->lock
, flags
);
311 list_for_each_entry(itr
, &eda
->cache
, list_node
) {
312 if (!memcmp(itr
->virt_addr
, virt_addr
,
313 sizeof(itr
->virt_addr
))) {
314 result
= (*function
)(wlp
, itr
, priv
);
315 *dev_addr
= itr
->dev_addr
;
322 spin_unlock_irqrestore(&eda
->lock
, flags
);
326 static const char *__wlp_wss_connect_state
[] = { "WLP_WSS_UNCONNECTED",
328 "WLP_WSS_CONNECT_FAILED",
331 static const char *wlp_wss_connect_state_str(unsigned id
)
333 if (id
>= ARRAY_SIZE(__wlp_wss_connect_state
))
334 return "unknown WSS connection state";
335 return __wlp_wss_connect_state
[id
];
339 * View EDA cache from user space
341 * A debugging feature to give user visibility into the EDA cache. Also
342 * used to display members of WSS to user (called from wlp_wss_members_show())
344 ssize_t
wlp_eda_show(struct wlp
*wlp
, char *buf
)
347 struct wlp_eda_node
*entry
;
349 struct wlp_eda
*eda
= &wlp
->eda
;
350 spin_lock_irqsave(&eda
->lock
, flags
);
351 result
= scnprintf(buf
, PAGE_SIZE
, "#eth_addr dev_addr wss_ptr "
352 "tag state virt_addr\n");
353 list_for_each_entry(entry
, &eda
->cache
, list_node
) {
354 result
+= scnprintf(buf
+ result
, PAGE_SIZE
- result
,
355 "%pM %02x:%02x %p 0x%02x %s %pM\n",
357 entry
->dev_addr
.data
[1],
358 entry
->dev_addr
.data
[0], entry
->wss
,
360 wlp_wss_connect_state_str(entry
->state
),
362 if (result
>= PAGE_SIZE
)
365 spin_unlock_irqrestore(&eda
->lock
, flags
);
368 EXPORT_SYMBOL_GPL(wlp_eda_show
);
371 * Add new EDA cache entry based on user input in sysfs
373 * Should only be used for debugging.
375 * The WSS is assumed to be the only WSS supported. This needs to be
376 * redesigned when we support more than one WSS.
378 ssize_t
wlp_eda_store(struct wlp
*wlp
, const char *buf
, size_t size
)
381 struct wlp_eda
*eda
= &wlp
->eda
;
383 struct uwb_dev_addr dev_addr
;
387 result
= sscanf(buf
, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx "
388 "%02hhx:%02hhx %02hhx %u\n",
389 ð_addr
[0], ð_addr
[1],
390 ð_addr
[2], ð_addr
[3],
391 ð_addr
[4], ð_addr
[5],
392 &dev_addr
.data
[1], &dev_addr
.data
[0], &tag
, &state
);
394 case 6: /* no dev addr specified -- remove entry NOT IMPLEMENTED */
395 /*result = wlp_eda_rm(eda, eth_addr, &dev_addr);*/
399 state
= state
>= 1 ? 1 : 0;
400 result
= wlp_eda_create_node(eda
, eth_addr
, &dev_addr
);
401 if (result
< 0 && result
!= -EEXIST
)
403 /* Set virtual addr to be same as MAC */
404 result
= wlp_eda_update_node(eda
, &dev_addr
, &wlp
->wss
,
405 eth_addr
, tag
, state
);
409 default: /* bad format */
413 return result
< 0 ? result
: size
;
415 EXPORT_SYMBOL_GPL(wlp_eda_store
);