TAS
TCP Acceleration as an OS Service
shm.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 <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 #include <sys/stat.h>
31 #include <sys/mman.h>
32 #include <fcntl.h>
33 #include <errno.h>
34 #include <assert.h>
35 #include <inttypes.h>
36 
37 #include <utils.h>
38 #include <rte_config.h>
39 #include <rte_malloc.h>
40 #include <rte_cycles.h>
41 
42 #include <tas.h>
43 #include <tas_memif.h>
44 
45 void *tas_shm = NULL;
46 struct flextcp_pl_mem *fp_state = NULL;
47 struct flexnic_info *tas_info = NULL;
48 
49 /* destroy shared memory region */
50 static void destroy_shm(const char *name, size_t size, void *addr);
51 /* create shared memory region using huge pages */
52 static void *util_create_shmsiszed_huge(const char *name, size_t size,
53  void *addr) __attribute__((used));
54 /* destroy shared huge page memory region */
55 static void destroy_shm_huge(const char *name, size_t size, void *addr)
56  __attribute__((used));
57 /* convert microseconds to cycles */
58 static uint64_t us_to_cycles(uint32_t us);
59 
60 /* Allocate DMA memory before DPDK grabs all huge pages */
61 int shm_preinit(void)
62 {
63  /* create shm for dma memory */
64  if (config.fp_hugepages) {
65  tas_shm = util_create_shmsiszed_huge(FLEXNIC_NAME_DMA_MEM,
66  config.shm_len, NULL);
67  } else {
68  tas_shm = util_create_shmsiszed(FLEXNIC_NAME_DMA_MEM, config.shm_len,
69  NULL);
70  }
71  if (tas_shm == NULL) {
72  fprintf(stderr, "mapping flexnic dma memory failed\n");
73  return -1;
74  }
75 
76  /* create shm for internal memory */
77  if (config.fp_hugepages) {
78  fp_state = util_create_shmsiszed_huge(FLEXNIC_NAME_INTERNAL_MEM,
79  FLEXNIC_INTERNAL_MEM_SIZE, NULL);
80  } else {
81  fp_state = util_create_shmsiszed(FLEXNIC_NAME_INTERNAL_MEM,
82  FLEXNIC_INTERNAL_MEM_SIZE, NULL);
83  }
84  if (fp_state == NULL) {
85  fprintf(stderr, "mapping flexnic internal memory failed\n");
86  shm_cleanup();
87  return -1;
88  }
89 
90  return 0;
91 }
92 
93 int shm_init(unsigned num)
94 {
95  umask(0);
96 
97  /* create shm for tas_info */
98  tas_info = util_create_shmsiszed(FLEXNIC_NAME_INFO, FLEXNIC_INFO_BYTES, NULL);
99  if (tas_info == NULL) {
100  fprintf(stderr, "mapping flexnic tas_info failed\n");
101  shm_cleanup();
102  return -1;
103  }
104 
105  tas_info->dma_mem_size = config.shm_len;
106  tas_info->internal_mem_size = FLEXNIC_INTERNAL_MEM_SIZE;
107  tas_info->qmq_num = FLEXNIC_NUM_QMQUEUES;
108  tas_info->cores_num = num;
109  tas_info->mac_address = 0;
110  tas_info->poll_cycle_app = us_to_cycles(config.fp_poll_interval_app);
111  tas_info->poll_cycle_tas = us_to_cycles(config.fp_poll_interval_tas);
112 
113  if (config.fp_hugepages)
114  tas_info->flags |= FLEXNIC_FLAG_HUGEPAGES;
115 
116  return 0;
117 }
118 
119 void shm_cleanup(void)
120 {
121  /* cleanup internal memory region */
122  if (fp_state != NULL) {
123  if (config.fp_hugepages) {
124  destroy_shm_huge(FLEXNIC_NAME_INTERNAL_MEM, FLEXNIC_INTERNAL_MEM_SIZE,
125  fp_state);
126  } else {
127  destroy_shm(FLEXNIC_NAME_INTERNAL_MEM, FLEXNIC_INTERNAL_MEM_SIZE,
128  fp_state);
129  }
130  }
131 
132  /* cleanup dma memory region */
133  if (tas_shm != NULL) {
134  if (config.fp_hugepages) {
135  destroy_shm_huge(FLEXNIC_NAME_DMA_MEM, config.shm_len, tas_shm);
136  } else {
137  destroy_shm(FLEXNIC_NAME_DMA_MEM, config.shm_len, tas_shm);
138  }
139  }
140 
141  /* cleanup tas_info memory region */
142  if (tas_info != NULL) {
143  destroy_shm(FLEXNIC_NAME_INFO, FLEXNIC_INFO_BYTES, tas_info);
144  }
145 }
146 
147 void shm_set_ready(void)
148 {
149  tas_info->flags |= FLEXNIC_FLAG_READY;
150 }
151 
152 void *util_create_shmsiszed(const char *name, size_t size, void *addr)
153 {
154  int fd;
155  void *p;
156 
157  if ((fd = shm_open(name, O_CREAT | O_RDWR, 0666)) == -1) {
158  perror("shm_open failed");
159  goto error_out;
160  }
161  if (ftruncate(fd, size) != 0) {
162  perror("ftruncate failed");
163  goto error_remove;
164  }
165 
166  if ((p = mmap(addr, size, PROT_READ | PROT_WRITE,
167  MAP_SHARED | (addr == NULL ? 0 : MAP_FIXED) | MAP_POPULATE, fd, 0)) ==
168  (void *) -1)
169  {
170  perror("mmap failed");
171  goto error_remove;
172  }
173 
174  memset(p, 0, size);
175 
176  close(fd);
177  return p;
178 
179 error_remove:
180  close(fd);
181  shm_unlink(name);
182 error_out:
183  return NULL;
184 }
185 
186 static void destroy_shm(const char *name, size_t size, void *addr)
187 {
188  if (munmap(addr, size) != 0) {
189  fprintf(stderr, "Warning: munmap failed (%s)\n", strerror(errno));
190  }
191  shm_unlink(name);
192 }
193 
194 static void *util_create_shmsiszed_huge(const char *name, size_t size,
195  void *addr)
196 {
197  int fd;
198  void *p;
199  char path[128];
200 
201  snprintf(path, sizeof(path), "%s/%s", FLEXNIC_HUGE_PREFIX, name);
202 
203  if ((fd = open(path, O_CREAT | O_RDWR, 0666)) == -1) {
204  perror("util_create_shmsiszed: open failed");
205  goto error_out;
206  }
207  if (ftruncate(fd, size) != 0) {
208  perror("util_create_shmsiszed: ftruncate failed");
209  goto error_remove;
210  }
211 
212  if ((p = mmap(addr, size, PROT_READ | PROT_WRITE,
213  MAP_SHARED | (addr == NULL ? 0 : MAP_FIXED) | MAP_POPULATE, fd, 0)) ==
214  (void *) -1)
215  {
216  perror("util_create_shmsiszed: mmap failed");
217  goto error_remove;
218  }
219 
220  memset(p, 0, size);
221 
222  close(fd);
223  return p;
224 
225 error_remove:
226  close(fd);
227  shm_unlink(name);
228 error_out:
229  return NULL;
230 }
231 
232 static void destroy_shm_huge(const char *name, size_t size, void *addr)
233 {
234  char path[128];
235 
236  snprintf(path, sizeof(path), "%s/%s", FLEXNIC_HUGE_PREFIX, name);
237 
238  if (munmap(addr, size) != 0) {
239  fprintf(stderr, "Warning: munmap failed (%s)\n", strerror(errno));
240  }
241  unlink(path);
242 }
243 
244 static uint64_t us_to_cycles(uint32_t us)
245 {
246  if (us == UINT32_MAX) {
247  return UINT64_MAX;
248  }
249 
250  return (rte_get_tsc_hz() * us) / 1000000;
251 }
252 
#define FLEXNIC_NAME_INFO
Definition: tas_memif.h:41
uint32_t fp_hugepages
Definition: config.h:123
uint64_t poll_cycle_app
Definition: tas_memif.h:66
#define FLEXNIC_FLAG_READY
Definition: tas_memif.h:51
uint32_t cores_num
Definition: tas_memif.h:72
uint64_t flags
Definition: tas_memif.h:58
#define FLEXNIC_NAME_INTERNAL_MEM
Definition: tas_memif.h:45
uint64_t internal_mem_size
Definition: tas_memif.h:62
uint64_t poll_cycle_tas
Definition: tas_memif.h:68
uint32_t qmq_num
Definition: tas_memif.h:70
#define FLEXNIC_NAME_DMA_MEM
Definition: tas_memif.h:43
uint32_t fp_poll_interval_app
Definition: config.h:129
#define FLEXNIC_INFO_BYTES
Definition: tas_memif.h:48
#define FLEXNIC_FLAG_HUGEPAGES
Definition: tas_memif.h:53
uint64_t dma_mem_size
Definition: tas_memif.h:60
uint64_t mac_address
Definition: tas_memif.h:64
uint32_t fp_poll_interval_tas
Definition: config.h:127