summaryrefslogtreecommitdiffstats
path: root/VNFs/DPPD-PROX/genl4_stream.h
diff options
context:
space:
mode:
Diffstat (limited to 'VNFs/DPPD-PROX/genl4_stream.h')
-rw-r--r--VNFs/DPPD-PROX/genl4_stream.h201
1 files changed, 201 insertions, 0 deletions
diff --git a/VNFs/DPPD-PROX/genl4_stream.h b/VNFs/DPPD-PROX/genl4_stream.h
new file mode 100644
index 00000000..b180765d
--- /dev/null
+++ b/VNFs/DPPD-PROX/genl4_stream.h
@@ -0,0 +1,201 @@
+/*
+// Copyright (c) 2010-2017 Intel Corporation
+//
+// Licensed 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.
+*/
+
+#ifndef _GENL4_STREAM_H_
+#define _GENL4_STREAM_H_
+
+#include "prox_lua_types.h"
+#include "pkt_parser.h"
+#include "token_time.h"
+#include "quit.h"
+
+enum tcp_state {
+ CLOSED,
+ LISTEN,
+ SYN_SENT,
+ SYN_RECEIVED,
+ ESTABLISHED,
+ CLOSE_WAIT,
+ LAST_ACK,
+ FIN_WAIT,
+ TIME_WAIT
+};
+
+static const char *tcp_state_to_str(const enum tcp_state s)
+{
+ switch(s) {
+ case CLOSED:
+ return "CLOSED";
+ case LISTEN:
+ return "LISTEN";
+ case SYN_SENT:
+ return "SYN_SENT";
+ case SYN_RECEIVED:
+ return "SYN_RECEIVED";
+ case ESTABLISHED:
+ return "ESTABLISHED";
+ case CLOSE_WAIT:
+ return "CLOSE_WAIT";
+ case LAST_ACK:
+ return "LAST_ACK";
+ case FIN_WAIT:
+ return "FIN_WAIT";
+ case TIME_WAIT:
+ return "TIME_WAIT";
+ default:
+ return "INVALID_STATE";
+ }
+}
+
+#define STREAM_CTX_F_EXPIRED 0x01
+#define STREAM_CTX_F_NEW_DATA 0x02 /* Set on recv to track first ACK of data */
+#define STREAM_CTX_F_TCP_ENDED 0x04
+#define STREAM_CTX_F_TCP_GOT_SYN 0x08 /* Set only once when syn has been received */
+#define STREAM_CTX_F_TCP_GOT_FIN 0x10 /* Set only once when fin has been received */
+#define STREAM_CTX_F_MORE_DATA 0x20
+#define STREAM_CTX_F_LAST_RX_PKT_MADE_PROGRESS 0x40
+
+/* Run-time structure to management state information associated with current stream_cfg. */
+struct stream_ctx {
+ enum l4gen_peer peer;
+ uint32_t cur_action;
+ uint32_t cur_pos[2];
+ enum tcp_state tcp_state;
+ struct token_time token_time;
+ struct token_time token_time_other;
+ uint16_t flags;
+ uint16_t same_state;
+ uint32_t next_seq;
+ uint32_t ackd_seq;
+ uint32_t recv_seq;
+ uint32_t ackable_data_seq;
+ uint32_t seq_first_byte; /* seq number - seq_first_byte gives offset within content. */
+ uint32_t other_seq_first_byte; /* seq number - seq_first_byte gives offset within content. */
+ uint32_t other_mss;
+ uint64_t sched_tsc;
+ uint32_t retransmits;
+ const struct stream_cfg *stream_cfg; /* Current active steam_cfg */
+ struct pkt_tuple *tuple;
+};
+
+struct host_set {
+ uint32_t ip;
+ uint32_t ip_mask;
+ uint16_t port;
+ uint16_t port_mask;
+};
+
+struct stream_cfg {
+ struct peer_data data[2];
+ struct host_set servers; // Current implementation only allows mask == 0. (i.e. single server)
+ struct token_time_cfg tt_cfg[2]; // bytes per period rate
+ uint16_t proto;
+ uint64_t tsc_timeout;
+ uint64_t tsc_timeout_time_wait;
+ uint32_t n_actions;
+ uint32_t n_pkts;
+ uint32_t n_bytes;
+ int (*proc)(struct stream_ctx *meta, struct rte_mbuf *mbuf, struct l4_meta *l4_meta, uint64_t *next_tsc);
+ int (*is_ended)(struct stream_ctx *meta);
+ struct peer_action actions[0];
+};
+
+static void scale_for_jitter(uint64_t *to_scale)
+{
+ (*to_scale) *= 2;
+}
+
+static void reset_token_times(struct stream_ctx *ctx)
+{
+ const uint64_t now = rte_rdtsc();
+ const struct stream_cfg *cfg = ctx->stream_cfg;
+ enum l4gen_peer peer = ctx->peer;
+
+ token_time_init(&ctx->token_time, &cfg->tt_cfg[peer]);
+ token_time_reset_full(&ctx->token_time, now);
+
+ token_time_init(&ctx->token_time_other, &cfg->tt_cfg[!peer]);
+ scale_for_jitter(&ctx->token_time_other.cfg.bytes_max);
+ token_time_reset_full(&ctx->token_time_other, now);
+}
+
+static void stream_ctx_init(struct stream_ctx *ctx, enum l4gen_peer peer, struct stream_cfg *cfg, struct pkt_tuple *tuple)
+{
+ ctx->stream_cfg = cfg;
+ ctx->peer = peer;
+ ctx->tuple = tuple;
+
+ /* Server's initial state is different from client for
+ TCP. For now, don't use a specific init function for
+ TCP/UDP since there is not a lot of difference and to avoid
+ an additional function pointer. */
+ ctx->tcp_state = PEER_CLIENT == peer? CLOSED : LISTEN;
+ ctx->other_mss = 536; /* default 536 as per RFC 879 */
+
+ reset_token_times(ctx);
+}
+
+static void stream_ctx_reset_move(struct stream_ctx *ctx, struct stream_cfg *cfg)
+{
+ enum l4gen_peer peer = ctx->peer;
+ struct pkt_tuple *tuple = ctx->tuple;
+
+ memset(ctx, 0, sizeof(*ctx));
+ stream_ctx_init(ctx, peer, cfg, tuple);
+}
+
+static int stream_cfg_calc_max_payload_len(struct stream_cfg *cfg, enum l4gen_peer peer)
+{
+ const uint32_t l4_hdr_len = cfg->proto == IPPROTO_UDP?
+ sizeof(struct udp_hdr) : sizeof(struct tcp_hdr);
+
+ return ETHER_MAX_LEN - ETHER_CRC_LEN - cfg->data[peer].hdr_len - l4_hdr_len;
+}
+
+static int stream_cfg_max_n_segments(struct stream_cfg *cfg)
+{
+ if (cfg->proto == IPPROTO_UDP)
+ return 1;
+
+ uint32_t ret = 1;
+ uint32_t cur;
+
+ const uint32_t mss = stream_cfg_calc_max_payload_len(cfg, PEER_CLIENT);
+
+ for (uint32_t i = 0; i < cfg->n_actions; ++i) {
+ cur = (cfg->actions[i].len + (mss - 1)) / mss;
+ ret = ret > cur? ret: cur;
+ }
+
+ return ret;
+}
+
+static int stream_cfg_verify_action(struct stream_cfg *cfg, struct peer_action *action)
+{
+ if (cfg->proto == IPPROTO_TCP)
+ return 0;
+
+ uint16_t max_payload_len = stream_cfg_calc_max_payload_len(cfg, action->peer);
+
+ PROX_PANIC(action->len > max_payload_len,
+ "Action %zu has length %u while for the maximum action length for UDP connections is limited to %u\n",
+ action - cfg->actions,
+ action->len,
+ max_payload_len);
+ return 0;
+}
+
+#endif /* _GENL4_STREAM_H_ */