def test_delete_table_flows(self): # import here, after we've checked the environment from ovstest import util from magma.pkt_tester.topology_builder import OvsException # basic setup self._generate_topology() self.controller_thread.start() self._wait_for_controller() self._setup_ovs() self._wait_for_datapath() # add flows to the test bridge for iface in self.TEST_IPS: port = self._port_no[iface] flow = "in_port=%d,table=5,actions=output:%d" % (port, port) ret, out, err = util.start_process( ["ovs-ofctl", "add-flow", self.TEST_BRIDGE, flow]) flow = "in_port=%d,table=6,actions=output:%d" % (port, port) ret, out, err = util.start_process( ["ovs-ofctl", "add-flow", self.TEST_BRIDGE, flow]) ret, out, err = util.start_process( ["ovs-ofctl", "dump-flows", self.TEST_BRIDGE]) dp = list(self.mc.datapaths.values())[0] self.mc.delete_all_table_flows(dp, table=5) time.sleep(1.5) ret, out, err = util.start_process( ["ovs-ofctl", "dump-flows", self.TEST_BRIDGE]) self.assertTrue("table=6" in str(out)) self.assertFalse("table=5" in str(out))
def create_match_flow(test_tun_id, src_of_port, dst_of_port): """ Create a match flow that matches on the GTP tunnel id and the in_port and outputs to the specified out_port. This is better done through an openflow controller. Args: test_tun_id: The tunnel id to match. src_of_port: The openflow port number of the src port dst_of_port: The destination port number of the dst port """ from ovstest import util # pylint: disable=import-error from magma.pkt_tester.topology_builder import OvsException # Set bridge to secure (to prevent learning) ret_val, out, err = util.start_process( ["ovs-vsctl", "set-fail-mode", "test_br", "secure"]) if ret_val: raise OvsException("Failed to set bridge in secure mode %s, %s" % (out, err)) flow = ("in_port=%s,gtp_tun_id=%s,actions=output:%s" % (src_of_port, test_tun_id, dst_of_port)) ret_val, out, err = util.start_process( ["ovs-ofctl", "add-flow", TestOvsGtp.TEST_BRIDGE_NAME, flow]) if ret_val: raise OvsException("Failed to install gtp match flow %s, " "%s" % (out, err))
def test_delete_all_flows(self): # import here, after we've checked the environment from ovstest import util from magma.pkt_tester.topology_builder import OvsException # basic setup self._generate_topology() self.controller_thread.start() self._wait_for_controller() self._setup_ovs() self._wait_for_datapath() # add flows to the test bridge for iface in self.TEST_IPS: port = self._port_no[iface] flow = "in_port=%d,actions=output:%d" % (port, port) ret, out, err = util.start_process( ["ovs-ofctl", "add-flow", self.TEST_BRIDGE, flow]) ret, out, err = util.start_process( ["ovs-ofctl", "dump-flows", self.TEST_BRIDGE]) self.mc.reset_all_flows(list(self.mc.datapaths.values())[0]) time.sleep(1.5) # we gotta wait a while in practice :-( ret, out, err = util.start_process( ["ovs-ofctl", "dump-flows", self.TEST_BRIDGE]) flows = out.decode("utf-8").strip().split('\n') # when no flows, you get just one element containing "NXST_FLOW" self.assertEqual(len(flows), 1)
def destroy_bridge(self, br_name=None): # Destroy the br_name (default: TEST_BRIDGE) from ovstest import util if not br_name: br_name = self.TEST_BRIDGE util.start_process(["ovs-vsctl", "del-br", br_name]) if self.mc: for k in list(self.mc.TABLES.keys()): # reset all the tables del self.mc.TABLES[k]
def test_add_inout_flows(self): from ovstest import util from magma.pkt_tester.topology_builder import OvsException self._generate_topology() self.controller_thread.start() self._wait_for_controller() # clear out any existing in_blocks and set up for the test in_net = self.TEST_NETS[self.SRC_PORT] del self.mc.in_blocks[:] self.mc.in_blocks.append(in_net) # clear out existing net block to of port mappings for k in list(self.mc.IPBLOCK_TO_OFPORT.keys()): del self.mc.IPBLOCK_TO_OFPORT[k] self.mc.IPBLOCK_TO_OFPORT[in_net] = self._port_no[self.SRC_PORT] self._setup_ovs() self._wait_for_datapath() ret, out, err = util.start_process(["ovs-ofctl", "dump-flows", self.TEST_BRIDGE]) flow_string = str(out) # check if the flows we expect are loaded # directions are tagged properly, and resubmit to right table expected = "nw_dst=%s actions=set_field:0->metadata,resubmit(,1)" % in_net self.assertTrue(expected in flow_string) expected = "nw_src=%s actions=set_field:0x10->metadata,resubmit(,1)" % in_net self.assertTrue(expected in flow_string)
def interface_get_ip(iface): """ Returns ip address and netmask (in dot decimal format) for the given iface. Args: iface: Interface name Return: (ip_address, netmask) tuple Raises: OvsException if iface doesn't exist """ args = ["ip", "-f", "inet", "-o", "addr", "show", iface] ret, out, _err = util.start_process(args) if ret: raise OvsException("Can't get ip address for %s" % iface) try: res = re.search(br'inet (\S+)/(\S+)', out) if res: ip = res.group(1).decode('utf-8') netmask = Interface.cidr_to_dotdec(int(res.group(2))) return (ip, netmask) except ValueError as e: raise OvsException("Can't get ip address for %s" % iface) from e
def destroy(self): """ Bring the interface down. Raises OvsException if interface destroy fails. """ ret, _, _ = util.start_process(["ip", "link", "show", self._iface]) if ret == 1: # iface doesn't exist self._valid = False return ret, _out, _err = util.start_process( ["ip", "link", "set", self._iface, "down"]) if ret: raise OvsException("Failed to bring down interface %s" % self._iface) self._valid = False
def _setup_ovs(self): """ This actually causes the switch to come up and connect to the controller. """ # Make sure OVS is pointing to the controller. from ovstest import util # set ovs protocol version ret, out, err = util.start_process([ "ovs-vsctl", "set", "bridge", self.TEST_BRIDGE, "protocols=OpenFlow10,OpenFlow14" ]) # connect to a controller ret, out, err = util.start_process([ "ovs-vsctl", "set-controller", self.TEST_BRIDGE, "tcp:127.0.0.1:6633" ])
def up(self): # pylint: disable=invalid-name """ Bring up the interface Raises: OvsException if the interface bring up failed. """ ret, _, _ = util.start_process( ["ip", "link", "set", self._iface, "up"]) if ret: raise OvsException("Failed to bring up interface %s" % self._iface)
def _extract_of_port_no(iface_name): """ Extract the ofport number for the interface. Returns: return of ofport number of the specified interface. """ # Query the db for the ofport number. ret, out, err = util.start_process( ["ovs-vsctl", "get", Port.INT_TABLE, iface_name, Port.INT_OFPORT]) if ret: raise OvsException("Failed to read port number for interface %s, " "message %s, error no %s" % (iface_name, out, err)) return int(out)
def __init__(self, iface_name, bridge_name, port_type): """ Create a bridge port of the same name as the iface and sets the port type in the interface table. Initialize the list of port attributes. Internal ports are special in the sense that they are opened as tap devices by the bridge implementation. Bridge needs to already exist for the creation to succeed. Interface needs to exist for the port status to be up. Args: iface_name: Interface to connect to the bridge bridge_name: Name of the bridge. port_type: Type of port defaults to internal Raises: OvsException in case of error """ self._iface_name = iface_name self._bridge_name = bridge_name self._port_type = port_type self._of_port_no = self.UNINITIALIZED_PORT_NO # Lazy initialization. # Create the interface ret_val, out, err = util.start_process([ "ovs-vsctl", "add-port", bridge_name, iface_name, ]) if ret_val: raise OvsException( "Error creating port on bridge %s output %s, " "error %s" % (bridge_name, out, err), ) ret_val = vswitch.ovs_vsctl_set( self.INT_TABLE, iface_name, self.INT_TYPE, None, port_type, ) if ret_val: raise OvsException( "Error setting interface type for interface " "%s" % iface_name, ) self._valid = True
def sanity_check(self): """ Check that a port is in linked up state. Returns: True if port is in linked up state False otherwise Raises: OvsException if port cannot be accessed. """ up_str = b'up\n' ret, out, err = util.start_process([ "ovs-vsctl", "get", Port.INT_TABLE, self._iface_name, Port.INT_LINK_STATE ]) if ret: raise OvsException("Failed to determine interface link state %s, " "output %s, erro %s" % (self._iface_name, out, err)) return out == up_str
def __init__(self, iface, ip_address, netmask): """ Create a network interface with the provided configuration Args: iface: iface name ip_address: string address netmask: Netmask TODO: Support v6. """ self._iface = iface self._ip_address = ip_address self._netmask = netmask ip_cidr = "%s/%s" % (self._ip_address, Interface.dotdec_to_cidr(self._netmask)) args = ["ip", "addr", "add", ip_cidr, "dev", self._iface] ret, _, _ = util.start_process(args) if ret: raise OvsException("Failed to create interface %s" % self._iface) self._valid = True
def test_add_meter_flows(self): from ovstest import util from magma.pkt_tester.topology_builder import OvsException self._generate_topology() self.controller_thread.start() self._wait_for_controller("MeterController") # clear out any existing in_blocks and set up for the test in_net = self.TEST_NETS[self.SRC_PORT] # clear out existing net block to of port mappings for k in list(self.mc.IPBLOCK_TO_OFPORT.keys()): del self.mc.IPBLOCK_TO_OFPORT[k] self.mc.IPBLOCK_TO_OFPORT[in_net] = self._port_no[self.SRC_PORT] self._setup_ovs() self._wait_for_datapath() ret, out, err = util.start_process(["ovs-ofctl", "dump-flows", self.TEST_BRIDGE]) dpid = list(self.mc.datapaths.keys())[0] self.mc._poll_stats(self.mc.datapaths[dpid]) time.sleep(0.5) # give the vswitch some time to respond # check if we're tracking usage for each user # it should be zero since there's no traffic for sid in self.mc.ip_to_sid.values(): self.assertTrue(sid in self.mc.usage) ur = self.mc.usage[sid] self.assertTrue(ur.bytes_tx == 0) self.assertTrue(ur.bytes_rx == 0) self.assertTrue(ur.pkts_tx == 0) self.assertTrue(ur.pkts_rx == 0)