Hi, We're testing the CoPP, in the first tests, it works correctly.
I agree about avoiding new options. Regards, Lucas 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
