dewrich closed pull request #1799: Traffic Ops API/GUI configuration of FQ 
Pacing plugin
URL: https://github.com/apache/incubator-trafficcontrol/pull/1799
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cb15ac1ca..1ff16b960 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 b5849753e..825bf2668 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 fca9e4929..a79345a62 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 000000000..e033fcdb0
--- /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 532c07200..ab9c95d00 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 9a8018dc6..beb6e4eca 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 rangeRequestHandling regexRemap regionalGeoBlocking remapText 
routingName signed signingAlgorithm sslKeyVersion tenantId trRequestHeaders 
trResponseHeaders typeId xmlId/
+                       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 
qstringIgnore rangeRequestHandling regexRemap regionalGeoBlocking remapText 
routingName signed signingAlgorithm sslKeyVersion tenantId trRequestHeaders 
trResponseHeaders typeId xmlId/
                ],
 
                # 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 4069ccc72..7adbea790 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 c4e3a3aae..678df65b2 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 f9e6a538c..e3879c3db 100755
--- a/traffic_ops/app/lib/MojoPlugins/DeliveryService.pm
+++ b/traffic_ops/app/lib/MojoPlugins/DeliveryService.pm
@@ -55,12 +55,28 @@ 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);
diff --git 
a/traffic_ops/app/lib/Schema/Result/DeliveryServiceInfoForDomainList.pm 
b/traffic_ops/app/lib/Schema/Result/DeliveryServiceInfoForDomainList.pm
index 29754741f..fe37913a9 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 239cc093c..2d84155f2 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 b458b402a..f37e41565 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 d9752a778..4443349f8 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 c6b76ce82..5e017dc10 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 b2e0156bb..86def8dd8 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 ea718cab2..e6cc5d81a 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 e3f674d39..0c5114586 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 ec80c42bc..f2c8bd9ae 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 @@
                     </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 61182feb4..f7359e0e9 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 @@
                     </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 37210181f..7dc91a78e 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."


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to