Message ID | 20200924164955.2733564-1-numans@ovn.org |
---|---|
State | Changes Requested |
Headers | show |
Series | [ovs-dev] ovn-northd: Optimize logical flow generation for reject ACLs. | expand |
Thanks Numan. I have some comments on the solution. On Thu, Sep 24, 2020 at 9:50 AM <numans@ovn.org> wrote: > > From: Numan Siddique <numans@ovn.org> > > ovn-northd adds below lflows for a reject ACL with a match - M > > match = (ip4 && tcp && 'M') action = tcp_reject{} > match = (ip6 && tcp && 'M') action = tcp_reject{} > match = (ip4 && 'M') action = icmp4{} > match = (ip6 && 'M') action = icmp6{} > > This approach has a couple of problems: > - ovn-controller can reject the lflows if there are invalid matches. > Eg. If match 'M' is - 'ip4 && udp'. > > - In a large scale deployment, this could result in lot of invalid > logical flows and increase the size of the SB DB. > > This patch addresses this problem by providing an option to the CMS > to specify the l3 protocol and l4 protocol as hints. A new column > 'options' is added to the ACL table with the options - > options:l3-protocol and options:l4-protocol. > > ovn-northd will now generate only the required lflows for the reject > ACL. If no options are set, then it falls back to the default scenario. > Thanks Numan. I believe the solution should work. However, it seems a little confusing for the end user about how to use the hint field. I think maybe we should try to avoid the extra field if possible. Here is my proposal: 1. For the tcp v.s. udp check, since we don't want northd to parse the match condition, we will have to rely on users input. However, instead of a hint, I think it is better to let the user explicitly specify in the action field. E.g. "reject" means sending icmp, and "tcp_reject" means sending tcp reset if the traffic is tcp and otherwise sending icmp. So, if the user adds an ACL with match include "udp", they will naturally use "reject" instead of "tcp_reject" because they know it is not possible for a TCP packet to hit this ACL. If they add an ACL that tcp traffic is expected to match (either TCP only, or general IP traffic), they can use "tcp_reject". Would this be more straightforward than an extra "hint" field? 2. For ip4 v.s. ip6, the idea is to support generic ovn logical flow actions "tcp_reject" and "icmp" in ovn-controller, which can handle both ipv4 and ipv6. If this can be supported, the logical flows only needs to be: match = (tcp && 'M') action = tcp_reject{} match = ('M') action = icmp{} I haven't thought through all the details but it seems doable. Did you have any thoughts on this? (If it proves to be unreasonable I am ok with current "hint" approach) In addition, I found the existing TCP reject handling has a bug which messes up the user defined ACL priorities. I just posted a patch: https://patchwork.ozlabs.org/project/ovn/patch/20200928000904.858685-1-hzhou@ovn.org/ It is not directly related to this patch but it would be great if you could take a look. Thanks, Han > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1876990 > Reported-by: Ilya Maximets <i.maximets@ovn.org> > Signed-off-by: Numan Siddique <numans@ovn.org> > --- > northd/ovn-northd.c | 194 ++++++++++++++++++++---------- > ovn-nb.ovsschema | 7 +- > ovn-nb.xml | 43 +++++++ > tests/ovn-northd.at | 285 ++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 461 insertions(+), 68 deletions(-) > > diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c > index 3324c9e81d..d167137e07 100644 > --- a/northd/ovn-northd.c > +++ b/northd/ovn-northd.c > @@ -5372,73 +5372,135 @@ build_reject_acl_rules(struct ovn_datapath *od, struct hmap *lflows, > struct ds actions = DS_EMPTY_INITIALIZER; > bool ingress = (stage == S_SWITCH_IN_ACL); > > - /* TCP */ > - build_acl_log(&actions, acl); > - if (extra_match->length > 0) { > - ds_put_format(&match, "(%s) && ", extra_match->string); > - } > - ds_put_format(&match, "ip4 && tcp && (%s)", acl->match); > - ds_put_format(&actions, "reg0 = 0; " > - "eth.dst <-> eth.src; ip4.dst <-> ip4.src; " > - "tcp_reset { outport <-> inport; %s };", > - ingress ? "next(pipeline=egress,table=5);" > - : "next(pipeline=ingress,table=20);"); > - ovn_lflow_add_with_hint(lflows, od, stage, > - acl->priority + OVN_ACL_PRI_OFFSET + 10, > - ds_cstr(&match), ds_cstr(&actions), stage_hint); > - ds_clear(&match); > - ds_clear(&actions); > - build_acl_log(&actions, acl); > - if (extra_match->length > 0) { > - ds_put_format(&match, "(%s) && ", extra_match->string); > - } > - ds_put_format(&match, "ip6 && tcp && (%s)", acl->match); > - ds_put_format(&actions, "reg0 = 0; " > - "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > - "tcp_reset { outport <-> inport; %s };", > - ingress ? "next(pipeline=egress,table=5);" > - : "next(pipeline=ingress,table=20);"); > - ovn_lflow_add_with_hint(lflows, od, stage, > - acl->priority + OVN_ACL_PRI_OFFSET + 10, > - ds_cstr(&match), ds_cstr(&actions), stage_hint); > + bool is_ip4 = true; > + bool is_ip6 = true; > + bool tcp_reset = true; > + bool icmp_reset = true; > + bool is_udp = false; > + > + const char *l3_protocol = smap_get(&acl->options, "l3-protocol"); > + if (l3_protocol) { > + if (!strcasecmp(l3_protocol, "ip")) { > + is_ip4 = true; > + is_ip6 = true; > + } else if (!strcasecmp(l3_protocol, "ip4")) { > + is_ip4 = true; > + is_ip6 = false; > + } else if (!strcasecmp(l3_protocol, "ip6")) { > + is_ip6 = true; > + is_ip4 = false; > + } > + } > + > + const char *l4_protocol = smap_get(&acl->options, "l4-protocol"); > + if (l4_protocol) { > + if (!strcasecmp(l4_protocol, "tcp")) { > + tcp_reset = true; > + icmp_reset = false; > + } else if (!strcasecmp(l4_protocol, "udp")) { > + tcp_reset = false; > + is_udp = true; > + } else { > + tcp_reset = false; > + } > + } > > - /* IP traffic */ > - ds_clear(&match); > - ds_clear(&actions); > - build_acl_log(&actions, acl); > - if (extra_match->length > 0) { > - ds_put_format(&match, "(%s) && ", extra_match->string); > - } > - ds_put_format(&match, "ip4 && (%s)", acl->match); > - if (extra_actions->length > 0) { > - ds_put_format(&actions, "%s ", extra_actions->string); > - } > - ds_put_format(&actions, "reg0 = 0; " > - "icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; " > - "outport <-> inport; %s };", > - ingress ? "next(pipeline=egress,table=5);" > - : "next(pipeline=ingress,table=20);"); > - ovn_lflow_add_with_hint(lflows, od, stage, > - acl->priority + OVN_ACL_PRI_OFFSET, > - ds_cstr(&match), ds_cstr(&actions), stage_hint); > - ds_clear(&match); > - ds_clear(&actions); > - build_acl_log(&actions, acl); > - if (extra_match->length > 0) { > - ds_put_format(&match, "(%s) && ", extra_match->string); > - } > - ds_put_format(&match, "ip6 && (%s)", acl->match); > - if (extra_actions->length > 0) { > - ds_put_format(&actions, "%s ", extra_actions->string); > - } > - ds_put_format(&actions, "reg0 = 0; icmp6 { " > - "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > - "outport <-> inport; %s };", > - ingress ? "next(pipeline=egress,table=5);" > - : "next(pipeline=ingress,table=20);"); > - ovn_lflow_add_with_hint(lflows, od, stage, > - acl->priority + OVN_ACL_PRI_OFFSET, > - ds_cstr(&match), ds_cstr(&actions), stage_hint); > + if (is_ip4) { > + if (tcp_reset) { > + build_acl_log(&actions, acl); > + if (extra_match->length > 0) { > + ds_put_format(&match, "(%s) && ", extra_match->string); > + } > + ds_put_format(&match, "ip4 && tcp && (%s)", acl->match); > + if (extra_actions->length > 0) { > + ds_put_format(&actions, "%s ", extra_actions->string); > + } > + ds_put_format(&actions, "reg0 = 0; " > + "eth.dst <-> eth.src; ip4.dst <-> ip4.src; " > + "tcp_reset { outport <-> inport; %s };", > + ingress ? "next(pipeline=egress,table=5);" > + : "next(pipeline=ingress,table=20);"); > + ovn_lflow_add_with_hint(lflows, od, stage, > + acl->priority + OVN_ACL_PRI_OFFSET + 10, > + ds_cstr(&match), ds_cstr(&actions), > + stage_hint); > + } > + > + if (icmp_reset) { > + ds_clear(&match); > + ds_clear(&actions); > + build_acl_log(&actions, acl); > + if (extra_match->length > 0) { > + ds_put_format(&match, "(%s) && ", extra_match->string); > + } > + ds_put_format(&match, "ip4 && (%s)", acl->match); > + if (is_udp) { > + ds_put_cstr(&match, " && udp"); > + } > + if (extra_actions->length > 0) { > + ds_put_format(&actions, "%s ", extra_actions->string); > + } > + ds_put_format(&actions, "reg0 = 0; " > + "icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; " > + "outport <-> inport; %s };", > + ingress ? "next(pipeline=egress,table=5);" > + : "next(pipeline=ingress,table=20);"); > + ovn_lflow_add_with_hint(lflows, od, stage, > + acl->priority + OVN_ACL_PRI_OFFSET, > + ds_cstr(&match), ds_cstr(&actions), > + stage_hint); > + } > + } > + > + if (is_ip6) { > + if (tcp_reset) { > + ds_clear(&match); > + ds_clear(&actions); > + build_acl_log(&actions, acl); > + if (extra_match->length > 0) { > + ds_put_format(&match, "(%s) && ", extra_match->string); > + } > + ds_put_format(&match, "ip6 && tcp && (%s)", acl->match); > + if (extra_actions->length > 0) { > + ds_put_format(&actions, "%s ", extra_actions->string); > + } > + ds_put_format(&actions, "reg0 = 0; " > + "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > + "tcp_reset { outport <-> inport; %s };", > + ingress ? "next(pipeline=egress,table=5);" > + : "next(pipeline=ingress,table=20);"); > + ovn_lflow_add_with_hint(lflows, od, stage, > + acl->priority + OVN_ACL_PRI_OFFSET + 10, > + ds_cstr(&match), ds_cstr(&actions), > + stage_hint); > + } > + > + if (icmp_reset) { > + ds_clear(&match); > + ds_clear(&actions); > + build_acl_log(&actions, acl); > + if (extra_match->length > 0) { > + ds_put_format(&match, "(%s) && ", extra_match->string); > + } > + ds_put_format(&match, "ip6 && (%s)", acl->match); > + if (is_udp) { > + ds_put_cstr(&match, " && udp"); > + } > + > + if (extra_actions->length > 0) { > + ds_put_format(&actions, "%s ", extra_actions->string); > + } > + ds_put_format(&actions, "reg0 = 0; icmp6 { " > + "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > + "outport <-> inport; %s };", > + ingress ? "next(pipeline=egress,table=5);" > + : "next(pipeline=ingress,table=20);"); > + ovn_lflow_add_with_hint(lflows, od, stage, > + acl->priority + OVN_ACL_PRI_OFFSET, > + ds_cstr(&match), ds_cstr(&actions), > + stage_hint); > + } > + } > > ds_destroy(&match); > ds_destroy(&actions); > diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema > index 092322ab2c..00f1c7cd4b 100644 > --- a/ovn-nb.ovsschema > +++ b/ovn-nb.ovsschema > @@ -1,7 +1,7 @@ > { > "name": "OVN_Northbound", > - "version": "5.27.0", > - "cksum": "3507518247 26773", > + "version": "5.28.0", > + "cksum": "699859908 26928", > "tables": { > "NB_Global": { > "columns": { > @@ -225,6 +225,9 @@ > "debug"]]}, > "min": 0, "max": 1}}, > "meter": {"type": {"key": "string", "min": 0, "max": 1}}, > + "options": { > + "type": {"key": "string", "value": "string", > + "min": 0, "max": "unlimited"}}, > "external_ids": { > "type": {"key": "string", "value": "string", > "min": 0, "max": "unlimited"}}}, > diff --git a/ovn-nb.xml b/ovn-nb.xml > index 86195af341..2c3497e2ae 100644 > --- a/ovn-nb.xml > +++ b/ovn-nb.xml > @@ -1721,6 +1721,49 @@ > </ul> > </column> > > + <group title="Common options"> > + <column name="options"> > + This column provides general key/value settings. The supported > + options are described individually below. > + </column> > + > + <group title="Options for providing protocol hints for reject ACL."> > + <p> > + The ACL match specified in the > + <ref column="match" table="ACL" db="OVN_Northbound"/> column is > + opaque to <code>OVN</code> and <code>ovn-northd</code> doesn't > + look into the match fields. > + These options can be specified by CMS to provide hints to > + <code>OVN</code> about the L3 and L4 protocol matches for the reject > + ACL. <code>ovn-northd</code> uses these options if set to use > + appropriate actions when generating logical flows. > + </p> > + > + <p> > + If these options are not set, then <code>ovn-northd</code> assumes > + the reject ACL applies to IPv4, IPv6 and TCP packets. > + </p> > + > + <column name="options" key="l3-protocol"> > + The possible values are <code>ip</code>, <code>ip4</code> and > + <code>ip6</code>. If the value is <code>ip</code>, it means the > + reject ACL action applies to both IPv4 and IPv6 packets. If the > + value is <code>ip4</code>, it means the reject ACL action applies to > + IPv4 packets and the value <code>ip6</code> applies to IPv6 packets. > + </column> > + > + <column name="options" key="l4-protocol"> > + <p> > + The possible values are <code>tcp</code> and <code>udp</code>. > + If the value is <code>tcp</code>, it means the > + reject ACL action applies to TCP packets. If the > + value is <code>udp</code>, it means the reject ACL action applies > + to UDP packets. > + </p> > + </column> > + </group> > + </group> > + > <group title="Logging"> > <p> > These columns control whether and how OVN logs packets that match an > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at > index 99a9204f1f..4a30f8ed07 100644 > --- a/tests/ovn-northd.at > +++ b/tests/ovn-northd.at > @@ -2010,3 +2010,288 @@ ovn-nbctl --wait=sb set NB_Global . options:ignore_lsp_down=true > AT_CHECK([ovn-sbctl lflow-list | grep arp | grep 10\.0\.0\.1], [0], [ignore]) > > AT_CLEANUP > + > +AT_SETUP([ovn-northd -- ACL reject flows]) > +ovn_start > + > +ovn-nbctl ls-add sw0 > +ovn-nbctl lsp-add sw0 sw0-p1 > +ovn-nbctl lsp-add sw0 sw0-p2 > + > +ovn-nbctl pg-add pg0 sw0-p1 sw0-p2 > +ovn-nbctl acl-add pg0 to-lport 1002 "inport == @pg0 && ip" reject > + > +ovn-nbctl --wait=sb sync > + > +# If there is a reject ACL wihtout any protocol hints, then ovn-northd should > +# generate lflows with ip4 tcp_reset, icmp4, ip6 tcp_reset and icmp6 actions. > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=(ip4 && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=(ip6 && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +# Set l3-protocol=ip4 for the reject ACL. > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip4 > + > +# ovn-northd should generate 2 lflows with ip4 tcp_reset and icmp4 actions. > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=(ip4 && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +# Set l4-protocol=tcp for the reject ACL. > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > + > +# ovn-northd should generate 1 lflow with ip4 tcp_reset action. > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl > +]) > + > +# Set l4-protocol=udp for the reject ACL. > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > + > +# ovn-northd should generate 1 lflow with udp match and icmp4 action. > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl > +]) > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=(ip4 && (inport == @pg0 && ip) && udp), dnl > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +# Remove l4-protocol from the reject ACL. > +ovn-nbctl --wait=sb remove ACL . options l4-protocol > + > +# ovn-northd should generate 2 lflow with tcp_reset and icmp4 action. > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=(ip4 && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +# Set l3-protocol to ip. > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > + > +# ovn-northd should generate 4 lflow with ip4 tcp_reset, ip6 tcp_reset, icmp4 and icmp6 actions. > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=(ip4 && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=(ip6 && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +# Set l3-protocol=ip6 for the reject ACL. > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip6 > + > +# ovn-northd should generate 2 lflows with ip6 tcp_reset and icmp6 actions. > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=(ip6 && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +# Set l4-protocol=tcp for the reject ACL. > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > + > +# ovn-northd should generate 1 lflow with ip6 tcp_reset action. > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl > +]) > + > +# Set l4-protocol=udp for the reject ACL. > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > + > +# ovn-northd should generate 1 lflow with udp match and icmp6 action. > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl > +]) > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=(ip6 && (inport == @pg0 && ip) && udp), dnl > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL. > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > + > +# ovn-northd should generate 2 lflow with ip4 tcp_reset and ip6 tcp_reset actions. > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl > +]) > + > +# Set l3-protocol to ip and l4-protocol=udp for the reject ACL. > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > + > +# ovn-northd should generate 2 lflows (udp match) with icmp4 and icmp6 actions. > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl > +]) > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=(ip4 && (inport == @pg0 && ip) && udp), dnl > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=(ip6 && (inport == @pg0 && ip) && udp), dnl > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +# Add an ACL with allow-related > +ovn-nbctl --wait=sb acl-add pg0 to-lport 1000 "ip" allow-related > + > +# ovn-northd should generate 4 lflow with 2 icmp4 and 2 icmp6 actions. > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl > +]) > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl\ > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL. > +rej_acl=$(ovn-nbctl --bare --columns _uuid find ACL action=reject) > +ovn-nbctl --wait=sb set ACL $rej_acl options:l3-protocol=ip > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp > + > +# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and 2 ip6 tcp_reset actions. > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl > +]) > + > + > +# Clear l3-protocol and set l4-protocol to udp > +ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=udp > + > +# ovn-northd should generate 4 lflows (with udp match) with 2 icmp4 and 2 icmp6 actions. > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl > +]) > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl\ > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2002 , dnl > +match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +# Clear l3-protocol and set l4-protocol to tcp > +ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp > + > +# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and 2 ip6 tcp_reset actions. > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > + table=5 (ls_out_acl ), priority=2012 , dnl > +match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) > +]) > + > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl > +]) > + > +AT_CLEANUP > -- > 2.26.2 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
On Mon, Sep 28, 2020 at 5:57 AM Han Zhou <hzhou@ovn.org> wrote: > > Thanks Numan. I have some comments on the solution. > > On Thu, Sep 24, 2020 at 9:50 AM <numans@ovn.org> wrote: > > > > From: Numan Siddique <numans@ovn.org> > > > > ovn-northd adds below lflows for a reject ACL with a match - M > > > > match = (ip4 && tcp && 'M') action = tcp_reject{} > > match = (ip6 && tcp && 'M') action = tcp_reject{} > > match = (ip4 && 'M') action = icmp4{} > > match = (ip6 && 'M') action = icmp6{} > > > > This approach has a couple of problems: > > - ovn-controller can reject the lflows if there are invalid matches. > > Eg. If match 'M' is - 'ip4 && udp'. > > > > - In a large scale deployment, this could result in lot of invalid > > logical flows and increase the size of the SB DB. > > > > This patch addresses this problem by providing an option to the CMS > > to specify the l3 protocol and l4 protocol as hints. A new column > > 'options' is added to the ACL table with the options - > > options:l3-protocol and options:l4-protocol. > > > > ovn-northd will now generate only the required lflows for the reject > > ACL. If no options are set, then it falls back to the default scenario. > > > > Thanks Numan. I believe the solution should work. However, it seems a > little confusing for the end user about how to use the hint field. I think > maybe we should try to avoid the extra field if possible. Here is my > proposal: > Thanks Han for the comments. I do agree if we can avoid the extra option. > 1. For the tcp v.s. udp check, since we don't want northd to parse the > match condition, we will have to rely on users input. However, instead of a > hint, I think it is better to let the user explicitly specify in the action > field. E.g. "reject" means sending icmp, and "tcp_reject" means sending tcp > reset if the traffic is tcp and otherwise sending icmp. So, if the user > adds an ACL with match include "udp", they will naturally use "reject" > instead of "tcp_reject" because they know it is not possible for a TCP > packet to hit this ACL. If they add an ACL that tcp traffic is expected to > match (either TCP only, or general IP traffic), they can use "tcp_reject". > Would this be more straightforward than an extra "hint" field? > I have few comments here. - If we consider "reject" = "icmp", then we will be breaking the backward compatibility. Right now, for a reject action, ovn-northd would send tcp_reset for tcp traffic and icmp reply or other traffic. After your proposed approach, the behaviour would change ? Is that OK ? Because existing test cases would fail. The proposed patch handles the backward compatibility. Although I'm not sure if it is really required in this case. - For a tcp_reject action, if the match has "tcp", then we will end up adding a logical flow with the icmp action, which is really not required. Or do you mean, pinctrl would take the decision while handling the "tcp_reject" action to either send tcp reset packet or icmp packet ? If so, we can probably just have one action - "reject". Please see below. > 2. For ip4 v.s. ip6, the idea is to support generic ovn logical flow > actions "tcp_reject" and "icmp" in ovn-controller, which can handle both > ipv4 and ipv6. If this can be supported, the logical flows only needs to be: > match = (tcp && 'M') action = tcp_reject{} > match = ('M') action = icmp{} > Ok. In this case we cannot support inner actions unless they are independent of the ip version. i.e we can't support - tcp_reject { eth.dst <-> eth.src; ip4.dst <-> ip4.src; } or tcp_reject {eth.dst <-> eth.src; ip6.dst <-> ip6.src;} in one logical flow. ovn-northd has to generate 2 logical flows. - ip4 && 'M', action = tcp_reject { eth.dst <-> eth.src; ip4.dst <-> ip4.src; } - ip6 && 'M', action = tcp_reject { eth.dst <-> eth.src; ip6.dst <-> ip6.src; } Right now for one reject ACL we add the below lflows - ip4 && tcp && 'M', action = tcp_reset { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport;} - ip6 && tcp && 'M', action = tcp_reset { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport;} - ip4 && 'M' , action = icmp4 {eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport;} - ip6 && 'M' , action = icmp6 {eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport;} I have another idea based on your suggestions here: How about we have a new action - reject{} which will be used for all reject ACLs and this will - send tcp reset packet if the packet is tcp (pinctrl would take the decision) - send icmp packet otherwise. We can add the logical flow for a reject ACL in 2 ways 1. match = M, action = reject { eth.dst <-> eth.src, outport <-> inport;} OR 2. match = M, action = reject { eth.dst <-> eth.src, ip.src <-> ip.dst; outport <-> inport;} In (1), pinctrl while handling the reject action, will swap the ip src with ip dst (i.e ip4.dst <-> ip4.src or ip6.dst <-> ip6.src }. In (2), we will add 2 new OVN fields "ip.src" and "ip.dst" (just like we have icmp4.frag_mtu now) and the action - ip.src <-> ip.dst will result in another controller action which will swap the ip src and ip dst fields (just like how "icmp4.frag_mtu = 1400" would result into a controller action). Even though (1) will work, it's not transparent. I would personally prefer (2) and I think it's ok if the reject ACL would result in 2 OF controller actions. With this we will have just one logical flow (instead of 4 ) and there will be no changes on the CMS side. What do you think ? Thanks Numan > I haven't thought through all the details but it seems doable. Did you have > any thoughts on this? (If it proves to be unreasonable I am ok with current > "hint" approach) > > In addition, I found the existing TCP reject handling has a bug which > messes up the user defined ACL priorities. I just posted a patch: > https://patchwork.ozlabs.org/project/ovn/patch/20200928000904.858685-1-hzhou@ovn.org/ > It is not directly related to this patch but it would be great if you could > take a look. > > Thanks, > Han > > > > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1876990 > > Reported-by: Ilya Maximets <i.maximets@ovn.org> > > Signed-off-by: Numan Siddique <numans@ovn.org> > > --- > > northd/ovn-northd.c | 194 ++++++++++++++++++++---------- > > ovn-nb.ovsschema | 7 +- > > ovn-nb.xml | 43 +++++++ > > tests/ovn-northd.at | 285 ++++++++++++++++++++++++++++++++++++++++++++ > > 4 files changed, 461 insertions(+), 68 deletions(-) > > > > diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c > > index 3324c9e81d..d167137e07 100644 > > --- a/northd/ovn-northd.c > > +++ b/northd/ovn-northd.c > > @@ -5372,73 +5372,135 @@ build_reject_acl_rules(struct ovn_datapath *od, > struct hmap *lflows, > > struct ds actions = DS_EMPTY_INITIALIZER; > > bool ingress = (stage == S_SWITCH_IN_ACL); > > > > - /* TCP */ > > - build_acl_log(&actions, acl); > > - if (extra_match->length > 0) { > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > - } > > - ds_put_format(&match, "ip4 && tcp && (%s)", acl->match); > > - ds_put_format(&actions, "reg0 = 0; " > > - "eth.dst <-> eth.src; ip4.dst <-> ip4.src; " > > - "tcp_reset { outport <-> inport; %s };", > > - ingress ? "next(pipeline=egress,table=5);" > > - : "next(pipeline=ingress,table=20);"); > > - ovn_lflow_add_with_hint(lflows, od, stage, > > - acl->priority + OVN_ACL_PRI_OFFSET + 10, > > - ds_cstr(&match), ds_cstr(&actions), > stage_hint); > > - ds_clear(&match); > > - ds_clear(&actions); > > - build_acl_log(&actions, acl); > > - if (extra_match->length > 0) { > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > - } > > - ds_put_format(&match, "ip6 && tcp && (%s)", acl->match); > > - ds_put_format(&actions, "reg0 = 0; " > > - "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > - "tcp_reset { outport <-> inport; %s };", > > - ingress ? "next(pipeline=egress,table=5);" > > - : "next(pipeline=ingress,table=20);"); > > - ovn_lflow_add_with_hint(lflows, od, stage, > > - acl->priority + OVN_ACL_PRI_OFFSET + 10, > > - ds_cstr(&match), ds_cstr(&actions), > stage_hint); > > + bool is_ip4 = true; > > + bool is_ip6 = true; > > + bool tcp_reset = true; > > + bool icmp_reset = true; > > + bool is_udp = false; > > + > > + const char *l3_protocol = smap_get(&acl->options, "l3-protocol"); > > + if (l3_protocol) { > > + if (!strcasecmp(l3_protocol, "ip")) { > > + is_ip4 = true; > > + is_ip6 = true; > > + } else if (!strcasecmp(l3_protocol, "ip4")) { > > + is_ip4 = true; > > + is_ip6 = false; > > + } else if (!strcasecmp(l3_protocol, "ip6")) { > > + is_ip6 = true; > > + is_ip4 = false; > > + } > > + } > > + > > + const char *l4_protocol = smap_get(&acl->options, "l4-protocol"); > > + if (l4_protocol) { > > + if (!strcasecmp(l4_protocol, "tcp")) { > > + tcp_reset = true; > > + icmp_reset = false; > > + } else if (!strcasecmp(l4_protocol, "udp")) { > > + tcp_reset = false; > > + is_udp = true; > > + } else { > > + tcp_reset = false; > > + } > > + } > > > > - /* IP traffic */ > > - ds_clear(&match); > > - ds_clear(&actions); > > - build_acl_log(&actions, acl); > > - if (extra_match->length > 0) { > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > - } > > - ds_put_format(&match, "ip4 && (%s)", acl->match); > > - if (extra_actions->length > 0) { > > - ds_put_format(&actions, "%s ", extra_actions->string); > > - } > > - ds_put_format(&actions, "reg0 = 0; " > > - "icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; " > > - "outport <-> inport; %s };", > > - ingress ? "next(pipeline=egress,table=5);" > > - : "next(pipeline=ingress,table=20);"); > > - ovn_lflow_add_with_hint(lflows, od, stage, > > - acl->priority + OVN_ACL_PRI_OFFSET, > > - ds_cstr(&match), ds_cstr(&actions), > stage_hint); > > - ds_clear(&match); > > - ds_clear(&actions); > > - build_acl_log(&actions, acl); > > - if (extra_match->length > 0) { > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > - } > > - ds_put_format(&match, "ip6 && (%s)", acl->match); > > - if (extra_actions->length > 0) { > > - ds_put_format(&actions, "%s ", extra_actions->string); > > - } > > - ds_put_format(&actions, "reg0 = 0; icmp6 { " > > - "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > - "outport <-> inport; %s };", > > - ingress ? "next(pipeline=egress,table=5);" > > - : "next(pipeline=ingress,table=20);"); > > - ovn_lflow_add_with_hint(lflows, od, stage, > > - acl->priority + OVN_ACL_PRI_OFFSET, > > - ds_cstr(&match), ds_cstr(&actions), > stage_hint); > > + if (is_ip4) { > > + if (tcp_reset) { > > + build_acl_log(&actions, acl); > > + if (extra_match->length > 0) { > > + ds_put_format(&match, "(%s) && ", extra_match->string); > > + } > > + ds_put_format(&match, "ip4 && tcp && (%s)", acl->match); > > + if (extra_actions->length > 0) { > > + ds_put_format(&actions, "%s ", extra_actions->string); > > + } > > + ds_put_format(&actions, "reg0 = 0; " > > + "eth.dst <-> eth.src; ip4.dst <-> ip4.src; " > > + "tcp_reset { outport <-> inport; %s };", > > + ingress ? "next(pipeline=egress,table=5);" > > + : "next(pipeline=ingress,table=20);"); > > + ovn_lflow_add_with_hint(lflows, od, stage, > > + acl->priority + OVN_ACL_PRI_OFFSET + > 10, > > + ds_cstr(&match), ds_cstr(&actions), > > + stage_hint); > > + } > > + > > + if (icmp_reset) { > > + ds_clear(&match); > > + ds_clear(&actions); > > + build_acl_log(&actions, acl); > > + if (extra_match->length > 0) { > > + ds_put_format(&match, "(%s) && ", extra_match->string); > > + } > > + ds_put_format(&match, "ip4 && (%s)", acl->match); > > + if (is_udp) { > > + ds_put_cstr(&match, " && udp"); > > + } > > + if (extra_actions->length > 0) { > > + ds_put_format(&actions, "%s ", extra_actions->string); > > + } > > + ds_put_format(&actions, "reg0 = 0; " > > + "icmp4 { eth.dst <-> eth.src; ip4.dst <-> > ip4.src; " > > + "outport <-> inport; %s };", > > + ingress ? "next(pipeline=egress,table=5);" > > + : "next(pipeline=ingress,table=20);"); > > + ovn_lflow_add_with_hint(lflows, od, stage, > > + acl->priority + OVN_ACL_PRI_OFFSET, > > + ds_cstr(&match), ds_cstr(&actions), > > + stage_hint); > > + } > > + } > > + > > + if (is_ip6) { > > + if (tcp_reset) { > > + ds_clear(&match); > > + ds_clear(&actions); > > + build_acl_log(&actions, acl); > > + if (extra_match->length > 0) { > > + ds_put_format(&match, "(%s) && ", extra_match->string); > > + } > > + ds_put_format(&match, "ip6 && tcp && (%s)", acl->match); > > + if (extra_actions->length > 0) { > > + ds_put_format(&actions, "%s ", extra_actions->string); > > + } > > + ds_put_format(&actions, "reg0 = 0; " > > + "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > + "tcp_reset { outport <-> inport; %s };", > > + ingress ? "next(pipeline=egress,table=5);" > > + : "next(pipeline=ingress,table=20);"); > > + ovn_lflow_add_with_hint(lflows, od, stage, > > + acl->priority + OVN_ACL_PRI_OFFSET + > 10, > > + ds_cstr(&match), ds_cstr(&actions), > > + stage_hint); > > + } > > + > > + if (icmp_reset) { > > + ds_clear(&match); > > + ds_clear(&actions); > > + build_acl_log(&actions, acl); > > + if (extra_match->length > 0) { > > + ds_put_format(&match, "(%s) && ", extra_match->string); > > + } > > + ds_put_format(&match, "ip6 && (%s)", acl->match); > > + if (is_udp) { > > + ds_put_cstr(&match, " && udp"); > > + } > > + > > + if (extra_actions->length > 0) { > > + ds_put_format(&actions, "%s ", extra_actions->string); > > + } > > + ds_put_format(&actions, "reg0 = 0; icmp6 { " > > + "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > + "outport <-> inport; %s };", > > + ingress ? "next(pipeline=egress,table=5);" > > + : "next(pipeline=ingress,table=20);"); > > + ovn_lflow_add_with_hint(lflows, od, stage, > > + acl->priority + OVN_ACL_PRI_OFFSET, > > + ds_cstr(&match), ds_cstr(&actions), > > + stage_hint); > > + } > > + } > > > > ds_destroy(&match); > > ds_destroy(&actions); > > diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema > > index 092322ab2c..00f1c7cd4b 100644 > > --- a/ovn-nb.ovsschema > > +++ b/ovn-nb.ovsschema > > @@ -1,7 +1,7 @@ > > { > > "name": "OVN_Northbound", > > - "version": "5.27.0", > > - "cksum": "3507518247 26773", > > + "version": "5.28.0", > > + "cksum": "699859908 26928", > > "tables": { > > "NB_Global": { > > "columns": { > > @@ -225,6 +225,9 @@ > > "debug"]]}, > > "min": 0, "max": 1}}, > > "meter": {"type": {"key": "string", "min": 0, "max": 1}}, > > + "options": { > > + "type": {"key": "string", "value": "string", > > + "min": 0, "max": "unlimited"}}, > > "external_ids": { > > "type": {"key": "string", "value": "string", > > "min": 0, "max": "unlimited"}}}, > > diff --git a/ovn-nb.xml b/ovn-nb.xml > > index 86195af341..2c3497e2ae 100644 > > --- a/ovn-nb.xml > > +++ b/ovn-nb.xml > > @@ -1721,6 +1721,49 @@ > > </ul> > > </column> > > > > + <group title="Common options"> > > + <column name="options"> > > + This column provides general key/value settings. The supported > > + options are described individually below. > > + </column> > > + > > + <group title="Options for providing protocol hints for reject > ACL."> > > + <p> > > + The ACL match specified in the > > + <ref column="match" table="ACL" db="OVN_Northbound"/> column is > > + opaque to <code>OVN</code> and <code>ovn-northd</code> doesn't > > + look into the match fields. > > + These options can be specified by CMS to provide hints to > > + <code>OVN</code> about the L3 and L4 protocol matches for the > reject > > + ACL. <code>ovn-northd</code> uses these options if set to use > > + appropriate actions when generating logical flows. > > + </p> > > + > > + <p> > > + If these options are not set, then <code>ovn-northd</code> > assumes > > + the reject ACL applies to IPv4, IPv6 and TCP packets. > > + </p> > > + > > + <column name="options" key="l3-protocol"> > > + The possible values are <code>ip</code>, <code>ip4</code> and > > + <code>ip6</code>. If the value is <code>ip</code>, it means the > > + reject ACL action applies to both IPv4 and IPv6 packets. If the > > + value is <code>ip4</code>, it means the reject ACL action > applies to > > + IPv4 packets and the value <code>ip6</code> applies to IPv6 > packets. > > + </column> > > + > > + <column name="options" key="l4-protocol"> > > + <p> > > + The possible values are <code>tcp</code> and > <code>udp</code>. > > + If the value is <code>tcp</code>, it means the > > + reject ACL action applies to TCP packets. If the > > + value is <code>udp</code>, it means the reject ACL action > applies > > + to UDP packets. > > + </p> > > + </column> > > + </group> > > + </group> > > + > > <group title="Logging"> > > <p> > > These columns control whether and how OVN logs packets that > match an > > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at > > index 99a9204f1f..4a30f8ed07 100644 > > --- a/tests/ovn-northd.at > > +++ b/tests/ovn-northd.at > > @@ -2010,3 +2010,288 @@ ovn-nbctl --wait=sb set NB_Global . > options:ignore_lsp_down=true > > AT_CHECK([ovn-sbctl lflow-list | grep arp | grep 10\.0\.0\.1], [0], > [ignore]) > > > > AT_CLEANUP > > + > > +AT_SETUP([ovn-northd -- ACL reject flows]) > > +ovn_start > > + > > +ovn-nbctl ls-add sw0 > > +ovn-nbctl lsp-add sw0 sw0-p1 > > +ovn-nbctl lsp-add sw0 sw0-p2 > > + > > +ovn-nbctl pg-add pg0 sw0-p1 sw0-p2 > > +ovn-nbctl acl-add pg0 to-lport 1002 "inport == @pg0 && ip" reject > > + > > +ovn-nbctl --wait=sb sync > > + > > +# If there is a reject ACL wihtout any protocol hints, then ovn-northd > should > > +# generate lflows with ip4 tcp_reset, icmp4, ip6 tcp_reset and icmp6 > actions. > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > outport <-> inport; next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > outport <-> inport; next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +# Set l3-protocol=ip4 for the reject ACL. > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip4 > > + > > +# ovn-northd should generate 2 lflows with ip4 tcp_reset and icmp4 > actions. > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +# Set l4-protocol=tcp for the reject ACL. > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > + > > +# ovn-northd should generate 1 lflow with ip4 tcp_reset action. > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > sort], [0], [dnl > > +]) > > + > > +# Set l4-protocol=udp for the reject ACL. > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > + > > +# ovn-northd should generate 1 lflow with udp match and icmp4 action. > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > sort], [0], [dnl > > +]) > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=(ip4 && (inport == @pg0 && ip) && udp), dnl > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +# Remove l4-protocol from the reject ACL. > > +ovn-nbctl --wait=sb remove ACL . options l4-protocol > > + > > +# ovn-northd should generate 2 lflow with tcp_reset and icmp4 action. > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +# Set l3-protocol to ip. > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > + > > +# ovn-northd should generate 4 lflow with ip4 tcp_reset, ip6 tcp_reset, > icmp4 and icmp6 actions. > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > outport <-> inport; next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > outport <-> inport; next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +# Set l3-protocol=ip6 for the reject ACL. > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip6 > > + > > +# ovn-northd should generate 2 lflows with ip6 tcp_reset and icmp6 > actions. > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +# Set l4-protocol=tcp for the reject ACL. > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > + > > +# ovn-northd should generate 1 lflow with ip6 tcp_reset action. > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > sort], [0], [dnl > > +]) > > + > > +# Set l4-protocol=udp for the reject ACL. > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > + > > +# ovn-northd should generate 1 lflow with udp match and icmp6 action. > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > sort], [0], [dnl > > +]) > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=(ip6 && (inport == @pg0 && ip) && udp), dnl > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL. > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > + > > +# ovn-northd should generate 2 lflow with ip4 tcp_reset and ip6 > tcp_reset actions. > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > outport <-> inport; next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > sort], [0], [dnl > > +]) > > + > > +# Set l3-protocol to ip and l4-protocol=udp for the reject ACL. > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > + > > +# ovn-northd should generate 2 lflows (udp match) with icmp4 and icmp6 > actions. > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > sort], [0], [dnl > > +]) > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=(ip4 && (inport == @pg0 && ip) && udp), dnl > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > outport <-> inport; next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=(ip6 && (inport == @pg0 && ip) && udp), dnl > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +# Add an ACL with allow-related > > +ovn-nbctl --wait=sb acl-add pg0 to-lport 1000 "ip" allow-related > > + > > +# ovn-northd should generate 4 lflow with 2 icmp4 and 2 icmp6 actions. > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > sort], [0], [dnl > > +]) > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl\ > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp4 { eth.dst > <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; > next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp6 { eth.dst > <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; > next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > outport <-> inport; next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL. > > +rej_acl=$(ovn-nbctl --bare --columns _uuid find ACL action=reject) > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l3-protocol=ip > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp > > + > > +# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and 2 ip6 > tcp_reset actions. > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; > next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; > next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > outport <-> inport; next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > sort], [0], [dnl > > +]) > > + > > + > > +# Clear l3-protocol and set l4-protocol to udp > > +ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=udp > > + > > +# ovn-northd should generate 4 lflows (with udp match) with 2 icmp4 and > 2 icmp6 actions. > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > sort], [0], [dnl > > +]) > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl\ > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp4 { eth.dst > <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; > next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp6 { eth.dst > <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; > next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > outport <-> inport; next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2002 , dnl > > +match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +# Clear l3-protocol and set l4-protocol to tcp > > +ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp > > + > > +# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and 2 ip6 > tcp_reset actions. > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > sort], [0], [dnl > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; > next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; > next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > outport <-> inport; next(pipeline=ingress,table=20); };) > > + table=5 (ls_out_acl ), priority=2012 , dnl > > +match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > outport <-> inport; next(pipeline=ingress,table=20); };) > > +]) > > + > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > sort], [0], [dnl > > +]) > > + > > +AT_CLEANUP > > -- > > 2.26.2 > > > > _______________________________________________ > > dev mailing list > > dev@openvswitch.org > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev >
On Mon, Sep 28, 2020 at 2:14 PM Numan Siddique <numans@ovn.org> wrote: > > On Mon, Sep 28, 2020 at 5:57 AM Han Zhou <hzhou@ovn.org> wrote: > > > > Thanks Numan. I have some comments on the solution. > > > > On Thu, Sep 24, 2020 at 9:50 AM <numans@ovn.org> wrote: > > > > > > From: Numan Siddique <numans@ovn.org> > > > > > > ovn-northd adds below lflows for a reject ACL with a match - M > > > > > > match = (ip4 && tcp && 'M') action = tcp_reject{} > > > match = (ip6 && tcp && 'M') action = tcp_reject{} > > > match = (ip4 && 'M') action = icmp4{} > > > match = (ip6 && 'M') action = icmp6{} > > > > > > This approach has a couple of problems: > > > - ovn-controller can reject the lflows if there are invalid matches. > > > Eg. If match 'M' is - 'ip4 && udp'. > > > > > > - In a large scale deployment, this could result in lot of invalid > > > logical flows and increase the size of the SB DB. > > > > > > This patch addresses this problem by providing an option to the CMS > > > to specify the l3 protocol and l4 protocol as hints. A new column > > > 'options' is added to the ACL table with the options - > > > options:l3-protocol and options:l4-protocol. > > > > > > ovn-northd will now generate only the required lflows for the reject > > > ACL. If no options are set, then it falls back to the default scenario. > > > > > > > Thanks Numan. I believe the solution should work. However, it seems a > > little confusing for the end user about how to use the hint field. I think > > maybe we should try to avoid the extra field if possible. Here is my > > proposal: > > > > Thanks Han for the comments. I do agree if we can avoid the extra option. > > > 1. For the tcp v.s. udp check, since we don't want northd to parse the > > match condition, we will have to rely on users input. However, instead of a > > hint, I think it is better to let the user explicitly specify in the action > > field. E.g. "reject" means sending icmp, and "tcp_reject" means sending tcp > > reset if the traffic is tcp and otherwise sending icmp. So, if the user > > adds an ACL with match include "udp", they will naturally use "reject" > > instead of "tcp_reject" because they know it is not possible for a TCP > > packet to hit this ACL. If they add an ACL that tcp traffic is expected to > > match (either TCP only, or general IP traffic), they can use "tcp_reject". > > Would this be more straightforward than an extra "hint" field? > > > > I have few comments here. > - If we consider "reject" = "icmp", then we will be breaking the > backward compatibility. > Right now, for a reject action, ovn-northd would send tcp_reset > for tcp traffic and icmp reply or other traffic. > After your proposed approach, the behaviour would change ? Is > that OK ? Because existing test cases would fail. > The proposed patch handles the backward compatibility. Although > I'm not sure if it is really required in this case. > > - For a tcp_reject action, if the match has "tcp", then we will end > up adding a logical flow with the icmp action, which is > really not required. Or do you mean, pinctrl would take the > decision while handling the "tcp_reject" action to either > send tcp reset packet or icmp packet ? If so, we can probably just > have one action - "reject". Please see below. > > > 2. For ip4 v.s. ip6, the idea is to support generic ovn logical flow > > actions "tcp_reject" and "icmp" in ovn-controller, which can handle both > > ipv4 and ipv6. If this can be supported, the logical flows only needs to be: > > match = (tcp && 'M') action = tcp_reject{} > > match = ('M') action = icmp{} > > > > Ok. In this case we cannot support inner actions unless they are > independent of the ip version. > i.e we can't support - tcp_reject { eth.dst <-> eth.src; ip4.dst <-> > ip4.src; } or > tcp_reject {eth.dst <-> eth.src; ip6.dst <-> ip6.src;} in one logical > flow. ovn-northd has to generate > 2 logical flows. > - ip4 && 'M', action = tcp_reject { eth.dst <-> eth.src; ip4.dst <-> > ip4.src; } > - ip6 && 'M', action = tcp_reject { eth.dst <-> eth.src; ip6.dst <-> > ip6.src; } > > > Right now for one reject ACL we add the below lflows > - ip4 && tcp && 'M', action = tcp_reset { eth.dst <-> eth.src; > ip4.dst <-> ip4.src; outport <-> inport;} > - ip6 && tcp && 'M', action = tcp_reset { eth.dst <-> eth.src; > ip6.dst <-> ip6.src; outport <-> inport;} > - ip4 && 'M' , action = icmp4 {eth.dst <-> eth.src; > ip4.dst <-> ip4.src; outport <-> inport;} > - ip6 && 'M' , action = icmp6 {eth.dst <-> eth.src; > ip6.dst <-> ip6.src; outport <-> inport;} > > I have another idea based on your suggestions here: How about we have > a new action - reject{} which will be used > for all reject ACLs and this will > - send tcp reset packet if the packet is tcp (pinctrl would take > the decision) > - send icmp packet otherwise. > > We can add the logical flow for a reject ACL in 2 ways > > 1. match = M, action = reject { eth.dst <-> eth.src, outport <-> inport;} > > OR > > 2. match = M, action = reject { eth.dst <-> eth.src, ip.src <-> > ip.dst; outport <-> inport;} > > In (1), pinctrl while handling the reject action, will swap the ip src > with ip dst (i.e ip4.dst <-> ip4.src or ip6.dst <-> ip6.src }. > > In (2), we will add 2 new OVN fields "ip.src" and "ip.dst" (just like > we have icmp4.frag_mtu now) and the action - ip.src <-> ip.dst > will result in another controller action which will swap the ip src > and ip dst fields (just like how "icmp4.frag_mtu = 1400" would result > into a controller action). > > Even though (1) will work, it's not transparent. I would personally > prefer (2) and I think it's ok if the reject ACL would result in 2 OF > controller actions. > > With this we will have just one logical flow (instead of 4 ) and there > will be no changes on the CMS side. > > What do you think ? > > Thanks > Numan > > > > I haven't thought through all the details but it seems doable. Did you have > > any thoughts on this? (If it proves to be unreasonable I am ok with current > > "hint" approach) > > > > In addition, I found the existing TCP reject handling has a bug which > > messes up the user defined ACL priorities. I just posted a patch: > > https://patchwork.ozlabs.org/project/ovn/patch/20200928000904.858685-1-hzhou@ovn.org/ > > It is not directly related to this patch but it would be great if you could > > take a look. Sure. Thanks Numan > > > > Thanks, > > Han > > > > > > > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1876990 > > > Reported-by: Ilya Maximets <i.maximets@ovn.org> > > > Signed-off-by: Numan Siddique <numans@ovn.org> > > > --- > > > northd/ovn-northd.c | 194 ++++++++++++++++++++---------- > > > ovn-nb.ovsschema | 7 +- > > > ovn-nb.xml | 43 +++++++ > > > tests/ovn-northd.at | 285 ++++++++++++++++++++++++++++++++++++++++++++ > > > 4 files changed, 461 insertions(+), 68 deletions(-) > > > > > > diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c > > > index 3324c9e81d..d167137e07 100644 > > > --- a/northd/ovn-northd.c > > > +++ b/northd/ovn-northd.c > > > @@ -5372,73 +5372,135 @@ build_reject_acl_rules(struct ovn_datapath *od, > > struct hmap *lflows, > > > struct ds actions = DS_EMPTY_INITIALIZER; > > > bool ingress = (stage == S_SWITCH_IN_ACL); > > > > > > - /* TCP */ > > > - build_acl_log(&actions, acl); > > > - if (extra_match->length > 0) { > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > - } > > > - ds_put_format(&match, "ip4 && tcp && (%s)", acl->match); > > > - ds_put_format(&actions, "reg0 = 0; " > > > - "eth.dst <-> eth.src; ip4.dst <-> ip4.src; " > > > - "tcp_reset { outport <-> inport; %s };", > > > - ingress ? "next(pipeline=egress,table=5);" > > > - : "next(pipeline=ingress,table=20);"); > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > - acl->priority + OVN_ACL_PRI_OFFSET + 10, > > > - ds_cstr(&match), ds_cstr(&actions), > > stage_hint); > > > - ds_clear(&match); > > > - ds_clear(&actions); > > > - build_acl_log(&actions, acl); > > > - if (extra_match->length > 0) { > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > - } > > > - ds_put_format(&match, "ip6 && tcp && (%s)", acl->match); > > > - ds_put_format(&actions, "reg0 = 0; " > > > - "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > > - "tcp_reset { outport <-> inport; %s };", > > > - ingress ? "next(pipeline=egress,table=5);" > > > - : "next(pipeline=ingress,table=20);"); > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > - acl->priority + OVN_ACL_PRI_OFFSET + 10, > > > - ds_cstr(&match), ds_cstr(&actions), > > stage_hint); > > > + bool is_ip4 = true; > > > + bool is_ip6 = true; > > > + bool tcp_reset = true; > > > + bool icmp_reset = true; > > > + bool is_udp = false; > > > + > > > + const char *l3_protocol = smap_get(&acl->options, "l3-protocol"); > > > + if (l3_protocol) { > > > + if (!strcasecmp(l3_protocol, "ip")) { > > > + is_ip4 = true; > > > + is_ip6 = true; > > > + } else if (!strcasecmp(l3_protocol, "ip4")) { > > > + is_ip4 = true; > > > + is_ip6 = false; > > > + } else if (!strcasecmp(l3_protocol, "ip6")) { > > > + is_ip6 = true; > > > + is_ip4 = false; > > > + } > > > + } > > > + > > > + const char *l4_protocol = smap_get(&acl->options, "l4-protocol"); > > > + if (l4_protocol) { > > > + if (!strcasecmp(l4_protocol, "tcp")) { > > > + tcp_reset = true; > > > + icmp_reset = false; > > > + } else if (!strcasecmp(l4_protocol, "udp")) { > > > + tcp_reset = false; > > > + is_udp = true; > > > + } else { > > > + tcp_reset = false; > > > + } > > > + } > > > > > > - /* IP traffic */ > > > - ds_clear(&match); > > > - ds_clear(&actions); > > > - build_acl_log(&actions, acl); > > > - if (extra_match->length > 0) { > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > - } > > > - ds_put_format(&match, "ip4 && (%s)", acl->match); > > > - if (extra_actions->length > 0) { > > > - ds_put_format(&actions, "%s ", extra_actions->string); > > > - } > > > - ds_put_format(&actions, "reg0 = 0; " > > > - "icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; " > > > - "outport <-> inport; %s };", > > > - ingress ? "next(pipeline=egress,table=5);" > > > - : "next(pipeline=ingress,table=20);"); > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > - acl->priority + OVN_ACL_PRI_OFFSET, > > > - ds_cstr(&match), ds_cstr(&actions), > > stage_hint); > > > - ds_clear(&match); > > > - ds_clear(&actions); > > > - build_acl_log(&actions, acl); > > > - if (extra_match->length > 0) { > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > - } > > > - ds_put_format(&match, "ip6 && (%s)", acl->match); > > > - if (extra_actions->length > 0) { > > > - ds_put_format(&actions, "%s ", extra_actions->string); > > > - } > > > - ds_put_format(&actions, "reg0 = 0; icmp6 { " > > > - "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > > - "outport <-> inport; %s };", > > > - ingress ? "next(pipeline=egress,table=5);" > > > - : "next(pipeline=ingress,table=20);"); > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > - acl->priority + OVN_ACL_PRI_OFFSET, > > > - ds_cstr(&match), ds_cstr(&actions), > > stage_hint); > > > + if (is_ip4) { > > > + if (tcp_reset) { > > > + build_acl_log(&actions, acl); > > > + if (extra_match->length > 0) { > > > + ds_put_format(&match, "(%s) && ", extra_match->string); > > > + } > > > + ds_put_format(&match, "ip4 && tcp && (%s)", acl->match); > > > + if (extra_actions->length > 0) { > > > + ds_put_format(&actions, "%s ", extra_actions->string); > > > + } > > > + ds_put_format(&actions, "reg0 = 0; " > > > + "eth.dst <-> eth.src; ip4.dst <-> ip4.src; " > > > + "tcp_reset { outport <-> inport; %s };", > > > + ingress ? "next(pipeline=egress,table=5);" > > > + : "next(pipeline=ingress,table=20);"); > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > + acl->priority + OVN_ACL_PRI_OFFSET + > > 10, > > > + ds_cstr(&match), ds_cstr(&actions), > > > + stage_hint); > > > + } > > > + > > > + if (icmp_reset) { > > > + ds_clear(&match); > > > + ds_clear(&actions); > > > + build_acl_log(&actions, acl); > > > + if (extra_match->length > 0) { > > > + ds_put_format(&match, "(%s) && ", extra_match->string); > > > + } > > > + ds_put_format(&match, "ip4 && (%s)", acl->match); > > > + if (is_udp) { > > > + ds_put_cstr(&match, " && udp"); > > > + } > > > + if (extra_actions->length > 0) { > > > + ds_put_format(&actions, "%s ", extra_actions->string); > > > + } > > > + ds_put_format(&actions, "reg0 = 0; " > > > + "icmp4 { eth.dst <-> eth.src; ip4.dst <-> > > ip4.src; " > > > + "outport <-> inport; %s };", > > > + ingress ? "next(pipeline=egress,table=5);" > > > + : "next(pipeline=ingress,table=20);"); > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > + acl->priority + OVN_ACL_PRI_OFFSET, > > > + ds_cstr(&match), ds_cstr(&actions), > > > + stage_hint); > > > + } > > > + } > > > + > > > + if (is_ip6) { > > > + if (tcp_reset) { > > > + ds_clear(&match); > > > + ds_clear(&actions); > > > + build_acl_log(&actions, acl); > > > + if (extra_match->length > 0) { > > > + ds_put_format(&match, "(%s) && ", extra_match->string); > > > + } > > > + ds_put_format(&match, "ip6 && tcp && (%s)", acl->match); > > > + if (extra_actions->length > 0) { > > > + ds_put_format(&actions, "%s ", extra_actions->string); > > > + } > > > + ds_put_format(&actions, "reg0 = 0; " > > > + "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > > + "tcp_reset { outport <-> inport; %s };", > > > + ingress ? "next(pipeline=egress,table=5);" > > > + : "next(pipeline=ingress,table=20);"); > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > + acl->priority + OVN_ACL_PRI_OFFSET + > > 10, > > > + ds_cstr(&match), ds_cstr(&actions), > > > + stage_hint); > > > + } > > > + > > > + if (icmp_reset) { > > > + ds_clear(&match); > > > + ds_clear(&actions); > > > + build_acl_log(&actions, acl); > > > + if (extra_match->length > 0) { > > > + ds_put_format(&match, "(%s) && ", extra_match->string); > > > + } > > > + ds_put_format(&match, "ip6 && (%s)", acl->match); > > > + if (is_udp) { > > > + ds_put_cstr(&match, " && udp"); > > > + } > > > + > > > + if (extra_actions->length > 0) { > > > + ds_put_format(&actions, "%s ", extra_actions->string); > > > + } > > > + ds_put_format(&actions, "reg0 = 0; icmp6 { " > > > + "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > > + "outport <-> inport; %s };", > > > + ingress ? "next(pipeline=egress,table=5);" > > > + : "next(pipeline=ingress,table=20);"); > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > + acl->priority + OVN_ACL_PRI_OFFSET, > > > + ds_cstr(&match), ds_cstr(&actions), > > > + stage_hint); > > > + } > > > + } > > > > > > ds_destroy(&match); > > > ds_destroy(&actions); > > > diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema > > > index 092322ab2c..00f1c7cd4b 100644 > > > --- a/ovn-nb.ovsschema > > > +++ b/ovn-nb.ovsschema > > > @@ -1,7 +1,7 @@ > > > { > > > "name": "OVN_Northbound", > > > - "version": "5.27.0", > > > - "cksum": "3507518247 26773", > > > + "version": "5.28.0", > > > + "cksum": "699859908 26928", > > > "tables": { > > > "NB_Global": { > > > "columns": { > > > @@ -225,6 +225,9 @@ > > > "debug"]]}, > > > "min": 0, "max": 1}}, > > > "meter": {"type": {"key": "string", "min": 0, "max": 1}}, > > > + "options": { > > > + "type": {"key": "string", "value": "string", > > > + "min": 0, "max": "unlimited"}}, > > > "external_ids": { > > > "type": {"key": "string", "value": "string", > > > "min": 0, "max": "unlimited"}}}, > > > diff --git a/ovn-nb.xml b/ovn-nb.xml > > > index 86195af341..2c3497e2ae 100644 > > > --- a/ovn-nb.xml > > > +++ b/ovn-nb.xml > > > @@ -1721,6 +1721,49 @@ > > > </ul> > > > </column> > > > > > > + <group title="Common options"> > > > + <column name="options"> > > > + This column provides general key/value settings. The supported > > > + options are described individually below. > > > + </column> > > > + > > > + <group title="Options for providing protocol hints for reject > > ACL."> > > > + <p> > > > + The ACL match specified in the > > > + <ref column="match" table="ACL" db="OVN_Northbound"/> column is > > > + opaque to <code>OVN</code> and <code>ovn-northd</code> doesn't > > > + look into the match fields. > > > + These options can be specified by CMS to provide hints to > > > + <code>OVN</code> about the L3 and L4 protocol matches for the > > reject > > > + ACL. <code>ovn-northd</code> uses these options if set to use > > > + appropriate actions when generating logical flows. > > > + </p> > > > + > > > + <p> > > > + If these options are not set, then <code>ovn-northd</code> > > assumes > > > + the reject ACL applies to IPv4, IPv6 and TCP packets. > > > + </p> > > > + > > > + <column name="options" key="l3-protocol"> > > > + The possible values are <code>ip</code>, <code>ip4</code> and > > > + <code>ip6</code>. If the value is <code>ip</code>, it means the > > > + reject ACL action applies to both IPv4 and IPv6 packets. If the > > > + value is <code>ip4</code>, it means the reject ACL action > > applies to > > > + IPv4 packets and the value <code>ip6</code> applies to IPv6 > > packets. > > > + </column> > > > + > > > + <column name="options" key="l4-protocol"> > > > + <p> > > > + The possible values are <code>tcp</code> and > > <code>udp</code>. > > > + If the value is <code>tcp</code>, it means the > > > + reject ACL action applies to TCP packets. If the > > > + value is <code>udp</code>, it means the reject ACL action > > applies > > > + to UDP packets. > > > + </p> > > > + </column> > > > + </group> > > > + </group> > > > + > > > <group title="Logging"> > > > <p> > > > These columns control whether and how OVN logs packets that > > match an > > > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at > > > index 99a9204f1f..4a30f8ed07 100644 > > > --- a/tests/ovn-northd.at > > > +++ b/tests/ovn-northd.at > > > @@ -2010,3 +2010,288 @@ ovn-nbctl --wait=sb set NB_Global . > > options:ignore_lsp_down=true > > > AT_CHECK([ovn-sbctl lflow-list | grep arp | grep 10\.0\.0\.1], [0], > > [ignore]) > > > > > > AT_CLEANUP > > > + > > > +AT_SETUP([ovn-northd -- ACL reject flows]) > > > +ovn_start > > > + > > > +ovn-nbctl ls-add sw0 > > > +ovn-nbctl lsp-add sw0 sw0-p1 > > > +ovn-nbctl lsp-add sw0 sw0-p2 > > > + > > > +ovn-nbctl pg-add pg0 sw0-p1 sw0-p2 > > > +ovn-nbctl acl-add pg0 to-lport 1002 "inport == @pg0 && ip" reject > > > + > > > +ovn-nbctl --wait=sb sync > > > + > > > +# If there is a reject ACL wihtout any protocol hints, then ovn-northd > > should > > > +# generate lflows with ip4 tcp_reset, icmp4, ip6 tcp_reset and icmp6 > > actions. > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +# Set l3-protocol=ip4 for the reject ACL. > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip4 > > > + > > > +# ovn-northd should generate 2 lflows with ip4 tcp_reset and icmp4 > > actions. > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +# Set l4-protocol=tcp for the reject ACL. > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > > + > > > +# ovn-northd should generate 1 lflow with ip4 tcp_reset action. > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > sort], [0], [dnl > > > +]) > > > + > > > +# Set l4-protocol=udp for the reject ACL. > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > > + > > > +# ovn-northd should generate 1 lflow with udp match and icmp4 action. > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > sort], [0], [dnl > > > +]) > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=(ip4 && (inport == @pg0 && ip) && udp), dnl > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +# Remove l4-protocol from the reject ACL. > > > +ovn-nbctl --wait=sb remove ACL . options l4-protocol > > > + > > > +# ovn-northd should generate 2 lflow with tcp_reset and icmp4 action. > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +# Set l3-protocol to ip. > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > > + > > > +# ovn-northd should generate 4 lflow with ip4 tcp_reset, ip6 tcp_reset, > > icmp4 and icmp6 actions. > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +# Set l3-protocol=ip6 for the reject ACL. > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip6 > > > + > > > +# ovn-northd should generate 2 lflows with ip6 tcp_reset and icmp6 > > actions. > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +# Set l4-protocol=tcp for the reject ACL. > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > > + > > > +# ovn-northd should generate 1 lflow with ip6 tcp_reset action. > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > sort], [0], [dnl > > > +]) > > > + > > > +# Set l4-protocol=udp for the reject ACL. > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > > + > > > +# ovn-northd should generate 1 lflow with udp match and icmp6 action. > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > sort], [0], [dnl > > > +]) > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=(ip6 && (inport == @pg0 && ip) && udp), dnl > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL. > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > > + > > > +# ovn-northd should generate 2 lflow with ip4 tcp_reset and ip6 > > tcp_reset actions. > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > sort], [0], [dnl > > > +]) > > > + > > > +# Set l3-protocol to ip and l4-protocol=udp for the reject ACL. > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > > + > > > +# ovn-northd should generate 2 lflows (udp match) with icmp4 and icmp6 > > actions. > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > sort], [0], [dnl > > > +]) > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=(ip4 && (inport == @pg0 && ip) && udp), dnl > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=(ip6 && (inport == @pg0 && ip) && udp), dnl > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +# Add an ACL with allow-related > > > +ovn-nbctl --wait=sb acl-add pg0 to-lport 1000 "ip" allow-related > > > + > > > +# ovn-northd should generate 4 lflow with 2 icmp4 and 2 icmp6 actions. > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > sort], [0], [dnl > > > +]) > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl\ > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp4 { eth.dst > > <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; > > next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp6 { eth.dst > > <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; > > next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL. > > > +rej_acl=$(ovn-nbctl --bare --columns _uuid find ACL action=reject) > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l3-protocol=ip > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp > > > + > > > +# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and 2 ip6 > > tcp_reset actions. > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > > eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; > > next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > > eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; > > next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > sort], [0], [dnl > > > +]) > > > + > > > + > > > +# Clear l3-protocol and set l4-protocol to udp > > > +ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=udp > > > + > > > +# ovn-northd should generate 4 lflows (with udp match) with 2 icmp4 and > > 2 icmp6 actions. > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > sort], [0], [dnl > > > +]) > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl\ > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp4 { eth.dst > > <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; > > next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp6 { eth.dst > > <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; > > next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > +match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +# Clear l3-protocol and set l4-protocol to tcp > > > +ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp > > > + > > > +# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and 2 ip6 > > tcp_reset actions. > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > sort], [0], [dnl > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > > eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; > > next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > > eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; > > next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > +match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > +]) > > > + > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > sort], [0], [dnl > > > +]) > > > + > > > +AT_CLEANUP > > > -- > > > 2.26.2 > > > > > > _______________________________________________ > > > dev mailing list > > > dev@openvswitch.org > > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > _______________________________________________ > > dev mailing list > > dev@openvswitch.org > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > >
On Mon, Sep 28, 2020 at 2:21 AM Numan Siddique <numans@ovn.org> wrote: > > On Mon, Sep 28, 2020 at 2:14 PM Numan Siddique <numans@ovn.org> wrote: > > > > On Mon, Sep 28, 2020 at 5:57 AM Han Zhou <hzhou@ovn.org> wrote: > > > > > > Thanks Numan. I have some comments on the solution. > > > > > > On Thu, Sep 24, 2020 at 9:50 AM <numans@ovn.org> wrote: > > > > > > > > From: Numan Siddique <numans@ovn.org> > > > > > > > > ovn-northd adds below lflows for a reject ACL with a match - M > > > > > > > > match = (ip4 && tcp && 'M') action = tcp_reject{} > > > > match = (ip6 && tcp && 'M') action = tcp_reject{} > > > > match = (ip4 && 'M') action = icmp4{} > > > > match = (ip6 && 'M') action = icmp6{} > > > > > > > > This approach has a couple of problems: > > > > - ovn-controller can reject the lflows if there are invalid matches. > > > > Eg. If match 'M' is - 'ip4 && udp'. > > > > > > > > - In a large scale deployment, this could result in lot of invalid > > > > logical flows and increase the size of the SB DB. > > > > > > > > This patch addresses this problem by providing an option to the CMS > > > > to specify the l3 protocol and l4 protocol as hints. A new column > > > > 'options' is added to the ACL table with the options - > > > > options:l3-protocol and options:l4-protocol. > > > > > > > > ovn-northd will now generate only the required lflows for the reject > > > > ACL. If no options are set, then it falls back to the default scenario. > > > > > > > > > > Thanks Numan. I believe the solution should work. However, it seems a > > > little confusing for the end user about how to use the hint field. I think > > > maybe we should try to avoid the extra field if possible. Here is my > > > proposal: > > > > > > > Thanks Han for the comments. I do agree if we can avoid the extra option. > > > > > 1. For the tcp v.s. udp check, since we don't want northd to parse the > > > match condition, we will have to rely on users input. However, instead of a > > > hint, I think it is better to let the user explicitly specify in the action > > > field. E.g. "reject" means sending icmp, and "tcp_reject" means sending tcp > > > reset if the traffic is tcp and otherwise sending icmp. So, if the user > > > adds an ACL with match include "udp", they will naturally use "reject" > > > instead of "tcp_reject" because they know it is not possible for a TCP > > > packet to hit this ACL. If they add an ACL that tcp traffic is expected to > > > match (either TCP only, or general IP traffic), they can use "tcp_reject". > > > Would this be more straightforward than an extra "hint" field? > > > > > > > I have few comments here. > > - If we consider "reject" = "icmp", then we will be breaking the > > backward compatibility. > > Right now, for a reject action, ovn-northd would send tcp_reset > > for tcp traffic and icmp reply or other traffic. > > After your proposed approach, the behaviour would change ? Is > > that OK ? Because existing test cases would fail. > > The proposed patch handles the backward compatibility. Although > > I'm not sure if it is really required in this case. > > > > - For a tcp_reject action, if the match has "tcp", then we will end > > up adding a logical flow with the icmp action, which is > > really not required. Or do you mean, pinctrl would take the > > decision while handling the "tcp_reject" action to either > > send tcp reset packet or icmp packet ? If so, we can probably just > > have one action - "reject". Please see below. > > > > > 2. For ip4 v.s. ip6, the idea is to support generic ovn logical flow > > > actions "tcp_reject" and "icmp" in ovn-controller, which can handle both > > > ipv4 and ipv6. If this can be supported, the logical flows only needs to be: > > > match = (tcp && 'M') action = tcp_reject{} > > > match = ('M') action = icmp{} > > > > > > > Ok. In this case we cannot support inner actions unless they are > > independent of the ip version. > > i.e we can't support - tcp_reject { eth.dst <-> eth.src; ip4.dst <-> > > ip4.src; } or > > tcp_reject {eth.dst <-> eth.src; ip6.dst <-> ip6.src;} in one logical > > flow. ovn-northd has to generate > > 2 logical flows. > > - ip4 && 'M', action = tcp_reject { eth.dst <-> eth.src; ip4.dst <-> > > ip4.src; } > > - ip6 && 'M', action = tcp_reject { eth.dst <-> eth.src; ip6.dst <-> > > ip6.src; } > > > > > > Right now for one reject ACL we add the below lflows > > - ip4 && tcp && 'M', action = tcp_reset { eth.dst <-> eth.src; > > ip4.dst <-> ip4.src; outport <-> inport;} > > - ip6 && tcp && 'M', action = tcp_reset { eth.dst <-> eth.src; > > ip6.dst <-> ip6.src; outport <-> inport;} > > - ip4 && 'M' , action = icmp4 {eth.dst <-> eth.src; > > ip4.dst <-> ip4.src; outport <-> inport;} > > - ip6 && 'M' , action = icmp6 {eth.dst <-> eth.src; > > ip6.dst <-> ip6.src; outport <-> inport;} > > > > I have another idea based on your suggestions here: How about we have > > a new action - reject{} which will be used > > for all reject ACLs and this will > > - send tcp reset packet if the packet is tcp (pinctrl would take > > the decision) > > - send icmp packet otherwise. > > > > We can add the logical flow for a reject ACL in 2 ways > > > > 1. match = M, action = reject { eth.dst <-> eth.src, outport <-> inport;} > > > > OR > > > > 2. match = M, action = reject { eth.dst <-> eth.src, ip.src <-> > > ip.dst; outport <-> inport;} > > > > In (1), pinctrl while handling the reject action, will swap the ip src > > with ip dst (i.e ip4.dst <-> ip4.src or ip6.dst <-> ip6.src }. > > > > In (2), we will add 2 new OVN fields "ip.src" and "ip.dst" (just like > > we have icmp4.frag_mtu now) and the action - ip.src <-> ip.dst > > will result in another controller action which will swap the ip src > > and ip dst fields (just like how "icmp4.frag_mtu = 1400" would result > > into a controller action). > > > > Even though (1) will work, it's not transparent. I would personally > > prefer (2) and I think it's ok if the reject ACL would result in 2 OF > > controller actions. > > > > With this we will have just one logical flow (instead of 4 ) and there > > will be no changes on the CMS side. > > Yes, this would be even better. > > What do you think ? > > > > Thanks > > Numan > > > > > > > I haven't thought through all the details but it seems doable. Did you have > > > any thoughts on this? (If it proves to be unreasonable I am ok with current > > > "hint" approach) > > > > > > In addition, I found the existing TCP reject handling has a bug which > > > messes up the user defined ACL priorities. I just posted a patch: > > > https://patchwork.ozlabs.org/project/ovn/patch/20200928000904.858685-1-hzhou@ovn.org/ > > > It is not directly related to this patch but it would be great if you could > > > take a look. > > Sure. > With only one lflow, my above fix is not needed. (I am not sure about backporting to old branches.) > Thanks > Numan > > > > > > > Thanks, > > > Han > > > > > > > > > > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1876990 > > > > Reported-by: Ilya Maximets <i.maximets@ovn.org> > > > > Signed-off-by: Numan Siddique <numans@ovn.org> > > > > --- > > > > northd/ovn-northd.c | 194 ++++++++++++++++++++---------- > > > > ovn-nb.ovsschema | 7 +- > > > > ovn-nb.xml | 43 +++++++ > > > > tests/ovn-northd.at | 285 ++++++++++++++++++++++++++++++++++++++++++++ > > > > 4 files changed, 461 insertions(+), 68 deletions(-) > > > > > > > > diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c > > > > index 3324c9e81d..d167137e07 100644 > > > > --- a/northd/ovn-northd.c > > > > +++ b/northd/ovn-northd.c > > > > @@ -5372,73 +5372,135 @@ build_reject_acl_rules(struct ovn_datapath *od, > > > struct hmap *lflows, > > > > struct ds actions = DS_EMPTY_INITIALIZER; > > > > bool ingress = (stage == S_SWITCH_IN_ACL); > > > > > > > > - /* TCP */ > > > > - build_acl_log(&actions, acl); > > > > - if (extra_match->length > 0) { > > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > > - } > > > > - ds_put_format(&match, "ip4 && tcp && (%s)", acl->match); > > > > - ds_put_format(&actions, "reg0 = 0; " > > > > - "eth.dst <-> eth.src; ip4.dst <-> ip4.src; " > > > > - "tcp_reset { outport <-> inport; %s };", > > > > - ingress ? "next(pipeline=egress,table=5);" > > > > - : "next(pipeline=ingress,table=20);"); > > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > > - acl->priority + OVN_ACL_PRI_OFFSET + 10, > > > > - ds_cstr(&match), ds_cstr(&actions), > > > stage_hint); > > > > - ds_clear(&match); > > > > - ds_clear(&actions); > > > > - build_acl_log(&actions, acl); > > > > - if (extra_match->length > 0) { > > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > > - } > > > > - ds_put_format(&match, "ip6 && tcp && (%s)", acl->match); > > > > - ds_put_format(&actions, "reg0 = 0; " > > > > - "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > > > - "tcp_reset { outport <-> inport; %s };", > > > > - ingress ? "next(pipeline=egress,table=5);" > > > > - : "next(pipeline=ingress,table=20);"); > > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > > - acl->priority + OVN_ACL_PRI_OFFSET + 10, > > > > - ds_cstr(&match), ds_cstr(&actions), > > > stage_hint); > > > > + bool is_ip4 = true; > > > > + bool is_ip6 = true; > > > > + bool tcp_reset = true; > > > > + bool icmp_reset = true; > > > > + bool is_udp = false; > > > > + > > > > + const char *l3_protocol = smap_get(&acl->options, "l3-protocol"); > > > > + if (l3_protocol) { > > > > + if (!strcasecmp(l3_protocol, "ip")) { > > > > + is_ip4 = true; > > > > + is_ip6 = true; > > > > + } else if (!strcasecmp(l3_protocol, "ip4")) { > > > > + is_ip4 = true; > > > > + is_ip6 = false; > > > > + } else if (!strcasecmp(l3_protocol, "ip6")) { > > > > + is_ip6 = true; > > > > + is_ip4 = false; > > > > + } > > > > + } > > > > + > > > > + const char *l4_protocol = smap_get(&acl->options, "l4-protocol"); > > > > + if (l4_protocol) { > > > > + if (!strcasecmp(l4_protocol, "tcp")) { > > > > + tcp_reset = true; > > > > + icmp_reset = false; > > > > + } else if (!strcasecmp(l4_protocol, "udp")) { > > > > + tcp_reset = false; > > > > + is_udp = true; > > > > + } else { > > > > + tcp_reset = false; > > > > + } > > > > + } > > > > > > > > - /* IP traffic */ > > > > - ds_clear(&match); > > > > - ds_clear(&actions); > > > > - build_acl_log(&actions, acl); > > > > - if (extra_match->length > 0) { > > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > > - } > > > > - ds_put_format(&match, "ip4 && (%s)", acl->match); > > > > - if (extra_actions->length > 0) { > > > > - ds_put_format(&actions, "%s ", extra_actions->string); > > > > - } > > > > - ds_put_format(&actions, "reg0 = 0; " > > > > - "icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; " > > > > - "outport <-> inport; %s };", > > > > - ingress ? "next(pipeline=egress,table=5);" > > > > - : "next(pipeline=ingress,table=20);"); > > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > > - acl->priority + OVN_ACL_PRI_OFFSET, > > > > - ds_cstr(&match), ds_cstr(&actions), > > > stage_hint); > > > > - ds_clear(&match); > > > > - ds_clear(&actions); > > > > - build_acl_log(&actions, acl); > > > > - if (extra_match->length > 0) { > > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > > - } > > > > - ds_put_format(&match, "ip6 && (%s)", acl->match); > > > > - if (extra_actions->length > 0) { > > > > - ds_put_format(&actions, "%s ", extra_actions->string); > > > > - } > > > > - ds_put_format(&actions, "reg0 = 0; icmp6 { " > > > > - "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > > > - "outport <-> inport; %s };", > > > > - ingress ? "next(pipeline=egress,table=5);" > > > > - : "next(pipeline=ingress,table=20);"); > > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > > - acl->priority + OVN_ACL_PRI_OFFSET, > > > > - ds_cstr(&match), ds_cstr(&actions), > > > stage_hint); > > > > + if (is_ip4) { > > > > + if (tcp_reset) { > > > > + build_acl_log(&actions, acl); > > > > + if (extra_match->length > 0) { > > > > + ds_put_format(&match, "(%s) && ", extra_match->string); > > > > + } > > > > + ds_put_format(&match, "ip4 && tcp && (%s)", acl->match); > > > > + if (extra_actions->length > 0) { > > > > + ds_put_format(&actions, "%s ", extra_actions->string); > > > > + } > > > > + ds_put_format(&actions, "reg0 = 0; " > > > > + "eth.dst <-> eth.src; ip4.dst <-> ip4.src; " > > > > + "tcp_reset { outport <-> inport; %s };", > > > > + ingress ? "next(pipeline=egress,table=5);" > > > > + : "next(pipeline=ingress,table=20);"); > > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > > + acl->priority + OVN_ACL_PRI_OFFSET + > > > 10, > > > > + ds_cstr(&match), ds_cstr(&actions), > > > > + stage_hint); > > > > + } > > > > + > > > > + if (icmp_reset) { > > > > + ds_clear(&match); > > > > + ds_clear(&actions); > > > > + build_acl_log(&actions, acl); > > > > + if (extra_match->length > 0) { > > > > + ds_put_format(&match, "(%s) && ", extra_match->string); > > > > + } > > > > + ds_put_format(&match, "ip4 && (%s)", acl->match); > > > > + if (is_udp) { > > > > + ds_put_cstr(&match, " && udp"); > > > > + } > > > > + if (extra_actions->length > 0) { > > > > + ds_put_format(&actions, "%s ", extra_actions->string); > > > > + } > > > > + ds_put_format(&actions, "reg0 = 0; " > > > > + "icmp4 { eth.dst <-> eth.src; ip4.dst <-> > > > ip4.src; " > > > > + "outport <-> inport; %s };", > > > > + ingress ? "next(pipeline=egress,table=5);" > > > > + : "next(pipeline=ingress,table=20);"); > > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > > + acl->priority + OVN_ACL_PRI_OFFSET, > > > > + ds_cstr(&match), ds_cstr(&actions), > > > > + stage_hint); > > > > + } > > > > + } > > > > + > > > > + if (is_ip6) { > > > > + if (tcp_reset) { > > > > + ds_clear(&match); > > > > + ds_clear(&actions); > > > > + build_acl_log(&actions, acl); > > > > + if (extra_match->length > 0) { > > > > + ds_put_format(&match, "(%s) && ", extra_match->string); > > > > + } > > > > + ds_put_format(&match, "ip6 && tcp && (%s)", acl->match); > > > > + if (extra_actions->length > 0) { > > > > + ds_put_format(&actions, "%s ", extra_actions->string); > > > > + } > > > > + ds_put_format(&actions, "reg0 = 0; " > > > > + "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > > > + "tcp_reset { outport <-> inport; %s };", > > > > + ingress ? "next(pipeline=egress,table=5);" > > > > + : "next(pipeline=ingress,table=20);"); > > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > > + acl->priority + OVN_ACL_PRI_OFFSET + > > > 10, > > > > + ds_cstr(&match), ds_cstr(&actions), > > > > + stage_hint); > > > > + } > > > > + > > > > + if (icmp_reset) { > > > > + ds_clear(&match); > > > > + ds_clear(&actions); > > > > + build_acl_log(&actions, acl); > > > > + if (extra_match->length > 0) { > > > > + ds_put_format(&match, "(%s) && ", extra_match->string); > > > > + } > > > > + ds_put_format(&match, "ip6 && (%s)", acl->match); > > > > + if (is_udp) { > > > > + ds_put_cstr(&match, " && udp"); > > > > + } > > > > + > > > > + if (extra_actions->length > 0) { > > > > + ds_put_format(&actions, "%s ", extra_actions->string); > > > > + } > > > > + ds_put_format(&actions, "reg0 = 0; icmp6 { " > > > > + "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > > > + "outport <-> inport; %s };", > > > > + ingress ? "next(pipeline=egress,table=5);" > > > > + : "next(pipeline=ingress,table=20);"); > > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > > + acl->priority + OVN_ACL_PRI_OFFSET, > > > > + ds_cstr(&match), ds_cstr(&actions), > > > > + stage_hint); > > > > + } > > > > + } > > > > > > > > ds_destroy(&match); > > > > ds_destroy(&actions); > > > > diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema > > > > index 092322ab2c..00f1c7cd4b 100644 > > > > --- a/ovn-nb.ovsschema > > > > +++ b/ovn-nb.ovsschema > > > > @@ -1,7 +1,7 @@ > > > > { > > > > "name": "OVN_Northbound", > > > > - "version": "5.27.0", > > > > - "cksum": "3507518247 26773", > > > > + "version": "5.28.0", > > > > + "cksum": "699859908 26928", > > > > "tables": { > > > > "NB_Global": { > > > > "columns": { > > > > @@ -225,6 +225,9 @@ > > > > "debug"]]}, > > > > "min": 0, "max": 1}}, > > > > "meter": {"type": {"key": "string", "min": 0, "max": 1}}, > > > > + "options": { > > > > + "type": {"key": "string", "value": "string", > > > > + "min": 0, "max": "unlimited"}}, > > > > "external_ids": { > > > > "type": {"key": "string", "value": "string", > > > > "min": 0, "max": "unlimited"}}}, > > > > diff --git a/ovn-nb.xml b/ovn-nb.xml > > > > index 86195af341..2c3497e2ae 100644 > > > > --- a/ovn-nb.xml > > > > +++ b/ovn-nb.xml > > > > @@ -1721,6 +1721,49 @@ > > > > </ul> > > > > </column> > > > > > > > > + <group title="Common options"> > > > > + <column name="options"> > > > > + This column provides general key/value settings. The supported > > > > + options are described individually below. > > > > + </column> > > > > + > > > > + <group title="Options for providing protocol hints for reject > > > ACL."> > > > > + <p> > > > > + The ACL match specified in the > > > > + <ref column="match" table="ACL" db="OVN_Northbound"/> column is > > > > + opaque to <code>OVN</code> and <code>ovn-northd</code> doesn't > > > > + look into the match fields. > > > > + These options can be specified by CMS to provide hints to > > > > + <code>OVN</code> about the L3 and L4 protocol matches for the > > > reject > > > > + ACL. <code>ovn-northd</code> uses these options if set to use > > > > + appropriate actions when generating logical flows. > > > > + </p> > > > > + > > > > + <p> > > > > + If these options are not set, then <code>ovn-northd</code> > > > assumes > > > > + the reject ACL applies to IPv4, IPv6 and TCP packets. > > > > + </p> > > > > + > > > > + <column name="options" key="l3-protocol"> > > > > + The possible values are <code>ip</code>, <code>ip4</code> and > > > > + <code>ip6</code>. If the value is <code>ip</code>, it means the > > > > + reject ACL action applies to both IPv4 and IPv6 packets. If the > > > > + value is <code>ip4</code>, it means the reject ACL action > > > applies to > > > > + IPv4 packets and the value <code>ip6</code> applies to IPv6 > > > packets. > > > > + </column> > > > > + > > > > + <column name="options" key="l4-protocol"> > > > > + <p> > > > > + The possible values are <code>tcp</code> and > > > <code>udp</code>. > > > > + If the value is <code>tcp</code>, it means the > > > > + reject ACL action applies to TCP packets. If the > > > > + value is <code>udp</code>, it means the reject ACL action > > > applies > > > > + to UDP packets. > > > > + </p> > > > > + </column> > > > > + </group> > > > > + </group> > > > > + > > > > <group title="Logging"> > > > > <p> > > > > These columns control whether and how OVN logs packets that > > > match an > > > > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at > > > > index 99a9204f1f..4a30f8ed07 100644 > > > > --- a/tests/ovn-northd.at > > > > +++ b/tests/ovn-northd.at > > > > @@ -2010,3 +2010,288 @@ ovn-nbctl --wait=sb set NB_Global . > > > options:ignore_lsp_down=true > > > > AT_CHECK([ovn-sbctl lflow-list | grep arp | grep 10\.0\.0\.1], [0], > > > [ignore]) > > > > > > > > AT_CLEANUP > > > > + > > > > +AT_SETUP([ovn-northd -- ACL reject flows]) > > > > +ovn_start > > > > + > > > > +ovn-nbctl ls-add sw0 > > > > +ovn-nbctl lsp-add sw0 sw0-p1 > > > > +ovn-nbctl lsp-add sw0 sw0-p2 > > > > + > > > > +ovn-nbctl pg-add pg0 sw0-p1 sw0-p2 > > > > +ovn-nbctl acl-add pg0 to-lport 1002 "inport == @pg0 && ip" reject > > > > + > > > > +ovn-nbctl --wait=sb sync > > > > + > > > > +# If there is a reject ACL wihtout any protocol hints, then ovn-northd > > > should > > > > +# generate lflows with ip4 tcp_reset, icmp4, ip6 tcp_reset and icmp6 > > > actions. > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +# Set l3-protocol=ip4 for the reject ACL. > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip4 > > > > + > > > > +# ovn-northd should generate 2 lflows with ip4 tcp_reset and icmp4 > > > actions. > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +# Set l4-protocol=tcp for the reject ACL. > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > > > + > > > > +# ovn-northd should generate 1 lflow with ip4 tcp_reset action. > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > sort], [0], [dnl > > > > +]) > > > > + > > > > +# Set l4-protocol=udp for the reject ACL. > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > > > + > > > > +# ovn-northd should generate 1 lflow with udp match and icmp4 action. > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > sort], [0], [dnl > > > > +]) > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=(ip4 && (inport == @pg0 && ip) && udp), dnl > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +# Remove l4-protocol from the reject ACL. > > > > +ovn-nbctl --wait=sb remove ACL . options l4-protocol > > > > + > > > > +# ovn-northd should generate 2 lflow with tcp_reset and icmp4 action. > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +# Set l3-protocol to ip. > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > > > + > > > > +# ovn-northd should generate 4 lflow with ip4 tcp_reset, ip6 tcp_reset, > > > icmp4 and icmp6 actions. > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +# Set l3-protocol=ip6 for the reject ACL. > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip6 > > > > + > > > > +# ovn-northd should generate 2 lflows with ip6 tcp_reset and icmp6 > > > actions. > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +# Set l4-protocol=tcp for the reject ACL. > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > > > + > > > > +# ovn-northd should generate 1 lflow with ip6 tcp_reset action. > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > sort], [0], [dnl > > > > +]) > > > > + > > > > +# Set l4-protocol=udp for the reject ACL. > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > > > + > > > > +# ovn-northd should generate 1 lflow with udp match and icmp6 action. > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > sort], [0], [dnl > > > > +]) > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=(ip6 && (inport == @pg0 && ip) && udp), dnl > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL. > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > > > + > > > > +# ovn-northd should generate 2 lflow with ip4 tcp_reset and ip6 > > > tcp_reset actions. > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > sort], [0], [dnl > > > > +]) > > > > + > > > > +# Set l3-protocol to ip and l4-protocol=udp for the reject ACL. > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > > > + > > > > +# ovn-northd should generate 2 lflows (udp match) with icmp4 and icmp6 > > > actions. > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > sort], [0], [dnl > > > > +]) > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=(ip4 && (inport == @pg0 && ip) && udp), dnl > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=(ip6 && (inport == @pg0 && ip) && udp), dnl > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +# Add an ACL with allow-related > > > > +ovn-nbctl --wait=sb acl-add pg0 to-lport 1000 "ip" allow-related > > > > + > > > > +# ovn-northd should generate 4 lflow with 2 icmp4 and 2 icmp6 actions. > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > sort], [0], [dnl > > > > +]) > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl\ > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp4 { eth.dst > > > <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; > > > next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp6 { eth.dst > > > <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; > > > next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL. > > > > +rej_acl=$(ovn-nbctl --bare --columns _uuid find ACL action=reject) > > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l3-protocol=ip > > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp > > > > + > > > > +# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and 2 ip6 > > > tcp_reset actions. > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > > > eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; > > > next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > > > eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; > > > next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > sort], [0], [dnl > > > > +]) > > > > + > > > > + > > > > +# Clear l3-protocol and set l4-protocol to udp > > > > +ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol > > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=udp > > > > + > > > > +# ovn-northd should generate 4 lflows (with udp match) with 2 icmp4 and > > > 2 icmp6 actions. > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > sort], [0], [dnl > > > > +]) > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl\ > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp4 { eth.dst > > > <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; > > > next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp6 { eth.dst > > > <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; > > > next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > +match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +# Clear l3-protocol and set l4-protocol to tcp > > > > +ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol > > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp > > > > + > > > > +# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and 2 ip6 > > > tcp_reset actions. > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > sort], [0], [dnl > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > > > eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; > > > next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > > > eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; > > > next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > +match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > +]) > > > > + > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > sort], [0], [dnl > > > > +]) > > > > + > > > > +AT_CLEANUP > > > > -- > > > > 2.26.2 > > > > > > > > _______________________________________________ > > > > dev mailing list > > > > dev@openvswitch.org > > > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > > _______________________________________________ > > > dev mailing list > > > dev@openvswitch.org > > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > >
On Mon, Sep 28, 2020 at 9:41 PM Han Zhou <hzhou@ovn.org> wrote: > > On Mon, Sep 28, 2020 at 2:21 AM Numan Siddique <numans@ovn.org> wrote: > > > > On Mon, Sep 28, 2020 at 2:14 PM Numan Siddique <numans@ovn.org> wrote: > > > > > > On Mon, Sep 28, 2020 at 5:57 AM Han Zhou <hzhou@ovn.org> wrote: > > > > > > > > Thanks Numan. I have some comments on the solution. > > > > > > > > On Thu, Sep 24, 2020 at 9:50 AM <numans@ovn.org> wrote: > > > > > > > > > > From: Numan Siddique <numans@ovn.org> > > > > > > > > > > ovn-northd adds below lflows for a reject ACL with a match - M > > > > > > > > > > match = (ip4 && tcp && 'M') action = tcp_reject{} > > > > > match = (ip6 && tcp && 'M') action = tcp_reject{} > > > > > match = (ip4 && 'M') action = icmp4{} > > > > > match = (ip6 && 'M') action = icmp6{} > > > > > > > > > > This approach has a couple of problems: > > > > > - ovn-controller can reject the lflows if there are invalid > matches. > > > > > Eg. If match 'M' is - 'ip4 && udp'. > > > > > > > > > > - In a large scale deployment, this could result in lot of > invalid > > > > > logical flows and increase the size of the SB DB. > > > > > > > > > > This patch addresses this problem by providing an option to the CMS > > > > > to specify the l3 protocol and l4 protocol as hints. A new column > > > > > 'options' is added to the ACL table with the options - > > > > > options:l3-protocol and options:l4-protocol. > > > > > > > > > > ovn-northd will now generate only the required lflows for the reject > > > > > ACL. If no options are set, then it falls back to the default > scenario. > > > > > > > > > > > > > Thanks Numan. I believe the solution should work. However, it seems a > > > > little confusing for the end user about how to use the hint field. I > think > > > > maybe we should try to avoid the extra field if possible. Here is my > > > > proposal: > > > > > > > > > > Thanks Han for the comments. I do agree if we can avoid the extra > option. > > > > > > > 1. For the tcp v.s. udp check, since we don't want northd to parse the > > > > match condition, we will have to rely on users input. However, > instead of a > > > > hint, I think it is better to let the user explicitly specify in the > action > > > > field. E.g. "reject" means sending icmp, and "tcp_reject" means > sending tcp > > > > reset if the traffic is tcp and otherwise sending icmp. So, if the > user > > > > adds an ACL with match include "udp", they will naturally use "reject" > > > > instead of "tcp_reject" because they know it is not possible for a TCP > > > > packet to hit this ACL. If they add an ACL that tcp traffic is > expected to > > > > match (either TCP only, or general IP traffic), they can use > "tcp_reject". > > > > Would this be more straightforward than an extra "hint" field? > > > > > > > > > > I have few comments here. > > > - If we consider "reject" = "icmp", then we will be breaking the > > > backward compatibility. > > > Right now, for a reject action, ovn-northd would send tcp_reset > > > for tcp traffic and icmp reply or other traffic. > > > After your proposed approach, the behaviour would change ? Is > > > that OK ? Because existing test cases would fail. > > > The proposed patch handles the backward compatibility. Although > > > I'm not sure if it is really required in this case. > > > > > > - For a tcp_reject action, if the match has "tcp", then we will end > > > up adding a logical flow with the icmp action, which is > > > really not required. Or do you mean, pinctrl would take the > > > decision while handling the "tcp_reject" action to either > > > send tcp reset packet or icmp packet ? If so, we can probably just > > > have one action - "reject". Please see below. > > > > > > > 2. For ip4 v.s. ip6, the idea is to support generic ovn logical flow > > > > actions "tcp_reject" and "icmp" in ovn-controller, which can handle > both > > > > ipv4 and ipv6. If this can be supported, the logical flows only needs > to be: > > > > match = (tcp && 'M') action = tcp_reject{} > > > > match = ('M') action = icmp{} > > > > > > > > > > Ok. In this case we cannot support inner actions unless they are > > > independent of the ip version. > > > i.e we can't support - tcp_reject { eth.dst <-> eth.src; ip4.dst <-> > > > ip4.src; } or > > > tcp_reject {eth.dst <-> eth.src; ip6.dst <-> ip6.src;} in one logical > > > flow. ovn-northd has to generate > > > 2 logical flows. > > > - ip4 && 'M', action = tcp_reject { eth.dst <-> eth.src; ip4.dst <-> > > > ip4.src; } > > > - ip6 && 'M', action = tcp_reject { eth.dst <-> eth.src; ip6.dst <-> > > > ip6.src; } > > > > > > > > > Right now for one reject ACL we add the below lflows > > > - ip4 && tcp && 'M', action = tcp_reset { eth.dst <-> eth.src; > > > ip4.dst <-> ip4.src; outport <-> inport;} > > > - ip6 && tcp && 'M', action = tcp_reset { eth.dst <-> eth.src; > > > ip6.dst <-> ip6.src; outport <-> inport;} > > > - ip4 && 'M' , action = icmp4 {eth.dst <-> eth.src; > > > ip4.dst <-> ip4.src; outport <-> inport;} > > > - ip6 && 'M' , action = icmp6 {eth.dst <-> eth.src; > > > ip6.dst <-> ip6.src; outport <-> inport;} > > > > > > I have another idea based on your suggestions here: How about we have > > > a new action - reject{} which will be used > > > for all reject ACLs and this will > > > - send tcp reset packet if the packet is tcp (pinctrl would take > > > the decision) > > > - send icmp packet otherwise. > > > > > > We can add the logical flow for a reject ACL in 2 ways > > > > > > 1. match = M, action = reject { eth.dst <-> eth.src, outport <-> > inport;} > > > > > > OR > > > > > > 2. match = M, action = reject { eth.dst <-> eth.src, ip.src <-> > > > ip.dst; outport <-> inport;} > > > > > > In (1), pinctrl while handling the reject action, will swap the ip src > > > with ip dst (i.e ip4.dst <-> ip4.src or ip6.dst <-> ip6.src }. > > > > > > In (2), we will add 2 new OVN fields "ip.src" and "ip.dst" (just like > > > we have icmp4.frag_mtu now) and the action - ip.src <-> ip.dst > > > will result in another controller action which will swap the ip src > > > and ip dst fields (just like how "icmp4.frag_mtu = 1400" would result > > > into a controller action). > > > > > > Even though (1) will work, it's not transparent. I would personally > > > prefer (2) and I think it's ok if the reject ACL would result in 2 OF > > > controller actions. > > > > > > With this we will have just one logical flow (instead of 4 ) and there > > > will be no changes on the CMS side. > > > > > Yes, this would be even better. Thanks. I will work on it. > > > > What do you think ? > > > > > > Thanks > > > Numan > > > > > > > > > > I haven't thought through all the details but it seems doable. Did > you have > > > > any thoughts on this? (If it proves to be unreasonable I am ok with > current > > > > "hint" approach) > > > > > > > > In addition, I found the existing TCP reject handling has a bug which > > > > messes up the user defined ACL priorities. I just posted a patch: > > > > > https://patchwork.ozlabs.org/project/ovn/patch/20200928000904.858685-1-hzhou@ovn.org/ > > > > It is not directly related to this patch but it would be great if you > could > > > > take a look. > > > > Sure. > > > With only one lflow, my above fix is not needed. (I am not sure about > backporting to old branches.) I thought about it. Since this issue has been there for a long time and no one reported it. Probably its ok to not address this for the branches ? We could also take the approach of accepting your patch and backport to the branches. And we can revert it when I submit the patch with the proposed new approach here. Thanks Numan > > > Thanks > > Numan > > > > > > > > > > Thanks, > > > > Han > > > > > > > > > > > > > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1876990 > > > > > Reported-by: Ilya Maximets <i.maximets@ovn.org> > > > > > Signed-off-by: Numan Siddique <numans@ovn.org> > > > > > --- > > > > > northd/ovn-northd.c | 194 ++++++++++++++++++++---------- > > > > > ovn-nb.ovsschema | 7 +- > > > > > ovn-nb.xml | 43 +++++++ > > > > > tests/ovn-northd.at | 285 > ++++++++++++++++++++++++++++++++++++++++++++ > > > > > 4 files changed, 461 insertions(+), 68 deletions(-) > > > > > > > > > > diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c > > > > > index 3324c9e81d..d167137e07 100644 > > > > > --- a/northd/ovn-northd.c > > > > > +++ b/northd/ovn-northd.c > > > > > @@ -5372,73 +5372,135 @@ build_reject_acl_rules(struct ovn_datapath > *od, > > > > struct hmap *lflows, > > > > > struct ds actions = DS_EMPTY_INITIALIZER; > > > > > bool ingress = (stage == S_SWITCH_IN_ACL); > > > > > > > > > > - /* TCP */ > > > > > - build_acl_log(&actions, acl); > > > > > - if (extra_match->length > 0) { > > > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > > > - } > > > > > - ds_put_format(&match, "ip4 && tcp && (%s)", acl->match); > > > > > - ds_put_format(&actions, "reg0 = 0; " > > > > > - "eth.dst <-> eth.src; ip4.dst <-> ip4.src; " > > > > > - "tcp_reset { outport <-> inport; %s };", > > > > > - ingress ? "next(pipeline=egress,table=5);" > > > > > - : "next(pipeline=ingress,table=20);"); > > > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > > > - acl->priority + OVN_ACL_PRI_OFFSET + > 10, > > > > > - ds_cstr(&match), ds_cstr(&actions), > > > > stage_hint); > > > > > - ds_clear(&match); > > > > > - ds_clear(&actions); > > > > > - build_acl_log(&actions, acl); > > > > > - if (extra_match->length > 0) { > > > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > > > - } > > > > > - ds_put_format(&match, "ip6 && tcp && (%s)", acl->match); > > > > > - ds_put_format(&actions, "reg0 = 0; " > > > > > - "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > > > > - "tcp_reset { outport <-> inport; %s };", > > > > > - ingress ? "next(pipeline=egress,table=5);" > > > > > - : "next(pipeline=ingress,table=20);"); > > > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > > > - acl->priority + OVN_ACL_PRI_OFFSET + > 10, > > > > > - ds_cstr(&match), ds_cstr(&actions), > > > > stage_hint); > > > > > + bool is_ip4 = true; > > > > > + bool is_ip6 = true; > > > > > + bool tcp_reset = true; > > > > > + bool icmp_reset = true; > > > > > + bool is_udp = false; > > > > > + > > > > > + const char *l3_protocol = smap_get(&acl->options, > "l3-protocol"); > > > > > + if (l3_protocol) { > > > > > + if (!strcasecmp(l3_protocol, "ip")) { > > > > > + is_ip4 = true; > > > > > + is_ip6 = true; > > > > > + } else if (!strcasecmp(l3_protocol, "ip4")) { > > > > > + is_ip4 = true; > > > > > + is_ip6 = false; > > > > > + } else if (!strcasecmp(l3_protocol, "ip6")) { > > > > > + is_ip6 = true; > > > > > + is_ip4 = false; > > > > > + } > > > > > + } > > > > > + > > > > > + const char *l4_protocol = smap_get(&acl->options, > "l4-protocol"); > > > > > + if (l4_protocol) { > > > > > + if (!strcasecmp(l4_protocol, "tcp")) { > > > > > + tcp_reset = true; > > > > > + icmp_reset = false; > > > > > + } else if (!strcasecmp(l4_protocol, "udp")) { > > > > > + tcp_reset = false; > > > > > + is_udp = true; > > > > > + } else { > > > > > + tcp_reset = false; > > > > > + } > > > > > + } > > > > > > > > > > - /* IP traffic */ > > > > > - ds_clear(&match); > > > > > - ds_clear(&actions); > > > > > - build_acl_log(&actions, acl); > > > > > - if (extra_match->length > 0) { > > > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > > > - } > > > > > - ds_put_format(&match, "ip4 && (%s)", acl->match); > > > > > - if (extra_actions->length > 0) { > > > > > - ds_put_format(&actions, "%s ", extra_actions->string); > > > > > - } > > > > > - ds_put_format(&actions, "reg0 = 0; " > > > > > - "icmp4 { eth.dst <-> eth.src; ip4.dst <-> > ip4.src; " > > > > > - "outport <-> inport; %s };", > > > > > - ingress ? "next(pipeline=egress,table=5);" > > > > > - : "next(pipeline=ingress,table=20);"); > > > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > > > - acl->priority + OVN_ACL_PRI_OFFSET, > > > > > - ds_cstr(&match), ds_cstr(&actions), > > > > stage_hint); > > > > > - ds_clear(&match); > > > > > - ds_clear(&actions); > > > > > - build_acl_log(&actions, acl); > > > > > - if (extra_match->length > 0) { > > > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > > > - } > > > > > - ds_put_format(&match, "ip6 && (%s)", acl->match); > > > > > - if (extra_actions->length > 0) { > > > > > - ds_put_format(&actions, "%s ", extra_actions->string); > > > > > - } > > > > > - ds_put_format(&actions, "reg0 = 0; icmp6 { " > > > > > - "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > > > > - "outport <-> inport; %s };", > > > > > - ingress ? "next(pipeline=egress,table=5);" > > > > > - : "next(pipeline=ingress,table=20);"); > > > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > > > - acl->priority + OVN_ACL_PRI_OFFSET, > > > > > - ds_cstr(&match), ds_cstr(&actions), > > > > stage_hint); > > > > > + if (is_ip4) { > > > > > + if (tcp_reset) { > > > > > + build_acl_log(&actions, acl); > > > > > + if (extra_match->length > 0) { > > > > > + ds_put_format(&match, "(%s) && ", > extra_match->string); > > > > > + } > > > > > + ds_put_format(&match, "ip4 && tcp && (%s)", > acl->match); > > > > > + if (extra_actions->length > 0) { > > > > > + ds_put_format(&actions, "%s ", > extra_actions->string); > > > > > + } > > > > > + ds_put_format(&actions, "reg0 = 0; " > > > > > + "eth.dst <-> eth.src; ip4.dst <-> > ip4.src; " > > > > > + "tcp_reset { outport <-> inport; %s };", > > > > > + ingress ? > "next(pipeline=egress,table=5);" > > > > > + : > "next(pipeline=ingress,table=20);"); > > > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > > > + acl->priority + > OVN_ACL_PRI_OFFSET + > > > > 10, > > > > > + ds_cstr(&match), > ds_cstr(&actions), > > > > > + stage_hint); > > > > > + } > > > > > + > > > > > + if (icmp_reset) { > > > > > + ds_clear(&match); > > > > > + ds_clear(&actions); > > > > > + build_acl_log(&actions, acl); > > > > > + if (extra_match->length > 0) { > > > > > + ds_put_format(&match, "(%s) && ", > extra_match->string); > > > > > + } > > > > > + ds_put_format(&match, "ip4 && (%s)", acl->match); > > > > > + if (is_udp) { > > > > > + ds_put_cstr(&match, " && udp"); > > > > > + } > > > > > + if (extra_actions->length > 0) { > > > > > + ds_put_format(&actions, "%s ", > extra_actions->string); > > > > > + } > > > > > + ds_put_format(&actions, "reg0 = 0; " > > > > > + "icmp4 { eth.dst <-> eth.src; ip4.dst <-> > > > > ip4.src; " > > > > > + "outport <-> inport; %s };", > > > > > + ingress ? > "next(pipeline=egress,table=5);" > > > > > + : > "next(pipeline=ingress,table=20);"); > > > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > > > + acl->priority + > OVN_ACL_PRI_OFFSET, > > > > > + ds_cstr(&match), > ds_cstr(&actions), > > > > > + stage_hint); > > > > > + } > > > > > + } > > > > > + > > > > > + if (is_ip6) { > > > > > + if (tcp_reset) { > > > > > + ds_clear(&match); > > > > > + ds_clear(&actions); > > > > > + build_acl_log(&actions, acl); > > > > > + if (extra_match->length > 0) { > > > > > + ds_put_format(&match, "(%s) && ", > extra_match->string); > > > > > + } > > > > > + ds_put_format(&match, "ip6 && tcp && (%s)", > acl->match); > > > > > + if (extra_actions->length > 0) { > > > > > + ds_put_format(&actions, "%s ", > extra_actions->string); > > > > > + } > > > > > + ds_put_format(&actions, "reg0 = 0; " > > > > > + "eth.dst <-> eth.src; ip6.dst <-> > ip6.src; " > > > > > + "tcp_reset { outport <-> inport; %s };", > > > > > + ingress ? > "next(pipeline=egress,table=5);" > > > > > + : > "next(pipeline=ingress,table=20);"); > > > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > > > + acl->priority + > OVN_ACL_PRI_OFFSET + > > > > 10, > > > > > + ds_cstr(&match), > ds_cstr(&actions), > > > > > + stage_hint); > > > > > + } > > > > > + > > > > > + if (icmp_reset) { > > > > > + ds_clear(&match); > > > > > + ds_clear(&actions); > > > > > + build_acl_log(&actions, acl); > > > > > + if (extra_match->length > 0) { > > > > > + ds_put_format(&match, "(%s) && ", > extra_match->string); > > > > > + } > > > > > + ds_put_format(&match, "ip6 && (%s)", acl->match); > > > > > + if (is_udp) { > > > > > + ds_put_cstr(&match, " && udp"); > > > > > + } > > > > > + > > > > > + if (extra_actions->length > 0) { > > > > > + ds_put_format(&actions, "%s ", > extra_actions->string); > > > > > + } > > > > > + ds_put_format(&actions, "reg0 = 0; icmp6 { " > > > > > + "eth.dst <-> eth.src; ip6.dst <-> > ip6.src; " > > > > > + "outport <-> inport; %s };", > > > > > + ingress ? > "next(pipeline=egress,table=5);" > > > > > + : > "next(pipeline=ingress,table=20);"); > > > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > > > + acl->priority + > OVN_ACL_PRI_OFFSET, > > > > > + ds_cstr(&match), > ds_cstr(&actions), > > > > > + stage_hint); > > > > > + } > > > > > + } > > > > > > > > > > ds_destroy(&match); > > > > > ds_destroy(&actions); > > > > > diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema > > > > > index 092322ab2c..00f1c7cd4b 100644 > > > > > --- a/ovn-nb.ovsschema > > > > > +++ b/ovn-nb.ovsschema > > > > > @@ -1,7 +1,7 @@ > > > > > { > > > > > "name": "OVN_Northbound", > > > > > - "version": "5.27.0", > > > > > - "cksum": "3507518247 26773", > > > > > + "version": "5.28.0", > > > > > + "cksum": "699859908 26928", > > > > > "tables": { > > > > > "NB_Global": { > > > > > "columns": { > > > > > @@ -225,6 +225,9 @@ > > > > > "debug"]]}, > > > > > "min": 0, "max": 1}}, > > > > > "meter": {"type": {"key": "string", "min": 0, > "max": 1}}, > > > > > + "options": { > > > > > + "type": {"key": "string", "value": "string", > > > > > + "min": 0, "max": "unlimited"}}, > > > > > "external_ids": { > > > > > "type": {"key": "string", "value": "string", > > > > > "min": 0, "max": "unlimited"}}}, > > > > > diff --git a/ovn-nb.xml b/ovn-nb.xml > > > > > index 86195af341..2c3497e2ae 100644 > > > > > --- a/ovn-nb.xml > > > > > +++ b/ovn-nb.xml > > > > > @@ -1721,6 +1721,49 @@ > > > > > </ul> > > > > > </column> > > > > > > > > > > + <group title="Common options"> > > > > > + <column name="options"> > > > > > + This column provides general key/value settings. The > supported > > > > > + options are described individually below. > > > > > + </column> > > > > > + > > > > > + <group title="Options for providing protocol hints for reject > > > > ACL."> > > > > > + <p> > > > > > + The ACL match specified in the > > > > > + <ref column="match" table="ACL" db="OVN_Northbound"/> > column is > > > > > + opaque to <code>OVN</code> and <code>ovn-northd</code> > doesn't > > > > > + look into the match fields. > > > > > + These options can be specified by CMS to provide hints to > > > > > + <code>OVN</code> about the L3 and L4 protocol matches > for the > > > > reject > > > > > + ACL. <code>ovn-northd</code> uses these options if set > to use > > > > > + appropriate actions when generating logical flows. > > > > > + </p> > > > > > + > > > > > + <p> > > > > > + If these options are not set, then > <code>ovn-northd</code> > > > > assumes > > > > > + the reject ACL applies to IPv4, IPv6 and TCP packets. > > > > > + </p> > > > > > + > > > > > + <column name="options" key="l3-protocol"> > > > > > + The possible values are <code>ip</code>, > <code>ip4</code> and > > > > > + <code>ip6</code>. If the value is <code>ip</code>, it > means the > > > > > + reject ACL action applies to both IPv4 and IPv6 packets. > If the > > > > > + value is <code>ip4</code>, it means the reject ACL action > > > > applies to > > > > > + IPv4 packets and the value <code>ip6</code> applies to > IPv6 > > > > packets. > > > > > + </column> > > > > > + > > > > > + <column name="options" key="l4-protocol"> > > > > > + <p> > > > > > + The possible values are <code>tcp</code> and > > > > <code>udp</code>. > > > > > + If the value is <code>tcp</code>, it means the > > > > > + reject ACL action applies to TCP packets. If the > > > > > + value is <code>udp</code>, it means the reject ACL > action > > > > applies > > > > > + to UDP packets. > > > > > + </p> > > > > > + </column> > > > > > + </group> > > > > > + </group> > > > > > + > > > > > <group title="Logging"> > > > > > <p> > > > > > These columns control whether and how OVN logs packets that > > > > match an > > > > > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at > > > > > index 99a9204f1f..4a30f8ed07 100644 > > > > > --- a/tests/ovn-northd.at > > > > > +++ b/tests/ovn-northd.at > > > > > @@ -2010,3 +2010,288 @@ ovn-nbctl --wait=sb set NB_Global . > > > > options:ignore_lsp_down=true > > > > > AT_CHECK([ovn-sbctl lflow-list | grep arp | grep 10\.0\.0\.1], [0], > > > > [ignore]) > > > > > > > > > > AT_CLEANUP > > > > > + > > > > > +AT_SETUP([ovn-northd -- ACL reject flows]) > > > > > +ovn_start > > > > > + > > > > > +ovn-nbctl ls-add sw0 > > > > > +ovn-nbctl lsp-add sw0 sw0-p1 > > > > > +ovn-nbctl lsp-add sw0 sw0-p2 > > > > > + > > > > > +ovn-nbctl pg-add pg0 sw0-p1 sw0-p2 > > > > > +ovn-nbctl acl-add pg0 to-lport 1002 "inport == @pg0 && ip" reject > > > > > + > > > > > +ovn-nbctl --wait=sb sync > > > > > + > > > > > +# If there is a reject ACL wihtout any protocol hints, then > ovn-northd > > > > should > > > > > +# generate lflows with ip4 tcp_reset, icmp4, ip6 tcp_reset and > icmp6 > > > > actions. > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > tcp_reset { > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > tcp_reset { > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +# Set l3-protocol=ip4 for the reject ACL. > > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip4 > > > > > + > > > > > +# ovn-northd should generate 2 lflows with ip4 tcp_reset and icmp4 > > > > actions. > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > tcp_reset { > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +# Set l4-protocol=tcp for the reject ACL. > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > > > > + > > > > > +# ovn-northd should generate 1 lflow with ip4 tcp_reset action. > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > tcp_reset { > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > sort], [0], [dnl > > > > > +]) > > > > > + > > > > > +# Set l4-protocol=udp for the reject ACL. > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > > > > + > > > > > +# ovn-northd should generate 1 lflow with udp match and icmp4 > action. > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > sort], [0], [dnl > > > > > +]) > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=(ip4 && (inport == @pg0 && ip) && udp), dnl > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +# Remove l4-protocol from the reject ACL. > > > > > +ovn-nbctl --wait=sb remove ACL . options l4-protocol > > > > > + > > > > > +# ovn-northd should generate 2 lflow with tcp_reset and icmp4 > action. > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > tcp_reset { > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +# Set l3-protocol to ip. > > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > > > > + > > > > > +# ovn-northd should generate 4 lflow with ip4 tcp_reset, ip6 > tcp_reset, > > > > icmp4 and icmp6 actions. > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > tcp_reset { > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > tcp_reset { > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +# Set l3-protocol=ip6 for the reject ACL. > > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip6 > > > > > + > > > > > +# ovn-northd should generate 2 lflows with ip6 tcp_reset and icmp6 > > > > actions. > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > tcp_reset { > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +# Set l4-protocol=tcp for the reject ACL. > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > > > > + > > > > > +# ovn-northd should generate 1 lflow with ip6 tcp_reset action. > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > tcp_reset { > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > sort], [0], [dnl > > > > > +]) > > > > > + > > > > > +# Set l4-protocol=udp for the reject ACL. > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > > > > + > > > > > +# ovn-northd should generate 1 lflow with udp match and icmp6 > action. > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > sort], [0], [dnl > > > > > +]) > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=(ip6 && (inport == @pg0 && ip) && udp), dnl > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL. > > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > > > > + > > > > > +# ovn-northd should generate 2 lflow with ip4 tcp_reset and ip6 > > > > tcp_reset actions. > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > tcp_reset { > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > tcp_reset { > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > sort], [0], [dnl > > > > > +]) > > > > > + > > > > > +# Set l3-protocol to ip and l4-protocol=udp for the reject ACL. > > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > > > > + > > > > > +# ovn-northd should generate 2 lflows (udp match) with icmp4 and > icmp6 > > > > actions. > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > sort], [0], [dnl > > > > > +]) > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=(ip4 && (inport == @pg0 && ip) && udp), dnl > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=(ip6 && (inport == @pg0 && ip) && udp), dnl > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +# Add an ACL with allow-related > > > > > +ovn-nbctl --wait=sb acl-add pg0 to-lport 1000 "ip" allow-related > > > > > + > > > > > +# ovn-northd should generate 4 lflow with 2 icmp4 and 2 icmp6 > actions. > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > sort], [0], [dnl > > > > > +]) > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && udp), > dnl\ > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp4 { > eth.dst > > > > <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; > > > > next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && udp), > dnl > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp6 { > eth.dst > > > > <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; > > > > next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && udp), > dnl > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && udp), > dnl > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL. > > > > > +rej_acl=$(ovn-nbctl --bare --columns _uuid find ACL action=reject) > > > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l3-protocol=ip > > > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp > > > > > + > > > > > +# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and 2 ip6 > > > > tcp_reset actions. > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), > dnl > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > > > > eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; > > > > next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), > dnl > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > > > > eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; > > > > next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), > dnl > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > tcp_reset { > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), > dnl > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > tcp_reset { > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > sort], [0], [dnl > > > > > +]) > > > > > + > > > > > + > > > > > +# Clear l3-protocol and set l4-protocol to udp > > > > > +ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol > > > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=udp > > > > > + > > > > > +# ovn-northd should generate 4 lflows (with udp match) with 2 > icmp4 and > > > > 2 icmp6 actions. > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > sort], [0], [dnl > > > > > +]) > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && udp), > dnl\ > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp4 { > eth.dst > > > > <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; > > > > next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && udp), > dnl > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp6 { > eth.dst > > > > <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; > > > > next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && udp), > dnl > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > +match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && udp), > dnl > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +# Clear l3-protocol and set l4-protocol to tcp > > > > > +ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol > > > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp > > > > > + > > > > > +# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and 2 ip6 > > > > tcp_reset actions. > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > sort], [0], [dnl > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), > dnl > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > > > > eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; > > > > next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), > dnl > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > > > > eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; > > > > next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), > dnl > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > tcp_reset { > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > +match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), > dnl > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > tcp_reset { > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > +]) > > > > > + > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > sort], [0], [dnl > > > > > +]) > > > > > + > > > > > +AT_CLEANUP > > > > > -- > > > > > 2.26.2 > > > > > > > > > > _______________________________________________ > > > > > dev mailing list > > > > > dev@openvswitch.org > > > > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > > > _______________________________________________ > > > > dev mailing list > > > > dev@openvswitch.org > > > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > > > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev >
On Mon, Sep 28, 2020 at 10:03 AM Numan Siddique <numans@ovn.org> wrote: > > On Mon, Sep 28, 2020 at 9:41 PM Han Zhou <hzhou@ovn.org> wrote: > > > > On Mon, Sep 28, 2020 at 2:21 AM Numan Siddique <numans@ovn.org> wrote: > > > > > > On Mon, Sep 28, 2020 at 2:14 PM Numan Siddique <numans@ovn.org> wrote: > > > > > > > > On Mon, Sep 28, 2020 at 5:57 AM Han Zhou <hzhou@ovn.org> wrote: > > > > > > > > > > Thanks Numan. I have some comments on the solution. > > > > > > > > > > On Thu, Sep 24, 2020 at 9:50 AM <numans@ovn.org> wrote: > > > > > > > > > > > > From: Numan Siddique <numans@ovn.org> > > > > > > > > > > > > ovn-northd adds below lflows for a reject ACL with a match - M > > > > > > > > > > > > match = (ip4 && tcp && 'M') action = tcp_reject{} > > > > > > match = (ip6 && tcp && 'M') action = tcp_reject{} > > > > > > match = (ip4 && 'M') action = icmp4{} > > > > > > match = (ip6 && 'M') action = icmp6{} > > > > > > > > > > > > This approach has a couple of problems: > > > > > > - ovn-controller can reject the lflows if there are invalid > > matches. > > > > > > Eg. If match 'M' is - 'ip4 && udp'. > > > > > > > > > > > > - In a large scale deployment, this could result in lot of > > invalid > > > > > > logical flows and increase the size of the SB DB. > > > > > > > > > > > > This patch addresses this problem by providing an option to the CMS > > > > > > to specify the l3 protocol and l4 protocol as hints. A new column > > > > > > 'options' is added to the ACL table with the options - > > > > > > options:l3-protocol and options:l4-protocol. > > > > > > > > > > > > ovn-northd will now generate only the required lflows for the reject > > > > > > ACL. If no options are set, then it falls back to the default > > scenario. > > > > > > > > > > > > > > > > Thanks Numan. I believe the solution should work. However, it seems a > > > > > little confusing for the end user about how to use the hint field. I > > think > > > > > maybe we should try to avoid the extra field if possible. Here is my > > > > > proposal: > > > > > > > > > > > > > Thanks Han for the comments. I do agree if we can avoid the extra > > option. > > > > > > > > > 1. For the tcp v.s. udp check, since we don't want northd to parse the > > > > > match condition, we will have to rely on users input. However, > > instead of a > > > > > hint, I think it is better to let the user explicitly specify in the > > action > > > > > field. E.g. "reject" means sending icmp, and "tcp_reject" means > > sending tcp > > > > > reset if the traffic is tcp and otherwise sending icmp. So, if the > > user > > > > > adds an ACL with match include "udp", they will naturally use "reject" > > > > > instead of "tcp_reject" because they know it is not possible for a TCP > > > > > packet to hit this ACL. If they add an ACL that tcp traffic is > > expected to > > > > > match (either TCP only, or general IP traffic), they can use > > "tcp_reject". > > > > > Would this be more straightforward than an extra "hint" field? > > > > > > > > > > > > > I have few comments here. > > > > - If we consider "reject" = "icmp", then we will be breaking the > > > > backward compatibility. > > > > Right now, for a reject action, ovn-northd would send tcp_reset > > > > for tcp traffic and icmp reply or other traffic. > > > > After your proposed approach, the behaviour would change ? Is > > > > that OK ? Because existing test cases would fail. > > > > The proposed patch handles the backward compatibility. Although > > > > I'm not sure if it is really required in this case. > > > > > > > > - For a tcp_reject action, if the match has "tcp", then we will end > > > > up adding a logical flow with the icmp action, which is > > > > really not required. Or do you mean, pinctrl would take the > > > > decision while handling the "tcp_reject" action to either > > > > send tcp reset packet or icmp packet ? If so, we can probably just > > > > have one action - "reject". Please see below. > > > > > > > > > 2. For ip4 v.s. ip6, the idea is to support generic ovn logical flow > > > > > actions "tcp_reject" and "icmp" in ovn-controller, which can handle > > both > > > > > ipv4 and ipv6. If this can be supported, the logical flows only needs > > to be: > > > > > match = (tcp && 'M') action = tcp_reject{} > > > > > match = ('M') action = icmp{} > > > > > > > > > > > > > Ok. In this case we cannot support inner actions unless they are > > > > independent of the ip version. > > > > i.e we can't support - tcp_reject { eth.dst <-> eth.src; ip4.dst <-> > > > > ip4.src; } or > > > > tcp_reject {eth.dst <-> eth.src; ip6.dst <-> ip6.src;} in one logical > > > > flow. ovn-northd has to generate > > > > 2 logical flows. > > > > - ip4 && 'M', action = tcp_reject { eth.dst <-> eth.src; ip4.dst <-> > > > > ip4.src; } > > > > - ip6 && 'M', action = tcp_reject { eth.dst <-> eth.src; ip6.dst <-> > > > > ip6.src; } > > > > > > > > > > > > Right now for one reject ACL we add the below lflows > > > > - ip4 && tcp && 'M', action = tcp_reset { eth.dst <-> eth.src; > > > > ip4.dst <-> ip4.src; outport <-> inport;} > > > > - ip6 && tcp && 'M', action = tcp_reset { eth.dst <-> eth.src; > > > > ip6.dst <-> ip6.src; outport <-> inport;} > > > > - ip4 && 'M' , action = icmp4 {eth.dst <-> eth.src; > > > > ip4.dst <-> ip4.src; outport <-> inport;} > > > > - ip6 && 'M' , action = icmp6 {eth.dst <-> eth.src; > > > > ip6.dst <-> ip6.src; outport <-> inport;} > > > > > > > > I have another idea based on your suggestions here: How about we have > > > > a new action - reject{} which will be used > > > > for all reject ACLs and this will > > > > - send tcp reset packet if the packet is tcp (pinctrl would take > > > > the decision) > > > > - send icmp packet otherwise. > > > > > > > > We can add the logical flow for a reject ACL in 2 ways > > > > > > > > 1. match = M, action = reject { eth.dst <-> eth.src, outport <-> > > inport;} > > > > > > > > OR > > > > > > > > 2. match = M, action = reject { eth.dst <-> eth.src, ip.src <-> > > > > ip.dst; outport <-> inport;} > > > > > > > > In (1), pinctrl while handling the reject action, will swap the ip src > > > > with ip dst (i.e ip4.dst <-> ip4.src or ip6.dst <-> ip6.src }. > > > > > > > > In (2), we will add 2 new OVN fields "ip.src" and "ip.dst" (just like > > > > we have icmp4.frag_mtu now) and the action - ip.src <-> ip.dst > > > > will result in another controller action which will swap the ip src > > > > and ip dst fields (just like how "icmp4.frag_mtu = 1400" would result > > > > into a controller action). > > > > > > > > Even though (1) will work, it's not transparent. I would personally > > > > prefer (2) and I think it's ok if the reject ACL would result in 2 OF > > > > controller actions. > > > > > > > > With this we will have just one logical flow (instead of 4 ) and there > > > > will be no changes on the CMS side. > > > > > > > > Yes, this would be even better. > > Thanks. I will work on it. > > > > > > > > What do you think ? > > > > > > > > Thanks > > > > Numan > > > > > > > > > > > > > I haven't thought through all the details but it seems doable. Did > > you have > > > > > any thoughts on this? (If it proves to be unreasonable I am ok with > > current > > > > > "hint" approach) > > > > > > > > > > In addition, I found the existing TCP reject handling has a bug which > > > > > messes up the user defined ACL priorities. I just posted a patch: > > > > > > > https://patchwork.ozlabs.org/project/ovn/patch/20200928000904.858685-1-hzhou@ovn.org/ > > > > > It is not directly related to this patch but it would be great if you > > could > > > > > take a look. > > > > > > Sure. > > > > > With only one lflow, my above fix is not needed. (I am not sure about > > backporting to old branches.) > > I thought about it. Since this issue has been there for a long time > and no one reported it. Probably its ok to not > address this for the branches ? > Maybe. It seems this feature is not heavily used. Otherwise such issues should have been reported. I reported another issue related to "reject" but didn't have time to debug: https://mail.openvswitch.org/pipermail/ovs-discuss/2020-September/050711.html > We could also take the approach of accepting your patch and backport > to the branches. And we can revert it when I submit the patch > with the proposed new approach here. > I think we can wait for your patch, unless someone complains and requires an immediate fix. My patch reduces the ACL priority range, which is a risk of backward compatibility, so I'd rather not apply it if you could work out the proposed fix here. > Thanks > Numan > > > > > > Thanks > > > Numan > > > > > > > > > > > > > Thanks, > > > > > Han > > > > > > > > > > > > > > > > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1876990 > > > > > > Reported-by: Ilya Maximets <i.maximets@ovn.org> > > > > > > Signed-off-by: Numan Siddique <numans@ovn.org> > > > > > > --- > > > > > > northd/ovn-northd.c | 194 ++++++++++++++++++++---------- > > > > > > ovn-nb.ovsschema | 7 +- > > > > > > ovn-nb.xml | 43 +++++++ > > > > > > tests/ovn-northd.at | 285 > > ++++++++++++++++++++++++++++++++++++++++++++ > > > > > > 4 files changed, 461 insertions(+), 68 deletions(-) > > > > > > > > > > > > diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c > > > > > > index 3324c9e81d..d167137e07 100644 > > > > > > --- a/northd/ovn-northd.c > > > > > > +++ b/northd/ovn-northd.c > > > > > > @@ -5372,73 +5372,135 @@ build_reject_acl_rules(struct ovn_datapath > > *od, > > > > > struct hmap *lflows, > > > > > > struct ds actions = DS_EMPTY_INITIALIZER; > > > > > > bool ingress = (stage == S_SWITCH_IN_ACL); > > > > > > > > > > > > - /* TCP */ > > > > > > - build_acl_log(&actions, acl); > > > > > > - if (extra_match->length > 0) { > > > > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > > > > - } > > > > > > - ds_put_format(&match, "ip4 && tcp && (%s)", acl->match); > > > > > > - ds_put_format(&actions, "reg0 = 0; " > > > > > > - "eth.dst <-> eth.src; ip4.dst <-> ip4.src; " > > > > > > - "tcp_reset { outport <-> inport; %s };", > > > > > > - ingress ? "next(pipeline=egress,table=5);" > > > > > > - : "next(pipeline=ingress,table=20);"); > > > > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > > > > - acl->priority + OVN_ACL_PRI_OFFSET + > > 10, > > > > > > - ds_cstr(&match), ds_cstr(&actions), > > > > > stage_hint); > > > > > > - ds_clear(&match); > > > > > > - ds_clear(&actions); > > > > > > - build_acl_log(&actions, acl); > > > > > > - if (extra_match->length > 0) { > > > > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > > > > - } > > > > > > - ds_put_format(&match, "ip6 && tcp && (%s)", acl->match); > > > > > > - ds_put_format(&actions, "reg0 = 0; " > > > > > > - "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > > > > > - "tcp_reset { outport <-> inport; %s };", > > > > > > - ingress ? "next(pipeline=egress,table=5);" > > > > > > - : "next(pipeline=ingress,table=20);"); > > > > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > > > > - acl->priority + OVN_ACL_PRI_OFFSET + > > 10, > > > > > > - ds_cstr(&match), ds_cstr(&actions), > > > > > stage_hint); > > > > > > + bool is_ip4 = true; > > > > > > + bool is_ip6 = true; > > > > > > + bool tcp_reset = true; > > > > > > + bool icmp_reset = true; > > > > > > + bool is_udp = false; > > > > > > + > > > > > > + const char *l3_protocol = smap_get(&acl->options, > > "l3-protocol"); > > > > > > + if (l3_protocol) { > > > > > > + if (!strcasecmp(l3_protocol, "ip")) { > > > > > > + is_ip4 = true; > > > > > > + is_ip6 = true; > > > > > > + } else if (!strcasecmp(l3_protocol, "ip4")) { > > > > > > + is_ip4 = true; > > > > > > + is_ip6 = false; > > > > > > + } else if (!strcasecmp(l3_protocol, "ip6")) { > > > > > > + is_ip6 = true; > > > > > > + is_ip4 = false; > > > > > > + } > > > > > > + } > > > > > > + > > > > > > + const char *l4_protocol = smap_get(&acl->options, > > "l4-protocol"); > > > > > > + if (l4_protocol) { > > > > > > + if (!strcasecmp(l4_protocol, "tcp")) { > > > > > > + tcp_reset = true; > > > > > > + icmp_reset = false; > > > > > > + } else if (!strcasecmp(l4_protocol, "udp")) { > > > > > > + tcp_reset = false; > > > > > > + is_udp = true; > > > > > > + } else { > > > > > > + tcp_reset = false; > > > > > > + } > > > > > > + } > > > > > > > > > > > > - /* IP traffic */ > > > > > > - ds_clear(&match); > > > > > > - ds_clear(&actions); > > > > > > - build_acl_log(&actions, acl); > > > > > > - if (extra_match->length > 0) { > > > > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > > > > - } > > > > > > - ds_put_format(&match, "ip4 && (%s)", acl->match); > > > > > > - if (extra_actions->length > 0) { > > > > > > - ds_put_format(&actions, "%s ", extra_actions->string); > > > > > > - } > > > > > > - ds_put_format(&actions, "reg0 = 0; " > > > > > > - "icmp4 { eth.dst <-> eth.src; ip4.dst <-> > > ip4.src; " > > > > > > - "outport <-> inport; %s };", > > > > > > - ingress ? "next(pipeline=egress,table=5);" > > > > > > - : "next(pipeline=ingress,table=20);"); > > > > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > > > > - acl->priority + OVN_ACL_PRI_OFFSET, > > > > > > - ds_cstr(&match), ds_cstr(&actions), > > > > > stage_hint); > > > > > > - ds_clear(&match); > > > > > > - ds_clear(&actions); > > > > > > - build_acl_log(&actions, acl); > > > > > > - if (extra_match->length > 0) { > > > > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > > > > - } > > > > > > - ds_put_format(&match, "ip6 && (%s)", acl->match); > > > > > > - if (extra_actions->length > 0) { > > > > > > - ds_put_format(&actions, "%s ", extra_actions->string); > > > > > > - } > > > > > > - ds_put_format(&actions, "reg0 = 0; icmp6 { " > > > > > > - "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > > > > > - "outport <-> inport; %s };", > > > > > > - ingress ? "next(pipeline=egress,table=5);" > > > > > > - : "next(pipeline=ingress,table=20);"); > > > > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > > > > - acl->priority + OVN_ACL_PRI_OFFSET, > > > > > > - ds_cstr(&match), ds_cstr(&actions), > > > > > stage_hint); > > > > > > + if (is_ip4) { > > > > > > + if (tcp_reset) { > > > > > > + build_acl_log(&actions, acl); > > > > > > + if (extra_match->length > 0) { > > > > > > + ds_put_format(&match, "(%s) && ", > > extra_match->string); > > > > > > + } > > > > > > + ds_put_format(&match, "ip4 && tcp && (%s)", > > acl->match); > > > > > > + if (extra_actions->length > 0) { > > > > > > + ds_put_format(&actions, "%s ", > > extra_actions->string); > > > > > > + } > > > > > > + ds_put_format(&actions, "reg0 = 0; " > > > > > > + "eth.dst <-> eth.src; ip4.dst <-> > > ip4.src; " > > > > > > + "tcp_reset { outport <-> inport; %s };", > > > > > > + ingress ? > > "next(pipeline=egress,table=5);" > > > > > > + : > > "next(pipeline=ingress,table=20);"); > > > > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > > > > + acl->priority + > > OVN_ACL_PRI_OFFSET + > > > > > 10, > > > > > > + ds_cstr(&match), > > ds_cstr(&actions), > > > > > > + stage_hint); > > > > > > + } > > > > > > + > > > > > > + if (icmp_reset) { > > > > > > + ds_clear(&match); > > > > > > + ds_clear(&actions); > > > > > > + build_acl_log(&actions, acl); > > > > > > + if (extra_match->length > 0) { > > > > > > + ds_put_format(&match, "(%s) && ", > > extra_match->string); > > > > > > + } > > > > > > + ds_put_format(&match, "ip4 && (%s)", acl->match); > > > > > > + if (is_udp) { > > > > > > + ds_put_cstr(&match, " && udp"); > > > > > > + } > > > > > > + if (extra_actions->length > 0) { > > > > > > + ds_put_format(&actions, "%s ", > > extra_actions->string); > > > > > > + } > > > > > > + ds_put_format(&actions, "reg0 = 0; " > > > > > > + "icmp4 { eth.dst <-> eth.src; ip4.dst <-> > > > > > ip4.src; " > > > > > > + "outport <-> inport; %s };", > > > > > > + ingress ? > > "next(pipeline=egress,table=5);" > > > > > > + : > > "next(pipeline=ingress,table=20);"); > > > > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > > > > + acl->priority + > > OVN_ACL_PRI_OFFSET, > > > > > > + ds_cstr(&match), > > ds_cstr(&actions), > > > > > > + stage_hint); > > > > > > + } > > > > > > + } > > > > > > + > > > > > > + if (is_ip6) { > > > > > > + if (tcp_reset) { > > > > > > + ds_clear(&match); > > > > > > + ds_clear(&actions); > > > > > > + build_acl_log(&actions, acl); > > > > > > + if (extra_match->length > 0) { > > > > > > + ds_put_format(&match, "(%s) && ", > > extra_match->string); > > > > > > + } > > > > > > + ds_put_format(&match, "ip6 && tcp && (%s)", > > acl->match); > > > > > > + if (extra_actions->length > 0) { > > > > > > + ds_put_format(&actions, "%s ", > > extra_actions->string); > > > > > > + } > > > > > > + ds_put_format(&actions, "reg0 = 0; " > > > > > > + "eth.dst <-> eth.src; ip6.dst <-> > > ip6.src; " > > > > > > + "tcp_reset { outport <-> inport; %s };", > > > > > > + ingress ? > > "next(pipeline=egress,table=5);" > > > > > > + : > > "next(pipeline=ingress,table=20);"); > > > > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > > > > + acl->priority + > > OVN_ACL_PRI_OFFSET + > > > > > 10, > > > > > > + ds_cstr(&match), > > ds_cstr(&actions), > > > > > > + stage_hint); > > > > > > + } > > > > > > + > > > > > > + if (icmp_reset) { > > > > > > + ds_clear(&match); > > > > > > + ds_clear(&actions); > > > > > > + build_acl_log(&actions, acl); > > > > > > + if (extra_match->length > 0) { > > > > > > + ds_put_format(&match, "(%s) && ", > > extra_match->string); > > > > > > + } > > > > > > + ds_put_format(&match, "ip6 && (%s)", acl->match); > > > > > > + if (is_udp) { > > > > > > + ds_put_cstr(&match, " && udp"); > > > > > > + } > > > > > > + > > > > > > + if (extra_actions->length > 0) { > > > > > > + ds_put_format(&actions, "%s ", > > extra_actions->string); > > > > > > + } > > > > > > + ds_put_format(&actions, "reg0 = 0; icmp6 { " > > > > > > + "eth.dst <-> eth.src; ip6.dst <-> > > ip6.src; " > > > > > > + "outport <-> inport; %s };", > > > > > > + ingress ? > > "next(pipeline=egress,table=5);" > > > > > > + : > > "next(pipeline=ingress,table=20);"); > > > > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > > > > + acl->priority + > > OVN_ACL_PRI_OFFSET, > > > > > > + ds_cstr(&match), > > ds_cstr(&actions), > > > > > > + stage_hint); > > > > > > + } > > > > > > + } > > > > > > > > > > > > ds_destroy(&match); > > > > > > ds_destroy(&actions); > > > > > > diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema > > > > > > index 092322ab2c..00f1c7cd4b 100644 > > > > > > --- a/ovn-nb.ovsschema > > > > > > +++ b/ovn-nb.ovsschema > > > > > > @@ -1,7 +1,7 @@ > > > > > > { > > > > > > "name": "OVN_Northbound", > > > > > > - "version": "5.27.0", > > > > > > - "cksum": "3507518247 26773", > > > > > > + "version": "5.28.0", > > > > > > + "cksum": "699859908 26928", > > > > > > "tables": { > > > > > > "NB_Global": { > > > > > > "columns": { > > > > > > @@ -225,6 +225,9 @@ > > > > > > "debug"]]}, > > > > > > "min": 0, "max": 1}}, > > > > > > "meter": {"type": {"key": "string", "min": 0, > > "max": 1}}, > > > > > > + "options": { > > > > > > + "type": {"key": "string", "value": "string", > > > > > > + "min": 0, "max": "unlimited"}}, > > > > > > "external_ids": { > > > > > > "type": {"key": "string", "value": "string", > > > > > > "min": 0, "max": "unlimited"}}}, > > > > > > diff --git a/ovn-nb.xml b/ovn-nb.xml > > > > > > index 86195af341..2c3497e2ae 100644 > > > > > > --- a/ovn-nb.xml > > > > > > +++ b/ovn-nb.xml > > > > > > @@ -1721,6 +1721,49 @@ > > > > > > </ul> > > > > > > </column> > > > > > > > > > > > > + <group title="Common options"> > > > > > > + <column name="options"> > > > > > > + This column provides general key/value settings. The > > supported > > > > > > + options are described individually below. > > > > > > + </column> > > > > > > + > > > > > > + <group title="Options for providing protocol hints for reject > > > > > ACL."> > > > > > > + <p> > > > > > > + The ACL match specified in the > > > > > > + <ref column="match" table="ACL" db="OVN_Northbound"/> > > column is > > > > > > + opaque to <code>OVN</code> and <code>ovn-northd</code> > > doesn't > > > > > > + look into the match fields. > > > > > > + These options can be specified by CMS to provide hints to > > > > > > + <code>OVN</code> about the L3 and L4 protocol matches > > for the > > > > > reject > > > > > > + ACL. <code>ovn-northd</code> uses these options if set > > to use > > > > > > + appropriate actions when generating logical flows. > > > > > > + </p> > > > > > > + > > > > > > + <p> > > > > > > + If these options are not set, then > > <code>ovn-northd</code> > > > > > assumes > > > > > > + the reject ACL applies to IPv4, IPv6 and TCP packets. > > > > > > + </p> > > > > > > + > > > > > > + <column name="options" key="l3-protocol"> > > > > > > + The possible values are <code>ip</code>, > > <code>ip4</code> and > > > > > > + <code>ip6</code>. If the value is <code>ip</code>, it > > means the > > > > > > + reject ACL action applies to both IPv4 and IPv6 packets. > > If the > > > > > > + value is <code>ip4</code>, it means the reject ACL action > > > > > applies to > > > > > > + IPv4 packets and the value <code>ip6</code> applies to > > IPv6 > > > > > packets. > > > > > > + </column> > > > > > > + > > > > > > + <column name="options" key="l4-protocol"> > > > > > > + <p> > > > > > > + The possible values are <code>tcp</code> and > > > > > <code>udp</code>. > > > > > > + If the value is <code>tcp</code>, it means the > > > > > > + reject ACL action applies to TCP packets. If the > > > > > > + value is <code>udp</code>, it means the reject ACL > > action > > > > > applies > > > > > > + to UDP packets. > > > > > > + </p> > > > > > > + </column> > > > > > > + </group> > > > > > > + </group> > > > > > > + > > > > > > <group title="Logging"> > > > > > > <p> > > > > > > These columns control whether and how OVN logs packets that > > > > > match an > > > > > > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at > > > > > > index 99a9204f1f..4a30f8ed07 100644 > > > > > > --- a/tests/ovn-northd.at > > > > > > +++ b/tests/ovn-northd.at > > > > > > @@ -2010,3 +2010,288 @@ ovn-nbctl --wait=sb set NB_Global . > > > > > options:ignore_lsp_down=true > > > > > > AT_CHECK([ovn-sbctl lflow-list | grep arp | grep 10\.0\.0\.1], [0], > > > > > [ignore]) > > > > > > > > > > > > AT_CLEANUP > > > > > > + > > > > > > +AT_SETUP([ovn-northd -- ACL reject flows]) > > > > > > +ovn_start > > > > > > + > > > > > > +ovn-nbctl ls-add sw0 > > > > > > +ovn-nbctl lsp-add sw0 sw0-p1 > > > > > > +ovn-nbctl lsp-add sw0 sw0-p2 > > > > > > + > > > > > > +ovn-nbctl pg-add pg0 sw0-p1 sw0-p2 > > > > > > +ovn-nbctl acl-add pg0 to-lport 1002 "inport == @pg0 && ip" reject > > > > > > + > > > > > > +ovn-nbctl --wait=sb sync > > > > > > + > > > > > > +# If there is a reject ACL wihtout any protocol hints, then > > ovn-northd > > > > > should > > > > > > +# generate lflows with ip4 tcp_reset, icmp4, ip6 tcp_reset and > > icmp6 > > > > > actions. > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > tcp_reset { > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > tcp_reset { > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +# Set l3-protocol=ip4 for the reject ACL. > > > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip4 > > > > > > + > > > > > > +# ovn-northd should generate 2 lflows with ip4 tcp_reset and icmp4 > > > > > actions. > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > tcp_reset { > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +# Set l4-protocol=tcp for the reject ACL. > > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > > > > > + > > > > > > +# ovn-northd should generate 1 lflow with ip4 tcp_reset action. > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > tcp_reset { > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > > sort], [0], [dnl > > > > > > +]) > > > > > > + > > > > > > +# Set l4-protocol=udp for the reject ACL. > > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > > > > > + > > > > > > +# ovn-northd should generate 1 lflow with udp match and icmp4 > > action. > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > > sort], [0], [dnl > > > > > > +]) > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=(ip4 && (inport == @pg0 && ip) && udp), dnl > > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +# Remove l4-protocol from the reject ACL. > > > > > > +ovn-nbctl --wait=sb remove ACL . options l4-protocol > > > > > > + > > > > > > +# ovn-northd should generate 2 lflow with tcp_reset and icmp4 > > action. > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > tcp_reset { > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +# Set l3-protocol to ip. > > > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > > > > > + > > > > > > +# ovn-northd should generate 4 lflow with ip4 tcp_reset, ip6 > > tcp_reset, > > > > > icmp4 and icmp6 actions. > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > tcp_reset { > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > tcp_reset { > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +# Set l3-protocol=ip6 for the reject ACL. > > > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip6 > > > > > > + > > > > > > +# ovn-northd should generate 2 lflows with ip6 tcp_reset and icmp6 > > > > > actions. > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > tcp_reset { > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +# Set l4-protocol=tcp for the reject ACL. > > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > > > > > + > > > > > > +# ovn-northd should generate 1 lflow with ip6 tcp_reset action. > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > tcp_reset { > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > > sort], [0], [dnl > > > > > > +]) > > > > > > + > > > > > > +# Set l4-protocol=udp for the reject ACL. > > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > > > > > + > > > > > > +# ovn-northd should generate 1 lflow with udp match and icmp6 > > action. > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > > sort], [0], [dnl > > > > > > +]) > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=(ip6 && (inport == @pg0 && ip) && udp), dnl > > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL. > > > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > > > > > + > > > > > > +# ovn-northd should generate 2 lflow with ip4 tcp_reset and ip6 > > > > > tcp_reset actions. > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > tcp_reset { > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > tcp_reset { > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > > sort], [0], [dnl > > > > > > +]) > > > > > > + > > > > > > +# Set l3-protocol to ip and l4-protocol=udp for the reject ACL. > > > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > > > > > + > > > > > > +# ovn-northd should generate 2 lflows (udp match) with icmp4 and > > icmp6 > > > > > actions. > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > > sort], [0], [dnl > > > > > > +]) > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=(ip4 && (inport == @pg0 && ip) && udp), dnl > > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=(ip6 && (inport == @pg0 && ip) && udp), dnl > > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +# Add an ACL with allow-related > > > > > > +ovn-nbctl --wait=sb acl-add pg0 to-lport 1000 "ip" allow-related > > > > > > + > > > > > > +# ovn-northd should generate 4 lflow with 2 icmp4 and 2 icmp6 > > actions. > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > > sort], [0], [dnl > > > > > > +]) > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && udp), > > dnl\ > > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp4 { > > eth.dst > > > > > <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; > > > > > next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && udp), > > dnl > > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp6 { > > eth.dst > > > > > <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; > > > > > next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && udp), > > dnl > > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && udp), > > dnl > > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL. > > > > > > +rej_acl=$(ovn-nbctl --bare --columns _uuid find ACL action=reject) > > > > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l3-protocol=ip > > > > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp > > > > > > + > > > > > > +# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and 2 ip6 > > > > > tcp_reset actions. > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), > > dnl > > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > > > > > eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; > > > > > next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), > > dnl > > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > > > > > eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; > > > > > next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), > > dnl > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > tcp_reset { > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), > > dnl > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > tcp_reset { > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > > sort], [0], [dnl > > > > > > +]) > > > > > > + > > > > > > + > > > > > > +# Clear l3-protocol and set l4-protocol to udp > > > > > > +ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol > > > > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=udp > > > > > > + > > > > > > +# ovn-northd should generate 4 lflows (with udp match) with 2 > > icmp4 and > > > > > 2 icmp6 actions. > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > > sort], [0], [dnl > > > > > > +]) > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && udp), > > dnl\ > > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp4 { > > eth.dst > > > > > <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; > > > > > next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && udp), > > dnl > > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp6 { > > eth.dst > > > > > <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; > > > > > next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && udp), > > dnl > > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > +match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && udp), > > dnl > > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +# Clear l3-protocol and set l4-protocol to tcp > > > > > > +ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol > > > > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp > > > > > > + > > > > > > +# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and 2 ip6 > > > > > tcp_reset actions. > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | > > > > > sort], [0], [dnl > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), > > dnl > > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > > > > > eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; > > > > > next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), > > dnl > > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> > > > > > eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; > > > > > next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), > > dnl > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > tcp_reset { > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > +match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), > > dnl > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > tcp_reset { > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > +]) > > > > > > + > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | > > > > > sort], [0], [dnl > > > > > > +]) > > > > > > + > > > > > > +AT_CLEANUP > > > > > > -- > > > > > > 2.26.2 > > > > > > > > > > > > _______________________________________________ > > > > > > dev mailing list > > > > > > dev@openvswitch.org > > > > > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > > > > _______________________________________________ > > > > > dev mailing list > > > > > dev@openvswitch.org > > > > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > > > > > > _______________________________________________ > > dev mailing list > > dev@openvswitch.org > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > >
On Mon, Sep 28, 2020 at 11:13 PM Han Zhou <hzhou@ovn.org> wrote: > > On Mon, Sep 28, 2020 at 10:03 AM Numan Siddique <numans@ovn.org> wrote: > > > > On Mon, Sep 28, 2020 at 9:41 PM Han Zhou <hzhou@ovn.org> wrote: > > > > > > On Mon, Sep 28, 2020 at 2:21 AM Numan Siddique <numans@ovn.org> wrote: > > > > > > > > On Mon, Sep 28, 2020 at 2:14 PM Numan Siddique <numans@ovn.org> wrote: > > > > > > > > > > On Mon, Sep 28, 2020 at 5:57 AM Han Zhou <hzhou@ovn.org> wrote: > > > > > > > > > > > > Thanks Numan. I have some comments on the solution. > > > > > > > > > > > > On Thu, Sep 24, 2020 at 9:50 AM <numans@ovn.org> wrote: > > > > > > > > > > > > > > From: Numan Siddique <numans@ovn.org> > > > > > > > > > > > > > > ovn-northd adds below lflows for a reject ACL with a match - M > > > > > > > > > > > > > > match = (ip4 && tcp && 'M') action = tcp_reject{} > > > > > > > match = (ip6 && tcp && 'M') action = tcp_reject{} > > > > > > > match = (ip4 && 'M') action = icmp4{} > > > > > > > match = (ip6 && 'M') action = icmp6{} > > > > > > > > > > > > > > This approach has a couple of problems: > > > > > > > - ovn-controller can reject the lflows if there are invalid > > > matches. > > > > > > > Eg. If match 'M' is - 'ip4 && udp'. > > > > > > > > > > > > > > - In a large scale deployment, this could result in lot of > > > invalid > > > > > > > logical flows and increase the size of the SB DB. > > > > > > > > > > > > > > This patch addresses this problem by providing an option to the > CMS > > > > > > > to specify the l3 protocol and l4 protocol as hints. A new > column > > > > > > > 'options' is added to the ACL table with the options - > > > > > > > options:l3-protocol and options:l4-protocol. > > > > > > > > > > > > > > ovn-northd will now generate only the required lflows for the > reject > > > > > > > ACL. If no options are set, then it falls back to the default > > > scenario. > > > > > > > > > > > > > > > > > > > Thanks Numan. I believe the solution should work. However, it > seems a > > > > > > little confusing for the end user about how to use the hint > field. I > > > think > > > > > > maybe we should try to avoid the extra field if possible. Here is > my > > > > > > proposal: > > > > > > > > > > > > > > > > Thanks Han for the comments. I do agree if we can avoid the extra > > > option. > > > > > > > > > > > 1. For the tcp v.s. udp check, since we don't want northd to > parse the > > > > > > match condition, we will have to rely on users input. However, > > > instead of a > > > > > > hint, I think it is better to let the user explicitly specify in > the > > > action > > > > > > field. E.g. "reject" means sending icmp, and "tcp_reject" means > > > sending tcp > > > > > > reset if the traffic is tcp and otherwise sending icmp. So, if the > > > user > > > > > > adds an ACL with match include "udp", they will naturally use > "reject" > > > > > > instead of "tcp_reject" because they know it is not possible for > a TCP > > > > > > packet to hit this ACL. If they add an ACL that tcp traffic is > > > expected to > > > > > > match (either TCP only, or general IP traffic), they can use > > > "tcp_reject". > > > > > > Would this be more straightforward than an extra "hint" field? > > > > > > > > > > > > > > > > I have few comments here. > > > > > - If we consider "reject" = "icmp", then we will be breaking the > > > > > backward compatibility. > > > > > Right now, for a reject action, ovn-northd would send tcp_reset > > > > > for tcp traffic and icmp reply or other traffic. > > > > > After your proposed approach, the behaviour would change ? Is > > > > > that OK ? Because existing test cases would fail. > > > > > The proposed patch handles the backward compatibility. Although > > > > > I'm not sure if it is really required in this case. > > > > > > > > > > - For a tcp_reject action, if the match has "tcp", then we will > end > > > > > up adding a logical flow with the icmp action, which is > > > > > really not required. Or do you mean, pinctrl would take the > > > > > decision while handling the "tcp_reject" action to either > > > > > send tcp reset packet or icmp packet ? If so, we can probably > just > > > > > have one action - "reject". Please see below. > > > > > > > > > > > 2. For ip4 v.s. ip6, the idea is to support generic ovn logical > flow > > > > > > actions "tcp_reject" and "icmp" in ovn-controller, which can > handle > > > both > > > > > > ipv4 and ipv6. If this can be supported, the logical flows only > needs > > > to be: > > > > > > match = (tcp && 'M') action = tcp_reject{} > > > > > > match = ('M') action = icmp{} > > > > > > > > > > > > > > > > Ok. In this case we cannot support inner actions unless they are > > > > > independent of the ip version. > > > > > i.e we can't support - tcp_reject { eth.dst <-> eth.src; ip4.dst <-> > > > > > ip4.src; } or > > > > > tcp_reject {eth.dst <-> eth.src; ip6.dst <-> ip6.src;} in one > logical > > > > > flow. ovn-northd has to generate > > > > > 2 logical flows. > > > > > - ip4 && 'M', action = tcp_reject { eth.dst <-> eth.src; ip4.dst > <-> > > > > > ip4.src; } > > > > > - ip6 && 'M', action = tcp_reject { eth.dst <-> eth.src; ip6.dst > <-> > > > > > ip6.src; } > > > > > > > > > > > > > > > Right now for one reject ACL we add the below lflows > > > > > - ip4 && tcp && 'M', action = tcp_reset { eth.dst <-> eth.src; > > > > > ip4.dst <-> ip4.src; outport <-> inport;} > > > > > - ip6 && tcp && 'M', action = tcp_reset { eth.dst <-> eth.src; > > > > > ip6.dst <-> ip6.src; outport <-> inport;} > > > > > - ip4 && 'M' , action = icmp4 {eth.dst <-> eth.src; > > > > > ip4.dst <-> ip4.src; outport <-> inport;} > > > > > - ip6 && 'M' , action = icmp6 {eth.dst <-> eth.src; > > > > > ip6.dst <-> ip6.src; outport <-> inport;} > > > > > > > > > > I have another idea based on your suggestions here: How about we > have > > > > > a new action - reject{} which will be used > > > > > for all reject ACLs and this will > > > > > - send tcp reset packet if the packet is tcp (pinctrl would take > > > > > the decision) > > > > > - send icmp packet otherwise. > > > > > > > > > > We can add the logical flow for a reject ACL in 2 ways > > > > > > > > > > 1. match = M, action = reject { eth.dst <-> eth.src, outport <-> > > > inport;} > > > > > > > > > > OR > > > > > > > > > > 2. match = M, action = reject { eth.dst <-> eth.src, ip.src <-> > > > > > ip.dst; outport <-> inport;} > > > > > > > > > > In (1), pinctrl while handling the reject action, will swap the ip > src > > > > > with ip dst (i.e ip4.dst <-> ip4.src or ip6.dst <-> ip6.src }. > > > > > > > > > > In (2), we will add 2 new OVN fields "ip.src" and "ip.dst" (just > like > > > > > we have icmp4.frag_mtu now) and the action - ip.src <-> ip.dst > > > > > will result in another controller action which will swap the ip src > > > > > and ip dst fields (just like how "icmp4.frag_mtu = 1400" would > result > > > > > into a controller action). > > > > > > > > > > Even though (1) will work, it's not transparent. I would personally > > > > > prefer (2) and I think it's ok if the reject ACL would result in 2 > OF > > > > > controller actions. > > > > > > > > > > With this we will have just one logical flow (instead of 4 ) and > there > > > > > will be no changes on the CMS side. > > > > > > > > > > > Yes, this would be even better. > > > > Thanks. I will work on it. > > > > > > > > > > > > What do you think ? > > > > > > > > > > Thanks > > > > > Numan > > > > > > > > > > > > > > > > I haven't thought through all the details but it seems doable. Did > > > you have > > > > > > any thoughts on this? (If it proves to be unreasonable I am ok > with > > > current > > > > > > "hint" approach) > > > > > > > > > > > > In addition, I found the existing TCP reject handling has a bug > which > > > > > > messes up the user defined ACL priorities. I just posted a patch: > > > > > > > > > > https://patchwork.ozlabs.org/project/ovn/patch/20200928000904.858685-1-hzhou@ovn.org/ > > > > > > It is not directly related to this patch but it would be great if > you > > > could > > > > > > take a look. > > > > > > > > Sure. > > > > > > > With only one lflow, my above fix is not needed. (I am not sure about > > > backporting to old branches.) > > > > I thought about it. Since this issue has been there for a long time > > and no one reported it. Probably its ok to not > > address this for the branches ? > > > Maybe. It seems this feature is not heavily used. Otherwise such issues > should have been reported. I reported another issue related to "reject" but > didn't have time to debug: > https://mail.openvswitch.org/pipermail/ovs-discuss/2020-September/050711.html I didn't notice that this issue is different from the patch you submitted. I thought you're trying to address this issue in your patch. I will test this scenario out and make sure it's addressed. Thanks Numan > > > We could also take the approach of accepting your patch and backport > > to the branches. And we can revert it when I submit the patch > > with the proposed new approach here. > > > I think we can wait for your patch, unless someone complains and requires > an immediate fix. My patch reduces the ACL priority range, which is a risk > of backward compatibility, so I'd rather not apply it if you could work out > the proposed fix here. > > > Thanks > > Numan > > > > > > > > > Thanks > > > > Numan > > > > > > > > > > > > > > > > Thanks, > > > > > > Han > > > > > > > > > > > > > > > > > > > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1876990 > > > > > > > Reported-by: Ilya Maximets <i.maximets@ovn.org> > > > > > > > Signed-off-by: Numan Siddique <numans@ovn.org> > > > > > > > --- > > > > > > > northd/ovn-northd.c | 194 ++++++++++++++++++++---------- > > > > > > > ovn-nb.ovsschema | 7 +- > > > > > > > ovn-nb.xml | 43 +++++++ > > > > > > > tests/ovn-northd.at | 285 > > > ++++++++++++++++++++++++++++++++++++++++++++ > > > > > > > 4 files changed, 461 insertions(+), 68 deletions(-) > > > > > > > > > > > > > > diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c > > > > > > > index 3324c9e81d..d167137e07 100644 > > > > > > > --- a/northd/ovn-northd.c > > > > > > > +++ b/northd/ovn-northd.c > > > > > > > @@ -5372,73 +5372,135 @@ build_reject_acl_rules(struct > ovn_datapath > > > *od, > > > > > > struct hmap *lflows, > > > > > > > struct ds actions = DS_EMPTY_INITIALIZER; > > > > > > > bool ingress = (stage == S_SWITCH_IN_ACL); > > > > > > > > > > > > > > - /* TCP */ > > > > > > > - build_acl_log(&actions, acl); > > > > > > > - if (extra_match->length > 0) { > > > > > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > > > > > - } > > > > > > > - ds_put_format(&match, "ip4 && tcp && (%s)", acl->match); > > > > > > > - ds_put_format(&actions, "reg0 = 0; " > > > > > > > - "eth.dst <-> eth.src; ip4.dst <-> ip4.src; " > > > > > > > - "tcp_reset { outport <-> inport; %s };", > > > > > > > - ingress ? "next(pipeline=egress,table=5);" > > > > > > > - : > "next(pipeline=ingress,table=20);"); > > > > > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > > > > > - acl->priority + OVN_ACL_PRI_OFFSET > + > > > 10, > > > > > > > - ds_cstr(&match), ds_cstr(&actions), > > > > > > stage_hint); > > > > > > > - ds_clear(&match); > > > > > > > - ds_clear(&actions); > > > > > > > - build_acl_log(&actions, acl); > > > > > > > - if (extra_match->length > 0) { > > > > > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > > > > > - } > > > > > > > - ds_put_format(&match, "ip6 && tcp && (%s)", acl->match); > > > > > > > - ds_put_format(&actions, "reg0 = 0; " > > > > > > > - "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > > > > > > - "tcp_reset { outport <-> inport; %s };", > > > > > > > - ingress ? "next(pipeline=egress,table=5);" > > > > > > > - : > "next(pipeline=ingress,table=20);"); > > > > > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > > > > > - acl->priority + OVN_ACL_PRI_OFFSET > + > > > 10, > > > > > > > - ds_cstr(&match), ds_cstr(&actions), > > > > > > stage_hint); > > > > > > > + bool is_ip4 = true; > > > > > > > + bool is_ip6 = true; > > > > > > > + bool tcp_reset = true; > > > > > > > + bool icmp_reset = true; > > > > > > > + bool is_udp = false; > > > > > > > + > > > > > > > + const char *l3_protocol = smap_get(&acl->options, > > > "l3-protocol"); > > > > > > > + if (l3_protocol) { > > > > > > > + if (!strcasecmp(l3_protocol, "ip")) { > > > > > > > + is_ip4 = true; > > > > > > > + is_ip6 = true; > > > > > > > + } else if (!strcasecmp(l3_protocol, "ip4")) { > > > > > > > + is_ip4 = true; > > > > > > > + is_ip6 = false; > > > > > > > + } else if (!strcasecmp(l3_protocol, "ip6")) { > > > > > > > + is_ip6 = true; > > > > > > > + is_ip4 = false; > > > > > > > + } > > > > > > > + } > > > > > > > + > > > > > > > + const char *l4_protocol = smap_get(&acl->options, > > > "l4-protocol"); > > > > > > > + if (l4_protocol) { > > > > > > > + if (!strcasecmp(l4_protocol, "tcp")) { > > > > > > > + tcp_reset = true; > > > > > > > + icmp_reset = false; > > > > > > > + } else if (!strcasecmp(l4_protocol, "udp")) { > > > > > > > + tcp_reset = false; > > > > > > > + is_udp = true; > > > > > > > + } else { > > > > > > > + tcp_reset = false; > > > > > > > + } > > > > > > > + } > > > > > > > > > > > > > > - /* IP traffic */ > > > > > > > - ds_clear(&match); > > > > > > > - ds_clear(&actions); > > > > > > > - build_acl_log(&actions, acl); > > > > > > > - if (extra_match->length > 0) { > > > > > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > > > > > - } > > > > > > > - ds_put_format(&match, "ip4 && (%s)", acl->match); > > > > > > > - if (extra_actions->length > 0) { > > > > > > > - ds_put_format(&actions, "%s ", extra_actions->string); > > > > > > > - } > > > > > > > - ds_put_format(&actions, "reg0 = 0; " > > > > > > > - "icmp4 { eth.dst <-> eth.src; ip4.dst <-> > > > ip4.src; " > > > > > > > - "outport <-> inport; %s };", > > > > > > > - ingress ? "next(pipeline=egress,table=5);" > > > > > > > - : > "next(pipeline=ingress,table=20);"); > > > > > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > > > > > - acl->priority + OVN_ACL_PRI_OFFSET, > > > > > > > - ds_cstr(&match), ds_cstr(&actions), > > > > > > stage_hint); > > > > > > > - ds_clear(&match); > > > > > > > - ds_clear(&actions); > > > > > > > - build_acl_log(&actions, acl); > > > > > > > - if (extra_match->length > 0) { > > > > > > > - ds_put_format(&match, "(%s) && ", extra_match->string); > > > > > > > - } > > > > > > > - ds_put_format(&match, "ip6 && (%s)", acl->match); > > > > > > > - if (extra_actions->length > 0) { > > > > > > > - ds_put_format(&actions, "%s ", extra_actions->string); > > > > > > > - } > > > > > > > - ds_put_format(&actions, "reg0 = 0; icmp6 { " > > > > > > > - "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > > > > > > > - "outport <-> inport; %s };", > > > > > > > - ingress ? "next(pipeline=egress,table=5);" > > > > > > > - : > "next(pipeline=ingress,table=20);"); > > > > > > > - ovn_lflow_add_with_hint(lflows, od, stage, > > > > > > > - acl->priority + OVN_ACL_PRI_OFFSET, > > > > > > > - ds_cstr(&match), ds_cstr(&actions), > > > > > > stage_hint); > > > > > > > + if (is_ip4) { > > > > > > > + if (tcp_reset) { > > > > > > > + build_acl_log(&actions, acl); > > > > > > > + if (extra_match->length > 0) { > > > > > > > + ds_put_format(&match, "(%s) && ", > > > extra_match->string); > > > > > > > + } > > > > > > > + ds_put_format(&match, "ip4 && tcp && (%s)", > > > acl->match); > > > > > > > + if (extra_actions->length > 0) { > > > > > > > + ds_put_format(&actions, "%s ", > > > extra_actions->string); > > > > > > > + } > > > > > > > + ds_put_format(&actions, "reg0 = 0; " > > > > > > > + "eth.dst <-> eth.src; ip4.dst <-> > > > ip4.src; " > > > > > > > + "tcp_reset { outport <-> inport; %s > };", > > > > > > > + ingress ? > > > "next(pipeline=egress,table=5);" > > > > > > > + : > > > "next(pipeline=ingress,table=20);"); > > > > > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > > > > > + acl->priority + > > > OVN_ACL_PRI_OFFSET + > > > > > > 10, > > > > > > > + ds_cstr(&match), > > > ds_cstr(&actions), > > > > > > > + stage_hint); > > > > > > > + } > > > > > > > + > > > > > > > + if (icmp_reset) { > > > > > > > + ds_clear(&match); > > > > > > > + ds_clear(&actions); > > > > > > > + build_acl_log(&actions, acl); > > > > > > > + if (extra_match->length > 0) { > > > > > > > + ds_put_format(&match, "(%s) && ", > > > extra_match->string); > > > > > > > + } > > > > > > > + ds_put_format(&match, "ip4 && (%s)", acl->match); > > > > > > > + if (is_udp) { > > > > > > > + ds_put_cstr(&match, " && udp"); > > > > > > > + } > > > > > > > + if (extra_actions->length > 0) { > > > > > > > + ds_put_format(&actions, "%s ", > > > extra_actions->string); > > > > > > > + } > > > > > > > + ds_put_format(&actions, "reg0 = 0; " > > > > > > > + "icmp4 { eth.dst <-> eth.src; > ip4.dst <-> > > > > > > ip4.src; " > > > > > > > + "outport <-> inport; %s };", > > > > > > > + ingress ? > > > "next(pipeline=egress,table=5);" > > > > > > > + : > > > "next(pipeline=ingress,table=20);"); > > > > > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > > > > > + acl->priority + > > > OVN_ACL_PRI_OFFSET, > > > > > > > + ds_cstr(&match), > > > ds_cstr(&actions), > > > > > > > + stage_hint); > > > > > > > + } > > > > > > > + } > > > > > > > + > > > > > > > + if (is_ip6) { > > > > > > > + if (tcp_reset) { > > > > > > > + ds_clear(&match); > > > > > > > + ds_clear(&actions); > > > > > > > + build_acl_log(&actions, acl); > > > > > > > + if (extra_match->length > 0) { > > > > > > > + ds_put_format(&match, "(%s) && ", > > > extra_match->string); > > > > > > > + } > > > > > > > + ds_put_format(&match, "ip6 && tcp && (%s)", > > > acl->match); > > > > > > > + if (extra_actions->length > 0) { > > > > > > > + ds_put_format(&actions, "%s ", > > > extra_actions->string); > > > > > > > + } > > > > > > > + ds_put_format(&actions, "reg0 = 0; " > > > > > > > + "eth.dst <-> eth.src; ip6.dst <-> > > > ip6.src; " > > > > > > > + "tcp_reset { outport <-> inport; %s > };", > > > > > > > + ingress ? > > > "next(pipeline=egress,table=5);" > > > > > > > + : > > > "next(pipeline=ingress,table=20);"); > > > > > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > > > > > + acl->priority + > > > OVN_ACL_PRI_OFFSET + > > > > > > 10, > > > > > > > + ds_cstr(&match), > > > ds_cstr(&actions), > > > > > > > + stage_hint); > > > > > > > + } > > > > > > > + > > > > > > > + if (icmp_reset) { > > > > > > > + ds_clear(&match); > > > > > > > + ds_clear(&actions); > > > > > > > + build_acl_log(&actions, acl); > > > > > > > + if (extra_match->length > 0) { > > > > > > > + ds_put_format(&match, "(%s) && ", > > > extra_match->string); > > > > > > > + } > > > > > > > + ds_put_format(&match, "ip6 && (%s)", acl->match); > > > > > > > + if (is_udp) { > > > > > > > + ds_put_cstr(&match, " && udp"); > > > > > > > + } > > > > > > > + > > > > > > > + if (extra_actions->length > 0) { > > > > > > > + ds_put_format(&actions, "%s ", > > > extra_actions->string); > > > > > > > + } > > > > > > > + ds_put_format(&actions, "reg0 = 0; icmp6 { " > > > > > > > + "eth.dst <-> eth.src; ip6.dst <-> > > > ip6.src; " > > > > > > > + "outport <-> inport; %s };", > > > > > > > + ingress ? > > > "next(pipeline=egress,table=5);" > > > > > > > + : > > > "next(pipeline=ingress,table=20);"); > > > > > > > + ovn_lflow_add_with_hint(lflows, od, stage, > > > > > > > + acl->priority + > > > OVN_ACL_PRI_OFFSET, > > > > > > > + ds_cstr(&match), > > > ds_cstr(&actions), > > > > > > > + stage_hint); > > > > > > > + } > > > > > > > + } > > > > > > > > > > > > > > ds_destroy(&match); > > > > > > > ds_destroy(&actions); > > > > > > > diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema > > > > > > > index 092322ab2c..00f1c7cd4b 100644 > > > > > > > --- a/ovn-nb.ovsschema > > > > > > > +++ b/ovn-nb.ovsschema > > > > > > > @@ -1,7 +1,7 @@ > > > > > > > { > > > > > > > "name": "OVN_Northbound", > > > > > > > - "version": "5.27.0", > > > > > > > - "cksum": "3507518247 26773", > > > > > > > + "version": "5.28.0", > > > > > > > + "cksum": "699859908 26928", > > > > > > > "tables": { > > > > > > > "NB_Global": { > > > > > > > "columns": { > > > > > > > @@ -225,6 +225,9 @@ > > > > > > > > "debug"]]}, > > > > > > > "min": 0, "max": 1}}, > > > > > > > "meter": {"type": {"key": "string", "min": 0, > > > "max": 1}}, > > > > > > > + "options": { > > > > > > > + "type": {"key": "string", "value": > "string", > > > > > > > + "min": 0, "max": "unlimited"}}, > > > > > > > "external_ids": { > > > > > > > "type": {"key": "string", "value": > "string", > > > > > > > "min": 0, "max": "unlimited"}}}, > > > > > > > diff --git a/ovn-nb.xml b/ovn-nb.xml > > > > > > > index 86195af341..2c3497e2ae 100644 > > > > > > > --- a/ovn-nb.xml > > > > > > > +++ b/ovn-nb.xml > > > > > > > @@ -1721,6 +1721,49 @@ > > > > > > > </ul> > > > > > > > </column> > > > > > > > > > > > > > > + <group title="Common options"> > > > > > > > + <column name="options"> > > > > > > > + This column provides general key/value settings. The > > > supported > > > > > > > + options are described individually below. > > > > > > > + </column> > > > > > > > + > > > > > > > + <group title="Options for providing protocol hints for > reject > > > > > > ACL."> > > > > > > > + <p> > > > > > > > + The ACL match specified in the > > > > > > > + <ref column="match" table="ACL" db="OVN_Northbound"/> > > > column is > > > > > > > + opaque to <code>OVN</code> and > <code>ovn-northd</code> > > > doesn't > > > > > > > + look into the match fields. > > > > > > > + These options can be specified by CMS to provide > hints to > > > > > > > + <code>OVN</code> about the L3 and L4 protocol matches > > > for the > > > > > > reject > > > > > > > + ACL. <code>ovn-northd</code> uses these options if > set > > > to use > > > > > > > + appropriate actions when generating logical flows. > > > > > > > + </p> > > > > > > > + > > > > > > > + <p> > > > > > > > + If these options are not set, then > > > <code>ovn-northd</code> > > > > > > assumes > > > > > > > + the reject ACL applies to IPv4, IPv6 and TCP packets. > > > > > > > + </p> > > > > > > > + > > > > > > > + <column name="options" key="l3-protocol"> > > > > > > > + The possible values are <code>ip</code>, > > > <code>ip4</code> and > > > > > > > + <code>ip6</code>. If the value is <code>ip</code>, it > > > means the > > > > > > > + reject ACL action applies to both IPv4 and IPv6 > packets. > > > If the > > > > > > > + value is <code>ip4</code>, it means the reject ACL > action > > > > > > applies to > > > > > > > + IPv4 packets and the value <code>ip6</code> applies > to > > > IPv6 > > > > > > packets. > > > > > > > + </column> > > > > > > > + > > > > > > > + <column name="options" key="l4-protocol"> > > > > > > > + <p> > > > > > > > + The possible values are <code>tcp</code> and > > > > > > <code>udp</code>. > > > > > > > + If the value is <code>tcp</code>, it means the > > > > > > > + reject ACL action applies to TCP packets. If the > > > > > > > + value is <code>udp</code>, it means the reject ACL > > > action > > > > > > applies > > > > > > > + to UDP packets. > > > > > > > + </p> > > > > > > > + </column> > > > > > > > + </group> > > > > > > > + </group> > > > > > > > + > > > > > > > <group title="Logging"> > > > > > > > <p> > > > > > > > These columns control whether and how OVN logs packets > that > > > > > > match an > > > > > > > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at > > > > > > > index 99a9204f1f..4a30f8ed07 100644 > > > > > > > --- a/tests/ovn-northd.at > > > > > > > +++ b/tests/ovn-northd.at > > > > > > > @@ -2010,3 +2010,288 @@ ovn-nbctl --wait=sb set NB_Global . > > > > > > options:ignore_lsp_down=true > > > > > > > AT_CHECK([ovn-sbctl lflow-list | grep arp | grep 10\.0\.0\.1], > [0], > > > > > > [ignore]) > > > > > > > > > > > > > > AT_CLEANUP > > > > > > > + > > > > > > > +AT_SETUP([ovn-northd -- ACL reject flows]) > > > > > > > +ovn_start > > > > > > > + > > > > > > > +ovn-nbctl ls-add sw0 > > > > > > > +ovn-nbctl lsp-add sw0 sw0-p1 > > > > > > > +ovn-nbctl lsp-add sw0 sw0-p2 > > > > > > > + > > > > > > > +ovn-nbctl pg-add pg0 sw0-p1 sw0-p2 > > > > > > > +ovn-nbctl acl-add pg0 to-lport 1002 "inport == @pg0 && ip" > reject > > > > > > > + > > > > > > > +ovn-nbctl --wait=sb sync > > > > > > > + > > > > > > > +# If there is a reject ACL wihtout any protocol hints, then > > > ovn-northd > > > > > > should > > > > > > > +# generate lflows with ip4 tcp_reset, icmp4, ip6 tcp_reset and > > > icmp6 > > > > > > actions. > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2012" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > tcp_reset { > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > tcp_reset { > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2002" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> > ip4.src; > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> > ip6.src; > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +# Set l3-protocol=ip4 for the reject ACL. > > > > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip4 > > > > > > > + > > > > > > > +# ovn-northd should generate 2 lflows with ip4 tcp_reset and > icmp4 > > > > > > actions. > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2012" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > tcp_reset { > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2002" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> > ip4.src; > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +# Set l4-protocol=tcp for the reject ACL. > > > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > > > > > > + > > > > > > > +# ovn-northd should generate 1 lflow with ip4 tcp_reset action. > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2012" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > tcp_reset { > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2002" | > > > > > > sort], [0], [dnl > > > > > > > +]) > > > > > > > + > > > > > > > +# Set l4-protocol=udp for the reject ACL. > > > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > > > > > > + > > > > > > > +# ovn-northd should generate 1 lflow with udp match and icmp4 > > > action. > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2012" | > > > > > > sort], [0], [dnl > > > > > > > +]) > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2002" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=(ip4 && (inport == @pg0 && ip) && udp), dnl > > > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> > ip4.src; > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +# Remove l4-protocol from the reject ACL. > > > > > > > +ovn-nbctl --wait=sb remove ACL . options l4-protocol > > > > > > > + > > > > > > > +# ovn-northd should generate 2 lflow with tcp_reset and icmp4 > > > action. > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2012" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > tcp_reset { > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2002" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> > ip4.src; > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +# Set l3-protocol to ip. > > > > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > > > > > > + > > > > > > > +# ovn-northd should generate 4 lflow with ip4 tcp_reset, ip6 > > > tcp_reset, > > > > > > icmp4 and icmp6 actions. > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2012" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > tcp_reset { > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > tcp_reset { > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2002" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=(ip4 && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> > ip4.src; > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> > ip6.src; > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +# Set l3-protocol=ip6 for the reject ACL. > > > > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip6 > > > > > > > + > > > > > > > +# ovn-northd should generate 2 lflows with ip6 tcp_reset and > icmp6 > > > > > > actions. > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2012" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > tcp_reset { > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2002" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=(ip6 && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> > ip6.src; > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +# Set l4-protocol=tcp for the reject ACL. > > > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > > > > > > + > > > > > > > +# ovn-northd should generate 1 lflow with ip6 tcp_reset action. > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2012" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > tcp_reset { > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2002" | > > > > > > sort], [0], [dnl > > > > > > > +]) > > > > > > > + > > > > > > > +# Set l4-protocol=udp for the reject ACL. > > > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > > > > > > + > > > > > > > +# ovn-northd should generate 1 lflow with udp match and icmp6 > > > action. > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2012" | > > > > > > sort], [0], [dnl > > > > > > > +]) > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2002" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=(ip6 && (inport == @pg0 && ip) && udp), dnl > > > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> > ip6.src; > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL. > > > > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp > > > > > > > + > > > > > > > +# ovn-northd should generate 2 lflow with ip4 tcp_reset and ip6 > > > > > > tcp_reset actions. > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2012" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > tcp_reset { > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl > > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > tcp_reset { > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2002" | > > > > > > sort], [0], [dnl > > > > > > > +]) > > > > > > > + > > > > > > > +# Set l3-protocol to ip and l4-protocol=udp for the reject ACL. > > > > > > > +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip > > > > > > > +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp > > > > > > > + > > > > > > > +# ovn-northd should generate 2 lflows (udp match) with icmp4 > and > > > icmp6 > > > > > > actions. > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2012" | > > > > > > sort], [0], [dnl > > > > > > > +]) > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2002" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=(ip4 && (inport == @pg0 && ip) && udp), dnl > > > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> > ip4.src; > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=(ip6 && (inport == @pg0 && ip) && udp), dnl > > > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> > ip6.src; > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +# Add an ACL with allow-related > > > > > > > +ovn-nbctl --wait=sb acl-add pg0 to-lport 1000 "ip" > allow-related > > > > > > > + > > > > > > > +# ovn-northd should generate 4 lflow with 2 icmp4 and 2 icmp6 > > > actions. > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2012" | > > > > > > sort], [0], [dnl > > > > > > > +]) > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2002" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && > udp), > > > dnl\ > > > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp4 { > > > eth.dst > > > > > > <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; > > > > > > next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && > udp), > > > dnl > > > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp6 { > > > eth.dst > > > > > > <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; > > > > > > next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && > udp), > > > dnl > > > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> > ip4.src; > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && > udp), > > > dnl > > > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> > ip6.src; > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL. > > > > > > > +rej_acl=$(ovn-nbctl --bare --columns _uuid find ACL > action=reject) > > > > > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l3-protocol=ip > > > > > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp > > > > > > > + > > > > > > > +# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and > 2 ip6 > > > > > > tcp_reset actions. > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2012" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && > ip)), > > > dnl > > > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; > eth.dst <-> > > > > > > eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; > > > > > > next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && > ip)), > > > dnl > > > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; > eth.dst <-> > > > > > > eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; > > > > > > next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && > ip)), > > > dnl > > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > tcp_reset { > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && > ip)), > > > dnl > > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > tcp_reset { > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2002" | > > > > > > sort], [0], [dnl > > > > > > > +]) > > > > > > > + > > > > > > > + > > > > > > > +# Clear l3-protocol and set l4-protocol to udp > > > > > > > +ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol > > > > > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=udp > > > > > > > + > > > > > > > +# ovn-northd should generate 4 lflows (with udp match) with 2 > > > icmp4 and > > > > > > 2 icmp6 actions. > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2012" | > > > > > > sort], [0], [dnl > > > > > > > +]) > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2002" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && > udp), > > > dnl\ > > > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp4 { > > > eth.dst > > > > > > <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; > > > > > > next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && > udp), > > > dnl > > > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp6 { > > > eth.dst > > > > > > <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; > > > > > > next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && > udp), > > > dnl > > > > > > > +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> > ip4.src; > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2002 , dnl > > > > > > > +match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && > udp), > > > dnl > > > > > > > +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> > ip6.src; > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +# Clear l3-protocol and set l4-protocol to tcp > > > > > > > +ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol > > > > > > > +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp > > > > > > > + > > > > > > > +# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and > 2 ip6 > > > > > > tcp_reset actions. > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2012" | > > > > > > sort], [0], [dnl > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && > ip)), > > > dnl > > > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; > eth.dst <-> > > > > > > eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; > > > > > > next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && > ip)), > > > dnl > > > > > > > +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; > eth.dst <-> > > > > > > eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; > > > > > > next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && > ip)), > > > dnl > > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; > > > tcp_reset { > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > + table=5 (ls_out_acl ), priority=2012 , dnl > > > > > > > +match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && > ip)), > > > dnl > > > > > > > +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; > > > tcp_reset { > > > > > > outport <-> inport; next(pipeline=ingress,table=20); };) > > > > > > > +]) > > > > > > > + > > > > > > > +AT_CHECK([ovn-sbctl lflow-list | grep > "ls_out_acl.*priority=2002" | > > > > > > sort], [0], [dnl > > > > > > > +]) > > > > > > > + > > > > > > > +AT_CLEANUP > > > > > > > -- > > > > > > > 2.26.2 > > > > > > > > > > > > > > _______________________________________________ > > > > > > > dev mailing list > > > > > > > dev@openvswitch.org > > > > > > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > > > > > _______________________________________________ > > > > > > dev mailing list > > > > > > dev@openvswitch.org > > > > > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > > > > > > > > _______________________________________________ > > > dev mailing list > > > dev@openvswitch.org > > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev >
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 3324c9e81d..d167137e07 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -5372,73 +5372,135 @@ build_reject_acl_rules(struct ovn_datapath *od, struct hmap *lflows, struct ds actions = DS_EMPTY_INITIALIZER; bool ingress = (stage == S_SWITCH_IN_ACL); - /* TCP */ - build_acl_log(&actions, acl); - if (extra_match->length > 0) { - ds_put_format(&match, "(%s) && ", extra_match->string); - } - ds_put_format(&match, "ip4 && tcp && (%s)", acl->match); - ds_put_format(&actions, "reg0 = 0; " - "eth.dst <-> eth.src; ip4.dst <-> ip4.src; " - "tcp_reset { outport <-> inport; %s };", - ingress ? "next(pipeline=egress,table=5);" - : "next(pipeline=ingress,table=20);"); - ovn_lflow_add_with_hint(lflows, od, stage, - acl->priority + OVN_ACL_PRI_OFFSET + 10, - ds_cstr(&match), ds_cstr(&actions), stage_hint); - ds_clear(&match); - ds_clear(&actions); - build_acl_log(&actions, acl); - if (extra_match->length > 0) { - ds_put_format(&match, "(%s) && ", extra_match->string); - } - ds_put_format(&match, "ip6 && tcp && (%s)", acl->match); - ds_put_format(&actions, "reg0 = 0; " - "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " - "tcp_reset { outport <-> inport; %s };", - ingress ? "next(pipeline=egress,table=5);" - : "next(pipeline=ingress,table=20);"); - ovn_lflow_add_with_hint(lflows, od, stage, - acl->priority + OVN_ACL_PRI_OFFSET + 10, - ds_cstr(&match), ds_cstr(&actions), stage_hint); + bool is_ip4 = true; + bool is_ip6 = true; + bool tcp_reset = true; + bool icmp_reset = true; + bool is_udp = false; + + const char *l3_protocol = smap_get(&acl->options, "l3-protocol"); + if (l3_protocol) { + if (!strcasecmp(l3_protocol, "ip")) { + is_ip4 = true; + is_ip6 = true; + } else if (!strcasecmp(l3_protocol, "ip4")) { + is_ip4 = true; + is_ip6 = false; + } else if (!strcasecmp(l3_protocol, "ip6")) { + is_ip6 = true; + is_ip4 = false; + } + } + + const char *l4_protocol = smap_get(&acl->options, "l4-protocol"); + if (l4_protocol) { + if (!strcasecmp(l4_protocol, "tcp")) { + tcp_reset = true; + icmp_reset = false; + } else if (!strcasecmp(l4_protocol, "udp")) { + tcp_reset = false; + is_udp = true; + } else { + tcp_reset = false; + } + } - /* IP traffic */ - ds_clear(&match); - ds_clear(&actions); - build_acl_log(&actions, acl); - if (extra_match->length > 0) { - ds_put_format(&match, "(%s) && ", extra_match->string); - } - ds_put_format(&match, "ip4 && (%s)", acl->match); - if (extra_actions->length > 0) { - ds_put_format(&actions, "%s ", extra_actions->string); - } - ds_put_format(&actions, "reg0 = 0; " - "icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; " - "outport <-> inport; %s };", - ingress ? "next(pipeline=egress,table=5);" - : "next(pipeline=ingress,table=20);"); - ovn_lflow_add_with_hint(lflows, od, stage, - acl->priority + OVN_ACL_PRI_OFFSET, - ds_cstr(&match), ds_cstr(&actions), stage_hint); - ds_clear(&match); - ds_clear(&actions); - build_acl_log(&actions, acl); - if (extra_match->length > 0) { - ds_put_format(&match, "(%s) && ", extra_match->string); - } - ds_put_format(&match, "ip6 && (%s)", acl->match); - if (extra_actions->length > 0) { - ds_put_format(&actions, "%s ", extra_actions->string); - } - ds_put_format(&actions, "reg0 = 0; icmp6 { " - "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " - "outport <-> inport; %s };", - ingress ? "next(pipeline=egress,table=5);" - : "next(pipeline=ingress,table=20);"); - ovn_lflow_add_with_hint(lflows, od, stage, - acl->priority + OVN_ACL_PRI_OFFSET, - ds_cstr(&match), ds_cstr(&actions), stage_hint); + if (is_ip4) { + if (tcp_reset) { + build_acl_log(&actions, acl); + if (extra_match->length > 0) { + ds_put_format(&match, "(%s) && ", extra_match->string); + } + ds_put_format(&match, "ip4 && tcp && (%s)", acl->match); + if (extra_actions->length > 0) { + ds_put_format(&actions, "%s ", extra_actions->string); + } + ds_put_format(&actions, "reg0 = 0; " + "eth.dst <-> eth.src; ip4.dst <-> ip4.src; " + "tcp_reset { outport <-> inport; %s };", + ingress ? "next(pipeline=egress,table=5);" + : "next(pipeline=ingress,table=20);"); + ovn_lflow_add_with_hint(lflows, od, stage, + acl->priority + OVN_ACL_PRI_OFFSET + 10, + ds_cstr(&match), ds_cstr(&actions), + stage_hint); + } + + if (icmp_reset) { + ds_clear(&match); + ds_clear(&actions); + build_acl_log(&actions, acl); + if (extra_match->length > 0) { + ds_put_format(&match, "(%s) && ", extra_match->string); + } + ds_put_format(&match, "ip4 && (%s)", acl->match); + if (is_udp) { + ds_put_cstr(&match, " && udp"); + } + if (extra_actions->length > 0) { + ds_put_format(&actions, "%s ", extra_actions->string); + } + ds_put_format(&actions, "reg0 = 0; " + "icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; " + "outport <-> inport; %s };", + ingress ? "next(pipeline=egress,table=5);" + : "next(pipeline=ingress,table=20);"); + ovn_lflow_add_with_hint(lflows, od, stage, + acl->priority + OVN_ACL_PRI_OFFSET, + ds_cstr(&match), ds_cstr(&actions), + stage_hint); + } + } + + if (is_ip6) { + if (tcp_reset) { + ds_clear(&match); + ds_clear(&actions); + build_acl_log(&actions, acl); + if (extra_match->length > 0) { + ds_put_format(&match, "(%s) && ", extra_match->string); + } + ds_put_format(&match, "ip6 && tcp && (%s)", acl->match); + if (extra_actions->length > 0) { + ds_put_format(&actions, "%s ", extra_actions->string); + } + ds_put_format(&actions, "reg0 = 0; " + "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " + "tcp_reset { outport <-> inport; %s };", + ingress ? "next(pipeline=egress,table=5);" + : "next(pipeline=ingress,table=20);"); + ovn_lflow_add_with_hint(lflows, od, stage, + acl->priority + OVN_ACL_PRI_OFFSET + 10, + ds_cstr(&match), ds_cstr(&actions), + stage_hint); + } + + if (icmp_reset) { + ds_clear(&match); + ds_clear(&actions); + build_acl_log(&actions, acl); + if (extra_match->length > 0) { + ds_put_format(&match, "(%s) && ", extra_match->string); + } + ds_put_format(&match, "ip6 && (%s)", acl->match); + if (is_udp) { + ds_put_cstr(&match, " && udp"); + } + + if (extra_actions->length > 0) { + ds_put_format(&actions, "%s ", extra_actions->string); + } + ds_put_format(&actions, "reg0 = 0; icmp6 { " + "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " + "outport <-> inport; %s };", + ingress ? "next(pipeline=egress,table=5);" + : "next(pipeline=ingress,table=20);"); + ovn_lflow_add_with_hint(lflows, od, stage, + acl->priority + OVN_ACL_PRI_OFFSET, + ds_cstr(&match), ds_cstr(&actions), + stage_hint); + } + } ds_destroy(&match); ds_destroy(&actions); diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema index 092322ab2c..00f1c7cd4b 100644 --- a/ovn-nb.ovsschema +++ b/ovn-nb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Northbound", - "version": "5.27.0", - "cksum": "3507518247 26773", + "version": "5.28.0", + "cksum": "699859908 26928", "tables": { "NB_Global": { "columns": { @@ -225,6 +225,9 @@ "debug"]]}, "min": 0, "max": 1}}, "meter": {"type": {"key": "string", "min": 0, "max": 1}}, + "options": { + "type": {"key": "string", "value": "string", + "min": 0, "max": "unlimited"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, diff --git a/ovn-nb.xml b/ovn-nb.xml index 86195af341..2c3497e2ae 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -1721,6 +1721,49 @@ </ul> </column> + <group title="Common options"> + <column name="options"> + This column provides general key/value settings. The supported + options are described individually below. + </column> + + <group title="Options for providing protocol hints for reject ACL."> + <p> + The ACL match specified in the + <ref column="match" table="ACL" db="OVN_Northbound"/> column is + opaque to <code>OVN</code> and <code>ovn-northd</code> doesn't + look into the match fields. + These options can be specified by CMS to provide hints to + <code>OVN</code> about the L3 and L4 protocol matches for the reject + ACL. <code>ovn-northd</code> uses these options if set to use + appropriate actions when generating logical flows. + </p> + + <p> + If these options are not set, then <code>ovn-northd</code> assumes + the reject ACL applies to IPv4, IPv6 and TCP packets. + </p> + + <column name="options" key="l3-protocol"> + The possible values are <code>ip</code>, <code>ip4</code> and + <code>ip6</code>. If the value is <code>ip</code>, it means the + reject ACL action applies to both IPv4 and IPv6 packets. If the + value is <code>ip4</code>, it means the reject ACL action applies to + IPv4 packets and the value <code>ip6</code> applies to IPv6 packets. + </column> + + <column name="options" key="l4-protocol"> + <p> + The possible values are <code>tcp</code> and <code>udp</code>. + If the value is <code>tcp</code>, it means the + reject ACL action applies to TCP packets. If the + value is <code>udp</code>, it means the reject ACL action applies + to UDP packets. + </p> + </column> + </group> + </group> + <group title="Logging"> <p> These columns control whether and how OVN logs packets that match an diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 99a9204f1f..4a30f8ed07 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -2010,3 +2010,288 @@ ovn-nbctl --wait=sb set NB_Global . options:ignore_lsp_down=true AT_CHECK([ovn-sbctl lflow-list | grep arp | grep 10\.0\.0\.1], [0], [ignore]) AT_CLEANUP + +AT_SETUP([ovn-northd -- ACL reject flows]) +ovn_start + +ovn-nbctl ls-add sw0 +ovn-nbctl lsp-add sw0 sw0-p1 +ovn-nbctl lsp-add sw0 sw0-p2 + +ovn-nbctl pg-add pg0 sw0-p1 sw0-p2 +ovn-nbctl acl-add pg0 to-lport 1002 "inport == @pg0 && ip" reject + +ovn-nbctl --wait=sb sync + +# If there is a reject ACL wihtout any protocol hints, then ovn-northd should +# generate lflows with ip4 tcp_reset, icmp4, ip6 tcp_reset and icmp6 actions. + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2012 , dnl +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2012 , dnl +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2002 , dnl +match=(ip4 && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2002 , dnl +match=(ip6 && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +# Set l3-protocol=ip4 for the reject ACL. +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip4 + +# ovn-northd should generate 2 lflows with ip4 tcp_reset and icmp4 actions. +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2012 , dnl +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2002 , dnl +match=(ip4 && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +# Set l4-protocol=tcp for the reject ACL. +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp + +# ovn-northd should generate 1 lflow with ip4 tcp_reset action. +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2012 , dnl +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl +]) + +# Set l4-protocol=udp for the reject ACL. +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp + +# ovn-northd should generate 1 lflow with udp match and icmp4 action. +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl +]) + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2002 , dnl +match=(ip4 && (inport == @pg0 && ip) && udp), dnl +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +# Remove l4-protocol from the reject ACL. +ovn-nbctl --wait=sb remove ACL . options l4-protocol + +# ovn-northd should generate 2 lflow with tcp_reset and icmp4 action. +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2012 , dnl +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2002 , dnl +match=(ip4 && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +# Set l3-protocol to ip. +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip + +# ovn-northd should generate 4 lflow with ip4 tcp_reset, ip6 tcp_reset, icmp4 and icmp6 actions. + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2012 , dnl +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2012 , dnl +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2002 , dnl +match=(ip4 && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2002 , dnl +match=(ip6 && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +# Set l3-protocol=ip6 for the reject ACL. +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip6 + +# ovn-northd should generate 2 lflows with ip6 tcp_reset and icmp6 actions. +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2012 , dnl +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2002 , dnl +match=(ip6 && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +# Set l4-protocol=tcp for the reject ACL. +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp + +# ovn-northd should generate 1 lflow with ip6 tcp_reset action. +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2012 , dnl +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl +]) + +# Set l4-protocol=udp for the reject ACL. +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp + +# ovn-northd should generate 1 lflow with udp match and icmp6 action. +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl +]) + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2002 , dnl +match=(ip6 && (inport == @pg0 && ip) && udp), dnl +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL. +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip +ovn-nbctl --wait=sb set ACL . options:l4-protocol=tcp + +# ovn-northd should generate 2 lflow with ip4 tcp_reset and ip6 tcp_reset actions. +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2012 , dnl +match=(ip4 && tcp && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2012 , dnl +match=(ip6 && tcp && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl +]) + +# Set l3-protocol to ip and l4-protocol=udp for the reject ACL. +ovn-nbctl --wait=sb set ACL . options:l3-protocol=ip +ovn-nbctl --wait=sb set ACL . options:l4-protocol=udp + +# ovn-northd should generate 2 lflows (udp match) with icmp4 and icmp6 actions. +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl +]) + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2002 , dnl +match=(ip4 && (inport == @pg0 && ip) && udp), dnl +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2002 , dnl +match=(ip6 && (inport == @pg0 && ip) && udp), dnl +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +# Add an ACL with allow-related +ovn-nbctl --wait=sb acl-add pg0 to-lport 1000 "ip" allow-related + +# ovn-northd should generate 4 lflow with 2 icmp4 and 2 icmp6 actions. +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl +]) + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2002 , dnl +match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl\ +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2002 , dnl +match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2002 , dnl +match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2002 , dnl +match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +# Set l3-protocol to ip and l4-protocol=tcp for the reject ACL. +rej_acl=$(ovn-nbctl --bare --columns _uuid find ACL action=reject) +ovn-nbctl --wait=sb set ACL $rej_acl options:l3-protocol=ip +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp + +# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and 2 ip6 tcp_reset actions. +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2012 , dnl +match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2012 , dnl +match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2012 , dnl +match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2012 , dnl +match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl +]) + + +# Clear l3-protocol and set l4-protocol to udp +ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=udp + +# ovn-northd should generate 4 lflows (with udp match) with 2 icmp4 and 2 icmp6 actions. +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl +]) + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2002 , dnl +match=((reg0[[10]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl\ +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2002 , dnl +match=((reg0[[10]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2002 , dnl +match=((reg0[[9]] == 1) && ip4 && (inport == @pg0 && ip) && udp), dnl +action=(reg0 = 0; icmp4 { eth.dst <-> eth.src; ip4.dst <-> ip4.src; outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2002 , dnl +match=((reg0[[9]] == 1) && ip6 && (inport == @pg0 && ip) && udp), dnl +action=(reg0 = 0; icmp6 { eth.dst <-> eth.src; ip6.dst <-> ip6.src; outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +# Clear l3-protocol and set l4-protocol to tcp +ovn-nbctl --wait=sb remove ACL $rej_acl options l3-protocol +ovn-nbctl --wait=sb set ACL $rej_acl options:l4-protocol=tcp + +# ovn-northd should generate 4 lflow with 2 ip4 tcp_reset and 2 ip6 tcp_reset actions. +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2012" | sort], [0], [dnl + table=5 (ls_out_acl ), priority=2012 , dnl +match=((reg0[[10]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2012 , dnl +match=((reg0[[10]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl +action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2012 , dnl +match=((reg0[[9]] == 1) && ip4 && tcp && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; eth.dst <-> eth.src; ip4.dst <-> ip4.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) + table=5 (ls_out_acl ), priority=2012 , dnl +match=((reg0[[9]] == 1) && ip6 && tcp && (inport == @pg0 && ip)), dnl +action=(reg0 = 0; eth.dst <-> eth.src; ip6.dst <-> ip6.src; tcp_reset { outport <-> inport; next(pipeline=ingress,table=20); };) +]) + +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_acl.*priority=2002" | sort], [0], [dnl +]) + +AT_CLEANUP