FD.io VPP  v16.09
Vector Packet Processing
handoff.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef included_vnet_handoff_h
17 #define included_vnet_handoff_h
18 
19 #include <vlib/vlib.h>
20 #include <vnet/ethernet/ethernet.h>
21 #include <vnet/ip/ip4_packet.h>
22 #include <vnet/ip/ip6_packet.h>
23 #include <vnet/mpls-gre/packet.h>
24 
25 typedef enum
26 {
34 
35 static inline void
37 {
39  hf->valid = 1;
40 }
41 
42 static inline vlib_frame_queue_elt_t *
43 vlib_get_handoff_queue_elt (u32 vlib_worker_index)
44 {
47  u64 new_tail;
48 
49  fq = vlib_frame_queues[vlib_worker_index];
50  ASSERT (fq);
51 
52  new_tail = __sync_add_and_fetch (&fq->tail, 1);
53 
54  /* Wait until a ring slot is available */
55  while (new_tail >= fq->head_hint + fq->nelts)
57 
58  elt = fq->elts + (new_tail & (fq->nelts - 1));
59 
60  /* this would be very bad... */
61  while (elt->valid)
62  ;
63 
65  elt->last_n_vectors = elt->n_vectors = 0;
66 
67  return elt;
68 }
69 
70 static inline vlib_frame_queue_t *
72  u32 queue_hi_thresh,
74  handoff_queue_by_worker_index)
75 {
77 
78  fq = handoff_queue_by_worker_index[vlib_worker_index];
79  if (fq != (vlib_frame_queue_t *) (~0))
80  return fq;
81 
82  fq = vlib_frame_queues[vlib_worker_index];
83  ASSERT (fq);
84 
85  if (PREDICT_FALSE (fq->tail >= (fq->head_hint + queue_hi_thresh)))
86  {
87  /* a valid entry in the array will indicate the queue has reached
88  * the specified threshold and is congested
89  */
90  handoff_queue_by_worker_index[vlib_worker_index] = fq;
91  fq->enqueue_full_events++;
92  return fq;
93  }
94 
95  return NULL;
96 }
97 
98 static inline vlib_frame_queue_elt_t *
99 dpdk_get_handoff_queue_elt (u32 vlib_worker_index,
101  handoff_queue_elt_by_worker_index)
102 {
104 
105  if (handoff_queue_elt_by_worker_index[vlib_worker_index])
106  return handoff_queue_elt_by_worker_index[vlib_worker_index];
107 
108  elt = vlib_get_handoff_queue_elt (vlib_worker_index);
109 
110  handoff_queue_elt_by_worker_index[vlib_worker_index] = elt;
111 
112  return elt;
113 }
114 
115 static inline u64
117 {
118  u64 hash_key;
119 
120  hash_key = *((u64 *) (&ip->address_pair)) ^ ip->protocol;
121 
122  return hash_key;
123 }
124 
125 static inline u64
127 {
128  u64 hash_key;
129 
130  hash_key = ip->src_address.as_u64[0] ^
131  rotate_left (ip->src_address.as_u64[1], 13) ^
132  rotate_left (ip->dst_address.as_u64[0], 26) ^
133  rotate_left (ip->dst_address.as_u64[1], 39) ^ ip->protocol;
134 
135  return hash_key;
136 }
137 
138 #define MPLS_BOTTOM_OF_STACK_BIT_MASK 0x00000100U
139 #define MPLS_LABEL_MASK 0xFFFFF000U
140 
141 static inline u64
143 {
144  u64 hash_key;
145  u8 ip_ver;
146 
147 
148  /* find the bottom of the MPLS label stack. */
149  if (PREDICT_TRUE (m->label_exp_s_ttl &
150  clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK)))
151  {
152  goto bottom_lbl_found;
153  }
154  m++;
155 
156  if (PREDICT_TRUE (m->label_exp_s_ttl &
157  clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK)))
158  {
159  goto bottom_lbl_found;
160  }
161  m++;
162 
163  if (m->label_exp_s_ttl &
164  clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
165  {
166  goto bottom_lbl_found;
167  }
168  m++;
169 
170  if (m->label_exp_s_ttl &
171  clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
172  {
173  goto bottom_lbl_found;
174  }
175  m++;
176 
177  if (m->label_exp_s_ttl &
178  clib_net_to_host_u32 (MPLS_BOTTOM_OF_STACK_BIT_MASK))
179  {
180  goto bottom_lbl_found;
181  }
182 
183  /* the bottom label was not found - use the last label */
184  hash_key = m->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_LABEL_MASK);
185 
186  return hash_key;
187 
188 bottom_lbl_found:
189  m++;
190  ip_ver = (*((u8 *) m) >> 4);
191 
192  /* find out if it is IPV4 or IPV6 header */
193  if (PREDICT_TRUE (ip_ver == 4))
194  {
195  hash_key = ipv4_get_key ((ip4_header_t *) m);
196  }
197  else if (PREDICT_TRUE (ip_ver == 6))
198  {
199  hash_key = ipv6_get_key ((ip6_header_t *) m);
200  }
201  else
202  {
203  /* use the bottom label */
204  hash_key =
205  (m - 1)->label_exp_s_ttl & clib_net_to_host_u32 (MPLS_LABEL_MASK);
206  }
207 
208  return hash_key;
209 
210 }
211 
212 
213 static inline u64
215 {
216  u64 hash_key;
217 
218  if (PREDICT_TRUE (h0->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
219  {
220  hash_key = ipv4_get_key ((ip4_header_t *) (h0 + 1));
221  }
222  else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
223  {
224  hash_key = ipv6_get_key ((ip6_header_t *) (h0 + 1));
225  }
226  else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS_UNICAST))
227  {
228  hash_key = mpls_get_key ((mpls_unicast_header_t *) (h0 + 1));
229  }
230  else if ((h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ||
231  (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD)))
232  {
233  ethernet_vlan_header_t *outer = (ethernet_vlan_header_t *) (h0 + 1);
234 
235  outer = (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ?
236  outer + 1 : outer;
237  if (PREDICT_TRUE (outer->type) ==
238  clib_host_to_net_u16 (ETHERNET_TYPE_IP4))
239  {
240  hash_key = ipv4_get_key ((ip4_header_t *) (outer + 1));
241  }
242  else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6))
243  {
244  hash_key = ipv6_get_key ((ip6_header_t *) (outer + 1));
245  }
246  else if (outer->type ==
247  clib_host_to_net_u16 (ETHERNET_TYPE_MPLS_UNICAST))
248  {
249  hash_key = mpls_get_key ((mpls_unicast_header_t *) (outer + 1));
250  }
251  else
252  {
253  hash_key = outer->type;
254  }
255  }
256  else
257  {
258  hash_key = 0;
259  }
260 
261  return hash_key;
262 }
263 
264 #endif /* included_vnet_handoff_h */
265 
266 /*
267  * fd.io coding-style-patch-verification: ON
268  *
269  * Local Variables:
270  * eval: (c-set-style "gnu")
271  * End:
272  */
#define PREDICT_TRUE(x)
Definition: clib.h:98
u64 as_u64[2]
Definition: ip6_packet.h:50
#define NULL
Definition: clib.h:55
static vlib_frame_queue_elt_t * vlib_get_handoff_queue_elt(u32 vlib_worker_index)
Definition: handoff.h:43
volatile u32 valid
Definition: threads.h:74
ip6_address_t src_address
Definition: ip6_packet.h:298
static void vlib_worker_thread_barrier_check(void)
Definition: threads.h:204
#define MPLS_LABEL_MASK
Definition: handoff.h:139
unsigned long u64
Definition: types.h:89
vlib_frame_queue_elt_t * elts
Definition: threads.h:137
vlib_frame_queue_t ** vlib_frame_queues
Definition: threads.h:142
static vlib_frame_queue_elt_t * dpdk_get_handoff_queue_elt(u32 vlib_worker_index, vlib_frame_queue_elt_t **handoff_queue_elt_by_worker_index)
Definition: handoff.h:99
#define MPLS_BOTTOM_OF_STACK_BIT_MASK
Definition: handoff.h:138
static void vlib_put_handoff_queue_elt(vlib_frame_queue_elt_t *hf)
Definition: handoff.h:36
ip4_address_pair_t address_pair
Definition: ip4_packet.h:140
#define PREDICT_FALSE(x)
Definition: clib.h:97
static u64 ipv4_get_key(ip4_header_t *ip)
Definition: handoff.h:116
volatile u64 tail
Definition: threads.h:115
static vlib_frame_queue_t * is_vlib_handoff_queue_congested(u32 vlib_worker_index, u32 queue_hi_thresh, vlib_frame_queue_t **handoff_queue_by_worker_index)
Definition: handoff.h:71
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u32 enqueue_full_events
Definition: threads.h:119
unsigned char u8
Definition: types.h:56
handoff_dispatch_next_t
Definition: handoff.h:25
volatile u64 head_hint
Definition: threads.h:133
static u64 ipv6_get_key(ip6_header_t *ip)
Definition: handoff.h:126
static u64 eth_get_key(ethernet_header_t *h0)
Definition: handoff.h:214
static u64 mpls_get_key(mpls_unicast_header_t *m)
Definition: handoff.h:142
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:101
static uword rotate_left(uword x, uword i)
Definition: bitops.h:134
ip6_address_t dst_address
Definition: ip6_packet.h:298