diff --git a/SOURCES/openvswitch-2.13.0.patch b/SOURCES/openvswitch-2.13.0.patch index 9835e49..076eb18 100644 --- a/SOURCES/openvswitch-2.13.0.patch +++ b/SOURCES/openvswitch-2.13.0.patch @@ -82054,7 +82054,7 @@ index cc8c6857af..a8e9b9ebb1 100644 VLOG(level, "%s", ds_cstr(&ds)); ds_destroy(&ds); diff --git a/lib/classifier.c b/lib/classifier.c -index 0fad953213..2a1d155dad 100644 +index 0fad953213..c4790ee6ba 100644 --- a/lib/classifier.c +++ b/lib/classifier.c @@ -393,7 +393,9 @@ classifier_set_prefix_fields(struct classifier *cls, @@ -82155,6 +82155,15 @@ index 0fad953213..2a1d155dad 100644 return true; } } +@@ -1672,7 +1683,7 @@ find_match(const struct cls_subtable *subtable, ovs_version_t version, + + static const struct cls_match * + find_match_wc(const struct cls_subtable *subtable, ovs_version_t version, +- const struct flow *flow, struct trie_ctx trie_ctx[CLS_MAX_TRIES], ++ const struct flow *flow, struct trie_ctx *trie_ctx, + unsigned int n_tries, struct flow_wildcards *wc) + { + if (OVS_UNLIKELY(!wc)) { @@ -2001,12 +2012,12 @@ static unsigned int trie_lookup(const struct cls_trie *trie, const struct flow *flow, union trie_prefix *plens) @@ -85495,7 +85504,7 @@ index 42d3335f0f..97320a4dba 100644 } else { a = attrs[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL]; diff --git a/lib/odp-util.c b/lib/odp-util.c -index 746d1e97d4..6daad7f58b 100644 +index 746d1e97d4..0df892132e 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -390,7 +390,8 @@ format_odp_push_nsh_action(struct ds *ds, @@ -85637,7 +85646,19 @@ index 746d1e97d4..6daad7f58b 100644 if (flow_tnl_dst_is_set(&md->tunnel)) { tun_key_to_attr(buf, &md->tunnel, &md->tunnel, NULL, NULL); } -@@ -7416,15 +7437,18 @@ odp_key_fitness_to_string(enum odp_key_fitness fitness) +@@ -6971,11 +6992,6 @@ parse_l2_5_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1], + } + } + } +- } else if (src_flow->nw_proto == IPPROTO_IGMP +- && src_flow->dl_type == htons(ETH_TYPE_IP)) { +- /* OVS userspace parses the IGMP type, code, and group, but its +- * datapaths do not, so there is always missing information. */ +- return ODP_FIT_TOO_LITTLE; + } + if (is_mask && expected_bit != OVS_KEY_ATTR_UNSPEC) { + if ((flow->tp_src || flow->tp_dst) && flow->nw_proto != 0xff) { +@@ -7416,15 +7432,18 @@ odp_key_fitness_to_string(enum odp_key_fitness fitness) /* Appends an OVS_ACTION_ATTR_USERSPACE action to 'odp_actions' that specifies * Netlink PID 'pid'. If 'userdata' is nonnull, adds a userdata attribute @@ -85661,7 +85682,7 @@ index 746d1e97d4..6daad7f58b 100644 { size_t userdata_ofs; size_t offset; -@@ -7432,6 +7456,9 @@ odp_put_userspace_action(uint32_t pid, +@@ -7432,6 +7451,9 @@ odp_put_userspace_action(uint32_t pid, offset = nl_msg_start_nested(odp_actions, OVS_ACTION_ATTR_USERSPACE); nl_msg_put_u32(odp_actions, OVS_USERSPACE_ATTR_PID, pid); if (userdata) { @@ -85671,7 +85692,7 @@ index 746d1e97d4..6daad7f58b 100644 userdata_ofs = odp_actions->size + NLA_HDRLEN; /* The OVS kernel module before OVS 1.11 and the upstream Linux kernel -@@ -7457,9 +7484,16 @@ odp_put_userspace_action(uint32_t pid, +@@ -7457,9 +7479,16 @@ odp_put_userspace_action(uint32_t pid, if (include_actions) { nl_msg_put_flag(odp_actions, OVS_USERSPACE_ATTR_ACTIONS); } @@ -85689,7 +85710,7 @@ index 746d1e97d4..6daad7f58b 100644 } void -@@ -7565,6 +7599,28 @@ struct offsetof_sizeof { +@@ -7565,6 +7594,28 @@ struct offsetof_sizeof { int size; }; @@ -85718,7 +85739,7 @@ index 746d1e97d4..6daad7f58b 100644 /* Compares each of the fields in 'key0' and 'key1'. The fields are specified * in 'offsetof_sizeof_arr', which is an array terminated by a 0-size field. * Returns true if all of the fields are equal, false if at least one differs. -@@ -7643,9 +7699,10 @@ commit_set_ether_action(const struct flow *flow, struct flow *base_flow, +@@ -7643,9 +7694,10 @@ commit_set_ether_action(const struct flow *flow, struct flow *base_flow, struct flow_wildcards *wc, bool use_masked) { @@ -85730,7 +85751,7 @@ index 746d1e97d4..6daad7f58b 100644 if (flow->packet_type != htonl(PT_ETH)) { return; } -@@ -7653,11 +7710,13 @@ commit_set_ether_action(const struct flow *flow, struct flow *base_flow, +@@ -7653,11 +7705,13 @@ commit_set_ether_action(const struct flow *flow, struct flow *base_flow, get_ethernet_key(flow, &key); get_ethernet_key(base_flow, &base); get_ethernet_key(&wc->masks, &mask); @@ -85744,7 +85765,7 @@ index 746d1e97d4..6daad7f58b 100644 put_ethernet_key(&mask, &wc->masks); } } -@@ -7781,7 +7840,7 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow, +@@ -7781,7 +7835,7 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow, struct ofpbuf *odp_actions, struct flow_wildcards *wc, bool use_masked) { @@ -85753,7 +85774,7 @@ index 746d1e97d4..6daad7f58b 100644 struct offsetof_sizeof ovs_key_ipv4_offsetof_sizeof_arr[] = OVS_KEY_IPV4_OFFSETOF_SIZEOF_ARR; -@@ -7792,6 +7851,7 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow, +@@ -7792,6 +7846,7 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow, get_ipv4_key(flow, &key, false); get_ipv4_key(base_flow, &base, false); get_ipv4_key(&wc->masks, &mask, true); @@ -85761,7 +85782,7 @@ index 746d1e97d4..6daad7f58b 100644 mask.ipv4_proto = 0; /* Not writeable. */ mask.ipv4_frag = 0; /* Not writable. */ -@@ -7803,9 +7863,8 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow, +@@ -7803,9 +7858,8 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow, if (commit(OVS_KEY_ATTR_IPV4, use_masked, &key, &base, &mask, sizeof key, ovs_key_ipv4_offsetof_sizeof_arr, odp_actions)) { put_ipv4_key(&base, base_flow, false); @@ -85773,7 +85794,7 @@ index 746d1e97d4..6daad7f58b 100644 } } -@@ -7838,7 +7897,7 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow, +@@ -7838,7 +7892,7 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow, struct ofpbuf *odp_actions, struct flow_wildcards *wc, bool use_masked) { @@ -85782,7 +85803,7 @@ index 746d1e97d4..6daad7f58b 100644 struct offsetof_sizeof ovs_key_ipv6_offsetof_sizeof_arr[] = OVS_KEY_IPV6_OFFSETOF_SIZEOF_ARR; -@@ -7849,6 +7908,7 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow, +@@ -7849,6 +7903,7 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow, get_ipv6_key(flow, &key, false); get_ipv6_key(base_flow, &base, false); get_ipv6_key(&wc->masks, &mask, true); @@ -85790,7 +85811,7 @@ index 746d1e97d4..6daad7f58b 100644 mask.ipv6_proto = 0; /* Not writeable. */ mask.ipv6_frag = 0; /* Not writable. */ mask.ipv6_label &= htonl(IPV6_LABEL_MASK); /* Not writable. */ -@@ -7861,9 +7921,8 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow, +@@ -7861,9 +7916,8 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow, if (commit(OVS_KEY_ATTR_IPV6, use_masked, &key, &base, &mask, sizeof key, ovs_key_ipv6_offsetof_sizeof_arr, odp_actions)) { put_ipv6_key(&base, base_flow, false); @@ -85802,7 +85823,7 @@ index 746d1e97d4..6daad7f58b 100644 } } -@@ -7894,17 +7953,19 @@ static enum slow_path_reason +@@ -7894,17 +7948,19 @@ static enum slow_path_reason commit_set_arp_action(const struct flow *flow, struct flow *base_flow, struct ofpbuf *odp_actions, struct flow_wildcards *wc) { @@ -85823,7 +85844,7 @@ index 746d1e97d4..6daad7f58b 100644 put_arp_key(&mask, &wc->masks); return SLOW_ACTION; } -@@ -7931,7 +7992,7 @@ static enum slow_path_reason +@@ -7931,7 +7987,7 @@ static enum slow_path_reason commit_set_icmp_action(const struct flow *flow, struct flow *base_flow, struct ofpbuf *odp_actions, struct flow_wildcards *wc) { @@ -85832,7 +85853,7 @@ index 746d1e97d4..6daad7f58b 100644 struct offsetof_sizeof ovs_key_icmp_offsetof_sizeof_arr[] = OVS_KEY_ICMP_OFFSETOF_SIZEOF_ARR; enum ovs_key_attr attr; -@@ -7947,10 +8008,12 @@ commit_set_icmp_action(const struct flow *flow, struct flow *base_flow, +@@ -7947,10 +8003,12 @@ commit_set_icmp_action(const struct flow *flow, struct flow *base_flow, get_icmp_key(flow, &key); get_icmp_key(base_flow, &base); get_icmp_key(&wc->masks, &mask); @@ -85845,7 +85866,7 @@ index 746d1e97d4..6daad7f58b 100644 put_icmp_key(&mask, &wc->masks); return SLOW_ACTION; } -@@ -7998,17 +8061,19 @@ commit_set_nd_action(const struct flow *flow, struct flow *base_flow, +@@ -7998,17 +8056,19 @@ commit_set_nd_action(const struct flow *flow, struct flow *base_flow, struct ofpbuf *odp_actions, struct flow_wildcards *wc, bool use_masked) { @@ -85866,7 +85887,7 @@ index 746d1e97d4..6daad7f58b 100644 put_nd_key(&mask, &wc->masks); return SLOW_ACTION; } -@@ -8022,18 +8087,20 @@ commit_set_nd_extensions_action(const struct flow *flow, +@@ -8022,18 +8082,20 @@ commit_set_nd_extensions_action(const struct flow *flow, struct ofpbuf *odp_actions, struct flow_wildcards *wc, bool use_masked) { @@ -85888,7 +85909,7 @@ index 746d1e97d4..6daad7f58b 100644 put_nd_extensions_key(&mask, &wc->masks); return SLOW_ACTION; } -@@ -8248,7 +8315,7 @@ commit_set_port_action(const struct flow *flow, struct flow *base_flow, +@@ -8248,7 +8310,7 @@ commit_set_port_action(const struct flow *flow, struct flow *base_flow, bool use_masked) { enum ovs_key_attr key_type; @@ -85897,7 +85918,7 @@ index 746d1e97d4..6daad7f58b 100644 struct offsetof_sizeof ovs_key_tp_offsetof_sizeof_arr[] = OVS_KEY_TCP_OFFSETOF_SIZEOF_ARR; -@@ -8274,10 +8341,12 @@ commit_set_port_action(const struct flow *flow, struct flow *base_flow, +@@ -8274,10 +8336,12 @@ commit_set_port_action(const struct flow *flow, struct flow *base_flow, get_tp_key(flow, &key); get_tp_key(base_flow, &base); get_tp_key(&wc->masks, &mask); @@ -85910,7 +85931,7 @@ index 746d1e97d4..6daad7f58b 100644 put_tp_key(&mask, &wc->masks); } } -@@ -8301,7 +8370,7 @@ commit_set_priority_action(const struct flow *flow, struct flow *base_flow, +@@ -8301,7 +8365,7 @@ commit_set_priority_action(const struct flow *flow, struct flow *base_flow, if (commit(OVS_KEY_ATTR_PRIORITY, use_masked, &key, &base, &mask, sizeof key, ovs_key_prio_offsetof_sizeof_arr, odp_actions)) { base_flow->skb_priority = base; @@ -85919,7 +85940,7 @@ index 746d1e97d4..6daad7f58b 100644 } } -@@ -8325,7 +8394,7 @@ commit_set_pkt_mark_action(const struct flow *flow, struct flow *base_flow, +@@ -8325,7 +8389,7 @@ commit_set_pkt_mark_action(const struct flow *flow, struct flow *base_flow, sizeof key, ovs_key_pkt_mark_offsetof_sizeof_arr, odp_actions)) { base_flow->pkt_mark = base; @@ -88721,7 +88742,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 4407f9c97a..f2a47fc697 100644 +index 4407f9c97a..bc190e855b 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -460,7 +460,7 @@ static void xlate_commit_actions(struct xlate_ctx *ctx); @@ -88860,7 +88881,15 @@ index 4407f9c97a..f2a47fc697 100644 } /* Determine output bundle. */ -@@ -3076,6 +3117,7 @@ xlate_normal(struct xlate_ctx *ctx) +@@ -3024,7 +3065,6 @@ xlate_normal(struct xlate_ctx *ctx) + */ + ctx->xout->slow |= SLOW_ACTION; + +- memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src); + if (mcast_snooping_is_membership(flow->tp_src) || + mcast_snooping_is_query(flow->tp_src)) { + if (ctx->xin->allow_side_effects && ctx->xin->packet) { +@@ -3076,6 +3116,7 @@ xlate_normal(struct xlate_ctx *ctx) xlate_report(ctx, OFT_DETAIL, "MLD query, flooding"); xlate_normal_flood(ctx, in_xbundle, &xvlan); } @@ -88868,7 +88897,7 @@ index 4407f9c97a..f2a47fc697 100644 } else { if (is_ip_local_multicast(flow, wc)) { /* RFC4541: section 2.1.2, item 2: Packets with a dst IP -@@ -3198,12 +3240,11 @@ compose_sample_action(struct xlate_ctx *ctx, +@@ -3198,12 +3239,11 @@ compose_sample_action(struct xlate_ctx *ctx, odp_port_t odp_port = ofp_port_to_odp_port( ctx->xbridge, ctx->xin->flow.in_port.ofp_port); uint32_t pid = dpif_port_get_pid(ctx->xbridge->dpif, odp_port); @@ -88886,7 +88915,7 @@ index 4407f9c97a..f2a47fc697 100644 if (is_sample) { nl_msg_end_nested(ctx->odp_actions, actions_offset); nl_msg_end_nested(ctx->odp_actions, sample_offset); -@@ -3248,7 +3289,9 @@ compose_ipfix_action(struct xlate_ctx *ctx, odp_port_t output_odp_port) +@@ -3248,7 +3288,9 @@ compose_ipfix_action(struct xlate_ctx *ctx, odp_port_t output_odp_port) struct dpif_ipfix *ipfix = ctx->xbridge->ipfix; odp_port_t tunnel_out_port = ODPP_NONE; @@ -88897,7 +88926,7 @@ index 4407f9c97a..f2a47fc697 100644 return; } -@@ -3497,6 +3540,9 @@ propagate_tunnel_data_to_flow__(struct flow *dst_flow, +@@ -3497,6 +3539,9 @@ propagate_tunnel_data_to_flow__(struct flow *dst_flow, dst_flow->dl_dst = dmac; dst_flow->dl_src = smac; @@ -88907,7 +88936,7 @@ index 4407f9c97a..f2a47fc697 100644 dst_flow->packet_type = htonl(PT_ETH); dst_flow->nw_dst = src_flow->tunnel.ip_dst; dst_flow->nw_src = src_flow->tunnel.ip_src; -@@ -3572,7 +3618,7 @@ propagate_tunnel_data_to_flow(struct xlate_ctx *ctx, struct eth_addr dmac, +@@ -3572,7 +3617,7 @@ propagate_tunnel_data_to_flow(struct xlate_ctx *ctx, struct eth_addr dmac, static int native_tunnel_output(struct xlate_ctx *ctx, const struct xport *xport, const struct flow *flow, odp_port_t tunnel_odp_port, @@ -88916,7 +88945,7 @@ index 4407f9c97a..f2a47fc697 100644 { struct netdev_tnl_build_header_params tnl_params; struct ovs_action_push_tnl tnl_push_data; -@@ -3702,7 +3748,7 @@ native_tunnel_output(struct xlate_ctx *ctx, const struct xport *xport, +@@ -3702,7 +3747,7 @@ native_tunnel_output(struct xlate_ctx *ctx, const struct xport *xport, entry->tunnel_hdr.hdr_size = tnl_push_data.header_len; entry->tunnel_hdr.operation = ADD; @@ -88925,7 +88954,7 @@ index 4407f9c97a..f2a47fc697 100644 /* Similar to the stats update in revalidation, the x_cache entries * are populated by the previous translation are used to update the -@@ -3796,7 +3842,7 @@ xlate_flow_is_protected(const struct xlate_ctx *ctx, const struct flow *flow, co +@@ -3796,7 +3841,7 @@ xlate_flow_is_protected(const struct xlate_ctx *ctx, const struct flow *flow, co */ static void patch_port_output(struct xlate_ctx *ctx, const struct xport *in_dev, @@ -88934,7 +88963,7 @@ index 4407f9c97a..f2a47fc697 100644 { struct flow *flow = &ctx->xin->flow; struct flow old_flow = ctx->xin->flow; -@@ -3838,8 +3884,9 @@ patch_port_output(struct xlate_ctx *ctx, const struct xport *in_dev, +@@ -3838,8 +3883,9 @@ patch_port_output(struct xlate_ctx *ctx, const struct xport *in_dev, if (!process_special(ctx, out_dev) && may_receive(out_dev, ctx)) { if (xport_stp_forward_state(out_dev) && xport_rstp_forward_state(out_dev)) { @@ -88945,7 +88974,7 @@ index 4407f9c97a..f2a47fc697 100644 if (!ctx->freezing) { xlate_action_set(ctx); } -@@ -3854,7 +3901,7 @@ patch_port_output(struct xlate_ctx *ctx, const struct xport *in_dev, +@@ -3854,7 +3900,7 @@ patch_port_output(struct xlate_ctx *ctx, const struct xport *in_dev, mirror_mask_t old_mirrors2 = ctx->mirrors; xlate_table_action(ctx, flow->in_port.ofp_port, 0, true, true, @@ -88954,7 +88983,7 @@ index 4407f9c97a..f2a47fc697 100644 ctx->mirrors = old_mirrors2; ctx->base_flow = old_base_flow; ctx->odp_actions->size = old_size; -@@ -4071,7 +4118,21 @@ terminate_native_tunnel(struct xlate_ctx *ctx, struct flow *flow, +@@ -4071,7 +4117,21 @@ terminate_native_tunnel(struct xlate_ctx *ctx, struct flow *flow, (flow->dl_type == htons(ETH_TYPE_ARP) || flow->nw_proto == IPPROTO_ICMPV6) && is_neighbor_reply_correct(ctx, flow)) { @@ -88977,7 +89006,7 @@ index 4407f9c97a..f2a47fc697 100644 } } -@@ -4081,7 +4142,7 @@ terminate_native_tunnel(struct xlate_ctx *ctx, struct flow *flow, +@@ -4081,7 +4141,7 @@ terminate_native_tunnel(struct xlate_ctx *ctx, struct flow *flow, static void compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, const struct xlate_bond_recirc *xr, bool check_stp, @@ -88986,7 +89015,7 @@ index 4407f9c97a..f2a47fc697 100644 { const struct xport *xport = get_ofp_port(ctx->xbridge, ofp_port); struct flow_wildcards *wc = ctx->wc; -@@ -4111,6 +4172,10 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, +@@ -4111,6 +4171,10 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, if (xport->pt_mode == NETDEV_PT_LEGACY_L3) { flow->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE, ntohs(flow->dl_type)); @@ -88997,7 +89026,7 @@ index 4407f9c97a..f2a47fc697 100644 } } -@@ -4118,7 +4183,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, +@@ -4118,7 +4182,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, if (truncate) { xlate_report_error(ctx, "Cannot truncate output to patch port"); } @@ -89006,7 +89035,7 @@ index 4407f9c97a..f2a47fc697 100644 return; } -@@ -4203,7 +4268,8 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, +@@ -4203,7 +4267,8 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, xr->recirc_id); } else if (is_native_tunnel) { /* Output to native tunnel port. */ @@ -89016,7 +89045,7 @@ index 4407f9c97a..f2a47fc697 100644 flow->tunnel = flow_tnl; /* Restore tunnel metadata */ } else if (terminate_native_tunnel(ctx, flow, wc, -@@ -4796,7 +4862,7 @@ put_controller_user_action(struct xlate_ctx *ctx, +@@ -4796,7 +4861,7 @@ put_controller_user_action(struct xlate_ctx *ctx, ctx->xin->flow.in_port.ofp_port); uint32_t pid = dpif_port_get_pid(ctx->xbridge->dpif, odp_port); odp_put_userspace_action(pid, &cookie, sizeof cookie, ODPP_NONE, @@ -89025,7 +89054,7 @@ index 4407f9c97a..f2a47fc697 100644 } static void -@@ -6123,11 +6189,32 @@ static void +@@ -6123,11 +6188,32 @@ static void compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc, bool is_last_action) { @@ -89061,7 +89090,7 @@ index 4407f9c97a..f2a47fc697 100644 /* Ensure that any prior actions are applied before composing the new * conntrack action. */ xlate_commit_actions(ctx); -@@ -6139,11 +6226,6 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc, +@@ -6139,11 +6225,6 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc, do_xlate_actions(ofc->actions, ofpact_ct_get_action_len(ofc), ctx, is_last_action, false); @@ -89073,7 +89102,7 @@ index 4407f9c97a..f2a47fc697 100644 ct_offset = nl_msg_start_nested(ctx->odp_actions, OVS_ACTION_ATTR_CT); if (ofc->flags & NX_CT_F_COMMIT) { -@@ -6278,6 +6360,7 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx, +@@ -6278,6 +6359,7 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx, * then ctx->exit would be true. Reset to false so that we can * do flow translation for 'IF_LESS_EQUAL' case. finish_freezing() * would have taken care of Undoing the changes done for freeze. */ @@ -89081,7 +89110,7 @@ index 4407f9c97a..f2a47fc697 100644 ctx->exit = false; offset_attr = nl_msg_start_nested( -@@ -6302,7 +6385,7 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx, +@@ -6302,7 +6384,7 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx, ctx->was_mpls = old_was_mpls; ctx->conntracked = old_conntracked; ctx->xin->flow = old_flow; @@ -89090,7 +89119,7 @@ index 4407f9c97a..f2a47fc697 100644 } static void -@@ -6680,13 +6763,14 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -6680,13 +6762,14 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, return; } @@ -89106,7 +89135,7 @@ index 4407f9c97a..f2a47fc697 100644 if (ctx->error) { break; -@@ -6694,7 +6778,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -6694,7 +6777,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, recirc_for_mpls(a, ctx); @@ -89115,7 +89144,7 @@ index 4407f9c97a..f2a47fc697 100644 /* Check if need to store the remaining actions for later * execution. */ if (ctx->freezing) { -@@ -7067,7 +7151,9 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -7067,7 +7150,9 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_CT_CLEAR: @@ -89126,7 +89155,7 @@ index 4407f9c97a..f2a47fc697 100644 break; case OFPACT_NAT: -@@ -7085,17 +7171,18 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -7085,17 +7170,18 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_CHECK_PKT_LARGER: { @@ -89150,7 +89179,7 @@ index 4407f9c97a..f2a47fc697 100644 break; } } -@@ -7519,7 +7606,8 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) +@@ -7519,7 +7605,8 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) /* Restore pipeline metadata. May change flow's in_port and other * metadata to the values that existed when freezing was triggered. */ @@ -89160,7 +89189,7 @@ index 4407f9c97a..f2a47fc697 100644 /* Restore stack, if any. */ if (state->stack) { -@@ -7571,14 +7659,10 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) +@@ -7571,14 +7658,10 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) ctx.error = XLATE_INVALID_TUNNEL_METADATA; goto exit; } @@ -89189,7 +89218,7 @@ index 3426a27b2d..e4959ec686 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 d3cb392077..d8189814b5 100644 +index d3cb392077..f426ffdc5c 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); @@ -89317,7 +89346,31 @@ index d3cb392077..d8189814b5 100644 cdtp.id = ct_tp->tp_id; SIMAP_FOR_EACH (node, &ct_tp->tp) { ct_dpif_set_timeout_policy_attr_by_name(&cdtp, node->name, node->data); -@@ -5563,6 +5585,7 @@ get_datapath_cap(const char *datapath_type, struct smap *cap) +@@ -5496,6 +5518,7 @@ ct_set_zone_timeout_policy(const char *datapath_type, uint16_t zone_id, + ct_timeout_policy_unref(backer, ct_zone->ct_tp); + ct_zone->ct_tp = ct_tp; + ct_tp->ref_count++; ++ backer->need_revalidate = REV_RECONFIGURE; + } + } else { + struct ct_zone *new_ct_zone = ct_zone_alloc(zone_id); +@@ -5503,6 +5526,7 @@ ct_set_zone_timeout_policy(const char *datapath_type, uint16_t zone_id, + cmap_insert(&backer->ct_zones, &new_ct_zone->node, + hash_int(zone_id, 0)); + ct_tp->ref_count++; ++ backer->need_revalidate = REV_RECONFIGURE; + } + } + +@@ -5519,6 +5543,7 @@ ct_del_zone_timeout_policy(const char *datapath_type, uint16_t zone_id) + if (ct_zone) { + ct_timeout_policy_unref(backer, ct_zone->ct_tp); + ct_zone_remove_and_destroy(backer, ct_zone); ++ backer->need_revalidate = REV_RECONFIGURE; + } + } + +@@ -5563,6 +5588,7 @@ get_datapath_cap(const char *datapath_type, struct smap *cap) smap_add(cap, "ct_timeout", s.ct_timeout ? "true" : "false"); smap_add(cap, "explicit_drop_action", s.explicit_drop_action ? "true" :"false"); @@ -89325,7 +89378,7 @@ index d3cb392077..d8189814b5 100644 } /* Gets timeout policy name in 'backer' based on 'zone', 'dl_type' and -@@ -5717,15 +5740,7 @@ ofproto_dpif_lookup_by_name(const char *name) +@@ -5717,15 +5743,7 @@ ofproto_dpif_lookup_by_name(const char *name) struct ofproto_dpif * ofproto_dpif_lookup_by_uuid(const struct uuid *uuid) { @@ -89342,7 +89395,7 @@ index d3cb392077..d8189814b5 100644 } static void -@@ -6335,6 +6350,7 @@ ofproto_unixctl_dpif_show_dp_features(struct unixctl_conn *conn, +@@ -6335,6 +6353,7 @@ ofproto_unixctl_dpif_show_dp_features(struct unixctl_conn *conn, dpif_show_support(&ofproto->backer->bt_support, &ds); unixctl_command_reply(conn, ds_cstr(&ds)); @@ -90320,7 +90373,7 @@ index 18c83fe9c2..dd14d81091 100644 struct hmap servers; struct ovsdb_error *error = diff --git a/ovsdb/raft.c b/ovsdb/raft.c -index 4789bc4f22..68aea2823b 100644 +index 4789bc4f22..b09889d40b 100644 --- a/ovsdb/raft.c +++ b/ovsdb/raft.c @@ -36,6 +36,7 @@ @@ -90331,18 +90384,20 @@ index 4789bc4f22..68aea2823b 100644 #include "socket-util.h" #include "stream.h" #include "timeval.h" -@@ -73,7 +74,9 @@ enum raft_failure_test { +@@ -73,7 +74,11 @@ enum raft_failure_test { FT_CRASH_BEFORE_SEND_EXEC_REQ, FT_CRASH_AFTER_SEND_EXEC_REQ, FT_CRASH_AFTER_RECV_APPEND_REQ_UPDATE, - FT_DELAY_ELECTION + FT_CRASH_BEFORE_SEND_SNAPSHOT_REP, + FT_DELAY_ELECTION, -+ FT_DONT_SEND_VOTE_REQUEST ++ FT_DONT_SEND_VOTE_REQUEST, ++ FT_TRANSFER_LEADERSHIP, ++ FT_TRANSFER_LEADERSHIP_AFTER_SEND_APPEND_REQ, }; static enum raft_failure_test failure_test; -@@ -298,6 +301,17 @@ struct raft { +@@ -298,6 +303,17 @@ struct raft { bool had_leader; /* There has been leader elected since last election initiated. This is to help setting candidate_retrying. */ @@ -90360,7 +90415,7 @@ index 4789bc4f22..68aea2823b 100644 }; /* All Raft structures. */ -@@ -357,12 +371,19 @@ static bool raft_handle_write_error(struct raft *, struct ovsdb_error *); +@@ -357,12 +373,19 @@ static bool raft_handle_write_error(struct raft *, struct ovsdb_error *); static void raft_run_reconfigure(struct raft *); static void raft_set_leader(struct raft *, const struct uuid *sid); @@ -90380,7 +90435,7 @@ index 4789bc4f22..68aea2823b 100644 static char * raft_make_address_passive(const char *address_) { -@@ -405,6 +426,9 @@ raft_alloc(void) +@@ -405,6 +428,9 @@ raft_alloc(void) raft->election_timer = ELECTION_BASE_MSEC; @@ -90390,7 +90445,7 @@ index 4789bc4f22..68aea2823b 100644 return raft; } -@@ -918,6 +942,34 @@ raft_reset_ping_timer(struct raft *raft) +@@ -918,6 +944,34 @@ raft_reset_ping_timer(struct raft *raft) raft->ping_timeout = time_msec() + raft->election_timer / 3; } @@ -90425,7 +90480,7 @@ index 4789bc4f22..68aea2823b 100644 static void raft_add_conn(struct raft *raft, struct jsonrpc_session *js, const struct uuid *sid, bool incoming) -@@ -932,6 +984,9 @@ raft_add_conn(struct raft *raft, struct jsonrpc_session *js, +@@ -932,6 +986,9 @@ raft_add_conn(struct raft *raft, struct jsonrpc_session *js, &conn->sid); conn->incoming = incoming; conn->js_seqno = jsonrpc_session_get_seqno(conn->js); @@ -90435,7 +90490,7 @@ index 4789bc4f22..68aea2823b 100644 } /* Starts the local server in an existing Raft cluster, using the local copy of -@@ -1007,6 +1062,23 @@ raft_get_sid(const struct raft *raft) +@@ -1007,6 +1064,23 @@ raft_get_sid(const struct raft *raft) return &raft->sid; } @@ -90459,7 +90514,7 @@ index 4789bc4f22..68aea2823b 100644 /* Returns true if 'raft' has completed joining its cluster, has not left or * initiated leaving the cluster, does not have failed disk storage, and is * apparently connected to the leader in a healthy way (or is itself the -@@ -1020,12 +1092,22 @@ raft_get_sid(const struct raft *raft) +@@ -1020,12 +1094,22 @@ raft_get_sid(const struct raft *raft) bool raft_is_connected(const struct raft *raft) { @@ -90484,7 +90539,7 @@ index 4789bc4f22..68aea2823b 100644 return ret; } -@@ -1397,8 +1479,19 @@ raft_conn_run(struct raft *raft, struct raft_conn *conn) +@@ -1397,8 +1481,19 @@ raft_conn_run(struct raft *raft, struct raft_conn *conn) jsonrpc_session_run(conn->js); unsigned int new_seqno = jsonrpc_session_get_seqno(conn->js); @@ -90505,7 +90560,7 @@ index 4789bc4f22..68aea2823b 100644 conn->js_seqno = new_seqno; if (just_connected) { if (raft->joining) { -@@ -1641,6 +1734,7 @@ raft_start_election(struct raft *raft, bool leadership_transfer) +@@ -1641,6 +1736,7 @@ raft_start_election(struct raft *raft, bool leadership_transfer) } ovs_assert(raft->role != RAFT_LEADER); @@ -90513,7 +90568,7 @@ index 4789bc4f22..68aea2823b 100644 raft->role = RAFT_CANDIDATE; /* If there was no leader elected since last election, we know we are * retrying now. */ -@@ -1684,7 +1778,9 @@ raft_start_election(struct raft *raft, bool leadership_transfer) +@@ -1684,7 +1780,9 @@ raft_start_election(struct raft *raft, bool leadership_transfer) .leadership_transfer = leadership_transfer, }, }; @@ -90524,7 +90579,7 @@ index 4789bc4f22..68aea2823b 100644 } /* Vote for ourselves. */ -@@ -1703,6 +1799,8 @@ raft_open_conn(struct raft *raft, const char *address, const struct uuid *sid) +@@ -1703,6 +1801,8 @@ raft_open_conn(struct raft *raft, const char *address, const struct uuid *sid) static void raft_conn_close(struct raft_conn *conn) { @@ -90533,7 +90588,21 @@ index 4789bc4f22..68aea2823b 100644 jsonrpc_session_close(conn->js); ovs_list_remove(&conn->list_node); free(conn->nickname); -@@ -1793,15 +1891,29 @@ raft_run(struct raft *raft) +@@ -1757,6 +1857,13 @@ raft_run(struct raft *raft) + return; + } + ++ if (failure_test == FT_TRANSFER_LEADERSHIP) { ++ /* Using this function as it conveniently implements all we need and ++ * snapshotting is the main test scenario for leadership transfer. */ ++ raft_notify_snapshot_recommended(raft); ++ failure_test = FT_NO_TEST; ++ } ++ + raft_waiters_run(raft); + + if (!raft->listener && time_msec() >= raft->listen_backoff) { +@@ -1793,15 +1900,29 @@ raft_run(struct raft *raft) } /* Close unneeded sessions. */ @@ -90564,7 +90633,57 @@ index 4789bc4f22..68aea2823b 100644 HMAP_FOR_EACH (server, hmap_node, &raft->servers) { raft_open_conn(raft, server->address, &server->sid); } -@@ -2513,13 +2625,14 @@ raft_server_init_leader(struct raft *raft, struct raft_server *s) +@@ -1878,7 +1999,14 @@ raft_run(struct raft *raft) + HMAP_FOR_EACH_SAFE (cmd, next_cmd, hmap_node, &raft->commands) { + if (cmd->timestamp + && now - cmd->timestamp > raft->election_timer * 2) { +- raft_command_complete(raft, cmd, RAFT_CMD_TIMEOUT); ++ if (cmd->index && raft->role != RAFT_LEADER) { ++ /* This server lost leadership and command didn't complete ++ * in time. Likely, it wasn't replicated to the majority ++ * of servers before losing the leadership. */ ++ raft_command_complete(raft, cmd, RAFT_CMD_LOST_LEADERSHIP); ++ } else { ++ raft_command_complete(raft, cmd, RAFT_CMD_TIMEOUT); ++ } + } + } + raft_reset_ping_timer(raft); +@@ -2068,6 +2196,9 @@ raft_command_initiate(struct raft *raft, + if (failure_test == FT_CRASH_AFTER_SEND_APPEND_REQ) { + ovs_fatal(0, "Raft test: crash after sending append_request."); + } ++ if (failure_test == FT_TRANSFER_LEADERSHIP_AFTER_SEND_APPEND_REQ) { ++ failure_test = FT_TRANSFER_LEADERSHIP; ++ } + raft_reset_ping_timer(raft); + + return cmd; +@@ -2434,7 +2565,13 @@ raft_become_follower(struct raft *raft) + * configuration is already part of the log. Possibly the configuration + * log entry will not be committed, but until we know that we must use the + * new configuration. Our AppendEntries processing will properly update +- * the server configuration later, if necessary. */ ++ * the server configuration later, if necessary. ++ * ++ * Also we do not complete commands here, as they can still be completed ++ * if their log entries have already been replicated to other servers. ++ * If the entries were actually committed according to the new leader, our ++ * AppendEntries processing will complete the corresponding commands. ++ */ + struct raft_server *s; + HMAP_FOR_EACH (s, hmap_node, &raft->add_servers) { + raft_send_add_server_reply__(raft, &s->sid, s->address, false, +@@ -2448,8 +2585,6 @@ raft_become_follower(struct raft *raft) + raft_server_destroy(raft->remove_server); + raft->remove_server = NULL; + } +- +- raft_complete_all_commands(raft, RAFT_CMD_LOST_LEADERSHIP); + } + + static void +@@ -2513,13 +2648,14 @@ raft_server_init_leader(struct raft *raft, struct raft_server *s) s->match_index = 0; s->phase = RAFT_PHASE_STABLE; s->replied = false; @@ -90580,23 +90699,113 @@ index 4789bc4f22..68aea2823b 100644 raft->candidate_retrying = false; } -@@ -2731,6 +2844,7 @@ raft_update_commit_index(struct raft *raft, uint64_t new_commit_index) - raft->election_timer, e->election_timer); - raft->election_timer = e->election_timer; - raft->election_timer_new = 0; -+ raft_update_probe_intervals(raft); - } - if (e->servers) { - /* raft_run_reconfigure() can write a new Raft entry, which can -@@ -2747,6 +2861,7 @@ raft_update_commit_index(struct raft *raft, uint64_t new_commit_index) - VLOG_INFO("Election timer changed from %"PRIu64" to %"PRIu64, - raft->election_timer, e->election_timer); - raft->election_timer = e->election_timer; -+ raft_update_probe_intervals(raft); +@@ -2709,59 +2845,56 @@ raft_update_commit_index(struct raft *raft, uint64_t new_commit_index) + return false; + } + +- if (raft->role == RAFT_LEADER) { +- while (raft->commit_index < new_commit_index) { +- uint64_t index = ++raft->commit_index; +- const struct raft_entry *e = raft_get_entry(raft, index); +- if (e->data) { +- struct raft_command *cmd +- = raft_find_command_by_eid(raft, &e->eid); +- if (cmd) { +- if (!cmd->index) { +- VLOG_DBG("Command completed after role change from" +- " follower to leader "UUID_FMT, +- UUID_ARGS(&e->eid)); +- cmd->index = index; +- } +- raft_command_complete(raft, cmd, RAFT_CMD_SUCCESS); ++ while (raft->commit_index < new_commit_index) { ++ uint64_t index = ++raft->commit_index; ++ const struct raft_entry *e = raft_get_entry(raft, index); ++ ++ if (e->data) { ++ struct raft_command *cmd = raft_find_command_by_eid(raft, &e->eid); ++ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); ++ ++ if (cmd) { ++ if (!cmd->index && raft->role == RAFT_LEADER) { ++ VLOG_INFO_RL(&rl, ++ "command completed after role change from " ++ "follower to leader (eid: "UUID_FMT", " ++ "commit index: %"PRIu64")", UUID_ARGS(&e->eid), index); ++ } else if (!cmd->index && raft->role != RAFT_LEADER) { ++ /* This can happen when leader fail-over before sending ++ * execute_command_reply. */ ++ VLOG_INFO_RL(&rl, ++ "command completed without reply (eid: "UUID_FMT", " ++ "commit index: %"PRIu64")", UUID_ARGS(&e->eid), index); ++ } else if (cmd->index && raft->role != RAFT_LEADER) { ++ /* This can happen if current server lost leadership after ++ * sending append requests to the majority of servers, but ++ * before receiving majority of append replies. */ ++ VLOG_INFO_RL(&rl, ++ "command completed after role change from " ++ "leader to follower (eid: "UUID_FMT", " ++ "commit index: %"PRIu64")", UUID_ARGS(&e->eid), index); ++ /* Clearing 'sid' to avoid sending cmd execution reply. */ ++ cmd->sid = UUID_ZERO; ++ } else { ++ /* (cmd->index && raft->role == RAFT_LEADER) ++ * Normal command completion on a leader. */ + } +- } +- if (e->election_timer) { +- VLOG_INFO("Election timer changed from %"PRIu64" to %"PRIu64, +- raft->election_timer, e->election_timer); +- raft->election_timer = e->election_timer; +- raft->election_timer_new = 0; +- } +- if (e->servers) { +- /* raft_run_reconfigure() can write a new Raft entry, which can +- * reallocate raft->entries, which would invalidate 'e', so +- * this case must be last, after the one for 'e->data'. */ +- raft_run_reconfigure(raft); ++ cmd->index = index; ++ raft_command_complete(raft, cmd, RAFT_CMD_SUCCESS); } } - /* Check if any pending command can be completed, and complete it. -@@ -2960,6 +3075,15 @@ raft_update_leader(struct raft *raft, const struct uuid *sid) +- } else { +- while (raft->commit_index < new_commit_index) { +- uint64_t index = ++raft->commit_index; +- const struct raft_entry *e = raft_get_entry(raft, index); +- if (e->election_timer) { +- VLOG_INFO("Election timer changed from %"PRIu64" to %"PRIu64, +- raft->election_timer, e->election_timer); +- raft->election_timer = e->election_timer; +- } ++ if (e->election_timer) { ++ VLOG_INFO("Election timer changed from %"PRIu64" to %"PRIu64, ++ raft->election_timer, e->election_timer); ++ raft->election_timer = e->election_timer; ++ raft->election_timer_new = 0; ++ raft_update_probe_intervals(raft); + } +- /* Check if any pending command can be completed, and complete it. +- * This can happen when leader fail-over before sending +- * execute_command_reply. */ +- const struct uuid *eid = raft_get_eid(raft, new_commit_index); +- struct raft_command *cmd = raft_find_command_by_eid(raft, eid); +- if (cmd) { +- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); +- VLOG_INFO_RL(&rl, +- "Command completed without reply (eid: "UUID_FMT", " +- "commit index: %"PRIu64")", +- UUID_ARGS(eid), new_commit_index); +- cmd->index = new_commit_index; +- raft_command_complete(raft, cmd, RAFT_CMD_SUCCESS); ++ if (e->servers && raft->role == RAFT_LEADER) { ++ /* raft_run_reconfigure() can write a new Raft entry, which can ++ * reallocate raft->entries, which would invalidate 'e', so ++ * this case must be last, after the one for 'e->data'. */ ++ raft_run_reconfigure(raft); + } + } + +@@ -2960,6 +3093,15 @@ raft_update_leader(struct raft *raft, const struct uuid *sid) }; ignore(ovsdb_log_write_and_free(raft->log, raft_record_to_json(&r))); } @@ -90612,7 +90821,7 @@ index 4789bc4f22..68aea2823b 100644 return true; } -@@ -3176,12 +3300,6 @@ raft_find_peer(struct raft *raft, const struct uuid *uuid) +@@ -3176,12 +3318,6 @@ raft_find_peer(struct raft *raft, const struct uuid *uuid) return s && !uuid_equals(&raft->sid, &s->sid) ? s : NULL; } @@ -90625,7 +90834,7 @@ index 4789bc4f22..68aea2823b 100644 /* Figure 3.1: "If there exists an N such that N > commitIndex, a * majority of matchIndex[i] >= N, and log[N].term == currentTerm, set * commitIndex = N (sections 3.5 and 3.6)." */ -@@ -3260,7 +3378,20 @@ raft_send_install_snapshot_request(struct raft *raft, +@@ -3260,7 +3396,20 @@ raft_send_install_snapshot_request(struct raft *raft, .election_timer = raft->election_timer, /* use latest value */ } }; @@ -90647,7 +90856,7 @@ index 4789bc4f22..68aea2823b 100644 } static void -@@ -3913,7 +4044,7 @@ raft_handle_install_snapshot_request__( +@@ -3913,7 +4062,7 @@ raft_handle_install_snapshot_request__( struct ovsdb_error *error = raft_save_snapshot(raft, new_log_start, &new_snapshot); if (error) { @@ -90656,7 +90865,7 @@ index 4789bc4f22..68aea2823b 100644 VLOG_WARN("could not save snapshot: %s", error_s); free(error_s); return false; -@@ -3942,6 +4073,10 @@ static void +@@ -3942,6 +4091,10 @@ static void raft_handle_install_snapshot_request( struct raft *raft, const struct raft_install_snapshot_request *rq) { @@ -90667,7 +90876,7 @@ index 4789bc4f22..68aea2823b 100644 if (raft_handle_install_snapshot_request__(raft, rq)) { union raft_rpc rpy = { .install_snapshot_reply = { -@@ -3977,6 +4112,8 @@ raft_handle_install_snapshot_reply( +@@ -3977,6 +4130,8 @@ raft_handle_install_snapshot_reply( } } @@ -90676,7 +90885,7 @@ index 4789bc4f22..68aea2823b 100644 if (rpy->last_index != raft->log_start - 1 || rpy->last_term != raft->snap.term) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); -@@ -3992,8 +4129,9 @@ raft_handle_install_snapshot_reply( +@@ -3992,8 +4147,9 @@ raft_handle_install_snapshot_reply( VLOG_INFO_RL(&rl, "cluster "CID_FMT": installed snapshot on server %s " " up to %"PRIu64":%"PRIu64, CID_ARGS(&raft->cid), s->nickname, rpy->last_term, rpy->last_index); @@ -90688,7 +90897,7 @@ index 4789bc4f22..68aea2823b 100644 } /* Returns true if 'raft' has grown enough since the last snapshot that -@@ -4023,9 +4161,24 @@ raft_may_snapshot(const struct raft *raft) +@@ -4023,9 +4179,24 @@ raft_may_snapshot(const struct raft *raft) && !raft->leaving && !raft->left && !raft->failed @@ -90713,7 +90922,7 @@ index 4789bc4f22..68aea2823b 100644 /* Replaces the log for 'raft', up to the last log entry read, by * 'new_snapshot_data'. Returns NULL if successful, otherwise an error that * the caller must eventually free. -@@ -4143,9 +4296,7 @@ raft_handle_execute_command_request__( +@@ -4143,9 +4314,7 @@ raft_handle_execute_command_request__( cmd->sid = rq->common.sid; enum raft_command_status status = cmd->status; @@ -90724,7 +90933,7 @@ index 4789bc4f22..68aea2823b 100644 return status; } -@@ -4366,6 +4517,8 @@ raft_unixctl_status(struct unixctl_conn *conn, +@@ -4366,6 +4535,8 @@ raft_unixctl_status(struct unixctl_conn *conn, : raft->leaving ? "leaving cluster" : raft->left ? "left cluster" : raft->failed ? "failed" @@ -90733,7 +90942,7 @@ index 4789bc4f22..68aea2823b 100644 : "cluster member"); if (raft->joining) { ds_put_format(&s, "Remotes for joining:"); -@@ -4639,6 +4792,42 @@ raft_unixctl_change_election_timer(struct unixctl_conn *conn, +@@ -4639,6 +4810,42 @@ raft_unixctl_change_election_timer(struct unixctl_conn *conn, unixctl_command_reply(conn, "change of election timer initiated."); } @@ -90776,7 +90985,7 @@ index 4789bc4f22..68aea2823b 100644 static void raft_unixctl_failure_test(struct unixctl_conn *conn OVS_UNUSED, int argc OVS_UNUSED, const char *argv[], -@@ -4659,6 +4848,8 @@ raft_unixctl_failure_test(struct unixctl_conn *conn OVS_UNUSED, +@@ -4659,6 +4866,8 @@ raft_unixctl_failure_test(struct unixctl_conn *conn OVS_UNUSED, failure_test = FT_CRASH_AFTER_SEND_EXEC_REQ; } else if (!strcmp(test, "crash-after-receiving-append-request-update")) { failure_test = FT_CRASH_AFTER_RECV_APPEND_REQ_UPDATE; @@ -90785,16 +90994,21 @@ index 4789bc4f22..68aea2823b 100644 } else if (!strcmp(test, "delay-election")) { failure_test = FT_DELAY_ELECTION; struct raft *raft; -@@ -4667,6 +4858,8 @@ raft_unixctl_failure_test(struct unixctl_conn *conn OVS_UNUSED, +@@ -4667,6 +4876,13 @@ raft_unixctl_failure_test(struct unixctl_conn *conn OVS_UNUSED, raft_reset_election_timer(raft); } } + } else if (!strcmp(test, "dont-send-vote-request")) { + failure_test = FT_DONT_SEND_VOTE_REQUEST; ++ } else if (!strcmp(test, ++ "transfer-leadership-after-sending-append-request")) { ++ failure_test = FT_TRANSFER_LEADERSHIP_AFTER_SEND_APPEND_REQ; ++ } else if (!strcmp(test, "transfer-leadership")) { ++ failure_test = FT_TRANSFER_LEADERSHIP; } else if (!strcmp(test, "clear")) { failure_test = FT_NO_TEST; unixctl_command_reply(conn, "test dismissed"); -@@ -4697,6 +4890,9 @@ raft_init(void) +@@ -4697,6 +4913,9 @@ raft_init(void) raft_unixctl_kick, NULL); unixctl_command_register("cluster/change-election-timer", "DB TIME", 2, 2, raft_unixctl_change_election_timer, NULL); @@ -92757,7 +92971,7 @@ index 8d777a0275..52a15f3dd1 100644 AT_KEYWORDS([ovsdb client positive]) diff --git a/tests/ovsdb-cluster.at b/tests/ovsdb-cluster.at -index 3a0bd4579e..efb0efd7f7 100644 +index 3a0bd4579e..2ed656c745 100644 --- a/tests/ovsdb-cluster.at +++ b/tests/ovsdb-cluster.at @@ -128,7 +128,7 @@ ovsdb_test_cluster_disconnect () { @@ -92955,7 +93169,11 @@ index 3a0bd4579e..efb0efd7f7 100644 OVS_START_SHELL_HELPERS -@@ -289,9 +461,8 @@ ovsdb_cluster_failure_test () { +@@ -286,12 +458,12 @@ ovsdb_cluster_failure_test () { + if test "$crash_node" == "1"; then + new_leader=$5 + fi ++ log_grep=$6 cp $top_srcdir/vswitchd/vswitch.ovsschema schema schema=`ovsdb-tool schema-name schema` @@ -92967,10 +93185,53 @@ index 3a0bd4579e..efb0efd7f7 100644 n=3 join_cluster() { -@@ -436,6 +607,61 @@ AT_KEYWORDS([ovsdb server negative unix cluster pending-txn]) +@@ -307,7 +479,7 @@ ovsdb|WARN|schema: changed 30 columns in 'Open_vSwitch' database from ephemeral + start_server() { + local i=$1 + printf "\ns$i: starting\n" +- AT_CHECK([ovsdb-server -vjsonrpc -vconsole:off -vsyslog:off --detach --no-chdir --log-file=s$i.log --pidfile=s$i.pid --unixctl=s$i --remote=punix:s$i.ovsdb s$i.db]) ++ AT_CHECK([ovsdb-server -vjsonrpc -vraft -vconsole:off -vsyslog:off --detach --no-chdir --log-file=s$i.log --pidfile=s$i.pid --unixctl=s$i --remote=punix:s$i.ovsdb s$i.db]) + } + connect_server() { + local i=$1 +@@ -333,14 +505,23 @@ ovsdb|WARN|schema: changed 30 columns in 'Open_vSwitch' database from ephemeral + fi + AT_CHECK([ovs-appctl -t "`pwd`"/s$delay_election_node cluster/failure-test delay-election], [0], [ignore]) + fi ++ ++ # Initializing the database separately to avoid extra 'wait' operation ++ # in later transactions. ++ AT_CHECK([ovs-vsctl -v --db="$db" --no-leader-only --no-shuffle-remotes --no-wait init], [0], [ignore], [ignore]) ++ + AT_CHECK([ovs-appctl -t "`pwd`"/s$crash_node cluster/failure-test $crash_command], [0], [ignore]) + AT_CHECK([ovs-vsctl -v --db="$db" --no-leader-only --no-shuffle-remotes --no-wait create QoS type=x], [0], [ignore], [ignore]) + +- # Make sure that the node really crashed. +- AT_CHECK([ls s$crash_node.ovsdb], [2], [ignore], [ignore]) +- # XXX: Client will fail if remotes contains unix socket that doesn't exist (killed). +- if test "$remote_1" = "$crash_node"; then +- db=unix:s$remote_2.ovsdb ++ # Make sure that the node really crashed or has specific log message. ++ if test -z "$log_grep"; then ++ AT_CHECK([ls s$crash_node.ovsdb], [2], [ignore], [ignore]) ++ # XXX: Client will fail if remotes contains unix socket that doesn't exist (killed). ++ if test "$remote_1" = "$crash_node"; then ++ db=unix:s$remote_2.ovsdb ++ fi ++ else ++ OVS_WAIT_UNTIL([grep -q "$log_grep" s${crash_node}.log]) + fi + AT_CHECK([ovs-vsctl --db="$db" --no-leader-only --no-wait --columns=type --bare list QoS], [0], [x + ]) +@@ -436,6 +617,66 @@ AT_KEYWORDS([ovsdb server negative unix cluster pending-txn]) ovsdb_cluster_failure_test 2 2 3 crash-after-receiving-append-request-update AT_CLEANUP ++AT_SETUP([OVSDB cluster - txn on leader, leader transfers leadership after sending appendReq]) ++AT_KEYWORDS([ovsdb server negative unix cluster pending-txn transfer]) ++ovsdb_cluster_failure_test 1 2 1 transfer-leadership-after-sending-append-request -1 "Transferring leadership" ++AT_CLEANUP ++ + +AT_SETUP([OVSDB cluster - competing candidates]) +AT_KEYWORDS([ovsdb server negative unix cluster competing-candidates]) @@ -93029,7 +93290,7 @@ index 3a0bd4579e..efb0efd7f7 100644 AT_BANNER([OVSDB - cluster tests]) -@@ -447,9 +673,8 @@ ovsdb_torture_test () { +@@ -447,9 +688,8 @@ ovsdb_torture_test () { local variant=$3 # 'kill' and restart or 'remove' and add cp $top_srcdir/vswitchd/vswitch.ovsschema schema schema=`ovsdb-tool schema-name schema` @@ -93041,7 +93302,7 @@ index 3a0bd4579e..efb0efd7f7 100644 join_cluster() { local i=$1 -@@ -529,7 +754,7 @@ ovsdb|WARN|schema: changed 30 columns in 'Open_vSwitch' database from ephemeral +@@ -529,7 +769,7 @@ ovsdb|WARN|schema: changed 30 columns in 'Open_vSwitch' database from ephemeral # Use file instead of var because code inside "while" runs in a subshell. echo 0 > phase i=0 diff --git a/SPECS/openvswitch2.13.spec b/SPECS/openvswitch2.13.spec index 800f795..4e0c5c3 100644 --- a/SPECS/openvswitch2.13.spec +++ b/SPECS/openvswitch2.13.spec @@ -59,7 +59,7 @@ Summary: Open vSwitch Group: System Environment/Daemons daemon/database/utilities URL: http://www.openvswitch.org/ Version: 2.13.0 -Release: 183%{?commit0:.%{date}git%{shortcommit0}}%{?commit1:dpdk%{shortcommit1}}%{?dist} +Release: 184%{?commit0:.%{date}git%{shortcommit0}}%{?commit1:dpdk%{shortcommit1}}%{?dist} # Nearly all of openvswitch is ASL 2.0. The bugtool is LGPLv2+, and the # lib/sflow*.[ch] files are SISSL @@ -715,6 +715,15 @@ exit 0 %endif %changelog +* Thu May 26 2022 Open vSwitch CI - 2.13.0-184 +- Merging upstream branch-2.13 [RH git: 9d3ca376af] + Commit list: + 91d3fc87ac classifier: Make find_match_wc() prototype and definition match. + 78a5ad8051 ovsdb: raft: Fix transaction double commit due to lost leadership. (#2046340) + d0171d3b47 Revert "odp-util: Always report ODP_FIT_TOO_LITTLE for IGMP." + 5ae081baeb ofproto-dpif: Trigger revalidation if ct tp changes. + + * Wed May 25 2022 Open vSwitch CI - 2.13.0-183 - Merging upstream branch-2.13 [RH git: 89f8ffb9c2] Commit list: