summaryrefslogtreecommitdiffstats
path: root/src/vnet/vxlan/vxlan_packet.h
blob: 5f93a36fd8fafa835a3810804e870940057dbc1f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/*
 * Copyright (c) 2015 Cisco and/or its affiliates.
 * 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:
 *
 *     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.
 */
#ifndef __included_vxlan_packet_h__
#define __included_vxlan_packet_h__ 1

/* 
 * From RFC-7384
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |R|R|R|R|I|R|R|R|            Reserved                           |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                VXLAN Network Identifier (VNI) |   Reserved    |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * 
 * VXLAN Header:  This is an 8-byte field that has:
 * 
 * - Flags (8 bits): where the I flag MUST be set to 1 for a valid
 * VXLAN Network ID (VNI).  The other 7 bits (designated "R") are
 * reserved fields and MUST be set to zero on transmission and
 * ignored on receipt.
 * 
 * - VXLAN Segment ID/VXLAN Network Identifier (VNI): this is a
 * 24-bit value used to designate the individual VXLAN overlay
 * network on which the communicating VMs are situated.  VMs in
 * different VXLAN overlay networks cannot communicate with each
 * other.
 * 
 * - Reserved fields (24 bits and 8 bits): MUST be set to zero on
 * transmission and ignored on receipt.
 * 
 */

typedef struct {
  u8 flags;
  u8 res1;
  u8 res2;
  u8 res3;
  u32 vni_reserved;
} vxlan_header_t;

#define VXLAN_FLAGS_I 0x08

static inline u32 vnet_get_vni (vxlan_header_t * h)
{
  u32 vni_reserved_host_byte_order;

  vni_reserved_host_byte_order = clib_net_to_host_u32 (h->vni_reserved);
  return vni_reserved_host_byte_order >> 8;
}

static inline void vnet_set_vni_and_flags (vxlan_header_t * h, u32 vni)
{
  h->vni_reserved = clib_host_to_net_u32 (vni<<8);
  * (u32 *) h = 0;
  h->flags = VXLAN_FLAGS_I;
}

#endif /* __included_vxlan_packet_h__ */
.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * 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. */ #ifndef included_vnet_handoff_h #define included_vnet_handoff_h #include <vlib/vlib.h> #include <vnet/ethernet/ethernet.h> #include <vnet/ip/ip4_packet.h> #include <vnet/ip/ip6_packet.h> #include <vnet/mpls/packet.h> typedef enum { HANDOFF_DISPATCH_NEXT_IP4_INPUT, HANDOFF_DISPATCH_NEXT_IP6_INPUT, HANDOFF_DISPATCH_NEXT_MPLS_INPUT, HANDOFF_DISPATCH_NEXT_ETHERNET_INPUT, HANDOFF_DISPATCH_NEXT_DROP, HANDOFF_DISPATCH_N_NEXT, } handoff_dispatch_next_t; static inline u64 ipv4_get_key (ip4_header_t * ip) { u64 hash_key; hash_key = *((u64 *) (&ip->address_pair)) ^ ip->protocol; return hash_key; } static inline u64 ipv6_get_key (ip6_header_t * ip) { u64 hash_key; hash_key = ip->src_address.as_u64[0] ^ rotate_left (ip->src_address.as_u64[1], 13) ^ rotate_left (ip->dst_address.as_u64[0], 26) ^ rotate_left (ip->dst_address.as_u64[1], 39) ^ ip->protocol; return hash_key; } #define MPLS_BOTTOM_OF_STACK_BIT_MASK 0x00000100U #define MPLS_LABEL_MASK 0xFFFFF000U static inline u64 mpls_get_key (mpls_unicast_header_t * m) { u64 hash_key; u8 ip_ver; /* find the bottom of the MPLS label stack. */ if (PREDICT_TRUE (m->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))) { goto bottom_lbl_found; } m++; if (PREDICT_TRUE (m->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))) { goto bottom_lbl_found; } m++; if (m->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK)) { goto bottom_lbl_found; } m++; if (m->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK)) { goto bottom_lbl_found; } m++; if (m->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK)) { goto bottom_lbl_found; } /* the bottom label was not found - use the last label */ hash_key = m->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_LABEL_MASK); return hash_key; bottom_lbl_found: m++; ip_ver = (*((u8 *) m) >> 4); /* find out if it is IPV4 or IPV6 header */ if (PREDICT_TRUE (ip_ver == 4)) { hash_key = ipv4_get_key ((ip4_header_t *) m); } else if (PREDICT_TRUE (ip_ver == 6)) { hash_key = ipv6_get_key ((ip6_header_t *) m); } else { /* use the bottom label */ hash_key = (m - 1)->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_LABEL_MASK); } return hash_key; } static inline u64 eth_get_sym_key (ethernet_header_t * h0) { u64 hash_key; if (PREDICT_TRUE (h0->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4)) { ip4_header_t *ip = (ip4_header_t *) (h0 + 1); hash_key = (u64) (ip->src_address.as_u32 ^ ip->dst_address.as_u32 ^ ip->protocol); } else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6)) { ip6_header_t *ip = (ip6_header_t *) (h0 + 1); hash_key = (u64) (ip->src_address.as_u64[0] ^ ip->src_address.as_u64[1] ^ ip->dst_address.as_u64[0] ^ ip->dst_address.as_u64[1] ^ ip->protocol); } else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS)) { hash_key = mpls_get_key ((mpls_unicast_header_t *) (h0 + 1)); } else if (PREDICT_FALSE ((h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) || (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD)))) { ethernet_vlan_header_t *outer = (ethernet_vlan_header_t *) (h0 + 1); outer = (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ? outer + 1 : outer; if (PREDICT_TRUE (outer->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4)) { ip4_header_t *ip = (ip4_header_t *) (outer + 1); hash_key = (u64) (ip->src_address.as_u32 ^ ip->dst_address.as_u32 ^ ip->protocol); } else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6)) { ip6_header_t *ip = (ip6_header_t *) (outer + 1); hash_key = (u64) (ip->src_address.as_u64[0] ^ ip->src_address.as_u64[1] ^ ip->dst_address.as_u64[0] ^ ip->dst_address.as_u64[1] ^ ip->protocol); } else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS)) { hash_key = mpls_get_key ((mpls_unicast_header_t *) (outer + 1)); } else { hash_key = outer->type; } } else { hash_key = 0; } return hash_key; } static inline u64 eth_get_key (ethernet_header_t * h0) { u64 hash_key; if (PREDICT_TRUE (h0->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4)) { hash_key = ipv4_get_key ((ip4_header_t *) (h0 + 1)); } else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6)) { hash_key = ipv6_get_key ((ip6_header_t *) (h0 + 1)); } else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS)) { hash_key = mpls_get_key ((mpls_unicast_header_t *) (h0 + 1)); } else if ((h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) || (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD))) { ethernet_vlan_header_t *outer = (ethernet_vlan_header_t *) (h0 + 1); outer = (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ? outer + 1 : outer; if (PREDICT_TRUE (outer->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4)) { hash_key = ipv4_get_key ((ip4_header_t *) (outer + 1)); } else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6)) { hash_key = ipv6_get_key ((ip6_header_t *) (outer + 1)); } else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS)) { hash_key = mpls_get_key ((mpls_unicast_header_t *) (outer + 1)); } else { hash_key = outer->type; } } else { hash_key = 0; } return hash_key; } #endif /* included_vnet_handoff_h */ /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */