def __init__(self, qid, operator_id, keys, p4_raw_fields): super(P4MapInit, self).__init__('MapInit', qid, operator_id, keys, p4_raw_fields) # Add map init map_init_fields = list() for fld in self.keys: if fld == 'qid': map_init_fields.append( P4Field(layer=None, target_name="qid", sonata_name="qid", size=QID_SIZE)) elif fld == 'count': map_init_fields.append( P4Field(layer=None, target_name="count", sonata_name="count", size=COUNT_SIZE)) elif fld == 'index': map_init_fields.append( P4Field(layer=None, target_name="index", sonata_name="index", size=INDEX_SIZE)) else: map_init_fields.append( self.p4_raw_fields.get_target_field(fld)) # create METADATA object to store data for all keys meta_fields = list() for fld in map_init_fields: meta_fields.append((fld.target_name.replace(".", "_"), fld.size)) self.metadata = MetaData(self.operator_name, meta_fields) # create ACTION to initialize the metadata primitives = list() for fld in map_init_fields: sonata_name = fld.sonata_name target_name = fld.target_name meta_field_name = '%s.%s' % (self.metadata.get_name(), target_name.replace(".", "_")) if sonata_name == 'qid': # Assign query id to this field primitives.append(ModifyField(meta_field_name, qid)) elif sonata_name == 'count': primitives.append(ModifyField(meta_field_name, 0)) elif sonata_name == 'index': primitives.append(ModifyField(meta_field_name, 0)) else: # Read data from raw header fields and assign them to these meta fields primitives.append(ModifyField(meta_field_name, target_name)) self.action = Action('do_%s' % self.operator_name, primitives) # create dummy TABLE to execute the action self.table = Table(self.operator_name, self.action.get_name(), [], None, 1)
def mark_satisfied(self): primitives = list() primitives.append(ModifyField(self.satisfied_meta_field, 1)) primitives.append(ModifyField(self.clone_meta_field, 1)) self.actions['satisfied'] = Action('do_mark_satisfied_%i' % self.id, primitives) self.satisfied_table = Table('mark_satisfied_%i' % self.id, self.actions['satisfied'].get_name(), [], None, 1)
def append_out_header(self): primitives = list() primitives.append(AddHeader(self.out_header.get_name())) for fld in self.out_header.fields: primitives.append(ModifyField('%s.%s' % (self.out_header.get_name(), fld.target_name.replace(".", "_")), '%s.%s' % (self.meta_init_name, fld.target_name.replace(".", "_")))) self.actions['append_out_header'] = Action('do_add_out_header_%i' % self.id, primitives) self.out_header_table = Table('add_out_header_%i' % self.id, self.actions['append_out_header'].get_name(), [], None, 1)
def init_application(self, app): queries = dict() # define final header # TODO: Use new p4 layer object tmp = OutHeaders("final_header") tmp.fields = [P4Field(tmp, "delimiter", "delimiter", 32)] self.final_header = tmp primitives = list() primitives.append(AddHeader(self.final_header.get_name())) primitives.append(ModifyField('%s.delimiter' % self.final_header.get_name(), 0)) self.final_header_action = Action('do_add_final_header', primitives) self.final_header_table = Table('add_final_header', self.final_header_action.get_name(), [], None, 1) # define nop action self.nop_action = Action('_nop', NoOp()) nop_name = self.nop_action.get_name() # app metadata fields = list() for query_id in app: fields.append(('%s_%i' % (self.drop_meta_field, query_id), 1)) fields.append(('%s_%i' % (self.satisfied_meta_field, query_id), 1)) fields.append((self.clone_meta_field, 1)) self.metadata = MetaData('app_data', fields) meta_name = self.metadata.get_name() # action and table to init app metadata primitives = list() for field_name, _ in fields: primitives.append(ModifyField('%s.%s' % (self.metadata.get_name(), field_name), 0)) self.init_action = Action('do_init_app_metadata', primitives) self.init_action_table = Table('init_app_metadata', self.init_action.get_name(), [], None, 1) # transforms queries for query_id in app: self.logger.debug('create query pipeline for qid: %i' % (query_id)) parse_payload = app[query_id].parse_payload payload_fields = app[query_id].payload_fields read_register = app[query_id].read_register filter_payload = app[query_id].filter_payload filter_payload_str = app[query_id].filter_payload_str operators = app[query_id].operators query = P4Query(query_id, parse_payload, payload_fields, read_register, filter_payload, filter_payload_str, operators, nop_name, '%s.%s' % (meta_name, self.drop_meta_field), '%s.%s' % (meta_name, self.satisfied_meta_field), '%s.%s' % (meta_name, self.clone_meta_field), self.p4_raw_fields) queries[query_id] = query # define mirroring session self.mirror_session = MirrorSession(SESSION_ID, SPAN_PORT) # define report action that clones the packet and sends it to the stream processor fields = [self.metadata.get_name()] for query in queries.values(): fields.append(query.get_metadata_name()) self.field_list = FieldList('report_packet', fields) self.report_action = Action('do_report_packet', CloneIngressPktToEgress(self.mirror_session.get_session_id(), self.field_list.get_name())) self.report_action_table = Table('report_packet', self.report_action.get_name(), [], None, 1) return queries
def add_general_drop_action(self): self.actions['drop'] = Action('drop_%i' % self.id, (ModifyField(self.drop_meta_field, 1))) self.query_drop_action = self.actions['drop'].get_name()
def __init__(self, qid, operator_id, meta_init_name, keys, map_keys, map_values, func, p4_raw_fields): super(P4Map, self).__init__('Map', qid, operator_id, keys, p4_raw_fields) self.meta_init_name = meta_init_name self.map_keys = map_keys self.func = func self.map_values = map_values # Add map init map_fields = list() for fld in self.map_keys: if fld == 'qid': map_fields.append( P4Field(layer=None, target_name="qid", sonata_name="qid", size=QID_SIZE)) elif fld == 'count': map_fields.append( P4Field(layer=None, target_name="count", sonata_name="count", size=COUNT_SIZE)) else: map_fields.append(self.p4_raw_fields.get_target_field(fld)) map_fields_values = list() for fld in self.map_values: if fld == 'qid': map_fields_values.append( P4Field(layer=None, target_name="qid", sonata_name="qid", size=QID_SIZE)) elif fld == 'count': map_fields_values.append( P4Field(layer=None, target_name="count", sonata_name="count", size=COUNT_SIZE)) else: map_fields_values.append( self.p4_raw_fields.get_target_field(fld)) # create ACTION using the function primitives = list() if len(func) > 0: self.func = func if func[0] == 'mask' or not func[0]: for field in map_fields: mask_size = (func[1] / 4) mask = '0x' + ('f' * mask_size) + ( '0' * (HEADER_MASK_SIZE[field.target_name] - mask_size)) field_name = '%s.%s' % (self.meta_init_name, field.target_name.replace( ".", "_")) primitives.append(BitAnd(field_name, field_name, mask)) if func[0] == 'set' or not func[0]: for field in map_fields_values: field_name = '%s.%s' % (self.meta_init_name, field.target_name.replace( ".", "_")) primitives.append(ModifyField(field_name, func[1])) self.action = Action('do_%s' % self.operator_name, primitives) # create dummy TABLE to execute the action self.table = Table(self.operator_name, self.action.get_name(), [], None, 1)
def __init__(self, qid, operator_id, meta_init_name, drop_action, keys, values, threshold, read_register, p4_raw_fields): super(P4Reduce, self).__init__('Reduce', qid, operator_id, keys, p4_raw_fields) if threshold == '-1': self.threshold = int(THRESHOLD) else: self.threshold = int(threshold) self.read_register = read_register if self.read_register: self.out_headers += ['index'] else: self.out_headers += ['count'] # create METADATA to store index and value fields = [('value', REGISTER_WIDTH), ('index', REGISTER_NUM_INDEX_BITS)] self.metadata = MetaData(self.operator_name, fields) # create REGISTER to keep track of counts self.register = Register(self.operator_name, REGISTER_WIDTH, REGISTER_INSTANCE_COUNT) self.values = values # Add map init hash_init_fields = list() for fld in self.keys: if fld == 'qid': hash_init_fields.append( P4Field(layer=None, target_name="qid", sonata_name="qid", size=QID_SIZE)) elif fld == 'count': hash_init_fields.append( P4Field(layer=None, target_name="count", sonata_name="count", size=COUNT_SIZE)) elif fld == 'index': hash_init_fields.append( P4Field(layer=None, target_name="index", sonata_name="index", size=INDEX_SIZE)) else: hash_init_fields.append( self.p4_raw_fields.get_target_field(fld)) # create HASH for access to register hash_fields = list() for field in hash_init_fields: if '/' in field.sonata_name: self.logger.error('found a / in the key') raise NotImplementedError else: hash_fields.append( '%s.%s' % (meta_init_name, field.target_name.replace(".", "_"))) self.hash = HashFields(self.operator_name, hash_fields, 'crc16', REGISTER_NUM_INDEX_BITS) # name of metadata field where the index of the count within the register is stored self.index_field_name = '%s.index' % self.metadata.get_name() # name of metadata field where the count is kept temporarily self.value_field_name = '%s.value' % self.metadata.get_name() # create ACTION and TABLE to compute hash and get value primitives = list() primitives.append( ModifyFieldWithHashBasedOffset(self.index_field_name, 0, self.hash.get_name(), REGISTER_INSTANCE_COUNT)) primitives.append( RegisterRead(self.value_field_name, self.register.get_name(), self.index_field_name)) if self.values[0] == 'count': if self.threshold <= 1: self.threshold = '1' primitives.append( ModifyField(self.value_field_name, '%s + %i' % (self.value_field_name, 1))) else: target_fld = self.p4_raw_fields.get_target_field(self.values[0]) if self.threshold <= 1: self.threshold = '%s.%s' % ( meta_init_name, target_fld.target_name.replace(".", "_")) primitives.append( ModifyField( self.value_field_name, '%s + %s' % (self.value_field_name, '%s.%s' % (meta_init_name, target_fld.target_name.replace(".", "_"))))) primitives.append( RegisterWrite(self.register.get_name(), self.index_field_name, self.value_field_name)) self.init_action = Action('do_init_%s' % self.operator_name, primitives) table_name = 'init_%s' % self.operator_name self.init_table = Table(table_name, self.init_action.get_name(), [], None, 1) # create three TABLEs that implement reduce operation # if count <= THRESHOLD, update count and drop, table_name = 'drop_%s' % self.operator_name self.drop_table = Table(table_name, drop_action, [], None, 1) # if count == THRESHOLD, pass through with current count field_to_modified = None if not self.read_register: field_to_modified = ModifyField('%s.count' % meta_init_name, self.value_field_name) else: field_to_modified = ModifyField('%s.index' % meta_init_name, self.index_field_name) self.set_count_action = Action('set_count_%s' % self.operator_name, field_to_modified) table_name = 'first_pass_%s' % self.operator_name self.first_pass_table = Table(table_name, self.set_count_action.get_name(), [], None, 1) if not self.read_register: # if count > THRESHOLD, let it pass through with count set to 1 self.reset_count_action = Action( 'reset_count_%s' % self.operator_name, ModifyField('%s.count' % meta_init_name, 1)) table_name = 'pass_%s' % self.operator_name self.pass_table = Table(table_name, self.reset_count_action.get_name(), [], None, 1)