FD.io VPP  v16.06
Vector Packet Processing
format.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  * ethernet_format.c: ethernet formatting/parsing.
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 <vlib/vlib.h>
41 #include <vnet/ethernet/ethernet.h>
42 
43 u8 * format_ethernet_address (u8 * s, va_list * args)
44 {
46  u8 * a = va_arg (*args, u8 *);
47 
49  return format (s, "%02x%02x.%02x%02x.%02x%02x",
50  a[0], a[1], a[2], a[3], a[4], a[5]);
51  else
52  return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
53  a[0], a[1], a[2], a[3], a[4], a[5]);
54 }
55 
56 u8 * format_ethernet_type (u8 * s, va_list * args)
57 {
58  ethernet_type_t type = va_arg (*args, u32);
61 
62  if (t)
63  s = format (s, "%s", t->name);
64  else
65  s = format (s, "0x%04x", type);
66 
67  return s;
68 }
69 
70 u8 * format_ethernet_header_with_length (u8 * s, va_list * args)
71 {
72  ethernet_max_header_t * m = va_arg (*args, ethernet_max_header_t *);
73  u32 max_header_bytes = va_arg (*args, u32);
75  ethernet_header_t * e = &m->ethernet;
77  ethernet_type_t type = clib_net_to_host_u16 (e->type);
78  u32 n_vlan = 0, i, header_bytes;
79  uword indent;
80 
81  while (type == ETHERNET_TYPE_VLAN
82  && n_vlan < ARRAY_LEN (m->vlan))
83  {
84  v = m->vlan + n_vlan;
85  type = clib_net_to_host_u16 (v->type);
86  n_vlan++;
87  }
88 
89  header_bytes = sizeof (e[0]) + n_vlan * sizeof (v[0]);
90  if (max_header_bytes != 0 && header_bytes > max_header_bytes)
91  return format (s, "ethernet header truncated");
92 
93  indent = format_get_indent (s);
94 
95  s = format (s, "%U: %U -> %U",
99 
100  for (i = 0; i < n_vlan; i++)
101  {
102  u32 v = clib_net_to_host_u16 (m->vlan[i].priority_cfi_and_id);
103  u32 vid = (v & 0xfff);
104  u32 cfi = (v >> 12) & 1;
105  u32 pri = (v >> 13);
106 
107  s = format (s, " vlan %d", vid);
108  if (pri != 0)
109  s = format (s, " priority %d", pri);
110  if (cfi != 0)
111  s = format (s, " cfi");
112  }
113 
114  if (max_header_bytes != 0 && header_bytes < max_header_bytes)
115  {
117  vlib_node_t * node = 0;
118 
119  ti = ethernet_get_type_info (em, type);
120  if (ti && ti->node_index != ~0)
121  node = vlib_get_node (em->vlib_main, ti->node_index);
122  if (node && node->format_buffer)
123  s = format (s, "\n%U%U",
124  format_white_space, indent,
125  node->format_buffer, (void *) m + header_bytes,
126  max_header_bytes - header_bytes);
127  }
128 
129  return s;
130 }
131 
132 u8 * format_ethernet_header (u8 * s, va_list * args)
133 {
134  ethernet_max_header_t * m = va_arg (*args, ethernet_max_header_t *);
135  return format (s, "%U", format_ethernet_header_with_length, m, 0);
136 }
137 
138 /* Parse X:X:X:X:X:X unix style ethernet address. */
139 static uword
141 {
142  u8 * result = va_arg (*args, u8 *);
143  u32 i, a[6];
144 
145  if (! unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
146  &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
147  return 0;
148 
149  /* Check range. */
150  for (i = 0; i < ARRAY_LEN (a); i++)
151  if (a[i] >= (1 << 8))
152  return 0;
153 
154  for (i = 0; i < ARRAY_LEN (a); i++)
155  result[i] = a[i];
156 
157  return 1;
158 }
159 
160 /* Parse X.X.X cisco style ethernet address. */
161 static uword
163 {
164  u8 * result = va_arg (*args, u8 *);
165  u32 i, a[3];
166 
167  if (! unformat (input, "%_%x.%x.%x%_", &a[0], &a[1], &a[2]))
168  return 0;
169 
170  /* Check range. */
171  for (i = 0; i < ARRAY_LEN (a); i++)
172  if (a[i] >= (1 << 16))
173  return 0;
174 
175  result[0] = (a[0] >> 8) & 0xff;
176  result[1] = (a[0] >> 0) & 0xff;
177  result[2] = (a[1] >> 8) & 0xff;
178  result[3] = (a[1] >> 0) & 0xff;
179  result[4] = (a[2] >> 8) & 0xff;
180  result[5] = (a[2] >> 0) & 0xff;
181 
182  return 1;
183 }
184 
185 /* Parse ethernet address; accept either unix or style addresses. */
186 uword
188 {
189  u8 * result = va_arg (*args, u8 *);
190  return (unformat_user (input, unformat_ethernet_address_unix, result)
191  || unformat_user (input, unformat_ethernet_address_cisco, result));
192 }
193 
194 /* Returns ethernet type as an int in host byte order. */
195 uword
197  va_list * args)
198 {
199  u16 * result = va_arg (*args, u16 *);
201  int type, i;
202 
203  /* Numeric type. */
204  if (unformat (input, "0x%x", &type)
205  || unformat (input, "%d", &type))
206  {
207  if (type >= (1 << 16))
208  return 0;
209  *result = type;
210  return 1;
211  }
212 
213  /* Named type. */
215  em->type_info_by_name, &i))
216  {
218  *result = ti->type;
219  return 1;
220  }
221 
222  return 0;
223 }
224 
225 uword
227  va_list * args)
228 {
229  u16 * result = va_arg (*args, u16 *);
231  return 0;
232 
233  *result = clib_host_to_net_u16 ((u16) *result);
234  return 1;
235 }
236 
237 uword
239 {
240  u8 ** result = va_arg (*args, u8 **);
241  ethernet_max_header_t _m, * m = &_m;
242  ethernet_header_t * e = &m->ethernet;
243  u16 type;
244  u32 n_vlan;
245 
246  if (! unformat (input, "%U: %U -> %U",
250  return 0;
251 
252  n_vlan = 0;
253  while (unformat (input, "vlan"))
254  {
255  u32 id, priority;
256 
257  if (! unformat_user (input, unformat_vlib_number, &id)
258  || id >= ETHERNET_N_VLAN)
259  return 0;
260 
261  if (unformat (input, "priority %d", &priority))
262  {
263  if (priority >= 8)
264  return 0;
265  id |= priority << 13;
266  }
267 
268  if (unformat (input, "cfi"))
269  id |= 1 << 12;
270 
271  /* Too many vlans given. */
272  if (n_vlan >= ARRAY_LEN (m->vlan))
273  return 0;
274 
275  m->vlan[n_vlan].priority_cfi_and_id = clib_host_to_net_u16 (id);
276  n_vlan++;
277  }
278 
279  if (n_vlan == 0)
280  e->type = clib_host_to_net_u16 (type);
281  else
282  {
283  int i;
284 
285  e->type = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
286  for (i = 0; i < n_vlan - 1; i++)
287  m->vlan[i].type = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
288  m->vlan[n_vlan - 1].type = clib_host_to_net_u16 (type);
289  }
290 
291  /* Add header to result. */
292  {
293  void * p;
294  u32 n_bytes = sizeof (e[0]) + n_vlan * sizeof (m->vlan[0]);
295 
296  vec_add2 (*result, p, n_bytes);
297  clib_memcpy (p, m, n_bytes);
298  }
299 
300  return 1;
301 }
uword unformat_vlib_number(unformat_input_t *input, va_list *args)
Definition: format.c:130
uword unformat_ethernet_header(unformat_input_t *input, va_list *args)
Definition: format.c:238
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:43
#define ETHERNET_N_VLAN
Definition: packet.h:79
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:942
a
Definition: bitmap.h:393
always_inline ethernet_type_info_t * ethernet_get_type_info(ethernet_main_t *em, ethernet_type_t type)
Definition: ethernet.h:229
vlib_main_t * vlib_main
Definition: ethernet.h:188
always_inline vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Definition: node_funcs.h:46
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
ethernet_type_t
Definition: packet.h:43
u8 src_address[6]
Definition: packet.h:52
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:519
uword * type_info_by_name
Definition: ethernet.h:206
u8 * format_ethernet_header_with_length(u8 *s, va_list *args)
Definition: format.c:70
ethernet_main_t ethernet_main
Definition: ethernet.h:226
u8 dst_address[6]
Definition: packet.h:51
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:107
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
int format_ethernet_address_16bit
Definition: ethernet.h:219
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:953
uword unformat_ethernet_type_net_byte_order(unformat_input_t *input, va_list *args)
Definition: format.c:226
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
Definition: format.c:187
format_function_t * format_buffer
Definition: node.h:277
static uword unformat_ethernet_address_unix(unformat_input_t *input, va_list *args)
Definition: format.c:140
#define clib_memcpy(a, b, c)
Definition: string.h:63
uword unformat_vlib_number_by_name(unformat_input_t *input, va_list *args)
Definition: format.c:139
ethernet_vlan_header_t vlan[2]
Definition: ethernet.h:66
#define ARRAY_LEN(x)
Definition: clib.h:59
u8 * format_ethernet_header(u8 *s, va_list *args)
Definition: format.c:132
unsigned int u32
Definition: types.h:88
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
ethernet_type_t type
Definition: ethernet.h:106
static uword unformat_ethernet_address_cisco(unformat_input_t *input, va_list *args)
Definition: format.c:162
always_inline uword format_get_indent(u8 *s)
Definition: format.h:72
u64 uword
Definition: types.h:112
unsigned short u16
Definition: types.h:57
unsigned char u8
Definition: types.h:56
ethernet_header_t ethernet
Definition: ethernet.h:63
uword unformat_ethernet_type_host_byte_order(unformat_input_t *input, va_list *args)
Definition: format.c:196
struct _unformat_input_t unformat_input_t
u8 * format_ethernet_type(u8 *s, va_list *args)
Definition: format.c:56
ethernet_type_info_t * type_infos
Definition: ethernet.h:203