FD.io VPP  v18.07-rc0-415-g6c78436
Vector Packet Processing
gbp_endpoint.c
Go to the documentation of this file.
1 /*
2  * gbp.h : Group Based Policy
3  *
4  * Copyright (c) 2018 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
20 
22 
23 /**
24  * IP4 destintion address to destination EPG mapping table
25  */
26 typedef struct gbp_ip4_to_epg_db_t_
27 {
28  /**
29  * use a simple hash table
30  */
33 
35 
36 /**
37  * IP6 destintion address to destination EPG mapping table
38  */
39 typedef struct gbp_ip6_to_epg_db_t_
40 {
41  /**
42  * use a memroy hash table
43  */
46 
48 
49 
50 const static gbp_itf_t ITF_INVALID = {
52  .gi_ref_count = 0,
53 };
54 
56 
57 /**
58  * Pool of GBP endpoints
59  */
61 
62 /**
63  * DB of endpoints
64  */
66 
67 static void
68 gbp_ip_epg_update (const ip46_address_t * ip, epg_id_t epg_id)
69 {
70  /*
71  * we are dealing only with addresses here so this limited
72  * is_ip4 check is ok
73  */
74  if (ip46_address_is_ip4 (ip))
75  {
76  hash_set (gbp_ip4_to_epg_db.g4ie_hash, ip->ip4.as_u32, epg_id);
77  }
78  else
79  {
80  hash_set_mem (gbp_ip6_to_epg_db.g6ie_hash, &ip->ip6, epg_id);
81  }
82 }
83 
84 static void
85 gbp_ip_epg_delete (const ip46_address_t * ip)
86 {
87  if (ip46_address_is_ip4 (ip))
88  {
89  hash_unset (gbp_ip4_to_epg_db.g4ie_hash, ip->ip4.as_u32);
90  }
91  else
92  {
93  hash_unset_mem (gbp_ip6_to_epg_db.g6ie_hash, &ip->ip6);
94  }
95 }
96 
97 void
98 gbp_itf_epg_update (u32 sw_if_index, epg_id_t src_epg, u8 do_policy)
99 {
100  vec_validate_init_empty (gbp_itf_to_epg_db.gte_vec,
101  sw_if_index, ITF_INVALID);
102 
103  if (0 == gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count)
104  {
105  l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_SRC_CLASSIFY,
106  1);
107  l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_FWD, 1);
108  if (do_policy)
109  l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_GBP_POLICY,
110  1);
111  }
112  gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg = src_epg;
113  gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count++;
114 }
115 
116 void
117 gbp_itf_epg_delete (u32 sw_if_index)
118 {
119  if (vec_len (gbp_itf_to_epg_db.gte_vec) <= sw_if_index)
120  return;
121 
122  if (1 == gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count)
123  {
124  gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg = EPG_INVALID;
125 
126  l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_SRC_CLASSIFY,
127  0);
128  l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_FWD, 0);
129  l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_GBP_POLICY, 0);
130  }
131  gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count--;
132 }
133 
134 int
136  const ip46_address_t * ip, epg_id_t epg_id)
137 {
138  gbp_endpoint_key_t key = {
139  .gek_ip = *ip,
140  .gek_sw_if_index = sw_if_index,
141  };
142  gbp_endpoint_group_t *gepg;
143  gbp_endpoint_t *gbpe;
144  uword *p;
145 
146  gepg = gbp_endpoint_group_find (epg_id);
147 
148  if (NULL == gepg)
149  return (VNET_API_ERROR_NO_SUCH_ENTRY);
150 
151  p = hash_get_mem (gbp_endpoint_db, &key);
152 
153  if (p)
154  {
155  gbpe = pool_elt_at_index (gbp_endpoint_pool, p[0]);
156  }
157  else
158  {
159  pool_get (gbp_endpoint_pool, gbpe);
160 
161  gbpe->ge_key = clib_mem_alloc (sizeof (gbp_endpoint_key_t));
162  clib_memcpy (gbpe->ge_key, &key, sizeof (gbp_endpoint_key_t));
163 
164  hash_set_mem (gbp_endpoint_db, gbpe->ge_key, gbpe - gbp_endpoint_pool);
165  }
166 
167  gbpe->ge_epg_id = epg_id;
168 
170 
171  if (!ip46_address_is_zero (&gbpe->ge_key->gek_ip))
172  gbp_ip_epg_update (&gbpe->ge_key->gek_ip, gbpe->ge_epg_id);
173 
174  /*
175  * send a gratuitous ARP on the EPG's uplink. this is done so that if
176  * this EP has moved from some other place in the 'fabric', upstream
177  * devices are informed
178  */
179  if (ip46_address_is_ip4 (&gbpe->ge_key->gek_ip))
181  &gbpe->ge_key->gek_ip.ip4,
183  else
185  &gbpe->ge_key->gek_ip.ip6,
187 
188  return (0);
189 }
190 
191 void
192 gbp_endpoint_delete (u32 sw_if_index, const ip46_address_t * ip)
193 {
194  gbp_endpoint_key_t key = {
195  .gek_ip = *ip,
196  .gek_sw_if_index = sw_if_index,
197  };
198  gbp_endpoint_t *gbpe;
199  uword *p;
200 
201  p = hash_get_mem (gbp_endpoint_db, &key);
202 
203  if (p)
204  {
205  gbpe = pool_elt_at_index (gbp_endpoint_pool, p[0]);
206 
208 
210  if (!ip46_address_is_zero (&gbpe->ge_key->gek_ip))
211  gbp_ip_epg_delete (&gbpe->ge_key->gek_ip);
212 
213  clib_mem_free (gbpe->ge_key);
214 
215  pool_put (gbp_endpoint_pool, gbpe);
216  }
217 }
218 
219 void
221 {
222  gbp_endpoint_t *gbpe;
223 
224  /* *INDENT-OFF* */
225  pool_foreach(gbpe, gbp_endpoint_pool,
226  {
227  if (!cb(gbpe, ctx))
228  break;
229  });
230  /* *INDENT-ON* */
231 }
232 
233 static clib_error_t *
235  unformat_input_t * input, vlib_cli_command_t * cmd)
236 {
237  vnet_main_t *vnm = vnet_get_main ();
238  epg_id_t epg_id = EPG_INVALID;
239  ip46_address_t ip = { };
240  u32 sw_if_index = ~0;
241  u8 add = 1;
242 
244  {
245  if (unformat (input, "%U", unformat_vnet_sw_interface,
246  vnm, &sw_if_index))
247  ;
248  else if (unformat (input, "add"))
249  add = 1;
250  else if (unformat (input, "del"))
251  add = 0;
252  else if (unformat (input, "epg %d", &epg_id))
253  ;
254  else if (unformat (input, "ip %U", unformat_ip4_address, &ip.ip4))
255  ;
256  else if (unformat (input, "ip %U", unformat_ip6_address, &ip.ip6))
257  ;
258  else
259  break;
260  }
261 
262  if (~0 == sw_if_index)
263  return clib_error_return (0, "interface must be specified");
264  if (EPG_INVALID == epg_id)
265  return clib_error_return (0, "EPG-ID must be specified");
266  if (ip46_address_is_zero (&ip))
267  return clib_error_return (0, "IP address must be specified");
268 
269  if (add)
270  gbp_endpoint_update (sw_if_index, &ip, epg_id);
271  else
272  gbp_endpoint_delete (sw_if_index, &ip);
273 
274  return (NULL);
275 }
276 
277 
278 /*?
279  * Configure a GBP Endpoint
280  *
281  * @cliexpar
282  * @cliexstart{set gbp endpoint [del] <interface> epg <ID> ip <IP>}
283  * @cliexend
284  ?*/
285 /* *INDENT-OFF* */
286 VLIB_CLI_COMMAND (gbp_endpoint_cli_node, static) = {
287  .path = "gbp endpoint",
288  .short_help = "gbp endpoint [del] <interface> epg <ID> ip <IP>",
289  .function = gbp_endpoint_cli,
290 };
291 /* *INDENT-ON* */
292 
293 static int
295 {
296  vnet_main_t *vnm = vnet_get_main ();
297  vlib_main_t *vm;
298 
299  vm = ctx;
300  vlib_cli_output (vm, " {%U, %U} -> %d",
302  gbpe->ge_key->gek_sw_if_index,
304  gbpe->ge_epg_id);
305 
306  return (1);
307 }
308 
309 static clib_error_t *
311  unformat_input_t * input, vlib_cli_command_t * cmd)
312 {
313  vnet_main_t *vnm = vnet_get_main ();
314  ip46_address_t ip, *ipp;
315  epg_id_t epg_id;
316  u32 sw_if_index;
317 
318  vlib_cli_output (vm, "Endpoints:");
320 
321  vlib_cli_output (vm, "\nSource interface to EPG:");
322 
323  vec_foreach_index (sw_if_index, gbp_itf_to_epg_db.gte_vec)
324  {
325  if (EPG_INVALID != gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg)
326  {
327  vlib_cli_output (vm, " %U -> %d",
328  format_vnet_sw_if_index_name, vnm, sw_if_index,
329  gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg);
330  }
331  }
332 
333  vlib_cli_output (vm, "\nDestination IP4 to EPG:");
334 
335  /* *INDENT-OFF* */
336  hash_foreach (ip.ip4.as_u32, epg_id, gbp_ip4_to_epg_db.g4ie_hash,
337  {
338  vlib_cli_output (vm, " %U -> %d", format_ip46_address, &ip,
339  IP46_TYPE_IP4, epg_id);
340  });
341  /* *INDENT-ON* */
342 
343  vlib_cli_output (vm, "\nDestination IP6 to EPG:");
344 
345  /* *INDENT-OFF* */
346  hash_foreach_mem (ipp, epg_id, gbp_ip6_to_epg_db.g6ie_hash,
347  {
348  vlib_cli_output (vm, " %U -> %d", format_ip46_address, ipp,
349  IP46_TYPE_IP6, epg_id);
350  });
351  /* *INDENT-ON* */
352 
353  return (NULL);
354 }
355 
356 
357 /*?
358  * Show Group Based Policy Endpoints and derived information
359  *
360  * @cliexpar
361  * @cliexstart{show gbp endpoint}
362  * @cliexend
363  ?*/
364 /* *INDENT-OFF* */
365 VLIB_CLI_COMMAND (gbp_endpoint_show_node, static) = {
366  .path = "show gbp endpoint",
367  .short_help = "show gbp endpoint\n",
368  .function = gbp_endpoint_show,
369 };
370 /* *INDENT-ON* */
371 
372 static clib_error_t *
374 {
376  sizeof (gbp_endpoint_key_t),
377  sizeof (u32));
378  gbp_ip6_to_epg_db.g6ie_hash =
379  hash_create_mem (0, sizeof (ip6_address_t), sizeof (u32));
380  return 0;
381 }
382 
384 
385 /*
386  * fd.io coding-style-patch-verification: ON
387  *
388  * Local Variables:
389  * eval: (c-set-style "gnu")
390  * End:
391  */
#define vec_foreach_index(var, v)
Iterate over vector indices.
#define hash_set(h, key, value)
Definition: hash.h:255
A Group Based Policy Endpoint.
Definition: gbp_endpoint.h:43
#define hash_unset(h, key)
Definition: hash.h:261
void gbp_itf_epg_delete(u32 sw_if_index)
Definition: gbp_endpoint.c:117
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
static gbp_ip6_to_epg_db_t gbp_ip6_to_epg_db
Definition: gbp_endpoint.c:47
#define NULL
Definition: clib.h:55
IP6 destintion address to destination EPG mapping table.
Definition: gbp_endpoint.c:39
Interface to source EPG DB - a per-interface vector.
Definition: gbp_endpoint.h:70
gbp_endpoint_key_t * ge_key
The endpoint&#39;s interface and IP address.
Definition: gbp_endpoint.h:48
format_function_t format_ip46_address
Definition: format.h:61
#define hash_set_mem(h, key, value)
Definition: hash.h:275
unformat_function_t unformat_vnet_sw_interface
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:227
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
gbp_itf_to_epg_db_t gbp_itf_to_epg_db
DP functions and databases.
Definition: gbp_endpoint.c:55
static void gbp_ip_epg_update(const ip46_address_t *ip, epg_id_t epg_id)
Definition: gbp_endpoint.c:68
static gbp_endpoint_t * gbp_endpoint_pool
Pool of GBP endpoints.
Definition: gbp_endpoint.c:60
uword * g6ie_hash
use a memroy hash table
Definition: gbp_endpoint.c:44
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:440
unformat_function_t unformat_ip4_address
Definition: format.h:76
static int gbp_endpoint_show_one(gbp_endpoint_t *gbpe, void *ctx)
Definition: gbp_endpoint.c:294
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:156
u32 gek_sw_if_index
The interface on which the EP is connected.
Definition: gbp_endpoint.h:30
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:442
gbp_endpoint_group_t * gbp_endpoint_group_find(epg_id_t epg_id)
#define clib_error_return(e, args...)
Definition: error.h:99
u32 epg_id_t
Definition: gbp_types.h:21
static gbp_ip4_to_epg_db_t gbp_ip4_to_epg_db
Definition: gbp_endpoint.c:34
unsigned int u32
Definition: types.h:88
void l2output_intf_bitmap_enable(u32 sw_if_index, u32 feature_bitmap, u32 enable)
Enable (or disable) the feature in the bitmap for the given interface.
Definition: l2_output.c:617
int gbp_endpoint_update(u32 sw_if_index, const ip46_address_t *ip, epg_id_t epg_id)
Definition: gbp_endpoint.c:135
#define hash_create_mem(elts, key_bytes, value_bytes)
Definition: hash.h:661
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:461
#define hash_unset_mem(h, key)
Definition: hash.h:291
epg_id_t gi_epg
Definition: gbp_endpoint.h:63
struct _unformat_input_t unformat_input_t
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:273
#define hash_foreach_mem(key_var, value_var, h, body)
Definition: hash.h:461
An Endpoint Group representation.
static uword * gbp_endpoint_db
DB of endpoints.
Definition: gbp_endpoint.c:65
#define ip46_address_is_ip4(ip46)
Definition: ip6_packet.h:81
unformat_function_t unformat_ip6_address
Definition: format.h:97
void gbp_itf_epg_update(u32 sw_if_index, epg_id_t src_epg, u8 do_policy)
Port to EPG mapping management.
Definition: gbp_endpoint.c:98
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
ip46_address_t gek_ip
The IP[46] address of the endpoint.
Definition: gbp_endpoint.h:35
Result of a interface to EPG mapping.
Definition: gbp_endpoint.h:61
vlib_main_t * vm
Definition: buffer.c:294
void gbp_endpoint_walk(gbp_endpoint_cb_t cb, void *ctx)
Definition: gbp_endpoint.c:220
uword * g4ie_hash
use a simple hash table
Definition: gbp_endpoint.c:31
void send_ip6_na_w_addr(vlib_main_t *vm, const ip6_address_t *addr, u32 sw_if_index)
#define clib_memcpy(a, b, c)
Definition: string.h:75
static clib_error_t * gbp_endpoint_init(vlib_main_t *vm)
Definition: gbp_endpoint.c:373
gbp_itf_t * gte_vec
Definition: gbp_endpoint.h:72
void send_ip4_garp_w_addr(vlib_main_t *vm, const ip4_address_t *ip4_addr, u32 sw_if_index)
Definition: arp.c:2562
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
The key for an Endpoint.
Definition: gbp_endpoint.h:25
struct gbp_ip6_to_epg_db_t_ gbp_ip6_to_epg_db_t
IP6 destintion address to destination EPG mapping table.
long ctx[MAX_CONNS]
Definition: main.c:126
void gbp_endpoint_delete(u32 sw_if_index, const ip46_address_t *ip)
Definition: gbp_endpoint.c:192
#define EPG_INVALID
Definition: gbp_types.h:22
static void clib_mem_free(void *p)
Definition: mem.h:179
u32 gepg_uplink_sw_if_index
the uplink interface dedicated to the EPG
static clib_error_t * gbp_endpoint_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: gbp_endpoint.c:310
int(* gbp_endpoint_cb_t)(gbp_endpoint_t *gbpe, void *ctx)
Definition: gbp_endpoint.h:79
static void * clib_mem_alloc(uword size)
Definition: mem.h:112
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
u32 l2input_intf_bitmap_enable(u32 sw_if_index, u32 feature_bitmap, u32 enable)
Enable (or disable) the feature in the bitmap for the given interface.
Definition: l2_input.c:520
struct gbp_ip4_to_epg_db_t_ gbp_ip4_to_epg_db_t
IP4 destintion address to destination EPG mapping table.
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
epg_id_t ge_epg_id
The endpoint&#39;s designated EPG.
Definition: gbp_endpoint.h:53
u64 uword
Definition: types.h:112
IP4 destintion address to destination EPG mapping table.
Definition: gbp_endpoint.c:26
u32 gi_ref_count
Definition: gbp_endpoint.h:64
#define hash_get_mem(h, key)
Definition: hash.h:269
#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:486
#define ip46_address_is_zero(ip46)
Definition: ip6_packet.h:86
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:681
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
static clib_error_t * gbp_endpoint_cli(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: gbp_endpoint.c:234
static void gbp_ip_epg_delete(const ip46_address_t *ip)
Definition: gbp_endpoint.c:85
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169