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