On 1/28/25 3:49 PM, Mark Michelson wrote:
> On 1/28/25 05:36, Xavier Simonart wrote:
>> Hi Ales
>>
>> Thanks for the patch!
>>
>> On Tue, Jan 28, 2025 at 10:45 AM Ales Musil <amu...@redhat.com> wrote:
>>
>>> The registers used in actions and lflow created by controller are
>>> hardcoded, which causes upgrade issues. When the register are changed
>>> the "old" version might be still propagated by northd until upgraded.
>>>
>>> To prevent that add flag that will be populated only by northd that
>>> is using the "new" version of registers. The controller checks
>>> this flag and uses proper registers in lflows/actions.
>>>
>>> Reported-by: Xavier Simonart <xsimo...@redhat.com>
>>> Suggested-by: Dumitru Ceara <dce...@redhat.com>
>>> Signed-off-by: Ales Musil <amu...@redhat.com>
>>> ---
>>>   controller/lflow.c           | 52 +++++++++++++++++++++++-------------
>>>   controller/lflow.h           |  1 +
>>>   controller/ovn-controller.c  | 19 +++++++++++++
>>>   include/ovn/actions.h        |  4 +++
>>>   include/ovn/logical-fields.h |  7 +++++
>>>   lib/actions.c                | 10 +++++--
>>>   northd/en-global-config.c    |  4 +++
>>>   tests/test-ovn.c             |  1 +
>>>   8 files changed, 78 insertions(+), 20 deletions(-)
>>>
>>> diff --git a/controller/lflow.c b/controller/lflow.c
>>> index 856261f40..a77d07d22 100644
>>> --- a/controller/lflow.c
>>> +++ b/controller/lflow.c
>>> @@ -100,7 +100,8 @@ consider_logical_flow(const struct
>>> sbrec_logical_flow
>>> *lflow,
>>>   static void
>>>   consider_lb_hairpin_flows(const struct ovn_controller_lb *lb,
>>>                             const struct hmap *local_datapaths,
>>> -                          struct ovn_desired_flow_table *flow_table);
>>> +                          struct ovn_desired_flow_table *flow_table,
>>> +                          bool register_consolidation);
>>>
>>>   static void add_port_sec_flows(const struct shash *binding_lports,
>>>                                  const struct sbrec_chassis *,
>>> @@ -878,6 +879,7 @@ add_matches_to_flow_table(const struct
>>> sbrec_logical_flow *lflow,
>>>           .lflow_uuid = lflow->header_.uuid,
>>>           .dp_key = ldp->datapath->tunnel_key,
>>>           .explicit_arp_ns_output = l_ctx_in->explicit_arp_ns_output,
>>> +        .register_consolidation = l_ctx_in->register_consolidation,
>>>
>>>           .pipeline = ingress ? OVNACT_P_INGRESS : OVNACT_P_EGRESS,
>>>           .ingress_ptable = OFTABLE_LOG_INGRESS_PIPELINE,
>>> @@ -1645,7 +1647,8 @@ static void
>>>   add_lb_vip_hairpin_flows(const struct ovn_controller_lb *lb,
>>>                            struct ovn_lb_vip *lb_vip,
>>>                            struct ovn_lb_backend *lb_backend,
>>> -                         struct ovn_desired_flow_table *flow_table)
>>> +                         struct ovn_desired_flow_table *flow_table,
>>> +                         bool register_consolidation)
>>>   {
>>>       uint64_t stub[1024 / 8];
>>>       struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub);
>>> @@ -1677,9 +1680,10 @@ add_lb_vip_hairpin_flows(const struct
>>> ovn_controller_lb *lb,
>>>           if (!lb->hairpin_orig_tuple) {
>>>               match_set_ct_nw_dst(&hairpin_match, vip4);
>>>           } else {
>>> -            match_set_reg(&hairpin_match,
>>> -                          MFF_LOG_LB_ORIG_DIP_IPV4 - MFF_LOG_REG0,
>>> -                          ntohl(vip4));
>>> +            enum mf_field_id id = register_consolidation
>>> +                ? MFF_LOG_LB_ORIG_DIP_IPV4
>>> +                : MFF_LOG_LB_ORIG_DIP_IPV4_OLD;
>>> +            match_set_reg(&hairpin_match, id - MFF_LOG_REG0,
>>> ntohl(vip4));
>>>           }
>>>
>>>           add_lb_vip_hairpin_reply_action(NULL, snat_vip4, lb->proto,
>>> @@ -1788,7 +1792,8 @@ static void
>>>   add_lb_ct_snat_hairpin_vip_flow(const struct ovn_controller_lb *lb,
>>>                                   const struct ovn_lb_vip *lb_vip,
>>>                                   const struct hmap *local_datapaths,
>>> -                                struct ovn_desired_flow_table
>>> *flow_table)
>>> +                                struct ovn_desired_flow_table
>>> *flow_table,
>>> +                                bool register_consolidation)
>>>   {
>>>       uint64_t stub[1024 / 8];
>>>       struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub);
>>> @@ -1845,8 +1850,10 @@ add_lb_ct_snat_hairpin_vip_flow(const struct
>>> ovn_controller_lb *lb,
>>>           if (!lb->hairpin_orig_tuple) {
>>>               match_set_ct_nw_dst(&match, vip4);
>>>           } else {
>>> -            match_set_reg(&match, MFF_LOG_LB_ORIG_DIP_IPV4 -
>>> MFF_LOG_REG0,
>>> -                          ntohl(vip4));
>>> +            enum mf_field_id id = register_consolidation
>>> +                                  ? MFF_LOG_LB_ORIG_DIP_IPV4
>>> +                                  : MFF_LOG_LB_ORIG_DIP_IPV4_OLD;
>>> +            match_set_reg(&match, id - MFF_LOG_REG0, ntohl(vip4));
>>>           }
>>>       } else {
>>>           match_set_dl_type(&match, htons(ETH_TYPE_IPV6));
>>> @@ -1922,7 +1929,8 @@ add_lb_ct_snat_hairpin_vip_flow(const struct
>>> ovn_controller_lb *lb,
>>>   static void
>>>   add_lb_ct_snat_hairpin_flows(const struct ovn_controller_lb *lb,
>>>                                const struct hmap *local_datapaths,
>>> -                             struct ovn_desired_flow_table *flow_table)
>>> +                             struct ovn_desired_flow_table *flow_table,
>>> +                             bool register_consolidation)
>>>   {
>>>       /* We must add a flow for each LB VIP. In the general case,
>>> this flow
>>>          is added to the OFTABLE_CT_SNAT_HAIRPIN table. If it
>>> matches, we
>>> @@ -1956,14 +1964,15 @@ add_lb_ct_snat_hairpin_flows(const struct
>>> ovn_controller_lb *lb,
>>>
>>>       for (int i = 0; i < lb->n_vips; i++) {
>>>           add_lb_ct_snat_hairpin_vip_flow(lb, &lb->vips[i],
>>> local_datapaths,
>>> -                                        flow_table);
>>> +                                        flow_table,
>>> register_consolidation);
>>>       }
>>>   }
>>>
>>>   static void
>>>   consider_lb_hairpin_flows(const struct ovn_controller_lb *lb,
>>>                             const struct hmap *local_datapaths,
>>> -                          struct ovn_desired_flow_table *flow_table)
>>> +                          struct ovn_desired_flow_table *flow_table,
>>> +                          bool register_consolidation)
>>>   {
>>>       for (size_t i = 0; i < lb->n_vips; i++) {
>>>           struct ovn_lb_vip *lb_vip = &lb->vips[i];
>>> @@ -1971,11 +1980,13 @@ consider_lb_hairpin_flows(const struct
>>> ovn_controller_lb *lb,
>>>           for (size_t j = 0; j < lb_vip->n_backends; j++) {
>>>               struct ovn_lb_backend *lb_backend = &lb_vip->backends[j];
>>>
>>> -            add_lb_vip_hairpin_flows(lb, lb_vip, lb_backend,
>>> flow_table);
>>> +            add_lb_vip_hairpin_flows(lb, lb_vip, lb_backend,
>>> flow_table,
>>> +                                     register_consolidation);
>>>           }
>>>       }
>>>
>>> -    add_lb_ct_snat_hairpin_flows(lb, local_datapaths, flow_table);
>>> +    add_lb_ct_snat_hairpin_flows(lb, local_datapaths, flow_table,
>>> +                                 register_consolidation);
>>>   }
>>>
>>>   /* Adds OpenFlow flows to flow tables for each Load balancer VIPs and
>>> @@ -1983,11 +1994,13 @@ consider_lb_hairpin_flows(const struct
>>> ovn_controller_lb *lb,
>>>   static void
>>>   add_lb_hairpin_flows(const struct hmap *local_lbs,
>>>                        const struct hmap *local_datapaths,
>>> -                     struct ovn_desired_flow_table *flow_table)
>>> +                     struct ovn_desired_flow_table *flow_table,
>>> +                     bool register_consolidation)
>>>   {
>>>       const struct ovn_controller_lb *lb;
>>>       HMAP_FOR_EACH (lb, hmap_node, local_lbs) {
>>> -        consider_lb_hairpin_flows(lb, local_datapaths, flow_table);
>>> +        consider_lb_hairpin_flows(lb, local_datapaths, flow_table,
>>> +                                  register_consolidation);
>>>       }
>>>   }
>>>
>>> @@ -2147,7 +2160,8 @@ lflow_run(struct lflow_ctx_in *l_ctx_in, struct
>>> lflow_ctx_out *l_ctx_out)
>>>                          l_ctx_out->flow_table);
>>>       add_lb_hairpin_flows(l_ctx_in->local_lbs,
>>>                            l_ctx_in->local_datapaths,
>>> -                         l_ctx_out->flow_table);
>>> +                         l_ctx_out->flow_table,
>>> +                         l_ctx_in->register_consolidation);
>>>       add_fdb_flows(l_ctx_in->fdb_table, l_ctx_in->local_datapaths,
>>>                     l_ctx_out->flow_table,
>>>                     l_ctx_in->sbrec_port_binding_by_key,
>>> @@ -2401,7 +2415,8 @@ lflow_handle_changed_lbs(struct lflow_ctx_in
>>> *l_ctx_in,
>>>                     UUID_FMT, UUID_ARGS(&uuid_node->uuid));
>>>           ofctrl_remove_flows(l_ctx_out->flow_table, &uuid_node->uuid);
>>>           consider_lb_hairpin_flows(lb, l_ctx_in->local_datapaths,
>>> -                                  l_ctx_out->flow_table);
>>> +                                  l_ctx_out->flow_table,
>>> +                                  l_ctx_in->register_consolidation);
>>>       }
>>>
>>>       UUIDSET_FOR_EACH (uuid_node, new_lbs) {
>>> @@ -2410,7 +2425,8 @@ lflow_handle_changed_lbs(struct lflow_ctx_in
>>> *l_ctx_in,
>>>           VLOG_DBG("Add load balancer hairpin flows for "UUID_FMT,
>>>                    UUID_ARGS(&uuid_node->uuid));
>>>           consider_lb_hairpin_flows(lb, l_ctx_in->local_datapaths,
>>> -                                  l_ctx_out->flow_table);
>>> +                                  l_ctx_out->flow_table,
>>> +                                  l_ctx_in->register_consolidation);
>>>       }
>>>
>>>       return true;
>>> diff --git a/controller/lflow.h b/controller/lflow.h
>>> index 206328f9e..93a9f3b7e 100644
>>> --- a/controller/lflow.h
>>> +++ b/controller/lflow.h
>>> @@ -135,6 +135,7 @@ struct lflow_ctx_in {
>>>       bool localnet_learn_fdb;
>>>       bool localnet_learn_fdb_changed;
>>>       bool explicit_arp_ns_output;
>>> +    bool register_consolidation;
>>>   };
>>>
>>>   struct lflow_ctx_out {
>>> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
>>> index 910963e25..63c787bde 100644
>>> --- a/controller/ovn-controller.c
>>> +++ b/controller/ovn-controller.c
>>> @@ -3520,6 +3520,7 @@ struct ed_type_northd_options {
>>>                            * switch (i.e with localnet port) should
>>>                            * be tunnelled or sent via the localnet
>>>                            * port.  Default value is 'false'. */
>>> +    bool register_consolidation;
>>>   };
>>>
>>>
>>> @@ -3557,6 +3558,12 @@ en_northd_options_run(struct engine_node *node,
>>> void *data)
>>>                               false)
>>>               : false;
>>>
>>> +    n_opts->register_consolidation =
>>> +        sb_global
>>> +        ? smap_get_bool(&sb_global->options, "register_consolidation",
>>> +                        false)
>>> +        : false;
>>> +
>>>       engine_set_node_state(node, EN_UPDATED);
>>>   }
>>>
>>> @@ -3591,6 +3598,17 @@ en_northd_options_sb_sb_global_handler(struct
>>> engine_node *node, void *data)
>>>           engine_set_node_state(node, EN_UPDATED);
>>>       }
>>>
>>> +    bool register_consolidation =
>>> +        sb_global
>>> +        ? smap_get_bool(&sb_global->options, "register_consolidation",
>>> +                        false)
>>> +        : false;
>>> +
>>> +    if (register_consolidation != n_opts->register_consolidation) {
>>> +        n_opts->register_consolidation = register_consolidation;
>>> +        engine_set_node_state(node, EN_UPDATED);
>>> +    }
>>> +
>>>       return true;
>>>   }
>>>
>>> @@ -3820,6 +3838,7 @@ init_lflow_ctx(struct engine_node *node,
>>>       l_ctx_in->localnet_learn_fdb_changed =
>>> rt_data->localnet_learn_fdb_changed;
>>>       l_ctx_in->chassis_tunnels = &non_vif_data->chassis_tunnels;
>>>       l_ctx_in->explicit_arp_ns_output = n_opts->explicit_arp_ns_output;
>>> +    l_ctx_in->register_consolidation = n_opts->register_consolidation;
>>>       l_ctx_in->nd_ra_opts = &fo->nd_ra_opts;
>>>       l_ctx_in->dhcp_opts = &dhcp_opts->v4_opts;
>>>       l_ctx_in->dhcpv6_opts = &dhcp_opts->v6_opts;
>>> diff --git a/include/ovn/actions.h b/include/ovn/actions.h
>>> index db7342f1d..3c3d06570 100644
>>> --- a/include/ovn/actions.h
>>> +++ b/include/ovn/actions.h
>>> @@ -893,6 +893,10 @@ struct ovnact_encode_params {
>>>       /* Indication if we should add explicit output after arp/nd_ns
>>> action. */
>>>       bool explicit_arp_ns_output;
>>>
>>> +    /* Indication if we should use the "old" version of registers. */
>>> +    bool register_consolidation;
>>> +
>>> +
>>>       /* OVN maps each logical flow table (ltable), one-to-one, onto a
>>> physical
>>>        * OpenFlow flow table (ptable).  A number of parameters
>>> describe this
>>>        * mapping and data related to flow tables:
>>> diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h
>>> index 6a87fc386..f853b1f61 100644
>>> --- a/include/ovn/logical-fields.h
>>> +++ b/include/ovn/logical-fields.h
>>> @@ -64,6 +64,13 @@ enum ovn_controller_event {
>>>   #define MFF_LOG_CT_ORIG_TP_DST_PORT         MFF_REG2   /*
>>> REG_ORIG_TP_DPORT
>>>                                                           * (bits
>>> 0..15). */
>>>
>>> +/* Logical registers that are needed for backwards
>>> + * compatibility with older northd versions.
>>> + * XXX: All of them can be removed in 26.09. */
>>> +#define MFF_LOG_LB_ORIG_DIP_IPV4_OLD         MFF_REG1
>>> +#define MFF_LOG_LB_AFF_MATCH_PORT_OLD        MFF_REG8
>>> +#define MFF_LOG_LB_AFF_MATCH_LS_IP6_ADDR_OLD MFF_XXREG0
>>> +
>>>   void ovn_init_symtab(struct shash *symtab);
>>>
>>>   /* MFF_LOG_FLAGS_REG bit assignments */
>>> diff --git a/lib/actions.c b/lib/actions.c
>>> index 62e73b2c5..5dbcfe324 100644
>>> --- a/lib/actions.c
>>> +++ b/lib/actions.c
>>> @@ -5371,7 +5371,10 @@ encode_COMMIT_LB_AFF(const struct
>>> ovnact_commit_lb_aff *lb_aff,
>>>           imm_backend_ip = (union mf_value) {
>>>               .ipv6 =  lb_aff->backend,
>>>           };
>>> -        ol_spec->dst.field = mf_from_id(MFF_LOG_LB_AFF_MATCH_IP6_ADDR);
>>> +        enum mf_field_id id = !ep->register_consolidation && ep-
>>> >is_switch
>>> +            ? MFF_LOG_LB_AFF_MATCH_LS_IP6_ADDR_OLD
>>> +            : MFF_LOG_LB_AFF_MATCH_IP6_ADDR;
>>> +        ol_spec->dst.field = mf_from_id(id);
>>>       } else {
>>>           ovs_be32 ip4 = in6_addr_get_mapped_ipv4(&lb_aff->backend);
>>>           imm_backend_ip = (union mf_value) {
>>> @@ -5399,7 +5402,10 @@ encode_COMMIT_LB_AFF(const struct
>>> ovnact_commit_lb_aff *lb_aff,
>>>               .be16 = htons(lb_aff->backend_port),
>>>           };
>>>
>>> -        ol_spec->dst.field = mf_from_id(MFF_LOG_LB_AFF_MATCH_PORT);
>>> +        enum mf_field_id id = !ep->register_consolidation
>>> +            ? MFF_LOG_LB_AFF_MATCH_PORT_OLD
>>> +            : MFF_LOG_LB_AFF_MATCH_PORT;
>>> +        ol_spec->dst.field = mf_from_id(id);
>>>           ol_spec->dst_type = NX_LEARN_DST_LOAD;
>>>           ol_spec->src_type = NX_LEARN_SRC_IMMEDIATE;
>>>           ol_spec->dst.ofs = 0;
>>> diff --git a/northd/en-global-config.c b/northd/en-global-config.c
>>> index ce16c26f2..9aef9209f 100644
>>> --- a/northd/en-global-config.c
>>> +++ b/northd/en-global-config.c
>>> @@ -590,6 +590,10 @@ update_sb_config_options_to_sbrec(struct
>>> ed_type_global_config *config_data,
>>>        * arp/nd_ns action. */
>>>       smap_add(options, "arp_ns_explicit_output", "true");
>>>
>>> +    /* Adds indication that northd has code with consolidated
>>> +     * register usage. */
>>> +    smap_add(options, "register_consolidation", "true");
>>> +
>>>       if (!smap_equal(&sb->options, options)) {
>>>           sbrec_sb_global_set_options(sb, options);
>>>       }
>>> diff --git a/tests/test-ovn.c b/tests/test-ovn.c
>>> index b097ec084..c310e197e 100644
>>> --- a/tests/test-ovn.c
>>> +++ b/tests/test-ovn.c
>>> @@ -1366,6 +1366,7 @@ test_parse_actions(struct ovs_cmdl_context *ctx
>>> OVS_UNUSED)
>>>                   .meter_table = &meter_table,
>>>                   .collector_ids = &collector_ids,
>>>                   .explicit_arp_ns_output = true,
>>> +                .register_consolidation = true,
>>>
>>>                   .pipeline = OVNACT_P_INGRESS,
>>>                   .ingress_ptable = OFTABLE_LOG_INGRESS_PIPELINE,
>>> -- 
>>> 2.48.1
>>>
>>> It looks good to me.
>> I also run some tests in an "upgrade-like" scenario (old ovn-northd with
>> new ovn-controller), and they look ok.
>>
>> Acked-by: Xavier Simonart <xsimo...@redhat.com>
>> Thanks
>> Xavier
> 
> Thanks for this, Ales and Xavier. https://patchwork.ozlabs.org/project/
> ovn/list/?series=441693 depends on register consolidation to function
> properly. I'll add a note on the series not to merge it until a new
> version has been posted that takes the new register_consolidation
> boolean into effect.
> 

Thanks, Ales, Xavier and Mark!

Applied to main.


_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to