From 3b09645d2b0259962d7f1e8a0adf76ab4b00fc1c Mon Sep 17 00:00:00 2001 From: Junfeng Wang Date: Mon, 9 Sep 2019 02:37:32 +0000 Subject: Revert "add source code" This reverts commit 4b0f20eed87e8b1542f991e06f4868b05f36dd64. Reason for revert: Change-Id: I81a3d178c661bbc4e6fd9b0d6063a12bbfc0817c Signed-off-by: Junfeng Wang --- src/dpi_node.c | 1035 -------------------------------------------------------- 1 file changed, 1035 deletions(-) delete mode 100644 src/dpi_node.c (limited to 'src/dpi_node.c') diff --git a/src/dpi_node.c b/src/dpi_node.c deleted file mode 100644 index 6b5f9c1..0000000 --- a/src/dpi_node.c +++ /dev/null @@ -1,1035 +0,0 @@ -/* - * Copyright (c) 2019 Intel and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#include -#include - -#include "dpi.h" - -vlib_node_registration_t dpi4_input_node; -vlib_node_registration_t dpi6_input_node; -vlib_node_registration_t dpi4_flow_input_node; -vlib_node_registration_t dpi6_flow_input_node; - - -#define foreach_dpi_input_error \ - _(NONE, "no error") \ - _(NO_SUCH_FLOW, "flow not existed") - -typedef enum -{ -#define _(sym,str) DPI_INPUT_ERROR_##sym, - foreach_dpi_input_error -#undef _ - DPI_INPUT_N_ERROR, -} dpi_input_error_t; - -static char *dpi_input_error_strings[] = { -#define _(sym,string) string, - foreach_dpi_input_error -#undef _ -}; - -typedef struct -{ - u32 next_index; - u32 flow_id; - u32 app_id; - u32 error; -} dpi_rx_trace_t; - -/* *INDENT-OFF* */ -VNET_FEATURE_INIT (dpi4_input, static) = -{ - .arc_name = "ip4-unicast", - .node_name = "dpi4-input", - .runs_before = VNET_FEATURES ("ip4-lookup"), -}; - -VNET_FEATURE_INIT (dpi6_input, static) = -{ - .arc_name = "ip6-unicast", - .node_name = "dpi6-input", - .runs_before = VNET_FEATURES ("ip6-lookup"), -}; -/* *INDENT-on* */ - -static u8 * -format_dpi_rx_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - dpi_rx_trace_t *t = va_arg (*args, dpi_rx_trace_t *); - - if (t->flow_id == ~0) - return format (s, "DPI error - flow %d does not exist", - t->flow_id); - - return format (s, "DPI from flow %d app_id %d next %d error %d", - t->flow_id, t->app_id, t->next_index, t->error); -} - - - -static inline int -parse_ip4_packet_and_lookup (ip4_header_t * ip4, u32 fib_index, - dpi4_flow_key_t * key4, - int * not_found, u64 * flow_id) -{ - dpi_main_t *dm = &dpi_main; - u8 protocol = ip4_is_fragment (ip4) ? 0xfe : ip4->protocol; - u16 src_port = 0; - u16 dst_port = 0; - dpi_flow_entry_t *flow; - - key4->key[0] = ip4->src_address.as_u32 - | (((u64) ip4->dst_address.as_u32) << 32); - - if (protocol == IP_PROTOCOL_UDP || protocol == IP_PROTOCOL_TCP) - { - /* tcp and udp ports have the same offset */ - udp_header_t * udp = ip4_next_header (ip4); - src_port = udp->src_port; - dst_port = udp->dst_port; - } - - key4->key[1] = (((u64) protocol) << 32) | ((u32) src_port << 16) | dst_port; - key4->key[2] = (u64) fib_index; - - key4->value = ~0; - *not_found = clib_bihash_search_inline_24_8 (&dm->dpi4_flow_by_key, key4); - *flow_id = key4->value; - - /* not found, then create new SW flow dynamically */ - if (*not_found) - { - int add_failed; - pool_get_aligned(dm->dpi_flows, flow, CLIB_CACHE_LINE_BYTES); - clib_memset(flow, 0, sizeof(*flow)); - *flow_id = flow - dm->dpi_flows; - - flow->next_index = DPI_INPUT_NEXT_IP4_LOOKUP; - flow->flow_index = ~0; - - pool_get_aligned(dm->dpi_infos, flow->info, CLIB_CACHE_LINE_BYTES); - clib_memset(flow->info, 0, sizeof(*flow->info)); - flow->info->app_id = ~0; - - /* Add forwarding flow entry */ - key4->value = *flow_id; - add_failed = clib_bihash_add_del_24_8 (&dm->dpi4_flow_by_key, key4, - 1 /*add */); - - if (add_failed) - { - pool_put(dm->dpi_infos, flow->info); - pool_put(dm->dpi_flows, flow); - return -1; - } - - /* Add reverse flow entry*/ - key4->key[0] = ip4->dst_address.as_u32 - | (((u64) ip4->src_address.as_u32) << 32); - key4->key[1] = (((u64) protocol) << 32) | ((u32) dst_port << 16) - | src_port; - key4->key[2] = (u64) fib_index; - key4->value = (u64) flow_id | ((u64) 1 << 63); - add_failed = clib_bihash_add_del_24_8 (&dm->dpi4_flow_by_key, key4, - 1 /*add */); - - if (add_failed) - { - pool_put(dm->dpi_infos, flow->info); - pool_put(dm->dpi_flows, flow); - return -1; - } - - /* Open a Hyperscan stream for each flow */ - hs_error_t err = hs_open_stream (dm->default_db.database, 0, - &(flow->info->stream)); - - if (err != HS_SUCCESS) - { - pool_put(dm->dpi_infos, flow->info); - pool_put(dm->dpi_flows, flow); - return -1; - } - } - - return 0; -} - -static inline int -parse_ip6_packet_and_lookup (ip6_header_t * ip6, u32 fib_index, - dpi6_flow_key_t * key6, - int * not_found, u64 * flow_id) -{ - dpi_main_t *dm = &dpi_main; - u8 protocol = ip6->protocol; - u16 src_port = 0; - u16 dst_port = 0; - dpi_flow_entry_t *flow; - - key6->key[0] = ip6->src_address.as_u64[0]; - key6->key[1] = ip6->src_address.as_u64[1]; - key6->key[2] = ip6->dst_address.as_u64[0]; - key6->key[3] = ip6->dst_address.as_u64[1]; - - if (protocol == IP_PROTOCOL_UDP || protocol == IP_PROTOCOL_TCP) - { - /* tcp and udp ports have the same offset */ - udp_header_t * udp = ip6_next_header(ip6); - src_port = udp->src_port; - dst_port = udp->dst_port; - } - - key6->key[4] = (((u64) protocol) << 32) - | ((u32) src_port << 16) - | dst_port; - key6->key[5] = (u64) fib_index; - - key6->value = ~0; - *not_found = clib_bihash_search_inline_48_8 (&dm->dpi6_flow_by_key, key6); - *flow_id = key6->value; - - /* not found, then create new SW flow dynamically */ - if (*not_found) - { - int add_failed; - pool_get_aligned(dm->dpi_flows, flow, CLIB_CACHE_LINE_BYTES); - clib_memset(flow, 0, sizeof(*flow)); - *flow_id = flow - dm->dpi_flows; - - flow->next_index = DPI_INPUT_NEXT_IP4_LOOKUP; - flow->flow_index = ~0; - - pool_get_aligned(dm->dpi_infos, flow->info, CLIB_CACHE_LINE_BYTES); - clib_memset(flow->info, 0, sizeof(*flow->info)); - flow->info->app_id = ~0; - - /* Add forwarding flow entry */ - key6->value = (u64) flow_id; - add_failed = clib_bihash_add_del_48_8 (&dm->dpi6_flow_by_key, - key6, 1 /*add */ ); - if (add_failed) - { - pool_put(dm->dpi_infos, flow->info); - pool_put(dm->dpi_flows, flow); - return -1; - } - - /* Add reverse flow entry*/ - key6->key[0] = ip6->dst_address.as_u64[0]; - key6->key[1] = ip6->dst_address.as_u64[1]; - key6->key[2] = ip6->src_address.as_u64[0]; - key6->key[3] = ip6->src_address.as_u64[1]; - key6->key[4] = (((u64) protocol) << 32) - | ((u32) dst_port << 16) - | src_port; - key6->key[5] = (u64) fib_index; - key6->value = (u64) flow_id | ((u64) 1 << 63); - add_failed = clib_bihash_add_del_48_8 (&dm->dpi6_flow_by_key, - key6, 1 /*add */ ); - - if (add_failed) - { - pool_put(dm->dpi_infos, flow->info); - pool_put(dm->dpi_flows, flow); - return -1; - } - - /* Open a Hyperscan stream for each flow */ - hs_error_t err = hs_open_stream (dm->default_db.database, 0, - &(flow->info->stream)); - - if (err != HS_SUCCESS) - { - pool_put(dm->dpi_infos, flow->info); - pool_put(dm->dpi_flows, flow); - return -1; - } - } - - return 0; -} - -static inline void -dpi_trim_overlap(u32 left_sn, segment *seg) -{ - int overlap_len; - - overlap_len = left_sn - seg->send_sn; - /* trim leading overlap bytes */ - seg->data += overlap_len; - seg->len -= overlap_len; - seg->send_sn += overlap_len; - - /* trim the right overlap bytes */ - if( seg->next - && (seg->send_sn+seg->len) > (seg->next->send_sn) ) - { - overlap_len = (seg->send_sn+seg->len) - (seg->next->send_sn); - if(seg->len > overlap_len) - { - seg->len -= overlap_len; - } - } -} - -/* - * re-order out-of-order segments, and handle overlap segments. - * */ -static inline void -dpi_handle_tcp_segments (dpi_flow_entry_t *flow, tcp_stream_t *stream, - u32 bi, u8 *pkt, u32 payload_len) -{ - dpi_main_t *dm = &dpi_main; - u32 send_sn; - u32 ack_sn; - u32 next_sn; - u32 left_sn; - segment *first_seg = 0; - segment *seg = 0; - segment *new_seg = 0; - tcp_header_t *tcp = (tcp_header_t *)pkt; - u8 *payload = pkt + tcp_doff(tcp) * 4; - - if((tcp->flags & TCP_FLAG_ACK) == TCP_FLAG_ACK) - { - ack_sn = clib_net_to_host_u32(tcp->ack_number); - if(ack_sn != stream->ack_sn) - { - stream->ack_sn = ack_sn; - } - } - - send_sn = clib_net_to_host_u32(tcp->seq_number); - next_sn = send_sn + payload_len; - - /* Handle fully overlapping segments */ - if(SN_GT(stream->send_sn, next_sn)) - { - flow->consumed = 1; - return; - } - - if(SN_LT(stream->send_sn, send_sn)) - { - /* Store out-of-order segments to segment queue */ - for(seg=stream->seg_queue; seg; seg=seg->next) - { - if (send_sn < seg->send_sn ) - break; - } - - pool_get_aligned (dm->seg_pool, new_seg, CLIB_CACHE_LINE_BYTES); - new_seg->bi = bi; - new_seg->send_sn = send_sn; - new_seg->data = payload; - new_seg->len = payload_len; - - /* Insert new segment to right position of segment queue */ - if(seg == stream->seg_queue) - { - new_seg->next = stream->seg_queue; - stream->seg_queue = new_seg; - stream->send_sn = seg->send_sn; - left_sn = stream->send_sn; - } - else - { - new_seg->next = seg->next; - seg->next = new_seg; - left_sn = seg->send_sn; - } - - /* trim overlapped packet */ - dpi_trim_overlap(left_sn, new_seg); - - flow->consumed = 1; - } - else - { - pool_get_aligned(dm->seg_pool, first_seg, CLIB_CACHE_LINE_BYTES); - first_seg->bi = bi; - first_seg->send_sn = send_sn; - first_seg->data = payload; - first_seg->len = payload_len; - first_seg->next = stream->seg_queue; - - /* trim overlapped packet */ - dpi_trim_overlap (stream->send_sn, first_seg); - - /* reassemble continuous segments and move forward to scan */ - for (seg = first_seg; seg->next; seg = seg->next) - { - if (seg->send_sn + seg->len != seg->next->send_sn) - break; - } - - /* left non-continuous segments */ - stream->seg_queue = seg->next; - stream->send_sn = seg->send_sn + seg->len; - - flow->first_seg = first_seg; - seg->next = 0; - - /* scan ordered segments */ - for (seg = first_seg; seg; seg = seg->next) - { - /* detect layer 7 application for single segment */ - dpi_detect_application (seg->data, seg->len, flow->info); - if(flow->info->detect_done) - break; - } - } -} - -static inline int -dpi_handle_tcp_stream (dpi_flow_entry_t *flow, u32 bi, - u8 *pkt, u32 payload_len, u8 is_reverse) -{ - tcp_header_t *tcp; - tcp_stream_t *stream; - - tcp = (tcp_header_t *)pkt; - if((tcp->flags & (TCP_FLAG_SYN|TCP_FLAG_ACK)) == TCP_FLAG_SYN) - { - flow->c2s.send_sn = clib_net_to_host_u32(tcp->seq_number) + 1; - flow->pkt_dir = DIR_C2S; - flow->forward_is_c2s = !is_reverse; - flow->tcp_state = TCP_STATE_SYN; - } - else - { - /* - forward_is_c2s | is_reverse - 0 1 - 0 s2c(1) c2s(0) - 1 c2s(0) s2c(1) - */ - flow->pkt_dir = (flow->forward_is_c2s == is_reverse); - } - - switch(flow->tcp_state) - { - case TCP_STATE_SYN: - { - if(flow->pkt_dir != DIR_S2C) - break; - - if((tcp->flags & (TCP_FLAG_SYN|TCP_FLAG_ACK)) - != (TCP_FLAG_SYN|TCP_FLAG_ACK)) - break; - - flow->s2c.send_sn = clib_net_to_host_u32(tcp->seq_number) + 1; - flow->s2c.ack_sn = clib_net_to_host_u32(tcp->ack_number) + 1; - flow->tcp_state = TCP_STATE_SYN_ACK; - break; - } - - case TCP_STATE_SYN_ACK: - { - if(flow->pkt_dir != DIR_C2S) - break; - - flow->c2s.ack_sn = clib_net_to_host_u32(tcp->ack_number) + 1; - flow->tcp_state = TCP_STATE_ESTABLISH; - break; - } - - case TCP_STATE_ACK: - case TCP_STATE_ESTABLISH: - case TCP_STATE_FIN1: - { - stream = (flow->pkt_dir == DIR_C2S)? &(flow->c2s) : &(flow->s2c); - if( (flow->reass_dir == REASS_BOTH) - || ((flow->pkt_dir==DIR_C2S) && (flow->reass_dir==REASS_C2S)) - || ((flow->pkt_dir==DIR_S2C) && (flow->reass_dir==REASS_S2C)) ) - { - dpi_handle_tcp_segments(flow, stream, bi, pkt, payload_len); - } - - break; - } - - case TCP_STATE_CLOSE: - { - /* Free all segments in the queue */ - break; - } - } - - return 0; -} - -void -dpi_detect_application (u8 *payload, u32 payload_len, - dpi_flow_info_t *flow) -{ - - /* detect if payload is SSL's payload for default port */ - dpi_search_tcp_ssl(payload, payload_len, flow); - - /* TBD: add detect if is SSL's payload with non default port*/ - -} - -always_inline uword -dpi_input_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame, u32 is_ip4) -{ - dpi_main_t *dm = &dpi_main; - u32 *from, *to_next, n_left_from, n_left_to_next, next_index; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 bi0, next0 = 0; - vlib_buffer_t *b0; - ip4_header_t *ip40; - ip6_header_t *ip60; - tcp_header_t *tcp0; - udp_header_t *udp0; - dpi4_flow_key_t key40; - dpi6_flow_key_t key60; - u32 fib_index0 = ~0; - u64 flow_id0 = ~0; - u32 flow_index0 = ~0; - int not_found0 = 0; - u8 is_reverse0 = 0; - dpi_flow_entry_t *flow0 = 0; - u32 ip_len0, l4_len0, payload_len0; - u8 protocol0; - u8 *l4_pkt0, *payload0; - u16 dst_port = 0; - segment *seg = 0; - segment *prev_seg = 0; - - bi0 = to_next[0] = from[0]; - b0 = vlib_get_buffer (vm, bi0); - ip_len0 = vlib_buffer_length_in_chain (vm, b0); - - if (is_ip4) - { - ip40 = vlib_buffer_get_current (b0); - ip4_main_t *im4 = &ip4_main; - fib_index0 = vec_elt (im4->fib_index_by_sw_if_index, - vnet_buffer(b0)->sw_if_index[VLIB_RX]); - parse_ip4_packet_and_lookup(ip40, fib_index0, &key40, - ¬_found0, &flow_id0); - } - else - { - ip60 = vlib_buffer_get_current (b0); - ip6_main_t *im6 = &ip6_main; - fib_index0 = vec_elt (im6->fib_index_by_sw_if_index, - vnet_buffer(b0)->sw_if_index[VLIB_RX]); - parse_ip6_packet_and_lookup(ip60, fib_index0, &key60, - ¬_found0, &flow_id0); - } - - is_reverse0 = (u8)((flow_id0 >> 63) & 0x1); - flow_index0 = (u32)(flow_id0 & (u32)(~0)); - flow0 = pool_elt_at_index (dm->dpi_flows, flow_index0); - /* have detected successfully, directly return */ - if(flow0->info->detect_done) - goto enqueue0; - - /* check layer4 */ - if (is_ip4) - { - l4_pkt0 = (u8 *)(ip40 + 1); - l4_len0 = ip_len0 - sizeof(ip4_header_t); - protocol0 = ip40->protocol; - } - else - { - l4_pkt0 = (u8 *)(ip60 + 1); - l4_len0 = ip_len0 - sizeof(ip6_header_t); - protocol0 = ip60->protocol; - } - - if((protocol0 == IP_PROTOCOL_TCP) && (l4_len0 >= 20)) - { - tcp0 = (tcp_header_t *)l4_pkt0; - payload_len0 = l4_len0 - tcp_doff(tcp0) * 4; - payload0 = l4_pkt0 + tcp_doff(tcp0) * 4; - dst_port = tcp0->dst_port; - } - else if ((protocol0 == IP_PROTOCOL_UDP) && (l4_len0 >= 8)) - { - udp0 = (udp_header_t *)l4_pkt0; - payload_len0 = l4_len0 - sizeof(udp_header_t); - payload0 = l4_pkt0 + sizeof(udp_header_t); - dst_port = udp0->dst_port; - } - else - { - payload_len0 = l4_len0; - payload0 = l4_pkt0; - } - - flow0->info->l4_protocol = protocol0; - flow0->info->dst_port = dst_port; - - /* TCP stream reassembly and detect a protocol pdu */ - if((protocol0 == IP_PROTOCOL_TCP) && (flow0->reass_en)) - { - dpi_handle_tcp_stream(flow0, bi0, l4_pkt0, payload_len0, is_reverse0); - - /* This packet has been consumed, retrieve next packet */ - if(flow0->consumed) - goto trace0; - - /* send out continuous scanned segments */ - seg=flow0->first_seg; - dpi_enqueue_tcp_segments(seg,vm,node,next_index,to_next,n_left_to_next,bi0,next0); - flow0->first_seg = 0; - - /* Here detected successfully, send out remaining segments in seg_queue */ - if(flow0->info->detect_done) - { - seg=flow0->c2s.seg_queue; - dpi_enqueue_tcp_segments(seg,vm,node,next_index,to_next,n_left_to_next,bi0,next0); - flow0->c2s.seg_queue = 0; - - seg=flow0->s2c.seg_queue; - dpi_enqueue_tcp_segments(seg,vm,node,next_index,to_next,n_left_to_next,bi0,next0); - flow0->s2c.seg_queue = 0; - } - goto trace0; - } - else - { - /* detect layer 7 application for single packet */ - dpi_detect_application (payload0, payload_len0, flow0->info); - } - -enqueue0: - to_next[0] = bi0; - to_next++; - n_left_to_next--; - next0 = flow0->next_index; - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); - -trace0: - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - dpi_rx_trace_t *tr - = vlib_add_trace (vm, node, b0, sizeof (*tr)); - tr->app_id = flow0->info->app_id; - tr->next_index = next0; - tr->error = b0->error; - tr->flow_id = flow_index0; - } - - from += 1; - n_left_from -= 1; - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return frame->n_vectors; -} - -VLIB_NODE_FN (dpi4_input_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dpi_input_inline (vm, node, frame, /* is_ip4 */ 1); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dpi4_input_node) = -{ - .name = "dpi4-input", - .vector_size = sizeof (u32), - .n_errors = DPI_INPUT_N_ERROR, - .error_strings = dpi_input_error_strings, - .n_next_nodes = DPI_INPUT_N_NEXT, - .next_nodes = { -#define _(s,n) [DPI_INPUT_NEXT_##s] = n, - foreach_dpi_input_next -#undef _ - }, - .format_trace = format_dpi_rx_trace, -}; - -/* *INDENT-ON* */ - -/* Dummy init function to get us linked in. */ -static clib_error_t * -dpi4_input_init (vlib_main_t * vm) -{ - return 0; -} - -VLIB_INIT_FUNCTION (dpi4_input_init); - - -VLIB_NODE_FN (dpi6_input_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dpi_input_inline (vm, node, frame, /* is_ip4 */ 0); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dpi6_input_node) = -{ - .name = "dpi6-input", - .vector_size = sizeof (u32), - .n_errors = DPI_INPUT_N_ERROR, - .error_strings = dpi_input_error_strings, - .n_next_nodes = DPI_INPUT_N_NEXT, - .next_nodes = { -#define _(s,n) [DPI_INPUT_NEXT_##s] = n, - foreach_dpi_input_next -#undef _ - }, - .format_trace = format_dpi_rx_trace, -}; -/* *INDENT-ON* */ - -/* Dummy init function to get us linked in. */ -static clib_error_t * -dpi6_input_init (vlib_main_t * vm) -{ - return 0; -} - -VLIB_INIT_FUNCTION (dpi6_input_init); - - - -#define foreach_dpi_flow_input_next \ -_(DROP, "error-drop") \ -_(IP4_LOOKUP, "ip4-lookup") - -typedef enum -{ -#define _(s,n) DPI_FLOW_NEXT_##s, - foreach_dpi_flow_input_next -#undef _ - DPI_FLOW_N_NEXT, -} dpi_flow_input_next_t; - -#define foreach_dpi_flow_error \ - _(NONE, "no error") \ - _(IP_CHECKSUM_ERROR, "Rx ip checksum errors") \ - _(IP_HEADER_ERROR, "Rx ip header errors") \ - _(UDP_CHECKSUM_ERROR, "Rx udp checksum errors") \ - _(UDP_LENGTH_ERROR, "Rx udp length errors") - -typedef enum -{ -#define _(f,s) DPI_FLOW_ERROR_##f, - foreach_dpi_flow_error -#undef _ - DPI_FLOW_N_ERROR, -} dpi_flow_error_t; - -static char *dpi_flow_error_strings[] = { -#define _(n,s) s, - foreach_dpi_flow_error -#undef _ -}; - -static_always_inline u8 -dpi_check_ip4 (ip4_header_t * ip4, u16 payload_len) -{ - u16 ip_len = clib_net_to_host_u16 (ip4->length); - return ip_len > payload_len || ip4->ttl == 0 - || ip4->ip_version_and_header_length != 0x45; -} - -static_always_inline u8 -dpi_check_ip6 (ip6_header_t * ip6, u16 payload_len) -{ - u16 ip_len = clib_net_to_host_u16 (ip6->payload_length); - return ip_len > (payload_len - sizeof (ip6_header_t)) - || ip6->hop_limit == 0 - || (ip6->ip_version_traffic_class_and_flow_label >> 28) != 0x6; -} - -always_inline uword -dpi_flow_input_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame, u32 is_ip4) -{ - dpi_main_t *dm = &dpi_main; - u32 *from, *to_next, n_left_from, n_left_to_next, next_index; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 bi0, next0 = DPI_FLOW_NEXT_IP4_LOOKUP; - vlib_buffer_t *b0; - ip4_header_t *ip40; - ip6_header_t *ip60; - tcp_header_t *tcp0; - udp_header_t *udp0; - u32 flow_id0 = ~0; - u32 flow_index0 = ~0; - u32 is_reverse0 = 0; - dpi_flow_entry_t *flow0; - u32 ip_len0, l4_len0, payload_len0; - u8 protocol0; - u8 *l4_pkt0, *payload0; - u16 dst_port = 0; - segment *seg = 0; - segment *prev_seg = 0; - - bi0 = to_next[0] = from[0]; - b0 = vlib_get_buffer (vm, bi0); - ip_len0 = vlib_buffer_length_in_chain (vm, b0); - - if (is_ip4) - { - ip40 = vlib_buffer_get_current (b0); - dpi_check_ip4 (ip40, ip_len0); - } - else - { - ip60 = vlib_buffer_get_current (b0); - dpi_check_ip6 (ip60, ip_len0); - } - - ASSERT (b0->flow_id != 0); - flow_id0 = b0->flow_id - dm->flow_id_start; - - is_reverse0 = (u32) ((flow_id0 >> 31) & 0x1); - flow_index0 = (u32) (flow_id0 & (u32) (~(1 << 31))); - flow0 = pool_elt_at_index (dm->dpi_flows, flow_index0); - - /* have detected successfully, directly return */ - if (flow0->info->detect_done) - goto enqueue0; - - /* check layer4 */ - if (is_ip4) - { - l4_pkt0 = (u8 *) (ip40 + 1); - l4_len0 = ip_len0 - sizeof (ip4_header_t); - protocol0 = ip40->protocol; - } - else - { - l4_pkt0 = (u8 *) (ip60 + 1); - l4_len0 = ip_len0 - sizeof (ip6_header_t); - protocol0 = ip60->protocol; - } - - if ((protocol0 == IP_PROTOCOL_TCP) && (l4_len0 >= 20)) - { - tcp0 = (tcp_header_t *) l4_pkt0; - payload_len0 = l4_len0 - tcp_doff (tcp0) * 4; - payload0 = l4_pkt0 + tcp_doff (tcp0) * 4; - dst_port = tcp0->dst_port; - } - else if ((protocol0 == IP_PROTOCOL_UDP) && (l4_len0 >= 8)) - { - udp0 = (udp_header_t *) l4_pkt0; - payload_len0 = l4_len0 - sizeof (udp_header_t); - payload0 = l4_pkt0 + sizeof (udp_header_t); - dst_port = udp0->dst_port; - } - else - { - payload_len0 = l4_len0; - payload0 = l4_pkt0; - } - - flow0->info->l4_protocol = protocol0; - flow0->info->dst_port = dst_port; - - /* TCP stream reassembly and detect a protocol pdu */ - if ((protocol0 == IP_PROTOCOL_TCP) && (flow0->reass_en)) - { - dpi_handle_tcp_stream (flow0, bi0, l4_pkt0, payload_len0, - is_reverse0); - - /* This packet has been consumed, retrieve next packet */ - if (flow0->consumed) - goto trace0; - - /* send out continuous scanned segments */ - seg = flow0->first_seg; - dpi_enqueue_tcp_segments (seg, vm, node, next_index, to_next, - n_left_to_next, bi0, next0); - flow0->first_seg = 0; - - /* Here detected successfully, send out remaining segments in seg_queue */ - if (flow0->info->detect_done) - { - seg = flow0->c2s.seg_queue; - dpi_enqueue_tcp_segments (seg, vm, node, next_index, - to_next, n_left_to_next, bi0, - next0); - flow0->c2s.seg_queue = 0; - - seg = flow0->s2c.seg_queue; - dpi_enqueue_tcp_segments (seg, vm, node, next_index, - to_next, n_left_to_next, bi0, - next0); - flow0->s2c.seg_queue = 0; - } - goto trace0; - } - else - { - /* detect layer 7 application for single packet */ - dpi_detect_application (payload0, payload_len0, flow0->info); - } - -enqueue0: - to_next[0] = bi0; - to_next++; - n_left_to_next--; - next0 = flow0->next_index; - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); - -trace0: - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - dpi_rx_trace_t *tr - = vlib_add_trace (vm, node, b0, sizeof (*tr)); - tr->app_id = flow0->info->app_id; - tr->next_index = next0; - tr->error = b0->error; - tr->flow_id = flow_index0; - } - - from += 1; - n_left_from -= 1; - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return frame->n_vectors; -} - - -VLIB_NODE_FN (dpi4_flow_input_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dpi_flow_input_inline (vm, node, frame, /* is_ip4 */ 1); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dpi4_flow_input_node) = { - .name = "dpi4-flow-input", - .type = VLIB_NODE_TYPE_INTERNAL, - .vector_size = sizeof (u32), - - .format_trace = format_dpi_rx_trace, - - .n_errors = DPI_FLOW_N_ERROR, - .error_strings = dpi_flow_error_strings, - - .n_next_nodes = DPI_FLOW_N_NEXT, - .next_nodes = { -#define _(s,n) [DPI_FLOW_NEXT_##s] = n, - foreach_dpi_flow_input_next -#undef _ - }, -}; -/* *INDENT-ON* */ - -/* Dummy init function to get us linked in. */ -static clib_error_t * -dpi4_flow_input_init (vlib_main_t * vm) -{ - return 0; -} - -VLIB_INIT_FUNCTION (dpi4_flow_input_init); - -VLIB_NODE_FN (dpi6_flow_input_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dpi_flow_input_inline (vm, node, frame, /* is_ip4 */ 0); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dpi6_flow_input_node) = { - .name = "dpi6-flow-input", - .type = VLIB_NODE_TYPE_INTERNAL, - .vector_size = sizeof (u32), - - .format_trace = format_dpi_rx_trace, - - .n_errors = DPI_FLOW_N_ERROR, - .error_strings = dpi_flow_error_strings, - - .n_next_nodes = DPI_FLOW_N_NEXT, - .next_nodes = { -#define _(s,n) [DPI_FLOW_NEXT_##s] = n, - foreach_dpi_flow_input_next -#undef _ - }, -}; -/* *INDENT-ON* */ - -/* Dummy init function to get us linked in. */ -static clib_error_t * -dpi6_flow_input_init (vlib_main_t * vm) -{ - return 0; -} - -VLIB_INIT_FUNCTION (dpi6_flow_input_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ -- cgit 1.2.3-korg