18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org). 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Transport usage: 68c2ecf20Sopenharmony_ci * ethN=vde,<vde_switch>,<mac addr>,<port>,<group>,<mode>,<description> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/init.h> 118c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 128c2ecf20Sopenharmony_ci#include <net_kern.h> 138c2ecf20Sopenharmony_ci#include <net_user.h> 148c2ecf20Sopenharmony_ci#include "vde.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistatic void vde_init(struct net_device *dev, void *data) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci struct vde_init *init = data; 198c2ecf20Sopenharmony_ci struct uml_net_private *pri; 208c2ecf20Sopenharmony_ci struct vde_data *vpri; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci pri = netdev_priv(dev); 238c2ecf20Sopenharmony_ci vpri = (struct vde_data *) pri->user; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci vpri->vde_switch = init->vde_switch; 268c2ecf20Sopenharmony_ci vpri->descr = init->descr ? init->descr : "UML vde_transport"; 278c2ecf20Sopenharmony_ci vpri->args = NULL; 288c2ecf20Sopenharmony_ci vpri->conn = NULL; 298c2ecf20Sopenharmony_ci vpri->dev = dev; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci printk("vde backend - %s, ", vpri->vde_switch ? 328c2ecf20Sopenharmony_ci vpri->vde_switch : "(default socket)"); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci vde_init_libstuff(vpri, init); 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci printk("\n"); 378c2ecf20Sopenharmony_ci} 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic int vde_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci struct vde_data *pri = (struct vde_data *) &lp->user; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci if (pri->conn != NULL) 448c2ecf20Sopenharmony_ci return vde_user_read(pri->conn, skb_mac_header(skb), 458c2ecf20Sopenharmony_ci skb->dev->mtu + ETH_HEADER_OTHER); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci printk(KERN_ERR "vde_read - we have no VDECONN to read from"); 488c2ecf20Sopenharmony_ci return -EBADF; 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistatic int vde_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci struct vde_data *pri = (struct vde_data *) &lp->user; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (pri->conn != NULL) 568c2ecf20Sopenharmony_ci return vde_user_write((void *)pri->conn, skb->data, 578c2ecf20Sopenharmony_ci skb->len); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci printk(KERN_ERR "vde_write - we have no VDECONN to write to"); 608c2ecf20Sopenharmony_ci return -EBADF; 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic const struct net_kern_info vde_kern_info = { 648c2ecf20Sopenharmony_ci .init = vde_init, 658c2ecf20Sopenharmony_ci .protocol = eth_protocol, 668c2ecf20Sopenharmony_ci .read = vde_read, 678c2ecf20Sopenharmony_ci .write = vde_write, 688c2ecf20Sopenharmony_ci}; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic int vde_setup(char *str, char **mac_out, void *data) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci struct vde_init *init = data; 738c2ecf20Sopenharmony_ci char *remain, *port_str = NULL, *mode_str = NULL, *last; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci *init = ((struct vde_init) 768c2ecf20Sopenharmony_ci { .vde_switch = NULL, 778c2ecf20Sopenharmony_ci .descr = NULL, 788c2ecf20Sopenharmony_ci .port = 0, 798c2ecf20Sopenharmony_ci .group = NULL, 808c2ecf20Sopenharmony_ci .mode = 0 }); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci remain = split_if_spec(str, &init->vde_switch, mac_out, &port_str, 838c2ecf20Sopenharmony_ci &init->group, &mode_str, &init->descr, NULL); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci if (remain != NULL) 868c2ecf20Sopenharmony_ci printk(KERN_WARNING "vde_setup - Ignoring extra data :" 878c2ecf20Sopenharmony_ci "'%s'\n", remain); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci if (port_str != NULL) { 908c2ecf20Sopenharmony_ci init->port = simple_strtoul(port_str, &last, 10); 918c2ecf20Sopenharmony_ci if ((*last != '\0') || (last == port_str)) { 928c2ecf20Sopenharmony_ci printk(KERN_ERR "vde_setup - Bad port : '%s'\n", 938c2ecf20Sopenharmony_ci port_str); 948c2ecf20Sopenharmony_ci return 0; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci if (mode_str != NULL) { 998c2ecf20Sopenharmony_ci init->mode = simple_strtoul(mode_str, &last, 8); 1008c2ecf20Sopenharmony_ci if ((*last != '\0') || (last == mode_str)) { 1018c2ecf20Sopenharmony_ci printk(KERN_ERR "vde_setup - Bad mode : '%s'\n", 1028c2ecf20Sopenharmony_ci mode_str); 1038c2ecf20Sopenharmony_ci return 0; 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci printk(KERN_INFO "Configured vde device: %s\n", init->vde_switch ? 1088c2ecf20Sopenharmony_ci init->vde_switch : "(default socket)"); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci return 1; 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic struct transport vde_transport = { 1148c2ecf20Sopenharmony_ci .list = LIST_HEAD_INIT(vde_transport.list), 1158c2ecf20Sopenharmony_ci .name = "vde", 1168c2ecf20Sopenharmony_ci .setup = vde_setup, 1178c2ecf20Sopenharmony_ci .user = &vde_user_info, 1188c2ecf20Sopenharmony_ci .kern = &vde_kern_info, 1198c2ecf20Sopenharmony_ci .private_size = sizeof(struct vde_data), 1208c2ecf20Sopenharmony_ci .setup_size = sizeof(struct vde_init), 1218c2ecf20Sopenharmony_ci}; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic int register_vde(void) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci register_transport(&vde_transport); 1268c2ecf20Sopenharmony_ci return 0; 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cilate_initcall(register_vde); 130