Line data Source code
1 : /*
2 : * l2_uu_fwd.c : Foward unknown unicast packets to BD's configured interface
3 : *
4 : * Copyright (c) 2018 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 : #include <vnet/l2/l2_bd.h>
19 : #include <vnet/l2/l2_input.h>
20 :
21 : #define foreach_l2_uu_fwd_error \
22 : _(L2_UU_FWD, "L2 UU fwd")
23 :
24 : typedef enum
25 : {
26 : #define _(sym,str) L2_UU_FWD_ERROR_##sym,
27 : foreach_l2_uu_fwd_error
28 : #undef _
29 : L2_UU_FWD_N_ERROR,
30 : } l2_uu_fwd_error_t;
31 :
32 : static char *l2_uu_fwd_error_strings[] = {
33 : #define _(sym,string) string,
34 : foreach_l2_uu_fwd_error
35 : #undef _
36 : };
37 :
38 : typedef enum
39 : {
40 : L2_UU_FWD_NEXT_DROP,
41 : L2_UU_FWD_NEXT_L2_OUTPUT,
42 : L2_UU_FWD_N_NEXT,
43 : } l2_uu_fwd_next_t;
44 :
45 : typedef struct
46 : {
47 : u32 sw_if_index;
48 : } l2_uu_fwd_trace_t;
49 :
50 : /* packet trace format function */
51 : static u8 *
52 0 : format_l2_uu_fwd_trace (u8 * s, va_list * args)
53 : {
54 0 : CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
55 0 : CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
56 0 : l2_uu_fwd_trace_t *t = va_arg (*args, l2_uu_fwd_trace_t *);
57 :
58 0 : s = format (s, "l2-uu-fwd: sw_if_index %d", t->sw_if_index);
59 0 : return s;
60 : }
61 :
62 2302 : VLIB_NODE_FN (l2_uu_fwd_node) (vlib_main_t * vm,
63 : vlib_node_runtime_t * node,
64 : vlib_frame_t * frame)
65 : {
66 : u32 n_left_from, *from, *to_next;
67 : l2_uu_fwd_next_t next_index;
68 :
69 2 : from = vlib_frame_vector_args (frame);
70 2 : n_left_from = frame->n_vectors;
71 2 : next_index = node->cached_next_index;
72 :
73 4 : while (n_left_from > 0)
74 : {
75 : u32 n_left_to_next;
76 :
77 2 : vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
78 :
79 32 : while (n_left_from >= 8 && n_left_to_next >= 4)
80 : {
81 : const l2_bridge_domain_t *bdc0, *bdc1, *bdc2, *bdc3;
82 : l2_uu_fwd_next_t next0, next1, next2, next3;
83 : vlib_buffer_t *b0, *b1, *b2, *b3;
84 : u32 bi0, bi1, bi2, bi3;
85 :
86 : {
87 : vlib_buffer_t *b4, *b5, *b6, *b7;
88 :
89 30 : b4 = vlib_get_buffer (vm, from[4]);
90 30 : b5 = vlib_get_buffer (vm, from[5]);
91 30 : b6 = vlib_get_buffer (vm, from[6]);
92 30 : b7 = vlib_get_buffer (vm, from[7]);
93 :
94 30 : vlib_prefetch_buffer_header (b4, STORE);
95 30 : vlib_prefetch_buffer_header (b5, STORE);
96 30 : vlib_prefetch_buffer_header (b6, STORE);
97 30 : vlib_prefetch_buffer_header (b7, STORE);
98 : }
99 30 : bi0 = to_next[0] = from[0];
100 30 : bi1 = to_next[1] = from[1];
101 30 : bi2 = to_next[2] = from[2];
102 30 : bi3 = to_next[3] = from[3];
103 :
104 30 : from += 4;
105 30 : to_next += 4;
106 30 : n_left_from -= 4;
107 30 : n_left_to_next -= 4;
108 :
109 30 : next3 = next2 = next1 = next0 = L2_UU_FWD_NEXT_L2_OUTPUT;
110 :
111 30 : b0 = vlib_get_buffer (vm, bi0);
112 30 : b1 = vlib_get_buffer (vm, bi1);
113 30 : b2 = vlib_get_buffer (vm, bi2);
114 30 : b3 = vlib_get_buffer (vm, bi3);
115 :
116 30 : bdc0 = vec_elt_at_index (l2input_main.bd_configs,
117 : vnet_buffer (b0)->l2.bd_index);
118 30 : bdc1 = vec_elt_at_index (l2input_main.bd_configs,
119 : vnet_buffer (b1)->l2.bd_index);
120 30 : bdc2 = vec_elt_at_index (l2input_main.bd_configs,
121 : vnet_buffer (b2)->l2.bd_index);
122 30 : bdc3 = vec_elt_at_index (l2input_main.bd_configs,
123 : vnet_buffer (b3)->l2.bd_index);
124 :
125 30 : ASSERT (~0 != bdc0->uu_fwd_sw_if_index);
126 :
127 30 : vnet_buffer (b0)->sw_if_index[VLIB_TX] = bdc0->uu_fwd_sw_if_index;
128 30 : vnet_buffer (b1)->sw_if_index[VLIB_TX] = bdc1->uu_fwd_sw_if_index;
129 30 : vnet_buffer (b2)->sw_if_index[VLIB_TX] = bdc2->uu_fwd_sw_if_index;
130 30 : vnet_buffer (b3)->sw_if_index[VLIB_TX] = bdc3->uu_fwd_sw_if_index;
131 :
132 30 : if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
133 : (b0->flags & VLIB_BUFFER_IS_TRACED)))
134 : {
135 : l2_uu_fwd_trace_t *t;
136 :
137 30 : t = vlib_add_trace (vm, node, b0, sizeof (*t));
138 30 : t->sw_if_index = bdc0->uu_fwd_sw_if_index;
139 : }
140 30 : if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
141 : (b1->flags & VLIB_BUFFER_IS_TRACED)))
142 : {
143 : l2_uu_fwd_trace_t *t;
144 :
145 30 : t = vlib_add_trace (vm, node, b1, sizeof (*t));
146 30 : t->sw_if_index = bdc1->uu_fwd_sw_if_index;
147 : }
148 30 : if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
149 : (b1->flags & VLIB_BUFFER_IS_TRACED)))
150 : {
151 : l2_uu_fwd_trace_t *t;
152 :
153 30 : t = vlib_add_trace (vm, node, b2, sizeof (*t));
154 30 : t->sw_if_index = bdc2->uu_fwd_sw_if_index;
155 : }
156 30 : if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
157 : (b1->flags & VLIB_BUFFER_IS_TRACED)))
158 : {
159 : l2_uu_fwd_trace_t *t;
160 :
161 30 : t = vlib_add_trace (vm, node, b3, sizeof (*t));
162 30 : t->sw_if_index = bdc3->uu_fwd_sw_if_index;
163 : }
164 30 : vlib_validate_buffer_enqueue_x4 (vm, node, next_index,
165 : to_next, n_left_to_next,
166 : bi0, bi1, bi2, bi3,
167 : next0, next1, next2, next3);
168 : }
169 :
170 16 : while (n_left_from > 0 && n_left_to_next > 0)
171 : {
172 : const l2_bridge_domain_t *bdc0;
173 : l2_uu_fwd_next_t next0;
174 : vlib_buffer_t *b0;
175 : u32 bi0;
176 :
177 14 : bi0 = from[0];
178 14 : to_next[0] = bi0;
179 14 : from += 1;
180 14 : to_next += 1;
181 14 : n_left_from -= 1;
182 14 : n_left_to_next -= 1;
183 14 : next0 = L2_UU_FWD_NEXT_L2_OUTPUT;
184 14 : b0 = vlib_get_buffer (vm, bi0);
185 :
186 14 : bdc0 = vec_elt_at_index (l2input_main.bd_configs,
187 : vnet_buffer (b0)->l2.bd_index);
188 14 : ASSERT (~0 != bdc0->uu_fwd_sw_if_index);
189 :
190 14 : vnet_buffer (b0)->sw_if_index[VLIB_TX] = bdc0->uu_fwd_sw_if_index;
191 :
192 14 : if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
193 : (b0->flags & VLIB_BUFFER_IS_TRACED)))
194 : {
195 : l2_uu_fwd_trace_t *t;
196 :
197 14 : t = vlib_add_trace (vm, node, b0, sizeof (*t));
198 14 : t->sw_if_index = bdc0->uu_fwd_sw_if_index;
199 : }
200 14 : vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
201 : to_next, n_left_to_next,
202 : bi0, next0);
203 : }
204 :
205 2 : vlib_put_next_frame (vm, node, next_index, n_left_to_next);
206 : }
207 :
208 2 : vlib_node_increment_counter (vm, node->node_index,
209 2 : L2_UU_FWD_ERROR_L2_UU_FWD, frame->n_vectors);
210 :
211 2 : return frame->n_vectors;
212 : }
213 :
214 : /* *INDENT-OFF* */
215 183788 : VLIB_REGISTER_NODE (l2_uu_fwd_node) = {
216 : .name = "l2-uu-fwd",
217 : .vector_size = sizeof (u32),
218 : .format_trace = format_l2_uu_fwd_trace,
219 : .type = VLIB_NODE_TYPE_INTERNAL,
220 :
221 : .n_errors = ARRAY_LEN(l2_uu_fwd_error_strings),
222 : .error_strings = l2_uu_fwd_error_strings,
223 :
224 : .n_next_nodes = L2_UU_FWD_N_NEXT,
225 :
226 : .next_nodes = {
227 : [L2_UU_FWD_NEXT_DROP] = "error-drop",
228 : [L2_UU_FWD_NEXT_L2_OUTPUT] = "l2-output",
229 : },
230 : };
231 : /* *INDENT-ON* */
232 :
233 : /*
234 : * fd.io coding-style-patch-verification: ON
235 : *
236 : * Local Variables:
237 : * eval: (c-set-style "gnu")
238 : * End:
239 : */
|