diff options
| -rw-r--r-- | interface-definitions/include/qos/queue-average-packet.xml.i | 16 | ||||
| -rw-r--r-- | interface-definitions/include/qos/queue-mark-probability.xml.i | 16 | ||||
| -rw-r--r-- | interface-definitions/include/qos/queue-maximum-threshold.xml.i | 16 | ||||
| -rw-r--r-- | interface-definitions/include/qos/queue-minimum-threshold.xml.i | 15 | ||||
| -rw-r--r-- | interface-definitions/qos.xml.in | 67 | ||||
| -rw-r--r-- | python/vyos/qos/base.py | 29 | ||||
| -rwxr-xr-x | smoketest/scripts/cli/test_qos.py | 64 | 
7 files changed, 167 insertions, 56 deletions
| diff --git a/interface-definitions/include/qos/queue-average-packet.xml.i b/interface-definitions/include/qos/queue-average-packet.xml.i new file mode 100644 index 000000000..2f8bfe266 --- /dev/null +++ b/interface-definitions/include/qos/queue-average-packet.xml.i @@ -0,0 +1,16 @@ +<!-- include start from qos/queue-average-packet.xml.i --> +<leafNode name="average-packet"> +  <properties> +    <help>Average packet size (bytes)</help> +    <valueHelp> +      <format>u32:16-10240</format> +      <description>Average packet size in bytes</description> +    </valueHelp> +    <constraint> +      <validator name="numeric" argument="--range 16-10240"/> +    </constraint> +    <constraintErrorMessage>Average packet size must be between 16 and 10240</constraintErrorMessage> +  </properties> +  <defaultValue>1024</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/queue-mark-probability.xml.i b/interface-definitions/include/qos/queue-mark-probability.xml.i new file mode 100644 index 000000000..1a2862845 --- /dev/null +++ b/interface-definitions/include/qos/queue-mark-probability.xml.i @@ -0,0 +1,16 @@ +<!-- include start from qos/queue-mark-probability.xml.i --> +<leafNode name="mark-probability"> +  <properties> +    <help>Mark probability for random detection</help> +    <valueHelp> +      <format>u32</format> +      <description>Numeric value (1/N)</description> +    </valueHelp> +    <constraint> +      <validator name="numeric" argument="--positive"/> +    </constraint> +    <constraintErrorMessage>Mark probability must be greater than 0</constraintErrorMessage> +  </properties> +  <defaultValue>10</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/queue-maximum-threshold.xml.i b/interface-definitions/include/qos/queue-maximum-threshold.xml.i new file mode 100644 index 000000000..66d17ccc4 --- /dev/null +++ b/interface-definitions/include/qos/queue-maximum-threshold.xml.i @@ -0,0 +1,16 @@ +<!-- include start from qos/queue-maximum-threshold.xml.i --> +<leafNode name="maximum-threshold"> +  <properties> +    <help>Maximum threshold for random detection</help> +    <valueHelp> +      <format>u32:0-4096</format> +      <description>Maximum threshold in packets</description> +    </valueHelp> +    <constraint> +      <validator name="numeric" argument="--range 0-4096"/> +    </constraint> +    <constraintErrorMessage>Threshold must be between 0 and 4096</constraintErrorMessage> +  </properties> +  <defaultValue>18</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/queue-minimum-threshold.xml.i b/interface-definitions/include/qos/queue-minimum-threshold.xml.i new file mode 100644 index 000000000..81e12d6e2 --- /dev/null +++ b/interface-definitions/include/qos/queue-minimum-threshold.xml.i @@ -0,0 +1,15 @@ +<!-- include start from qos/queue-minimum-threshold.xml.i --> +<leafNode name="minimum-threshold"> +  <properties> +    <help>Minimum threshold for random detection</help> +    <valueHelp> +      <format>u32:0-4096</format> +      <description>Minimum threshold in packets</description> +    </valueHelp> +    <constraint> +      <validator name="numeric" argument="--range 0-4096"/> +    </constraint> +    <constraintErrorMessage>Threshold must be between 0 and 4096</constraintErrorMessage> +  </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/qos.xml.in b/interface-definitions/qos.xml.in index 7618c3027..8f9ae3fa6 100644 --- a/interface-definitions/qos.xml.in +++ b/interface-definitions/qos.xml.in @@ -470,61 +470,10 @@                  </properties>                  <children>                    #include <include/qos/queue-limit-1-4294967295.xml.i> -                  <leafNode name="average-packet"> -                    <properties> -                      <help>Average packet size (bytes)</help> -                      <valueHelp> -                        <format>u32:16-10240</format> -                        <description>Average packet size in bytes</description> -                      </valueHelp> -                      <constraint> -                        <validator name="numeric" argument="--range 0-100"/> -                      </constraint> -                      <constraintErrorMessage>Average packet size must be between 16 and 10240</constraintErrorMessage> -                    </properties> -                    <defaultValue>1024</defaultValue> -                  </leafNode> -                  <leafNode name="mark-probability"> -                    <properties> -                      <help>Mark probability for this precedence</help> -                      <valueHelp> -                        <format><number></format> -                        <description>Numeric value (1/N)</description> -                      </valueHelp> -                      <constraint> -                        <validator name="numeric" argument="--positive"/> -                      </constraint> -                      <constraintErrorMessage>Mark probability must be greater than 0</constraintErrorMessage> -                    </properties> -                    <defaultValue>10</defaultValue> -                  </leafNode> -                  <leafNode name="maximum-threshold"> -                    <properties> -                      <help>Maximum threshold for random detection</help> -                      <valueHelp> -                        <format>u32:0-4096</format> -                        <description>Maximum Threshold in packets</description> -                      </valueHelp> -                      <constraint> -                        <validator name="numeric" argument="--range 0-4096"/> -                      </constraint> -                      <constraintErrorMessage>Threshold must be between 0 and 4096</constraintErrorMessage> -                    </properties> -                    <defaultValue>18</defaultValue> -                  </leafNode> -                  <leafNode name="minimum-threshold"> -                    <properties> -                      <help>Minimum  threshold for random detection</help> -                      <valueHelp> -                        <format>u32:0-4096</format> -                        <description>Maximum Threshold in packets</description> -                      </valueHelp> -                      <constraint> -                        <validator name="numeric" argument="--range 0-4096"/> -                      </constraint> -                      <constraintErrorMessage>Threshold must be between 0 and 4096</constraintErrorMessage> -                    </properties> -                  </leafNode> +                  #include <include/qos/queue-average-packet.xml.i> +                  #include <include/qos/queue-maximum-threshold.xml.i> +                  #include <include/qos/queue-minimum-threshold.xml.i> +                  #include <include/qos/queue-mark-probability.xml.i>                  </children>                </tagNode>              </children> @@ -697,6 +646,10 @@                    #include <include/qos/interval.xml.i>                    #include <include/qos/class-match.xml.i>                    #include <include/qos/class-priority.xml.i> +                  #include <include/qos/queue-average-packet.xml.i> +                  #include <include/qos/queue-maximum-threshold.xml.i> +                  #include <include/qos/queue-minimum-threshold.xml.i> +                  #include <include/qos/queue-mark-probability.xml.i>                    #include <include/qos/queue-limit-1-4294967295.xml.i>                    #include <include/qos/queue-type.xml.i>                    <leafNode name="queue-type"> @@ -759,6 +712,10 @@                      </properties>                      <defaultValue>20</defaultValue>                    </leafNode> +                  #include <include/qos/queue-average-packet.xml.i> +                  #include <include/qos/queue-maximum-threshold.xml.i> +                  #include <include/qos/queue-minimum-threshold.xml.i> +                  #include <include/qos/queue-mark-probability.xml.i>                    #include <include/qos/queue-limit-1-4294967295.xml.i>                    #include <include/qos/queue-type.xml.i>                    <leafNode name="queue-type"> diff --git a/python/vyos/qos/base.py b/python/vyos/qos/base.py index c8e881ee2..f9366c6b1 100644 --- a/python/vyos/qos/base.py +++ b/python/vyos/qos/base.py @@ -90,6 +90,23 @@ class QoSBase:          else:              return value +    def _calc_random_detect_queue_params(self, avg_pkt, max_thr, limit=None, min_thr=None, mark_probability=None): +        params = dict() +        avg_pkt = int(avg_pkt) +        max_thr = int(max_thr) +        mark_probability = int(mark_probability) +        limit = int(limit) if limit else 4 * max_thr +        min_thr = int(min_thr) if min_thr else (9 * max_thr) // 18 + +        params['avg_pkt'] = avg_pkt +        params['limit'] = limit * avg_pkt +        params['min_val'] = min_thr * avg_pkt +        params['max_val'] = max_thr * avg_pkt +        params['burst'] = (2 * min_thr + max_thr) // 3 +        params['probability'] = 1 / mark_probability + +        return params +      def _build_base_qdisc(self, config : dict, cls_id : int):          """          Add/replace qdisc for every class (also default is a class). This is @@ -144,6 +161,18 @@ class QoSBase:          elif queue_type == 'random-detect':              default_tc += f' red' +            qparams = self._calc_random_detect_queue_params( +                avg_pkt=dict_search('average_packet', config), +                max_thr=dict_search('maximum_threshold', config), +                limit=dict_search('queue_limit', config), +                min_thr=dict_search('minimum_threshold', config), +                mark_probability=dict_search('mark_probability', config) +            ) + +            default_tc += f' limit {qparams["limit"]} avpkt {qparams["avg_pkt"]}' +            default_tc += f' max {qparams["max_val"]} min {qparams["min_val"]}' +            default_tc += f' burst {qparams["burst"]} probability {qparams["probability"]}' +              self._cmd(default_tc)          elif queue_type == 'drop-tail': diff --git a/smoketest/scripts/cli/test_qos.py b/smoketest/scripts/cli/test_qos.py index 1eb4b5cfb..4f41e36cd 100755 --- a/smoketest/scripts/cli/test_qos.py +++ b/smoketest/scripts/cli/test_qos.py @@ -581,7 +581,6 @@ class TestQoS(VyOSUnitTestSHIM.TestCase):                          dport = int(match_config['dport'])                          self.assertEqual(f'{dport:x}', filter['options']['match']['value']) -      def test_11_shaper(self):          bandwidth = 250          default_bandwidth = 20 @@ -635,6 +634,69 @@ class TestQoS(VyOSUnitTestSHIM.TestCase):              class_bandwidth += 1              class_ceil += 1 +    def test_12_shaper_with_red_queue(self): +        bandwidth = 100 +        default_bandwidth = 100 +        default_burst = 100 +        interface = self._interfaces[0] +        class_bandwidth = 50 +        dst_address = '192.0.2.8/32' + +        shaper_name = f'qos-shaper-{interface}' +        self.cli_set(base_path + ['interface', interface, 'egress', shaper_name]) +        self.cli_set(base_path + ['policy', 'shaper', shaper_name, 'bandwidth', f'{bandwidth}mbit']) +        self.cli_set(base_path + ['policy', 'shaper', shaper_name, 'default', 'bandwidth', f'{default_bandwidth}%']) +        self.cli_set(base_path + ['policy', 'shaper', shaper_name, 'default', 'burst', f'{default_burst}']) +        self.cli_set(base_path + ['policy', 'shaper', shaper_name, 'default', 'queue-type', 'random-detect']) + +        self.cli_set(base_path + ['policy', 'shaper', shaper_name, 'class', '2', 'bandwidth', f'{class_bandwidth}mbit']) +        self.cli_set(base_path + ['policy', 'shaper', shaper_name, 'class', '2', 'match', '10', 'ip', 'destination', 'address', dst_address]) +        self.cli_set(base_path + ['policy', 'shaper', shaper_name, 'class', '2', 'queue-type', 'random-detect']) + +        # commit changes +        self.cli_commit() + +        # check root htb config +        output = cmd(f'tc class show dev {interface}') + +        config_entries = ( +            f'prio 0 rate {class_bandwidth}Mbit ceil 50Mbit burst 15Kb',  # specified class +            f'prio 7 rate {default_bandwidth}Mbit ceil 100Mbit burst {default_burst}b',  # default class +        ) +        for config_entry in config_entries: +            self.assertIn(config_entry, output) + +        output = cmd(f'tc -d qdisc show dev {interface}') +        config_entries = ( +            'qdisc red',  # use random detect +            'limit 72Kb min 9Kb max 18Kb ewma 3 probability 0.1',  # default config for random detect +        ) +        for config_entry in config_entries: +            self.assertIn(config_entry, output) + +        # test random detect queue params +        self.cli_set(base_path + ['policy', 'shaper', shaper_name, 'default', 'queue-limit', '1024']) +        self.cli_set(base_path + ['policy', 'shaper', shaper_name, 'default', 'average-packet', '1024']) +        self.cli_set(base_path + ['policy', 'shaper', shaper_name, 'default', 'maximum-threshold', '32']) +        self.cli_set(base_path + ['policy', 'shaper', shaper_name, 'default', 'minimum-threshold', '16']) + +        self.cli_set(base_path + ['policy', 'shaper', shaper_name, 'class', '2', 'queue-limit', '1024']) +        self.cli_set(base_path + ['policy', 'shaper', shaper_name, 'class', '2', 'average-packet', '512']) +        self.cli_set(base_path + ['policy', 'shaper', shaper_name, 'class', '2', 'maximum-threshold', '32']) +        self.cli_set(base_path + ['policy', 'shaper', shaper_name, 'class', '2', 'minimum-threshold', '16']) +        self.cli_set(base_path + ['policy', 'shaper', shaper_name, 'class', '2', 'mark-probability', '20']) + +        self.cli_commit() + +        output = cmd(f'tc -d qdisc show dev {interface}') +        config_entries = ( +            'qdisc red',  # use random detect +            'limit 1Mb min 16Kb max 32Kb ewma 3 probability 0.1',  # default config for random detect +            'limit 512Kb min 8Kb max 16Kb ewma 3 probability 0.05',  # class config for random detect +        ) +        for config_entry in config_entries: +            self.assertIn(config_entry, output) +  if __name__ == '__main__':      unittest.main(verbosity=2) | 
