From e5b56f361b2c14f469150632cb2a2ab8f2596704 Mon Sep 17 00:00:00 2001 From: Open vSwitch CI Date: Jul 17 2021 13:19:20 +0000 Subject: Import openvswitch2.13-2.13.0-117 from Fast DataPath --- diff --git a/SOURCES/openvswitch-2.13.0.patch b/SOURCES/openvswitch-2.13.0.patch index 390e82a..7afd1d8 100644 --- a/SOURCES/openvswitch-2.13.0.patch +++ b/SOURCES/openvswitch-2.13.0.patch @@ -987,12 +987,19 @@ index b279303d18..b3b56cd50e 100644 boot.sh \ poc/builders/Vagrantfile \ diff --git a/NEWS b/NEWS -index dab94e924d..733c785f06 100644 +index dab94e924d..0ae1076ee1 100644 --- a/NEWS +++ b/NEWS -@@ -1,3 +1,49 @@ -+v2.13.4 - xx xxx xxxx +@@ -1,3 +1,56 @@ ++v2.13.5 - xx xxx xxxx +--------------------- ++ - OVS now reports the datapath capability 'ct_zero_snat', which reflects ++ whether the SNAT with all-zero IP address is supported. ++ See ovs-vswitchd.conf.db(5) for details. ++ ++v2.13.4 - 01 Jul 2021 ++--------------------- ++ - Bug fixes + - DPDK: + * OVS validated with DPDK 19.11.8. It is recommended to use this version + until further releases. @@ -1040,7 +1047,7 @@ index dab94e924d..733c785f06 100644 v2.13.0 - 14 Feb 2020 --------------------- - OVN: -@@ -43,6 +89,9 @@ v2.13.0 - 14 Feb 2020 +@@ -43,6 +96,9 @@ v2.13.0 - 14 Feb 2020 - 'ovs-appctl dpctl/dump-flows' can now show offloaded=partial for partially offloaded flows, dp:dpdk for fully offloaded by dpdk, and type filter supports new filters: "dpdk" and "partially-offloaded". @@ -1050,7 +1057,7 @@ index dab94e924d..733c785f06 100644 v2.12.0 - 03 Sep 2019 --------------------- -@@ -117,9 +166,6 @@ v2.12.0 - 03 Sep 2019 +@@ -117,9 +173,6 @@ v2.12.0 - 03 Sep 2019 * Add support for conntrack zone-based timeout policy. - 'ovs-dpctl dump-flows' is no longer suitable for dumping offloaded flows. 'ovs-appctl dpctl/dump-flows' should be used instead. @@ -1201,7 +1208,7 @@ index f6b88ca2d0..9429702db9 100755 manpages=`cd $distdir && echo *` diff --git a/configure.ac b/configure.ac -index 92b52f6712..34276bcbe7 100644 +index 92b52f6712..0dc2a7dbca 100644 --- a/configure.ac +++ b/configure.ac @@ -13,7 +13,7 @@ @@ -1209,7 +1216,7 @@ index 92b52f6712..34276bcbe7 100644 AC_PREREQ(2.63) -AC_INIT(openvswitch, 2.13.0, bugs@openvswitch.org) -+AC_INIT(openvswitch, 2.13.4, bugs@openvswitch.org) ++AC_INIT(openvswitch, 2.13.5, bugs@openvswitch.org) AC_CONFIG_SRCDIR([datapath/datapath.c]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) @@ -1480,6 +1487,50 @@ index bc6580d708..b0932186af 100644 } CT_UPDATE_RES; /* Metadata mark for masked write to conntrack mark */ +diff --git a/datapath-windows/ovsext/ovsext.vcxproj b/datapath-windows/ovsext/ovsext.vcxproj +index d50a126b43..18f884f41b 100644 +--- a/datapath-windows/ovsext/ovsext.vcxproj ++++ b/datapath-windows/ovsext/ovsext.vcxproj +@@ -192,22 +192,39 @@ + + + true ++ $(CRT_IncludePath);$(KM_IncludePath); + + + true ++ $(CRT_IncludePath);$(KM_IncludePath); + + + true + ..\misc\DriverRecommendedRules.ruleset + true ++ $(CRT_IncludePath);$(KM_IncludePath); + + + true + ..\misc\DriverRecommendedRules.ruleset ++ $(CRT_IncludePath);$(KM_IncludePath); + + + true + ..\misc\DriverRecommendedRules.ruleset ++ $(CRT_IncludePath);$(KM_IncludePath); ++ ++ ++ $(CRT_IncludePath);$(KM_IncludePath); ++ ++ ++ $(CRT_IncludePath);$(KM_IncludePath); ++ ++ ++ $(CRT_IncludePath);$(KM_IncludePath); ++ ++ ++ $(CRT_IncludePath);$(KM_IncludePath); + + + diff --git a/datapath/conntrack.c b/datapath/conntrack.c index 838cf63c90..67e0628703 100644 --- a/datapath/conntrack.c @@ -1687,15 +1738,21 @@ index 23118e8b63..05ccfb9288 100644 *saddr = fl6.saddr; if (use_cache) diff --git a/debian/changelog b/debian/changelog -index 8e075bc98b..f63d5cc46a 100644 +index 8e075bc98b..05025442a6 100644 --- a/debian/changelog +++ b/debian/changelog -@@ -1,3 +1,27 @@ +@@ -1,3 +1,33 @@ ++openvswitch (2.13.5-1) unstable; urgency=low ++ [ Open vSwitch team ] ++ * New upstream version ++ ++ -- Open vSwitch team Thu, 01 Jul 2021 20:17:41 +0200 ++ +openvswitch (2.13.4-1) unstable; urgency=low + [ Open vSwitch team ] + * New upstream version + -+ -- Open vSwitch team Wed, 10 Feb 2021 16:07:28 +0100 ++ -- Open vSwitch team Thu, 01 Jul 2021 20:17:41 +0200 + +openvswitch (2.13.3-1) unstable; urgency=low + [ Open vSwitch team ] @@ -80434,10 +80491,18 @@ index 416cb769d2..47261c7551 100644 } diff --git a/lib/conntrack.c b/lib/conntrack.c -index ff5a89457c..a673678fe5 100644 +index ff5a89457c..4a26f370c3 100644 --- a/lib/conntrack.c +++ b/lib/conntrack.c -@@ -143,12 +143,7 @@ detect_ftp_ctl_type(const struct conn_lookup_ctx *ctx, +@@ -44,6 +44,7 @@ VLOG_DEFINE_THIS_MODULE(conntrack); + + COVERAGE_DEFINE(conntrack_full); + COVERAGE_DEFINE(conntrack_long_cleanup); ++COVERAGE_DEFINE(conntrack_lookup_natted_miss); + + struct conn_lookup_ctx { + struct conn_key key; +@@ -143,12 +144,7 @@ detect_ftp_ctl_type(const struct conn_lookup_ctx *ctx, static void expectation_clean(struct conntrack *ct, const struct conn_key *master_key); @@ -80451,7 +80516,7 @@ index ff5a89457c..a673678fe5 100644 static void handle_ftp_ctl(struct conntrack *ct, const struct conn_lookup_ctx *ctx, -@@ -296,6 +291,7 @@ ct_print_conn_info(const struct conn *c, const char *log_msg, +@@ -296,6 +292,7 @@ ct_print_conn_info(const struct conn *c, const char *log_msg, struct conntrack * conntrack_init(void) { @@ -80459,7 +80524,7 @@ index ff5a89457c..a673678fe5 100644 struct conntrack *ct = xzalloc(sizeof *ct); ovs_rwlock_init(&ct->resources_lock); -@@ -322,6 +318,18 @@ conntrack_init(void) +@@ -322,6 +319,18 @@ conntrack_init(void) ct->clean_thread = ovs_thread_create("ct_clean", clean_thread_main, ct); ct->ipf = ipf_init(); @@ -80478,7 +80543,7 @@ index ff5a89457c..a673678fe5 100644 return ct; } -@@ -813,7 +821,7 @@ static void +@@ -813,7 +822,7 @@ static void reverse_nat_packet(struct dp_packet *pkt, const struct conn *conn) { char *tail = dp_packet_tail(pkt); @@ -80487,7 +80552,42 @@ index ff5a89457c..a673678fe5 100644 struct conn_key inner_key; const char *inner_l4 = NULL; uint16_t orig_l3_ofs = pkt->l3_ofs; -@@ -1277,6 +1285,11 @@ process_one(struct conntrack *ct, struct dp_packet *pkt, +@@ -1269,6 +1278,34 @@ process_one_fast(uint16_t zone, const uint32_t *setmark, + } + } + ++static void ++initial_conn_lookup(struct conntrack *ct, struct conn_lookup_ctx *ctx, ++ long long now, bool natted) ++{ ++ if (natted) { ++ /* If the packet has been already natted (e.g. a previous ++ * action took place), retrieve it performing a lookup of its ++ * reverse key. */ ++ conn_key_reverse(&ctx->key); ++ } ++ ++ conn_key_lookup(ct, &ctx->key, ctx->hash, now, &ctx->conn, &ctx->reply); ++ ++ if (natted) { ++ if (OVS_LIKELY(ctx->conn)) { ++ ctx->reply = !ctx->reply; ++ ctx->key = ctx->reply ? ctx->conn->rev_key : ctx->conn->key; ++ ctx->hash = conn_key_hash(&ctx->key, ct->hash_basis); ++ } else { ++ /* A lookup failure does not necessarily imply that an ++ * error occurred, it may simply indicate that a conn got ++ * removed during the recirculation. */ ++ COVERAGE_INC(conntrack_lookup_natted_miss); ++ conn_key_reverse(&ctx->key); ++ } ++ } ++} ++ + static void + process_one(struct conntrack *ct, struct dp_packet *pkt, + struct conn_lookup_ctx *ctx, uint16_t zone, +@@ -1277,8 +1314,14 @@ process_one(struct conntrack *ct, struct dp_packet *pkt, const struct nat_action_info_t *nat_action_info, ovs_be16 tp_src, ovs_be16 tp_dst, const char *helper) { @@ -80497,9 +80597,13 @@ index ff5a89457c..a673678fe5 100644 + } + bool create_new_conn = false; - conn_key_lookup(ct, &ctx->key, ctx->hash, now, &ctx->conn, &ctx->reply); +- conn_key_lookup(ct, &ctx->key, ctx->hash, now, &ctx->conn, &ctx->reply); ++ initial_conn_lookup(ct, ctx, now, !!(pkt->md.ct_state & ++ (CS_SRC_NAT | CS_DST_NAT))); struct conn *conn = ctx->conn; -@@ -1300,9 +1313,10 @@ process_one(struct conntrack *ct, struct dp_packet *pkt, + + /* Delete found entry if in wrong direction. 'force' implies commit. */ +@@ -1300,9 +1343,10 @@ process_one(struct conntrack *ct, struct dp_packet *pkt, conn_key_lookup(ct, &ctx->key, hash, now, &conn, &ctx->reply); if (!conn) { @@ -80512,7 +80616,7 @@ index ff5a89457c..a673678fe5 100644 free(log_msg); return; } -@@ -1964,9 +1978,10 @@ extract_l4(struct conn_key *key, const void *data, size_t size, bool *related, +@@ -1964,9 +2008,10 @@ extract_l4(struct conn_key *key, const void *data, size_t size, bool *related, return (!related || check_l4_icmp6(key, data, size, l3, validate_checksum)) && extract_l4_icmp6(key, data, size, related); @@ -80525,7 +80629,7 @@ index ff5a89457c..a673678fe5 100644 } static bool -@@ -2249,8 +2264,8 @@ nat_select_range_tuple(struct conntrack *ct, const struct conn *conn, +@@ -2249,8 +2294,8 @@ nat_select_range_tuple(struct conntrack *ct, const struct conn *conn, conn->nat_info->nat_action & NAT_ACTION_SRC_PORT ? true : false; union ct_addr first_addr = ct_addr; @@ -80536,8 +80640,47 @@ index ff5a89457c..a673678fe5 100644 while (true) { if (conn->nat_info->nat_action & NAT_ACTION_SRC) { +diff --git a/lib/ct-dpif.c b/lib/ct-dpif.c +index 8c2480e7ac..880352376e 100644 +--- a/lib/ct-dpif.c ++++ b/lib/ct-dpif.c +@@ -889,3 +889,11 @@ ct_dpif_get_timeout_policy_name(struct dpif *dpif, uint32_t tp_id, + dpif, tp_id, dl_type, nw_proto, tp_name, is_generic) + : EOPNOTSUPP); + } ++ ++int ++ct_dpif_get_features(struct dpif *dpif, enum ct_features *features) ++{ ++ return (dpif->dpif_class->ct_get_features ++ ? dpif->dpif_class->ct_get_features(dpif, features) ++ : EOPNOTSUPP); ++} +diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h +index 3e227d9e3b..ebd9ac9be5 100644 +--- a/lib/ct-dpif.h ++++ b/lib/ct-dpif.h +@@ -269,6 +269,11 @@ struct ct_dpif_timeout_policy { + * timeout attribute values */ + }; + ++/* Conntrack Features. */ ++enum ct_features { ++ CONNTRACK_F_ZERO_SNAT = 1 << 0, /* All-zero SNAT support. */ ++}; ++ + int ct_dpif_dump_start(struct dpif *, struct ct_dpif_dump_state **, + const uint16_t *zone, int *); + int ct_dpif_dump_next(struct ct_dpif_dump_state *, struct ct_dpif_entry *); +@@ -323,5 +328,6 @@ int ct_dpif_timeout_policy_dump_done(struct dpif *dpif, void *state); + int ct_dpif_get_timeout_policy_name(struct dpif *dpif, uint32_t tp_id, + uint16_t dl_type, uint8_t nw_proto, + char **tp_name, bool *is_generic); ++int ct_dpif_get_features(struct dpif *dpif, enum ct_features *features); + + #endif /* CT_DPIF_H */ diff --git a/lib/dp-packet.h b/lib/dp-packet.h -index 9f8991faad..45655af461 100644 +index 9f8991faad..dc8b773fe1 100644 --- a/lib/dp-packet.h +++ b/lib/dp-packet.h @@ -81,7 +81,7 @@ struct dp_packet { @@ -80577,6 +80720,22 @@ index 9f8991faad..45655af461 100644 { ovs_assert(pad_size <= dp_packet_size(b)); b->l2_pad_size = pad_size; +@@ -950,7 +950,6 @@ enum { NETDEV_MAX_BURST = 32 }; /* Maximum number packets in a batch. */ + struct dp_packet_batch { + size_t count; + bool trunc; /* true if the batch needs truncate. */ +- bool do_not_steal; /* Indicate that the packets should not be stolen. */ + struct dp_packet *packets[NETDEV_MAX_BURST]; + }; + +@@ -959,7 +958,6 @@ dp_packet_batch_init(struct dp_packet_batch *batch) + { + batch->count = 0; + batch->trunc = false; +- batch->do_not_steal = false; + } + + static inline void diff --git a/lib/dpctl.c b/lib/dpctl.c index db2b1f8961..36038a13d8 100644 --- a/lib/dpctl.c @@ -80624,7 +80783,7 @@ index 68c33a0f96..9b251f81fa 100644 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c -index d393aab5e3..df3c2c9c3e 100644 +index d393aab5e3..8b04f779e4 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -83,9 +83,9 @@ @@ -80858,7 +81017,15 @@ index d393aab5e3..df3c2c9c3e 100644 if (put->ufid) { ufid = *put->ufid; } else { -@@ -3875,11 +3980,12 @@ dpif_netdev_operate(struct dpif *dpif, struct dpif_op **ops, size_t n_ops, +@@ -3831,7 +3936,6 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute) + } + + dp_packet_batch_init_packet(&pp, execute->packet); +- pp.do_not_steal = true; + dp_netdev_execute_actions(pmd, &pp, false, execute->flow, + execute->actions, execute->actions_len); + dp_netdev_pmd_flush_output_packets(pmd, true); +@@ -3875,11 +3979,12 @@ dpif_netdev_operate(struct dpif *dpif, struct dpif_op **ops, size_t n_ops, /* Enable or Disable PMD auto load balancing. */ static void @@ -80872,7 +81039,7 @@ index d393aab5e3..df3c2c9c3e 100644 bool enable_alb = false; bool multi_rxq = false; -@@ -3906,18 +4012,24 @@ set_pmd_auto_lb(struct dp_netdev *dp) +@@ -3906,18 +4011,24 @@ set_pmd_auto_lb(struct dp_netdev *dp) enable_alb = enable_alb && pmd_rxq_assign_cyc && pmd_alb->auto_lb_requested; @@ -80901,7 +81068,7 @@ index d393aab5e3..df3c2c9c3e 100644 } /* Applies datapath configuration from the database. Some of the changes are -@@ -3935,6 +4047,9 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config) +@@ -3935,6 +4046,9 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config) uint32_t insert_min, cur_min; uint32_t tx_flush_interval, cur_tx_flush_interval; uint64_t rebalance_intvl; @@ -80911,7 +81078,7 @@ index d393aab5e3..df3c2c9c3e 100644 tx_flush_interval = smap_get_int(other_config, "tx-flush-interval", DEFAULT_TX_FLUSH_INTERVAL); -@@ -4012,7 +4127,7 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config) +@@ -4012,7 +4126,7 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config) false); rebalance_intvl = smap_get_int(other_config, "pmd-auto-lb-rebal-interval", @@ -80920,7 +81087,7 @@ index d393aab5e3..df3c2c9c3e 100644 /* Input is in min, convert it to msec. */ rebalance_intvl = -@@ -4020,9 +4135,38 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config) +@@ -4020,9 +4134,38 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config) if (pmd_alb->rebalance_intvl != rebalance_intvl) { pmd_alb->rebalance_intvl = rebalance_intvl; @@ -80962,7 +81129,7 @@ index d393aab5e3..df3c2c9c3e 100644 return 0; } -@@ -4493,6 +4637,12 @@ struct rr_numa { +@@ -4493,6 +4636,12 @@ struct rr_numa { bool idx_inc; }; @@ -80975,7 +81142,7 @@ index d393aab5e3..df3c2c9c3e 100644 static struct rr_numa * rr_numa_list_lookup(struct rr_numa_list *rr, int numa_id) { -@@ -4940,9 +5090,17 @@ reconfigure_datapath(struct dp_netdev *dp) +@@ -4940,9 +5089,17 @@ reconfigure_datapath(struct dp_netdev *dp) /* Check for all the ports that need reconfiguration. We cache this in * 'port->need_reconfigure', because netdev_is_reconf_required() can @@ -80995,7 +81162,7 @@ index d393aab5e3..df3c2c9c3e 100644 port->need_reconfigure = true; } } -@@ -5076,7 +5234,7 @@ reconfigure_datapath(struct dp_netdev *dp) +@@ -5076,7 +5233,7 @@ reconfigure_datapath(struct dp_netdev *dp) reload_affected_pmds(dp); /* Check if PMD Auto LB is to be enabled */ @@ -81004,7 +81171,7 @@ index d393aab5e3..df3c2c9c3e 100644 } /* Returns true if one of the netdevs in 'dp' requires a reconfiguration */ -@@ -5189,10 +5347,17 @@ get_dry_run_variance(struct dp_netdev *dp, uint32_t *core_list, +@@ -5189,10 +5346,17 @@ get_dry_run_variance(struct dp_netdev *dp, uint32_t *core_list, for (int i = 0; i < n_rxqs; i++) { int numa_id = netdev_get_numa_id(rxqs[i]->port->netdev); numa = rr_numa_list_lookup(&rr, numa_id); @@ -81025,7 +81192,7 @@ index d393aab5e3..df3c2c9c3e 100644 goto cleanup; } -@@ -5320,7 +5485,7 @@ pmd_rebalance_dry_run(struct dp_netdev *dp) +@@ -5320,7 +5484,7 @@ pmd_rebalance_dry_run(struct dp_netdev *dp) improvement = ((curr_variance - new_variance) * 100) / curr_variance; } @@ -81034,7 +81201,7 @@ index d393aab5e3..df3c2c9c3e 100644 ret = false; } } -@@ -5787,12 +5952,14 @@ dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_, +@@ -5787,12 +5951,14 @@ dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_, /* Update all bands and find the one hit with the highest rate for each * packet (if any). */ for (int m = 0; m < meter->n_bands; ++m) { @@ -81053,7 +81220,7 @@ index d393aab5e3..df3c2c9c3e 100644 } /* Drain the bucket for all the packets, if possible. */ -@@ -5810,8 +5977,8 @@ dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_, +@@ -5810,8 +5976,8 @@ dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_, * (Only one band will be fired by a packet, and that * can be different for each packet.) */ for (int i = band_exceeded_pkt; i < cnt; i++) { @@ -81064,7 +81231,7 @@ index d393aab5e3..df3c2c9c3e 100644 exceeded_band[i] = m; } } -@@ -5830,8 +5997,8 @@ dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_, +@@ -5830,8 +5996,8 @@ dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_, /* Update the exceeding band for the exceeding packet. * (Only one band will be fired by a packet, and that * can be different for each packet.) */ @@ -81075,7 +81242,7 @@ index d393aab5e3..df3c2c9c3e 100644 exceeded_band[i] = m; } } -@@ -5913,16 +6080,14 @@ dpif_netdev_meter_set(struct dpif *dpif, ofproto_meter_id meter_id, +@@ -5913,16 +6079,14 @@ dpif_netdev_meter_set(struct dpif *dpif, ofproto_meter_id meter_id, config->bands[i].burst_size = config->bands[i].rate; } @@ -81097,6 +81264,14 @@ index d393aab5e3..df3c2c9c3e 100644 if (band_max_delta_t > meter->max_delta_t) { meter->max_delta_t = band_max_delta_t; } +@@ -7800,6 +7964,7 @@ const struct dpif_class dpif_netdev_class = { + NULL, /* ct_timeout_policy_dump_next */ + NULL, /* ct_timeout_policy_dump_done */ + NULL, /* ct_get_timeout_policy_name */ ++ NULL, /* ct_get_features */ + dpif_netdev_ipf_set_enabled, + dpif_netdev_ipf_set_min_frag, + dpif_netdev_ipf_set_max_nfrags, @@ -8040,6 +8205,7 @@ dp_netdev_pmd_try_optimize(struct dp_netdev_pmd_thread *pmd, if (pmd->ctx.now > pmd->rxq_next_cycle_store) { @@ -81117,7 +81292,7 @@ index d393aab5e3..df3c2c9c3e 100644 } else { atomic_count_set(&pmd->pmd_overloaded, 0); diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c -index 5b5c96d727..0b40bb083f 100644 +index 5b5c96d727..2c6c23c645 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -691,6 +691,7 @@ dpif_netlink_set_features(struct dpif *dpif_, uint32_t new_features) @@ -81208,6 +81383,68 @@ index 5b5c96d727..0b40bb083f 100644 nl_msg_put(request, &req_zone_limit, sizeof req_zone_limit); } nl_msg_end_nested(request, opt_offset); +@@ -3140,6 +3150,20 @@ dpif_netlink_ct_get_timeout_policy_name(struct dpif *dpif OVS_UNUSED, + return 0; + } + ++static int ++dpif_netlink_ct_get_features(struct dpif *dpif OVS_UNUSED, ++ enum ct_features *features) ++{ ++ if (features != NULL) { ++#ifndef _WIN32 ++ *features = CONNTRACK_F_ZERO_SNAT; ++#else ++ *features = 0; ++#endif ++ } ++ return 0; ++} ++ + #define CT_DPIF_NL_TP_TCP_MAPPINGS \ + CT_DPIF_NL_TP_MAPPING(TCP, TCP, SYN_SENT, SYN_SENT) \ + CT_DPIF_NL_TP_MAPPING(TCP, TCP, SYN_RECV, SYN_RECV) \ +@@ -3982,6 +4006,7 @@ const struct dpif_class dpif_netlink_class = { + dpif_netlink_ct_timeout_policy_dump_next, + dpif_netlink_ct_timeout_policy_dump_done, + dpif_netlink_ct_get_timeout_policy_name, ++ dpif_netlink_ct_get_features, + NULL, /* ipf_set_enabled */ + NULL, /* ipf_set_min_frag */ + NULL, /* ipf_set_max_nfrags */ +@@ -4638,7 +4663,7 @@ report_loss(struct dpif_netlink *dpif, struct dpif_channel *ch, uint32_t ch_idx, + time_msec() - ch->last_poll); + } + +- VLOG_WARN("%s: lost packet on port channel %u of handler %u", +- dpif_name(&dpif->dpif), ch_idx, handler_id); ++ VLOG_WARN("%s: lost packet on port channel %u of handler %u%s", ++ dpif_name(&dpif->dpif), ch_idx, handler_id, ds_cstr(&s)); + ds_destroy(&s); + } +diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h +index b77317bca1..9941c9ba8a 100644 +--- a/lib/dpif-provider.h ++++ b/lib/dpif-provider.h +@@ -81,6 +81,7 @@ struct ct_dpif_dump_state; + struct ct_dpif_entry; + struct ct_dpif_tuple; + struct ct_dpif_timeout_policy; ++enum ct_features; + + /* 'dpif_ipf_proto_status' and 'dpif_ipf_status' are presently in + * sync with 'ipf_proto_status' and 'ipf_status', but more +@@ -562,6 +563,10 @@ struct dpif_class { + uint16_t dl_type, uint8_t nw_proto, + char **tp_name, bool *is_generic); + ++ /* Stores the conntrack features supported by 'dpif' into features. ++ * The value is a bitmap of CONNTRACK_F_* bits. */ ++ int (*ct_get_features)(struct dpif *, enum ct_features *features); ++ + /* IP Fragmentation. */ + + /* Disables or enables conntrack fragment reassembly. The default diff --git a/lib/dpif.c b/lib/dpif.c index 9d9c716c13..1847689114 100644 --- a/lib/dpif.c @@ -81258,10 +81495,69 @@ index 45bb96b543..353d5cd3ed 100644 } diff --git a/lib/ipf.c b/lib/ipf.c -index 446e89d13c..c20bcc0b33 100644 +index 446e89d13c..9c83f1913a 100644 --- a/lib/ipf.c +++ b/lib/ipf.c -@@ -1153,7 +1153,7 @@ ipf_post_execute_reass_pkts(struct ipf *ipf, +@@ -93,7 +93,6 @@ struct ipf_frag { + struct dp_packet *pkt; + uint16_t start_data_byte; + uint16_t end_data_byte; +- bool dnsteal; /* 'do not steal': if true, ipf should not free packet. */ + }; + + /* The key for a collection of fragments potentially making up an unfragmented +@@ -795,8 +794,7 @@ ipf_is_frag_duped(const struct ipf_frag *frag_list, int last_inuse_idx, + static bool + ipf_process_frag(struct ipf *ipf, struct ipf_list *ipf_list, + struct dp_packet *pkt, uint16_t start_data_byte, +- uint16_t end_data_byte, bool ff, bool lf, bool v6, +- bool dnsteal) ++ uint16_t end_data_byte, bool ff, bool lf, bool v6) + OVS_REQUIRES(ipf->ipf_lock) + { + bool duped_frag = ipf_is_frag_duped(ipf_list->frag_list, +@@ -811,10 +809,9 @@ ipf_process_frag(struct ipf *ipf, struct ipf_list *ipf_list, + * recommend not setting the mempool number of buffers too low + * and also clamp the number of fragments. */ + struct ipf_frag *frag = &ipf_list->frag_list[last_inuse_idx + 1]; +- frag->pkt = pkt; ++ frag->pkt = dp_packet_clone(pkt); + frag->start_data_byte = start_data_byte; + frag->end_data_byte = end_data_byte; +- frag->dnsteal = dnsteal; + ipf_list->last_inuse_idx++; + atomic_count_inc(&ipf->nfrag); + ipf_count(ipf, v6, IPF_NFRAGS_ACCEPTED); +@@ -851,8 +848,7 @@ ipf_list_init(struct ipf_list *ipf_list, struct ipf_list_key *key, + * to a list of fragemnts. */ + static bool + ipf_handle_frag(struct ipf *ipf, struct dp_packet *pkt, ovs_be16 dl_type, +- uint16_t zone, long long now, uint32_t hash_basis, +- bool dnsteal) ++ uint16_t zone, long long now, uint32_t hash_basis) + OVS_REQUIRES(ipf->ipf_lock) + { + struct ipf_list_key key; +@@ -921,7 +917,7 @@ ipf_handle_frag(struct ipf *ipf, struct dp_packet *pkt, ovs_be16 dl_type, + } + + return ipf_process_frag(ipf, ipf_list, pkt, start_data_byte, +- end_data_byte, ff, lf, v6, dnsteal); ++ end_data_byte, ff, lf, v6); + } + + /* Filters out fragments from a batch of fragments and adjust the batch. */ +@@ -942,8 +938,7 @@ ipf_extract_frags_from_batch(struct ipf *ipf, struct dp_packet_batch *pb, + ipf_is_valid_v6_frag(ipf, pkt)))) { + + ovs_mutex_lock(&ipf->ipf_lock); +- if (!ipf_handle_frag(ipf, pkt, dl_type, zone, now, hash_basis, +- pb->do_not_steal)) { ++ if (!ipf_handle_frag(ipf, pkt, dl_type, zone, now, hash_basis)) { + dp_packet_batch_refill(pb, pkt, pb_idx); + } + ovs_mutex_unlock(&ipf->ipf_lock); +@@ -1153,7 +1148,7 @@ ipf_post_execute_reass_pkts(struct ipf *ipf, /* Inner batch loop is constant time since batch size is <= * NETDEV_MAX_BURST. */ DP_PACKET_BATCH_REFILL_FOR_EACH (pb_idx, pb_cnt, pkt, pb) { @@ -81270,7 +81566,7 @@ index 446e89d13c..c20bcc0b33 100644 for (int i = 0; i <= rp->list->last_inuse_idx; i++) { rp->list->frag_list[i].pkt->md.ct_label = pkt->md.ct_label; rp->list->frag_list[i].pkt->md.ct_mark = pkt->md.ct_mark; -@@ -1206,6 +1206,7 @@ ipf_post_execute_reass_pkts(struct ipf *ipf, +@@ -1206,6 +1201,7 @@ ipf_post_execute_reass_pkts(struct ipf *ipf, ipf_reassembled_list_remove(rp); dp_packet_delete(rp->pkt); free(rp); @@ -81278,6 +81574,17 @@ index 446e89d13c..c20bcc0b33 100644 } else { dp_packet_batch_refill(pb, pkt, pb_idx); } +@@ -1337,9 +1333,7 @@ ipf_destroy(struct ipf *ipf) + while (ipf_list->last_sent_idx < ipf_list->last_inuse_idx) { + struct dp_packet *pkt + = ipf_list->frag_list[ipf_list->last_sent_idx + 1].pkt; +- if (!ipf_list->frag_list[ipf_list->last_sent_idx + 1].dnsteal) { +- dp_packet_delete(pkt); +- } ++ dp_packet_delete(pkt); + atomic_count_dec(&ipf->nfrag); + ipf_list->last_sent_idx++; + } diff --git a/lib/jsonrpc.c b/lib/jsonrpc.c index ed748dbde7..e74771e2bc 100644 --- a/lib/jsonrpc.c @@ -81895,7 +82202,7 @@ index 6187129c00..f080dec61f 100644 err = rte_vhost_driver_start(dev->vhost_id); diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c -index c6f3d27409..5a747f73ca 100644 +index c6f3d27409..557c3f5e94 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -231,6 +231,14 @@ struct rtnl_link_stats64 { @@ -81994,7 +82301,39 @@ index c6f3d27409..5a747f73ca 100644 } do { -@@ -2562,7 +2573,7 @@ exit: +@@ -1266,14 +1277,28 @@ netdev_linux_batch_rxq_recv_sock(struct netdev_rxq_linux *rx, int mtu, + for (i = 0; i < retval; i++) { + struct dp_packet *pkt; + +- if (mmsgs[i].msg_len < ETH_HEADER_LEN) { ++ if (mmsgs[i].msg_hdr.msg_flags & MSG_TRUNC ++ || mmsgs[i].msg_len < ETH_HEADER_LEN) { + struct netdev *netdev_ = netdev_rxq_get_netdev(&rx->up); + struct netdev_linux *netdev = netdev_linux_cast(netdev_); + ++ /* The rx->aux_bufs[i] will be re-used next time. */ + dp_packet_delete(buffers[i]); + netdev->rx_dropped += 1; +- VLOG_WARN_RL(&rl, "%s: Dropped packet: less than ether hdr size", +- netdev_get_name(netdev_)); ++ if (mmsgs[i].msg_hdr.msg_flags & MSG_TRUNC) { ++ /* Data is truncated, so the packet is corrupted, and needs ++ * to be dropped. This can happen if TSO/GRO is enabled in ++ * the kernel, but not in userspace, i.e. there is no dp ++ * buffer to store the full packet. */ ++ VLOG_WARN_RL(&rl, ++ "%s: Dropped packet: Too big. GRO/TSO enabled?", ++ netdev_get_name(netdev_)); ++ } else { ++ VLOG_WARN_RL(&rl, ++ "%s: Dropped packet: less than ether hdr size", ++ netdev_get_name(netdev_)); ++ } ++ + continue; + } + +@@ -2562,7 +2587,7 @@ exit: static struct tc_police tc_matchall_fill_police(uint32_t kbits_rate, uint32_t kbits_burst) { @@ -82147,7 +82486,7 @@ index f8c46bbaad..b42d314b65 100644 static int diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c -index 550e440b3a..2507f7d8bd 100644 +index 550e440b3a..89d3324e60 100644 --- a/lib/netdev-offload-tc.c +++ b/lib/netdev-offload-tc.c @@ -48,6 +48,7 @@ static struct hmap ufid_to_tc = HMAP_INITIALIZER(&ufid_to_tc); @@ -82169,7 +82508,17 @@ index 550e440b3a..2507f7d8bd 100644 return err; } -@@ -1352,6 +1355,66 @@ flower_match_to_tun_opt(struct tc_flower *flower, const struct flow_tnl *tnl, +@@ -757,8 +760,7 @@ parse_tc_flower_to_match(struct tc_flower *flower, + action->encap.tp_dst); + } + if (!action->encap.no_csum) { +- nl_msg_put_u8(buf, OVS_TUNNEL_KEY_ATTR_CSUM, +- !action->encap.no_csum); ++ nl_msg_put_flag(buf, OVS_TUNNEL_KEY_ATTR_CSUM); + } + + parse_tc_flower_geneve_opts(action, buf); +@@ -1352,6 +1354,66 @@ flower_match_to_tun_opt(struct tc_flower *flower, const struct flow_tnl *tnl, flower->mask.tunnel.metadata.present.len = tnl->metadata.present.len; } @@ -82236,7 +82585,7 @@ index 550e440b3a..2507f7d8bd 100644 static int netdev_tc_flow_put(struct netdev *netdev, struct match *match, struct nlattr *actions, size_t actions_len, -@@ -1572,53 +1635,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, +@@ -1572,53 +1634,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, } } @@ -82291,7 +82640,7 @@ index 550e440b3a..2507f7d8bd 100644 /* ignore exact match on skb_mark of 0. */ if (mask->pkt_mark == UINT32_MAX && !key->pkt_mark) { -@@ -1699,6 +1716,10 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, +@@ -1699,6 +1715,10 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, const struct nlattr *ct = nl_attr_get(nla); const size_t ct_len = nl_attr_get_size(nla); @@ -82302,7 +82651,7 @@ index 550e440b3a..2507f7d8bd 100644 err = parse_put_flow_ct_action(&flower, action, ct, ct_len); if (err) { return err; -@@ -1727,7 +1748,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, +@@ -1727,7 +1747,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, if (get_ufid_tc_mapping(ufid, &id) == 0) { VLOG_DBG_RL(&rl, "updating old handle: %d prio: %d", id.handle, id.prio); @@ -82311,7 +82660,7 @@ index 550e440b3a..2507f7d8bd 100644 } prio = get_prio_for_tc_flower(&flower); -@@ -1837,6 +1858,7 @@ probe_multi_mask_per_prio(int ifindex) +@@ -1837,6 +1857,7 @@ probe_multi_mask_per_prio(int ifindex) memset(&flower, 0, sizeof flower); @@ -82319,7 +82668,7 @@ index 550e440b3a..2507f7d8bd 100644 flower.key.eth_type = htons(ETH_P_IP); flower.mask.eth_type = OVS_BE16_MAX; memset(&flower.key.dst_mac, 0x11, sizeof flower.key.dst_mac); -@@ -1868,6 +1890,96 @@ out: +@@ -1868,6 +1889,96 @@ out: tc_add_del_qdisc(ifindex, false, block_id, TC_INGRESS); } @@ -82416,7 +82765,7 @@ index 550e440b3a..2507f7d8bd 100644 static void probe_tc_block_support(int ifindex) { -@@ -1884,6 +1996,7 @@ probe_tc_block_support(int ifindex) +@@ -1884,6 +1995,7 @@ probe_tc_block_support(int ifindex) memset(&flower, 0, sizeof flower); @@ -82424,7 +82773,7 @@ index 550e440b3a..2507f7d8bd 100644 flower.key.eth_type = htons(ETH_P_IP); flower.mask.eth_type = OVS_BE16_MAX; memset(&flower.key.dst_mac, 0x11, sizeof flower.key.dst_mac); -@@ -1907,6 +2020,7 @@ netdev_tc_init_flow_api(struct netdev *netdev) +@@ -1907,6 +2019,7 @@ netdev_tc_init_flow_api(struct netdev *netdev) static struct ovsthread_once block_once = OVSTHREAD_ONCE_INITIALIZER; enum tc_qdisc_hook hook = get_tc_qdisc_hook(netdev); uint32_t block_id = 0; @@ -82432,7 +82781,7 @@ index 550e440b3a..2507f7d8bd 100644 int ifindex; int error; -@@ -1917,20 +2031,30 @@ netdev_tc_init_flow_api(struct netdev *netdev) +@@ -1917,20 +2030,30 @@ netdev_tc_init_flow_api(struct netdev *netdev) return -ifindex; } @@ -83172,6 +83521,36 @@ index b675e802c3..cc33feda4a 100644 ofputil_group_to_string(group_id, name, sizeof name); ds_put_cstr(s, name); +diff --git a/lib/ovs-actions.xml b/lib/ovs-actions.xml +index ab8e08b84d..8f8c9041ac 100644 +--- a/lib/ovs-actions.xml ++++ b/lib/ovs-actions.xml +@@ -1649,7 +1649,7 @@ for i in [1,n_slaves]: + + +

The ct action

+- ct(argument]...) ++ ct([argument]...) + ct(commit[, argument]...) + +

+@@ -1816,6 +1816,16 @@ for i in [1,n_slaves]: + connection, will behave the same as a bare nat. +

+ ++

++ For SNAT, there is a special case when the src IP ++ address is configured as all 0's, i.e., ++ nat(src=0.0.0.0). In this case, when a source port ++ collision is detected during the commit, the source port will be ++ translated to an ephemeral port. If there is no collision, no SNAT ++ is performed. Note that this is currently only implemented in the ++ Linux kernel datapath. ++

++ +

+ Open vSwitch 2.6 introduced nat. Linux 4.6 was the + earliest upstream kernel that implemented ct support for diff --git a/lib/ovs-rcu.c b/lib/ovs-rcu.c index ebc8120f0f..cde1e925ba 100644 --- a/lib/ovs-rcu.c @@ -84313,6 +84692,19 @@ index d31c0953ed..0dc62bd83f 100644 }; /* assert that if we overflow with a masked write of uint32_t to the last byte +diff --git a/lib/tun-metadata.c b/lib/tun-metadata.c +index f8a0e19524..d177333297 100644 +--- a/lib/tun-metadata.c ++++ b/lib/tun-metadata.c +@@ -811,7 +811,7 @@ tun_metadata_to_geneve_nlattr(const struct flow_tnl *tun, + } else { + tun_metadata_to_geneve_nlattr_mask(key, tun, flow, b); + } +- } else if (flow->metadata.present.len || is_mask) { ++ } else { + nl_msg_put_unspec(b, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS, + tun->metadata.opts.gnv, + flow->metadata.present.len); diff --git a/lib/util.c b/lib/util.c index 830e14516f..25635b27ff 100644 --- a/lib/util.c @@ -84432,10 +84824,10 @@ index 51d656cba9..fd926cbb82 100644 struct rconn_packet_counter *counter = ofconn->monitor_counter; diff --git a/ofproto/ipfix-gen-entities b/ofproto/ipfix-gen-entities -index 0be719967d..d5abe9c2ed 100755 +index 0be719967d..dcecdab212 100755 --- a/ofproto/ipfix-gen-entities +++ b/ofproto/ipfix-gen-entities -@@ -1,6 +1,6 @@ +@@ -1,14 +1,12 @@ -#! /usr/bin/env python +#!/usr/bin/env python3 # @@ -84444,6 +84836,14 @@ index 0be719967d..d5abe9c2ed 100755 # # Copying and distribution of this file, with or without modification, # are permitted in any medium without royalty provided the copyright + # notice and this notice are preserved. This file is offered as-is, + # without warranty of any kind. + +-from __future__ import print_function +- + import getopt + import re + import sys diff --git a/ofproto/ofproto-dpif-rid.h b/ofproto/ofproto-dpif-rid.h index 147ef9c333..97699cb905 100644 --- a/ofproto/ofproto-dpif-rid.h @@ -84626,10 +85026,43 @@ index 4407f9c97a..04a75e12d3 100644 &ctx.xbridge->ofproto->up); } diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c -index d3cb392077..4d1048f70c 100644 +index d3cb392077..12a1d3ca7e 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c -@@ -5375,6 +5375,8 @@ ct_add_timeout_policy_to_dpif(struct dpif *dpif, +@@ -1381,6 +1381,24 @@ check_ct_timeout_policy(struct dpif_backer *backer) + return !error; + } + ++/* Tests whether 'backer''s datapath supports the all-zero SNAT case. */ ++static bool ++dpif_supports_ct_zero_snat(struct dpif_backer *backer) ++{ ++ enum ct_features features; ++ bool supported = false; ++ ++ if (!ct_dpif_get_features(backer->dpif, &features)) { ++ if (features & CONNTRACK_F_ZERO_SNAT) { ++ supported = true; ++ } ++ } ++ VLOG_INFO("%s: Datapath %s ct_zero_snat", ++ dpif_name(backer->dpif), (supported) ? "supports" ++ : "does not support"); ++ return supported; ++} ++ + /* Tests whether 'backer''s datapath supports the + * OVS_ACTION_ATTR_CHECK_PKT_LEN action. */ + static bool +@@ -1580,6 +1598,7 @@ check_support(struct dpif_backer *backer) + backer->rt_support.ct_timeout = check_ct_timeout_policy(backer); + backer->rt_support.explicit_drop_action = + dpif_supports_explicit_drop_action(backer->dpif); ++ backer->rt_support.ct_zero_snat = dpif_supports_ct_zero_snat(backer); + + /* Flow fields. */ + backer->rt_support.odp.ct_state = check_ct_state(backer); +@@ -5375,6 +5394,8 @@ ct_add_timeout_policy_to_dpif(struct dpif *dpif, struct ct_dpif_timeout_policy cdtp; struct simap_node *node; @@ -84638,10 +85071,61 @@ index d3cb392077..4d1048f70c 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 +5584,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"); ++ smap_add(cap, "ct_zero_snat", s.ct_zero_snat ? "true" : "false"); + } + + /* Gets timeout policy name in 'backer' based on 'zone', 'dl_type' and +diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h +index c9d5df34b0..4d1f126910 100644 +--- a/ofproto/ofproto-dpif.h ++++ b/ofproto/ofproto-dpif.h +@@ -202,7 +202,10 @@ struct group_dpif *group_dpif_lookup(struct ofproto_dpif *, + DPIF_SUPPORT_FIELD(bool, ct_timeout, "Conntrack timeout policy") \ + \ + /* True if the datapath supports explicit drop action. */ \ +- DPIF_SUPPORT_FIELD(bool, explicit_drop_action, "Explicit Drop action") ++ DPIF_SUPPORT_FIELD(bool, explicit_drop_action, "Explicit Drop action") \ ++ \ ++ /* True if the datapath supports all-zero IP SNAT. */ \ ++ DPIF_SUPPORT_FIELD(bool, ct_zero_snat, "Conntrack all-zero IP SNAT") + + + /* Stores the various features which the corresponding backer supports. */ diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c -index 08830d8371..8594afad4a 100644 +index 08830d8371..4e9569e4ad 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c +@@ -961,7 +961,7 @@ ofproto_get_datapath_cap(const char *datapath_type, struct smap *dp_cap) + datapath_type = ofproto_normalize_type(datapath_type); + const struct ofproto_class *class = ofproto_class_find__(datapath_type); + +- if (class->get_datapath_cap) { ++ if (class && class->get_datapath_cap) { + class->get_datapath_cap(datapath_type, dp_cap); + } + } +@@ -974,7 +974,7 @@ ofproto_ct_set_zone_timeout_policy(const char *datapath_type, uint16_t zone_id, + datapath_type = ofproto_normalize_type(datapath_type); + const struct ofproto_class *class = ofproto_class_find__(datapath_type); + +- if (class->ct_set_zone_timeout_policy) { ++ if (class && class->ct_set_zone_timeout_policy) { + class->ct_set_zone_timeout_policy(datapath_type, zone_id, + timeout_policy); + } +@@ -986,7 +986,7 @@ ofproto_ct_del_zone_timeout_policy(const char *datapath_type, uint16_t zone_id) + datapath_type = ofproto_normalize_type(datapath_type); + const struct ofproto_class *class = ofproto_class_find__(datapath_type); + +- if (class->ct_del_zone_timeout_policy) { ++ if (class && class->ct_del_zone_timeout_policy) { + class->ct_del_zone_timeout_policy(datapath_type, zone_id); + } + @@ -6077,8 +6077,8 @@ ofproto_rule_send_removed(struct rule *rule) fr.hard_timeout = rule->hard_timeout; ovs_mutex_unlock(&rule->mutex); @@ -84755,10 +85239,17 @@ index 406c293114..10d0c0c134 100755 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in -index c285ee4b3c..e296bb6d4f 100755 +index c285ee4b3c..9bec653421 100755 --- a/ovsdb/ovsdb-idlc.in +++ b/ovsdb/ovsdb-idlc.in -@@ -279,13 +279,21 @@ const struct %(s)s *%(s)s_table_track_get_first(const struct %(s)s_table *); +@@ -1,6 +1,5 @@ + #! @PYTHON3@ + +-from __future__ import print_function + import getopt + import os + import re +@@ -279,13 +278,21 @@ const struct %(s)s *%(s)s_table_track_get_first(const struct %(s)s_table *); (ROW) = %(s)s_track_get_next(ROW)) @@ -84783,7 +85274,7 @@ index c285ee4b3c..e296bb6d4f 100755 static inline bool %(s)s_is_deleted(const struct %(s)s *row) { return %(s)s_row_get_seqno(row, OVSDB_IDL_CHANGE_DELETE) > 0; -@@ -333,6 +341,14 @@ struct %(s)s *%(s)s_cursor_data(struct ovsdb_idl_cursor *); +@@ -333,6 +340,14 @@ struct %(s)s *%(s)s_cursor_data(struct ovsdb_idl_cursor *); void %(s)s_init(struct %(s)s *); void %(s)s_delete(const struct %(s)s *); struct %(s)s *%(s)s_insert(struct ovsdb_idl_txn *); @@ -84826,7 +85317,7 @@ index 338f3bc299..b8bd1c2d57 100644 .so lib/vlog-unixctl.man .so lib/memory-unixctl.man diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c -index b6957d7300..54ed7c4283 100644 +index b6957d7300..2bc0a69066 100644 --- a/ovsdb/ovsdb-server.c +++ b/ovsdb/ovsdb-server.c @@ -76,8 +76,12 @@ static char *ssl_protocols; @@ -84913,7 +85404,36 @@ index b6957d7300..54ed7c4283 100644 if (error) { break; } -@@ -1481,7 +1495,8 @@ ovsdb_server_compact(struct unixctl_conn *conn, int argc, +@@ -637,8 +651,6 @@ add_db(struct server_config *config, struct db *db) + static struct ovsdb_error * OVS_WARN_UNUSED_RESULT + open_db(struct server_config *config, const char *filename) + { +- struct db *db; +- + /* If we know that the file is already open, return a good error message. + * Otherwise, if the file is open, we'll fail later on with a harder to + * interpret file locking error. */ +@@ -653,9 +665,6 @@ open_db(struct server_config *config, const char *filename) + return error; + } + +- db = xzalloc(sizeof *db); +- db->filename = xstrdup(filename); +- + struct ovsdb_schema *schema; + if (ovsdb_storage_is_clustered(storage)) { + schema = NULL; +@@ -668,6 +677,9 @@ open_db(struct server_config *config, const char *filename) + } + ovs_assert(schema && !txn_json); + } ++ ++ struct db *db = xzalloc(sizeof *db); ++ db->filename = xstrdup(filename); + db->db = ovsdb_create(schema, storage); + ovsdb_jsonrpc_server_add_db(config->jsonrpc, db->db); + +@@ -1481,7 +1493,8 @@ ovsdb_server_compact(struct unixctl_conn *conn, int argc, VLOG_INFO("compacting %s database by user request", node->name); @@ -84923,7 +85443,7 @@ index b6957d7300..54ed7c4283 100644 if (error) { char *s = ovsdb_error_to_string(error); ds_put_format(&reply, "%s\n", s); -@@ -1504,6 +1519,35 @@ ovsdb_server_compact(struct unixctl_conn *conn, int argc, +@@ -1504,6 +1517,35 @@ ovsdb_server_compact(struct unixctl_conn *conn, int argc, ds_destroy(&reply); } @@ -85733,8 +86253,21 @@ index 9852786466..8bbcd824f4 100644 @@ -1 +1,2 @@ version.py +dirs.py +diff --git a/python/ovs/compat/sortedcontainers/sortedlist.py b/python/ovs/compat/sortedcontainers/sortedlist.py +index 8aec6bbac1..ba55566926 100644 +--- a/python/ovs/compat/sortedcontainers/sortedlist.py ++++ b/python/ovs/compat/sortedcontainers/sortedlist.py +@@ -3,8 +3,6 @@ + """ + # pylint: disable=redefined-builtin, ungrouped-imports + +-from __future__ import print_function +- + from bisect import bisect_left, bisect_right, insort + from collections import Sequence, MutableSequence + from functools import wraps diff --git a/python/ovs/db/idl.py b/python/ovs/db/idl.py -index 020291d486..4226d1cb2f 100644 +index 020291d486..4cf79cf94e 100644 --- a/python/ovs/db/idl.py +++ b/python/ovs/db/idl.py @@ -12,6 +12,7 @@ @@ -85756,7 +86289,60 @@ index 020291d486..4226d1cb2f 100644 class Idl(object): """Open vSwitch Database Interface Definition Language (OVSDB IDL). -@@ -614,6 +619,7 @@ class Idl(object): +@@ -241,6 +246,7 @@ class Idl(object): + i = 0 + while i < 50: + i += 1 ++ previous_change_seqno = self.change_seqno + if not self._session.is_connected(): + break + +@@ -269,7 +275,7 @@ class Idl(object): + if msg.params[0] == str(self.server_monitor_uuid): + self.__parse_update(msg.params[1], OVSDB_UPDATE, + tables=self.server_tables) +- self.change_seqno = initial_change_seqno ++ self.change_seqno = previous_change_seqno + if not self.__check_server_db(): + self.force_reconnect() + break +@@ -312,7 +318,7 @@ class Idl(object): + self.__error() + break + else: +- self.change_seqno = initial_change_seqno ++ self.change_seqno = previous_change_seqno + self.__send_monitor_request() + elif (msg.type == ovs.jsonrpc.Message.T_REPLY + and self._server_monitor_request_id is not None +@@ -322,7 +328,7 @@ class Idl(object): + self._server_monitor_request_id = None + self.__parse_update(msg.result, OVSDB_UPDATE, + tables=self.server_tables) +- self.change_seqno = initial_change_seqno ++ self.change_seqno = previous_change_seqno + if self.__check_server_db(): + self.__send_monitor_request() + self.__send_db_change_aware() +@@ -336,7 +342,7 @@ class Idl(object): + self.__error() + break + else: +- self.change_seqno = initial_change_seqno ++ self.change_seqno = previous_change_seqno + self.__send_monitor_request() + elif (msg.type == ovs.jsonrpc.Message.T_REPLY + and self._db_change_aware_request_id is not None +@@ -372,7 +378,7 @@ class Idl(object): + self.force_reconnect() + break + else: +- self.change_seqno = initial_change_seqno ++ self.change_seqno = previous_change_seqno + self.__send_monitor_request() + elif (msg.type in (ovs.jsonrpc.Message.T_ERROR, + ovs.jsonrpc.Message.T_REPLY) +@@ -614,6 +620,7 @@ class Idl(object): raise error.Error(" is not an object", table_updates) @@ -85764,7 +86350,7 @@ index 020291d486..4226d1cb2f 100644 for table_name, table_update in table_updates.items(): table = tables.get(table_name) if not table: -@@ -639,7 +645,9 @@ class Idl(object): +@@ -639,7 +646,9 @@ class Idl(object): % (table_name, uuid_string)) if version == OVSDB_UPDATE2: @@ -85775,7 +86361,7 @@ index 020291d486..4226d1cb2f 100644 self.change_seqno += 1 continue -@@ -652,17 +660,20 @@ class Idl(object): +@@ -652,17 +661,20 @@ class Idl(object): raise error.Error(' missing "old" and ' '"new" members', row_update) @@ -85800,7 +86386,7 @@ index 020291d486..4226d1cb2f 100644 else: # XXX rate-limit vlog.warn("cannot delete missing row %s from table" -@@ -681,29 +692,27 @@ class Idl(object): +@@ -681,29 +693,27 @@ class Idl(object): changed = self.__row_update(table, row, row_update) table.rows[uuid] = row if changed: @@ -85835,7 +86421,7 @@ index 020291d486..4226d1cb2f 100644 else: # XXX rate-limit vlog.warn("cannot delete missing row %s from table %s" -@@ -723,7 +732,7 @@ class Idl(object): +@@ -723,7 +733,7 @@ class Idl(object): if op == ROW_CREATE: table.rows[uuid] = row if changed: @@ -85844,7 +86430,7 @@ index 020291d486..4226d1cb2f 100644 else: op = ROW_UPDATE if not row: -@@ -737,8 +746,8 @@ class Idl(object): +@@ -737,8 +747,8 @@ class Idl(object): if op == ROW_CREATE: table.rows[uuid] = row if changed: @@ -85855,7 +86441,7 @@ index 020291d486..4226d1cb2f 100644 def __check_server_db(self): """Returns True if this is a valid server database, False otherwise.""" -@@ -1567,10 +1576,9 @@ class Transaction(object): +@@ -1567,10 +1577,9 @@ class Transaction(object): for col, val in row._mutations['_inserts'].items(): column = row._table.columns[col] if column.type.is_map(): @@ -85951,11 +86537,137 @@ index e9bb0c8548..f5a520862c 100644 @staticmethod def needs_probes(): return True +diff --git a/python/ovstest/rpcserver.py b/python/ovstest/rpcserver.py +index c4aab70207..05b6b1be20 100644 +--- a/python/ovstest/rpcserver.py ++++ b/python/ovstest/rpcserver.py +@@ -18,22 +18,14 @@ rpcserver is an XML RPC server that allows RPC client to initiate tests + + import sys + +-import exceptions +- + import xmlrpc.client + +-import tcp +- + from twisted.internet import reactor + from twisted.internet.error import CannotListenError + from twisted.web import server + from twisted.web import xmlrpc + +-import udp +- +-import util +- +-import vswitch ++from . import tcp, udp, util, vswitch + + + class TestArena(xmlrpc.XMLRPC): +@@ -210,7 +202,7 @@ class TestArena(xmlrpc.XMLRPC): + (_, port) = self.__get_handle_resources(handle) + port.loseConnection() + self.__delete_handle(handle) +- except exceptions.KeyError: ++ except KeyError: + return -1 + return 0 + +@@ -222,7 +214,7 @@ class TestArena(xmlrpc.XMLRPC): + (_, connector) = self.__get_handle_resources(handle) + connector.disconnect() + self.__delete_handle(handle) +- except exceptions.KeyError: ++ except KeyError: + return -1 + return 0 + +diff --git a/python/ovstest/tcp.py b/python/ovstest/tcp.py +index c495717f2f..098c6cba3e 100644 +--- a/python/ovstest/tcp.py ++++ b/python/ovstest/tcp.py +@@ -21,7 +21,7 @@ import time + from twisted.internet import interfaces + from twisted.internet.protocol import ClientFactory, Factory, Protocol + +-from zope.interface import implements ++from zope.interface.declarations import implementer + + + class TcpListenerConnection(Protocol): +@@ -55,8 +55,8 @@ class TcpListenerFactory(Factory): + return str(self.stats) + + ++@implementer(interfaces.IPushProducer) + class Producer(object): +- implements(interfaces.IPushProducer) + """ + This producer class generates infinite byte stream for a specified time + duration +diff --git a/python/ovstest/tests.py b/python/ovstest/tests.py +index 6de3cc3af4..f959f945ef 100644 +--- a/python/ovstest/tests.py ++++ b/python/ovstest/tests.py +@@ -10,8 +10,6 @@ + # See the License for the specific language governing permissions and + # limitations under the License. + +-from __future__ import print_function +- + import math + import time + +diff --git a/python/ovstest/util.py b/python/ovstest/util.py +index 72457158f2..270d6a0376 100644 +--- a/python/ovstest/util.py ++++ b/python/ovstest/util.py +@@ -26,8 +26,6 @@ import socket + import struct + import subprocess + +-import exceptions +- + import xmlrpc.client + + +@@ -88,7 +86,7 @@ def start_process(args): + stderr=subprocess.PIPE) + out, err = p.communicate() + return (p.returncode, out, err) +- except exceptions.OSError: ++ except OSError: + return (-1, None, None) + + +diff --git a/python/ovstest/vswitch.py b/python/ovstest/vswitch.py +index 9d5b5cffd0..45c9587eeb 100644 +--- a/python/ovstest/vswitch.py ++++ b/python/ovstest/vswitch.py +@@ -15,7 +15,7 @@ + """ + vswitch module allows its callers to interact with OVS DB. + """ +-import util ++from . import util + + + def ovs_vsctl_add_bridge(bridge): diff --git a/python/setup.py b/python/setup.py -index b7252800c1..d385d83722 100644 +index b7252800c1..cfe01763f3 100644 --- a/python/setup.py +++ b/python/setup.py -@@ -30,6 +30,15 @@ except IOError: +@@ -10,8 +10,6 @@ + # See the License for the specific language governing permissions and + # limitations under the License. + +-from __future__ import print_function +- + import sys + + from distutils.command.build_ext import build_ext +@@ -30,6 +28,15 @@ except IOError: file=sys.stderr) sys.exit(-1) @@ -85971,6 +86683,15 @@ index b7252800c1..d385d83722 100644 ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError) if sys.platform == 'win32': ext_errors += (IOError, ValueError) +@@ -73,8 +80,6 @@ setup_args = dict( + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Topic :: System :: Networking', + 'License :: OSI Approved :: Apache Software License', +- 'Programming Language :: Python :: 2', +- 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', diff --git a/rhel/openvswitch-fedora.spec.in b/rhel/openvswitch-fedora.spec.in index 7bc8c34b80..f6ec347c15 100644 --- a/rhel/openvswitch-fedora.spec.in @@ -88512,6 +89233,28 @@ index 68c8774d1a..9d5e24a292 100644 # OVS_CHECK_VXLAN() # # Do basic check for vxlan functionality, skip the test if it's not there. +diff --git a/tests/system-kmod-macros.at b/tests/system-kmod-macros.at +index daf66bdec8..26beefcf44 100644 +--- a/tests/system-kmod-macros.at ++++ b/tests/system-kmod-macros.at +@@ -99,6 +99,17 @@ m4_define([CHECK_CONNTRACK_FRAG_OVERLAP], + # + m4_define([CHECK_CONNTRACK_NAT]) + ++# CHECK_CONNTRACK_ZEROIP_SNAT() ++# ++# Perform requirements checks for running conntrack all-zero IP SNAT tests. ++# The kernel always supports all-zero IP SNAT, so no check is needed. ++# However, the Windows datapath using the same netlink interface does not. ++# ++m4_define([CHECK_CONNTRACK_ZEROIP_SNAT], ++[ ++ AT_SKIP_IF([test "$IS_WIN32" = "yes"]) ++]) ++ + # CHECK_CONNTRACK_TIMEOUT() + # + # Perform requirements checks for running conntrack customized timeout tests. diff --git a/tests/system-offloads-traffic.at b/tests/system-offloads-traffic.at index 379a8a5e92..bfad66e051 100644 --- a/tests/system-offloads-traffic.at @@ -88605,10 +89348,71 @@ index 0000000000..1714273e35 +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP diff --git a/tests/system-traffic.at b/tests/system-traffic.at -index 4a39c929c2..da61e4cae8 100644 +index 4a39c929c2..2bd7ef71fe 100644 --- a/tests/system-traffic.at +++ b/tests/system-traffic.at -@@ -611,6 +611,16 @@ NS_CHECK_EXEC([at_ns0], [ping -q -c 3 10.1.1.100 | FORMAT_PING], [0], [dnl +@@ -574,6 +574,60 @@ NS_CHECK_EXEC([at_ns0], [ping -s 3200 -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PI + OVS_TRAFFIC_VSWITCHD_STOP + AT_CLEANUP + ++AT_SETUP([datapath - ping over geneve tunnel, delete flow regression]) ++OVS_CHECK_GENEVE() ++ ++OVS_TRAFFIC_VSWITCHD_START() ++ADD_BR([br-underlay]) ++ ++AT_DATA([flows.txt], [dnl ++priority=100,icmp actions=resubmit(,10) ++priority=0 actions=NORMAL ++table=10, priority=100, ip, actions=ct(table=20,zone=65520) ++table=20, priority=200, ip, ct_state=-new+trk, actions=resubmit(,30) ++table=20, priority=100, ip, ct_state=+new, actions=resubmit(,30) ++table=20, priority=50, ip, actions=DROP ++table=30, priority=100, ip, actions=ct(commit,table=40,zone=65520) ++table=40, actions=normal ++]) ++ ++AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) ++AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"]) ++ ++ADD_NAMESPACES(at_ns0) ++ ++dnl Set up underlay link from host into the namespace using veth pair. ++ADD_VETH(p0, at_ns0, br-underlay, "172.31.1.1/24") ++AT_CHECK([ip addr add dev br-underlay "172.31.1.100/24"]) ++AT_CHECK([ip link set dev br-underlay up]) ++ ++dnl Set up tunnel endpoints on OVS outside the namespace and with a native ++dnl linux device inside the namespace. ++ADD_OVS_TUNNEL([geneve], [br0], [at_gnv0], [172.31.1.1], [10.1.1.100/24]) ++ADD_NATIVE_TUNNEL([geneve], [ns_gnv0], [at_ns0], [172.31.1.100], [10.1.1.1/24], ++ [vni 0]) ++ ++dnl First, check the underlay ++NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 172.31.1.100 | FORMAT_PING], [0], [dnl ++3 packets transmitted, 3 received, 0% packet loss, time 0ms ++]) ++ ++dnl ping over tunnel should work ++NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], [0], [dnl ++3 packets transmitted, 3 received, 0% packet loss, time 0ms ++]) ++ ++AT_CHECK([ovs-ofctl del-flows br0 "ct_state=+new"]) ++ ++dnl ping should not go through after removal of the flow ++NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], [0], [dnl ++7 packets transmitted, 0 received, 100% packet loss, time 0ms ++]) ++ ++OVS_TRAFFIC_VSWITCHD_STOP(["/|ERR|/d ++/|WARN|/d"]) ++AT_CLEANUP ++ + AT_SETUP([datapath - flow resume with geneve tun_metadata]) + OVS_CHECK_GENEVE() + +@@ -611,6 +665,16 @@ NS_CHECK_EXEC([at_ns0], [ping -q -c 3 10.1.1.100 | FORMAT_PING], [0], [dnl 3 packets transmitted, 3 received, 0% packet loss, time 0ms ]) @@ -88625,7 +89429,7 @@ index 4a39c929c2..da61e4cae8 100644 OVS_APP_EXIT_AND_WAIT([ovs-ofctl]) OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP -@@ -2331,6 +2341,35 @@ NXST_FLOW reply: +@@ -2331,6 +2395,35 @@ NXST_FLOW reply: OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP @@ -88661,7 +89465,102 @@ index 4a39c929c2..da61e4cae8 100644 AT_SETUP([conntrack - ICMP related]) AT_SKIP_IF([test $HAVE_NC = no]) CHECK_CONNTRACK() -@@ -5873,6 +5912,50 @@ ovs-appctl dpif/dump-flows br0 +@@ -4379,6 +4472,52 @@ tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=,dport=),reply=(src= + OVS_TRAFFIC_VSWITCHD_STOP + AT_CLEANUP + ++ ++AT_SETUP([conntrack - all-zero IP SNAT]) ++AT_SKIP_IF([test $HAVE_NC = no]) ++CHECK_CONNTRACK() ++CHECK_CONNTRACK_ZEROIP_SNAT() ++OVS_TRAFFIC_VSWITCHD_START() ++ ++ADD_NAMESPACES(at_ns0, at_ns1) ++ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24") ++ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24") ++NS_CHECK_EXEC([at_ns0], [ip route add 172.1.1.0/24 via 10.1.1.2]) ++ ++OVS_START_L7([at_ns1], [http]) ++ ++AT_DATA([flows.txt], [dnl ++table=0,priority=30,ct_state=-trk,ip,action=ct(table=0) ++table=0,priority=20,ct_state=-rpl,ip,nw_dst=10.1.1.0/24,actions=ct(commit,nat(src=0.0.0.0),table=10) ++table=0,priority=20,ct_state=+rpl,ip,nw_dst=10.1.1.0/24,actions=resubmit(,10) ++table=0,priority=20,ip,nw_dst=172.1.1.2,actions=ct(commit,nat(dst=10.1.1.2),table=10) ++table=0,priority=10,arp,action=normal ++table=0,priority=1,action=drop ++table=10,priority=20,ct_state=+rpl,ip,nw_dst=10.1.1.0/24 actions=ct(table=20,nat) ++table=10,priority=10,ip,nw_dst=10.1.1.0/24 actions=resubmit(,20) ++table=20,priority=10,ip,nw_dst=10.1.1.1,action=1 ++table=20,priority=10,ip,nw_dst=10.1.1.2,action=2 ++]) ++AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt]) ++ ++dnl - Test to make sure src nat is NOT done when not needed ++NS_CHECK_EXEC([at_ns0], [echo "TEST" | nc -p 30000 10.1.1.2 80 > nc-1.log]) ++AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "orig=.src=10\.1\.1\.1,"], [0], [dnl ++tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=30000,dport=80),reply=(src=10.1.1.2,dst=10.1.1.1,sport=80,dport=30000),protoinfo=(state=TIME_WAIT) ++]) ++ ++dnl - Test to make sure src nat is done when needed ++NS_CHECK_EXEC([at_ns0], [echo "TEST2" | nc -p 30001 172.1.1.2 80 > nc-2.log]) ++NS_CHECK_EXEC([at_ns0], [echo "TEST3" | nc -p 30001 10.1.1.2 80 > nc-3.log]) ++AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep 30001 | grep "orig=.src=10\.1\.1\.1," | sed -e 's/port=30001/port=/g' -e 's/sport=80,dport=[[0-9]]\+/sport=80,dport=/g' | sort], [0], [dnl ++tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=,dport=80),reply=(src=10.1.1.2,dst=10.1.1.1,sport=80,dport=),protoinfo=(state=TIME_WAIT) ++tcp,orig=(src=10.1.1.1,dst=172.1.1.2,sport=,dport=80),reply=(src=10.1.1.2,dst=10.1.1.1,sport=80,dport=),protoinfo=(state=TIME_WAIT) ++]) ++ ++OVS_TRAFFIC_VSWITCHD_STOP ++AT_CLEANUP ++ ++ + AT_SETUP([conntrack - simple DNAT]) + CHECK_CONNTRACK() + CHECK_CONNTRACK_NAT() +@@ -4434,6 +4573,41 @@ tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=,dport=),reply=(src= + OVS_TRAFFIC_VSWITCHD_STOP + AT_CLEANUP + ++AT_SETUP([conntrack - DNAT with additional SNAT]) ++CHECK_CONNTRACK() ++OVS_TRAFFIC_VSWITCHD_START() ++ ++ADD_NAMESPACES(at_ns0, at_ns1) ++ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24") ++ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24") ++NS_CHECK_EXEC([at_ns0], [ip route add 172.1.1.0/24 via 10.1.1.2]) ++ ++OVS_START_L7([at_ns1], [http]) ++ ++AT_DATA([flows.txt], [dnl ++table=0,priority=30,in_port=1,ip,nw_dst=172.1.1.2,actions=ct(commit,nat(dst=10.1.1.2:80),table=1) ++table=0,priority=20,in_port=2,ip,actions=ct(nat),1 ++table=0,priority=10,arp,actions=NORMAL ++table=0,priority=1,actions=drop ++dnl Be sure all ct() actions but src nat are executed ++table=1,ip,actions=ct(commit,nat(src=10.1.1.240),exec(set_field:0xac->ct_mark,set_field:0xac->ct_label),table=2) ++table=2,in_port=1,ip,ct_mark=0xac,ct_label=0xac,actions=2 ++]) ++AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt]) ++ ++NS_CHECK_EXEC([at_ns0], [wget http://172.1.1.2:8080 -t 5 -T 1 --retry-connrefused -v -o wget0.log]) ++ ++dnl - make sure only dst nat has been performed ++AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.240)], [0], [dnl ++]) ++ ++AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.1)], [0], [dnl ++tcp,orig=(src=10.1.1.1,dst=172.1.1.2,sport=,dport=),reply=(src=10.1.1.2,dst=10.1.1.1,sport=,dport=),mark=172,labels=0xac,protoinfo=(state=) ++]) ++ ++OVS_TRAFFIC_VSWITCHD_STOP ++AT_CLEANUP ++ + AT_SETUP([conntrack - more complex DNAT]) + CHECK_CONNTRACK() + CHECK_CONNTRACK_NAT() +@@ -5873,6 +6047,50 @@ ovs-appctl dpif/dump-flows br0 OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP @@ -88712,6 +89611,27 @@ index 4a39c929c2..da61e4cae8 100644 AT_BANNER([802.1ad]) AT_SETUP([802.1ad - vlan_limit]) +diff --git a/tests/system-userspace-macros.at b/tests/system-userspace-macros.at +index ba7f4102f4..5c96f943df 100644 +--- a/tests/system-userspace-macros.at ++++ b/tests/system-userspace-macros.at +@@ -96,6 +96,16 @@ m4_define([CHECK_CONNTRACK_FRAG_OVERLAP]) + # + m4_define([CHECK_CONNTRACK_NAT]) + ++# CHECK_CONNTRACK_ZEROIP_SNAT() ++# ++# Perform requirements checks for running conntrack all-zero IP SNAT tests. ++# The userspace datapath does not support all-zero IP SNAT. ++# ++m4_define([CHECK_CONNTRACK_ZEROIP_SNAT], ++[ ++ AT_SKIP_IF([:]) ++]) ++ + # CHECK_CONNTRACK_TIMEOUT() + # + # Perform requirements checks for running conntrack customized timeout tests. diff --git a/tests/system-userspace-packet-type-aware.at b/tests/system-userspace-packet-type-aware.at index c2246316de..974304758f 100644 --- a/tests/system-userspace-packet-type-aware.at @@ -88787,6 +89707,19 @@ index f77ee75e38..da1ac63b6c 100644 } ovs_barrier_block(&barrier); destroy_packets(pkt_batch); +diff --git a/tests/test-jsonrpc.py b/tests/test-jsonrpc.py +index 3eabcd78d5..1df5afa221 100644 +--- a/tests/test-jsonrpc.py ++++ b/tests/test-jsonrpc.py +@@ -12,8 +12,6 @@ + # See the License for the specific language governing permissions and + # limitations under the License. + +-from __future__ import print_function +- + import argparse + import errno + import os diff --git a/tests/test-l7.py b/tests/test-l7.py index d7854a1df3..32a77392c6 100755 --- a/tests/test-l7.py @@ -89689,6 +90622,19 @@ index 5a14e7fe58..bf0463e25c 100644 reconnect_set_name(reconnect, "remote"); reconnect_get_stats(reconnect, now, &prev); printf("### t=%d ###\n", now); +diff --git a/tests/test-reconnect.py b/tests/test-reconnect.py +index 6cd052878e..ef669b0417 100644 +--- a/tests/test-reconnect.py ++++ b/tests/test-reconnect.py +@@ -12,8 +12,6 @@ + # See the License for the specific language governing permissions and + # limitations under the License. + +-from __future__ import print_function +- + import errno + import sys + diff --git a/tests/test-sha1.c b/tests/test-sha1.c index b7279db6aa..cc80888a7d 100644 --- a/tests/test-sha1.c @@ -90008,6 +90954,18 @@ index e55bfc2ed5..987d211069 100755 self.mtime = time.time() +diff --git a/utilities/checkpatch.py b/utilities/checkpatch.py +index fc9e20bf1b..893244578a 100755 +--- a/utilities/checkpatch.py ++++ b/utilities/checkpatch.py +@@ -13,7 +13,6 @@ + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +-from __future__ import print_function + + import email + import getopt diff --git a/utilities/ovs-ctl.in b/utilities/ovs-ctl.in index 8c5cd70327..4156da20ef 100644 --- a/utilities/ovs-ctl.in @@ -90217,6 +91175,39 @@ index f2cc3f7f2a..fbe6e4f560 100755 def main(): +diff --git a/utilities/ovs-l3ping.in b/utilities/ovs-l3ping.in +index 92d32acb3f..1ece06457c 100644 +--- a/utilities/ovs-l3ping.in ++++ b/utilities/ovs-l3ping.in +@@ -19,7 +19,7 @@ achieved by tunneling the control connection inside the tunnel itself. + """ + + import socket +-import xmlrpclib ++import xmlrpc.client + + import ovstest.args as args + import ovstest.tests as tests +@@ -64,13 +64,13 @@ if __name__ == '__main__': + ps = get_packet_sizes(me, he, args.client[0]) + tests.do_direct_tests(me, he, bandwidth, interval, ps) + except KeyboardInterrupt: +- print "Terminating" +- except xmlrpclib.Fault: +- print "Couldn't contact peer" ++ print("Terminating") ++ except xmlrpc.client.Fault: ++ print("Couldn't contact peer") + except socket.error: +- print "Couldn't contact peer" +- except xmlrpclib.ProtocolError: +- print "XMLRPC control channel was abruptly terminated" ++ print("Couldn't contact peer") ++ except xmlrpc.client.ProtocolError: ++ print("XMLRPC control channel was abruptly terminated") + finally: + if local_server is not None: + local_server.terminate() diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 3601890f40..ede7f1e61a 100644 --- a/utilities/ovs-ofctl.c @@ -90262,6 +91253,62 @@ index 3601890f40..ede7f1e61a 100644 { "mod-group", "switch group", 1, 2, ofctl_mod_group, OVS_RW }, { "del-groups", "switch [group]", +diff --git a/utilities/ovs-parse-backtrace.in b/utilities/ovs-parse-backtrace.in +index d5506769a8..f44f05cd1e 100755 +--- a/utilities/ovs-parse-backtrace.in ++++ b/utilities/ovs-parse-backtrace.in +@@ -70,7 +70,7 @@ result. Expected usage is for ovs-appctl backtrace to be piped in.""") + if os.path.exists(debug): + binary = debug + +- print "Binary: %s\n" % binary ++ print("Binary: %s\n" % binary) + + stdin = sys.stdin.read() + +@@ -88,15 +88,15 @@ result. Expected usage is for ovs-appctl backtrace to be piped in.""") + for lines, count in traces: + longest = max(len(l) for l in lines) + +- print "Backtrace Count: %d" % count ++ print("Backtrace Count: %d" % count) + for line in lines: + match = re.search(r'\[(0x.*)]', line) + if match: +- print "%s %s" % (line.ljust(longest), +- addr2line(binary, match.group(1))) ++ print("%s %s" % (line.ljust(longest), ++ addr2line(binary, match.group(1)))) + else: +- print line +- print ++ print(line) ++ print() + + + if __name__ == "__main__": +diff --git a/utilities/ovs-pcap.in b/utilities/ovs-pcap.in +index dddbee4dfb..6b5f63399e 100755 +--- a/utilities/ovs-pcap.in ++++ b/utilities/ovs-pcap.in +@@ -14,8 +14,6 @@ + # See the License for the specific language governing permissions and + # limitations under the License. + +-from __future__ import print_function +- + import binascii + import getopt + import struct +@@ -79,7 +77,7 @@ if __name__ == "__main__": + try: + options, args = getopt.gnu_getopt(sys.argv[1:], 'hV', + ['help', 'version']) +- except getopt.GetoptException as geo: ++ except getopt.GetoptError as geo: + sys.stderr.write("%s: %s\n" % (argv0, geo.msg)) + sys.exit(1) + diff --git a/utilities/ovs-pipegen.py b/utilities/ovs-pipegen.py index ee5797221c..a3b6a661de 100755 --- a/utilities/ovs-pipegen.py @@ -90274,6 +91321,122 @@ index ee5797221c..a3b6a661de 100755 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. +diff --git a/utilities/ovs-vlan-test.in b/utilities/ovs-vlan-test.in +index 154573a9b5..de3ae16862 100755 +--- a/utilities/ovs-vlan-test.in ++++ b/utilities/ovs-vlan-test.in +@@ -14,9 +14,9 @@ + # See the License for the specific language governing permissions and + # limitations under the License. + +-import BaseHTTPServer + import getopt +-import httplib ++import http.client ++import http.server + import os + import threading + import time +@@ -84,7 +84,7 @@ class UDPReceiver: + + try: + sock.bind((self.vlan_ip, self.vlan_port)) +- except socket.error, e: ++ except socket.error as e: + print_safe('Failed to bind to %s:%d with error: %s' + % (self.vlan_ip, self.vlan_port, e)) + os._exit(1) #sys.exit only exits the current thread. +@@ -95,7 +95,7 @@ class UDPReceiver: + data, _ = sock.recvfrom(4096) + except socket.timeout: + continue +- except socket.error, e: ++ except socket.error as e: + print_safe('Failed to receive from %s:%d with error: %s' + % (self.vlan_ip, self.vlan_port, e)) + os._exit(1) +@@ -180,7 +180,7 @@ class VlanServer: + for _ in range(send_time * 2): + try: + send_packet(test_id, size, ip, port) +- except socket.error, e: ++ except socket.error as e: + self.set_result(test_id, 'Failure: ' + str(e)) + return + time.sleep(.5) +@@ -194,15 +194,15 @@ class VlanServer: + def run(self): + self.udp_recv.start() + try: +- BaseHTTPServer.HTTPServer((self.server_ip, self.server_port), ++ http.server.HTTPServer((self.server_ip, self.server_port), + VlanServerHandler).serve_forever() +- except socket.error, e: ++ except socket.error as e: + print_safe('Failed to start control server: %s' % e) + self.udp_recv.stop() + + return 1 + +-class VlanServerHandler(BaseHTTPServer.BaseHTTPRequestHandler): ++class VlanServerHandler(http.server.BaseHTTPRequestHandler): + def do_GET(self): + + #Guarantee three arguments. +@@ -244,7 +244,7 @@ class VlanClient: + self.udp_recv = UDPReceiver(vlan_ip, vlan_port) + + def request(self, resource): +- conn = httplib.HTTPConnection(self.server_ip_port) ++ conn = http.client.HTTPConnection(self.server_ip_port) + conn.request('GET', resource) + return conn + +@@ -256,7 +256,7 @@ class VlanClient: + try: + conn = self.request('/start/recv') + data = conn.getresponse().read() +- except (socket.error, httplib.HTTPException), e: ++ except (socket.error, http.client.HTTPException) as e: + error_msg(e) + return False + +@@ -277,7 +277,7 @@ class VlanClient: + send_packet(test_id, size, ip, port) + resp = self.request('/result/%d' % test_id).getresponse() + data = resp.read() +- except (socket.error, httplib.HTTPException), e: ++ except (socket.error, http.client.HTTPException) as e: + error_msg(e) + return False + +@@ -302,7 +302,7 @@ class VlanClient: + try: + conn = self.request(resource) + test_id = conn.getresponse().read() +- except (socket.error, httplib.HTTPException), e: ++ except (socket.error, http.client.HTTPException) as e: + error_msg(e) + return False + +@@ -335,7 +335,7 @@ class VlanClient: + try: + resp = self.request('/ping').getresponse() + data = resp.read() +- except (socket.error, httplib.HTTPException), e: ++ except (socket.error, http.client.HTTPException) as e: + error_msg(e) + return False + +@@ -383,7 +383,7 @@ def main(): + try: + options, args = getopt.gnu_getopt(sys.argv[1:], 'hVs', + ['help', 'version', 'server']) +- except getopt.GetoptError, geo: ++ except getopt.GetoptError as geo: + print_safe('%s: %s\n' % (sys.argv[0], geo.msg)) + return 1 + diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c index bd3972636e..37cc72d401 100644 --- a/utilities/ovs-vsctl.c @@ -90313,7 +91476,7 @@ index e591c26a6c..ce348b9d16 100644 } diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml -index 3ddaaefda8..11880f1d2f 100644 +index 3ddaaefda8..fd13281a7f 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -653,8 +653,9 @@ @@ -90392,6 +91555,22 @@ index 3ddaaefda8..11880f1d2f 100644 The Excess Burst Size (EBS) is measured in bytes and represents a +@@ -5976,6 +6005,15 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \ + True if the datapath supports OVS_ACTION_ATTR_DROP. If false, + explicit drop action will not be sent to the datapath. + ++ ++ True if the datapath supports all-zero SNAT. This is a special case ++ if the src IP address is configured as all 0's, i.e., ++ nat(src=0.0.0.0). In this case, when a source port ++ collision is detected during the commit, the source port will be ++ translated to an ephemeral port. If there is no collision, no SNAT ++ is performed. ++ + + + diff --git a/xenserver/etc_xapi.d_plugins_openvswitch-cfg-update b/xenserver/etc_xapi.d_plugins_openvswitch-cfg-update index e7404e3b00..b8db881949 100755 --- a/xenserver/etc_xapi.d_plugins_openvswitch-cfg-update diff --git a/SPECS/openvswitch2.13.spec b/SPECS/openvswitch2.13.spec index a9c677d..00bd95a 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: 115%{?commit0:.%{date}git%{shortcommit0}}%{?commit1:dpdk%{shortcommit1}}%{?dist} +Release: 117%{?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 @@ -710,6 +710,14 @@ exit 0 %endif %changelog +* Sat Jul 17 2021 Open vSwitch CI - 2.13.0-117 +- Merging upstream branch-2.13 + [1dbd295283c1533e979c2d7694168a6737c8d645] + +* Wed Jun 30 2021 Timothy Redaelli - 2.13.0-116 +- Merging 15251f0e1d datapath-windows: Specify external include .. + [f9d10a495b5d502d948a4c8e3c6301cfb942d6ac] + * Thu May 27 2021 Open vSwitch CI - 2.13.0-115 - Merging upstream branch-2.13 [190762bf5ce2ebac4f08d1505bcee11520f7be38]