aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers
diff options
context:
space:
mode:
authorAnton Ivanov <anton.ivanov@cambridgegreys.com>2019-08-09 03:40:17 -0400
committerRichard Weinberger <richard@nod.at>2019-09-15 15:37:08 -0400
commitb3b8ca2a1b63713f59e8d7ad772b09bcd8dc9048 (patch)
tree0011db879e9f96c8a9e1404cf9227dca9aa2445b /arch/um/drivers
parent03e46a4d5b439079286e5e0c5211cee33e480c3a (diff)
um: Add legacy tap support and rename existing vector to hybrid
1. Adds legacy tap support 2. Renames tap+raw as hybrid Signed-off-by: Anton Ivanov <anton.ivanov@cambridgegreys.com> Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch/um/drivers')
-rw-r--r--arch/um/drivers/vector_kern.c2
-rw-r--r--arch/um/drivers/vector_transports.c29
-rw-r--r--arch/um/drivers/vector_user.c203
-rw-r--r--arch/um/drivers/vector_user.h4
4 files changed, 151 insertions, 87 deletions
diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index e190e4ca52e1..8fa094770965 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -186,6 +186,8 @@ static int get_transport_options(struct arglist *def)
186 186
187 187
188 if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0) 188 if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0)
189 return 0;
190 if (strncmp(transport, TRANS_HYBRID, TRANS_HYBRID_LEN) == 0)
189 return (vec_rx | VECTOR_BPF); 191 return (vec_rx | VECTOR_BPF);
190 if (strncmp(transport, TRANS_RAW, TRANS_RAW_LEN) == 0) 192 if (strncmp(transport, TRANS_RAW, TRANS_RAW_LEN) == 0)
191 return (vec_rx | vec_tx | VECTOR_QDISC_BYPASS); 193 return (vec_rx | vec_tx | VECTOR_QDISC_BYPASS);
diff --git a/arch/um/drivers/vector_transports.c b/arch/um/drivers/vector_transports.c
index 77e4ebc206ae..2999f3bd1781 100644
--- a/arch/um/drivers/vector_transports.c
+++ b/arch/um/drivers/vector_transports.c
@@ -418,7 +418,7 @@ static int build_raw_transport_data(struct vector_private *vp)
418 return 0; 418 return 0;
419} 419}
420 420
421static int build_tap_transport_data(struct vector_private *vp) 421static int build_hybrid_transport_data(struct vector_private *vp)
422{ 422{
423 if (uml_raw_enable_vnet_headers(vp->fds->rx_fd)) { 423 if (uml_raw_enable_vnet_headers(vp->fds->rx_fd)) {
424 vp->form_header = &raw_form_header; 424 vp->form_header = &raw_form_header;
@@ -432,7 +432,7 @@ static int build_tap_transport_data(struct vector_private *vp)
432 NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GRO); 432 NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GRO);
433 netdev_info( 433 netdev_info(
434 vp->dev, 434 vp->dev,
435 "tap/raw: using vnet headers for tso and tx/rx checksum" 435 "tap/raw hybrid: using vnet headers for tso and tx/rx checksum"
436 ); 436 );
437 } else { 437 } else {
438 return 0; /* do not try to enable tap too if raw failed */ 438 return 0; /* do not try to enable tap too if raw failed */
@@ -442,6 +442,29 @@ static int build_tap_transport_data(struct vector_private *vp)
442 return -1; 442 return -1;
443} 443}
444 444
445static int build_tap_transport_data(struct vector_private *vp)
446{
447 /* "Pure" tap uses the same fd for rx and tx */
448 if (uml_tap_enable_vnet_headers(vp->fds->tx_fd)) {
449 vp->form_header = &raw_form_header;
450 vp->verify_header = &raw_verify_header;
451 vp->header_size = sizeof(struct virtio_net_hdr);
452 vp->rx_header_size = sizeof(struct virtio_net_hdr);
453 vp->dev->hw_features |=
454 (NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GRO);
455 vp->dev->features |=
456 (NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
457 NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GRO);
458 netdev_info(
459 vp->dev,
460 "tap: using vnet headers for tso and tx/rx checksum"
461 );
462 return 0;
463 }
464 return -1;
465}
466
467
445int build_transport_data(struct vector_private *vp) 468int build_transport_data(struct vector_private *vp)
446{ 469{
447 char *transport = uml_vector_fetch_arg(vp->parsed, "transport"); 470 char *transport = uml_vector_fetch_arg(vp->parsed, "transport");
@@ -454,6 +477,8 @@ int build_transport_data(struct vector_private *vp)
454 return build_raw_transport_data(vp); 477 return build_raw_transport_data(vp);
455 if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0) 478 if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0)
456 return build_tap_transport_data(vp); 479 return build_tap_transport_data(vp);
480 if (strncmp(transport, TRANS_HYBRID, TRANS_HYBRID_LEN) == 0)
481 return build_hybrid_transport_data(vp);
457 return 0; 482 return 0;
458} 483}
459 484
diff --git a/arch/um/drivers/vector_user.c b/arch/um/drivers/vector_user.c
index b3f7b3ca896d..0ada22f82965 100644
--- a/arch/um/drivers/vector_user.c
+++ b/arch/um/drivers/vector_user.c
@@ -114,12 +114,76 @@ cleanup:
114 114
115#define PATH_NET_TUN "/dev/net/tun" 115#define PATH_NET_TUN "/dev/net/tun"
116 116
117static struct vector_fds *user_init_tap_fds(struct arglist *ifspec) 117
118static int create_tap_fd(char *iface)
118{ 119{
119 struct ifreq ifr; 120 struct ifreq ifr;
120 int fd = -1; 121 int fd = -1;
121 struct sockaddr_ll sock;
122 int err = -ENOMEM, offload; 122 int err = -ENOMEM, offload;
123
124 fd = open(PATH_NET_TUN, O_RDWR);
125 if (fd < 0) {
126 printk(UM_KERN_ERR "uml_tap: failed to open tun device\n");
127 goto tap_fd_cleanup;
128 }
129 memset(&ifr, 0, sizeof(ifr));
130 ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
131 strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
132
133 err = ioctl(fd, TUNSETIFF, (void *) &ifr);
134 if (err != 0) {
135 printk(UM_KERN_ERR "uml_tap: failed to select tap interface\n");
136 goto tap_fd_cleanup;
137 }
138
139 offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6;
140 ioctl(fd, TUNSETOFFLOAD, offload);
141 return fd;
142tap_fd_cleanup:
143 if (fd >= 0)
144 os_close_file(fd);
145 return err;
146}
147
148static int create_raw_fd(char *iface, int flags, int proto)
149{
150 struct ifreq ifr;
151 int fd = -1;
152 struct sockaddr_ll sock;
153 int err = -ENOMEM;
154
155 fd = socket(AF_PACKET, SOCK_RAW, flags);
156 if (fd == -1) {
157 err = -errno;
158 goto raw_fd_cleanup;
159 }
160 memset(&ifr, 0, sizeof(ifr));
161 strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
162 if (ioctl(fd, SIOCGIFINDEX, (void *) &ifr) < 0) {
163 err = -errno;
164 goto raw_fd_cleanup;
165 }
166
167 sock.sll_family = AF_PACKET;
168 sock.sll_protocol = htons(proto);
169 sock.sll_ifindex = ifr.ifr_ifindex;
170
171 if (bind(fd,
172 (struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) {
173 err = -errno;
174 goto raw_fd_cleanup;
175 }
176 return fd;
177raw_fd_cleanup:
178 printk(UM_KERN_ERR "user_init_raw: init failed, error %d", err);
179 if (fd >= 0)
180 os_close_file(fd);
181 return err;
182}
183
184static struct vector_fds *user_init_tap_fds(struct arglist *ifspec)
185{
186 int fd = -1;
123 char *iface; 187 char *iface;
124 struct vector_fds *result = NULL; 188 struct vector_fds *result = NULL;
125 189
@@ -141,117 +205,88 @@ static struct vector_fds *user_init_tap_fds(struct arglist *ifspec)
141 205
142 /* TAP */ 206 /* TAP */
143 207
144 fd = open(PATH_NET_TUN, O_RDWR); 208 fd = create_tap_fd(iface);
145 if (fd < 0) { 209 if (fd < 0) {
146 printk(UM_KERN_ERR "uml_tap: failed to open tun device\n"); 210 printk(UM_KERN_ERR "uml_tap: failed to create tun interface\n");
147 goto tap_cleanup; 211 goto tap_cleanup;
148 } 212 }
149 result->tx_fd = fd; 213 result->tx_fd = fd;
150 memset(&ifr, 0, sizeof(ifr)); 214 result->rx_fd = fd;
151 ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR; 215 return result;
152 strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1); 216tap_cleanup:
217 printk(UM_KERN_ERR "user_init_tap: init failed, error %d", fd);
218 if (result != NULL)
219 kfree(result);
220 return NULL;
221}
153 222
154 err = ioctl(fd, TUNSETIFF, (void *) &ifr); 223static struct vector_fds *user_init_hybrid_fds(struct arglist *ifspec)
155 if (err != 0) { 224{
156 printk(UM_KERN_ERR "uml_tap: failed to select tap interface\n"); 225 char *iface;
157 goto tap_cleanup; 226 struct vector_fds *result = NULL;
227
228 iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME);
229 if (iface == NULL) {
230 printk(UM_KERN_ERR "uml_tap: failed to parse interface spec\n");
231 goto hybrid_cleanup;
158 } 232 }
159 233
160 offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6; 234 result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
161 ioctl(fd, TUNSETOFFLOAD, offload); 235 if (result == NULL) {
236 printk(UM_KERN_ERR "uml_tap: failed to allocate file descriptors\n");
237 goto hybrid_cleanup;
238 }
239 result->rx_fd = -1;
240 result->tx_fd = -1;
241 result->remote_addr = NULL;
242 result->remote_addr_size = 0;
162 243
163 /* RAW */ 244 /* TAP */
164 245
165 fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 246 result->tx_fd = create_tap_fd(iface);
166 if (fd == -1) { 247 if (result->tx_fd < 0) {
167 printk(UM_KERN_ERR 248 printk(UM_KERN_ERR "uml_tap: failed to create tun interface: %i\n", result->tx_fd);
168 "uml_tap: failed to create socket: %i\n", -errno); 249 goto hybrid_cleanup;
169 goto tap_cleanup;
170 }
171 result->rx_fd = fd;
172 memset(&ifr, 0, sizeof(ifr));
173 strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
174 if (ioctl(fd, SIOCGIFINDEX, (void *) &ifr) < 0) {
175 printk(UM_KERN_ERR
176 "uml_tap: failed to set interface: %i\n", -errno);
177 goto tap_cleanup;
178 } 250 }
179 251
180 sock.sll_family = AF_PACKET; 252 /* RAW */
181 sock.sll_protocol = htons(ETH_P_ALL);
182 sock.sll_ifindex = ifr.ifr_ifindex;
183 253
184 if (bind(fd, 254 result->rx_fd = create_raw_fd(iface, ETH_P_ALL, ETH_P_ALL);
185 (struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) { 255 if (result->rx_fd == -1) {
186 printk(UM_KERN_ERR 256 printk(UM_KERN_ERR
187 "user_init_tap: failed to bind raw pair, err %d\n", 257 "uml_tap: failed to create paired raw socket: %i\n", result->rx_fd);
188 -errno); 258 goto hybrid_cleanup;
189 goto tap_cleanup;
190 } 259 }
191 return result; 260 return result;
192tap_cleanup: 261hybrid_cleanup:
193 printk(UM_KERN_ERR "user_init_tap: init failed, error %d", err); 262 printk(UM_KERN_ERR "user_init_hybrid: init failed");
194 if (result != NULL) { 263 if (result != NULL)
195 if (result->rx_fd >= 0)
196 os_close_file(result->rx_fd);
197 if (result->tx_fd >= 0)
198 os_close_file(result->tx_fd);
199 kfree(result); 264 kfree(result);
200 }
201 return NULL; 265 return NULL;
202} 266}
203 267
204 268
205static struct vector_fds *user_init_raw_fds(struct arglist *ifspec) 269static struct vector_fds *user_init_raw_fds(struct arglist *ifspec)
206{ 270{
207 struct ifreq ifr;
208 int rxfd = -1, txfd = -1; 271 int rxfd = -1, txfd = -1;
209 struct sockaddr_ll sock;
210 int err = -ENOMEM; 272 int err = -ENOMEM;
211 char *iface; 273 char *iface;
212 struct vector_fds *result = NULL; 274 struct vector_fds *result = NULL;
213 275
214 iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME); 276 iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME);
215 if (iface == NULL) 277 if (iface == NULL)
216 goto cleanup; 278 goto raw_cleanup;
217 279
218 rxfd = socket(AF_PACKET, SOCK_RAW, ETH_P_ALL); 280 rxfd = create_raw_fd(iface, ETH_P_ALL, ETH_P_ALL);
219 if (rxfd == -1) { 281 if (rxfd == -1) {
220 err = -errno; 282 err = -errno;
221 goto cleanup; 283 goto raw_cleanup;
222 } 284 }
223 txfd = socket(AF_PACKET, SOCK_RAW, 0); /* Turn off RX on this fd */ 285 txfd = create_raw_fd(iface, 0, ETH_P_IP); /* Turn off RX on this fd */
224 if (txfd == -1) { 286 if (txfd == -1) {
225 err = -errno; 287 err = -errno;
226 goto cleanup; 288 goto raw_cleanup;
227 }
228 memset(&ifr, 0, sizeof(ifr));
229 strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
230 if (ioctl(rxfd, SIOCGIFINDEX, (void *) &ifr) < 0) {
231 err = -errno;
232 goto cleanup;
233 }
234
235 sock.sll_family = AF_PACKET;
236 sock.sll_protocol = htons(ETH_P_ALL);
237 sock.sll_ifindex = ifr.ifr_ifindex;
238
239 if (bind(rxfd,
240 (struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) {
241 err = -errno;
242 goto cleanup;
243 } 289 }
244
245 sock.sll_family = AF_PACKET;
246 sock.sll_protocol = htons(ETH_P_IP);
247 sock.sll_ifindex = ifr.ifr_ifindex;
248
249 if (bind(txfd,
250 (struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) {
251 err = -errno;
252 goto cleanup;
253 }
254
255 result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL); 290 result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
256 if (result != NULL) { 291 if (result != NULL) {
257 result->rx_fd = rxfd; 292 result->rx_fd = rxfd;
@@ -260,13 +295,10 @@ static struct vector_fds *user_init_raw_fds(struct arglist *ifspec)
260 result->remote_addr_size = 0; 295 result->remote_addr_size = 0;
261 } 296 }
262 return result; 297 return result;
263cleanup: 298raw_cleanup:
264 printk(UM_KERN_ERR "user_init_raw: init failed, error %d", err); 299 printk(UM_KERN_ERR "user_init_raw: init failed, error %d", err);
265 if (rxfd >= 0) 300 if (result != NULL)
266 os_close_file(rxfd); 301 kfree(result);
267 if (txfd >= 0)
268 os_close_file(txfd);
269 kfree(result);
270 return NULL; 302 return NULL;
271} 303}
272 304
@@ -456,6 +488,8 @@ struct vector_fds *uml_vector_user_open(
456 } 488 }
457 if (strncmp(transport, TRANS_RAW, TRANS_RAW_LEN) == 0) 489 if (strncmp(transport, TRANS_RAW, TRANS_RAW_LEN) == 0)
458 return user_init_raw_fds(parsed); 490 return user_init_raw_fds(parsed);
491 if (strncmp(transport, TRANS_HYBRID, TRANS_HYBRID_LEN) == 0)
492 return user_init_hybrid_fds(parsed);
459 if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0) 493 if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0)
460 return user_init_tap_fds(parsed); 494 return user_init_tap_fds(parsed);
461 if (strncmp(transport, TRANS_GRE, TRANS_GRE_LEN) == 0) 495 if (strncmp(transport, TRANS_GRE, TRANS_GRE_LEN) == 0)
@@ -482,8 +516,9 @@ int uml_vector_sendmsg(int fd, void *hdr, int flags)
482int uml_vector_recvmsg(int fd, void *hdr, int flags) 516int uml_vector_recvmsg(int fd, void *hdr, int flags)
483{ 517{
484 int n; 518 int n;
519 struct msghdr *msg = (struct msghdr *) hdr;
485 520
486 CATCH_EINTR(n = recvmsg(fd, (struct msghdr *) hdr, flags)); 521 CATCH_EINTR(n = readv(fd, msg->msg_iov, msg->msg_iovlen));
487 if ((n < 0) && (errno == EAGAIN)) 522 if ((n < 0) && (errno == EAGAIN))
488 return 0; 523 return 0;
489 if (n >= 0) 524 if (n >= 0)
diff --git a/arch/um/drivers/vector_user.h b/arch/um/drivers/vector_user.h
index d7cbff73b7ff..6bf50cf78ad0 100644
--- a/arch/um/drivers/vector_user.h
+++ b/arch/um/drivers/vector_user.h
@@ -16,13 +16,15 @@
16#define TRANS_TAP "tap" 16#define TRANS_TAP "tap"
17#define TRANS_TAP_LEN strlen(TRANS_TAP) 17#define TRANS_TAP_LEN strlen(TRANS_TAP)
18 18
19
20#define TRANS_GRE "gre" 19#define TRANS_GRE "gre"
21#define TRANS_GRE_LEN strlen(TRANS_RAW) 20#define TRANS_GRE_LEN strlen(TRANS_RAW)
22 21
23#define TRANS_L2TPV3 "l2tpv3" 22#define TRANS_L2TPV3 "l2tpv3"
24#define TRANS_L2TPV3_LEN strlen(TRANS_L2TPV3) 23#define TRANS_L2TPV3_LEN strlen(TRANS_L2TPV3)
25 24
25#define TRANS_HYBRID "hybrid"
26#define TRANS_HYBRID_LEN strlen(TRANS_HYBRID)
27
26#ifndef IPPROTO_GRE 28#ifndef IPPROTO_GRE
27#define IPPROTO_GRE 0x2F 29#define IPPROTO_GRE 0x2F
28#endif 30#endif