diff --git a/SOURCES/openvswitch-2.17.0.patch b/SOURCES/openvswitch-2.17.0.patch index fc7cc38..8cd41b8 100644 --- a/SOURCES/openvswitch-2.17.0.patch +++ b/SOURCES/openvswitch-2.17.0.patch @@ -61128,9 +61128,18 @@ index 57f94df544..53b47073ad 100644 * netdev, flow state (offloaded/kernel path), flow_pps_rate. */ diff --git a/ofproto/ofproto-dpif-xlate-cache.c b/ofproto/ofproto-dpif-xlate-cache.c -index dcc91cb380..9224ee2e6d 100644 +index dcc91cb380..2e1fcb3a6f 100644 --- a/ofproto/ofproto-dpif-xlate-cache.c +++ b/ofproto/ofproto-dpif-xlate-cache.c +@@ -125,7 +125,7 @@ xlate_push_stats_entry(struct xc_entry *entry, + case XC_LEARN: { + enum ofperr error; + error = ofproto_flow_mod_learn(entry->learn.ofm, true, +- entry->learn.limit, NULL); ++ entry->learn.limit, NULL, stats->used); + if (error) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "xcache LEARN action execution failed."); @@ -209,6 +209,7 @@ xlate_cache_clear_entry(struct xc_entry *entry) { switch (entry->type) { @@ -61164,7 +61173,7 @@ index 114aff8ea3..0fc6d2ea60 100644 enum xc_type type; union { diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c -index 578cbfe581..2b1611c912 100644 +index 578cbfe581..b91b5757fd 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -66,6 +66,7 @@ @@ -61749,7 +61758,25 @@ index 578cbfe581..2b1611c912 100644 } else { xlate_report(ctx, OFT_WARN, "output port %"PRIu64" is out of range", port); -@@ -5622,7 +5768,8 @@ xlate_sample_action(struct xlate_ctx *ctx, +@@ -5525,8 +5671,16 @@ xlate_learn_action(struct xlate_ctx *ctx, const struct ofpact_learn *learn) + if (!error) { + bool success = true; + if (ctx->xin->allow_side_effects) { ++ long long int last_used; ++ ++ if (ctx->xin->resubmit_stats) { ++ last_used = ctx->xin->resubmit_stats->used; ++ } else { ++ last_used = time_msec(); ++ } + error = ofproto_flow_mod_learn(ofm, ctx->xin->xcache != NULL, +- learn->limit, &success); ++ learn->limit, &success, ++ last_used); + } else if (learn->limit) { + if (!ofm->temp_rule + || ofm->temp_rule->state != RULE_INSERTED) { +@@ -5622,7 +5776,8 @@ xlate_sample_action(struct xlate_ctx *ctx, /* Scale the probability from 16-bit to 32-bit while representing * the same percentage. */ @@ -61759,7 +61786,7 @@ index 578cbfe581..2b1611c912 100644 /* If ofp_port in flow sample action is equel to ofp_port, * this sample action is a input port action. */ -@@ -5656,13 +5803,15 @@ xlate_sample_action(struct xlate_ctx *ctx, +@@ -5656,13 +5811,15 @@ xlate_sample_action(struct xlate_ctx *ctx, struct flow *flow = &ctx->xin->flow; tnl_port_send(xport->ofport, flow, ctx->wc); if (!ovs_native_tunneling_is_on(ctx->xbridge->ofproto)) { @@ -61777,7 +61804,7 @@ index 578cbfe581..2b1611c912 100644 } } else { xlate_report_error(ctx, -@@ -5772,21 +5921,12 @@ clone_xlate_actions(const struct ofpact *actions, size_t actions_len, +@@ -5772,21 +5929,12 @@ clone_xlate_actions(const struct ofpact *actions, size_t actions_len, struct xlate_ctx *ctx, bool is_last_action, bool group_bucket_action OVS_UNUSED) { @@ -61802,7 +61829,7 @@ index 578cbfe581..2b1611c912 100644 do_xlate_actions(actions, actions_len, ctx, is_last_action, false); if (!ctx->freezing) { xlate_action_set(ctx); -@@ -5801,7 +5941,8 @@ clone_xlate_actions(const struct ofpact *actions, size_t actions_len, +@@ -5801,7 +5949,8 @@ clone_xlate_actions(const struct ofpact *actions, size_t actions_len, * avoid emitting those actions twice. Once inside * the clone, another time for the action after clone. */ xlate_commit_actions(ctx); @@ -61812,7 +61839,7 @@ index 578cbfe581..2b1611c912 100644 bool old_was_mpls = ctx->was_mpls; bool old_conntracked = ctx->conntracked; -@@ -5858,14 +5999,10 @@ dp_clone_done: +@@ -5858,14 +6007,10 @@ dp_clone_done: ctx->was_mpls = old_was_mpls; /* Restore the 'base_flow' for the next action. */ @@ -61829,7 +61856,7 @@ index 578cbfe581..2b1611c912 100644 } static void -@@ -6241,8 +6378,8 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc, +@@ -6241,8 +6386,8 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc, { uint16_t zone; if (ofc->zone_src.field) { @@ -61840,7 +61867,7 @@ index 578cbfe581..2b1611c912 100644 zone = mf_get_subfield(&ofc->zone_src, &ctx->xin->flow); if (ctx->xin->frozen_state) { -@@ -6252,12 +6389,13 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc, +@@ -6252,12 +6397,13 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc, * which will invalidate the megaflow with old the recirc_id. */ if (!mf_is_frozen_metadata(ofc->zone_src.field)) { @@ -61856,7 +61883,7 @@ index 578cbfe581..2b1611c912 100644 } else { zone = ofc->zone_imm; } -@@ -6347,16 +6485,16 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx, +@@ -6347,16 +6493,16 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx, const struct ofpact *remaining_acts, size_t remaining_acts_len) { @@ -61877,7 +61904,7 @@ index 578cbfe581..2b1611c912 100644 &ctx->xin->flow); /* If datapath doesn't support check_pkt_len action, then set the * SLOW_ACTION flag. If we don't set SLOW_ACTION, we -@@ -6366,22 +6504,17 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx, +@@ -6366,22 +6512,17 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx, * the packet length. This results in wrong actions being applied. */ ctx->xout->slow |= SLOW_ACTION; @@ -61905,7 +61932,7 @@ index 578cbfe581..2b1611c912 100644 bool old_was_mpls = ctx->was_mpls; bool old_conntracked = ctx->conntracked; -@@ -6391,8 +6524,8 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx, +@@ -6391,8 +6532,8 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx, check_pkt_larger->pkt_len); size_t offset_attr = nl_msg_start_nested( ctx->odp_actions, OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER); @@ -61916,7 +61943,7 @@ index 578cbfe581..2b1611c912 100644 do_xlate_actions(remaining_acts, remaining_acts_len, ctx, true, false); if (!ctx->freezing) { xlate_action_set(ctx); -@@ -6402,10 +6535,10 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx, +@@ -6402,10 +6543,10 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx, } nl_msg_end_nested(ctx->odp_actions, offset_attr); @@ -61929,7 +61956,7 @@ index 578cbfe581..2b1611c912 100644 /* If the flow translation for the IF_GREATER case requires freezing, * then ctx->exit would be true. Reset to false so that we can -@@ -6416,8 +6549,8 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx, +@@ -6416,8 +6557,8 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx, offset_attr = nl_msg_start_nested( ctx->odp_actions, OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL); @@ -61940,7 +61967,7 @@ index 578cbfe581..2b1611c912 100644 do_xlate_actions(remaining_acts, remaining_acts_len, ctx, true, false); if (!ctx->freezing) { xlate_action_set(ctx); -@@ -6428,15 +6561,12 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx, +@@ -6428,15 +6569,12 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx, nl_msg_end_nested(ctx->odp_actions, offset_attr); nl_msg_end_nested(ctx->odp_actions, offset); @@ -61959,7 +61986,7 @@ index 578cbfe581..2b1611c912 100644 } static void -@@ -6887,6 +7017,107 @@ xlate_ofpact_unroll_xlate(struct xlate_ctx *ctx, +@@ -6887,6 +7025,107 @@ xlate_ofpact_unroll_xlate(struct xlate_ctx *ctx, "cookie=%#"PRIx64, a->rule_table_id, a->rule_cookie); } @@ -62067,7 +62094,7 @@ index 578cbfe581..2b1611c912 100644 static void do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, struct xlate_ctx *ctx, bool is_last_action, -@@ -6928,6 +7159,8 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -6928,6 +7167,8 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; } @@ -62076,7 +62103,7 @@ index 578cbfe581..2b1611c912 100644 if (OVS_UNLIKELY(ctx->xin->trace)) { struct ds s = DS_EMPTY_INITIALIZER; struct ofpact_format_params fp = { .s = &s }; -@@ -7027,6 +7260,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -7027,6 +7268,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, case OFPACT_SET_IPV4_SRC: if (flow->dl_type == htons(ETH_TYPE_IP)) { memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src); @@ -62084,7 +62111,7 @@ index 578cbfe581..2b1611c912 100644 flow->nw_src = ofpact_get_SET_IPV4_SRC(a)->ipv4; } break; -@@ -7034,12 +7268,14 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -7034,12 +7276,14 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, case OFPACT_SET_IPV4_DST: if (flow->dl_type == htons(ETH_TYPE_IP)) { memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst); @@ -62099,7 +62126,7 @@ index 578cbfe581..2b1611c912 100644 wc->masks.nw_tos |= IP_DSCP_MASK; flow->nw_tos &= ~IP_DSCP_MASK; flow->nw_tos |= ofpact_get_SET_IP_DSCP(a)->dscp; -@@ -7048,6 +7284,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -7048,6 +7292,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, case OFPACT_SET_IP_ECN: if (is_ip_any(flow)) { @@ -62107,7 +62134,7 @@ index 578cbfe581..2b1611c912 100644 wc->masks.nw_tos |= IP_ECN_MASK; flow->nw_tos &= ~IP_ECN_MASK; flow->nw_tos |= ofpact_get_SET_IP_ECN(a)->ecn; -@@ -7056,6 +7293,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -7056,6 +7301,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, case OFPACT_SET_IP_TTL: if (is_ip_any(flow)) { @@ -62115,7 +62142,7 @@ index 578cbfe581..2b1611c912 100644 wc->masks.nw_ttl = 0xff; flow->nw_ttl = ofpact_get_SET_IP_TTL(a)->ttl; } -@@ -7123,6 +7361,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -7123,6 +7369,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, /* Set the field only if the packet actually has it. */ if (mf_are_prereqs_ok(mf, flow, wc)) { @@ -62123,7 +62150,7 @@ index 578cbfe581..2b1611c912 100644 mf_mask_field_masked(mf, ofpact_set_field_mask(set_field), wc); mf_set_flow_value_masked(mf, set_field->value, ofpact_set_field_mask(set_field), -@@ -7179,6 +7418,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -7179,6 +7426,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, case OFPACT_DEC_TTL: wc->masks.nw_ttl = 0xff; @@ -62131,7 +62158,7 @@ index 578cbfe581..2b1611c912 100644 if (compose_dec_ttl(ctx, ofpact_get_DEC_TTL(a))) { return; } -@@ -7609,6 +7849,43 @@ xlate_wc_finish(struct xlate_ctx *ctx) +@@ -7609,6 +7857,43 @@ xlate_wc_finish(struct xlate_ctx *ctx) ctx->wc->masks.vlans[i].tci = 0; } } @@ -62175,7 +62202,7 @@ index 578cbfe581..2b1611c912 100644 } /* Translates the flow, actions, or rule in 'xin' into datapath actions in -@@ -7784,6 +8061,12 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) +@@ -7784,6 +8069,12 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) goto exit; } @@ -62188,7 +62215,7 @@ index 578cbfe581..2b1611c912 100644 /* Tunnel metadata in udpif format must be normalized before translation. */ if (flow->tunnel.flags & FLOW_TNL_F_UDPIF) { const struct tun_table *tun_tab = ofproto_get_tun_tab( -@@ -8030,6 +8313,10 @@ exit: +@@ -8030,6 +8321,10 @@ exit: if (xin->odp_actions) { ofpbuf_clear(xin->odp_actions); } @@ -62212,7 +62239,7 @@ index 851088d794..2ba90e999c 100644 void xlate_bundle_set(struct ofproto_dpif *, struct ofbundle *, const char *name, enum port_vlan_mode, diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c -index 8143dd965f..bd235ce2b8 100644 +index 8143dd965f..06f6d00b39 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -215,10 +215,6 @@ struct shash all_dpif_backers = SHASH_INITIALIZER(&all_dpif_backers); @@ -62544,6 +62571,15 @@ index 8143dd965f..bd235ce2b8 100644 } if (rule) { goto out; /* Match. */ +@@ -4879,7 +4880,7 @@ packet_xlate(struct ofproto *ofproto_, struct ofproto_packet_out *opo) + if (entry->type == XC_LEARN) { + struct ofproto_flow_mod *ofm = entry->learn.ofm; + +- error = ofproto_flow_mod_learn_refresh(ofm); ++ error = ofproto_flow_mod_learn_refresh(ofm, time_msec()); + if (error) { + goto error_out; + } @@ -5550,9 +5551,9 @@ ct_zone_timeout_policy_sweep(struct dpif_backer *backer) { if (!ovs_list_is_empty(&backer->ct_tp_kill_list) @@ -62598,7 +62634,7 @@ index 8143dd965f..bd235ce2b8 100644 static void diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h -index 14b909973d..e64ca5b805 100644 +index 14b909973d..4cdae27bc1 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -143,6 +143,8 @@ struct ofproto { @@ -62622,8 +62658,22 @@ index 14b909973d..e64ca5b805 100644 /* Number of upcall handler and revalidator threads. Only affects the * ofproto-dpif implementation. */ extern uint32_t n_handlers, n_revalidators; +@@ -2015,9 +2022,11 @@ enum ofperr ofproto_flow_mod_init_for_learn(struct ofproto *, + struct ofproto_flow_mod *) + OVS_EXCLUDED(ofproto_mutex); + enum ofperr ofproto_flow_mod_learn(struct ofproto_flow_mod *, bool keep_ref, +- unsigned limit, bool *below_limit) ++ unsigned limit, bool *below_limit, ++ long long int last_used) + OVS_EXCLUDED(ofproto_mutex); +-enum ofperr ofproto_flow_mod_learn_refresh(struct ofproto_flow_mod *ofm); ++enum ofperr ofproto_flow_mod_learn_refresh(struct ofproto_flow_mod *ofm, ++ long long int last_used); + enum ofperr ofproto_flow_mod_learn_start(struct ofproto_flow_mod *ofm) + OVS_REQUIRES(ofproto_mutex); + void ofproto_flow_mod_learn_revert(struct ofproto_flow_mod *ofm) diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c -index 56aeac7209..8569ce94cb 100644 +index 56aeac7209..609627d99e 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -310,6 +310,7 @@ unsigned ofproto_flow_limit = OFPROTO_FLOW_LIMIT_DEFAULT; @@ -62801,7 +62851,120 @@ index 56aeac7209..8569ce94cb 100644 VLOG_WARN_RL(&rl, "%s: failed to allocate a rule.", ofproto->name); return OFPERR_OFPFMFC_UNKNOWN; } -@@ -6797,9 +6862,9 @@ static void +@@ -5377,7 +5442,8 @@ ofproto_flow_mod_init_for_learn(struct ofproto *ofproto, + } + + enum ofperr +-ofproto_flow_mod_learn_refresh(struct ofproto_flow_mod *ofm) ++ofproto_flow_mod_learn_refresh(struct ofproto_flow_mod *ofm, ++ long long int last_used) + { + enum ofperr error = 0; + +@@ -5398,9 +5464,37 @@ ofproto_flow_mod_learn_refresh(struct ofproto_flow_mod *ofm) + * this function is executed the rule will be reinstated. */ + if (rule->state == RULE_REMOVED) { + struct cls_rule cr; ++ struct oftable *table = &rule->ofproto->tables[rule->table_id]; ++ ovs_version_t tables_version = rule->ofproto->tables_version; ++ ++ if (!cls_rule_visible_in_version(&rule->cr, tables_version)) { ++ const struct cls_rule *curr_cls_rule; ++ ++ /* Only check for matching classifier rules and their modified ++ * time, instead of also checking all rule metadata, with the goal ++ * of suppressing a learn action update that would replace a more ++ * recent rule in the classifier. */ ++ curr_cls_rule = classifier_find_rule_exactly(&table->cls, ++ &rule->cr, ++ tables_version); ++ if (curr_cls_rule) { ++ struct rule *curr_rule = rule_from_cls_rule(curr_cls_rule); ++ long long int curr_last_used; ++ ++ ovs_mutex_lock(&curr_rule->mutex); ++ curr_last_used = curr_rule->modified; ++ ovs_mutex_unlock(&curr_rule->mutex); ++ ++ if (curr_last_used > last_used) { ++ /* In the case of a newer visible rule, don't recreate the ++ * current rule. */ ++ return 0; ++ } ++ } ++ } + +- cls_rule_clone(&cr, &rule->cr); + ovs_mutex_lock(&rule->mutex); ++ cls_rule_clone(&cr, &rule->cr); + error = ofproto_rule_create(rule->ofproto, &cr, rule->table_id, + rule->flow_cookie, + rule->idle_timeout, +@@ -5411,6 +5505,7 @@ ofproto_flow_mod_learn_refresh(struct ofproto_flow_mod *ofm) + rule->match_tlv_bitmap, + rule->ofpacts_tlv_bitmap, + &ofm->temp_rule); ++ ofm->temp_rule->modified = last_used; + ovs_mutex_unlock(&rule->mutex); + if (!error) { + ofproto_rule_unref(rule); /* Release old reference. */ +@@ -5418,7 +5513,7 @@ ofproto_flow_mod_learn_refresh(struct ofproto_flow_mod *ofm) + } else { + /* Refresh the existing rule. */ + ovs_mutex_lock(&rule->mutex); +- rule->modified = time_msec(); ++ rule->modified = last_used; + ovs_mutex_unlock(&rule->mutex); + } + return error; +@@ -5470,10 +5565,16 @@ ofproto_flow_mod_learn_finish(struct ofproto_flow_mod *ofm, + + /* Refresh 'ofm->temp_rule', for which the caller holds a reference, if already + * in the classifier, insert it otherwise. If the rule has already been +- * removed from the classifier, a new rule is created using 'ofm->temp_rule' as +- * a template and the reference to the old 'ofm->temp_rule' is freed. If +- * 'keep_ref' is true, then a reference to the current rule is held, otherwise +- * it is released and 'ofm->temp_rule' is set to NULL. ++ * removed from the classifier and replaced by another rule, the 'last_used' ++ * parameter is used to determine whether the newer rule is replaced or kept. ++ * If 'last_used' is greater than the last modified time of an identical rule ++ * in the classifier, then a new rule is created using 'ofm->temp_rule' as a ++ * template and the reference to the old 'ofm->temp_rule' is freed. If the ++ * rule has been removed but another identical rule doesn't exist in the ++ * classifier, then it will be recreated. If the rule hasn't been removed ++ * from the classifier, then 'last_used' is used to update the rules modified ++ * time. If 'keep_ref' is true, then a reference to the current rule is held, ++ * otherwise it is released and 'ofm->temp_rule' is set to NULL. + * + * If 'limit' != 0, insertion will fail if there are more than 'limit' rules + * in the same table with the same cookie. If insertion succeeds, +@@ -5484,10 +5585,11 @@ ofproto_flow_mod_learn_finish(struct ofproto_flow_mod *ofm, + * during the call. */ + enum ofperr + ofproto_flow_mod_learn(struct ofproto_flow_mod *ofm, bool keep_ref, +- unsigned limit, bool *below_limitp) ++ unsigned limit, bool *below_limitp, ++ long long int last_used) + OVS_EXCLUDED(ofproto_mutex) + { +- enum ofperr error = ofproto_flow_mod_learn_refresh(ofm); ++ enum ofperr error = ofproto_flow_mod_learn_refresh(ofm, last_used); + struct rule *rule = ofm->temp_rule; + bool below_limit = true; + +@@ -5520,6 +5622,11 @@ ofproto_flow_mod_learn(struct ofproto_flow_mod *ofm, bool keep_ref, + + error = ofproto_flow_mod_learn_start(ofm); + if (!error) { ++ /* ofproto_flow_mod_learn_start may have overwritten ++ * modified with current time. */ ++ ovs_mutex_lock(&ofm->temp_rule->mutex); ++ ofm->temp_rule->modified = last_used; ++ ovs_mutex_unlock(&ofm->temp_rule->mutex); + error = ofproto_flow_mod_learn_finish(ofm, NULL); + } + } else { +@@ -6797,9 +6904,9 @@ static void meter_delete_all(struct ofproto *ofproto) OVS_REQUIRES(ofproto_mutex) { @@ -62813,7 +62976,7 @@ index 56aeac7209..8569ce94cb 100644 hmap_remove(&ofproto->meters, &meter->node); meter_destroy(ofproto, meter); } -@@ -7339,8 +7404,13 @@ init_group(struct ofproto *ofproto, const struct ofputil_group_mod *gm, +@@ -7339,8 +7446,13 @@ init_group(struct ofproto *ofproto, const struct ofputil_group_mod *gm, return OFPERR_OFPGMFC_BAD_TYPE; } @@ -62827,7 +62990,7 @@ index 56aeac7209..8569ce94cb 100644 VLOG_WARN_RL(&rl, "%s: failed to allocate group", ofproto->name); return OFPERR_OFPGMFC_OUT_OF_GROUPS; } -@@ -7377,6 +7447,7 @@ init_group(struct ofproto *ofproto, const struct ofputil_group_mod *gm, +@@ -7377,6 +7489,7 @@ init_group(struct ofproto *ofproto, const struct ofputil_group_mod *gm, &(*ofgroup)->props)); ofputil_bucket_list_destroy(CONST_CAST(struct ovs_list *, &(*ofgroup)->buckets)); @@ -62835,7 +62998,7 @@ index 56aeac7209..8569ce94cb 100644 ofproto->ofproto_class->group_dealloc(*ofgroup); } return error; -@@ -8902,7 +8973,7 @@ eviction_group_hash_rule(struct rule *rule) +@@ -8902,7 +9015,7 @@ eviction_group_hash_rule(struct rule *rule) hash = table->eviction_group_id_basis; miniflow_expand(rule->cr.match.flow, &flow); for (sf = table->eviction_fields; @@ -62844,7 +63007,7 @@ index 56aeac7209..8569ce94cb 100644 sf++) { if (mf_are_prereqs_ok(sf->field, &flow, NULL)) { -@@ -9138,8 +9209,8 @@ oftable_configure_eviction(struct oftable *table, unsigned int eviction, +@@ -9138,8 +9251,8 @@ oftable_configure_eviction(struct oftable *table, unsigned int eviction, /* Destroy existing eviction groups, then destroy and recreate data * structures to recover memory. */ @@ -66644,7 +66807,7 @@ index f3e19cd83b..1d3af98dab 100644 ovs-appctl netdev-dummy/receive p1 'in_port(1),packet_type(ns=0,id=0),eth(src=3a:6d:d2:09:9c:ab,dst=1e:2c:e9:2a:66:9e),ipv4(src=192.168.10.10,dst=192.168.10.30,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' ], [0], [ignore]) diff --git a/tests/learn.at b/tests/learn.at -index 5f1d6df9de..d127fed348 100644 +index 5f1d6df9de..d0bcc83633 100644 --- a/tests/learn.at +++ b/tests/learn.at @@ -6,7 +6,7 @@ actions=learn() @@ -66665,6 +66828,70 @@ index 5f1d6df9de..d127fed348 100644 OFPT_FLOW_MOD (xid=0x6): ADD actions=learn(table=1,idle_timeout=10,hard_timeout=20,fin_idle_timeout=5,fin_hard_timeout=10,priority=10,cookie=0xfedcba9876543210,in_port=99,NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG1[16..31]) OFPT_FLOW_MOD (xid=0x7): ADD actions=learn(table=1,limit=4096) OFPT_FLOW_MOD (xid=0x8): ADD actions=learn(table=1,limit=4096,result_dst=NXM_NX_REG0[0]) +@@ -836,3 +836,63 @@ AT_CHECK([ovs-vsctl add-br br1 -- set b br1 datapath_type=dummy]) + + OVS_VSWITCHD_STOP + AT_CLEANUP ++ ++AT_SETUP([learning action - flapping learn rule]) ++OVS_VSWITCHD_START ++add_of_ports br0 1 2 3 ++ ++AT_CHECK([ovs-appctl time/stop], [0], [ignore]) ++AT_CHECK([[ovs-ofctl add-flow br0 'table=0,priority=2,in_port=1,actions=resubmit(,2)']]) ++AT_CHECK([[ovs-ofctl add-flow br0 'table=0,priority=2,in_port=2,actions=resubmit(,2)']]) ++AT_CHECK([[ovs-ofctl add-flow br0 'table=2,actions=learn(table=0,hard_timeout=3,priority=1,cookie=0x123,NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],output:OXM_OF_IN_PORT[]),output:3']]) ++ ++packet="eth(src=50:54:00:00:00:06,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)" ++ ++dnl Run this test a few times in a loop to reduce the likelyhood that it passes by chance. ++for i in 1 2 3; do ++ AT_CHECK([ovs-appctl revalidator/pause], [0]) ++ AT_CHECK([ovs-appctl netdev-dummy/receive p2 $packet], [0]) ++ AT_CHECK([ovs-appctl time/warp 75], [0], [ignore]) ++ AT_CHECK([ovs-appctl netdev-dummy/receive p1 $packet], [0]) ++ AT_CHECK([ovs-appctl time/warp 75], [0], [ignore]) ++ AT_CHECK([ovs-appctl netdev-dummy/receive p2 $packet], [0]) ++ AT_CHECK([ovs-appctl time/warp 75], [0], [ignore]) ++ AT_CHECK([ovs-appctl netdev-dummy/receive p1 $packet], [0]) ++ AT_CHECK([ovs-appctl time/warp 75], [0], [ignore]) ++ ++ AT_CHECK([ovs-appctl revalidator/resume], [0]) ++ AT_CHECK([ovs-appctl revalidator/wait], [0]) ++ ++ AT_CHECK([ovs-ofctl --no-stats dump-flows br0 | ofctl_strip | sort | grep 0x123], [0], [dnl ++ cookie=0x123, hard_timeout=3, priority=1,dl_dst=50:54:00:00:00:06 actions=output:1 ++ table=2, actions=learn(table=0,hard_timeout=3,priority=1,cookie=0x123,NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],output:OXM_OF_IN_PORT[[]]),output:3 ++]) ++ ++ AT_CHECK([ovs-appctl revalidator/pause], [0]) ++ AT_CHECK([ovs-appctl netdev-dummy/receive p1 $packet], [0]) ++ AT_CHECK([ovs-appctl time/warp 75], [0], [ignore]) ++ AT_CHECK([ovs-appctl netdev-dummy/receive p2 $packet], [0]) ++ AT_CHECK([ovs-appctl time/warp 75], [0], [ignore]) ++ AT_CHECK([ovs-appctl netdev-dummy/receive p1 $packet], [0]) ++ AT_CHECK([ovs-appctl time/warp 75], [0], [ignore]) ++ AT_CHECK([ovs-appctl netdev-dummy/receive p2 $packet], [0]) ++ AT_CHECK([ovs-appctl time/warp 75], [0], [ignore]) ++ ++ AT_CHECK([ovs-appctl revalidator/resume], [0]) ++ AT_CHECK([ovs-appctl revalidator/wait], [0]) ++ ++ AT_CHECK([ovs-ofctl --no-stats dump-flows br0 | ofctl_strip | sort | grep 0x123], [0], [dnl ++ cookie=0x123, hard_timeout=3, priority=1,dl_dst=50:54:00:00:00:06 actions=output:2 ++ table=2, actions=learn(table=0,hard_timeout=3,priority=1,cookie=0x123,NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],output:OXM_OF_IN_PORT[[]]),output:3 ++]) ++done ++ ++dnl Wait and check for learned rule eviction due to hard timeout. ++AT_CHECK([ovs-appctl time/warp 3200], [0], [ignore]) ++ ++AT_CHECK([ovs-ofctl --no-stats dump-flows br0 | ofctl_strip | grep 0x123], [0], [dnl ++ table=2, actions=learn(table=0,hard_timeout=3,priority=1,cookie=0x123,NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],output:OXM_OF_IN_PORT[[]]),output:3 ++]) ++ ++OVS_VSWITCHD_STOP ++AT_CLEANUP diff --git a/tests/learning-switch.at b/tests/learning-switch.at new file mode 100644 index 0000000000..ac2fc1b801 diff --git a/SPECS/openvswitch2.17.spec b/SPECS/openvswitch2.17.spec index b3ec986..d37d2a7 100644 --- a/SPECS/openvswitch2.17.spec +++ b/SPECS/openvswitch2.17.spec @@ -57,7 +57,7 @@ Summary: Open vSwitch Group: System Environment/Daemons daemon/database/utilities URL: http://www.openvswitch.org/ Version: 2.17.0 -Release: 106%{?dist} +Release: 107%{?dist} # Nearly all of openvswitch is ASL 2.0. The bugtool is LGPLv2+, and the # lib/sflow*.[ch] files are SISSL @@ -751,6 +751,12 @@ exit 0 %endif %changelog +* Wed Sep 06 2023 Open vSwitch CI - 2.17.0-107 +- Merging upstream branch-2.17 [RH git: 9ed4710854] + Commit list: + a141b62c2f ofproto-dpif-xlate: Don't reinstall removed XC_LEARN rule. (#2213892) + + * Wed Aug 30 2023 Open vSwitch CI - 2.17.0-106 - Merging upstream branch-2.17 [RH git: 8da11aaa9d] Commit list: