Skip to content

Commit 6de6e46

Browse files
yosh1k104davem330
authored andcommitted
cls_flower: Fix inability to match GRE/IPIP packets
When a packet of a new flow arrives in openvswitch kernel module, it dissects the packet and passes the extracted flow key to ovs-vswtichd daemon. If hw- offload configuration is enabled, the daemon creates a new TC flower entry to bypass openvswitch kernel module for the flow (TC flower can also offload flows to NICs but this time that does not matter). In this processing flow, I found the following issue in cases of GRE/IPIP packets. When ovs_flow_key_extract() in openvswitch module parses a packet of a new GRE (or IPIP) flow received on non-tunneling vports, it extracts information of the outer IP header for ip_proto/src_ip/dst_ip match keys. This means ovs-vswitchd creates a TC flower entry with IP protocol/addresses match keys whose values are those of the outer IP header. OTOH, TC flower, which uses flow_dissector (different parser from openvswitch module), extracts information of the inner IP header. The following flow is an example to describe the issue in more detail. <----------- Outer IP -----------------> <---------- Inner IP ----------> +----------+--------------+--------------+----------+----------+----------+ | ip_proto | src_ip | dst_ip | ip_proto | src_ip | dst_ip | | 47 (GRE) | 192.168.10.1 | 192.168.10.2 | 6 (TCP) | 10.0.0.1 | 10.0.0.2 | +----------+--------------+--------------+----------+----------+----------+ In this case, TC flower entry and extracted information are shown as below: - ovs-vswitchd creates TC flower entry with: - ip_proto: 47 - src_ip: 192.168.10.1 - dst_ip: 192.168.10.2 - TC flower extracts below for IP header matches: - ip_proto: 6 - src_ip: 10.0.0.1 - dst_ip: 10.0.0.2 Thus, GRE or IPIP packets never match the TC flower entry, as each dissector behaves differently. IMHO, the behavior of TC flower (flow dissector) does not look correct, as ip_proto/src_ip/dst_ip in TC flower match means the outermost IP header information except for GRE/IPIP cases. This patch adds a new flow_dissector flag FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP which skips dissection of the encapsulated inner GRE/IPIP header in TC flower classifier. Signed-off-by: Yoshiki Komachi <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 34d7ecb commit 6de6e46

File tree

3 files changed

+18
-1
lines changed

3 files changed

+18
-1
lines changed

include/net/flow_dissector.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ enum flow_dissector_key_id {
287287
#define FLOW_DISSECTOR_F_PARSE_1ST_FRAG BIT(0)
288288
#define FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL BIT(1)
289289
#define FLOW_DISSECTOR_F_STOP_AT_ENCAP BIT(2)
290+
#define FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP BIT(3)
290291

291292
struct flow_dissector_key {
292293
enum flow_dissector_key_id key_id;

net/core/flow_dissector.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,11 @@ bool __skb_flow_dissect(const struct net *net,
13071307

13081308
switch (ip_proto) {
13091309
case IPPROTO_GRE:
1310+
if (flags & FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP) {
1311+
fdret = FLOW_DISSECT_RET_OUT_GOOD;
1312+
break;
1313+
}
1314+
13101315
fdret = __skb_flow_dissect_gre(skb, key_control, flow_dissector,
13111316
target_container, data,
13121317
&proto, &nhoff, &hlen, flags);
@@ -1364,6 +1369,11 @@ bool __skb_flow_dissect(const struct net *net,
13641369
break;
13651370
}
13661371
case IPPROTO_IPIP:
1372+
if (flags & FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP) {
1373+
fdret = FLOW_DISSECT_RET_OUT_GOOD;
1374+
break;
1375+
}
1376+
13671377
proto = htons(ETH_P_IP);
13681378

13691379
key_control->flags |= FLOW_DIS_ENCAPSULATION;
@@ -1376,6 +1386,11 @@ bool __skb_flow_dissect(const struct net *net,
13761386
break;
13771387

13781388
case IPPROTO_IPV6:
1389+
if (flags & FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP) {
1390+
fdret = FLOW_DISSECT_RET_OUT_GOOD;
1391+
break;
1392+
}
1393+
13791394
proto = htons(ETH_P_IPV6);
13801395

13811396
key_control->flags |= FLOW_DIS_ENCAPSULATION;

net/sched/cls_flower.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,8 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp,
329329
ARRAY_SIZE(fl_ct_info_to_flower_map),
330330
post_ct);
331331
skb_flow_dissect_hash(skb, &mask->dissector, &skb_key);
332-
skb_flow_dissect(skb, &mask->dissector, &skb_key, 0);
332+
skb_flow_dissect(skb, &mask->dissector, &skb_key,
333+
FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP);
333334

334335
f = fl_mask_lookup(mask, &skb_key);
335336
if (f && !tc_skip_sw(f->flags)) {

0 commit comments

Comments
 (0)