summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--interface-definitions/interfaces-bridge.xml76
-rw-r--r--python/vyos/configinterface.py8
-rwxr-xr-xsrc/conf_mode/interface-bridge.py86
-rwxr-xr-xsrc/migration-scripts/interfaces/0-to-1 (renamed from src/migration-scripts/interface/0-to-1)0
4 files changed, 125 insertions, 45 deletions
diff --git a/interface-definitions/interfaces-bridge.xml b/interface-definitions/interfaces-bridge.xml
index a5f2df5b5..af19d9438 100644
--- a/interface-definitions/interfaces-bridge.xml
+++ b/interface-definitions/interfaces-bridge.xml
@@ -51,7 +51,8 @@
<description>Address aging time for bridge seconds (default 300)</description>
</valueHelp>
<constraint>
- <validator name="numeric" argument="--range 0-1000000"/>
+ <validator name="numeric" argument="--range 0-0"/>
+ <validator name="numeric" argument="--range 10-1000000"/>
</constraint>
</properties>
</leafNode>
@@ -146,20 +147,7 @@
<leafNode name="querier">
<properties>
<help>Enable or disable IGMP querier</help>
- <completionHelp>
- <list>enable disable</list>
- </completionHelp>
- <valueHelp>
- <format>enable</format>
- <description>Enable IGMP querier</description>
- </valueHelp>
- <valueHelp>
- <format>disable</format>
- <description>Disable IGMP querier</description>
- </valueHelp>
- <constraint>
- <regex>(enable|disable)</regex>
- </constraint>
+ <valueless/>
</properties>
</leafNode>
</children>
@@ -206,6 +194,49 @@
<constraintErrorMessage>Bridge max aging value must be between 1 and 40 seconds</constraintErrorMessage>
</properties>
</leafNode>
+ <node name="member">
+ <properties>
+ <help>Bridge member interfaces</help>
+ </properties>
+ <children>
+ <tagNode name="interface">
+ <properties>
+ <help>Member interface name</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py --bridgeable</script>
+ </completionHelp>
+ </properties>
+ <children>
+ <leafNode name="cost">
+ <properties>
+ <help>Bridge port cost</help>
+ <valueHelp>
+ <format>1-65535</format>
+ <description>Path cost value for Spanning Tree Protocol</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ <constraintErrorMessage>Path cost value must be between 1 and 65535</constraintErrorMessage>
+ </properties>
+ </leafNode>
+ <leafNode name="priority">
+ <properties>
+ <help>Bridge port priority</help>
+ <valueHelp>
+ <format>0-63</format>
+ <description>Bridge port priority</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-63"/>
+ </constraint>
+ <constraintErrorMessage>Port priority value must be between 0 and 63</constraintErrorMessage>
+ </properties>
+ </leafNode>
+ </children>
+ </tagNode>
+ </children>
+ </node>
<leafNode name="priority">
<properties>
<help>Priority for this bridge</help>
@@ -222,20 +253,7 @@
<leafNode name="stp">
<properties>
<help>Enable spanning tree protocol</help>
- <completionHelp>
- <list>true false</list>
- </completionHelp>
- <valueHelp>
- <format>true</format>
- <description>Enable Spanning Tree Protocol</description>
- </valueHelp>
- <valueHelp>
- <format>false</format>
- <description>Disable Spanning Tree Protocol</description>
- </valueHelp>
- <constraint>
- <regex>(true|false)</regex>
- </constraint>
+ <valueless/>
</properties>
</leafNode>
</children>
diff --git a/python/vyos/configinterface.py b/python/vyos/configinterface.py
index b0d766b9c..37b6b92c1 100644
--- a/python/vyos/configinterface.py
+++ b/python/vyos/configinterface.py
@@ -15,6 +15,14 @@
import os
+def set_mac_address(intf, addr):
+ """
+ Configure interface mac address using iproute2 command
+
+ NOTE: mac address should be validated here???
+ """
+ os.system('ip link set {} address {}'.format(intf, addr))
+
def set_description(intf, desc):
"""
Sets the interface secription reported usually by SNMP
diff --git a/src/conf_mode/interface-bridge.py b/src/conf_mode/interface-bridge.py
index f7f70b15d..637c58a5e 100755
--- a/src/conf_mode/interface-bridge.py
+++ b/src/conf_mode/interface-bridge.py
@@ -44,6 +44,8 @@ default_config_data = {
'arp_cache_timeout_ms': '30000',
'mac' : '',
'max_age': '20',
+ 'member': [],
+ 'member_remove': [],
'priority': '32768',
'stp': 'off'
}
@@ -53,6 +55,10 @@ def subprocess_cmd(command):
proc_stdout = process.communicate()[0].strip()
print(proc_stdout)
+def diff(first, second):
+ second = set(second)
+ return [item for item in first if item not in second]
+
def get_config():
bridge = copy.deepcopy(default_config_data)
conf = Config()
@@ -60,7 +66,6 @@ def get_config():
# determine tagNode instance
try:
bridge['br_name'] = os.environ['VYOS_TAGNODE_VALUE']
- print("Executing script for interface: " + bridge['br_name'])
except KeyError as E:
print("Interface not specified")
@@ -118,9 +123,7 @@ def get_config():
# Enable or disable IGMP querier
if conf.exists('igmp-snooping querier'):
- tmp = conf.return_value('igmp-snooping querier')
- if tmp == "enable":
- bridge['igmp_querier'] = 1
+ bridge['igmp_querier'] = 1
# ARP cache entry timeout in seconds
if conf.exists('ip arp-cache-timeout'):
@@ -135,15 +138,35 @@ def get_config():
if conf.exists('max-age'):
bridge['max_age'] = conf.return_value('max-age')
+ # Determine bridge member interface (currently configured)
+ for intf in conf.list_nodes('member interface'):
+ iface = {
+ 'name': intf,
+ 'cost': '',
+ 'priority': ''
+ }
+
+ if conf.exists('member interface {} cost'.format(intf)):
+ iface['cost'] = conf.return_value('member interface {} cost'.format(intf))
+
+ if conf.exists('member interface {} priority'.format(intf)):
+ iface['priority'] = conf.return_value('member interface {} priority'.format(intf))
+
+ bridge['member'].append(iface)
+
+ # Determine bridge member interface (currently effective) - to determine which interfaces
+ # need to be removed from the bridge
+ eff_intf = conf.list_effective_nodes('member interface')
+ act_intf = conf.list_nodes('member interface')
+ bridge['member_remove'] = diff(eff_intf, act_intf)
+
# Priority for this bridge
if conf.exists('priority'):
bridge['priority'] = conf.return_value('priority')
# Enable spanning tree protocol
if conf.exists('stp'):
- tmp = conf.return_value('stp')
- if tmp == "true":
- bridge['stp'] = 'on'
+ bridge['stp'] = 'on'
return bridge
@@ -151,6 +174,9 @@ def verify(bridge):
if bridge is None:
return None
+ # validate agains other bridge interfaces that the interface is not assigned
+ # to another bridge
+
return None
def generate(bridge):
@@ -165,43 +191,71 @@ def apply(bridge):
if bridge['deleted']:
# bridges need to be shutdown first
- os.system("ip link set dev {0} down".format(bridge['br_name']))
+ os.system("ip link set dev {} down".format(bridge['br_name']))
# delete bridge
- os.system("brctl delbr {0}".format(bridge['br_name']))
+ os.system("brctl delbr {}".format(bridge['br_name']))
else:
# create bridge if it does not exist
if not os.path.exists("/sys/class/net/" + bridge['br_name']):
- os.system("brctl addbr {0}".format(bridge['br_name']))
+ os.system("brctl addbr {}".format(bridge['br_name']))
# assemble bridge configuration
# configuration is passed via subprocess to brctl
cmd = ''
# set ageing time
- cmd += 'brctl setageing {0} {1}'.format(bridge['br_name'], bridge['aging'])
+ cmd += 'brctl setageing {} {}'.format(bridge['br_name'], bridge['aging'])
cmd += ' && '
# set bridge forward delay
- cmd += 'brctl setfd {0} {1}'.format(bridge['br_name'], bridge['forwarding_delay'])
+ cmd += 'brctl setfd {} {}'.format(bridge['br_name'], bridge['forwarding_delay'])
cmd += ' && '
# set hello time
- cmd += 'brctl sethello {0} {1}'.format(bridge['br_name'], bridge['hello_time'])
+ cmd += 'brctl sethello {} {}'.format(bridge['br_name'], bridge['hello_time'])
cmd += ' && '
# set max message age
- cmd += 'brctl setmaxage {0} {1}'.format(bridge['br_name'], bridge['max_age'])
+ cmd += 'brctl setmaxage {} {}'.format(bridge['br_name'], bridge['max_age'])
cmd += ' && '
# set bridge priority
- cmd += 'brctl setbridgeprio {0} {1}'.format(bridge['br_name'], bridge['priority'])
+ cmd += 'brctl setbridgeprio {} {}'.format(bridge['br_name'], bridge['priority'])
cmd += ' && '
# turn stp on/off
- cmd += 'brctl stp {0} {1}'.format(bridge['br_name'], bridge['stp'])
+ cmd += 'brctl stp {} {}'.format(bridge['br_name'], bridge['stp'])
+
+ for intf in bridge['member_remove']:
+ # remove interface from bridge
+ cmd += ' && '
+ cmd += 'brctl delif {} {}'.format(bridge['br_name'], intf)
+
+ for intf in bridge['member']:
+ # add interface to bridge
+ # but only if it is not yet member of this bridge
+ if not os.path.exists('/sys/devices/virtual/net/' + bridge['br_name'] + '/brif/' + intf['name']):
+ cmd += ' && '
+ cmd += 'brctl addif {} {}'.format(bridge['br_name'], intf['name'])
+
+ # set bridge port cost
+ if intf['cost']:
+ cmd += ' && '
+ cmd += 'brctl setpathcost {} {} {}'.format(bridge['br_name'], intf['name'], intf['cost'])
+
+ # set bridge port priority
+ if intf['priority']:
+ cmd += ' && '
+ cmd += 'brctl setportprio {} {} {}'.format(bridge['br_name'], intf['name'], intf['priority'])
subprocess_cmd(cmd)
+ # Change interface MAC address
+ if bridge['mac']:
+ VyIfconfig.set_mac_address(bridge['br_name'], bridge['mac'])
+ else:
+ print("TODO: change mac mac address to the autoselected one based on member interfaces"
+
# update interface description used e.g. within SNMP
VyIfconfig.set_description(bridge['br_name'], bridge['description'])
diff --git a/src/migration-scripts/interface/0-to-1 b/src/migration-scripts/interfaces/0-to-1
index 1c6119d86..1c6119d86 100755
--- a/src/migration-scripts/interface/0-to-1
+++ b/src/migration-scripts/interfaces/0-to-1