2011-09-12 12:11:50 -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
|
|
|
|
* Copyright (c) 2011-2017 Nicira, Inc.
|
2011-09-12 12:11:50 -07: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>
|
|
|
|
|
|
2016-04-04 21:32:07 -04:00
|
|
|
|
#include "openvswitch/meta-flow.h"
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <limits.h>
|
|
|
|
|
#include <netinet/icmp6.h>
|
|
|
|
|
#include <netinet/ip6.h>
|
|
|
|
|
|
|
|
|
|
#include "classifier.h"
|
2016-03-03 10:20:46 -08:00
|
|
|
|
#include "openvswitch/dynamic-string.h"
|
2014-09-16 22:13:44 -07:00
|
|
|
|
#include "nx-match.h"
|
2016-04-04 21:32:09 -04:00
|
|
|
|
#include "openvswitch/ofp-util.h"
|
2017-03-13 11:28:21 -07:00
|
|
|
|
#include "ovs-atomic.h"
|
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
|
|
|
|
#include "ovs-rcu.h"
|
2013-04-15 15:30:03 -07:00
|
|
|
|
#include "ovs-thread.h"
|
2011-09-12 12:11:50 -07:00
|
|
|
|
#include "packets.h"
|
|
|
|
|
#include "random.h"
|
2016-07-12 16:37:34 -05:00
|
|
|
|
#include "openvswitch/shash.h"
|
2011-09-12 12:11:50 -07:00
|
|
|
|
#include "socket-util.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"
|
2011-09-12 12:11:50 -07:00
|
|
|
|
#include "unaligned.h"
|
2014-11-11 15:50:51 -08:00
|
|
|
|
#include "util.h"
|
2016-03-03 10:20:43 -08:00
|
|
|
|
#include "openvswitch/ofp-errors.h"
|
2014-12-15 14:10:38 +01:00
|
|
|
|
#include "openvswitch/vlog.h"
|
2017-02-17 17:47:44 -08:00
|
|
|
|
#include "vl-mff-map.h"
|
2011-12-28 12:42:14 -08:00
|
|
|
|
|
|
|
|
|
VLOG_DEFINE_THIS_MODULE(meta_flow);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2013-12-11 11:07:01 -08:00
|
|
|
|
#define FLOW_U32OFS(FIELD) \
|
|
|
|
|
offsetof(struct flow, FIELD) % 4 ? -1 : offsetof(struct flow, FIELD) / 4
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
#define MF_FIELD_SIZES(MEMBER) \
|
|
|
|
|
sizeof ((union mf_value *)0)->MEMBER, \
|
|
|
|
|
8 * sizeof ((union mf_value *)0)->MEMBER
|
|
|
|
|
|
2013-10-24 13:19:27 -07:00
|
|
|
|
extern const struct mf_field mf_fields[MFF_N_IDS]; /* Silence a warning. */
|
|
|
|
|
|
|
|
|
|
const struct mf_field mf_fields[MFF_N_IDS] = {
|
2014-10-07 15:24:11 -07:00
|
|
|
|
#include "meta-flow.inc"
|
2011-09-12 12:11:50 -07:00
|
|
|
|
};
|
|
|
|
|
|
2013-04-15 15:30:03 -07:00
|
|
|
|
/* Maps from an mf_field's 'name' or 'extra_name' to the mf_field. */
|
|
|
|
|
static struct shash mf_by_name;
|
2011-10-12 17:04:13 -07:00
|
|
|
|
|
2011-12-28 12:42:14 -08:00
|
|
|
|
/* Rate limit for parse errors. These always indicate a bug in an OpenFlow
|
|
|
|
|
* controller 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);
|
|
|
|
|
|
2015-08-27 10:48:03 -07:00
|
|
|
|
#define MF_VALUE_EXACT_8 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
|
|
|
|
#define MF_VALUE_EXACT_16 MF_VALUE_EXACT_8, MF_VALUE_EXACT_8
|
|
|
|
|
#define MF_VALUE_EXACT_32 MF_VALUE_EXACT_16, MF_VALUE_EXACT_16
|
|
|
|
|
#define MF_VALUE_EXACT_64 MF_VALUE_EXACT_32, MF_VALUE_EXACT_32
|
|
|
|
|
#define MF_VALUE_EXACT_128 MF_VALUE_EXACT_64, MF_VALUE_EXACT_64
|
|
|
|
|
#define MF_VALUE_EXACT_INITIALIZER { .tun_metadata = { MF_VALUE_EXACT_128 } }
|
|
|
|
|
|
|
|
|
|
const union mf_value exact_match_mask = MF_VALUE_EXACT_INITIALIZER;
|
|
|
|
|
|
2013-04-15 15:30:03 -07:00
|
|
|
|
static void nxm_init(void);
|
2012-06-26 10:52:34 -07:00
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
/* Returns the field with the given 'name', or a null pointer if no field has
|
|
|
|
|
* that name. */
|
|
|
|
|
const struct mf_field *
|
|
|
|
|
mf_from_name(const char *name)
|
|
|
|
|
{
|
2013-04-15 15:30:03 -07:00
|
|
|
|
nxm_init();
|
2011-09-12 12:11:50 -07:00
|
|
|
|
return shash_find_data(&mf_by_name, name);
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
/* Returns the field with the given 'name' (which is 'len' bytes long), or a
|
|
|
|
|
* null pointer if no field has that name. */
|
|
|
|
|
const struct mf_field *
|
|
|
|
|
mf_from_name_len(const char *name, size_t len)
|
|
|
|
|
{
|
|
|
|
|
nxm_init();
|
|
|
|
|
|
|
|
|
|
struct shash_node *node = shash_find_len(&mf_by_name, name, len);
|
|
|
|
|
return node ? node->data : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-12 17:04:13 -07:00
|
|
|
|
static void
|
2013-04-15 15:30:03 -07:00
|
|
|
|
nxm_do_init(void)
|
2011-10-12 17:04:13 -07:00
|
|
|
|
{
|
2013-10-15 08:35:39 -07:00
|
|
|
|
int i;
|
2011-10-12 17:04:13 -07:00
|
|
|
|
|
2013-04-15 15:30:03 -07:00
|
|
|
|
shash_init(&mf_by_name);
|
2013-10-15 08:35:39 -07:00
|
|
|
|
for (i = 0; i < MFF_N_IDS; i++) {
|
|
|
|
|
const struct mf_field *mf = &mf_fields[i];
|
|
|
|
|
|
|
|
|
|
ovs_assert(mf->id == i); /* Fields must be in the enum order. */
|
|
|
|
|
|
2013-04-15 15:30:03 -07:00
|
|
|
|
shash_add_once(&mf_by_name, mf->name, mf);
|
|
|
|
|
if (mf->extra_name) {
|
|
|
|
|
shash_add_once(&mf_by_name, mf->extra_name, mf);
|
|
|
|
|
}
|
2011-10-12 17:04:13 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-15 15:30:03 -07:00
|
|
|
|
static void
|
|
|
|
|
nxm_init(void)
|
|
|
|
|
{
|
|
|
|
|
static pthread_once_t once = PTHREAD_ONCE_INIT;
|
|
|
|
|
pthread_once(&once, nxm_do_init);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-15 15:06:23 -07:00
|
|
|
|
/* Consider the two value/mask pairs 'a_value/a_mask' and 'b_value/b_mask' as
|
|
|
|
|
* restrictions on a field's value. Then, this function initializes
|
|
|
|
|
* 'dst_value/dst_mask' such that it combines the restrictions of both pairs.
|
|
|
|
|
* This is not always possible, i.e. if one pair insists on a value of 0 in
|
|
|
|
|
* some bit and the other pair insists on a value of 1 in that bit. This
|
|
|
|
|
* function returns false in a case where the combined restriction is
|
|
|
|
|
* impossible (in which case 'dst_value/dst_mask' is not fully initialized),
|
|
|
|
|
* true otherwise.
|
|
|
|
|
*
|
|
|
|
|
* (As usually true for value/mask pairs in OVS, any 1-bit in a value must have
|
|
|
|
|
* a corresponding 1-bit in its mask.) */
|
|
|
|
|
bool
|
|
|
|
|
mf_subvalue_intersect(const union mf_subvalue *a_value,
|
|
|
|
|
const union mf_subvalue *a_mask,
|
|
|
|
|
const union mf_subvalue *b_value,
|
|
|
|
|
const union mf_subvalue *b_mask,
|
|
|
|
|
union mf_subvalue *dst_value,
|
|
|
|
|
union mf_subvalue *dst_mask)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(a_value->be64); i++) {
|
|
|
|
|
ovs_be64 av = a_value->be64[i];
|
|
|
|
|
ovs_be64 am = a_mask->be64[i];
|
|
|
|
|
ovs_be64 bv = b_value->be64[i];
|
|
|
|
|
ovs_be64 bm = b_mask->be64[i];
|
|
|
|
|
ovs_be64 *dv = &dst_value->be64[i];
|
|
|
|
|
ovs_be64 *dm = &dst_mask->be64[i];
|
|
|
|
|
|
|
|
|
|
if ((av ^ bv) & (am & bm)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
*dv = av | bv;
|
|
|
|
|
*dm = am | bm;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns the "number of bits" in 'v', e.g. 1 if only the lowest-order bit is
|
|
|
|
|
* set, 2 if the second-lowest-order bit is set, and so on. */
|
|
|
|
|
int
|
|
|
|
|
mf_subvalue_width(const union mf_subvalue *v)
|
|
|
|
|
{
|
|
|
|
|
return 1 + bitwise_rscan(v, sizeof *v, true, sizeof *v * 8 - 1, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* For positive 'n', shifts the bits in 'value' 'n' bits to the left, and for
|
|
|
|
|
* negative 'n', shifts the bits '-n' bits to the right. */
|
|
|
|
|
void
|
|
|
|
|
mf_subvalue_shift(union mf_subvalue *value, int n)
|
|
|
|
|
{
|
|
|
|
|
if (n) {
|
|
|
|
|
union mf_subvalue tmp;
|
|
|
|
|
memset(&tmp, 0, sizeof tmp);
|
|
|
|
|
|
|
|
|
|
if (n > 0 && n < 8 * sizeof tmp) {
|
|
|
|
|
bitwise_copy(value, sizeof *value, 0,
|
|
|
|
|
&tmp, sizeof tmp, n,
|
|
|
|
|
8 * sizeof tmp - n);
|
|
|
|
|
} else if (n < 0 && n > -8 * sizeof tmp) {
|
|
|
|
|
bitwise_copy(value, sizeof *value, -n,
|
|
|
|
|
&tmp, sizeof tmp, 0,
|
|
|
|
|
8 * sizeof tmp + n);
|
|
|
|
|
}
|
|
|
|
|
*value = tmp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
/* Appends a formatted representation of 'sv' to 's'. */
|
|
|
|
|
void
|
|
|
|
|
mf_subvalue_format(const union mf_subvalue *sv, struct ds *s)
|
|
|
|
|
{
|
|
|
|
|
ds_put_hex(s, sv, sizeof *sv);
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
/* Returns true if 'wc' wildcards all the bits in field 'mf', false if 'wc'
|
|
|
|
|
* specifies at least one bit in the field.
|
|
|
|
|
*
|
|
|
|
|
* The caller is responsible for ensuring that 'wc' corresponds to a flow that
|
|
|
|
|
* meets 'mf''s prerequisites. */
|
|
|
|
|
bool
|
|
|
|
|
mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
|
|
|
|
|
{
|
|
|
|
|
switch (mf->id) {
|
2014-03-04 14:20:19 -08:00
|
|
|
|
case MFF_DP_HASH:
|
|
|
|
|
return !wc->masks.dp_hash;
|
|
|
|
|
case MFF_RECIRC_ID:
|
|
|
|
|
return !wc->masks.recirc_id;
|
2017-06-23 16:47:57 +00:00
|
|
|
|
case MFF_PACKET_TYPE:
|
|
|
|
|
return !wc->masks.packet_type;
|
2015-01-11 13:25:24 -08:00
|
|
|
|
case MFF_CONJ_ID:
|
|
|
|
|
return !wc->masks.conj_id;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_SRC:
|
2013-05-09 15:24:16 +03:00
|
|
|
|
return !wc->masks.tunnel.ip_src;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_DST:
|
2013-05-09 15:24:16 +03:00
|
|
|
|
return !wc->masks.tunnel.ip_dst;
|
2015-12-04 12:36:50 -02:00
|
|
|
|
case MFF_TUN_IPV6_SRC:
|
|
|
|
|
return ipv6_mask_is_any(&wc->masks.tunnel.ipv6_src);
|
|
|
|
|
case MFF_TUN_IPV6_DST:
|
|
|
|
|
return ipv6_mask_is_any(&wc->masks.tunnel.ipv6_dst);
|
2013-05-09 15:24:16 +03:00
|
|
|
|
case MFF_TUN_ID:
|
2015-07-08 16:02:30 -07:00
|
|
|
|
return !wc->masks.tunnel.tun_id;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_TOS:
|
2015-07-08 16:02:30 -07:00
|
|
|
|
return !wc->masks.tunnel.ip_tos;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_TTL:
|
2015-07-08 16:02:30 -07:00
|
|
|
|
return !wc->masks.tunnel.ip_ttl;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_FLAGS:
|
2015-07-08 16:02:30 -07:00
|
|
|
|
return !(wc->masks.tunnel.flags & FLOW_TNL_PUB_F_MASK);
|
2015-02-14 15:13:17 +01:00
|
|
|
|
case MFF_TUN_GBP_ID:
|
|
|
|
|
return !wc->masks.tunnel.gbp_id;
|
|
|
|
|
case MFF_TUN_GBP_FLAGS:
|
|
|
|
|
return !wc->masks.tunnel.gbp_flags;
|
2015-08-11 18:41:37 -07:00
|
|
|
|
CASE_MFF_TUN_METADATA:
|
|
|
|
|
return !ULLONG_GET(wc->masks.tunnel.metadata.present.map,
|
|
|
|
|
mf->id - MFF_TUN_METADATA0);
|
2012-06-27 01:09:44 +12:00
|
|
|
|
case MFF_METADATA:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return !wc->masks.metadata;
|
2012-08-03 13:27:15 -07:00
|
|
|
|
case MFF_IN_PORT:
|
2013-05-19 15:44:53 +03:00
|
|
|
|
case MFF_IN_PORT_OXM:
|
2013-06-19 16:58:44 -07:00
|
|
|
|
return !wc->masks.in_port.ofp_port;
|
2012-11-29 14:36:49 -08:00
|
|
|
|
case MFF_SKB_PRIORITY:
|
|
|
|
|
return !wc->masks.skb_priority;
|
2013-08-06 12:57:13 -07:00
|
|
|
|
case MFF_PKT_MARK:
|
|
|
|
|
return !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
|
|
|
|
case MFF_CT_STATE:
|
|
|
|
|
return !wc->masks.ct_state;
|
|
|
|
|
case MFF_CT_ZONE:
|
|
|
|
|
return !wc->masks.ct_zone;
|
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
|
|
|
|
case MFF_CT_MARK:
|
|
|
|
|
return !wc->masks.ct_mark;
|
Add connection tracking label support.
This patch adds a new 128-bit metadata field to the connection tracking
interface. When a label 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_label" 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 label 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_label)),2
table=0,in_port=2,ct_state=-trk,tcp,action=ct(table=1)
table=1,in_port=2,ct_state=+trk,ct_label=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-10-13 11:13:10 -07:00
|
|
|
|
case MFF_CT_LABEL:
|
2016-05-03 18:20:51 -07:00
|
|
|
|
return ovs_u128_is_zero(wc->masks.ct_label);
|
2017-03-08 17:18:23 -08:00
|
|
|
|
case MFF_CT_NW_PROTO:
|
|
|
|
|
return !wc->masks.ct_nw_proto;
|
|
|
|
|
case MFF_CT_NW_SRC:
|
|
|
|
|
return !wc->masks.ct_nw_src;
|
|
|
|
|
case MFF_CT_NW_DST:
|
|
|
|
|
return !wc->masks.ct_nw_dst;
|
|
|
|
|
case MFF_CT_TP_SRC:
|
|
|
|
|
return !wc->masks.ct_tp_src;
|
|
|
|
|
case MFF_CT_TP_DST:
|
|
|
|
|
return !wc->masks.ct_tp_dst;
|
|
|
|
|
case MFF_CT_IPV6_SRC:
|
|
|
|
|
return ipv6_mask_is_any(&wc->masks.ct_ipv6_src);
|
|
|
|
|
case MFF_CT_IPV6_DST:
|
|
|
|
|
return ipv6_mask_is_any(&wc->masks.ct_ipv6_dst);
|
2012-06-27 07:23:25 -07:00
|
|
|
|
CASE_MFF_REGS:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return !wc->masks.regs[mf->id - MFF_REG0];
|
2014-07-28 09:50:37 -07:00
|
|
|
|
CASE_MFF_XREGS:
|
|
|
|
|
return !flow_get_xreg(&wc->masks, mf->id - MFF_XREG0);
|
2015-10-31 04:45:28 -07:00
|
|
|
|
CASE_MFF_XXREGS: {
|
|
|
|
|
ovs_u128 value = flow_get_xxreg(&wc->masks, mf->id - MFF_XXREG0);
|
|
|
|
|
return ovs_u128_is_zero(value);
|
|
|
|
|
}
|
2014-11-03 14:24:01 -08:00
|
|
|
|
case MFF_ACTSET_OUTPUT:
|
|
|
|
|
return !wc->masks.actset_output;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2012-05-29 00:38:21 +12:00
|
|
|
|
case MFF_ETH_SRC:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return eth_addr_is_zero(wc->masks.dl_src);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_ETH_DST:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return eth_addr_is_zero(wc->masks.dl_dst);
|
2012-06-18 13:33:13 -07:00
|
|
|
|
case MFF_ETH_TYPE:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return !wc->masks.dl_type;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2012-07-19 09:21:49 -07:00
|
|
|
|
case MFF_ARP_SHA:
|
|
|
|
|
case MFF_ND_SLL:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return eth_addr_is_zero(wc->masks.arp_sha);
|
2012-07-19 09:21:49 -07:00
|
|
|
|
|
|
|
|
|
case MFF_ARP_THA:
|
|
|
|
|
case MFF_ND_TLL:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return eth_addr_is_zero(wc->masks.arp_tha);
|
2012-07-19 09:21:49 -07:00
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_VLAN_TCI:
|
2017-03-01 17:47:59 -05:00
|
|
|
|
return !wc->masks.vlans[0].tci;
|
2012-07-22 23:36:41 -07:00
|
|
|
|
case MFF_DL_VLAN:
|
2017-03-01 17:47:59 -05:00
|
|
|
|
return !(wc->masks.vlans[0].tci & htons(VLAN_VID_MASK));
|
2012-07-22 23:20:22 -07:00
|
|
|
|
case MFF_VLAN_VID:
|
2017-03-01 17:47:59 -05:00
|
|
|
|
return !(wc->masks.vlans[0].tci & htons(VLAN_VID_MASK | VLAN_CFI));
|
2012-07-22 23:36:41 -07:00
|
|
|
|
case MFF_DL_VLAN_PCP:
|
2012-07-22 23:20:22 -07:00
|
|
|
|
case MFF_VLAN_PCP:
|
2017-03-01 17:47:59 -05:00
|
|
|
|
return !(wc->masks.vlans[0].tci & htons(VLAN_PCP_MASK));
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2013-01-25 16:22:07 +09:00
|
|
|
|
case MFF_MPLS_LABEL:
|
2014-02-04 10:32:35 -08:00
|
|
|
|
return !(wc->masks.mpls_lse[0] & htonl(MPLS_LABEL_MASK));
|
2013-01-25 16:22:07 +09:00
|
|
|
|
case MFF_MPLS_TC:
|
2014-10-06 14:12:57 -07:00
|
|
|
|
return !(wc->masks.mpls_lse[0] & htonl(MPLS_TC_MASK));
|
2013-01-25 16:22:07 +09:00
|
|
|
|
case MFF_MPLS_BOS:
|
2014-10-06 14:12:57 -07:00
|
|
|
|
return !(wc->masks.mpls_lse[0] & htonl(MPLS_BOS_MASK));
|
2016-03-07 20:46:48 -08:00
|
|
|
|
case MFF_MPLS_TTL:
|
|
|
|
|
return !(wc->masks.mpls_lse[0] & htonl(MPLS_TTL_MASK));
|
2013-01-25 16:22:07 +09:00
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_IPV4_SRC:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return !wc->masks.nw_src;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_IPV4_DST:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return !wc->masks.nw_dst;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
|
|
|
|
case MFF_IPV6_SRC:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return ipv6_mask_is_any(&wc->masks.ipv6_src);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_IPV6_DST:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return ipv6_mask_is_any(&wc->masks.ipv6_dst);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2012-07-18 12:02:19 +09:00
|
|
|
|
case MFF_IPV6_LABEL:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return !wc->masks.ipv6_label;
|
2012-07-18 12:02:19 +09:00
|
|
|
|
|
2012-06-18 14:12:52 -07:00
|
|
|
|
case MFF_IP_PROTO:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return !wc->masks.nw_proto;
|
2012-06-18 14:11:13 -07:00
|
|
|
|
case MFF_IP_DSCP:
|
2013-04-18 09:40:48 -07:00
|
|
|
|
case MFF_IP_DSCP_SHIFTED:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return !(wc->masks.nw_tos & IP_DSCP_MASK);
|
2012-06-18 14:11:13 -07:00
|
|
|
|
case MFF_IP_ECN:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return !(wc->masks.nw_tos & IP_ECN_MASK);
|
2012-06-18 11:36:03 -07:00
|
|
|
|
case MFF_IP_TTL:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return !wc->masks.nw_ttl;
|
2012-06-18 14:11:13 -07:00
|
|
|
|
|
2012-04-25 15:48:40 -07:00
|
|
|
|
case MFF_ND_TARGET:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return ipv6_mask_is_any(&wc->masks.nd_target);
|
2012-04-25 15:48:40 -07: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
|
|
|
|
case MFF_IP_FRAG:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return !(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
|
|
|
|
|
2012-06-18 14:12:52 -07:00
|
|
|
|
case MFF_ARP_OP:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return !wc->masks.nw_proto;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_ARP_SPA:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return !wc->masks.nw_src;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_ARP_TPA:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return !wc->masks.nw_dst;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2012-01-27 17:16:05 -08:00
|
|
|
|
case MFF_TCP_SRC:
|
|
|
|
|
case MFF_UDP_SRC:
|
2013-08-22 20:24:45 +12:00
|
|
|
|
case MFF_SCTP_SRC:
|
2012-01-27 17:16:05 -08:00
|
|
|
|
case MFF_ICMPV4_TYPE:
|
|
|
|
|
case MFF_ICMPV6_TYPE:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return !wc->masks.tp_src;
|
2012-01-27 17:16:05 -08:00
|
|
|
|
case MFF_TCP_DST:
|
|
|
|
|
case MFF_UDP_DST:
|
2013-08-22 20:24:45 +12:00
|
|
|
|
case MFF_SCTP_DST:
|
2012-01-27 17:16:05 -08:00
|
|
|
|
case MFF_ICMPV4_CODE:
|
|
|
|
|
case MFF_ICMPV6_CODE:
|
2012-08-07 13:38:38 -07:00
|
|
|
|
return !wc->masks.tp_dst;
|
2013-10-28 13:54:40 -07:00
|
|
|
|
case MFF_TCP_FLAGS:
|
|
|
|
|
return !wc->masks.tcp_flags;
|
2012-01-27 17:16:05 -08:00
|
|
|
|
|
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
|
|
|
|
case MFF_NSH_FLAGS:
|
|
|
|
|
return !wc->masks.nsh.flags;
|
|
|
|
|
case MFF_NSH_MDTYPE:
|
|
|
|
|
return !wc->masks.nsh.mdtype;
|
|
|
|
|
case MFF_NSH_NP:
|
|
|
|
|
return !wc->masks.nsh.np;
|
|
|
|
|
case MFF_NSH_SPI:
|
|
|
|
|
return !wc->masks.nsh.spi;
|
|
|
|
|
case MFF_NSH_SI:
|
|
|
|
|
return !wc->masks.nsh.si;
|
|
|
|
|
case MFF_NSH_C1:
|
|
|
|
|
case MFF_NSH_C2:
|
|
|
|
|
case MFF_NSH_C3:
|
|
|
|
|
case MFF_NSH_C4:
|
|
|
|
|
return !wc->masks.nsh.c[mf->id - MFF_NSH_C1];
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_N_IDS:
|
|
|
|
|
default:
|
2013-12-17 10:32:12 -08:00
|
|
|
|
OVS_NOT_REACHED();
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Initializes 'mask' with the wildcard bit pattern for field 'mf' within 'wc'.
|
|
|
|
|
* Each bit in 'mask' will be set to 1 if the bit is significant for matching
|
|
|
|
|
* purposes, or to 0 if it is wildcarded.
|
|
|
|
|
*
|
|
|
|
|
* The caller is responsible for ensuring that 'wc' corresponds to a flow that
|
|
|
|
|
* meets 'mf''s prerequisites. */
|
|
|
|
|
void
|
|
|
|
|
mf_get_mask(const struct mf_field *mf, const struct flow_wildcards *wc,
|
|
|
|
|
union mf_value *mask)
|
|
|
|
|
{
|
2012-12-18 09:45:02 -08:00
|
|
|
|
mf_get_value(mf, &wc->masks, mask);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Tests whether 'mask' is a valid wildcard bit pattern for 'mf'. Returns true
|
|
|
|
|
* if the mask is valid, false otherwise. */
|
|
|
|
|
bool
|
|
|
|
|
mf_is_mask_valid(const struct mf_field *mf, const union mf_value *mask)
|
|
|
|
|
{
|
|
|
|
|
switch (mf->maskable) {
|
|
|
|
|
case MFM_NONE:
|
2014-09-05 15:44:19 -07:00
|
|
|
|
return (is_all_zeros(mask, mf->n_bytes) ||
|
|
|
|
|
is_all_ones(mask, mf->n_bytes));
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
|
|
|
|
case MFM_FULLY:
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-17 10:32:12 -08:00
|
|
|
|
OVS_NOT_REACHED();
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
2016-07-29 16:52:03 -07:00
|
|
|
|
/* Returns true if 'flow' meets the prerequisites for 'mf', false otherwise.
|
2017-03-08 17:18:22 -08:00
|
|
|
|
* If a non-NULL 'mask' is passed, zero-valued matches can also be verified.
|
2016-07-29 16:52:03 -07:00
|
|
|
|
* Sets inspected bits in 'wc', if non-NULL. */
|
2017-03-08 17:18:22 -08:00
|
|
|
|
static bool
|
|
|
|
|
mf_are_prereqs_ok__(const struct mf_field *mf, const struct flow *flow,
|
2017-03-08 17:18:23 -08:00
|
|
|
|
const struct flow_wildcards *mask,
|
2017-03-08 17:18:22 -08:00
|
|
|
|
struct flow_wildcards *wc)
|
2011-09-12 12:11:50 -07:00
|
|
|
|
{
|
2017-06-23 16:47:57 +00:00
|
|
|
|
ovs_be16 dl_type = get_dl_type(flow);
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
switch (mf->prereqs) {
|
|
|
|
|
case MFP_NONE:
|
|
|
|
|
return true;
|
2017-06-02 16:16:17 +00:00
|
|
|
|
case MFP_ETHERNET:
|
|
|
|
|
return is_ethernet(flow, wc);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFP_ARP:
|
2017-06-23 16:47:57 +00:00
|
|
|
|
return (dl_type == htons(ETH_TYPE_ARP) ||
|
|
|
|
|
dl_type == htons(ETH_TYPE_RARP));
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFP_IPV4:
|
2017-06-23 16:47:57 +00:00
|
|
|
|
return dl_type == htons(ETH_TYPE_IP);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFP_IPV6:
|
2017-06-23 16:47:57 +00:00
|
|
|
|
return dl_type == htons(ETH_TYPE_IPV6);
|
2012-07-23 11:36:44 +09:00
|
|
|
|
case MFP_VLAN_VID:
|
2016-07-29 16:52:03 -07:00
|
|
|
|
return is_vlan(flow, wc);
|
2013-01-25 16:22:07 +09:00
|
|
|
|
case MFP_MPLS:
|
2017-06-23 16:47:57 +00:00
|
|
|
|
return eth_type_mpls(dl_type);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFP_IP_ANY:
|
|
|
|
|
return is_ip_any(flow);
|
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
|
|
|
|
case MFP_NSH:
|
|
|
|
|
return dl_type == htons(ETH_TYPE_NSH);
|
2017-03-08 17:18:23 -08:00
|
|
|
|
case MFP_CT_VALID:
|
|
|
|
|
return is_ct_valid(flow, mask, wc);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFP_TCP:
|
2017-03-08 17:18:22 -08:00
|
|
|
|
/* Matching !FRAG_LATER is not enforced (mask is not checked). */
|
2016-07-29 16:52:03 -07:00
|
|
|
|
return is_tcp(flow, wc) && !(flow->nw_frag & FLOW_NW_FRAG_LATER);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFP_UDP:
|
2016-07-29 16:52:03 -07:00
|
|
|
|
return is_udp(flow, wc) && !(flow->nw_frag & FLOW_NW_FRAG_LATER);
|
2013-08-22 20:24:45 +12:00
|
|
|
|
case MFP_SCTP:
|
2016-07-29 16:52:03 -07:00
|
|
|
|
return is_sctp(flow, wc) && !(flow->nw_frag & FLOW_NW_FRAG_LATER);
|
2011-10-22 13:11:48 -07:00
|
|
|
|
case MFP_ICMPV4:
|
2016-07-29 16:52:03 -07:00
|
|
|
|
return is_icmpv4(flow, wc);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFP_ICMPV6:
|
2016-07-29 16:52:03 -07:00
|
|
|
|
return is_icmpv6(flow, wc);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFP_ND:
|
2016-07-29 16:52:03 -07:00
|
|
|
|
return is_nd(flow, wc);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFP_ND_SOLICIT:
|
2016-07-29 16:52:03 -07:00
|
|
|
|
return is_nd(flow, wc) && flow->tp_src == htons(ND_NEIGHBOR_SOLICIT);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFP_ND_ADVERT:
|
2016-07-29 16:52:03 -07:00
|
|
|
|
return is_nd(flow, wc) && flow->tp_src == htons(ND_NEIGHBOR_ADVERT);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
2013-12-17 10:32:12 -08:00
|
|
|
|
OVS_NOT_REACHED();
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-08 17:18:22 -08:00
|
|
|
|
/* Returns true if 'flow' meets the prerequisites for 'mf', false otherwise.
|
|
|
|
|
* Sets inspected bits in 'wc', if non-NULL. */
|
|
|
|
|
bool
|
|
|
|
|
mf_are_prereqs_ok(const struct mf_field *mf, const struct flow *flow,
|
|
|
|
|
struct flow_wildcards *wc)
|
|
|
|
|
{
|
|
|
|
|
return mf_are_prereqs_ok__(mf, flow, NULL, wc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns true if 'match' meets the prerequisites for 'mf', false otherwise.
|
|
|
|
|
*/
|
|
|
|
|
bool
|
|
|
|
|
mf_are_match_prereqs_ok(const struct mf_field *mf, const struct match *match)
|
|
|
|
|
{
|
|
|
|
|
return mf_are_prereqs_ok__(mf, &match->flow, &match->wc, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
/* Returns true if 'value' may be a valid value *as part of a masked match*,
|
|
|
|
|
* false otherwise.
|
|
|
|
|
*
|
|
|
|
|
* A value is not rejected just because it is not valid for the field in
|
|
|
|
|
* question, but only if it doesn't make sense to test the bits in question at
|
|
|
|
|
* all. For example, the MFF_VLAN_TCI field will never have a nonzero value
|
|
|
|
|
* without the VLAN_CFI bit being set, but we can't reject those values because
|
|
|
|
|
* it is still legitimate to test just for those bits (see the documentation
|
2016-09-30 15:31:03 -03:00
|
|
|
|
* for NXM_OF_VLAN_TCI in meta-flow.h). On the other hand, there is never a
|
2011-11-02 23:34:15 -07:00
|
|
|
|
* reason to set the low bit of MFF_IP_DSCP to 1, so we reject that. */
|
2011-09-12 12:11:50 -07:00
|
|
|
|
bool
|
|
|
|
|
mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
|
|
|
|
|
{
|
|
|
|
|
switch (mf->id) {
|
2014-03-04 14:20:19 -08:00
|
|
|
|
case MFF_DP_HASH:
|
|
|
|
|
case MFF_RECIRC_ID:
|
2017-06-23 16:47:57 +00:00
|
|
|
|
case MFF_PACKET_TYPE:
|
2015-01-11 13:25:24 -08:00
|
|
|
|
case MFF_CONJ_ID:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_TUN_ID:
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_SRC:
|
|
|
|
|
case MFF_TUN_DST:
|
2015-12-04 12:36:50 -02:00
|
|
|
|
case MFF_TUN_IPV6_SRC:
|
|
|
|
|
case MFF_TUN_IPV6_DST:
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_TOS:
|
|
|
|
|
case MFF_TUN_TTL:
|
2015-02-14 15:13:17 +01:00
|
|
|
|
case MFF_TUN_GBP_ID:
|
|
|
|
|
case MFF_TUN_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
|
|
|
|
CASE_MFF_TUN_METADATA:
|
2012-06-27 01:09:44 +12:00
|
|
|
|
case MFF_METADATA:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_IN_PORT:
|
2012-11-29 14:36:49 -08:00
|
|
|
|
case MFF_SKB_PRIORITY:
|
2013-08-06 12:57:13 -07:00
|
|
|
|
case MFF_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
|
|
|
|
case MFF_CT_ZONE:
|
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
|
|
|
|
case MFF_CT_MARK:
|
Add connection tracking label support.
This patch adds a new 128-bit metadata field to the connection tracking
interface. When a label 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_label" 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 label 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_label)),2
table=0,in_port=2,ct_state=-trk,tcp,action=ct(table=1)
table=1,in_port=2,ct_state=+trk,ct_label=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-10-13 11:13:10 -07:00
|
|
|
|
case MFF_CT_LABEL:
|
2017-03-08 17:18:23 -08:00
|
|
|
|
case MFF_CT_NW_PROTO:
|
|
|
|
|
case MFF_CT_NW_SRC:
|
|
|
|
|
case MFF_CT_NW_DST:
|
|
|
|
|
case MFF_CT_IPV6_SRC:
|
|
|
|
|
case MFF_CT_IPV6_DST:
|
|
|
|
|
case MFF_CT_TP_SRC:
|
|
|
|
|
case MFF_CT_TP_DST:
|
2012-06-27 07:23:25 -07:00
|
|
|
|
CASE_MFF_REGS:
|
2014-07-28 09:50:37 -07:00
|
|
|
|
CASE_MFF_XREGS:
|
2015-10-31 04:45:28 -07:00
|
|
|
|
CASE_MFF_XXREGS:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_ETH_SRC:
|
|
|
|
|
case MFF_ETH_DST:
|
|
|
|
|
case MFF_ETH_TYPE:
|
|
|
|
|
case MFF_VLAN_TCI:
|
2016-03-07 20:46:48 -08:00
|
|
|
|
case MFF_MPLS_TTL:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_IPV4_SRC:
|
|
|
|
|
case MFF_IPV4_DST:
|
|
|
|
|
case MFF_IPV6_SRC:
|
|
|
|
|
case MFF_IPV6_DST:
|
|
|
|
|
case MFF_IP_PROTO:
|
2011-11-05 15:48:12 -07:00
|
|
|
|
case MFF_IP_TTL:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_ARP_SPA:
|
|
|
|
|
case MFF_ARP_TPA:
|
|
|
|
|
case MFF_ARP_SHA:
|
|
|
|
|
case MFF_ARP_THA:
|
|
|
|
|
case MFF_TCP_SRC:
|
|
|
|
|
case MFF_TCP_DST:
|
|
|
|
|
case MFF_UDP_SRC:
|
|
|
|
|
case MFF_UDP_DST:
|
2013-08-22 20:24:45 +12:00
|
|
|
|
case MFF_SCTP_SRC:
|
|
|
|
|
case MFF_SCTP_DST:
|
2011-10-22 13:11:48 -07:00
|
|
|
|
case MFF_ICMPV4_TYPE:
|
|
|
|
|
case MFF_ICMPV4_CODE:
|
|
|
|
|
case MFF_ICMPV6_TYPE:
|
|
|
|
|
case MFF_ICMPV6_CODE:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_ND_TARGET:
|
|
|
|
|
case MFF_ND_SLL:
|
|
|
|
|
case MFF_ND_TLL:
|
|
|
|
|
return true;
|
|
|
|
|
|
2014-11-03 14:24:01 -08:00
|
|
|
|
case MFF_IN_PORT_OXM:
|
|
|
|
|
case MFF_ACTSET_OUTPUT: {
|
2013-06-19 16:58:44 -07:00
|
|
|
|
ofp_port_t port;
|
2013-05-19 15:44:53 +03:00
|
|
|
|
return !ofputil_port_from_ofp11(value->be32, &port);
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-02 23:34:15 -07:00
|
|
|
|
case MFF_IP_DSCP:
|
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
|
|
|
|
return !(value->u8 & ~IP_DSCP_MASK);
|
2013-04-18 09:40:48 -07:00
|
|
|
|
case MFF_IP_DSCP_SHIFTED:
|
|
|
|
|
return !(value->u8 & (~IP_DSCP_MASK >> 2));
|
2011-11-02 23:34:15 -07:00
|
|
|
|
case MFF_IP_ECN:
|
|
|
|
|
return !(value->u8 & ~IP_ECN_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
|
|
|
|
case MFF_IP_FRAG:
|
2011-11-09 17:10:27 -08:00
|
|
|
|
return !(value->u8 & ~FLOW_NW_FRAG_MASK);
|
2013-10-28 13:54:40 -07:00
|
|
|
|
case MFF_TCP_FLAGS:
|
|
|
|
|
return !(value->be16 & ~htons(0x0fff));
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
|
|
|
|
case MFF_ARP_OP:
|
|
|
|
|
return !(value->be16 & htons(0xff00));
|
|
|
|
|
|
2012-07-22 23:36:41 -07:00
|
|
|
|
case MFF_DL_VLAN:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
return !(value->be16 & htons(VLAN_CFI | VLAN_PCP_MASK));
|
2012-07-22 23:20:22 -07:00
|
|
|
|
case MFF_VLAN_VID:
|
|
|
|
|
return !(value->be16 & htons(VLAN_PCP_MASK));
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2012-07-22 23:36:41 -07:00
|
|
|
|
case MFF_DL_VLAN_PCP:
|
2012-07-22 23:20:22 -07:00
|
|
|
|
case MFF_VLAN_PCP:
|
2012-06-27 13:26:57 +09:00
|
|
|
|
return !(value->u8 & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT));
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2011-11-01 15:57:56 -07:00
|
|
|
|
case MFF_IPV6_LABEL:
|
|
|
|
|
return !(value->be32 & ~htonl(IPV6_LABEL_MASK));
|
|
|
|
|
|
2013-01-25 16:22:07 +09:00
|
|
|
|
case MFF_MPLS_LABEL:
|
|
|
|
|
return !(value->be32 & ~htonl(MPLS_LABEL_MASK >> MPLS_LABEL_SHIFT));
|
|
|
|
|
|
|
|
|
|
case MFF_MPLS_TC:
|
|
|
|
|
return !(value->u8 & ~(MPLS_TC_MASK >> MPLS_TC_SHIFT));
|
|
|
|
|
|
|
|
|
|
case MFF_MPLS_BOS:
|
|
|
|
|
return !(value->u8 & ~(MPLS_BOS_MASK >> MPLS_BOS_SHIFT));
|
|
|
|
|
|
2015-07-08 16:02:30 -07:00
|
|
|
|
case MFF_TUN_FLAGS:
|
|
|
|
|
return !(value->be16 & ~htons(FLOW_TNL_PUB_F_MASK));
|
|
|
|
|
|
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
|
|
|
|
case MFF_CT_STATE:
|
|
|
|
|
return !(value->be32 & ~htonl(CS_SUPPORTED_MASK));
|
|
|
|
|
|
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
|
|
|
|
case MFF_NSH_FLAGS:
|
|
|
|
|
return true;
|
|
|
|
|
case MFF_NSH_MDTYPE:
|
|
|
|
|
return (value->u8 == 1 || value->u8 == 2);
|
|
|
|
|
case MFF_NSH_NP:
|
|
|
|
|
return true;
|
|
|
|
|
case MFF_NSH_SPI:
|
|
|
|
|
return !(value->be32 & htonl(0xFF000000));
|
|
|
|
|
case MFF_NSH_SI:
|
|
|
|
|
case MFF_NSH_C1:
|
|
|
|
|
case MFF_NSH_C2:
|
|
|
|
|
case MFF_NSH_C3:
|
|
|
|
|
case MFF_NSH_C4:
|
|
|
|
|
return true;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_N_IDS:
|
|
|
|
|
default:
|
2013-12-17 10:32:12 -08:00
|
|
|
|
OVS_NOT_REACHED();
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Copies the value of field 'mf' from 'flow' into 'value'. The caller is
|
|
|
|
|
* responsible for ensuring that 'flow' meets 'mf''s prerequisites. */
|
|
|
|
|
void
|
|
|
|
|
mf_get_value(const struct mf_field *mf, const struct flow *flow,
|
|
|
|
|
union mf_value *value)
|
|
|
|
|
{
|
|
|
|
|
switch (mf->id) {
|
2014-03-04 14:20:19 -08:00
|
|
|
|
case MFF_DP_HASH:
|
|
|
|
|
value->be32 = htonl(flow->dp_hash);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_RECIRC_ID:
|
|
|
|
|
value->be32 = htonl(flow->recirc_id);
|
|
|
|
|
break;
|
2017-06-23 16:47:57 +00:00
|
|
|
|
case MFF_PACKET_TYPE:
|
|
|
|
|
value->be32 = flow->packet_type;
|
|
|
|
|
break;
|
2015-01-11 13:25:24 -08:00
|
|
|
|
case MFF_CONJ_ID:
|
|
|
|
|
value->be32 = htonl(flow->conj_id);
|
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_TUN_ID:
|
2012-09-13 20:11:08 -07:00
|
|
|
|
value->be64 = flow->tunnel.tun_id;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_SRC:
|
|
|
|
|
value->be32 = flow->tunnel.ip_src;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_DST:
|
|
|
|
|
value->be32 = flow->tunnel.ip_dst;
|
|
|
|
|
break;
|
2015-12-04 12:36:50 -02:00
|
|
|
|
case MFF_TUN_IPV6_SRC:
|
|
|
|
|
value->ipv6 = flow->tunnel.ipv6_src;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_IPV6_DST:
|
|
|
|
|
value->ipv6 = flow->tunnel.ipv6_dst;
|
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_FLAGS:
|
2015-07-08 16:02:30 -07:00
|
|
|
|
value->be16 = htons(flow->tunnel.flags & FLOW_TNL_PUB_F_MASK);
|
2012-11-21 18:51:36 -08:00
|
|
|
|
break;
|
2015-02-14 15:13:17 +01:00
|
|
|
|
case MFF_TUN_GBP_ID:
|
|
|
|
|
value->be16 = flow->tunnel.gbp_id;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_GBP_FLAGS:
|
|
|
|
|
value->u8 = flow->tunnel.gbp_flags;
|
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_TTL:
|
|
|
|
|
value->u8 = flow->tunnel.ip_ttl;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_TOS:
|
|
|
|
|
value->u8 = flow->tunnel.ip_tos;
|
|
|
|
|
break;
|
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
|
|
|
|
CASE_MFF_TUN_METADATA:
|
2015-06-29 18:01:59 -07:00
|
|
|
|
tun_metadata_read(&flow->tunnel, mf, value);
|
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
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
|
2012-06-27 01:09:44 +12:00
|
|
|
|
case MFF_METADATA:
|
|
|
|
|
value->be64 = flow->metadata;
|
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
|
|
|
|
case MFF_IN_PORT:
|
2013-06-19 16:58:44 -07:00
|
|
|
|
value->be16 = htons(ofp_to_u16(flow->in_port.ofp_port));
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
2013-05-19 15:44:53 +03:00
|
|
|
|
case MFF_IN_PORT_OXM:
|
2013-06-19 16:58:44 -07:00
|
|
|
|
value->be32 = ofputil_port_to_ofp11(flow->in_port.ofp_port);
|
2013-05-19 15:44:53 +03:00
|
|
|
|
break;
|
2014-11-03 14:24:01 -08:00
|
|
|
|
case MFF_ACTSET_OUTPUT:
|
|
|
|
|
value->be32 = ofputil_port_to_ofp11(flow->actset_output);
|
|
|
|
|
break;
|
2013-05-19 15:44:53 +03:00
|
|
|
|
|
2012-11-29 14:36:49 -08:00
|
|
|
|
case MFF_SKB_PRIORITY:
|
2012-12-18 15:54:29 -08:00
|
|
|
|
value->be32 = htonl(flow->skb_priority);
|
2012-11-29 14:36:49 -08:00
|
|
|
|
break;
|
|
|
|
|
|
2013-08-06 12:57:13 -07:00
|
|
|
|
case MFF_PKT_MARK:
|
|
|
|
|
value->be32 = htonl(flow->pkt_mark);
|
2012-11-29 14:36:49 -08:00
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_CT_STATE:
|
|
|
|
|
value->be32 = htonl(flow->ct_state);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_ZONE:
|
|
|
|
|
value->be16 = htons(flow->ct_zone);
|
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_CT_MARK:
|
|
|
|
|
value->be32 = htonl(flow->ct_mark);
|
|
|
|
|
break;
|
|
|
|
|
|
Add connection tracking label support.
This patch adds a new 128-bit metadata field to the connection tracking
interface. When a label 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_label" 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 label 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_label)),2
table=0,in_port=2,ct_state=-trk,tcp,action=ct(table=1)
table=1,in_port=2,ct_state=+trk,ct_label=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-10-13 11:13:10 -07:00
|
|
|
|
case MFF_CT_LABEL:
|
2015-10-31 03:12:38 -07:00
|
|
|
|
value->be128 = hton128(flow->ct_label);
|
Add connection tracking label support.
This patch adds a new 128-bit metadata field to the connection tracking
interface. When a label 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_label" 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 label 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_label)),2
table=0,in_port=2,ct_state=-trk,tcp,action=ct(table=1)
table=1,in_port=2,ct_state=+trk,ct_label=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-10-13 11:13:10 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2017-03-08 17:18:23 -08:00
|
|
|
|
case MFF_CT_NW_PROTO:
|
|
|
|
|
value->u8 = flow->ct_nw_proto;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_NW_SRC:
|
|
|
|
|
value->be32 = flow->ct_nw_src;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_NW_DST:
|
|
|
|
|
value->be32 = flow->ct_nw_dst;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_IPV6_SRC:
|
|
|
|
|
value->ipv6 = flow->ct_ipv6_src;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_IPV6_DST:
|
|
|
|
|
value->ipv6 = flow->ct_ipv6_dst;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_TP_SRC:
|
|
|
|
|
value->be16 = flow->ct_tp_src;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_TP_DST:
|
|
|
|
|
value->be16 = flow->ct_tp_dst;
|
|
|
|
|
break;
|
|
|
|
|
|
2012-06-27 07:23:25 -07:00
|
|
|
|
CASE_MFF_REGS:
|
2011-10-11 06:58:49 -07:00
|
|
|
|
value->be32 = htonl(flow->regs[mf->id - MFF_REG0]);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2014-07-28 09:50:37 -07:00
|
|
|
|
CASE_MFF_XREGS:
|
|
|
|
|
value->be64 = htonll(flow_get_xreg(flow, mf->id - MFF_XREG0));
|
|
|
|
|
break;
|
|
|
|
|
|
2015-10-31 04:45:28 -07:00
|
|
|
|
CASE_MFF_XXREGS:
|
|
|
|
|
value->be128 = hton128(flow_get_xxreg(flow, mf->id - MFF_XXREG0));
|
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_ETH_SRC:
|
2015-08-28 14:55:11 -07:00
|
|
|
|
value->mac = flow->dl_src;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ETH_DST:
|
2015-08-28 14:55:11 -07:00
|
|
|
|
value->mac = flow->dl_dst;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ETH_TYPE:
|
|
|
|
|
value->be16 = flow->dl_type;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_VLAN_TCI:
|
2017-03-01 17:47:59 -05:00
|
|
|
|
value->be16 = flow->vlans[0].tci;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2012-07-22 23:36:41 -07:00
|
|
|
|
case MFF_DL_VLAN:
|
2017-03-01 17:47:59 -05:00
|
|
|
|
value->be16 = flow->vlans[0].tci & htons(VLAN_VID_MASK);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
2012-07-22 23:20:22 -07:00
|
|
|
|
case MFF_VLAN_VID:
|
2017-03-01 17:47:59 -05:00
|
|
|
|
value->be16 = flow->vlans[0].tci & htons(VLAN_VID_MASK | VLAN_CFI);
|
2012-07-22 23:20:22 -07:00
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2012-07-22 23:36:41 -07:00
|
|
|
|
case MFF_DL_VLAN_PCP:
|
2012-07-22 23:20:22 -07:00
|
|
|
|
case MFF_VLAN_PCP:
|
2017-03-01 17:47:59 -05:00
|
|
|
|
value->u8 = vlan_tci_to_pcp(flow->vlans[0].tci);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2013-01-25 16:22:07 +09:00
|
|
|
|
case MFF_MPLS_LABEL:
|
2014-02-04 10:32:35 -08:00
|
|
|
|
value->be32 = htonl(mpls_lse_to_label(flow->mpls_lse[0]));
|
2013-01-25 16:22:07 +09:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_MPLS_TC:
|
2014-02-04 10:32:35 -08:00
|
|
|
|
value->u8 = mpls_lse_to_tc(flow->mpls_lse[0]);
|
2013-01-25 16:22:07 +09:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_MPLS_BOS:
|
2014-02-04 10:32:35 -08:00
|
|
|
|
value->u8 = mpls_lse_to_bos(flow->mpls_lse[0]);
|
|
|
|
|
break;
|
2013-01-25 16:22:07 +09:00
|
|
|
|
|
2016-03-07 20:46:48 -08:00
|
|
|
|
case MFF_MPLS_TTL:
|
|
|
|
|
value->u8 = mpls_lse_to_ttl(flow->mpls_lse[0]);
|
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_IPV4_SRC:
|
|
|
|
|
value->be32 = flow->nw_src;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IPV4_DST:
|
|
|
|
|
value->be32 = flow->nw_dst;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IPV6_SRC:
|
|
|
|
|
value->ipv6 = flow->ipv6_src;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IPV6_DST:
|
|
|
|
|
value->ipv6 = flow->ipv6_dst;
|
|
|
|
|
break;
|
|
|
|
|
|
2011-11-01 15:57:56 -07:00
|
|
|
|
case MFF_IPV6_LABEL:
|
|
|
|
|
value->be32 = flow->ipv6_label;
|
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_IP_PROTO:
|
|
|
|
|
value->u8 = flow->nw_proto;
|
|
|
|
|
break;
|
|
|
|
|
|
2011-11-02 23:34:15 -07:00
|
|
|
|
case MFF_IP_DSCP:
|
2011-11-09 17:10:27 -08:00
|
|
|
|
value->u8 = flow->nw_tos & IP_DSCP_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
|
|
|
|
break;
|
|
|
|
|
|
2013-04-18 09:40:48 -07:00
|
|
|
|
case MFF_IP_DSCP_SHIFTED:
|
|
|
|
|
value->u8 = flow->nw_tos >> 2;
|
|
|
|
|
break;
|
|
|
|
|
|
2011-11-02 23:34:15 -07:00
|
|
|
|
case MFF_IP_ECN:
|
2011-11-09 17:10:27 -08:00
|
|
|
|
value->u8 = flow->nw_tos & IP_ECN_MASK;
|
2011-11-02 23:34:15 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2011-11-05 15:48:12 -07:00
|
|
|
|
case MFF_IP_TTL:
|
|
|
|
|
value->u8 = flow->nw_ttl;
|
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_IP_FRAG:
|
2011-11-09 17:10:27 -08:00
|
|
|
|
value->u8 = flow->nw_frag;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_OP:
|
|
|
|
|
value->be16 = htons(flow->nw_proto);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_SPA:
|
|
|
|
|
value->be32 = flow->nw_src;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_TPA:
|
|
|
|
|
value->be32 = flow->nw_dst;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_SHA:
|
|
|
|
|
case MFF_ND_SLL:
|
2015-08-28 14:55:11 -07:00
|
|
|
|
value->mac = flow->arp_sha;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_THA:
|
|
|
|
|
case MFF_ND_TLL:
|
2015-08-28 14:55:11 -07:00
|
|
|
|
value->mac = flow->arp_tha;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_TCP_SRC:
|
|
|
|
|
case MFF_UDP_SRC:
|
2013-08-22 20:24:45 +12:00
|
|
|
|
case MFF_SCTP_SRC:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
value->be16 = flow->tp_src;
|
|
|
|
|
break;
|
|
|
|
|
|
2012-07-12 11:07:15 +12:00
|
|
|
|
case MFF_TCP_DST:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_UDP_DST:
|
2013-08-22 20:24:45 +12:00
|
|
|
|
case MFF_SCTP_DST:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
value->be16 = flow->tp_dst;
|
|
|
|
|
break;
|
|
|
|
|
|
2013-10-28 13:54:40 -07:00
|
|
|
|
case MFF_TCP_FLAGS:
|
|
|
|
|
value->be16 = flow->tcp_flags;
|
|
|
|
|
break;
|
|
|
|
|
|
2011-10-22 13:11:48 -07:00
|
|
|
|
case MFF_ICMPV4_TYPE:
|
|
|
|
|
case MFF_ICMPV6_TYPE:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
value->u8 = ntohs(flow->tp_src);
|
|
|
|
|
break;
|
|
|
|
|
|
2011-10-22 13:11:48 -07:00
|
|
|
|
case MFF_ICMPV4_CODE:
|
|
|
|
|
case MFF_ICMPV6_CODE:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
value->u8 = ntohs(flow->tp_dst);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ND_TARGET:
|
|
|
|
|
value->ipv6 = flow->nd_target;
|
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_NSH_FLAGS:
|
|
|
|
|
value->u8 = flow->nsh.flags;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_MDTYPE:
|
|
|
|
|
value->u8 = flow->nsh.mdtype;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_NP:
|
|
|
|
|
value->u8 = flow->nsh.np;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_SPI:
|
|
|
|
|
value->be32 = flow->nsh.spi;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_SI:
|
|
|
|
|
value->u8 = flow->nsh.si;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_C1:
|
|
|
|
|
case MFF_NSH_C2:
|
|
|
|
|
case MFF_NSH_C3:
|
|
|
|
|
case MFF_NSH_C4:
|
|
|
|
|
value->be32 = flow->nsh.c[mf->id - MFF_NSH_C1];
|
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_N_IDS:
|
|
|
|
|
default:
|
2013-12-17 10:32:12 -08:00
|
|
|
|
OVS_NOT_REACHED();
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-07 15:28:18 -07:00
|
|
|
|
/* Makes 'match' match field 'mf' exactly, with the value matched taken from
|
|
|
|
|
* 'value'. The caller is responsible for ensuring that 'match' meets 'mf''s
|
2015-08-31 14:20:17 -07:00
|
|
|
|
* prerequisites.
|
|
|
|
|
*
|
|
|
|
|
* If non-NULL, 'err_str' returns a malloc'ed string describing any errors
|
|
|
|
|
* with the request or NULL if there is no error. The caller is reponsible
|
|
|
|
|
* for freeing the string. */
|
2011-09-12 12:11:50 -07:00
|
|
|
|
void
|
|
|
|
|
mf_set_value(const struct mf_field *mf,
|
2015-08-31 14:20:17 -07:00
|
|
|
|
const union mf_value *value, struct match *match, char **err_str)
|
2011-09-12 12:11:50 -07:00
|
|
|
|
{
|
2015-08-31 14:20:17 -07:00
|
|
|
|
if (err_str) {
|
|
|
|
|
*err_str = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
switch (mf->id) {
|
2014-03-04 14:20:19 -08:00
|
|
|
|
case MFF_DP_HASH:
|
|
|
|
|
match_set_dp_hash(match, ntohl(value->be32));
|
|
|
|
|
break;
|
|
|
|
|
case MFF_RECIRC_ID:
|
|
|
|
|
match_set_recirc_id(match, ntohl(value->be32));
|
|
|
|
|
break;
|
2017-06-23 16:47:57 +00:00
|
|
|
|
case MFF_PACKET_TYPE:
|
|
|
|
|
match_set_packet_type(match, value->be32);
|
|
|
|
|
break;
|
2015-01-11 13:25:24 -08:00
|
|
|
|
case MFF_CONJ_ID:
|
|
|
|
|
match_set_conj_id(match, ntohl(value->be32));
|
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_TUN_ID:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_tun_id(match, value->be64);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_SRC:
|
|
|
|
|
match_set_tun_src(match, value->be32);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_DST:
|
|
|
|
|
match_set_tun_dst(match, value->be32);
|
|
|
|
|
break;
|
2015-12-04 12:36:50 -02:00
|
|
|
|
case MFF_TUN_IPV6_SRC:
|
|
|
|
|
match_set_tun_ipv6_src(match, &value->ipv6);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_IPV6_DST:
|
|
|
|
|
match_set_tun_ipv6_dst(match, &value->ipv6);
|
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_FLAGS:
|
|
|
|
|
match_set_tun_flags(match, ntohs(value->be16));
|
|
|
|
|
break;
|
2015-02-14 15:13:17 +01:00
|
|
|
|
case MFF_TUN_GBP_ID:
|
|
|
|
|
match_set_tun_gbp_id(match, value->be16);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_GBP_FLAGS:
|
|
|
|
|
match_set_tun_gbp_flags(match, value->u8);
|
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_TOS:
|
|
|
|
|
match_set_tun_tos(match, value->u8);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_TTL:
|
|
|
|
|
match_set_tun_ttl(match, value->u8);
|
|
|
|
|
break;
|
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
|
|
|
|
CASE_MFF_TUN_METADATA:
|
2015-08-31 14:20:17 -07:00
|
|
|
|
tun_metadata_set_match(mf, value, NULL, match, err_str);
|
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
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
|
2012-06-27 01:09:44 +12:00
|
|
|
|
case MFF_METADATA:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_metadata(match, value->be64);
|
2012-06-27 01:09:44 +12:00
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
|
|
|
|
case MFF_IN_PORT:
|
2013-06-19 16:58:44 -07:00
|
|
|
|
match_set_in_port(match, u16_to_ofp(ntohs(value->be16)));
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2013-05-19 15:44:53 +03:00
|
|
|
|
case MFF_IN_PORT_OXM: {
|
2013-06-19 16:58:44 -07:00
|
|
|
|
ofp_port_t port;
|
2013-05-20 12:21:51 -07:00
|
|
|
|
ofputil_port_from_ofp11(value->be32, &port);
|
2013-05-19 15:44:53 +03:00
|
|
|
|
match_set_in_port(match, port);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-11-03 14:24:01 -08:00
|
|
|
|
case MFF_ACTSET_OUTPUT: {
|
|
|
|
|
ofp_port_t port;
|
|
|
|
|
ofputil_port_from_ofp11(value->be32, &port);
|
|
|
|
|
match_set_actset_output(match, port);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2013-05-19 15:44:53 +03:00
|
|
|
|
|
2012-11-29 14:36:49 -08:00
|
|
|
|
case MFF_SKB_PRIORITY:
|
|
|
|
|
match_set_skb_priority(match, ntohl(value->be32));
|
|
|
|
|
break;
|
|
|
|
|
|
2013-08-06 12:57:13 -07:00
|
|
|
|
case MFF_PKT_MARK:
|
|
|
|
|
match_set_pkt_mark(match, ntohl(value->be32));
|
2012-11-29 14:36:49 -08:00
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_CT_STATE:
|
|
|
|
|
match_set_ct_state(match, ntohl(value->be32));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_ZONE:
|
|
|
|
|
match_set_ct_zone(match, ntohs(value->be16));
|
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_CT_MARK:
|
|
|
|
|
match_set_ct_mark(match, ntohl(value->be32));
|
|
|
|
|
break;
|
|
|
|
|
|
2015-10-31 03:12:38 -07:00
|
|
|
|
case MFF_CT_LABEL:
|
|
|
|
|
match_set_ct_label(match, ntoh128(value->be128));
|
Add connection tracking label support.
This patch adds a new 128-bit metadata field to the connection tracking
interface. When a label 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_label" 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 label 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_label)),2
table=0,in_port=2,ct_state=-trk,tcp,action=ct(table=1)
table=1,in_port=2,ct_state=+trk,ct_label=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-10-13 11:13:10 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2017-03-08 17:18:23 -08:00
|
|
|
|
case MFF_CT_NW_PROTO:
|
|
|
|
|
match_set_ct_nw_proto(match, value->u8);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_NW_SRC:
|
|
|
|
|
match_set_ct_nw_src(match, value->be32);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_NW_DST:
|
|
|
|
|
match_set_ct_nw_dst(match, value->be32);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_IPV6_SRC:
|
|
|
|
|
match_set_ct_ipv6_src(match, &value->ipv6);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_IPV6_DST:
|
|
|
|
|
match_set_ct_ipv6_dst(match, &value->ipv6);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_TP_SRC:
|
|
|
|
|
match_set_ct_tp_src(match, value->be16);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_TP_DST:
|
|
|
|
|
match_set_ct_tp_dst(match, value->be16);
|
|
|
|
|
break;
|
|
|
|
|
|
2012-06-27 07:23:25 -07:00
|
|
|
|
CASE_MFF_REGS:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_reg(match, mf->id - MFF_REG0, ntohl(value->be32));
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2014-07-28 09:50:37 -07:00
|
|
|
|
CASE_MFF_XREGS:
|
|
|
|
|
match_set_xreg(match, mf->id - MFF_XREG0, ntohll(value->be64));
|
|
|
|
|
break;
|
|
|
|
|
|
2015-10-31 04:45:28 -07:00
|
|
|
|
CASE_MFF_XXREGS:
|
|
|
|
|
match_set_xxreg(match, mf->id - MFF_XXREG0, ntoh128(value->be128));
|
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_ETH_SRC:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_dl_src(match, value->mac);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ETH_DST:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_dl_dst(match, value->mac);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ETH_TYPE:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_dl_type(match, value->be16);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_VLAN_TCI:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_dl_tci(match, value->be16);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2012-07-22 23:36:41 -07:00
|
|
|
|
case MFF_DL_VLAN:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_dl_vlan(match, value->be16);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
2012-07-22 23:20:22 -07:00
|
|
|
|
case MFF_VLAN_VID:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_vlan_vid(match, value->be16);
|
2012-07-22 23:20:22 -07:00
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2012-07-22 23:36:41 -07:00
|
|
|
|
case MFF_DL_VLAN_PCP:
|
2012-07-22 23:20:22 -07:00
|
|
|
|
case MFF_VLAN_PCP:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_dl_vlan_pcp(match, value->u8);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2013-01-25 16:22:07 +09:00
|
|
|
|
case MFF_MPLS_LABEL:
|
2014-02-04 10:32:35 -08:00
|
|
|
|
match_set_mpls_label(match, 0, value->be32);
|
2013-01-25 16:22:07 +09:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_MPLS_TC:
|
2014-02-04 10:32:35 -08:00
|
|
|
|
match_set_mpls_tc(match, 0, value->u8);
|
2013-01-25 16:22:07 +09:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_MPLS_BOS:
|
2014-02-04 10:32:35 -08:00
|
|
|
|
match_set_mpls_bos(match, 0, value->u8);
|
|
|
|
|
break;
|
2013-01-25 16:22:07 +09:00
|
|
|
|
|
2016-03-07 20:46:48 -08:00
|
|
|
|
case MFF_MPLS_TTL:
|
|
|
|
|
match_set_mpls_ttl(match, 0, value->u8);
|
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_IPV4_SRC:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_src(match, value->be32);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IPV4_DST:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_dst(match, value->be32);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IPV6_SRC:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_ipv6_src(match, &value->ipv6);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IPV6_DST:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_ipv6_dst(match, &value->ipv6);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2011-11-01 15:57:56 -07:00
|
|
|
|
case MFF_IPV6_LABEL:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_ipv6_label(match, value->be32);
|
2011-11-01 15:57:56 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_IP_PROTO:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_proto(match, value->u8);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2011-11-02 23:34:15 -07:00
|
|
|
|
case MFF_IP_DSCP:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_dscp(match, value->u8);
|
2011-11-02 23:34:15 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2013-04-18 09:40:48 -07:00
|
|
|
|
case MFF_IP_DSCP_SHIFTED:
|
|
|
|
|
match_set_nw_dscp(match, value->u8 << 2);
|
|
|
|
|
break;
|
|
|
|
|
|
2011-11-02 23:34:15 -07:00
|
|
|
|
case MFF_IP_ECN:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_ecn(match, value->u8);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2011-11-05 15:48:12 -07:00
|
|
|
|
case MFF_IP_TTL:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_ttl(match, value->u8);
|
2011-11-05 15:48:12 -07:00
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_IP_FRAG:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_frag(match, value->u8);
|
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
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_ARP_OP:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_proto(match, ntohs(value->be16));
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_SPA:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_src(match, value->be32);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_TPA:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_dst(match, value->be32);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_SHA:
|
|
|
|
|
case MFF_ND_SLL:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_arp_sha(match, value->mac);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_THA:
|
|
|
|
|
case MFF_ND_TLL:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_arp_tha(match, value->mac);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_TCP_SRC:
|
|
|
|
|
case MFF_UDP_SRC:
|
2013-08-22 20:24:45 +12:00
|
|
|
|
case MFF_SCTP_SRC:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_tp_src(match, value->be16);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2012-07-12 11:07:15 +12:00
|
|
|
|
case MFF_TCP_DST:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_UDP_DST:
|
2013-08-22 20:24:45 +12:00
|
|
|
|
case MFF_SCTP_DST:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_tp_dst(match, value->be16);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2013-10-28 13:54:40 -07:00
|
|
|
|
case MFF_TCP_FLAGS:
|
|
|
|
|
match_set_tcp_flags(match, value->be16);
|
|
|
|
|
break;
|
|
|
|
|
|
2011-10-22 13:11:48 -07:00
|
|
|
|
case MFF_ICMPV4_TYPE:
|
|
|
|
|
case MFF_ICMPV6_TYPE:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_icmp_type(match, value->u8);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2011-10-22 13:11:48 -07:00
|
|
|
|
case MFF_ICMPV4_CODE:
|
|
|
|
|
case MFF_ICMPV6_CODE:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_icmp_code(match, value->u8);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ND_TARGET:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nd_target(match, &value->ipv6);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_NSH_FLAGS:
|
|
|
|
|
MATCH_SET_FIELD_UINT8(match, nsh.flags, value->u8);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_MDTYPE:
|
|
|
|
|
MATCH_SET_FIELD_UINT8(match, nsh.mdtype, value->u8);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_NP:
|
|
|
|
|
MATCH_SET_FIELD_UINT8(match, nsh.np, value->u8);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_SPI:
|
|
|
|
|
MATCH_SET_FIELD_BE32(match, nsh.spi, value->be32);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_SI:
|
|
|
|
|
MATCH_SET_FIELD_UINT8(match, nsh.si, value->u8);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_C1:
|
|
|
|
|
case MFF_NSH_C2:
|
|
|
|
|
case MFF_NSH_C3:
|
|
|
|
|
case MFF_NSH_C4:
|
|
|
|
|
MATCH_SET_FIELD_BE32(match, nsh.c[mf->id - MFF_NSH_C1], value->be32);
|
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_N_IDS:
|
|
|
|
|
default:
|
2013-12-17 10:32:12 -08:00
|
|
|
|
OVS_NOT_REACHED();
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-29 16:52:03 -07:00
|
|
|
|
/* Unwildcard the bits in 'mask' of the 'wc' member field described by 'mf'.
|
|
|
|
|
* The caller is responsible for ensuring that 'wc' meets 'mf''s
|
|
|
|
|
* prerequisites. */
|
2013-10-13 12:44:20 -07:00
|
|
|
|
void
|
2016-07-29 16:52:03 -07:00
|
|
|
|
mf_mask_field_masked(const struct mf_field *mf, const union mf_value *mask,
|
|
|
|
|
struct flow_wildcards *wc)
|
2013-10-13 12:44:20 -07:00
|
|
|
|
{
|
2016-07-29 16:52:03 -07:00
|
|
|
|
union mf_value temp_mask;
|
|
|
|
|
/* For MFF_DL_VLAN, we cannot send a all 1's to flow_set_dl_vlan() as that
|
|
|
|
|
* will be considered as OFP10_VLAN_NONE. So make sure the mask only has
|
|
|
|
|
* valid bits in this case. */
|
2013-10-13 12:44:20 -07:00
|
|
|
|
if (mf->id == MFF_DL_VLAN) {
|
2016-07-29 16:52:03 -07:00
|
|
|
|
temp_mask.be16 = htons(VLAN_VID_MASK) & mask->be16;
|
|
|
|
|
mask = &temp_mask;
|
2013-10-13 12:44:20 -07:00
|
|
|
|
}
|
2016-07-29 16:52:03 -07:00
|
|
|
|
|
|
|
|
|
union mf_value mask_value;
|
|
|
|
|
|
|
|
|
|
mf_get_value(mf, &wc->masks, &mask_value);
|
|
|
|
|
for (size_t i = 0; i < mf->n_bytes; i++) {
|
|
|
|
|
mask_value.b[i] |= mask->b[i];
|
|
|
|
|
}
|
|
|
|
|
mf_set_flow_value(mf, &mask_value, &wc->masks);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Unwildcard 'wc' member field described by 'mf'. The caller is
|
|
|
|
|
* responsible for ensuring that 'mask' meets 'mf''s prerequisites. */
|
|
|
|
|
void
|
|
|
|
|
mf_mask_field(const struct mf_field *mf, struct flow_wildcards *wc)
|
|
|
|
|
{
|
|
|
|
|
mf_mask_field_masked(mf, &exact_match_mask, wc);
|
2013-10-13 12:44:20 -07:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-06 18:05:18 -07:00
|
|
|
|
static int
|
|
|
|
|
field_len(const struct mf_field *mf, const union mf_value *value_)
|
|
|
|
|
{
|
|
|
|
|
const uint8_t *value = &value_->u8;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (!mf->variable_len) {
|
|
|
|
|
return mf->n_bytes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!value) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < mf->n_bytes; i++) {
|
|
|
|
|
if (value[i] != 0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mf->n_bytes - i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns the effective length of the field. For fixed length fields,
|
|
|
|
|
* this is just the defined length. For variable length fields, it is
|
|
|
|
|
* the minimum size encoding that retains the same meaning (i.e.
|
2015-08-11 18:41:37 -07:00
|
|
|
|
* discarding leading zeros).
|
|
|
|
|
*
|
|
|
|
|
* 'is_masked' returns (if non-NULL) whether the original contained
|
|
|
|
|
* a mask. Otherwise, a mask that is the same length as the value
|
|
|
|
|
* might be misinterpreted as an exact match. */
|
2015-05-06 18:05:18 -07:00
|
|
|
|
int
|
|
|
|
|
mf_field_len(const struct mf_field *mf, const union mf_value *value,
|
2015-08-11 18:41:37 -07:00
|
|
|
|
const union mf_value *mask, bool *is_masked_)
|
2015-05-06 18:05:18 -07:00
|
|
|
|
{
|
|
|
|
|
int len, mask_len;
|
2015-08-11 18:41:37 -07:00
|
|
|
|
bool is_masked = mask && !is_all_ones(mask, mf->n_bytes);
|
2015-05-06 18:05:18 -07:00
|
|
|
|
|
|
|
|
|
len = field_len(mf, value);
|
2015-08-11 18:41:37 -07:00
|
|
|
|
if (is_masked) {
|
2015-05-06 18:05:18 -07:00
|
|
|
|
mask_len = field_len(mf, mask);
|
|
|
|
|
len = MAX(len, mask_len);
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-11 18:41:37 -07:00
|
|
|
|
if (is_masked_) {
|
|
|
|
|
*is_masked_ = is_masked;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-06 18:05:18 -07:00
|
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-01 11:44:01 -07:00
|
|
|
|
/* Sets 'flow' member field described by 'mf' to 'value'. The caller is
|
|
|
|
|
* responsible for ensuring that 'flow' meets 'mf''s prerequisites.*/
|
2011-10-12 17:04:13 -07:00
|
|
|
|
void
|
|
|
|
|
mf_set_flow_value(const struct mf_field *mf,
|
|
|
|
|
const union mf_value *value, struct flow *flow)
|
|
|
|
|
{
|
|
|
|
|
switch (mf->id) {
|
2014-03-04 14:20:19 -08:00
|
|
|
|
case MFF_DP_HASH:
|
|
|
|
|
flow->dp_hash = ntohl(value->be32);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_RECIRC_ID:
|
|
|
|
|
flow->recirc_id = ntohl(value->be32);
|
|
|
|
|
break;
|
2017-06-23 16:47:57 +00:00
|
|
|
|
case MFF_PACKET_TYPE:
|
|
|
|
|
flow->packet_type = value->be32;
|
|
|
|
|
break;
|
2015-01-11 13:25:24 -08:00
|
|
|
|
case MFF_CONJ_ID:
|
|
|
|
|
flow->conj_id = ntohl(value->be32);
|
|
|
|
|
break;
|
2011-10-12 17:04:13 -07:00
|
|
|
|
case MFF_TUN_ID:
|
2012-09-13 20:11:08 -07:00
|
|
|
|
flow->tunnel.tun_id = value->be64;
|
2011-10-12 17:04:13 -07:00
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_SRC:
|
|
|
|
|
flow->tunnel.ip_src = value->be32;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_DST:
|
|
|
|
|
flow->tunnel.ip_dst = value->be32;
|
|
|
|
|
break;
|
2015-12-04 12:36:50 -02:00
|
|
|
|
case MFF_TUN_IPV6_SRC:
|
|
|
|
|
flow->tunnel.ipv6_src = value->ipv6;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_IPV6_DST:
|
|
|
|
|
flow->tunnel.ipv6_dst = value->ipv6;
|
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_FLAGS:
|
2015-07-08 16:02:30 -07:00
|
|
|
|
flow->tunnel.flags = (flow->tunnel.flags & ~FLOW_TNL_PUB_F_MASK) |
|
|
|
|
|
ntohs(value->be16);
|
2012-11-21 18:51:36 -08:00
|
|
|
|
break;
|
2015-02-14 15:13:17 +01:00
|
|
|
|
case MFF_TUN_GBP_ID:
|
|
|
|
|
flow->tunnel.gbp_id = value->be16;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_GBP_FLAGS:
|
|
|
|
|
flow->tunnel.gbp_flags = value->u8;
|
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_TOS:
|
|
|
|
|
flow->tunnel.ip_tos = value->u8;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_TTL:
|
|
|
|
|
flow->tunnel.ip_ttl = value->u8;
|
|
|
|
|
break;
|
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
|
|
|
|
CASE_MFF_TUN_METADATA:
|
2015-06-29 18:01:59 -07:00
|
|
|
|
tun_metadata_write(&flow->tunnel, mf, value);
|
2015-07-15 13:17:01 -07:00
|
|
|
|
break;
|
2012-06-27 01:09:44 +12:00
|
|
|
|
case MFF_METADATA:
|
|
|
|
|
flow->metadata = value->be64;
|
|
|
|
|
break;
|
2011-10-12 17:04:13 -07:00
|
|
|
|
|
|
|
|
|
case MFF_IN_PORT:
|
2013-06-19 16:58:44 -07:00
|
|
|
|
flow->in_port.ofp_port = u16_to_ofp(ntohs(value->be16));
|
2011-10-12 17:04:13 -07:00
|
|
|
|
break;
|
2014-11-03 14:24:01 -08:00
|
|
|
|
case MFF_IN_PORT_OXM:
|
|
|
|
|
ofputil_port_from_ofp11(value->be32, &flow->in_port.ofp_port);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_ACTSET_OUTPUT:
|
|
|
|
|
ofputil_port_from_ofp11(value->be32, &flow->actset_output);
|
2013-05-19 15:44:53 +03:00
|
|
|
|
break;
|
|
|
|
|
|
2012-11-29 14:36:49 -08:00
|
|
|
|
case MFF_SKB_PRIORITY:
|
|
|
|
|
flow->skb_priority = ntohl(value->be32);
|
|
|
|
|
break;
|
|
|
|
|
|
2013-08-06 12:57:13 -07:00
|
|
|
|
case MFF_PKT_MARK:
|
|
|
|
|
flow->pkt_mark = ntohl(value->be32);
|
2012-11-29 14:36:49 -08:00
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_CT_STATE:
|
|
|
|
|
flow->ct_state = ntohl(value->be32);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_ZONE:
|
|
|
|
|
flow->ct_zone = ntohs(value->be16);
|
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_CT_MARK:
|
|
|
|
|
flow->ct_mark = ntohl(value->be32);
|
|
|
|
|
break;
|
|
|
|
|
|
Add connection tracking label support.
This patch adds a new 128-bit metadata field to the connection tracking
interface. When a label 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_label" 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 label 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_label)),2
table=0,in_port=2,ct_state=-trk,tcp,action=ct(table=1)
table=1,in_port=2,ct_state=+trk,ct_label=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-10-13 11:13:10 -07:00
|
|
|
|
case MFF_CT_LABEL:
|
2015-10-31 03:12:38 -07:00
|
|
|
|
flow->ct_label = ntoh128(value->be128);
|
Add connection tracking label support.
This patch adds a new 128-bit metadata field to the connection tracking
interface. When a label 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_label" 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 label 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_label)),2
table=0,in_port=2,ct_state=-trk,tcp,action=ct(table=1)
table=1,in_port=2,ct_state=+trk,ct_label=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-10-13 11:13:10 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2017-03-08 17:18:23 -08:00
|
|
|
|
case MFF_CT_NW_PROTO:
|
|
|
|
|
flow->ct_nw_proto = value->u8;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_NW_SRC:
|
|
|
|
|
flow->ct_nw_src = value->be32;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_NW_DST:
|
|
|
|
|
flow->ct_nw_dst = value->be32;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_IPV6_SRC:
|
|
|
|
|
flow->ct_ipv6_src = value->ipv6;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_IPV6_DST:
|
|
|
|
|
flow->ct_ipv6_dst = value->ipv6;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_TP_SRC:
|
|
|
|
|
flow->ct_tp_src = value->be16;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_TP_DST:
|
|
|
|
|
flow->ct_tp_dst = value->be16;
|
|
|
|
|
break;
|
|
|
|
|
|
2012-06-27 07:23:25 -07:00
|
|
|
|
CASE_MFF_REGS:
|
2011-10-12 17:04:13 -07:00
|
|
|
|
flow->regs[mf->id - MFF_REG0] = ntohl(value->be32);
|
|
|
|
|
break;
|
|
|
|
|
|
2014-07-28 09:50:37 -07:00
|
|
|
|
CASE_MFF_XREGS:
|
|
|
|
|
flow_set_xreg(flow, mf->id - MFF_XREG0, ntohll(value->be64));
|
|
|
|
|
break;
|
|
|
|
|
|
2015-10-31 04:45:28 -07:00
|
|
|
|
CASE_MFF_XXREGS:
|
|
|
|
|
flow_set_xxreg(flow, mf->id - MFF_XXREG0, ntoh128(value->be128));
|
|
|
|
|
break;
|
|
|
|
|
|
2011-10-12 17:04:13 -07:00
|
|
|
|
case MFF_ETH_SRC:
|
2015-08-28 14:55:11 -07:00
|
|
|
|
flow->dl_src = value->mac;
|
2011-10-12 17:04:13 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ETH_DST:
|
2015-08-28 14:55:11 -07:00
|
|
|
|
flow->dl_dst = value->mac;
|
2011-10-12 17:04:13 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ETH_TYPE:
|
|
|
|
|
flow->dl_type = value->be16;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_VLAN_TCI:
|
2017-03-01 17:47:59 -05:00
|
|
|
|
flow->vlans[0].tci = value->be16;
|
|
|
|
|
flow_fix_vlan_tpid(flow);
|
2011-10-12 17:04:13 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2012-07-22 23:36:41 -07:00
|
|
|
|
case MFF_DL_VLAN:
|
2012-07-22 22:42:55 -07:00
|
|
|
|
flow_set_dl_vlan(flow, value->be16);
|
2017-03-01 17:47:59 -05:00
|
|
|
|
flow_fix_vlan_tpid(flow);
|
2011-10-12 17:04:13 -07:00
|
|
|
|
break;
|
2017-03-01 17:47:59 -05:00
|
|
|
|
|
2012-07-22 23:20:22 -07:00
|
|
|
|
case MFF_VLAN_VID:
|
|
|
|
|
flow_set_vlan_vid(flow, value->be16);
|
2017-03-01 17:47:59 -05:00
|
|
|
|
flow_fix_vlan_tpid(flow);
|
2012-07-22 23:20:22 -07:00
|
|
|
|
break;
|
2011-10-12 17:04:13 -07:00
|
|
|
|
|
2012-07-22 23:36:41 -07:00
|
|
|
|
case MFF_DL_VLAN_PCP:
|
2012-07-22 23:20:22 -07:00
|
|
|
|
case MFF_VLAN_PCP:
|
2011-10-12 17:04:13 -07:00
|
|
|
|
flow_set_vlan_pcp(flow, value->u8);
|
2017-03-01 17:47:59 -05:00
|
|
|
|
flow_fix_vlan_tpid(flow);
|
2011-10-12 17:04:13 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2013-01-25 16:22:07 +09:00
|
|
|
|
case MFF_MPLS_LABEL:
|
2014-02-04 10:32:35 -08:00
|
|
|
|
flow_set_mpls_label(flow, 0, value->be32);
|
2013-01-25 16:22:07 +09:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_MPLS_TC:
|
2014-02-04 10:32:35 -08:00
|
|
|
|
flow_set_mpls_tc(flow, 0, value->u8);
|
2013-01-25 16:22:07 +09:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_MPLS_BOS:
|
2014-02-04 10:32:35 -08:00
|
|
|
|
flow_set_mpls_bos(flow, 0, value->u8);
|
|
|
|
|
break;
|
2013-01-25 16:22:07 +09:00
|
|
|
|
|
2016-03-07 20:46:48 -08:00
|
|
|
|
case MFF_MPLS_TTL:
|
|
|
|
|
flow_set_mpls_ttl(flow, 0, value->u8);
|
|
|
|
|
break;
|
|
|
|
|
|
2011-10-12 17:04:13 -07:00
|
|
|
|
case MFF_IPV4_SRC:
|
|
|
|
|
flow->nw_src = value->be32;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IPV4_DST:
|
|
|
|
|
flow->nw_dst = value->be32;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IPV6_SRC:
|
|
|
|
|
flow->ipv6_src = value->ipv6;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IPV6_DST:
|
|
|
|
|
flow->ipv6_dst = value->ipv6;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IPV6_LABEL:
|
2015-01-12 17:46:49 -08:00
|
|
|
|
flow->ipv6_label = value->be32 & htonl(IPV6_LABEL_MASK);
|
2011-10-12 17:04:13 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IP_PROTO:
|
|
|
|
|
flow->nw_proto = value->u8;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IP_DSCP:
|
|
|
|
|
flow->nw_tos &= ~IP_DSCP_MASK;
|
|
|
|
|
flow->nw_tos |= value->u8 & IP_DSCP_MASK;
|
|
|
|
|
break;
|
|
|
|
|
|
2013-04-18 09:40:48 -07:00
|
|
|
|
case MFF_IP_DSCP_SHIFTED:
|
|
|
|
|
flow->nw_tos &= ~IP_DSCP_MASK;
|
|
|
|
|
flow->nw_tos |= value->u8 << 2;
|
|
|
|
|
break;
|
|
|
|
|
|
2011-10-12 17:04:13 -07:00
|
|
|
|
case MFF_IP_ECN:
|
|
|
|
|
flow->nw_tos &= ~IP_ECN_MASK;
|
|
|
|
|
flow->nw_tos |= value->u8 & IP_ECN_MASK;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IP_TTL:
|
|
|
|
|
flow->nw_ttl = value->u8;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IP_FRAG:
|
2014-02-07 11:34:02 -08:00
|
|
|
|
flow->nw_frag = value->u8 & FLOW_NW_FRAG_MASK;
|
2011-10-12 17:04:13 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_OP:
|
|
|
|
|
flow->nw_proto = ntohs(value->be16);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_SPA:
|
|
|
|
|
flow->nw_src = value->be32;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_TPA:
|
|
|
|
|
flow->nw_dst = value->be32;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_SHA:
|
|
|
|
|
case MFF_ND_SLL:
|
2015-08-28 14:55:11 -07:00
|
|
|
|
flow->arp_sha = value->mac;
|
2011-10-12 17:04:13 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_THA:
|
|
|
|
|
case MFF_ND_TLL:
|
2015-08-28 14:55:11 -07:00
|
|
|
|
flow->arp_tha = value->mac;
|
2011-10-12 17:04:13 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_TCP_SRC:
|
|
|
|
|
case MFF_UDP_SRC:
|
2013-08-22 20:24:45 +12:00
|
|
|
|
case MFF_SCTP_SRC:
|
2011-10-12 17:04:13 -07:00
|
|
|
|
flow->tp_src = value->be16;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_TCP_DST:
|
|
|
|
|
case MFF_UDP_DST:
|
2013-08-22 20:24:45 +12:00
|
|
|
|
case MFF_SCTP_DST:
|
2011-10-12 17:04:13 -07:00
|
|
|
|
flow->tp_dst = value->be16;
|
|
|
|
|
break;
|
|
|
|
|
|
2013-10-28 13:54:40 -07:00
|
|
|
|
case MFF_TCP_FLAGS:
|
|
|
|
|
flow->tcp_flags = value->be16;
|
|
|
|
|
break;
|
|
|
|
|
|
2011-10-12 17:04:13 -07:00
|
|
|
|
case MFF_ICMPV4_TYPE:
|
|
|
|
|
case MFF_ICMPV6_TYPE:
|
|
|
|
|
flow->tp_src = htons(value->u8);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ICMPV4_CODE:
|
|
|
|
|
case MFF_ICMPV6_CODE:
|
|
|
|
|
flow->tp_dst = htons(value->u8);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ND_TARGET:
|
|
|
|
|
flow->nd_target = value->ipv6;
|
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_NSH_FLAGS:
|
|
|
|
|
flow->nsh.flags = value->u8;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_MDTYPE:
|
|
|
|
|
flow->nsh.mdtype = value->u8;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_NP:
|
|
|
|
|
flow->nsh.np = value->u8;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_SPI:
|
|
|
|
|
flow->nsh.spi = value->be32;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_SI:
|
|
|
|
|
flow->nsh.si = value->u8;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_C1:
|
|
|
|
|
case MFF_NSH_C2:
|
|
|
|
|
case MFF_NSH_C3:
|
|
|
|
|
case MFF_NSH_C4:
|
|
|
|
|
flow->nsh.c[mf->id - MFF_NSH_C1] = value->be32;
|
|
|
|
|
break;
|
|
|
|
|
|
2011-10-12 17:04:13 -07:00
|
|
|
|
case MFF_N_IDS:
|
|
|
|
|
default:
|
2013-12-17 10:32:12 -08:00
|
|
|
|
OVS_NOT_REACHED();
|
2011-10-12 17:04:13 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-07 16:49:50 -07:00
|
|
|
|
/* Consider each of 'src', 'mask', and 'dst' as if they were arrays of 8*n
|
|
|
|
|
* bits. Then, for each 0 <= i < 8 * n such that mask[i] == 1, sets dst[i] =
|
|
|
|
|
* src[i]. */
|
|
|
|
|
static void
|
|
|
|
|
apply_mask(const uint8_t *src, const uint8_t *mask, uint8_t *dst, size_t n)
|
|
|
|
|
{
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
|
dst[i] = (src[i] & mask[i]) | (dst[i] & ~mask[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Sets 'flow' member field described by 'field' to 'value', except that bits
|
|
|
|
|
* for which 'mask' has a 0-bit keep their existing values. The caller is
|
|
|
|
|
* responsible for ensuring that 'flow' meets 'field''s prerequisites.*/
|
|
|
|
|
void
|
|
|
|
|
mf_set_flow_value_masked(const struct mf_field *field,
|
|
|
|
|
const union mf_value *value,
|
|
|
|
|
const union mf_value *mask,
|
|
|
|
|
struct flow *flow)
|
|
|
|
|
{
|
|
|
|
|
union mf_value tmp;
|
|
|
|
|
|
|
|
|
|
mf_get_value(field, flow, &tmp);
|
|
|
|
|
apply_mask((const uint8_t *) value, (const uint8_t *) mask,
|
|
|
|
|
(uint8_t *) &tmp, field->n_bytes);
|
|
|
|
|
mf_set_flow_value(field, &tmp, flow);
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-11 18:41:37 -07:00
|
|
|
|
bool
|
|
|
|
|
mf_is_tun_metadata(const struct mf_field *mf)
|
|
|
|
|
{
|
|
|
|
|
return mf->id >= MFF_TUN_METADATA0 &&
|
|
|
|
|
mf->id < MFF_TUN_METADATA0 + TUN_METADATA_NUM_OPTS;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
|
mf_is_pipeline_field(const struct mf_field *mf)
|
|
|
|
|
{
|
|
|
|
|
switch (mf->id) {
|
|
|
|
|
case MFF_TUN_ID:
|
|
|
|
|
case MFF_TUN_SRC:
|
|
|
|
|
case MFF_TUN_DST:
|
|
|
|
|
case MFF_TUN_IPV6_SRC:
|
|
|
|
|
case MFF_TUN_IPV6_DST:
|
|
|
|
|
case MFF_TUN_FLAGS:
|
|
|
|
|
case MFF_TUN_GBP_ID:
|
|
|
|
|
case MFF_TUN_GBP_FLAGS:
|
|
|
|
|
CASE_MFF_TUN_METADATA:
|
|
|
|
|
case MFF_METADATA:
|
|
|
|
|
case MFF_IN_PORT:
|
|
|
|
|
case MFF_IN_PORT_OXM:
|
|
|
|
|
CASE_MFF_REGS:
|
|
|
|
|
CASE_MFF_XREGS:
|
|
|
|
|
CASE_MFF_XXREGS:
|
2017-06-23 16:47:57 +00:00
|
|
|
|
case MFF_PACKET_TYPE:
|
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 true;
|
|
|
|
|
|
|
|
|
|
case MFF_DP_HASH:
|
|
|
|
|
case MFF_RECIRC_ID:
|
|
|
|
|
case MFF_CONJ_ID:
|
|
|
|
|
case MFF_TUN_TTL:
|
|
|
|
|
case MFF_TUN_TOS:
|
|
|
|
|
case MFF_ACTSET_OUTPUT:
|
|
|
|
|
case MFF_SKB_PRIORITY:
|
|
|
|
|
case MFF_PKT_MARK:
|
|
|
|
|
case MFF_CT_STATE:
|
|
|
|
|
case MFF_CT_ZONE:
|
|
|
|
|
case MFF_CT_MARK:
|
|
|
|
|
case MFF_CT_LABEL:
|
|
|
|
|
case MFF_CT_NW_PROTO:
|
|
|
|
|
case MFF_CT_NW_SRC:
|
|
|
|
|
case MFF_CT_NW_DST:
|
|
|
|
|
case MFF_CT_IPV6_SRC:
|
|
|
|
|
case MFF_CT_IPV6_DST:
|
|
|
|
|
case MFF_CT_TP_SRC:
|
|
|
|
|
case MFF_CT_TP_DST:
|
|
|
|
|
case MFF_ETH_SRC:
|
|
|
|
|
case MFF_ETH_DST:
|
|
|
|
|
case MFF_ETH_TYPE:
|
|
|
|
|
case MFF_VLAN_TCI:
|
|
|
|
|
case MFF_DL_VLAN:
|
|
|
|
|
case MFF_VLAN_VID:
|
|
|
|
|
case MFF_DL_VLAN_PCP:
|
|
|
|
|
case MFF_VLAN_PCP:
|
|
|
|
|
case MFF_MPLS_LABEL:
|
|
|
|
|
case MFF_MPLS_TC:
|
|
|
|
|
case MFF_MPLS_BOS:
|
|
|
|
|
case MFF_MPLS_TTL:
|
|
|
|
|
case MFF_IPV4_SRC:
|
|
|
|
|
case MFF_IPV4_DST:
|
|
|
|
|
case MFF_IPV6_SRC:
|
|
|
|
|
case MFF_IPV6_DST:
|
|
|
|
|
case MFF_IPV6_LABEL:
|
|
|
|
|
case MFF_IP_PROTO:
|
|
|
|
|
case MFF_IP_DSCP:
|
|
|
|
|
case MFF_IP_DSCP_SHIFTED:
|
|
|
|
|
case MFF_IP_ECN:
|
|
|
|
|
case MFF_IP_TTL:
|
|
|
|
|
case MFF_IP_FRAG:
|
|
|
|
|
case MFF_ARP_OP:
|
|
|
|
|
case MFF_ARP_SPA:
|
|
|
|
|
case MFF_ARP_TPA:
|
|
|
|
|
case MFF_ARP_SHA:
|
|
|
|
|
case MFF_ARP_THA:
|
|
|
|
|
case MFF_TCP_SRC:
|
|
|
|
|
case MFF_TCP_DST:
|
|
|
|
|
case MFF_TCP_FLAGS:
|
|
|
|
|
case MFF_UDP_SRC:
|
|
|
|
|
case MFF_UDP_DST:
|
|
|
|
|
case MFF_SCTP_SRC:
|
|
|
|
|
case MFF_SCTP_DST:
|
|
|
|
|
case MFF_ICMPV4_TYPE:
|
|
|
|
|
case MFF_ICMPV4_CODE:
|
|
|
|
|
case MFF_ICMPV6_TYPE:
|
|
|
|
|
case MFF_ICMPV6_CODE:
|
|
|
|
|
case MFF_ND_TARGET:
|
|
|
|
|
case MFF_ND_SLL:
|
|
|
|
|
case MFF_ND_TLL:
|
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
|
|
|
|
case MFF_NSH_FLAGS:
|
|
|
|
|
case MFF_NSH_MDTYPE:
|
|
|
|
|
case MFF_NSH_NP:
|
|
|
|
|
case MFF_NSH_SPI:
|
|
|
|
|
case MFF_NSH_SI:
|
|
|
|
|
case MFF_NSH_C1:
|
|
|
|
|
case MFF_NSH_C2:
|
|
|
|
|
case MFF_NSH_C3:
|
|
|
|
|
case MFF_NSH_C4:
|
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 false;
|
|
|
|
|
|
|
|
|
|
case MFF_N_IDS:
|
|
|
|
|
default:
|
|
|
|
|
OVS_NOT_REACHED();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-11 18:41:37 -07:00
|
|
|
|
/* Returns true if 'mf' has previously been set in 'flow', false if
|
|
|
|
|
* it contains a non-default value.
|
2012-05-04 09:52:37 -07:00
|
|
|
|
*
|
|
|
|
|
* The caller is responsible for ensuring that 'flow' meets 'mf''s
|
|
|
|
|
* prerequisites. */
|
|
|
|
|
bool
|
2015-08-11 18:41:37 -07:00
|
|
|
|
mf_is_set(const struct mf_field *mf, const struct flow *flow)
|
2012-05-04 09:52:37 -07:00
|
|
|
|
{
|
2015-08-11 18:41:37 -07:00
|
|
|
|
if (!mf_is_tun_metadata(mf)) {
|
|
|
|
|
union mf_value value;
|
2012-05-04 09:52:37 -07:00
|
|
|
|
|
2015-08-11 18:41:37 -07:00
|
|
|
|
mf_get_value(mf, flow, &value);
|
|
|
|
|
return !is_all_zeros(&value, mf->n_bytes);
|
|
|
|
|
} else {
|
|
|
|
|
return ULLONG_GET(flow->tunnel.metadata.present.map,
|
|
|
|
|
mf->id - MFF_TUN_METADATA0);
|
|
|
|
|
}
|
2012-05-04 09:52:37 -07:00
|
|
|
|
}
|
|
|
|
|
|
2012-08-07 15:28:18 -07:00
|
|
|
|
/* Makes 'match' wildcard field 'mf'.
|
2011-09-12 12:11:50 -07:00
|
|
|
|
*
|
2012-08-07 15:28:18 -07:00
|
|
|
|
* The caller is responsible for ensuring that 'match' meets 'mf''s
|
2015-08-31 14:20:17 -07:00
|
|
|
|
* prerequisites.
|
|
|
|
|
*
|
|
|
|
|
* If non-NULL, 'err_str' returns a malloc'ed string describing any errors
|
|
|
|
|
* with the request or NULL if there is no error. The caller is reponsible
|
|
|
|
|
* for freeing the string. */
|
2011-09-12 12:11:50 -07:00
|
|
|
|
void
|
2015-08-31 14:20:17 -07:00
|
|
|
|
mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str)
|
2011-09-12 12:11:50 -07:00
|
|
|
|
{
|
2015-08-31 14:20:17 -07:00
|
|
|
|
if (err_str) {
|
|
|
|
|
*err_str = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
switch (mf->id) {
|
2014-03-04 14:20:19 -08:00
|
|
|
|
case MFF_DP_HASH:
|
|
|
|
|
match->flow.dp_hash = 0;
|
|
|
|
|
match->wc.masks.dp_hash = 0;
|
|
|
|
|
break;
|
|
|
|
|
case MFF_RECIRC_ID:
|
|
|
|
|
match->flow.recirc_id = 0;
|
|
|
|
|
match->wc.masks.recirc_id = 0;
|
|
|
|
|
break;
|
2017-06-23 16:47:57 +00:00
|
|
|
|
case MFF_PACKET_TYPE:
|
|
|
|
|
match->flow.packet_type = 0;
|
|
|
|
|
match->wc.masks.packet_type = 0;
|
|
|
|
|
break;
|
2015-01-11 13:25:24 -08:00
|
|
|
|
case MFF_CONJ_ID:
|
|
|
|
|
match->flow.conj_id = 0;
|
|
|
|
|
match->wc.masks.conj_id = 0;
|
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_TUN_ID:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_tun_id_masked(match, htonll(0), htonll(0));
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_SRC:
|
|
|
|
|
match_set_tun_src_masked(match, htonl(0), htonl(0));
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_DST:
|
|
|
|
|
match_set_tun_dst_masked(match, htonl(0), htonl(0));
|
|
|
|
|
break;
|
2015-12-04 12:36:50 -02:00
|
|
|
|
case MFF_TUN_IPV6_SRC:
|
|
|
|
|
memset(&match->wc.masks.tunnel.ipv6_src, 0,
|
|
|
|
|
sizeof match->wc.masks.tunnel.ipv6_src);
|
|
|
|
|
memset(&match->flow.tunnel.ipv6_src, 0,
|
|
|
|
|
sizeof match->flow.tunnel.ipv6_src);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_IPV6_DST:
|
|
|
|
|
memset(&match->wc.masks.tunnel.ipv6_dst, 0,
|
|
|
|
|
sizeof match->wc.masks.tunnel.ipv6_dst);
|
|
|
|
|
memset(&match->flow.tunnel.ipv6_dst, 0,
|
|
|
|
|
sizeof match->flow.tunnel.ipv6_dst);
|
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_FLAGS:
|
|
|
|
|
match_set_tun_flags_masked(match, 0, 0);
|
|
|
|
|
break;
|
2015-02-14 15:13:17 +01:00
|
|
|
|
case MFF_TUN_GBP_ID:
|
|
|
|
|
match_set_tun_gbp_id_masked(match, 0, 0);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_GBP_FLAGS:
|
|
|
|
|
match_set_tun_gbp_flags_masked(match, 0, 0);
|
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_TOS:
|
|
|
|
|
match_set_tun_tos_masked(match, 0, 0);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_TTL:
|
|
|
|
|
match_set_tun_ttl_masked(match, 0, 0);
|
|
|
|
|
break;
|
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
|
|
|
|
CASE_MFF_TUN_METADATA:
|
2015-08-31 14:20:17 -07:00
|
|
|
|
tun_metadata_set_match(mf, NULL, NULL, match, err_str);
|
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
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
|
2012-06-27 01:09:44 +12:00
|
|
|
|
case MFF_METADATA:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_metadata_masked(match, htonll(0), htonll(0));
|
2013-01-24 13:41:10 -08:00
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
|
|
|
|
case MFF_IN_PORT:
|
2013-05-19 15:44:53 +03:00
|
|
|
|
case MFF_IN_PORT_OXM:
|
2013-06-19 16:58:44 -07:00
|
|
|
|
match->flow.in_port.ofp_port = 0;
|
|
|
|
|
match->wc.masks.in_port.ofp_port = 0;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
2014-11-03 14:24:01 -08:00
|
|
|
|
case MFF_ACTSET_OUTPUT:
|
|
|
|
|
match->flow.actset_output = 0;
|
|
|
|
|
match->wc.masks.actset_output = 0;
|
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2012-11-29 14:36:49 -08:00
|
|
|
|
case MFF_SKB_PRIORITY:
|
|
|
|
|
match->flow.skb_priority = 0;
|
|
|
|
|
match->wc.masks.skb_priority = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
2013-08-06 12:57:13 -07:00
|
|
|
|
case MFF_PKT_MARK:
|
|
|
|
|
match->flow.pkt_mark = 0;
|
|
|
|
|
match->wc.masks.pkt_mark = 0;
|
2012-11-29 14:36:49 -08:00
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_CT_STATE:
|
|
|
|
|
match->flow.ct_state = 0;
|
|
|
|
|
match->wc.masks.ct_state = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_ZONE:
|
|
|
|
|
match->flow.ct_zone = 0;
|
|
|
|
|
match->wc.masks.ct_zone = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_CT_MARK:
|
|
|
|
|
match->flow.ct_mark = 0;
|
|
|
|
|
match->wc.masks.ct_mark = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
Add connection tracking label support.
This patch adds a new 128-bit metadata field to the connection tracking
interface. When a label 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_label" 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 label 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_label)),2
table=0,in_port=2,ct_state=-trk,tcp,action=ct(table=1)
table=1,in_port=2,ct_state=+trk,ct_label=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-10-13 11:13:10 -07:00
|
|
|
|
case MFF_CT_LABEL:
|
|
|
|
|
memset(&match->flow.ct_label, 0, sizeof(match->flow.ct_label));
|
|
|
|
|
memset(&match->wc.masks.ct_label, 0, sizeof(match->wc.masks.ct_label));
|
|
|
|
|
break;
|
|
|
|
|
|
2017-03-08 17:18:23 -08:00
|
|
|
|
case MFF_CT_NW_PROTO:
|
|
|
|
|
match->flow.ct_nw_proto = 0;
|
|
|
|
|
match->wc.masks.ct_nw_proto = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_NW_SRC:
|
|
|
|
|
match->flow.ct_nw_src = 0;
|
|
|
|
|
match->wc.masks.ct_nw_src = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_NW_DST:
|
|
|
|
|
match->flow.ct_nw_dst = 0;
|
|
|
|
|
match->wc.masks.ct_nw_dst = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_IPV6_SRC:
|
|
|
|
|
memset(&match->flow.ct_ipv6_src, 0, sizeof(match->flow.ct_ipv6_src));
|
|
|
|
|
WC_UNMASK_FIELD(&match->wc, ct_ipv6_src);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_IPV6_DST:
|
|
|
|
|
memset(&match->flow.ct_ipv6_dst, 0, sizeof(match->flow.ct_ipv6_dst));
|
|
|
|
|
WC_UNMASK_FIELD(&match->wc, ct_ipv6_dst);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_TP_SRC:
|
|
|
|
|
match->flow.ct_tp_src = 0;
|
|
|
|
|
match->wc.masks.ct_tp_src = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_CT_TP_DST:
|
|
|
|
|
match->flow.ct_tp_dst = 0;
|
|
|
|
|
match->wc.masks.ct_tp_dst = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
2012-06-27 07:23:25 -07:00
|
|
|
|
CASE_MFF_REGS:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_reg_masked(match, mf->id - MFF_REG0, 0, 0);
|
2012-03-08 14:44:54 -08:00
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2014-07-28 09:50:37 -07:00
|
|
|
|
CASE_MFF_XREGS:
|
|
|
|
|
match_set_xreg_masked(match, mf->id - MFF_XREG0, 0, 0);
|
|
|
|
|
break;
|
|
|
|
|
|
2015-10-31 04:45:28 -07:00
|
|
|
|
CASE_MFF_XXREGS: {
|
|
|
|
|
match_set_xxreg_masked(match, mf->id - MFF_XXREG0, OVS_U128_ZERO,
|
|
|
|
|
OVS_U128_ZERO);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_ETH_SRC:
|
2015-08-28 14:55:11 -07:00
|
|
|
|
match->flow.dl_src = eth_addr_zero;
|
|
|
|
|
match->wc.masks.dl_src = eth_addr_zero;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ETH_DST:
|
2015-08-28 14:55:11 -07:00
|
|
|
|
match->flow.dl_dst = eth_addr_zero;
|
|
|
|
|
match->wc.masks.dl_dst = eth_addr_zero;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ETH_TYPE:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match->flow.dl_type = htons(0);
|
|
|
|
|
match->wc.masks.dl_type = htons(0);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_VLAN_TCI:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_dl_tci_masked(match, htons(0), htons(0));
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2012-07-22 23:36:41 -07:00
|
|
|
|
case MFF_DL_VLAN:
|
2012-07-22 23:20:22 -07:00
|
|
|
|
case MFF_VLAN_VID:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_any_vid(match);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2012-07-22 23:36:41 -07:00
|
|
|
|
case MFF_DL_VLAN_PCP:
|
2012-07-22 23:20:22 -07:00
|
|
|
|
case MFF_VLAN_PCP:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_any_pcp(match);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2013-01-25 16:22:07 +09:00
|
|
|
|
case MFF_MPLS_LABEL:
|
2014-02-04 10:32:35 -08:00
|
|
|
|
match_set_any_mpls_label(match, 0);
|
2013-01-25 16:22:07 +09:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_MPLS_TC:
|
2014-02-04 10:32:35 -08:00
|
|
|
|
match_set_any_mpls_tc(match, 0);
|
2013-01-25 16:22:07 +09:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_MPLS_BOS:
|
2014-02-04 10:32:35 -08:00
|
|
|
|
match_set_any_mpls_bos(match, 0);
|
|
|
|
|
break;
|
2013-01-25 16:22:07 +09:00
|
|
|
|
|
2016-03-07 20:46:48 -08:00
|
|
|
|
case MFF_MPLS_TTL:
|
|
|
|
|
match_set_any_mpls_ttl(match, 0);
|
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_IPV4_SRC:
|
|
|
|
|
case MFF_ARP_SPA:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_src_masked(match, htonl(0), htonl(0));
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IPV4_DST:
|
|
|
|
|
case MFF_ARP_TPA:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_dst_masked(match, htonl(0), htonl(0));
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IPV6_SRC:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
memset(&match->wc.masks.ipv6_src, 0, sizeof match->wc.masks.ipv6_src);
|
|
|
|
|
memset(&match->flow.ipv6_src, 0, sizeof match->flow.ipv6_src);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IPV6_DST:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
memset(&match->wc.masks.ipv6_dst, 0, sizeof match->wc.masks.ipv6_dst);
|
|
|
|
|
memset(&match->flow.ipv6_dst, 0, sizeof match->flow.ipv6_dst);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2011-11-01 15:57:56 -07:00
|
|
|
|
case MFF_IPV6_LABEL:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match->wc.masks.ipv6_label = htonl(0);
|
|
|
|
|
match->flow.ipv6_label = htonl(0);
|
2011-11-01 15:57:56 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_IP_PROTO:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match->wc.masks.nw_proto = 0;
|
|
|
|
|
match->flow.nw_proto = 0;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2011-11-02 23:34:15 -07:00
|
|
|
|
case MFF_IP_DSCP:
|
2013-04-18 09:40:48 -07:00
|
|
|
|
case MFF_IP_DSCP_SHIFTED:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match->wc.masks.nw_tos &= ~IP_DSCP_MASK;
|
|
|
|
|
match->flow.nw_tos &= ~IP_DSCP_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
|
|
|
|
break;
|
|
|
|
|
|
2011-11-02 23:34:15 -07:00
|
|
|
|
case MFF_IP_ECN:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match->wc.masks.nw_tos &= ~IP_ECN_MASK;
|
|
|
|
|
match->flow.nw_tos &= ~IP_ECN_MASK;
|
2011-11-02 23:34:15 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2011-11-05 15:48:12 -07:00
|
|
|
|
case MFF_IP_TTL:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match->wc.masks.nw_ttl = 0;
|
|
|
|
|
match->flow.nw_ttl = 0;
|
2011-11-05 15:48:12 -07:00
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_IP_FRAG:
|
2015-08-20 13:10:07 -07:00
|
|
|
|
match->wc.masks.nw_frag &= ~FLOW_NW_FRAG_MASK;
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match->flow.nw_frag &= ~FLOW_NW_FRAG_MASK;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_OP:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match->wc.masks.nw_proto = 0;
|
|
|
|
|
match->flow.nw_proto = 0;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_SHA:
|
|
|
|
|
case MFF_ND_SLL:
|
2015-08-28 14:55:11 -07:00
|
|
|
|
match->flow.arp_sha = eth_addr_zero;
|
|
|
|
|
match->wc.masks.arp_sha = eth_addr_zero;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_THA:
|
|
|
|
|
case MFF_ND_TLL:
|
2015-08-28 14:55:11 -07:00
|
|
|
|
match->flow.arp_tha = eth_addr_zero;
|
|
|
|
|
match->wc.masks.arp_tha = eth_addr_zero;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_TCP_SRC:
|
|
|
|
|
case MFF_UDP_SRC:
|
2013-08-22 20:24:45 +12:00
|
|
|
|
case MFF_SCTP_SRC:
|
2011-10-22 13:11:48 -07:00
|
|
|
|
case MFF_ICMPV4_TYPE:
|
|
|
|
|
case MFF_ICMPV6_TYPE:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match->wc.masks.tp_src = htons(0);
|
|
|
|
|
match->flow.tp_src = htons(0);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_TCP_DST:
|
|
|
|
|
case MFF_UDP_DST:
|
2013-08-22 20:24:45 +12:00
|
|
|
|
case MFF_SCTP_DST:
|
2011-10-22 13:11:48 -07:00
|
|
|
|
case MFF_ICMPV4_CODE:
|
|
|
|
|
case MFF_ICMPV6_CODE:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match->wc.masks.tp_dst = htons(0);
|
|
|
|
|
match->flow.tp_dst = htons(0);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2013-10-28 13:54:40 -07:00
|
|
|
|
case MFF_TCP_FLAGS:
|
|
|
|
|
match->wc.masks.tcp_flags = htons(0);
|
|
|
|
|
match->flow.tcp_flags = htons(0);
|
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_ND_TARGET:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
memset(&match->wc.masks.nd_target, 0,
|
|
|
|
|
sizeof match->wc.masks.nd_target);
|
|
|
|
|
memset(&match->flow.nd_target, 0, sizeof match->flow.nd_target);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_NSH_FLAGS:
|
|
|
|
|
MATCH_SET_FIELD_MASKED(match, nsh.flags, 0, 0);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_MDTYPE:
|
|
|
|
|
MATCH_SET_FIELD_MASKED(match, nsh.mdtype, 0, 0);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_NP:
|
|
|
|
|
MATCH_SET_FIELD_MASKED(match, nsh.np, 0, 0);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_SPI:
|
|
|
|
|
MATCH_SET_FIELD_MASKED(match, nsh.spi, htonl(0), htonl(0));
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_SI:
|
|
|
|
|
MATCH_SET_FIELD_MASKED(match, nsh.si, 0, 0);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_C1:
|
|
|
|
|
case MFF_NSH_C2:
|
|
|
|
|
case MFF_NSH_C3:
|
|
|
|
|
case MFF_NSH_C4:
|
|
|
|
|
MATCH_SET_FIELD_MASKED(match, nsh.c[mf->id - MFF_NSH_C1],
|
|
|
|
|
htonl(0), htonl(0));
|
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_N_IDS:
|
|
|
|
|
default:
|
2013-12-17 10:32:12 -08:00
|
|
|
|
OVS_NOT_REACHED();
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-07 15:28:18 -07:00
|
|
|
|
/* Makes 'match' match field 'mf' with the specified 'value' and 'mask'.
|
2011-09-12 12:11:50 -07:00
|
|
|
|
* 'value' specifies a value to match and 'mask' specifies a wildcard pattern,
|
|
|
|
|
* with a 1-bit indicating that the corresponding value bit must match and a
|
|
|
|
|
* 0-bit indicating a don't-care.
|
|
|
|
|
*
|
|
|
|
|
* If 'mask' is NULL or points to all-1-bits, then this call is equivalent to
|
2012-08-07 15:28:18 -07:00
|
|
|
|
* mf_set_value(mf, value, match). If 'mask' points to all-0-bits, then this
|
|
|
|
|
* call is equivalent to mf_set_wild(mf, match).
|
2011-09-12 12:11:50 -07:00
|
|
|
|
*
|
|
|
|
|
* 'mask' must be a valid mask for 'mf' (see mf_is_mask_valid()). The caller
|
2015-08-31 14:20:17 -07:00
|
|
|
|
* is responsible for ensuring that 'match' meets 'mf''s prerequisites.
|
|
|
|
|
*
|
|
|
|
|
* If non-NULL, 'err_str' returns a malloc'ed string describing any errors
|
|
|
|
|
* with the request or NULL if there is no error. The caller is reponsible
|
2015-10-09 17:24:00 -07:00
|
|
|
|
* for freeing the string.
|
|
|
|
|
*
|
|
|
|
|
* Return a set of enum ofputil_protocol bits (as an uint32_t to avoid circular
|
|
|
|
|
* dependency on enum ofputil_protocol definition) indicating which OpenFlow
|
|
|
|
|
* protocol versions can support this functionality. */
|
|
|
|
|
uint32_t
|
2011-09-12 12:11:50 -07:00
|
|
|
|
mf_set(const struct mf_field *mf,
|
|
|
|
|
const union mf_value *value, const union mf_value *mask,
|
2015-08-31 14:20:17 -07:00
|
|
|
|
struct match *match, char **err_str)
|
2011-09-12 12:11:50 -07:00
|
|
|
|
{
|
2014-09-05 15:44:19 -07:00
|
|
|
|
if (!mask || is_all_ones(mask, mf->n_bytes)) {
|
2015-08-31 14:20:17 -07:00
|
|
|
|
mf_set_value(mf, value, match, err_str);
|
2014-10-07 15:24:11 -07:00
|
|
|
|
return mf->usable_protocols_exact;
|
2015-08-11 18:41:37 -07:00
|
|
|
|
} else if (is_all_zeros(mask, mf->n_bytes) && !mf_is_tun_metadata(mf)) {
|
|
|
|
|
/* Tunnel metadata matches on the existence of the field itself, so
|
|
|
|
|
* it still needs to be encoded even if the value is wildcarded. */
|
2015-08-31 14:20:17 -07:00
|
|
|
|
mf_set_wild(mf, match, err_str);
|
2013-08-20 18:41:45 -07:00
|
|
|
|
return OFPUTIL_P_ANY;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-31 14:20:17 -07:00
|
|
|
|
if (err_str) {
|
|
|
|
|
*err_str = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
switch (mf->id) {
|
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
|
|
|
|
case MFF_CT_ZONE:
|
2017-03-08 17:18:23 -08:00
|
|
|
|
case MFF_CT_NW_PROTO:
|
|
|
|
|
case MFF_CT_NW_SRC:
|
|
|
|
|
case MFF_CT_NW_DST:
|
|
|
|
|
case MFF_CT_IPV6_SRC:
|
|
|
|
|
case MFF_CT_IPV6_DST:
|
|
|
|
|
case MFF_CT_TP_SRC:
|
|
|
|
|
case MFF_CT_TP_DST:
|
2014-03-04 14:20:19 -08:00
|
|
|
|
case MFF_RECIRC_ID:
|
2017-06-23 16:47:57 +00:00
|
|
|
|
case MFF_PACKET_TYPE:
|
2015-01-11 13:25:24 -08:00
|
|
|
|
case MFF_CONJ_ID:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_IN_PORT:
|
2013-05-19 15:44:53 +03:00
|
|
|
|
case MFF_IN_PORT_OXM:
|
2014-11-03 14:24:01 -08:00
|
|
|
|
case MFF_ACTSET_OUTPUT:
|
2012-11-29 14:36:49 -08:00
|
|
|
|
case MFF_SKB_PRIORITY:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_ETH_TYPE:
|
2012-07-22 23:36:41 -07:00
|
|
|
|
case MFF_DL_VLAN:
|
|
|
|
|
case MFF_DL_VLAN_PCP:
|
2012-07-22 23:20:22 -07:00
|
|
|
|
case MFF_VLAN_PCP:
|
2013-01-25 16:22:07 +09:00
|
|
|
|
case MFF_MPLS_LABEL:
|
|
|
|
|
case MFF_MPLS_TC:
|
|
|
|
|
case MFF_MPLS_BOS:
|
2016-03-07 20:46:48 -08:00
|
|
|
|
case MFF_MPLS_TTL:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_IP_PROTO:
|
2011-11-05 15:48:12 -07:00
|
|
|
|
case MFF_IP_TTL:
|
2011-11-02 23:34:15 -07:00
|
|
|
|
case MFF_IP_DSCP:
|
2013-04-18 09:40:48 -07:00
|
|
|
|
case MFF_IP_DSCP_SHIFTED:
|
2011-11-02 23:34:15 -07:00
|
|
|
|
case MFF_IP_ECN:
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_ARP_OP:
|
2011-10-22 13:11:48 -07:00
|
|
|
|
case MFF_ICMPV4_TYPE:
|
|
|
|
|
case MFF_ICMPV4_CODE:
|
|
|
|
|
case MFF_ICMPV6_TYPE:
|
|
|
|
|
case MFF_ICMPV6_CODE:
|
2013-10-31 13:00:02 +09:00
|
|
|
|
return OFPUTIL_P_NONE;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2014-03-04 14:20:19 -08:00
|
|
|
|
case MFF_DP_HASH:
|
|
|
|
|
match_set_dp_hash_masked(match, ntohl(value->be32), ntohl(mask->be32));
|
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_TUN_ID:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_tun_id_masked(match, value->be64, mask->be64);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_SRC:
|
|
|
|
|
match_set_tun_src_masked(match, value->be32, mask->be32);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_DST:
|
|
|
|
|
match_set_tun_dst_masked(match, value->be32, mask->be32);
|
|
|
|
|
break;
|
2015-12-04 12:36:50 -02:00
|
|
|
|
case MFF_TUN_IPV6_SRC:
|
|
|
|
|
match_set_tun_ipv6_src_masked(match, &value->ipv6, &mask->ipv6);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_IPV6_DST:
|
|
|
|
|
match_set_tun_ipv6_dst_masked(match, &value->ipv6, &mask->ipv6);
|
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_FLAGS:
|
|
|
|
|
match_set_tun_flags_masked(match, ntohs(value->be16), ntohs(mask->be16));
|
|
|
|
|
break;
|
2015-02-14 15:13:17 +01:00
|
|
|
|
case MFF_TUN_GBP_ID:
|
|
|
|
|
match_set_tun_gbp_id_masked(match, value->be16, mask->be16);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_GBP_FLAGS:
|
|
|
|
|
match_set_tun_gbp_flags_masked(match, value->u8, mask->u8);
|
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFF_TUN_TTL:
|
|
|
|
|
match_set_tun_ttl_masked(match, value->u8, mask->u8);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_TUN_TOS:
|
|
|
|
|
match_set_tun_tos_masked(match, value->u8, mask->u8);
|
|
|
|
|
break;
|
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
|
|
|
|
CASE_MFF_TUN_METADATA:
|
2015-08-31 14:20:17 -07:00
|
|
|
|
tun_metadata_set_match(mf, value, mask, match, err_str);
|
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
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
|
2012-06-27 01:09:44 +12:00
|
|
|
|
case MFF_METADATA:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_metadata_masked(match, value->be64, mask->be64);
|
2012-06-27 01:09:44 +12:00
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2012-06-27 07:23:25 -07:00
|
|
|
|
CASE_MFF_REGS:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_reg_masked(match, mf->id - MFF_REG0,
|
|
|
|
|
ntohl(value->be32), ntohl(mask->be32));
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
2013-08-06 12:57:16 -07:00
|
|
|
|
|
2014-07-28 09:50:37 -07:00
|
|
|
|
CASE_MFF_XREGS:
|
|
|
|
|
match_set_xreg_masked(match, mf->id - MFF_XREG0,
|
|
|
|
|
ntohll(value->be64), ntohll(mask->be64));
|
|
|
|
|
break;
|
|
|
|
|
|
2015-10-31 04:45:28 -07:00
|
|
|
|
CASE_MFF_XXREGS: {
|
|
|
|
|
match_set_xxreg_masked(match, mf->id - MFF_XXREG0,
|
|
|
|
|
ntoh128(value->be128), ntoh128(mask->be128));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-06 12:57:16 -07:00
|
|
|
|
case MFF_PKT_MARK:
|
|
|
|
|
match_set_pkt_mark_masked(match, ntohl(value->be32),
|
|
|
|
|
ntohl(mask->be32));
|
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
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
|
|
|
|
case MFF_CT_STATE:
|
|
|
|
|
match_set_ct_state_masked(match, ntohl(value->be32), ntohl(mask->be32));
|
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_CT_MARK:
|
|
|
|
|
match_set_ct_mark_masked(match, ntohl(value->be32), ntohl(mask->be32));
|
|
|
|
|
break;
|
|
|
|
|
|
2015-10-31 03:12:38 -07:00
|
|
|
|
case MFF_CT_LABEL:
|
|
|
|
|
match_set_ct_label_masked(match, ntoh128(value->be128),
|
2017-05-26 22:09:35 -07:00
|
|
|
|
ntoh128(mask->be128));
|
Add connection tracking label support.
This patch adds a new 128-bit metadata field to the connection tracking
interface. When a label 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_label" 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 label 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_label)),2
table=0,in_port=2,ct_state=-trk,tcp,action=ct(table=1)
table=1,in_port=2,ct_state=+trk,ct_label=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-10-13 11:13:10 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_ETH_DST:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_dl_dst_masked(match, value->mac, mask->mac);
|
2012-05-29 00:38:21 +12:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ETH_SRC:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_dl_src_masked(match, value->mac, mask->mac);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2012-07-19 09:21:49 -07:00
|
|
|
|
case MFF_ARP_SHA:
|
|
|
|
|
case MFF_ND_SLL:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_arp_sha_masked(match, value->mac, mask->mac);
|
2012-07-19 09:21:49 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_ARP_THA:
|
|
|
|
|
case MFF_ND_TLL:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_arp_tha_masked(match, value->mac, mask->mac);
|
2012-07-19 09:21:49 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_VLAN_TCI:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_dl_tci_masked(match, value->be16, mask->be16);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2012-07-22 23:20:22 -07:00
|
|
|
|
case MFF_VLAN_VID:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_vlan_vid_masked(match, value->be16, mask->be16);
|
2012-07-22 23:20:22 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_IPV4_SRC:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_src_masked(match, value->be32, mask->be32);
|
2014-10-07 15:24:11 -07:00
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
|
|
|
|
case MFF_IPV4_DST:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_dst_masked(match, value->be32, mask->be32);
|
2014-10-07 15:24:11 -07:00
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
|
|
|
|
case MFF_IPV6_SRC:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_ipv6_src_masked(match, &value->ipv6, &mask->ipv6);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_IPV6_DST:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_ipv6_dst_masked(match, &value->ipv6, &mask->ipv6);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2012-07-18 12:02:19 +09:00
|
|
|
|
case MFF_IPV6_LABEL:
|
|
|
|
|
if ((mask->be32 & htonl(IPV6_LABEL_MASK)) == htonl(IPV6_LABEL_MASK)) {
|
2015-08-31 14:20:17 -07:00
|
|
|
|
mf_set_value(mf, value, match, err_str);
|
2012-07-18 12:02:19 +09:00
|
|
|
|
} else {
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_ipv6_label_masked(match, value->be32, mask->be32);
|
2012-07-18 12:02:19 +09:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2012-04-25 15:48:40 -07:00
|
|
|
|
case MFF_ND_TARGET:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nd_target_masked(match, &value->ipv6, &mask->ipv6);
|
2012-04-25 15:48:40 -07:00
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_IP_FRAG:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_frag_masked(match, value->u8, mask->u8);
|
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
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_ARP_SPA:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_src_masked(match, value->be32, mask->be32);
|
2014-10-07 15:24:11 -07:00
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
|
|
|
|
case MFF_ARP_TPA:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_nw_dst_masked(match, value->be32, mask->be32);
|
2014-10-07 15:24:11 -07:00
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2012-01-27 17:16:05 -08:00
|
|
|
|
case MFF_TCP_SRC:
|
|
|
|
|
case MFF_UDP_SRC:
|
2013-08-22 20:24:45 +12:00
|
|
|
|
case MFF_SCTP_SRC:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_tp_src_masked(match, value->be16, mask->be16);
|
2012-01-27 17:16:05 -08:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFF_TCP_DST:
|
|
|
|
|
case MFF_UDP_DST:
|
2013-08-22 20:24:45 +12:00
|
|
|
|
case MFF_SCTP_DST:
|
2012-08-07 15:28:18 -07:00
|
|
|
|
match_set_tp_dst_masked(match, value->be16, mask->be16);
|
2012-01-27 17:16:05 -08:00
|
|
|
|
break;
|
|
|
|
|
|
2013-10-28 13:54:40 -07:00
|
|
|
|
case MFF_TCP_FLAGS:
|
|
|
|
|
match_set_tcp_flags_masked(match, value->be16, mask->be16);
|
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFF_NSH_FLAGS:
|
|
|
|
|
MATCH_SET_FIELD_MASKED(match, nsh.flags, value->u8, mask->u8);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_MDTYPE:
|
|
|
|
|
MATCH_SET_FIELD_MASKED(match, nsh.mdtype, value->u8, mask->u8);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_NP:
|
|
|
|
|
MATCH_SET_FIELD_MASKED(match, nsh.np, value->u8, mask->u8);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_SPI:
|
|
|
|
|
MATCH_SET_FIELD_MASKED(match, nsh.spi, value->be32, mask->be32);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_SI:
|
|
|
|
|
MATCH_SET_FIELD_MASKED(match, nsh.si, value->u8, mask->u8);
|
|
|
|
|
break;
|
|
|
|
|
case MFF_NSH_C1:
|
|
|
|
|
case MFF_NSH_C2:
|
|
|
|
|
case MFF_NSH_C3:
|
|
|
|
|
case MFF_NSH_C4:
|
|
|
|
|
MATCH_SET_FIELD_MASKED(match, nsh.c[mf->id - MFF_NSH_C1],
|
|
|
|
|
value->be32, mask->be32);
|
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFF_N_IDS:
|
|
|
|
|
default:
|
2013-12-17 10:32:12 -08:00
|
|
|
|
OVS_NOT_REACHED();
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
2013-08-20 18:41:45 -07:00
|
|
|
|
|
2014-10-07 15:24:11 -07:00
|
|
|
|
return ((mf->usable_protocols_bitwise == mf->usable_protocols_cidr
|
|
|
|
|
|| ip_is_cidr(mask->be32))
|
|
|
|
|
? mf->usable_protocols_cidr
|
|
|
|
|
: mf->usable_protocols_bitwise);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
2011-12-28 12:42:14 -08:00
|
|
|
|
static enum ofperr
|
2017-03-08 17:18:22 -08:00
|
|
|
|
mf_check__(const struct mf_subfield *sf, const struct match *match,
|
2011-12-28 12:42:14 -08:00
|
|
|
|
const char *type)
|
2011-09-12 12:11:50 -07:00
|
|
|
|
{
|
2011-12-28 12:42:14 -08:00
|
|
|
|
if (!sf->field) {
|
|
|
|
|
VLOG_WARN_RL(&rl, "unknown %s field", type);
|
2013-08-23 11:11:03 -07:00
|
|
|
|
return OFPERR_OFPBAC_BAD_SET_TYPE;
|
2011-12-28 12:42:14 -08:00
|
|
|
|
} else if (!sf->n_bits) {
|
|
|
|
|
VLOG_WARN_RL(&rl, "zero bit %s field %s", type, sf->field->name);
|
2013-08-23 11:11:03 -07:00
|
|
|
|
return OFPERR_OFPBAC_BAD_SET_LEN;
|
2011-12-28 12:42:14 -08:00
|
|
|
|
} else if (sf->ofs >= sf->field->n_bits) {
|
|
|
|
|
VLOG_WARN_RL(&rl, "bit offset %d exceeds %d-bit width of %s field %s",
|
|
|
|
|
sf->ofs, sf->field->n_bits, type, sf->field->name);
|
2013-08-23 11:11:03 -07:00
|
|
|
|
return OFPERR_OFPBAC_BAD_SET_LEN;
|
2011-12-28 12:42:14 -08:00
|
|
|
|
} else if (sf->ofs + sf->n_bits > sf->field->n_bits) {
|
|
|
|
|
VLOG_WARN_RL(&rl, "bit offset %d and width %d exceeds %d-bit width "
|
|
|
|
|
"of %s field %s", sf->ofs, sf->n_bits,
|
|
|
|
|
sf->field->n_bits, type, sf->field->name);
|
2013-08-23 11:11:03 -07:00
|
|
|
|
return OFPERR_OFPBAC_BAD_SET_LEN;
|
2017-03-08 17:18:22 -08:00
|
|
|
|
} else if (match && !mf_are_match_prereqs_ok(sf->field, match)) {
|
2011-12-28 12:42:14 -08:00
|
|
|
|
VLOG_WARN_RL(&rl, "%s field %s lacks correct prerequisites",
|
|
|
|
|
type, sf->field->name);
|
2013-08-23 11:11:03 -07:00
|
|
|
|
return OFPERR_OFPBAC_MATCH_INCONSISTENT;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
} else {
|
2011-12-28 12:42:14 -08:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2016-08-01 22:50:10 -07:00
|
|
|
|
/* Sets all the bits in 'sf' to 1 within 'wc', if 'wc' is nonnull. */
|
|
|
|
|
static void
|
|
|
|
|
unwildcard_subfield(const struct mf_subfield *sf, struct flow_wildcards *wc)
|
|
|
|
|
{
|
|
|
|
|
if (wc) {
|
|
|
|
|
union mf_value mask;
|
|
|
|
|
|
|
|
|
|
memset(&mask, 0, sizeof mask);
|
|
|
|
|
bitwise_one(&mask, sf->field->n_bytes, sf->ofs, sf->n_bits);
|
|
|
|
|
mf_mask_field_masked(sf->field, &mask, wc);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Copies 'src' into 'dst' within 'flow', and sets all the bits in 'src' and
|
|
|
|
|
* 'dst' to 1s in 'wc', if 'wc' is nonnull.
|
|
|
|
|
*
|
|
|
|
|
* 'src' and 'dst' may overlap. */
|
|
|
|
|
void
|
|
|
|
|
mf_subfield_copy(const struct mf_subfield *src,
|
|
|
|
|
const struct mf_subfield *dst,
|
|
|
|
|
struct flow *flow, struct flow_wildcards *wc)
|
|
|
|
|
{
|
|
|
|
|
ovs_assert(src->n_bits == dst->n_bits);
|
|
|
|
|
if (mf_are_prereqs_ok(dst->field, flow, wc)
|
|
|
|
|
&& mf_are_prereqs_ok(src->field, flow, wc)) {
|
|
|
|
|
unwildcard_subfield(src, wc);
|
|
|
|
|
unwildcard_subfield(dst, wc);
|
|
|
|
|
|
|
|
|
|
union mf_value src_value;
|
|
|
|
|
union mf_value dst_value;
|
|
|
|
|
mf_get_value(dst->field, flow, &dst_value);
|
|
|
|
|
mf_get_value(src->field, flow, &src_value);
|
|
|
|
|
bitwise_copy(&src_value, src->field->n_bytes, src->ofs,
|
|
|
|
|
&dst_value, dst->field->n_bytes, dst->ofs,
|
|
|
|
|
src->n_bits);
|
|
|
|
|
mf_set_flow_value(dst->field, &dst_value, flow);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Swaps the bits in 'src' and 'dst' within 'flow', and sets all the bits in
|
|
|
|
|
* 'src' and 'dst' to 1s in 'wc', if 'wc' is nonnull.
|
|
|
|
|
*
|
|
|
|
|
* 'src' and 'dst' may overlap. */
|
|
|
|
|
void
|
|
|
|
|
mf_subfield_swap(const struct mf_subfield *a,
|
|
|
|
|
const struct mf_subfield *b,
|
|
|
|
|
struct flow *flow, struct flow_wildcards *wc)
|
|
|
|
|
{
|
|
|
|
|
ovs_assert(a->n_bits == b->n_bits);
|
|
|
|
|
if (mf_are_prereqs_ok(a->field, flow, wc)
|
|
|
|
|
&& mf_are_prereqs_ok(b->field, flow, wc)) {
|
|
|
|
|
unwildcard_subfield(a, wc);
|
|
|
|
|
unwildcard_subfield(b, wc);
|
|
|
|
|
|
|
|
|
|
union mf_value a_value;
|
|
|
|
|
union mf_value b_value;
|
|
|
|
|
mf_get_value(a->field, flow, &a_value);
|
|
|
|
|
mf_get_value(b->field, flow, &b_value);
|
|
|
|
|
union mf_value b2_value = b_value;
|
|
|
|
|
|
|
|
|
|
/* Copy 'a' into 'b'. */
|
|
|
|
|
bitwise_copy(&a_value, a->field->n_bytes, a->ofs,
|
|
|
|
|
&b_value, b->field->n_bytes, b->ofs,
|
|
|
|
|
a->n_bits);
|
|
|
|
|
mf_set_flow_value(b->field, &b_value, flow);
|
|
|
|
|
|
|
|
|
|
/* Copy original 'b' into 'a'. */
|
|
|
|
|
bitwise_copy(&b2_value, b->field->n_bytes, b->ofs,
|
|
|
|
|
&a_value, a->field->n_bytes, a->ofs,
|
|
|
|
|
b->n_bits);
|
|
|
|
|
mf_set_flow_value(a->field, &a_value, flow);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-28 12:42:14 -08:00
|
|
|
|
/* Checks whether 'sf' is valid for reading a subfield out of 'flow'. Returns
|
|
|
|
|
* 0 if so, otherwise an OpenFlow error code (e.g. as returned by
|
|
|
|
|
* ofp_mkerr()). */
|
|
|
|
|
enum ofperr
|
2017-03-08 17:18:22 -08:00
|
|
|
|
mf_check_src(const struct mf_subfield *sf, const struct match *match)
|
2011-12-28 12:42:14 -08:00
|
|
|
|
{
|
2017-03-08 17:18:22 -08:00
|
|
|
|
return mf_check__(sf, match, "source");
|
2011-12-28 12:42:14 -08:00
|
|
|
|
}
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2011-12-28 12:42:14 -08:00
|
|
|
|
/* Checks whether 'sf' is valid for writing a subfield into 'flow'. Returns 0
|
|
|
|
|
* if so, otherwise an OpenFlow error code (e.g. as returned by
|
|
|
|
|
* ofp_mkerr()). */
|
|
|
|
|
enum ofperr
|
2017-03-08 17:18:22 -08:00
|
|
|
|
mf_check_dst(const struct mf_subfield *sf, const struct match *match)
|
2011-12-28 12:42:14 -08:00
|
|
|
|
{
|
2017-03-08 17:18:22 -08:00
|
|
|
|
int error = mf_check__(sf, match, "destination");
|
2011-12-28 12:42:14 -08:00
|
|
|
|
if (!error && !sf->field->writable) {
|
|
|
|
|
VLOG_WARN_RL(&rl, "destination field %s is not writable",
|
|
|
|
|
sf->field->name);
|
2013-08-23 11:11:03 -07:00
|
|
|
|
return OFPERR_OFPBAC_BAD_SET_ARGUMENT;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
2011-12-28 12:42:14 -08:00
|
|
|
|
return error;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
2012-08-07 15:28:18 -07:00
|
|
|
|
/* Copies the value and wildcard bit pattern for 'mf' from 'match' into the
|
2011-09-12 12:11:50 -07:00
|
|
|
|
* 'value' and 'mask', respectively. */
|
|
|
|
|
void
|
2012-08-07 15:28:18 -07:00
|
|
|
|
mf_get(const struct mf_field *mf, const struct match *match,
|
2011-09-12 12:11:50 -07:00
|
|
|
|
union mf_value *value, union mf_value *mask)
|
|
|
|
|
{
|
2012-08-07 15:28:18 -07:00
|
|
|
|
mf_get_value(mf, &match->flow, value);
|
|
|
|
|
mf_get_mask(mf, &match->wc, mask);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
mf_from_integer_string(const struct mf_field *mf, const char *s,
|
|
|
|
|
uint8_t *valuep, uint8_t *maskp)
|
|
|
|
|
{
|
|
|
|
|
char *tail;
|
2015-05-18 17:17:41 -07:00
|
|
|
|
const char *err_str = "";
|
|
|
|
|
int err;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2015-05-18 17:17:41 -07:00
|
|
|
|
err = parse_int_string(s, valuep, mf->n_bytes, &tail);
|
|
|
|
|
if (err || (*tail != '\0' && *tail != '/')) {
|
|
|
|
|
err_str = "value";
|
2011-09-12 12:11:50 -07:00
|
|
|
|
goto syntax_error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*tail == '/') {
|
2015-05-18 17:17:41 -07:00
|
|
|
|
err = parse_int_string(tail + 1, maskp, mf->n_bytes, &tail);
|
|
|
|
|
if (err || *tail != '\0') {
|
|
|
|
|
err_str = "mask";
|
2011-09-12 12:11:50 -07:00
|
|
|
|
goto syntax_error;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2015-05-18 17:17:41 -07:00
|
|
|
|
memset(maskp, 0xff, mf->n_bytes);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
syntax_error:
|
2015-05-18 17:17:41 -07:00
|
|
|
|
if (err == ERANGE) {
|
|
|
|
|
return xasprintf("%s: %s too large for %u-byte field %s",
|
|
|
|
|
s, err_str, mf->n_bytes, mf->name);
|
|
|
|
|
} else {
|
|
|
|
|
return xasprintf("%s: bad syntax for %s %s", s, mf->name, err_str);
|
|
|
|
|
}
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
2017-06-23 16:47:57 +00:00
|
|
|
|
static char *
|
|
|
|
|
mf_from_packet_type_string(const char *s, ovs_be32 *packet_type)
|
|
|
|
|
{
|
|
|
|
|
char *tail;
|
|
|
|
|
const char *err_str = "";
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
if (*s != '(') {
|
|
|
|
|
err_str = "missing '('";
|
|
|
|
|
goto syntax_error;
|
|
|
|
|
}
|
|
|
|
|
s++;
|
|
|
|
|
err = parse_int_string(s, (uint8_t *)packet_type, 2, &tail);
|
|
|
|
|
if (err) {
|
|
|
|
|
err_str = "ns";
|
|
|
|
|
goto syntax_error;
|
|
|
|
|
}
|
|
|
|
|
if (*tail != ',') {
|
|
|
|
|
err_str = "missing ','";
|
|
|
|
|
goto syntax_error;
|
|
|
|
|
}
|
|
|
|
|
s = tail + 1;
|
|
|
|
|
err = parse_int_string(s, ((uint8_t *)packet_type) + 2, 2, &tail);
|
|
|
|
|
if (err) {
|
|
|
|
|
err_str = "ns_type";
|
|
|
|
|
goto syntax_error;
|
|
|
|
|
}
|
|
|
|
|
if (*tail != ')') {
|
|
|
|
|
err_str = "missing ')'";
|
|
|
|
|
goto syntax_error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
syntax_error:
|
|
|
|
|
return xasprintf("%s: bad syntax for packet type %s", s, err_str);
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
static char *
|
|
|
|
|
mf_from_ethernet_string(const struct mf_field *mf, const char *s,
|
2015-08-28 14:55:11 -07:00
|
|
|
|
struct eth_addr *mac, struct eth_addr *mask)
|
2011-09-12 12:11:50 -07:00
|
|
|
|
{
|
2013-07-25 09:48:36 -07:00
|
|
|
|
int n;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2013-07-25 09:48:36 -07:00
|
|
|
|
ovs_assert(mf->n_bytes == ETH_ADDR_LEN);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2013-07-25 09:48:36 -07:00
|
|
|
|
n = -1;
|
2015-08-28 14:55:11 -07:00
|
|
|
|
if (ovs_scan(s, ETH_ADDR_SCAN_FMT"%n", ETH_ADDR_SCAN_ARGS(*mac), &n)
|
2013-07-25 09:48:36 -07:00
|
|
|
|
&& n == strlen(s)) {
|
2015-08-28 14:55:11 -07:00
|
|
|
|
*mask = eth_addr_exact;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
return NULL;
|
2013-07-25 09:48:36 -07:00
|
|
|
|
}
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2013-07-25 09:48:36 -07:00
|
|
|
|
n = -1;
|
2013-11-09 15:44:23 -08:00
|
|
|
|
if (ovs_scan(s, ETH_ADDR_SCAN_FMT"/"ETH_ADDR_SCAN_FMT"%n",
|
2015-08-28 14:55:11 -07:00
|
|
|
|
ETH_ADDR_SCAN_ARGS(*mac), ETH_ADDR_SCAN_ARGS(*mask), &n)
|
2013-07-25 09:48:36 -07:00
|
|
|
|
&& n == strlen(s)) {
|
|
|
|
|
return NULL;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
2013-07-25 09:48:36 -07:00
|
|
|
|
|
|
|
|
|
return xasprintf("%s: invalid Ethernet address", s);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
mf_from_ipv4_string(const struct mf_field *mf, const char *s,
|
|
|
|
|
ovs_be32 *ip, ovs_be32 *mask)
|
|
|
|
|
{
|
2012-11-06 13:14:55 -08:00
|
|
|
|
ovs_assert(mf->n_bytes == sizeof *ip);
|
2015-10-16 13:54:45 -07:00
|
|
|
|
return ip_parse_masked(s, ip, mask);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
mf_from_ipv6_string(const struct mf_field *mf, const char *s,
|
2015-11-10 15:08:43 -08:00
|
|
|
|
struct in6_addr *ipv6, struct in6_addr *mask)
|
2011-09-12 12:11:50 -07:00
|
|
|
|
{
|
2015-11-10 15:08:43 -08:00
|
|
|
|
ovs_assert(mf->n_bytes == sizeof *ipv6);
|
|
|
|
|
return ipv6_parse_masked(s, ipv6, mask);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
mf_from_ofp_port_string(const struct mf_field *mf, const char *s,
|
2017-05-31 16:06:12 -07:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
2011-09-12 12:11:50 -07:00
|
|
|
|
ovs_be16 *valuep, ovs_be16 *maskp)
|
|
|
|
|
{
|
2013-06-19 16:58:44 -07:00
|
|
|
|
ofp_port_t port;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2012-11-06 13:14:55 -08:00
|
|
|
|
ovs_assert(mf->n_bytes == sizeof(ovs_be16));
|
2013-05-10 22:54:35 +03:00
|
|
|
|
|
2017-05-31 16:06:12 -07:00
|
|
|
|
if (ofputil_port_from_string(s, port_map, &port)) {
|
2013-06-19 16:58:44 -07:00
|
|
|
|
*valuep = htons(ofp_to_u16(port));
|
2013-06-27 15:27:15 -07:00
|
|
|
|
*maskp = OVS_BE16_MAX;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2017-05-31 16:06:12 -07:00
|
|
|
|
return xasprintf("%s: invalid or unknown port for %s", s, mf->name);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
2013-05-19 15:44:53 +03:00
|
|
|
|
static char *
|
|
|
|
|
mf_from_ofp_port_string32(const struct mf_field *mf, const char *s,
|
2017-05-31 16:06:12 -07:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
2013-05-19 15:44:53 +03:00
|
|
|
|
ovs_be32 *valuep, ovs_be32 *maskp)
|
|
|
|
|
{
|
2013-06-19 16:58:44 -07:00
|
|
|
|
ofp_port_t port;
|
2013-05-19 15:44:53 +03:00
|
|
|
|
|
|
|
|
|
ovs_assert(mf->n_bytes == sizeof(ovs_be32));
|
2017-05-31 16:06:12 -07:00
|
|
|
|
if (ofputil_port_from_string(s, port_map, &port)) {
|
2013-05-19 15:44:53 +03:00
|
|
|
|
*valuep = ofputil_port_to_ofp11(port);
|
2013-06-27 15:27:15 -07:00
|
|
|
|
*maskp = OVS_BE32_MAX;
|
2013-05-19 15:44:53 +03:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return xasprintf("%s: port value out of range for %s", s, mf->name);
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
struct frag_handling {
|
|
|
|
|
const char *name;
|
|
|
|
|
uint8_t mask;
|
|
|
|
|
uint8_t value;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const struct frag_handling all_frags[] = {
|
2011-11-09 17:10:27 -08:00
|
|
|
|
#define A FLOW_NW_FRAG_ANY
|
|
|
|
|
#define L FLOW_NW_FRAG_LATER
|
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
|
|
|
|
/* name mask value */
|
|
|
|
|
|
|
|
|
|
{ "no", A|L, 0 },
|
|
|
|
|
{ "first", A|L, A },
|
|
|
|
|
{ "later", A|L, A|L },
|
|
|
|
|
|
|
|
|
|
{ "no", A, 0 },
|
|
|
|
|
{ "yes", A, A },
|
|
|
|
|
|
|
|
|
|
{ "not_later", L, 0 },
|
|
|
|
|
{ "later", L, L },
|
|
|
|
|
#undef A
|
|
|
|
|
#undef L
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
mf_from_frag_string(const char *s, uint8_t *valuep, uint8_t *maskp)
|
|
|
|
|
{
|
|
|
|
|
const struct frag_handling *h;
|
|
|
|
|
|
|
|
|
|
for (h = all_frags; h < &all_frags[ARRAY_SIZE(all_frags)]; h++) {
|
|
|
|
|
if (!strcasecmp(s, h->name)) {
|
|
|
|
|
/* We force the upper bits of the mask on to make mf_parse_value()
|
|
|
|
|
* happy (otherwise it will never think it's an exact match.) */
|
2011-11-09 17:10:27 -08:00
|
|
|
|
*maskp = h->mask | ~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
|
|
|
|
*valuep = h->value;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return xasprintf("%s: unknown fragment type (valid types are \"no\", "
|
|
|
|
|
"\"yes\", \"first\", \"later\", \"not_first\"", s);
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-11 20:48:29 -07:00
|
|
|
|
static char *
|
|
|
|
|
parse_mf_flags(const char *s, const char *(*bit_to_string)(uint32_t),
|
|
|
|
|
const char *field_name, ovs_be16 *flagsp, ovs_be16 allowed,
|
|
|
|
|
ovs_be16 *maskp)
|
2012-11-21 18:51:36 -08:00
|
|
|
|
{
|
2015-07-11 20:48:29 -07:00
|
|
|
|
int err;
|
|
|
|
|
char *err_str;
|
|
|
|
|
uint32_t flags, mask;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
|
2015-07-11 20:48:29 -07:00
|
|
|
|
err = parse_flags(s, bit_to_string, '\0', field_name, &err_str,
|
|
|
|
|
&flags, ntohs(allowed), maskp ? &mask : NULL);
|
|
|
|
|
if (err < 0) {
|
|
|
|
|
return err_str;
|
|
|
|
|
}
|
2012-11-21 18:51:36 -08:00
|
|
|
|
|
2015-07-11 20:48:29 -07:00
|
|
|
|
*flagsp = htons(flags);
|
|
|
|
|
if (maskp) {
|
|
|
|
|
*maskp = htons(mask);
|
2012-11-21 18:51:36 -08:00
|
|
|
|
}
|
|
|
|
|
|
2015-07-11 20:48:29 -07:00
|
|
|
|
return NULL;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
2015-07-11 20:48:29 -07:00
|
|
|
|
mf_from_tcp_flags_string(const char *s, ovs_be16 *flagsp, ovs_be16 *maskp)
|
2012-11-21 18:51:36 -08:00
|
|
|
|
{
|
2015-07-11 20:48:29 -07:00
|
|
|
|
return parse_mf_flags(s, packet_tcp_flag_to_string, "TCP", flagsp,
|
|
|
|
|
TCP_FLAGS_BE16(OVS_BE16_MAX), maskp);
|
2012-11-21 18:51:36 -08:00
|
|
|
|
}
|
|
|
|
|
|
2013-12-02 15:14:09 -08:00
|
|
|
|
static char *
|
2015-07-11 20:48:29 -07:00
|
|
|
|
mf_from_tun_flags_string(const char *s, ovs_be16 *flagsp, ovs_be16 *maskp)
|
2013-12-02 15:14:09 -08:00
|
|
|
|
{
|
2015-07-11 20:48:29 -07:00
|
|
|
|
return parse_mf_flags(s, flow_tun_flag_to_string, "tunnel", flagsp,
|
2015-07-08 16:02:30 -07:00
|
|
|
|
htons(FLOW_TNL_PUB_F_MASK), maskp);
|
2013-12-02 15:14:09 -08:00
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
static char *
|
|
|
|
|
mf_from_ct_state_string(const char *s, ovs_be32 *flagsp, ovs_be32 *maskp)
|
|
|
|
|
{
|
|
|
|
|
int err;
|
|
|
|
|
char *err_str;
|
|
|
|
|
uint32_t flags, mask;
|
|
|
|
|
|
|
|
|
|
err = parse_flags(s, ct_state_to_string, '\0', "ct_state", &err_str,
|
|
|
|
|
&flags, CS_SUPPORTED_MASK, maskp ? &mask : NULL);
|
|
|
|
|
if (err < 0) {
|
|
|
|
|
return err_str;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*flagsp = htonl(flags);
|
|
|
|
|
if (maskp) {
|
|
|
|
|
*maskp = htonl(mask);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
/* Parses 's', a string value for field 'mf', into 'value' and 'mask'. Returns
|
|
|
|
|
* NULL if successful, otherwise a malloc()'d string describing the error. */
|
|
|
|
|
char *
|
|
|
|
|
mf_parse(const struct mf_field *mf, const char *s,
|
2017-05-31 16:06:12 -07:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
2011-09-12 12:11:50 -07:00
|
|
|
|
union mf_value *value, union mf_value *mask)
|
|
|
|
|
{
|
2013-10-31 17:18:38 -07:00
|
|
|
|
char *error;
|
|
|
|
|
|
2013-01-08 15:29:44 -08:00
|
|
|
|
if (!strcmp(s, "*")) {
|
2011-09-12 12:11:50 -07:00
|
|
|
|
memset(value, 0, mf->n_bytes);
|
|
|
|
|
memset(mask, 0, mf->n_bytes);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (mf->string) {
|
|
|
|
|
case MFS_DECIMAL:
|
|
|
|
|
case MFS_HEXADECIMAL:
|
2013-10-31 17:18:38 -07:00
|
|
|
|
error = mf_from_integer_string(mf, s,
|
|
|
|
|
(uint8_t *) value, (uint8_t *) mask);
|
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
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
|
|
|
|
case MFS_CT_STATE:
|
|
|
|
|
ovs_assert(mf->n_bytes == sizeof(ovs_be32));
|
|
|
|
|
error = mf_from_ct_state_string(s, &value->be32, &mask->be32);
|
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFS_ETHERNET:
|
2015-08-28 14:55:11 -07:00
|
|
|
|
error = mf_from_ethernet_string(mf, s, &value->mac, &mask->mac);
|
2013-10-31 17:18:38 -07:00
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
|
|
|
|
case MFS_IPV4:
|
2013-10-31 17:18:38 -07:00
|
|
|
|
error = mf_from_ipv4_string(mf, s, &value->be32, &mask->be32);
|
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
|
|
|
|
case MFS_IPV6:
|
2013-10-31 17:18:38 -07:00
|
|
|
|
error = mf_from_ipv6_string(mf, s, &value->ipv6, &mask->ipv6);
|
|
|
|
|
break;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
|
|
|
|
case MFS_OFP_PORT:
|
2017-05-31 16:06:12 -07:00
|
|
|
|
error = mf_from_ofp_port_string(mf, s, port_map,
|
|
|
|
|
&value->be16, &mask->be16);
|
2013-10-31 17:18:38 -07:00
|
|
|
|
break;
|
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
|
|
|
|
|
2013-05-19 15:44:53 +03:00
|
|
|
|
case MFS_OFP_PORT_OXM:
|
2017-05-31 16:06:12 -07:00
|
|
|
|
error = mf_from_ofp_port_string32(mf, s, port_map,
|
|
|
|
|
&value->be32, &mask->be32);
|
2013-10-31 17:18:38 -07:00
|
|
|
|
break;
|
2013-05-19 15:44:53 +03: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
|
|
|
|
case MFS_FRAG:
|
2013-10-31 17:18:38 -07:00
|
|
|
|
error = mf_from_frag_string(s, &value->u8, &mask->u8);
|
|
|
|
|
break;
|
2012-11-21 18:51:36 -08:00
|
|
|
|
|
|
|
|
|
case MFS_TNL_FLAGS:
|
2012-11-06 13:14:55 -08:00
|
|
|
|
ovs_assert(mf->n_bytes == sizeof(ovs_be16));
|
2013-10-31 17:18:38 -07:00
|
|
|
|
error = mf_from_tun_flags_string(s, &value->be16, &mask->be16);
|
|
|
|
|
break;
|
|
|
|
|
|
2013-12-02 15:14:09 -08:00
|
|
|
|
case MFS_TCP_FLAGS:
|
|
|
|
|
ovs_assert(mf->n_bytes == sizeof(ovs_be16));
|
|
|
|
|
error = mf_from_tcp_flags_string(s, &value->be16, &mask->be16);
|
|
|
|
|
break;
|
|
|
|
|
|
2017-06-23 16:47:57 +00:00
|
|
|
|
case MFS_PACKET_TYPE:
|
|
|
|
|
ovs_assert(mf->n_bytes == sizeof(ovs_be32));
|
|
|
|
|
error = mf_from_packet_type_string(s, &value->be32);
|
|
|
|
|
mask->be32 = OVS_BE32_MAX;
|
|
|
|
|
break;
|
|
|
|
|
|
2013-10-31 17:18:38 -07:00
|
|
|
|
default:
|
2013-12-17 10:32:12 -08:00
|
|
|
|
OVS_NOT_REACHED();
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
2013-10-31 17:18:38 -07:00
|
|
|
|
|
|
|
|
|
if (!error && !mf_is_mask_valid(mf, mask)) {
|
|
|
|
|
error = xasprintf("%s: invalid mask for field %s", s, mf->name);
|
|
|
|
|
}
|
|
|
|
|
return error;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parses 's', a string value for field 'mf', into 'value'. Returns NULL if
|
|
|
|
|
* successful, otherwise a malloc()'d string describing the error. */
|
|
|
|
|
char *
|
2017-05-31 16:06:12 -07:00
|
|
|
|
mf_parse_value(const struct mf_field *mf, const char *s,
|
|
|
|
|
const struct ofputil_port_map *port_map, union mf_value *value)
|
2011-09-12 12:11:50 -07:00
|
|
|
|
{
|
|
|
|
|
union mf_value mask;
|
|
|
|
|
char *error;
|
|
|
|
|
|
2017-05-31 16:06:12 -07:00
|
|
|
|
error = mf_parse(mf, s, port_map, value, &mask);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
if (error) {
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!is_all_ones((const uint8_t *) &mask, mf->n_bytes)) {
|
|
|
|
|
return xasprintf("%s: wildcards not allowed here", s);
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
mf_format_integer_string(const struct mf_field *mf, const uint8_t *valuep,
|
|
|
|
|
const uint8_t *maskp, struct ds *s)
|
|
|
|
|
{
|
|
|
|
|
if (mf->string == MFS_HEXADECIMAL) {
|
2015-05-18 17:17:41 -07:00
|
|
|
|
ds_put_hex(s, valuep, mf->n_bytes);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
} else {
|
2015-05-18 17:17:41 -07:00
|
|
|
|
unsigned long long int integer = 0;
|
|
|
|
|
int i;
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2015-05-18 17:17:41 -07:00
|
|
|
|
ovs_assert(mf->n_bytes <= 8);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
for (i = 0; i < mf->n_bytes; i++) {
|
2015-05-18 17:17:41 -07:00
|
|
|
|
integer = (integer << 8) | valuep[i];
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
2015-05-18 17:17:41 -07:00
|
|
|
|
ds_put_format(s, "%lld", integer);
|
|
|
|
|
}
|
2011-09-12 12:11:50 -07:00
|
|
|
|
|
2015-05-18 17:17:41 -07:00
|
|
|
|
if (maskp) {
|
2011-09-12 12:11:50 -07:00
|
|
|
|
/* I guess we could write the mask in decimal for MFS_DECIMAL but I'm
|
|
|
|
|
* not sure that that a bit-mask written in decimal is ever easier to
|
|
|
|
|
* understand than the same bit-mask written in hexadecimal. */
|
2015-05-18 17:17:41 -07:00
|
|
|
|
ds_put_char(s, '/');
|
|
|
|
|
ds_put_hex(s, maskp, mf->n_bytes);
|
2011-09-12 12:11:50 -07: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
|
2013-01-24 13:39:23 -08:00
|
|
|
|
mf_format_frag_string(uint8_t value, uint8_t mask, struct ds *s)
|
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
|
|
|
|
{
|
|
|
|
|
const struct frag_handling *h;
|
|
|
|
|
|
2011-11-09 17:10:27 -08:00
|
|
|
|
mask &= FLOW_NW_FRAG_MASK;
|
2013-01-24 13:39:23 -08:00
|
|
|
|
value &= 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
|
|
|
|
|
|
|
|
|
for (h = all_frags; h < &all_frags[ARRAY_SIZE(all_frags)]; h++) {
|
|
|
|
|
if (value == h->value && mask == h->mask) {
|
|
|
|
|
ds_put_cstr(s, h->name);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ds_put_cstr(s, "<error>");
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-21 18:51:36 -08:00
|
|
|
|
static void
|
2015-07-08 16:02:30 -07:00
|
|
|
|
mf_format_tnl_flags_string(ovs_be16 value, ovs_be16 mask, struct ds *s)
|
2012-11-21 18:51:36 -08:00
|
|
|
|
{
|
2015-07-08 16:02:30 -07:00
|
|
|
|
format_flags_masked(s, NULL, flow_tun_flag_to_string, ntohs(value),
|
|
|
|
|
ntohs(mask) & FLOW_TNL_PUB_F_MASK, FLOW_TNL_PUB_F_MASK);
|
2012-11-21 18:51:36 -08:00
|
|
|
|
}
|
|
|
|
|
|
2013-12-02 15:14:09 -08:00
|
|
|
|
static void
|
|
|
|
|
mf_format_tcp_flags_string(ovs_be16 value, ovs_be16 mask, struct ds *s)
|
|
|
|
|
{
|
|
|
|
|
format_flags_masked(s, NULL, packet_tcp_flag_to_string, ntohs(value),
|
2015-07-11 20:48:29 -07:00
|
|
|
|
TCP_FLAGS(mask), TCP_FLAGS(OVS_BE16_MAX));
|
2013-12-02 15:14:09 -08:00
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
static void
|
|
|
|
|
mf_format_ct_state_string(ovs_be32 value, ovs_be32 mask, struct ds *s)
|
|
|
|
|
{
|
|
|
|
|
format_flags_masked(s, NULL, ct_state_to_string, ntohl(value),
|
|
|
|
|
ntohl(mask), UINT16_MAX);
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-23 16:47:57 +00:00
|
|
|
|
static void
|
|
|
|
|
mf_format_packet_type_string(ovs_be32 value, ovs_be32 mask, struct ds *s)
|
|
|
|
|
{
|
|
|
|
|
format_packet_type_masked(s, value, mask);
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
/* Appends to 's' a string representation of field 'mf' whose value is in
|
|
|
|
|
* 'value' and 'mask'. 'mask' may be NULL to indicate an exact match. */
|
|
|
|
|
void
|
|
|
|
|
mf_format(const struct mf_field *mf,
|
|
|
|
|
const union mf_value *value, const union mf_value *mask,
|
2017-05-31 16:06:12 -07:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
2011-09-12 12:11:50 -07:00
|
|
|
|
struct ds *s)
|
|
|
|
|
{
|
|
|
|
|
if (mask) {
|
2014-09-05 15:44:19 -07:00
|
|
|
|
if (is_all_zeros(mask, mf->n_bytes)) {
|
2011-09-12 12:11:50 -07:00
|
|
|
|
ds_put_cstr(s, "ANY");
|
|
|
|
|
return;
|
2014-09-05 15:44:19 -07:00
|
|
|
|
} else if (is_all_ones(mask, mf->n_bytes)) {
|
2011-09-12 12:11:50 -07:00
|
|
|
|
mask = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (mf->string) {
|
2013-05-19 15:44:53 +03:00
|
|
|
|
case MFS_OFP_PORT_OXM:
|
|
|
|
|
if (!mask) {
|
2013-06-19 16:58:44 -07:00
|
|
|
|
ofp_port_t port;
|
2013-05-20 12:21:51 -07:00
|
|
|
|
ofputil_port_from_ofp11(value->be32, &port);
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofputil_format_port(port, port_map, s);
|
2013-05-19 15:44:53 +03:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* fall through */
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFS_OFP_PORT:
|
|
|
|
|
if (!mask) {
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofputil_format_port(u16_to_ofp(ntohs(value->be16)), port_map, s);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* fall through */
|
|
|
|
|
case MFS_DECIMAL:
|
|
|
|
|
case MFS_HEXADECIMAL:
|
|
|
|
|
mf_format_integer_string(mf, (uint8_t *) value, (uint8_t *) mask, s);
|
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFS_CT_STATE:
|
|
|
|
|
mf_format_ct_state_string(value->be32,
|
|
|
|
|
mask ? mask->be32 : OVS_BE32_MAX, s);
|
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
case MFS_ETHERNET:
|
2015-08-28 14:55:11 -07:00
|
|
|
|
eth_format_masked(value->mac, mask ? &mask->mac : NULL, s);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFS_IPV4:
|
2013-06-27 15:27:15 -07:00
|
|
|
|
ip_format_masked(value->be32, mask ? mask->be32 : OVS_BE32_MAX, s);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MFS_IPV6:
|
2015-10-25 13:19:22 -07:00
|
|
|
|
ipv6_format_masked(&value->ipv6, mask ? &mask->ipv6 : NULL, s);
|
2011-09-12 12:11:50 -07:00
|
|
|
|
break;
|
|
|
|
|
|
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
|
|
|
|
case MFS_FRAG:
|
2013-01-24 13:39:23 -08:00
|
|
|
|
mf_format_frag_string(value->u8, mask ? mask->u8 : UINT8_MAX, s);
|
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
|
|
|
|
break;
|
|
|
|
|
|
2012-11-21 18:51:36 -08:00
|
|
|
|
case MFS_TNL_FLAGS:
|
2015-07-08 16:02:30 -07:00
|
|
|
|
mf_format_tnl_flags_string(value->be16,
|
|
|
|
|
mask ? mask->be16 : OVS_BE16_MAX, s);
|
2012-11-21 18:51:36 -08:00
|
|
|
|
break;
|
|
|
|
|
|
2013-12-02 15:14:09 -08:00
|
|
|
|
case MFS_TCP_FLAGS:
|
|
|
|
|
mf_format_tcp_flags_string(value->be16,
|
|
|
|
|
mask ? mask->be16 : OVS_BE16_MAX, s);
|
|
|
|
|
break;
|
|
|
|
|
|
2017-06-23 16:47:57 +00:00
|
|
|
|
case MFS_PACKET_TYPE:
|
|
|
|
|
mf_format_packet_type_string(value->be32,
|
|
|
|
|
mask ? mask->be32 : OVS_BE32_MAX, s);
|
|
|
|
|
break;
|
|
|
|
|
|
2011-09-12 12:11:50 -07:00
|
|
|
|
default:
|
2013-12-17 10:32:12 -08:00
|
|
|
|
OVS_NOT_REACHED();
|
2011-09-12 12:11:50 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
2011-12-28 12:42:14 -08:00
|
|
|
|
|
2012-09-12 17:44:28 +09:00
|
|
|
|
/* Makes subfield 'sf' within 'flow' exactly match the 'sf->n_bits'
|
|
|
|
|
* least-significant bits in 'x'.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
mf_write_subfield_flow(const struct mf_subfield *sf,
|
|
|
|
|
const union mf_subvalue *x, struct flow *flow)
|
|
|
|
|
{
|
|
|
|
|
const struct mf_field *field = sf->field;
|
|
|
|
|
union mf_value value;
|
|
|
|
|
|
|
|
|
|
mf_get_value(field, flow, &value);
|
2012-09-12 11:37:53 -07:00
|
|
|
|
bitwise_copy(x, sizeof *x, 0, &value, field->n_bytes,
|
2012-09-12 17:44:28 +09:00
|
|
|
|
sf->ofs, sf->n_bits);
|
|
|
|
|
mf_set_flow_value(field, &value, flow);
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-07 15:28:18 -07:00
|
|
|
|
/* Makes subfield 'sf' within 'match' exactly match the 'sf->n_bits'
|
2012-04-11 14:45:34 -07:00
|
|
|
|
* least-significant bits in 'x'.
|
2012-07-05 17:15:17 +09:00
|
|
|
|
*/
|
2012-04-11 14:45:34 -07:00
|
|
|
|
void
|
|
|
|
|
mf_write_subfield(const struct mf_subfield *sf, const union mf_subvalue *x,
|
2012-08-07 15:28:18 -07:00
|
|
|
|
struct match *match)
|
2012-04-11 14:45:34 -07:00
|
|
|
|
{
|
|
|
|
|
const struct mf_field *field = sf->field;
|
|
|
|
|
union mf_value value, mask;
|
|
|
|
|
|
2012-08-07 15:28:18 -07:00
|
|
|
|
mf_get(field, match, &value, &mask);
|
2012-04-11 14:45:34 -07:00
|
|
|
|
bitwise_copy(x, sizeof *x, 0, &value, field->n_bytes, sf->ofs, sf->n_bits);
|
|
|
|
|
bitwise_one ( &mask, field->n_bytes, sf->ofs, sf->n_bits);
|
2015-08-31 14:20:17 -07:00
|
|
|
|
mf_set(field, &value, &mask, match, NULL);
|
2012-04-11 14:45:34 -07:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-31 08:43:48 -07:00
|
|
|
|
void
|
|
|
|
|
mf_write_subfield_value(const struct mf_subfield *sf, const void *src,
|
|
|
|
|
struct match *match)
|
|
|
|
|
{
|
|
|
|
|
const struct mf_field *field = sf->field;
|
|
|
|
|
union mf_value value, mask;
|
|
|
|
|
unsigned int size = DIV_ROUND_UP(sf->n_bits, 8);
|
|
|
|
|
|
|
|
|
|
mf_get(field, match, &value, &mask);
|
|
|
|
|
bitwise_copy(src, size, 0, &value, field->n_bytes, sf->ofs, sf->n_bits);
|
|
|
|
|
bitwise_one ( &mask, field->n_bytes, sf->ofs, sf->n_bits);
|
|
|
|
|
mf_set(field, &value, &mask, match, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-15 15:06:23 -07:00
|
|
|
|
/* 'v' and 'm' correspond to values of 'field'. This function copies them into
|
|
|
|
|
* 'match' in the correspond positions. */
|
|
|
|
|
void
|
|
|
|
|
mf_mask_subfield(const struct mf_field *field,
|
|
|
|
|
const union mf_subvalue *v,
|
|
|
|
|
const union mf_subvalue *m,
|
|
|
|
|
struct match *match)
|
|
|
|
|
{
|
|
|
|
|
union mf_value value, mask;
|
|
|
|
|
|
|
|
|
|
mf_get(field, match, &value, &mask);
|
|
|
|
|
bitwise_copy(v, sizeof *v, 0, &value, field->n_bytes, 0, field->n_bits);
|
|
|
|
|
bitwise_copy(m, sizeof *m, 0, &mask, field->n_bytes, 0, field->n_bits);
|
2015-08-31 14:20:17 -07:00
|
|
|
|
mf_set(field, &value, &mask, match, NULL);
|
2015-04-15 15:06:23 -07:00
|
|
|
|
}
|
|
|
|
|
|
2012-04-11 14:45:34 -07:00
|
|
|
|
/* Initializes 'x' to the value of 'sf' within 'flow'. 'sf' must be valid for
|
|
|
|
|
* reading 'flow', e.g. as checked by mf_check_src(). */
|
|
|
|
|
void
|
|
|
|
|
mf_read_subfield(const struct mf_subfield *sf, const struct flow *flow,
|
|
|
|
|
union mf_subvalue *x)
|
|
|
|
|
{
|
|
|
|
|
union mf_value value;
|
|
|
|
|
|
|
|
|
|
mf_get_value(sf->field, flow, &value);
|
|
|
|
|
|
|
|
|
|
memset(x, 0, sizeof *x);
|
|
|
|
|
bitwise_copy(&value, sf->field->n_bytes, sf->ofs,
|
|
|
|
|
x, sizeof *x, 0,
|
|
|
|
|
sf->n_bits);
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-28 12:42:14 -08:00
|
|
|
|
/* Returns the value of 'sf' within 'flow'. 'sf' must be valid for reading
|
|
|
|
|
* 'flow', e.g. as checked by mf_check_src() and sf->n_bits must be 64 or
|
|
|
|
|
* less. */
|
|
|
|
|
uint64_t
|
|
|
|
|
mf_get_subfield(const struct mf_subfield *sf, const struct flow *flow)
|
|
|
|
|
{
|
|
|
|
|
union mf_value value;
|
|
|
|
|
|
|
|
|
|
mf_get_value(sf->field, flow, &value);
|
|
|
|
|
return bitwise_get(&value, sf->field->n_bytes, sf->ofs, sf->n_bits);
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-12 17:44:28 +09:00
|
|
|
|
void
|
|
|
|
|
mf_format_subvalue(const union mf_subvalue *subvalue, struct ds *s)
|
|
|
|
|
{
|
2015-05-20 18:47:21 -07:00
|
|
|
|
ds_put_hex(s, subvalue->u8, sizeof subvalue->u8);
|
2012-09-12 17:44:28 +09:00
|
|
|
|
}
|
2015-03-20 13:50:30 +09:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
field_array_set(enum mf_field_id id, const union mf_value *value,
|
|
|
|
|
struct field_array *fa)
|
|
|
|
|
{
|
2016-07-29 16:52:04 -07:00
|
|
|
|
size_t i, offset = 0;
|
|
|
|
|
|
2015-03-20 13:50:30 +09:00
|
|
|
|
ovs_assert(id < MFF_N_IDS);
|
2016-07-29 16:52:04 -07:00
|
|
|
|
|
|
|
|
|
/* Find the spot for 'id'. */
|
|
|
|
|
BITMAP_FOR_EACH_1 (i, id, fa->used.bm) {
|
|
|
|
|
offset += mf_from_id(i)->n_bytes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t value_size = mf_from_id(id)->n_bytes;
|
|
|
|
|
|
|
|
|
|
/* make room if necessary. */
|
|
|
|
|
if (!bitmap_is_set(fa->used.bm, id)) {
|
|
|
|
|
fa->values = xrealloc(fa->values, fa->values_size + value_size);
|
|
|
|
|
/* Move remainder forward, if any. */
|
|
|
|
|
if (offset < fa->values_size) {
|
|
|
|
|
memmove(fa->values + offset + value_size, fa->values + offset,
|
|
|
|
|
fa->values_size - offset);
|
|
|
|
|
}
|
|
|
|
|
fa->values_size += value_size;
|
|
|
|
|
}
|
2015-03-20 13:50:30 +09:00
|
|
|
|
bitmap_set1(fa->used.bm, id);
|
2016-07-29 16:52:04 -07:00
|
|
|
|
|
|
|
|
|
memcpy(fa->values + offset, value, value_size);
|
2015-03-20 13:50:30 +09: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
|
|
|
|
|
2017-02-17 17:47:44 -08:00
|
|
|
|
/* A wrapper for variable length mf_fields that is maintained by
|
|
|
|
|
* struct vl_mff_map.*/
|
|
|
|
|
struct vl_mf_field {
|
|
|
|
|
struct mf_field mf;
|
2017-03-13 11:28:21 -07:00
|
|
|
|
struct ovs_refcount ref_cnt;
|
2017-02-17 17:47:44 -08:00
|
|
|
|
struct cmap_node cmap_node; /* In ofproto->vl_mff_map->cmap. */
|
|
|
|
|
};
|
|
|
|
|
|
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
|
|
|
|
static inline uint32_t
|
|
|
|
|
mf_field_hash(uint32_t key)
|
|
|
|
|
{
|
|
|
|
|
return hash_int(key, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-13 11:28:21 -07:00
|
|
|
|
static void
|
|
|
|
|
vmf_delete(struct vl_mf_field *vmf)
|
|
|
|
|
{
|
|
|
|
|
if (ovs_refcount_unref(&vmf->ref_cnt) == 1) {
|
|
|
|
|
/* Postpone as this function is typically called immediately
|
|
|
|
|
* after removing from cmap. */
|
|
|
|
|
ovsrcu_postpone(free, vmf);
|
|
|
|
|
} else {
|
|
|
|
|
VLOG_WARN_RL(&rl,
|
|
|
|
|
"Attempted to delete VMF %s but refcount is nonzero!",
|
|
|
|
|
vmf->mf.name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum ofperr
|
|
|
|
|
mf_vl_mff_map_clear(struct vl_mff_map *vl_mff_map, bool force)
|
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
|
|
|
|
OVS_REQUIRES(vl_mff_map->mutex)
|
|
|
|
|
{
|
2017-02-17 17:47:44 -08:00
|
|
|
|
struct vl_mf_field *vmf;
|
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
|
|
|
|
|
2017-03-13 11:28:21 -07:00
|
|
|
|
if (!force) {
|
|
|
|
|
CMAP_FOR_EACH (vmf, cmap_node, &vl_mff_map->cmap) {
|
|
|
|
|
if (ovs_refcount_read(&vmf->ref_cnt) != 1) {
|
|
|
|
|
return OFPERR_NXTTMFC_INVALID_TLV_DEL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-17 17:47:44 -08:00
|
|
|
|
CMAP_FOR_EACH (vmf, cmap_node, &vl_mff_map->cmap) {
|
|
|
|
|
cmap_remove(&vl_mff_map->cmap, &vmf->cmap_node,
|
|
|
|
|
mf_field_hash(vmf->mf.id));
|
2017-03-13 11:28:21 -07:00
|
|
|
|
vmf_delete(vmf);
|
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
|
|
|
|
}
|
2017-03-13 11:28:21 -07:00
|
|
|
|
|
|
|
|
|
return 0;
|
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
|
|
|
|
}
|
|
|
|
|
|
2017-02-17 17:47:44 -08:00
|
|
|
|
static struct vl_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_get_vl_mff__(uint32_t id, const struct vl_mff_map *vl_mff_map)
|
|
|
|
|
{
|
2017-02-17 17:47:44 -08:00
|
|
|
|
struct vl_mf_field *vmf;
|
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
|
|
|
|
|
2017-02-17 17:47:44 -08:00
|
|
|
|
CMAP_FOR_EACH_WITH_HASH (vmf, cmap_node, mf_field_hash(id),
|
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
|
|
|
|
&vl_mff_map->cmap) {
|
2017-02-17 17:47:44 -08:00
|
|
|
|
if (vmf->mf.id == id) {
|
|
|
|
|
return vmf;
|
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
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If 'mff' is a variable length field, looks up 'vl_mff_map', returns a
|
|
|
|
|
* pointer to the variable length meta-flow field corresponding to 'mff'.
|
|
|
|
|
* Returns NULL if no mapping is existed for 'mff'. */
|
|
|
|
|
const struct mf_field *
|
|
|
|
|
mf_get_vl_mff(const struct mf_field *mff,
|
|
|
|
|
const struct vl_mff_map *vl_mff_map)
|
|
|
|
|
{
|
|
|
|
|
if (mff && mff->variable_len && vl_mff_map) {
|
2017-02-17 17:47:44 -08:00
|
|
|
|
return &mf_get_vl_mff__(mff->id, vl_mff_map)->mf;
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-13 11:28:21 -07:00
|
|
|
|
static enum ofperr
|
|
|
|
|
mf_vl_mff_map_del(struct vl_mff_map *vl_mff_map,
|
|
|
|
|
const struct ofputil_tlv_table_mod *ttm, bool force)
|
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
|
|
|
|
OVS_REQUIRES(vl_mff_map->mutex)
|
|
|
|
|
{
|
|
|
|
|
struct ofputil_tlv_map *tlv_map;
|
2017-03-13 11:28:21 -07:00
|
|
|
|
struct vl_mf_field *vmf;
|
|
|
|
|
unsigned int idx;
|
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
|
|
|
|
|
2017-03-13 11:28:21 -07:00
|
|
|
|
if (!force) {
|
|
|
|
|
LIST_FOR_EACH (tlv_map, list_node, &ttm->mappings) {
|
|
|
|
|
idx = MFF_TUN_METADATA0 + tlv_map->index;
|
|
|
|
|
if (idx >= MFF_TUN_METADATA0 + TUN_METADATA_NUM_OPTS) {
|
|
|
|
|
return OFPERR_NXTTMFC_BAD_FIELD_IDX;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vmf = mf_get_vl_mff__(idx, vl_mff_map);
|
|
|
|
|
if (vmf && ovs_refcount_read(&vmf->ref_cnt) != 1) {
|
|
|
|
|
return OFPERR_NXTTMFC_INVALID_TLV_DEL;
|
|
|
|
|
}
|
|
|
|
|
}
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LIST_FOR_EACH (tlv_map, list_node, &ttm->mappings) {
|
2017-03-13 11:28:21 -07:00
|
|
|
|
idx = MFF_TUN_METADATA0 + tlv_map->index;
|
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 (idx >= MFF_TUN_METADATA0 + TUN_METADATA_NUM_OPTS) {
|
|
|
|
|
return OFPERR_NXTTMFC_BAD_FIELD_IDX;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-13 11:28:21 -07:00
|
|
|
|
vmf = mf_get_vl_mff__(idx, vl_mff_map);
|
|
|
|
|
if (vmf) {
|
|
|
|
|
cmap_remove(&vl_mff_map->cmap, &vmf->cmap_node,
|
2017-02-17 17:47:44 -08:00
|
|
|
|
mf_field_hash(idx));
|
2017-03-13 11:28:21 -07:00
|
|
|
|
vmf_delete(vmf);
|
|
|
|
|
}
|
|
|
|
|
}
|
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
|
|
|
|
|
2017-03-13 11:28:21 -07:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
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
|
|
|
|
|
2017-03-13 11:28:21 -07:00
|
|
|
|
static enum ofperr
|
|
|
|
|
mf_vl_mff_map_add(struct vl_mff_map *vl_mff_map,
|
|
|
|
|
const struct ofputil_tlv_table_mod *ttm)
|
|
|
|
|
OVS_REQUIRES(vl_mff_map->mutex)
|
|
|
|
|
{
|
|
|
|
|
struct ofputil_tlv_map *tlv_map;
|
|
|
|
|
struct vl_mf_field *vmf;
|
|
|
|
|
unsigned int idx;
|
|
|
|
|
|
|
|
|
|
LIST_FOR_EACH (tlv_map, list_node, &ttm->mappings) {
|
|
|
|
|
idx = MFF_TUN_METADATA0 + tlv_map->index;
|
|
|
|
|
if (idx >= MFF_TUN_METADATA0 + TUN_METADATA_NUM_OPTS) {
|
|
|
|
|
return OFPERR_NXTTMFC_BAD_FIELD_IDX;
|
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
|
|
|
|
}
|
2017-03-13 11:28:21 -07:00
|
|
|
|
|
|
|
|
|
vmf = xmalloc(sizeof *vmf);
|
|
|
|
|
vmf->mf = mf_fields[idx];
|
|
|
|
|
vmf->mf.n_bytes = tlv_map->option_len;
|
|
|
|
|
vmf->mf.n_bits = tlv_map->option_len * 8;
|
|
|
|
|
vmf->mf.mapped = true;
|
|
|
|
|
ovs_refcount_init(&vmf->ref_cnt);
|
|
|
|
|
|
|
|
|
|
cmap_insert(&vl_mff_map->cmap, &vmf->cmap_node,
|
|
|
|
|
mf_field_hash(idx));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Updates the tun_metadata mf_field in 'vl_mff_map' according to 'ttm'.
|
|
|
|
|
* This function must be invoked after tun_metadata_table_mod().
|
|
|
|
|
* Returns OFPERR_NXTTMFC_BAD_FIELD_IDX, if the index for the vl_mf_field is
|
|
|
|
|
* invalid.
|
|
|
|
|
* Returns OFPERR_NXTTMFC_INVALID_TLV_DEL, if 'ttm' tries to delete an
|
|
|
|
|
* vl_mf_field that is still used by any active flow.*/
|
|
|
|
|
enum ofperr
|
|
|
|
|
mf_vl_mff_map_mod_from_tun_metadata(struct vl_mff_map *vl_mff_map,
|
|
|
|
|
const struct ofputil_tlv_table_mod *ttm)
|
|
|
|
|
OVS_REQUIRES(vl_mff_map->mutex)
|
|
|
|
|
{
|
|
|
|
|
switch (ttm->command) {
|
|
|
|
|
case NXTTMC_ADD:
|
|
|
|
|
return mf_vl_mff_map_add(vl_mff_map, ttm);
|
|
|
|
|
|
|
|
|
|
case NXTTMC_DELETE:
|
|
|
|
|
return mf_vl_mff_map_del(vl_mff_map, ttm, false);
|
|
|
|
|
|
|
|
|
|
case NXTTMC_CLEAR:
|
|
|
|
|
return mf_vl_mff_map_clear(vl_mff_map, false);
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
OVS_NOT_REACHED();
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns true if a variable length meta-flow field 'mff' is not mapped in
|
|
|
|
|
* the 'vl_mff_map'. */
|
|
|
|
|
bool
|
|
|
|
|
mf_vl_mff_invalid(const struct mf_field *mff, const struct vl_mff_map *map)
|
|
|
|
|
{
|
|
|
|
|
return map && mff && mff->variable_len && !mff->mapped;
|
|
|
|
|
}
|
2017-03-13 11:28:21 -07:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
mf_vl_mff_set_tlv_bitmap(const struct mf_field *mff, uint64_t *tlv_bitmap)
|
|
|
|
|
{
|
|
|
|
|
if (mff && mff->mapped) {
|
|
|
|
|
ovs_assert(mf_is_tun_metadata(mff));
|
|
|
|
|
ULLONG_SET1(*tlv_bitmap, mff->id - MFF_TUN_METADATA0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
mf_vl_mff_ref_cnt_mod(const struct vl_mff_map *map, uint64_t tlv_bitmap,
|
|
|
|
|
bool ref)
|
|
|
|
|
{
|
|
|
|
|
struct vl_mf_field *vmf;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (map) {
|
|
|
|
|
ULLONG_FOR_EACH_1 (i, tlv_bitmap) {
|
|
|
|
|
vmf = mf_get_vl_mff__(i + MFF_TUN_METADATA0, map);
|
|
|
|
|
if (vmf) {
|
|
|
|
|
if (ref) {
|
|
|
|
|
ovs_refcount_ref(&vmf->ref_cnt);
|
|
|
|
|
} else {
|
|
|
|
|
ovs_refcount_unref(&vmf->ref_cnt);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
VLOG_WARN("Invalid TLV index %d.", i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
mf_vl_mff_ref(const struct vl_mff_map *map, uint64_t tlv_bitmap)
|
|
|
|
|
{
|
|
|
|
|
mf_vl_mff_ref_cnt_mod(map, tlv_bitmap, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
mf_vl_mff_unref(const struct vl_mff_map *map, uint64_t tlv_bitmap)
|
|
|
|
|
{
|
|
|
|
|
mf_vl_mff_ref_cnt_mod(map, tlv_bitmap, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum ofperr
|
|
|
|
|
mf_vl_mff_nx_pull_header(struct ofpbuf *b, const struct vl_mff_map *vl_mff_map,
|
|
|
|
|
const struct mf_field **field, bool *masked,
|
|
|
|
|
uint64_t *tlv_bitmap)
|
|
|
|
|
{
|
|
|
|
|
enum ofperr error = nx_pull_header(b, vl_mff_map, field, masked);
|
|
|
|
|
if (error) {
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mf_vl_mff_set_tlv_bitmap(*field, tlv_bitmap);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum ofperr
|
|
|
|
|
mf_vl_mff_nx_pull_entry(struct ofpbuf *b, const struct vl_mff_map *vl_mff_map,
|
|
|
|
|
const struct mf_field **field, union mf_value *value,
|
|
|
|
|
union mf_value *mask, uint64_t *tlv_bitmap)
|
|
|
|
|
{
|
|
|
|
|
enum ofperr error = nx_pull_entry(b, vl_mff_map, field, value, mask);
|
|
|
|
|
if (error) {
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mf_vl_mff_set_tlv_bitmap(*field, tlv_bitmap);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum ofperr
|
|
|
|
|
mf_vl_mff_mf_from_nxm_header(uint32_t header,
|
|
|
|
|
const struct vl_mff_map *vl_mff_map,
|
|
|
|
|
const struct mf_field **field,
|
|
|
|
|
uint64_t *tlv_bitmap)
|
|
|
|
|
{
|
|
|
|
|
*field = mf_from_nxm_header(header, vl_mff_map);
|
|
|
|
|
if (mf_vl_mff_invalid(*field, vl_mff_map)) {
|
|
|
|
|
return OFPERR_NXFMFC_INVALID_TLV_FIELD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mf_vl_mff_set_tlv_bitmap(*field, tlv_bitmap);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|