fix udp mangle
Scott Baker [Fri, 20 Mar 2015 17:54:29 +0000 (10:54 -0700)]
opencloud-net/opencloud-net.py

index 5b2061c..ca0154d 100755 (executable)
@@ -78,11 +78,26 @@ def run_iptables_cmd(args):
     cmd = ['/sbin/iptables'] + args
     print('%s: %s' % (plugin, ' '.join(cmd)))
     subprocess.check_call(cmd)
-    
+
+def del_iptables_rule(table, chain, args):
+    iptargs = ['-t', table, '-C',  chain] + args
+    try:
+        run_iptables_cmd(iptargs)
+    except:
+        #print "rule does not exist", iptargs
+        return
+
+    iptargs[2] = '-D'
+    try:
+        run_iptables_cmd(iptargs)
+    except:
+        print('%s: FAILED to delete iptables rule' % plugin, iptargs)
+
 def add_iptables_rule(table, chain, args, pos = None):
     iptargs = ['-t', table, '-C',  chain] + args
     try:
         run_iptables_cmd(iptargs)
+        #print "rule already exists", iptargs
     except:
         if pos:
             iptargs = ['-t', table, '-I', chain, str(pos)] + args
@@ -99,18 +114,25 @@ def reset_iptables_chain():
         run_iptables_cmd(['-t', 'nat', '-F', plugin])
     except:
         # Probably the chain doesn't exist, try creating it
-        run_iptables_cmd(['-t', 'nat', '-N', plugin]) 
+        run_iptables_cmd(['-t', 'nat', '-N', plugin])
+
+    add_iptables_rule('nat', 'PREROUTING', ['-j', plugin])
+
+def fix_udp_mangle():
+    # get rid of the existing UDP mangle rule that is attached to virbr0
+    del_iptables_rule('mangle', 'POSTROUTING', ['-p', 'udp', '--dport', 'bootpc', '-o', 'virbr0', '-j', 'CHECKSUM', '--checksum-fill'])
 
-    add_iptables_rule('nat', 'PREROUTING', ['-j', plugin]) 
+    # add the new rule that is attached to all devices
+    add_iptables_rule('mangle', 'POSTROUTING', ['-p', 'udp', '--dport', 'bootpc', '-j', 'CHECKSUM', '--checksum-fill'])
 
 # Nova blocks packets from external addresses by default.
 # This is hacky but it gets around the issue.
 def unfilter_ipaddr(dev, ipaddr):
-    add_iptables_rule(table = 'filter', 
-                      chain = 'nova-compute-sg-fallback', 
-                      args = ['-d', ipaddr, '-j', 'ACCEPT'], 
+    add_iptables_rule(table = 'filter',
+                      chain = 'nova-compute-sg-fallback',
+                      args = ['-d', ipaddr, '-j', 'ACCEPT'],
                       pos = 1)
-    
+
 # Enable iptables MASQ for a device
 def add_iptables_masq(dev, cidr):
     args = ['-s',  cidr, '!',  '-d',  cidr, '-j', 'MASQUERADE']
@@ -380,7 +402,7 @@ def main(argv):
         except:
             print("%s: no network called %s..." % (plugin, nat_net_name))
             sys.exit(1)
-            
+
     print("%s: %s id is %s..." % (plugin, nat_net_name, nat_net_id))
 
     if not site_net_id:
@@ -389,11 +411,11 @@ def main(argv):
             print("%s: %s id is %s..." % (plugin, site_net_name, site_net_id))
         except:
             print("%s: no network called %s..." % (plugin, site_net_name))
-            
+
     reset_iptables_chain()
     ports = get_local_neutron_ports()
     # print ports
-    
+
     # Set IP address on br-nat if necessary
     (nat_ip_addr, nat_cidr) = get_subnet_network(nat_net_id)
     set_ip_address(nat_net_dev, nat_ip_addr, nat_cidr)
@@ -412,5 +434,7 @@ def main(argv):
         block_remote_dns_queries(ipaddr, cidr)
         start_dnsmasq(site_net_dev, ipaddr, authoritative=True)
 
+    fix_udp_mangle()
+
 if __name__ == "__main__":
    main(sys.argv[1:])