2021-07-09 15:58:15 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2015 Nicira, Inc.
|
|
|
|
* Copyright (c) 2019, 2020, 2021 Intel Corporation.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at:
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef DPIF_NETDEV_PRIVATE_THREAD_H
|
|
|
|
#define DPIF_NETDEV_PRIVATE_THREAD_H 1
|
|
|
|
|
|
|
|
#include "dpif.h"
|
|
|
|
#include "dpif-netdev-perf.h"
|
|
|
|
#include "dpif-netdev-private-dfc.h"
|
2021-07-09 15:58:17 +00:00
|
|
|
#include "dpif-netdev-private-dpif.h"
|
2021-07-09 15:58:15 +00:00
|
|
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
|
dpif-netdev: Forwarding optimization for flows with a simple match.
There are cases where users might want simple forwarding or drop rules
for all packets received from a specific port, e.g ::
"in_port=1,actions=2"
"in_port=2,actions=IN_PORT"
"in_port=3,vlan_tci=0x1234/0x1fff,actions=drop"
"in_port=4,actions=push_vlan:0x8100,set_field:4196->vlan_vid,output:3"
There are also cases where complex OpenFlow rules can be simplified
down to datapath flows with very simple match criteria.
In theory, for very simple forwarding, OVS doesn't need to parse
packets at all in order to follow these rules. "Simple match" lookup
optimization is intended to speed up packet forwarding in these cases.
Design:
Due to various implementation constraints userspace datapath has
following flow fields always in exact match (i.e. it's required to
match at least these fields of a packet even if the OF rule doesn't
need that):
- recirc_id
- in_port
- packet_type
- dl_type
- vlan_tci (CFI + VID) - in most cases
- nw_frag - for ip packets
Not all of these fields are related to packet itself. We already
know the current 'recirc_id' and the 'in_port' before starting the
packet processing. It also seems safe to assume that we're working
with Ethernet packets. So, for the simple OF rule we need to match
only on 'dl_type', 'vlan_tci' and 'nw_frag'.
'in_port', 'dl_type', 'nw_frag' and 13 bits of 'vlan_tci' can be
combined in a single 64bit integer (mark) that can be used as a
hash in hash map. We are using only VID and CFI form the 'vlan_tci',
flows that need to match on PCP will not qualify for the optimization.
Workaround for matching on non-existence of vlan updated to match on
CFI and VID only in order to qualify for the optimization. CFI is
always set by OVS if vlan is present in a packet, so there is no need
to match on PCP in this case. 'nw_frag' takes 2 bits of PCP inside
the simple match mark.
New per-PMD flow table 'simple_match_table' introduced to store
simple match flows only. 'dp_netdev_flow_add' adds flow to the
usual 'flow_table' and to the 'simple_match_table' if the flow
meets following constraints:
- 'recirc_id' in flow match is 0.
- 'packet_type' in flow match is Ethernet.
- Flow wildcards contains only minimal set of non-wildcarded fields
(listed above).
If the number of flows for current 'in_port' in a regular 'flow_table'
equals number of flows for current 'in_port' in a 'simple_match_table',
we may use simple match optimization, because all the flows we have
are simple match flows. This means that we only need to parse
'dl_type', 'vlan_tci' and 'nw_frag' to perform packet matching.
Now we make the unique flow mark from the 'in_port', 'dl_type',
'nw_frag' and 'vlan_tci' and looking for it in the 'simple_match_table'.
On successful lookup we don't need to run full 'miniflow_extract()'.
Unsuccessful lookup technically means that we have no suitable flow
in the datapath and upcall will be required. So, in this case EMC and
SMC lookups are disabled. We may optimize this path in the future by
bypassing the dpcls lookup too.
Performance improvement of this solution on a 'simple match' flows
should be comparable with partial HW offloading, because it parses same
packet fields and uses similar flow lookup scheme.
However, unlike partial HW offloading, it works for all port types
including virtual ones.
Performance results when compared to EMC:
Test setup:
virtio-user OVS virtio-user
Testpmd1 ------------> pmd1 ------------> Testpmd2
(txonly) x<------ pmd2 <------------ (mac swap)
Single stream of 64byte packets. Actions:
in_port=vhost0,actions=vhost1
in_port=vhost1,actions=vhost0
Stats collected from pmd1 and pmd2, so there are 2 scenarios:
Virt-to-Virt : Testpmd1 ------> pmd1 ------> Testpmd2.
Virt-to-NoCopy : Testpmd2 ------> pmd2 --->x Testpmd1.
Here the packet sent from pmd2 to Testpmd1 is always dropped, because
the virtqueue is full since Testpmd1 is in txonly mode and doesn't
receive any packets. This should be closer to the performance of a
VM-to-Phy scenario.
Test performed on machine with Intel Xeon CPU E5-2690 v4 @ 2.60GHz.
Table below represents improvement in throughput when compared to EMC.
+----------------+------------------------+------------------------+
| | Default (-g -O2) | "-Ofast -march=native" |
| Scenario +------------+-----------+------------+-----------+
| | GCC | Clang | GCC | Clang |
+----------------+------------+-----------+------------+-----------+
| Virt-to-Virt | +18.9% | +25.5% | +10.8% | +16.7% |
| Virt-to-NoCopy | +24.3% | +33.7% | +14.9% | +22.0% |
+----------------+------------+-----------+------------+-----------+
For Phy-to-Phy case performance improvement should be even higher, but
it's not the main use-case for this functionality. Performance
difference for the non-simple flows is within a margin of error.
Acked-by: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
2021-08-09 14:57:52 +02:00
|
|
|
#include "ccmap.h"
|
2021-07-09 15:58:15 +00:00
|
|
|
#include "cmap.h"
|
2021-07-15 21:36:07 +05:30
|
|
|
|
|
|
|
#include "dpif-netdev-private-dfc.h"
|
|
|
|
#include "dpif-netdev-private-dpif.h"
|
|
|
|
#include "dpif-netdev-perf.h"
|
|
|
|
#include "dpif-netdev-private-extract.h"
|
2021-07-09 15:58:15 +00:00
|
|
|
#include "openvswitch/thread.h"
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* PMD Thread Structures */
|
|
|
|
|
|
|
|
/* A set of properties for the current processing loop that is not directly
|
|
|
|
* associated with the pmd thread itself, but with the packets being
|
|
|
|
* processed or the short-term system configuration (for example, time).
|
|
|
|
* Contained by struct dp_netdev_pmd_thread's 'ctx' member. */
|
|
|
|
struct dp_netdev_pmd_thread_ctx {
|
|
|
|
/* Latest measured time. See 'pmd_thread_ctx_time_update()'. */
|
|
|
|
long long now;
|
|
|
|
/* RX queue from which last packet was received. */
|
|
|
|
struct dp_netdev_rxq *last_rxq;
|
|
|
|
/* EMC insertion probability context for the current processing cycle. */
|
|
|
|
uint32_t emc_insert_min;
|
2021-07-09 15:58:17 +00:00
|
|
|
/* Enable the SMC cache from ovsdb config. */
|
|
|
|
bool smc_enable_db;
|
2021-07-09 15:58:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* PMD: Poll modes drivers. PMD accesses devices via polling to eliminate
|
|
|
|
* the performance overhead of interrupt processing. Therefore netdev can
|
|
|
|
* not implement rx-wait for these devices. dpif-netdev needs to poll
|
|
|
|
* these device to check for recv buffer. pmd-thread does polling for
|
|
|
|
* devices assigned to itself.
|
|
|
|
*
|
|
|
|
* DPDK used PMD for accessing NIC.
|
|
|
|
*
|
|
|
|
* Note, instance with cpu core id NON_PMD_CORE_ID will be reserved for
|
|
|
|
* I/O of all non-pmd threads. There will be no actual thread created
|
|
|
|
* for the instance.
|
|
|
|
*
|
|
|
|
* Each struct has its own flow cache and classifier per managed ingress port.
|
|
|
|
* For packets received on ingress port, a look up is done on corresponding PMD
|
|
|
|
* thread's flow cache and in case of a miss, lookup is performed in the
|
|
|
|
* corresponding classifier of port. Packets are executed with the found
|
|
|
|
* actions in either case.
|
|
|
|
* */
|
|
|
|
struct dp_netdev_pmd_thread {
|
|
|
|
struct dp_netdev *dp;
|
|
|
|
struct ovs_refcount ref_cnt; /* Every reference must be refcount'ed. */
|
|
|
|
struct cmap_node node; /* In 'dp->poll_threads'. */
|
|
|
|
|
2021-09-09 16:30:47 +01:00
|
|
|
/* Per thread exact match cache and signature match cache. Note, the
|
|
|
|
* instance for cpu core NON_PMD_CORE_ID can be accessed by multiple
|
|
|
|
* threads, and thusly need to be protected by 'non_pmd_mutex'. Every
|
|
|
|
* other instance will only be accessed by its own pmd thread. */
|
2022-01-24 15:17:40 +01:00
|
|
|
struct dfc_cache flow_cache;
|
2021-07-09 15:58:15 +00:00
|
|
|
|
|
|
|
/* Flow-Table and classifiers
|
|
|
|
*
|
dpif-netdev: Forwarding optimization for flows with a simple match.
There are cases where users might want simple forwarding or drop rules
for all packets received from a specific port, e.g ::
"in_port=1,actions=2"
"in_port=2,actions=IN_PORT"
"in_port=3,vlan_tci=0x1234/0x1fff,actions=drop"
"in_port=4,actions=push_vlan:0x8100,set_field:4196->vlan_vid,output:3"
There are also cases where complex OpenFlow rules can be simplified
down to datapath flows with very simple match criteria.
In theory, for very simple forwarding, OVS doesn't need to parse
packets at all in order to follow these rules. "Simple match" lookup
optimization is intended to speed up packet forwarding in these cases.
Design:
Due to various implementation constraints userspace datapath has
following flow fields always in exact match (i.e. it's required to
match at least these fields of a packet even if the OF rule doesn't
need that):
- recirc_id
- in_port
- packet_type
- dl_type
- vlan_tci (CFI + VID) - in most cases
- nw_frag - for ip packets
Not all of these fields are related to packet itself. We already
know the current 'recirc_id' and the 'in_port' before starting the
packet processing. It also seems safe to assume that we're working
with Ethernet packets. So, for the simple OF rule we need to match
only on 'dl_type', 'vlan_tci' and 'nw_frag'.
'in_port', 'dl_type', 'nw_frag' and 13 bits of 'vlan_tci' can be
combined in a single 64bit integer (mark) that can be used as a
hash in hash map. We are using only VID and CFI form the 'vlan_tci',
flows that need to match on PCP will not qualify for the optimization.
Workaround for matching on non-existence of vlan updated to match on
CFI and VID only in order to qualify for the optimization. CFI is
always set by OVS if vlan is present in a packet, so there is no need
to match on PCP in this case. 'nw_frag' takes 2 bits of PCP inside
the simple match mark.
New per-PMD flow table 'simple_match_table' introduced to store
simple match flows only. 'dp_netdev_flow_add' adds flow to the
usual 'flow_table' and to the 'simple_match_table' if the flow
meets following constraints:
- 'recirc_id' in flow match is 0.
- 'packet_type' in flow match is Ethernet.
- Flow wildcards contains only minimal set of non-wildcarded fields
(listed above).
If the number of flows for current 'in_port' in a regular 'flow_table'
equals number of flows for current 'in_port' in a 'simple_match_table',
we may use simple match optimization, because all the flows we have
are simple match flows. This means that we only need to parse
'dl_type', 'vlan_tci' and 'nw_frag' to perform packet matching.
Now we make the unique flow mark from the 'in_port', 'dl_type',
'nw_frag' and 'vlan_tci' and looking for it in the 'simple_match_table'.
On successful lookup we don't need to run full 'miniflow_extract()'.
Unsuccessful lookup technically means that we have no suitable flow
in the datapath and upcall will be required. So, in this case EMC and
SMC lookups are disabled. We may optimize this path in the future by
bypassing the dpcls lookup too.
Performance improvement of this solution on a 'simple match' flows
should be comparable with partial HW offloading, because it parses same
packet fields and uses similar flow lookup scheme.
However, unlike partial HW offloading, it works for all port types
including virtual ones.
Performance results when compared to EMC:
Test setup:
virtio-user OVS virtio-user
Testpmd1 ------------> pmd1 ------------> Testpmd2
(txonly) x<------ pmd2 <------------ (mac swap)
Single stream of 64byte packets. Actions:
in_port=vhost0,actions=vhost1
in_port=vhost1,actions=vhost0
Stats collected from pmd1 and pmd2, so there are 2 scenarios:
Virt-to-Virt : Testpmd1 ------> pmd1 ------> Testpmd2.
Virt-to-NoCopy : Testpmd2 ------> pmd2 --->x Testpmd1.
Here the packet sent from pmd2 to Testpmd1 is always dropped, because
the virtqueue is full since Testpmd1 is in txonly mode and doesn't
receive any packets. This should be closer to the performance of a
VM-to-Phy scenario.
Test performed on machine with Intel Xeon CPU E5-2690 v4 @ 2.60GHz.
Table below represents improvement in throughput when compared to EMC.
+----------------+------------------------+------------------------+
| | Default (-g -O2) | "-Ofast -march=native" |
| Scenario +------------+-----------+------------+-----------+
| | GCC | Clang | GCC | Clang |
+----------------+------------+-----------+------------+-----------+
| Virt-to-Virt | +18.9% | +25.5% | +10.8% | +16.7% |
| Virt-to-NoCopy | +24.3% | +33.7% | +14.9% | +22.0% |
+----------------+------------+-----------+------------+-----------+
For Phy-to-Phy case performance improvement should be even higher, but
it's not the main use-case for this functionality. Performance
difference for the non-simple flows is within a margin of error.
Acked-by: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
2021-08-09 14:57:52 +02:00
|
|
|
* Writers of 'flow_table'/'simple_match_table' and their n* ccmap's must
|
|
|
|
* take the 'flow_mutex'. Corresponding changes to 'classifiers' must be
|
|
|
|
* made while still holding the 'flow_mutex'.
|
2021-07-09 15:58:15 +00:00
|
|
|
*/
|
|
|
|
struct ovs_mutex flow_mutex;
|
|
|
|
struct cmap flow_table OVS_GUARDED; /* Flow table. */
|
dpif-netdev: Forwarding optimization for flows with a simple match.
There are cases where users might want simple forwarding or drop rules
for all packets received from a specific port, e.g ::
"in_port=1,actions=2"
"in_port=2,actions=IN_PORT"
"in_port=3,vlan_tci=0x1234/0x1fff,actions=drop"
"in_port=4,actions=push_vlan:0x8100,set_field:4196->vlan_vid,output:3"
There are also cases where complex OpenFlow rules can be simplified
down to datapath flows with very simple match criteria.
In theory, for very simple forwarding, OVS doesn't need to parse
packets at all in order to follow these rules. "Simple match" lookup
optimization is intended to speed up packet forwarding in these cases.
Design:
Due to various implementation constraints userspace datapath has
following flow fields always in exact match (i.e. it's required to
match at least these fields of a packet even if the OF rule doesn't
need that):
- recirc_id
- in_port
- packet_type
- dl_type
- vlan_tci (CFI + VID) - in most cases
- nw_frag - for ip packets
Not all of these fields are related to packet itself. We already
know the current 'recirc_id' and the 'in_port' before starting the
packet processing. It also seems safe to assume that we're working
with Ethernet packets. So, for the simple OF rule we need to match
only on 'dl_type', 'vlan_tci' and 'nw_frag'.
'in_port', 'dl_type', 'nw_frag' and 13 bits of 'vlan_tci' can be
combined in a single 64bit integer (mark) that can be used as a
hash in hash map. We are using only VID and CFI form the 'vlan_tci',
flows that need to match on PCP will not qualify for the optimization.
Workaround for matching on non-existence of vlan updated to match on
CFI and VID only in order to qualify for the optimization. CFI is
always set by OVS if vlan is present in a packet, so there is no need
to match on PCP in this case. 'nw_frag' takes 2 bits of PCP inside
the simple match mark.
New per-PMD flow table 'simple_match_table' introduced to store
simple match flows only. 'dp_netdev_flow_add' adds flow to the
usual 'flow_table' and to the 'simple_match_table' if the flow
meets following constraints:
- 'recirc_id' in flow match is 0.
- 'packet_type' in flow match is Ethernet.
- Flow wildcards contains only minimal set of non-wildcarded fields
(listed above).
If the number of flows for current 'in_port' in a regular 'flow_table'
equals number of flows for current 'in_port' in a 'simple_match_table',
we may use simple match optimization, because all the flows we have
are simple match flows. This means that we only need to parse
'dl_type', 'vlan_tci' and 'nw_frag' to perform packet matching.
Now we make the unique flow mark from the 'in_port', 'dl_type',
'nw_frag' and 'vlan_tci' and looking for it in the 'simple_match_table'.
On successful lookup we don't need to run full 'miniflow_extract()'.
Unsuccessful lookup technically means that we have no suitable flow
in the datapath and upcall will be required. So, in this case EMC and
SMC lookups are disabled. We may optimize this path in the future by
bypassing the dpcls lookup too.
Performance improvement of this solution on a 'simple match' flows
should be comparable with partial HW offloading, because it parses same
packet fields and uses similar flow lookup scheme.
However, unlike partial HW offloading, it works for all port types
including virtual ones.
Performance results when compared to EMC:
Test setup:
virtio-user OVS virtio-user
Testpmd1 ------------> pmd1 ------------> Testpmd2
(txonly) x<------ pmd2 <------------ (mac swap)
Single stream of 64byte packets. Actions:
in_port=vhost0,actions=vhost1
in_port=vhost1,actions=vhost0
Stats collected from pmd1 and pmd2, so there are 2 scenarios:
Virt-to-Virt : Testpmd1 ------> pmd1 ------> Testpmd2.
Virt-to-NoCopy : Testpmd2 ------> pmd2 --->x Testpmd1.
Here the packet sent from pmd2 to Testpmd1 is always dropped, because
the virtqueue is full since Testpmd1 is in txonly mode and doesn't
receive any packets. This should be closer to the performance of a
VM-to-Phy scenario.
Test performed on machine with Intel Xeon CPU E5-2690 v4 @ 2.60GHz.
Table below represents improvement in throughput when compared to EMC.
+----------------+------------------------+------------------------+
| | Default (-g -O2) | "-Ofast -march=native" |
| Scenario +------------+-----------+------------+-----------+
| | GCC | Clang | GCC | Clang |
+----------------+------------+-----------+------------+-----------+
| Virt-to-Virt | +18.9% | +25.5% | +10.8% | +16.7% |
| Virt-to-NoCopy | +24.3% | +33.7% | +14.9% | +22.0% |
+----------------+------------+-----------+------------+-----------+
For Phy-to-Phy case performance improvement should be even higher, but
it's not the main use-case for this functionality. Performance
difference for the non-simple flows is within a margin of error.
Acked-by: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
2021-08-09 14:57:52 +02:00
|
|
|
struct cmap simple_match_table OVS_GUARDED; /* Flow table with simple
|
|
|
|
match flows only. */
|
|
|
|
/* Number of flows in the 'flow_table' per in_port. */
|
|
|
|
struct ccmap n_flows OVS_GUARDED;
|
|
|
|
/* Number of flows in the 'simple_match_table' per in_port. */
|
|
|
|
struct ccmap n_simple_flows OVS_GUARDED;
|
2021-07-09 15:58:15 +00:00
|
|
|
|
|
|
|
/* One classifier per in_port polled by the pmd */
|
|
|
|
struct cmap classifiers;
|
|
|
|
/* Periodically sort subtable vectors according to hit frequencies */
|
|
|
|
long long int next_optimization;
|
|
|
|
/* End of the next time interval for which processing cycles
|
|
|
|
are stored for each polled rxq. */
|
2021-07-16 18:21:16 +02:00
|
|
|
long long int next_cycle_store;
|
2021-07-09 15:58:15 +00:00
|
|
|
|
|
|
|
/* Last interval timestamp. */
|
|
|
|
uint64_t intrvl_tsc_prev;
|
|
|
|
/* Last interval cycles. */
|
|
|
|
atomic_ullong intrvl_cycles;
|
|
|
|
|
2021-07-16 18:21:16 +02:00
|
|
|
/* Write index for 'busy_cycles_intrvl'. */
|
2022-11-30 17:39:52 +00:00
|
|
|
atomic_count intrvl_idx;
|
2021-07-16 18:21:16 +02:00
|
|
|
/* Busy cycles in last PMD_INTERVAL_MAX intervals. */
|
|
|
|
atomic_ullong *busy_cycles_intrvl;
|
|
|
|
|
2021-07-09 15:58:15 +00:00
|
|
|
/* Current context of the PMD thread. */
|
|
|
|
struct dp_netdev_pmd_thread_ctx ctx;
|
|
|
|
|
2021-07-09 15:58:16 +00:00
|
|
|
/* Function pointer to call for dp_netdev_input() functionality. */
|
|
|
|
ATOMIC(dp_netdev_input_func) netdev_input_func;
|
|
|
|
|
2021-07-09 15:58:17 +00:00
|
|
|
/* Pointer for per-DPIF implementation scratch space. */
|
|
|
|
void *netdev_input_func_userdata;
|
|
|
|
|
2021-07-15 21:36:07 +05:30
|
|
|
/* Function pointer to call for miniflow_extract() functionality. */
|
|
|
|
ATOMIC(miniflow_extract_func) miniflow_extract_opt;
|
|
|
|
|
2021-07-09 15:58:15 +00:00
|
|
|
struct seq *reload_seq;
|
|
|
|
uint64_t last_reload_seq;
|
|
|
|
|
|
|
|
/* These are atomic variables used as a synchronization and configuration
|
|
|
|
* points for thread reload/exit.
|
|
|
|
*
|
|
|
|
* 'reload' atomic is the main one and it's used as a memory
|
|
|
|
* synchronization point for all other knobs and data.
|
|
|
|
*
|
|
|
|
* For a thread that requests PMD reload:
|
|
|
|
*
|
|
|
|
* * All changes that should be visible to the PMD thread must be made
|
|
|
|
* before setting the 'reload'. These changes could use any memory
|
|
|
|
* ordering model including 'relaxed'.
|
|
|
|
* * Setting the 'reload' atomic should occur in the same thread where
|
|
|
|
* all other PMD configuration options updated.
|
|
|
|
* * Setting the 'reload' atomic should be done with 'release' memory
|
|
|
|
* ordering model or stricter. This will guarantee that all previous
|
|
|
|
* changes (including non-atomic and 'relaxed') will be visible to
|
|
|
|
* the PMD thread.
|
|
|
|
* * To check that reload is done, thread should poll the 'reload' atomic
|
|
|
|
* to become 'false'. Polling should be done with 'acquire' memory
|
|
|
|
* ordering model or stricter. This ensures that PMD thread completed
|
|
|
|
* the reload process.
|
|
|
|
*
|
|
|
|
* For the PMD thread:
|
|
|
|
*
|
|
|
|
* * PMD thread should read 'reload' atomic with 'acquire' memory
|
|
|
|
* ordering model or stricter. This will guarantee that all changes
|
|
|
|
* made before setting the 'reload' in the requesting thread will be
|
|
|
|
* visible to the PMD thread.
|
|
|
|
* * All other configuration data could be read with any memory
|
|
|
|
* ordering model (including non-atomic and 'relaxed') but *only after*
|
|
|
|
* reading the 'reload' atomic set to 'true'.
|
|
|
|
* * When the PMD reload done, PMD should (optionally) set all the below
|
|
|
|
* knobs except the 'reload' to their default ('false') values and
|
|
|
|
* (mandatory), as the last step, set the 'reload' to 'false' using
|
|
|
|
* 'release' memory ordering model or stricter. This will inform the
|
|
|
|
* requesting thread that PMD has completed a reload cycle.
|
|
|
|
*/
|
|
|
|
atomic_bool reload; /* Do we need to reload ports? */
|
|
|
|
atomic_bool wait_for_reload; /* Can we busy wait for the next reload? */
|
|
|
|
atomic_bool reload_tx_qid; /* Do we need to reload static_tx_qid? */
|
|
|
|
atomic_bool exit; /* For terminating the pmd thread. */
|
|
|
|
|
|
|
|
pthread_t thread;
|
|
|
|
unsigned core_id; /* CPU core id of this pmd thread. */
|
|
|
|
int numa_id; /* numa node id of this pmd thread. */
|
|
|
|
bool isolated;
|
|
|
|
|
2023-12-14 11:15:15 +00:00
|
|
|
/* Max sleep request in microseconds. */
|
|
|
|
atomic_uint64_t max_sleep;
|
|
|
|
|
2021-07-09 15:58:15 +00:00
|
|
|
/* Queue id used by this pmd thread to send packets on all netdevs if
|
|
|
|
* XPS disabled for this netdev. All static_tx_qid's are unique and less
|
|
|
|
* than 'cmap_count(dp->poll_threads)'. */
|
|
|
|
uint32_t static_tx_qid;
|
|
|
|
|
|
|
|
/* Number of filled output batches. */
|
|
|
|
int n_output_batches;
|
|
|
|
|
|
|
|
struct ovs_mutex port_mutex; /* Mutex for 'poll_list' and 'tx_ports'. */
|
|
|
|
/* List of rx queues to poll. */
|
|
|
|
struct hmap poll_list OVS_GUARDED;
|
|
|
|
/* Map of 'tx_port's used for transmission. Written by the main thread,
|
|
|
|
* read by the pmd thread. */
|
|
|
|
struct hmap tx_ports OVS_GUARDED;
|
|
|
|
|
|
|
|
struct ovs_mutex bond_mutex; /* Protects updates of 'tx_bonds'. */
|
|
|
|
/* Map of 'tx_bond's used for transmission. Written by the main thread
|
|
|
|
* and read by the pmd thread. */
|
|
|
|
struct cmap tx_bonds;
|
|
|
|
|
|
|
|
/* These are thread-local copies of 'tx_ports'. One contains only tunnel
|
|
|
|
* ports (that support push_tunnel/pop_tunnel), the other contains ports
|
|
|
|
* with at least one txq (that support send). A port can be in both.
|
|
|
|
*
|
|
|
|
* There are two separate maps to make sure that we don't try to execute
|
|
|
|
* OUTPUT on a device which has 0 txqs or PUSH/POP on a non-tunnel device.
|
|
|
|
*
|
|
|
|
* The instances for cpu core NON_PMD_CORE_ID can be accessed by multiple
|
|
|
|
* threads, and thusly need to be protected by 'non_pmd_mutex'. Every
|
|
|
|
* other instance will only be accessed by its own pmd thread. */
|
|
|
|
struct hmap tnl_port_cache;
|
|
|
|
struct hmap send_port_cache;
|
|
|
|
|
|
|
|
/* Keep track of detailed PMD performance statistics. */
|
|
|
|
struct pmd_perf_stats perf_stats;
|
|
|
|
|
|
|
|
/* Stats from previous iteration used by automatic pmd
|
|
|
|
* load balance logic. */
|
|
|
|
uint64_t prev_stats[PMD_N_STATS];
|
|
|
|
atomic_count pmd_overloaded;
|
|
|
|
|
|
|
|
/* Set to true if the pmd thread needs to be reloaded. */
|
|
|
|
bool need_reload;
|
|
|
|
|
|
|
|
/* Next time when PMD should try RCU quiescing. */
|
|
|
|
long long next_rcu_quiesce;
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* dpif-netdev-private-thread.h */
|