Skip to content

Commit 5b7705d

Browse files
committed
vpp: private plugin that adds npol matched rule to acl trace
1 parent a3a531d commit 5b7705d

File tree

2 files changed

+369
-0
lines changed

2 files changed

+369
-0
lines changed
Lines changed: 368 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,368 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: hedi bouattour <hedibouattour2010@gmail.com>
3+
Date: Tue, 3 Mar 2026 12:55:00 +0000
4+
Subject: [PATCH] npol: add matched rule id to acl trace
5+
6+
This allows to track the policy rule that was hit
7+
in npol
8+
9+
Type: feature
10+
11+
Change-Id: If81470f8266ea56a8f3b154c6d72a1ad57502b87
12+
Signed-off-by: hedi bouattour <hedibouattour2010@gmail.com>
13+
---
14+
src/plugins/acl/acl.h | 8 +--
15+
src/plugins/acl/acl_caiop.c | 5 +-
16+
src/plugins/acl/dataplane_node.c | 85 +++++++++++++++-----------------
17+
src/plugins/acl/fa_node.h | 3 +-
18+
src/plugins/npol/npol.c | 4 +-
19+
src/plugins/npol/npol_match.c | 34 +++++++------
20+
src/plugins/npol/npol_match.h | 8 +--
21+
7 files changed, 75 insertions(+), 72 deletions(-)
22+
23+
diff --git a/src/plugins/acl/acl.h b/src/plugins/acl/acl.h
24+
index cbadefb82..b5ba853d7 100644
25+
--- a/src/plugins/acl/acl.h
26+
+++ b/src/plugins/acl/acl.h
27+
@@ -105,9 +105,11 @@ typedef struct
28+
} ace_mask_type_entry_t;
29+
30+
/* This is a private experimental type, subject to change */
31+
-typedef int (*acl_plugin_private_caiop_match_5tuple_func_t) (
32+
- void *p_acl_main, u32 sw_if_index, u32 is_inbound,
33+
- fa_5tuple_opaque_t *pkt_5tuple, int is_ip6, u8 *r_action, u32 *trace_bitmap);
34+
+typedef int (*acl_plugin_private_caiop_match_5tuple_func_t) (void *p_acl_main, u32 sw_if_index,
35+
+ u32 is_inbound,
36+
+ fa_5tuple_opaque_t *pkt_5tuple,
37+
+ int is_ip6, u8 *r_action,
38+
+ u32 *trace_bitmap, u32 *matched);
39+
40+
typedef struct {
41+
/* API message ID base */
42+
diff --git a/src/plugins/acl/acl_caiop.c b/src/plugins/acl/acl_caiop.c
43+
index fa11d32a0..2de0fd205 100644
44+
--- a/src/plugins/acl/acl_caiop.c
45+
+++ b/src/plugins/acl/acl_caiop.c
46+
@@ -198,10 +198,11 @@ acl_show_custom_access_policies_fn (vlib_main_t *vm, unformat_input_t *input,
47+
48+
static int
49+
dummy_match_5tuple_fun (void *p_acl_main, u32 sw_if_index, u32 is_inbound,
50+
- fa_5tuple_opaque_t *pkt_5tuple, int is_ip6,
51+
- u8 *r_action, u32 *trace_bitmap)
52+
+ fa_5tuple_opaque_t *pkt_5tuple, int is_ip6, u8 *r_action, u32 *trace_bitmap,
53+
+ u32 *npol_matched_rule_id)
54+
{
55+
/* permit and create connection */
56+
+ *npol_matched_rule_id = 0;
57+
*r_action = 2;
58+
return 1;
59+
}
60+
diff --git a/src/plugins/acl/dataplane_node.c b/src/plugins/acl/dataplane_node.c
61+
index 673a774fd..76cf3672b 100644
62+
--- a/src/plugins/acl/dataplane_node.c
63+
+++ b/src/plugins/acl/dataplane_node.c
64+
@@ -34,6 +34,7 @@ typedef struct
65+
u64 packet_info[6];
66+
u32 trace_bitmap;
67+
u8 action;
68+
+ u32 npol_matched_rule_id;
69+
} acl_fa_trace_t;
70+
71+
#define foreach_acl_fa_error \
72+
@@ -69,10 +70,9 @@ get_current_policy_epoch (acl_main_t * am, int is_input, u32 sw_if_index0)
73+
}
74+
75+
always_inline void
76+
-maybe_trace_buffer (vlib_main_t * vm, vlib_node_runtime_t * node,
77+
- vlib_buffer_t * b, u32 sw_if_index0, u32 lc_index0,
78+
- u16 next0, int match_acl_in_index, int match_rule_index,
79+
- fa_5tuple_t * fa_5tuple, u8 action, u32 trace_bitmap)
80+
+maybe_trace_buffer (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b, u32 sw_if_index0,
81+
+ u32 lc_index0, u16 next0, int match_acl_in_index, int match_rule_index,
82+
+ fa_5tuple_t *fa_5tuple, u8 action, u32 trace_bitmap, u32 npol_matched_rule_id)
83+
{
84+
if (PREDICT_FALSE (b->flags & VLIB_BUFFER_IS_TRACED))
85+
{
86+
@@ -90,6 +90,7 @@ maybe_trace_buffer (vlib_main_t * vm, vlib_node_runtime_t * node,
87+
t->packet_info[5] = fa_5tuple->kv_40_8.value;
88+
t->action = action;
89+
t->trace_bitmap = trace_bitmap;
90+
+ t->npol_matched_rule_id = npol_matched_rule_id;
91+
}
92+
}
93+
94+
@@ -170,17 +171,19 @@ prefetch_session_entry (acl_main_t * am, fa_full_session_id_t f_sess_id)
95+
}
96+
97+
always_inline u8
98+
-process_established_session (vlib_main_t * vm, acl_main_t * am,
99+
- u32 counter_node_index, int is_input, u64 now,
100+
- fa_full_session_id_t f_sess_id,
101+
- u32 * sw_if_index, fa_5tuple_t * fa_5tuple,
102+
- u32 pkt_len, int node_trace_on,
103+
- u32 * trace_bitmap)
104+
+process_established_session (vlib_main_t *vm, acl_main_t *am, u32 counter_node_index, int is_input,
105+
+ u64 now, fa_full_session_id_t f_sess_id, u32 *sw_if_index,
106+
+ fa_5tuple_t *fa_5tuple, u32 pkt_len, int node_trace_on,
107+
+ u32 *trace_bitmap, int do_custom_access_policies,
108+
+ u32 *npol_matched_rule_id)
109+
{
110+
u8 action = 0;
111+
fa_session_t *sess = get_session_ptr_no_check (am, f_sess_id.thread_index,
112+
f_sess_id.session_index);
113+
-
114+
+ if (do_custom_access_policies)
115+
+ {
116+
+ *npol_matched_rule_id = sess->npol_matched_rule_id;
117+
+ }
118+
int old_timeout_type = fa_session_get_timeout_type (am, sess);
119+
action =
120+
acl_fa_track_session (am, is_input, sw_if_index[0], now,
121+
@@ -373,6 +376,7 @@ acl_fa_inner_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
122+
u32 match_acl_in_index = ~0;
123+
u32 match_acl_pos = ~0;
124+
u32 match_rule_index = ~0;
125+
+ u32 npol_matched_rule_id = 0;
126+
127+
next[0] = 0; /* drop by default */
128+
129+
@@ -411,14 +415,10 @@ acl_fa_inner_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
130+
b[0]->error = no_error_existing_session;
131+
acl_check_needed = 0;
132+
pkts_exist_session += 1;
133+
- action =
134+
- process_established_session (vm, am, node->node_index,
135+
- is_input, now, f_sess_id,
136+
- &sw_if_index[0],
137+
- &fa_5tuple[0],
138+
- b[0]->current_length,
139+
- node_trace_on,
140+
- &trace_bitmap);
141+
+ action = process_established_session (
142+
+ vm, am, node->node_index, is_input, now, f_sess_id, &sw_if_index[0],
143+
+ &fa_5tuple[0], b[0]->current_length, node_trace_on, &trace_bitmap,
144+
+ do_custom_access_policies, &npol_matched_rule_id);
145+
146+
/* expose the session id to the tracer */
147+
if (node_trace_on)
148+
@@ -477,10 +477,9 @@ acl_fa_inner_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
149+
}
150+
vec_foreach (pf, caiop_match_vec)
151+
{
152+
- int is_match =
153+
- (*pf) (am, sw_if_index[0], is_input,
154+
- (fa_5tuple_opaque_t *) &fa_5tuple[0],
155+
- is_ip6, &action, &trace_bitmap);
156+
+ int is_match = (*pf) (am, sw_if_index[0], is_input,
157+
+ (fa_5tuple_opaque_t *) &fa_5tuple[0], is_ip6,
158+
+ &action, &trace_bitmap, &npol_matched_rule_id);
159+
if (is_match)
160+
{
161+
acl_check_needed = 0;
162+
@@ -557,17 +556,16 @@ acl_fa_inner_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
163+
sw_if_index[0],
164+
now, &fa_5tuple[0],
165+
current_policy_epoch);
166+
+ /* store the matched rule in the session */
167+
+ fa_session_t *sess = get_session_ptr_no_check (am, f_sess_id.thread_index,
168+
+ f_sess_id.session_index);
169+
+ sess->npol_matched_rule_id = npol_matched_rule_id;
170+
171+
/* perform the accounting for the newly added session */
172+
- process_established_session (vm, am,
173+
- node->node_index,
174+
- is_input, now,
175+
- f_sess_id,
176+
- &sw_if_index[0],
177+
- &fa_5tuple[0],
178+
- b[0]->current_length,
179+
- node_trace_on,
180+
- &trace_bitmap);
181+
+ process_established_session (
182+
+ vm, am, node->node_index, is_input, now, f_sess_id, &sw_if_index[0],
183+
+ &fa_5tuple[0], b[0]->current_length, node_trace_on, &trace_bitmap,
184+
+ do_custom_access_policies, &npol_matched_rule_id);
185+
pkts_new_session++;
186+
/*
187+
* If the next 5tuple is the same and we just added the session,
188+
@@ -598,10 +596,9 @@ acl_fa_inner_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
189+
190+
if (node_trace_on) // PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
191+
{
192+
- maybe_trace_buffer (vm, node, b[0], sw_if_index[0], lc_index0,
193+
- next[0], match_acl_in_index,
194+
- match_rule_index, &fa_5tuple[0], action,
195+
- trace_bitmap);
196+
+ maybe_trace_buffer (vm, node, b[0], sw_if_index[0], lc_index0, next[0],
197+
+ match_acl_in_index, match_rule_index, &fa_5tuple[0], action,
198+
+ trace_bitmap, npol_matched_rule_id);
199+
}
200+
201+
next++;
202+
@@ -769,14 +766,14 @@ format_acl_plugin_trace (u8 * s, va_list * args)
203+
CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
204+
acl_fa_trace_t *t = va_arg (*args, acl_fa_trace_t *);
205+
206+
- s =
207+
- format (s,
208+
- "acl-plugin: lc_index: %d, sw_if_index %d, next index %d, action: %d, match: acl %d rule %d trace_bits %08x\n"
209+
- " pkt info %016llx %016llx %016llx %016llx %016llx %016llx",
210+
- t->lc_index, t->sw_if_index, t->next_index, t->action,
211+
- t->match_acl_in_index, t->match_rule_index, t->trace_bitmap,
212+
- t->packet_info[0], t->packet_info[1], t->packet_info[2],
213+
- t->packet_info[3], t->packet_info[4], t->packet_info[5]);
214+
+ s = format (s,
215+
+ "acl-plugin: lc_index: %d, sw_if_index %d, next index %d, action: %d, match: acl %d "
216+
+ "rule %d trace_bits %08x npol_matched_rule_id %d\n"
217+
+ " pkt info %016llx %016llx %016llx %016llx %016llx %016llx",
218+
+ t->lc_index, t->sw_if_index, t->next_index, t->action, t->match_acl_in_index,
219+
+ t->match_rule_index, t->trace_bitmap, t->npol_matched_rule_id, t->packet_info[0],
220+
+ t->packet_info[1], t->packet_info[2], t->packet_info[3], t->packet_info[4],
221+
+ t->packet_info[5]);
222+
223+
/* Now also print out the packet_info in a form usable by humans */
224+
s = format (s, "\n %U", format_fa_5tuple, t->packet_info);
225+
diff --git a/src/plugins/acl/fa_node.h b/src/plugins/acl/fa_node.h
226+
index 699df7923..6b8bc9dc7 100644
227+
--- a/src/plugins/acl/fa_node.h
228+
+++ b/src/plugins/acl/fa_node.h
229+
@@ -117,7 +117,8 @@ typedef struct {
230+
u8 link_list_id; /* +1 bytes = 17 */
231+
u8 deleted; /* +1 bytes = 18 */
232+
u8 is_ip6; /* +1 bytes = 19 */
233+
- u8 reserved1[5]; /* +5 bytes = 24 */
234+
+ u8 reserved1[1]; /* +1 bytes = 20 */
235+
+ u32 npol_matched_rule_id; /* +4 bytes = 24 */
236+
u64 reserved2[5]; /* +5*8 bytes = 64 */
237+
} fa_session_t;
238+
239+
diff --git a/src/plugins/npol/npol.c b/src/plugins/npol/npol.c
240+
index 6fce47f3e..c343842e6 100644
241+
--- a/src/plugins/npol/npol.c
242+
+++ b/src/plugins/npol/npol.c
243+
@@ -17,7 +17,7 @@ npol_match_fn (vlib_main_t *vm, unformat_input_t *input,
244+
clib_error_t *error = 0;
245+
u32 is_inbound = 0;
246+
int is_ip6 = 0;
247+
- u32 sport = 0, dport = 0, proto = 0;
248+
+ u32 sport = 0, dport = 0, proto = 0, matched_rule_id = 0;
249+
int rv;
250+
251+
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
252+
@@ -67,7 +67,7 @@ npol_match_fn (vlib_main_t *vm, unformat_input_t *input,
253+
goto done;
254+
}
255+
256+
- rv = npol_match_func (sw_if_index, is_inbound, pkt_5tuple, is_ip6, r_action);
257+
+ rv = npol_match_func (sw_if_index, is_inbound, pkt_5tuple, is_ip6, r_action, &matched_rule_id);
258+
259+
vlib_cli_output (vm, "matched:%d action:%U", rv, format_npol_action,
260+
*r_action);
261+
diff --git a/src/plugins/npol/npol_match.c b/src/plugins/npol/npol_match.c
262+
index 6e4e1e2de..215157fcf 100644
263+
--- a/src/plugins/npol/npol_match.c
264+
+++ b/src/plugins/npol/npol_match.c
265+
@@ -600,8 +600,8 @@ npol_match_rule (npol_rule_t *rule, u32 is_ip6, fa_5tuple_t *pkt_5tuple)
266+
}
267+
268+
always_inline int
269+
-npol_match_policy (npol_policy_t *policy, u32 is_inbound, u32 is_ip6,
270+
- fa_5tuple_t *pkt_5tuple)
271+
+npol_match_policy (npol_policy_t *policy, u32 is_inbound, u32 is_ip6, fa_5tuple_t *pkt_5tuple,
272+
+ u32 *matched_rule_id)
273+
{
274+
/* packets RX/TX from VPP perspective */
275+
u32 *rules =
276+
@@ -616,6 +616,7 @@ npol_match_policy (npol_policy_t *policy, u32 is_inbound, u32 is_ip6,
277+
r = npol_match_rule (rule, is_ip6, pkt_5tuple);
278+
if (r >= 0)
279+
{
280+
+ *matched_rule_id = *rule_id;
281+
return r;
282+
}
283+
}
284+
@@ -629,9 +630,10 @@ npol_match_policy (npol_policy_t *policy, u32 is_inbound, u32 is_ip6,
285+
* - is_inbound = 0 : to be txed on interface sw_if_index
286+
* The function sets r_action to NPOL_ACTION_ALLOW or NPOL_ACTION_DENY
287+
* It returns 1 if a rule was matched, 0 otherwise
288+
+ * It sets matched to the rule_id if a rule was matched
289+
*/
290+
-CLIB_MARCH_FN (npol_match, int, u32 sw_if_index, u32 is_inbound,
291+
- fa_5tuple_t *pkt_5tuple, int is_ip6, u8 *r_action)
292+
+CLIB_MARCH_FN (npol_match, int, u32 sw_if_index, u32 is_inbound, fa_5tuple_t *pkt_5tuple,
293+
+ int is_ip6, u8 *r_action, u32 *matched_rule_id)
294+
{
295+
npol_interface_config_t *if_config;
296+
npol_policy_t *policy;
297+
@@ -658,8 +660,8 @@ CLIB_MARCH_FN (npol_match, int, u32 sw_if_index, u32 is_inbound,
298+
vec_foreach_index (i, policies)
299+
{
300+
policy = &npol_policies[policies[i]];
301+
- r = npol_match_policy (policy, is_inbound ^ if_config->invert_rx_tx,
302+
- is_ip6, pkt_5tuple);
303+
+ r = npol_match_policy (policy, is_inbound ^ if_config->invert_rx_tx, is_ip6, pkt_5tuple,
304+
+ matched_rule_id);
305+
switch (r)
306+
{
307+
case NPOL_ALLOW:
308+
@@ -697,8 +699,8 @@ profiles:
309+
vec_foreach_index (i, if_config->profiles)
310+
{
311+
policy = &npol_policies[if_config->profiles[i]];
312+
- r = npol_match_policy (policy, is_inbound ^ if_config->invert_rx_tx,
313+
- is_ip6, pkt_5tuple);
314+
+ r = npol_match_policy (policy, is_inbound ^ if_config->invert_rx_tx, is_ip6, pkt_5tuple,
315+
+ matched_rule_id);
316+
switch (r)
317+
{
318+
case NPOL_ALLOW:
319+
@@ -739,19 +741,19 @@ profiles:
320+
321+
#ifndef CLIB_MARCH_VARIANT
322+
int
323+
-npol_match_func (u32 sw_if_index, u32 is_inbound, fa_5tuple_t *pkt_5tuple,
324+
- int is_ip6, u8 *r_action)
325+
+npol_match_func (u32 sw_if_index, u32 is_inbound, fa_5tuple_t *pkt_5tuple, int is_ip6, u8 *r_action,
326+
+ u32 *matched_rule_id)
327+
{
328+
- return CLIB_MARCH_FN_SELECT (npol_match) (sw_if_index, is_inbound,
329+
- pkt_5tuple, is_ip6, r_action);
330+
+ return CLIB_MARCH_FN_SELECT (npol_match) (sw_if_index, is_inbound, pkt_5tuple, is_ip6, r_action,
331+
+ matched_rule_id);
332+
}
333+
334+
int
335+
npol_match_func_acl (void *p_acl_main, u32 sw_if_index, u32 is_inbound,
336+
- fa_5tuple_opaque_t *pkt_5tuple, int is_ip6, u8 *r_action,
337+
- u32 *trace_bitmap)
338+
+ fa_5tuple_opaque_t *pkt_5tuple, int is_ip6, u8 *r_action, u32 *trace_bitmap,
339+
+ u32 *matched_rule_id)
340+
{
341+
- return CLIB_MARCH_FN_SELECT (npol_match) (
342+
- sw_if_index, is_inbound, (fa_5tuple_t *) pkt_5tuple, is_ip6, r_action);
343+
+ return CLIB_MARCH_FN_SELECT (npol_match) (sw_if_index, is_inbound, (fa_5tuple_t *) pkt_5tuple,
344+
+ is_ip6, r_action, matched_rule_id);
345+
}
346+
#endif /* CLIB_MARCH_VARIANT */
347+
diff --git a/src/plugins/npol/npol_match.h b/src/plugins/npol/npol_match.h
348+
index d4fd1700a..0f8a02b1a 100644
349+
--- a/src/plugins/npol/npol_match.h
350+
+++ b/src/plugins/npol/npol_match.h
351+
@@ -12,10 +12,10 @@
352+
#include <npol/npol_policy.h>
353+
#include <npol/npol_rule.h>
354+
355+
-int npol_match_func (u32 sw_if_index, u32 is_inbound, fa_5tuple_t *pkt_5tuple,
356+
- int is_ip6, u8 *r_action);
357+
+int npol_match_func (u32 sw_if_index, u32 is_inbound, fa_5tuple_t *pkt_5tuple, int is_ip6,
358+
+ u8 *r_action, u32 *matched_rule_id);
359+
int npol_match_func_acl (void *p_acl_main, u32 sw_if_index, u32 is_inbound,
360+
- fa_5tuple_opaque_t *pkt_5tuple, int is_ip6,
361+
- u8 *r_action, u32 *trace_bitmap);
362+
+ fa_5tuple_opaque_t *pkt_5tuple, int is_ip6, u8 *r_action,
363+
+ u32 *trace_bitmap, u32 *matched_rule_id);
364+
365+
#endif
366+
--
367+
2.43.0
368+

vpplink/generated/vpp_clone_current.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,4 @@ git_apply_private 0001-pbl-Port-based-balancer.patch
137137
git_apply_private 0002-cnat-WIP-no-k8s-maglev-from-pods.patch
138138
git_apply_private 0003-acl-acl-plugin-custom-policies.patch
139139
git_apply_private 0004-ip-neighbor-preserve-interface-ll-receive-dpo.patch
140+
git_apply_private 0005-npol-add-matched-rule-id-to-acl-trace.patch

0 commit comments

Comments
 (0)