def gen_extract_header_2(hdrinst, hdrtype, w): if not hdrtype.is_vw: addError("generating extract header call", "fixed-width header extracted with two-param extract") return x = header_bit_width(hdrtype) w = format_expr(w)
def gen_extract_header_2(h, w): if not h.type.is_vw: addError("generating extract header call", "fixed-width header extracted with two-param extract") else: x = header_bit_width(h) w = format_expr(w)
def gen_extract_header_tmp_2(h, w): x = header_bit_width(h) w = format_expr(w)
def __exit__(self, type, value, traceback): global type_env for v in self.env_vars: del type_env[v] # forward declarations for externs for m in hlir16.objects['Method']: # TODO temporary fix for l3-routing-full, this will be computed later on with types({ "T": "struct uint8_buffer_s", "O": "unsigned", "HashAlgorithm": "int", }): t = m.type ret_type = format_type(t.returnType) args = ", ".join([format_expr(arg) for arg in t.parameters.parameters] + ['SHORT_STDPARAMS']) #[ extern ${ret_type} ${m.name}(${args}); for ctl in p4_ctls: #[ void control_${ctl.name}(STDPARAMS) #{ { #[ debug("Entering control $$[control]{ctl.name}...\n"); #[ uint32_t value32, res32; #[ (void)value32, (void)res32; #[ control_locals_${ctl.name}_t local_vars_struct; #[ control_locals_${ctl.name}_t* local_vars = &local_vars_struct; #[ pd->control_locals = (void*) local_vars; #= format_statement(ctl.body, ctl) #} }
def __exit__(self, type, value, traceback): global type_env for v in self.env_vars: del type_env[v] # objects for externs for m in hlir16.objects['Method']: # TODO temporary fix for l3-routing-full, this will be computed later on with types({ "T": "struct uint8_buffer_s", "O": "unsigned", "HashAlgorithm": "int", }): t = m.type ret_type = format_type(t.returnType) args = ", ".join([format_expr(arg) for arg in t.parameters.parameters] + [STDPARAMS]) #[ extern ${ret_type} ${m.name}(${args}); for pe in pipeline_elements: ctl = hlir16.objects.get(pe.expression.type.name, 'P4Control') if ctl is None: continue #[ void control_${pe.expression.type.name}(STDPARAMS) #{ { #[ debug("Entering control $$[control]{ctl.name}...\n"); #[ uint32_t value32, res32; #[ (void)value32, (void)res32; #[ control_locals_${pe.expression.type.name}_t control_locals_struct;
return hdrinst for s in parser.states: if not s.is_reachable: continue if s.name in ('accept', 'reject'): continue if s.selectExpression.node_type != 'SelectExpression': continue #{ static void parser_state_${s.name}_next_state(STDPARAMS) { #[ parser_state_t parameters = *pstate; bexpr = format_expr(s.selectExpression) prebuf, postbuf = statement_buffer_value() #[ $prebuf #= bexpr #[ $postbuf #} } #[ def state_component_name(s, idx, component): def methodcall_info(mc): m = mc.method if 'expr' not in m: return f'_{m.path.name}' hdrname = m.expr.member if 'member' in m.expr else m.expr.path.name method_name = m.member
#{ if (pd->payload_length > 0) { #[ dbg_bytes(pd->data + pd->parsed_length, pd->payload_length, " : " T4LIT(Payload,header) " is $${}{%d} bytes: ", pd->payload_length); #[ } else { #[ debug(" " T4LIT(:,status) " " T4LIT(Payload,header) " is " T4LIT(empty,status) "\n"); #} } elif s.name == 'reject': #[ debug(" " T4LIT(::,status) " Packet is $$[status]{}{dropped}\n"); #[ drop_packet(STDPARAMS_IN); else: b = s.selectExpression if b.node_type == 'PathExpression': #[ parser_state_${b.path.name}(STDPARAMS_IN); elif b.node_type == 'SelectExpression': bexpr = format_expr(b) prebuf, postbuf = statement_buffer_value() #[ $prebuf #= bexpr #[ $postbuf #} } #[ #[ void parse_packet(STDPARAMS) { #[ pd->parsed_length = 0; #[ pd->extract_ptr = pd->data; #[ parser_state_start(STDPARAMS_IN); #[ } #[
def __exit__(self, type, value, traceback): global type_env for v in self.env_vars: del type_env[v] # forward declarations for externs for m in hlir16.objects['Method']: # TODO temporary fix for l3-routing-full, this will be computed later on with types({ "T": "struct uint8_buffer_s", "O": "unsigned", "HashAlgorithm": "int", }): t = m.type ret_type = format_type(t.returnType) args = ", ".join([format_expr(arg) for arg in t.parameters.parameters if not arg.type._type_ref('is_metadata')] + ['SHORT_STDPARAMS']) #[ extern ${ret_type} ${m.name}(${args}); # TODO do not duplicate code def unique_stable(items): """Returns only the first occurrence of the items in a list. Equivalent to unique_everseen from Python 3.""" from collections import OrderedDict return list(OrderedDict.fromkeys(items)) #{ char* action_names[] = { for table in hlir16.tables: for action in unique_stable(table.actions):
def gen_extract_header_tmp_2(hdrinst, hdrtype, w): x = header_bit_width(hdrtype) w = format_expr(w)
def gen_extract_header_tmp(h): #[ memcpy(pstate->${h.ref.name}, buf, ${h.type.byte_width}); #[ buf += ${h.type.byte_width}; #[ pd->parsed_length += ${h.type.byte_width}; def gen_extract_header_tmp_2(hdrinst, hdrtype, w): x = header_bit_width(hdrtype) w = format_expr(w) #[ int hdrlen = ((${w}+${x})/8); #[ pd->parsed_length += hdrlen; #[ memcpy(pstate->${hdrinst.ref.name}, buf, hdrlen); #[ pstate->${hdrinst.ref.name}_var += ${w}+${x}; #[ buf += hdrlen; def gen_extract_header(hdrinst, hdrtype): if hdrinst is None: addError("extracting header", "no instance found for header type " + hdrtype.name) return #[ if((int)((uint8_t*)buf-(uint8_t*)(pd->data))+${hdrtype.byte_width} > pd->wrapper->pkt_len) #[ ; // packet_too_short // TODO optimize this #[ pd->headers[${hdrinst.id}].pointer = buf; #[ pd->headers[${hdrinst.id}].length = ${hdrtype.byte_width}; #[ pd->parsed_length += ${hdrtype.byte_width}; #[ buf += pd->headers[${hdrinst.id}].length; for f in hdrtype.valid_fields: # TODO get rid of "f.get_attr('preparsed') is not None" # TODO (f must always have a preparsed attribute) if f.get_attr('preparsed') is not None and f.preparsed and f.size <= 32: #[ EXTRACT_INT32_AUTO_PACKET(pd, ${hdrinst.id}, ${f.id}, value32) #[ pd->fields.${f.id} = value32; #[ pd->fields.attr_${f.id} = 0; def gen_extract_header_2(hdrinst, hdrtype, w): if not hdrtype.is_vw: addError("generating extract header call", "fixed-width header extracted with two-param extract") return x = header_bit_width(hdrtype) w = format_expr(w) #[ uint32_t hdrlen = ((${w}+${x})/8); #[ if ((int)((uint8_t*)buf-(uint8_t*)(pd->data))+hdrlen > pd->wrapper->pkt_len) #[ ; // packet_too_short // TODO optimize this #[ if (hdrlen > ${hdrtype.byte_width}) #[ debug(" " T4LIT(!,warning) " header " T4LIT(${hdrinst.name},header) " is too long (" T4LIT(%d,warning) " bytes)\n", hdrlen); #[ pd->headers[${hdrinst.id}].pointer = buf; #[ pd->headers[${hdrinst.id}].length = hdrlen; #[ pd->parsed_length += hdrlen; #[ pd->headers[${hdrinst.id}].var_width_field_bitwidth = hdrlen * 8 - ${header_bit_width(hdrtype)}; ################################################################################ parser = hlir16.objects['P4Parser'][0] for l in parser.parserLocals: #[ ${format_declaration(l)} for s in parser.states: #[ static void parser_state_${s.name}(packet_descriptor_t* pd, uint8_t* buf, lookup_table_t** tables, parser_state_t* pstate); for s in parser.states: if s.node_type != 'ParserState': continue #[ static void parser_state_${s.name}(packet_descriptor_t* pd, uint8_t* buf, lookup_table_t** tables, parser_state_t* pstate) { #[ uint32_t value32; (void)value32; #[ uint32_t res32; (void)res32; #[ debug(" :::: Parser state $$[parserstate]{s.name}\n"); for c in s.components: if hasattr(c, 'call'): if c.call == 'extract_header': hdrtype = c.header.type_ref if hasattr(c.header, 'type_ref') else c.header # TODO find a more universal way to get to the header instance if hasattr(c.methodCall.arguments[0].expression, 'path'): hdrinst_name = c.methodCall.arguments['Argument'][0].expression.path.name hdrinst = hlir16.header_instances.get(hdrinst_name, 'Declaration_Variable', lambda hi: hi.type.type_ref.name == hdrtype.name) elif hasattr(c.methodCall.method.expr, 'header_ref'): hdrinst = c.methodCall.method.expr.header_ref else: if not hasattr(c.methodCall.arguments[0].expression, 'member'): import ipdb ipdb.set_trace() hdrinst_name = c.methodCall.arguments[0].expression.member hdrinst = hlir16.header_instances.get(hdrinst_name, 'StructField', lambda hi: hi.type.type_ref.name == hdrtype.name) # TODO there should be no "secondary" hdrtype node if not hasattr(hdrtype, 'bit_width'): hdrtype = hlir16.header_types.get(hdrtype.name, 'Type_Header') bitwidth = hdrtype.bit_width if not c.is_vw else header_bit_width(hdrtype) if not c.is_tmp: if not c.is_vw: #[ ${gen_extract_header(hdrinst, hdrtype)} else: #[ ${gen_extract_header_2(hdrinst, hdrtype, c.width)} #[ dbg_bytes(pd->headers[${hdrinst.id}].pointer, pd->headers[${hdrinst.id}].length, #[ " :: Extracted header $$[header]{hdrinst.name} ($${(bitwidth+7)/8}{ bytes}): "); else: if not c.is_vw: #[ ${gen_extract_header_tmp(hdrinst)} #[ dbg_bytes(pstate->${hdrinst.ref.name}, ${hdrinst.type.byte_width}, #[ " :: Extracted header $$[header]{hdrinst.path.name} of type $${hdrinst.type.name} ($${bitwidth} bits, $${hdrinst.type.byte_width} bytes): "); else: #[ ${gen_extract_header_tmp_2(hdrinst, hdrtype, c.width)} hdr_width = header_bit_width(hdrtype) var_width = format_expr(c.width) #[ dbg_bytes(pstate->${hdrinst.ref.name}, (($hdr_width + $var_width)+7)/8, #[ " :: Extracted header $$[header]{hdrinst.path.name} of type $${hdrinst.type.name}: ($${hdr_width}+$${}{%d} bits, $${}{%d} bytes): ", #[ $var_width, (($hdr_width + $var_width)+7)/8); else: #[ ${format_statement(c)} if not hasattr(s, 'selectExpression'): if s.name == 'accept': #[ debug(" :: Packet is $$[success]{}{accepted}\n"); if s.name == 'reject': #[ debug(" :: Packet is $$[success]{}{dropped}\n"); #[ pd->dropped = 1; else: b = s.selectExpression if b.node_type == 'PathExpression': x = "parser_state_" + format_expr(b) + "(pd, buf, tables, pstate);" if b.node_type == 'SelectExpression': x = format_expr(b) prebuf, postbuf = statement_buffer_value() #[ $prebuf #[ $x #[ $postbuf #[ } #[ void parse_packet(packet_descriptor_t* pd, lookup_table_t** tables, parser_state_t* pstate) { #[ parser_state_start(pd, pd->data, tables, pstate); #[ } #{ const char* header_instance_names[HEADER_INSTANCE_COUNT] = { for hdr in hlir16.header_instances: #[ "${hdr.name}", // header_instance_${hdr.name} #} }; #{ const char* field_names[FIELD_COUNT] = { for hdr in hlir16.header_types: for fld in hdr.valid_fields: #[ "${fld.name}", // field_instance_${hdr.name}_${fld.name} #} }; #[ // Returns the sum of all collected variable widths, #[ // and resets all varwidth counters. #{ int get_var_width_bitwidth(parser_state_t* pstate) { #[ int retval = 0 for loc in parser.parserLocals: #[ + pstate->${loc.name}_var #[ ; for loc in parser.parserLocals: