| # Copyright (c) Barefoot Networks, Inc. |
| # Licensed under the Apache License, Version 2.0 (the "License") |
| |
| from p4_hlir.hlir import p4_header_instance |
| from ebpfType import EbpfType |
| from compilationException import CompilationException |
| from programSerializer import ProgramSerializer |
| import typeFactory |
| |
| |
| class EbpfInstanceBase(object): |
| def __init__(self): |
| pass |
| |
| |
| class SimpleInstance(EbpfInstanceBase): |
| # A header or a metadata instance (but not array elements) |
| def __init__(self, hlirInstance, factory, isMetadata): |
| super(SimpleInstance, self).__init__() |
| self.hlirInstance = hlirInstance |
| self.name = hlirInstance.base_name |
| self.type = factory.build(hlirInstance.header_type, isMetadata) |
| |
| def declare(self, serializer): |
| assert isinstance(serializer, ProgramSerializer) |
| self.type.declare(serializer, self.name, False) |
| |
| |
| class EbpfHeader(SimpleInstance): |
| """ Represents a header instance from a P4 program """ |
| def __init__(self, hlirHeaderInstance, factory): |
| super(EbpfHeader, self).__init__(hlirHeaderInstance, factory, False) |
| if hlirHeaderInstance.metadata: |
| raise CompilationException(True, "Metadata passed to EpbfHeader") |
| if hlirHeaderInstance.index is not None: |
| self.name += "_" + str(hlirHeaderInstance.index) |
| |
| |
| class EbpfMetadata(SimpleInstance): |
| """Represents a metadata instance from a P4 program""" |
| def __init__(self, hlirMetadataInstance, factory): |
| super(EbpfMetadata, self).__init__(hlirMetadataInstance, factory, True) |
| if not hlirMetadataInstance.metadata: |
| raise CompilationException( |
| True, "Header instance passed to EpbfMetadata {0}", |
| hlirMetadataInstance) |
| if hlirMetadataInstance.index is not None: |
| raise CompilationException( |
| True, "Unexpected metadata array {0}", self.hlirInstance) |
| if hasattr(hlirMetadataInstance, "initializer"): |
| self.initializer = hlirMetadataInstance.initializer |
| else: |
| self.initializer = None |
| |
| def emitInitializer(self, serializer): |
| assert isinstance(serializer, ProgramSerializer) |
| if self.initializer is None: |
| self.type.emitInitializer(serializer) |
| else: |
| for key in self.initializer.keys(): |
| serializer.appendFormat( |
| ".{0} = {1},", key, self.initializer[key]) |
| |
| |
| class EbpfHeaderStack(EbpfInstanceBase): |
| """Represents a header stack instance; there is one instance of |
| this class for each STACK, and not for each |
| element of the stack, as in the HLIR""" |
| def __init__(self, hlirInstance, indexVar, factory): |
| super(EbpfHeaderStack, self).__init__() |
| |
| # indexVar: name of the ebpf variable that |
| # holds the current index for this stack |
| assert isinstance(indexVar, str) |
| assert isinstance(factory, typeFactory.EbpfTypeFactory) |
| assert isinstance(hlirInstance, p4_header_instance) |
| |
| self.indexVar = indexVar |
| self.name = hlirInstance.base_name |
| self.basetype = factory.build(hlirInstance.header_type, False) |
| assert isinstance(self.basetype, EbpfType) |
| self.arraySize = hlirInstance.max_index + 1 |
| self.hlirInstance = hlirInstance |
| |
| def declare(self, serializer): |
| assert isinstance(serializer, ProgramSerializer) |
| self.basetype.declareArray(serializer, self.name, self.arraySize) |