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

Reply via email to