def clear_rules(vif): try: delcmd = "/sbin/ebtables -t nat -L PREROUTING | grep " + vif delcmds = pluginlib.do_cmd(['/bin/bash', '-c', delcmd]).split('\n') for cmd in delcmds: try: cmd = '/sbin/ebtables -t nat -D PREROUTING ' + cmd pluginlib.do_cmd(['/bin/bash', '-c', cmd]) except: pass except: pass
def setup_ovs_bridge(bridge, key, cs_host_id): res = lib.check_switch() if res != "SUCCESS": #return "FAILURE:%s" % res return 'false' logging.debug("About to manually create the bridge:%s" % bridge) #set gre_key to bridge res = lib.do_cmd([ lib.VSCTL_PATH, "set", "bridge", bridge, "other_config:gre_key=%s" % key ]) # enable stp lib.do_cmd([lib.VSCTL_PATH, "set", "Bridge", bridge, "stp_enable=true"]) logging.debug("Bridge has been manually created:%s" % res) if res: # result = "FAILURE:%s" % res result = 'false' else: # Verify the bridge actually exists, with the gre_key properly set res = lib.do_cmd( [lib.VSCTL_PATH, "get", "bridge", bridge, "other_config:gre_key"]) if key in str(res): # result = "SUCCESS:%s" % bridge result = 'true' else: # result = "FAILURE:%s" % res result = 'false' lib.do_cmd([ lib.VSCTL_PATH, "set", "bridge", bridge, "other_config:is-ovs-tun-network=True" ]) #get list of hosts using this bridge conf_hosts = lib.do_cmd([ lib.VSCTL_PATH, "get", "bridge", bridge, "other_config:ovs-host-setup" ]) #add cs_host_id to list of hosts using this bridge conf_hosts = cs_host_id + (conf_hosts and ',%s' % eval(conf_hosts) or '') lib.do_cmd([ lib.VSCTL_PATH, "set", "bridge", bridge, "other_config:ovs-host-setup=%s" % conf_hosts ]) logging.debug("Setup_ovs_bridge completed with result:%s" % result) return result
def main(command, vif_raw): if command not in ('online', 'offline'): return vif_name, dom_id, vif_index = vif_raw.split('-') # validate vif and dom-id this_vif = "%s%s.%s" % (vif_name, dom_id, vif_index) # Make sure the networking stack is not linux bridge! net_stack = pluginlib.do_cmd(['cat', '/etc/xensource/network.conf']) if net_stack.lower() == "bridge": if command == 'offline': clear_rules(this_vif) # Nothing to do here! return bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'iface-to-br', this_vif]) # find xs network for this bridge, verify is used for ovs tunnel network xs_nw_uuid = pluginlib.do_cmd( [pluginlib.XE_PATH, "network-list", "bridge=%s" % bridge, "--minimal"]) result = pluginlib.do_cmd([ pluginlib.XE_PATH, "network-param-get", "uuid=%s" % xs_nw_uuid, "param-name=other-config", "param-key=is-ovs-tun-network", "--minimal" ]) if result != 'True': return vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge]) if vlan != '0': # 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]) vifs = vsctl_output.split('\n') vif_ofports = [] for vif in vifs: vif_ofport = pluginlib.do_cmd( [pluginlib.VSCTL_PATH, 'get', 'Interface', vif, 'ofport']) if this_vif == vif: this_vif_ofport = vif_ofport if vif.startswith('vif'): vif_ofports.append(vif_ofport) if command == 'offline': clear_flows(bridge, this_vif_ofport, vif_ofports) if command == 'online': apply_flows(bridge, this_vif_ofport, vif_ofports)
def main(command, vif_raw): if command not in ('online', 'offline'): return vif_name, dom_id, vif_index = vif_raw.split('-') # validate vif and dom-id this_vif = "%s%s.%s" % (vif_name, dom_id, vif_index) # Make sure the networking stack is not linux bridge! net_stack = pluginlib.do_cmd(['cat', '/etc/xensource/network.conf']) if net_stack.lower() == "bridge": if command == 'offline': clear_rules(this_vif) # Nothing to do here! return bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'iface-to-br', this_vif]) # find xs network for this bridge, verify is used for ovs tunnel network xs_nw_uuid = pluginlib.do_cmd([pluginlib.XE_PATH, "network-list", "bridge=%s" % bridge, "--minimal"]) result = pluginlib.do_cmd([pluginlib.XE_PATH,"network-param-get", "uuid=%s" % xs_nw_uuid, "param-name=other-config", "param-key=is-ovs-tun-network", "--minimal"]) if result != 'True': return vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge]) if vlan != '0': # 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]) vifs = vsctl_output.split('\n') vif_ofports = [] for vif in vifs: vif_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get', 'Interface', vif, 'ofport']) if this_vif == vif: this_vif_ofport = vif_ofport if vif.startswith('vif'): vif_ofports.append(vif_ofport) if command == 'offline': clear_flows(bridge, this_vif_ofport, vif_ofports) if command == 'online': apply_flows(bridge, this_vif_ofport, vif_ofports)
def main(command, vif_raw): if command not in ('online', 'offline'): return # TODO (very important) # Quit immediately if networking is NOT being managed by the OVS tunnel manager vif_name, dom_id, vif_index = vif_raw.split('-') # validate vif and dom-id vif = "%s%s.%s" % (vif_name, dom_id, vif_index) bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'iface-to-br', vif]) # find xs network for this bridge, verify is used for ovs tunnel network xs_nw_uuid = pluginlib.do_cmd([pluginlib.XE_PATH, "network-list", "bridge=%s" % bridge, "--minimal"]) result = pluginlib.do_cmd([pluginlib.XE_PATH,"network-param-get", "uuid=%s" % xs_nw_uuid, "param-name=other-config", "param-key=is-ovs-tun-network", "--minimal"]) if result != 'True': return vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge]) if vlan != '0': # We need the REAL bridge name bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-parent', bridge]) vif_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get', 'Interface', vif, 'ofport']) if command == 'offline': clear_flows(bridge, vif_ofport) if command == 'online': apply_flows(bridge, vif_ofport)
def setup_ovs_bridge(bridge, key, cs_host_id): res = lib.check_switch() if res != "SUCCESS": #return "FAILURE:%s" % res return 'false' logging.debug("About to manually create the bridge:%s" % bridge) #set gre_key to bridge res = lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other_config:gre_key=%s" % key]) # enable stp lib.do_cmd([lib.VSCTL_PATH, "set", "Bridge", bridge, "stp_enable=true"]) logging.debug("Bridge has been manually created:%s" % res) if res: # result = "FAILURE:%s" % res result = 'false' else: # Verify the bridge actually exists, with the gre_key properly set res = lib.do_cmd([lib.VSCTL_PATH, "get", "bridge", bridge, "other_config:gre_key"]) if key in res: # result = "SUCCESS:%s" % bridge result = 'true' else: # result = "FAILURE:%s" % res result = 'false' lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other_config:is-ovs-tun-network=True"]) #get list of hosts using this bridge conf_hosts = lib.do_cmd([lib.VSCTL_PATH, "get","bridge", bridge,"other_config:ovs-host-setup"]) #add cs_host_id to list of hosts using this bridge conf_hosts = cs_host_id + (conf_hosts and ',%s' % conf_hosts or '') lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other_config:ovs-host-setup=%s" % conf_hosts]) logging.debug("Setup_ovs_bridge completed with result:%s" % result) return result
def destroy_ovs_bridge(bridge): res = lib.check_switch() if res != "SUCCESS": # return res return 'false' res = lib.do_cmd([lib.VSCTL_PATH, "del-br", bridge]) logging.debug("Bridge has been manually removed:%s" % res) if res: # result = "FAILURE:%s" % res result = 'false' else: # result = "SUCCESS:%s" % bridge result = 'true' logging.debug("Destroy_ovs_bridge completed with result:%s" % result) return result
def setup_ovs_bridge_for_distributed_routing(bridge, cs_host_id): res = lib.check_switch() if res != "SUCCESS": return "FAILURE:%s" % res logging.debug("About to manually create the bridge:%s" % bridge) res = lib.do_cmd([lib.VSCTL_PATH, "--", "--may-exist", "add-br", bridge]) logging.debug("Bridge has been manually created:%s" % res) # Non empty result means something went wrong if res: result = "FAILURE:%s" % res else: # Verify the bridge actually exists res = lib.do_cmd([lib.VSCTL_PATH, "list", "bridge", bridge]) res = lib.do_cmd( [lib.VSCTL_PATH, "set", "bridge", bridge, "other_config:is-ovs_vpc_distributed_vr_network=True"] ) conf_hosts = lib.do_cmd([lib.VSCTL_PATH, "get", "bridge", bridge, "other:ovs-host-setup"]) conf_hosts = cs_host_id + (conf_hosts and ",%s" % conf_hosts or "") lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other_config:ovs-host-setup=%s" % conf_hosts]) # 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)") # 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)") # add a default rule to send unknown mac address to L2 flooding table lib.add_flow(bridge, priority=0, table=1, actions="resubmit(,2)") # 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 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 lib.add_flow(bridge, priority=0, table=4, actions="resubmit(,1)") # add a default rule in ingress table to drop in bound packets lib.add_flow(bridge, priority=0, table=5, actions="drop") result = "SUCCESS: successfully setup bridge with flow rules" logging.debug("Setup_ovs_bridge completed with result:%s" % result) return result
def setup_ovs_bridge_for_distributed_routing(bridge, cs_host_id): res = lib.check_switch() if res != "SUCCESS": return "FAILURE:%s" % res logging.debug("About to manually create the bridge:%s" % bridge) res = lib.do_cmd([lib.VSCTL_PATH, "--", "--may-exist", "add-br", bridge]) logging.debug("Bridge has been manually created:%s" % res) # Non empty result means something went wrong if res: result = "FAILURE:%s" % res else: # Verify the bridge actually exists res = lib.do_cmd([lib.VSCTL_PATH, "list", "bridge", bridge]) res = lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other_config:is-ovs_vpc_distributed_vr_network=True"]) conf_hosts = lib.do_cmd([lib.VSCTL_PATH, "get","bridge", bridge,"other:ovs-host-setup"]) conf_hosts = cs_host_id + (conf_hosts and ',%s' % conf_hosts or '') lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other_config:ovs-host-setup=%s" % conf_hosts]) # 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)') # 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)') # add a default rule to send unknown mac address to L2 flooding table lib.add_flow(bridge, priority=0, table=1, actions='resubmit(,2)') # 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 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 lib.add_flow(bridge, priority=0, table=4, actions='resubmit(,1)') # add a default rule in ingress table to drop in bound packets lib.add_flow(bridge, priority=0, table=5, actions='drop') result = "SUCCESS: successfully setup bridge with flow rules" logging.debug("Setup_ovs_bridge completed with result:%s" % result) return result
def main(command, vif_raw): if command not in ('online', 'offline'): return # TODO (very important) # Quit immediately if networking is NOT being managed by the OVS tunnel manager vif_name, dom_id, vif_index = vif_raw.split('-') # validate vif and dom-id this_vif = "%s%s.%s" % (vif_name, dom_id, vif_index) bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'iface-to-br', this_vif]) # find xs network for this bridge, verify is used for ovs tunnel network xs_nw_uuid = pluginlib.do_cmd([pluginlib.XE_PATH, "network-list", "bridge=%s" % bridge, "--minimal"]) result = pluginlib.do_cmd([pluginlib.XE_PATH,"network-param-get", "uuid=%s" % xs_nw_uuid, "param-name=other-config", "param-key=is-ovs-tun-network", "--minimal"]) if result != 'True': return vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge]) if vlan != '0': # We need the REAL bridge name bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-parent', bridge]) # For the OVS version shipped with XS56FP1 we need to retrieve # the ofport number for all interfaces vsctl_output = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'list-ports', bridge]) vifs = vsctl_output.split('\n') vif_ofports = [] for vif in vifs: vif_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get', 'Interface', vif, 'ofport']) if this_vif == vif: this_vif_ofport = vif_ofport vif_ofports.append(vif_ofport) if command == 'offline': clear_flows(bridge, this_vif_ofport, vif_ofports) if command == 'online': apply_flows(bridge, this_vif_ofport, vif_ofports)
def create_tunnel(bridge, remote_ip, key, src_host, dst_host): logging.debug("Entering create_tunnel") res = lib.check_switch() if res != "SUCCESS": logging.debug("Openvswitch running: NO") # return "FAILURE:%s" % res return 'false' # We need to keep the name below 14 characters # src and target are enough - consider a fixed length hash name = "t%s-%s-%s" % (key, src_host, dst_host) # Verify the bridge to be created # NOTE: Timeout should not be necessary anymore wait = [ lib.VSCTL_PATH, "--timeout=30", "wait-until", "bridge", bridge, "--", "get", "bridge", bridge, "name" ] res = lib.do_cmd(wait) if bridge not in res: logging.debug("WARNING:Can't find bridge %s for creating " + "tunnel!" % bridge) # return "FAILURE:NO_BRIDGE" return 'false' logging.debug("bridge %s for creating tunnel - VERIFIED" % bridge) tunnel_setup = False drop_flow_setup = False try: # Create a port and configure the tunnel interface for it add_tunnel = [ lib.VSCTL_PATH, "add-port", bridge, name, "--", "set", "interface", name, "type=gre", "options:key=%s" % key, "options:remote_ip=%s" % remote_ip ] lib.do_cmd(add_tunnel) tunnel_setup = True # verify port verify_port = [lib.VSCTL_PATH, "get", "port", name, "interfaces"] res = lib.do_cmd(verify_port) # Expecting python-style list as output iface_list = [] if len(res) > 2: iface_list = res.strip()[1:-1].split(',') if len(iface_list) != 1: logging.debug("WARNING: Unexpected output while verifying " + "port %s on bridge %s" % (name, bridge)) # return "FAILURE:VERIFY_PORT_FAILED" return 'false' # verify interface iface_uuid = iface_list[0] verify_interface_key = [ lib.VSCTL_PATH, "get", "interface", iface_uuid, "options:key" ] verify_interface_ip = [ lib.VSCTL_PATH, "get", "interface", iface_uuid, "options:remote_ip" ] key_validation = lib.do_cmd(verify_interface_key) ip_validation = lib.do_cmd(verify_interface_ip) if not key in key_validation or not remote_ip in ip_validation: logging.debug("WARNING: Unexpected output while verifying " + "interface %s on bridge %s" % (name, bridge)) # return "FAILURE:VERIFY_INTERFACE_FAILED" return 'false' logging.debug("Tunnel interface validated:%s" % verify_interface_ip) cmd_tun_ofport = [ lib.VSCTL_PATH, "get", "interface", iface_uuid, "ofport" ] tun_ofport = lib.do_cmd(cmd_tun_ofport) # Ensure no trailing LF if tun_ofport.endswith('\n'): tun_ofport = tun_ofport[:-1] # add flow entryies for dropping broadcast coming in from gre tunnel lib.add_flow(bridge, priority=1000, in_port=tun_ofport, dl_dst='ff:ff:ff:ff:ff:ff', actions='drop') lib.add_flow(bridge, priority=1000, in_port=tun_ofport, nw_dst='224.0.0.0/24', actions='drop') drop_flow_setup = True logging.debug("Broadcast drop rules added") # return "SUCCESS:%s" % name return 'true' except: logging.debug("An unexpected error occured. Rolling back") if tunnel_setup: logging.debug("Deleting GRE interface") # Destroy GRE port and interface lib.del_port(bridge, name) if drop_flow_setup: # Delete flows logging.debug("Deleting flow entries from GRE interface") lib.del_flows(bridge, in_port=tun_ofport) # This will not cancel the original exception raise
def get_field_of_interface(iface_name, field): get_iface_cmd = [lib.VSCTL_PATH, "get", "interface", iface_name, field] res = lib.do_cmd(get_iface_cmd) return res
def main(command, vif_raw): if command not in ('online', 'offline'): return vif_name, dom_id, vif_index = vif_raw.split('-') # validate vif and dom-id this_vif = "%s%s.%s" % (vif_name, dom_id, vif_index) # Make sure the networking stack is not linux bridge! net_stack = pluginlib.do_cmd(['cat', '/etc/xensource/network.conf']) if net_stack.lower() == "bridge": if command == 'offline': clear_rules(this_vif) # Nothing to do here! return bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'iface-to-br', this_vif]) # find xs network for this bridge, verify is used for ovs tunnel network xs_nw_uuid = pluginlib.do_cmd([pluginlib.XE_PATH, "network-list", "bridge=%s" % bridge, "--minimal"]) ovs_tunnel_network = False try: ovs_tunnel_network = pluginlib.do_cmd([pluginlib.XE_PATH,"network-param-get", "uuid=%s" % xs_nw_uuid, "param-name=other-config", "param-key=is-ovs-tun-network", "--minimal"]) except: pass ovs_vpc_distributed_vr_network = False try: ovs_vpc_distributed_vr_network = pluginlib.do_cmd([pluginlib.XE_PATH,"network-param-get", "uuid=%s" % xs_nw_uuid, "param-name=other-config", "param-key=is-ovs-vpc-distributed-vr-network", "--minimal"]) except: pass if ovs_tunnel_network == 'True': vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge]) if vlan != '0': # 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]) vifs = vsctl_output.split('\n') vif_ofports = [] for vif in vifs: vif_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get', 'Interface', vif, 'ofport']) if this_vif == vif: this_vif_ofport = vif_ofport if vif.startswith('vif'): vif_ofports.append(vif_ofport) if command == 'offline': clear_flows(bridge, this_vif_ofport, vif_ofports) if command == 'online': apply_flows(bridge, this_vif_ofport, vif_ofports) # handle case where brdige is setup for VPC and VPC is enabled for distributed routing if ovs_vpc_distributed_vr_network == 'True': vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge]) if vlan != '0': # 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) return
def main(command, vif_raw): if command not in ('online', 'offline'): return vif_name, dom_id, vif_index = vif_raw.split('-') # validate vif and dom-id this_vif = "%s%s.%s" % (vif_name, dom_id, vif_index) # Make sure the networking stack is not linux bridge! net_stack = pluginlib.do_cmd(['cat', '/etc/xensource/network.conf']) if net_stack.lower() == "bridge": if command == 'offline': clear_rules(this_vif) # Nothing to do here! return bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'iface-to-br', this_vif]) # find xs network for this bridge, verify is used for ovs tunnel network xs_nw_uuid = pluginlib.do_cmd([pluginlib.XE_PATH, "network-list", "bridge=%s" % bridge, "--minimal"]) ovs_tunnel_network = pluginlib.is_regular_tunnel_network(xs_nw_uuid) # handle case where network is reguar tunnel network if ovs_tunnel_network == 'True': vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge]) if vlan != '0': # 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]) 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']) if this_vif == vif: this_vif_ofport = vif_ofport if vif.startswith('vif'): vif_ofports.append(vif_ofport) if command == 'offline': 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) # handle case where bridge is setup for VPC which is enabled for distributed routing ovs_vpc_distributed_vr_network = pluginlib.is_vpc_network_with_distributed_routing(xs_nw_uuid) if ovs_vpc_distributed_vr_network == 'True': vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge]) if vlan != '0': # We need the REAL bridge name bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-parent', bridge]) vif_network_id = pluginlib.get_network_id_for_vif(this_vif) pluginlib.update_flooding_rules_on_port_plug_unplug(bridge, this_vif, command, vif_network_id) return
def main(command, vif_raw): if command not in ('online', 'offline'): return vif_name, dom_id, vif_index = vif_raw.split('-') # validate vif and dom-id this_vif = "%s%s.%s" % (vif_name, dom_id, vif_index) # Make sure the networking stack is not linux bridge! net_stack = pluginlib.do_cmd(['cat', '/etc/xensource/network.conf']) if net_stack.lower() == "bridge": if command == 'offline': clear_rules(this_vif) # Nothing to do here! return bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'iface-to-br', this_vif]) # find xs network for this bridge, verify is used for ovs tunnel network xs_nw_uuid = pluginlib.do_cmd( [pluginlib.XE_PATH, "network-list", "bridge=%s" % bridge, "--minimal"]) ovs_tunnel_network = False try: ovs_tunnel_network = pluginlib.do_cmd([ pluginlib.XE_PATH, "network-param-get", "uuid=%s" % xs_nw_uuid, "param-name=other-config", "param-key=is-ovs-tun-network", "--minimal" ]) except: pass ovs_vpc_distributed_vr_network = False try: ovs_vpc_distributed_vr_network = pluginlib.do_cmd([ pluginlib.XE_PATH, "network-param-get", "uuid=%s" % xs_nw_uuid, "param-name=other-config", "param-key=is-ovs-vpc-distributed-vr-network", "--minimal" ]) except: pass if ovs_tunnel_network == 'True': vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge]) if vlan != '0': # 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]) vifs = vsctl_output.split('\n') vif_ofports = [] for vif in vifs: vif_ofport = pluginlib.do_cmd( [pluginlib.VSCTL_PATH, 'get', 'Interface', vif, 'ofport']) if this_vif == vif: this_vif_ofport = vif_ofport if vif.startswith('vif'): vif_ofports.append(vif_ofport) if command == 'offline': clear_flows(bridge, this_vif_ofport, vif_ofports) if command == 'online': apply_flows(bridge, this_vif_ofport, vif_ofports) # handle case where bridge is setup for VPC which is enabled for distributed routing if ovs_vpc_distributed_vr_network == 'True': vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge]) if vlan != '0': # 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) return
def create_tunnel(bridge, remote_ip, key, src_host, dst_host): logging.debug("Entering create_tunnel") res = lib.check_switch() if res != "SUCCESS": logging.debug("Openvswitch running: NO") # return "FAILURE:%s" % res return 'false' # We need to keep the name below 14 characters # src and target are enough - consider a fixed length hash name = "t%s-%s-%s" % (key, src_host, dst_host) # Verify the bridge to be created # NOTE: Timeout should not be necessary anymore wait = [lib.VSCTL_PATH, "--timeout=30", "wait-until", "bridge", bridge, "--", "get", "bridge", bridge, "name"] res = lib.do_cmd(wait) if bridge not in res: logging.debug("WARNING:Can't find bridge %s for creating " + "tunnel!" % bridge) # return "FAILURE:NO_BRIDGE" return 'false' logging.debug("bridge %s for creating tunnel - VERIFIED" % bridge) tunnel_setup = False drop_flow_setup = False try: # Create a port and configure the tunnel interface for it add_tunnel = [lib.VSCTL_PATH, "add-port", bridge, name, "--", "set", "interface", name, "type=gre", "options:key=%s" % key, "options:remote_ip=%s" % remote_ip] lib.do_cmd(add_tunnel) tunnel_setup = True # verify port verify_port = [lib.VSCTL_PATH, "get", "port", name, "interfaces"] res = lib.do_cmd(verify_port) # Expecting python-style list as output iface_list = [] if len(res) > 2: iface_list = res.strip()[1:-1].split(',') if len(iface_list) != 1: logging.debug("WARNING: Unexpected output while verifying " + "port %s on bridge %s" % (name, bridge)) # return "FAILURE:VERIFY_PORT_FAILED" return 'false' # verify interface iface_uuid = iface_list[0] verify_interface_key = [lib.VSCTL_PATH, "get", "interface", iface_uuid, "options:key"] verify_interface_ip = [lib.VSCTL_PATH, "get", "interface", iface_uuid, "options:remote_ip"] key_validation = lib.do_cmd(verify_interface_key) ip_validation = lib.do_cmd(verify_interface_ip) if not key in key_validation or not remote_ip in ip_validation: logging.debug("WARNING: Unexpected output while verifying " + "interface %s on bridge %s" % (name, bridge)) # return "FAILURE:VERIFY_INTERFACE_FAILED" return 'false' logging.debug("Tunnel interface validated:%s" % verify_interface_ip) cmd_tun_ofport = [lib.VSCTL_PATH, "get", "interface", iface_uuid, "ofport"] tun_ofport = lib.do_cmd(cmd_tun_ofport) # Ensure no trailing LF if tun_ofport.endswith('\n'): tun_ofport = tun_ofport[:-1] # add flow entryies for dropping broadcast coming in from gre tunnel lib.add_flow(bridge, priority=1000, in_port=tun_ofport, dl_dst='ff:ff:ff:ff:ff:ff', actions='drop') lib.add_flow(bridge, priority=1000, in_port=tun_ofport, nw_dst='224.0.0.0/24', actions='drop') drop_flow_setup = True logging.debug("Broadcast drop rules added") # return "SUCCESS:%s" % name return 'true' except: logging.debug("An unexpected error occured. Rolling back") if tunnel_setup: logging.debug("Deleting GRE interface") # Destroy GRE port and interface lib.del_port(bridge, name) if drop_flow_setup: # Delete flows logging.debug("Deleting flow entries from GRE interface") lib.del_flows(bridge, in_port=tun_ofport) # This will not cancel the original exception raise