X-Git-Url: https://gerrit.fd.io/r/gitweb?p=csit.git;a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2FSRv6.py;h=fe706f5f70d399ea6a1baa7f459e15af315ae9a8;hp=a22bb5e8328045afac4ee3e1d420aa1be9e8b0aa;hb=82094363f6077e1b28845719db3a6191c0c93a99;hpb=2291eaac7509aadf30be407a6eb84cfa3d3a33d0 diff --git a/resources/libraries/python/SRv6.py b/resources/libraries/python/SRv6.py index a22bb5e832..fe706f5f70 100644 --- a/resources/libraries/python/SRv6.py +++ b/resources/libraries/python/SRv6.py @@ -1,4 +1,4 @@ -# Copyright (c) 2017 Cisco and/or its affiliates. +# Copyright (c) 2018 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -13,29 +13,31 @@ """Segment Routing over IPv6 dataplane utilities library.""" -from enum import Enum - from resources.libraries.python.VatExecutor import VatTerminal -from resources.libraries.python.VatJsonUtil import VatJsonUtil from resources.libraries.python.topology import Topology -class SRv6Behaviour(Enum): - """Defines SRv6 endpoint functions implemented in VPP.""" - # Endpoint function - END = 'end' - # Endpoint function with Layer-3 cross-connect - END_X = 'end.x' - # Endpoint with decapsulation and Layer-2 cross-connect - END_DX2 = 'end.dx2' - # Endpoint with decapsulation and IPv4 cross-connect - END_DX4 = 'end.dx4' - # Endpoint with decapsulation and IPv4 table lookup - END_DT4 = 'end.dt4' - # Endpoint with decapsulation and IPv6 cross-connect - END_DX6 = 'end.dx6' - # Endpoint with decapsulation and IPv6 table lookup - END_DT6 = 'end.dt6' +# SRv6 LocalSID supported functions. +# Endpoint function +SRV6BEHAVIOUR_END = 'end' +# Endpoint function with Layer-3 cross-connect +SRV6BEHAVIOUR_END_X = 'end.x' +# Endpoint with decapsulation and Layer-2 cross-connect +SRV6BEHAVIOUR_END_DX2 = 'end.dx2' +# Endpoint with decapsulation and IPv4 cross-connect +SRV6BEHAVIOUR_END_DX4 = 'end.dx4' +# Endpoint with decapsulation and IPv4 table lookup +SRV6BEHAVIOUR_END_DT4 = 'end.dt4' +# Endpoint with decapsulation and IPv6 cross-connect +SRV6BEHAVIOUR_END_DX6 = 'end.dx6' +# Endpoint with decapsulation and IPv6 table lookup +SRV6BEHAVIOUR_END_DT6 = 'end.dt6' +# Endpoint to SR-unaware appliance via static proxy +SRV6BEHAVIOUR_END_AS = 'end.as' +# Endpoint to SR-unaware appliance via dynamic proxy +SRV6BEHAVIOUR_END_AD = 'end.ad' +# Endpoint to SR-unaware appliance via masquerading +SRV6BEHAVIOUR_END_AM = 'end.am' class SRv6(object): @@ -46,7 +48,8 @@ class SRv6(object): @staticmethod def configure_sr_localsid(node, local_sid, behavior, interface=None, - next_hop=None, fib_table=None): + next_hop=None, fib_table=None, out_if=None, + in_if=None, src_addr=None, sid_list=None): """Create SRv6 LocalSID and binds it to a particular behaviour on the given node. @@ -59,47 +62,77 @@ class SRv6(object): xconnects). :param fib_table: FIB table for IPv4/IPv6 lookup (Optional, required for L3 routing). + :param out_if: Interface name of local interface for sending traffic + towards the Service Function (Optional, required for SRv6 endpoint + to SR-unaware appliance). + :param in_if: Interface name of local interface receiving the traffic + coming back from the Service Function (Optional, required for SRv6 + endpoint to SR-unaware appliance). + :param src_addr: Source address on the packets coming back on in_if + interface (Optional, required for SRv6 endpoint to SR-unaware + appliance via static proxy). + :param sid_list: SID list (Optional, required for SRv6 endpoint to + SR-unaware appliance via static proxy). :type node: dict :type local_sid: str :type behavior: str :type interface: str :type next_hop: int :type fib_table: str + :type out_if: str + :type in_if: str + :type src_addr: str + :type sid_list: list :raises ValueError: If unsupported SRv6 LocalSID function used or required parameter is missing. """ - if behavior == SRv6Behaviour.END: + if behavior == SRV6BEHAVIOUR_END: params = '' - elif behavior in [SRv6Behaviour.END_X, SRv6Behaviour.END_DX4, - SRv6Behaviour.END_DX6]: + elif behavior in [SRV6BEHAVIOUR_END_X, SRV6BEHAVIOUR_END_DX4, + SRV6BEHAVIOUR_END_DX6]: if interface is None or next_hop is None: - raise ValueError('Required data missing.\ninterface:{0}\n' - 'next_hop:{1}'.format(interface, next_hop)) + raise ValueError('Required parameter(s) missing.\ninterface:{0}' + '\nnext_hop:{1}'.format(interface, next_hop)) interface_name = Topology.get_interface_name(node, interface) params = '{0} {1}'.format(interface_name, next_hop) - elif behavior == SRv6Behaviour.END_DX2: + elif behavior == SRV6BEHAVIOUR_END_DX2: if interface is None: - raise ValueError('Required data missing.\ninterface:{0}\n'. + raise ValueError('Required parameter missing.\ninterface:{0}'. format(interface)) params = '{0}'.format(interface) - elif behavior in [SRv6Behaviour.END_DT4, SRv6Behaviour.END_DT6]: + elif behavior in [SRV6BEHAVIOUR_END_DT4, SRV6BEHAVIOUR_END_DT6]: if fib_table is None: - raise ValueError('Required data missing.\nfib_table:{0}\n'. + raise ValueError('Required parameter missing.\nfib_table: {0}'. format(fib_table)) params = '{0}'.format(fib_table) + elif behavior == SRV6BEHAVIOUR_END_AS: + if next_hop is None or out_if is None or in_if is None or \ + src_addr is None or sid_list is None: + raise ValueError('Required parameter(s) missing.\nnext_hop:{0}' + '\nout_if:{1}\nin_if:{2}\nsrc_addr:{3}\n' + 'sid_list:{4}'.format(next_hop, out_if, in_if, + src_addr, sid_list)) + sid_conf = 'next ' + ' next '.join(sid_list) + params = 'nh {0} oif {1} iif {2} src {3} {4}'.\ + format(next_hop, out_if, in_if, src_addr, sid_conf) + elif behavior in [SRV6BEHAVIOUR_END_AD, SRV6BEHAVIOUR_END_AM]: + if next_hop is None or out_if is None or in_if is None: + raise ValueError('Required parameter(s) missing.\nnext_hop:{0}' + '\nout_if:{1}\nin_if:{2}'. + format(next_hop, out_if, in_if)) + params = 'nh {0} oif {1} iif {2}'.format(next_hop, out_if, in_if) else: raise ValueError('Unsupported SRv6 LocalSID function: {0}'. format(behavior)) - with VatTerminal(node) as vat: - resp = vat.vat_terminal_exec_cmd_from_template( + with VatTerminal(node, json_param=False) as vat: + vat.vat_terminal_exec_cmd_from_template( 'srv6/sr_localsid_add.vat', local_sid=local_sid, behavior=behavior, params=params) - VatJsonUtil.verify_vat_retval( - resp[0], - err_msg='Create SRv6 LocalSID {0} failed on node {1}'.format( - local_sid, node['host'])) + if "exec error: Misc" in vat.vat_stdout: + raise RuntimeError('Create SRv6 LocalSID {0} failed on node {1}'. + format(local_sid, node['host'])) @staticmethod def delete_sr_localsid(node, local_sid): @@ -110,14 +143,13 @@ class SRv6(object): :type node: dict :type local_sid: str """ - with VatTerminal(node) as vat: - resp = vat.vat_terminal_exec_cmd_from_template( + with VatTerminal(node, json_param=False) as vat: + vat.vat_terminal_exec_cmd_from_template( 'srv6/sr_localsid_del.vat', local_sid=local_sid) - VatJsonUtil.verify_vat_retval( - resp[0], - err_msg='Delete SRv6 LocalSID {0} failed on node {1}'.format( - local_sid, node['host'])) + if "exec error: Misc" in vat.vat_stdout: + raise RuntimeError('Delete SRv6 LocalSID {0} failed on node {1}'. + format(local_sid, node['host'])) @staticmethod def show_sr_localsids(node): @@ -126,7 +158,7 @@ class SRv6(object): :param node: Given node to show localSIDs on. :type node: dict """ - with VatTerminal(node) as vat: + with VatTerminal(node, json_param=False) as vat: vat.vat_terminal_exec_cmd_from_template( 'srv6/sr_localsids_show.vat') @@ -145,15 +177,14 @@ class SRv6(object): """ sid_conf = 'next ' + ' next '.join(sid_list) - with VatTerminal(node) as vat: - resp = vat.vat_terminal_exec_cmd_from_template( + with VatTerminal(node, json_param=False) as vat: + vat.vat_terminal_exec_cmd_from_template( 'srv6/sr_policy_add.vat', bsid=bsid, sid_conf=sid_conf, mode=mode) - VatJsonUtil.verify_vat_retval( - resp[0], - err_msg='Create SRv6 policy for BindingSID {0} failed on node ' - '{1}'.format(bsid, node['host'])) + if "exec error: Misc" in vat.vat_stdout: + raise RuntimeError('Create SRv6 policy for BindingSID {0} failed on' + ' node {1}'.format(bsid, node['host'])) @staticmethod def delete_sr_policy(node, bsid): @@ -164,14 +195,13 @@ class SRv6(object): :type node: dict :type bsid: str """ - with VatTerminal(node) as vat: - resp = vat.vat_terminal_exec_cmd_from_template( + with VatTerminal(node, json_param=False) as vat: + vat.vat_terminal_exec_cmd_from_template( 'srv6/sr_policy_del.vat', bsid=bsid) - VatJsonUtil.verify_vat_retval( - resp[0], - err_msg='Delete SRv6 policy for BindingSID {0} failed on node ' - '{1}'.format(bsid, node['host'])) + if "exec error: Misc" in vat.vat_stdout: + raise RuntimeError('Delete SRv6 policy for BindingSID {0} failed on' + ' node {1}'.format(bsid, node['host'])) @staticmethod def show_sr_policies(node): @@ -186,7 +216,7 @@ class SRv6(object): @staticmethod def configure_sr_steer(node, mode, bsid, interface=None, ip_addr=None, - mask=None): + prefix=None): """Create SRv6 steering policy on the given node. :param node: Given node to create steering policy on. @@ -196,38 +226,42 @@ class SRv6(object): L2 mode). :param ip_addr: IPv4/IPv6 address (Optional, required in case of L3 mode). - :param mask: IP address mask (Optional, required in case of L3 mode). + :param prefix: IP address prefix (Optional, required in case of L3 + mode). :type node: dict :type mode: str :type bsid: str :type interface: str - :type ip_addr: int - :type mask: int + :type ip_addr: str + :type prefix: int :raises ValueError: If unsupported mode used or required parameter is missing. """ - if mode == 'l2': + if mode.lower() == 'l2': if interface is None: raise ValueError('Required data missing.\ninterface:{0}\n'. format(interface)) interface_name = Topology.get_interface_name(node, interface) params = 'l2 {0}'.format(interface_name) - elif mode == 'l3': - if ip_addr is None or mask is None: + elif mode.lower() == 'l3': + if ip_addr is None or prefix is None: raise ValueError('Required data missing.\nIP address:{0}\n' - 'mask:{1}'.format(ip_addr, mask)) - params = '{0}/{1}'.format(ip_addr, mask) + 'mask:{1}'.format(ip_addr, prefix)) + params = 'l3 {0}/{1}'.format(ip_addr, prefix) else: raise ValueError('Unsupported mode: {0}'.format(mode)) - with VatTerminal(node) as vat: - resp = vat.vat_terminal_exec_cmd_from_template( + with VatTerminal(node, json_param=False) as vat: + vat.vat_terminal_exec_cmd_from_template( 'srv6/sr_steer_add_del.vat', params=params, bsid=bsid) - VatJsonUtil.verify_vat_retval( - resp[0], - err_msg='Create SRv6 steering policy for BindingSID {0} failed on ' - 'node {1}'.format(bsid, node['host'])) + sr_steer_errors = ("exec error: Misc", + "sr steer: No SR policy specified") + for err in sr_steer_errors: + if err in vat.vat_stdout: + raise RuntimeError('Create SRv6 steering policy for BindingSID' + ' {0} failed on node {1}'. + format(bsid, node['host'])) @staticmethod def delete_sr_steer(node, mode, bsid, interface=None, ip_addr=None, @@ -266,14 +300,13 @@ class SRv6(object): else: raise ValueError('Unsupported mode: {0}'.format(mode)) - with VatTerminal(node) as vat: - resp = vat.vat_terminal_exec_cmd_from_template( + with VatTerminal(node, json_param=False) as vat: + vat.vat_terminal_exec_cmd_from_template( 'srv6/sr_steer_add_del.vat', params=params, bsid=bsid) - VatJsonUtil.verify_vat_retval( - resp[0], - err_msg='Delete SRv6 policy for bsid {0} failed on node {1}'.format( - bsid, node['host'])) + if "exec error: Misc" in vat.vat_stdout: + raise RuntimeError('Delete SRv6 policy for bsid {0} failed on node' + ' {1}'.format(bsid, node['host'])) @staticmethod def show_sr_steering_policies(node): @@ -285,3 +318,16 @@ class SRv6(object): with VatTerminal(node, json_param=False) as vat: vat.vat_terminal_exec_cmd_from_template( 'srv6/sr_steer_policies_show.vat') + + @staticmethod + def set_sr_encaps_source_address(node, ip6_addr): + """Set SRv6 encapsulation source address on the given node. + + :param node: Given node to set SRv6 encapsulation source address on. + :param ip6_addr: Local SID IPv6 address. + :type node: dict + :type ip6_addr: str + """ + with VatTerminal(node, json_param=False) as vat: + vat.vat_terminal_exec_cmd_from_template( + 'srv6/sr_set_encaps_source.vat', ip6_addr=ip6_addr)