fix kvm traffic labels (guest traffic types on multiple networks don't

work)

Cloudstack seems to let you create guest traffic types on multiple
physical networks. However, when I try this with KVM I end up always
bridging to whatever device is used for guest.network.device. This pulls
the traffic label (NicTO.getName()) and uses that bridge to ensure that
we get on the correct physical network, rather than just always using
the guest.network.device.

This also changes the bridge naming scheme from cloudVirBr + vlanid to
br + physicalinterface + "-" + vlanid. This is because we should be able
to support the same vlan numbers per physical network, and the previous
bridge name would not support this and collide.

Signed-off-by: Edison Su <sudison@gmail.com>
This commit is contained in:
Marcus Sorensen 2012-09-26 17:14:57 -07:00 committed by Edison Su
parent de13b097ae
commit 915babd970
3 changed files with 79 additions and 54 deletions

View File

@ -85,11 +85,18 @@ public class BridgeVifDriver extends VifDriverBase {
URI broadcastUri = nic.getBroadcastUri();
vlanId = broadcastUri.getHost();
}
String trafficLabel = nic.getName();
if (nic.getType() == Networks.TrafficType.Guest) {
if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan
&& !vlanId.equalsIgnoreCase("untagged")) {
String brName = createVlanBr(vlanId, _pifs.get("private"));
intf.defBridgeNet(brName, null, nic.getMac(), getGuestNicModel(guestOsType));
if(trafficLabel != null || !trafficLabel.isEmpty()) {
s_logger.debug("creating a vlan dev and bridge for guest traffic per traffic label " + trafficLabel);
String brName = createVlanBr(vlanId, _pifs.get(trafficLabel));
intf.defBridgeNet(brName, null, nic.getMac(), getGuestNicModel(guestOsType));
} else {
String brName = createVlanBr(vlanId, _pifs.get("private"));
intf.defBridgeNet(brName, null, nic.getMac(), getGuestNicModel(guestOsType));
}
} else {
intf.defBridgeNet(_bridges.get("guest"), null, nic.getMac(), getGuestNicModel(guestOsType));
}
@ -100,8 +107,14 @@ public class BridgeVifDriver extends VifDriverBase {
} else if (nic.getType() == Networks.TrafficType.Public) {
if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan
&& !vlanId.equalsIgnoreCase("untagged")) {
String brName = createVlanBr(vlanId, _pifs.get("public"));
intf.defBridgeNet(brName, null, nic.getMac(), getGuestNicModel(guestOsType));
if(trafficLabel != null || !trafficLabel.isEmpty()){
s_logger.debug("creating a vlan dev and bridge for public traffic per traffic label " + trafficLabel);
String brName = createVlanBr(vlanId, _pifs.get(trafficLabel));
intf.defBridgeNet(brName, null, nic.getMac(), getGuestNicModel(guestOsType));
} else {
String brName = createVlanBr(vlanId, _pifs.get("public"));
intf.defBridgeNet(brName, null, nic.getMac(), getGuestNicModel(guestOsType));
}
} else {
intf.defBridgeNet(_bridges.get("public"), null, nic.getMac(), getGuestNicModel(guestOsType));
}
@ -120,22 +133,32 @@ public class BridgeVifDriver extends VifDriverBase {
// Nothing needed as libvirt cleans up tap interface from bridge.
}
private String setVnetBrName(String vnetId) {
return "cloudVirBr" + vnetId;
private String setVnetBrName(String pifName, String vnetId) {
String brName = "br" + pifName + "-"+ vnetId;
String oldStyleBrName = "cloudVirBr" + vnetId;
String cmdout = Script.runSimpleBashScript("brctl show | grep " + oldStyleBrName);
if (cmdout != null && cmdout.contains(oldStyleBrName)) {
s_logger.info("Using old style bridge name for vlan " + vnetId + " because existing bridge " + oldStyleBrName + " was found");
brName = oldStyleBrName;
}
return brName;
}
private String createVlanBr(String vlanId, String nic)
throws InternalErrorException {
String brName = setVnetBrName(vlanId);
createVnet(vlanId, nic);
String brName = setVnetBrName(nic, vlanId);
createVnet(vlanId, nic, brName);
return brName;
}
private void createVnet(String vnetId, String pif)
private void createVnet(String vnetId, String pif, String brName)
throws InternalErrorException {
final Script command = new Script(_modifyVlanPath, _timeout, s_logger);
command.add("-v", vnetId);
command.add("-p", pif);
command.add("-b", brName);
command.add("-o", "add");
final String result = command.execute();

View File

@ -44,6 +44,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@ -777,32 +779,32 @@ public class LibvirtComputingResource extends ServerResourceBase implements
}
private void getPifs() {
/* get pifs from bridge */
String pubPif = null;
String privPif = null;
String vlan = null;
if (_publicBridgeName != null) {
pubPif = Script.runSimpleBashScript("brctl show | grep "
+ _publicBridgeName + " | awk '{print $4}'");
vlan = Script.runSimpleBashScript("ls /proc/net/vlan/" + pubPif);
if (vlan != null && !vlan.isEmpty()) {
pubPif = Script
.runSimpleBashScript("grep ^Device\\: /proc/net/vlan/"
+ pubPif + " | awk {'print $2'}");
/* gather all available bridges and find their pifs, so that we can match them against traffic labels later */
String cmdout = Script.runSimpleBashScript("brctl show | tail -n +2 | grep -v \"^\\s\"|awk '{print $1}'|sed '{:q;N;s/\\n/%/g;t q}'");
s_logger.debug("cmdout was " + cmdout);
List<String> bridges = Arrays.asList(cmdout.split("%"));
for (String bridge : bridges) {
s_logger.debug("looking for pif for bridge " + bridge);
String pif = getPif(bridge);
if(_publicBridgeName != null && bridge.equals(_publicBridgeName)){
_pifs.put("public", pif);
} else if (_guestBridgeName != null) {
_pifs.put("private", pif);
}
_pifs.put(bridge, pif);
}
if (_guestBridgeName != null) {
privPif = Script.runSimpleBashScript("brctl show | grep "
+ _guestBridgeName + " | awk '{print $4}'");
vlan = Script.runSimpleBashScript("ls /proc/net/vlan/" + privPif);
if (vlan != null && !vlan.isEmpty()) {
privPif = Script
.runSimpleBashScript("grep ^Device\\: /proc/net/vlan/"
+ privPif + " | awk {'print $2'}");
}
s_logger.debug("done looking for pifs, no more bridges");
}
private String getPif(String bridge) {
String pif = Script.runSimpleBashScript("brctl show | grep " + bridge + " | awk '{print $4}'");
String vlan = Script.runSimpleBashScript("ls /proc/net/vlan/" + pif);
if (vlan != null && !vlan.isEmpty()) {
pif = Script.runSimpleBashScript("grep ^Device\\: /proc/net/vlan/" + pif + " | awk {'print $2'}");
}
_pifs.put("private", privPif);
_pifs.put("public", pubPif);
return pif;
}
private boolean checkNetwork(String networkName) {
@ -3914,7 +3916,18 @@ public class LibvirtComputingResource extends ServerResourceBase implements
}
private String getVnetIdFromBrName(String vnetBrName) {
return vnetBrName.replaceAll("cloudVirBr", "");
if (vnetBrName.contains("cloudVirBr")) {
return vnetBrName.replaceAll("cloudVirBr", "");
} else {
Pattern r = Pattern.compile("-(\\d+)$");
Matcher m = r.matcher(vnetBrName);
if(m.group(1) != null || !m.group(1).isEmpty()) {
return m.group(1);
} else {
s_logger.debug("unable to get a vlan ID from name " + vnetBrName);
return "";
}
}
}
private void cleanupVMNetworks(Connect conn, List<InterfaceDef> nics) {

View File

@ -22,15 +22,14 @@
# set -x
usage() {
printf "Usage: %s: -o <op>(add | delete) -v <vlan id> -p <pif> \n"
printf "Usage: %s: -o <op>(add | delete) -v <vlan id> -p <pif> -b <bridge name>\n"
}
VIRBR=cloudVirBr
addVlan() {
local vlanId=$1
local pif=$2
local vlanDev=$pif.$vlanId
local vlanBr=$VIRBR$vlanId
local vlanBr=$3
vconfig set_name_type DEV_PLUS_VID_NO_PAD
@ -99,7 +98,7 @@ deleteVlan() {
local vlanId=$1
local pif=$2
local vlanDev=$pif.$vlanId
local vlanBr=$VIRBR$vlanId
local vlanBr=$3
vconfig rem $vlanDev > /dev/null
@ -132,7 +131,7 @@ op=
vlanId=
option=$@
while getopts 'o:v:p:' OPTION
while getopts 'o:v:p:b:' OPTION
do
case $OPTION in
o) oflag=1
@ -144,6 +143,9 @@ do
p) pflag=1
pif="$OPTARG"
;;
b) bflag=1
brName="$OPTARG"
;;
?) usage
exit 2
;;
@ -151,7 +153,7 @@ do
done
# Check that all arguments were passed in
if [ "$oflag$vflag$pflag" != "111" ]
if [ "$oflag$vflag$pflag$bflag" != "1111" ]
then
usage
exit 2
@ -167,7 +169,7 @@ fi
if [ "$op" == "add" ]
then
# Add the vlan
addVlan $vlanId $pif
addVlan $vlanId $pif $brName
# If the add fails then return failure
if [ $? -gt 0 ]
@ -178,22 +180,9 @@ else
if [ "$op" == "delete" ]
then
# Delete the vlan
deleteVlan $vlanId $pif
deleteVlan $vlanId $pif $brName
# Always exit with success
exit 0
fi
fi