Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions doc/developer-guide/api/functions/TSHttpSsnInfoIntGet.en.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
.. Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed
with this work for additional information regarding copyright
ownership. The ASF licenses this file to you under the Apache
License, Version 2.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the License for the specific language governing
permissions and limitations under the License.


TSHttpSsnInfoIntGet
===================

Synopsis
--------

.. code-block:: cpp

#include <ts/ts.h>

.. c:function:: TSReturnCode TSHttpSsnInfoIntGet(TSHttpSsn ssnp, TSHttpSsnInfoKey key, TSMgmtInt * value, uint64_t subkey = 0)

Description
-----------

:c:func:`TSHttpSsnInfoIntGet` returns arbitrary integer-typed info about a session as defined in
:c:type:`TSHttpSsnInfoKey`. The API will be part of a generic API umbrella that can support returning
arbitrary info about a session using custom log tags.

The :c:type:`TSHttpSsnInfoKey` currently supports the below integer-based info about a transaction

.. c:enum:: TSHttpSsnInfoKey

.. c:enumerator:: TS_SSN_INFO_TRANSACTION_COUNT

The value indicate the number of transactions made on the session.

.. c:enumerator:: TS_SSN_INFO_RECEIVED_FRAME_COUNT

The value indicate the number of HTTP/2 or HTTP/3 frames received on the session.
A frame type must be specified by passing it to subkey.
You can use TS_SSN_INFO_RECEIVED_FRAME_COUNT_H2_UNKNOWN and TS_SSN_INFO_RECEIVED_FRAME_COUNT_H3_UNKNOWN to get the value for
unknown frames.

Return values
-------------

The API returns :c:data:`TS_SUCCESS`, if the requested info is supported, :c:data:`TS_ERROR` otherwise.
3 changes: 3 additions & 0 deletions include/proxy/ProxySession.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ class ProxySession : public VConnection, public PluginUserArgs<TS_USER_ARGS_SSN>

virtual PoolableSession *get_server_session() const;

virtual bool is_protocol_framed() const;
virtual uint64_t get_received_frame_count(uint64_t type) const;

// Replicate NetVConnection API
virtual sockaddr const *get_remote_addr() const;
virtual sockaddr const *get_local_addr();
Expand Down
13 changes: 13 additions & 0 deletions include/proxy/http2/HTTP2.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,17 @@ struct Http2StatsBlock {
Metrics::Counter::AtomicType *insufficient_avg_window_update;
Metrics::Counter::AtomicType *max_concurrent_streams_exceeded_in;
Metrics::Counter::AtomicType *max_concurrent_streams_exceeded_out;
Metrics::Counter::AtomicType *data_frames_in;
Metrics::Counter::AtomicType *headers_frames_in;
Metrics::Counter::AtomicType *priority_frames_in;
Metrics::Counter::AtomicType *rst_stream_frames_in;
Metrics::Counter::AtomicType *settings_frames_in;
Metrics::Counter::AtomicType *push_promise_frames_in;
Metrics::Counter::AtomicType *ping_frames_in;
Metrics::Counter::AtomicType *goaway_frames_in;
Metrics::Counter::AtomicType *window_update_frames_in;
Metrics::Counter::AtomicType *continuation_frames_in;
Metrics::Counter::AtomicType *unknown_frames_in;
};

extern Http2StatsBlock http2_rsb;
Expand Down Expand Up @@ -166,6 +177,8 @@ enum Http2FrameType {
HTTP2_FRAME_TYPE_MAX,
};

extern Metrics::Counter::AtomicType *http2_frame_metrics_in[HTTP2_FRAME_TYPE_MAX + 1];

// [RFC 7540] 6.1. Data
enum Http2FrameFlagsData {
HTTP2_FLAGS_DATA_END_STREAM = 0x01,
Expand Down
2 changes: 2 additions & 0 deletions include/proxy/http2/Http2ClientSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class Http2ClientSession : public ProxySession, public Http2CommonSession
void destroy() override;
void release(ProxyTransaction *trans) override;
void free() override;
bool is_protocol_framed() const override;
uint64_t get_received_frame_count(uint64_t type) const override;

////////////////////
// Accessors
Expand Down
20 changes: 20 additions & 0 deletions include/proxy/http2/Http2CommonSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ class Http2CommonSession
int do_start_frame_read(Http2ErrorCode &ret_error);
int do_complete_frame_read();

/**
* Count received frames
*/
void _count_received_frames(uint32_t type);

bool _should_do_something_else();

////////
Expand Down Expand Up @@ -169,6 +174,21 @@ class Http2CommonSession
int64_t read_from_early_data = 0;
bool cur_frame_from_early_data = false;

// Counter for received frames
std::atomic<uint64_t> _frame_counts_in[HTTP2_FRAME_TYPE_MAX + 1] = {
Copy link
Copy Markdown
Contributor

@bryancall bryancall Nov 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why doesd this need to be atomic? h2 connections shouldn't be handled on multiple threads.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that is true, but we have a lot of SCOPED_MUTEX_LOCK in http2 code and other counters for H2 use atomic too. I don't want any surprise from this PR.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an index enum for these values?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is Http2FrameType, and HTTP2_FRAME_TYPE_MAX is the last item. We need one extra space for unknown type.

0, // DATA
0, // HEADERS
0, // PRIORITY
0, // RST_STREAM
0, // SETTINGS
0, // PUSH_PROMISE
0, // PING
0, // GOAWAY
0, // WINDOW_UPDATE
0, // CONTINUATION
0 // UNKNOWN
};

private:
bool _interrupt_reading_frames = false;
};
Expand Down
2 changes: 2 additions & 0 deletions include/proxy/http2/Http2ServerSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class Http2ServerSession : public PoolableSession, public Http2CommonSession
void release(ProxyTransaction *trans) override;
void free() override;
ProxyTransaction *new_transaction() override;
bool is_protocol_framed() const override;
uint64_t get_received_frame_count(uint64_t type) const override;

void add_session() override;
void remove_session();
Expand Down
10 changes: 10 additions & 0 deletions include/proxy/http3/Http3.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include "tscore/ink_defs.h"
#include "tsutil/Metrics.h"
#include "Http3Types.h"

using ts::Metrics;

Expand All @@ -44,6 +45,15 @@ struct Http3StatsBlock {
// Example: Metrics::Counter::AtomicType *current_client_session_count;
// Once created, e.g.
// Metrics::Counter::increment(http3_rsb.current_client_session_count);
Metrics::Counter::AtomicType *data_frames_in;
Metrics::Counter::AtomicType *headers_frames_in;
Metrics::Counter::AtomicType *cancel_push_frames_in;
Metrics::Counter::AtomicType *settings_frames_in;
Metrics::Counter::AtomicType *push_promise_frames_in;
Metrics::Counter::AtomicType *goaway_frames_in;
Metrics::Counter::AtomicType *max_push_id;
Metrics::Counter::AtomicType *unknown_frames_in;
};

extern Http3StatsBlock http3_rsb; // Container for statistics.
extern Metrics::Counter::AtomicType *http3_frame_metrics_in[static_cast<int>(Http3FrameType::UNKNOWN) + 1];
60 changes: 60 additions & 0 deletions include/proxy/http3/Http3FrameCounter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/** @file
*
* A brief file description
*
* @section license License
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include "proxy/http3/Http3Types.h"
#include "proxy/http3/Http3FrameHandler.h"

class Http3FrameCounter : public Http3FrameHandler
{
public:
Http3FrameCounter(){};

// Http3FrameHandler
std::vector<Http3FrameType> interests() override;
Http3ErrorUPtr handle_frame(std::shared_ptr<const Http3Frame> frame, int32_t frame_seq = -1,
Http3StreamType s_type = Http3StreamType::UNKNOWN) override;

uint64_t get_count(uint64_t type) const;

private:
// Counter for received frames
std::atomic<uint64_t> _frame_counts_in[static_cast<int>(Http3FrameType::UNKNOWN) + 1] = {
0, // DATA
0, // HEADERS
0, // X_RESERVED_1
0, // CANCEL_PUSH
0, // SETTINGS
0, // PUSH_PROMISE
0, // X_RESERVED_2
0, // GOAWAY
0, // X_RESERVED_3
0, // X_RESERVED_4
0, // UNDEFINED
0, // UNDEFINED
0, // UNDEFINED
0, // MAX_PUSH_ID
0 // UNKNOWN
};
};
5 changes: 5 additions & 0 deletions include/proxy/http3/Http3Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include "proxy/ProxySession.h"
#include "proxy/http3/Http3Transaction.h"
#include "proxy/http3/Http3FrameCounter.h"
#include "proxy/http3/QPACK.h"

class HQSession : public ProxySession
Expand Down Expand Up @@ -76,16 +77,20 @@ class Http3Session : public HQSession
HTTPVersion get_version(HTTPHdr &hdr) const override;
void increment_current_active_connections_stat() override;
void decrement_current_active_connections_stat() override;
bool is_protocol_framed() const override;
uint64_t get_received_frame_count(uint64_t type) const override;

// Implement ProxySession interface
const char *get_protocol_string() const override;

QPACK *local_qpack();
QPACK *remote_qpack();
Http3FrameCounter *get_received_frame_counter();

private:
QPACK *_remote_qpack = nullptr; // QPACK for decoding
QPACK *_local_qpack = nullptr; // QPACK for encoding
Http3FrameCounter _received_frame_counter;
};

/**
Expand Down
27 changes: 13 additions & 14 deletions include/proxy/http3/Http3Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,19 @@ enum class Http3SettingsId : uint64_t {

// Update Http3Frame::type(const uint8_t *) too when you modify this list
enum class Http3FrameType : uint64_t {
DATA = 0x00,
HEADERS = 0x01,
PRIORITY = 0x02,
CANCEL_PUSH = 0x03,
SETTINGS = 0x04,
PUSH_PROMISE = 0x05,
X_RESERVED_1 = 0x06,
GOAWAY = 0x07,
X_RESERVED_2 = 0x08,
X_RESERVED_3 = 0x09,
MAX_PUSH_ID = 0x0D,
DUPLICATE_PUSH_ID = 0x0E,
X_MAX_DEFINED = 0x0E,
UNKNOWN = 0xFF,
DATA = 0x00,
HEADERS = 0x01,
X_RESERVED_1 = 0x02,
CANCEL_PUSH = 0x03,
SETTINGS = 0x04,
PUSH_PROMISE = 0x05,
X_RESERVED_2 = 0x06,
GOAWAY = 0x07,
X_RESERVED_3 = 0x08,
X_RESERVED_4 = 0x09,
MAX_PUSH_ID = 0x0D,
X_MAX_DEFINED = 0x0D,
UNKNOWN = 0x0E,
};

enum class Http3ErrorClass {
Expand Down
9 changes: 9 additions & 0 deletions include/ts/apidefs.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,15 @@ char const TS_VERSION_STRING[] = "@TS_VERSION_STRING@";
TS_TXN_INFO_LAST_ENTRY,
};

enum TSHttpSsnInfoKey {
TS_SSN_INFO_NONE = -1,
TS_SSN_INFO_TRANSACTION_COUNT,
TS_SSN_INFO_RECEIVED_FRAME_COUNT,
};

#define TS_SSN_INFO_RECEIVED_FRAME_COUNT_H2_UNKNOWN 999
#define TS_SSN_INFO_RECEIVED_FRAME_COUNT_H3_UNKNOWN 0x21
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this 0x21 when the index enum value is 0x0e?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because 0x0e is just an unassigned number (it could be used later for something). 0x21 is reserved for exercising and will never be used.
https://datatracker.ietf.org/doc/html/rfc9114#name-reserved-frame-types


enum TSVConnCloseFlags {
TS_VC_CLOSE_ABORT = -1,
TS_VC_CLOSE_NORMAL = 1,
Expand Down
13 changes: 13 additions & 0 deletions include/ts/ts.h
Original file line number Diff line number Diff line change
Expand Up @@ -3036,6 +3036,19 @@ namespace c
*/
TSReturnCode TSHttpTxnInfoIntGet(TSHttpTxn txnp, TSHttpTxnInfoKey key, TSMgmtInt *value);

/* Get Arbitrary Ssn info such as total transaction count etc as defined in TSHttpSsnInfoKey */
/**
Return the particular ssn info requested.

@param ssnp the transaction pointer
@param key the requested ssn info.
@param TSMgmtInt a pointer to a integer where the return value is stored

@return @c TS_SUCCESS if the requested info is supported, TS_ERROR otherwise

*/
TSReturnCode TSHttpSsnInfoIntGet(TSHttpSsn ssnp, TSHttpSsnInfoKey key, TSMgmtInt *value, uint64_t sub_key = 0);

/****************************************************************************
* TSHttpTxnCacheLookupCountGet
* Return: TS_SUCCESS/TS_ERROR
Expand Down
25 changes: 25 additions & 0 deletions src/api/InkAPI.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4933,6 +4933,31 @@ tsapi::c::TSHttpTxnInfoIntGet(TSHttpTxn txnp, TSHttpTxnInfoKey key, TSMgmtInt *v
return TS_SUCCESS;
}

TSReturnCode
tsapi::c::TSHttpSsnInfoIntGet(TSHttpSsn ssnp, TSHttpSsnInfoKey key, TSMgmtInt *value, uint64_t sub_key)
{
sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)value) == TS_SUCCESS);

ProxySession *ssn = reinterpret_cast<ProxySession *>(ssnp);

switch (key) {
case TS_SSN_INFO_TRANSACTION_COUNT:
*value = ssn->get_transact_count();
break;
case TS_SSN_INFO_RECEIVED_FRAME_COUNT:
if (!ssn->is_protocol_framed()) {
return TS_ERROR;
}
*value = ssn->get_received_frame_count(sub_key);
break;
default:
return TS_ERROR;
}

return TS_SUCCESS;
}

int
tsapi::c::TSHttpTxnIsWebsocket(TSHttpTxn txnp)
{
Expand Down
12 changes: 12 additions & 0 deletions src/proxy/ProxySession.cc
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,18 @@ ProxySession::get_server_session() const
return nullptr;
}

bool
ProxySession::is_protocol_framed() const
{
return false;
}

uint64_t
ProxySession::get_received_frame_count(uint64_t type) const
{
return 0;
}

void
ProxySession::set_active_timeout(ink_hrtime timeout_in)
{
Expand Down
Loading