u32 next_index;
u32 tunnel_index;
u32 error;
- u32 vni;
+ u32 vni_rsvd;
} geneve_rx_trace_t;
static u8 *
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;
}
/* 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
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;
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))
(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))
{
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
{
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))
{
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;
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))
(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))
{
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
{
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))
{
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,
/* 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
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;
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))
(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))
{
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
{
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))
{
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,
#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;
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
/*