mirror of
https://github.com/haproxy/haproxy.git
synced 2026-03-29 05:43:58 -04:00
Compare commits
No commits in common. "master" and "v3.4-dev4" have entirely different histories.
232 changed files with 4911 additions and 13459 deletions
38
.github/matrix.py
vendored
38
.github/matrix.py
vendored
|
|
@ -19,10 +19,9 @@ from packaging import version
|
|||
#
|
||||
# this CI is used for both development and stable branches of HAProxy
|
||||
#
|
||||
# naming convention used, if branch/tag name matches:
|
||||
# naming convention used, if branch name matches:
|
||||
#
|
||||
# "haproxy-" - stable branches
|
||||
# "vX.Y.Z" - release tags
|
||||
# otherwise - development branch (i.e. "latest" ssl variants, "latest" github images)
|
||||
#
|
||||
|
||||
|
|
@ -121,13 +120,11 @@ def clean_compression(compression):
|
|||
def main(ref_name):
|
||||
print("Generating matrix for branch '{}'.".format(ref_name))
|
||||
|
||||
is_stable = "haproxy-" in ref_name or re.match(r'^v\d+\.\d+\.\d+$', ref_name)
|
||||
|
||||
matrix = []
|
||||
|
||||
# Ubuntu
|
||||
|
||||
if is_stable:
|
||||
if "haproxy-" in ref_name:
|
||||
os = "ubuntu-24.04" # stable branch
|
||||
os_arm = "ubuntu-24.04-arm" # stable branch
|
||||
else:
|
||||
|
|
@ -231,7 +228,7 @@ def main(ref_name):
|
|||
# "BORINGSSL=yes",
|
||||
]
|
||||
|
||||
if not is_stable: # development branch
|
||||
if "haproxy-" not in ref_name: # development branch
|
||||
ssl_versions = ssl_versions + [
|
||||
"OPENSSL_VERSION=latest",
|
||||
"LIBRESSL_VERSION=latest",
|
||||
|
|
@ -278,21 +275,24 @@ def main(ref_name):
|
|||
}
|
||||
)
|
||||
|
||||
# macOS on dev branches
|
||||
if not is_stable:
|
||||
# macOS
|
||||
|
||||
if "haproxy-" in ref_name:
|
||||
os = "macos-13" # stable branch
|
||||
else:
|
||||
os = "macos-26" # development branch
|
||||
|
||||
TARGET = "osx"
|
||||
for CC in ["clang"]:
|
||||
matrix.append(
|
||||
{
|
||||
"name": "{}, {}, no features".format(os, CC),
|
||||
"os": os,
|
||||
"TARGET": TARGET,
|
||||
"CC": CC,
|
||||
"FLAGS": [],
|
||||
}
|
||||
)
|
||||
TARGET = "osx"
|
||||
for CC in ["clang"]:
|
||||
matrix.append(
|
||||
{
|
||||
"name": "{}, {}, no features".format(os, CC),
|
||||
"os": os,
|
||||
"TARGET": TARGET,
|
||||
"CC": CC,
|
||||
"FLAGS": [],
|
||||
}
|
||||
)
|
||||
|
||||
# Print matrix
|
||||
|
||||
|
|
|
|||
3
.github/workflows/contrib.yml
vendored
3
.github/workflows/contrib.yml
vendored
|
|
@ -11,6 +11,9 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Compile admin/halog/halog
|
||||
run: |
|
||||
make admin/halog/halog
|
||||
- name: Compile dev/flags/flags
|
||||
run: |
|
||||
make dev/flags/flags
|
||||
|
|
|
|||
73
.github/workflows/quic-interop-aws-lc.yml
vendored
73
.github/workflows/quic-interop-aws-lc.yml
vendored
|
|
@ -11,7 +11,7 @@ on:
|
|||
|
||||
|
||||
jobs:
|
||||
combined-build-and-run:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
if: ${{ github.repository_owner == 'haproxy' || github.event_name == 'workflow_dispatch' }}
|
||||
permissions:
|
||||
|
|
@ -21,47 +21,84 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Update Docker to the latest
|
||||
uses: docker/setup-docker-action@v4
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build Docker image
|
||||
- name: Build and push Docker image
|
||||
id: push
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: https://github.com/haproxytech/haproxy-qns.git
|
||||
platforms: linux/amd64
|
||||
push: true
|
||||
build-args: |
|
||||
SSLLIB=AWS-LC
|
||||
tags: local:aws-lc
|
||||
tags: ghcr.io/${{ github.repository }}:aws-lc
|
||||
|
||||
- name: Cleanup registry
|
||||
uses: actions/delete-package-versions@v5
|
||||
with:
|
||||
owner: ${{ github.repository_owner }}
|
||||
package-name: 'haproxy'
|
||||
package-type: container
|
||||
min-versions-to-keep: 1
|
||||
delete-only-untagged-versions: 'true'
|
||||
|
||||
run:
|
||||
needs: build
|
||||
strategy:
|
||||
matrix:
|
||||
suite: [
|
||||
{ client: chrome, tests: "http3" },
|
||||
{ client: picoquic, tests: "handshake,transfer,longrtt,chacha20,multiplexing,retry,resumption,zerortt,http3,blackhole,keyupdate,ecn,amplificationlimit,handshakeloss,transferloss,handshakecorruption,transfercorruption,ipv6,v2" },
|
||||
{ client: quic-go, tests: "handshake,transfer,longrtt,chacha20,multiplexing,retry,resumption,zerortt,http3,blackhole,keyupdate,ecn,amplificationlimit,handshakeloss,transferloss,handshakecorruption,transfercorruption,ipv6,v2" },
|
||||
{ client: ngtcp2, tests: "handshake,transfer,longrtt,chacha20,multiplexing,retry,resumption,zerortt,http3,blackhole,keyupdate,ecn,amplificationlimit,handshakeloss,transferloss,handshakecorruption,transfercorruption,ipv6,v2" }
|
||||
]
|
||||
fail-fast: false
|
||||
|
||||
name: ${{ matrix.suite.client }}
|
||||
runs-on: ubuntu-24.04
|
||||
if: ${{ github.repository_owner == 'haproxy' || github.event_name == 'workflow_dispatch' }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install tshark
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install tshark
|
||||
|
||||
- name: Pull image
|
||||
run: |
|
||||
docker pull ghcr.io/${{ github.repository }}:aws-lc
|
||||
|
||||
- name: Run
|
||||
run: |
|
||||
git clone https://github.com/quic-interop/quic-interop-runner
|
||||
cd quic-interop-runner
|
||||
pip install -r requirements.txt --break-system-packages
|
||||
python run.py -j result.json -l logs-chrome -r haproxy=local:aws-lc -t "http3" -c chrome -s haproxy
|
||||
python run.py -j result.json -l logs-picoquic -r haproxy=local:aws-lc -t "handshake,transfer,longrtt,chacha20,multiplexing,retry,resumption,zerortt,http3,blackhole,keyupdate,ecn,amplificationlimit,handshakeloss,transferloss,handshakecorruption,transfercorruption,ipv6,v2" -c picoquic -s haproxy
|
||||
python run.py -j result.json -l logs-quic-go -r haproxy=local:aws-lc -t "handshake,transfer,longrtt,chacha20,multiplexing,retry,resumption,zerortt,http3,blackhole,keyupdate,ecn,amplificationlimit,handshakeloss,transferloss,handshakecorruption,transfercorruption,ipv6,v2" -c quic-go -s haproxy
|
||||
python run.py -j result.json -l logs-ngtcp2 -r haproxy=local:aws-lc -t "handshake,transfer,longrtt,chacha20,multiplexing,retry,resumption,zerortt,http3,blackhole,keyupdate,ecn,amplificationlimit,handshakeloss,transferloss,handshakecorruption,transfercorruption,ipv6,v2" -c ngtcp2 -s haproxy
|
||||
python run.py -j result.json -l logs -r haproxy=ghcr.io/${{ github.repository }}:aws-lc -t ${{ matrix.suite.tests }} -c ${{ matrix.suite.client }} -s haproxy
|
||||
|
||||
- name: Delete succeeded logs
|
||||
if: failure()
|
||||
run: |
|
||||
for client in chrome picoquic quic-go ngtcp2; do
|
||||
pushd quic-interop-runner/logs-${client}/haproxy_${client}
|
||||
cat ../../result.json | jq -r '.results[][] | select(.result=="succeeded") | .name' | xargs rm -rf
|
||||
popd
|
||||
done
|
||||
cd quic-interop-runner/logs/haproxy_${{ matrix.suite.client }}
|
||||
cat ../../result.json | jq -r '.results[][] | select(.result=="succeeded") | .name' | xargs rm -rf
|
||||
|
||||
- name: Logs upload
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: logs
|
||||
path: quic-interop-runner/logs*/
|
||||
name: logs-${{ matrix.suite.client }}
|
||||
path: quic-interop-runner/logs/
|
||||
retention-days: 6
|
||||
|
|
|
|||
69
.github/workflows/quic-interop-libressl.yml
vendored
69
.github/workflows/quic-interop-libressl.yml
vendored
|
|
@ -11,7 +11,7 @@ on:
|
|||
|
||||
|
||||
jobs:
|
||||
combined-build-and-run:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
if: ${{ github.repository_owner == 'haproxy' || github.event_name == 'workflow_dispatch' }}
|
||||
permissions:
|
||||
|
|
@ -21,45 +21,82 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Update Docker to the latest
|
||||
uses: docker/setup-docker-action@v4
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build Docker image
|
||||
- name: Build and push Docker image
|
||||
id: push
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: https://github.com/haproxytech/haproxy-qns.git
|
||||
platforms: linux/amd64
|
||||
push: true
|
||||
build-args: |
|
||||
SSLLIB=LibreSSL
|
||||
tags: local:libressl
|
||||
tags: ghcr.io/${{ github.repository }}:libressl
|
||||
|
||||
- name: Cleanup registry
|
||||
uses: actions/delete-package-versions@v5
|
||||
with:
|
||||
owner: ${{ github.repository_owner }}
|
||||
package-name: 'haproxy'
|
||||
package-type: container
|
||||
min-versions-to-keep: 1
|
||||
delete-only-untagged-versions: 'true'
|
||||
|
||||
run:
|
||||
needs: build
|
||||
strategy:
|
||||
matrix:
|
||||
suite: [
|
||||
{ client: picoquic, tests: "handshake,transfer,longrtt,chacha20,multiplexing,retry,http3,blackhole,amplificationlimit,handshakeloss,transferloss,handshakecorruption,transfercorruption,v2" },
|
||||
{ client: quic-go, tests: "handshake,transfer,longrtt,chacha20,multiplexing,retry,http3,blackhole,amplificationlimit,transferloss,transfercorruption,v2" }
|
||||
]
|
||||
fail-fast: false
|
||||
|
||||
name: ${{ matrix.suite.client }}
|
||||
runs-on: ubuntu-24.04
|
||||
if: ${{ github.repository_owner == 'haproxy' || github.event_name == 'workflow_dispatch' }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install tshark
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install tshark
|
||||
|
||||
- name: Pull image
|
||||
run: |
|
||||
docker pull ghcr.io/${{ github.repository }}:libressl
|
||||
|
||||
- name: Run
|
||||
run: |
|
||||
git clone https://github.com/quic-interop/quic-interop-runner
|
||||
cd quic-interop-runner
|
||||
pip install -r requirements.txt --break-system-packages
|
||||
python run.py -j result.json -l logs-picoquic -r haproxy=local:libressl -t "handshake,transfer,longrtt,chacha20,multiplexing,retry,http3,blackhole,amplificationlimit,handshakeloss,transferloss,handshakecorruption,transfercorruption,v2" -c picoquic -s haproxy
|
||||
python run.py -j result.json -l logs-quic-go -r haproxy=local:libressl -t "handshake,transfer,longrtt,chacha20,multiplexing,retry,http3,blackhole,amplificationlimit,transferloss,transfercorruption,v2" -c quic-go -s haproxy
|
||||
python run.py -j result.json -l logs -r haproxy=ghcr.io/${{ github.repository }}:libressl -t ${{ matrix.suite.tests }} -c ${{ matrix.suite.client }} -s haproxy
|
||||
|
||||
- name: Delete succeeded logs
|
||||
if: failure()
|
||||
run: |
|
||||
for client in picoquic quic-go; do
|
||||
pushd quic-interop-runner/logs-${client}/haproxy_${client}
|
||||
cat ../../result.json | jq -r '.results[][] | select(.result=="succeeded") | .name' | xargs rm -rf
|
||||
popd
|
||||
done
|
||||
cd quic-interop-runner/logs/haproxy_${{ matrix.suite.client }}
|
||||
cat ../../result.json | jq -r '.results[][] | select(.result=="succeeded") | .name' | xargs rm -rf
|
||||
|
||||
- name: Logs upload
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: logs
|
||||
path: quic-interop-runner/logs*/
|
||||
name: logs-${{ matrix.suite.client }}
|
||||
path: quic-interop-runner/logs/
|
||||
retention-days: 6
|
||||
|
|
|
|||
1
.github/workflows/windows.yml
vendored
1
.github/workflows/windows.yml
vendored
|
|
@ -18,7 +18,6 @@ jobs:
|
|||
msys2:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
if: ${{ github.repository_owner == 'haproxy' || github.event_name == 'workflow_dispatch' }}
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
|
|
|
|||
380
CHANGELOG
380
CHANGELOG
|
|
@ -1,386 +1,6 @@
|
|||
ChangeLog :
|
||||
===========
|
||||
|
||||
2026/03/20 : 3.4-dev7
|
||||
- BUG/MINOR: stconn: Increase SC bytes_out value in se_done_ff()
|
||||
- BUG/MINOR: ssl-sample: Fix sample_conv_sha2() by checking EVP_Digest* failures
|
||||
- BUG/MINOR: backend: Don't get proto to use for webscoket if there is no server
|
||||
- BUG/MINOR: jwt: Missing 'jwt_tokenize' return value check
|
||||
- MINOR: flt_http_comp: define and use proxy_get_comp() helper function
|
||||
- MEDIUM: flt_http_comp: split "compression" filter in 2 distinct filters
|
||||
- CLEANUP: flt_http_comp: comp_state doesn't bother about the direction anymore
|
||||
- BUG/MINOR: admin: haproxy-reload use explicit socat address type
|
||||
- MEDIUM: admin: haproxy-reload conversion to POSIX sh
|
||||
- BUG/MINOR: admin: haproxy-reload rename -vv long option
|
||||
- SCRIPTS: git-show-backports: hide the common ancestor warning in quiet mode
|
||||
- SCRIPTS: git-show-backports: add a restart-from-last option
|
||||
- MINOR: mworker: add a BUG_ON() on mproxy_li in _send_status
|
||||
- BUG/MINOR: mworker: don't set the PROC_O_LEAVING flag on master process
|
||||
- Revert "BUG/MINOR: jwt: Missing 'jwt_tokenize' return value check"
|
||||
- MINOR: jwt: Improve 'jwt_tokenize' function
|
||||
- MINOR: jwt: Convert EC JWK to EVP_PKEY
|
||||
- MINOR: jwt: Parse ec-specific fields in jose header
|
||||
- MINOR: jwt: Manage ECDH-ES algorithm in jwt_decrypt_jwk function
|
||||
- MINOR: jwt: Add ecdh-es+axxxkw support in jwt_decrypt_jwk converter
|
||||
- MINOR: jwt: Manage ec certificates in jwt_decrypt_cert
|
||||
- DOC: jwt: Add ECDH support in jwt_decrypt converters
|
||||
- MINOR: stconn: Call sc_conn_process from the I/O callback if TASK_WOKEN_MSG state was set
|
||||
- MINOR: mux-h2: Rely on h2s_notify_send() when resuming h2s for sending
|
||||
- MINOR: mux-spop: Rely on spop_strm_notify_send() when resuming streams for sending
|
||||
- MINOR: muxes: Wakup the data layer from a mux stream with TASK_WOKEN_IO state
|
||||
- MAJOR: muxes: No longer use app_ops .wake() callback function from muxes
|
||||
- MINOR: applet: Call sc_applet_process() instead of .wake() callback function
|
||||
- MINOR: connection: Call sc_conn_process() instead of .wake() callback function
|
||||
- MEDIUM: stconn: Remove .wake() callback function from app_ops
|
||||
- MINOR: check: Remove wake_srv_chk() function
|
||||
- MINOR: haterm: Remove hstream_wake() function
|
||||
- MINOR: stconn: Wakup the SC with TASK_WOKEN_IO state from opposite side
|
||||
- MEDIUM: stconn: Merge all .chk_rcv() callback functions in sc_chk_rcv()
|
||||
- MINOR: stconn: Remove .chk_rcv() callback functions
|
||||
- MEDIUM: stconn: Merge all .chk_snd() callback functions in sc_chk_snd()
|
||||
- MINOR: stconn: Remove .chk_snd() callback functions
|
||||
- MEDIUM: stconn: Merge all .abort() callback functions in sc_abort()
|
||||
- MINOR: stconn: Remove .abort() callback functions
|
||||
- MEDIUM: stconn: Merge all .shutdown() callback functions in sc_shutdown()
|
||||
- MINOR: stconn: Remove .shutdown() callback functions
|
||||
- MINOR: stconn: Totally app_ops from the stconns
|
||||
- MINOR: stconn: Simplify sc_abort/sc_shutdown by merging calls to se_shutdown
|
||||
- DEBUG: stconn: Add a CHECK_IF() when I/O are performed on a orphan SC
|
||||
- MEDIUM: mworker: exiting when couldn't find the master mworker_proc element
|
||||
- BUILD: ssl: use ASN1_STRING accessors for OpenSSL 4.0 compatibility
|
||||
- BUILD: ssl: make X509_NAME usage OpenSSL 4.0 ready
|
||||
- BUG/MINOR: tcpcheck: Fix typo in error error message for `http-check expect`
|
||||
- BUG/MINOR: jws: fix memory leak in jws_b64_signature
|
||||
- DOC: configuration: http-check expect example typo
|
||||
- DOC/CLEANUP: config: update mentions of the old "Global parameters" section
|
||||
- BUG/MEDIUM: ssl: Handle receiving early data with BoringSSL/AWS-LC
|
||||
- BUG/MINOR: mworker: always stop the receiving listener
|
||||
- BUG/MEDIUM: ssl: Don't report read data as early data with AWS-LC
|
||||
- BUILD: makefile: fix range build without test command
|
||||
- BUG/MINOR: memprof: avoid a small memory leak in "show profiling"
|
||||
- BUG/MINOR: proxy: do not forget to validate quic-initial rules
|
||||
- MINOR: activity: use dynamic allocation for "show profiling" entries
|
||||
- MINOR: tools: extend the pointer hashing code to ease manipulations
|
||||
- MINOR: tools: add a new pointer hash function that also takes an argument
|
||||
- MINOR: memprof: attempt different retry slots for different hashes on collision
|
||||
- MINOR: tinfo: start to add basic thread_exec_ctx
|
||||
- MINOR: memprof: prepare to consider exec_ctx in reporting
|
||||
- MINOR: memprof: also permit to sort output by calling context
|
||||
- MINOR: tools: add a function to write a thread execution context.
|
||||
- MINOR: debug: report the execution context on thread dumps
|
||||
- MINOR: memprof: report the execution context on profiling output
|
||||
- MINOR: initcall: record the file and line declaration of an INITCALL
|
||||
- MINOR: tools: decode execution context TH_EX_CTX_INITCALL
|
||||
- MINOR: tools: support decoding ha_caller type exec context
|
||||
- MINOR: sample: store location for fetch/conv via initcalls
|
||||
- MINOR: sample: also report contexts registered directly
|
||||
- MINOR: tools: support an execution context that is just a function
|
||||
- MINOR: actions: store the location of keywords registered via initcalls
|
||||
- MINOR: actions: also report execution contexts registered directly
|
||||
- MINOR: filters: set the exec context to the current filter config
|
||||
- MINOR: ssl: set the thread execution context during message callbacks
|
||||
- MINOR: connection: track mux calls to report their allocation context
|
||||
- MINOR: task: set execution context on task/tasklet calls
|
||||
- MINOR: applet: set execution context on applet calls
|
||||
- MINOR: cli: keep the info of the current keyword being processed in the appctx
|
||||
- MINOR: cli: keep track of the initcall context since kw registration
|
||||
- MINOR: cli: implement execution context for manually registered keywords
|
||||
- MINOR: activity: support aggregating by caller also for memprofile
|
||||
- MINOR: activity: raise the default number of memprofile buckets to 4k
|
||||
- DOC: internals: short explanation on how thread_exec_ctx works
|
||||
- BUG/MINOR: mworker: only match worker processes when looking for unspawned proc
|
||||
- MINOR: traces: defer processing of "-dt" options
|
||||
- BUG/MINOR: mworker: fix typo &= instead of & in proc list serialization
|
||||
- BUG/MINOR: mworker: set a timeout on the worker socketpair read at startup
|
||||
- BUG/MINOR: mworker: avoid passing NULL version in proc list serialization
|
||||
- BUG/MINOR: sockpair: set FD_CLOEXEC on fd received via SCM_RIGHTS
|
||||
- BUG/MEDIUM: stconn: Don't forget to wakeup applets on shutdown
|
||||
- BUG/MINOR: spoe: Properly switch SPOE filter to WAITING_ACK state
|
||||
- BUG/MEDIUM: spoe: Properly abort processing on client abort
|
||||
- BUG/MEDIUM: stconn: Fix abort on close when a large buffer is used
|
||||
- BUG/MEDIUM: stconn: Don't perform L7 retries with large buffer
|
||||
- BUG/MINOR: h2/h3: Only test number of trailers inserted in HTX message
|
||||
- MINOR: htx: Add function to truncate all blocks after a specific block
|
||||
- BUG/MINOR: h2/h3: Never insert partial headers/trailers in an HTX message
|
||||
- BUG/MINOR: http-ana: Swap L7 buffer with request buffer by hand
|
||||
- BUG/MINOR: stream: Fix crash in stream dump if the current rule has no keyword
|
||||
- BUG/MINOR: mjson: make mystrtod() length-aware to prevent out-of-bounds reads
|
||||
- MEDIUM: stats-file/clock: automatically update now_offset based on shared clock
|
||||
- MINOR: promex: export "haproxy_sticktable_local_updates" metric
|
||||
- BUG/MINOR: spoe: Fix condition to abort processing on client abort
|
||||
- BUILD: spoe: Remove unsused variable
|
||||
- MINOR: tools: add a function to create a tar file header
|
||||
- MINOR: tools: add a function to load a file into a tar archive
|
||||
- MINOR: config: support explicit "on" and "off" for "set-dumpable"
|
||||
- MINOR: debug: read all libs in memory when set-dumpable=libs
|
||||
- DEV: gdb: add a new utility to extract libs from a core dump: libs-from-core
|
||||
- MINOR: debug: copy debug symbols from /usr/lib/debug when present
|
||||
- MINOR: debug: opportunistically load libthread_db.so.1 with set-dumpable=libs
|
||||
- BUG/MINOR: mworker: don't try to access an initializing process
|
||||
- BUG/MEDIUM: peers: enforce check on incoming table key type
|
||||
- BUG/MINOR: mux-h2: properly ignore R bit in GOAWAY stream ID
|
||||
- BUG/MINOR: mux-h2: properly ignore R bit in WINDOW_UPDATE increments
|
||||
- OPTIM: haterm: use chunk builders for generated response headers
|
||||
- BUG/MAJOR: h3: check body size with content-length on empty FIN
|
||||
- BUG/MEDIUM: h3: reject unaligned frames except DATA
|
||||
- BUG/MINOR: mworker/cli: fix show proc pagination losing entries on resume
|
||||
- CI: github: treat vX.Y.Z release tags as stable like haproxy-* branches
|
||||
- MINOR: freq_ctr: add a function to add values with a peak
|
||||
- MINOR: task: maintain a per-thread indicator of the peak run-queue size
|
||||
- MINOR: mux-h2: store the concurrent streams hard limit in the h2c
|
||||
- MINOR: mux-h2: permit to moderate the advertised streams limit depending on load
|
||||
- MINOR: mux-h2: permit to fix a minimum value for the advertised streams limit
|
||||
- BUG/MINOR: mworker: fix sort order of mworker_proc in 'show proc'
|
||||
- CLEANUP: mworker: fix tab/space mess in mworker_env_to_proc_list()
|
||||
|
||||
2026/03/05 : 3.4-dev6
|
||||
- CLEANUP: acme: remove duplicate includes
|
||||
- BUG/MINOR: proxy: detect strdup error on server auto SNI
|
||||
- BUG/MINOR: server: set auto SNI for dynamic servers
|
||||
- BUG/MINOR: server: enable no-check-sni-auto for dynamic servers
|
||||
- MINOR: haterm: provide -b and -c options (RSA key size, ECDSA curves)
|
||||
- MINOR: haterm: add long options for QUIC and TCP "bind" settings
|
||||
- BUG/MINOR: haterm: missing allocation check in copy_argv()
|
||||
- BUG/MINOR: quic: fix counters used on BE side
|
||||
- MINOR: quic: add BUG_ON() on half_open_conn counter access from BE
|
||||
- BUG/MINOR: quic/h3: display QUIC/H3 backend module on HTML stats
|
||||
- BUG/MINOR: acme: acme_ctx_destroy() leaks auth->dns
|
||||
- BUG/MINOR: acme: wrong labels logic always memprintf errmsg
|
||||
- MINOR: ssl: clarify error reporting for unsupported keywords
|
||||
- BUG/MINOR: acme: fix incorrect number of arguments allowed in config
|
||||
- CLEANUP: haterm: remove unreachable labels hstream_add_data()
|
||||
- CLEANUP: haterm: avoid static analyzer warnings about rand() use
|
||||
- CLEANUP: ssl: Remove a useless variable from ssl_gen_x509()
|
||||
- CI: use the latest docker for QUIC Interop
|
||||
- CI: remove redundant "halog" compilation
|
||||
- CLENAUP: cfgparse: accept-invalid-http-* does not support "no"/"defaults"
|
||||
- BUG/MEDIUM: spoe: Acquire context buffer in applet before consuming a frame
|
||||
- MINOR: traces: always mark trace_source as thread-aligned
|
||||
- MINOR: ncbmbuf: improve itbmap_next() code
|
||||
- MINOR: proxy: improve code when checking server name conflicts
|
||||
- MINOR: quic: add a new metric for ncbuf failures
|
||||
- BUG/MINOR: haterm: cannot reset default "haterm" mode
|
||||
- BUG/MEDIUM: cpu-topo: Distribute CPUs fairly across groups
|
||||
- BUG/MINOR: quic: missing app ops init during backend 0-RTT sessions
|
||||
- CLEANUP: ssl: remove outdated comments
|
||||
- MINOR: mux-h2: also count glitches on invalid trailers
|
||||
- MINOR: mux-h2: add a new setting, "tune.h2.log-errors" to tweak error logging
|
||||
- BUG/MEDIUM: mux-h2: make sure to always report pending errors to the stream
|
||||
- BUG/MINOR: server: adjust initialization order for dynamic servers
|
||||
- CLEANUP: tree-wide: drop a few useless null-checks before free()
|
||||
- CLEANUP: quic-stats: include counters from quic_stats
|
||||
- REORG: stats/counters: move extra_counters to counters not stats
|
||||
- CLEANUP: stats: drop stats.h / stats-t.h where not needed
|
||||
- MEDIUM: counters: change the fill_stats() API to pass the module and extra_counters
|
||||
- CLEANUP: counters: only retrieve zeroes for unallocated extra_counters
|
||||
- MEDIUM: counters: add a dedicated storage for extra_counters in various structs
|
||||
- MINOR: counters: store a tgroup step for extra_counters to access multiple tgroups
|
||||
- MEDIUM: counters: store the number of thread groups accessing extra_counters
|
||||
- MINOR: counters: add EXTRA_COUNTERS_BASE() to retrieve extra_counters base storage
|
||||
- MEDIUM: counters: return aggregate extra counters in ->fill_stats()
|
||||
- MEDIUM: counters: make EXTRA_COUNTERS_GET() consider tgid
|
||||
- BUG/MINOR: call EXTRA_COUNTERS_FREE() before srv_free_params() in srv_drop()
|
||||
- MINOR: promex: test applet resume in stress mode
|
||||
- BUG/MINOR: promex: fix server iteration when last server is deleted
|
||||
- BUG/MINOR: proxy: add dynamic backend into ID tree
|
||||
- MINOR: proxy: convert proxy flags to uint
|
||||
- MINOR: server: refactor srv_detach()
|
||||
- MINOR: proxy: define a basic "del backend" CLI
|
||||
- MINOR: proxy: define proxy watcher member
|
||||
- MINOR: stats: protect proxy iteration via watcher
|
||||
- MINOR: promex: use watcher to iterate over backend instances
|
||||
- MINOR: lua: use watcher for proxies iterator
|
||||
- MINOR: proxy: add refcount to proxies
|
||||
- MINOR: proxy: rename default refcount to avoid confusion
|
||||
- MINOR: server: take proxy refcount when deleting a server
|
||||
- MINOR: lua: handle proxy refcount
|
||||
- MINOR: proxy: prevent backend removal when unsupported
|
||||
- MINOR: proxy: prevent deletion of backend referenced by config elements
|
||||
- MINOR: proxy: prevent backend deletion if server still exists in it
|
||||
- MINOR: server: mark backend removal as forbidden if QUIC was used
|
||||
- MINOR: cli: implement wait on be-removable
|
||||
- MINOR: proxy: add comment for defaults_px_ref/unref_all()
|
||||
- MEDIUM: proxy: add lock for global accesses during proxy free
|
||||
- MEDIUM: proxy: add lock for global accesses during default free
|
||||
- MINOR: proxy: use atomic ops for default proxy refcount
|
||||
- MEDIUM: proxy: implement backend deletion
|
||||
- REGTESTS: add a test on "del backend"
|
||||
- REGTESTS: complete "del backend" with unnamed defaults ref free
|
||||
- BUG/MINOR: hlua: fix return with push nil on proxy check
|
||||
- BUG/MEDIUM: stream: Handle TASK_WOKEN_RES as a stream event
|
||||
- MINOR: quic: use signed char type for ALPN manipulation
|
||||
- MINOR: quic/h3: reorganize stream reject after MUX closure
|
||||
- MINOR: mux-quic: add function for ALPN to app-ops conversion
|
||||
- MEDIUM: quic/mux-quic: adjust app-ops install
|
||||
- MINOR: quic: use server cache for ALPN on BE side
|
||||
- BUG/MEDIUM: hpack: correctly deal with too large decoded numbers
|
||||
- BUG/MAJOR: qpack: unchecked length passed to huffman decoder
|
||||
- BUG/MINOR: qpack: fix 1-byte OOB read in qpack_decode_fs_pfx()
|
||||
- BUG/MINOR: quic: fix OOB read in preferred_address transport parameter
|
||||
- BUG/MEDIUM: qpack: correctly deal with too large decoded numbers
|
||||
- BUG/MINOR: hlua: Properly enable/disable line receives from HTTP applet
|
||||
- BUG/MEDIUM: hlua: Fix end of request detection when retrieving payload
|
||||
- BUG/MINOR: hlua: Properly enable/disable receives for TCP applets
|
||||
- MINOR: htx: Add a function to retrieve the HTTP version from a start-line
|
||||
- MINOR: h1-htx: Reports non-HTTP version via dedicated flags
|
||||
- BUG/MINOR: h1-htx: Be sure that H1 response version starts by "HTTP/"
|
||||
- MINOR: http-ana: Save the message version in the http_msg structure
|
||||
- MEDIUM: http-fetch: Rework how HTTP message version is retrieved
|
||||
- MEDIUM: http-ana: Use the version of the opposite side for internal messages
|
||||
- DEBUG: stream: Display the currently running rule in stream dump
|
||||
- MINOR: filters: Use filter API as far as poissible to break loops on filters
|
||||
- MINOR: filters: Set last_entity when a filter fails on stream_start callback
|
||||
- MINOR: stream: Display the currently running filter per channel in stream dump
|
||||
- DOC: config: Use the right alias for %B
|
||||
- BUG/MINOR: channel: Increase the stconn bytes_in value in channel_add_input()
|
||||
- BUG/MINOR: sample: Fix sample to retrieve the number of bytes received and sent
|
||||
- BUG/MINOR: http-ana: Increment scf bytes_out value if an haproxy error is sent
|
||||
- BUG/MAJOR: fcgi: Fix param decoding by properly checking its size
|
||||
- BUG/MAJOR: resolvers: Properly lowered the names found in DNS response
|
||||
- BUG/MEDIUM: mux-fcgi: Use a safe loop to resume each stream eligible for sending
|
||||
- MINOR: mux-fcgi: Use a dedicated function to resume streams eligible for sending
|
||||
- CLEANUP: qpack: simplify length checks in qpack_decode_fs()
|
||||
- MINOR: counters: Introduce COUNTERS_UPDATE_MAX()
|
||||
- MINOR: listeners: Update the frequency counters separately when needed
|
||||
- MINOR: proxies: Update beconn separately
|
||||
- MINOR: stats: Add an option to disable the calculation of max counters
|
||||
|
||||
2026/02/19 : 3.4-dev5
|
||||
- DOC: internals: addd mworker V3 internals
|
||||
- BUG/MINOR: threads: Initialize maxthrpertgroup earlier.
|
||||
- BUG/MEDIUM: threads: Differ checking the max threads per group number
|
||||
- BUG/MINOR: startup: fix allocation error message of progname string
|
||||
- BUG/MINOR: startup: handle a possible strdup() failure
|
||||
- MINOR: cfgparse: validate defaults proxies separately
|
||||
- MINOR: cfgparse: move proxy post-init in a dedicated function
|
||||
- MINOR: proxy: refactor proxy inheritance of a defaults section
|
||||
- MINOR: proxy: refactor mode parsing
|
||||
- MINOR: backend: add function to check support for dynamic servers
|
||||
- MINOR: proxy: define "add backend" handler
|
||||
- MINOR: proxy: parse mode on dynamic backend creation
|
||||
- MINOR: proxy: parse guid on dynamic backend creation
|
||||
- MINOR: proxy: check default proxy compatibility on "add backend"
|
||||
- MEDIUM: proxy: implement dynamic backend creation
|
||||
- MINOR: proxy: assign dynamic proxy ID
|
||||
- REGTESTS: add dynamic backend creation test
|
||||
- BUG/MINOR: proxy: fix clang build error on "add backend" handler
|
||||
- BUG/MINOR: proxy: fix null dereference in "add backend" handler
|
||||
- MINOR: net_helper: extend the ip.fp output with an option presence mask
|
||||
- BUG/MINOR: proxy: fix default ALPN bind settings
|
||||
- CLEANUP: lb-chash: free lb_nodes from chash's deinit(), not global
|
||||
- BUG/MEDIUM: lb-chash: always properly initialize lb_nodes with dynamic servers
|
||||
- CLEANUP: haproxy: fix bad line wrapping in run_poll_loop()
|
||||
- MINOR: activity: support setting/clearing lock/memory watching for task profiling
|
||||
- MEDIUM: activity: apply and use new finegrained task profiling settings
|
||||
- MINOR: activity: allow to switch per-task lock/memory profiling at runtime
|
||||
- MINOR: startup: Add the SSL lib verify directory in haproxy -vv
|
||||
- BUG/MINOR: ssl: SSL_CERT_DIR environment variable doesn't affect haproxy
|
||||
- CLEANUP: initcall: adjust comments to INITCALL{0,1} macros
|
||||
- DOC: proxy-proto: underline the packed attribute for struct pp2_tlv_ssl
|
||||
- MINOR: queues: Check minconn first in srv_dynamic_maxconn()
|
||||
- MINOR: servers: Call process_srv_queue() without lock when possible
|
||||
- BUG/MINOR: quic: ensure handshake speed up is only run once per conn
|
||||
- BUG/MAJOR: quic: reject invalid token
|
||||
- BUG/MAJOR: quic: fix parsing frame type
|
||||
- MINOR: ssl: Missing '\n' in error message
|
||||
- MINOR: jwt: Convert an RSA JWK into an EVP_PKEY
|
||||
- MINOR: jwt: Add new jwt_decrypt_jwk converter
|
||||
- REGTESTS: jwt: Add new "jwt_decrypt_jwk" tests
|
||||
- MINOR: startup: Add HAVE_WORKING_TCP_MD5SIG in haproxy -vv
|
||||
- MINOR: startup: sort the feature list in haproxy -vv
|
||||
- MINOR: startup: show the list of detected features at runtime with haproxy -vv
|
||||
- SCRIPTS: build-vtest: allow to set a TMPDIR and a DESTDIR
|
||||
- MINOR: filters: rework RESUME_FILTER_* macros as inline functions
|
||||
- MINOR: filters: rework filter iteration for channel related callback functions
|
||||
- MEDIUM: filters: use per-channel filter list when relevant
|
||||
- DEV: gdb: add a utility to find the post-mortem address from a core
|
||||
- BUG/MINOR: deviceatlas: add missing return on error in config parsers
|
||||
- BUG/MINOR: deviceatlas: add NULL checks on strdup() results in config parsers
|
||||
- BUG/MEDIUM: deviceatlas: fix resource leaks on init error paths
|
||||
- BUG/MINOR: deviceatlas: fix off-by-one in da_haproxy_conv()
|
||||
- BUG/MINOR: deviceatlas: fix cookie vlen using wrong length after extraction
|
||||
- BUG/MINOR: deviceatlas: fix double-checked locking race in checkinst
|
||||
- BUG/MINOR: deviceatlas: fix resource leak on hot-reload compile failure
|
||||
- BUG/MINOR: deviceatlas: fix deinit to only finalize when initialized
|
||||
- BUG/MINOR: deviceatlas: set cache_size on hot-reloaded atlas instance
|
||||
- MINOR: deviceatlas: check getproptype return and remove pprop indirection
|
||||
- MINOR: deviceatlas: increase DA_MAX_HEADERS and header buffer sizes
|
||||
- MINOR: deviceatlas: define header_evidence_entry in dummy library header
|
||||
- MINOR: deviceatlas: precompute maxhdrlen to skip oversized headers early
|
||||
- CLEANUP: deviceatlas: add unlikely hints and minor code tidying
|
||||
- DEV: gdb: use unsigned longs to display pools memory usage
|
||||
- BUG/MINOR: ssl: lack crtlist_dup_ssl_conf() declaration
|
||||
- BUG/MINOR: ssl: double-free on error path w/ ssl-f-use parser
|
||||
- BUG/MINOR: ssl: fix leak in ssl-f-use parser upon error
|
||||
- BUG/MINOR: ssl: clarify ssl-f-use errors in post-section parsing
|
||||
- BUG/MINOR: ssl: error with ssl-f-use when no "crt"
|
||||
- MEDIUM: backend: make "balance random" consider tg local req rate when loads are equal
|
||||
- BUG/MAJOR: Revert "MEDIUM: mux-quic: add BUG_ON if sending on locally closed QCS"
|
||||
- BUG/MEDIUM: h3: reject frontend CONNECT as currently not implemented
|
||||
- MINOR: mux-quic: add BUG_ON_STRESS() when draining data on closed stream
|
||||
- REGTESTS: fix quoting in feature cmd which prevents test execution
|
||||
- BUG/MEDIUM: mux-h2/quic: Stop sending via fast-forward if stream is closed
|
||||
- BUG/MEDIUM: mux-h1: Stop sending vi fast-forward for unexpected states
|
||||
- BUG/MEDIUM: applet: Fix test on shut flags for legacy applets (v2)
|
||||
- DEV: term-events: Fix hanshake events decoding
|
||||
- BUG/MINOR: flt-trace: Properly compute length of the first DATA block
|
||||
- MINOR: flt-trace: Add an option to limit the amount of data forwarded
|
||||
- CLEANUP: compression: Remove unused static buffers
|
||||
- BUG/MEDIUM: shctx: Use the next block when data exactly filled a block
|
||||
- BUG/MINOR: http-ana: Stop to wait for body on client error/abort
|
||||
- MINOR: stconn: Add missing SC_FL_NO_FASTFWD flag in sc_show_flags
|
||||
- REORG: stconn: Move functions related to channel buffers to sc_strm.h
|
||||
- BUG/MEDIUM: jwe: fix timing side-channel and dead code in JWE decryption
|
||||
- MINOR: tree-wide: Use the buffer size instead of global setting when possible
|
||||
- MINOR: buffers: Swap buffers of same size only
|
||||
- BUG/MINOR: config: Check buffer pool creation for failures
|
||||
- MEDIUM: cache: Don't rely on a chunk to store messages payload
|
||||
- MEDIUM: stream: Limit number of synchronous send per stream wakeup
|
||||
- MEDIUM: compression: Be sure to never compress more than a chunk at once
|
||||
- MEDIUM: mux-h1/mux-h2/mux-fcgi/h3: Disable 0-copy for buffers of different size
|
||||
- MEDIUM: applet: Disable 0-copy for buffers of different size
|
||||
- MINOR: h1-htx: Disable 0-copy for buffers of different size
|
||||
- MEDIUM: stream: Offer buffers of default size only
|
||||
- BUG/MEDIUM: htx: Fix function used to change part of a block value when defrag
|
||||
- MEDIUM: htx: Refactor transfer of htx blocks to merge DATA blocks if possible
|
||||
- MEDIUM: htx: Refactor htx defragmentation to merge data blocks
|
||||
- MEDIUM: htx: Improve detection of fragmented/unordered HTX messages
|
||||
- MINOR: http-ana: Do a defrag on unaligned HTX message when waiting for payload
|
||||
- MINOR: http-fetch: Use pointer to HTX DATA block when retrieving HTX body
|
||||
- MEDIUM: dynbuf: Add a pool for large buffers with a configurable size
|
||||
- MEDIUM: chunk: Add support for large chunks
|
||||
- MEDIUM: stconn: Properly handle large buffers during a receive
|
||||
- MEDIUM: sample: Get chunks with a size dependent on input data when necessary
|
||||
- MEDIUM: http-fetch: Be able to use large chunks when necessary
|
||||
- MINPR: htx: Get large chunk if necessary to perform a defrag
|
||||
- MEDIUM: http-ana: Use a large buffer if necessary when waiting for body
|
||||
- MINOR: dynbuf: Add helpers to know if a buffer is a default or a large buffer
|
||||
- MINOR: config: reject configs using HTTP with large bufsize >= 256 MB
|
||||
- CI: do not use ghcr.io for Quic Interop workflows
|
||||
- BUG/MEDIUM: ssl: SSL backend sessions used after free
|
||||
- CI: vtest: move the vtest2 URL to vinyl-cache.org
|
||||
- CI: github: disable windows.yml by default on unofficials repo
|
||||
- MEDIUM: Add connect/queue/tarpit timeouts to set-timeout
|
||||
- CLEANUP: mux-h1: Remove unneeded null check
|
||||
- DOC: remove openssl no-deprecated CI image
|
||||
- BUG/MINOR: acme: fix X509_NAME leak when X509_set_issuer_name() fails
|
||||
- BUG/MINOR: backend: check delay MUX before conn_prepare()
|
||||
- OPTIM: backend: reduce contention when checking MUX init with ALPN
|
||||
- DOC: configuration: add the ACME wiki page link
|
||||
- MINOR: ssl/ckch: Move EVP_PKEY and cert code generation from acme
|
||||
- MINOR: ssl/ckch: certificates generation from "load" "crt-store" directive
|
||||
- MINOR: trace: add definitions for haterm streams
|
||||
- MINOR: init: allow a fileless init mode
|
||||
- MEDIUM: init: allow the redefinition of argv[] parsing function
|
||||
- MINOR: stconn: stream instantiation from proxy callback
|
||||
- MINOR: haterm: add haterm HTTP server
|
||||
- MINOR: haterm: new "haterm" utility
|
||||
- MINOR: haterm: increase thread-local pool size
|
||||
- BUG/MEDIUM: stats-file: fix shm-stats-file recover when all process slots are full
|
||||
- BUG/MINOR: stats-file: manipulate shm-stats-file heartbeat using unsigned int
|
||||
- BUG/MEDIUM: stats-file: detect and fix inconsistent shared clock when resuming from shm-stats-file
|
||||
- CI: github: only enable OS X on development branches
|
||||
|
||||
2026/02/04 : 3.4-dev4
|
||||
- BUG/MEDIUM: hlua: fix invalid lua_pcall() usage in hlua_traceback()
|
||||
- BUG/MINOR: hlua: consume error object if ignored after a failing lua_pcall()
|
||||
|
|
|
|||
21
Makefile
21
Makefile
|
|
@ -956,7 +956,6 @@ endif # obsolete targets
|
|||
endif # TARGET
|
||||
|
||||
OBJS =
|
||||
HATERM_OBJS =
|
||||
|
||||
ifneq ($(EXTRA_OBJS),)
|
||||
OBJS += $(EXTRA_OBJS)
|
||||
|
|
@ -1004,14 +1003,12 @@ OBJS += src/mux_h2.o src/mux_h1.o src/mux_fcgi.o src/log.o \
|
|||
src/http_acl.o src/dict.o src/dgram.o src/pipe.o \
|
||||
src/hpack-huff.o src/hpack-enc.o src/ebtree.o src/hash.o \
|
||||
src/httpclient_cli.o src/version.o src/ncbmbuf.o src/ech.o \
|
||||
src/cfgparse-peers.o src/haterm.o
|
||||
src/cfgparse-peers.o
|
||||
|
||||
ifneq ($(TRACE),)
|
||||
OBJS += src/calltrace.o
|
||||
endif
|
||||
|
||||
HATERM_OBJS += $(OBJS) src/haterm_init.o
|
||||
|
||||
# Used only for forced dependency checking. May be cleared during development.
|
||||
INCLUDES = $(wildcard include/*/*.h)
|
||||
DEP = $(INCLUDES) .build_opts
|
||||
|
|
@ -1043,7 +1040,7 @@ IGNORE_OPTS=help install install-man install-doc install-bin \
|
|||
uninstall clean tags cscope tar git-tar version update-version \
|
||||
opts reg-tests reg-tests-help unit-tests admin/halog/halog dev/flags/flags \
|
||||
dev/haring/haring dev/ncpu/ncpu dev/poll/poll dev/tcploop/tcploop \
|
||||
dev/term_events/term_events dev/gdb/pm-from-core dev/gdb/libs-from-core
|
||||
dev/term_events/term_events
|
||||
|
||||
ifneq ($(TARGET),)
|
||||
ifeq ($(filter $(firstword $(MAKECMDGOALS)),$(IGNORE_OPTS)),)
|
||||
|
|
@ -1059,9 +1056,6 @@ endif # non-empty target
|
|||
haproxy: $(OPTIONS_OBJS) $(OBJS)
|
||||
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
||||
|
||||
haterm: $(OPTIONS_OBJS) $(HATERM_OBJS)
|
||||
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
||||
|
||||
objsize: haproxy
|
||||
$(Q)objdump -t $^|grep ' g '|grep -F '.text'|awk '{print $$5 FS $$6}'|sort
|
||||
|
||||
|
|
@ -1077,12 +1071,6 @@ admin/dyncookie/dyncookie: admin/dyncookie/dyncookie.o
|
|||
dev/flags/flags: dev/flags/flags.o
|
||||
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
||||
|
||||
dev/gdb/libs-from-core: dev/gdb/libs-from-core.o
|
||||
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
||||
|
||||
dev/gdb/pm-from-core: dev/gdb/pm-from-core.o
|
||||
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
||||
|
||||
dev/haring/haring: dev/haring/haring.o
|
||||
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
||||
|
||||
|
|
@ -1181,7 +1169,7 @@ distclean: clean
|
|||
$(Q)rm -f admin/dyncookie/dyncookie
|
||||
$(Q)rm -f dev/haring/haring dev/ncpu/ncpu{,.so} dev/poll/poll dev/tcploop/tcploop
|
||||
$(Q)rm -f dev/hpack/decode dev/hpack/gen-enc dev/hpack/gen-rht
|
||||
$(Q)rm -f dev/qpack/decode dev/gdb/pm-from-core dev/gdb/libs-from-core
|
||||
$(Q)rm -f dev/qpack/decode
|
||||
|
||||
tags:
|
||||
$(Q)find src include \( -name '*.c' -o -name '*.h' \) -print0 | \
|
||||
|
|
@ -1335,8 +1323,7 @@ range:
|
|||
echo "[ $$index/$$count ] $$commit #############################"; \
|
||||
git checkout -q $$commit || die 1; \
|
||||
$(MAKE) all || die 1; \
|
||||
set -- $(TEST_CMD); \
|
||||
[ "$$#" -eq 0 ] || "$$@" || die 1; \
|
||||
[ -z "$(TEST_CMD)" ] || $(TEST_CMD) || die 1; \
|
||||
index=$$((index + 1)); \
|
||||
done; \
|
||||
echo;echo "Done! $${count} commit(s) built successfully for RANGE $${RANGE}" ; \
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
[](https://github.com/haproxy/haproxy/actions/workflows/musl.yml)
|
||||
[](https://github.com/haproxy/haproxy/actions/workflows/aws-lc.yml)
|
||||
[](https://github.com/haproxy/haproxy/actions/workflows/openssl-nodeprecated.yml)
|
||||
[](https://github.com/haproxy/haproxy/actions/workflows/illumos.yml)
|
||||
[](https://github.com/haproxy/haproxy/actions/workflows/netbsd.yml)
|
||||
[](https://cirrus-ci.com/github/haproxy/haproxy/)
|
||||
|
|
|
|||
2
VERDATE
2
VERDATE
|
|
@ -1,2 +1,2 @@
|
|||
$Format:%ci$
|
||||
2026/03/20
|
||||
2026/02/04
|
||||
|
|
|
|||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
3.4-dev7
|
||||
3.4-dev4
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ static struct {
|
|||
da_atlas_t atlas;
|
||||
da_evidence_id_t useragentid;
|
||||
da_severity_t loglevel;
|
||||
size_t maxhdrlen;
|
||||
char separator;
|
||||
unsigned char daset:1;
|
||||
} global_deviceatlas = {
|
||||
|
|
@ -43,7 +42,6 @@ static struct {
|
|||
.atlasmap = NULL,
|
||||
.atlasfd = -1,
|
||||
.useragentid = 0,
|
||||
.maxhdrlen = 0,
|
||||
.daset = 0,
|
||||
.separator = '|',
|
||||
};
|
||||
|
|
@ -59,10 +57,6 @@ static int da_json_file(char **args, int section_type, struct proxy *curpx,
|
|||
return -1;
|
||||
}
|
||||
global_deviceatlas.jsonpath = strdup(args[1]);
|
||||
if (unlikely(global_deviceatlas.jsonpath == NULL)) {
|
||||
memprintf(err, "deviceatlas json file : out of memory.\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +73,6 @@ static int da_log_level(char **args, int section_type, struct proxy *curpx,
|
|||
loglevel = atol(args[1]);
|
||||
if (loglevel < 0 || loglevel > 3) {
|
||||
memprintf(err, "deviceatlas log level : expects a log level between 0 and 3, %s given.\n", args[1]);
|
||||
return -1;
|
||||
} else {
|
||||
global_deviceatlas.loglevel = (da_severity_t)loglevel;
|
||||
}
|
||||
|
|
@ -108,10 +101,6 @@ static int da_properties_cookie(char **args, int section_type, struct proxy *cur
|
|||
return -1;
|
||||
} else {
|
||||
global_deviceatlas.cookiename = strdup(args[1]);
|
||||
if (unlikely(global_deviceatlas.cookiename == NULL)) {
|
||||
memprintf(err, "deviceatlas cookie name : out of memory.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
global_deviceatlas.cookienamelen = strlen(global_deviceatlas.cookiename);
|
||||
return 0;
|
||||
|
|
@ -130,7 +119,6 @@ static int da_cache_size(char **args, int section_type, struct proxy *curpx,
|
|||
cachesize = atol(args[1]);
|
||||
if (cachesize < 0 || cachesize > DA_CACHE_MAX) {
|
||||
memprintf(err, "deviceatlas cache size : expects a cache size between 0 and %d, %s given.\n", DA_CACHE_MAX, args[1]);
|
||||
return -1;
|
||||
} else {
|
||||
#ifdef APINOCACHE
|
||||
fprintf(stdout, "deviceatlas cache size : no-op, its support is disabled.\n");
|
||||
|
|
@ -177,7 +165,7 @@ static int init_deviceatlas(void)
|
|||
da_status_t status;
|
||||
|
||||
jsonp = fopen(global_deviceatlas.jsonpath, "r");
|
||||
if (unlikely(jsonp == 0)) {
|
||||
if (jsonp == 0) {
|
||||
ha_alert("deviceatlas : '%s' json file has invalid path or is not readable.\n",
|
||||
global_deviceatlas.jsonpath);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
|
|
@ -189,11 +177,9 @@ static int init_deviceatlas(void)
|
|||
status = da_atlas_compile(jsonp, da_haproxy_read, da_haproxy_seek,
|
||||
&global_deviceatlas.atlasimgptr, &atlasimglen);
|
||||
fclose(jsonp);
|
||||
if (unlikely(status != DA_OK)) {
|
||||
if (status != DA_OK) {
|
||||
ha_alert("deviceatlas : '%s' json file is invalid.\n",
|
||||
global_deviceatlas.jsonpath);
|
||||
free(global_deviceatlas.atlasimgptr);
|
||||
da_fini();
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -201,10 +187,8 @@ static int init_deviceatlas(void)
|
|||
status = da_atlas_open(&global_deviceatlas.atlas, extraprops,
|
||||
global_deviceatlas.atlasimgptr, atlasimglen);
|
||||
|
||||
if (unlikely(status != DA_OK)) {
|
||||
if (status != DA_OK) {
|
||||
ha_alert("deviceatlas : data could not be compiled.\n");
|
||||
free(global_deviceatlas.atlasimgptr);
|
||||
da_fini();
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -213,28 +197,11 @@ static int init_deviceatlas(void)
|
|||
|
||||
if (global_deviceatlas.cookiename == 0) {
|
||||
global_deviceatlas.cookiename = strdup(DA_COOKIENAME_DEFAULT);
|
||||
if (unlikely(global_deviceatlas.cookiename == NULL)) {
|
||||
ha_alert("deviceatlas : out of memory.\n");
|
||||
da_atlas_close(&global_deviceatlas.atlas);
|
||||
free(global_deviceatlas.atlasimgptr);
|
||||
da_fini();
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
global_deviceatlas.cookienamelen = strlen(global_deviceatlas.cookiename);
|
||||
}
|
||||
|
||||
global_deviceatlas.useragentid = da_atlas_header_evidence_id(&global_deviceatlas.atlas,
|
||||
"user-agent");
|
||||
{
|
||||
size_t hi;
|
||||
global_deviceatlas.maxhdrlen = 16;
|
||||
for (hi = 0; hi < global_deviceatlas.atlas.header_evidence_count; hi++) {
|
||||
size_t nl = strlen(global_deviceatlas.atlas.header_priorities[hi].name);
|
||||
if (nl > global_deviceatlas.maxhdrlen)
|
||||
global_deviceatlas.maxhdrlen = nl;
|
||||
}
|
||||
}
|
||||
if ((global_deviceatlas.atlasfd = shm_open(ATLASMAPNM, O_RDWR, 0660)) != -1) {
|
||||
global_deviceatlas.atlasmap = mmap(NULL, ATLASTOKSZ, PROT_READ | PROT_WRITE, MAP_SHARED, global_deviceatlas.atlasfd, 0);
|
||||
if (global_deviceatlas.atlasmap == MAP_FAILED) {
|
||||
|
|
@ -264,22 +231,24 @@ static void deinit_deviceatlas(void)
|
|||
free(global_deviceatlas.cookiename);
|
||||
da_atlas_close(&global_deviceatlas.atlas);
|
||||
free(global_deviceatlas.atlasimgptr);
|
||||
da_fini();
|
||||
}
|
||||
|
||||
if (global_deviceatlas.atlasfd != -1) {
|
||||
munmap(global_deviceatlas.atlasmap, ATLASTOKSZ);
|
||||
close(global_deviceatlas.atlasfd);
|
||||
shm_unlink(ATLASMAPNM);
|
||||
}
|
||||
|
||||
da_fini();
|
||||
}
|
||||
|
||||
static void da_haproxy_checkinst(void)
|
||||
{
|
||||
if (global_deviceatlas.atlasmap != 0) {
|
||||
char *base;
|
||||
base = (char *)global_deviceatlas.atlasmap;
|
||||
char *base;
|
||||
base = (char *)global_deviceatlas.atlasmap;
|
||||
|
||||
if (base[0] != 0) {
|
||||
if (base[0] != 0) {
|
||||
FILE *jsonp;
|
||||
void *cnew;
|
||||
da_status_t status;
|
||||
|
|
@ -289,10 +258,6 @@ static void da_haproxy_checkinst(void)
|
|||
da_property_decl_t extraprops[1] = {{NULL, 0}};
|
||||
#ifdef USE_THREAD
|
||||
HA_SPIN_LOCK(OTHER_LOCK, &dadwsch_lock);
|
||||
if (base[0] == 0) {
|
||||
HA_SPIN_UNLOCK(OTHER_LOCK, &dadwsch_lock);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
strlcpy2(atlasp, base + sizeof(char), sizeof(atlasp));
|
||||
jsonp = fopen(atlasp, "r");
|
||||
|
|
@ -310,20 +275,10 @@ static void da_haproxy_checkinst(void)
|
|||
fclose(jsonp);
|
||||
if (status == DA_OK) {
|
||||
if (da_atlas_open(&inst, extraprops, cnew, atlassz) == DA_OK) {
|
||||
inst.config.cache_size = global_deviceatlas.cachesize;
|
||||
da_atlas_close(&global_deviceatlas.atlas);
|
||||
free(global_deviceatlas.atlasimgptr);
|
||||
global_deviceatlas.atlasimgptr = cnew;
|
||||
global_deviceatlas.atlas = inst;
|
||||
{
|
||||
size_t hi;
|
||||
global_deviceatlas.maxhdrlen = 16;
|
||||
for (hi = 0; hi < inst.header_evidence_count; hi++) {
|
||||
size_t nl = strlen(inst.header_priorities[hi].name);
|
||||
if (nl > global_deviceatlas.maxhdrlen)
|
||||
global_deviceatlas.maxhdrlen = nl;
|
||||
}
|
||||
}
|
||||
base[0] = 0;
|
||||
ha_notice("deviceatlas : new instance, data file date `%s`.\n",
|
||||
da_getdatacreationiso8601(&global_deviceatlas.atlas));
|
||||
|
|
@ -331,8 +286,6 @@ static void da_haproxy_checkinst(void)
|
|||
ha_alert("deviceatlas : instance update failed.\n");
|
||||
free(cnew);
|
||||
}
|
||||
} else {
|
||||
free(cnew);
|
||||
}
|
||||
#ifdef USE_THREAD
|
||||
HA_SPIN_UNLOCK(OTHER_LOCK, &dadwsch_lock);
|
||||
|
|
@ -344,7 +297,7 @@ static void da_haproxy_checkinst(void)
|
|||
static int da_haproxy(const struct arg *args, struct sample *smp, da_deviceinfo_t *devinfo)
|
||||
{
|
||||
struct buffer *tmp;
|
||||
da_propid_t prop;
|
||||
da_propid_t prop, *pprop;
|
||||
da_status_t status;
|
||||
da_type_t proptype;
|
||||
const char *propname;
|
||||
|
|
@ -364,15 +317,13 @@ static int da_haproxy(const struct arg *args, struct sample *smp, da_deviceinfo_
|
|||
chunk_appendf(tmp, "%c", global_deviceatlas.separator);
|
||||
continue;
|
||||
}
|
||||
if (unlikely(da_atlas_getproptype(&global_deviceatlas.atlas, prop, &proptype) != DA_OK)) {
|
||||
chunk_appendf(tmp, "%c", global_deviceatlas.separator);
|
||||
continue;
|
||||
}
|
||||
pprop = ∝
|
||||
da_atlas_getproptype(&global_deviceatlas.atlas, *pprop, &proptype);
|
||||
|
||||
switch (proptype) {
|
||||
case DA_TYPE_BOOLEAN: {
|
||||
bool val;
|
||||
status = da_getpropboolean(devinfo, prop, &val);
|
||||
status = da_getpropboolean(devinfo, *pprop, &val);
|
||||
if (status == DA_OK) {
|
||||
chunk_appendf(tmp, "%d", val);
|
||||
}
|
||||
|
|
@ -381,7 +332,7 @@ static int da_haproxy(const struct arg *args, struct sample *smp, da_deviceinfo_
|
|||
case DA_TYPE_INTEGER:
|
||||
case DA_TYPE_NUMBER: {
|
||||
long val;
|
||||
status = da_getpropinteger(devinfo, prop, &val);
|
||||
status = da_getpropinteger(devinfo, *pprop, &val);
|
||||
if (status == DA_OK) {
|
||||
chunk_appendf(tmp, "%ld", val);
|
||||
}
|
||||
|
|
@ -389,7 +340,7 @@ static int da_haproxy(const struct arg *args, struct sample *smp, da_deviceinfo_
|
|||
}
|
||||
case DA_TYPE_STRING: {
|
||||
const char *val;
|
||||
status = da_getpropstring(devinfo, prop, &val);
|
||||
status = da_getpropstring(devinfo, *pprop, &val);
|
||||
if (status == DA_OK) {
|
||||
chunk_appendf(tmp, "%s", val);
|
||||
}
|
||||
|
|
@ -420,26 +371,29 @@ static int da_haproxy_conv(const struct arg *args, struct sample *smp, void *pri
|
|||
{
|
||||
da_deviceinfo_t devinfo;
|
||||
da_status_t status;
|
||||
char useragentbuf[1024];
|
||||
const char *useragent;
|
||||
char useragentbuf[1024] = { 0 };
|
||||
int i;
|
||||
|
||||
if (unlikely(global_deviceatlas.daset == 0) || smp->data.u.str.data == 0) {
|
||||
if (global_deviceatlas.daset == 0 || smp->data.u.str.data == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
da_haproxy_checkinst();
|
||||
|
||||
i = smp->data.u.str.data > sizeof(useragentbuf) - 1 ? sizeof(useragentbuf) - 1 : smp->data.u.str.data;
|
||||
memcpy(useragentbuf, smp->data.u.str.area, i);
|
||||
useragentbuf[i] = 0;
|
||||
i = smp->data.u.str.data > sizeof(useragentbuf) ? sizeof(useragentbuf) : smp->data.u.str.data;
|
||||
memcpy(useragentbuf, smp->data.u.str.area, i - 1);
|
||||
useragentbuf[i - 1] = 0;
|
||||
|
||||
useragent = (const char *)useragentbuf;
|
||||
|
||||
status = da_search(&global_deviceatlas.atlas, &devinfo,
|
||||
global_deviceatlas.useragentid, useragentbuf, 0);
|
||||
global_deviceatlas.useragentid, useragent, 0);
|
||||
|
||||
return status != DA_OK ? 0 : da_haproxy(args, smp, &devinfo);
|
||||
}
|
||||
|
||||
#define DA_MAX_HEADERS 32
|
||||
#define DA_MAX_HEADERS 24
|
||||
|
||||
static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
||||
{
|
||||
|
|
@ -449,10 +403,10 @@ static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const ch
|
|||
struct channel *chn;
|
||||
struct htx *htx;
|
||||
struct htx_blk *blk;
|
||||
char vbuf[DA_MAX_HEADERS][1024];
|
||||
char vbuf[DA_MAX_HEADERS][1024] = {{ 0 }};
|
||||
int i, nbh = 0;
|
||||
|
||||
if (unlikely(global_deviceatlas.daset == 0)) {
|
||||
if (global_deviceatlas.daset == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -460,17 +414,18 @@ static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const ch
|
|||
|
||||
chn = (smp->strm ? &smp->strm->req : NULL);
|
||||
htx = smp_prefetch_htx(smp, chn, NULL, 1);
|
||||
if (unlikely(!htx))
|
||||
if (!htx)
|
||||
return 0;
|
||||
|
||||
i = 0;
|
||||
for (blk = htx_get_first_blk(htx); nbh < DA_MAX_HEADERS && blk; blk = htx_get_next_blk(htx, blk)) {
|
||||
size_t vlen;
|
||||
char *pval;
|
||||
da_evidence_id_t evid;
|
||||
enum htx_blk_type type;
|
||||
struct ist n, v;
|
||||
char hbuf[64];
|
||||
char tval[1024];
|
||||
char hbuf[24] = { 0 };
|
||||
char tval[1024] = { 0 };
|
||||
|
||||
type = htx_get_blk_type(blk);
|
||||
|
||||
|
|
@ -483,18 +438,20 @@ static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const ch
|
|||
continue;
|
||||
}
|
||||
|
||||
if (n.len > global_deviceatlas.maxhdrlen || n.len >= sizeof(hbuf)) {
|
||||
/* The HTTP headers used by the DeviceAtlas API are not longer */
|
||||
if (n.len >= sizeof(hbuf)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(hbuf, n.ptr, n.len);
|
||||
hbuf[n.len] = 0;
|
||||
pval = v.ptr;
|
||||
vlen = v.len;
|
||||
evid = -1;
|
||||
i = v.len > sizeof(tval) - 1 ? sizeof(tval) - 1 : v.len;
|
||||
memcpy(tval, v.ptr, i);
|
||||
tval[i] = 0;
|
||||
pval = tval;
|
||||
vlen = i;
|
||||
|
||||
if (strcasecmp(hbuf, "Accept-Language") == 0) {
|
||||
evid = da_atlas_accept_language_evidence_id(&global_deviceatlas.atlas);
|
||||
|
|
@ -512,7 +469,7 @@ static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const ch
|
|||
continue;
|
||||
}
|
||||
|
||||
vlen = pl;
|
||||
vlen -= global_deviceatlas.cookienamelen - 1;
|
||||
pval = p;
|
||||
evid = da_atlas_clientprop_evidence_id(&global_deviceatlas.atlas);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -141,11 +141,6 @@ enum {
|
|||
DA_INITIAL_MEMORY_ESTIMATE = 1024 * 1024 * 14
|
||||
};
|
||||
|
||||
struct header_evidence_entry {
|
||||
const char *name;
|
||||
da_evidence_id_t id;
|
||||
};
|
||||
|
||||
struct da_config {
|
||||
unsigned int cache_size;
|
||||
unsigned int __reserved[15]; /* enough reserved keywords for future use */
|
||||
|
|
|
|||
|
|
@ -407,7 +407,6 @@ listed below. Metrics from extra counters are not listed.
|
|||
+----------------------------------------------------+
|
||||
| haproxy_sticktable_size |
|
||||
| haproxy_sticktable_used |
|
||||
| haproxy_sticktable_local_updates |
|
||||
+----------------------------------------------------+
|
||||
|
||||
* Resolvers metrics
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@
|
|||
#include <haproxy/stats.h>
|
||||
#include <haproxy/stconn.h>
|
||||
#include <haproxy/stream.h>
|
||||
#include <haproxy/stress.h>
|
||||
#include <haproxy/task.h>
|
||||
#include <haproxy/tools.h>
|
||||
#include <haproxy/version.h>
|
||||
|
|
@ -83,7 +82,6 @@ struct promex_ctx {
|
|||
unsigned field_num; /* current field number (ST_I_PX_* etc) */
|
||||
unsigned mod_field_num; /* first field number of the current module (ST_I_PX_* etc) */
|
||||
int obj_state; /* current state among PROMEX_{FRONT|BACK|SRV|LI}_STATE_* */
|
||||
struct watcher px_watch; /* watcher to automatically update next pointer */
|
||||
struct watcher srv_watch; /* watcher to automatically update next pointer */
|
||||
struct list modules; /* list of promex modules to export */
|
||||
struct eb_root filters; /* list of filters to apply on metrics name */
|
||||
|
|
@ -349,10 +347,6 @@ static int promex_dump_ts(struct appctx *appctx, struct ist prefix,
|
|||
istcat(&n, prefix, PROMEX_MAX_NAME_LEN);
|
||||
istcat(&n, name, PROMEX_MAX_NAME_LEN);
|
||||
|
||||
/* In stress mode, force yielding on each metric. */
|
||||
if (STRESS_RUN1(istlen(*out), 0))
|
||||
goto full;
|
||||
|
||||
if ((ctx->flags & PROMEX_FL_METRIC_HDR) &&
|
||||
!promex_dump_ts_header(n, desc, type, out, max))
|
||||
goto full;
|
||||
|
|
@ -632,6 +626,8 @@ static int promex_dump_front_metrics(struct appctx *appctx, struct htx *htx)
|
|||
}
|
||||
|
||||
list_for_each_entry_from(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
|
||||
void *counters;
|
||||
|
||||
if (!(stats_px_get_cap(mod->domain_flags) & STATS_PX_CAP_FE))
|
||||
continue;
|
||||
|
||||
|
|
@ -668,7 +664,8 @@ static int promex_dump_front_metrics(struct appctx *appctx, struct htx *htx)
|
|||
if ((px->flags & PR_FL_DISABLED) || px->uuid <= 0 || !(px->cap & PR_CAP_FE))
|
||||
goto next_px2;
|
||||
|
||||
if (!mod->fill_stats(mod, px->extra_counters_fe, stats + ctx->field_num, &ctx->mod_field_num))
|
||||
counters = EXTRA_COUNTERS_GET(px->extra_counters_fe, mod);
|
||||
if (!mod->fill_stats(counters, stats + ctx->field_num, &ctx->mod_field_num))
|
||||
return -1;
|
||||
|
||||
val = stats[ctx->field_num + ctx->mod_field_num];
|
||||
|
|
@ -820,6 +817,8 @@ static int promex_dump_listener_metrics(struct appctx *appctx, struct htx *htx)
|
|||
}
|
||||
|
||||
list_for_each_entry_from(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
|
||||
void *counters;
|
||||
|
||||
if (!(stats_px_get_cap(mod->domain_flags) & STATS_PX_CAP_LI))
|
||||
continue;
|
||||
|
||||
|
|
@ -865,7 +864,8 @@ static int promex_dump_listener_metrics(struct appctx *appctx, struct htx *htx)
|
|||
labels[lb_idx+1].name = ist("mod");
|
||||
labels[lb_idx+1].value = ist2(mod->name, strlen(mod->name));
|
||||
|
||||
if (!mod->fill_stats(mod, li->extra_counters, stats + ctx->field_num, &ctx->mod_field_num))
|
||||
counters = EXTRA_COUNTERS_GET(li->extra_counters, mod);
|
||||
if (!mod->fill_stats(counters, stats + ctx->field_num, &ctx->mod_field_num))
|
||||
return -1;
|
||||
|
||||
val = stats[ctx->field_num + ctx->mod_field_num];
|
||||
|
|
@ -941,6 +941,9 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
|
|||
if (promex_filter_metric(appctx, prefix, name))
|
||||
continue;
|
||||
|
||||
if (!px)
|
||||
px = proxies_list;
|
||||
|
||||
while (px) {
|
||||
struct promex_label labels[PROMEX_MAX_LABELS-1] = {};
|
||||
unsigned int srv_state_count[PROMEX_SRV_STATE_COUNT] = { 0 };
|
||||
|
|
@ -1095,16 +1098,9 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
|
|||
&val, labels, &out, max))
|
||||
goto full;
|
||||
next_px:
|
||||
px = watcher_next(&ctx->px_watch, px->next);
|
||||
px = px->next;
|
||||
}
|
||||
watcher_detach(&ctx->px_watch);
|
||||
ctx->flags |= PROMEX_FL_METRIC_HDR;
|
||||
|
||||
/* Prepare a new iteration for the next stat column.
|
||||
* Update ctx.p[0] via watcher.
|
||||
*/
|
||||
watcher_attach(&ctx->px_watch, proxies_list);
|
||||
px = proxies_list;
|
||||
}
|
||||
|
||||
/* Skip extra counters */
|
||||
|
|
@ -1117,6 +1113,8 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
|
|||
}
|
||||
|
||||
list_for_each_entry_from(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
|
||||
void *counters;
|
||||
|
||||
if (!(stats_px_get_cap(mod->domain_flags) & STATS_PX_CAP_BE))
|
||||
continue;
|
||||
|
||||
|
|
@ -1127,6 +1125,9 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
|
|||
if (promex_filter_metric(appctx, prefix, name))
|
||||
continue;
|
||||
|
||||
if (!px)
|
||||
px = proxies_list;
|
||||
|
||||
while (px) {
|
||||
struct promex_label labels[PROMEX_MAX_LABELS-1] = {};
|
||||
struct promex_metric metric;
|
||||
|
|
@ -1150,7 +1151,8 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
|
|||
if ((px->flags & PR_FL_DISABLED) || px->uuid <= 0 || !(px->cap & PR_CAP_BE))
|
||||
goto next_px2;
|
||||
|
||||
if (!mod->fill_stats(mod, px->extra_counters_be, stats + ctx->field_num, &ctx->mod_field_num))
|
||||
counters = EXTRA_COUNTERS_GET(px->extra_counters_be, mod);
|
||||
if (!mod->fill_stats(counters, stats + ctx->field_num, &ctx->mod_field_num))
|
||||
return -1;
|
||||
|
||||
val = stats[ctx->field_num + ctx->mod_field_num];
|
||||
|
|
@ -1161,39 +1163,25 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
|
|||
goto full;
|
||||
|
||||
next_px2:
|
||||
px = watcher_next(&ctx->px_watch, px->next);
|
||||
px = px->next;
|
||||
}
|
||||
watcher_detach(&ctx->px_watch);
|
||||
ctx->flags |= PROMEX_FL_METRIC_HDR;
|
||||
|
||||
/* Prepare a new iteration for the next stat column.
|
||||
* Update ctx.p[0] via watcher.
|
||||
*/
|
||||
watcher_attach(&ctx->px_watch, proxies_list);
|
||||
px = proxies_list;
|
||||
}
|
||||
|
||||
ctx->field_num += mod->stats_count;
|
||||
ctx->mod_field_num = 0;
|
||||
}
|
||||
|
||||
px = NULL;
|
||||
mod = NULL;
|
||||
|
||||
end:
|
||||
if (ret) {
|
||||
watcher_detach(&ctx->px_watch);
|
||||
mod = NULL;
|
||||
}
|
||||
|
||||
if (out.len) {
|
||||
if (!htx_add_data_atonce(htx, out)) {
|
||||
watcher_detach(&ctx->px_watch);
|
||||
if (!htx_add_data_atonce(htx, out))
|
||||
return -1; /* Unexpected and unrecoverable error */
|
||||
}
|
||||
}
|
||||
|
||||
/* Save pointers of the current context for dump resumption :
|
||||
* 0=current proxy, 1=current stats module
|
||||
* Note that p[0] is already automatically updated via px_watch.
|
||||
*/
|
||||
/* Save pointers (0=current proxy, 1=current stats module) of the current context */
|
||||
ctx->p[0] = px;
|
||||
ctx->p[1] = mod;
|
||||
return ret;
|
||||
full:
|
||||
|
|
@ -1235,6 +1223,9 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||
if (promex_filter_metric(appctx, prefix, name))
|
||||
continue;
|
||||
|
||||
if (!px)
|
||||
px = proxies_list;
|
||||
|
||||
while (px) {
|
||||
struct promex_label labels[PROMEX_MAX_LABELS-1] = {};
|
||||
enum promex_mt_type type;
|
||||
|
|
@ -1254,6 +1245,11 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||
if ((px->flags & PR_FL_DISABLED) || px->uuid <= 0 || !(px->cap & PR_CAP_BE))
|
||||
goto next_px;
|
||||
|
||||
if (!sv) {
|
||||
watcher_attach(&ctx->srv_watch, px->srv);
|
||||
sv = px->srv;
|
||||
}
|
||||
|
||||
while (sv) {
|
||||
labels[lb_idx].name = ist("server");
|
||||
labels[lb_idx].value = ist2(sv->id, strlen(sv->id));
|
||||
|
|
@ -1409,25 +1405,9 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||
|
||||
next_px:
|
||||
watcher_detach(&ctx->srv_watch);
|
||||
px = watcher_next(&ctx->px_watch, px->next);
|
||||
if (px) {
|
||||
/* Update ctx.p[1] via watcher. */
|
||||
watcher_attach(&ctx->srv_watch, px->srv);
|
||||
sv = ctx->p[1];
|
||||
}
|
||||
px = px->next;
|
||||
}
|
||||
watcher_detach(&ctx->px_watch);
|
||||
ctx->flags |= PROMEX_FL_METRIC_HDR;
|
||||
|
||||
/* Prepare a new iteration for the next stat column.
|
||||
* Update ctx.p[0]/p[1] via px_watch/srv_watch.
|
||||
*/
|
||||
watcher_attach(&ctx->px_watch, proxies_list);
|
||||
px = proxies_list;
|
||||
if (likely(px)) {
|
||||
watcher_attach(&ctx->srv_watch, px->srv);
|
||||
sv = ctx->p[1];
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip extra counters */
|
||||
|
|
@ -1440,6 +1420,8 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||
}
|
||||
|
||||
list_for_each_entry_from(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
|
||||
void *counters;
|
||||
|
||||
if (!(stats_px_get_cap(mod->domain_flags) & STATS_PX_CAP_SRV))
|
||||
continue;
|
||||
|
||||
|
|
@ -1450,6 +1432,9 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||
if (promex_filter_metric(appctx, prefix, name))
|
||||
continue;
|
||||
|
||||
if (!px)
|
||||
px = proxies_list;
|
||||
|
||||
while (px) {
|
||||
struct promex_label labels[PROMEX_MAX_LABELS-1] = {};
|
||||
struct promex_metric metric;
|
||||
|
|
@ -1470,6 +1455,11 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||
if ((px->flags & PR_FL_DISABLED) || px->uuid <= 0 || !(px->cap & PR_CAP_BE))
|
||||
goto next_px2;
|
||||
|
||||
if (!sv) {
|
||||
watcher_attach(&ctx->srv_watch, px->srv);
|
||||
sv = px->srv;
|
||||
}
|
||||
|
||||
while (sv) {
|
||||
labels[lb_idx].name = ist("server");
|
||||
labels[lb_idx].value = ist2(sv->id, strlen(sv->id));
|
||||
|
|
@ -1481,7 +1471,8 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||
goto next_sv2;
|
||||
|
||||
|
||||
if (!mod->fill_stats(mod, sv->extra_counters, stats + ctx->field_num, &ctx->mod_field_num))
|
||||
counters = EXTRA_COUNTERS_GET(sv->extra_counters, mod);
|
||||
if (!mod->fill_stats(counters, stats + ctx->field_num, &ctx->mod_field_num))
|
||||
goto error;
|
||||
|
||||
val = stats[ctx->field_num + ctx->mod_field_num];
|
||||
|
|
@ -1497,47 +1488,28 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||
|
||||
next_px2:
|
||||
watcher_detach(&ctx->srv_watch);
|
||||
px = watcher_next(&ctx->px_watch, px->next);
|
||||
if (px) {
|
||||
/* Update ctx.p[1] via watcher. */
|
||||
watcher_attach(&ctx->srv_watch, px->srv);
|
||||
sv = ctx->p[1];
|
||||
}
|
||||
px = px->next;
|
||||
}
|
||||
watcher_detach(&ctx->px_watch);
|
||||
ctx->flags |= PROMEX_FL_METRIC_HDR;
|
||||
|
||||
/* Prepare a new iteration for the next stat column.
|
||||
* Update ctx.p[0]/p[1] via px_watch/srv_watch.
|
||||
*/
|
||||
watcher_attach(&ctx->px_watch, proxies_list);
|
||||
px = proxies_list;
|
||||
if (likely(px)) {
|
||||
watcher_attach(&ctx->srv_watch, px->srv);
|
||||
sv = ctx->p[1];
|
||||
}
|
||||
}
|
||||
|
||||
ctx->field_num += mod->stats_count;
|
||||
ctx->mod_field_num = 0;
|
||||
}
|
||||
|
||||
end:
|
||||
if (ret) {
|
||||
watcher_detach(&ctx->px_watch);
|
||||
watcher_detach(&ctx->srv_watch);
|
||||
mod = NULL;
|
||||
}
|
||||
px = NULL;
|
||||
sv = NULL;
|
||||
mod = NULL;
|
||||
|
||||
end:
|
||||
if (out.len) {
|
||||
if (!htx_add_data_atonce(htx, out))
|
||||
return -1; /* Unexpected and unrecoverable error */
|
||||
}
|
||||
|
||||
/* Save pointers of the current context for dump resumption :
|
||||
* 0=current proxy, 1=current server, 2=current stats module
|
||||
* Note that p[0]/p[1] are already automatically updated via px_watch/srv_watch.
|
||||
*/
|
||||
/* Save pointers (0=current proxy, 1=current server, 2=current stats module) of the current context */
|
||||
ctx->p[0] = px;
|
||||
ctx->p[1] = sv;
|
||||
ctx->p[2] = mod;
|
||||
return ret;
|
||||
full:
|
||||
|
|
@ -1545,7 +1517,6 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||
goto end;
|
||||
|
||||
error:
|
||||
watcher_detach(&ctx->px_watch);
|
||||
watcher_detach(&ctx->srv_watch);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1768,11 +1739,6 @@ static int promex_dump_metrics(struct appctx *appctx, struct htx *htx)
|
|||
ctx->field_num = ST_I_PX_PXNAME;
|
||||
ctx->mod_field_num = 0;
|
||||
appctx->st1 = PROMEX_DUMPER_BACK;
|
||||
|
||||
if (ctx->flags & PROMEX_FL_SCOPE_BACK) {
|
||||
/* Update ctx.p[0] via watcher. */
|
||||
watcher_attach(&ctx->px_watch, proxies_list);
|
||||
}
|
||||
__fallthrough;
|
||||
|
||||
case PROMEX_DUMPER_BACK:
|
||||
|
|
@ -1790,15 +1756,6 @@ static int promex_dump_metrics(struct appctx *appctx, struct htx *htx)
|
|||
ctx->field_num = ST_I_PX_PXNAME;
|
||||
ctx->mod_field_num = 0;
|
||||
appctx->st1 = PROMEX_DUMPER_SRV;
|
||||
|
||||
if (ctx->flags & PROMEX_FL_SCOPE_SERVER) {
|
||||
/* Update ctx.p[0] via watcher. */
|
||||
watcher_attach(&ctx->px_watch, proxies_list);
|
||||
if (likely(proxies_list)) {
|
||||
/* Update ctx.p[1] via watcher. */
|
||||
watcher_attach(&ctx->srv_watch, proxies_list->srv);
|
||||
}
|
||||
}
|
||||
__fallthrough;
|
||||
|
||||
case PROMEX_DUMPER_SRV:
|
||||
|
|
@ -2076,7 +2033,6 @@ static int promex_appctx_init(struct appctx *appctx)
|
|||
LIST_INIT(&ctx->modules);
|
||||
ctx->filters = EB_ROOT;
|
||||
appctx->st0 = PROMEX_ST_INIT;
|
||||
watcher_init(&ctx->px_watch, &ctx->p[0], offsetof(struct proxy, watcher_list));
|
||||
watcher_init(&ctx->srv_watch, &ctx->p[1], offsetof(struct server, watcher_list));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2091,11 +2047,6 @@ static void promex_appctx_release(struct appctx *appctx)
|
|||
struct promex_metric_filter *flt;
|
||||
struct eb32_node *node, *next;
|
||||
|
||||
if (appctx->st1 == PROMEX_DUMPER_BACK ||
|
||||
appctx->st1 == PROMEX_DUMPER_SRV) {
|
||||
watcher_detach(&ctx->px_watch);
|
||||
}
|
||||
|
||||
if (appctx->st1 == PROMEX_DUMPER_SRV)
|
||||
watcher_detach(&ctx->srv_watch);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export VERBOSE=1
|
||||
export TIMEOUT=90
|
||||
export MASTER_SOCKET="${MASTER_SOCKET:-/var/run/haproxy-master.sock}"
|
||||
export MASTER_SOCKET=${MASTER_SOCKET:-/var/run/haproxy-master.sock}
|
||||
export RET=
|
||||
|
||||
alert() {
|
||||
if [ "$VERBOSE" -ge "1" ]; then
|
||||
|
|
@ -14,38 +15,32 @@ alert() {
|
|||
|
||||
|
||||
reload() {
|
||||
if [ -S "$MASTER_SOCKET" ]; then
|
||||
socat_addr="UNIX-CONNECT:${MASTER_SOCKET}"
|
||||
else
|
||||
case "$MASTER_SOCKET" in
|
||||
*:[0-9]*)
|
||||
socat_addr="TCP:${MASTER_SOCKET}"
|
||||
;;
|
||||
*)
|
||||
alert "Invalid master socket address '${MASTER_SOCKET}': expected a UNIX socket file or <host>:<port>"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
while read -r line; do
|
||||
|
||||
echo "reload" | socat -t"${TIMEOUT}" "$socat_addr" - | {
|
||||
read -r status || { alert "No status received (connection error or timeout after ${TIMEOUT}s)."; exit 1; }
|
||||
case "$status" in
|
||||
"Success=1") ret=0 ;;
|
||||
"Success=0") ret=1 ;;
|
||||
*) alert "Unexpected response: '$status'"; exit 1 ;;
|
||||
esac
|
||||
|
||||
read -r _ # consume "--"
|
||||
|
||||
if [ "$VERBOSE" -ge 3 ] || { [ "$ret" = 1 ] && [ "$VERBOSE" -ge 2 ]; }; then
|
||||
cat >&2
|
||||
if [ "$line" = "Success=0" ]; then
|
||||
RET=1
|
||||
elif [ "$line" = "Success=1" ]; then
|
||||
RET=0
|
||||
elif [ "$line" = "Another reload is still in progress." ]; then
|
||||
alert "$line"
|
||||
elif [ "$line" = "--" ]; then
|
||||
continue;
|
||||
else
|
||||
cat >/dev/null
|
||||
if [ "$RET" = 1 ] && [ "$VERBOSE" = "2" ]; then
|
||||
echo "$line" >&2
|
||||
elif [ "$VERBOSE" = "3" ]; then
|
||||
echo "$line" >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
exit "$ret"
|
||||
}
|
||||
done < <(echo "reload" | socat -t"${TIMEOUT}" "${MASTER_SOCKET}" -)
|
||||
|
||||
if [ -z "$RET" ]; then
|
||||
alert "Couldn't finish the reload before the timeout (${TIMEOUT})."
|
||||
return 1
|
||||
fi
|
||||
|
||||
return "$RET"
|
||||
}
|
||||
|
||||
usage() {
|
||||
|
|
@ -57,12 +52,12 @@ usage() {
|
|||
echo " EXPERIMENTAL script!"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -S, --master-socket <addr> Unix socket path or <host>:<port> (default: ${MASTER_SOCKET})"
|
||||
echo " -S, --master-socket <path> Use the master socket at <path> (default: ${MASTER_SOCKET})"
|
||||
echo " -d, --debug Debug mode, set -x"
|
||||
echo " -t, --timeout Timeout (socat -t) (default: ${TIMEOUT})"
|
||||
echo " -s, --silent Silent mode (no output)"
|
||||
echo " -v, --verbose Verbose output (output from haproxy on failure)"
|
||||
echo " -vv --verbose=all Very verbose output (output from haproxy on success and failure)"
|
||||
echo " -vv Even more verbose output (output from haproxy on success and failure)"
|
||||
echo " -h, --help This help"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
|
|
@ -89,7 +84,7 @@ main() {
|
|||
VERBOSE=2
|
||||
shift
|
||||
;;
|
||||
-vv|--verbose=all)
|
||||
-vv|--verbose)
|
||||
VERBOSE=3
|
||||
shift
|
||||
;;
|
||||
|
|
|
|||
|
|
@ -1,162 +0,0 @@
|
|||
/*
|
||||
* Extracts the libs archives from a core dump
|
||||
*
|
||||
* Copyright (C) 2026 Willy Tarreau <w@1wt.eu>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Note: builds with no option under glibc, and can be built as a minimal
|
||||
* uploadable static executable using nolibc as well:
|
||||
gcc -o libs-from-core -nostdinc -nostdlib -s -Os -static -fno-ident \
|
||||
-fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables \
|
||||
-Wl,--gc-sections,--orphan-handling=discard,-znoseparate-code \
|
||||
-I /path/to/nolibc-sysroot/include libs-from-core.c
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <elf.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void usage(const char *progname)
|
||||
{
|
||||
const char *slash = strrchr(progname, '/');
|
||||
|
||||
if (slash)
|
||||
progname = slash + 1;
|
||||
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-q] <core_file>\n"
|
||||
"Locate a libs archive from an haproxy core dump and dump it to stdout.\n"
|
||||
"Arguments:\n"
|
||||
" -q Query mode: only report offset and length, do not dump\n"
|
||||
" core_file Core dump produced by haproxy\n",
|
||||
progname);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Elf64_Ehdr *ehdr;
|
||||
Elf64_Phdr *phdr;
|
||||
struct stat st;
|
||||
uint8_t *mem;
|
||||
int i, fd;
|
||||
const char *fname;
|
||||
int quiet = 0;
|
||||
int arg;
|
||||
|
||||
for (arg = 1; arg < argc; arg++) {
|
||||
if (*argv[arg] != '-')
|
||||
break;
|
||||
|
||||
if (strcmp(argv[arg], "-q") == 0)
|
||||
quiet = 1;
|
||||
else if (strcmp(argv[arg], "--") == 0) {
|
||||
arg++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (arg < argc) {
|
||||
fname = argv[arg];
|
||||
} else {
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fd = open(fname, O_RDONLY);
|
||||
|
||||
/* Let's just map the core dump as an ELF header */
|
||||
fstat(fd, &st);
|
||||
mem = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (mem == MAP_FAILED) {
|
||||
perror("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* get the program headers */
|
||||
ehdr = (Elf64_Ehdr *)mem;
|
||||
|
||||
/* check that it's really a core. Should be "\x7fELF" */
|
||||
if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
|
||||
fprintf(stderr, "ELF magic not found.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) {
|
||||
fprintf(stderr, "Only 64-bit ELF supported.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ehdr->e_type != ET_CORE) {
|
||||
fprintf(stderr, "ELF type %d, not a core dump.\n", ehdr->e_type);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* OK we can safely go with program headers */
|
||||
phdr = (Elf64_Phdr *)(mem + ehdr->e_phoff);
|
||||
|
||||
for (i = 0; i < ehdr->e_phnum; i++) {
|
||||
uint64_t size = phdr[i].p_filesz;
|
||||
uint64_t offset = phdr[i].p_offset;
|
||||
int ret = 0;
|
||||
|
||||
if (phdr[i].p_type != PT_LOAD)
|
||||
continue;
|
||||
|
||||
//fprintf(stderr, "Scanning segment %d...\n", ehdr->e_phnum);
|
||||
//fprintf(stderr, "\r%-5d: off=%lx va=%lx sz=%lx ", i, (long)offset, (long)phdr[i].p_vaddr, (long)size);
|
||||
if (!size)
|
||||
continue;
|
||||
|
||||
if (size < 512) // minimum for a tar header
|
||||
continue;
|
||||
|
||||
/* tar magic */
|
||||
if (memcmp(mem + offset + 257, "ustar\0""00", 8) != 0)
|
||||
continue;
|
||||
|
||||
/* uid, gid */
|
||||
if (memcmp(mem + offset + 108, "0000000\0""0000000\0", 16) != 0)
|
||||
continue;
|
||||
|
||||
/* link name */
|
||||
if (memcmp(mem + offset + 157, "haproxy-libs-dump\0", 18) != 0)
|
||||
continue;
|
||||
|
||||
/* OK that's really it */
|
||||
|
||||
if (quiet)
|
||||
printf("offset=%#lx size=%#lx\n", offset, size);
|
||||
else
|
||||
ret = (write(1, mem + offset, size) == size) ? 0 : 1;
|
||||
return ret;
|
||||
}
|
||||
//fprintf(stderr, "\r%75s\n", "\r");
|
||||
fprintf(stderr, "libs archive not found. Was 'set-dumpable' set to 'libs' ?\n");
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
/*
|
||||
* Find the post-mortem offset from a core dump
|
||||
*
|
||||
* Copyright (C) 2026 Willy Tarreau <w@1wt.eu>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Note: builds with no option under glibc, and can be built as a minimal
|
||||
* uploadable static executable using nolibc as well:
|
||||
gcc -o pm-from-core -nostdinc -nostdlib -s -Os -static -fno-ident \
|
||||
-fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables \
|
||||
-Wl,--gc-sections,--orphan-handling=discard,-znoseparate-code \
|
||||
-I /path/to/nolibc-sysroot/include pm-from-core.c
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <elf.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__GLIBC__)
|
||||
# define my_memmem memmem
|
||||
#else
|
||||
void *my_memmem(const void *haystack, size_t haystacklen,
|
||||
const void *needle, size_t needlelen)
|
||||
{
|
||||
while (haystacklen >= needlelen) {
|
||||
if (!memcmp(haystack, needle, needlelen))
|
||||
return (void*)haystack;
|
||||
haystack++;
|
||||
haystacklen--;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MAGIC "POST-MORTEM STARTS HERE+7654321\0"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Elf64_Ehdr *ehdr;
|
||||
Elf64_Phdr *phdr;
|
||||
struct stat st;
|
||||
uint8_t *mem;
|
||||
int i, fd;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s <core_file>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fd = open(argv[1], O_RDONLY);
|
||||
|
||||
/* Let's just map the core dump as an ELF header */
|
||||
fstat(fd, &st);
|
||||
mem = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (mem == MAP_FAILED) {
|
||||
perror("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* get the program headers */
|
||||
ehdr = (Elf64_Ehdr *)mem;
|
||||
|
||||
/* check that it's really a core. Should be "\x7fELF" */
|
||||
if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
|
||||
fprintf(stderr, "ELF magic not found.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) {
|
||||
fprintf(stderr, "Only 64-bit ELF supported.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ehdr->e_type != ET_CORE) {
|
||||
fprintf(stderr, "ELF type %d, not a core dump.\n", ehdr->e_type);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* OK we can safely go with program headers */
|
||||
phdr = (Elf64_Phdr *)(mem + ehdr->e_phoff);
|
||||
|
||||
for (i = 0; i < ehdr->e_phnum; i++) {
|
||||
uint64_t size = phdr[i].p_filesz;
|
||||
uint64_t offset = phdr[i].p_offset;
|
||||
uint64_t vaddr = phdr[i].p_vaddr;
|
||||
uint64_t found_ofs;
|
||||
uint8_t *found;
|
||||
|
||||
if (phdr[i].p_type != PT_LOAD)
|
||||
continue;
|
||||
|
||||
//printf("Scanning segment %d...\n", ehdr->e_phnum);
|
||||
//printf("\r%-5d: off=%lx va=%lx sz=%lx ", i, (long)offset, (long)vaddr, (long)size);
|
||||
if (!size)
|
||||
continue;
|
||||
|
||||
if (size >= 1048576) // don't scan large segments
|
||||
continue;
|
||||
|
||||
found = my_memmem(mem + offset, size, MAGIC, sizeof(MAGIC) - 1);
|
||||
if (!found)
|
||||
continue;
|
||||
|
||||
found_ofs = found - (mem + offset);
|
||||
|
||||
printf("Found post-mortem magic in segment %d:\n", i);
|
||||
printf(" Core File Offset: 0x%lx (0x%lx + 0x%lx)\n", offset + found_ofs, offset, found_ofs);
|
||||
printf(" Runtime VAddr: 0x%lx (0x%lx + 0x%lx)\n", vaddr + found_ofs, vaddr, found_ofs);
|
||||
printf(" Segment Size: 0x%lx\n", size);
|
||||
printf("\nIn gdb, copy-paste this line:\n\n pm_init 0x%lx\n\n", vaddr + found_ofs);
|
||||
return 0;
|
||||
}
|
||||
//printf("\r%75s\n", "\r");
|
||||
printf("post-mortem magic not found\n");
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -14,8 +14,8 @@ define pools_dump
|
|||
set $idx=$idx + 1
|
||||
end
|
||||
|
||||
set $mem = (unsigned long)$total * $e->size
|
||||
printf "list=%#lx pool_head=%p name=%s size=%u alloc=%u used=%u mem=%lu\n", $p, $e, $e->name, $e->size, $total, $used, $mem
|
||||
set $mem = $total * $e->size
|
||||
printf "list=%#lx pool_head=%p name=%s size=%u alloc=%u used=%u mem=%u\n", $p, $e, $e->name, $e->size, $total, $used, $mem
|
||||
set $p = *(void **)$p
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -30,10 +30,10 @@ static const char *tevt_fd_types[16] = {
|
|||
};
|
||||
|
||||
static const char *tevt_hs_types[16] = {
|
||||
[ 0] = "-", [ 1] = "-", [ 2] = "-", [ 3] = "-",
|
||||
[ 4] = "snd_err", [ 5] = "truncated_shutr", [ 6] = "truncated_rcv_err", [ 7] = "-",
|
||||
[ 8] = "-", [ 9] = "-", [10] = "-", [11] = "-",
|
||||
[12] = "-", [13] = "-", [14] = "-", [15] = "-",
|
||||
[ 0] = "-", [ 1] = "-", [ 2] = "-", [ 3] = "rcv_err",
|
||||
[ 4] = "snd_err", [ 5] = "-", [ 6] = "-", [ 7] = "-",
|
||||
[ 8] = "-", [ 9] = "-", [10] = "-", [11] = "-",
|
||||
[12] = "-", [13] = "-", [14] = "-", [15] = "-",
|
||||
};
|
||||
|
||||
static const char *tevt_xprt_types[16] = {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
140
doc/haterm.txt
140
doc/haterm.txt
|
|
@ -1,140 +0,0 @@
|
|||
------
|
||||
HATerm
|
||||
------
|
||||
HAProxy's dummy HTTP
|
||||
server for benchmarks
|
||||
|
||||
1. Background
|
||||
-------------
|
||||
|
||||
HATerm is a dummy HTTP server that leverages the flexible and scalable
|
||||
architecture of HAProxy to ease benchmarking of HTTP agents in all versions of
|
||||
HTTP currently supported by HAProxy (HTTP/1, HTTP/2, HTTP/3), and both in clear
|
||||
and TLS / QUIC. It follows the same principle as its ancestor HTTPTerm [1],
|
||||
consisting in producing HTTP responses entirely configured by the request
|
||||
parameters (size, response time, status etc). It also preserves the spirit
|
||||
HTTPTerm which does not require any configuration beyond an optional listening
|
||||
address and a port number, though it also supports advanced configurations with
|
||||
the full spectrum of HAProxy features for specific testing. The goal remains
|
||||
to make it almost as fast as the original HTTPTerm so that it can become a
|
||||
de-facto replacement, with a compatible command line and request parameters
|
||||
that will not change users' habits.
|
||||
|
||||
[1] https://github.com/wtarreau/httpterm
|
||||
|
||||
|
||||
2. Compilation
|
||||
--------------
|
||||
|
||||
HATerm may be compiled in the same way as HAProxy but with "haterm" as Makefile
|
||||
target to provide on the "make" command line as follows:
|
||||
|
||||
$ make -j $(nproc) TARGET=linux-glibc haterm
|
||||
|
||||
HATerm supports HTTPS/SSL/TCP:
|
||||
|
||||
$ make TARGET=linux-glibc USE_OPENSSL=1
|
||||
|
||||
It also supports QUIC:
|
||||
|
||||
$ make -j $(nproc) TARGET=linux-glibc USE_OPENSSL=1 USE_QUIC=1 haterm
|
||||
|
||||
Technically speaking, it uses the regular HAProxy source and object code with a
|
||||
different command line parser. As such, all build options supported by HAProxy
|
||||
also apply to HATerm. See INSTALL for more details about how to compile them.
|
||||
|
||||
|
||||
3. Execution
|
||||
------------
|
||||
|
||||
HATerm is a very easy to use HTTP server with supports for all the HTTP
|
||||
versions. It displays its usage when run without argument or wrong arguments:
|
||||
|
||||
$ ./haterm
|
||||
Usage : haterm -L [<ip>]:<clear port>[:<TCP&QUIC SSL port>] [-L...]* [opts]
|
||||
where <opts> may be any combination of:
|
||||
-G <line> : multiple option; append <line> to the "global" section
|
||||
-F <line> : multiple option; append <line> to the "frontend" section
|
||||
-T <line> : multiple option; append <line> to the "traces" section
|
||||
-C : dump the configuration and exit
|
||||
-D : goes daemon
|
||||
-b <keysize> : RSA key size in bits (ex: "2048", "4096"...)
|
||||
-c <curves> : ECSDA curves (ex: "P-256", "P-384"...)
|
||||
-v : shows version
|
||||
-d : enable the traces for all http protocols
|
||||
--quic-bind-opts <opts> : append options to QUIC "bind" lines
|
||||
--tcp-bind-opts <opts> : append options to TCP "bind" lines
|
||||
|
||||
|
||||
Arguments -G, -F, -T permit to append one or multiple lines at the end of their
|
||||
respective sections. A tab character ('\t') is prepended at the beginning of
|
||||
the argument, and a line feed ('\n') is appended at the end. It is also
|
||||
possible to insert multiple lines at once using escape sequences '\n' and '\t'
|
||||
inside the string argument.
|
||||
|
||||
As HAProxy, HATerm may listen on several TCP/UDP addresses which can be
|
||||
provided by multiple "-L" options. To be functional, it needs at least one
|
||||
correct "-L" option to be set.
|
||||
|
||||
Examples:
|
||||
|
||||
$ ./haterm -L 127.0.0.1:8888 # listen on 127.0.0.1:8888 TCP address
|
||||
|
||||
$ ./haterm -L 127.0.0.1:8888:8889 # listen on 127.0.0.1:8888 TCP address,
|
||||
# 127.0.01:8889 SSL/TCP address,
|
||||
# and 127.0.01:8889 QUIC/UDP address
|
||||
|
||||
$ ./haterm -L 127.0.0.1:8888:8889 -L [::1]:8888:8889
|
||||
|
||||
With USE_QUIC_OPENSSL_COMPAT support, the user must configure a global
|
||||
section as for HAProxy. HATerm sets internally its configuration in.
|
||||
memory as this is done by HAProxy from configuration files:
|
||||
|
||||
$ ./haterm -L 127.0.0.1:8888:8889
|
||||
[NOTICE] (1371578) : haproxy version is 3.4-dev4-ba5eab-28
|
||||
[NOTICE] (1371578) : path to executable is ./haterm
|
||||
[ALERT] (1371578) : Binding [haterm cfgfile:12] for frontend
|
||||
___haterm_frontend___: this SSL library does not
|
||||
support the QUIC protocol. A limited compatibility
|
||||
layer may be enabled using the "limited-quic" global
|
||||
option if desired.
|
||||
|
||||
Such an alert may be fixed with "-G' option:
|
||||
|
||||
$ ./haterm -L 127.0.0.1:8888:8889 -G "limited-quic"
|
||||
|
||||
|
||||
When the SSL support is not compiled in, the second port is ignored. This is
|
||||
also the case for the QUIC support.
|
||||
|
||||
HATerm adjusts its responses depending on the requests it receives. An empty
|
||||
query string provides the information about how the URIs are understood by
|
||||
HATerm:
|
||||
|
||||
$ curl http://127.0.0.1:8888/?
|
||||
HAProxy's dummy HTTP server for benchmarks - version 3.4-dev4.
|
||||
All integer argument values are in the form [digits]*[kmgr] (r=random(0..1))
|
||||
The following arguments are supported to override the default objects :
|
||||
- /?s=<size> return <size> bytes.
|
||||
E.g. /?s=20k
|
||||
- /?r=<retcode> present <retcode> as the HTTP return code.
|
||||
E.g. /?r=404
|
||||
- /?c=<cache> set the return as not cacheable if <1.
|
||||
E.g. /?c=0
|
||||
- /?A=<req-after> drain the request body after sending the response.
|
||||
E.g. /?A=1
|
||||
- /?C=<close> force the response to use close if >0.
|
||||
E.g. /?C=1
|
||||
- /?K=<keep-alive> force the response to use keep-alive if >0.
|
||||
E.g. /?K=1
|
||||
- /?t=<time> wait <time> milliseconds before responding.
|
||||
E.g. /?t=500
|
||||
- /?k=<enable> Enable transfer encoding chunked with only one chunk
|
||||
if >0.
|
||||
- /?R=<enable> Enable sending random data if >0.
|
||||
|
||||
Note that those arguments may be cumulated on one line separated by a set of
|
||||
delimitors among [&?,;/] :
|
||||
- GET /?s=20k&c=1&t=700&K=30r HTTP/1.0
|
||||
- GET /?r=500?s=0?c=0?t=1000 HTTP/1.0
|
||||
|
||||
|
|
@ -539,22 +539,10 @@ message. These functions are used by HTX analyzers or by multiplexers.
|
|||
with the first block not removed, or NULL if everything was removed, and
|
||||
the amount of data drained.
|
||||
|
||||
- htx_xfer() transfers HTX blocks from an HTX message to another, stopping
|
||||
when a specific amount of bytes, including meta-data, was copied. If the
|
||||
tail block is a DATA block, it may be partially copied. All other block
|
||||
are transferred at once. By default, copied blocks are removed from the
|
||||
original HTX message and headers and trailers parts cannot be partially
|
||||
copied. But flags can be set to change the default behavior:
|
||||
|
||||
- HTX_XFER_KEEP_SRC_BLKS: source blocks are not removed
|
||||
- HTX_XFER_PARTIAL_HDRS_COPY: partial headers and trailers
|
||||
part can be xferred
|
||||
- HTX_XFER_HDRS_ONLY: Only the headers part is xferred
|
||||
|
||||
- htx_xfer_blks() [DEPRECATED] transfers HTX blocks from an HTX message to
|
||||
another, stopping after the first block of a specified type is transferred
|
||||
or when a specific amount of bytes, including meta-data, was moved. If the
|
||||
tail block is a DATA block, it may be partially moved. All other block are
|
||||
- htx_xfer_blks() transfers HTX blocks from an HTX message to another,
|
||||
stopping after the first block of a specified type is transferred or when
|
||||
a specific amount of bytes, including meta-data, was moved. If the tail
|
||||
block is a DATA block, it may be partially moved. All other block are
|
||||
transferred at once or kept. This function returns a mixed value, with the
|
||||
last block moved, or NULL if nothing was moved, and the amount of data
|
||||
transferred. When HEADERS or TRAILERS blocks must be transferred, this
|
||||
|
|
|
|||
|
|
@ -208,38 +208,3 @@ starts with -st to achieve a hard stop on the previous worker.
|
|||
Version 3.0 got rid of the libsystemd dependencies for sd_notify() after the
|
||||
events of xz/openssh, the function is now implemented directly in haproxy in
|
||||
src/systemd.c.
|
||||
|
||||
### mworker V3
|
||||
|
||||
This version was implemented with HAProxy 3.1, the goal was to stop parsing and
|
||||
applying the configuration in the master process.
|
||||
|
||||
One of the caveats of the previous implementation was that the parser could take
|
||||
a lot of time, and the master process would be stuck in the parser instead of
|
||||
handling its polling loop, signals etc. Some parts of the configuration parsing
|
||||
could also be less reliable with third-party code (EXTRA_OBJS), it could, for
|
||||
example, allow opening FDs and not closing them before the reload which
|
||||
would crash the master after a few reloads.
|
||||
|
||||
The startup of the master-worker was reorganized this way:
|
||||
|
||||
- the "discovery" mode, which is a lighter configuration parsing step, only
|
||||
applies the configuration which need to be effective for the master process.
|
||||
For example, "master-worker", "mworker-max-reloads" and less than 20 other
|
||||
keywords that are identified by KWF_DISCOVERY in the code. It is really fast
|
||||
as it don't need all the configuration to be applied in the master process.
|
||||
|
||||
- the master will then fork a worker, with a PROC_O_INIT flag. This worker has
|
||||
a temporary sockpair connected to the master CLI. Once the worker is forked,
|
||||
the master initializes its configuration and starts its polling loop.
|
||||
|
||||
- The newly forked worker will try to parse the configuration, which could
|
||||
result in a failure (exit 1), or any bad error code. In case of success, the
|
||||
worker will send a "READY" message to the master CLI then close this FD. At
|
||||
this step everything was initialized and the worker can enter its polling
|
||||
loop.
|
||||
|
||||
- The master then waits for the worker, it could:
|
||||
* receive the READY message over the mCLI, resulting in a successful loading
|
||||
of haproxy
|
||||
* receive a SIGCHLD, meaning the worker exited and couldn't load
|
||||
|
|
|
|||
|
|
@ -1,50 +0,0 @@
|
|||
2026-03-12 - thread execution context
|
||||
|
||||
Thread execution context (thread_exec_ctx) is a combination of type and pointer
|
||||
that are set in the current running thread at th_ctx->exec_ctx when entering
|
||||
certain processing (tasks, sample fetch functions, actions, CLI keywords etc).
|
||||
They're refined along execution, so that a task such as process_stream could
|
||||
temporarily switch to a converter while evaluating an expression and switch
|
||||
back to process_stream. They are reported in thread dumps and are mixed with
|
||||
caller locations for memory profiling. As such they are intentionally not too
|
||||
precise in order to avoid an explosion of the number of buckets. At the moment,
|
||||
the level of granularity it provides is sufficient to try to narrow a
|
||||
misbehaving origin down to a list of keywords. The context types can currently
|
||||
be:
|
||||
|
||||
- something registered via an initcall, with the initcall's location
|
||||
- something registered via an ha_caller, with the caller's location
|
||||
- an explicit sample fetch / converter / action / CLI keyword list
|
||||
- an explicit function (mainly used for actions without keywords)
|
||||
- a task / tasklet (no distinction is made), using the ->process pointer
|
||||
- a filter (e.g. compression), via flt_conf, reporting name
|
||||
- a mux (via the mux_ops, reporting the name)
|
||||
- an applet (e.g. cache, stats, CLI)
|
||||
|
||||
A macro EXEC_CTX_MAKE(type, pointer) makes a thread_exec_ctx from such
|
||||
values.
|
||||
|
||||
A macro EXEC_CTX_NO_RET(ctx, statement) calls a void statement under the
|
||||
specified context.
|
||||
|
||||
A macro EXEC_CTX_WITH_RET(ctx, expr) calls an expression under the specified
|
||||
context.
|
||||
|
||||
Most locations were modified to directly use these macros on the fly, by
|
||||
retrieving the context from where it was set on the element being evaluated
|
||||
(e.g. an action rule contains the context inherited by the action keyword
|
||||
that was used to create it).
|
||||
|
||||
In tools.c, chunk_append_thread_ctx() tries to decode the given exec_ctx and
|
||||
appends it into the provided buffer. It's used by ha_thread_dump_one() and
|
||||
cli_io_handler_show_activity() for memory profiling. In this latter case,
|
||||
the detected thread_ctx are reported in the output under brackets prefixed
|
||||
with "[via ...]" to distinguish call paths to the same allocators.
|
||||
|
||||
A good way to test if a context is properly reported is to place a bleeding
|
||||
malloc() call into one of the monitored functions, e.g.:
|
||||
|
||||
DISGUISE(malloc(8));
|
||||
|
||||
and issue "show profiling memory" after stressing the function. Its context
|
||||
must appear on the right with the number of calls.
|
||||
|
|
@ -1725,27 +1725,6 @@ add acl [@<ver>] <acl> <pattern>
|
|||
This command cannot be used if the reference <acl> is a name also used with
|
||||
a map. In this case, the "add map" command must be used instead.
|
||||
|
||||
add backend <name> from <defproxy> [mode <mode>] [guid <guid>] [ EXPERIMENTAL ]
|
||||
Instantiate a new backend proxy with the name <name>.
|
||||
|
||||
Only TCP or HTTP proxies can be created. All of the settings are inherited
|
||||
from <defproxy> default proxy instance. By default, it is mandatory to
|
||||
specify the backend mode via the argument of the same name, unless <defproxy>
|
||||
already defines it explicitely. It is also possible to use an optional GUID
|
||||
argument if wanted.
|
||||
|
||||
Servers can be added via the command "add server". The backend is initialized
|
||||
in the unpublished state. Once considered ready for traffic, use "publish
|
||||
backend" to expose the newly created instance.
|
||||
|
||||
All named default proxies can be used, given that they validate the same
|
||||
inheritance rules applied during configuration parsing. There is some
|
||||
exceptions though, for example when the mode is neither TCP nor HTTP.
|
||||
|
||||
This command is restricted and can only be issued on sockets configured for
|
||||
level "admin". Moreover, this feature is still considered in development so it
|
||||
also requires experimental mode (see "experimental-mode on").
|
||||
|
||||
add map [@<ver>] <map> <key> <value>
|
||||
add map [@<ver>] <map> <payload>
|
||||
Add an entry into the map <map> to associate the value <value> to the key
|
||||
|
|
@ -2121,30 +2100,6 @@ del acl <acl> [<key>|#<ref>]
|
|||
listing the content of the acl. Note that if the reference <acl> is a name and
|
||||
is shared with a map, the entry will be also deleted in the map.
|
||||
|
||||
del backend <name>
|
||||
Removes the backend proxy with the name <name>.
|
||||
|
||||
This operation is only possible for TCP or HTTP proxies. To succeed, the
|
||||
backend instance must have been first unpublished. Also, all of its servers
|
||||
must first be removed (via "del server" CLI). Finally, no stream must still
|
||||
be attached to the backend instance.
|
||||
|
||||
There is additional restrictions which prevent backend removal. First, a
|
||||
backend cannot be removed if it is explicitely referenced by config elements,
|
||||
for example via a use_backend rule or in sample expressions. Some proxies
|
||||
options are also incompatible with runtime deletion. Currently, this is the
|
||||
case when deprecated dispatch or option transparent are used. Also, a backend
|
||||
cannot be removed if there is a stick-table declared in it. Finally, it is
|
||||
impossible for now to remove a backend if QUIC servers were present in it.
|
||||
|
||||
It can be useful to use "wait be-removable" prior to this command to check
|
||||
for the aformentioned requisites. This also provides a methode to wait for
|
||||
the final closure of the streams attached to the target backend.
|
||||
|
||||
This command is restricted and can only be issued on sockets configured for
|
||||
level "admin". Moreover, this feature is still considered in development so it
|
||||
also requires experimental mode (see "experimental-mode on").
|
||||
|
||||
del map <map> [<key>|#<ref>]
|
||||
Delete all the map entries from the map <map> corresponding to the key <key>.
|
||||
<map> is the #<id> or the <name> returned by "show map". If the <ref> is used,
|
||||
|
|
@ -2579,8 +2534,7 @@ set maxconn global <maxconn>
|
|||
delayed until the threshold is reached. A value of zero restores the initial
|
||||
setting.
|
||||
|
||||
set profiling memory { on | off }
|
||||
set profiling tasks { auto | on | off | lock | no-lock | memory | no-memory }
|
||||
set profiling { tasks | memory } { auto | on | off }
|
||||
Enables or disables CPU or memory profiling for the indicated subsystem. This
|
||||
is equivalent to setting or clearing the "profiling" settings in the "global"
|
||||
section of the configuration file. Please also see "show profiling". Note
|
||||
|
|
@ -2590,13 +2544,6 @@ set profiling tasks { auto | on | off | lock | no-lock | memory | no-memory }
|
|||
on the linux-glibc target), and requires USE_MEMORY_PROFILING to be set at
|
||||
compile time.
|
||||
|
||||
. For tasks profiling, it is possible to enable or disable the collection of
|
||||
per-task lock and memory timings at runtime, but the change is only taken
|
||||
into account next time the profiler switches from off/auto to on (either
|
||||
automatically or manually). Thus when using "no-lock" to disable per-task
|
||||
lock profiling and save CPU cycles, it is recommended to flip the task
|
||||
profiling off then on to commit the change.
|
||||
|
||||
set rate-limit connections global <value>
|
||||
Change the process-wide connection rate limit, which is set by the global
|
||||
'maxconnrate' setting. A value of zero disables the limitation. This limit
|
||||
|
|
@ -3356,7 +3303,7 @@ show pools [byname|bysize|byusage] [detailed] [match <pfx>] [<nb>]
|
|||
- Pool quic_conn_c (152 bytes) : 1337 allocated (203224 bytes), ...
|
||||
Total: 15 pools, 109578176 bytes allocated, 109578176 used ...
|
||||
|
||||
show profiling [{all | status | tasks | memory}] [byaddr|bytime|byctx|aggr|<max_lines>]*
|
||||
show profiling [{all | status | tasks | memory}] [byaddr|bytime|aggr|<max_lines>]*
|
||||
Dumps the current profiling settings, one per line, as well as the command
|
||||
needed to change them. When tasks profiling is enabled, some per-function
|
||||
statistics collected by the scheduler will also be emitted, with a summary
|
||||
|
|
@ -3365,15 +3312,14 @@ show profiling [{all | status | tasks | memory}] [byaddr|bytime|byctx|aggr|<max_
|
|||
allocations/releases and their sizes will be reported. It is possible to
|
||||
limit the dump to only the profiling status, the tasks, or the memory
|
||||
profiling by specifying the respective keywords; by default all profiling
|
||||
information are dumped. It is also possible to limit the number of lines of
|
||||
information are dumped. It is also possible to limit the number of lines
|
||||
of output of each category by specifying a numeric limit. If is possible to
|
||||
request that the output is sorted by address, by total execution time, or by
|
||||
calling context instead of usage, e.g. to ease comparisons between subsequent
|
||||
calls or to check what needs to be optimized, and to aggregate task activity
|
||||
by called function instead of seeing the details. Please note that profiling
|
||||
is essentially aimed at developers since it gives hints about where CPU
|
||||
cycles or memory are wasted in the code. There is nothing useful to monitor
|
||||
there.
|
||||
request that the output is sorted by address or by total execution time
|
||||
instead of usage, e.g. to ease comparisons between subsequent calls or to
|
||||
check what needs to be optimized, and to aggregate task activity by called
|
||||
function instead of seeing the details. Please note that profiling is
|
||||
essentially aimed at developers since it gives hints about where CPU cycles
|
||||
or memory are wasted in the code. There is nothing useful to monitor there.
|
||||
|
||||
show resolvers [<resolvers section id>]
|
||||
Dump statistics for the given resolvers section, or all resolvers sections
|
||||
|
|
@ -4548,13 +4494,6 @@ wait { -h | <delay> } [<condition> [<args>...]]
|
|||
specified condition to be satisfied, to unrecoverably fail, or to remain
|
||||
unsatisfied for the whole <delay> duration. The supported conditions are:
|
||||
|
||||
- be-removable <proxy> : this will wait for the specified proxy backend to be
|
||||
removable by the "del backend" command. Some conditions will never be
|
||||
accepted (e.g. backend not yet unpublished or with servers in it) and will
|
||||
cause the report of a specific error message indicating what condition is
|
||||
not met. If everything is OK before the delay, a success is returned and
|
||||
the operation is terminated.
|
||||
|
||||
- srv-removable <proxy>/<server> : this will wait for the specified server to
|
||||
be removable by the "del server" command, i.e. be in maintenance and no
|
||||
longer have any connection on it (neither active or idle). Some conditions
|
||||
|
|
|
|||
|
|
@ -627,10 +627,7 @@ For the type PP2_TYPE_SSL, the value is itself a defined like this :
|
|||
uint8_t client;
|
||||
uint32_t verify;
|
||||
struct pp2_tlv sub_tlv[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
Note the "packed" attribute which indicates that each field starts immediately
|
||||
after the previous one (i.e. without type-specific alignment nor padding).
|
||||
};
|
||||
|
||||
The <verify> field will be zero if the client presented a certificate
|
||||
and it was successfully verified, and non-zero otherwise.
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@ struct acme_auth {
|
|||
struct ist auth; /* auth URI */
|
||||
struct ist chall; /* challenge URI */
|
||||
struct ist token; /* token */
|
||||
int validated; /* already validated */
|
||||
int ready; /* is the challenge ready ? */
|
||||
void *next;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -102,10 +102,7 @@ enum act_name {
|
|||
|
||||
/* Timeout name valid for a set-timeout rule */
|
||||
enum act_timeout_name {
|
||||
ACT_TIMEOUT_CONNECT,
|
||||
ACT_TIMEOUT_SERVER,
|
||||
ACT_TIMEOUT_QUEUE,
|
||||
ACT_TIMEOUT_TARPIT,
|
||||
ACT_TIMEOUT_TUNNEL,
|
||||
ACT_TIMEOUT_CLIENT,
|
||||
};
|
||||
|
|
@ -198,11 +195,6 @@ struct act_rule {
|
|||
struct server *srv; /* target server to attach the connection */
|
||||
struct sample_expr *name; /* used to differentiate idle connections */
|
||||
} attach_srv; /* 'attach-srv' rule */
|
||||
struct {
|
||||
enum log_orig_id orig;
|
||||
char *profile_name;
|
||||
struct log_profile *profile;
|
||||
} do_log; /* 'do-log' action */
|
||||
struct {
|
||||
int value;
|
||||
struct sample_expr *expr;
|
||||
|
|
@ -211,7 +203,6 @@ struct act_rule {
|
|||
void *p[4];
|
||||
} act; /* generic pointers to be used by custom actions */
|
||||
} arg; /* arguments used by some actions */
|
||||
struct thread_exec_ctx exec_ctx; /* execution context */
|
||||
struct {
|
||||
char *file; /* file name where the rule appears (or NULL) */
|
||||
int line; /* line number where the rule appears */
|
||||
|
|
@ -223,9 +214,7 @@ struct action_kw {
|
|||
enum act_parse_ret (*parse)(const char **args, int *cur_arg, struct proxy *px,
|
||||
struct act_rule *rule, char **err);
|
||||
int flags;
|
||||
/* 4 bytes here */
|
||||
void *private;
|
||||
struct thread_exec_ctx exec_ctx; /* execution context */
|
||||
};
|
||||
|
||||
struct action_kw_list {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ int act_resolution_cb(struct resolv_requester *requester, struct dns_counters *c
|
|||
int act_resolution_error_cb(struct resolv_requester *requester, int error_code);
|
||||
const char *action_suggest(const char *word, const struct list *keywords, const char **extra);
|
||||
void free_act_rule(struct act_rule *rule);
|
||||
void act_add_list(struct list *head, struct action_kw_list *kw_list);
|
||||
|
||||
static inline struct action_kw *action_lookup(struct list *keywords, const char *kw)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#include <haproxy/api-t.h>
|
||||
#include <haproxy/freq_ctr-t.h>
|
||||
#include <haproxy/tinfo-t.h>
|
||||
|
||||
/* bit fields for the "profiling" global variable */
|
||||
#define HA_PROF_TASKS_OFF 0x00000000 /* per-task CPU profiling forced disabled */
|
||||
|
|
@ -34,8 +33,6 @@
|
|||
#define HA_PROF_TASKS_MASK 0x00000003 /* per-task CPU profiling mask */
|
||||
|
||||
#define HA_PROF_MEMORY 0x00000004 /* memory profiling */
|
||||
#define HA_PROF_TASKS_MEM 0x00000008 /* per-task CPU profiling with memory */
|
||||
#define HA_PROF_TASKS_LOCK 0x00000010 /* per-task CPU profiling with locks */
|
||||
|
||||
|
||||
#ifdef USE_MEMORY_PROFILING
|
||||
|
|
@ -85,7 +82,6 @@ struct memprof_stats {
|
|||
unsigned long long alloc_tot;
|
||||
unsigned long long free_tot;
|
||||
void *info; // for pools, ptr to the pool
|
||||
struct thread_exec_ctx exec_ctx;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -130,7 +130,6 @@ struct appctx {
|
|||
int (*io_handler)(struct appctx *appctx); /* used within the cli_io_handler when st0 = CLI_ST_CALLBACK */
|
||||
void (*io_release)(struct appctx *appctx); /* used within the cli_io_handler when st0 = CLI_ST_CALLBACK,
|
||||
if the command is terminated or the session released */
|
||||
struct cli_kw *kw; /* the keyword being processed */
|
||||
} cli_ctx; /* context dedicated to the CLI applet */
|
||||
|
||||
struct buffer_wait buffer_wait; /* position in the list of objects waiting for a buffer */
|
||||
|
|
|
|||
|
|
@ -62,13 +62,6 @@ ssize_t applet_append_line(void *ctx, struct ist v1, struct ist v2, size_t ofs,
|
|||
static forceinline void applet_fl_set(struct appctx *appctx, uint on);
|
||||
static forceinline void applet_fl_clr(struct appctx *appctx, uint off);
|
||||
|
||||
/* macros to switch the calling context to the applet during a call. There's
|
||||
* one with a return value for most calls, and one without for the few like
|
||||
* fct(), shut(), or release() with no return.
|
||||
*/
|
||||
#define CALL_APPLET_WITH_RET(applet, func) EXEC_CTX_WITH_RET(EXEC_CTX_MAKE(TH_EX_CTX_APPLET, (applet)), (applet)->func)
|
||||
#define CALL_APPLET_NO_RET(applet, func) EXEC_CTX_NO_RET(EXEC_CTX_MAKE(TH_EX_CTX_APPLET, (applet)), (applet)->func)
|
||||
|
||||
|
||||
static forceinline uint appctx_app_test(const struct appctx *appctx, uint test)
|
||||
{
|
||||
|
|
@ -133,7 +126,7 @@ static inline int appctx_init(struct appctx *appctx)
|
|||
task_set_thread(appctx->t, tid);
|
||||
|
||||
if (appctx->applet->init)
|
||||
return CALL_APPLET_WITH_RET(appctx->applet, init(appctx));
|
||||
return appctx->applet->init(appctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -192,7 +192,6 @@ struct lbprm {
|
|||
void (*server_requeue)(struct server *); /* function used to place the server where it must be */
|
||||
void (*proxy_deinit)(struct proxy *); /* to be called when we're destroying the proxy */
|
||||
void (*server_deinit)(struct server *); /* to be called when we're destroying the server */
|
||||
int (*server_init)(struct server *); /* initialize a freshly added server (runtime); <0=fail. */
|
||||
};
|
||||
|
||||
#endif /* _HAPROXY_BACKEND_T_H */
|
||||
|
|
|
|||
|
|
@ -69,7 +69,6 @@ int backend_parse_balance(const char **args, char **err, struct proxy *curproxy)
|
|||
int tcp_persist_rdp_cookie(struct stream *s, struct channel *req, int an_bit);
|
||||
|
||||
int be_downtime(struct proxy *px);
|
||||
int be_supports_dynamic_srv(struct proxy *px, char **msg);
|
||||
void recount_servers(struct proxy *px);
|
||||
void update_backend_weight(struct proxy *px);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#include <haproxy/api-t.h>
|
||||
#include <haproxy/buf-t.h>
|
||||
#include <haproxy/filters-t.h>
|
||||
#include <haproxy/show_flags-t.h>
|
||||
|
||||
/* The CF_* macros designate Channel Flags, which may be ORed in the bit field
|
||||
|
|
@ -206,7 +205,6 @@ struct channel {
|
|||
unsigned char xfer_large; /* number of consecutive large xfers */
|
||||
unsigned char xfer_small; /* number of consecutive small xfers */
|
||||
int analyse_exp; /* expiration date for current analysers (if set) */
|
||||
struct chn_flt flt; /* current state of filters active on this channel */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -376,7 +376,6 @@ static inline void channel_add_input(struct channel *chn, unsigned int len)
|
|||
c_adv(chn, fwd);
|
||||
}
|
||||
/* notify that some data was read */
|
||||
chn_prod(chn)->bytes_in += len;
|
||||
chn->flags |= CF_READ_EVENT;
|
||||
}
|
||||
|
||||
|
|
@ -788,12 +787,8 @@ static inline int channel_recv_max(const struct channel *chn)
|
|||
*/
|
||||
static inline size_t channel_data_limit(const struct channel *chn)
|
||||
{
|
||||
size_t max = (global.tune.bufsize - global.tune.maxrewrite);
|
||||
|
||||
size_t max;
|
||||
|
||||
if (!c_size(chn))
|
||||
return 0;
|
||||
max = (c_size(chn) - global.tune.maxrewrite);
|
||||
if (IS_HTX_STRM(chn_strm(chn)))
|
||||
max -= HTX_BUF_OVERHEAD;
|
||||
return max;
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ enum chk_result {
|
|||
#define CHK_ST_FASTINTER 0x0400 /* force fastinter check */
|
||||
#define CHK_ST_READY 0x0800 /* check ready to migrate or run, see below */
|
||||
#define CHK_ST_SLEEPING 0x1000 /* check was sleeping, i.e. not currently bound to a thread, see below */
|
||||
#define CHK_ST_USE_SMALL_BUFF 0x2000 /* Use small buffers if possible for the request */
|
||||
|
||||
/* 4 possible states for CHK_ST_SLEEPING and CHK_ST_READY:
|
||||
* SLP RDY State Description
|
||||
|
|
@ -189,7 +188,6 @@ struct check {
|
|||
char **envp; /* the environment to use if running a process-based check */
|
||||
struct pid_list *curpid; /* entry in pid_list used for current process-based test, or -1 if not in test */
|
||||
struct sockaddr_storage addr; /* the address to check */
|
||||
struct protocol *proto; /* protocol used for check, may be different from the server's one */
|
||||
char *pool_conn_name; /* conn name used on reuse */
|
||||
char *sni; /* Server name */
|
||||
char *alpn_str; /* ALPN to use for checks */
|
||||
|
|
|
|||
|
|
@ -78,11 +78,12 @@ struct task *process_chk(struct task *t, void *context, unsigned int state);
|
|||
struct task *srv_chk_io_cb(struct task *t, void *ctx, unsigned int state);
|
||||
|
||||
int check_buf_available(void *target);
|
||||
struct buffer *check_get_buf(struct check *check, struct buffer *bptr, unsigned int small_buffer);
|
||||
struct buffer *check_get_buf(struct check *check, struct buffer *bptr);
|
||||
void check_release_buf(struct check *check, struct buffer *bptr);
|
||||
const char *init_check(struct check *check, int type);
|
||||
void free_check(struct check *check);
|
||||
void check_purge(struct check *check);
|
||||
int wake_srv_chk(struct stconn *sc);
|
||||
|
||||
int init_srv_check(struct server *srv);
|
||||
int init_srv_agent_check(struct server *srv);
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@
|
|||
|
||||
|
||||
extern struct pool_head *pool_head_trash;
|
||||
extern struct pool_head *pool_head_large_trash;
|
||||
extern struct pool_head *pool_head_small_trash;
|
||||
|
||||
/* function prototypes */
|
||||
|
||||
|
|
@ -48,10 +46,6 @@ int chunk_asciiencode(struct buffer *dst, struct buffer *src, char qc);
|
|||
int chunk_strcmp(const struct buffer *chk, const char *str);
|
||||
int chunk_strcasecmp(const struct buffer *chk, const char *str);
|
||||
struct buffer *get_trash_chunk(void);
|
||||
struct buffer *get_large_trash_chunk(void);
|
||||
struct buffer *get_small_trash_chunk(void);
|
||||
struct buffer *get_trash_chunk_sz(size_t size);
|
||||
struct buffer *get_larger_trash_chunk(struct buffer *chunk);
|
||||
int init_trash_buffers(int first);
|
||||
|
||||
static inline void chunk_reset(struct buffer *chk)
|
||||
|
|
@ -112,80 +106,12 @@ static forceinline struct buffer *alloc_trash_chunk(void)
|
|||
return chunk;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a large trash chunk from the reentrant pool. The buffer starts at
|
||||
* the end of the chunk. This chunk must be freed using free_trash_chunk(). This
|
||||
* call may fail and the caller is responsible for checking that the returned
|
||||
* pointer is not NULL.
|
||||
*/
|
||||
static forceinline struct buffer *alloc_large_trash_chunk(void)
|
||||
{
|
||||
struct buffer *chunk;
|
||||
|
||||
if (!pool_head_large_trash)
|
||||
return NULL;
|
||||
|
||||
chunk = pool_alloc(pool_head_large_trash);
|
||||
if (chunk) {
|
||||
char *buf = (char *)chunk + sizeof(struct buffer);
|
||||
*buf = 0;
|
||||
chunk_init(chunk, buf,
|
||||
pool_head_large_trash->size - sizeof(struct buffer));
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a small trash chunk from the reentrant pool. The buffer starts at
|
||||
* the end of the chunk. This chunk must be freed using free_trash_chunk(). This
|
||||
* call may fail and the caller is responsible for checking that the returned
|
||||
* pointer is not NULL.
|
||||
*/
|
||||
static forceinline struct buffer *alloc_small_trash_chunk(void)
|
||||
{
|
||||
struct buffer *chunk;
|
||||
|
||||
if (!pool_head_small_trash)
|
||||
return NULL;
|
||||
|
||||
chunk = pool_alloc(pool_head_small_trash);
|
||||
if (chunk) {
|
||||
char *buf = (char *)chunk + sizeof(struct buffer);
|
||||
*buf = 0;
|
||||
chunk_init(chunk, buf,
|
||||
pool_head_small_trash->size - sizeof(struct buffer));
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a trash chunk accordingly to the requested size. This chunk must be
|
||||
* freed using free_trash_chunk(). This call may fail and the caller is
|
||||
* responsible for checking that the returned pointer is not NULL.
|
||||
*/
|
||||
static forceinline struct buffer *alloc_trash_chunk_sz(size_t size)
|
||||
{
|
||||
if (pool_head_small_trash && size <= pool_head_small_trash->size)
|
||||
return alloc_small_trash_chunk();
|
||||
else if (size <= pool_head_trash->size)
|
||||
return alloc_trash_chunk();
|
||||
else if (pool_head_large_trash && size <= pool_head_large_trash->size)
|
||||
return alloc_large_trash_chunk();
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* free a trash chunk allocated by alloc_trash_chunk(). NOP on NULL.
|
||||
*/
|
||||
static forceinline void free_trash_chunk(struct buffer *chunk)
|
||||
{
|
||||
if (pool_head_small_trash && chunk && chunk->size == pool_head_small_trash->size - sizeof(struct buffer))
|
||||
pool_free(pool_head_small_trash, chunk);
|
||||
else if (pool_head_large_trash && chunk && chunk->size == pool_head_large_trash->size - sizeof(struct buffer))
|
||||
pool_free(pool_head_large_trash, chunk);
|
||||
else
|
||||
pool_free(pool_head_trash, chunk);
|
||||
pool_free(pool_head_trash, chunk);
|
||||
}
|
||||
|
||||
/* copies chunk <src> into <chk>. Returns 0 in case of failure. */
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
#define _HAPROXY_CLI_T_H
|
||||
|
||||
#include <haproxy/applet-t.h>
|
||||
#include <haproxy/tinfo-t.h>
|
||||
|
||||
/* Access level for a stats socket (appctx->cli_ctx.level) */
|
||||
#define ACCESS_LVL_NONE 0x0000
|
||||
|
|
@ -101,7 +100,6 @@ enum cli_wait_err {
|
|||
enum cli_wait_cond {
|
||||
CLI_WAIT_COND_NONE, // no condition to wait on
|
||||
CLI_WAIT_COND_SRV_UNUSED,// wait for server to become unused
|
||||
CLI_WAIT_COND_BE_UNUSED, // wait for backend to become unused
|
||||
};
|
||||
|
||||
struct cli_wait_ctx {
|
||||
|
|
@ -121,8 +119,6 @@ struct cli_kw {
|
|||
void (*io_release)(struct appctx *appctx);
|
||||
void *private;
|
||||
int level; /* this is the level needed to show the keyword usage and to use it */
|
||||
/* 4-byte hole here */
|
||||
struct thread_exec_ctx exec_ctx; /* execution context */
|
||||
};
|
||||
|
||||
struct cli_kw_list {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include <haproxy/listener-t.h>
|
||||
#include <haproxy/obj_type.h>
|
||||
#include <haproxy/pool-t.h>
|
||||
#include <haproxy/protocol.h>
|
||||
#include <haproxy/server.h>
|
||||
#include <haproxy/session-t.h>
|
||||
#include <haproxy/task-t.h>
|
||||
|
|
@ -50,13 +49,6 @@ extern struct mux_stopping_data mux_stopping_data[MAX_THREADS];
|
|||
|
||||
#define IS_HTX_CONN(conn) ((conn)->mux && ((conn)->mux->flags & MX_FL_HTX))
|
||||
|
||||
/* macros to switch the calling context to the mux during a call. There's one
|
||||
* with a return value for most calls, and one without for the few like shut(),
|
||||
* detach() or destroy() with no return.
|
||||
*/
|
||||
#define CALL_MUX_WITH_RET(mux, func) EXEC_CTX_WITH_RET(EXEC_CTX_MAKE(TH_EX_CTX_MUX, (mux)), (mux)->func)
|
||||
#define CALL_MUX_NO_RET(mux, func) EXEC_CTX_NO_RET(EXEC_CTX_MAKE(TH_EX_CTX_MUX, (mux)), (mux)->func)
|
||||
|
||||
/* receive a PROXY protocol header over a connection */
|
||||
int conn_recv_proxy(struct connection *conn, int flag);
|
||||
int conn_send_proxy(struct connection *conn, unsigned int flag);
|
||||
|
|
@ -488,7 +480,7 @@ static inline int conn_install_mux(struct connection *conn, const struct mux_ops
|
|||
|
||||
conn->mux = mux;
|
||||
conn->ctx = ctx;
|
||||
ret = mux->init ? CALL_MUX_WITH_RET(mux, init(conn, prx, sess, &BUF_NULL)) : 0;
|
||||
ret = mux->init ? mux->init(conn, prx, sess, &BUF_NULL) : 0;
|
||||
if (ret < 0) {
|
||||
conn->mux = NULL;
|
||||
conn->ctx = NULL;
|
||||
|
|
@ -610,13 +602,13 @@ void list_mux_proto(FILE *out);
|
|||
*/
|
||||
static inline const struct mux_proto_list *conn_get_best_mux_entry(
|
||||
const struct ist mux_proto,
|
||||
int proto_side, int proto_is_quic, int proto_mode)
|
||||
int proto_side, int proto_mode)
|
||||
{
|
||||
struct mux_proto_list *item;
|
||||
struct mux_proto_list *fallback = NULL;
|
||||
|
||||
list_for_each_entry(item, &mux_proto_list.list, list) {
|
||||
if (!(item->side & proto_side) || !(item->mode & proto_mode) || (proto_is_quic && !(item->mux->flags & MX_FL_FRAMED)))
|
||||
if (!(item->side & proto_side) || !(item->mode & proto_mode))
|
||||
continue;
|
||||
if (istlen(mux_proto) && isteq(mux_proto, item->token))
|
||||
return item;
|
||||
|
|
@ -641,7 +633,7 @@ static inline const struct mux_ops *conn_get_best_mux(struct connection *conn,
|
|||
{
|
||||
const struct mux_proto_list *item;
|
||||
|
||||
item = conn_get_best_mux_entry(mux_proto, proto_side, proto_is_quic(conn->ctrl), proto_mode);
|
||||
item = conn_get_best_mux_entry(mux_proto, proto_side, proto_mode);
|
||||
|
||||
return item ? item->mux : NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,29 +185,6 @@ struct be_counters {
|
|||
} p; /* protocol-specific stats */
|
||||
};
|
||||
|
||||
/* extra counters that are registered at boot by various modules */
|
||||
enum counters_type {
|
||||
COUNTERS_FE = 0,
|
||||
COUNTERS_BE,
|
||||
COUNTERS_SV,
|
||||
COUNTERS_LI,
|
||||
COUNTERS_RSLV,
|
||||
|
||||
COUNTERS_OFF_END /* must always be last */
|
||||
};
|
||||
|
||||
struct extra_counters {
|
||||
char **datap; /* points to pointer to heap containing counters allocated in a linear fashion */
|
||||
size_t size; /* size of allocated data */
|
||||
size_t tgrp_step; /* distance in words between two datap for consecutive tgroups, 0 for single */
|
||||
uint nbtgrp; /* number of thread groups accessing these counters */
|
||||
enum counters_type type; /* type of object containing the counters */
|
||||
};
|
||||
|
||||
|
||||
#define EXTRA_COUNTERS(name) \
|
||||
struct extra_counters *name
|
||||
|
||||
#endif /* _HAPROXY_COUNTERS_T_H */
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -26,9 +26,6 @@
|
|||
|
||||
#include <haproxy/counters-t.h>
|
||||
#include <haproxy/guid-t.h>
|
||||
#include <haproxy/global.h>
|
||||
|
||||
extern THREAD_LOCAL void *trash_counters;
|
||||
|
||||
int counters_fe_shared_prepare(struct fe_counters_shared *counters, const struct guid_node *guid, char **errmsg);
|
||||
int counters_be_shared_prepare(struct be_counters_shared *counters, const struct guid_node *guid, char **errmsg);
|
||||
|
|
@ -104,106 +101,4 @@ void counters_be_shared_drop(struct be_counters_shared *counters);
|
|||
__ret; \
|
||||
})
|
||||
|
||||
#define COUNTERS_UPDATE_MAX(counter, count) \
|
||||
do { \
|
||||
if (!(global.tune.options & GTUNE_NO_MAX_COUNTER)) \
|
||||
HA_ATOMIC_UPDATE_MAX(counter, count); \
|
||||
} while (0)
|
||||
|
||||
/* Manipulation of extra_counters, for boot-time registrable modules */
|
||||
/* retrieve the base storage of extra counters (first tgroup if any) */
|
||||
#define EXTRA_COUNTERS_BASE(counters, mod) \
|
||||
(likely(counters) ? \
|
||||
((void *)(*(counters)->datap + (mod)->counters_off[(counters)->type])) : \
|
||||
(trash_counters))
|
||||
|
||||
/* retrieve the pointer to the extra counters storage for module <mod> for the
|
||||
* current TGID.
|
||||
*/
|
||||
#define EXTRA_COUNTERS_GET(counters, mod) \
|
||||
(likely(counters) ? \
|
||||
((void *)(counters)->datap[(counters)->tgrp_step * (tgid - 1)] + \
|
||||
(mod)->counters_off[(counters)->type]) : \
|
||||
(trash_counters))
|
||||
|
||||
#define EXTRA_COUNTERS_REGISTER(counters, ctype, alloc_failed_label, storage, step) \
|
||||
do { \
|
||||
typeof(*counters) _ctr; \
|
||||
_ctr = calloc(1, sizeof(*_ctr)); \
|
||||
if (!_ctr) \
|
||||
goto alloc_failed_label; \
|
||||
_ctr->type = (ctype); \
|
||||
_ctr->tgrp_step = (step); \
|
||||
_ctr->datap = (storage); \
|
||||
*(counters) = _ctr; \
|
||||
} while (0)
|
||||
|
||||
#define EXTRA_COUNTERS_ADD(mod, counters, new_counters, csize) \
|
||||
do { \
|
||||
typeof(counters) _ctr = (counters); \
|
||||
(mod)->counters_off[_ctr->type] = _ctr->size; \
|
||||
_ctr->size += (csize); \
|
||||
} while (0)
|
||||
|
||||
#define EXTRA_COUNTERS_ALLOC(counters, alloc_failed_label, nbtg) \
|
||||
do { \
|
||||
typeof(counters) _ctr = (counters); \
|
||||
char **datap = _ctr->datap; \
|
||||
uint tgrp; \
|
||||
_ctr->nbtgrp = _ctr->tgrp_step ? (nbtg) : 1; \
|
||||
for (tgrp = 0; tgrp < _ctr->nbtgrp; tgrp++) { \
|
||||
*datap = malloc((_ctr)->size); \
|
||||
if (!*_ctr->datap) \
|
||||
goto alloc_failed_label; \
|
||||
datap += _ctr->tgrp_step; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define EXTRA_COUNTERS_INIT(counters, mod, init_counters, init_counters_size) \
|
||||
do { \
|
||||
typeof(counters) _ctr = (counters); \
|
||||
char **datap = _ctr->datap; \
|
||||
uint tgrp; \
|
||||
for (tgrp = 0; tgrp < _ctr->nbtgrp; tgrp++) { \
|
||||
memcpy(*datap + mod->counters_off[_ctr->type], \
|
||||
(init_counters), (init_counters_size)); \
|
||||
datap += _ctr->tgrp_step; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define EXTRA_COUNTERS_FREE(counters) \
|
||||
do { \
|
||||
typeof(counters) _ctr = (counters); \
|
||||
if (_ctr) { \
|
||||
char **datap = _ctr->datap; \
|
||||
uint tgrp; \
|
||||
for (tgrp = 0; tgrp < _ctr->nbtgrp; tgrp++) { \
|
||||
ha_free(datap); \
|
||||
datap += _ctr->tgrp_step; \
|
||||
} \
|
||||
free(_ctr); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* aggregate all values of <metricp> over the thread groups handled by
|
||||
* <counters>. <metricp> MUST correspond to an entry of the first tgrp of
|
||||
* <counters>. The number of groups and the step are found in <counters>. The
|
||||
* type of the return value is the same as <metricp>, and must be a scalar so
|
||||
* that values are summed before being returned.
|
||||
*/
|
||||
#define EXTRA_COUNTERS_AGGR(counters, metricp) \
|
||||
({ \
|
||||
typeof(counters) _ctr = (counters); \
|
||||
typeof(metricp) *valp, _ret = 0; \
|
||||
if (_ctr) { \
|
||||
size_t ofs = (char *)&metricp - _ctr->datap[0]; \
|
||||
uint tgrp; \
|
||||
for (tgrp = 0; tgrp < _ctr->nbtgrp; tgrp++) { \
|
||||
valp = (typeof(valp))(_ctr->datap[tgrp * (counters)->tgrp_step] + ofs); \
|
||||
_ret += HA_ATOMIC_LOAD(valp); \
|
||||
} \
|
||||
} \
|
||||
_ret; \
|
||||
})
|
||||
|
||||
#endif /* _HAPROXY_COUNTERS_H */
|
||||
|
|
|
|||
|
|
@ -536,11 +536,6 @@
|
|||
#define TIME_STATS_SAMPLES 512
|
||||
#endif
|
||||
|
||||
/* number of samples used to measure the load in the run queue */
|
||||
#ifndef RQ_LOAD_SAMPLES
|
||||
#define RQ_LOAD_SAMPLES 512
|
||||
#endif
|
||||
|
||||
/* max ocsp cert id asn1 encoded length */
|
||||
#ifndef OCSP_MAX_CERTID_ASN1_LENGTH
|
||||
#define OCSP_MAX_CERTID_ASN1_LENGTH 128
|
||||
|
|
@ -606,7 +601,7 @@
|
|||
* store stats.
|
||||
*/
|
||||
#ifndef MEMPROF_HASH_BITS
|
||||
# define MEMPROF_HASH_BITS 12
|
||||
# define MEMPROF_HASH_BITS 10
|
||||
#endif
|
||||
#define MEMPROF_HASH_BUCKETS (1U << MEMPROF_HASH_BITS)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,12 +24,12 @@
|
|||
|
||||
#include <import/ebtree-t.h>
|
||||
|
||||
#include <haproxy/buf-t.h>
|
||||
#include <haproxy/connection-t.h>
|
||||
#include <haproxy/counters-t.h>
|
||||
#include <haproxy/buf-t.h>
|
||||
#include <haproxy/dgram-t.h>
|
||||
#include <haproxy/dns_ring-t.h>
|
||||
#include <haproxy/obj_type-t.h>
|
||||
#include <haproxy/stats-t.h>
|
||||
#include <haproxy/task-t.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
|
|
@ -152,7 +152,6 @@ struct dns_nameserver {
|
|||
struct dns_stream_server *stream; /* used for tcp dns */
|
||||
|
||||
EXTRA_COUNTERS(extra_counters);
|
||||
char *extra_counters_storage; /* storage used for extra_counters above */
|
||||
struct dns_counters *counters;
|
||||
|
||||
struct list list; /* nameserver chained list */
|
||||
|
|
|
|||
|
|
@ -36,8 +36,6 @@
|
|||
#include <haproxy/pool.h>
|
||||
|
||||
extern struct pool_head *pool_head_buffer;
|
||||
extern struct pool_head *pool_head_large_buffer;
|
||||
extern struct pool_head *pool_head_small_buffer;
|
||||
|
||||
int init_buffer(void);
|
||||
void buffer_dump(FILE *o, struct buffer *b, int from, int to);
|
||||
|
|
@ -55,42 +53,6 @@ static inline int buffer_almost_full(const struct buffer *buf)
|
|||
return b_almost_full(buf);
|
||||
}
|
||||
|
||||
/* Return 1 if <sz> is the default buffer size */
|
||||
static inline int b_is_default_sz(size_t sz)
|
||||
{
|
||||
return (sz == pool_head_buffer->size);
|
||||
}
|
||||
|
||||
/* Return 1 if <sz> is the size of a large buffer (alwoys false is large buffers are not configured) */
|
||||
static inline int b_is_large_sz(size_t sz)
|
||||
{
|
||||
return (pool_head_large_buffer && sz == pool_head_large_buffer->size);
|
||||
}
|
||||
|
||||
/* Return 1 if <sz> is the size of a small buffer */
|
||||
static inline int b_is_small_sz(size_t sz)
|
||||
{
|
||||
return (pool_head_small_buffer && sz == pool_head_small_buffer->size);
|
||||
}
|
||||
|
||||
/* Return 1 if <bug> is a default buffer */
|
||||
static inline int b_is_default(struct buffer *buf)
|
||||
{
|
||||
return b_is_default_sz(b_size(buf));
|
||||
}
|
||||
|
||||
/* Return 1 if <buf> is a large buffer (alwoys 0 is large buffers are not configured) */
|
||||
static inline int b_is_large(struct buffer *buf)
|
||||
{
|
||||
return b_is_large_sz(b_size(buf));
|
||||
}
|
||||
|
||||
/* Return 1 if <buf> is a small buffer */
|
||||
static inline int b_is_small(struct buffer *buf)
|
||||
{
|
||||
return b_is_small_sz(b_size(buf));
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
/* Functions below are used for buffer allocation */
|
||||
/**************************************************/
|
||||
|
|
@ -174,20 +136,13 @@ static inline char *__b_get_emergency_buf(void)
|
|||
#define __b_free(_buf) \
|
||||
do { \
|
||||
char *area = (_buf)->area; \
|
||||
size_t sz = (_buf)->size; \
|
||||
\
|
||||
/* let's first clear the area to save an occasional "show sess all" \
|
||||
* glancing over our shoulder from getting a dangling pointer. \
|
||||
*/ \
|
||||
*(_buf) = BUF_NULL; \
|
||||
__ha_barrier_store(); \
|
||||
/* if enabled, large buffers are always strictly greater \
|
||||
* than the default buffers */ \
|
||||
if (unlikely(b_is_large_sz(sz))) \
|
||||
pool_free(pool_head_large_buffer, area); \
|
||||
else if (unlikely(b_is_small_sz(sz))) \
|
||||
pool_free(pool_head_small_buffer, area); \
|
||||
else if (th_ctx->emergency_bufs_left < global.tune.reserved_bufs) \
|
||||
if (th_ctx->emergency_bufs_left < global.tune.reserved_bufs) \
|
||||
th_ctx->emergency_bufs[th_ctx->emergency_bufs_left++] = area; \
|
||||
else \
|
||||
pool_free(pool_head_buffer, area); \
|
||||
|
|
@ -200,35 +155,6 @@ static inline char *__b_get_emergency_buf(void)
|
|||
__b_free((_buf)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
static inline struct buffer *b_alloc_small(struct buffer *buf)
|
||||
{
|
||||
char *area = NULL;
|
||||
|
||||
if (!buf->size) {
|
||||
area = pool_alloc(pool_head_small_buffer);
|
||||
if (!area)
|
||||
return NULL;
|
||||
buf->area = area;
|
||||
buf->size = global.tune.bufsize_small;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static inline struct buffer *b_alloc_large(struct buffer *buf)
|
||||
{
|
||||
char *area = NULL;
|
||||
|
||||
if (!buf->size) {
|
||||
area = pool_alloc(pool_head_large_buffer);
|
||||
if (!area)
|
||||
return NULL;
|
||||
buf->area = area;
|
||||
buf->size = global.tune.bufsize_large;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Offer one or multiple buffer currently belonging to target <from> to whoever
|
||||
* needs one. Any pointer is valid for <from>, including NULL. Its purpose is
|
||||
* to avoid passing a buffer to oneself in case of failed allocations (e.g.
|
||||
|
|
|
|||
|
|
@ -232,28 +232,22 @@ struct filter {
|
|||
* 0: request channel, 1: response channel */
|
||||
unsigned int pre_analyzers; /* bit field indicating analyzers to pre-process */
|
||||
unsigned int post_analyzers; /* bit field indicating analyzers to post-process */
|
||||
struct list list; /* Filter list for the stream */
|
||||
/* req_list and res_list are exactly equivalent, except the order may differ */
|
||||
struct list req_list; /* Filter list for request channel */
|
||||
struct list res_list; /* Filter list for response channel */
|
||||
struct list list; /* Next filter for the same proxy/stream */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure reprensenting the "global" state of filters attached to a stream.
|
||||
* Doesn't hold much information, as the channel themselves hold chn_flt struct
|
||||
* which contains the per-channel members.
|
||||
*/
|
||||
struct strm_flt {
|
||||
struct list filters; /* List of filters attached to a stream */
|
||||
struct filter *current[2]; /* From which filter resume processing, for a specific channel.
|
||||
* This is used for resumable callbacks only,
|
||||
* If NULL, we start from the first filter.
|
||||
* 0: request channel, 1: response channel */
|
||||
unsigned short flags; /* STRM_FL_* */
|
||||
};
|
||||
|
||||
/* structure holding filter state for some members that are channel oriented */
|
||||
struct chn_flt {
|
||||
struct list filters; /* List of filters attached to a channel */
|
||||
struct filter *current; /* From which filter resume processing, for a specific channel. */
|
||||
unsigned char nb_data_filters; /* Number of data filters registered on channel */
|
||||
unsigned long long offset;
|
||||
unsigned char nb_req_data_filters; /* Number of data filters registered on the request channel */
|
||||
unsigned char nb_rsp_data_filters; /* Number of data filters registered on the response channel */
|
||||
unsigned long long offset[2];
|
||||
};
|
||||
|
||||
#endif /* _HAPROXY_FILTERS_T_H */
|
||||
|
|
|
|||
|
|
@ -28,9 +28,7 @@
|
|||
#include <haproxy/stream-t.h>
|
||||
|
||||
extern const char *trace_flt_id;
|
||||
extern const char *http_comp_req_flt_id;
|
||||
extern const char *http_comp_res_flt_id;
|
||||
|
||||
extern const char *http_comp_flt_id;
|
||||
extern const char *cache_store_flt_id;
|
||||
extern const char *spoe_filter_id;
|
||||
extern const char *fcgi_flt_id;
|
||||
|
|
@ -42,13 +40,13 @@ extern const char *fcgi_flt_id;
|
|||
/* Useful macros to access per-channel values. It can be safely used inside
|
||||
* filters. */
|
||||
#define CHN_IDX(chn) (((chn)->flags & CF_ISRESP) == CF_ISRESP)
|
||||
#define FLT_STRM_OFF(s, chn) (chn->flt.offset)
|
||||
#define FLT_STRM_OFF(s, chn) (strm_flt(s)->offset[CHN_IDX(chn)])
|
||||
#define FLT_OFF(flt, chn) ((flt)->offset[CHN_IDX(chn)])
|
||||
|
||||
#define HAS_FILTERS(strm) ((strm)->strm_flt.flags & STRM_FLT_FL_HAS_FILTERS)
|
||||
|
||||
#define HAS_REQ_DATA_FILTERS(strm) ((strm)->req.flt.nb_data_filters != 0)
|
||||
#define HAS_RSP_DATA_FILTERS(strm) ((strm)->res.flt.nb_data_filters != 0)
|
||||
#define HAS_REQ_DATA_FILTERS(strm) ((strm)->strm_flt.nb_req_data_filters != 0)
|
||||
#define HAS_RSP_DATA_FILTERS(strm) ((strm)->strm_flt.nb_rsp_data_filters != 0)
|
||||
#define HAS_DATA_FILTERS(strm, chn) (((chn)->flags & CF_ISRESP) ? HAS_RSP_DATA_FILTERS(strm) : HAS_REQ_DATA_FILTERS(strm))
|
||||
|
||||
#define IS_REQ_DATA_FILTER(flt) ((flt)->flags & FLT_FL_IS_REQ_DATA_FILTER)
|
||||
|
|
@ -139,11 +137,14 @@ static inline void
|
|||
register_data_filter(struct stream *s, struct channel *chn, struct filter *filter)
|
||||
{
|
||||
if (!IS_DATA_FILTER(filter, chn)) {
|
||||
if (chn->flags & CF_ISRESP)
|
||||
if (chn->flags & CF_ISRESP) {
|
||||
filter->flags |= FLT_FL_IS_RSP_DATA_FILTER;
|
||||
else
|
||||
strm_flt(s)->nb_rsp_data_filters++;
|
||||
}
|
||||
else {
|
||||
filter->flags |= FLT_FL_IS_REQ_DATA_FILTER;
|
||||
chn->flt.nb_data_filters++;
|
||||
strm_flt(s)->nb_req_data_filters++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -152,66 +153,18 @@ static inline void
|
|||
unregister_data_filter(struct stream *s, struct channel *chn, struct filter *filter)
|
||||
{
|
||||
if (IS_DATA_FILTER(filter, chn)) {
|
||||
if (chn->flags & CF_ISRESP)
|
||||
if (chn->flags & CF_ISRESP) {
|
||||
filter->flags &= ~FLT_FL_IS_RSP_DATA_FILTER;
|
||||
else
|
||||
strm_flt(s)->nb_rsp_data_filters--;
|
||||
|
||||
}
|
||||
else {
|
||||
filter->flags &= ~FLT_FL_IS_REQ_DATA_FILTER;
|
||||
chn->flt.nb_data_filters--;
|
||||
strm_flt(s)->nb_req_data_filters--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* flt_list_start() and flt_list_next() can be used to iterate over the list of filters
|
||||
* for a given <strm> and <chn> combination. It will automatically choose the proper
|
||||
* list to iterate from depending on the context.
|
||||
*
|
||||
* flt_list_start() has to be called exactly once to get the first value from the list
|
||||
* to get the following values, use flt_list_next() until NULL is returned.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* struct filter *filter;
|
||||
*
|
||||
* for (filter = flt_list_start(stream, channel); filter;
|
||||
* filter = flt_list_next(stream, channel, filter)) {
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
static inline struct filter *flt_list_start(struct stream *strm, struct channel *chn)
|
||||
{
|
||||
struct filter *filter;
|
||||
|
||||
if (chn->flags & CF_ISRESP) {
|
||||
filter = LIST_NEXT(&chn->flt.filters, struct filter *, res_list);
|
||||
if (&filter->res_list == &chn->flt.filters)
|
||||
filter = NULL; /* empty list */
|
||||
}
|
||||
else {
|
||||
filter = LIST_NEXT(&chn->flt.filters, struct filter *, req_list);
|
||||
if (&filter->req_list == &chn->flt.filters)
|
||||
filter = NULL; /* empty list */
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
static inline struct filter *flt_list_next(struct stream *strm, struct channel *chn,
|
||||
struct filter *filter)
|
||||
{
|
||||
if (chn->flags & CF_ISRESP) {
|
||||
filter = LIST_NEXT(&filter->res_list, struct filter *, res_list);
|
||||
if (&filter->res_list == &chn->flt.filters)
|
||||
filter = NULL; /* end of list */
|
||||
}
|
||||
else {
|
||||
filter = LIST_NEXT(&filter->req_list, struct filter *, req_list);
|
||||
if (&filter->req_list == &chn->flt.filters)
|
||||
filter = NULL; /* end of list */
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
/* This function must be called when a filter alter payload data. It updates
|
||||
* offsets of all previous filters. Do not call this function when a filter
|
||||
* change the size of payload data leads to an undefined behavior.
|
||||
|
|
@ -224,8 +177,7 @@ flt_update_offsets(struct filter *filter, struct channel *chn, int len)
|
|||
struct stream *s = chn_strm(chn);
|
||||
struct filter *f;
|
||||
|
||||
for (f = flt_list_start(s, chn); f;
|
||||
f = flt_list_next(s, chn, f)) {
|
||||
list_for_each_entry(f, &strm_flt(s)->filters, list) {
|
||||
if (f == filter)
|
||||
break;
|
||||
FLT_OFF(f, chn) += len;
|
||||
|
|
|
|||
|
|
@ -403,25 +403,6 @@ static inline uint swrate_add_scaled_opportunistic(uint *sum, uint n, uint v, ui
|
|||
return new_sum;
|
||||
}
|
||||
|
||||
/* Like swrate_add() except that if <v> is beyond the current average, the
|
||||
* average is replaced by the peak. This is essentially used to measure peak
|
||||
* loads in the scheduler, reason why it is provided as a local variant that
|
||||
* does not involve atomic operations.
|
||||
*/
|
||||
static inline uint swrate_add_peak_local(uint *sum, uint n, uint v)
|
||||
{
|
||||
uint old_sum, new_sum;
|
||||
|
||||
old_sum = *sum;
|
||||
if (v * n > old_sum)
|
||||
new_sum = v * n;
|
||||
else
|
||||
new_sum = old_sum - (old_sum + n - 1) / n + v;
|
||||
|
||||
*sum = new_sum;
|
||||
return new_sum;
|
||||
}
|
||||
|
||||
/* Returns the average sample value for the sum <sum> over a sliding window of
|
||||
* <n> samples. Better if <n> is a power of two. It must be the same <n> as the
|
||||
* one used above in all additions.
|
||||
|
|
|
|||
|
|
@ -79,14 +79,13 @@
|
|||
#define GTUNE_DISABLE_H2_WEBSOCKET (1<<21)
|
||||
#define GTUNE_DISABLE_ACTIVE_CLOSE (1<<22)
|
||||
#define GTUNE_QUICK_EXIT (1<<23)
|
||||
#define GTUNE_COLLECT_LIBS (1<<24)
|
||||
/* (1<<24) unused */
|
||||
/* (1<<25) unused */
|
||||
#define GTUNE_USE_FAST_FWD (1<<26)
|
||||
#define GTUNE_LISTENER_MQ_FAIR (1<<27)
|
||||
#define GTUNE_LISTENER_MQ_OPT (1<<28)
|
||||
#define GTUNE_LISTENER_MQ_ANY (GTUNE_LISTENER_MQ_FAIR | GTUNE_LISTENER_MQ_OPT)
|
||||
#define GTUNE_NO_KTLS (1<<29)
|
||||
#define GTUNE_NO_MAX_COUNTER (1<<30)
|
||||
|
||||
/* subsystem-specific debugging options for tune.debug */
|
||||
#define GDBG_CPU_AFFINITY (1U<< 0)
|
||||
|
|
@ -180,7 +179,6 @@ struct global {
|
|||
uint recv_enough; /* how many input bytes at once are "enough" */
|
||||
uint bufsize; /* buffer size in bytes, defaults to BUFSIZE */
|
||||
uint bufsize_small;/* small buffer size in bytes */
|
||||
uint bufsize_large;/* large buffer size in bytes */
|
||||
int maxrewrite; /* buffer max rewrite size in bytes, defaults to MAXREWRITE */
|
||||
int reserved_bufs; /* how many buffers can only be allocated for response */
|
||||
int buf_limit; /* if not null, how many total buffers may only be allocated */
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#include <haproxy/api-t.h>
|
||||
#include <haproxy/global-t.h>
|
||||
#include <haproxy/cfgparse.h>
|
||||
|
||||
extern struct global global;
|
||||
extern int pid; /* current process id */
|
||||
|
|
@ -55,12 +54,6 @@ extern char **old_argv;
|
|||
extern const char *old_unixsocket;
|
||||
extern int daemon_fd[2];
|
||||
extern int devnullfd;
|
||||
extern int fileless_mode;
|
||||
extern struct cfgfile fileless_cfg;
|
||||
|
||||
/* storage for collected libs */
|
||||
extern void *lib_storage;
|
||||
extern size_t lib_size;
|
||||
|
||||
struct proxy;
|
||||
struct server;
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ enum h1m_state {
|
|||
#define H1_MF_TE_CHUNKED 0x00010000 // T-E "chunked"
|
||||
#define H1_MF_TE_OTHER 0x00020000 // T-E other than supported ones found (only "chunked" is supported for now)
|
||||
#define H1_MF_UPG_H2C 0x00040000 // "h2c" or "h2" used as upgrade token
|
||||
#define H1_MF_NOT_HTTP 0x00080000 // Not an HTTP message (e.g "RTSP", only possible if invalid message are accepted)
|
||||
|
||||
/* Mask to use to reset H1M flags when we restart headers parsing.
|
||||
*
|
||||
* WARNING: Don't forget to update it if a new flag must be preserved when
|
||||
|
|
|
|||
|
|
@ -222,7 +222,6 @@ struct hlua_proxy_list {
|
|||
};
|
||||
|
||||
struct hlua_proxy_list_iterator_context {
|
||||
struct watcher px_watch; /* watcher to automatically update next pointer on backend deletion */
|
||||
struct proxy *next;
|
||||
char capabilities;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
#ifndef _HAPROXY_HSTREAM_T_H
|
||||
#define _HAPROXY_HSTREAM_T_H
|
||||
|
||||
#include <haproxy/dynbuf-t.h>
|
||||
#include <haproxy/http-t.h>
|
||||
#include <haproxy/obj_type-t.h>
|
||||
|
||||
/* hastream stream */
|
||||
struct hstream {
|
||||
enum obj_type obj_type;
|
||||
struct session *sess;
|
||||
|
||||
struct stconn *sc;
|
||||
struct task *task;
|
||||
|
||||
struct buffer req;
|
||||
struct buffer res;
|
||||
unsigned long long to_write; /* #of response data bytes to write after headers */
|
||||
struct buffer_wait buf_wait; /* Wait list for buffer allocation */
|
||||
|
||||
int flags;
|
||||
|
||||
int ka; /* .0: keep-alive .1: forced .2: http/1.1, .3: was_reused */
|
||||
int req_cache;
|
||||
unsigned long long req_size; /* values passed in the URI to override the server's */
|
||||
unsigned long long req_body; /* remaining body to be consumed from the request */
|
||||
int req_code;
|
||||
int res_wait; /* time to wait before replying in ms */
|
||||
int res_time;
|
||||
int req_chunked;
|
||||
int req_random;
|
||||
int req_after_res; /* Drain the request body after having sent the response */
|
||||
enum http_meth_t req_meth;
|
||||
};
|
||||
|
||||
#endif /* _HAPROXY_HSTREAM_T_H */
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
#ifndef _HAPROXY_HSTREAM_H
|
||||
#define _HAPROXY_HSTREAM_H
|
||||
|
||||
#include <haproxy/cfgparse.h>
|
||||
#include <haproxy/hstream-t.h>
|
||||
|
||||
struct task *sc_hstream_io_cb(struct task *t, void *ctx, unsigned int state);
|
||||
void hstream_shutdown(struct stconn *sc);
|
||||
void *hstream_new(struct session *sess, struct stconn *sc, struct buffer *input);
|
||||
|
||||
#endif /* _HAPROXY_HSTREAM_H */
|
||||
|
|
@ -228,8 +228,7 @@ enum h1_state {
|
|||
*/
|
||||
struct http_msg {
|
||||
enum h1_state msg_state; /* where we are in the current message parsing */
|
||||
unsigned char vsn; /* HTTP version, 4 bits per digit */
|
||||
/* 2 bytes unused here */
|
||||
/* 3 bytes unused here */
|
||||
unsigned int flags; /* flags describing the message (HTTP version, ...) */
|
||||
struct channel *chn; /* pointer to the channel transporting the message */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ int http_req_replace_stline(int action, const char *replace, int len,
|
|||
int http_res_set_status(unsigned int status, struct ist reason, struct stream *s);
|
||||
void http_check_request_for_cacheability(struct stream *s, struct channel *req);
|
||||
void http_check_response_for_cacheability(struct stream *s, struct channel *res);
|
||||
enum rule_result http_wait_for_msg_body(struct stream *s, struct channel *chn, unsigned int time, unsigned int bytes, unsigned int large_buffer);
|
||||
enum rule_result http_wait_for_msg_body(struct stream *s, struct channel *chn, unsigned int time, unsigned int bytes);
|
||||
void http_perform_server_redirect(struct stream *s, struct stconn *sc);
|
||||
void http_server_error(struct stream *s, struct stconn *sc, int err, int finst, struct http_reply *msg);
|
||||
void http_reply_and_close(struct stream *s, short status, struct http_reply *msg);
|
||||
|
|
|
|||
|
|
@ -93,22 +93,4 @@ struct http_errors {
|
|||
struct list list; /* http-errors list */
|
||||
};
|
||||
|
||||
/* Indicates the keyword origin of an http-error definition. This is used in
|
||||
* <conf_errors> type to indicate which part of the internal union should be
|
||||
* manipulated.
|
||||
*/
|
||||
enum http_err_directive {
|
||||
HTTP_ERR_DIRECTIVE_SECTION = 0, /* "errorfiles" keyword referencing a http-errors section */
|
||||
HTTP_ERR_DIRECTIVE_INLINE, /* "errorfile" keyword with inline error definition */
|
||||
};
|
||||
|
||||
/* Used with "errorfiles" directives. It indicates for each known HTTP error
|
||||
* status codes if they are defined in the target http-errors section.
|
||||
*/
|
||||
enum http_err_import {
|
||||
HTTP_ERR_IMPORT_NO = 0,
|
||||
HTTP_ERR_IMPORT_IMPLICIT, /* import every errcode defined in a section */
|
||||
HTTP_ERR_IMPORT_EXPLICIT, /* import a specific errcode from a section */
|
||||
};
|
||||
|
||||
#endif /* _HAPROXY_HTTP_HTX_T_H */
|
||||
|
|
|
|||
|
|
@ -78,7 +78,6 @@ struct buffer *http_load_errorfile(const char *file, char **errmsg);
|
|||
struct buffer *http_load_errormsg(const char *key, const struct ist msg, char **errmsg);
|
||||
struct buffer *http_parse_errorfile(int status, const char *file, char **errmsg);
|
||||
struct buffer *http_parse_errorloc(int errloc, int status, const char *url, char **errmsg);
|
||||
int proxy_check_http_errors(struct proxy *px);
|
||||
int proxy_dup_default_conf_errors(struct proxy *curpx, const struct proxy *defpx, char **errmsg);
|
||||
void proxy_release_conf_errors(struct proxy *px);
|
||||
|
||||
|
|
|
|||
|
|
@ -141,7 +141,6 @@
|
|||
#define HTX_SL_F_NORMALIZED_URI 0x00000800 /* The received URI is normalized (an implicit absolute-uri form) */
|
||||
#define HTX_SL_F_CONN_UPG 0x00001000 /* The message contains "connection: upgrade" header */
|
||||
#define HTX_SL_F_BODYLESS_RESP 0x00002000 /* The response to this message is bodyloess (only for reqyest) */
|
||||
#define HTX_SL_F_NOT_HTTP 0x00004000 /* Not an HTTP message (e.g "RTSP", only possible if invalid message are accepted) */
|
||||
|
||||
/* This function is used to report flags in debugging tools. Please reflect
|
||||
* below any single-bit flag addition above in the same order via the
|
||||
|
|
@ -178,7 +177,7 @@ static forceinline char *hsl_show_flags(char *buf, size_t len, const char *delim
|
|||
#define HTX_FL_PARSING_ERROR 0x00000001 /* Set when a parsing error occurred */
|
||||
#define HTX_FL_PROCESSING_ERROR 0x00000002 /* Set when a processing error occurred */
|
||||
#define HTX_FL_FRAGMENTED 0x00000004 /* Set when the HTX buffer is fragmented */
|
||||
#define HTX_FL_UNORDERED 0x00000008 /* Set when the HTX buffer are not ordered */
|
||||
/* 0x00000008 unused */
|
||||
#define HTX_FL_EOM 0x00000010 /* Set when end-of-message is reached from the HTTP point of view
|
||||
* (at worst, on the EOM block is missing)
|
||||
*/
|
||||
|
|
@ -193,7 +192,7 @@ static forceinline char *htx_show_flags(char *buf, size_t len, const char *delim
|
|||
_(0);
|
||||
/* flags */
|
||||
_(HTX_FL_PARSING_ERROR, _(HTX_FL_PROCESSING_ERROR,
|
||||
_(HTX_FL_FRAGMENTED, _(HTX_FL_UNORDERED, _(HTX_FL_EOM)))));
|
||||
_(HTX_FL_FRAGMENTED, _(HTX_FL_EOM))));
|
||||
/* epilogue */
|
||||
_(~0U);
|
||||
return buf;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ struct htx_blk *htx_add_blk(struct htx *htx, enum htx_blk_type type, uint32_t bl
|
|||
struct htx_blk *htx_remove_blk(struct htx *htx, struct htx_blk *blk);
|
||||
struct htx_ret htx_find_offset(struct htx *htx, uint32_t offset);
|
||||
void htx_truncate(struct htx *htx, uint32_t offset);
|
||||
void htx_truncate_blk(struct htx *htx, struct htx_blk *blk);
|
||||
struct htx_ret htx_drain(struct htx *htx, uint32_t max);
|
||||
|
||||
struct htx_blk *htx_replace_blk_value(struct htx *htx, struct htx_blk *blk,
|
||||
|
|
@ -57,16 +56,6 @@ size_t htx_add_data(struct htx *htx, const struct ist data);
|
|||
struct htx_blk *htx_add_last_data(struct htx *htx, struct ist data);
|
||||
void htx_move_blk_before(struct htx *htx, struct htx_blk **blk, struct htx_blk **ref);
|
||||
int htx_append_msg(struct htx *dst, const struct htx *src);
|
||||
struct buffer *htx_move_to_small_buffer(struct buffer *dst, struct buffer *src);
|
||||
struct buffer *htx_move_to_large_buffer(struct buffer *dst, struct buffer *src);
|
||||
struct buffer *htx_copy_to_small_buffer(struct buffer *dst, struct buffer *src);
|
||||
struct buffer *htx_copy_to_large_buffer(struct buffer *dst, struct buffer *src);
|
||||
|
||||
#define HTX_XFER_DEFAULT 0x00000000 /* Default XFER: no partial xfer / remove blocks from source */
|
||||
#define HTX_XFER_KEEP_SRC_BLKS 0x00000001 /* Don't remove xfer blocks from source messages during xfer */
|
||||
#define HTX_XFER_PARTIAL_HDRS_COPY 0x00000002 /* Allow partial copy of headers and trailers part */
|
||||
#define HTX_XFER_HDRS_ONLY 0x00000003 /* Only Transfert header blocks (start-line, header and EOH) */
|
||||
size_t htx_xfer(struct htx *dst, struct htx *src, size_t count, unsigned int flags);
|
||||
|
||||
/* Functions and macros to get parts of the start-line or length of these
|
||||
* parts. Request and response start-lines are both composed of 3 parts.
|
||||
|
|
@ -109,11 +98,6 @@ static inline struct ist htx_sl_p3(const struct htx_sl *sl)
|
|||
return ist2(HTX_SL_P3_PTR(sl), HTX_SL_P3_LEN(sl));
|
||||
}
|
||||
|
||||
static inline struct ist htx_sl_vsn(const struct htx_sl *sl)
|
||||
{
|
||||
return ((sl->flags & HTX_SL_F_IS_RESP) ? htx_sl_p1(sl) : htx_sl_p3(sl));
|
||||
}
|
||||
|
||||
static inline struct ist htx_sl_req_meth(const struct htx_sl *sl)
|
||||
{
|
||||
return htx_sl_p1(sl);
|
||||
|
|
@ -490,12 +474,11 @@ static inline struct htx_sl *htx_add_stline(struct htx *htx, enum htx_blk_type t
|
|||
static inline struct htx_blk *htx_add_header(struct htx *htx, const struct ist name,
|
||||
const struct ist value)
|
||||
{
|
||||
struct htx_blk *blk, *tailblk;
|
||||
struct htx_blk *blk;
|
||||
|
||||
if (name.len > 255 || value.len > 1048575)
|
||||
return NULL;
|
||||
|
||||
tailblk = htx_get_tail_blk(htx);
|
||||
blk = htx_add_blk(htx, HTX_BLK_HDR, name.len + value.len);
|
||||
if (!blk)
|
||||
return NULL;
|
||||
|
|
@ -503,8 +486,6 @@ static inline struct htx_blk *htx_add_header(struct htx *htx, const struct ist n
|
|||
blk->info += (value.len << 8) + name.len;
|
||||
ist2bin_lc(htx_get_blk_ptr(htx, blk), name);
|
||||
memcpy(htx_get_blk_ptr(htx, blk) + name.len, value.ptr, value.len);
|
||||
if (tailblk && htx_get_blk_type(tailblk) >= HTX_BLK_EOH)
|
||||
htx->flags |= HTX_FL_UNORDERED;
|
||||
return blk;
|
||||
}
|
||||
|
||||
|
|
@ -514,12 +495,11 @@ static inline struct htx_blk *htx_add_header(struct htx *htx, const struct ist n
|
|||
static inline struct htx_blk *htx_add_trailer(struct htx *htx, const struct ist name,
|
||||
const struct ist value)
|
||||
{
|
||||
struct htx_blk *blk, *tailblk;
|
||||
struct htx_blk *blk;
|
||||
|
||||
if (name.len > 255 || value.len > 1048575)
|
||||
return NULL;
|
||||
|
||||
tailblk = htx_get_tail_blk(htx);
|
||||
blk = htx_add_blk(htx, HTX_BLK_TLR, name.len + value.len);
|
||||
if (!blk)
|
||||
return NULL;
|
||||
|
|
@ -527,8 +507,6 @@ static inline struct htx_blk *htx_add_trailer(struct htx *htx, const struct ist
|
|||
blk->info += (value.len << 8) + name.len;
|
||||
ist2bin_lc(htx_get_blk_ptr(htx, blk), name);
|
||||
memcpy(htx_get_blk_ptr(htx, blk) + name.len, value.ptr, value.len);
|
||||
if (tailblk && htx_get_blk_type(tailblk) >= HTX_BLK_EOT)
|
||||
htx->flags |= HTX_FL_UNORDERED;
|
||||
return blk;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,11 +20,6 @@ extern struct list server_deinit_list;
|
|||
extern struct list per_thread_free_list;
|
||||
extern struct list per_thread_deinit_list;
|
||||
|
||||
/* initcall caller location */
|
||||
extern const struct initcall *caller_initcall;
|
||||
extern const char *caller_file;
|
||||
extern int caller_line;
|
||||
|
||||
void hap_register_pre_check(int (*fct)());
|
||||
void hap_register_post_check(int (*fct)());
|
||||
void hap_register_post_proxy_check(int (*fct)(struct proxy *));
|
||||
|
|
|
|||
|
|
@ -77,8 +77,6 @@ struct initcall {
|
|||
void *arg1;
|
||||
void *arg2;
|
||||
void *arg3;
|
||||
const char *loc_file; /* file where the call is declared, or NULL */
|
||||
int loc_line; /* line where the call is declared, or NULL */
|
||||
#if defined(USE_OBSOLETE_LINKER)
|
||||
void *next;
|
||||
#endif
|
||||
|
|
@ -109,8 +107,6 @@ struct initcall {
|
|||
.arg1 = (void *)(a1), \
|
||||
.arg2 = (void *)(a2), \
|
||||
.arg3 = (void *)(a3), \
|
||||
.loc_file = __FILE__, \
|
||||
.loc_line = linenum, \
|
||||
} : NULL
|
||||
|
||||
|
||||
|
|
@ -135,8 +131,6 @@ __attribute__((constructor)) static void __initcb_##linenum() \
|
|||
.arg1 = (void *)(a1), \
|
||||
.arg2 = (void *)(a2), \
|
||||
.arg3 = (void *)(a3), \
|
||||
.loc_file = __FILE__, \
|
||||
.loc_line = linenum, \
|
||||
}; \
|
||||
if (stg < STG_SIZE) { \
|
||||
entry.next = __initstg[stg]; \
|
||||
|
|
@ -153,14 +147,14 @@ __attribute__((constructor)) static void __initcb_##linenum() \
|
|||
#define _DECLARE_INITCALL(...) \
|
||||
__DECLARE_INITCALL(__VA_ARGS__)
|
||||
|
||||
/* This requires that function <function> is called without arguments
|
||||
* during init stage <stage> which must be one of init_stage.
|
||||
/* This requires that function <function> is called with pointer argument
|
||||
* <argument> during init stage <stage> which must be one of init_stage.
|
||||
*/
|
||||
#define INITCALL0(stage, function) \
|
||||
_DECLARE_INITCALL(stage, __LINE__, function, 0, 0, 0)
|
||||
|
||||
/* This requires that function <function> is called with pointer argument
|
||||
* <arg1> during init stage <stage> which must be one of init_stage.
|
||||
* <argument> during init stage <stage> which must be one of init_stage.
|
||||
*/
|
||||
#define INITCALL1(stage, function, arg1) \
|
||||
_DECLARE_INITCALL(stage, __LINE__, function, arg1, 0, 0)
|
||||
|
|
@ -235,15 +229,8 @@ extern struct initcall *__initstg[STG_SIZE];
|
|||
const struct initcall **ptr; \
|
||||
if (stg >= STG_SIZE) \
|
||||
break; \
|
||||
FOREACH_INITCALL(ptr, stg) { \
|
||||
caller_initcall = *ptr; \
|
||||
caller_file = (*ptr)->loc_file; \
|
||||
caller_line = (*ptr)->loc_line; \
|
||||
FOREACH_INITCALL(ptr, stg) \
|
||||
(*ptr)->fct((*ptr)->arg1, (*ptr)->arg2, (*ptr)->arg3); \
|
||||
caller_initcall = NULL; \
|
||||
caller_file = NULL; \
|
||||
caller_line = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else // USE_OBSOLETE_LINKER
|
||||
|
|
@ -256,15 +243,8 @@ extern struct initcall *__initstg[STG_SIZE];
|
|||
const struct initcall *ptr; \
|
||||
if (stg >= STG_SIZE) \
|
||||
break; \
|
||||
FOREACH_INITCALL(ptr, stg) { \
|
||||
caller_initcall = ptr; \
|
||||
caller_file = (ptr)->loc_file; \
|
||||
caller_line = (ptr)->loc_line; \
|
||||
FOREACH_INITCALL(ptr, stg) \
|
||||
(ptr)->fct((ptr)->arg1, (ptr)->arg2, (ptr)->arg3); \
|
||||
caller_initcall = NULL; \
|
||||
caller_file = NULL; \
|
||||
caller_line = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif // USE_OBSOLETE_LINKER
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#ifdef USE_OPENSSL
|
||||
enum jwt_alg jwt_parse_alg(const char *alg_str, unsigned int alg_len);
|
||||
int jwt_tokenize(const struct buffer *jwt, struct jwt_item *items, unsigned int item_num);
|
||||
int jwt_tokenize(const struct buffer *jwt, struct jwt_item *items, unsigned int *item_num);
|
||||
int jwt_tree_load_cert(char *path, int pathlen, int tryload_cert, const char *file, int line, char **err);
|
||||
|
||||
enum jwt_vrfy_status jwt_verify(const struct buffer *token, const struct buffer *alg,
|
||||
|
|
|
|||
|
|
@ -28,13 +28,13 @@
|
|||
#include <import/ebtree-t.h>
|
||||
|
||||
#include <haproxy/api-t.h>
|
||||
#include <haproxy/counters-t.h>
|
||||
#include <haproxy/guid-t.h>
|
||||
#include <haproxy/obj_type-t.h>
|
||||
#include <haproxy/quic_cc-t.h>
|
||||
#include <haproxy/quic_sock-t.h>
|
||||
#include <haproxy/quic_tp-t.h>
|
||||
#include <haproxy/receiver-t.h>
|
||||
#include <haproxy/stats-t.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
/* Some pointer types reference below */
|
||||
|
|
@ -263,7 +263,6 @@ struct listener {
|
|||
|
||||
struct li_per_thread *per_thr; /* per-thread fields (one per thread in the group) */
|
||||
|
||||
char *extra_counters_storage; /* storage for extra_counters */
|
||||
EXTRA_COUNTERS(extra_counters);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -200,8 +200,6 @@ enum qcc_app_ops_close_side {
|
|||
|
||||
/* QUIC application layer operations */
|
||||
struct qcc_app_ops {
|
||||
const char *alpn;
|
||||
|
||||
/* Initialize <qcc> connection app context. */
|
||||
int (*init)(struct qcc *qcc);
|
||||
/* Finish connection initialization if prelude required. */
|
||||
|
|
@ -234,9 +232,6 @@ struct qcc_app_ops {
|
|||
void (*inc_err_cnt)(void *ctx, int err_code);
|
||||
/* Set QCC error code as suspicious activity has been detected. */
|
||||
void (*report_susp)(void *ctx);
|
||||
|
||||
/* Free function to close a stream after MUX layer shutdown. */
|
||||
int (*strm_reject)(struct list *out, uint64_t id);
|
||||
};
|
||||
|
||||
#endif /* USE_QUIC */
|
||||
|
|
|
|||
|
|
@ -12,9 +12,6 @@
|
|||
#include <haproxy/mux_quic-t.h>
|
||||
#include <haproxy/stconn.h>
|
||||
|
||||
#include <haproxy/h3.h>
|
||||
#include <haproxy/hq_interop.h>
|
||||
|
||||
#define qcc_report_glitch(qcc, inc, ...) ({ \
|
||||
COUNT_GLITCH(__VA_ARGS__); \
|
||||
_qcc_report_glitch(qcc, inc); \
|
||||
|
|
@ -91,7 +88,7 @@ static inline char *qcs_st_to_str(enum qcs_state st)
|
|||
}
|
||||
}
|
||||
|
||||
int qcc_install_app_ops(struct qcc *qcc);
|
||||
int qcc_install_app_ops(struct qcc *qcc, const struct qcc_app_ops *app_ops);
|
||||
|
||||
/* Register <qcs> stream for http-request timeout. If the stream is not yet
|
||||
* attached in the configured delay, qcc timeout task will be triggered. This
|
||||
|
|
@ -118,16 +115,6 @@ void qcc_show_quic(struct qcc *qcc);
|
|||
|
||||
void qcc_wakeup(struct qcc *qcc);
|
||||
|
||||
static inline const struct qcc_app_ops *quic_alpn_to_app_ops(const char *alpn, int alpn_len)
|
||||
{
|
||||
if (alpn_len >= 2 && memcmp(alpn, "h3", 2) == 0)
|
||||
return &h3_ops;
|
||||
else if (alpn_len >= 10 && memcmp(alpn, "hq-interop", 10) == 0)
|
||||
return &hq_interop_ops;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* USE_QUIC */
|
||||
|
||||
#endif /* _HAPROXY_MUX_QUIC_H */
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ enum obj_type {
|
|||
#ifdef USE_QUIC
|
||||
OBJ_TYPE_DGRAM, /* object is a struct quic_dgram */
|
||||
#endif
|
||||
OBJ_TYPE_HATERM, /* object is a struct hstream */
|
||||
OBJ_TYPE_ENTRIES /* last one : number of entries */
|
||||
} __attribute__((packed)) ;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#include <haproxy/applet-t.h>
|
||||
#include <haproxy/check-t.h>
|
||||
#include <haproxy/connection-t.h>
|
||||
#include <haproxy/hstream-t.h>
|
||||
#include <haproxy/listener-t.h>
|
||||
#include <haproxy/obj_type-t.h>
|
||||
#include <haproxy/pool.h>
|
||||
|
|
@ -190,19 +189,6 @@ static inline struct check *objt_check(enum obj_type *t)
|
|||
return __objt_check(t);
|
||||
}
|
||||
|
||||
static inline struct hstream *__objt_hstream(enum obj_type *t)
|
||||
{
|
||||
return container_of(t, struct hstream, obj_type);
|
||||
}
|
||||
|
||||
static inline struct hstream *objt_hstream(enum obj_type *t)
|
||||
{
|
||||
if (!t || *t != OBJ_TYPE_HATERM)
|
||||
return NULL;
|
||||
|
||||
return __objt_hstream(t);
|
||||
}
|
||||
|
||||
#ifdef USE_QUIC
|
||||
static inline struct quic_dgram *__objt_dgram(enum obj_type *t)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -394,12 +394,6 @@ static inline unsigned long ERR_peek_error_func(const char **func)
|
|||
#define __OPENSSL_110_CONST__
|
||||
#endif
|
||||
|
||||
#if (HA_OPENSSL_VERSION_NUMBER >= 0x40000000L) && (!defined(USE_OPENSSL_WOLFSSL))
|
||||
#define __X509_NAME_CONST__ const
|
||||
#else
|
||||
#define __X509_NAME_CONST__
|
||||
#endif
|
||||
|
||||
/* ERR_remove_state() was deprecated in 1.0.0 in favor of
|
||||
* ERR_remove_thread_state(), which was in turn deprecated in
|
||||
* 1.1.0 and does nothing anymore. Let's simply silently kill
|
||||
|
|
|
|||
|
|
@ -124,12 +124,6 @@ static inline int real_family(int ss_family)
|
|||
return fam ? fam->real_family : AF_UNSPEC;
|
||||
}
|
||||
|
||||
static inline int proto_is_quic(const struct protocol *proto)
|
||||
{
|
||||
return (proto->proto_type == PROTO_TYPE_DGRAM &&
|
||||
proto->xprt_type == PROTO_TYPE_STREAM);
|
||||
}
|
||||
|
||||
#endif /* _HAPROXY_PROTOCOL_H */
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include <haproxy/obj_type-t.h>
|
||||
#include <haproxy/queue-t.h>
|
||||
#include <haproxy/server-t.h>
|
||||
#include <haproxy/stats-t.h>
|
||||
#include <haproxy/tcpcheck-t.h>
|
||||
#include <haproxy/thread-t.h>
|
||||
#include <haproxy/tools-t.h>
|
||||
|
|
@ -156,17 +157,14 @@ enum PR_SRV_STATE_FILE {
|
|||
#define PR_O2_RSTRICT_REQ_HDR_NAMES_NOOP 0x01000000 /* preserve request header names containing chars outside of [0-9a-zA-Z-] charset */
|
||||
#define PR_O2_RSTRICT_REQ_HDR_NAMES_MASK 0x01c00000 /* mask for restrict-http-header-names option */
|
||||
|
||||
/* server health checks */
|
||||
#define PR_O2_CHK_NONE 0x00000000 /* no L7 health checks configured (TCP by default) */
|
||||
#define PR_O2_TCPCHK_CHK 0x02000000 /* use TCPCHK check for server health */
|
||||
#define PR_O2_EXT_CHK 0x04000000 /* use external command for server health */
|
||||
#define PR_O2_CHK_ANY 0x06000000 /* Mask to cover any check */
|
||||
/* unused : 0x02000000 ... 0x08000000 */
|
||||
|
||||
#define PR_O2_USE_SBUF_QUEUE 0x08000000 /* use small buffer for request when stream are queued*/
|
||||
#define PR_O2_USE_SBUF_L7_RETRY 0x10000000 /* use small buffer for request when L7 retires are enabled */
|
||||
#define PR_O2_USE_SBUF_CHECK 0x20000000 /* use small buffer for request's healthchecks */
|
||||
#define PR_O2_USE_SBUF_ALL 0x38000000 /* all flags for use-large-buffer option */
|
||||
/* unused : 0x40000000 ... 0x80000000 */
|
||||
/* server health checks */
|
||||
#define PR_O2_CHK_NONE 0x00000000 /* no L7 health checks configured (TCP by default) */
|
||||
#define PR_O2_TCPCHK_CHK 0x90000000 /* use TCPCHK check for server health */
|
||||
#define PR_O2_EXT_CHK 0xA0000000 /* use external command for server health */
|
||||
/* unused: 0xB0000000 to 0xF000000, reserved for health checks */
|
||||
#define PR_O2_CHK_ANY 0xF0000000 /* Mask to cover any check */
|
||||
/* end of proxy->options2 */
|
||||
|
||||
/* bits for proxy->options3 */
|
||||
|
|
@ -242,16 +240,14 @@ enum PR_SRV_STATE_FILE {
|
|||
#define PR_RE_JUNK_REQUEST 0x00020000 /* We received an incomplete or garbage response */
|
||||
|
||||
/* Proxy flags */
|
||||
#define PR_FL_DISABLED 0x00000001 /* The proxy was disabled in the configuration (not at runtime) */
|
||||
#define PR_FL_STOPPED 0x00000002 /* The proxy was stopped */
|
||||
#define PR_FL_DEF_EXPLICIT_MODE 0x00000004 /* Proxy mode is explicitely defined - only used for defaults instance */
|
||||
#define PR_FL_EXPLICIT_REF 0x00000008 /* The default proxy is explicitly referenced by another proxy */
|
||||
#define PR_FL_IMPLICIT_REF 0x00000010 /* The default proxy is implicitly referenced by another proxy */
|
||||
#define PR_FL_PAUSED 0x00000020 /* The proxy was paused at run time (reversible) */
|
||||
#define PR_FL_CHECKED 0x00000040 /* The proxy configuration was fully checked (including postparsing checks) */
|
||||
#define PR_FL_BE_UNPUBLISHED 0x00000080 /* The proxy cannot be targetted by content switching rules */
|
||||
#define PR_FL_DELETED 0x00000100 /* Proxy has been deleted and must be manipulated with care */
|
||||
#define PR_FL_NON_PURGEABLE 0x00000200 /* Proxy referenced by config elements which prevent its runtime removal. */
|
||||
#define PR_FL_DISABLED 0x01 /* The proxy was disabled in the configuration (not at runtime) */
|
||||
#define PR_FL_STOPPED 0x02 /* The proxy was stopped */
|
||||
#define PR_FL_READY 0x04 /* The proxy is ready to be used (initialized and configured) */
|
||||
#define PR_FL_EXPLICIT_REF 0x08 /* The default proxy is explicitly referenced by another proxy */
|
||||
#define PR_FL_IMPLICIT_REF 0x10 /* The default proxy is implicitly referenced by another proxy */
|
||||
#define PR_FL_PAUSED 0x20 /* The proxy was paused at run time (reversible) */
|
||||
#define PR_FL_CHECKED 0x40 /* The proxy configuration was fully checked (including postparsing checks) */
|
||||
#define PR_FL_BE_UNPUBLISHED 0x80 /* The proxy cannot be targetted by content switching rules */
|
||||
|
||||
struct stream;
|
||||
|
||||
|
|
@ -297,8 +293,7 @@ struct error_snapshot {
|
|||
struct server *srv; /* server associated with the error (or NULL) */
|
||||
/* @64 */
|
||||
unsigned int ev_id; /* event number (counter incremented for each capture) */
|
||||
unsigned int buf_size; /* buffer size */
|
||||
|
||||
/* @68: 4 bytes hole here */
|
||||
struct sockaddr_storage src; /* client's address */
|
||||
|
||||
/**** protocol-specific part ****/
|
||||
|
|
@ -310,16 +305,13 @@ struct error_snapshot {
|
|||
struct proxy_per_tgroup {
|
||||
struct queue queue;
|
||||
struct lbprm_per_tgrp lbprm;
|
||||
char *extra_counters_fe_storage; /* storage for extra_counters_fe */
|
||||
char *extra_counters_be_storage; /* storage for extra_counters_be */
|
||||
} THREAD_ALIGNED();
|
||||
|
||||
struct proxy {
|
||||
enum obj_type obj_type; /* object type == OBJ_TYPE_PROXY */
|
||||
char flags; /* bit field PR_FL_* */
|
||||
enum pr_mode mode; /* mode = PR_MODE_TCP, PR_MODE_HTTP, ... */
|
||||
char cap; /* supported capabilities (PR_CAP_*) */
|
||||
/* 1 byte hole */
|
||||
unsigned int flags; /* bit field PR_FL_* */
|
||||
int to_log; /* things to be logged (LW_*), special value LW_LOGSTEPS == follow log-steps */
|
||||
unsigned long last_change; /* internal use only: last time the proxy state was changed */
|
||||
|
||||
|
|
@ -420,7 +412,6 @@ struct proxy {
|
|||
int redispatch_after; /* number of retries before redispatch */
|
||||
unsigned down_time; /* total time the proxy was down */
|
||||
int (*accept)(struct stream *s); /* application layer's accept() */
|
||||
void *(*stream_new_from_sc)(struct session *sess, struct stconn *sc, struct buffer *in); /* stream instantiation callback for mux stream connector */
|
||||
struct conn_src conn_src; /* connection source settings */
|
||||
enum obj_type *default_target; /* default target to use for accepted streams or NULL */
|
||||
struct proxy *next;
|
||||
|
|
@ -483,7 +474,7 @@ struct proxy {
|
|||
struct log_steps log_steps; /* bitfield of log origins where log should be generated during request handling */
|
||||
const char *file_prev; /* file of the previous instance found with the same name, or NULL */
|
||||
int line_prev; /* line of the previous instance found with the same name, or 0 */
|
||||
unsigned int def_ref; /* default proxy only refcount */
|
||||
unsigned int refcount; /* refcount on this proxy (only used for default proxy for now) */
|
||||
} conf; /* config information */
|
||||
struct http_ext *http_ext; /* http ext options */
|
||||
struct ceb_root *used_server_addr; /* list of server addresses in use */
|
||||
|
|
@ -512,8 +503,6 @@ struct proxy {
|
|||
struct list filter_configs; /* list of the filters that are declared on this proxy */
|
||||
|
||||
struct guid_node guid; /* GUID global tree node */
|
||||
struct mt_list watcher_list; /* list of elems which currently references this proxy instance (currently only used with backends) */
|
||||
uint refcount; /* refcount to keep proxy from being deleted during runtime */
|
||||
|
||||
EXTRA_COUNTERS(extra_counters_fe);
|
||||
EXTRA_COUNTERS(extra_counters_be);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
#include <haproxy/api.h>
|
||||
#include <haproxy/applet-t.h>
|
||||
#include <haproxy/counters.h>
|
||||
#include <haproxy/freq_ctr.h>
|
||||
#include <haproxy/list.h>
|
||||
#include <haproxy/listener-t.h>
|
||||
|
|
@ -42,8 +41,6 @@ extern unsigned int error_snapshot_id; /* global ID assigned to each error then
|
|||
extern struct ceb_root *proxy_by_name; /* tree of proxies sorted by name */
|
||||
extern struct list defaults_list; /* all defaults proxies list */
|
||||
|
||||
extern unsigned int dynpx_next_id;
|
||||
|
||||
extern const struct cfg_opt cfg_opts[];
|
||||
extern const struct cfg_opt cfg_opts2[];
|
||||
extern const struct cfg_opt cfg_opts3[];
|
||||
|
|
@ -59,10 +56,9 @@ void stop_proxy(struct proxy *p);
|
|||
int stream_set_backend(struct stream *s, struct proxy *be);
|
||||
|
||||
void deinit_proxy(struct proxy *p);
|
||||
void proxy_drop(struct proxy *p);
|
||||
void free_proxy(struct proxy *p);
|
||||
const char *proxy_cap_str(int cap);
|
||||
const char *proxy_mode_str(int mode);
|
||||
enum pr_mode str_to_proxy_mode(const char *mode);
|
||||
const char *proxy_find_best_option(const char *word, const char **extra);
|
||||
uint proxy_get_next_id(uint from);
|
||||
void proxy_store_name(struct proxy *px);
|
||||
|
|
@ -78,12 +74,12 @@ void defaults_px_destroy_all_unref(void);
|
|||
void defaults_px_detach(struct proxy *px);
|
||||
void defaults_px_ref_all(void);
|
||||
void defaults_px_unref_all(void);
|
||||
int proxy_ref_defaults(struct proxy *px, struct proxy *defpx, char **errmsg);
|
||||
|
||||
void proxy_ref_defaults(struct proxy *px, struct proxy *defpx);
|
||||
void proxy_unref_defaults(struct proxy *px);
|
||||
int setup_new_proxy(struct proxy *px, const char *name, unsigned int cap, char **errmsg);
|
||||
struct proxy *alloc_new_proxy(const char *name, unsigned int cap,
|
||||
char **errmsg);
|
||||
void proxy_take(struct proxy *px);
|
||||
struct proxy *parse_new_proxy(const char *name, unsigned int cap,
|
||||
const char *file, int linenum,
|
||||
const struct proxy *defproxy);
|
||||
|
|
@ -101,9 +97,6 @@ int resolve_stick_rule(struct proxy *curproxy, struct sticking_rule *mrule);
|
|||
void free_stick_rules(struct list *rules);
|
||||
void free_server_rules(struct list *srules);
|
||||
int proxy_init_per_thr(struct proxy *px);
|
||||
int proxy_finalize(struct proxy *px, int *err_code);
|
||||
|
||||
int be_check_for_deletion(const char *bename, struct proxy **pb, const char **pm);
|
||||
|
||||
/*
|
||||
* This function returns a string containing the type of the proxy in a format
|
||||
|
|
@ -182,7 +175,7 @@ static inline void proxy_inc_fe_conn_ctr(struct listener *l, struct proxy *fe)
|
|||
}
|
||||
if (l && l->counters && l->counters->shared.tg)
|
||||
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->cum_conn);
|
||||
COUNTERS_UPDATE_MAX(&fe->fe_counters.cps_max,
|
||||
HA_ATOMIC_UPDATE_MAX(&fe->fe_counters.cps_max,
|
||||
update_freq_ctr(&fe->fe_counters._conn_per_sec, 1));
|
||||
}
|
||||
|
||||
|
|
@ -195,7 +188,7 @@ static inline void proxy_inc_fe_sess_ctr(struct listener *l, struct proxy *fe)
|
|||
}
|
||||
if (l && l->counters && l->counters->shared.tg)
|
||||
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->cum_sess);
|
||||
COUNTERS_UPDATE_MAX(&fe->fe_counters.sps_max,
|
||||
HA_ATOMIC_UPDATE_MAX(&fe->fe_counters.sps_max,
|
||||
update_freq_ctr(&fe->fe_counters._sess_per_sec, 1));
|
||||
}
|
||||
|
||||
|
|
@ -222,7 +215,7 @@ static inline void proxy_inc_be_ctr(struct proxy *be)
|
|||
_HA_ATOMIC_INC(&be->be_counters.shared.tg[tgid - 1]->cum_sess);
|
||||
update_freq_ctr(&be->be_counters.shared.tg[tgid - 1]->sess_per_sec, 1);
|
||||
}
|
||||
COUNTERS_UPDATE_MAX(&be->be_counters.sps_max,
|
||||
HA_ATOMIC_UPDATE_MAX(&be->be_counters.sps_max,
|
||||
update_freq_ctr(&be->be_counters._sess_per_sec, 1));
|
||||
}
|
||||
|
||||
|
|
@ -242,7 +235,7 @@ static inline void proxy_inc_fe_req_ctr(struct listener *l, struct proxy *fe,
|
|||
}
|
||||
if (l && l->counters && l->counters->shared.tg)
|
||||
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->p.http.cum_req[http_ver]);
|
||||
COUNTERS_UPDATE_MAX(&fe->fe_counters.p.http.rps_max,
|
||||
HA_ATOMIC_UPDATE_MAX(&fe->fe_counters.p.http.rps_max,
|
||||
update_freq_ctr(&fe->fe_counters.p.http._req_per_sec, 1));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ int qcs_http_handle_standalone_fin(struct qcs *qcs);
|
|||
|
||||
size_t qcs_http_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count,
|
||||
char *fin);
|
||||
size_t qcs_http_reset_buf(struct qcs *qcs, struct buffer *buf, size_t count);
|
||||
|
||||
#endif /* USE_QUIC */
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include <haproxy/quic_cc-t.h>
|
||||
#include <haproxy/quic_frame-t.h>
|
||||
#include <haproxy/quic_openssl_compat-t.h>
|
||||
#include <haproxy/quic_stats-t.h>
|
||||
#include <haproxy/quic_tls-t.h>
|
||||
#include <haproxy/quic_tp-t.h>
|
||||
#include <haproxy/show_flags-t.h>
|
||||
|
|
@ -400,8 +401,6 @@ struct quic_conn {
|
|||
|
||||
struct eb_root streams_by_id; /* qc_stream_desc tree */
|
||||
|
||||
const char *alpn;
|
||||
|
||||
/* MUX */
|
||||
struct qcc *qcc;
|
||||
struct task *timer_task;
|
||||
|
|
@ -410,9 +409,7 @@ struct quic_conn {
|
|||
/* Handshake expiration date */
|
||||
unsigned int hs_expire;
|
||||
|
||||
/* Callback to close any stream after MUX closure - set by the MUX itself */
|
||||
int (*strm_reject)(struct list *out, uint64_t stream_id);
|
||||
|
||||
const struct qcc_app_ops *app_ops;
|
||||
/* Proxy counters */
|
||||
struct quic_counters *prx_counters;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
#include <import/eb64tree.h>
|
||||
#include <import/ebmbtree.h>
|
||||
|
||||
#include <haproxy/counters.h>
|
||||
#include <haproxy/chunk.h>
|
||||
#include <haproxy/dynbuf.h>
|
||||
#include <haproxy/ncbmbuf.h>
|
||||
|
|
@ -84,7 +83,7 @@ void qc_check_close_on_released_mux(struct quic_conn *qc);
|
|||
int quic_stateless_reset_token_cpy(unsigned char *pos, size_t len,
|
||||
const unsigned char *salt, size_t saltlen);
|
||||
int quic_reuse_srv_params(struct quic_conn *qc,
|
||||
const char *alpn,
|
||||
const unsigned char *alpn,
|
||||
const struct quic_early_transport_params *etps);
|
||||
|
||||
/* Returns true if <qc> is used on the backed side (as a client). */
|
||||
|
|
@ -194,17 +193,13 @@ static inline void *qc_counters(enum obj_type *o, const struct stats_module *m)
|
|||
p = l ? l->bind_conf->frontend :
|
||||
s ? s->proxy : NULL;
|
||||
|
||||
if (l && p)
|
||||
return EXTRA_COUNTERS_GET(p->extra_counters_fe, m);
|
||||
else if (s && p)
|
||||
return EXTRA_COUNTERS_GET(p->extra_counters_be, m);
|
||||
return NULL;
|
||||
return p ? EXTRA_COUNTERS_GET(p->extra_counters_fe, m) : NULL;
|
||||
}
|
||||
|
||||
void chunk_frm_appendf(struct buffer *buf, const struct quic_frame *frm);
|
||||
void quic_set_connection_close(struct quic_conn *qc, const struct quic_err err);
|
||||
void quic_set_tls_alert(struct quic_conn *qc, int alert);
|
||||
int qc_register_alpn(struct quic_conn *qc, const char *alpn, int alpn_len);
|
||||
int quic_set_app_ops(struct quic_conn *qc, const unsigned char *alpn, size_t alpn_len);
|
||||
int qc_check_dcid(struct quic_conn *qc, unsigned char *dcid, size_t dcid_len);
|
||||
|
||||
void qc_notify_err(struct quic_conn *qc);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#error "Must define USE_OPENSSL"
|
||||
#endif
|
||||
|
||||
extern struct stats_module quic_stats_module;
|
||||
|
||||
enum {
|
||||
QUIC_ST_RXBUF_FULL,
|
||||
QUIC_ST_DROPPED_PACKET,
|
||||
|
|
@ -50,7 +52,6 @@ enum {
|
|||
QUIC_ST_STREAM_DATA_BLOCKED,
|
||||
QUIC_ST_STREAMS_BLOCKED_BIDI,
|
||||
QUIC_ST_STREAMS_BLOCKED_UNI,
|
||||
QUIC_ST_NCBUF_GAP_LIMIT,
|
||||
QUIC_STATS_COUNT /* must be the last */
|
||||
};
|
||||
|
||||
|
|
@ -98,7 +99,6 @@ struct quic_counters {
|
|||
long long stream_data_blocked; /* total number of times STREAM_DATA_BLOCKED frame was received */
|
||||
long long streams_blocked_bidi; /* total number of times STREAMS_BLOCKED_BIDI frame was received */
|
||||
long long streams_blocked_uni; /* total number of times STREAMS_BLOCKED_UNI frame was received */
|
||||
long long ncbuf_gap_limit; /* total number of times we failed to add data to ncbuf due to gap size limit */
|
||||
};
|
||||
|
||||
#endif /* USE_QUIC */
|
||||
|
|
|
|||
|
|
@ -7,9 +7,7 @@
|
|||
#endif
|
||||
|
||||
#include <haproxy/quic_stats-t.h>
|
||||
#include <haproxy/stats-t.h>
|
||||
|
||||
extern struct stats_module quic_stats_module;
|
||||
void quic_stats_transp_err_count_inc(struct quic_counters *ctrs, int error_code);
|
||||
|
||||
#endif /* USE_QUIC */
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <haproxy/connection-t.h>
|
||||
#include <haproxy/dns-t.h>
|
||||
#include <haproxy/obj_type-t.h>
|
||||
#include <haproxy/stats-t.h>
|
||||
#include <haproxy/task-t.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
#define _HAPROXY_SAMPLE_T_H
|
||||
|
||||
#include <haproxy/api-t.h>
|
||||
#include <haproxy/tinfo-t.h>
|
||||
#include <haproxy/sample_data-t.h>
|
||||
|
||||
/* input and output sample types
|
||||
|
|
@ -266,7 +265,6 @@ struct sample_conv {
|
|||
unsigned int in_type; /* expected input sample type */
|
||||
unsigned int out_type; /* output sample type */
|
||||
void *private; /* private values. only used by maps and Lua */
|
||||
struct thread_exec_ctx exec_ctx; /* execution context */
|
||||
};
|
||||
|
||||
/* sample conversion expression */
|
||||
|
|
@ -290,7 +288,6 @@ struct sample_fetch {
|
|||
unsigned int use; /* fetch source (SMP_USE_*) */
|
||||
unsigned int val; /* fetch validity (SMP_VAL_*) */
|
||||
void *private; /* private values. only used by Lua */
|
||||
struct thread_exec_ctx exec_ctx; /* execution context */
|
||||
};
|
||||
|
||||
/* sample expression */
|
||||
|
|
|
|||
|
|
@ -36,13 +36,9 @@
|
|||
void sc_update_rx(struct stconn *sc);
|
||||
void sc_update_tx(struct stconn *sc);
|
||||
|
||||
void sc_abort(struct stconn *sc);
|
||||
void sc_shutdown(struct stconn *sc);
|
||||
void sc_chk_rcv(struct stconn *sc);
|
||||
|
||||
struct task *sc_conn_io_cb(struct task *t, void *ctx, unsigned int state);
|
||||
int sc_conn_sync_recv(struct stconn *sc);
|
||||
int sc_conn_sync_send(struct stconn *sc);
|
||||
void sc_conn_sync_send(struct stconn *sc);
|
||||
|
||||
int sc_applet_sync_recv(struct stconn *sc);
|
||||
void sc_applet_sync_send(struct stconn *sc);
|
||||
|
|
@ -78,70 +74,6 @@ static inline struct buffer *sc_ob(const struct stconn *sc)
|
|||
{
|
||||
return &sc_oc(sc)->buf;
|
||||
}
|
||||
|
||||
|
||||
/* The application layer tells the stream connector that it just got the input
|
||||
* buffer it was waiting for. A read activity is reported. The SC_FL_HAVE_BUFF
|
||||
* flag is set and held until sc_used_buff() is called to indicate it was
|
||||
* used.
|
||||
*/
|
||||
static inline void sc_have_buff(struct stconn *sc)
|
||||
{
|
||||
if (sc->flags & SC_FL_NEED_BUFF) {
|
||||
sc->flags &= ~SC_FL_NEED_BUFF;
|
||||
sc->flags |= SC_FL_HAVE_BUFF;
|
||||
sc_ep_report_read_activity(sc);
|
||||
}
|
||||
}
|
||||
|
||||
/* The stream connector failed to get an input buffer and is waiting for it.
|
||||
* It indicates a willingness to deliver data to the buffer that will have to
|
||||
* be retried. As such, callers will often automatically clear SE_FL_HAVE_NO_DATA
|
||||
* to be called again as soon as SC_FL_NEED_BUFF is cleared.
|
||||
*/
|
||||
static inline void sc_need_buff(struct stconn *sc)
|
||||
{
|
||||
sc->flags |= SC_FL_NEED_BUFF;
|
||||
}
|
||||
|
||||
/* The stream connector indicates that it has successfully allocated the buffer
|
||||
* it was previously waiting for so it drops the SC_FL_HAVE_BUFF bit.
|
||||
*/
|
||||
static inline void sc_used_buff(struct stconn *sc)
|
||||
{
|
||||
sc->flags &= ~SC_FL_HAVE_BUFF;
|
||||
}
|
||||
|
||||
/* Tell a stream connector some room was made in the input buffer and any
|
||||
* failed attempt to inject data into it may be tried again. This is usually
|
||||
* called after a successful transfer of buffer contents to the other side.
|
||||
* A read activity is reported.
|
||||
*/
|
||||
static inline void sc_have_room(struct stconn *sc)
|
||||
{
|
||||
if (sc->flags & SC_FL_NEED_ROOM) {
|
||||
sc->flags &= ~SC_FL_NEED_ROOM;
|
||||
sc->room_needed = 0;
|
||||
sc_ep_report_read_activity(sc);
|
||||
}
|
||||
}
|
||||
|
||||
/* The stream connector announces it failed to put data into the input buffer
|
||||
* by lack of room. Since it indicates a willingness to deliver data to the
|
||||
* buffer that will have to be retried. Usually the caller will also clear
|
||||
* SE_FL_HAVE_NO_DATA to be called again as soon as SC_FL_NEED_ROOM is cleared.
|
||||
*
|
||||
* The caller is responsible to specified the amount of free space required to
|
||||
* progress. It must take care to not exceed the buffer size.
|
||||
*/
|
||||
static inline void sc_need_room(struct stconn *sc, ssize_t room_needed)
|
||||
{
|
||||
sc->flags |= SC_FL_NEED_ROOM;
|
||||
BUG_ON_HOT(room_needed > (ssize_t)c_size(sc_ic(sc)));
|
||||
sc->room_needed = room_needed;
|
||||
}
|
||||
|
||||
|
||||
/* returns the stream's task associated to this stream connector */
|
||||
static inline struct task *sc_strm_task(const struct stconn *sc)
|
||||
{
|
||||
|
|
@ -364,6 +296,38 @@ static inline int sc_is_recv_allowed(const struct stconn *sc)
|
|||
return !(sc->flags & (SC_FL_WONT_READ|SC_FL_NEED_BUFF|SC_FL_NEED_ROOM));
|
||||
}
|
||||
|
||||
/* This is to be used after making some room available in a channel. It will
|
||||
* return without doing anything if the stream connector's RX path is blocked.
|
||||
* It will automatically mark the stream connector as busy processing the end
|
||||
* point in order to avoid useless repeated wakeups.
|
||||
* It will then call ->chk_rcv() to enable receipt of new data.
|
||||
*/
|
||||
static inline void sc_chk_rcv(struct stconn *sc)
|
||||
{
|
||||
if (sc_ep_test(sc, SE_FL_APPLET_NEED_CONN) &&
|
||||
sc_state_in(sc_opposite(sc)->state, SC_SB_RDY|SC_SB_EST|SC_SB_DIS|SC_SB_CLO)) {
|
||||
sc_ep_clr(sc, SE_FL_APPLET_NEED_CONN);
|
||||
sc_ep_report_read_activity(sc);
|
||||
}
|
||||
|
||||
if (!sc_is_recv_allowed(sc))
|
||||
return;
|
||||
|
||||
if (!sc_state_in(sc->state, SC_SB_RDY|SC_SB_EST))
|
||||
return;
|
||||
|
||||
sc_ep_set(sc, SE_FL_HAVE_NO_DATA);
|
||||
if (likely(sc->app_ops->chk_rcv))
|
||||
sc->app_ops->chk_rcv(sc);
|
||||
}
|
||||
|
||||
/* Calls chk_snd on the endpoint using the data layer */
|
||||
static inline void sc_chk_snd(struct stconn *sc)
|
||||
{
|
||||
if (likely(sc->app_ops->chk_snd))
|
||||
sc->app_ops->chk_snd(sc);
|
||||
}
|
||||
|
||||
|
||||
/* Perform a synchronous receive using the right version, depending the endpoing
|
||||
* is a connection or an applet.
|
||||
|
|
@ -380,15 +344,10 @@ static inline int sc_sync_recv(struct stconn *sc)
|
|||
/* Perform a synchronous send using the right version, depending the endpoing is
|
||||
* a connection or an applet.
|
||||
*/
|
||||
static inline int sc_sync_send(struct stconn *sc, unsigned cnt)
|
||||
static inline void sc_sync_send(struct stconn *sc)
|
||||
{
|
||||
if (!sc_ep_test(sc, SE_FL_T_MUX))
|
||||
return 0;
|
||||
if (cnt >= 2 && co_data(sc_oc(sc))) {
|
||||
task_wakeup(__sc_strm(sc)->task, TASK_WOKEN_MSG);
|
||||
return 0;
|
||||
}
|
||||
return sc_conn_sync_send(sc);
|
||||
if (sc_ep_test(sc, SE_FL_T_MUX))
|
||||
sc_conn_sync_send(sc);
|
||||
}
|
||||
|
||||
/* Combines both sc_update_rx() and sc_update_tx() at once */
|
||||
|
|
@ -508,10 +467,24 @@ static inline void sc_schedule_abort(struct stconn *sc)
|
|||
sc->flags |= SC_FL_ABRT_WANTED;
|
||||
}
|
||||
|
||||
/* Abort the SC and notify the endpoint using the data layer */
|
||||
static inline void sc_abort(struct stconn *sc)
|
||||
{
|
||||
if (likely(sc->app_ops->abort))
|
||||
sc->app_ops->abort(sc);
|
||||
}
|
||||
|
||||
/* Schedule a shutdown for the SC */
|
||||
static inline void sc_schedule_shutdown(struct stconn *sc)
|
||||
{
|
||||
sc->flags |= SC_FL_SHUT_WANTED;
|
||||
}
|
||||
|
||||
/* Shutdown the SC and notify the endpoint using the data layer */
|
||||
static inline void sc_shutdown(struct stconn *sc)
|
||||
{
|
||||
if (likely(sc->app_ops->shutdown))
|
||||
sc->app_ops->shutdown(sc);
|
||||
}
|
||||
|
||||
#endif /* _HAPROXY_SC_STRM_H */
|
||||
|
|
|
|||
|
|
@ -286,7 +286,6 @@ struct srv_per_tgroup {
|
|||
struct queue queue; /* pending connections */
|
||||
struct server *server; /* pointer to the corresponding server */
|
||||
struct eb32_node lb_node; /* node used for tree-based load balancing */
|
||||
char *extra_counters_storage; /* storage for extra_counters */
|
||||
struct server *next_full; /* next server in the temporary full list */
|
||||
unsigned int last_other_tgrp_served; /* Last other tgrp we dequeued from */
|
||||
unsigned int self_served; /* Number of connection we dequeued from our own queue */
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
#include <haproxy/api.h>
|
||||
#include <haproxy/applet-t.h>
|
||||
#include <haproxy/arg-t.h>
|
||||
#include <haproxy/counters.h>
|
||||
#include <haproxy/freq_ctr.h>
|
||||
#include <haproxy/proxy-t.h>
|
||||
#include <haproxy/resolvers-t.h>
|
||||
|
|
@ -56,7 +55,6 @@ int srv_update_addr(struct server *s, void *ip, int ip_sin_family, struct server
|
|||
struct sample_expr *_parse_srv_expr(char *expr, struct arg_list *args_px,
|
||||
const char *file, int linenum, char **err);
|
||||
int server_parse_exprs(struct server *srv, struct proxy *px, char **err);
|
||||
int srv_configure_auto_sni(struct server *srv, int *err_code, char **err);
|
||||
int server_set_inetaddr(struct server *s, const struct server_inetaddr *inetaddr, struct server_inetaddr_updater updater, struct buffer *msg);
|
||||
int server_set_inetaddr_warn(struct server *s, const struct server_inetaddr *inetaddr, struct server_inetaddr_updater updater);
|
||||
void server_get_inetaddr(struct server *s, struct server_inetaddr *inetaddr);
|
||||
|
|
@ -213,7 +211,7 @@ static inline void srv_inc_sess_ctr(struct server *s)
|
|||
_HA_ATOMIC_INC(&s->counters.shared.tg[tgid - 1]->cum_sess);
|
||||
update_freq_ctr(&s->counters.shared.tg[tgid - 1]->sess_per_sec, 1);
|
||||
}
|
||||
COUNTERS_UPDATE_MAX(&s->counters.sps_max,
|
||||
HA_ATOMIC_UPDATE_MAX(&s->counters.sps_max,
|
||||
update_freq_ctr(&s->counters._sess_per_sec, 1));
|
||||
}
|
||||
|
||||
|
|
@ -351,26 +349,28 @@ static inline int srv_is_transparent(const struct server *srv)
|
|||
(srv->flags & SRV_F_MAPPORTS);
|
||||
}
|
||||
|
||||
/* Detach <srv> server from its parent proxy list.
|
||||
*
|
||||
* Must be called under thread isolation.
|
||||
/* Detach server from proxy list. It is supported to call this
|
||||
* even if the server is not yet in the list
|
||||
* Must be called under thread isolation or when it is safe to assume
|
||||
* that the parent proxy doesn't is not skimming through the server list
|
||||
*/
|
||||
static inline void srv_detach(struct server *srv)
|
||||
{
|
||||
struct proxy *px = srv->proxy;
|
||||
struct server *prev;
|
||||
|
||||
if (px->srv == srv) {
|
||||
if (px->srv == srv)
|
||||
px->srv = srv->next;
|
||||
}
|
||||
else {
|
||||
struct server *prev;
|
||||
|
||||
for (prev = px->srv; prev && prev->next != srv; prev = prev->next)
|
||||
;
|
||||
BUG_ON(!prev); /* Server instance not found in proxy list ? */
|
||||
|
||||
BUG_ON(!prev);
|
||||
|
||||
prev->next = srv->next;
|
||||
}
|
||||
|
||||
/* Reset the proxy's ready_srv if it was this one. */
|
||||
/* reset the proxy's ready_srv if it was this one */
|
||||
HA_ATOMIC_CAS(&px->ready_srv, &srv, NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -73,14 +73,6 @@ struct ckch_conf {
|
|||
char *id;
|
||||
char **domains;
|
||||
} acme;
|
||||
struct {
|
||||
struct {
|
||||
char *type; /* "RSA" or "ECSDA" */
|
||||
int bits; /* bits for RSA */
|
||||
char *curves; /* NID of curves for ECDSA*/
|
||||
} key;
|
||||
int on;
|
||||
} gencrt;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -80,7 +80,6 @@ void ssl_store_delete_cafile_entry(struct cafile_entry *ca_e);
|
|||
int ssl_store_load_ca_from_buf(struct cafile_entry *ca_e, char *cert_buf, int append);
|
||||
int ssl_store_load_locations_file(char *path, int create_if_none, enum cafile_type type);
|
||||
int __ssl_store_load_locations_file(char *path, int create_if_none, enum cafile_type type, int shuterror);
|
||||
const char *ha_default_cert_dir();
|
||||
|
||||
extern struct cert_exts cert_exts[];
|
||||
extern int (*ssl_commit_crlfile_cb)(const char *path, X509_STORE *ctx, char **err);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
/* crt-list entry functions */
|
||||
void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf);
|
||||
struct ssl_bind_conf *crtlist_dup_ssl_conf(struct ssl_bind_conf *src);
|
||||
char **crtlist_dup_filters(char **args, int fcount);
|
||||
void crtlist_free_filters(char **args);
|
||||
void crtlist_entry_free(struct crtlist_entry *entry);
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ int ssl_sock_set_generated_cert(SSL_CTX *ctx, unsigned int key, struct bind_conf
|
|||
unsigned int ssl_sock_generated_cert_key(const void *data, size_t len);
|
||||
int ssl_sock_gencert_load_ca(struct bind_conf *bind_conf);
|
||||
void ssl_sock_gencert_free_ca(struct bind_conf *bind_conf);
|
||||
EVP_PKEY *ssl_gen_EVP_PKEY(int keytype, int curves, int bits, char **errmsg);
|
||||
X509 *ssl_gen_x509(EVP_PKEY *pkey);
|
||||
|
||||
#endif /* USE_OPENSSL */
|
||||
#endif /* _HAPROXY_SSL_GENCERT_H */
|
||||
|
|
|
|||
|
|
@ -25,13 +25,12 @@
|
|||
|
||||
|
||||
#include <haproxy/connection.h>
|
||||
#include <haproxy/counters.h>
|
||||
#include <haproxy/openssl-compat.h>
|
||||
#include <haproxy/pool-t.h>
|
||||
#include <haproxy/proxy-t.h>
|
||||
#include <haproxy/quic_conn-t.h>
|
||||
#include <haproxy/ssl_sock-t.h>
|
||||
#include <haproxy/stats-t.h>
|
||||
#include <haproxy/stats.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
extern struct list tlskeys_reference;
|
||||
|
|
@ -74,7 +73,7 @@ int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx,
|
|||
const char **str, int *len);
|
||||
int ssl_bio_and_sess_init(struct connection *conn, SSL_CTX *ssl_ctx,
|
||||
SSL **ssl, BIO **bio, BIO_METHOD *bio_meth, void *ctx);
|
||||
void ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv);
|
||||
int ssl_sock_srv_try_reuse_sess(struct ssl_sock_ctx *ctx, struct server *srv);
|
||||
const char *ssl_sock_get_sni(struct connection *conn);
|
||||
const char *ssl_sock_get_cert_sig(struct connection *conn);
|
||||
const char *ssl_sock_get_cipher_name(struct connection *conn);
|
||||
|
|
|
|||
|
|
@ -34,10 +34,10 @@ int cert_get_pkey_algo(X509 *crt, struct buffer *out);
|
|||
int ssl_sock_get_serial(X509 *crt, struct buffer *out);
|
||||
int ssl_sock_crt2der(X509 *crt, struct buffer *out);
|
||||
int ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out);
|
||||
int ssl_sock_get_dn_entry(__X509_NAME_CONST__ X509_NAME *a, const struct buffer *entry, int pos,
|
||||
int ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
|
||||
struct buffer *out);
|
||||
int ssl_sock_get_dn_formatted(__X509_NAME_CONST__ X509_NAME *a, const struct buffer *format, struct buffer *out);
|
||||
int ssl_sock_get_dn_oneline(__X509_NAME_CONST__ X509_NAME *a, struct buffer *out);
|
||||
int ssl_sock_get_dn_formatted(X509_NAME *a, const struct buffer *format, struct buffer *out);
|
||||
int ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out);
|
||||
X509* ssl_sock_get_peer_certificate(SSL *ssl);
|
||||
X509* ssl_sock_get_verified_chain_root(SSL *ssl);
|
||||
unsigned int openssl_version_parser(const char *version);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ struct shm_stats_file_hdr {
|
|||
/* 2 bytes hole */
|
||||
uint global_now_ms; /* global monotonic date (ms) common to all processes using the shm */
|
||||
ullong global_now_ns; /* global monotonic date (ns) common to all processes using the shm */
|
||||
ALWAYS_PAD(8); // 8 bytes hole
|
||||
llong now_offset; /* offset applied to global monotonic date on startup */
|
||||
/* each process uses one slot and is identified using its pid, max 64 in order
|
||||
* to be able to use bitmask to refer to a process and then look its pid in the
|
||||
* "slots.pid" map
|
||||
|
|
@ -47,7 +47,7 @@ struct shm_stats_file_hdr {
|
|||
*/
|
||||
struct {
|
||||
pid_t pid;
|
||||
uint heartbeat; // last activity of this process + heartbeat timeout, in ticks
|
||||
int heartbeat; // last activity of this process + heartbeat timeout, in ticks
|
||||
} slots[64];
|
||||
int objects; /* actual number of objects stored in the shm */
|
||||
int objects_slots; /* total available objects slots unless map is resized */
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include <import/ebtree-t.h>
|
||||
#include <haproxy/api-t.h>
|
||||
#include <haproxy/buf-t.h>
|
||||
#include <haproxy/counters-t.h>
|
||||
|
||||
/* Flags for applet.ctx.stats.flags */
|
||||
#define STAT_F_FMT_HTML 0x00000001 /* dump the stats in HTML format */
|
||||
|
|
@ -516,13 +515,23 @@ struct field {
|
|||
} u;
|
||||
};
|
||||
|
||||
enum counters_type {
|
||||
COUNTERS_FE = 0,
|
||||
COUNTERS_BE,
|
||||
COUNTERS_SV,
|
||||
COUNTERS_LI,
|
||||
COUNTERS_RSLV,
|
||||
|
||||
COUNTERS_OFF_END
|
||||
};
|
||||
|
||||
/* Entity used to generate statistics on an HAProxy component */
|
||||
struct stats_module {
|
||||
struct list list;
|
||||
const char *name;
|
||||
|
||||
/* function used to generate the stats module using counters provided through data parameter */
|
||||
int (*fill_stats)(struct stats_module *, struct extra_counters *, struct field *, unsigned int *);
|
||||
/* functor used to generate the stats module using counters provided through data parameter */
|
||||
int (*fill_stats)(void *data, struct field *, unsigned int *);
|
||||
|
||||
struct stat_col *stats; /* statistics provided by the module */
|
||||
void *counters; /* initial values of allocated counters */
|
||||
|
|
@ -534,6 +543,12 @@ struct stats_module {
|
|||
char clearable; /* reset on a clear counters */
|
||||
};
|
||||
|
||||
struct extra_counters {
|
||||
char *data; /* heap containing counters allocated in a linear fashion */
|
||||
size_t size; /* size of allocated data */
|
||||
enum counters_type type; /* type of object containing the counters */
|
||||
};
|
||||
|
||||
/* stats_domain is used in a flag as a 1 byte field */
|
||||
enum stats_domain {
|
||||
STATS_DOMAIN_PROXY = 0,
|
||||
|
|
@ -578,9 +593,58 @@ struct show_stat_ctx {
|
|||
int iid, type, sid; /* proxy id, type and service id if bounding of stats is enabled */
|
||||
int st_code; /* the status code returned by an action */
|
||||
struct buffer chunk; /* temporary buffer which holds a single-line output */
|
||||
struct watcher px_watch; /* watcher to automatically update obj1 on backend deletion */
|
||||
struct watcher srv_watch; /* watcher to automatically update obj2 on server deletion */
|
||||
enum stat_state state; /* phase of output production */
|
||||
};
|
||||
|
||||
extern THREAD_LOCAL void *trash_counters;
|
||||
|
||||
#define EXTRA_COUNTERS(name) \
|
||||
struct extra_counters *name
|
||||
|
||||
#define EXTRA_COUNTERS_GET(counters, mod) \
|
||||
(likely(counters) ? \
|
||||
((void *)((counters)->data + (mod)->counters_off[(counters)->type])) : \
|
||||
(trash_counters))
|
||||
|
||||
#define EXTRA_COUNTERS_REGISTER(counters, ctype, alloc_failed_label) \
|
||||
do { \
|
||||
typeof(*counters) _ctr; \
|
||||
_ctr = calloc(1, sizeof(*_ctr)); \
|
||||
if (!_ctr) \
|
||||
goto alloc_failed_label; \
|
||||
_ctr->type = (ctype); \
|
||||
*(counters) = _ctr; \
|
||||
} while (0)
|
||||
|
||||
#define EXTRA_COUNTERS_ADD(mod, counters, new_counters, csize) \
|
||||
do { \
|
||||
typeof(counters) _ctr = (counters); \
|
||||
(mod)->counters_off[_ctr->type] = _ctr->size; \
|
||||
_ctr->size += (csize); \
|
||||
} while (0)
|
||||
|
||||
#define EXTRA_COUNTERS_ALLOC(counters, alloc_failed_label) \
|
||||
do { \
|
||||
typeof(counters) _ctr = (counters); \
|
||||
_ctr->data = malloc((_ctr)->size); \
|
||||
if (!_ctr->data) \
|
||||
goto alloc_failed_label; \
|
||||
} while (0)
|
||||
|
||||
#define EXTRA_COUNTERS_INIT(counters, mod, init_counters, init_counters_size) \
|
||||
do { \
|
||||
typeof(counters) _ctr = (counters); \
|
||||
memcpy(_ctr->data + mod->counters_off[_ctr->type], \
|
||||
(init_counters), (init_counters_size)); \
|
||||
} while (0)
|
||||
|
||||
#define EXTRA_COUNTERS_FREE(counters) \
|
||||
do { \
|
||||
if (counters) { \
|
||||
free((counters)->data); \
|
||||
free(counters); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* _HAPROXY_STATS_T_H */
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
#define _HAPROXY_STATS_H
|
||||
|
||||
#include <haproxy/api.h>
|
||||
#include <haproxy/counters.h>
|
||||
#include <haproxy/listener-t.h>
|
||||
#include <haproxy/stats-t.h>
|
||||
#include <haproxy/tools-t.h>
|
||||
|
|
@ -168,8 +167,7 @@ static inline enum stats_domain_px_cap stats_px_get_cap(uint32_t domain)
|
|||
}
|
||||
|
||||
int stats_allocate_proxy_counters_internal(struct extra_counters **counters,
|
||||
int type, int px_cap,
|
||||
char **storage, size_t step);
|
||||
int type, int px_cap);
|
||||
int stats_allocate_proxy_counters(struct proxy *px);
|
||||
|
||||
void stats_register_module(struct stats_module *m);
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ static forceinline char *sc_show_flags(char *buf, size_t len, const char *delim,
|
|||
_(SC_FL_NEED_BUFF, _(SC_FL_NEED_ROOM,
|
||||
_(SC_FL_RCV_ONCE, _(SC_FL_SND_ASAP, _(SC_FL_SND_NEVERWAIT, _(SC_FL_SND_EXP_MORE,
|
||||
_(SC_FL_ABRT_WANTED, _(SC_FL_SHUT_WANTED, _(SC_FL_ABRT_DONE, _(SC_FL_SHUT_DONE,
|
||||
_(SC_FL_EOS, _(SC_FL_HAVE_BUFF, _(SC_FL_NO_FASTFWD)))))))))))))))))))));
|
||||
_(SC_FL_EOS, _(SC_FL_HAVE_BUFF))))))))))))))))))));
|
||||
/* epilogue */
|
||||
_(~0U);
|
||||
return buf;
|
||||
|
|
@ -349,6 +349,19 @@ struct sedesc {
|
|||
unsigned long long kop; /* Known outgoing payload length (see above) */
|
||||
};
|
||||
|
||||
/* sc_app_ops describes the application layer's operations and notification
|
||||
* callbacks when I/O activity is reported and to use to perform shutr/shutw.
|
||||
* There are very few combinations in practice (strm/chk <-> none/mux/applet).
|
||||
*/
|
||||
struct sc_app_ops {
|
||||
void (*chk_rcv)(struct stconn *); /* chk_rcv function, may not be null */
|
||||
void (*chk_snd)(struct stconn *); /* chk_snd function, may not be null */
|
||||
void (*abort)(struct stconn *); /* abort function, may not be null */
|
||||
void (*shutdown)(struct stconn *); /* shutdown function, may not be null */
|
||||
int (*wake)(struct stconn *); /* data-layer callback to report activity */
|
||||
char name[8]; /* data layer name, zero-terminated */
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure describes the elements of a connection relevant to a stream
|
||||
*/
|
||||
|
|
@ -370,6 +383,7 @@ struct stconn {
|
|||
struct wait_event wait_event; /* We're in a wait list */
|
||||
struct sedesc *sedesc; /* points to the stream endpoint descriptor */
|
||||
enum obj_type *app; /* points to the applicative point (stream or check) */
|
||||
const struct sc_app_ops *app_ops; /* general operations used at the app layer */
|
||||
struct sockaddr_storage *src; /* source address (pool), when known, otherwise NULL */
|
||||
struct sockaddr_storage *dst; /* destination address (pool), when known, otherwise NULL */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#include <haproxy/api.h>
|
||||
#include <haproxy/connection.h>
|
||||
#include <haproxy/hstream-t.h>
|
||||
#include <haproxy/htx-t.h>
|
||||
#include <haproxy/obj_type.h>
|
||||
#include <haproxy/stconn-t.h>
|
||||
|
|
@ -46,19 +45,15 @@ void se_shutdown(struct sedesc *sedesc, enum se_shut_mode mode);
|
|||
struct stconn *sc_new_from_endp(struct sedesc *sedesc, struct session *sess, struct buffer *input);
|
||||
struct stconn *sc_new_from_strm(struct stream *strm, unsigned int flags);
|
||||
struct stconn *sc_new_from_check(struct check *check, unsigned int flags);
|
||||
struct stconn *sc_new_from_haterm(struct sedesc *sd, struct session *sess, struct buffer *input);
|
||||
void sc_free(struct stconn *sc);
|
||||
|
||||
int sc_attach_mux(struct stconn *sc, void *target, void *ctx);
|
||||
int sc_attach_strm(struct stconn *sc, struct stream *strm);
|
||||
int sc_attach_hstream(struct stconn *sc, struct hstream *hs);
|
||||
|
||||
void sc_destroy(struct stconn *sc);
|
||||
int sc_reset_endp(struct stconn *sc);
|
||||
|
||||
struct appctx *sc_applet_create(struct stconn *sc, struct applet *app);
|
||||
int sc_applet_process(struct stconn *sc);
|
||||
int sc_conn_process(struct stconn *sc);
|
||||
|
||||
void sc_conn_prepare_endp_upgrade(struct stconn *sc);
|
||||
void sc_conn_abort_endp_upgrade(struct stconn *sc);
|
||||
|
|
@ -336,19 +331,14 @@ static inline struct check *sc_check(const struct stconn *sc)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns the haterm stream from a sc if the application is a
|
||||
* haterm stream. Otherwise NULL is returned. __sc_hstream() returns the haterm
|
||||
* stream without any control while sc_hstream() check the application type.
|
||||
/* Returns the name of the application layer's name for the stconn,
|
||||
* or "NONE" when none is attached.
|
||||
*/
|
||||
static inline struct hstream *__sc_hstream(const struct stconn *sc)
|
||||
static inline const char *sc_get_data_name(const struct stconn *sc)
|
||||
{
|
||||
return __objt_hstream(sc->app);
|
||||
}
|
||||
static inline struct hstream *sc_hstream(const struct stconn *sc)
|
||||
{
|
||||
if (obj_type(sc->app) == OBJ_TYPE_HATERM)
|
||||
return __objt_hstream(sc->app);
|
||||
return NULL;
|
||||
if (!sc->app_ops)
|
||||
return "NONE";
|
||||
return sc->app_ops->name;
|
||||
}
|
||||
|
||||
/* Returns non-zero if the stream connector's Rx path is blocked because of
|
||||
|
|
@ -407,6 +397,67 @@ static inline void se_need_remote_conn(struct sedesc *se)
|
|||
se_fl_set(se, SE_FL_APPLET_NEED_CONN);
|
||||
}
|
||||
|
||||
/* The application layer tells the stream connector that it just got the input
|
||||
* buffer it was waiting for. A read activity is reported. The SC_FL_HAVE_BUFF
|
||||
* flag is set and held until sc_used_buff() is called to indicate it was
|
||||
* used.
|
||||
*/
|
||||
static inline void sc_have_buff(struct stconn *sc)
|
||||
{
|
||||
if (sc->flags & SC_FL_NEED_BUFF) {
|
||||
sc->flags &= ~SC_FL_NEED_BUFF;
|
||||
sc->flags |= SC_FL_HAVE_BUFF;
|
||||
sc_ep_report_read_activity(sc);
|
||||
}
|
||||
}
|
||||
|
||||
/* The stream connector failed to get an input buffer and is waiting for it.
|
||||
* It indicates a willingness to deliver data to the buffer that will have to
|
||||
* be retried. As such, callers will often automatically clear SE_FL_HAVE_NO_DATA
|
||||
* to be called again as soon as SC_FL_NEED_BUFF is cleared.
|
||||
*/
|
||||
static inline void sc_need_buff(struct stconn *sc)
|
||||
{
|
||||
sc->flags |= SC_FL_NEED_BUFF;
|
||||
}
|
||||
|
||||
/* The stream connector indicates that it has successfully allocated the buffer
|
||||
* it was previously waiting for so it drops the SC_FL_HAVE_BUFF bit.
|
||||
*/
|
||||
static inline void sc_used_buff(struct stconn *sc)
|
||||
{
|
||||
sc->flags &= ~SC_FL_HAVE_BUFF;
|
||||
}
|
||||
|
||||
/* Tell a stream connector some room was made in the input buffer and any
|
||||
* failed attempt to inject data into it may be tried again. This is usually
|
||||
* called after a successful transfer of buffer contents to the other side.
|
||||
* A read activity is reported.
|
||||
*/
|
||||
static inline void sc_have_room(struct stconn *sc)
|
||||
{
|
||||
if (sc->flags & SC_FL_NEED_ROOM) {
|
||||
sc->flags &= ~SC_FL_NEED_ROOM;
|
||||
sc->room_needed = 0;
|
||||
sc_ep_report_read_activity(sc);
|
||||
}
|
||||
}
|
||||
|
||||
/* The stream connector announces it failed to put data into the input buffer
|
||||
* by lack of room. Since it indicates a willingness to deliver data to the
|
||||
* buffer that will have to be retried. Usually the caller will also clear
|
||||
* SE_FL_HAVE_NO_DATA to be called again as soon as SC_FL_NEED_ROOM is cleared.
|
||||
*
|
||||
* The caller is responsible to specified the amount of free space required to
|
||||
* progress. It must take care to not exceed the buffer size.
|
||||
*/
|
||||
static inline void sc_need_room(struct stconn *sc, ssize_t room_needed)
|
||||
{
|
||||
sc->flags |= SC_FL_NEED_ROOM;
|
||||
BUG_ON_HOT(room_needed > (ssize_t)global.tune.bufsize);
|
||||
sc->room_needed = room_needed;
|
||||
}
|
||||
|
||||
/* The stream endpoint indicates that it's ready to consume data from the
|
||||
* stream's output buffer. Report a send activity if the SE is unblocked.
|
||||
*/
|
||||
|
|
@ -452,7 +503,7 @@ static inline size_t se_nego_ff(struct sedesc *se, struct buffer *input, size_t
|
|||
goto end;
|
||||
}
|
||||
|
||||
ret = CALL_MUX_WITH_RET(mux, nego_fastfwd(se->sc, input, count, flags));
|
||||
ret = mux->nego_fastfwd(se->sc, input, count, flags);
|
||||
if (se->iobuf.flags & IOBUF_FL_FF_BLOCKED) {
|
||||
sc_ep_report_blocked_send(se->sc, 0);
|
||||
|
||||
|
|
@ -485,7 +536,7 @@ static inline size_t se_done_ff(struct sedesc *se)
|
|||
size_t to_send = se_ff_data(se);
|
||||
|
||||
BUG_ON(!mux->done_fastfwd);
|
||||
ret = CALL_MUX_WITH_RET(mux, done_fastfwd(se->sc));
|
||||
ret = mux->done_fastfwd(se->sc);
|
||||
if (ret) {
|
||||
/* Something was forwarded, unblock the zero-copy forwarding.
|
||||
* If all data was sent, report and send activity.
|
||||
|
|
@ -517,7 +568,7 @@ static inline size_t se_done_ff(struct sedesc *se)
|
|||
}
|
||||
}
|
||||
}
|
||||
se->sc->bytes_out += ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -180,7 +180,6 @@ enum {
|
|||
STRM_EVT_SHUT_SRV_DOWN = 0x00000004, /* Must be shut because the selected server became available */
|
||||
STRM_EVT_SHUT_SRV_UP = 0x00000008, /* Must be shut because a preferred server became available */
|
||||
STRM_EVT_KILLED = 0x00000010, /* Must be shut for external reason */
|
||||
STRM_EVT_RES = 0x00000020, /* A requested resource is available (a buffer, a conn_slot...) */
|
||||
};
|
||||
|
||||
/* This function is used to report flags in debugging tools. Please reflect
|
||||
|
|
@ -321,10 +320,7 @@ struct stream {
|
|||
struct list *current_rule_list; /* this is used to store the current executed rule list. */
|
||||
void *current_rule; /* this is used to store the current rule to be resumed. */
|
||||
int rules_exp; /* expiration date for current rules execution */
|
||||
int tunnel_timeout; /* per-stream tunnel timeout, set by set-timeout action */
|
||||
int connect_timeout; /* per-stream connect timeout, set by set-timeout action */
|
||||
int queue_timeout; /* per-stream queue timeout, set by set-timeout action */
|
||||
int tarpit_timeout; /* per-stream tarpit timeout, set by set-timeout action */
|
||||
int tunnel_timeout;
|
||||
|
||||
struct {
|
||||
void *ptr; /* Pointer on the entity (def: NULL) */
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ extern struct pool_head *pool_head_uniqueid;
|
|||
|
||||
extern struct data_cb sess_conn_cb;
|
||||
|
||||
void *stream_new(struct session *sess, struct stconn *sc, struct buffer *input);
|
||||
struct stream *stream_new(struct session *sess, struct stconn *sc, struct buffer *input);
|
||||
void stream_free(struct stream *s);
|
||||
int stream_upgrade_from_sc(struct stconn *sc, struct buffer *input);
|
||||
int stream_set_http_mode(struct stream *s, const struct mux_proto_list *mux_proto);
|
||||
|
|
@ -412,7 +412,6 @@ static inline void stream_shutdown(struct stream *s, int why)
|
|||
static inline unsigned int stream_map_task_state(unsigned int state)
|
||||
{
|
||||
return ((state & TASK_WOKEN_TIMER) ? STRM_EVT_TIMER : 0) |
|
||||
((state & TASK_WOKEN_RES) ? STRM_EVT_RES : 0) |
|
||||
((state & TASK_WOKEN_MSG) ? STRM_EVT_MSG : 0) |
|
||||
((state & TASK_F_UEVT1) ? STRM_EVT_SHUT_SRV_DOWN : 0) |
|
||||
((state & TASK_F_UEVT3) ? STRM_EVT_SHUT_SRV_UP : 0) |
|
||||
|
|
|
|||
|
|
@ -130,22 +130,20 @@ struct notification {
|
|||
* on return.
|
||||
*/
|
||||
#define TASK_COMMON \
|
||||
unsigned int state; /* task state : bitfield of TASK_ */ \
|
||||
int tid; /* tid of task/tasklet. <0 = local for tasklet, unbound for task */ \
|
||||
struct task *(*process)(struct task *t, void *ctx, unsigned int state); /* the function which processes the task */ \
|
||||
void *context; /* the task's context */ \
|
||||
const struct ha_caller *caller; /* call place of last wakeup(); 0 on init, -1 on free */ \
|
||||
uint32_t wake_date; /* date of the last task wakeup */ \
|
||||
unsigned int calls; /* number of times process was called */ \
|
||||
TASK_DEBUG_STORAGE; \
|
||||
short last_run; /* 16-bit now_ms of last run */
|
||||
/* a 16- or 48-bit hole remains here and is used by task */
|
||||
struct { \
|
||||
unsigned int state; /* task state : bitfield of TASK_ */ \
|
||||
int tid; /* tid of task/tasklet. <0 = local for tasklet, unbound for task */ \
|
||||
struct task *(*process)(struct task *t, void *ctx, unsigned int state); /* the function which processes the task */ \
|
||||
void *context; /* the task's context */ \
|
||||
const struct ha_caller *caller; /* call place of last wakeup(); 0 on init, -1 on free */ \
|
||||
uint32_t wake_date; /* date of the last task wakeup */ \
|
||||
unsigned int calls; /* number of times process was called */ \
|
||||
TASK_DEBUG_STORAGE; \
|
||||
}
|
||||
|
||||
/* The base for all tasks */
|
||||
struct task {
|
||||
TASK_COMMON; /* must be at the beginning! */
|
||||
short nice; /* task prio from -1024 to +1024 */
|
||||
int expire; /* next expiration date for this task, in ticks */
|
||||
struct eb32_node rq; /* ebtree node used to hold the task in the run queue */
|
||||
/* WARNING: the struct task is often aliased as a struct tasklet when
|
||||
* it is NOT in the run queue. The tasklet has its struct list here
|
||||
|
|
@ -153,12 +151,14 @@ struct task {
|
|||
* ever reorder these fields without taking this into account!
|
||||
*/
|
||||
struct eb32_node wq; /* ebtree node used to hold the task in the wait queue */
|
||||
int expire; /* next expiration date for this task, in ticks */
|
||||
short nice; /* task prio from -1024 to +1024 */
|
||||
/* 16-bit hole here */
|
||||
};
|
||||
|
||||
/* lightweight tasks, without priority, mainly used for I/Os */
|
||||
struct tasklet {
|
||||
TASK_COMMON; /* must be at the beginning! */
|
||||
/* 48-bit hole here */
|
||||
struct list list;
|
||||
/* WARNING: the struct task is often aliased as a struct tasklet when
|
||||
* it is not in the run queue. The task has its struct rq here where
|
||||
|
|
|
|||
|
|
@ -121,7 +121,6 @@ enum tcpcheck_rule_type {
|
|||
/* Unused 0x000000A0..0x00000FF0 (reserved for future proto) */
|
||||
#define TCPCHK_RULES_TCP_CHK 0x00000FF0
|
||||
#define TCPCHK_RULES_PROTO_CHK 0x00000FF0 /* Mask to cover protocol check */
|
||||
#define TCPCHK_RULES_MAY_USE_SBUF 0x00001000 /* checks may try to use small buffers if possible for the request */
|
||||
|
||||
struct check;
|
||||
struct tcpcheck_connect {
|
||||
|
|
|
|||
|
|
@ -217,7 +217,6 @@ enum lock_label {
|
|||
QC_CID_LOCK,
|
||||
CACHE_LOCK,
|
||||
GUID_LOCK,
|
||||
PROXIES_DEL_LOCK,
|
||||
OTHER_LOCK,
|
||||
/* WT: make sure never to use these ones outside of development,
|
||||
* we need them for lock profiling!
|
||||
|
|
|
|||
|
|
@ -362,19 +362,15 @@ static inline unsigned long thread_isolated()
|
|||
extern uint64_t now_mono_time(void); \
|
||||
if (_LK_ != _LK_UN) { \
|
||||
th_ctx->lock_level += bal; \
|
||||
if (unlikely((th_ctx->flags & (TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_L)) == \
|
||||
(TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_L))) \
|
||||
if (unlikely(th_ctx->flags & TH_FL_TASK_PROFILING)) \
|
||||
lock_start = now_mono_time(); \
|
||||
} \
|
||||
(void)(expr); \
|
||||
if (_LK_ == _LK_UN) { \
|
||||
th_ctx->lock_level += bal; \
|
||||
if (th_ctx->lock_level == 0 &&\
|
||||
unlikely((th_ctx->flags & (TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_L)) == \
|
||||
(TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_L))) \
|
||||
if (th_ctx->lock_level == 0 && unlikely(th_ctx->flags & TH_FL_TASK_PROFILING)) \
|
||||
th_ctx->locked_total += now_mono_time() - th_ctx->lock_start_date; \
|
||||
} else if (unlikely((th_ctx->flags & (TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_L)) == \
|
||||
(TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_L))) { \
|
||||
} else if (unlikely(th_ctx->flags & TH_FL_TASK_PROFILING)) { \
|
||||
uint64_t now = now_mono_time(); \
|
||||
if (lock_start) \
|
||||
th_ctx->lock_wait_total += now - lock_start; \
|
||||
|
|
@ -388,8 +384,7 @@ static inline unsigned long thread_isolated()
|
|||
typeof(expr) _expr = (expr); \
|
||||
if (_expr == 0) { \
|
||||
th_ctx->lock_level += bal; \
|
||||
if (unlikely((th_ctx->flags & (TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_L)) == \
|
||||
(TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_L))) { \
|
||||
if (unlikely(th_ctx->flags & TH_FL_TASK_PROFILING)) { \
|
||||
if (_LK_ == _LK_UN && th_ctx->lock_level == 0) \
|
||||
th_ctx->locked_total += now_mono_time() - th_ctx->lock_start_date; \
|
||||
else if (_LK_ != _LK_UN && th_ctx->lock_level == 1) \
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue