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

Reply via email to