diff --git a/SOURCES/openvswitch-2.16.0.patch b/SOURCES/openvswitch-2.16.0.patch index 7df258c..356509d 100644 --- a/SOURCES/openvswitch-2.16.0.patch +++ b/SOURCES/openvswitch-2.16.0.patch @@ -1,3 +1,18 @@ +diff --git a/.ci/linux-build.sh b/.ci/linux-build.sh +index 863f023888..1e7565b8bb 100755 +--- a/.ci/linux-build.sh ++++ b/.ci/linux-build.sh +@@ -246,8 +246,8 @@ if [ "$ASAN" ]; then + export ASAN_OPTIONS='detect_leaks=1' + # -O2 generates few false-positive memory leak reports in test-ovsdb + # application, so lowering optimizations to -O1 here. +- CLFAGS_ASAN="-O1 -fno-omit-frame-pointer -fno-common -fsanitize=address" +- CFLAGS_FOR_OVS="${CFLAGS_FOR_OVS} ${CLFAGS_ASAN}" ++ CFLAGS_ASAN="-O1 -fno-omit-frame-pointer -fno-common -fsanitize=address" ++ CFLAGS_FOR_OVS="${CFLAGS_FOR_OVS} ${CFLAGS_ASAN}" + fi + + save_OPTS="${OPTS} $*" diff --git a/.ci/linux-prepare.sh b/.ci/linux-prepare.sh index c55125cf78..c0b7473eda 100755 --- a/.ci/linux-prepare.sh @@ -657,6 +672,122 @@ index 89a36fe17b..a8b0705d9f 100755 (tunnel.conf["remote_ip"], tunnel.conf["private_key"])) if tunnel.conf["remote_cert"]: +diff --git a/lib/bfd.c b/lib/bfd.c +index 3c965699ac..9698576d07 100644 +--- a/lib/bfd.c ++++ b/lib/bfd.c +@@ -131,16 +131,17 @@ enum diag { + * | Required Min Echo RX Interval | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct msg { +- uint8_t vers_diag; /* Version and diagnostic. */ +- uint8_t flags; /* 2bit State field followed by flags. */ +- uint8_t mult; /* Fault detection multiplier. */ +- uint8_t length; /* Length of this BFD message. */ +- ovs_be32 my_disc; /* My discriminator. */ +- ovs_be32 your_disc; /* Your discriminator. */ +- ovs_be32 min_tx; /* Desired minimum tx interval. */ +- ovs_be32 min_rx; /* Required minimum rx interval. */ +- ovs_be32 min_rx_echo; /* Required minimum echo rx interval. */ ++ uint8_t vers_diag; /* Version and diagnostic. */ ++ uint8_t flags; /* 2bit State field followed by flags. */ ++ uint8_t mult; /* Fault detection multiplier. */ ++ uint8_t length; /* Length of this BFD message. */ ++ ovs_16aligned_be32 my_disc; /* My discriminator. */ ++ ovs_16aligned_be32 your_disc; /* Your discriminator. */ ++ ovs_16aligned_be32 min_tx; /* Desired minimum tx interval. */ ++ ovs_16aligned_be32 min_rx; /* Required minimum rx interval. */ ++ ovs_16aligned_be32 min_rx_echo; /* Required minimum echo rx interval. */ + }; ++ + BUILD_ASSERT_DECL(BFD_PACKET_LEN == sizeof(struct msg)); + + #define DIAG_MASK 0x1f +@@ -634,9 +635,9 @@ bfd_put_packet(struct bfd *bfd, struct dp_packet *p, + + msg->mult = bfd->mult; + msg->length = BFD_PACKET_LEN; +- msg->my_disc = htonl(bfd->disc); +- msg->your_disc = htonl(bfd->rmt_disc); +- msg->min_rx_echo = htonl(0); ++ put_16aligned_be32(&msg->my_disc, htonl(bfd->disc)); ++ put_16aligned_be32(&msg->your_disc, htonl(bfd->rmt_disc)); ++ put_16aligned_be32(&msg->min_rx_echo, htonl(0)); + + if (bfd_in_poll(bfd)) { + min_tx = bfd->poll_min_tx; +@@ -646,8 +647,8 @@ bfd_put_packet(struct bfd *bfd, struct dp_packet *p, + min_rx = bfd->min_rx; + } + +- msg->min_tx = htonl(min_tx * 1000); +- msg->min_rx = htonl(min_rx * 1000); ++ put_16aligned_be32(&msg->min_tx, htonl(min_tx * 1000)); ++ put_16aligned_be32(&msg->min_rx, htonl(min_rx * 1000)); + + bfd->flags &= ~FLAG_FINAL; + *oam = bfd->oam; +@@ -781,12 +782,12 @@ bfd_process_packet(struct bfd *bfd, const struct flow *flow, + goto out; + } + +- if (!msg->my_disc) { ++ if (!get_16aligned_be32(&msg->my_disc)) { + log_msg(VLL_WARN, msg, "NULL my_disc", bfd); + goto out; + } + +- pkt_your_disc = ntohl(msg->your_disc); ++ pkt_your_disc = ntohl(get_16aligned_be32(&msg->your_disc)); + if (pkt_your_disc) { + /* Technically, we should use the your discriminator field to figure + * out which 'struct bfd' this packet is destined towards. That way a +@@ -806,7 +807,7 @@ bfd_process_packet(struct bfd *bfd, const struct flow *flow, + bfd_status_changed(bfd); + } + +- bfd->rmt_disc = ntohl(msg->my_disc); ++ bfd->rmt_disc = ntohl(get_16aligned_be32(&msg->my_disc)); + bfd->rmt_state = rmt_state; + bfd->rmt_flags = flags; + bfd->rmt_diag = msg->vers_diag & DIAG_MASK; +@@ -834,7 +835,7 @@ bfd_process_packet(struct bfd *bfd, const struct flow *flow, + bfd->rmt_mult = msg->mult; + } + +- rmt_min_rx = MAX(ntohl(msg->min_rx) / 1000, 1); ++ rmt_min_rx = MAX(ntohl(get_16aligned_be32(&msg->min_rx)) / 1000, 1); + if (bfd->rmt_min_rx != rmt_min_rx) { + bfd->rmt_min_rx = rmt_min_rx; + if (bfd->next_tx) { +@@ -843,7 +844,7 @@ bfd_process_packet(struct bfd *bfd, const struct flow *flow, + log_msg(VLL_INFO, msg, "New remote min_rx", bfd); + } + +- bfd->rmt_min_tx = MAX(ntohl(msg->min_tx) / 1000, 1); ++ bfd->rmt_min_tx = MAX(ntohl(get_16aligned_be32(&msg->min_tx)) / 1000, 1); + bfd->detect_time = bfd_rx_interval(bfd) * bfd->rmt_mult + time_msec(); + + if (bfd->state == STATE_ADMIN_DOWN) { +@@ -1105,10 +1106,14 @@ log_msg(enum vlog_level level, const struct msg *p, const char *message, + bfd_diag_str(p->vers_diag & DIAG_MASK), + bfd_state_str(p->flags & STATE_MASK), + p->mult, p->length, bfd_flag_str(p->flags & FLAGS_MASK), +- ntohl(p->my_disc), ntohl(p->your_disc), +- ntohl(p->min_tx), ntohl(p->min_tx) / 1000, +- ntohl(p->min_rx), ntohl(p->min_rx) / 1000, +- ntohl(p->min_rx_echo), ntohl(p->min_rx_echo) / 1000); ++ ntohl(get_16aligned_be32(&p->my_disc)), ++ ntohl(get_16aligned_be32(&p->your_disc)), ++ ntohl(get_16aligned_be32(&p->min_tx)), ++ ntohl(get_16aligned_be32(&p->min_tx)) / 1000, ++ ntohl(get_16aligned_be32(&p->min_rx)), ++ ntohl(get_16aligned_be32(&p->min_rx)) / 1000, ++ ntohl(get_16aligned_be32(&p->min_rx_echo)), ++ ntohl(get_16aligned_be32(&p->min_rx_echo)) / 1000); + bfd_put_details(&ds, bfd); + VLOG(level, "%s", ds_cstr(&ds)); + ds_destroy(&ds); diff --git a/lib/db-ctl-base.c b/lib/db-ctl-base.c index 77cc76a9f6..7074561588 100644 --- a/lib/db-ctl-base.c @@ -755,6 +886,19 @@ index 77cc76a9f6..7074561588 100644 ovsdb_datum_destroy(&add, type); } if (old.n > type->n_max) { +diff --git a/lib/dp-packet.c b/lib/dp-packet.c +index 72f6d09ac7..35c72542a2 100644 +--- a/lib/dp-packet.c ++++ b/lib/dp-packet.c +@@ -294,7 +294,7 @@ dp_packet_resize(struct dp_packet *b, size_t new_headroom, size_t new_tailroom) + void + dp_packet_prealloc_tailroom(struct dp_packet *b, size_t size) + { +- if (size > dp_packet_tailroom(b)) { ++ if ((size && !dp_packet_base(b)) || (size > dp_packet_tailroom(b))) { + dp_packet_resize(b, dp_packet_headroom(b), MAX(size, 64)); + } + } diff --git a/lib/dp-packet.h b/lib/dp-packet.h index 08d93c2779..3dc582fbfd 100644 --- a/lib/dp-packet.h @@ -1064,6 +1208,23 @@ index 92092ebec9..3dfc91f0fe 100644 * If dp_netdev_input is not called from a pmd thread, a mutex is used. */ +diff --git a/lib/dpif-netdev-private-dpcls.h b/lib/dpif-netdev-private-dpcls.h +index 7c4a840cb1..0d5da73c7a 100644 +--- a/lib/dpif-netdev-private-dpcls.h ++++ b/lib/dpif-netdev-private-dpcls.h +@@ -83,8 +83,10 @@ struct dpcls_subtable { + /* The lookup function to use for this subtable. If there is a known + * property of the subtable (eg: only 3 bits of miniflow metadata is + * used for the lookup) then this can point at an optimized version of +- * the lookup function for this particular subtable. */ +- dpcls_subtable_lookup_func lookup_func; ++ * the lookup function for this particular subtable. The lookup function ++ * can be used at any time by a PMD thread, so it's declared as an atomic ++ * here to prevent garbage from being read. */ ++ ATOMIC(dpcls_subtable_lookup_func) lookup_func; + + /* Caches the masks to match a packet to, reducing runtime calculations. */ + uint64_t *mf_masks; diff --git a/lib/dpif-netdev-private-thread.h b/lib/dpif-netdev-private-thread.h index a782d9678a..ac4885538c 100644 --- a/lib/dpif-netdev-private-thread.h @@ -1084,10 +1245,20 @@ index a782d9678a..ac4885538c 100644 /* Flow-Table and classifiers diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c -index bddce75b63..d6bee2a5a9 100644 +index bddce75b63..0b47c1a486 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c -@@ -4061,7 +4061,10 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute) +@@ -984,7 +984,9 @@ dpif_netdev_subtable_lookup_set(struct unixctl_conn *conn, int argc OVS_UNUSED, + if (!cls) { + continue; + } ++ ovs_mutex_lock(&pmd->flow_mutex); + uint32_t subtbl_changes = dpcls_subtable_lookup_reprobe(cls); ++ ovs_mutex_unlock(&pmd->flow_mutex); + if (subtbl_changes) { + lookup_dpcls_changed++; + lookup_subtable_changed += subtbl_changes; +@@ -4061,7 +4063,10 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute) flow_hash_5tuple(execute->flow, 0)); } @@ -1099,7 +1270,7 @@ index bddce75b63..d6bee2a5a9 100644 dp_netdev_execute_actions(pmd, &pp, false, execute->flow, execute->actions, execute->actions_len); dp_netdev_pmd_flush_output_packets(pmd, true); -@@ -4071,6 +4074,24 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute) +@@ -4071,6 +4076,24 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute) dp_netdev_pmd_unref(pmd); } @@ -1124,6 +1295,48 @@ index bddce75b63..d6bee2a5a9 100644 return 0; } +@@ -8942,9 +8965,12 @@ dpcls_create_subtable(struct dpcls *cls, const struct netdev_flow_key *mask) + + /* Get the preferred subtable search function for this (u0,u1) subtable. + * The function is guaranteed to always return a valid implementation, and +- * possibly an ISA optimized, and/or specialized implementation. ++ * possibly an ISA optimized, and/or specialized implementation. Initialize ++ * the subtable search function atomically to avoid garbage data being read ++ * by the PMD thread. + */ +- subtable->lookup_func = dpcls_subtable_get_best_impl(unit0, unit1); ++ atomic_init(&subtable->lookup_func, ++ dpcls_subtable_get_best_impl(unit0, unit1)); + + cmap_insert(&cls->subtables_map, &subtable->cmap_node, mask->hash); + /* Add the new subtable at the end of the pvector (with no hits yet) */ +@@ -8973,6 +8999,10 @@ dpcls_find_subtable(struct dpcls *cls, const struct netdev_flow_key *mask) + /* Checks for the best available implementation for each subtable lookup + * function, and assigns it as the lookup function pointer for each subtable. + * Returns the number of subtables that have changed lookup implementation. ++ * This function requires holding a flow_mutex when called. This is to make ++ * sure modifications done by this function are not overwritten. This could ++ * happen if dpcls_sort_subtable_vector() is called at the same time as this ++ * function. + */ + static uint32_t + dpcls_subtable_lookup_reprobe(struct dpcls *cls) +@@ -8985,10 +9015,13 @@ dpcls_subtable_lookup_reprobe(struct dpcls *cls) + uint32_t u0_bits = subtable->mf_bits_set_unit0; + uint32_t u1_bits = subtable->mf_bits_set_unit1; + void *old_func = subtable->lookup_func; +- subtable->lookup_func = dpcls_subtable_get_best_impl(u0_bits, u1_bits); ++ ++ /* Set the subtable lookup function atomically to avoid garbage data ++ * being read by the PMD thread. */ ++ atomic_store_relaxed(&subtable->lookup_func, ++ dpcls_subtable_get_best_impl(u0_bits, u1_bits)); + subtables_changed += (old_func != subtable->lookup_func); + } +- pvector_publish(pvec); + + return subtables_changed; + } diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 34fc042373..5f4b60c5a6 100644 --- a/lib/dpif-netlink.c @@ -1496,6 +1709,21 @@ index 32d25003b8..0baf7c622c 100644 + } ds_put_char(ds, '"'); } +diff --git a/lib/lldp/lldp.c b/lib/lldp/lldp.c +index 18afbab9a7..dfeb2a8002 100644 +--- a/lib/lldp/lldp.c ++++ b/lib/lldp/lldp.c +@@ -146,7 +146,9 @@ static void + lldp_tlv_end(struct dp_packet *p, unsigned int start) + { + ovs_be16 *tlv = dp_packet_at_assert(p, start, 2); +- *tlv |= htons((dp_packet_size(p) - (start + 2)) & 0x1ff); ++ put_unaligned_be16(tlv, ++ get_unaligned_be16(tlv) ++ | htons((dp_packet_size(p) - (start + 2)) & 0x1ff)); + } + + int diff --git a/lib/meta-flow.c b/lib/meta-flow.c index c808d205d5..e03cd8d0c5 100644 --- a/lib/meta-flow.c @@ -2433,6 +2661,81 @@ index b30a11c24b..41835f6f4d 100644 return NULL; } +diff --git a/lib/stopwatch.c b/lib/stopwatch.c +index f5602163bc..1c71df1a12 100644 +--- a/lib/stopwatch.c ++++ b/lib/stopwatch.c +@@ -114,7 +114,6 @@ static void + calc_percentile(unsigned long long n_samples, struct percentile *pctl, + unsigned long long new_sample) + { +- + if (n_samples < P_SQUARE_MIN) { + pctl->samples[n_samples - 1] = new_sample; + } +@@ -228,13 +227,12 @@ add_sample(struct stopwatch *sw, unsigned long long new_sample) + sw->min = new_sample; + } + +- calc_percentile(sw->n_samples, &sw->pctl, new_sample); +- + if (sw->n_samples++ == 0) { + sw->short_term.average = sw->long_term.average = new_sample; + return; + } + ++ calc_percentile(sw->n_samples, &sw->pctl, new_sample); + calc_average(&sw->short_term, new_sample); + calc_average(&sw->long_term, new_sample); + } +diff --git a/lib/stp.c b/lib/stp.c +index 809b405a52..a869b5f390 100644 +--- a/lib/stp.c ++++ b/lib/stp.c +@@ -737,7 +737,7 @@ void + stp_received_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) + { + struct stp *stp = p->stp; +- const struct stp_bpdu_header *header; ++ struct stp_bpdu_header header; + + ovs_mutex_lock(&mutex); + if (p->state == STP_DISABLED) { +@@ -750,19 +750,19 @@ stp_received_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) + goto out; + } + +- header = bpdu; +- if (header->protocol_id != htons(STP_PROTOCOL_ID)) { ++ memcpy(&header, bpdu, sizeof header); ++ if (header.protocol_id != htons(STP_PROTOCOL_ID)) { + VLOG_WARN("%s: received BPDU with unexpected protocol ID %"PRIu16, +- stp->name, ntohs(header->protocol_id)); ++ stp->name, ntohs(header.protocol_id)); + p->error_count++; + goto out; + } +- if (header->protocol_version != STP_PROTOCOL_VERSION) { ++ if (header.protocol_version != STP_PROTOCOL_VERSION) { + VLOG_DBG("%s: received BPDU with unexpected protocol version %"PRIu8, +- stp->name, header->protocol_version); ++ stp->name, header.protocol_version); + } + +- switch (header->bpdu_type) { ++ switch (header.bpdu_type) { + case STP_TYPE_CONFIG: + if (bpdu_size < sizeof(struct stp_config_bpdu)) { + VLOG_WARN("%s: received config BPDU with invalid size %"PRIuSIZE, +@@ -785,7 +785,7 @@ stp_received_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) + + default: + VLOG_WARN("%s: received BPDU of unexpected type %"PRIu8, +- stp->name, header->bpdu_type); ++ stp->name, header.bpdu_type); + p->error_count++; + goto out; + } diff --git a/lib/tc.c b/lib/tc.c index 38a1dfc0eb..adb2d3182a 100644 --- a/lib/tc.c @@ -3222,7 +3525,7 @@ index 56edc5f000..03d1c3499e 100644 break; diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in -index 61cded16d3..78ebf2dc14 100755 +index 61cded16d3..a2ee10af1b 100755 --- a/ovsdb/ovsdb-idlc.in +++ b/ovsdb/ovsdb-idlc.in @@ -551,20 +551,20 @@ static void @@ -3462,6 +3765,15 @@ index 61cded16d3..78ebf2dc14 100755 print("}") # Index table related functions +@@ -1272,7 +1265,7 @@ struct ovsdb_idl_cursor + struct ovsdb_idl_index *index, const struct %(s)s *target) + { + ovs_assert(index->table->class_ == &%(p)stable_%(tl)s); +- return ovsdb_idl_cursor_first_ge(index, &target->header_); ++ return ovsdb_idl_cursor_first_ge(index, target ? &target->header_ : NULL); + } + + struct %(s)s * @@ -1309,8 +1302,8 @@ struct %(s)s * i = 0; diff --git a/SPECS/openvswitch2.16.spec b/SPECS/openvswitch2.16.spec index 39ef635..816847f 100644 --- a/SPECS/openvswitch2.16.spec +++ b/SPECS/openvswitch2.16.spec @@ -57,7 +57,7 @@ Summary: Open vSwitch Group: System Environment/Daemons daemon/database/utilities URL: http://www.openvswitch.org/ Version: 2.16.0 -Release: 51%{?dist} +Release: 52%{?dist} # Nearly all of openvswitch is ASL 2.0. The bugtool is LGPLv2+, and the # lib/sflow*.[ch] files are SISSL @@ -699,6 +699,17 @@ exit 0 %endif %changelog +* Wed Feb 16 2022 Open vSwitch CI - 2.16.0-52 +- Merging upstream branch-2.16 [RH git: bba08b5363] + Commit list: + 8e23c06f24 dpif-netdev-dpcls: Make subtable reprobe thread-safe. + ac0e3dd3ba ci: Fix typo in variable name. + fc25e0397a dp-packet: Ensure packet base is always non-NULL. + dbae56e702 bfd: lldp: stp: Fix misaligned packet field access. + ee17b06cf9 ovsdb-idlc: Avoid accessing member within NULL idl index cursors. + 1d799a5d17 stopwatch: Fix buffer underflow when computing percentiles. + + * Wed Feb 09 2022 Open vSwitch CI - 2.16.0-51 - Merging upstream branch-2.16 [RH git: 7b6570c65f] Commit list: