def _handle_o_call(self, sig, packet, bit_offset): op = sig[0] args = sig[1] if op == 'tLookup': resp = packet.metadata[args[0]] req = packet.metadata[args[1]] if self.table: resp.reset_values() self.table.lookup(req, resp) elif op == 'hInsert': length = args[0] if len(args) > 0 else len(self.header) packet.insert(length, bit_offset) elif op == 'hRemove': length = args[0] if len(args) > 0 else len(self.header) packet.remove(length, bit_offset) elif op == 'tInsert': mask = args[2] if len(args) > 2 else None if self.table: self.table.add_entry(args[0], args[1], mask) elif op == 'tRemove': mask = args[2] if len(args) > 2 else None if self.table: self.table.remove_entry(args[0], args[1], mask) else: raise BIRError("unknown build-in function: {}".format(op))
def _get_processor(self, name): if name in self.bir_control_flows.keys(): return self.bir_control_flows[name] elif name in self.bir_other_processors.keys(): return self.bir_other_processors[name] else: raise BIRError("unknown processor: {}".format(name))
def _get_basic_block(self, packet, bit_offset): for cond in self.basic_block: if isinstance(cond, str): return cond elif self.bir_parser.eval_cond(cond[0], self.header, packet, bit_offset): return cond[1] raise BIRError("didn't find basic_block!")
def _handle_m_call(self, sig, packet, bit_offset): if len(sig[1]) != 2: raise BIRError("M instructions require 2 arguments") op = sig[0] data_out = sig[1][0] data_in = sig[1][1] if op not in self.other_modules.keys(): raise BIRError("cannot find other_module: {}".format(sig[0])) module = self.other_modules[op] if data_out: data_out = packet.metadata[data_out] if data_in: # TODO: to ensure correctness, the data_in should be a copy of the # metadata instance. data_in = packet.metadata[data_in] module(data_in, data_out)
def process(self, packet, bit_offset): for inst in self.instructions: if inst[0] == 'V': self._handle_v_call(inst[1:], packet, bit_offset) elif inst[0] == 'O': self._handle_o_call(inst[1:], packet, bit_offset) elif inst[0] == 'M': self._handle_m_call(inst[1:], packet, bit_offset) else: raise BIRError("unknown instruction type: {}".format(inst[0]))
def _get_offset(self, packet, bit_offset): for cond in self.offset: if isinstance(cond, str) or isinstance(cond, int): return self.bir_parser.eval_inst(cond, self.header, packet, bit_offset) elif self.bir_parser.eval_cond(cond[0], self.header, packet, bit_offset): return self.bir_parser.eval_inst(cond[1], self.header, packet, bit_offset) raise BIRError("didn't find offset!")
def run(self): msg = "Processor {}: does not implement run()".format(self.name) raise BIRError(msg)
def process(self, packet, bit_offset=0): msg = "Processor {}: does not implement process()".format(self.name) raise BIRError(msg)