FD.io VPP  v16.09
Vector Packet Processing
rewrite.c
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.c: 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 #include <vnet/vnet.h>
41 #include <vnet/ip/lookup.h>
42 
43 void
45  vnet_rewrite_data_t * rw0,
46  word n_left, uword most_likely_size)
47 {
48  uword n_done =
49  round_pow2 (most_likely_size, sizeof (rw0[0])) / sizeof (rw0[0]);
50 
51  p0 -= n_done;
52  rw0 -= n_done;
53 
54  /* As we enter the cleanup loop, p0 and rw0 point to the last chunk written
55  by the fast path. Hence, the constant 1, which the
56  vnet_rewrite_copy_one macro renders as p0[-1] = rw0[-1]. */
57 
58  while (n_left > 0)
59  {
60  vnet_rewrite_copy_one (p0, rw0, 1);
61  p0--;
62  rw0--;
63  n_left--;
64  }
65 }
66 
67 u8 *
68 format_vnet_rewrite (u8 * s, va_list * args)
69 {
70  vlib_main_t *vm = va_arg (*args, vlib_main_t *);
71  vnet_rewrite_header_t *rw = va_arg (*args, vnet_rewrite_header_t *);
72  u32 max_data_bytes = va_arg (*args, u32);
73  vnet_main_t *vnm = vnet_get_main ();
74  vlib_node_t *next;
75  uword indent;
76 
77  next = vlib_get_next_node (vm, rw->node_index, rw->next_index);
78 
79  indent = format_get_indent (s);
80 
81  if (rw->sw_if_index != ~0)
82  {
84  si = vnet_get_sw_interface (vnm, rw->sw_if_index);
85  s = format (s, "%U", format_vnet_sw_interface_name, vnm, si);
86  }
87  else
88  s = format (s, "%v", next->name);
89 
90  /* Format rewrite string. */
91  if (rw->data_bytes > 0)
92  s = format (s, "\n%U%U",
93  format_white_space, indent,
95  rw->data + max_data_bytes - rw->data_bytes, rw->data_bytes);
96 
97  return s;
98 }
99 
100 u8 *
101 format_vnet_rewrite_header (u8 * s, va_list * args)
102 {
103  vlib_main_t *vm = va_arg (*args, vlib_main_t *);
104  vnet_rewrite_header_t *rw = va_arg (*args, vnet_rewrite_header_t *);
105  u8 *packet_data = va_arg (*args, u8 *);
106  u32 packet_data_bytes = va_arg (*args, u32);
107  vlib_node_t *next;
108 
109  next = vlib_get_next_node (vm, rw->node_index, rw->next_index);
110 
111  /* Format rewrite string. */
112  s = format (s, "%U",
114  packet_data, packet_data_bytes);
115 
116  return s;
117 }
118 
119 uword
120 unformat_vnet_rewrite (unformat_input_t * input, va_list * args)
121 {
122  vlib_main_t *vm = va_arg (*args, vlib_main_t *);
123  vnet_rewrite_header_t *rw = va_arg (*args, vnet_rewrite_header_t *);
124  u32 max_data_bytes = va_arg (*args, u32);
125  vnet_main_t *vnm = vnet_get_main ();
126  vlib_node_t *next;
127  u32 next_index, sw_if_index, max_packet_bytes, error;
128  u8 *rw_data;
129 
130  rw_data = 0;
131  sw_if_index = ~0;
132  max_packet_bytes = ~0;
133  error = 1;
134 
135  /* Parse sw interface. */
136  if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
137  {
139 
140  hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
141 
142  next_index = hi->output_node_index;
143  max_packet_bytes = hi->max_l3_packet_bytes[VLIB_RX];
144  }
145 
146  else if (unformat (input, "%U", unformat_vlib_node, vm, &next_index))
147  ;
148 
149  else
150  goto done;
151 
152  next = vlib_get_node (vm, next_index);
153 
154  if (next->unformat_buffer
155  && unformat_user (input, next->unformat_buffer, &rw_data))
156  ;
157 
158  else if (unformat_user (input, unformat_hex_string, &rw_data)
159  || unformat (input, "0x%U", unformat_hex_string, &rw_data))
160  ;
161 
162  else
163  goto done;
164 
165  /* Re-write does not fit. */
166  if (vec_len (rw_data) >= max_data_bytes)
167  goto done;
168 
169  {
170  u32 tmp;
171 
172  if (unformat (input, "mtu %d", &tmp)
173  && tmp < (1 << BITS (rw->max_l3_packet_bytes)))
174  max_packet_bytes = tmp;
175  }
176 
177  error = 0;
178  rw->sw_if_index = sw_if_index;
179  rw->max_l3_packet_bytes = max_packet_bytes;
180  rw->next_index = vlib_node_add_next (vm, rw->node_index, next_index);
181  vnet_rewrite_set_data_internal (rw, max_data_bytes, rw_data,
182  vec_len (rw_data));
183 
184 done:
185  vec_free (rw_data);
186  return error == 0;
187 }
188 
189 void
191  vnet_l3_packet_type_t packet_type,
192  u32 sw_if_index,
193  u32 node_index,
194  void *dst_address,
195  vnet_rewrite_header_t * rw,
196  u32 max_rewrite_bytes)
197 {
198  vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
201  static u8 *rw_tmp = 0;
202  uword n_rw_tmp;
203 
204  rw->sw_if_index = sw_if_index;
205  rw->node_index = node_index;
206  rw->next_index =
207  vlib_node_add_next (vnm->vlib_main, node_index, hw->output_node_index);
208  rw->max_l3_packet_bytes = hw->max_l3_packet_bytes[VLIB_TX];
209 
210  ASSERT (max_rewrite_bytes > 0);
211  vec_reset_length (rw_tmp);
212  vec_validate (rw_tmp, max_rewrite_bytes - 1);
213 
214  ASSERT (hc->set_rewrite);
215  n_rw_tmp =
216  hc->set_rewrite (vnm, sw_if_index, packet_type, dst_address, rw_tmp,
217  max_rewrite_bytes);
218 
219  ASSERT (n_rw_tmp < max_rewrite_bytes);
220  vnet_rewrite_set_data_internal (rw, max_rewrite_bytes, rw_tmp, n_rw_tmp);
221 }
222 
223 void
225  u32 tx_sw_if_index,
226  u32 rewrite_node_index,
227  u32 post_rewrite_node_index,
228  vnet_rewrite_header_t * rw,
229  u8 * rewrite_data, u32 rewrite_length)
230 {
231  ip_adjacency_t *adj = 0;
232  /*
233  * Installed into vnet_buffer(b)->sw_if_index[VLIB_TX] e.g.
234  * by ip4_rewrite_inline. If the post-rewrite node injects into
235  * ipX-forward, this will be interpreted as a FIB number.
236  */
237  rw->sw_if_index = tx_sw_if_index;
238  rw->node_index = rewrite_node_index;
239  rw->next_index = vlib_node_add_next (vnm->vlib_main, rewrite_node_index,
240  post_rewrite_node_index);
241  rw->max_l3_packet_bytes = (u16) ~ 0; /* we can't know at this point */
242 
243  ASSERT (rewrite_length < sizeof (adj->rewrite_data));
244  /* Leave room for ethernet + VLAN tag */
245  vnet_rewrite_set_data_internal (rw, sizeof (adj->rewrite_data),
246  rewrite_data, rewrite_length);
247 }
248 
249 void
251 {
252  vnet_rewrite_header_t *rw = va_arg (*va, vnet_rewrite_header_t *);
253  u32 max_data_bytes = va_arg (*va, u32);
254  u8 *p;
255 
256  serialize_integer (m, rw->sw_if_index, sizeof (rw->sw_if_index));
257  serialize_integer (m, rw->data_bytes, sizeof (rw->data_bytes));
258  serialize_integer (m, rw->max_l3_packet_bytes,
259  sizeof (rw->max_l3_packet_bytes));
260  p = serialize_get (m, rw->data_bytes);
261  clib_memcpy (p, vnet_rewrite_get_data_internal (rw, max_data_bytes),
262  rw->data_bytes);
263 }
264 
265 void
267 {
268  vnet_rewrite_header_t *rw = va_arg (*va, vnet_rewrite_header_t *);
269  u32 max_data_bytes = va_arg (*va, u32);
270  u8 *p;
271 
272  /* It is up to user to fill these in. */
273  rw->node_index = ~0;
274  rw->next_index = ~0;
275 
276  unserialize_integer (m, &rw->sw_if_index, sizeof (rw->sw_if_index));
277  unserialize_integer (m, &rw->data_bytes, sizeof (rw->data_bytes));
278  unserialize_integer (m, &rw->max_l3_packet_bytes,
279  sizeof (rw->max_l3_packet_bytes));
280  p = unserialize_get (m, rw->data_bytes);
281  clib_memcpy (vnet_rewrite_get_data_internal (rw, max_data_bytes), p,
282  rw->data_bytes);
283 }
284 
285 /*
286  * fd.io coding-style-patch-verification: ON
287  *
288  * Local Variables:
289  * eval: (c-set-style "gnu")
290  * End:
291  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
vmrglw vmrglh hi
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
IP unicast adjacency.
Definition: lookup.h:164
Definitions for all things IP (v4|v6) unicast and multicast lookup related.
uword vnet_rewrite_data_t
Definition: rewrite.h:47
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
unformat_function_t unformat_vnet_sw_interface
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1061
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
void serialize_vnet_rewrite(serialize_main_t *m, va_list *va)
Definition: rewrite.c:250
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
vnet_l3_packet_type_t
Definition: l3_types.h:44
void unserialize_vnet_rewrite(serialize_main_t *m, va_list *va)
Definition: rewrite.c:266
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
unformat_function_t unformat_hex_string
Definition: format.h:287
static void * serialize_get(serialize_main_t *m, uword n_bytes)
Definition: serialize.h:178
u8 * format_hex_bytes(u8 *s, va_list *va)
Definition: std-formats.c:84
static void vnet_rewrite_copy_one(vnet_rewrite_data_t *p0, vnet_rewrite_data_t *rw0, int i)
Definition: rewrite.h:121
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:977
u8 * format_vnet_rewrite_header(u8 *s, va_list *args)
Definition: rewrite.c:101
format_function_t format_vnet_sw_interface_name
static uword format_get_indent(u8 *s)
Definition: format.h:72
vlib_main_t * vlib_main
Definition: vnet.h:80
uword unformat_vnet_rewrite(unformat_input_t *input, va_list *args)
Definition: rewrite.c:120
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
static void * vnet_rewrite_get_data_internal(vnet_rewrite_header_t *rw, int max_size)
Definition: rewrite.h:111
static void * unserialize_get(serialize_main_t *m, uword n_bytes)
Definition: serialize.h:171
format_function_t * format_buffer
Definition: node.h:311
void vnet_rewrite_for_tunnel(vnet_main_t *vnm, u32 tx_sw_if_index, u32 rewrite_node_index, u32 post_rewrite_node_index, vnet_rewrite_header_t *rw, u8 *rewrite_data, u32 rewrite_length)
Definition: rewrite.c:224
u8 * name
Definition: node.h:221
u8 * format_vnet_rewrite(u8 *s, va_list *args)
Definition: rewrite.c:68
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
void vnet_rewrite_for_sw_interface(vnet_main_t *vnm, vnet_l3_packet_type_t packet_type, u32 sw_if_index, u32 node_index, void *dst_address, vnet_rewrite_header_t *rw, u32 max_rewrite_bytes)
Definition: rewrite.c:190
static void vnet_rewrite_set_data_internal(vnet_rewrite_header_t *rw, int max_size, void *data, int data_bytes)
Definition: rewrite.h:92
#define clib_memcpy(a, b, c)
Definition: string.h:63
unformat_function_t * unformat_buffer
Definition: node.h:312
static void unserialize_integer(serialize_main_t *m, void *x, u32 n_bytes)
Definition: serialize.h:201
static void serialize_integer(serialize_main_t *m, u64 x, u32 n_bytes)
Definition: serialize.h:185
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:272
u32 max_l3_packet_bytes[VLIB_N_RX_TX]
Definition: interface.h:345
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
static vnet_hw_interface_class_t * vnet_get_hw_interface_class(vnet_main_t *vnm, u32 hw_class_index)
u64 uword
Definition: types.h:112
Definition: defs.h:47
static vlib_node_t * vlib_get_next_node(vlib_main_t *vm, u32 node_index, u32 next_index)
Get vlib node by graph arc (next) index.
Definition: node_funcs.h:71
unsigned short u16
Definition: types.h:57
i64 word
Definition: types.h:111
struct _vnet_hw_interface_class vnet_hw_interface_class_t
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
unformat_function_t unformat_vlib_node
Definition: node_funcs.h:1108
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:58
struct _unformat_input_t unformat_input_t
#define BITS(x)
Definition: clib.h:58
Definition: defs.h:46