forked from iovisor/bcc
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathebpfCounter.py
More file actions
116 lines (95 loc) · 4.13 KB
/
Copy pathebpfCounter.py
File metadata and controls
116 lines (95 loc) · 4.13 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
# Copyright (c) Barefoot Networks, Inc.
# Licensed under the Apache License, Version 2.0 (the "License")
from p4_hlir.hlir import p4_counter, P4_DIRECT, P4_COUNTER_BYTES
from programSerializer import ProgramSerializer
from compilationException import *
import ebpfTable
import ebpfProgram
class EbpfCounter(object):
# noinspection PyUnresolvedReferences
def __init__(self, hlircounter, program):
assert isinstance(hlircounter, p4_counter)
assert isinstance(program, ebpfProgram.EbpfProgram)
self.name = hlircounter.name
self.hlircounter = hlircounter
width = hlircounter.min_width
# ebpf counters only work on 64-bits
if width <= 64:
self.valueTypeName = program.config.uprefix + "64"
else:
raise NotSupportedException(
"{0}: Counters with {1} bits", hlircounter, width)
self.dataMapName = self.name
if ((hlircounter.binding is None) or
(hlircounter.binding[0] != P4_DIRECT)):
raise NotSupportedException(
"{0}: counter which is not direct", hlircounter)
self.autoIncrement = (hlircounter.binding != None and
hlircounter.binding[0] == P4_DIRECT)
if hlircounter.type is P4_COUNTER_BYTES:
self.increment = "{0}->len".format(program.packetName)
else:
self.increment = "1"
def getSize(self, program):
if self.hlircounter.instance_count is not None:
return self.hlircounter.instance_count
if self.autoIncrement:
return self.getTable(program).size
program.emitWarning(
"{0} does not specify a max_size; using 1024", self.hlircounter)
return 1024
def getTable(self, program):
table = program.getTable(self.hlircounter.binding[1].name)
assert isinstance(table, ebpfTable.EbpfTable)
return table
def serialize(self, serializer, program):
assert isinstance(serializer, ProgramSerializer)
# Direct counters have the same key as the associated table
# Static counters have integer keys
if self.autoIncrement:
keyTypeName = "struct " + self.getTable(program).keyTypeName
else:
keyTypeName = program.config.uprefix + "32"
program.config.serializeTableDeclaration(
serializer, self.dataMapName, True, keyTypeName,
self.valueTypeName, self.getSize(program))
def serializeCode(self, keyname, serializer, program):
assert isinstance(serializer, ProgramSerializer)
assert isinstance(program, ebpfProgram.EbpfProgram)
serializer.emitIndent()
serializer.appendFormat("/* Update counter {0} */", self.name)
serializer.newline()
valueName = "ctrvalue"
initValuename = "init_val"
serializer.emitIndent()
serializer.appendFormat("{0} *{1};", self.valueTypeName, valueName)
serializer.newline()
serializer.emitIndent()
serializer.appendFormat("{0} {1};", self.valueTypeName, initValuename)
serializer.newline()
serializer.emitIndent()
serializer.appendLine("/* perform lookup */")
serializer.emitIndent()
program.config.serializeLookup(
serializer, self.dataMapName, keyname, valueName)
serializer.newline()
serializer.emitIndent()
serializer.appendFormat("if ({0} != NULL) ", valueName)
serializer.newline()
serializer.increaseIndent()
serializer.emitIndent()
serializer.appendFormat("__sync_fetch_and_add({0}, {1});",
valueName, self.increment)
serializer.newline()
serializer.decreaseIndent()
serializer.emitIndent()
serializer.append("else ")
serializer.blockStart()
serializer.emitIndent()
serializer.appendFormat("{0} = {1};", initValuename, self.increment)
serializer.newline()
serializer.emitIndent()
program.config.serializeUpdate(
serializer, self.dataMapName, keyname, initValuename)
serializer.newline()
serializer.blockEnd(True)