Exemplo n.º 1
0
def parseGrpcErrorBinaryDetails(grpc_error):
    if grpc_error.code() != grpc.StatusCode.UNKNOWN:
        return None

    error = None
    # The gRPC Python package does not have a convenient way to access the
    # binary details for the error: they are treated as trailing metadata.
    for meta in grpc_error.trailing_metadata():
        if meta[0] == "grpc-status-details-bin":
            error = status_pb2.Status()
            error.ParseFromString(meta[1])
            break
    if error is None:  # no binary details field
        return None
    if len(error.details) == 0:
        # binary details field has empty Any details repeated field
        return None

    indexed_p4_errors = []
    for idx, one_error_any in enumerate(error.details):
        p4_error = p4runtime_pb2.Error()
        if not one_error_any.Unpack(p4_error):
            raise P4RuntimeErrorFormatException(
                "Cannot convert Any message to p4.Error")
        if p4_error.canonical_code == code_pb2.OK:
            continue
        indexed_p4_errors += [(idx, p4_error)]

    return indexed_p4_errors
Exemplo n.º 2
0
 def next(self):
     while self.idx < len(self.errors):
         p4_error = p4runtime_pb2.Error()
         one_error_any = self.errors[self.idx]
         if not one_error_any.Unpack(p4_error):
             raise P4RuntimeErrorFormatException(
                 "Cannot convert Any message to p4.Error")
         if p4_error.canonical_code == code_pb2.OK:
             continue
         v = self.idx, p4_error
         self.idx += 1
         return v
     raise StopIteration
Exemplo n.º 3
0
    def process_write_request_pvs(request):
        switch = SwitchConf.getSwitchById(request.device_id)

        for request_update in request.updates:
            if request_update.entity.HasField("table_entry"):

                switch_id = switch.switch_id
                table_id = request_update.entity.table_entry.table_id

                switch_table = SwitchConf.getSwitchTableById(
                    switch.switch_id, table_id)
                if switch_table == False:
                    ontext.set_code(grpc.StatusCode.NOT_FOUND)
                    context.set_details(
                        "Table with id {} from switch {} not found".format(
                            table_id, switch.switch_name))
                    return response

                action_id = request_update.entity.table_entry.action.action.action_id

                try:
                    table_action = SwitchConf.table_action_dict[switch_id,
                                                                table_id,
                                                                action_id]
                except KeyError:
                    context.set_code(grpc.StatusCode.NOT_FOUND)
                    context.set_details(
                        "Action with id {} from table {}, switch {} not found".
                        format(action_id, switch_table.table_name,
                               switch.switch_name))
                    return response

                # Necessary match manipulations.
                match = request_update.entity.table_entry.match[0]
                match_key = request_update.entity.table_entry.match[
                    0].exact.value
                match_key = match_key.split()

                # Necessary action manipulations
                action_params = request_update.entity.table_entry.action.action.params
                action_key = action_params[0].value
                action_key = action_key.split()

                check_bytestr = re.match("[\\x00-\\x1F\\x80-\\xFF]",
                                         match_key[0])
                if check_bytestr:
                    # Match value contains a byte string
                    # Need to decode it
                    match_hexvalue = hexlify(match_key[0])
                    action_hexvalue = hexlify(action_key[0])
                    if convert.matchesMac(match_hexvalue) == True:
                        decoded_key = convert.decodeMac(match_key[0])
                        match_key = []
                        match_key.insert(0, decoded_key)
                    if convert.matchesPort(action_hexvalue) == True:
                        decoded_port = convert.decodePort(action_hexvalue)
                        action_key = []
                        action_key.insert(0, decoded_port)
                    if convert.matchesIPv4(match_key) == True:
                        decoded_key = convert.decodeIpv4(match_key[0])
                        match_key = []
                        match_key.insert(0, decoded_key)
                else:
                    #match contains a normal string
                    match_key = ast.literal_eval(json.dumps(match_key))
                    action_key = ast.literal_eval(json.dumps(action_key))

                # Insert an entry.
                if request_update.type == p4runtime_pb2.Update.INSERT:
                    if match.HasField("exact"):
                        p4_tables_api.table_cam_add_entry(
                            switch, switch_table, table_action, match_key,
                            action_key)

                # Update an entry.
                elif request_update.type == p4runtime_pb2.Update.MODIFY:
                    # First: Read the entry provided by the client to see its existance in the switch.
                    # TODO: hardcoded yet, need to remove dependence on switch specific p4_tables_api.
                    if match.HasField("exact"):
                        # key = map(p4_px_tables.convert_to_int, match_key)
                        (found, val) = p4_tables_api.table_cam_read_entry(
                            switch_table.switch_id, switch_table.table_name,
                            match_key)
                        if found != "False":
                            # p4_tables_api.table_cam_delete_entry(switch_table.switch_id, switch_table.table_name, match_key)
                            # Second: Modify the existing entry with the values stored in the variables.
                            ServerConfig.print_debug(
                                "Match key: {} exists in table {} of switch {}: found {}, val {}. Updating..."
                                .format(match_key, switch_table.table_name,
                                        switch.switch_name, found, val))
                            p4_tables_api.table_cam_add_entry(
                                switch_table.switch_id,
                                switch_table.table_name, match_key,
                                action_name, action_key)
                        else:
                            ServerConfig.print_debug(
                                "Error: Match key {} not found in table {} of switch {}"
                                .format(match_key, switch_table.table_name,
                                        switch.switch_name))
                            response = p4runtime_pb2.Error()
                            response.canonical_code = code_pb2.NOT_FOUND
                            return response

                # Delete an entry.
                elif request_update.type == p4runtime_pb2.Update.DELETE:

                    # First: Use read entry which will check the existence, then delete it.
                    if match.HasField("exact"):
                        # key = map(p4_px_tables.convert_to_int, match_key)
                        (found, val) = p4_tables_api.table_cam_read_entry(
                            switch_table.switch_id, switch_table.table_name,
                            match_key)
                        if found != "False":
                            ServerConfig.print_debug(
                                "Match key: {} exists in table {} of switch {}: found {}, val {}. Deleting..."
                                .format(match_key, switch_table.table_name,
                                        switch.switch_name, found, val))
                            p4_tables_api.table_cam_delete_entry(
                                switch_table.switch_id,
                                switch_table.table_name, match_key)
                        else:
                            ServerConfig.print_debug(
                                "Error: Match key {} not found in table {} of switch {}"
                                .format(match_key, switch_table.table_name,
                                        switch.switch_name))

                else:
                    context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
                    context.set_details(
                        "Update code {} is invalid. Please inform a valid one (INSERT, MODIFY OR DELETE"
                        .format(update[0].type))
                    return response

            # TODO: refactor.
            elif request_update.entity.HasField("register_entry"):

                # Verify if the user has permission to write into registers from the requested switch.
                if ConnectionArray.verifyPermission(
                        context, switch, PermEnum.DEVICE_WRITE
                        | PermEnum.RESOURCE_WRITE) is False:
                    ServerConfig.print_debug(
                        "Error: user does not have permission to write into registers from switch '{}'"
                        .format(switch.switch_name))
                    context.set_code(grpc.StatusCode.PERMISSION_DENIED)
                    context.set_details(
                        "User does not have permission to write into registers from switch '{}'"
                        .format(switch.switch_name))
                    return response

                register_id = request_update.entity.register_entry.register_id
                register = SwitchConf.getRegisterById(switch_id, register_id)

                result = p4_regs_api.reg_write(
                    register.switch_id, register.reg_name,
                    request_update.entity.register_entry.index.index,
                    int(request_update.entity.register_entry.data.enum_value))
                return response

        return response