Antoni Segura Puimedon has uploaded a new change for review.

Change subject: tc: increased parsing capabilities
......................................................................

tc: increased parsing capabilities

Change-Id: I95aa9aaaeb0f8e612734b32a578e46fade7fdd9c
Signed-off-by: Antoni S. Puimedon <[email protected]>
---
M vdsm/network/tc.py
1 file changed, 185 insertions(+), 2 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/11/29211/1

diff --git a/vdsm/network/tc.py b/vdsm/network/tc.py
index 35c4a92..1deb6ab 100644
--- a/vdsm/network/tc.py
+++ b/vdsm/network/tc.py
@@ -192,6 +192,190 @@
 MirredAction = namedtuple('MirredAction', 'target')
 
 
+def _filter_show(dev, parent=None, prio=None):
+    cmd = [EXT_TC, 'filter', 'show', 'dev', dev]
+    if parent is not None:
+        cmd += ['parent', parent]
+    if prio is not None:
+        cmd += ['prio', prio]
+    return _process_request(cmd)
+
+
+def _parse_u32(tokens):
+    """Returns a dictionary with the parsed information and consumes the parsed
+    elements from the input list"""
+    data = {}
+    while tokens:
+        token = tokens.pop(0)
+        if token in ('fh', 'order', 'link'):
+            data[token] = tokens.pop(0)
+        elif token in ('*flowid', 'flowid'):
+            data['flowid'] = tokens.pop(0)
+        elif token == 'terminal':
+            data['terminal'] = True
+            tokens.pop(0)  # swallow 'flowid'
+            tokens.pop(0)  # swallow '???'
+        elif token == 'ht':
+            tokens.pop(0)
+            data['ht_divisor'] = tokens.pop(0)
+        elif token == 'key':
+            tokens.pop(0)  # swallow 'ht'
+            data['key_ht'] = tokens.pop(0)
+            tokens.pop(0)  # swallow 'bkt'
+            data['key_bkt'] = tokens.pop(0)
+        elif token == '???':
+            continue
+        elif token == 0:  # line break
+            continue
+        elif token == 'match':
+            if tokens[0] != 'IP':
+                data['match'] = _parse_match_raw(tokens)
+            else:
+                data['match'] = _parse_match_ip(tokens)  # To implement
+        elif token == 'action':
+            try:
+                data['actions'].append(_parse_action(tokens))
+            except KeyError:
+                data['actions'] = [_parse_action(tokens)]
+        else:
+            break  # We should not get here unless iproute adds fields. Log?
+    return data
+
+
+def _parse_skip_line(tokens):
+    while tokens:
+        token = tokens.pop(0)
+        if token == 0:
+            break
+
+
+_parse_match_ip = _parse_skip_line
+
+
+def _parse_match_raw(tokens):
+    value, mask = tokens.pop(0).split('/')
+    value = int(value, 16)
+    mask = int(mask, 16)
+    tokens.pop(0)  # Swallow 'at'
+    offset = int(tokens.pop(0))
+    return {'value': value, 'mask': mask, 'offset': offset}
+
+
+def _parse_mirred(tokens):
+    data = {}
+    action = tokens.pop(0)[1:]  # Get the first token without the opening paren
+    if action == 'unkown':
+        data['action'] = action
+    else:
+        data['action'] = '%s_%s' % (action.lower(), tokens.pop(0).lower())
+    tokens.pop(0)  # swallow 'to'
+    tokens.pop(0)  # swallow 'device'
+    data['target'] = tokens.pop(0)[:-1]
+    data['op'] = tokens.pop(0)
+    tokens.pop(0)  # pop the 0 that marks new line
+    while tokens:
+        token = tokens.pop(0)
+        if token in ('index', 'ref', 'bind'):
+            data[token] = tokens.pop(0)
+        elif token == 0:
+            break
+        else:
+            break  # We should not get here unless iproute adds fields. Log?
+    return data
+
+
+FILTER_ACTIONS = {'csum': None, 'gact': None, 'ipt': None,
+                  'mirred': _parse_mirred, 'nat': None, 'pedit': None,
+                  'police': None, 'simple': None, 'skbedit': None, 'xt': None}
+
+
+def _parse_action(tokens):
+    """Returns a dictionary with the parsed information and consumes the parsed
+    elements from the input list"""
+    data = {}
+    while tokens:
+        token = tokens.pop(0)
+        if token == 'order':
+            data[token] = tokens.pop(0)
+            data['kind'] = tokens.pop(0)
+            action_opt_parse = FILTER_ACTIONS.get(data['kind'])
+            if action_opt_parse is not None:
+                data.update(action_opt_parse(tokens))
+    return data
+
+
+FILTER_CLS = {'basic': None, 'cgroup': None, 'flow': None, 'fw': None,
+              'route': None, 'rsvp': None, 'tcindex': None, 'u32': _parse_u32}
+
+
+def _filter_parse_general(tokens):
+    """Returns a dictionary with the parsed information and consumes the parsed
+    elements from the input list"""
+    data = {}
+    tokens.pop(0)  # Pop the 'filter' element
+    while tokens:
+        token = tokens.pop(0)
+        if token == 'root':
+            data['root'] = True
+        elif token in ('dev', 'parent', 'protocol', 'pref'):
+            data[token] = tokens.pop(0)
+        elif token in FILTER_CLS:
+            data['kind'] = token
+            break
+    return data
+
+
+def foo(dev):
+    out = _filter_show(dev).splitlines()
+    lines = []
+    current = []
+    for line in out:
+        line = line.replace('\t', ' ')
+        if line.startswith(' '):
+            current.append(0)
+            current.extend(line.strip().split())
+        else:
+            if current:
+                lines.append(current)
+            current = line.strip().split()
+    if current:
+        lines.append(current)
+
+    for tokens in lines:
+        if tokens[0] == 'filter':
+            filt = _filter_parse_general(tokens)
+            cls_parser = FILTER_CLS[filt['kind']]
+            if cls_parser is not None:
+                filt[filt['kind']] = cls_parser(tokens)
+            print filt
+
+
+def _filters(dev, parent=None, out=None):
+    if out is None:
+        out = _filter_show(dev, parent=parent)
+    lines = []
+    current = []
+    for line in out:
+        line = line.replace('\t', ' ')
+        if line.startswith(' '):
+            current.append(0)
+            current.extend(line.strip().split())
+        else:
+            if current:
+                lines.append(current)
+            current = line.strip().split()
+    if current:
+        lines.append(current)
+
+    for tokens in lines:
+        if tokens[0] == 'filter':
+            filt = _filter_parse_general(tokens)
+            cls_parser = FILTER_CLS[filt['kind']]
+            if cls_parser is not None:
+                filt[filt['kind']] = cls_parser(tokens)
+            yield filt
+
+
 def filters(dev, parent, out=None):
     """
     Return a (very) limitted information about tc filters on dev
@@ -200,8 +384,7 @@
     """
 
     if out is None:
-        out = _process_request([EXT_TC, 'filter', 'show', 'dev', dev,
-                               'parent', parent])
+        out = _filter_show(dev, parent=parent)
 
     HEADER = 'filter protocol ip pref '
     prio = handle = None


-- 
To view, visit http://gerrit.ovirt.org/29211
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I95aa9aaaeb0f8e612734b32a578e46fade7fdd9c
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Antoni Segura Puimedon <[email protected]>
_______________________________________________
vdsm-patches mailing list
[email protected]
https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches

Reply via email to