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

Reply via email to