When the OFPC_FRAG_DROP policy is in effect, IP fragments are supposed to
be dropped before they reach the flow table. Open vSwitch properly dropped
IP fragments in this case, but still accounted them to the packet and byte
counters for the flow that they would have hit if the OFPC_FRAG_NX_MATCh
policy had been in effect.
Reported-by: love you <thunder.love07@gmail.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Ethan Jackson <ethan@nicira.com>
/* Special OpenFlow rules. */
struct rule_dpif *miss_rule; /* Sends flow table misses to controller. */
struct rule_dpif *no_packet_in_rule; /* Drops flow table misses. */
/* Special OpenFlow rules. */
struct rule_dpif *miss_rule; /* Sends flow table misses to controller. */
struct rule_dpif *no_packet_in_rule; /* Drops flow table misses. */
+ struct rule_dpif *drop_frags_rule; /* Used in OFPC_FRAG_DROP mode. */
/* Bridging. */
struct netflow *netflow;
/* Bridging. */
struct netflow *netflow;
ofpbuf_clear(&ofpacts);
error = add_internal_flow(ofproto, id++, &ofpacts,
&ofproto->no_packet_in_rule);
ofpbuf_clear(&ofpacts);
error = add_internal_flow(ofproto, id++, &ofpacts,
&ofproto->no_packet_in_rule);
+ if (error) {
+ return error;
+ }
+
+ error = add_internal_flow(ofproto, id++, &ofpacts,
+ &ofproto->drop_frags_rule);
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
struct dpif_dp_stats s;
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
struct dpif_dp_stats s;
- uint64_t n_miss, n_no_pkt_in, n_bytes;
+ uint64_t n_miss, n_no_pkt_in, n_bytes, n_dropped_frags;
uint64_t n_lookup;
strcpy(ots->name, "classifier");
uint64_t n_lookup;
strcpy(ots->name, "classifier");
dpif_get_dp_stats(ofproto->dpif, &s);
rule_get_stats(&ofproto->miss_rule->up, &n_miss, &n_bytes);
rule_get_stats(&ofproto->no_packet_in_rule->up, &n_no_pkt_in, &n_bytes);
dpif_get_dp_stats(ofproto->dpif, &s);
rule_get_stats(&ofproto->miss_rule->up, &n_miss, &n_bytes);
rule_get_stats(&ofproto->no_packet_in_rule->up, &n_no_pkt_in, &n_bytes);
+ rule_get_stats(&ofproto->drop_frags_rule->up, &n_dropped_frags, &n_bytes);
- n_lookup = s.n_hit + s.n_missed;
+ n_lookup = s.n_hit + s.n_missed - n_dropped_frags;
ots->lookup_count = htonll(n_lookup);
ots->matched_count = htonll(n_lookup - n_miss - n_no_pkt_in);
}
ots->lookup_count = htonll(n_lookup);
ots->matched_count = htonll(n_lookup - n_miss - n_no_pkt_in);
}
{
struct cls_rule *cls_rule;
struct classifier *cls;
{
struct cls_rule *cls_rule;
struct classifier *cls;
if (table_id >= N_TABLES) {
return NULL;
}
cls = &ofproto->up.tables[table_id].cls;
if (table_id >= N_TABLES) {
return NULL;
}
cls = &ofproto->up.tables[table_id].cls;
- if (flow->nw_frag & FLOW_NW_FRAG_ANY
- && ofproto->up.frag_handling == OFPC_FRAG_NORMAL) {
- /* For OFPC_NORMAL frag_handling, we must pretend that transport ports
- * are unavailable. */
+ frag = (flow->nw_frag & FLOW_NW_FRAG_ANY) != 0;
+ if (frag && ofproto->up.frag_handling == OFPC_FRAG_NORMAL) {
+ /* We must pretend that transport ports are unavailable. */
struct flow ofpc_normal_flow = *flow;
ofpc_normal_flow.tp_src = htons(0);
ofpc_normal_flow.tp_dst = htons(0);
cls_rule = classifier_lookup(cls, &ofpc_normal_flow);
struct flow ofpc_normal_flow = *flow;
ofpc_normal_flow.tp_src = htons(0);
ofpc_normal_flow.tp_dst = htons(0);
cls_rule = classifier_lookup(cls, &ofpc_normal_flow);
+ } else if (frag && ofproto->up.frag_handling == OFPC_FRAG_DROP) {
+ cls_rule = &ofproto->drop_frags_rule->up.cr;
} else {
cls_rule = classifier_lookup(cls, flow);
}
} else {
cls_rule = classifier_lookup(cls, flow);
}
} else if (rule == ofproto->no_packet_in_rule) {
ds_put_cstr(ds, "\nNo match, packets dropped because "
"OFPPC_NO_PACKET_IN is set on in_port.\n");
} else if (rule == ofproto->no_packet_in_rule) {
ds_put_cstr(ds, "\nNo match, packets dropped because "
"OFPPC_NO_PACKET_IN is set on in_port.\n");
+ } else if (rule == ofproto->drop_frags_rule) {
+ ds_put_cstr(ds, "\nPackets dropped because they are IP fragments "
+ "and the fragment handling mode is \"drop\".\n");
AT_CHECK([ovs-ofctl set-frags br0 $mode])
for type in no first later; do
eval flow=\$${type}_flow exp_output=\$$type
AT_CHECK([ovs-ofctl set-frags br0 $mode])
for type in no first later; do
eval flow=\$${type}_flow exp_output=\$$type
+ printf "\n%s\n" "----$mode $type-----"
AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
- AT_CHECK_UNQUOTED([tail -1 stdout], [0], [Datapath actions: $exp_output
-])
+ : > expout
+ if test $mode = drop && test $type != no; then
+ echo 'Packets dropped because they are IP fragments and the fragment handling mode is "drop".' >> expout
+ fi
+ echo "Datapath actions: $exp_output" >> expout
+ AT_CHECK([grep 'IP fragments' stdout; tail -1 stdout], [0], [expout])
done
done
OVS_VSWITCHD_STOP
done
done
OVS_VSWITCHD_STOP
" $x table$x
x=`expr $x + 1`
done
" $x table$x
x=`expr $x + 1`
done
- echo " 254: table254: wild=0x3fffff, max=1000000, active=2
+ echo " 254: table254: wild=0x3fffff, max=1000000, active=3
lookup=0, matched=0") > expout
AT_CHECK([ovs-ofctl dump-tables br0], [0], [expout])
# Change the configuration.
lookup=0, matched=0") > expout
AT_CHECK([ovs-ofctl dump-tables br0], [0], [expout])
# Change the configuration.