def process_counter_read(switch_id, entry): # Get the counter (register) object from the database. counter_id = entry.counter_id counter = SwitchConf.getRegisterById(switch_id, counter_id) if counter is False: code = grpc.StatusCode.NOT_FOUND message = "Counter with id {} not found".format(counter_id) return (p4runtime_pb2.ReadResponse(), code, message) ServerConfig.print_debug( "Processing read request for counter {} from switch id {}".format( counter.reg_name, counter.switch_id)) data = p4_regs_api.reg_read(counter.switch_id, counter.reg_name, entry.index.index) if data is False: code = grpc.StatusCode.NOT_FOUND message = "Failed reading data from counter '{}'".format( counter.reg_name) return (p4runtime_pb2.ReadResponse(), code, message) # Create and fill the counter read response. response = p4runtime_pb2.ReadResponse() resp_entity = response.entities.add() resp_entity.counter_entry.counter_id = counter_id + 10 resp_entity.counter_entry.index.index = entry.index.index code = grpc.StatusCode.OK message = None return (response, code, message)
def main(): global dev_id host = ServerConfig.HOST server_port = ServerConfig.SERVER_PORT with open(ServerConfig.SERVER_CERTIFICATE, "rb") as file: trusted_certs = file.read() credentials = grpc.ssl_channel_credentials(root_certificates=trusted_certs) channel = grpc.secure_channel("{}:{}".format(host, server_port), credentials) client = P4RuntimeClient() streamC = client.StreamChannel() while True: try: packet = next(streamC) # we will only process packet-ins from l2 (check device id) if packet.HasField("packet") and packet.packet.metadata[ 0].metadata_id == dev_id: print "Received Packet inf from switch {}".format( packet.packet.metadata[0].metadata_id) if packet.HasField("other"): if packet.other.value == "\n\014Auth success": ServerConfig.print_debug( "Received authentication response from server:") ServerConfig.print_debug(packet) except IndexError: continue
def process_register_read(switch_id, entry): # Get the register object from the database. register_id = entry.register_id register = SwitchConf.getRegisterById(switch_id, register_id) if register is False: code = grpc.StatusCode.NOT_FOUND message = "Register with id {} not found".format(register_id) return (p4runtime_pb2.ReadResponse(), code, message) # TODO: finish this when testing is possible. ServerConfig.print_debug( "Processing read request for register {} from switch id {}".format( register.reg_name, register.switch_id)) data = p4_regs_api.reg_read(register.switch_id, register.reg_name, entry.index.index) if data is False: code = grpc.StatusCode.NOT_FOUND message = "Failed reading data from register '{}'".format( register.reg_name) return (p4runtime_pb2.ReadResponse(), code, message) # Create and fill the register read response. response = p4runtime_pb2.ReadResponse() resp_entity = response.entities.add() resp_entity.register_entry.register_id = register_id resp_entity.register_entry.index.index = entry.index.index resp_entity.register_entry.data.enum_value = bytes(data) code = grpc.StatusCode.OK message = None return (response, code, message)
def authenticate(peer_key): global _connections _connections[peer_key].state = Connection.CLIENT_AUTHENTICATED ServerConfig.print_debug("Authenticated {} (user id {})".format( _connections[peer_key].user.user_name, _connections[peer_key].user.user_id)) return
def remove(peer_key): global _connections if peer_key in _connections: ServerConfig.print_debug( "Removed {} (user id {}) from ConnectionArray".format( _connections[peer_key].user.user_name, _connections[peer_key].user.user_id)) del _connections[peer_key] return
def add(peer_key, user_name): global _connections if peer_key not in _connections: user = Auth.getUserByName(user_name) _connections[peer_key] = Connection(user) ServerConfig.print_debug( "Added {} (user id {}) to ConnectionArray".format( _connections[peer_key].user.user_name, _connections[peer_key].user.user_id)) return
def reg_write(switch_id, reg_name, index, value): if switch_id not in p4_externs_dict: ServerConfig.print_debug( "Failed reading register: switch id {} not found in p4_externs_dict" .format(switch_id)) return False address = get_address(switch_id, reg_name, index) return libsume.regwrite(address, value) if address != False else False
def hexify_key(table, key_list): ServerConfig.print_debug( "Calling hexify_key for switch id {}, table id {}, key list {}". format(table.switch_id, table.table_id, key_list)) fields = PXTable.extract_fields(table) field_vals = key_list ServerConfig.print_debug( "Table match fields: {}, supplied values: {}".format( fields, field_vals)) return PXTable._hexify(field_vals, fields)
def table_cam_add_entry(switch, table, action, keys, action_data): ServerConfig.print_debug("Processing table_cam_add_entry: switch {}(id {}), table {}(id {}), keys {}, action {}(id {}), action_data {}".format(switch.switch_name, switch.switch_id, table.table_name, table.table_id, keys, action.action_name, action.action_id, action_data)) # TODO: change this return value. if not check_valid_cam_table_name(table): return ("NA", "NA") key = PXTable.hexify_key(table, keys) value = PXTable.hexify_value(table, action, action_data) ServerConfig.print_debug("table_cam_add_entry: table id {}, key {:X}, value {:X}".format(table.table_id, key, value)) rc = libcam_dict[switch.switch_id].cam_add_entry(table.table_id, "{:X}".format(key), "{:X}".format(value)) print libcam_dict[switch.switch_id].cam_error_decode(rc)
def table_lpm_verify_dataset(switch_id, table_name, filename): ServerConfig.print_debug("Processing table_lpm_verify_dataset for switch id {} and table name {}".format(switch_id, table_name)) switch_table = SwitchConf.getSwitchTableByName(switch_id, table_name) if switch_table is False: return "NA", "NA" if not check_valid_lpm_table_name(switch_table.switch_id, switch_table.table_id): return return liblpm_dict[switch_table.switch_id].lpm_verify_dataset(switch_table.table_id, filename)
def hexify_value(table, action, action_data): ServerConfig.print_debug( "Calling hexify_value for switch id {}, table id {}, action {}, data {}" .format(table.switch_id, table.table_id, action.action_name, action_data)) fields = PXTable.extract_action_fields(action) field_vals = [action.action_id] + action_data ServerConfig.print_debug( "Table action fields: {}, supplied values: {}".format( fields, field_vals)) return PXTable._hexify(field_vals, fields)
def table_cam_get_size(switch_id, table_name): ServerConfig.print_debug("Processing table_cam_get_size for switch id {} and table name {}".format(switch_id, table_name)) switch_table = SwitchConf.getSwitchTableByName(switch_id, table_name) if switch_table is False: return "NA", "NA" if not check_valid_cam_table_name(switch_table.switch_id, switch_table.table_id): return 0 return libcam_dict[switch_table.switch_id].cam_get_size(switch_table.table_id)
def table_lpm_set_active_lookup_bank(switch_id, table_name, bank): ServerConfig.print_debug("Processing table_lpm_set_active_lookup_bank for switch id {} and table name {}".format(switch_id, table_name)) switch_table = SwitchConf.getSwitchTableByName(switch_id, table_name) if switch_table is False: return "NA", "NA" if not check_valid_lpm_table_name(switch_table.switch_id, switch_table.table_id): return rc = liblpm_dict[switch_table.switch_id].lpm_set_active_lookup_bank(switch_table.table_id, bank) ServerConfig.print_debug(liblpm_dict[switch_table.switch_id].lpm_error_decode(rc))
def table_tcam_erase_entry(switch_id, table_name, addr): ServerConfig.print_debug("Processing table_tcam_erase_entry for switch id {} and table name {}".format(switch_id, table_name)) switch_table = SwitchConf.getSwitchTableByName(switch_id, table_name) if switch_table is False: return "NA", "NA" if not check_valid_tcam_table_name(switch_table.switch_id, switch_table.table_id): return rc = libtcam_dict[switch_table.switch_id].tcam_erase_entry(switch_table.table_id, addr) ServerConfig.print_debug(libtcam_dict[switch_table.switch_id].tcam_error_decode(rc))
def table_cam_delete_entry(switch_id, table_name, keys): ServerConfig.print_debug("Processing table_cam_delete_entry: switch_id {}, table {}, keys {}".format(switch_id, table_name, keys)) switch_table = SwitchConf.getSwitchTableByName(switch_id, table_name) if switch_table is False: return "NA", "NA" if not check_valid_cam_table_name(switch_table.switch_id, switch_table.table_id): return key = PXTable.hexify_key(switch_table.switch_id, switch_table.table_id, keys) ServerConfig.print_debug("table_cam_delete_entry: switch_table.table_id {}, key {:X}".format (switch_table.table_id, key)) rc = libcam_dict[switch_table.switch_id].cam_delete_entry(switch_table.table_id, "{:X}".format(key)) print libcam_dict[switch_table.switch_id].cam_error_decode(rc)
def table_tcam_verify_entry(switch_id, table_name, addr, keys, masks, action_name, action_data): ServerConfig.print_debug("Processing table_tcam_verify_entry for switch id {} and table name {}".format(switch_id, table_name)) switch_table = SwitchConf.getSwitchTableByName(switch_id, table_name) if switch_table is False: return "NA", "NA" if not check_valid_tcam_table_name(switch_table.switch_id, switch_table.table_id): return mask = PXTable.hexify_mask(switch_table.switch_id, switch_table.table_id, masks) key = PXTable.hexify_key(switch_table.switch_id, switch_table.table_id, keys) value = PXTable.hexify_value(switch_table.switch_id, switch_table.table_id, action_name, action_data) return libtcam_dict[switch_table.switch_id].tcam_verify_entry(switch_table.table_id, addr, "{:X}".format(key), "{:X}".format(mask), "{:X}".format(value))
def WriteTableEntry(self, update_type, table, match_key, action_data): global dev_id request = p4runtime_pb2.WriteRequest() request.device_id = dev_id request.election_id.low = 1 update = request.updates.add() update.type = update_type update.entity.table_entry.table_id = table update.entity.table_entry.is_default_action = 1 update.entity.table_entry.action.action.action_id = 1 matches = update.entity.table_entry.match.add() matches.field_id = 1 matches.exact.value = bytes(match_key) act = update.entity.table_entry.action.action.params.add() act.param_id = 2 act.value = bytes(action_data) ServerConfig.print_debug("Sending table write request to server:") ServerConfig.print_debug(request) try: self.stub.Write(request) except grpc.RpcError as error: ServerConfig.print_debug("An error ocurred during a 'write' execution!") ServerConfig.print_debug("{}: {}".format(error.code().name, error.details())) return
def process_write_request(self, request, context): peer_key = context.peer() username = ConnectionArray.getUsername(peer_key) ServerConfig.print_debug( "Received write request from peer {}({}):".format( peer_key, username)) ServerLog.print_log("Received write request (%s): %.9f" % (username, time.time())) response = request # Verify if the user is authenticated. if ConnectionArray.isAuthenticated(peer_key) is False: context.set_code(grpc.StatusCode.UNAUTHENTICATED) context.set_details( "User {} is not authenticated".format(username)) return response # Get the switch object from memory. switch = SwitchConf.getSwitchById(request.device_id) if switch == False: context.set_code(grpc.StatusCode.NOT_FOUND) context.set_details( "Switch with id {} not found".format(switch_id)) return response # Verify permissions for request_update in request.updates: if request_update.entity.HasField("table_entry"): # Verify if the user has permission to write table entries into the requested switch. if ConnectionArray.verifyPermission( context, switch, PermEnum.DEVICE_WRITE | PermEnum.FLOWRULE_WRITE) is False: context.set_code(grpc.StatusCode.PERMISSION_DENIED) context.set_details( "User {} does not have permission to write table entries into switch {}" .format(username, switch.switch_name)) return response if switch.switch_type == SwitchTypeEnum.TYPE_BMV2: response = RPC_mgmt.process_write_request_bmv2(request) elif switch.switch_type == SwitchTypeEnum.TYPE_PVS: response = RPC_mgmt.process_write_request_pvs(request) ServerLog.print_log("Write Request success (%s): %.9f" % (username, time.time())) return response
def table_cam_read_entry(switch, table, keys): ServerConfig.print_debug("Processing table_cam_read_entry: switch {}(id {}), table {}(id {}), keys {}".format(switch.switch_name, switch.switch_id, table.table_name, table.table_id, keys)) # TODO: change this return value. if not check_valid_cam_table_name(table): return ("NA", "NA") key = PXTable.hexify_key(table, keys) hex_key_buf = create_string_buffer("{:X}".format(key)) value = create_string_buffer(1024) # TODO: Fix this ... Must be large enough to hold entire value found = create_string_buffer(10) # Should only need to hold "True" or "False" ServerConfig.print_debug("table_cam_read_entry: table id {}, key {}, key_hex_buf {}".format(table.table_id, key, hex_key_buf)) rc = libcam_dict[switch.switch_id].cam_read_entry(table.table_id, hex_key_buf, value, found) print libcam_dict[switch.switch_id].cam_error_decode(rc) return (found.value, value.value)
def reg_read(switch_id, reg_name, index): if switch_id not in p4_externs_dict: ServerConfig.print_debug( "Failed reading register: switch id {} not found in p4_externs_dict" .format(switch_id)) return False # print "REGISTERS FROM SWITCH ID {}: {}\n".format(switch_id, p4_externs_dict[switch_id].keys()) # print "KEYS FROM '{}' REGISTER: {}\n".format(reg_name, p4_externs_dict[switch_id][reg_name].keys()) # print "CONTROL WIDTH FOR REGISTER '{}': {}\n".format(reg_name, p4_externs_dict[switch_id][reg_name]["control_width"]) address = get_address(switch_id, reg_name, index) # print "READ ADDRESS: {}\n".format(address) return libsume.regread(address) if address != False else False
def process_table_read(peer_key, username, switch, entry): # Get the switch table object from the database. table_id = entry.table_id try: table = SwitchConf.table_dict[switch.switch_id, table_id] except KeyError: code = grpc.StatusCode.NOT_FOUND message = "Table with id {} not found".format(table_id) return (p4runtime_pb2.ReadResponse(), code, message) # Check the table type. match = entry.match[0] if not match.HasField("exact"): code = grpc.StatusCode.UNIMPLEMENTED message = "The requested table type is not supported" return (p4runtime_pb2.ReadResponse(), code, message) # Necessary match manipulations. match = entry.match[0] match_key = entry.match[0].exact.value match_key = re.sub('match_key', '[match_key]', match_key) match_key = match_key.split() match_key = ast.literal_eval(json.dumps(match_key)) # Read the data from the requested table entry. ServerConfig.print_debug( "Processing read request from {}({}) for table {}, switch {}". format(peer_key, username, table.table_name, switch.switch_name)) (found, data) = p4_tables_api.table_cam_read_entry(switch, table, match_key) ServerConfig.print_debug("Entry found: {}, data: {}\n".format( found, data)) # Create and fill the table read response. # Note that the action parameter id is hardcoded. response = p4runtime_pb2.ReadResponse() resp_entity = response.entities.add() resp_entity.table_entry.table_id = table.table_id resp_match = resp_entity.table_entry.match.add() resp_match.field_id = match.field_id resp_match.exact.value = match.exact.value bin_data = bin(int(data, 16))[2:] if len(bin_data) % 4: padding = 4 - (len(bin_data) % 4) bin_data = "0" * padding + bin_data resp_entity.table_entry.action.action.action_id = int(bin_data[0:4], 2) resp_action = resp_entity.table_entry.action.action.params.add() resp_action.param_id = 2 resp_action.value = bin_data[4:] ServerConfig.print_debug(response) code = grpc.StatusCode.OK message = None return (response, code, message)
def get_address(switch_id, reg_name, index): # cond = reg_name not in p4_externs_dict[switch_id].keys() or "control_width" not in p4_externs_dict[switch_id][reg_name].keys() or p4_externs_dict[switch_id][reg_name]["control_width"] < 0 if reg_name not in p4_externs_dict[switch_id].keys(): ServerConfig.print_debug( "Failed getting register read address: register {} not found". format(reg_name)) return False if "control_width" not in p4_externs_dict[switch_id][reg_name].keys(): ServerConfig.print_debug( "Failed getting register read address: register {} does not have 'control_width' field" .format(reg_name)) return False if p4_externs_dict[switch_id][reg_name]["control_width"] < 0: ServerConfig.print_debug( "Failed getting register read address: register {} has negative 'control_width' field" .format(reg_name)) return False # This is handled differently from the original API. if "base_addr" not in p4_externs_dict[switch_id][reg_name].keys(): ServerConfig.print_debug( "Failed getting register read address: register {} does not have 'base_addr' field" .format(reg_name)) return False addressable_depth = 2**p4_externs_dict[switch_id][reg_name][ "control_width"] if index >= addressable_depth or index < 0: ServerConfig.print_debug( "Failed getting register read address: index {}[{}] out of bounds". format(reg_name, index)) return False return p4_externs_dict[switch_id][reg_name]["base_addr"] + index
def process_setPipe(request, context): ServerConfig.print_debug( "Method process_setPipe called from client...") switch_id = request.device_id switch = SwitchConf.getSwitchById(switch_id) if switch is False: ServerConfig.print_debug( "Switch with id {} not found".format(switch_id)) return code_pb2.NOT_FOUND global p4_cookie response = request p4_cookie = response.config.cookie response.device_id = request.device_id response.role_id = request.role_id p4info = None p4_device_config = None config = p4runtime_pb2.ForwardingPipelineConfig() if p4info: config.p4info.CopyFrom(p4info) if p4_device_config: config.p4_device_config = p4_device_config.SerializeToString() response.action = p4runtime_pb2.SetForwardingPipelineConfigRequest.VERIFY_AND_COMMIT return p4runtime_pb2.SetForwardingPipelineConfigResponse()
def WriteRegisterEntry(self, register_id, index, value): global dev_id request = p4runtime_pb2.WriteRequest() request.device_id = dev_id request.election_id.low = 1 update = request.updates.add() update.type = p4runtime_pb2.Update.MODIFY update.entity.register_entry.register_id = register_id update.entity.register_entry.index.index = index update.entity.register_entry.data.enum_value = bytes(value) ServerConfig.print_debug("Sending register write request to server:") ServerConfig.print_debug(request) try: self.stub.Write(request) except grpc.RpcError as error: ServerConfig.print_debug("An error ocurred during a 'write' execution!") ServerConfig.print_debug("{}: {}\n".format(error.code().name, error.details())) return
def recv_packet(self, pktlen, packet_data, timestamp): switch_id = ord(packet_data[0]) input_port = ord(packet_data[1]) payload = packet_data[2:] switch = SwitchConf.getSwitchById(switch_id) if switch is not False: ServerConfig.print_debug("Packet {} ----------".format(self.packet_count)) ServerConfig.print_debug("Packet-in arrived at {} from Switch {} (Switch ID = {})".format(timestamp, switch.switch_name, str(switch.switch_id))) ServerConfig.print_debug("Preparing to send to the control plane, switch id {}, input port {}".format(switch_id, input_port)) # print "Raw Data: {}".format(hexlify(payload)) # we need to do it quickly # else: # print "Error retrieving Switch ID {}".format(switch_id) self.output [0] = switch_id self.output [1] = struct.pack("Q", input_port) self.output [2] = payload self.packet_count += 1
def recv_packet(self, pktlen, packet_data, timestamp): packet_ok = True switch_id = ord(packet_data[0]) input_port = ord(packet_data[1]) payload = packet_data[2:] #payload = packet_data[0:] #switch_id = ord(packet_data[-3]) #input_port = ord(packet_data[-1]) switch = SwitchConf.getSwitchById(switch_id) if switch is not False: ServerConfig.print_debug("Packet {} ----------".format( self.packet_count)) ServerConfig.print_debug( "Packet-in arrived at {} from Switch {} (Switch ID = {})". format(timestamp, switch.switch_name, str(switch.switch_id))) ServerConfig.print_debug( "Preparing to send to the control plane, switch id {}, input port {}" .format(switch_id, input_port)) else: print "ID %d - No found" % switch_id packet_ok = False if input_port != 1: print "Invalid Input Port: %d" % input_port packet_ok = False self.output[0] = switch_id self.output[1] = struct.pack("h", input_port) self.output[2] = payload if packet_ok: self.packet_count += 1 else: self.output[0] = -1
import sys eth_src = "00:15:4d:13:61:49" ip_src = "10.0.0.1" eth_dst = "00:15:4d:13:61:07" ip_dst = "10.0.0.1" vlan_id = 1 dst_iface = ServerConfig.PACKETIN_IFACE class Metadata(Packet): name = "MetadataPacket" fields_desc = [XByteField("metadata_id", 1), XByteField("port", 1)] metadata = Metadata(metadata_id=1, port=1) eth = Ether(dst=eth_dst, src=eth_src) vlan = Dot1Q(vlan=vlan_id) ip = IP(src=ip_src, dst=ip_dst) icmp = ICMP() ServerConfig.print_debug( "Preparing packet-in from {} ({}) => {} ({}) type IPv4/ICMP (vlan={}) over iface {}" .format(eth_src, ip_src, eth_dst, ip_dst, vlan_id, dst_iface)) packet = metadata / eth / vlan / ip / icmp sendp(packet, iface=dst_iface)
def ReadTableEntry(self, table, match_key): global dev_id request = p4runtime_pb2.ReadRequest() request.device_id = dev_id entity = request.entities.add() entity.table_entry.table_id = table matches = entity.table_entry.match.add() matches.field_id = 1 matches.exact.value = bytes(match_key) ServerConfig.print_debug("Sending table read request to server:") ServerConfig.print_debug(request) try: for response in self.stub.Read(request): ServerConfig.print_debug("Table read response received from server:") ServerConfig.print_debug(response) except grpc.RpcError as error: ServerConfig.print_debug("An error occured during a 'read' execution!") ServerConfig.print_debug("{}: {}\n".format(error.code().name, error.details())) return
def main(): host = ServerConfig.HOST server_port = ServerConfig.SERVER_PORT with open(ServerConfig.SERVER_CERTIFICATE, "rb") as file: trusted_certs = file.read() credentials = grpc.ssl_channel_credentials(root_certificates=trusted_certs) channel = grpc.secure_channel("{}:{}".format(host, server_port), credentials) client = P4RuntimeClient() streamC = client.StreamChannel() tables_initialized = False while True: try: packet = next(streamC) if packet.HasField("packet") and packet.packet.metadata[0].metadata_id == dev_id: ServerConfig.print_debug("Received packet:") ServerConfig.print_debug("Payload: {}".format(hexlify(packet.packet.payload))) ServerConfig.print_debug("Switch id: {}".format(packet.packet.metadata[0].metadata_id)) ServerConfig.print_debug("Input port: {}\n".format(hexlify(packet.packet.metadata[0].value))) if packet.HasField("other"): if packet.other.value == "\n\014Auth success": ServerConfig.print_debug("Received authentication response from server:") ServerConfig.print_debug(packet) # Prepare an arbitration request. client.streamChannelRequest = p4runtime_pb2.StreamMessageRequest() client.streamChannelRequest.arbitration.device_id = 1 client.streamChannelRequest.arbitration.role.id = 1 client.sendRequest = True if packet.HasField("arbitration"): ServerConfig.print_debug("Received arbitration response from server:") ServerConfig.print_debug(packet) if tables_initialized is False: for mac in forward_table_dict: client.WriteTableEntry(p4runtime_pb2.Update.INSERT, FORWARD, mac, forward_table_dict[mac]) # client.ReadTableEntry(FORWARD, mac) tables_initialized = True while True: client.ReadRegisterEntry(2, 0) client.WriteRegisterEntry(2, 0, 10) client.ReadRegisterEntry(2, 0) sleep(2) except IndexError: continue
def ReadCounterEntry(self, counter_id, index): global dev_id request = p4runtime_pb2.ReadRequest() request.device_id = dev_id entity = request.entities.add() entity.counter_entry.counter_id = counter_id entity.counter_entry.index.index = index ServerConfig.print_debug("Sending counter read request to server:") ServerConfig.print_debug(request) try: for response in self.stub.Read(request): ServerConfig.print_debug("Read counter response received from server:") ServerConfig.print_debug(response) except grpc.RpcError as error: ServerConfig.print_debug("An error occured during a 'read' execution!") ServerConfig.print_debug("{}: {}\n".format(error.code().name, error.details())) return