blob: 0450064eafea74838f62d59a66b5674259ca514e [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * Copyright (c) 2015 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 * ip/ip6_input.c: IP v6 input node
17 *
18 * Copyright (c) 2008 Eliot Dresselhaus
19 *
20 * Permission is hereby granted, free of charge, to any person obtaining
21 * a copy of this software and associated documentation files (the
22 * "Software"), to deal in the Software without restriction, including
23 * without limitation the rights to use, copy, modify, merge, publish,
24 * distribute, sublicense, and/or sell copies of the Software, and to
25 * permit persons to whom the Software is furnished to do so, subject to
26 * the following conditions:
27 *
28 * The above copyright notice and this permission notice shall be
29 * included in all copies or substantial portions of the Software.
30 *
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 */
39
Neale Ranns4c7c8e52017-10-21 09:37:55 -070040#include <vnet/ip/ip6_input.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070041#include <vnet/ethernet/ethernet.h>
42#include <vnet/ppp/ppp.h>
43#include <vnet/hdlc/hdlc.h>
44
Dave Barachd7cb1b52016-12-09 09:52:16 -050045typedef struct
46{
Ed Warnickecb9cada2015-12-08 15:45:58 -070047 u8 packet_data[64];
48} ip6_input_trace_t;
49
Dave Barachd7cb1b52016-12-09 09:52:16 -050050static u8 *
51format_ip6_input_trace (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070052{
53 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
54 CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
Dave Barachd7cb1b52016-12-09 09:52:16 -050055 ip6_input_trace_t *t = va_arg (*va, ip6_input_trace_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070056
57 s = format (s, "%U",
Dave Barachd7cb1b52016-12-09 09:52:16 -050058 format_ip6_header, t->packet_data, sizeof (t->packet_data));
Ed Warnickecb9cada2015-12-08 15:45:58 -070059
60 return s;
61}
62
Ed Warnickecb9cada2015-12-08 15:45:58 -070063/* Validate IP v6 packets and pass them either to forwarding code
64 or drop exception packets. */
Filip Tehlar26ea14e2019-03-11 05:30:21 -070065VLIB_NODE_FN (ip6_input_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
66 vlib_frame_t * frame)
Ed Warnickecb9cada2015-12-08 15:45:58 -070067{
Dave Barachd7cb1b52016-12-09 09:52:16 -050068 vnet_main_t *vnm = vnet_get_main ();
69 ip6_main_t *im = &ip6_main;
70 ip_lookup_main_t *lm = &im->lookup_main;
71 u32 n_left_from, *from, *to_next;
Ed Warnickecb9cada2015-12-08 15:45:58 -070072 ip6_input_next_t next_index;
Dave Barachd7cb1b52016-12-09 09:52:16 -050073 vlib_node_runtime_t *error_node =
74 vlib_node_get_runtime (vm, ip6_input_node.index);
75 vlib_simple_counter_main_t *cm;
Damjan Marion067cd622018-07-11 12:47:43 +020076 u32 thread_index = vm->thread_index;
Ed Warnickecb9cada2015-12-08 15:45:58 -070077
78 from = vlib_frame_vector_args (frame);
79 n_left_from = frame->n_vectors;
80 next_index = node->cached_next_index;
81
82 if (node->flags & VLIB_NODE_FLAG_TRACE)
83 vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
84 /* stride */ 1,
85 sizeof (ip6_input_trace_t));
86
87 cm = vec_elt_at_index (vnm->interface_main.sw_if_counters,
Dave Barachd7cb1b52016-12-09 09:52:16 -050088 VNET_INTERFACE_COUNTER_IP6);
Ed Warnickecb9cada2015-12-08 15:45:58 -070089
90 while (n_left_from > 0)
91 {
92 u32 n_left_to_next;
93
Dave Barachd7cb1b52016-12-09 09:52:16 -050094 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
Ed Warnickecb9cada2015-12-08 15:45:58 -070095
96 while (n_left_from >= 4 && n_left_to_next >= 2)
97 {
Dave Barachd7cb1b52016-12-09 09:52:16 -050098 vlib_buffer_t *p0, *p1;
99 ip6_header_t *ip0, *ip1;
Damjan Marion8b3191e2016-11-09 19:54:20 +0100100 u32 pi0, sw_if_index0, next0 = 0;
101 u32 pi1, sw_if_index1, next1 = 0;
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700102 u8 arc0, arc1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700103
104 /* Prefetch next iteration. */
105 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500106 vlib_buffer_t *p2, *p3;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700107
108 p2 = vlib_get_buffer (vm, from[2]);
109 p3 = vlib_get_buffer (vm, from[3]);
110
111 vlib_prefetch_buffer_header (p2, LOAD);
112 vlib_prefetch_buffer_header (p3, LOAD);
113
114 CLIB_PREFETCH (p2->data, sizeof (ip0[0]), LOAD);
115 CLIB_PREFETCH (p3->data, sizeof (ip1[0]), LOAD);
116 }
117
118 pi0 = from[0];
119 pi1 = from[1];
120
121 to_next[0] = pi0;
122 to_next[1] = pi1;
123 from += 2;
124 to_next += 2;
125 n_left_from -= 2;
126 n_left_to_next -= 2;
127
128 p0 = vlib_get_buffer (vm, pi0);
129 p1 = vlib_get_buffer (vm, pi1);
130
131 ip0 = vlib_buffer_get_current (p0);
132 ip1 = vlib_buffer_get_current (p1);
133
134 sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
135 sw_if_index1 = vnet_buffer (p1)->sw_if_index[VLIB_RX];
136
Neale Ranns32e1c012016-11-22 17:07:28 +0000137 if (PREDICT_FALSE (ip6_address_is_multicast (&ip0->dst_address)))
138 {
139 arc0 = lm->mcast_feature_arc_index;
140 next0 = IP6_INPUT_NEXT_LOOKUP_MULTICAST;
141 }
142 else
143 {
144 arc0 = lm->ucast_feature_arc_index;
145 next0 = IP6_INPUT_NEXT_LOOKUP;
146 }
147
148 if (PREDICT_FALSE (ip6_address_is_multicast (&ip1->dst_address)))
149 {
150 arc1 = lm->mcast_feature_arc_index;
151 next1 = IP6_INPUT_NEXT_LOOKUP_MULTICAST;
152 }
153 else
154 {
155 arc1 = lm->ucast_feature_arc_index;
156 next1 = IP6_INPUT_NEXT_LOOKUP;
157 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700158
159 vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0;
160 vnet_buffer (p1)->ip.adj_index[VLIB_RX] = ~0;
161
Damjan Marion8b3191e2016-11-09 19:54:20 +0100162 vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0);
163 vnet_feature_arc_start (arc1, sw_if_index1, &next1, p1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700164
Damjan Marion586afd72017-04-05 19:18:20 +0200165 vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1);
166 vlib_increment_simple_counter (cm, thread_index, sw_if_index1, 1);
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700167 ip6_input_check_x2 (vm, error_node,
168 p0, p1, ip0, ip1, &next0, &next1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700169
170 vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
171 to_next, n_left_to_next,
172 pi0, pi1, next0, next1);
173 }
Dave Barachd7cb1b52016-12-09 09:52:16 -0500174
Ed Warnickecb9cada2015-12-08 15:45:58 -0700175 while (n_left_from > 0 && n_left_to_next > 0)
176 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500177 vlib_buffer_t *p0;
178 ip6_header_t *ip0;
Damjan Marion8b3191e2016-11-09 19:54:20 +0100179 u32 pi0, sw_if_index0, next0 = 0;
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700180 u8 arc0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700181
182 pi0 = from[0];
183 to_next[0] = pi0;
184 from += 1;
185 to_next += 1;
186 n_left_from -= 1;
187 n_left_to_next -= 1;
188
189 p0 = vlib_get_buffer (vm, pi0);
190 ip0 = vlib_buffer_get_current (p0);
191
192 sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
Neale Ranns32e1c012016-11-22 17:07:28 +0000193 if (PREDICT_FALSE (ip6_address_is_multicast (&ip0->dst_address)))
194 {
195 arc0 = lm->mcast_feature_arc_index;
196 next0 = IP6_INPUT_NEXT_LOOKUP_MULTICAST;
197 }
198 else
199 {
200 arc0 = lm->ucast_feature_arc_index;
201 next0 = IP6_INPUT_NEXT_LOOKUP;
202 }
203
Ed Warnickecb9cada2015-12-08 15:45:58 -0700204 vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0;
Damjan Marion8b3191e2016-11-09 19:54:20 +0100205 vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700206
Damjan Marion586afd72017-04-05 19:18:20 +0200207 vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1);
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700208 ip6_input_check_x1 (vm, error_node, p0, ip0, &next0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700209
210 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
211 to_next, n_left_to_next,
212 pi0, next0);
213 }
214
215 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
216 }
217
218 return frame->n_vectors;
219}
220
Filip Tehlar26ea14e2019-03-11 05:30:21 -0700221#ifndef CLIB_MARCH_VARIANT
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700222char *ip6_error_strings[] = {
Ed Warnickecb9cada2015-12-08 15:45:58 -0700223#define _(sym,string) string,
224 foreach_ip6_error
225#undef _
226};
Filip Tehlar26ea14e2019-03-11 05:30:21 -0700227#endif /* CLIB_MARCH_VARIANT */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700228
Dave Barachd7cb1b52016-12-09 09:52:16 -0500229/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700230VLIB_REGISTER_NODE (ip6_input_node) = {
Ed Warnickecb9cada2015-12-08 15:45:58 -0700231 .name = "ip6-input",
232 .vector_size = sizeof (u32),
233
234 .n_errors = IP6_N_ERROR,
235 .error_strings = ip6_error_strings,
236
237 .n_next_nodes = IP6_INPUT_N_NEXT,
238 .next_nodes = {
239 [IP6_INPUT_NEXT_DROP] = "error-drop",
240 [IP6_INPUT_NEXT_LOOKUP] = "ip6-lookup",
Ole Troan9fb87552016-01-13 22:30:43 +0100241 [IP6_INPUT_NEXT_ICMP_ERROR] = "ip6-icmp-error",
Neale Ranns32e1c012016-11-22 17:07:28 +0000242 [IP6_INPUT_NEXT_LOOKUP_MULTICAST] = "ip6-mfib-forward-lookup",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700243 },
244
245 .format_buffer = format_ip6_header,
246 .format_trace = format_ip6_input_trace,
247};
Dave Barachd7cb1b52016-12-09 09:52:16 -0500248/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700249
Dave Barach49433ad2018-08-08 17:59:03 -0400250static clib_error_t *
251ip6_init (vlib_main_t * vm)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700252{
Dave Barachd7cb1b52016-12-09 09:52:16 -0500253 ethernet_register_input_type (vm, ETHERNET_TYPE_IP6, ip6_input_node.index);
254 ppp_register_input_protocol (vm, PPP_PROTOCOL_ip6, ip6_input_node.index);
255 hdlc_register_input_protocol (vm, HDLC_PROTOCOL_ip6, ip6_input_node.index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700256
257 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500258 pg_node_t *pn;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700259 pn = pg_get_node (ip6_input_node.index);
260 pn->unformat_edit = unformat_pg_ip6_header;
261 }
262
263 /* Set flow hash to something non-zero. */
264 ip6_main.flow_hash_seed = 0xdeadbeef;
265
266 /* Default hop limit for packets we generate. */
267 ip6_main.host_config.ttl = 64;
268
269 return /* no error */ 0;
270}
271
272VLIB_INIT_FUNCTION (ip6_init);
Dave Barachd7cb1b52016-12-09 09:52:16 -0500273
Dave Barach49433ad2018-08-08 17:59:03 -0400274static clib_error_t *
275ip6_main_loop_enter (vlib_main_t * vm)
276{
277 ip6_main_t *im = &ip6_main;
278 vlib_thread_main_t *tm = &vlib_thread_main;
Dave Barach49433ad2018-08-08 17:59:03 -0400279
Neale Rannscd35e532018-08-31 02:51:45 -0700280 throttle_init (&im->nd_throttle, tm->n_vlib_mains, 1e-3);
Dave Barach49433ad2018-08-08 17:59:03 -0400281
Dave Barach49433ad2018-08-08 17:59:03 -0400282 return 0;
283}
284
285VLIB_MAIN_LOOP_ENTER_FUNCTION (ip6_main_loop_enter);
286
Dave Barachd7cb1b52016-12-09 09:52:16 -0500287/*
288 * fd.io coding-style-patch-verification: ON
289 *
290 * Local Variables:
291 * eval: (c-set-style "gnu")
292 * End:
293 */