FD.io VPP  v17.01-9-ge7dcee4
Vector Packet Processing
rewrite.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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  * rewrite.h: packet rewrite
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #ifndef included_vnet_rewrite_h
41 #define included_vnet_rewrite_h
42 
43 #include <vlib/vlib.h>
44 #include <vnet/l3_types.h>
45 
46 /* Consider using vector types for speed? */
48 
49 /* *INDENT-OFF* */
50 typedef CLIB_PACKED (struct {
51  /* Interface to mark re-written packets with. */
52  u32 sw_if_index;
53 
54  /* Packet processing node where rewrite happens. */
55  u32 node_index;
56 
57  /* Next node to feed after packet rewrite is done. */
58  u16 next_index;
59 
60  /* Number of bytes in rewrite data. */
61  u16 data_bytes;
62 
63  /* Max packet size layer 3 (MTU) for output interface.
64  Used for MTU check after packet rewrite. */
65  u16 max_l3_packet_bytes;
66 
67  /* Rewrite string starting at end and going backwards. */
68  u8 data[0];
69 }) vnet_rewrite_header_t;
70 /* *INDENT-ON* */
71 
72 /*
73  Helper macro for declaring rewrite string w/ given max-size.
74 
75  Typical usage:
76  typedef struct {
77  //
78  int a, b;
79 
80  // Total adjacency is 64 bytes.
81  vnet_rewrite_declare(64 - 2*sizeof(int)) rw;
82  } my_adjacency_t;
83 */
84 #define vnet_declare_rewrite(total_bytes) \
85 struct { \
86  vnet_rewrite_header_t rewrite_header; \
87  \
88  u8 rewrite_data[(total_bytes) - sizeof (vnet_rewrite_header_t)]; \
89 }
90 
91 always_inline void
92 vnet_rewrite_clear_data_internal (vnet_rewrite_header_t * rw, int max_size)
93 {
94  /* Sanity check values carefully for this memset operation */
95  ASSERT ((max_size > 0) && (max_size < VLIB_BUFFER_PRE_DATA_SIZE));
96 
97  rw->data_bytes = 0;
98  memset (rw->data, 0xfe, max_size);
99 }
100 
101 always_inline void
102 vnet_rewrite_set_data_internal (vnet_rewrite_header_t * rw,
103  int max_size, void *data, int data_bytes)
104 {
105  /* Sanity check values carefully for this memset operation */
106  ASSERT ((max_size > 0) && (max_size < VLIB_BUFFER_PRE_DATA_SIZE));
107  ASSERT ((data_bytes >= 0) && (data_bytes < max_size));
108 
109  rw->data_bytes = data_bytes;
110  clib_memcpy (rw->data + max_size - data_bytes, data, data_bytes);
111  memset (rw->data, 0xfe, max_size - data_bytes);
112 }
113 
114 #define vnet_rewrite_set_data(rw,data,data_bytes) \
115  vnet_rewrite_set_data_internal (&((rw).rewrite_header), \
116  sizeof ((rw).rewrite_data), \
117  (data), \
118  (data_bytes))
119 
120 always_inline void *
121 vnet_rewrite_get_data_internal (vnet_rewrite_header_t * rw, int max_size)
122 {
123  ASSERT (rw->data_bytes <= max_size);
124  return rw->data + max_size - rw->data_bytes;
125 }
126 
127 #define vnet_rewrite_get_data(rw) \
128  vnet_rewrite_get_data_internal (&((rw).rewrite_header), sizeof ((rw).rewrite_data))
129 
130 always_inline void
131 vnet_rewrite_copy_one (vnet_rewrite_data_t * p0, vnet_rewrite_data_t * rw0,
132  int i)
133 {
134  p0[-i] = rw0[-i];
135 }
136 
137 void vnet_rewrite_copy_slow_path (vnet_rewrite_data_t * p0,
138  vnet_rewrite_data_t * rw0,
139  word n_left, uword most_likely_size);
140 
141 /* *INDENT-OFF* */
142 typedef CLIB_PACKED (struct {
143  u64 a;
144  u32 b;
145  u16 c;
146 }) eh_copy_t;
147 /* *INDENT-ON* */
148 
149 always_inline void
150 _vnet_rewrite_one_header (vnet_rewrite_header_t * h0,
151  void *packet0, int max_size, int most_likely_size)
152 {
153  vnet_rewrite_data_t *p0 = packet0;
154  vnet_rewrite_data_t *rw0 = (vnet_rewrite_data_t *) (h0->data + max_size);
155  word n_left0;
156 
157  /* 0xfefe => poisoned adjacency => crash */
158  ASSERT (h0->data_bytes != 0xfefe);
159 
160  if (PREDICT_TRUE (h0->data_bytes == sizeof (eh_copy_t)))
161  {
162  eh_copy_t *s, *d;
163  s = (eh_copy_t *) (h0->data + max_size - sizeof (eh_copy_t));
164  d = (eh_copy_t *) (((u8 *) packet0) - sizeof (eh_copy_t));
165  clib_memcpy (d, s, sizeof (eh_copy_t));
166  return;
167  }
168 
169 
170 #define _(i) \
171  do { \
172  if (most_likely_size > ((i)-1)*sizeof (vnet_rewrite_data_t)) \
173  vnet_rewrite_copy_one (p0, rw0, (i)); \
174  } while (0)
175 
176  _(4);
177  _(3);
178  _(2);
179  _(1);
180 
181 #undef _
182 
183  n_left0 = (int)
184  (((int) h0->data_bytes - most_likely_size) + (sizeof (rw0[0]) - 1))
185  / (int) sizeof (rw0[0]);
186  if (PREDICT_FALSE (n_left0 > 0))
187  vnet_rewrite_copy_slow_path (p0, rw0, n_left0, most_likely_size);
188 }
189 
190 always_inline void
191 _vnet_rewrite_two_headers (vnet_rewrite_header_t * h0,
192  vnet_rewrite_header_t * h1,
193  void *packet0,
194  void *packet1, int max_size, int most_likely_size)
195 {
196  vnet_rewrite_data_t *p0 = packet0;
197  vnet_rewrite_data_t *p1 = packet1;
198  vnet_rewrite_data_t *rw0 = (vnet_rewrite_data_t *) (h0->data + max_size);
199  vnet_rewrite_data_t *rw1 = (vnet_rewrite_data_t *) (h1->data + max_size);
200  word n_left0, n_left1;
201  int slow_path;
202 
203  /* 0xfefe => poisoned adjacency => crash */
204  ASSERT (h0->data_bytes != 0xfefe);
205  ASSERT (h1->data_bytes != 0xfefe);
206 
207  /* Arithmetic calculation: bytes0 == bytes1 == 14 */
208  slow_path = h0->data_bytes ^ h1->data_bytes;
209  slow_path += h0->data_bytes ^ sizeof (eh_copy_t);
210 
211  if (PREDICT_TRUE (slow_path == 0))
212  {
213  eh_copy_t *s0, *d0, *s1, *d1;
214  s0 = (eh_copy_t *) (h0->data + max_size - sizeof (eh_copy_t));
215  d0 = (eh_copy_t *) (((u8 *) packet0) - sizeof (eh_copy_t));
216  clib_memcpy (d0, s0, sizeof (eh_copy_t));
217  s1 = (eh_copy_t *) (h1->data + max_size - sizeof (eh_copy_t));
218  d1 = (eh_copy_t *) (((u8 *) packet1) - sizeof (eh_copy_t));
219  clib_memcpy (d1, s1, sizeof (eh_copy_t));
220  return;
221  }
222 
223 #define _(i) \
224  do { \
225  if (most_likely_size > ((i)-1)*sizeof (vnet_rewrite_data_t)) \
226  { \
227  vnet_rewrite_copy_one (p0, rw0, (i)); \
228  vnet_rewrite_copy_one (p1, rw1, (i)); \
229  } \
230  } while (0)
231 
232  _(4);
233  _(3);
234  _(2);
235  _(1);
236 
237 #undef _
238 
239  n_left0 = (int)
240  (((int) h0->data_bytes - most_likely_size) + (sizeof (rw0[0]) - 1))
241  / (int) sizeof (rw0[0]);
242  n_left1 = (int)
243  (((int) h1->data_bytes - most_likely_size) + (sizeof (rw1[0]) - 1))
244  / (int) sizeof (rw1[0]);
245 
246  if (PREDICT_FALSE (n_left0 > 0 || n_left1 > 0))
247  {
248  vnet_rewrite_copy_slow_path (p0, rw0, n_left0, most_likely_size);
249  vnet_rewrite_copy_slow_path (p1, rw1, n_left1, most_likely_size);
250  }
251 }
252 
253 #define vnet_rewrite_one_header(rw0,p0,most_likely_size) \
254  _vnet_rewrite_one_header (&((rw0).rewrite_header), (p0), \
255  sizeof ((rw0).rewrite_data), \
256  (most_likely_size))
257 
258 #define vnet_rewrite_two_headers(rw0,rw1,p0,p1,most_likely_size) \
259  _vnet_rewrite_two_headers (&((rw0).rewrite_header), &((rw1).rewrite_header), \
260  (p0), (p1), \
261  sizeof ((rw0).rewrite_data), \
262  (most_likely_size))
263 
264 #define VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST ((void *) 0)
265 /** Deprecated */
267  vnet_link_t packet_type,
268  u32 sw_if_index,
269  u32 node_index,
270  void *dst_address,
271  vnet_rewrite_header_t * rw,
272  u32 max_rewrite_bytes);
273 
275  u32 sw_if_index);
276 
277 void vnet_rewrite_init (struct vnet_main_t *vnm,
278  u32 sw_if_index,
279  u32 this_node,
280  u32 next_node, vnet_rewrite_header_t * rw);
281 
283  u32 sw_if_index,
284  vnet_link_t packet_type,
285  const void *dst_address);
287  u32 sw_if_index, u32 ai);
288 
289 /* Parser for unformat header & rewrite string. */
291 
294 
296 
297 #endif /* included_vnet_rewrite_h */
298 
299 /*
300  * fd.io coding-style-patch-verification: ON
301  *
302  * Local Variables:
303  * eval: (c-set-style "gnu")
304  * End:
305  */
u8 * vnet_build_rewrite_for_sw_interface(struct vnet_main_t *vnm, u32 sw_if_index, vnet_link_t packet_type, const void *dst_address)
Definition: rewrite.c:297
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
uword( unformat_function_t)(unformat_input_t *input, va_list *args)
Definition: format.h:231
void vnet_update_adjacency_for_sw_interface(struct vnet_main_t *vnm, u32 sw_if_index, u32 ai)
Definition: rewrite.c:312
a
Definition: bitmap.h:516
serialize_function_t unserialize_vnet_rewrite
Definition: rewrite.h:295
#define PREDICT_TRUE(x)
Definition: clib.h:98
uword vnet_rewrite_data_t
Definition: rewrite.h:47
void vnet_rewrite_init(struct vnet_main_t *vnm, u32 sw_if_index, u32 this_node, u32 next_node, vnet_rewrite_header_t *rw)
Definition: rewrite.c:195
#define always_inline
Definition: clib.h:84
static void vnet_rewrite_clear_data_internal(vnet_rewrite_header_t *rw, int max_size)
Definition: rewrite.h:92
static void vnet_rewrite_copy_one(vnet_rewrite_data_t *p0, vnet_rewrite_data_t *rw0, int i)
Definition: rewrite.h:131
unsigned long u64
Definition: types.h:89
format_function_t format_vnet_rewrite
Definition: rewrite.h:292
#define VLIB_BUFFER_PRE_DATA_SIZE
Definition: buffer.h:52
serialize_function_t serialize_vnet_rewrite
Definition: rewrite.h:295
static void * vnet_rewrite_get_data_internal(vnet_rewrite_header_t *rw, int max_size)
Definition: rewrite.h:121
#define PREDICT_FALSE(x)
Definition: clib.h:97
void vnet_rewrite_copy_slow_path(vnet_rewrite_data_t *p0, vnet_rewrite_data_t *rw0, word n_left, uword most_likely_size)
Definition: rewrite.c:44
unformat_function_t unformat_vnet_rewrite
Definition: rewrite.h:290
svmdb_client_t * c
typedef CLIB_PACKED(struct{u32 sw_if_index;u32 node_index;u16 next_index;u16 data_bytes;u16 max_l3_packet_bytes;u8 data[0];}) vnet_rewrite_header_t
u32 vnet_tx_node_index_for_sw_interface(struct vnet_main_t *vnm, u32 sw_if_index)
Definition: rewrite.c:188
static void vnet_rewrite_set_data_internal(vnet_rewrite_header_t *rw, int max_size, void *data, int data_bytes)
Definition: rewrite.h:102
#define clib_memcpy(a, b, c)
Definition: string.h:69
format_function_t format_vnet_rewrite_header
Definition: rewrite.h:293
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
enum vnet_link_t_ vnet_link_t
Link Type: A description of the protocol of packets on the link.
u8 *( format_function_t)(u8 *s, va_list *args)
Definition: format.h:48
void vnet_rewrite_for_sw_interface(struct vnet_main_t *vnm, vnet_link_t packet_type, u32 sw_if_index, u32 node_index, void *dst_address, vnet_rewrite_header_t *rw, u32 max_rewrite_bytes)
Deprecated.
Definition: rewrite.c:207
u64 uword
Definition: types.h:112
unsigned short u16
Definition: types.h:57
i64 word
Definition: types.h:111
void( serialize_function_t)(serialize_main_t *m, va_list *va)
Definition: serialize.h:168
unsigned char u8
Definition: types.h:56
static never_inline u32 slow_path(vlib_main_t *vm, u32 bi, vlib_buffer_t *b, u32 n_left_to_tx, u32 *to_tx, u32 *n_slow_bytes_result)