Skip to content

Commit

Permalink
northd: apply QoS rules on the localnet port related to LSP ports
Browse files Browse the repository at this point in the history
This patch allows to apply QoS rules on the localnet port related to
logical switch ports running on the same datapath. Considering the
following netowrk configuration:

LSP{0,1} -- LogicalSwitch -- Localnet0

It is possible to apply the following QoS rules on Localnet0 on egress traffic
entering the cluster from LSP{0,1}:
- LSP0: min-rate r0, max_rate R0
- LSP1: min-rate r1, max_rate R1

Acked-by: Numan Siddique <numans@ovn.org>
Acked-By: Ihar Hrachyshka <ihrachys@redhat.com>
Tested-by: Rodolfo Alonso <ralonsoh@redhat.com>
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Signed-off-by: Mark Michelson <mmichels@redhat.com>
  • Loading branch information
LorenzoBianconi authored and putnopvut committed May 18, 2023
1 parent 13ce5c0 commit 1c99a50
Show file tree
Hide file tree
Showing 6 changed files with 306 additions and 11 deletions.
6 changes: 3 additions & 3 deletions controller/binding.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,9 @@ get_qos_egress_port_interface(struct shash *bridge_mappings,
continue;
}

bool is_egress_iface = smap_get_bool(&iface->external_ids,
"ovn-egress-iface", false);
if (is_egress_iface) {
if (smap_get_bool(&iface->external_ids,
"ovn-egress-iface", false) ||
!strcmp(iface->type, "")) {
*pport = port;
return iface;
}
Expand Down
26 changes: 20 additions & 6 deletions northd/northd.c
Original file line number Diff line number Diff line change
Expand Up @@ -5737,15 +5737,29 @@ build_lswitch_port_sec_op(struct ovn_port *op, struct hmap *lflows,
ds_cstr(match), ds_cstr(actions),
op->key, &op->nbsp->header_);

if (!lsp_is_localnet(op->nbsp) && !op->od->n_localnet_ports) {
return;
}

ds_clear(actions);
ds_put_format(actions, "set_queue(%s); output;", queue_id);

ds_clear(match);
if (lsp_is_localnet(op->nbsp)) {
ds_clear(match);
ds_clear(actions);
ds_put_format(match, "outport == %s", op->json_key);
ds_put_format(actions, "set_queue(%s); output;", queue_id);
ovn_lflow_add_with_lport_and_hint(lflows, op->od,
S_SWITCH_OUT_APPLY_PORT_SEC, 100,
ds_cstr(match), ds_cstr(actions),
op->key, &op->nbsp->header_);
S_SWITCH_OUT_APPLY_PORT_SEC, 100,
ds_cstr(match), ds_cstr(actions),
op->key, &op->nbsp->header_);
} else if (op->od->n_localnet_ports) {
ds_put_format(match, "outport == %s && inport == %s",
op->od->localnet_ports[0]->json_key,
op->json_key);
ovn_lflow_add_with_lport_and_hint(lflows, op->od,
S_SWITCH_OUT_APPLY_PORT_SEC, 110,
ds_cstr(match), ds_cstr(actions),
op->od->localnet_ports[0]->key,
&op->od->localnet_ports[0]->nbsp->header_);
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions northd/ovn-northd.8.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2223,6 +2223,18 @@ output;
</p>

<ul>
<li>
<p>
For each port configured with egress qos in the
<ref column="options:qdisc_queue_id" table="Logical_Switch_Port"
db="OVN_Northbound"/> column of <ref table="Logical_Switch_Port"
db="OVN_Northbound"/>, running a localnet port on the same logical
switch, a priority 110 flow is added which matches on the localnet
<code>outport</code> and on the port <code>inport</code> and
applies the action <code>set_queue(id); output;"</code>.
</p>
</li>

<li>
<p>
For each localnet port configured with egress qos in the
Expand Down
2 changes: 2 additions & 0 deletions tests/ovn-northd.at
Original file line number Diff line number Diff line change
Expand Up @@ -8154,6 +8154,7 @@ sort | sed 's/table=../table=??/' ], [0], [dnl
table=??(ls_out_check_port_sec), priority=0 , match=(1), action=(reg0[[15]] = check_out_port_sec(); next;)
table=??(ls_out_check_port_sec), priority=100 , match=(eth.mcast), action=(reg0[[15]] = 0; next;)
table=??(ls_out_apply_port_sec), priority=0 , match=(1), action=(output;)
table=??(ls_out_apply_port_sec), priority=110 , match=(outport == "localnetport" && inport == "sw0p2"), action=(set_queue(10); output;)
table=??(ls_out_apply_port_sec), priority=50 , match=(reg0[[15]] == 1), action=(drop;)
])

Expand Down Expand Up @@ -8184,6 +8185,7 @@ sort | sed 's/table=../table=??/' ], [0], [dnl
table=??(ls_out_check_port_sec), priority=100 , match=(eth.mcast), action=(reg0[[15]] = 0; next;)
table=??(ls_out_apply_port_sec), priority=0 , match=(1), action=(output;)
table=??(ls_out_apply_port_sec), priority=100 , match=(outport == "localnetport"), action=(set_queue(10); output;)
table=??(ls_out_apply_port_sec), priority=110 , match=(outport == "localnetport" && inport == "sw0p2"), action=(set_queue(10); output;)
table=??(ls_out_apply_port_sec), priority=50 , match=(reg0[[15]] == 1), action=(drop;)
])

Expand Down
185 changes: 185 additions & 0 deletions tests/ovn.at
Original file line number Diff line number Diff line change
Expand Up @@ -35623,3 +35623,188 @@ check test "$current_id2" = "$prev_id2"
OVN_CLEANUP([hv1])
AT_CLEANUP
])

OVN_FOR_EACH_NORTHD([
AT_SETUP([OVN QoS])
ovn_start

check ovn-nbctl ls-add ls0
check ovn-nbctl lsp-add ls0 public0
check ovn-nbctl lsp-set-addresses public0 unknown
check ovn-nbctl lsp-set-type public0 localnet
check ovn-nbctl lsp-set-options public0 network_name=phys
net_add n

# two hypervisors, each connected to the same network
for i in 1 2; do
sim_add hv-$i
as hv-$i
ovs-vsctl add-br br-phys
ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
ovn_attach n br-phys 192.168.0.$i
done

for i in 1 2; do
check ovn-nbctl lsp-add ls0 lsp$i
check ovn-nbctl lsp-set-addresses lsp$i f0:00:00:00:00:0$i
done

for i in 1 2; do
as hv-$i
ovs-vsctl add-port br-int vif$i -- set Interface vif$i external-ids:iface-id=lsp$i \
ofport-request=$i
OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lsp$i` = xup])

# Patch port might be created after ports are reported up
# Wait for a flow outputing to patch port
OVN_WAIT_PATCH_PORT_FLOWS(["public0"], ["hv-$i"])
done

check ovn-nbctl set Logical_Switch_Port lsp1 options:qos_min_rate=200000

OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list qos | grep -c linux-htb) -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'min-rate="200000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'max-rate="0"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'burst="0"') -eq 1])

check ovn-nbctl set Logical_Switch_Port lsp1 options:qos_max_rate=350000
check ovn-nbctl set Logical_Switch_Port lsp1 options:qos_burst=3000000

OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'max-rate="350000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'burst="3000000"') -eq 1])

check ovn-nbctl set Logical_Switch_Port lsp2 options:qos_min_rate=400000
check ovn-nbctl set Logical_Switch_Port lsp2 options:qos_max_rate=500000
check ovn-nbctl set Logical_Switch_Port lsp2 options:qos_burst=3000000

OVS_WAIT_UNTIL([test $(as hv-2 ovs-vsctl list qos | grep -c linux-htb) -eq 1])
OVS_WAIT_UNTIL([test $(as hv-2 ovs-vsctl list queue | grep -c 'min-rate="400000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-2 ovs-vsctl list queue | grep -c 'max-rate="500000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-2 ovs-vsctl list queue | grep -c 'burst="3000000"') -eq 1])

check ovn-nbctl lsp-add ls0 lsp3
check ovn-nbctl lsp-set-addresses lsp3 f0:00:00:00:00:03
as hv-1
ovs-vsctl add-port br-int vif3 -- \
set Interface vif3 external-ids:iface-id=lsp3 \
ofport-request=3
OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lsp3` = xup])

check ovn-nbctl lsp-add ls0 lsp4
check ovn-nbctl lsp-set-addresses lsp4 f0:00:00:00:00:04
as hv-1
ovs-vsctl add-port br-int vif4 -- \
set Interface vif4 external-ids:iface-id=lsp4 \
ofport-request=4
OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lsp4` = xup])

check ovn-nbctl set Logical_Switch_Port lsp3 options:qos_min_rate=700000
check ovn-nbctl set Logical_Switch_Port lsp3 options:qos_max_rate=800000
check ovn-nbctl set Logical_Switch_Port lsp3 options:qos_burst=9000000

OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list qos | grep -c linux-htb) -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'min-rate="200000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'max-rate="350000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'burst="3000000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'min-rate="700000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'max-rate="800000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'burst="9000000"') -eq 1])

check ovn-nbctl remove Logical_Switch_Port lsp3 options qos_min_rate=700000
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list qos | grep -c linux-htb) -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'min-rate="0"') -eq 1])

check ovn-nbctl remove Logical_Switch_Port lsp3 options qos_max_rate=800000
check ovn-nbctl remove Logical_Switch_Port lsp3 options qos_burst=9000000

OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list qos | grep -c linux-htb) -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'min-rate="200000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'max-rate="350000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'burst="3000000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'min-rate="700000"') -eq 0])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'max-rate="800000"') -eq 0])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'burst="9000000"') -eq 0])

check ovn-nbctl set Logical_Switch_Port lsp4 options:qos_min_rate=1700000
check ovn-nbctl set Logical_Switch_Port lsp4 options:qos_max_rate=1800000
check ovn-nbctl set Logical_Switch_Port lsp4 options:qos_burst=19000000
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'min-rate="1700000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'max-rate="1800000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'burst="19000000"') -eq 1])

as hv-1
ovs-vsctl remove Interface vif4 external-ids iface-id
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'min-rate="1700000"') -eq 0])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'max-rate="1800000"') -eq 0])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'burst="19000000"') -eq 0])

check ovn-nbctl set Logical_Switch_Port lsp2 options:qos_min_rate=410000
OVS_WAIT_UNTIL([test $(as hv-2 ovs-vsctl list queue | grep -c 'min-rate="410000"') -eq 1])

check ovn-nbctl remove Logical_Switch_Port lsp2 options qos_min_rate=410000
check ovn-nbctl remove Logical_Switch_Port lsp2 options qos_max_rate=500000
check ovn-nbctl remove Logical_Switch_Port lsp2 options qos_burst=3000000

OVS_WAIT_UNTIL([test $(as hv-2 ovs-vsctl list qos | grep -c linux-htb) -eq 0])
OVS_WAIT_UNTIL([test $(as hv-2 ovs-vsctl list queue | grep -c 'min-rate="410000"') -eq 0])
OVS_WAIT_UNTIL([test $(as hv-2 ovs-vsctl list queue | grep -c 'max-rate="500000"') -eq 0])
OVS_WAIT_UNTIL([test $(as hv-2 ovs-vsctl list queue | grep -c 'burst="3000000"') -eq 0])

check ovn-nbctl lsp-del lsp1
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list qos | grep -c linux-htb) -eq 0])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'min-rate="200000"') -eq 0])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'max-rate="350000"') -eq 0])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'burst="3000000"') -eq 0])

check ovn-nbctl set Logical_Switch_Port public0 options:qos_min_rate=100000
check ovn-nbctl set Logical_Switch_Port public0 options:qos_max_rate=200000
check ovn-nbctl set Logical_Switch_Port public0 options:qos_burst=3000000
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list qos | grep -c linux-htb) -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'min-rate="100000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'max-rate="200000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'burst="3000000"') -eq 1])

check ovn-nbctl ls-add ls1
check ovn-nbctl lsp-add ls1 public1
check ovn-nbctl lsp-set-addresses public1 unknown
check ovn-nbctl lsp-set-type public1 localnet

check ovn-nbctl lsp-add ls1 lsp5
check ovn-nbctl lsp-set-addresses lsp5 f0:00:00:00:00:05
as hv-1
ovs-vsctl add-port br-int vif5 -- \
set Interface vif5 external-ids:iface-id=lsp5 \
ofport-request=5
OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lsp5` = xup])

check ovn-nbctl set Logical_Switch_Port public1 options:qos_min_rate=6000000000
check ovn-nbctl set Logical_Switch_Port public1 options:qos_max_rate=7000000000
check ovn-nbctl set Logical_Switch_Port public1 options:qos_burst=8000000000

OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'min-rate="6000000000"') -eq 0])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'max-rate="7000000000"') -eq 0])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'burst="8000000000"') -eq 0])

check ovn-nbctl set Logical_Switch_Port public1 options:qos_min_rate=6000000000 options:qos_max_rate=7000000000 options:qos_burst=8000000000 options:network_name=phys

OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'min-rate="6000000000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'max-rate="7000000000"') -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'burst="8000000000"') -eq 1])

check ovn-nbctl lsp-del public0
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list qos | grep -c linux-htb) -eq 1])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'min-rate="100000"') -eq 0])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'max-rate="200000"') -eq 0])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'burst="3000000"') -eq 0])

check ovn-nbctl remove Logical_Switch_Port public1 options qos_min_rate=6000000000
check ovn-nbctl remove Logical_Switch_Port public1 options qos_max_rate=7000000000
check ovn-nbctl remove Logical_Switch_Port public1 options qos_burst=8000000000

OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list qos | grep -c linux-htb) -eq 0])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'min-rate="6000000000"') -eq 0])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'max-rate="7000000000"') -eq 0])
OVS_WAIT_UNTIL([test $(as hv-1 ovs-vsctl list queue | grep -c 'burst="8000000000"') -eq 0])

AT_CLEANUP
])

0 comments on commit 1c99a50

Please sign in to comment.