diff --git a/SOURCES/openvswitch-2.15.0.patch b/SOURCES/openvswitch-2.15.0.patch index a33b00a..9026005 100644 --- a/SOURCES/openvswitch-2.15.0.patch +++ b/SOURCES/openvswitch-2.15.0.patch @@ -19729,8 +19729,25 @@ index b7d577870d..fe24f9abdf 100644 "cannot use CPU flag based optimizations"); return false; } +diff --git a/lib/dpif-netdev-private.h b/lib/dpif-netdev-private.h +index 4fda1220b0..45360dc3e1 100644 +--- a/lib/dpif-netdev-private.h ++++ b/lib/dpif-netdev-private.h +@@ -80,8 +80,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.c b/lib/dpif-netdev.c -index 4381c618f1..a07a34b89a 100644 +index 4381c618f1..fe0a81862a 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -279,8 +279,9 @@ static bool dpcls_lookup(struct dpcls *cls, @@ -19769,7 +19786,7 @@ index 4381c618f1..a07a34b89a 100644 if (errno != 0 || new_prio > UINT8_MAX) { unixctl_command_reply_error(conn, "error converting priority, use integer in range 0-255\n"); -@@ -1364,58 +1367,43 @@ dpif_netdev_subtable_lookup_set(struct unixctl_conn *conn, int argc, +@@ -1364,58 +1367,45 @@ dpif_netdev_subtable_lookup_set(struct unixctl_conn *conn, int argc, return; } @@ -19791,31 +19808,31 @@ index 4381c618f1..a07a34b89a 100644 - "please specify an existing datapath"); - return; - } -+ SHASH_FOR_EACH (node, &dp_netdevs) { -+ struct dp_netdev *dp = node->data; - +- - /* Get PMD threads list, required to get DPCLS instances. */ - size_t n; - uint32_t lookup_dpcls_changed = 0; - uint32_t lookup_subtable_changed = 0; - struct dp_netdev_pmd_thread **pmd_list; - sorted_poll_thread_list(dp, &pmd_list, &n); ++ SHASH_FOR_EACH (node, &dp_netdevs) { ++ struct dp_netdev *dp = node->data; + +- /* take port mutex as HMAP iters over them. */ +- ovs_mutex_lock(&dp->port_mutex); + /* Get PMD threads list, required to get DPCLS instances. */ + size_t n; + struct dp_netdev_pmd_thread **pmd_list; + sorted_poll_thread_list(dp, &pmd_list, &n); -- /* take port mutex as HMAP iters over them. */ -- ovs_mutex_lock(&dp->port_mutex); -+ /* take port mutex as HMAP iters over them. */ -+ ovs_mutex_lock(&dp->port_mutex); - - for (size_t i = 0; i < n; i++) { - struct dp_netdev_pmd_thread *pmd = pmd_list[i]; - if (pmd->core_id == NON_PMD_CORE_ID) { - continue; - } -- ++ /* take port mutex as HMAP iters over them. */ ++ ovs_mutex_lock(&dp->port_mutex); + - struct dp_netdev_port *port = NULL; - HMAP_FOR_EACH (port, node, &dp->ports) { - odp_port_t in_port = port->port_no; @@ -19838,7 +19855,9 @@ index 4381c618f1..a07a34b89a 100644 + 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; @@ -19856,7 +19875,7 @@ index 4381c618f1..a07a34b89a 100644 ovs_mutex_unlock(&dp_netdev_mutex); struct ds reply = DS_EMPTY_INITIALIZER; -@@ -1644,8 +1632,8 @@ dpif_netdev_init(void) +@@ -1644,8 +1634,8 @@ dpif_netdev_init(void) 0, 1, dpif_netdev_bond_show, NULL); unixctl_command_register("dpif-netdev/subtable-lookup-prio-set", @@ -19867,7 +19886,7 @@ index 4381c618f1..a07a34b89a 100644 NULL); unixctl_command_register("dpif-netdev/subtable-lookup-prio-get", "", 0, 0, dpif_netdev_subtable_lookup_get, -@@ -2569,18 +2557,6 @@ mark_to_flow_disassociate(struct dp_netdev_pmd_thread *pmd, +@@ -2569,18 +2559,6 @@ mark_to_flow_disassociate(struct dp_netdev_pmd_thread *pmd, return ret; } @@ -19886,7 +19905,7 @@ index 4381c618f1..a07a34b89a 100644 static struct dp_netdev_flow * mark_to_flow_find(const struct dp_netdev_pmd_thread *pmd, const uint32_t mark) -@@ -2659,7 +2635,8 @@ dp_netdev_flow_offload_put(struct dp_flow_offload_item *offload) +@@ -2659,7 +2637,8 @@ dp_netdev_flow_offload_put(struct dp_flow_offload_item *offload) struct dp_netdev_flow *flow = offload->flow; odp_port_t in_port = flow->flow.in_port.odp_port; const char *dpif_type_str = dpif_normalize_type(pmd->dp->class->type); @@ -19896,7 +19915,7 @@ index 4381c618f1..a07a34b89a 100644 struct offload_info info; struct netdev *port; uint32_t mark; -@@ -2671,7 +2648,6 @@ dp_netdev_flow_offload_put(struct dp_flow_offload_item *offload) +@@ -2671,7 +2650,6 @@ dp_netdev_flow_offload_put(struct dp_flow_offload_item *offload) if (modification) { mark = flow->mark; @@ -19904,7 +19923,7 @@ index 4381c618f1..a07a34b89a 100644 } else { /* * If a mega flow has already been offloaded (from other PMD -@@ -2798,10 +2774,9 @@ queue_netdev_flow_del(struct dp_netdev_pmd_thread *pmd, +@@ -2798,10 +2776,9 @@ queue_netdev_flow_del(struct dp_netdev_pmd_thread *pmd, static void queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd, struct dp_netdev_flow *flow, struct match *match, @@ -19916,7 +19935,7 @@ index 4381c618f1..a07a34b89a 100644 if (!netdev_is_flow_api_enabled()) { return; -@@ -2814,11 +2789,6 @@ queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd, +@@ -2814,11 +2791,6 @@ queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd, ovsthread_once_done(&offload_thread_once); } @@ -19928,7 +19947,7 @@ index 4381c618f1..a07a34b89a 100644 offload = dp_netdev_alloc_flow_offload(pmd, flow, op); offload->match = *match; offload->actions = xmalloc(actions_len); -@@ -3691,7 +3661,8 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd, +@@ -3691,7 +3663,8 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd, cmap_insert(&pmd->flow_table, CONST_CAST(struct cmap_node *, &flow->node), dp_netdev_flow_hash(&flow->ufid)); @@ -19938,7 +19957,7 @@ index 4381c618f1..a07a34b89a 100644 if (OVS_UNLIKELY(!VLOG_DROP_DBG((&upcall_rl)))) { struct ds ds = DS_EMPTY_INITIALIZER; -@@ -3778,7 +3749,8 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd, +@@ -3778,7 +3751,8 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd, ovsrcu_set(&netdev_flow->actions, new_actions); queue_netdev_flow_put(pmd, netdev_flow, match, @@ -19948,7 +19967,7 @@ index 4381c618f1..a07a34b89a 100644 if (stats) { get_dpif_flow_status(pmd->dp, netdev_flow, stats, NULL); -@@ -3834,6 +3806,15 @@ dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put) +@@ -3834,6 +3808,15 @@ dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put) return error; } @@ -19964,7 +19983,7 @@ index 4381c618f1..a07a34b89a 100644 if (put->ufid) { ufid = *put->ufid; } else { -@@ -4158,8 +4139,10 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute) +@@ -4158,8 +4141,10 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute) flow_hash_5tuple(execute->flow, 0)); } @@ -19977,7 +19996,7 @@ index 4381c618f1..a07a34b89a 100644 dp_netdev_execute_actions(pmd, &pp, false, execute->flow, execute->actions, execute->actions_len); dp_netdev_pmd_flush_output_packets(pmd, true); -@@ -4169,6 +4152,24 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute) +@@ -4169,6 +4154,24 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute) dp_netdev_pmd_unref(pmd); } @@ -20002,7 +20021,7 @@ index 4381c618f1..a07a34b89a 100644 return 0; } -@@ -4878,6 +4879,12 @@ struct rr_numa { +@@ -4878,6 +4881,12 @@ struct rr_numa { bool idx_inc; }; @@ -20015,7 +20034,7 @@ index 4381c618f1..a07a34b89a 100644 static struct rr_numa * rr_numa_list_lookup(struct rr_numa_list *rr, int numa_id) { -@@ -5149,7 +5156,6 @@ reload_affected_pmds(struct dp_netdev *dp) +@@ -5149,7 +5158,6 @@ reload_affected_pmds(struct dp_netdev *dp) CMAP_FOR_EACH (pmd, node, &dp->poll_threads) { if (pmd->need_reload) { @@ -20023,7 +20042,7 @@ index 4381c618f1..a07a34b89a 100644 dp_netdev_reload_pmd__(pmd); } } -@@ -5590,10 +5596,17 @@ get_dry_run_variance(struct dp_netdev *dp, uint32_t *core_list, +@@ -5590,10 +5598,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); @@ -20044,7 +20063,7 @@ index 4381c618f1..a07a34b89a 100644 goto cleanup; } -@@ -6203,12 +6216,14 @@ dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_, +@@ -6203,12 +6218,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) { @@ -20063,7 +20082,7 @@ index 4381c618f1..a07a34b89a 100644 } /* Drain the bucket for all the packets, if possible. */ -@@ -6226,8 +6241,8 @@ dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_, +@@ -6226,8 +6243,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++) { @@ -20074,7 +20093,7 @@ index 4381c618f1..a07a34b89a 100644 exceeded_band[i] = m; } } -@@ -6246,8 +6261,8 @@ dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_, +@@ -6246,8 +6263,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.) */ @@ -20085,7 +20104,7 @@ index 4381c618f1..a07a34b89a 100644 exceeded_band[i] = m; } } -@@ -6329,16 +6344,14 @@ dpif_netdev_meter_set(struct dpif *dpif, ofproto_meter_id meter_id, +@@ -6329,16 +6346,14 @@ dpif_netdev_meter_set(struct dpif *dpif, ofproto_meter_id meter_id, config->bands[i].burst_size = config->bands[i].rate; } @@ -20107,7 +20126,7 @@ index 4381c618f1..a07a34b89a 100644 if (band_max_delta_t > meter->max_delta_t) { meter->max_delta_t = band_max_delta_t; } -@@ -8493,6 +8506,7 @@ const struct dpif_class dpif_netdev_class = { +@@ -8493,6 +8508,7 @@ const struct dpif_class dpif_netdev_class = { NULL, /* ct_timeout_policy_dump_next */ NULL, /* ct_timeout_policy_dump_done */ dpif_netdev_ct_get_timeout_policy_name, @@ -20115,6 +20134,48 @@ index 4381c618f1..a07a34b89a 100644 dpif_netdev_ipf_set_enabled, dpif_netdev_ipf_set_min_frag, dpif_netdev_ipf_set_max_nfrags, +@@ -8681,9 +8697,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) */ +@@ -8712,6 +8731,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) +@@ -8724,10 +8747,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 ceb56c6851..16a5838019 100644 --- a/lib/dpif-netlink.c diff --git a/SPECS/openvswitch2.15.spec b/SPECS/openvswitch2.15.spec index d45fec8..c5043d7 100644 --- a/SPECS/openvswitch2.15.spec +++ b/SPECS/openvswitch2.15.spec @@ -57,7 +57,7 @@ Summary: Open vSwitch Group: System Environment/Daemons daemon/database/utilities URL: http://www.openvswitch.org/ Version: 2.15.0 -Release: 73%{?dist} +Release: 74%{?dist} # Nearly all of openvswitch is ASL 2.0. The bugtool is LGPLv2+, and the # lib/sflow*.[ch] files are SISSL @@ -702,6 +702,12 @@ exit 0 %endif %changelog +* Tue Feb 15 2022 Open vSwitch CI - 2.15.0-74 +- Merging upstream branch-2.15 [RH git: 84306060e6] + Commit list: + 9e2af615c1 dpif-netdev-dpcls: Make subtable reprobe thread-safe. + + * Tue Feb 15 2022 Open vSwitch CI - 2.15.0-73 - Merging upstream branch-2.15 [RH git: 0b62621839] Commit list: