162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org). 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Transport usage: 662306a36Sopenharmony_ci * ethN=vde,<vde_switch>,<mac addr>,<port>,<group>,<mode>,<description> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/init.h> 1162306a36Sopenharmony_ci#include <linux/netdevice.h> 1262306a36Sopenharmony_ci#include <net_kern.h> 1362306a36Sopenharmony_ci#include <net_user.h> 1462306a36Sopenharmony_ci#include "vde.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistatic void vde_init(struct net_device *dev, void *data) 1762306a36Sopenharmony_ci{ 1862306a36Sopenharmony_ci struct vde_init *init = data; 1962306a36Sopenharmony_ci struct uml_net_private *pri; 2062306a36Sopenharmony_ci struct vde_data *vpri; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci pri = netdev_priv(dev); 2362306a36Sopenharmony_ci vpri = (struct vde_data *) pri->user; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci vpri->vde_switch = init->vde_switch; 2662306a36Sopenharmony_ci vpri->descr = init->descr ? init->descr : "UML vde_transport"; 2762306a36Sopenharmony_ci vpri->args = NULL; 2862306a36Sopenharmony_ci vpri->conn = NULL; 2962306a36Sopenharmony_ci vpri->dev = dev; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci printk("vde backend - %s, ", vpri->vde_switch ? 3262306a36Sopenharmony_ci vpri->vde_switch : "(default socket)"); 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci vde_init_libstuff(vpri, init); 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci printk("\n"); 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic int vde_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci struct vde_data *pri = (struct vde_data *) &lp->user; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci if (pri->conn != NULL) 4462306a36Sopenharmony_ci return vde_user_read(pri->conn, skb_mac_header(skb), 4562306a36Sopenharmony_ci skb->dev->mtu + ETH_HEADER_OTHER); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci printk(KERN_ERR "vde_read - we have no VDECONN to read from"); 4862306a36Sopenharmony_ci return -EBADF; 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic int vde_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci struct vde_data *pri = (struct vde_data *) &lp->user; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci if (pri->conn != NULL) 5662306a36Sopenharmony_ci return vde_user_write((void *)pri->conn, skb->data, 5762306a36Sopenharmony_ci skb->len); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci printk(KERN_ERR "vde_write - we have no VDECONN to write to"); 6062306a36Sopenharmony_ci return -EBADF; 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistatic const struct net_kern_info vde_kern_info = { 6462306a36Sopenharmony_ci .init = vde_init, 6562306a36Sopenharmony_ci .protocol = eth_protocol, 6662306a36Sopenharmony_ci .read = vde_read, 6762306a36Sopenharmony_ci .write = vde_write, 6862306a36Sopenharmony_ci}; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic int vde_setup(char *str, char **mac_out, void *data) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci struct vde_init *init = data; 7362306a36Sopenharmony_ci char *remain, *port_str = NULL, *mode_str = NULL, *last; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci *init = ((struct vde_init) 7662306a36Sopenharmony_ci { .vde_switch = NULL, 7762306a36Sopenharmony_ci .descr = NULL, 7862306a36Sopenharmony_ci .port = 0, 7962306a36Sopenharmony_ci .group = NULL, 8062306a36Sopenharmony_ci .mode = 0 }); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci remain = split_if_spec(str, &init->vde_switch, mac_out, &port_str, 8362306a36Sopenharmony_ci &init->group, &mode_str, &init->descr, NULL); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci if (remain != NULL) 8662306a36Sopenharmony_ci printk(KERN_WARNING "vde_setup - Ignoring extra data :" 8762306a36Sopenharmony_ci "'%s'\n", remain); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci if (port_str != NULL) { 9062306a36Sopenharmony_ci init->port = simple_strtoul(port_str, &last, 10); 9162306a36Sopenharmony_ci if ((*last != '\0') || (last == port_str)) { 9262306a36Sopenharmony_ci printk(KERN_ERR "vde_setup - Bad port : '%s'\n", 9362306a36Sopenharmony_ci port_str); 9462306a36Sopenharmony_ci return 0; 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci if (mode_str != NULL) { 9962306a36Sopenharmony_ci init->mode = simple_strtoul(mode_str, &last, 8); 10062306a36Sopenharmony_ci if ((*last != '\0') || (last == mode_str)) { 10162306a36Sopenharmony_ci printk(KERN_ERR "vde_setup - Bad mode : '%s'\n", 10262306a36Sopenharmony_ci mode_str); 10362306a36Sopenharmony_ci return 0; 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci printk(KERN_INFO "Configured vde device: %s\n", init->vde_switch ? 10862306a36Sopenharmony_ci init->vde_switch : "(default socket)"); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci return 1; 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistatic struct transport vde_transport = { 11462306a36Sopenharmony_ci .list = LIST_HEAD_INIT(vde_transport.list), 11562306a36Sopenharmony_ci .name = "vde", 11662306a36Sopenharmony_ci .setup = vde_setup, 11762306a36Sopenharmony_ci .user = &vde_user_info, 11862306a36Sopenharmony_ci .kern = &vde_kern_info, 11962306a36Sopenharmony_ci .private_size = sizeof(struct vde_data), 12062306a36Sopenharmony_ci .setup_size = sizeof(struct vde_init), 12162306a36Sopenharmony_ci}; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistatic int register_vde(void) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci register_transport(&vde_transport); 12662306a36Sopenharmony_ci return 0; 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cilate_initcall(register_vde); 130