urpf: add interface dump to API
[vpp.git] / src / plugins / urpf / urpf_api.c
1 /*
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:
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
16 #include <urpf/urpf.h>
17 #include <vnet/plugin/plugin.h>
18 #include <vnet/ip/ip_types_api.h>
19
20 #include <vpp/app/version.h>
21
22 #include <vlibapi/api.h>
23 #include <vlibmemory/api.h>
24
25 /* define message IDs */
26 #include <vnet/format_fns.h>
27 #include <urpf/urpf.api_enum.h>
28 #include <urpf/urpf.api_types.h>
29 #include <vnet/fib/fib_table.h>
30 #include <vnet/ip/ip_types.h>
31
32 /**
33  * Base message ID fot the plugin
34  */
35 static u32 urpf_base_msg_id;
36 #define REPLY_MSG_ID_BASE urpf_base_msg_id
37
38 #include <vlibapi/api_helper_macros.h>
39
40 static int
41 urpf_mode_decode (vl_api_urpf_mode_t in, urpf_mode_t * out)
42 {
43   if (0)
44     ;
45 #define _(a,b)                                  \
46   else if (URPF_API_MODE_##a == in)             \
47     {                                           \
48       *out = URPF_MODE_##a;                     \
49       return (0);                               \
50     }
51   foreach_urpf_mode
52 #undef _
53     return (VNET_API_ERROR_INVALID_VALUE);
54 }
55
56 static void
57 vl_api_urpf_update_t_handler (vl_api_urpf_update_t * mp)
58 {
59   vl_api_urpf_update_reply_t *rmp;
60   ip_address_family_t af;
61   urpf_mode_t mode;
62   int rv = 0;
63
64   VALIDATE_SW_IF_INDEX (mp);
65
66   rv = urpf_mode_decode (mp->mode, &mode);
67   if (rv)
68     goto done;
69
70   rv = ip_address_family_decode (mp->af, &af);
71   if (rv)
72     goto done;
73
74   rv = urpf_update (mode, htonl (mp->sw_if_index), af,
75                     (mp->is_input ? VLIB_RX : VLIB_TX), 0);
76   if (rv)
77     goto done;
78
79   BAD_SW_IF_INDEX_LABEL;
80 done:
81   REPLY_MACRO (VL_API_URPF_UPDATE_REPLY);
82 }
83
84 static void
85 vl_api_urpf_update_v2_t_handler (vl_api_urpf_update_v2_t *mp)
86 {
87   vl_api_urpf_update_reply_t *rmp;
88   ip_address_family_t af;
89   urpf_mode_t mode;
90   int rv = 0;
91
92   VALIDATE_SW_IF_INDEX (mp);
93
94   rv = urpf_mode_decode (mp->mode, &mode);
95   if (rv)
96     goto done;
97
98   rv = ip_address_family_decode (mp->af, &af);
99
100   if (rv)
101     goto done;
102
103   rv = urpf_update (mode, htonl (mp->sw_if_index), af,
104                     (mp->is_input ? VLIB_RX : VLIB_TX), ntohl (mp->table_id));
105
106   if (rv)
107     goto done;
108
109   BAD_SW_IF_INDEX_LABEL;
110 done:
111   REPLY_MACRO (VL_API_URPF_UPDATE_V2_REPLY);
112 }
113
114 static void
115 send_urpf_interface_details (vpe_api_main_t *am, vl_api_registration_t *reg,
116                              u32 context, const u32 sw_if_index,
117                              const urpf_data_t *ud,
118                              const ip_address_family_t af,
119                              const vlib_dir_t dir)
120 {
121   vl_api_urpf_interface_details_t *mp;
122
123   mp = vl_msg_api_alloc_zero (sizeof (*mp));
124   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_URPF_INTERFACE_DETAILS);
125   mp->context = context;
126
127   mp->sw_if_index = htonl (sw_if_index);
128   mp->table_id = htonl (fib_table_get_table_id (
129     ud->fib_index, (af == AF_IP4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6)));
130   mp->af = (vl_api_address_family_t) af;
131   mp->mode = (vl_api_urpf_mode_t) ud->mode;
132   mp->is_input = (dir == VLIB_RX);
133
134   vl_api_send_msg (reg, (u8 *) mp);
135 }
136
137 static void
138 send_urpf_interface (vpe_api_main_t *am, vl_api_registration_t *reg,
139                      u32 context, const u32 sw_if_index)
140 {
141   urpf_data_t *ud;
142   vlib_dir_t dir;
143   ip_address_family_t af;
144
145   FOR_EACH_IP_ADDRESS_FAMILY (af)
146   FOREACH_VLIB_DIR (dir)
147   if (sw_if_index < vec_len (urpf_cfgs[af][dir]))
148     {
149       ud = &urpf_cfgs[af][dir][sw_if_index];
150       if (ud->mode || ud->fib_index_is_custom)
151         send_urpf_interface_details (am, reg, context, sw_if_index, ud, af,
152                                      dir);
153     }
154 }
155
156 static void
157 vl_api_urpf_interface_dump_t_handler (vl_api_urpf_interface_dump_t *mp)
158 {
159   vpe_api_main_t *am = &vpe_api_main;
160   vl_api_registration_t *reg;
161   vnet_interface_main_t *im = &vnet_main.interface_main;
162   vnet_sw_interface_t *si;
163   u32 sw_if_index = ~0;
164   int __attribute__ ((unused)) rv = 0;
165
166   reg = vl_api_client_index_to_registration (mp->client_index);
167   if (!reg)
168     return;
169   sw_if_index = ntohl (mp->sw_if_index);
170
171   if (sw_if_index == ~0)
172     {
173       pool_foreach (si, im->sw_interfaces)
174         {
175           send_urpf_interface (am, reg, mp->context, si->sw_if_index);
176         }
177       return;
178     }
179   VALIDATE_SW_IF_INDEX (mp);
180   send_urpf_interface (am, reg, mp->context, sw_if_index);
181   BAD_SW_IF_INDEX_LABEL;
182 }
183
184 #include <urpf/urpf.api.c>
185
186 static clib_error_t *
187 urpf_api_init (vlib_main_t * vm)
188 {
189   /* Ask for a correctly-sized block of API message decode slots */
190   urpf_base_msg_id = setup_message_id_table ();
191
192   return 0;
193 }
194
195 VLIB_INIT_FUNCTION (urpf_api_init);
196
197 /* *INDENT-OFF* */
198 VLIB_PLUGIN_REGISTER () = {
199     .version = VPP_BUILD_VER,
200     .description = "Unicast Reverse Path Forwarding (uRPF)",
201 };
202 /* *INDENT-ON* */
203
204 /*
205  * fd.io coding-style-patch-verification: ON
206  *
207  * Local Variables:
208  * eval: (c-set-style "gnu")
209  * End:
210  */