From 61cf03e22bbd1cef574e1884e9814cc3cc464a90 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 5 Aug 2019 11:41:39 +0200 Subject: [bridge] T1156: support adding interface addresses --- python/vyos/configinterface.py | 40 +++++++++++++++++++++++++ src/conf_mode/interface-bridge.py | 61 +++++++++++++++++++++++++-------------- 2 files changed, 79 insertions(+), 22 deletions(-) diff --git a/python/vyos/configinterface.py b/python/vyos/configinterface.py index 0f25c4a89..0f5b0842c 100644 --- a/python/vyos/configinterface.py +++ b/python/vyos/configinterface.py @@ -14,6 +14,7 @@ # License along with this library. If not, see . import os +import vyos.validate def validate_mac_address(addr): # a mac address consits out of 6 octets @@ -111,3 +112,42 @@ def set_link_detect(intf, enable): os.system('/usr/bin/vtysh -c "configure terminal" -c "interface {}" -c "no link-detect"'.format(intf)) pass + +def add_interface_address(intf, addr): + """ + Configure an interface IPv4/IPv6 address + """ + if addr == "dhcp": + os.system('/opt/vyatta/sbin/vyatta-interfaces.pl --dev="{}" --dhcp=start'.format(intf)) + elif addr == "dhcpv6": + os.system('/opt/vyatta/sbin/vyatta-dhcpv6-client.pl --start -ifname "{}"'.format(intf)) + elif vyos.validate.is_ipv4(addr): + if not vyos.validate.is_intf_addr_assigned(intf, addr): + print("Assigning {} to {}".format(addr, intf)) + os.system('sudo ip -4 addr add "{}" broadcast + dev "{}"'.format(addr, intf)) + elif vyos.validate.is_ipv6(addr): + if not vyos.validate.is_intf_addr_assigned(intf, addr): + print("Assigning {} to {}".format(addr, intf)) + os.system('sudo ip -6 addr add "{}" dev "{}"'.format(addr, intf)) + else: + raise ConfigError('{} is not a valid interface address'.format(addr)) + + pass + +def remove_interface_address(intf, addr): + """ + Remove IPv4/IPv6 address from given interface + """ + + if addr == "dhcp": + os.system('/opt/vyatta/sbin/vyatta-interfaces.pl --dev="{}" --dhcp=stop'.format(intf)) + elif addr == "dhcpv6": + os.system('/opt/vyatta/sbin/vyatta-dhcpv6-client.pl --stop -ifname "{}"'.format(intf)) + elif vyos.validate.is_ipv4(addr): + os.system('ip -4 addr del "{}" dev "{}"'.format(addr, intf)) + elif vyos.validate.is_ipv6(addr): + os.system('ip -6 addr del "{}" dev "{}"'.format(addr, intf)) + else: + raise ConfigError('{} is not a valid interface address'.format(addr)) + + pass diff --git a/src/conf_mode/interface-bridge.py b/src/conf_mode/interface-bridge.py index 4f1cbd17c..93eb3839c 100755 --- a/src/conf_mode/interface-bridge.py +++ b/src/conf_mode/interface-bridge.py @@ -28,6 +28,7 @@ from vyos import ConfigError default_config_data = { 'address': [], + 'address_remove': [], 'aging': '300', 'br_name': '', 'description': '', @@ -53,7 +54,7 @@ default_config_data = { def subprocess_cmd(command): process = subprocess.Popen(command,stdout=subprocess.PIPE, shell=True) proc_stdout = process.communicate()[0].strip() - print(proc_stdout) + pass def diff(first, second): second = set(second) @@ -154,12 +155,18 @@ def get_config(): bridge['member'].append(iface) - # Determine bridge member interface (currently effective) - to determine which interfaces - # need to be removed from the bridge + # Determine bridge member interface (currently effective) - to determine which + # interfaces is no longer assigend to the bridge and thus can be removed eff_intf = conf.list_effective_nodes('member interface') act_intf = conf.list_nodes('member interface') bridge['member_remove'] = diff(eff_intf, act_intf) + # Determine interface addresses (currently effective) - to determine which + # address is no longer valid and needs to be removed from the bridge + eff_addr = conf.return_effective_values('address') + act_addr = conf.return_values('address') + bridge['address_remove'] = diff(eff_addr, act_addr) + # Priority for this bridge if conf.exists('priority'): bridge['priority'] = conf.return_value('priority') @@ -197,72 +204,75 @@ def apply(bridge): if bridge is None: return None + cmd = '' if bridge['deleted']: # bridges need to be shutdown first - os.system("ip link set dev {} down".format(bridge['br_name'])) + cmd += 'ip link set dev "{}" down'.format(bridge['br_name']) + cmd += ' && ' # delete bridge - os.system("brctl delbr {}".format(bridge['br_name'])) + cmd += 'brctl delbr "{}"'.format(bridge['br_name']) + subprocess_cmd(cmd) + else: # create bridge if it does not exist if not os.path.exists("/sys/class/net/" + bridge['br_name']): - os.system("brctl addbr {}".format(bridge['br_name'])) - - # assemble bridge configuration - # configuration is passed via subprocess to brctl - cmd = '' + # create bridge interface + cmd += 'brctl addbr "{}"'.format(bridge['br_name']) + cmd += ' && ' + # activate "UP" the interface + cmd += 'ip link set dev "{}" up'.format(bridge['br_name']) + cmd += ' && ' # set ageing time - cmd += 'brctl setageing {} {}'.format(bridge['br_name'], bridge['aging']) + cmd += 'brctl setageing "{}" "{}"'.format(bridge['br_name'], bridge['aging']) cmd += ' && ' # set bridge forward delay - cmd += 'brctl setfd {} {}'.format(bridge['br_name'], bridge['forwarding_delay']) + cmd += 'brctl setfd "{}" "{}"'.format(bridge['br_name'], bridge['forwarding_delay']) cmd += ' && ' # set hello time - cmd += 'brctl sethello {} {}'.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 {} {}'.format(bridge['br_name'], bridge['max_age']) + cmd += 'brctl setmaxage "{}" "{}"'.format(bridge['br_name'], bridge['max_age']) cmd += ' && ' # set bridge priority - cmd += 'brctl setbridgeprio {} {}'.format(bridge['br_name'], bridge['priority']) + cmd += 'brctl setbridgeprio "{}" "{}"'.format(bridge['br_name'], bridge['priority']) cmd += ' && ' # turn stp on/off - cmd += 'brctl stp {} {}'.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) + 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']) + 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']) + 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']) + 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']) @@ -276,6 +286,13 @@ def apply(bridge): # ARP cache entry timeout in seconds VyIfconfig.set_arp_cache_timeout(bridge['br_name'], bridge['arp_cache_timeout_ms']) + # Configure interface address(es) + for addr in bridge['address_remove']: + VyIfconfig.remove_interface_address(bridge['br_name'], addr) + + for addr in bridge['address']: + VyIfconfig.add_interface_address(bridge['br_name'], addr) + return None if __name__ == '__main__': -- cgit v1.2.3