From patchwork Fri Feb 2 15:41:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 1894684 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Ya/BA8nC; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4TRKlb2GJPz23g7 for ; Sat, 3 Feb 2024 02:42:19 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 31AE1617BD; Fri, 2 Feb 2024 15:42:17 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 31AE1617BD Authentication-Results: smtp3.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Ya/BA8nC X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id riIrol4AxZ2D; Fri, 2 Feb 2024 15:42:15 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp3.osuosl.org (Postfix) with ESMTPS id 95A3E615F8; Fri, 2 Feb 2024 15:42:14 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 95A3E615F8 Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 698D9C0072; Fri, 2 Feb 2024 15:42:14 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) by lists.linuxfoundation.org (Postfix) with ESMTP id C4FF7C0037 for ; Fri, 2 Feb 2024 15:42:12 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 90B23437C2 for ; Fri, 2 Feb 2024 15:42:12 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 90B23437C2 Authentication-Results: smtp2.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Ya/BA8nC X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id yakFYilCPKeh for ; Fri, 2 Feb 2024 15:42:10 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp2.osuosl.org (Postfix) with ESMTPS id 42F27437BF for ; Fri, 2 Feb 2024 15:42:10 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 42F27437BF DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1706888529; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=7uMCGJ1Q3KRTUVQY6lHp2EtK4HHox63bzYCTpCmYxS4=; b=Ya/BA8nCYGcq81a6DbwobDdNc1X9cb+qHWrggakp0nEBx/IAHAXC359CMhXcpq/e30685g 9HSmIh96zBa9b5ohoqNkM509dgF1aSaHnzDLqrXoUo6lc3hC1LEl6UjD+c82FBVWJQrPYA P7ft6fytK6HJ9fhRd4eGcpSAZQFvW7s= Received: from mail-wr1-f72.google.com (mail-wr1-f72.google.com [209.85.221.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-538-GgGHb02MP02PPLgAfEj86g-1; Fri, 02 Feb 2024 10:42:06 -0500 X-MC-Unique: GgGHb02MP02PPLgAfEj86g-1 Received: by mail-wr1-f72.google.com with SMTP id ffacd0b85a97d-33b248e7cd7so233775f8f.2 for ; Fri, 02 Feb 2024 07:42:06 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706888525; x=1707493325; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=7uMCGJ1Q3KRTUVQY6lHp2EtK4HHox63bzYCTpCmYxS4=; b=Q5nKBRiQb1IgyBYnmkIZdjWwo6eSd6YEgvUNFORK5trPgE2WrdwMQzuOi2d3lP7dGI jacorZsnt850fn4qVSoRO2q1INBJ3dyq8qDmhEq5ZolP1/g0srVEjDw0NZvO8nmJMxCT UdM5BpwKl3pjUk3/0hVdZZDyZ3F0im4OYsCG7e6zokIFZRJ0XL1NX1ZOBQ6VMXRDNntX F/0y+RAJt9N/g9IDEc5su6iPzSH9SnNl0gk73mGP1v9aIMQfiw4iYRzqq9R0FQKY33Vo gvWfePTRpVLcWeckHC6qOzHqrdBiytt7/P3wg5aUeMRfrK3cfPePX0BFO+IUUXkUBiP4 1XxA== X-Gm-Message-State: AOJu0YwDTGmxeEDz9JEDrdu3hEk1R0gwP+rGxPpWdPxFE1NA9AgQ4/EP vLui+FJahi4iaFNNNZXeTCw0zNYyeE0+z9svS3HlX8eYlXQ/1Hy6z8w0LaSv2We7IlIq1WHqKRd 6nsUZ0kvRuXJup4wbVskkwHW78L67CZaJyIDAxpS6id2leK2FocsyUnKRbUV2CUYoEAqz3v59tN 3QWuxvSqDRPljTME96+mP5L8sqKANXb1bZfMd2repQ98QqItIJ0g== X-Received: by 2002:adf:a4cc:0:b0:33b:1cd4:6b2e with SMTP id h12-20020adfa4cc000000b0033b1cd46b2emr2370471wrb.66.1706888524875; Fri, 02 Feb 2024 07:42:04 -0800 (PST) X-Google-Smtp-Source: AGHT+IG+KBu41/EgiVEykX83jR0ZToEWE9jhH0NWuUJA4se5D2OmBLfoxU+h7UmUtBXNHbCApvKY3w== X-Received: by 2002:adf:a4cc:0:b0:33b:1cd4:6b2e with SMTP id h12-20020adfa4cc000000b0033b1cd46b2emr2370444wrb.66.1706888524236; Fri, 02 Feb 2024 07:42:04 -0800 (PST) X-Forwarded-Encrypted: i=0; AJvYcCU44KoP3nONZl2O4t4GFJZiHjBK95dncgOAr4hjd5oT5tOCwBApI/Vy5P9BYPZU8xAmVDx6+SxhfuaXgtaVar5/zbuVTjPE/0wy37o0TXKQrzCN2YRqDyMkjaflPno6wxulevABoFQDfWofJT6bX4aSm2MQQIsfWThqxQ== Received: from localhost (net-93-71-3-198.cust.vodafonedsl.it. [93.71.3.198]) by smtp.gmail.com with ESMTPSA id c6-20020adfef46000000b0033b1f023af2sm1941157wrp.52.2024.02.02.07.42.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Feb 2024 07:42:03 -0800 (PST) From: Lorenzo Bianconi To: ovs-dev@openvswitch.org Date: Fri, 2 Feb 2024 16:41:47 +0100 Message-ID: X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: dceara@redhat.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v3 ovn] northd: Add qos packet marking. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Add the capbility to mark (through pkt.mark) incoming/outgoing packets in logical_switch datapath according to user configured QoS rule. Co-developed-by: Dumitru Ceara Reported-at: https://issues.redhat.com/browse/FDP-42 Signed-off-by: Lorenzo Bianconi Acked-by: Mark Michelson --- Changes since v2: - set max dscp/mark value in ovn-nb.ovsschema - add unit-test for new dscp/mark boundaries Changes since v1: - move qos packet mark action in QOS_MARK ls {ingress/egress} stage --- NEWS | 2 + northd/northd.c | 33 +++++++++++++--- northd/ovn-northd.8.xml | 6 +++ ovn-nb.ovsschema | 8 ++-- ovn-nb.xml | 12 +++++- tests/ovn-nbctl.at | 8 +++- tests/ovn-northd.at | 81 ++++++++++++++++++++++++++++++++++++++ tests/ovn.at | 83 +++++++++++++++++++++++++++++++++++++++ utilities/ovn-nbctl.8.xml | 5 ++- utilities/ovn-nbctl.c | 27 ++++++++++--- 10 files changed, 245 insertions(+), 20 deletions(-) diff --git a/NEWS b/NEWS index 6553bd078..a8beb09fb 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,8 @@ Post v23.09.0 - Support selecting encapsulation IP based on the source/destination VIF's settting. See ovn-controller(8) 'external_ids:ovn-encap-ip' for more details. + - Add the capability to mark (through pkt.mark) incoming/outgoing packets + in the logical switch datapath according to user configured QoS rule. OVN v23.09.0 - 15 Sep 2023 -------------------------- diff --git a/northd/northd.c b/northd/northd.c index d2091d4bc..a77919af3 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -8363,6 +8363,8 @@ build_acls(struct ovn_datapath *od, const struct chassis_features *features, ds_destroy(&actions); } +#define QOS_MAX_DSCP 63 + static void build_qos(struct ovn_datapath *od, struct hmap *lflows) { struct ds action = DS_EMPTY_INITIALIZER; @@ -8376,21 +8378,40 @@ build_qos(struct ovn_datapath *od, struct hmap *lflows) { struct nbrec_qos *qos = od->nbs->qos_rules[i]; bool ingress = !strcmp(qos->direction, "from-lport") ? true :false; enum ovn_stage stage = ingress ? S_SWITCH_IN_QOS_MARK : S_SWITCH_OUT_QOS_MARK; + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); int64_t rate = 0; int64_t burst = 0; + ds_clear(&action); for (size_t j = 0; j < qos->n_action; j++) { + if (strcmp(qos->key_action[j], "dscp") && + strcmp(qos->key_action[j], "mark")) { + continue; + } + if (!strcmp(qos->key_action[j], "dscp")) { - ds_clear(&action); - ds_put_format(&action, "ip.dscp = %"PRId64"; next;", + if (qos->value_action[j] > QOS_MAX_DSCP) { + VLOG_WARN_RL(&rl, "Bad 'dscp' value %"PRId64" in qos " + UUID_FMT, qos->value_action[j], + UUID_ARGS(&qos->header_.uuid)); + continue; + } + + ds_put_format(&action, "ip.dscp = %"PRId64"; ", + qos->value_action[j]); + } else if (!strcmp(qos->key_action[j], "mark")) { + ds_put_format(&action, "pkt.mark = %"PRId64"; ", qos->value_action[j]); - ovn_lflow_add_with_hint(lflows, od, stage, - qos->priority, - qos->match, ds_cstr(&action), - &qos->header_); } } + if (action.length) { + ds_put_cstr(&action, "next;"); + ovn_lflow_add_with_hint(lflows, od, stage, qos->priority, + qos->match, ds_cstr(&action), + &qos->header_); + } + for (size_t n = 0; n < qos->n_bandwidth; n++) { if (!strcmp(qos->key_bandwidth[n], "rate")) { rate = qos->value_bandwidth[n]; diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index 068d47e1a..9583abeff 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -915,6 +915,12 @@ QoS table. +
  • + For every qos_rules entry in a logical switch with packet marking + enabled, a flow will be added at the priority mentioned in the + QoS table. +
  • +
  • One priority-0 fallback flow that matches all packets and advances to the next table. diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema index b2e0993e0..12ddce3f6 100644 --- a/ovn-nb.ovsschema +++ b/ovn-nb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Northbound", - "version": "7.2.0", - "cksum": "1069338687 34162", + "version": "7.3.0", + "cksum": "4237284067 34178", "tables": { "NB_Global": { "columns": { @@ -293,10 +293,10 @@ "enum": ["set", ["from-lport", "to-lport"]]}}}, "match": {"type": "string"}, "action": {"type": {"key": {"type": "string", - "enum": ["set", ["dscp"]]}, + "enum": ["set", ["dscp", "mark"]]}, "value": {"type": "integer", "minInteger": 0, - "maxInteger": 63}, + "maxInteger": 4294967295}, "min": 0, "max": "unlimited"}}, "bandwidth": {"type": {"key": {"type": "string", "enum": ["set", ["rate", diff --git a/ovn-nb.xml b/ovn-nb.xml index 765ffcf2e..5b593f6a7 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -2808,12 +2808,22 @@ or -

    When specified, matching flows will have DSCP marking applied.

    +

    + When dscp action is specified, matching flows will have + have DSCP marking applied. + When mark action is specified, matching flows will have + packet marking applied. +

    +
    • dscp: The value of this action should be in the range of 0 to 63 (inclusive).
    • +
    • + mark: The value of this action should be a positive + integer. +
    diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at index 7f37d7716..b11e4ec6b 100644 --- a/tests/ovn-nbctl.at +++ b/tests/ovn-nbctl.at @@ -316,6 +316,8 @@ AT_CHECK([ovn-nbctl qos-add ls0 from-lport 400 tcp dscp=0 rate=300 burst=3000]) AT_CHECK([ovn-nbctl qos-add ls0 to-lport 300 tcp dscp=48]) AT_CHECK([ovn-nbctl qos-add ls0 to-lport 200 ip rate=101]) AT_CHECK([ovn-nbctl qos-add ls0 to-lport 100 ip4 dscp=13 rate=301 burst=30000]) +AT_CHECK([ovn-nbctl qos-add ls0 to-lport 101 ip4 mark=15]) +AT_CHECK([ovn-nbctl qos-add ls0 to-lport 102 ip4 dscp=16 mark=17]) dnl Add duplicated qos AT_CHECK([ovn-nbctl qos-add ls0 to-lport 100 ip4 dscp=11 rate=302 burst=30002], [1], [], [stderr]) @@ -328,6 +330,8 @@ from-lport 500 (udp) rate=100 burst=1000 from-lport 400 (tcp) rate=300 burst=3000 dscp=0 to-lport 300 (tcp) dscp=48 to-lport 200 (ip) rate=101 + to-lport 102 (ip4) dscp=16 mark=17 + to-lport 101 (ip4) mark=15 to-lport 100 (ip4) rate=301 burst=30000 dscp=13 ]) @@ -371,11 +375,11 @@ AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip dscp=-1], [1], [], ]) AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip dscpa=-1], [1], [], -[ovn-nbctl: dscpa=-1: supported arguments are "dscp=", "rate=", and "burst=" +[ovn-nbctl: dscpa=-1: supported arguments are "dscp=", "rate=", "burst=" and "mark=" ]) AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip burst=123], [1], [], -[ovn-nbctl: Either "rate" and/or "dscp" must be specified +[ovn-nbctl: Either "mark", "rate" and/or "dscp" must be specified ])]) dnl --------------------------------------------------------------------- diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 67e81ddba..8f2d1d1b0 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -9860,6 +9860,41 @@ AT_CHECK([fetch_column sb:Port_Binding options logical_port=public |grep -q 'qos AT_CLEANUP ]) +OVN_FOR_EACH_NORTHD_NO_HV([ +AT_SETUP([check OVN QoS mark/meter logical flows]) +AT_KEYWORDS([OVN-QoS]) +ovn_start + +check ovn-nbctl ls-add ls +check ovn-nbctl qos-add ls from-lport 100 ip4 rate=100 burst=1000 +check ovn-nbctl qos-add ls from-lport 101 ip4 mark=15 +check ovn-nbctl qos-add ls from-lport 102 ip4 dscp=16 +check ovn-nbctl qos-add ls from-lport 103 ip4 dscp=17 mark=18 + +check ovn-nbctl qos-add ls to-lport 100 ip4 rate=100 burst=1000 +check ovn-nbctl qos-add ls to-lport 101 ip4 mark=15 +check ovn-nbctl qos-add ls to-lport 102 ip4 dscp=16 +check ovn-nbctl qos-add ls to-lport 103 ip4 dscp=17 mark=18 +check ovn-nbctl --wait=sb sync + +AT_CHECK([ovn-sbctl lflow-list ls | grep qos | sed 's/table=../table=??/'], [0], [dnl + table=??(ls_in_qos_mark ), priority=103 , match=(ip4), action=(ip.dscp = 17; pkt.mark = 18; next;) + table=??(ls_in_qos_mark ), priority=102 , match=(ip4), action=(ip.dscp = 16; next;) + table=??(ls_in_qos_mark ), priority=101 , match=(ip4), action=(pkt.mark = 15; next;) + table=??(ls_in_qos_mark ), priority=0 , match=(1), action=(next;) + table=??(ls_in_qos_meter ), priority=100 , match=(ip4), action=(set_meter(100, 1000); next;) + table=??(ls_in_qos_meter ), priority=0 , match=(1), action=(next;) + table=??(ls_out_qos_mark ), priority=103 , match=(ip4), action=(ip.dscp = 17; pkt.mark = 18; next;) + table=??(ls_out_qos_mark ), priority=102 , match=(ip4), action=(ip.dscp = 16; next;) + table=??(ls_out_qos_mark ), priority=101 , match=(ip4), action=(pkt.mark = 15; next;) + table=??(ls_out_qos_mark ), priority=0 , match=(1), action=(next;) + table=??(ls_out_qos_meter ), priority=100 , match=(ip4), action=(set_meter(100, 1000); next;) + table=??(ls_out_qos_meter ), priority=0 , match=(1), action=(next;) +]) + +AT_CLEANUP +]) + AT_SETUP([Tiered ACL logical flows]) AT_KEYWORDS([acl]) @@ -11495,3 +11530,49 @@ CHECK_NO_CHANGE_AFTER_RECOMPUTE OVN_CLEANUP([hv1]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD_NO_HV([ +AT_SETUP([check QoS table configuration]) +ovn_start + +check ovn-nbctl ls-add lsw0 +check ovn-nbctl lsp-add lsw0 lp0 +check ovn-nbctl ls-add lsw1 +check ovn-nbctl --wait=hv lsp-add lsw1 lp1 + +AT_CHECK([ovn-nbctl --wait=hv -- --id=@lp0-qos create QoS priority=100 action=dscp=48 match="inport\=\=\"lp0\"\ &&\ is_chassis_resident(\"lp0\")" direction="from-lport" -- set Logical_Switch lsw0 qos_rules=@lp0-qos],[0],[ignore]) +check_row_count nb:QoS 1 + +AT_CHECK([ovn-nbctl --wait=hv -- --id=@lp1-qos create QoS priority=101 action=mark=49 match="inport\=\=\"lp1\"\ &&\ is_chassis_resident(\"lp1\")" direction="from-lport" -- set Logical_Switch lsw1 qos_rules=@lp1-qos],[0],[ignore]) +check_row_count nb:QoS 2 + +AT_CHECK([ovn-nbctl list qos |grep -q dscp=48]) +AT_CHECK([ovn-nbctl list qos |grep -q mark=49]) + +check ovn-nbctl qos-del lsw0 +check_row_count nb:QoS 1 + +# check wrong dscp values +AT_CHECK([ovn-nbctl --wait=hv -- --id=@lp0-qos create QoS priority=100 action=dscp=100 match="inport\=\=\"lp0\"\ &&\ is_chassis_resident(\"lp0\")" direction="from-lport" -- set Logical_Switch lsw0 qos_rules=@lp0-qos],[0],[ignore]) +AT_CHECK([ovn-sbctl dump-flows | grep -q dscp], [1]) +AT_CHECK([grep -q "Bad 'dscp' value 100" northd/ovn-northd.log]) + +check ovn-nbctl qos-del lsw0 +check_row_count nb:QoS 1 + +AT_CHECK([ovn-nbctl --wait=hv -- --id=@lp0-qos create QoS priority=100 action=dscp="-1" match="inport\=\=\"lp0\"\ &&\ is_chassis_resident(\"lp0\")" direction="from-lport" -- set Logical_Switch lsw0 qos_rules=@lp0-qos],[1],[ignore],[dnl +ovn-nbctl: constraint violation: -1 is not in the valid range 0 to 4294967295 (inclusive) +]) +check_row_count nb:QoS 1 + +check ovn-nbctl qos-del lsw1 +check_row_count nb:QoS 0 + +# check wrong mark value +AT_CHECK([ovn-nbctl --wait=hv -- --id=@lp1-qos create QoS priority=101 action=mark="-2" match="inport\=\=\"lp1\"\ &&\ is_chassis_resident(\"lp1\")" direction="from-lport" -- set Logical_Switch lsw1 qos_rules=@lp1-qos],[1],[ignore],[dnl +ovn-nbctl: constraint violation: -2 is not in the valid range 0 to 4294967295 (inclusive) +]) +check_row_count nb:QoS 0 + +AT_CLEANUP +]) diff --git a/tests/ovn.at b/tests/ovn.at index 28c6b6c34..ee7c8cb1e 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -37929,3 +37929,86 @@ AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \ OVS_APP_EXIT_AND_WAIT([ovsdb-server]) AT_CLEANUP + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([QoS packet marking]) +AT_KEYWORDS([ovn-qos-pkt-marking]) +AT_SKIP_IF([test $HAVE_SCAPY = no]) +ovn_start + +check ovn-nbctl lr-add lr0 +check ovn-nbctl ls-add ls0 +check ovn-nbctl ls-add ls1 + +check ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:10 10.0.0.254/24 +check ovn-nbctl lsp-add ls0 lrp-s0 -- \ + set Logical_Switch_Port lrp-s0 type=router \ + options:router-port=lrp0 addresses='"f0:00:00:00:00:10"' +check ovn-nbctl lrp-add lr0 lrp1 f0:00:00:00:00:20 20.0.0.254/24 +check ovn-nbctl lsp-add ls1 lrp-s1 -- \ + set Logical_Switch_Port lrp-s1 type=router \ + options:router-port=lrp1 addresses='"f0:00:00:00:00:20"' + +check ovn-nbctl --wait=sb lsp-add ls0 lp0 +check ovn-nbctl lsp-set-addresses lp0 f0:00:00:00:00:01 +check ovn-nbctl --wait=sb lsp-add ls0 lp1 +check ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:02 + +check ovn-nbctl --wait=sb lsp-add ls1 lp2 +check ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:11 +check ovn-nbctl --wait=sb sync + +net_add n1 +sim_add hv + +as hv +check ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 + +check ovs-vsctl add-port br-int vif0 -- \ + set Interface vif0 external-ids:iface-id=lp0 \ + options:tx_pcap=hv/vif0-tx.pcap \ + options:rxq_pcap=hv/vif0-rx.pcap \ + ofport-request=1 +check ovs-vsctl add-port br-int vif1 -- \ + set Interface vif1 external-ids:iface-id=lp1 \ + options:tx_pcap=hv/vif1-tx.pcap \ + options:rxq_pcap=hv/vif1-rx.pcap \ + ofport-request=2 +check ovs-vsctl add-port br-int vif2 -- \ + set Interface vif2 external-ids:iface-id=lp2 \ + options:tx_pcap=hv/vif2-tx.pcap \ + options:rxq_pcap=hv/vif2-rx.pcap \ + ofport-request=3 + +# Create QoS rules for packet marking. +check ovn-nbctl qos-add ls0 from-lport 100 "inport==\"lp0\" && udp" mark=48 +check ovn-nbctl qos-add ls0 to-lport 100 "outport==\"lrp-s0\" && udp" mark=49 +check_row_count nb:QoS 2 + +# Create some flows to count pkt marking. +check ovn-nbctl acl-add ls0 to-lport 1002 "outport==\"lp1\" && pkt.mark == 48" drop +check ovn-nbctl lr-policy-add lr0 200 "pkt.mark == 49" drop +wait_for_ports_up +check ovn-nbctl --wait=hv sync + +send_udp_packet() { + local inport=$1 eth_src=$2 eth_dst=$3 ipv4_src=$4 ipv4_dst=$5 + local packet=$(fmt_pkt "Ether(dst='${eth_dst}', src='${eth_src}')/ \ + IP(src='${ipv4_src}', dst='${ipv4_dst}', ttl=0x40)/ \ + UDP(sport=4242, dport=4343)") + as hv ovs-appctl netdev-dummy/receive vif$inport $packet +} + +ls0_dp_key=$(printf "0x%x" $(fetch_column Datapath_Binding tunnel_key external_ids:name=ls0)) +lr0_dp_key=$(printf "0x%x" $(fetch_column Datapath_Binding tunnel_key external_ids:name=lr0)) + +send_udp_packet 0 f0:00:00:00:00:01 f0:00:00:00:00:02 10.0.0.1 10.0.0.2 +OVS_WAIT_UNTIL([test 1 = $(as hv ovs-ofctl dump-flows br-int | grep -E "pkt_mark=0x30.*metadata=$ls0_dp_key" | grep -c n_packets=1)]) + +send_udp_packet 0 f0:00:00:00:00:01 f0:00:00:00:00:10 10.0.0.1 10.0.0.10 +OVS_WAIT_UNTIL([test 1 = $(as hv ovs-ofctl dump-flows br-int | grep -E "pkt_mark=0x31.*metadata=$lr0_dp_key" | grep -c n_packets=1)]) + +OVN_CLEANUP([hv]) +AT_CLEANUP +]) diff --git a/utilities/ovn-nbctl.8.xml b/utilities/ovn-nbctl.8.xml index 6f74bd557..c1a280191 100644 --- a/utilities/ovn-nbctl.8.xml +++ b/utilities/ovn-nbctl.8.xml @@ -463,7 +463,7 @@

    Logical Switch QoS Rule Commands

    -
    [--may-exist] qos-add switch direction priority match [dscp=dscp] [rate=rate [burst=burst]]
    +
    [--may-exist] qos-add switch direction priority match [mark=mark] [dscp=dscp] [rate=rate [burst=burst]]

    Adds QoS marking and metering rules to switch. @@ -482,6 +482,9 @@ burst=burst specifies the burst rate limit in kilobits. dscp and/or rate are required arguments. + If mark=mark is specified, then matching + packets will be marked (through pkt.mark). + mark must be a positive integer.

    diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c index 526369b68..14460991f 100644 --- a/utilities/ovn-nbctl.c +++ b/utilities/ovn-nbctl.c @@ -283,7 +283,7 @@ ACL commands:\n\ print ACLs for SWITCH\n\ \n\ QoS commands:\n\ - qos-add SWITCH DIRECTION PRIORITY MATCH [rate=RATE [burst=BURST]] [dscp=DSCP]\n\ + qos-add SWITCH DIRECTION PRIORITY MATCH [rate=RATE [burst=BURST]] [dscp=DSCP] [mark=MARK]\n\ add an QoS rule to SWITCH\n\ qos-del SWITCH [{DIRECTION | UUID} [PRIORITY MATCH]]\n\ remove QoS rules from SWITCH\n\ @@ -2614,6 +2614,9 @@ nbctl_qos_list(struct ctl_context *ctx) if (!strcmp(qos_rule->key_action[j], "dscp")) { ds_put_format(&ctx->output, " dscp=%"PRId64"", qos_rule->value_action[j]); + } else if (!strcmp(qos_rule->key_action[j], "mark")) { + ds_put_format(&ctx->output, " mark=%"PRId64"", + qos_rule->value_action[j]); } } ds_put_cstr(&ctx->output, "\n"); @@ -2631,6 +2634,7 @@ nbctl_pre_qos_add(struct ctl_context *ctx) ovsdb_idl_add_column(ctx->idl, &nbrec_qos_col_direction); ovsdb_idl_add_column(ctx->idl, &nbrec_qos_col_priority); ovsdb_idl_add_column(ctx->idl, &nbrec_qos_col_match); + ovsdb_idl_add_column(ctx->idl, &nbrec_qos_col_action); } static void @@ -2640,6 +2644,7 @@ nbctl_qos_add(struct ctl_context *ctx) const char *direction; int64_t priority; int64_t dscp = -1; + int64_t mark = 0; int64_t rate = 0; int64_t burst = 0; char *error; @@ -2669,6 +2674,13 @@ nbctl_qos_add(struct ctl_context *ctx) return; } } + else if (!strncmp(ctx->argv[i], "mark=", 5)) { + if (!ovs_scan(ctx->argv[i] + 5, "%"SCNd64, &mark) || mark < 0) { + ctl_error(ctx, "%s: mark must be a positive integer", + ctx->argv[i] + 5); + return; + } + } else if (!strncmp(ctx->argv[i], "rate=", 5)) { if (!ovs_scan(ctx->argv[i] + 5, "%"SCNd64, &rate) || rate < 1 || rate > UINT32_MAX) { @@ -2686,14 +2698,15 @@ nbctl_qos_add(struct ctl_context *ctx) } } else { ctl_error(ctx, "%s: supported arguments are \"dscp=\", \"rate=\", " - "and \"burst=\"", ctx->argv[i]); + "\"burst=\" and \"mark=\"", ctx->argv[i]); return; } } /* Validate rate and dscp. */ - if (-1 == dscp && !rate) { - ctl_error(ctx, "Either \"rate\" and/or \"dscp\" must be specified"); + if (-1 == dscp && !rate && !mark) { + ctl_error(ctx, "Either \"mark\", \"rate\" and/or \"dscp\" must be " + "specified"); return; } @@ -2702,9 +2715,11 @@ nbctl_qos_add(struct ctl_context *ctx) nbrec_qos_set_priority(qos, priority); nbrec_qos_set_direction(qos, direction); nbrec_qos_set_match(qos, ctx->argv[4]); + if (mark) { + nbrec_qos_update_action_setkey(qos, "mark", mark); + } if (-1 != dscp) { - const char *dscp_key = "dscp"; - nbrec_qos_set_action(qos, &dscp_key, &dscp, 1); + nbrec_qos_update_action_setkey(qos, "dscp", dscp); } if (rate) { const char *bandwidth_key[2] = {"rate", "burst"};