Line data Source code
1 : /*
2 : * Copyright (c) 2015 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:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
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.
14 : */
15 : #ifndef included_ping_ping_h
16 : #define included_ping_ping_h
17 :
18 :
19 : #include <vnet/ip/ip.h>
20 :
21 : #include <vnet/ip/lookup.h>
22 :
23 : typedef enum
24 : {
25 : PING_RESPONSE_IP6 = 42,
26 : PING_RESPONSE_IP4,
27 : } ping_response_type_t;
28 :
29 : #define foreach_ip46_ping_result \
30 : _ (OK, "OK") \
31 : _ (ALLOC_FAIL, "packet allocation failed") \
32 : _ (NO_INTERFACE, "no egress interface") \
33 : _ (NO_TABLE, "no FIB table for lookup") \
34 : _ (NO_SRC_ADDRESS, "no source address for egress interface") \
35 : _ (NO_BUFFERS, "could not allocate a new buffer") \
36 :
37 : typedef enum
38 : {
39 : #define _(v, s) SEND_PING_##v,
40 : foreach_ip46_ping_result
41 : #undef _
42 : } send_ip46_ping_result_t;
43 :
44 : /*
45 : * Currently running ping command.
46 : */
47 : typedef struct ping_run_t
48 : {
49 : u16 icmp_id;
50 : uword cli_process_id;
51 : } ping_run_t;
52 :
53 : typedef struct ping_main_t
54 : {
55 : /* API message ID base */
56 : u16 msg_id_base;
57 :
58 : ip6_main_t *ip6_main;
59 : ip4_main_t *ip4_main;
60 : /* a vector of current ping runs. */
61 : ping_run_t *active_ping_runs;
62 : /* a lock held while add/remove/search on active_ping_runs */
63 : clib_spinlock_t ping_run_check_lock;
64 : } ping_main_t;
65 :
66 : extern ping_main_t ping_main;
67 :
68 : #define PING_DEFAULT_DATA_LEN 60
69 : #define PING_DEFAULT_INTERVAL 1.0
70 :
71 : #define PING_MAXIMUM_DATA_SIZE 32768
72 :
73 : #define PING_CLI_UNKNOWN_NODE (~0)
74 :
75 : /* *INDENT-OFF* */
76 :
77 : typedef CLIB_PACKED (struct {
78 : u16 id;
79 : u16 seq;
80 : u64 time_sent;
81 : u8 data[0];
82 : }) icmp46_echo_request_t;
83 :
84 : /* *INDENT-ON* */
85 :
86 :
87 : typedef enum
88 : {
89 : ICMP46_ECHO_REPLY_NEXT_DROP,
90 : ICMP46_ECHO_REPLY_NEXT_PUNT,
91 : ICMP46_ECHO_REPLY_N_NEXT,
92 : } icmp46_echo_reply_next_t;
93 :
94 : static_always_inline uword
95 7 : get_cli_process_id_by_icmp_id_mt (vlib_main_t *vm, u16 icmp_id)
96 : {
97 7 : ping_main_t *pm = &ping_main;
98 7 : uword cli_process_id = PING_CLI_UNKNOWN_NODE;
99 : ping_run_t *pr;
100 :
101 7 : clib_spinlock_lock_if_init (&pm->ping_run_check_lock);
102 7 : vec_foreach (pr, pm->active_ping_runs)
103 : {
104 0 : if (pr->icmp_id == icmp_id)
105 : {
106 0 : cli_process_id = pr->cli_process_id;
107 0 : break;
108 : }
109 : }
110 7 : clib_spinlock_unlock_if_init (&pm->ping_run_check_lock);
111 7 : return cli_process_id;
112 : }
113 :
114 : static_always_inline void
115 6 : set_cli_process_id_by_icmp_id_mt (vlib_main_t *vm, u16 icmp_id,
116 : uword cli_process_id)
117 : {
118 6 : ping_main_t *pm = &ping_main;
119 : ping_run_t *pr;
120 :
121 6 : clib_spinlock_lock_if_init (&pm->ping_run_check_lock);
122 6 : vec_foreach (pr, pm->active_ping_runs)
123 : {
124 0 : if (pr->icmp_id == icmp_id)
125 : {
126 0 : pr->cli_process_id = cli_process_id;
127 0 : goto have_found_and_set;
128 : }
129 : }
130 : /* no such key yet - add a new one */
131 6 : ping_run_t new_pr = { .icmp_id = icmp_id, .cli_process_id = cli_process_id };
132 6 : vec_add1 (pm->active_ping_runs, new_pr);
133 6 : have_found_and_set:
134 6 : clib_spinlock_unlock_if_init (&pm->ping_run_check_lock);
135 6 : }
136 :
137 : static_always_inline void
138 6 : clear_cli_process_id_by_icmp_id_mt (vlib_main_t *vm, u16 icmp_id)
139 : {
140 6 : ping_main_t *pm = &ping_main;
141 : ping_run_t *pr;
142 :
143 6 : clib_spinlock_lock_if_init (&pm->ping_run_check_lock);
144 6 : vec_foreach (pr, pm->active_ping_runs)
145 : {
146 6 : if (pr->icmp_id == icmp_id)
147 : {
148 6 : vec_del1 (pm->active_ping_runs, pr - pm->active_ping_runs);
149 6 : break;
150 : }
151 : }
152 6 : clib_spinlock_unlock_if_init (&pm->ping_run_check_lock);
153 6 : }
154 : clib_error_t *ping_plugin_api_hookup (vlib_main_t *vm);
155 : send_ip46_ping_result_t send_ip4_ping (vlib_main_t *vm, u32 table_id,
156 : ip4_address_t *pa4, u32 sw_if_index,
157 : u16 seq_host, u16 id_host, u16 data_len,
158 : u32 burst, u8 verbose);
159 : send_ip46_ping_result_t send_ip6_ping (vlib_main_t *vm, u32 table_id,
160 : ip6_address_t *pa6, u32 sw_if_index,
161 : u16 seq_host, u16 id_host, u16 data_len,
162 : u32 burst, u8 verbose);
163 :
164 : #endif /* included_ping_ping_h */
|