aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2011-10-19 21:33:44 -0700
committerBen Pfaff <blp@nicira.com>2011-10-21 15:07:36 -0700
commit7257b535ab8e5fafd811c5f6788205eefdd44948 (patch)
tree75072ea003837f756ce6910fb5e0ba3113db30be /include
parent4edb9ae90e4092f5f56b9d914d2b88783c49860d (diff)
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.
Diffstat (limited to 'include')
-rw-r--r--include/linux/openvswitch.h38
-rw-r--r--include/openflow/nicira-ext.h49
-rw-r--r--include/openflow/openflow.h1
3 files changed, 70 insertions, 18 deletions
diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h
index acc27693..190bf79e 100644
--- a/include/linux/openvswitch.h
+++ b/include/linux/openvswitch.h
@@ -80,9 +80,6 @@ struct ovs_header {
* not be sent.
* @OVS_DP_ATTR_STATS: Statistics about packets that have passed through the
* datapath. Always present in notifications.
- * @OVS_DP_ATTR_IPV4_FRAGS: One of %OVS_DP_FRAG_*. Always present in
- * notifications. May be included in %OVS_DP_NEW or %OVS_DP_SET requests to
- * change the fragment handling policy.
*
* These attributes follow the &struct ovs_header within the Generic Netlink
* payload for %OVS_DP_* commands.
@@ -92,27 +89,12 @@ enum ovs_datapath_attr {
OVS_DP_ATTR_NAME, /* name of dp_ifindex netdev */
OVS_DP_ATTR_UPCALL_PID, /* Netlink PID to receive upcalls */
OVS_DP_ATTR_STATS, /* struct ovs_dp_stats */
- OVS_DP_ATTR_IPV4_FRAGS, /* 32-bit enum ovs_datapath_frag */
__OVS_DP_ATTR_MAX
};
#define OVS_DP_ATTR_MAX (__OVS_DP_ATTR_MAX - 1)
-/**
- * enum ovs_datapath_frag - policy for handling received IPv4 fragments.
- * @OVS_DP_FRAG_ZERO: Treat IP fragments as IP protocol 0 and transport ports
- * zero.
- * @OVS_DP_FRAG_DROP: Drop IP fragments. Do not pass them through the flow
- * table or up to userspace.
- */
-enum ovs_datapath_frag {
- OVS_DP_FRAG_UNSPEC,
- OVS_DP_FRAG_ZERO, /* Treat IP fragments as transport port 0. */
- OVS_DP_FRAG_DROP /* Drop IP fragments. */
-};
-
struct ovs_dp_stats {
- __u64 n_frags; /* Number of dropped IP fragments. */
__u64 n_hit; /* Number of flow table matches. */
__u64 n_missed; /* Number of flow table misses. */
__u64 n_lost; /* Number of misses not sent to userspace. */
@@ -290,6 +272,24 @@ enum ovs_key_attr {
#define OVS_KEY_ATTR_MAX (__OVS_KEY_ATTR_MAX - 1)
+/**
+ * enum ovs_frag_type - IPv4 and IPv6 fragment type
+ * @OVS_FRAG_TYPE_NONE: Packet is not a fragment.
+ * @OVS_FRAG_TYPE_FIRST: Packet is a fragment with offset 0.
+ * @OVS_FRAG_TYPE_LATER: Packet is a fragment with nonzero offset.
+ *
+ * Used as the @ipv4_frag in &struct ovs_key_ipv4 and as @ipv6_frag &struct
+ * ovs_key_ipv6.
+ */
+enum ovs_frag_type {
+ OVS_FRAG_TYPE_NONE,
+ OVS_FRAG_TYPE_FIRST,
+ OVS_FRAG_TYPE_LATER,
+ __OVS_FRAG_TYPE_MAX
+};
+
+#define OVS_FRAG_TYPE_MAX (__OVS_FRAG_TYPE_MAX - 1)
+
struct ovs_key_ethernet {
__u8 eth_src[6];
__u8 eth_dst[6];
@@ -305,6 +305,7 @@ struct ovs_key_ipv4 {
__be32 ipv4_dst;
__u8 ipv4_proto;
__u8 ipv4_tos;
+ __u8 ipv4_frag; /* One of OVS_FRAG_TYPE_*. */
};
struct ovs_key_ipv6 {
@@ -312,6 +313,7 @@ struct ovs_key_ipv6 {
__be32 ipv6_dst[4];
__u8 ipv6_proto;
__u8 ipv6_tos;
+ __u8 ipv6_frag; /* One of OVS_FRAG_TYPE_*. */
};
struct ovs_key_tcp {
diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index a6d2db45..aeb1a31c 100644
--- a/include/openflow/nicira-ext.h
+++ b/include/openflow/nicira-ext.h
@@ -1531,6 +1531,55 @@ OFP_ASSERT(sizeof(struct nx_action_output_reg) == 24);
* Masking: Not maskable. */
#define NXM_NX_ND_TLL NXM_HEADER (0x0001, 25, 6)
+/* IP fragment information.
+ *
+ * Prereqs:
+ * NXM_OF_ETH_TYPE must be either 0x0800 or 0x86dd.
+ *
+ * Format: 8-bit value with one of the values 0, 1, or 3, as described below.
+ *
+ * Masking: Fully maskable.
+ *
+ * This field has three possible values:
+ *
+ * - A packet that is not an IP fragment has value 0.
+ *
+ * - A packet that is an IP fragment with offset 0 (the first fragment) has
+ * bit 0 set and thus value 1.
+ *
+ * - A packet that is an IP fragment with nonzero offset has bits 0 and 1 set
+ * and thus value 3.
+ *
+ * NX_IP_FRAG_ANY and NX_IP_FRAG_LATER are declared to symbolically represent
+ * the meanings of bits 0 and 1.
+ *
+ * The switch may reject matches against values that can never appear.
+ *
+ * It is important to understand how this field interacts with the OpenFlow IP
+ * fragment handling mode:
+ *
+ * - In OFPC_FRAG_DROP mode, the OpenFlow switch drops all IP fragments
+ * before they reach the flow table, so every packet that is available for
+ * matching will have value 0 in this field.
+ *
+ * - Open vSwitch does not implement OFPC_FRAG_REASM mode, but if it did then
+ * IP fragments would be reassembled before they reached the flow table and
+ * again every packet available for matching would always have value 0.
+ *
+ * - In OFPC_FRAG_NORMAL mode, all three values are possible, but OpenFlow
+ * 1.0 says that fragments' transport ports are always 0, even for the
+ * first fragment, so this does not provide much extra information.
+ *
+ * - In OFPC_FRAG_NX_MATCH mode, all three values are possible. For
+ * fragments with offset 0, Open vSwitch makes L4 header information
+ * available.
+ */
+#define NXM_NX_IP_FRAG NXM_HEADER (0x0001, 26, 1)
+#define NXM_NX_IP_FRAG_W NXM_HEADER_W(0x0001, 26, 1)
+
+/* Bits in the value of NXM_NX_IP_FRAG. */
+#define NX_IP_FRAG_ANY (1 << 0) /* Is this a fragment? */
+#define NX_IP_FRAG_LATER (1 << 1) /* Is this a fragment with nonzero offset? */
/* ## --------------------- ## */
/* ## Requests and replies. ## */
diff --git a/include/openflow/openflow.h b/include/openflow/openflow.h
index fd8fbeb1..cee62e8f 100644
--- a/include/openflow/openflow.h
+++ b/include/openflow/openflow.h
@@ -134,6 +134,7 @@ enum ofp_config_flags {
OFPC_FRAG_NORMAL = 0, /* No special handling for fragments. */
OFPC_FRAG_DROP = 1, /* Drop fragments. */
OFPC_FRAG_REASM = 2, /* Reassemble (only if OFPC_IP_REASM set). */
+ OFPC_FRAG_NX_MATCH = 3, /* Make first fragments available for matching. */
OFPC_FRAG_MASK = 3
};