TAS
TCP Acceleration as an OS Service
kni.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 <inttypes.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 
31 #include <rte_version.h>
32 #include <rte_kni.h>
33 #include <rte_mbuf.h>
34 #include <rte_mempool.h>
35 
36 #include <tas.h>
37 #include "internal.h"
38 
39 #define MBUF_SIZE (1500 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
40 #define POOL_SIZE (4 * 4096)
41 #define KNI_MTU 1500
42 
43 enum change_linkstate {
44  LST_NOOP = 0,
45  LST_UP,
46  LST_DOWN,
47 };
48 
49 static int interface_set_carrier(const char *name, int status);
50 static int op_config_network_if(uint16_t port_id, uint8_t if_up);
51 #if RTE_VER_YEAR >= 18
52 static int op_config_mac_address(uint16_t port_id, uint8_t mac_addr[]);
53 #endif
54 
55 static struct rte_mempool *kni_pool;
56 static struct rte_kni *kni_if;
57 static struct rte_kni_conf conf;
58 static struct rte_kni_ops ops = {
59  .port_id = 0,
60  .config_network_if = op_config_network_if,
61 #if RTE_VER_YEAR >= 18
62  .config_mac_address = op_config_mac_address,
63 #endif
64  };
65 static int change_linkstate = LST_NOOP;
66 
67 int kni_init(void)
68 {
69  if (config.kni_name == NULL)
70  return 0;
71 
72 #if RTE_VER_YEAR < 19
73  rte_kni_init(1);
74 #else
75  if (rte_kni_init(1) != 0) {
76  fprintf(stderr, "kni_init: rte_kni_init failed\n");
77  return -1;
78  }
79 #endif
80 
81  /* alloc mempool for kni */
82  kni_pool = rte_mempool_create("tas_kni", POOL_SIZE, MBUF_SIZE, 32,
83  sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL,
84  rte_pktmbuf_init, NULL, rte_socket_id(), 0);
85  if (kni_pool == NULL) {
86  fprintf(stderr, "kni_init: rte_mempool_create failed\n");
87  return -1;
88  }
89 
90  /* initialize config */
91  memset(&conf, 0, sizeof(conf));
92  strncpy(conf.name, config.kni_name, RTE_KNI_NAMESIZE - 1);
93  conf.name[RTE_KNI_NAMESIZE - 1] = 0;
94  conf.mbuf_size = MBUF_SIZE;
95 #if RTE_VER_YEAR >= 18
96  memcpy(conf.mac_addr, &eth_addr, sizeof(eth_addr));
97  conf.mtu = KNI_MTU;
98 #endif
99 
100  /* allocate kni */
101  if ((kni_if = rte_kni_alloc(kni_pool, &conf, &ops)) == NULL) {
102  fprintf(stderr, "kni_init: rte_kni_alloc failed\n");
103  return -1;
104  }
105 
106  return 0;
107 }
108 
109 void kni_packet(const void *pkt, uint16_t len)
110 {
111  struct rte_mbuf *mb;
112  void *dst;
113 
114  if (config.kni_name == NULL)
115  return;
116 
117  if ((mb = rte_pktmbuf_alloc(kni_pool)) == NULL) {
118  fprintf(stderr, "kni_packet: mbuf alloc failed\n");
119  return;
120  }
121 
122  if ((dst = rte_pktmbuf_append(mb, len)) == NULL) {
123  fprintf(stderr, "kni_packet: mbuf append failed\n");
124  return;
125  }
126 
127  memcpy(dst, pkt, len);
128  if (rte_kni_tx_burst(kni_if, &mb, 1) != 1) {
129  fprintf(stderr, "kni_packet: send failed\n");
130  rte_pktmbuf_free(mb);
131  }
132 
133 }
134 
135 unsigned kni_poll(void)
136 {
137  unsigned n;
138  struct rte_mbuf *mb;
139  uint32_t op;
140  void *buf;
141 
142  if (config.kni_name == NULL)
143  return 0;
144 
145  if (change_linkstate != LST_NOOP) {
146  if (interface_set_carrier(config.kni_name, change_linkstate == LST_UP)) {
147  fprintf(stderr, "kni_poll: linkstate update failed\n");
148  }
149  change_linkstate = LST_NOOP;
150  }
151 
152  rte_kni_handle_request(kni_if);
153 
154  n = rte_kni_rx_burst(kni_if, &mb, 1);
155  if (n == 1) {
156  if (nicif_tx_alloc(rte_pktmbuf_pkt_len(mb), &buf, &op) == 0) {
157  memcpy(buf, rte_pktmbuf_mtod(mb, void *), rte_pktmbuf_pkt_len(mb));
158  nicif_tx_send(op, 1);
159  } else {
160  fprintf(stderr, "kni_poll: send failed\n");
161  }
162 
163  rte_pktmbuf_free(mb);
164  }
165  return 1;
166 }
167 
168 static int interface_set_carrier(const char *name, int status)
169 {
170  char path[64];
171  int fd, ret;
172  const char *st = status ? "1" : "0";
173 
174  sprintf(path, "/sys/class/net/%s/carrier", name);
175 
176  if ((fd = open(path, O_WRONLY)) < 0) {
177  perror("interface_set_carrier: open failed");
178  return -1;
179  }
180 
181  if ((ret = write(fd, st, 2)) != 2) {
182  perror("interface_set_carrier: write failed");
183  close(fd);
184  return -1;
185  }
186 
187  close(fd);
188  return 0;
189 }
190 
191 static int op_config_network_if(uint16_t port_id, uint8_t if_up)
192 {
193  change_linkstate = (if_up ? LST_UP : LST_DOWN);
194  return 0;
195 }
196 
197 #if RTE_VER_YEAR >= 18
198 static int op_config_mac_address(uint16_t port_id, uint8_t mac_addr[])
199 {
200  return 0;
201 }
202 #endif
unsigned kni_poll(void)
Definition: kni.c:135
void kni_packet(const void *pkt, uint16_t len)
Definition: kni.c:109
Definition: conf.py:1
char * kni_name
Definition: config.h:131
int kni_init(void)
Definition: kni.c:67
int nicif_tx_alloc(uint16_t len, void **buf, uint32_t *opaque)
Definition: nicif.c:352
void nicif_tx_send(uint32_t opaque, int no_ts)
Definition: nicif.c:368