blob: 170ed19855e5d1f0826835f67b69e6bddabf12f6 [file] [log] [blame]
Neale Rannsf339f492021-03-31 07:36:33 +00001/*
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 */
22typedef 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
30always_inline uword
31adj_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 vnet_main_t *vnm = vnet_get_main ();
40 vnet_interface_main_t *im = &vnm->interface_main;
41
42 thread_index = vm->thread_index;
43 n_left = frame->n_vectors;
44 from = vlib_frame_vector_args (frame);
45
46 vlib_get_buffers (vm, from, bufs, n_left);
47
48 next = nexts;
49 b = bufs;
50
51 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 vlib_prefetch_buffer_header (b[4], LOAD);
60 vlib_prefetch_buffer_header (b[5], LOAD);
61 vlib_prefetch_buffer_header (b[6], LOAD);
62 vlib_prefetch_buffer_header (b[7], LOAD);
63 }
64
65 /* Follow the DPO on which the midchain is stacked */
66 adj_index0 = vnet_buffer(b[0])->ip.adj_index[VLIB_TX];
67 adj_index1 = vnet_buffer(b[1])->ip.adj_index[VLIB_TX];
68 adj_index2 = vnet_buffer(b[2])->ip.adj_index[VLIB_TX];
69 adj_index3 = vnet_buffer(b[3])->ip.adj_index[VLIB_TX];
70
71 adj0 = adj_get(adj_index0);
72 adj1 = adj_get(adj_index1);
73 adj2 = adj_get(adj_index2);
74 adj3 = adj_get(adj_index3);
75
76 dpo0 = &adj0->sub_type.midchain.next_dpo;
77 dpo1 = &adj1->sub_type.midchain.next_dpo;
78 dpo2 = &adj2->sub_type.midchain.next_dpo;
79 dpo3 = &adj3->sub_type.midchain.next_dpo;
80
81 next[0] = dpo0->dpoi_next_node;
82 next[1] = dpo1->dpoi_next_node;
83 next[2] = dpo2->dpoi_next_node;
84 next[3] = dpo3->dpoi_next_node;
85
86 vnet_buffer(b[0])->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
87 vnet_buffer(b[1])->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
88 vnet_buffer(b[2])->ip.adj_index[VLIB_TX] = dpo2->dpoi_index;
89 vnet_buffer(b[3])->ip.adj_index[VLIB_TX] = dpo3->dpoi_index;
90
91 if (interface_count)
92 {
93 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 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 vlib_buffer_length_in_chain (vm, b[1]));
105 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 vlib_buffer_length_in_chain (vm, b[2]));
111 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 vlib_buffer_length_in_chain (vm, b[3]));
117 }
118
119 if (PREDICT_FALSE(node->flags & VLIB_NODE_FLAG_TRACE))
120 {
121 if (PREDICT_FALSE(b[0]->flags & VLIB_BUFFER_IS_TRACED))
122 {
123 adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
124 b[0], sizeof (*tr));
125 tr->ai = adj_index0;
126 }
127 if (PREDICT_FALSE(b[1]->flags & VLIB_BUFFER_IS_TRACED))
128 {
129 adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
130 b[1], sizeof (*tr));
131 tr->ai = adj_index1;
132 }
133 if (PREDICT_FALSE(b[2]->flags & VLIB_BUFFER_IS_TRACED))
134 {
135 adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
136 b[2], sizeof (*tr));
137 tr->ai = adj_index2;
138 }
139 if (PREDICT_FALSE(b[3]->flags & VLIB_BUFFER_IS_TRACED))
140 {
141 adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
142 b[3], sizeof (*tr));
143 tr->ai = adj_index3;
144 }
145 }
146 n_left -= 4;
147 b += 4;
148 next += 4;
149 }
150
151 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 adj_index0 = vnet_buffer(b[0])->ip.adj_index[VLIB_TX];
159 adj0 = adj_get(adj_index0);
160 dpo0 = &adj0->sub_type.midchain.next_dpo;
161 next[0] = dpo0->dpoi_next_node;
162 vnet_buffer(b[0])->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
163
164 if (interface_count)
165 {
166 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 if (PREDICT_FALSE(b[0]->flags & VLIB_BUFFER_IS_TRACED))
175 {
176 adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
177 b[0], sizeof (*tr));
178 tr->ai = adj_index0;
179 }
180
181 n_left -= 1;
182 b += 1;
183 next += 1;
184 }
185
186 vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
187
188 return frame->n_vectors;
189}
190
191static u8 *
192format_adj_midchain_tx_trace (u8 * s, va_list * args)
193{
194 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
195 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
196 adj_midchain_tx_trace_t *tr = va_arg (*args, adj_midchain_tx_trace_t*);
197
198 s = format(s, "adj-midchain:[%d]:%U", tr->ai,
199 format_ip_adjacency, tr->ai,
200 FORMAT_IP_ADJACENCY_NONE);
201
202 return (s);
203}
204
205static uword
206adj_midchain_tx (vlib_main_t * vm,
207 vlib_node_runtime_t * node,
208 vlib_frame_t * frame)
209{
210 return (adj_midchain_tx_inline(vm, node, frame, 1));
211}
212
213VLIB_REGISTER_NODE (adj_midchain_tx_node) = {
214 .function = adj_midchain_tx,
215 .name = "adj-midchain-tx",
216 .vector_size = sizeof (u32),
217
218 .format_trace = format_adj_midchain_tx_trace,
219
220 .n_next_nodes = 1,
221 .next_nodes = {
222 [0] = "error-drop",
223 },
224};
225
226static uword
227adj_midchain_tx_no_count (vlib_main_t * vm,
228 vlib_node_runtime_t * node,
229 vlib_frame_t * frame)
230{
231 return (adj_midchain_tx_inline(vm, node, frame, 0));
232}
233
234VLIB_REGISTER_NODE (adj_midchain_tx_no_count_node) = {
235 .function = adj_midchain_tx_no_count,
236 .name = "adj-midchain-tx-no-count",
237 .vector_size = sizeof (u32),
238
239 .format_trace = format_adj_midchain_tx_trace,
240 .sibling_of = "adj-midchain-tx",
241};