bug 7722: open vswitch -

fix a race condition, create tunnel sync
correct drop flow, this fix a flooding case which may cause openvswitch hang in kernel
This commit is contained in:
Frank 2011-01-13 13:51:22 -08:00
parent 80f6db937f
commit 488dd424aa
3 changed files with 62 additions and 34 deletions

View File

@ -369,6 +369,24 @@ def get_interface_on_port(nameOruuid):
return str.split(",") return str.split(",")
return None return None
def get_gre_ports(bridge):
portUuids = get_ports_on_bridge(bridge)
if portUuids == None:
pr("WARNING:No ports on bridge %s" % bridge)
return []
OfPorts = []
for i in portUuids:
iface = get_filed_of_port(i, "interfaces")
iface = strip(iface, "both")
type = get_field_of_interface(iface, "type")
if type == 'gre':
port = get_field_of_interface(iface, "ofport")
if port != '[]':
OfPorts.append(port)
return OfPorts
def get_ofports_by_tag(bridge, tag): def get_ofports_by_tag(bridge, tag):
portUuids = get_ports_on_bridge(bridge) portUuids = get_ports_on_bridge(bridge)
if portUuids == None: if portUuids == None:
@ -395,11 +413,16 @@ def format_flow(inPort, vlan, mac, outPut):
priority=10000 actions=strip_vlan,output:%s" % (inPort, vlan, mac, outPut) priority=10000 actions=strip_vlan,output:%s" % (inPort, vlan, mac, outPut)
return flow return flow
def format_drop_flow(inPort, vlan): def format_drop_flow(inPort):
flow = "in_port=%s dl_vlan=%s priority=0 idle_timeout=0 hard_timeout=0 \ flow = "in_port=%s priority=1000 idle_timeout=0 hard_timeout=0 \
actions=drop" % (inPort, vlan) actions=drop" % inPort
return flow return flow
def add_drop_flow(bridge, inPorts):
for i in inPorts:
flow = format_drop_flow(i)
add_flow(bridge, flow)
def del_flow(bridge, mac): def del_flow(bridge, mac):
param = "dl_dst=%s" % mac param = "dl_dst=%s" % mac
flow = ["ovs-ofctl del-flows %s" % bridge, '"%s"' % param] flow = ["ovs-ofctl del-flows %s" % bridge, '"%s"' % param]
@ -477,9 +500,6 @@ def create_flow (bridge, vifName, mac, vlans):
for v in vlans.split(","): for v in vlans.split(","):
try: try:
(vlan, inPort) = v.split(":") (vlan, inPort) = v.split(":")
flow = format_drop_flow(inPort, vlan)
add_flow(bridge, flow)
flow = format_flow(inPort, vlan, mac, output) flow = format_flow(inPort, vlan, mac, output)
add_flow(bridge, flow) add_flow(bridge, flow)
except Exception, e: except Exception, e:
@ -490,6 +510,10 @@ def create_flow (bridge, vifName, mac, vlans):
flow = format_normal_flow() flow = format_normal_flow()
add_flow(bridge, flow) add_flow(bridge, flow)
inports = get_gre_ports(bridge)
for i in inports:
add_drop_flow(bridge, i)
return errors["SUCCESS"] return errors["SUCCESS"]
######################## End Flow creation utils ########################## ######################## End Flow creation utils ##########################
@ -669,7 +693,7 @@ def ovs_get_domid_vifrs_hostuuid(session, vmName):
try: try:
vm = session.xenapi.VM.get_by_name_label(vmName) vm = session.xenapi.VM.get_by_name_label(vmName)
if len(vm) != 1: if len(vm) != 1:
return 'NO_VM' return (-1, [], "-1")
vm_rec = session.xenapi.VM.get_record(vm[0]) vm_rec = session.xenapi.VM.get_record(vm[0])
vm_vifs = vm_rec.get('VIFs') vm_vifs = vm_rec.get('VIFs')
vifrs = [] vifrs = []

View File

@ -50,30 +50,7 @@ public class OvsListener implements Listener {
Set<Long> failedFlowVms = new HashSet<Long>(); Set<Long> failedFlowVms = new HashSet<Long>();
try { try {
for (Answer ans : answers) { for (Answer ans : answers) {
if (ans instanceof OvsCreateGreTunnelAnswer) { if (ans instanceof OvsSetTagAndFlowAnswer) {
OvsCreateGreTunnelAnswer r = (OvsCreateGreTunnelAnswer) ans;
String s = String
.format("(hostIP:%1$s, remoteIP:%2$s, bridge:%3$s, greKey:%4$s)",
r.getHostIp(), r.getRemoteIp(),
r.getBridge(), r.getKey());
if (!r.getResult()) {
s_logger.warn("Create GRE tunnel failed due to "
+ r.getDetails() + s);
} else {
GreTunnelVO tunnel = _tunnelDao.getByFromAndTo(
r.getFrom(), r.getTo());
if (tunnel == null) {
throw new GreTunnelException(
"No record matches from = " + r.getFrom() + " to = " + r.getTo());
} else {
tunnel.setInPort(r.getPort());
_tunnelDao.update(tunnel.getId(), tunnel);
s_logger.info("Create GRE tunnel success" + s
+ " from " + r.getFrom() + " to "
+ r.getTo() + " inport=" + r.getPort());
}
}
} else if (ans instanceof OvsSetTagAndFlowAnswer) {
OvsSetTagAndFlowAnswer r = (OvsSetTagAndFlowAnswer) ans; OvsSetTagAndFlowAnswer r = (OvsSetTagAndFlowAnswer) ans;
if (!r.getResult()) { if (!r.getResult()) {
s_logger.warn("Failed to set flow for VM " s_logger.warn("Failed to set flow for VM "

View File

@ -17,6 +17,7 @@ import javax.persistence.EntityExistsException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager; import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.manager.Commands; import com.cloud.agent.manager.Commands;
import com.cloud.configuration.Config; import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.configuration.dao.ConfigurationDao;
@ -294,6 +295,31 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
return target.getVlan(); return target.getVlan();
} }
private void handleCreateTunnelAnswer(Answer[] answers) throws GreTunnelException {
OvsCreateGreTunnelAnswer r = (OvsCreateGreTunnelAnswer) answers[0];
String s = String.format(
"(hostIP:%1$s, remoteIP:%2$s, bridge:%3$s, greKey:%4$s)",
r.getHostIp(), r.getRemoteIp(), r.getBridge(), r.getKey());
if (!r.getResult()) {
s_logger.warn("Create GRE tunnel failed due to " + r.getDetails()
+ s);
} else {
GreTunnelVO tunnel = _tunnelDao.getByFromAndTo(r.getFrom(), r.getTo());
if (tunnel == null) {
throw new GreTunnelException("No record matches from = "
+ r.getFrom() + " to = " + r.getTo());
} else {
tunnel.setInPort(r.getPort());
_tunnelDao.update(tunnel.getId(), tunnel);
s_logger.info("Create GRE tunnel success" + s + " from "
+ r.getFrom() + " to " + r.getTo() + " inport="
+ r.getPort());
}
}
}
@DB @DB
protected void CheckAndCreateTunnel(VMInstanceVO instance, protected void CheckAndCreateTunnel(VMInstanceVO instance,
DeployDestination dest) throws GreTunnelException { DeployDestination dest) throws GreTunnelException {
@ -309,7 +335,6 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
final Transaction txn = Transaction.currentTxn(); final Transaction txn = Transaction.currentTxn();
long hostId = dest.getHost().getId(); long hostId = dest.getHost().getId();
long accountId = instance.getAccountId(); long accountId = instance.getAccountId();
//TODO: considerate router?
List<UserVmVO>vms = _userVmDao.listByAccountId(accountId); List<UserVmVO>vms = _userVmDao.listByAccountId(accountId);
DomainRouterVO router = _routerDao.findBy(accountId, instance.getDataCenterId()); DomainRouterVO router = _routerDao.findBy(accountId, instance.getDataCenterId());
List<VMInstanceVO>ins = new ArrayList<VMInstanceVO>(); List<VMInstanceVO>ins = new ArrayList<VMInstanceVO>();
@ -360,14 +385,16 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
new OvsCreateGreTunnelCommand( new OvsCreateGreTunnelCommand(
rHost.getPrivateIpAddress(), "1", hostId, rHost.getPrivateIpAddress(), "1", hostId,
i.longValue())); i.longValue()));
_agentMgr.send(hostId, cmds , _ovsListener);
s_logger.debug("Ask host " + hostId + " to create gre tunnel to " + i.longValue()); s_logger.debug("Ask host " + hostId + " to create gre tunnel to " + i.longValue());
Answer[] answers = _agentMgr.send(hostId, cmds);
handleCreateTunnelAnswer(answers);
} }
for (Long i : fromHostIds) { for (Long i : fromHostIds) {
Commands cmd2s = new Commands(new OvsCreateGreTunnelCommand(myIp, "1", i.longValue(), hostId)); Commands cmd2s = new Commands(new OvsCreateGreTunnelCommand(myIp, "1", i.longValue(), hostId));
_agentMgr.send(i.longValue(), cmd2s , _ovsListener);
s_logger.debug("Ask host " + i.longValue() + " to create gre tunnel to " + hostId); s_logger.debug("Ask host " + i.longValue() + " to create gre tunnel to " + hostId);
Answer[] answers = _agentMgr.send(i.longValue(), cmd2s);
handleCreateTunnelAnswer(answers);
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();