Skip to content

Commit ffd3e3b

Browse files
committed
meta-flow: Fix nw_frag mask while parsing from string.
mf_from_frag_string() sets all the upper bits of the nw_frag to make sure the exact match check will pass. This was not taken into account while splitting nw_frag and IP TOS bits into separate fields and the mask clean up was removed from the cls_rule_set_frag_masked() which is now called match_set_nw_frag_masked(). This leads to the case where the match parsed from the string is not considered equal to the match parsed from the OpenFlow, due to difference in masks. And that is causing ovs-ofctl replace-flows to always replace flows that match on nw_frag, even if they are exactly the same triggering unnecessary flow table updates and revalidation. $ cat frag_flows.txt ip,in_port=1,nw_frag=yes actions=drop $ ovs-ofctl dump-flows --no-stat --no-names br0 ip,in_port=1,nw_frag=yes actions=drop $ ovs-ofctl -vvconn replace-flows br0 frag_flows.txt 2>&1 | grep MOD NXT_FLOW_MOD: DEL_STRICT ip,in_port=1,nw_frag=yes actions=drop NXT_FLOW_MOD: ADD ip,in_port=1,nw_frag=yes actions=drop Clear the extra mask bits while setting match/flow structure from the field to avoid the issue. The issue mainly affects non-exact matches 'non_later' and 'yes', since exact matches are special-handled in many places / considered equal to not having a mask at all. Note: ideally we would not use byte-sized is_all_ones() for exact match checking, but use field-specific checks instead. However, this leads to a much larger change throughout OVS code base and would be much harder to backport. For now, fixing the issue in the way the code was originally implemented. Fixes: 9e44d71 ("Don't overload IP TOS with the frag matching bits.") Acked-by: Aaron Conole <[email protected]> Acked-by: Eelco Chaudron <[email protected]> Signed-off-by: Ilya Maximets <[email protected]>
1 parent c5bd6ef commit ffd3e3b

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

lib/meta-flow.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2543,7 +2543,8 @@ mf_set(const struct mf_field *mf,
25432543
break;
25442544

25452545
case MFF_IP_FRAG:
2546-
match_set_nw_frag_masked(match, value->u8, mask->u8);
2546+
match_set_nw_frag_masked(match, value->u8,
2547+
mask->u8 & FLOW_NW_FRAG_MASK);
25472548
break;
25482549

25492550
case MFF_ARP_SPA:

tests/ovs-ofctl.at

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3086,6 +3086,51 @@ AT_CHECK([ovs-ofctl -O OpenFlow14 dump-flows br0 | ofctl_strip | sed '/OFPST_FLO
30863086
OVS_VSWITCHD_STOP
30873087
AT_CLEANUP
30883088

3089+
AT_SETUP([ovs-ofctl replace-flows with fragments])
3090+
OVS_VSWITCHD_START
3091+
3092+
AT_DATA([frag_flows.txt], [dnl
3093+
ip,nw_frag=first actions=drop
3094+
ip,nw_frag=later actions=drop
3095+
ip,nw_frag=no actions=NORMAL
3096+
ip,nw_frag=not_later actions=NORMAL
3097+
ip,nw_frag=yes actions=LOCAL
3098+
])
3099+
AT_DATA([replace_flows.txt], [dnl
3100+
ip,nw_frag=first actions=NORMAL
3101+
ip,nw_frag=later actions=LOCAL
3102+
ip,nw_frag=no actions=drop
3103+
ip,nw_frag=not_later actions=drop
3104+
ip,nw_frag=yes actions=drop
3105+
])
3106+
3107+
AT_CHECK([ovs-ofctl -O OpenFlow13 add-flows br0 frag_flows.txt])
3108+
on_exit 'ovs-ofctl -O OpenFlow13 dump-flows br0'
3109+
3110+
dnl Check that flow replacement works.
3111+
AT_CHECK([ovs-ofctl -vvconn:console:dbg -O OpenFlow13 \
3112+
replace-flows br0 replace_flows.txt 2>&1 | grep FLOW_MOD \
3113+
| sed 's/.*\(OFPT_FLOW_MOD.*\)/\1/' | strip_xids | sort], [0], [dnl
3114+
OFPT_FLOW_MOD (OF1.3): ADD ip,nw_frag=first actions=NORMAL
3115+
OFPT_FLOW_MOD (OF1.3): ADD ip,nw_frag=later actions=LOCAL
3116+
OFPT_FLOW_MOD (OF1.3): ADD ip,nw_frag=no actions=drop
3117+
OFPT_FLOW_MOD (OF1.3): ADD ip,nw_frag=not_later actions=drop
3118+
OFPT_FLOW_MOD (OF1.3): ADD ip,nw_frag=yes actions=drop
3119+
])
3120+
3121+
dnl Check that replacement to the same set doesn't cause flow modifications.
3122+
AT_CHECK([ovs-ofctl -vvconn:console:dbg -O OpenFlow13 \
3123+
replace-flows br0 replace_flows.txt 2>&1 | grep FLOW_MOD \
3124+
| sed 's/.*\(OFPT_FLOW_MOD.*\)/\1/' | strip_xids | sort], [0], [])
3125+
3126+
dnl Compare the flow dump against the expected set.
3127+
cat replace_flows.txt > expout
3128+
AT_CHECK([ovs-ofctl -O OpenFlow13 dump-flows br0 \
3129+
| ofctl_strip | sed '/OFPST_FLOW/d' | sort], [0], [expout])
3130+
3131+
OVS_VSWITCHD_STOP
3132+
AT_CLEANUP
3133+
30893134
AT_SETUP([ovs-ofctl replace-flows with --bundle])
30903135
OVS_VSWITCHD_START
30913136

0 commit comments

Comments
 (0)