FD.io VPP  v19.04.1-1-ge4a0f9f
Vector Packet Processing
gbp_policy_node.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.h>
18 
21 
22 #define foreach_gbp_policy \
23  _(DENY, "deny") \
24  _(REFLECTION, "reflection")
25 
26 typedef enum
27 {
28 #define _(sym,str) GBP_POLICY_ERROR_##sym,
30 #undef _
33 
34 static char *gbp_policy_error_strings[] = {
35 #define _(sym,string) string,
37 #undef _
38 };
39 
40 typedef enum
41 {
45 
46 /**
47  * per-packet trace data
48  */
49 typedef struct gbp_policy_trace_t_
50 {
51  /* per-pkt trace data */
58 
61 {
62  etype = clib_net_to_host_u16 (etype);
63 
64  switch (etype)
65  {
66  case ETHERNET_TYPE_IP4:
67  return (DPO_PROTO_IP4);
68  case ETHERNET_TYPE_IP6:
69  return (DPO_PROTO_IP6);
70  }
71 
72  return (DPO_PROTO_NONE);
73 }
74 
77 {
78  const ethernet_header_t *eth0;
79  const dpo_id_t *dpo;
80  dpo_proto_t dproto;
81 
82  eth0 = vlib_buffer_get_current (b0);
83  /* pop the ethernet header to prepare for L3 rewrite */
84  vlib_buffer_advance (b0, vnet_buffer (b0)->l2.l2_len);
85 
86  dproto = ethertype_to_dpo_proto (eth0->type);
87  dpo = &gu->gu_dpo[GBP_POLICY_NODE_L2][dproto];
88 
89  /* save the LB index for the next node and reset the IP flow hash
90  * so it's recalculated */
91  vnet_buffer (b0)->ip.adj_index[VLIB_TX] = dpo->dpoi_index;
92  vnet_buffer (b0)->ip.flow_hash = 0;
93 
94  return (dpo->dpoi_next_node);
95 }
96 
99 {
100  u16 *et;
101 
103  {
104  if (*et == ethertype)
105  return (1);
106  }
107  return (0);
108 }
109 
110 static uword
112  vlib_node_runtime_t * node,
113  vlib_frame_t * frame, u8 is_port_based)
114 {
115  gbp_main_t *gm = &gbp_main;
117  u32 n_left_from, *from, *to_next;
118  u32 next_index, thread_index;
119  u32 n_allow_intra, n_allow_a_bit;
120 
121  next_index = 0;
122  n_left_from = frame->n_vectors;
123  from = vlib_frame_vector_args (frame);
124  thread_index = vm->thread_index;
125  n_allow_intra = n_allow_a_bit = 0;
126 
127  while (n_left_from > 0)
128  {
129  u32 n_left_to_next;
130 
131  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
132 
133  while (n_left_from > 0 && n_left_to_next > 0)
134  {
135  const ethernet_header_t *h0;
136  const gbp_endpoint_t *ge0;
137  const gbp_contract_t *gc0;
138  gbp_policy_next_t next0;
139  gbp_contract_key_t key0;
140  u32 bi0, sw_if_index0;
141  vlib_buffer_t *b0;
142  index_t gci0;
143 
144  gc0 = NULL;
145  next0 = GBP_POLICY_NEXT_DROP;
146  bi0 = from[0];
147  to_next[0] = bi0;
148  from += 1;
149  to_next += 1;
150  n_left_from -= 1;
151  n_left_to_next -= 1;
152 
153  b0 = vlib_get_buffer (vm, bi0);
154  h0 = vlib_buffer_get_current (b0);
155  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
156 
157  /*
158  * Reflection check; in and out on an ivxlan tunnel
159  */
160  if ((~0 != vxlan_gbp_tunnel_by_sw_if_index (sw_if_index0)) &&
161  (vnet_buffer2 (b0)->gbp.flags & VXLAN_GBP_GPFLAGS_R))
162  {
163  goto trace;
164  }
165 
166  /*
167  * If the A-bit is set then policy has already been applied
168  * and we skip enforcement here.
169  */
170  if (vnet_buffer2 (b0)->gbp.flags & VXLAN_GBP_GPFLAGS_A)
171  {
172  next0 = vnet_l2_feature_next (b0,
174  [is_port_based],
175  (is_port_based ?
176  L2OUTPUT_FEAT_GBP_POLICY_PORT :
177  L2OUTPUT_FEAT_GBP_POLICY_MAC));
178  n_allow_a_bit++;
179  key0.as_u32 = ~0;
180  goto trace;
181  }
182 
183  /*
184  * determine the src and dst EPG
185  */
186  if (is_port_based)
187  ge0 = gbp_endpoint_find_itf (sw_if_index0);
188  else
190  vnet_buffer (b0)->l2.bd_index);
191 
192  if (NULL != ge0)
193  key0.gck_dst = ge0->ge_fwd.gef_sclass;
194  else
195  {
196  /* If you cannot determine the destination EP then drop */
197  b0->error = node->errors[GBP_POLICY_ERROR_DROP_NO_DCLASS];
198  goto trace;
199  }
200  key0.gck_src = vnet_buffer2 (b0)->gbp.sclass;
201 
202  if (SCLASS_INVALID != key0.gck_src)
203  {
204  if (PREDICT_FALSE (key0.gck_src == key0.gck_dst))
205  {
206  /*
207  * intra-epg allowed
208  */
209  next0 =
212  [is_port_based],
213  (is_port_based ?
214  L2OUTPUT_FEAT_GBP_POLICY_PORT :
215  L2OUTPUT_FEAT_GBP_POLICY_MAC));
216  vnet_buffer2 (b0)->gbp.flags |= VXLAN_GBP_GPFLAGS_A;
217  n_allow_intra++;
218  }
219  else
220  {
221  gci0 = gbp_contract_find (&key0);
222 
223  if (INDEX_INVALID != gci0)
224  {
225  u32 rule_match_p0, trace_bitmap0;
226  fa_5tuple_opaque_t pkt_5tuple0;
227  u32 acl_pos_p0, acl_match_p0;
228  u8 is_ip60, l2_len0, action0;
229  const gbp_rule_t *gu;
230  u16 ether_type0;
231  const u8 *h0;
232 
234  (&gbp_contract_drop_counters, thread_index, gci0);
236  (&gbp_contract_permit_counters, thread_index, gci0);
237 
238  action0 = 0;
239  gc0 = gbp_contract_get (gci0);
240  l2_len0 = vnet_buffer (b0)->l2.l2_len;
241  h0 = vlib_buffer_get_current (b0);
242 
243  ether_type0 = *(u16 *) (h0 + l2_len0 - 2);
244 
245  if (!gbp_policy_is_ethertype_allowed (gc0, ether_type0))
246  {
247  /*
248  * black list model so drop
249  */
250  b0->error =
251  node->errors[GBP_POLICY_ERROR_DROP_ETHER_TYPE];
252 
255  thread_index,
256  gci0, 1, vlib_buffer_length_in_chain (vm, b0));
257 
258  goto trace;
259  }
260 
261  if ((ether_type0 ==
262  clib_net_to_host_u16 (ETHERNET_TYPE_IP6))
263  || (ether_type0 ==
264  clib_net_to_host_u16 (ETHERNET_TYPE_IP4)))
265  {
266  is_ip60 =
267  (ether_type0 ==
268  clib_net_to_host_u16 (ETHERNET_TYPE_IP6)) ? 1 :
269  0;
270  /*
271  * tests against the ACL
272  */
275  gc0->gc_lc_index, b0,
276  is_ip60,
277  /* is_input */ 0,
278  /* is_l2_path */ 1,
279  &pkt_5tuple0);
282  gc0->gc_lc_index,
283  &pkt_5tuple0,
284  is_ip60, &action0,
285  &acl_pos_p0,
286  &acl_match_p0,
287  &rule_match_p0,
288  &trace_bitmap0);
289 
290  if (action0 > 0)
291  {
292  vnet_buffer2 (b0)->gbp.flags |=
293  VXLAN_GBP_GPFLAGS_A;
294  gu =
295  gbp_rule_get (gc0->gc_rules[rule_match_p0]);
296 
297  switch (gu->gu_action)
298  {
299  case GBP_RULE_PERMIT:
300  next0 = vnet_l2_feature_next
301  (b0,
303  [is_port_based],
304  (is_port_based ?
305  L2OUTPUT_FEAT_GBP_POLICY_PORT :
306  L2OUTPUT_FEAT_GBP_POLICY_MAC));
307  break;
308  case GBP_RULE_DENY:
309  next0 = GBP_POLICY_NEXT_DROP;
310  break;
311  case GBP_RULE_REDIRECT:
312  next0 = gbp_rule_l2_redirect (gu, b0);
313  break;
314  }
315  }
316  }
317  if (next0 == GBP_POLICY_NEXT_DROP)
318  {
321  thread_index,
322  gci0, 1, vlib_buffer_length_in_chain (vm, b0));
323  b0->error =
324  node->errors[GBP_POLICY_ERROR_DROP_CONTRACT];
325  }
326  else
327  {
330  thread_index,
331  gci0, 1, vlib_buffer_length_in_chain (vm, b0));
332  }
333  }
334  else
335  {
336  b0->error =
337  node->errors[GBP_POLICY_ERROR_DROP_NO_CONTRACT];
338  }
339  }
340  }
341  else
342  {
343  /*
344  * the src EPG is not set when the packet arrives on an EPG
345  * uplink interface and we do not need to apply policy
346  */
347  next0 =
349  gpm->l2_output_feat_next[is_port_based],
350  (is_port_based ?
351  L2OUTPUT_FEAT_GBP_POLICY_PORT :
352  L2OUTPUT_FEAT_GBP_POLICY_MAC));
353  }
354 
355  trace:
356  if (PREDICT_FALSE ((b0->flags & VLIB_BUFFER_IS_TRACED)))
357  {
358  gbp_policy_trace_t *t =
359  vlib_add_trace (vm, node, b0, sizeof (*t));
360  t->sclass = key0.gck_src;
361  t->dst_epg = key0.gck_dst;
362  t->acl_index = (gc0 ? gc0->gc_acl_index : ~0);
363  t->allowed = (next0 != GBP_POLICY_NEXT_DROP);
364  t->flags = vnet_buffer2 (b0)->gbp.flags;
365  }
366 
367  /* verify speculative enqueue, maybe switch current next frame */
368  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
369  to_next, n_left_to_next,
370  bi0, next0);
371  }
372 
373  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
374  }
375 
377  GBP_POLICY_ERROR_ALLOW_INTRA, n_allow_intra);
379  GBP_POLICY_ERROR_ALLOW_A_BIT, n_allow_a_bit);
380 
381  return frame->n_vectors;
382 }
383 
385  vlib_node_runtime_t * node,
386  vlib_frame_t * frame)
387 {
388  return (gbp_policy_inline (vm, node, frame, 1));
389 }
390 
392  vlib_node_runtime_t * node,
393  vlib_frame_t * frame)
394 {
395  return (gbp_policy_inline (vm, node, frame, 0));
396 }
397 
398 /* packet trace format function */
399 static u8 *
400 format_gbp_policy_trace (u8 * s, va_list * args)
401 {
402  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
403  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
404  gbp_policy_trace_t *t = va_arg (*args, gbp_policy_trace_t *);
405 
406  s =
407  format (s, "sclass:%d, dst:%d, acl:%d allowed:%d flags:%U",
408  t->sclass, t->dst_epg, t->acl_index, t->allowed,
410 
411  return s;
412 }
413 
414 /* *INDENT-OFF* */
416  .name = "gbp-policy-port",
417  .vector_size = sizeof (u32),
418  .format_trace = format_gbp_policy_trace,
419  .type = VLIB_NODE_TYPE_INTERNAL,
420 
421  .n_errors = ARRAY_LEN(gbp_policy_error_strings),
422  .error_strings = gbp_policy_error_strings,
423 
424  .n_next_nodes = GBP_POLICY_N_NEXT,
425  .next_nodes = {
426  [GBP_POLICY_NEXT_DROP] = "error-drop",
427  },
428 };
429 
431  .name = "gbp-policy-mac",
432  .vector_size = sizeof (u32),
433  .format_trace = format_gbp_policy_trace,
434  .type = VLIB_NODE_TYPE_INTERNAL,
435 
436  .n_errors = ARRAY_LEN(gbp_policy_error_strings),
437  .error_strings = gbp_policy_error_strings,
438 
439  .n_next_nodes = GBP_POLICY_N_NEXT,
440  .next_nodes = {
441  [GBP_POLICY_NEXT_DROP] = "error-drop",
442  },
443 };
444 
445 /* *INDENT-ON* */
446 
447 /*
448  * fd.io coding-style-patch-verification: ON
449  *
450  * Local Variables:
451  * eval: (c-set-style "gnu")
452  * End:
453  */
u16 * gc_allowed_ethertypes
An ethertype whitelist.
Definition: gbp_contract.h:137
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
gbp_policy_next_t
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: vlib_api_cli.c:862
A Group Based Policy Endpoint.
Definition: gbp_endpoint.h:187
#define CLIB_UNUSED(x)
Definition: clib.h:82
static u8 gbp_policy_is_ethertype_allowed(const gbp_contract_t *gc0, u16 ethertype)
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 thread_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
Definition: counter.h:220
gbp_endpoint_fwd_t ge_fwd
Definition: gbp_endpoint.h:205
#define vnet_buffer2(b)
Definition: buffer.h:428
#define NULL
Definition: clib.h:58
The key for an Contract.
Definition: gbp_contract.h:34
u32 thread_index
Definition: main.h:197
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
gbp_policy_next_t
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
#define VLIB_NODE_FN(node)
Definition: node.h:201
static gbp_rule_t * gbp_rule_get(index_t gui)
Definition: gbp_contract.h:198
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:469
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:366
vlib_node_registration_t gbp_policy_mac_node
(constructor) VLIB_REGISTER_NODE (gbp_policy_mac_node)
unsigned char u8
Definition: types.h:56
static u32 vnet_l2_feature_next(vlib_buffer_t *b, u32 *next_nodes, u32 feat_bit)
Return the graph node index for the feature corresponding to the next set bit after clearing the curr...
Definition: feat_bitmap.h:94
static acl_plugin_methods_t acl_plugin
u32 l2_output_feat_next[2][32]
Next nodes for L2 output features.
Definition: gbp.h:59
#define always_inline
Definition: clib.h:98
u8 * format_vxlan_gbp_header_gpflags(u8 *s, va_list *args)
u8 dst_address[6]
Definition: packet.h:55
#define DPO_PROTO_NONE
Definition: dpo.h:71
static u32 vxlan_gbp_tunnel_by_sw_if_index(u32 sw_if_index)
Definition: vxlan_gbp.h:230
per-packet trace data
static_always_inline gbp_endpoint_t * gbp_endpoint_find_mac(const u8 *mac, u32 bd_index)
Definition: gbp_endpoint.h:276
static uword gbp_policy_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u8 is_port_based)
gbp_policy_main_t gbp_policy_main
Definition: gbp_policy.c:19
unsigned int u32
Definition: types.h:88
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
static void acl_plugin_fill_5tuple_inline(void *p_acl_main, u32 lc_index, vlib_buffer_t *b0, int is_ip6, int is_input, int is_l2_path, fa_5tuple_opaque_t *p5tuple_pkt)
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:168
#define gm
Definition: dlmalloc.c:1217
index_t * gc_rules
The ACL to apply for packets from the source to the destination EPG.
Definition: gbp_contract.h:132
unsigned short u16
Definition: types.h:57
sclass_t gck_src
source and destination EPGs for which the ACL applies
Definition: gbp_contract.h:43
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
gbp_rule_action_t gu_action
Definition: gbp_contract.h:105
#define PREDICT_FALSE(x)
Definition: clib.h:111
static void vlib_prefetch_combined_counter(const vlib_combined_counter_main_t *cm, u32 thread_index, u32 index)
Pre-fetch a per-thread combined counter for the given object index.
Definition: counter.h:235
#define SCLASS_INVALID
Definition: gbp_types.h:25
u32 node_index
Node index.
Definition: node.h:495
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:218
sclass_t gef_sclass
Endpoint Group&#39;s sclass.
Definition: gbp_endpoint.h:169
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:368
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1180
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:395
#define foreach_gbp_policy_error
Definition: gbp_contract.h:21
vlib_main_t * vm
Definition: buffer.c:312
vlib_combined_counter_main_t gbp_contract_permit_counters
Definition: gbp_contract.c:44
static dpo_proto_t ethertype_to_dpo_proto(u16 etype)
vlib_node_registration_t gbp_policy_port_node
(constructor) VLIB_REGISTER_NODE (gbp_policy_port_node)
dpo_id_t gu_dpo[GBP_POLICY_N_NODES][FIB_PROTOCOL_IP_MAX]
DPO of the load-balance object used to redirect.
Definition: gbp_contract.h:112
#define ARRAY_LEN(x)
Definition: clib.h:62
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:465
gbp_main_t gbp_main
Definition: gbp_api.c:87
gbp_policy_error_t
static int acl_plugin_match_5tuple_inline(void *p_acl_main, u32 lc_index, fa_5tuple_opaque_t *pkt_5tuple, int is_ip6, u8 *r_action, u32 *r_acl_pos_p, u32 *r_acl_match_p, u32 *r_rule_match_p, u32 *trace_bitmap)
static char * gbp_policy_error_strings[]
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:248
static gbp_contract_t * gbp_contract_get(index_t gci)
Definition: gbp_contract.h:190
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:57
Definition: defs.h:47
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:184
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:47
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:274
Group Base Policy (GBP) defines:
Definition: gbp.h:43
#define vnet_buffer(b)
Definition: buffer.h:369
static_always_inline gbp_endpoint_t * gbp_endpoint_find_itf(u32 sw_if_index)
Definition: gbp_endpoint.h:352
#define vec_foreach(var, vec)
Vector iterator.
static u8 * format_gbp_policy_trace(u8 *s, va_list *args)
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:180
vlib_combined_counter_main_t gbp_contract_drop_counters
Definition: gbp_contract.c:49
Grouping of global data for the GBP source EPG classification feature.
Definition: gbp.h:54
struct gbp_policy_trace_t_ gbp_policy_trace_t
per-packet trace data
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
static u32 gbp_rule_l2_redirect(const gbp_rule_t *gu, vlib_buffer_t *b0)
static index_t gbp_contract_find(gbp_contract_key_t *key)
Definition: gbp_contract.h:175
A Group Based Policy Contract.
Definition: gbp_contract.h:119