> 2022年7月14日 下午4:32,Lorenzo Bianconi <[email protected]> 写道:
> 
>>> 
>>> On 7/13/22 18:07, Lorenzo Bianconi wrote:
>>>>> On 6/17/22 00:31, Lorenzo Bianconi wrote:
>>>>>> When using VLAN backed networks and OVN routers leveraging the
>>>>>> 'ovn-chassis-mac-mappings' option, the eth.src field is replaced by the
>>>>>> chassis mac address in order to not expose the router mac address from
>>>>>> different nodes and confuse the TOR switch. However doing so the TOR
>>>>>> switch is not able to learn the port/mac bindings for routed E/W traffic
>>>>>> and it is force to always flood it. Fix this issue adding the capability
>>>>>> to send GARP traffic for logical switch ports if the corresponding 
>>>>>> logical
>>>>>> switch has the ovn-lsp-garp parameter set to true in the option column.
>>>>>> More into about the issue can be found here [0].
>>>>>> 
>>>>>> [0] 
>>>>>> https://mail.openvswitch.org/pipermail/ovs-discuss/2020-September/050678.html
>>>>>>  
>>>>>> <https://mail.openvswitch.org/pipermail/ovs-discuss/2020-September/050678.html>
>>>>>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2087779 
>>>>>> <https://bugzilla.redhat.com/show_bug.cgi?id=2087779>
>>>>>> 
>>>>>> Signed-off-by: Lorenzo Bianconi <[email protected] 
>>>>>> <mailto:[email protected]>>
>>>>>> ---
>>>>> 
>>>>> Hi Lorenzo,
>>>> 
>>>> Hi Dumitru,
>>>> 
>>>> Thanks for reviewing it :)
>>>> 
>>>>> 
>>>>> I have a few concerns with this approach:
>>>>> 
>>>>> a. The CMS will have to set this option for all VMs on all logical
>>>>> switches which will enable periodic GARPs for all of them all the time.
>>>>> That seems like quite a lot of broadcast traffic in the fabric.
>>>>> 
>>>>> b. There's no guarantee that the GARPs are sent in time to prevent the
>>>>> FDB timeouts on the ToR switches.  At best we could make the interval
>>>>> configurable but I don't think this is way better either.
>>>>> 
>>>>> c. This is not really introduced by your patch but we will be causing
>>>>> this more often now.  With the topology:
>>>>> 
>>>>> (HV1) VM1 -- LS1 --- LR -- LS2 -- VM2 (HV2)
>>>>>           (VLAN-backed network)
>>>>> 
>>>>> HV1 configured with chassis mac mapping HV1-MAC
>>>>> HV2 configured with chassis mac mapping HV2-MAC
>>>>> 
>>>>> We're leaking MAC addresses from LS1's broadcast domain (VM1-MAC) and
>>>>> from LS2's broadcast domain (VM2-MAC) into the fabric.  I'm not sure
>>>>> that's OK.
>>>>> 
>>>>> I think a proper solution is to change how we run the logical pipelines
>>>>> in case of vlan-backed networks.  We currently have an assymetry:
>>>>> 
>>>>> For packets flowing from VM1 to VM2 we execute:
>>>>> - on HV1: LS1-ingress, LS1-egress, LR-ingress, LR-egress, LS2-ingress
>>>>> - on HV2: LS2-egress
>>>>> 
>>>>> For packets flowing from VM2 to VM1 we execute:
>>>>> - on HV2: LS2-ingress, LS2-egress, LR-ingress, LR-egress, LS1-ingress
>>>>> - on HV1: LS1-egress
>>>>> 
>>>>> What if we change this to:
>>>>> VM1 -> VM2:
>>>>> - on HV1: LS1-ingress, LS1-egress, LR-ingress
>>>>> - on HV2: LR-egress, LS2-ingress, LS2-egress
>>>>> 
>>>>> VM2 -> VM1:
>>>>> - on HV2: LS2-ingress, LS2-egress, LR-ingress
>>>>> - on HV2: LR-egress, LS1-ingress, LS1-egress
>>>> 
>>>> I do not know why the current architecture is done this way (any 
>>>> suggestions??).
>>>> I guess the approach you suggested should work. Are we introducing any 
>>>> backward
>>>> compatibility issue?
>>> 
>>> We would probably create a compatibility issue. :)
>>> 
>>> I don't know if this approach would even work, I was just trying to
>>> imagine how traffic from within OVN should be seen on the fabric in this
>>> case.
>>> 
>>> Maybe we need to think some more about other options.
>>> 
>>> Regards,
>>> Dumitru
>> Hi Dumitru and Lorenzo, 
> 
> Hi Shy Liu,
> 
>> in my opinion, the flood issue maybe caused by the implemention that
>> logical_switch always be an arp-proxy for lsp which has known address, 
>> but this implemention is not applicable to vlan backed network. Right ?
>> 
>> I have an solution:
>> Maybe we can add a option named arp-proxy for logical_switch 
>> that always be false if network type is vlan, then disable the 
>> logical_switch response the arp for  the lsp which belongs to 
>> the vlan backed network.
>> 
>> So that this solution can let the destination MAC address
>> always learnt by TOR for vlan backed network.
> 
> For e/w routed traffic from pod A to pod B, pod A will send an arp request
> for the router ip address. Who is going to reply to this request in this way?
Hi Lorenzo, 
sorry that I had not describe it clearly.
We can disable arp response for the lsp which type is not router port nor 
localport.
So the logical_switch still responses the arp request for lrp.

> If ovn replies to the arp request from pod A but let the request go through
> the router pipeline I think even the other hypervisor will reply to the arp
> request (please remember the logical router is distributed in ovn) and so we
> will confuse the TOR switch since we will see the router mac address flapping
> between two ports. Do you agree or am I missing something?

We can use 'ovn-chassis-mac-mappings’ option to avoid the problem
 that the lrp's mac address flap. Right ?


> 
> Regards,
> Lorenzo

> 
>> 
>> But the lrp might learn the destination MAC address and put_arp,
>> so this operation also should been disabled. 
>> 
>> This is not useful for logical_switch which is external net.
>> 
>> 
>> Reference:
>> [0] https://mail.openvswitch.org/pipermail/ovs-discuss/2022-May/051837.html 
>> <https://mail.openvswitch.org/pipermail/ovs-discuss/2022-May/051837.html>. 
>>> 
>>>> 
>>>> Regards,
>>>> Lorenzo
>>>> 
>>>>> 
>>>>> Would this we ensure that we always only use ovn-chassis-mac-mappings on
>>>>> the VLAN network and avoid flooding on the ToR?
>>>>> 
>>>>> Regards,
>>>>> Dumitru
>>>>> 
>>>>>> controller/pinctrl.c | 85 +++++++++++++++++++++++++++++---------------
>>>>>> northd/northd.c      | 29 +++++++++++++++
>>>>>> 2 files changed, 85 insertions(+), 29 deletions(-)
>>>>>> 
>>>>>> diff --git a/controller/pinctrl.c b/controller/pinctrl.c
>>>>>> index 9a1a0faa1..eb5739bfc 100644
>>>>>> --- a/controller/pinctrl.c
>>>>>> +++ b/controller/pinctrl.c
>>>>>> @@ -4533,7 +4533,8 @@ send_garp_rarp(struct rconn *swconn, struct 
>>>>>> garp_rarp_data *garp_rarp,
>>>>>>        garp_rarp->backoff *= 2;
>>>>>>        garp_rarp->announce_time = current_time + garp_rarp->backoff * 
>>>>>> 1000;
>>>>>>    } else {
>>>>>> -        garp_rarp->announce_time = LLONG_MAX;
>>>>>> +        /* Default timeout is 180s. */
>>>>>> +        garp_rarp->announce_time = current_time + 180 * 1000;
>>>>>>    }
>>>>>>    return garp_rarp->announce_time;
>>>>>> }
>>>>>> @@ -5510,14 +5511,15 @@ ip_mcast_querier_wait(long long int query_time)
>>>>>> 
>>>>>> /* Get localnet vifs, local l3gw ports and ofport for localnet patch 
>>>>>> ports. */
>>>>>> static void
>>>>>> -get_localnet_vifs_l3gwports(
>>>>>> +get_local_vifs_l3gwports(
>>>>>>    struct ovsdb_idl_index *sbrec_port_binding_by_datapath,
>>>>>>    struct ovsdb_idl_index *sbrec_port_binding_by_name,
>>>>>>    const struct ovsrec_bridge *br_int,
>>>>>>    const struct sbrec_chassis *chassis,
>>>>>>    const struct hmap *local_datapaths,
>>>>>>    struct sset *localnet_vifs,
>>>>>> -    struct sset *local_l3gw_ports)
>>>>>> +    struct sset *local_l3gw_ports,
>>>>>> +    struct sset *local_vifs)
>>>>>> {
>>>>>>    for (int i = 0; i < br_int->n_ports; i++) {
>>>>>>        const struct ovsrec_port *port_rec = br_int->ports[i];
>>>>>> @@ -5574,7 +5576,8 @@ get_localnet_vifs_l3gwports(
>>>>>>        /* Get l3gw ports.  Consider port bindings with type "l3gateway"
>>>>>>         * that connect to gateway routers (if local), and consider port
>>>>>>         * bindings of type "patch" since they might connect to
>>>>>> -         * distributed gateway ports with NAT addresses. */
>>>>>> +         * distributed gateway ports with NAT addresses.
>>>>>> +         * Get LSP ports if requested by CMS. */
>>>>>> 
>>>>>>        sbrec_port_binding_index_set_datapath(target, ld->datapath);
>>>>>>        SBREC_PORT_BINDING_FOR_EACH_EQUAL (pb, target,
>>>>>> @@ -5583,6 +5586,11 @@ get_localnet_vifs_l3gwports(
>>>>>>                || !strcmp(pb->type, "patch")) {
>>>>>>                sset_add(local_l3gw_ports, pb->logical_port);
>>>>>>            }
>>>>>> +            /* GARP packets for lsp ports. */
>>>>>> +            if (pb->chassis == chassis &&
>>>>>> +                smap_get_bool(&pb->options, "ovn-lsp-garp", false)) {
>>>>>> +                sset_add(local_vifs, pb->logical_port);
>>>>>> +            }
>>>>>>        }
>>>>>>    }
>>>>>>    sbrec_port_binding_index_destroy_row(target);
>>>>>> @@ -5761,6 +5769,26 @@ send_garp_rarp_run(struct rconn *swconn, long 
>>>>>> long int *send_garp_rarp_time)
>>>>>>    }
>>>>>> }
>>>>>> 
>>>>>> +static void
>>>>>> +send_garp_rarp_update_for_pb_set(
>>>>>> +        struct ovsdb_idl_txn *ovnsb_idl_txn,
>>>>>> +        struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip,
>>>>>> +        struct ovsdb_idl_index *sbrec_port_binding_by_name,
>>>>>> +        struct sset *vif_set, const struct hmap *local_datapaths,
>>>>>> +        struct shash *nat_addresses)
>>>>>> +{
>>>>>> +    const char *iface_id;
>>>>>> +    SSET_FOR_EACH (iface_id, vif_set) {
>>>>>> +        const struct sbrec_port_binding *pb = lport_lookup_by_name(
>>>>>> +            sbrec_port_binding_by_name, iface_id);
>>>>>> +        if (pb) {
>>>>>> +            send_garp_rarp_update(ovnsb_idl_txn,
>>>>>> +                                  sbrec_mac_binding_by_lport_ip,
>>>>>> +                                  local_datapaths, pb, nat_addresses);
>>>>>> +        }
>>>>>> +    }
>>>>>> +}
>>>>>> +
>>>>>> /* Called by pinctrl_run(). Runs with in the main ovn-controller
>>>>>> * thread context. */
>>>>>> static void
>>>>>> @@ -5776,15 +5804,17 @@ send_garp_rarp_prepare(struct ovsdb_idl_txn 
>>>>>> *ovnsb_idl_txn,
>>>>>> {
>>>>>>    struct sset localnet_vifs = SSET_INITIALIZER(&localnet_vifs);
>>>>>>    struct sset local_l3gw_ports = SSET_INITIALIZER(&local_l3gw_ports);
>>>>>> +    struct sset local_vifs = SSET_INITIALIZER(&local_vifs);
>>>>>>    struct sset nat_ip_keys = SSET_INITIALIZER(&nat_ip_keys);
>>>>>>    struct shash nat_addresses;
>>>>>> 
>>>>>>    shash_init(&nat_addresses);
>>>>>> 
>>>>>> -    get_localnet_vifs_l3gwports(sbrec_port_binding_by_datapath,
>>>>>> -                                sbrec_port_binding_by_name,
>>>>>> -                                br_int, chassis, local_datapaths,
>>>>>> -                                &localnet_vifs, &local_l3gw_ports);
>>>>>> +    get_local_vifs_l3gwports(sbrec_port_binding_by_datapath,
>>>>>> +                             sbrec_port_binding_by_name,
>>>>>> +                             br_int, chassis, local_datapaths,
>>>>>> +                             &localnet_vifs, &local_l3gw_ports,
>>>>>> +                             &local_vifs);
>>>>>> 
>>>>>>    get_nat_addresses_and_keys(sbrec_port_binding_by_name,
>>>>>>                               &nat_ip_keys, &local_l3gw_ports,
>>>>>> @@ -5795,36 +5825,33 @@ send_garp_rarp_prepare(struct ovsdb_idl_txn 
>>>>>> *ovnsb_idl_txn,
>>>>>>    struct shash_node *iter;
>>>>>>    SHASH_FOR_EACH_SAFE (iter, &send_garp_rarp_data) {
>>>>>>        if (!sset_contains(&localnet_vifs, iter->name) &&
>>>>>> -            !sset_contains(&nat_ip_keys, iter->name)) {
>>>>>> +            !sset_contains(&nat_ip_keys, iter->name) &&
>>>>>> +            !sset_contains(&local_vifs, iter->name)) {
>>>>>>            send_garp_rarp_delete(iter->name);
>>>>>>        }
>>>>>>    }
>>>>>> 
>>>>>>    /* Update send_garp_rarp_data. */
>>>>>> -    const char *iface_id;
>>>>>> -    SSET_FOR_EACH (iface_id, &localnet_vifs) {
>>>>>> -        const struct sbrec_port_binding *pb = lport_lookup_by_name(
>>>>>> -            sbrec_port_binding_by_name, iface_id);
>>>>>> -        if (pb) {
>>>>>> -            send_garp_rarp_update(ovnsb_idl_txn,
>>>>>> -                                  sbrec_mac_binding_by_lport_ip,
>>>>>> -                                  local_datapaths, pb, &nat_addresses);
>>>>>> -        }
>>>>>> -    }
>>>>>> -
>>>>>> +    send_garp_rarp_update_for_pb_set(ovnsb_idl_txn,
>>>>>> +                                     sbrec_mac_binding_by_lport_ip,
>>>>>> +                                     sbrec_port_binding_by_name,
>>>>>> +                                     &localnet_vifs, local_datapaths,
>>>>>> +                                     &nat_addresses);
>>>>>> +    send_garp_rarp_update_for_pb_set(ovnsb_idl_txn,
>>>>>> +                                     sbrec_mac_binding_by_lport_ip,
>>>>>> +                                     sbrec_port_binding_by_name,
>>>>>> +                                     &local_vifs, local_datapaths,
>>>>>> +                                     &nat_addresses);
>>>>>>    /* Update send_garp_rarp_data for nat-addresses. */
>>>>>> -    const char *gw_port;
>>>>>> -    SSET_FOR_EACH (gw_port, &local_l3gw_ports) {
>>>>>> -        const struct sbrec_port_binding *pb
>>>>>> -            = lport_lookup_by_name(sbrec_port_binding_by_name, gw_port);
>>>>>> -        if (pb) {
>>>>>> -            send_garp_rarp_update(ovnsb_idl_txn, 
>>>>>> sbrec_mac_binding_by_lport_ip,
>>>>>> -                                  local_datapaths, pb, &nat_addresses);
>>>>>> -        }
>>>>>> -    }
>>>>>> +    send_garp_rarp_update_for_pb_set(ovnsb_idl_txn,
>>>>>> +                                     sbrec_mac_binding_by_lport_ip,
>>>>>> +                                     sbrec_port_binding_by_name,
>>>>>> +                                     &local_l3gw_ports, local_datapaths,
>>>>>> +                                     &nat_addresses);
>>>>>> 
>>>>>>    /* pinctrl_handler thread will send the GARPs. */
>>>>>> 
>>>>>> +    sset_destroy(&local_vifs);
>>>>>>    sset_destroy(&localnet_vifs);
>>>>>>    sset_destroy(&local_l3gw_ports);
>>>>>> 
>>>>>> diff --git a/northd/northd.c b/northd/northd.c
>>>>>> index 0d6ebccde..9a4a880a7 100644
>>>>>> --- a/northd/northd.c
>>>>>> +++ b/northd/northd.c
>>>>>> @@ -6446,6 +6446,34 @@ ovn_update_ipv6_options(struct hmap *ports)
>>>>>>    }
>>>>>> }
>>>>>> 
>>>>>> +static void
>>>>>> +ovn_update_lsp_garp_options(struct hmap *ports)
>>>>>> +{
>>>>>> +    struct ovn_port *op;
>>>>>> +    HMAP_FOR_EACH (op, key_node, ports) {
>>>>>> +        if (!op->nbsp) {
>>>>>> +            continue;
>>>>>> +        }
>>>>>> +        if (op->nbsp->type[0] || op->nbsp->parent_name) {
>>>>>> +            continue;
>>>>>> +        }
>>>>>> +
>>>>>> +        struct ovn_datapath *od = op->od;
>>>>>> +        if (!od || !od->nbs) {
>>>>>> +            continue;
>>>>>> +        }
>>>>>> +
>>>>>> +        struct smap options;
>>>>>> +        smap_clone(&options, &op->sb->options);
>>>>>> +
>>>>>> +        bool ovn_lsp_garp = smap_get_bool(&od->nbs->other_config,
>>>>>> +                                          "ovn-lsp-garp", false);
>>>>>> +        smap_add(&options, "ovn-lsp-garp", ovn_lsp_garp ? "true" : 
>>>>>> "false");
>>>>>> +        sbrec_port_binding_set_options(op->sb, &options);
>>>>>> +        smap_destroy(&options);
>>>>>> +    }
>>>>>> +}
>>>>>> +
>>>>>> static void
>>>>>> build_port_group_lswitches(struct northd_input *input_data,
>>>>>>                           struct hmap *pgs,
>>>>>> @@ -15381,6 +15409,7 @@ ovnnb_db_run(struct northd_input *input_data,
>>>>>>    stopwatch_start(CLEAR_LFLOWS_CTX_STOPWATCH_NAME, time_msec());
>>>>>>    ovn_update_ipv6_options(&data->ports);
>>>>>>    ovn_update_ipv6_prefix(&data->ports);
>>>>>> +    ovn_update_lsp_garp_options(&data->ports);
>>>>>> 
>>>>>>    sync_lbs(input_data, ovnsb_txn, &data->datapaths, &data->lbs);
>>>>>>    sync_address_sets(input_data, ovnsb_txn, &data->datapaths);
>>>>> 

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to