Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
c7c6575f
Commit
c7c6575f
authored
Dec 12, 2011
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'batman-adv/next' of
git://git.open-mesh.org/linux-merge
parents
0850f0f5
b5a1eeef
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
216 additions
and
168 deletions
+216
-168
Documentation/networking/batman-adv.txt
Documentation/networking/batman-adv.txt
+4
-3
net/batman-adv/gateway_client.c
net/batman-adv/gateway_client.c
+1
-1
net/batman-adv/icmp_socket.c
net/batman-adv/icmp_socket.c
+4
-10
net/batman-adv/routing.c
net/batman-adv/routing.c
+1
-2
net/batman-adv/soft-interface.c
net/batman-adv/soft-interface.c
+1
-1
net/batman-adv/translation-table.c
net/batman-adv/translation-table.c
+195
-141
net/batman-adv/types.h
net/batman-adv/types.h
+7
-7
net/batman-adv/vis.c
net/batman-adv/vis.c
+3
-3
No files found.
Documentation/networking/batman-adv.txt
View file @
c7c6575f
...
...
@@ -200,15 +200,16 @@ abled during run time. Following log_levels are defined:
0 - All debug output disabled
1 - Enable messages related to routing / flooding / broadcasting
2 - Enable route or tt entry added / changed / deleted
3 - Enable all messages
2 - Enable messages related to route added / changed / deleted
4 - Enable messages related to translation table operations
7 - Enable all messages
The debug output can be changed at runtime using the file
/sys/class/net/bat0/mesh/log_level. e.g.
# echo 2 > /sys/class/net/bat0/mesh/log_level
will enable debug messages for when routes
or TTs
change.
will enable debug messages for when routes change.
BATCTL
...
...
net/batman-adv/gateway_client.c
View file @
c7c6575f
...
...
@@ -695,7 +695,7 @@ bool gw_out_of_range(struct bat_priv *bat_priv,
}
neigh_old
=
find_router
(
bat_priv
,
orig_dst_node
,
NULL
);
if
(
!
!
neigh_old
)
if
(
!
neigh_old
)
goto
out
;
if
(
curr_tq_avg
-
neigh_old
->
tq_avg
>
GW_THRESHOLD
)
...
...
net/batman-adv/icmp_socket.c
View file @
c7c6575f
...
...
@@ -136,10 +136,9 @@ static ssize_t bat_socket_read(struct file *file, char __user *buf,
spin_unlock_bh
(
&
socket_client
->
lock
);
error
=
__copy_to_user
(
buf
,
&
socket_packet
->
icmp_packet
,
socket_packet
->
icmp
_len
);
packet_len
=
min
(
count
,
socket_packet
->
icmp_len
);
error
=
copy_to_user
(
buf
,
&
socket_packet
->
icmp_packet
,
packet
_len
);
packet_len
=
socket_packet
->
icmp_len
;
kfree
(
socket_packet
);
if
(
error
)
...
...
@@ -187,12 +186,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
skb_reserve
(
skb
,
sizeof
(
struct
ethhdr
));
icmp_packet
=
(
struct
icmp_packet_rr
*
)
skb_put
(
skb
,
packet_len
);
if
(
!
access_ok
(
VERIFY_READ
,
buff
,
packet_len
))
{
len
=
-
EFAULT
;
goto
free_skb
;
}
if
(
__copy_from_user
(
icmp_packet
,
buff
,
packet_len
))
{
if
(
copy_from_user
(
icmp_packet
,
buff
,
packet_len
))
{
len
=
-
EFAULT
;
goto
free_skb
;
}
...
...
@@ -217,7 +211,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
if
(
icmp_packet
->
version
!=
COMPAT_VERSION
)
{
icmp_packet
->
msg_type
=
PARAMETER_PROBLEM
;
icmp_packet
->
ttl
=
COMPAT_VERSION
;
icmp_packet
->
version
=
COMPAT_VERSION
;
bat_socket_add_packet
(
socket_client
,
icmp_packet
,
packet_len
);
goto
free_skb
;
}
...
...
net/batman-adv/routing.c
View file @
c7c6575f
...
...
@@ -627,8 +627,7 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
/* Ensure we have all the claimed data */
if
(
unlikely
(
skb_headlen
(
skb
)
<
sizeof
(
struct
tt_query_packet
)
+
tt_len
))
sizeof
(
struct
tt_query_packet
)
+
tt_len
))
goto
out
;
handle_tt_response
(
bat_priv
,
tt_query
);
...
...
net/batman-adv/soft-interface.c
View file @
c7c6575f
...
...
@@ -874,7 +874,7 @@ struct net_device *softif_create(const char *name)
unreg_sysfs:
sysfs_del_meshif
(
soft_iface
);
unreg_soft_iface:
unregister_netdev
(
soft_iface
);
unregister_netdev
ice
(
soft_iface
);
return
NULL
;
free_soft_iface:
...
...
net/batman-adv/translation-table.c
View file @
c7c6575f
...
...
@@ -36,18 +36,9 @@ static void _tt_global_del(struct bat_priv *bat_priv,
static
void
tt_purge
(
struct
work_struct
*
work
);
/* returns 1 if they are the same mac addr */
static
int
compare_
l
tt
(
const
struct
hlist_node
*
node
,
const
void
*
data2
)
static
int
compare_tt
(
const
struct
hlist_node
*
node
,
const
void
*
data2
)
{
const
void
*
data1
=
container_of
(
node
,
struct
tt_local_entry
,
hash_entry
);
return
(
memcmp
(
data1
,
data2
,
ETH_ALEN
)
==
0
?
1
:
0
);
}
/* returns 1 if they are the same mac addr */
static
int
compare_gtt
(
const
struct
hlist_node
*
node
,
const
void
*
data2
)
{
const
void
*
data1
=
container_of
(
node
,
struct
tt_global_entry
,
const
void
*
data1
=
container_of
(
node
,
struct
tt_common_entry
,
hash_entry
);
return
(
memcmp
(
data1
,
data2
,
ETH_ALEN
)
==
0
?
1
:
0
);
...
...
@@ -60,13 +51,12 @@ static void tt_start_timer(struct bat_priv *bat_priv)
msecs_to_jiffies
(
5000
));
}
static
struct
tt_
local_entry
*
tt_local_hash_find
(
struct
bat_priv
*
bat_priv
,
const
void
*
data
)
static
struct
tt_
common_entry
*
tt_hash_find
(
struct
hashtable_t
*
hash
,
const
void
*
data
)
{
struct
hashtable_t
*
hash
=
bat_priv
->
tt_local_hash
;
struct
hlist_head
*
head
;
struct
hlist_node
*
node
;
struct
tt_
local_entry
*
tt_local_entry
,
*
tt_local
_entry_tmp
=
NULL
;
struct
tt_
common_entry
*
tt_common_entry
,
*
tt_common
_entry_tmp
=
NULL
;
uint32_t
index
;
if
(
!
hash
)
...
...
@@ -76,51 +66,46 @@ static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv,
head
=
&
hash
->
table
[
index
];
rcu_read_lock
();
hlist_for_each_entry_rcu
(
tt_
local
_entry
,
node
,
head
,
hash_entry
)
{
if
(
!
compare_eth
(
tt_
local
_entry
,
data
))
hlist_for_each_entry_rcu
(
tt_
common
_entry
,
node
,
head
,
hash_entry
)
{
if
(
!
compare_eth
(
tt_
common
_entry
,
data
))
continue
;
if
(
!
atomic_inc_not_zero
(
&
tt_
local
_entry
->
refcount
))
if
(
!
atomic_inc_not_zero
(
&
tt_
common
_entry
->
refcount
))
continue
;
tt_
local_entry_tmp
=
tt_local
_entry
;
tt_
common_entry_tmp
=
tt_common
_entry
;
break
;
}
rcu_read_unlock
();
return
tt_
local
_entry_tmp
;
return
tt_
common
_entry_tmp
;
}
static
struct
tt_
global_entry
*
tt_glob
al_hash_find
(
struct
bat_priv
*
bat_priv
,
const
void
*
data
)
static
struct
tt_
local_entry
*
tt_loc
al_hash_find
(
struct
bat_priv
*
bat_priv
,
const
void
*
data
)
{
struct
hashtable_t
*
hash
=
bat_priv
->
tt_global_hash
;
struct
hlist_head
*
head
;
struct
hlist_node
*
node
;
struct
tt_global_entry
*
tt_global_entry
;
struct
tt_global_entry
*
tt_global_entry_tmp
=
NULL
;
uint32_t
index
;
if
(
!
hash
)
return
NULL
;
index
=
choose_orig
(
data
,
hash
->
size
);
head
=
&
hash
->
table
[
index
];
struct
tt_common_entry
*
tt_common_entry
;
struct
tt_local_entry
*
tt_local_entry
=
NULL
;
rcu_read_lock
();
hlist_for_each_entry_rcu
(
tt_global_entry
,
node
,
head
,
hash_entry
)
{
if
(
!
compare_eth
(
tt_global_entry
,
data
))
continue
;
tt_common_entry
=
tt_hash_find
(
bat_priv
->
tt_local_hash
,
data
);
if
(
tt_common_entry
)
tt_local_entry
=
container_of
(
tt_common_entry
,
struct
tt_local_entry
,
common
);
return
tt_local_entry
;
}
if
(
!
atomic_inc_not_zero
(
&
tt_global_entry
->
refcount
))
continue
;
static
struct
tt_global_entry
*
tt_global_hash_find
(
struct
bat_priv
*
bat_priv
,
const
void
*
data
)
{
struct
tt_common_entry
*
tt_common_entry
;
struct
tt_global_entry
*
tt_global_entry
=
NULL
;
tt_global_entry_tmp
=
tt_global_entry
;
break
;
}
rcu_read_unlock
();
tt_common_entry
=
tt_hash_find
(
bat_priv
->
tt_global_hash
,
data
);
if
(
tt_common_entry
)
tt_global_entry
=
container_of
(
tt_common_entry
,
struct
tt_global_entry
,
common
);
return
tt_global_entry
;
return
tt_global_entry_tmp
;
}
static
bool
is_out_of_time
(
unsigned
long
starting_time
,
unsigned
long
timeout
)
...
...
@@ -133,15 +118,18 @@ static bool is_out_of_time(unsigned long starting_time, unsigned long timeout)
static
void
tt_local_entry_free_ref
(
struct
tt_local_entry
*
tt_local_entry
)
{
if
(
atomic_dec_and_test
(
&
tt_local_entry
->
refcount
))
kfree_rcu
(
tt_local_entry
,
rcu
);
if
(
atomic_dec_and_test
(
&
tt_local_entry
->
common
.
refcount
))
kfree_rcu
(
tt_local_entry
,
common
.
rcu
);
}
static
void
tt_global_entry_free_rcu
(
struct
rcu_head
*
rcu
)
{
struct
tt_common_entry
*
tt_common_entry
;
struct
tt_global_entry
*
tt_global_entry
;
tt_global_entry
=
container_of
(
rcu
,
struct
tt_global_entry
,
rcu
);
tt_common_entry
=
container_of
(
rcu
,
struct
tt_common_entry
,
rcu
);
tt_global_entry
=
container_of
(
tt_common_entry
,
struct
tt_global_entry
,
common
);
if
(
tt_global_entry
->
orig_node
)
orig_node_free_ref
(
tt_global_entry
->
orig_node
);
...
...
@@ -151,8 +139,9 @@ static void tt_global_entry_free_rcu(struct rcu_head *rcu)
static
void
tt_global_entry_free_ref
(
struct
tt_global_entry
*
tt_global_entry
)
{
if
(
atomic_dec_and_test
(
&
tt_global_entry
->
refcount
))
call_rcu
(
&
tt_global_entry
->
rcu
,
tt_global_entry_free_rcu
);
if
(
atomic_dec_and_test
(
&
tt_global_entry
->
common
.
refcount
))
call_rcu
(
&
tt_global_entry
->
common
.
rcu
,
tt_global_entry_free_rcu
);
}
static
void
tt_local_event
(
struct
bat_priv
*
bat_priv
,
const
uint8_t
*
addr
,
...
...
@@ -201,6 +190,7 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
struct
bat_priv
*
bat_priv
=
netdev_priv
(
soft_iface
);
struct
tt_local_entry
*
tt_local_entry
=
NULL
;
struct
tt_global_entry
*
tt_global_entry
=
NULL
;
int
hash_added
;
tt_local_entry
=
tt_local_hash_find
(
bat_priv
,
addr
);
...
...
@@ -217,26 +207,33 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
"Creating new local tt entry: %pM (ttvn: %d)
\n
"
,
addr
,
(
uint8_t
)
atomic_read
(
&
bat_priv
->
ttvn
));
memcpy
(
tt_local_entry
->
addr
,
addr
,
ETH_ALEN
);
tt_local_entry
->
last_seen
=
jiffies
;
tt_local_entry
->
flags
=
NO_FLAGS
;
memcpy
(
tt_local_entry
->
common
.
addr
,
addr
,
ETH_ALEN
);
tt_local_entry
->
common
.
flags
=
NO_FLAGS
;
if
(
is_wifi_iface
(
ifindex
))
tt_local_entry
->
flags
|=
TT_CLIENT_WIFI
;
atomic_set
(
&
tt_local_entry
->
refcount
,
2
);
tt_local_entry
->
common
.
flags
|=
TT_CLIENT_WIFI
;
atomic_set
(
&
tt_local_entry
->
common
.
refcount
,
2
);
tt_local_entry
->
last_seen
=
jiffies
;
/* the batman interface mac address should never be purged */
if
(
compare_eth
(
addr
,
soft_iface
->
dev_addr
))
tt_local_entry
->
flags
|=
TT_CLIENT_NOPURGE
;
tt_local_entry
->
common
.
flags
|=
TT_CLIENT_NOPURGE
;
tt_local_event
(
bat_priv
,
addr
,
tt_local_entry
->
flags
);
hash_added
=
hash_add
(
bat_priv
->
tt_local_hash
,
compare_tt
,
choose_orig
,
&
tt_local_entry
->
common
,
&
tt_local_entry
->
common
.
hash_entry
);
if
(
unlikely
(
hash_added
!=
0
))
{
/* remove the reference for the hash */
tt_local_entry_free_ref
(
tt_local_entry
);
goto
out
;
}
tt_local_event
(
bat_priv
,
addr
,
tt_local_entry
->
common
.
flags
);
/* The local entry has to be marked as NEW to avoid to send it in
* a full table response going out before the next ttvn increment
* (consistency check) */
tt_local_entry
->
flags
|=
TT_CLIENT_NEW
;
hash_add
(
bat_priv
->
tt_local_hash
,
compare_ltt
,
choose_orig
,
tt_local_entry
,
&
tt_local_entry
->
hash_entry
);
tt_local_entry
->
common
.
flags
|=
TT_CLIENT_NEW
;
/* remove address from global hash if present */
tt_global_entry
=
tt_global_hash_find
(
bat_priv
,
addr
);
...
...
@@ -247,8 +244,8 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
tt_global_entry
->
orig_node
->
tt_poss_change
=
true
;
/* The global entry has to be marked as PENDING and has to be
* kept for consistency purpose */
tt_global_entry
->
flags
|=
TT_CLIENT_PENDING
;
send_roam_adv
(
bat_priv
,
tt_global_entry
->
addr
,
tt_global_entry
->
common
.
flags
|=
TT_CLIENT_PENDING
;
send_roam_adv
(
bat_priv
,
tt_global_entry
->
common
.
addr
,
tt_global_entry
->
orig_node
);
}
out:
...
...
@@ -310,7 +307,7 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
struct
net_device
*
net_dev
=
(
struct
net_device
*
)
seq
->
private
;
struct
bat_priv
*
bat_priv
=
netdev_priv
(
net_dev
);
struct
hashtable_t
*
hash
=
bat_priv
->
tt_local_hash
;
struct
tt_
local_entry
*
tt_local
_entry
;
struct
tt_
common_entry
*
tt_common
_entry
;
struct
hard_iface
*
primary_if
;
struct
hlist_node
*
node
;
struct
hlist_head
*
head
;
...
...
@@ -340,19 +337,19 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
head
=
&
hash
->
table
[
i
];
rcu_read_lock
();
hlist_for_each_entry_rcu
(
tt_
local
_entry
,
node
,
hlist_for_each_entry_rcu
(
tt_
common
_entry
,
node
,
head
,
hash_entry
)
{
seq_printf
(
seq
,
" * %pM [%c%c%c%c%c]
\n
"
,
tt_
local
_entry
->
addr
,
(
tt_
local
_entry
->
flags
&
tt_
common
_entry
->
addr
,
(
tt_
common
_entry
->
flags
&
TT_CLIENT_ROAM
?
'R'
:
'.'
),
(
tt_
local
_entry
->
flags
&
(
tt_
common
_entry
->
flags
&
TT_CLIENT_NOPURGE
?
'P'
:
'.'
),
(
tt_
local
_entry
->
flags
&
(
tt_
common
_entry
->
flags
&
TT_CLIENT_NEW
?
'N'
:
'.'
),
(
tt_
local
_entry
->
flags
&
(
tt_
common
_entry
->
flags
&
TT_CLIENT_PENDING
?
'X'
:
'.'
),
(
tt_
local
_entry
->
flags
&
(
tt_
common
_entry
->
flags
&
TT_CLIENT_WIFI
?
'W'
:
'.'
));
}
rcu_read_unlock
();
...
...
@@ -367,13 +364,13 @@ static void tt_local_set_pending(struct bat_priv *bat_priv,
struct
tt_local_entry
*
tt_local_entry
,
uint16_t
flags
)
{
tt_local_event
(
bat_priv
,
tt_local_entry
->
addr
,
tt_local_entry
->
flags
|
flags
);
tt_local_event
(
bat_priv
,
tt_local_entry
->
common
.
addr
,
tt_local_entry
->
common
.
flags
|
flags
);
/* The local client has to be marked as "pending to be removed" but has
* to be kept in the table in order to send it in a full table
* response issued before the net ttvn increment (consistency check) */
tt_local_entry
->
flags
|=
TT_CLIENT_PENDING
;
tt_local_entry
->
common
.
flags
|=
TT_CLIENT_PENDING
;
}
void
tt_local_remove
(
struct
bat_priv
*
bat_priv
,
const
uint8_t
*
addr
,
...
...
@@ -389,7 +386,7 @@ void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr,
(
roaming
?
TT_CLIENT_ROAM
:
NO_FLAGS
));
bat_dbg
(
DBG_TT
,
bat_priv
,
"Local tt entry (%pM) pending to be removed: "
"%s
\n
"
,
tt_local_entry
->
addr
,
message
);
"%s
\n
"
,
tt_local_entry
->
common
.
addr
,
message
);
out:
if
(
tt_local_entry
)
tt_local_entry_free_ref
(
tt_local_entry
);
...
...
@@ -399,6 +396,7 @@ static void tt_local_purge(struct bat_priv *bat_priv)
{
struct
hashtable_t
*
hash
=
bat_priv
->
tt_local_hash
;
struct
tt_local_entry
*
tt_local_entry
;
struct
tt_common_entry
*
tt_common_entry
;
struct
hlist_node
*
node
,
*
node_tmp
;
struct
hlist_head
*
head
;
spinlock_t
*
list_lock
;
/* protects write access to the hash lists */
...
...
@@ -409,13 +407,16 @@ static void tt_local_purge(struct bat_priv *bat_priv)
list_lock
=
&
hash
->
list_locks
[
i
];
spin_lock_bh
(
list_lock
);
hlist_for_each_entry_safe
(
tt_
local
_entry
,
node
,
node_tmp
,
hlist_for_each_entry_safe
(
tt_
common
_entry
,
node
,
node_tmp
,
head
,
hash_entry
)
{
if
(
tt_local_entry
->
flags
&
TT_CLIENT_NOPURGE
)
tt_local_entry
=
container_of
(
tt_common_entry
,
struct
tt_local_entry
,
common
);
if
(
tt_local_entry
->
common
.
flags
&
TT_CLIENT_NOPURGE
)
continue
;
/* entry already marked for deletion */
if
(
tt_local_entry
->
flags
&
TT_CLIENT_PENDING
)
if
(
tt_local_entry
->
common
.
flags
&
TT_CLIENT_PENDING
)
continue
;
if
(
!
is_out_of_time
(
tt_local_entry
->
last_seen
,
...
...
@@ -426,7 +427,7 @@ static void tt_local_purge(struct bat_priv *bat_priv)
TT_CLIENT_DEL
);
bat_dbg
(
DBG_TT
,
bat_priv
,
"Local tt entry (%pM) "
"pending to be removed: timed out
\n
"
,
tt_local_entry
->
addr
);
tt_local_entry
->
common
.
addr
);
}
spin_unlock_bh
(
list_lock
);
}
...
...
@@ -437,6 +438,7 @@ static void tt_local_table_free(struct bat_priv *bat_priv)
{
struct
hashtable_t
*
hash
;
spinlock_t
*
list_lock
;
/* protects write access to the hash lists */
struct
tt_common_entry
*
tt_common_entry
;
struct
tt_local_entry
*
tt_local_entry
;
struct
hlist_node
*
node
,
*
node_tmp
;
struct
hlist_head
*
head
;
...
...
@@ -452,9 +454,12 @@ static void tt_local_table_free(struct bat_priv *bat_priv)
list_lock
=
&
hash
->
list_locks
[
i
];
spin_lock_bh
(
list_lock
);
hlist_for_each_entry_safe
(
tt_
local
_entry
,
node
,
node_tmp
,
hlist_for_each_entry_safe
(
tt_
common
_entry
,
node
,
node_tmp
,
head
,
hash_entry
)
{
hlist_del_rcu
(
node
);
tt_local_entry
=
container_of
(
tt_common_entry
,
struct
tt_local_entry
,
common
);
tt_local_entry_free_ref
(
tt_local_entry
);
}
spin_unlock_bh
(
list_lock
);
...
...
@@ -502,6 +507,7 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
struct
tt_global_entry
*
tt_global_entry
;
struct
orig_node
*
orig_node_tmp
;
int
ret
=
0
;
int
hash_added
;
tt_global_entry
=
tt_global_hash_find
(
bat_priv
,
tt_addr
);
...
...
@@ -512,18 +518,24 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
if
(
!
tt_global_entry
)
goto
out
;
memcpy
(
tt_global_entry
->
addr
,
tt_addr
,
ETH_ALEN
);
memcpy
(
tt_global_entry
->
common
.
addr
,
tt_addr
,
ETH_ALEN
);
tt_global_entry
->
common
.
flags
=
NO_FLAGS
;
atomic_set
(
&
tt_global_entry
->
common
.
refcount
,
2
);
/* Assign the new orig_node */
atomic_inc
(
&
orig_node
->
refcount
);
tt_global_entry
->
orig_node
=
orig_node
;
tt_global_entry
->
ttvn
=
ttvn
;
tt_global_entry
->
flags
=
NO_FLAGS
;
tt_global_entry
->
roam_at
=
0
;
atomic_set
(
&
tt_global_entry
->
refcount
,
2
);
hash_add
(
bat_priv
->
tt_global_hash
,
compare_gtt
,
choose_orig
,
tt_global_entry
,
&
tt_global_entry
->
hash_entry
);
hash_added
=
hash_add
(
bat_priv
->
tt_global_hash
,
compare_tt
,
choose_orig
,
&
tt_global_entry
->
common
,
&
tt_global_entry
->
common
.
hash_entry
);
if
(
unlikely
(
hash_added
!=
0
))
{
/* remove the reference for the hash */
tt_global_entry_free_ref
(
tt_global_entry
);
goto
out_remove
;
}
atomic_inc
(
&
orig_node
->
tt_size
);
}
else
{
if
(
tt_global_entry
->
orig_node
!=
orig_node
)
{
...
...
@@ -534,20 +546,21 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
orig_node_free_ref
(
orig_node_tmp
);
atomic_inc
(
&
orig_node
->
tt_size
);
}
tt_global_entry
->
common
.
flags
=
NO_FLAGS
;
tt_global_entry
->
ttvn
=
ttvn
;
tt_global_entry
->
flags
=
NO_FLAGS
;
tt_global_entry
->
roam_at
=
0
;
}
if
(
wifi
)
tt_global_entry
->
flags
|=
TT_CLIENT_WIFI
;
tt_global_entry
->
common
.
flags
|=
TT_CLIENT_WIFI
;
bat_dbg
(
DBG_TT
,
bat_priv
,
"Creating new global tt entry: %pM (via %pM)
\n
"
,
tt_global_entry
->
addr
,
orig_node
->
orig
);
tt_global_entry
->
common
.
addr
,
orig_node
->
orig
);
out_remove:
/* remove address from local hash if present */
tt_local_remove
(
bat_priv
,
tt_global_entry
->
addr
,
tt_local_remove
(
bat_priv
,
tt_global_entry
->
common
.
addr
,
"global tt received"
,
roaming
);
ret
=
1
;
out:
...
...
@@ -561,6 +574,7 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
struct
net_device
*
net_dev
=
(
struct
net_device
*
)
seq
->
private
;
struct
bat_priv
*
bat_priv
=
netdev_priv
(
net_dev
);
struct
hashtable_t
*
hash
=
bat_priv
->
tt_global_hash
;
struct
tt_common_entry
*
tt_common_entry
;
struct
tt_global_entry
*
tt_global_entry
;
struct
hard_iface
*
primary_if
;
struct
hlist_node
*
node
;
...
...
@@ -593,20 +607,24 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
head
=
&
hash
->
table
[
i
];
rcu_read_lock
();
hlist_for_each_entry_rcu
(
tt_
global
_entry
,
node
,
hlist_for_each_entry_rcu
(
tt_
common
_entry
,
node
,
head
,
hash_entry
)
{
tt_global_entry
=
container_of
(
tt_common_entry
,
struct
tt_global_entry
,
common
);
seq_printf
(
seq
,
" * %pM (%3u) via %pM (%3u) "
"[%c%c%c]
\n
"
,
tt_global_entry
->
addr
,
"[%c%c%c]
\n
"
,
tt_global_entry
->
common
.
addr
,
tt_global_entry
->
ttvn
,
tt_global_entry
->
orig_node
->
orig
,
(
uint8_t
)
atomic_read
(
&
tt_global_entry
->
orig_node
->
last_ttvn
),
(
tt_global_entry
->
flags
&
(
tt_global_entry
->
common
.
flags
&
TT_CLIENT_ROAM
?
'R'
:
'.'
),
(
tt_global_entry
->
flags
&
(
tt_global_entry
->
common
.
flags
&
TT_CLIENT_PENDING
?
'X'
:
'.'
),
(
tt_global_entry
->
flags
&
(
tt_global_entry
->
common
.
flags
&
TT_CLIENT_WIFI
?
'W'
:
'.'
));
}
rcu_read_unlock
();
...
...
@@ -626,13 +644,13 @@ static void _tt_global_del(struct bat_priv *bat_priv,
bat_dbg
(
DBG_TT
,
bat_priv
,
"Deleting global tt entry %pM (via %pM): %s
\n
"
,
tt_global_entry
->
addr
,
tt_global_entry
->
orig_node
->
orig
,
tt_global_entry
->
common
.
addr
,
tt_global_entry
->
orig_node
->
orig
,
message
);
atomic_dec
(
&
tt_global_entry
->
orig_node
->
tt_size
);
hash_remove
(
bat_priv
->
tt_global_hash
,
compare_
g
tt
,
choose_orig
,
tt_global_entry
->
addr
);
hash_remove
(
bat_priv
->
tt_global_hash
,
compare_tt
,
choose_orig
,
tt_global_entry
->
common
.
addr
);
out:
if
(
tt_global_entry
)
tt_global_entry_free_ref
(
tt_global_entry
);
...
...
@@ -650,7 +668,7 @@ void tt_global_del(struct bat_priv *bat_priv,
if
(
tt_global_entry
->
orig_node
==
orig_node
)
{
if
(
roaming
)
{
tt_global_entry
->
flags
|=
TT_CLIENT_ROAM
;
tt_global_entry
->
common
.
flags
|=
TT_CLIENT_ROAM
;
tt_global_entry
->
roam_at
=
jiffies
;
goto
out
;
}
...
...
@@ -665,6 +683,7 @@ void tt_global_del_orig(struct bat_priv *bat_priv,
struct
orig_node
*
orig_node
,
const
char
*
message
)
{
struct
tt_global_entry
*
tt_global_entry
;
struct
tt_common_entry
*
tt_common_entry
;
uint32_t
i
;
struct
hashtable_t
*
hash
=
bat_priv
->
tt_global_hash
;
struct
hlist_node
*
node
,
*
safe
;
...
...
@@ -679,13 +698,16 @@ void tt_global_del_orig(struct bat_priv *bat_priv,
list_lock
=
&
hash
->
list_locks
[
i
];
spin_lock_bh
(
list_lock
);
hlist_for_each_entry_safe
(
tt_
global
_entry
,
node
,
safe
,
hlist_for_each_entry_safe
(
tt_
common
_entry
,
node
,
safe
,
head
,
hash_entry
)
{
tt_global_entry
=
container_of
(
tt_common_entry
,
struct
tt_global_entry
,
common
);
if
(
tt_global_entry
->
orig_node
==
orig_node
)
{
bat_dbg
(
DBG_TT
,
bat_priv
,
"Deleting global tt entry %pM "
"(via %pM): %s
\n
"
,
tt_global_entry
->
addr
,
tt_global_entry
->
common
.
addr
,
tt_global_entry
->
orig_node
->
orig
,
message
);
hlist_del_rcu
(
node
);
...
...
@@ -700,6 +722,7 @@ void tt_global_del_orig(struct bat_priv *bat_priv,
static
void
tt_global_roam_purge
(
struct
bat_priv
*
bat_priv
)
{
struct
hashtable_t
*
hash
=
bat_priv
->
tt_global_hash
;
struct
tt_common_entry
*
tt_common_entry
;
struct
tt_global_entry
*
tt_global_entry
;
struct
hlist_node
*
node
,
*
node_tmp
;
struct
hlist_head
*
head
;
...
...
@@ -711,9 +734,12 @@ static void tt_global_roam_purge(struct bat_priv *bat_priv)
list_lock
=
&
hash
->
list_locks
[
i
];
spin_lock_bh
(
list_lock
);
hlist_for_each_entry_safe
(
tt_
global
_entry
,
node
,
node_tmp
,
hlist_for_each_entry_safe
(
tt_
common
_entry
,
node
,
node_tmp
,
head
,
hash_entry
)
{
if
(
!
(
tt_global_entry
->
flags
&
TT_CLIENT_ROAM
))
tt_global_entry
=
container_of
(
tt_common_entry
,
struct
tt_global_entry
,
common
);
if
(
!
(
tt_global_entry
->
common
.
flags
&
TT_CLIENT_ROAM
))
continue
;
if
(
!
is_out_of_time
(
tt_global_entry
->
roam_at
,
TT_CLIENT_ROAM_TIMEOUT
*
1000
))
...
...
@@ -721,7 +747,7 @@ static void tt_global_roam_purge(struct bat_priv *bat_priv)
bat_dbg
(
DBG_TT
,
bat_priv
,
"Deleting global "
"tt entry (%pM): Roaming timeout
\n
"
,
tt_global_entry
->
addr
);
tt_global_entry
->
common
.
addr
);
atomic_dec
(
&
tt_global_entry
->
orig_node
->
tt_size
);
hlist_del_rcu
(
node
);
tt_global_entry_free_ref
(
tt_global_entry
);
...
...
@@ -735,6 +761,7 @@ static void tt_global_table_free(struct bat_priv *bat_priv)
{
struct
hashtable_t
*
hash
;
spinlock_t
*
list_lock
;
/* protects write access to the hash lists */
struct
tt_common_entry
*
tt_common_entry
;
struct
tt_global_entry
*
tt_global_entry
;
struct
hlist_node
*
node
,
*
node_tmp
;
struct
hlist_head
*
head
;
...
...
@@ -750,9 +777,12 @@ static void tt_global_table_free(struct bat_priv *bat_priv)
list_lock
=
&
hash
->
list_locks
[
i
];
spin_lock_bh
(
list_lock
);
hlist_for_each_entry_safe
(
tt_
global
_entry
,
node
,
node_tmp
,
hlist_for_each_entry_safe
(
tt_
common
_entry
,
node
,
node_tmp
,
head
,
hash_entry
)
{
hlist_del_rcu
(
node
);
tt_global_entry
=
container_of
(
tt_common_entry
,
struct
tt_global_entry
,
common
);
tt_global_entry_free_ref
(
tt_global_entry
);
}
spin_unlock_bh
(
list_lock
);
...
...
@@ -768,8 +798,8 @@ static bool _is_ap_isolated(struct tt_local_entry *tt_local_entry,
{
bool
ret
=
false
;
if
(
tt_local_entry
->
flags
&
TT_CLIENT_WIFI
&&
tt_global_entry
->
flags
&
TT_CLIENT_WIFI
)
if
(
tt_local_entry
->
common
.
flags
&
TT_CLIENT_WIFI
&&
tt_global_entry
->
common
.
flags
&
TT_CLIENT_WIFI
)
ret
=
true
;
return
ret
;
...
...
@@ -802,7 +832,7 @@ struct orig_node *transtable_search(struct bat_priv *bat_priv,
/* A global client marked as PENDING has already moved from that
* originator */
if
(
tt_global_entry
->
flags
&
TT_CLIENT_PENDING
)
if
(
tt_global_entry
->
common
.
flags
&
TT_CLIENT_PENDING
)
goto
out
;
orig_node
=
tt_global_entry
->
orig_node
;
...
...
@@ -821,6 +851,7 @@ uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node)
{
uint16_t
total
=
0
,
total_one
;
struct
hashtable_t
*
hash
=
bat_priv
->
tt_global_hash
;
struct
tt_common_entry
*
tt_common_entry
;
struct
tt_global_entry
*
tt_global_entry
;
struct
hlist_node
*
node
;
struct
hlist_head
*
head
;
...
...
@@ -831,20 +862,23 @@ uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node)
head
=
&
hash
->
table
[
i
];
rcu_read_lock
();
hlist_for_each_entry_rcu
(
tt_
global
_entry
,
node
,
hlist_for_each_entry_rcu
(
tt_
common
_entry
,
node
,
head
,
hash_entry
)
{
tt_global_entry
=
container_of
(
tt_common_entry
,
struct
tt_global_entry
,
common
);
if
(
compare_eth
(
tt_global_entry
->
orig_node
,
orig_node
))
{
/* Roaming clients are in the global table for
* consistency only. They don't have to be
* taken into account while computing the
* global crc */
if
(
tt_
global
_entry
->
flags
&
TT_CLIENT_ROAM
)
if
(
tt_
common
_entry
->
flags
&
TT_CLIENT_ROAM
)
continue
;
total_one
=
0
;
for
(
j
=
0
;
j
<
ETH_ALEN
;
j
++
)
total_one
=
crc16_byte
(
total_one
,
tt_
global
_entry
->
addr
[
j
]);
tt_
common
_entry
->
addr
[
j
]);
total
^=
total_one
;
}
}
...
...
@@ -859,7 +893,7 @@ uint16_t tt_local_crc(struct bat_priv *bat_priv)
{
uint16_t
total
=
0
,
total_one
;
struct
hashtable_t
*
hash
=
bat_priv
->
tt_local_hash
;
struct
tt_
local_entry
*
tt_local
_entry
;
struct
tt_
common_entry
*
tt_common
_entry
;
struct
hlist_node
*
node
;
struct
hlist_head
*
head
;
uint32_t
i
;
...
...
@@ -869,16 +903,16 @@ uint16_t tt_local_crc(struct bat_priv *bat_priv)
head
=
&
hash
->
table
[
i
];
rcu_read_lock
();
hlist_for_each_entry_rcu
(
tt_
local
_entry
,
node
,
hlist_for_each_entry_rcu
(
tt_
common
_entry
,
node
,
head
,
hash_entry
)
{
/* not yet committed clients have not to be taken into
* account while computing the CRC */
if
(
tt_
local
_entry
->
flags
&
TT_CLIENT_NEW
)
if
(
tt_
common
_entry
->
flags
&
TT_CLIENT_NEW
)
continue
;
total_one
=
0
;
for
(
j
=
0
;
j
<
ETH_ALEN
;
j
++
)
total_one
=
crc16_byte
(
total_one
,
tt_
local
_entry
->
addr
[
j
]);
tt_
common
_entry
->
addr
[
j
]);
total
^=
total_one
;
}
rcu_read_unlock
();
...
...
@@ -967,21 +1001,25 @@ static struct tt_req_node *new_tt_req_node(struct bat_priv *bat_priv,
/* data_ptr is useless here, but has to be kept to respect the prototype */
static
int
tt_local_valid_entry
(
const
void
*
entry_ptr
,
const
void
*
data_ptr
)
{
const
struct
tt_
local_entry
*
tt_local
_entry
=
entry_ptr
;
const
struct
tt_
common_entry
*
tt_common
_entry
=
entry_ptr
;
if
(
tt_
local
_entry
->
flags
&
TT_CLIENT_NEW
)
if
(
tt_
common
_entry
->
flags
&
TT_CLIENT_NEW
)
return
0
;
return
1
;
}
static
int
tt_global_valid_entry
(
const
void
*
entry_ptr
,
const
void
*
data_ptr
)
{
const
struct
tt_global_entry
*
tt_global_entry
=
entry_ptr
;
const
struct
tt_common_entry
*
tt_common_entry
=
entry_ptr
;
const
struct
tt_global_entry
*
tt_global_entry
;
const
struct
orig_node
*
orig_node
=
data_ptr
;
if
(
tt_
global
_entry
->
flags
&
TT_CLIENT_ROAM
)
if
(
tt_
common
_entry
->
flags
&
TT_CLIENT_ROAM
)
return
0
;
tt_global_entry
=
container_of
(
tt_common_entry
,
struct
tt_global_entry
,
common
);
return
(
tt_global_entry
->
orig_node
==
orig_node
);
}
...
...
@@ -992,7 +1030,7 @@ static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
const
void
*
),
void
*
cb_data
)
{
struct
tt_
local_entry
*
tt_local
_entry
;
struct
tt_
common_entry
*
tt_common
_entry
;
struct
tt_query_packet
*
tt_response
;
struct
tt_change
*
tt_change
;
struct
hlist_node
*
node
;
...
...
@@ -1024,15 +1062,16 @@ static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
for
(
i
=
0
;
i
<
hash
->
size
;
i
++
)
{
head
=
&
hash
->
table
[
i
];
hlist_for_each_entry_rcu
(
tt_
local
_entry
,
node
,
hlist_for_each_entry_rcu
(
tt_
common
_entry
,
node
,
head
,
hash_entry
)
{
if
(
tt_count
==
tt_tot
)
break
;
if
((
valid_cb
)
&&
(
!
valid_cb
(
tt_
local
_entry
,
cb_data
)))
if
((
valid_cb
)
&&
(
!
valid_cb
(
tt_
common
_entry
,
cb_data
)))
continue
;
memcpy
(
tt_change
->
addr
,
tt_local_entry
->
addr
,
ETH_ALEN
);
memcpy
(
tt_change
->
addr
,
tt_common_entry
->
addr
,
ETH_ALEN
);
tt_change
->
flags
=
NO_FLAGS
;
tt_count
++
;
...
...
@@ -1449,7 +1488,7 @@ bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr)
goto
out
;
/* Check if the client has been logically deleted (but is kept for
* consistency purpose) */
if
(
tt_local_entry
->
flags
&
TT_CLIENT_PENDING
)
if
(
tt_local_entry
->
common
.
flags
&
TT_CLIENT_PENDING
)
goto
out
;
ret
=
true
;
out:
...
...
@@ -1672,40 +1711,48 @@ void tt_free(struct bat_priv *bat_priv)
kfree
(
bat_priv
->
tt_buff
);
}
/* This function will
reset the specified flags from all the entries in
*
the given hash table and will increment num_local_tt for each involved
* entry */
static
void
tt_local_reset_flags
(
struct
bat_priv
*
bat_priv
,
uint16_t
flags
)
/* This function will
enable or disable the specified flags for all the entries
*
in the given hash table and returns the number of modified entries */
static
uint16_t
tt_set_flags
(
struct
hashtable_t
*
hash
,
uint16_t
flags
,
bool
enable
)
{
uint32_t
i
;
struct
hashtable_t
*
hash
=
bat_priv
->
tt_local_hash
;
uint16_t
changed_num
=
0
;
struct
hlist_head
*
head
;
struct
hlist_node
*
node
;
struct
tt_
local_entry
*
tt_local
_entry
;
struct
tt_
common_entry
*
tt_common
_entry
;
if
(
!
hash
)
return
;
goto
out
;
for
(
i
=
0
;
i
<
hash
->
size
;
i
++
)
{
head
=
&
hash
->
table
[
i
];
rcu_read_lock
();
hlist_for_each_entry_rcu
(
tt_
local
_entry
,
node
,
hlist_for_each_entry_rcu
(
tt_
common
_entry
,
node
,
head
,
hash_entry
)
{
if
(
!
(
tt_local_entry
->
flags
&
flags
))
continue
;
tt_local_entry
->
flags
&=
~
flags
;
atomic_inc
(
&
bat_priv
->
num_local_tt
);
if
(
enable
)
{
if
((
tt_common_entry
->
flags
&
flags
)
==
flags
)
continue
;
tt_common_entry
->
flags
|=
flags
;
}
else
{
if
(
!
(
tt_common_entry
->
flags
&
flags
))
continue
;
tt_common_entry
->
flags
&=
~
flags
;
}
changed_num
++
;
}
rcu_read_unlock
();
}
out:
return
changed_num
;
}
/* Purge out all the tt local entries marked with TT_CLIENT_PENDING */
static
void
tt_local_purge_pending_clients
(
struct
bat_priv
*
bat_priv
)
{
struct
hashtable_t
*
hash
=
bat_priv
->
tt_local_hash
;
struct
tt_common_entry
*
tt_common_entry
;
struct
tt_local_entry
*
tt_local_entry
;
struct
hlist_node
*
node
,
*
node_tmp
;
struct
hlist_head
*
head
;
...
...
@@ -1720,16 +1767,19 @@ static void tt_local_purge_pending_clients(struct bat_priv *bat_priv)
list_lock
=
&
hash
->
list_locks
[
i
];
spin_lock_bh
(
list_lock
);
hlist_for_each_entry_safe
(
tt_
local
_entry
,
node
,
node_tmp
,
hlist_for_each_entry_safe
(
tt_
common
_entry
,
node
,
node_tmp
,
head
,
hash_entry
)
{
if
(
!
(
tt_
local
_entry
->
flags
&
TT_CLIENT_PENDING
))
if
(
!
(
tt_
common
_entry
->
flags
&
TT_CLIENT_PENDING
))
continue
;
bat_dbg
(
DBG_TT
,
bat_priv
,
"Deleting local tt entry "
"(%pM): pending
\n
"
,
tt_
local
_entry
->
addr
);
"(%pM): pending
\n
"
,
tt_
common
_entry
->
addr
);
atomic_dec
(
&
bat_priv
->
num_local_tt
);
hlist_del_rcu
(
node
);
tt_local_entry
=
container_of
(
tt_common_entry
,
struct
tt_local_entry
,
common
);
tt_local_entry_free_ref
(
tt_local_entry
);
}
spin_unlock_bh
(
list_lock
);
...
...
@@ -1739,7 +1789,11 @@ static void tt_local_purge_pending_clients(struct bat_priv *bat_priv)
void
tt_commit_changes
(
struct
bat_priv
*
bat_priv
)
{
tt_local_reset_flags
(
bat_priv
,
TT_CLIENT_NEW
);
uint16_t
changed_num
=
tt_set_flags
(
bat_priv
->
tt_local_hash
,
TT_CLIENT_NEW
,
false
);
/* all the reset entries have now to be effectively counted as local
* entries */
atomic_add
(
changed_num
,
&
bat_priv
->
num_local_tt
);
tt_local_purge_pending_clients
(
bat_priv
);
/* Increment the TTVN only once per OGM interval */
...
...
net/batman-adv/types.h
View file @
c7c6575f
...
...
@@ -222,24 +222,24 @@ struct socket_packet {
struct
icmp_packet_rr
icmp_packet
;
};
struct
tt_
local
_entry
{
struct
tt_
common
_entry
{
uint8_t
addr
[
ETH_ALEN
];
struct
hlist_node
hash_entry
;
unsigned
long
last_seen
;
uint16_t
flags
;
atomic_t
refcount
;
struct
rcu_head
rcu
;
};
struct
tt_local_entry
{
struct
tt_common_entry
common
;
unsigned
long
last_seen
;
};
struct
tt_global_entry
{
uint8_t
addr
[
ETH_ALEN
];
struct
hlist_node
hash_entry
;
/* entry in the global table */
struct
tt_common_entry
common
;
struct
orig_node
*
orig_node
;
uint8_t
ttvn
;
uint16_t
flags
;
/* only TT_GLOBAL_ROAM is used */
unsigned
long
roam_at
;
/* time at which TT_GLOBAL_ROAM was set */
atomic_t
refcount
;
struct
rcu_head
rcu
;
};
struct
tt_change_node
{
...
...
net/batman-adv/vis.c
View file @
c7c6575f
...
...
@@ -609,7 +609,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
struct
vis_info
*
info
=
bat_priv
->
my_vis_info
;
struct
vis_packet
*
packet
=
(
struct
vis_packet
*
)
info
->
skb_packet
->
data
;
struct
vis_info_entry
*
entry
;
struct
tt_
local_entry
*
tt_local
_entry
;
struct
tt_
common_entry
*
tt_common
_entry
;
int
best_tq
=
-
1
;
uint32_t
i
;
...
...
@@ -672,13 +672,13 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
head
=
&
hash
->
table
[
i
];
rcu_read_lock
();
hlist_for_each_entry_rcu
(
tt_
local
_entry
,
node
,
head
,
hlist_for_each_entry_rcu
(
tt_
common
_entry
,
node
,
head
,
hash_entry
)
{
entry
=
(
struct
vis_info_entry
*
)
skb_put
(
info
->
skb_packet
,
sizeof
(
*
entry
));
memset
(
entry
->
src
,
0
,
ETH_ALEN
);
memcpy
(
entry
->
dest
,
tt_
local
_entry
->
addr
,
ETH_ALEN
);
memcpy
(
entry
->
dest
,
tt_
common
_entry
->
addr
,
ETH_ALEN
);
entry
->
quality
=
0
;
/* 0 means TT */
packet
->
entries
++
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment