diff options
Diffstat (limited to 'src/conf_mode/interfaces-pseudo-ethernet.py')
-rwxr-xr-x | src/conf_mode/interfaces-pseudo-ethernet.py | 128 |
1 files changed, 105 insertions, 23 deletions
diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py index 864e28936..ce3d472c4 100755 --- a/src/conf_mode/interfaces-pseudo-ethernet.py +++ b/src/conf_mode/interfaces-pseudo-ethernet.py @@ -21,8 +21,10 @@ from sys import exit from netifaces import interfaces from vyos.ifconfig import MACVLANIf -from vyos.configdict import list_diff +from vyos.ifconfig_vlan import apply_vlan_config, verify_vlan_config +from vyos.configdict import list_diff, vlan_to_dict from vyos.config import Config +from vyos.util import is_bridge_member from vyos import ConfigError default_config_data = { @@ -44,15 +46,20 @@ default_config_data = { 'ip_enable_arp_ignore': 0, 'ip_proxy_arp': 0, 'ip_proxy_arp_pvlan': 0, + 'ipv6_autoconf': 0, + 'ipv6_eui64_prefix': '', + 'ipv6_forwarding': 1, + 'ipv6_dup_addr_detect': 1, 'intf': '', - 'link': '', - 'link_changed': False, + 'source_interface': '', + 'source_interface_changed': False, 'mac': '', 'mode': 'private', 'vif_s': [], 'vif_s_remove': [], 'vif': [], - 'vif_remove': [] + 'vif_remove': [], + 'vrf': '' } def get_config(): @@ -60,11 +67,10 @@ def get_config(): conf = Config() # determine tagNode instance - try: - peth['intf'] = os.environ['VYOS_TAGNODE_VALUE'] - except KeyError as E: - print("Interface not specified") + if 'VYOS_TAGNODE_VALUE' not in os.environ: + raise ConfigError('Interface (VYOS_TAGNODE_VALUE) not specified') + peth['intf'] = os.environ['VYOS_TAGNODE_VALUE'] cfg_base = ['interfaces', 'pseudo-ethernet', peth['intf']] # Check if interface has been removed @@ -144,12 +150,28 @@ def get_config(): if conf.exists(['ip', 'proxy-arp-pvlan']): peth['ip_proxy_arp_pvlan'] = 1 - # Lower link device - if conf.exists(['link']): - peth['link'] = conf.return_value(['link']) - tmp = conf.return_effective_value(['link']) - if tmp != peth['link']: - peth['link_changed'] = True + # Enable acquisition of IPv6 address using stateless autoconfig (SLAAC) + if conf.exists('ipv6 address autoconf'): + peth['ipv6_autoconf'] = 1 + + # Get prefix for IPv6 addressing based on MAC address (EUI-64) + if conf.exists('ipv6 address eui64'): + peth['ipv6_eui64_prefix'] = conf.return_value('ipv6 address eui64') + + # Disable IPv6 forwarding on this interface + if conf.exists('ipv6 disable-forwarding'): + peth['ipv6_forwarding'] = 0 + + # IPv6 Duplicate Address Detection (DAD) tries + if conf.exists('ipv6 dup-addr-detect-transmits'): + peth['ipv6_dup_addr_detect'] = int(conf.return_value('ipv6 dup-addr-detect-transmits')) + + # Physical interface + if conf.exists(['source-interface']): + peth['source_interface'] = conf.return_value(['source-interface']) + tmp = conf.return_effective_value(['source-interface']) + if tmp != peth['source_interface']: + peth['source_interface_changed'] = True # Media Access Control (MAC) address if conf.exists(['mac']): @@ -159,6 +181,10 @@ def get_config(): if conf.exists(['mode']): peth['mode'] = conf.return_value(['mode']) + # retrieve VRF instance + if conf.exists('vrf'): + peth['vrf'] = conf.return_value('vrf') + # re-set configuration level to parse new nodes conf.set_level(cfg_base) # get vif-s interfaces (currently effective) - to determine which vif-s @@ -192,11 +218,27 @@ def get_config(): def verify(peth): if peth['deleted']: + interface = peth['intf'] + is_member, bridge = is_bridge_member(interface) + if is_member: + # can not use a f'' formatted-string here as bridge would not get + # expanded in the print statement + raise ConfigError('Can not delete interface "{0}" as it ' \ + 'is a member of bridge "{1}"!'.format(interface, bridge)) return None - if not peth['link']: + if not peth['source_interface']: raise ConfigError('Link device must be set for virtual ethernet {}'.format(peth['intf'])) + if not peth['source_interface'] in interfaces(): + raise ConfigError('Pseudo-ethernet source interface does not exist') + + vrf_name = peth['vrf'] + if vrf_name and vrf_name not in interfaces(): + raise ConfigError(f'VRF "{vrf_name}" does not exist') + + # use common function to verify VLAN configuration + verify_vlan_config(peth) return None def generate(peth): @@ -211,12 +253,12 @@ def apply(peth): p.remove() return None - elif peth['link_changed']: + elif peth['source_interface_changed']: # Check if MACVLAN interface already exists. Parameters like the - # underlaying link device can not be changed on the fly and the - # interface needs to be recreated from the bottom. + # underlaying source-interface device can not be changed on the fly + # and the interface needs to be recreated from the bottom. # - # link_changed also means - the interface was not present in the + # source_interface_changed also means - the interface was not present in the # beginning and is newly created if peth['intf'] in interfaces(): p = MACVLANIf(peth['intf']) @@ -227,12 +269,12 @@ def apply(peth): conf = deepcopy(MACVLANIf.get_config()) # Assign MACVLAN instance configuration parameters to config dict - conf['link'] = peth['link'] + conf['source_interface'] = peth['source_interface'] conf['mode'] = peth['mode'] # It is safe to "re-create" the interface always, there is a sanity check # that the interface will only be create if its non existent - p = MACVLANIf(peth['intf'], config=conf) + p = MACVLANIf(peth['intf'], **conf) else: p = MACVLANIf(peth['intf']) @@ -282,6 +324,17 @@ def apply(peth): p.set_proxy_arp(peth['ip_proxy_arp']) # Enable private VLAN proxy ARP on this interface p.set_proxy_arp_pvlan(peth['ip_proxy_arp_pvlan']) + # IPv6 address autoconfiguration + p.set_ipv6_autoconf(peth['ipv6_autoconf']) + # IPv6 EUI-based address + p.set_ipv6_eui64_address(peth['ipv6_eui64_prefix']) + # IPv6 forwarding + p.set_ipv6_forwarding(peth['ipv6_forwarding']) + # IPv6 Duplicate Address Detection (DAD) tries + p.set_ipv6_dad_messages(peth['ipv6_dup_addr_detect']) + + # assign/remove VRF + p.set_vrf(peth['vrf']) # Change interface MAC address if peth['mac']: @@ -292,9 +345,9 @@ def apply(peth): # Enable/Disable interface if peth['disable']: - p.set_state('down') + p.set_admin_state('down') else: - p.set_state('up') + p.set_admin_state('up') # Configure interface address(es) # - not longer required addresses get removed first @@ -304,6 +357,35 @@ def apply(peth): for addr in peth['address']: p.add_addr(addr) + # remove no longer required service VLAN interfaces (vif-s) + for vif_s in peth['vif_s_remove']: + p.del_vlan(vif_s) + + # create service VLAN interfaces (vif-s) + for vif_s in peth['vif_s']: + s_vlan = p.add_vlan(vif_s['id'], ethertype=vif_s['ethertype']) + apply_vlan_config(s_vlan, vif_s) + + # remove no longer required client VLAN interfaces (vif-c) + # on lower service VLAN interface + for vif_c in vif_s['vif_c_remove']: + s_vlan.del_vlan(vif_c) + + # create client VLAN interfaces (vif-c) + # on lower service VLAN interface + for vif_c in vif_s['vif_c']: + c_vlan = s_vlan.add_vlan(vif_c['id']) + apply_vlan_config(c_vlan, vif_c) + + # remove no longer required VLAN interfaces (vif) + for vif in peth['vif_remove']: + p.del_vlan(vif) + + # create VLAN interfaces (vif) + for vif in peth['vif']: + vlan = p.add_vlan(vif['id']) + apply_vlan_config(vlan, vif) + return None if __name__ == '__main__': |