Line data Source code
1 : /*
2 : * Copyright (c) 2016 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 : #include <vnet/adj/adj_internal.h>
17 : #include <vnet/adj/adj_midchain.h>
18 :
19 : /**
20 : * @brief Trace data for packets traversing the midchain tx node
21 : */
22 : typedef struct adj_midchain_tx_trace_t_
23 : {
24 : /**
25 : * @brief the midchain adj we are traversing
26 : */
27 : adj_index_t ai;
28 : } adj_midchain_tx_trace_t;
29 :
30 : always_inline uword
31 620 : adj_midchain_tx_inline (vlib_main_t * vm,
32 : vlib_node_runtime_t * node,
33 : vlib_frame_t * frame,
34 : int interface_count)
35 : {
36 : vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
37 : u16 nexts[VLIB_FRAME_SIZE], *next;
38 : u32 * from, n_left, thread_index;
39 620 : vnet_main_t *vnm = vnet_get_main ();
40 620 : vnet_interface_main_t *im = &vnm->interface_main;
41 :
42 620 : thread_index = vm->thread_index;
43 620 : n_left = frame->n_vectors;
44 620 : from = vlib_frame_vector_args (frame);
45 :
46 620 : vlib_get_buffers (vm, from, bufs, n_left);
47 :
48 620 : next = nexts;
49 620 : b = bufs;
50 :
51 12516 : while (n_left > 8)
52 : {
53 : u32 adj_index0, adj_index1, adj_index2, adj_index3;
54 : const ip_adjacency_t *adj0, *adj1, *adj2, *adj3;
55 : const dpo_id_t *dpo0, *dpo1, *dpo2, *dpo3;
56 :
57 : /* Prefetch next iteration. */
58 : {
59 11896 : vlib_prefetch_buffer_header (b[4], LOAD);
60 11896 : vlib_prefetch_buffer_header (b[5], LOAD);
61 11896 : vlib_prefetch_buffer_header (b[6], LOAD);
62 11896 : vlib_prefetch_buffer_header (b[7], LOAD);
63 : }
64 :
65 : /* Follow the DPO on which the midchain is stacked */
66 11896 : adj_index0 = vnet_buffer(b[0])->ip.adj_index[VLIB_TX];
67 11896 : adj_index1 = vnet_buffer(b[1])->ip.adj_index[VLIB_TX];
68 11896 : adj_index2 = vnet_buffer(b[2])->ip.adj_index[VLIB_TX];
69 11896 : adj_index3 = vnet_buffer(b[3])->ip.adj_index[VLIB_TX];
70 :
71 11896 : adj0 = adj_get(adj_index0);
72 11896 : adj1 = adj_get(adj_index1);
73 11896 : adj2 = adj_get(adj_index2);
74 11896 : adj3 = adj_get(adj_index3);
75 :
76 11896 : dpo0 = &adj0->sub_type.midchain.next_dpo;
77 11896 : dpo1 = &adj1->sub_type.midchain.next_dpo;
78 11896 : dpo2 = &adj2->sub_type.midchain.next_dpo;
79 11896 : dpo3 = &adj3->sub_type.midchain.next_dpo;
80 :
81 11896 : next[0] = dpo0->dpoi_next_node;
82 11896 : next[1] = dpo1->dpoi_next_node;
83 11896 : next[2] = dpo2->dpoi_next_node;
84 11896 : next[3] = dpo3->dpoi_next_node;
85 :
86 11896 : vnet_buffer(b[0])->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
87 11896 : vnet_buffer(b[1])->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
88 11896 : vnet_buffer(b[2])->ip.adj_index[VLIB_TX] = dpo2->dpoi_index;
89 11896 : vnet_buffer(b[3])->ip.adj_index[VLIB_TX] = dpo3->dpoi_index;
90 :
91 11896 : if (interface_count)
92 : {
93 11524 : vlib_increment_combined_counter (im->combined_sw_if_counters
94 : + VNET_INTERFACE_COUNTER_TX,
95 : thread_index,
96 : adj0->rewrite_header.sw_if_index,
97 : 1,
98 : vlib_buffer_length_in_chain (vm, b[0]));
99 11524 : vlib_increment_combined_counter (im->combined_sw_if_counters
100 : + VNET_INTERFACE_COUNTER_TX,
101 : thread_index,
102 : adj1->rewrite_header.sw_if_index,
103 : 1,
104 11524 : vlib_buffer_length_in_chain (vm, b[1]));
105 11524 : vlib_increment_combined_counter (im->combined_sw_if_counters
106 : + VNET_INTERFACE_COUNTER_TX,
107 : thread_index,
108 : adj2->rewrite_header.sw_if_index,
109 : 1,
110 11524 : vlib_buffer_length_in_chain (vm, b[2]));
111 11524 : vlib_increment_combined_counter (im->combined_sw_if_counters
112 : + VNET_INTERFACE_COUNTER_TX,
113 : thread_index,
114 : adj3->rewrite_header.sw_if_index,
115 : 1,
116 11524 : vlib_buffer_length_in_chain (vm, b[3]));
117 : }
118 :
119 11896 : if (PREDICT_FALSE(node->flags & VLIB_NODE_FLAG_TRACE))
120 : {
121 11648 : if (PREDICT_FALSE(b[0]->flags & VLIB_BUFFER_IS_TRACED))
122 : {
123 11648 : adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
124 : b[0], sizeof (*tr));
125 11648 : tr->ai = adj_index0;
126 : }
127 11648 : if (PREDICT_FALSE(b[1]->flags & VLIB_BUFFER_IS_TRACED))
128 : {
129 11648 : adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
130 11648 : b[1], sizeof (*tr));
131 11648 : tr->ai = adj_index1;
132 : }
133 11648 : if (PREDICT_FALSE(b[2]->flags & VLIB_BUFFER_IS_TRACED))
134 : {
135 11648 : adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
136 11648 : b[2], sizeof (*tr));
137 11648 : tr->ai = adj_index2;
138 : }
139 11648 : if (PREDICT_FALSE(b[3]->flags & VLIB_BUFFER_IS_TRACED))
140 : {
141 11648 : adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
142 11648 : b[3], sizeof (*tr));
143 11648 : tr->ai = adj_index3;
144 : }
145 : }
146 11896 : n_left -= 4;
147 11896 : b += 4;
148 11896 : next += 4;
149 : }
150 :
151 3875 : while (n_left)
152 : {
153 : const ip_adjacency_t * adj0;
154 : const dpo_id_t *dpo0;
155 : u32 adj_index0;
156 :
157 : /* Follow the DPO on which the midchain is stacked */
158 3255 : adj_index0 = vnet_buffer(b[0])->ip.adj_index[VLIB_TX];
159 3255 : adj0 = adj_get(adj_index0);
160 3255 : dpo0 = &adj0->sub_type.midchain.next_dpo;
161 3255 : next[0] = dpo0->dpoi_next_node;
162 3255 : vnet_buffer(b[0])->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
163 :
164 3255 : if (interface_count)
165 : {
166 3201 : vlib_increment_combined_counter (im->combined_sw_if_counters
167 : + VNET_INTERFACE_COUNTER_TX,
168 : thread_index,
169 : adj0->rewrite_header.sw_if_index,
170 : 1,
171 : vlib_buffer_length_in_chain (vm, b[0]));
172 : }
173 :
174 3255 : if (PREDICT_FALSE(b[0]->flags & VLIB_BUFFER_IS_TRACED))
175 : {
176 3250 : adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
177 : b[0], sizeof (*tr));
178 3250 : tr->ai = adj_index0;
179 : }
180 :
181 3255 : n_left -= 1;
182 3255 : b += 1;
183 3255 : next += 1;
184 : }
185 :
186 620 : vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
187 :
188 620 : return frame->n_vectors;
189 : }
190 :
191 : static u8 *
192 28222 : format_adj_midchain_tx_trace (u8 * s, va_list * args)
193 : {
194 28222 : CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
195 28222 : CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
196 28222 : adj_midchain_tx_trace_t *tr = va_arg (*args, adj_midchain_tx_trace_t*);
197 :
198 28222 : s = format(s, "adj-midchain:[%d]:%U", tr->ai,
199 : format_ip_adjacency, tr->ai,
200 : FORMAT_IP_ADJACENCY_NONE);
201 :
202 28222 : return (s);
203 : }
204 :
205 2544 : VLIB_NODE_FN (adj_midchain_tx) (vlib_main_t * vm,
206 : vlib_node_runtime_t * node,
207 : vlib_frame_t * frame)
208 : {
209 308 : return (adj_midchain_tx_inline(vm, node, frame, 1));
210 : }
211 2536 : VLIB_NODE_FN (tunnel_output) (vlib_main_t * vm,
212 : vlib_node_runtime_t * node,
213 : vlib_frame_t * frame)
214 : {
215 300 : return (adj_midchain_tx_inline(vm, node, frame, 1));
216 : }
217 :
218 178120 : VLIB_REGISTER_NODE (adj_midchain_tx) = {
219 : .name = "adj-midchain-tx",
220 : .vector_size = sizeof (u32),
221 :
222 : .format_trace = format_adj_midchain_tx_trace,
223 :
224 : .n_next_nodes = 1,
225 : .next_nodes = {
226 : [0] = "error-drop",
227 : },
228 : };
229 178120 : VLIB_REGISTER_NODE (tunnel_output) = {
230 : .name = "tunnel-output",
231 : .vector_size = sizeof (u32),
232 : .format_trace = format_adj_midchain_tx_trace,
233 : .sibling_of = "adj-midchain-tx",
234 : };
235 :
236 2248 : VLIB_NODE_FN (tunnel_output_no_count) (vlib_main_t * vm,
237 : vlib_node_runtime_t * node,
238 : vlib_frame_t * frame)
239 : {
240 12 : return (adj_midchain_tx_inline(vm, node, frame, 0));
241 : }
242 :
243 178120 : VLIB_REGISTER_NODE (tunnel_output_no_count) = {
244 : .name = "tunnel-output-no-count",
245 : .vector_size = sizeof (u32),
246 : .format_trace = format_adj_midchain_tx_trace,
247 : .sibling_of = "adj-midchain-tx",
248 : };
|