static bool parse_vnic_interface(char* name, uint16_t* vmid, uint16_t* vnic_index, uint16_t* interface_index) { if(strncmp(name, "v", 1)) return false; char* next; char* _vmid = strtok_r(name + 1, "eth", &next); if(!_vmid) return false; if(!is_uint8(_vmid)) return false; *vmid = parse_uint8(_vmid); char* _interface_index; char* _vnic_index = strtok_r(next, ":", &_interface_index); if(!_vnic_index) return false; if(!is_uint8(_vnic_index)) return false; *vnic_index = parse_uint8(_vnic_index); if(_interface_index) { if(!is_uint8(_interface_index)) return false; *interface_index = parse_uint8(_interface_index) + 1; } else *interface_index = 0; return true; }
static int vm_create(int argc, char* argv[]) { // Default value VMSpec vm = {}; vm.core_size = 1; vm.memory_size = 0x1000000; // 16MB vm.storage_size = 0x1000000; // 16MB // Main options static struct option options[] = { { "core", required_argument, 0, 'c' }, { "memory", required_argument, 0, 'm' }, { "storage", required_argument, 0, 's' }, { "nic", optional_argument, 0, 'n' }, { "args", required_argument, 0, 'a' }, { 0, 0, 0, 0 } }; int opt; int index = 0; while((opt = getopt_long(argc, argv, "c:m:s:n::a:", options, &index)) != -1) { switch(opt) { case 'c' : if(!is_uint32(optarg)) goto failure; vm.core_size = strtol(optarg, NULL, 0); break; case 'm' : if(!is_uint32(optarg)) goto failure; vm.memory_size = strtol(optarg, NULL, 16); break; case 's' : if(!is_uint32(optarg)) goto failure; vm.storage_size = strtol(optarg, NULL, 16); break; case 'n' :; // Suboptions for NIC enum { EMPTY, MAC, DEV, IBUF, OBUF, IBAND, OBAND, HPAD, TPAD, POOL, INHERITMAC, NOARP, PROMISC, BROADCAST, MULTICAST, MULTIQUEUE, }; const char* token[] = { [EMPTY] = "", [MAC] = "mac", [DEV] = "dev", [IBUF] = "ibuf", [OBUF] = "obuf", [IBAND] = "iband", [OBAND] = "oband", [HPAD] = "hpad", [TPAD] = "tpad", [POOL] = "pool", [INHERITMAC] = "inheritmac", [NOARP] = "noarp", [PROMISC] = "promisc", [BROADCAST] = "broadcast", [MULTICAST] = "multicast", [MULTIQUEUE] = "multiqueue", NULL, }; // Default NIC configuration NICSpec* nic = &vm.nics[vm.nic_count++]; nic->mac = 0; nic->parent[0] = '\0'; nic->budget = NICSPEC_DEFAULT_BUDGET_SIZE; nic->flags = NICSPEC_DEFAULT_FLAGS; nic->rx_buffer_size = 1024; nic->tx_buffer_size = 1024; nic->rx_bandwidth = 1000000000; /* 1 GB */ nic->tx_bandwidth = 1000000000; /* 1 GB */ nic->padding_head = 32; nic->padding_tail = 32; nic->pool_size = 0x400000; /* 4 MB */ char* subopts = optarg; while(optarg && *subopts != '\0') { char* value = NULL; int subopt_index = getsubopt(&subopts, (char* const*)token, &value); if(subopt_index == -1) goto failure; switch(subopt_index) { case EMPTY: break; case MAC: if(!is_uint64(value)) goto failure; nic->mac = strtoll(value, NULL, 16); break; case DEV: strncpy(nic->parent, value, MAX_NIC_NAME_LEN); break; case IBUF: if(!is_uint32(value)) goto failure; nic->rx_buffer_size = strtoul(value, NULL, 0); break; case OBUF: if(!is_uint32(value)) goto failure; nic->tx_buffer_size = strtoul(value, NULL, 0); break; case IBAND: if(!is_uint64(value)) goto failure; nic->rx_bandwidth = strtoull(value, NULL, 0); break; case OBAND: if(!is_uint64(value)) goto failure; nic->tx_bandwidth = strtoull(value, NULL, 0); break; case HPAD: if(!is_uint8(value)) goto failure; nic->padding_head = strtoul(value, NULL, 0); break; case TPAD: if(!is_uint8(value)) goto failure; nic->padding_tail = strtoul(value, NULL, 0); break; case POOL: if(!is_uint32(value)) goto failure; nic->pool_size = strtoul(value, NULL, 16); break; case INHERITMAC: if(!strcmp("on", value)) { nic->flags |= NICSPEC_F_INHERITMAC; } else if(!strcmp("off", value)) { nic->flags |= NICSPEC_F_INHERITMAC; nic->flags ^= NICSPEC_F_INHERITMAC; } else goto failure; break; case NOARP: if(!strcmp("on", value)) { nic->flags |= NICSPEC_F_NOARP; } else if(!strcmp("off", value)) { nic->flags |= NICSPEC_F_NOARP; nic->flags ^= NICSPEC_F_NOARP; } else goto failure; break; case PROMISC: if(!strcmp("on", value)) { nic->flags |= NICSPEC_F_PROMISC; } else if(!strcmp("off", value)) { nic->flags |= NICSPEC_F_PROMISC; nic->flags ^= NICSPEC_F_PROMISC; } else goto failure; break; case BROADCAST: if(!strcmp("on", value)) { nic->flags |= NICSPEC_F_BROADCAST; } else if(!strcmp("off", value)) { nic->flags |= NICSPEC_F_BROADCAST; nic->flags ^= NICSPEC_F_BROADCAST; } else goto failure; break; case MULTICAST: if(!strcmp("on", value)) { nic->flags |= NICSPEC_F_MULTICAST; } else if(!strcmp("off", value)) { nic->flags |= NICSPEC_F_MULTICAST; nic->flags ^= NICSPEC_F_MULTICAST; } else goto failure; break; case MULTIQUEUE: if(!strcmp("on", value)) { nic->flags |= NICSPEC_F_MULTIQUEUE; } else if(!strcmp("off", value)) { nic->flags |= NICSPEC_F_MULTIQUEUE; nic->flags ^= NICSPEC_F_MULTIQUEUE; } else goto failure; break; default: goto failure; break; } } break; case 'a' : vm.argv[vm.argc++] = strdup(optarg); if(errno == ENOMEM) goto failure; break; default: goto failure; } } rpc_vm_create(rpc, &vm, callback_vm_create, NULL); return 0; failure: printf("Malformed input were given\n"); help(); exit(EXIT_FAILURE); }