Line data Source code
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 : * pg_edit.c: packet generator edits
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/pg/pg.h>
42 :
43 : static void
44 51 : pg_edit_set_value_helper (pg_edit_t * e, u64 value, u8 * result)
45 : {
46 : int i, j, n_bits_left;
47 : u8 *v, tmp[8];
48 :
49 51 : v = tmp;
50 :
51 51 : n_bits_left = e->n_bits;
52 51 : i = 0;
53 51 : j = e->lsb_bit_offset % BITS (v[0]);
54 :
55 51 : if (n_bits_left > 0 && j != 0)
56 : {
57 18 : v[i] = (value & 0xff) << j;
58 18 : value >>= BITS (v[0]) - j;
59 18 : n_bits_left -= BITS (v[0]) - j;
60 18 : i += 1;
61 : }
62 :
63 109 : while (n_bits_left > 0)
64 : {
65 58 : v[i] = value & 0xff;
66 58 : value >>= 8;
67 58 : n_bits_left -= 8;
68 58 : i += 1;
69 : }
70 :
71 : /* Convert to network byte order. */
72 127 : for (j = 0; j < i; j++)
73 76 : result[j] = v[i - 1 - j];
74 51 : }
75 :
76 : void
77 45 : pg_edit_set_value (pg_edit_t * e, int hi_or_lo, u64 value)
78 : {
79 45 : pg_edit_alloc_value (e, hi_or_lo);
80 45 : pg_edit_set_value_helper (e, value, e->values[hi_or_lo]);
81 45 : }
82 :
83 : /* Parse an int either %d or 0x%x into network byte order. */
84 : uword
85 6 : unformat_pg_number (unformat_input_t * input, va_list * args)
86 : {
87 6 : u8 *result = va_arg (*args, u8 *);
88 6 : pg_edit_t *e = va_arg (*args, pg_edit_t *);
89 : u64 value;
90 :
91 6 : ASSERT (BITS (value) >= e->n_bits);
92 :
93 6 : if (!unformat (input, "0x%X", sizeof (value), &value)
94 6 : && !unformat (input, "%D", sizeof (value), &value))
95 0 : return 0;
96 :
97 : /* Number given does not fit into bit field. */
98 6 : if (e->n_bits < 64 && value >= (u64) 1 << (u64) e->n_bits)
99 0 : return 0;
100 :
101 6 : pg_edit_set_value_helper (e, value, result);
102 6 : return 1;
103 : }
104 :
105 : uword
106 52 : unformat_pg_edit (unformat_input_t * input, va_list * args)
107 : {
108 52 : unformat_function_t *f = va_arg (*args, unformat_function_t *);
109 52 : pg_edit_t *e = va_arg (*args, pg_edit_t *);
110 :
111 52 : pg_edit_alloc_value (e, PG_EDIT_LO);
112 52 : if (!unformat_user (input, f, e->values[PG_EDIT_LO], e))
113 0 : return 0;
114 :
115 52 : pg_edit_alloc_value (e, PG_EDIT_HI);
116 52 : if (unformat (input, "-%U", f, e->values[PG_EDIT_HI], e))
117 1 : e->type = PG_EDIT_INCREMENT;
118 51 : else if (unformat (input, "+%U", f, e->values[PG_EDIT_HI], e))
119 0 : e->type = PG_EDIT_RANDOM;
120 : else
121 51 : e->type = PG_EDIT_FIXED;
122 :
123 52 : return 1;
124 : }
125 :
126 : uword
127 6 : unformat_pg_payload (unformat_input_t * input, va_list * args)
128 : {
129 6 : pg_stream_t *s = va_arg (*args, pg_stream_t *);
130 6 : vlib_main_t *vm = vlib_get_main ();
131 : pg_edit_t *e;
132 : u32 i, node_index, len, max_len;
133 : u8 *v;
134 :
135 6 : v = 0;
136 :
137 6 : if (unformat (input, "incrementing %d", &len))
138 : {
139 6 : vec_resize (v, len);
140 538 : for (i = 0; i < len; i++)
141 532 : v[i] = i % len;
142 : }
143 0 : else if (unformat (input, "hex 0x%U", unformat_hex_string, &v))
144 : ;
145 0 : else if (unformat (input, "%U", unformat_vlib_node, vm, &node_index))
146 : {
147 0 : pg_node_t *pn = pg_get_node (node_index);
148 0 : if (!pn->unformat_edit)
149 0 : return 0;
150 0 : return unformat (input, "%U", pn->unformat_edit, s);
151 : }
152 :
153 : else
154 0 : return 0;
155 :
156 : /* Length not including this payload. */
157 6 : max_len = pg_edit_group_n_bytes (s, 0);
158 :
159 6 : if (max_len >= s->max_packet_bytes)
160 : {
161 : /* no payload */
162 0 : len = 0;
163 : }
164 : else
165 : {
166 : /* make a bigger v to hold the data */
167 6 : len = s->max_packet_bytes - max_len;
168 : }
169 :
170 6 : vec_resize (v, len);
171 :
172 6 : e = pg_create_edit_group (s, sizeof (e[0]), len, 0);
173 :
174 6 : e->type = PG_EDIT_FIXED;
175 6 : e->n_bits = len * BITS (v[0]);
176 :
177 : /* Least significant bit is at end of bitstream, since everything is always bigendian. */
178 6 : e->lsb_bit_offset = len > 0 ? e->n_bits - BITS (v[0]) : 0;
179 :
180 6 : e->values[PG_EDIT_LO] = v;
181 :
182 6 : return 1;
183 : }
184 :
185 : /*
186 : * fd.io coding-style-patch-verification: ON
187 : *
188 : * Local Variables:
189 : * eval: (c-set-style "gnu")
190 : * End:
191 : */
|