> 
> 
> > 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.

IIUC what you mean here, this approach will be helpful just if pod A and pod B
are on the same logical switch but they are running on two different 
hypervisors,
right? What if pod A and pod B are on the same logical switch and they are 
running
on the same HV?

Regards,
Lorenzo

> 
> > 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