mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 06:15:47 +00:00
userspace: Switching of L3 packets in L2 pipeline
Ports have a new layer3 attribute if they send/receive L3 packets. The packet_type included in structs dp_packet and flow is considered in ofproto-dpif. The classical L2 match fields (dl_src, dl_dst, dl_type, and vlan_tci, vlan_vid, vlan_pcp) now have Ethernet as pre-requisite. A dummy ethernet header is pushed to L3 packets received from L3 ports before the the pipeline processing starts. The ethernet header is popped before sending a packet to a L3 port. For datapath ports that can receive L2 or L3 packets, the packet_type becomes part of the flow key for datapath flows and is handled appropriately in dpif-netdev. In the 'else' branch in flow_put_on_pmd() function, the additional check flow_equal(&match.flow, &netdev_flow->flow) was removed, as a) the dpcls lookup is sufficient to uniquely identify a flow and b) it caused false negatives because the flow in netdev->flow may not properly masked. In dpif_netdev_flow_put() we now use the same method for constructing the netdev_flow_key as the one used when adding the flow to the dplcs to make sure these always match. The function netdev_flow_key_from_flow() used so far was not only inefficient but sometimes caused mismatches and subsequent flow update failures. The kernel datapath does not support the packet_type match field. Instead it encodes the packet type implictly by the presence or absence of the Ethernet attribute in the flow key and mask. This patch filters the PACKET_TYPE attribute out of netlink flow key and mask to be sent to the kernel datapath. Signed-off-by: Lorand Jakab <lojakab@cisco.com> Signed-off-by: Simon Horman <simon.horman@netronome.com> Signed-off-by: Jiri Benc <jbenc@redhat.com> Signed-off-by: Yi Yang <yi.y.yang@intel.com> Signed-off-by: Jan Scheurich <jan.scheurich@ericsson.com> Co-authored-by: Zoltan Balogh <zoltan.balogh@ericsson.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
@@ -1918,24 +1918,6 @@ netdev_flow_key_clone(struct netdev_flow_key *dst,
|
||||
offsetof(struct netdev_flow_key, mf) + src->len);
|
||||
}
|
||||
|
||||
/* Slow. */
|
||||
static void
|
||||
netdev_flow_key_from_flow(struct netdev_flow_key *dst,
|
||||
const struct flow *src)
|
||||
{
|
||||
struct dp_packet packet;
|
||||
uint64_t buf_stub[512 / 8];
|
||||
|
||||
dp_packet_use_stub(&packet, buf_stub, sizeof buf_stub);
|
||||
pkt_metadata_from_flow(&packet.md, src);
|
||||
flow_compose(&packet, src);
|
||||
miniflow_extract(&packet, &dst->mf);
|
||||
dp_packet_uninit(&packet);
|
||||
|
||||
dst->len = netdev_flow_key_size(miniflow_n_values(&dst->mf));
|
||||
dst->hash = 0; /* Not computed yet. */
|
||||
}
|
||||
|
||||
/* Initialize a netdev_flow_key 'mask' from 'match'. */
|
||||
static inline void
|
||||
netdev_flow_mask_init(struct netdev_flow_key *mask,
|
||||
@@ -2411,7 +2393,7 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd,
|
||||
cmap_insert(&pmd->flow_table, CONST_CAST(struct cmap_node *, &flow->node),
|
||||
dp_netdev_flow_hash(&flow->ufid));
|
||||
|
||||
if (OVS_UNLIKELY(VLOG_IS_DBG_ENABLED())) {
|
||||
if (OVS_UNLIKELY(!VLOG_DROP_DBG((&upcall_rl)))) {
|
||||
struct ds ds = DS_EMPTY_INITIALIZER;
|
||||
struct ofpbuf key_buf, mask_buf;
|
||||
struct odp_flow_key_parms odp_parms = {
|
||||
@@ -2436,10 +2418,21 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd,
|
||||
ds_put_cstr(&ds, ", actions:");
|
||||
format_odp_actions(&ds, actions, actions_len);
|
||||
|
||||
VLOG_DBG_RL(&upcall_rl, "%s", ds_cstr(&ds));
|
||||
VLOG_DBG("%s", ds_cstr(&ds));
|
||||
|
||||
ofpbuf_uninit(&key_buf);
|
||||
ofpbuf_uninit(&mask_buf);
|
||||
|
||||
/* Add a printout of the actual match installed. */
|
||||
struct match m;
|
||||
ds_clear(&ds);
|
||||
ds_put_cstr(&ds, "flow match: ");
|
||||
miniflow_expand(&flow->cr.flow.mf, &m.flow);
|
||||
miniflow_expand(&flow->cr.mask->mf, &m.wc.masks);
|
||||
match_format(&m, NULL, &ds, OFP_DEFAULT_PRIORITY);
|
||||
|
||||
VLOG_DBG("%s", ds_cstr(&ds));
|
||||
|
||||
ds_destroy(&ds);
|
||||
}
|
||||
|
||||
@@ -2476,8 +2469,7 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd,
|
||||
error = ENOENT;
|
||||
}
|
||||
} else {
|
||||
if (put->flags & DPIF_FP_MODIFY
|
||||
&& flow_equal(&match->flow, &netdev_flow->flow)) {
|
||||
if (put->flags & DPIF_FP_MODIFY) {
|
||||
struct dp_netdev_actions *new_actions;
|
||||
struct dp_netdev_actions *old_actions;
|
||||
|
||||
@@ -2519,7 +2511,7 @@ static int
|
||||
dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put)
|
||||
{
|
||||
struct dp_netdev *dp = get_dp_netdev(dpif);
|
||||
struct netdev_flow_key key;
|
||||
struct netdev_flow_key key, mask;
|
||||
struct dp_netdev_pmd_thread *pmd;
|
||||
struct match match;
|
||||
ovs_u128 ufid;
|
||||
@@ -2548,9 +2540,10 @@ dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put)
|
||||
}
|
||||
|
||||
/* Must produce a netdev_flow_key for lookup.
|
||||
* This interface is no longer performance critical, since it is not used
|
||||
* for upcall processing any more. */
|
||||
netdev_flow_key_from_flow(&key, &match.flow);
|
||||
* Use the same method as employed to create the key when adding
|
||||
* the flow to the dplcs to make sure they match. */
|
||||
netdev_flow_mask_init(&mask, &match);
|
||||
netdev_flow_key_init_masked(&key, &match.flow, &mask);
|
||||
|
||||
if (put->pmd_id == PMD_ID_NULL) {
|
||||
if (cmap_count(&dp->poll_threads) == 0) {
|
||||
|
Reference in New Issue
Block a user