Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
cefd81cf
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
cefd81cf
编写于
9月 04, 2012
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
git://git.kernel.org/pub/scm/linux/kernel/git/jesse/openvswitch
上级
3731a334
15eac2a7
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
317 addition
and
171 deletion
+317
-171
net/openvswitch/actions.c
net/openvswitch/actions.c
+1
-1
net/openvswitch/datapath.c
net/openvswitch/datapath.c
+237
-138
net/openvswitch/datapath.h
net/openvswitch/datapath.h
+42
-8
net/openvswitch/dp_notify.c
net/openvswitch/dp_notify.c
+5
-3
net/openvswitch/flow.c
net/openvswitch/flow.c
+4
-7
net/openvswitch/flow.h
net/openvswitch/flow.h
+2
-1
net/openvswitch/vport-internal_dev.c
net/openvswitch/vport-internal_dev.c
+6
-1
net/openvswitch/vport-netdev.c
net/openvswitch/vport-netdev.c
+1
-1
net/openvswitch/vport.c
net/openvswitch/vport.c
+15
-8
net/openvswitch/vport.h
net/openvswitch/vport.h
+4
-3
未找到文件。
net/openvswitch/actions.c
浏览文件 @
cefd81cf
...
...
@@ -266,7 +266,7 @@ static int do_output(struct datapath *dp, struct sk_buff *skb, int out_port)
if
(
unlikely
(
!
skb
))
return
-
ENOMEM
;
vport
=
rcu_dereference
(
dp
->
ports
[
out_port
]
);
vport
=
ovs_vport_rcu
(
dp
,
out_port
);
if
(
unlikely
(
!
vport
))
{
kfree_skb
(
skb
);
return
-
ENODEV
;
...
...
net/openvswitch/datapath.c
浏览文件 @
cefd81cf
...
...
@@ -49,11 +49,28 @@
#include <linux/dmi.h>
#include <linux/workqueue.h>
#include <net/genetlink.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
#include "datapath.h"
#include "flow.h"
#include "vport-internal_dev.h"
/**
* struct ovs_net - Per net-namespace data for ovs.
* @dps: List of datapaths to enable dumping them all out.
* Protected by genl_mutex.
*/
struct
ovs_net
{
struct
list_head
dps
;
};
static
int
ovs_net_id
__read_mostly
;
#define REHASH_FLOW_INTERVAL (10 * 60 * HZ)
static
void
rehash_flow_table
(
struct
work_struct
*
work
);
static
DECLARE_DELAYED_WORK
(
rehash_flow_wq
,
rehash_flow_table
);
/**
* DOC: Locking:
*
...
...
@@ -71,29 +88,21 @@
* each other.
*/
/* Global list of datapaths to enable dumping them all out.
* Protected by genl_mutex.
*/
static
LIST_HEAD
(
dps
);
#define REHASH_FLOW_INTERVAL (10 * 60 * HZ)
static
void
rehash_flow_table
(
struct
work_struct
*
work
);
static
DECLARE_DELAYED_WORK
(
rehash_flow_wq
,
rehash_flow_table
);
static
struct
vport
*
new_vport
(
const
struct
vport_parms
*
);
static
int
queue_gso_packets
(
int
dp_ifindex
,
struct
sk_buff
*
,
static
int
queue_gso_packets
(
struct
net
*
,
int
dp_ifindex
,
struct
sk_buff
*
,
const
struct
dp_upcall_info
*
);
static
int
queue_userspace_packet
(
int
dp_ifindex
,
struct
sk_buff
*
,
static
int
queue_userspace_packet
(
struct
net
*
,
int
dp_ifindex
,
struct
sk_buff
*
,
const
struct
dp_upcall_info
*
);
/* Must be called with rcu_read_lock, genl_mutex, or RTNL lock. */
static
struct
datapath
*
get_dp
(
int
dp_ifindex
)
static
struct
datapath
*
get_dp
(
struct
net
*
net
,
int
dp_ifindex
)
{
struct
datapath
*
dp
=
NULL
;
struct
net_device
*
dev
;
rcu_read_lock
();
dev
=
dev_get_by_index_rcu
(
&
init_
net
,
dp_ifindex
);
dev
=
dev_get_by_index_rcu
(
net
,
dp_ifindex
);
if
(
dev
)
{
struct
vport
*
vport
=
ovs_internal_dev_get_vport
(
dev
);
if
(
vport
)
...
...
@@ -107,7 +116,7 @@ static struct datapath *get_dp(int dp_ifindex)
/* Must be called with rcu_read_lock or RTNL lock. */
const
char
*
ovs_dp_name
(
const
struct
datapath
*
dp
)
{
struct
vport
*
vport
=
rcu_dereference_rtnl
(
dp
->
ports
[
OVSP_LOCAL
]
);
struct
vport
*
vport
=
ovs_vport_rtnl_rcu
(
dp
,
OVSP_LOCAL
);
return
vport
->
ops
->
get_name
(
vport
);
}
...
...
@@ -118,7 +127,7 @@ static int get_dpifindex(struct datapath *dp)
rcu_read_lock
();
local
=
rcu_dereference
(
dp
->
ports
[
OVSP_LOCAL
]
);
local
=
ovs_vport_rcu
(
dp
,
OVSP_LOCAL
);
if
(
local
)
ifindex
=
local
->
ops
->
get_ifindex
(
local
);
else
...
...
@@ -135,9 +144,31 @@ static void destroy_dp_rcu(struct rcu_head *rcu)
ovs_flow_tbl_destroy
((
__force
struct
flow_table
*
)
dp
->
table
);
free_percpu
(
dp
->
stats_percpu
);
release_net
(
ovs_dp_get_net
(
dp
));
kfree
(
dp
->
ports
);
kfree
(
dp
);
}
static
struct
hlist_head
*
vport_hash_bucket
(
const
struct
datapath
*
dp
,
u16
port_no
)
{
return
&
dp
->
ports
[
port_no
&
(
DP_VPORT_HASH_BUCKETS
-
1
)];
}
struct
vport
*
ovs_lookup_vport
(
const
struct
datapath
*
dp
,
u16
port_no
)
{
struct
vport
*
vport
;
struct
hlist_node
*
n
;
struct
hlist_head
*
head
;
head
=
vport_hash_bucket
(
dp
,
port_no
);
hlist_for_each_entry_rcu
(
vport
,
n
,
head
,
dp_hash_node
)
{
if
(
vport
->
port_no
==
port_no
)
return
vport
;
}
return
NULL
;
}
/* Called with RTNL lock and genl_lock. */
static
struct
vport
*
new_vport
(
const
struct
vport_parms
*
parms
)
{
...
...
@@ -146,9 +177,9 @@ static struct vport *new_vport(const struct vport_parms *parms)
vport
=
ovs_vport_add
(
parms
);
if
(
!
IS_ERR
(
vport
))
{
struct
datapath
*
dp
=
parms
->
dp
;
struct
hlist_head
*
head
=
vport_hash_bucket
(
dp
,
vport
->
port_no
);
rcu_assign_pointer
(
dp
->
ports
[
parms
->
port_no
],
vport
);
list_add
(
&
vport
->
node
,
&
dp
->
port_list
);
hlist_add_head_rcu
(
&
vport
->
dp_hash_node
,
head
);
}
return
vport
;
...
...
@@ -160,8 +191,7 @@ void ovs_dp_detach_port(struct vport *p)
ASSERT_RTNL
();
/* First drop references to device. */
list_del
(
&
p
->
node
);
rcu_assign_pointer
(
p
->
dp
->
ports
[
p
->
port_no
],
NULL
);
hlist_del_rcu
(
&
p
->
dp_hash_node
);
/* Then destroy it. */
ovs_vport_del
(
p
);
...
...
@@ -220,11 +250,12 @@ static struct genl_family dp_packet_genl_family = {
.
hdrsize
=
sizeof
(
struct
ovs_header
),
.
name
=
OVS_PACKET_FAMILY
,
.
version
=
OVS_PACKET_VERSION
,
.
maxattr
=
OVS_PACKET_ATTR_MAX
.
maxattr
=
OVS_PACKET_ATTR_MAX
,
.
netnsok
=
true
};
int
ovs_dp_upcall
(
struct
datapath
*
dp
,
struct
sk_buff
*
skb
,
const
struct
dp_upcall_info
*
upcall_info
)
const
struct
dp_upcall_info
*
upcall_info
)
{
struct
dp_stats_percpu
*
stats
;
int
dp_ifindex
;
...
...
@@ -242,9 +273,9 @@ int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
}
if
(
!
skb_is_gso
(
skb
))
err
=
queue_userspace_packet
(
dp_ifindex
,
skb
,
upcall_info
);
err
=
queue_userspace_packet
(
ovs_dp_get_net
(
dp
),
dp_ifindex
,
skb
,
upcall_info
);
else
err
=
queue_gso_packets
(
dp_ifindex
,
skb
,
upcall_info
);
err
=
queue_gso_packets
(
ovs_dp_get_net
(
dp
),
dp_ifindex
,
skb
,
upcall_info
);
if
(
err
)
goto
err
;
...
...
@@ -260,7 +291,8 @@ int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
return
err
;
}
static
int
queue_gso_packets
(
int
dp_ifindex
,
struct
sk_buff
*
skb
,
static
int
queue_gso_packets
(
struct
net
*
net
,
int
dp_ifindex
,
struct
sk_buff
*
skb
,
const
struct
dp_upcall_info
*
upcall_info
)
{
unsigned
short
gso_type
=
skb_shinfo
(
skb
)
->
gso_type
;
...
...
@@ -276,7 +308,7 @@ static int queue_gso_packets(int dp_ifindex, struct sk_buff *skb,
/* Queue all of the segments. */
skb
=
segs
;
do
{
err
=
queue_userspace_packet
(
dp_ifindex
,
skb
,
upcall_info
);
err
=
queue_userspace_packet
(
net
,
dp_ifindex
,
skb
,
upcall_info
);
if
(
err
)
break
;
...
...
@@ -306,7 +338,8 @@ static int queue_gso_packets(int dp_ifindex, struct sk_buff *skb,
return
err
;
}
static
int
queue_userspace_packet
(
int
dp_ifindex
,
struct
sk_buff
*
skb
,
static
int
queue_userspace_packet
(
struct
net
*
net
,
int
dp_ifindex
,
struct
sk_buff
*
skb
,
const
struct
dp_upcall_info
*
upcall_info
)
{
struct
ovs_header
*
upcall
;
...
...
@@ -362,7 +395,7 @@ static int queue_userspace_packet(int dp_ifindex, struct sk_buff *skb,
skb_copy_and_csum_dev
(
skb
,
nla_data
(
nla
));
err
=
genlmsg_unicast
(
&
init_
net
,
user_skb
,
upcall_info
->
pid
);
err
=
genlmsg_unicast
(
net
,
user_skb
,
upcall_info
->
pid
);
out:
kfree_skb
(
nskb
);
...
...
@@ -370,15 +403,10 @@ static int queue_userspace_packet(int dp_ifindex, struct sk_buff *skb,
}
/* Called with genl_mutex. */
static
int
flush_flows
(
int
dp_ifindex
)
static
int
flush_flows
(
struct
datapath
*
dp
)
{
struct
flow_table
*
old_table
;
struct
flow_table
*
new_table
;
struct
datapath
*
dp
;
dp
=
get_dp
(
dp_ifindex
);
if
(
!
dp
)
return
-
ENODEV
;
old_table
=
genl_dereference
(
dp
->
table
);
new_table
=
ovs_flow_tbl_alloc
(
TBL_MIN_BUCKETS
);
...
...
@@ -668,7 +696,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
packet
->
priority
=
flow
->
key
.
phy
.
priority
;
rcu_read_lock
();
dp
=
get_dp
(
ovs_header
->
dp_ifindex
);
dp
=
get_dp
(
sock_net
(
skb
->
sk
),
ovs_header
->
dp_ifindex
);
err
=
-
ENODEV
;
if
(
!
dp
)
goto
err_unlock
;
...
...
@@ -742,7 +770,8 @@ static struct genl_family dp_flow_genl_family = {
.
hdrsize
=
sizeof
(
struct
ovs_header
),
.
name
=
OVS_FLOW_FAMILY
,
.
version
=
OVS_FLOW_VERSION
,
.
maxattr
=
OVS_FLOW_ATTR_MAX
.
maxattr
=
OVS_FLOW_ATTR_MAX
,
.
netnsok
=
true
};
static
struct
genl_multicast_group
ovs_dp_flow_multicast_group
=
{
...
...
@@ -894,7 +923,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
goto
error
;
}
dp
=
get_dp
(
ovs_header
->
dp_ifindex
);
dp
=
get_dp
(
sock_net
(
skb
->
sk
),
ovs_header
->
dp_ifindex
);
error
=
-
ENODEV
;
if
(
!
dp
)
goto
error
;
...
...
@@ -995,7 +1024,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
ovs_dp_flow_multicast_group
.
id
,
info
->
nlhdr
,
GFP_KERNEL
);
else
netlink_set_err
(
init_net
.
genl_sock
,
0
,
netlink_set_err
(
sock_net
(
skb
->
sk
)
->
genl_sock
,
0
,
ovs_dp_flow_multicast_group
.
id
,
PTR_ERR
(
reply
));
return
0
;
...
...
@@ -1023,7 +1052,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
if
(
err
)
return
err
;
dp
=
get_dp
(
ovs_header
->
dp_ifindex
);
dp
=
get_dp
(
sock_net
(
skb
->
sk
),
ovs_header
->
dp_ifindex
);
if
(
!
dp
)
return
-
ENODEV
;
...
...
@@ -1052,16 +1081,17 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
int
err
;
int
key_len
;
dp
=
get_dp
(
sock_net
(
skb
->
sk
),
ovs_header
->
dp_ifindex
);
if
(
!
dp
)
return
-
ENODEV
;
if
(
!
a
[
OVS_FLOW_ATTR_KEY
])
return
flush_flows
(
ovs_header
->
dp_ifindex
);
return
flush_flows
(
dp
);
err
=
ovs_flow_from_nlattrs
(
&
key
,
&
key_len
,
a
[
OVS_FLOW_ATTR_KEY
]);
if
(
err
)
return
err
;
dp
=
get_dp
(
ovs_header
->
dp_ifindex
);
if
(
!
dp
)
return
-
ENODEV
;
table
=
genl_dereference
(
dp
->
table
);
flow
=
ovs_flow_tbl_lookup
(
table
,
&
key
,
key_len
);
if
(
!
flow
)
...
...
@@ -1090,7 +1120,7 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
struct
datapath
*
dp
;
struct
flow_table
*
table
;
dp
=
get_dp
(
ovs_header
->
dp_ifindex
);
dp
=
get_dp
(
sock_net
(
skb
->
sk
),
ovs_header
->
dp_ifindex
);
if
(
!
dp
)
return
-
ENODEV
;
...
...
@@ -1152,7 +1182,8 @@ static struct genl_family dp_datapath_genl_family = {
.
hdrsize
=
sizeof
(
struct
ovs_header
),
.
name
=
OVS_DATAPATH_FAMILY
,
.
version
=
OVS_DATAPATH_VERSION
,
.
maxattr
=
OVS_DP_ATTR_MAX
.
maxattr
=
OVS_DP_ATTR_MAX
,
.
netnsok
=
true
};
static
struct
genl_multicast_group
ovs_dp_datapath_multicast_group
=
{
...
...
@@ -1210,18 +1241,19 @@ static struct sk_buff *ovs_dp_cmd_build_info(struct datapath *dp, u32 pid,
}
/* Called with genl_mutex and optionally with RTNL lock also. */
static
struct
datapath
*
lookup_datapath
(
struct
ovs_header
*
ovs_header
,
static
struct
datapath
*
lookup_datapath
(
struct
net
*
net
,
struct
ovs_header
*
ovs_header
,
struct
nlattr
*
a
[
OVS_DP_ATTR_MAX
+
1
])
{
struct
datapath
*
dp
;
if
(
!
a
[
OVS_DP_ATTR_NAME
])
dp
=
get_dp
(
ovs_header
->
dp_ifindex
);
dp
=
get_dp
(
net
,
ovs_header
->
dp_ifindex
);
else
{
struct
vport
*
vport
;
rcu_read_lock
();
vport
=
ovs_vport_locate
(
nla_data
(
a
[
OVS_DP_ATTR_NAME
]));
vport
=
ovs_vport_locate
(
n
et
,
n
la_data
(
a
[
OVS_DP_ATTR_NAME
]));
dp
=
vport
&&
vport
->
port_no
==
OVSP_LOCAL
?
vport
->
dp
:
NULL
;
rcu_read_unlock
();
}
...
...
@@ -1235,22 +1267,21 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
struct
sk_buff
*
reply
;
struct
datapath
*
dp
;
struct
vport
*
vport
;
int
err
;
struct
ovs_net
*
ovs_net
;
int
err
,
i
;
err
=
-
EINVAL
;
if
(
!
a
[
OVS_DP_ATTR_NAME
]
||
!
a
[
OVS_DP_ATTR_UPCALL_PID
])
goto
err
;
rtnl_lock
();
err
=
-
ENODEV
;
if
(
!
try_module_get
(
THIS_MODULE
))
goto
err_unlock_rtnl
;
err
=
-
ENOMEM
;
dp
=
kzalloc
(
sizeof
(
*
dp
),
GFP_KERNEL
);
if
(
dp
==
NULL
)
goto
err_put_module
;
INIT_LIST_HEAD
(
&
dp
->
port_list
);
goto
err_unlock_rtnl
;
ovs_dp_set_net
(
dp
,
hold_net
(
sock_net
(
skb
->
sk
)));
/* Allocate table. */
err
=
-
ENOMEM
;
...
...
@@ -1264,6 +1295,16 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
goto
err_destroy_table
;
}
dp
->
ports
=
kmalloc
(
DP_VPORT_HASH_BUCKETS
*
sizeof
(
struct
hlist_head
),
GFP_KERNEL
);
if
(
!
dp
->
ports
)
{
err
=
-
ENOMEM
;
goto
err_destroy_percpu
;
}
for
(
i
=
0
;
i
<
DP_VPORT_HASH_BUCKETS
;
i
++
)
INIT_HLIST_HEAD
(
&
dp
->
ports
[
i
]);
/* Set up our datapath device. */
parms
.
name
=
nla_data
(
a
[
OVS_DP_ATTR_NAME
]);
parms
.
type
=
OVS_VPORT_TYPE_INTERNAL
;
...
...
@@ -1278,7 +1319,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
if
(
err
==
-
EBUSY
)
err
=
-
EEXIST
;
goto
err_destroy_p
ercpu
;
goto
err_destroy_p
orts_array
;
}
reply
=
ovs_dp_cmd_build_info
(
dp
,
info
->
snd_pid
,
...
...
@@ -1287,7 +1328,8 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
if
(
IS_ERR
(
reply
))
goto
err_destroy_local_port
;
list_add_tail
(
&
dp
->
list_node
,
&
dps
);
ovs_net
=
net_generic
(
ovs_dp_get_net
(
dp
),
ovs_net_id
);
list_add_tail
(
&
dp
->
list_node
,
&
ovs_net
->
dps
);
rtnl_unlock
();
genl_notify
(
reply
,
genl_info_net
(
info
),
info
->
snd_pid
,
...
...
@@ -1296,46 +1338,40 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
return
0
;
err_destroy_local_port:
ovs_dp_detach_port
(
rtnl_dereference
(
dp
->
ports
[
OVSP_LOCAL
]));
ovs_dp_detach_port
(
ovs_vport_rtnl
(
dp
,
OVSP_LOCAL
));
err_destroy_ports_array:
kfree
(
dp
->
ports
);
err_destroy_percpu:
free_percpu
(
dp
->
stats_percpu
);
err_destroy_table:
ovs_flow_tbl_destroy
(
genl_dereference
(
dp
->
table
));
err_free_dp:
release_net
(
ovs_dp_get_net
(
dp
));
kfree
(
dp
);
err_put_module:
module_put
(
THIS_MODULE
);
err_unlock_rtnl:
rtnl_unlock
();
err:
return
err
;
}
static
int
ovs_dp_cmd_del
(
struct
sk_buff
*
skb
,
struct
genl_info
*
info
)
/* Called with genl_mutex. */
static
void
__dp_destroy
(
struct
datapath
*
dp
)
{
struct
vport
*
vport
,
*
next_vport
;
struct
sk_buff
*
reply
;
struct
datapath
*
dp
;
int
err
;
int
i
;
rtnl_lock
();
dp
=
lookup_datapath
(
info
->
userhdr
,
info
->
attrs
);
err
=
PTR_ERR
(
dp
);
if
(
IS_ERR
(
dp
))
goto
exit_unlock
;
reply
=
ovs_dp_cmd_build_info
(
dp
,
info
->
snd_pid
,
info
->
snd_seq
,
OVS_DP_CMD_DEL
);
err
=
PTR_ERR
(
reply
);
if
(
IS_ERR
(
reply
))
goto
exit_unlock
;
for
(
i
=
0
;
i
<
DP_VPORT_HASH_BUCKETS
;
i
++
)
{
struct
vport
*
vport
;
struct
hlist_node
*
node
,
*
n
;
list_for_each_entry_safe
(
vport
,
next_vport
,
&
dp
->
port_list
,
node
)
if
(
vport
->
port_no
!=
OVSP_LOCAL
)
ovs_dp_detach_port
(
vport
);
hlist_for_each_entry_safe
(
vport
,
node
,
n
,
&
dp
->
ports
[
i
],
dp_hash_node
)
if
(
vport
->
port_no
!=
OVSP_LOCAL
)
ovs_dp_detach_port
(
vport
);
}
list_del
(
&
dp
->
list_node
);
ovs_dp_detach_port
(
rtnl_dereference
(
dp
->
ports
[
OVSP_LOCAL
]
));
ovs_dp_detach_port
(
ovs_vport_rtnl
(
dp
,
OVSP_LOCAL
));
/* rtnl_unlock() will wait until all the references to devices that
* are pending unregistration have been dropped. We do it here to
...
...
@@ -1345,17 +1381,32 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct genl_info *info)
rtnl_unlock
();
call_rcu
(
&
dp
->
rcu
,
destroy_dp_rcu
);
module_put
(
THIS_MODULE
);
}
static
int
ovs_dp_cmd_del
(
struct
sk_buff
*
skb
,
struct
genl_info
*
info
)
{
struct
sk_buff
*
reply
;
struct
datapath
*
dp
;
int
err
;
dp
=
lookup_datapath
(
sock_net
(
skb
->
sk
),
info
->
userhdr
,
info
->
attrs
);
err
=
PTR_ERR
(
dp
);
if
(
IS_ERR
(
dp
))
return
err
;
reply
=
ovs_dp_cmd_build_info
(
dp
,
info
->
snd_pid
,
info
->
snd_seq
,
OVS_DP_CMD_DEL
);
err
=
PTR_ERR
(
reply
);
if
(
IS_ERR
(
reply
))
return
err
;
__dp_destroy
(
dp
);
genl_notify
(
reply
,
genl_info_net
(
info
),
info
->
snd_pid
,
ovs_dp_datapath_multicast_group
.
id
,
info
->
nlhdr
,
GFP_KERNEL
);
return
0
;
exit_unlock:
rtnl_unlock
();
return
err
;
}
static
int
ovs_dp_cmd_set
(
struct
sk_buff
*
skb
,
struct
genl_info
*
info
)
...
...
@@ -1364,7 +1415,7 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
struct
datapath
*
dp
;
int
err
;
dp
=
lookup_datapath
(
info
->
userhdr
,
info
->
attrs
);
dp
=
lookup_datapath
(
sock_net
(
skb
->
sk
),
info
->
userhdr
,
info
->
attrs
);
if
(
IS_ERR
(
dp
))
return
PTR_ERR
(
dp
);
...
...
@@ -1372,7 +1423,7 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
info
->
snd_seq
,
OVS_DP_CMD_NEW
);
if
(
IS_ERR
(
reply
))
{
err
=
PTR_ERR
(
reply
);
netlink_set_err
(
init_net
.
genl_sock
,
0
,
netlink_set_err
(
sock_net
(
skb
->
sk
)
->
genl_sock
,
0
,
ovs_dp_datapath_multicast_group
.
id
,
err
);
return
0
;
}
...
...
@@ -1389,7 +1440,7 @@ static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info)
struct
sk_buff
*
reply
;
struct
datapath
*
dp
;
dp
=
lookup_datapath
(
info
->
userhdr
,
info
->
attrs
);
dp
=
lookup_datapath
(
sock_net
(
skb
->
sk
),
info
->
userhdr
,
info
->
attrs
);
if
(
IS_ERR
(
dp
))
return
PTR_ERR
(
dp
);
...
...
@@ -1403,11 +1454,12 @@ static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info)
static
int
ovs_dp_cmd_dump
(
struct
sk_buff
*
skb
,
struct
netlink_callback
*
cb
)
{
struct
ovs_net
*
ovs_net
=
net_generic
(
sock_net
(
skb
->
sk
),
ovs_net_id
);
struct
datapath
*
dp
;
int
skip
=
cb
->
args
[
0
];
int
i
=
0
;
list_for_each_entry
(
dp
,
&
dps
,
list_node
)
{
list_for_each_entry
(
dp
,
&
ovs_net
->
dps
,
list_node
)
{
if
(
i
>=
skip
&&
ovs_dp_cmd_fill_info
(
dp
,
skb
,
NETLINK_CB
(
cb
->
skb
).
pid
,
cb
->
nlh
->
nlmsg_seq
,
NLM_F_MULTI
,
...
...
@@ -1459,7 +1511,8 @@ static struct genl_family dp_vport_genl_family = {
.
hdrsize
=
sizeof
(
struct
ovs_header
),
.
name
=
OVS_VPORT_FAMILY
,
.
version
=
OVS_VPORT_VERSION
,
.
maxattr
=
OVS_VPORT_ATTR_MAX
.
maxattr
=
OVS_VPORT_ATTR_MAX
,
.
netnsok
=
true
};
struct
genl_multicast_group
ovs_dp_vport_multicast_group
=
{
...
...
@@ -1525,14 +1578,15 @@ struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, u32 pid,
}
/* Called with RTNL lock or RCU read lock. */
static
struct
vport
*
lookup_vport
(
struct
ovs_header
*
ovs_header
,
static
struct
vport
*
lookup_vport
(
struct
net
*
net
,
struct
ovs_header
*
ovs_header
,
struct
nlattr
*
a
[
OVS_VPORT_ATTR_MAX
+
1
])
{
struct
datapath
*
dp
;
struct
vport
*
vport
;
if
(
a
[
OVS_VPORT_ATTR_NAME
])
{
vport
=
ovs_vport_locate
(
nla_data
(
a
[
OVS_VPORT_ATTR_NAME
]));
vport
=
ovs_vport_locate
(
n
et
,
n
la_data
(
a
[
OVS_VPORT_ATTR_NAME
]));
if
(
!
vport
)
return
ERR_PTR
(
-
ENODEV
);
if
(
ovs_header
->
dp_ifindex
&&
...
...
@@ -1545,11 +1599,11 @@ static struct vport *lookup_vport(struct ovs_header *ovs_header,
if
(
port_no
>=
DP_MAX_PORTS
)
return
ERR_PTR
(
-
EFBIG
);
dp
=
get_dp
(
ovs_header
->
dp_ifindex
);
dp
=
get_dp
(
net
,
ovs_header
->
dp_ifindex
);
if
(
!
dp
)
return
ERR_PTR
(
-
ENODEV
);
vport
=
rcu_dereference_rtnl
(
dp
->
ports
[
port_no
]
);
vport
=
ovs_vport_rtnl_rcu
(
dp
,
port_no
);
if
(
!
vport
)
return
ERR_PTR
(
-
ENOENT
);
return
vport
;
...
...
@@ -1574,7 +1628,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
goto
exit
;
rtnl_lock
();
dp
=
get_dp
(
ovs_header
->
dp_ifindex
);
dp
=
get_dp
(
sock_net
(
skb
->
sk
),
ovs_header
->
dp_ifindex
);
err
=
-
ENODEV
;
if
(
!
dp
)
goto
exit_unlock
;
...
...
@@ -1586,7 +1640,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
if
(
port_no
>=
DP_MAX_PORTS
)
goto
exit_unlock
;
vport
=
rtnl_dereference
(
dp
->
ports
[
port_no
]
);
vport
=
ovs_vport_rtnl_rcu
(
dp
,
port_no
);
err
=
-
EBUSY
;
if
(
vport
)
goto
exit_unlock
;
...
...
@@ -1596,7 +1650,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
err
=
-
EFBIG
;
goto
exit_unlock
;
}
vport
=
rtnl_dereference
(
dp
->
ports
[
port_no
]
);
vport
=
ovs_vport_rtnl
(
dp
,
port_no
);
if
(
!
vport
)
break
;
}
...
...
@@ -1638,7 +1692,7 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
int
err
;
rtnl_lock
();
vport
=
lookup_vport
(
info
->
userhdr
,
a
);
vport
=
lookup_vport
(
sock_net
(
skb
->
sk
),
info
->
userhdr
,
a
);
err
=
PTR_ERR
(
vport
);
if
(
IS_ERR
(
vport
))
goto
exit_unlock
;
...
...
@@ -1658,7 +1712,7 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
reply
=
ovs_vport_cmd_build_info
(
vport
,
info
->
snd_pid
,
info
->
snd_seq
,
OVS_VPORT_CMD_NEW
);
if
(
IS_ERR
(
reply
))
{
netlink_set_err
(
init_net
.
genl_sock
,
0
,
netlink_set_err
(
sock_net
(
skb
->
sk
)
->
genl_sock
,
0
,
ovs_dp_vport_multicast_group
.
id
,
PTR_ERR
(
reply
));
goto
exit_unlock
;
}
...
...
@@ -1679,7 +1733,7 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
int
err
;
rtnl_lock
();
vport
=
lookup_vport
(
info
->
userhdr
,
a
);
vport
=
lookup_vport
(
sock_net
(
skb
->
sk
),
info
->
userhdr
,
a
);
err
=
PTR_ERR
(
vport
);
if
(
IS_ERR
(
vport
))
goto
exit_unlock
;
...
...
@@ -1714,7 +1768,7 @@ static int ovs_vport_cmd_get(struct sk_buff *skb, struct genl_info *info)
int
err
;
rcu_read_lock
();
vport
=
lookup_vport
(
ovs_header
,
a
);
vport
=
lookup_vport
(
sock_net
(
skb
->
sk
),
ovs_header
,
a
);
err
=
PTR_ERR
(
vport
);
if
(
IS_ERR
(
vport
))
goto
exit_unlock
;
...
...
@@ -1738,54 +1792,39 @@ static int ovs_vport_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
struct
ovs_header
*
ovs_header
=
genlmsg_data
(
nlmsg_data
(
cb
->
nlh
));
struct
datapath
*
dp
;
u32
port_no
;
int
retval
;
int
bucket
=
cb
->
args
[
0
],
skip
=
cb
->
args
[
1
]
;
int
i
,
j
=
0
;
dp
=
get_dp
(
ovs_header
->
dp_ifindex
);
dp
=
get_dp
(
sock_net
(
skb
->
sk
),
ovs_header
->
dp_ifindex
);
if
(
!
dp
)
return
-
ENODEV
;
rcu_read_lock
();
for
(
port_no
=
cb
->
args
[
0
];
port_no
<
DP_MAX_PORTS
;
port_no
++
)
{
for
(
i
=
bucket
;
i
<
DP_VPORT_HASH_BUCKETS
;
i
++
)
{
struct
vport
*
vport
;
vport
=
rcu_dereference
(
dp
->
ports
[
port_no
]);
if
(
!
vport
)
continue
;
if
(
ovs_vport_cmd_fill_info
(
vport
,
skb
,
NETLINK_CB
(
cb
->
skb
).
pid
,
cb
->
nlh
->
nlmsg_seq
,
NLM_F_MULTI
,
OVS_VPORT_CMD_NEW
)
<
0
)
break
;
}
rcu_read_unlock
();
cb
->
args
[
0
]
=
port_no
;
retval
=
skb
->
len
;
return
retval
;
}
static
void
rehash_flow_table
(
struct
work_struct
*
work
)
{
struct
datapath
*
dp
;
genl_lock
();
list_for_each_entry
(
dp
,
&
dps
,
list_node
)
{
struct
flow_table
*
old_table
=
genl_dereference
(
dp
->
table
);
struct
flow_table
*
new_table
;
new_table
=
ovs_flow_tbl_rehash
(
old_table
);
if
(
!
IS_ERR
(
new_table
))
{
rcu_assign_pointer
(
dp
->
table
,
new_table
);
ovs_flow_tbl_deferred_destroy
(
old_table
);
struct
hlist_node
*
n
;
j
=
0
;
hlist_for_each_entry_rcu
(
vport
,
n
,
&
dp
->
ports
[
i
],
dp_hash_node
)
{
if
(
j
>=
skip
&&
ovs_vport_cmd_fill_info
(
vport
,
skb
,
NETLINK_CB
(
cb
->
skb
).
pid
,
cb
->
nlh
->
nlmsg_seq
,
NLM_F_MULTI
,
OVS_VPORT_CMD_NEW
)
<
0
)
goto
out
;
j
++
;
}
skip
=
0
;
}
out:
rcu_read_unlock
();
genl_unlock
();
cb
->
args
[
0
]
=
i
;
cb
->
args
[
1
]
=
j
;
schedule_delayed_work
(
&
rehash_flow_wq
,
REHASH_FLOW_INTERVAL
)
;
return
skb
->
len
;
}
static
struct
genl_ops
dp_vport_genl_ops
[]
=
{
...
...
@@ -1872,6 +1911,59 @@ static int dp_register_genl(void)
return
err
;
}
static
void
rehash_flow_table
(
struct
work_struct
*
work
)
{
struct
datapath
*
dp
;
struct
net
*
net
;
genl_lock
();
rtnl_lock
();
for_each_net
(
net
)
{
struct
ovs_net
*
ovs_net
=
net_generic
(
net
,
ovs_net_id
);
list_for_each_entry
(
dp
,
&
ovs_net
->
dps
,
list_node
)
{
struct
flow_table
*
old_table
=
genl_dereference
(
dp
->
table
);
struct
flow_table
*
new_table
;
new_table
=
ovs_flow_tbl_rehash
(
old_table
);
if
(
!
IS_ERR
(
new_table
))
{
rcu_assign_pointer
(
dp
->
table
,
new_table
);
ovs_flow_tbl_deferred_destroy
(
old_table
);
}
}
}
rtnl_unlock
();
genl_unlock
();
schedule_delayed_work
(
&
rehash_flow_wq
,
REHASH_FLOW_INTERVAL
);
}
static
int
__net_init
ovs_init_net
(
struct
net
*
net
)
{
struct
ovs_net
*
ovs_net
=
net_generic
(
net
,
ovs_net_id
);
INIT_LIST_HEAD
(
&
ovs_net
->
dps
);
return
0
;
}
static
void
__net_exit
ovs_exit_net
(
struct
net
*
net
)
{
struct
ovs_net
*
ovs_net
=
net_generic
(
net
,
ovs_net_id
);
struct
datapath
*
dp
,
*
dp_next
;
genl_lock
();
list_for_each_entry_safe
(
dp
,
dp_next
,
&
ovs_net
->
dps
,
list_node
)
__dp_destroy
(
dp
);
genl_unlock
();
}
static
struct
pernet_operations
ovs_net_ops
=
{
.
init
=
ovs_init_net
,
.
exit
=
ovs_exit_net
,
.
id
=
&
ovs_net_id
,
.
size
=
sizeof
(
struct
ovs_net
),
};
static
int
__init
dp_init
(
void
)
{
struct
sk_buff
*
dummy_skb
;
...
...
@@ -1889,10 +1981,14 @@ static int __init dp_init(void)
if
(
err
)
goto
error_flow_exit
;
err
=
register_
netdevice_notifier
(
&
ovs_dp_device_notifier
);
err
=
register_
pernet_device
(
&
ovs_net_ops
);
if
(
err
)
goto
error_vport_exit
;
err
=
register_netdevice_notifier
(
&
ovs_dp_device_notifier
);
if
(
err
)
goto
error_netns_exit
;
err
=
dp_register_genl
();
if
(
err
<
0
)
goto
error_unreg_notifier
;
...
...
@@ -1903,6 +1999,8 @@ static int __init dp_init(void)
error_unreg_notifier:
unregister_netdevice_notifier
(
&
ovs_dp_device_notifier
);
error_netns_exit:
unregister_pernet_device
(
&
ovs_net_ops
);
error_vport_exit:
ovs_vport_exit
();
error_flow_exit:
...
...
@@ -1914,9 +2012,10 @@ static int __init dp_init(void)
static
void
dp_cleanup
(
void
)
{
cancel_delayed_work_sync
(
&
rehash_flow_wq
);
rcu_barrier
();
dp_unregister_genl
(
ARRAY_SIZE
(
dp_genl_families
));
unregister_netdevice_notifier
(
&
ovs_dp_device_notifier
);
unregister_pernet_device
(
&
ovs_net_ops
);
rcu_barrier
();
ovs_vport_exit
();
ovs_flow_exit
();
}
...
...
net/openvswitch/datapath.h
浏览文件 @
cefd81cf
...
...
@@ -27,10 +27,11 @@
#include <linux/u64_stats_sync.h>
#include "flow.h"
#include "vport.h"
struct
vport
;
#define DP_MAX_PORTS USHRT_MAX
#define DP_VPORT_HASH_BUCKETS 1024
#define DP_MAX_PORTS 1024
#define SAMPLE_ACTION_DEPTH 3
/**
...
...
@@ -58,11 +59,10 @@ struct dp_stats_percpu {
* @list_node: Element in global 'dps' list.
* @n_flows: Number of flows currently in flow table.
* @table: Current flow table. Protected by genl_lock and RCU.
* @ports: Map from port number to &struct vport. %OVSP_LOCAL port
* always exists, other ports may be %NULL. Protected by RTNL and RCU.
* @port_list: List of all ports in @ports in arbitrary order. RTNL required
* to iterate or modify.
* @ports: Hash table for ports. %OVSP_LOCAL port always exists. Protected by
* RTNL and RCU.
* @stats_percpu: Per-CPU datapath statistics.
* @net: Reference to net namespace.
*
* Context: See the comment on locking at the top of datapath.c for additional
* locking information.
...
...
@@ -75,13 +75,37 @@ struct datapath {
struct
flow_table
__rcu
*
table
;
/* Switch ports. */
struct
vport
__rcu
*
ports
[
DP_MAX_PORTS
];
struct
list_head
port_list
;
struct
hlist_head
*
ports
;
/* Stats. */
struct
dp_stats_percpu
__percpu
*
stats_percpu
;
#ifdef CONFIG_NET_NS
/* Network namespace ref. */
struct
net
*
net
;
#endif
};
struct
vport
*
ovs_lookup_vport
(
const
struct
datapath
*
dp
,
u16
port_no
);
static
inline
struct
vport
*
ovs_vport_rcu
(
const
struct
datapath
*
dp
,
int
port_no
)
{
WARN_ON_ONCE
(
!
rcu_read_lock_held
());
return
ovs_lookup_vport
(
dp
,
port_no
);
}
static
inline
struct
vport
*
ovs_vport_rtnl_rcu
(
const
struct
datapath
*
dp
,
int
port_no
)
{
WARN_ON_ONCE
(
!
rcu_read_lock_held
()
&&
!
rtnl_is_locked
());
return
ovs_lookup_vport
(
dp
,
port_no
);
}
static
inline
struct
vport
*
ovs_vport_rtnl
(
const
struct
datapath
*
dp
,
int
port_no
)
{
ASSERT_RTNL
();
return
ovs_lookup_vport
(
dp
,
port_no
);
}
/**
* struct ovs_skb_cb - OVS data in skb CB
* @flow: The flow associated with this packet. May be %NULL if no flow.
...
...
@@ -108,6 +132,16 @@ struct dp_upcall_info {
u32
pid
;
};
static
inline
struct
net
*
ovs_dp_get_net
(
struct
datapath
*
dp
)
{
return
read_pnet
(
&
dp
->
net
);
}
static
inline
void
ovs_dp_set_net
(
struct
datapath
*
dp
,
struct
net
*
net
)
{
write_pnet
(
&
dp
->
net
,
net
);
}
extern
struct
notifier_block
ovs_dp_device_notifier
;
extern
struct
genl_multicast_group
ovs_dp_vport_multicast_group
;
...
...
net/openvswitch/dp_notify.c
浏览文件 @
cefd81cf
...
...
@@ -41,19 +41,21 @@ static int dp_device_event(struct notifier_block *unused, unsigned long event,
case
NETDEV_UNREGISTER
:
if
(
!
ovs_is_internal_dev
(
dev
))
{
struct
sk_buff
*
notify
;
struct
datapath
*
dp
=
vport
->
dp
;
notify
=
ovs_vport_cmd_build_info
(
vport
,
0
,
0
,
OVS_VPORT_CMD_DEL
);
ovs_dp_detach_port
(
vport
);
if
(
IS_ERR
(
notify
))
{
netlink_set_err
(
init_net
.
genl_sock
,
0
,
netlink_set_err
(
ovs_dp_get_net
(
dp
)
->
genl_sock
,
0
,
ovs_dp_vport_multicast_group
.
id
,
PTR_ERR
(
notify
));
break
;
}
genlmsg_multicast
(
notify
,
0
,
ovs_dp_vport_multicast_group
.
id
,
GFP_KERNEL
);
genlmsg_multicast_netns
(
ovs_dp_get_net
(
dp
),
notify
,
0
,
ovs_dp_vport_multicast_group
.
id
,
GFP_KERNEL
);
}
break
;
}
...
...
net/openvswitch/flow.c
浏览文件 @
cefd81cf
...
...
@@ -203,10 +203,7 @@ struct sw_flow_actions *ovs_flow_actions_alloc(const struct nlattr *actions)
int
actions_len
=
nla_len
(
actions
);
struct
sw_flow_actions
*
sfa
;
/* At least DP_MAX_PORTS actions are required to be able to flood a
* packet to every port. Factor of 2 allows for setting VLAN tags,
* etc. */
if
(
actions_len
>
2
*
DP_MAX_PORTS
*
nla_total_size
(
4
))
if
(
actions_len
>
MAX_ACTIONS_BUFSIZE
)
return
ERR_PTR
(
-
EINVAL
);
sfa
=
kmalloc
(
sizeof
(
*
sfa
)
+
actions_len
,
GFP_KERNEL
);
...
...
@@ -992,7 +989,7 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
swkey
->
phy
.
in_port
=
in_port
;
attrs
&=
~
(
1
<<
OVS_KEY_ATTR_IN_PORT
);
}
else
{
swkey
->
phy
.
in_port
=
USHRT_MAX
;
swkey
->
phy
.
in_port
=
DP_MAX_PORTS
;
}
/* Data attributes. */
...
...
@@ -1135,7 +1132,7 @@ int ovs_flow_metadata_from_nlattrs(u32 *priority, u16 *in_port,
const
struct
nlattr
*
nla
;
int
rem
;
*
in_port
=
USHRT_MAX
;
*
in_port
=
DP_MAX_PORTS
;
*
priority
=
0
;
nla_for_each_nested
(
nla
,
attr
,
rem
)
{
...
...
@@ -1172,7 +1169,7 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
nla_put_u32
(
skb
,
OVS_KEY_ATTR_PRIORITY
,
swkey
->
phy
.
priority
))
goto
nla_put_failure
;
if
(
swkey
->
phy
.
in_port
!=
USHRT_MAX
&&
if
(
swkey
->
phy
.
in_port
!=
DP_MAX_PORTS
&&
nla_put_u32
(
skb
,
OVS_KEY_ATTR_IN_PORT
,
swkey
->
phy
.
in_port
))
goto
nla_put_failure
;
...
...
net/openvswitch/flow.h
浏览文件 @
cefd81cf
...
...
@@ -43,7 +43,7 @@ struct sw_flow_actions {
struct
sw_flow_key
{
struct
{
u32
priority
;
/* Packet QoS priority. */
u16
in_port
;
/* Input switch port (or
USHRT_MAX
). */
u16
in_port
;
/* Input switch port (or
DP_MAX_PORTS
). */
}
phy
;
struct
{
u8
src
[
ETH_ALEN
];
/* Ethernet source address. */
...
...
@@ -161,6 +161,7 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
int
ovs_flow_metadata_from_nlattrs
(
u32
*
priority
,
u16
*
in_port
,
const
struct
nlattr
*
);
#define MAX_ACTIONS_BUFSIZE (16 * 1024)
#define TBL_MIN_BUCKETS 1024
struct
flow_table
{
...
...
net/openvswitch/vport-internal_dev.c
浏览文件 @
cefd81cf
...
...
@@ -144,7 +144,7 @@ static void do_setup(struct net_device *netdev)
netdev
->
tx_queue_len
=
0
;
netdev
->
features
=
NETIF_F_LLTX
|
NETIF_F_SG
|
NETIF_F_FRAGLIST
|
NETIF_F_HIGHDMA
|
NETIF_F_HW_CSUM
|
NETIF_F_TSO
;
NETIF_F_HIGHDMA
|
NETIF_F_HW_CSUM
|
NETIF_F_TSO
;
netdev
->
vlan_features
=
netdev
->
features
;
netdev
->
features
|=
NETIF_F_HW_VLAN_TX
;
...
...
@@ -175,9 +175,14 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
goto
error_free_vport
;
}
dev_net_set
(
netdev_vport
->
dev
,
ovs_dp_get_net
(
vport
->
dp
));
internal_dev
=
internal_dev_priv
(
netdev_vport
->
dev
);
internal_dev
->
vport
=
vport
;
/* Restrict bridge port to current netns. */
if
(
vport
->
port_no
==
OVSP_LOCAL
)
netdev_vport
->
dev
->
features
|=
NETIF_F_NETNS_LOCAL
;
err
=
register_netdevice
(
netdev_vport
->
dev
);
if
(
err
)
goto
error_free_netdev
;
...
...
net/openvswitch/vport-netdev.c
浏览文件 @
cefd81cf
...
...
@@ -83,7 +83,7 @@ static struct vport *netdev_create(const struct vport_parms *parms)
netdev_vport
=
netdev_vport_priv
(
vport
);
netdev_vport
->
dev
=
dev_get_by_name
(
&
init_net
,
parms
->
name
);
netdev_vport
->
dev
=
dev_get_by_name
(
ovs_dp_get_net
(
vport
->
dp
)
,
parms
->
name
);
if
(
!
netdev_vport
->
dev
)
{
err
=
-
ENODEV
;
goto
error_free_vport
;
...
...
net/openvswitch/vport.c
浏览文件 @
cefd81cf
...
...
@@ -16,10 +16,10 @@
* 02110-1301, USA
*/
#include <linux/dcache.h>
#include <linux/etherdevice.h>
#include <linux/if.h>
#include <linux/if_vlan.h>
#include <linux/jhash.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mutex.h>
...
...
@@ -27,7 +27,9 @@
#include <linux/rcupdate.h>
#include <linux/rtnetlink.h>
#include <linux/compat.h>
#include <net/net_namespace.h>
#include "datapath.h"
#include "vport.h"
#include "vport-internal_dev.h"
...
...
@@ -67,9 +69,9 @@ void ovs_vport_exit(void)
kfree
(
dev_table
);
}
static
struct
hlist_head
*
hash_bucket
(
const
char
*
name
)
static
struct
hlist_head
*
hash_bucket
(
struct
net
*
net
,
const
char
*
name
)
{
unsigned
int
hash
=
full_name_hash
(
name
,
strlen
(
name
)
);
unsigned
int
hash
=
jhash
(
name
,
strlen
(
name
),
(
unsigned
long
)
net
);
return
&
dev_table
[
hash
&
(
VPORT_HASH_BUCKETS
-
1
)];
}
...
...
@@ -80,14 +82,15 @@ static struct hlist_head *hash_bucket(const char *name)
*
* Must be called with RTNL or RCU read lock.
*/
struct
vport
*
ovs_vport_locate
(
const
char
*
name
)
struct
vport
*
ovs_vport_locate
(
struct
net
*
net
,
const
char
*
name
)
{
struct
hlist_head
*
bucket
=
hash_bucket
(
name
);
struct
hlist_head
*
bucket
=
hash_bucket
(
n
et
,
n
ame
);
struct
vport
*
vport
;
struct
hlist_node
*
node
;
hlist_for_each_entry_rcu
(
vport
,
node
,
bucket
,
hash_node
)
if
(
!
strcmp
(
name
,
vport
->
ops
->
get_name
(
vport
)))
if
(
!
strcmp
(
name
,
vport
->
ops
->
get_name
(
vport
))
&&
net_eq
(
ovs_dp_get_net
(
vport
->
dp
),
net
))
return
vport
;
return
NULL
;
...
...
@@ -124,6 +127,7 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
vport
->
port_no
=
parms
->
port_no
;
vport
->
upcall_pid
=
parms
->
upcall_pid
;
vport
->
ops
=
ops
;
INIT_HLIST_NODE
(
&
vport
->
dp_hash_node
);
vport
->
percpu_stats
=
alloc_percpu
(
struct
vport_percpu_stats
);
if
(
!
vport
->
percpu_stats
)
{
...
...
@@ -170,14 +174,17 @@ struct vport *ovs_vport_add(const struct vport_parms *parms)
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
vport_ops_list
);
i
++
)
{
if
(
vport_ops_list
[
i
]
->
type
==
parms
->
type
)
{
struct
hlist_head
*
bucket
;
vport
=
vport_ops_list
[
i
]
->
create
(
parms
);
if
(
IS_ERR
(
vport
))
{
err
=
PTR_ERR
(
vport
);
goto
out
;
}
hlist_add_head_rcu
(
&
vport
->
hash_node
,
hash_bucket
(
vport
->
ops
->
get_name
(
vport
)));
bucket
=
hash_bucket
(
ovs_dp_get_net
(
vport
->
dp
),
vport
->
ops
->
get_name
(
vport
));
hlist_add_head_rcu
(
&
vport
->
hash_node
,
bucket
);
return
vport
;
}
}
...
...
net/openvswitch/vport.h
浏览文件 @
cefd81cf
...
...
@@ -20,6 +20,7 @@
#define VPORT_H 1
#include <linux/list.h>
#include <linux/netlink.h>
#include <linux/openvswitch.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
...
...
@@ -38,7 +39,7 @@ void ovs_vport_exit(void);
struct
vport
*
ovs_vport_add
(
const
struct
vport_parms
*
);
void
ovs_vport_del
(
struct
vport
*
);
struct
vport
*
ovs_vport_locate
(
const
char
*
name
);
struct
vport
*
ovs_vport_locate
(
struct
net
*
net
,
const
char
*
name
);
void
ovs_vport_get_stats
(
struct
vport
*
,
struct
ovs_vport_stats
*
);
...
...
@@ -69,10 +70,10 @@ struct vport_err_stats {
* @rcu: RCU callback head for deferred destruction.
* @port_no: Index into @dp's @ports array.
* @dp: Datapath to which this port belongs.
* @node: Element in @dp's @port_list.
* @upcall_pid: The Netlink port to use for packets received on this port that
* miss the flow table.
* @hash_node: Element in @dev_table hash table in vport.c.
* @dp_hash_node: Element in @datapath->ports hash table in datapath.c.
* @ops: Class structure.
* @percpu_stats: Points to per-CPU statistics used and maintained by vport
* @stats_lock: Protects @err_stats;
...
...
@@ -82,10 +83,10 @@ struct vport {
struct
rcu_head
rcu
;
u16
port_no
;
struct
datapath
*
dp
;
struct
list_head
node
;
u32
upcall_pid
;
struct
hlist_node
hash_node
;
struct
hlist_node
dp_hash_node
;
const
struct
vport_ops
*
ops
;
struct
vport_percpu_stats
__percpu
*
percpu_stats
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录