From 488dd424aaad50a6cd761d29e2506bf65aaf4b8c Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 13 Jan 2011 13:51:22 -0800 Subject: [PATCH] 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 --- scripts/vm/hypervisor/xenserver/ovsgre | 38 +++++++++++++++---- .../com/cloud/network/ovs/OvsListener.java | 25 +----------- .../network/ovs/OvsNetworkManagerImpl.java | 33 ++++++++++++++-- 3 files changed, 62 insertions(+), 34 deletions(-) diff --git a/scripts/vm/hypervisor/xenserver/ovsgre b/scripts/vm/hypervisor/xenserver/ovsgre index 99804ae63df..44032a7dfea 100755 --- a/scripts/vm/hypervisor/xenserver/ovsgre +++ b/scripts/vm/hypervisor/xenserver/ovsgre @@ -369,6 +369,24 @@ def get_interface_on_port(nameOruuid): return str.split(",") 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): portUuids = get_ports_on_bridge(bridge) 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) return flow -def format_drop_flow(inPort, vlan): - flow = "in_port=%s dl_vlan=%s priority=0 idle_timeout=0 hard_timeout=0 \ - actions=drop" % (inPort, vlan) +def format_drop_flow(inPort): + flow = "in_port=%s priority=1000 idle_timeout=0 hard_timeout=0 \ + actions=drop" % inPort 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): param = "dl_dst=%s" % mac 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(","): try: (vlan, inPort) = v.split(":") - flow = format_drop_flow(inPort, vlan) - add_flow(bridge, flow) - flow = format_flow(inPort, vlan, mac, output) add_flow(bridge, flow) except Exception, e: @@ -490,6 +510,10 @@ def create_flow (bridge, vifName, mac, vlans): flow = format_normal_flow() add_flow(bridge, flow) + inports = get_gre_ports(bridge) + for i in inports: + add_drop_flow(bridge, i) + return errors["SUCCESS"] ######################## End Flow creation utils ########################## @@ -669,7 +693,7 @@ def ovs_get_domid_vifrs_hostuuid(session, vmName): try: vm = session.xenapi.VM.get_by_name_label(vmName) if len(vm) != 1: - return 'NO_VM' + return (-1, [], "-1") vm_rec = session.xenapi.VM.get_record(vm[0]) vm_vifs = vm_rec.get('VIFs') vifrs = [] diff --git a/server/src/com/cloud/network/ovs/OvsListener.java b/server/src/com/cloud/network/ovs/OvsListener.java index 213edaf7b5f..d66678e9dc7 100644 --- a/server/src/com/cloud/network/ovs/OvsListener.java +++ b/server/src/com/cloud/network/ovs/OvsListener.java @@ -50,30 +50,7 @@ public class OvsListener implements Listener { Set failedFlowVms = new HashSet(); try { for (Answer ans : answers) { - if (ans instanceof OvsCreateGreTunnelAnswer) { - 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) { + if (ans instanceof OvsSetTagAndFlowAnswer) { OvsSetTagAndFlowAnswer r = (OvsSetTagAndFlowAnswer) ans; if (!r.getResult()) { s_logger.warn("Failed to set flow for VM " diff --git a/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java b/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java index da5dd3a6641..93ac42d5b33 100644 --- a/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java +++ b/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java @@ -17,6 +17,7 @@ import javax.persistence.EntityExistsException; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; import com.cloud.agent.manager.Commands; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; @@ -294,6 +295,31 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { 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 protected void CheckAndCreateTunnel(VMInstanceVO instance, DeployDestination dest) throws GreTunnelException { @@ -309,7 +335,6 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { final Transaction txn = Transaction.currentTxn(); long hostId = dest.getHost().getId(); long accountId = instance.getAccountId(); - //TODO: considerate router? Listvms = _userVmDao.listByAccountId(accountId); DomainRouterVO router = _routerDao.findBy(accountId, instance.getDataCenterId()); Listins = new ArrayList(); @@ -360,14 +385,16 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { new OvsCreateGreTunnelCommand( rHost.getPrivateIpAddress(), "1", hostId, i.longValue())); - _agentMgr.send(hostId, cmds , _ovsListener); 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) { 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); + Answer[] answers = _agentMgr.send(i.longValue(), cmd2s); + handleCreateTunnelAnswer(answers); } } catch (Exception e) { e.printStackTrace();