Hi, the attached diff adds support for rdomains in vmd.
In vm.conf, add an interface to a specified rdomain. local interfaces work as expected, but the host-side routing and PF has to be done in the non-default rdomain as well. vm "foo" { local interface rdomain 1 interface { rdomain 2 } ... } Or add all VM interfaces on a switch to a specified rdomain: switch "bar" { rdomain 1 ... } OK? Reyk Index: usr.sbin/vmd/config.c =================================================================== RCS file: /cvs/src/usr.sbin/vmd/config.c,v retrieving revision 1.30 diff -u -p -u -p -r1.30 config.c --- usr.sbin/vmd/config.c 21 Apr 2017 07:03:26 -0000 1.30 +++ usr.sbin/vmd/config.c 3 May 2017 10:02:58 -0000 @@ -282,6 +282,9 @@ config_setvm(struct privsep *ps, struct } } + /* non-default rdomain (requires VMIFF_RDOMAIN below) */ + vif->vif_rdomain = vmc->vmc_ifrdomain[i]; + /* Set the interface status */ vif->vif_flags = vmc->vmc_ifflags[i] & (VMIFF_UP|VMIFF_OPTMASK); Index: usr.sbin/vmd/parse.y =================================================================== RCS file: /cvs/src/usr.sbin/vmd/parse.y,v retrieving revision 1.28 diff -u -p -u -p -r1.28 parse.y --- usr.sbin/vmd/parse.y 3 May 2017 08:21:57 -0000 1.28 +++ usr.sbin/vmd/parse.y 3 May 2017 10:02:59 -0000 @@ -116,7 +116,7 @@ typedef struct { %token INCLUDE ERROR %token ADD BOOT DISABLE DISK DOWN ENABLE GROUP INTERFACE LLADDR LOCAL LOCKED -%token MEMORY NIFS OWNER PATH PREFIX SIZE SWITCH UP VM VMID +%token MEMORY NIFS OWNER PATH PREFIX RDOMAIN SIZE SWITCH UP VM VMID %token <v.number> NUMBER %token <v.string> STRING %type <v.lladdr> lladdr @@ -263,6 +263,14 @@ switch_opts : disable { | LOCKED LLADDR { vsw->sw_flags |= VMIFF_LOCKED; } + | RDOMAIN NUMBER { + if ($2 < 0 || $2 > RT_TABLEID_MAX) { + yyerror("invalid rdomain: %lld", $2); + YYERROR; + } + vsw->sw_flags |= VMIFF_RDOMAIN; + vsw->sw_rdomain = $2; + } | updown { if ($1) vsw->sw_flags |= VMIFF_UP; @@ -532,6 +540,14 @@ iface_opts : SWITCH string { vmc.vmc_ifflags[vcp_nnics] |= VMIFF_LOCKED; memcpy(vcp->vcp_macs[vcp_nnics], $3, ETHER_ADDR_LEN); } + | RDOMAIN NUMBER { + if ($2 < 0 || $2 > RT_TABLEID_MAX) { + yyerror("invalid rdomain: %lld", $2); + YYERROR; + } + vmc.vmc_ifflags[vcp_nnics] |= VMIFF_RDOMAIN; + vmc.vmc_ifrdomain[vcp_nnics] = $2; + } | updown { if ($1) vmc.vmc_ifflags[vcp_nnics] |= VMIFF_UP; @@ -645,6 +661,7 @@ lookup(char *s) { "memory", MEMORY }, { "owner", OWNER }, { "prefix", PREFIX }, + { "rdomain", RDOMAIN }, { "size", SIZE }, { "switch", SWITCH }, { "up", UP }, Index: usr.sbin/vmd/priv.c =================================================================== RCS file: /cvs/src/usr.sbin/vmd/priv.c,v retrieving revision 1.8 diff -u -p -u -p -r1.8 priv.c --- usr.sbin/vmd/priv.c 21 Apr 2017 07:03:26 -0000 1.8 +++ usr.sbin/vmd/priv.c 3 May 2017 10:02:59 -0000 @@ -88,6 +88,7 @@ priv_dispatch_parent(int fd, struct priv switch (imsg->hdr.type) { case IMSG_VMDOP_PRIV_IFDESCR: case IMSG_VMDOP_PRIV_IFCREATE: + case IMSG_VMDOP_PRIV_IFRDOMAIN: case IMSG_VMDOP_PRIV_IFADD: case IMSG_VMDOP_PRIV_IFUP: case IMSG_VMDOP_PRIV_IFDOWN: @@ -124,6 +125,12 @@ priv_dispatch_parent(int fd, struct priv errno != EEXIST) log_warn("SIOCIFCREATE"); break; + case IMSG_VMDOP_PRIV_IFRDOMAIN: + strlcpy(ifr.ifr_name, vfr.vfr_name, sizeof(ifr.ifr_name)); + ifr.ifr_rdomainid = vfr.vfr_id; + if (ioctl(env->vmd_fd, SIOCSIFRDOMAIN, &ifr) < 0) + log_warn("SIOCSIFRDOMAIN"); + break; case IMSG_VMDOP_PRIV_IFADD: if (priv_getiftype(vfr.vfr_value, type, NULL) == -1) fatalx("%s: rejected to add interface: %s", @@ -272,6 +279,17 @@ vm_priv_ifconfig(struct privsep *ps, str sizeof(vfr.vfr_name)) >= sizeof(vfr.vfr_name)) return (-1); + /* Set non-default rdomain */ + if (vif->vif_flags & VMIFF_RDOMAIN) { + vfr.vfr_id = vif->vif_rdomain; + + log_debug("%s: interface %s rdomain %u", __func__, + vfr.vfr_name, vfr.vfr_id); + + proc_compose(ps, PROC_PRIV, IMSG_VMDOP_PRIV_IFRDOMAIN, + &vfr, sizeof(vfr)); + } + /* Description can be truncated */ (void)snprintf(vfr.vfr_value, sizeof(vfr.vfr_value), "vm%u-if%u-%s", vm->vm_vmid, i, vcp->vcp_name); @@ -284,18 +302,25 @@ vm_priv_ifconfig(struct privsep *ps, str /* Add interface to bridge/switch */ if ((vsw = switch_getbyname(vif->vif_switch)) != NULL) { + memset(&vfbr, 0, sizeof(vfbr)); + if (strlcpy(vfbr.vfr_name, vsw->sw_ifname, sizeof(vfbr.vfr_name)) >= sizeof(vfbr.vfr_name)) return (-1); if (strlcpy(vfbr.vfr_value, vif->vif_name, sizeof(vfbr.vfr_value)) >= sizeof(vfbr.vfr_value)) return (-1); + vfbr.vfr_id = vsw->sw_rdomain; log_debug("%s: interface %s add %s", __func__, vfbr.vfr_name, vfbr.vfr_value); proc_compose(ps, PROC_PRIV, IMSG_VMDOP_PRIV_IFCREATE, &vfbr, sizeof(vfbr)); + if (vsw->sw_flags & VMIFF_RDOMAIN) + proc_compose(ps, + PROC_PRIV, IMSG_VMDOP_PRIV_IFRDOMAIN, + &vfbr, sizeof(vfbr)); proc_compose(ps, PROC_PRIV, IMSG_VMDOP_PRIV_IFADD, &vfbr, sizeof(vfbr)); } else if (vif->vif_switch != NULL) @@ -365,12 +390,20 @@ vm_priv_brconfig(struct privsep *ps, str struct vmd_if *vif; struct vmop_ifreq vfr; + memset(&vfr, 0, sizeof(vfr)); + if (strlcpy(vfr.vfr_name, vsw->sw_ifname, sizeof(vfr.vfr_name)) >= sizeof(vfr.vfr_name)) return (-1); + vfr.vfr_id = vsw->sw_rdomain; proc_compose(ps, PROC_PRIV, IMSG_VMDOP_PRIV_IFCREATE, &vfr, sizeof(vfr)); + + /* Set non-default rdomain */ + if (vsw->sw_flags & VMIFF_RDOMAIN) + proc_compose(ps, PROC_PRIV, IMSG_VMDOP_PRIV_IFRDOMAIN, + &vfr, sizeof(vfr)); /* Description can be truncated */ (void)snprintf(vfr.vfr_value, sizeof(vfr.vfr_value), Index: usr.sbin/vmd/vm.conf.5 =================================================================== RCS file: /cvs/src/usr.sbin/vmd/vm.conf.5,v retrieving revision 1.19 diff -u -p -u -p -r1.19 vm.conf.5 --- usr.sbin/vmd/vm.conf.5 21 Apr 2017 07:03:26 -0000 1.19 +++ usr.sbin/vmd/vm.conf.5 3 May 2017 10:02:59 -0000 @@ -161,6 +161,9 @@ If the keyword is specified, .Xr vmd 8 will drop packets from the VM with altered source addresses. +.It Cm rdomain Ar rdomainid +Attach the interface to the routing domain with the specified +.Ar rdomainid . .It Cm switch Ar name Set the virtual switch by @@ -282,6 +285,12 @@ e.g.\& If the type is changed to .Ar switch0 , it will be used for each following switch. +.It Cm rdomain Ar rdomainid +Set the routing domain of the switch and all of its VM interfaces to +.Ar rdomainid . +This overwrites the +.Cm rdomain +option of VM interfaces. .It Cm up Start the switch forwarding packets. This is the default. Index: usr.sbin/vmd/vmd.c =================================================================== RCS file: /cvs/src/usr.sbin/vmd/vmd.c,v retrieving revision 1.59 diff -u -p -u -p -r1.59 vmd.c --- usr.sbin/vmd/vmd.c 25 Apr 2017 16:38:23 -0000 1.59 +++ usr.sbin/vmd/vmd.c 3 May 2017 10:02:59 -0000 @@ -863,6 +863,10 @@ vm_register(struct privsep *ps, struct v vm->vm_ifs[i].vif_fd = -1; if ((sw = switch_getbyname(vmc->vmc_ifswitch[i])) != NULL) { + /* overwrite the rdomain; if configured on the switch */ + if (sw->sw_flags & VMIFF_RDOMAIN) + vmc->vmc_ifrdomain[i] = sw->sw_rdomain; + /* inherit per-interface flags from the switch */ vmc->vmc_ifflags[i] |= (sw->sw_flags & VMIFF_OPTMASK); } Index: usr.sbin/vmd/vmd.h =================================================================== RCS file: /cvs/src/usr.sbin/vmd/vmd.h,v retrieving revision 1.52 diff -u -p -u -p -r1.52 vmd.h --- usr.sbin/vmd/vmd.h 21 Apr 2017 07:03:26 -0000 1.52 +++ usr.sbin/vmd/vmd.h 3 May 2017 10:02:59 -0000 @@ -80,6 +80,7 @@ enum imsg_type { IMSG_VMDOP_PRIV_IFDOWN, IMSG_VMDOP_PRIV_IFGROUP, IMSG_VMDOP_PRIV_IFADDR, + IMSG_VMDOP_PRIV_IFRDOMAIN, IMSG_VMDOP_VM_SHUTDOWN, IMSG_VMDOP_VM_REBOOT, IMSG_VMDOP_CONFIG @@ -125,10 +126,12 @@ struct vmop_create_params { #define VMIFF_UP 0x01 #define VMIFF_LOCKED 0x02 #define VMIFF_LOCAL 0x04 -#define VMIFF_OPTMASK (VMIFF_LOCKED|VMIFF_LOCAL) +#define VMIFF_RDOMAIN 0x08 +#define VMIFF_OPTMASK (VMIFF_LOCKED|VMIFF_LOCAL|VMIFF_RDOMAIN) char vmc_ifnames[VMM_MAX_NICS_PER_VM][IF_NAMESIZE]; char vmc_ifswitch[VMM_MAX_NICS_PER_VM][VM_NAME_MAX]; char vmc_ifgroup[VMM_MAX_NICS_PER_VM][IF_NAMESIZE]; + unsigned int vmc_ifrdomain[VMM_MAX_NICS_PER_VM]; uid_t vmc_uid; int64_t vmc_gid; }; @@ -148,6 +151,7 @@ struct vmd_if { char *vif_switch; char *vif_group; int vif_fd; + unsigned int vif_rdomain; unsigned int vif_flags; TAILQ_ENTRY(vmd_if) vif_entry; }; @@ -158,6 +162,7 @@ struct vmd_switch { char *sw_name; char sw_ifname[IF_NAMESIZE]; char *sw_group; + unsigned int sw_rdomain; unsigned int sw_flags; struct viflist sw_ifs; int sw_running;