[MAJOR] session: add track-counters to track counters related to the session
This patch adds the ability to set a pointer in the session to an
entry in a stick table which holds various counters related to a
specific pattern.
Right now the syntax matches the target syntax and only the "src"
pattern can be specified, to track counters related to the session's
IPv4 source address. There is a special function to extract it and
convert it to a key. But the goal is to be able to later support as
many patterns as for the stick rules, and get rid of the specific
function.
The "track-counters" directive may only be set in a "tcp-request"
statement right now. Only the first one applies. Probably that later
we'll support multi-criteria tracking for a single session and that
we'll have to name tracking pointers.
No counter is updated right now, only the refcount is. Some subsequent
patches will have to bring that feature.
diff --git a/include/proto/proto_tcp.h b/include/proto/proto_tcp.h
index 37d8ea8..1b46d37 100644
--- a/include/proto/proto_tcp.h
+++ b/include/proto/proto_tcp.h
@@ -25,6 +25,7 @@
#include <common/config.h>
#include <types/proto_tcp.h>
#include <types/task.h>
+#include <proto/stick_table.h>
int tcpv4_bind_socket(int fd, int flags, struct sockaddr_in *local, struct sockaddr_in *remote);
void tcpv4_add_listener(struct listener *listener);
@@ -37,6 +38,22 @@
int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit);
int tcp_exec_req_rules(struct session *s);
+/* Converts the TCPv4 source address to a stick_table key usable for table
+ * lookups. Returns either NULL if the source cannot be converted (eg: not
+ * IPv4) or a pointer to the converted result in static_table_key in the
+ * appropriate format (IP).
+ */
+static inline struct stktable_key *tcpv4_src_to_stktable_key(struct session *s)
+{
+ /* right now we only support IPv4 */
+ if (s->cli_addr.ss_family != AF_INET)
+ return NULL;
+
+ static_table_key.key = (void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr;
+ return &static_table_key;
+}
+
+
#endif /* _PROTO_PROTO_TCP_H */
/*
diff --git a/include/proto/session.h b/include/proto/session.h
index c7a693e..3d56f8e 100644
--- a/include/proto/session.h
+++ b/include/proto/session.h
@@ -25,6 +25,7 @@
#include <common/config.h>
#include <common/memory.h>
#include <types/session.h>
+#include <proto/stick_table.h>
extern struct pool_head *pool2_session;
extern struct list sessions;
@@ -40,6 +41,31 @@
struct task *process_session(struct task *t);
void sess_set_term_flags(struct session *s);
void default_srv_error(struct session *s, struct stream_interface *si);
+int parse_track_counters(char **args, int *arg,
+ int section_type, struct proxy *curpx,
+ struct track_ctr_prm *prm,
+ struct proxy *defpx, char *err, int errlen);
+
+/* Remove the refcount from the session to the tracked counters, and clear the
+ * pointer to ensure this is only performed once. The caller is responsible for
+ * ensuring that the pointer is valid first.
+ */
+static inline void session_store_counters(struct session *s)
+{
+ s->tracked_counters->ref_cnt--;
+ s->tracked_counters = NULL;
+}
+
+/* Enable tracking of session counters on stksess <ts>. The caller is
+ * responsible for ensuring that <t> and <ts> are valid pointers and that no
+ * previous tracked_counters was assigned to the session.
+ */
+static inline void session_track_counters(struct session *s, struct stktable *t, struct stksess *ts)
+{
+ ts->ref_cnt++;
+ s->tracked_table = t;
+ s->tracked_counters = ts;
+}
static void inline trace_term(struct session *s, unsigned int code)
{
diff --git a/include/proto/stick_table.h b/include/proto/stick_table.h
index db45760..813b3b9 100644
--- a/include/proto/stick_table.h
+++ b/include/proto/stick_table.h
@@ -36,6 +36,7 @@
int stktable_init(struct stktable *t);
int stktable_parse_type(char **args, int *idx, unsigned long *type, size_t *key_size);
+struct stksess *stktable_get_entry(struct stktable *table, struct stktable_key *key);
struct stksess *stktable_store(struct stktable *t, struct stksess *ts);
struct stksess *stktable_touch(struct stktable *t, struct stksess *ts);
struct stksess *stktable_lookup(struct stktable *t, struct stksess *ts);