[openstack-dev] [neutron] [VXLAN] patch to use per-VNI multicast group addresses

John Nielsen lists at jnielsen.net
Tue Jul 21 22:41:50 UTC 2015

I may be in a small minority since I a) use VXLAN, b) don’t hate multicast and c) use linuxbridge instead of OVS. However I thought I’d share this patch in case I’m not alone.

If you assume the use of multicast, VXLAN works quite nicely to isolate L2 domains AND to prevent delivery of unwanted broadcast/unknown/multicast packets to VTEPs that don’t need them. However, the latter only holds up if each VXLAN VNI uses its own unique multicast group address. Currently, you have to either disable multicast (and use l2_population or similar) or use only a single group address for ALL VNIs (and force every single VTEP to receive every BUM packet from every network). For my usage, this patch seems simpler.

Feedback is very welcome. In particular I’d like to know if anyone else finds this useful and if so, what (if any) changes might be required to get it committed. Thanks!


commit 17c32a9ad07911f3b4148e96cbcae88720eef322
Author: John Nielsen <john at jnielsen.net>
Date:   Tue Jul 21 16:13:42 2015 -0600

    Add a boolean option, vxlan_group_auto, which if enabled will compute
    a unique multicast group address group for each VXLAN VNI. Since VNIs
    are 24 bits, they map nicely to the "site-local" multicast
    range. Eight bits of the VNI are used for the second, third and fourth
    octets (with 239 always as the first octet).
    Using this option allows VTEPs to receive BUM datagrams via multicast,
    but only for those VNIs in which they participate. In other words, it is
    an alternative to the l2_population extension and driver for environments
    where both multicast and linuxbridge are used.
    If the option is True then multicast groups are computed as described
    above. If the option is False then the previous behavior is used
    (either a single multicast group is defined by vxlan_group or multicast
    is disabled).

diff --git a/etc/neutron/plugins/ml2/linuxbridge_agent.ini b/etc/neutron/plugins/ml2/linuxbridge_agent.ini
index d1a01ba..03578ad 100644
--- a/etc/neutron/plugins/ml2/linuxbridge_agent.ini
+++ b/etc/neutron/plugins/ml2/linuxbridge_agent.ini
@@ -25,6 +25,10 @@
 # This group must be the same on all the agents.
 # vxlan_group =
+# (BoolOpt) Derive a unique 239.x.x.x multicast group for each vxlan VNI.
+# If this option is true, the setting of vxlan_group is ignored.
+# vxlan_group_auto = False
 # (StrOpt) Local IP address to use for VXLAN endpoints (required)
 # local_ip =
diff --git a/neutron/plugins/ml2/drivers/linuxbridge/agent/common/config.py b/neutron/plugins/ml2/drivers/linuxbridge/agent/common/config.py
index 6f15236..b4805d5 100644
--- a/neutron/plugins/ml2/drivers/linuxbridge/agent/common/config.py
+++ b/neutron/plugins/ml2/drivers/linuxbridge/agent/common/config.py
@@ -31,6 +31,9 @@ vxlan_opts = [
                help=_("TOS for vxlan interface protocol packets.")),
     cfg.StrOpt('vxlan_group', default=DEFAULT_VXLAN_GROUP,
                help=_("Multicast group for vxlan interface.")),
+    cfg.BoolOpt('vxlan_group_auto', default=False,
+                help=_("Derive a unique 239.x.x.x multicast group for each "
+                       "vxlan VNI")),
     cfg.IPOpt('local_ip', version=4,
               help=_("Local IP address of the VXLAN endpoints.")),
     cfg.BoolOpt('l2_population', default=False,
diff --git a/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py b/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py
index 61627eb..a0efde1 100644
--- a/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py
+++ b/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py
@@ -127,6 +127,14 @@ class LinuxBridgeManager(object):
             LOG.warning(_LW("Invalid Segmentation ID: %s, will lead to "
                             "incorrect vxlan device name"), segmentation_id)
+    def get_vxlan_group(self, segmentation_id):
+        if cfg.CONF.VXLAN.vxlan_group_auto:
+            return ("239." +
+                    str(segmentation_id >> 16) + "." +
+                    str(segmentation_id >> 8 % 256) + "." +
+                    str(segmentation_id % 256))
+        return cfg.CONF.VXLAN.vxlan_group
     def get_all_neutron_bridges(self):
         neutron_bridge_list = []
         bridge_list = os.listdir(BRIDGE_FS)
@@ -240,7 +248,7 @@ class LinuxBridgeManager(object):
                        'segmentation_id': segmentation_id})
             args = {'dev': self.local_int}
             if self.vxlan_mode == lconst.VXLAN_MCAST:
-                args['group'] = cfg.CONF.VXLAN.vxlan_group
+                args['group'] = self.get_vxlan_group(segmentation_id)
             if cfg.CONF.VXLAN.ttl:
                 args['ttl'] = cfg.CONF.VXLAN.ttl
             if cfg.CONF.VXLAN.tos:
@@ -553,9 +561,10 @@ class LinuxBridgeManager(object):
     def vxlan_mcast_supported(self):
-        if not cfg.CONF.VXLAN.vxlan_group:
+        if not (cfg.CONF.VXLAN.vxlan_group or cfg.CONF.VXLAN.vxlan_group_auto):
             LOG.warning(_LW('VXLAN muticast group must be provided in '
-                            'vxlan_group option to enable VXLAN MCAST mode'))
+                            'vxlan_group option or vxlan_group_auto must '
+                            'be True to enable VXLAN MCAST mode'))
             return False
         if not ip_lib.iproute_arg_supported(
                 ['ip', 'link', 'add', 'type', 'vxlan'],

More information about the OpenStack-dev mailing list