mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
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:
parent
80f6db937f
commit
488dd424aa
@ -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 = []
|
||||||
|
|||||||
@ -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 "
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user