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
nexedi
linux
Commits
3f9aed7c
Commit
3f9aed7c
authored
Jul 08, 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
31817df0
a7f9becb
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
147 additions
and
32 deletions
+147
-32
net/batman-adv/originator.c
net/batman-adv/originator.c
+2
-0
net/batman-adv/packet.h
net/batman-adv/packet.h
+3
-1
net/batman-adv/routing.c
net/batman-adv/routing.c
+12
-0
net/batman-adv/send.c
net/batman-adv/send.c
+1
-3
net/batman-adv/translation-table.c
net/batman-adv/translation-table.c
+128
-28
net/batman-adv/translation-table.h
net/batman-adv/translation-table.h
+1
-0
No files found.
net/batman-adv/originator.c
View file @
3f9aed7c
...
@@ -223,6 +223,8 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr)
...
@@ -223,6 +223,8 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr)
orig_node
->
bat_priv
=
bat_priv
;
orig_node
->
bat_priv
=
bat_priv
;
memcpy
(
orig_node
->
orig
,
addr
,
ETH_ALEN
);
memcpy
(
orig_node
->
orig
,
addr
,
ETH_ALEN
);
orig_node
->
router
=
NULL
;
orig_node
->
router
=
NULL
;
orig_node
->
tt_crc
=
0
;
atomic_set
(
&
orig_node
->
last_ttvn
,
0
);
orig_node
->
tt_buff
=
NULL
;
orig_node
->
tt_buff
=
NULL
;
orig_node
->
tt_buff_len
=
0
;
orig_node
->
tt_buff_len
=
0
;
atomic_set
(
&
orig_node
->
tt_size
,
0
);
atomic_set
(
&
orig_node
->
tt_size
,
0
);
...
...
net/batman-adv/packet.h
View file @
3f9aed7c
...
@@ -84,7 +84,9 @@ enum tt_query_flags {
...
@@ -84,7 +84,9 @@ enum tt_query_flags {
enum
tt_client_flags
{
enum
tt_client_flags
{
TT_CLIENT_DEL
=
1
<<
0
,
TT_CLIENT_DEL
=
1
<<
0
,
TT_CLIENT_ROAM
=
1
<<
1
,
TT_CLIENT_ROAM
=
1
<<
1
,
TT_CLIENT_NOPURGE
=
1
<<
8
TT_CLIENT_NOPURGE
=
1
<<
8
,
TT_CLIENT_NEW
=
1
<<
9
,
TT_CLIENT_PENDING
=
1
<<
10
};
};
struct
batman_packet
{
struct
batman_packet
{
...
...
net/batman-adv/routing.c
View file @
3f9aed7c
...
@@ -91,6 +91,18 @@ static void update_transtable(struct bat_priv *bat_priv,
...
@@ -91,6 +91,18 @@ static void update_transtable(struct bat_priv *bat_priv,
* to recompute it to spot any possible inconsistency
* to recompute it to spot any possible inconsistency
* in the global table */
* in the global table */
orig_node
->
tt_crc
=
tt_global_crc
(
bat_priv
,
orig_node
);
orig_node
->
tt_crc
=
tt_global_crc
(
bat_priv
,
orig_node
);
/* The ttvn alone is not enough to guarantee consistency
* because a single value could repesent different states
* (due to the wrap around). Thus a node has to check whether
* the resulting table (after applying the changes) is still
* consistent or not. E.g. a node could disconnect while its
* ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
* checking the CRC value is mandatory to detect the
* inconsistency */
if
(
orig_node
->
tt_crc
!=
tt_crc
)
goto
request_table
;
/* Roaming phase is over: tables are in sync again. I can
/* Roaming phase is over: tables are in sync again. I can
* unset the flag */
* unset the flag */
orig_node
->
tt_poss_change
=
false
;
orig_node
->
tt_poss_change
=
false
;
...
...
net/batman-adv/send.c
View file @
3f9aed7c
...
@@ -309,10 +309,8 @@ void schedule_own_packet(struct hard_iface *hard_iface)
...
@@ -309,10 +309,8 @@ void schedule_own_packet(struct hard_iface *hard_iface)
if
(
hard_iface
==
primary_if
)
{
if
(
hard_iface
==
primary_if
)
{
/* if at least one change happened */
/* if at least one change happened */
if
(
atomic_read
(
&
bat_priv
->
tt_local_changes
)
>
0
)
{
if
(
atomic_read
(
&
bat_priv
->
tt_local_changes
)
>
0
)
{
tt_commit_changes
(
bat_priv
);
prepare_packet_buffer
(
bat_priv
,
hard_iface
);
prepare_packet_buffer
(
bat_priv
,
hard_iface
);
/* Increment the TTVN only once per OGM interval */
atomic_inc
(
&
bat_priv
->
ttvn
);
bat_priv
->
tt_poss_change
=
false
;
}
}
/* if the changes have been sent enough times */
/* if the changes have been sent enough times */
...
...
net/batman-adv/translation-table.c
View file @
3f9aed7c
...
@@ -215,11 +215,14 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr)
...
@@ -215,11 +215,14 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr)
tt_local_event
(
bat_priv
,
addr
,
tt_local_entry
->
flags
);
tt_local_event
(
bat_priv
,
addr
,
tt_local_entry
->
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
,
hash_add
(
bat_priv
->
tt_local_hash
,
compare_ltt
,
choose_orig
,
tt_local_entry
,
&
tt_local_entry
->
hash_entry
);
tt_local_entry
,
&
tt_local_entry
->
hash_entry
);
atomic_inc
(
&
bat_priv
->
num_local_tt
);
/* remove address from global hash if present */
/* remove address from global hash if present */
tt_global_entry
=
tt_global_hash_find
(
bat_priv
,
addr
);
tt_global_entry
=
tt_global_hash_find
(
bat_priv
,
addr
);
...
@@ -227,8 +230,9 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr)
...
@@ -227,8 +230,9 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr)
if
(
tt_global_entry
)
{
if
(
tt_global_entry
)
{
/* This node is probably going to update its tt table */
/* This node is probably going to update its tt table */
tt_global_entry
->
orig_node
->
tt_poss_change
=
true
;
tt_global_entry
->
orig_node
->
tt_poss_change
=
true
;
_tt_global_del
(
bat_priv
,
tt_global_entry
,
/* The global entry has to be marked as PENDING and has to be
"local tt received"
);
* kept for consistency purpose */
tt_global_entry
->
flags
|=
TT_CLIENT_PENDING
;
send_roam_adv
(
bat_priv
,
tt_global_entry
->
addr
,
send_roam_adv
(
bat_priv
,
tt_global_entry
->
addr
,
tt_global_entry
->
orig_node
);
tt_global_entry
->
orig_node
);
}
}
...
@@ -358,19 +362,17 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
...
@@ -358,19 +362,17 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
return
ret
;
return
ret
;
}
}
static
void
tt_local_
del
(
struct
bat_priv
*
bat_priv
,
static
void
tt_local_
set_pending
(
struct
bat_priv
*
bat_priv
,
struct
tt_local_entry
*
tt_local_entry
,
struct
tt_local_entry
*
tt_local_entry
,
const
char
*
message
)
uint16_t
flags
)
{
{
bat_dbg
(
DBG_TT
,
bat_priv
,
"Deleting local tt entry (%pM): %s
\n
"
,
tt_local_event
(
bat_priv
,
tt_local_entry
->
addr
,
tt_local_entry
->
addr
,
message
);
tt_local_entry
->
flags
|
flags
);
atomic_dec
(
&
bat_priv
->
num_local_tt
);
hash_remove
(
bat_priv
->
tt_local_hash
,
compare_ltt
,
choose_orig
,
tt_local_entry
->
addr
);
tt_local_entry_free_ref
(
tt_local_entry
);
/* The local client has to be merked as "pending to be removed" but has
* to be kept in the table in order to send it in an full tables
* response issued before the net ttvn increment (consistency check) */
tt_local_entry
->
flags
|=
TT_CLIENT_PENDING
;
}
}
void
tt_local_remove
(
struct
bat_priv
*
bat_priv
,
const
uint8_t
*
addr
,
void
tt_local_remove
(
struct
bat_priv
*
bat_priv
,
const
uint8_t
*
addr
,
...
@@ -379,14 +381,14 @@ void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr,
...
@@ -379,14 +381,14 @@ void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr,
struct
tt_local_entry
*
tt_local_entry
=
NULL
;
struct
tt_local_entry
*
tt_local_entry
=
NULL
;
tt_local_entry
=
tt_local_hash_find
(
bat_priv
,
addr
);
tt_local_entry
=
tt_local_hash_find
(
bat_priv
,
addr
);
if
(
!
tt_local_entry
)
if
(
!
tt_local_entry
)
goto
out
;
goto
out
;
tt_local_event
(
bat_priv
,
tt_local_entry
->
addr
,
tt_local_set_pending
(
bat_priv
,
tt_local_entry
,
TT_CLIENT_DEL
|
tt_local_entry
->
flags
|
TT_CLIENT_DEL
|
(
roaming
?
TT_CLIENT_ROAM
:
NO_FLAGS
));
(
roaming
?
TT_CLIENT_ROAM
:
NO_FLAGS
));
tt_local_del
(
bat_priv
,
tt_local_entry
,
message
);
bat_dbg
(
DBG_TT
,
bat_priv
,
"Local tt entry (%pM) pending to be removed: "
"%s
\n
"
,
tt_local_entry
->
addr
,
message
);
out:
out:
if
(
tt_local_entry
)
if
(
tt_local_entry
)
tt_local_entry_free_ref
(
tt_local_entry
);
tt_local_entry_free_ref
(
tt_local_entry
);
...
@@ -411,18 +413,19 @@ static void tt_local_purge(struct bat_priv *bat_priv)
...
@@ -411,18 +413,19 @@ static void tt_local_purge(struct bat_priv *bat_priv)
if
(
tt_local_entry
->
flags
&
TT_CLIENT_NOPURGE
)
if
(
tt_local_entry
->
flags
&
TT_CLIENT_NOPURGE
)
continue
;
continue
;
/* entry already marked for deletion */
if
(
tt_local_entry
->
flags
&
TT_CLIENT_PENDING
)
continue
;
if
(
!
is_out_of_time
(
tt_local_entry
->
last_seen
,
if
(
!
is_out_of_time
(
tt_local_entry
->
last_seen
,
TT_LOCAL_TIMEOUT
*
1000
))
TT_LOCAL_TIMEOUT
*
1000
))
continue
;
continue
;
tt_local_event
(
bat_priv
,
tt_local_entry
->
addr
,
tt_local_set_pending
(
bat_priv
,
tt_local_entry
,
tt_local_entry
->
flags
|
TT_CLIENT_DEL
);
TT_CLIENT_DEL
);
atomic_dec
(
&
bat_priv
->
num_local_tt
);
bat_dbg
(
DBG_TT
,
bat_priv
,
"Local tt entry (%pM) "
bat_dbg
(
DBG_TT
,
bat_priv
,
"Deleting local "
"pending to be removed: timed out
\n
"
,
"tt entry (%pM): timed out
\n
"
,
tt_local_entry
->
addr
);
tt_local_entry
->
addr
);
hlist_del_rcu
(
node
);
tt_local_entry_free_ref
(
tt_local_entry
);
}
}
spin_unlock_bh
(
list_lock
);
spin_unlock_bh
(
list_lock
);
}
}
...
@@ -785,6 +788,11 @@ struct orig_node *transtable_search(struct bat_priv *bat_priv,
...
@@ -785,6 +788,11 @@ struct orig_node *transtable_search(struct bat_priv *bat_priv,
if
(
!
atomic_inc_not_zero
(
&
tt_global_entry
->
orig_node
->
refcount
))
if
(
!
atomic_inc_not_zero
(
&
tt_global_entry
->
orig_node
->
refcount
))
goto
free_tt
;
goto
free_tt
;
/* A global client marked as PENDING has already moved from that
* originator */
if
(
tt_global_entry
->
flags
&
TT_CLIENT_PENDING
)
goto
free_tt
;
orig_node
=
tt_global_entry
->
orig_node
;
orig_node
=
tt_global_entry
->
orig_node
;
free_tt:
free_tt:
...
@@ -846,6 +854,10 @@ uint16_t tt_local_crc(struct bat_priv *bat_priv)
...
@@ -846,6 +854,10 @@ uint16_t tt_local_crc(struct bat_priv *bat_priv)
rcu_read_lock
();
rcu_read_lock
();
hlist_for_each_entry_rcu
(
tt_local_entry
,
node
,
hlist_for_each_entry_rcu
(
tt_local_entry
,
node
,
head
,
hash_entry
)
{
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
)
continue
;
total_one
=
0
;
total_one
=
0
;
for
(
j
=
0
;
j
<
ETH_ALEN
;
j
++
)
for
(
j
=
0
;
j
<
ETH_ALEN
;
j
++
)
total_one
=
crc16_byte
(
total_one
,
total_one
=
crc16_byte
(
total_one
,
...
@@ -935,6 +947,16 @@ static struct tt_req_node *new_tt_req_node(struct bat_priv *bat_priv,
...
@@ -935,6 +947,16 @@ static struct tt_req_node *new_tt_req_node(struct bat_priv *bat_priv,
return
tt_req_node
;
return
tt_req_node
;
}
}
/* 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
;
if
(
tt_local_entry
->
flags
&
TT_CLIENT_NEW
)
return
0
;
return
1
;
}
static
int
tt_global_valid_entry
(
const
void
*
entry_ptr
,
const
void
*
data_ptr
)
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_global_entry
*
tt_global_entry
=
entry_ptr
;
...
@@ -1275,7 +1297,8 @@ static bool send_my_tt_response(struct bat_priv *bat_priv,
...
@@ -1275,7 +1297,8 @@ static bool send_my_tt_response(struct bat_priv *bat_priv,
skb
=
tt_response_fill_table
(
tt_len
,
ttvn
,
skb
=
tt_response_fill_table
(
tt_len
,
ttvn
,
bat_priv
->
tt_local_hash
,
bat_priv
->
tt_local_hash
,
primary_if
,
NULL
,
NULL
);
primary_if
,
tt_local_valid_entry
,
NULL
);
if
(
!
skb
)
if
(
!
skb
)
goto
out
;
goto
out
;
...
@@ -1400,6 +1423,10 @@ bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr)
...
@@ -1400,6 +1423,10 @@ bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr)
tt_local_entry
=
tt_local_hash_find
(
bat_priv
,
addr
);
tt_local_entry
=
tt_local_hash_find
(
bat_priv
,
addr
);
if
(
!
tt_local_entry
)
if
(
!
tt_local_entry
)
goto
out
;
goto
out
;
/* Check if the client has been logically deleted (but is kept for
* consistency purpose) */
if
(
tt_local_entry
->
flags
&
TT_CLIENT_PENDING
)
goto
out
;
ret
=
true
;
ret
=
true
;
out:
out:
if
(
tt_local_entry
)
if
(
tt_local_entry
)
...
@@ -1620,3 +1647,76 @@ void tt_free(struct bat_priv *bat_priv)
...
@@ -1620,3 +1647,76 @@ void tt_free(struct bat_priv *bat_priv)
kfree
(
bat_priv
->
tt_buff
);
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
)
{
int
i
;
struct
hashtable_t
*
hash
=
bat_priv
->
tt_local_hash
;
struct
hlist_head
*
head
;
struct
hlist_node
*
node
;
struct
tt_local_entry
*
tt_local_entry
;
if
(
!
hash
)
return
;
for
(
i
=
0
;
i
<
hash
->
size
;
i
++
)
{
head
=
&
hash
->
table
[
i
];
rcu_read_lock
();
hlist_for_each_entry_rcu
(
tt_local_entry
,
node
,
head
,
hash_entry
)
{
tt_local_entry
->
flags
&=
~
flags
;
atomic_inc
(
&
bat_priv
->
num_local_tt
);
}
rcu_read_unlock
();
}
}
/* 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_local_entry
*
tt_local_entry
;
struct
hlist_node
*
node
,
*
node_tmp
;
struct
hlist_head
*
head
;
spinlock_t
*
list_lock
;
/* protects write access to the hash lists */
int
i
;
if
(
!
hash
)
return
;
for
(
i
=
0
;
i
<
hash
->
size
;
i
++
)
{
head
=
&
hash
->
table
[
i
];
list_lock
=
&
hash
->
list_locks
[
i
];
spin_lock_bh
(
list_lock
);
hlist_for_each_entry_safe
(
tt_local_entry
,
node
,
node_tmp
,
head
,
hash_entry
)
{
if
(
!
(
tt_local_entry
->
flags
&
TT_CLIENT_PENDING
))
continue
;
bat_dbg
(
DBG_TT
,
bat_priv
,
"Deleting local tt entry "
"(%pM): pending
\n
"
,
tt_local_entry
->
addr
);
atomic_dec
(
&
bat_priv
->
num_local_tt
);
hlist_del_rcu
(
node
);
tt_local_entry_free_ref
(
tt_local_entry
);
}
spin_unlock_bh
(
list_lock
);
}
}
void
tt_commit_changes
(
struct
bat_priv
*
bat_priv
)
{
tt_local_reset_flags
(
bat_priv
,
TT_CLIENT_NEW
);
tt_local_purge_pending_clients
(
bat_priv
);
/* Increment the TTVN only once per OGM interval */
atomic_inc
(
&
bat_priv
->
ttvn
);
bat_priv
->
tt_poss_change
=
false
;
}
net/batman-adv/translation-table.h
View file @
3f9aed7c
...
@@ -61,5 +61,6 @@ void handle_tt_response(struct bat_priv *bat_priv,
...
@@ -61,5 +61,6 @@ void handle_tt_response(struct bat_priv *bat_priv,
struct
tt_query_packet
*
tt_response
);
struct
tt_query_packet
*
tt_response
);
void
send_roam_adv
(
struct
bat_priv
*
bat_priv
,
uint8_t
*
client
,
void
send_roam_adv
(
struct
bat_priv
*
bat_priv
,
uint8_t
*
client
,
struct
orig_node
*
orig_node
);
struct
orig_node
*
orig_node
);
void
tt_commit_changes
(
struct
bat_priv
*
bat_priv
);
#endif
/* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
#endif
/* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
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