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