Clean up old datapath code in ACL plugin.
Change-Id: I3d64d5ced38a68f3fa208be00c49d20c4e6d4d0e Signed-off-by: Andrew Yourtchenko <ayourtch@gmail.com>
This commit is contained in:
committed by
Damjan Marion
parent
0bc5063ae9
commit
24beb84040
@@ -16,11 +16,7 @@ vppplugins_LTLIBRARIES += acl_plugin.la
|
||||
|
||||
acl_plugin_la_SOURCES = \
|
||||
acl/acl.c \
|
||||
acl/node_in.c \
|
||||
acl/node_out.c \
|
||||
acl/fa_node.c \
|
||||
acl/l2sess.c \
|
||||
acl/l2sess_node.c \
|
||||
acl/l2sess.h \
|
||||
acl/manual_fns.h \
|
||||
acl/acl_plugin.api.h
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,6 +30,10 @@
|
||||
#define ACL_PLUGIN_VERSION_MAJOR 1
|
||||
#define ACL_PLUGIN_VERSION_MINOR 2
|
||||
|
||||
#define UDP_SESSION_IDLE_TIMEOUT_SEC 600
|
||||
#define TCP_SESSION_IDLE_TIMEOUT_SEC (3600*24)
|
||||
#define TCP_SESSION_TRANSIENT_TIMEOUT_SEC 120
|
||||
|
||||
extern vlib_node_registration_t acl_in_node;
|
||||
extern vlib_node_registration_t acl_out_node;
|
||||
|
||||
@@ -128,22 +132,6 @@ typedef struct {
|
||||
/* MACIP (input) ACLs associated with the interfaces */
|
||||
u32 *macip_acl_by_sw_if_index;
|
||||
|
||||
/* next indices for our nodes in the l2-classify tables */
|
||||
u32 l2_input_classify_next_acl_old;
|
||||
u32 l2_output_classify_next_acl_old;
|
||||
|
||||
/* next node indices for feature bitmap */
|
||||
u32 acl_in_node_feat_next_node_index[32];
|
||||
u32 acl_out_node_feat_next_node_index[32];
|
||||
|
||||
/* ACL match actions (must be coherent across in/out ACLs to next indices (can differ) */
|
||||
|
||||
u32 acl_in_ip4_match_next[256];
|
||||
u32 acl_in_ip6_match_next[256];
|
||||
u32 acl_out_ip4_match_next[256];
|
||||
u32 acl_out_ip6_match_next[256];
|
||||
u32 n_match_actions;
|
||||
|
||||
/* bitmaps when set the processing is enabled on the interface */
|
||||
uword *fa_in_acl_on_sw_if_index;
|
||||
uword *fa_out_acl_on_sw_if_index;
|
||||
@@ -162,16 +150,11 @@ typedef struct {
|
||||
|
||||
/* L2 datapath glue */
|
||||
|
||||
/* active next indices within L2 classifiers - switch old/new path */
|
||||
/* next indices within L2 classifiers for ip4/ip6 fa L2 nodes */
|
||||
u32 l2_input_classify_next_acl_ip4;
|
||||
u32 l2_input_classify_next_acl_ip6;
|
||||
u32 l2_output_classify_next_acl_ip4;
|
||||
u32 l2_output_classify_next_acl_ip6;
|
||||
/* saved next indices within L2 classifiers for ip4/ip6 fa L2 nodes */
|
||||
u32 fa_l2_input_classify_next_acl_ip4;
|
||||
u32 fa_l2_input_classify_next_acl_ip6;
|
||||
u32 fa_l2_output_classify_next_acl_ip4;
|
||||
u32 fa_l2_output_classify_next_acl_ip6;
|
||||
/* next node indices for L2 dispatch */
|
||||
u32 fa_acl_in_ip4_l2_node_feat_next_node_index[32];
|
||||
u32 fa_acl_in_ip6_l2_node_feat_next_node_index[32];
|
||||
@@ -212,6 +195,10 @@ typedef struct {
|
||||
u32 fa_conn_list_head[ACL_N_TIMEOUTS];
|
||||
u32 fa_conn_list_tail[ACL_N_TIMEOUTS];
|
||||
|
||||
/* Configured session timeout */
|
||||
u64 session_timeout[ACL_N_TIMEOUTS];
|
||||
|
||||
|
||||
/* Counters for the cleaner thread */
|
||||
|
||||
#define foreach_fa_cleaner_counter \
|
||||
|
||||
@@ -1,238 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Cisco 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.
|
||||
*/
|
||||
/*
|
||||
*------------------------------------------------------------------
|
||||
* l2sess.c - simple MAC-swap API / debug CLI handling
|
||||
*------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <vnet/vnet.h>
|
||||
#include <vnet/plugin/plugin.h>
|
||||
#include <acl/l2sess.h>
|
||||
|
||||
#include <vlibapi/api.h>
|
||||
#include <vlibmemory/api.h>
|
||||
#include <vlibsocket/api.h>
|
||||
#include <vppinfra/timing_wheel.h>
|
||||
|
||||
#include <vnet/l2/l2_output.h>
|
||||
#include <vnet/l2/l2_input.h>
|
||||
|
||||
void
|
||||
l2sess_init_next_features (vlib_main_t * vm, l2sess_main_t * sm)
|
||||
{
|
||||
#define _(node_name, node_var, is_out, is_ip6, is_track) \
|
||||
if (is_out) \
|
||||
feat_bitmap_init_next_nodes(vm, node_var.index, L2OUTPUT_N_FEAT, \
|
||||
l2output_get_feat_names (), \
|
||||
sm->node_var ## _feat_next_node_index); \
|
||||
else \
|
||||
feat_bitmap_init_next_nodes(vm, node_var.index, L2INPUT_N_FEAT, \
|
||||
l2input_get_feat_names (), \
|
||||
sm->node_var ## _feat_next_node_index);
|
||||
|
||||
foreach_l2sess_node
|
||||
#undef _
|
||||
}
|
||||
|
||||
void
|
||||
l2sess_add_our_next_nodes (vlib_main_t * vm, l2sess_main_t * sm,
|
||||
u8 * prev_node_name, int add_output_nodes)
|
||||
{
|
||||
vlib_node_t *n;
|
||||
n = vlib_get_node_by_name (vm, prev_node_name);
|
||||
#define _(node_name, node_var, is_out, is_ip6, is_track) \
|
||||
if (is_out == add_output_nodes) { \
|
||||
u32 idx = vlib_node_add_next_with_slot(vm, n->index, node_var.index, ~0); \
|
||||
if (is_track) { \
|
||||
sm->next_slot_track_node_by_is_ip6_is_out[is_ip6][is_out] = idx; \
|
||||
} \
|
||||
}
|
||||
foreach_l2sess_node
|
||||
#undef _
|
||||
}
|
||||
|
||||
void
|
||||
l2sess_setup_nodes (void)
|
||||
{
|
||||
vlib_main_t *vm = vlib_get_main ();
|
||||
l2sess_main_t *sm = &l2sess_main;
|
||||
|
||||
l2sess_init_next_features (vm, sm);
|
||||
|
||||
l2sess_add_our_next_nodes (vm, sm, (u8 *) "l2-input-classify", 0);
|
||||
l2sess_add_our_next_nodes (vm, sm, (u8 *) "l2-output-classify", 1);
|
||||
|
||||
}
|
||||
|
||||
static char *
|
||||
get_l4_proto_str (int is_ip6, uint8_t l4_proto)
|
||||
{
|
||||
switch (l4_proto)
|
||||
{
|
||||
case 6:
|
||||
return "tcp";
|
||||
case 17:
|
||||
return "udp";
|
||||
case 1:
|
||||
return "icmp";
|
||||
case 58:
|
||||
return "icmp6";
|
||||
default:
|
||||
return "<?l4-unknown?>";
|
||||
}
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
l2sess_show_command_fn (vlib_main_t * vm,
|
||||
unformat_input_t * input, vlib_cli_command_t * cmd)
|
||||
{
|
||||
l2sess_main_t *sm = &l2sess_main;
|
||||
clib_time_t *ct = &vm->clib_time;
|
||||
l2s_session_t *s;
|
||||
u64 now = clib_cpu_time_now ();
|
||||
|
||||
vlib_cli_output (vm, "Timing wheel info: \n%U", format_timing_wheel,
|
||||
&sm->timing_wheel, 255);
|
||||
|
||||
pool_foreach (s, sm->sessions, (
|
||||
{
|
||||
f64 ctime =
|
||||
(now -
|
||||
s->create_time) * ct->seconds_per_clock;
|
||||
f64 atime0 =
|
||||
(now -
|
||||
s->side[0].active_time) *
|
||||
ct->seconds_per_clock;
|
||||
f64 atime1 =
|
||||
(now -
|
||||
s->side[1].active_time) *
|
||||
ct->seconds_per_clock;
|
||||
/*
|
||||
f64 ctime = (s->create_time - vm->cpu_time_main_loop_start) * ct->seconds_per_clock;
|
||||
f64 atime0 = (s->side[0].active_time - vm->cpu_time_main_loop_start) * ct->seconds_per_clock;
|
||||
f64 atime1 = (s->side[1].active_time - vm->cpu_time_main_loop_start) * ct->seconds_per_clock;
|
||||
*/
|
||||
u8 * out0 =
|
||||
format (0,
|
||||
"%5d: create time: %U pkts/bytes/active time: [ %ld %ld %U : %ld %ld %U ]\n",
|
||||
(s - sm->sessions),
|
||||
format_time_interval, "h:m:s:u",
|
||||
ctime, s->side[0].n_packets,
|
||||
s->side[0].n_bytes,
|
||||
format_time_interval, "h:m:s:u",
|
||||
atime0, s->side[1].n_packets,
|
||||
s->side[1].n_bytes,
|
||||
format_time_interval, "h:m:s:u",
|
||||
atime1); u8 * out1 = 0;
|
||||
if (s->is_ip6)
|
||||
{
|
||||
out1 =
|
||||
format (0, "%s %U :%u <-> %U :%u",
|
||||
get_l4_proto_str (s->is_ip6,
|
||||
s->l4_proto),
|
||||
format_ip6_address,
|
||||
&s->side[0].addr.ip6,
|
||||
s->side[0].port,
|
||||
format_ip6_address,
|
||||
&s->side[1].addr.ip6,
|
||||
s->side[1].port);}
|
||||
else
|
||||
{
|
||||
out1 =
|
||||
format (0, "%s %U :%u <-> %U :%u",
|
||||
get_l4_proto_str (s->is_ip6,
|
||||
s->l4_proto),
|
||||
format_ip4_address,
|
||||
&s->side[0].addr.ip4,
|
||||
s->side[0].port,
|
||||
format_ip4_address,
|
||||
&s->side[1].addr.ip4,
|
||||
s->side[1].port);}
|
||||
vlib_cli_output (vm, "%s %s", out0,
|
||||
out1); vec_free (out0);
|
||||
vec_free (out1);}
|
||||
));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
l2sess_show_count_command_fn (vlib_main_t * vm,
|
||||
unformat_input_t * input,
|
||||
vlib_cli_command_t * cmd)
|
||||
{
|
||||
l2sess_main_t *sm = &l2sess_main;
|
||||
|
||||
vlib_cli_output (vm, "Timing wheel info: \n%U", format_timing_wheel,
|
||||
&sm->timing_wheel, 255);
|
||||
vlib_cli_output (vm, "session pool len: %d, pool elts: %d",
|
||||
pool_len (sm->sessions), pool_elts (sm->sessions));
|
||||
vlib_cli_output (vm,
|
||||
"attempted to delete sessions which were already free: %d",
|
||||
sm->counter_attempted_delete_free_session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_CLI_COMMAND (l2sess_show_command, static) = {
|
||||
.path = "show l2sess",
|
||||
.short_help = "show l2sess",
|
||||
.function = l2sess_show_command_fn,
|
||||
};
|
||||
|
||||
VLIB_CLI_COMMAND (l2sess_show_count_command, static) = {
|
||||
.path = "show l2sess count",
|
||||
.short_help = "show l2sess count",
|
||||
.function = l2sess_show_count_command_fn,
|
||||
};
|
||||
/* *INDENT-OFF* */
|
||||
|
||||
static inline u64
|
||||
time_sec_to_clock( clib_time_t *ct, f64 sec)
|
||||
{
|
||||
return (u64)(((f64)sec)/ct->seconds_per_clock);
|
||||
}
|
||||
|
||||
static clib_error_t * l2sess_init (vlib_main_t * vm)
|
||||
{
|
||||
l2sess_main_t * sm = &l2sess_main;
|
||||
clib_error_t * error = 0;
|
||||
u64 cpu_time_now = clib_cpu_time_now();
|
||||
|
||||
|
||||
clib_time_t *ct = &vm->clib_time;
|
||||
sm->udp_session_idle_timeout = time_sec_to_clock(ct, UDP_SESSION_IDLE_TIMEOUT_SEC);
|
||||
sm->tcp_session_idle_timeout = time_sec_to_clock(ct, TCP_SESSION_IDLE_TIMEOUT_SEC);
|
||||
sm->tcp_session_transient_timeout = time_sec_to_clock(ct, TCP_SESSION_TRANSIENT_TIMEOUT_SEC);
|
||||
|
||||
/* The min sched time of 10e-1 causes erroneous behavior... */
|
||||
sm->timing_wheel.min_sched_time = 10e-2;
|
||||
sm->timing_wheel.max_sched_time = 3600.0*48.0;
|
||||
timing_wheel_init (&sm->timing_wheel, cpu_time_now, vm->clib_time.clocks_per_second);
|
||||
sm->timer_wheel_next_expiring_time = 0;
|
||||
sm->timer_wheel_tick = time_sec_to_clock(ct, sm->timing_wheel.min_sched_time);
|
||||
/* Pre-allocate expired nodes. */
|
||||
vec_alloc (sm->data_from_advancing_timing_wheel, 32);
|
||||
|
||||
l2sess_setup_nodes();
|
||||
l2output_init_output_node_vec (&sm->output_next_nodes.output_node_index_vec);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
VLIB_INIT_FUNCTION (l2sess_init);
|
||||
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Cisco 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.
|
||||
*/
|
||||
#ifndef __included_l2sess_h__
|
||||
#define __included_l2sess_h__
|
||||
|
||||
#include <vnet/vnet.h>
|
||||
#include <vnet/ip/ip.h>
|
||||
#include <vnet/ethernet/ethernet.h>
|
||||
|
||||
#include <vppinfra/hash.h>
|
||||
#include <vppinfra/error.h>
|
||||
#include <vppinfra/elog.h>
|
||||
#include <vppinfra/timing_wheel.h>
|
||||
|
||||
#include <vnet/l2/l2_output.h>
|
||||
#include <vnet/l2/l2_input.h>
|
||||
|
||||
#define _(node_name, node_var, is_out, is_ip6, is_track)
|
||||
#undef _
|
||||
#define foreach_l2sess_node \
|
||||
_("aclp-l2s-input-ip4-add", l2sess_in_ip4_add, 0, 0, 0) \
|
||||
_("aclp-l2s-input-ip6-add", l2sess_in_ip6_add, 0, 1, 0) \
|
||||
_("aclp-l2s-output-ip4-add", l2sess_out_ip4_add, 1, 0, 0) \
|
||||
_("aclp-l2s-output-ip6-add", l2sess_out_ip6_add, 1, 1, 0) \
|
||||
_("aclp-l2s-input-ip4-track", l2sess_in_ip4_track, 0, 0, 1) \
|
||||
_("aclp-l2s-input-ip6-track", l2sess_in_ip6_track, 0, 1, 1) \
|
||||
_("aclp-l2s-output-ip4-track",l2sess_out_ip4_track, 1, 0, 1) \
|
||||
_("aclp-l2s-output-ip6-track", l2sess_out_ip6_track, 1, 1, 1)
|
||||
|
||||
#define _(node_name, node_var, is_out, is_ip6, is_track) \
|
||||
extern vlib_node_registration_t node_var;
|
||||
foreach_l2sess_node
|
||||
#undef _
|
||||
|
||||
#define TCP_FLAG_FIN 0x01
|
||||
#define TCP_FLAG_SYN 0x02
|
||||
#define TCP_FLAG_RST 0x04
|
||||
#define TCP_FLAG_PUSH 0x08
|
||||
#define TCP_FLAG_ACK 0x10
|
||||
#define TCP_FLAG_URG 0x20
|
||||
#define TCP_FLAG_ECE 0x40
|
||||
#define TCP_FLAG_CWR 0x80
|
||||
#define TCP_FLAGS_RSTFINACKSYN (TCP_FLAG_RST + TCP_FLAG_FIN + TCP_FLAG_SYN + TCP_FLAG_ACK)
|
||||
#define TCP_FLAGS_ACKSYN (TCP_FLAG_SYN + TCP_FLAG_ACK)
|
||||
|
||||
typedef struct {
|
||||
ip46_address_t addr;
|
||||
u64 active_time;
|
||||
u64 n_packets;
|
||||
u64 n_bytes;
|
||||
u16 port;
|
||||
} l2s_session_side_t;
|
||||
|
||||
enum {
|
||||
L2S_SESSION_SIDE_IN = 0,
|
||||
L2S_SESSION_SIDE_OUT,
|
||||
L2S_N_SESSION_SIDES
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
u64 create_time;
|
||||
l2s_session_side_t side[L2S_N_SESSION_SIDES];
|
||||
u8 l4_proto;
|
||||
u8 is_ip6;
|
||||
u16 tcp_flags_seen; /* u16 because of two sides */
|
||||
} l2s_session_t;
|
||||
|
||||
#define PROD
|
||||
#ifdef PROD
|
||||
#define UDP_SESSION_IDLE_TIMEOUT_SEC 600
|
||||
#define TCP_SESSION_IDLE_TIMEOUT_SEC (3600*24)
|
||||
#define TCP_SESSION_TRANSIENT_TIMEOUT_SEC 120
|
||||
#else
|
||||
#define UDP_SESSION_IDLE_TIMEOUT_SEC 15
|
||||
#define TCP_SESSION_IDLE_TIMEOUT_SEC 15
|
||||
#define TCP_SESSION_TRANSIENT_TIMEOUT_SEC 5
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
/*
|
||||
* the next two fields are present for all nodes, but
|
||||
* only one of them is used per node - depending
|
||||
* on whether the node is an input or output one.
|
||||
*/
|
||||
#define _(node_name, node_var, is_out, is_ip6, is_track) \
|
||||
u32 node_var ## _feat_next_node_index[32];
|
||||
foreach_l2sess_node
|
||||
#undef _
|
||||
l2_output_next_nodes_st output_next_nodes;
|
||||
|
||||
/* Next indices of the tracker nodes */
|
||||
u32 next_slot_track_node_by_is_ip6_is_out[2][2];
|
||||
|
||||
/*
|
||||
* Pairing of "forward" and "reverse" tables by table index.
|
||||
* Each relationship has two entries - for one and the other table,
|
||||
* so it is bidirectional.
|
||||
*/
|
||||
|
||||
u32 *fwd_to_rev_by_table_index;
|
||||
|
||||
/*
|
||||
* The vector of per-interface session pools
|
||||
*/
|
||||
|
||||
l2s_session_t *sessions;
|
||||
|
||||
/* The session timeouts */
|
||||
u64 tcp_session_transient_timeout;
|
||||
u64 tcp_session_idle_timeout;
|
||||
u64 udp_session_idle_timeout;
|
||||
|
||||
/* Timing wheel to time out the idle sessions */
|
||||
timing_wheel_t timing_wheel;
|
||||
u32 *data_from_advancing_timing_wheel;
|
||||
u64 timer_wheel_next_expiring_time;
|
||||
u64 timer_wheel_tick;
|
||||
|
||||
/* convenience */
|
||||
vlib_main_t * vlib_main;
|
||||
vnet_main_t * vnet_main;
|
||||
|
||||
/* Counter(s) */
|
||||
u64 counter_attempted_delete_free_session;
|
||||
} l2sess_main_t;
|
||||
|
||||
l2sess_main_t l2sess_main;
|
||||
|
||||
/* Just exposed for acl.c */
|
||||
|
||||
void
|
||||
l2sess_vlib_plugin_register (vlib_main_t * vm, void * hh,
|
||||
int from_early_init);
|
||||
|
||||
|
||||
#endif /* __included_l2sess_h__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Cisco 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 <vlib/vlib.h>
|
||||
#include <vnet/vnet.h>
|
||||
#include <vnet/pg/pg.h>
|
||||
#include <vppinfra/error.h>
|
||||
#include <acl/acl.h>
|
||||
#include "node_in.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 next_index;
|
||||
u32 sw_if_index;
|
||||
u32 match_acl_index;
|
||||
u32 match_rule_index;
|
||||
u32 trace_bitmap;
|
||||
} acl_in_trace_t;
|
||||
|
||||
/* packet trace format function */
|
||||
static u8 *
|
||||
format_acl_in_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 *);
|
||||
acl_in_trace_t *t = va_arg (*args, acl_in_trace_t *);
|
||||
|
||||
s =
|
||||
format (s,
|
||||
"ACL_IN: sw_if_index %d, next index %d, match: inacl %d rule %d trace_bits %08x",
|
||||
t->sw_if_index, t->next_index, t->match_acl_index,
|
||||
t->match_rule_index, t->trace_bitmap);
|
||||
return s;
|
||||
}
|
||||
|
||||
vlib_node_registration_t acl_in_node;
|
||||
|
||||
#define foreach_acl_in_error \
|
||||
_(ACL_CHECK, "InACL check packets processed")
|
||||
|
||||
typedef enum
|
||||
{
|
||||
#define _(sym,str) ACL_IN_ERROR_##sym,
|
||||
foreach_acl_in_error
|
||||
#undef _
|
||||
ACL_IN_N_ERROR,
|
||||
} acl_in_error_t;
|
||||
|
||||
static char *acl_in_error_strings[] = {
|
||||
#define _(sym,string) string,
|
||||
foreach_acl_in_error
|
||||
#undef _
|
||||
};
|
||||
|
||||
static uword
|
||||
acl_in_node_fn (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node, vlib_frame_t * frame)
|
||||
{
|
||||
u32 n_left_from, *from, *to_next;
|
||||
acl_in_next_t next_index;
|
||||
u32 pkts_acl_checked = 0;
|
||||
u32 feature_bitmap0;
|
||||
u32 trace_bitmap = 0;
|
||||
u32 *input_feat_next_node_index =
|
||||
acl_main.acl_in_node_feat_next_node_index;
|
||||
|
||||
from = vlib_frame_vector_args (frame);
|
||||
n_left_from = frame->n_vectors;
|
||||
next_index = node->cached_next_index;
|
||||
|
||||
while (n_left_from > 0)
|
||||
{
|
||||
u32 n_left_to_next;
|
||||
|
||||
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;
|
||||
vlib_buffer_t *b0;
|
||||
u32 next0 = ~0;
|
||||
u32 sw_if_index0;
|
||||
u32 next = ~0;
|
||||
u32 match_acl_index = ~0;
|
||||
u32 match_rule_index = ~0;
|
||||
|
||||
/* speculatively enqueue b0 to the current next frame */
|
||||
bi0 = from[0];
|
||||
to_next[0] = bi0;
|
||||
from += 1;
|
||||
to_next += 1;
|
||||
n_left_from -= 1;
|
||||
n_left_to_next -= 1;
|
||||
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
|
||||
|
||||
sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
|
||||
feature_bitmap0 = vnet_buffer (b0)->l2.feature_bitmap;
|
||||
|
||||
input_acl_packet_match (sw_if_index0, b0, &next, &match_acl_index,
|
||||
&match_rule_index, &trace_bitmap);
|
||||
if (next != ~0)
|
||||
{
|
||||
next0 = next;
|
||||
}
|
||||
if (next0 == ~0)
|
||||
{
|
||||
next0 =
|
||||
feat_bitmap_get_next_node_index (input_feat_next_node_index,
|
||||
feature_bitmap0);
|
||||
}
|
||||
|
||||
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
|
||||
&& (b0->flags & VLIB_BUFFER_IS_TRACED)))
|
||||
{
|
||||
acl_in_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
|
||||
t->sw_if_index = sw_if_index0;
|
||||
t->next_index = next0;
|
||||
t->match_acl_index = match_acl_index;
|
||||
t->match_rule_index = match_rule_index;
|
||||
t->trace_bitmap = trace_bitmap;
|
||||
}
|
||||
|
||||
next0 = next0 < node->n_next_nodes ? next0 : 0;
|
||||
|
||||
pkts_acl_checked += 1;
|
||||
|
||||
/* verify speculative enqueue, maybe switch current next frame */
|
||||
vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
|
||||
to_next, n_left_to_next,
|
||||
bi0, next0);
|
||||
}
|
||||
|
||||
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
|
||||
}
|
||||
|
||||
vlib_node_increment_counter (vm, acl_in_node.index,
|
||||
ACL_IN_ERROR_ACL_CHECK, pkts_acl_checked);
|
||||
return frame->n_vectors;
|
||||
}
|
||||
|
||||
VLIB_REGISTER_NODE (acl_in_node) =
|
||||
{
|
||||
.function = acl_in_node_fn,.name = "acl-plugin-in",.vector_size =
|
||||
sizeof (u32),.format_trace = format_acl_in_trace,.type =
|
||||
VLIB_NODE_TYPE_INTERNAL,.n_errors =
|
||||
ARRAY_LEN (acl_in_error_strings),.error_strings =
|
||||
acl_in_error_strings,.n_next_nodes = ACL_IN_N_NEXT,
|
||||
/* edit / add dispositions here */
|
||||
.next_nodes =
|
||||
{
|
||||
[ACL_IN_ERROR_DROP] = "error-drop",
|
||||
[ACL_IN_ETHERNET_INPUT] = "ethernet-input",
|
||||
[ACL_IN_L2S_INPUT_IP4_ADD] = "aclp-l2s-input-ip4-add",
|
||||
[ACL_IN_L2S_INPUT_IP6_ADD] = "aclp-l2s-input-ip6-add",}
|
||||
,};
|
||||
@@ -1,12 +0,0 @@
|
||||
#ifndef _NODE_IN_H_
|
||||
#define _NODE_IN_H_
|
||||
|
||||
typedef enum {
|
||||
ACL_IN_ERROR_DROP,
|
||||
ACL_IN_ETHERNET_INPUT,
|
||||
ACL_IN_L2S_INPUT_IP4_ADD,
|
||||
ACL_IN_L2S_INPUT_IP6_ADD,
|
||||
ACL_IN_N_NEXT,
|
||||
} acl_in_next_t;
|
||||
|
||||
#endif
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Cisco 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 <vlib/vlib.h>
|
||||
#include <vnet/vnet.h>
|
||||
#include <vnet/pg/pg.h>
|
||||
#include <vppinfra/error.h>
|
||||
#include <acl/acl.h>
|
||||
|
||||
#include "node_out.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 next_index;
|
||||
u32 sw_if_index;
|
||||
u32 match_acl_index;
|
||||
u32 match_rule_index;
|
||||
u32 trace_bitmap;
|
||||
} acl_out_trace_t;
|
||||
|
||||
/* packet trace format function */
|
||||
static u8 *
|
||||
format_acl_out_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 *);
|
||||
acl_out_trace_t *t = va_arg (*args, acl_out_trace_t *);
|
||||
s =
|
||||
format (s,
|
||||
"ACL_OUT: sw_if_index %d, next index %d, match: outacl %d rule %d trace_bits %08x",
|
||||
t->sw_if_index, t->next_index, t->match_acl_index,
|
||||
t->match_rule_index, t->trace_bitmap);
|
||||
return s;
|
||||
}
|
||||
|
||||
vlib_node_registration_t acl_out_node;
|
||||
|
||||
#define foreach_acl_out_error \
|
||||
_(ACL_CHECK, "OutACL check packets processed")
|
||||
|
||||
typedef enum
|
||||
{
|
||||
#define _(sym,str) ACL_OUT_ERROR_##sym,
|
||||
foreach_acl_out_error
|
||||
#undef _
|
||||
ACL_OUT_N_ERROR,
|
||||
} acl_out_error_t;
|
||||
|
||||
static char *acl_out_error_strings[] = {
|
||||
#define _(sym,string) string,
|
||||
foreach_acl_out_error
|
||||
#undef _
|
||||
};
|
||||
|
||||
static uword
|
||||
acl_out_node_fn (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node, vlib_frame_t * frame)
|
||||
{
|
||||
acl_main_t *am = &acl_main;
|
||||
u32 *output_feat_next_node_index =
|
||||
am->acl_out_node_feat_next_node_index;
|
||||
u32 n_left_from, *from, *to_next;
|
||||
acl_out_next_t next_index;
|
||||
u32 pkts_acl_checked = 0;
|
||||
u32 feature_bitmap0;
|
||||
u32 match_acl_index = ~0;
|
||||
u32 match_rule_index = ~0;
|
||||
u32 trace_bitmap = 0;
|
||||
|
||||
from = vlib_frame_vector_args (frame);
|
||||
n_left_from = frame->n_vectors;
|
||||
next_index = node->cached_next_index;
|
||||
|
||||
while (n_left_from > 0)
|
||||
{
|
||||
u32 n_left_to_next;
|
||||
|
||||
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;
|
||||
vlib_buffer_t *b0;
|
||||
u32 next0 = ~0;
|
||||
u32 next = 0;
|
||||
u32 sw_if_index0;
|
||||
|
||||
/* speculatively enqueue b0 to the current next frame */
|
||||
bi0 = from[0];
|
||||
to_next[0] = bi0;
|
||||
from += 1;
|
||||
to_next += 1;
|
||||
n_left_from -= 1;
|
||||
n_left_to_next -= 1;
|
||||
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
|
||||
|
||||
sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
|
||||
feature_bitmap0 = vnet_buffer (b0)->l2.feature_bitmap;
|
||||
|
||||
output_acl_packet_match (sw_if_index0, b0, &next, &match_acl_index,
|
||||
&match_rule_index, &trace_bitmap);
|
||||
if (next != ~0)
|
||||
{
|
||||
next0 = next;
|
||||
}
|
||||
if (next0 == ~0)
|
||||
{
|
||||
next0 =
|
||||
feat_bitmap_get_next_node_index (output_feat_next_node_index,
|
||||
feature_bitmap0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
|
||||
&& (b0->flags & VLIB_BUFFER_IS_TRACED)))
|
||||
{
|
||||
acl_out_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
|
||||
t->sw_if_index = sw_if_index0;
|
||||
t->next_index = next0;
|
||||
t->match_acl_index = match_acl_index;
|
||||
t->match_rule_index = match_rule_index;
|
||||
t->trace_bitmap = trace_bitmap;
|
||||
}
|
||||
|
||||
pkts_acl_checked += 1;
|
||||
|
||||
/* verify speculative enqueue, maybe switch current next frame */
|
||||
vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
|
||||
to_next, n_left_to_next,
|
||||
bi0, next0);
|
||||
}
|
||||
|
||||
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
|
||||
}
|
||||
|
||||
vlib_node_increment_counter (vm, acl_out_node.index,
|
||||
ACL_OUT_ERROR_ACL_CHECK, pkts_acl_checked);
|
||||
return frame->n_vectors;
|
||||
}
|
||||
|
||||
VLIB_REGISTER_NODE (acl_out_node) =
|
||||
{
|
||||
.function = acl_out_node_fn,.name = "acl-plugin-out",.vector_size =
|
||||
sizeof (u32),.format_trace = format_acl_out_trace,.type =
|
||||
VLIB_NODE_TYPE_INTERNAL,.n_errors =
|
||||
ARRAY_LEN (acl_out_error_strings),.error_strings =
|
||||
acl_out_error_strings,.n_next_nodes = ACL_OUT_N_NEXT,
|
||||
/* edit / add dispositions here */
|
||||
.next_nodes =
|
||||
{
|
||||
[ACL_OUT_ERROR_DROP] = "error-drop",
|
||||
[ACL_OUT_INTERFACE_OUTPUT] = "interface-output",
|
||||
[ACL_OUT_L2S_OUTPUT_IP4_ADD] = "aclp-l2s-output-ip4-add",
|
||||
[ACL_OUT_L2S_OUTPUT_IP6_ADD] = "aclp-l2s-output-ip6-add",}
|
||||
,};
|
||||
@@ -1,12 +0,0 @@
|
||||
#ifndef _NODE_OUT_H_
|
||||
#define _NODE_OUT_H_
|
||||
|
||||
typedef enum {
|
||||
ACL_OUT_ERROR_DROP,
|
||||
ACL_OUT_INTERFACE_OUTPUT,
|
||||
ACL_OUT_L2S_OUTPUT_IP4_ADD,
|
||||
ACL_OUT_L2S_OUTPUT_IP6_ADD,
|
||||
ACL_OUT_N_NEXT,
|
||||
} acl_out_next_t;
|
||||
|
||||
#endif
|
||||
@@ -1,28 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Do all the legwork to run a scapy shell with APIs available for load
|
||||
#
|
||||
CURR_DIR=`pwd`
|
||||
ROOT_DIR=`git rev-parse --show-toplevel`
|
||||
cd $ROOT_DIR
|
||||
sudo apt-get install -y python-virtualenv
|
||||
# uncomment the line below to enable build of plugins and api each time
|
||||
# make plugins && make build-vpp-api || exit
|
||||
virtualenv virtualenv
|
||||
virtualenv/bin/pip install ipaddress
|
||||
virtualenv/bin/pip install scapy
|
||||
# install the python API into the virtualenv
|
||||
cd $ROOT_DIR/vpp-api/python/
|
||||
$ROOT_DIR/virtualenv/bin/python setup.py install
|
||||
# install the python ACL plugin API into the virtualenv
|
||||
ACL_PLUGIN_SETUP_DIR=`find $ROOT_DIR/build-root -name acl-plugin`
|
||||
cd $ACL_PLUGIN_SETUP_DIR;
|
||||
$ROOT_DIR/virtualenv/bin/python setup.py install
|
||||
cd $ROOT_DIR
|
||||
# figure out the shared library path and start scapy
|
||||
export LD_LIBRARY_PATH=`pwd`/`find . -name "libpneum.so" -exec dirname {} \; | grep lib64 | head -n 1`
|
||||
cd $CURR_DIR
|
||||
sudo LD_LIBRARY_PATH=$LD_LIBRARY_PATH $ROOT_DIR/virtualenv/bin/python $1 $2 $3 $4 $5 $6 $7 $8 $9
|
||||
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Do all the legwork to run a scapy shell with APIs available for load
|
||||
#
|
||||
ROOT_DIR=`git rev-parse --show-toplevel`
|
||||
cd $ROOT_DIR
|
||||
sudo apt-get install -y python-virtualenv
|
||||
# uncomment the line below to enable the build of plugins and API each time..
|
||||
# make plugins && make build-vpp-api || exit
|
||||
virtualenv virtualenv
|
||||
virtualenv/bin/pip install ipaddress
|
||||
virtualenv/bin/pip install scapy
|
||||
# install the python API into the virtualenv
|
||||
cd $ROOT_DIR/vpp-api/python/
|
||||
$ROOT_DIR/virtualenv/bin/python setup.py install
|
||||
# install the python ACL plugin API into the virtualenv
|
||||
ACL_PLUGIN_SETUP_DIR=`find $ROOT_DIR/build-root -name acl-plugin`
|
||||
cd $ACL_PLUGIN_SETUP_DIR;
|
||||
$ROOT_DIR/virtualenv/bin/python setup.py install
|
||||
cd $ROOT_DIR
|
||||
# figure out the shared library path and start scapy
|
||||
export LD_LIBRARY_PATH=`pwd`/`find . -name "libpneum.so" -exec dirname {} \; | grep lib64 | head -n 1`
|
||||
sudo LD_LIBRARY_PATH=$LD_LIBRARY_PATH virtualenv/bin/scapy
|
||||
|
||||
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
from __future__ import print_function
|
||||
import unittest, sys, time, threading, struct, logging, os
|
||||
import vpp_papi
|
||||
# import vpp_papi_plugins.acl
|
||||
from ipaddress import *
|
||||
papi_event = threading.Event()
|
||||
print(vpp_papi.vpe.VL_API_SW_INTERFACE_SET_FLAGS)
|
||||
def papi_event_handler(result):
|
||||
if result.vl_msg_id == vpp_papi.vpe.VL_API_SW_INTERFACE_SET_FLAGS:
|
||||
return
|
||||
if result.vl_msg_id == vpp_papi.vpe.VL_API_VNET_INTERFACE_COUNTERS:
|
||||
print('Interface counters', result)
|
||||
return
|
||||
if result.vl_msg_id == vpp_papi.vpe.VL_API_VNET_IP6_FIB_COUNTERS:
|
||||
print('IPv6 FIB counters', result)
|
||||
papi_event.set()
|
||||
return
|
||||
|
||||
print('Unknown message id:', result.vl_msg_id)
|
||||
|
||||
import glob, subprocess
|
||||
class TestAclPlugin(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
print("Setup")
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
print("Teardown")
|
||||
|
||||
def setUp(self):
|
||||
print("Connecting API")
|
||||
r = vpp_papi.connect("test_papi")
|
||||
self.assertEqual(r, 0)
|
||||
|
||||
def tearDown(self):
|
||||
r = vpp_papi.disconnect()
|
||||
self.assertEqual(r, 0)
|
||||
|
||||
#
|
||||
# The tests themselves
|
||||
#
|
||||
|
||||
#
|
||||
# Basic request / reply
|
||||
#
|
||||
def test_show_version(self):
|
||||
t = vpp_papi.show_version()
|
||||
print('T', t);
|
||||
program = t.program.decode().rstrip('\x00')
|
||||
self.assertEqual('vpe', program)
|
||||
|
||||
def x_test_acl_add(self):
|
||||
print("Test ACL add")
|
||||
self.assertEqual(1, 1)
|
||||
|
||||
#
|
||||
# Details / Dump
|
||||
#
|
||||
def x_test_details_dump(self):
|
||||
t = vpp_papi.sw_interface_dump(0, b'')
|
||||
print('Dump/details T', t)
|
||||
|
||||
#
|
||||
# Arrays
|
||||
#
|
||||
def x_test_arrays(self):
|
||||
t = vpp_papi.vnet_get_summary_stats()
|
||||
print('Summary stats', t)
|
||||
print('Packets:', t.total_pkts[0])
|
||||
print('Packets:', t.total_pkts[1])
|
||||
#
|
||||
# Variable sized arrays and counters
|
||||
#
|
||||
#@unittest.skip("stats")
|
||||
def x_test_want_stats(self):
|
||||
pid = 123
|
||||
vpp_papi.register_event_callback(papi_event_handler)
|
||||
papi_event.clear()
|
||||
|
||||
# Need to configure IPv6 to get som IPv6 FIB stats
|
||||
t = vpp_papi.create_loopback('')
|
||||
print(t)
|
||||
self.assertEqual(t.retval, 0)
|
||||
|
||||
ifindex = t.sw_if_index
|
||||
addr = str(IPv6Address(u'1::1').packed)
|
||||
t = vpp_papi.sw_interface_add_del_address(ifindex, 1, 1, 0, 16, addr)
|
||||
print(t)
|
||||
self.assertEqual(t.retval, 0)
|
||||
|
||||
# Check if interface is up
|
||||
# XXX: Add new API to query interface state based on ifindex, instead of dump all.
|
||||
t = vpp_papi.sw_interface_set_flags(ifindex, 1, 1, 0)
|
||||
self.assertEqual(t.retval, 0)
|
||||
|
||||
t = vpp_papi.want_stats(True, pid)
|
||||
|
||||
print (t)
|
||||
|
||||
#
|
||||
# Wait for some stats
|
||||
#
|
||||
self.assertEqual(papi_event.wait(15), True)
|
||||
t = vpp_papi.want_stats(False, pid)
|
||||
print (t)
|
||||
|
||||
|
||||
#
|
||||
# Plugins?
|
||||
#
|
||||
|
||||
if __name__ == '__main__' or __name__ == '__builtin__':
|
||||
print("This is main")
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(TestAclPlugin)
|
||||
unittest.TextTestRunner(verbosity=2).run(suite)
|
||||
#logging.basicConfig(level=logging.DEBUG)
|
||||
# unittest.main()
|
||||
|
||||
@@ -715,53 +715,5 @@ class TestIpIrb(VppTestCase):
|
||||
self.run_test_ip46_bridged_to_routed_and_back(False, False,
|
||||
self.WITH_EH)
|
||||
|
||||
# Old datapath group
|
||||
def test_8900_ip6_irb_1(self):
|
||||
""" ACL plugin set old L2 datapath"""
|
||||
if not self.vpp_dead:
|
||||
cmd = "set acl-plugin l2-datapath old"
|
||||
self.logger.info(self.vapi.ppcli(cmd))
|
||||
|
||||
def test_8901_ip6_irb_1(self):
|
||||
""" ACL IPv6 routed -> bridged, L2 ACL deny"""
|
||||
self.run_test_ip46_routed_to_bridged(True, True, False,
|
||||
self.WITHOUT_EH)
|
||||
|
||||
def test_8902_ip6_irb_1(self):
|
||||
""" ACL IPv6 routed -> bridged, L3 ACL deny"""
|
||||
self.run_test_ip46_routed_to_bridged(False, True, False,
|
||||
self.WITHOUT_EH)
|
||||
|
||||
def test_8903_ip4_irb_1(self):
|
||||
""" ACL IPv4 routed -> bridged, L2 ACL deny"""
|
||||
self.run_test_ip46_routed_to_bridged(True, False, False,
|
||||
self.WITHOUT_EH)
|
||||
|
||||
def test_8904_ip4_irb_1(self):
|
||||
""" ACL IPv4 routed -> bridged, L3 ACL deny"""
|
||||
self.run_test_ip46_routed_to_bridged(False, False, False,
|
||||
self.WITHOUT_EH)
|
||||
|
||||
def test_8905_ip6_irb_1(self):
|
||||
""" ACL IPv6 bridged -> routed, L2 ACL deny """
|
||||
self.run_test_ip46_bridged_to_routed(True, True, False,
|
||||
self.WITHOUT_EH)
|
||||
|
||||
def test_8906_ip6_irb_1(self):
|
||||
""" ACL IPv6 bridged -> routed, L3 ACL deny """
|
||||
self.run_test_ip46_bridged_to_routed(False, True, False,
|
||||
self.WITHOUT_EH)
|
||||
|
||||
def test_8907_ip6_irb_1(self):
|
||||
""" ACL IPv4 bridged -> routed, L2 ACL deny """
|
||||
self.run_test_ip46_bridged_to_routed(True, False, False,
|
||||
self.WITHOUT_EH)
|
||||
|
||||
def test_8908_ip6_irb_1(self):
|
||||
""" ACL IPv4 bridged -> routed, L3 ACL deny """
|
||||
self.run_test_ip46_bridged_to_routed(False, False, False,
|
||||
self.WITHOUT_EH)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(testRunner=VppTestRunner)
|
||||
|
||||
Reference in New Issue
Block a user