The qos settings are managed using the 'options' fields in the "Port_Binding" table.
Signed-off-by: Babu Shanmugam <bscha...@redhat.com> --- ovn/controller/binding.c | 116 +++++++++++++++++++++++++++++++++++++++- ovn/controller/ovn-controller.c | 4 ++ 2 files changed, 118 insertions(+), 2 deletions(-) diff --git a/ovn/controller/binding.c b/ovn/controller/binding.c index 1854ff4..0556662 100644 --- a/ovn/controller/binding.c +++ b/ovn/controller/binding.c @@ -19,6 +19,8 @@ #include "lib/bitmap.h" #include "lib/sset.h" #include "lib/util.h" +#include "lib/hmap.h" +#include "lib/hash.h" #include "lib/vswitch-idl.h" #include "openvswitch/vlog.h" #include "ovn/lib/ovn-sb-idl.h" @@ -26,6 +28,13 @@ VLOG_DEFINE_THIS_MODULE(binding); +struct iface_qos { + struct hmap_node hmap_node; + const char *iface_id; + uint32_t policing_rate; + uint32_t policing_burst; +}; + void binding_register_ovs_idl(struct ovsdb_idl *ovs_idl) { @@ -46,7 +55,8 @@ binding_register_ovs_idl(struct ovsdb_idl *ovs_idl) } static void -get_local_iface_ids(const struct ovsrec_bridge *br_int, struct sset *lports) +get_local_iface_ids(const struct ovsrec_bridge *br_int, struct sset *lports, + struct hmap *iface_qos) { int i; @@ -68,6 +78,101 @@ get_local_iface_ids(const struct ovsrec_bridge *br_int, struct sset *lports) continue; } sset_add(lports, iface_id); + if (iface_rec->ingress_policing_rate > 0) { + struct iface_qos *qos = xmalloc(sizeof (*qos)); + + hmap_insert(iface_qos, &qos->hmap_node, + hash_string(iface_id, 0)); + qos->iface_id = iface_id; + qos->policing_rate = iface_rec->ingress_policing_rate; + qos->policing_burst = iface_rec->ingress_policing_burst; + } + } + } +} + +static struct iface_qos * +iface_qos_find(struct hmap *iface_qos, const char *iface_id) +{ + struct iface_qos *qos; + + HMAP_FOR_EACH_WITH_HASH(qos, hmap_node, hash_string(iface_id, 0), + iface_qos) { + if (!strcmp(qos->iface_id, iface_id)) { + return qos; + } + } + return NULL; +} + +static void +update_qos_map(const struct sbrec_port_binding *binding_rec, + struct hmap *iface_qos) +{ + struct iface_qos *qos; + bool is_vif = (strlen(binding_rec->type) == 0); + + qos = iface_qos_find(iface_qos, binding_rec->logical_port); + + uint32_t rate = + (uint32_t) smap_get_int(&binding_rec->options, "policing_rate", 0); + uint32_t burst = + (uint32_t) smap_get_int(&binding_rec->options, "policing_burst", 0); + + if (qos) { + if ((qos->policing_burst == burst && qos->policing_rate == rate) || + !is_vif) { + /* Remove this node, as there are no updates */ + hmap_remove(iface_qos, &qos->hmap_node); + } else { + /* Update */ + qos->policing_rate = rate; + qos->policing_burst = burst; + } + } else if (rate > 0 && is_vif) { + /* New setting */ + qos = xmalloc(sizeof (*qos)); + + hmap_insert(iface_qos, &qos->hmap_node, + hash_string(binding_rec->logical_port, 0)); + qos->iface_id = binding_rec->logical_port; + qos->policing_rate = rate; + qos->policing_burst = burst; + } +} + +static void +update_qos_interface_table(const struct ovsrec_bridge *br_int, + struct hmap *iface_qos) +{ + int i; + + for (i = 0; i < br_int->n_ports; i++) { + const struct ovsrec_port *port_rec = br_int->ports[i]; + const char *iface_id; + int j; + + if (!strcmp(port_rec->name, br_int->name)) { + continue; + } + + for (j = 0; j < port_rec->n_interfaces; j++) { + struct ovsrec_interface *iface_rec; + + iface_rec = port_rec->interfaces[j]; + iface_id = smap_get(&iface_rec->external_ids, "iface-id"); + if (!iface_id) { + continue; + } + struct iface_qos *qos = iface_qos_find(iface_qos, iface_id); + + if (!qos) { + continue; + } + ovsrec_interface_set_ingress_policing_rate(iface_rec, + qos->policing_rate); + ovsrec_interface_set_ingress_policing_burst(iface_rec, + qos->policing_burst); } } } @@ -125,6 +230,7 @@ binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int, const struct sbrec_chassis *chassis_rec; const struct sbrec_port_binding *binding_rec; struct sset lports, all_lports; + struct hmap iface_qos = HMAP_INITIALIZER(&iface_qos); const char *name; if (!ctx->ovnsb_idl_txn) { @@ -139,7 +245,7 @@ binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int, sset_init(&lports); sset_init(&all_lports); if (br_int) { - get_local_iface_ids(br_int, &lports); + get_local_iface_ids(br_int, &lports, &iface_qos); } else { /* We have no integration bridge, therefore no local logical ports. * We'll remove our chassis from all port binding records below. */ @@ -161,6 +267,7 @@ binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int, /* Add child logical port to the set of all local ports. */ sset_add(&all_lports, binding_rec->logical_port); } + update_qos_map(binding_rec, &iface_qos); if (binding_rec->chassis == chassis_rec) { continue; } @@ -182,6 +289,11 @@ binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int, update_ct_zones(&all_lports, ct_zones, ct_zone_bitmap); + if (br_int) { + update_qos_interface_table(br_int, &iface_qos); + } + + hmap_destroy(&iface_qos); sset_destroy(&lports); sset_destroy(&all_lports); } diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 02ecb3e..8b7eb64 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -239,6 +239,10 @@ main(int argc, char *argv[]) ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_interface_col_name); ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_interface_col_type); ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_interface_col_options); + ovsdb_idl_add_column(ovs_idl_loop.idl, + &ovsrec_interface_col_ingress_policing_rate); + ovsdb_idl_add_column(ovs_idl_loop.idl, + &ovsrec_interface_col_ingress_policing_burst); ovsdb_idl_add_table(ovs_idl_loop.idl, &ovsrec_table_port); ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_port_col_name); ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_port_col_interfaces); -- 1.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev