2 * Copyright (c) 2016 Cisco and/or its affiliates.
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.
16 *------------------------------------------------------------------
17 * l2sess.c - simple MAC-swap API / debug CLI handling
18 *------------------------------------------------------------------
21 #include <vnet/vnet.h>
22 #include <vnet/plugin/plugin.h>
23 #include <acl/l2sess.h>
25 #include <vlibapi/api.h>
26 #include <vlibmemory/api.h>
27 #include <vlibsocket/api.h>
28 #include <vppinfra/timing_wheel.h>
30 #include <vnet/l2/l2_output.h>
31 #include <vnet/l2/l2_input.h>
34 l2sess_init_next_features (vlib_main_t * vm, l2sess_main_t * sm)
36 #define _(node_name, node_var, is_out, is_ip6, is_track) \
38 feat_bitmap_init_next_nodes(vm, node_var.index, L2OUTPUT_N_FEAT, \
39 l2output_get_feat_names (), \
40 sm->node_var ## _feat_next_node_index); \
42 feat_bitmap_init_next_nodes(vm, node_var.index, L2INPUT_N_FEAT, \
43 l2input_get_feat_names (), \
44 sm->node_var ## _feat_next_node_index);
51 l2sess_add_our_next_nodes (vlib_main_t * vm, l2sess_main_t * sm,
52 u8 * prev_node_name, int add_output_nodes)
55 n = vlib_get_node_by_name (vm, prev_node_name);
56 #define _(node_name, node_var, is_out, is_ip6, is_track) \
57 if (is_out == add_output_nodes) { \
58 u32 idx = vlib_node_add_next_with_slot(vm, n->index, node_var.index, ~0); \
60 sm->next_slot_track_node_by_is_ip6_is_out[is_ip6][is_out] = idx; \
68 l2sess_setup_nodes (void)
70 vlib_main_t *vm = vlib_get_main ();
71 l2sess_main_t *sm = &l2sess_main;
73 l2sess_init_next_features (vm, sm);
75 l2sess_add_our_next_nodes (vm, sm, (u8 *) "l2-input-classify", 0);
76 l2sess_add_our_next_nodes (vm, sm, (u8 *) "l2-output-classify", 1);
81 get_l4_proto_str (int is_ip6, uint8_t l4_proto)
94 return "<?l4-unknown?>";
99 l2sess_show_command_fn (vlib_main_t * vm,
100 unformat_input_t * input, vlib_cli_command_t * cmd)
102 l2sess_main_t *sm = &l2sess_main;
103 clib_time_t *ct = &vm->clib_time;
105 u64 now = clib_cpu_time_now ();
107 vlib_cli_output (vm, "Timing wheel info: \n%U", format_timing_wheel,
108 &sm->timing_wheel, 255);
110 pool_foreach (s, sm->sessions, (
114 s->create_time) * ct->seconds_per_clock;
117 s->side[0].active_time) *
118 ct->seconds_per_clock;
121 s->side[1].active_time) *
122 ct->seconds_per_clock;
124 f64 ctime = (s->create_time - vm->cpu_time_main_loop_start) * ct->seconds_per_clock;
125 f64 atime0 = (s->side[0].active_time - vm->cpu_time_main_loop_start) * ct->seconds_per_clock;
126 f64 atime1 = (s->side[1].active_time - vm->cpu_time_main_loop_start) * ct->seconds_per_clock;
130 "%5d: create time: %U pkts/bytes/active time: [ %ld %ld %U : %ld %ld %U ]\n",
132 format_time_interval, "h:m:s:u",
133 ctime, s->side[0].n_packets,
135 format_time_interval, "h:m:s:u",
136 atime0, s->side[1].n_packets,
138 format_time_interval, "h:m:s:u",
139 atime1); u8 * out1 = 0;
143 format (0, "%s %U :%u <-> %U :%u",
144 get_l4_proto_str (s->is_ip6,
147 &s->side[0].addr.ip6,
150 &s->side[1].addr.ip6,
155 format (0, "%s %U :%u <-> %U :%u",
156 get_l4_proto_str (s->is_ip6,
159 &s->side[0].addr.ip4,
162 &s->side[1].addr.ip4,
164 vlib_cli_output (vm, "%s %s", out0,
165 out1); vec_free (out0);
171 static clib_error_t *
172 l2sess_show_count_command_fn (vlib_main_t * vm,
173 unformat_input_t * input,
174 vlib_cli_command_t * cmd)
176 l2sess_main_t *sm = &l2sess_main;
178 vlib_cli_output (vm, "Timing wheel info: \n%U", format_timing_wheel,
179 &sm->timing_wheel, 255);
180 vlib_cli_output (vm, "session pool len: %d, pool elts: %d",
181 pool_len (sm->sessions), pool_elts (sm->sessions));
183 "attempted to delete sessions which were already free: %d",
184 sm->counter_attempted_delete_free_session);
190 VLIB_CLI_COMMAND (l2sess_show_command, static) = {
191 .path = "show l2sess",
192 .short_help = "show l2sess",
193 .function = l2sess_show_command_fn,
196 VLIB_CLI_COMMAND (l2sess_show_count_command, static) = {
197 .path = "show l2sess count",
198 .short_help = "show l2sess count",
199 .function = l2sess_show_count_command_fn,
204 time_sec_to_clock( clib_time_t *ct, f64 sec)
206 return (u64)(((f64)sec)/ct->seconds_per_clock);
209 static clib_error_t * l2sess_init (vlib_main_t * vm)
211 l2sess_main_t * sm = &l2sess_main;
212 clib_error_t * error = 0;
213 u64 cpu_time_now = clib_cpu_time_now();
216 clib_time_t *ct = &vm->clib_time;
217 sm->udp_session_idle_timeout = time_sec_to_clock(ct, UDP_SESSION_IDLE_TIMEOUT_SEC);
218 sm->tcp_session_idle_timeout = time_sec_to_clock(ct, TCP_SESSION_IDLE_TIMEOUT_SEC);
219 sm->tcp_session_transient_timeout = time_sec_to_clock(ct, TCP_SESSION_TRANSIENT_TIMEOUT_SEC);
221 /* The min sched time of 10e-1 causes erroneous behavior... */
222 sm->timing_wheel.min_sched_time = 10e-2;
223 sm->timing_wheel.max_sched_time = 3600.0*48.0;
224 timing_wheel_init (&sm->timing_wheel, cpu_time_now, vm->clib_time.clocks_per_second);
225 sm->timer_wheel_next_expiring_time = 0;
226 sm->timer_wheel_tick = time_sec_to_clock(ct, sm->timing_wheel.min_sched_time);
227 /* Pre-allocate expired nodes. */
228 vec_alloc (sm->data_from_advancing_timing_wheel, 32);
230 l2sess_setup_nodes();
231 l2output_init_output_node_vec (&sm->output_next_nodes.output_node_index_vec);
236 VLIB_INIT_FUNCTION (l2sess_init);