2010-11-09 17:00:59 -08:00
|
|
|
|
/*
|
ofp-actions: Add delete field action
This patch adds a new OpenFlow action, delete field, to delete a
field in packets. Currently, only the tun_metadata fields are
supported.
One use case to add this action is to support multiple versions
of geneve tunnel metadatas to be exchanged among different versions
of networks. For example, we may introduce tun_metadata2 to
replace old tun_metadata1, but still want to provide backward
compatibility to the older release. In this case, in the new
OpenFlow pipeline, we would like to support the case to receive a
packet with tun_metadata1, do some processing. And if the packet
is going to a switch in the newer release, we would like to delete
the value in tun_metadata1 and set a value into tun_metadata2.
Currently, ovs does not provide an action to remove a value in
tun_metadata if the value is present. This patch fulfills the gap
by adding the delete_field action. For example, the OpenFlow
syntax to delete tun_metadata1 is:
actions=delete_field:tun_metadata1
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: William Tu <u9012063@gmail.com>
Acked-by: William Tu <u9012063@gmail.com>
2020-04-14 13:33:28 -07:00
|
|
|
|
* Copyright (c) 2010-2017, 2020 Nicira, Inc.
|
2010-11-09 17:00:59 -08:00
|
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
|
|
#include "nx-match.h"
|
|
|
|
|
|
2011-02-01 22:54:11 -08:00
|
|
|
|
#include <netinet/icmp6.h>
|
|
|
|
|
|
2010-11-09 17:00:59 -08:00
|
|
|
|
#include "classifier.h"
|
2016-03-02 15:56:20 +01:00
|
|
|
|
#include "colors.h"
|
2016-07-12 16:37:34 -05:00
|
|
|
|
#include "openvswitch/hmap.h"
|
2016-04-14 15:20:19 -07:00
|
|
|
|
#include "openflow/nicira-ext.h"
|
|
|
|
|
#include "openvswitch/dynamic-string.h"
|
2016-04-04 21:32:07 -04:00
|
|
|
|
#include "openvswitch/meta-flow.h"
|
2016-04-14 15:20:19 -07:00
|
|
|
|
#include "openvswitch/ofp-actions.h"
|
|
|
|
|
#include "openvswitch/ofp-errors.h"
|
2018-02-09 10:04:26 -08:00
|
|
|
|
#include "openvswitch/ofp-match.h"
|
|
|
|
|
#include "openvswitch/ofp-port.h"
|
2016-03-25 14:10:24 -07:00
|
|
|
|
#include "openvswitch/ofpbuf.h"
|
2016-04-14 15:20:19 -07:00
|
|
|
|
#include "openvswitch/vlog.h"
|
2010-11-09 17:00:59 -08:00
|
|
|
|
#include "packets.h"
|
2016-07-12 16:37:34 -05:00
|
|
|
|
#include "openvswitch/shash.h"
|
tunnel: Geneve TLV handling support for OpenFlow.
The current support for Geneve in OVS is exactly equivalent to VXLAN:
it is possible to set and match on the VNI but not on any options
contained in the header. This patch enables the use of options.
The goal for Geneve support is not to add support for any particular option
but to allow end users or controllers to specify what they would like to
match. That is, the full range of Geneve's capabilities should be exposed
without modifying the code (the one exception being options that require
per-packet computation in the fast path).
The main issue with supporting Geneve options is how to integrate the
fields into the existing OpenFlow pipeline. All existing operations
are referred to by their NXM/OXM field name - matches, action generation,
arithmetic operations (i.e. tranfer to a register). However, the Geneve
option space is exactly the same as the OXM space, so a direct mapping
is not feasible. Instead, we create a pool of 64 NXMs that are then
dynamically mapped on Geneve option TLVs using OpenFlow. Once mapped,
these fields become first-class citizens in the OpenFlow pipeline.
An example of how to use Geneve options:
ovs-ofctl add-geneve-map br0 {class=0xffff,type=0,len=4}->tun_metadata0
ovs-ofctl add-flow br0 in_port=LOCAL,actions=set_field:0xffffffff->tun_metadata0,1
This will add a 4 bytes option (filled will all 1's) to all packets
coming from the LOCAL port and then send then out to port 1.
A limitation of this patch is that although the option table is specified
for a particular switch over OpenFlow, it is currently global to all
switches. This will be addressed in a future patch.
Based on work originally done by Madhu Challa. Ben Pfaff also significantly
improved the comments.
Signed-off-by: Madhu Challa <challa@noironetworks.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-04-30 18:09:57 -07:00
|
|
|
|
#include "tun-metadata.h"
|
2010-11-09 17:00:59 -08:00
|
|
|
|
#include "unaligned.h"
|
2012-01-17 16:38:23 -08:00
|
|
|
|
#include "util.h"
|
2017-02-17 17:47:44 -08:00
|
|
|
|
#include "vl-mff-map.h"
|
2010-11-09 17:00:59 -08:00
|
|
|
|
|
|
|
|
|
VLOG_DEFINE_THIS_MODULE(nx_match);
|
|
|
|
|
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
/* OXM headers.
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* Standard OXM/NXM
|
|
|
|
|
* ================
|
|
|
|
|
*
|
|
|
|
|
* The header is 32 bits long. It looks like this:
|
|
|
|
|
*
|
|
|
|
|
* |31 16 15 9| 8 7 0
|
|
|
|
|
* +----------------------------------+---------------+--+------------------+
|
|
|
|
|
* | oxm_class | oxm_field |hm| oxm_length |
|
|
|
|
|
* +----------------------------------+---------------+--+------------------+
|
|
|
|
|
*
|
|
|
|
|
* where hm stands for oxm_hasmask. It is followed by oxm_length bytes of
|
|
|
|
|
* payload. When oxm_hasmask is 0, the payload is the value of the field
|
|
|
|
|
* identified by the header; when oxm_hasmask is 1, the payload is a value for
|
|
|
|
|
* the field followed by a mask of equal length.
|
|
|
|
|
*
|
|
|
|
|
* Internally, we represent a standard OXM header as a 64-bit integer with the
|
|
|
|
|
* above information in the most-significant bits.
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* Experimenter OXM
|
|
|
|
|
* ================
|
|
|
|
|
*
|
|
|
|
|
* The header is 64 bits long. It looks like the diagram above except that a
|
|
|
|
|
* 32-bit experimenter ID, which we call oxm_vendor and which identifies a
|
|
|
|
|
* vendor, is inserted just before the payload. Experimenter OXMs are
|
|
|
|
|
* identified by an all-1-bits oxm_class (OFPXMC12_EXPERIMENTER). The
|
|
|
|
|
* oxm_length value *includes* the experimenter ID, so that the real payload is
|
|
|
|
|
* only oxm_length - 4 bytes long.
|
|
|
|
|
*
|
|
|
|
|
* Internally, we represent an experimenter OXM header as a 64-bit integer with
|
|
|
|
|
* the standard header in the upper 32 bits and the experimenter ID in the
|
|
|
|
|
* lower 32 bits. (It would be more convenient to swap the positions of the
|
|
|
|
|
* two 32-bit words, but this would be more error-prone because experimenter
|
|
|
|
|
* OXMs are very rarely used, so accidentally passing one through a 32-bit type
|
|
|
|
|
* somewhere in the OVS code would be hard to find.)
|
|
|
|
|
*/
|
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
/*
|
|
|
|
|
* OXM Class IDs.
|
|
|
|
|
* The high order bit differentiate reserved classes from member classes.
|
|
|
|
|
* Classes 0x0000 to 0x7FFF are member classes, allocated by ONF.
|
|
|
|
|
* Classes 0x8000 to 0xFFFE are reserved classes, reserved for standardisation.
|
|
|
|
|
*/
|
|
|
|
|
enum ofp12_oxm_class {
|
|
|
|
|
OFPXMC12_NXM_0 = 0x0000, /* Backward compatibility with NXM */
|
|
|
|
|
OFPXMC12_NXM_1 = 0x0001, /* Backward compatibility with NXM */
|
|
|
|
|
OFPXMC12_OPENFLOW_BASIC = 0x8000, /* Basic class for OpenFlow */
|
|
|
|
|
OFPXMC15_PACKET_REGS = 0x8001, /* Packet registers (pipeline fields). */
|
|
|
|
|
OFPXMC12_EXPERIMENTER = 0xffff, /* Experimenter class */
|
|
|
|
|
};
|
|
|
|
|
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
/* Functions for extracting raw field values from OXM/NXM headers. */
|
|
|
|
|
static uint32_t nxm_vendor(uint64_t header) { return header; }
|
|
|
|
|
static int nxm_class(uint64_t header) { return header >> 48; }
|
|
|
|
|
static int nxm_field(uint64_t header) { return (header >> 41) & 0x7f; }
|
|
|
|
|
static bool nxm_hasmask(uint64_t header) { return (header >> 40) & 1; }
|
|
|
|
|
static int nxm_length(uint64_t header) { return (header >> 32) & 0xff; }
|
2015-05-06 17:59:24 -07:00
|
|
|
|
static uint64_t nxm_no_len(uint64_t header) { return header & 0xffffff80ffffffffULL; }
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
is_experimenter_oxm(uint64_t header)
|
|
|
|
|
{
|
|
|
|
|
return nxm_class(header) == OFPXMC12_EXPERIMENTER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The OXM header "length" field is somewhat tricky:
|
|
|
|
|
*
|
|
|
|
|
* - For a standard OXM header, the length is the number of bytes of the
|
|
|
|
|
* payload, and the payload consists of just the value (and mask, if
|
|
|
|
|
* present).
|
|
|
|
|
*
|
|
|
|
|
* - For an experimenter OXM header, the length is the number of bytes in
|
|
|
|
|
* the payload plus 4 (the length of the experimenter ID). That is, the
|
|
|
|
|
* experimenter ID is included in oxm_length.
|
|
|
|
|
*
|
|
|
|
|
* This function returns the length of the experimenter ID field in 'header'.
|
|
|
|
|
* That is, for an experimenter OXM (when an experimenter ID is present), it
|
|
|
|
|
* returns 4, and for a standard OXM (when no experimenter ID is present), it
|
|
|
|
|
* returns 0. */
|
|
|
|
|
static int
|
|
|
|
|
nxm_experimenter_len(uint64_t header)
|
|
|
|
|
{
|
|
|
|
|
return is_experimenter_oxm(header) ? 4 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns the number of bytes that follow the header for an NXM/OXM entry
|
|
|
|
|
* with the given 'header'. */
|
2025-02-06 12:09:37 +01:00
|
|
|
|
static unsigned int
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
nxm_payload_len(uint64_t header)
|
|
|
|
|
{
|
2025-02-06 12:09:37 +01:00
|
|
|
|
ovs_assert(nxm_length(header) >= nxm_experimenter_len(header));
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
return nxm_length(header) - nxm_experimenter_len(header);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns the number of bytes in the header for an NXM/OXM entry with the
|
|
|
|
|
* given 'header'. */
|
|
|
|
|
static int
|
|
|
|
|
nxm_header_len(uint64_t header)
|
|
|
|
|
{
|
|
|
|
|
return 4 + nxm_experimenter_len(header);
|
|
|
|
|
}
|
2014-09-16 22:13:44 -07:00
|
|
|
|
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
#define NXM_HEADER(VENDOR, CLASS, FIELD, HASMASK, LENGTH) \
|
|
|
|
|
(((uint64_t) (CLASS) << 48) | \
|
|
|
|
|
((uint64_t) (FIELD) << 41) | \
|
|
|
|
|
((uint64_t) (HASMASK) << 40) | \
|
|
|
|
|
((uint64_t) (LENGTH) << 32) | \
|
|
|
|
|
(VENDOR))
|
2014-09-16 22:13:44 -07:00
|
|
|
|
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
#define NXM_HEADER_FMT "%#"PRIx32":%d:%d:%d:%d"
|
|
|
|
|
#define NXM_HEADER_ARGS(HEADER) \
|
|
|
|
|
nxm_vendor(HEADER), nxm_class(HEADER), nxm_field(HEADER), \
|
2014-09-16 22:13:44 -07:00
|
|
|
|
nxm_hasmask(HEADER), nxm_length(HEADER)
|
|
|
|
|
|
|
|
|
|
/* Functions for turning the "hasmask" bit on or off. (This also requires
|
|
|
|
|
* adjusting the length.) */
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
static uint64_t
|
|
|
|
|
nxm_make_exact_header(uint64_t header)
|
2014-09-16 22:13:44 -07:00
|
|
|
|
{
|
2025-02-06 12:09:37 +01:00
|
|
|
|
unsigned int new_len = nxm_payload_len(header)
|
|
|
|
|
/ 2 + nxm_experimenter_len(header);
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
return NXM_HEADER(nxm_vendor(header), nxm_class(header),
|
|
|
|
|
nxm_field(header), 0, new_len);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
}
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
static uint64_t
|
|
|
|
|
nxm_make_wild_header(uint64_t header)
|
2014-09-16 22:13:44 -07:00
|
|
|
|
{
|
2025-02-06 12:09:37 +01:00
|
|
|
|
unsigned int new_len = nxm_payload_len(header) * 2
|
|
|
|
|
+ nxm_experimenter_len(header);
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
return NXM_HEADER(nxm_vendor(header), nxm_class(header),
|
|
|
|
|
nxm_field(header), 1, new_len);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Flow cookie.
|
|
|
|
|
*
|
|
|
|
|
* This may be used to gain the OpenFlow 1.1-like ability to restrict
|
|
|
|
|
* certain NXM-based Flow Mod and Flow Stats Request messages to flows
|
|
|
|
|
* with specific cookies. See the "nx_flow_mod" and "nx_flow_stats_request"
|
|
|
|
|
* structure definitions for more details. This match is otherwise not
|
|
|
|
|
* allowed. */
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
#define NXM_NX_COOKIE NXM_HEADER (0, 0x0001, 30, 0, 8)
|
2014-09-16 22:13:44 -07:00
|
|
|
|
#define NXM_NX_COOKIE_W nxm_make_wild_header(NXM_NX_COOKIE)
|
|
|
|
|
|
|
|
|
|
struct nxm_field {
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
uint64_t header;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
enum ofp_version version;
|
|
|
|
|
const char *name; /* e.g. "NXM_OF_IN_PORT". */
|
|
|
|
|
|
|
|
|
|
enum mf_field_id id;
|
|
|
|
|
};
|
|
|
|
|
|
2019-01-16 16:53:52 -08:00
|
|
|
|
static const struct nxm_field *nxm_field_by_header(uint64_t header, bool is_action, enum ofperr *h_error);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
static const struct nxm_field *nxm_field_by_name(const char *name, size_t len);
|
2014-10-09 22:57:47 -07:00
|
|
|
|
static const struct nxm_field *nxm_field_by_mf_id(enum mf_field_id,
|
|
|
|
|
enum ofp_version);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
static void nx_put_header__(struct ofpbuf *, uint64_t header, bool masked);
|
2015-05-06 18:04:11 -07:00
|
|
|
|
static void nx_put_header_len(struct ofpbuf *, enum mf_field_id field,
|
|
|
|
|
enum ofp_version version, bool masked,
|
|
|
|
|
size_t n_bytes);
|
2014-09-30 17:26:28 -07:00
|
|
|
|
|
2010-11-09 17:00:59 -08:00
|
|
|
|
/* Rate limit for nx_match parse errors. These always indicate a bug in the
|
|
|
|
|
* peer and so there's not much point in showing a lot of them. */
|
|
|
|
|
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
|
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
static const struct nxm_field *
|
|
|
|
|
mf_parse_subfield_name(const char *name, int name_len, bool *wild);
|
|
|
|
|
|
|
|
|
|
/* Returns the preferred OXM header to use for field 'id' in OpenFlow version
|
|
|
|
|
* 'version'. Specify 0 for 'version' if an NXM legacy header should be
|
|
|
|
|
* preferred over any standardized OXM header. Returns 0 if field 'id' cannot
|
|
|
|
|
* be expressed in NXM or OXM. */
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
static uint64_t
|
2014-09-16 22:13:44 -07:00
|
|
|
|
mf_oxm_header(enum mf_field_id id, enum ofp_version version)
|
|
|
|
|
{
|
2014-10-09 22:57:47 -07:00
|
|
|
|
const struct nxm_field *f = nxm_field_by_mf_id(id, version);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
return f ? f->header : 0;
|
|
|
|
|
}
|
|
|
|
|
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
/* Returns the 32-bit OXM or NXM header to use for field 'id', preferring an
|
|
|
|
|
* NXM legacy header over any standardized OXM header. Returns 0 if field 'id'
|
|
|
|
|
* cannot be expressed with a 32-bit NXM or OXM header.
|
|
|
|
|
*
|
|
|
|
|
* Whenever possible, use nx_pull_header() instead of this function, because
|
|
|
|
|
* this function cannot support 64-bit experimenter OXM headers. */
|
|
|
|
|
uint32_t
|
|
|
|
|
mf_nxm_header(enum mf_field_id id)
|
|
|
|
|
{
|
|
|
|
|
uint64_t oxm = mf_oxm_header(id, 0);
|
|
|
|
|
return is_experimenter_oxm(oxm) ? 0 : oxm >> 32;
|
|
|
|
|
}
|
|
|
|
|
|
ofp-actions: Fix variable length meta-flow OXMs.
Previously, if a flow action that involves a tunnel metadata meta-flow
field is dumped from vswitchd, the replied field length in the OXM header
is filled with the maximum possible field length, instead of the length
configured in the tunnel TLV mapping table. To solve this issue, this patch
introduces the following changes.
In order to maintain the correct length of variable length mf_fields (i.e.
tun_metadata), this patch creates a per-switch based map (struct vl_mff_map)
that hosts the variable length mf_fields. This map is updated when a
controller adds/deletes tlv-mapping entries to/from a switch. Although the
per-swtch based vl_mff_map only hosts tun_metadata for now, it is able to
support new variable length mf_fields in the future.
With this commit, when a switch decodes a flow action with mf_field, the switch
firstly looks up the global mf_fields map to identify the mf_field type. For
the variable length mf_fields, the switch uses the vl_mff_map to get the
configured mf_field entries. By lookig up vl_mff_map, the switch can check
if the added flow action access beyond the configured size of a variable
length mf_field, and the switch reports an ofperr if the controller adds a flow
with unmapped variable length mf_field. Later on, when a controller request
flows from the switch, with the per-switch based mf_fields, the switch will
encode the OXM header with correct length for variable length mf_fields.
To use the vl_mff_map for decoding flow actions, extract-ofp-actions is
updated to pass the vl_mff_map to the required action decoding functions.
Also, a new error code is introduced to identify a flow with an invalid
variable length mf_field. Moreover, a testcase is added to prevent future
regressions.
Committer notes:
- Factor out common code
- Style fixups
- Rename OFPERR_NXFMFC_INVALID_VL_MFF -> OFPERR_NXFMFC_INVALID_TLV_FIELD
VMWare-BZ: #1768370
Reported-by: Harold Lim <haroldl@vmware.com>
Suggested-by: Joe Stringer <joe@ovn.org>
Suggested-by: Jarno Rajahalme <jarno@ovn.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Joe Stringer <joe@ovn.org>
2017-01-20 15:12:21 -08:00
|
|
|
|
/* Returns the 32-bit OXM or NXM header to use for field 'mff'. If 'mff' is
|
|
|
|
|
* a mapped variable length mf_field, update the header with the configured
|
|
|
|
|
* length of 'mff'. Returns 0 if 'mff' cannot be expressed with a 32-bit NXM
|
|
|
|
|
* or OXM header.*/
|
|
|
|
|
uint32_t
|
|
|
|
|
nxm_header_from_mff(const struct mf_field *mff)
|
|
|
|
|
{
|
|
|
|
|
uint64_t oxm = mf_oxm_header(mff->id, 0);
|
|
|
|
|
|
|
|
|
|
if (mff->mapped) {
|
|
|
|
|
oxm = nxm_no_len(oxm) | ((uint64_t) mff->n_bytes << 32);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return is_experimenter_oxm(oxm) ? 0 : oxm >> 32;
|
|
|
|
|
}
|
|
|
|
|
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
static const struct mf_field *
|
2019-01-16 16:53:52 -08:00
|
|
|
|
mf_from_oxm_header(uint64_t header, const struct vl_mff_map *vl_mff_map,
|
|
|
|
|
bool is_action, enum ofperr *h_error)
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
{
|
2019-01-16 16:53:52 -08:00
|
|
|
|
const struct nxm_field *f = nxm_field_by_header(header, is_action, h_error);
|
ofp-actions: Fix variable length meta-flow OXMs.
Previously, if a flow action that involves a tunnel metadata meta-flow
field is dumped from vswitchd, the replied field length in the OXM header
is filled with the maximum possible field length, instead of the length
configured in the tunnel TLV mapping table. To solve this issue, this patch
introduces the following changes.
In order to maintain the correct length of variable length mf_fields (i.e.
tun_metadata), this patch creates a per-switch based map (struct vl_mff_map)
that hosts the variable length mf_fields. This map is updated when a
controller adds/deletes tlv-mapping entries to/from a switch. Although the
per-swtch based vl_mff_map only hosts tun_metadata for now, it is able to
support new variable length mf_fields in the future.
With this commit, when a switch decodes a flow action with mf_field, the switch
firstly looks up the global mf_fields map to identify the mf_field type. For
the variable length mf_fields, the switch uses the vl_mff_map to get the
configured mf_field entries. By lookig up vl_mff_map, the switch can check
if the added flow action access beyond the configured size of a variable
length mf_field, and the switch reports an ofperr if the controller adds a flow
with unmapped variable length mf_field. Later on, when a controller request
flows from the switch, with the per-switch based mf_fields, the switch will
encode the OXM header with correct length for variable length mf_fields.
To use the vl_mff_map for decoding flow actions, extract-ofp-actions is
updated to pass the vl_mff_map to the required action decoding functions.
Also, a new error code is introduced to identify a flow with an invalid
variable length mf_field. Moreover, a testcase is added to prevent future
regressions.
Committer notes:
- Factor out common code
- Style fixups
- Rename OFPERR_NXFMFC_INVALID_VL_MFF -> OFPERR_NXFMFC_INVALID_TLV_FIELD
VMWare-BZ: #1768370
Reported-by: Harold Lim <haroldl@vmware.com>
Suggested-by: Joe Stringer <joe@ovn.org>
Suggested-by: Jarno Rajahalme <jarno@ovn.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Joe Stringer <joe@ovn.org>
2017-01-20 15:12:21 -08:00
|
|
|
|
|
|
|
|
|
if (f) {
|
|
|
|
|
const struct mf_field *mff = mf_from_id(f->id);
|
|
|
|
|
const struct mf_field *vl_mff = mf_get_vl_mff(mff, vl_mff_map);
|
|
|
|
|
return vl_mff ? vl_mff : mff;
|
|
|
|
|
} else {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
/* Returns the "struct mf_field" that corresponds to NXM or OXM header
|
|
|
|
|
* 'header', or NULL if 'header' doesn't correspond to any known field. */
|
|
|
|
|
const struct mf_field *
|
ofp-actions: Fix variable length meta-flow OXMs.
Previously, if a flow action that involves a tunnel metadata meta-flow
field is dumped from vswitchd, the replied field length in the OXM header
is filled with the maximum possible field length, instead of the length
configured in the tunnel TLV mapping table. To solve this issue, this patch
introduces the following changes.
In order to maintain the correct length of variable length mf_fields (i.e.
tun_metadata), this patch creates a per-switch based map (struct vl_mff_map)
that hosts the variable length mf_fields. This map is updated when a
controller adds/deletes tlv-mapping entries to/from a switch. Although the
per-swtch based vl_mff_map only hosts tun_metadata for now, it is able to
support new variable length mf_fields in the future.
With this commit, when a switch decodes a flow action with mf_field, the switch
firstly looks up the global mf_fields map to identify the mf_field type. For
the variable length mf_fields, the switch uses the vl_mff_map to get the
configured mf_field entries. By lookig up vl_mff_map, the switch can check
if the added flow action access beyond the configured size of a variable
length mf_field, and the switch reports an ofperr if the controller adds a flow
with unmapped variable length mf_field. Later on, when a controller request
flows from the switch, with the per-switch based mf_fields, the switch will
encode the OXM header with correct length for variable length mf_fields.
To use the vl_mff_map for decoding flow actions, extract-ofp-actions is
updated to pass the vl_mff_map to the required action decoding functions.
Also, a new error code is introduced to identify a flow with an invalid
variable length mf_field. Moreover, a testcase is added to prevent future
regressions.
Committer notes:
- Factor out common code
- Style fixups
- Rename OFPERR_NXFMFC_INVALID_VL_MFF -> OFPERR_NXFMFC_INVALID_TLV_FIELD
VMWare-BZ: #1768370
Reported-by: Harold Lim <haroldl@vmware.com>
Suggested-by: Joe Stringer <joe@ovn.org>
Suggested-by: Jarno Rajahalme <jarno@ovn.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Joe Stringer <joe@ovn.org>
2017-01-20 15:12:21 -08:00
|
|
|
|
mf_from_nxm_header(uint32_t header, const struct vl_mff_map *vl_mff_map)
|
2014-09-16 22:13:44 -07:00
|
|
|
|
{
|
2019-01-16 16:53:52 -08:00
|
|
|
|
return mf_from_oxm_header((uint64_t) header << 32, vl_mff_map, false, NULL);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
}
|
|
|
|
|
|
2010-11-09 17:00:59 -08:00
|
|
|
|
/* Returns the width of the data for a field with the given 'header', in
|
|
|
|
|
* bytes. */
|
2014-09-16 22:13:44 -07:00
|
|
|
|
static int
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
nxm_field_bytes(uint64_t header)
|
2010-11-09 17:00:59 -08:00
|
|
|
|
{
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
unsigned int length = nxm_payload_len(header);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
return nxm_hasmask(header) ? length / 2 : length;
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
2014-10-09 22:57:47 -07:00
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
/* nx_pull_match() and helpers. */
|
2010-11-09 17:00:59 -08:00
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
/* Given NXM/OXM value 'value' and mask 'mask' associated with 'header', checks
|
|
|
|
|
* for any 1-bit in the value where there is a 0-bit in the mask. Returns 0 if
|
|
|
|
|
* none, otherwise an error code. */
|
|
|
|
|
static bool
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
is_mask_consistent(uint64_t header, const uint8_t *value, const uint8_t *mask)
|
2010-11-09 17:00:59 -08:00
|
|
|
|
{
|
2014-09-16 22:13:44 -07:00
|
|
|
|
unsigned int width = nxm_field_bytes(header);
|
|
|
|
|
unsigned int i;
|
2010-11-09 17:00:59 -08:00
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
for (i = 0; i < width; i++) {
|
|
|
|
|
if (value[i] & ~mask[i]) {
|
|
|
|
|
if (!VLOG_DROP_WARN(&rl)) {
|
|
|
|
|
VLOG_WARN_RL(&rl, "Rejecting NXM/OXM entry "NXM_HEADER_FMT " "
|
|
|
|
|
"with 1-bits in value for bits wildcarded by the "
|
|
|
|
|
"mask.", NXM_HEADER_ARGS(header));
|
|
|
|
|
}
|
|
|
|
|
return false;
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
2014-09-16 22:13:44 -07:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2010-11-09 17:00:59 -08:00
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
static bool
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
is_cookie_pseudoheader(uint64_t header)
|
2014-09-16 22:13:44 -07:00
|
|
|
|
{
|
|
|
|
|
return header == NXM_NX_COOKIE || header == NXM_NX_COOKIE_W;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum ofperr
|
ofp-actions: Fix variable length meta-flow OXMs.
Previously, if a flow action that involves a tunnel metadata meta-flow
field is dumped from vswitchd, the replied field length in the OXM header
is filled with the maximum possible field length, instead of the length
configured in the tunnel TLV mapping table. To solve this issue, this patch
introduces the following changes.
In order to maintain the correct length of variable length mf_fields (i.e.
tun_metadata), this patch creates a per-switch based map (struct vl_mff_map)
that hosts the variable length mf_fields. This map is updated when a
controller adds/deletes tlv-mapping entries to/from a switch. Although the
per-swtch based vl_mff_map only hosts tun_metadata for now, it is able to
support new variable length mf_fields in the future.
With this commit, when a switch decodes a flow action with mf_field, the switch
firstly looks up the global mf_fields map to identify the mf_field type. For
the variable length mf_fields, the switch uses the vl_mff_map to get the
configured mf_field entries. By lookig up vl_mff_map, the switch can check
if the added flow action access beyond the configured size of a variable
length mf_field, and the switch reports an ofperr if the controller adds a flow
with unmapped variable length mf_field. Later on, when a controller request
flows from the switch, with the per-switch based mf_fields, the switch will
encode the OXM header with correct length for variable length mf_fields.
To use the vl_mff_map for decoding flow actions, extract-ofp-actions is
updated to pass the vl_mff_map to the required action decoding functions.
Also, a new error code is introduced to identify a flow with an invalid
variable length mf_field. Moreover, a testcase is added to prevent future
regressions.
Committer notes:
- Factor out common code
- Style fixups
- Rename OFPERR_NXFMFC_INVALID_VL_MFF -> OFPERR_NXFMFC_INVALID_TLV_FIELD
VMWare-BZ: #1768370
Reported-by: Harold Lim <haroldl@vmware.com>
Suggested-by: Joe Stringer <joe@ovn.org>
Suggested-by: Jarno Rajahalme <jarno@ovn.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Joe Stringer <joe@ovn.org>
2017-01-20 15:12:21 -08:00
|
|
|
|
nx_pull_header__(struct ofpbuf *b, bool allow_cookie,
|
|
|
|
|
const struct vl_mff_map *vl_mff_map, uint64_t *header,
|
2019-01-16 16:53:52 -08:00
|
|
|
|
const struct mf_field **field, bool is_action)
|
2014-09-16 22:13:44 -07:00
|
|
|
|
{
|
2015-03-02 17:29:44 -08:00
|
|
|
|
if (b->size < 4) {
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
goto bad_len;
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
|
2015-03-02 17:29:44 -08:00
|
|
|
|
*header = ((uint64_t) ntohl(get_unaligned_be32(b->data))) << 32;
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
if (is_experimenter_oxm(*header)) {
|
2015-03-02 17:29:44 -08:00
|
|
|
|
if (b->size < 8) {
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
goto bad_len;
|
|
|
|
|
}
|
2015-03-02 17:29:44 -08:00
|
|
|
|
*header = ntohll(get_unaligned_be64(b->data));
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
}
|
2015-08-11 18:41:37 -07:00
|
|
|
|
if (nxm_length(*header) < nxm_experimenter_len(*header)) {
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
VLOG_WARN_RL(&rl, "OXM header "NXM_HEADER_FMT" has invalid length %d "
|
|
|
|
|
"(minimum is %d)",
|
|
|
|
|
NXM_HEADER_ARGS(*header), nxm_length(*header),
|
2015-08-11 18:41:37 -07:00
|
|
|
|
nxm_header_len(*header));
|
2014-09-16 22:13:44 -07:00
|
|
|
|
goto error;
|
|
|
|
|
}
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
ofpbuf_pull(b, nxm_header_len(*header));
|
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
if (field) {
|
2019-01-16 16:53:52 -08:00
|
|
|
|
enum ofperr h_error = 0;
|
|
|
|
|
*field = mf_from_oxm_header(*header, vl_mff_map, is_action, &h_error);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
if (!*field && !(allow_cookie && is_cookie_pseudoheader(*header))) {
|
|
|
|
|
VLOG_DBG_RL(&rl, "OXM header "NXM_HEADER_FMT" is unknown",
|
|
|
|
|
NXM_HEADER_ARGS(*header));
|
2019-01-16 16:53:52 -08:00
|
|
|
|
if (is_action) {
|
|
|
|
|
if (h_error) {
|
|
|
|
|
*field = NULL;
|
|
|
|
|
return h_error;
|
|
|
|
|
}
|
|
|
|
|
return OFPERR_OFPBAC_BAD_SET_TYPE;
|
|
|
|
|
} else {
|
|
|
|
|
return OFPERR_OFPBMC_BAD_FIELD;
|
|
|
|
|
}
|
ofp-actions: Fix variable length meta-flow OXMs.
Previously, if a flow action that involves a tunnel metadata meta-flow
field is dumped from vswitchd, the replied field length in the OXM header
is filled with the maximum possible field length, instead of the length
configured in the tunnel TLV mapping table. To solve this issue, this patch
introduces the following changes.
In order to maintain the correct length of variable length mf_fields (i.e.
tun_metadata), this patch creates a per-switch based map (struct vl_mff_map)
that hosts the variable length mf_fields. This map is updated when a
controller adds/deletes tlv-mapping entries to/from a switch. Although the
per-swtch based vl_mff_map only hosts tun_metadata for now, it is able to
support new variable length mf_fields in the future.
With this commit, when a switch decodes a flow action with mf_field, the switch
firstly looks up the global mf_fields map to identify the mf_field type. For
the variable length mf_fields, the switch uses the vl_mff_map to get the
configured mf_field entries. By lookig up vl_mff_map, the switch can check
if the added flow action access beyond the configured size of a variable
length mf_field, and the switch reports an ofperr if the controller adds a flow
with unmapped variable length mf_field. Later on, when a controller request
flows from the switch, with the per-switch based mf_fields, the switch will
encode the OXM header with correct length for variable length mf_fields.
To use the vl_mff_map for decoding flow actions, extract-ofp-actions is
updated to pass the vl_mff_map to the required action decoding functions.
Also, a new error code is introduced to identify a flow with an invalid
variable length mf_field. Moreover, a testcase is added to prevent future
regressions.
Committer notes:
- Factor out common code
- Style fixups
- Rename OFPERR_NXFMFC_INVALID_VL_MFF -> OFPERR_NXFMFC_INVALID_TLV_FIELD
VMWare-BZ: #1768370
Reported-by: Harold Lim <haroldl@vmware.com>
Suggested-by: Joe Stringer <joe@ovn.org>
Suggested-by: Jarno Rajahalme <jarno@ovn.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Joe Stringer <joe@ovn.org>
2017-01-20 15:12:21 -08:00
|
|
|
|
} else if (mf_vl_mff_invalid(*field, vl_mff_map)) {
|
|
|
|
|
return OFPERR_NXFMFC_INVALID_TLV_FIELD;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
}
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
return 0;
|
|
|
|
|
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
bad_len:
|
|
|
|
|
VLOG_DBG_RL(&rl, "encountered partial (%"PRIu32"-byte) OXM entry",
|
2015-03-02 17:29:44 -08:00
|
|
|
|
b->size);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
error:
|
|
|
|
|
*header = 0;
|
2015-04-16 14:04:47 -07:00
|
|
|
|
if (field) {
|
|
|
|
|
*field = NULL;
|
|
|
|
|
}
|
2014-09-16 22:13:44 -07:00
|
|
|
|
return OFPERR_OFPBMC_BAD_LEN;
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
|
|
|
|
|
nx-match: Handle receiving variable length fields.
This adds support for receiving variable length fields encoded in
NXM/OXM and mapping them into OVS internal structures. In order
for this to make sense, we need to define some semantics:
There are three lengths that matter in this process: the maximum
size of the field (represented as the existing mf->n_bytes), the
size of the field in the incoming NXM (given by the length in the
NXM header), and the currently configured length of the field
(defined by the consumer of the field and outside the scope of
this patch).
Fields are modeled as being their maximum length and have the
characteristics expected by exsiting code (i.e. exact match fields
have masks that are all 1's for the whole field, etc.). Incoming
NXMs are stored in the field in the least significant bits. If
the NXM length is larger than the field, is is truncated, if it
is smaller it is zero-extended. When the field is consumed, the
component that needs data picks the configured length out of the
generated field.
In most cases, the configured and NXM lengths will be equal and
these edge cases do not matter. However, since we cannot easily
enforce that the lengths match (and might not even know what the
right length is, such as in the case of a string parsed by
ovs-ofctl), these semantics should provide deterministic results
that are easy to understand and not require most existing code
to be aware of variable length fields.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-05-06 18:00:52 -07:00
|
|
|
|
static void
|
|
|
|
|
copy_entry_value(const struct mf_field *field, union mf_value *value,
|
|
|
|
|
const uint8_t *payload, int width)
|
|
|
|
|
{
|
|
|
|
|
int copy_len;
|
|
|
|
|
void *copy_dst;
|
|
|
|
|
|
|
|
|
|
copy_dst = value;
|
|
|
|
|
copy_len = MIN(width, field ? field->n_bytes : sizeof *value);
|
|
|
|
|
|
|
|
|
|
if (field && field->variable_len) {
|
|
|
|
|
memset(value, 0, field->n_bytes);
|
|
|
|
|
copy_dst = &value->u8 + field->n_bytes - copy_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy(copy_dst, payload, copy_len);
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-04 13:34:37 -07:00
|
|
|
|
static enum ofperr
|
ofp-actions: Fix variable length meta-flow OXMs.
Previously, if a flow action that involves a tunnel metadata meta-flow
field is dumped from vswitchd, the replied field length in the OXM header
is filled with the maximum possible field length, instead of the length
configured in the tunnel TLV mapping table. To solve this issue, this patch
introduces the following changes.
In order to maintain the correct length of variable length mf_fields (i.e.
tun_metadata), this patch creates a per-switch based map (struct vl_mff_map)
that hosts the variable length mf_fields. This map is updated when a
controller adds/deletes tlv-mapping entries to/from a switch. Although the
per-swtch based vl_mff_map only hosts tun_metadata for now, it is able to
support new variable length mf_fields in the future.
With this commit, when a switch decodes a flow action with mf_field, the switch
firstly looks up the global mf_fields map to identify the mf_field type. For
the variable length mf_fields, the switch uses the vl_mff_map to get the
configured mf_field entries. By lookig up vl_mff_map, the switch can check
if the added flow action access beyond the configured size of a variable
length mf_field, and the switch reports an ofperr if the controller adds a flow
with unmapped variable length mf_field. Later on, when a controller request
flows from the switch, with the per-switch based mf_fields, the switch will
encode the OXM header with correct length for variable length mf_fields.
To use the vl_mff_map for decoding flow actions, extract-ofp-actions is
updated to pass the vl_mff_map to the required action decoding functions.
Also, a new error code is introduced to identify a flow with an invalid
variable length mf_field. Moreover, a testcase is added to prevent future
regressions.
Committer notes:
- Factor out common code
- Style fixups
- Rename OFPERR_NXFMFC_INVALID_VL_MFF -> OFPERR_NXFMFC_INVALID_TLV_FIELD
VMWare-BZ: #1768370
Reported-by: Harold Lim <haroldl@vmware.com>
Suggested-by: Joe Stringer <joe@ovn.org>
Suggested-by: Jarno Rajahalme <jarno@ovn.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Joe Stringer <joe@ovn.org>
2017-01-20 15:12:21 -08:00
|
|
|
|
nx_pull_entry__(struct ofpbuf *b, bool allow_cookie,
|
|
|
|
|
const struct vl_mff_map *vl_mff_map, uint64_t *header,
|
nx-match: Handle receiving variable length fields.
This adds support for receiving variable length fields encoded in
NXM/OXM and mapping them into OVS internal structures. In order
for this to make sense, we need to define some semantics:
There are three lengths that matter in this process: the maximum
size of the field (represented as the existing mf->n_bytes), the
size of the field in the incoming NXM (given by the length in the
NXM header), and the currently configured length of the field
(defined by the consumer of the field and outside the scope of
this patch).
Fields are modeled as being their maximum length and have the
characteristics expected by exsiting code (i.e. exact match fields
have masks that are all 1's for the whole field, etc.). Incoming
NXMs are stored in the field in the least significant bits. If
the NXM length is larger than the field, is is truncated, if it
is smaller it is zero-extended. When the field is consumed, the
component that needs data picks the configured length out of the
generated field.
In most cases, the configured and NXM lengths will be equal and
these edge cases do not matter. However, since we cannot easily
enforce that the lengths match (and might not even know what the
right length is, such as in the case of a string parsed by
ovs-ofctl), these semantics should provide deterministic results
that are easy to understand and not require most existing code
to be aware of variable length fields.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-05-06 18:00:52 -07:00
|
|
|
|
const struct mf_field **field_,
|
2019-01-16 16:53:52 -08:00
|
|
|
|
union mf_value *value, union mf_value *mask, bool is_action)
|
2012-10-03 09:48:57 -07:00
|
|
|
|
{
|
nx-match: Handle receiving variable length fields.
This adds support for receiving variable length fields encoded in
NXM/OXM and mapping them into OVS internal structures. In order
for this to make sense, we need to define some semantics:
There are three lengths that matter in this process: the maximum
size of the field (represented as the existing mf->n_bytes), the
size of the field in the incoming NXM (given by the length in the
NXM header), and the currently configured length of the field
(defined by the consumer of the field and outside the scope of
this patch).
Fields are modeled as being their maximum length and have the
characteristics expected by exsiting code (i.e. exact match fields
have masks that are all 1's for the whole field, etc.). Incoming
NXMs are stored in the field in the least significant bits. If
the NXM length is larger than the field, is is truncated, if it
is smaller it is zero-extended. When the field is consumed, the
component that needs data picks the configured length out of the
generated field.
In most cases, the configured and NXM lengths will be equal and
these edge cases do not matter. However, since we cannot easily
enforce that the lengths match (and might not even know what the
right length is, such as in the case of a string parsed by
ovs-ofctl), these semantics should provide deterministic results
that are easy to understand and not require most existing code
to be aware of variable length fields.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-05-06 18:00:52 -07:00
|
|
|
|
const struct mf_field *field;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
enum ofperr header_error;
|
|
|
|
|
unsigned int payload_len;
|
|
|
|
|
const uint8_t *payload;
|
|
|
|
|
int width;
|
2012-10-03 09:48:57 -07:00
|
|
|
|
|
ofp-actions: Fix variable length meta-flow OXMs.
Previously, if a flow action that involves a tunnel metadata meta-flow
field is dumped from vswitchd, the replied field length in the OXM header
is filled with the maximum possible field length, instead of the length
configured in the tunnel TLV mapping table. To solve this issue, this patch
introduces the following changes.
In order to maintain the correct length of variable length mf_fields (i.e.
tun_metadata), this patch creates a per-switch based map (struct vl_mff_map)
that hosts the variable length mf_fields. This map is updated when a
controller adds/deletes tlv-mapping entries to/from a switch. Although the
per-swtch based vl_mff_map only hosts tun_metadata for now, it is able to
support new variable length mf_fields in the future.
With this commit, when a switch decodes a flow action with mf_field, the switch
firstly looks up the global mf_fields map to identify the mf_field type. For
the variable length mf_fields, the switch uses the vl_mff_map to get the
configured mf_field entries. By lookig up vl_mff_map, the switch can check
if the added flow action access beyond the configured size of a variable
length mf_field, and the switch reports an ofperr if the controller adds a flow
with unmapped variable length mf_field. Later on, when a controller request
flows from the switch, with the per-switch based mf_fields, the switch will
encode the OXM header with correct length for variable length mf_fields.
To use the vl_mff_map for decoding flow actions, extract-ofp-actions is
updated to pass the vl_mff_map to the required action decoding functions.
Also, a new error code is introduced to identify a flow with an invalid
variable length mf_field. Moreover, a testcase is added to prevent future
regressions.
Committer notes:
- Factor out common code
- Style fixups
- Rename OFPERR_NXFMFC_INVALID_VL_MFF -> OFPERR_NXFMFC_INVALID_TLV_FIELD
VMWare-BZ: #1768370
Reported-by: Harold Lim <haroldl@vmware.com>
Suggested-by: Joe Stringer <joe@ovn.org>
Suggested-by: Jarno Rajahalme <jarno@ovn.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Joe Stringer <joe@ovn.org>
2017-01-20 15:12:21 -08:00
|
|
|
|
header_error = nx_pull_header__(b, allow_cookie, vl_mff_map, header,
|
2019-01-16 16:53:52 -08:00
|
|
|
|
&field, is_action);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
if (header_error && header_error != OFPERR_OFPBMC_BAD_FIELD) {
|
|
|
|
|
return header_error;
|
|
|
|
|
}
|
|
|
|
|
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
payload_len = nxm_payload_len(*header);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
payload = ofpbuf_try_pull(b, payload_len);
|
|
|
|
|
if (!payload) {
|
|
|
|
|
VLOG_DBG_RL(&rl, "OXM header "NXM_HEADER_FMT" calls for %u-byte "
|
|
|
|
|
"payload but only %"PRIu32" bytes follow OXM header",
|
2015-03-02 17:29:44 -08:00
|
|
|
|
NXM_HEADER_ARGS(*header), payload_len, b->size);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
return OFPERR_OFPBMC_BAD_LEN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
width = nxm_field_bytes(*header);
|
|
|
|
|
if (nxm_hasmask(*header)
|
|
|
|
|
&& !is_mask_consistent(*header, payload, payload + width)) {
|
|
|
|
|
return OFPERR_OFPBMC_BAD_WILDCARDS;
|
|
|
|
|
}
|
|
|
|
|
|
nx-match: Handle receiving variable length fields.
This adds support for receiving variable length fields encoded in
NXM/OXM and mapping them into OVS internal structures. In order
for this to make sense, we need to define some semantics:
There are three lengths that matter in this process: the maximum
size of the field (represented as the existing mf->n_bytes), the
size of the field in the incoming NXM (given by the length in the
NXM header), and the currently configured length of the field
(defined by the consumer of the field and outside the scope of
this patch).
Fields are modeled as being their maximum length and have the
characteristics expected by exsiting code (i.e. exact match fields
have masks that are all 1's for the whole field, etc.). Incoming
NXMs are stored in the field in the least significant bits. If
the NXM length is larger than the field, is is truncated, if it
is smaller it is zero-extended. When the field is consumed, the
component that needs data picks the configured length out of the
generated field.
In most cases, the configured and NXM lengths will be equal and
these edge cases do not matter. However, since we cannot easily
enforce that the lengths match (and might not even know what the
right length is, such as in the case of a string parsed by
ovs-ofctl), these semantics should provide deterministic results
that are easy to understand and not require most existing code
to be aware of variable length fields.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-05-06 18:00:52 -07:00
|
|
|
|
copy_entry_value(field, value, payload, width);
|
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
if (mask) {
|
|
|
|
|
if (nxm_hasmask(*header)) {
|
nx-match: Handle receiving variable length fields.
This adds support for receiving variable length fields encoded in
NXM/OXM and mapping them into OVS internal structures. In order
for this to make sense, we need to define some semantics:
There are three lengths that matter in this process: the maximum
size of the field (represented as the existing mf->n_bytes), the
size of the field in the incoming NXM (given by the length in the
NXM header), and the currently configured length of the field
(defined by the consumer of the field and outside the scope of
this patch).
Fields are modeled as being their maximum length and have the
characteristics expected by exsiting code (i.e. exact match fields
have masks that are all 1's for the whole field, etc.). Incoming
NXMs are stored in the field in the least significant bits. If
the NXM length is larger than the field, is is truncated, if it
is smaller it is zero-extended. When the field is consumed, the
component that needs data picks the configured length out of the
generated field.
In most cases, the configured and NXM lengths will be equal and
these edge cases do not matter. However, since we cannot easily
enforce that the lengths match (and might not even know what the
right length is, such as in the case of a string parsed by
ovs-ofctl), these semantics should provide deterministic results
that are easy to understand and not require most existing code
to be aware of variable length fields.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-05-06 18:00:52 -07:00
|
|
|
|
copy_entry_value(field, mask, payload + width, width);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
} else {
|
nx-match: Handle receiving variable length fields.
This adds support for receiving variable length fields encoded in
NXM/OXM and mapping them into OVS internal structures. In order
for this to make sense, we need to define some semantics:
There are three lengths that matter in this process: the maximum
size of the field (represented as the existing mf->n_bytes), the
size of the field in the incoming NXM (given by the length in the
NXM header), and the currently configured length of the field
(defined by the consumer of the field and outside the scope of
this patch).
Fields are modeled as being their maximum length and have the
characteristics expected by exsiting code (i.e. exact match fields
have masks that are all 1's for the whole field, etc.). Incoming
NXMs are stored in the field in the least significant bits. If
the NXM length is larger than the field, is is truncated, if it
is smaller it is zero-extended. When the field is consumed, the
component that needs data picks the configured length out of the
generated field.
In most cases, the configured and NXM lengths will be equal and
these edge cases do not matter. However, since we cannot easily
enforce that the lengths match (and might not even know what the
right length is, such as in the case of a string parsed by
ovs-ofctl), these semantics should provide deterministic results
that are easy to understand and not require most existing code
to be aware of variable length fields.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-05-06 18:00:52 -07:00
|
|
|
|
memset(mask, 0xff, sizeof *mask);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
}
|
|
|
|
|
} else if (nxm_hasmask(*header)) {
|
|
|
|
|
VLOG_DBG_RL(&rl, "OXM header "NXM_HEADER_FMT" includes mask but "
|
|
|
|
|
"masked OXMs are not allowed here",
|
|
|
|
|
NXM_HEADER_ARGS(*header));
|
|
|
|
|
return OFPERR_OFPBMC_BAD_MASK;
|
|
|
|
|
}
|
|
|
|
|
|
nx-match: Handle receiving variable length fields.
This adds support for receiving variable length fields encoded in
NXM/OXM and mapping them into OVS internal structures. In order
for this to make sense, we need to define some semantics:
There are three lengths that matter in this process: the maximum
size of the field (represented as the existing mf->n_bytes), the
size of the field in the incoming NXM (given by the length in the
NXM header), and the currently configured length of the field
(defined by the consumer of the field and outside the scope of
this patch).
Fields are modeled as being their maximum length and have the
characteristics expected by exsiting code (i.e. exact match fields
have masks that are all 1's for the whole field, etc.). Incoming
NXMs are stored in the field in the least significant bits. If
the NXM length is larger than the field, is is truncated, if it
is smaller it is zero-extended. When the field is consumed, the
component that needs data picks the configured length out of the
generated field.
In most cases, the configured and NXM lengths will be equal and
these edge cases do not matter. However, since we cannot easily
enforce that the lengths match (and might not even know what the
right length is, such as in the case of a string parsed by
ovs-ofctl), these semantics should provide deterministic results
that are easy to understand and not require most existing code
to be aware of variable length fields.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-05-06 18:00:52 -07:00
|
|
|
|
if (field_) {
|
|
|
|
|
*field_ = field;
|
|
|
|
|
return header_error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Attempts to pull an NXM or OXM header, value, and mask (if present) from the
|
|
|
|
|
* beginning of 'b'. If successful, stores a pointer to the "struct mf_field"
|
|
|
|
|
* corresponding to the pulled header in '*field', the value into '*value',
|
|
|
|
|
* and the mask into '*mask', and returns 0. On error, returns an OpenFlow
|
|
|
|
|
* error; in this case, some bytes might have been pulled off 'b' anyhow, and
|
|
|
|
|
* the output parameters might have been modified.
|
|
|
|
|
*
|
|
|
|
|
* If a NULL 'mask' is supplied, masked OXM or NXM entries are treated as
|
|
|
|
|
* errors (with OFPERR_OFPBMC_BAD_MASK).
|
2019-01-16 16:53:52 -08:00
|
|
|
|
*
|
|
|
|
|
* The "bool is_action" is supplied to differentiate between match and action
|
|
|
|
|
* headers. This is done in order to return appropriate error type and code for
|
|
|
|
|
* bad match or bad action conditions. If set to True, indicates that the
|
|
|
|
|
* OXM or NXM entries belong to an action header.
|
2014-09-16 22:13:44 -07:00
|
|
|
|
*/
|
|
|
|
|
enum ofperr
|
ofp-actions: Fix variable length meta-flow OXMs.
Previously, if a flow action that involves a tunnel metadata meta-flow
field is dumped from vswitchd, the replied field length in the OXM header
is filled with the maximum possible field length, instead of the length
configured in the tunnel TLV mapping table. To solve this issue, this patch
introduces the following changes.
In order to maintain the correct length of variable length mf_fields (i.e.
tun_metadata), this patch creates a per-switch based map (struct vl_mff_map)
that hosts the variable length mf_fields. This map is updated when a
controller adds/deletes tlv-mapping entries to/from a switch. Although the
per-swtch based vl_mff_map only hosts tun_metadata for now, it is able to
support new variable length mf_fields in the future.
With this commit, when a switch decodes a flow action with mf_field, the switch
firstly looks up the global mf_fields map to identify the mf_field type. For
the variable length mf_fields, the switch uses the vl_mff_map to get the
configured mf_field entries. By lookig up vl_mff_map, the switch can check
if the added flow action access beyond the configured size of a variable
length mf_field, and the switch reports an ofperr if the controller adds a flow
with unmapped variable length mf_field. Later on, when a controller request
flows from the switch, with the per-switch based mf_fields, the switch will
encode the OXM header with correct length for variable length mf_fields.
To use the vl_mff_map for decoding flow actions, extract-ofp-actions is
updated to pass the vl_mff_map to the required action decoding functions.
Also, a new error code is introduced to identify a flow with an invalid
variable length mf_field. Moreover, a testcase is added to prevent future
regressions.
Committer notes:
- Factor out common code
- Style fixups
- Rename OFPERR_NXFMFC_INVALID_VL_MFF -> OFPERR_NXFMFC_INVALID_TLV_FIELD
VMWare-BZ: #1768370
Reported-by: Harold Lim <haroldl@vmware.com>
Suggested-by: Joe Stringer <joe@ovn.org>
Suggested-by: Jarno Rajahalme <jarno@ovn.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Joe Stringer <joe@ovn.org>
2017-01-20 15:12:21 -08:00
|
|
|
|
nx_pull_entry(struct ofpbuf *b, const struct vl_mff_map *vl_mff_map,
|
|
|
|
|
const struct mf_field **field, union mf_value *value,
|
2019-01-16 16:53:52 -08:00
|
|
|
|
union mf_value *mask, bool is_action)
|
2014-09-16 22:13:44 -07:00
|
|
|
|
{
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
uint64_t header;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
|
2019-01-16 16:53:52 -08:00
|
|
|
|
return nx_pull_entry__(b, false, vl_mff_map, &header, field, value, mask, is_action);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Attempts to pull an NXM or OXM header from the beginning of 'b'. If
|
|
|
|
|
* successful, stores a pointer to the "struct mf_field" corresponding to the
|
|
|
|
|
* pulled header in '*field', stores the header's hasmask bit in '*masked'
|
|
|
|
|
* (true if hasmask=1, false if hasmask=0), and returns 0. On error, returns
|
|
|
|
|
* an OpenFlow error; in this case, some bytes might have been pulled off 'b'
|
|
|
|
|
* anyhow, and the output parameters might have been modified.
|
|
|
|
|
*
|
|
|
|
|
* If NULL 'masked' is supplied, masked OXM or NXM headers are treated as
|
|
|
|
|
* errors (with OFPERR_OFPBMC_BAD_MASK).
|
|
|
|
|
*/
|
|
|
|
|
enum ofperr
|
ofp-actions: Fix variable length meta-flow OXMs.
Previously, if a flow action that involves a tunnel metadata meta-flow
field is dumped from vswitchd, the replied field length in the OXM header
is filled with the maximum possible field length, instead of the length
configured in the tunnel TLV mapping table. To solve this issue, this patch
introduces the following changes.
In order to maintain the correct length of variable length mf_fields (i.e.
tun_metadata), this patch creates a per-switch based map (struct vl_mff_map)
that hosts the variable length mf_fields. This map is updated when a
controller adds/deletes tlv-mapping entries to/from a switch. Although the
per-swtch based vl_mff_map only hosts tun_metadata for now, it is able to
support new variable length mf_fields in the future.
With this commit, when a switch decodes a flow action with mf_field, the switch
firstly looks up the global mf_fields map to identify the mf_field type. For
the variable length mf_fields, the switch uses the vl_mff_map to get the
configured mf_field entries. By lookig up vl_mff_map, the switch can check
if the added flow action access beyond the configured size of a variable
length mf_field, and the switch reports an ofperr if the controller adds a flow
with unmapped variable length mf_field. Later on, when a controller request
flows from the switch, with the per-switch based mf_fields, the switch will
encode the OXM header with correct length for variable length mf_fields.
To use the vl_mff_map for decoding flow actions, extract-ofp-actions is
updated to pass the vl_mff_map to the required action decoding functions.
Also, a new error code is introduced to identify a flow with an invalid
variable length mf_field. Moreover, a testcase is added to prevent future
regressions.
Committer notes:
- Factor out common code
- Style fixups
- Rename OFPERR_NXFMFC_INVALID_VL_MFF -> OFPERR_NXFMFC_INVALID_TLV_FIELD
VMWare-BZ: #1768370
Reported-by: Harold Lim <haroldl@vmware.com>
Suggested-by: Joe Stringer <joe@ovn.org>
Suggested-by: Jarno Rajahalme <jarno@ovn.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Joe Stringer <joe@ovn.org>
2017-01-20 15:12:21 -08:00
|
|
|
|
nx_pull_header(struct ofpbuf *b, const struct vl_mff_map *vl_mff_map,
|
|
|
|
|
const struct mf_field **field, bool *masked)
|
2014-09-16 22:13:44 -07:00
|
|
|
|
{
|
|
|
|
|
enum ofperr error;
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
uint64_t header;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
|
2019-01-16 16:53:52 -08:00
|
|
|
|
error = nx_pull_header__(b, false, vl_mff_map, &header, field, false);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
if (masked) {
|
|
|
|
|
*masked = !error && nxm_hasmask(header);
|
|
|
|
|
} else if (!error && nxm_hasmask(header)) {
|
|
|
|
|
error = OFPERR_OFPBMC_BAD_MASK;
|
|
|
|
|
}
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum ofperr
|
|
|
|
|
nx_pull_match_entry(struct ofpbuf *b, bool allow_cookie,
|
2017-03-13 11:28:20 -07:00
|
|
|
|
const struct vl_mff_map *vl_mff_map,
|
2014-09-16 22:13:44 -07:00
|
|
|
|
const struct mf_field **field,
|
|
|
|
|
union mf_value *value, union mf_value *mask)
|
|
|
|
|
{
|
|
|
|
|
enum ofperr error;
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
uint64_t header;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
|
2017-03-13 11:28:20 -07:00
|
|
|
|
error = nx_pull_entry__(b, allow_cookie, vl_mff_map, &header, field, value,
|
2019-01-16 16:53:52 -08:00
|
|
|
|
mask, false);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
if (error) {
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
if (field && *field) {
|
|
|
|
|
if (!mf_is_mask_valid(*field, mask)) {
|
|
|
|
|
VLOG_DBG_RL(&rl, "bad mask for field %s", (*field)->name);
|
|
|
|
|
return OFPERR_OFPBMC_BAD_MASK;
|
|
|
|
|
}
|
|
|
|
|
if (!mf_is_value_valid(*field, value)) {
|
|
|
|
|
VLOG_DBG_RL(&rl, "bad value for field %s", (*field)->name);
|
|
|
|
|
return OFPERR_OFPBMC_BAD_VALUE;
|
2012-10-03 09:48:57 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
2014-09-04 13:34:37 -07:00
|
|
|
|
return 0;
|
2012-10-03 09:48:57 -07:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-08 17:18:23 -08:00
|
|
|
|
/* Prerequisites will only be checked when 'strict' is 'true'. This allows
|
|
|
|
|
* decoding conntrack original direction 5-tuple IP addresses without the
|
|
|
|
|
* ethertype being present, when decoding metadata only. */
|
2012-01-12 15:48:19 -08:00
|
|
|
|
static enum ofperr
|
2012-08-01 16:01:45 +09:00
|
|
|
|
nx_pull_raw(const uint8_t *p, unsigned int match_len, bool strict,
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
bool pipeline_fields_only, struct match *match, ovs_be64 *cookie,
|
|
|
|
|
ovs_be64 *cookie_mask, const struct tun_table *tun_table,
|
2017-03-13 11:28:20 -07:00
|
|
|
|
const struct vl_mff_map *vl_mff_map)
|
2010-11-09 17:00:59 -08:00
|
|
|
|
{
|
2012-11-06 13:14:55 -08:00
|
|
|
|
ovs_assert((cookie != NULL) == (cookie_mask != NULL));
|
2011-12-23 12:23:24 -08:00
|
|
|
|
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_init_catchall(match);
|
2016-04-19 18:36:04 -07:00
|
|
|
|
match->flow.tunnel.metadata.tab = tun_table;
|
2012-07-19 00:15:19 -07:00
|
|
|
|
if (cookie) {
|
|
|
|
|
*cookie = *cookie_mask = htonll(0);
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(p, match_len);
|
2015-03-02 17:29:44 -08:00
|
|
|
|
while (b.size) {
|
|
|
|
|
const uint8_t *pos = b.data;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
const struct mf_field *field;
|
|
|
|
|
union mf_value value;
|
|
|
|
|
union mf_value mask;
|
2012-01-12 15:48:19 -08:00
|
|
|
|
enum ofperr error;
|
2010-11-09 17:00:59 -08:00
|
|
|
|
|
2017-03-13 11:28:20 -07:00
|
|
|
|
error = nx_pull_match_entry(&b, cookie != NULL, vl_mff_map, &field,
|
|
|
|
|
&value, &mask);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
if (error) {
|
|
|
|
|
if (error == OFPERR_OFPBMC_BAD_FIELD && !strict) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
} else if (!field) {
|
|
|
|
|
if (!cookie) {
|
2012-03-26 13:46:35 -07:00
|
|
|
|
error = OFPERR_OFPBMC_BAD_FIELD;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
} else if (*cookie_mask) {
|
|
|
|
|
error = OFPERR_OFPBMC_DUP_FIELD;
|
2012-01-03 13:30:45 -08:00
|
|
|
|
} else {
|
2014-09-16 22:13:44 -07:00
|
|
|
|
*cookie = value.be64;
|
|
|
|
|
*cookie_mask = mask.be64;
|
2012-01-03 13:30:45 -08:00
|
|
|
|
}
|
2017-03-08 17:18:23 -08:00
|
|
|
|
} else if (strict && !mf_are_match_prereqs_ok(field, match)) {
|
2012-03-26 13:46:35 -07:00
|
|
|
|
error = OFPERR_OFPBMC_BAD_PREREQ;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
} else if (!mf_is_all_wild(field, &match->wc)) {
|
2012-03-26 13:46:35 -07:00
|
|
|
|
error = OFPERR_OFPBMC_DUP_FIELD;
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
} else if (pipeline_fields_only && !mf_is_pipeline_field(field)) {
|
|
|
|
|
error = OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY;
|
2013-05-19 15:44:53 +03:00
|
|
|
|
} else {
|
2015-08-31 14:20:17 -07:00
|
|
|
|
char *err_str;
|
|
|
|
|
|
|
|
|
|
mf_set(field, &value, &mask, match, &err_str);
|
|
|
|
|
if (err_str) {
|
|
|
|
|
VLOG_DBG_RL(&rl, "error parsing OXM at offset %"PRIdPTR" "
|
|
|
|
|
"within match (%s)", pos - p, err_str);
|
|
|
|
|
free(err_str);
|
|
|
|
|
return OFPERR_OFPBMC_BAD_VALUE;
|
|
|
|
|
}
|
2017-06-23 16:47:57 +00:00
|
|
|
|
|
|
|
|
|
match_add_ethernet_prereq(match, field);
|
2011-12-23 12:23:24 -08:00
|
|
|
|
}
|
|
|
|
|
|
2010-11-09 17:00:59 -08:00
|
|
|
|
if (error) {
|
2014-09-16 22:13:44 -07:00
|
|
|
|
VLOG_DBG_RL(&rl, "error parsing OXM at offset %"PRIdPTR" "
|
|
|
|
|
"within match (%s)", pos -
|
|
|
|
|
p, ofperr_to_string(error));
|
2010-11-09 17:00:59 -08:00
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-19 18:36:04 -07:00
|
|
|
|
match->flow.tunnel.metadata.tab = NULL;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
return 0;
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
2012-01-03 13:30:45 -08:00
|
|
|
|
|
2012-08-01 16:01:45 +09:00
|
|
|
|
static enum ofperr
|
|
|
|
|
nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
bool pipeline_fields_only, struct match *match,
|
2016-04-19 18:36:04 -07:00
|
|
|
|
ovs_be64 *cookie, ovs_be64 *cookie_mask,
|
2017-03-13 11:28:20 -07:00
|
|
|
|
const struct tun_table *tun_table,
|
|
|
|
|
const struct vl_mff_map *vl_mff_map)
|
2012-08-01 16:01:45 +09:00
|
|
|
|
{
|
|
|
|
|
uint8_t *p = NULL;
|
|
|
|
|
|
|
|
|
|
if (match_len) {
|
|
|
|
|
p = ofpbuf_try_pull(b, ROUND_UP(match_len, 8));
|
|
|
|
|
if (!p) {
|
|
|
|
|
VLOG_DBG_RL(&rl, "nx_match length %u, rounded up to a "
|
|
|
|
|
"multiple of 8, is longer than space in message (max "
|
2015-03-02 17:29:44 -08:00
|
|
|
|
"length %"PRIu32")", match_len, b->size);
|
2012-08-01 16:01:45 +09:00
|
|
|
|
return OFPERR_OFPBMC_BAD_LEN;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
return nx_pull_raw(p, match_len, strict, pipeline_fields_only, match,
|
|
|
|
|
cookie, cookie_mask, tun_table, vl_mff_map);
|
2012-08-01 16:01:45 +09:00
|
|
|
|
}
|
|
|
|
|
|
2012-01-03 13:30:45 -08:00
|
|
|
|
/* Parses the nx_match formatted match description in 'b' with length
|
2012-08-07 15:28:18 -07:00
|
|
|
|
* 'match_len'. Stores the results in 'match'. If 'cookie' and 'cookie_mask'
|
|
|
|
|
* are valid pointers, then stores the cookie and mask in them if 'b' contains
|
|
|
|
|
* a "NXM_NX_COOKIE*" match. Otherwise, stores 0 in both.
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
* If 'pipeline_fields_only' is true, this function returns
|
|
|
|
|
* OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY if there is any non pipeline fields
|
|
|
|
|
* in 'b'.
|
2012-01-03 13:30:45 -08:00
|
|
|
|
*
|
2017-03-13 11:28:20 -07:00
|
|
|
|
* 'vl_mff_map" is an optional parameter that is used to validate the length
|
|
|
|
|
* of variable length mf_fields in 'match'. If it is not provided, the
|
|
|
|
|
* default mf_fields with maximum length will be used.
|
|
|
|
|
*
|
2012-08-07 15:28:18 -07:00
|
|
|
|
* Fails with an error upon encountering an unknown NXM header.
|
2012-01-03 13:30:45 -08:00
|
|
|
|
*
|
|
|
|
|
* Returns 0 if successful, otherwise an OpenFlow error code. */
|
2012-01-12 15:48:19 -08:00
|
|
|
|
enum ofperr
|
2012-08-07 15:28:18 -07:00
|
|
|
|
nx_pull_match(struct ofpbuf *b, unsigned int match_len, struct match *match,
|
2016-04-19 18:36:04 -07:00
|
|
|
|
ovs_be64 *cookie, ovs_be64 *cookie_mask,
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
bool pipeline_fields_only, const struct tun_table *tun_table,
|
2017-03-13 11:28:20 -07:00
|
|
|
|
const struct vl_mff_map *vl_mff_map)
|
2012-01-03 13:30:45 -08:00
|
|
|
|
{
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
return nx_pull_match__(b, match_len, true, pipeline_fields_only, match,
|
|
|
|
|
cookie, cookie_mask, tun_table, vl_mff_map);
|
2012-01-03 13:30:45 -08:00
|
|
|
|
}
|
|
|
|
|
|
2012-08-07 15:28:18 -07:00
|
|
|
|
/* Behaves the same as nx_pull_match(), but skips over unknown NXM headers,
|
2017-03-08 17:18:23 -08:00
|
|
|
|
* instead of failing with an error, and does not check for field
|
2017-06-09 19:47:50 -07:00
|
|
|
|
* prerequisites. */
|
2012-01-12 15:48:19 -08:00
|
|
|
|
enum ofperr
|
2012-01-03 13:30:45 -08:00
|
|
|
|
nx_pull_match_loose(struct ofpbuf *b, unsigned int match_len,
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
struct match *match, ovs_be64 *cookie,
|
|
|
|
|
ovs_be64 *cookie_mask, bool pipeline_fields_only,
|
2016-04-19 18:36:04 -07:00
|
|
|
|
const struct tun_table *tun_table)
|
2012-01-03 13:30:45 -08:00
|
|
|
|
{
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
return nx_pull_match__(b, match_len, false, pipeline_fields_only, match,
|
|
|
|
|
cookie, cookie_mask, tun_table, NULL);
|
2012-01-03 13:30:45 -08:00
|
|
|
|
}
|
2012-08-01 16:01:45 +09:00
|
|
|
|
|
|
|
|
|
static enum ofperr
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
oxm_pull_match__(struct ofpbuf *b, bool strict, bool pipeline_fields_only,
|
2017-03-13 11:28:20 -07:00
|
|
|
|
const struct tun_table *tun_table,
|
|
|
|
|
const struct vl_mff_map *vl_mff_map, struct match *match)
|
2012-08-01 16:01:45 +09:00
|
|
|
|
{
|
2015-03-02 17:29:44 -08:00
|
|
|
|
struct ofp11_match_header *omh = b->data;
|
2012-08-01 16:01:45 +09:00
|
|
|
|
uint8_t *p;
|
|
|
|
|
uint16_t match_len;
|
|
|
|
|
|
2015-03-02 17:29:44 -08:00
|
|
|
|
if (b->size < sizeof *omh) {
|
2012-08-01 16:01:45 +09:00
|
|
|
|
return OFPERR_OFPBMC_BAD_LEN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
match_len = ntohs(omh->length);
|
|
|
|
|
if (match_len < sizeof *omh) {
|
|
|
|
|
return OFPERR_OFPBMC_BAD_LEN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (omh->type != htons(OFPMT_OXM)) {
|
|
|
|
|
return OFPERR_OFPBMC_BAD_TYPE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p = ofpbuf_try_pull(b, ROUND_UP(match_len, 8));
|
|
|
|
|
if (!p) {
|
|
|
|
|
VLOG_DBG_RL(&rl, "oxm length %u, rounded up to a "
|
|
|
|
|
"multiple of 8, is longer than space in message (max "
|
2015-03-02 17:29:44 -08:00
|
|
|
|
"length %"PRIu32")", match_len, b->size);
|
2012-08-01 16:01:45 +09:00
|
|
|
|
return OFPERR_OFPBMC_BAD_LEN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nx_pull_raw(p + sizeof *omh, match_len - sizeof *omh,
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
strict, pipeline_fields_only, match, NULL, NULL,
|
|
|
|
|
tun_table, vl_mff_map);
|
2012-08-01 16:01:45 +09:00
|
|
|
|
}
|
|
|
|
|
|
2013-10-16 17:26:19 +09:00
|
|
|
|
/* Parses the oxm formatted match description preceded by a struct
|
|
|
|
|
* ofp11_match_header in 'b'. Stores the result in 'match'.
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
* If 'pipeline_fields_only' is true, this function returns
|
|
|
|
|
* OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY if there is any non pipeline fields
|
|
|
|
|
* in 'b'.
|
2012-08-01 16:01:45 +09:00
|
|
|
|
*
|
2017-03-13 11:28:20 -07:00
|
|
|
|
* 'vl_mff_map' is an optional parameter that is used to validate the length
|
|
|
|
|
* of variable length mf_fields in 'match'. If it is not provided, the
|
|
|
|
|
* default mf_fields with maximum length will be used.
|
|
|
|
|
*
|
2012-08-01 16:01:45 +09:00
|
|
|
|
* Fails with an error when encountering unknown OXM headers.
|
|
|
|
|
*
|
|
|
|
|
* Returns 0 if successful, otherwise an OpenFlow error code. */
|
|
|
|
|
enum ofperr
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
oxm_pull_match(struct ofpbuf *b, bool pipeline_fields_only,
|
|
|
|
|
const struct tun_table *tun_table,
|
2017-03-13 11:28:20 -07:00
|
|
|
|
const struct vl_mff_map *vl_mff_map, struct match *match)
|
2012-08-01 16:01:45 +09:00
|
|
|
|
{
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
return oxm_pull_match__(b, true, pipeline_fields_only, tun_table,
|
|
|
|
|
vl_mff_map, match);
|
2012-08-01 16:01:45 +09:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-08 17:18:23 -08:00
|
|
|
|
/* Behaves the same as oxm_pull_match() with two exceptions. Skips over
|
|
|
|
|
* unknown OXM headers instead of failing with an error when they are
|
2017-06-09 19:47:50 -07:00
|
|
|
|
* encountered, and does not check for field prerequisites. */
|
2012-08-01 16:01:45 +09:00
|
|
|
|
enum ofperr
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
oxm_pull_match_loose(struct ofpbuf *b, bool pipeline_fields_only,
|
|
|
|
|
const struct tun_table *tun_table, struct match *match)
|
2012-08-01 16:01:45 +09:00
|
|
|
|
{
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
return oxm_pull_match__(b, false, pipeline_fields_only, tun_table, NULL,
|
|
|
|
|
match);
|
2012-08-01 16:01:45 +09:00
|
|
|
|
}
|
2015-03-20 13:50:30 +09:00
|
|
|
|
|
2016-01-18 14:55:30 -08:00
|
|
|
|
/* Parses the OXM match description in the 'oxm_len' bytes in 'oxm'. Stores
|
|
|
|
|
* the result in 'match'.
|
|
|
|
|
*
|
2017-03-08 17:18:23 -08:00
|
|
|
|
* Returns 0 if successful, otherwise an OpenFlow error code.
|
2016-01-18 14:55:30 -08:00
|
|
|
|
*
|
2017-03-13 11:27:49 -07:00
|
|
|
|
* If 'loose' is true, encountering unknown OXM headers or missing field
|
|
|
|
|
* prerequisites are not considered as error conditions.
|
2017-03-08 17:18:23 -08:00
|
|
|
|
*/
|
2016-01-18 14:55:30 -08:00
|
|
|
|
enum ofperr
|
2017-03-13 11:27:49 -07:00
|
|
|
|
oxm_decode_match(const void *oxm, size_t oxm_len, bool loose,
|
2017-03-13 11:28:20 -07:00
|
|
|
|
const struct tun_table *tun_table,
|
|
|
|
|
const struct vl_mff_map *vl_mff_map, struct match *match)
|
2016-01-18 14:55:30 -08:00
|
|
|
|
{
|
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates
the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY
is returned if the match field of a packet-out messages contains any
non pipeline fields. Currently, the supported pipeline fields
are as following.
* metadata fields:
- in_port, in_port_oxm
* tunnel fields:
- tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst
- tun_gbp_id, tun_gpb_flags, tun_flags
- tun_metadata0 - tun_metadata63
* register fields:
- metadata
- reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-05-15 10:04:57 -07:00
|
|
|
|
return nx_pull_raw(oxm, oxm_len, !loose, false, match, NULL, NULL,
|
|
|
|
|
tun_table, vl_mff_map);
|
2016-01-18 14:55:30 -08:00
|
|
|
|
}
|
|
|
|
|
|
2015-03-20 13:50:30 +09:00
|
|
|
|
/* Verify an array of OXM TLVs treating value of each TLV as a mask,
|
|
|
|
|
* disallowing masks in each TLV and ignoring pre-requisites. */
|
|
|
|
|
enum ofperr
|
|
|
|
|
oxm_pull_field_array(const void *fields_data, size_t fields_len,
|
|
|
|
|
struct field_array *fa)
|
|
|
|
|
{
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(fields_data, fields_len);
|
2015-03-20 13:50:30 +09:00
|
|
|
|
while (b.size) {
|
|
|
|
|
const uint8_t *pos = b.data;
|
|
|
|
|
const struct mf_field *field;
|
|
|
|
|
union mf_value value;
|
|
|
|
|
enum ofperr error;
|
|
|
|
|
uint64_t header;
|
|
|
|
|
|
ofp-actions: Fix variable length meta-flow OXMs.
Previously, if a flow action that involves a tunnel metadata meta-flow
field is dumped from vswitchd, the replied field length in the OXM header
is filled with the maximum possible field length, instead of the length
configured in the tunnel TLV mapping table. To solve this issue, this patch
introduces the following changes.
In order to maintain the correct length of variable length mf_fields (i.e.
tun_metadata), this patch creates a per-switch based map (struct vl_mff_map)
that hosts the variable length mf_fields. This map is updated when a
controller adds/deletes tlv-mapping entries to/from a switch. Although the
per-swtch based vl_mff_map only hosts tun_metadata for now, it is able to
support new variable length mf_fields in the future.
With this commit, when a switch decodes a flow action with mf_field, the switch
firstly looks up the global mf_fields map to identify the mf_field type. For
the variable length mf_fields, the switch uses the vl_mff_map to get the
configured mf_field entries. By lookig up vl_mff_map, the switch can check
if the added flow action access beyond the configured size of a variable
length mf_field, and the switch reports an ofperr if the controller adds a flow
with unmapped variable length mf_field. Later on, when a controller request
flows from the switch, with the per-switch based mf_fields, the switch will
encode the OXM header with correct length for variable length mf_fields.
To use the vl_mff_map for decoding flow actions, extract-ofp-actions is
updated to pass the vl_mff_map to the required action decoding functions.
Also, a new error code is introduced to identify a flow with an invalid
variable length mf_field. Moreover, a testcase is added to prevent future
regressions.
Committer notes:
- Factor out common code
- Style fixups
- Rename OFPERR_NXFMFC_INVALID_VL_MFF -> OFPERR_NXFMFC_INVALID_TLV_FIELD
VMWare-BZ: #1768370
Reported-by: Harold Lim <haroldl@vmware.com>
Suggested-by: Joe Stringer <joe@ovn.org>
Suggested-by: Jarno Rajahalme <jarno@ovn.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Joe Stringer <joe@ovn.org>
2017-01-20 15:12:21 -08:00
|
|
|
|
error = nx_pull_entry__(&b, false, NULL, &header, &field, &value,
|
2019-01-16 16:53:52 -08:00
|
|
|
|
NULL, false);
|
2015-03-20 13:50:30 +09:00
|
|
|
|
if (error) {
|
|
|
|
|
VLOG_DBG_RL(&rl, "error pulling field array field");
|
|
|
|
|
} else if (!field) {
|
|
|
|
|
VLOG_DBG_RL(&rl, "unknown field array field");
|
|
|
|
|
error = OFPERR_OFPBMC_BAD_FIELD;
|
|
|
|
|
} else if (bitmap_is_set(fa->used.bm, field->id)) {
|
|
|
|
|
VLOG_DBG_RL(&rl, "duplicate field array field '%s'", field->name);
|
|
|
|
|
error = OFPERR_OFPBMC_DUP_FIELD;
|
|
|
|
|
} else if (!mf_is_mask_valid(field, &value)) {
|
|
|
|
|
VLOG_DBG_RL(&rl, "bad mask in field array field '%s'", field->name);
|
2018-07-26 15:43:27 -07:00
|
|
|
|
error = OFPERR_OFPBMC_BAD_MASK;
|
2015-03-20 13:50:30 +09:00
|
|
|
|
} else {
|
|
|
|
|
field_array_set(field->id, &value, fa);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
|
const uint8_t *start = fields_data;
|
|
|
|
|
|
|
|
|
|
VLOG_DBG_RL(&rl, "error parsing OXM at offset %"PRIdPTR" "
|
|
|
|
|
"within field array (%s)", pos - start,
|
|
|
|
|
ofperr_to_string(error));
|
2018-07-26 15:43:27 -07:00
|
|
|
|
|
|
|
|
|
free(fa->values);
|
2018-08-24 14:50:12 -07:00
|
|
|
|
fa->values = NULL;
|
2015-03-20 13:50:30 +09:00
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2010-11-09 17:00:59 -08:00
|
|
|
|
|
|
|
|
|
/* nx_put_match() and helpers.
|
|
|
|
|
*
|
|
|
|
|
* 'put' functions whose names end in 'w' add a wildcarded field.
|
|
|
|
|
* 'put' functions whose names end in 'm' add a field that might be wildcarded.
|
|
|
|
|
* Other 'put' functions add exact-match fields.
|
|
|
|
|
*/
|
2017-06-23 16:47:54 +00:00
|
|
|
|
|
|
|
|
|
struct nxm_put_ctx {
|
|
|
|
|
struct ofpbuf *output;
|
2017-06-23 16:47:57 +00:00
|
|
|
|
bool implied_ethernet;
|
2017-06-23 16:47:54 +00:00
|
|
|
|
};
|
|
|
|
|
|
2015-08-11 18:41:37 -07:00
|
|
|
|
void
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_entry_raw(struct ofpbuf *b,
|
|
|
|
|
enum mf_field_id field, enum ofp_version version,
|
|
|
|
|
const void *value, const void *mask, size_t n_bytes)
|
2010-11-09 17:00:59 -08:00
|
|
|
|
{
|
2015-08-11 18:41:37 -07:00
|
|
|
|
nx_put_header_len(b, field, version, !!mask, n_bytes);
|
2014-09-30 17:26:28 -07:00
|
|
|
|
ofpbuf_put(b, value, n_bytes);
|
2015-08-11 18:41:37 -07:00
|
|
|
|
if (mask) {
|
|
|
|
|
ofpbuf_put(b, mask, n_bytes);
|
|
|
|
|
}
|
2017-06-23 16:47:54 +00:00
|
|
|
|
}
|
2015-08-11 18:41:37 -07:00
|
|
|
|
|
2017-06-23 16:47:54 +00:00
|
|
|
|
static void
|
|
|
|
|
nxm_put__(struct nxm_put_ctx *ctx,
|
|
|
|
|
enum mf_field_id field, enum ofp_version version,
|
|
|
|
|
const void *value, const void *mask, size_t n_bytes)
|
|
|
|
|
{
|
|
|
|
|
nxm_put_entry_raw(ctx->output, field, version, value, mask, n_bytes);
|
2017-06-23 16:47:57 +00:00
|
|
|
|
if (!ctx->implied_ethernet && mf_from_id(field)->prereqs != MFP_NONE) {
|
|
|
|
|
ctx->implied_ethernet = true;
|
|
|
|
|
}
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-11 18:41:37 -07:00
|
|
|
|
static void
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put(struct nxm_put_ctx *ctx,
|
|
|
|
|
enum mf_field_id field, enum ofp_version version,
|
2014-09-30 17:26:28 -07:00
|
|
|
|
const void *value, const void *mask, size_t n_bytes)
|
2010-11-23 10:06:28 -08:00
|
|
|
|
{
|
2014-09-30 17:26:28 -07:00
|
|
|
|
if (!is_all_zeros(mask, n_bytes)) {
|
|
|
|
|
bool masked = !is_all_ones(mask, n_bytes);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put__(ctx, field, version, value, masked ? mask : NULL, n_bytes);
|
2010-11-23 10:06:28 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-09 17:00:59 -08:00
|
|
|
|
static void
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_8m(struct nxm_put_ctx *ctx,
|
|
|
|
|
enum mf_field_id field, enum ofp_version version,
|
2014-09-30 17:26:28 -07:00
|
|
|
|
uint8_t value, uint8_t mask)
|
2010-11-09 17:00:59 -08:00
|
|
|
|
{
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put(ctx, field, version, &value, &mask, sizeof value);
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_8(struct nxm_put_ctx *ctx,
|
|
|
|
|
enum mf_field_id field, enum ofp_version version, uint8_t value)
|
2010-11-09 17:00:59 -08:00
|
|
|
|
{
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put__(ctx, field, version, &value, NULL, sizeof value);
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16m(struct nxm_put_ctx *ctx,
|
|
|
|
|
enum mf_field_id field, enum ofp_version version,
|
2014-09-30 17:26:28 -07:00
|
|
|
|
ovs_be16 value, ovs_be16 mask)
|
2010-11-09 17:00:59 -08:00
|
|
|
|
{
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put(ctx, field, version, &value, &mask, sizeof value);
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16(struct nxm_put_ctx *ctx,
|
|
|
|
|
enum mf_field_id field, enum ofp_version version, ovs_be16 value)
|
2010-11-09 17:00:59 -08:00
|
|
|
|
{
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put__(ctx, field, version, &value, NULL, sizeof value);
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
|
|
|
|
|
2011-01-20 15:29:00 -08:00
|
|
|
|
static void
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32m(struct nxm_put_ctx *ctx,
|
|
|
|
|
enum mf_field_id field, enum ofp_version version,
|
2014-09-30 17:26:28 -07:00
|
|
|
|
ovs_be32 value, ovs_be32 mask)
|
2011-01-20 15:29:00 -08:00
|
|
|
|
{
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put(ctx, field, version, &value, &mask, sizeof value);
|
2011-01-20 15:29:00 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32(struct nxm_put_ctx *ctx,
|
|
|
|
|
enum mf_field_id field, enum ofp_version version, ovs_be32 value)
|
2011-01-20 15:29:00 -08:00
|
|
|
|
{
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put__(ctx, field, version, &value, NULL, sizeof value);
|
2011-01-20 15:29:00 -08:00
|
|
|
|
}
|
|
|
|
|
|
2010-11-09 17:00:59 -08:00
|
|
|
|
static void
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_64m(struct nxm_put_ctx *ctx,
|
|
|
|
|
enum mf_field_id field, enum ofp_version version,
|
2014-09-30 17:26:28 -07:00
|
|
|
|
ovs_be64 value, ovs_be64 mask)
|
2010-11-09 17:00:59 -08:00
|
|
|
|
{
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put(ctx, field, version, &value, &mask, sizeof value);
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-31 04:28:00 -07:00
|
|
|
|
static void
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_128m(struct nxm_put_ctx *ctx,
|
2015-10-31 04:28:00 -07:00
|
|
|
|
enum mf_field_id field, enum ofp_version version,
|
|
|
|
|
const ovs_be128 value, const ovs_be128 mask)
|
|
|
|
|
{
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put(ctx, field, version, &value, &mask, sizeof(value));
|
2015-10-31 04:28:00 -07:00
|
|
|
|
}
|
|
|
|
|
|
2010-11-11 10:46:23 -08:00
|
|
|
|
static void
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_eth_masked(struct nxm_put_ctx *ctx,
|
2014-09-30 17:26:28 -07:00
|
|
|
|
enum mf_field_id field, enum ofp_version version,
|
2015-08-28 14:55:11 -07:00
|
|
|
|
const struct eth_addr value, const struct eth_addr mask)
|
2010-11-11 10:46:23 -08:00
|
|
|
|
{
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put(ctx, field, version, value.ea, mask.ea, ETH_ADDR_LEN);
|
2010-11-11 10:46:23 -08:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-29 19:03:46 -08:00
|
|
|
|
static void
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_ipv6(struct nxm_put_ctx *ctx,
|
2014-09-30 17:26:28 -07:00
|
|
|
|
enum mf_field_id field, enum ofp_version version,
|
2010-12-29 19:03:46 -08:00
|
|
|
|
const struct in6_addr *value, const struct in6_addr *mask)
|
|
|
|
|
{
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put(ctx, field, version, value->s6_addr, mask->s6_addr,
|
2014-09-30 17:26:28 -07:00
|
|
|
|
sizeof value->s6_addr);
|
2010-12-29 19:03:46 -08:00
|
|
|
|
}
|
|
|
|
|
|
Implement new fragment handling policy.
Until now, OVS has handled IP fragments more awkwardly than necessary. It
has not been possible to match on L4 headers, even in fragments with offset
0 where they are actually present. This means that there was no way to
implement ACLs that treat, say, different TCP ports differently, on
fragmented traffic; instead, all decisions for fragment forwarding had to
be made on the basis of L2 and L3 headers alone.
This commit improves the situation significantly. It is still not possible
to match on L4 headers in fragments with nonzero offset, because that
information is simply not present in such fragments, but this commit adds
the ability to match on L4 headers for fragments with zero offset. This
means that it becomes possible to implement ACLs that drop such "first
fragments" on the basis of L4 headers. In practice, that effectively
blocks even fragmented traffic on an L4 basis, because the receiving IP
stack cannot reassemble a full packet when the first fragment is missing.
This commit works by adding a new "fragment type" to the kernel flow match
and making it available through OpenFlow as a new NXM field named
NXM_NX_IP_FRAG. Because OpenFlow 1.0 explicitly says that the L4 fields
are always 0 for IP fragments, it adds a new OpenFlow fragment handling
mode that fills in the L4 fields for "first fragments". It also enhances
ovs-ofctl to allow users to configure this new fragment handling mode and
to parse the new field.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Bug #7557.
2011-10-19 21:33:44 -07:00
|
|
|
|
static void
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_frag(struct nxm_put_ctx *ctx, const struct match *match,
|
2014-09-30 17:26:28 -07:00
|
|
|
|
enum ofp_version version)
|
Implement new fragment handling policy.
Until now, OVS has handled IP fragments more awkwardly than necessary. It
has not been possible to match on L4 headers, even in fragments with offset
0 where they are actually present. This means that there was no way to
implement ACLs that treat, say, different TCP ports differently, on
fragmented traffic; instead, all decisions for fragment forwarding had to
be made on the basis of L2 and L3 headers alone.
This commit improves the situation significantly. It is still not possible
to match on L4 headers in fragments with nonzero offset, because that
information is simply not present in such fragments, but this commit adds
the ability to match on L4 headers for fragments with zero offset. This
means that it becomes possible to implement ACLs that drop such "first
fragments" on the basis of L4 headers. In practice, that effectively
blocks even fragmented traffic on an L4 basis, because the receiving IP
stack cannot reassemble a full packet when the first fragment is missing.
This commit works by adding a new "fragment type" to the kernel flow match
and making it available through OpenFlow as a new NXM field named
NXM_NX_IP_FRAG. Because OpenFlow 1.0 explicitly says that the L4 fields
are always 0 for IP fragments, it adds a new OpenFlow fragment handling
mode that fills in the L4 fields for "first fragments". It also enhances
ovs-ofctl to allow users to configure this new fragment handling mode and
to parse the new field.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Bug #7557.
2011-10-19 21:33:44 -07:00
|
|
|
|
{
|
2014-09-30 17:26:28 -07:00
|
|
|
|
uint8_t nw_frag = match->flow.nw_frag & FLOW_NW_FRAG_MASK;
|
|
|
|
|
uint8_t nw_frag_mask = match->wc.masks.nw_frag & FLOW_NW_FRAG_MASK;
|
Implement new fragment handling policy.
Until now, OVS has handled IP fragments more awkwardly than necessary. It
has not been possible to match on L4 headers, even in fragments with offset
0 where they are actually present. This means that there was no way to
implement ACLs that treat, say, different TCP ports differently, on
fragmented traffic; instead, all decisions for fragment forwarding had to
be made on the basis of L2 and L3 headers alone.
This commit improves the situation significantly. It is still not possible
to match on L4 headers in fragments with nonzero offset, because that
information is simply not present in such fragments, but this commit adds
the ability to match on L4 headers for fragments with zero offset. This
means that it becomes possible to implement ACLs that drop such "first
fragments" on the basis of L4 headers. In practice, that effectively
blocks even fragmented traffic on an L4 basis, because the receiving IP
stack cannot reassemble a full packet when the first fragment is missing.
This commit works by adding a new "fragment type" to the kernel flow match
and making it available through OpenFlow as a new NXM field named
NXM_NX_IP_FRAG. Because OpenFlow 1.0 explicitly says that the L4 fields
are always 0 for IP fragments, it adds a new OpenFlow fragment handling
mode that fills in the L4 fields for "first fragments". It also enhances
ovs-ofctl to allow users to configure this new fragment handling mode and
to parse the new field.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Bug #7557.
2011-10-19 21:33:44 -07:00
|
|
|
|
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_8m(ctx, MFF_IP_FRAG, version, nw_frag,
|
2014-09-30 17:26:28 -07:00
|
|
|
|
nw_frag_mask == FLOW_NW_FRAG_MASK ? UINT8_MAX : nw_frag_mask);
|
Implement new fragment handling policy.
Until now, OVS has handled IP fragments more awkwardly than necessary. It
has not been possible to match on L4 headers, even in fragments with offset
0 where they are actually present. This means that there was no way to
implement ACLs that treat, say, different TCP ports differently, on
fragmented traffic; instead, all decisions for fragment forwarding had to
be made on the basis of L2 and L3 headers alone.
This commit improves the situation significantly. It is still not possible
to match on L4 headers in fragments with nonzero offset, because that
information is simply not present in such fragments, but this commit adds
the ability to match on L4 headers for fragments with zero offset. This
means that it becomes possible to implement ACLs that drop such "first
fragments" on the basis of L4 headers. In practice, that effectively
blocks even fragmented traffic on an L4 basis, because the receiving IP
stack cannot reassemble a full packet when the first fragment is missing.
This commit works by adding a new "fragment type" to the kernel flow match
and making it available through OpenFlow as a new NXM field named
NXM_NX_IP_FRAG. Because OpenFlow 1.0 explicitly says that the L4 fields
are always 0 for IP fragments, it adds a new OpenFlow fragment handling
mode that fills in the L4 fields for "first fragments". It also enhances
ovs-ofctl to allow users to configure this new fragment handling mode and
to parse the new field.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Bug #7557.
2011-10-19 21:33:44 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-05-09 18:16:38 -07:00
|
|
|
|
/* Appends to 'b' a set of OXM or NXM matches for the IPv4 or IPv6 fields in
|
|
|
|
|
* 'match'. */
|
2012-02-02 16:44:44 -08:00
|
|
|
|
static void
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_ip(struct nxm_put_ctx *ctx,
|
|
|
|
|
const struct match *match, enum ofp_version oxm)
|
2012-02-02 16:44:44 -08:00
|
|
|
|
{
|
2012-08-07 15:28:18 -07:00
|
|
|
|
const struct flow *flow = &match->flow;
|
2017-06-23 16:47:57 +00:00
|
|
|
|
ovs_be16 dl_type = get_dl_type(flow);
|
2012-02-02 16:44:44 -08:00
|
|
|
|
|
2017-06-23 16:47:57 +00:00
|
|
|
|
if (dl_type == htons(ETH_TYPE_IP)) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32m(ctx, MFF_IPV4_SRC, oxm,
|
2014-05-09 18:16:38 -07:00
|
|
|
|
flow->nw_src, match->wc.masks.nw_src);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32m(ctx, MFF_IPV4_DST, oxm,
|
2014-05-09 18:16:38 -07:00
|
|
|
|
flow->nw_dst, match->wc.masks.nw_dst);
|
|
|
|
|
} else {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_ipv6(ctx, MFF_IPV6_SRC, oxm,
|
2014-05-09 18:16:38 -07:00
|
|
|
|
&flow->ipv6_src, &match->wc.masks.ipv6_src);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_ipv6(ctx, MFF_IPV6_DST, oxm,
|
2014-05-09 18:16:38 -07:00
|
|
|
|
&flow->ipv6_dst, &match->wc.masks.ipv6_dst);
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_frag(ctx, match, oxm);
|
2012-02-02 16:44:44 -08:00
|
|
|
|
|
2012-08-07 15:28:18 -07:00
|
|
|
|
if (match->wc.masks.nw_tos & IP_DSCP_MASK) {
|
2013-04-18 09:40:48 -07:00
|
|
|
|
if (oxm) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_8(ctx, MFF_IP_DSCP_SHIFTED, oxm,
|
2014-05-09 18:18:17 -07:00
|
|
|
|
flow->nw_tos >> 2);
|
2013-04-18 09:40:48 -07:00
|
|
|
|
} else {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_8(ctx, MFF_IP_DSCP, oxm,
|
2014-05-09 18:18:17 -07:00
|
|
|
|
flow->nw_tos & IP_DSCP_MASK);
|
2013-04-18 09:40:48 -07:00
|
|
|
|
}
|
2012-02-02 16:44:44 -08:00
|
|
|
|
}
|
|
|
|
|
|
2012-08-07 15:28:18 -07:00
|
|
|
|
if (match->wc.masks.nw_tos & IP_ECN_MASK) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_8(ctx, MFF_IP_ECN, oxm,
|
2012-06-11 09:56:12 -07:00
|
|
|
|
flow->nw_tos & IP_ECN_MASK);
|
2012-02-02 16:44:44 -08:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-09 20:33:26 -07:00
|
|
|
|
if (match->wc.masks.nw_ttl) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_8(ctx, MFF_IP_TTL, oxm, flow->nw_ttl);
|
2012-02-02 16:44:44 -08:00
|
|
|
|
}
|
|
|
|
|
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32m(ctx, MFF_IPV6_LABEL, oxm,
|
2014-05-09 18:16:38 -07:00
|
|
|
|
flow->ipv6_label, match->wc.masks.ipv6_label);
|
|
|
|
|
|
2012-08-07 15:28:18 -07:00
|
|
|
|
if (match->wc.masks.nw_proto) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_8(ctx, MFF_IP_PROTO, oxm, flow->nw_proto);
|
2012-02-02 16:44:44 -08:00
|
|
|
|
|
|
|
|
|
if (flow->nw_proto == IPPROTO_TCP) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16m(ctx, MFF_TCP_SRC, oxm,
|
2012-08-07 15:28:18 -07:00
|
|
|
|
flow->tp_src, match->wc.masks.tp_src);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16m(ctx, MFF_TCP_DST, oxm,
|
2012-08-07 15:28:18 -07:00
|
|
|
|
flow->tp_dst, match->wc.masks.tp_dst);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16m(ctx, MFF_TCP_FLAGS, oxm,
|
2013-10-28 13:54:40 -07:00
|
|
|
|
flow->tcp_flags, match->wc.masks.tcp_flags);
|
2012-02-02 16:44:44 -08:00
|
|
|
|
} else if (flow->nw_proto == IPPROTO_UDP) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16m(ctx, MFF_UDP_SRC, oxm,
|
2012-08-07 15:28:18 -07:00
|
|
|
|
flow->tp_src, match->wc.masks.tp_src);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16m(ctx, MFF_UDP_DST, oxm,
|
2012-08-07 15:28:18 -07:00
|
|
|
|
flow->tp_dst, match->wc.masks.tp_dst);
|
2013-08-22 20:24:45 +12:00
|
|
|
|
} else if (flow->nw_proto == IPPROTO_SCTP) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16m(ctx, MFF_SCTP_SRC, oxm, flow->tp_src,
|
2013-08-22 20:24:45 +12:00
|
|
|
|
match->wc.masks.tp_src);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16m(ctx, MFF_SCTP_DST, oxm, flow->tp_dst,
|
2013-08-22 20:24:45 +12:00
|
|
|
|
match->wc.masks.tp_dst);
|
2016-05-08 10:34:10 -07:00
|
|
|
|
} else if (is_icmpv4(flow, NULL)) {
|
2014-05-09 18:16:38 -07:00
|
|
|
|
if (match->wc.masks.tp_src) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_8(ctx, MFF_ICMPV4_TYPE, oxm,
|
2014-05-09 18:16:38 -07:00
|
|
|
|
ntohs(flow->tp_src));
|
|
|
|
|
}
|
|
|
|
|
if (match->wc.masks.tp_dst) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_8(ctx, MFF_ICMPV4_CODE, oxm,
|
2014-05-09 18:16:38 -07:00
|
|
|
|
ntohs(flow->tp_dst));
|
|
|
|
|
}
|
2016-05-08 10:34:10 -07:00
|
|
|
|
} else if (is_icmpv6(flow, NULL)) {
|
2012-08-07 15:28:18 -07:00
|
|
|
|
if (match->wc.masks.tp_src) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_8(ctx, MFF_ICMPV6_TYPE, oxm,
|
2014-05-09 18:16:38 -07:00
|
|
|
|
ntohs(flow->tp_src));
|
2012-02-02 16:44:44 -08:00
|
|
|
|
}
|
2012-08-07 15:28:18 -07:00
|
|
|
|
if (match->wc.masks.tp_dst) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_8(ctx, MFF_ICMPV6_CODE, oxm,
|
2014-05-09 18:16:38 -07:00
|
|
|
|
ntohs(flow->tp_dst));
|
|
|
|
|
}
|
2016-07-02 11:35:29 -07:00
|
|
|
|
if (is_nd(flow, NULL)) {
|
2019-01-28 11:41:06 +00:00
|
|
|
|
if (match->wc.masks.igmp_group_ip4) {
|
|
|
|
|
nxm_put_32(ctx, MFF_ND_RESERVED, oxm,
|
|
|
|
|
flow->igmp_group_ip4);
|
|
|
|
|
}
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_ipv6(ctx, MFF_ND_TARGET, oxm,
|
2014-05-09 18:16:38 -07:00
|
|
|
|
&flow->nd_target, &match->wc.masks.nd_target);
|
2019-01-28 11:41:06 +00:00
|
|
|
|
if (match->wc.masks.tcp_flags) {
|
|
|
|
|
nxm_put_8(ctx, MFF_ND_OPTIONS_TYPE, oxm,
|
|
|
|
|
ntohs(flow->tcp_flags));
|
|
|
|
|
}
|
2014-05-09 18:16:38 -07:00
|
|
|
|
if (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_eth_masked(ctx, MFF_ND_SLL, oxm,
|
2014-05-09 18:16:38 -07:00
|
|
|
|
flow->arp_sha, match->wc.masks.arp_sha);
|
|
|
|
|
}
|
|
|
|
|
if (flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_eth_masked(ctx, MFF_ND_TLL, oxm,
|
2014-05-09 18:16:38 -07:00
|
|
|
|
flow->arp_tha, match->wc.masks.arp_tha);
|
|
|
|
|
}
|
2012-02-02 16:44:44 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-07 15:28:18 -07:00
|
|
|
|
/* Appends to 'b' the nx_match format that expresses 'match'. For Flow Mod and
|
2012-08-01 16:01:45 +09:00
|
|
|
|
* Flow Stats Requests messages, a 'cookie' and 'cookie_mask' may be supplied.
|
|
|
|
|
* Otherwise, 'cookie_mask' should be zero.
|
2010-12-15 09:48:16 -08:00
|
|
|
|
*
|
2014-05-09 18:18:17 -07:00
|
|
|
|
* Specify 'oxm' as 0 to express the match in NXM format; otherwise, specify
|
|
|
|
|
* 'oxm' as the OpenFlow version number for the OXM format to use.
|
|
|
|
|
*
|
2010-12-15 09:48:16 -08:00
|
|
|
|
* This function can cause 'b''s data to be reallocated.
|
|
|
|
|
*
|
|
|
|
|
* Returns the number of bytes appended to 'b', excluding padding.
|
|
|
|
|
*
|
2012-08-07 15:28:18 -07:00
|
|
|
|
* If 'match' is a catch-all rule that matches every packet, then this function
|
2010-12-15 09:48:16 -08:00
|
|
|
|
* appends nothing to 'b' and returns 0. */
|
2012-08-01 16:01:45 +09:00
|
|
|
|
static int
|
2014-05-09 18:18:17 -07:00
|
|
|
|
nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
|
2012-08-01 16:01:45 +09:00
|
|
|
|
ovs_be64 cookie, ovs_be64 cookie_mask)
|
2010-11-09 17:00:59 -08:00
|
|
|
|
{
|
2012-08-07 15:28:18 -07:00
|
|
|
|
const struct flow *flow = &match->flow;
|
2015-03-02 17:29:44 -08:00
|
|
|
|
const size_t start_len = b->size;
|
2017-06-23 16:47:57 +00:00
|
|
|
|
ovs_be16 dl_type = get_dl_type(flow);
|
2018-01-11 13:24:01 +08:00
|
|
|
|
ovs_be32 spi_mask;
|
2010-11-09 17:00:59 -08:00
|
|
|
|
int match_len;
|
|
|
|
|
|
2019-11-25 11:19:23 -08:00
|
|
|
|
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
|
2011-07-29 13:15:09 -07:00
|
|
|
|
|
2017-06-23 16:47:57 +00:00
|
|
|
|
struct nxm_put_ctx ctx = { .output = b, .implied_ethernet = false };
|
|
|
|
|
|
|
|
|
|
/* OpenFlow Packet Type. Must be first. */
|
|
|
|
|
if (match->wc.masks.packet_type && !match_has_default_packet_type(match)) {
|
|
|
|
|
nxm_put_32m(&ctx, MFF_PACKET_TYPE, oxm, flow->packet_type,
|
|
|
|
|
match->wc.masks.packet_type);
|
|
|
|
|
}
|
2017-06-23 16:47:54 +00:00
|
|
|
|
|
2010-11-09 17:00:59 -08:00
|
|
|
|
/* Metadata. */
|
2014-03-04 14:20:19 -08:00
|
|
|
|
if (match->wc.masks.dp_hash) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32m(&ctx, MFF_DP_HASH, oxm,
|
2014-09-12 14:42:47 -07:00
|
|
|
|
htonl(flow->dp_hash), htonl(match->wc.masks.dp_hash));
|
2014-03-04 14:20:19 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (match->wc.masks.recirc_id) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32(&ctx, MFF_RECIRC_ID, oxm, htonl(flow->recirc_id));
|
2014-03-04 14:20:19 -08:00
|
|
|
|
}
|
|
|
|
|
|
2015-01-11 13:25:24 -08:00
|
|
|
|
if (match->wc.masks.conj_id) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32(&ctx, MFF_CONJ_ID, oxm, htonl(flow->conj_id));
|
2015-01-11 13:25:24 -08:00
|
|
|
|
}
|
|
|
|
|
|
2013-06-19 16:58:44 -07:00
|
|
|
|
if (match->wc.masks.in_port.ofp_port) {
|
|
|
|
|
ofp_port_t in_port = flow->in_port.ofp_port;
|
2012-06-11 09:56:12 -07:00
|
|
|
|
if (oxm) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32(&ctx, MFF_IN_PORT_OXM, oxm,
|
2014-05-09 18:18:17 -07:00
|
|
|
|
ofputil_port_to_ofp11(in_port));
|
2012-06-11 09:56:12 -07:00
|
|
|
|
} else {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16(&ctx, MFF_IN_PORT, oxm,
|
2014-05-09 18:18:17 -07:00
|
|
|
|
htons(ofp_to_u16(in_port)));
|
2012-06-11 09:56:12 -07:00
|
|
|
|
}
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
2014-11-03 14:24:01 -08:00
|
|
|
|
if (match->wc.masks.actset_output) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32(&ctx, MFF_ACTSET_OUTPUT, oxm,
|
2014-11-03 14:24:01 -08:00
|
|
|
|
ofputil_port_to_ofp11(flow->actset_output));
|
|
|
|
|
}
|
2010-11-09 17:00:59 -08:00
|
|
|
|
|
|
|
|
|
/* Ethernet. */
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_eth_masked(&ctx, MFF_ETH_SRC, oxm,
|
2012-08-07 15:28:18 -07:00
|
|
|
|
flow->dl_src, match->wc.masks.dl_src);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_eth_masked(&ctx, MFF_ETH_DST, oxm,
|
2012-08-07 15:28:18 -07:00
|
|
|
|
flow->dl_dst, match->wc.masks.dl_dst);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16m(&ctx, MFF_ETH_TYPE, oxm,
|
2012-06-18 13:33:13 -07:00
|
|
|
|
ofputil_dl_type_to_openflow(flow->dl_type),
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match->wc.masks.dl_type);
|
2010-11-09 17:00:59 -08:00
|
|
|
|
|
2012-07-23 11:36:43 +09:00
|
|
|
|
/* 802.1Q. */
|
|
|
|
|
if (oxm) {
|
2012-08-07 13:38:38 -07:00
|
|
|
|
ovs_be16 VID_CFI_MASK = htons(VLAN_VID_MASK | VLAN_CFI);
|
2017-03-01 17:47:59 -05:00
|
|
|
|
ovs_be16 vid = flow->vlans[0].tci & VID_CFI_MASK;
|
|
|
|
|
ovs_be16 mask = match->wc.masks.vlans[0].tci & VID_CFI_MASK;
|
2012-07-23 11:36:43 +09:00
|
|
|
|
|
|
|
|
|
if (mask == htons(VLAN_VID_MASK | VLAN_CFI)) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16(&ctx, MFF_VLAN_VID, oxm, vid);
|
2012-07-23 11:36:43 +09:00
|
|
|
|
} else if (mask) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16m(&ctx, MFF_VLAN_VID, oxm, vid, mask);
|
2012-07-23 11:36:43 +09:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-01 17:47:59 -05:00
|
|
|
|
if (vid && vlan_tci_to_pcp(match->wc.masks.vlans[0].tci)) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_8(&ctx, MFF_VLAN_PCP, oxm,
|
2017-03-01 17:47:59 -05:00
|
|
|
|
vlan_tci_to_pcp(flow->vlans[0].tci));
|
2012-07-23 11:36:43 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16m(&ctx, MFF_VLAN_TCI, oxm, flow->vlans[0].tci,
|
2017-03-01 17:47:59 -05:00
|
|
|
|
match->wc.masks.vlans[0].tci);
|
2012-07-23 11:36:43 +09:00
|
|
|
|
}
|
2010-11-09 17:00:59 -08:00
|
|
|
|
|
2013-01-25 16:22:07 +09:00
|
|
|
|
/* MPLS. */
|
2017-06-23 16:47:57 +00:00
|
|
|
|
if (eth_type_mpls(dl_type)) {
|
2014-02-04 10:32:35 -08:00
|
|
|
|
if (match->wc.masks.mpls_lse[0] & htonl(MPLS_TC_MASK)) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_8(&ctx, MFF_MPLS_TC, oxm,
|
2014-05-09 18:18:17 -07:00
|
|
|
|
mpls_lse_to_tc(flow->mpls_lse[0]));
|
2013-01-25 16:22:07 +09:00
|
|
|
|
}
|
|
|
|
|
|
2014-02-04 10:32:35 -08:00
|
|
|
|
if (match->wc.masks.mpls_lse[0] & htonl(MPLS_BOS_MASK)) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_8(&ctx, MFF_MPLS_BOS, oxm,
|
2014-05-09 18:18:17 -07:00
|
|
|
|
mpls_lse_to_bos(flow->mpls_lse[0]));
|
2013-01-25 16:22:07 +09:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-18 19:19:35 +02:00
|
|
|
|
if (match->wc.masks.mpls_lse[0] & htonl(MPLS_TTL_MASK)) {
|
|
|
|
|
nxm_put_8(&ctx, MFF_MPLS_TTL, oxm,
|
|
|
|
|
mpls_lse_to_ttl(flow->mpls_lse[0]));
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-04 10:32:35 -08:00
|
|
|
|
if (match->wc.masks.mpls_lse[0] & htonl(MPLS_LABEL_MASK)) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32(&ctx, MFF_MPLS_LABEL, oxm,
|
2014-02-04 10:32:35 -08:00
|
|
|
|
htonl(mpls_lse_to_label(flow->mpls_lse[0])));
|
2013-01-25 16:22:07 +09:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-23 10:06:28 -08:00
|
|
|
|
/* L3. */
|
2014-05-09 18:16:38 -07:00
|
|
|
|
if (is_ip_any(flow)) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_ip(&ctx, match, oxm);
|
2017-06-23 16:47:57 +00:00
|
|
|
|
} else if (dl_type == htons(ETH_TYPE_ARP) ||
|
|
|
|
|
dl_type == htons(ETH_TYPE_RARP)) {
|
2010-11-09 17:00:59 -08:00
|
|
|
|
/* ARP. */
|
2012-08-07 15:28:18 -07:00
|
|
|
|
if (match->wc.masks.nw_proto) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16(&ctx, MFF_ARP_OP, oxm,
|
2012-06-11 09:56:12 -07:00
|
|
|
|
htons(flow->nw_proto));
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32m(&ctx, MFF_ARP_SPA, oxm,
|
2012-08-07 15:28:18 -07:00
|
|
|
|
flow->nw_src, match->wc.masks.nw_src);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32m(&ctx, MFF_ARP_TPA, oxm,
|
2012-08-07 15:28:18 -07:00
|
|
|
|
flow->nw_dst, match->wc.masks.nw_dst);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_eth_masked(&ctx, MFF_ARP_SHA, oxm,
|
2012-08-07 15:28:18 -07:00
|
|
|
|
flow->arp_sha, match->wc.masks.arp_sha);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_eth_masked(&ctx, MFF_ARP_THA, oxm,
|
2012-08-07 15:28:18 -07:00
|
|
|
|
flow->arp_tha, match->wc.masks.arp_tha);
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Tunnel ID. */
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_64m(&ctx, MFF_TUN_ID, oxm,
|
2013-05-09 15:24:16 +03:00
|
|
|
|
flow->tunnel.tun_id, match->wc.masks.tunnel.tun_id);
|
|
|
|
|
|
|
|
|
|
/* Other tunnel metadata. */
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16m(&ctx, MFF_TUN_FLAGS, oxm,
|
2015-07-08 16:02:30 -07:00
|
|
|
|
htons(flow->tunnel.flags), htons(match->wc.masks.tunnel.flags));
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32m(&ctx, MFF_TUN_SRC, oxm,
|
2013-05-09 15:24:16 +03:00
|
|
|
|
flow->tunnel.ip_src, match->wc.masks.tunnel.ip_src);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32m(&ctx, MFF_TUN_DST, oxm,
|
2013-05-09 15:24:16 +03:00
|
|
|
|
flow->tunnel.ip_dst, match->wc.masks.tunnel.ip_dst);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_ipv6(&ctx, MFF_TUN_IPV6_SRC, oxm,
|
2015-12-04 12:36:50 -02:00
|
|
|
|
&flow->tunnel.ipv6_src, &match->wc.masks.tunnel.ipv6_src);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_ipv6(&ctx, MFF_TUN_IPV6_DST, oxm,
|
2015-12-04 12:36:50 -02:00
|
|
|
|
&flow->tunnel.ipv6_dst, &match->wc.masks.tunnel.ipv6_dst);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16m(&ctx, MFF_TUN_GBP_ID, oxm,
|
2015-02-14 15:13:17 +01:00
|
|
|
|
flow->tunnel.gbp_id, match->wc.masks.tunnel.gbp_id);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_8m(&ctx, MFF_TUN_GBP_FLAGS, oxm,
|
2015-02-14 15:13:17 +01:00
|
|
|
|
flow->tunnel.gbp_flags, match->wc.masks.tunnel.gbp_flags);
|
tunnel: Geneve TLV handling support for OpenFlow.
The current support for Geneve in OVS is exactly equivalent to VXLAN:
it is possible to set and match on the VNI but not on any options
contained in the header. This patch enables the use of options.
The goal for Geneve support is not to add support for any particular option
but to allow end users or controllers to specify what they would like to
match. That is, the full range of Geneve's capabilities should be exposed
without modifying the code (the one exception being options that require
per-packet computation in the fast path).
The main issue with supporting Geneve options is how to integrate the
fields into the existing OpenFlow pipeline. All existing operations
are referred to by their NXM/OXM field name - matches, action generation,
arithmetic operations (i.e. tranfer to a register). However, the Geneve
option space is exactly the same as the OXM space, so a direct mapping
is not feasible. Instead, we create a pool of 64 NXMs that are then
dynamically mapped on Geneve option TLVs using OpenFlow. Once mapped,
these fields become first-class citizens in the OpenFlow pipeline.
An example of how to use Geneve options:
ovs-ofctl add-geneve-map br0 {class=0xffff,type=0,len=4}->tun_metadata0
ovs-ofctl add-flow br0 in_port=LOCAL,actions=set_field:0xffffffff->tun_metadata0,1
This will add a 4 bytes option (filled will all 1's) to all packets
coming from the LOCAL port and then send then out to port 1.
A limitation of this patch is that although the option table is specified
for a particular switch over OpenFlow, it is currently global to all
switches. This will be addressed in a future patch.
Based on work originally done by Madhu Challa. Ben Pfaff also significantly
improved the comments.
Signed-off-by: Madhu Challa <challa@noironetworks.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-04-30 18:09:57 -07:00
|
|
|
|
tun_metadata_to_nx_match(b, oxm, match);
|
2010-11-09 17:00:59 -08:00
|
|
|
|
|
2018-05-15 16:10:48 -04:00
|
|
|
|
/* ERSPAN */
|
|
|
|
|
nxm_put_32m(&ctx, MFF_TUN_ERSPAN_IDX, oxm,
|
|
|
|
|
htonl(flow->tunnel.erspan_idx),
|
|
|
|
|
htonl(match->wc.masks.tunnel.erspan_idx));
|
|
|
|
|
nxm_put_8m(&ctx, MFF_TUN_ERSPAN_VER, oxm,
|
|
|
|
|
flow->tunnel.erspan_ver, match->wc.masks.tunnel.erspan_ver);
|
|
|
|
|
nxm_put_8m(&ctx, MFF_TUN_ERSPAN_DIR, oxm,
|
|
|
|
|
flow->tunnel.erspan_dir, match->wc.masks.tunnel.erspan_dir);
|
|
|
|
|
nxm_put_8m(&ctx, MFF_TUN_ERSPAN_HWID, oxm,
|
|
|
|
|
flow->tunnel.erspan_hwid, match->wc.masks.tunnel.erspan_hwid);
|
|
|
|
|
|
2019-11-25 11:19:23 -08:00
|
|
|
|
/* GTP-U */
|
|
|
|
|
nxm_put_8m(&ctx, MFF_TUN_GTPU_FLAGS, oxm, flow->tunnel.gtpu_flags,
|
|
|
|
|
match->wc.masks.tunnel.gtpu_flags);
|
|
|
|
|
nxm_put_8m(&ctx, MFF_TUN_GTPU_MSGTYPE, oxm, flow->tunnel.gtpu_msgtype,
|
|
|
|
|
match->wc.masks.tunnel.gtpu_msgtype);
|
|
|
|
|
|
userspace: Add support for NSH MD1 match fields
This patch adds support for NSH packet header fields to the OVS
control plane and the userspace datapath. Initially we support the
fields of the NSH base header as defined in
https://www.ietf.org/id/draft-ietf-sfc-nsh-13.txt
and the fixed context headers specified for metadata format MD1.
The variable length MD2 format is parsed but the TLV context headers
are not yet available for matching.
The NSH fields are modelled as experimenter fields with the dedicated
experimenter class 0x005ad650 proposed for NSH in ONF. The following
fields are defined:
NXOXM code ofctl name Size Comment
=====================================================================
NXOXM_NSH_FLAGS nsh_flags 8 Bits 2-9 of 1st NSH word
(0x005ad650,1)
NXOXM_NSH_MDTYPE nsh_mdtype 8 Bits 16-23
(0x005ad650,2)
NXOXM_NSH_NEXTPROTO nsh_np 8 Bits 24-31
(0x005ad650,3)
NXOXM_NSH_SPI nsh_spi 24 Bits 0-23 of 2nd NSH word
(0x005ad650,4)
NXOXM_NSH_SI nsh_si 8 Bits 24-31
(0x005ad650,5)
NXOXM_NSH_C1 nsh_c1 32 Maskable, nsh_mdtype==1
(0x005ad650,6)
NXOXM_NSH_C2 nsh_c2 32 Maskable, nsh_mdtype==1
(0x005ad650,7)
NXOXM_NSH_C3 nsh_c3 32 Maskable, nsh_mdtype==1
(0x005ad650,8)
NXOXM_NSH_C4 nsh_c4 32 Maskable, nsh_mdtype==1
(0x005ad650,9)
Co-authored-by: Johnson Li <johnson.li@intel.com>
Signed-off-by: Yi Yang <yi.y.yang@intel.com>
Signed-off-by: Jan Scheurich <jan.scheurich@ericsson.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-08-05 13:41:08 +08:00
|
|
|
|
/* Network Service Header */
|
|
|
|
|
nxm_put_8m(&ctx, MFF_NSH_FLAGS, oxm, flow->nsh.flags,
|
|
|
|
|
match->wc.masks.nsh.flags);
|
2018-01-11 13:24:01 +08:00
|
|
|
|
nxm_put_8m(&ctx, MFF_NSH_TTL, oxm, flow->nsh.ttl,
|
|
|
|
|
match->wc.masks.nsh.ttl);
|
userspace: Add support for NSH MD1 match fields
This patch adds support for NSH packet header fields to the OVS
control plane and the userspace datapath. Initially we support the
fields of the NSH base header as defined in
https://www.ietf.org/id/draft-ietf-sfc-nsh-13.txt
and the fixed context headers specified for metadata format MD1.
The variable length MD2 format is parsed but the TLV context headers
are not yet available for matching.
The NSH fields are modelled as experimenter fields with the dedicated
experimenter class 0x005ad650 proposed for NSH in ONF. The following
fields are defined:
NXOXM code ofctl name Size Comment
=====================================================================
NXOXM_NSH_FLAGS nsh_flags 8 Bits 2-9 of 1st NSH word
(0x005ad650,1)
NXOXM_NSH_MDTYPE nsh_mdtype 8 Bits 16-23
(0x005ad650,2)
NXOXM_NSH_NEXTPROTO nsh_np 8 Bits 24-31
(0x005ad650,3)
NXOXM_NSH_SPI nsh_spi 24 Bits 0-23 of 2nd NSH word
(0x005ad650,4)
NXOXM_NSH_SI nsh_si 8 Bits 24-31
(0x005ad650,5)
NXOXM_NSH_C1 nsh_c1 32 Maskable, nsh_mdtype==1
(0x005ad650,6)
NXOXM_NSH_C2 nsh_c2 32 Maskable, nsh_mdtype==1
(0x005ad650,7)
NXOXM_NSH_C3 nsh_c3 32 Maskable, nsh_mdtype==1
(0x005ad650,8)
NXOXM_NSH_C4 nsh_c4 32 Maskable, nsh_mdtype==1
(0x005ad650,9)
Co-authored-by: Johnson Li <johnson.li@intel.com>
Signed-off-by: Yi Yang <yi.y.yang@intel.com>
Signed-off-by: Jan Scheurich <jan.scheurich@ericsson.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-08-05 13:41:08 +08:00
|
|
|
|
nxm_put_8m(&ctx, MFF_NSH_MDTYPE, oxm, flow->nsh.mdtype,
|
|
|
|
|
match->wc.masks.nsh.mdtype);
|
|
|
|
|
nxm_put_8m(&ctx, MFF_NSH_NP, oxm, flow->nsh.np,
|
|
|
|
|
match->wc.masks.nsh.np);
|
2018-01-11 13:24:01 +08:00
|
|
|
|
spi_mask = nsh_path_hdr_to_spi(match->wc.masks.nsh.path_hdr);
|
|
|
|
|
if (spi_mask == htonl(NSH_SPI_MASK >> NSH_SPI_SHIFT)) {
|
|
|
|
|
spi_mask = OVS_BE32_MAX;
|
|
|
|
|
}
|
|
|
|
|
nxm_put_32m(&ctx, MFF_NSH_SPI, oxm,
|
|
|
|
|
nsh_path_hdr_to_spi(flow->nsh.path_hdr),
|
|
|
|
|
spi_mask);
|
|
|
|
|
nxm_put_8m(&ctx, MFF_NSH_SI, oxm,
|
|
|
|
|
nsh_path_hdr_to_si(flow->nsh.path_hdr),
|
|
|
|
|
nsh_path_hdr_to_si(match->wc.masks.nsh.path_hdr));
|
userspace: Add support for NSH MD1 match fields
This patch adds support for NSH packet header fields to the OVS
control plane and the userspace datapath. Initially we support the
fields of the NSH base header as defined in
https://www.ietf.org/id/draft-ietf-sfc-nsh-13.txt
and the fixed context headers specified for metadata format MD1.
The variable length MD2 format is parsed but the TLV context headers
are not yet available for matching.
The NSH fields are modelled as experimenter fields with the dedicated
experimenter class 0x005ad650 proposed for NSH in ONF. The following
fields are defined:
NXOXM code ofctl name Size Comment
=====================================================================
NXOXM_NSH_FLAGS nsh_flags 8 Bits 2-9 of 1st NSH word
(0x005ad650,1)
NXOXM_NSH_MDTYPE nsh_mdtype 8 Bits 16-23
(0x005ad650,2)
NXOXM_NSH_NEXTPROTO nsh_np 8 Bits 24-31
(0x005ad650,3)
NXOXM_NSH_SPI nsh_spi 24 Bits 0-23 of 2nd NSH word
(0x005ad650,4)
NXOXM_NSH_SI nsh_si 8 Bits 24-31
(0x005ad650,5)
NXOXM_NSH_C1 nsh_c1 32 Maskable, nsh_mdtype==1
(0x005ad650,6)
NXOXM_NSH_C2 nsh_c2 32 Maskable, nsh_mdtype==1
(0x005ad650,7)
NXOXM_NSH_C3 nsh_c3 32 Maskable, nsh_mdtype==1
(0x005ad650,8)
NXOXM_NSH_C4 nsh_c4 32 Maskable, nsh_mdtype==1
(0x005ad650,9)
Co-authored-by: Johnson Li <johnson.li@intel.com>
Signed-off-by: Yi Yang <yi.y.yang@intel.com>
Signed-off-by: Jan Scheurich <jan.scheurich@ericsson.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-08-05 13:41:08 +08:00
|
|
|
|
for (int i = 0; i < 4; i++) {
|
2018-01-06 13:47:51 +08:00
|
|
|
|
nxm_put_32m(&ctx, MFF_NSH_C1 + i, oxm, flow->nsh.context[i],
|
|
|
|
|
match->wc.masks.nsh.context[i]);
|
userspace: Add support for NSH MD1 match fields
This patch adds support for NSH packet header fields to the OVS
control plane and the userspace datapath. Initially we support the
fields of the NSH base header as defined in
https://www.ietf.org/id/draft-ietf-sfc-nsh-13.txt
and the fixed context headers specified for metadata format MD1.
The variable length MD2 format is parsed but the TLV context headers
are not yet available for matching.
The NSH fields are modelled as experimenter fields with the dedicated
experimenter class 0x005ad650 proposed for NSH in ONF. The following
fields are defined:
NXOXM code ofctl name Size Comment
=====================================================================
NXOXM_NSH_FLAGS nsh_flags 8 Bits 2-9 of 1st NSH word
(0x005ad650,1)
NXOXM_NSH_MDTYPE nsh_mdtype 8 Bits 16-23
(0x005ad650,2)
NXOXM_NSH_NEXTPROTO nsh_np 8 Bits 24-31
(0x005ad650,3)
NXOXM_NSH_SPI nsh_spi 24 Bits 0-23 of 2nd NSH word
(0x005ad650,4)
NXOXM_NSH_SI nsh_si 8 Bits 24-31
(0x005ad650,5)
NXOXM_NSH_C1 nsh_c1 32 Maskable, nsh_mdtype==1
(0x005ad650,6)
NXOXM_NSH_C2 nsh_c2 32 Maskable, nsh_mdtype==1
(0x005ad650,7)
NXOXM_NSH_C3 nsh_c3 32 Maskable, nsh_mdtype==1
(0x005ad650,8)
NXOXM_NSH_C4 nsh_c4 32 Maskable, nsh_mdtype==1
(0x005ad650,9)
Co-authored-by: Johnson Li <johnson.li@intel.com>
Signed-off-by: Yi Yang <yi.y.yang@intel.com>
Signed-off-by: Jan Scheurich <jan.scheurich@ericsson.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2017-08-05 13:41:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
2010-11-11 10:41:33 -08:00
|
|
|
|
/* Registers. */
|
2014-08-20 20:59:43 -07:00
|
|
|
|
if (oxm < OFP15_VERSION) {
|
2018-02-27 12:32:29 -08:00
|
|
|
|
for (int i = 0; i < FLOW_N_REGS; i++) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32m(&ctx, MFF_REG0 + i, oxm,
|
2014-08-20 20:59:43 -07:00
|
|
|
|
htonl(flow->regs[i]), htonl(match->wc.masks.regs[i]));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2018-02-27 12:32:29 -08:00
|
|
|
|
for (int i = 0; i < FLOW_N_XREGS; i++) {
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_64m(&ctx, MFF_XREG0 + i, oxm,
|
2014-08-20 20:59:43 -07:00
|
|
|
|
htonll(flow_get_xreg(flow, i)),
|
|
|
|
|
htonll(flow_get_xreg(&match->wc.masks, i)));
|
|
|
|
|
}
|
2010-11-11 10:41:33 -08:00
|
|
|
|
}
|
|
|
|
|
|
Add connection tracking mark support.
This patch adds a new 32-bit metadata field to the connection tracking
interface. When a mark is specified as part of the ct action and the
connection is committed, the value is saved with the current connection.
Subsequent ct lookups with the table specified will expose this metadata
as the "ct_mark" field in the flow.
For example, to allow new TCP connections from port 1->2 and only allow
established connections from port 2->1, and to associate a mark with those
connections:
table=0,priority=1,action=drop
table=0,arp,action=normal
table=0,in_port=1,tcp,action=ct(commit,exec(set_field:1->ct_mark)),2
table=0,in_port=2,ct_state=-trk,tcp,action=ct(table=1)
table=1,in_port=2,ct_state=+trk,ct_mark=1,tcp,action=1
Signed-off-by: Joe Stringer <joestringer@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-09-18 13:58:00 -07:00
|
|
|
|
/* Packet mark. */
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32m(&ctx, MFF_PKT_MARK, oxm, htonl(flow->pkt_mark),
|
2013-08-06 12:57:16 -07:00
|
|
|
|
htonl(match->wc.masks.pkt_mark));
|
|
|
|
|
|
Add support for connection tracking.
This patch adds a new action and fields to OVS that allow connection
tracking to be performed. This support works in conjunction with the
Linux kernel support merged into the Linux-4.3 development cycle.
Packets have two possible states with respect to connection tracking:
Untracked packets have not previously passed through the connection
tracker, while tracked packets have previously been through the
connection tracker. For OpenFlow pipeline processing, untracked packets
can become tracked, and they will remain tracked until the end of the
pipeline. Tracked packets cannot become untracked.
Connections can be unknown, uncommitted, or committed. Packets which are
untracked have unknown connection state. To know the connection state,
the packet must become tracked. Uncommitted connections have no
connection state stored about them, so it is only possible for the
connection tracker to identify whether they are a new connection or
whether they are invalid. Committed connections have connection state
stored beyond the lifetime of the packet, which allows later packets in
the same connection to be identified as part of the same established
connection, or related to an existing connection - for instance ICMP
error responses.
The new 'ct' action transitions the packet from "untracked" to
"tracked" by sending this flow through the connection tracker.
The following parameters are supported initally:
- "commit": When commit is executed, the connection moves from
uncommitted state to committed state. This signals that information
about the connection should be stored beyond the lifetime of the
packet within the pipeline. This allows future packets in the same
connection to be recognized as part of the same "established" (est)
connection, as well as identifying packets in the reply (rpl)
direction, or packets related to an existing connection (rel).
- "zone=[u16|NXM]": Perform connection tracking in the zone specified.
Each zone is an independent connection tracking context. When the
"commit" parameter is used, the connection will only be committed in
the specified zone, and not in other zones. This is 0 by default.
- "table=NUMBER": Fork pipeline processing in two. The original instance
of the packet will continue processing the current actions list as an
untracked packet. An additional instance of the packet will be sent to
the connection tracker, which will be re-injected into the OpenFlow
pipeline to resume processing in the specified table, with the
ct_state and other ct match fields set. If the table is not specified,
then the packet is submitted to the connection tracker, but the
pipeline does not fork and the ct match fields are not populated. It
is strongly recommended to specify a table later than the current
table to prevent loops.
When the "table" option is used, the packet that continues processing in
the specified table will have the ct_state populated. The ct_state may
have any of the following flags set:
- Tracked (trk): Connection tracking has occurred.
- Reply (rpl): The flow is in the reply direction.
- Invalid (inv): The connection tracker couldn't identify the connection.
- New (new): This is the beginning of a new connection.
- Established (est): This is part of an already existing connection.
- Related (rel): This connection is related to an existing connection.
For more information, consult the ovs-ofctl(8) man pages.
Below is a simple example flow table to allow outbound TCP traffic from
port 1 and drop traffic from port 2 that was not initiated by port 1:
table=0,priority=1,action=drop
table=0,arp,action=normal
table=0,in_port=1,tcp,ct_state=-trk,action=ct(commit,zone=9),2
table=0,in_port=2,tcp,ct_state=-trk,action=ct(zone=9,table=1)
table=1,in_port=2,ct_state=+trk+est,tcp,action=1
table=1,in_port=2,ct_state=+trk+new,tcp,action=drop
Based on original design by Justin Pettit, contributions from Thomas
Graf and Daniele Di Proietto.
Signed-off-by: Joe Stringer <joestringer@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-08-11 10:56:09 -07:00
|
|
|
|
/* Connection tracking. */
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32m(&ctx, MFF_CT_STATE, oxm, htonl(flow->ct_state),
|
Add support for connection tracking.
This patch adds a new action and fields to OVS that allow connection
tracking to be performed. This support works in conjunction with the
Linux kernel support merged into the Linux-4.3 development cycle.
Packets have two possible states with respect to connection tracking:
Untracked packets have not previously passed through the connection
tracker, while tracked packets have previously been through the
connection tracker. For OpenFlow pipeline processing, untracked packets
can become tracked, and they will remain tracked until the end of the
pipeline. Tracked packets cannot become untracked.
Connections can be unknown, uncommitted, or committed. Packets which are
untracked have unknown connection state. To know the connection state,
the packet must become tracked. Uncommitted connections have no
connection state stored about them, so it is only possible for the
connection tracker to identify whether they are a new connection or
whether they are invalid. Committed connections have connection state
stored beyond the lifetime of the packet, which allows later packets in
the same connection to be identified as part of the same established
connection, or related to an existing connection - for instance ICMP
error responses.
The new 'ct' action transitions the packet from "untracked" to
"tracked" by sending this flow through the connection tracker.
The following parameters are supported initally:
- "commit": When commit is executed, the connection moves from
uncommitted state to committed state. This signals that information
about the connection should be stored beyond the lifetime of the
packet within the pipeline. This allows future packets in the same
connection to be recognized as part of the same "established" (est)
connection, as well as identifying packets in the reply (rpl)
direction, or packets related to an existing connection (rel).
- "zone=[u16|NXM]": Perform connection tracking in the zone specified.
Each zone is an independent connection tracking context. When the
"commit" parameter is used, the connection will only be committed in
the specified zone, and not in other zones. This is 0 by default.
- "table=NUMBER": Fork pipeline processing in two. The original instance
of the packet will continue processing the current actions list as an
untracked packet. An additional instance of the packet will be sent to
the connection tracker, which will be re-injected into the OpenFlow
pipeline to resume processing in the specified table, with the
ct_state and other ct match fields set. If the table is not specified,
then the packet is submitted to the connection tracker, but the
pipeline does not fork and the ct match fields are not populated. It
is strongly recommended to specify a table later than the current
table to prevent loops.
When the "table" option is used, the packet that continues processing in
the specified table will have the ct_state populated. The ct_state may
have any of the following flags set:
- Tracked (trk): Connection tracking has occurred.
- Reply (rpl): The flow is in the reply direction.
- Invalid (inv): The connection tracker couldn't identify the connection.
- New (new): This is the beginning of a new connection.
- Established (est): This is part of an already existing connection.
- Related (rel): This connection is related to an existing connection.
For more information, consult the ovs-ofctl(8) man pages.
Below is a simple example flow table to allow outbound TCP traffic from
port 1 and drop traffic from port 2 that was not initiated by port 1:
table=0,priority=1,action=drop
table=0,arp,action=normal
table=0,in_port=1,tcp,ct_state=-trk,action=ct(commit,zone=9),2
table=0,in_port=2,tcp,ct_state=-trk,action=ct(zone=9,table=1)
table=1,in_port=2,ct_state=+trk+est,tcp,action=1
table=1,in_port=2,ct_state=+trk+new,tcp,action=drop
Based on original design by Justin Pettit, contributions from Thomas
Graf and Daniele Di Proietto.
Signed-off-by: Joe Stringer <joestringer@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-08-11 10:56:09 -07:00
|
|
|
|
htonl(match->wc.masks.ct_state));
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16m(&ctx, MFF_CT_ZONE, oxm, htons(flow->ct_zone),
|
Add support for connection tracking.
This patch adds a new action and fields to OVS that allow connection
tracking to be performed. This support works in conjunction with the
Linux kernel support merged into the Linux-4.3 development cycle.
Packets have two possible states with respect to connection tracking:
Untracked packets have not previously passed through the connection
tracker, while tracked packets have previously been through the
connection tracker. For OpenFlow pipeline processing, untracked packets
can become tracked, and they will remain tracked until the end of the
pipeline. Tracked packets cannot become untracked.
Connections can be unknown, uncommitted, or committed. Packets which are
untracked have unknown connection state. To know the connection state,
the packet must become tracked. Uncommitted connections have no
connection state stored about them, so it is only possible for the
connection tracker to identify whether they are a new connection or
whether they are invalid. Committed connections have connection state
stored beyond the lifetime of the packet, which allows later packets in
the same connection to be identified as part of the same established
connection, or related to an existing connection - for instance ICMP
error responses.
The new 'ct' action transitions the packet from "untracked" to
"tracked" by sending this flow through the connection tracker.
The following parameters are supported initally:
- "commit": When commit is executed, the connection moves from
uncommitted state to committed state. This signals that information
about the connection should be stored beyond the lifetime of the
packet within the pipeline. This allows future packets in the same
connection to be recognized as part of the same "established" (est)
connection, as well as identifying packets in the reply (rpl)
direction, or packets related to an existing connection (rel).
- "zone=[u16|NXM]": Perform connection tracking in the zone specified.
Each zone is an independent connection tracking context. When the
"commit" parameter is used, the connection will only be committed in
the specified zone, and not in other zones. This is 0 by default.
- "table=NUMBER": Fork pipeline processing in two. The original instance
of the packet will continue processing the current actions list as an
untracked packet. An additional instance of the packet will be sent to
the connection tracker, which will be re-injected into the OpenFlow
pipeline to resume processing in the specified table, with the
ct_state and other ct match fields set. If the table is not specified,
then the packet is submitted to the connection tracker, but the
pipeline does not fork and the ct match fields are not populated. It
is strongly recommended to specify a table later than the current
table to prevent loops.
When the "table" option is used, the packet that continues processing in
the specified table will have the ct_state populated. The ct_state may
have any of the following flags set:
- Tracked (trk): Connection tracking has occurred.
- Reply (rpl): The flow is in the reply direction.
- Invalid (inv): The connection tracker couldn't identify the connection.
- New (new): This is the beginning of a new connection.
- Established (est): This is part of an already existing connection.
- Related (rel): This connection is related to an existing connection.
For more information, consult the ovs-ofctl(8) man pages.
Below is a simple example flow table to allow outbound TCP traffic from
port 1 and drop traffic from port 2 that was not initiated by port 1:
table=0,priority=1,action=drop
table=0,arp,action=normal
table=0,in_port=1,tcp,ct_state=-trk,action=ct(commit,zone=9),2
table=0,in_port=2,tcp,ct_state=-trk,action=ct(zone=9,table=1)
table=1,in_port=2,ct_state=+trk+est,tcp,action=1
table=1,in_port=2,ct_state=+trk+new,tcp,action=drop
Based on original design by Justin Pettit, contributions from Thomas
Graf and Daniele Di Proietto.
Signed-off-by: Joe Stringer <joestringer@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-08-11 10:56:09 -07:00
|
|
|
|
htons(match->wc.masks.ct_zone));
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32m(&ctx, MFF_CT_MARK, oxm, htonl(flow->ct_mark),
|
Add connection tracking mark support.
This patch adds a new 32-bit metadata field to the connection tracking
interface. When a mark is specified as part of the ct action and the
connection is committed, the value is saved with the current connection.
Subsequent ct lookups with the table specified will expose this metadata
as the "ct_mark" field in the flow.
For example, to allow new TCP connections from port 1->2 and only allow
established connections from port 2->1, and to associate a mark with those
connections:
table=0,priority=1,action=drop
table=0,arp,action=normal
table=0,in_port=1,tcp,action=ct(commit,exec(set_field:1->ct_mark)),2
table=0,in_port=2,ct_state=-trk,tcp,action=ct(table=1)
table=1,in_port=2,ct_state=+trk,ct_mark=1,tcp,action=1
Signed-off-by: Joe Stringer <joestringer@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-09-18 13:58:00 -07:00
|
|
|
|
htonl(match->wc.masks.ct_mark));
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_128m(&ctx, MFF_CT_LABEL, oxm, hton128(flow->ct_label),
|
2015-10-31 04:28:00 -07:00
|
|
|
|
hton128(match->wc.masks.ct_label));
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32m(&ctx, MFF_CT_NW_SRC, oxm,
|
2017-03-08 17:18:23 -08:00
|
|
|
|
flow->ct_nw_src, match->wc.masks.ct_nw_src);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_ipv6(&ctx, MFF_CT_IPV6_SRC, oxm,
|
2017-03-08 17:18:23 -08:00
|
|
|
|
&flow->ct_ipv6_src, &match->wc.masks.ct_ipv6_src);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_32m(&ctx, MFF_CT_NW_DST, oxm,
|
2017-03-08 17:18:23 -08:00
|
|
|
|
flow->ct_nw_dst, match->wc.masks.ct_nw_dst);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_ipv6(&ctx, MFF_CT_IPV6_DST, oxm,
|
2017-03-08 17:18:23 -08:00
|
|
|
|
&flow->ct_ipv6_dst, &match->wc.masks.ct_ipv6_dst);
|
|
|
|
|
if (flow->ct_nw_proto) {
|
2017-07-12 15:43:45 -07:00
|
|
|
|
nxm_put_8m(&ctx, MFF_CT_NW_PROTO, oxm, flow->ct_nw_proto,
|
|
|
|
|
match->wc.masks.ct_nw_proto);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16m(&ctx, MFF_CT_TP_SRC, oxm,
|
2017-03-08 17:18:23 -08:00
|
|
|
|
flow->ct_tp_src, match->wc.masks.ct_tp_src);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_16m(&ctx, MFF_CT_TP_DST, oxm,
|
2017-03-08 17:18:23 -08:00
|
|
|
|
flow->ct_tp_dst, match->wc.masks.ct_tp_dst);
|
|
|
|
|
}
|
2012-06-27 01:09:44 +12:00
|
|
|
|
/* OpenFlow 1.1+ Metadata. */
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_64m(&ctx, MFF_METADATA, oxm,
|
2014-05-09 18:18:17 -07:00
|
|
|
|
flow->metadata, match->wc.masks.metadata);
|
2012-06-27 01:09:44 +12:00
|
|
|
|
|
2011-12-23 12:23:24 -08:00
|
|
|
|
/* Cookie. */
|
2014-09-30 17:26:28 -07:00
|
|
|
|
if (cookie_mask) {
|
|
|
|
|
bool masked = cookie_mask != OVS_BE64_MAX;
|
|
|
|
|
|
|
|
|
|
cookie &= cookie_mask;
|
|
|
|
|
nx_put_header__(b, NXM_NX_COOKIE, masked);
|
|
|
|
|
ofpbuf_put(b, &cookie, sizeof cookie);
|
|
|
|
|
if (masked) {
|
|
|
|
|
ofpbuf_put(b, &cookie_mask, sizeof cookie_mask);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-12-23 12:23:24 -08:00
|
|
|
|
|
2017-06-23 16:47:57 +00:00
|
|
|
|
if (match_has_default_packet_type(match) && !ctx.implied_ethernet) {
|
|
|
|
|
uint64_t pt_stub[16 / 8];
|
|
|
|
|
struct ofpbuf pt;
|
|
|
|
|
ofpbuf_use_stack(&pt, pt_stub, sizeof pt_stub);
|
|
|
|
|
nxm_put_entry_raw(&pt, MFF_PACKET_TYPE, oxm, &flow->packet_type,
|
|
|
|
|
NULL, sizeof flow->packet_type);
|
|
|
|
|
|
|
|
|
|
ofpbuf_insert(b, start_len, pt.data, pt.size);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 17:29:44 -08:00
|
|
|
|
match_len = b->size - start_len;
|
2012-08-01 16:01:45 +09:00
|
|
|
|
return match_len;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-07 15:28:18 -07:00
|
|
|
|
/* Appends to 'b' the nx_match format that expresses 'match', plus enough zero
|
2012-08-01 16:01:45 +09:00
|
|
|
|
* bytes to pad the nx_match out to a multiple of 8. For Flow Mod and Flow
|
|
|
|
|
* Stats Requests messages, a 'cookie' and 'cookie_mask' may be supplied.
|
|
|
|
|
* Otherwise, 'cookie_mask' should be zero.
|
|
|
|
|
*
|
|
|
|
|
* This function can cause 'b''s data to be reallocated.
|
|
|
|
|
*
|
|
|
|
|
* Returns the number of bytes appended to 'b', excluding padding. The return
|
|
|
|
|
* value can be zero if it appended nothing at all to 'b' (which happens if
|
|
|
|
|
* 'cr' is a catch-all rule that matches every packet). */
|
|
|
|
|
int
|
2012-08-07 15:28:18 -07:00
|
|
|
|
nx_put_match(struct ofpbuf *b, const struct match *match,
|
2012-08-01 16:01:45 +09:00
|
|
|
|
ovs_be64 cookie, ovs_be64 cookie_mask)
|
|
|
|
|
{
|
2014-05-09 18:18:17 -07:00
|
|
|
|
int match_len = nx_put_raw(b, 0, match, cookie, cookie_mask);
|
2012-08-01 16:01:45 +09:00
|
|
|
|
|
2014-03-10 23:50:54 -07:00
|
|
|
|
ofpbuf_put_zeros(b, PAD_SIZE(match_len, 8));
|
2012-08-01 16:01:45 +09:00
|
|
|
|
return match_len;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-09 18:18:17 -07:00
|
|
|
|
/* Appends to 'b' an struct ofp11_match_header followed by the OXM format that
|
2016-01-18 14:55:30 -08:00
|
|
|
|
* expresses 'match', plus enough zero bytes to pad the data appended out to a
|
2012-08-07 15:28:18 -07:00
|
|
|
|
* multiple of 8.
|
2012-08-01 16:01:45 +09:00
|
|
|
|
*
|
2014-05-09 18:18:17 -07:00
|
|
|
|
* OXM differs slightly among versions of OpenFlow. Specify the OpenFlow
|
|
|
|
|
* version in use as 'version'.
|
|
|
|
|
*
|
2012-08-01 16:01:45 +09:00
|
|
|
|
* This function can cause 'b''s data to be reallocated.
|
|
|
|
|
*
|
|
|
|
|
* Returns the number of bytes appended to 'b', excluding the padding. Never
|
|
|
|
|
* returns zero. */
|
|
|
|
|
int
|
2014-05-09 18:18:17 -07:00
|
|
|
|
oxm_put_match(struct ofpbuf *b, const struct match *match,
|
|
|
|
|
enum ofp_version version)
|
2012-08-01 16:01:45 +09:00
|
|
|
|
{
|
|
|
|
|
int match_len;
|
|
|
|
|
struct ofp11_match_header *omh;
|
2015-03-02 17:29:44 -08:00
|
|
|
|
size_t start_len = b->size;
|
2012-08-01 16:01:45 +09:00
|
|
|
|
ovs_be64 cookie = htonll(0), cookie_mask = htonll(0);
|
|
|
|
|
|
|
|
|
|
ofpbuf_put_uninit(b, sizeof *omh);
|
2014-05-09 18:18:17 -07:00
|
|
|
|
match_len = (nx_put_raw(b, version, match, cookie, cookie_mask)
|
|
|
|
|
+ sizeof *omh);
|
2014-03-10 23:50:54 -07:00
|
|
|
|
ofpbuf_put_zeros(b, PAD_SIZE(match_len, 8));
|
2012-08-01 16:01:45 +09:00
|
|
|
|
|
2013-07-22 15:47:19 -07:00
|
|
|
|
omh = ofpbuf_at(b, start_len, sizeof *omh);
|
2012-08-01 16:01:45 +09:00
|
|
|
|
omh->type = htons(OFPMT_OXM);
|
|
|
|
|
omh->length = htons(match_len);
|
|
|
|
|
|
2010-11-09 17:00:59 -08:00
|
|
|
|
return match_len;
|
|
|
|
|
}
|
2014-09-16 22:13:44 -07:00
|
|
|
|
|
2016-01-18 14:55:30 -08:00
|
|
|
|
/* Appends to 'b' the OXM formats that expresses 'match', without header or
|
|
|
|
|
* padding.
|
|
|
|
|
*
|
|
|
|
|
* OXM differs slightly among versions of OpenFlow. Specify the OpenFlow
|
|
|
|
|
* version in use as 'version'.
|
|
|
|
|
*
|
|
|
|
|
* This function can cause 'b''s data to be reallocated. */
|
|
|
|
|
void
|
|
|
|
|
oxm_put_raw(struct ofpbuf *b, const struct match *match,
|
|
|
|
|
enum ofp_version version)
|
|
|
|
|
{
|
|
|
|
|
nx_put_raw(b, version, match, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-20 13:50:31 +09:00
|
|
|
|
/* Appends to 'b' the nx_match format that expresses the tlv corresponding
|
|
|
|
|
* to 'id'. If mask is not all-ones then it is also formated as the value
|
|
|
|
|
* of the tlv. */
|
|
|
|
|
static void
|
|
|
|
|
nx_format_mask_tlv(struct ds *ds, enum mf_field_id id,
|
|
|
|
|
const union mf_value *mask)
|
|
|
|
|
{
|
|
|
|
|
const struct mf_field *mf = mf_from_id(id);
|
|
|
|
|
|
|
|
|
|
ds_put_format(ds, "%s", mf->name);
|
|
|
|
|
|
|
|
|
|
if (!is_all_ones(mask, mf->n_bytes)) {
|
|
|
|
|
ds_put_char(ds, '=');
|
2017-05-31 16:06:12 -07:00
|
|
|
|
mf_format(mf, mask, NULL, NULL, ds);
|
2015-03-20 13:50:31 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_char(ds, ',');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Appends a string representation of 'fa_' to 'ds'.
|
|
|
|
|
* The TLVS value of 'fa_' is treated as a mask and
|
|
|
|
|
* only the name of fields is formated if it is all ones. */
|
|
|
|
|
void
|
|
|
|
|
oxm_format_field_array(struct ds *ds, const struct field_array *fa)
|
|
|
|
|
{
|
|
|
|
|
size_t start_len = ds->length;
|
2016-07-29 16:52:04 -07:00
|
|
|
|
size_t i, offset = 0;
|
2015-03-20 13:50:31 +09:00
|
|
|
|
|
2016-07-29 16:52:04 -07:00
|
|
|
|
BITMAP_FOR_EACH_1 (i, MFF_N_IDS, fa->used.bm) {
|
|
|
|
|
const struct mf_field *mf = mf_from_id(i);
|
|
|
|
|
union mf_value value;
|
|
|
|
|
|
|
|
|
|
memcpy(&value, fa->values + offset, mf->n_bytes);
|
|
|
|
|
nx_format_mask_tlv(ds, i, &value);
|
|
|
|
|
offset += mf->n_bytes;
|
2015-03-20 13:50:31 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ds->length > start_len) {
|
|
|
|
|
ds_chomp(ds, ',');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Appends to 'b' a series of OXM TLVs corresponding to the series
|
|
|
|
|
* of enum mf_field_id and value tuples in 'fa_'.
|
|
|
|
|
*
|
|
|
|
|
* OXM differs slightly among versions of OpenFlow. Specify the OpenFlow
|
|
|
|
|
* version in use as 'version'.
|
|
|
|
|
*
|
|
|
|
|
* This function can cause 'b''s data to be reallocated.
|
|
|
|
|
*
|
|
|
|
|
* Returns the number of bytes appended to 'b'. May return zero. */
|
|
|
|
|
int
|
|
|
|
|
oxm_put_field_array(struct ofpbuf *b, const struct field_array *fa,
|
|
|
|
|
enum ofp_version version)
|
|
|
|
|
{
|
|
|
|
|
size_t start_len = b->size;
|
|
|
|
|
|
2018-05-09 17:03:56 -07:00
|
|
|
|
/* XXX Some care might need to be taken of different TLVs that handle the
|
|
|
|
|
* same flow fields. In particular:
|
|
|
|
|
|
2015-03-20 13:50:31 +09:00
|
|
|
|
* - VLAN_TCI, VLAN_VID and MFF_VLAN_PCP
|
|
|
|
|
* - IP_DSCP_MASK and DSCP_SHIFTED
|
|
|
|
|
* - REGS and XREGS
|
|
|
|
|
*/
|
|
|
|
|
|
2016-07-29 16:52:04 -07:00
|
|
|
|
size_t i, offset = 0;
|
|
|
|
|
|
|
|
|
|
BITMAP_FOR_EACH_1 (i, MFF_N_IDS, fa->used.bm) {
|
|
|
|
|
const struct mf_field *mf = mf_from_id(i);
|
|
|
|
|
union mf_value value;
|
|
|
|
|
|
|
|
|
|
memcpy(&value, fa->values + offset, mf->n_bytes);
|
|
|
|
|
|
|
|
|
|
int len = mf_field_len(mf, &value, NULL, NULL);
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_entry_raw(b, i, version,
|
|
|
|
|
&value + mf->n_bytes - len, NULL, len);
|
2016-07-29 16:52:04 -07:00
|
|
|
|
offset += mf->n_bytes;
|
2015-03-20 13:50:31 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return b->size - start_len;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-30 17:26:28 -07:00
|
|
|
|
static void
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
nx_put_header__(struct ofpbuf *b, uint64_t header, bool masked)
|
2014-09-30 17:26:28 -07:00
|
|
|
|
{
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
uint64_t masked_header = masked ? nxm_make_wild_header(header) : header;
|
|
|
|
|
ovs_be64 network_header = htonll(masked_header);
|
2014-09-30 17:26:28 -07:00
|
|
|
|
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
ofpbuf_put(b, &network_header, nxm_header_len(header));
|
2014-09-30 17:26:28 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
void
|
|
|
|
|
nx_put_header(struct ofpbuf *b, enum mf_field_id field,
|
|
|
|
|
enum ofp_version version, bool masked)
|
|
|
|
|
{
|
2014-09-30 17:26:28 -07:00
|
|
|
|
nx_put_header__(b, mf_oxm_header(field, version), masked);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
}
|
|
|
|
|
|
ofp-actions: Fix variable length meta-flow OXMs.
Previously, if a flow action that involves a tunnel metadata meta-flow
field is dumped from vswitchd, the replied field length in the OXM header
is filled with the maximum possible field length, instead of the length
configured in the tunnel TLV mapping table. To solve this issue, this patch
introduces the following changes.
In order to maintain the correct length of variable length mf_fields (i.e.
tun_metadata), this patch creates a per-switch based map (struct vl_mff_map)
that hosts the variable length mf_fields. This map is updated when a
controller adds/deletes tlv-mapping entries to/from a switch. Although the
per-swtch based vl_mff_map only hosts tun_metadata for now, it is able to
support new variable length mf_fields in the future.
With this commit, when a switch decodes a flow action with mf_field, the switch
firstly looks up the global mf_fields map to identify the mf_field type. For
the variable length mf_fields, the switch uses the vl_mff_map to get the
configured mf_field entries. By lookig up vl_mff_map, the switch can check
if the added flow action access beyond the configured size of a variable
length mf_field, and the switch reports an ofperr if the controller adds a flow
with unmapped variable length mf_field. Later on, when a controller request
flows from the switch, with the per-switch based mf_fields, the switch will
encode the OXM header with correct length for variable length mf_fields.
To use the vl_mff_map for decoding flow actions, extract-ofp-actions is
updated to pass the vl_mff_map to the required action decoding functions.
Also, a new error code is introduced to identify a flow with an invalid
variable length mf_field. Moreover, a testcase is added to prevent future
regressions.
Committer notes:
- Factor out common code
- Style fixups
- Rename OFPERR_NXFMFC_INVALID_VL_MFF -> OFPERR_NXFMFC_INVALID_TLV_FIELD
VMWare-BZ: #1768370
Reported-by: Harold Lim <haroldl@vmware.com>
Suggested-by: Joe Stringer <joe@ovn.org>
Suggested-by: Jarno Rajahalme <jarno@ovn.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Joe Stringer <joe@ovn.org>
2017-01-20 15:12:21 -08:00
|
|
|
|
void nx_put_mff_header(struct ofpbuf *b, const struct mf_field *mff,
|
|
|
|
|
enum ofp_version version, bool masked)
|
|
|
|
|
{
|
|
|
|
|
if (mff->mapped) {
|
|
|
|
|
nx_put_header_len(b, mff->id, version, masked, mff->n_bytes);
|
|
|
|
|
} else {
|
|
|
|
|
nx_put_header(b, mff->id, version, masked);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-06 18:04:11 -07:00
|
|
|
|
static void
|
|
|
|
|
nx_put_header_len(struct ofpbuf *b, enum mf_field_id field,
|
|
|
|
|
enum ofp_version version, bool masked, size_t n_bytes)
|
|
|
|
|
{
|
|
|
|
|
uint64_t header = mf_oxm_header(field, version);
|
|
|
|
|
|
|
|
|
|
header = NXM_HEADER(nxm_vendor(header), nxm_class(header),
|
|
|
|
|
nxm_field(header), false,
|
|
|
|
|
nxm_experimenter_len(header) + n_bytes);
|
|
|
|
|
|
|
|
|
|
nx_put_header__(b, header, masked);
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
void
|
ofp-actions: Fix variable length meta-flow OXMs.
Previously, if a flow action that involves a tunnel metadata meta-flow
field is dumped from vswitchd, the replied field length in the OXM header
is filled with the maximum possible field length, instead of the length
configured in the tunnel TLV mapping table. To solve this issue, this patch
introduces the following changes.
In order to maintain the correct length of variable length mf_fields (i.e.
tun_metadata), this patch creates a per-switch based map (struct vl_mff_map)
that hosts the variable length mf_fields. This map is updated when a
controller adds/deletes tlv-mapping entries to/from a switch. Although the
per-swtch based vl_mff_map only hosts tun_metadata for now, it is able to
support new variable length mf_fields in the future.
With this commit, when a switch decodes a flow action with mf_field, the switch
firstly looks up the global mf_fields map to identify the mf_field type. For
the variable length mf_fields, the switch uses the vl_mff_map to get the
configured mf_field entries. By lookig up vl_mff_map, the switch can check
if the added flow action access beyond the configured size of a variable
length mf_field, and the switch reports an ofperr if the controller adds a flow
with unmapped variable length mf_field. Later on, when a controller request
flows from the switch, with the per-switch based mf_fields, the switch will
encode the OXM header with correct length for variable length mf_fields.
To use the vl_mff_map for decoding flow actions, extract-ofp-actions is
updated to pass the vl_mff_map to the required action decoding functions.
Also, a new error code is introduced to identify a flow with an invalid
variable length mf_field. Moreover, a testcase is added to prevent future
regressions.
Committer notes:
- Factor out common code
- Style fixups
- Rename OFPERR_NXFMFC_INVALID_VL_MFF -> OFPERR_NXFMFC_INVALID_TLV_FIELD
VMWare-BZ: #1768370
Reported-by: Harold Lim <haroldl@vmware.com>
Suggested-by: Joe Stringer <joe@ovn.org>
Suggested-by: Jarno Rajahalme <jarno@ovn.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Joe Stringer <joe@ovn.org>
2017-01-20 15:12:21 -08:00
|
|
|
|
nx_put_entry(struct ofpbuf *b, const struct mf_field *mff,
|
|
|
|
|
enum ofp_version version, const union mf_value *value,
|
|
|
|
|
const union mf_value *mask)
|
2014-09-16 22:13:44 -07:00
|
|
|
|
{
|
2015-08-11 18:41:37 -07:00
|
|
|
|
bool masked;
|
2015-05-06 18:05:18 -07:00
|
|
|
|
int len, offset;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
|
ofp-actions: Fix variable length meta-flow OXMs.
Previously, if a flow action that involves a tunnel metadata meta-flow
field is dumped from vswitchd, the replied field length in the OXM header
is filled with the maximum possible field length, instead of the length
configured in the tunnel TLV mapping table. To solve this issue, this patch
introduces the following changes.
In order to maintain the correct length of variable length mf_fields (i.e.
tun_metadata), this patch creates a per-switch based map (struct vl_mff_map)
that hosts the variable length mf_fields. This map is updated when a
controller adds/deletes tlv-mapping entries to/from a switch. Although the
per-swtch based vl_mff_map only hosts tun_metadata for now, it is able to
support new variable length mf_fields in the future.
With this commit, when a switch decodes a flow action with mf_field, the switch
firstly looks up the global mf_fields map to identify the mf_field type. For
the variable length mf_fields, the switch uses the vl_mff_map to get the
configured mf_field entries. By lookig up vl_mff_map, the switch can check
if the added flow action access beyond the configured size of a variable
length mf_field, and the switch reports an ofperr if the controller adds a flow
with unmapped variable length mf_field. Later on, when a controller request
flows from the switch, with the per-switch based mf_fields, the switch will
encode the OXM header with correct length for variable length mf_fields.
To use the vl_mff_map for decoding flow actions, extract-ofp-actions is
updated to pass the vl_mff_map to the required action decoding functions.
Also, a new error code is introduced to identify a flow with an invalid
variable length mf_field. Moreover, a testcase is added to prevent future
regressions.
Committer notes:
- Factor out common code
- Style fixups
- Rename OFPERR_NXFMFC_INVALID_VL_MFF -> OFPERR_NXFMFC_INVALID_TLV_FIELD
VMWare-BZ: #1768370
Reported-by: Harold Lim <haroldl@vmware.com>
Suggested-by: Joe Stringer <joe@ovn.org>
Suggested-by: Jarno Rajahalme <jarno@ovn.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Joe Stringer <joe@ovn.org>
2017-01-20 15:12:21 -08:00
|
|
|
|
len = mf_field_len(mff, value, mask, &masked);
|
|
|
|
|
offset = mff->n_bytes - len;
|
2015-05-06 18:05:18 -07:00
|
|
|
|
|
2017-06-23 16:47:54 +00:00
|
|
|
|
nxm_put_entry_raw(b, mff->id, version,
|
|
|
|
|
&value->u8 + offset, masked ? &mask->u8 + offset : NULL,
|
|
|
|
|
len);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
}
|
2010-11-09 17:00:59 -08:00
|
|
|
|
|
|
|
|
|
/* nx_match_to_string() and helpers. */
|
|
|
|
|
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
static void format_nxm_field_name(struct ds *, uint64_t header);
|
2010-12-09 11:03:35 -08:00
|
|
|
|
|
2010-11-09 17:00:59 -08:00
|
|
|
|
char *
|
|
|
|
|
nx_match_to_string(const uint8_t *p, unsigned int match_len)
|
|
|
|
|
{
|
|
|
|
|
if (!match_len) {
|
|
|
|
|
return xstrdup("<any>");
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(p, match_len);
|
|
|
|
|
struct ds s = DS_EMPTY_INITIALIZER;
|
2015-03-02 17:29:44 -08:00
|
|
|
|
while (b.size) {
|
2014-09-16 22:13:44 -07:00
|
|
|
|
union mf_value value;
|
|
|
|
|
union mf_value mask;
|
|
|
|
|
enum ofperr error;
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
uint64_t header;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
int value_len;
|
|
|
|
|
|
2019-01-16 16:53:52 -08:00
|
|
|
|
error = nx_pull_entry__(&b, true, NULL, &header, NULL, &value, &mask, false);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
if (error) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
value_len = MIN(sizeof value, nxm_field_bytes(header));
|
2010-11-09 17:00:59 -08:00
|
|
|
|
|
|
|
|
|
if (s.length) {
|
|
|
|
|
ds_put_cstr(&s, ", ");
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-09 11:03:35 -08:00
|
|
|
|
format_nxm_field_name(&s, header);
|
2010-11-09 17:00:59 -08:00
|
|
|
|
ds_put_char(&s, '(');
|
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
for (int i = 0; i < value_len; i++) {
|
|
|
|
|
ds_put_format(&s, "%02x", ((const uint8_t *) &value)[i]);
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
2014-09-16 22:13:44 -07:00
|
|
|
|
if (nxm_hasmask(header)) {
|
2010-11-09 17:00:59 -08:00
|
|
|
|
ds_put_char(&s, '/');
|
2014-09-16 22:13:44 -07:00
|
|
|
|
for (int i = 0; i < value_len; i++) {
|
|
|
|
|
ds_put_format(&s, "%02x", ((const uint8_t *) &mask)[i]);
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ds_put_char(&s, ')');
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 17:29:44 -08:00
|
|
|
|
if (b.size) {
|
2010-11-09 17:00:59 -08:00
|
|
|
|
if (s.length) {
|
|
|
|
|
ds_put_cstr(&s, ", ");
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 17:29:44 -08:00
|
|
|
|
ds_put_format(&s, "<%u invalid bytes>", b.size);
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ds_steal_cstr(&s);
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-01 16:01:45 +09:00
|
|
|
|
char *
|
2013-07-22 15:47:19 -07:00
|
|
|
|
oxm_match_to_string(const struct ofpbuf *p, unsigned int match_len)
|
2012-08-01 16:01:45 +09:00
|
|
|
|
{
|
2015-03-02 17:29:44 -08:00
|
|
|
|
const struct ofp11_match_header *omh = p->data;
|
2012-08-01 16:01:45 +09:00
|
|
|
|
uint16_t match_len_;
|
|
|
|
|
struct ds s;
|
|
|
|
|
|
|
|
|
|
ds_init(&s);
|
|
|
|
|
|
|
|
|
|
if (match_len < sizeof *omh) {
|
|
|
|
|
ds_put_format(&s, "<match too short: %u>", match_len);
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (omh->type != htons(OFPMT_OXM)) {
|
|
|
|
|
ds_put_format(&s, "<bad match type field: %u>", ntohs(omh->type));
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
match_len_ = ntohs(omh->length);
|
|
|
|
|
if (match_len_ < sizeof *omh) {
|
|
|
|
|
ds_put_format(&s, "<match length field too short: %u>", match_len_);
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (match_len_ != match_len) {
|
|
|
|
|
ds_put_format(&s, "<match length field incorrect: %u != %u>",
|
|
|
|
|
match_len_, match_len);
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-22 15:47:19 -07:00
|
|
|
|
return nx_match_to_string(ofpbuf_at(p, sizeof *omh, 0),
|
|
|
|
|
match_len - sizeof *omh);
|
2012-08-01 16:01:45 +09:00
|
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
return ds_steal_cstr(&s);
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
void
|
|
|
|
|
nx_format_field_name(enum mf_field_id id, enum ofp_version version,
|
|
|
|
|
struct ds *s)
|
|
|
|
|
{
|
|
|
|
|
format_nxm_field_name(s, mf_oxm_header(id, version));
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-09 11:03:35 -08:00
|
|
|
|
static void
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
format_nxm_field_name(struct ds *s, uint64_t header)
|
2010-12-09 11:03:35 -08:00
|
|
|
|
{
|
2019-01-16 16:53:52 -08:00
|
|
|
|
const struct nxm_field *f = nxm_field_by_header(header, false, NULL);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
if (f) {
|
|
|
|
|
ds_put_cstr(s, f->name);
|
|
|
|
|
if (nxm_hasmask(header)) {
|
2011-10-12 17:04:13 -07:00
|
|
|
|
ds_put_cstr(s, "_W");
|
|
|
|
|
}
|
2011-12-23 12:23:24 -08:00
|
|
|
|
} else if (header == NXM_NX_COOKIE) {
|
|
|
|
|
ds_put_cstr(s, "NXM_NX_COOKIE");
|
|
|
|
|
} else if (header == NXM_NX_COOKIE_W) {
|
|
|
|
|
ds_put_cstr(s, "NXM_NX_COOKIE_W");
|
2010-12-09 11:03:35 -08:00
|
|
|
|
} else {
|
2014-09-10 11:15:20 -07:00
|
|
|
|
ds_put_format(s, "%d:%d", nxm_class(header), nxm_field(header));
|
2010-12-09 11:03:35 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
static bool
|
|
|
|
|
streq_len(const char *a, size_t a_len, const char *b)
|
|
|
|
|
{
|
|
|
|
|
return strlen(b) == a_len && !memcmp(a, b, a_len);
|
|
|
|
|
}
|
|
|
|
|
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
static uint64_t
|
2010-12-07 11:04:15 -08:00
|
|
|
|
parse_nxm_field_name(const char *name, int name_len)
|
2010-11-09 17:00:59 -08:00
|
|
|
|
{
|
2014-09-16 22:13:44 -07:00
|
|
|
|
const struct nxm_field *f;
|
2011-10-12 17:04:13 -07:00
|
|
|
|
bool wild;
|
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
f = mf_parse_subfield_name(name, name_len, &wild);
|
|
|
|
|
if (f) {
|
2012-06-11 09:56:12 -07:00
|
|
|
|
if (!wild) {
|
2014-09-16 22:13:44 -07:00
|
|
|
|
return f->header;
|
|
|
|
|
} else if (mf_from_id(f->id)->maskable != MFM_NONE) {
|
|
|
|
|
return nxm_make_wild_header(f->header);
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
if (streq_len(name, name_len, "NXM_NX_COOKIE")) {
|
|
|
|
|
return NXM_NX_COOKIE;
|
|
|
|
|
} else if (streq_len(name, name_len, "NXM_NX_COOKIE_W")) {
|
|
|
|
|
return NXM_NX_COOKIE_W;
|
2011-12-23 12:23:24 -08:00
|
|
|
|
}
|
|
|
|
|
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
/* Check whether it's a field header value as hex.
|
2010-12-07 11:04:15 -08:00
|
|
|
|
* (This isn't ordinarily useful except for testing error behavior.) */
|
|
|
|
|
if (name_len == 8) {
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
uint64_t header;
|
2014-09-30 12:45:50 -07:00
|
|
|
|
bool ok;
|
|
|
|
|
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
header = hexits_value(name, name_len, &ok) << 32;
|
2014-09-30 12:45:50 -07:00
|
|
|
|
if (ok) {
|
2010-12-07 11:04:15 -08:00
|
|
|
|
return header;
|
|
|
|
|
}
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
} else if (name_len == 16) {
|
|
|
|
|
uint64_t header;
|
|
|
|
|
bool ok;
|
|
|
|
|
|
|
|
|
|
header = hexits_value(name, name_len, &ok);
|
|
|
|
|
if (ok && is_experimenter_oxm(header)) {
|
|
|
|
|
return header;
|
|
|
|
|
}
|
2010-12-07 11:04:15 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* nx_match_from_string(). */
|
|
|
|
|
|
2012-08-01 16:01:45 +09:00
|
|
|
|
static int
|
|
|
|
|
nx_match_from_string_raw(const char *s, struct ofpbuf *b)
|
2010-11-09 17:00:59 -08:00
|
|
|
|
{
|
|
|
|
|
const char *full_s = s;
|
2015-03-02 17:29:44 -08:00
|
|
|
|
const size_t start_len = b->size;
|
2010-11-09 17:00:59 -08:00
|
|
|
|
|
|
|
|
|
if (!strcmp(s, "<any>")) {
|
2015-03-02 17:29:44 -08:00
|
|
|
|
/* Ensure that 'b->data' isn't actually null. */
|
2010-11-09 17:00:59 -08:00
|
|
|
|
ofpbuf_prealloc_tailroom(b, 1);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (s += strspn(s, ", "); *s; s += strspn(s, ", ")) {
|
2010-12-07 11:04:15 -08:00
|
|
|
|
const char *name;
|
nx-match: Add support for experimenter OXM.
OpenFlow 1.2+ defines a means for vendors to define vendor-specific OXM
fields, called "experimenter OXM". These OXM fields are expressed with a
64-bit OXM header instead of the 32-bit header used for standard OXM (and
NXM). Until now, OVS has not implemented experimenter OXM, and indeed we
have had little need to do so because of a pair of special 32-bit OXM classes
grandfathered to OVS as part of the OpenFlow 1.2 standardization process.
However, I want to prototype a feature for OpenFlow 1.5 that uses an
experimenter OXM as part of the prototype, so to do this OVS needs to
support experimenter OXM. This commit adds that support.
Most of this commit is a fairly straightforward change: it extends the type
used for OXM/NXM from 32 to 64 bits and adds code to encode and decode the
longer headers when necessary. Some other changes are necessary because
experimenter OXMs have a funny idea of the division between "header" and
"body": the extra 32 bits for experimenter OXMs are counted as part of the body
rather than the header according to the OpenFlow standard (even though this
does not entirely make sense), so arithmetic in various places has to be
adjusted, which is the reason for the new functions nxm_experimenter_len(),
nxm_payload_len(), and nxm_header_len().
Another change that calls for explanation is the new function mf_nxm_header()
that has been split from mf_oxm_header(). This function is used in actions
where the space for an NXM or OXM header is fixed so that there is no room
for a 64-bit experimenter type. An upcoming commit will add new variations
of these actions that can support experimenter OXM.
Testing experimenter OXM is tricky because I do not know of any in
widespread use. Two ONF proposals use experimenter OXMs: EXT-256 and
EXT-233. EXT-256 is not suitable to implement for testing because its use
of experimenter OXM is wrong and will be changed. EXT-233 is not suitable
to implement for testing because it requires adding a new field to struct
flow and I am not yet convinced that that field and the feature that it
supports is worth having in Open vSwitch. Thus, this commit assigns an
experimenter OXM code point to an existing OVS field that is currently
restricted from use by controllers, "dp_hash", and uses that for testing.
Because controllers cannot use it, this leaves future versions of OVS free
to drop the support for the experimenter OXM for this field without causing
backward compatibility problems.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
2014-10-08 15:41:00 -07:00
|
|
|
|
uint64_t header;
|
2015-05-07 20:11:57 -07:00
|
|
|
|
ovs_be64 nw_header;
|
2010-11-09 17:00:59 -08:00
|
|
|
|
int name_len;
|
2010-12-08 13:09:59 -08:00
|
|
|
|
size_t n;
|
2010-11-09 17:00:59 -08:00
|
|
|
|
|
2010-12-07 11:04:15 -08:00
|
|
|
|
name = s;
|
2010-11-09 17:00:59 -08:00
|
|
|
|
name_len = strcspn(s, "(");
|
|
|
|
|
if (s[name_len] != '(') {
|
|
|
|
|
ovs_fatal(0, "%s: missing ( at end of nx_match", full_s);
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-07 11:04:15 -08:00
|
|
|
|
header = parse_nxm_field_name(name, name_len);
|
|
|
|
|
if (!header) {
|
2010-11-09 17:00:59 -08:00
|
|
|
|
ovs_fatal(0, "%s: unknown field `%.*s'", full_s, name_len, s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s += name_len + 1;
|
|
|
|
|
|
2016-03-07 11:31:02 -08:00
|
|
|
|
b->header = ofpbuf_put_uninit(b, nxm_header_len(header));
|
2010-12-08 13:09:59 -08:00
|
|
|
|
s = ofpbuf_put_hex(b, s, &n);
|
|
|
|
|
if (n != nxm_field_bytes(header)) {
|
2019-01-16 16:53:52 -08:00
|
|
|
|
const struct mf_field *field = mf_from_oxm_header(header, NULL, false, NULL);
|
2015-05-07 20:11:57 -07:00
|
|
|
|
|
|
|
|
|
if (field && field->variable_len) {
|
|
|
|
|
if (n <= field->n_bytes) {
|
|
|
|
|
int len = (nxm_hasmask(header) ? n * 2 : n) +
|
|
|
|
|
nxm_experimenter_len(header);
|
|
|
|
|
|
|
|
|
|
header = NXM_HEADER(nxm_vendor(header), nxm_class(header),
|
|
|
|
|
nxm_field(header),
|
|
|
|
|
nxm_hasmask(header) ? 1 : 0, len);
|
|
|
|
|
} else {
|
|
|
|
|
ovs_fatal(0, "expected to read at most %d bytes but got "
|
|
|
|
|
"%"PRIuSIZE, field->n_bytes, n);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ovs_fatal(0, "expected to read %d bytes but got %"PRIuSIZE,
|
|
|
|
|
nxm_field_bytes(header), n);
|
|
|
|
|
}
|
2010-12-08 13:09:59 -08:00
|
|
|
|
}
|
2015-05-07 20:11:57 -07:00
|
|
|
|
nw_header = htonll(header);
|
2016-03-07 11:31:02 -08:00
|
|
|
|
memcpy(b->header, &nw_header, nxm_header_len(header));
|
2015-05-07 20:11:57 -07:00
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
if (nxm_hasmask(header)) {
|
2010-11-09 17:00:59 -08:00
|
|
|
|
s += strspn(s, " ");
|
|
|
|
|
if (*s != '/') {
|
2010-12-07 11:04:15 -08:00
|
|
|
|
ovs_fatal(0, "%s: missing / in masked field %.*s",
|
|
|
|
|
full_s, name_len, name);
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
2010-12-08 13:09:59 -08:00
|
|
|
|
s = ofpbuf_put_hex(b, s + 1, &n);
|
|
|
|
|
if (n != nxm_field_bytes(header)) {
|
|
|
|
|
ovs_fatal(0, "%.2s: hex digits expected", s);
|
|
|
|
|
}
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s += strspn(s, " ");
|
|
|
|
|
if (*s != ')') {
|
2010-12-07 11:04:15 -08:00
|
|
|
|
ovs_fatal(0, "%s: missing ) following field %.*s",
|
|
|
|
|
full_s, name_len, name);
|
2010-11-09 17:00:59 -08:00
|
|
|
|
}
|
|
|
|
|
s++;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 17:29:44 -08:00
|
|
|
|
return b->size - start_len;
|
2012-08-01 16:01:45 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
nx_match_from_string(const char *s, struct ofpbuf *b)
|
|
|
|
|
{
|
|
|
|
|
int match_len = nx_match_from_string_raw(s, b);
|
2014-03-10 23:50:54 -07:00
|
|
|
|
ofpbuf_put_zeros(b, PAD_SIZE(match_len, 8));
|
2012-08-01 16:01:45 +09:00
|
|
|
|
return match_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
oxm_match_from_string(const char *s, struct ofpbuf *b)
|
|
|
|
|
{
|
|
|
|
|
int match_len;
|
|
|
|
|
struct ofp11_match_header *omh;
|
2015-03-02 17:29:44 -08:00
|
|
|
|
size_t start_len = b->size;
|
2012-08-01 16:01:45 +09:00
|
|
|
|
|
|
|
|
|
ofpbuf_put_uninit(b, sizeof *omh);
|
|
|
|
|
match_len = nx_match_from_string_raw(s, b) + sizeof *omh;
|
2014-03-10 23:50:54 -07:00
|
|
|
|
ofpbuf_put_zeros(b, PAD_SIZE(match_len, 8));
|
2012-08-01 16:01:45 +09:00
|
|
|
|
|
2013-07-22 15:47:19 -07:00
|
|
|
|
omh = ofpbuf_at(b, start_len, sizeof *omh);
|
2012-08-01 16:01:45 +09:00
|
|
|
|
omh->type = htons(OFPMT_OXM);
|
|
|
|
|
omh->length = htons(match_len);
|
|
|
|
|
|
2010-11-09 17:00:59 -08:00
|
|
|
|
return match_len;
|
|
|
|
|
}
|
2010-11-11 10:41:33 -08:00
|
|
|
|
|
2018-11-08 21:39:55 -08:00
|
|
|
|
/* Parses 's' as a "move" action, in the form described in ovs-actions(7), into
|
2013-07-08 10:15:00 -07:00
|
|
|
|
* '*move'.
|
|
|
|
|
*
|
|
|
|
|
* Returns NULL if successful, otherwise a malloc()'d string describing the
|
|
|
|
|
* error. The caller is responsible for freeing the returned string. */
|
2014-12-15 14:10:38 +01:00
|
|
|
|
char * OVS_WARN_UNUSED_RESULT
|
2012-07-03 22:17:14 -07:00
|
|
|
|
nxm_parse_reg_move(struct ofpact_reg_move *move, const char *s)
|
2010-12-09 11:03:35 -08:00
|
|
|
|
{
|
|
|
|
|
const char *full_s = s;
|
2013-07-08 10:15:00 -07:00
|
|
|
|
char *error;
|
2010-12-09 11:03:35 -08:00
|
|
|
|
|
2013-07-08 10:15:00 -07:00
|
|
|
|
error = mf_parse_subfield__(&move->src, &s);
|
|
|
|
|
if (error) {
|
|
|
|
|
return error;
|
|
|
|
|
}
|
2010-12-09 11:03:35 -08:00
|
|
|
|
if (strncmp(s, "->", 2)) {
|
2013-07-08 10:15:00 -07:00
|
|
|
|
return xasprintf("%s: missing `->' following source", full_s);
|
2010-12-09 11:03:35 -08:00
|
|
|
|
}
|
|
|
|
|
s += 2;
|
2013-07-08 10:15:00 -07:00
|
|
|
|
error = mf_parse_subfield(&move->dst, s);
|
|
|
|
|
if (error) {
|
|
|
|
|
return error;
|
2010-12-09 11:03:35 -08:00
|
|
|
|
}
|
|
|
|
|
|
2012-07-03 22:17:14 -07:00
|
|
|
|
if (move->src.n_bits != move->dst.n_bits) {
|
2013-07-08 10:15:00 -07:00
|
|
|
|
return xasprintf("%s: source field is %d bits wide but destination is "
|
|
|
|
|
"%d bits wide", full_s,
|
|
|
|
|
move->src.n_bits, move->dst.n_bits);
|
2010-12-09 11:03:35 -08:00
|
|
|
|
}
|
2013-07-08 10:15:00 -07:00
|
|
|
|
return NULL;
|
2010-12-09 11:03:35 -08:00
|
|
|
|
}
|
|
|
|
|
|
2014-10-07 16:49:50 -07:00
|
|
|
|
/* nxm_format_reg_move(). */
|
2010-12-09 11:03:35 -08:00
|
|
|
|
|
|
|
|
|
void
|
2012-07-03 22:17:14 -07:00
|
|
|
|
nxm_format_reg_move(const struct ofpact_reg_move *move, struct ds *s)
|
2010-12-09 11:03:35 -08:00
|
|
|
|
{
|
2016-03-02 15:56:20 +01:00
|
|
|
|
ds_put_format(s, "%smove:%s", colors.special, colors.end);
|
2012-07-03 22:17:14 -07:00
|
|
|
|
mf_format_subfield(&move->src, s);
|
2016-03-02 15:56:20 +01:00
|
|
|
|
ds_put_format(s, "%s->%s", colors.special, colors.end);
|
2012-07-03 22:17:14 -07:00
|
|
|
|
mf_format_subfield(&move->dst, s);
|
2010-12-09 11:03:35 -08:00
|
|
|
|
}
|
|
|
|
|
|
2012-07-03 22:17:14 -07:00
|
|
|
|
|
|
|
|
|
enum ofperr
|
2017-03-08 17:18:22 -08:00
|
|
|
|
nxm_reg_move_check(const struct ofpact_reg_move *move,
|
|
|
|
|
const struct match *match)
|
2011-07-19 15:47:02 -07:00
|
|
|
|
{
|
2012-01-12 15:48:19 -08:00
|
|
|
|
enum ofperr error;
|
2011-07-19 15:47:02 -07:00
|
|
|
|
|
2017-03-08 17:18:22 -08:00
|
|
|
|
error = mf_check_src(&move->src, match);
|
2011-07-19 15:47:02 -07:00
|
|
|
|
if (error) {
|
|
|
|
|
return error;
|
2010-11-11 10:41:33 -08:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-08 17:18:22 -08:00
|
|
|
|
return mf_check_dst(&move->dst, match);
|
2012-07-03 22:17:14 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-10-07 16:49:50 -07:00
|
|
|
|
/* nxm_execute_reg_move(). */
|
2010-11-11 10:41:33 -08:00
|
|
|
|
|
2011-12-28 12:42:14 -08:00
|
|
|
|
void
|
2012-07-03 22:17:14 -07:00
|
|
|
|
nxm_reg_load(const struct mf_subfield *dst, uint64_t src_data,
|
2013-08-02 21:17:31 -07:00
|
|
|
|
struct flow *flow, struct flow_wildcards *wc)
|
2011-12-28 12:42:14 -08:00
|
|
|
|
{
|
2012-09-12 17:44:28 +09:00
|
|
|
|
union mf_subvalue src_subvalue;
|
2013-08-02 21:17:31 -07:00
|
|
|
|
union mf_subvalue mask_value;
|
2012-09-12 17:44:28 +09:00
|
|
|
|
ovs_be64 src_data_be = htonll(src_data);
|
2012-07-03 22:17:14 -07:00
|
|
|
|
|
2013-08-02 21:17:31 -07:00
|
|
|
|
memset(&mask_value, 0xff, sizeof mask_value);
|
|
|
|
|
mf_write_subfield_flow(dst, &mask_value, &wc->masks);
|
|
|
|
|
|
2012-09-12 17:44:28 +09:00
|
|
|
|
bitwise_copy(&src_data_be, sizeof src_data_be, 0,
|
|
|
|
|
&src_subvalue, sizeof src_subvalue, 0,
|
|
|
|
|
sizeof src_data_be * 8);
|
|
|
|
|
mf_write_subfield_flow(dst, &src_subvalue, flow);
|
2010-11-11 10:41:33 -08:00
|
|
|
|
}
|
2013-03-05 16:27:55 -08:00
|
|
|
|
|
|
|
|
|
/* nxm_parse_stack_action, works for both push() and pop(). */
|
2013-07-08 10:15:00 -07:00
|
|
|
|
|
|
|
|
|
/* Parses 's' as a "push" or "pop" action, in the form described in
|
2018-11-08 21:39:55 -08:00
|
|
|
|
* ovs-actions(7), into '*stack_action'.
|
2013-07-08 10:15:00 -07:00
|
|
|
|
*
|
|
|
|
|
* Returns NULL if successful, otherwise a malloc()'d string describing the
|
|
|
|
|
* error. The caller is responsible for freeing the returned string. */
|
2014-12-15 14:10:38 +01:00
|
|
|
|
char * OVS_WARN_UNUSED_RESULT
|
2013-03-05 16:27:55 -08:00
|
|
|
|
nxm_parse_stack_action(struct ofpact_stack *stack_action, const char *s)
|
|
|
|
|
{
|
2013-07-08 10:15:00 -07:00
|
|
|
|
char *error;
|
|
|
|
|
|
|
|
|
|
error = mf_parse_subfield__(&stack_action->subfield, &s);
|
|
|
|
|
if (error) {
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-05 16:27:55 -08:00
|
|
|
|
if (*s != '\0') {
|
2013-07-08 10:15:00 -07:00
|
|
|
|
return xasprintf("%s: trailing garbage following push or pop", s);
|
2013-03-05 16:27:55 -08:00
|
|
|
|
}
|
2013-07-08 10:15:00 -07:00
|
|
|
|
|
|
|
|
|
return NULL;
|
2013-03-05 16:27:55 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nxm_format_stack_push(const struct ofpact_stack *push, struct ds *s)
|
|
|
|
|
{
|
2016-03-02 15:56:20 +01:00
|
|
|
|
ds_put_format(s, "%spush:%s", colors.param, colors.end);
|
2013-03-05 16:27:55 -08:00
|
|
|
|
mf_format_subfield(&push->subfield, s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nxm_format_stack_pop(const struct ofpact_stack *pop, struct ds *s)
|
|
|
|
|
{
|
2016-03-02 15:56:20 +01:00
|
|
|
|
ds_put_format(s, "%spop:%s", colors.param, colors.end);
|
2013-03-05 16:27:55 -08:00
|
|
|
|
mf_format_subfield(&pop->subfield, s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum ofperr
|
|
|
|
|
nxm_stack_push_check(const struct ofpact_stack *push,
|
2017-03-08 17:18:22 -08:00
|
|
|
|
const struct match *match)
|
2013-03-05 16:27:55 -08:00
|
|
|
|
{
|
2017-03-08 17:18:22 -08:00
|
|
|
|
return mf_check_src(&push->subfield, match);
|
2013-03-05 16:27:55 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum ofperr
|
|
|
|
|
nxm_stack_pop_check(const struct ofpact_stack *pop,
|
2017-03-08 17:18:22 -08:00
|
|
|
|
const struct match *match)
|
2013-03-05 16:27:55 -08:00
|
|
|
|
{
|
2017-03-08 17:18:22 -08:00
|
|
|
|
return mf_check_dst(&pop->subfield, match);
|
2013-03-05 16:27:55 -08:00
|
|
|
|
}
|
|
|
|
|
|
2017-01-05 17:30:27 -08:00
|
|
|
|
/* nxm_execute_stack_push(), nxm_execute_stack_pop().
|
|
|
|
|
*
|
|
|
|
|
* A stack is an ofpbuf with 'data' pointing to the bottom of the stack and
|
|
|
|
|
* 'size' indexing the top of the stack. Each value of some byte length is
|
|
|
|
|
* stored to the stack immediately followed by the length of the value as an
|
|
|
|
|
* unsigned byte. This way a POP operation can first read the length byte, and
|
|
|
|
|
* then the appropriate number of bytes from the stack. This also means that
|
|
|
|
|
* it is only possible to traverse the stack from top to bottom. It is
|
|
|
|
|
* possible, however, to push values also to the bottom of the stack, which is
|
|
|
|
|
* useful when a stack has been serialized to a wire format in reverse order
|
|
|
|
|
* (topmost value first).
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* Push value 'v' of length 'bytes' to the top of 'stack'. */
|
|
|
|
|
void
|
|
|
|
|
nx_stack_push(struct ofpbuf *stack, const void *v, uint8_t bytes)
|
2013-03-05 16:27:55 -08:00
|
|
|
|
{
|
2017-01-05 17:30:27 -08:00
|
|
|
|
ofpbuf_put(stack, v, bytes);
|
|
|
|
|
ofpbuf_put(stack, &bytes, sizeof bytes);
|
2013-03-05 16:27:55 -08:00
|
|
|
|
}
|
|
|
|
|
|
2017-01-05 17:30:27 -08:00
|
|
|
|
/* Push value 'v' of length 'bytes' to the bottom of 'stack'. */
|
|
|
|
|
void
|
|
|
|
|
nx_stack_push_bottom(struct ofpbuf *stack, const void *v, uint8_t bytes)
|
2013-03-05 16:27:55 -08:00
|
|
|
|
{
|
2017-01-05 17:30:27 -08:00
|
|
|
|
ofpbuf_push(stack, &bytes, sizeof bytes);
|
|
|
|
|
ofpbuf_push(stack, v, bytes);
|
|
|
|
|
}
|
2014-03-30 01:31:50 -07:00
|
|
|
|
|
2017-01-05 17:30:27 -08:00
|
|
|
|
/* Pop the topmost value from 'stack', returning a pointer to the value in the
|
|
|
|
|
* stack and the length of the value in '*bytes'. In case of underflow a NULL
|
|
|
|
|
* is returned and length is returned as zero via '*bytes'. */
|
|
|
|
|
void *
|
|
|
|
|
nx_stack_pop(struct ofpbuf *stack, uint8_t *bytes)
|
|
|
|
|
{
|
|
|
|
|
if (!stack->size) {
|
|
|
|
|
*bytes = 0;
|
|
|
|
|
return NULL;
|
2013-03-05 16:27:55 -08:00
|
|
|
|
}
|
|
|
|
|
|
2017-01-05 17:30:27 -08:00
|
|
|
|
stack->size -= sizeof *bytes;
|
|
|
|
|
memcpy(bytes, ofpbuf_tail(stack), sizeof *bytes);
|
|
|
|
|
|
|
|
|
|
ovs_assert(stack->size >= *bytes);
|
|
|
|
|
stack->size -= *bytes;
|
|
|
|
|
return ofpbuf_tail(stack);
|
2013-03-05 16:27:55 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nxm_execute_stack_push(const struct ofpact_stack *push,
|
2013-05-14 18:24:43 -07:00
|
|
|
|
const struct flow *flow, struct flow_wildcards *wc,
|
|
|
|
|
struct ofpbuf *stack)
|
2013-03-05 16:27:55 -08:00
|
|
|
|
{
|
|
|
|
|
union mf_subvalue dst_value;
|
|
|
|
|
|
2017-01-05 17:30:27 -08:00
|
|
|
|
mf_write_subfield_flow(&push->subfield,
|
|
|
|
|
(union mf_subvalue *)&exact_match_mask,
|
|
|
|
|
&wc->masks);
|
2013-05-14 18:24:43 -07:00
|
|
|
|
|
2013-03-05 16:27:55 -08:00
|
|
|
|
mf_read_subfield(&push->subfield, flow, &dst_value);
|
2017-01-05 17:30:27 -08:00
|
|
|
|
uint8_t bytes = DIV_ROUND_UP(push->subfield.n_bits, 8);
|
|
|
|
|
nx_stack_push(stack, &dst_value.u8[sizeof dst_value - bytes], bytes);
|
2013-03-05 16:27:55 -08:00
|
|
|
|
}
|
|
|
|
|
|
ofproto-dpif: Make ofproto/trace output easier to read.
"ovs-appctl ofproto/trace" is invaluable for debugging, but as the users of
Open vSwitch have evolved it has failed to keep up with the times. It's
pretty easy to design OpenFlow tables and pipelines that resubmit dozens of
times. Each resubmit causes an additional tab of indentation, so the
output wraps around, sometimes again and again, and makes the output close
to unreadable.
ovn-trace pioneered better formatting for tracing in OVN logical datapaths,
mostly by not increasing indentation for tail recursion, which in practice
gets rid of almost all indentation.
This commit experiments with redoing ofproto/trace the same way. Try
looking at, for example, the testsuite output for test 2282 "ovn -- 3 HVs,
3 LRs connected via LS, source IP based routes". Without this commit, it
indents 61 levels (488 spaces!). With this commit, it indents 1 level
(4 spaces) and it's possible to actually understand what's going on almost
at a glance.
To see this for yourself, try the following command either with or without
this commit (but be sure to keep the change to ovn.at that adds an
ofproto/trace to the test):
make check TESTSUITEFLAGS='-d 2282' && less tests/testsuite.dir/2282/testsuite.log
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Lance Richardson <lrichard@redhat.com>
Acked-by: Justin Pettit <jpettit@ovn.org>
2017-01-12 08:15:02 -08:00
|
|
|
|
bool
|
2013-03-05 16:27:55 -08:00
|
|
|
|
nxm_execute_stack_pop(const struct ofpact_stack *pop,
|
2013-08-02 21:17:31 -07:00
|
|
|
|
struct flow *flow, struct flow_wildcards *wc,
|
|
|
|
|
struct ofpbuf *stack)
|
2013-03-05 16:27:55 -08:00
|
|
|
|
{
|
2017-01-05 17:30:27 -08:00
|
|
|
|
uint8_t src_bytes;
|
|
|
|
|
const void *src = nx_stack_pop(stack, &src_bytes);
|
|
|
|
|
if (src) {
|
|
|
|
|
union mf_subvalue src_value;
|
|
|
|
|
uint8_t dst_bytes = DIV_ROUND_UP(pop->subfield.n_bits, 8);
|
2013-08-02 21:17:31 -07:00
|
|
|
|
|
2017-01-05 17:30:27 -08:00
|
|
|
|
if (src_bytes < dst_bytes) {
|
|
|
|
|
memset(&src_value.u8[sizeof src_value - dst_bytes], 0,
|
|
|
|
|
dst_bytes - src_bytes);
|
|
|
|
|
}
|
|
|
|
|
memcpy(&src_value.u8[sizeof src_value - src_bytes], src, src_bytes);
|
|
|
|
|
mf_write_subfield_flow(&pop->subfield,
|
|
|
|
|
(union mf_subvalue *)&exact_match_mask,
|
|
|
|
|
&wc->masks);
|
|
|
|
|
mf_write_subfield_flow(&pop->subfield, &src_value, flow);
|
ofproto-dpif: Make ofproto/trace output easier to read.
"ovs-appctl ofproto/trace" is invaluable for debugging, but as the users of
Open vSwitch have evolved it has failed to keep up with the times. It's
pretty easy to design OpenFlow tables and pipelines that resubmit dozens of
times. Each resubmit causes an additional tab of indentation, so the
output wraps around, sometimes again and again, and makes the output close
to unreadable.
ovn-trace pioneered better formatting for tracing in OVN logical datapaths,
mostly by not increasing indentation for tail recursion, which in practice
gets rid of almost all indentation.
This commit experiments with redoing ofproto/trace the same way. Try
looking at, for example, the testsuite output for test 2282 "ovn -- 3 HVs,
3 LRs connected via LS, source IP based routes". Without this commit, it
indents 61 levels (488 spaces!). With this commit, it indents 1 level
(4 spaces) and it's possible to actually understand what's going on almost
at a glance.
To see this for yourself, try the following command either with or without
this commit (but be sure to keep the change to ovn.at that adds an
ofproto/trace to the test):
make check TESTSUITEFLAGS='-d 2282' && less tests/testsuite.dir/2282/testsuite.log
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Lance Richardson <lrichard@redhat.com>
Acked-by: Justin Pettit <jpettit@ovn.org>
2017-01-12 08:15:02 -08:00
|
|
|
|
return true;
|
2013-03-05 16:27:55 -08:00
|
|
|
|
} else {
|
ofproto-dpif: Make ofproto/trace output easier to read.
"ovs-appctl ofproto/trace" is invaluable for debugging, but as the users of
Open vSwitch have evolved it has failed to keep up with the times. It's
pretty easy to design OpenFlow tables and pipelines that resubmit dozens of
times. Each resubmit causes an additional tab of indentation, so the
output wraps around, sometimes again and again, and makes the output close
to unreadable.
ovn-trace pioneered better formatting for tracing in OVN logical datapaths,
mostly by not increasing indentation for tail recursion, which in practice
gets rid of almost all indentation.
This commit experiments with redoing ofproto/trace the same way. Try
looking at, for example, the testsuite output for test 2282 "ovn -- 3 HVs,
3 LRs connected via LS, source IP based routes". Without this commit, it
indents 61 levels (488 spaces!). With this commit, it indents 1 level
(4 spaces) and it's possible to actually understand what's going on almost
at a glance.
To see this for yourself, try the following command either with or without
this commit (but be sure to keep the change to ovn.at that adds an
ofproto/trace to the test):
make check TESTSUITEFLAGS='-d 2282' && less tests/testsuite.dir/2282/testsuite.log
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Lance Richardson <lrichard@redhat.com>
Acked-by: Justin Pettit <jpettit@ovn.org>
2017-01-12 08:15:02 -08:00
|
|
|
|
/* Attempted to pop from an empty stack. */
|
|
|
|
|
return false;
|
2013-03-05 16:27:55 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
2014-09-16 22:13:44 -07:00
|
|
|
|
|
ofp-actions: Add delete field action
This patch adds a new OpenFlow action, delete field, to delete a
field in packets. Currently, only the tun_metadata fields are
supported.
One use case to add this action is to support multiple versions
of geneve tunnel metadatas to be exchanged among different versions
of networks. For example, we may introduce tun_metadata2 to
replace old tun_metadata1, but still want to provide backward
compatibility to the older release. In this case, in the new
OpenFlow pipeline, we would like to support the case to receive a
packet with tun_metadata1, do some processing. And if the packet
is going to a switch in the newer release, we would like to delete
the value in tun_metadata1 and set a value into tun_metadata2.
Currently, ovs does not provide an action to remove a value in
tun_metadata if the value is present. This patch fulfills the gap
by adding the delete_field action. For example, the OpenFlow
syntax to delete tun_metadata1 is:
actions=delete_field:tun_metadata1
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: William Tu <u9012063@gmail.com>
Acked-by: William Tu <u9012063@gmail.com>
2020-04-14 13:33:28 -07:00
|
|
|
|
/* Parses a field from '*s' into '*field'. If successful, stores the
|
|
|
|
|
* reference to the field in '*field', and returns NULL. On failure,
|
|
|
|
|
* returns a malloc()'ed error message.
|
|
|
|
|
*/
|
|
|
|
|
char * OVS_WARN_UNUSED_RESULT
|
|
|
|
|
mf_parse_field(const struct mf_field **field, const char *s)
|
|
|
|
|
{
|
|
|
|
|
const struct nxm_field *f;
|
|
|
|
|
int s_len = strlen(s);
|
|
|
|
|
|
|
|
|
|
f = nxm_field_by_name(s, s_len);
|
|
|
|
|
(*field) = f ? mf_from_id(f->id) : mf_from_name_len(s, s_len);
|
|
|
|
|
if (!*field) {
|
|
|
|
|
return xasprintf("unknown field `%s'", s);
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
/* Formats 'sf' into 's' in a format normally acceptable to
|
|
|
|
|
* mf_parse_subfield(). (It won't be acceptable if sf->field is NULL or if
|
|
|
|
|
* sf->field has no NXM name.) */
|
|
|
|
|
void
|
|
|
|
|
mf_format_subfield(const struct mf_subfield *sf, struct ds *s)
|
|
|
|
|
{
|
|
|
|
|
if (!sf->field) {
|
|
|
|
|
ds_put_cstr(s, "<unknown>");
|
|
|
|
|
} else {
|
2014-10-09 22:57:47 -07:00
|
|
|
|
const struct nxm_field *f = nxm_field_by_mf_id(sf->field->id, 0);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
ds_put_cstr(s, f ? f->name : sf->field->name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sf->field && sf->ofs == 0 && sf->n_bits == sf->field->n_bits) {
|
|
|
|
|
ds_put_cstr(s, "[]");
|
|
|
|
|
} else if (sf->n_bits == 1) {
|
|
|
|
|
ds_put_format(s, "[%d]", sf->ofs);
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_format(s, "[%d..%d]", sf->ofs, sf->ofs + sf->n_bits - 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const struct nxm_field *
|
|
|
|
|
mf_parse_subfield_name(const char *name, int name_len, bool *wild)
|
|
|
|
|
{
|
|
|
|
|
*wild = name_len > 2 && !memcmp(&name[name_len - 2], "_W", 2);
|
|
|
|
|
if (*wild) {
|
|
|
|
|
name_len -= 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nxm_field_by_name(name, name_len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parses a subfield from the beginning of '*sp' into 'sf'. If successful,
|
|
|
|
|
* returns NULL and advances '*sp' to the first byte following the parsed
|
|
|
|
|
* string. On failure, returns a malloc()'d error message, does not modify
|
|
|
|
|
* '*sp', and does not properly initialize 'sf'.
|
|
|
|
|
*
|
|
|
|
|
* The syntax parsed from '*sp' takes the form "header[start..end]" where
|
|
|
|
|
* 'header' is the name of an NXM field and 'start' and 'end' are (inclusive)
|
|
|
|
|
* bit indexes. "..end" may be omitted to indicate a single bit. "start..end"
|
|
|
|
|
* may both be omitted (the [] are still required) to indicate an entire
|
|
|
|
|
* field. */
|
2014-12-15 14:10:38 +01:00
|
|
|
|
char * OVS_WARN_UNUSED_RESULT
|
2014-09-16 22:13:44 -07:00
|
|
|
|
mf_parse_subfield__(struct mf_subfield *sf, const char **sp)
|
|
|
|
|
{
|
ofp-parse: Allow match field names in actions and brackets in matches.
Allow using match field names in addition to the canonical register
names in actions (including 'load', 'move', 'push', 'pop', 'output',
'multipath', 'bundle_load', and 'learn'). Allow also leaving out the
trailing '[]' to indicate full field. These changes allow simpler
syntax similar to 'set_field' to be used also elsewhere.
Correspondingly, allow the '[start..end]' syntax to be used in matches
in addition to the more explicit 'value/mask' notation. For example,
to match on the value 2 of the bits 14..15 of NXM_NX_REG0, the match
could include:
... reg0[14..15]=2 ...
instead of
... reg0=0x8000/0xc000 ...
Note that only contiguous masks can be specified with the bracket
notation.
Signed-off-by: Jarno Rajahalme <jarno@ovn.org>
Acked-by: Ben Pfaff <blp@ovn.org>
2017-01-04 16:10:56 -08:00
|
|
|
|
const struct mf_field *field = NULL;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
const struct nxm_field *f;
|
|
|
|
|
const char *name;
|
|
|
|
|
int start, end;
|
|
|
|
|
const char *s;
|
|
|
|
|
int name_len;
|
|
|
|
|
bool wild;
|
|
|
|
|
|
|
|
|
|
s = *sp;
|
|
|
|
|
name = s;
|
ofp-parse: Allow match field names in actions and brackets in matches.
Allow using match field names in addition to the canonical register
names in actions (including 'load', 'move', 'push', 'pop', 'output',
'multipath', 'bundle_load', and 'learn'). Allow also leaving out the
trailing '[]' to indicate full field. These changes allow simpler
syntax similar to 'set_field' to be used also elsewhere.
Correspondingly, allow the '[start..end]' syntax to be used in matches
in addition to the more explicit 'value/mask' notation. For example,
to match on the value 2 of the bits 14..15 of NXM_NX_REG0, the match
could include:
... reg0[14..15]=2 ...
instead of
... reg0=0x8000/0xc000 ...
Note that only contiguous masks can be specified with the bracket
notation.
Signed-off-by: Jarno Rajahalme <jarno@ovn.org>
Acked-by: Ben Pfaff <blp@ovn.org>
2017-01-04 16:10:56 -08:00
|
|
|
|
name_len = strcspn(s, "[-");
|
2014-09-16 22:13:44 -07:00
|
|
|
|
|
|
|
|
|
f = mf_parse_subfield_name(name, name_len, &wild);
|
ofp-parse: Allow match field names in actions and brackets in matches.
Allow using match field names in addition to the canonical register
names in actions (including 'load', 'move', 'push', 'pop', 'output',
'multipath', 'bundle_load', and 'learn'). Allow also leaving out the
trailing '[]' to indicate full field. These changes allow simpler
syntax similar to 'set_field' to be used also elsewhere.
Correspondingly, allow the '[start..end]' syntax to be used in matches
in addition to the more explicit 'value/mask' notation. For example,
to match on the value 2 of the bits 14..15 of NXM_NX_REG0, the match
could include:
... reg0[14..15]=2 ...
instead of
... reg0=0x8000/0xc000 ...
Note that only contiguous masks can be specified with the bracket
notation.
Signed-off-by: Jarno Rajahalme <jarno@ovn.org>
Acked-by: Ben Pfaff <blp@ovn.org>
2017-01-04 16:10:56 -08:00
|
|
|
|
field = f ? mf_from_id(f->id) : mf_from_name_len(name, name_len);
|
|
|
|
|
if (!field) {
|
2014-09-16 22:13:44 -07:00
|
|
|
|
return xasprintf("%s: unknown field `%.*s'", *sp, name_len, s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s += name_len;
|
ofp-parse: Allow match field names in actions and brackets in matches.
Allow using match field names in addition to the canonical register
names in actions (including 'load', 'move', 'push', 'pop', 'output',
'multipath', 'bundle_load', and 'learn'). Allow also leaving out the
trailing '[]' to indicate full field. These changes allow simpler
syntax similar to 'set_field' to be used also elsewhere.
Correspondingly, allow the '[start..end]' syntax to be used in matches
in addition to the more explicit 'value/mask' notation. For example,
to match on the value 2 of the bits 14..15 of NXM_NX_REG0, the match
could include:
... reg0[14..15]=2 ...
instead of
... reg0=0x8000/0xc000 ...
Note that only contiguous masks can be specified with the bracket
notation.
Signed-off-by: Jarno Rajahalme <jarno@ovn.org>
Acked-by: Ben Pfaff <blp@ovn.org>
2017-01-04 16:10:56 -08:00
|
|
|
|
/* Assume full field. */
|
|
|
|
|
start = 0;
|
|
|
|
|
end = field->n_bits - 1;
|
|
|
|
|
if (*s == '[') {
|
|
|
|
|
if (!strncmp(s, "[]", 2)) {
|
|
|
|
|
/* Nothing to do. */
|
|
|
|
|
} else if (ovs_scan(s, "[%d..%d]", &start, &end)) {
|
|
|
|
|
/* Nothing to do. */
|
|
|
|
|
} else if (ovs_scan(s, "[%d]", &start)) {
|
|
|
|
|
end = start;
|
|
|
|
|
} else {
|
|
|
|
|
return xasprintf("%s: syntax error expecting [] or [<bit>] or "
|
|
|
|
|
"[<start>..<end>]", *sp);
|
|
|
|
|
}
|
|
|
|
|
s = strchr(s, ']') + 1;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (start > end) {
|
|
|
|
|
return xasprintf("%s: starting bit %d is after ending bit %d",
|
|
|
|
|
*sp, start, end);
|
|
|
|
|
} else if (start >= field->n_bits) {
|
|
|
|
|
return xasprintf("%s: starting bit %d is not valid because field is "
|
|
|
|
|
"only %d bits wide", *sp, start, field->n_bits);
|
|
|
|
|
} else if (end >= field->n_bits){
|
|
|
|
|
return xasprintf("%s: ending bit %d is not valid because field is "
|
|
|
|
|
"only %d bits wide", *sp, end, field->n_bits);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sf->field = field;
|
|
|
|
|
sf->ofs = start;
|
|
|
|
|
sf->n_bits = end - start + 1;
|
|
|
|
|
|
|
|
|
|
*sp = s;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parses a subfield from the entirety of 's' into 'sf'. Returns NULL if
|
|
|
|
|
* successful, otherwise a malloc()'d string describing the error. The caller
|
|
|
|
|
* is responsible for freeing the returned string.
|
|
|
|
|
*
|
|
|
|
|
* The syntax parsed from 's' takes the form "header[start..end]" where
|
|
|
|
|
* 'header' is the name of an NXM field and 'start' and 'end' are (inclusive)
|
|
|
|
|
* bit indexes. "..end" may be omitted to indicate a single bit. "start..end"
|
|
|
|
|
* may both be omitted (the [] are still required) to indicate an entire
|
|
|
|
|
* field. */
|
2014-12-15 14:10:38 +01:00
|
|
|
|
char * OVS_WARN_UNUSED_RESULT
|
2014-09-16 22:13:44 -07:00
|
|
|
|
mf_parse_subfield(struct mf_subfield *sf, const char *s)
|
|
|
|
|
{
|
|
|
|
|
char *error = mf_parse_subfield__(sf, &s);
|
|
|
|
|
if (!error && s[0]) {
|
|
|
|
|
error = xstrdup("unexpected input following field syntax");
|
|
|
|
|
}
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns an bitmap in which each bit corresponds to the like-numbered field
|
|
|
|
|
* in the OFPXMC12_OPENFLOW_BASIC OXM class, in which the bit values are taken
|
|
|
|
|
* from the 'fields' bitmap. Only fields defined in OpenFlow 'version' are
|
|
|
|
|
* considered.
|
|
|
|
|
*
|
|
|
|
|
* This is useful for encoding OpenFlow 1.2 table stats messages. */
|
|
|
|
|
ovs_be64
|
|
|
|
|
oxm_bitmap_from_mf_bitmap(const struct mf_bitmap *fields,
|
|
|
|
|
enum ofp_version version)
|
|
|
|
|
{
|
|
|
|
|
uint64_t oxm_bitmap = 0;
|
2024-12-04 16:48:52 +01:00
|
|
|
|
enum mf_field_id id;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
|
2024-12-04 16:48:52 +01:00
|
|
|
|
BITMAP_FOR_EACH_1 (id, MFF_N_IDS, fields->bm) {
|
|
|
|
|
uint64_t oxm = mf_oxm_header(id, version);
|
2014-09-10 11:15:20 -07:00
|
|
|
|
uint32_t class = nxm_class(oxm);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
int field = nxm_field(oxm);
|
|
|
|
|
|
2014-09-10 11:15:20 -07:00
|
|
|
|
if (class == OFPXMC12_OPENFLOW_BASIC && field < 64) {
|
2014-09-16 22:13:44 -07:00
|
|
|
|
oxm_bitmap |= UINT64_C(1) << field;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return htonll(oxm_bitmap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Opposite conversion from oxm_bitmap_from_mf_bitmap().
|
|
|
|
|
*
|
|
|
|
|
* This is useful for decoding OpenFlow 1.2 table stats messages. */
|
|
|
|
|
struct mf_bitmap
|
|
|
|
|
oxm_bitmap_to_mf_bitmap(ovs_be64 oxm_bitmap, enum ofp_version version)
|
|
|
|
|
{
|
|
|
|
|
struct mf_bitmap fields = MF_BITMAP_INITIALIZER;
|
|
|
|
|
|
|
|
|
|
for (enum mf_field_id id = 0; id < MFF_N_IDS; id++) {
|
2014-10-09 22:57:47 -07:00
|
|
|
|
uint64_t oxm = mf_oxm_header(id, version);
|
2019-01-16 16:53:52 -08:00
|
|
|
|
if (oxm && version >= nxm_field_by_header(oxm, false, NULL)->version) {
|
2014-09-10 11:15:20 -07:00
|
|
|
|
uint32_t class = nxm_class(oxm);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
int field = nxm_field(oxm);
|
|
|
|
|
|
2014-09-10 11:15:20 -07:00
|
|
|
|
if (class == OFPXMC12_OPENFLOW_BASIC
|
2014-09-16 22:13:44 -07:00
|
|
|
|
&& field < 64
|
|
|
|
|
&& oxm_bitmap & htonll(UINT64_C(1) << field)) {
|
|
|
|
|
bitmap_set1(fields.bm, id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return fields;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns a bitmap of fields that can be encoded in OXM and that can be
|
|
|
|
|
* modified with a "set_field" action. */
|
|
|
|
|
struct mf_bitmap
|
|
|
|
|
oxm_writable_fields(void)
|
|
|
|
|
{
|
|
|
|
|
struct mf_bitmap b = MF_BITMAP_INITIALIZER;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < MFF_N_IDS; i++) {
|
|
|
|
|
if (mf_oxm_header(i, 0) && mf_from_id(i)->writable) {
|
|
|
|
|
bitmap_set1(b.bm, i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns a bitmap of fields that can be encoded in OXM and that can be
|
|
|
|
|
* matched in a flow table. */
|
|
|
|
|
struct mf_bitmap
|
|
|
|
|
oxm_matchable_fields(void)
|
|
|
|
|
{
|
|
|
|
|
struct mf_bitmap b = MF_BITMAP_INITIALIZER;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < MFF_N_IDS; i++) {
|
|
|
|
|
if (mf_oxm_header(i, 0)) {
|
|
|
|
|
bitmap_set1(b.bm, i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns a bitmap of fields that can be encoded in OXM and that can be
|
|
|
|
|
* matched in a flow table with an arbitrary bitmask. */
|
|
|
|
|
struct mf_bitmap
|
|
|
|
|
oxm_maskable_fields(void)
|
|
|
|
|
{
|
|
|
|
|
struct mf_bitmap b = MF_BITMAP_INITIALIZER;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < MFF_N_IDS; i++) {
|
|
|
|
|
if (mf_oxm_header(i, 0) && mf_from_id(i)->maskable == MFM_FULLY) {
|
|
|
|
|
bitmap_set1(b.bm, i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct nxm_field_index {
|
2014-10-09 22:57:47 -07:00
|
|
|
|
struct hmap_node header_node; /* In nxm_header_map. */
|
|
|
|
|
struct hmap_node name_node; /* In nxm_name_map. */
|
2014-12-15 14:10:38 +01:00
|
|
|
|
struct ovs_list mf_node; /* In mf_mf_map[nf.id]. */
|
2014-10-09 22:57:47 -07:00
|
|
|
|
const struct nxm_field nf;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#include "nx-match.inc"
|
|
|
|
|
|
|
|
|
|
static struct hmap nxm_header_map;
|
|
|
|
|
static struct hmap nxm_name_map;
|
2014-12-15 14:10:38 +01:00
|
|
|
|
static struct ovs_list nxm_mf_map[MFF_N_IDS];
|
2014-09-16 22:13:44 -07:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nxm_init(void)
|
|
|
|
|
{
|
|
|
|
|
static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
|
|
|
|
|
if (ovsthread_once_start(&once)) {
|
|
|
|
|
hmap_init(&nxm_header_map);
|
|
|
|
|
hmap_init(&nxm_name_map);
|
2014-10-09 22:57:47 -07:00
|
|
|
|
for (int i = 0; i < MFF_N_IDS; i++) {
|
2016-03-25 14:10:22 -07:00
|
|
|
|
ovs_list_init(&nxm_mf_map[i]);
|
2014-10-09 22:57:47 -07:00
|
|
|
|
}
|
2014-09-16 22:13:44 -07:00
|
|
|
|
for (struct nxm_field_index *nfi = all_nxm_fields;
|
|
|
|
|
nfi < &all_nxm_fields[ARRAY_SIZE(all_nxm_fields)]; nfi++) {
|
|
|
|
|
hmap_insert(&nxm_header_map, &nfi->header_node,
|
2015-05-06 17:59:24 -07:00
|
|
|
|
hash_uint64(nxm_no_len(nfi->nf.header)));
|
2014-09-16 22:13:44 -07:00
|
|
|
|
hmap_insert(&nxm_name_map, &nfi->name_node,
|
|
|
|
|
hash_string(nfi->nf.name, 0));
|
2016-03-25 14:10:22 -07:00
|
|
|
|
ovs_list_push_back(&nxm_mf_map[nfi->nf.id], &nfi->mf_node);
|
2014-09-16 22:13:44 -07:00
|
|
|
|
}
|
|
|
|
|
ovsthread_once_done(&once);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-16 16:53:52 -08:00
|
|
|
|
|
2014-09-16 22:13:44 -07:00
|
|
|
|
static const struct nxm_field *
|
2019-01-16 16:53:52 -08:00
|
|
|
|
nxm_field_by_header(uint64_t header, bool is_action, enum ofperr *h_error)
|
2014-09-16 22:13:44 -07:00
|
|
|
|
{
|
|
|
|
|
const struct nxm_field_index *nfi;
|
2015-05-06 17:59:24 -07:00
|
|
|
|
uint64_t header_no_len;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
|
|
|
|
|
nxm_init();
|
|
|
|
|
if (nxm_hasmask(header)) {
|
|
|
|
|
header = nxm_make_exact_header(header);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-06 17:59:24 -07:00
|
|
|
|
header_no_len = nxm_no_len(header);
|
|
|
|
|
|
|
|
|
|
HMAP_FOR_EACH_IN_BUCKET (nfi, header_node, hash_uint64(header_no_len),
|
2014-09-16 22:13:44 -07:00
|
|
|
|
&nxm_header_map) {
|
2019-01-16 16:53:52 -08:00
|
|
|
|
if (is_action && nxm_length(header) > 0) {
|
|
|
|
|
if (nxm_length(header) != nxm_length(nfi->nf.header) && h_error ) {
|
|
|
|
|
*h_error = OFPERR_OFPBAC_BAD_SET_LEN;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-05-06 17:59:24 -07:00
|
|
|
|
if (header_no_len == nxm_no_len(nfi->nf.header)) {
|
|
|
|
|
if (nxm_length(header) == nxm_length(nfi->nf.header) ||
|
|
|
|
|
mf_from_id(nfi->nf.id)->variable_len) {
|
|
|
|
|
return &nfi->nf;
|
|
|
|
|
} else {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2014-09-16 22:13:44 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const struct nxm_field *
|
|
|
|
|
nxm_field_by_name(const char *name, size_t len)
|
|
|
|
|
{
|
|
|
|
|
const struct nxm_field_index *nfi;
|
|
|
|
|
|
|
|
|
|
nxm_init();
|
|
|
|
|
HMAP_FOR_EACH_WITH_HASH (nfi, name_node, hash_bytes(name, len, 0),
|
|
|
|
|
&nxm_name_map) {
|
|
|
|
|
if (strlen(nfi->nf.name) == len && !memcmp(nfi->nf.name, name, len)) {
|
|
|
|
|
return &nfi->nf;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const struct nxm_field *
|
2014-10-09 22:57:47 -07:00
|
|
|
|
nxm_field_by_mf_id(enum mf_field_id id, enum ofp_version version)
|
2014-09-16 22:13:44 -07:00
|
|
|
|
{
|
2014-10-09 22:57:47 -07:00
|
|
|
|
const struct nxm_field_index *nfi;
|
|
|
|
|
const struct nxm_field *f;
|
2014-09-16 22:13:44 -07:00
|
|
|
|
|
|
|
|
|
nxm_init();
|
|
|
|
|
|
2014-10-09 22:57:47 -07:00
|
|
|
|
f = NULL;
|
|
|
|
|
LIST_FOR_EACH (nfi, mf_node, &nxm_mf_map[id]) {
|
|
|
|
|
if (!f || version >= nfi->nf.version) {
|
|
|
|
|
f = &nfi->nf;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return f;
|
|
|
|
|
}
|