Change in vdsm[master]: Support VLAN hardware offloading in hostQOS

ibarkan at redhat.com ibarkan at redhat.com
Wed Oct 14 14:42:33 UTC 2015


Ido Barkan has uploaded a new change for review.

Change subject: Support VLAN hardware offloading in hostQOS
......................................................................

Support VLAN hardware offloading in hostQOS

Apparently, the tc filter that VDSM uses to classify 802.1q traffic
is not working when the kernel offloads VLAN tagging to the underlying
physical nic.
This is because the VLAN field in the link layer header is only added
by the hardware and is not present by the time the filter inspects it.
Since the filter uses a straight forward matcher which only looks at
the headers it fails to match and the packets aren't classified to the
desired queuing discipline (qdisc).
Using a kernel packet meta data matcher should work regardless of VLAN
tagging offloading is enabled.

Change-Id: I667a9f38f4314da309685f6ba247f705a2e9c23e
Signed-off-by: Ido Barkan <ibarkan at redhat.com>
---
M tests/tcTests.py
M vdsm/network/configurators/qos.py
M vdsm/network/tc/filter.py
3 files changed, 50 insertions(+), 11 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/32/47332/1

diff --git a/tests/tcTests.py b/tests/tcTests.py
index f14d5a3..ade7b8e 100644
--- a/tests/tcTests.py
+++ b/tests/tcTests.py
@@ -417,8 +417,9 @@
             self._assert_parent([vlan_qdisc], vlan_class)
 
             self.assertEqual(len(tc_filters.tagged_filters), 1)
-            self.assertEqual(tc_filters.tagged_filters[0]['u32']['flowid'],
-                             ':%x' % vlan.tag)
+            self.assertEqual(
+                int(tc_filters.tagged_filters[0]['basic']['value']),
+                vlan.tag)
 
     def test_multiple_vlans(self):
         with vlan_device(self.device_name, tag=16) as vlan1:
@@ -441,7 +442,7 @@
 
                 self.assertEqual(len(tc_filters.tagged_filters), 2)
                 current_tagged_filters_flow_id = set(
-                    f['u32']['flowid'] for f in tc_filters.tagged_filters)
+                    f['basic']['flowid'] for f in tc_filters.tagged_filters)
                 expected_flow_ids = set(':%x' % v.tag for v in (vlan1, vlan2))
                 self.assertEqual(current_tagged_filters_flow_id,
                                  expected_flow_ids)
@@ -598,10 +599,7 @@
 
     def _tagged_filters(self, filters):
         def tagged(f):
-            flow_id = f.get('u32', {}).get('flowid')
-            if flow_id is not None and flow_id != ':%x' % qos._NON_VLANNED_ID:
-                return True
-            return False
+            return f.get('basic', {}).get('object') == 'vlan'
 
         return list(f for f in filters if tagged(f))
 
diff --git a/vdsm/network/configurators/qos.py b/vdsm/network/configurators/qos.py
index 7806239..77350dd 100644
--- a/vdsm/network/configurators/qos.py
+++ b/vdsm/network/configurators/qos.py
@@ -128,8 +128,13 @@
 def _qdisc_conf_out(dev, root_qdisc_handle, vlan_tag, class_id, qos):
     """Adds the traffic class and filtering to the current hfsc qdisc"""
     flow_id = ':' + class_id
+
+    def filt_flow_id(filt, kind):
+        return filt.get(kind, {}).get('flowid')
+
     filters = [filt for filt in tc._filters(dev, parent=root_qdisc_handle) if
-               'u32' in filt and filt['u32'].get('flowid') == flow_id]
+               flow_id in
+               (filt_flow_id(filt, 'basic'), filt_flow_id(filt, 'u32'))]
 
     # Clear up any previous filters to the class
     for filt in filters:
@@ -157,8 +162,9 @@
 def _add_vlan_filter(dev, vlan_tag, root_qdisc_handle, class_id):
     tc.filter.replace(dev, parent=root_qdisc_handle, protocol='802.1q',
                       pref=vlan_tag,
-                      u32=['match', 'u16', '0x%x' % vlan_tag, '0xFFF', 'at',
-                           '-4', 'flowid', '0x' + class_id])
+                      basic=['match', 'meta(vlan eq %s)' % vlan_tag,
+                             'flowid', '0x' + class_id]
+                      )
 
 
 def _add_non_vlanned_filter(dev, root_qdisc_handle):
diff --git a/vdsm/network/tc/filter.py b/vdsm/network/tc/filter.py
index 9b3913c..778e7ed 100644
--- a/vdsm/network/tc/filter.py
+++ b/vdsm/network/tc/filter.py
@@ -130,6 +130,27 @@
     return data
 
 
+def _parse_ematch(tokens):
+    """Parses tokens describing a raw ematch, (see man tc-ematch) e.g.,
+    'meta(vlan mask 0x00000000 eq 16)' into a data dictionary.
+    currently only a single 'meta' module predicate is supported"""
+    data = {}
+    for token in tokens:
+        if token == _parser.LINE_DELIMITER:  # line break
+            continue
+        elif token == 'handle':
+            data[token] = _parser.parse_str(tokens)
+        elif token == 'flowid':
+            data['flowid'] = _parser.parse_str(tokens)
+        elif '(' in token:
+            module, first_arg = token.split('(')
+            if module != 'meta':
+                _parser.parse_skip_line(tokens)
+            data['module'] = module
+            data.update(_parse_ematch_match(first_arg, tokens))
+    return data
+
+
 _parse_match_ip = _parser.parse_skip_line  # Unimplemented, skip line
 
 
@@ -142,6 +163,20 @@
     _parser.consume(tokens, 'at')
     offset = _parser.parse_int(tokens)
     return {'value': value, 'mask': mask, 'offset': offset}
+
+
+def _parse_ematch_match(first_arg, tokens):
+    data = {}
+    if first_arg in ('random', 'loadavg_1', 'nf_mark', 'vlan', 'sk_rcvbuf',
+                     'sk_snd_queue'):
+        data['object'] = first_arg
+    for token in tokens:
+        if token in ('eq', 'lt', 'gt'):
+            data['relation'] = token
+            data['value'] = next(tokens).strip(')')
+        elif token == 'mask':
+            data['mask'] = _parser.parse_str(tokens)
+    return data
 
 
 def _parse_action(tokens):
@@ -199,5 +234,5 @@
             'skbedit': None, 'xt': None}
 
 
-_CLASSES = {'basic': None, 'cgroup': None, 'flow': None, 'fw': None,
+_CLASSES = {'basic': _parse_ematch, 'cgroup': None, 'flow': None, 'fw': None,
             'route': None, 'rsvp': None, 'tcindex': None, 'u32': _parse_u32}


-- 
To view, visit https://gerrit.ovirt.org/47332
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I667a9f38f4314da309685f6ba247f705a2e9c23e
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Ido Barkan <ibarkan at redhat.com>


More information about the vdsm-patches mailing list