2009-07-08 13:19:16 -07:00
|
|
|
|
/*
|
2012-05-02 15:21:36 -07:00
|
|
|
|
* Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
|
2009-07-08 13:19:16 -07:00
|
|
|
|
*
|
2009-06-15 15:11:30 -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:
|
2009-07-08 13:19:16 -07:00
|
|
|
|
*
|
2009-06-15 15:11:30 -07:00
|
|
|
|
* 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.
|
2009-07-08 13:19:16 -07:00
|
|
|
|
*/
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include "flow.h"
|
2011-06-06 14:21:40 -07:00
|
|
|
|
#include <assert.h>
|
2010-12-29 19:03:46 -08:00
|
|
|
|
#include <errno.h>
|
2009-07-08 13:19:16 -07:00
|
|
|
|
#include <inttypes.h>
|
|
|
|
|
#include <netinet/in.h>
|
2010-12-29 19:03:46 -08:00
|
|
|
|
#include <netinet/icmp6.h>
|
|
|
|
|
#include <netinet/ip6.h>
|
2009-07-08 13:19:16 -07:00
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
2010-10-28 17:13:18 -07:00
|
|
|
|
#include "byte-order.h"
|
2009-07-08 13:19:16 -07:00
|
|
|
|
#include "coverage.h"
|
|
|
|
|
#include "dynamic-string.h"
|
|
|
|
|
#include "hash.h"
|
|
|
|
|
#include "ofpbuf.h"
|
|
|
|
|
#include "openflow/openflow.h"
|
|
|
|
|
#include "packets.h"
|
2010-05-07 11:43:18 -07:00
|
|
|
|
#include "unaligned.h"
|
2010-07-16 11:02:49 -07:00
|
|
|
|
#include "vlog.h"
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2010-10-19 14:47:01 -07:00
|
|
|
|
VLOG_DEFINE_THIS_MODULE(flow);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
coverage: Make the coverage counters catalog program-specific.
Until now, the collection of coverage counters supported by a given OVS
program was not specific to that program. That means that, for example,
even though ovs-dpctl does not have anything to do with mac_learning, it
still has a coverage counter for it. This is confusing, at best.
This commit fixes the problem on some systems, in particular on ones that
use GCC and the GNU linker. It uses the feature of the GNU linker
described in its manual as:
If an orphaned section's name is representable as a C identifier then
the linker will automatically see PROVIDE two symbols: __start_SECNAME
and __end_SECNAME, where SECNAME is the name of the section. These
indicate the start address and end address of the orphaned section
respectively.
Systems that don't support these features retain the earlier behavior.
This commit also fixes the annoyance that files that include coverage
counters must be listed on COVERAGE_FILES in lib/automake.mk.
This commit also fixes the annoyance that modifying any source file that
includes a coverage counter caused all programs that link against
libopenvswitch.a to relink, even programs that the source file was not
linked into. For example, modifying ofproto/ofproto.c (which includes
coverage counters) caused tests/test-aes128 to relink, even though
test-aes128 does not link again ofproto.o.
2010-11-01 14:14:27 -07:00
|
|
|
|
COVERAGE_DEFINE(flow_extract);
|
|
|
|
|
|
2009-07-16 12:58:28 -07:00
|
|
|
|
static struct arp_eth_header *
|
|
|
|
|
pull_arp(struct ofpbuf *packet)
|
|
|
|
|
{
|
|
|
|
|
return ofpbuf_try_pull(packet, ARP_ETH_HEADER_LEN);
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-08 13:19:16 -07:00
|
|
|
|
static struct ip_header *
|
|
|
|
|
pull_ip(struct ofpbuf *packet)
|
|
|
|
|
{
|
|
|
|
|
if (packet->size >= IP_HEADER_LEN) {
|
|
|
|
|
struct ip_header *ip = packet->data;
|
|
|
|
|
int ip_len = IP_IHL(ip->ip_ihl_ver) * 4;
|
|
|
|
|
if (ip_len >= IP_HEADER_LEN && packet->size >= ip_len) {
|
|
|
|
|
return ofpbuf_pull(packet, ip_len);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct tcp_header *
|
2010-08-30 00:24:53 -07:00
|
|
|
|
pull_tcp(struct ofpbuf *packet)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
|
|
|
|
if (packet->size >= TCP_HEADER_LEN) {
|
|
|
|
|
struct tcp_header *tcp = packet->data;
|
|
|
|
|
int tcp_len = TCP_OFFSET(tcp->tcp_ctl) * 4;
|
|
|
|
|
if (tcp_len >= TCP_HEADER_LEN && packet->size >= tcp_len) {
|
|
|
|
|
return ofpbuf_pull(packet, tcp_len);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct udp_header *
|
2010-08-30 00:24:53 -07:00
|
|
|
|
pull_udp(struct ofpbuf *packet)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
|
|
|
|
return ofpbuf_try_pull(packet, UDP_HEADER_LEN);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct icmp_header *
|
2010-08-30 00:24:53 -07:00
|
|
|
|
pull_icmp(struct ofpbuf *packet)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
|
|
|
|
return ofpbuf_try_pull(packet, ICMP_HEADER_LEN);
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-29 19:03:46 -08:00
|
|
|
|
static struct icmp6_hdr *
|
|
|
|
|
pull_icmpv6(struct ofpbuf *packet)
|
|
|
|
|
{
|
|
|
|
|
return ofpbuf_try_pull(packet, sizeof(struct icmp6_hdr));
|
|
|
|
|
}
|
|
|
|
|
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
static void
|
2010-09-03 11:30:02 -07:00
|
|
|
|
parse_vlan(struct ofpbuf *b, struct flow *flow)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
struct qtag_prefix {
|
2010-10-26 15:24:26 -07:00
|
|
|
|
ovs_be16 eth_type; /* ETH_TYPE_VLAN */
|
|
|
|
|
ovs_be16 tci;
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
};
|
|
|
|
|
|
2010-10-26 15:24:26 -07:00
|
|
|
|
if (b->size >= sizeof(struct qtag_prefix) + sizeof(ovs_be16)) {
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
struct qtag_prefix *qp = ofpbuf_pull(b, sizeof *qp);
|
2010-11-23 10:06:28 -08:00
|
|
|
|
flow->vlan_tci = qp->tci | htons(VLAN_CFI);
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
}
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2010-10-26 15:24:26 -07:00
|
|
|
|
static ovs_be16
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
parse_ethertype(struct ofpbuf *b)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
struct llc_snap_header *llc;
|
2010-10-26 15:24:26 -07:00
|
|
|
|
ovs_be16 proto;
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
|
2010-10-26 15:24:26 -07:00
|
|
|
|
proto = *(ovs_be16 *) ofpbuf_pull(b, sizeof proto);
|
2011-01-23 18:44:44 -08:00
|
|
|
|
if (ntohs(proto) >= ETH_TYPE_MIN) {
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
return proto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (b->size < sizeof *llc) {
|
2011-01-23 18:44:44 -08:00
|
|
|
|
return htons(FLOW_DL_TYPE_NONE);
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
llc = b->data;
|
|
|
|
|
if (llc->llc.llc_dsap != LLC_DSAP_SNAP
|
|
|
|
|
|| llc->llc.llc_ssap != LLC_SSAP_SNAP
|
|
|
|
|
|| llc->llc.llc_cntl != LLC_CNTL_SNAP
|
|
|
|
|
|| memcmp(llc->snap.snap_org, SNAP_ORG_ETHERNET,
|
|
|
|
|
sizeof llc->snap.snap_org)) {
|
2011-01-23 18:44:44 -08:00
|
|
|
|
return htons(FLOW_DL_TYPE_NONE);
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ofpbuf_pull(b, sizeof *llc);
|
|
|
|
|
return llc->snap.snap_type;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-29 19:03:46 -08:00
|
|
|
|
static int
|
|
|
|
|
parse_ipv6(struct ofpbuf *packet, struct flow *flow)
|
|
|
|
|
{
|
2011-03-02 15:12:48 -08:00
|
|
|
|
const struct ip6_hdr *nh;
|
2010-12-29 19:03:46 -08:00
|
|
|
|
ovs_be32 tc_flow;
|
|
|
|
|
int nexthdr;
|
|
|
|
|
|
2011-03-02 15:12:48 -08:00
|
|
|
|
nh = ofpbuf_try_pull(packet, sizeof *nh);
|
|
|
|
|
if (!nh) {
|
|
|
|
|
return EINVAL;
|
2010-12-29 19:03:46 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nexthdr = nh->ip6_nxt;
|
|
|
|
|
|
|
|
|
|
flow->ipv6_src = nh->ip6_src;
|
|
|
|
|
flow->ipv6_dst = nh->ip6_dst;
|
|
|
|
|
|
|
|
|
|
tc_flow = get_unaligned_be32(&nh->ip6_flow);
|
2011-11-15 18:35:26 -08:00
|
|
|
|
flow->nw_tos = ntohl(tc_flow) >> 20;
|
2011-11-01 15:57:56 -07:00
|
|
|
|
flow->ipv6_label = tc_flow & htonl(IPV6_LABEL_MASK);
|
2011-11-05 15:48:12 -07:00
|
|
|
|
flow->nw_ttl = nh->ip6_hlim;
|
2010-12-29 19:03:46 -08:00
|
|
|
|
flow->nw_proto = IPPROTO_NONE;
|
|
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
if ((nexthdr != IPPROTO_HOPOPTS)
|
|
|
|
|
&& (nexthdr != IPPROTO_ROUTING)
|
|
|
|
|
&& (nexthdr != IPPROTO_DSTOPTS)
|
|
|
|
|
&& (nexthdr != IPPROTO_AH)
|
|
|
|
|
&& (nexthdr != IPPROTO_FRAGMENT)) {
|
|
|
|
|
/* It's either a terminal header (e.g., TCP, UDP) or one we
|
|
|
|
|
* don't understand. In either case, we're done with the
|
|
|
|
|
* packet, so use it to fill in 'nw_proto'. */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We only verify that at least 8 bytes of the next header are
|
|
|
|
|
* available, but many of these headers are longer. Ensure that
|
|
|
|
|
* accesses within the extension header are within those first 8
|
2011-03-02 15:12:48 -08:00
|
|
|
|
* bytes. All extension headers are required to be at least 8
|
2010-12-29 19:03:46 -08:00
|
|
|
|
* bytes. */
|
2011-03-02 15:12:48 -08:00
|
|
|
|
if (packet->size < 8) {
|
|
|
|
|
return EINVAL;
|
2010-12-29 19:03:46 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((nexthdr == IPPROTO_HOPOPTS)
|
|
|
|
|
|| (nexthdr == IPPROTO_ROUTING)
|
|
|
|
|
|| (nexthdr == IPPROTO_DSTOPTS)) {
|
|
|
|
|
/* These headers, while different, have the fields we care about
|
|
|
|
|
* in the same location and with the same interpretation. */
|
2011-03-02 15:12:48 -08:00
|
|
|
|
const struct ip6_ext *ext_hdr = (struct ip6_ext *)packet->data;
|
2010-12-29 19:03:46 -08:00
|
|
|
|
nexthdr = ext_hdr->ip6e_nxt;
|
2011-03-02 15:12:48 -08:00
|
|
|
|
if (!ofpbuf_try_pull(packet, (ext_hdr->ip6e_len + 1) * 8)) {
|
|
|
|
|
return EINVAL;
|
|
|
|
|
}
|
2010-12-29 19:03:46 -08:00
|
|
|
|
} else if (nexthdr == IPPROTO_AH) {
|
|
|
|
|
/* A standard AH definition isn't available, but the fields
|
|
|
|
|
* we care about are in the same location as the generic
|
|
|
|
|
* option header--only the header length is calculated
|
|
|
|
|
* differently. */
|
2011-03-02 15:12:48 -08:00
|
|
|
|
const struct ip6_ext *ext_hdr = (struct ip6_ext *)packet->data;
|
2010-12-29 19:03:46 -08:00
|
|
|
|
nexthdr = ext_hdr->ip6e_nxt;
|
2011-03-02 15:12:48 -08:00
|
|
|
|
if (!ofpbuf_try_pull(packet, (ext_hdr->ip6e_len + 2) * 4)) {
|
|
|
|
|
return EINVAL;
|
|
|
|
|
}
|
2010-12-29 19:03:46 -08:00
|
|
|
|
} else if (nexthdr == IPPROTO_FRAGMENT) {
|
2011-03-02 15:12:48 -08:00
|
|
|
|
const struct ip6_frag *frag_hdr = (struct ip6_frag *)packet->data;
|
2010-12-29 19:03:46 -08:00
|
|
|
|
|
|
|
|
|
nexthdr = frag_hdr->ip6f_nxt;
|
2011-03-02 15:12:48 -08:00
|
|
|
|
if (!ofpbuf_try_pull(packet, sizeof *frag_hdr)) {
|
|
|
|
|
return EINVAL;
|
|
|
|
|
}
|
2010-12-29 19:03:46 -08:00
|
|
|
|
|
|
|
|
|
/* We only process the first fragment. */
|
2011-12-01 16:09:05 -08:00
|
|
|
|
if (frag_hdr->ip6f_offlg != htons(0)) {
|
|
|
|
|
if ((frag_hdr->ip6f_offlg & IP6F_OFF_MASK) == htons(0)) {
|
|
|
|
|
flow->nw_frag = FLOW_NW_FRAG_ANY;
|
|
|
|
|
} else {
|
|
|
|
|
flow->nw_frag |= FLOW_NW_FRAG_LATER;
|
|
|
|
|
nexthdr = IPPROTO_FRAGMENT;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2010-12-29 19:03:46 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flow->nw_proto = nexthdr;
|
2011-03-02 15:12:48 -08:00
|
|
|
|
return 0;
|
2010-12-29 19:03:46 -08:00
|
|
|
|
}
|
|
|
|
|
|
2011-03-02 15:12:48 -08:00
|
|
|
|
static void
|
|
|
|
|
parse_tcp(struct ofpbuf *packet, struct ofpbuf *b, struct flow *flow)
|
|
|
|
|
{
|
|
|
|
|
const struct tcp_header *tcp = pull_tcp(b);
|
|
|
|
|
if (tcp) {
|
|
|
|
|
flow->tp_src = tcp->tcp_src;
|
|
|
|
|
flow->tp_dst = tcp->tcp_dst;
|
|
|
|
|
packet->l7 = b->data;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
parse_udp(struct ofpbuf *packet, struct ofpbuf *b, struct flow *flow)
|
|
|
|
|
{
|
|
|
|
|
const struct udp_header *udp = pull_udp(b);
|
|
|
|
|
if (udp) {
|
|
|
|
|
flow->tp_src = udp->udp_src;
|
|
|
|
|
flow->tp_dst = udp->udp_dst;
|
|
|
|
|
packet->l7 = b->data;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-02-01 22:54:11 -08:00
|
|
|
|
|
|
|
|
|
static bool
|
2011-03-02 15:12:48 -08:00
|
|
|
|
parse_icmpv6(struct ofpbuf *b, struct flow *flow)
|
2011-02-01 22:54:11 -08:00
|
|
|
|
{
|
|
|
|
|
const struct icmp6_hdr *icmp = pull_icmpv6(b);
|
|
|
|
|
|
|
|
|
|
if (!icmp) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The ICMPv6 type and code fields use the 16-bit transport port
|
|
|
|
|
* fields, so we need to store them in 16-bit network byte order. */
|
2011-10-05 11:06:12 -07:00
|
|
|
|
flow->tp_src = htons(icmp->icmp6_type);
|
|
|
|
|
flow->tp_dst = htons(icmp->icmp6_code);
|
2011-02-01 22:54:11 -08:00
|
|
|
|
|
2011-03-02 15:12:48 -08:00
|
|
|
|
if (icmp->icmp6_code == 0 &&
|
|
|
|
|
(icmp->icmp6_type == ND_NEIGHBOR_SOLICIT ||
|
|
|
|
|
icmp->icmp6_type == ND_NEIGHBOR_ADVERT)) {
|
|
|
|
|
const struct in6_addr *nd_target;
|
2011-02-01 22:54:11 -08:00
|
|
|
|
|
2011-03-02 15:12:48 -08:00
|
|
|
|
nd_target = ofpbuf_try_pull(b, sizeof *nd_target);
|
|
|
|
|
if (!nd_target) {
|
2011-02-01 22:54:11 -08:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2011-03-02 15:12:48 -08:00
|
|
|
|
flow->nd_target = *nd_target;
|
2011-02-01 22:54:11 -08:00
|
|
|
|
|
2011-03-02 15:12:48 -08:00
|
|
|
|
while (b->size >= 8) {
|
2011-02-01 22:54:11 -08:00
|
|
|
|
/* The minimum size of an option is 8 bytes, which also is
|
|
|
|
|
* the size of Ethernet link-layer options. */
|
2011-03-02 15:12:48 -08:00
|
|
|
|
const struct nd_opt_hdr *nd_opt = b->data;
|
|
|
|
|
int opt_len = nd_opt->nd_opt_len * 8;
|
|
|
|
|
|
|
|
|
|
if (!opt_len || opt_len > b->size) {
|
2011-02-01 22:54:11 -08:00
|
|
|
|
goto invalid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Store the link layer address if the appropriate option is
|
|
|
|
|
* provided. It is considered an error if the same link
|
|
|
|
|
* layer option is specified twice. */
|
|
|
|
|
if (nd_opt->nd_opt_type == ND_OPT_SOURCE_LINKADDR
|
|
|
|
|
&& opt_len == 8) {
|
|
|
|
|
if (eth_addr_is_zero(flow->arp_sha)) {
|
2011-03-02 15:12:48 -08:00
|
|
|
|
memcpy(flow->arp_sha, nd_opt + 1, ETH_ADDR_LEN);
|
2011-02-01 22:54:11 -08:00
|
|
|
|
} else {
|
|
|
|
|
goto invalid;
|
|
|
|
|
}
|
|
|
|
|
} else if (nd_opt->nd_opt_type == ND_OPT_TARGET_LINKADDR
|
|
|
|
|
&& opt_len == 8) {
|
|
|
|
|
if (eth_addr_is_zero(flow->arp_tha)) {
|
2011-03-02 15:12:48 -08:00
|
|
|
|
memcpy(flow->arp_tha, nd_opt + 1, ETH_ADDR_LEN);
|
2011-02-01 22:54:11 -08:00
|
|
|
|
} else {
|
|
|
|
|
goto invalid;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-02 15:12:48 -08:00
|
|
|
|
if (!ofpbuf_try_pull(b, opt_len)) {
|
2011-02-01 22:54:11 -08:00
|
|
|
|
goto invalid;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
invalid:
|
2011-03-02 15:12:48 -08:00
|
|
|
|
memset(&flow->nd_target, 0, sizeof(flow->nd_target));
|
|
|
|
|
memset(flow->arp_sha, 0, sizeof(flow->arp_sha));
|
|
|
|
|
memset(flow->arp_tha, 0, sizeof(flow->arp_tha));
|
2011-02-01 22:54:11 -08:00
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:52:23 -08:00
|
|
|
|
/* Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and
|
|
|
|
|
* 'ofp_in_port'.
|
|
|
|
|
*
|
2010-10-26 15:24:26 -07:00
|
|
|
|
* Initializes 'packet' header pointers as follows:
|
2010-08-13 10:46:12 -07:00
|
|
|
|
*
|
|
|
|
|
* - packet->l2 to the start of the Ethernet header.
|
|
|
|
|
*
|
|
|
|
|
* - packet->l3 to just past the Ethernet header, or just past the
|
|
|
|
|
* vlan_header if one is present, to the first byte of the payload of the
|
|
|
|
|
* Ethernet frame.
|
|
|
|
|
*
|
|
|
|
|
* - packet->l4 to just past the IPv4 header, if one is present and has a
|
|
|
|
|
* correct length, and otherwise NULL.
|
|
|
|
|
*
|
|
|
|
|
* - packet->l7 to just past the TCP or UDP or ICMP header, if one is
|
|
|
|
|
* present and has a correct length, and otherwise NULL.
|
|
|
|
|
*/
|
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
|
|
|
|
void
|
2011-12-21 15:52:23 -08:00
|
|
|
|
flow_extract(struct ofpbuf *packet, uint32_t skb_priority, ovs_be64 tun_id,
|
2011-11-01 10:13:16 -07:00
|
|
|
|
uint16_t ofp_in_port, struct flow *flow)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
|
|
|
|
struct ofpbuf b = *packet;
|
|
|
|
|
struct eth_header *eth;
|
|
|
|
|
|
|
|
|
|
COVERAGE_INC(flow_extract);
|
|
|
|
|
|
|
|
|
|
memset(flow, 0, sizeof *flow);
|
2010-04-12 11:49:16 -04:00
|
|
|
|
flow->tun_id = tun_id;
|
2011-05-11 12:13:10 -07:00
|
|
|
|
flow->in_port = ofp_in_port;
|
2011-12-21 15:52:23 -08:00
|
|
|
|
flow->skb_priority = skb_priority;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
|
|
|
|
packet->l2 = b.data;
|
|
|
|
|
packet->l3 = NULL;
|
|
|
|
|
packet->l4 = NULL;
|
|
|
|
|
packet->l7 = NULL;
|
|
|
|
|
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
if (b.size < sizeof *eth) {
|
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;
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
}
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
/* Link layer. */
|
|
|
|
|
eth = b.data;
|
|
|
|
|
memcpy(flow->dl_src, eth->eth_src, ETH_ADDR_LEN);
|
|
|
|
|
memcpy(flow->dl_dst, eth->eth_dst, ETH_ADDR_LEN);
|
|
|
|
|
|
2010-11-23 10:06:28 -08:00
|
|
|
|
/* dl_type, vlan_tci. */
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
ofpbuf_pull(&b, ETH_ADDR_LEN * 2);
|
|
|
|
|
if (eth->eth_type == htons(ETH_TYPE_VLAN)) {
|
|
|
|
|
parse_vlan(&b, flow);
|
|
|
|
|
}
|
|
|
|
|
flow->dl_type = parse_ethertype(&b);
|
|
|
|
|
|
|
|
|
|
/* Network layer. */
|
|
|
|
|
packet->l3 = b.data;
|
|
|
|
|
if (flow->dl_type == htons(ETH_TYPE_IP)) {
|
|
|
|
|
const struct ip_header *nh = pull_ip(&b);
|
|
|
|
|
if (nh) {
|
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
|
|
|
|
packet->l4 = b.data;
|
|
|
|
|
|
2010-11-15 15:53:00 -08:00
|
|
|
|
flow->nw_src = get_unaligned_be32(&nh->ip_src);
|
|
|
|
|
flow->nw_dst = get_unaligned_be32(&nh->ip_dst);
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
flow->nw_proto = nh->ip_proto;
|
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
|
|
|
|
|
2011-11-09 17:10:27 -08:00
|
|
|
|
flow->nw_tos = nh->ip_tos;
|
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
|
|
|
|
if (IP_IS_FRAGMENT(nh->ip_frag_off)) {
|
2011-11-09 17:10:27 -08:00
|
|
|
|
flow->nw_frag = FLOW_NW_FRAG_ANY;
|
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
|
|
|
|
if (nh->ip_frag_off & htons(IP_FRAG_OFF_MASK)) {
|
2011-11-09 17:10:27 -08:00
|
|
|
|
flow->nw_frag |= 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
|
|
|
|
}
|
|
|
|
|
}
|
2011-11-05 15:48:12 -07:00
|
|
|
|
flow->nw_ttl = nh->ip_ttl;
|
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
|
|
|
|
|
|
|
|
|
if (!(nh->ip_frag_off & htons(IP_FRAG_OFF_MASK))) {
|
2011-02-02 11:33:20 -08:00
|
|
|
|
if (flow->nw_proto == IPPROTO_TCP) {
|
2011-03-02 15:12:48 -08:00
|
|
|
|
parse_tcp(packet, &b, flow);
|
2011-02-02 11:33:20 -08:00
|
|
|
|
} else if (flow->nw_proto == IPPROTO_UDP) {
|
2011-03-02 15:12:48 -08:00
|
|
|
|
parse_udp(packet, &b, flow);
|
2011-02-02 11:33:20 -08:00
|
|
|
|
} else if (flow->nw_proto == IPPROTO_ICMP) {
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
const struct icmp_header *icmp = pull_icmp(&b);
|
|
|
|
|
if (icmp) {
|
2011-10-05 11:06:12 -07:00
|
|
|
|
flow->tp_src = htons(icmp->icmp_type);
|
|
|
|
|
flow->tp_dst = htons(icmp->icmp_code);
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
packet->l7 = b.data;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
2010-12-29 19:03:46 -08:00
|
|
|
|
} else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
|
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
|
|
|
|
if (parse_ipv6(&b, flow)) {
|
|
|
|
|
return;
|
2010-12-29 19:03:46 -08:00
|
|
|
|
}
|
|
|
|
|
|
2011-03-02 15:12:48 -08:00
|
|
|
|
packet->l4 = b.data;
|
|
|
|
|
if (flow->nw_proto == IPPROTO_TCP) {
|
|
|
|
|
parse_tcp(packet, &b, flow);
|
|
|
|
|
} else if (flow->nw_proto == IPPROTO_UDP) {
|
|
|
|
|
parse_udp(packet, &b, flow);
|
|
|
|
|
} else if (flow->nw_proto == IPPROTO_ICMPV6) {
|
|
|
|
|
if (parse_icmpv6(&b, flow)) {
|
|
|
|
|
packet->l7 = b.data;
|
2010-12-29 19:03:46 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
} else if (flow->dl_type == htons(ETH_TYPE_ARP)) {
|
|
|
|
|
const struct arp_eth_header *arp = pull_arp(&b);
|
|
|
|
|
if (arp && arp->ar_hrd == htons(1)
|
2010-08-30 00:24:53 -07:00
|
|
|
|
&& arp->ar_pro == htons(ETH_TYPE_IP)
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
&& arp->ar_hln == ETH_ADDR_LEN
|
|
|
|
|
&& arp->ar_pln == 4) {
|
|
|
|
|
/* We only match on the lower 8 bits of the opcode. */
|
|
|
|
|
if (ntohs(arp->ar_op) <= 0xff) {
|
|
|
|
|
flow->nw_proto = ntohs(arp->ar_op);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
2009-07-16 12:58:28 -07:00
|
|
|
|
|
2010-08-30 00:24:53 -07:00
|
|
|
|
if ((flow->nw_proto == ARP_OP_REQUEST)
|
datapath: Fix handling of 802.1Q and SNAP headers.
The kernel and user datapaths have code that assumes that 802.1Q headers
are used only inside Ethernet II frames, not inside SNAP-encapsulated
frames. But the kernel and user flow_extract() implementations would
interpret 802.1Q headers inside SNAP headers as being valid VLANs. This
would cause packet corruption if any VLAN-related actions were to be taken,
so change the two flow_extract() implementations only to accept 802.1Q as
an Ethernet II frame type, not as a SNAP-encoded frame type.
802.1Q-2005 says that this is correct anyhow:
Where the ISS instance used to transmit and receive tagged frames is
provided by a media access control method that can support Ethernet
Type encoding directly (e.g., is an IEEE 802.3 or IEEE 802.11 MAC) or
is media access method independent (e.g., 6.6), the TPID is Ethernet
Type encoded, i.e., is two octets in length and comprises solely the
assigned Ethernet Type value.
Where the ISS instance is provided by a media access method that
cannot directly support Ethernet Type encoding (e.g., is an IEEE
802.5 or FDDI MAC), the TPID is encoded according to the rule for
a Subnetwork Access Protocol (Clause 10 of IEEE Std 802) that
encapsulates Ethernet frames over LLC, and comprises the SNAP
header (AA-AA-03) followed by the SNAP PID (00-00-00) followed by
the two octets of the assigned Ethernet Type value.
All of the media that OVS handles supports Ethernet Type fields, so to me
that means that we don't have to handle 802.1Q-inside-SNAP.
On the other hand, we *do* have to handle SNAP-inside-802.1Q, because this
is actually allowed by the standards. So this commit also adds that
support.
I verified that, with this change, both SNAP and Ethernet packets are
properly recognized both with and without 802.1Q encapsulation.
I was a bit surprised to find out that Linux does not accept
SNAP-encapsulated IP frames on Ethernet.
Here's a summary of how frames are handled before and after this commit:
Common cases
------------
Ethernet
+------------+
1. |dst|src|TYPE|
+------------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
2. |dst|src| len| |aa|aa|03| |000000|TYPE|
+------------+ +--------+ +-----------+
Ethernet 802.1Q
+------------+ +---------+
3. |dst|src|8100| |VLAN|TYPE|
+------------+ +---------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
4. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |000000|TYPE|
+------------+ +---------+ +--------+ +-----------+
Unusual cases
-------------
Ethernet LLC SNAP 802.1Q
+------------+ +--------+ +-----------+ +---------+
5. |dst|src| len| |aa|aa|03| |000000|8100| |VLAN|TYPE|
+------------+ +--------+ +-----------+ +---------+
Ethernet LLC
+------------+ +--------+
6. |dst|src| len| |xx|xx|xx|
+------------+ +--------+
Ethernet LLC SNAP
+------------+ +--------+ +-----------+
7. |dst|src| len| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +--------+ +-----------+
Ethernet 802.1Q LLC
+------------+ +---------+ +--------+
8. |dst|src|8100| |VLAN| LEN| |xx|xx|xx|
+------------+ +---------+ +--------+
Ethernet 802.1Q LLC SNAP
+------------+ +---------+ +--------+ +-----------+
9. |dst|src|8100| |VLAN| LEN| |aa|aa|03| |xxxxxx|xxxx|
+------------+ +---------+ +--------+ +-----------+
Behavior
--------
--------------- --------------- -------------------------------------
Before After
this commit this commit
dl_type dl_vlan dl_type dl_vlan Notes
------- ------- ------- ------- -------------------------------------
1. TYPE ffff TYPE ffff no change
2. TYPE ffff TYPE ffff no change
3. TYPE VLAN TYPE VLAN no change
4. LEN VLAN TYPE VLAN proposal fixes behavior
5. TYPE VLAN 8100 ffff 802.1Q says this is invalid framing
6. 05ff ffff 05ff ffff no change
7. 05ff ffff 05ff ffff no change
8. LEN VLAN 05ff VLAN proposal fixes behavior
9. LEN VLAN 05ff VLAN proposal fixes behavior
Signed-off-by: Ben Pfaff <blp@nicira.com>
2010-08-10 11:35:46 -07:00
|
|
|
|
|| (flow->nw_proto == ARP_OP_REPLY)) {
|
|
|
|
|
flow->nw_src = arp->ar_spa;
|
|
|
|
|
flow->nw_dst = arp->ar_tpa;
|
2010-12-07 14:02:17 -08:00
|
|
|
|
memcpy(flow->arp_sha, arp->ar_sha, ETH_ADDR_LEN);
|
|
|
|
|
memcpy(flow->arp_tha, arp->ar_tha, ETH_ADDR_LEN);
|
2009-07-16 12:58:28 -07:00
|
|
|
|
}
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-19 09:39:16 -07:00
|
|
|
|
/* For every bit of a field that is wildcarded in 'wildcards', sets the
|
|
|
|
|
* corresponding bit in 'flow' to zero. */
|
|
|
|
|
void
|
|
|
|
|
flow_zero_wildcards(struct flow *flow, const struct flow_wildcards *wildcards)
|
|
|
|
|
{
|
|
|
|
|
const flow_wildcards_t wc = wildcards->wildcards;
|
|
|
|
|
int i;
|
|
|
|
|
|
2012-07-18 12:02:19 +09:00
|
|
|
|
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 13);
|
2011-08-19 09:39:16 -07:00
|
|
|
|
|
|
|
|
|
for (i = 0; i < FLOW_N_REGS; i++) {
|
|
|
|
|
flow->regs[i] &= wildcards->reg_masks[i];
|
|
|
|
|
}
|
|
|
|
|
flow->tun_id &= wildcards->tun_id_mask;
|
2012-06-27 01:09:44 +12:00
|
|
|
|
flow->metadata &= wildcards->metadata_mask;
|
2011-08-19 09:39:16 -07:00
|
|
|
|
flow->nw_src &= wildcards->nw_src_mask;
|
|
|
|
|
flow->nw_dst &= wildcards->nw_dst_mask;
|
|
|
|
|
if (wc & FWW_IN_PORT) {
|
|
|
|
|
flow->in_port = 0;
|
|
|
|
|
}
|
|
|
|
|
flow->vlan_tci &= wildcards->vlan_tci_mask;
|
|
|
|
|
if (wc & FWW_DL_TYPE) {
|
2011-11-09 23:54:33 -08:00
|
|
|
|
flow->dl_type = htons(0);
|
2011-08-19 09:39:16 -07:00
|
|
|
|
}
|
2012-01-27 17:16:05 -08:00
|
|
|
|
flow->tp_src &= wildcards->tp_src_mask;
|
|
|
|
|
flow->tp_dst &= wildcards->tp_dst_mask;
|
2012-05-29 00:38:21 +12:00
|
|
|
|
eth_addr_bitand(flow->dl_src, wildcards->dl_src_mask, flow->dl_src);
|
|
|
|
|
eth_addr_bitand(flow->dl_dst, wildcards->dl_dst_mask, flow->dl_dst);
|
2011-08-19 09:39:16 -07:00
|
|
|
|
if (wc & FWW_NW_PROTO) {
|
|
|
|
|
flow->nw_proto = 0;
|
|
|
|
|
}
|
2012-07-18 12:02:19 +09:00
|
|
|
|
flow->ipv6_label &= wildcards->ipv6_label_mask;
|
2011-11-09 23:39:16 -08:00
|
|
|
|
if (wc & FWW_NW_DSCP) {
|
|
|
|
|
flow->nw_tos &= ~IP_DSCP_MASK;
|
|
|
|
|
}
|
|
|
|
|
if (wc & FWW_NW_ECN) {
|
|
|
|
|
flow->nw_tos &= ~IP_ECN_MASK;
|
|
|
|
|
}
|
2011-11-05 15:48:12 -07:00
|
|
|
|
if (wc & FWW_NW_TTL) {
|
|
|
|
|
flow->nw_ttl = 0;
|
|
|
|
|
}
|
2011-11-09 17:10:27 -08:00
|
|
|
|
flow->nw_frag &= wildcards->nw_frag_mask;
|
2011-08-19 09:39:16 -07:00
|
|
|
|
if (wc & FWW_ARP_SHA) {
|
|
|
|
|
memset(flow->arp_sha, 0, sizeof flow->arp_sha);
|
|
|
|
|
}
|
|
|
|
|
if (wc & FWW_ARP_THA) {
|
|
|
|
|
memset(flow->arp_tha, 0, sizeof flow->arp_tha);
|
|
|
|
|
}
|
|
|
|
|
flow->ipv6_src = ipv6_addr_bitand(&flow->ipv6_src,
|
|
|
|
|
&wildcards->ipv6_src_mask);
|
|
|
|
|
flow->ipv6_dst = ipv6_addr_bitand(&flow->ipv6_dst,
|
|
|
|
|
&wildcards->ipv6_dst_mask);
|
2012-04-25 15:48:40 -07:00
|
|
|
|
flow->nd_target = ipv6_addr_bitand(&flow->nd_target,
|
|
|
|
|
&wildcards->nd_target_mask);
|
2011-12-21 15:52:23 -08:00
|
|
|
|
flow->skb_priority = 0;
|
2011-08-19 09:39:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2012-01-04 16:40:13 -08:00
|
|
|
|
/* Initializes 'fmd' with the metadata found in 'flow'. */
|
|
|
|
|
void
|
|
|
|
|
flow_get_metadata(const struct flow *flow, struct flow_metadata *fmd)
|
|
|
|
|
{
|
2012-07-18 12:02:19 +09:00
|
|
|
|
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 13);
|
2012-03-08 14:44:54 -08:00
|
|
|
|
|
2012-01-04 16:40:13 -08:00
|
|
|
|
fmd->tun_id = flow->tun_id;
|
|
|
|
|
fmd->tun_id_mask = htonll(UINT64_MAX);
|
|
|
|
|
|
2012-06-27 01:09:44 +12:00
|
|
|
|
fmd->metadata = flow->metadata;
|
|
|
|
|
fmd->metadata_mask = htonll(UINT64_MAX);
|
|
|
|
|
|
2012-01-04 16:40:13 -08:00
|
|
|
|
memcpy(fmd->regs, flow->regs, sizeof fmd->regs);
|
|
|
|
|
memset(fmd->reg_masks, 0xff, sizeof fmd->reg_masks);
|
|
|
|
|
|
|
|
|
|
fmd->in_port = flow->in_port;
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-08 13:19:16 -07:00
|
|
|
|
char *
|
2010-09-03 11:30:02 -07:00
|
|
|
|
flow_to_string(const struct flow *flow)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
|
|
|
|
struct ds ds = DS_EMPTY_INITIALIZER;
|
|
|
|
|
flow_format(&ds, flow);
|
|
|
|
|
return ds_cstr(&ds);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2010-09-03 11:30:02 -07:00
|
|
|
|
flow_format(struct ds *ds, const struct flow *flow)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2011-12-20 12:57:04 -08:00
|
|
|
|
ds_put_format(ds, "priority:%"PRIu32
|
|
|
|
|
",tunnel:%#"PRIx64
|
2012-06-27 01:09:44 +12:00
|
|
|
|
",metadata:%#"PRIx64
|
2011-12-20 12:57:04 -08:00
|
|
|
|
",in_port:%04"PRIx16,
|
2011-12-21 15:52:23 -08:00
|
|
|
|
flow->skb_priority,
|
2011-11-01 10:13:16 -07:00
|
|
|
|
ntohll(flow->tun_id),
|
2012-06-27 01:09:44 +12:00
|
|
|
|
ntohll(flow->metadata),
|
2011-11-01 10:13:16 -07:00
|
|
|
|
flow->in_port);
|
|
|
|
|
|
2011-12-20 12:57:04 -08:00
|
|
|
|
ds_put_format(ds, ",tci(");
|
2010-11-23 10:06:28 -08:00
|
|
|
|
if (flow->vlan_tci) {
|
2011-12-20 12:57:04 -08:00
|
|
|
|
ds_put_format(ds, "vlan:%"PRIu16",pcp:%d",
|
2010-11-23 10:06:28 -08:00
|
|
|
|
vlan_tci_to_vid(flow->vlan_tci),
|
|
|
|
|
vlan_tci_to_pcp(flow->vlan_tci));
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_char(ds, '0');
|
|
|
|
|
}
|
2011-12-20 12:57:04 -08:00
|
|
|
|
ds_put_format(ds, ") mac("ETH_ADDR_FMT"->"ETH_ADDR_FMT
|
|
|
|
|
") type:%04"PRIx16,
|
2010-04-12 11:49:16 -04:00
|
|
|
|
ETH_ADDR_ARGS(flow->dl_src),
|
|
|
|
|
ETH_ADDR_ARGS(flow->dl_dst),
|
2010-12-29 19:03:46 -08:00
|
|
|
|
ntohs(flow->dl_type));
|
|
|
|
|
|
|
|
|
|
if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
|
2011-12-20 12:57:04 -08:00
|
|
|
|
ds_put_format(ds, " label:%#"PRIx32" proto:%"PRIu8" tos:%#"PRIx8
|
|
|
|
|
" ttl:%"PRIu8" ipv6(",
|
2011-11-05 15:48:12 -07:00
|
|
|
|
ntohl(flow->ipv6_label), flow->nw_proto,
|
2011-11-09 17:10:27 -08:00
|
|
|
|
flow->nw_tos, flow->nw_ttl);
|
2010-12-29 19:03:46 -08:00
|
|
|
|
print_ipv6_addr(ds, &flow->ipv6_src);
|
|
|
|
|
ds_put_cstr(ds, "->");
|
|
|
|
|
print_ipv6_addr(ds, &flow->ipv6_dst);
|
2011-12-20 12:57:04 -08:00
|
|
|
|
ds_put_char(ds, ')');
|
2010-12-29 19:03:46 -08:00
|
|
|
|
} else {
|
2011-12-20 12:57:04 -08:00
|
|
|
|
ds_put_format(ds, " proto:%"PRIu8" tos:%#"PRIx8" ttl:%"PRIu8
|
|
|
|
|
" ip("IP_FMT"->"IP_FMT")",
|
|
|
|
|
flow->nw_proto, flow->nw_tos, flow->nw_ttl,
|
|
|
|
|
IP_ARGS(&flow->nw_src), IP_ARGS(&flow->nw_dst));
|
2010-12-29 19:03:46 -08:00
|
|
|
|
}
|
2011-11-09 17:10:27 -08:00
|
|
|
|
if (flow->nw_frag) {
|
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
|
|
|
|
ds_put_format(ds, " frag(%s)",
|
2011-11-09 17:10:27 -08:00
|
|
|
|
flow->nw_frag == FLOW_NW_FRAG_ANY ? "first"
|
|
|
|
|
: flow->nw_frag == (FLOW_NW_FRAG_ANY | FLOW_NW_FRAG_LATER)
|
2011-11-02 18:17:36 -07:00
|
|
|
|
? "later" : "<error>");
|
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
|
|
|
|
}
|
2010-12-07 14:02:17 -08:00
|
|
|
|
if (flow->tp_src || flow->tp_dst) {
|
2011-12-20 12:57:04 -08:00
|
|
|
|
ds_put_format(ds, " port(%"PRIu16"->%"PRIu16")",
|
2010-12-07 14:02:17 -08:00
|
|
|
|
ntohs(flow->tp_src), ntohs(flow->tp_dst));
|
|
|
|
|
}
|
|
|
|
|
if (!eth_addr_is_zero(flow->arp_sha) || !eth_addr_is_zero(flow->arp_tha)) {
|
2011-12-20 12:57:04 -08:00
|
|
|
|
ds_put_format(ds, " arp_ha("ETH_ADDR_FMT"->"ETH_ADDR_FMT")",
|
2010-12-07 14:02:17 -08:00
|
|
|
|
ETH_ADDR_ARGS(flow->arp_sha),
|
|
|
|
|
ETH_ADDR_ARGS(flow->arp_tha));
|
|
|
|
|
}
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2010-09-03 11:30:02 -07:00
|
|
|
|
flow_print(FILE *stream, const struct flow *flow)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
|
|
|
|
char *s = flow_to_string(flow);
|
|
|
|
|
fputs(s, stream);
|
|
|
|
|
free(s);
|
|
|
|
|
}
|
2010-10-20 16:33:10 -07:00
|
|
|
|
|
|
|
|
|
/* flow_wildcards functions. */
|
|
|
|
|
|
2010-11-10 14:39:54 -08:00
|
|
|
|
/* Initializes 'wc' as a set of wildcards that matches every packet. */
|
2010-10-20 16:33:10 -07:00
|
|
|
|
void
|
2010-11-10 14:39:54 -08:00
|
|
|
|
flow_wildcards_init_catchall(struct flow_wildcards *wc)
|
2010-10-20 16:33:10 -07:00
|
|
|
|
{
|
2012-07-18 12:02:19 +09:00
|
|
|
|
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 13);
|
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
|
|
|
|
|
2010-11-10 14:39:54 -08:00
|
|
|
|
wc->wildcards = FWW_ALL;
|
2011-01-20 15:29:00 -08:00
|
|
|
|
wc->tun_id_mask = htonll(0);
|
2010-11-10 14:39:54 -08:00
|
|
|
|
wc->nw_src_mask = htonl(0);
|
|
|
|
|
wc->nw_dst_mask = htonl(0);
|
2010-12-29 19:03:46 -08:00
|
|
|
|
wc->ipv6_src_mask = in6addr_any;
|
|
|
|
|
wc->ipv6_dst_mask = in6addr_any;
|
2012-07-18 12:02:19 +09:00
|
|
|
|
wc->ipv6_label_mask = htonl(0);
|
2012-04-25 15:48:40 -07:00
|
|
|
|
wc->nd_target_mask = in6addr_any;
|
2010-11-11 10:41:33 -08:00
|
|
|
|
memset(wc->reg_masks, 0, sizeof wc->reg_masks);
|
2012-06-27 01:09:44 +12:00
|
|
|
|
wc->metadata_mask = htonll(0);
|
2010-11-23 10:06:28 -08:00
|
|
|
|
wc->vlan_tci_mask = htons(0);
|
2011-11-09 17:10:27 -08:00
|
|
|
|
wc->nw_frag_mask = 0;
|
2012-01-27 17:16:05 -08:00
|
|
|
|
wc->tp_src_mask = htons(0);
|
|
|
|
|
wc->tp_dst_mask = htons(0);
|
2012-05-29 00:38:21 +12:00
|
|
|
|
memset(wc->dl_src_mask, 0, ETH_ADDR_LEN);
|
|
|
|
|
memset(wc->dl_dst_mask, 0, ETH_ADDR_LEN);
|
2011-10-04 11:49:22 -07:00
|
|
|
|
memset(wc->zeros, 0, sizeof wc->zeros);
|
2010-10-20 16:33:10 -07:00
|
|
|
|
}
|
|
|
|
|
|
2010-10-27 20:15:56 -07:00
|
|
|
|
/* Initializes 'wc' as an exact-match set of wildcards; that is, 'wc' does not
|
|
|
|
|
* wildcard any bits or fields. */
|
|
|
|
|
void
|
|
|
|
|
flow_wildcards_init_exact(struct flow_wildcards *wc)
|
|
|
|
|
{
|
2012-07-18 12:02:19 +09:00
|
|
|
|
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 13);
|
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
|
|
|
|
|
2010-11-11 10:41:33 -08:00
|
|
|
|
wc->wildcards = 0;
|
2011-01-20 15:29:00 -08:00
|
|
|
|
wc->tun_id_mask = htonll(UINT64_MAX);
|
2010-11-11 10:41:33 -08:00
|
|
|
|
wc->nw_src_mask = htonl(UINT32_MAX);
|
|
|
|
|
wc->nw_dst_mask = htonl(UINT32_MAX);
|
2010-12-29 19:03:46 -08:00
|
|
|
|
wc->ipv6_src_mask = in6addr_exact;
|
|
|
|
|
wc->ipv6_dst_mask = in6addr_exact;
|
2012-07-18 12:02:19 +09:00
|
|
|
|
wc->ipv6_label_mask = htonl(UINT32_MAX);
|
2012-04-25 15:48:40 -07:00
|
|
|
|
wc->nd_target_mask = in6addr_exact;
|
2010-11-11 10:41:33 -08:00
|
|
|
|
memset(wc->reg_masks, 0xff, sizeof wc->reg_masks);
|
2012-06-27 01:09:44 +12:00
|
|
|
|
wc->metadata_mask = htonll(UINT64_MAX);
|
2010-11-23 10:06:28 -08:00
|
|
|
|
wc->vlan_tci_mask = htons(UINT16_MAX);
|
2011-11-09 17:10:27 -08:00
|
|
|
|
wc->nw_frag_mask = UINT8_MAX;
|
2012-01-27 17:16:05 -08:00
|
|
|
|
wc->tp_src_mask = htons(UINT16_MAX);
|
|
|
|
|
wc->tp_dst_mask = htons(UINT16_MAX);
|
2012-05-29 00:38:21 +12:00
|
|
|
|
memset(wc->dl_src_mask, 0xff, ETH_ADDR_LEN);
|
|
|
|
|
memset(wc->dl_dst_mask, 0xff, ETH_ADDR_LEN);
|
2011-10-04 11:49:22 -07:00
|
|
|
|
memset(wc->zeros, 0, sizeof wc->zeros);
|
2010-10-27 20:15:56 -07:00
|
|
|
|
}
|
|
|
|
|
|
2010-11-08 16:45:00 -08:00
|
|
|
|
/* Returns true if 'wc' is exact-match, false if 'wc' wildcards any bits or
|
|
|
|
|
* fields. */
|
|
|
|
|
bool
|
|
|
|
|
flow_wildcards_is_exact(const struct flow_wildcards *wc)
|
|
|
|
|
{
|
2010-11-10 14:39:54 -08:00
|
|
|
|
int i;
|
2010-11-08 16:45:00 -08:00
|
|
|
|
|
2012-07-18 12:02:19 +09:00
|
|
|
|
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 13);
|
2011-09-12 16:38:52 -07:00
|
|
|
|
|
2010-11-10 14:39:54 -08:00
|
|
|
|
if (wc->wildcards
|
2011-01-20 15:29:00 -08:00
|
|
|
|
|| wc->tun_id_mask != htonll(UINT64_MAX)
|
2010-11-10 14:39:54 -08:00
|
|
|
|
|| wc->nw_src_mask != htonl(UINT32_MAX)
|
2010-11-23 10:06:28 -08:00
|
|
|
|
|| wc->nw_dst_mask != htonl(UINT32_MAX)
|
2012-01-27 17:16:05 -08:00
|
|
|
|
|| wc->tp_src_mask != htons(UINT16_MAX)
|
|
|
|
|
|| wc->tp_dst_mask != htons(UINT16_MAX)
|
2010-12-29 19:03:46 -08:00
|
|
|
|
|| wc->vlan_tci_mask != htons(UINT16_MAX)
|
2012-06-27 01:09:44 +12:00
|
|
|
|
|| wc->metadata_mask != htonll(UINT64_MAX)
|
2012-05-29 00:38:21 +12:00
|
|
|
|
|| !eth_mask_is_exact(wc->dl_src_mask)
|
|
|
|
|
|| !eth_mask_is_exact(wc->dl_dst_mask)
|
2010-12-29 19:03:46 -08:00
|
|
|
|
|| !ipv6_mask_is_exact(&wc->ipv6_src_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
|
|
|
|
|| !ipv6_mask_is_exact(&wc->ipv6_dst_mask)
|
2012-07-18 12:02:19 +09:00
|
|
|
|
|| wc->ipv6_label_mask != htonl(UINT32_MAX)
|
2012-04-25 15:48:40 -07:00
|
|
|
|
|| !ipv6_mask_is_exact(&wc->nd_target_mask)
|
2011-11-09 17:10:27 -08:00
|
|
|
|
|| wc->nw_frag_mask != UINT8_MAX) {
|
2010-11-10 14:39:54 -08:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < FLOW_N_REGS; i++) {
|
2011-05-06 11:27:05 -07:00
|
|
|
|
if (wc->reg_masks[i] != UINT32_MAX) {
|
2010-11-10 14:39:54 -08:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
2010-11-03 11:00:58 -07:00
|
|
|
|
}
|
|
|
|
|
|
2011-09-12 16:38:52 -07:00
|
|
|
|
/* Returns true if 'wc' matches every packet, false if 'wc' fixes any bits or
|
|
|
|
|
* fields. */
|
|
|
|
|
bool
|
|
|
|
|
flow_wildcards_is_catchall(const struct flow_wildcards *wc)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
2012-07-18 12:02:19 +09:00
|
|
|
|
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 13);
|
2011-09-12 16:38:52 -07:00
|
|
|
|
|
|
|
|
|
if (wc->wildcards != FWW_ALL
|
|
|
|
|
|| wc->tun_id_mask != htonll(0)
|
|
|
|
|
|| wc->nw_src_mask != htonl(0)
|
|
|
|
|
|| wc->nw_dst_mask != htonl(0)
|
2012-01-27 17:16:05 -08:00
|
|
|
|
|| wc->tp_src_mask != htons(0)
|
|
|
|
|
|| wc->tp_dst_mask != htons(0)
|
2011-09-12 16:38:52 -07:00
|
|
|
|
|| wc->vlan_tci_mask != htons(0)
|
2012-06-27 01:09:44 +12:00
|
|
|
|
|| wc->metadata_mask != htonll(0)
|
2012-05-29 00:38:21 +12:00
|
|
|
|
|| !eth_addr_is_zero(wc->dl_src_mask)
|
|
|
|
|
|| !eth_addr_is_zero(wc->dl_dst_mask)
|
2011-09-12 16:38:52 -07:00
|
|
|
|
|| !ipv6_mask_is_any(&wc->ipv6_src_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
|
|
|
|
|| !ipv6_mask_is_any(&wc->ipv6_dst_mask)
|
2012-07-18 12:02:19 +09:00
|
|
|
|
|| wc->ipv6_label_mask != htonl(0)
|
2012-04-25 15:48:40 -07:00
|
|
|
|
|| !ipv6_mask_is_any(&wc->nd_target_mask)
|
2011-11-09 17:10:27 -08:00
|
|
|
|
|| wc->nw_frag_mask != 0) {
|
2011-09-12 16:38:52 -07:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < FLOW_N_REGS; i++) {
|
|
|
|
|
if (wc->reg_masks[i] != 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-03 11:00:58 -07:00
|
|
|
|
/* Initializes 'dst' as the combination of wildcards in 'src1' and 'src2'.
|
|
|
|
|
* That is, a bit or a field is wildcarded in 'dst' if it is wildcarded in
|
|
|
|
|
* 'src1' or 'src2' or both. */
|
|
|
|
|
void
|
|
|
|
|
flow_wildcards_combine(struct flow_wildcards *dst,
|
|
|
|
|
const struct flow_wildcards *src1,
|
|
|
|
|
const struct flow_wildcards *src2)
|
|
|
|
|
{
|
2010-11-11 10:41:33 -08:00
|
|
|
|
int i;
|
2010-11-03 11:00:58 -07:00
|
|
|
|
|
2012-07-18 12:02:19 +09:00
|
|
|
|
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 13);
|
2012-01-27 15:38:53 -08:00
|
|
|
|
|
2010-11-10 14:39:54 -08:00
|
|
|
|
dst->wildcards = src1->wildcards | src2->wildcards;
|
2011-01-20 15:29:00 -08:00
|
|
|
|
dst->tun_id_mask = src1->tun_id_mask & src2->tun_id_mask;
|
2010-11-03 11:00:58 -07:00
|
|
|
|
dst->nw_src_mask = src1->nw_src_mask & src2->nw_src_mask;
|
|
|
|
|
dst->nw_dst_mask = src1->nw_dst_mask & src2->nw_dst_mask;
|
2010-12-29 19:03:46 -08:00
|
|
|
|
dst->ipv6_src_mask = ipv6_addr_bitand(&src1->ipv6_src_mask,
|
|
|
|
|
&src2->ipv6_src_mask);
|
|
|
|
|
dst->ipv6_dst_mask = ipv6_addr_bitand(&src1->ipv6_dst_mask,
|
|
|
|
|
&src2->ipv6_dst_mask);
|
2012-07-18 12:02:19 +09:00
|
|
|
|
dst->ipv6_label_mask = src1->ipv6_label_mask & src2->ipv6_label_mask;
|
2012-04-25 15:48:40 -07:00
|
|
|
|
dst->nd_target_mask = ipv6_addr_bitand(&src1->nd_target_mask,
|
|
|
|
|
&src2->nd_target_mask);
|
2010-11-11 10:41:33 -08:00
|
|
|
|
for (i = 0; i < FLOW_N_REGS; i++) {
|
|
|
|
|
dst->reg_masks[i] = src1->reg_masks[i] & src2->reg_masks[i];
|
|
|
|
|
}
|
2012-06-27 01:09:44 +12:00
|
|
|
|
dst->metadata_mask = src1->metadata_mask & src2->metadata_mask;
|
2010-11-23 10:06:28 -08:00
|
|
|
|
dst->vlan_tci_mask = src1->vlan_tci_mask & src2->vlan_tci_mask;
|
2012-01-27 17:16:05 -08:00
|
|
|
|
dst->tp_src_mask = src1->tp_src_mask & src2->tp_src_mask;
|
|
|
|
|
dst->tp_dst_mask = src1->tp_dst_mask & src2->tp_dst_mask;
|
2012-05-29 00:38:21 +12:00
|
|
|
|
eth_addr_bitand(src1->dl_src_mask, src2->dl_src_mask, dst->dl_src_mask);
|
|
|
|
|
eth_addr_bitand(src1->dl_dst_mask, src2->dl_dst_mask, dst->dl_dst_mask);
|
2010-11-03 11:00:58 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns a hash of the wildcards in 'wc'. */
|
|
|
|
|
uint32_t
|
2011-05-26 16:23:21 -07:00
|
|
|
|
flow_wildcards_hash(const struct flow_wildcards *wc, uint32_t basis)
|
2010-11-03 11:00:58 -07:00
|
|
|
|
{
|
2010-11-10 14:39:54 -08:00
|
|
|
|
/* If you change struct flow_wildcards and thereby trigger this
|
|
|
|
|
* assertion, please check that the new struct flow_wildcards has no holes
|
|
|
|
|
* in it before you update the assertion. */
|
2012-07-18 12:02:19 +09:00
|
|
|
|
BUILD_ASSERT_DECL(sizeof *wc == 104 + FLOW_N_REGS * 4);
|
2011-05-26 16:23:21 -07:00
|
|
|
|
return hash_bytes(wc, sizeof *wc, basis);
|
2010-11-03 11:00:58 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns true if 'a' and 'b' represent the same wildcards, false if they are
|
|
|
|
|
* different. */
|
|
|
|
|
bool
|
|
|
|
|
flow_wildcards_equal(const struct flow_wildcards *a,
|
|
|
|
|
const struct flow_wildcards *b)
|
|
|
|
|
{
|
2010-11-11 10:41:33 -08:00
|
|
|
|
int i;
|
|
|
|
|
|
2012-07-18 12:02:19 +09:00
|
|
|
|
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 13);
|
2012-01-27 15:38:53 -08:00
|
|
|
|
|
2010-11-10 14:39:54 -08:00
|
|
|
|
if (a->wildcards != b->wildcards
|
2011-01-20 15:29:00 -08:00
|
|
|
|
|| a->tun_id_mask != b->tun_id_mask
|
2010-11-10 14:39:54 -08:00
|
|
|
|
|| a->nw_src_mask != b->nw_src_mask
|
2010-11-23 10:06:28 -08:00
|
|
|
|
|| a->nw_dst_mask != b->nw_dst_mask
|
2011-08-04 16:50:25 -07:00
|
|
|
|
|| a->vlan_tci_mask != b->vlan_tci_mask
|
2012-06-27 01:09:44 +12:00
|
|
|
|
|| a->metadata_mask != b->metadata_mask
|
2010-12-29 19:03:46 -08:00
|
|
|
|
|| !ipv6_addr_equals(&a->ipv6_src_mask, &b->ipv6_src_mask)
|
2012-01-27 17:16:05 -08:00
|
|
|
|
|| !ipv6_addr_equals(&a->ipv6_dst_mask, &b->ipv6_dst_mask)
|
2012-07-18 12:02:19 +09:00
|
|
|
|
|| a->ipv6_label_mask != b->ipv6_label_mask
|
2012-04-25 15:48:40 -07:00
|
|
|
|
|| !ipv6_addr_equals(&a->nd_target_mask, &b->nd_target_mask)
|
2012-01-27 17:16:05 -08:00
|
|
|
|
|| a->tp_src_mask != b->tp_src_mask
|
2012-05-29 00:38:21 +12:00
|
|
|
|
|| a->tp_dst_mask != b->tp_dst_mask
|
|
|
|
|
|| !eth_addr_equals(a->dl_src_mask, b->dl_src_mask)
|
|
|
|
|
|| !eth_addr_equals(a->dl_dst_mask, b->dl_dst_mask)) {
|
2010-11-11 10:41:33 -08:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < FLOW_N_REGS; i++) {
|
|
|
|
|
if (a->reg_masks[i] != b->reg_masks[i]) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
2010-11-03 11:00:58 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns true if at least one bit or field is wildcarded in 'a' but not in
|
|
|
|
|
* 'b', false otherwise. */
|
|
|
|
|
bool
|
|
|
|
|
flow_wildcards_has_extra(const struct flow_wildcards *a,
|
|
|
|
|
const struct flow_wildcards *b)
|
|
|
|
|
{
|
2010-11-11 10:41:33 -08:00
|
|
|
|
int i;
|
2012-05-29 00:38:21 +12:00
|
|
|
|
uint8_t eth_masked[ETH_ADDR_LEN];
|
2010-12-29 19:03:46 -08:00
|
|
|
|
struct in6_addr ipv6_masked;
|
2010-11-11 10:41:33 -08:00
|
|
|
|
|
2012-07-18 12:02:19 +09:00
|
|
|
|
BUILD_ASSERT_DECL(FLOW_WC_SEQ == 13);
|
2012-01-27 15:38:53 -08:00
|
|
|
|
|
2010-11-11 10:41:33 -08:00
|
|
|
|
for (i = 0; i < FLOW_N_REGS; i++) {
|
|
|
|
|
if ((a->reg_masks[i] & b->reg_masks[i]) != b->reg_masks[i]) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-29 00:38:21 +12:00
|
|
|
|
eth_addr_bitand(a->dl_src_mask, b->dl_src_mask, eth_masked);
|
|
|
|
|
if (!eth_addr_equals(eth_masked, b->dl_src_mask)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
eth_addr_bitand(a->dl_dst_mask, b->dl_dst_mask, eth_masked);
|
|
|
|
|
if (!eth_addr_equals(eth_masked, b->dl_dst_mask)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-29 19:03:46 -08:00
|
|
|
|
ipv6_masked = ipv6_addr_bitand(&a->ipv6_src_mask, &b->ipv6_src_mask);
|
|
|
|
|
if (!ipv6_addr_equals(&ipv6_masked, &b->ipv6_src_mask)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ipv6_masked = ipv6_addr_bitand(&a->ipv6_dst_mask, &b->ipv6_dst_mask);
|
|
|
|
|
if (!ipv6_addr_equals(&ipv6_masked, &b->ipv6_dst_mask)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-25 15:48:40 -07:00
|
|
|
|
ipv6_masked = ipv6_addr_bitand(&a->nd_target_mask, &b->nd_target_mask);
|
|
|
|
|
if (!ipv6_addr_equals(&ipv6_masked, &b->nd_target_mask)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-10 14:39:54 -08:00
|
|
|
|
return (a->wildcards & ~b->wildcards
|
2011-01-20 15:29:00 -08:00
|
|
|
|
|| (a->tun_id_mask & b->tun_id_mask) != b->tun_id_mask
|
2010-11-03 11:00:58 -07:00
|
|
|
|
|| (a->nw_src_mask & b->nw_src_mask) != b->nw_src_mask
|
2010-11-23 10:06:28 -08:00
|
|
|
|
|| (a->nw_dst_mask & b->nw_dst_mask) != b->nw_dst_mask
|
2012-07-18 12:02:19 +09:00
|
|
|
|
|| (a->ipv6_label_mask & b->ipv6_label_mask) != b->ipv6_label_mask
|
2012-01-27 17:16:05 -08:00
|
|
|
|
|| (a->vlan_tci_mask & b->vlan_tci_mask) != b->vlan_tci_mask
|
2012-06-27 01:09:44 +12:00
|
|
|
|
|| (a->metadata_mask & b->metadata_mask) != b->metadata_mask
|
2012-01-27 17:16:05 -08:00
|
|
|
|
|| (a->tp_src_mask & b->tp_src_mask) != b->tp_src_mask
|
|
|
|
|
|| (a->tp_dst_mask & b->tp_dst_mask) != b->tp_dst_mask);
|
2010-11-03 11:00:58 -07:00
|
|
|
|
}
|
|
|
|
|
|
2010-11-11 10:41:33 -08:00
|
|
|
|
/* Sets the wildcard mask for register 'idx' in 'wc' to 'mask'.
|
|
|
|
|
* (A 0-bit indicates a wildcard bit.) */
|
|
|
|
|
void
|
|
|
|
|
flow_wildcards_set_reg_mask(struct flow_wildcards *wc, int idx, uint32_t mask)
|
|
|
|
|
{
|
2010-11-10 14:39:54 -08:00
|
|
|
|
wc->reg_masks[idx] = mask;
|
2010-11-11 10:41:33 -08:00
|
|
|
|
}
|
2011-02-01 18:50:25 -08:00
|
|
|
|
|
|
|
|
|
/* Hashes 'flow' based on its L2 through L4 protocol information. */
|
|
|
|
|
uint32_t
|
|
|
|
|
flow_hash_symmetric_l4(const struct flow *flow, uint32_t basis)
|
|
|
|
|
{
|
|
|
|
|
struct {
|
2010-12-29 19:03:46 -08:00
|
|
|
|
union {
|
|
|
|
|
ovs_be32 ipv4_addr;
|
|
|
|
|
struct in6_addr ipv6_addr;
|
|
|
|
|
};
|
2011-02-01 18:50:25 -08:00
|
|
|
|
ovs_be16 eth_type;
|
|
|
|
|
ovs_be16 vlan_tci;
|
2012-02-02 21:57:54 -08:00
|
|
|
|
ovs_be16 tp_port;
|
2011-02-01 18:50:25 -08:00
|
|
|
|
uint8_t eth_addr[ETH_ADDR_LEN];
|
|
|
|
|
uint8_t ip_proto;
|
|
|
|
|
} fields;
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
memset(&fields, 0, sizeof fields);
|
|
|
|
|
for (i = 0; i < ETH_ADDR_LEN; i++) {
|
|
|
|
|
fields.eth_addr[i] = flow->dl_src[i] ^ flow->dl_dst[i];
|
|
|
|
|
}
|
|
|
|
|
fields.vlan_tci = flow->vlan_tci & htons(VLAN_VID_MASK);
|
|
|
|
|
fields.eth_type = flow->dl_type;
|
2011-05-23 11:39:17 -07:00
|
|
|
|
|
|
|
|
|
/* UDP source and destination port are not taken into account because they
|
|
|
|
|
* will not necessarily be symmetric in a bidirectional flow. */
|
2011-02-01 18:50:25 -08:00
|
|
|
|
if (fields.eth_type == htons(ETH_TYPE_IP)) {
|
2010-12-29 19:03:46 -08:00
|
|
|
|
fields.ipv4_addr = flow->nw_src ^ flow->nw_dst;
|
|
|
|
|
fields.ip_proto = flow->nw_proto;
|
2011-05-23 11:39:17 -07:00
|
|
|
|
if (fields.ip_proto == IPPROTO_TCP) {
|
2012-02-02 21:57:54 -08:00
|
|
|
|
fields.tp_port = flow->tp_src ^ flow->tp_dst;
|
2010-12-29 19:03:46 -08:00
|
|
|
|
}
|
|
|
|
|
} else if (fields.eth_type == htons(ETH_TYPE_IPV6)) {
|
|
|
|
|
const uint8_t *a = &flow->ipv6_src.s6_addr[0];
|
|
|
|
|
const uint8_t *b = &flow->ipv6_dst.s6_addr[0];
|
|
|
|
|
uint8_t *ipv6_addr = &fields.ipv6_addr.s6_addr[0];
|
|
|
|
|
|
|
|
|
|
for (i=0; i<16; i++) {
|
|
|
|
|
ipv6_addr[i] = a[i] ^ b[i];
|
|
|
|
|
}
|
2011-02-01 18:50:25 -08:00
|
|
|
|
fields.ip_proto = flow->nw_proto;
|
2011-05-23 11:39:17 -07:00
|
|
|
|
if (fields.ip_proto == IPPROTO_TCP) {
|
2012-02-02 21:57:54 -08:00
|
|
|
|
fields.tp_port = flow->tp_src ^ flow->tp_dst;
|
2011-02-01 18:50:25 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return hash_bytes(&fields, sizeof fields, basis);
|
|
|
|
|
}
|
2011-07-13 16:20:24 -07:00
|
|
|
|
|
|
|
|
|
/* Hashes the portions of 'flow' designated by 'fields'. */
|
|
|
|
|
uint32_t
|
|
|
|
|
flow_hash_fields(const struct flow *flow, enum nx_hash_fields fields,
|
|
|
|
|
uint16_t basis)
|
|
|
|
|
{
|
|
|
|
|
switch (fields) {
|
|
|
|
|
|
|
|
|
|
case NX_HASH_FIELDS_ETH_SRC:
|
|
|
|
|
return hash_bytes(flow->dl_src, sizeof flow->dl_src, basis);
|
|
|
|
|
|
|
|
|
|
case NX_HASH_FIELDS_SYMMETRIC_L4:
|
|
|
|
|
return flow_hash_symmetric_l4(flow, basis);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NOT_REACHED();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns a string representation of 'fields'. */
|
|
|
|
|
const char *
|
|
|
|
|
flow_hash_fields_to_str(enum nx_hash_fields fields)
|
|
|
|
|
{
|
|
|
|
|
switch (fields) {
|
|
|
|
|
case NX_HASH_FIELDS_ETH_SRC: return "eth_src";
|
|
|
|
|
case NX_HASH_FIELDS_SYMMETRIC_L4: return "symmetric_l4";
|
|
|
|
|
default: return "<unknown>";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns true if the value of 'fields' is supported. Otherwise false. */
|
|
|
|
|
bool
|
|
|
|
|
flow_hash_fields_valid(enum nx_hash_fields fields)
|
|
|
|
|
{
|
|
|
|
|
return fields == NX_HASH_FIELDS_ETH_SRC
|
|
|
|
|
|| fields == NX_HASH_FIELDS_SYMMETRIC_L4;
|
|
|
|
|
}
|
2011-09-08 14:32:13 -07:00
|
|
|
|
|
2011-11-21 14:14:02 -08:00
|
|
|
|
/* Sets the VLAN VID that 'flow' matches to 'vid', which is interpreted as an
|
|
|
|
|
* OpenFlow 1.0 "dl_vlan" value:
|
|
|
|
|
*
|
|
|
|
|
* - If it is in the range 0...4095, 'flow->vlan_tci' is set to match
|
|
|
|
|
* that VLAN. Any existing PCP match is unchanged (it becomes 0 if
|
|
|
|
|
* 'flow' previously matched packets without a VLAN header).
|
|
|
|
|
*
|
|
|
|
|
* - If it is OFP_VLAN_NONE, 'flow->vlan_tci' is set to match a packet
|
|
|
|
|
* without a VLAN tag.
|
|
|
|
|
*
|
|
|
|
|
* - Other values of 'vid' should not be used. */
|
|
|
|
|
void
|
|
|
|
|
flow_set_vlan_vid(struct flow *flow, ovs_be16 vid)
|
|
|
|
|
{
|
2012-07-05 17:41:10 +09:00
|
|
|
|
if (vid == htons(OFP10_VLAN_NONE)) {
|
2011-11-21 14:14:02 -08:00
|
|
|
|
flow->vlan_tci = htons(0);
|
|
|
|
|
} else {
|
|
|
|
|
vid &= htons(VLAN_VID_MASK);
|
|
|
|
|
flow->vlan_tci &= ~htons(VLAN_VID_MASK);
|
|
|
|
|
flow->vlan_tci |= htons(VLAN_CFI) | vid;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Sets the VLAN PCP that 'flow' matches to 'pcp', which should be in the
|
|
|
|
|
* range 0...7.
|
|
|
|
|
*
|
|
|
|
|
* This function has no effect on the VLAN ID that 'flow' matches.
|
|
|
|
|
*
|
|
|
|
|
* After calling this function, 'flow' will not match packets without a VLAN
|
|
|
|
|
* header. */
|
|
|
|
|
void
|
|
|
|
|
flow_set_vlan_pcp(struct flow *flow, uint8_t pcp)
|
|
|
|
|
{
|
|
|
|
|
pcp &= 0x07;
|
|
|
|
|
flow->vlan_tci &= ~htons(VLAN_PCP_MASK);
|
|
|
|
|
flow->vlan_tci |= htons((pcp << VLAN_PCP_SHIFT) | VLAN_CFI);
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-08 14:32:13 -07:00
|
|
|
|
/* Puts into 'b' a packet that flow_extract() would parse as having the given
|
|
|
|
|
* 'flow'.
|
|
|
|
|
*
|
|
|
|
|
* (This is useful only for testing, obviously, and the packet isn't really
|
|
|
|
|
* valid. It hasn't got any checksums filled in, for one, and lots of fields
|
|
|
|
|
* are just zeroed.) */
|
|
|
|
|
void
|
|
|
|
|
flow_compose(struct ofpbuf *b, const struct flow *flow)
|
|
|
|
|
{
|
|
|
|
|
eth_compose(b, flow->dl_dst, flow->dl_src, ntohs(flow->dl_type), 0);
|
|
|
|
|
if (flow->dl_type == htons(FLOW_DL_TYPE_NONE)) {
|
|
|
|
|
struct eth_header *eth = b->l2;
|
|
|
|
|
eth->eth_type = htons(b->size);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flow->vlan_tci & htons(VLAN_CFI)) {
|
2012-01-03 10:42:56 -08:00
|
|
|
|
eth_push_vlan(b, flow->vlan_tci);
|
2011-09-08 14:32:13 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flow->dl_type == htons(ETH_TYPE_IP)) {
|
|
|
|
|
struct ip_header *ip;
|
|
|
|
|
|
|
|
|
|
b->l3 = ip = ofpbuf_put_zeros(b, sizeof *ip);
|
|
|
|
|
ip->ip_ihl_ver = IP_IHL_VER(5, 4);
|
2011-11-09 17:10:27 -08:00
|
|
|
|
ip->ip_tos = flow->nw_tos;
|
2011-09-08 14:32:13 -07:00
|
|
|
|
ip->ip_proto = flow->nw_proto;
|
|
|
|
|
ip->ip_src = flow->nw_src;
|
|
|
|
|
ip->ip_dst = flow->nw_dst;
|
|
|
|
|
|
2011-11-09 17:10:27 -08:00
|
|
|
|
if (flow->nw_frag & FLOW_NW_FRAG_ANY) {
|
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
|
|
|
|
ip->ip_frag_off |= htons(IP_MORE_FRAGMENTS);
|
2011-11-09 17:10:27 -08:00
|
|
|
|
if (flow->nw_frag & 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
|
|
|
|
ip->ip_frag_off |= htons(100);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-11-09 17:10:27 -08:00
|
|
|
|
if (!(flow->nw_frag & FLOW_NW_FRAG_ANY)
|
|
|
|
|
|| !(flow->nw_frag & 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
|
|
|
|
if (flow->nw_proto == IPPROTO_TCP) {
|
|
|
|
|
struct tcp_header *tcp;
|
|
|
|
|
|
|
|
|
|
b->l4 = tcp = ofpbuf_put_zeros(b, sizeof *tcp);
|
|
|
|
|
tcp->tcp_src = flow->tp_src;
|
|
|
|
|
tcp->tcp_dst = flow->tp_dst;
|
2011-12-19 14:45:23 -08:00
|
|
|
|
tcp->tcp_ctl = TCP_CTL(0, 5);
|
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
|
|
|
|
} else if (flow->nw_proto == IPPROTO_UDP) {
|
|
|
|
|
struct udp_header *udp;
|
|
|
|
|
|
|
|
|
|
b->l4 = udp = ofpbuf_put_zeros(b, sizeof *udp);
|
|
|
|
|
udp->udp_src = flow->tp_src;
|
|
|
|
|
udp->udp_dst = flow->tp_dst;
|
|
|
|
|
} else if (flow->nw_proto == IPPROTO_ICMP) {
|
|
|
|
|
struct icmp_header *icmp;
|
|
|
|
|
|
|
|
|
|
b->l4 = icmp = ofpbuf_put_zeros(b, sizeof *icmp);
|
|
|
|
|
icmp->icmp_type = ntohs(flow->tp_src);
|
|
|
|
|
icmp->icmp_code = ntohs(flow->tp_dst);
|
|
|
|
|
}
|
2011-09-08 14:32:13 -07:00
|
|
|
|
}
|
2011-12-19 14:45:23 -08:00
|
|
|
|
|
|
|
|
|
ip->ip_tot_len = htons((uint8_t *) b->data + b->size
|
|
|
|
|
- (uint8_t *) b->l3);
|
2011-09-08 14:32:13 -07:00
|
|
|
|
} else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
|
|
|
|
|
/* XXX */
|
|
|
|
|
} else if (flow->dl_type == htons(ETH_TYPE_ARP)) {
|
|
|
|
|
struct arp_eth_header *arp;
|
|
|
|
|
|
|
|
|
|
b->l3 = arp = ofpbuf_put_zeros(b, sizeof *arp);
|
|
|
|
|
arp->ar_hrd = htons(1);
|
|
|
|
|
arp->ar_pro = htons(ETH_TYPE_IP);
|
|
|
|
|
arp->ar_hln = ETH_ADDR_LEN;
|
|
|
|
|
arp->ar_pln = 4;
|
|
|
|
|
arp->ar_op = htons(flow->nw_proto);
|
|
|
|
|
|
|
|
|
|
if (flow->nw_proto == ARP_OP_REQUEST ||
|
|
|
|
|
flow->nw_proto == ARP_OP_REPLY) {
|
|
|
|
|
arp->ar_spa = flow->nw_src;
|
|
|
|
|
arp->ar_tpa = flow->nw_dst;
|
|
|
|
|
memcpy(arp->ar_sha, flow->arp_sha, ETH_ADDR_LEN);
|
|
|
|
|
memcpy(arp->ar_tha, flow->arp_tha, ETH_ADDR_LEN);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|