Last active
November 14, 2018 09:00
-
-
Save elazarl/fbc8c57370e1ba905e668f69800478e2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
import re | |
import io | |
class FtraceEventParser(object): | |
"""FTraceEventParser parses the text form of a single event | |
to a tuple of all the event's arguments. | |
Example usage: | |
TRACE = '/sys/kernel/debug/tracing/events' | |
event = 'tcp_set_state' | |
EVT = TRACE + '/tcp/' + event | |
with open(EVT + '/format') as fd: | |
parser = FtraceEventParser.from_fileobj(fd) | |
with open(EVT + '/enable') as fd: | |
fd.write('1\n') | |
for line in open(TRACE + '/trace'): | |
if not (event+':') in line: | |
continue | |
prefix, trace = line.split(' %s: ' % event) | |
sport, dport, saddr, daddr, saddrv6, daddrv6, oldstate, newstate = parser.parse(trace) | |
ts = float(prefix[prefix.rfind(' ')+1:-1]) | |
with open(EVT + '/enable') as fd: | |
fd.write('0\n') | |
""" | |
def parse(self, s): | |
m = self.regexp.match(s) | |
if not m: | |
return None | |
return m.groups() | |
def __init__(self, fileobj): | |
self.regexp = self.re_from_format(fileobj) | |
@classmethod | |
def from_fileobj(cls, fileobj): | |
return cls(fileobj) | |
@classmethod | |
def from_string(cls, s): | |
return cls(io.StringIO(s)) | |
@staticmethod | |
def re_from_format(fd): | |
"""This would parse an event format string, and create a capturing regexp | |
that is able to sort-of-parse format string, under reasonable assumptions. | |
For example, tcp_set_state printf-like format string is: | |
"sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c oldstate=%s newstate=%s" | |
and would generate the regexp | |
sport=([^ ]*) dport=([^ ]*) saddr=([^ ]*) daddr=([^ ]*) saddrv6=([^ ]*) daddrv6=([^ ]*) oldstate=([^ ]*) newstate=(.*) | |
Note, we're assuming that a pattern of the form '%s:' would not have the %s contain ':' | |
""" | |
prefix = 'print fmt:' | |
pattern = re.compile('(%[a-z0-9.]*)([^a-z0-9.])', re.IGNORECASE) | |
end_pattern = re.compile('(%[a-z0-9.]*)$', re.IGNORECASE) | |
for line in fd.readlines(): | |
if not line.startswith(prefix): | |
continue | |
line = line[len(prefix)+2:] | |
fmt = line[:line.index('"')] | |
while True: | |
m = pattern.search(fmt) | |
if not m: | |
break | |
fmt = pattern.sub(r'([^\2]*)\2', fmt) | |
m = end_pattern.search(fmt) | |
if not m: | |
continue | |
fmt = end_pattern.sub('(.*)$', fmt) | |
print(fmt) | |
return re.compile(fmt) | |
if __name__ == '__main__': | |
with open('/sys/kernel/debug/tracing/events/tcp/tcp_set_state/format') as fd: | |
parser = FtraceEventParser.from_fileobj(fd) | |
example = 'sport=54192 dport=443 saddr=10.0.0.10 daddr=169.60.79.3 saddrv6=::ffff:10.0.0.10 daddrv6=::ffff:169.60.79.3 oldstate=TCP_ESTABLISHED newstate=TCP_CLOSE_WAIT' | |
m = parser.parse(example) | |
print(m) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment