From 70dcb24c1c796d4133e03549be804030132b5544 Mon Sep 17 00:00:00 2001 From: Open vSwitch CI Date: Nov 03 2022 04:41:45 +0000 Subject: Import openvswitch2.17-2.17.0-61 from Fast DataPath --- diff --git a/SOURCES/openvswitch-2.17.0.patch b/SOURCES/openvswitch-2.17.0.patch index 864a2a4..d744d04 100644 --- a/SOURCES/openvswitch-2.17.0.patch +++ b/SOURCES/openvswitch-2.17.0.patch @@ -50766,6 +50766,21 @@ index c4790ee6ba..0a89626cc3 100644 if (!(cm >= cm_stubs && cm < &cm_stubs[n_cm_stubs])) { free(cm); } +diff --git a/lib/cmap.c b/lib/cmap.c +index c9eef3f4ae..8ca893b0b2 100644 +--- a/lib/cmap.c ++++ b/lib/cmap.c +@@ -598,7 +598,9 @@ cmap_set_bucket(struct cmap_bucket *b, int i, + uint32_t c; + + atomic_read_explicit(&b->counter, &c, memory_order_acquire); +- atomic_store_explicit(&b->counter, c + 1, memory_order_release); ++ atomic_store_explicit(&b->counter, c + 1, memory_order_relaxed); ++ /* Need to make sure setting hash is not moved up before counter update. */ ++ atomic_thread_fence(memory_order_release); + ovsrcu_set(&b->nodes[i].next, node); /* Also atomic. */ + b->hashes[i] = hash; + atomic_store_explicit(&b->counter, c + 2, memory_order_release); diff --git a/lib/cmap.h b/lib/cmap.h index c502d23112..72e2ec5f71 100644 --- a/lib/cmap.h @@ -51476,7 +51491,7 @@ index 66016eb099..7425dd44e7 100644 /* Statistics. */ struct dp_netdev_flow_stats stats; diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c -index 9f35713ef5..3d9d8929f7 100644 +index 9f35713ef5..24b64b1686 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -93,7 +93,8 @@ VLOG_DEFINE_THIS_MODULE(dpif_netdev); @@ -51489,7 +51504,15 @@ index 9f35713ef5..3d9d8929f7 100644 #define MIN_TO_MSEC 60000 #define FLOW_DUMP_MAX_BATCH 50 -@@ -1932,13 +1933,13 @@ static void +@@ -430,7 +431,6 @@ struct dp_netdev_rxq { + unsigned intrvl_idx; /* Write index for 'cycles_intrvl'. */ + struct dp_netdev_pmd_thread *pmd; /* pmd thread that polls this queue. */ + bool is_vhost; /* Is rxq of a vhost port. */ +- bool hw_miss_api_supported; /* hw_miss_packet_recover() supported.*/ + + /* Counters of cycles spent successfully polling and processing pkts. */ + atomic_ullong cycles[RXQ_N_CYCLES]; +@@ -1932,13 +1932,13 @@ static void dp_netdev_free(struct dp_netdev *dp) OVS_REQUIRES(dp_netdev_mutex) { @@ -51505,7 +51528,7 @@ index 9f35713ef5..3d9d8929f7 100644 do_del_port(dp, port); } ovs_rwlock_unlock(&dp->port_rwlock); -@@ -3006,7 +3007,7 @@ static void +@@ -3006,7 +3006,7 @@ static void queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd, struct dp_netdev_flow *flow, struct match *match, const struct nlattr *actions, size_t actions_len, @@ -51514,7 +51537,7 @@ index 9f35713ef5..3d9d8929f7 100644 { struct dp_offload_thread_item *item; struct dp_offload_flow_item *flow_offload; -@@ -3021,7 +3022,7 @@ queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd, +@@ -3021,7 +3021,7 @@ queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd, flow_offload->actions = xmalloc(actions_len); memcpy(flow_offload->actions, actions, actions_len); flow_offload->actions_len = actions_len; @@ -51523,7 +51546,7 @@ index 9f35713ef5..3d9d8929f7 100644 item->timestamp = pmd->ctx.now; dp_netdev_offload_flow_enqueue(item); -@@ -4095,6 +4096,7 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd, +@@ -4095,6 +4095,7 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd, flow->dead = false; flow->batch = NULL; flow->mark = INVALID_FLOW_MARK; @@ -51531,7 +51554,7 @@ index 9f35713ef5..3d9d8929f7 100644 *CONST_CAST(unsigned *, &flow->pmd_id) = pmd->core_id; *CONST_CAST(struct flow *, &flow->flow) = match->flow; *CONST_CAST(ovs_u128 *, &flow->ufid) = *ufid; -@@ -4129,7 +4131,7 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd, +@@ -4129,7 +4130,7 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd, } queue_netdev_flow_put(pmd, flow, match, actions, actions_len, @@ -51540,7 +51563,7 @@ index 9f35713ef5..3d9d8929f7 100644 log_netdev_flow_change(flow, match, NULL, actions, actions_len); return flow; -@@ -4171,7 +4173,7 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd, +@@ -4171,7 +4172,7 @@ 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, @@ -51549,7 +51572,7 @@ index 9f35713ef5..3d9d8929f7 100644 DP_NETDEV_FLOW_OFFLOAD_OP_MOD); log_netdev_flow_change(netdev_flow, match, old_actions, put->actions, put->actions_len); -@@ -4778,8 +4780,8 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config) +@@ -4778,8 +4779,8 @@ 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; @@ -51560,7 +51583,7 @@ index 9f35713ef5..3d9d8929f7 100644 bool log_autolb = false; enum sched_assignment_type pmd_rxq_assign_type; -@@ -4880,8 +4882,12 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config) +@@ -4880,8 +4881,12 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config) struct pmd_auto_lb *pmd_alb = &dp->pmd_alb; @@ -51575,7 +51598,7 @@ index 9f35713ef5..3d9d8929f7 100644 /* Input is in min, convert it to msec. */ rebalance_intvl = -@@ -4894,21 +4900,21 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config) +@@ -4894,21 +4899,21 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config) log_autolb = true; } @@ -51603,7 +51626,7 @@ index 9f35713ef5..3d9d8929f7 100644 if (rebalance_load > 100) { rebalance_load = ALB_LOAD_THRESHOLD; } -@@ -4916,7 +4922,7 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config) +@@ -4916,7 +4921,7 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config) if (rebalance_load != cur_rebalance_load) { atomic_store_relaxed(&pmd_alb->rebalance_load_thresh, rebalance_load); @@ -51612,7 +51635,15 @@ index 9f35713ef5..3d9d8929f7 100644 rebalance_load); log_autolb = true; } -@@ -5684,23 +5690,28 @@ sched_numa_list_put_in_place(struct sched_numa_list *numa_list) +@@ -5425,7 +5430,6 @@ port_reconfigure(struct dp_netdev_port *port) + + port->rxqs[i].port = port; + port->rxqs[i].is_vhost = !strncmp(port->type, "dpdkvhost", 9); +- port->rxqs[i].hw_miss_api_supported = true; + + err = netdev_rxq_open(netdev, &port->rxqs[i].rx, i); + if (err) { +@@ -5684,23 +5688,28 @@ sched_numa_list_put_in_place(struct sched_numa_list *numa_list) } } @@ -51646,7 +51677,7 @@ index 9f35713ef5..3d9d8929f7 100644 rxq->pmd->numa_id != netdev_get_numa_id(rxq->port->netdev)) { return true; -@@ -6000,10 +6011,10 @@ sched_numa_list_schedule(struct sched_numa_list *numa_list, +@@ -6000,10 +6009,10 @@ sched_numa_list_schedule(struct sched_numa_list *numa_list, /* Find any numa with available PMDs. */ for (int j = 0; j < n_numa; j++) { numa = sched_numa_list_next(numa_list, last_cross_numa); @@ -51658,7 +51689,7 @@ index 9f35713ef5..3d9d8929f7 100644 numa = NULL; } } -@@ -6111,7 +6122,7 @@ sched_numa_list_variance(struct sched_numa_list *numa_list) +@@ -6111,7 +6120,7 @@ sched_numa_list_variance(struct sched_numa_list *numa_list) * pmd_rebalance_dry_run() can be avoided when it is not needed. */ static bool @@ -51667,7 +51698,7 @@ index 9f35713ef5..3d9d8929f7 100644 OVS_REQ_RDLOCK(dp->port_rwlock) { struct dp_netdev_pmd_thread *pmd; -@@ -6342,11 +6353,11 @@ pmd_remove_stale_ports(struct dp_netdev *dp, +@@ -6342,11 +6351,11 @@ pmd_remove_stale_ports(struct dp_netdev *dp, OVS_EXCLUDED(pmd->port_mutex) OVS_REQ_RDLOCK(dp->port_rwlock) { @@ -51682,7 +51713,7 @@ index 9f35713ef5..3d9d8929f7 100644 struct dp_netdev_port *port = poll->rxq->port; if (port->need_reconfigure -@@ -6354,7 +6365,7 @@ pmd_remove_stale_ports(struct dp_netdev *dp, +@@ -6354,7 +6363,7 @@ pmd_remove_stale_ports(struct dp_netdev *dp, dp_netdev_del_rxq_from_pmd(pmd, poll); } } @@ -51691,7 +51722,7 @@ index 9f35713ef5..3d9d8929f7 100644 struct dp_netdev_port *port = tx->port; if (port->need_reconfigure -@@ -6430,8 +6441,7 @@ reconfigure_datapath(struct dp_netdev *dp) +@@ -6430,8 +6439,7 @@ reconfigure_datapath(struct dp_netdev *dp) /* We only reconfigure the ports that we determined above, because they're * not being used by any pmd thread at the moment. If a port fails to * reconfigure we remove it from the datapath. */ @@ -51701,7 +51732,7 @@ index 9f35713ef5..3d9d8929f7 100644 int err; if (!port->need_reconfigure) { -@@ -6487,10 +6497,10 @@ reconfigure_datapath(struct dp_netdev *dp) +@@ -6487,10 +6495,10 @@ reconfigure_datapath(struct dp_netdev *dp) } CMAP_FOR_EACH (pmd, node, &dp->poll_threads) { @@ -51714,7 +51745,7 @@ index 9f35713ef5..3d9d8929f7 100644 if (poll->rxq->pmd != pmd) { dp_netdev_del_rxq_from_pmd(pmd, poll); -@@ -6682,7 +6692,7 @@ dpif_netdev_run(struct dpif *dpif) +@@ -6682,7 +6690,7 @@ dpif_netdev_run(struct dpif *dpif) if (pmd_rebalance && !dp_netdev_is_reconf_required(dp) && !ports_require_restart(dp) && @@ -51723,7 +51754,7 @@ index 9f35713ef5..3d9d8929f7 100644 pmd_rebalance_dry_run(dp)) { VLOG_INFO("PMD auto load balance dry run. " "Requesting datapath reconfigure."); -@@ -7364,15 +7374,15 @@ static struct dp_netdev_pmd_thread * +@@ -7364,15 +7372,15 @@ static struct dp_netdev_pmd_thread * dp_netdev_get_pmd(struct dp_netdev *dp, unsigned core_id) { struct dp_netdev_pmd_thread *pmd; @@ -51745,7 +51776,7 @@ index 9f35713ef5..3d9d8929f7 100644 } /* Sets the 'struct dp_netdev_pmd_thread' for non-pmd threads. */ -@@ -7505,6 +7515,7 @@ dp_netdev_destroy_pmd(struct dp_netdev_pmd_thread *pmd) +@@ -7505,6 +7513,7 @@ dp_netdev_destroy_pmd(struct dp_netdev_pmd_thread *pmd) seq_destroy(pmd->reload_seq); ovs_mutex_destroy(&pmd->port_mutex); ovs_mutex_destroy(&pmd->bond_mutex); @@ -51753,6 +51784,31 @@ index 9f35713ef5..3d9d8929f7 100644 free(pmd); } +@@ -8020,17 +8029,15 @@ dp_netdev_hw_flow(const struct dp_netdev_pmd_thread *pmd, + #ifdef ALLOW_EXPERIMENTAL_API /* Packet restoration API required. */ + /* Restore the packet if HW processing was terminated before completion. */ + struct dp_netdev_rxq *rxq = pmd->ctx.last_rxq; ++ bool miss_api_supported; + +- if (rxq->hw_miss_api_supported) { ++ atomic_read_relaxed(&rxq->port->netdev->hw_info.miss_api_supported, ++ &miss_api_supported); ++ if (miss_api_supported) { + int err = netdev_hw_miss_packet_recover(rxq->port->netdev, packet); +- if (err) { +- if (err != EOPNOTSUPP) { +- COVERAGE_INC(datapath_drop_hw_miss_recover); +- return -1; +- } else { +- /* API unsupported by the port; avoid subsequent calls. */ +- rxq->hw_miss_api_supported = false; +- } ++ if (err && err != EOPNOTSUPP) { ++ COVERAGE_INC(datapath_drop_hw_miss_recover); ++ return -1; + } + } + #endif diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 71e35ccdda..484545cfb8 100644 --- a/lib/dpif-netlink.c @@ -52521,10 +52577,34 @@ index a024dc5e58..4bff7b017f 100644 ovs_list_remove(&chassis->list); lldpd_chassis_cleanup(chassis, 1); diff --git a/lib/mac-learning.c b/lib/mac-learning.c -index 3fcd7d9b77..a60794fb26 100644 +index 3fcd7d9b77..5932e2709d 100644 --- a/lib/mac-learning.c +++ b/lib/mac-learning.c -@@ -244,10 +244,10 @@ void +@@ -176,12 +176,18 @@ get_lru(struct mac_learning *ml, struct mac_entry **e) + OVS_REQ_RDLOCK(ml->rwlock) + { + if (!ovs_list_is_empty(&ml->lrus)) { +- *e = mac_entry_from_lru_node(ml->lrus.next); +- return true; +- } else { +- *e = NULL; +- return false; ++ struct mac_entry *entry; ++ ++ LIST_FOR_EACH (entry, lru_node, &ml->lrus) { ++ if (entry->expires != MAC_ENTRY_AGE_STATIC_ENTRY) { ++ *e = entry; ++ return true; ++ } ++ } + } ++ ++ *e = NULL; ++ return false; + } + + static unsigned int +@@ -244,10 +250,10 @@ void mac_learning_unref(struct mac_learning *ml) { if (ml && ovs_refcount_unref(&ml->ref_cnt) == 1) { @@ -52537,6 +52617,35 @@ index 3fcd7d9b77..a60794fb26 100644 mac_learning_expire(ml, e); } hmap_destroy(&ml->table); +@@ -618,25 +624,10 @@ mac_learning_expire(struct mac_learning *ml, struct mac_entry *e) + void + mac_learning_flush(struct mac_learning *ml) + { +- struct mac_entry *e, *first_static_mac = NULL; +- +- while (get_lru(ml, &e) && (e != first_static_mac)) { +- +- /* Static mac should not be evicted. */ +- if (MAC_ENTRY_AGE_STATIC_ENTRY == e->expires) { +- +- /* Make note of first static-mac encountered, so that this while +- * loop will break on visting this mac again via get_lru(). */ +- if (!first_static_mac) { +- first_static_mac = e; +- } ++ struct mac_entry *e; + +- /* Remove from lru head and append it to tail. */ +- ovs_list_remove(&e->lru_node); +- ovs_list_push_back(&ml->lrus, &e->lru_node); +- } else { +- mac_learning_expire(ml, e); +- } ++ while (get_lru(ml, &e)) { ++ mac_learning_expire(ml, e); + } + hmap_shrink(&ml->table); + } diff --git a/lib/match.c b/lib/match.c index 2ad03e044e..0b9dc4278c 100644 --- a/lib/match.c @@ -52646,7 +52755,7 @@ index 482400d8d1..ca3f2431ea 100644 count = umem_pool_count(&pool->umem_info->mpool); ovs_assert(count + pool->lost_in_rings <= NUM_FRAMES); diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c -index b6b29c75e3..e28e397d7e 100644 +index b6b29c75e3..39a1fd388d 100644 --- a/lib/netdev-dpdk.c +++ b/lib/netdev-dpdk.c @@ -622,9 +622,9 @@ dpdk_mp_full(const struct rte_mempool *mp) OVS_REQUIRES(dpdk_mp_mutex) @@ -52862,7 +52971,7 @@ index b6b29c75e3..e28e397d7e 100644 + cnt = dpdk_copy_batch_to_mbuf(netdev, batch); + stats->tx_failure_drops += pkt_cnt - cnt; + pkt_cnt = cnt; - } ++ } + + /* Drop oversized packets. */ + cnt = netdev_dpdk_filter_packet_len(dev, pkts, pkt_cnt); @@ -52874,7 +52983,7 @@ index b6b29c75e3..e28e397d7e 100644 + cnt = netdev_dpdk_prep_hwol_batch(dev, pkts, pkt_cnt); + stats->tx_invalid_hwol_drops += pkt_cnt - cnt; + pkt_cnt = cnt; -+ } + } + + /* Apply Quality of Service policy. */ + cnt = netdev_dpdk_qos_run(dev, pkts, pkt_cnt, true); @@ -52998,9 +53107,9 @@ index b6b29c75e3..e28e397d7e 100644 - dpdk_do_tx_copy(netdev, qid, batch); - dp_packet_delete_batch(batch, true); - } else { -+ dropped = batch_cnt - cnt; -+ -+ dropped += netdev_dpdk_eth_tx_burst(dev, qid, pkts, cnt); ++ dropped = netdev_dpdk_eth_tx_burst(dev, qid, pkts, cnt); ++ stats.tx_failure_drops += dropped; ++ dropped += batch_cnt - cnt; + if (OVS_UNLIKELY(dropped)) { struct netdev_dpdk_sw_stats *sw_stats = dev->sw_stats; - int dropped; @@ -53071,7 +53180,7 @@ index b6b29c75e3..e28e397d7e 100644 free(queue); } diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c -index 620a451dec..1b9c2874ac 100644 +index 620a451dec..5aa8a8ca3c 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -247,6 +247,14 @@ enum { @@ -53110,7 +53219,26 @@ index 620a451dec..1b9c2874ac 100644 nl_msg_end_nested(request, offset); nl_msg_end_nested(request, act_offset); } -@@ -5331,11 +5342,11 @@ static void +@@ -2970,12 +2981,18 @@ netdev_linux_set_qos(struct netdev *netdev_, + /* Delete existing qdisc. */ + error = tc_del_qdisc(netdev_); + if (error) { ++ VLOG_WARN_RL(&rl, "%s: Failed to delete existing qdisc: %s", ++ netdev_get_name(netdev_), ovs_strerror(error)); + goto exit; + } + ovs_assert(netdev->tc == NULL); + + /* Install new qdisc. */ + error = new_ops->tc_install(netdev_, details); ++ if (error) { ++ VLOG_WARN_RL(&rl, "%s: Failed to install new qdisc: %s", ++ netdev_get_name(netdev_), ovs_strerror(error)); ++ } + ovs_assert((error == 0) == (netdev->tc != NULL)); + } + +@@ -5331,11 +5348,11 @@ static void hfsc_tc_destroy(struct tc *tc) { struct hfsc *hfsc; @@ -53124,7 +53252,24 @@ index 620a451dec..1b9c2874ac 100644 hmap_remove(&hfsc->tc.queues, &hc->tc_queue.hmap_node); free(hc); } -@@ -6295,7 +6306,14 @@ get_stats_via_netlink(const struct netdev *netdev_, struct netdev_stats *stats) +@@ -5966,13 +5983,12 @@ tc_del_qdisc(struct netdev *netdev_) + if (!tcmsg) { + return ENODEV; + } +- tcmsg->tcm_handle = tc_make_handle(1, 0); + tcmsg->tcm_parent = TC_H_ROOT; + + error = tc_transact(&request, NULL); +- if (error == EINVAL) { +- /* EINVAL probably means that the default qdisc was in use, in which +- * case we've accomplished our purpose. */ ++ if (error == EINVAL || error == ENOENT) { ++ /* EINVAL or ENOENT probably means that the default qdisc was in use, ++ * in which case we've accomplished our purpose. */ + error = 0; + } + if (!error && netdev->tc) { +@@ -6295,7 +6311,14 @@ get_stats_via_netlink(const struct netdev *netdev_, struct netdev_stats *stats) if (ofpbuf_try_pull(reply, NLMSG_HDRLEN + sizeof(struct ifinfomsg))) { const struct nlattr *a = nl_attr_find(reply, 0, IFLA_STATS64); if (a && nl_attr_get_size(a) >= sizeof(struct rtnl_link_stats64)) { @@ -53140,7 +53285,7 @@ index 620a451dec..1b9c2874ac 100644 error = 0; } else { a = nl_attr_find(reply, 0, IFLA_STATS); -@@ -6411,6 +6429,9 @@ netdev_linux_update_via_netlink(struct netdev_linux *netdev) +@@ -6411,6 +6434,9 @@ netdev_linux_update_via_netlink(struct netdev_linux *netdev) if (netdev_linux_netnsid_is_remote(netdev)) { nl_msg_put_u32(&request, IFLA_IF_NETNSID, netdev->netnsid); } @@ -53731,11 +53876,81 @@ index 9845e8d3fe..93321989a9 100644 } } +diff --git a/lib/netdev-offload.c b/lib/netdev-offload.c +index fb108c0d50..eea8fadc0e 100644 +--- a/lib/netdev-offload.c ++++ b/lib/netdev-offload.c +@@ -182,6 +182,7 @@ netdev_assign_flow_api(struct netdev *netdev) + CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) { + if (!rfa->flow_api->init_flow_api(netdev)) { + ovs_refcount_ref(&rfa->refcnt); ++ atomic_store_relaxed(&netdev->hw_info.miss_api_supported, true); + ovsrcu_set(&netdev->flow_api, rfa->flow_api); + VLOG_INFO("%s: Assigned flow API '%s'.", + netdev_get_name(netdev), rfa->flow_api->type); +@@ -190,6 +191,7 @@ netdev_assign_flow_api(struct netdev *netdev) + VLOG_DBG("%s: flow API '%s' is not suitable.", + netdev_get_name(netdev), rfa->flow_api->type); + } ++ atomic_store_relaxed(&netdev->hw_info.miss_api_supported, false); + VLOG_INFO("%s: No suitable flow API found.", netdev_get_name(netdev)); + + return -1; +@@ -263,12 +265,28 @@ int + netdev_hw_miss_packet_recover(struct netdev *netdev, + struct dp_packet *packet) + { +- const struct netdev_flow_api *flow_api = +- ovsrcu_get(const struct netdev_flow_api *, &netdev->flow_api); ++ const struct netdev_flow_api *flow_api; ++ bool miss_api_supported; ++ int rv; ++ ++ atomic_read_relaxed(&netdev->hw_info.miss_api_supported, ++ &miss_api_supported); ++ if (!miss_api_supported) { ++ return EOPNOTSUPP; ++ } ++ ++ flow_api = ovsrcu_get(const struct netdev_flow_api *, &netdev->flow_api); ++ if (!flow_api || !flow_api->hw_miss_packet_recover) { ++ return EOPNOTSUPP; ++ } ++ ++ rv = flow_api->hw_miss_packet_recover(netdev, packet); ++ if (rv == EOPNOTSUPP) { ++ /* API unsupported by the port; avoid subsequent calls. */ ++ atomic_store_relaxed(&netdev->hw_info.miss_api_supported, false); ++ } + +- return (flow_api && flow_api->hw_miss_packet_recover) +- ? flow_api->hw_miss_packet_recover(netdev, packet) +- : EOPNOTSUPP; ++ return rv; + } + + int diff --git a/lib/netdev-offload.h b/lib/netdev-offload.h -index 8237a85ddb..93eb2df48b 100644 +index 8237a85ddb..13ab06d116 100644 --- a/lib/netdev-offload.h +++ b/lib/netdev-offload.h -@@ -65,9 +65,6 @@ struct netdev_flow_dump { +@@ -20,6 +20,7 @@ + + #include "openvswitch/netdev.h" + #include "openvswitch/types.h" ++#include "ovs-atomic.h" + #include "ovs-rcu.h" + #include "ovs-thread.h" + #include "packets.h" +@@ -45,6 +46,7 @@ struct ovs_action_push_tnl; + /* Offload-capable (HW) netdev information */ + struct netdev_hw_info { + bool oor; /* Out of Offload Resources ? */ ++ atomic_bool miss_api_supported; /* hw_miss_packet_recover() supported.*/ + int offload_count; /* Pending (non-offloaded) flow count */ + int pending_count; /* Offloaded flow count */ + OVSRCU_TYPE(void *) offload_data; /* Offload metadata. */ +@@ -65,9 +67,6 @@ struct netdev_flow_dump { /* Flow offloading. */ struct offload_info { @@ -53746,7 +53961,7 @@ index 8237a85ddb..93eb2df48b 100644 * sync with datapath recirc ids. */ diff --git a/lib/netdev.c b/lib/netdev.c -index 8305f6c427..ce0d4117ac 100644 +index 8305f6c427..c797783782 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -387,25 +387,30 @@ netdev_open(const char *name, const char *type, struct netdev **netdevp) @@ -53798,10 +54013,27 @@ index 8305f6c427..ce0d4117ac 100644 } } +@@ -426,6 +431,7 @@ netdev_open(const char *name, const char *type, struct netdev **netdevp) + seq_read(netdev->reconfigure_seq); + ovsrcu_set(&netdev->flow_api, NULL); + netdev->hw_info.oor = false; ++ atomic_init(&netdev->hw_info.miss_api_supported, false); + netdev->node = shash_add(&netdev_shash, name, netdev); + + /* By default enable one tx and rx queue per netdev. */ diff --git a/lib/odp-util.c b/lib/odp-util.c -index 9a705cffa3..2d2a6893c6 100644 +index 9a705cffa3..3bbc9a1010 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c +@@ -1003,7 +1003,7 @@ format_odp_conntrack_action(struct ds *ds, const struct nlattr *attr) + ds_put_format(ds, "helper=%s,", helper); + } + if (timeout) { +- ds_put_format(ds, "timeout=%s", timeout); ++ ds_put_format(ds, "timeout=%s,", timeout); + } + if (nat) { + format_odp_ct_nat(ds, nat); @@ -3429,16 +3429,16 @@ format_eth(struct ds *ds, const char *name, const struct eth_addr key, static void @@ -55511,7 +55743,7 @@ index fcaddf10ad..71039e24f1 100644 /* Attempts to guess the content type of a stream whose first few bytes were diff --git a/lib/tc.c b/lib/tc.c -index adb2d3182a..276cc54b35 100644 +index adb2d3182a..900a631553 100644 --- a/lib/tc.c +++ b/lib/tc.c @@ -395,8 +395,14 @@ static const struct nl_policy tca_flower_policy[] = { @@ -55668,7 +55900,32 @@ index adb2d3182a..276cc54b35 100644 size_t keys_ex_size, left; int type, i = 0, err; -@@ -1092,7 +1112,6 @@ nl_parse_act_pedit(struct nlattr *options, struct tc_flower *flower) +@@ -1068,7 +1088,7 @@ nl_parse_act_pedit(struct nlattr *options, struct tc_flower *flower) + int diff = flower_off + (keys->off - mf); + ovs_be32 *dst = (void *) (rewrite_key + diff); + ovs_be32 *dst_m = (void *) (rewrite_mask + diff); +- ovs_be32 mask, mask_word, data_word; ++ ovs_be32 mask, mask_word, data_word, val; + uint32_t zero_bits; + + mask_word = htonl(ntohl(keys->mask) << m->boundary_shift); +@@ -1083,8 +1103,13 @@ nl_parse_act_pedit(struct nlattr *options, struct tc_flower *flower) + mask &= htonl(UINT32_MAX << zero_bits); + } + +- *dst_m |= mask; +- *dst |= data_word & mask; ++ val = get_unaligned_be32(dst_m); ++ val |= mask; ++ put_unaligned_be32(dst_m, val); ++ ++ val = get_unaligned_be32(dst); ++ val |= data_word & mask; ++ put_unaligned_be32(dst, val); + } + } + +@@ -1092,7 +1117,6 @@ nl_parse_act_pedit(struct nlattr *options, struct tc_flower *flower) i++; } @@ -55676,7 +55933,7 @@ index adb2d3182a..276cc54b35 100644 action->type = TC_ACT_PEDIT; return 0; -@@ -1314,8 +1333,8 @@ nl_parse_act_gact(struct nlattr *options, struct tc_flower *flower) +@@ -1314,8 +1338,8 @@ nl_parse_act_gact(struct nlattr *options, struct tc_flower *flower) struct nlattr *gact_attrs[ARRAY_SIZE(gact_policy)]; const struct tc_gact *p; struct nlattr *gact_parms; @@ -55686,7 +55943,7 @@ index adb2d3182a..276cc54b35 100644 if (!nl_parse_nested(options, gact_policy, gact_attrs, ARRAY_SIZE(gact_policy))) { -@@ -1335,8 +1354,9 @@ nl_parse_act_gact(struct nlattr *options, struct tc_flower *flower) +@@ -1335,8 +1359,9 @@ nl_parse_act_gact(struct nlattr *options, struct tc_flower *flower) return EINVAL; } @@ -55698,7 +55955,7 @@ index adb2d3182a..276cc54b35 100644 return 0; } -@@ -1357,9 +1377,9 @@ nl_parse_act_mirred(struct nlattr *options, struct tc_flower *flower) +@@ -1357,9 +1382,9 @@ nl_parse_act_mirred(struct nlattr *options, struct tc_flower *flower) struct nlattr *mirred_attrs[ARRAY_SIZE(mirred_policy)]; const struct tc_mirred *m; const struct nlattr *mirred_parms; @@ -55709,7 +55966,7 @@ index adb2d3182a..276cc54b35 100644 if (!nl_parse_nested(options, mirred_policy, mirred_attrs, ARRAY_SIZE(mirred_policy))) { -@@ -1387,8 +1407,8 @@ nl_parse_act_mirred(struct nlattr *options, struct tc_flower *flower) +@@ -1387,8 +1412,8 @@ nl_parse_act_mirred(struct nlattr *options, struct tc_flower *flower) action->type = TC_ACT_OUTPUT; mirred_tm = mirred_attrs[TCA_MIRRED_TM]; @@ -55720,7 +55977,7 @@ index adb2d3182a..276cc54b35 100644 return 0; } -@@ -1487,7 +1507,9 @@ nl_parse_act_ct(struct nlattr *options, struct tc_flower *flower) +@@ -1487,7 +1512,9 @@ nl_parse_act_ct(struct nlattr *options, struct tc_flower *flower) if (ipv4_max) { ovs_be32 addr = nl_attr_get_be32(ipv4_max); @@ -55731,7 +55988,7 @@ index adb2d3182a..276cc54b35 100644 } } else if (ipv6_min) { action->ct.range.ip_family = AF_INET6; -@@ -1496,7 +1518,9 @@ nl_parse_act_ct(struct nlattr *options, struct tc_flower *flower) +@@ -1496,7 +1523,9 @@ nl_parse_act_ct(struct nlattr *options, struct tc_flower *flower) if (ipv6_max) { struct in6_addr addr = nl_attr_get_in6_addr(ipv6_max); @@ -55742,7 +55999,7 @@ index adb2d3182a..276cc54b35 100644 } } -@@ -1504,6 +1528,10 @@ nl_parse_act_ct(struct nlattr *options, struct tc_flower *flower) +@@ -1504,6 +1533,10 @@ nl_parse_act_ct(struct nlattr *options, struct tc_flower *flower) action->ct.range.port.min = nl_attr_get_be16(port_min); if (port_max) { action->ct.range.port.max = nl_attr_get_be16(port_max); @@ -55753,7 +56010,7 @@ index adb2d3182a..276cc54b35 100644 } } } -@@ -1702,6 +1730,9 @@ static const struct nl_policy stats_policy[] = { +@@ -1702,6 +1735,9 @@ static const struct nl_policy stats_policy[] = { [TCA_STATS_BASIC] = { .type = NL_A_UNSPEC, .min_len = sizeof(struct gnet_stats_basic), .optional = false, }, @@ -55763,7 +56020,7 @@ index adb2d3182a..276cc54b35 100644 }; static int -@@ -1714,8 +1745,9 @@ nl_parse_single_action(struct nlattr *action, struct tc_flower *flower, +@@ -1714,8 +1750,9 @@ nl_parse_single_action(struct nlattr *action, struct tc_flower *flower, const char *act_kind; struct nlattr *action_attrs[ARRAY_SIZE(act_policy)]; struct nlattr *stats_attrs[ARRAY_SIZE(stats_policy)]; @@ -55775,7 +56032,7 @@ index adb2d3182a..276cc54b35 100644 int err = 0; if (!nl_parse_nested(action, act_policy, action_attrs, -@@ -1771,10 +1803,30 @@ nl_parse_single_action(struct nlattr *action, struct tc_flower *flower, +@@ -1771,10 +1808,30 @@ nl_parse_single_action(struct nlattr *action, struct tc_flower *flower, return EPROTO; } @@ -55810,7 +56067,7 @@ index adb2d3182a..276cc54b35 100644 } return 0; -@@ -2399,14 +2451,14 @@ nl_msg_put_act_flags(struct ofpbuf *request) { +@@ -2399,14 +2456,14 @@ nl_msg_put_act_flags(struct ofpbuf *request) { * first_word_mask/last_word_mask - the mask to use for the first/last read * (as we read entire words). */ static void @@ -55828,7 +56085,7 @@ index adb2d3182a..276cc54b35 100644 max_offset = m->offset + m->size; start_offset = ROUND_DOWN(m->offset, 4); -@@ -2473,7 +2525,8 @@ csum_update_flag(struct tc_flower *flower, +@@ -2473,7 +2530,8 @@ csum_update_flag(struct tc_flower *flower, static int nl_msg_put_flower_rewrite_pedits(struct ofpbuf *request, @@ -55838,7 +56095,7 @@ index adb2d3182a..276cc54b35 100644 { struct { struct tc_pedit sel; -@@ -2497,12 +2550,12 @@ nl_msg_put_flower_rewrite_pedits(struct ofpbuf *request, +@@ -2497,12 +2555,12 @@ nl_msg_put_flower_rewrite_pedits(struct ofpbuf *request, continue; } @@ -55854,7 +56111,7 @@ index adb2d3182a..276cc54b35 100644 if (j == 0) { mask_word &= first_word_mask; -@@ -2556,6 +2609,29 @@ nl_msg_put_flower_acts_release(struct ofpbuf *request, uint16_t act_index) +@@ -2556,6 +2614,29 @@ nl_msg_put_flower_acts_release(struct ofpbuf *request, uint16_t act_index) nl_msg_end_nested(request, act_offset); } @@ -55884,7 +56141,7 @@ index adb2d3182a..276cc54b35 100644 static int nl_msg_put_flower_acts(struct ofpbuf *request, struct tc_flower *flower) { -@@ -2572,20 +2648,22 @@ nl_msg_put_flower_acts(struct ofpbuf *request, struct tc_flower *flower) +@@ -2572,20 +2653,22 @@ nl_msg_put_flower_acts(struct ofpbuf *request, struct tc_flower *flower) action = flower->actions; for (i = 0; i < flower->action_count; i++, action++) { @@ -55913,7 +56170,7 @@ index adb2d3182a..276cc54b35 100644 } } break; -@@ -2792,13 +2870,16 @@ nl_msg_put_flower_tunnel(struct ofpbuf *request, struct tc_flower *flower) +@@ -2792,13 +2875,16 @@ nl_msg_put_flower_tunnel(struct ofpbuf *request, struct tc_flower *flower) struct in6_addr *ipv6_dst_mask = &flower->mask.tunnel.ipv6.ipv6_dst; struct in6_addr *ipv6_src = &flower->key.tunnel.ipv6.ipv6_src; struct in6_addr *ipv6_dst = &flower->key.tunnel.ipv6.ipv6_dst; @@ -55931,7 +56188,7 @@ index adb2d3182a..276cc54b35 100644 if (ipv4_dst_mask || ipv4_src_mask) { nl_msg_put_be32(request, TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, -@@ -2824,8 +2905,15 @@ nl_msg_put_flower_tunnel(struct ofpbuf *request, struct tc_flower *flower) +@@ -2824,8 +2910,15 @@ nl_msg_put_flower_tunnel(struct ofpbuf *request, struct tc_flower *flower) nl_msg_put_u8(request, TCA_FLOWER_KEY_ENC_IP_TTL, ttl); nl_msg_put_u8(request, TCA_FLOWER_KEY_ENC_IP_TTL_MASK, ttl_mask); } @@ -55948,7 +56205,7 @@ index adb2d3182a..276cc54b35 100644 } if (id_mask) { nl_msg_put_be32(request, TCA_FLOWER_KEY_ENC_KEY_ID, id); -@@ -2914,13 +3002,13 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower) +@@ -2914,13 +3007,13 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower) FLOWER_PUT_MASKED_VALUE(icmp_code, TCA_FLOWER_KEY_ICMPV6_CODE); FLOWER_PUT_MASKED_VALUE(icmp_type, TCA_FLOWER_KEY_ICMPV6_TYPE); } @@ -55967,7 +56224,7 @@ index adb2d3182a..276cc54b35 100644 if (host_eth_type == ETH_P_IP) { FLOWER_PUT_MASKED_VALUE(ipv4.ipv4_src, TCA_FLOWER_KEY_IPV4_SRC); FLOWER_PUT_MASKED_VALUE(ipv4.ipv4_dst, TCA_FLOWER_KEY_IPV4_DST); -@@ -2993,12 +3081,79 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower) +@@ -2993,12 +3086,79 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower) return 0; } @@ -56048,7 +56305,7 @@ index adb2d3182a..276cc54b35 100644 return false; } -@@ -3011,8 +3166,8 @@ cmp_tc_flower_match_action(const struct tc_flower *a, +@@ -3011,8 +3171,8 @@ cmp_tc_flower_match_action(const struct tc_flower *a, uint8_t key_b = ((uint8_t *)&b->key)[i] & mask; if (key_a != key_b) { @@ -56059,7 +56316,7 @@ index adb2d3182a..276cc54b35 100644 return false; } } -@@ -3022,14 +3177,15 @@ cmp_tc_flower_match_action(const struct tc_flower *a, +@@ -3022,14 +3182,15 @@ cmp_tc_flower_match_action(const struct tc_flower *a, const struct tc_action *action_b = b->actions; if (a->action_count != b->action_count) { @@ -56208,6 +56465,44 @@ index 58269d3b16..050eafa6b8 100644 char dev_name[IFNAMSIZ]; if (ip_dev->change_seq == netdev_get_change_seq(ip_dev->dev)) { +diff --git a/lib/unaligned.h b/lib/unaligned.h +index f40e4e10df..15334e3c76 100644 +--- a/lib/unaligned.h ++++ b/lib/unaligned.h +@@ -95,7 +95,7 @@ GCC_UNALIGNED_ACCESSORS(ovs_be64, be64); + static inline uint16_t get_unaligned_u16(const uint16_t *p_) + { + const uint8_t *p = (const uint8_t *) p_; +- return ntohs((p[0] << 8) | p[1]); ++ return ntohs(((uint16_t) p[0] << 8) | (uint16_t) p[1]); + } + + static inline void put_unaligned_u16(uint16_t *p_, uint16_t x_) +@@ -110,7 +110,8 @@ static inline void put_unaligned_u16(uint16_t *p_, uint16_t x_) + static inline uint32_t get_unaligned_u32(const uint32_t *p_) + { + const uint8_t *p = (const uint8_t *) p_; +- return ntohl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); ++ return ntohl(((uint32_t) p[0] << 24) | ((uint32_t) p[1] << 16) | ++ ((uint32_t) p[2] << 8) | (uint32_t) p[3]); + } + + static inline void put_unaligned_u32(uint32_t *p_, uint32_t x_) +@@ -131,10 +132,10 @@ static inline uint64_t get_unaligned_u64__(const uint64_t *p_) + | ((uint64_t) p[1] << 48) + | ((uint64_t) p[2] << 40) + | ((uint64_t) p[3] << 32) +- | (p[4] << 24) +- | (p[5] << 16) +- | (p[6] << 8) +- | p[7]); ++ | ((uint64_t) p[4] << 24) ++ | ((uint64_t) p[5] << 16) ++ | ((uint64_t) p[6] << 8) ++ | (uint64_t) p[7]); + } + + static inline void put_unaligned_u64__(uint64_t *p_, uint64_t x_) diff --git a/lib/unixctl.c b/lib/unixctl.c index 69aed6722c..103357ee91 100644 --- a/lib/unixctl.c @@ -56394,7 +56689,7 @@ index 4c3bace6ef..09134feca0 100644 AC_DEFINE([HAVE_LD_AVX512_GOOD], [1], [Define to 1 if binutils correctly supports AVX512.]) diff --git a/ofproto/bond.c b/ofproto/bond.c -index cdfdf0b9d8..6ecd6e1c9f 100644 +index cdfdf0b9d8..a7c859b909 100644 --- a/ofproto/bond.c +++ b/ofproto/bond.c @@ -185,10 +185,14 @@ static struct bond_member *choose_output_member(const struct bond *, @@ -56456,6 +56751,15 @@ index cdfdf0b9d8..6ecd6e1c9f 100644 revalidate = bond->bond_revalidate; bond->bond_revalidate = false; ovs_rwlock_unlock(&rwlock); +@@ -876,7 +892,7 @@ bond_check_admissibility(struct bond *bond, const void *member_, + if (!member->enabled && member->may_enable) { + VLOG_DBG_RL(&rl, "bond %s: member %s: " + "main thread has not yet enabled member", +- bond->name, bond->active_member->name); ++ bond->name, member->name); + } + goto out; + case LACP_CONFIGURED: @@ -1038,7 +1054,7 @@ bond_may_recirc(const struct bond *bond) } @@ -57001,7 +57305,7 @@ index 114aff8ea3..0fc6d2ea60 100644 enum xc_type type; union { diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c -index 578cbfe581..e804c4d887 100644 +index 578cbfe581..8a28b29d4c 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -865,7 +865,7 @@ xlate_xbridge_init(struct xlate_cfg *xcfg, struct xbridge *xbridge) @@ -57105,7 +57409,49 @@ index 578cbfe581..e804c4d887 100644 static struct xbundle * xbundle_lookup(struct xlate_cfg *xcfg, const struct ofbundle *ofbundle) { -@@ -2125,9 +2142,14 @@ mirror_packet(struct xlate_ctx *ctx, struct xbundle *xbundle, +@@ -1894,8 +1911,8 @@ group_is_alive(const struct xlate_ctx *ctx, uint32_t group_id, int depth) + #define MAX_LIVENESS_RECURSION 128 /* Arbitrary limit */ + + static bool +-bucket_is_alive(const struct xlate_ctx *ctx, +- struct ofputil_bucket *bucket, int depth) ++bucket_is_alive(const struct xlate_ctx *ctx, const struct group_dpif *group, ++ const struct ofputil_bucket *bucket, int depth) + { + if (depth >= MAX_LIVENESS_RECURSION) { + xlate_report_error(ctx, "bucket chaining exceeded %d links", +@@ -1903,6 +1920,12 @@ bucket_is_alive(const struct xlate_ctx *ctx, + return false; + } + ++ /* In "select" groups, buckets with weight 0 are not used. ++ * In other kinds of groups, weight does not matter. */ ++ if (group->up.type == OFPGT11_SELECT && bucket->weight == 0) { ++ return false; ++ } ++ + return (!ofputil_bucket_has_liveness(bucket) + || (bucket->watch_port != OFPP_ANY + && bucket->watch_port != OFPP_CONTROLLER +@@ -1943,7 +1966,7 @@ group_first_live_bucket(const struct xlate_ctx *ctx, + { + struct ofputil_bucket *bucket; + LIST_FOR_EACH (bucket, list_node, &group->up.buckets) { +- if (bucket_is_alive(ctx, bucket, depth)) { ++ if (bucket_is_alive(ctx, group, bucket, depth)) { + return bucket; + } + xlate_report_bucket_not_live(ctx, bucket); +@@ -1962,7 +1985,7 @@ group_best_live_bucket(const struct xlate_ctx *ctx, + + struct ofputil_bucket *bucket; + LIST_FOR_EACH (bucket, list_node, &group->up.buckets) { +- if (bucket_is_alive(ctx, bucket, 0)) { ++ if (bucket_is_alive(ctx, group, bucket, 0)) { + uint32_t score = + (hash_int(bucket->bucket_id, basis) & 0xffff) * bucket->weight; + if (score >= best_score) { +@@ -2125,9 +2148,14 @@ mirror_packet(struct xlate_ctx *ctx, struct xbundle *xbundle, int snaplen; /* Get the details of the mirror represented by the rightmost 1-bit. */ @@ -57123,7 +57469,7 @@ index 578cbfe581..e804c4d887 100644 /* If this mirror selects on the basis of VLAN, and it does not select -@@ -2444,9 +2466,18 @@ output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle, +@@ -2444,9 +2472,18 @@ output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle, /* In case recirculation is not actually in use, 'xr.recirc_id' * will be set to '0', since a valid 'recirc_id' can * not be zero. */ @@ -57145,7 +57491,7 @@ index 578cbfe581..e804c4d887 100644 if (xr.recirc_id) { /* Use recirculation instead of output. */ use_recirc = true; -@@ -3015,7 +3046,7 @@ xlate_normal(struct xlate_ctx *ctx) +@@ -3015,7 +3052,7 @@ xlate_normal(struct xlate_ctx *ctx) bool is_grat_arp = is_gratuitous_arp(flow, wc); if (ctx->xin->allow_side_effects && flow->packet_type == htonl(PT_ETH) @@ -57154,7 +57500,7 @@ index 578cbfe581..e804c4d887 100644 ) { update_learning_table(ctx, in_xbundle, flow->dl_src, vlan, is_grat_arp); -@@ -3024,12 +3055,14 @@ xlate_normal(struct xlate_ctx *ctx) +@@ -3024,12 +3061,14 @@ xlate_normal(struct xlate_ctx *ctx) struct xc_entry *entry; /* Save just enough info to update mac learning table later. */ @@ -57175,7 +57521,7 @@ index 578cbfe581..e804c4d887 100644 } /* Determine output bundle. */ -@@ -3048,7 +3081,6 @@ xlate_normal(struct xlate_ctx *ctx) +@@ -3048,7 +3087,6 @@ xlate_normal(struct xlate_ctx *ctx) */ ctx->xout->slow |= SLOW_ACTION; @@ -57183,7 +57529,7 @@ index 578cbfe581..e804c4d887 100644 if (mcast_snooping_is_membership(flow->tp_src) || mcast_snooping_is_query(flow->tp_src)) { if (ctx->xin->allow_side_effects && ctx->xin->packet) { -@@ -3523,6 +3555,9 @@ propagate_tunnel_data_to_flow__(struct flow *dst_flow, +@@ -3523,6 +3561,9 @@ propagate_tunnel_data_to_flow__(struct flow *dst_flow, dst_flow->dl_dst = dmac; dst_flow->dl_src = smac; @@ -57193,7 +57539,7 @@ index 578cbfe581..e804c4d887 100644 dst_flow->packet_type = htonl(PT_ETH); dst_flow->nw_dst = src_flow->tunnel.ip_dst; dst_flow->nw_src = src_flow->tunnel.ip_src; -@@ -3654,14 +3689,27 @@ native_tunnel_output(struct xlate_ctx *ctx, const struct xport *xport, +@@ -3654,14 +3695,27 @@ native_tunnel_output(struct xlate_ctx *ctx, const struct xport *xport, err = tnl_neigh_lookup(out_dev->xbridge->name, &d_ip6, &dmac); if (err) { @@ -57223,7 +57569,35 @@ index 578cbfe581..e804c4d887 100644 } return err; } -@@ -4176,6 +4224,10 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, +@@ -4099,6 +4153,16 @@ xport_has_ip(const struct xport *xport) + return n_in6 ? true : false; + } + ++static bool check_neighbor_reply(struct xlate_ctx *ctx, struct flow *flow) ++{ ++ if (flow->dl_type == htons(ETH_TYPE_ARP) || ++ flow->nw_proto == IPPROTO_ICMPV6) { ++ return is_neighbor_reply_correct(ctx, flow); ++ } ++ ++ return false; ++} ++ + static bool + terminate_native_tunnel(struct xlate_ctx *ctx, const struct xport *xport, + struct flow *flow, struct flow_wildcards *wc, +@@ -4119,9 +4183,7 @@ terminate_native_tunnel(struct xlate_ctx *ctx, const struct xport *xport, + /* If no tunnel port was found and it's about an ARP or ICMPv6 packet, + * do tunnel neighbor snooping. */ + if (*tnl_port == ODPP_NONE && +- (flow->dl_type == htons(ETH_TYPE_ARP) || +- flow->nw_proto == IPPROTO_ICMPV6) && +- is_neighbor_reply_correct(ctx, flow)) { ++ (check_neighbor_reply(ctx, flow) || is_garp(flow, wc))) { + tnl_neigh_snoop(flow, wc, ctx->xbridge->name, + ctx->xin->allow_side_effects); + } else if (*tnl_port != ODPP_NONE && +@@ -4176,6 +4238,10 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, if (xport->pt_mode == NETDEV_PT_LEGACY_L3) { flow->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE, ntohs(flow->dl_type)); @@ -57234,7 +57608,16 @@ index 578cbfe581..e804c4d887 100644 } } -@@ -5622,7 +5674,8 @@ xlate_sample_action(struct xlate_ctx *ctx, +@@ -4678,7 +4744,7 @@ pick_dp_hash_select_group(struct xlate_ctx *ctx, struct group_dpif *group) + for (int i = 0; i <= hash_mask; i++) { + struct ofputil_bucket *b = + group->hash_map[(dp_hash + i) & hash_mask]; +- if (bucket_is_alive(ctx, b, 0)) { ++ if (bucket_is_alive(ctx, group, b, 0)) { + return b; + } + } +@@ -5622,7 +5688,8 @@ xlate_sample_action(struct xlate_ctx *ctx, /* Scale the probability from 16-bit to 32-bit while representing * the same percentage. */ @@ -57244,7 +57627,7 @@ index 578cbfe581..e804c4d887 100644 /* If ofp_port in flow sample action is equel to ofp_port, * this sample action is a input port action. */ -@@ -7609,6 +7662,10 @@ xlate_wc_finish(struct xlate_ctx *ctx) +@@ -7609,6 +7676,10 @@ xlate_wc_finish(struct xlate_ctx *ctx) ctx->wc->masks.vlans[i].tci = 0; } } @@ -57255,7 +57638,7 @@ index 578cbfe581..e804c4d887 100644 } /* Translates the flow, actions, or rule in 'xin' into datapath actions in -@@ -7784,6 +7841,12 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) +@@ -7784,6 +7855,12 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) goto exit; } @@ -60448,9 +60831,47 @@ index 00e3a46b8b..b6155af253 100644 AT_CLEANUP diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at -index a79ebdb618..3179e1645d 100644 +index a79ebdb618..6aff1eda7b 100644 --- a/tests/dpif-netdev.at +++ b/tests/dpif-netdev.at +@@ -6,8 +6,8 @@ m4_divert_push([PREPARE_TESTS]) + # that vary from one run to another (e.g., timing and bond actions). + strip_timers () { + sed ' +- s/duration:[0-9]*\.[0-9]*/duration:0.0/ +- s/used:[0-9]*\.[0-9]*/used:0.0/ ++ s/duration:[0-9\.][0-9\.]*/duration:0.0/ ++ s/used:[0-9\.][0-9\.]*/used:0.0/ + ' + } + +@@ -15,7 +15,7 @@ strip_xout () { + sed ' + s/mega_ufid:[-0-9a-f]* // + s/ufid:[-0-9a-f]* // +- s/used:[0-9]*\.[0-9]*/used:0.0/ ++ s/used:[0-9\.][0-9\.]*/used:0.0/ + s/actions:.*/actions: / + s/packets:[0-9]*/packets:0/ + s/bytes:[0-9]*/bytes:0/ +@@ -26,7 +26,7 @@ strip_xout_keep_actions () { + sed ' + s/mega_ufid:[-0-9a-f]* // + s/ufid:[-0-9a-f]* // +- s/used:[0-9]*\.[0-9]*/used:0.0/ ++ s/used:[0-9\.][0-9\.]*/used:0.0/ + s/packets:[0-9]*/packets:0/ + s/bytes:[0-9]*/bytes:0/ + ' | sort +@@ -51,7 +51,7 @@ filter_hw_packet_netdev_dummy () { + filter_flow_dump () { + grep 'flow_dump ' | sed ' + s/.*flow_dump // +- s/used:[0-9]*\.[0-9]*/used:0.0/ ++ s/used:[0-9\.][0-9\.]*/used:0.0/ + ' | sort | uniq + } + @@ -439,7 +439,7 @@ recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), a # Check for succesfull packet matching with installed offloaded flow. @@ -60680,6 +61101,20 @@ index 4d49f12017..91ded1445d 100644 bridge("br0") ------------- +diff --git a/tests/odp.at b/tests/odp.at +index 4d08c59ca6..fce6a4f2bc 100644 +--- a/tests/odp.at ++++ b/tests/odp.at +@@ -348,7 +348,9 @@ ct(commit,helper=tftp) + ct(commit,timeout=ovs_tp_1_tcp4) + ct(nat) + ct(commit,nat(src)) ++ct(commit,timeout=ovs_tp_1_tcp4,nat(src)) + ct(commit,nat(dst)) ++ct(commit,timeout=ovs_tp_1_tcp4,nat(dst)) + ct(commit,nat(src=10.0.0.240,random)) + ct(commit,nat(src=10.0.0.240:32768-65535,random)) + ct(commit,nat(dst=10.0.0.128-10.0.0.254,hash)) diff --git a/tests/ofp-print.at b/tests/ofp-print.at index 2c7e163bd6..7be6628c34 100644 --- a/tests/ofp-print.at @@ -60784,7 +61219,7 @@ index 2c7e163bd6..7be6628c34 100644 AT_CLEANUP diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at -index 7c2edeb9d4..1a8de7398c 100644 +index 7c2edeb9d4..73a5e8c3d0 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -29,6 +29,39 @@ AT_CHECK([ovs-appctl revalidator/wait]) @@ -62057,7 +62492,37 @@ index 7c2edeb9d4..1a8de7398c 100644 OVS_VSWITCHD_STOP AT_CLEANUP -@@ -7031,7 +7173,7 @@ dnl An 170 byte packet +@@ -7004,6 +7146,29 @@ AT_CHECK([ovs-appctl coverage/read-counter mac_learning_static_none_move], [0], + OVS_VSWITCHD_STOP + AT_CLEANUP + ++AT_SETUP([ofproto-dpif - static-mac learned mac age out]) ++OVS_VSWITCHD_START([set bridge br0 fail-mode=standalone -- set bridge br0 other_config:mac-aging-time=5]) ++add_of_ports br0 1 2 ++ ++dnl Add some static mac entries. ++AT_CHECK([ovs-appctl fdb/add br0 p1 0 50:54:00:00:01:01]) ++AT_CHECK([ovs-appctl fdb/add br0 p2 0 50:54:00:00:02:02]) ++ ++dnl Generate some dynamic fdb entries on some ports. ++OFPROTO_TRACE([ovs-dummy], [in_port(1),eth(src=60:54:00:00:00:01)], [-generate], [100,2]) ++OFPROTO_TRACE([ovs-dummy], [in_port(2),eth(src=60:54:00:00:00:02)], [-generate], [100,1]) ++ ++dnl Waiting for aging out. ++ovs-appctl time/warp 20000 ++ ++dnl Count number of static entries remaining. ++AT_CHECK_UNQUOTED([ovs-appctl fdb/stats-show br0 | grep expired], [0], [dnl ++ Total number of expired MAC entries : 2 ++]) ++ ++OVS_VSWITCHD_STOP ++AT_CLEANUP ++ + AT_SETUP([ofproto-dpif - basic truncate action]) + OVS_VSWITCHD_START + add_of_ports br0 1 2 3 4 5 +@@ -7031,7 +7196,7 @@ dnl An 170 byte packet AT_CHECK([ovs-appctl netdev-dummy/receive p1 '000c29c8a0a4005056c0000808004500009cb4a6000040019003c0a8da01c0a8da640800cb5fa762000556f431ad0009388e08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f']) AT_CHECK([ovs-ofctl parse-pcap p1.pcap], [0], [dnl @@ -62066,7 +62531,7 @@ index 7c2edeb9d4..1a8de7398c 100644 ]) AT_CHECK([ovs-appctl revalidator/purge], [0]) -@@ -7600,13 +7742,28 @@ dnl configure bridge IPFIX and ensure that sample action generation works at the +@@ -7600,13 +7765,28 @@ dnl configure bridge IPFIX and ensure that sample action generation works at the dnl datapath level. AT_SETUP([ofproto-dpif - Bridge IPFIX sanity check]) OVS_VSWITCHD_START @@ -62096,7 +62561,7 @@ index 7c2edeb9d4..1a8de7398c 100644 dnl Send some packets that should be sampled. for i in `seq 1 3`; do AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)']) -@@ -8666,7 +8823,7 @@ recirc_id(0),in_port(100),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=192.1 +@@ -8666,7 +8846,7 @@ recirc_id(0),in_port(100),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=192.1 ]) AT_CHECK([grep -e '|ofproto_dpif_xlate|WARN|' ovs-vswitchd.log | sed "s/^.*|WARN|//"], [0], [dnl @@ -62105,7 +62570,7 @@ index 7c2edeb9d4..1a8de7398c 100644 ]) OVS_VSWITCHD_STOP(["/stack underflow/d"]) -@@ -9855,7 +10012,7 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl]) +@@ -9855,7 +10035,7 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl]) AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=86 in_port=1 (via no_match) data_len=86 (unbuffered) @@ -62114,7 +62579,7 @@ index 7c2edeb9d4..1a8de7398c 100644 ]) OVS_VSWITCHD_STOP -@@ -9906,7 +10063,7 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl]) +@@ -9906,7 +10086,7 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl]) AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=86 in_port=1 (via action) data_len=86 (unbuffered) @@ -62123,7 +62588,7 @@ index 7c2edeb9d4..1a8de7398c 100644 ]) OVS_VSWITCHD_STOP -@@ -10166,10 +10323,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) +@@ -10166,10 +10346,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) dnl Check this output. We only see the latter two packets, not the first. AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x0 total_len=106 reg0=0x1,reg1=0x4d2,reg2=0x1,reg3=0x1,reg4=0x1,in_port=1 (via action) data_len=106 (unbuffered) @@ -62136,7 +62601,7 @@ index 7c2edeb9d4..1a8de7398c 100644 ]) AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log]) -@@ -10187,10 +10344,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) +@@ -10187,10 +10367,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) dnl Check this output. We should see both packets AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x0 total_len=106 reg0=0x1,reg1=0x4d2,reg2=0x1,reg3=0x1,reg4=0x1,in_port=1 (via action) data_len=106 (unbuffered) @@ -62149,7 +62614,7 @@ index 7c2edeb9d4..1a8de7398c 100644 ]) OVS_VSWITCHD_STOP -@@ -10239,10 +10396,10 @@ dnl Note that the first packet doesn't have the ct_state bits set. This +@@ -10239,10 +10419,10 @@ dnl Note that the first packet doesn't have the ct_state bits set. This dnl happens because the ct_state field is available only after recirc. AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered) @@ -62162,7 +62627,7 @@ index 7c2edeb9d4..1a8de7398c 100644 ]) AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log]) -@@ -10261,10 +10418,10 @@ dnl Note that the first packet doesn't have the ct_state bits set. This +@@ -10261,10 +10441,10 @@ dnl Note that the first packet doesn't have the ct_state bits set. This dnl happens because the ct_state field is available only after recirc. AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered) @@ -62175,7 +62640,7 @@ index 7c2edeb9d4..1a8de7398c 100644 ]) dnl -@@ -10320,9 +10477,9 @@ dnl Note that the first packet doesn't have the ct_state bits set. This +@@ -10320,9 +10500,9 @@ dnl Note that the first packet doesn't have the ct_state bits set. This dnl happens because the ct_state field is available only after recirc. AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=126 in_port=1 (via action) data_len=126 (unbuffered) @@ -62187,7 +62652,7 @@ index 7c2edeb9d4..1a8de7398c 100644 ]) OVS_VSWITCHD_STOP -@@ -10433,7 +10590,7 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) +@@ -10433,7 +10613,7 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) dnl Check this output. Only one reply must be there AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ip,in_port=2 (via action) data_len=106 (unbuffered) @@ -62196,7 +62661,7 @@ index 7c2edeb9d4..1a8de7398c 100644 dnl OFPT_ECHO_REQUEST (xid=0x0): 0 bytes of payload ]) -@@ -10467,7 +10624,7 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) +@@ -10467,7 +10647,7 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=86 ct_state=inv|trk,ipv6,in_port=2 (via action) data_len=86 (unbuffered) @@ -62205,7 +62670,7 @@ index 7c2edeb9d4..1a8de7398c 100644 ]) OVS_VSWITCHD_STOP -@@ -10523,16 +10680,16 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) +@@ -10523,16 +10703,16 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) dnl Check this output. We only see the latter two packets (for each zone), not the first. AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered) @@ -62226,7 +62691,7 @@ index 7c2edeb9d4..1a8de7398c 100644 ]) OVS_VSWITCHD_STOP -@@ -10579,10 +10736,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) +@@ -10579,10 +10759,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) dnl Check this output. We only see the latter two packets, not the first. AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered) @@ -62239,7 +62704,7 @@ index 7c2edeb9d4..1a8de7398c 100644 ]) OVS_VSWITCHD_STOP -@@ -10629,10 +10786,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) +@@ -10629,10 +10809,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) dnl Check this output. We only see the first and the last packet AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=47 ct_state=new|trk,ct_nw_src=172.16.0.1,ct_nw_dst=172.16.0.2,ct_nw_proto=17,ct_tp_src=41614,ct_tp_dst=5555,ip,in_port=1 (via action) data_len=47 (unbuffered) @@ -62252,7 +62717,7 @@ index 7c2edeb9d4..1a8de7398c 100644 ]) OVS_VSWITCHD_STOP -@@ -10681,19 +10838,19 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) +@@ -10681,19 +10861,19 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) dnl Check this output. AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered) @@ -62277,7 +62742,7 @@ index 7c2edeb9d4..1a8de7398c 100644 ]) OVS_VSWITCHD_STOP -@@ -10738,10 +10895,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) +@@ -10738,10 +10918,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) dnl Check this output. AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_label=0x1,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ip,in_port=2 (via action) data_len=106 (unbuffered) @@ -62290,7 +62755,7 @@ index 7c2edeb9d4..1a8de7398c 100644 ]) OVS_VSWITCHD_STOP -@@ -11152,16 +11309,16 @@ dnl Note that the first packet doesn't have the ct_state bits set. This +@@ -11152,16 +11332,16 @@ dnl Note that the first packet doesn't have the ct_state bits set. This dnl happens because the ct_state field is available only after recirc. AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered) @@ -62311,7 +62776,7 @@ index 7c2edeb9d4..1a8de7398c 100644 ]) dnl The next test verifies that ct_clear at the datapath only gets executed -@@ -11235,13 +11392,13 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) +@@ -11235,13 +11415,13 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) dnl Check this output. AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_nw_src=10.1.2.100,ct_nw_dst=10.1.2.200,ct_nw_proto=17,ct_tp_src=6,ct_tp_dst=6,ip,in_port=2 (via action) data_len=106 (unbuffered) @@ -63593,6 +64058,19 @@ index 0f74709f5a..5bca84351c 100644 run should send probe in IDLE for 0 ms (1000 ms backoff) +diff --git a/tests/stp.at b/tests/stp.at +index 7ddacfc3a0..69475843e5 100644 +--- a/tests/stp.at ++++ b/tests/stp.at +@@ -368,7 +368,7 @@ AT_CLEANUP + # Strips out uninteresting parts of flow output, as well as parts + # that vary from one run to another (e.g., timing and bond actions). + m4_define([STRIP_USED], [[sed ' +- s/used:[0-9]*\.[0-9]*/used:0.0/ ++ s/used:[0-9\.][0-9\.]*/used:0.0/ + s/duration=[0-9.]*s*/duration=Xs/ + s/idle_age=[0-9]*,/idle_age=X,/ + ']]) diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at index 19a0b125b9..8b9f5c7525 100644 --- a/tests/system-common-macros.at @@ -63710,7 +64188,7 @@ index 1714273e35..270956d13f 100644 dnl Delete ip address. AT_CHECK([ip addr del 10.0.0.17/24 dev p1-route], [0], [stdout]) diff --git a/tests/system-traffic.at b/tests/system-traffic.at -index f22d86e466..69de604fa0 100644 +index f22d86e466..9d1c96bb43 100644 --- a/tests/system-traffic.at +++ b/tests/system-traffic.at @@ -192,6 +192,46 @@ NS_CHECK_EXEC([at_ns0], [ping6 -s 3200 -q -c 3 -i 0.3 -w 2 fc00:1::2 | FORMAT_PI @@ -64138,7 +64616,7 @@ index f22d86e466..69de604fa0 100644 OVS_TRAFFIC_VSWITCHD_STOP -@@ -1933,13 +2037,13 @@ dnl p1(at_ns1) interface +@@ -1933,15 +2037,51 @@ dnl p1(at_ns1) interface NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 00 00 00 00 00 02 00 00 00 00 00 01 88 47 00 00 21 40 36 b1 ee 7c 01 02 36 b1 ee 7c 01 03 08 00 45 00 00 54 03 44 40 00 40 01 21 61 0a 01 01 01 0a 01 01 02 08 00 ef ac 7c e4 00 03 5b 2c 1f 61 00 00 00 00 50 0b 02 00 00 00 00 00 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 > /dev/null]) dnl Check the expected decapsulated on the egress interface @@ -64158,8 +64636,46 @@ index f22d86e466..69de604fa0 100644 +OVS_WAIT_UNTIL([cat p1.pcap | grep -E "0x0060: *3637" 2>&1 1>/dev/null]) ++OVS_TRAFFIC_VSWITCHD_STOP ++AT_CLEANUP ++ ++AT_BANNER([QoS]) ++ ++AT_SETUP([QoS - basic configuration]) ++AT_SKIP_IF([test $HAVE_TC = no]) ++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") ++ ++dnl Adding a custom qdisc to ovs-p1, ovs-p0 will have the default qdisc. ++AT_CHECK([tc qdisc add dev ovs-p1 root noqueue]) ++AT_CHECK([tc qdisc show dev ovs-p1 | grep -q noqueue]) ++ ++dnl Configure the same QoS for both ports. ++AT_CHECK([ovs-vsctl set port ovs-p0 qos=@qos -- set port ovs-p1 qos=@qos dnl ++ -- --id=@qos create qos dnl ++ type=linux-htb other-config:max-rate=3000000 queues:0=@queue dnl ++ -- --id=@queue create queue dnl ++ other_config:min-rate=2000000 other_config:max-rate=3000000 dnl ++ other_config:burst=3000000], ++ [ignore], [ignore]) ++ ++dnl Wait for qdiscs to be applied. ++OVS_WAIT_UNTIL([tc qdisc show dev ovs-p0 | grep -q htb]) ++OVS_WAIT_UNTIL([tc qdisc show dev ovs-p1 | grep -q htb]) ++ ++dnl Check the configuration. ++m4_define([HTB_CONF], [rate 2Mbit ceil 3Mbit burst 375000b cburst 375000b]) ++AT_CHECK([tc class show dev ovs-p0 | grep -q 'class htb .* HTB_CONF']) ++AT_CHECK([tc class show dev ovs-p1 | grep -q 'class htb .* HTB_CONF']) ++ OVS_TRAFFIC_VSWITCHD_STOP -@@ -1985,9 +2089,9 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl]) + AT_CLEANUP + +@@ -1985,9 +2125,9 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl]) dnl Check this output. We only see the latter two packets, not the first. AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN2 (xid=0x0): total_len=42 in_port=1 (via action) data_len=42 (unbuffered) @@ -64171,7 +64687,7 @@ index f22d86e466..69de604fa0 100644 ]) OVS_TRAFFIC_VSWITCHD_STOP -@@ -2033,9 +2137,9 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl]) +@@ -2033,9 +2173,9 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl]) dnl Check this output. We only see the latter two packets, not the first. AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN2 (xid=0x0): cookie=0x0 total_len=42 in_port=1 (via action) data_len=42 (unbuffered) @@ -64183,7 +64699,7 @@ index f22d86e466..69de604fa0 100644 ]) dnl -@@ -2980,6 +3084,15 @@ NXST_FLOW reply: +@@ -2980,6 +3120,15 @@ NXST_FLOW reply: table=1, priority=100,ct_state=+est+trk,in_port=1 actions=output:2 ]) @@ -64199,7 +64715,7 @@ index f22d86e466..69de604fa0 100644 OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP -@@ -3140,11 +3253,11 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl]) +@@ -3140,11 +3289,11 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl]) dnl Check this output. We only see the latter two packets, not the first. AT_CHECK([cat ofctl_monitor.log | grep -v ff02 | grep -v fe80 | grep -v no_match], [0], [dnl NXT_PACKET_IN2 (xid=0x0): table_id=1 cookie=0x0 total_len=75 ct_state=inv|trk,ip,in_port=2 (via action) data_len=75 (unbuffered) @@ -64214,7 +64730,7 @@ index f22d86e466..69de604fa0 100644 ]) AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.0.1)], [0], [dnl -@@ -3345,6 +3458,11 @@ AT_CHECK([ovs-ofctl bundle br0 bundle.txt]) +@@ -3345,6 +3494,11 @@ AT_CHECK([ovs-ofctl bundle br0 bundle.txt]) AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl ]) @@ -64226,7 +64742,7 @@ index f22d86e466..69de604fa0 100644 OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP -@@ -4100,15 +4218,15 @@ action=normal +@@ -4100,15 +4254,15 @@ action=normal AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt]) @@ -64245,7 +64761,7 @@ index f22d86e466..69de604fa0 100644 "1616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161610a, actions=ct(table=1)"]) AT_CHECK([ovs-appctl dpctl/dump-flows | head -2 | tail -1 | grep -q -e ["]udp[(]src=5001["]]) -@@ -5384,7 +5502,7 @@ AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2) | sed -e 's/dst= +@@ -5384,7 +5538,7 @@ AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2) | sed -e 's/dst= udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=,dport=),reply=(src=10.1.1.2,dst=10.1.1.2XX,sport=,dport=),mark=1 ]) @@ -64254,7 +64770,7 @@ index f22d86e466..69de604fa0 100644 OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP -@@ -6134,7 +6252,7 @@ sleep 1 +@@ -6134,7 +6288,7 @@ sleep 1 dnl UDP packets from ns0->ns1 should solicit "destination unreachable" response. NS_CHECK_EXEC([at_ns0], [bash -c "echo a | nc -6 $NC_EOF_OPT -u fc00::2 1"]) @@ -64263,7 +64779,7 @@ index f22d86e466..69de604fa0 100644 AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fc00::2)], [0], [dnl udp,orig=(src=fc00::1,dst=fc00::2,sport=,dport=),reply=(src=fc00::2,dst=fc00::240,sport=,dport=) -@@ -6454,7 +6572,7 @@ on_exit 'ovs-appctl revalidator/purge' +@@ -6454,7 +6608,7 @@ on_exit 'ovs-appctl revalidator/purge' on_exit 'ovs-appctl dpif/dump-flows br0' dnl Should work with the virtual IP address through NAT @@ -64272,7 +64788,7 @@ index f22d86e466..69de604fa0 100644 echo Request $i NS_CHECK_EXEC([at_ns1], [wget 10.1.1.64 -t 5 -T 1 --retry-connrefused -v -o wget$i.log]) done -@@ -6743,6 +6861,132 @@ AT_CHECK([ovs-ofctl dump-flows br0 | grep table=2, | OFPROTO_CLEAR_DURATION_IDLE +@@ -6743,6 +6897,132 @@ AT_CHECK([ovs-ofctl dump-flows br0 | grep table=2, | OFPROTO_CLEAR_DURATION_IDLE OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP @@ -64405,7 +64921,7 @@ index f22d86e466..69de604fa0 100644 AT_BANNER([802.1ad]) AT_SETUP([802.1ad - vlan_limit]) -@@ -7007,12 +7251,12 @@ dnl p1(at_ns1) interface +@@ -7007,12 +7287,12 @@ dnl p1(at_ns1) interface NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f2 00 00 00 00 02 f2 00 00 00 00 01 08 00 45 00 00 28 00 01 00 00 40 06 b0 13 c0 a8 00 0a 0a 00 00 0a 04 00 08 00 00 00 00 c8 00 00 00 00 50 02 20 00 b8 5e 00 00 > /dev/null]) dnl Check the expected nsh encapsulated packet on the egress interface @@ -64424,7 +64940,7 @@ index f22d86e466..69de604fa0 100644 OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP -@@ -7039,10 +7283,10 @@ dnl p1(at_ns1) interface +@@ -7039,10 +7319,10 @@ dnl p1(at_ns1) interface NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f2 ff 00 00 00 02 f2 ff 00 00 00 01 89 4f 02 06 01 03 00 00 64 03 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 f2 00 00 00 00 02 f2 00 00 00 00 01 08 00 45 00 00 28 00 01 00 00 40 06 b0 13 c0 a8 00 0a 0a 00 00 0a 04 00 08 00 00 00 00 c8 00 00 00 00 50 02 20 00 b8 5e 00 00 > /dev/null]) dnl Check the expected de-capsulated TCP packet on the egress interface @@ -64439,7 +64955,7 @@ index f22d86e466..69de604fa0 100644 OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP -@@ -7072,12 +7316,12 @@ dnl p1(at_ns1) interface +@@ -7072,12 +7352,12 @@ dnl p1(at_ns1) interface NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f2 ff 00 00 00 02 f2 ff 00 00 00 01 89 4f 02 06 01 03 00 01 00 03 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 f2 00 00 00 00 02 f2 00 00 00 00 01 08 00 45 00 00 28 00 01 00 00 40 06 b0 13 c0 a8 00 0a 0a 00 00 0a 04 00 08 00 00 00 00 c8 00 00 00 00 50 02 20 00 b8 5e 00 00 > /dev/null]) dnl Check the expected NSH packet with new fields in the header @@ -64458,7 +64974,7 @@ index f22d86e466..69de604fa0 100644 OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP -@@ -7106,23 +7350,23 @@ dnl First send packet from at_ns0 --> OVS with SPI=0x100 and SI=2 +@@ -7106,23 +7386,23 @@ dnl First send packet from at_ns0 --> OVS with SPI=0x100 and SI=2 NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f2 ff 00 00 00 02 f2 ff 00 00 00 01 89 4f 02 06 01 03 00 01 00 02 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 f2 00 00 00 00 02 f2 00 00 00 00 01 08 00 45 00 00 28 00 01 00 00 40 06 b0 13 c0 a8 00 0a 0a 00 00 0a 04 00 08 00 00 00 00 c8 00 00 00 00 50 02 20 00 b8 5e 00 00 > /dev/null]) dnl Check for the above packet on p1 interface @@ -65348,10 +65864,37 @@ index 3f58e3e8fd..8c5af459e9 100644 AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 5'], [0], [dnl diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at -index 57589758f4..c9a04c76bd 100644 +index 57589758f4..50f90815a1 100644 --- a/tests/tunnel-push-pop.at +++ b/tests/tunnel-push-pop.at -@@ -546,6 +546,28 @@ AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port [[37]]' | sort], [0], [dnl +@@ -369,6 +369,26 @@ AT_CHECK([ovs-appctl tnl/neigh/show | grep br | sort], [0], [dnl + 1.1.2.92 f8:bc:12:44:34:b6 br0 + ]) + ++dnl Receiving Gratuitous ARP request with correct VLAN id should alter tunnel neighbor cache ++AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(1),eth(src=f8:bc:12:44:34:c8,dst=ff:ff:ff:ff:ff:ff),eth_type(0x8100),vlan(vid=10,pcp=7),encap(eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.92,op=1,sha=f8:bc:12:44:34:c8,tha=00:00:00:00:00:00))']) ++ ++ovs-appctl time/warp 1000 ++ovs-appctl time/warp 1000 ++ ++AT_CHECK([ovs-appctl tnl/neigh/show | grep br | sort], [0], [dnl ++1.1.2.92 f8:bc:12:44:34:c8 br0 ++]) ++ ++dnl Receiving Gratuitous ARP reply with correct VLAN id should alter tunnel neighbor cache ++AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(1),eth(src=f8:bc:12:44:34:b2,dst=ff:ff:ff:ff:ff:ff),eth_type(0x8100),vlan(vid=10,pcp=7),encap(eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.92,op=2,sha=f8:bc:12:44:34:b2,tha=f8:bc:12:44:34:b2))']) ++ ++ovs-appctl time/warp 1000 ++ovs-appctl time/warp 1000 ++ ++AT_CHECK([ovs-appctl tnl/neigh/show | grep br | sort], [0], [dnl ++1.1.2.92 f8:bc:12:44:34:b2 br0 ++]) ++ + dnl Receive ARP reply without VLAN header + AT_CHECK([ovs-vsctl set port br0 tag=0]) + AT_CHECK([ovs-appctl tnl/neigh/flush], [0], [OK +@@ -546,6 +566,28 @@ AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port [[37]]' | sort], [0], [dnl port 7: rx pkts=5, bytes=434, drop=?, errs=?, frame=?, over=?, crc=? ]) @@ -65380,7 +65923,7 @@ index 57589758f4..c9a04c76bd 100644 dnl Check decapsulation of Geneve packet with options AT_CAPTURE_FILE([ofctl_monitor.log]) AT_CHECK([ovs-ofctl monitor int-br 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log]) -@@ -559,14 +581,14 @@ OVS_APP_EXIT_AND_WAIT(ovs-ofctl) +@@ -559,14 +601,14 @@ OVS_APP_EXIT_AND_WAIT(ovs-ofctl) AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN2 (xid=0x0): cookie=0x0 total_len=98 tun_id=0x7b,tun_src=1.1.2.92,tun_dst=1.1.2.88,tun_metadata0=0xa,in_port=5 (via action) data_len=98 (unbuffered) @@ -65398,7 +65941,7 @@ index 57589758f4..c9a04c76bd 100644 ]) dnl Receive VXLAN with different MAC and verify that the neigh cache gets updated -@@ -718,14 +740,14 @@ dnl Output to tunnel from a int-br internal port. +@@ -718,14 +760,14 @@ dnl Output to tunnel from a int-br internal port. dnl Checking that the packet arrived and it was correctly encapsulated. AT_CHECK([ovs-ofctl add-flow int-br "in_port=LOCAL,actions=debug_slow,output:2"]) AT_CHECK([ovs-appctl netdev-dummy/receive int-br "${packet}4"]) @@ -65416,7 +65959,7 @@ index 57589758f4..c9a04c76bd 100644 dnl Datapath actions should not have tunnel push action. AT_CHECK([ovs-appctl dpctl/dump-flows | grep -q tnl_push], [1]) -@@ -842,3 +864,54 @@ Datapath actions: 7 +@@ -842,3 +884,54 @@ Datapath actions: 7 OVS_VSWITCHD_STOP AT_CLEANUP @@ -65556,10 +66099,18 @@ index fb2025b765..67092ecf7e 100755 awk '/^ *0x/ {if (cnt != 0) printf ","; \ cnt++;printf "{class="$1",type="$2",len="$3"}->"$4}' diff --git a/utilities/ovs-tcpdump.in b/utilities/ovs-tcpdump.in -index 82d1bedfa6..e12bab8895 100755 +index 82d1bedfa6..a49ec9f942 100755 --- a/utilities/ovs-tcpdump.in +++ b/utilities/ovs-tcpdump.in -@@ -165,6 +165,9 @@ class OVSDB(object): +@@ -44,6 +44,7 @@ try: + from ovs import jsonrpc + from ovs.poller import Poller + from ovs.stream import Stream ++ from ovs.fatal_signal import add_hook + except Exception: + print("ERROR: Please install the correct Open vSwitch python support") + print(" libraries (version @VERSION@).") +@@ -165,6 +166,9 @@ class OVSDB(object): self._idl_conn = idl.Idl(db_sock, schema) OVSDB.wait_for_db_change(self._idl_conn) # Initial Sync with DB @@ -65569,7 +66120,7 @@ index 82d1bedfa6..e12bab8895 100755 def _get_schema(self): error, strm = Stream.open_block(Stream.open(self._db_sock)) if error: -@@ -222,6 +225,13 @@ class OVSDB(object): +@@ -222,6 +226,13 @@ class OVSDB(object): def interface_mtu(self, intf_name): try: intf = self._find_row_by_name('Interface', intf_name) @@ -65583,9 +66134,28 @@ index 82d1bedfa6..e12bab8895 100755 return intf.mtu[0] except Exception: return None -@@ -403,7 +413,8 @@ def py_which(executable): +@@ -402,8 +413,27 @@ def py_which(executable): + for path in os.environ["PATH"].split(os.pathsep)) ++def teardown(db_sock, interface, mirror_interface, tap_created): ++ def cleanup_mirror(): ++ try: ++ ovsdb = OVSDB(db_sock) ++ ovsdb.destroy_mirror(interface, ovsdb.port_bridge(interface)) ++ ovsdb.destroy_port(mirror_interface, ovsdb.port_bridge(interface)) ++ if tap_created is True: ++ _del_taps[sys.platform](mirror_interface) ++ except Exception: ++ print("Unable to tear down the ports and mirrors.") ++ print("Please use ovs-vsctl to remove the ports and mirrors" ++ " created.") ++ print(" ex: ovs-vsctl --db=%s del-port %s" % (db_sock, ++ mirror_interface)) ++ ++ add_hook(cleanup_mirror, None, True) ++ ++ def main(): - db_sock = 'unix:@RUNDIR@/db.sock' + rundir = os.environ.get('OVS_RUNDIR', '@RUNDIR@') @@ -65593,8 +66163,26 @@ index 82d1bedfa6..e12bab8895 100755 interface = None tcpdargs = [] -@@ -500,6 +511,8 @@ def main(): - pass +@@ -485,6 +515,9 @@ def main(): + print("ERROR: Mirror port (%s) exists for port %s." % + (mirror_interface, interface)) + sys.exit(1) ++ ++ teardown(db_sock, interface, mirror_interface, tap_created) ++ + try: + ovsdb.make_port(mirror_interface, ovsdb.port_bridge(interface)) + ovsdb.bridge_mirror(interface, mirror_interface, +@@ -492,14 +525,10 @@ def main(): + mirror_select_all) + except OVSDBException as oe: + print("ERROR: Unable to properly setup the mirror: %s." % str(oe)) +- try: +- ovsdb.destroy_port(mirror_interface, ovsdb.port_bridge(interface)) +- if tap_created is True: +- _del_taps[sys.platform](mirror_interface) +- except Exception: +- pass sys.exit(1) + ovsdb.close_idl() @@ -65602,14 +66190,24 @@ index 82d1bedfa6..e12bab8895 100755 pipes = _doexec(*([dump_cmd, '-i', mirror_interface] + tcpdargs)) try: while pipes.poll() is None: -@@ -512,6 +525,7 @@ def main(): +@@ -512,17 +541,6 @@ def main(): if pipes.poll() is None: pipes.terminate() -+ ovsdb = OVSDB(db_sock) - ovsdb.destroy_mirror(interface, ovsdb.port_bridge(interface)) - ovsdb.destroy_port(mirror_interface, ovsdb.port_bridge(interface)) - if tap_created is True: +- ovsdb.destroy_mirror(interface, ovsdb.port_bridge(interface)) +- ovsdb.destroy_port(mirror_interface, ovsdb.port_bridge(interface)) +- if tap_created is True: +- _del_taps[sys.platform](mirror_interface) +- except Exception: +- print("Unable to tear down the ports and mirrors.") +- print("Please use ovs-vsctl to remove the ports and mirrors created.") +- print(" ex: ovs-vsctl --db=%s del-port %s" % (db_sock, +- mirror_interface)) +- sys.exit(1) +- + sys.exit(0) + + diff --git a/utilities/ovs-vsctl-bashcomp.bash b/utilities/ovs-vsctl-bashcomp.bash old mode 100755 new mode 100644 @@ -65984,6 +66582,19 @@ index 5223aa8970..e328d8ead1 100644 union ovsdb_atom atom; atom.uuid = m->uuid; +diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml +index 0c66326171..87d8f3e67a 100644 +--- a/vswitchd/vswitch.xml ++++ b/vswitchd/vswitch.xml +@@ -2312,7 +2312,7 @@ + lowest port-id is elected as the root. + + +- + The port path cost. The Port's contribution, when it is + the Root Port, to the Root Path Cost for the Bridge. By default the diff --git a/vtep/vtep-ctl.c b/vtep/vtep-ctl.c index ab552457d9..99c4adcd53 100644 --- a/vtep/vtep-ctl.c diff --git a/SPECS/openvswitch2.17.spec b/SPECS/openvswitch2.17.spec index c052166..b72036e 100644 --- a/SPECS/openvswitch2.17.spec +++ b/SPECS/openvswitch2.17.spec @@ -57,7 +57,7 @@ Summary: Open vSwitch Group: System Environment/Daemons daemon/database/utilities URL: http://www.openvswitch.org/ Version: 2.17.0 -Release: 59%{?dist} +Release: 61%{?dist} # Nearly all of openvswitch is ASL 2.0. The bugtool is LGPLv2+, and the # lib/sflow*.[ch] files are SISSL @@ -743,6 +743,30 @@ exit 0 %endif %changelog +* Wed Nov 02 2022 Open vSwitch CI - 2.17.0-61 +- Merging upstream branch-2.17 [RH git: bf6774bd2c] + Commit list: + fa95bf9621 ovs-tcpdump: Cleanup mirror port on SIGHUP/SIGTERM. + 7ebef81f91 netdev-linux: Fix inability to apply QoS on ports with custom qdiscs. (#2138339) + 037ef6301b tc: Fix misaligned writes while parsing pedit. + 869e2e1ba0 odp-util: Add missing separator in format_odp_conntrack_action(). + 0aa55709fc vswitch.xml: Fix the name of rstp-path-cost option. + af459fa370 mac-learning: Fix learned fdb entries not age out issue. + c4336a1f12 ofproto-dpif-xlate: Update tunnel neighbor when receive gratuitous ARP. + 683508cd4e bond: Fix crash while logging not yet enabled member. + 41b178d525 netdev-dpdk: Fix tx_dropped counters value. + + +* Wed Oct 26 2022 Open vSwitch CI - 2.17.0-60 +- Merging upstream branch-2.17 [RH git: 4ad2c662f3] + Commit list: + d0276481a1 unaligned: Correct the stats of packet_count and byte_count on Windows. + 71401199ff tests: Fix filtering of whole-second durations. + 3c1c034e58 netdev-offload: Set 'miss_api_supported' to be under netdev. + 35615cd37a cmap: Add thread fence for slot update. + 5f8ba216a4 ofproto-dpif-xlate: Do not use zero-weight buckets in select groups. + + * Thu Oct 13 2022 Open vSwitch CI - 2.17.0-59 - Merging upstream branch-2.17 [RH git: ff2d81a848] Commit list: