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/vnet.h>
17 : #include <vnet/adj/adj_l2.h>
18 : #include <vnet/ethernet/ethernet.h>
19 : #include <vnet/ip/ip.h>
20 :
21 : /**
22 : * @brief Trace data for a L2 Midchain
23 : */
24 : typedef struct adj_l2_trace_t_ {
25 : /** Adjacency index taken. */
26 : u32 adj_index;
27 : } adj_l2_trace_t;
28 :
29 : static u8 *
30 1699 : format_adj_l2_trace (u8 * s, va_list * args)
31 : {
32 1699 : CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
33 1699 : CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
34 1699 : adj_l2_trace_t * t = va_arg (*args, adj_l2_trace_t *);
35 :
36 1699 : s = format (s, "adj-idx %d : %U",
37 : t->adj_index,
38 : format_ip_adjacency, t->adj_index, FORMAT_IP_ADJACENCY_NONE);
39 1699 : return s;
40 : }
41 :
42 : typedef enum adj_l2_rewrite_next_t_
43 : {
44 : ADJ_L2_REWRITE_NEXT_DROP,
45 : } adj_l2_rewrite_next_t;
46 :
47 : always_inline uword
48 28 : adj_l2_rewrite_inline (vlib_main_t * vm,
49 : vlib_node_runtime_t * node,
50 : vlib_frame_t * frame,
51 : int is_midchain,
52 : int do_counters)
53 : {
54 28 : u32 * from = vlib_frame_vector_args (frame);
55 : u32 n_left_from, n_left_to_next, * to_next, next_index;
56 28 : u32 thread_index = vlib_get_thread_index();
57 28 : ethernet_main_t * em = ðernet_main;
58 :
59 28 : n_left_from = frame->n_vectors;
60 28 : next_index = node->cached_next_index;
61 :
62 56 : while (n_left_from > 0)
63 : {
64 28 : vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
65 :
66 2090 : while (n_left_from > 0 && n_left_to_next > 0)
67 : {
68 : ip_adjacency_t * adj0;
69 : vlib_buffer_t * p0;
70 : char *h0;
71 2062 : u32 pi0, rw_len0, len0, adj_index0, next0 = 0;
72 : u32 tx_sw_if_index0;
73 :
74 2062 : pi0 = to_next[0] = from[0];
75 2062 : from += 1;
76 2062 : n_left_from -= 1;
77 2062 : to_next += 1;
78 2062 : n_left_to_next -= 1;
79 :
80 2062 : p0 = vlib_get_buffer (vm, pi0);
81 2062 : h0 = vlib_buffer_get_current (p0);
82 :
83 2062 : adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
84 :
85 2062 : adj0 = adj_get (adj_index0);
86 :
87 : /* Guess we are writing on ip4 header. */
88 2062 : vnet_rewrite_one_header (adj0[0], h0,
89 : //sizeof (gre_header_t) +
90 : sizeof (ip4_header_t));
91 :
92 : /* Update packet buffer attributes/set output interface. */
93 2062 : rw_len0 = adj0[0].rewrite_header.data_bytes;
94 2062 : vnet_buffer(p0)->ip.save_rewrite_length = rw_len0;
95 2062 : vnet_buffer(p0)->sw_if_index[VLIB_TX] = adj0->rewrite_header.sw_if_index;
96 2062 : len0 = vlib_buffer_length_in_chain (vm, p0);
97 : /* since we are coming out of the L2 world, where the vlib_buffer
98 : * union is used for other things, make sure it is clean for
99 : * MPLS from now on.
100 : */
101 2062 : vnet_buffer(p0)->mpls.first = 0;
102 :
103 2062 : if (do_counters)
104 0 : vlib_increment_combined_counter(&adjacency_counters,
105 : thread_index,
106 : adj_index0,
107 : 0, len0);
108 :
109 : /* Check MTU of outgoing interface. */
110 2062 : if (PREDICT_TRUE(len0 <= adj0[0].rewrite_header.max_l3_packet_bytes))
111 : {
112 : /* Don't adjust the buffer for ttl issue; icmp-error node wants
113 : * to see the IP header */
114 2062 : p0->current_data -= rw_len0;
115 2062 : p0->current_length += rw_len0;
116 2062 : tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index;
117 :
118 2062 : if (is_midchain)
119 : {
120 2062 : adj0->sub_type.midchain.fixup_func(
121 : vm, adj0, p0,
122 : adj0->sub_type.midchain.fixup_data);
123 : }
124 :
125 2062 : vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
126 :
127 : /*
128 : * Follow the feature ARC. this will result eventually in
129 : * the midchain-tx node
130 : */
131 2062 : if (PREDICT_FALSE (adj0->rewrite_header.flags &
132 : VNET_REWRITE_HAS_FEATURES))
133 0 : vnet_feature_arc_start_w_cfg_index (
134 0 : em->output_feature_arc_index,
135 : tx_sw_if_index0,
136 : &next0, p0,
137 : adj0->ia_cfg_index);
138 : else
139 2062 : next0 = adj0[0].rewrite_header.next_index;
140 : }
141 : else
142 : {
143 : /* can't fragment L2 */
144 0 : next0 = ADJ_L2_REWRITE_NEXT_DROP;
145 : }
146 :
147 2062 : if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED))
148 : {
149 2062 : adj_l2_trace_t *tr = vlib_add_trace (vm, node,
150 : p0, sizeof (*tr));
151 2062 : tr->adj_index = vnet_buffer(p0)->ip.adj_index[VLIB_TX];
152 : }
153 :
154 2062 : vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
155 : to_next, n_left_to_next,
156 : pi0, next0);
157 : }
158 :
159 28 : vlib_put_next_frame (vm, node, next_index, n_left_to_next);
160 : }
161 :
162 28 : return frame->n_vectors;
163 : }
164 :
165 2236 : VLIB_NODE_FN (adj_l2_rewrite_node) (vlib_main_t * vm,
166 : vlib_node_runtime_t * node,
167 : vlib_frame_t * frame)
168 : {
169 0 : if (adj_are_counters_enabled ())
170 0 : return adj_l2_rewrite_inline (vm, node, frame, 0, 1);
171 : else
172 0 : return adj_l2_rewrite_inline (vm, node, frame, 0, 0);
173 : }
174 :
175 2264 : VLIB_NODE_FN (adj_l2_midchain_node) (vlib_main_t * vm,
176 : vlib_node_runtime_t * node,
177 : vlib_frame_t * frame)
178 : {
179 28 : if (adj_are_counters_enabled ())
180 0 : return adj_l2_rewrite_inline (vm, node, frame, 1, 1);
181 : else
182 28 : return adj_l2_rewrite_inline (vm, node, frame, 1, 0);
183 : }
184 :
185 178120 : VLIB_REGISTER_NODE (adj_l2_rewrite_node) = {
186 : .name = "adj-l2-rewrite",
187 : .vector_size = sizeof (u32),
188 :
189 : .format_trace = format_adj_l2_trace,
190 :
191 : .n_next_nodes = 1,
192 : .next_nodes = {
193 : [ADJ_L2_REWRITE_NEXT_DROP] = "error-drop",
194 : },
195 : };
196 :
197 178120 : VLIB_REGISTER_NODE (adj_l2_midchain_node) = {
198 : .name = "adj-l2-midchain",
199 : .vector_size = sizeof (u32),
200 :
201 : .format_trace = format_adj_l2_trace,
202 :
203 : .n_next_nodes = 1,
204 : .next_nodes = {
205 : [ADJ_L2_REWRITE_NEXT_DROP] = "error-drop",
206 : },
207 : };
|