This is an automated email from the ASF dual-hosted git repository.

dewrich pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new e85eea8  Traffic Ops API/GUI and Traffic Portal configuration of FQ 
Pacing plugin
e85eea8 is described below

commit e85eea870c65f77b90f4ceac5b327080d3a2ff98
Author: Eric Friedrich <efrie...@cisco.com>
AuthorDate: Wed Jan 17 13:20:05 2018 -0500

    Traffic Ops API/GUI and Traffic Portal configuration of FQ Pacing plugin
---
 CHANGELOG.md                                       |  1 +
 docs/source/admin/traffic_ops/using.rst            |  5 +++++
 .../traffic_ops_api/v12/deliveryservice.rst        | 26 ++++++++++++++++++++++
 .../db/migrations/20180117000000_add_fq_pacing.sql | 23 +++++++++++++++++++
 .../app/lib/API/Configs/ApacheTrafficServer.pm     | 15 +++++++++++++
 traffic_ops/app/lib/API/Deliveryservice.pm         | 12 +++++++++-
 traffic_ops/app/lib/Fixtures/Deliveryservice.pm    | 15 +++++++++++++
 .../lib/Fixtures/Integration/Deliveryservice.pm    |  8 +++++++
 traffic_ops/app/lib/MojoPlugins/DeliveryService.pm | 18 ++++++++++++++-
 .../Result/DeliveryServiceInfoForDomainList.pm     |  2 ++
 .../Result/DeliveryServiceInfoForServerList.pm     |  2 ++
 .../app/lib/Schema/Result/Deliveryservice.pm       | 24 +++++++++++++-------
 traffic_ops/app/lib/UI/DeliveryService.pm          | 10 +++++++++
 traffic_ops/app/t/deliveryservice.t                |  2 ++
 .../app/templates/delivery_service/_form.html.ep   | 11 +++++++++
 .../app/templates/delivery_service/add.html.ep     |  4 ++++
 .../app/templates/delivery_service/edit.html.ep    |  4 ++++
 .../form.deliveryService.DNS.tpl.html              | 12 ++++++++++
 .../form.deliveryService.HTTP.tpl.html             | 12 ++++++++++
 .../app/src/traffic_portal_properties.json         |  4 ++++
 20 files changed, 200 insertions(+), 10 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cb15ac1..1ff16b9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -32,6 +32,7 @@ The format is based on [Keep a 
Changelog](http://keepachangelog.com/en/1.0.0/).
   - /api/1.3/statuses (R)
   - /api/1.3/system/info
   - /api/1.3/types (R)
+- Fair Queuing Pacing: Using the FQ Pacing Rate parameter in Delivery Services 
allows operators to limit the rate of individual sessions to the edge cache. 
This feature requires a Trafficserver RPM containing the fq_pacing experimental 
plugin AND setting 'fq' as the default Linux qdisc in sysctl. 
 
 ### Changed
 - Reformatted this CHANGELOG file to the keep-a-changelog format
diff --git a/docs/source/admin/traffic_ops/using.rst 
b/docs/source/admin/traffic_ops/using.rst
index b584975..825bf26 100644
--- a/docs/source/admin/traffic_ops/using.rst
+++ b/docs/source/admin/traffic_ops/using.rst
@@ -375,6 +375,11 @@ The fields in the Delivery Service view are:
 
+--------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 | DNS Bypass TTL                                   |                           
                                                                                
                                                                                
                          |
 
+--------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Maximum Bytes per Second allowed per session     | The maximum bytes per 
second a cache will delivery on any single TCP connection. This uses the Linux 
kernel's Fair Queuing setsockopt(SO_MAX_PACING_RATE) to limit the rate of 
delivery. Traffic exceeding this     |
+|                                                  | speed will only be 
rate-limited and not diverted. This option *requires* `net.core.default_qdisc = 
fq` in `/etc/sysctl.conf`.                                                      
                                 |
++--------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Long Description                                 | Long description for this 
delivery service. To be consumed from the APIs by downstream tools (Portal).    
                                                                                
                          |
++--------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 | Max DNS Answers                                  |                           
                                                                                
                                                                                
                          |
 
+--------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 | Delivery Service DNS TTL                         | The Time To Live on the 
DNS record for the Traffic Router A and AAAA records 
(``<routing-name>.<deliveryservice>.<cdn-domain>``).                            
                                                       |
diff --git a/docs/source/development/traffic_ops_api/v12/deliveryservice.rst 
b/docs/source/development/traffic_ops_api/v12/deliveryservice.rst
index fca9e49..a79345a 100644
--- a/docs/source/development/traffic_ops_api/v12/deliveryservice.rst
+++ b/docs/source/development/traffic_ops_api/v12/deliveryservice.rst
@@ -109,6 +109,9 @@ Delivery Service
   |                          |        | traffic will be sent to the 
dnsByPassIp* for DNS deliveryservices and to the httpBypassFqdn for             
                         |
   |                          |        | HTTP deliveryservices                  
                                                                                
              |
   
+--------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------+
+  | ``fqPacingRate``         |  int   | The maximum rate in bytes per second 
for each TCP connection in this delivery service. If exceeded,                  
                |
+  |                          |        | will be rate limited by the Linux 
kernel. A default value of 0 disables this feature                              
                   |
+  
+--------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------+
  
   | ``httpBypassFqdn``       | string | The HTTP destination to use for bypass 
on an HTTP deliveryservice - bypass starts when serving more than the           
              |
   |                          |        | globalMaxMbps traffic on this 
deliveryservice.                                                                
                       |
   
+--------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------+
@@ -228,6 +231,7 @@ Delivery Service
             "geoProvider": "0",
             "globalMaxMbps": null,
             "globalMaxTps": "0",
+           "fqPacingRate": "0",
             "httpBypassFqdn": "",
             "id": "442",
             "infoUrl": "",
@@ -350,6 +354,9 @@ Delivery Service
   |                          |        | traffic will be sent to the 
dnsByPassIp* for DNS deliveryservices and to the httpBypassFqdn for             
                         |
   |                          |        | HTTP deliveryservices                  
                                                                                
              |
   
+--------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------+
+  | ``fqPacingRate``         |  int   | The maximum rate in bytes per second 
for each TCP connection in this delivery service. If exceeded,                  
                |
+  |                          |        | will be rate limited by the Linux 
kernel. A default value of 0 disables this feature                              
                   |  
+  
+--------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------+
   | ``httpBypassFqdn``       | string | The HTTP destination to use for bypass 
on an HTTP deliveryservice - bypass starts when serving more than the           
              |
   |                          |        | globalMaxMbps traffic on this 
deliveryservice.                                                                
                       |
   
+--------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------+
@@ -477,6 +484,7 @@ Delivery Service
             "geoProvider": "0",
             "globalMaxMbps": null,
             "globalMaxTps": "0",
+           "fqPacingRate": "0",
             "httpBypassFqdn": "",
             "id": "442",
             "infoUrl": "",
@@ -2122,6 +2130,9 @@ URL Sig Keys
   |                        |          | traffic will be sent to the 
dnsByPassIp* for DNS deliveryservices and to the httpBypassFqdn for         |
   |                        |          | HTTP deliveryservices                  
                                                                 |
   
+------------------------+----------+---------------------------------------------------------------------------------------------------------+
+  | fqPacingRate           | no       | The maximum rate in bytes per second 
for each TCP connection in this delivery service. If exceeded,     |
+  |                        |          | will be rate limited by the Linux 
kernel. A default value of 0 disables this feature                    |  
+  
+------------------------+----------+---------------------------------------------------------------------------------------------------------+
   | httpBypassFqdn         | no       | The HTTP destination to use for bypass 
on an HTTP deliveryservice - bypass starts when serving more     |
   |                        |          | than the globalMaxMbps traffic on this 
deliveryservice.                                                 |
   
+------------------------+----------+---------------------------------------------------------------------------------------------------------+
@@ -2303,6 +2314,9 @@ URL Sig Keys
   | ``httpBypassFqdn``       | string | The HTTP destination to use for bypass 
on an HTTP deliveryservice - bypass starts when serving more than the           
              |
   |                          |        | globalMaxMbps traffic on this 
deliveryservice.                                                                
                       |
   
+--------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------+
+  | ``fqPacingRate``         |  int   | The maximum rate in bytes per second 
for each TCP connection in this delivery service. If exceeded,                  
                |
+  |                          |        | will be rate limited by the Linux 
kernel. A default value of 0 disables this feature                              
                   |  
+  
+--------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------+
   | ``id``                   |  int   | The deliveryservice id (database row 
number).                                                                        
                |
   
+--------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------+
   | ``infoUrl``              | string | Use this to add a URL that points to 
more information about that deliveryservice.                                    
                |
@@ -2423,6 +2437,7 @@ URL Sig Keys
             "geoProvider": "0",
             "globalMaxMbps": null,
             "globalMaxTps": "0",
+           "fqPacingRate": "0",
             "httpBypassFqdn": "",
             "id": "442",
             "infoUrl": "",
@@ -2545,6 +2560,9 @@ URL Sig Keys
   |                        |          | traffic will be sent to the 
dnsByPassIp* for DNS deliveryservices and to the httpBypassFqdn for         |
   |                        |          | HTTP deliveryservices                  
                                                                 |
   
+------------------------+----------+---------------------------------------------------------------------------------------------------------+
+  | fqPacingRate           | no       | The maximum rate in bytes per second 
for each TCP connection in this delivery service. If exceeded,     |
+  |                        |          | will be rate limited by the Linux 
kernel. A default value of 0 disables this feature                    |  
+  
+------------------------+----------+---------------------------------------------------------------------------------------------------------+
   | httpBypassFqdn         | no       | The HTTP destination to use for bypass 
on an HTTP deliveryservice - bypass starts when serving more     |
   |                        |          | than the globalMaxMbps traffic on this 
deliveryservice.                                                 |
   
+------------------------+----------+---------------------------------------------------------------------------------------------------------+
@@ -2723,6 +2741,9 @@ URL Sig Keys
   |                          |        | traffic will be sent to the 
dnsByPassIp* for DNS deliveryservices and to the httpBypassFqdn for             
                         |
   |                          |        | HTTP deliveryservices                  
                                                                                
              |
   
+--------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------+
+  | ``fqPacingRate``         |  int   | The maximum rate in bytes per second 
for each TCP connection in this delivery service. If exceeded,                  
                |
+  |                          |        | will be rate limited by the Linux 
kernel. A default value of 0 disables this feature                              
                   |  
+  
+--------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------+
   | ``httpBypassFqdn``       | string | The HTTP destination to use for bypass 
on an HTTP deliveryservice - bypass starts when serving more than the           
              |
   |                          |        | globalMaxMbps traffic on this 
deliveryservice.                                                                
                       |
   
+--------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------+
@@ -2846,6 +2867,7 @@ URL Sig Keys
             "geoProvider": "0",
             "globalMaxMbps": null,
             "globalMaxTps": "0",
+           "fqPacingRate": "0",
             "httpBypassFqdn": "",
             "id": "442",
             "infoUrl": "",
@@ -2998,6 +3020,9 @@ URL Sig Keys
   |                          |        | traffic will be sent to the 
dnsByPassIp* for DNS deliveryservices and to the httpBypassFqdn for             
                         |
   |                          |        | HTTP deliveryservices                  
                                                                                
              |
   
+--------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------+
+  | ``fqPacingRate``         |  int   | The maximum rate in bytes per second 
for each TCP connection in this delivery service. If exceeded,                  
                |
+  |                          |        | will be rate limited by the Linux 
kernel. A default value of 0 disables this feature                              
                   |  
+  
+--------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------+
   | ``httpBypassFqdn``       | string | The HTTP destination to use for bypass 
on an HTTP deliveryservice - bypass starts when serving more than the           
              |
   |                          |        | globalMaxMbps traffic on this 
deliveryservice.                                                                
                       |
   
+--------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------+
@@ -3121,6 +3146,7 @@ URL Sig Keys
             "geoProvider": "0",
             "globalMaxMbps": null,
             "globalMaxTps": "0",
+           "fqPacingRate": "0",
             "httpBypassFqdn": "",
             "id": "442",
             "infoUrl": "www.info.com",
diff --git a/traffic_ops/app/db/migrations/20180117000000_add_fq_pacing.sql 
b/traffic_ops/app/db/migrations/20180117000000_add_fq_pacing.sql
new file mode 100644
index 0000000..e033fcd
--- /dev/null
+++ b/traffic_ops/app/db/migrations/20180117000000_add_fq_pacing.sql
@@ -0,0 +1,23 @@
+/*
+
+    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
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+-- +goose Up
+-- SQL in section 'Up' is executed when this migration is applied
+ALTER TABLE deliveryservice ADD COLUMN fq_pacing_rate bigint default 0;
+
+-- +goose Down
+-- SQL section 'Down' is executed when this migration is rolled back
+ALTER TABLE deliveryservice DROP COLUMN fq_pacing_rate;
+
diff --git a/traffic_ops/app/lib/API/Configs/ApacheTrafficServer.pm 
b/traffic_ops/app/lib/API/Configs/ApacheTrafficServer.pm
index 532c072..ab9c95d 100755
--- a/traffic_ops/app/lib/API/Configs/ApacheTrafficServer.pm
+++ b/traffic_ops/app/lib/API/Configs/ApacheTrafficServer.pm
@@ -505,6 +505,7 @@ sub delivery_service_data_by_profile {
                deliveryservice.protocol,
                deliveryservice.ssl_key_version,
                deliveryservice.range_request_handling,
+               deliveryservice.fq_pacing_rate,
                deliveryservice.edge_header_rewrite,
                deliveryservice.mid_header_rewrite,
                deliveryservice.regex_remap,
@@ -550,6 +551,7 @@ sub delivery_service_data_by_profile {
        my $deliveryservice_protocol;
        my $deliveryservice_ssl_key_version;
        my $deliveryservice_range_request_handling;
+       my $deliveryservice_fq_pacing_rate;
        my $deliveryservice_edge_header_rewrite;
        my $deliveryservice_mid_header_rewrite;
        my $deliveryservice_regex_remap;
@@ -575,6 +577,7 @@ sub delivery_service_data_by_profile {
                \$deliveryservice_protocol,
                \$deliveryservice_ssl_key_version,
                \$deliveryservice_range_request_handling,
+               \$deliveryservice_fq_pacing_rate,
                \$deliveryservice_edge_header_rewrite,
                \$deliveryservice_mid_header_rewrite,
                \$deliveryservice_regex_remap,
@@ -604,6 +607,7 @@ sub delivery_service_data_by_profile {
                                        "protocol" => $deliveryservice_protocol,
                                        "ssl_key_version" => 
$deliveryservice_ssl_key_version,
                                        "range_request_handling" => 
$deliveryservice_range_request_handling,
+                                       "fq_pacing_rate" => 
$deliveryservice_fq_pacing_rate,
                                        "edge_header_rewrite" => 
$deliveryservice_edge_header_rewrite,
                                        "mid_header_rewrite" => 
$deliveryservice_mid_header_rewrite,
                                        "regex_remap" => 
$deliveryservice_regex_remap,
@@ -644,6 +648,7 @@ sub profile_ds_data {
                my $regex_remap                 = $row->{'regex_remap'};
                my $protocol                    = $row->{'protocol'};
                my $range_request_handling      = 
$row->{'range_request_handling'};
+               my $fq_pacing_rate              = $row->{'fq_pacing_rate'};
                my $origin_shield               = $row->{'origin_shield'};
                my $cacheurl                    = $row->{'cacheurl'};
                my $remap_text                  = $row->{'remap_text'};
@@ -713,6 +718,7 @@ sub profile_ds_data {
                $dsinfo->{dslist}->[$j]->{"mid_header_rewrite"}          = 
$mid_header_rewrite;
                $dsinfo->{dslist}->[$j]->{"regex_remap"}                 = 
$regex_remap;
                $dsinfo->{dslist}->[$j]->{"range_request_handling"}      = 
$range_request_handling;
+               $dsinfo->{dslist}->[$j]->{"fq_pacing_rate"}              = 
$fq_pacing_rate;
                $dsinfo->{dslist}->[$j]->{"origin_shield"}               = 
$origin_shield;
                $dsinfo->{dslist}->[$j]->{"cacheurl"}                    = 
$cacheurl;
                $dsinfo->{dslist}->[$j]->{"remap_text"}                  = 
$remap_text;
@@ -768,6 +774,7 @@ sub cdn_ds_data {
                my $regex_remap                 = $row->regex_remap;
                my $protocol                    = $row->protocol;
                my $range_request_handling      = $row->range_request_handling;
+               my $fq_pacing_rate              = $row->fq_pacing_rate;
                my $origin_shield               = $row->origin_shield;
                my $cacheurl                    = $row->cacheurl;
                my $remap_text                  = $row->remap_text;
@@ -837,6 +844,7 @@ sub cdn_ds_data {
                $dsinfo->{dslist}->[$j]->{"mid_header_rewrite"}          = 
$mid_header_rewrite;
                $dsinfo->{dslist}->[$j]->{"regex_remap"}                 = 
$regex_remap;
                $dsinfo->{dslist}->[$j]->{"range_request_handling"}      = 
$range_request_handling;
+               $dsinfo->{dslist}->[$j]->{"fq_pacing_rate"}              = 
$fq_pacing_rate;
                $dsinfo->{dslist}->[$j]->{"origin_shield"}               = 
$origin_shield;
                $dsinfo->{dslist}->[$j]->{"cacheurl"}                    = 
$cacheurl;
                $dsinfo->{dslist}->[$j]->{"remap_text"}                  = 
$remap_text;
@@ -902,6 +910,7 @@ sub ds_data {
                my $regex_remap                 = $dsinfo->regex_remap;
                my $protocol                    = $dsinfo->protocol;
                my $range_request_handling      = 
$dsinfo->range_request_handling;
+               my $fq_pacing_rate              = $dsinfo->fq_pacing_rate;
                my $origin_shield               = $dsinfo->origin_shield;
                my $cacheurl                    = $dsinfo->cacheurl;
                my $remap_text                  = $dsinfo->remap_text;
@@ -970,6 +979,7 @@ sub ds_data {
                $response_obj->{dslist}->[$j]->{"mid_header_rewrite"}          
= $mid_header_rewrite;
                $response_obj->{dslist}->[$j]->{"regex_remap"}                 
= $regex_remap;
                $response_obj->{dslist}->[$j]->{"range_request_handling"}      
= $range_request_handling;
+               $response_obj->{dslist}->[$j]->{"fq_pacing_rate"}              
= $fq_pacing_rate;
                $response_obj->{dslist}->[$j]->{"origin_shield"}               
= $origin_shield;
                $response_obj->{dslist}->[$j]->{"cacheurl"}                    
= $cacheurl;
                $response_obj->{dslist}->[$j]->{"remap_text"}                  
= $remap_text;
@@ -1138,6 +1148,7 @@ sub remap_ds_data {
                        my $regex_remap                 = $dsinfo->regex_remap;
                        my $protocol                    = $dsinfo->protocol;
                        my $range_request_handling      = 
$dsinfo->range_request_handling;
+                       my $fq_pacing_rate              = 
$dsinfo->fq_pacing_rate;
                        my $cacheurl                    = $dsinfo->cacheurl;
                        my $remap_text                  = $dsinfo->remap_text;
 
@@ -1201,6 +1212,7 @@ sub remap_ds_data {
                        $response_obj->{dslist}->[$j]->{"edge_header_rewrite"}  
       = $edge_header_rewrite;
                        $response_obj->{dslist}->[$j]->{"regex_remap"}          
       = $regex_remap;
                        
$response_obj->{dslist}->[$j]->{"range_request_handling"}      = 
$range_request_handling;
+                       $response_obj->{dslist}->[$j]->{"fq_pacing_rate"}       
       = $fq_pacing_rate;
                        $response_obj->{dslist}->[$j]->{"cacheurl"}             
       = $cacheurl;
                        $response_obj->{dslist}->[$j]->{"remap_text"}           
       = $remap_text;
 
@@ -2701,6 +2713,9 @@ sub build_remap_line {
        if ( defined( $remap->{remap_text} ) ) {
                $text .= " " . $remap->{remap_text};
        }
+       if ( defined( $remap->{fq_pacing_rate} ) && $remap->{fq_pacing_rate} > 
0 ) {
+               $text .= " \@plugin=fq_pacing.so \@pparam=--rate=" . 
$remap->{fq_pacing_rate}; 
+       }       
        $text .= "\n";
        return $text;
 }
diff --git a/traffic_ops/app/lib/API/Deliveryservice.pm 
b/traffic_ops/app/lib/API/Deliveryservice.pm
index 9a8018d..beb6e4e 100644
--- a/traffic_ops/app/lib/API/Deliveryservice.pm
+++ b/traffic_ops/app/lib/API/Deliveryservice.pm
@@ -121,6 +121,7 @@ sub index {
                                "geoProvider"          => $row->geo_provider,
                                "globalMaxMbps"        => $row->global_max_mbps,
                                "globalMaxTps"         => $row->global_max_tps,
+                               "fqPacingRate"         => $row->fq_pacing_rate,
                                "httpBypassFqdn"       => 
$row->http_bypass_fqdn,
                                "id"                   => $row->id,
                                "infoUrl"              => $row->info_url,
@@ -242,6 +243,7 @@ sub show {
                                "geoProvider"          => $row->geo_provider,
                                "globalMaxMbps"        => $row->global_max_mbps,
                                "globalMaxTps"         => $row->global_max_tps,
+                               "fqPacingRate"         => $row->fq_pacing_rate,
                                "httpBypassFqdn"       => 
$row->http_bypass_fqdn,
                                "id"                   => $row->id,
                                "infoUrl"              => $row->info_url,
@@ -348,6 +350,7 @@ sub update {
                geo_provider           => $params->{geoProvider},
                global_max_mbps        => $params->{globalMaxMbps},
                global_max_tps         => $params->{globalMaxTps},
+               fq_pacing_rate         => $params->{fqPacingRate},
                http_bypass_fqdn       => $params->{httpBypassFqdn},
                info_url               => $params->{infoUrl},
                initial_dispersion     => $params->{initialDispersion},
@@ -447,6 +450,7 @@ sub update {
                                "geoProvider"              => $rs->geo_provider,
                                "globalMaxMbps"            => 
$rs->global_max_mbps,
                                "globalMaxTps"             => 
$rs->global_max_tps,
+                               "fqPacingRate"             => 
$rs->fq_pacing_rate,
                                "httpBypassFqdn"           => 
$rs->http_bypass_fqdn,
                                "id"                       => $rs->id,
                                "infoUrl"                  => $rs->info_url,
@@ -579,6 +583,7 @@ sub safe_update {
                                "geoProvider"              => $rs->geo_provider,
                                "globalMaxMbps"            => 
$rs->global_max_mbps,
                                "globalMaxTps"             => 
$rs->global_max_tps,
+                               "fqPacingRate"             => 
$rs->fq_pacing_rate,
                                "httpBypassFqdn"           => 
$rs->http_bypass_fqdn,
                                "id"                       => $rs->id,
                                "infoUrl"                  => $rs->info_url,
@@ -685,6 +690,7 @@ sub create {
                geo_provider           => $params->{geoProvider},
                global_max_mbps        => $params->{globalMaxMbps},
                global_max_tps         => $params->{globalMaxTps},
+               fq_pacing_rate         => $params->{fqPacingRate},
                http_bypass_fqdn       => $params->{httpBypassFqdn},
                info_url               => $params->{infoUrl},
                initial_dispersion     => $params->{initialDispersion},
@@ -795,6 +801,7 @@ sub create {
                                "geoProvider"              => 
$insert->geo_provider,
                                "globalMaxMbps"            => 
$insert->global_max_mbps,
                                "globalMaxTps"             => 
$insert->global_max_tps,
+                               "fqPacingRate"             => 
$insert->fq_pacing_rate,
                                "httpBypassFqdn"           => 
$insert->http_bypass_fqdn,
                                "id"                       => $insert->id,
                                "infoUrl"                  => $insert->info_url,
@@ -987,6 +994,7 @@ sub get_deliveryservices_by_serverId {
                                        "geoProvider"          => 
$row->geo_provider,
                                        "globalMaxMbps"        => 
$row->global_max_mbps,
                                        "globalMaxTps"         => 
$row->global_max_tps,
+                                       "fqPacingRate"         => 
$row->fq_pacing_rate,
                                        "httpBypassFqdn"       => 
$row->http_bypass_fqdn,
                                        "id"                   => $row->id,
                                        "infoUrl"              => 
$row->info_url,
@@ -1086,6 +1094,7 @@ sub get_deliveryservices_by_userId {
                                        "geoProvider"          => 
$row->geo_provider,
                                        "globalMaxMbps"        => 
$row->global_max_mbps,
                                        "globalMaxTps"         => 
$row->global_max_tps,
+                                       "fqPacingRate"         => 
$row->fq_pacing_rate,    
                                        "httpBypassFqdn"       => 
$row->http_bypass_fqdn,
                                        "id"                   => $row->id,
                                        "infoUrl"              => 
$row->info_url,
@@ -1379,7 +1388,7 @@ sub is_deliveryservice_valid {
 
        my $rules = {
                fields => [
-                       qw/active cacheurl ccrDnsTtl cdnId checkPath 
deepCachingType displayName dnsBypassCname dnsBypassIp dnsBypassIp6 
dnsBypassTtl dscp edgeHeaderRewrite geoLimitRedirectURL geoLimit 
geoLimitCountries geoProvider globalMaxMbps globalMaxTps httpBypassFqdn infoUrl 
initialDispersion ipv6RoutingEnabled logsEnabled longDesc longDesc1 longDesc2 
maxDnsAnswers midHeaderRewrite missLat missLong multiSiteOrigin 
multiSiteOriginAlgorithm orgServerFqdn originShield profileId protocol 
qstringIgnore rang [...]
+                       qw/active cacheurl ccrDnsTtl cdnId checkPath 
deepCachingType displayName dnsBypassCname dnsBypassIp dnsBypassIp6 
dnsBypassTtl dscp edgeHeaderRewrite fqPacingRate geoLimitRedirectURL geoLimit 
geoLimitCountries geoProvider globalMaxMbps globalMaxTps httpBypassFqdn infoUrl 
initialDispersion ipv6RoutingEnabled logsEnabled longDesc longDesc1 longDesc2 
maxDnsAnswers midHeaderRewrite missLat missLong multiSiteOrigin 
multiSiteOriginAlgorithm orgServerFqdn originShield profileId protocol qstri 
[...]
                ],
 
                # validation checks to perform for ALL delivery services
@@ -1395,6 +1404,7 @@ sub is_deliveryservice_valid {
                        geoProvider                     => [ is_required("is 
required"), \&is_valid_int_or_undef ],
                        globalMaxMbps                   => [ 
\&is_valid_int_or_undef ],
                        globalMaxTps                    => [ 
\&is_valid_int_or_undef ],
+                       fqPacingRate                    => [ 
\&is_valid_int_or_undef ],
                        initialDispersion               => [ 
\&is_valid_int_or_undef ],
                        logsEnabled                     => [ is_required("is 
required") ],
                        maxDnsAnswers                   => [ 
\&is_valid_int_or_undef ],
diff --git a/traffic_ops/app/lib/Fixtures/Deliveryservice.pm 
b/traffic_ops/app/lib/Fixtures/Deliveryservice.pm
index 4069ccc..7adbea7 100644
--- a/traffic_ops/app/lib/Fixtures/Deliveryservice.pm
+++ b/traffic_ops/app/lib/Fixtures/Deliveryservice.pm
@@ -38,6 +38,7 @@ my %definition_for = (
                        ccr_dns_ttl           => 3600,
                        global_max_mbps       => 0,
                        global_max_tps        => 0,
+                       fq_pacing_rate        => 0,
                        long_desc             => 'test-ds1 long_desc',
                        long_desc_1           => 'test-ds1 long_desc_1',
                        long_desc_2           => 'test-ds1 long_desc_2',
@@ -78,6 +79,7 @@ my %definition_for = (
                        ccr_dns_ttl           => 3600,
                        global_max_mbps       => 0,
                        global_max_tps        => 0,
+                       fq_pacing_rate        => 0,                     
                        long_desc             => 'test-ds2 long_desc',
                        long_desc_1           => 'test-ds2 long_desc_1',
                        long_desc_2           => 'test-ds2 long_desc_2',
@@ -118,6 +120,7 @@ my %definition_for = (
                        ccr_dns_ttl           => 3600,
                        global_max_mbps       => 0,
                        global_max_tps        => 0,
+                       fq_pacing_rate        => 0,                     
                        long_desc             => 'test-ds3 long_desc',
                        long_desc_1           => 'test-ds3 long_desc_1',
                        long_desc_2           => 'test-ds3 long_desc_2',
@@ -158,6 +161,7 @@ my %definition_for = (
                        ccr_dns_ttl           => 3600,
                        global_max_mbps       => 0,
                        global_max_tps        => 0,
+                       fq_pacing_rate        => 0,                     
                        long_desc             => 'test-ds4 long_desc',
                        long_desc_1           => 'test-ds4 long_desc_1',
                        long_desc_2           => 'test-ds4 long_desc_2',
@@ -198,6 +202,7 @@ my %definition_for = (
                        ccr_dns_ttl           => 3600,
                        global_max_mbps       => 0,
                        global_max_tps        => 0,
+                       fq_pacing_rate        => 0,                     
                        long_desc             => 'test-ds5 long_desc',
                        long_desc_1           => 'test-ds5 long_desc_1',
                        long_desc_2           => 'test-ds5 long_desc_2',
@@ -238,6 +243,7 @@ my %definition_for = (
                        ccr_dns_ttl           => 3600,
                        global_max_mbps       => 0,
                        global_max_tps        => 0,
+                       fq_pacing_rate        => 10,                    
                        long_desc             => 'test-ds6 long_desc',
                        long_desc_1           => 'test-ds6 long_desc_1',
                        long_desc_2           => 'test-ds6 long_desc_2',
@@ -277,6 +283,7 @@ my %definition_for = (
                        ccr_dns_ttl           => 3600,
                        global_max_mbps       => 0,
                        global_max_tps        => 0,
+                       fq_pacing_rate        => 5,                     
                        long_desc             => 'steering-ds1 long_desc',
                        long_desc_1           => 'steering-ds1 long_desc_1',
                        long_desc_2           => 'steering-ds1 long_desc_2',
@@ -315,6 +322,7 @@ my %definition_for = (
                        ccr_dns_ttl           => 3600,
                        global_max_mbps       => 0,
                        global_max_tps        => 0,
+                       fq_pacing_rate        => 0,                     
                        long_desc             => 'steering-ds2 long_desc',
                        long_desc_1           => 'steering-ds2 long_desc_1',
                        long_desc_2           => 'steering-ds2 long_desc_2',
@@ -353,6 +361,7 @@ my %definition_for = (
                        ccr_dns_ttl           => 3600,
                        global_max_mbps       => 0,
                        global_max_tps        => 0,
+                       fq_pacing_rate        => 0,                     
                        long_desc             => 'new-steering-ds long_desc',
                        long_desc_1           => 'new-steering-ds long_desc_1',
                        long_desc_2           => 'new-steering-ds long_desc_2',
@@ -391,6 +400,7 @@ my %definition_for = (
                        ccr_dns_ttl           => 3600,
                        global_max_mbps       => 0,
                        global_max_tps        => 0,
+                       fq_pacing_rate        => 0,                     
                        long_desc             => 'target-ds1 long_desc',
                        long_desc_1           => 'target-ds1 long_desc_1',
                        long_desc_2           => 'target-ds1 long_desc_2',
@@ -429,6 +439,7 @@ my %definition_for = (
                        ccr_dns_ttl           => 3600,
                        global_max_mbps       => 0,
                        global_max_tps        => 0,
+                       fq_pacing_rate        => 0,                     
                        long_desc             => 'target-ds2 long_desc',
                        long_desc_1           => 'target-ds2 long_desc_1',
                        long_desc_2           => 'target-ds2 long_desc_2',
@@ -467,6 +478,7 @@ my %definition_for = (
                        ccr_dns_ttl           => 3600,
                        global_max_mbps       => 0,
                        global_max_tps        => 0,
+                       fq_pacing_rate        => 0,                     
                        long_desc             => 'target-ds3 long_desc',
                        long_desc_1           => 'target-ds3 long_desc_1',
                        long_desc_2           => 'target-ds3 long_desc_2',
@@ -505,6 +517,7 @@ my %definition_for = (
                        ccr_dns_ttl           => 3600,
                        global_max_mbps       => 0,
                        global_max_tps        => 0,
+                       fq_pacing_rate        => 0,                     
                        long_desc             => 'target-ds4 long_desc',
                        long_desc_1           => 'target-ds4 long_desc_1',
                        long_desc_2           => 'target-ds4 long_desc_2',
@@ -544,6 +557,7 @@ my %definition_for = (
                        ccr_dns_ttl           => 3600,
                        global_max_mbps       => 0,
                        global_max_tps        => 0,
+                       fq_pacing_rate        => 0,                     
                        long_desc             => 'test-ds1-root long_desc',
                        long_desc_1           => 'test-ds1-root long_desc_1',
                        long_desc_2           => 'test-ds1-root long_desc_2',
@@ -584,6 +598,7 @@ my %definition_for = (
                        ccr_dns_ttl           => 3600,
                        global_max_mbps       => 0,
                        global_max_tps        => 0,
+                       fq_pacing_rate        => 0,                     
                        long_desc             => 'foo.bar long_desc',
                        long_desc_1           => 'foo.bar long_desc_1',
                        long_desc_2           => 'foo.bar long_desc_2',
diff --git a/traffic_ops/app/lib/Fixtures/Integration/Deliveryservice.pm 
b/traffic_ops/app/lib/Fixtures/Integration/Deliveryservice.pm
index c4e3a3a..678df65 100644
--- a/traffic_ops/app/lib/Fixtures/Integration/Deliveryservice.pm
+++ b/traffic_ops/app/lib/Fixtures/Integration/Deliveryservice.pm
@@ -63,6 +63,7 @@ my %definition_for = (
                        profile                     => '8',
                        ssl_key_version             => '0',
                        global_max_tps              => '0',
+                       fq_pacing_rate              => '0',
                        max_dns_answers             => '0',
                        tr_response_headers         => undef,
                        tenant_id                   => undef,
@@ -106,6 +107,7 @@ my %definition_for = (
                        cdn_id                      => '1',
                        global_max_mbps             => '0',
                        global_max_tps              => '0',
+                       fq_pacing_rate              => '0',                     
                        long_desc_2                 => 'test-ds3 long_desc_2',
                        origin_shield               => undef,
                        long_desc_1                 => 'test-ds3 long_desc_1',
@@ -163,6 +165,7 @@ my %definition_for = (
                        range_request_handling      => '0',
                        geo_limit                   => '0',
                        global_max_mbps             => '0',
+                       fq_pacing_rate              => '0',                     
                        long_desc_2                 => 'test-ds2 long_desc_2',
                        origin_shield               => undef,
                        max_dns_answers             => '0',
@@ -229,6 +232,7 @@ my %definition_for = (
                        tr_response_headers         => undef,
                        dns_bypass_cname            => undef,
                        global_max_tps              => '0',
+                       fq_pacing_rate              => '7',                     
                        long_desc_2                 => 'test-ds1 long_desc_2',
                        qstring_ignore              => '0',
                        tr_request_headers          => undef,
@@ -280,6 +284,7 @@ my %definition_for = (
                        edge_header_rewrite         => undef,
                        global_max_mbps             => '0',
                        global_max_tps              => '0',
+                       fq_pacing_rate              => '0',                     
                        http_bypass_fqdn            => '',
                        origin_shield               => undef,
                        tenant_id                   => undef,
@@ -314,6 +319,7 @@ my %definition_for = (
                        routing_name                => 'foo',
                        remap_text                  => undef,
                        global_max_mbps             => '0',
+                       fq_pacing_rate              => '0',                     
                        http_bypass_fqdn            => '',
                        miss_long                   => '-87.627778',
                        org_server_fqdn             => 
'https://games.origin.kabletown.net',
@@ -365,6 +371,7 @@ my %definition_for = (
                        deep_caching_type           => 'NEVER',
                        routing_name                => 'foo',
                        global_max_tps              => '0',
+                       fq_pacing_rate              => '0',                     
                        initial_dispersion          => '1',
                        multi_site_origin           => undef,
                        org_server_fqdn             => 
'http://national-tv.origin.kabletown.net',
@@ -421,6 +428,7 @@ my %definition_for = (
                        dns_bypass_ip               => '',
                        dns_bypass_ttl              => undef,
                        global_max_tps              => '0',
+                       fq_pacing_rate              => '1000000000',            
        
                        max_dns_answers             => '0',
                        regex_remap                 => undef,
                        remap_text                  => undef,
diff --git a/traffic_ops/app/lib/MojoPlugins/DeliveryService.pm 
b/traffic_ops/app/lib/MojoPlugins/DeliveryService.pm
index f9e6a53..e3879c3 100755
--- a/traffic_ops/app/lib/MojoPlugins/DeliveryService.pm
+++ b/traffic_ops/app/lib/MojoPlugins/DeliveryService.pm
@@ -55,13 +55,29 @@ sub register {
                        elsif ( $inp =~ /^(\d+)G$/ ) { return $1 * 1000; }
                        elsif ( $inp =~ /^(\d+)M$/ ) { return $1; }
                        elsif ( $inp =~ /^(\d+)k$/ ) { return int( $1 / 1000 ); 
}
-                       elsif ( $inp =~ /^\d+$/ )    { return $1; }
+                       elsif ( $inp =~ /^(\d+)$/  ) { return $1; }
                        else                         { return -1; }
 
                }
        );
 
        $app->renderer->add_helper(
+               hr_string_to_bps => sub {
+                       my $self = shift;
+                       my $inp  = shift;
+
+                       if    ( !defined($inp) )     { return 0; }              
    # default is 0
+                       elsif ( $inp =~ /^(\d+)T$/ ) { return $1 * 
1000000000000; }
+                       elsif ( $inp =~ /^(\d+)G$/ ) { return $1 * 1000000000; }
+                       elsif ( $inp =~ /^(\d+)M$/ ) { return $1 * 1000000; }
+                       elsif ( $inp =~ /^(\d+)k$/ ) { return $1 * 1000; }
+                       elsif ( $inp =~ /^(\d+)$/  ) { return $1; }
+                       else                         { return -1; }
+
+               }
+       );
+       
+       $app->renderer->add_helper(
                is_delivery_service_assigned => sub {
                        my $self = shift || confess($no_instance_message);
                        my $id   = shift || confess("Please supply a delivery 
service ID");
diff --git 
a/traffic_ops/app/lib/Schema/Result/DeliveryServiceInfoForDomainList.pm 
b/traffic_ops/app/lib/Schema/Result/DeliveryServiceInfoForDomainList.pm
index 2975474..fe37913 100644
--- a/traffic_ops/app/lib/Schema/Result/DeliveryServiceInfoForDomainList.pm
+++ b/traffic_ops/app/lib/Schema/Result/DeliveryServiceInfoForDomainList.pm
@@ -48,6 +48,7 @@ SELECT
     deliveryservice.org_server_fqdn,
     deliveryservice.multi_site_origin,
     deliveryservice.range_request_handling,
+    deliveryservice.fq_pacing_rate,  
     deliveryservice.origin_shield,
     regex.pattern,
     retype.name AS re_type,
@@ -102,6 +103,7 @@ __PACKAGE__->add_columns(
        "remap_text",                  { data_type => "varchar", is_nullable => 
0, size => 2048 },
        "protocol",                    { data_type => "tinyint", is_nullable => 
0, size => 4 },
        "range_request_handling",      { data_type => "tinyint", is_nullable => 
0, size => 4 },
+       "fq_pacing_rate",              { data_type => "bigint",  is_nullable => 
0 },   
        "origin_shield",               { data_type => "varchar", is_nullable => 
0, size => 1024 },
        "profile",                     { data_type => "integer", is_nullable => 
1},
 );
diff --git 
a/traffic_ops/app/lib/Schema/Result/DeliveryServiceInfoForServerList.pm 
b/traffic_ops/app/lib/Schema/Result/DeliveryServiceInfoForServerList.pm
index 239cc09..2d84155 100644
--- a/traffic_ops/app/lib/Schema/Result/DeliveryServiceInfoForServerList.pm
+++ b/traffic_ops/app/lib/Schema/Result/DeliveryServiceInfoForServerList.pm
@@ -48,6 +48,7 @@ SELECT
     deliveryservice.org_server_fqdn as org_server_fqdn,
     deliveryservice.multi_site_origin as multi_site_origin,
     deliveryservice.range_request_handling as range_request_handling,
+    deliveryservice.fq_pacing_rate as fq_pacing_rate,
     deliveryservice.origin_shield as origin_shield,
     regex.pattern AS pattern,
     retype.name AS re_type,
@@ -95,6 +96,7 @@ __PACKAGE__->add_columns(
        "remap_text",                  { data_type => "varchar", is_nullable => 
0, size => 2048 },
        "protocol",                    { data_type => "tinyint", is_nullable => 
0, size => 4 },
        "range_request_handling",      { data_type => "tinyint", is_nullable => 
0, size => 4 },
+        "fq_pacing_rate",              { data_type => "bigint",  is_nullable 
=> 0},
        "origin_shield",               { data_type => "varchar", is_nullable => 
0, size => 1024 },
        "profile",                     { data_type => "integer", is_nullable => 
1},
 );
diff --git a/traffic_ops/app/lib/Schema/Result/Deliveryservice.pm 
b/traffic_ops/app/lib/Schema/Result/Deliveryservice.pm
index b458b40..f37e415 100644
--- a/traffic_ops/app/lib/Schema/Result/Deliveryservice.pm
+++ b/traffic_ops/app/lib/Schema/Result/Deliveryservice.pm
@@ -138,7 +138,7 @@ __PACKAGE__->table("deliveryservice");
 =head2 max_dns_answers
 
   data_type: 'bigint'
-  default_value: 0
+  default_value: 5
   is_nullable: 1
 
 =head2 info_url
@@ -306,6 +306,12 @@ __PACKAGE__->table("deliveryservice");
   extra: {custom_type_name => "deep_caching_type",list => ["NEVER","ALWAYS"]}
   is_nullable: 1
 
+=head2 fq_pacing_rate
+
+  data_type: 'bigint'
+  default_value: 0
+  is_nullable: 1
+
 =cut
 
 __PACKAGE__->add_columns(
@@ -357,7 +363,7 @@ __PACKAGE__->add_columns(
   "long_desc_2",
   { data_type => "text", is_nullable => 1 },
   "max_dns_answers",
-  { data_type => "bigint", default_value => 0, is_nullable => 1 },
+  { data_type => "bigint", default_value => 5, is_nullable => 1 },
   "info_url",
   { data_type => "text", is_nullable => 1 },
   "miss_lat",
@@ -431,6 +437,8 @@ __PACKAGE__->add_columns(
     },
     is_nullable => 1,
   },
+  "fq_pacing_rate",
+  { data_type => "bigint", default_value => 0, is_nullable => 1 },
 );
 
 =head1 PRIMARY KEY
@@ -449,7 +457,7 @@ __PACKAGE__->set_primary_key("id", "type");
 
 =head1 UNIQUE CONSTRAINTS
 
-=head2 C<idx_140234_ds_id_unique>
+=head2 C<idx_89502_ds_id_unique>
 
 =over 4
 
@@ -459,9 +467,9 @@ __PACKAGE__->set_primary_key("id", "type");
 
 =cut
 
-__PACKAGE__->add_unique_constraint("idx_140234_ds_id_unique", ["id"]);
+__PACKAGE__->add_unique_constraint("idx_89502_ds_id_unique", ["id"]);
 
-=head2 C<idx_140234_ds_name_unique>
+=head2 C<idx_89502_ds_name_unique>
 
 =over 4
 
@@ -471,7 +479,7 @@ 
__PACKAGE__->add_unique_constraint("idx_140234_ds_id_unique", ["id"]);
 
 =cut
 
-__PACKAGE__->add_unique_constraint("idx_140234_ds_name_unique", ["xml_id"]);
+__PACKAGE__->add_unique_constraint("idx_89502_ds_name_unique", ["xml_id"]);
 
 =head1 RELATIONS
 
@@ -666,8 +674,8 @@ __PACKAGE__->belongs_to(
 );
 
 
-# Created by DBIx::Class::Schema::Loader v0.07042 @ 2017-11-09 14:44:59
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:IA1IQ3w/BEYermjf9PoVtA
+# Created by DBIx::Class::Schema::Loader v0.07047 @ 2018-02-28 21:54:35
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:3ETqht/3FTxKgD/YuRf3Bg
 
 # You can replace this text with custom code or comments, and it will be 
preserved on regeneration
 #
diff --git a/traffic_ops/app/lib/UI/DeliveryService.pm 
b/traffic_ops/app/lib/UI/DeliveryService.pm
index d9752a7..4443349 100644
--- a/traffic_ops/app/lib/UI/DeliveryService.pm
+++ b/traffic_ops/app/lib/UI/DeliveryService.pm
@@ -232,6 +232,7 @@ sub read {
                                "profile_description"         => 
$row->profile->description,
                                "global_max_mbps"             => 
$row->global_max_mbps,
                                "global_max_tps"              => 
$row->global_max_tps,
+                               "fq_pacing_rate"              => 
$row->fq_pacing_rate,    
                                "edge_header_rewrite"         => 
$row->edge_header_rewrite,
                                "mid_header_rewrite"          => 
$row->mid_header_rewrite,
                                "tr_response_headers"         => 
$row->tr_response_headers,
@@ -498,6 +499,13 @@ sub check_deliveryservice_input {
        {
                $self->field('ds.global_max_tps')->is_equal( "", "Invalid 
global_max_tps (NaN)." );
        }
+       if (   defined( $self->param('ds.fq_pacing_rate') )
+               && $self->param('ds.fq_pacing_rate') ne "" )
+       {
+               if ( $self->hr_string_to_bps( $self->param('ds.fq_pacing_rate') 
) < 0 ) {
+                       $self->field('ds.fq_pacing_rate')->is_equal( "", 
"Invalid fq_pacing_rate (NaN)." );
+               }           
+       }              
 
        if ( $typename =~ /^DNS/ ) {
                if ( defined( $self->param('ds.tr_response_headers') )
@@ -814,6 +822,7 @@ sub update {
                        profile                     => 
($self->paramAsScalar('ds.profile') == -1) ? undef : 
$self->paramAsScalar('ds.profile'),
                        global_max_mbps             => 
$self->hr_string_to_mbps( $self->paramAsScalar( 'ds.global_max_mbps', 0 ) ),
                        global_max_tps              => $self->paramAsScalar( 
'ds.global_max_tps', 0 ),
+                       fq_pacing_rate              => $self->hr_string_to_bps( 
$self->paramAsScalar('ds.fq_pacing_rate', 0) ),
                        miss_lat                    => 
$self->paramAsScalar('ds.miss_lat'),
                        miss_long                   => 
$self->paramAsScalar('ds.miss_long'),
                        long_desc                   => 
$self->paramAsScalar('ds.long_desc'),
@@ -1053,6 +1062,7 @@ sub create {
                                profile                     => 
($self->paramAsScalar('ds.profile') == -1) ? undef : 
$self->paramAsScalar('ds.profile'),
                                global_max_mbps             => 
$self->hr_string_to_mbps( $self->paramAsScalar( 'ds.global_max_mbps', 0 ) ),
                                global_max_tps              => 
$self->paramAsScalar( 'ds.global_max_tps', 0 ),
+                               fq_pacing_rate              => 
$self->hr_string_to_bps($self->paramAsScalar('ds.fq_pacing_rate', 0)),
                                miss_lat                    => 
$self->paramAsScalar('ds.miss_lat'),
                                miss_long                   => 
$self->paramAsScalar('ds.miss_long'),
                                long_desc                   => 
$self->paramAsScalar('ds.long_desc'),
diff --git a/traffic_ops/app/t/deliveryservice.t 
b/traffic_ops/app/t/deliveryservice.t
index c6b76ce..5e017dc 100644
--- a/traffic_ops/app/t/deliveryservice.t
+++ b/traffic_ops/app/t/deliveryservice.t
@@ -256,6 +256,7 @@ ok $t->post_ok(
                'ds.global_max_mbps'             => '4T',
                'ds.http_bypass_fqdn'            => '',
                'ds.global_max_tps'              => '10001',
+               'ds.fq_pacing_rate'              => '500k',
                'ds.info_url'                    => 'http://knutsel-update.com',
                'ds.long_desc'                   => 'long_update',
                'ds.long_desc_1'                 => 'cust_update',
@@ -311,6 +312,7 @@ ok $t->get_ok('/datadeliveryservice')->status_is(200)
   ->json_is( '/1/ccr_dns_ttl' => 3601 )
   ->json_is( '/1/global_max_mbps' => 4000000 )
   ->json_is( '/1/global_max_tps' => 10001 )
+  ->json_is( '/1/fq_pacing_rate' => 500000 )
   ->json_is( '/1/miss_lat' => '0' )
   ->json_is( '/1/miss_long' => '0' )
   ->json_is( '/1/long_desc' => 'long_update' )
diff --git a/traffic_ops/app/templates/delivery_service/_form.html.ep 
b/traffic_ops/app/templates/delivery_service/_form.html.ep
index b2e0156..86def8d 100644
--- a/traffic_ops/app/templates/delivery_service/_form.html.ep
+++ b/traffic_ops/app/templates/delivery_service/_form.html.ep
@@ -399,6 +399,17 @@
                %= field('ds.global_max_tps')->text(class => 'field', readonly 
=> 'readonly');
                <% }  %>
        </div>
+       <div class="block form-row" id="fq_pacing_rate_row">
+               <% unless (field('ds.fq_pacing_rate')->valid) { %>
+                       <span class="field-with-error"><%= 
field('ds.fq_pacing_rate')->error %></span>
+               <% } %>
+               %= label_for 'fq_pacing_rate' => 'Max Bytes per Second allowed 
per session (3000k or 5M are valid entries)', class => 'label'
+               <% if ($priv_level >= 20) { %>
+               %= field('ds.fq_pacing_rate')->text(class => 'field', id => 
'fq_pacing_rate', name => 'ds.fq_pacing_rate');
+               <% } else { %>
+               %= field('ds.fq_pacing_rate')->text(class => 'field', readonly 
=> 'readonly');
+               <% } %>
+       </div>  
        <div class="block form-row" id="miss_lat_row">
                <% unless (field('ds.miss_lat')->valid) { %>
                        <span class="field-with-error"><%= 
field('ds.miss_lat')->error %></span>
diff --git a/traffic_ops/app/templates/delivery_service/add.html.ep 
b/traffic_ops/app/templates/delivery_service/add.html.ep
index ea718ca..e6cc5d8 100644
--- a/traffic_ops/app/templates/delivery_service/add.html.ep
+++ b/traffic_ops/app/templates/delivery_service/add.html.ep
@@ -123,6 +123,7 @@
             $('#org_server_fqdn_row').show(speed);
             $('#global_max_mbps_row').show(speed);
             $('#global_max_tps_row').show(speed);
+            $('#fq_pacing_rate_row').show(speed);
             $('#miss_lat_row').show(speed);
             $('#miss_long_row').show(speed);
             $('#edge_header_rewrite_row').show(speed);
@@ -166,6 +167,7 @@
             $('#org_server_fqdn_row').show(speed);
             $('#global_max_mbps_row').show(speed);
             $('#global_max_tps_row').show(speed);
+            $('#fq_pacing_rate_row').show(speed);
             $('#miss_lat_row').show(speed);
             $('#miss_long_row').show(speed);
             $('#edge_header_rewrite_row').show(speed);
@@ -205,6 +207,7 @@
             $('#org_server_fqdn_row').hide(speed);
             $('#global_max_mbps_row').hide(speed);
             $('#global_max_tps_row').hide(speed);
+            $('#fq_pacing_rate_row').hide(speed);      
             $('#miss_lat_row').hide(speed);
             $('#miss_long_row').hide(speed);
             $('#edge_header_rewrite_row').hide(speed);
@@ -244,6 +247,7 @@
             $('#org_server_fqdn_row').hide(speed);
             $('#global_max_mbps_row').hide(speed);
             $('#global_max_tps_row').hide(speed);
+            $('#fq_pacing_rate_row').hide(speed);      
             $('#miss_lat_row').show(speed);
             $('#miss_long_row').show(speed);
             $('#edge_header_rewrite_row').hide(speed);
diff --git a/traffic_ops/app/templates/delivery_service/edit.html.ep 
b/traffic_ops/app/templates/delivery_service/edit.html.ep
index e3f674d..0c51145 100644
--- a/traffic_ops/app/templates/delivery_service/edit.html.ep
+++ b/traffic_ops/app/templates/delivery_service/edit.html.ep
@@ -217,6 +217,7 @@ function setup_form(speed) {
             $('#org_server_fqdn_row').show(speed);
             $('#global_max_mbps_row').show(speed);
             $('#global_max_tps_row').show(speed);
+            $('#fq_pacing_rate_row').show(speed);    
             $('#miss_lat_row').show(speed);
             $('#miss_long_row').show(speed);
             $('#edge_header_rewrite_row').show(speed);
@@ -258,6 +259,7 @@ function setup_form(speed) {
             $('#org_server_fqdn_row').show(speed);
             $('#global_max_mbps_row').show(speed);
             $('#global_max_tps_row').show(speed);
+            $('#fq_pacing_rate_row').show(speed);    
             $('#miss_lat_row').show(speed);
             $('#miss_long_row').show(speed);
             $('#edge_header_rewrite_row').show(speed);
@@ -297,6 +299,7 @@ function setup_form(speed) {
             $('#org_server_fqdn_row').hide(speed);
             $('#global_max_mbps_row').hide(speed);
             $('#global_max_tps_row').hide(speed);
+            $('#fq_pacing_rate_row').hide(speed);    
             $('#miss_lat_row').hide(speed);
             $('#miss_long_row').hide(speed);
             $('#edge_header_rewrite_row').hide(speed);
@@ -336,6 +339,7 @@ function setup_form(speed) {
             $('#org_server_fqdn_row').hide(speed);
             $('#global_max_mbps_row').hide(speed);
             $('#global_max_tps_row').hide(speed);
+            $('#fq_pacing_rate_row').hide(speed);    
             $('#miss_lat_row').show(speed);
             $('#miss_long_row').show(speed);
             $('#edge_header_rewrite_row').hide(speed);
diff --git 
a/traffic_portal/app/src/common/modules/form/deliveryService/form.deliveryService.DNS.tpl.html
 
b/traffic_portal/app/src/common/modules/form/deliveryService/form.deliveryService.DNS.tpl.html
index ec80c42..f2c8bd9 100644
--- 
a/traffic_portal/app/src/common/modules/form/deliveryService/form.deliveryService.DNS.tpl.html
+++ 
b/traffic_portal/app/src/common/modules/form/deliveryService/form.deliveryService.DNS.tpl.html
@@ -468,6 +468,18 @@ under the License.
                     </div>
                 </div>
 
+                <div class="form-group" ng-class="{'has-error': 
hasError(deliveryServiceForm.fqPacingRate), 'has-feedback': 
hasError(deliveryServiceForm.fqPacingRate)}">
+                    <label class="control-label col-md-2 col-sm-2 col-xs-12">
+                        <span uib-popover-html="label('fqPacingRate', 'desc')" 
popover-trigger="mouseenter" popover-placement="top" 
popover-append-to-body="true" 
popover-class="popover-class">{{label('fqPacingRate', 'title')}}</span>
+                    </label>
+                    <div class="col-md-10 col-sm-10 col-xs-12">
+                        <input name="fqPacingRate" type="number" 
class="form-control" placeholder="Rate-limit connections to this Bytes per 
second" ng-model="deliveryService.fqPacingRate" ng-pattern="/^\d+$/" autofocus>
+                        <small class="input-error" 
ng-show="hasPropertyError(deliveryServiceForm.fqPacingRate, 'pattern')">Whole 
Number</small>
+                        <small class="input-diff" ng-show="settings.isRequest 
&& open() && deliveryService.fqPacingRate != dsCurrent.fqPacingRate">Current 
Value: [ {{dsCurrent.fqPacingRate}} ]</small>
+                        <span 
ng-show="hasError(deliveryServiceForm.fqPacingRate)" 
class="form-control-feedback"><i class="fa fa-times"></i></span>
+                    </div>
+                </div>         
+
                 <div class="form-group" ng-class="{'has-error': 
hasError(deliveryServiceForm.edgeHeaderRewrite), 'has-feedback': 
hasError(deliveryServiceForm.edgeHeaderRewrite)}">
                     <label class="control-label col-md-2 col-sm-2 col-xs-12">
                         <span uib-popover-html="label('edgeHeaderRewrite', 
'desc')" popover-trigger="mouseenter" popover-placement="top" 
popover-append-to-body="true" 
popover-class="popover-class">{{label('edgeHeaderRewrite', 'title')}}</span>
diff --git 
a/traffic_portal/app/src/common/modules/form/deliveryService/form.deliveryService.HTTP.tpl.html
 
b/traffic_portal/app/src/common/modules/form/deliveryService/form.deliveryService.HTTP.tpl.html
index 61182fe..f7359e0 100644
--- 
a/traffic_portal/app/src/common/modules/form/deliveryService/form.deliveryService.HTTP.tpl.html
+++ 
b/traffic_portal/app/src/common/modules/form/deliveryService/form.deliveryService.HTTP.tpl.html
@@ -471,6 +471,18 @@ under the License.
                     </div>
                 </div>
 
+               <div class="form-group" ng-class="{'has-error': 
hasError(deliveryServiceForm.fqPacingRate), 'has-feedback': 
hasError(deliveryServiceForm.fqPacingRate)}">
+                    <label class="control-label col-md-2 col-sm-2 col-xs-12">
+                        <span uib-popover-html="label('fqPacingRate', 'desc')" 
popover-trigger="mouseenter" popover-placement="top" 
popover-append-to-body="true" 
popover-class="popover-class">{{label('fqPacingRate', 'title')}}</span>
+                    </label>
+                    <div class="col-md-10 col-sm-10 col-xs-12">
+                        <input name="fqPacingRate" type="number" 
class="form-control" placeholder="Rate-limit connections to this Bytes per 
second" ng-model="deliveryService.fqPacingRate" ng-pattern="/^\d+$/" autofocus>
+                        <small class="input-error" 
ng-show="hasPropertyError(deliveryServiceForm.fqPacingRate, 'pattern')">Whole 
Number</small>
+                        <small class="input-diff" ng-show="settings.isRequest 
&& open() && deliveryService.fqPacingRate != dsCurrent.fqPacingRate">Current 
Value: [ {{dsCurrent.fqPacingRate}} ]</small>
+                        <span 
ng-show="hasError(deliveryServiceForm.fqPacingRate)" 
class="form-control-feedback"><i class="fa fa-times"></i></span>
+                    </div>
+                </div>                         
+
                 <div class="form-group" ng-class="{'has-error': 
hasError(deliveryServiceForm.edgeHeaderRewrite), 'has-feedback': 
hasError(deliveryServiceForm.edgeHeaderRewrite)}">
                     <label class="control-label col-md-2 col-sm-2 col-xs-12">
                         <span uib-popover-html="label('edgeHeaderRewrite', 
'desc')" popover-trigger="mouseenter" popover-placement="top" 
popover-append-to-body="true" 
popover-class="popover-class">{{label('edgeHeaderRewrite', 'title')}}</span>
diff --git a/traffic_portal/app/src/traffic_portal_properties.json 
b/traffic_portal/app/src/traffic_portal_properties.json
index 3721018..7dc91a7 100644
--- a/traffic_portal/app/src/traffic_portal_properties.json
+++ b/traffic_portal/app/src/traffic_portal_properties.json
@@ -199,6 +199,10 @@
             "title": "Global Max TPS",
             "desc": "The maximum transactions this delivery service can serve 
across all EDGE caches before traffic will be diverted to the bypass 
destination. For a DNS delivery service, the Bypass Ipv4 or Ipv6 will be used 
(depending on whether this was a A or AAAA request), and for HTTP delivery 
services the Bypass FQDN will be used."
           },
+         "fqPacingRate": {
+           "title": "Fair Queuing Pacing Rate Bps",
+            "desc": "The maximum bytes per second a cache will delivery on any 
single TCP connection. This uses the Linux kernel's Fair Queuing 
setsockopt(SO_MAX_PACING_RATE) to limit the rate of delivery."
+          },
           "httpBypassFqdn": {
             "title": "HTTP Bypass FQDN",
             "desc": "This is the FQDN Traffic Router will redirect to (with 
the same path) when the max Bps or Max Tps for this delivery service are 
exceeded."

-- 
To stop receiving notification emails like this one, please contact
dewr...@apache.org.

Reply via email to