On Mon, Mar 3, 2025 at 2:10 AM Ales Musil <amu...@redhat.com> wrote:
>
> Simplify the processing by avoiding double loops which also allows
> removal of few extra ofpbufs that were used during the whole process.
> This is preparation for usage of CT instead of sending the packet
> into ovn-controller.
>
> Acked-by: Numan Siddique <num...@ovn.org>
> Signed-off-by: Ales Musil <amu...@redhat.com>
> ---
> v2: Rebase on top of latest main.
>     Address comment from Numan about get_vtep_port function signature.
>     Add ack from Numan.

Thanks.  I applied to main.

Numan

> ---
>  controller/physical.c | 249 +++++++++++++++++++-----------------------
>  1 file changed, 115 insertions(+), 134 deletions(-)
>
> diff --git a/controller/physical.c b/controller/physical.c
> index 69bf05347..2abd8bb6f 100644
> --- a/controller/physical.c
> +++ b/controller/physical.c
> @@ -301,12 +301,12 @@ get_localnet_port(const struct hmap *local_datapaths, 
> int64_t tunnel_key)
>  }
>
>
> -static const struct sbrec_port_binding *
> -get_vtep_port(const struct hmap *local_datapaths, int64_t tunnel_key)
> +static bool
> +has_vtep_port(const struct hmap *local_datapaths, int64_t tunnel_key)
>  {
>      const struct local_datapath *ld = get_local_datapath(local_datapaths,
>                                                           tunnel_key);
> -    return ld ? ld->vtep_port : NULL;
> +    return ld != NULL;
>  }
>
>
> @@ -2181,39 +2181,52 @@ local_output_pb(int64_t tunnel_key, struct ofpbuf 
> *ofpacts)
>  #define MC_OFPACTS_MAX_MSG_SIZE     8192
>  #define MC_BUF_START_ID             0x9000
>
> +struct mc_buf_split_ctx {
> +    uint8_t index;
> +    uint8_t stage;
> +    uint16_t prio;
> +    uint32_t flags;
> +    uint32_t flags_mask;
> +    struct ofpbuf ofpacts;
> +};
> +
> +enum mc_buf_split_type {
> +    MC_BUF_SPLIT_LOCAL,
> +    MC_BUF_SPLIT_REMOTE,
> +    MC_BUF_SPLIT_REMOTE_RAMP,
> +    MC_BUF_SPLIT_MAX,
> +};
> +
>  static void
>  mc_ofctrl_add_flow(const struct sbrec_multicast_group *mc,
> -                   struct match *match, struct ofpbuf *ofpacts,
> -                   struct ofpbuf *ofpacts_last, uint8_t stage,
> -                   size_t index, uint32_t *pflow_index,
> -                   uint16_t prio, struct ovn_desired_flow_table *flow_table)
> +                   struct mc_buf_split_ctx *ctx, bool split,
> +                   struct ovn_desired_flow_table *flow_table)
>
>  {
> -    /* do not overcome max netlink message size used by ovs-vswitchd to
> -     * send netlink configuration to the kernel. */
> -    if (ofpacts->size < MC_OFPACTS_MAX_MSG_SIZE && index < (mc->n_ports - 
> 1)) {
> -        return;
> -    }
> +    struct match match = MATCH_CATCHALL_INITIALIZER;
> +
> +    match_outport_dp_and_port_keys(&match, mc->datapath->tunnel_key,
> +                                   mc->tunnel_key);
> +    match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0,
> +                         ctx->flags, ctx->flags_mask);
>
> -    uint32_t flow_index = *pflow_index;
> -    bool is_first = (flow_index == MC_BUF_START_ID);
> -    if (!is_first) {
> -        match_set_reg(match, MFF_REG6 - MFF_REG0, flow_index);
> +    uint16_t prio = ctx->prio;
> +    if (ctx->index) {
> +        match_set_reg(&match, MFF_REG6 - MFF_REG0,
> +                      MC_BUF_START_ID + ctx->index);
>          prio += 10;
>      }
>
> -    if (index == (mc->n_ports - 1)) {
> -        ofpbuf_put(ofpacts, ofpacts_last->data, ofpacts_last->size);
> -    } else {
> -        put_split_buf_function(++flow_index, mc->tunnel_key, stage, ofpacts);
> +    if (split) {
> +        put_split_buf_function(MC_BUF_START_ID + ctx->index + 1,
> +                               mc->tunnel_key, ctx->stage, &ctx->ofpacts);
>      }
>
> -    ofctrl_add_flow(flow_table, stage, prio, mc->header_.uuid.parts[0],
> -                    match, ofpacts, &mc->header_.uuid);
> -    ofpbuf_clear(ofpacts);
> +    ofctrl_add_flow(flow_table, ctx->stage, prio, mc->header_.uuid.parts[0],
> +                    &match, &ctx->ofpacts, &mc->header_.uuid);
> +    ofpbuf_clear(&ctx->ofpacts);
>      /* reset MFF_REG6. */
> -    put_load(0, MFF_REG6, 0, 32, ofpacts);
> -    *pflow_index = flow_index;
> +    put_load(0, MFF_REG6, 0, 32, &ctx->ofpacts);
>  }
>
>  static void
> @@ -2221,9 +2234,8 @@ consider_mc_group(const struct physical_ctx *ctx,
>                    const struct sbrec_multicast_group *mc,
>                    struct ovn_desired_flow_table *flow_table)
>  {
> -    uint32_t dp_key = mc->datapath->tunnel_key;
>      struct local_datapath *ldp = get_local_datapath(ctx->local_datapaths,
> -                                                    dp_key);
> +                                                    
> mc->datapath->tunnel_key);
>      if (!ldp) {
>          return;
>      }
> @@ -2251,20 +2263,34 @@ consider_mc_group(const struct physical_ctx *ctx,
>       *      set the output port to be the router patch port for which
>       *      the redirect port was added.
>       */
> -    struct ofpbuf ofpacts, remote_ofpacts, remote_ofpacts_ramp;
> -    struct ofpbuf ofpacts_last, ofpacts_ramp_last;
> -    ofpbuf_init(&ofpacts, 0);
> -    ofpbuf_init(&remote_ofpacts, 0);
> -    ofpbuf_init(&remote_ofpacts_ramp, 0);
> -    ofpbuf_init(&ofpacts_last, 0);
> -    ofpbuf_init(&ofpacts_ramp_last, 0);
> -
> -    bool local_ports = false, remote_ports = false, remote_ramp_ports = 
> false;
> +    bool has_vtep = has_vtep_port(ctx->local_datapaths,
> +                                  mc->datapath->tunnel_key);
> +    struct mc_buf_split_ctx mc_split[MC_BUF_SPLIT_MAX] = {
> +        {
> +            .stage = OFTABLE_LOCAL_OUTPUT,
> +            .prio = 100,
> +        },
> +        {
> +            .stage = OFTABLE_REMOTE_OUTPUT,
> +            .prio = 100,
> +            .flags_mask = has_vtep ? MLF_RCV_FROM_RAMP : 0,
> +        },
> +        {
> +            .stage = OFTABLE_REMOTE_OUTPUT,
> +            .prio = 120,
> +            .flags = MLF_RCV_FROM_RAMP | MLF_ALLOW_LOOPBACK,
> +            .flags_mask = MLF_RCV_FROM_RAMP | MLF_ALLOW_LOOPBACK,
> +        },
> +    };
> +    for (size_t i = 0; i < MC_BUF_SPLIT_MAX; i++) {
> +        struct mc_buf_split_ctx *split_ctx = &mc_split[i];
> +        ofpbuf_init(&split_ctx->ofpacts, 0);
> +        put_load(0, MFF_REG6, 0, 32, &split_ctx->ofpacts);
> +    }
>
> -    /* local port loop. */
> -    uint32_t flow_index = MC_BUF_START_ID;
> -    put_load(0, MFF_REG6, 0, 32, &ofpacts);
> -    put_load(mc->tunnel_key, MFF_LOG_OUTPORT, 0, 32, &ofpacts_last);
> +    struct mc_buf_split_ctx *local_ctx = &mc_split[MC_BUF_SPLIT_LOCAL];
> +    struct mc_buf_split_ctx *remote_ctx = &mc_split[MC_BUF_SPLIT_REMOTE];
> +    struct mc_buf_split_ctx *ramp_ctx = &mc_split[MC_BUF_SPLIT_REMOTE_RAMP];
>
>      for (size_t i = 0; i < mc->n_ports; i++) {
>          struct sbrec_port_binding *port = mc->ports[i];
> @@ -2280,7 +2306,7 @@ consider_mc_group(const struct physical_ctx *ctx,
>
>          int zone_id = ct_zone_find_zone(ctx->ct_zones, port->logical_port);
>          if (zone_id) {
> -            put_load(zone_id, MFF_LOG_CT_ZONE, 0, 16, &ofpacts);
> +            put_load(zone_id, MFF_LOG_CT_ZONE, 0, 16, &local_ctx->ofpacts);
>          }
>
>          const char *lport_name = (port->parent_port && *port->parent_port) ?
> @@ -2288,25 +2314,29 @@ consider_mc_group(const struct physical_ctx *ctx,
>
>          if (type == LP_PATCH) {
>              if (ldp->is_transit_switch) {
> -                local_output_pb(port->tunnel_key, &ofpacts);
> +                local_output_pb(port->tunnel_key, &local_ctx->ofpacts);
>              } else {
> -                remote_ramp_ports = true;
> -                remote_ports = true;
> +                local_output_pb(port->tunnel_key, &remote_ctx->ofpacts);
> +                local_output_pb(port->tunnel_key, &ramp_ctx->ofpacts);
>              }
>          } else if (type == LP_REMOTE) {
>              if (port->chassis) {
> -                remote_ports = true;
> +                put_load(port->tunnel_key, MFF_LOG_OUTPORT, 0, 32,
> +                         &remote_ctx->ofpacts);
> +                tunnel_to_chassis(ctx->mff_ovn_geneve, port->chassis->name,
> +                                  ctx->chassis_tunnels, mc->datapath,
> +                                  port->tunnel_key, &remote_ctx->ofpacts);
>              }
>          } else if (type == LP_LOCALPORT) {
> -            remote_ports = true;
> +            local_output_pb(port->tunnel_key, &remote_ctx->ofpacts);
>          } else if ((port->chassis == ctx->chassis
>                      || is_additional_chassis(port, ctx->chassis))
>                     && (local_binding_get_primary_pb(ctx->local_bindings,
>                                                      lport_name)
>                         || type == LP_L3GATEWAY)) {
> -            local_output_pb(port->tunnel_key, &ofpacts);
> +            local_output_pb(port->tunnel_key, &local_ctx->ofpacts);
>          } else if (simap_contains(ctx->patch_ofports, port->logical_port)) {
> -            local_output_pb(port->tunnel_key, &ofpacts);
> +            local_output_pb(port->tunnel_key, &local_ctx->ofpacts);
>          } else if (type == LP_CHASSISREDIRECT
>                     && port->chassis == ctx->chassis) {
>              const char *distributed_port = smap_get(&port->options,
> @@ -2317,7 +2347,8 @@ consider_mc_group(const struct physical_ctx *ctx,
>                                             distributed_port);
>                  if (distributed_binding
>                      && port->datapath == distributed_binding->datapath) {
> -                    local_output_pb(distributed_binding->tunnel_key, 
> &ofpacts);
> +                    local_output_pb(distributed_binding->tunnel_key,
> +                                    &local_ctx->ofpacts);
>                  }
>              }
>          } else if (!get_localnet_port(ctx->local_datapaths,
> @@ -2343,104 +2374,54 @@ consider_mc_group(const struct physical_ctx *ctx,
>              }
>          }
>
> -        local_ports |= (ofpacts.size > 0);
> -        if (!local_ports) {
> -            continue;
> +        for (size_t n = 0; n < MC_BUF_SPLIT_MAX; n++) {
> +            struct mc_buf_split_ctx *split_ctx = &mc_split[n];
> +            if (!has_vtep && n == MC_BUF_SPLIT_REMOTE_RAMP) {
> +                continue;
> +            }
> +            if (split_ctx->ofpacts.size >= MC_OFPACTS_MAX_MSG_SIZE) {
> +                mc_ofctrl_add_flow(mc, split_ctx, true, flow_table);
> +                split_ctx->index++;
> +            }
>          }
> +    }
>
> -        struct match match;
> -        match_outport_dp_and_port_keys(&match, dp_key, mc->tunnel_key);
> -        mc_ofctrl_add_flow(mc, &match, &ofpacts, &ofpacts_last,
> -                           OFTABLE_LOCAL_OUTPUT, i, &flow_index, 100,
> -                           flow_table);
> +    bool local_lports = local_ctx->ofpacts.size > 0;
> +    bool remote_ports = remote_ctx->ofpacts.size > 0;
> +    bool ramp_ports = ramp_ctx->ofpacts.size > 0;
> +
> +    if (local_lports) {
> +        put_load(mc->tunnel_key, MFF_LOG_OUTPORT, 0, 32, 
> &local_ctx->ofpacts);
> +        mc_ofctrl_add_flow(mc, local_ctx, false, flow_table);
>      }
>
> -    /* remote port loop. */
> -    ofpbuf_clear(&ofpacts_last);
>      if (remote_ports) {
> -        put_load(mc->tunnel_key, MFF_LOG_OUTPORT, 0, 32, &ofpacts_last);
> +        put_load(mc->tunnel_key, MFF_LOG_OUTPORT, 0, 32, 
> &remote_ctx->ofpacts);
>      }
> -
>      fanout_to_chassis(ctx->mff_ovn_geneve, &remote_chassis,
>                        ctx->chassis_tunnels, mc->datapath, mc->tunnel_key,
> -                      false, &ofpacts_last);
> -    fanout_to_chassis(ctx->mff_ovn_geneve, &vtep_chassis, 
> ctx->chassis_tunnels,
> -                      mc->datapath, mc->tunnel_key, true, &ofpacts_last);
> -
> -    remote_ports |= (ofpacts_last.size > 0);
> -    if (remote_ports && local_ports) {
> -        put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts_last);
> -    }
> -
> -    bool has_vtep = get_vtep_port(ctx->local_datapaths,
> -                                  mc->datapath->tunnel_key);
> -    uint32_t reverse_ramp_flow_index = MC_BUF_START_ID;
> -    flow_index = MC_BUF_START_ID;
> -
> -    put_load(0, MFF_REG6, 0, 32, &remote_ofpacts);
> -    put_load(0, MFF_REG6, 0, 32, &remote_ofpacts_ramp);
> -
> -    put_load(mc->tunnel_key, MFF_LOG_OUTPORT, 0, 32, &ofpacts_ramp_last);
> -    put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts_ramp_last);
> -
> -    for (size_t i = 0; remote_ports && i < mc->n_ports; i++) {
> -        struct sbrec_port_binding *port = mc->ports[i];
> -        enum en_lport_type type = get_lport_type(port);
> -
> -        if (port->datapath != mc->datapath) {
> -            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> -            VLOG_WARN_RL(&rl, UUID_FMT": multicast group contains ports "
> -                         "in wrong datapath",
> -                         UUID_ARGS(&mc->header_.uuid));
> -            continue;
> -        }
> -
> -        if (type == LP_PATCH) {
> -            if (!ldp->is_transit_switch) {
> -                local_output_pb(port->tunnel_key, &remote_ofpacts);
> -                local_output_pb(port->tunnel_key, &remote_ofpacts_ramp);
> -            }
> -        } if (type == LP_REMOTE) {
> -            if (port->chassis) {
> -                put_load(port->tunnel_key, MFF_LOG_OUTPORT, 0, 32,
> -                         &remote_ofpacts);
> -                tunnel_to_chassis(ctx->mff_ovn_geneve, port->chassis->name,
> -                                  ctx->chassis_tunnels, mc->datapath,
> -                                  port->tunnel_key, &remote_ofpacts);
> -            }
> -        } else if (type == LP_LOCALPORT) {
> -            local_output_pb(port->tunnel_key, &remote_ofpacts);
> -        }
> -
> -        struct match match;
> -        match_outport_dp_and_port_keys(&match, dp_key, mc->tunnel_key);
> -        if (has_vtep) {
> -            match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0, 0,
> -                                 MLF_RCV_FROM_RAMP);
> -        }
> -        mc_ofctrl_add_flow(mc, &match, &remote_ofpacts, &ofpacts_last,
> -                           OFTABLE_REMOTE_OUTPUT, i, &flow_index, 100,
> -                           flow_table);
> +                      false, &remote_ctx->ofpacts);
> +    fanout_to_chassis(ctx->mff_ovn_geneve, &vtep_chassis,
> +                      ctx->chassis_tunnels, mc->datapath, mc->tunnel_key,
> +                      true, &remote_ctx->ofpacts);
>
> -        if (!remote_ramp_ports || !has_vtep) {
> -            continue;
> +    remote_ports = remote_ctx->ofpacts.size > 0;
> +    if (remote_ports) {
> +        if (local_lports) {
> +            put_resubmit(OFTABLE_LOCAL_OUTPUT, &remote_ctx->ofpacts);
>          }
> +        mc_ofctrl_add_flow(mc, remote_ctx, false, flow_table);
> +    }
>
> -        struct match match_ramp;
> -        match_outport_dp_and_port_keys(&match_ramp, dp_key, mc->tunnel_key);
> -        match_set_reg_masked(&match_ramp, MFF_LOG_FLAGS - MFF_REG0,
> -                             MLF_RCV_FROM_RAMP | MLF_ALLOW_LOOPBACK,
> -                             MLF_RCV_FROM_RAMP | MLF_ALLOW_LOOPBACK);
> -        mc_ofctrl_add_flow(mc, &match_ramp, &remote_ofpacts_ramp,
> -                           &ofpacts_ramp_last, OFTABLE_REMOTE_OUTPUT, i,
> -                           &reverse_ramp_flow_index, 120, flow_table);
> +    if (ramp_ports && has_vtep) {
> +        put_load(mc->tunnel_key, MFF_LOG_OUTPORT, 0, 32, &ramp_ctx->ofpacts);
> +        put_resubmit(OFTABLE_LOCAL_OUTPUT, &ramp_ctx->ofpacts);
> +        mc_ofctrl_add_flow(mc, ramp_ctx, false, flow_table);
>      }
>
> -    ofpbuf_uninit(&ofpacts);
> -    ofpbuf_uninit(&remote_ofpacts);
> -    ofpbuf_uninit(&ofpacts_last);
> -    ofpbuf_uninit(&ofpacts_ramp_last);
> -    ofpbuf_uninit(&remote_ofpacts_ramp);
> +    for (size_t i = 0; i < MC_BUF_SPLIT_MAX; i++) {
> +        ofpbuf_uninit(&mc_split[i].ofpacts);
> +    }
>      sset_destroy(&remote_chassis);
>      sset_destroy(&vtep_chassis);
>  }
> --
> 2.48.1
>
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to