Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
9c6bc165
K
Kernel
项目概览
openeuler
/
Kernel
接近 2 年 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
9c6bc165
编写于
4月 17, 2011
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'batman-adv/next' of
git://git.open-mesh.org/ecsv/linux-merge
上级
03746b0a
af20b710
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
537 addition
and
393 deletion
+537
-393
net/batman-adv/gateway_client.c
net/batman-adv/gateway_client.c
+151
-108
net/batman-adv/gateway_client.h
net/batman-adv/gateway_client.h
+1
-1
net/batman-adv/icmp_socket.c
net/batman-adv/icmp_socket.c
+3
-15
net/batman-adv/originator.c
net/batman-adv/originator.c
+29
-9
net/batman-adv/originator.h
net/batman-adv/originator.h
+1
-0
net/batman-adv/routing.c
net/batman-adv/routing.c
+202
-176
net/batman-adv/send.c
net/batman-adv/send.c
+12
-7
net/batman-adv/soft-interface.c
net/batman-adv/soft-interface.c
+88
-27
net/batman-adv/types.h
net/batman-adv/types.h
+4
-3
net/batman-adv/unicast.c
net/batman-adv/unicast.c
+1
-1
net/batman-adv/vis.c
net/batman-adv/vis.c
+45
-46
未找到文件。
net/batman-adv/gateway_client.c
浏览文件 @
9c6bc165
...
@@ -23,6 +23,7 @@
...
@@ -23,6 +23,7 @@
#include "gateway_client.h"
#include "gateway_client.h"
#include "gateway_common.h"
#include "gateway_common.h"
#include "hard-interface.h"
#include "hard-interface.h"
#include "originator.h"
#include <linux/ip.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/ipv6.h>
#include <linux/udp.h>
#include <linux/udp.h>
...
@@ -42,61 +43,76 @@ static void gw_node_free_ref(struct gw_node *gw_node)
...
@@ -42,61 +43,76 @@ static void gw_node_free_ref(struct gw_node *gw_node)
call_rcu
(
&
gw_node
->
rcu
,
gw_node_free_rcu
);
call_rcu
(
&
gw_node
->
rcu
,
gw_node_free_rcu
);
}
}
void
*
gw_get_selected
(
struct
bat_priv
*
bat_priv
)
static
struct
gw_node
*
gw_get_selected_gw_node
(
struct
bat_priv
*
bat_priv
)
{
{
struct
gw_node
*
curr_gateway_tmp
;
struct
gw_node
*
gw_node
;
struct
orig_node
*
orig_node
=
NULL
;
rcu_read_lock
();
rcu_read_lock
();
curr_gateway_tmp
=
rcu_dereference
(
bat_priv
->
curr_gw
);
gw_node
=
rcu_dereference
(
bat_priv
->
curr_gw
);
if
(
!
curr_gateway_tmp
)
if
(
!
gw_node
)
goto
out
;
orig_node
=
curr_gateway_tmp
->
orig_node
;
if
(
!
orig_node
)
goto
out
;
goto
out
;
if
(
!
atomic_inc_not_zero
(
&
orig
_node
->
refcount
))
if
(
!
atomic_inc_not_zero
(
&
gw
_node
->
refcount
))
orig
_node
=
NULL
;
gw
_node
=
NULL
;
out:
out:
rcu_read_unlock
();
rcu_read_unlock
();
return
orig
_node
;
return
gw
_node
;
}
}
void
gw_deselect
(
struct
bat_priv
*
bat_priv
)
struct
orig_node
*
gw_get_selected_orig
(
struct
bat_priv
*
bat_priv
)
{
{
struct
gw_node
*
gw_node
;
struct
gw_node
*
gw_node
;
struct
orig_node
*
orig_node
=
NULL
;
spin_lock_bh
(
&
bat_priv
->
gw_list_lock
);
gw_node
=
gw_get_selected_gw_node
(
bat_priv
);
gw_node
=
rcu_dereference
(
bat_priv
->
curr_gw
);
if
(
!
gw_node
)
rcu_assign_pointer
(
bat_priv
->
curr_gw
,
NULL
);
goto
out
;
spin_unlock_bh
(
&
bat_priv
->
gw_list_lock
);
rcu_read_lock
();
orig_node
=
gw_node
->
orig_node
;
if
(
!
orig_node
)
goto
unlock
;
if
(
!
atomic_inc_not_zero
(
&
orig_node
->
refcount
))
orig_node
=
NULL
;
unlock:
rcu_read_unlock
();
out:
if
(
gw_node
)
if
(
gw_node
)
gw_node_free_ref
(
gw_node
);
gw_node_free_ref
(
gw_node
);
return
orig_node
;
}
}
static
void
gw_select
(
struct
bat_priv
*
bat_priv
,
struct
gw_node
*
new_gw_node
)
static
void
gw_select
(
struct
bat_priv
*
bat_priv
,
struct
gw_node
*
new_gw_node
)
{
{
struct
gw_node
*
curr_gw_node
;
struct
gw_node
*
curr_gw_node
;
spin_lock_bh
(
&
bat_priv
->
gw_list_lock
);
if
(
new_gw_node
&&
!
atomic_inc_not_zero
(
&
new_gw_node
->
refcount
))
if
(
new_gw_node
&&
!
atomic_inc_not_zero
(
&
new_gw_node
->
refcount
))
new_gw_node
=
NULL
;
new_gw_node
=
NULL
;
spin_lock_bh
(
&
bat_priv
->
gw_list_lock
);
curr_gw_node
=
bat_priv
->
curr_gw
;
curr_gw_node
=
rcu_dereference
(
bat_priv
->
curr_gw
);
rcu_assign_pointer
(
bat_priv
->
curr_gw
,
new_gw_node
);
rcu_assign_pointer
(
bat_priv
->
curr_gw
,
new_gw_node
);
spin_unlock_bh
(
&
bat_priv
->
gw_list_lock
);
if
(
curr_gw_node
)
if
(
curr_gw_node
)
gw_node_free_ref
(
curr_gw_node
);
gw_node_free_ref
(
curr_gw_node
);
spin_unlock_bh
(
&
bat_priv
->
gw_list_lock
);
}
void
gw_deselect
(
struct
bat_priv
*
bat_priv
)
{
gw_select
(
bat_priv
,
NULL
);
}
}
void
gw_election
(
struct
bat_priv
*
bat_priv
)
void
gw_election
(
struct
bat_priv
*
bat_priv
)
{
{
struct
hlist_node
*
node
;
struct
hlist_node
*
node
;
struct
gw_node
*
gw_node
,
*
curr_gw
,
*
curr_gw_tmp
=
NULL
;
struct
gw_node
*
gw_node
,
*
curr_gw
=
NULL
,
*
curr_gw_tmp
=
NULL
;
struct
neigh_node
*
router
;
uint8_t
max_tq
=
0
;
uint8_t
max_tq
=
0
;
uint32_t
max_gw_factor
=
0
,
tmp_gw_factor
=
0
;
uint32_t
max_gw_factor
=
0
,
tmp_gw_factor
=
0
;
int
down
,
up
;
int
down
,
up
;
...
@@ -110,32 +126,25 @@ void gw_election(struct bat_priv *bat_priv)
...
@@ -110,32 +126,25 @@ void gw_election(struct bat_priv *bat_priv)
if
(
atomic_read
(
&
bat_priv
->
gw_mode
)
!=
GW_MODE_CLIENT
)
if
(
atomic_read
(
&
bat_priv
->
gw_mode
)
!=
GW_MODE_CLIENT
)
return
;
return
;
rcu_read_lock
();
curr_gw
=
gw_get_selected_gw_node
(
bat_priv
);
curr_gw
=
rcu_dereference
(
bat_priv
->
curr_gw
);
if
(
!
curr_gw
)
if
(
curr_gw
)
{
goto
out
;
rcu_read_unlock
();
return
;
}
rcu_read_lock
();
if
(
hlist_empty
(
&
bat_priv
->
gw_list
))
{
if
(
hlist_empty
(
&
bat_priv
->
gw_list
))
{
bat_dbg
(
DBG_BATMAN
,
bat_priv
,
if
(
curr_gw
)
{
"Removing selected gateway - "
rcu_read_unlock
();
"no gateway in range
\n
"
);
bat_dbg
(
DBG_BATMAN
,
bat_priv
,
gw_deselect
(
bat_priv
);
"Removing selected gateway - "
goto
unlock
;
"no gateway in range
\n
"
);
gw_deselect
(
bat_priv
);
}
else
rcu_read_unlock
();
return
;
}
}
hlist_for_each_entry_rcu
(
gw_node
,
node
,
&
bat_priv
->
gw_list
,
list
)
{
hlist_for_each_entry_rcu
(
gw_node
,
node
,
&
bat_priv
->
gw_list
,
list
)
{
if
(
!
gw_node
->
orig_node
->
router
)
if
(
gw_node
->
deleted
)
continue
;
continue
;
if
(
gw_node
->
deleted
)
router
=
orig_node_get_router
(
gw_node
->
orig_node
);
if
(
!
router
)
continue
;
continue
;
switch
(
atomic_read
(
&
bat_priv
->
gw_sel_class
))
{
switch
(
atomic_read
(
&
bat_priv
->
gw_sel_class
))
{
...
@@ -143,15 +152,14 @@ void gw_election(struct bat_priv *bat_priv)
...
@@ -143,15 +152,14 @@ void gw_election(struct bat_priv *bat_priv)
gw_bandwidth_to_kbit
(
gw_node
->
orig_node
->
gw_flags
,
gw_bandwidth_to_kbit
(
gw_node
->
orig_node
->
gw_flags
,
&
down
,
&
up
);
&
down
,
&
up
);
tmp_gw_factor
=
(
gw_node
->
orig_node
->
router
->
tq_avg
*
tmp_gw_factor
=
(
router
->
tq_avg
*
router
->
tq_avg
*
gw_node
->
orig_node
->
router
->
tq_avg
*
down
*
100
*
100
)
/
down
*
100
*
100
)
/
(
TQ_LOCAL_WINDOW_SIZE
*
(
TQ_LOCAL_WINDOW_SIZE
*
TQ_LOCAL_WINDOW_SIZE
*
64
);
TQ_LOCAL_WINDOW_SIZE
*
64
);
if
((
tmp_gw_factor
>
max_gw_factor
)
||
if
((
tmp_gw_factor
>
max_gw_factor
)
||
((
tmp_gw_factor
==
max_gw_factor
)
&&
((
tmp_gw_factor
==
max_gw_factor
)
&&
(
gw_node
->
orig_node
->
router
->
tq_avg
>
max_tq
)))
(
router
->
tq_avg
>
max_tq
)))
curr_gw_tmp
=
gw_node
;
curr_gw_tmp
=
gw_node
;
break
;
break
;
...
@@ -163,19 +171,25 @@ void gw_election(struct bat_priv *bat_priv)
...
@@ -163,19 +171,25 @@ void gw_election(struct bat_priv *bat_priv)
* soon as a better gateway appears which has
* soon as a better gateway appears which has
* $routing_class more tq points)
* $routing_class more tq points)
**/
**/
if
(
gw_node
->
orig_node
->
router
->
tq_avg
>
max_tq
)
if
(
router
->
tq_avg
>
max_tq
)
curr_gw_tmp
=
gw_node
;
curr_gw_tmp
=
gw_node
;
break
;
break
;
}
}
if
(
gw_node
->
orig_node
->
router
->
tq_avg
>
max_tq
)
if
(
router
->
tq_avg
>
max_tq
)
max_tq
=
gw_node
->
orig_node
->
router
->
tq_avg
;
max_tq
=
router
->
tq_avg
;
if
(
tmp_gw_factor
>
max_gw_factor
)
if
(
tmp_gw_factor
>
max_gw_factor
)
max_gw_factor
=
tmp_gw_factor
;
max_gw_factor
=
tmp_gw_factor
;
neigh_node_free_ref
(
router
);
}
}
if
(
curr_gw
!=
curr_gw_tmp
)
{
if
(
curr_gw
!=
curr_gw_tmp
)
{
router
=
orig_node_get_router
(
curr_gw_tmp
->
orig_node
);
if
(
!
router
)
goto
unlock
;
if
((
curr_gw
)
&&
(
!
curr_gw_tmp
))
if
((
curr_gw
)
&&
(
!
curr_gw_tmp
))
bat_dbg
(
DBG_BATMAN
,
bat_priv
,
bat_dbg
(
DBG_BATMAN
,
bat_priv
,
"Removing selected gateway - "
"Removing selected gateway - "
...
@@ -186,48 +200,50 @@ void gw_election(struct bat_priv *bat_priv)
...
@@ -186,48 +200,50 @@ void gw_election(struct bat_priv *bat_priv)
"(gw_flags: %i, tq: %i)
\n
"
,
"(gw_flags: %i, tq: %i)
\n
"
,
curr_gw_tmp
->
orig_node
->
orig
,
curr_gw_tmp
->
orig_node
->
orig
,
curr_gw_tmp
->
orig_node
->
gw_flags
,
curr_gw_tmp
->
orig_node
->
gw_flags
,
curr_gw_tmp
->
orig_node
->
router
->
tq_avg
);
router
->
tq_avg
);
else
else
bat_dbg
(
DBG_BATMAN
,
bat_priv
,
bat_dbg
(
DBG_BATMAN
,
bat_priv
,
"Changing route to gateway %pM "
"Changing route to gateway %pM "
"(gw_flags: %i, tq: %i)
\n
"
,
"(gw_flags: %i, tq: %i)
\n
"
,
curr_gw_tmp
->
orig_node
->
orig
,
curr_gw_tmp
->
orig_node
->
orig
,
curr_gw_tmp
->
orig_node
->
gw_flags
,
curr_gw_tmp
->
orig_node
->
gw_flags
,
curr_gw_tmp
->
orig_node
->
router
->
tq_avg
);
router
->
tq_avg
);
neigh_node_free_ref
(
router
);
gw_select
(
bat_priv
,
curr_gw_tmp
);
gw_select
(
bat_priv
,
curr_gw_tmp
);
}
}
unlock:
rcu_read_unlock
();
rcu_read_unlock
();
out:
if
(
curr_gw
)
gw_node_free_ref
(
curr_gw
);
}
}
void
gw_check_election
(
struct
bat_priv
*
bat_priv
,
struct
orig_node
*
orig_node
)
void
gw_check_election
(
struct
bat_priv
*
bat_priv
,
struct
orig_node
*
orig_node
)
{
{
struct
gw_node
*
curr_gateway_tmp
;
struct
orig_node
*
curr_gw_orig
;
struct
neigh_node
*
router_gw
=
NULL
,
*
router_orig
=
NULL
;
uint8_t
gw_tq_avg
,
orig_tq_avg
;
uint8_t
gw_tq_avg
,
orig_tq_avg
;
rcu_read_lock
();
curr_gw_orig
=
gw_get_selected_orig
(
bat_priv
);
curr_gateway_tmp
=
rcu_dereference
(
bat_priv
->
curr_gw
);
if
(
!
curr_gw_orig
)
if
(
!
curr_gateway_tmp
)
goto
deselect
;
goto
out_rcu
;
if
(
!
curr_gateway_tmp
->
orig_node
)
router_gw
=
orig_node_get_router
(
curr_gw_orig
);
goto
deselect_rcu
;
if
(
!
router_gw
)
goto
deselect
;
if
(
!
curr_gateway_tmp
->
orig_node
->
router
)
goto
deselect_rcu
;
/* this node already is the gateway */
/* this node already is the gateway */
if
(
curr_gateway_tmp
->
orig_node
==
orig_node
)
if
(
curr_gw_orig
==
orig_node
)
goto
out_rcu
;
goto
out
;
if
(
!
orig_node
->
router
)
goto
out_rcu
;
gw_tq_avg
=
curr_gateway_tmp
->
orig_node
->
router
->
tq_avg
;
router_orig
=
orig_node_get_router
(
orig_node
);
rcu_read_unlock
();
if
(
!
router_orig
)
goto
out
;
orig_tq_avg
=
orig_node
->
router
->
tq_avg
;
gw_tq_avg
=
router_gw
->
tq_avg
;
orig_tq_avg
=
router_orig
->
tq_avg
;
/* the TQ value has to be better */
/* the TQ value has to be better */
if
(
orig_tq_avg
<
gw_tq_avg
)
if
(
orig_tq_avg
<
gw_tq_avg
)
...
@@ -245,16 +261,17 @@ void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
...
@@ -245,16 +261,17 @@ void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
"Restarting gateway selection: better gateway found (tq curr: "
"Restarting gateway selection: better gateway found (tq curr: "
"%i, tq new: %i)
\n
"
,
"%i, tq new: %i)
\n
"
,
gw_tq_avg
,
orig_tq_avg
);
gw_tq_avg
,
orig_tq_avg
);
goto
deselect
;
out_rcu:
rcu_read_unlock
();
goto
out
;
deselect_rcu:
rcu_read_unlock
();
deselect:
deselect:
gw_deselect
(
bat_priv
);
gw_deselect
(
bat_priv
);
out:
out:
if
(
curr_gw_orig
)
orig_node_free_ref
(
curr_gw_orig
);
if
(
router_gw
)
neigh_node_free_ref
(
router_gw
);
if
(
router_orig
)
neigh_node_free_ref
(
router_orig
);
return
;
return
;
}
}
...
@@ -291,7 +308,11 @@ void gw_node_update(struct bat_priv *bat_priv,
...
@@ -291,7 +308,11 @@ void gw_node_update(struct bat_priv *bat_priv,
struct
orig_node
*
orig_node
,
uint8_t
new_gwflags
)
struct
orig_node
*
orig_node
,
uint8_t
new_gwflags
)
{
{
struct
hlist_node
*
node
;
struct
hlist_node
*
node
;
struct
gw_node
*
gw_node
;
struct
gw_node
*
gw_node
,
*
curr_gw
;
curr_gw
=
gw_get_selected_gw_node
(
bat_priv
);
if
(
!
curr_gw
)
goto
out
;
rcu_read_lock
();
rcu_read_lock
();
hlist_for_each_entry_rcu
(
gw_node
,
node
,
&
bat_priv
->
gw_list
,
list
)
{
hlist_for_each_entry_rcu
(
gw_node
,
node
,
&
bat_priv
->
gw_list
,
list
)
{
...
@@ -312,22 +333,26 @@ void gw_node_update(struct bat_priv *bat_priv,
...
@@ -312,22 +333,26 @@ void gw_node_update(struct bat_priv *bat_priv,
"Gateway %pM removed from gateway list
\n
"
,
"Gateway %pM removed from gateway list
\n
"
,
orig_node
->
orig
);
orig_node
->
orig
);
if
(
gw_node
==
rcu_dereference
(
bat_priv
->
curr_gw
))
{
if
(
gw_node
==
curr_gw
)
rcu_read_unlock
();
goto
deselect
;
gw_deselect
(
bat_priv
);
return
;
}
}
}
rcu_read_unlock
();
goto
unlock
;
return
;
}
}
rcu_read_unlock
();
if
(
new_gwflags
==
0
)
if
(
new_gwflags
==
0
)
return
;
goto
unlock
;
gw_node_add
(
bat_priv
,
orig_node
,
new_gwflags
);
gw_node_add
(
bat_priv
,
orig_node
,
new_gwflags
);
goto
unlock
;
deselect:
gw_deselect
(
bat_priv
);
unlock:
rcu_read_unlock
();
out:
if
(
curr_gw
)
gw_node_free_ref
(
curr_gw
);
}
}
void
gw_node_delete
(
struct
bat_priv
*
bat_priv
,
struct
orig_node
*
orig_node
)
void
gw_node_delete
(
struct
bat_priv
*
bat_priv
,
struct
orig_node
*
orig_node
)
...
@@ -337,9 +362,12 @@ void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node)
...
@@ -337,9 +362,12 @@ void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node)
void
gw_node_purge
(
struct
bat_priv
*
bat_priv
)
void
gw_node_purge
(
struct
bat_priv
*
bat_priv
)
{
{
struct
gw_node
*
gw_node
;
struct
gw_node
*
gw_node
,
*
curr_gw
;
struct
hlist_node
*
node
,
*
node_tmp
;
struct
hlist_node
*
node
,
*
node_tmp
;
unsigned
long
timeout
=
2
*
PURGE_TIMEOUT
*
HZ
;
unsigned
long
timeout
=
2
*
PURGE_TIMEOUT
*
HZ
;
char
do_deselect
=
0
;
curr_gw
=
gw_get_selected_gw_node
(
bat_priv
);
spin_lock_bh
(
&
bat_priv
->
gw_list_lock
);
spin_lock_bh
(
&
bat_priv
->
gw_list_lock
);
...
@@ -350,41 +378,56 @@ void gw_node_purge(struct bat_priv *bat_priv)
...
@@ -350,41 +378,56 @@ void gw_node_purge(struct bat_priv *bat_priv)
atomic_read
(
&
bat_priv
->
mesh_state
)
==
MESH_ACTIVE
)
atomic_read
(
&
bat_priv
->
mesh_state
)
==
MESH_ACTIVE
)
continue
;
continue
;
if
(
rcu_dereference
(
bat_priv
->
curr_gw
)
==
gw_node
)
if
(
curr_gw
==
gw_node
)
gw_deselect
(
bat_priv
)
;
do_deselect
=
1
;
hlist_del_rcu
(
&
gw_node
->
list
);
hlist_del_rcu
(
&
gw_node
->
list
);
gw_node_free_ref
(
gw_node
);
gw_node_free_ref
(
gw_node
);
}
}
spin_unlock_bh
(
&
bat_priv
->
gw_list_lock
);
spin_unlock_bh
(
&
bat_priv
->
gw_list_lock
);
/* gw_deselect() needs to acquire the gw_list_lock */
if
(
do_deselect
)
gw_deselect
(
bat_priv
);
if
(
curr_gw
)
gw_node_free_ref
(
curr_gw
);
}
}
/**
* fails if orig_node has no router
*/
static
int
_write_buffer_text
(
struct
bat_priv
*
bat_priv
,
static
int
_write_buffer_text
(
struct
bat_priv
*
bat_priv
,
struct
seq_file
*
seq
,
struct
gw_node
*
gw_node
)
struct
seq_file
*
seq
,
struct
gw_node
*
gw_node
)
{
{
struct
gw_node
*
curr_gw
;
struct
gw_node
*
curr_gw
;
int
down
,
up
,
ret
;
struct
neigh_node
*
router
;
int
down
,
up
,
ret
=
-
1
;
gw_bandwidth_to_kbit
(
gw_node
->
orig_node
->
gw_flags
,
&
down
,
&
up
);
gw_bandwidth_to_kbit
(
gw_node
->
orig_node
->
gw_flags
,
&
down
,
&
up
);
rcu_read_lock
();
router
=
orig_node_get_router
(
gw_node
->
orig_node
);
curr_gw
=
rcu_dereference
(
bat_priv
->
curr_gw
);
if
(
!
router
)
goto
out
;
ret
=
seq_printf
(
seq
,
"%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s
\n
"
,
curr_gw
=
gw_get_selected_gw_node
(
bat_priv
);
(
curr_gw
==
gw_node
?
"=>"
:
" "
),
gw_node
->
orig_node
->
orig
,
gw_node
->
orig_node
->
router
->
tq_avg
,
gw_node
->
orig_node
->
router
->
addr
,
gw_node
->
orig_node
->
router
->
if_incoming
->
net_dev
->
name
,
gw_node
->
orig_node
->
gw_flags
,
(
down
>
2048
?
down
/
1024
:
down
),
(
down
>
2048
?
"MBit"
:
"KBit"
),
(
up
>
2048
?
up
/
1024
:
up
),
(
up
>
2048
?
"MBit"
:
"KBit"
));
rcu_read_unlock
();
ret
=
seq_printf
(
seq
,
"%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s
\n
"
,
(
curr_gw
==
gw_node
?
"=>"
:
" "
),
gw_node
->
orig_node
->
orig
,
router
->
tq_avg
,
router
->
addr
,
router
->
if_incoming
->
net_dev
->
name
,
gw_node
->
orig_node
->
gw_flags
,
(
down
>
2048
?
down
/
1024
:
down
),
(
down
>
2048
?
"MBit"
:
"KBit"
),
(
up
>
2048
?
up
/
1024
:
up
),
(
up
>
2048
?
"MBit"
:
"KBit"
));
neigh_node_free_ref
(
router
);
if
(
curr_gw
)
gw_node_free_ref
(
curr_gw
);
out:
return
ret
;
return
ret
;
}
}
...
@@ -422,10 +465,10 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset)
...
@@ -422,10 +465,10 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset)
if
(
gw_node
->
deleted
)
if
(
gw_node
->
deleted
)
continue
;
continue
;
if
(
!
gw_node
->
orig_node
->
router
)
/* fails if orig_node has no router */
if
(
_write_buffer_text
(
bat_priv
,
seq
,
gw_node
)
<
0
)
continue
;
continue
;
_write_buffer_text
(
bat_priv
,
seq
,
gw_node
);
gw_count
++
;
gw_count
++
;
}
}
rcu_read_unlock
();
rcu_read_unlock
();
...
@@ -442,6 +485,7 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
...
@@ -442,6 +485,7 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
struct
iphdr
*
iphdr
;
struct
iphdr
*
iphdr
;
struct
ipv6hdr
*
ipv6hdr
;
struct
ipv6hdr
*
ipv6hdr
;
struct
udphdr
*
udphdr
;
struct
udphdr
*
udphdr
;
struct
gw_node
*
curr_gw
;
unsigned
int
header_len
=
0
;
unsigned
int
header_len
=
0
;
if
(
atomic_read
(
&
bat_priv
->
gw_mode
)
==
GW_MODE_OFF
)
if
(
atomic_read
(
&
bat_priv
->
gw_mode
)
==
GW_MODE_OFF
)
...
@@ -506,12 +550,11 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
...
@@ -506,12 +550,11 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
if
(
atomic_read
(
&
bat_priv
->
gw_mode
)
==
GW_MODE_SERVER
)
if
(
atomic_read
(
&
bat_priv
->
gw_mode
)
==
GW_MODE_SERVER
)
return
-
1
;
return
-
1
;
rcu_read_lock
();
curr_gw
=
gw_get_selected_gw_node
(
bat_priv
);
if
(
!
rcu_dereference
(
bat_priv
->
curr_gw
))
{
if
(
!
curr_gw
)
rcu_read_unlock
();
return
0
;
return
0
;
}
rcu_read_unlock
();
if
(
curr_gw
)
gw_node_free_ref
(
curr_gw
);
return
1
;
return
1
;
}
}
net/batman-adv/gateway_client.h
浏览文件 @
9c6bc165
...
@@ -24,7 +24,7 @@
...
@@ -24,7 +24,7 @@
void
gw_deselect
(
struct
bat_priv
*
bat_priv
);
void
gw_deselect
(
struct
bat_priv
*
bat_priv
);
void
gw_election
(
struct
bat_priv
*
bat_priv
);
void
gw_election
(
struct
bat_priv
*
bat_priv
);
void
*
gw_get_selected
(
struct
bat_priv
*
bat_priv
);
struct
orig_node
*
gw_get_selected_orig
(
struct
bat_priv
*
bat_priv
);
void
gw_check_election
(
struct
bat_priv
*
bat_priv
,
struct
orig_node
*
orig_node
);
void
gw_check_election
(
struct
bat_priv
*
bat_priv
,
struct
orig_node
*
orig_node
);
void
gw_node_update
(
struct
bat_priv
*
bat_priv
,
void
gw_node_update
(
struct
bat_priv
*
bat_priv
,
struct
orig_node
*
orig_node
,
uint8_t
new_gwflags
);
struct
orig_node
*
orig_node
,
uint8_t
new_gwflags
);
...
...
net/batman-adv/icmp_socket.c
浏览文件 @
9c6bc165
...
@@ -218,23 +218,13 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
...
@@ -218,23 +218,13 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
if
(
atomic_read
(
&
bat_priv
->
mesh_state
)
!=
MESH_ACTIVE
)
if
(
atomic_read
(
&
bat_priv
->
mesh_state
)
!=
MESH_ACTIVE
)
goto
dst_unreach
;
goto
dst_unreach
;
rcu_read_lock
();
orig_node
=
orig_hash_find
(
bat_priv
,
icmp_packet
->
dst
);
orig_node
=
orig_hash_find
(
bat_priv
,
icmp_packet
->
dst
);
if
(
!
orig_node
)
if
(
!
orig_node
)
goto
unlock
;
goto
dst_unreach
;
neigh_node
=
orig_node
->
router
;
neigh_node
=
orig_node_get_router
(
orig_node
);
if
(
!
neigh_node
)
if
(
!
neigh_node
)
goto
unlock
;
goto
dst_unreach
;
if
(
!
atomic_inc_not_zero
(
&
neigh_node
->
refcount
))
{
neigh_node
=
NULL
;
goto
unlock
;
}
rcu_read_unlock
();
if
(
!
neigh_node
->
if_incoming
)
if
(
!
neigh_node
->
if_incoming
)
goto
dst_unreach
;
goto
dst_unreach
;
...
@@ -252,8 +242,6 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
...
@@ -252,8 +242,6 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
send_skb_packet
(
skb
,
neigh_node
->
if_incoming
,
neigh_node
->
addr
);
send_skb_packet
(
skb
,
neigh_node
->
if_incoming
,
neigh_node
->
addr
);
goto
out
;
goto
out
;
unlock:
rcu_read_unlock
();
dst_unreach:
dst_unreach:
icmp_packet
->
msg_type
=
DESTINATION_UNREACHABLE
;
icmp_packet
->
msg_type
=
DESTINATION_UNREACHABLE
;
bat_socket_add_packet
(
socket_client
,
icmp_packet
,
packet_len
);
bat_socket_add_packet
(
socket_client
,
icmp_packet
,
packet_len
);
...
...
net/batman-adv/originator.c
浏览文件 @
9c6bc165
...
@@ -70,6 +70,21 @@ void neigh_node_free_ref(struct neigh_node *neigh_node)
...
@@ -70,6 +70,21 @@ void neigh_node_free_ref(struct neigh_node *neigh_node)
call_rcu
(
&
neigh_node
->
rcu
,
neigh_node_free_rcu
);
call_rcu
(
&
neigh_node
->
rcu
,
neigh_node_free_rcu
);
}
}
/* increases the refcounter of a found router */
struct
neigh_node
*
orig_node_get_router
(
struct
orig_node
*
orig_node
)
{
struct
neigh_node
*
router
;
rcu_read_lock
();
router
=
rcu_dereference
(
orig_node
->
router
);
if
(
router
&&
!
atomic_inc_not_zero
(
&
router
->
refcount
))
router
=
NULL
;
rcu_read_unlock
();
return
router
;
}
struct
neigh_node
*
create_neighbor
(
struct
orig_node
*
orig_node
,
struct
neigh_node
*
create_neighbor
(
struct
orig_node
*
orig_node
,
struct
orig_node
*
orig_neigh_node
,
struct
orig_node
*
orig_neigh_node
,
uint8_t
*
neigh
,
uint8_t
*
neigh
,
...
@@ -87,6 +102,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node,
...
@@ -87,6 +102,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node,
INIT_HLIST_NODE
(
&
neigh_node
->
list
);
INIT_HLIST_NODE
(
&
neigh_node
->
list
);
INIT_LIST_HEAD
(
&
neigh_node
->
bonding_list
);
INIT_LIST_HEAD
(
&
neigh_node
->
bonding_list
);
spin_lock_init
(
&
neigh_node
->
tq_lock
);
memcpy
(
neigh_node
->
addr
,
neigh
,
ETH_ALEN
);
memcpy
(
neigh_node
->
addr
,
neigh
,
ETH_ALEN
);
neigh_node
->
orig_node
=
orig_neigh_node
;
neigh_node
->
orig_node
=
orig_neigh_node
;
...
@@ -390,7 +406,7 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
...
@@ -390,7 +406,7 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
struct
hlist_node
*
node
,
*
node_tmp
;
struct
hlist_node
*
node
,
*
node_tmp
;
struct
hlist_head
*
head
;
struct
hlist_head
*
head
;
struct
orig_node
*
orig_node
;
struct
orig_node
*
orig_node
;
struct
neigh_node
*
neigh_node
;
struct
neigh_node
*
neigh_node
,
*
neigh_node_tmp
;
int
batman_count
=
0
;
int
batman_count
=
0
;
int
last_seen_secs
;
int
last_seen_secs
;
int
last_seen_msecs
;
int
last_seen_msecs
;
...
@@ -421,37 +437,41 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
...
@@ -421,37 +437,41 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
rcu_read_lock
();
rcu_read_lock
();
hlist_for_each_entry_rcu
(
orig_node
,
node
,
head
,
hash_entry
)
{
hlist_for_each_entry_rcu
(
orig_node
,
node
,
head
,
hash_entry
)
{
if
(
!
orig_node
->
router
)
neigh_node
=
orig_node_get_router
(
orig_node
);
if
(
!
neigh_node
)
continue
;
continue
;
if
(
orig_node
->
router
->
tq_avg
==
0
)
if
(
neigh_node
->
tq_avg
==
0
)
continue
;
goto
next
;
last_seen_secs
=
jiffies_to_msecs
(
jiffies
-
last_seen_secs
=
jiffies_to_msecs
(
jiffies
-
orig_node
->
last_valid
)
/
1000
;
orig_node
->
last_valid
)
/
1000
;
last_seen_msecs
=
jiffies_to_msecs
(
jiffies
-
last_seen_msecs
=
jiffies_to_msecs
(
jiffies
-
orig_node
->
last_valid
)
%
1000
;
orig_node
->
last_valid
)
%
1000
;
neigh_node
=
orig_node
->
router
;
seq_printf
(
seq
,
"%pM %4i.%03is (%3i) %pM [%10s]:"
,
seq_printf
(
seq
,
"%pM %4i.%03is (%3i) %pM [%10s]:"
,
orig_node
->
orig
,
last_seen_secs
,
orig_node
->
orig
,
last_seen_secs
,
last_seen_msecs
,
neigh_node
->
tq_avg
,
last_seen_msecs
,
neigh_node
->
tq_avg
,
neigh_node
->
addr
,
neigh_node
->
addr
,
neigh_node
->
if_incoming
->
net_dev
->
name
);
neigh_node
->
if_incoming
->
net_dev
->
name
);
hlist_for_each_entry_rcu
(
neigh_node
,
node_tmp
,
hlist_for_each_entry_rcu
(
neigh_node
_tmp
,
node_tmp
,
&
orig_node
->
neigh_list
,
list
)
{
&
orig_node
->
neigh_list
,
list
)
{
seq_printf
(
seq
,
" %pM (%3i)"
,
neigh_node
->
addr
,
seq_printf
(
seq
,
" %pM (%3i)"
,
neigh_node
->
tq_avg
);
neigh_node_tmp
->
addr
,
neigh_node_tmp
->
tq_avg
);
}
}
seq_printf
(
seq
,
"
\n
"
);
seq_printf
(
seq
,
"
\n
"
);
batman_count
++
;
batman_count
++
;
next:
neigh_node_free_ref
(
neigh_node
);
}
}
rcu_read_unlock
();
rcu_read_unlock
();
}
}
if
(
(
batman_count
==
0
)
)
if
(
batman_count
==
0
)
seq_printf
(
seq
,
"No batman nodes in range ...
\n
"
);
seq_printf
(
seq
,
"No batman nodes in range ...
\n
"
);
return
0
;
return
0
;
...
...
net/batman-adv/originator.h
浏览文件 @
9c6bc165
...
@@ -34,6 +34,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node,
...
@@ -34,6 +34,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node,
uint8_t
*
neigh
,
uint8_t
*
neigh
,
struct
hard_iface
*
if_incoming
);
struct
hard_iface
*
if_incoming
);
void
neigh_node_free_ref
(
struct
neigh_node
*
neigh_node
);
void
neigh_node_free_ref
(
struct
neigh_node
*
neigh_node
);
struct
neigh_node
*
orig_node_get_router
(
struct
orig_node
*
orig_node
);
int
orig_seq_print_text
(
struct
seq_file
*
seq
,
void
*
offset
);
int
orig_seq_print_text
(
struct
seq_file
*
seq
,
void
*
offset
);
int
orig_hash_add_if
(
struct
hard_iface
*
hard_iface
,
int
max_if_num
);
int
orig_hash_add_if
(
struct
hard_iface
*
hard_iface
,
int
max_if_num
);
int
orig_hash_del_if
(
struct
hard_iface
*
hard_iface
,
int
max_if_num
);
int
orig_hash_del_if
(
struct
hard_iface
*
hard_iface
,
int
max_if_num
);
...
...
net/batman-adv/routing.c
浏览文件 @
9c6bc165
...
@@ -87,18 +87,20 @@ static void update_route(struct bat_priv *bat_priv,
...
@@ -87,18 +87,20 @@ static void update_route(struct bat_priv *bat_priv,
struct
neigh_node
*
neigh_node
,
struct
neigh_node
*
neigh_node
,
unsigned
char
*
hna_buff
,
int
hna_buff_len
)
unsigned
char
*
hna_buff
,
int
hna_buff_len
)
{
{
struct
neigh_node
*
neigh_node_tmp
;
struct
neigh_node
*
curr_router
;
curr_router
=
orig_node_get_router
(
orig_node
);
/* route deleted */
/* route deleted */
if
((
orig_node
->
router
)
&&
(
!
neigh_node
))
{
if
((
curr_
router
)
&&
(
!
neigh_node
))
{
bat_dbg
(
DBG_ROUTES
,
bat_priv
,
"Deleting route towards: %pM
\n
"
,
bat_dbg
(
DBG_ROUTES
,
bat_priv
,
"Deleting route towards: %pM
\n
"
,
orig_node
->
orig
);
orig_node
->
orig
);
hna_global_del_orig
(
bat_priv
,
orig_node
,
hna_global_del_orig
(
bat_priv
,
orig_node
,
"originator timed out"
);
"originator timed out"
);
/* route added */
/* route added */
}
else
if
((
!
orig_node
->
router
)
&&
(
neigh_node
))
{
}
else
if
((
!
curr_
router
)
&&
(
neigh_node
))
{
bat_dbg
(
DBG_ROUTES
,
bat_priv
,
bat_dbg
(
DBG_ROUTES
,
bat_priv
,
"Adding route towards: %pM (via %pM)
\n
"
,
"Adding route towards: %pM (via %pM)
\n
"
,
...
@@ -106,21 +108,29 @@ static void update_route(struct bat_priv *bat_priv,
...
@@ -106,21 +108,29 @@ static void update_route(struct bat_priv *bat_priv,
hna_global_add_orig
(
bat_priv
,
orig_node
,
hna_global_add_orig
(
bat_priv
,
orig_node
,
hna_buff
,
hna_buff_len
);
hna_buff
,
hna_buff_len
);
/* route changed */
/* route changed */
}
else
{
}
else
{
bat_dbg
(
DBG_ROUTES
,
bat_priv
,
bat_dbg
(
DBG_ROUTES
,
bat_priv
,
"Changing route towards: %pM "
"Changing route towards: %pM "
"(now via %pM - was via %pM)
\n
"
,
"(now via %pM - was via %pM)
\n
"
,
orig_node
->
orig
,
neigh_node
->
addr
,
orig_node
->
orig
,
neigh_node
->
addr
,
orig_node
->
router
->
addr
);
curr_
router
->
addr
);
}
}
if
(
curr_router
)
neigh_node_free_ref
(
curr_router
);
/* increase refcount of new best neighbor */
if
(
neigh_node
&&
!
atomic_inc_not_zero
(
&
neigh_node
->
refcount
))
if
(
neigh_node
&&
!
atomic_inc_not_zero
(
&
neigh_node
->
refcount
))
neigh_node
=
NULL
;
neigh_node
=
NULL
;
neigh_node_tmp
=
orig_node
->
router
;
orig_node
->
router
=
neigh_node
;
spin_lock_bh
(
&
orig_node
->
neigh_list_lock
);
if
(
neigh_node_tmp
)
rcu_assign_pointer
(
orig_node
->
router
,
neigh_node
);
neigh_node_free_ref
(
neigh_node_tmp
);
spin_unlock_bh
(
&
orig_node
->
neigh_list_lock
);
/* decrease refcount of previous best neighbor */
if
(
curr_router
)
neigh_node_free_ref
(
curr_router
);
}
}
...
@@ -128,16 +138,23 @@ void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
...
@@ -128,16 +138,23 @@ void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
struct
neigh_node
*
neigh_node
,
unsigned
char
*
hna_buff
,
struct
neigh_node
*
neigh_node
,
unsigned
char
*
hna_buff
,
int
hna_buff_len
)
int
hna_buff_len
)
{
{
struct
neigh_node
*
router
=
NULL
;
if
(
!
orig_node
)
if
(
!
orig_node
)
return
;
goto
out
;
router
=
orig_node_get_router
(
orig_node
);
if
(
orig_node
->
router
!=
neigh_node
)
if
(
router
!=
neigh_node
)
update_route
(
bat_priv
,
orig_node
,
neigh_node
,
update_route
(
bat_priv
,
orig_node
,
neigh_node
,
hna_buff
,
hna_buff_len
);
hna_buff
,
hna_buff_len
);
/* may be just HNA changed */
/* may be just HNA changed */
else
else
update_HNA
(
bat_priv
,
orig_node
,
hna_buff
,
hna_buff_len
);
update_HNA
(
bat_priv
,
orig_node
,
hna_buff
,
hna_buff_len
);
out:
if
(
router
)
neigh_node_free_ref
(
router
);
}
}
static
int
is_bidirectional_neigh
(
struct
orig_node
*
orig_node
,
static
int
is_bidirectional_neigh
(
struct
orig_node
*
orig_node
,
...
@@ -288,8 +305,8 @@ static void bonding_candidate_add(struct orig_node *orig_node,
...
@@ -288,8 +305,8 @@ static void bonding_candidate_add(struct orig_node *orig_node,
struct
neigh_node
*
neigh_node
)
struct
neigh_node
*
neigh_node
)
{
{
struct
hlist_node
*
node
;
struct
hlist_node
*
node
;
struct
neigh_node
*
tmp_neigh_node
;
struct
neigh_node
*
tmp_neigh_node
,
*
router
=
NULL
;
uint8_t
best_tq
,
interference_candidate
=
0
;
uint8_t
interference_candidate
=
0
;
spin_lock_bh
(
&
orig_node
->
neigh_list_lock
);
spin_lock_bh
(
&
orig_node
->
neigh_list_lock
);
...
@@ -298,13 +315,12 @@ static void bonding_candidate_add(struct orig_node *orig_node,
...
@@ -298,13 +315,12 @@ static void bonding_candidate_add(struct orig_node *orig_node,
neigh_node
->
orig_node
->
primary_addr
))
neigh_node
->
orig_node
->
primary_addr
))
goto
candidate_del
;
goto
candidate_del
;
if
(
!
orig_node
->
router
)
router
=
orig_node_get_router
(
orig_node
);
if
(
!
router
)
goto
candidate_del
;
goto
candidate_del
;
best_tq
=
orig_node
->
router
->
tq_avg
;
/* ... and is good enough to be considered */
/* ... and is good enough to be considered */
if
(
neigh_node
->
tq_avg
<
best_tq
-
BONDING_TQ_THRESHOLD
)
if
(
neigh_node
->
tq_avg
<
router
->
tq_avg
-
BONDING_TQ_THRESHOLD
)
goto
candidate_del
;
goto
candidate_del
;
/**
/**
...
@@ -350,7 +366,9 @@ static void bonding_candidate_add(struct orig_node *orig_node,
...
@@ -350,7 +366,9 @@ static void bonding_candidate_add(struct orig_node *orig_node,
out:
out:
spin_unlock_bh
(
&
orig_node
->
neigh_list_lock
);
spin_unlock_bh
(
&
orig_node
->
neigh_list_lock
);
return
;
if
(
router
)
neigh_node_free_ref
(
router
);
}
}
/* copy primary address for bonding */
/* copy primary address for bonding */
...
@@ -373,6 +391,7 @@ static void update_orig(struct bat_priv *bat_priv,
...
@@ -373,6 +391,7 @@ static void update_orig(struct bat_priv *bat_priv,
char
is_duplicate
)
char
is_duplicate
)
{
{
struct
neigh_node
*
neigh_node
=
NULL
,
*
tmp_neigh_node
=
NULL
;
struct
neigh_node
*
neigh_node
=
NULL
,
*
tmp_neigh_node
=
NULL
;
struct
neigh_node
*
router
=
NULL
;
struct
orig_node
*
orig_node_tmp
;
struct
orig_node
*
orig_node_tmp
;
struct
hlist_node
*
node
;
struct
hlist_node
*
node
;
int
tmp_hna_buff_len
;
int
tmp_hna_buff_len
;
...
@@ -396,10 +415,12 @@ static void update_orig(struct bat_priv *bat_priv,
...
@@ -396,10 +415,12 @@ static void update_orig(struct bat_priv *bat_priv,
if
(
is_duplicate
)
if
(
is_duplicate
)
continue
;
continue
;
spin_lock_bh
(
&
tmp_neigh_node
->
tq_lock
);
ring_buffer_set
(
tmp_neigh_node
->
tq_recv
,
ring_buffer_set
(
tmp_neigh_node
->
tq_recv
,
&
tmp_neigh_node
->
tq_index
,
0
);
&
tmp_neigh_node
->
tq_index
,
0
);
tmp_neigh_node
->
tq_avg
=
tmp_neigh_node
->
tq_avg
=
ring_buffer_avg
(
tmp_neigh_node
->
tq_recv
);
ring_buffer_avg
(
tmp_neigh_node
->
tq_recv
);
spin_unlock_bh
(
&
tmp_neigh_node
->
tq_lock
);
}
}
if
(
!
neigh_node
)
{
if
(
!
neigh_node
)
{
...
@@ -424,10 +445,12 @@ static void update_orig(struct bat_priv *bat_priv,
...
@@ -424,10 +445,12 @@ static void update_orig(struct bat_priv *bat_priv,
orig_node
->
flags
=
batman_packet
->
flags
;
orig_node
->
flags
=
batman_packet
->
flags
;
neigh_node
->
last_valid
=
jiffies
;
neigh_node
->
last_valid
=
jiffies
;
spin_lock_bh
(
&
neigh_node
->
tq_lock
);
ring_buffer_set
(
neigh_node
->
tq_recv
,
ring_buffer_set
(
neigh_node
->
tq_recv
,
&
neigh_node
->
tq_index
,
&
neigh_node
->
tq_index
,
batman_packet
->
tq
);
batman_packet
->
tq
);
neigh_node
->
tq_avg
=
ring_buffer_avg
(
neigh_node
->
tq_recv
);
neigh_node
->
tq_avg
=
ring_buffer_avg
(
neigh_node
->
tq_recv
);
spin_unlock_bh
(
&
neigh_node
->
tq_lock
);
if
(
!
is_duplicate
)
{
if
(
!
is_duplicate
)
{
orig_node
->
last_ttl
=
batman_packet
->
ttl
;
orig_node
->
last_ttl
=
batman_packet
->
ttl
;
...
@@ -441,19 +464,18 @@ static void update_orig(struct bat_priv *bat_priv,
...
@@ -441,19 +464,18 @@ static void update_orig(struct bat_priv *bat_priv,
/* if this neighbor already is our next hop there is nothing
/* if this neighbor already is our next hop there is nothing
* to change */
* to change */
if
(
orig_node
->
router
==
neigh_node
)
router
=
orig_node_get_router
(
orig_node
);
if
(
router
==
neigh_node
)
goto
update_hna
;
goto
update_hna
;
/* if this neighbor does not offer a better TQ we won't consider it */
/* if this neighbor does not offer a better TQ we won't consider it */
if
((
orig_node
->
router
)
&&
if
(
router
&&
(
router
->
tq_avg
>
neigh_node
->
tq_avg
))
(
orig_node
->
router
->
tq_avg
>
neigh_node
->
tq_avg
))
goto
update_hna
;
goto
update_hna
;
/* if the TQ is the same and the link not more symetric we
/* if the TQ is the same and the link not more symetric we
* won't consider it either */
* won't consider it either */
if
((
orig_node
->
router
)
&&
if
(
router
&&
(
neigh_node
->
tq_avg
==
router
->
tq_avg
))
{
(
neigh_node
->
tq_avg
==
orig_node
->
router
->
tq_avg
))
{
orig_node_tmp
=
router
->
orig_node
;
orig_node_tmp
=
orig_node
->
router
->
orig_node
;
spin_lock_bh
(
&
orig_node_tmp
->
ogm_cnt_lock
);
spin_lock_bh
(
&
orig_node_tmp
->
ogm_cnt_lock
);
bcast_own_sum_orig
=
bcast_own_sum_orig
=
orig_node_tmp
->
bcast_own_sum
[
if_incoming
->
if_num
];
orig_node_tmp
->
bcast_own_sum
[
if_incoming
->
if_num
];
...
@@ -474,7 +496,7 @@ static void update_orig(struct bat_priv *bat_priv,
...
@@ -474,7 +496,7 @@ static void update_orig(struct bat_priv *bat_priv,
goto
update_gw
;
goto
update_gw
;
update_hna:
update_hna:
update_routes
(
bat_priv
,
orig_node
,
orig_node
->
router
,
update_routes
(
bat_priv
,
orig_node
,
router
,
hna_buff
,
tmp_hna_buff_len
);
hna_buff
,
tmp_hna_buff_len
);
update_gw:
update_gw:
...
@@ -496,6 +518,8 @@ static void update_orig(struct bat_priv *bat_priv,
...
@@ -496,6 +518,8 @@ static void update_orig(struct bat_priv *bat_priv,
out:
out:
if
(
neigh_node
)
if
(
neigh_node
)
neigh_node_free_ref
(
neigh_node
);
neigh_node_free_ref
(
neigh_node
);
if
(
router
)
neigh_node_free_ref
(
router
);
}
}
/* checks whether the host restarted and is in the protection time.
/* checks whether the host restarted and is in the protection time.
...
@@ -603,6 +627,8 @@ void receive_bat_packet(struct ethhdr *ethhdr,
...
@@ -603,6 +627,8 @@ void receive_bat_packet(struct ethhdr *ethhdr,
struct
bat_priv
*
bat_priv
=
netdev_priv
(
if_incoming
->
soft_iface
);
struct
bat_priv
*
bat_priv
=
netdev_priv
(
if_incoming
->
soft_iface
);
struct
hard_iface
*
hard_iface
;
struct
hard_iface
*
hard_iface
;
struct
orig_node
*
orig_neigh_node
,
*
orig_node
;
struct
orig_node
*
orig_neigh_node
,
*
orig_node
;
struct
neigh_node
*
router
=
NULL
,
*
router_router
=
NULL
;
struct
neigh_node
*
orig_neigh_router
=
NULL
;
char
has_directlink_flag
;
char
has_directlink_flag
;
char
is_my_addr
=
0
,
is_my_orig
=
0
,
is_my_oldorig
=
0
;
char
is_my_addr
=
0
,
is_my_orig
=
0
,
is_my_oldorig
=
0
;
char
is_broadcast
=
0
,
is_bidirectional
,
is_single_hop_neigh
;
char
is_broadcast
=
0
,
is_bidirectional
,
is_single_hop_neigh
;
...
@@ -747,14 +773,15 @@ void receive_bat_packet(struct ethhdr *ethhdr,
...
@@ -747,14 +773,15 @@ void receive_bat_packet(struct ethhdr *ethhdr,
goto
out
;
goto
out
;
}
}
router
=
orig_node_get_router
(
orig_node
);
if
(
router
)
router_router
=
orig_node_get_router
(
router
->
orig_node
);
/* avoid temporary routing loops */
/* avoid temporary routing loops */
if
((
orig_node
->
router
)
&&
if
(
router
&&
router_router
&&
(
orig_node
->
router
->
orig_node
->
router
)
&&
(
compare_eth
(
router
->
addr
,
batman_packet
->
prev_sender
))
&&
(
compare_eth
(
orig_node
->
router
->
addr
,
batman_packet
->
prev_sender
))
&&
!
(
compare_eth
(
batman_packet
->
orig
,
batman_packet
->
prev_sender
))
&&
!
(
compare_eth
(
batman_packet
->
orig
,
batman_packet
->
prev_sender
))
&&
(
compare_eth
(
orig_node
->
router
->
addr
,
(
compare_eth
(
router
->
addr
,
router_router
->
addr
)))
{
orig_node
->
router
->
orig_node
->
router
->
addr
)))
{
bat_dbg
(
DBG_BATMAN
,
bat_priv
,
bat_dbg
(
DBG_BATMAN
,
bat_priv
,
"Drop packet: ignoring all rebroadcast packets that "
"Drop packet: ignoring all rebroadcast packets that "
"may make me loop (sender: %pM)
\n
"
,
ethhdr
->
h_source
);
"may make me loop (sender: %pM)
\n
"
,
ethhdr
->
h_source
);
...
@@ -769,9 +796,11 @@ void receive_bat_packet(struct ethhdr *ethhdr,
...
@@ -769,9 +796,11 @@ void receive_bat_packet(struct ethhdr *ethhdr,
if
(
!
orig_neigh_node
)
if
(
!
orig_neigh_node
)
goto
out
;
goto
out
;
orig_neigh_router
=
orig_node_get_router
(
orig_neigh_node
);
/* drop packet if sender is not a direct neighbor and if we
/* drop packet if sender is not a direct neighbor and if we
* don't route towards it */
* don't route towards it */
if
(
!
is_single_hop_neigh
&&
(
!
orig_neigh_
node
->
router
))
{
if
(
!
is_single_hop_neigh
&&
(
!
orig_neigh_router
))
{
bat_dbg
(
DBG_BATMAN
,
bat_priv
,
bat_dbg
(
DBG_BATMAN
,
bat_priv
,
"Drop packet: OGM via unknown neighbor!
\n
"
);
"Drop packet: OGM via unknown neighbor!
\n
"
);
goto
out_neigh
;
goto
out_neigh
;
...
@@ -825,6 +854,13 @@ void receive_bat_packet(struct ethhdr *ethhdr,
...
@@ -825,6 +854,13 @@ void receive_bat_packet(struct ethhdr *ethhdr,
if
((
orig_neigh_node
)
&&
(
!
is_single_hop_neigh
))
if
((
orig_neigh_node
)
&&
(
!
is_single_hop_neigh
))
orig_node_free_ref
(
orig_neigh_node
);
orig_node_free_ref
(
orig_neigh_node
);
out:
out:
if
(
router
)
neigh_node_free_ref
(
router
);
if
(
router_router
)
neigh_node_free_ref
(
router_router
);
if
(
orig_neigh_router
)
neigh_node_free_ref
(
orig_neigh_router
);
orig_node_free_ref
(
orig_node
);
orig_node_free_ref
(
orig_node
);
}
}
...
@@ -869,7 +905,7 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
...
@@ -869,7 +905,7 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
struct
sk_buff
*
skb
,
size_t
icmp_len
)
struct
sk_buff
*
skb
,
size_t
icmp_len
)
{
{
struct
orig_node
*
orig_node
=
NULL
;
struct
orig_node
*
orig_node
=
NULL
;
struct
neigh_node
*
neigh_node
=
NULL
;
struct
neigh_node
*
router
=
NULL
;
struct
icmp_packet_rr
*
icmp_packet
;
struct
icmp_packet_rr
*
icmp_packet
;
int
ret
=
NET_RX_DROP
;
int
ret
=
NET_RX_DROP
;
...
@@ -886,23 +922,13 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
...
@@ -886,23 +922,13 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
/* answer echo request (ping) */
/* answer echo request (ping) */
/* get routing information */
/* get routing information */
rcu_read_lock
();
orig_node
=
orig_hash_find
(
bat_priv
,
icmp_packet
->
orig
);
orig_node
=
orig_hash_find
(
bat_priv
,
icmp_packet
->
orig
);
if
(
!
orig_node
)
if
(
!
orig_node
)
goto
unlock
;
goto
out
;
neigh_node
=
orig_node
->
router
;
if
(
!
neigh_node
)
goto
unlock
;
if
(
!
atomic_inc_not_zero
(
&
neigh_node
->
refcount
))
{
neigh_node
=
NULL
;
goto
unlock
;
}
rcu_read_unlock
();
router
=
orig_node_get_router
(
orig_node
);
if
(
!
router
)
goto
out
;
/* create a copy of the skb, if needed, to modify it. */
/* create a copy of the skb, if needed, to modify it. */
if
(
skb_cow
(
skb
,
sizeof
(
struct
ethhdr
))
<
0
)
if
(
skb_cow
(
skb
,
sizeof
(
struct
ethhdr
))
<
0
)
...
@@ -916,15 +942,12 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
...
@@ -916,15 +942,12 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
icmp_packet
->
msg_type
=
ECHO_REPLY
;
icmp_packet
->
msg_type
=
ECHO_REPLY
;
icmp_packet
->
ttl
=
TTL
;
icmp_packet
->
ttl
=
TTL
;
send_skb_packet
(
skb
,
neigh_node
->
if_incoming
,
neigh_node
->
addr
);
send_skb_packet
(
skb
,
router
->
if_incoming
,
router
->
addr
);
ret
=
NET_RX_SUCCESS
;
ret
=
NET_RX_SUCCESS
;
goto
out
;
unlock:
rcu_read_unlock
();
out:
out:
if
(
neigh_node
)
if
(
router
)
neigh_node_free_ref
(
neigh_node
);
neigh_node_free_ref
(
router
);
if
(
orig_node
)
if
(
orig_node
)
orig_node_free_ref
(
orig_node
);
orig_node_free_ref
(
orig_node
);
return
ret
;
return
ret
;
...
@@ -934,7 +957,7 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
...
@@ -934,7 +957,7 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
struct
sk_buff
*
skb
)
struct
sk_buff
*
skb
)
{
{
struct
orig_node
*
orig_node
=
NULL
;
struct
orig_node
*
orig_node
=
NULL
;
struct
neigh_node
*
neigh_node
=
NULL
;
struct
neigh_node
*
router
=
NULL
;
struct
icmp_packet
*
icmp_packet
;
struct
icmp_packet
*
icmp_packet
;
int
ret
=
NET_RX_DROP
;
int
ret
=
NET_RX_DROP
;
...
@@ -952,23 +975,13 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
...
@@ -952,23 +975,13 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
goto
out
;
goto
out
;
/* get routing information */
/* get routing information */
rcu_read_lock
();
orig_node
=
orig_hash_find
(
bat_priv
,
icmp_packet
->
orig
);
orig_node
=
orig_hash_find
(
bat_priv
,
icmp_packet
->
orig
);
if
(
!
orig_node
)
if
(
!
orig_node
)
goto
unlock
;
goto
out
;
neigh_node
=
orig_node
->
router
;
if
(
!
neigh_node
)
goto
unlock
;
if
(
!
atomic_inc_not_zero
(
&
neigh_node
->
refcount
))
{
neigh_node
=
NULL
;
goto
unlock
;
}
rcu_read_unlock
();
router
=
orig_node_get_router
(
orig_node
);
if
(
!
router
)
goto
out
;
/* create a copy of the skb, if needed, to modify it. */
/* create a copy of the skb, if needed, to modify it. */
if
(
skb_cow
(
skb
,
sizeof
(
struct
ethhdr
))
<
0
)
if
(
skb_cow
(
skb
,
sizeof
(
struct
ethhdr
))
<
0
)
...
@@ -982,15 +995,12 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
...
@@ -982,15 +995,12 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
icmp_packet
->
msg_type
=
TTL_EXCEEDED
;
icmp_packet
->
msg_type
=
TTL_EXCEEDED
;
icmp_packet
->
ttl
=
TTL
;
icmp_packet
->
ttl
=
TTL
;
send_skb_packet
(
skb
,
neigh_node
->
if_incoming
,
neigh_node
->
addr
);
send_skb_packet
(
skb
,
router
->
if_incoming
,
router
->
addr
);
ret
=
NET_RX_SUCCESS
;
ret
=
NET_RX_SUCCESS
;
goto
out
;
unlock:
rcu_read_unlock
();
out:
out:
if
(
neigh_node
)
if
(
router
)
neigh_node_free_ref
(
neigh_node
);
neigh_node_free_ref
(
router
);
if
(
orig_node
)
if
(
orig_node
)
orig_node_free_ref
(
orig_node
);
orig_node_free_ref
(
orig_node
);
return
ret
;
return
ret
;
...
@@ -1003,7 +1013,7 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if)
...
@@ -1003,7 +1013,7 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if)
struct
icmp_packet_rr
*
icmp_packet
;
struct
icmp_packet_rr
*
icmp_packet
;
struct
ethhdr
*
ethhdr
;
struct
ethhdr
*
ethhdr
;
struct
orig_node
*
orig_node
=
NULL
;
struct
orig_node
*
orig_node
=
NULL
;
struct
neigh_node
*
neigh_node
=
NULL
;
struct
neigh_node
*
router
=
NULL
;
int
hdr_size
=
sizeof
(
struct
icmp_packet
);
int
hdr_size
=
sizeof
(
struct
icmp_packet
);
int
ret
=
NET_RX_DROP
;
int
ret
=
NET_RX_DROP
;
...
@@ -1050,23 +1060,13 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if)
...
@@ -1050,23 +1060,13 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if)
return
recv_icmp_ttl_exceeded
(
bat_priv
,
skb
);
return
recv_icmp_ttl_exceeded
(
bat_priv
,
skb
);
/* get routing information */
/* get routing information */
rcu_read_lock
();
orig_node
=
orig_hash_find
(
bat_priv
,
icmp_packet
->
dst
);
orig_node
=
orig_hash_find
(
bat_priv
,
icmp_packet
->
dst
);
if
(
!
orig_node
)
if
(
!
orig_node
)
goto
unlock
;
goto
out
;
neigh_node
=
orig_node
->
router
;
if
(
!
neigh_node
)
goto
unlock
;
if
(
!
atomic_inc_not_zero
(
&
neigh_node
->
refcount
))
{
neigh_node
=
NULL
;
goto
unlock
;
}
rcu_read_unlock
();
router
=
orig_node_get_router
(
orig_node
);
if
(
!
router
)
goto
out
;
/* create a copy of the skb, if needed, to modify it. */
/* create a copy of the skb, if needed, to modify it. */
if
(
skb_cow
(
skb
,
sizeof
(
struct
ethhdr
))
<
0
)
if
(
skb_cow
(
skb
,
sizeof
(
struct
ethhdr
))
<
0
)
...
@@ -1078,20 +1078,117 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if)
...
@@ -1078,20 +1078,117 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if)
icmp_packet
->
ttl
--
;
icmp_packet
->
ttl
--
;
/* route it */
/* route it */
send_skb_packet
(
skb
,
neigh_node
->
if_incoming
,
neigh_node
->
addr
);
send_skb_packet
(
skb
,
router
->
if_incoming
,
router
->
addr
);
ret
=
NET_RX_SUCCESS
;
ret
=
NET_RX_SUCCESS
;
goto
out
;
unlock:
rcu_read_unlock
();
out:
out:
if
(
neigh_node
)
if
(
router
)
neigh_node_free_ref
(
neigh_node
);
neigh_node_free_ref
(
router
);
if
(
orig_node
)
if
(
orig_node
)
orig_node_free_ref
(
orig_node
);
orig_node_free_ref
(
orig_node
);
return
ret
;
return
ret
;
}
}
/* In the bonding case, send the packets in a round
* robin fashion over the remaining interfaces.
*
* This method rotates the bonding list and increases the
* returned router's refcount. */
static
struct
neigh_node
*
find_bond_router
(
struct
orig_node
*
primary_orig
,
struct
hard_iface
*
recv_if
)
{
struct
neigh_node
*
tmp_neigh_node
;
struct
neigh_node
*
router
=
NULL
,
*
first_candidate
=
NULL
;
rcu_read_lock
();
list_for_each_entry_rcu
(
tmp_neigh_node
,
&
primary_orig
->
bond_list
,
bonding_list
)
{
if
(
!
first_candidate
)
first_candidate
=
tmp_neigh_node
;
/* recv_if == NULL on the first node. */
if
(
tmp_neigh_node
->
if_incoming
==
recv_if
)
continue
;
if
(
!
atomic_inc_not_zero
(
&
tmp_neigh_node
->
refcount
))
continue
;
router
=
tmp_neigh_node
;
break
;
}
/* use the first candidate if nothing was found. */
if
(
!
router
&&
first_candidate
&&
atomic_inc_not_zero
(
&
first_candidate
->
refcount
))
router
=
first_candidate
;
if
(
!
router
)
goto
out
;
/* selected should point to the next element
* after the current router */
spin_lock_bh
(
&
primary_orig
->
neigh_list_lock
);
/* this is a list_move(), which unfortunately
* does not exist as rcu version */
list_del_rcu
(
&
primary_orig
->
bond_list
);
list_add_rcu
(
&
primary_orig
->
bond_list
,
&
router
->
bonding_list
);
spin_unlock_bh
(
&
primary_orig
->
neigh_list_lock
);
out:
rcu_read_unlock
();
return
router
;
}
/* Interface Alternating: Use the best of the
* remaining candidates which are not using
* this interface.
*
* Increases the returned router's refcount */
static
struct
neigh_node
*
find_ifalter_router
(
struct
orig_node
*
primary_orig
,
struct
hard_iface
*
recv_if
)
{
struct
neigh_node
*
tmp_neigh_node
;
struct
neigh_node
*
router
=
NULL
,
*
first_candidate
=
NULL
;
rcu_read_lock
();
list_for_each_entry_rcu
(
tmp_neigh_node
,
&
primary_orig
->
bond_list
,
bonding_list
)
{
if
(
!
first_candidate
)
first_candidate
=
tmp_neigh_node
;
/* recv_if == NULL on the first node. */
if
(
tmp_neigh_node
->
if_incoming
==
recv_if
)
continue
;
if
(
!
atomic_inc_not_zero
(
&
tmp_neigh_node
->
refcount
))
continue
;
/* if we don't have a router yet
* or this one is better, choose it. */
if
((
!
router
)
||
(
tmp_neigh_node
->
tq_avg
>
router
->
tq_avg
))
{
/* decrement refcount of
* previously selected router */
if
(
router
)
neigh_node_free_ref
(
router
);
router
=
tmp_neigh_node
;
atomic_inc_not_zero
(
&
router
->
refcount
);
}
neigh_node_free_ref
(
tmp_neigh_node
);
}
/* use the first candidate if nothing was found. */
if
(
!
router
&&
first_candidate
&&
atomic_inc_not_zero
(
&
first_candidate
->
refcount
))
router
=
first_candidate
;
rcu_read_unlock
();
return
router
;
}
/* find a suitable router for this originator, and use
/* find a suitable router for this originator, and use
* bonding if possible. increases the found neighbors
* bonding if possible. increases the found neighbors
* refcount.*/
* refcount.*/
...
@@ -1101,14 +1198,15 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
...
@@ -1101,14 +1198,15 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
{
{
struct
orig_node
*
primary_orig_node
;
struct
orig_node
*
primary_orig_node
;
struct
orig_node
*
router_orig
;
struct
orig_node
*
router_orig
;
struct
neigh_node
*
router
,
*
first_candidate
,
*
tmp_neigh_node
;
struct
neigh_node
*
router
;
static
uint8_t
zero_mac
[
ETH_ALEN
]
=
{
0
,
0
,
0
,
0
,
0
,
0
};
static
uint8_t
zero_mac
[
ETH_ALEN
]
=
{
0
,
0
,
0
,
0
,
0
,
0
};
int
bonding_enabled
;
int
bonding_enabled
;
if
(
!
orig_node
)
if
(
!
orig_node
)
return
NULL
;
return
NULL
;
if
(
!
orig_node
->
router
)
router
=
orig_node_get_router
(
orig_node
);
if
(
!
router
)
return
NULL
;
return
NULL
;
/* without bonding, the first node should
/* without bonding, the first node should
...
@@ -1117,9 +1215,8 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
...
@@ -1117,9 +1215,8 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
rcu_read_lock
();
rcu_read_lock
();
/* select default router to output */
/* select default router to output */
router
=
orig_node
->
router
;
router_orig
=
router
->
orig_node
;
router_orig
=
orig_node
->
router
->
orig_node
;
if
(
!
router_orig
)
{
if
(
!
router_orig
||
!
atomic_inc_not_zero
(
&
router
->
refcount
))
{
rcu_read_unlock
();
rcu_read_unlock
();
return
NULL
;
return
NULL
;
}
}
...
@@ -1151,88 +1248,17 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
...
@@ -1151,88 +1248,17 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
if
(
atomic_read
(
&
primary_orig_node
->
bond_candidates
)
<
2
)
if
(
atomic_read
(
&
primary_orig_node
->
bond_candidates
)
<
2
)
goto
return_router
;
goto
return_router
;
/* all nodes between should choose a candidate which
/* all nodes between should choose a candidate which
* is is not on the interface where the packet came
* is is not on the interface where the packet came
* in. */
* in. */
neigh_node_free_ref
(
router
);
neigh_node_free_ref
(
router
);
first_candidate
=
NULL
;
router
=
NULL
;
if
(
bonding_enabled
)
{
/* in the bonding case, send the packets in a round
* robin fashion over the remaining interfaces. */
list_for_each_entry_rcu
(
tmp_neigh_node
,
&
primary_orig_node
->
bond_list
,
bonding_list
)
{
if
(
!
first_candidate
)
first_candidate
=
tmp_neigh_node
;
/* recv_if == NULL on the first node. */
if
(
tmp_neigh_node
->
if_incoming
!=
recv_if
&&
atomic_inc_not_zero
(
&
tmp_neigh_node
->
refcount
))
{
router
=
tmp_neigh_node
;
break
;
}
}
/* use the first candidate if nothing was found. */
if
(
!
router
&&
first_candidate
&&
atomic_inc_not_zero
(
&
first_candidate
->
refcount
))
router
=
first_candidate
;
if
(
!
router
)
{
rcu_read_unlock
();
return
NULL
;
}
/* selected should point to the next element
* after the current router */
spin_lock_bh
(
&
primary_orig_node
->
neigh_list_lock
);
/* this is a list_move(), which unfortunately
* does not exist as rcu version */
list_del_rcu
(
&
primary_orig_node
->
bond_list
);
list_add_rcu
(
&
primary_orig_node
->
bond_list
,
&
router
->
bonding_list
);
spin_unlock_bh
(
&
primary_orig_node
->
neigh_list_lock
);
}
else
{
/* if bonding is disabled, use the best of the
* remaining candidates which are not using
* this interface. */
list_for_each_entry_rcu
(
tmp_neigh_node
,
&
primary_orig_node
->
bond_list
,
bonding_list
)
{
if
(
!
first_candidate
)
first_candidate
=
tmp_neigh_node
;
/* recv_if == NULL on the first node. */
if
(
tmp_neigh_node
->
if_incoming
==
recv_if
)
continue
;
if
(
!
atomic_inc_not_zero
(
&
tmp_neigh_node
->
refcount
))
if
(
bonding_enabled
)
continue
;
router
=
find_bond_router
(
primary_orig_node
,
recv_if
);
else
/* if we don't have a router yet
router
=
find_ifalter_router
(
primary_orig_node
,
recv_if
);
* or this one is better, choose it. */
if
((
!
router
)
||
(
tmp_neigh_node
->
tq_avg
>
router
->
tq_avg
))
{
/* decrement refcount of
* previously selected router */
if
(
router
)
neigh_node_free_ref
(
router
);
router
=
tmp_neigh_node
;
atomic_inc_not_zero
(
&
router
->
refcount
);
}
neigh_node_free_ref
(
tmp_neigh_node
);
}
/* use the first candidate if nothing was found. */
if
(
!
router
&&
first_candidate
&&
atomic_inc_not_zero
(
&
first_candidate
->
refcount
))
router
=
first_candidate
;
}
return_router:
return_router:
rcu_read_unlock
();
rcu_read_unlock
();
return
router
;
return
router
;
...
...
net/batman-adv/send.c
浏览文件 @
9c6bc165
...
@@ -308,6 +308,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
...
@@ -308,6 +308,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
struct
hard_iface
*
if_incoming
)
struct
hard_iface
*
if_incoming
)
{
{
struct
bat_priv
*
bat_priv
=
netdev_priv
(
if_incoming
->
soft_iface
);
struct
bat_priv
*
bat_priv
=
netdev_priv
(
if_incoming
->
soft_iface
);
struct
neigh_node
*
router
;
unsigned
char
in_tq
,
in_ttl
,
tq_avg
=
0
;
unsigned
char
in_tq
,
in_ttl
,
tq_avg
=
0
;
unsigned
long
send_time
;
unsigned
long
send_time
;
...
@@ -316,6 +317,8 @@ void schedule_forward_packet(struct orig_node *orig_node,
...
@@ -316,6 +317,8 @@ void schedule_forward_packet(struct orig_node *orig_node,
return
;
return
;
}
}
router
=
orig_node_get_router
(
orig_node
);
in_tq
=
batman_packet
->
tq
;
in_tq
=
batman_packet
->
tq
;
in_ttl
=
batman_packet
->
ttl
;
in_ttl
=
batman_packet
->
ttl
;
...
@@ -324,20 +327,22 @@ void schedule_forward_packet(struct orig_node *orig_node,
...
@@ -324,20 +327,22 @@ void schedule_forward_packet(struct orig_node *orig_node,
/* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast
/* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast
* of our best tq value */
* of our best tq value */
if
(
(
orig_node
->
router
)
&&
(
orig_node
->
router
->
tq_avg
!=
0
)
)
{
if
(
router
&&
router
->
tq_avg
!=
0
)
{
/* rebroadcast ogm of best ranking neighbor as is */
/* rebroadcast ogm of best ranking neighbor as is */
if
(
!
compare_eth
(
orig_node
->
router
->
addr
,
ethhdr
->
h_source
))
{
if
(
!
compare_eth
(
router
->
addr
,
ethhdr
->
h_source
))
{
batman_packet
->
tq
=
orig_node
->
router
->
tq_avg
;
batman_packet
->
tq
=
router
->
tq_avg
;
if
(
orig_node
->
router
->
last_ttl
)
if
(
router
->
last_ttl
)
batman_packet
->
ttl
=
orig_node
->
router
->
last_ttl
batman_packet
->
ttl
=
router
->
last_ttl
-
1
;
-
1
;
}
}
tq_avg
=
orig_node
->
router
->
tq_avg
;
tq_avg
=
router
->
tq_avg
;
}
}
if
(
router
)
neigh_node_free_ref
(
router
);
/* apply hop penalty */
/* apply hop penalty */
batman_packet
->
tq
=
hop_penalty
(
batman_packet
->
tq
,
bat_priv
);
batman_packet
->
tq
=
hop_penalty
(
batman_packet
->
tq
,
bat_priv
);
...
...
net/batman-adv/soft-interface.c
浏览文件 @
9c6bc165
...
@@ -90,10 +90,51 @@ static void softif_neigh_free_ref(struct softif_neigh *softif_neigh)
...
@@ -90,10 +90,51 @@ static void softif_neigh_free_ref(struct softif_neigh *softif_neigh)
call_rcu
(
&
softif_neigh
->
rcu
,
softif_neigh_free_rcu
);
call_rcu
(
&
softif_neigh
->
rcu
,
softif_neigh_free_rcu
);
}
}
static
struct
softif_neigh
*
softif_neigh_get_selected
(
struct
bat_priv
*
bat_priv
)
{
struct
softif_neigh
*
neigh
;
rcu_read_lock
();
neigh
=
rcu_dereference
(
bat_priv
->
softif_neigh
);
if
(
neigh
&&
!
atomic_inc_not_zero
(
&
neigh
->
refcount
))
neigh
=
NULL
;
rcu_read_unlock
();
return
neigh
;
}
static
void
softif_neigh_select
(
struct
bat_priv
*
bat_priv
,
struct
softif_neigh
*
new_neigh
)
{
struct
softif_neigh
*
curr_neigh
;
spin_lock_bh
(
&
bat_priv
->
softif_neigh_lock
);
if
(
new_neigh
&&
!
atomic_inc_not_zero
(
&
new_neigh
->
refcount
))
new_neigh
=
NULL
;
curr_neigh
=
bat_priv
->
softif_neigh
;
rcu_assign_pointer
(
bat_priv
->
softif_neigh
,
new_neigh
);
if
(
curr_neigh
)
softif_neigh_free_ref
(
curr_neigh
);
spin_unlock_bh
(
&
bat_priv
->
softif_neigh_lock
);
}
static
void
softif_neigh_deselect
(
struct
bat_priv
*
bat_priv
)
{
softif_neigh_select
(
bat_priv
,
NULL
);
}
void
softif_neigh_purge
(
struct
bat_priv
*
bat_priv
)
void
softif_neigh_purge
(
struct
bat_priv
*
bat_priv
)
{
{
struct
softif_neigh
*
softif_neigh
,
*
softif_neigh_tmp
;
struct
softif_neigh
*
softif_neigh
,
*
curr_softif_neigh
;
struct
hlist_node
*
node
,
*
node_tmp
;
struct
hlist_node
*
node
,
*
node_tmp
;
char
do_deselect
=
0
;
curr_softif_neigh
=
softif_neigh_get_selected
(
bat_priv
);
spin_lock_bh
(
&
bat_priv
->
softif_neigh_lock
);
spin_lock_bh
(
&
bat_priv
->
softif_neigh_lock
);
...
@@ -105,22 +146,26 @@ void softif_neigh_purge(struct bat_priv *bat_priv)
...
@@ -105,22 +146,26 @@ void softif_neigh_purge(struct bat_priv *bat_priv)
(
atomic_read
(
&
bat_priv
->
mesh_state
)
==
MESH_ACTIVE
))
(
atomic_read
(
&
bat_priv
->
mesh_state
)
==
MESH_ACTIVE
))
continue
;
continue
;
hlist_del_rcu
(
&
softif_neigh
->
list
);
if
(
curr_softif_neigh
==
softif_neigh
)
{
if
(
bat_priv
->
softif_neigh
==
softif_neigh
)
{
bat_dbg
(
DBG_ROUTES
,
bat_priv
,
bat_dbg
(
DBG_ROUTES
,
bat_priv
,
"Current mesh exit point '%pM' vanished "
"Current mesh exit point '%pM' vanished "
"(vid: %d).
\n
"
,
"(vid: %d).
\n
"
,
softif_neigh
->
addr
,
softif_neigh
->
vid
);
softif_neigh
->
addr
,
softif_neigh
->
vid
);
softif_neigh_tmp
=
bat_priv
->
softif_neigh
;
do_deselect
=
1
;
bat_priv
->
softif_neigh
=
NULL
;
softif_neigh_free_ref
(
softif_neigh_tmp
);
}
}
hlist_del_rcu
(
&
softif_neigh
->
list
);
softif_neigh_free_ref
(
softif_neigh
);
softif_neigh_free_ref
(
softif_neigh
);
}
}
spin_unlock_bh
(
&
bat_priv
->
softif_neigh_lock
);
spin_unlock_bh
(
&
bat_priv
->
softif_neigh_lock
);
/* soft_neigh_deselect() needs to acquire the softif_neigh_lock */
if
(
do_deselect
)
softif_neigh_deselect
(
bat_priv
);
if
(
curr_softif_neigh
)
softif_neigh_free_ref
(
curr_softif_neigh
);
}
}
static
struct
softif_neigh
*
softif_neigh_get
(
struct
bat_priv
*
bat_priv
,
static
struct
softif_neigh
*
softif_neigh_get
(
struct
bat_priv
*
bat_priv
,
...
@@ -171,6 +216,7 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
...
@@ -171,6 +216,7 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
struct
bat_priv
*
bat_priv
=
netdev_priv
(
net_dev
);
struct
bat_priv
*
bat_priv
=
netdev_priv
(
net_dev
);
struct
softif_neigh
*
softif_neigh
;
struct
softif_neigh
*
softif_neigh
;
struct
hlist_node
*
node
;
struct
hlist_node
*
node
;
struct
softif_neigh
*
curr_softif_neigh
;
if
(
!
bat_priv
->
primary_if
)
{
if
(
!
bat_priv
->
primary_if
)
{
return
seq_printf
(
seq
,
"BATMAN mesh %s disabled - "
return
seq_printf
(
seq
,
"BATMAN mesh %s disabled - "
...
@@ -180,14 +226,17 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
...
@@ -180,14 +226,17 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
seq_printf
(
seq
,
"Softif neighbor list (%s)
\n
"
,
net_dev
->
name
);
seq_printf
(
seq
,
"Softif neighbor list (%s)
\n
"
,
net_dev
->
name
);
curr_softif_neigh
=
softif_neigh_get_selected
(
bat_priv
);
rcu_read_lock
();
rcu_read_lock
();
hlist_for_each_entry_rcu
(
softif_neigh
,
node
,
hlist_for_each_entry_rcu
(
softif_neigh
,
node
,
&
bat_priv
->
softif_neigh_list
,
list
)
&
bat_priv
->
softif_neigh_list
,
list
)
seq_printf
(
seq
,
"%s %pM (vid: %d)
\n
"
,
seq_printf
(
seq
,
"%s %pM (vid: %d)
\n
"
,
bat_priv
->
softif_neigh
==
softif_neigh
curr_
softif_neigh
==
softif_neigh
?
"=>"
:
" "
,
softif_neigh
->
addr
,
?
"=>"
:
" "
,
softif_neigh
->
addr
,
softif_neigh
->
vid
);
softif_neigh
->
vid
);
rcu_read_unlock
();
rcu_read_unlock
();
if
(
curr_softif_neigh
)
softif_neigh_free_ref
(
curr_softif_neigh
);
return
0
;
return
0
;
}
}
...
@@ -198,7 +247,8 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
...
@@ -198,7 +247,8 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
struct
bat_priv
*
bat_priv
=
netdev_priv
(
dev
);
struct
bat_priv
*
bat_priv
=
netdev_priv
(
dev
);
struct
ethhdr
*
ethhdr
=
(
struct
ethhdr
*
)
skb
->
data
;
struct
ethhdr
*
ethhdr
=
(
struct
ethhdr
*
)
skb
->
data
;
struct
batman_packet
*
batman_packet
;
struct
batman_packet
*
batman_packet
;
struct
softif_neigh
*
softif_neigh
,
*
softif_neigh_tmp
;
struct
softif_neigh
*
softif_neigh
;
struct
softif_neigh
*
curr_softif_neigh
=
NULL
;
if
(
ntohs
(
ethhdr
->
h_proto
)
==
ETH_P_8021Q
)
if
(
ntohs
(
ethhdr
->
h_proto
)
==
ETH_P_8021Q
)
batman_packet
=
(
struct
batman_packet
*
)
batman_packet
=
(
struct
batman_packet
*
)
...
@@ -223,7 +273,8 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
...
@@ -223,7 +273,8 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
if
(
!
softif_neigh
)
if
(
!
softif_neigh
)
goto
err
;
goto
err
;
if
(
bat_priv
->
softif_neigh
==
softif_neigh
)
curr_softif_neigh
=
softif_neigh_get_selected
(
bat_priv
);
if
(
curr_softif_neigh
==
softif_neigh
)
goto
out
;
goto
out
;
/* we got a neighbor but its mac is 'bigger' than ours */
/* we got a neighbor but its mac is 'bigger' than ours */
...
@@ -232,38 +283,39 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
...
@@ -232,38 +283,39 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
goto
out
;
goto
out
;
/* switch to new 'smallest neighbor' */
/* switch to new 'smallest neighbor' */
if
((
bat_priv
->
softif_neigh
)
&&
if
((
curr_
softif_neigh
)
&&
(
memcmp
(
softif_neigh
->
addr
,
bat_priv
->
softif_neigh
->
addr
,
(
memcmp
(
softif_neigh
->
addr
,
curr_
softif_neigh
->
addr
,
ETH_ALEN
)
<
0
))
{
ETH_ALEN
)
<
0
))
{
bat_dbg
(
DBG_ROUTES
,
bat_priv
,
bat_dbg
(
DBG_ROUTES
,
bat_priv
,
"Changing mesh exit point from %pM (vid: %d) "
"Changing mesh exit point from %pM (vid: %d) "
"to %pM (vid: %d).
\n
"
,
"to %pM (vid: %d).
\n
"
,
bat_priv
->
softif_neigh
->
addr
,
curr_
softif_neigh
->
addr
,
bat_priv
->
softif_neigh
->
vid
,
curr_
softif_neigh
->
vid
,
softif_neigh
->
addr
,
softif_neigh
->
vid
);
softif_neigh
->
addr
,
softif_neigh
->
vid
);
softif_neigh_tmp
=
bat_priv
->
softif_neigh
;
bat_priv
->
softif_neigh
=
softif_neigh
;
softif_neigh_select
(
bat_priv
,
softif_neigh
);
softif_neigh_free_ref
(
softif_neigh_tmp
);
goto
out
;
/* we need to hold the additional reference */
goto
err
;
}
}
/* close own batX device and use softif_neigh as exit node */
/* close own batX device and use softif_neigh as exit node */
if
((
!
bat_priv
->
softif_neigh
)
&&
if
((
!
curr_
softif_neigh
)
&&
(
memcmp
(
softif_neigh
->
addr
,
(
memcmp
(
softif_neigh
->
addr
,
bat_priv
->
primary_if
->
net_dev
->
dev_addr
,
ETH_ALEN
)
<
0
))
{
bat_priv
->
primary_if
->
net_dev
->
dev_addr
,
ETH_ALEN
)
<
0
))
{
bat_dbg
(
DBG_ROUTES
,
bat_priv
,
bat_dbg
(
DBG_ROUTES
,
bat_priv
,
"Setting mesh exit point to %pM (vid: %d).
\n
"
,
"Setting mesh exit point to %pM (vid: %d).
\n
"
,
softif_neigh
->
addr
,
softif_neigh
->
vid
);
softif_neigh
->
addr
,
softif_neigh
->
vid
);
bat_priv
->
softif_neigh
=
softif_neigh
;
/* we need to hold the additional reference */
softif_neigh_select
(
bat_priv
,
softif_neigh
);
goto
err
;
goto
out
;
}
}
out:
out:
softif_neigh_free_ref
(
softif_neigh
);
softif_neigh_free_ref
(
softif_neigh
);
err:
err:
kfree_skb
(
skb
);
kfree_skb
(
skb
);
if
(
curr_softif_neigh
)
softif_neigh_free_ref
(
curr_softif_neigh
);
return
;
return
;
}
}
...
@@ -321,6 +373,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
...
@@ -321,6 +373,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
struct
bat_priv
*
bat_priv
=
netdev_priv
(
soft_iface
);
struct
bat_priv
*
bat_priv
=
netdev_priv
(
soft_iface
);
struct
bcast_packet
*
bcast_packet
;
struct
bcast_packet
*
bcast_packet
;
struct
vlan_ethhdr
*
vhdr
;
struct
vlan_ethhdr
*
vhdr
;
struct
softif_neigh
*
curr_softif_neigh
=
NULL
;
int
data_len
=
skb
->
len
,
ret
;
int
data_len
=
skb
->
len
,
ret
;
short
vid
=
-
1
;
short
vid
=
-
1
;
bool
do_bcast
=
false
;
bool
do_bcast
=
false
;
...
@@ -348,7 +401,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
...
@@ -348,7 +401,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
* if we have a another chosen mesh exit node in range
* if we have a another chosen mesh exit node in range
* it will transport the packets to the mesh
* it will transport the packets to the mesh
*/
*/
if
((
bat_priv
->
softif_neigh
)
&&
(
bat_priv
->
softif_neigh
->
vid
==
vid
))
curr_softif_neigh
=
softif_neigh_get_selected
(
bat_priv
);
if
((
curr_softif_neigh
)
&&
(
curr_softif_neigh
->
vid
==
vid
))
goto
dropped
;
goto
dropped
;
/* TODO: check this for locks */
/* TODO: check this for locks */
...
@@ -410,6 +464,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
...
@@ -410,6 +464,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
dropped_freed:
dropped_freed:
bat_priv
->
stats
.
tx_dropped
++
;
bat_priv
->
stats
.
tx_dropped
++
;
end:
end:
if
(
curr_softif_neigh
)
softif_neigh_free_ref
(
curr_softif_neigh
);
return
NETDEV_TX_OK
;
return
NETDEV_TX_OK
;
}
}
...
@@ -421,6 +477,7 @@ void interface_rx(struct net_device *soft_iface,
...
@@ -421,6 +477,7 @@ void interface_rx(struct net_device *soft_iface,
struct
unicast_packet
*
unicast_packet
;
struct
unicast_packet
*
unicast_packet
;
struct
ethhdr
*
ethhdr
;
struct
ethhdr
*
ethhdr
;
struct
vlan_ethhdr
*
vhdr
;
struct
vlan_ethhdr
*
vhdr
;
struct
softif_neigh
*
curr_softif_neigh
=
NULL
;
short
vid
=
-
1
;
short
vid
=
-
1
;
int
ret
;
int
ret
;
...
@@ -450,7 +507,8 @@ void interface_rx(struct net_device *soft_iface,
...
@@ -450,7 +507,8 @@ void interface_rx(struct net_device *soft_iface,
* if we have a another chosen mesh exit node in range
* if we have a another chosen mesh exit node in range
* it will transport the packets to the non-mesh network
* it will transport the packets to the non-mesh network
*/
*/
if
((
bat_priv
->
softif_neigh
)
&&
(
bat_priv
->
softif_neigh
->
vid
==
vid
))
{
curr_softif_neigh
=
softif_neigh_get_selected
(
bat_priv
);
if
(
curr_softif_neigh
&&
(
curr_softif_neigh
->
vid
==
vid
))
{
skb_push
(
skb
,
hdr_size
);
skb_push
(
skb
,
hdr_size
);
unicast_packet
=
(
struct
unicast_packet
*
)
skb
->
data
;
unicast_packet
=
(
struct
unicast_packet
*
)
skb
->
data
;
...
@@ -461,7 +519,7 @@ void interface_rx(struct net_device *soft_iface,
...
@@ -461,7 +519,7 @@ void interface_rx(struct net_device *soft_iface,
skb_reset_mac_header
(
skb
);
skb_reset_mac_header
(
skb
);
memcpy
(
unicast_packet
->
dest
,
memcpy
(
unicast_packet
->
dest
,
bat_priv
->
softif_neigh
->
addr
,
ETH_ALEN
);
curr_
softif_neigh
->
addr
,
ETH_ALEN
);
ret
=
route_unicast_packet
(
skb
,
recv_if
);
ret
=
route_unicast_packet
(
skb
,
recv_if
);
if
(
ret
==
NET_RX_DROP
)
if
(
ret
==
NET_RX_DROP
)
goto
dropped
;
goto
dropped
;
...
@@ -486,11 +544,13 @@ void interface_rx(struct net_device *soft_iface,
...
@@ -486,11 +544,13 @@ void interface_rx(struct net_device *soft_iface,
soft_iface
->
last_rx
=
jiffies
;
soft_iface
->
last_rx
=
jiffies
;
netif_rx
(
skb
);
netif_rx
(
skb
);
return
;
goto
out
;
dropped:
dropped:
kfree_skb
(
skb
);
kfree_skb
(
skb
);
out:
out:
if
(
curr_softif_neigh
)
softif_neigh_free_ref
(
curr_softif_neigh
);
return
;
return
;
}
}
...
@@ -524,6 +584,7 @@ static void interface_setup(struct net_device *dev)
...
@@ -524,6 +584,7 @@ static void interface_setup(struct net_device *dev)
dev
->
hard_start_xmit
=
interface_tx
;
dev
->
hard_start_xmit
=
interface_tx
;
#endif
#endif
dev
->
destructor
=
free_netdev
;
dev
->
destructor
=
free_netdev
;
dev
->
tx_queue_len
=
0
;
/**
/**
* can't call min_mtu, because the needed variables
* can't call min_mtu, because the needed variables
...
...
net/batman-adv/types.h
浏览文件 @
9c6bc165
...
@@ -67,7 +67,7 @@ struct hard_iface {
...
@@ -67,7 +67,7 @@ struct hard_iface {
struct
orig_node
{
struct
orig_node
{
uint8_t
orig
[
ETH_ALEN
];
uint8_t
orig
[
ETH_ALEN
];
uint8_t
primary_addr
[
ETH_ALEN
];
uint8_t
primary_addr
[
ETH_ALEN
];
struct
neigh_node
*
router
;
struct
neigh_node
__rcu
*
router
;
/* rcu protected pointer */
unsigned
long
*
bcast_own
;
unsigned
long
*
bcast_own
;
uint8_t
*
bcast_own_sum
;
uint8_t
*
bcast_own_sum
;
unsigned
long
last_valid
;
unsigned
long
last_valid
;
...
@@ -83,7 +83,7 @@ struct orig_node {
...
@@ -83,7 +83,7 @@ struct orig_node {
uint32_t
last_bcast_seqno
;
uint32_t
last_bcast_seqno
;
struct
hlist_head
neigh_list
;
struct
hlist_head
neigh_list
;
struct
list_head
frag_list
;
struct
list_head
frag_list
;
spinlock_t
neigh_list_lock
;
/* protects neigh
bor list
*/
spinlock_t
neigh_list_lock
;
/* protects neigh
_list and router
*/
atomic_t
refcount
;
atomic_t
refcount
;
struct
rcu_head
rcu
;
struct
rcu_head
rcu
;
struct
hlist_node
hash_entry
;
struct
hlist_node
hash_entry
;
...
@@ -125,6 +125,7 @@ struct neigh_node {
...
@@ -125,6 +125,7 @@ struct neigh_node {
struct
rcu_head
rcu
;
struct
rcu_head
rcu
;
struct
orig_node
*
orig_node
;
struct
orig_node
*
orig_node
;
struct
hard_iface
*
if_incoming
;
struct
hard_iface
*
if_incoming
;
spinlock_t
tq_lock
;
/* protects: tq_recv, tq_index */
};
};
...
@@ -146,7 +147,7 @@ struct bat_priv {
...
@@ -146,7 +147,7 @@ struct bat_priv {
atomic_t
batman_queue_left
;
atomic_t
batman_queue_left
;
char
num_ifaces
;
char
num_ifaces
;
struct
hlist_head
softif_neigh_list
;
struct
hlist_head
softif_neigh_list
;
struct
softif_neigh
*
softif_neigh
;
struct
softif_neigh
__rcu
*
softif_neigh
;
struct
debug_log
*
debug_log
;
struct
debug_log
*
debug_log
;
struct
hard_iface
*
primary_if
;
struct
hard_iface
*
primary_if
;
struct
kobject
*
mesh_obj
;
struct
kobject
*
mesh_obj
;
...
...
net/batman-adv/unicast.c
浏览文件 @
9c6bc165
...
@@ -289,7 +289,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
...
@@ -289,7 +289,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
/* get routing information */
/* get routing information */
if
(
is_multicast_ether_addr
(
ethhdr
->
h_dest
))
{
if
(
is_multicast_ether_addr
(
ethhdr
->
h_dest
))
{
orig_node
=
(
struct
orig_node
*
)
gw_get_selected
(
bat_priv
);
orig_node
=
(
struct
orig_node
*
)
gw_get_selected
_orig
(
bat_priv
);
if
(
orig_node
)
if
(
orig_node
)
goto
find_router
;
goto
find_router
;
}
}
...
...
net/batman-adv/vis.c
浏览文件 @
9c6bc165
...
@@ -558,6 +558,7 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
...
@@ -558,6 +558,7 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
struct
vis_info
*
info
)
struct
vis_info
*
info
)
{
{
struct
hashtable_t
*
hash
=
bat_priv
->
orig_hash
;
struct
hashtable_t
*
hash
=
bat_priv
->
orig_hash
;
struct
neigh_node
*
router
;
struct
hlist_node
*
node
;
struct
hlist_node
*
node
;
struct
hlist_head
*
head
;
struct
hlist_head
*
head
;
struct
orig_node
*
orig_node
;
struct
orig_node
*
orig_node
;
...
@@ -571,13 +572,17 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
...
@@ -571,13 +572,17 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
rcu_read_lock
();
rcu_read_lock
();
hlist_for_each_entry_rcu
(
orig_node
,
node
,
head
,
hash_entry
)
{
hlist_for_each_entry_rcu
(
orig_node
,
node
,
head
,
hash_entry
)
{
if
((
orig_node
)
&&
(
orig_node
->
router
)
&&
router
=
orig_node_get_router
(
orig_node
);
(
orig_node
->
flags
&
VIS_SERVER
)
&&
if
(
!
router
)
(
orig_node
->
router
->
tq_avg
>
best_tq
))
{
continue
;
best_tq
=
orig_node
->
router
->
tq_avg
;
if
((
orig_node
->
flags
&
VIS_SERVER
)
&&
(
router
->
tq_avg
>
best_tq
))
{
best_tq
=
router
->
tq_avg
;
memcpy
(
packet
->
target_orig
,
orig_node
->
orig
,
memcpy
(
packet
->
target_orig
,
orig_node
->
orig
,
ETH_ALEN
);
ETH_ALEN
);
}
}
neigh_node_free_ref
(
router
);
}
}
rcu_read_unlock
();
rcu_read_unlock
();
}
}
...
@@ -605,7 +610,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
...
@@ -605,7 +610,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
struct
hlist_node
*
node
;
struct
hlist_node
*
node
;
struct
hlist_head
*
head
;
struct
hlist_head
*
head
;
struct
orig_node
*
orig_node
;
struct
orig_node
*
orig_node
;
struct
neigh_node
*
neigh_node
;
struct
neigh_node
*
router
;
struct
vis_info
*
info
=
(
struct
vis_info
*
)
bat_priv
->
my_vis_info
;
struct
vis_info
*
info
=
(
struct
vis_info
*
)
bat_priv
->
my_vis_info
;
struct
vis_packet
*
packet
=
(
struct
vis_packet
*
)
info
->
skb_packet
->
data
;
struct
vis_packet
*
packet
=
(
struct
vis_packet
*
)
info
->
skb_packet
->
data
;
struct
vis_info_entry
*
entry
;
struct
vis_info_entry
*
entry
;
...
@@ -633,30 +638,32 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
...
@@ -633,30 +638,32 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
rcu_read_lock
();
rcu_read_lock
();
hlist_for_each_entry_rcu
(
orig_node
,
node
,
head
,
hash_entry
)
{
hlist_for_each_entry_rcu
(
orig_node
,
node
,
head
,
hash_entry
)
{
neigh_node
=
orig_node
->
router
;
router
=
orig_node_get_router
(
orig_node
);
if
(
!
router
)
if
(
!
neigh_node
)
continue
;
continue
;
if
(
!
compare_eth
(
neigh_node
->
addr
,
orig_node
->
orig
))
if
(
!
compare_eth
(
router
->
addr
,
orig_node
->
orig
))
continue
;
goto
next
;
if
(
neigh_node
->
if_incoming
->
if_status
!=
IF_ACTIVE
)
if
(
router
->
if_incoming
->
if_status
!=
IF_ACTIVE
)
continue
;
goto
next
;
if
(
neigh_node
->
tq_avg
<
1
)
if
(
router
->
tq_avg
<
1
)
continue
;
goto
next
;
/* fill one entry into buffer. */
/* fill one entry into buffer. */
entry
=
(
struct
vis_info_entry
*
)
entry
=
(
struct
vis_info_entry
*
)
skb_put
(
info
->
skb_packet
,
sizeof
(
*
entry
));
skb_put
(
info
->
skb_packet
,
sizeof
(
*
entry
));
memcpy
(
entry
->
src
,
memcpy
(
entry
->
src
,
neigh_node
->
if_incoming
->
net_dev
->
dev_addr
,
router
->
if_incoming
->
net_dev
->
dev_addr
,
ETH_ALEN
);
ETH_ALEN
);
memcpy
(
entry
->
dest
,
orig_node
->
orig
,
ETH_ALEN
);
memcpy
(
entry
->
dest
,
orig_node
->
orig
,
ETH_ALEN
);
entry
->
quality
=
neigh_node
->
tq_avg
;
entry
->
quality
=
router
->
tq_avg
;
packet
->
entries
++
;
packet
->
entries
++
;
next:
neigh_node_free_ref
(
router
);
if
(
vis_packet_full
(
info
))
if
(
vis_packet_full
(
info
))
goto
unlock
;
goto
unlock
;
}
}
...
@@ -725,6 +732,7 @@ static void purge_vis_packets(struct bat_priv *bat_priv)
...
@@ -725,6 +732,7 @@ static void purge_vis_packets(struct bat_priv *bat_priv)
static
void
broadcast_vis_packet
(
struct
bat_priv
*
bat_priv
,
static
void
broadcast_vis_packet
(
struct
bat_priv
*
bat_priv
,
struct
vis_info
*
info
)
struct
vis_info
*
info
)
{
{
struct
neigh_node
*
router
;
struct
hashtable_t
*
hash
=
bat_priv
->
orig_hash
;
struct
hashtable_t
*
hash
=
bat_priv
->
orig_hash
;
struct
hlist_node
*
node
;
struct
hlist_node
*
node
;
struct
hlist_head
*
head
;
struct
hlist_head
*
head
;
...
@@ -745,19 +753,26 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
...
@@ -745,19 +753,26 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
rcu_read_lock
();
rcu_read_lock
();
hlist_for_each_entry_rcu
(
orig_node
,
node
,
head
,
hash_entry
)
{
hlist_for_each_entry_rcu
(
orig_node
,
node
,
head
,
hash_entry
)
{
/* if it's a vis server and reachable, send it. */
/* if it's a vis server and reachable, send it. */
if
((
!
orig_node
)
||
(
!
orig_node
->
router
))
continue
;
if
(
!
(
orig_node
->
flags
&
VIS_SERVER
))
if
(
!
(
orig_node
->
flags
&
VIS_SERVER
))
continue
;
continue
;
router
=
orig_node_get_router
(
orig_node
);
if
(
!
router
)
continue
;
/* don't send it if we already received the packet from
/* don't send it if we already received the packet from
* this node. */
* this node. */
if
(
recv_list_is_in
(
bat_priv
,
&
info
->
recv_list
,
if
(
recv_list_is_in
(
bat_priv
,
&
info
->
recv_list
,
orig_node
->
orig
))
orig_node
->
orig
))
{
neigh_node_free_ref
(
router
);
continue
;
continue
;
}
memcpy
(
packet
->
target_orig
,
orig_node
->
orig
,
ETH_ALEN
);
memcpy
(
packet
->
target_orig
,
orig_node
->
orig
,
ETH_ALEN
);
hard_iface
=
orig_node
->
router
->
if_incoming
;
hard_iface
=
router
->
if_incoming
;
memcpy
(
dstaddr
,
orig_node
->
router
->
addr
,
ETH_ALEN
);
memcpy
(
dstaddr
,
router
->
addr
,
ETH_ALEN
);
neigh_node_free_ref
(
router
);
skb
=
skb_clone
(
info
->
skb_packet
,
GFP_ATOMIC
);
skb
=
skb_clone
(
info
->
skb_packet
,
GFP_ATOMIC
);
if
(
skb
)
if
(
skb
)
...
@@ -772,45 +787,29 @@ static void unicast_vis_packet(struct bat_priv *bat_priv,
...
@@ -772,45 +787,29 @@ static void unicast_vis_packet(struct bat_priv *bat_priv,
struct
vis_info
*
info
)
struct
vis_info
*
info
)
{
{
struct
orig_node
*
orig_node
;
struct
orig_node
*
orig_node
;
struct
neigh_node
*
neigh_node
=
NULL
;
struct
neigh_node
*
router
=
NULL
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
struct
vis_packet
*
packet
;
struct
vis_packet
*
packet
;
packet
=
(
struct
vis_packet
*
)
info
->
skb_packet
->
data
;
packet
=
(
struct
vis_packet
*
)
info
->
skb_packet
->
data
;
rcu_read_lock
();
orig_node
=
orig_hash_find
(
bat_priv
,
packet
->
target_orig
);
orig_node
=
orig_hash_find
(
bat_priv
,
packet
->
target_orig
);
if
(
!
orig_node
)
if
(
!
orig_node
)
goto
unlock
;
goto
out
;
neigh_node
=
orig_node
->
router
;
router
=
orig_node_get_router
(
orig_node
);
if
(
!
router
)
if
(
!
neigh_node
)
goto
out
;
goto
unlock
;
if
(
!
atomic_inc_not_zero
(
&
neigh_node
->
refcount
))
{
neigh_node
=
NULL
;
goto
unlock
;
}
rcu_read_unlock
();
skb
=
skb_clone
(
info
->
skb_packet
,
GFP_ATOMIC
);
skb
=
skb_clone
(
info
->
skb_packet
,
GFP_ATOMIC
);
if
(
skb
)
if
(
skb
)
send_skb_packet
(
skb
,
neigh_node
->
if_incoming
,
send_skb_packet
(
skb
,
router
->
if_incoming
,
router
->
addr
);
neigh_node
->
addr
);
goto
out
;
unlock:
rcu_read_unlock
();
out:
out:
if
(
neigh_node
)
if
(
router
)
neigh_node_free_ref
(
neigh_node
);
neigh_node_free_ref
(
router
);
if
(
orig_node
)
if
(
orig_node
)
orig_node_free_ref
(
orig_node
);
orig_node_free_ref
(
orig_node
);
return
;
}
}
/* only send one vis packet. called from send_vis_packets() */
/* only send one vis packet. called from send_vis_packets() */
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录