FD.io VPP  v19.08-23-g4b943d6
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 #include <plugins/gbp/gbp_policy.h>
23 
26 
27 typedef enum
28 {
32 
35 {
36  etype = clib_net_to_host_u16 (etype);
37 
38  switch (etype)
39  {
40  case ETHERNET_TYPE_IP4:
41  return (DPO_PROTO_IP4);
42  case ETHERNET_TYPE_IP6:
43  return (DPO_PROTO_IP6);
44  }
45 
46  return (DPO_PROTO_NONE);
47 }
48 
51 {
52  const ethernet_header_t *eth0;
53  const dpo_id_t *dpo;
54  dpo_proto_t dproto;
55 
56  eth0 = vlib_buffer_get_current (b0);
57  /* pop the ethernet header to prepare for L3 rewrite */
58  vlib_buffer_advance (b0, vnet_buffer (b0)->l2.l2_len);
59 
60  dproto = ethertype_to_dpo_proto (eth0->type);
61  dpo = &gu->gu_dpo[GBP_POLICY_NODE_L2][dproto];
62 
63  /* save the LB index for the next node and reset the IP flow hash
64  * so it's recalculated */
65  vnet_buffer (b0)->ip.adj_index[VLIB_TX] = dpo->dpoi_index;
66  vnet_buffer (b0)->ip.flow_hash = 0;
67 
68  return (dpo->dpoi_next_node);
69 }
70 
73  const gbp_policy_type_t type)
74 {
75  u32 feat_bit;
76 
77  switch (type)
78  {
79  case GBP_POLICY_PORT:
80  feat_bit = L2OUTPUT_FEAT_GBP_POLICY_PORT;
81  break;
82  case GBP_POLICY_MAC:
83  feat_bit = L2OUTPUT_FEAT_GBP_POLICY_MAC;
84  break;
85  case GBP_POLICY_LPM:
86  feat_bit = L2OUTPUT_FEAT_GBP_POLICY_LPM;
87  break;
88  default:
89  return GBP_POLICY_NEXT_DROP;
90  }
91 
92  return vnet_l2_feature_next (b, gpm->l2_output_feat_next[type], feat_bit);
93 }
94 
95 static uword
97  vlib_node_runtime_t * node,
98  vlib_frame_t * frame, const gbp_policy_type_t type)
99 {
100  gbp_main_t *gm = &gbp_main;
102  u32 n_left_from, *from, *to_next;
103  u32 next_index;
104  u32 n_allow_intra, n_allow_a_bit, n_allow_sclass_1;
105 
106  next_index = 0;
107  n_left_from = frame->n_vectors;
108  from = vlib_frame_vector_args (frame);
109  n_allow_intra = n_allow_a_bit = n_allow_sclass_1 = 0;
110 
111  while (n_left_from > 0)
112  {
113  u32 n_left_to_next;
114 
115  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
116 
117  while (n_left_from > 0 && n_left_to_next > 0)
118  {
119  const ethernet_header_t *h0;
120  const gbp_endpoint_t *ge0;
121  gbp_rule_action_t action0;
123  gbp_policy_next_t next0;
124  gbp_contract_key_t key0;
125  u32 bi0, sw_if_index0;
126  vlib_buffer_t *b0;
127  gbp_rule_t *rule0;
128 
129  next0 = GBP_POLICY_NEXT_DROP;
130  bi0 = from[0];
131  to_next[0] = bi0;
132  from += 1;
133  to_next += 1;
134  n_left_from -= 1;
135  n_left_to_next -= 1;
136 
137  b0 = vlib_get_buffer (vm, bi0);
138  h0 = vlib_buffer_get_current (b0);
139  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
140 
141  /*
142  * Reflection check; in and out on an ivxlan tunnel
143  */
144  if ((~0 != vxlan_gbp_tunnel_by_sw_if_index (sw_if_index0)) &&
145  (vnet_buffer2 (b0)->gbp.flags & VXLAN_GBP_GPFLAGS_R))
146  {
147  goto trace;
148  }
149 
150  /*
151  * If the A-bit is set then policy has already been applied
152  * and we skip enforcement here.
153  */
154  if (vnet_buffer2 (b0)->gbp.flags & VXLAN_GBP_GPFLAGS_A)
155  {
156  next0 = gbp_policy_l2_feature_next (gpm, b0, type);
157  n_allow_a_bit++;
158  key0.as_u64 = ~0;
159  goto trace;
160  }
161 
162  /*
163  * determine the src and dst EPG
164  */
165 
166  /* zero out the key to ensure the pad space is clear */
167  key0.as_u64 = 0;
168  key0.gck_src = vnet_buffer2 (b0)->gbp.sclass;
169  key0.gck_dst = SCLASS_INVALID;
170 
171  if (GBP_POLICY_LPM == type)
172  {
173  const ip4_address_t *ip4 = 0;
174  const ip6_address_t *ip6 = 0;
175  const dpo_proto_t proto =
176  gbp_classify_get_ip_address (h0, &ip4, &ip6,
178  if (PREDICT_TRUE (DPO_PROTO_NONE != proto))
179  {
180  const gbp_ext_itf_t *ext_itf =
181  gbp_ext_itf_get (sw_if_index0);
182  const gbp_policy_dpo_t *gpd =
183  gbp_classify_get_gpd (ip4, ip6,
184  ext_itf->gx_fib_index[proto]);
185  if (gpd)
186  key0.gck_dst = gpd->gpd_sclass;
187  }
188  }
189  else
190  {
191  if (GBP_POLICY_PORT == type)
192  ge0 = gbp_endpoint_find_itf (sw_if_index0);
193  else
195  vnet_buffer (b0)->l2.bd_index);
196  if (NULL != ge0)
197  key0.gck_dst = ge0->ge_fwd.gef_sclass;
198  }
199 
200  if (SCLASS_INVALID == key0.gck_dst)
201  {
202  /* If you cannot determine the destination EP then drop */
203  b0->error = node->errors[GBP_CONTRACT_ERROR_DROP_NO_DCLASS];
204  goto trace;
205  }
206 
207  key0.gck_src = vnet_buffer2 (b0)->gbp.sclass;
208  if (SCLASS_INVALID == key0.gck_src)
209  {
210  /*
211  * the src EPG is not set when the packet arrives on an EPG
212  * uplink interface and we do not need to apply policy
213  */
214  next0 = gbp_policy_l2_feature_next (gpm, b0, type);
215  goto trace;
216  }
217 
218  key0.gck_scope =
219  gbp_bridge_domain_get_scope (vnet_buffer (b0)->l2.bd_index);
220 
221  action0 =
222  gbp_contract_apply (vm, gm, &key0, b0, &rule0, &n_allow_intra,
223  &n_allow_sclass_1, &err0,
225  switch (action0)
226  {
227  case GBP_RULE_PERMIT:
228  next0 = gbp_policy_l2_feature_next (gpm, b0, type);
229  vnet_buffer2 (b0)->gbp.flags |= VXLAN_GBP_GPFLAGS_A;
230  break;
231  case GBP_RULE_REDIRECT:
232  next0 = gbp_rule_l2_redirect (rule0, b0);
233  vnet_buffer2 (b0)->gbp.flags |= VXLAN_GBP_GPFLAGS_A;
234  break;
235  case GBP_RULE_DENY:
236  next0 = GBP_POLICY_NEXT_DROP;
237  b0->error = node->errors[err0];
238  break;
239  }
240 
241  trace:
242  gbp_policy_trace (vm, node, b0, &key0,
243  (next0 != GBP_POLICY_NEXT_DROP));
244 
245  /* verify speculative enqueue, maybe switch current next frame */
246  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
247  to_next, n_left_to_next,
248  bi0, next0);
249  }
250 
251  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
252  }
253 
255  GBP_CONTRACT_ERROR_ALLOW_INTRA, n_allow_intra);
257  GBP_CONTRACT_ERROR_ALLOW_A_BIT, n_allow_a_bit);
259  GBP_CONTRACT_ERROR_ALLOW_SCLASS_1,
260  n_allow_sclass_1);
261 
262  return frame->n_vectors;
263 }
264 
266  vlib_node_runtime_t * node,
267  vlib_frame_t * frame)
268 {
269  return (gbp_policy_inline (vm, node, frame, GBP_POLICY_PORT));
270 }
271 
273  vlib_node_runtime_t * node,
274  vlib_frame_t * frame)
275 {
276  return (gbp_policy_inline (vm, node, frame, GBP_POLICY_MAC));
277 }
278 
280  vlib_node_runtime_t * node,
281  vlib_frame_t * frame)
282 {
283  return (gbp_policy_inline (vm, node, frame, GBP_POLICY_LPM));
284 }
285 
286 /* *INDENT-OFF* */
288  .name = "gbp-policy-port",
289  .vector_size = sizeof (u32),
290  .format_trace = format_gbp_policy_trace,
292 
294  .error_strings = gbp_contract_error_strings,
295 
296  .n_next_nodes = GBP_POLICY_N_NEXT,
297  .next_nodes = {
298  [GBP_POLICY_NEXT_DROP] = "error-drop",
299  },
300 };
301 
303  .name = "gbp-policy-mac",
304  .vector_size = sizeof (u32),
305  .format_trace = format_gbp_policy_trace,
307 
309  .error_strings = gbp_contract_error_strings,
310 
311  .n_next_nodes = GBP_POLICY_N_NEXT,
312  .next_nodes = {
313  [GBP_POLICY_NEXT_DROP] = "error-drop",
314  },
315 };
316 
318  .name = "gbp-policy-lpm",
319  .vector_size = sizeof (u32),
320  .format_trace = format_gbp_policy_trace,
322 
324  .error_strings = gbp_contract_error_strings,
325 
326  .n_next_nodes = GBP_POLICY_N_NEXT,
327  .next_nodes = {
328  [GBP_POLICY_NEXT_DROP] = "error-drop",
329  },
330 };
331 
332 /* *INDENT-ON* */
333 
334 /*
335  * fd.io coding-style-patch-verification: ON
336  *
337  * Local Variables:
338  * eval: (c-set-style "gnu")
339  * End:
340  */
static gbp_scope_t gbp_bridge_domain_get_scope(u32 bd_index)
gbp_policy_next_t
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: vlib_api_cli.c:870
A Group Based Policy Endpoint.
Definition: gbp_endpoint.h:190
gbp_endpoint_fwd_t ge_fwd
Definition: gbp_endpoint.h:208
#define vnet_buffer2(b)
Definition: buffer.h:420
#define PREDICT_TRUE(x)
Definition: clib.h:112
#define NULL
Definition: clib.h:58
The key for an Contract.
Definition: gbp_contract.h:47
gbp_policy_next_t
vlib_node_registration_t gbp_policy_lpm_node
(constructor) VLIB_REGISTER_NODE (gbp_policy_lpm_node)
char * gbp_contract_error_strings[]
Definition: gbp_contract.c:27
#define VLIB_NODE_FN(node)
Definition: node.h:201
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:468
static uword gbp_policy_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, const gbp_policy_type_t type)
vlib_node_registration_t gbp_policy_mac_node
(constructor) VLIB_REGISTER_NODE (gbp_policy_mac_node)
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
#define static_always_inline
Definition: clib.h:99
#define always_inline
Definition: clib.h:98
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
u32 gx_fib_index[DPO_PROTO_NUM]
cached FIB indices from the RD
Definition: gbp_ext_itf.h:53
static_always_inline gbp_endpoint_t * gbp_endpoint_find_mac(const u8 *mac, u32 bd_index)
Definition: gbp_endpoint.h:279
gbp_policy_main_t gbp_policy_main
Definition: gbp_policy.c:20
unsigned int u32
Definition: types.h:88
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
vl_api_fib_path_type_t type
Definition: fib_types.api:123
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:170
The GBP FWD DPO.
static gbp_ext_itf_t * gbp_ext_itf_get(u32 sw_if_index)
Definition: gbp_ext_itf.h:79
#define gm
Definition: dlmalloc.c:1217
unsigned short u16
Definition: types.h:57
sclass_t gck_src
source and destination EPGs for which the ACL applies
Definition: gbp_contract.h:57
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
u32 l2_output_feat_next[GBP_N_POLICY][32]
Next nodes for L2 output features.
Definition: gbp.h:67
#define SCLASS_INVALID
Definition: gbp_types.h:26
u32 node_index
Node index.
Definition: node.h:494
#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:172
gbp_contract_error_t
Definition: gbp_contract.h:33
#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:338
static_always_inline gbp_rule_action_t gbp_contract_apply(vlib_main_t *vm, gbp_main_t *gm, gbp_contract_key_t *key, vlib_buffer_t *b, gbp_rule_t **rule, u32 *intra, u32 *sclass1, gbp_contract_error_t *err, gbp_contract_apply_type_t type)
Definition: gbp_contract.h:230
enum gbp_policy_type_t_ gbp_policy_type_t
An external interface maps directly to an oflex L3ExternalInterface.
Definition: gbp_ext_itf.h:33
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1150
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:395
vlib_main_t * vm
Definition: buffer.c:312
static dpo_proto_t ethertype_to_dpo_proto(u16 etype)
static_always_inline const gbp_policy_dpo_t * gbp_classify_get_gpd(const ip4_address_t *ip4, const ip6_address_t *ip6, const u32 fib_index)
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:126
#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:458
sclass_t gpd_sclass
SClass.
gbp_main_t gbp_main
Definition: gbp_api.c:88
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:248
u8 * format_gbp_policy_trace(u8 *s, va_list *args)
Definition: gbp_policy.c:24
enum gbp_rule_action_t_ gbp_rule_action_t
Definition: defs.h:47
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:186
gbp_scope_t gck_scope
Definition: gbp_contract.h:53
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:244
Group Base Policy (GBP) defines:
Definition: gbp.h:42
#define vnet_buffer(b)
Definition: buffer.h:361
static_always_inline gbp_endpoint_t * gbp_endpoint_find_itf(u32 sw_if_index)
Definition: gbp_endpoint.h:355
static_always_inline dpo_proto_t gbp_classify_get_ip_address(const ethernet_header_t *eh0, const ip4_address_t **ip4, const ip6_address_t **ip6, const enum gbp_classify_get_ip_way way)
Definition: gbp_classify.h:54
static_always_inline void gbp_policy_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b, const gbp_contract_key_t *key, u8 allowed)
Definition: gbp_policy.h:38
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:182
Grouping of global data for the GBP source EPG classification feature.
Definition: gbp.h:62
static_always_inline gbp_policy_next_t gbp_policy_l2_feature_next(gbp_policy_main_t *gpm, vlib_buffer_t *b, const gbp_policy_type_t type)
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)
vl_api_fib_path_nh_proto_t proto
Definition: fib_types.api:125