FD.io VPP  v16.09
Vector Packet Processing
sample.c
Go to the documentation of this file.
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 /*
16  *------------------------------------------------------------------
17  * sample.c - simple MAC-swap API / debug CLI handling
18  *------------------------------------------------------------------
19  */
20 
21 #include <vnet/vnet.h>
22 #include <vnet/plugin/plugin.h>
23 #include <sample/sample.h>
24 
25 #include <vlibapi/api.h>
26 #include <vlibmemory/api.h>
27 #include <vlibsocket/api.h>
28 
29 /* define message IDs */
30 #include <sample/sample_msg_enum.h>
31 
32 /* define message structures */
33 #define vl_typedefs
34 #include <sample/sample_all_api_h.h>
35 #undef vl_typedefs
36 
37 /* define generated endian-swappers */
38 #define vl_endianfun
39 #include <sample/sample_all_api_h.h>
40 #undef vl_endianfun
41 
42 /* instantiate all the print functions we know about */
43 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
44 #define vl_printfun
45 #include <sample/sample_all_api_h.h>
46 #undef vl_printfun
47 
48 /* Get the API version number */
49 #define vl_api_version(n,v) static u32 api_version=(v);
51 #undef vl_api_version
52 
53 /*
54  * A handy macro to set up a message reply.
55  * Assumes that the following variables are available:
56  * mp - pointer to request message
57  * rmp - pointer to reply message type
58  * rv - return value
59  */
60 
61 #define REPLY_MACRO(t) \
62 do { \
63  unix_shared_memory_queue_t * q = \
64  vl_api_client_index_to_input_queue (mp->client_index); \
65  if (!q) \
66  return; \
67  \
68  rmp = vl_msg_api_alloc (sizeof (*rmp)); \
69  rmp->_vl_msg_id = ntohs((t)+sm->msg_id_base); \
70  rmp->context = mp->context; \
71  rmp->retval = ntohl(rv); \
72  \
73  vl_msg_api_send_shmem (q, (u8 *)&rmp); \
74 } while(0);
75 
76 
77 /* List of message types that this plugin understands */
78 
79 #define foreach_sample_plugin_api_msg \
80 _(SAMPLE_MACSWAP_ENABLE_DISABLE, sample_macswap_enable_disable)
81 
82 /*
83  * This routine exists to convince the vlib plugin framework that
84  * we haven't accidentally copied a random .dll into the plugin directory.
85  *
86  * Also collects global variable pointers passed from the vpp engine
87  */
88 
89 clib_error_t *
91  int from_early_init)
92 {
93  sample_main_t * sm = &sample_main;
94  clib_error_t * error = 0;
95 
96  sm->vlib_main = vm;
97  sm->vnet_main = h->vnet_main;
99 
100  return error;
101 }
102 
103 /* Action function shared between message handler and debug CLI */
104 
106  int enable_disable)
107 {
108  vnet_sw_interface_t * sw;
109  int rv;
110  u32 node_index = enable_disable ? sample_node.index : ~0;
111 
112  /* Utterly wrong? */
114  sw_if_index))
115  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
116 
117  /* Not a physical port? */
118  sw = vnet_get_sw_interface (sm->vnet_main, sw_if_index);
120  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
121 
122  /*
123  * Redirect pkts from the driver to the macswap node.
124  * Returns VNET_API_ERROR_UNIMPLEMENTED if the h/w driver
125  * doesn't implement the API.
126  *
127  * Node_index = ~0 => shut off redirection
128  */
129  rv = vnet_hw_interface_rx_redirect_to_node (sm->vnet_main, sw_if_index,
130  node_index);
131  return rv;
132 }
133 
134 static clib_error_t *
136  unformat_input_t * input,
137  vlib_cli_command_t * cmd)
138 {
139  sample_main_t * sm = &sample_main;
140  u32 sw_if_index = ~0;
141  int enable_disable = 1;
142 
143  int rv;
144 
145  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
146  if (unformat (input, "disable"))
147  enable_disable = 0;
148  else if (unformat (input, "%U", unformat_vnet_sw_interface,
149  sm->vnet_main, &sw_if_index))
150  ;
151  else
152  break;
153  }
154 
155  if (sw_if_index == ~0)
156  return clib_error_return (0, "Please specify an interface...");
157 
158  rv = sample_macswap_enable_disable (sm, sw_if_index, enable_disable);
159 
160  switch(rv) {
161  case 0:
162  break;
163 
164  case VNET_API_ERROR_INVALID_SW_IF_INDEX:
165  return clib_error_return
166  (0, "Invalid interface, only works on physical ports");
167  break;
168 
169  case VNET_API_ERROR_UNIMPLEMENTED:
170  return clib_error_return (0, "Device driver doesn't support redirection");
171  break;
172 
173  default:
174  return clib_error_return (0, "sample_macswap_enable_disable returned %d",
175  rv);
176  }
177  return 0;
178 }
179 
180 VLIB_CLI_COMMAND (sr_content_command, static) = {
181  .path = "sample macswap",
182  .short_help =
183  "sample macswap <interface-name> [disable]",
185 };
186 
187 /* API message handler */
190 {
192  sample_main_t * sm = &sample_main;
193  int rv;
194 
195  rv = sample_macswap_enable_disable (sm, ntohl(mp->sw_if_index),
196  (int) (mp->enable_disable));
197 
198  REPLY_MACRO(VL_API_SAMPLE_MACSWAP_ENABLE_DISABLE_REPLY);
199 }
200 
201 /* Set up the API message handling tables */
202 static clib_error_t *
204 {
205  sample_main_t * sm = &sample_main;
206 #define _(N,n) \
207  vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \
208  #n, \
209  vl_api_##n##_t_handler, \
210  vl_noop_handler, \
211  vl_api_##n##_t_endian, \
212  vl_api_##n##_t_print, \
213  sizeof(vl_api_##n##_t), 1);
215 #undef _
216 
217  return 0;
218 }
219 
221 {
222  sample_main_t * sm = &sample_main;
223  clib_error_t * error = 0;
224  u8 * name;
225 
226  name = format (0, "sample_%08x%c", api_version, 0);
227 
228  /* Ask for a correctly-sized block of API message decode slots */
230  ((char *) name, VL_MSG_FIRST_AVAILABLE);
231 
232  error = sample_plugin_api_hookup (vm);
233 
234  vec_free(name);
235 
236  return error;
237 }
238 
240 
241 
#define REPLY_MACRO(t)
Definition: sample.c:61
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
vnet_interface_main_t interface_main
Definition: vnet.h:64
int vnet_hw_interface_rx_redirect_to_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: interface.c:1022
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
static void vl_api_sample_macswap_enable_disable_t_handler(vl_api_sample_macswap_enable_disable_t *mp)
Definition: sample.c:189
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
unformat_function_t unformat_vnet_sw_interface
vlib_main_t * vlib_main
Definition: sample.h:31
ethernet_main_t * ethernet_main
Definition: plugin.h:27
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
ethernet_main_t * ethernet_main
Definition: sample.h:33
vlib_node_registration_t sample_node
(constructor) VLIB_REGISTER_NODE (sample_node)
Definition: node.c:38
sample_main_t sample_main
Definition: sample.h:36
int sample_macswap_enable_disable(sample_main_t *sm, u32 sw_if_index, int enable_disable)
Definition: sample.c:105
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:211
vnet_main_t * vnet_main
Definition: sample.h:32
unsigned int u32
Definition: types.h:88
static clib_error_t * sample_init(vlib_main_t *vm)
Definition: sample.c:220
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
VLIB_CLI_COMMAND(set_interface_ip_source_and_port_range_check_command, static)
static clib_error_t * sample_plugin_api_hookup(vlib_main_t *vm)
Definition: sample.c:203
unsigned char u8
Definition: types.h:56
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:492
vnet_main_t * vnet_main
Definition: plugin.h:26
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
vnet_sw_interface_type_t type
Definition: interface.h:410
u16 vl_msg_api_get_msg_ids(char *name, int n)
Definition: api_shared.c:1269
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
static clib_error_t * macswap_enable_disable_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: sample.c:135
clib_error_t * vlib_plugin_register(vlib_main_t *vm, vnet_plugin_handoff_t *h, int from_early_init)
Definition: sample.c:90
u16 msg_id_base
Definition: sample.h:28
#define foreach_sample_plugin_api_msg
Definition: sample.c:79