On Thu, Dec 4, 2025 at 1:40 PM Lucas Vargas Dias <[email protected]> wrote:
> Hi, > > We're testing the CoPP, in the first tests, it works correctly. > > I agree about avoiding new options. > > > Regards, > Lucas > Thank you, based on that I'll mark the series as deferred for now. Regards, Ales > > Em sex., 28 de nov. de 2025 às 07:29, Ales Musil <[email protected]> > escreveu: > >> >> >> On Mon, Oct 27, 2025 at 9:21 PM Lucas Vargas Dias via dev < >> [email protected]> wrote: >> >>> Consider the following scenario: >>> (192.168.10.10/24) VM1 -> LS -> LR -> TS -> LR -> LS -> VM2 ( >>> 192.168.20.20/24) >>> >>> Also, LSPs from LS have the addresses configured, it's not used unknown >>> addresses >>> in this case. >>> >>> Ping from VM1 to VM2 works correctly, it's ok. But, if VM1 try to flood, >>> for example the IP 192.168.20.30 (an innexistent LSP), we'll see a high >>> CPU load in >>> ovn-controller from the network destination due to the get_arp function. >>> For this case, ovn-controller have ovn-is-interconn = true. >>> >>> In the connection LR -> TS -> LR all addresses are known, so arp resolve >>> could be disable. For this case, add the option disable_arp_resolve=true >>> to logical_router_port drop the packets for unknown addresses. If the >>> communication is IPv6, configure the option disable_nd_resolve=true. >>> >>> >>> Co-authored-by: Tiago Matos Carvalho Reis <[email protected]> >>> Signed-off-by: Tiago Matos Carvalho Reis <[email protected]> >>> Signed-off-by: Lucas Vargas Dias <[email protected]> >>> --- >>> >> >> Hi Lucas, >> >> sorry for the late response, but I have to agree with Lorenzo and >> Alexander on this. Both of them mentioned CoPP as a solution which >> makes sense considering the problem seems to be high ovn-controller >> CPU usage in pinctrl. And it makes me wonder if there is any reason >> why couldn't CoPP be used? It was built exactly for this to limit >> the traffic towards userspace, to protect the control plane. >> >> There might be another solution, that is ACLs. Would that be >> feasible in any capacity for you to create ACLs that would block >> this traffic? As you said in your case those IPs are known I think >> it should be possible to create ACL drop flow based on those IPs. >> >> While there isn't technically anything wrong with the option, >> it's the fact that we would be adding another option. I would >> love to avoid that if possible, especially if any of the solutions >> above would work. My bet would be on the CoPP, because as I said, >> it's specifically made for those scenarios. >> >> Please let me know what you think. >> >> Thanks, >> Ales >> >> >>> northd/northd.c | 54 ++++++++++++++++++++++++++++++ >>> ovn-nb.xml | 13 ++++++++ >>> tests/ovn-northd.at | 81 +++++++++++++++++++++++++++++++++++++++++++++ >>> 3 files changed, 148 insertions(+) >>> >>> diff --git a/northd/northd.c b/northd/northd.c >>> index 9da995cea..356dbaa94 100644 >>> --- a/northd/northd.c >>> +++ b/northd/northd.c >>> @@ -14940,6 +14940,60 @@ build_arp_resolve_flows_for_lrp(struct ovn_port >>> *op, >>> &op->nbrp->header_, >>> lflow_ref); >>> } >>> + >>> + bool discard_arp_resolve = smap_get_bool(&op->nbrp->options, >>> + "disable_arp_resolve", false); >>> + bool discard_nd_resolve = smap_get_bool(&op->nbrp->options, >>> + "disable_nd_resolve", false); >>> + if (discard_arp_resolve || discard_nd_resolve) { >>> + ds_clear(match); >>> + >>> + ds_put_format(match, "inport == %s && >>> is_chassis_resident(%s) && " >>> + "(", op->json_key, op->cr_port->json_key); >>> + >>> + size_t match_len = match->length; >>> + for (size_t i = 0; i < op->od->nbr->n_ports; i++) { >>> + struct nbrec_logical_router_port *lrp = >>> op->od->nbr->ports[i]; >>> + struct lport_addresses lrp_networks; >>> + if (!extract_lrp_networks(lrp, &lrp_networks)) { >>> + continue; >>> + } >>> + >>> + for (int j = 0; j < lrp_networks.n_ipv4_addrs; j++) { >>> + if (!discard_arp_resolve) { >>> + break; >>> + } >>> + struct ipv4_netaddr ipv4 = >>> lrp_networks.ipv4_addrs[j]; >>> + struct in6_addr ip = >>> in6_addr_mapped_ipv4(ipv4.addr); >>> + if (prefix_is_link_local(&ip, ipv4.plen)) { >>> + continue; >>> + } >>> + ds_put_format(match, "(ip4.dst == %s/%u) || ", >>> + ipv4.network_s, ipv4.plen); >>> + } >>> + for (int j = 0; j < lrp_networks.n_ipv6_addrs; j++) { >>> + if (!discard_nd_resolve) { >>> + break; >>> + } >>> + struct ipv6_netaddr ipv6 = >>> lrp_networks.ipv6_addrs[j]; >>> + if (prefix_is_link_local(&ipv6.addr, ipv6.plen)) { >>> + continue; >>> + } >>> + ds_put_format(match, "(ip6.dst == %s/%u) || ", >>> + ipv6.network_s, ipv6.plen); >>> + } >>> + destroy_lport_addresses(&lrp_networks); >>> + } >>> + >>> + if (match->length > match_len) { >>> + ds_truncate(match, match->length - 4); >>> + ds_put_format(match, ")"); >>> + ovn_lflow_add_drop_with_desc(lflows, op->od, >>> + S_ROUTER_IN_ARP_RESOLVE, 50, >>> + ds_cstr(match), "No L2 unknown", >>> + lflow_ref); >>> + } >>> + } >>> } >>> } >>> >>> diff --git a/ovn-nb.xml b/ovn-nb.xml >>> index 73b5f213f..872741a2f 100644 >>> --- a/ovn-nb.xml >>> +++ b/ovn-nb.xml >>> @@ -4499,6 +4499,19 @@ or >>> routes in <code>ovn-ic</code> daemon. >>> </p> >>> </column> >>> + >>> + <column name="options" key="disable_arp_resolve"> >>> + <p> >>> + If set to <code>true</code>, disable get_arp for >>> + known networks. >>> + </p> >>> + </column> >>> + <column name="options" key="disable_nd_resolve"> >>> + <p> >>> + If set to <code>true</code>, disable get_nd for >>> + known networks. >>> + </p> >>> + </column> >>> </group> >>> >>> <group title="Attachment"> >>> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at >>> index 5c9cc5cca..7c8237acd 100644 >>> --- a/tests/ovn-northd.at >>> +++ b/tests/ovn-northd.at >>> @@ -10111,6 +10111,87 @@ AT_CHECK([grep -e "ls_in_arp_rsp" S1flows | >>> ovn_strip_lflows], [0], [dnl >>> AT_CLEANUP >>> ]) >>> >>> + >>> +OVN_FOR_EACH_NORTHD_NO_HV([ >>> +AT_SETUP([check options:disable_arp_resolve and >>> options:disable_nd_resolve for LRP]) >>> +ovn_start NORTHD_TYPE >>> +check ovn-nbctl lr-add S1 >>> +check ovn-nbctl --wait=sb lrp-add S1 S1-vm1 50:54:00:00:00:010 >>> 192.168.0.10/24 fd00::2/64 >>> +check ovn-nbctl --wait=sb lrp-set-gateway-chassis S1-vm1 chassis-1 >>> + >>> +ovn-sbctl dump-flows S1 > S1flows >>> +AT_CAPTURE_FILE([S1flows]) >>> + >>> +ovn-sbctl dump-flows S1 > S1flows >>> +AT_CAPTURE_FILE([S1flows]) >>> + >>> +AT_CHECK([grep -e "lr_in_arp_resolve" S1flows | ovn_strip_lflows], [0], >>> [dnl >>> + table=??(lr_in_arp_resolve ), priority=0 , match=(1), >>> action=(drop;) >>> + table=??(lr_in_arp_resolve ), priority=1 , match=(reg9[[9]] == >>> 0), action=(get_nd(outport, xxreg0); next;) >>> + table=??(lr_in_arp_resolve ), priority=1 , match=(reg9[[9]] == >>> 1), action=(get_arp(outport, reg0); next;) >>> + table=??(lr_in_arp_resolve ), priority=500 , match=(ip4.mcast || >>> ip6.mcast), action=(next;) >>> +]) >>> + >>> + >>> +# Set the disable_arp_resolve option and verify the flow >>> +check ovn-nbctl --wait=sb set logical_router_port S1-vm1 >>> options:disable_arp_resolve=true >>> + >>> +ovn-sbctl dump-flows S1 > S1flows >>> +AT_CAPTURE_FILE([S1flows]) >>> + >>> +AT_CHECK([grep -e "lr_in_arp_resolve" S1flows | ovn_strip_lflows], [0], >>> [dnl >>> + table=??(lr_in_arp_resolve ), priority=0 , match=(1), >>> action=(drop;) >>> + table=??(lr_in_arp_resolve ), priority=1 , match=(reg9[[9]] == >>> 0), action=(get_nd(outport, xxreg0); next;) >>> + table=??(lr_in_arp_resolve ), priority=1 , match=(reg9[[9]] == >>> 1), action=(get_arp(outport, reg0); next;) >>> + table=??(lr_in_arp_resolve ), priority=50 , match=(inport == >>> "S1-vm1" && is_chassis_resident("cr-S1-vm1") && ((ip4.dst == >>> 192.168.0.0/24))), action=(drop;) >>> + table=??(lr_in_arp_resolve ), priority=500 , match=(ip4.mcast || >>> ip6.mcast), action=(next;) >>> +]) >>> + >>> +check ovn-nbctl --wait=sb set logical_router_port S1-vm1 >>> options:disable_nd_resolve=true >>> + >>> +ovn-sbctl dump-flows S1 > S1flows >>> +AT_CAPTURE_FILE([S1flows]) >>> + >>> +AT_CHECK([grep -e "lr_in_arp_resolve" S1flows | ovn_strip_lflows], [0], >>> [dnl >>> + table=??(lr_in_arp_resolve ), priority=0 , match=(1), >>> action=(drop;) >>> + table=??(lr_in_arp_resolve ), priority=1 , match=(reg9[[9]] == >>> 0), action=(get_nd(outport, xxreg0); next;) >>> + table=??(lr_in_arp_resolve ), priority=1 , match=(reg9[[9]] == >>> 1), action=(get_arp(outport, reg0); next;) >>> + table=??(lr_in_arp_resolve ), priority=50 , match=(inport == >>> "S1-vm1" && is_chassis_resident("cr-S1-vm1") && ((ip4.dst == >>> 192.168.0.0/24) || (ip6.dst == fd00::/64))), action=(drop;) >>> + table=??(lr_in_arp_resolve ), priority=500 , match=(ip4.mcast || >>> ip6.mcast), action=(next;) >>> +]) >>> + >>> +# Remove lrp from chassis >>> +check ovn-nbctl --wait=sb lrp-del-gateway-chassis S1-vm1 chassis-1 >>> + >>> +ovn-sbctl dump-flows S1 > S1flows >>> +AT_CAPTURE_FILE([S1flows]) >>> + >>> +AT_CHECK([grep -e "lr_in_arp_resolve" S1flows | ovn_strip_lflows], [0], >>> [dnl >>> + table=??(lr_in_arp_resolve ), priority=0 , match=(1), >>> action=(drop;) >>> + table=??(lr_in_arp_resolve ), priority=1 , match=(reg9[[9]] == >>> 0), action=(get_nd(outport, xxreg0); next;) >>> + table=??(lr_in_arp_resolve ), priority=1 , match=(reg9[[9]] == >>> 1), action=(get_arp(outport, reg0); next;) >>> + table=??(lr_in_arp_resolve ), priority=500 , match=(ip4.mcast || >>> ip6.mcast), action=(next;) >>> +]) >>> + >>> +check ovn-nbctl --wait=sb set logical_router_port S1-vm1 >>> options:disable_arp_resolve=false >>> +check ovn-nbctl --wait=sb lrp-set-gateway-chassis S1-vm1 chassis-1 >>> + >>> +ovn-sbctl dump-flows S1 > S1flows >>> +AT_CAPTURE_FILE([S1flows]) >>> + >>> +AT_CHECK([grep -e "lr_in_arp_resolve" S1flows | ovn_strip_lflows], [0], >>> [dnl >>> + table=??(lr_in_arp_resolve ), priority=0 , match=(1), >>> action=(drop;) >>> + table=??(lr_in_arp_resolve ), priority=1 , match=(reg9[[9]] == >>> 0), action=(get_nd(outport, xxreg0); next;) >>> + table=??(lr_in_arp_resolve ), priority=1 , match=(reg9[[9]] == >>> 1), action=(get_arp(outport, reg0); next;) >>> + table=??(lr_in_arp_resolve ), priority=50 , match=(inport == >>> "S1-vm1" && is_chassis_resident("cr-S1-vm1") && ((ip6.dst == fd00::/64))), >>> action=(drop;) >>> + table=??(lr_in_arp_resolve ), priority=500 , match=(ip4.mcast || >>> ip6.mcast), action=(next;) >>> +]) >>> + >>> + >>> +AT_CLEANUP >>> +]) >>> + >>> + >>> OVN_FOR_EACH_NORTHD_NO_HV([ >>> AT_SETUP([Address set incremental processing]) >>> ovn_start >>> -- >>> 2.43.0 >>> >>> >>> -- >>> >>> >>> >>> >>> _'Esta mensagem é direcionada apenas para os endereços constantes no >>> cabeçalho inicial. Se você não está listado nos endereços constantes no >>> cabeçalho, pedimos-lhe que desconsidere completamente o conteúdo dessa >>> mensagem e cuja cópia, encaminhamento e/ou execução das ações citadas >>> estão >>> imediatamente anuladas e proibidas'._ >>> >>> >>> * **'Apesar do Magazine Luiza tomar >>> todas as precauções razoáveis para assegurar que nenhum vírus esteja >>> presente nesse e-mail, a empresa não poderá aceitar a responsabilidade >>> por >>> quaisquer perdas ou danos causados por esse e-mail ou por seus anexos'.* >>> >>> >>> >>> _______________________________________________ >>> dev mailing list >>> [email protected] >>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev >>> >>> > > *‘Esta mensagem é direcionada apenas para os endereços constantes no > cabeçalho inicial. Se você não está listado nos endereços constantes no > cabeçalho, pedimos-lhe que desconsidere completamente o conteúdo dessa > mensagem e cuja cópia, encaminhamento e/ou execução das ações citadas estão > imediatamente anuladas e proibidas’.* > > *‘Apesar do Magazine Luiza tomar todas as precauções razoáveis para > assegurar que nenhum vírus esteja presente nesse e-mail, a empresa não > poderá aceitar a responsabilidade por quaisquer perdas ou danos causados > por esse e-mail ou por seus anexos’.* > _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
