Exemple #1
0
 def SetConfiguration(self, request, context):
     """
     Configure sender and reflector nodes for running an experiment.
     """
     # pylint: disable=invalid-name, unused-argument, no-self-use
     #
     # Establish a gRPC connection to the sender and to the reflector
     with utils.get_grpc_session(request.sender.address,
                                 request.sender.port) as sender_channel, \
         utils.get_grpc_session(request.reflector.address,
                                request.reflector.port) as refl_channel:
         # Send the set configuration request
         logger.debug('Trying to set the experiment configuration')
         res = srv6_pm.set_configuration(
             sender_channel=sender_channel,
             reflector_channel=refl_channel,
             send_udp_port=request.send_udp_port,
             refl_udp_port=request.refl_udp_port,
             interval_duration=request.color_options.interval_duration,
             delay_margin=request.color_options.delay_margin,
             number_of_color=request.color_options.number_of_color,
             pm_driver=request.pm_driver)
         logger.debug('Configuration installed successfully')
         # TODO set_configuration should return an exception in case of
         # error
         logger.debug('%s\n\n', utils.STATUS_CODE_TO_DESC[res])
     # Done, create a reply
     return srv6pm_manager_pb2_grpc.SRv6PMManagerReply(
         status=nb_commons_pb2.STATUS_SUCCESS)
Exemple #2
0
 def GetExperimentResults(self, request, context):
     """
     Get the results of a running experiment.
     """
     # pylint: disable=invalid-name, unused-argument, no-self-use
     #
     # Establish a gRPC connection to the sender and to the reflector
     with utils.get_grpc_session(request.sender.address,
                                 request.sender.port) as sender_channel, \
             utils.get_grpc_session(request.reflector.address,
                                    request.reflector.port) as refl_channel:
         # Trying to collect the experiment results
         logger.debug('Trying to collect the experiment results')
         print(
             srv6_pm.get_experiment_results(
                 sender_channel=sender_channel,
                 reflector_channel=refl_channel,
                 send_refl_sidlist=list(request.send_refl_sidlist),
                 refl_send_sidlist=list(request.refl_send_sidlist)))
         logger.debug('Results retrieved successfully')
         # TODO get_experiment_results should return an exception in case of error
         # TODO get_experiment_results should return the results instead of printing them
     # Done, create a reply
     return srv6pm_manager_pb2_grpc.SRv6PMManagerReply(
         status=nb_commons_pb2.STATUS_SUCCESS)
Exemple #3
0
def start_experiment():
    """Start a new experiment"""

    logger.info('*** Starting a new experiment')
    # IP addresses
    sender = SENDER
    reflector = REFLECTOR
    logger.info('Sender: %s' % sender)
    logger.info('Reflector: %s' % reflector)
    # Open gRPC channels
    with utils.get_grpc_session(sender, GRPC_PORT) as sender_channel, \
            utils.get_grpc_session(reflector, GRPC_PORT) as reflector_channel:
        # Start the experiment
        srv6_pm.start_experiment(
            sender_channel=sender_channel,
            reflector_channel=reflector_channel,
            send_refl_dest='fd00:0:83::2',
            refl_send_dest='fd00:0:13::2',
            send_refl_sidlist=['fcff:3::1', 'fcff:4::1', 'fcff:8::100'],
            refl_send_sidlist=['fcff:4::1', 'fcff:3::1', 'fcff:1::100'],
            send_refl_localseg='fcff:8::100',
            refl_send_localseg='fcff:1::100',
            send_in_interfaces=['r1-r2'],
            refl_in_interfaces=['r8-r6'],
            send_out_interfaces=['r1-r2_egr'],
            refl_out_interfaces=['r8-r6_egr'],
            measurement_protocol='TWAMP',
            measurement_type='LOSS',
            authentication_mode='HMAC_SHA_256',
            authentication_key='s75pbhd-xsh;290f',
            timestamp_format='PTPv2',
            delay_measurement_mode='OneWay',
            padding_mbz=10,
            loss_measurement_mode='Inferred',
            force=True)
Exemple #4
0
 def StopExperiment(self, request, context):
     """
     Stop a running experiment.
     """
     # pylint: disable=invalid-name, unused-argument, no-self-use
     #
     # Establish a gRPC connection to the sender and to the reflector
     with utils.get_grpc_session(request.sender.address,
                                 request.sender.port) as sender_channel, \
             utils.get_grpc_session(request.reflector.address,
                                    request.reflector.port) as refl_channel:
         # Trying to stop the experiment
         logger.debug('Trying to stop the experiment')
         res = srv6_pm.stop_experiment(
             sender_channel=sender_channel,
             reflector_channel=refl_channel,
             send_refl_dest=request.send_refl_dest,
             refl_send_dest=request.refl_send_dest,
             send_refl_sidlist=list(request.send_refl_sidlist),
             refl_send_sidlist=list(request.refl_send_sidlist),
             send_refl_localseg=request.send_refl_localseg,
             refl_send_localseg=request.refl_send_localseg)
         logger.debug('Experiment stopped successfully')
         # TODO stop_experiment should return an exception in case of error
         logger.debug('%s\n\n', utils.STATUS_CODE_TO_DESC[res])
     # Done, create a reply
     return srv6pm_manager_pb2_grpc.SRv6PMManagerReply(
         status=nb_commons_pb2.STATUS_SUCCESS)
def start_experiment(
        sender,
        reflector,
        sender_port,
        reflector_port,
        send_refl_dest,
        refl_send_dest,
        send_refl_sidlist,
        refl_send_sidlist,
        #  send_in_interfaces, refl_in_interfaces,
        #  send_out_interfaces, refl_out_interfaces,
        measurement_protocol,
        measurement_type,
        authentication_mode,
        authentication_key,
        timestamp_format,
        delay_measurement_mode,
        padding_mbz,
        loss_measurement_mode,
        measure_id=None,
        send_refl_localseg=None,
        refl_send_localseg=None,
        force=False):
    """Start an experiment"""

    # pylint: disable=too-many-arguments, too-many-locals

    with utils.get_grpc_session(sender, sender_port) as sender_channel, \
            utils.get_grpc_session(reflector, reflector_port) as refl_channel:
        res = srv6_pm.start_experiment(
            sender_channel=sender_channel,
            reflector_channel=refl_channel,
            send_refl_dest=send_refl_dest,
            refl_send_dest=refl_send_dest,
            send_refl_sidlist=send_refl_sidlist.split(','),
            refl_send_sidlist=refl_send_sidlist.split(','),
            # Interfaces moved to set_configuration
            # send_in_interfaces=send_in_interfaces,
            # refl_in_interfaces=refl_in_interfaces,
            # send_out_interfaces=send_out_interfaces,
            # refl_out_interfaces=refl_out_interfaces,
            measurement_protocol=measurement_protocol,
            measurement_type=measurement_type,
            authentication_mode=authentication_mode,
            authentication_key=authentication_key,
            timestamp_format=timestamp_format,
            delay_measurement_mode=delay_measurement_mode,
            padding_mbz=padding_mbz,
            loss_measurement_mode=loss_measurement_mode,
            measure_id=measure_id,
            send_refl_localseg=send_refl_localseg,
            refl_send_localseg=refl_send_localseg,
            force=force)
        if res == 0:
            print('OK')
        else:
            print('Error')
def reset_configuration(sender, reflector, sender_port, reflector_port):
    """Clear node configuration"""

    with utils.get_grpc_session(sender, sender_port) as sender_channel, \
            utils.get_grpc_session(reflector, reflector_port) as refl_channel:
        res = srv6_pm.reset_configuration(sender_channel=sender_channel,
                                          reflector_channel=refl_channel)
        if res == 0:
            print('OK')
        else:
            print('Error')
def get_experiment_results(sender, reflector, sender_port, reflector_port,
                           send_refl_sidlist, refl_send_sidlist):
    """Get the results of a running experiment"""

    # pylint: disable=too-many-arguments

    with utils.get_grpc_session(sender, sender_port) as sender_channel, \
            utils.get_grpc_session(reflector, reflector_port) as refl_channel:
        print(
            srv6_pm.get_experiment_results(
                sender_channel=sender_channel,
                reflector_channel=refl_channel,
                send_refl_sidlist=send_refl_sidlist.split(','),
                refl_send_sidlist=refl_send_sidlist.split(',')))
def handle_srv6_path(
        operation,
        grpc_address,
        grpc_port,
        destination,
        segments="",
        device='',
        encapmode="encap",
        table=-1,
        metric=-1,
        bsid_addr='',
        fwd_engine='Linux'):
    """Handle a SRv6 path"""

    # pylint: disable=too-many-arguments

    with utils.get_grpc_session(grpc_address, grpc_port) as channel:
        res = srv6_utils.handle_srv6_path(
            operation=operation,
            channel=channel,
            destination=destination,
            segments=segments.split(','),
            device=device,
            encapmode=encapmode,
            table=table,
            metric=metric,
            bsid_addr=bsid_addr,
            fwd_engine=fwd_engine
        )
        if res == 0:
            print('OK')
        else:
            print('Error')
def handle_srv6_biditunnel(operation, node_l_ip, node_l_port,
                           node_r_ip, node_r_port,
                           sidlist_lr, sidlist_rl, dest_lr, dest_rl,
                           localseg_lr=None, localseg_rl=None,
                           bsid_addr='', fwd_engine='Linux'):
    """Handle SRv6 bidirectional tunnel"""

    # pylint: disable=too-many-arguments

    with utils.get_grpc_session(node_l_ip, node_l_port) as node_l_channel, \
            utils.get_grpc_session(node_r_ip, node_r_port) as node_r_channel:
        if operation == 'add':
            res = srv6_utils.create_srv6_tunnel(
                node_l_channel=node_l_channel,
                node_r_channel=node_r_channel,
                sidlist_lr=sidlist_lr.split(','),
                sidlist_rl=sidlist_rl.split(','),
                dest_lr=dest_lr,
                dest_rl=dest_rl,
                localseg_lr=localseg_lr,
                localseg_rl=localseg_rl,
                bsid_addr=bsid_addr,
                fwd_engine=fwd_engine
            )
            if res == 0:
                print('OK')
            else:
                print('Error')
        elif operation == 'del':
            res = srv6_utils.destroy_srv6_tunnel(
                node_l_channel=node_l_channel,
                node_r_channel=node_r_channel,
                dest_lr=dest_lr,
                dest_rl=dest_rl,
                localseg_lr=localseg_lr,
                localseg_rl=localseg_rl,
                bsid_addr=bsid_addr,
                fwd_engine=fwd_engine
            )
            if res == 0:
                print('OK')
            else:
                print('Error')
        else:
            print('Invalid operation %s' % operation)
Exemple #10
0
 def StartExperiment(self, request, context):
     """
     Start an experiment.
     """
     # pylint: disable=invalid-name, unused-argument, no-self-use
     #
     # Establish a gRPC connection to the sender and to the reflector
     with utils.get_grpc_session(request.sender.address,
                                 request.sender.port) as sender_channel, \
             utils.get_grpc_session(request.reflector.address,
                                    request.reflector.port) as refl_channel:
         # Trying to start the experiment
         logger.debug('Trying to start the experiment')
         res = srv6_pm.start_experiment(
             sender_channel=sender_channel,
             reflector_channel=refl_channel,
             send_refl_dest=request.send_refl_dest,
             refl_send_dest=request.refl_send_dest,
             send_refl_sidlist=list(request.send_refl_sidlist),
             refl_send_sidlist=list(request.refl_send_sidlist),
             measurement_protocol=grpc_to_py_measurement_protocol(
                 request.measurement_protocol),
             measurement_type=grpc_to_py_measurement_type(
                 request.measurement_type),
             authentication_mode=grpc_to_py_authentication_mode(
                 request.authentication_mode),
             authentication_key=request.authentication_key,
             timestamp_format=grpc_to_py_timestamp_format(
                 request.timestamp_format),
             delay_measurement_mode=grpc_to_py_delay_measurement_mode(
                 request.delay_measurement_mode),
             padding_mbz=request.padding_mbz,
             loss_measurement_mode=grpc_to_py_loss_measurement_mode(
                 request.loss_measurement_mode),
             measure_id=request.measure_id,
             send_refl_localseg=request.send_refl_localseg,
             refl_send_localseg=request.refl_send_localseg,
             force=request.force)
         logger.debug('Experiment started successfully')
         # TODO start_experiment should return an exception in case of error
         logger.debug('%s\n\n', utils.STATUS_CODE_TO_DESC[res])
     # Done, create a reply
     return srv6pm_manager_pb2_grpc.SRv6PMManagerReply(
         status=nb_commons_pb2.STATUS_SUCCESS)
Exemple #11
0
def get_experiment_results():
    """Get the results of a running experiment"""

    logger.info('*** Get experiment results')
    # IP addresses
    sender = SENDER
    reflector = REFLECTOR
    logger.info('Sender: %s' % sender)
    logger.info('Reflector: %s' % reflector)
    # Open gRPC channels
    with utils.get_grpc_session(sender, GRPC_PORT) as sender_channel, \
            utils.get_grpc_session(reflector, GRPC_PORT) as reflector_channel:
        # Get the results
        results = srv6_pm.get_experiment_results(
            sender_channel=sender_channel,
            reflector_channel=reflector_channel,
            send_refl_sidlist=['fcff:3::1', 'fcff:4::1', 'fcff:8::100'],
            refl_send_sidlist=['fcff:4::1', 'fcff:3::1', 'fcff:1::100'],
        )
    # Check for errors
    if results is None:
        print('Error in get_experiment_results()')
        print()
        return
    # Print the results
    for result in results:
        print("------------------------------")
        print("Measurement ID: %s" % result['measure_id'])
        print("Interval: %s" % result['interval'])
        print("Timestamp: %s" % result['timestamp'])
        print("FW Color: %s" % result['fw_color'])
        print("RV Color: %s" % result['rv_color'])
        print("sender_seq_num: %s" % result['sender_seq_num'])
        print("reflector_seq_num: %s" % result['reflector_seq_num'])
        print("Sender TX counter: %s" % result['sender_tx_counter'])
        print("Sender RX counter: %s" % result['sender_rx_counter'])
        print("Reflector TX counter: %s" % result['reflector_tx_counter'])
        print("Reflector RX counter: %s" % result['reflector_rx_counter'])
        print("------------------------------")
        print()
    print()
def set_configuration(sender, reflector, sender_port, reflector_port,
                      send_udp_port, refl_udp_port, interval_duration,
                      delay_margin, number_of_color, pm_driver):
    """Configure a node"""

    # pylint: disable=too-many-arguments

    with utils.get_grpc_session(sender, sender_port) as sender_channel, \
            utils.get_grpc_session(reflector, reflector_port) as refl_channel:
        res = srv6_pm.set_configuration(sender_channel=sender_channel,
                                        reflector_channel=refl_channel,
                                        send_udp_port=send_udp_port,
                                        refl_udp_port=refl_udp_port,
                                        interval_duration=interval_duration,
                                        delay_margin=delay_margin,
                                        number_of_color=number_of_color,
                                        pm_driver=pm_driver)
        if res == 0:
            print('OK')
        else:
            print('Error')
Exemple #13
0
def set_configuration():
    """Start a new experiment"""

    logger.info('*** Set experiment configuration')
    # IP addresses
    sender = SENDER
    reflector = REFLECTOR
    logger.info('Sender: %s' % sender)
    logger.info('Reflector: %s' % reflector)
    # Open gRPC channels
    with utils.get_grpc_session(sender, GRPC_PORT) as sender_channel, \
            utils.get_grpc_session(reflector, GRPC_PORT) as reflector_channel:
        # Start the experiment
        srv6_pm.set_configuration(
            sender_channel=sender_channel,
            reflector_channel=reflector_channel,
            send_udp_port=1205,
            refl_udp_port=1206,
            interval_duration=10,
            delay_margin=5,  # sec assert(<interval)
            number_of_color=2,  # sec assert(==2)
            pm_driver=srv6pmCommons_pb2.PMDriver.Value('eBPF'))
def handle_srv6_unitunnel(operation, ingress_ip, ingress_port,
                          egress_ip, egress_port,
                          destination, segments, localseg=None,
                          bsid_addr='', fwd_engine='Linux'):
    """Handle a SRv6 unidirectional tunnel"""

    # pylint: disable=too-many-arguments

    with utils.get_grpc_session(ingress_ip, ingress_port) as ingress_channel, \
            utils.get_grpc_session(egress_ip, egress_port) as egress_channel:
        if operation == 'add':
            res = srv6_utils.create_uni_srv6_tunnel(
                ingress_channel=ingress_channel,
                egress_channel=egress_channel,
                destination=destination,
                segments=segments.split(','),
                localseg=localseg,
                bsid_addr=bsid_addr,
                fwd_engine=fwd_engine
            )
            if res == 0:
                print('OK')
            else:
                print('Error')
        elif operation == 'del':
            res = srv6_utils.destroy_uni_srv6_tunnel(
                ingress_channel=ingress_channel,
                egress_channel=egress_channel,
                destination=destination,
                localseg=localseg,
                bsid_addr=bsid_addr,
                fwd_engine=fwd_engine
            )
            if res == 0:
                print('OK')
            else:
                print('Error')
        else:
            print('Invalid operation %s' % operation)
Exemple #15
0
 def ResetConfiguration(self, request, context):
     """
     Clear node configuration.
     """
     # pylint: disable=invalid-name, unused-argument, no-self-use
     #
     # Establish a gRPC connection to the sender and to the reflector
     with utils.get_grpc_session(request.sender.address,
                                 request.sender.port) as sender_channel, \
             utils.get_grpc_session(request.reflector.address,
                                    request.reflector.port) as refl_channel:
         # Send the reset configuration request
         logger.debug('Trying to reset the experiment configuration')
         res = srv6_pm.reset_configuration(sender_channel=sender_channel,
                                           reflector_channel=refl_channel)
         logger.debug('Configuration reset successfully')
         # TODO reset_configuration should return an exception in case of
         # error
         logger.debug('%s\n\n', utils.STATUS_CODE_TO_DESC[res])
     # Done, create a reply
     return srv6pm_manager_pb2_grpc.SRv6PMManagerReply(
         status=nb_commons_pb2.STATUS_SUCCESS)
Exemple #16
0
def stop_experiment():
    """Stop a running experiment"""

    logger.info('*** Stopping experiment')
    # IP addresses
    sender = SENDER
    reflector = REFLECTOR
    logger.info('Sender: %s' % sender)
    logger.info('Reflector: %s' % reflector)
    # Open gRPC channels
    with utils.get_grpc_session(sender, GRPC_PORT) as sender_channel, \
            utils.get_grpc_session(reflector, GRPC_PORT) as reflector_channel:
        # Stop the experiment
        srv6_pm.stop_experiment(
            sender_channel=sender_channel,
            reflector_channel=reflector_channel,
            send_refl_dest='fd00:0:83::2',
            refl_send_dest='fd00:0:13::2',
            send_refl_sidlist=['fcff:3::1', 'fcff:4::1', 'fcff:8::100'],
            refl_send_sidlist=['fcff:4::1', 'fcff:3::1', 'fcff:1::100'],
            send_refl_localseg='fcff:8::100',
            refl_send_localseg='fcff:1::100',
        )
def stop_experiment(sender,
                    reflector,
                    sender_port,
                    reflector_port,
                    send_refl_dest,
                    refl_send_dest,
                    send_refl_sidlist,
                    refl_send_sidlist,
                    send_refl_localseg=None,
                    refl_send_localseg=None):
    """Stop a running experiment"""

    # pylint: disable=too-many-arguments

    with utils.get_grpc_session(sender, sender_port) as sender_channel, \
            utils.get_grpc_session(reflector, reflector_port) as refl_channel:
        srv6_pm.stop_experiment(sender_channel=sender_channel,
                                reflector_channel=refl_channel,
                                send_refl_dest=send_refl_dest,
                                refl_send_dest=refl_send_dest,
                                send_refl_sidlist=send_refl_sidlist.split(','),
                                refl_send_sidlist=refl_send_sidlist.split(','),
                                send_refl_localseg=send_refl_localseg,
                                refl_send_localseg=refl_send_localseg)
def handle_srv6_behavior(
        operation,
        grpc_address,
        grpc_port,
        segment,
        action='',
        device='',
        table=-1,
        nexthop="",
        lookup_table=-1,
        interface="",
        segments="",
        metric=-1,
        fwd_engine='Linux'):
    """Handle a SRv6 behavior"""

    # pylint: disable=too-many-arguments

    with utils.get_grpc_session(grpc_address, grpc_port) as channel:
        res = srv6_utils.handle_srv6_behavior(
            operation=operation,
            channel=channel,
            segment=segment,
            action=action,
            device=device,
            table=table,
            nexthop=nexthop,
            lookup_table=lookup_table,
            interface=interface,
            segments=segments.split(','),
            metric=metric,
            fwd_engine=fwd_engine
        )
        if res == 0:
            print('OK')
        else:
            print('Error')
Exemple #19
0
def handle_srv6_usid_policy(operation,
                            lr_destination=None, rl_destination=None,
                            nodes_lr=None,
                            nodes_rl=None, table=-1, metric=-1,
                            persistency=True, _id=None, l_grpc_ip=None,
                            l_grpc_port=None, l_fwd_engine=None,
                            r_grpc_ip=None, r_grpc_port=None,
                            r_fwd_engine=None, decap_sid=None, locator=None,
                            db_conn=None):
    """
    Handle a SRv6 Policy using uSIDs

    :param operation: The operation to be performed on the uSID policy
                      (i.e. add, get, change, del)
    :type operation: str
    :param destination: Destination of the SRv6 route
    :type destination: str
    :param nodes: Waypoints of the SRv6 route
    :type nodes: list
    :param device: Device of the SRv6 route. If not provided, the device
                   is selected automatically by the node.
    :type device: str, optional
    :param table: Routing table containing the SRv6 route. If not provided,
                  the main table (i.e. table 254) will be used.
    :type table: int, optional
    :param metric: Metric for the SRv6 route. If not provided, the default
                   metric will be used.
    :type metric: int, optional
    :param l_grpc_ip: gRPC IP address of the left node, required if the left
                      node is expressed numerically in the nodes list.
    :type l_grpc_ip: str, optional
    :param l_grpc_port: gRPC port of the left node, required if the left
                        node is expressed numerically in the nodes list.
    :type l_grpc_port: str, optional
    :param l_fwd_engine: forwarding engine of the left node, required if the
                         left node is expressed numerically in the nodes list.
    :type l_fwd_engine: str, optional
    :param r_grpc_ip: gRPC IP address of the right node, required if the right
                      node is expressed numerically in the nodes list.
    :type r_grpc_ip: str, optional
    :param r_grpc_port: gRPC port of the right node, required if the right
                        node is expressed numerically in the nodes list.
    :type r_grpc_port: str, optional
    :param r_fwd_engine: Forwarding engine of the right node, required if the
                         right node is expressed numerically in the nodes
                         list.
    :type r_fwd_engine: str, optional
    :param decap_sid: uSID used for the decap behavior (End.DT6).
    :type decap_sid: str, optional
    :param locator: Locator prefix (e.g. 'fcbb:bbbb::').
    :type locator: str, optional
    :return: Status Code of the operation (e.g. 0 for STATUS_SUCCESS)
    :rtype: int
    :raises NodeNotFoundError: Node name not found in the mapping file
    :raises InvalidConfigurationError: The mapping file is not a valid
                                       YAML file
    :raises TooManySegmentsError: segments arg contains more than 6 segments
    :raises SIDLocatorError: SID Locator is wrong for one or more segments
    :raises InvalidSIDError: SID is wrong for one or more segments
    """
    # pylint: disable=too-many-locals, too-many-arguments
    # pylint: disable=too-many-return-statements, too-many-branches
    # pylint: disable=too-many-statements
    #
    # Validate arguments
    if lr_destination is None:
        if operation in ['add']:
            logger.error('"lr_destination" argument is mandatory for %s '
                         'operation', operation)
            return None
    if rl_destination is None:
        if operation in ['add']:
            logger.error('"rl_destination" argument is mandatory for %s '
                         'operation', operation)
            return None
    if nodes_lr is None:
        if operation in ['add']:
            logger.error('"nodes_lr" argument is mandatory for %s '
                         'operation', operation)
            return None
    if nodes_rl is None:
        pass
    if operation == 'change':
        logger.error('Operation not yet implemented: %s', operation)
        return None
    if operation == 'get':
        if not persistency:
            logger.error('Error in get(): Persistency is disabled')
            return None
        # Get the policy from the db
        policies = arangodb_driver.find_usid_policy(
            database=db_conn,
            key=_id,
            lr_dst=lr_destination,
            rl_dst=rl_destination,
            lr_nodes=nodes_lr,
            rl_nodes=nodes_rl,
            table=table if table != -1 else None,
            metric=metric if metric != -1 else None
        )
        # Print policies
        print('\n\n*** uSID policies:')
        pprint.PrettyPrinter(indent=4).pprint(list(policies))
        print('\n\n')
        return 0
    if operation in ['add', 'del']:
        # Extract the nodes configuration from the db
        nodes_config = topo_utils.get_nodes_config()
        #
        # In order to perform this translation, a file containing the
        # mapping of node names to IPv6 addresses is required
        #
        # Read nodes from YAML file
        nodes_info = {node['name']: node for node in nodes_config['nodes']}
        locator_bits = DEFAULT_LOCATOR_BITS  # TODO configurable locator bits
        usid_id_bits = DEFAULT_USID_ID_BITS  # TODO configurable uSID id bits
        # Add nodes list for the left-to-right path to the 'nodes_info' dict
        if nodes_lr is not None:
            fill_nodes_info(
                nodes_info=nodes_info,
                nodes=nodes_lr,
                l_grpc_ip=l_grpc_ip,
                l_grpc_port=l_grpc_port,
                l_fwd_engine=l_fwd_engine,
                r_grpc_ip=r_grpc_ip,
                r_grpc_port=r_grpc_port,
                r_fwd_engine=r_fwd_engine,
                decap_sid=decap_sid,
                locator=locator
            )
        # Add nodes list for the right-to-left path to the 'nodes_info' dict
        if nodes_rl is not None:
            fill_nodes_info(
                nodes_info=nodes_info,
                nodes=nodes_rl,
                l_grpc_ip=r_grpc_ip,
                l_grpc_port=r_grpc_port,
                l_fwd_engine=r_fwd_engine,
                r_grpc_ip=l_grpc_ip,
                r_grpc_port=l_grpc_port,
                r_fwd_engine=l_fwd_engine,
                decap_sid=decap_sid,
                locator=locator
            )
        # Add
        if operation == 'add':
            policies = [{
                'lr_dst': lr_destination,
                'rl_dst': rl_destination,
                'lr_nodes': nodes_lr,
                'rl_nodes': nodes_rl
            }]
        if operation == 'del':
            # Get the policy from the db
            policies = arangodb_driver.find_usid_policy(
                database=db_conn,
                key=_id,
                lr_dst=lr_destination,
                rl_dst=rl_destination,
                lr_nodes=nodes_lr,
                rl_nodes=nodes_rl,
                table=table if table != -1 else None,
                metric=metric if metric != -1 else None
            )

            policies = list(policies)
            for policy in policies:
                # Add nodes list for the left-to-right path to the
                # 'nodes_info' dict
                if policy.get('lr_nodes') is not None:
                    fill_nodes_info(
                        nodes_info=nodes_info,
                        nodes=policy.get('lr_nodes'),
                        l_grpc_ip=policy.get('l_grpc_ip'),
                        l_grpc_port=policy.get('l_grpc_port'),
                        l_fwd_engine=policy.get('l_fwd_engine'),
                        r_grpc_ip=policy.get('r_grpc_ip'),
                        r_grpc_port=policy.get('r_grpc_port'),
                        r_fwd_engine=policy.get('r_fwd_engine'),
                        decap_sid=policy.get('decap_sid'),
                        locator=policy.get('locator')
                    )
                # Add nodes list for the right-to-left path to the
                # 'nodes_info' dict
                if policy.get('rl_nodes') is not None:
                    fill_nodes_info(
                        nodes_info=nodes_info,
                        nodes=policy.get('rl_nodes'),
                        l_grpc_ip=policy.get('r_grpc_ip'),
                        l_grpc_port=policy.get('r_grpc_port'),
                        l_fwd_engine=policy.get('r_fwd_engine'),
                        r_grpc_ip=policy.get('l_grpc_ip'),
                        r_grpc_port=policy.get('l_grpc_port'),
                        r_fwd_engine=policy.get('l_fwd_engine'),
                        decap_sid=policy.get('decap_sid'),
                        locator=policy.get('locator')
                    )
        if len(policies) == 0:
            logger.error('Policy not found')
            return None
        # Iterate on the policies
        for policy in policies:
            lr_destination = policy.get('lr_dst')
            rl_destination = policy.get('rl_dst')
            nodes_lr = policy.get('lr_nodes')
            nodes_rl = policy.get('rl_nodes')
            _id = policy.get('_key')
            #
            # If right to left nodes list is not provided, we use the reverse
            # left to right SID list (symmetric path)
            if nodes_rl is None:
                nodes_rl = nodes_lr[::-1]
            # The two SID lists must have the same endpoints
            if nodes_lr[0] != nodes_rl[-1] or nodes_rl[0] != nodes_lr[-1]:
                logger.error('Bad tunnel endpoints')
                return None
            # Create the SRv6 Policy
            try:
                # # Prefix length for local segment
                # prefix_len = locator_bits + usid_id_bits
                # Ingress node
                ingress_node = nodes_info[nodes_lr[0]]
                # Intermediate nodes
                intermediate_nodes_lr = list()
                for node in nodes_lr[1:-1]:
                    intermediate_nodes_lr.append(nodes_info[node])
                intermediate_nodes_rl = list()
                for node in nodes_rl[1:-1]:
                    intermediate_nodes_rl.append(nodes_info[node])
                # Egress node
                egress_node = nodes_info[nodes_lr[-1]]
                # Extract the segments
                segments_lr = list()
                for node in nodes_lr:
                    segments_lr.append(nodes_info[node]['uN'])
                segments_rl = list()
                for node in nodes_rl:
                    segments_rl.append(nodes_info[node]['uN'])

                # Ingress node
                with utils.get_grpc_session(ingress_node['grpc_ip'],
                                            ingress_node['grpc_port']
                                            ) as channel:
                    # Currently ony Linux and VPP are suppoted for the encap
                    if ingress_node['fwd_engine'] not in ['linux', 'vpp']:
                        logger.error(
                            'Encap operation is not supported for '
                            '%s with fwd engine %s',
                            ingress_node['name'],
                            ingress_node['fwd_engine'])
                        return commons_pb2.STATUS_INTERNAL_ERROR
                    # VPP requires a BSID address
                    bsid_addr = ''
                    if ingress_node['fwd_engine'] == 'VPP':
                        for char in lr_destination:
                            if char not in ('0', ':'):
                                bsid_addr += char
                        add_colon = False
                        if len(bsid_addr) <= 28:
                            add_colon = True
                        bsid_addr = [(bsid_addr[i:i + 4])
                                     for i in range(0, len(bsid_addr), 4)]
                        bsid_addr = ':'.join(bsid_addr)
                        if add_colon:
                            bsid_addr += '::'

                    udt_sids = list()
                    # Locator mask
                    locator_mask = str(IPv6Address(
                        int('1' * 128, 2) ^
                        int('1' * (128 - locator_bits), 2)))
                    # uDT mask
                    udt_mask_1 = str(
                        IPv6Address(int('1' * usid_id_bits, 2) <<
                                    (128 - locator_bits - usid_id_bits)))
                    udt_mask_2 = str(
                        IPv6Address(int('1' * usid_id_bits, 2) <<
                                    (128 - locator_bits - 2 * usid_id_bits)))
                    # Build uDT sid list
                    locator_int = int(IPv6Address(egress_node['uDT'])) & \
                        int(IPv6Address(locator_mask))
                    udt_mask_1_int = int(IPv6Address(egress_node['uDT'])) & \
                        int(IPv6Address(udt_mask_1))
                    udt_mask_2_int = int(IPv6Address(egress_node['uDT'])) & \
                        int(IPv6Address(udt_mask_2))
                    udt_sids += [str(IPv6Address(locator_int +
                                                 udt_mask_1_int))]
                    udt_sids += [str(IPv6Address(locator_int +
                                                 (udt_mask_2_int <<
                                                  usid_id_bits)))]
                    # We need to convert the SID list into a uSID list
                    #  before creating the SRv6 policy
                    usid_list = sidlist_to_usidlist(
                        sid_list=segments_lr[1:][:-1],
                        udt_sids=[segments_lr[1:][-1]] + udt_sids,
                        locator_bits=locator_bits,
                        usid_id_bits=usid_id_bits
                    )
                    # Handle a SRv6 path
                    response = srv6_utils.handle_srv6_path(
                        operation=operation,
                        channel=channel,
                        destination=lr_destination,
                        segments=usid_list,
                        encapmode='encap.red',
                        table=table,
                        metric=metric,
                        bsid_addr=bsid_addr,
                        fwd_engine=ingress_node['fwd_engine'],
                        update_db=False
                    )
                    if response != commons_pb2.STATUS_SUCCESS:
                        # Error
                        return response
                    # # Create the uN behavior
                    # response = handle_srv6_behavior(
                    #     operation=operation,
                    #     channel=channel,
                    #     segment='%s/%s' % (ingress_node['uN'], prefix_len),
                    #     action='uN',
                    #     fwd_engine=ingress_node['fwd_engine']
                    # )
                    # if response != commons_pb2.STATUS_SUCCESS:
                    #     # Error
                    #     return response
                    # # Create the End behavior
                    # response = handle_srv6_behavior(
                    #     operation=operation,
                    #     channel=channel,
                    #     segment='%s/%s' % (ingress_node['uN'], 64),
                    #     action='End',
                    #     fwd_engine=ingress_node['fwd_engine']
                    # )
                    # if response != commons_pb2.STATUS_SUCCESS:
                    #     # Error
                    #     return response
                    # # Create the decap behavior
                    # response = handle_srv6_behavior(
                    #     operation=operation,
                    #     channel=channel,
                    #     segment='%s/%s' % (ingress_node['uDT'], 64),
                    #     action='End.DT6',
                    #     lookup_table=254,
                    #     fwd_engine=ingress_node['fwd_engine']
                    # )
                    # if response != commons_pb2.STATUS_SUCCESS:
                    #     # Error
                    #     return response
                # # Intermediate nodes
                # for node in intermediate_nodes:
                #     with utils.get_grpc_session(node['grpc_ip'],
                #                                 node['grpc_port']
                #                                 ) as channel:
                #         # Create the uN behavior
                #         response = handle_srv6_behavior(
                #             operation=operation,
                #             channel=channel,
                #             segment='%s/%s' % (node['uN'], prefix_len),
                #             action='uN',
                #             fwd_engine=node['fwd_engine']
                #         )
                #         if response != commons_pb2.STATUS_SUCCESS:
                #             # Error
                #             return response
                # Egress node
                with utils.get_grpc_session(egress_node['grpc_ip'],
                                            egress_node['grpc_port']
                                            ) as channel:
                    # Currently ony Linux and VPP are suppoted for the encap
                    if egress_node['fwd_engine'] not in ['linux', 'vpp']:
                        logger.error(
                            'Encap operation is not supported for '
                            '%s with fwd engine %s',
                            egress_node['name'], egress_node['fwd_engine'])
                        return commons_pb2.STATUS_INTERNAL_ERROR
                    # VPP requires a BSID address
                    bsid_addr = ''
                    if egress_node['fwd_engine'] == 'VPP':
                        for char in lr_destination:
                            if char not in ('0', ':'):
                                bsid_addr += char
                        add_colon = False
                        if len(bsid_addr) <= 28:
                            add_colon = True
                        bsid_addr = [(bsid_addr[i:i + 4])
                                     for i in range(0, len(bsid_addr), 4)]
                        bsid_addr = ':'.join(bsid_addr)
                        if add_colon:
                            bsid_addr += '::'
                    # # Create the uN behavior
                    # response = handle_srv6_behavior(
                    #     operation=operation,
                    #     channel=channel,
                    #     segment='%s/%s' % (egress_node['uN'], prefix_len),
                    #     action='uN',
                    #     fwd_engine=egress_node['fwd_engine']
                    # )
                    # if response != commons_pb2.STATUS_SUCCESS:
                    #     # Error
                    #     return response
                    # # Create the End behavior
                    # response = handle_srv6_behavior(
                    #     operation=operation,
                    #     channel=channel,
                    #     segment='%s/%s' % (egress_node['uN'], 64),
                    #     action='End',
                    #     fwd_engine=egress_node['fwd_engine']
                    # )
                    # if response != commons_pb2.STATUS_SUCCESS:
                    #     # Error
                    #     return response
                    # # Create the decap behavior
                    # response = handle_srv6_behavior(
                    #     operation=operation,
                    #     channel=channel,
                    #     segment='%s/%s' % (egress_node['uDT'], 64),
                    #     action='End.DT6',
                    #     lookup_table=254,
                    #     fwd_engine=egress_node['fwd_engine']
                    # )
                    # if response != commons_pb2.STATUS_SUCCESS:
                    #     # Error
                    #     return response
                    udt_sids = list()
                    # Locator mask
                    locator_mask = str(IPv6Address(
                        int('1' * 128, 2) ^
                        int('1' * (128 - locator_bits), 2)))
                    # uDT mask
                    udt_mask_1 = str(IPv6Address(int('1' * usid_id_bits, 2) <<
                                                 (128 - locator_bits -
                                                  usid_id_bits)))
                    udt_mask_2 = str(IPv6Address(int('1' * usid_id_bits, 2) <<
                                                 (128 - locator_bits -
                                                  2 * usid_id_bits)))
                    # Build uDT sid list
                    locator_int = int(
                        IPv6Address(
                            ingress_node['uDT'])) & int(
                                IPv6Address(locator_mask))
                    udt_mask_1_int = int(
                        IPv6Address(
                            ingress_node['uDT'])) & int(
                                IPv6Address(udt_mask_1))
                    udt_mask_2_int = int(
                        IPv6Address(
                            ingress_node['uDT'])) & int(
                                IPv6Address(udt_mask_2))
                    udt_sids += [str(IPv6Address(locator_int +
                                                 udt_mask_1_int))]
                    udt_sids += [str(IPv6Address(locator_int +
                                                 (udt_mask_2_int <<
                                                  usid_id_bits)))]
                    # We need to convert the SID list into a uSID list
                    #  before creating the SRv6 policy
                    usid_list = sidlist_to_usidlist(
                        sid_list=segments_rl[1:][:-1],
                        udt_sids=[segments_rl[1:][-1]] + udt_sids,
                        locator_bits=locator_bits,
                        usid_id_bits=usid_id_bits
                    )
                    # Handle a SRv6 path
                    response = srv6_utils.handle_srv6_path(
                        operation=operation,
                        channel=channel,
                        destination=rl_destination,
                        segments=usid_list,
                        encapmode='encap.red',
                        table=table,
                        metric=metric,
                        bsid_addr=bsid_addr,
                        fwd_engine=egress_node['fwd_engine'],
                        update_db=False
                    )
                    if response != commons_pb2.STATUS_SUCCESS:
                        # Error
                        return response
                # Persist uSID policy to database
                if persistency:
                    if operation == 'add':
                        # Save the policy to the db
                        arangodb_driver.insert_usid_policy(
                            database=db_conn,
                            lr_dst=lr_destination,
                            rl_dst=rl_destination,
                            lr_nodes=nodes_lr,
                            rl_nodes=nodes_rl,
                            table=table if table != -1 else None,
                            metric=metric if metric != -1 else None,
                            l_grpc_ip=l_grpc_ip,
                            l_grpc_port=l_grpc_port,
                            l_fwd_engine=l_fwd_engine,
                            r_grpc_ip=r_grpc_ip,
                            r_grpc_port=r_grpc_port,
                            r_fwd_engine=r_fwd_engine,
                            decap_sid=decap_sid,
                            locator=locator
                        )
                    elif operation == 'del':
                        # Save the policy to the db
                        arangodb_driver.delete_usid_policy(
                            database=db_conn,
                            key=_id,
                            lr_dst=lr_destination,
                            rl_dst=rl_destination,
                            lr_nodes=nodes_lr,
                            rl_nodes=nodes_rl,
                            table=table if table != -1 else None,
                            metric=metric if metric != -1 else None
                        )
                    else:
                        logger.error('Unsupported operation: %s', operation)
            except (InvalidConfigurationError, NodeNotFoundError,
                    TooManySegmentsError, SIDLocatorError, InvalidSIDError):
                return commons_pb2.STATUS_INTERNAL_ERROR
        # Return the response
        return response
    logger.error('Unsupported operation: %s', operation)
    return None
Exemple #20
0
def create_tunnel_r1r4r8():
    # +--------------------------------------------------------------------+
    # |          Create a bidirectional tunnel between h11 and h83         |
    # |              passing through router r4 (r1---r4---r8)              |
    # +--------------------------------------------------------------------+
    logger.info('*** Attempting to create tunnel r1---r4---r8')
    # IP addresses
    r1 = 'fcff:1::1'
    r8 = 'fcff:8::1'
    # Open gRPC channels
    with get_grpc_session(r1, GRPC_PORT) as r1_chan, \
            get_grpc_session(r8, GRPC_PORT) as r8_chan:
        # +---------------------------------------------------------------+
        # |          Set tunnel from r1 to r8 for fd00:0:83::/64          |
        # +---------------------------------------------------------------+
        logger.info('******* Set tunnel from r1 to r8 for fd00:0:83::/64')
        #
        # Encap route on r1
        # on r1: ip -6 route add fd00:0:83::/64 encap seg6 mode encap segs
        #        fcff:4::1,fcff:8::100 dev r1-h11 metric 200
        logger.info('*********** Creating encap route')
        res = handle_srv6_path(
            op='add',
            channel=r1_chan,
            destination='fd00:0:83::/64',
            segments=['fcff:4::1', 'fcff:8::100'],
            device='r1-h11',
            metric=200
        )
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Encap route created successfully')
        else:
            logger.error('*********** Error while creating encap route')
        #
        # Decap route on r8
        # on r8: ip -6 route add fcff:8::100 encap seg6local action End.DT6
        #        table 254 dev r8-h83 metric 200
        logger.info('*********** Creating decap route')
        res = handle_srv6_behavior(
            op='add',
            channel=r8_chan,
            segment='fcff:8::100',
            action='End.DT6',
            lookup_table=254,
            device='r8-h83',
            metric=200
        )
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Decap route created successfully')
        else:
            logger.error('*********** Error while creating decap route')
        #
        #
        # +---------------------------------------------------------------+
        # |          Set tunnel from r8 to r1 for fd00:0:11::/64          |
        # +---------------------------------------------------------------+
        logger.info('******* Set tunnel from r8 to r1 for fd00:0:11::/64')
        #
        # Encap route on r8
        # on r8: ip -6 route add fd00:0:11::/64 encap seg6 mode encap segs
        #        fcff:4::1,fcff:1::100 dev r8-h83 metric 200
        logger.info('*********** Creating encap route')
        res = handle_srv6_path(
            op='add',
            channel=r8_chan,
            destination='fd00:0:11::/64',
            segments=['fcff:4::1', 'fcff:1::100'],
            device='r8-h83',
            metric=200
        )
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Encap route created successfully')
        else:
            logger.error('*********** Error while creating encap route')
        #
        # Decap route on r1
        # on r1: ip -6 route add fcff:1::100 encap seg6local action End.DT6
        #        table 254 dev r1-h11 metric 200
        logger.info('*********** Creating decap route')
        res = handle_srv6_behavior(
            op='add',
            channel=r1_chan,
            segment='fcff:1::100',
            action='End.DT6',
            lookup_table=254,
            device='r1-h11',
            metric=200
        )
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Decap route created successfully')
        else:
            logger.error('*********** Error while creating decap route')
        #
        #
        # +---------------------------------------------------------------+
        # |                             Done                              |
        # +---------------------------------------------------------------+
        print()
def shift_path():
    # +--------------------------------------------------------------------+
    # |         Switch from r1---r7---r8 path to r1---r4---r8 path         |
    # |                     by exchanging the metrics                      |
    # +--------------------------------------------------------------------+
    logger.info(
        '*** Attempting to change path from r1---r7---r8 to r1---r4---r8')
    # IP addresses
    r1 = 'fcff:1::1'
    r8 = 'fcff:8::1'
    # Open gRPC channels
    with get_grpc_session(r1, GRPC_PORT) as r1_chan, \
            get_grpc_session(r8, GRPC_PORT) as r8_chan:
        # +---------------------------------------------------------------+
        # |              Decreasing the metric value of the               |
        # |               r4 route to an intermediate value               |
        # +---------------------------------------------------------------+
        logger.info('******* Decreasing the metric value of '
                    'the r4 route to an intermediate value')
        #
        # Encap route on r1
        # on r1: ip -6 route add fd00:0:83::/64 encap seg6 mode encap segs
        #        fcff:4::1,fcff:8:100 dev r1-h11 metric 99
        logger.info('*********** Creating encap route on r1')
        res = handle_srv6_path(op='add',
                               channel=r1_chan,
                               destination='fd00:0:83::/64',
                               segments=['fcff:4::1', 'fcff:8::100'],
                               device='r1-h11',
                               metric=99)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Encap route created successfully')
        else:
            logger.error('*********** Error while creating encap route')
        #
        # Decap route on r8
        # on r8: ip -6 route add fcff:8::100 encap seg6local action End.DT6
        #        table 254 dev r8-h83 metric 99
        logger.info('*********** Creating decap route on r8')
        res = handle_srv6_behavior(op='add',
                                   channel=r8_chan,
                                   segment='fcff:8::100',
                                   action='End.DT6',
                                   lookup_table=254,
                                   device='r8-h83',
                                   metric=99)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Decap route created successfully')
        else:
            logger.error('*********** Error while creating decap route')
        #
        # Encap route on r8
        # on r8: ip -6 route add fd00:0:11::/64 encap seg6 mode encap segs
        #        fcff:4::1,fcff:1:100 dev r8-h83 metric 99
        logger.info('*********** Creating encap route on r8')
        res = handle_srv6_path(op='add',
                               channel=r8_chan,
                               destination='fd00:0:11::/64',
                               segments=['fcff:4::1', 'fcff:1::100'],
                               device='r8-h83',
                               metric=99)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Encap route created successfully')
        else:
            logger.error('*********** Error while creating encap route')
        #
        # Decap route on r1
        # on r1: ip -6 route add fcff:1::100 encap seg6local action End.DT6
        #        table 254 dev r1-h11 metric 99
        logger.info('*********** Creating decap route on r1')
        res = handle_srv6_behavior(op='add',
                                   channel=r1_chan,
                                   segment='fcff:1::100',
                                   action='End.DT6',
                                   lookup_table=254,
                                   device='r1-h11',
                                   metric=99)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Decap route created successfully')
        else:
            logger.error('*********** Error while creating decap route')
        #
        #
        # +---------------------------------------------------------------+
        # |                   Removing old route via r4                   |
        # +---------------------------------------------------------------+
        logger.info('*** Attempting to remove tunnel r1---r4---r8')
        #
        # Encap route on r1
        # on r1: ip -6 route del fd00:0:83::/64 encap seg6 mode encap segs
        #        fcff:4::1,fcff:8:100 dev r1-h11 metric 200
        logger.info('*********** Removing encap route on r1')
        res = handle_srv6_path(op='del',
                               channel=r1_chan,
                               destination='fd00:0:83::/64',
                               device='r1-h11',
                               metric=200)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Encap route removed successfully')
        else:
            logger.error('*********** Error while removing encap route')
        #
        # Decap route on r8
        # on r8: ip -6 route del fcff:8::100 encap seg6local action End.DT6
        #        table 254 dev r8-h83 metric 200
        logger.info('*********** Removing decap route on r8')
        res = handle_srv6_behavior(op='del',
                                   channel=r8_chan,
                                   segment='fcff:8::100',
                                   device='r8-h83',
                                   metric=200)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Decap route removed successfully')
        else:
            logger.error('*********** Error while removing decap route')
        #
        # Encap route on r8
        # on r8: ip -6 route del fd00:0:11::/64 encap seg6 mode encap segs
        #        fcff:4::1,fcff:1:100 dev r8-h83 metric 200
        logger.info('*********** Removing encap route on r8')
        res = handle_srv6_path(op='del',
                               channel=r8_chan,
                               destination='fd00:0:11::/64',
                               device='r8-h83',
                               metric=200)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Encap route removed successfully')
        else:
            logger.error('*********** Error while removing encap route')
        #
        # Decap route on r1
        # on r1: ip -6 route del fcff:1::100 encap seg6local action End.DT6
        #        table 254 dev r1-h11 metric 200
        logger.info('*********** Removing decap route on r1')
        res = handle_srv6_behavior(op='del',
                                   channel=r1_chan,
                                   segment='fcff:1::100',
                                   device='r1-h11',
                                   metric=200)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Decap route removed successfully')
        else:
            logger.error('*********** Error while removing decap route')
        #
        #
        # +----------------------------------------------------------------+
        # |           Increasing the metric value of the r7 path           |
        # +----------------------------------------------------------------+
        logger.info(
            '*** Increasing the metric value of the tunnel r1---r7---r8')
        #
        # Encap route on r1
        # on r1: ip -6 route add fd00:0:83::/64 encap seg6 mode encap segs
        #        fcff:7::1,fcff:8:100 dev r1-h11 metric 200
        logger.info('*********** Creating encap route on r1')
        res = handle_srv6_path(op='add',
                               channel=r1_chan,
                               destination='fd00:0:83::/64',
                               segments=['fcff:7::1', 'fcff:8::100'],
                               device='r1-h11',
                               metric=200)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Encap route created successfully')
        else:
            logger.error('*********** Error while creating encap route')
        #
        # Decap route on r8
        # on r8: ip -6 route add fcff:8::100 encap seg6local action End.DT6
        #        table 254 dev r8-h83 metric 200
        logger.info('*********** Creating decap route on r8')
        res = handle_srv6_behavior(op='add',
                                   channel=r8_chan,
                                   segment='fcff:8::100',
                                   action='End.DT6',
                                   lookup_table=254,
                                   device='r8-h83',
                                   metric=200)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Decap route created successfully')
        else:
            logger.error('*********** Error while creating decap route')
        #
        # Encap route on r8
        # on r8: ip -6 route add fd00:0:11::/64 encap seg6 mode encap segs
        #        fcff:7::1,fcff:1:100 dev r8-h83 metric 200
        logger.info('*********** Creating encap route on r8')
        res = handle_srv6_path(op='add',
                               channel=r8_chan,
                               destination='fd00:0:11::/64',
                               segments=['fcff:7::1', 'fcff:1::100'],
                               device='r8-h83',
                               metric=200)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Encap route created successfully')
        else:
            logger.error('*********** Error while creating encap route')
        #
        # Decap route on r1
        # on r1: ip -6 route add fcff:1::100 encap seg6local action End.DT6
        #        table 254 dev r1-h11 metric 200
        logger.info('*********** Creating decap route on r1')
        res = handle_srv6_behavior(op='add',
                                   channel=r1_chan,
                                   segment='fcff:1::100',
                                   action='End.DT6',
                                   lookup_table=254,
                                   device='r1-h11',
                                   metric=200)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Decap route created successfully')
        else:
            logger.error('*********** Error while creating decap route')
        #
        #
        # +---------------------------------------------------------------+
        # |                   Removing old route via r7                   |
        # +---------------------------------------------------------------+
        logger.info('*** Attempting to remove tunnel r1---r7---r8')
        # Encap route on r1
        # on r1: ip -6 route del fd00:0:83::/64 encap seg6 mode encap segs
        #        fcff:7::1,fcff:8:100 dev r1-h11 metric 100
        logger.info('*********** Removing encap route on r1')
        res = handle_srv6_path(op='del',
                               channel=r1_chan,
                               destination='fd00:0:83::/64',
                               device='r1-h11',
                               metric=100)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Encap route removed successfully')
        else:
            logger.error('*********** Error while removing encap route')
        #
        # Decap route on r8
        # on r8: ip -6 route del fcff:8::100 encap seg6local action End.DT6
        #        table 254 dev r8-h83 metric 100
        logger.info('*********** Removing decap route on r8')
        res = handle_srv6_behavior(op='del',
                                   channel=r8_chan,
                                   segment='fcff:8::100',
                                   device='r8-h83',
                                   metric=100)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Decap route removed successfully')
        else:
            logger.error('*********** Error while removing decap route')
        #
        # Encap route on r8
        # on r8: ip -6 route del fd00:0:11::/64 encap seg6 mode encap segs
        #        fcff:7::1,fcff:1:100 dev r8-h83 metric 100
        logger.info('*********** Removing encap route on r8')
        res = handle_srv6_path(op='del',
                               channel=r8_chan,
                               destination='fd00:0:11::/64',
                               device='r8-h83',
                               metric=100)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Encap route removed successfully')
        else:
            logger.error('*********** Error while removing encap route')
        #
        # Decap route on r1
        # on r1: ip -6 route del fcff:1::100 encap seg6local action End.DT6
        #        table 254 dev r1-h11 metric 100
        logger.info('*********** Removing decap route on r1')
        res = handle_srv6_behavior(op='del',
                                   channel=r1_chan,
                                   segment='fcff:1::100',
                                   device='r1-h11',
                                   metric=100)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Decap route removed successfully')
        else:
            logger.error('*********** Error while removing decap route')
        #
        #
        # +---------------------------------------------------------------+
        # |      Assign to r4 route a definitive value of the metric      |
        # +---------------------------------------------------------------+
        logger.info('*** Assign to r4 route a definitive value of the metric')
        #
        # Encap route on r1
        # on r1: ip -6 route add fd00:0:83::/64 encap seg6 mode encap segs
        #        fcff:4::1,fcff:8:100 dev r1-h11 metric 100
        logger.info('*********** Creating encap route on r1')
        res = handle_srv6_path(op='add',
                               channel=r1_chan,
                               destination='fd00:0:83::/64',
                               segments=['fcff:4::1', 'fcff:8::100'],
                               device='r1-h11',
                               metric=100)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Encap route created successfully')
        else:
            logger.error('*********** Error while creating encap route')
        #
        # Decap route on r8
        # on r8: ip -6 route add fcff:8::100 encap seg6local action End.DT6
        #        table 254 dev r8-h83 metric 100
        logger.info('*********** Creating decap route on r8')
        res = handle_srv6_behavior(op='add',
                                   channel=r8_chan,
                                   segment='fcff:8::100',
                                   action='End.DT6',
                                   lookup_table=254,
                                   device='r8-h83',
                                   metric=100)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Decap route created successfully')
        else:
            logger.error('*********** Error while creating decap route')
        #
        # Encap route on r8
        # on r8: ip -6 route add fd00:0:11::/64 encap seg6 mode encap segs
        #        fcff:4::1,fcff:1:100 dev r8-h83 metric 100
        logger.info('*********** Creating encap route on r8')
        res = handle_srv6_path(op='add',
                               channel=r8_chan,
                               destination='fd00:0:11::/64',
                               segments=['fcff:4::1', 'fcff:1::100'],
                               device='r8-h83',
                               metric=100)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Encap route created successfully')
        else:
            logger.error('*********** Error while creating encap route')
        #
        # Decap route on r1
        # on r1: ip -6 route add fcff:1::100 encap seg6local action End.DT6
        #        table 254 dev r1-h11 metric 100
        logger.info('*********** Creating decap route on r1')
        res = handle_srv6_behavior(op='add',
                                   channel=r1_chan,
                                   segment='fcff:1::100',
                                   action='End.DT6',
                                   lookup_table=254,
                                   device='r1-h11',
                                   metric=100)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Decap route created successfully')
        else:
            logger.error('*********** Error while creating decap route')
        #
        #
        # +---------------------------------------------------------------+
        # | Delete the r4 route with the intermediate value of the metric |
        # +---------------------------------------------------------------+
        logger.info('*** Delete the r4 route with the intermediate value of '
                    'the metric')
        #
        # Encap route on r1
        # on r1: ip -6 route del fd00:0:83::/64 encap seg6 mode encap segs
        #        fcff:4::1,fcff:8:100 dev r1-h11 metric 99
        logger.info('*********** Removing encap route on r1')
        res = handle_srv6_path(op='del',
                               channel=r1_chan,
                               destination='fd00:0:83::/64',
                               device='r1-h11',
                               metric=99)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Encap route removed successfully')
        else:
            logger.error('*********** Error while removing encap route')
        #
        # Decap route on r8
        # on r8: ip -6 route del fcff:8::100 encap seg6local action End.DT6
        #        table 254 dev r8-h83 metric 99
        logger.info('*********** Removing decap route on r8')
        res = handle_srv6_behavior(op='del',
                                   channel=r8_chan,
                                   segment='fcff:8::100',
                                   device='r8-h83',
                                   metric=99)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Decap route removed successfully')
        else:
            logger.error('*********** Error while removing decap route')
        #
        # Encap route on r8
        # on r8: ip -6 route del fd00:0:11::/64 encap seg6 mode encap segs
        #        fcff:4::1,fcff:1:100 dev r8-h83 metric 99
        logger.info('*********** Removing encap route on r8')
        res = handle_srv6_path(op='del',
                               channel=r8_chan,
                               destination='fd00:0:11::/64',
                               device='r8-h83',
                               metric=99)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Encap route removed successfully')
        else:
            logger.error('*********** Error while removing encap route')
        #
        # Decap route on r1
        # on r1: ip -6 route del fcff:1::100 encap seg6local action End.DT6
        #        table 254 dev r1-h11 metric 99
        logger.info('*********** Removing decap route on r1')
        res = handle_srv6_behavior(op='del',
                                   channel=r1_chan,
                                   segment='fcff:1::100',
                                   device='r1-h11',
                                   metric=99)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Decap route removed successfully')
        else:
            logger.error('*********** Error while removing decap route')
        #
        #
        # +---------------------------------------------------------------+
        # |                             Done                              |
        # +---------------------------------------------------------------+
        print()
def remove_tunnel_r1r7r8():
    # +--------------------------------------------------------------------+
    # |          Remove a bidirectional tunnel between h11 and h83         |
    # |              passing through router r7 (r1---r7---r8)              |
    # +--------------------------------------------------------------------+
    logger.info('*** Attempting to remove tunnel r1---r7---r8')
    # IP addresses
    r1 = 'fcff:1::1'
    r8 = 'fcff:8::1'
    # Open gRPC channels
    with get_grpc_session(r1, GRPC_PORT) as r1_chan, \
            get_grpc_session(r8, GRPC_PORT) as r8_chan:
        # +---------------------------------------------------------------+
        # |         Remove tunnel from r1 to r8 for fd00:0:83::/64        |
        # +---------------------------------------------------------------+
        logger.info('******* Removing tunnel from r1 to r8 for fd00:0:83::/64')
        #
        # Decap route on r8
        # on r8: ip -6 route del fcff:8::100 dev r8-h83 metric 100
        logger.info('*********** Removing decap route')
        res = handle_srv6_behavior(op='del',
                                   channel=r8_chan,
                                   segment='fcff:8::100',
                                   device='r8-h83',
                                   metric=200)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Decap route removed successfully')
        else:
            logger.error('*********** Error while removing decap route')
        #
        # Encap route on r1
        # on r1: ip -6 route del fd00:0:83::/64 dev r1-h11 metric 100
        logger.info('*********** Removing encap route')
        res = handle_srv6_path(op='del',
                               channel=r1_chan,
                               destination='fd00:0:83::/64',
                               device='r1-h11',
                               metric=200)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Encap route removed successfully')
        else:
            logger.error('*********** Error while removing encap route')
        #
        #
        # +---------------------------------------------------------------+
        # |         Remove tunnel from r8 to r1 for fd00:0:11::/64        |
        # +---------------------------------------------------------------+
        logger.info('******* Removing tunnel from r8 to r1 for fd00:0:11::/64')
        #
        # Decap route on r1
        # on r1: ip -6 route del fcff:1::100 dev r1-h11 metric 100
        logger.info('*********** Removing decap route')
        res = handle_srv6_behavior(op='del',
                                   channel=r1_chan,
                                   segment='fcff:1::100',
                                   device='r1-h11',
                                   metric=200)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Decap route removed successfully')
        else:
            logger.error('*********** Error while removing decap route')
        #
        # Encap route on r8
        # on r8: ip -6 route del fd00:0:11::/64 dev r8-h83 metric 200
        logger.info('*********** Removing encap route')
        res = handle_srv6_path(op='del',
                               channel=r8_chan,
                               destination='fd00:0:11::/64',
                               device='r8-h83',
                               metric=200)
        if res == srv6_manager_pb2.StatusCode.STATUS_SUCCESS:
            logger.info('*********** Encap route removed successfully')
        else:
            logger.error('*********** Error while removing encap route')
        #
        #
        # +---------------------------------------------------------------+
        # |                             Done                              |
        # +---------------------------------------------------------------+
        print()