-#if SCTP_DEBUG_STATE_MACHINE
- packet_length = clib_net_to_host_u16 (iph6->payload_length);
-#endif
- }
-
- u8 is_valid =
- (sctp_conn->sub_conn[idx].connection.lcl_port ==
- sctp_hdr->src_port
- || sctp_conn->sub_conn[idx].connection.lcl_port ==
- sctp_hdr->dst_port)
- && (sctp_conn->sub_conn[idx].connection.rmt_port ==
- sctp_hdr->dst_port
- || sctp_conn->sub_conn[idx].connection.rmt_port ==
- sctp_hdr->src_port);
-
- sctp_full_hdr_t *full_hdr = (sctp_full_hdr_t *) sctp_hdr;
- u8 chunk_type = vnet_sctp_get_chunk_type (&full_hdr->common_hdr);
-
- if (!is_valid)
- {
- SCTP_DBG_STATE_MACHINE ("BUFFER IS INCORRECT: conn_index = %u, "
- "packet_length = %u, "
- "chunk_type = %u [%s], "
- "connection.lcl_port = %u, sctp_hdr->src_port = %u, "
- "connection.rmt_port = %u, sctp_hdr->dst_port = %u",
- sctp_conn->sub_conn
- [idx].connection.c_index, packet_length,
- chunk_type,
- sctp_chunk_to_string (chunk_type),
- sctp_conn->sub_conn[idx].
- connection.lcl_port, sctp_hdr->src_port,
- sctp_conn->sub_conn[idx].
- connection.rmt_port,
- sctp_hdr->dst_port);
-
- error0 = SCTP_ERROR_UNKOWN_CHUNK;
- next0 = SCTP_OUTPUT_NEXT_DROP;
- goto done;
- }
-
- SCTP_DBG_STATE_MACHINE
- ("CONN_INDEX = %u, CURR_CONN_STATE = %u (%s), "
- "CHUNK_TYPE = %s, " "SRC_PORT = %u, DST_PORT = %u",
- sctp_conn->sub_conn[idx].connection.c_index,
- sctp_conn->state, sctp_state_to_string (sctp_conn->state),
- sctp_chunk_to_string (chunk_type), full_hdr->hdr.src_port,
- full_hdr->hdr.dst_port);
-
- if (chunk_type == DATA)
- SCTP_ADV_DBG_OUTPUT ("PACKET_LENGTH = %u", packet_length);
-
- /* Let's make sure the state-machine does not send anything crazy */
- switch (sctp_conn->state)
- {
- case SCTP_STATE_CLOSED:
- {
- if (chunk_type != INIT && chunk_type != INIT_ACK)
- {
- SCTP_DBG_STATE_MACHINE
- ("Sending the wrong chunk (%s) based on state-machine status (%s)",
- sctp_chunk_to_string (chunk_type),
- sctp_state_to_string (sctp_conn->state));
-
- error0 = SCTP_ERROR_UNKOWN_CHUNK;
- next0 = SCTP_OUTPUT_NEXT_DROP;
- goto done;
- }
- break;
- }
- case SCTP_STATE_ESTABLISHED:
- if (chunk_type != DATA && chunk_type != HEARTBEAT &&
- chunk_type != HEARTBEAT_ACK && chunk_type != SACK &&
- chunk_type != COOKIE_ACK && chunk_type != SHUTDOWN)
- {
- SCTP_DBG_STATE_MACHINE
- ("Sending the wrong chunk (%s) based on state-machine status (%s)",
- sctp_chunk_to_string (chunk_type),
- sctp_state_to_string (sctp_conn->state));
-
- error0 = SCTP_ERROR_UNKOWN_CHUNK;
- next0 = SCTP_OUTPUT_NEXT_DROP;
- goto done;
- }
- break;
- case SCTP_STATE_COOKIE_WAIT:
- if (chunk_type != COOKIE_ECHO)
- {
- SCTP_DBG_STATE_MACHINE
- ("Sending the wrong chunk (%s) based on state-machine status (%s)",
- sctp_chunk_to_string (chunk_type),
- sctp_state_to_string (sctp_conn->state));
-
- error0 = SCTP_ERROR_UNKOWN_CHUNK;
- next0 = SCTP_OUTPUT_NEXT_DROP;
- goto done;
- }
- /* Change state */
- sctp_conn->state = SCTP_STATE_COOKIE_ECHOED;
- break;
- case SCTP_STATE_SHUTDOWN_SENT:
- if (chunk_type != SHUTDOWN_COMPLETE)
- {
- SCTP_DBG_STATE_MACHINE
- ("Sending the wrong chunk (%s) based on state-machine status (%s)",
- sctp_chunk_to_string (chunk_type),
- sctp_state_to_string (sctp_conn->state));
-
- error0 = SCTP_ERROR_UNKOWN_CHUNK;
- next0 = SCTP_OUTPUT_NEXT_DROP;
- goto done;
- }
- case SCTP_STATE_SHUTDOWN_RECEIVED:
- if (chunk_type != SHUTDOWN_ACK)
- {
- SCTP_DBG_STATE_MACHINE
- ("Sending the wrong chunk (%s) based on state-machine status (%s)",
- sctp_chunk_to_string (chunk_type),
- sctp_state_to_string (sctp_conn->state));
-
- error0 = SCTP_ERROR_UNKOWN_CHUNK;
- next0 = SCTP_OUTPUT_NEXT_DROP;
- goto done;
- }
- default:
- SCTP_DBG_STATE_MACHINE
- ("Sending chunk (%s) based on state-machine status (%s)",
- sctp_chunk_to_string (chunk_type),
- sctp_state_to_string (sctp_conn->state));
- break;
- }
-
- switch (chunk_type)
- {
- case DATA:
- {
- sctp_timer_update (sctp_conn, idx, SCTP_TIMER_T3_RXTX,
- sctp_conn->sub_conn[idx].RTO);
- break;
- }
- case SHUTDOWN:
- {
- /* Start the SCTP_TIMER_T2_SHUTDOWN timer */
- sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T2_SHUTDOWN,
- sctp_conn->sub_conn[idx].RTO);
- sctp_conn->state = SCTP_STATE_SHUTDOWN_SENT;
- break;
- }
- case SHUTDOWN_ACK:
- {
- /* Start the SCTP_TIMER_T2_SHUTDOWN timer */
- sctp_timer_set (sctp_conn, idx, SCTP_TIMER_T2_SHUTDOWN,
- sctp_conn->sub_conn[idx].RTO);
- sctp_conn->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
- break;
- }
- }
-
- vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
-
- b0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
-
- SCTP_DBG_STATE_MACHINE ("CONNECTION_INDEX = %u, "
- "NEW_STATE = %s, "
- "CHUNK_SENT = %s",
- sctp_conn->sub_conn[idx].connection.c_index,
- sctp_state_to_string (sctp_conn->state),
- sctp_chunk_to_string (chunk_type));
-
- vnet_sctp_common_hdr_params_host_to_net (&full_hdr->common_hdr);
-
- done:
- b0->error = node->errors[error0];
- if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
- {
- t0 = vlib_add_trace (vm, node, b0, sizeof (*t0));
- if (th0)
- {
- clib_memcpy (&t0->sctp_header, th0,
- sizeof (t0->sctp_header));
- }
- else
- {
- memset (&t0->sctp_header, 0, sizeof (t0->sctp_header));
- }
- clib_memcpy (&t0->sctp_connection, sctp_conn,
- sizeof (t0->sctp_connection));
- }
-
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
- n_left_to_next, bi0, next0);
- }