FD.io VPP  v16.12-rc0-308-g931be3a
Vector Packet Processing
ioam_export.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 #ifndef __included_ioam_export_h__
16 #define __included_ioam_export_h__
17 
18 #include <vnet/vnet.h>
19 #include <vnet/ip/ip.h>
20 #include <vnet/ip/ip_packet.h>
21 #include <vnet/ip/ip4_packet.h>
22 #include <vnet/ip/ip6_packet.h>
23 #include <vnet/ip/udp.h>
24 #include <vnet/flow/ipfix_packet.h>
25 
26 #include <vppinfra/pool.h>
27 #include <vppinfra/hash.h>
28 #include <vppinfra/error.h>
29 #include <vppinfra/elog.h>
30 
31 #include <vlib/threads.h>
32 
33 typedef struct ioam_export_buffer {
34  /* Allocated buffer */
39 
40 
41 typedef struct {
42  /* API message ID base */
44 
45  /* TODO: to support multiple collectors all this has to be grouped and create a vector here*/
49 
50  /* ipfix collector, our ip address */
53 
54  /* Pool of ioam_export_buffer_t */
56  /* Vector of per thread ioam_export_buffer_t to buffer pool index */
58  /* Lock per thread to swap buffers between worker and timer process*/
59  volatile u32 **lockp;
60 
61  /* time scale transform*/
64 
65  /* convenience */
70 
74 
76 
78 
79 #define DEFAULT_EXPORT_SIZE (3 * CLIB_CACHE_LINE_BYTES)
80 /*
81  * Number of records in a buffer
82  * ~(MTU (1500) - [ip hdr(40) + UDP(8) + ipfix (24)]) / DEFAULT_EXPORT_SIZE
83  */
84 #define DEFAULT_EXPORT_RECORDS 7
85 
87 {
89 
90  if (vec_len(em->buffer_per_thread) > thread_id)
91  return(pool_elt_at_index(em->buffer_pool, em->buffer_per_thread[thread_id]));
92  return(0);
93 }
94 
96 {
99  b0->current_data = 0;
102  return(1);
103 }
104 
105 inline static int ioam_export_init_buffer (vlib_main_t *vm,
107 {
108  vlib_buffer_t *b = 0;
109 
110  if (!eb)
111  return(-1);
112  /* TODO: Perhaps buffer init from template here */
113  if (vlib_buffer_alloc (vm, &(eb->buffer_index), 1) != 1)
114  return(-2);
115  eb->records_in_this_buffer = 0;
116  eb->touched_at = vlib_time_now(vm);
117  b = vlib_get_buffer(vm, eb->buffer_index);
119  vnet_buffer(b)->sw_if_index[VLIB_RX] = 0;
120  vnet_buffer(b)->sw_if_index[VLIB_TX] = ~0;
121  return(1);
122 }
123 
124 inline static void ioam_export_thread_buffer_free (void)
125 {
127  vlib_main_t *vm = em->vlib_main;
128  ioam_export_buffer_t *eb = 0;
129  int i;
130  for (i = 0; i < vec_len(em->buffer_per_thread); i++)
131  {
133  if (eb)
134  vlib_buffer_free(vm, &(eb->buffer_index), 1);
135  }
136  for (i = 0; i < vec_len(em->lockp); i++)
137  clib_mem_free((void *) em->lockp[i]);
139  pool_free(em->buffer_pool);
140  vec_free(em->lockp);
141  em->buffer_per_thread = 0;
142  em->buffer_pool = 0;
143  em->lockp = 0;
144 }
145 
147 {
149  int no_of_threads = vec_len(vlib_worker_threads);
150  int i;
151  ioam_export_buffer_t *eb = 0;
153 
155  no_of_threads - 1,
158  no_of_threads-1,
160  vec_validate_aligned(em->lockp, no_of_threads-1,
162  ip4_lookup_node = vlib_get_node_by_name (vm, (u8 *) "ip4-lookup");
163  em->ip4_lookup_node_index = ip4_lookup_node->index;
164  if (!em->buffer_per_thread || !em->buffer_pool || !em->lockp)
165  {
166  return(-1);
167  }
168  for (i=0; i < no_of_threads; i++)
169  {
170  eb = 0;
172  memset(eb, 0, sizeof (*eb));
173  em->buffer_per_thread[i] = eb - em->buffer_pool;
174  if (ioam_export_init_buffer(vm, eb) != 1)
175  {
177  return(-2);
178  }
181  memset ((void *) em->lockp[i], 0, CLIB_CACHE_LINE_BYTES);
182  }
183  return(1);
184 }
185 
186 #define IPFIX_IOAM_EXPORT_ID 272
187 
188 /* Used to build the rewrite */
189 /* data set packet */
190 typedef struct {
194 
195 typedef struct {
200 
201 
202 inline static void ioam_export_header_cleanup (ip4_address_t * collector_address,
203  ip4_address_t * src_address)
204 {
206  vec_free(em->record_header);
207  em->record_header = 0;
208 }
209 
210 inline static int ioam_export_header_create (ip4_address_t * collector_address,
211  ip4_address_t * src_address)
212 {
214  ip4_header_t * ip;
215  udp_header_t * udp;
217  ipfix_set_header_t * s;
218  u8 * rewrite = 0;
220 
221 
222  /* allocate rewrite space */
223  vec_validate_aligned (rewrite,
224  sizeof (ip4_ipfix_data_packet_t) - 1,
226 
227  tp = (ip4_ipfix_data_packet_t *) rewrite;
228  ip = (ip4_header_t *) &tp->ip4;
229  udp = (udp_header_t *) (ip+1);
230  h = (ipfix_message_header_t *)(udp+1);
231  s = (ipfix_set_header_t *)(h+1);
232 
233  ip->ip_version_and_header_length = 0x45;
234  ip->ttl = 254;
235  ip->protocol = IP_PROTOCOL_UDP;
236  ip->src_address.as_u32 = src_address->as_u32;
237  ip->dst_address.as_u32 = collector_address->as_u32;
238  udp->src_port = clib_host_to_net_u16 (4939 /* $$FIXME */);
239  udp->dst_port = clib_host_to_net_u16 (4939);
240  /* FIXUP: UDP length */
241  udp->length = clib_host_to_net_u16 (vec_len(rewrite) +
242  (DEFAULT_EXPORT_RECORDS * DEFAULT_EXPORT_SIZE) - sizeof (*ip));
243 
244  /* FIXUP: message header export_time */
245  /* FIXUP: message header sequence_number */
246  h->domain_id = clib_host_to_net_u32 (em->domain_id);
247 
248  /*FIXUP: Setid length in octets if records exported are not default*/
250  (sizeof(*s) + (DEFAULT_EXPORT_RECORDS * DEFAULT_EXPORT_SIZE)));
251 
252  /* FIXUP: h version and length length in octets if records exported are not default */
253  h->version_length = version_length (sizeof(*h)+
254  (sizeof(*s) + (DEFAULT_EXPORT_RECORDS * DEFAULT_EXPORT_SIZE)));
255 
256  /* FIXUP: ip length if records exported are not default */
257  /* FIXUP: ip checksum if records exported are not default */
258  ip->length = clib_host_to_net_u16 (vec_len(rewrite) +
259  (DEFAULT_EXPORT_RECORDS * DEFAULT_EXPORT_SIZE));
260  ip->checksum = ip4_header_checksum (ip);
261  _vec_len(rewrite) = sizeof(ip4_ipfix_data_packet_t);
262  em->record_header = rewrite;
263  return(1);
264 }
265 
266 inline static int ioam_export_send_buffer (vlib_main_t *vm,
268 {
270  ip4_header_t * ip;
271  udp_header_t * udp;
273  ipfix_set_header_t * s;
275  vlib_buffer_t *b0;
276  u16 new_l0, old_l0;
277  ip_csum_t sum0;
278  vlib_frame_t * nf = 0;
279  u32 * to_next;
280 
281  b0 = vlib_get_buffer(vm, eb->buffer_index);
282  tp = vlib_buffer_get_current (b0);
283  ip = (ip4_header_t *) &tp->ip4;
284  udp = (udp_header_t *) (ip+1);
285  h = (ipfix_message_header_t *)(udp+1);
286  s = (ipfix_set_header_t *)(h+1);
287 
288  /* FIXUP: message header export_time */
289  h->export_time = clib_host_to_net_u32((u32)
290  (((f64)em->unix_time_0) +
291  (vlib_time_now(em->vlib_main) - em->vlib_time_0)));
292 
293  /* FIXUP: message header sequence_number */
294  h->sequence_number = clib_host_to_net_u32 (em->sequence_number++);
295 
296  /* FIXUP: lengths if different from default */
299  b0->current_length -
300  (sizeof (*ip) + sizeof (*udp) +
301  sizeof (*h)));
303  (sizeof (*ip) + sizeof (*udp)));
304  sum0 = ip->checksum;
305  old_l0 = ip->length;
306  new_l0 = clib_host_to_net_u16 ((u16)b0->current_length);
307  sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
308  length /* changed member */);
309  ip->checksum = ip_csum_fold (sum0);
310  ip->length = new_l0;
311  udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
312  }
313 
314  /* Enqueue pkts to ip4-lookup */
315 
317  nf->n_vectors = 0;
318  to_next = vlib_frame_vector_args (nf);
319  nf->n_vectors = 1;
320  to_next[0] = eb->buffer_index;
322  return(1);
323 
324 }
325 
326 #endif /* __included_ioam_export_h__ */
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#define DEFAULT_EXPORT_RECORDS
Definition: ioam_export.h:84
ip4_address_t src_address
Definition: ip4_packet.h:138
Fixed length block allocator.
u32 export_process_node_index
Definition: ioam_export.h:72
u32 index
Definition: node.h:237
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:182
vlib_node_registration_t export_node
(constructor) VLIB_REGISTER_NODE (export_node)
Definition: ioam_export.h:77
struct _vlib_node_registration vlib_node_registration_t
vlib_worker_thread_t * vlib_worker_threads
Definition: threads.h:112
uword ip_csum_t
Definition: ip_packet.h:86
static int ioam_export_send_buffer(vlib_main_t *vm, ioam_export_buffer_t *eb)
Definition: ioam_export.h:266
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:407
ip4_address_t ipfix_collector
Definition: ioam_export.h:51
vlib_node_registration_t ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (ip4_lookup_node)
Definition: ip4_forward.c:485
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:78
#define pool_alloc_aligned(P, N, A)
Allocate N more free elements to pool (general version).
Definition: pool.h:235
ioam_export_buffer_t * buffer_pool
Definition: ioam_export.h:55
ipfix_data_packet_t ipfix
Definition: ioam_export.h:198
#define always_inline
Definition: clib.h:84
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:190
ip4_address_t dst_address
Definition: ip4_packet.h:138
struct ioam_export_buffer ioam_export_buffer_t
unsigned long u64
Definition: types.h:89
#define IPFIX_IOAM_EXPORT_ID
Definition: ioam_export.h:186
static int ioam_export_header_create(ip4_address_t *collector_address, ip4_address_t *src_address)
Definition: ioam_export.h:210
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:82
volatile u32 ** lockp
Definition: ioam_export.h:59
vnet_main_t * vnet_main
Definition: ioam_export.h:67
#define PREDICT_FALSE(x)
Definition: clib.h:97
static ioam_export_buffer_t * ioam_export_get_my_buffer(u32 thread_id)
Definition: ioam_export.h:86
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:194
static u32 version_length(u16 length)
Definition: ipfix_packet.h:31
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P (general version).
Definition: pool.h:169
#define pool_free(p)
Free a pool.
Definition: pool.h:263
ipfix_message_header_t h
Definition: ioam_export.h:191
vlib_main_t * vlib_main
Definition: ioam_export.h:66
u16 n_vectors
Definition: node.h:344
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
ip4_address_t src_address
Definition: ioam_export.h:52
#define clib_memcpy(a, b, c)
Definition: string.h:64
#define VLIB_BUFFER_TOTAL_LENGTH_VALID
Definition: buffer.h:99
static void ioam_export_header_cleanup(ip4_address_t *collector_address, ip4_address_t *src_address)
Definition: ioam_export.h:202
static int ioam_export_init_buffer(vlib_main_t *vm, ioam_export_buffer_t *eb)
Definition: ioam_export.h:105
ipfix_set_header_t s
Definition: ioam_export.h:192
unsigned int u32
Definition: types.h:88
#define vnet_buffer(b)
Definition: buffer.h:333
ethernet_main_t * ethernet_main
Definition: ioam_export.h:68
void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: dpdk_buffer.c:766
static void clib_mem_free(void *p)
Definition: mem.h:176
u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: dpdk_buffer.c:643
u64 uword
Definition: types.h:112
static u32 ipfix_set_id_length(u16 set_id, u16 length)
Definition: ipfix_packet.h:114
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
Definition: defs.h:47
static int ioam_export_thread_buffer_init(vlib_main_t *vm)
Definition: ioam_export.h:146
unsigned short u16
Definition: types.h:57
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:253
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:133
#define DEFAULT_EXPORT_SIZE
Definition: ioam_export.h:79
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:117
static void ioam_export_thread_buffer_free(void)
Definition: ioam_export.h:124
u8 data[0]
Packet data.
Definition: buffer.h:154
static int ioam_export_buffer_add_header(vlib_buffer_t *b0)
Definition: ioam_export.h:95
u8 ip_version_and_header_length
Definition: ip4_packet.h:108
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:185
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:194
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:138
ioam_export_main_t ioam_export_main
Definition: ioam_export.h:75
Definition: defs.h:46