TAS
TCP Acceleration as an OS Service
fast_kernel.c
1 /*
2  * Copyright 2019 University of Washington, Max Planck Institute for
3  * Software Systems, and The University of Texas at Austin
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include <assert.h>
26 #include <unistd.h>
27 #include <rte_config.h>
28 
29 #include <tas_memif.h>
30 
31 #include "internal.h"
32 #include "fastemu.h"
33 #include "tcp_common.h"
34 
35 
36 static inline void inject_tcp_ts(void *buf, uint16_t len, uint32_t ts,
37  struct network_buf_handle *nbh);
38 
39 int fast_kernel_poll(struct dataplane_context *ctx,
40  struct network_buf_handle *nbh, uint32_t ts)
41 {
42  void *buf = network_buf_buf(nbh);
43  struct flextcp_pl_appctx *kctx = &fp_state->kctx[ctx->id];
44  struct flextcp_pl_ktx *ktx;
45  uint32_t flow_id, len;
46  int ret = -1;
47 
48  /* stop if context is not in use */
49  if (kctx->tx_len == 0)
50  return -1;
51 
52  ktx = dma_pointer(kctx->tx_base + kctx->tx_head, sizeof(*ktx));
53 
54  if (ktx->type == 0) {
55  return -1;
56  } else if (ktx->type == FLEXTCP_PL_KTX_PACKET) {
57  len = ktx->msg.packet.len;
58 
59  /* Read transmit queue entry */
60  dma_read(ktx->msg.packet.addr, len, buf);
61 
62  ret = 0;
63  inject_tcp_ts(buf, len, ts, nbh);
64  tx_send(ctx, nbh, 0, len);
65  } else if (ktx->type == FLEXTCP_PL_KTX_PACKET_NOTS) {
66  /* send packet without filling in timestamp */
67  len = ktx->msg.packet.len;
68 
69  /* Read transmit queue entry */
70  dma_read(ktx->msg.packet.addr, len, buf);
71 
72  ret = 0;
73  tx_send(ctx, nbh, 0, len);
74  } else if (ktx->type == FLEXTCP_PL_KTX_CONNRETRAN) {
75  flow_id = ktx->msg.connretran.flow_id;
76  if (flow_id >= FLEXNIC_PL_FLOWST_NUM) {
77  fprintf(stderr, "fast_kernel_qman: invalid flow id=%u\n", flow_id);
78  abort();
79  }
80 
81  fast_flows_retransmit(ctx, flow_id);
82  ret = 1;
83  } else {
84  fprintf(stderr, "fast_appctx_poll: unknown type: %u\n", ktx->type);
85  abort();
86  }
87 
88  MEM_BARRIER();
89  ktx->type = 0;
90 
91  kctx->tx_head += sizeof(*ktx);
92  if (kctx->tx_head >= kctx->tx_len)
93  kctx->tx_head -= kctx->tx_len;
94 
95  return ret;
96 }
97 
98 void fast_kernel_packet(struct dataplane_context *ctx,
99  struct network_buf_handle *nbh)
100 {
101  struct flextcp_pl_appctx *kctx = &fp_state->kctx[ctx->id];
102  struct flextcp_pl_krx *krx;
103  uint16_t len;
104 
105  /* queue not initialized yet */
106  if (kctx->rx_len == 0) {
107  return;
108  }
109 
110  krx = dma_pointer(kctx->rx_base + kctx->rx_head, sizeof(*krx));
111 
112  /* queue full */
113  if (krx->type != 0) {
114  ctx->kernel_drop++;
115  return;
116  }
117 
118  kctx->rx_head += sizeof(*krx);
119  if (kctx->rx_head >= kctx->rx_len)
120  kctx->rx_head -= kctx->rx_len;
121 
122 
123  len = network_buf_len(nbh);
124  dma_write(krx->addr, len, network_buf_bufoff(nbh));
125 
126  if (network_buf_flowgroup(nbh, &krx->msg.packet.flow_group)) {
127  fprintf(stderr, "fast_kernel_packet: network_buf_flowgroup failed\n");
128  abort();
129  }
130 
131  krx->msg.packet.len = len;
132  krx->msg.packet.fn_core = ctx->id;
133  MEM_BARRIER();
134 
135  /* krx queue header */
136  krx->type = FLEXTCP_PL_KRX_PACKET;
137  notify_slowpath_core();
138 }
139 
140 static inline void inject_tcp_ts(void *buf, uint16_t len, uint32_t ts,
141  struct network_buf_handle *nbh)
142 {
143  struct pkt_tcp *p = buf;
144  struct tcp_opts opts;
145 
146  if (len < sizeof(*p) || f_beui16(p->eth.type) != ETH_TYPE_IP ||
147  p->ip.proto != IP_PROTO_TCP)
148  {
149  return;
150  }
151 
152  if (tcp_parse_options(buf, len, &opts) != 0) {
153  fprintf(stderr, "inject_tcp_ts: parsing options failed\n");
154  return;
155  }
156 
157  if (opts.ts == NULL) {
158  return;
159  }
160 
161  opts.ts->ts_val = t_beui32(ts);
162 
163  fast_flows_kernelxsums(nbh, p);
164 }