bind 9.16.8 does not honor CPU affinity
Summary
bind 9.16.8 does not honor CPU affinity mask on linux.
We are running a dpdk application that works as an firewall/ddos protection protecting named. To run dpdk we need to reserve a couple of dedicated CPUs for dpdk threads. These threads must run on same CPU socket as PCI-bus/NIC card, so they must run on the first CPU socket. No other threads must use these CPUs that is dedicated to this dpdk application.
On linux the command taskset is used to set the CPU affinity mask for a process. Or one can use kernel boot parameter isolcpus to set system CPU affinity.
The problem is that named ignores the existing affinity mask and blindly binds the threads for isc-{net,worker,socket}-{nr} to process number {nr}.
BIND version used
BIND 9.16.8
Steps to reproduce
# taskset fff0 ./bin/named/named -f -c /etc/named/named.conf -u named -U 6 -n 10
# ps -T -o pid,psr,time,comm -e | egrep 'isc-net-0000'
32374 0 00:00:00 isc-net-0000
The taskset command signals to named that it can select all cpus but not cpu 0,1,2,3
What is the current bug behavior?
What is the expected correct behavior?
Select next available CPU relative to the existing affinity mask. For the process above I would have expected the first thread to bind to CPU 4.
# ps -T -o pid,psr,time,comm -e | egrep 'isc-net-0000'
32374 4 00:00:00 isc-net-0000
Possible fixes
The following code fetches the existing affinity mask and use it to select next available CPU.
# cat ../telenor-patches/telenor-honor-affinity.patch
diff -r -c ../bind-9.16.8-orig/lib/isc/pthreads/thread.c lib/isc/pthreads/thread.c
*** ../bind-9.16.8-orig/lib/isc/pthreads/thread.c 2020-10-13 10:41:40.000000000 +0200
--- lib/isc/pthreads/thread.c 2020-10-30 12:24:26.627360658 +0100
***************
*** 155,162 ****
cpuset_destroy(cset);
#else /* linux? */
cpu_set_t set;
CPU_ZERO(&set);
! CPU_SET(cpu, &set);
if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &set) !=
0) {
return (ISC_R_FAILURE);
--- 155,174 ----
cpuset_destroy(cset);
#else /* linux? */
cpu_set_t set;
+ if (pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &set) !=
+ 0) {
+ return (ISC_R_FAILURE);
+ }
+ int cpu_id = -1, cpu_aff_ok_counter = -1;
+ while (cpu_aff_ok_counter < cpu) {
+ cpu_id++;
+ if (CPU_ISSET(cpu_id, &set)) /* true if process affinity allows using cpu */
+ cpu_aff_ok_counter++;
+ if (cpu_id > 10000)
+ return (ISC_R_FAILURE);
+ }
CPU_ZERO(&set);
! CPU_SET(cpu_id, &set);
if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &set) !=
0) {
return (ISC_R_FAILURE);