Removed configuration items on switches for: * adding interfaces * setting group * setting rdomain
All of these items are now to be set in hostname.if and are queried by vmd for propagation to the vm's vif(s). Update example vm.conf and vm.conf manpage to reflect changes. Comments? Ok? diff --git etc/examples/vm.conf etc/examples/vm.conf index f35235e3fba..836a9f5a7c7 100644 --- etc/examples/vm.conf +++ etc/examples/vm.conf @@ -10,15 +10,14 @@ sets="/var/www/htdocs/pub/OpenBSD/snapshots/amd64/" # switch "uplink" { - # This interface will default to bridge0, but switch(4) is supported - #interface switch0 - - # Add additional members - add em0 + # This switch will use bridge0, defined by /etc/hostname.bridge0, as + # the underlying interface. switch(4) is also supported as + # interface switchX + interface bridge0 } switch "local" { - add vether0 + interface bridge1 down } diff --git usr.sbin/vmd/parse.y usr.sbin/vmd/parse.y index a0e96545923..0bb1b0ceefa 100644 --- usr.sbin/vmd/parse.y +++ usr.sbin/vmd/parse.y @@ -88,7 +88,6 @@ int parse_disk(char *); static struct vmop_create_params vmc; static struct vm_create_params *vcp; static struct vmd_switch *vsw; -static struct vmd_if *vif; static struct vmd_vm *vm; static char vsw_type[IF_NAMESIZE]; static int vcp_disable; @@ -193,7 +192,7 @@ switch : SWITCH string { vsw->sw_id = env->vmd_nswitches + 1; vsw->sw_name = $2; vsw->sw_flags = VMIFF_UP; - TAILQ_INIT(&vsw->sw_ifs); + TAILQ_INIT(&vsw->sw_group); vcp_disable = 0; } '{' optnl switch_opts_l '}' { @@ -224,29 +223,6 @@ switch_opts_l : switch_opts_l switch_opts nl switch_opts : disable { vcp_disable = $1; } - | ADD string { - char type[IF_NAMESIZE]; - - if ((vif = calloc(1, sizeof(*vif))) == NULL) - fatal("could not allocate interface"); - - if (priv_getiftype($2, type, NULL) == -1) { - yyerror("invalid interface: %s", $2); - free($2); - YYERROR; - } - vif->vif_name = $2; - - TAILQ_INSERT_TAIL(&vsw->sw_ifs, vif, vif_entry); - } - | GROUP string { - if (priv_validgroup($2) == -1) { - yyerror("invalid group name: %s", $2); - free($2); - YYERROR; - } - vsw->sw_group = $2; - } | INTERFACE string { if (priv_getiftype($2, vsw_type, NULL) == -1 || priv_findname(vsw_type, vmd_descsw) == -1) { @@ -266,14 +242,6 @@ 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; diff --git usr.sbin/vmd/priv.c usr.sbin/vmd/priv.c index d585bf75a99..6253ccdd785 100644 --- usr.sbin/vmd/priv.c +++ usr.sbin/vmd/priv.c @@ -44,6 +44,9 @@ #include "proc.h" #include "vmd.h" +/* if groups to ignore */ +const char *ifgroup_ignore[] = { "all", "bridge", "switch", NULL }; + int priv_dispatch_parent(int, struct privsep_proc *, struct imsg *); void priv_run(struct privsep *, struct privsep_proc *, void *); @@ -264,6 +267,7 @@ 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_ifgr *vifgrp; struct vmd_switch *vsw; unsigned int i; struct vmop_ifreq vfr, vfbr; @@ -279,18 +283,6 @@ vm_priv_ifconfig(struct privsep *ps, struct vmd_vm *vm) sizeof(vfr.vfr_name)) >= sizeof(vfr.vfr_name)) return (-1); - /* Use the configured rdomain or get it from the process */ - if (vif->vif_flags & VMIFF_RDOMAIN) - vfr.vfr_id = vif->vif_rdomain; - else - vfr.vfr_id = getrtable(); - if (vfr.vfr_id != 0) - 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); @@ -301,7 +293,7 @@ vm_priv_ifconfig(struct privsep *ps, struct vmd_vm *vm) proc_compose(ps, PROC_PRIV, IMSG_VMDOP_PRIV_IFDESCR, &vfr, sizeof(vfr)); - /* Add interface to bridge/switch */ + /* Set rdomain (if needed) and add interface to bridge/switch */ if ((vsw = switch_getbyname(vif->vif_switch)) != NULL) { memset(&vfbr, 0, sizeof(vfbr)); @@ -311,18 +303,41 @@ vm_priv_ifconfig(struct privsep *ps, struct vmd_vm *vm) if (strlcpy(vfbr.vfr_value, vif->vif_name, sizeof(vfbr.vfr_value)) >= sizeof(vfbr.vfr_value)) return (-1); - if (vsw->sw_flags & VMIFF_RDOMAIN) - vfbr.vfr_id = vsw->sw_rdomain; - else - vfbr.vfr_id = getrtable(); + + + /* check rdomain on iterface prior to add*/ + if (vsw->sw_flags & VMIFF_RDOMAIN) { + vfr.vfr_id = vsw->sw_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)); + } log_debug("%s: interface %s add %s", __func__, vfbr.vfr_name, vfbr.vfr_value); proc_compose(ps, PROC_PRIV, IMSG_VMDOP_PRIV_IFADD, &vfbr, sizeof(vfbr)); - } else if (vif->vif_switch != NULL) - log_warnx("switch %s not found", vif->vif_switch); + } else if (vif->vif_switch != NULL) { + log_warnx("%s: switch %s not found", __func__, + vif->vif_switch); + } else { + /* Use the configured rdomain for the vif + * or + * get it from the process */ + if (vif->vif_flags & VMIFF_RDOMAIN) + vfr.vfr_id = vif->vif_rdomain; + else + vfr.vfr_id = getrtable(); + if (vfr.vfr_id != 0) + 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)); + } /* First group is defined per-interface */ if (vif->vif_group) { @@ -337,18 +352,22 @@ vm_priv_ifconfig(struct privsep *ps, struct vmd_vm *vm) &vfr, sizeof(vfr)); } - /* The second group is defined per-switch */ - if (vsw != NULL && vsw->sw_group != NULL) { - if (strlcpy(vfr.vfr_value, vsw->sw_group, - sizeof(vfr.vfr_value)) >= sizeof(vfr.vfr_value)) - return (-1); - - log_debug("%s: interface %s group %s switch %s", - __func__, vfr.vfr_name, vfr.vfr_value, - vsw->sw_name); - - proc_compose(ps, PROC_PRIV, IMSG_VMDOP_PRIV_IFGROUP, - &vfr, sizeof(vfr)); + /* Propagate any groups on bridge/switch to vif*/ + if (vsw != NULL && !TAILQ_EMPTY(&vsw->sw_group)) { + /* for each group, add group to interface */ + TAILQ_FOREACH(vifgrp, &vsw->sw_group, gr_entry) { + if (strlcpy(vfr.vfr_value, vifgrp->gr_name, + sizeof(vfr.vfr_value)) >= + sizeof(vfr.vfr_value)) + return (-1); + + log_debug("%s: interface %s group %s switch %s", + __func__, vfr.vfr_name, vfr.vfr_value, + vsw->sw_name); + + proc_compose(ps, PROC_PRIV, + IMSG_VMDOP_PRIV_IFGROUP, &vfr, sizeof(vfr)); + } } /* Set the new interface status to up or down */ @@ -385,8 +404,13 @@ vm_priv_ifconfig(struct privsep *ps, struct vmd_vm *vm) int vm_priv_brconfig(struct privsep *ps, struct vmd_switch *vsw) { - struct vmd_if *vif; struct vmop_ifreq vfr; + int sock_fd; + size_t len; + struct ifreq ifr; + struct ifgroupreq ifgr; + struct ifg_req *ifg; + struct vmd_ifgr *ifgroup; memset(&vfr, 0, sizeof(vfr)); @@ -398,17 +422,72 @@ vm_priv_brconfig(struct privsep *ps, struct vmd_switch *vsw) proc_compose(ps, PROC_PRIV, IMSG_VMDOP_PRIV_IFEXISTS, &vfr, sizeof(vfr)); - /* Use the configured rdomain or get it from the process */ - if (vsw->sw_flags & VMIFF_RDOMAIN) - vfr.vfr_id = vsw->sw_rdomain; - else - vfr.vfr_id = getrtable(); - if (vfr.vfr_id != 0) - log_debug("%s: interface %s rdomain %u", __func__, - vfr.vfr_name, vfr.vfr_id); + /* retrieve groups from bridge/switch and store for later */ + memset(&ifgr, 0, sizeof(ifgr)); + strlcpy(ifgr.ifgr_name, vsw->sw_ifname, sizeof(ifgr.ifgr_name)); - proc_compose(ps, PROC_PRIV, IMSG_VMDOP_PRIV_IFRDOMAIN, - &vfr, sizeof(vfr)); + if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) + fatal("socket"); + + log_debug("%s: querying interface %s for sw \"%s\"", + __func__, ifgr.ifgr_name, vsw->sw_name); + + if (ioctl(sock_fd, SIOCGIFGROUP, &ifgr) == -1) { + log_debug("%s: unable to obtain groups from sw \"%s\"", + __func__, vsw->sw_name); + } else { + len = ifgr.ifgr_len; + ifgr.ifgr_groups = calloc(len / sizeof(struct ifg_req), + sizeof(struct ifg_req)); + + if (ifgr.ifgr_groups == NULL) { + fatalx("%s: unable to alloc memory for groups", + __func__); + } + + if (ioctl(sock_fd, SIOCGIFGROUP, &ifgr) == -1) { + log_debug("%s: SIOCGIFGROUP issues from sw \"%s\"", + __func__, vsw->sw_name); + } else { + ifg = ifgr.ifgr_groups; + for (; ifg && len >= sizeof(struct ifg_req); ifg++) { + len -= sizeof(struct ifg_req); + /* filter out system defined groups */ + if (priv_findname(ifg->ifgrq_group, + ifgroup_ignore) == 0) + continue; + + if((ifgroup = calloc(1, + sizeof(*ifgroup))) == NULL) { + fatalx("could not alloc group"); + } + + log_debug("%s: adding group %s to sw \"%s\"", + __func__, ifg->ifgrq_group, vsw->sw_name); + + strlcpy(ifgroup->gr_name, ifg->ifgrq_group, + sizeof(ifgroup->gr_name)); + + TAILQ_INSERT_TAIL(&vsw->sw_group, ifgroup, + gr_entry); + } + } + + free(ifgr.ifgr_groups); + } + + /* Retrieve the rdomain from the underlying interface */ + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, vsw->sw_ifname, sizeof(ifr.ifr_name)); + + if (ioctl(sock_fd, SIOCGIFRDOMAIN, &ifr) < 0) { + vsw->sw_rdomain = 0; + } else { + vsw->sw_rdomain = ifr.ifr_rdomainid; + vsw->sw_flags |= VMIFF_RDOMAIN; + log_debug("%s: interface %s has rdomain %d", __func__, + vsw->sw_ifname, vsw->sw_rdomain); + } /* Description can be truncated */ (void)snprintf(vfr.vfr_value, sizeof(vfr.vfr_value), @@ -420,24 +499,13 @@ vm_priv_brconfig(struct privsep *ps, struct vmd_switch *vsw) proc_compose(ps, PROC_PRIV, IMSG_VMDOP_PRIV_IFDESCR, &vfr, sizeof(vfr)); - TAILQ_FOREACH(vif, &vsw->sw_ifs, vif_entry) { - if (strlcpy(vfr.vfr_value, vif->vif_name, - sizeof(vfr.vfr_value)) >= sizeof(vfr.vfr_value)) - return (-1); - - log_debug("%s: interface %s add %s", __func__, - vfr.vfr_name, vfr.vfr_value); - - proc_compose(ps, PROC_PRIV, IMSG_VMDOP_PRIV_IFADD, - &vfr, sizeof(vfr)); - } - - /* Set the new interface status to up or down */ + /* Set the interface status to up or down */ proc_compose(ps, PROC_PRIV, (vsw->sw_flags & VMIFF_UP) ? IMSG_VMDOP_PRIV_IFUP : IMSG_VMDOP_PRIV_IFDOWN, &vfr, sizeof(vfr)); vsw->sw_running = 1; + close(sock_fd); return (0); } diff --git usr.sbin/vmd/vm.conf.5 usr.sbin/vmd/vm.conf.5 index 6ce21896657..40d6403ea6d 100644 --- usr.sbin/vmd/vm.conf.5 +++ usr.sbin/vmd/vm.conf.5 @@ -152,7 +152,9 @@ For example, this can be used to write rules for several VM interfaces in the same group. The .Ar group-name -must not end with a digit. +must not end with a digit. If the interface is attached to a switch +and the switch has a user-defined group, the interface will inherit the +group name as well. .It Oo Cm locked Oc Cm lladdr Op Ar etheraddr Change the link layer address (MAC address) of the interface on the VM guest side. @@ -166,6 +168,9 @@ 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 . +If attaching to a switch, the switch's +.Ar rdomainid +will be used instead. .It Cm switch Ar name Set the virtual switch by @@ -244,12 +249,6 @@ This name can be any string, and is typically a network name. .Pp Followed by a block of parameters that is enclosed in curly brackets: .Bl -tag -width Ds -.It Cm add Ar interface -Add -.Ar interface -as a member of the switch. -Any network interface can be added, typically as an uplink interface, -but it can be a member of at most one switch. .It Cm enable Automatically configure the switch. This is the default if neither @@ -264,15 +263,6 @@ will drop packets with altered sources addresses that do not match the link layer addresses (MAC addresses) of the VM interfaces in this switch. .It Cm disable Do not configure this switch. -.It Cm group Ar group-name -Assign each interface to a specific interface -.Dq group . -For example, this can be used to write -.Xr pf.conf 5 -rules for several VM interfaces in the same group. -The -.Ar group-name -must not end with a digit. .It Cm interface Ar name Set the .Xr switch 4 @@ -282,12 +272,6 @@ network interface of this switch. 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. @@ -310,11 +294,10 @@ vm "vm2.example.com" { } .Ed .Pp -Create the switch "uplink" with an additional physical network interface: +Create the switch "uplink" using bridge0 as the underlying interface: .Bd -literal -offset indent switch "uplink" { interface bridge0 - add em0 } .Ed .Sh SEE ALSO diff --git usr.sbin/vmd/vmd.c usr.sbin/vmd/vmd.c index 9e90c63cc99..1fb9b7ce0d8 100644 --- usr.sbin/vmd/vmd.c +++ usr.sbin/vmd/vmd.c @@ -806,9 +806,11 @@ vmd_configure(void) * recvfd - for send and receive. * getpw - lookup user or group id by name. * chown, fattr - change tty ownership + * inet - for retrieving bridge groups + * route - for retrieving bridge rdomains */ if (pledge("stdio rpath wpath proc tty recvfd sendfd getpw" - " chown fattr", NULL) == -1) + " chown fattr inet route", NULL) == -1) fatal("pledge"); if (parse_config(env->vmd_conffile) == -1) { @@ -1342,21 +1344,17 @@ vm_closetty(struct vmd_vm *vm) void switch_remove(struct vmd_switch *vsw) { - struct vmd_if *vif; - + struct vmd_ifgr *ifgr; if (vsw == NULL) return; TAILQ_REMOVE(env->vmd_switches, vsw, sw_entry); - while ((vif = TAILQ_FIRST(&vsw->sw_ifs)) != NULL) { - free(vif->vif_name); - free(vif->vif_switch); - TAILQ_REMOVE(&vsw->sw_ifs, vif, vif_entry); - free(vif); + while ((ifgr = TAILQ_FIRST(&vsw->sw_group)) != NULL) { + TAILQ_REMOVE(&vsw->sw_group, ifgr, gr_entry); + free(ifgr); } - free(vsw->sw_group); free(vsw->sw_name); free(vsw); } diff --git usr.sbin/vmd/vmd.h usr.sbin/vmd/vmd.h index a82aa8e8107..f17e91ccc7c 100644 --- usr.sbin/vmd/vmd.h +++ usr.sbin/vmd/vmd.h @@ -191,16 +191,20 @@ struct vmd_if { unsigned int vif_flags; TAILQ_ENTRY(vmd_if) vif_entry; }; -TAILQ_HEAD(viflist, vmd_if); + +struct vmd_ifgr { + char gr_name[IF_NAMESIZE]; + TAILQ_ENTRY(vmd_ifgr) gr_entry; +}; +TAILQ_HEAD(ifgrlist, vmd_ifgr); struct vmd_switch { uint32_t sw_id; char *sw_name; char sw_ifname[IF_NAMESIZE]; - char *sw_group; + struct ifgrlist sw_group; unsigned int sw_rdomain; unsigned int sw_flags; - struct viflist sw_ifs; int sw_running; TAILQ_ENTRY(vmd_switch) sw_entry; }; -- 2.14.3