[ovs-dev] [PATCH] ovn: add qos function.
wang.qianyu at zte.com.cn
wang.qianyu at zte.com.cn
Mon Jun 26 02:06:17 UTC 2017
The current qos function is used for geneve
tunnel to control the traffic out the ovs. And have no to-port qos
control.
This patch do the modification as follow
1. change the qos configuration with direction to consistent with neutron
qos rule. Add qos_ingress_max_rate, qos_ingress_burst, qos_egress_max_rate
and qos_egress_burst to instead old qos_max_rate and qos_burst.
2. By configure the interface table field of ingress_policing_rate and
ingress_policing_bust to implement the ingress qos control.
3. Add qos configuration to qos field of port table to implement egress
qos
control.
4. Add dpdk qos support.
Change-Id: Ie90364cb5bee7f6b7e3086e0867997f7edab7038
---
ovn/controller/binding.c | 525
++++++++++++++++++++++++++++-------------------
ovn/northd/ovn-northd.c | 17 +-
ovn/ovn-nb.xml | 18 +-
ovn/ovn-sb.xml | 18 +-
4 files changed, 360 insertions(+), 218 deletions(-)
diff --git a/ovn/controller/binding.c b/ovn/controller/binding.c
index bb76608..f40273f 100644
--- a/ovn/controller/binding.c
+++ b/ovn/controller/binding.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, 2016, 2017 Nicira, Inc.
+/* Copyright (c) 2015, 2016, 2017 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,13 +33,26 @@ VLOG_DEFINE_THIS_MODULE(binding);
#define OVN_QOS_TYPE "linux-htb"
+#define IS_SUB_PORT(PB) (PB->parent_port && \
+ PB->parent_port[0])
+
struct qos_queue {
struct hmap_node node;
uint32_t queue_id;
- uint32_t max_rate;
- uint32_t burst;
+ uint32_t ingress_max_rate;
+ uint32_t ingress_burst;
+ uint32_t egress_max_rate;
+ uint32_t egress_burst;
};
+static void
+add_column_noalert(struct ovsdb_idl *idl,
+ const struct ovsdb_idl_column *column)
+{
+ ovsdb_idl_add_column(idl, column);
+ ovsdb_idl_omit_alert(idl, column);
+}
+
void
binding_register_ovs_idl(struct ovsdb_idl *ovs_idl)
{
@@ -59,16 +72,28 @@ binding_register_ovs_idl(struct ovsdb_idl *ovs_idl)
ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_name);
ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_external_ids);
ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_status);
+ add_column_noalert(ovs_idl,
&ovsrec_interface_col_ingress_policing_rate);
+ add_column_noalert(ovs_idl,
&ovsrec_interface_col_ingress_policing_burst);
+ add_column_noalert(ovs_idl, &ovsrec_port_col_qos);
ovsdb_idl_add_table(ovs_idl, &ovsrec_table_qos);
- ovsdb_idl_add_column(ovs_idl, &ovsrec_qos_col_type);
+ add_column_noalert(ovs_idl, &ovsrec_qos_col_external_ids);
+ add_column_noalert(ovs_idl, &ovsrec_qos_col_other_config);
+ add_column_noalert(ovs_idl, &ovsrec_qos_col_type);
+ add_column_noalert(ovs_idl, &ovsrec_qos_col_queues);
+
+ ovsdb_idl_add_table(ovs_idl, &ovsrec_table_queue);
+ add_column_noalert(ovs_idl, &ovsrec_queue_col_external_ids);
+ add_column_noalert(ovs_idl, &ovsrec_queue_col_other_config);
+ add_column_noalert(ovs_idl, &ovsrec_queue_col_dscp);
}
static void
get_local_iface_ids(const struct ovsrec_bridge *br_int,
struct shash *lport_to_iface,
struct sset *local_lports,
- struct sset *egress_ifaces)
+ struct sset *egress_ifaces,
+ struct shash *lport_to_pport)
{
int i;
@@ -90,6 +115,7 @@ get_local_iface_ids(const struct ovsrec_bridge *br_int,
if (iface_id && ofport > 0) {
shash_add(lport_to_iface, iface_id, iface_rec);
+ shash_add(lport_to_pport, iface_id, port_rec);
sset_add(local_lports, iface_id);
}
@@ -163,206 +189,39 @@ add_local_datapath(const struct ldatapath_index
*ldatapaths,
local_datapaths);
}
-static void
-get_qos_params(const struct sbrec_port_binding *pb, struct hmap
*queue_map)
+static bool
+get_qos_params(const struct sbrec_port_binding *pb, struct qos_queue
*queue)
{
- 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 ingress_max_rate = smap_get_int(&pb->options,
"qos_ingress_max_rate", 0);
+ uint32_t ingress_burst = smap_get_int(&pb->options,
"qos_ingress_burst", 0);
+ uint32_t egress_max_rate = smap_get_int(&pb->options,
"qos_egress_max_rate", 0);
+ uint32_t egress_burst = smap_get_int(&pb->options,
"qos_egress_burst", 0);
uint32_t queue_id = smap_get_int(&pb->options, "qdisc_queue_id", 0);
-
- if ((!max_rate && !burst) || !queue_id) {
+
+ if (!queue_id) {
/* Qos is not configured for this port. */
- return;
- }
-
- struct qos_queue *node = xzalloc(sizeof *node);
- hmap_insert(queue_map, &node->node, hash_int(queue_id, 0));
- node->max_rate = max_rate;
- node->burst = burst;
- node->queue_id = queue_id;
-}
-
-static const struct ovsrec_qos *
-get_noop_qos(struct controller_ctx *ctx)
-{
- const struct ovsrec_qos *qos;
- OVSREC_QOS_FOR_EACH (qos, ctx->ovs_idl) {
- if (!strcmp(qos->type, "linux-noop")) {
- return qos;
- }
- }
-
- if (!ctx->ovs_idl_txn) {
- return NULL;
- }
- qos = ovsrec_qos_insert(ctx->ovs_idl_txn);
- ovsrec_qos_set_type(qos, "linux-noop");
- return qos;
-}
-
-static bool
-set_noop_qos(struct controller_ctx *ctx, struct sset *egress_ifaces)
-{
- if (!ctx->ovs_idl_txn) {
- return false;
- }
-
- const struct ovsrec_qos *noop_qos = get_noop_qos(ctx);
- if (!noop_qos) {
return false;
}
- const struct ovsrec_port *port;
- size_t count = 0;
-
- OVSREC_PORT_FOR_EACH (port, ctx->ovs_idl) {
- if (sset_contains(egress_ifaces, port->name)) {
- ovsrec_port_set_qos(port, noop_qos);
- count++;
- }
- if (sset_count(egress_ifaces) == count) {
- break;
- }
- }
+ queue->ingress_max_rate = ingress_max_rate;
+ queue->ingress_burst = ingress_burst;
+ queue->egress_max_rate = egress_max_rate;
+ queue->egress_burst = egress_burst;
+
+ queue->queue_id = queue_id;
return true;
}
static void
-set_qos_type(struct netdev *netdev, const char *type)
-{
- int error = netdev_set_qos(netdev, type, NULL);
- if (error) {
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
- VLOG_WARN_RL(&rl, "%s: could not set qdisc type \"%s\" (%s)",
- netdev_get_name(netdev), type, ovs_strerror(error));
- }
-}
-
-static void
-setup_qos(const char *egress_iface, struct hmap *queue_map)
-{
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
- struct netdev *netdev_phy;
-
- if (!egress_iface) {
- /* Queues cannot be configured. */
- return;
- }
-
- int error = netdev_open(egress_iface, NULL, &netdev_phy);
- if (error) {
- VLOG_WARN_RL(&rl, "%s: could not open netdev (%s)",
- egress_iface, ovs_strerror(error));
- return;
- }
-
- /* Check current qdisc. */
- const char *qdisc_type;
- struct smap qdisc_details;
-
- smap_init(&qdisc_details);
- if (netdev_get_qos(netdev_phy, &qdisc_type, &qdisc_details) != 0 ||
- qdisc_type[0] == '\0') {
- smap_destroy(&qdisc_details);
- netdev_close(netdev_phy);
- /* Qos is not supported. */
- return;
- }
- smap_destroy(&qdisc_details);
-
- /* If we're not actually being requested to do any QoS:
- *
- * - If the current qdisc type is OVN_QOS_TYPE, then we clear the
qdisc
- * type to "". Otherwise, it's possible that our own leftover
qdisc
- * settings could cause strange behavior on egress. Also, QoS
is
- * expensive and may waste CPU time even if it's not really in
use.
- *
- * OVN isn't the only software that can configure qdiscs, and
- * physical interfaces are shared resources, so there is some
risk in
- * this strategy: we could disrupt some other program's QoS.
- * Probably, to entirely avoid this possibility we would need
to add
- * a configuration setting.
- *
- * - Otherwise leave the qdisc alone. */
- if (hmap_is_empty(queue_map)) {
- if (!strcmp(qdisc_type, OVN_QOS_TYPE)) {
- set_qos_type(netdev_phy, "");
- }
- netdev_close(netdev_phy);
- return;
- }
-
- /* Configure qdisc. */
- if (strcmp(qdisc_type, OVN_QOS_TYPE)) {
- set_qos_type(netdev_phy, OVN_QOS_TYPE);
- }
-
- /* Check and delete if needed. */
- struct netdev_queue_dump dump;
- unsigned int queue_id;
- struct smap queue_details;
- struct qos_queue *sb_info;
- struct hmap consistent_queues;
-
- smap_init(&queue_details);
- hmap_init(&consistent_queues);
- NETDEV_QUEUE_FOR_EACH (&queue_id, &queue_details, &dump, netdev_phy)
{
- bool is_queue_needed = false;
-
- HMAP_FOR_EACH_WITH_HASH (sb_info, node, hash_int(queue_id, 0),
- queue_map) {
- is_queue_needed = true;
- if (sb_info->max_rate ==
- smap_get_int(&queue_details, "max-rate", 0)
- && sb_info->burst == smap_get_int(&queue_details,
"burst", 0)) {
- /* This queue is consistent. */
- hmap_insert(&consistent_queues, &sb_info->node,
- hash_int(queue_id, 0));
- break;
- }
- }
-
- if (!is_queue_needed) {
- error = netdev_delete_queue(netdev_phy, queue_id);
- if (error) {
- VLOG_WARN_RL(&rl, "%s: could not delete queue %u (%s)",
- egress_iface, queue_id,
ovs_strerror(error));
- }
- }
- }
-
- /* Create/Update queues. */
- HMAP_FOR_EACH (sb_info, node, queue_map) {
- if (hmap_contains(&consistent_queues, &sb_info->node)) {
- hmap_remove(&consistent_queues, &sb_info->node);
- continue;
- }
-
- smap_clear(&queue_details);
- smap_add_format(&queue_details, "max-rate", "%d",
sb_info->max_rate);
- smap_add_format(&queue_details, "burst", "%d", sb_info->burst);
- error = netdev_set_queue(netdev_phy, sb_info->queue_id,
- &queue_details);
- if (error) {
- VLOG_WARN_RL(&rl, "%s: could not configure queue %u (%s)",
- egress_iface, sb_info->queue_id,
ovs_strerror(error));
- }
- }
- smap_destroy(&queue_details);
- hmap_destroy(&consistent_queues);
- netdev_close(netdev_phy);
-}
-
-static void
consider_local_datapath(struct controller_ctx *ctx,
const struct ldatapath_index *ldatapaths,
const struct lport_index *lports,
const struct sbrec_chassis *chassis_rec,
const struct sbrec_port_binding *binding_rec,
- struct hmap *qos_map,
struct hmap *local_datapaths,
struct shash *lport_to_iface,
- struct sset *local_lports)
+ struct sset *local_lports,
+ struct shash *lport_to_pport)
{
const struct ovsrec_interface *iface_rec
= shash_find_data(lport_to_iface, binding_rec->logical_port);
@@ -374,12 +233,15 @@ consider_local_datapath(struct controller_ctx *ctx,
if (binding_rec->parent_port && binding_rec->parent_port[0]) {
/* Add child logical port to the set of all local ports. */
sset_add(local_lports, binding_rec->logical_port);
+ const struct ovsrec_port *port_rec =
+ shash_find_data(lport_to_pport,
binding_rec->parent_port);
+ if (port_rec) {
+ VLOG_INFO("port_rec exist, port-name is %s",
binding_rec->logical_port);
+ shash_add(lport_to_pport, binding_rec->logical_port,
port_rec);
+ }
}
add_local_datapath(ldatapaths, lports, binding_rec->datapath,
false, local_datapaths);
- if (iface_rec && qos_map && ctx->ovs_idl_txn) {
- get_qos_params(binding_rec, qos_map);
- }
/* This port is in our chassis unless it is a localport. */
if (strcmp(binding_rec->type, "localport")) {
our_chassis = true;
@@ -442,6 +304,266 @@ consider_local_datapath(struct controller_ctx *ctx,
}
}
+static void
+del_qos(const struct ovsrec_qos *qos)
+{
+ int n_queue;
+ struct shash queues = SHASH_INITIALIZER(&queues);
+ char uuid_s[UUID_LEN + 1];
+ for (n_queue = 0; n_queue< qos->n_queues; n_queue++) {
+ struct ovsrec_queue *queue = qos->value_queues[n_queue];
+ sprintf(uuid_s, UUID_FMT, UUID_ARGS(&queue->header_.uuid));
+ shash_add(&queues, uuid_s, queue);
+ }
+ ovsrec_qos_delete(qos);
+
+ struct shash_node *node, *next_node;
+ SHASH_FOR_EACH_SAFE(node, next_node, &queues) {
+ ovsrec_queue_delete(node->data);
+ }
+}
+
+static void
+clear_port_qos(struct ovsrec_port *port_rec,
+ const struct sbrec_port_binding *binding_rec)
+{
+ if (IS_SUB_PORT(binding_rec) && port_rec->qos) {
+ int n_queue;
+ for (n_queue = 0; n_queue< port_rec->qos->n_queues; n_queue++) {
+ struct ovsrec_queue *queue =
port_rec->qos->value_queues[n_queue];
+ const char *port_id = smap_get(&queue->external_ids,
"port_id");
+ if (!strcmp(binding_rec->logical_port, port_id)) {
+ ovsrec_qos_update_queues_delkey(port_rec->qos,
+ port_rec->qos->key_queues[n_queue]);
+ ovsrec_queue_delete(queue);
+ break;
+ }
+ }
+ } else if (port_rec->qos) {
+ if (port_rec->qos) {
+ struct ovsrec_qos *qos = port_rec->qos;
+ ovsrec_port_set_qos(port_rec, NULL);
+ del_qos(qos);
+ }
+
+ for (int j = 0; j < port_rec->n_interfaces; j++) {
+ struct ovsrec_interface *iface_rec = port_rec->interfaces[j];
+ const char *iface_id = smap_get(&iface_rec->external_ids,
+ "iface-id");
+ if (iface_id && !strcmp(binding_rec->logical_port, iface_id))
{
+ if (iface_rec->ingress_policing_burst != 0) {
+ ovsrec_interface_set_ingress_policing_burst(iface_rec,
+ 0);
+ }
+ if (iface_rec->ingress_policing_rate != 0) {
+ ovsrec_interface_set_ingress_policing_rate(iface_rec,
+ 0);
+ }
+ }
+ }
+ }
+}
+
+static char *
+get_port_id(const struct sbrec_port_binding *binding_rec)
+{
+ if (IS_SUB_PORT(binding_rec)) {
+ return binding_rec->parent_port;
+ } else {
+ return binding_rec->logical_port;
+ }
+}
+
+static void
+set_interface_param( struct ovsrec_port *port_rec,
+ struct qos_queue *qos_param,
+ const struct sbrec_port_binding *binding_rec)
+{
+ for (int j = 0; j < port_rec->n_interfaces; j++) {
+ /* configure interface policing burst and policing rate*/
+ struct ovsrec_interface *iface_rec = port_rec->interfaces[j];
+ const char *iface_id = smap_get(&iface_rec->external_ids,
+ "iface-id");
+ if (iface_id && !strcmp(binding_rec->logical_port, iface_id)) {
+ if(qos_param->ingress_burst
+ != iface_rec->ingress_policing_burst) {
+ ovsrec_interface_set_ingress_policing_burst(iface_rec,
+ (int64_t)qos_param->ingress_burst);
+ }
+
+ if(qos_param->ingress_max_rate
+ != iface_rec->ingress_policing_rate) {
+ ovsrec_interface_set_ingress_policing_rate(iface_rec,
+ (int64_t)qos_param->ingress_max_rate);
+ }
+ break;
+ }
+ }
+}
+
+static const struct ovsrec_queue *
+get_queue_by_port(struct controller_ctx *ctx,
+ const char *port_name)
+{
+ const struct ovsrec_queue *queue, *next_queue;
+ OVSREC_QUEUE_FOR_EACH_SAFE(queue, next_queue, ctx->ovs_idl) {
+ const char *port_id = smap_get(&queue->external_ids, "port_id");
+ if (port_id && !strcmp(port_name, port_id)) {
+ return queue;
+ }
+ }
+ struct ovsrec_queue *newqueue =
+ ovsrec_queue_insert(ctx->ovs_idl_txn);
+ ovsrec_queue_update_external_ids_setkey(newqueue, "port_id",
+ port_name);
+ return newqueue;
+
+}
+
+static void
+set_queue(struct controller_ctx *ctx,
+ const struct ovsrec_qos *qos,
+ struct qos_queue *qos_param,
+ const struct sbrec_port_binding *binding_rec)
+{
+ int n_queue;
+ for (n_queue = 0; n_queue< qos->n_queues; n_queue++) {
+ struct ovsrec_queue *queue = qos->value_queues[n_queue];
+ const char *port_id = smap_get(&queue->external_ids, "port_id");
+ if (!strcmp(port_id, binding_rec->logical_port)) {
+ struct smap other_config;
+ smap_init(&other_config);
+ smap_add_format(&other_config, "max-rate", "%d",
+ qos_param->egress_max_rate*1000);
+ smap_add_format(&other_config, "burst", "%d",
+ qos_param->egress_burst*1000);
+ ovsrec_queue_set_other_config(queue, &other_config);
+ return;
+ }
+ }
+
+ const struct ovsrec_queue * queue =
+ get_queue_by_port(ctx, binding_rec->logical_port);
+ struct smap other_config;
+ smap_init(&other_config);
+ smap_add_format(&other_config, "max-rate", "%d",
+ qos_param->egress_max_rate);
+ smap_add_format(&other_config, "burst", "%d",
+ qos_param->egress_burst);
+ ovsrec_queue_set_other_config(queue, &other_config);
+ ovsrec_qos_update_queues_setkey(qos,
+ (int64_t)qos_param->queue_id,
+ queue);
+
+}
+
+static void
+set_qos_para(const struct ovsrec_qos *qos,
+ const struct qos_queue *qos_param,
+ const char *dptype)
+{
+ if (!strcmp(dptype, "netdev")) {
+ ovsrec_qos_set_type(qos, "egress-policer");
+ struct smap other_config;
+ smap_init(&other_config);
+ smap_add_format(&other_config, "cir", "%d",
+ qos_param->egress_max_rate*1000/8);
+ smap_add_format(&other_config, "cbs", "%d",
+ qos_param->egress_burst*1000/8);
+ ovsrec_qos_set_other_config(qos, &other_config);
+ } else {
+ ovsrec_qos_set_type(qos, "linux-htb");
+ }
+}
+
+
+static const struct ovsrec_qos *
+get_qos_by_port(struct controller_ctx *ctx,
+ const char *port_name)
+{
+ const struct ovsrec_qos *qos, *next_qos;
+ OVSREC_QOS_FOR_EACH_SAFE(qos, next_qos, ctx->ovs_idl) {
+ const char *port_id = smap_get(&qos->external_ids, "port_id");
+ if (port_id && !strcmp(port_name, port_id)) {
+ return qos;
+ }
+ }
+ struct ovsrec_qos *qosnew = ovsrec_qos_insert(ctx->ovs_idl_txn);
+ /* set port_id to external_id of qos */
+ struct smap new_ids;
+ smap_clone(&new_ids, &qosnew->external_ids);
+ smap_add(&new_ids, "port_id", port_name);
+ ovsrec_qos_set_external_ids(qosnew, &new_ids);
+ smap_destroy(&new_ids);
+ return qosnew;
+}
+
+static void
+setup_qos(struct controller_ctx *ctx,
+ const struct shash *lport_to_pport,
+ const char *dptype)
+{
+
+ struct qos_queue qos_param;
+ struct sset exist_pb = SSET_INITIALIZER(&exist_pb);
+ if (!ctx->ovs_idl_txn) {
+ return;
+ }
+ /* add queue and qos */
+ const struct sbrec_port_binding *binding_rec, *next_bind;
+ SBREC_PORT_BINDING_FOR_EACH_SAFE(binding_rec, next_bind,
ctx->ovnsb_idl) {
+ sset_add(&exist_pb, binding_rec->logical_port);
+
+ struct ovsrec_port *port_rec = shash_find_data(lport_to_pport,
+ binding_rec->logical_port);
+ if (!port_rec) {
+ continue;
+ }
+ if (!get_qos_params(binding_rec, &qos_param)) {
+ clear_port_qos(port_rec, binding_rec);
+ continue;
+ }
+ if (port_rec->qos) {
+ if (!IS_SUB_PORT(binding_rec)) {
+ /* not sub port */
+ set_interface_param(port_rec, &qos_param,
+ binding_rec);
+ }
+ set_qos_para(port_rec->qos, &qos_param, dptype);
+ set_queue(ctx, port_rec->qos, &qos_param, binding_rec);
+ } else {
+ char *port_name = get_port_id(binding_rec);
+ const struct ovsrec_qos *qos = get_qos_by_port(ctx,
port_name);
+ set_qos_para(qos, &qos_param, dptype);
+ ovsrec_port_set_qos(port_rec, qos);
+ if (!IS_SUB_PORT(binding_rec)) {
+ /* not sub port */
+ set_interface_param(port_rec, &qos_param, binding_rec);
+ }
+ set_queue(ctx, qos, &qos_param, binding_rec);
+ }
+ }
+ /* delete not used qos */
+ const struct ovsrec_qos *qos, *next_qos;
+ OVSREC_QOS_FOR_EACH_SAFE(qos, next_qos, ctx->ovs_idl) {
+ const char *port_id = smap_get(&qos->external_ids, "port_id");
+ if (port_id && !shash_find_data(lport_to_pport, port_id)) {
+ del_qos(qos);
+ }
+ }
+
+ /* delete not used queue */
+ const struct ovsrec_queue *queue, *next_queue;
+ OVSREC_QUEUE_FOR_EACH_SAFE(queue, next_queue, ctx->ovs_idl) {
+ const char *port_id = smap_get(&queue->external_ids, "port_id");
+ if (port_id && !sset_contains(&exist_pb, port_id)) {
+ ovsrec_queue_delete(queue);
+ }
+ }
+ sset_destroy(&exist_pb);
+
+}
+
void
binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge
*br_int,
const struct sbrec_chassis *chassis_rec,
@@ -455,13 +577,11 @@ binding_run(struct controller_ctx *ctx, const struct
ovsrec_bridge *br_int,
const struct sbrec_port_binding *binding_rec;
struct shash lport_to_iface = SHASH_INITIALIZER(&lport_to_iface);
+ struct shash lport_to_pport = SHASH_INITIALIZER(&lport_to_pport);
struct sset egress_ifaces = SSET_INITIALIZER(&egress_ifaces);
- struct hmap qos_map;
-
- hmap_init(&qos_map);
if (br_int) {
get_local_iface_ids(br_int, &lport_to_iface, local_lports,
- &egress_ifaces);
+ &egress_ifaces, &lport_to_pport);
}
/* Run through each binding record to see if it is resident on this
@@ -470,23 +590,16 @@ binding_run(struct controller_ctx *ctx, const struct
ovsrec_bridge *br_int,
SBREC_PORT_BINDING_FOR_EACH(binding_rec, ctx->ovnsb_idl) {
consider_local_datapath(ctx, ldatapaths, lports,
chassis_rec, binding_rec,
- sset_is_empty(&egress_ifaces) ? NULL :
- &qos_map, local_datapaths,
&lport_to_iface,
- local_lports);
+ local_datapaths, &lport_to_iface,
+ local_lports, &lport_to_pport);
}
- if (!sset_is_empty(&egress_ifaces)
- && set_noop_qos(ctx, &egress_ifaces)) {
- const char *entry;
- SSET_FOR_EACH (entry, &egress_ifaces) {
- setup_qos(entry, &qos_map);
- }
- }
+ setup_qos(ctx, &lport_to_pport, br_int->datapath_type);
shash_destroy(&lport_to_iface);
+ shash_destroy(&lport_to_pport);
sset_destroy(&egress_ifaces);
- hmap_destroy(&qos_map);
}
/* Returns true if the database is all cleaned up, false if more work is
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index be3b371..c683953 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -1,4 +1,4 @@
-/*
+/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -371,8 +371,10 @@ free_chassis_queueid(struct hmap *set, struct
sbrec_chassis *chassis,
static inline bool
port_has_qos_params(const struct smap *opts)
{
- return (smap_get(opts, "qos_max_rate") ||
- smap_get(opts, "qos_burst"));
+ return (smap_get(opts, "qos_ingress_max_rate") ||
+ smap_get(opts, "qos_ingress_burst") ||
+ smap_get(opts, "qos_egress_max_rate") ||
+ smap_get(opts, "qos_egress_burst"));
}
@@ -3715,12 +3717,19 @@ build_lswitch_flows(struct hmap *datapaths, struct
hmap *ports,
}
ds_clear(&match);
+ ds_clear(&actions);
ds_put_format(&match, "outport == %s", op->json_key);
if (lsp_is_enabled(op->nbsp)) {
build_port_security_l2("eth.dst", op->ps_addrs,
op->n_ps_addrs,
&match);
+ const char *queue_id = smap_get(&op->sb->options,
+ "qdisc_queue_id");
+ if (queue_id) {
+ ds_put_format(&actions, "set_queue(%s); ", queue_id);
+ }
+ ds_put_cstr(&actions, "output;");
ovn_lflow_add(lflows, op->od, S_SWITCH_OUT_PORT_SEC_L2, 50,
- ds_cstr(&match), "output;");
+ ds_cstr(&match), ds_cstr(&actions));
} else {
ovn_lflow_add(lflows, op->od, S_SWITCH_OUT_PORT_SEC_L2, 150,
ds_cstr(&match), "drop;");
diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
index 32c10c1..56229e9 100644
--- a/ovn/ovn-nb.xml
+++ b/ovn/ovn-nb.xml
@@ -435,14 +435,24 @@
(empty string)
</p>
- <column name="options" key="qos_max_rate">
+ <column name="options" key="qos_ingress_max_rate">
If set, indicates the maximum rate for data sent from this
interface,
- in bit/s. The traffic will be shaped according to this limit.
+ in kbps. The traffic will be shaped according to this limit.
</column>
- <column name="options" key="qos_burst">
+ <column name="options" key="qos_ingress_burst">
If set, indicates the maximum burst size for data sent from
this
- interface, in bits.
+ interface, in kb.
+ </column>
+
+ <column name="options" key="qos_egress_max_rate">
+ If set, indicates the maximum rate for data sent to this
interface,
+ in kbps. The traffic will be shaped according to this limit.
+ </column>
+
+ <column name="options" key="qos_egress_burst">
+ If set, indicates the maximum burst size for data sent to this
+ interface, in kb.
</column>
</group>
</group>
diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml
index b22d1ac..c8b940d 100644
--- a/ovn/ovn-sb.xml
+++ b/ovn/ovn-sb.xml
@@ -2103,14 +2103,24 @@ tcp.flags = RST;
(empty string)
</p>
- <column name="options" key="qos_max_rate">
+ <column name="options" key="qos_ingress_max_rate">
If set, indicates the maximum rate for data sent from this
interface,
- in bit/s. The traffic will be shaped according to this limit.
+ in kbps. The traffic will be shaped according to this limit.
</column>
- <column name="options" key="qos_burst">
+ <column name="options" key="qos_ingress_burst">
If set, indicates the maximum burst size for data sent from this
- interface, in bits.
+ interface, in kb.
+ </column>
+
+ <column name="options" key="qos_egress_max_rate">
+ If set, indicates the maximum rate for data sent to this
interface,
+ in kbps. The traffic will be shaped according to this limit.
+ </column>
+
+ <column name="options" key="qos_egress_burst">
+ If set, indicates the maximum burst size for data sent to this
+ interface, in kb.
</column>
<column name="options" key="qdisc_queue_id"
--
2.7.2.windows.1
More information about the dev
mailing list