• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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