1
0
mirror of https://github.com/CumulusNetworks/ifupdown2.git synced 2024-05-06 15:54:50 +00:00

Modified ifupdown support for vxlan head end replication

Replaced vxlan-peernodeip attribute with vxlan-remoteip.  Updated
the vxlan and iproute2 modules to configure head end replication
using bridge fdb commands.
(cherry picked from commit 567f445fc4a1828fc2aac0da3f2402a185656cb5)

Conflicts:
	packages/ifupdown2/addons/vxlan.py
	packages/ifupdown2/ifupdownaddons/iproute2.py

Conflicts:
	ifupdown2/addons/vxlan.py
	ifupdown2/ifupdownaddons/iproute2.py
This commit is contained in:
Wilson Kok
2015-04-15 09:48:12 -07:00
committed by Sam Tannous
parent 9ab24843eb
commit e04e8cba9e
2 changed files with 108 additions and 32 deletions

View File

@@ -20,9 +20,9 @@ class vxlan(moduleBase):
'vxlan-svcnodeip' :
{'help' : 'vxlan id',
'example': ['vxlan-svcnodeip 172.16.22.125']},
'vxlan-peernodeip' :
{'help' : 'vxlan peer node ip',
'example': ['vxlan-peernodeip 172.16.22.127']},
'vxlan-remoteip' :
{'help' : 'vxlan remote ip',
'example': ['vxlan-remoteip 172.16.22.127']},
'vxlan-learning' :
{'help' : 'vxlan learning on/off',
'example': ['vxlan-learning off'],
@@ -44,8 +44,9 @@ class vxlan(moduleBase):
self.ipcmd.link_create_vxlan(ifaceobj.name, vxlanid,
localtunnelip=ifaceobj.get_attr_value_first('vxlan-local-tunnelip'),
svcnodeips=ifaceobj.get_attr_value('vxlan-svcnodeip'),
peernodeips=ifaceobj.get_attr_value('vxlan-peernodeip'),
learning=ifaceobj.get_attr_value_first('vxlan-learning'))
remoteips=ifaceobj.get_attr_value('vxlan-remoteip'),
learning=ifaceobj.get_attr_value_first('vxlan-learning'),
ageing=ifaceobj.get_attr_value_first('vxlan-ageing'))
if ifaceobj.addr_method == 'manual':
rtnetlink_api.rtnl_api.link_set(ifaceobj.name, "up")
@@ -96,11 +97,13 @@ class vxlan(moduleBase):
ifaceobj.get_attr_value('vxlan-svcnodeip'),
vxlanattrs.get('svcnode', []))
self._query_check_n_update_addresses(ifaceobjcurr, 'vxlan-peernodeip',
ifaceobj.get_attr_value('vxlan-peernodeip'),
vxlanattrs.get('peernode', []))
self._query_check_n_update_addresses(ifaceobjcurr, 'vxlan-remoteip',
ifaceobj.get_attr_value('vxlan-remoteip'),
vxlanattrs.get('remote', []))
learning = ifaceobj.get_attr_value_first('vxlan-learning')
if not learning:
learning = 'on'
running_learning = vxlanattrs.get('learning')
if learning == running_learning:
ifaceobjcurr.update_config_with_status('vxlan-learning',
@@ -123,9 +126,9 @@ class vxlan(moduleBase):
if attrval:
[ifaceobjrunning.update_config('vxlan-svcnode', a)
for a in attrval]
attrval = vxlanattrs.get('peernode')
attrval = vxlanattrs.get('remote')
if attrval:
[ifaceobjrunning.update_config('vxlan-peernode', a)
[ifaceobjrunning.update_config('vxlan-remoteip', a)
for a in attrval]
attrval = vxlanattrs.get('learning')
if attrval and attrval == 'on':

View File

@@ -9,6 +9,8 @@ from collections import OrderedDict
from utilsbase import *
from cache import *
VXLAN_UDP_PORT = 4789
class iproute2(utilsBase):
""" This class contains helper methods to cache and interact with the
commands in the iproute2 package """
@@ -68,6 +70,8 @@ class iproute2(utilsBase):
elif citems[i] == 'vxlan' and citems[i+1] == 'id':
vattrs = {'vxlanid' : citems[i+2],
'svcnode' : [],
'remote' : [],
'ageing' : citems[i+2],
'learning': 'on'}
for j in range(i+2, len(citems)):
if citems[j] == 'local':
@@ -78,6 +82,10 @@ class iproute2(utilsBase):
vattrs['peernode'].append(citems[j+1])
elif citems[j] == 'nolearning':
vattrs['learning'] = 'off'
# get vxlan peer nodes
peers = self.get_vxlan_peers(ifname)
if peers:
vattrs['remote'] = peers
linkattrs['linkinfo'] = vattrs
break
#linkattrs['alias'] = self.read_file_oneline(
@@ -456,35 +464,80 @@ class iproute2(utilsBase):
self.exec_command('ip %s' %cmd)
self._cache_update([name], {})
def get_vxlan_peers(self, dev):
cmd = 'bridge fdb show brport %s' % dev
cur_peers = []
try:
ps = subprocess.Popen((cmd).split(), stdout=subprocess.PIPE, close_fds=True)
output = subprocess.check_output(('grep', '00:00:00:00:00:00'), stdin=ps.stdout)
ps.wait()
try:
ppat = re.compile('\s+dst\s+(\d+.\d+.\d+.\d+)\s+')
for l in output.split('\n'):
m = ppat.search(l)
if m:
cur_peers.append(m.group(1))
except:
self.logger.warn('error parsing ip link output')
pass
except subprocess.CalledProcessError as e:
if e.returncode != 1:
self.logger.error(str(e))
return cur_peers
def link_create_vxlan(self, name, vxlanid,
localtunnelip=None,
svcnodeips=None,
peernodeips=None,
learning='on'):
if svcnodeips and peernodeips:
raise Exception("svcnodeip and peernodeip is mutually exclusive")
remoteips=None,
learning='on',
ageing=None):
if svcnodeips and remoteips:
raise Exception("svcnodeip and remoteip is mutually exclusive")
args = ''
if localtunnelip:
args += ' local %s' %localtunnelip
if svcnodeips:
for s in svcnodeips:
args += ' svcnode %s' %s
if peernodeips:
for s in peernodeips:
args += ' peernode %s' %s
if ageing:
args += ' ageing %s' %ageing
if learning == 'off':
args += ' nolearning'
if self.link_exists(name):
cmd = 'link set dev %s type vxlan ' %(name)
cmd = 'link set dev %s type vxlan dstport %d' %(name, VXLAN_UDP_PORT)
else:
cmd = 'link add dev %s type vxlan id %s' %(name, vxlanid)
cmd = 'link add dev %s type vxlan id %s dstport %d' %(name, vxlanid, VXLAN_UDP_PORT)
cmd += args
if self.ipbatch and not self.ipbatch_pause:
self.add_to_batch(cmd)
else:
self.exec_command('ip %s' %cmd)
# figure out the diff for remotes and do the bridge fdb updates
cur_peers = set(self.get_vxlan_peers(name))
if remoteips:
new_peers = set(remoteips)
del_list = cur_peers.difference(new_peers)
add_list = new_peers.difference(cur_peers)
else:
del_list = cur_peers
add_list = []
try:
for addr in del_list:
self.bridge_fdb_del(name, '00:00:00:00:00:00', None, True, addr)
except:
pass
try:
for addr in add_list:
self.bridge_fdb_append(name, '00:00:00:00:00:00', None, True, addr)
except:
pass
# XXX: update linkinfo correctly
self._cache_update([name], {})
@@ -620,23 +673,43 @@ class iproute2(utilsBase):
[self.exec_command('bridge vlan del vid %s dev %s %s'
%(v, bridgeportname, target)) for v in vids]
def bridge_fdb_add(self, dev, address, vlan=None, bridge=True):
def bridge_fdb_add(self, dev, address, vlan=None, bridge=True, remote=None):
target = 'self' if bridge else ''
vlan_str = ''
if vlan:
self.exec_command('bridge fdb replace %s dev %s vlan %s %s'
%(address, dev, vlan, target))
else:
self.exec_command('bridge fdb replace %s dev %s %s'
%(address, dev, target))
vlan_str = 'vlan %s ' % vlan
def bridge_fdb_del(self, dev, address, vlan=None, bridge=True):
dst_str = ''
if remote:
dst_str = 'dst %s ' % remote
self.exec_command('bridge fdb replace %s dev %s %s %s %s'
%(address, dev, vlan_str, target, dst_str))
def bridge_fdb_append(self, dev, address, vlan=None, bridge=True, remote=None):
target = 'self' if bridge else ''
vlan_str = ''
if vlan:
self.exec_command('bridge fdb del %s dev %s vlan %s %s'
%(address, dev, vlan, target))
else:
self.exec_command('bridge fdb del %s dev %s %s'
%(address, dev, target))
vlan_str = 'vlan %s ' % vlan
dst_str = ''
if remote:
dst_str = 'dst %s ' % remote
self.exec_command('bridge fdb append %s dev %s %s %s %s'
%(address, dev, vlan_str, target, dst_str))
def bridge_fdb_del(self, dev, address, vlan=None, bridge=True, remote=None):
target = 'self' if bridge else ''
vlan_str = ''
if vlan:
vlan_str = 'vlan %s ' % vlan
dst_str = ''
if remote:
dst_str = 'dst %s ' % remote
self.exec_command('bridge fdb del %s dev %s %s %s %s'
%(address, dev, vlan_str, target, dst_str))
def bridge_is_vlan_aware(self, bridgename):
filename = '/sys/class/net/%s/bridge/vlan_filtering' %bridgename