summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vnet/geneve/decap.c57
-rw-r--r--src/vnet/geneve/geneve.c12
-rw-r--r--src/vnet/geneve/geneve_packet.h115
3 files changed, 133 insertions, 51 deletions
diff --git a/src/vnet/geneve/decap.c b/src/vnet/geneve/decap.c
index db052145ce2..2e6e9c58a0f 100644
--- a/src/vnet/geneve/decap.c
+++ b/src/vnet/geneve/decap.c
@@ -25,7 +25,7 @@ typedef struct
u32 next_index;
u32 tunnel_index;
u32 error;
- u32 vni;
+ u32 vni_rsvd;
} geneve_rx_trace_t;
static u8 *
@@ -40,12 +40,12 @@ format_geneve_rx_trace (u8 * s, va_list * args)
s =
format (s,
"GENEVE decap from geneve_tunnel%d vni %d next %d error %d",
- t->tunnel_index, t->vni, t->next_index, t->error);
+ t->tunnel_index, t->vni_rsvd, t->next_index, t->error);
}
else
{
s = format (s, "GENEVE decap error - tunnel for vni %d does not exist",
- t->vni);
+ t->vni_rsvd);
}
return s;
}
@@ -147,6 +147,10 @@ geneve_input (vlib_main_t * vm,
/* udp leaves current_data pointing at the geneve header */
geneve0 = vlib_buffer_get_current (b0);
geneve1 = vlib_buffer_get_current (b1);
+
+ vnet_geneve_hdr_1word_ntoh (geneve0);
+ vnet_geneve_hdr_1word_ntoh (geneve1);
+
if (is_ip4)
{
vlib_buffer_advance
@@ -198,13 +202,14 @@ geneve_input (vlib_main_t * vm,
tunnel_index1 = ~0;
error1 = 0;
- if (PREDICT_FALSE (geneve0->ver != GENEVE_VERSION))
+ if (PREDICT_FALSE
+ (vnet_get_geneve_version (geneve0) != GENEVE_VERSION))
{
error0 = GENEVE_ERROR_BAD_FLAGS;
next0 = GENEVE_INPUT_NEXT_DROP;
goto trace0;
}
-#if SUPPORT_OPTIONS_HEADER==0
+#if SUPPORT_OPTIONS_HEADER==1
if (PREDICT_FALSE (vnet_get_geneve_critical_bit (geneve0) == 1))
{
error0 = GENEVE_ERROR_BAD_FLAGS;
@@ -215,7 +220,7 @@ geneve_input (vlib_main_t * vm,
if (is_ip4)
{
key4_0.remote = ip4_0->src_address.as_u32;
- key4_0.vni = geneve0->vni;
+ key4_0.vni = vnet_get_geneve_vni_bigendian (geneve0);
/* Make sure GENEVE tunnel exist according to packet SIP and VNI */
if (PREDICT_FALSE (key4_0.as_u64 != last_key4.as_u64))
@@ -250,7 +255,7 @@ geneve_input (vlib_main_t * vm,
(ip4_address_is_multicast (&ip4_0->dst_address)))
{
key4_0.remote = ip4_0->dst_address.as_u32;
- key4_0.vni = geneve0->vni;
+ key4_0.vni = vnet_get_geneve_vni_bigendian (geneve0);
/* Make sure mcast GENEVE tunnel exist by packet DIP and VNI */
p0 = hash_get (vxm->geneve4_tunnel_by_key, key4_0.as_u64);
if (PREDICT_TRUE (p0 != NULL))
@@ -268,7 +273,7 @@ geneve_input (vlib_main_t * vm,
{
key6_0.remote.as_u64[0] = ip6_0->src_address.as_u64[0];
key6_0.remote.as_u64[1] = ip6_0->src_address.as_u64[1];
- key6_0.vni = geneve0->vni;
+ key6_0.vni = vnet_get_geneve_vni_bigendian (geneve0);
/* Make sure GENEVE tunnel exist according to packet SIP and VNI */
if (PREDICT_FALSE
@@ -305,7 +310,7 @@ geneve_input (vlib_main_t * vm,
{
key6_0.remote.as_u64[0] = ip6_0->dst_address.as_u64[0];
key6_0.remote.as_u64[1] = ip6_0->dst_address.as_u64[1];
- key6_0.vni = geneve0->vni;
+ key6_0.vni = vnet_get_geneve_vni_bigendian (geneve0);
p0 = hash_get_mem (vxm->geneve6_tunnel_by_key, &key6_0);
if (PREDICT_TRUE (p0 != NULL))
{
@@ -361,16 +366,17 @@ geneve_input (vlib_main_t * vm,
tr->next_index = next0;
tr->error = error0;
tr->tunnel_index = tunnel_index0;
- tr->vni = vnet_get_geneve_vni (geneve0);
+ tr->vni_rsvd = vnet_get_geneve_vni (geneve0);
}
- if (PREDICT_FALSE (geneve1->ver != GENEVE_VERSION))
+ if (PREDICT_FALSE
+ (vnet_get_geneve_version (geneve1) != GENEVE_VERSION))
{
error1 = GENEVE_ERROR_BAD_FLAGS;
next1 = GENEVE_INPUT_NEXT_DROP;
goto trace1;
}
-#if SUPPORT_OPTIONS_HEADER==0
+#if SUPPORT_OPTIONS_HEADER==1
if (PREDICT_FALSE (vnet_get_geneve_critical_bit (geneve1) == 1))
{
error1 = GENEVE_ERROR_BAD_FLAGS;
@@ -381,7 +387,7 @@ geneve_input (vlib_main_t * vm,
if (is_ip4)
{
key4_1.remote = ip4_1->src_address.as_u32;
- key4_1.vni = geneve1->vni;
+ key4_1.vni = vnet_get_geneve_vni_bigendian (geneve1);
/* Make sure unicast GENEVE tunnel exist by packet SIP and VNI */
if (PREDICT_FALSE (key4_1.as_u64 != last_key4.as_u64))
@@ -416,7 +422,7 @@ geneve_input (vlib_main_t * vm,
(ip4_address_is_multicast (&ip4_1->dst_address)))
{
key4_1.remote = ip4_1->dst_address.as_u32;
- key4_1.vni = geneve1->vni;
+ key4_1.vni = vnet_get_geneve_vni_bigendian (geneve1);
/* Make sure mcast GENEVE tunnel exist by packet DIP and VNI */
p1 = hash_get (vxm->geneve4_tunnel_by_key, key4_1.as_u64);
if (PREDICT_TRUE (p1 != NULL))
@@ -434,7 +440,7 @@ geneve_input (vlib_main_t * vm,
{
key6_1.remote.as_u64[0] = ip6_1->src_address.as_u64[0];
key6_1.remote.as_u64[1] = ip6_1->src_address.as_u64[1];
- key6_1.vni = geneve1->vni;
+ key6_1.vni = vnet_get_geneve_vni_bigendian (geneve1);
/* Make sure GENEVE tunnel exist according to packet SIP and VNI */
if (PREDICT_FALSE
@@ -473,7 +479,7 @@ geneve_input (vlib_main_t * vm,
{
key6_1.remote.as_u64[0] = ip6_1->dst_address.as_u64[0];
key6_1.remote.as_u64[1] = ip6_1->dst_address.as_u64[1];
- key6_1.vni = geneve1->vni;
+ key6_1.vni = vnet_get_geneve_vni_bigendian (geneve1);
p1 = hash_get_mem (vxm->geneve6_tunnel_by_key, &key6_1);
if (PREDICT_TRUE (p1 != NULL))
{
@@ -529,7 +535,7 @@ geneve_input (vlib_main_t * vm,
tr->next_index = next1;
tr->error = error1;
tr->tunnel_index = tunnel_index1;
- tr->vni = vnet_get_geneve_vni (geneve1);
+ tr->vni_rsvd = vnet_get_geneve_vni (geneve1);
}
vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
@@ -564,6 +570,8 @@ geneve_input (vlib_main_t * vm,
/* udp leaves current_data pointing at the geneve header */
geneve0 = vlib_buffer_get_current (b0);
+ vnet_geneve_hdr_1word_ntoh (geneve0);
+
if (is_ip4)
{
vlib_buffer_advance
@@ -598,13 +606,14 @@ geneve_input (vlib_main_t * vm,
tunnel_index0 = ~0;
error0 = 0;
- if (PREDICT_FALSE (geneve0->ver != GENEVE_VERSION))
+ if (PREDICT_FALSE
+ (vnet_get_geneve_version (geneve0) != GENEVE_VERSION))
{
error0 = GENEVE_ERROR_BAD_FLAGS;
next0 = GENEVE_INPUT_NEXT_DROP;
goto trace00;
}
-#if SUPPORT_OPTIONS_HEADER==0
+#if SUPPORT_OPTIONS_HEADER==1
if (PREDICT_FALSE (vnet_get_geneve_critical_bit (geneve0) == 1))
{
error0 = GENEVE_ERROR_BAD_FLAGS;
@@ -615,7 +624,7 @@ geneve_input (vlib_main_t * vm,
if (is_ip4)
{
key4_0.remote = ip4_0->src_address.as_u32;
- key4_0.vni = geneve0->vni;
+ key4_0.vni = vnet_get_geneve_vni_bigendian (geneve0);
/* Make sure unicast GENEVE tunnel exist by packet SIP and VNI */
if (PREDICT_FALSE (key4_0.as_u64 != last_key4.as_u64))
@@ -650,7 +659,7 @@ geneve_input (vlib_main_t * vm,
(ip4_address_is_multicast (&ip4_0->dst_address)))
{
key4_0.remote = ip4_0->dst_address.as_u32;
- key4_0.vni = geneve0->vni;
+ key4_0.vni = vnet_get_geneve_vni_bigendian (geneve0);
/* Make sure mcast GENEVE tunnel exist by packet DIP and VNI */
p0 = hash_get (vxm->geneve4_tunnel_by_key, key4_0.as_u64);
if (PREDICT_TRUE (p0 != NULL))
@@ -668,7 +677,7 @@ geneve_input (vlib_main_t * vm,
{
key6_0.remote.as_u64[0] = ip6_0->src_address.as_u64[0];
key6_0.remote.as_u64[1] = ip6_0->src_address.as_u64[1];
- key6_0.vni = geneve0->vni;
+ key6_0.vni = vnet_get_geneve_vni_bigendian (geneve0);
/* Make sure GENEVE tunnel exist according to packet SIP and VNI */
if (PREDICT_FALSE
@@ -705,7 +714,7 @@ geneve_input (vlib_main_t * vm,
{
key6_0.remote.as_u64[0] = ip6_0->dst_address.as_u64[0];
key6_0.remote.as_u64[1] = ip6_0->dst_address.as_u64[1];
- key6_0.vni = geneve0->vni;
+ key6_0.vni = vnet_get_geneve_vni_bigendian (geneve0);
p0 = hash_get_mem (vxm->geneve6_tunnel_by_key, &key6_0);
if (PREDICT_TRUE (p0 != NULL))
{
@@ -761,7 +770,7 @@ geneve_input (vlib_main_t * vm,
tr->next_index = next0;
tr->error = error0;
tr->tunnel_index = tunnel_index0;
- tr->vni = vnet_get_geneve_vni (geneve0);
+ tr->vni_rsvd = vnet_get_geneve_vni (geneve0);
}
vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
to_next, n_left_to_next,
diff --git a/src/vnet/geneve/geneve.c b/src/vnet/geneve/geneve.c
index 86250e9430b..25bf4a49741 100644
--- a/src/vnet/geneve/geneve.c
+++ b/src/vnet/geneve/geneve.c
@@ -32,9 +32,6 @@
* This makes it possible for servers to be co-located in the same data
* center or be separated geographically as long as they are reachable
* through the underlay L3 network.
- *
- * You can refer to this kind of L2 overlay bridge domain as a GENEVE
- * (Virtual eXtensible VLAN) segment.
*/
@@ -272,6 +269,9 @@ geneve_rewrite (geneve_tunnel_t * t, bool is_ip6)
vnet_set_geneve_oamframe_bit (geneve, 0);
vnet_set_geneve_critical_bit (geneve, 0);
vnet_set_geneve_protocol (geneve, GENEVE_ETH_PROTOCOL);
+
+ vnet_geneve_hdr_1word_hton (geneve);
+
vnet_set_geneve_vni (geneve, t->vni);
t->rewrite = r.rw;
@@ -404,13 +404,15 @@ int vnet_geneve_add_del_tunnel
if (!is_ip6)
{
key4.remote = a->remote.ip4.as_u32;
- key4.vni = clib_host_to_net_u32 (a->vni << 8);
+ key4.vni =
+ clib_host_to_net_u32 ((a->vni << GENEVE_VNI_SHIFT) & GENEVE_VNI_MASK);
p = hash_get (vxm->geneve4_tunnel_by_key, key4.as_u64);
}
else
{
key6.remote = a->remote.ip6;
- key6.vni = clib_host_to_net_u32 (a->vni << 8);
+ key6.vni =
+ clib_host_to_net_u32 ((a->vni << GENEVE_VNI_SHIFT) & GENEVE_VNI_MASK);
p = hash_get_mem (vxm->geneve6_tunnel_by_key, &key6);
}
diff --git a/src/vnet/geneve/geneve_packet.h b/src/vnet/geneve/geneve_packet.h
index 87e5225f755..ab37f5378df 100644
--- a/src/vnet/geneve/geneve_packet.h
+++ b/src/vnet/geneve/geneve_packet.h
@@ -55,12 +55,25 @@
#define INT_OPT_CLASS 0x0103
#define VMWARE_OPT_CLASS 0x0104
+/*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Option Class | Type |R|R|R| Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Variable Option Data |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
typedef struct
{
u16 opt_class;
u8 type;
- u8 res:3;
- u8 length:5;
+ /* The 3 reserved bits are for future use;
+ * Need to be 0 on sending and ignored on receipt.
+ */
+ u8 res;
+ /* Length is expressed in 4-bytes multiples excluding the options header. */
+ u8 length;
u32 opt_data[];
} geneve_options_t;
@@ -87,88 +100,146 @@ typedef struct
typedef struct
{
- u8 ver:2;
- u8 opt_len:6;
- u8 oam_frame:1;
- u8 critical_options:1;
- u8 res1:6;
- u16 protocol;
- u32 vni:24;
- u8 res2;
+ /*
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |Ver| Opt Len |O|C| Rsvd. | Protocol Type |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ u32 first_word;
+
+ /*
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Virtual Network Identifier (VNI) | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ u32 vni_rsvd;
geneve_options_t opts[];
} geneve_header_t;
+#define GENEVE_VERSION_SHIFT 30
+#define GENEVE_OPTLEN_SHIFT 24
+#define GENEVE_O_BIT_SHIFT 23
+#define GENEVE_C_BIT_SHIFT 22
+#define GENEVE_6_RESERVED_SHIFT 16
+#define GENEVE_VNI_SHIFT 8
+
+#define GENEVE_VERSION_MASK 0xC0000000
+#define GENEVE_OPTLEN_MASK 0x3F000000
+#define GENEVE_O_BIT_MASK 0x00800000
+#define GENEVE_C_BIT_MASK 0x00400000
+#define GENEVE_6_RESERVED_MASK 0x003F0000
+#define GENEVE_PROTOCOL_MASK 0x0000FFFF
+#define GENEVE_VNI_MASK 0xFFFFFF00
+
+/*
+ * Return the VNI in host-byte order
+ */
static inline u32
vnet_get_geneve_vni (geneve_header_t * h)
{
- return (clib_net_to_host_u32 (h->vni) >> 8);
+ return (clib_net_to_host_u32 (h->vni_rsvd & GENEVE_VNI_MASK) >>
+ GENEVE_VNI_SHIFT);
+}
+
+/*
+ * Return the VNI in network-byte order
+ *
+ * To be used in the DECAP phase to create the lookup key (IP + VNI)
+ */
+static inline u32
+vnet_get_geneve_vni_bigendian (geneve_header_t * h)
+{
+ u32 vni_host = vnet_get_geneve_vni (h);
+ return clib_host_to_net_u32 ((vni_host << GENEVE_VNI_SHIFT) &
+ GENEVE_VNI_MASK);
}
static inline void
vnet_set_geneve_vni (geneve_header_t * h, u32 vni)
{
- h->vni = clib_host_to_net_u32 (vni << 8);
+ h->vni_rsvd &= ~(GENEVE_VNI_MASK);
+ h->vni_rsvd |=
+ clib_host_to_net_u32 ((vni << GENEVE_VNI_SHIFT) & GENEVE_VNI_MASK);
}
static inline u8
vnet_get_geneve_version (geneve_header_t * h)
{
- return (clib_net_to_host_u32 (h->ver) >> 30);
+ return ((h->first_word & GENEVE_VERSION_MASK) >> GENEVE_VERSION_SHIFT);
}
static inline void
vnet_set_geneve_version (geneve_header_t * h, u8 version)
{
- h->ver = clib_host_to_net_u32 (version << 30);
+ h->first_word &= ~(GENEVE_VERSION_MASK);
+ h->first_word |= ((version << GENEVE_VERSION_SHIFT) & GENEVE_VERSION_MASK);
}
static inline u8
vnet_get_geneve_options_len (geneve_header_t * h)
{
- return (clib_net_to_host_u32 (h->opt_len) >> 24);
+ return ((h->first_word & GENEVE_OPTLEN_MASK) >> GENEVE_OPTLEN_SHIFT);
}
static inline void
vnet_set_geneve_options_len (geneve_header_t * h, u8 len)
{
- h->opt_len = clib_host_to_net_u32 (len << 24);
+ h->first_word &= ~(GENEVE_OPTLEN_MASK);
+ h->first_word |= ((len << GENEVE_OPTLEN_SHIFT) & GENEVE_OPTLEN_MASK);
}
static inline u8
vnet_get_geneve_oamframe_bit (geneve_header_t * h)
{
- return (clib_net_to_host_u32 (h->oam_frame) >> 23);
+ return ((h->first_word & GENEVE_O_BIT_MASK) >> GENEVE_O_BIT_SHIFT);
}
static inline void
vnet_set_geneve_oamframe_bit (geneve_header_t * h, u8 oam)
{
- h->oam_frame = clib_host_to_net_u32 (oam << 23);
+ h->first_word &= ~(GENEVE_O_BIT_MASK);
+ h->first_word |= ((oam << GENEVE_O_BIT_SHIFT) & GENEVE_O_BIT_MASK);
}
static inline u8
vnet_get_geneve_critical_bit (geneve_header_t * h)
{
- return (clib_net_to_host_u32 (h->critical_options) >> 22);
+ return ((h->first_word & GENEVE_C_BIT_MASK) >> GENEVE_C_BIT_SHIFT);
}
static inline void
vnet_set_geneve_critical_bit (geneve_header_t * h, u8 critical_opts)
{
- h->critical_options = clib_host_to_net_u32 (critical_opts << 22);
+ h->first_word &= ~(GENEVE_C_BIT_MASK);
+ h->first_word |=
+ ((critical_opts << GENEVE_C_BIT_SHIFT) & GENEVE_C_BIT_MASK);
}
static inline u16
vnet_get_geneve_protocol (geneve_header_t * h)
{
- return clib_net_to_host_u32 (h->protocol);
+ return (h->first_word & GENEVE_PROTOCOL_MASK);
}
static inline void
vnet_set_geneve_protocol (geneve_header_t * h, u16 protocol)
{
- h->protocol = clib_host_to_net_u32 (protocol);
+ h->first_word &= ~(GENEVE_PROTOCOL_MASK);
+ h->first_word |= (protocol & GENEVE_PROTOCOL_MASK);
}
+
+static inline void
+vnet_geneve_hdr_1word_ntoh (geneve_header_t * h)
+{
+ h->first_word = clib_net_to_host_u32 (h->first_word);
+}
+
+static inline void
+vnet_geneve_hdr_1word_hton (geneve_header_t * h)
+{
+ h->first_word = clib_host_to_net_u32 (h->first_word);
+}
+
#endif
/*