diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/SettingsController.php b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/SettingsController.php index f93f514e9..77ab8cc19 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/SettingsController.php +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/SettingsController.php @@ -1104,6 +1104,136 @@ class SettingsController extends ApiControllerBase ); } + /** + * retrieve cpu settings or return defaults + * @param $uuid item unique id + * @return array + */ + public function getCpuAction($uuid = null) + { + $mdlCP = new HAProxy(); + if ($uuid != null) { + $node = $mdlCP->getNodeByReference('cpus.cpu.'.$uuid); + if ($node != null) { + // return node + return array("cpu" => $node->getNodes()); + } + } else { + // generate new node, but don't save to disc + $node = $mdlCP->cpus->cpu->add(); + return array("cpu" => $node->getNodes()); + } + return array(); + } + + /** + * update cpu with given properties + * @param $uuid item unique id + * @return array + */ + public function setCpuAction($uuid) + { + if ($this->request->isPost() && $this->request->hasPost("cpu")) { + $mdlCP = new HAProxy(); + if ($uuid != null) { + $node = $mdlCP->getNodeByReference('cpus.cpu.'.$uuid); + if ($node != null) { + $node->setNodes($this->request->getPost("cpu")); + return $this->save($mdlCP, $node, "cpu"); + } + } + } + return array("result"=>"failed"); + } + + /** + * add new cpu and set with attributes from post + * @return array + */ + public function addCpuAction() + { + $result = array("result"=>"failed"); + if ($this->request->isPost() && $this->request->hasPost("cpu")) { + $mdlCP = new HAProxy(); + $node = $mdlCP->cpus->cpu->Add(); + $node->setNodes($this->request->getPost("cpu")); + return $this->save($mdlCP, $node, "cpu"); + } + return $result; + } + + /** + * delete cpu by uuid + * @param $uuid item unique id + * @return array status + */ + public function delCpuAction($uuid) + { + $result = array("result"=>"failed"); + if ($this->request->isPost()) { + $mdlCP = new HAProxy(); + if ($uuid != null) { + if ($mdlCP->cpus->cpu->del($uuid)) { + // if item is removed, serialize to config and save + $mdlCP->serializeToConfig(); + Config::getInstance()->save(); + $result['result'] = 'deleted'; + } else { + $result['result'] = 'not found'; + } + } + } + return $result; + } + + /** + * toggle cpu by uuid (enable/disable) + * @param $uuid item unique id + * @param $enabled desired state enabled(1)/disabled(0), leave empty for toggle + * @return array status + */ + public function toggleCpuAction($uuid, $enabled = null) + { + + $result = array("result" => "failed"); + if ($this->request->isPost()) { + $mdlCP = new HAProxy(); + if ($uuid != null) { + $node = $mdlCP->getNodeByReference('cpus.cpu.' . $uuid); + if ($node != null) { + if ($enabled == "0" || $enabled == "1") { + $node->enabled = (string)$enabled; + } elseif ((string)$node->enabled == "1") { + $node->enabled = "0"; + } else { + $node->enabled = "1"; + } + $result['result'] = $node->enabled; + // if item has toggled, serialize to config and save + $mdlCP->serializeToConfig(); + Config::getInstance()->save(); + } + } + } + return $result; + } + + /** + * search cpus + * @return array + */ + public function searchCpusAction() + { + $this->sessionClose(); + $mdlCP = new HAProxy(); + $grid = new UIModelGrid($mdlCP->cpus->cpu); + return $grid->fetchBindRequest( + $this->request, + array("enabled", "name", "process_id", "thread_id", "cpu_id"), + "name" + ); + } + /** * retrieve group settings or return defaults * @param $uuid item unique id diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/IndexController.php b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/IndexController.php index 604f1d4c7..020301521 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/IndexController.php +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/IndexController.php @@ -56,6 +56,7 @@ class IndexController extends \OPNsense\Base\IndexController $this->view->formDialogLua = $this->getForm("dialogLua"); $this->view->formDialogErrorfile = $this->getForm("dialogErrorfile"); $this->view->formDialogMapfile = $this->getForm("dialogMapfile"); + $this->view->formDialogCpu = $this->getForm("dialogCpu"); // set additional view parameters $mdlHAProxy = new \OPNsense\HAProxy\HAProxy(); $this->view->showIntro = (string)$mdlHAProxy->general->showIntro; diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogCpu.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogCpu.xml new file mode 100644 index 000000000..a1d97f46e --- /dev/null +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogCpu.xml @@ -0,0 +1,33 @@ +
+ + cpu.enabled + + checkbox + Enable this CPU affinity rule. + + + cpu.name + + text + Choose a name for this CPU affinity rule. + + + cpu.process_id + + dropdown + Process ID that should bind to a specific CPU set. Any process IDs above nbproc are ignored. + + + cpu.thread_id + + dropdown + Thread ID that should bind to a specific CPU set. Any thread IDs above nbthread are ignored. + + + cpu.cpu_id + + select_multiple + true + Bind the process/thread ID to this CPU. + +
diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogFrontend.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogFrontend.xml index 6372012b2..7e044a330 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogFrontend.xml +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogFrontend.xml @@ -217,6 +217,15 @@ true + + frontend.linkedCpuAffinityRules + + select_multiple + true + + Choose CPU affinity rules. + true + header diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/main.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/main.xml index 417f1e51b..48eb6193c 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/main.xml +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/main.xml @@ -97,6 +97,12 @@
NOTE: You may experience random issues in multi-process mode. For more information about the "nbproc" option please see the HAProxy Documentation.
]]>
true
+ + haproxy.general.tuning.nbthread + + text + + haproxy.general.tuning.maxConnections diff --git a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml index 6b135564a..de0c9093a 100644 --- a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml +++ b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml @@ -69,6 +69,13 @@ Please specify a value between 1 and 128. Y + + 1 + 1 + 1024 + Please specify a value between 1 and 1024. + N + Y ignore @@ -502,6 +509,18 @@ Should be a number between 1 and 8 characters, optionally followed by either "d", "h", "m", "s", "ms" or "us". N + + + + + Related CPU affinity rule not found + Y + N + 0 Y @@ -2085,5 +2104,236 @@ + + + + Y + + + 1 + Y + + + /^[^\t^,^;^\.^\[^\]^\{^\}]{1,255}$/u + Should be a string between 1 and 255 characters. + Y + + + Y + + All HAProxy processes + Processes with odd ID + Processes with even ID + Process 1 + Process 2 + Process 3 + Process 4 + Process 5 + Process 6 + Process 7 + Process 8 + Process 9 + Process 10 + Process 11 + Process 12 + Process 13 + Process 14 + Process 15 + Process 16 + Process 17 + Process 18 + Process 19 + Process 20 + Process 21 + Process 22 + Process 23 + Process 24 + Process 25 + Process 26 + Process 27 + Process 28 + Process 29 + Process 30 + Process 31 + Process 32 + Process 33 + Process 34 + Process 35 + Process 36 + Process 37 + Process 38 + Process 39 + Process 40 + Process 41 + Process 42 + Process 43 + Process 44 + Process 45 + Process 46 + Process 47 + Process 48 + Process 49 + Process 50 + Process 51 + Process 52 + Process 53 + Process 54 + Process 55 + Process 56 + Process 57 + Process 58 + Process 59 + Process 60 + Process 61 + Process 62 + Process 63 + + + + Y + + All HAProxy threads + Threads with odd ID + Threads with even ID + Thread 1 + Thread 2 + Thread 3 + Thread 4 + Thread 5 + Thread 6 + Thread 7 + Thread 8 + Thread 9 + Thread 10 + Thread 11 + Thread 12 + Thread 13 + Thread 14 + Thread 15 + Thread 16 + Thread 17 + Thread 18 + Thread 19 + Thread 20 + Thread 21 + Thread 22 + Thread 23 + Thread 24 + Thread 25 + Thread 26 + Thread 27 + Thread 28 + Thread 29 + Thread 30 + Thread 31 + Thread 32 + Thread 33 + Thread 34 + Thread 35 + Thread 36 + Thread 37 + Thread 38 + Thread 39 + Thread 40 + Thread 41 + Thread 42 + Thread 43 + Thread 44 + Thread 45 + Thread 46 + Thread 47 + Thread 48 + Thread 49 + Thread 50 + Thread 51 + Thread 52 + Thread 53 + Thread 54 + Thread 55 + Thread 56 + Thread 57 + Thread 58 + Thread 59 + Thread 60 + Thread 61 + Thread 62 + Thread 63 + + + + Y + Y + + All CPUs + CPUs with odd ID + CPUs with even ID + CPU 0 + CPU 1 + CPU 2 + CPU 3 + CPU 4 + CPU 5 + CPU 6 + CPU 7 + CPU 8 + CPU 9 + CPU 10 + CPU 11 + CPU 12 + CPU 13 + CPU 14 + CPU 15 + CPU 16 + CPU 17 + CPU 18 + CPU 19 + CPU 20 + CPU 21 + CPU 22 + CPU 23 + CPU 24 + CPU 25 + CPU 26 + CPU 27 + CPU 28 + CPU 29 + CPU 30 + CPU 31 + CPU 32 + CPU 33 + CPU 34 + CPU 35 + CPU 36 + CPU 37 + CPU 38 + CPU 39 + CPU 40 + CPU 41 + CPU 42 + CPU 43 + CPU 44 + CPU 45 + CPU 46 + CPU 47 + CPU 48 + CPU 49 + CPU 50 + CPU 51 + CPU 52 + CPU 53 + CPU 54 + CPU 55 + CPU 56 + CPU 57 + CPU 58 + CPU 59 + CPU 60 + CPU 61 + CPU 62 + CPU 63 + + + + diff --git a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt index f97a8f6ae..52a9c842a 100644 --- a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt +++ b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt @@ -184,6 +184,19 @@ POSSIBILITY OF SUCH DAMAGE. } ); + $("#grid-cpus").UIBootgrid( + { search:'/api/haproxy/settings/searchCpus', + get:'/api/haproxy/settings/getCpu/', + set:'/api/haproxy/settings/setCpu/', + add:'/api/haproxy/settings/addCpu/', + del:'/api/haproxy/settings/delCpu/', + toggle:'/api/haproxy/settings/toggleCpu/', + options: { + rowCount:[10,25,50,100,500,1000] + } + } + ); + // hook into on-show event for dialog to extend layout. $('#DialogAcl').on('shown.bs.modal', function (e) { $("#acl\\.expression").change(function(){ @@ -516,6 +529,7 @@ POSSIBILITY OF SUCH DAMAGE.
  • {{ lang._('Error Messages') }}
  • {{ lang._('Lua Scripts') }}
  • {{ lang._('Map Files') }}
  • +
  • {{ lang._('CPU Affinity Rules') }}
  • @@ -603,8 +617,9 @@ POSSIBILITY OF SUCH DAMAGE.
  • {{ lang._("%sError Messages:%s Return a custom message instead of errors generated by HAProxy. Useful to overwrite HAProxy's internal error messages. The message must represent the full HTTP response and include required HTTP headers.") | format('', '') }}
  • {{ lang._("%sLua scripts:%s Include your own Lua code/scripts to extend HAProxy's functionality. The Lua code can be used in certain %sRules%s, for example.") | format('', '', '', '') }}
  • {{ lang._("%sMap Files:%s A map allows to map a data in input to an other one on output. For example, this makes it possible to map a large number of domains to backend pools without using the GUI. Map files need to be used in %sRules%s, otherwise they are ignored.") | format('', '', '', '') }}
  • +
  • {{ lang._("%sCPU Affinity Rules:%s This feature makes it possible to bind HAProxy's processes/threads to a specific CPU (or a CPU set). Furthermore it is possible to select CPU Affinity Rules in %sPublic Services%s to restrict them to a certain set of processes/threads/CPUs.") | format('', '', '', '') }}
  • -

    {{ lang._("For more details visit HAProxy's official documentation regarding the %sError Messages%s, %sLua Script%s and the %sMap Files%s features.") | format('', '', '', '', '', '') }}

    +

    {{ lang._("For more details visit HAProxy's official documentation regarding the %sError Messages%s, %sLua Script%s and the %sMap Files%s features. More information on HAProxy's CPU Affinity is also available %shere%s, %shere%s and %shere%s.") | format('', '', '', '', '', '' ,'', '' ,'', '' ,'', '') }}


    @@ -1006,6 +1021,43 @@ POSSIBILITY OF SUCH DAMAGE.
    + +
    + + + + + + + + + + + + + + + + + + + + + + +
    {{ lang._('CPU Rule ID') }}{{ lang._('Enabled') }}{{ lang._('Name') }}{{ lang._('Process ID') }}{{ lang._('Thread ID') }}{{ lang._('CPU ID') }}{{ lang._('Commands') }}{{ lang._('ID') }}
    + + +
    + +
    +
    + + +
    +
    +
    +
    {# include dialogs #} @@ -1020,3 +1072,4 @@ POSSIBILITY OF SUCH DAMAGE. {{ partial("layout_partials/base_dialog",['fields':formDialogLua,'id':'DialogLua','label':lang._('Edit Lua Script')])}} {{ partial("layout_partials/base_dialog",['fields':formDialogErrorfile,'id':'DialogErrorfile','label':lang._('Edit Error Message')])}} {{ partial("layout_partials/base_dialog",['fields':formDialogMapfile,'id':'DialogMapfile','label':lang._('Edit Map File')])}} +{{ partial("layout_partials/base_dialog",['fields':formDialogCpu,'id':'DialogCpu','label':lang._('Edit CPU Affinity Rule')])}} diff --git a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf index 398e9561b..7029e93cd 100644 --- a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf +++ b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf @@ -758,6 +758,16 @@ global stats socket /var/run/haproxy.socket level admin {% endif %} nbproc {{OPNsense.HAProxy.general.tuning.nbproc}} +{% if OPNsense.HAProxy.general.tuning.nbthread|default('') != '' %} + nbthread {{OPNsense.HAProxy.general.tuning.nbthread}} +{% endif %} +{% if helpers.exists('OPNsense.HAProxy.cpus.cpu') %} +{% for cpu_map in helpers.toList('OPNsense.HAProxy.cpus.cpu') %} +{% if cpu_map.enabled == '1' %} + cpu-map {{cpu_map.process_id|replace('x', '')}}/{{cpu_map.thread_id|replace('x', '')}} {{cpu_map.cpu_id|replace('x', '')|replace(',', ' ')}} +{% endif %} +{% endfor %} +{% endif %} {% if helpers.exists('OPNsense.HAProxy.general.tuning.maxConnections') %} maxconn {{OPNsense.HAProxy.general.tuning.maxConnections}} {% endif %} @@ -969,10 +979,27 @@ frontend {{frontend.name}} {% endif %} {% endif %} {% endif %} +{# # CPU affinity configuration #} +{% set bind_process = [] %} +{% set process_thread = [] %} +{% if frontend.linkedCpuAffinityRules|default('') != '' %} +{% for cpu_map in frontend.linkedCpuAffinityRules.split(',') %} +{% set cpu_map_data = helpers.getUUID(cpu_map) %} +{% if cpu_map_data.enabled == '1' %} +{# # Limit visibility to a certain set of processes #} +{% do bind_process.append(cpu_map_data.process_id|replace('x', '')) %} +{# # Restrict the list of processes/threads on which this listener is allowed to run #} +{% do process_thread.append('process ' ~ cpu_map_data.process_id|replace('x', '') ~ '/' ~ cpu_map_data.thread_id|replace('x', '')) %} +{% endif %} +{% endfor %} +{% if bind_process|length > 0 %} + bind-process {{bind_process|join(' ')}} +{% endif %} +{% endif %} {# # bind/listen configuration #} {% if frontend.bind|default("") != "" %} {% for bind in frontend.bind.split(",") %} - bind {{bind}} name {{bind}} {% if frontend.bindOptions|default("") != "" %}{{ frontend.bindOptions }} {% endif %}{% if frontend.ssl_enabled == '1' and ssl_certs|default("") != "" %}ssl {{ ssl_options|join(' ') }} {{ ssl_certs|join(' ') }} {% endif %} + bind {{bind}} name {{bind}} {% if frontend.bindOptions|default("") != "" %}{{ frontend.bindOptions }} {% endif %}{% if frontend.ssl_enabled == '1' and ssl_certs|default("") != "" %}ssl {{ ssl_options|join(' ') }} {{ ssl_certs|join(' ') }} {% endif %}{% if process_thread|length > 0 %} {{ process_thread|join(' ') }} {% endif %} {% endfor %} {% endif %}