Quantcast

vmd: "local prefix" for L3 interfaces

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

vmd: "local prefix" for L3 interfaces

Reyk Floeter-2
Hi,

the following diffs allows to change the prefix that is used to
allocated "local interface" (-L) subnets, which is 100.64.0.0/10 by
default.

So you can just change it in vm.conf, eg.
local prefix 10.0.0.0/8

Most people should be fine with the default but sthen@ and chris@
asked for an option to change it.  This doesn't allow to change it
per-VM, it is currently only changed globally.

OK?

Reyk

Index: usr.sbin/vmd/config.c
===================================================================
RCS file: /cvs/src/usr.sbin/vmd/config.c,v
retrieving revision 1.29
diff -u -p -u -p -r1.29 config.c
--- usr.sbin/vmd/config.c 26 Mar 2017 18:32:39 -0000 1.29
+++ usr.sbin/vmd/config.c 20 Apr 2017 19:45:57 -0000
@@ -50,7 +50,9 @@ config_init(struct vmd *env)
  /* Global configuration */
  ps->ps_what[PROC_PARENT] = CONFIG_ALL;
  ps->ps_what[PROC_VMM] = CONFIG_VMS;
- ps->ps_what[PROC_PRIV] = 0;
+
+ if (host(VMD_DHCP_PREFIX, &env->vmd_cfg.cfg_localprefix) == -1)
+ return (-1);
 
  /* Other configuration */
  what = ps->ps_what[privsep_process];
@@ -77,6 +79,10 @@ config_purge(struct vmd *env, unsigned i
  struct vmd_switch *vsw;
  unsigned int what;
 
+ /* Reset global configuration (prefix was verified before) */
+ (void)host(VMD_DHCP_PREFIX, &env->vmd_cfg.cfg_localprefix);
+
+ /* Reset other configuration */
  what = ps->ps_what[privsep_process] & reset;
  if (what & CONFIG_VMS && env->vmd_vms != NULL) {
  while ((vm = TAILQ_FIRST(env->vmd_vms)) != NULL)
@@ -88,6 +94,31 @@ config_purge(struct vmd *env, unsigned i
  switch_remove(vsw);
  env->vmd_nswitches = 0;
  }
+}
+
+int
+config_setconfig(struct vmd *env)
+{
+ struct privsep *ps = &env->vmd_ps;
+ unsigned int id;
+
+ for (id = 0; id < PROC_MAX; id++) {
+ if (id == privsep_process)
+ continue;
+ proc_compose(ps, id, IMSG_VMDOP_CONFIG, &env->vmd_cfg,
+    sizeof(env->vmd_cfg));
+ }
+
+ return (0);
+}
+
+int
+config_getconfig(struct vmd *env, struct imsg *imsg)
+{
+ IMSG_SIZE_CHECK(imsg, &env->vmd_cfg);
+ memcpy(&env->vmd_cfg, imsg->data, sizeof(env->vmd_cfg));
+
+ return (0);
 }
 
 int
Index: usr.sbin/vmd/control.c
===================================================================
RCS file: /cvs/src/usr.sbin/vmd/control.c,v
retrieving revision 1.16
diff -u -p -u -p -r1.16 control.c
--- usr.sbin/vmd/control.c 15 Mar 2017 12:42:12 -0000 1.16
+++ usr.sbin/vmd/control.c 20 Apr 2017 19:45:57 -0000
@@ -79,6 +79,7 @@ int
 control_dispatch_vmd(int fd, struct privsep_proc *p, struct imsg *imsg)
 {
  struct ctl_conn *c;
+ struct privsep *ps = p->p_ps;
 
  switch (imsg->hdr.type) {
  case IMSG_VMDOP_START_VM_RESPONSE:
@@ -92,6 +93,12 @@ control_dispatch_vmd(int fd, struct priv
  }
  imsg_compose_event(&c->iev, imsg->hdr.type,
     0, 0, -1, imsg->data, IMSG_DATA_SIZE(imsg));
+ break;
+ case IMSG_VMDOP_CONFIG:
+ config_getconfig(ps->ps_env, imsg);
+ break;
+ case IMSG_CTL_RESET:
+ config_getreset(ps->ps_env, imsg);
  break;
  default:
  return (-1);
Index: usr.sbin/vmd/dhcp.c
===================================================================
RCS file: /cvs/src/usr.sbin/vmd/dhcp.c,v
retrieving revision 1.1
diff -u -p -u -p -r1.1 dhcp.c
--- usr.sbin/vmd/dhcp.c 19 Apr 2017 15:38:32 -0000 1.1
+++ usr.sbin/vmd/dhcp.c 20 Apr 2017 19:45:57 -0000
@@ -33,6 +33,7 @@
 #include "virtio.h"
 
 static const uint8_t broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+extern struct vmd *env;
 
 ssize_t
 dhcp_request(struct vionet_dev *dev, char *buf, size_t buflen, char **obuf)
@@ -81,13 +82,15 @@ dhcp_request(struct vionet_dev *dev, cha
  resp.hlen = req.hlen;
  resp.xid = req.xid;
 
- if ((in.s_addr = vm_priv_addr(dev->vm_vmid, dev->idx, 1)) == 0)
+ if ((in.s_addr = vm_priv_addr(&env->vmd_cfg.cfg_localprefix,
+    dev->vm_vmid, dev->idx, 1)) == 0)
  return (-1);
  memcpy(&resp.yiaddr, &in, sizeof(in));
  memcpy(&ss2sin(&pc.pc_dst)->sin_addr, &in, sizeof(in));
  ss2sin(&pc.pc_dst)->sin_port = htons(CLIENT_PORT);
 
- if ((in.s_addr = vm_priv_addr(dev->vm_vmid, dev->idx, 0)) == 0)
+ if ((in.s_addr = vm_priv_addr(&env->vmd_cfg.cfg_localprefix,
+    dev->vm_vmid, dev->idx, 0)) == 0)
  return (-1);
  memcpy(&resp.siaddr, &in, sizeof(in));
  memcpy(&ss2sin(&pc.pc_src)->sin_addr, &in, sizeof(in));
Index: usr.sbin/vmd/parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/vmd/parse.y,v
retrieving revision 1.25
diff -u -p -u -p -r1.25 parse.y
--- usr.sbin/vmd/parse.y 19 Apr 2017 15:38:32 -0000 1.25
+++ usr.sbin/vmd/parse.y 20 Apr 2017 19:45:57 -0000
@@ -116,7 +116,7 @@ typedef struct {
 
 %token INCLUDE ERROR
 %token ADD DISK DOWN GROUP INTERFACE NIFS PATH SIZE SWITCH UP VMID
-%token ENABLE DISABLE VM BOOT LLADDR MEMORY OWNER LOCKED LOCAL
+%token ENABLE DISABLE VM BOOT LLADDR MEMORY OWNER LOCKED LOCAL PREFIX
 %token <v.string> STRING
 %token  <v.number> NUMBER
 %type <v.number> disable
@@ -134,6 +134,7 @@ grammar : /* empty */
  | grammar include '\n'
  | grammar '\n'
  | grammar varset '\n'
+ | grammar main '\n'
  | grammar switch '\n'
  | grammar vm '\n'
  | grammar error '\n' { file->errors++; }
@@ -170,6 +171,22 @@ varset : STRING '=' STRING {
  }
  ;
 
+main : LOCAL PREFIX STRING {
+ struct address h;
+
+ /* The local prefix is IPv4-only */
+ if (host($3, &h) == -1 ||
+    h.ss.ss_family != AF_INET ||
+    h.prefixlen > 32 || h.prefixlen < 0) {
+ yyerror("invalid local prefix: %s", $3);
+ free($3);
+ YYERROR;
+ }
+
+ memcpy(&env->vmd_cfg.cfg_localprefix, &h, sizeof(h));
+ }
+ ;
+
 switch : SWITCH string {
  if ((vsw = calloc(1, sizeof(*vsw))) == NULL)
  fatal("could not allocate switch");
@@ -627,6 +644,7 @@ lookup(char *s)
  { "locked", LOCKED },
  { "memory", MEMORY },
  { "owner", OWNER },
+ { "prefix", PREFIX },
  { "size", SIZE },
  { "switch", SWITCH },
  { "up", UP },
@@ -1093,4 +1111,44 @@ parse_disk(char *word)
  vcp->vcp_ndisks++;
 
  return (0);
+}
+
+int
+host(const char *str, struct address *h)
+{
+ struct addrinfo hints, *res;
+ int prefixlen;
+ char *s, *p;
+ const char *errstr;
+
+ if ((s = strdup(str)) == NULL) {
+ log_warn("strdup");
+ goto fail;
+ }
+
+ if ((p = strrchr(s, '/')) != NULL) {
+ *p++ = '\0';
+ prefixlen = strtonum(p, 0, 128, &errstr);
+ if (errstr) {
+ log_warnx("prefixlen is %s: %s", errstr, p);
+ goto fail;
+ }
+ } else
+ prefixlen = 128;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_NUMERICHOST;
+ if (getaddrinfo(s, NULL, &hints, &res) == 0) {
+ memset(h, 0, sizeof(*h));
+ memcpy(&h->ss, res->ai_addr, res->ai_addrlen);
+ h->prefixlen = prefixlen;
+ freeaddrinfo(res);
+ free(s);
+ return (0);
+ }
+
+ fail:
+ free(s);
+ return (-1);
 }
Index: usr.sbin/vmd/priv.c
===================================================================
RCS file: /cvs/src/usr.sbin/vmd/priv.c,v
retrieving revision 1.7
diff -u -p -u -p -r1.7 priv.c
--- usr.sbin/vmd/priv.c 19 Apr 2017 15:38:32 -0000 1.7
+++ usr.sbin/vmd/priv.c 20 Apr 2017 19:45:57 -0000
@@ -102,6 +102,9 @@ priv_dispatch_parent(int fd, struct priv
  fatalx("%s: rejected priv operation on interface: %s",
     __func__, vfr.vfr_name);
  break;
+ case IMSG_VMDOP_CONFIG:
+ case IMSG_CTL_RESET:
+ break;
  default:
  return (-1);
  }
@@ -183,6 +186,12 @@ priv_dispatch_parent(int fd, struct priv
  if (ioctl(env->vmd_fd, SIOCAIFADDR, &ifra) < 0)
  log_warn("SIOCAIFADDR");
  break;
+ case IMSG_VMDOP_CONFIG:
+ config_getconfig(env, imsg);
+ break;
+ case IMSG_CTL_RESET:
+ config_getreset(env, imsg);
+ break;
  default:
  return (-1);
  }
@@ -245,6 +254,7 @@ priv_validgroup(const char *name)
 int
 vm_priv_ifconfig(struct privsep *ps, struct vmd_vm *vm)
 {
+ struct vmd *env = ps->ps_env;
  struct vm_create_params *vcp = &vm->vm_params.vmc_params;
  struct vmd_if *vif;
  struct vmd_switch *vsw;
@@ -333,7 +343,8 @@ vm_priv_ifconfig(struct privsep *ps, str
  sin4->sin_family = AF_INET;
  sin4->sin_len = sizeof(*sin4);
  if ((sin4->sin_addr.s_addr =
-    vm_priv_addr(vm->vm_vmid, i, 0)) == 0)
+    vm_priv_addr(&env->vmd_cfg.cfg_localprefix,
+    vm->vm_vmid, i, 0)) == 0)
  return (-1);
 
  log_debug("%s: interface %s address %s/31",
@@ -393,16 +404,18 @@ vm_priv_brconfig(struct privsep *ps, str
 }
 
 uint32_t
-vm_priv_addr(uint32_t vmid, int idx, int isvm)
+vm_priv_addr(struct address *h, uint32_t vmid, int idx, int isvm)
 {
- in_addr_t prefix, mask, addr;
+ in_addr_t prefix, mask, addr;
 
  /*
  * 1. Set the address prefix and mask, 100.64.0.0/10 by default.
- * XXX make the global prefix configurable.
  */
- prefix = inet_addr(VMD_DHCP_PREFIX);
- mask = prefixlen2mask(VMD_DHCP_PREFIXLEN);
+ if (h->ss.ss_family != AF_INET ||
+    h->prefixlen < 0 || h->prefixlen > 32)
+ fatal("local prefix");
+ prefix = ss2sin(&h->ss)->sin_addr.s_addr;
+ mask = prefixlen2mask(h->prefixlen);
 
  /* 2. Encode the VM ID as a per-VM subnet range N, 10.64.N.0/24. */
  addr = vmid << 8;
Index: usr.sbin/vmd/vm.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/vmd/vm.conf.5,v
retrieving revision 1.18
diff -u -p -u -p -r1.18 vm.conf.5
--- usr.sbin/vmd/vm.conf.5 19 Apr 2017 15:38:32 -0000 1.18
+++ usr.sbin/vmd/vm.conf.5 20 Apr 2017 19:45:58 -0000
@@ -31,11 +31,14 @@ The VMM subsystem is responsible for cre
 executing VMs.
 .Sh SECTIONS
 .Nm
-is divided into three main sections:
+is divided into four main sections:
 .Bl -tag -width xxxx
 .It Sy Macros
 User-defined variables may be defined and used later, simplifying the
 configuration file.
+.It Sy Global Configuration
+Global settings for
+.Xr vmd 8 .
 .It Sy VM Configuration
 Configuration for each individual virtual machine.
 .It Sy Switch Configuration
@@ -85,6 +88,19 @@ vm "vm1.example.com" {
  boot $ramdisk
 }
 .Ed
+.Sh GLOBAL CONFIGURATION
+The following setting can be configured globally:
+.Bl -tag -width Ds
+.It Ic local prefix Ar address Ns Li / Ns Ar prefix
+Set the network prefix that is used to allocate subnets for
+local interfaces, see
+.Ic local interface
+in the
+.Sx VM CONFIGURATION
+section below.
+The default is
+.Ar 100.64.0.0/10 .
+.El
 .Sh VM CONFIGURATION
 Each
 .Ic vm
Index: usr.sbin/vmd/vmd.c
===================================================================
RCS file: /cvs/src/usr.sbin/vmd/vmd.c,v
retrieving revision 1.57
diff -u -p -u -p -r1.57 vmd.c
--- usr.sbin/vmd/vmd.c 19 Apr 2017 15:38:32 -0000 1.57
+++ usr.sbin/vmd/vmd.c 20 Apr 2017 19:45:58 -0000
@@ -562,6 +562,10 @@ vmd_configure(void)
  return (-1);
  }
 
+ /* Send shared global configuration to all children */
+ if (config_setconfig(env) == -1)
+ return (-1);
+
  return (0);
 }
 
@@ -598,6 +602,10 @@ vmd_reload(unsigned int reset, const cha
  if (vm->vm_running == 0)
  vm_remove(vm);
  }
+
+ /* Update shared global configuration in all children */
+ if (config_setconfig(env) == -1)
+ return;
  }
 
  if (parse_config(filename) == -1) {
Index: usr.sbin/vmd/vmd.h
===================================================================
RCS file: /cvs/src/usr.sbin/vmd/vmd.h,v
retrieving revision 1.51
diff -u -p -u -p -r1.51 vmd.h
--- usr.sbin/vmd/vmd.h 19 Apr 2017 15:38:32 -0000 1.51
+++ usr.sbin/vmd/vmd.h 20 Apr 2017 19:45:58 -0000
@@ -51,8 +51,7 @@
 #define VM_DEFAULT_MEMORY 512
 
 /* 100.64.0.0/10 from rfc6598 (IPv4 Prefix for Shared Address Space) */
-#define VMD_DHCP_PREFIX "100.64.0.0"
-#define VMD_DHCP_PREFIXLEN 10
+#define VMD_DHCP_PREFIX "100.64.0.0/10"
 
 #ifdef VMD_DEBUG
 #define dprintf(x...)   do { log_debug(x); } while(0)
@@ -82,7 +81,8 @@ enum imsg_type {
  IMSG_VMDOP_PRIV_IFGROUP,
  IMSG_VMDOP_PRIV_IFADDR,
  IMSG_VMDOP_VM_SHUTDOWN,
- IMSG_VMDOP_VM_REBOOT
+ IMSG_VMDOP_VM_REBOOT,
+ IMSG_VMDOP_CONFIG
 };
 
 struct vmop_result {
@@ -189,17 +189,30 @@ struct vmd_vm {
 };
 TAILQ_HEAD(vmlist, vmd_vm);
 
+struct address {
+ struct sockaddr_storage ss;
+ int prefixlen;
+ TAILQ_ENTRY(address) entry;
+};
+TAILQ_HEAD(addresslist, address);
+
+struct vmd_config {
+ struct address cfg_localprefix;
+};
+
 struct vmd {
  struct privsep vmd_ps;
  const char *vmd_conffile;
 
+ /* global configuration that is sent to the children */
+ struct vmd_config vmd_cfg;
+
  int vmd_debug;
  int vmd_verbose;
  int vmd_noaction;
 
  uint32_t vmd_nvm;
  struct vmlist *vmd_vms;
-
  uint32_t vmd_nswitches;
  struct switchlist *vmd_switches;
 
@@ -266,7 +279,7 @@ int priv_findname(const char *, const c
 int priv_validgroup(const char *);
 int vm_priv_ifconfig(struct privsep *, struct vmd_vm *);
 int vm_priv_brconfig(struct privsep *, struct vmd_switch *);
-uint32_t vm_priv_addr(uint32_t, int, int);
+uint32_t vm_priv_addr(struct address *, uint32_t, int, int);
 
 /* vmm.c */
 void vmm(struct privsep *, struct privsep_proc *);
@@ -286,6 +299,8 @@ __dead void vm_shutdown(unsigned int);
 /* control.c */
 int config_init(struct vmd *);
 void config_purge(struct vmd *, unsigned int);
+int config_setconfig(struct vmd *);
+int config_getconfig(struct vmd *, struct imsg *);
 int config_setreset(struct vmd *, unsigned int);
 int config_getreset(struct vmd *, struct imsg *);
 int config_setvm(struct privsep *, struct vmd_vm *, uint32_t, uid_t);
@@ -300,5 +315,6 @@ void vmboot_close(FILE *, struct vmboot
 /* parse.y */
 int parse_config(const char *);
 int cmdline_symset(char *);
+int host(const char *, struct address *);
 
 #endif /* VMD_H */
Index: usr.sbin/vmd/vmm.c
===================================================================
RCS file: /cvs/src/usr.sbin/vmd/vmm.c,v
retrieving revision 1.68
diff -u -p -u -p -r1.68 vmm.c
--- usr.sbin/vmd/vmm.c 6 Apr 2017 18:07:13 -0000 1.68
+++ usr.sbin/vmd/vmm.c 20 Apr 2017 19:45:58 -0000
@@ -175,6 +175,9 @@ vmm_dispatch_parent(int fd, struct privs
  res = get_info_vm(ps, imsg, 0);
  cmd = IMSG_VMDOP_GET_INFO_VM_END_DATA;
  break;
+ case IMSG_VMDOP_CONFIG:
+ config_getconfig(env, imsg);
+ break;
  case IMSG_CTL_RESET:
  IMSG_SIZE_CHECK(imsg, &mode);
  memcpy(&mode, imsg->data, sizeof(mode));

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: vmd: "local prefix" for L3 interfaces

Mike Larkin
On Thu, Apr 20, 2017 at 10:03:52PM +0200, Reyk Floeter wrote:

> Hi,
>
> the following diffs allows to change the prefix that is used to
> allocated "local interface" (-L) subnets, which is 100.64.0.0/10 by
> default.
>
> So you can just change it in vm.conf, eg.
> local prefix 10.0.0.0/8
>
> Most people should be fine with the default but sthen@ and chris@
> asked for an option to change it.  This doesn't allow to change it
> per-VM, it is currently only changed globally.
>
> OK?
>
> Reyk
>

I was opposed to this earlier, thinking it added an un-needed knob.
However, the functionality is well hidden, so I think it's a good
compromise.

ok mlarkin

> Index: usr.sbin/vmd/config.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/vmd/config.c,v
> retrieving revision 1.29
> diff -u -p -u -p -r1.29 config.c
> --- usr.sbin/vmd/config.c 26 Mar 2017 18:32:39 -0000 1.29
> +++ usr.sbin/vmd/config.c 20 Apr 2017 19:45:57 -0000
> @@ -50,7 +50,9 @@ config_init(struct vmd *env)
>   /* Global configuration */
>   ps->ps_what[PROC_PARENT] = CONFIG_ALL;
>   ps->ps_what[PROC_VMM] = CONFIG_VMS;
> - ps->ps_what[PROC_PRIV] = 0;
> +
> + if (host(VMD_DHCP_PREFIX, &env->vmd_cfg.cfg_localprefix) == -1)
> + return (-1);
>  
>   /* Other configuration */
>   what = ps->ps_what[privsep_process];
> @@ -77,6 +79,10 @@ config_purge(struct vmd *env, unsigned i
>   struct vmd_switch *vsw;
>   unsigned int what;
>  
> + /* Reset global configuration (prefix was verified before) */
> + (void)host(VMD_DHCP_PREFIX, &env->vmd_cfg.cfg_localprefix);
> +
> + /* Reset other configuration */
>   what = ps->ps_what[privsep_process] & reset;
>   if (what & CONFIG_VMS && env->vmd_vms != NULL) {
>   while ((vm = TAILQ_FIRST(env->vmd_vms)) != NULL)
> @@ -88,6 +94,31 @@ config_purge(struct vmd *env, unsigned i
>   switch_remove(vsw);
>   env->vmd_nswitches = 0;
>   }
> +}
> +
> +int
> +config_setconfig(struct vmd *env)
> +{
> + struct privsep *ps = &env->vmd_ps;
> + unsigned int id;
> +
> + for (id = 0; id < PROC_MAX; id++) {
> + if (id == privsep_process)
> + continue;
> + proc_compose(ps, id, IMSG_VMDOP_CONFIG, &env->vmd_cfg,
> +    sizeof(env->vmd_cfg));
> + }
> +
> + return (0);
> +}
> +
> +int
> +config_getconfig(struct vmd *env, struct imsg *imsg)
> +{
> + IMSG_SIZE_CHECK(imsg, &env->vmd_cfg);
> + memcpy(&env->vmd_cfg, imsg->data, sizeof(env->vmd_cfg));
> +
> + return (0);
>  }
>  
>  int
> Index: usr.sbin/vmd/control.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/vmd/control.c,v
> retrieving revision 1.16
> diff -u -p -u -p -r1.16 control.c
> --- usr.sbin/vmd/control.c 15 Mar 2017 12:42:12 -0000 1.16
> +++ usr.sbin/vmd/control.c 20 Apr 2017 19:45:57 -0000
> @@ -79,6 +79,7 @@ int
>  control_dispatch_vmd(int fd, struct privsep_proc *p, struct imsg *imsg)
>  {
>   struct ctl_conn *c;
> + struct privsep *ps = p->p_ps;
>  
>   switch (imsg->hdr.type) {
>   case IMSG_VMDOP_START_VM_RESPONSE:
> @@ -92,6 +93,12 @@ control_dispatch_vmd(int fd, struct priv
>   }
>   imsg_compose_event(&c->iev, imsg->hdr.type,
>      0, 0, -1, imsg->data, IMSG_DATA_SIZE(imsg));
> + break;
> + case IMSG_VMDOP_CONFIG:
> + config_getconfig(ps->ps_env, imsg);
> + break;
> + case IMSG_CTL_RESET:
> + config_getreset(ps->ps_env, imsg);
>   break;
>   default:
>   return (-1);
> Index: usr.sbin/vmd/dhcp.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/vmd/dhcp.c,v
> retrieving revision 1.1
> diff -u -p -u -p -r1.1 dhcp.c
> --- usr.sbin/vmd/dhcp.c 19 Apr 2017 15:38:32 -0000 1.1
> +++ usr.sbin/vmd/dhcp.c 20 Apr 2017 19:45:57 -0000
> @@ -33,6 +33,7 @@
>  #include "virtio.h"
>  
>  static const uint8_t broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
> +extern struct vmd *env;
>  
>  ssize_t
>  dhcp_request(struct vionet_dev *dev, char *buf, size_t buflen, char **obuf)
> @@ -81,13 +82,15 @@ dhcp_request(struct vionet_dev *dev, cha
>   resp.hlen = req.hlen;
>   resp.xid = req.xid;
>  
> - if ((in.s_addr = vm_priv_addr(dev->vm_vmid, dev->idx, 1)) == 0)
> + if ((in.s_addr = vm_priv_addr(&env->vmd_cfg.cfg_localprefix,
> +    dev->vm_vmid, dev->idx, 1)) == 0)
>   return (-1);
>   memcpy(&resp.yiaddr, &in, sizeof(in));
>   memcpy(&ss2sin(&pc.pc_dst)->sin_addr, &in, sizeof(in));
>   ss2sin(&pc.pc_dst)->sin_port = htons(CLIENT_PORT);
>  
> - if ((in.s_addr = vm_priv_addr(dev->vm_vmid, dev->idx, 0)) == 0)
> + if ((in.s_addr = vm_priv_addr(&env->vmd_cfg.cfg_localprefix,
> +    dev->vm_vmid, dev->idx, 0)) == 0)
>   return (-1);
>   memcpy(&resp.siaddr, &in, sizeof(in));
>   memcpy(&ss2sin(&pc.pc_src)->sin_addr, &in, sizeof(in));
> Index: usr.sbin/vmd/parse.y
> ===================================================================
> RCS file: /cvs/src/usr.sbin/vmd/parse.y,v
> retrieving revision 1.25
> diff -u -p -u -p -r1.25 parse.y
> --- usr.sbin/vmd/parse.y 19 Apr 2017 15:38:32 -0000 1.25
> +++ usr.sbin/vmd/parse.y 20 Apr 2017 19:45:57 -0000
> @@ -116,7 +116,7 @@ typedef struct {
>  
>  %token INCLUDE ERROR
>  %token ADD DISK DOWN GROUP INTERFACE NIFS PATH SIZE SWITCH UP VMID
> -%token ENABLE DISABLE VM BOOT LLADDR MEMORY OWNER LOCKED LOCAL
> +%token ENABLE DISABLE VM BOOT LLADDR MEMORY OWNER LOCKED LOCAL PREFIX
>  %token <v.string> STRING
>  %token  <v.number> NUMBER
>  %type <v.number> disable
> @@ -134,6 +134,7 @@ grammar : /* empty */
>   | grammar include '\n'
>   | grammar '\n'
>   | grammar varset '\n'
> + | grammar main '\n'
>   | grammar switch '\n'
>   | grammar vm '\n'
>   | grammar error '\n' { file->errors++; }
> @@ -170,6 +171,22 @@ varset : STRING '=' STRING {
>   }
>   ;
>  
> +main : LOCAL PREFIX STRING {
> + struct address h;
> +
> + /* The local prefix is IPv4-only */
> + if (host($3, &h) == -1 ||
> +    h.ss.ss_family != AF_INET ||
> +    h.prefixlen > 32 || h.prefixlen < 0) {
> + yyerror("invalid local prefix: %s", $3);
> + free($3);
> + YYERROR;
> + }
> +
> + memcpy(&env->vmd_cfg.cfg_localprefix, &h, sizeof(h));
> + }
> + ;
> +
>  switch : SWITCH string {
>   if ((vsw = calloc(1, sizeof(*vsw))) == NULL)
>   fatal("could not allocate switch");
> @@ -627,6 +644,7 @@ lookup(char *s)
>   { "locked", LOCKED },
>   { "memory", MEMORY },
>   { "owner", OWNER },
> + { "prefix", PREFIX },
>   { "size", SIZE },
>   { "switch", SWITCH },
>   { "up", UP },
> @@ -1093,4 +1111,44 @@ parse_disk(char *word)
>   vcp->vcp_ndisks++;
>  
>   return (0);
> +}
> +
> +int
> +host(const char *str, struct address *h)
> +{
> + struct addrinfo hints, *res;
> + int prefixlen;
> + char *s, *p;
> + const char *errstr;
> +
> + if ((s = strdup(str)) == NULL) {
> + log_warn("strdup");
> + goto fail;
> + }
> +
> + if ((p = strrchr(s, '/')) != NULL) {
> + *p++ = '\0';
> + prefixlen = strtonum(p, 0, 128, &errstr);
> + if (errstr) {
> + log_warnx("prefixlen is %s: %s", errstr, p);
> + goto fail;
> + }
> + } else
> + prefixlen = 128;
> +
> + memset(&hints, 0, sizeof(hints));
> + hints.ai_family = AF_UNSPEC;
> + hints.ai_flags = AI_NUMERICHOST;
> + if (getaddrinfo(s, NULL, &hints, &res) == 0) {
> + memset(h, 0, sizeof(*h));
> + memcpy(&h->ss, res->ai_addr, res->ai_addrlen);
> + h->prefixlen = prefixlen;
> + freeaddrinfo(res);
> + free(s);
> + return (0);
> + }
> +
> + fail:
> + free(s);
> + return (-1);
>  }
> Index: usr.sbin/vmd/priv.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/vmd/priv.c,v
> retrieving revision 1.7
> diff -u -p -u -p -r1.7 priv.c
> --- usr.sbin/vmd/priv.c 19 Apr 2017 15:38:32 -0000 1.7
> +++ usr.sbin/vmd/priv.c 20 Apr 2017 19:45:57 -0000
> @@ -102,6 +102,9 @@ priv_dispatch_parent(int fd, struct priv
>   fatalx("%s: rejected priv operation on interface: %s",
>      __func__, vfr.vfr_name);
>   break;
> + case IMSG_VMDOP_CONFIG:
> + case IMSG_CTL_RESET:
> + break;
>   default:
>   return (-1);
>   }
> @@ -183,6 +186,12 @@ priv_dispatch_parent(int fd, struct priv
>   if (ioctl(env->vmd_fd, SIOCAIFADDR, &ifra) < 0)
>   log_warn("SIOCAIFADDR");
>   break;
> + case IMSG_VMDOP_CONFIG:
> + config_getconfig(env, imsg);
> + break;
> + case IMSG_CTL_RESET:
> + config_getreset(env, imsg);
> + break;
>   default:
>   return (-1);
>   }
> @@ -245,6 +254,7 @@ priv_validgroup(const char *name)
>  int
>  vm_priv_ifconfig(struct privsep *ps, struct vmd_vm *vm)
>  {
> + struct vmd *env = ps->ps_env;
>   struct vm_create_params *vcp = &vm->vm_params.vmc_params;
>   struct vmd_if *vif;
>   struct vmd_switch *vsw;
> @@ -333,7 +343,8 @@ vm_priv_ifconfig(struct privsep *ps, str
>   sin4->sin_family = AF_INET;
>   sin4->sin_len = sizeof(*sin4);
>   if ((sin4->sin_addr.s_addr =
> -    vm_priv_addr(vm->vm_vmid, i, 0)) == 0)
> +    vm_priv_addr(&env->vmd_cfg.cfg_localprefix,
> +    vm->vm_vmid, i, 0)) == 0)
>   return (-1);
>  
>   log_debug("%s: interface %s address %s/31",
> @@ -393,16 +404,18 @@ vm_priv_brconfig(struct privsep *ps, str
>  }
>  
>  uint32_t
> -vm_priv_addr(uint32_t vmid, int idx, int isvm)
> +vm_priv_addr(struct address *h, uint32_t vmid, int idx, int isvm)
>  {
> - in_addr_t prefix, mask, addr;
> + in_addr_t prefix, mask, addr;
>  
>   /*
>   * 1. Set the address prefix and mask, 100.64.0.0/10 by default.
> - * XXX make the global prefix configurable.
>   */
> - prefix = inet_addr(VMD_DHCP_PREFIX);
> - mask = prefixlen2mask(VMD_DHCP_PREFIXLEN);
> + if (h->ss.ss_family != AF_INET ||
> +    h->prefixlen < 0 || h->prefixlen > 32)
> + fatal("local prefix");
> + prefix = ss2sin(&h->ss)->sin_addr.s_addr;
> + mask = prefixlen2mask(h->prefixlen);
>  
>   /* 2. Encode the VM ID as a per-VM subnet range N, 10.64.N.0/24. */
>   addr = vmid << 8;
> Index: usr.sbin/vmd/vm.conf.5
> ===================================================================
> RCS file: /cvs/src/usr.sbin/vmd/vm.conf.5,v
> retrieving revision 1.18
> diff -u -p -u -p -r1.18 vm.conf.5
> --- usr.sbin/vmd/vm.conf.5 19 Apr 2017 15:38:32 -0000 1.18
> +++ usr.sbin/vmd/vm.conf.5 20 Apr 2017 19:45:58 -0000
> @@ -31,11 +31,14 @@ The VMM subsystem is responsible for cre
>  executing VMs.
>  .Sh SECTIONS
>  .Nm
> -is divided into three main sections:
> +is divided into four main sections:
>  .Bl -tag -width xxxx
>  .It Sy Macros
>  User-defined variables may be defined and used later, simplifying the
>  configuration file.
> +.It Sy Global Configuration
> +Global settings for
> +.Xr vmd 8 .
>  .It Sy VM Configuration
>  Configuration for each individual virtual machine.
>  .It Sy Switch Configuration
> @@ -85,6 +88,19 @@ vm "vm1.example.com" {
>   boot $ramdisk
>  }
>  .Ed
> +.Sh GLOBAL CONFIGURATION
> +The following setting can be configured globally:
> +.Bl -tag -width Ds
> +.It Ic local prefix Ar address Ns Li / Ns Ar prefix
> +Set the network prefix that is used to allocate subnets for
> +local interfaces, see
> +.Ic local interface
> +in the
> +.Sx VM CONFIGURATION
> +section below.
> +The default is
> +.Ar 100.64.0.0/10 .
> +.El
>  .Sh VM CONFIGURATION
>  Each
>  .Ic vm
> Index: usr.sbin/vmd/vmd.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/vmd/vmd.c,v
> retrieving revision 1.57
> diff -u -p -u -p -r1.57 vmd.c
> --- usr.sbin/vmd/vmd.c 19 Apr 2017 15:38:32 -0000 1.57
> +++ usr.sbin/vmd/vmd.c 20 Apr 2017 19:45:58 -0000
> @@ -562,6 +562,10 @@ vmd_configure(void)
>   return (-1);
>   }
>  
> + /* Send shared global configuration to all children */
> + if (config_setconfig(env) == -1)
> + return (-1);
> +
>   return (0);
>  }
>  
> @@ -598,6 +602,10 @@ vmd_reload(unsigned int reset, const cha
>   if (vm->vm_running == 0)
>   vm_remove(vm);
>   }
> +
> + /* Update shared global configuration in all children */
> + if (config_setconfig(env) == -1)
> + return;
>   }
>  
>   if (parse_config(filename) == -1) {
> Index: usr.sbin/vmd/vmd.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/vmd/vmd.h,v
> retrieving revision 1.51
> diff -u -p -u -p -r1.51 vmd.h
> --- usr.sbin/vmd/vmd.h 19 Apr 2017 15:38:32 -0000 1.51
> +++ usr.sbin/vmd/vmd.h 20 Apr 2017 19:45:58 -0000
> @@ -51,8 +51,7 @@
>  #define VM_DEFAULT_MEMORY 512
>  
>  /* 100.64.0.0/10 from rfc6598 (IPv4 Prefix for Shared Address Space) */
> -#define VMD_DHCP_PREFIX "100.64.0.0"
> -#define VMD_DHCP_PREFIXLEN 10
> +#define VMD_DHCP_PREFIX "100.64.0.0/10"
>  
>  #ifdef VMD_DEBUG
>  #define dprintf(x...)   do { log_debug(x); } while(0)
> @@ -82,7 +81,8 @@ enum imsg_type {
>   IMSG_VMDOP_PRIV_IFGROUP,
>   IMSG_VMDOP_PRIV_IFADDR,
>   IMSG_VMDOP_VM_SHUTDOWN,
> - IMSG_VMDOP_VM_REBOOT
> + IMSG_VMDOP_VM_REBOOT,
> + IMSG_VMDOP_CONFIG
>  };
>  
>  struct vmop_result {
> @@ -189,17 +189,30 @@ struct vmd_vm {
>  };
>  TAILQ_HEAD(vmlist, vmd_vm);
>  
> +struct address {
> + struct sockaddr_storage ss;
> + int prefixlen;
> + TAILQ_ENTRY(address) entry;
> +};
> +TAILQ_HEAD(addresslist, address);
> +
> +struct vmd_config {
> + struct address cfg_localprefix;
> +};
> +
>  struct vmd {
>   struct privsep vmd_ps;
>   const char *vmd_conffile;
>  
> + /* global configuration that is sent to the children */
> + struct vmd_config vmd_cfg;
> +
>   int vmd_debug;
>   int vmd_verbose;
>   int vmd_noaction;
>  
>   uint32_t vmd_nvm;
>   struct vmlist *vmd_vms;
> -
>   uint32_t vmd_nswitches;
>   struct switchlist *vmd_switches;
>  
> @@ -266,7 +279,7 @@ int priv_findname(const char *, const c
>  int priv_validgroup(const char *);
>  int vm_priv_ifconfig(struct privsep *, struct vmd_vm *);
>  int vm_priv_brconfig(struct privsep *, struct vmd_switch *);
> -uint32_t vm_priv_addr(uint32_t, int, int);
> +uint32_t vm_priv_addr(struct address *, uint32_t, int, int);
>  
>  /* vmm.c */
>  void vmm(struct privsep *, struct privsep_proc *);
> @@ -286,6 +299,8 @@ __dead void vm_shutdown(unsigned int);
>  /* control.c */
>  int config_init(struct vmd *);
>  void config_purge(struct vmd *, unsigned int);
> +int config_setconfig(struct vmd *);
> +int config_getconfig(struct vmd *, struct imsg *);
>  int config_setreset(struct vmd *, unsigned int);
>  int config_getreset(struct vmd *, struct imsg *);
>  int config_setvm(struct privsep *, struct vmd_vm *, uint32_t, uid_t);
> @@ -300,5 +315,6 @@ void vmboot_close(FILE *, struct vmboot
>  /* parse.y */
>  int parse_config(const char *);
>  int cmdline_symset(char *);
> +int host(const char *, struct address *);
>  
>  #endif /* VMD_H */
> Index: usr.sbin/vmd/vmm.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/vmd/vmm.c,v
> retrieving revision 1.68
> diff -u -p -u -p -r1.68 vmm.c
> --- usr.sbin/vmd/vmm.c 6 Apr 2017 18:07:13 -0000 1.68
> +++ usr.sbin/vmd/vmm.c 20 Apr 2017 19:45:58 -0000
> @@ -175,6 +175,9 @@ vmm_dispatch_parent(int fd, struct privs
>   res = get_info_vm(ps, imsg, 0);
>   cmd = IMSG_VMDOP_GET_INFO_VM_END_DATA;
>   break;
> + case IMSG_VMDOP_CONFIG:
> + config_getconfig(env, imsg);
> + break;
>   case IMSG_CTL_RESET:
>   IMSG_SIZE_CHECK(imsg, &mode);
>   memcpy(&mode, imsg->data, sizeof(mode));
>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: vmd: "local prefix" for L3 interfaces

Stuart Henderson
On 2017/04/20 13:26, Mike Larkin wrote:

> On Thu, Apr 20, 2017 at 10:03:52PM +0200, Reyk Floeter wrote:
> > Hi,
> >
> > the following diffs allows to change the prefix that is used to
> > allocated "local interface" (-L) subnets, which is 100.64.0.0/10 by
> > default.
> >
> > So you can just change it in vm.conf, eg.
> > local prefix 10.0.0.0/8
> >
> > Most people should be fine with the default but sthen@ and chris@
> > asked for an option to change it.  This doesn't allow to change it
> > per-VM, it is currently only changed globally.
> >
> > OK?

Thanks - OK.

> I was opposed to this earlier, thinking it added an un-needed knob.
> However, the functionality is well hidden, so I think it's a good
> compromise.
>
> ok mlarkin

The CGN block 100.64/10 is assigned by some providers to user devices,
it's not a hypothetical sometime-in-the-future, they're already doing it.

Loading...