• 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_SIGNED, P4_SATURATING
5from ebpfScalarType import *
6
7
8class EbpfField(object):
9    __doc__ = "represents a field in a struct type, not in an instance"
10
11    def __init__(self, hlirParentType, name, widthInBits, attributes, config):
12        self.name = name
13        self.width = widthInBits
14        self.hlirType = hlirParentType
15        signed = False
16        if P4_SIGNED in attributes:
17            signed = True
18        if P4_SATURATING in attributes:
19            raise NotSupportedException(
20                "{0}.{1}: Saturated types", self.hlirType, self.name)
21
22        try:
23            self.type = EbpfScalarType(
24                self.hlirType, widthInBits, signed, config)
25        except CompilationException, e:
26            raise CompilationException(
27                e.isBug, "{0}.{1}: {2}", hlirParentType, self.name, e.show())
28
29    def widthInBits(self):
30        return self.width
31
32
33class EbpfStructType(EbpfType):
34    # Abstract base class for HeaderType and MetadataType.
35    # They are both represented by a p4 header_type
36    def __init__(self, hlirHeader, config):
37        super(EbpfStructType, self).__init__(hlirHeader)
38        self.name = hlirHeader.name
39        self.fields = []
40
41        for (fieldName, fieldSize) in self.hlirType.layout.items():
42            attributes = self.hlirType.attributes[fieldName]
43            field = EbpfField(
44                hlirHeader, fieldName, fieldSize, attributes, config)
45            self.fields.append(field)
46
47    def serialize(self, serializer):
48        assert isinstance(serializer, ProgramSerializer)
49
50        serializer.emitIndent()
51        serializer.appendFormat("struct {0} ", self.name)
52        serializer.blockStart()
53
54        for field in self.fields:
55            serializer.emitIndent()
56            field.type.declare(serializer, field.name, False)
57            serializer.appendFormat("; /* {0} bits */", field.widthInBits())
58            serializer.newline()
59
60        serializer.blockEnd(False)
61        serializer.endOfStatement(True)
62
63    def declare(self, serializer, identifier, asPointer):
64        assert isinstance(serializer, ProgramSerializer)
65        assert isinstance(identifier, str)
66        assert isinstance(asPointer, bool)
67
68        serializer.appendFormat("struct {0} ", self.name)
69        if asPointer:
70            serializer.append("*")
71        serializer.append(identifier)
72
73    def widthInBits(self):
74        return self.hlirType.length * 8
75
76    def getField(self, name):
77        assert isinstance(name, str)
78
79        for f in self.fields:
80            assert isinstance(f, EbpfField)
81            if f.name == name:
82                return f
83        raise CompilationException(
84            True, "Could not locate field {0}.{1}", self, name)
85
86
87class EbpfHeaderType(EbpfStructType):
88    def __init__(self, hlirHeader, config):
89        super(EbpfHeaderType, self).__init__(hlirHeader, config)
90        validField = EbpfField(hlirHeader, "valid", 1, set(), config)
91        # check that no "valid" field exists already
92        for f in self.fields:
93            if f.name == "valid":
94                raise CompilationException(
95                    True,
96                    "Header type contains a field named `valid': {0}",
97                    f)
98        self.fields.append(validField)
99
100    def emitInitializer(self, serializer):
101        assert isinstance(serializer, ProgramSerializer)
102        serializer.blockStart()
103        serializer.emitIndent()
104        serializer.appendLine(".valid = 0")
105        serializer.blockEnd(False)
106
107    def declareArray(self, serializer, identifier, size):
108        assert isinstance(serializer, ProgramSerializer)
109        serializer.appendFormat(
110            "struct {0} {1}[{2}]", self.name, identifier, size)
111
112
113class EbpfMetadataType(EbpfStructType):
114    def __init__(self, hlirHeader, config):
115        super(EbpfMetadataType, self).__init__(hlirHeader, config)
116
117    def emitInitializer(self, serializer):
118        assert isinstance(serializer, ProgramSerializer)
119
120        serializer.blockStart()
121        for field in self.fields:
122            serializer.emitIndent()
123            serializer.appendFormat(".{0} = ", field.name)
124
125            field.type.emitInitializer(serializer)
126            serializer.append(",")
127            serializer.newline()
128        serializer.blockEnd(False)
129