In the current ACL implementation, the drop action is impacted by
conntrack behavior, leading to some unexpected results. Here is a
specific scenario we’ve encountered:
Topology:
VM-1(Logical Switch Port) -------- LS1(Logical Switch)
--------Router-Interface(Logical Switch Port, type=router)
-------Router(Logical Router)-----External Network
ACL rules:
VM-1:
from-lport 2000 (inport == @pg_vm && ip4) allow-related
to-lport 2000 (outport == @pg_vm && ip4) allow-related
Router-Interface:
from-lport 2000 (inport == @pg_interface && ip4) drop
to-lport 2000 (outport == @pg_interface && ip4)
allow-stateless
The expected outcome was for the VM-1 traffic to be blocked because
the reply should be denied by the drop ACL on the Router-Interface.
However, in testing, we observed that traffic from the LSP still
passes as if unaffected by the drop rule.
After analyzing the flow tables, we found that once conntrack has
established a connection for a packet within a logical switch
pipeline, it allows reply packets by default, bypassing the configured
drop rule. This means that drop rules applied on router ports are
impacted by conntrack if there are stateful rules within the same
logical switch.
To address this, we propose introducing a new drop action, tentatively
named drop-stateless, that would handle packets requiring a drop
action before they reach the stateful processing stage. This would
prevent these packets from being affected by any stateful rules in
place.
Below is the code I’ve hardcoded to test this approach:
diff --git a/northd/northd.c b/northd/northd.c
index 3037ce0b5..528505b9e 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -6031,7 +6031,12 @@ build_stateless_filter(const struct ovn_datapath *od,
struct lflow_table *lflows,
struct lflow_ref *lflow_ref)
{
- const char *action = REGBIT_ACL_STATELESS" = 1; next;";
+ const char *action = NULL;
+ if (!strcmp(acl->action, "allow-stateless")) {
+ action = REGBIT_ACL_STATELESS" = 1; next;";
+ } else if (!strcmp(acl->action, "drop-stateless")) {
+ action = "drop;";
+ }
if (!strcmp(acl->direction, "from-lport")) {
ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_PRE_ACL,
acl->priority + OVN_ACL_PRI_OFFSET,
@@ -6057,7 +6062,8 @@ build_stateless_filters(const struct ovn_datapath *od,
{
for (size_t i = 0; i < od->nbs->n_acls; i++) {
const struct nbrec_acl *acl = od->nbs->acls[i];
- if (!strcmp(acl->action, "allow-stateless")) {
+ if (!strcmp(acl->action, "allow-stateless") ||
+ !strcmp(acl->action, "drop-stateless")) {
build_stateless_filter(od, acl, lflows, lflow_ref);
}
}
@@ -6073,7 +6079,8 @@ build_stateless_filters(const struct ovn_datapath *od,
for (size_t i = 0; i < ls_pg_rec->nb_pg->n_acls; i++) {
const struct nbrec_acl *acl = ls_pg_rec->nb_pg->acls[i];
- if (!strcmp(acl->action, "allow-stateless")) {
+ if (!strcmp(acl->action, "allow-stateless") ||
+ !strcmp(acl->action, "drop-stateless")) {
build_stateless_filter(od, acl, lflows, lflow_ref);
}
}
Looking forward to your feedback and suggestions.
Best regards,
Liushy
_______________________________________________
discuss mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-discuss