On Sun, Dec 11, 2022 at 8:54 AM Lorenzo Bianconi
<[email protected]> wrote:
>
> > On Fri, Dec 9, 2022 at 9:43 AM Lorenzo Bianconi
> > <[email protected]> wrote:
> > >
> > > > On Sun, Dec 4, 2022 at 5:06 PM Lorenzo Bianconi
> > > > <[email protected]> wrote:
> > > > >
> > > > > Introduce the capability to apply QoS rules for logical switch ports
> > > > > claimed by ovn-controller. Rely on shash instead of sset for
> > > > > egress_ifaces.
> > > > >
> > > > > Acked-by: Mark Michelson <[email protected]>
> > > > > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2129742
> > > > > Signed-off-by: Lorenzo Bianconi <[email protected]>
> > > >
> > > > Hi Lorenzo,
> > >
> > > Hi Numan,
> > >
> > > thx for the review :)
> > >
> > > >
> > > > Thanks for addressing the comments.
> > > >
> > > > I tested this version and compared with the present main.
> > > >
> > > > I see a few differences.
> > > >
> > > > With the main version, when I configure qos params to a localnet
> > > > logical port, ovn-controller creates a qdisc on the tunnel interface
> > > > which I guess is expected.
> > > > But I'm still not sure why we need to configure qdiscs on the tunnel
> > > > interface. But that's a story. Perhaps I need to see the original
> > > > QoS commits and understand why it was added.
> > > >
> > > > With your patch, I don't see that happening. Perhaps there is a bug
> > > > in setup_qos() function now that 'shash' is used to store the egress
> > > > ifaces with the logical port and
> > > > there is no logical port for the tunnel interfaces.
> > >
> > > uhm, I can look into this. Do you think we should keep this behaviour?
> >
> > Frankly I don't know. We need to find out why qos was configured in
> > the first place.
> >
> > I do agree with Ilya's comment that it is odd to configure qos on the
> > tunnel interface
> > and that could impact the other traffic.
> >
> >
> > >
> > > >
> > > > Regarding the option - "ovn-egress-iface". I suppose the expectation
> > > > from the CMS is to set the qos parameters in the logical port and also
> > > > set this option in the
> > > > ovs interface right ? I don't really see a need for this. I think if
> > > > CMS configures the qos parameters in the logical port options,
> > > > ovn-controller should configure the qos.
> > > > I think otherwise this would complicate the CMS implementation.
> > > > Thoughts ?
> > >
> > > ovn-egress-iface is mandatory since it is used in setup_qos() to look for
> > > the
> > > proper netdevice pointer to configure ovs qdisc (please note it is used to
> > > identify ovs interfaces and not ovn ones).
> > > I think it can be doable (not sure about the complexity) to avoid it for
> > > logical switch ports (since we have iface-id in them external_ids column
> > > of
> > > ovs interface table) but I do not think we can avoid to set
> > > "ovn-egress-iface"
> > > for localnet port since afaik there is no direct link between ovn
> > > localnet port
> > > and ovs interface used to connect the underlay network, right? If so I
> > > guess
> > > it is better to keep it for both localnet and lsp ports. Do you agree?
> >
> > I think it's ok to expect CMS to set "ovn-egress-iface" for the
> > physical nic connected to the
> > provider bridge. But I don't think we should do the same for the
> > normal logical port VIFs.
>
> does it worth to introduce a difference here?
Yes.
Configuring ovn-egress-iface=true for a phsyical interface connected
to the provider bridge is a one time activity which CMS
can easily do during installation time. I think openstack installer -
tripleo does that during deployment.
But to set ovn-egress-iface=true on every ovs interface would
require some additional changes in CMS.
If we take openstack as an example, if qos has to be enabled on a VM,
then first neutron has to set the QoS options
in the logical switch port and the "nova" compute component also has
to set ovn-egress-iface=true when it creates a libvirt VM.
This seems unnecessary to me.
Thanks
Numan
>
> >
> >
> >
> > >
> > > >
> > > >
> > > > Please see a few comments below
> > > >
> > > > > ---
> > > > > Changes since v3:
> > > > > - fix typo in new system-ovn test
> > > > > Changes since v2:
> > > > > - fix qos configuration restarting ovn-controller
> > > > > Changes since v1:
> > > > > - improve ovs interface lookup
> > > > > - improve system-tests
> > > > > ---
> > > > > controller/binding.c | 155
> > > > > ++++++++++++++++++++++--------------
> > > > > controller/binding.h | 5 +-
> > > > > controller/ovn-controller.c | 15 ++--
> > > > > tests/system-ovn.at | 48 +++++++++++
> > > > > 4 files changed, 156 insertions(+), 67 deletions(-)
> > > > >
> > > > > diff --git a/controller/binding.c b/controller/binding.c
> > > > > index 5df62baef..53520263c 100644
> > > > > --- a/controller/binding.c
> > > > > +++ b/controller/binding.c
> > > > > @@ -115,6 +115,7 @@ struct qos_queue {
> > > > > uint32_t min_rate;
> > > > > uint32_t max_rate;
> > > > > uint32_t burst;
> > > > > + char *port_name;
> > > > > };
> > > > >
> > > > > void
> > > > > @@ -147,25 +148,50 @@ static void update_lport_tracking(const struct
> > > > > sbrec_port_binding *pb,
> > > > > struct hmap *tracked_dp_bindings,
> > > > > bool claimed);
> > > > >
> > > > > +static bool is_lport_vif(const struct sbrec_port_binding *pb);
> > > > > +
> > > > > +static struct qos_queue *
> > > > > +get_qos_map_entry(struct hmap *queue_map, const char *name)
> > > > > +{
> > > > > + struct qos_queue *qos_node;
> > > > > + HMAP_FOR_EACH (qos_node, node, queue_map) {
> > > > > + if (!strcmp(qos_node->port_name, name)) {
> > > > > + return qos_node;
> > > > > + }
> > > > > + }
> > > > > +
> > > > > + return NULL;
> > > > > +}
> > > > > +
> > > > > static void
> > > > > -get_qos_params(const struct sbrec_port_binding *pb, struct hmap
> > > > > *queue_map)
> > > > > +update_qos_params(const struct sbrec_port_binding *pb, struct hmap
> > > > > *queue_map)
> > > > > {
> > > > > uint32_t min_rate = smap_get_int(&pb->options, "qos_min_rate",
> > > > > 0);
> > > > > uint32_t max_rate = smap_get_int(&pb->options, "qos_max_rate",
> > > > > 0);
> > > > > uint32_t burst = smap_get_int(&pb->options, "qos_burst", 0);
> > > > > uint32_t queue_id = smap_get_int(&pb->options, "qdisc_queue_id",
> > > > > 0);
> > > > >
> > > > > + struct qos_queue *node = get_qos_map_entry(queue_map,
> > > > > pb->logical_port);
> > > > > +
> > > > > if ((!min_rate && !max_rate && !burst) || !queue_id) {
> > > > > /* Qos is not configured for this port. */
> > > > > + if (node) {
> > > > > + hmap_remove(queue_map, &node->node);
> > > > > + free(node->port_name);
> > > > > + free(node);
> > > > > + }
> > > > > return;
> > > > > }
> > > > >
> > > > > - struct qos_queue *node = xzalloc(sizeof *node);
> > > > > - hmap_insert(queue_map, &node->node, hash_int(queue_id, 0));
> > > > > + if (!node) {
> > > > > + node = xzalloc(sizeof *node);
> > > > > + hmap_insert(queue_map, &node->node, hash_int(queue_id, 0));
> > > > > + node->port_name = xstrdup(pb->logical_port);
> > > > > + }
> > > > > + node->queue_id = queue_id;
> > > > > node->min_rate = min_rate;
> > > > > node->max_rate = max_rate;
> > > > > node->burst = burst;
> > > > > - node->queue_id = queue_id;
> > > > > }
> > > > >
> > > > > static const struct ovsrec_qos *
> > > > > @@ -191,7 +217,7 @@ static bool
> > > > > set_noop_qos(struct ovsdb_idl_txn *ovs_idl_txn,
> > > > > const struct ovsrec_port_table *port_table,
> > > > > const struct ovsrec_qos_table *qos_table,
> > > > > - struct sset *egress_ifaces)
> > > > > + struct shash *egress_ifaces)
> > > > > {
> > > > > if (!ovs_idl_txn) {
> > > > > return false;
> > > > > @@ -206,11 +232,11 @@ set_noop_qos(struct ovsdb_idl_txn *ovs_idl_txn,
> > > > > size_t count = 0;
> > > > >
> > > > > OVSREC_PORT_TABLE_FOR_EACH (port, port_table) {
> > > > > - if (sset_contains(egress_ifaces, port->name)) {
> > > > > + if (shash_find(egress_ifaces, port->name)) {
> > > > > ovsrec_port_set_qos(port, noop_qos);
> > > > > count++;
> > > > > }
> > > > > - if (sset_count(egress_ifaces) == count) {
> > > > > + if (shash_count(egress_ifaces) == count) {
> > > > > break;
> > > > > }
> > > > > }
> > > > > @@ -236,7 +262,8 @@ set_qos_type(struct netdev *netdev, const char
> > > > > *type)
> > > > > }
> > > > >
> > > > > static void
> > > > > -setup_qos(const char *egress_iface, struct hmap *queue_map)
> > > > > +setup_qos(const char *egress_iface, const char *logical_port,
> > > > > + struct hmap *queue_map)
> > > > > {
> > > > > static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
> > > > > struct netdev *netdev_phy;
> > > > > @@ -281,7 +308,7 @@ setup_qos(const char *egress_iface, struct hmap
> > > > > *queue_map)
> > > > > * a configuration setting.
> > > > > *
> > > > > * - Otherwise leave the qdisc alone. */
> > > > > - if (hmap_is_empty(queue_map)) {
> > > > > + if (!get_qos_map_entry(queue_map, logical_port)) {
> > > > > if (!strcmp(qdisc_type, OVN_QOS_TYPE)) {
> > > > > set_qos_type(netdev_phy, "");
> > > > > }
> > > > > @@ -338,6 +365,10 @@ setup_qos(const char *egress_iface, struct hmap
> > > > > *queue_map)
> > > > > continue;
> > > > > }
> > > > >
> > > > > + if (strcmp(sb_info->port_name, logical_port)) {
> > > > > + continue;
> > > > > + }
> > > > > +
> > > > > smap_clear(&queue_details);
> > > > > smap_add_format(&queue_details, "min-rate", "%d",
> > > > > sb_info->min_rate);
> > > > > smap_add_format(&queue_details, "max-rate", "%d",
> > > > > sb_info->max_rate);
> > > > > @@ -354,11 +385,12 @@ setup_qos(const char *egress_iface, struct hmap
> > > > > *queue_map)
> > > > > netdev_close(netdev_phy);
> > > > > }
> > > > >
> > > > > -static void
> > > > > +void
> > > > > destroy_qos_map(struct hmap *qos_map)
> > > > > {
> > > > > struct qos_queue *qos_queue;
> > > > > HMAP_FOR_EACH_POP (qos_queue, node, qos_map) {
> > > > > + free(qos_queue->port_name);
> > > > > free(qos_queue);
> > > > > }
> > > > >
> > > > > @@ -404,7 +436,7 @@ sbrec_get_port_encap(const struct sbrec_chassis
> > > > > *chassis_rec,
> > > > > static void
> > > > > add_localnet_egress_interface_mappings(
> > > > > const struct sbrec_port_binding *port_binding,
> > > > > - struct shash *bridge_mappings, struct sset *egress_ifaces)
> > > > > + struct shash *bridge_mappings, struct shash *egress_ifaces)
> > > > > {
> > > > > const char *network = smap_get(&port_binding->options,
> > > > > "network_name");
> > > > > if (!network) {
> > > > > @@ -429,7 +461,8 @@ add_localnet_egress_interface_mappings(
> > > > > if (!is_egress_iface) {
> > > > > continue;
> > > > > }
> > > > > - sset_add(egress_ifaces, iface_rec->name);
> > > > > + shash_add(egress_ifaces, iface_rec->name,
> > > > > + port_binding->logical_port);
> > > > > }
> > > > > }
> > > > > }
> > > > > @@ -474,7 +507,7 @@ update_ld_multichassis_ports(const struct
> > > > > sbrec_port_binding *binding_rec,
> > > > > static void
> > > > > update_ld_localnet_port(const struct sbrec_port_binding *binding_rec,
> > > > > struct shash *bridge_mappings,
> > > > > - struct sset *egress_ifaces,
> > > > > + struct shash *egress_ifaces,
> > > > > struct hmap *local_datapaths)
> > > > > {
> > > > > /* Ignore localnet ports for unplugged networks. */
> > > > > @@ -1456,7 +1489,7 @@ consider_vif_lport_(const struct
> > > > > sbrec_port_binding *pb,
> > > > >
> > > > > b_ctx_out->tracked_dp_bindings);
> > > > > }
> > > > > if (b_lport->lbinding->iface && qos_map &&
> > > > > b_ctx_in->ovs_idl_txn) {
> > > > > - get_qos_params(pb, qos_map);
> > > > > + update_qos_params(pb, qos_map);
> > > > > }
> > > > > } else {
> > > > > /* We could, but can't claim the lport. */
> > > > > @@ -1519,6 +1552,16 @@ consider_vif_lport(const struct
> > > > > sbrec_port_binding *pb,
> > > > > b_lport = local_binding_add_lport(binding_lports,
> > > > > lbinding, pb,
> > > > > LP_VIF);
> > > > > }
> > > > > +
> > > > > + if (lbinding->iface &&
> > > > > + smap_get(&lbinding->iface->external_ids,
> > > > > "ovn-egress-iface")) {
> > > > > + const char *iface_id =
> > > > > smap_get(&lbinding->iface->external_ids,
> > > > > + "iface-id");
> > > > > + if (iface_id) {
> > > > > + shash_add(b_ctx_out->egress_ifaces,
> > > > > lbinding->iface->name,
> > > > > + iface_id);
> > > >
> > > > When a qos is configured on a logical port, this patch is adding 2
> > > > entries in the 'egress_ifaces' shash for the same logical port.
> > > > I think it's because of the above 'shash_add'. I think you should use
> > > > shash_replace instead.
> > >
> > > ack, I will fix it.
> > >
> > > >
> > > > When a full recompute happens, the function build_local_bindings()
> > > > also adds the qos configured logical ports to the 'egress_ifaces'
> > > > and later if there are any updates to the logical port, this function
> > > > - consider_vif_lport() also adds it to the shash.
> > > >
> > > > IMO the qos support in OVN needs a different approach. Instead of
> > > > configuring the qos using netdev() perhaps we should rely on the OVS
> > > > meters.
> > > > Maybe this was brought up earlier too.
> > >
> > > >
> > > > I'm of the opinion that instead of supporting Qos for logical ports
> > > > using netdev, we should use OVS meters (not just for logical ports,
> > > > even for localnet ports). Thoughts ?
> > >
> > > ovn qos is used for egress traffic (shaping) while ovn meters are used
> > > for incoming one (policing).
> > > What we can do is to avoid configuring directly netdev qdisc and rely on
> > > ovs to perform this configuration but this would be quite a massive
> > > rework.
> > > Do you think we should do it now before adding this feature or it is ok
> > > to do it after we added this feature? I do not have a strong opinion
> > > about it.
> >
> > IMO its better to add this new feature using the native OVS QoS support.
> > And along with that we can remove the netdev implementation from OVN.
> >
> > This is what I think. Anyway this feature is out of window for 22.12.
> > We can perhaps target this feature with the new approach in 23.03.
> >
> > Although I will not object if other maintainers are fine getting this
> > feature first
> > and then reimplement using OVS native QoS support.
>
> I am fine to work on a proper solution for lsp and then move localnet port
> too.
>
> Regards,
> Lorenzo
>
> >
> > Thanks
> > Numan
> >
> > >
> > > Regards,
> > > Lorenzo
> > >
> > > >
> > > > @Dumitru Ceara @Han Zhou @Mark Michelson @Ilya Maximets Do you have
> > > > any comments or suggestions here ?
> > > >
> > > > Thanks
> > > > Numan
> > > >
> > > >
> > > >
> > > > > + }
> > > > > + }
> > > > > }
> > > > >
> > > > > return consider_vif_lport_(pb, can_bind, b_ctx_in, b_ctx_out,
> > > > > @@ -1785,7 +1828,7 @@ consider_localnet_lport(const struct
> > > > > sbrec_port_binding *pb,
> > > > > update_local_lports(pb->logical_port, b_ctx_out);
> > > > >
> > > > > if (qos_map && b_ctx_in->ovs_idl_txn) {
> > > > > - get_qos_params(pb, qos_map);
> > > > > + update_qos_params(pb, qos_map);
> > > > > }
> > > > >
> > > > > update_related_lport(pb, b_ctx_out);
> > > > > @@ -1861,14 +1904,14 @@ build_local_bindings(struct binding_ctx_in
> > > > > *b_ctx_in,
> > > > > &b_ctx_out->lbinding_data->bindings;
> > > > > for (j = 0; j < port_rec->n_interfaces; j++) {
> > > > > const struct ovsrec_interface *iface_rec;
> > > > > + struct local_binding *lbinding = NULL;
> > > > >
> > > > > iface_rec = port_rec->interfaces[j];
> > > > > iface_id = smap_get(&iface_rec->external_ids,
> > > > > "iface-id");
> > > > > int64_t ofport = iface_rec->n_ofport ?
> > > > > *iface_rec->ofport : 0;
> > > > >
> > > > > if (iface_id && ofport > 0) {
> > > > > - struct local_binding *lbinding =
> > > > > - local_binding_find(local_bindings, iface_id);
> > > > > + lbinding = local_binding_find(local_bindings,
> > > > > iface_id);
> > > > > if (!lbinding) {
> > > > > lbinding = local_binding_create(iface_id,
> > > > > iface_rec);
> > > > > local_binding_add(local_bindings, lbinding);
> > > > > @@ -1895,8 +1938,11 @@ build_local_bindings(struct binding_ctx_in
> > > > > *b_ctx_in,
> > > > > const char *tunnel_iface
> > > > > = smap_get(&iface_rec->status,
> > > > > "tunnel_egress_iface");
> > > > > if (tunnel_iface) {
> > > > > - sset_add(b_ctx_out->egress_ifaces, tunnel_iface);
> > > > > + shash_add(b_ctx_out->egress_ifaces,
> > > > > tunnel_iface, "");
> > > > > }
> > > > > + } else if (lbinding && smap_get(&iface_rec->external_ids,
> > > > > + "ovn-egress-iface")) {
> > > > > + shash_add(b_ctx_out->egress_ifaces, iface_rec->name,
> > > > > iface_id);
> > > > > }
> > > > > }
> > > > > }
> > > > > @@ -1910,16 +1956,11 @@ binding_run(struct binding_ctx_in *b_ctx_in,
> > > > > struct binding_ctx_out *b_ctx_out)
> > > > > }
> > > > >
> > > > > struct shash bridge_mappings =
> > > > > SHASH_INITIALIZER(&bridge_mappings);
> > > > > - struct hmap qos_map;
> > > > >
> > > > > - hmap_init(&qos_map);
> > > > > if (b_ctx_in->br_int) {
> > > > > build_local_bindings(b_ctx_in, b_ctx_out);
> > > > > }
> > > > >
> > > > > - struct hmap *qos_map_ptr =
> > > > > - !sset_is_empty(b_ctx_out->egress_ifaces) ? &qos_map : NULL;
> > > > > -
> > > > > struct ovs_list localnet_lports =
> > > > > OVS_LIST_INITIALIZER(&localnet_lports);
> > > > > struct ovs_list external_lports =
> > > > > OVS_LIST_INITIALIZER(&external_lports);
> > > > > struct ovs_list multichassis_ports = OVS_LIST_INITIALIZER(
> > > > > @@ -1956,7 +1997,8 @@ binding_run(struct binding_ctx_in *b_ctx_in,
> > > > > struct binding_ctx_out *b_ctx_out)
> > > > > break;
> > > > >
> > > > > case LP_VIF:
> > > > > - consider_vif_lport(pb, b_ctx_in, b_ctx_out, NULL,
> > > > > qos_map_ptr);
> > > > > + consider_vif_lport(pb, b_ctx_in, b_ctx_out, NULL,
> > > > > + b_ctx_out->qos_map);
> > > > > if (pb->additional_chassis) {
> > > > > struct lport *multichassis_lport = xmalloc(
> > > > > sizeof *multichassis_lport);
> > > > > @@ -1967,11 +2009,13 @@ binding_run(struct binding_ctx_in *b_ctx_in,
> > > > > struct binding_ctx_out *b_ctx_out)
> > > > > break;
> > > > >
> > > > > case LP_CONTAINER:
> > > > > - consider_container_lport(pb, b_ctx_in, b_ctx_out,
> > > > > qos_map_ptr);
> > > > > + consider_container_lport(pb, b_ctx_in, b_ctx_out,
> > > > > + b_ctx_out->qos_map);
> > > > > break;
> > > > >
> > > > > case LP_VIRTUAL:
> > > > > - consider_virtual_lport(pb, b_ctx_in, b_ctx_out,
> > > > > qos_map_ptr);
> > > > > + consider_virtual_lport(pb, b_ctx_in, b_ctx_out,
> > > > > + b_ctx_out->qos_map);
> > > > > break;
> > > > >
> > > > > case LP_L2GATEWAY:
> > > > > @@ -1994,7 +2038,8 @@ binding_run(struct binding_ctx_in *b_ctx_in,
> > > > > struct binding_ctx_out *b_ctx_out)
> > > > > break;
> > > > >
> > > > > case LP_LOCALNET: {
> > > > > - consider_localnet_lport(pb, b_ctx_in, b_ctx_out,
> > > > > &qos_map);
> > > > > + consider_localnet_lport(pb, b_ctx_in, b_ctx_out,
> > > > > + b_ctx_out->qos_map);
> > > > > struct lport *lnet_lport = xmalloc(sizeof *lnet_lport);
> > > > > lnet_lport->pb = pb;
> > > > > ovs_list_push_back(&localnet_lports,
> > > > > &lnet_lport->list_node);
> > > > > @@ -2051,17 +2096,15 @@ binding_run(struct binding_ctx_in *b_ctx_in,
> > > > > struct binding_ctx_out *b_ctx_out)
> > > > >
> > > > > shash_destroy(&bridge_mappings);
> > > > >
> > > > > - if (!sset_is_empty(b_ctx_out->egress_ifaces)
> > > > > + if (!shash_is_empty(b_ctx_out->egress_ifaces)
> > > > > && set_noop_qos(b_ctx_in->ovs_idl_txn, b_ctx_in->port_table,
> > > > > b_ctx_in->qos_table,
> > > > > b_ctx_out->egress_ifaces)) {
> > > > > - const char *entry;
> > > > > - SSET_FOR_EACH (entry, b_ctx_out->egress_ifaces) {
> > > > > - setup_qos(entry, &qos_map);
> > > > > + struct shash_node *entry;
> > > > > + SHASH_FOR_EACH (entry, b_ctx_out->egress_ifaces) {
> > > > > + setup_qos(entry->name, entry->data, b_ctx_out->qos_map);
> > > > > }
> > > > > }
> > > > >
> > > > > - destroy_qos_map(&qos_map);
> > > > > -
> > > > > cleanup_claimed_port_timestamps();
> > > > > }
> > > > >
> > > > > @@ -2447,7 +2490,7 @@ binding_handle_ovs_interface_changes(struct
> > > > > binding_ctx_in *b_ctx_in,
> > > > > }
> > > > >
> > > > > if (smap_get(&iface_rec->external_ids, "ovn-egress-iface") ||
> > > > > - sset_contains(b_ctx_out->egress_ifaces,
> > > > > iface_rec->name)) {
> > > > > + shash_find(b_ctx_out->egress_ifaces, iface_rec->name)) {
> > > > > handled = false;
> > > > > break;
> > > > > }
> > > > > @@ -2493,10 +2536,6 @@ binding_handle_ovs_interface_changes(struct
> > > > > binding_ctx_in *b_ctx_in,
> > > > > return false;
> > > > > }
> > > > >
> > > > > - struct hmap qos_map = HMAP_INITIALIZER(&qos_map);
> > > > > - struct hmap *qos_map_ptr =
> > > > > - sset_is_empty(b_ctx_out->egress_ifaces) ? NULL : &qos_map;
> > > > > -
> > > > > /*
> > > > > * We consider an OVS interface for claiming if the following
> > > > > * 2 conditions are met:
> > > > > @@ -2525,24 +2564,22 @@ binding_handle_ovs_interface_changes(struct
> > > > > binding_ctx_in *b_ctx_in,
> > > > > if (iface_id && ofport > 0 &&
> > > > > is_iface_in_int_bridge(iface_rec, b_ctx_in->br_int))
> > > > > {
> > > > > handled = consider_iface_claim(iface_rec, iface_id,
> > > > > b_ctx_in,
> > > > > - b_ctx_out, qos_map_ptr);
> > > > > + b_ctx_out,
> > > > > b_ctx_out->qos_map);
> > > > > if (!handled) {
> > > > > break;
> > > > > }
> > > > > }
> > > > > }
> > > > >
> > > > > - if (handled && qos_map_ptr && set_noop_qos(b_ctx_in->ovs_idl_txn,
> > > > > - b_ctx_in->port_table,
> > > > > - b_ctx_in->qos_table,
> > > > > -
> > > > > b_ctx_out->egress_ifaces)) {
> > > > > - const char *entry;
> > > > > - SSET_FOR_EACH (entry, b_ctx_out->egress_ifaces) {
> > > > > - setup_qos(entry, &qos_map);
> > > > > + if (handled &&
> > > > > + set_noop_qos(b_ctx_in->ovs_idl_txn, b_ctx_in->port_table,
> > > > > + b_ctx_in->qos_table, b_ctx_out->egress_ifaces))
> > > > > {
> > > > > + struct shash_node *entry;
> > > > > + SHASH_FOR_EACH (entry, b_ctx_out->egress_ifaces) {
> > > > > + setup_qos(entry->name, entry->data, b_ctx_out->qos_map);
> > > > > }
> > > > > }
> > > > >
> > > > > - destroy_qos_map(&qos_map);
> > > > > return handled;
> > > > > }
> > > > >
> > > > > @@ -2977,10 +3014,6 @@ delete_done:
> > > > > return false;
> > > > > }
> > > > >
> > > > > - struct hmap qos_map = HMAP_INITIALIZER(&qos_map);
> > > > > - struct hmap *qos_map_ptr =
> > > > > - sset_is_empty(b_ctx_out->egress_ifaces) ? NULL : &qos_map;
> > > > > -
> > > > > SBREC_PORT_BINDING_TABLE_FOR_EACH_TRACKED (pb,
> > > > >
> > > > > b_ctx_in->port_binding_table) {
> > > > > /* Loop to handle create and update changes only. */
> > > > > @@ -2992,7 +3025,8 @@ delete_done:
> > > > > update_ld_peers(pb, b_ctx_out->local_datapaths);
> > > > > }
> > > > >
> > > > > - handled = handle_updated_port(b_ctx_in, b_ctx_out, pb,
> > > > > qos_map_ptr);
> > > > > + handled = handle_updated_port(b_ctx_in, b_ctx_out, pb,
> > > > > + b_ctx_out->qos_map);
> > > > > if (!handled) {
> > > > > break;
> > > > > }
> > > > > @@ -3009,7 +3043,8 @@ delete_done:
> > > > > sset_find_and_delete(b_ctx_out->postponed_ports,
> > > > > port_name);
> > > > > continue;
> > > > > }
> > > > > - handled = handle_updated_port(b_ctx_in, b_ctx_out, pb,
> > > > > qos_map_ptr);
> > > > > + handled = handle_updated_port(b_ctx_in, b_ctx_out, pb,
> > > > > + b_ctx_out->qos_map);
> > > > > if (!handled) {
> > > > > break;
> > > > > }
> > > > > @@ -3055,17 +3090,15 @@ delete_done:
> > > > > shash_destroy(&bridge_mappings);
> > > > > }
> > > > >
> > > > > - if (handled && qos_map_ptr && set_noop_qos(b_ctx_in->ovs_idl_txn,
> > > > > - b_ctx_in->port_table,
> > > > > - b_ctx_in->qos_table,
> > > > > -
> > > > > b_ctx_out->egress_ifaces)) {
> > > > > - const char *entry;
> > > > > - SSET_FOR_EACH (entry, b_ctx_out->egress_ifaces) {
> > > > > - setup_qos(entry, &qos_map);
> > > > > + if (handled &&
> > > > > + set_noop_qos(b_ctx_in->ovs_idl_txn, b_ctx_in->port_table,
> > > > > + b_ctx_in->qos_table, b_ctx_out->egress_ifaces))
> > > > > {
> > > > > + struct shash_node *entry;
> > > > > + SHASH_FOR_EACH (entry, b_ctx_out->egress_ifaces) {
> > > > > + setup_qos(entry->name, entry->data, b_ctx_out->qos_map);
> > > > > }
> > > > > }
> > > > >
> > > > > - destroy_qos_map(&qos_map);
> > > > > return handled;
> > > > > }
> > > > >
> > > > > diff --git a/controller/binding.h b/controller/binding.h
> > > > > index 6c3a98b02..8be33eddb 100644
> > > > > --- a/controller/binding.h
> > > > > +++ b/controller/binding.h
> > > > > @@ -91,7 +91,8 @@ struct binding_ctx_out {
> > > > > */
> > > > > bool non_vif_ports_changed;
> > > > >
> > > > > - struct sset *egress_ifaces;
> > > > > + struct shash *egress_ifaces;
> > > > > + struct hmap *qos_map;
> > > > > /* smap of OVS interface name as key and
> > > > > * OVS interface external_ids:iface-id as value. */
> > > > > struct smap *local_iface_ids;
> > > > > @@ -195,6 +196,8 @@ void set_pb_chassis_in_sbrec(const struct
> > > > > sbrec_port_binding *pb,
> > > > > const struct sbrec_chassis *chassis_rec,
> > > > > bool is_set);
> > > > >
> > > > > +void destroy_qos_map(struct hmap *qos_map);
> > > > > +
> > > > > /* Corresponds to each Port_Binding.type. */
> > > > > enum en_lport_type {
> > > > > LP_UNKNOWN,
> > > > > diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> > > > > index d6251afb8..066d76869 100644
> > > > > --- a/controller/ovn-controller.c
> > > > > +++ b/controller/ovn-controller.c
> > > > > @@ -1276,7 +1276,8 @@ struct ed_type_runtime_data {
> > > > > struct sset active_tunnels;
> > > > >
> > > > > /* runtime data engine private data. */
> > > > > - struct sset egress_ifaces;
> > > > > + struct shash egress_ifaces;
> > > > > + struct hmap qos_map;
> > > > > struct smap local_iface_ids;
> > > > >
> > > > > /* Tracked data. See below for more details and comments. */
> > > > > @@ -1372,7 +1373,8 @@ en_runtime_data_init(struct engine_node *node
> > > > > OVS_UNUSED,
> > > > > sset_init(&data->local_lports);
> > > > > related_lports_init(&data->related_lports);
> > > > > sset_init(&data->active_tunnels);
> > > > > - sset_init(&data->egress_ifaces);
> > > > > + shash_init(&data->egress_ifaces);
> > > > > + hmap_init(&data->qos_map);
> > > > > smap_init(&data->local_iface_ids);
> > > > > local_binding_data_init(&data->lbinding_data);
> > > > > shash_init(&data->local_active_ports_ipv6_pd);
> > > > > @@ -1392,7 +1394,8 @@ en_runtime_data_cleanup(void *data)
> > > > > sset_destroy(&rt_data->local_lports);
> > > > > related_lports_destroy(&rt_data->related_lports);
> > > > > sset_destroy(&rt_data->active_tunnels);
> > > > > - sset_destroy(&rt_data->egress_ifaces);
> > > > > + shash_destroy(&rt_data->egress_ifaces);
> > > > > + destroy_qos_map(&rt_data->qos_map);
> > > > > smap_destroy(&rt_data->local_iface_ids);
> > > > > local_datapaths_destroy(&rt_data->local_datapaths);
> > > > > shash_destroy(&rt_data->local_active_ports_ipv6_pd);
> > > > > @@ -1481,6 +1484,7 @@ init_binding_ctx(struct engine_node *node,
> > > > > b_ctx_out->related_lports_changed = false;
> > > > > b_ctx_out->non_vif_ports_changed = false;
> > > > > b_ctx_out->egress_ifaces = &rt_data->egress_ifaces;
> > > > > + b_ctx_out->qos_map = &rt_data->qos_map;
> > > > > b_ctx_out->lbinding_data = &rt_data->lbinding_data;
> > > > > b_ctx_out->local_iface_ids = &rt_data->local_iface_ids;
> > > > > b_ctx_out->postponed_ports = rt_data->postponed_ports;
> > > > > @@ -1510,13 +1514,14 @@ en_runtime_data_run(struct engine_node *node,
> > > > > void *data)
> > > > > sset_destroy(local_lports);
> > > > > related_lports_destroy(&rt_data->related_lports);
> > > > > sset_destroy(active_tunnels);
> > > > > - sset_destroy(&rt_data->egress_ifaces);
> > > > > + shash_clear(&rt_data->egress_ifaces);
> > > > > + destroy_qos_map(&rt_data->qos_map);
> > > > > + hmap_init(&rt_data->qos_map);
> > > > > smap_destroy(&rt_data->local_iface_ids);
> > > > > hmap_init(local_datapaths);
> > > > > sset_init(local_lports);
> > > > > related_lports_init(&rt_data->related_lports);
> > > > > sset_init(active_tunnels);
> > > > > - sset_init(&rt_data->egress_ifaces);
> > > > > smap_init(&rt_data->local_iface_ids);
> > > > > local_binding_data_init(&rt_data->lbinding_data);
> > > > > }
> > > > > diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> > > > > index 3e904c9dc..c986198a2 100644
> > > > > --- a/tests/system-ovn.at
> > > > > +++ b/tests/system-ovn.at
> > > > > @@ -6335,6 +6335,10 @@ ADD_NAMESPACES(sw01)
> > > > > ADD_VETH(sw01, sw01, br-int, "192.168.1.2/24", "f0:00:00:01:02:03")
> > > > > ovn-nbctl lsp-add sw0 sw01 \
> > > > > -- lsp-set-addresses sw01 "f0:00:00:01:02:03 192.168.1.2"
> > > > > +ADD_NAMESPACES(sw02)
> > > > > +ADD_VETH(sw02, sw02, br-int, "192.168.1.3/24", "f2:00:00:01:02:03")
> > > > > +ovn-nbctl lsp-add sw0 sw02 \
> > > > > + -- lsp-set-addresses sw02 "f2:00:00:01:02:03 192.168.1.3"
> > > > >
> > > > > ADD_NAMESPACES(public)
> > > > > ADD_VETH(public, public, br-ext, "192.168.2.2/24",
> > > > > "f0:00:00:01:02:05")
> > > > > @@ -6345,6 +6349,7 @@ ovn-nbctl lsp-add sw0 public \
> > > > > -- lsp-set-type public localnet \
> > > > > -- lsp-set-options public network_name=phynet
> > > > >
> > > > > +# Setup QoS on a localnet port
> > > > > AT_CHECK([ovn-nbctl set Logical_Switch_Port public
> > > > > options:qos_min_rate=200000])
> > > > > AT_CHECK([ovn-nbctl set Logical_Switch_Port public
> > > > > options:qos_max_rate=300000])
> > > > > AT_CHECK([ovn-nbctl set Logical_Switch_Port public
> > > > > options:qos_burst=3000000])
> > > > > @@ -6353,15 +6358,58 @@ OVS_WAIT_UNTIL([tc qdisc show | grep -q 'htb
> > > > > 1: dev ovs-public'])
> > > > > OVS_WAIT_UNTIL([tc class show dev ovs-public | \
> > > > > grep -q 'class htb .* rate 200Kbit ceil 300Kbit
> > > > > burst 375000b cburst 375000b'])
> > > > >
> > > > > +# Setup QoS on a logical switch ports
> > > > > +AT_CHECK([ovn-nbctl set Logical_Switch_Port sw01
> > > > > options:qos_min_rate=400000])
> > > > > +AT_CHECK([ovn-nbctl set Logical_Switch_Port sw01
> > > > > options:qos_max_rate=800000])
> > > > > +AT_CHECK([ovn-nbctl set Logical_Switch_Port sw01
> > > > > options:qos_burst=5000000])
> > > > > +AT_CHECK([ovs-vsctl set interface ovs-sw01
> > > > > external-ids:ovn-egress-iface=true])
> > > > > +OVS_WAIT_UNTIL([tc qdisc show | grep -q 'htb 1: dev ovs-sw01'])
> > > > > +OVS_WAIT_UNTIL([tc class show dev ovs-sw01 | \
> > > > > + grep -q 'class htb .* rate 400Kbit ceil 800Kbit
> > > > > burst 625000b cburst 625000b'])
> > > > > +
> > > > > +AT_CHECK([ovn-nbctl set Logical_Switch_Port sw02
> > > > > options:qos_min_rate=600000])
> > > > > +AT_CHECK([ovn-nbctl set Logical_Switch_Port sw02
> > > > > options:qos_max_rate=6000000])
> > > > > +AT_CHECK([ovn-nbctl set Logical_Switch_Port sw02
> > > > > options:qos_burst=6000000])
> > > > > +AT_CHECK([ovs-vsctl set interface ovs-sw02
> > > > > external-ids:ovn-egress-iface=true])
> > > > > +OVS_WAIT_UNTIL([tc qdisc show | grep -q 'htb 1: dev ovs-sw02'])
> > > > > +OVS_WAIT_UNTIL([tc class show dev ovs-sw02 | \
> > > > > + grep -q 'class htb .* rate 600Kbit ceil 6Mbit burst
> > > > > 750000b cburst 750000b'])
> > > > > +
> > > > > +AT_CHECK([ovn-appctl -t ovn-controller exit --restart])
> > > > > +OVS_WAIT_UNTIL([test "$(pidof ovn-controller)" = ""])
> > > > > +start_daemon ovn-controller
> > > > > +OVS_WAIT_UNTIL([test "$(pidof ovn-controller)" != ""])
> > > > > +
> > > > > +OVS_WAIT_UNTIL([tc qdisc show | grep -q 'htb 1: dev ovs-public'])
> > > > > +OVS_WAIT_UNTIL([tc class show dev ovs-public | \
> > > > > + grep -q 'class htb .* rate 200Kbit ceil 300Kbit
> > > > > burst 375000b cburst 375000b'])
> > > > > +OVS_WAIT_UNTIL([tc qdisc show | grep -q 'htb 1: dev ovs-sw01'])
> > > > > +OVS_WAIT_UNTIL([tc class show dev ovs-sw01 | \
> > > > > + grep -q 'class htb .* rate 400Kbit ceil 800Kbit
> > > > > burst 625000b cburst 625000b'])
> > > > > +OVS_WAIT_UNTIL([tc qdisc show | grep -q 'htb 1: dev ovs-sw02'])
> > > > > +OVS_WAIT_UNTIL([tc class show dev ovs-sw02 | \
> > > > > + grep -q 'class htb .* rate 600Kbit ceil 6Mbit burst
> > > > > 750000b cburst 750000b'])
> > > > >
> > > > > AT_CHECK([ovn-nbctl remove Logical_Switch_Port public options
> > > > > qos_max_rate=300000])
> > > > > OVS_WAIT_UNTIL([tc class show dev ovs-public | \
> > > > > grep -q 'class htb .* rate 200Kbit ceil 34359Mbit
> > > > > burst 375000b .*'])
> > > > >
> > > > > AT_CHECK([ovn-nbctl remove Logical_Switch_Port public options
> > > > > qos_min_rate=200000])
> > > > > +AT_CHECK([ovn-nbctl remove Logical_Switch_Port public options
> > > > > qos_max_rate=300000])
> > > > > AT_CHECK([ovn-nbctl remove Logical_Switch_Port public options
> > > > > qos_burst=3000000])
> > > > > OVS_WAIT_UNTIL([test "$(tc qdisc show | grep 'htb 1: dev
> > > > > ovs-public')" = ""])
> > > > >
> > > > > +AT_CHECK([ovn-nbctl set Logical_Switch_Port sw01
> > > > > options:qos_min_rate=200000])
> > > > > +OVS_WAIT_UNTIL([tc qdisc show | grep -q 'htb 1: dev ovs-sw01'])
> > > > > +OVS_WAIT_UNTIL([tc class show dev ovs-sw01 | \
> > > > > + grep -q 'class htb .* rate 200Kbit ceil 800Kbit
> > > > > burst 625000b cburst 625000b'])
> > > > > +
> > > > > +# Disable QoS rules from logical switch ports
> > > > > +AT_CHECK([ovn-nbctl set Logical_Switch_Port sw01
> > > > > options:qdisc_queue_id=0])
> > > > > +AT_CHECK([ovn-nbctl set Logical_Switch_Port sw02
> > > > > options:qdisc_queue_id=0])
> > > > > +OVS_WAIT_UNTIL([test "$(tc qdisc show | grep 'htb 1: dev ovs-sw01')"
> > > > > = ""])
> > > > > +OVS_WAIT_UNTIL([test "$(tc qdisc show | grep 'htb 1: dev ovs-sw02')"
> > > > > = ""])
> > > > > +
> > > > > kill $(pidof ovn-controller)
> > > > >
> > > > > as ovn-sb
> > > > > --
> > > > > 2.38.1
> > > > >
> > > > > _______________________________________________
> > > > > dev mailing list
> > > > > [email protected]
> > > > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> > > > >
> > > >
> > > _______________________________________________
> > > dev mailing list
> > > [email protected]
> > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> > >
> >
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev