b180765de2a197beaf3feddb80b2bd2ac23ad965
[samplevnf.git] / VNFs / DPPD-PROX / genl4_stream.h
1 /*
2 // Copyright (c) 2010-2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #ifndef _GENL4_STREAM_H_
18 #define _GENL4_STREAM_H_
19
20 #include "prox_lua_types.h"
21 #include "pkt_parser.h"
22 #include "token_time.h"
23 #include "quit.h"
24
25 enum tcp_state {
26         CLOSED,
27         LISTEN,
28         SYN_SENT,
29         SYN_RECEIVED,
30         ESTABLISHED,
31         CLOSE_WAIT,
32         LAST_ACK,
33         FIN_WAIT,
34         TIME_WAIT
35 };
36
37 static const char *tcp_state_to_str(const enum tcp_state s)
38 {
39         switch(s) {
40         case CLOSED:
41                 return "CLOSED";
42         case LISTEN:
43                 return "LISTEN";
44         case SYN_SENT:
45                 return "SYN_SENT";
46         case SYN_RECEIVED:
47                 return "SYN_RECEIVED";
48         case ESTABLISHED:
49                 return "ESTABLISHED";
50         case CLOSE_WAIT:
51                 return "CLOSE_WAIT";
52         case LAST_ACK:
53                 return "LAST_ACK";
54         case FIN_WAIT:
55                 return "FIN_WAIT";
56         case TIME_WAIT:
57                 return "TIME_WAIT";
58         default:
59                 return "INVALID_STATE";
60         }
61 }
62
63 #define STREAM_CTX_F_EXPIRED       0x01
64 #define STREAM_CTX_F_NEW_DATA      0x02 /* Set on recv to track first ACK of data */
65 #define STREAM_CTX_F_TCP_ENDED     0x04
66 #define STREAM_CTX_F_TCP_GOT_SYN   0x08 /* Set only once when syn has been received */
67 #define STREAM_CTX_F_TCP_GOT_FIN   0x10 /* Set only once when fin has been received */
68 #define STREAM_CTX_F_MORE_DATA     0x20
69 #define STREAM_CTX_F_LAST_RX_PKT_MADE_PROGRESS  0x40
70
71 /* Run-time structure to management state information associated with current stream_cfg. */
72 struct stream_ctx {
73         enum l4gen_peer         peer;
74         uint32_t                cur_action;
75         uint32_t                cur_pos[2];
76         enum tcp_state          tcp_state;
77         struct token_time       token_time;
78         struct token_time       token_time_other;
79         uint16_t                flags;
80         uint16_t                same_state;
81         uint32_t                next_seq;
82         uint32_t                ackd_seq;
83         uint32_t                recv_seq;
84         uint32_t                ackable_data_seq;
85         uint32_t                seq_first_byte;       /* seq number - seq_first_byte gives offset within content. */
86         uint32_t                other_seq_first_byte; /* seq number - seq_first_byte gives offset within content. */
87         uint32_t                other_mss;
88         uint64_t                sched_tsc;
89         uint32_t                retransmits;
90         const struct stream_cfg *stream_cfg;          /* Current active steam_cfg */
91         struct pkt_tuple        *tuple;
92 };
93
94 struct host_set {
95         uint32_t ip;
96         uint32_t ip_mask;
97         uint16_t port;
98         uint16_t port_mask;
99 };
100
101 struct stream_cfg {
102         struct peer_data   data[2];
103         struct host_set    servers; // Current implementation only allows mask == 0. (i.e. single server)
104         struct token_time_cfg tt_cfg[2]; // bytes per period rate
105         uint16_t           proto;
106         uint64_t           tsc_timeout;
107         uint64_t           tsc_timeout_time_wait;
108         uint32_t           n_actions;
109         uint32_t           n_pkts;
110         uint32_t           n_bytes;
111         int                (*proc)(struct stream_ctx *meta, struct rte_mbuf *mbuf, struct l4_meta *l4_meta, uint64_t *next_tsc);
112         int                (*is_ended)(struct stream_ctx *meta);
113         struct peer_action actions[0];
114 };
115
116 static void scale_for_jitter(uint64_t *to_scale)
117 {
118         (*to_scale) *= 2;
119 }
120
121 static void reset_token_times(struct stream_ctx *ctx)
122 {
123         const uint64_t now = rte_rdtsc();
124         const struct stream_cfg *cfg = ctx->stream_cfg;
125         enum l4gen_peer peer = ctx->peer;
126
127         token_time_init(&ctx->token_time, &cfg->tt_cfg[peer]);
128         token_time_reset_full(&ctx->token_time, now);
129
130         token_time_init(&ctx->token_time_other, &cfg->tt_cfg[!peer]);
131         scale_for_jitter(&ctx->token_time_other.cfg.bytes_max);
132         token_time_reset_full(&ctx->token_time_other, now);
133 }
134
135 static void stream_ctx_init(struct stream_ctx *ctx, enum l4gen_peer peer, struct stream_cfg *cfg, struct pkt_tuple *tuple)
136 {
137         ctx->stream_cfg = cfg;
138         ctx->peer = peer;
139         ctx->tuple = tuple;
140
141         /* Server's initial state is different from client for
142            TCP. For now, don't use a specific init function for
143            TCP/UDP since there is not a lot of difference and to avoid
144            an additional function pointer. */
145         ctx->tcp_state = PEER_CLIENT == peer? CLOSED : LISTEN;
146         ctx->other_mss = 536; /* default 536 as per RFC 879 */
147
148         reset_token_times(ctx);
149 }
150
151 static void stream_ctx_reset_move(struct stream_ctx *ctx, struct stream_cfg *cfg)
152 {
153         enum l4gen_peer peer = ctx->peer;
154         struct pkt_tuple *tuple = ctx->tuple;
155
156         memset(ctx, 0, sizeof(*ctx));
157         stream_ctx_init(ctx, peer, cfg, tuple);
158 }
159
160 static int stream_cfg_calc_max_payload_len(struct stream_cfg *cfg, enum l4gen_peer peer)
161 {
162         const uint32_t l4_hdr_len = cfg->proto == IPPROTO_UDP?
163                 sizeof(struct udp_hdr) : sizeof(struct tcp_hdr);
164
165         return ETHER_MAX_LEN - ETHER_CRC_LEN - cfg->data[peer].hdr_len - l4_hdr_len;
166 }
167
168 static int stream_cfg_max_n_segments(struct stream_cfg *cfg)
169 {
170         if (cfg->proto == IPPROTO_UDP)
171                 return 1;
172
173         uint32_t ret = 1;
174         uint32_t cur;
175
176         const uint32_t mss = stream_cfg_calc_max_payload_len(cfg, PEER_CLIENT);
177
178         for (uint32_t i = 0; i < cfg->n_actions; ++i) {
179                 cur = (cfg->actions[i].len + (mss - 1)) / mss;
180                 ret = ret > cur? ret: cur;
181         }
182
183         return ret;
184 }
185
186 static int stream_cfg_verify_action(struct stream_cfg *cfg, struct peer_action *action)
187 {
188         if (cfg->proto == IPPROTO_TCP)
189                 return 0;
190
191         uint16_t max_payload_len = stream_cfg_calc_max_payload_len(cfg, action->peer);
192
193         PROX_PANIC(action->len > max_payload_len,
194                    "Action %zu has length %u while for the maximum action length for UDP connections is limited to %u\n",
195                    action - cfg->actions,
196                    action->len,
197                    max_payload_len);
198         return 0;
199 }
200
201 #endif /* _GENL4_STREAM_H_ */