Added ability to filter and classify packets based on the containers interface.
authorXavi Leon <xleon@ac.upc.edu>
Fri, 2 Dec 2011 17:50:16 +0000 (12:50 -0500)
committerXavi Leon <xleon@ac.upc.edu>
Fri, 2 Dec 2011 17:50:16 +0000 (12:50 -0500)
Changes:
- lxc libvirt configuration template to attach the xid to the container
  interface
- added ebtables rule to mark packets going out from the containers interface
  with its xid and added a filter to classify packets based on this mark
- moved the definition of container after the user is created so we get the
  correct xid to attach to the virtual interface name.

bwlimit.py
config_template.xml
sliver_lxc.py

index ab760b5..7ac3def 100644 (file)
@@ -56,6 +56,9 @@ import pwd
 # Where the tc binary lives
 TC = "/sbin/tc"
 
+# Where the ebtables binary lives
+EBTABLES = "/sbin/ebtables"
+
 # Default interface
 dev = "eth0"
 
@@ -274,7 +277,7 @@ def get_slice(xid):
 
 def get_xid(slice):
     """
-    Get slice xid ("princeton_mlh") from slice name ("500" or "princeton_mlh")
+    Get slice xid ("500") from slice name ("princeton_mlh")
     """
 
     if slice == "root":
@@ -321,6 +324,13 @@ def tc(cmd):
 
     return run(TC + " " + cmd)
 
+def ebtables(cmd):
+    """
+    Shortcut for running a ebtables command
+    """
+
+    return run(EBTABLES + " " + cmd)
+
 
 def stop(dev = dev):
     '''
@@ -338,7 +348,9 @@ def init(dev = dev, bwcap = bwmax):
     """
 
     # Load the module used to manage exempt classes
-    run("/sbin/modprobe ip_set_iphash")
+    #run("/sbin/modprobe ip_set_iphash")
+    # Test the new module included in kernel 3 series
+    run("/sbin/modprobe ip_set_hash_ip")
 
     # Save current settings
     paramslist = get(None, dev)
@@ -569,7 +581,7 @@ def on(xid, dev = dev, share = None, minrate = None, maxrate = None, minexemptra
 
     tc("class replace dev %s parent 1:20 classid 1:%x htb rate %dbit ceil %dbit quantum %d" % \
        (dev, exempt_minor | xid, minexemptrate, maxexemptrate, share * quantum))
-
+    
     # Attach a FIFO to each subclass, which helps to throttle back
     # processes that are sending faster than the token buckets can
     # support.
@@ -579,6 +591,21 @@ def on(xid, dev = dev, share = None, minrate = None, maxrate = None, minexemptra
     tc("qdisc replace dev %s parent 1:%x handle %x pfifo" % \
        (dev, exempt_minor | xid, exempt_minor | xid))
 
+    # Setup a filter rule to the root class so each packet originated by a
+    # container interface is classified to it corresponding class
+    # The handle number is a mark created by ebtables with the xid
+    tc("filter replace dev %s parent 1:1 protocol ip prio 1 handle %d fw flowid 1:%x" % \
+        (dev, default_minor | xid, default_minor | xid))
+
+    # Create the ebtables rule to mark the packets going out from the virtual
+    # interface to the actual device so the filter canmatch against the mark
+    # We remove and readd the rule because this method is called each time the
+    # bandwidth limit is changed
+    ebtables("-D INPUT -i veth%d -j mark --set-mark %d" % \
+        (xid, default_minor | xid))
+    ebtables("-A INPUT -i veth%d -j mark --set-mark %d" % \
+        (xid, default_minor | xid))
+
 
 def set(xid, share = None, minrate = None, maxrate = None, minexemptrate = None, maxexemptrate = None, dev = dev ):
     on(xid = xid, dev = dev, share = share,
index 59379ac..a4d6152 100644 (file)
@@ -18,6 +18,7 @@
     </filesystem>
     <interface type='network'>
       <source network='default'/>
+      <target dev='veth%xid'/>
     </interface>
     <console type='pty' />
   </devices>
index 4c2a599..5a0d52f 100644 (file)
@@ -9,6 +9,7 @@ import os
 import libvirt
 import sys
 from string import Template
+import bwlimit
 import sliver_libvirt as lv
 
 
@@ -28,16 +29,7 @@ class Sliver_LXC(lv.Sliver_Libvirt):
     def create(name, rec=None):
         logger.verbose ('sliver_lxc: %s create'%(name))
         conn = lv.getConnection(Sliver_LXC.TYPE)
-        
-        # Template for libvirt sliver configuration
-        try:
-            with open(Sliver_LXC.REF_IMG_BASE_DIR + '/config_template.xml') as f:
-                template = Template(f.read())
-                xml  = template.substitute(name=name)
-        except IOError:
-            logger.log('Cannot find XML template file')
-            return
-        
+       
         ''' Create dirs, copy fs image, lxc_create '''
         # Get the type of image from vref myplc tags specified as:
         # pldistro = lxc
@@ -92,6 +84,19 @@ class Sliver_LXC(lv.Sliver_Libvirt):
         command = ['cp', '/home/%s/.ssh/id_rsa.pub'%name, '%s/root/.ssh/authorized_keys'%containerDir]
         logger.log_call(command, timeout=15*60)
 
+        # Lookup for xid and create template after the user is created so we
+        # can get the correct xid based on the name of the slice
+        xid = bwlimit.get_xid(name)
+
+        # Template for libvirt sliver configuration
+        try:
+            with open(Sliver_LXC.REF_IMG_BASE_DIR + '/config_template.xml') as f:
+                template = Template(f.read())
+                xml  = template.substitute(name=name, xid=xid)
+        except IOError:
+            logger.log('Cannot find XML template file')
+            return
         # Lookup for the sliver before actually
         # defining it, just in case it was already defined.
         try: