1# Copyright (c) Barefoot Networks, Inc. 2# Licensed under the Apache License, Version 2.0 (the "License") 3 4from p4_hlir.hlir import p4_header_instance 5from ebpfType import EbpfType 6from compilationException import CompilationException 7from programSerializer import ProgramSerializer 8import typeFactory 9 10 11class EbpfInstanceBase(object): 12 def __init__(self): 13 pass 14 15 16class SimpleInstance(EbpfInstanceBase): 17 # A header or a metadata instance (but not array elements) 18 def __init__(self, hlirInstance, factory, isMetadata): 19 super(SimpleInstance, self).__init__() 20 self.hlirInstance = hlirInstance 21 self.name = hlirInstance.base_name 22 self.type = factory.build(hlirInstance.header_type, isMetadata) 23 24 def declare(self, serializer): 25 assert isinstance(serializer, ProgramSerializer) 26 self.type.declare(serializer, self.name, False) 27 28 29class EbpfHeader(SimpleInstance): 30 """ Represents a header instance from a P4 program """ 31 def __init__(self, hlirHeaderInstance, factory): 32 super(EbpfHeader, self).__init__(hlirHeaderInstance, factory, False) 33 if hlirHeaderInstance.metadata: 34 raise CompilationException(True, "Metadata passed to EpbfHeader") 35 if hlirHeaderInstance.index is not None: 36 self.name += "_" + str(hlirHeaderInstance.index) 37 38 39class EbpfMetadata(SimpleInstance): 40 """Represents a metadata instance from a P4 program""" 41 def __init__(self, hlirMetadataInstance, factory): 42 super(EbpfMetadata, self).__init__(hlirMetadataInstance, factory, True) 43 if not hlirMetadataInstance.metadata: 44 raise CompilationException( 45 True, "Header instance passed to EpbfMetadata {0}", 46 hlirMetadataInstance) 47 if hlirMetadataInstance.index is not None: 48 raise CompilationException( 49 True, "Unexpected metadata array {0}", self.hlirInstance) 50 if hasattr(hlirMetadataInstance, "initializer"): 51 self.initializer = hlirMetadataInstance.initializer 52 else: 53 self.initializer = None 54 55 def emitInitializer(self, serializer): 56 assert isinstance(serializer, ProgramSerializer) 57 if self.initializer is None: 58 self.type.emitInitializer(serializer) 59 else: 60 for key in self.initializer.keys(): 61 serializer.appendFormat( 62 ".{0} = {1},", key, self.initializer[key]) 63 64 65class EbpfHeaderStack(EbpfInstanceBase): 66 """Represents a header stack instance; there is one instance of 67 this class for each STACK, and not for each 68 element of the stack, as in the HLIR""" 69 def __init__(self, hlirInstance, indexVar, factory): 70 super(EbpfHeaderStack, self).__init__() 71 72 # indexVar: name of the ebpf variable that 73 # holds the current index for this stack 74 assert isinstance(indexVar, str) 75 assert isinstance(factory, typeFactory.EbpfTypeFactory) 76 assert isinstance(hlirInstance, p4_header_instance) 77 78 self.indexVar = indexVar 79 self.name = hlirInstance.base_name 80 self.basetype = factory.build(hlirInstance.header_type, False) 81 assert isinstance(self.basetype, EbpfType) 82 self.arraySize = hlirInstance.max_index + 1 83 self.hlirInstance = hlirInstance 84 85 def declare(self, serializer): 86 assert isinstance(serializer, ProgramSerializer) 87 self.basetype.declareArray(serializer, self.name, self.arraySize) 88