162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org). 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <stddef.h> 762306a36Sopenharmony_ci#include <errno.h> 862306a36Sopenharmony_ci#include <libvdeplug.h> 962306a36Sopenharmony_ci#include <net_user.h> 1062306a36Sopenharmony_ci#include <um_malloc.h> 1162306a36Sopenharmony_ci#include "vde.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic int vde_user_init(void *data, void *dev) 1462306a36Sopenharmony_ci{ 1562306a36Sopenharmony_ci struct vde_data *pri = data; 1662306a36Sopenharmony_ci VDECONN *conn = NULL; 1762306a36Sopenharmony_ci int err = -EINVAL; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci pri->dev = dev; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci conn = vde_open(pri->vde_switch, pri->descr, pri->args); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci if (conn == NULL) { 2462306a36Sopenharmony_ci err = -errno; 2562306a36Sopenharmony_ci printk(UM_KERN_ERR "vde_user_init: vde_open failed, " 2662306a36Sopenharmony_ci "errno = %d\n", errno); 2762306a36Sopenharmony_ci return err; 2862306a36Sopenharmony_ci } 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci printk(UM_KERN_INFO "vde backend - connection opened\n"); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci pri->conn = conn; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci return 0; 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic int vde_user_open(void *data) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci struct vde_data *pri = data; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci if (pri->conn != NULL) 4262306a36Sopenharmony_ci return vde_datafd(pri->conn); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci printk(UM_KERN_WARNING "vde_open - we have no VDECONN to open"); 4562306a36Sopenharmony_ci return -EINVAL; 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic void vde_remove(void *data) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci struct vde_data *pri = data; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci if (pri->conn != NULL) { 5362306a36Sopenharmony_ci printk(UM_KERN_INFO "vde backend - closing connection\n"); 5462306a36Sopenharmony_ci vde_close(pri->conn); 5562306a36Sopenharmony_ci pri->conn = NULL; 5662306a36Sopenharmony_ci kfree(pri->args); 5762306a36Sopenharmony_ci pri->args = NULL; 5862306a36Sopenharmony_ci return; 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci printk(UM_KERN_WARNING "vde_remove - we have no VDECONN to remove"); 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ciconst struct net_user_info vde_user_info = { 6562306a36Sopenharmony_ci .init = vde_user_init, 6662306a36Sopenharmony_ci .open = vde_user_open, 6762306a36Sopenharmony_ci .close = NULL, 6862306a36Sopenharmony_ci .remove = vde_remove, 6962306a36Sopenharmony_ci .add_address = NULL, 7062306a36Sopenharmony_ci .delete_address = NULL, 7162306a36Sopenharmony_ci .mtu = ETH_MAX_PACKET, 7262306a36Sopenharmony_ci .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, 7362306a36Sopenharmony_ci}; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_civoid vde_init_libstuff(struct vde_data *vpri, struct vde_init *init) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci struct vde_open_args *args; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci vpri->args = uml_kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL); 8062306a36Sopenharmony_ci if (vpri->args == NULL) { 8162306a36Sopenharmony_ci printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args " 8262306a36Sopenharmony_ci "allocation failed"); 8362306a36Sopenharmony_ci return; 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci args = vpri->args; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci args->port = init->port; 8962306a36Sopenharmony_ci args->group = init->group; 9062306a36Sopenharmony_ci args->mode = init->mode ? init->mode : 0700; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci args->port ? printk("port %d", args->port) : 9362306a36Sopenharmony_ci printk("undefined port"); 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ciint vde_user_read(void *conn, void *buf, int len) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci VDECONN *vconn = conn; 9962306a36Sopenharmony_ci int rv; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci if (vconn == NULL) 10262306a36Sopenharmony_ci return 0; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci rv = vde_recv(vconn, buf, len, 0); 10562306a36Sopenharmony_ci if (rv < 0) { 10662306a36Sopenharmony_ci if (errno == EAGAIN) 10762306a36Sopenharmony_ci return 0; 10862306a36Sopenharmony_ci return -errno; 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci else if (rv == 0) 11162306a36Sopenharmony_ci return -ENOTCONN; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci return rv; 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ciint vde_user_write(void *conn, void *buf, int len) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci VDECONN *vconn = conn; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci if (vconn == NULL) 12162306a36Sopenharmony_ci return 0; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci return vde_send(vconn, buf, len, 0); 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 126