Line data Source code
1 : /*
2 : * node.c: p2p ethernet vpp node
3 : *
4 : * Copyright (c) 2016 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 <vlib/vlib.h>
19 : #include <vnet/vnet.h>
20 : #include <vppinfra/error.h>
21 :
22 : #include <vnet/ethernet/p2p_ethernet.h>
23 :
24 : #include <vppinfra/error.h>
25 : #include <vppinfra/elog.h>
26 :
27 : extern vlib_node_registration_t p2p_ethernet_input_node;
28 :
29 : /* packet trace format function */
30 : static u8 *
31 0 : format_p2p_ethernet_trace (u8 * s, va_list * args)
32 : {
33 0 : CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
34 0 : CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
35 0 : p2p_ethernet_trace_t *t = va_arg (*args, p2p_ethernet_trace_t *);
36 :
37 0 : vnet_main_t *vnm = &vnet_main;
38 0 : s = format (s, "P2P ethernet: %U -> %U",
39 : format_vnet_sw_if_index_name, vnm, t->sw_if_index,
40 : format_vnet_sw_if_index_name, vnm, t->p2pe_sw_if_index);
41 :
42 0 : return s;
43 : }
44 :
45 : #define foreach_p2p_ethernet_error \
46 : _(HITS, "P2P ethernet incoming packets processed")
47 :
48 : typedef enum
49 : {
50 : #define _(sym,str) P2PE_ERROR_##sym,
51 : foreach_p2p_ethernet_error
52 : #undef _
53 : P2PE_N_ERROR,
54 : } p2p_ethernet_error_t;
55 :
56 : static char *p2p_ethernet_error_strings[] = {
57 : #define _(sym,string) string,
58 : foreach_p2p_ethernet_error
59 : #undef _
60 : };
61 :
62 2307 : VLIB_NODE_FN (p2p_ethernet_input_node) (vlib_main_t * vm,
63 : vlib_node_runtime_t * node,
64 : vlib_frame_t * frame)
65 : {
66 7 : u32 thread_index = vm->thread_index;
67 7 : u32 n_trace = vlib_get_trace_count (vm, node);
68 : u32 n_left_from, *from, *to_next;
69 : u32 next_index;
70 7 : u32 n_p2p_ethernet_packets = 0;
71 7 : vlib_combined_counter_main_t *cm =
72 7 : vnet_get_main ()->interface_main.combined_sw_if_counters;
73 :
74 7 : from = vlib_frame_vector_args (frame);
75 7 : n_left_from = frame->n_vectors;
76 7 : next_index = node->cached_next_index;
77 :
78 14 : while (n_left_from > 0)
79 : {
80 : u32 n_left_to_next;
81 :
82 7 : vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
83 :
84 7 : while (n_left_from >= 4 && n_left_to_next >= 2)
85 : {
86 : u32 bi0, bi1;
87 : vlib_buffer_t *b0, *b1;
88 0 : u32 next0 = 0, next1 = 0;
89 : u32 sw_if_index0, sw_if_index1;
90 : ethernet_header_t *en0, *en1;
91 : u32 rx0, rx1;
92 :
93 0 : bi0 = from[0];
94 0 : bi1 = from[1];
95 0 : to_next[0] = bi0;
96 0 : to_next[1] = bi1;
97 0 : from += 2;
98 0 : to_next += 2;
99 0 : n_left_to_next -= 2;
100 0 : n_left_from -= 2;
101 :
102 0 : b0 = vlib_get_buffer (vm, bi0);
103 0 : b1 = vlib_get_buffer (vm, bi1);
104 :
105 0 : en0 = vlib_buffer_get_current (b0);
106 0 : sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
107 0 : en1 = vlib_buffer_get_current (b1);
108 0 : sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
109 :
110 0 : vnet_feature_next (&next0, b0);
111 0 : vnet_feature_next (&next1, b1);
112 :
113 0 : rx0 = p2p_ethernet_lookup (sw_if_index0, en0->src_address);
114 0 : rx1 = p2p_ethernet_lookup (sw_if_index1, en1->src_address);
115 :
116 0 : if (rx0 != ~0)
117 : {
118 : /* Send pkt to p2p_ethernet RX interface */
119 0 : vnet_buffer (b0)->sw_if_index[VLIB_RX] = rx0;
120 0 : n_p2p_ethernet_packets += 1;
121 :
122 0 : if (PREDICT_FALSE
123 : (n_trace > 0
124 : && vlib_trace_buffer (vm, node, next_index, b0,
125 : 1 /* follow_chain */ )))
126 : {
127 : p2p_ethernet_trace_t *t0;
128 0 : vlib_set_trace_count (vm, node, --n_trace);
129 0 : t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
130 0 : t0->sw_if_index = sw_if_index0;
131 0 : t0->p2pe_sw_if_index = rx0;
132 : }
133 :
134 0 : vlib_increment_combined_counter (cm, thread_index, rx0, 1,
135 : vlib_buffer_length_in_chain
136 : (vm, b0));
137 : }
138 0 : if (rx1 != ~0)
139 : {
140 : /* Send pkt to p2p_ethernet RX interface */
141 0 : vnet_buffer (b1)->sw_if_index[VLIB_RX] = rx1;
142 0 : n_p2p_ethernet_packets += 1;
143 :
144 0 : if (PREDICT_FALSE
145 : (n_trace > 0
146 : && vlib_trace_buffer (vm, node, next_index, b1,
147 : 1 /* follow_chain */ )))
148 : {
149 : p2p_ethernet_trace_t *t1;
150 0 : vlib_set_trace_count (vm, node, --n_trace);
151 0 : t1 = vlib_add_trace (vm, node, b1, sizeof (*t1));
152 0 : t1->sw_if_index = sw_if_index1;
153 0 : t1->p2pe_sw_if_index = rx1;
154 : }
155 :
156 0 : vlib_increment_combined_counter (cm, thread_index, rx1, 1,
157 : vlib_buffer_length_in_chain
158 : (vm, b1));
159 : }
160 :
161 : /* verify speculative enqueue, maybe switch current next frame */
162 0 : vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
163 : to_next, n_left_to_next,
164 : bi0, next0);
165 0 : vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
166 : to_next, n_left_to_next,
167 : bi1, next1);
168 : }
169 :
170 16 : while (n_left_from > 0 && n_left_to_next > 0)
171 : {
172 : u32 bi0;
173 : vlib_buffer_t *b0;
174 9 : u32 next0 = 0;
175 : u32 sw_if_index0;
176 : ethernet_header_t *en0;
177 : u32 rx0;
178 :
179 9 : bi0 = from[0];
180 9 : to_next[0] = bi0;
181 9 : from += 1;
182 9 : to_next += 1;
183 9 : n_left_from -= 1;
184 9 : n_left_to_next -= 1;
185 :
186 9 : b0 = vlib_get_buffer (vm, bi0);
187 :
188 9 : en0 = vlib_buffer_get_current (b0);
189 9 : sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
190 :
191 9 : vnet_feature_next (&next0, b0);
192 :
193 9 : rx0 = p2p_ethernet_lookup (sw_if_index0, en0->src_address);
194 9 : if (rx0 != ~0)
195 : {
196 : /* Send pkt to p2p_ethernet RX interface */
197 2 : vnet_buffer (b0)->sw_if_index[VLIB_RX] = rx0;
198 2 : n_p2p_ethernet_packets += 1;
199 :
200 2 : if (PREDICT_FALSE
201 : (n_trace > 0
202 : && vlib_trace_buffer (vm, node, next_index, b0,
203 : 1 /* follow_chain */ )))
204 : {
205 : p2p_ethernet_trace_t *t0;
206 0 : vlib_set_trace_count (vm, node, --n_trace);
207 0 : t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
208 0 : t0->sw_if_index = sw_if_index0;
209 0 : t0->p2pe_sw_if_index = rx0;
210 : }
211 :
212 2 : vlib_increment_combined_counter (cm, thread_index, rx0, 1,
213 : vlib_buffer_length_in_chain
214 : (vm, b0));
215 : }
216 : else
217 : {
218 7 : if (PREDICT_FALSE (n_trace > 0))
219 : {
220 0 : node->flags |= VLIB_NODE_FLAG_TRACE;
221 : }
222 : }
223 :
224 : /* verify speculative enqueue, maybe switch current next frame */
225 9 : vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
226 : to_next, n_left_to_next,
227 : bi0, next0);
228 : }
229 7 : vlib_put_next_frame (vm, node, next_index, n_left_to_next);
230 : }
231 :
232 7 : vlib_node_increment_counter (vm, p2p_ethernet_input_node.index,
233 : P2PE_ERROR_HITS, n_p2p_ethernet_packets);
234 :
235 7 : return frame->n_vectors;
236 : }
237 :
238 : /* *INDENT-OFF* */
239 183788 : VLIB_REGISTER_NODE (p2p_ethernet_input_node) = {
240 : .name = "p2p-ethernet-input",
241 : .vector_size = sizeof (u32),
242 : .format_trace = format_p2p_ethernet_trace,
243 : .type = VLIB_NODE_TYPE_INTERNAL,
244 : .flags = VLIB_NODE_FLAG_TRACE_SUPPORTED,
245 :
246 : .n_errors = ARRAY_LEN(p2p_ethernet_error_strings),
247 : .error_strings = p2p_ethernet_error_strings,
248 :
249 : .n_next_nodes = 1,
250 :
251 : /* edit / add dispositions here */
252 : .next_nodes = {
253 : [0] = "error-drop",
254 : },
255 : };
256 : /* *INDENT-ON* */
257 :
258 : /*
259 : * fd.io coding-style-patch-verification: ON
260 : *
261 : * Local Variables:
262 : * eval: (c-set-style "gnu")
263 : * End:
264 : */
|