FD.io VPP  v17.01.1-3-gc6833f8
Vector Packet Processing
sr_replicate.c
Go to the documentation of this file.
1 /*
2  * sr_replicate.c: ipv6 segment routing replicator for multicast
3  *
4  * Copyright (c) 2016 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 /**
18  * @file
19  * @brief Functions for replicating packets across SR tunnels.
20  *
21  * Leverages rte_pktmbuf_clone() so there is no memcpy for
22  * invariant parts of the packet.
23  *
24  * @note Currently requires DPDK
25 */
26 
27 #if DPDK > 0 /* Cannot run replicate without DPDK */
28 #include <vlib/vlib.h>
29 #include <vnet/vnet.h>
30 #include <vnet/pg/pg.h>
31 #include <vnet/sr/sr.h>
32 #include <vnet/devices/dpdk/dpdk.h>
33 #include <vnet/ip/ip.h>
34 #include <vnet/fib/ip6_fib.h>
35 
36 #include <vppinfra/hash.h>
37 #include <vppinfra/error.h>
38 #include <vppinfra/elog.h>
39 
40 /**
41  * @brief sr_replicate state.
42  *
43 */
44 typedef struct
45 {
46  /* convenience */
50 
52 
53 /**
54  * @brief Information to display in packet trace.
55  *
56 */
57 typedef struct
58 {
63  u8 sr[256];
65 
66 /**
67  * @brief packet trace format function.
68  *
69  * @param *s u8 used for string output
70  * @param *args va_list structured input to va_arg to output @ref sr_replicate_trace_t
71  * @return *s u8 - formatted trace output
72 */
73 static u8 *
74 format_sr_replicate_trace (u8 * s, va_list * args)
75 {
76  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
77  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
78  sr_replicate_trace_t *t = va_arg (*args, sr_replicate_trace_t *);
79  ip6_sr_main_t *sm = &sr_main;
81  ip6_fib_t *rx_fib, *tx_fib;
82 
83  rx_fib = ip6_fib_get (tun->rx_fib_index);
84  tx_fib = ip6_fib_get (tun->tx_fib_index);
85 
86  s = format
87  (s, "SR-REPLICATE: next %s ip6 src %U dst %U len %u\n"
88  " rx-fib-id %d tx-fib-id %d\n%U",
89  "ip6-lookup",
91  format_ip6_address, &t->dst, t->length,
92  rx_fib->table_id, tx_fib->table_id,
93  format_ip6_sr_header, t->sr, 0 /* print_hmac */ );
94  return s;
95 
96 }
97 
98 #define foreach_sr_replicate_error \
99 _(REPLICATED, "sr packets replicated") \
100 _(NO_BUFFERS, "error allocating buffers for replicas") \
101 _(NO_REPLICAS, "no replicas were needed") \
102 _(NO_BUFFER_DROPS, "sr no buffer drops")
103 
104 /**
105  * @brief Struct for SR replicate errors
106  */
107 typedef enum
108 {
109 #define _(sym,str) SR_REPLICATE_ERROR_##sym,
111 #undef _
114 
115 /**
116  * @brief Error strings for SR replicate
117  */
118 static char *sr_replicate_error_strings[] = {
119 #define _(sym,string) string,
121 #undef _
122 };
123 
124 /**
125  * @brief Defines next-nodes for packet processing.
126  *
127 */
128 typedef enum
129 {
133 
134 /**
135  * @brief Single loop packet replicator.
136  *
137  * @node sr-replicate
138  * @param vm vlib_main_t
139  * @return frame->n_vectors uword
140 */
141 static uword
143  vlib_node_runtime_t * node, vlib_frame_t * frame)
144 {
145  u32 n_left_from, *from, *to_next;
146  sr_replicate_next_t next_index;
147  int pkts_replicated = 0;
148  ip6_sr_main_t *sm = &sr_main;
149  int no_buffer_drops = 0;
151  unsigned socket_id = rte_socket_id ();
153 
154  from = vlib_frame_vector_args (frame);
155  n_left_from = frame->n_vectors;
156  next_index = node->cached_next_index;
157 
159 
160  while (n_left_from > 0)
161  {
162  u32 n_left_to_next;
163 
164  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
165 
166  while (n_left_from > 0 && n_left_to_next > 0)
167  {
168  u32 bi0, hdr_bi0;
169  vlib_buffer_t *b0, *orig_b0;
170  struct rte_mbuf *orig_mb0 = 0, *hdr_mb0 = 0, *clone0 = 0;
171  struct rte_mbuf **hdr_vec = 0, **rte_mbuf_vec = 0;
172  ip6_sr_policy_t *pol0 = 0;
173  ip6_sr_tunnel_t *t0 = 0;
174  ip6_sr_header_t *hdr_sr0 = 0;
175  ip6_header_t *ip0 = 0, *hdr_ip0 = 0;
176  int num_replicas = 0;
177  int i;
178  u32 len_bytes = sizeof (ip6_header_t);
179  u8 next_hdr, ip_next_hdr = IPPROTO_IPV6_ROUTE;
180 
181  bi0 = from[0];
182 
183  b0 = vlib_get_buffer (vm, bi0);
184  orig_b0 = b0;
185 
186  pol0 = pool_elt_at_index (sm->policies,
187  vnet_buffer (b0)->ip.save_protocol);
188 
189  ip0 = vlib_buffer_get_current (b0);
190  /* Skip forward to the punch-in point */
191  vlib_buffer_advance (b0, sizeof (*ip0));
192  next_hdr = ip0->protocol;
193 
194  /* HBH must immediately follow ipv6 header */
195  if (PREDICT_FALSE
196  (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS))
197  {
198  ip6_hop_by_hop_ext_t *ext_hdr =
199  (ip6_hop_by_hop_ext_t *) ip6_next_header (ip0);
200  u32 ext_hdr_len = 0;
201  ext_hdr_len = ip6_ext_header_len ((ip6_ext_header_t *) ext_hdr);
202  len_bytes += ext_hdr_len;
203  next_hdr = ext_hdr->next_hdr;
204  ext_hdr->next_hdr = IPPROTO_IPV6_ROUTE;
205  ip_next_hdr = IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS;
206  /* Skip forward to the punch-in point */
207  vlib_buffer_advance (b0, ext_hdr_len);
208 
209  }
210 
211  orig_mb0 = rte_mbuf_from_vlib_buffer (b0);
212 
213  i16 delta0 = vlib_buffer_length_in_chain (vm, orig_b0)
214  - (i16) orig_mb0->pkt_len;
215 
216  u16 new_data_len0 = (u16) ((i16) orig_mb0->data_len + delta0);
217  u16 new_pkt_len0 = (u16) ((i16) orig_mb0->pkt_len + delta0);
218 
219  orig_mb0->data_len = new_data_len0;
220  orig_mb0->pkt_len = new_pkt_len0;
221  orig_mb0->data_off += (u16) (b0->current_data);
222 
223  /*
224  Before entering loop determine if we can allocate:
225  - all the new HEADER RTE_MBUFs and assign them to a vector
226  - all the clones
227 
228  if successful, then iterate over vectors of resources
229 
230  */
231  num_replicas = vec_len (pol0->tunnel_indices);
232 
233  if (PREDICT_FALSE (num_replicas == 0))
234  {
235  b0->error = node->errors[SR_REPLICATE_ERROR_NO_REPLICAS];
236  goto do_trace0;
237  }
238 
239  vec_reset_length (hdr_vec);
240  vec_reset_length (rte_mbuf_vec);
241 
242  for (i = 0; i < num_replicas; i++)
243  {
244  uint8_t nb_seg;
245  struct rte_mbuf *clone0i;
246  vlib_buffer_t *clone0_c, *clone_b0;
247 
248  t0 = vec_elt_at_index (sm->tunnels, pol0->tunnel_indices[i]);
249  hdr_mb0 = rte_pktmbuf_alloc (bm->pktmbuf_pools[socket_id]);
250 
251  if (i < (num_replicas - 1))
252  {
253  /* Not the last tunnel to process */
254  clone0 = rte_pktmbuf_clone
255  (orig_mb0, bm->pktmbuf_pools[socket_id]);
256  if (clone0 == 0)
257  goto clone_fail;
258  nb_seg = 0;
259  clone0i = clone0;
260  clone0_c = NULL;
261  while ((clone0->nb_segs >= 1) && (nb_seg < clone0->nb_segs))
262  {
263 
264  clone_b0 = vlib_buffer_from_rte_mbuf (clone0i);
265  vlib_buffer_init_for_free_list (clone_b0, fl);
266 
267  ASSERT ((clone_b0->flags & VLIB_BUFFER_NEXT_PRESENT) ==
268  0);
269  ASSERT (clone_b0->current_data == 0);
270 
271  clone_b0->current_data =
272  (clone0i->buf_addr + clone0i->data_off) -
273  (void *) clone_b0->data;
274 
275  clone_b0->current_length = clone0i->data_len;
276  if (PREDICT_FALSE (clone0_c != NULL))
277  {
278  clone0_c->flags |= VLIB_BUFFER_NEXT_PRESENT;
279  clone0_c->next_buffer =
280  vlib_get_buffer_index (vm, clone_b0);
281  }
282  clone0_c = clone_b0;
283  clone0i = clone0i->next;
284  nb_seg++;
285  }
286  }
287  else
288  /* First tunnel to process, use original MB */
289  clone0 = orig_mb0;
290 
291 
292  if (PREDICT_FALSE (!clone0 || !hdr_mb0))
293  {
294  clone_fail:
295  b0->error = node->errors[SR_REPLICATE_ERROR_NO_BUFFERS];
296 
297  vec_foreach_index (i, rte_mbuf_vec)
298  {
299  rte_pktmbuf_free (rte_mbuf_vec[i]);
300  }
301  vec_free (rte_mbuf_vec);
302 
303  vec_foreach_index (i, hdr_vec)
304  {
305  rte_pktmbuf_free (hdr_vec[i]);
306  }
307  vec_free (hdr_vec);
308 
309  goto do_trace0;
310  }
311 
312  vec_add1 (hdr_vec, hdr_mb0);
313  vec_add1 (rte_mbuf_vec, clone0);
314 
315  }
316 
317  for (i = 0; i < num_replicas; i++)
318  {
319  vlib_buffer_t *hdr_b0;
320  u16 new_l0 = 0;
321 
322  t0 = vec_elt_at_index (sm->tunnels, pol0->tunnel_indices[i]);
323  /* Our replicas */
324  hdr_mb0 = hdr_vec[i];
325  clone0 = rte_mbuf_vec[i];
326 
327  hdr_mb0->data_len = len_bytes + vec_len (t0->rewrite);
328  hdr_mb0->pkt_len = hdr_mb0->data_len +
329  vlib_buffer_length_in_chain (vm, orig_b0);
330 
331  hdr_b0 = vlib_buffer_from_rte_mbuf (hdr_mb0);
332 
333  vlib_buffer_init_for_free_list (hdr_b0, fl);
334 
335  memcpy (hdr_b0->data, ip0, len_bytes);
336  memcpy (hdr_b0->data + len_bytes, t0->rewrite,
337  vec_len (t0->rewrite));
338 
339  hdr_b0->current_data = 0;
340  hdr_b0->current_length = len_bytes + vec_len (t0->rewrite);
341  hdr_b0->flags = orig_b0->flags | VLIB_BUFFER_NEXT_PRESENT;
342  hdr_b0->trace_index = orig_b0->trace_index;
343  vnet_buffer (hdr_b0)->l2_classify.opaque_index = 0;
344 
346  hdr_mb0->pkt_len - hdr_b0->current_length;
347  vnet_buffer (hdr_b0)->sw_if_index[VLIB_TX] = t0->tx_fib_index;
348 
349  hdr_ip0 = (ip6_header_t *) hdr_b0->data;
350  new_l0 = clib_net_to_host_u16 (ip0->payload_length) +
351  vec_len (t0->rewrite);
352  hdr_ip0->payload_length = clib_host_to_net_u16 (new_l0);
353  hdr_sr0 = (ip6_sr_header_t *) ((u8 *) hdr_ip0 + len_bytes);
354  /* $$$ tune */
355  clib_memcpy (hdr_sr0, t0->rewrite, vec_len (t0->rewrite));
356  hdr_sr0->protocol = next_hdr;
357  hdr_ip0->protocol = ip_next_hdr;
358 
359  /* Copy dst address into the DA slot in the segment list */
360  clib_memcpy (hdr_sr0->segments, ip0->dst_address.as_u64,
361  sizeof (ip6_address_t));
362 
363  /* Rewrite the ip6 dst address */
364  hdr_ip0->dst_address.as_u64[0] = t0->first_hop.as_u64[0];
365  hdr_ip0->dst_address.as_u64[1] = t0->first_hop.as_u64[1];
366 
367  sr_fix_hmac (sm, hdr_ip0, hdr_sr0);
368 
369  /* prepend new header to invariant piece */
370  hdr_mb0->next = clone0;
371  hdr_b0->next_buffer =
373  vlib_buffer_from_rte_mbuf (clone0));
374 
375  /* update header's fields */
376  hdr_mb0->pkt_len =
377  (uint16_t) (hdr_mb0->data_len + clone0->pkt_len);
378  hdr_mb0->nb_segs = (uint8_t) (clone0->nb_segs + 1);
379 
380  /* copy metadata from source packet */
381  hdr_mb0->port = clone0->port;
382  hdr_mb0->vlan_tci = clone0->vlan_tci;
383  hdr_mb0->vlan_tci_outer = clone0->vlan_tci_outer;
384  hdr_mb0->tx_offload = clone0->tx_offload;
385  hdr_mb0->hash = clone0->hash;
386 
387  hdr_mb0->ol_flags = clone0->ol_flags & ~(IND_ATTACHED_MBUF);
388 
389  __rte_mbuf_sanity_check (hdr_mb0, 1);
390 
391  hdr_bi0 = vlib_get_buffer_index (vm, hdr_b0);
392 
393  to_next[0] = hdr_bi0;
394  to_next += 1;
395  n_left_to_next -= 1;
396 
397  if (n_left_to_next == 0)
398  {
399  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
400  vlib_get_next_frame (vm, node, next_index,
401  to_next, n_left_to_next);
402 
403  }
404  pkts_replicated++;
405  }
406 
407  from += 1;
408  n_left_from -= 1;
409 
410  do_trace0:
412  {
413  sr_replicate_trace_t *tr = vlib_add_trace (vm, node,
414  b0, sizeof (*tr));
415  tr->tunnel_index = t0 - sm->tunnels;
416  tr->length = 0;
417  if (hdr_ip0)
418  {
419  memcpy (tr->src.as_u8, hdr_ip0->src_address.as_u8,
420  sizeof (tr->src.as_u8));
421  memcpy (tr->dst.as_u8, hdr_ip0->dst_address.as_u8,
422  sizeof (tr->dst.as_u8));
423  if (hdr_ip0->payload_length)
424  tr->length = clib_net_to_host_u16
425  (hdr_ip0->payload_length);
426  }
427  tr->next_index = next_index;
428  if (hdr_sr0)
429  memcpy (tr->sr, hdr_sr0, sizeof (tr->sr));
430  }
431 
432  }
433 
434  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
435  }
436 
438  SR_REPLICATE_ERROR_REPLICATED,
439  pkts_replicated);
440 
442  SR_REPLICATE_ERROR_NO_BUFFER_DROPS,
443  no_buffer_drops);
444 
445  return frame->n_vectors;
446 }
447 
448 /* *INDENT-OFF* */
450  .function = sr_replicate_node_fn,
451  .name = "sr-replicate",
452  .vector_size = sizeof (u32),
453  .format_trace = format_sr_replicate_trace,
455 
457  .error_strings = sr_replicate_error_strings,
458 
459  .n_next_nodes = SR_REPLICATE_N_NEXT,
460 
461  .next_nodes = {
462  [SR_REPLICATE_NEXT_IP6_LOOKUP] = "ip6-lookup",
463  },
464 };
465 
467 /* *INDENT-ON* */
468 
469 clib_error_t *
471 {
473 
474  msm->vlib_main = vm;
475  msm->vnet_main = vnet_get_main ();
476 
477  return 0;
478 }
479 
481 
482 #endif /* DPDK */
483 
484 /*
485  * fd.io coding-style-patch-verification: ON
486  *
487  * Local Variables:
488  * eval: (c-set-style "gnu")
489  * End:
490  */
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:459
ip6_sr_main_t sr_main
Definition: sr.c:30
clib_error_t * sr_replicate_init(vlib_main_t *vm)
Definition: sr_replicate.c:470
#define vec_foreach_index(var, v)
Iterate over vector indices.
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#define CLIB_UNUSED(x)
Definition: clib.h:79
#define rte_mbuf_from_vlib_buffer(x)
Definition: buffer.h:389
ip6_address_t src
Definition: sr_replicate.c:59
u32 tx_fib_index
TX Fib index.
Definition: sr.h:66
static ip6_fib_t * ip6_fib_get(fib_node_index_t index)
Definition: ip6_fib.h:106
format_function_t format_ip6_address
Definition: format.h:95
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
u8 as_u8[16]
Definition: ip6_packet.h:48
u64 as_u64[2]
Definition: ip6_packet.h:51
#define NULL
Definition: clib.h:55
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
unsigned rte_socket_id()
vlib_buffer_main_t * buffer_main
Definition: main.h:104
u32 rx_fib_index
RX Fib index.
Definition: sr.h:64
static uword sr_replicate_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Single loop packet replicator.
Definition: sr_replicate.c:142
vlib_error_t * errors
Definition: node.h:419
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:100
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static void vlib_buffer_init_for_free_list(vlib_buffer_t *_dst, vlib_buffer_free_list_t *fl)
Definition: buffer_funcs.h:613
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:78
ip6_address_t dst
Definition: sr_replicate.c:59
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:194
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
u8 protocol
Protocol for next header.
Definition: sr_packet.h:180
#define IPPROTO_IPV6_ROUTE
Definition: sr_packet.h:170
Information to display in packet trace.
Definition: sr_replicate.c:57
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
Definition: buffer_funcs.h:70
#define VLIB_BUFFER_NEXT_PRESENT
Definition: buffer.h:97
vlib_main_t * vlib_main
Definition: sr_replicate.c:47
#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
#define PREDICT_FALSE(x)
Definition: clib.h:97
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:350
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:121
static u8 * format_sr_replicate_trace(u8 *s, va_list *args)
packet trace format function.
Definition: sr_replicate.c:74
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1113
#define ip6_ext_header_len(p)
Definition: ip6_packet.h:458
u8 * rewrite
The actual ip6 SR header.
Definition: sr.h:69
struct rte_mempool ** pktmbuf_pools
Definition: buffer.h:328
u16 n_vectors
Definition: node.h:344
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
Definition: ip6.h:66
static char * sr_replicate_error_strings[]
Error strings for SR replicate.
Definition: sr_replicate.c:118
#define clib_memcpy(a, b, c)
Definition: string.h:69
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:207
u32 * tunnel_indices
vector to SR tunnel index
Definition: sr.h:155
#define ARRAY_LEN(x)
Definition: clib.h:59
sr_replicate state.
Definition: sr_replicate.c:44
void sr_fix_hmac(ip6_sr_main_t *sm, ip6_header_t *ip, ip6_sr_header_t *sr)
Use passed HMAC key in ip6_sr_header_t in OpenSSL HMAC routines.
Definition: sr.c:46
static void * ip6_next_header(ip6_header_t *i)
Definition: ip6_packet.h:341
Segment Route tunnel.
Definition: sr.h:49
#define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX
Definition: buffer.h:310
ip6_address_t first_hop
First hop, to save 1 elt in the segment list.
Definition: sr.h:61
u16 cached_next_index
Definition: node.h:463
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
#define vnet_buffer(b)
Definition: buffer.h:361
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:117
ip6_sr_tunnel_t * tunnels
pool of tunnel instances, sr entry only
Definition: sr.h:185
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:95
u64 uword
Definition: types.h:112
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:112
format_function_t format_ip6_sr_header
Definition: sr.h:236
Definition: defs.h:47
unsigned short u16
Definition: types.h:57
u16 payload_length
Definition: ip6_packet.h:328
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
ip6_address_t segments[0]
The segment + policy list elts.
Definition: sr_packet.h:219
Segment Routing policy.
Definition: sr.h:149
ip6_sr_policy_t * policies
policy pool
Definition: sr.h:194
SR header struct.
Definition: sr_packet.h:177
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:253
sr_replicate_error_t
Struct for SR replicate errors.
Definition: sr_replicate.c:107
#define foreach_sr_replicate_error
Definition: sr_replicate.c:98
short i16
Definition: types.h:46
#define VLIB_NODE_FUNCTION_MULTIARCH(node, fn)
Definition: node.h:158
Segment Routing header.
Segment Routing state.
Definition: sr.h:182
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
#define vlib_buffer_from_rte_mbuf(x)
Definition: buffer.h:390
u8 data[0]
Packet data.
Definition: buffer.h:158
sr_replicate_main_t sr_replicate_main
Definition: sr_replicate.c:51
vnet_main_t * vnet_main
Definition: sr_replicate.c:48
u32 table_id
Definition: ip6.h:69
static vlib_buffer_free_list_t * vlib_buffer_get_free_list(vlib_main_t *vm, u32 free_list_index)
Definition: buffer_funcs.h:317
vlib_node_registration_t sr_replicate_node
(constructor) VLIB_REGISTER_NODE (sr_replicate_node)
Definition: sr_replicate.c:449
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:57
u32 trace_index
Specifies index into trace buffer if VLIB_PACKET_IS_TRACED flag is set.
Definition: buffer.h:142
sr_replicate_next_t
Defines next-nodes for packet processing.
Definition: sr_replicate.c:128
ip6_address_t dst_address
Definition: ip6_packet.h:337