mirror of
https://github.com/churchers/vm-bhyve.git
synced 2025-12-11 09:20:17 +01:00
205 lines
6.6 KiB
Bash
205 lines
6.6 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.
|
|
|
|
# create a vxlan switch
|
|
# we create a bridge and then add the vxlan interface to it
|
|
#
|
|
# @param string _name name of the switch
|
|
#
|
|
switch::vxlan::init(){
|
|
local _name="$1"
|
|
local _id _vlan _if _maddr _addr _ifconf
|
|
|
|
# see if the bridge already exists
|
|
switch::standard::id "_id" "${_name}" && return 0
|
|
|
|
# need a vlan id and interface
|
|
config::core::get "_vlan" "vlan_${_name}"
|
|
config::core::get "_if" "ports_${_name}"
|
|
[ -z "${_vlan}" -o -z "${_if}" ] && return 1
|
|
|
|
# get local address for this interface
|
|
_local=$(ifconfig ${_if} | grep "inet " | cut -d" " -f 2)
|
|
[ -z "${_local}" ] && return 1
|
|
|
|
# come up with an ip address for multicast data
|
|
switch::vxlan::__multicast "_maddr" "${_name}"
|
|
|
|
# create the vxlan interface
|
|
ifconfig "vxlan${_vlan}" create vxlanid "${_vlan}" vxlanlocal "${_local}" vxlangroup "${_maddr}" \
|
|
vxlandev "${_if}" descr "vm-vxlan/${_switch}" group vm-vlan up >/dev/null 2>&1
|
|
[ $? -eq 0 ] || return 1
|
|
|
|
# get the length of the switch name
|
|
# it's useful for other utilities to use switch name as interface name
|
|
# as it's static. can't do that if it's > 12 chars
|
|
_len=$(echo -n "${_name}" | wc -m)
|
|
|
|
if [ ${_len} -le 12 ]; then
|
|
_ifconf="name vm-${_name}"
|
|
else
|
|
_ifconf="descr vm/${_name}"
|
|
fi
|
|
|
|
# create a bridge for this switch
|
|
_id=$(ifconfig bridge create ${_ifconf} group vm-switch up 2>/dev/null)
|
|
[ $? -eq 0 ] || util::err "failed to create bridge interface for switch ${_name}"
|
|
|
|
switch::set_viid "${_name}" "${_id}"
|
|
|
|
# randomise mac if feature is available
|
|
[ ${VERSION_BSD} -ge 1102000 ] && ifconfig "${_id}" link random
|
|
|
|
# bridge vxlan to our guest switch
|
|
# static route traffic for this multicast address via our specified interface
|
|
ifconfig "${_id}" addm "vxlan${_vlan}"
|
|
route add -net ${_maddr}/32 -iface ${_if} >/dev/null 2>&1
|
|
|
|
# custom address for bridge?
|
|
config::core::get "_addr" "addr_${_name}"
|
|
[ -n "${_addr}" ] && ifconfig "${_id}" inet ${_addr}
|
|
}
|
|
|
|
# show the configuration details for a vxlan switch
|
|
#
|
|
# @param string _name the switch name
|
|
# @param string _format output format
|
|
#
|
|
switch::vxlan::show(){
|
|
local _name="$1"
|
|
local _format="$2"
|
|
local _id _vlan _port _addr _priv
|
|
|
|
switch::standard::id "_id" "${_name}"
|
|
config::core::get "_vlan" "vlan_${_name}"
|
|
config::core::get "_port" "ports_${_name}"
|
|
config::core::get "_addr" "addr_${_name}"
|
|
config::core::get "_priv" "private_${_name}" "no"
|
|
|
|
printf "${_format}" "${_name}" "vxlan" "${_id:--}" "${_addr:--}" "${_priv}" "n/a" "${_vlan}" "${_port}"
|
|
}
|
|
|
|
# create a vxlan switch
|
|
#
|
|
switch::vxlan::create(){
|
|
|
|
# we must have an interface and vlan to use
|
|
[ -z "${_if}" -o -z "${_vlan}" ] && util::err "vxlan switches must be created with an interface and vlan id specified"
|
|
|
|
# store configuration
|
|
config::core::set "switch_list" "${_switch}" "1"
|
|
config::core::set "type_${_switch}" "vxlan"
|
|
config::core::set "vlan_${_switch}" "${_vlan}"
|
|
config::core::set "ports_${_switch}" "${_if}"
|
|
|
|
[ -n "${_addr}" ] && config::core::set "addr_${_switch}" "${_addr}"
|
|
[ -n "${_priv}" ] && config::core::set "private_${_switch}" "${_priv}"
|
|
|
|
config::core::load
|
|
switch::vxlan::init "${_switch}"
|
|
}
|
|
|
|
# destroy a vxlan switch
|
|
#
|
|
# @param string _switch the switch to remove
|
|
#
|
|
switch::vxlan::remove(){
|
|
local _switch="$1"
|
|
local _id _vlan _maddr
|
|
|
|
# try to get guest bridge and vxlan id
|
|
switch::standard::id "_id" "${_switch}"
|
|
[ $? -eq 0 ] || return 1
|
|
|
|
config::core::get "_vlan" "vlan_${_switch}"
|
|
[ -z "${_vlan}" ] && return 1
|
|
|
|
# get the multicast address we used for this switch
|
|
# and try to remove any route we may have added
|
|
switch::vxlan::__multicast "_maddr" "${_switch}"
|
|
route del -net "${_maddr}/32" >/dev/null 2>&1
|
|
|
|
# destroy the guest bridge
|
|
ifconfig ${_id} destroy >/dev/null 2>&1
|
|
[ $? -eq 0 ] || return 1
|
|
|
|
# destroy the vxlan
|
|
ifconfig "vxlan${_vlan}" destroy >/dev/null 2>&1
|
|
}
|
|
|
|
# add a new interface to this switch
|
|
# we only allow a single physical interface for
|
|
# vxlan switches. this must be set at creation time
|
|
# so this just reports an error
|
|
#
|
|
# @param string _switch name of the vxlan switch
|
|
# @param string _if the interface to add
|
|
#
|
|
switch::vxlan::add_member(){
|
|
util::err "vxlan interface must be configured at creation time"
|
|
}
|
|
|
|
# remove an interface from a switch
|
|
# we don't support this here
|
|
#
|
|
# @param string _switch name of the switch
|
|
# @param string _if the interface to remove
|
|
#
|
|
switch::vxlan::remove_member(){
|
|
util::err "vxlan interface must be configured at creation time"
|
|
}
|
|
|
|
# set vlan id
|
|
#
|
|
# @param string _switch name of switch
|
|
# @param int _vlan vlan id to set
|
|
#
|
|
switch::vxlan::vlan(){
|
|
util::err "vxlan id can only be set at creation time"
|
|
}
|
|
|
|
# get the multicast address for a vxlan switch
|
|
#
|
|
# @param string _var variable to put address into
|
|
# @param string _switch the switch name
|
|
#
|
|
switch::vxlan::__multicast(){
|
|
local _var="$1"
|
|
local _switch="$2"
|
|
local _hash _l_addr _octet _pos
|
|
|
|
# come up with an ip address for multicast data
|
|
_hash=$(md5 -qs "${_switch}")
|
|
_l_addr="239"
|
|
|
|
for _pos in 1-2 3-4 5-6; do
|
|
_octet=$(printf ".%d" "0x`echo "${_hash}"| cut -c ${_pos}`")
|
|
_l_addr="${_l_addr}${_octet}"
|
|
done
|
|
|
|
setvar "${_var}" "${_l_addr}"
|
|
}
|