2 * Copyright (c) 2018 SUSE LLC.
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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
15 #include <sctp/sctp.h>
16 #include <sctp/sctp_debug.h>
17 #include <vppinfra/random.h>
18 #include <openssl/hmac.h>
21 ip6_sctp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
22 ip6_header_t * ip0, int *bogus_lengthp);
25 ip4_sctp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
28 #define foreach_sctp4_output_next \
29 _ (DROP, "error-drop") \
30 _ (IP_LOOKUP, "ip4-lookup")
32 #define foreach_sctp6_output_next \
33 _ (DROP, "error-drop") \
34 _ (IP_LOOKUP, "ip6-lookup")
36 static char *sctp_error_strings[] = {
37 #define sctp_error(n,s) s,
38 #include <sctp/sctp_error.def>
42 typedef enum _sctp_output_next
44 SCTP_OUTPUT_NEXT_DROP,
45 SCTP_OUTPUT_NEXT_IP_LOOKUP,
51 sctp_header_t sctp_header;
52 sctp_connection_t sctp_connection;
56 sctp_is_retransmitting (sctp_connection_t * sctp_conn, u8 idx)
58 return sctp_conn->sub_conn[idx].is_retransmitting;
62 sctp46_output_inline (vlib_main_t * vm,
63 vlib_node_runtime_t * node,
64 vlib_frame_t * from_frame, int is_ip4)
66 u32 n_left_from, next_index, *from, *to_next;
67 u32 my_thread_index = vm->thread_index;
69 from = vlib_frame_vector_args (from_frame);
70 n_left_from = from_frame->n_vectors;
71 next_index = node->cached_next_index;
72 sctp_set_time_now (my_thread_index);
74 while (n_left_from > 0)
78 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
80 while (n_left_from > 0 && n_left_to_next > 0)
84 sctp_header_t *sctp_hdr = 0;
85 sctp_connection_t *sctp_conn;
87 sctp_header_t *th0 = 0;
88 u32 error0 = SCTP_ERROR_PKTS_SENT, next0 =
89 SCTP_OUTPUT_NEXT_IP_LOOKUP;
91 #if SCTP_DEBUG_STATE_MACHINE
92 u16 packet_length = 0;
102 b0 = vlib_get_buffer (vm, bi0);
105 sctp_connection_get (sctp_buffer_opaque (b0)->
106 sctp.connection_index, my_thread_index);
108 if (PREDICT_FALSE (sctp_conn == 0))
110 error0 = SCTP_ERROR_INVALID_CONNECTION;
111 next0 = SCTP_OUTPUT_NEXT_DROP;
115 u8 idx = sctp_buffer_opaque (b0)->sctp.subconn_idx;
117 th0 = vlib_buffer_get_current (b0);
121 ip4_header_t *iph4 = vlib_buffer_push_ip4 (vm,
130 IP_PROTOCOL_SCTP, 1);
132 u32 checksum = ip4_sctp_compute_checksum (vm, b0, iph4);
134 sctp_hdr = ip4_next_header (iph4);
135 sctp_hdr->checksum = checksum;
137 vnet_buffer (b0)->l4_hdr_offset = (u8 *) th0 - b0->data;
139 #if SCTP_DEBUG_STATE_MACHINE
140 packet_length = clib_net_to_host_u16 (iph4->length);
145 ip6_header_t *iph6 = vlib_buffer_push_ip6 (vm,
158 u32 checksum = ip6_sctp_compute_checksum (vm, b0, iph6, &bogus);
161 sctp_hdr = ip6_next_header (iph6);
162 sctp_hdr->checksum = checksum;
164 vnet_buffer (b0)->l3_hdr_offset = (u8 *) iph6 - b0->data;
165 vnet_buffer (b0)->l4_hdr_offset = (u8 *) th0 - b0->data;
167 #if SCTP_DEBUG_STATE_MACHINE
168 packet_length = clib_net_to_host_u16 (iph6->payload_length);
172 sctp_full_hdr_t *full_hdr = (sctp_full_hdr_t *) sctp_hdr;
173 u8 chunk_type = vnet_sctp_get_chunk_type (&full_hdr->common_hdr);
174 if (chunk_type >= UNKNOWN)
177 ("Trying to send an unrecognized chunk... something is really bad.");
178 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
179 next0 = SCTP_OUTPUT_NEXT_DROP;
183 #if SCTP_DEBUG_STATE_MACHINE
185 (sctp_conn->sub_conn[idx].connection.lcl_port ==
187 || sctp_conn->sub_conn[idx].connection.lcl_port ==
189 && (sctp_conn->sub_conn[idx].connection.rmt_port ==
191 || sctp_conn->sub_conn[idx].connection.rmt_port ==
196 SCTP_DBG_STATE_MACHINE ("BUFFER IS INCORRECT: conn_index = %u, "
197 "packet_length = %u, "
198 "chunk_type = %u [%s], "
199 "connection.lcl_port = %u, sctp_hdr->src_port = %u, "
200 "connection.rmt_port = %u, sctp_hdr->dst_port = %u",
201 sctp_conn->sub_conn[idx].
202 connection.c_index, packet_length,
204 sctp_chunk_to_string (chunk_type),
205 sctp_conn->sub_conn[idx].
206 connection.lcl_port, sctp_hdr->src_port,
207 sctp_conn->sub_conn[idx].
211 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
212 next0 = SCTP_OUTPUT_NEXT_DROP;
216 SCTP_DBG_STATE_MACHINE
217 ("SESSION_INDEX = %u, CONN_INDEX = %u, CURR_CONN_STATE = %u (%s), "
218 "CHUNK_TYPE = %s, " "SRC_PORT = %u, DST_PORT = %u",
219 sctp_conn->sub_conn[idx].connection.s_index,
220 sctp_conn->sub_conn[idx].connection.c_index,
221 sctp_conn->state, sctp_state_to_string (sctp_conn->state),
222 sctp_chunk_to_string (chunk_type), full_hdr->hdr.src_port,
223 full_hdr->hdr.dst_port);
225 /* Let's make sure the state-machine does not send anything crazy */
226 #if SCTP_DEBUG_STATE_MACHINE
227 if (sctp_validate_output_state_machine (sctp_conn, chunk_type) != 0)
229 SCTP_DBG_STATE_MACHINE
230 ("Sending the wrong chunk (%s) based on state-machine status (%s)",
231 sctp_chunk_to_string (chunk_type),
232 sctp_state_to_string (sctp_conn->state));
234 error0 = SCTP_ERROR_UNKNOWN_CHUNK;
235 next0 = SCTP_OUTPUT_NEXT_DROP;
241 /* Karn's algorithm: RTT measurements MUST NOT be made using
242 * packets that were retransmitted
244 if (!sctp_is_retransmitting (sctp_conn, idx))
246 /* Measure RTT with this */
247 if (chunk_type == DATA
248 && sctp_conn->sub_conn[idx].RTO_pending == 0)
250 sctp_conn->sub_conn[idx].RTO_pending = 1;
251 sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
254 sctp_conn->sub_conn[idx].rtt_ts = sctp_time_now ();
257 /* Let's take care of TIMERS */
262 sctp_conn->state = SCTP_STATE_COOKIE_ECHOED;
267 SCTP_ADV_DBG_OUTPUT ("PACKET_LENGTH = %u", packet_length);
269 sctp_timer_update (sctp_conn, idx, SCTP_TIMER_T3_RXTX,
270 sctp_conn->sub_conn[idx].RTO);
275 /* Start the SCTP_TIMER_T2_SHUTDOWN timer */
276 sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T2_SHUTDOWN,
277 sctp_conn->sub_conn[idx].RTO);
278 sctp_conn->state = SCTP_STATE_SHUTDOWN_SENT;
283 /* Start the SCTP_TIMER_T2_SHUTDOWN timer */
284 sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T2_SHUTDOWN,
285 sctp_conn->sub_conn[idx].RTO);
286 sctp_conn->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
289 case SHUTDOWN_COMPLETE:
291 sctp_conn->state = SCTP_STATE_CLOSED;
296 vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
297 vnet_buffer (b0)->sw_if_index[VLIB_TX] =
298 sctp_conn->sub_conn[idx].c_fib_index;
300 b0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
302 SCTP_DBG_STATE_MACHINE
303 ("SESSION_INDEX = %u, CONNECTION_INDEX = %u, " "NEW_STATE = %s, "
304 "CHUNK_SENT = %s", sctp_conn->sub_conn[idx].connection.s_index,
305 sctp_conn->sub_conn[idx].connection.c_index,
306 sctp_state_to_string (sctp_conn->state),
307 sctp_chunk_to_string (chunk_type));
309 vnet_sctp_common_hdr_params_host_to_net (&full_hdr->common_hdr);
312 b0->error = node->errors[error0];
313 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
315 t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
318 clib_memcpy_fast (&t0->sctp_header, th0,
319 sizeof (t0->sctp_header));
323 clib_memset (&t0->sctp_header, 0, sizeof (t0->sctp_header));
325 clib_memcpy_fast (&t0->sctp_connection, sctp_conn,
326 sizeof (t0->sctp_connection));
329 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
330 n_left_to_next, bi0, next0);
333 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
336 return from_frame->n_vectors;
339 VLIB_NODE_FN (sctp4_output_node) (vlib_main_t * vm,
340 vlib_node_runtime_t * node,
341 vlib_frame_t * from_frame)
343 return sctp46_output_inline (vm, node, from_frame, 1 /* is_ip4 */ );
346 VLIB_NODE_FN (sctp6_output_node) (vlib_main_t * vm,
347 vlib_node_runtime_t * node,
348 vlib_frame_t * from_frame)
350 return sctp46_output_inline (vm, node, from_frame, 0 /* is_ip4 */ );
354 VLIB_REGISTER_NODE (sctp4_output_node) =
356 .name = "sctp4-output",
357 /* Takes a vector of packets. */
358 .vector_size = sizeof (u32),
359 .n_errors = SCTP_N_ERROR,
360 .error_strings = sctp_error_strings,
361 .n_next_nodes = SCTP_OUTPUT_N_NEXT,
363 #define _(s,n) [SCTP_OUTPUT_NEXT_##s] = n,
364 foreach_sctp4_output_next
367 .format_buffer = format_sctp_header,
368 .format_trace = format_sctp_tx_trace,
373 VLIB_REGISTER_NODE (sctp6_output_node) =
375 .name = "sctp6-output",
376 /* Takes a vector of packets. */
377 .vector_size = sizeof (u32),
378 .n_errors = SCTP_N_ERROR,
379 .error_strings = sctp_error_strings,
380 .n_next_nodes = SCTP_OUTPUT_N_NEXT,
382 #define _(s,n) [SCTP_OUTPUT_NEXT_##s] = n,
383 foreach_sctp6_output_next
386 .format_buffer = format_sctp_header,
387 .format_trace = format_sctp_tx_trace,
392 * fd.io coding-style-patch-verification: ON
395 * eval: (c-set-style "gnu")