Return-Path: X-Original-To: apmail-cloudstack-commits-archive@www.apache.org Delivered-To: apmail-cloudstack-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 85E49FC7F for ; Fri, 25 Apr 2014 20:27:07 +0000 (UTC) Received: (qmail 41877 invoked by uid 500); 25 Apr 2014 20:26:51 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 41628 invoked by uid 500); 25 Apr 2014 20:26:44 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 41590 invoked by uid 99); 25 Apr 2014 20:26:42 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 25 Apr 2014 20:26:42 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id A67D995241E; Fri, 25 Apr 2014 20:26:41 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: dahn@apache.org To: commits@cloudstack.apache.org Date: Fri, 25 Apr 2014 20:26:53 -0000 Message-Id: <53ee761778b942da89fbaf07a0e2efd0@git.apache.org> In-Reply-To: <8f801e1450644e408a6d04f1d7ba539a@git.apache.org> References: <8f801e1450644e408a6d04f1d7ba539a@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [13/16] git commit: updated refs/heads/4.4 to 6b342ff CLOUDSTACK-6507: ensure sequence numbers are honoured while processing OvsVpcPhysicalTopologyConfigCommand and OvsVpcRoutingPolicyConfigCommand fix ensures only latest updates are applied (new openflow rules) to the bidge enabled for distributed routing. Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/cbe32683 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/cbe32683 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/cbe32683 Branch: refs/heads/4.4 Commit: cbe326838d77c0f4d22010ce9419a2854ad07e82 Parents: 2f96d43 Author: Murali Reddy Authored: Fri Apr 25 14:44:43 2014 +0530 Committer: Daan Hoogland Committed: Fri Apr 25 22:07:37 2014 +0200 ---------------------------------------------------------------------- .../cloud/network/ovs/OvsTunnelManagerImpl.java | 2 +- .../xenserver/cloudstack_pluginlib.py | 81 +++++++++++++++++++- .../vm/hypervisor/xenserver/ovs-vif-flows.py | 80 +++---------------- scripts/vm/hypervisor/xenserver/ovstunnel | 37 +++++++-- 4 files changed, 123 insertions(+), 77 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cbe32683/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java index c755d72..6fd7d6d 100644 --- a/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java +++ b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java @@ -912,7 +912,7 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage seqVo = new VpcDistributedRouterSeqNoVO(vpcId); _vpcDrSeqNoDao.persist(seqVo); } - _vpcDrSeqNoDao.lockRow(seqVo.getId(), true); + seqVo = _vpcDrSeqNoDao.lockRow(seqVo.getId(), true); seqVo.incrSequenceNo(); _vpcDrSeqNoDao.update(seqVo.getId(), seqVo); return seqVo.getSequenceNo(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cbe32683/scripts/vm/hypervisor/xenserver/cloudstack_pluginlib.py ---------------------------------------------------------------------- diff --git a/scripts/vm/hypervisor/xenserver/cloudstack_pluginlib.py b/scripts/vm/hypervisor/xenserver/cloudstack_pluginlib.py index cda3645..bcb9540 100644 --- a/scripts/vm/hypervisor/xenserver/cloudstack_pluginlib.py +++ b/scripts/vm/hypervisor/xenserver/cloudstack_pluginlib.py @@ -22,6 +22,7 @@ import logging import os import subprocess import simplejson as json +import copy from time import localtime, asctime @@ -349,7 +350,6 @@ def configure_bridge_for_network_topology(bridge, this_host_id, json_config, seq action_str = "table=0, in_port=%s," % of_port + " ip, dl_dst=%s," %network.gatewaymac +\ "nw_dst=%s," %vpconfig.cidr + "actions=resubmit(,3)" addflow = [OFCTL_PATH, "add-flow", bridge, action_str] - do_cmd(addflow) # get the list of hosts on which VPC spans from the JSON config @@ -510,4 +510,83 @@ def configure_ovs_bridge_for_routing_policies(bridge, json_config, sequence_no): except: logging.debug("An unexpected error occurred while configuring bridge as per VPC's routing policies.") + raise + +def update_flooding_rules_on_port_plug_unplug(bridge, interface, command, if_network_id): + + vnet_vif_ofports = [] + vnet_tunnelif_ofports = [] + vnet_all_ofports = [] + + logging.debug("Updating the flooding rules as interface %s" %interface + " is %s"%command + " now.") + try: + vsctl_output = do_cmd([VSCTL_PATH, 'list-ports', bridge]) + ports = vsctl_output.split('\n') + + for port in ports: + if_ofport = do_cmd([VSCTL_PATH, 'get', 'Interface', port, 'ofport']) + if port.startswith('vif'): + # check VIF is in same network as that of plugged vif + if if_network_id != get_network_id_for_vif(port): + continue + vnet_vif_ofports.append(if_ofport) + vnet_all_ofports.append(if_ofport) + + if port.startswith('t'): + # check tunnel port is in same network as that of plugged vif + if if_network_id != get_network_id_for_tunnel_port(port)[1:-1]: + continue + vnet_tunnelif_ofports.append(if_ofport) + vnet_all_ofports.append(if_ofport) + + if command == 'online': + + if len(vnet_all_ofports) == 1 : + return + + for port in vnet_all_ofports: + clear_flooding_rules_for_port(bridge, port) + + # for a packet arrived from tunnel port, flood only on VIF ports + for port in vnet_tunnelif_ofports: + add_flooding_rules_for_port(bridge, port, vnet_vif_ofports) + + # for a packet arrived from VIF port send on all VIF and tunnel port excluding the port + # on which packet arrived + for port in vnet_vif_ofports: + vnet_all_ofports_copy = copy.copy(vnet_all_ofports) + vnet_all_ofports_copy.remove(port) + add_flooding_rules_for_port(bridge, port, vnet_all_ofports_copy) + + this_if_ofport = do_cmd([VSCTL_PATH, 'get', 'Interface', interface, 'ofport']) + + #learn that MAC is reachable through the VIF port + if interface.startswith('vif'): + mac = get_macaddress_of_vif(interface) + add_mac_lookup_table_entry(bridge, mac, this_if_ofport) + + if command == 'offline': + for port in vnet_all_ofports: + clear_flooding_rules_for_port(bridge, port) + + vnet_all_ofports.remove(this_if_ofport) + vnet_vif_ofports.remove(this_if_ofport) + + # for a packet arrived from tunnel port, flood only on VIF ports + for port in vnet_tunnelif_ofports: + add_flooding_rules_for_port(bridge, port, vnet_vif_ofports) + + # for a packet from VIF port send on all VIF's and tunnel ports excluding the port on which packet arrived + for port in vnet_vif_ofports: + vnet_all_ofports_copy = copy.copy(vnet_all_ofports) + vnet_all_ofports_copy.remove(port) + add_flooding_rules_for_port(bridge, port, vnet_all_ofports_copy) + + #un-learn that MAC is reachable through the VIF port + if interface.startswith('vif'): + mac = get_macaddress_of_vif(interface) + delete_mac_lookup_table_entry(bridge, mac) + except: + logging.debug("An unexpected error occurred while updating the flooding rules when interface " + + " %s" %interface + " is %s"%command) raise \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cbe32683/scripts/vm/hypervisor/xenserver/ovs-vif-flows.py ---------------------------------------------------------------------- diff --git a/scripts/vm/hypervisor/xenserver/ovs-vif-flows.py b/scripts/vm/hypervisor/xenserver/ovs-vif-flows.py index b2fe11c..ba5f41a 100644 --- a/scripts/vm/hypervisor/xenserver/ovs-vif-flows.py +++ b/scripts/vm/hypervisor/xenserver/ovs-vif-flows.py @@ -15,8 +15,8 @@ # specific language governing permissions and limitations # under the License. -# A simple script for enabling and disabling per-vif rules for explicitly -# allowing broadcast/multicast traffic on the port where the VIF is attached +# A simple script for enabling and disabling per-vif and tunnel interface rules for explicitly +# allowing broadcast/multicast traffic from the tunnel ports and on the port where the VIF is attached import copy import os @@ -28,9 +28,11 @@ import cloudstack_pluginlib as pluginlib pluginlib.setup_logging("/var/log/cloud/ovstunnel.log") def clear_flows(bridge, this_vif_ofport, vif_ofports): + action = "".join("output:%s," %ofport + for ofport in vif_ofports)[:-1] # Remove flow entries originating from given ofport pluginlib.del_flows(bridge, in_port=this_vif_ofport) - # The following will remove the port being delete from actions + # The following will remove the port being delete from actions pluginlib.add_flow(bridge, priority=1100, dl_dst='ff:ff:ff:ff:ff:ff', actions=action) pluginlib.add_flow(bridge, priority=1100, @@ -40,7 +42,7 @@ def clear_flows(bridge, this_vif_ofport, vif_ofports): def apply_flows(bridge, this_vif_ofport, vif_ofports): action = "".join("output:%s," %ofport for ofport in vif_ofports)[:-1] - # Ensure {b|m}casts sent from VIF ports are always allowed + # Ensure {b|m}casts sent from VIF ports are always allowed pluginlib.add_flow(bridge, priority=1200, in_port=this_vif_ofport, dl_dst='ff:ff:ff:ff:ff:ff', @@ -49,7 +51,7 @@ def apply_flows(bridge, this_vif_ofport, vif_ofports): in_port=this_vif_ofport, nw_dst='224.0.0.0/24', actions='NORMAL') - # Ensure {b|m}casts are always propagated to VIF ports + # Ensure {b|m}casts are always propagated to VIF ports pluginlib.add_flow(bridge, priority=1100, dl_dst='ff:ff:ff:ff:ff:ff', actions=action) pluginlib.add_flow(bridge, priority=1100, @@ -116,6 +118,7 @@ def main(command, vif_raw): 'list-ports', bridge]) vifs = vsctl_output.split('\n') vif_ofports = [] + vif_other_ofports = [] for vif in vifs: vif_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get', 'Interface', vif, 'ofport']) @@ -125,7 +128,9 @@ def main(command, vif_raw): vif_ofports.append(vif_ofport) if command == 'offline': - clear_flows(bridge, this_vif_ofport, vif_ofports) + vif_other_ofports = copy.copy(vif_ofports) + vif_other_ofports.remove(this_vif_ofport) + clear_flows(bridge, this_vif_ofport, vif_other_ofports) if command == 'online': apply_flows(bridge, this_vif_ofport, vif_ofports) @@ -138,69 +143,8 @@ def main(command, vif_raw): # We need the REAL bridge name bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-parent', bridge]) - vsctl_output = pluginlib.do_cmd([pluginlib.VSCTL_PATH, - 'list-ports', bridge]) vif_network_id = pluginlib.get_network_id_for_vif(this_vif) - vnet_vif_ofports = [] - vnet_tunnelif_ofports = [] - vnet_all_ofports = [] - - ports = vsctl_output.split('\n') - for port in ports: - if_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get', 'Interface', port, 'ofport']) - if port.startswith('vif'): - # check VIF is in same network as that of plugged vif - if vif_network_id != pluginlib.get_network_id_for_vif(port): - continue - vnet_vif_ofports.append(if_ofport) - vnet_all_ofports.append(if_ofport) - - if port.startswith('t'): - # check tunnel port is in same network as that of plugged vif - if vif_network_id != pluginlib.get_network_id_for_tunnel_port(port)[1:-1]: - continue - vnet_tunnelif_ofports.append(if_ofport) - vnet_all_ofports.append(if_ofport) - - if command == 'online': - for port in vnet_all_ofports: - pluginlib.clear_flooding_rules_for_port(bridge, port) - - # for a packet arrived from tunnel port, flood only on VIF ports - for port in vnet_tunnelif_ofports: - pluginlib.add_flooding_rules_for_port(bridge, port, vnet_vif_ofports) - - # for a packet arrived from VIF port send on all VIF and tunnel port excluding the port - # on which packet arrived - for port in vnet_vif_ofports: - vnet_all_ofports_copy = copy.copy(vnet_all_ofports) - vnet_all_ofports_copy.remove(port) - pluginlib.add_flooding_rules_for_port(bridge, port, vnet_all_ofports_copy) - - #learn that MAC is reachable through the VIF port - mac = pluginlib.get_macaddress_of_vif(this_vif) - this_vif_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get', 'Interface', this_vif, 'ofport']) - pluginlib.add_mac_lookup_table_entry(bridge, mac, this_vif_ofport) - - if command == 'offline': - for port in vnet_all_ofports: - pluginlib.clear_flooding_rules_for_port(bridge, port) - vnet_all_ofports.remove(this_vif_ofport) - vnet_vif_ofports.remove(this_vif_ofport) - - # for a packet arrived from tunnel port, flood only on VIF ports - for port in vnet_tunnelif_ofports: - pluginlib.add_flooding_rules_for_port(bridge, port, vnet_vif_ofports) - - # for a packet from VIF port send on all VIF's and tunnel ports excluding the port on which packet arrived - for port in vnet_vif_ofports: - vnet_all_ofports_copy = copy.copy(vnet_all_ofports) - vnet_all_ofports_copy.remove(port) - pluginlib.add_flooding_rules_for_port(bridge, port, vnet_all_ofports_copy) - - #un-learn that MAC is reachable through the VIF port - mac = pluginlib.get_macaddress_of_vif(this_vif) - pluginlib.delete_mac_lookup_table_entry(bridge, mac) + pluginlib.update_flooding_rules_on_port_plug_unplug(bridge, this_vif, command, vif_network_id) return http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cbe32683/scripts/vm/hypervisor/xenserver/ovstunnel ---------------------------------------------------------------------- diff --git a/scripts/vm/hypervisor/xenserver/ovstunnel b/scripts/vm/hypervisor/xenserver/ovstunnel index a97df9b..db3216b 100755 --- a/scripts/vm/hypervisor/xenserver/ovstunnel +++ b/scripts/vm/hypervisor/xenserver/ovstunnel @@ -165,9 +165,12 @@ def setup_ovs_bridge_for_distributed_routing(session, args): lib.do_cmd([lib.XE_PATH, "network-param-set", "uuid=%s" % xs_nw_uuid, "other-config:ovs-host-setup=%s" % conf_hosts]) + # first clear the default rule (i.e rule for NORMAL processing) + lib.del_flows(bridge, table=0) + # add a default flow rule to send broadcast and multi-cast packets to L2 flooding table - lib.add_flow(bridge, priority=1000, dl_dst='ff:ff:ff:ff:ff:ff', table=0, actions='resubmit(,2)') - lib.add_flow(bridge, priority=1000, nw_dst='224.0.0.0/24', table=0, actions='resubmit(,2)') + lib.add_flow(bridge, priority=1200, dl_dst='ff:ff:ff:ff:ff:ff', table=0, actions='resubmit(,2)') + lib.add_flow(bridge, priority=1200, nw_dst='224.0.0.0/24', table=0, actions='resubmit(,2)') # add a default flow rule to send uni-cast traffic to L2 lookup table lib.add_flow(bridge, priority=0, table=0, actions='resubmit(,1)') @@ -178,7 +181,7 @@ def setup_ovs_bridge_for_distributed_routing(session, args): # add a default rule in L2 flood table to drop packet lib.add_flow(bridge, priority=0, table=2, actions='drop') - # add a default rule in egress table to forward packet to L3 lookup table + # add a default rule in egress ACL table to forward packet to L3 lookup table lib.add_flow(bridge, priority=0, table=3, actions='resubmit(,4)') # add a default rule in L3 lookup table to forward packet to L2 lookup table @@ -187,6 +190,9 @@ def setup_ovs_bridge_for_distributed_routing(session, args): # add a default rule in ingress table to drop in bound packets lib.add_flow(bridge, priority=0, table=5, actions='drop') + # initialize the sequence number for the bridge + lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other-config:sequence-number=0"]) + result = "SUCCESS: successfully setup bridge with flow rules" logging.debug("Setup_ovs_bridge completed with result:%s" % result) @@ -326,8 +332,11 @@ def create_tunnel(session, args): nw_dst='224.0.0.0/24', actions='drop') # add flow rule to send the traffic from tunnel ports to L2 switching table only - lib.add_flow(bridge, priority=1000, in_port=tun_ofport, table=0, actions='resubmit(,1)') + lib.add_flow(bridge, priority=1100, in_port=tun_ofport, table=0, actions='resubmit(,1)') + + # mark tunnel interface with network id for which this tunnel was created lib.do_cmd([lib.VSCTL_PATH, "set", "interface", name, "options:cloudstack-network-id=%s" % network_uuid]) + lib.update_flooding_rules_on_port_plug_unplug(bridge, name, 'online', network_uuid) return "SUCCESS:%s" % name except: @@ -402,15 +411,29 @@ def configure_ovs_bridge_for_network_topology(session, args): this_host_id = args.pop("host-id") sequence_no = args.pop("seq-no") - return lib.configure_bridge_for_network_topology(bridge, this_host_id, json_config, sequence_no) + # get the last update sequence number + last_seq_no = lib.do_cmd([lib.VSCTL_PATH, "get", "bridge", bridge, "other-config:sequence-number"]) + last_seq_no = last_seq_no[1:-1] + if sequence_no > last_seq_no: + lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other-config:sequence-number=%s"%sequence_no]) + return lib.configure_bridge_for_network_topology(bridge, this_host_id, json_config, sequence_no) + else: + return "SUCCESS: Ignoring the update as there is already recent update received and applied" + @echo def configure_ovs_bridge_for_routing_policies(session, args): bridge = args.pop("bridge") json_config = args.pop("config") sequence_no = args.pop("seq-no") - - return lib.configure_ovs_bridge_for_routing_policies(bridge, json_config, sequence_no) + # get the last update sequence number + last_seq_no = lib.do_cmd([lib.VSCTL_PATH, "get", "bridge", bridge, "other-config:sequence-number"]) + last_seq_no = last_seq_no[1:-1] + if sequence_no > last_seq_no: + lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other-config:sequence-number=%s"%sequence_no]) + return lib.configure_ovs_bridge_for_routing_policies(bridge, json_config, sequence_no) + else: + return "SUCCESS: Ignoring the update as there is already recent update received and applied" if __name__ == "__main__": XenAPIPlugin.dispatch({"create_tunnel": create_tunnel,