FD.io VPP  v20.01-48-g3e0dafb74
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
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  gbp_rule_action_t action0 = GBP_RULE_DENY;
120  const ethernet_header_t *h0;
121  const gbp_endpoint_t *ge0;
123  u32 acl_match = ~0, rule_match = ~0;
124  gbp_policy_next_t next0;
125  gbp_contract_key_t key0;
126  u32 bi0, sw_if_index0;
127  vlib_buffer_t *b0;
128  gbp_rule_t *rule0;
129 
130  next0 = GBP_POLICY_NEXT_DROP;
131  bi0 = from[0];
132  to_next[0] = bi0;
133  from += 1;
134  to_next += 1;
135  n_left_from -= 1;
136  n_left_to_next -= 1;
137 
138  b0 = vlib_get_buffer (vm, bi0);
139  h0 = vlib_buffer_get_current (b0);
140  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
141 
142  /*
143  * Reflection check; in and out on an ivxlan tunnel
144  */
145  if ((~0 != vxlan_gbp_tunnel_by_sw_if_index (sw_if_index0)) &&
146  (vnet_buffer2 (b0)->gbp.flags & VXLAN_GBP_GPFLAGS_R))
147  {
148  goto trace;
149  }
150 
151  /*
152  * If the A-bit is set then policy has already been applied
153  * and we skip enforcement here.
154  */
155  if (vnet_buffer2 (b0)->gbp.flags & VXLAN_GBP_GPFLAGS_A)
156  {
157  next0 = gbp_policy_l2_feature_next (gpm, b0, type);
158  n_allow_a_bit++;
159  key0.as_u64 = ~0;
160  goto trace;
161  }
162 
163  /*
164  * determine the src and dst EPG
165  */
166 
167  /* zero out the key to ensure the pad space is clear */
168  key0.as_u64 = 0;
169  key0.gck_src = vnet_buffer2 (b0)->gbp.sclass;
170  key0.gck_dst = SCLASS_INVALID;
171 
172  if (GBP_POLICY_LPM == type)
173  {
174  const ip4_address_t *ip4 = 0;
175  const ip6_address_t *ip6 = 0;
176  const dpo_proto_t proto =
177  gbp_classify_get_ip_address (h0, &ip4, &ip6,
179  if (PREDICT_TRUE (DPO_PROTO_NONE != proto))
180  {
181  const gbp_ext_itf_t *ext_itf =
182  gbp_ext_itf_get (sw_if_index0);
183  const gbp_policy_dpo_t *gpd =
184  gbp_classify_get_gpd (ip4, ip6,
185  ext_itf->gx_fib_index[proto]);
186  if (gpd)
187  key0.gck_dst = gpd->gpd_sclass;
188  }
189  }
190  else
191  {
192  if (GBP_POLICY_PORT == type)
193  ge0 = gbp_endpoint_find_itf (sw_if_index0);
194  else
196  vnet_buffer (b0)->l2.bd_index);
197  if (NULL != ge0)
198  key0.gck_dst = ge0->ge_fwd.gef_sclass;
199  }
200 
201  if (SCLASS_INVALID == key0.gck_dst)
202  {
203  /* If you cannot determine the destination EP then drop */
204  b0->error = node->errors[GBP_CONTRACT_ERROR_DROP_NO_DCLASS];
205  goto trace;
206  }
207 
208  key0.gck_src = vnet_buffer2 (b0)->gbp.sclass;
209  if (SCLASS_INVALID == key0.gck_src)
210  {
211  /*
212  * the src EPG is not set when the packet arrives on an EPG
213  * uplink interface and we do not need to apply policy
214  */
215  next0 = gbp_policy_l2_feature_next (gpm, b0, type);
216  goto trace;
217  }
218 
219  key0.gck_scope =
220  gbp_bridge_domain_get_scope (vnet_buffer (b0)->l2.bd_index);
221 
222  action0 =
223  gbp_contract_apply (vm, gm, &key0, b0, &rule0, &n_allow_intra,
224  &n_allow_sclass_1, &acl_match, &rule_match,
225  &err0, GBP_CONTRACT_APPLY_L2);
226  switch (action0)
227  {
228  case GBP_RULE_PERMIT:
229  next0 = gbp_policy_l2_feature_next (gpm, b0, type);
230  vnet_buffer2 (b0)->gbp.flags |= VXLAN_GBP_GPFLAGS_A;
231  break;
232  case GBP_RULE_REDIRECT:
233  next0 = gbp_rule_l2_redirect (rule0, b0);
234  vnet_buffer2 (b0)->gbp.flags |= VXLAN_GBP_GPFLAGS_A;
235  break;
236  case GBP_RULE_DENY:
237  next0 = GBP_POLICY_NEXT_DROP;
238  b0->error = node->errors[err0];
239  break;
240  }
241 
242  trace:
243  gbp_policy_trace (vm, node, b0, &key0, action0, acl_match,
244  rule_match);
245 
246  /* verify speculative enqueue, maybe switch current next frame */
247  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
248  to_next, n_left_to_next,
249  bi0, next0);
250  }
251 
252  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
253  }
254 
256  GBP_CONTRACT_ERROR_ALLOW_INTRA, n_allow_intra);
258  GBP_CONTRACT_ERROR_ALLOW_A_BIT, n_allow_a_bit);
260  GBP_CONTRACT_ERROR_ALLOW_SCLASS_1,
261  n_allow_sclass_1);
262 
263  return frame->n_vectors;
264 }
265 
269 {
270  return (gbp_policy_inline (vm, node, frame, GBP_POLICY_PORT));
271 }
272 
276 {
277  return (gbp_policy_inline (vm, node, frame, GBP_POLICY_MAC));
278 }
279 
283 {
284  return (gbp_policy_inline (vm, node, frame, GBP_POLICY_LPM));
285 }
286 
287 /* *INDENT-OFF* */
289  .name = "gbp-policy-port",
290  .vector_size = sizeof (u32),
291  .format_trace = format_gbp_policy_trace,
293 
295  .error_strings = gbp_contract_error_strings,
296 
297  .n_next_nodes = GBP_POLICY_N_NEXT,
298  .next_nodes = {
299  [GBP_POLICY_NEXT_DROP] = "error-drop",
300  },
301 };
302 
304  .name = "gbp-policy-mac",
305  .vector_size = sizeof (u32),
306  .format_trace = format_gbp_policy_trace,
308 
310  .error_strings = gbp_contract_error_strings,
311 
312  .n_next_nodes = GBP_POLICY_N_NEXT,
313  .next_nodes = {
314  [GBP_POLICY_NEXT_DROP] = "error-drop",
315  },
316 };
317 
319  .name = "gbp-policy-lpm",
320  .vector_size = sizeof (u32),
321  .format_trace = format_gbp_policy_trace,
323 
325  .error_strings = gbp_contract_error_strings,
326 
327  .n_next_nodes = GBP_POLICY_N_NEXT,
328  .next_nodes = {
329  [GBP_POLICY_NEXT_DROP] = "error-drop",
330  },
331 };
332 
333 /* *INDENT-ON* */
334 
335 /*
336  * fd.io coding-style-patch-verification: ON
337  *
338  * Local Variables:
339  * eval: (c-set-style "gnu")
340  * End:
341  */
static gbp_scope_t gbp_bridge_domain_get_scope(u32 bd_index)
gbp_policy_next_t
u8 proto
Definition: acl_types.api:47
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: vlib_api_cli.c:898
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:467
#define PREDICT_TRUE(x)
Definition: clib.h:112
#define NULL
Definition: clib.h:58
The key for an Contract.
Definition: gbp_contract.h:48
gbp_policy_next_t
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, gbp_rule_action_t action, u32 acl_match, u32 rule_match)
Definition: gbp_policy.h:40
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:202
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:470
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
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:231
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:1219
unsigned short u16
Definition: types.h:57
sclass_t gck_src
source and destination EPGs for which the ACL applies
Definition: gbp_contract.h:58
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
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, u32 *acl_match, u32 *rule_match, gbp_contract_error_t *err, gbp_contract_apply_type_t type)
Definition: gbp_contract.h:233
u32 l2_output_feat_next[GBP_N_POLICY][32]
Next nodes for L2 output features.
Definition: gbp.h:67
#define always_inline
Definition: ipsec.h:28
#define SCLASS_INVALID
Definition: gbp_types.h:26
u32 node_index
Node index.
Definition: node.h:496
#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:34
#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
vlib_main_t * vm
Definition: in2out_ed.c:1810
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
u8 ip6[16]
Definition: one.api:477
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:397
static dpo_proto_t ethertype_to_dpo_proto(u16 etype)
vlib_parse_match_function_t rule_match
Definition: parse.h:189
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:127
#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:456
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1810
sclass_t gpd_sclass
SClass.
gbp_main_t gbp_main
Definition: gbp_api.c:47
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:54
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:408
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
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1811
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:182
u32 ip4
Definition: one.api:440
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)