Skip to content

Instantly share code, notes, and snippets.

@elazarl
Last active November 14, 2018 09:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elazarl/fbc8c57370e1ba905e668f69800478e2 to your computer and use it in GitHub Desktop.
Save elazarl/fbc8c57370e1ba905e668f69800478e2 to your computer and use it in GitHub Desktop.
#!/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