Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
a507c346
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
a507c346
编写于
2月 09, 2017
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'openvswitch-Conntrack-integration-improvements'
上级
9878f602
316d4d78
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
420 addition
and
113 deletion
+420
-113
include/uapi/linux/openvswitch.h
include/uapi/linux/openvswitch.h
+30
-3
net/openvswitch/actions.c
net/openvswitch/actions.c
+2
-0
net/openvswitch/conntrack.c
net/openvswitch/conntrack.c
+232
-64
net/openvswitch/conntrack.h
net/openvswitch/conntrack.h
+10
-4
net/openvswitch/flow.c
net/openvswitch/flow.c
+29
-5
net/openvswitch/flow.h
net/openvswitch/flow.h
+42
-13
net/openvswitch/flow_netlink.c
net/openvswitch/flow_netlink.c
+70
-22
net/openvswitch/flow_netlink.h
net/openvswitch/flow_netlink.h
+5
-2
未找到文件。
include/uapi/linux/openvswitch.h
浏览文件 @
a507c346
/*
* Copyright (c) 2007-201
3
Nicira, Inc.
* Copyright (c) 2007-201
7
Nicira, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
...
...
@@ -331,6 +331,8 @@ enum ovs_key_attr {
OVS_KEY_ATTR_CT_ZONE
,
/* u16 connection tracking zone. */
OVS_KEY_ATTR_CT_MARK
,
/* u32 connection tracking mark */
OVS_KEY_ATTR_CT_LABELS
,
/* 16-octet connection tracking label */
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4
,
/* struct ovs_key_ct_tuple_ipv4 */
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6
,
/* struct ovs_key_ct_tuple_ipv6 */
#ifdef __KERNEL__
OVS_KEY_ATTR_TUNNEL_INFO
,
/* struct ip_tunnel_info */
...
...
@@ -446,9 +448,13 @@ struct ovs_key_nd {
__u8
nd_tll
[
ETH_ALEN
];
};
#define OVS_CT_LABELS_LEN 16
#define OVS_CT_LABELS_LEN_32 4
#define OVS_CT_LABELS_LEN (OVS_CT_LABELS_LEN_32 * sizeof(__u32))
struct
ovs_key_ct_labels
{
__u8
ct_labels
[
OVS_CT_LABELS_LEN
];
union
{
__u8
ct_labels
[
OVS_CT_LABELS_LEN
];
__u32
ct_labels_32
[
OVS_CT_LABELS_LEN_32
];
};
};
/* OVS_KEY_ATTR_CT_STATE flags */
...
...
@@ -468,6 +474,22 @@ struct ovs_key_ct_labels {
#define OVS_CS_F_NAT_MASK (OVS_CS_F_SRC_NAT | OVS_CS_F_DST_NAT)
struct
ovs_key_ct_tuple_ipv4
{
__be32
ipv4_src
;
__be32
ipv4_dst
;
__be16
src_port
;
__be16
dst_port
;
__u8
ipv4_proto
;
};
struct
ovs_key_ct_tuple_ipv6
{
__be32
ipv6_src
[
4
];
__be32
ipv6_dst
[
4
];
__be16
src_port
;
__be16
dst_port
;
__u8
ipv6_proto
;
};
/**
* enum ovs_flow_attr - attributes for %OVS_FLOW_* commands.
* @OVS_FLOW_ATTR_KEY: Nested %OVS_KEY_ATTR_* attributes specifying the flow
...
...
@@ -652,6 +674,10 @@ struct ovs_action_hash {
* @OVS_CT_ATTR_HELPER: variable length string defining conntrack ALG.
* @OVS_CT_ATTR_NAT: Nested OVS_NAT_ATTR_* for performing L3 network address
* translation (NAT) on the packet.
* @OVS_CT_ATTR_FORCE_COMMIT: Like %OVS_CT_ATTR_COMMIT, but instead of doing
* nothing if the connection is already committed will check that the current
* packet is in conntrack entry's original direction. If directionality does
* not match, will delete the existing conntrack entry and commit a new one.
*/
enum
ovs_ct_attr
{
OVS_CT_ATTR_UNSPEC
,
...
...
@@ -662,6 +688,7 @@ enum ovs_ct_attr {
OVS_CT_ATTR_HELPER
,
/* netlink helper to assist detection of
related connections. */
OVS_CT_ATTR_NAT
,
/* Nested OVS_NAT_ATTR_* */
OVS_CT_ATTR_FORCE_COMMIT
,
/* No argument */
__OVS_CT_ATTR_MAX
};
...
...
net/openvswitch/actions.c
浏览文件 @
a507c346
...
...
@@ -1074,6 +1074,8 @@ static int execute_masked_set_action(struct sk_buff *skb,
case
OVS_KEY_ATTR_CT_ZONE
:
case
OVS_KEY_ATTR_CT_MARK
:
case
OVS_KEY_ATTR_CT_LABELS
:
case
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4
:
case
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6
:
err
=
-
EINVAL
;
break
;
}
...
...
net/openvswitch/conntrack.c
浏览文件 @
a507c346
...
...
@@ -65,6 +65,7 @@ struct ovs_conntrack_info {
struct
nf_conn
*
ct
;
u8
commit
:
1
;
u8
nat
:
3
;
/* enum ovs_ct_nat */
u8
force
:
1
;
u16
family
;
struct
md_mark
mark
;
struct
md_labels
labels
;
...
...
@@ -73,6 +74,8 @@ struct ovs_conntrack_info {
#endif
};
static
bool
labels_nonzero
(
const
struct
ovs_key_ct_labels
*
labels
);
static
void
__ovs_ct_free_action
(
struct
ovs_conntrack_info
*
ct_info
);
static
u16
key_to_nfproto
(
const
struct
sw_flow_key
*
key
)
...
...
@@ -129,21 +132,33 @@ static u32 ovs_ct_get_mark(const struct nf_conn *ct)
#endif
}
/* Guard against conntrack labels max size shrinking below 128 bits. */
#if NF_CT_LABELS_MAX_SIZE < 16
#error NF_CT_LABELS_MAX_SIZE must be at least 16 bytes
#endif
static
void
ovs_ct_get_labels
(
const
struct
nf_conn
*
ct
,
struct
ovs_key_ct_labels
*
labels
)
{
struct
nf_conn_labels
*
cl
=
ct
?
nf_ct_labels_find
(
ct
)
:
NULL
;
if
(
cl
)
{
size_t
len
=
sizeof
(
cl
->
bits
);
if
(
cl
)
memcpy
(
labels
,
cl
->
bits
,
OVS_CT_LABELS_LEN
);
else
memset
(
labels
,
0
,
OVS_CT_LABELS_LEN
);
}
if
(
len
>
OVS_CT_LABELS_LEN
)
len
=
OVS_CT_LABELS_LEN
;
else
if
(
len
<
OVS_CT_LABELS_LEN
)
memset
(
labels
,
0
,
OVS_CT_LABELS_LEN
);
memcpy
(
labels
,
cl
->
bits
,
len
);
static
void
__ovs_ct_update_key_orig_tp
(
struct
sw_flow_key
*
key
,
const
struct
nf_conntrack_tuple
*
orig
,
u8
icmp_proto
)
{
key
->
ct_orig_proto
=
orig
->
dst
.
protonum
;
if
(
orig
->
dst
.
protonum
==
icmp_proto
)
{
key
->
ct
.
orig_tp
.
src
=
htons
(
orig
->
dst
.
u
.
icmp
.
type
);
key
->
ct
.
orig_tp
.
dst
=
htons
(
orig
->
dst
.
u
.
icmp
.
code
);
}
else
{
memset
(
labels
,
0
,
OVS_CT_LABELS_LEN
);
key
->
ct
.
orig_tp
.
src
=
orig
->
src
.
u
.
all
;
key
->
ct
.
orig_tp
.
dst
=
orig
->
dst
.
u
.
all
;
}
}
...
...
@@ -151,13 +166,42 @@ static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state,
const
struct
nf_conntrack_zone
*
zone
,
const
struct
nf_conn
*
ct
)
{
key
->
ct
.
state
=
state
;
key
->
ct
.
zone
=
zone
->
id
;
key
->
ct
_
state
=
state
;
key
->
ct
_
zone
=
zone
->
id
;
key
->
ct
.
mark
=
ovs_ct_get_mark
(
ct
);
ovs_ct_get_labels
(
ct
,
&
key
->
ct
.
labels
);
if
(
ct
)
{
const
struct
nf_conntrack_tuple
*
orig
;
/* Use the master if we have one. */
if
(
ct
->
master
)
ct
=
ct
->
master
;
orig
=
&
ct
->
tuplehash
[
IP_CT_DIR_ORIGINAL
].
tuple
;
/* IP version must match with the master connection. */
if
(
key
->
eth
.
type
==
htons
(
ETH_P_IP
)
&&
nf_ct_l3num
(
ct
)
==
NFPROTO_IPV4
)
{
key
->
ipv4
.
ct_orig
.
src
=
orig
->
src
.
u3
.
ip
;
key
->
ipv4
.
ct_orig
.
dst
=
orig
->
dst
.
u3
.
ip
;
__ovs_ct_update_key_orig_tp
(
key
,
orig
,
IPPROTO_ICMP
);
return
;
}
else
if
(
key
->
eth
.
type
==
htons
(
ETH_P_IPV6
)
&&
!
sw_flow_key_is_nd
(
key
)
&&
nf_ct_l3num
(
ct
)
==
NFPROTO_IPV6
)
{
key
->
ipv6
.
ct_orig
.
src
=
orig
->
src
.
u3
.
in6
;
key
->
ipv6
.
ct_orig
.
dst
=
orig
->
dst
.
u3
.
in6
;
__ovs_ct_update_key_orig_tp
(
key
,
orig
,
NEXTHDR_ICMP
);
return
;
}
}
/* Clear 'ct_orig_proto' to mark the non-existence of conntrack
* original direction key fields.
*/
key
->
ct_orig_proto
=
0
;
}
/* Update 'key' based on skb->nfct. If 'post_ct' is true, then OVS has
/* Update 'key' based on skb->
_
nfct. If 'post_ct' is true, then OVS has
* previously sent the packet to conntrack via the ct action. If
* 'keep_nat_flags' is true, the existing NAT flags retained, else they are
* initialized from the connection status.
...
...
@@ -184,7 +228,7 @@ static void ovs_ct_update_key(const struct sk_buff *skb,
if
(
ct
->
master
)
state
|=
OVS_CS_F_RELATED
;
if
(
keep_nat_flags
)
{
state
|=
key
->
ct
.
state
&
OVS_CS_F_NAT_MASK
;
state
|=
key
->
ct
_
state
&
OVS_CS_F_NAT_MASK
;
}
else
{
if
(
ct
->
status
&
IPS_SRC_NAT
)
state
|=
OVS_CS_F_SRC_NAT
;
...
...
@@ -208,44 +252,69 @@ void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key)
ovs_ct_update_key
(
skb
,
NULL
,
key
,
false
,
false
);
}
int
ovs_ct_put_key
(
const
struct
sw_flow_key
*
key
,
struct
sk_buff
*
skb
)
#define IN6_ADDR_INITIALIZER(ADDR) \
{ (ADDR).s6_addr32[0], (ADDR).s6_addr32[1], \
(ADDR).s6_addr32[2], (ADDR).s6_addr32[3] }
int
ovs_ct_put_key
(
const
struct
sw_flow_key
*
swkey
,
const
struct
sw_flow_key
*
output
,
struct
sk_buff
*
skb
)
{
if
(
nla_put_u32
(
skb
,
OVS_KEY_ATTR_CT_STATE
,
key
->
ct
.
state
))
if
(
nla_put_u32
(
skb
,
OVS_KEY_ATTR_CT_STATE
,
output
->
ct_
state
))
return
-
EMSGSIZE
;
if
(
IS_ENABLED
(
CONFIG_NF_CONNTRACK_ZONES
)
&&
nla_put_u16
(
skb
,
OVS_KEY_ATTR_CT_ZONE
,
key
->
ct
.
zone
))
nla_put_u16
(
skb
,
OVS_KEY_ATTR_CT_ZONE
,
output
->
ct_
zone
))
return
-
EMSGSIZE
;
if
(
IS_ENABLED
(
CONFIG_NF_CONNTRACK_MARK
)
&&
nla_put_u32
(
skb
,
OVS_KEY_ATTR_CT_MARK
,
key
->
ct
.
mark
))
nla_put_u32
(
skb
,
OVS_KEY_ATTR_CT_MARK
,
output
->
ct
.
mark
))
return
-
EMSGSIZE
;
if
(
IS_ENABLED
(
CONFIG_NF_CONNTRACK_LABELS
)
&&
nla_put
(
skb
,
OVS_KEY_ATTR_CT_LABELS
,
sizeof
(
key
->
ct
.
labels
),
&
key
->
ct
.
labels
))
nla_put
(
skb
,
OVS_KEY_ATTR_CT_LABELS
,
sizeof
(
output
->
ct
.
labels
),
&
output
->
ct
.
labels
))
return
-
EMSGSIZE
;
if
(
swkey
->
ct_orig_proto
)
{
if
(
swkey
->
eth
.
type
==
htons
(
ETH_P_IP
))
{
struct
ovs_key_ct_tuple_ipv4
orig
=
{
output
->
ipv4
.
ct_orig
.
src
,
output
->
ipv4
.
ct_orig
.
dst
,
output
->
ct
.
orig_tp
.
src
,
output
->
ct
.
orig_tp
.
dst
,
output
->
ct_orig_proto
,
};
if
(
nla_put
(
skb
,
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4
,
sizeof
(
orig
),
&
orig
))
return
-
EMSGSIZE
;
}
else
if
(
swkey
->
eth
.
type
==
htons
(
ETH_P_IPV6
))
{
struct
ovs_key_ct_tuple_ipv6
orig
=
{
IN6_ADDR_INITIALIZER
(
output
->
ipv6
.
ct_orig
.
src
),
IN6_ADDR_INITIALIZER
(
output
->
ipv6
.
ct_orig
.
dst
),
output
->
ct
.
orig_tp
.
src
,
output
->
ct
.
orig_tp
.
dst
,
output
->
ct_orig_proto
,
};
if
(
nla_put
(
skb
,
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6
,
sizeof
(
orig
),
&
orig
))
return
-
EMSGSIZE
;
}
}
return
0
;
}
static
int
ovs_ct_set_mark
(
struct
sk_buff
*
skb
,
struct
sw_flow_key
*
key
,
static
int
ovs_ct_set_mark
(
struct
nf_conn
*
ct
,
struct
sw_flow_key
*
key
,
u32
ct_mark
,
u32
mask
)
{
#if IS_ENABLED(CONFIG_NF_CONNTRACK_MARK)
enum
ip_conntrack_info
ctinfo
;
struct
nf_conn
*
ct
;
u32
new_mark
;
/* The connection could be invalid, in which case set_mark is no-op. */
ct
=
nf_ct_get
(
skb
,
&
ctinfo
);
if
(
!
ct
)
return
0
;
new_mark
=
ct_mark
|
(
ct
->
mark
&
~
(
mask
));
if
(
ct
->
mark
!=
new_mark
)
{
ct
->
mark
=
new_mark
;
nf_conntrack_event_cache
(
IPCT_MARK
,
ct
);
if
(
nf_ct_is_confirmed
(
ct
))
nf_conntrack_event_cache
(
IPCT_MARK
,
ct
);
key
->
ct
.
mark
=
new_mark
;
}
...
...
@@ -255,34 +324,80 @@ static int ovs_ct_set_mark(struct sk_buff *skb, struct sw_flow_key *key,
#endif
}
static
int
ovs_ct_set_labels
(
struct
sk_buff
*
skb
,
struct
sw_flow_key
*
key
,
const
struct
ovs_key_ct_labels
*
labels
,
const
struct
ovs_key_ct_labels
*
mask
)
static
struct
nf_conn_labels
*
ovs_ct_get_conn_labels
(
struct
nf_conn
*
ct
)
{
enum
ip_conntrack_info
ctinfo
;
struct
nf_conn_labels
*
cl
;
struct
nf_conn
*
ct
;
int
err
;
/* The connection could be invalid, in which case set_label is no-op.*/
ct
=
nf_ct_get
(
skb
,
&
ctinfo
);
if
(
!
ct
)
return
0
;
cl
=
nf_ct_labels_find
(
ct
);
if
(
!
cl
)
{
nf_ct_labels_ext_add
(
ct
);
cl
=
nf_ct_labels_find
(
ct
);
}
if
(
!
cl
||
sizeof
(
cl
->
bits
)
<
OVS_CT_LABELS_LEN
)
return
cl
;
}
/* Initialize labels for a new, yet to be committed conntrack entry. Note that
* since the new connection is not yet confirmed, and thus no-one else has
* access to it's labels, we simply write them over. Also, we refrain from
* triggering events, as receiving change events before the create event would
* be confusing.
*/
static
int
ovs_ct_init_labels
(
struct
nf_conn
*
ct
,
struct
sw_flow_key
*
key
,
const
struct
ovs_key_ct_labels
*
labels
,
const
struct
ovs_key_ct_labels
*
mask
)
{
struct
nf_conn_labels
*
cl
,
*
master_cl
;
bool
have_mask
=
labels_nonzero
(
mask
);
/* Inherit master's labels to the related connection? */
master_cl
=
ct
->
master
?
nf_ct_labels_find
(
ct
->
master
)
:
NULL
;
if
(
!
master_cl
&&
!
have_mask
)
return
0
;
/* Nothing to do. */
cl
=
ovs_ct_get_conn_labels
(
ct
);
if
(
!
cl
)
return
-
ENOSPC
;
/* Inherit the master's labels, if any. */
if
(
master_cl
)
*
cl
=
*
master_cl
;
if
(
have_mask
)
{
u32
*
dst
=
(
u32
*
)
cl
->
bits
;
int
i
;
for
(
i
=
0
;
i
<
OVS_CT_LABELS_LEN_32
;
i
++
)
dst
[
i
]
=
(
dst
[
i
]
&
~
mask
->
ct_labels_32
[
i
])
|
(
labels
->
ct_labels_32
[
i
]
&
mask
->
ct_labels_32
[
i
]);
}
memcpy
(
&
key
->
ct
.
labels
,
cl
->
bits
,
OVS_CT_LABELS_LEN
);
return
0
;
}
static
int
ovs_ct_set_labels
(
struct
nf_conn
*
ct
,
struct
sw_flow_key
*
key
,
const
struct
ovs_key_ct_labels
*
labels
,
const
struct
ovs_key_ct_labels
*
mask
)
{
struct
nf_conn_labels
*
cl
;
int
err
;
cl
=
ovs_ct_get_conn_labels
(
ct
);
if
(
!
cl
)
return
-
ENOSPC
;
err
=
nf_connlabels_replace
(
ct
,
(
u32
*
)
labels
,
(
u32
*
)
mask
,
OVS_CT_LABELS_LEN
/
sizeof
(
u32
));
err
=
nf_connlabels_replace
(
ct
,
labels
->
ct_labels_32
,
mask
->
ct_labels_32
,
OVS_CT_LABELS_LEN_32
);
if
(
err
)
return
err
;
ovs_ct_get_labels
(
ct
,
&
key
->
ct
.
labels
);
memcpy
(
&
key
->
ct
.
labels
,
cl
->
bits
,
OVS_CT_LABELS_LEN
);
return
0
;
}
...
...
@@ -421,16 +536,16 @@ ovs_ct_get_info(const struct nf_conntrack_tuple_hash *h)
/* Find an existing connection which this packet belongs to without
* re-attributing statistics or modifying the connection state. This allows an
* skb->nfct lost due to an upcall to be recovered during actions execution.
* skb->
_
nfct lost due to an upcall to be recovered during actions execution.
*
* Must be called with rcu_read_lock.
*
* On success, populates skb->
nfct and skb->nfctinfo, and returns the
*
connection. Returns NULL
if there is no existing entry.
* On success, populates skb->
_nfct and returns the connection. Returns NULL
* if there is no existing entry.
*/
static
struct
nf_conn
*
ovs_ct_find_existing
(
struct
net
*
net
,
const
struct
nf_conntrack_zone
*
zone
,
u8
l3num
,
struct
sk_buff
*
skb
)
u8
l3num
,
struct
sk_buff
*
skb
,
bool
natted
)
{
struct
nf_conntrack_l3proto
*
l3proto
;
struct
nf_conntrack_l4proto
*
l4proto
;
...
...
@@ -453,6 +568,17 @@ ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone,
return
NULL
;
}
/* Must invert the tuple if skb has been transformed by NAT. */
if
(
natted
)
{
struct
nf_conntrack_tuple
inverse
;
if
(
!
nf_ct_invert_tuple
(
&
inverse
,
&
tuple
,
l3proto
,
l4proto
))
{
pr_debug
(
"ovs_ct_find_existing: Inversion failed!
\n
"
);
return
NULL
;
}
tuple
=
inverse
;
}
/* look for tuple match */
h
=
nf_conntrack_find_get
(
net
,
zone
,
&
tuple
);
if
(
!
h
)
...
...
@@ -460,11 +586,18 @@ ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone,
ct
=
nf_ct_tuplehash_to_ctrack
(
h
);
/* Inverted packet tuple matches the reverse direction conntrack tuple,
* select the other tuplehash to get the right 'ctinfo' bits for this
* packet.
*/
if
(
natted
)
h
=
&
ct
->
tuplehash
[
!
h
->
tuple
.
dst
.
dir
];
nf_ct_set
(
skb
,
ct
,
ovs_ct_get_info
(
h
));
return
ct
;
}
/* Determine whether skb->nfct is equal to the result of conntrack lookup. */
/* Determine whether skb->
_
nfct is equal to the result of conntrack lookup. */
static
bool
skb_nfct_cached
(
struct
net
*
net
,
const
struct
sw_flow_key
*
key
,
const
struct
ovs_conntrack_info
*
info
,
...
...
@@ -475,14 +608,19 @@ static bool skb_nfct_cached(struct net *net,
ct
=
nf_ct_get
(
skb
,
&
ctinfo
);
/* If no ct, check if we have evidence that an existing conntrack entry
* might be found for this skb. This happens when we lose a skb->nfct
* might be found for this skb. This happens when we lose a skb->
_
nfct
* due to an upcall. If the connection was not confirmed, it is not
* cached and needs to be run through conntrack again.
*/
if
(
!
ct
&&
key
->
ct
.
state
&
OVS_CS_F_TRACKED
&&
!
(
key
->
ct
.
state
&
OVS_CS_F_INVALID
)
&&
key
->
ct
.
zone
==
info
->
zone
.
id
)
ct
=
ovs_ct_find_existing
(
net
,
&
info
->
zone
,
info
->
family
,
skb
);
if
(
!
ct
&&
key
->
ct_state
&
OVS_CS_F_TRACKED
&&
!
(
key
->
ct_state
&
OVS_CS_F_INVALID
)
&&
key
->
ct_zone
==
info
->
zone
.
id
)
{
ct
=
ovs_ct_find_existing
(
net
,
&
info
->
zone
,
info
->
family
,
skb
,
!!
(
key
->
ct_state
&
OVS_CS_F_NAT_MASK
));
if
(
ct
)
nf_ct_get
(
skb
,
&
ctinfo
);
}
if
(
!
ct
)
return
false
;
if
(
!
net_eq
(
net
,
read_pnet
(
&
ct
->
ct_net
)))
...
...
@@ -496,6 +634,18 @@ static bool skb_nfct_cached(struct net *net,
if
(
help
&&
rcu_access_pointer
(
help
->
helper
)
!=
info
->
helper
)
return
false
;
}
/* Force conntrack entry direction to the current packet? */
if
(
info
->
force
&&
CTINFO2DIR
(
ctinfo
)
!=
IP_CT_DIR_ORIGINAL
)
{
/* Delete the conntrack entry if confirmed, else just release
* the reference.
*/
if
(
nf_ct_is_confirmed
(
ct
))
nf_ct_delete
(
ct
,
0
,
0
);
else
nf_conntrack_put
(
&
ct
->
ct_general
);
nf_ct_set
(
skb
,
NULL
,
0
);
return
false
;
}
return
true
;
}
...
...
@@ -590,7 +740,7 @@ static void ovs_nat_update_key(struct sw_flow_key *key,
if
(
maniptype
==
NF_NAT_MANIP_SRC
)
{
__be16
src
;
key
->
ct
.
state
|=
OVS_CS_F_SRC_NAT
;
key
->
ct
_
state
|=
OVS_CS_F_SRC_NAT
;
if
(
key
->
eth
.
type
==
htons
(
ETH_P_IP
))
key
->
ipv4
.
addr
.
src
=
ip_hdr
(
skb
)
->
saddr
;
else
if
(
key
->
eth
.
type
==
htons
(
ETH_P_IPV6
))
...
...
@@ -612,7 +762,7 @@ static void ovs_nat_update_key(struct sw_flow_key *key,
}
else
{
__be16
dst
;
key
->
ct
.
state
|=
OVS_CS_F_DST_NAT
;
key
->
ct
_
state
|=
OVS_CS_F_DST_NAT
;
if
(
key
->
eth
.
type
==
htons
(
ETH_P_IP
))
key
->
ipv4
.
addr
.
dst
=
ip_hdr
(
skb
)
->
daddr
;
else
if
(
key
->
eth
.
type
==
htons
(
ETH_P_IPV6
))
...
...
@@ -699,7 +849,7 @@ static int ovs_ct_nat(struct net *net, struct sw_flow_key *key,
/* Pass 'skb' through conntrack in 'net', using zone configured in 'info', if
* not done already. Update key with new CT state after passing the packet
* through conntrack.
* Note that if the packet is deemed invalid by conntrack, skb->nfct will be
* Note that if the packet is deemed invalid by conntrack, skb->
_
nfct will be
* set to NULL and 0 will be returned.
*/
static
int
__ovs_ct_lookup
(
struct
net
*
net
,
struct
sw_flow_key
*
key
,
...
...
@@ -736,7 +886,7 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
* NAT after the nf_conntrack_in() call. We can actually clear
* the whole state, as it will be re-initialized below.
*/
key
->
ct
.
state
=
0
;
key
->
ct
_
state
=
0
;
/* Update the key, but keep the NAT flags. */
ovs_ct_update_key
(
skb
,
info
,
key
,
true
,
true
);
...
...
@@ -752,9 +902,9 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
*
* NAT will be done only if the CT action has NAT, and only
* once per packet (per zone), as guarded by the NAT bits in
* the key->ct
.
state.
* the key->ct
_
state.
*/
if
(
info
->
nat
&&
!
(
key
->
ct
.
state
&
OVS_CS_F_NAT_MASK
)
&&
if
(
info
->
nat
&&
!
(
key
->
ct
_
state
&
OVS_CS_F_NAT_MASK
)
&&
(
nf_ct_is_confirmed
(
ct
)
||
info
->
commit
)
&&
ovs_ct_nat
(
net
,
key
,
info
,
skb
,
ct
,
ctinfo
)
!=
NF_ACCEPT
)
{
return
-
EINVAL
;
...
...
@@ -830,8 +980,8 @@ static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
{
size_t
i
;
for
(
i
=
0
;
i
<
sizeof
(
*
labels
)
;
i
++
)
if
(
labels
->
ct_labels
[
i
])
for
(
i
=
0
;
i
<
OVS_CT_LABELS_LEN_32
;
i
++
)
if
(
labels
->
ct_labels
_32
[
i
])
return
true
;
return
false
;
...
...
@@ -842,24 +992,36 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
const
struct
ovs_conntrack_info
*
info
,
struct
sk_buff
*
skb
)
{
enum
ip_conntrack_info
ctinfo
;
struct
nf_conn
*
ct
;
int
err
;
err
=
__ovs_ct_lookup
(
net
,
key
,
info
,
skb
);
if
(
err
)
return
err
;
/* The connection could be invalid, in which case this is a no-op.*/
ct
=
nf_ct_get
(
skb
,
&
ctinfo
);
if
(
!
ct
)
return
0
;
/* Apply changes before confirming the connection so that the initial
* conntrack NEW netlink event carries the values given in the CT
* action.
*/
if
(
info
->
mark
.
mask
)
{
err
=
ovs_ct_set_mark
(
skb
,
key
,
info
->
mark
.
value
,
err
=
ovs_ct_set_mark
(
ct
,
key
,
info
->
mark
.
value
,
info
->
mark
.
mask
);
if
(
err
)
return
err
;
}
if
(
labels_nonzero
(
&
info
->
labels
.
mask
))
{
err
=
ovs_ct_set_labels
(
skb
,
key
,
&
info
->
labels
.
value
,
if
(
!
nf_ct_is_confirmed
(
ct
))
{
err
=
ovs_ct_init_labels
(
ct
,
key
,
&
info
->
labels
.
value
,
&
info
->
labels
.
mask
);
if
(
err
)
return
err
;
}
else
if
(
labels_nonzero
(
&
info
->
labels
.
mask
))
{
err
=
ovs_ct_set_labels
(
ct
,
key
,
&
info
->
labels
.
value
,
&
info
->
labels
.
mask
);
if
(
err
)
return
err
;
...
...
@@ -1061,6 +1223,7 @@ static int parse_nat(const struct nlattr *attr,
static
const
struct
ovs_ct_len_tbl
ovs_ct_attr_lens
[
OVS_CT_ATTR_MAX
+
1
]
=
{
[
OVS_CT_ATTR_COMMIT
]
=
{
.
minlen
=
0
,
.
maxlen
=
0
},
[
OVS_CT_ATTR_FORCE_COMMIT
]
=
{
.
minlen
=
0
,
.
maxlen
=
0
},
[
OVS_CT_ATTR_ZONE
]
=
{
.
minlen
=
sizeof
(
u16
),
.
maxlen
=
sizeof
(
u16
)
},
[
OVS_CT_ATTR_MARK
]
=
{
.
minlen
=
sizeof
(
struct
md_mark
),
...
...
@@ -1100,6 +1263,9 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
}
switch
(
type
)
{
case
OVS_CT_ATTR_FORCE_COMMIT
:
info
->
force
=
true
;
/* fall through. */
case
OVS_CT_ATTR_COMMIT
:
info
->
commit
=
true
;
break
;
...
...
@@ -1326,7 +1492,9 @@ int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info,
if
(
!
start
)
return
-
EMSGSIZE
;
if
(
ct_info
->
commit
&&
nla_put_flag
(
skb
,
OVS_CT_ATTR_COMMIT
))
if
(
ct_info
->
commit
&&
nla_put_flag
(
skb
,
ct_info
->
force
?
OVS_CT_ATTR_FORCE_COMMIT
:
OVS_CT_ATTR_COMMIT
))
return
-
EMSGSIZE
;
if
(
IS_ENABLED
(
CONFIG_NF_CONNTRACK_ZONES
)
&&
nla_put_u16
(
skb
,
OVS_CT_ATTR_ZONE
,
ct_info
->
zone
.
id
))
...
...
net/openvswitch/conntrack.h
浏览文件 @
a507c346
...
...
@@ -32,7 +32,8 @@ int ovs_ct_execute(struct net *, struct sk_buff *, struct sw_flow_key *,
const
struct
ovs_conntrack_info
*
);
void
ovs_ct_fill_key
(
const
struct
sk_buff
*
skb
,
struct
sw_flow_key
*
key
);
int
ovs_ct_put_key
(
const
struct
sw_flow_key
*
key
,
struct
sk_buff
*
skb
);
int
ovs_ct_put_key
(
const
struct
sw_flow_key
*
swkey
,
const
struct
sw_flow_key
*
output
,
struct
sk_buff
*
skb
);
void
ovs_ct_free_action
(
const
struct
nlattr
*
a
);
#define CT_SUPPORTED_MASK (OVS_CS_F_NEW | OVS_CS_F_ESTABLISHED | \
...
...
@@ -75,13 +76,18 @@ static inline int ovs_ct_execute(struct net *net, struct sk_buff *skb,
static
inline
void
ovs_ct_fill_key
(
const
struct
sk_buff
*
skb
,
struct
sw_flow_key
*
key
)
{
key
->
ct
.
state
=
0
;
key
->
ct
.
zone
=
0
;
key
->
ct
_
state
=
0
;
key
->
ct
_
zone
=
0
;
key
->
ct
.
mark
=
0
;
memset
(
&
key
->
ct
.
labels
,
0
,
sizeof
(
key
->
ct
.
labels
));
/* Clear 'ct_orig_proto' to mark the non-existence of original
* direction key fields.
*/
key
->
ct_orig_proto
=
0
;
}
static
inline
int
ovs_ct_put_key
(
const
struct
sw_flow_key
*
key
,
static
inline
int
ovs_ct_put_key
(
const
struct
sw_flow_key
*
swkey
,
const
struct
sw_flow_key
*
output
,
struct
sk_buff
*
skb
)
{
return
0
;
...
...
net/openvswitch/flow.c
浏览文件 @
a507c346
...
...
@@ -765,7 +765,7 @@ static int key_extract_mac_proto(struct sk_buff *skb)
int
ovs_flow_key_extract
(
const
struct
ip_tunnel_info
*
tun_info
,
struct
sk_buff
*
skb
,
struct
sw_flow_key
*
key
)
{
int
res
;
int
res
,
err
;
/* Extract metadata from packet. */
if
(
tun_info
)
{
...
...
@@ -792,7 +792,6 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
key
->
phy
.
priority
=
skb
->
priority
;
key
->
phy
.
in_port
=
OVS_CB
(
skb
)
->
input_vport
->
port_no
;
key
->
phy
.
skb_mark
=
skb
->
mark
;
ovs_ct_fill_key
(
skb
,
key
);
key
->
ovs_flow_hash
=
0
;
res
=
key_extract_mac_proto
(
skb
);
if
(
res
<
0
)
...
...
@@ -800,17 +799,26 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
key
->
mac_proto
=
res
;
key
->
recirc_id
=
0
;
return
key_extract
(
skb
,
key
);
err
=
key_extract
(
skb
,
key
);
if
(
!
err
)
ovs_ct_fill_key
(
skb
,
key
);
/* Must be after key_extract(). */
return
err
;
}
int
ovs_flow_key_extract_userspace
(
struct
net
*
net
,
const
struct
nlattr
*
attr
,
struct
sk_buff
*
skb
,
struct
sw_flow_key
*
key
,
bool
log
)
{
const
struct
nlattr
*
a
[
OVS_KEY_ATTR_MAX
+
1
];
u64
attrs
=
0
;
int
err
;
err
=
parse_flow_nlattrs
(
attr
,
a
,
&
attrs
,
log
);
if
(
err
)
return
-
EINVAL
;
/* Extract metadata from netlink attributes. */
err
=
ovs_nla_get_flow_metadata
(
net
,
a
ttr
,
key
,
log
);
err
=
ovs_nla_get_flow_metadata
(
net
,
a
,
attrs
,
key
,
log
);
if
(
err
)
return
err
;
...
...
@@ -824,5 +832,21 @@ int ovs_flow_key_extract_userspace(struct net *net, const struct nlattr *attr,
*/
skb
->
protocol
=
key
->
eth
.
type
;
return
key_extract
(
skb
,
key
);
err
=
key_extract
(
skb
,
key
);
if
(
err
)
return
err
;
/* Check that we have conntrack original direction tuple metadata only
* for packets for which it makes sense. Otherwise the key may be
* corrupted due to overlapping key fields.
*/
if
(
attrs
&
(
1
<<
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4
)
&&
key
->
eth
.
type
!=
htons
(
ETH_P_IP
))
return
-
EINVAL
;
if
(
attrs
&
(
1
<<
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6
)
&&
(
key
->
eth
.
type
!=
htons
(
ETH_P_IPV6
)
||
sw_flow_key_is_nd
(
key
)))
return
-
EINVAL
;
return
0
;
}
net/openvswitch/flow.h
浏览文件 @
a507c346
/*
* Copyright (c) 2007-201
4
Nicira, Inc.
* Copyright (c) 2007-201
7
Nicira, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
...
...
@@ -85,6 +85,11 @@ struct sw_flow_key {
struct
vlan_head
cvlan
;
__be16
type
;
/* Ethernet frame type. */
}
eth
;
/* Filling a hole of two bytes. */
u8
ct_state
;
u8
ct_orig_proto
;
/* CT original direction tuple IP
* protocol.
*/
union
{
struct
{
__be32
top_lse
;
/* top label stack entry */
...
...
@@ -96,6 +101,7 @@ struct sw_flow_key {
u8
frag
;
/* One of OVS_FRAG_TYPE_*. */
}
ip
;
};
u16
ct_zone
;
/* Conntrack zone. */
struct
{
__be16
src
;
/* TCP/UDP/SCTP source port. */
__be16
dst
;
/* TCP/UDP/SCTP destination port. */
...
...
@@ -107,10 +113,16 @@ struct sw_flow_key {
__be32
src
;
/* IP source address. */
__be32
dst
;
/* IP destination address. */
}
addr
;
struct
{
u8
sha
[
ETH_ALEN
];
/* ARP source hardware address. */
u8
tha
[
ETH_ALEN
];
/* ARP target hardware address. */
}
arp
;
union
{
struct
{
__be32
src
;
__be32
dst
;
}
ct_orig
;
/* Conntrack original direction fields. */
struct
{
u8
sha
[
ETH_ALEN
];
/* ARP source hardware address. */
u8
tha
[
ETH_ALEN
];
/* ARP target hardware address. */
}
arp
;
};
}
ipv4
;
struct
{
struct
{
...
...
@@ -118,23 +130,40 @@ struct sw_flow_key {
struct
in6_addr
dst
;
/* IPv6 destination address. */
}
addr
;
__be32
label
;
/* IPv6 flow label. */
struct
{
struct
in6_addr
target
;
/* ND target address. */
u8
sll
[
ETH_ALEN
];
/* ND source link layer address. */
u8
tll
[
ETH_ALEN
];
/* ND target link layer address. */
}
nd
;
union
{
struct
{
struct
in6_addr
src
;
struct
in6_addr
dst
;
}
ct_orig
;
/* Conntrack original direction fields. */
struct
{
struct
in6_addr
target
;
/* ND target address. */
u8
sll
[
ETH_ALEN
];
/* ND source link layer address. */
u8
tll
[
ETH_ALEN
];
/* ND target link layer address. */
}
nd
;
};
}
ipv6
;
};
struct
{
/* Connection tracking fields. */
u16
zone
;
/* Connection tracking fields not packed above. */
struct
{
__be16
src
;
/* CT orig tuple tp src port. */
__be16
dst
;
/* CT orig tuple tp dst port. */
}
orig_tp
;
u32
mark
;
u8
state
;
struct
ovs_key_ct_labels
labels
;
}
ct
;
}
__aligned
(
BITS_PER_LONG
/
8
);
/* Ensure that we can do comparisons as longs. */
static
inline
bool
sw_flow_key_is_nd
(
const
struct
sw_flow_key
*
key
)
{
return
key
->
eth
.
type
==
htons
(
ETH_P_IPV6
)
&&
key
->
ip
.
proto
==
NEXTHDR_ICMP
&&
key
->
tp
.
dst
==
0
&&
(
key
->
tp
.
src
==
htons
(
NDISC_NEIGHBOUR_SOLICITATION
)
||
key
->
tp
.
src
==
htons
(
NDISC_NEIGHBOUR_ADVERTISEMENT
));
}
struct
sw_flow_key_range
{
unsigned
short
int
start
;
unsigned
short
int
end
;
...
...
net/openvswitch/flow_netlink.c
浏览文件 @
a507c346
...
...
@@ -129,7 +129,9 @@ static bool match_validate(const struct sw_flow_match *match,
/* The following mask attributes allowed only if they
* pass the validation tests. */
mask_allowed
&=
~
((
1
<<
OVS_KEY_ATTR_IPV4
)
|
(
1
<<
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4
)
|
(
1
<<
OVS_KEY_ATTR_IPV6
)
|
(
1
<<
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6
)
|
(
1
<<
OVS_KEY_ATTR_TCP
)
|
(
1
<<
OVS_KEY_ATTR_TCP_FLAGS
)
|
(
1
<<
OVS_KEY_ATTR_UDP
)
...
...
@@ -161,8 +163,10 @@ static bool match_validate(const struct sw_flow_match *match,
if
(
match
->
key
->
eth
.
type
==
htons
(
ETH_P_IP
))
{
key_expected
|=
1
<<
OVS_KEY_ATTR_IPV4
;
if
(
match
->
mask
&&
(
match
->
mask
->
key
.
eth
.
type
==
htons
(
0xffff
)))
if
(
match
->
mask
&&
match
->
mask
->
key
.
eth
.
type
==
htons
(
0xffff
))
{
mask_allowed
|=
1
<<
OVS_KEY_ATTR_IPV4
;
mask_allowed
|=
1
<<
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4
;
}
if
(
match
->
key
->
ip
.
frag
!=
OVS_FRAG_TYPE_LATER
)
{
if
(
match
->
key
->
ip
.
proto
==
IPPROTO_UDP
)
{
...
...
@@ -196,8 +200,10 @@ static bool match_validate(const struct sw_flow_match *match,
if
(
match
->
key
->
eth
.
type
==
htons
(
ETH_P_IPV6
))
{
key_expected
|=
1
<<
OVS_KEY_ATTR_IPV6
;
if
(
match
->
mask
&&
(
match
->
mask
->
key
.
eth
.
type
==
htons
(
0xffff
)))
if
(
match
->
mask
&&
match
->
mask
->
key
.
eth
.
type
==
htons
(
0xffff
))
{
mask_allowed
|=
1
<<
OVS_KEY_ATTR_IPV6
;
mask_allowed
|=
1
<<
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6
;
}
if
(
match
->
key
->
ip
.
frag
!=
OVS_FRAG_TYPE_LATER
)
{
if
(
match
->
key
->
ip
.
proto
==
IPPROTO_UDP
)
{
...
...
@@ -230,6 +236,12 @@ static bool match_validate(const struct sw_flow_match *match,
htons
(
NDISC_NEIGHBOUR_SOLICITATION
)
||
match
->
key
->
tp
.
src
==
htons
(
NDISC_NEIGHBOUR_ADVERTISEMENT
))
{
key_expected
|=
1
<<
OVS_KEY_ATTR_ND
;
/* Original direction conntrack tuple
* uses the same space as the ND fields
* in the key, so both are not allowed
* at the same time.
*/
mask_allowed
&=
~
(
1ULL
<<
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6
);
if
(
match
->
mask
&&
(
match
->
mask
->
key
.
tp
.
src
==
htons
(
0xff
)))
mask_allowed
|=
1
<<
OVS_KEY_ATTR_ND
;
}
...
...
@@ -282,7 +294,7 @@ size_t ovs_key_attr_size(void)
/* Whenever adding new OVS_KEY_ FIELDS, we should consider
* updating this function.
*/
BUILD_BUG_ON
(
OVS_KEY_ATTR_TUNNEL_INFO
!=
2
6
);
BUILD_BUG_ON
(
OVS_KEY_ATTR_TUNNEL_INFO
!=
2
8
);
return
nla_total_size
(
4
)
/* OVS_KEY_ATTR_PRIORITY */
+
nla_total_size
(
0
)
/* OVS_KEY_ATTR_TUNNEL */
...
...
@@ -295,6 +307,7 @@ size_t ovs_key_attr_size(void)
+
nla_total_size
(
2
)
/* OVS_KEY_ATTR_CT_ZONE */
+
nla_total_size
(
4
)
/* OVS_KEY_ATTR_CT_MARK */
+
nla_total_size
(
16
)
/* OVS_KEY_ATTR_CT_LABELS */
+
nla_total_size
(
40
)
/* OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6 */
+
nla_total_size
(
12
)
/* OVS_KEY_ATTR_ETHERNET */
+
nla_total_size
(
2
)
/* OVS_KEY_ATTR_ETHERTYPE */
+
nla_total_size
(
4
)
/* OVS_KEY_ATTR_VLAN */
...
...
@@ -355,6 +368,10 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
[
OVS_KEY_ATTR_CT_ZONE
]
=
{
.
len
=
sizeof
(
u16
)
},
[
OVS_KEY_ATTR_CT_MARK
]
=
{
.
len
=
sizeof
(
u32
)
},
[
OVS_KEY_ATTR_CT_LABELS
]
=
{
.
len
=
sizeof
(
struct
ovs_key_ct_labels
)
},
[
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4
]
=
{
.
len
=
sizeof
(
struct
ovs_key_ct_tuple_ipv4
)
},
[
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6
]
=
{
.
len
=
sizeof
(
struct
ovs_key_ct_tuple_ipv6
)
},
};
static
bool
check_attr_len
(
unsigned
int
attr_len
,
unsigned
int
expected_len
)
...
...
@@ -430,9 +447,8 @@ static int parse_flow_mask_nlattrs(const struct nlattr *attr,
return
__parse_flow_nlattrs
(
attr
,
a
,
attrsp
,
log
,
true
);
}
static
int
parse_flow_nlattrs
(
const
struct
nlattr
*
attr
,
const
struct
nlattr
*
a
[],
u64
*
attrsp
,
bool
log
)
int
parse_flow_nlattrs
(
const
struct
nlattr
*
attr
,
const
struct
nlattr
*
a
[],
u64
*
attrsp
,
bool
log
)
{
return
__parse_flow_nlattrs
(
attr
,
a
,
attrsp
,
log
,
false
);
}
...
...
@@ -1056,14 +1072,14 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
return
-
EINVAL
;
}
SW_FLOW_KEY_PUT
(
match
,
ct
.
state
,
ct_state
,
is_mask
);
SW_FLOW_KEY_PUT
(
match
,
ct
_
state
,
ct_state
,
is_mask
);
*
attrs
&=
~
(
1ULL
<<
OVS_KEY_ATTR_CT_STATE
);
}
if
(
*
attrs
&
(
1
<<
OVS_KEY_ATTR_CT_ZONE
)
&&
ovs_ct_verify
(
net
,
OVS_KEY_ATTR_CT_ZONE
))
{
u16
ct_zone
=
nla_get_u16
(
a
[
OVS_KEY_ATTR_CT_ZONE
]);
SW_FLOW_KEY_PUT
(
match
,
ct
.
zone
,
ct_zone
,
is_mask
);
SW_FLOW_KEY_PUT
(
match
,
ct
_
zone
,
ct_zone
,
is_mask
);
*
attrs
&=
~
(
1ULL
<<
OVS_KEY_ATTR_CT_ZONE
);
}
if
(
*
attrs
&
(
1
<<
OVS_KEY_ATTR_CT_MARK
)
&&
...
...
@@ -1082,6 +1098,34 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
sizeof
(
*
cl
),
is_mask
);
*
attrs
&=
~
(
1ULL
<<
OVS_KEY_ATTR_CT_LABELS
);
}
if
(
*
attrs
&
(
1ULL
<<
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4
))
{
const
struct
ovs_key_ct_tuple_ipv4
*
ct
;
ct
=
nla_data
(
a
[
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4
]);
SW_FLOW_KEY_PUT
(
match
,
ipv4
.
ct_orig
.
src
,
ct
->
ipv4_src
,
is_mask
);
SW_FLOW_KEY_PUT
(
match
,
ipv4
.
ct_orig
.
dst
,
ct
->
ipv4_dst
,
is_mask
);
SW_FLOW_KEY_PUT
(
match
,
ct
.
orig_tp
.
src
,
ct
->
src_port
,
is_mask
);
SW_FLOW_KEY_PUT
(
match
,
ct
.
orig_tp
.
dst
,
ct
->
dst_port
,
is_mask
);
SW_FLOW_KEY_PUT
(
match
,
ct_orig_proto
,
ct
->
ipv4_proto
,
is_mask
);
*
attrs
&=
~
(
1ULL
<<
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4
);
}
if
(
*
attrs
&
(
1ULL
<<
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6
))
{
const
struct
ovs_key_ct_tuple_ipv6
*
ct
;
ct
=
nla_data
(
a
[
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6
]);
SW_FLOW_KEY_MEMCPY
(
match
,
ipv6
.
ct_orig
.
src
,
&
ct
->
ipv6_src
,
sizeof
(
match
->
key
->
ipv6
.
ct_orig
.
src
),
is_mask
);
SW_FLOW_KEY_MEMCPY
(
match
,
ipv6
.
ct_orig
.
dst
,
&
ct
->
ipv6_dst
,
sizeof
(
match
->
key
->
ipv6
.
ct_orig
.
dst
),
is_mask
);
SW_FLOW_KEY_PUT
(
match
,
ct
.
orig_tp
.
src
,
ct
->
src_port
,
is_mask
);
SW_FLOW_KEY_PUT
(
match
,
ct
.
orig_tp
.
dst
,
ct
->
dst_port
,
is_mask
);
SW_FLOW_KEY_PUT
(
match
,
ct_orig_proto
,
ct
->
ipv6_proto
,
is_mask
);
*
attrs
&=
~
(
1ULL
<<
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6
);
}
/* For layer 3 packets the Ethernet type is provided
* and treated as metadata but no MAC addresses are provided.
...
...
@@ -1493,9 +1537,12 @@ u32 ovs_nla_get_ufid_flags(const struct nlattr *attr)
/**
* ovs_nla_get_flow_metadata - parses Netlink attributes into a flow key.
* @key: Receives extracted in_port, priority, tun_key and skb_mark.
* @attr: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
* sequence.
* @net: Network namespace.
* @key: Receives extracted in_port, priority, tun_key, skb_mark and conntrack
* metadata.
* @a: Array of netlink attributes holding parsed %OVS_KEY_ATTR_* Netlink
* attributes.
* @attrs: Bit mask for the netlink attributes included in @a.
* @log: Boolean to allow kernel error logging. Normally true, but when
* probing for feature compatibility this should be passed in as false to
* suppress unnecessary error logging.
...
...
@@ -1504,25 +1551,26 @@ u32 ovs_nla_get_ufid_flags(const struct nlattr *attr)
* take the same form accepted by flow_from_nlattrs(), but only enough of it to
* get the metadata, that is, the parts of the flow key that cannot be
* extracted from the packet itself.
*
* This must be called before the packet key fields are filled in 'key'.
*/
int
ovs_nla_get_flow_metadata
(
struct
net
*
net
,
const
struct
nlattr
*
attr
,
struct
sw_flow_key
*
key
,
bool
log
)
int
ovs_nla_get_flow_metadata
(
struct
net
*
net
,
const
struct
nlattr
*
a
[
OVS_KEY_ATTR_MAX
+
1
]
,
u64
attrs
,
struct
sw_flow_key
*
key
,
bool
log
)
{
const
struct
nlattr
*
a
[
OVS_KEY_ATTR_MAX
+
1
];
struct
sw_flow_match
match
;
u64
attrs
=
0
;
int
err
;
err
=
parse_flow_nlattrs
(
attr
,
a
,
&
attrs
,
log
);
if
(
err
)
return
-
EINVAL
;
memset
(
&
match
,
0
,
sizeof
(
match
));
match
.
key
=
key
;
key
->
ct_state
=
0
;
key
->
ct_zone
=
0
;
key
->
ct_orig_proto
=
0
;
memset
(
&
key
->
ct
,
0
,
sizeof
(
key
->
ct
));
memset
(
&
key
->
ipv4
.
ct_orig
,
0
,
sizeof
(
key
->
ipv4
.
ct_orig
));
memset
(
&
key
->
ipv6
.
ct_orig
,
0
,
sizeof
(
key
->
ipv6
.
ct_orig
));
key
->
phy
.
in_port
=
DP_MAX_PORTS
;
return
metadata_from_nlattrs
(
net
,
&
match
,
&
attrs
,
a
,
false
,
log
);
...
...
@@ -1584,7 +1632,7 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
if
(
nla_put_u32
(
skb
,
OVS_KEY_ATTR_SKB_MARK
,
output
->
phy
.
skb_mark
))
goto
nla_put_failure
;
if
(
ovs_ct_put_key
(
output
,
skb
))
if
(
ovs_ct_put_key
(
swkey
,
output
,
skb
))
goto
nla_put_failure
;
if
(
ovs_key_mac_proto
(
swkey
)
==
MAC_PROTO_ETHERNET
)
{
...
...
net/openvswitch/flow_netlink.h
浏览文件 @
a507c346
...
...
@@ -46,8 +46,11 @@ void ovs_match_init(struct sw_flow_match *match,
int
ovs_nla_put_key
(
const
struct
sw_flow_key
*
,
const
struct
sw_flow_key
*
,
int
attr
,
bool
is_mask
,
struct
sk_buff
*
);
int
ovs_nla_get_flow_metadata
(
struct
net
*
,
const
struct
nlattr
*
,
struct
sw_flow_key
*
,
bool
log
);
int
parse_flow_nlattrs
(
const
struct
nlattr
*
attr
,
const
struct
nlattr
*
a
[],
u64
*
attrsp
,
bool
log
);
int
ovs_nla_get_flow_metadata
(
struct
net
*
net
,
const
struct
nlattr
*
a
[
OVS_KEY_ATTR_MAX
+
1
],
u64
attrs
,
struct
sw_flow_key
*
key
,
bool
log
);
int
ovs_nla_put_identifier
(
const
struct
sw_flow
*
flow
,
struct
sk_buff
*
skb
);
int
ovs_nla_put_masked_key
(
const
struct
sw_flow
*
flow
,
struct
sk_buff
*
skb
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录