/* * Our first setup routine is the console. It's a fairly simple device, but * UNIX tty handling makes it uglier than it could be. */ static void setup_console(void) { struct device *dev; /* If we can save the initial standard input settings... */ if (tcgetattr(STDIN_FILENO, &orig_term) == 0) { struct termios term = orig_term; /* * Then we turn off echo, line buffering and ^C etc: We want a * raw input stream to the Guest. */ term.c_lflag &= ~(ISIG|ICANON|ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &term); } dev = new_device("console", VIRTIO_ID_CONSOLE); /* We store the console state in dev->priv, and initialize it. */ dev->priv = malloc(sizeof(struct console_abort)); ((struct console_abort *)dev->priv)->count = 0; /* * The console needs two virtqueues: the input then the output. When * they put something the input queue, we make sure we're listening to * stdin. When they put something in the output queue, we write it to * stdout. */ add_virtqueue(dev, VIRTQUEUE_NUM, console_input); add_virtqueue(dev, VIRTQUEUE_NUM, console_output); verbose("device %u: console\n", ++devices.device_num); }
static void setup_console(void) { struct device *dev; if (tcgetattr(STDIN_FILENO, &orig_term) == 0) { struct termios term = orig_term; term.c_lflag &= ~(ISIG|ICANON|ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &term); } dev = new_device("console", VIRTIO_ID_CONSOLE); dev->priv = malloc(sizeof(struct console_abort)); ((struct console_abort *)dev->priv)->count = 0; add_virtqueue(dev, VIRTQUEUE_NUM, console_input); add_virtqueue(dev, VIRTQUEUE_NUM, console_output); verbose("device %u: console\n", ++devices.device_num); }
static void setup_tun_net(char *arg) { struct device *dev; struct net_info *net_info = malloc(sizeof(*net_info)); int ipfd; u32 ip = INADDR_ANY; bool bridging = false; char tapif[IFNAMSIZ], *p; struct virtio_net_config conf; net_info->tunfd = get_tun_device(tapif); dev = new_device("net", VIRTIO_ID_NET); dev->priv = net_info; add_virtqueue(dev, VIRTQUEUE_NUM, net_input); add_virtqueue(dev, VIRTQUEUE_NUM, net_output); ipfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if (ipfd < 0) err(1, "opening IP socket"); if (!strncmp(BRIDGE_PFX, arg, strlen(BRIDGE_PFX))) { arg += strlen(BRIDGE_PFX); bridging = true; } p = strchr(arg, ':'); if (p) { str2mac(p+1, conf.mac); add_feature(dev, VIRTIO_NET_F_MAC); *p = '\0'; } if (bridging) add_to_bridge(ipfd, tapif, arg); else ip = str2ip(arg); configure_device(ipfd, tapif, ip); add_feature(dev, VIRTIO_NET_F_CSUM); add_feature(dev, VIRTIO_NET_F_GUEST_CSUM); add_feature(dev, VIRTIO_NET_F_GUEST_TSO4); add_feature(dev, VIRTIO_NET_F_GUEST_TSO6); add_feature(dev, VIRTIO_NET_F_GUEST_ECN); add_feature(dev, VIRTIO_NET_F_HOST_TSO4); add_feature(dev, VIRTIO_NET_F_HOST_TSO6); add_feature(dev, VIRTIO_NET_F_HOST_ECN); add_feature(dev, VIRTIO_RING_F_INDIRECT_DESC); set_config(dev, sizeof(conf), &conf); close(ipfd); devices.device_num++; if (bridging) verbose("device %u: tun %s attached to bridge: %s\n", devices.device_num, tapif, arg); else verbose("device %u: tun %s: %s\n", devices.device_num, tapif, arg); }
/*L:195 * Our network is a Host<->Guest network. This can either use bridging or * routing, but the principle is the same: it uses the "tun" device to inject * packets into the Host as if they came in from a normal network card. We * just shunt packets between the Guest and the tun device. */ static void setup_tun_net(char *arg) { struct device *dev; struct net_info *net_info = malloc(sizeof(*net_info)); int ipfd; u32 ip = INADDR_ANY; bool bridging = false; char tapif[IFNAMSIZ], *p; struct virtio_net_config conf; net_info->tunfd = get_tun_device(tapif); /* First we create a new network device. */ dev = new_device("net", VIRTIO_ID_NET); dev->priv = net_info; /* Network devices need a recv and a send queue, just like console. */ add_virtqueue(dev, VIRTQUEUE_NUM, net_input); add_virtqueue(dev, VIRTQUEUE_NUM, net_output); /* * We need a socket to perform the magic network ioctls to bring up the * tap interface, connect to the bridge etc. Any socket will do! */ ipfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if (ipfd < 0) err(1, "opening IP socket"); /* If the command line was --tunnet=bridge:<name> do bridging. */ if (!strncmp(BRIDGE_PFX, arg, strlen(BRIDGE_PFX))) { arg += strlen(BRIDGE_PFX); bridging = true; } /* A mac address may follow the bridge name or IP address */ p = strchr(arg, ':'); if (p) { str2mac(p+1, conf.mac); add_feature(dev, VIRTIO_NET_F_MAC); *p = '\0'; } /* arg is now either an IP address or a bridge name */ if (bridging) add_to_bridge(ipfd, tapif, arg); else ip = str2ip(arg); /* Set up the tun device. */ configure_device(ipfd, tapif, ip); /* Expect Guest to handle everything except UFO */ add_feature(dev, VIRTIO_NET_F_CSUM); add_feature(dev, VIRTIO_NET_F_GUEST_CSUM); add_feature(dev, VIRTIO_NET_F_GUEST_TSO4); add_feature(dev, VIRTIO_NET_F_GUEST_TSO6); add_feature(dev, VIRTIO_NET_F_GUEST_ECN); add_feature(dev, VIRTIO_NET_F_HOST_TSO4); add_feature(dev, VIRTIO_NET_F_HOST_TSO6); add_feature(dev, VIRTIO_NET_F_HOST_ECN); /* We handle indirect ring entries */ add_feature(dev, VIRTIO_RING_F_INDIRECT_DESC); set_config(dev, sizeof(conf), &conf); /* We don't need the socket any more; setup is done. */ close(ipfd); devices.device_num++; if (bridging) verbose("device %u: tun %s attached to bridge: %s\n", devices.device_num, tapif, arg); else verbose("device %u: tun %s: %s\n", devices.device_num, tapif, arg); }