FD.io VPP  v21.01.1
Vector Packet Processing
gbp_recirc.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 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 <plugins/gbp/gbp_recirc.h>
19 #include <plugins/gbp/gbp_itf.h>
20 
21 #include <vnet/dpo/dvr_dpo.h>
22 #include <vnet/fib/fib_table.h>
23 
24 #include <vlib/unix/plugin.h>
25 
26 /**
27  * Pool of GBP recircs
28  */
30 
31 /**
32  * Recirc configs keyed by sw_if_index
33  */
35 
36 /**
37  * logger
38  */
40 
41 /**
42  * L2 Emulation enable/disable symbols
43  */
44 static void (*l2e_enable) (u32 sw_if_index);
45 static void (*l2e_disable) (u32 sw_if_index);
46 
47 #define GBP_RECIRC_DBG(...) \
48  vlib_log_debug (gr_logger, __VA_ARGS__);
49 
50 u8 *
51 format_gbp_recirc (u8 * s, va_list * args)
52 {
53  gbp_recirc_t *gr = va_arg (*args, gbp_recirc_t *);
54  vnet_main_t *vnm = vnet_get_main ();
55 
56  return format (s, " %U, sclass:%d, ext:%d",
58  gr->gr_sw_if_index, gr->gr_sclass, gr->gr_is_ext);
59 }
60 
61 int
63 {
64  gbp_recirc_t *gr;
65  index_t gri;
66 
68 
70 
71  if (INDEX_INVALID == gri)
72  {
74  fib_protocol_t fproto;
75  index_t ggi;
76 
77  ggi = gbp_endpoint_group_find (sclass);
78 
79  if (INDEX_INVALID == ggi)
80  return (VNET_API_ERROR_NO_SUCH_ENTRY);
81 
83  pool_get_zero (gbp_recirc_pool, gr);
84  gri = gr - gbp_recirc_pool;
85 
86  gr->gr_sclass = sclass;
87  gr->gr_is_ext = is_ext;
89 
90  /*
91  * IP enable the recirc interface
92  */
95 
96  /*
97  * cache the FIB indicies of the EPG
98  */
99  gr->gr_epgi = ggi;
100 
101  gg = gbp_endpoint_group_get (gr->gr_epgi);
102  FOR_EACH_FIB_IP_PROTOCOL (fproto)
103  {
104  gr->gr_fib_index[fib_proto_to_dpo (fproto)] =
106  }
107 
108  /*
109  * bind to the bridge-domain of the EPG
110  */
112 
113  /*
114  * set the interface into L2 emulation mode
115  */
117 
118  /*
119  * Packets on the recirculation interface are subject to src-EPG
120  * classification. Recirc interfaces are L2-emulation mode.
121  * for internal EPGs this is via an LPM on all external subnets.
122  * for external EPGs this is via a port mapping.
123  */
124  if (gr->gr_is_ext)
125  {
127  /*
128  * recirc is for post-NAT translation packets going into
129  * the external EPG, these are classified to the NAT EPG
130  * based on its port
131  */
134  (vnet_get_main (), gr->gr_sw_if_index));
135  gbp_endpoint_update_and_lock (GBP_ENDPOINT_SRC_CP,
136  gr->gr_sw_if_index,
137  NULL, &mac, INDEX_INVALID,
140  NULL, NULL, &gr->gr_ep);
141  vnet_feature_enable_disable ("ip4-unicast",
142  "ip4-gbp-src-classify",
143  gr->gr_sw_if_index, 1, 0, 0);
144  vnet_feature_enable_disable ("ip6-unicast",
145  "ip6-gbp-src-classify",
146  gr->gr_sw_if_index, 1, 0, 0);
147  }
148  else
149  {
150  /*
151  * recirc is for pre-NAT translation packets coming from
152  * the external EPG, these are classified based on a LPM
153  * in the EPG's route-domain
154  */
155  vnet_feature_enable_disable ("ip4-unicast",
156  "ip4-gbp-lpm-classify",
157  gr->gr_sw_if_index, 1, 0, 0);
158  vnet_feature_enable_disable ("ip6-unicast",
159  "ip6-gbp-lpm-classify",
160  gr->gr_sw_if_index, 1, 0, 0);
161  }
162 
163  gbp_recirc_db[sw_if_index] = gri;
164  }
165  else
166  {
167  gr = gbp_recirc_get (gri);
168  }
169 
170  GBP_RECIRC_DBG ("add: %U", format_gbp_recirc, gr);
171  return (0);
172 }
173 
174 int
176 {
177  gbp_recirc_t *gr;
178  index_t gri;
179 
180  if (vec_len (gbp_recirc_db) <= sw_if_index)
181  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
182  gri = gbp_recirc_db[sw_if_index];
183 
184  if (INDEX_INVALID != gri)
185  {
186  gr = pool_elt_at_index (gbp_recirc_pool, gri);
187 
188  GBP_RECIRC_DBG ("del: %U", format_gbp_recirc, gr);
189 
190  if (gr->gr_is_ext)
191  {
192  gbp_endpoint_unlock (GBP_ENDPOINT_SRC_CP, gr->gr_ep);
193  vnet_feature_enable_disable ("ip4-unicast",
194  "ip4-gbp-src-classify",
195  gr->gr_sw_if_index, 0, 0, 0);
196  vnet_feature_enable_disable ("ip6-unicast",
197  "ip6-gbp-src-classify",
198  gr->gr_sw_if_index, 0, 0, 0);
199  }
200  else
201  {
202  vnet_feature_enable_disable ("ip4-unicast",
203  "ip4-gbp-lpm-classify",
204  gr->gr_sw_if_index, 0, 0, 0);
205  vnet_feature_enable_disable ("ip6-unicast",
206  "ip6-gbp-lpm-classify",
207  gr->gr_sw_if_index, 0, 0, 0);
208  }
209 
213 
214  gbp_itf_unlock (&gr->gr_itf);
215 
218  pool_put (gbp_recirc_pool, gr);
219  return (0);
220  }
221  return VNET_API_ERROR_NO_SUCH_ENTRY;
222 }
223 
224 void
226 {
227  gbp_recirc_t *ge;
228 
229  /* *INDENT-OFF* */
230  pool_foreach (ge, gbp_recirc_pool)
231  {
232  if (!cb(ge, ctx))
233  break;
234  }
235  /* *INDENT-ON* */
236 }
237 
238 static walk_rc_t
240 {
241  vlib_cli_output (ctx, " %U", format_gbp_recirc, gr);
242 
243  return (WALK_CONTINUE);
244 }
245 
246 static clib_error_t *
248  unformat_input_t * input, vlib_cli_command_t * cmd)
249 {
250  vlib_cli_output (vm, "Recirculation-Interfaces:");
252 
253  return (NULL);
254 }
255 
256 /*?
257  * Show Group Based Policy Recircs and derived information
258  *
259  * @cliexpar
260  * @cliexstart{show gbp recirc}
261  * @cliexend
262  ?*/
263 /* *INDENT-OFF* */
264 VLIB_CLI_COMMAND (gbp_recirc_show_node, static) = {
265  .path = "show gbp recirc",
266  .short_help = "show gbp recirc\n",
267  .function = gbp_recirc_show,
268 };
269 /* *INDENT-ON* */
270 
271 static clib_error_t *
273 {
274  gr_logger = vlib_log_register_class ("gbp", "recirc");
275 
276  l2e_enable =
277  vlib_get_plugin_symbol ("l2e_plugin.so", "l2_emulation_enable");
278  l2e_disable =
279  vlib_get_plugin_symbol ("l2e_plugin.so", "l2_emulation_disable");
280 
281  return (NULL);
282 }
283 
285 
286 /*
287  * fd.io coding-style-patch-verification: ON
288  *
289  * Local Variables:
290  * eval: (c-set-style "gnu")
291  * End:
292  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:338
index_t gr_epgi
The index of the EPG.
Definition: gbp_recirc.h:39
static void(* l2e_disable)(u32 sw_if_index)
Definition: gbp_recirc.c:45
bool is_ext
Definition: gbp.api:227
sclass_t gr_sclass
EPG ID that packets will classify to when they arrive on this recirc.
Definition: gbp_recirc.h:34
u16 sclass_t
Definition: gbp_types.h:25
vl_api_mac_address_t mac
Definition: l2.api:502
void gbp_endpoint_unlock(gbp_endpoint_src_t src, index_t gei)
Definition: gbp_endpoint.c:916
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
int gbp_recirc_add(u32 sw_if_index, sclass_t sclass, u8 is_ext)
Definition: gbp_recirc.c:62
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
Definition: pool.h:254
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:527
void gbp_itf_unlock(gbp_itf_hdl_t *gh)
Definition: gbp_itf.c:288
static walk_rc_t gbp_recirc_show_one(gbp_recirc_t *gr, void *ctx)
Definition: gbp_recirc.c:239
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:41
vlib_main_t * vm
Definition: in2out_ed.c:1580
static clib_error_t * gbp_recirc_init(vlib_main_t *vm)
Definition: gbp_recirc.c:272
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
index_t gr_ep
The endpoint created to represent the reric interface.
Definition: gbp_recirc.h:60
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
gbp_itf_hdl_t gr_itf
Definition: gbp_recirc.h:55
enum walk_rc_t_ walk_rc_t
Walk return code.
u32 vlib_log_class_t
Definition: vlib.h:51
u8 gr_is_ext
Is the interface for packets post-NAT translation (i.e.
Definition: gbp_recirc.h:50
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
description fragment has unexpected format
Definition: map.api:433
gbp_endpoint_group_t * gbp_endpoint_group_get(index_t i)
A GBP recirculation interface representation Thes interfaces join Bridge domains that are internal to...
Definition: gbp_recirc.h:29
unsigned int u32
Definition: types.h:88
vlib_log_class_t gr_logger
logger
Definition: gbp_recirc.c:39
static const u8 * vnet_sw_interface_get_hw_address(vnet_main_t *vnm, u32 sw_if_index)
u32 gr_fib_index[DPO_PROTO_NUM]
FIB indices the EPG is mapped to.
Definition: gbp_recirc.h:44
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
static_always_inline void mac_address_from_bytes(mac_address_t *mac, const u8 *bytes)
Definition: mac_address.h:92
void ip4_sw_interface_enable_disable(u32 sw_if_index, u32 is_enable)
Definition: ip4_forward.c:601
long ctx[MAX_CONNS]
Definition: main.c:144
gbp_recirc_t * gbp_recirc_pool
Pool of GBP recircs.
Definition: gbp_recirc.c:29
struct _unformat_input_t unformat_input_t
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:301
u16 sclass
Definition: gbp.api:131
walk_rc_t(* gbp_recirc_cb_t)(gbp_recirc_t *gbpe, void *ctx)
Definition: gbp_recirc.h:66
int gbp_endpoint_update_and_lock(gbp_endpoint_src_t src, u32 sw_if_index, const ip46_address_t *ips, const mac_address_t *mac, index_t gbdi, index_t grdi, sclass_t sclass, gbp_endpoint_flags_t flags, const ip46_address_t *tun_src, const ip46_address_t *tun_dst, u32 *handle)
Definition: gbp_endpoint.c:820
An Endpoint Group representation.
static clib_error_t * gbp_recirc_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: gbp_recirc.c:247
static gbp_recirc_t * gbp_recirc_get(u32 sw_if_index)
Definition: gbp_recirc.h:76
gbp_itf_hdl_t gbp_itf_l2_add_and_lock(u32 sw_if_index, index_t gbi)
Definition: gbp_itf.c:198
void gbp_endpoint_group_lock(index_t ggi)
u32 gr_sw_if_index
Definition: gbp_recirc.h:54
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
#define GBP_RECIRC_DBG(...)
Definition: gbp_recirc.c:47
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
static void(* l2e_enable)(u32 sw_if_index)
L2 Emulation enable/disable symbols.
Definition: gbp_recirc.c:44
void gbp_endpoint_group_unlock(index_t ggi)
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:343
void * vlib_get_plugin_symbol(char *plugin_name, char *symbol_name)
Definition: plugin.c:38
void gbp_recirc_walk(gbp_recirc_cb_t cb, void *ctx)
Definition: gbp_recirc.c:225
index_t * gbp_recirc_db
Recirc configs keyed by sw_if_index.
Definition: gbp_recirc.c:34
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:47
#define FOR_EACH_FIB_IP_PROTOCOL(_item)
Definition: fib_types.h:69
u8 * format_gbp_recirc(u8 *s, va_list *args)
Definition: gbp_recirc.c:51
int gbp_recirc_delete(u32 sw_if_index)
Definition: gbp_recirc.c:175
index_t gbp_endpoint_group_find(sclass_t sclass)
index_t gbp_endpoint_group_get_fib_index(const gbp_endpoint_group_t *gg, fib_protocol_t fproto)
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:556
u8 ge
Definition: ip_types.api:160
void ip6_sw_interface_enable_disable(u32 sw_if_index, u32 is_enable)
Definition: ip6_forward.c:240
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:303
index_t gg_gbd
Bridge-domain ID the EPG is in.