diff --git a/patches/vpp/multi-snort-instance.patch b/patches/vpp/multi-snort-instance.patch new file mode 100644 index 0000000000000000000000000000000000000000..8b5b48eac98eb4027961a991749424f9575a1955 --- /dev/null +++ b/patches/vpp/multi-snort-instance.patch @@ -0,0 +1,192 @@ +diff --git a/src/plugins/snort/enqueue.c b/src/plugins/snort/enqueue.c +index 409c0e490..dfb1bc132 100644 +--- a/src/plugins/snort/enqueue.c ++++ b/src/plugins/snort/enqueue.c +@@ -4,6 +4,7 @@ + + #include + #include ++#include + #include + + typedef struct +@@ -56,6 +57,24 @@ static char *snort_enq_error_strings[] = { + #undef _ + }; + ++/* Five tuple informations */ ++typedef struct { ++ u32 src_ip; ++ u32 dst_ip; ++ u8 proto; ++ u16 src_port; ++ u16 dst_port; ++} snort_flow_t; ++ ++static_always_inline u16 snort_get_flow_hash(snort_flow_t *flow) ++{ ++ u16 hash; ++ ++ hash = ((flow->src_ip >> 16) ^ (flow->src_ip) ^ (flow->dst_ip >> 16) ^ (flow->dst_ip) ^ (flow->proto) ^ (flow->src_port) ^ (flow->dst_port)) & 0xFFFF; ++ ++ return hash; ++} ++ + static_always_inline uword + snort_enq_node_inline (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame, int with_trace) +@@ -63,13 +82,18 @@ snort_enq_node_inline (vlib_main_t *vm, vlib_node_runtime_t *node, + snort_main_t *sm = &snort_main; + snort_instance_t *si = 0; + snort_qpair_t *qp = 0; ++ ip4_header_t *ip_hdr; ++ snort_flow_t snort_flow; + u32 thread_index = vm->thread_index; + u32 n_left = frame->n_vectors; + u32 n_trace = 0; ++ u32 *snort_index; ++ u32 lb_index; + u32 total_enq = 0, n_processed = 0; + u32 *from = vlib_frame_vector_args (frame); + vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs; + u16 nexts[VLIB_FRAME_SIZE], *next = nexts; ++ u16 flow_hash; + + vlib_get_buffers (vm, from, bufs, n_left); + +@@ -85,6 +109,27 @@ snort_enq_node_inline (vlib_main_t *vm, vlib_node_runtime_t *node, + instance_index = (u32) (fa_data & 0xffffffff); + l3_offset = + (fa_data >> 32) ? vnet_buffer (b[0])->ip.save_rewrite_length : 0; ++ ++ ip_hdr = vlib_buffer_get_current(b[0]); ++ snort_flow.src_ip = htonl(ip_hdr->src_address.data_u32); ++ snort_flow.dst_ip = htonl(ip_hdr->dst_address.data_u32); ++ snort_flow.proto = ip_hdr->protocol; ++ if (snort_flow.proto == 0x06 || snort_flow.proto == 0x11 || ++ snort_flow.proto == 0xAC || snort_flow.proto == 0x3D || ++ snort_flow.proto == 0x84) { ++ u8 *tmp_l4_hdr = (u8 *)ip_hdr; ++ tmp_l4_hdr += (ip_hdr->ip_version_and_header_length & 0x0F) << 2; ++ snort_flow.src_port = (tmp_l4_hdr[0] << 8) | (tmp_l4_hdr[1]); ++ snort_flow.dst_port = (tmp_l4_hdr[2] << 8) | (tmp_l4_hdr[3]); ++ } else { ++ snort_flow.src_port = 0; ++ snort_flow.dst_port = 0; ++ } ++ ++ flow_hash = snort_get_flow_hash(&snort_flow); ++ lb_index = flow_hash % vec_len(sm->attached_instances); ++ snort_index = vec_elt_at_index (sm->attached_instances, lb_index); ++ instance_index = *snort_index; + si = vec_elt_at_index (sm->instances, instance_index); + + /* if client isn't connected skip enqueue and take default action */ +diff --git a/src/plugins/snort/main.c b/src/plugins/snort/main.c +index 2430fcdc5..31ca22eb5 100644 +--- a/src/plugins/snort/main.c ++++ b/src/plugins/snort/main.c +@@ -409,6 +409,37 @@ done: + return err; + } + ++static inline int snort_instance_not_attached(u32 index) ++{ ++ snort_main_t *sm = &snort_main; ++ u32 num_instances = vec_len(sm->attached_instances); ++ u32 *si; ++ u32 i; ++ ++ for (i = 0; i < num_instances; i++) ++ { ++ si = vec_elt_at_index (sm->attached_instances, i); ++ if (index == *si) ++ { ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++static inline int snort_instance_attach(u32 index) ++{ ++ snort_main_t *sm = &snort_main; ++ u32 *si; ++ ++ ++ pool_get_zero (sm->attached_instances, si); ++ *si = index; ++ ++ return 0; ++} ++ + clib_error_t * + snort_interface_enable_disable (vlib_main_t *vm, char *instance_name, + u32 sw_if_index, int is_enable, +@@ -431,31 +462,34 @@ snort_interface_enable_disable (vlib_main_t *vm, char *instance_name, + + vec_validate_init_empty (sm->instance_by_sw_if_index, sw_if_index, ~0); + ++ if (snort_instance_not_attached(si->index) == 0) { ++ if (snort_instance_attach(si->index) != 0) { ++ err = clib_error_return (0, "Unable to attache instance %s", instance_name); ++ goto done; ++ } ++ } ++ + index = sm->instance_by_sw_if_index[sw_if_index]; +- if (index != ~0) ++ if (index == 0) + { +- si = vec_elt_at_index (sm->instances, index); +- err = clib_error_return (0, +- "interface %U already assgined to " +- "instance '%s'", +- format_vnet_sw_if_index_name, vnm, +- sw_if_index, si->name); +- goto done; ++ sm->instance_by_sw_if_index[sw_if_index] = si->index; + } + +- index = sm->instance_by_sw_if_index[sw_if_index] = si->index; +- if (snort_dir & SNORT_INPUT) +- { +- fa_data = (u64) index; +- vnet_feature_enable_disable ("ip4-unicast", "snort-enq", sw_if_index, ++ index = si->index; ++ if (vec_len(sm->attached_instances) == 1) { ++ if (snort_dir & SNORT_INPUT) ++ { ++ fa_data = (u64) index; ++ vnet_feature_enable_disable ("ip4-unicast", "snort-enq", sw_if_index, + 1, &fa_data, sizeof (fa_data)); +- } +- if (snort_dir & SNORT_OUTPUT) +- { +- fa_data = (1LL << 32 | index); +- vnet_feature_enable_disable ("ip4-output", "snort-enq", sw_if_index, ++ } ++ if (snort_dir & SNORT_OUTPUT) ++ { ++ fa_data = (1LL << 32 | index); ++ vnet_feature_enable_disable ("ip4-output", "snort-enq", sw_if_index, + 1, &fa_data, sizeof (fa_data)); +- } ++ } ++ } + } + else + { +diff --git a/src/plugins/snort/snort.h b/src/plugins/snort/snort.h +index 79299aa6d..fdbdade04 100644 +--- a/src/plugins/snort/snort.h ++++ b/src/plugins/snort/snort.h +@@ -77,6 +77,7 @@ typedef struct + u8 **buffer_pool_base_addrs; + snort_per_thread_data_t *per_thread_data; + u32 input_mode; ++ u32 *attached_instances; + u8 *socket_name; + } snort_main_t; +