mirror of
https://github.com/churchers/vm-bhyve.git
synced 2025-12-11 09:20:17 +01:00
This change add simiular support to VALE for netgraph switches. Switches must be configured manually. Devices will be added using the bhyve support of netgraph. Link Num of a peer in the bridge is found by iterrating all devices already setup in. (Similiar hack is found in jail example).
442 lines
14 KiB
Bash
442 lines
14 KiB
Bash
#!/bin/sh
|
|
#-------------------------------------------------------------------------+
|
|
# Copyright (C) 2016 Matt Churchyard (churchers@gmail.com)
|
|
# All rights reserved
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted providing that the following conditions
|
|
# are met:
|
|
# 1. Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
# POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
# switch libraries
|
|
#
|
|
. "${LIB}/vm-switch-netgraph"
|
|
. "${LIB}/vm-switch-manual"
|
|
. "${LIB}/vm-switch-standard"
|
|
. "${LIB}/vm-switch-vale"
|
|
. "${LIB}/vm-switch-vxlan"
|
|
|
|
# create switches from rc list on init
|
|
# this should run once per boot to make sure switches from the
|
|
# configuration file have bridge interfaces. If any new switches are
|
|
# created, the create function takes care of setting them up
|
|
#
|
|
switch::init(){
|
|
local _switchlist _switch _type
|
|
|
|
config::core::get "_switchlist" "switch_list"
|
|
|
|
if [ -n "${_switchlist}" ]; then
|
|
for _switch in ${_switchlist}; do
|
|
# get the switch type
|
|
config::core::get "_type" "type_${_switch}"
|
|
|
|
case "${_type}" in
|
|
vxlan) switch::vxlan::init "${_switch}" ;;
|
|
manual) switch::manual::init "${_switch}" ;;
|
|
vale) ;;
|
|
netgraph) ;;
|
|
*) switch::standard::init "${_switch}" ;;
|
|
esac
|
|
done
|
|
fi
|
|
}
|
|
|
|
# list switches configured
|
|
#
|
|
switch::list(){
|
|
local _switchlist _switch _type
|
|
local _id _format="%s^%s^%s^%s^%s^%s^%s^%s\n"
|
|
|
|
config::core::get "_switchlist" "switch_list"
|
|
|
|
{
|
|
printf "${_format}" "NAME" "TYPE" "IFACE" "ADDRESS" "PRIVATE" "MTU" "VLAN" "PORTS"
|
|
|
|
if [ -n "${_switchlist}" ]; then
|
|
for _switch in ${_switchlist}; do
|
|
# get the switch type
|
|
config::core::get "_type" "type_${_switch}"
|
|
|
|
case "${_type}" in
|
|
netgraph) switch::netgraph::show "${_switch}" "${_format}" ;;
|
|
vale) switch::vale::show "${_switch}" "${_format}" ;;
|
|
vxlan) switch::vxlan::show "${_switch}" "${_format}" ;;
|
|
manual) switch::manual::show "${_switch}" "${_format}" ;;
|
|
*) switch::standard::show "${_switch}" "${_format}" ;;
|
|
esac
|
|
done
|
|
fi
|
|
} | column -ts^
|
|
}
|
|
|
|
# create a new virtual switch
|
|
#
|
|
# @param string _switch name of the switch to create
|
|
#
|
|
switch::create(){
|
|
local _switch
|
|
local _type="standard"
|
|
local _list _curr _vlan _if _bridge _addr _mtu _priv
|
|
|
|
# process options
|
|
while getopts t:i:n:b:a:m:p _opt; do
|
|
case ${_opt} in
|
|
t) _type="${OPTARG}" ;;
|
|
i) _if="${OPTARG}" ;;
|
|
n) _vlan="${OPTARG}" ;;
|
|
b) _bridge="${OPTARG}" ;;
|
|
a) _addr="${OPTARG}" ;;
|
|
m) _mtu="${OPTARG}" ;;
|
|
p) _priv="yes" ;;
|
|
*) util::usage ;;
|
|
esac
|
|
done
|
|
|
|
shift $((OPTIND - 1))
|
|
_switch="$1"
|
|
|
|
# check for a valid switch name
|
|
util::check_name "${_switch}" || util::err "invalid switch name - '${_switch}'"
|
|
|
|
# make sure it's not an existing name
|
|
config::core::get "_list" "switch_list"
|
|
|
|
for _curr in ${_list}; do
|
|
[ "${_switch}" = "${_curr}" ] && util::err "switch ${_switch} already exists"
|
|
done
|
|
|
|
# check vlan number
|
|
if [ -n "${_vlan}" ]; then
|
|
echo "${_vlan}" | egrep -qs '^[0-9]{1,4}$'
|
|
[ $? -eq 0 ] || util::err "invalid vlan number"
|
|
[ ${_vlan} -ge 4095 ] && util::err "invalid vlan number"
|
|
fi
|
|
|
|
# check address
|
|
if [ -n "${_addr}" ]; then
|
|
echo "${_addr}" | egrep -qs '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}$'
|
|
[ $? -eq 0 ] || util::err "address must be supplied in CIDR notation (a.b.c.d/prefix-len)"
|
|
fi
|
|
|
|
# check mtu
|
|
if [ -n "${_mtu}" ]; then
|
|
echo "${_mtu}" | egrep -qs '^[0-9]{3,4}$'
|
|
[ $? -eq 0 ] || util::err "invalid mtu"
|
|
[ ${_mtu} -gt 9000 ] && util::err "invalid mtu"
|
|
fi
|
|
|
|
# check switch type
|
|
case "${_type}" in
|
|
standard) switch::standard::create ;;
|
|
manual) switch::manual::create ;;
|
|
netgraph) switch::netgraph:create ;;
|
|
vale) switch::vale::create ;;
|
|
vxlan) switch::vxlan::create ;;
|
|
*) util::err "invalid switch type - '${_type}'" ;;
|
|
esac
|
|
}
|
|
|
|
# destroy a switch
|
|
# remove from configuration and unload any interfaces we created
|
|
#
|
|
# @param string _switch name of the switch to remove
|
|
#
|
|
switch::remove(){
|
|
local _switch="$1"
|
|
local _type
|
|
|
|
[ -z "${_switch}" ] && util::usage
|
|
|
|
# get the type of switch
|
|
config::core::get "_type" "type_${_switch}"
|
|
|
|
case "${_type}" in
|
|
standard) switch::standard::remove "${_switch}" ;;
|
|
manual) switch::manual::remove "${_switch}" ;;
|
|
netgraph) switch::netgraph::remove "${_switch}" ;;
|
|
vale) switch::vale::remove "${_switch}" ;;
|
|
vxlan) switch::vxlan::remove "${_switch}" ;;
|
|
*) util::err "unable to remove switch of unknown type" ;;
|
|
esac
|
|
|
|
# remove all configuration if there's no error
|
|
if [ $? -eq 0 ]; then
|
|
config::core::remove "switch_list" "${_switch}"
|
|
config::core::remove "ports_${_switch} vlan_${_switch} nat_${_switch} type_${_switch}"
|
|
config::core::remove "addr_${_switch} private_${_switch} mtu_${_switch}"
|
|
else
|
|
util::err "failed to remove virtual switch"
|
|
fi
|
|
|
|
# make sure the exit status indicates success,
|
|
# even if config::core::remove did not
|
|
return 0
|
|
}
|
|
|
|
# add a new interface to a switch
|
|
#
|
|
# @param string _switch name of the switch
|
|
# @param string _if the interface to add
|
|
#
|
|
switch::add_member(){
|
|
local _switch="$1"
|
|
local _if="$2"
|
|
local _type
|
|
|
|
[ -z "${_switch}" -o -z "${_if}" ] && util::usage
|
|
|
|
# get the type of switch
|
|
config::core::get "_type" "type_${_switch}"
|
|
|
|
case "${_type}" in
|
|
standard) switch::standard::add_member "${_switch}" "${_if}" ;;
|
|
manual) switch::manual::add_member "${_switch}" "${_if}" ;;
|
|
netgraph) switch::netgraph::add_member "${_switch}" "${_if}" ;;
|
|
vale) switch::vale::add_member "${_switch}" "${_if}" ;;
|
|
vxlan) switch::vxlan::add_member "${_switch}" "${_if}" ;;
|
|
*) util::err "unable to configure switch of unknown type" ;;
|
|
esac
|
|
}
|
|
|
|
# remove a member interface from a virtual switch
|
|
#
|
|
# @param string _switch name of the switch
|
|
# @param string _if the interface to remove
|
|
#
|
|
switch::remove_member(){
|
|
local _switch="$1"
|
|
local _if="$2"
|
|
local _type
|
|
|
|
[ -z "${_switch}" -o -z "${_if}" ] && util::usage
|
|
|
|
# get the type of switch
|
|
config::core::get "_type" "type_${_switch}"
|
|
|
|
case "${_type}" in
|
|
standard) switch::standard::remove_member "${_switch}" "${_if}" ;;
|
|
manual) switch::manual::remove_member "${_switch}" "${_if}" ;;
|
|
netgraph) switch::netgraph::remove_member "${_switch}" "${_if}" ;;
|
|
vale) switch::vale::remove_member "${_switch}" "${_if}" ;;
|
|
vxlan) switch::vxlan::remove_member "${_switch}" "${_if}" ;;
|
|
*) util::err "unable to configure switch of unknown type" ;;
|
|
esac
|
|
}
|
|
|
|
# change the vlan number on a virtual switch
|
|
#
|
|
# @param string _switch name of the switch
|
|
# @param int _vlan the vlan number (0 to turn vlan off)
|
|
#
|
|
switch::vlan(){
|
|
local _switch="$1"
|
|
local _vlan="$2"
|
|
local _id _type
|
|
|
|
[ -z "${_switch}" -o -z "${_vlan}" ] && util::usage
|
|
|
|
switch::id "_id" "${_switch}"
|
|
switch::type "_type" "${_switch}"
|
|
[ -z "${_id}" ] && util::err "unable to locate specified virtual switch"
|
|
|
|
echo "${_vlan}" | egrep -qs '^[0-9]{1,4}$'
|
|
[ $? -eq 0 ] || util::err "invalid vlan number"
|
|
[ ${_vlan} -ge 4095 ] && util::err "invalid vlan number"
|
|
|
|
case "${_type}" in
|
|
standard) switch::standard::vlan "${_switch}" "${_vlan}" ;;
|
|
manual) switch::manual::vlan "${_switch}" "${_vlan}" ;;
|
|
netgraph) switch::netgraph::vlan "${_switch}" "${_vlan}" ;;
|
|
vale) switch::vale::vlan "${_switch}" "${_vlan}" ;;
|
|
vxlan) switch::vxlan::vlan "${_switch}" "${_vlan}" ;;
|
|
*) util::err "unable to configure switch of unknown type" ;;
|
|
esac
|
|
}
|
|
|
|
# enable or diable private flag on a switch
|
|
# note that we don't update existing interfaces; this
|
|
# makes things easy for us and any guests booted after
|
|
# will get the new setting
|
|
#
|
|
# @param string _switch the switch to update
|
|
# @param string _priv on,yes|off,no
|
|
#
|
|
switch::private(){
|
|
local _switch="$1"
|
|
local _priv="$2"
|
|
local _type
|
|
|
|
# try to get switch type
|
|
[ -z "${_switch}" -o -z "${_priv}" ] && util::usage
|
|
switch::type "_type" "${_switch}" || util::err "specified switch does not appear to be valid"
|
|
|
|
case "${_type}" in
|
|
standard|manual|vxlan)
|
|
if util::yesno "${_priv}"; then
|
|
config::core::set "private_${_switch}" "yes"
|
|
else
|
|
config::core::set "private_${_switch}" "no"
|
|
fi
|
|
;;
|
|
netgraph)
|
|
util::err "unable to configure private mode on netgraph switches"
|
|
;;
|
|
vale)
|
|
util::err "unable to configure private mode on vale switches"
|
|
;;
|
|
*)
|
|
util::err "unable to configure switch of unknown type"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# enable or disable nat functionality on a virtual switch
|
|
#
|
|
# @param string _switch name of the switch
|
|
# @param string _nat on|off
|
|
#
|
|
switch::nat(){
|
|
util::warn "internal nat support is currently disabled"
|
|
util::warn "please add an address to the virtual switch and configure your firewall for NAT manually"
|
|
}
|
|
|
|
# set or remove ip address from a virtual switch
|
|
#
|
|
# @param string _switch name of the switch
|
|
# @param string _addr the ip address to add (or "none" to remove
|
|
#
|
|
switch::address(){
|
|
local _switch="$1"
|
|
local _addr="$2"
|
|
local _id _type
|
|
|
|
[ -z "${_switch}" ] && util::usage
|
|
|
|
switch::id "_id" "${_switch}"
|
|
switch::type "_type" "${_switch}"
|
|
[ -z "${_id}" ] && util::err "unable to locate specified virtual switch"
|
|
|
|
# check address
|
|
if [ -n "${_addr}" ] && [ "${_addr}" != "none" ]; then
|
|
echo "${_addr}" | egrep -qs '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}$'
|
|
[ $? -eq 0 ] || util::err "address must be supplied in CIDR notation (a.b.c.d/prefix-len)"
|
|
fi
|
|
|
|
case "${_type}" in
|
|
standard) switch::standard::address "${_switch}" "${_addr}" ;;
|
|
manual) ;&
|
|
netgraph) ;&
|
|
vale) ;&
|
|
vxlan) util::err "feature not currently supported on switches of this type" ;;
|
|
*) util::err "unable to configure switch of unknown type" ;;
|
|
esac
|
|
}
|
|
|
|
# return the type for a switch
|
|
#
|
|
# @param string _var variable to put type into
|
|
# @param string _switch the switch name
|
|
#
|
|
switch::type(){
|
|
local _var="$1"
|
|
local _switch="$2"
|
|
|
|
[ -z "${_switch}" ] && return 1
|
|
config::core::get "${_var}" "type_${_switch}" "standard"
|
|
}
|
|
|
|
# check if a switch is configured for private members
|
|
#
|
|
# @param string _switch switch name
|
|
# @return succes (0) if it's private
|
|
#
|
|
switch::is_private(){
|
|
local _switch="$1"
|
|
local _priv
|
|
|
|
config::core::get "_priv" "private_${_switch}"
|
|
util::yesno "${_priv}"
|
|
}
|
|
|
|
# get the bridge id for a virtual switch
|
|
#
|
|
# @param string _var variable to put name into
|
|
# @param string _switch the name of the switch
|
|
#
|
|
switch::id(){
|
|
local _var="$1"
|
|
local _switch="$2"
|
|
local _type
|
|
|
|
[ -z "${_switch}" ] && return 1
|
|
|
|
# get switch type
|
|
config::core::get "_type" "type_${_switch}"
|
|
|
|
case "${_type}" in
|
|
vale) switch::vale::id "${_var}" "${_switch}" ;;
|
|
netgraph) switch::netgraph::id "${_var}" "${_switch}" ;;
|
|
manual) switch::manual::id "${_var}" "${_switch}" ;;
|
|
*) switch::standard::id "${_var}" "${_switch}" ;;
|
|
esac
|
|
}
|
|
|
|
# get a virt interface id for a port/switch
|
|
#
|
|
# @param string _var variable name to put result into
|
|
# @param string _switch switch name to get id for
|
|
#
|
|
switch::__viid(){
|
|
local _hash=$(md5 -qs "${2}" | cut -c1-5)
|
|
setvar "$1" "viid-${_hash}@"
|
|
}
|
|
|
|
# retrieve interface name, given a switch name
|
|
# we convert to viid then look for the matching group
|
|
#
|
|
# @param string _var variable to put interface name into
|
|
# @param string _switch the switch name
|
|
#
|
|
switch::find(){
|
|
local _var="$1"
|
|
local _switch="$2"
|
|
local _viid _name
|
|
|
|
switch::__viid "_viid" "${_switch}"
|
|
_name=$(ifconfig -g "${_viid}" 2>/dev/null)
|
|
[ -n "${_name}" ] && setvar "${_var}" "${_name}"
|
|
}
|
|
|
|
# mark an interface with a unique viid
|
|
# i say unique, its 5 chars from an md5 hash which
|
|
# should be enough for half a dozen switches
|
|
#
|
|
# @parem string _switch switch name
|
|
# @param string _iface interface to mark
|
|
#
|
|
switch::set_viid(){
|
|
local _switch="$1"
|
|
local _iface="$2"
|
|
local _viid
|
|
|
|
switch::__viid "_viid" "${_switch}"
|
|
ifconfig "${_iface}" group "${_viid}" >/dev/null 2>&1
|
|
}
|