2 * Copyright (c) 2012 Jiri Svoboda
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 #include <fibril_synch.h>
40 #include <inet/iplink_srv.h>
46 /** Address translation list (of ethip_atrans_t) */
47 static FIBRIL_MUTEX_INITIALIZE(atrans_list_lock
);
48 static LIST_INITIALIZE(atrans_list
);
49 static FIBRIL_CONDVAR_INITIALIZE(atrans_cv
);
51 static ethip_atrans_t
*atrans_find(addr32_t ip_addr
)
53 list_foreach(atrans_list
, atrans_list
, ethip_atrans_t
, atrans
) {
54 if (atrans
->ip_addr
== ip_addr
)
61 errno_t
atrans_add(addr32_t ip_addr
, addr48_t mac_addr
)
63 ethip_atrans_t
*atrans
;
66 atrans
= calloc(1, sizeof(ethip_atrans_t
));
70 atrans
->ip_addr
= ip_addr
;
71 addr48(mac_addr
, atrans
->mac_addr
);
73 fibril_mutex_lock(&atrans_list_lock
);
74 prev
= atrans_find(ip_addr
);
76 list_remove(&prev
->atrans_list
);
80 list_append(&atrans
->atrans_list
, &atrans_list
);
81 fibril_mutex_unlock(&atrans_list_lock
);
82 fibril_condvar_broadcast(&atrans_cv
);
87 errno_t
atrans_remove(addr32_t ip_addr
)
89 ethip_atrans_t
*atrans
;
91 fibril_mutex_lock(&atrans_list_lock
);
92 atrans
= atrans_find(ip_addr
);
94 fibril_mutex_unlock(&atrans_list_lock
);
98 list_remove(&atrans
->atrans_list
);
99 fibril_mutex_unlock(&atrans_list_lock
);
105 static errno_t
atrans_lookup_locked(addr32_t ip_addr
, addr48_t mac_addr
)
107 ethip_atrans_t
*atrans
= atrans_find(ip_addr
);
111 addr48(atrans
->mac_addr
, mac_addr
);
115 errno_t
atrans_lookup(addr32_t ip_addr
, addr48_t mac_addr
)
119 fibril_mutex_lock(&atrans_list_lock
);
120 rc
= atrans_lookup_locked(ip_addr
, mac_addr
);
121 fibril_mutex_unlock(&atrans_list_lock
);
126 static void atrans_lookup_timeout_handler(void *arg
)
128 bool *timedout
= (bool *)arg
;
130 fibril_mutex_lock(&atrans_list_lock
);
132 fibril_mutex_unlock(&atrans_list_lock
);
133 fibril_condvar_broadcast(&atrans_cv
);
136 errno_t
atrans_lookup_timeout(addr32_t ip_addr
, usec_t timeout
,
143 t
= fibril_timer_create(NULL
);
148 fibril_timer_set(t
, timeout
, atrans_lookup_timeout_handler
, &timedout
);
150 fibril_mutex_lock(&atrans_list_lock
);
152 while ((rc
= atrans_lookup_locked(ip_addr
, mac_addr
)) == ENOENT
&&
154 fibril_condvar_wait(&atrans_cv
, &atrans_list_lock
);
157 fibril_mutex_unlock(&atrans_list_lock
);
158 (void) fibril_timer_clear(t
);
159 fibril_timer_destroy(t
);