diff options
-rw-r--r-- | src/vnet/geneve/decap.c | 57 | ||||
-rw-r--r-- | src/vnet/geneve/geneve.c | 12 | ||||
-rw-r--r-- | src/vnet/geneve/geneve_packet.h | 115 |
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 /* |