def produce_parser_topo_sorting(hlir): header_graph = Graph() def walk_rec(hlir, parse_state, prev_hdr_node, tag_stacks_index, visited): assert (isinstance(parse_state, p4.p4_parse_state)) for call in parse_state.call_sequence: call_type = call[0] if call_type == p4.parse_call.extract: hdr = call[1] if hdr.virtual: base_name = hdr.base_name current_index = tag_stacks_index[base_name] if current_index > hdr.max_index: return tag_stacks_index[base_name] += 1 name = base_name + "[%d]" % current_index hdr = hlir.p4_header_instances[name] # takes care of loops in parser (e.g. for TLV parsing) elif parse_state in visited: return if hdr not in header_graph: header_graph.add_node(hdr) hdr_node = header_graph.get_node(hdr) if prev_hdr_node: prev_hdr_node.add_edge_to(hdr_node) else: header_graph.root = hdr prev_hdr_node = hdr_node for branch_case, next_state in parse_state.branch_to.items(): if not next_state: continue if not isinstance(next_state, p4.p4_parse_state): continue walk_rec(hlir, next_state, prev_hdr_node, tag_stacks_index.copy(), visited | {parse_state}) start_state = hlir.p4_parse_states["start"] for pragma in start_state._pragmas: try: words = pragma.split() if words[0] != "header_ordering": continue except: # pragma: no cover continue sorting = process_forced_header_ordering(hlir, words[1:]) if sorting is None: # pragma: no cover LOG_CRITICAL("invalid 'header_ordering' pragma") return sorting walk_rec(hlir, start_state, None, defaultdict(int), set()) header_topo_sorting = header_graph.produce_topo_sorting() if header_topo_sorting is None: # pragma: no cover LOG_CRITICAL("could not produce topo sorting because of cycles") return header_topo_sorting
def produce_parser_topo_sorting(hlir): header_graph = Graph() def walk_rec(hlir, parse_state, prev_hdr_node, tag_stacks_index, visited): assert(isinstance(parse_state, p4.p4_parse_state)) for call in parse_state.call_sequence: call_type = call[0] if call_type == p4.parse_call.extract: hdr = call[1] if hdr.virtual: base_name = hdr.base_name current_index = tag_stacks_index[base_name] if current_index > hdr.max_index: return tag_stacks_index[base_name] += 1 name = base_name + "[%d]" % current_index hdr = hlir.p4_header_instances[name] # takes care of loops in parser (e.g. for TLV parsing) elif parse_state in visited: return if hdr not in header_graph: header_graph.add_node(hdr) hdr_node = header_graph.get_node(hdr) if prev_hdr_node: prev_hdr_node.add_edge_to(hdr_node) else: header_graph.root = hdr prev_hdr_node = hdr_node for branch_case, next_state in parse_state.branch_to.items(): if not next_state: continue if not isinstance(next_state, p4.p4_parse_state): continue walk_rec(hlir, next_state, prev_hdr_node, tag_stacks_index.copy(), visited | {parse_state}) start_state = hlir.p4_parse_states["start"] for pragma in start_state._pragmas: try: words = pragma.split() if words[0] != "header_ordering": continue except: # pragma: no cover continue sorting = process_forced_header_ordering(hlir, words[1:]) if sorting is None: # pragma: no cover LOG_CRITICAL("invalid 'header_ordering' pragma") return sorting walk_rec(hlir, start_state, None, defaultdict(int), set()) header_topo_sorting = header_graph.produce_topo_sorting() if header_topo_sorting is None: # pragma: no cover LOG_CRITICAL("could not produce topo sorting because of cycles") return header_topo_sorting
def produce_parser_topo_sorting(hlir): header_graph = Graph() def walk_rec(hlir, parse_state, prev_hdr_node, tag_stacks_index): assert(isinstance(parse_state, p4.p4_parse_state)) for call in parse_state.call_sequence: call_type = call[0] if call_type == p4.parse_call.extract: hdr = call[1] if hdr.virtual: base_name = hdr.base_name current_index = tag_stacks_index[base_name] if current_index > hdr.max_index: return tag_stacks_index[base_name] += 1 name = base_name + "[%d]" % current_index hdr = hlir.p4_header_instances[name] if hdr not in header_graph: header_graph.add_node(hdr) hdr_node = header_graph.get_node(hdr) if prev_hdr_node: prev_hdr_node.add_edge_to(hdr_node) else: header_graph.root = hdr; prev_hdr_node = hdr_node for branch_case, next_state in parse_state.branch_to.items(): if not next_state: continue if not isinstance(next_state, p4.p4_parse_state): continue walk_rec(hlir, next_state, prev_hdr_node, tag_stacks_index.copy()) start_state = hlir.p4_parse_states["start"] walk_rec(hlir, start_state, None, defaultdict(int)) header_topo_sorting = header_graph.produce_topo_sorting() # topo_sorting = [] # for hdr in header_topo_sorting: # topo_sorting.append(get_header_instance_name(hdr)) # dirty fix, to ensure that all tags in a stag are contiguous # this makes the (questionable) assumption that all those tags are # contiguous in the deparsed packet buckets = defaultdict(list) for header_instance in header_topo_sorting: base_name = header_instance.base_name buckets[base_name].append(header_instance) collapsed = [] for header_instance in header_topo_sorting: base_name = header_instance.base_name collapsed += buckets[base_name] buckets[base_name] = [] return collapsed
def produce_parser_topo_sorting(hlir): header_graph = Graph() def walk_rec(hlir, parse_state, prev_hdr_node, tag_stacks_index): assert (isinstance(parse_state, p4.p4_parse_state)) for call in parse_state.call_sequence: call_type = call[0] if call_type == p4.parse_call.extract: hdr = call[1] if hdr.virtual: base_name = hdr.base_name current_index = tag_stacks_index[base_name] if current_index > hdr.max_index: return tag_stacks_index[base_name] += 1 name = base_name + "[%d]" % current_index hdr = hlir.p4_header_instances[name] if hdr not in header_graph: header_graph.add_node(hdr) hdr_node = header_graph.get_node(hdr) if prev_hdr_node: prev_hdr_node.add_edge_to(hdr_node) else: header_graph.root = hdr prev_hdr_node = hdr_node for branch_case, next_state in parse_state.branch_to.items(): if not next_state: continue if not isinstance(next_state, p4.p4_parse_state): continue walk_rec(hlir, next_state, prev_hdr_node, tag_stacks_index.copy()) start_state = hlir.p4_parse_states["start"] walk_rec(hlir, start_state, None, defaultdict(int)) header_topo_sorting = header_graph.produce_topo_sorting() return header_topo_sorting
def produce_parser_topo_sorting(hlir): header_graph = Graph() def walk_rec(hlir, parse_state, prev_hdr_node, tag_stacks_index): assert(isinstance(parse_state, p4.p4_parse_state)) for call in parse_state.call_sequence: call_type = call[0] if call_type == p4.parse_call.extract: hdr = call[1] if hdr.virtual: base_name = hdr.base_name current_index = tag_stacks_index[base_name] if current_index > hdr.max_index: return tag_stacks_index[base_name] += 1 name = base_name + "[%d]" % current_index hdr = hlir.p4_header_instances[name] if hdr not in header_graph: header_graph.add_node(hdr) hdr_node = header_graph.get_node(hdr) if prev_hdr_node: prev_hdr_node.add_edge_to(hdr_node) else: header_graph.root = hdr prev_hdr_node = hdr_node for branch_case, next_state in parse_state.branch_to.items(): if not next_state: continue if not isinstance(next_state, p4.p4_parse_state): continue walk_rec(hlir, next_state, prev_hdr_node, tag_stacks_index.copy()) start_state = hlir.p4_parse_states["start"] walk_rec(hlir, start_state, None, defaultdict(int)) header_topo_sorting = header_graph.produce_topo_sorting() return header_topo_sorting