API

_MasterModel

class pyNTM.master_model._MasterModel(interface_objects={}, node_objects={}, demand_objects={}, rsvp_lsp_objects={})[source]

Bases: object

Parent class for Model and Parallel_Link_Model subclasses; holds common defs. This cannot be used to instantiate a functioning model directly. Use a subclass FlexModel or PerformanceModel

add_demand(source_node_name, dest_node_name, traffic=0, name='none')[source]

Adds a traffic load (Demand) from point A to point B in the model and validates model.

Parameters:
  • source_node_name – name of Demand’s source Node
  • dest_node_name – name of Demand’s destination Node
  • traffic – amount of traffic (magnitude) of the Demand
  • name – Demand name
Returns:

A validated Model object with the new demand

add_node(node_object)[source]

Adds a node object to the model object and validates self

Parameters:node_object – Node object to add to self
add_rsvp_lsp(source_node_name, dest_node_name, name)[source]

Adds an RSVP LSP with name from the source node to the dest node and validates model.

Parameters:
  • source_node_name – LSP source Node name
  • dest_node_name – LSP destination Node name
  • name – name of LSP
Returns:

A validated Model with the new RSVP_LSP object

add_srlg(srlg_name)[source]

Adds SRLG object to Model

Parameters:srlg_name – name of SRLG to add to self
all_interface_circuit_ids

Returns all interface circuit_ids

change_interface_name(node_name, current_interface_name, new_interface_name)[source]

Changes interface name

Parameters:
  • node_name – name of Node holding Interface
  • current_interface_name – current Interface name
  • new_interface_name – new Interface name
Returns:

Interface with new name

display_demand_paths()[source]

Displays each demand and its path(s) across the network

display_interface_objects()[source]

Displays interface objects in a more human readable manner

display_interface_status()[source]

Returns failed = True/False for each interface

display_interfaces_traffic()[source]

A human-readable(-ish) display of interfaces and traffic on each

display_node_status()[source]

Returns failed = True/False for each node

fail_interface(interface_name, node_name)[source]

Fails the Interface in self object for the interface_name/node_name pair

Parameters:
  • interface_name – name of Interface object
  • node_name – Name of Node holding Interface
fail_node(node_name)[source]

Fails specified Node with name node_name

fail_srlg(srlg_name)[source]

Sets SRLG with name srlg_name to failed = True

Parameters:srlg_name – name of SRLG to fail
Returns:none
get_circuit_object_from_interface(interface_name, node_name)[source]

Returns a Circuit object, given a Node name and Interface name

Parameters:
  • interface_name – Interface object on one side of Circuit
  • node_name – Node name where Interface resides
Returns:

Circuit object from self that contains Interface with interface_name and node_name

get_demand_object(source_node_name, dest_node_name, demand_name='none')[source]

Returns demand specified by the source_node_name, dest_node_name, name; throws exception if demand not found

Parameters:
  • source_node_name – name of Node where desired Demand originates (source)
  • dest_node_name – name of Node where desired Demand terminates (destination)
  • demand_name – name of Demand object
Returns:

desired Demand object that matches parameters above

get_demand_objects_dest_node(dest_node_name)[source]

Returns list of demands objects originating at the destination node

Parameters:dest_node_name – name of destination node for Demands
Returns:list of Demands terminating on destination node
get_demand_objects_source_node(source_node_name)[source]

Returns list of demand objects originating at the node with name source_node_name

Parameters:source_node_name – name of source node for Demands
Returns:list of Demands originating at node
get_failed_interface_objects()[source]

Returns a list of all failed interfaces in self

get_failed_node_objects()[source]

Returns a list of all failed Nodes in self

get_interface_object(interface_name, node_name)[source]

Returns an interface object for specified node name and interface name

Parameters:
  • interface_name – name of Interface
  • node_name – name of Node
Returns:

Specified Interface object from self

get_node_interfaces(node_name)[source]

Returns list of interfaces on specified node name

get_node_object(node_name)[source]

Returns a Node object from self, given a Node’s name

Parameters:node_name – name of Node object in self
Returns:Node object with node_name
get_non_failed_node_objects()[source]

Returns a list of all failed nodes

get_orphan_node_objects()[source]

Returns list of Nodes that have no interfaces

get_rsvp_lsp(source_node_name, dest_node_name, lsp_name='none')[source]

Returns the RSVP LSP from the model with the specified source node name, dest node name, and LSP name.

Parameters:
  • source_node_name – name of source node for LSP
  • dest_node_name – name of destination node for LSP
  • lsp_name – name of LSP
Returns:

RSVP_LSP object

get_srlg_object(srlg_name, raise_exception=True)[source]

Returns SRLG in self with srlg_name

Parameters:
  • srlg_name – name of SRLG
  • raise_exception – raise an exception if SRLG with name=srlg_name does not exist in self
Returns:

None

get_unfailed_interface_objects()[source]

Returns a list of all non-failed interfaces in the self

get_unrouted_demand_objects()[source]

Returns list of demand objects that cannot be routed in self

is_node_an_orphan(node_object)[source]

Determines if a node is in orphan_nodes. A node in orphan_nodes is a Node with no Interface objects

Parameters:node_object – Node object
Returns:Boolean indicating if Node is orphan (True) or not (False)
parallel_demand_groups()[source]

Determine demands with same source and dest nodes

Returns:dict with entries where key is ‘source_node_name-dest_node_name’ and value is a list of demands with matching source/dest nodes # noqa E501

Example:

{'A-F': [Demand(source = A, dest = F, traffic = 40, name = 'dmd_a_f_1')],
'A-D': [Demand(source = A, dest = D, traffic = 80, name = 'dmd_a_d_1'),
Demand(source = A, dest = D, traffic = 70, name = 'dmd_a_d_2'),
Demand(source = A, dest = D, traffic = 100, name = 'dmd_a_to_d_3')],
'F-E': [Demand(source = F, dest = E, traffic = 400, name = 'dmd_f_e_1')]}
parallel_lsp_groups()[source]

Determine LSPs with same source and dest nodes

Returns:dict with entries where key is ‘source_node_name-dest_node_name’ and value is a list of LSPs with matching source/dest nodes # noqa E501

Example:

{'A-F': [RSVP_LSP(source = A, dest = F, lsp_name = 'lsp_a_f')],
'A-D': [RSVP_LSP(source = A, dest = D, lsp_name = 'lsp_a_d_1'),
RSVP_LSP(source = A, dest = D, lsp_name = 'lsp_a_d_2'),
RSVP_LSP(source = A, dest = D, lsp_name = 'lsp_a_d_4'),
RSVP_LSP(source = A, dest = D, lsp_name = 'lsp_a_d_3')],
'B-C': [RSVP_LSP(source = B, dest = C, lsp_name = 'lsp_b_c_1')],
'F-E': [RSVP_LSP(source = F, dest = E, lsp_name = 'lsp_f_e_1')]}
simulation_diagnostics()[source]

Analyzes simulation results and looks for the following:

  • Number of routed LSPs carrying Demands
  • Number of routed LSPs with no Demands
  • Number of Demands riding LSPs
  • Number of Demands not riding LSPs
  • Number of unrouted LSPs
  • Number of unrouted Demands
Returns:dict with the above as keys and the quantity of each for values and generators for routed LSPs with no Demands, routed LSPs carrying Demands, Demands riding LSPs # noqa E501

This is not cached currently and my be expensive to (re)run on a very large model. Current best practice is to assign the output of this to a variable:

Example:

sim_diag1 = model1.simulation_diagnostics()
unfail_interface(interface_name, node_name, raise_exception=False)[source]

Unfails the Interface object for the interface_name, node_name pair.

Parameters:
  • interface_name – name of interface
  • node_name – node name
  • raise_exception – If raise_exception=True, an exception will be raised if the interface cannot be unfailed. An example of this would be if you tried to unfail the interface when the parent node or remote node was in a failed state
Returns:

Interface object from Model with ‘failed’ attribute set to False

unfail_node(node_name)[source]

Unfails the Node with name=node_name

unfail_srlg(srlg_name)[source]

Sets SRLG with srlg_name to failed = False :param srlg_name: name of SRLG to unfail :return: none

PerformanceModel

class pyNTM.performance_model.PerformanceModel(interface_objects={}, node_objects={}, demand_objects={}, rsvp_lsp_objects={})[source]

Bases: pyNTM.master_model._MasterModel

A network model object consisting of the following base components:
  • Interface objects (set): layer 3 Node interfaces. Interfaces have a ‘capacity’ attribute that determines how much traffic it can carry. Note: Interfaces are matched into Circuit objects based on the interface circuit_ids –> A pair of Interfaces with the same circuit_id value get matched into a Circuit
  • Node objects (set): vertices on the network (aka ‘layer 3 devices’) that contain Interface objects. Nodes are connected to each other via a pair of matched Interfaces (Circuits)
  • Demand objects (set): traffic loads on the network. Each demand starts from a source node and transits the network to a destination node. A demand also has a magnitude, representing how much traffic it is carrying. The demand’s magnitude will apply against each interface’s available capacity
  • RSVP LSP objects (set): RSVP LSPs in the Model
  • Circuit objects are created by matching Interface objects
add_circuit(node_a_object, node_b_object, node_a_interface_name, node_b_interface_name, cost_intf_a=1, cost_intf_b=1, capacity=1000, failed=False, circuit_id=None)[source]

Creates component Interface objects for a new Circuit in the Model. The Circuit object will then be created during the validate_model() call.

Parameters:
  • node_a_object – Node object
  • node_b_object – Node object
  • node_a_interface_name – name of component Interface on node_a
  • node_b_interface_name – name of component Interface on node_b
  • cost_intf_a – metric/cost of node_a_interface component Interface
  • cost_intf_b – metric/cost of node_b_interface component Interface
  • capacity – Circuit’s capacity
  • failed – Should the Circuit be created in a Failed state?
  • circuit_id – Optional. Will be auto-assigned unless specified
Returns:

Model with new Circuit comprised of 2 new Interfaces

add_network_interfaces_from_list(network_interfaces)[source]

A tool that reads network interface info and updates an existing model. Intended to be used from CLI/interactive environment Interface info must be a list of dicts and in format like below example.

Example:

network_interfaces = [
{'name':'A-to-B', 'cost':4,'capacity':100, 'node':'A',
'remote_node': 'B', 'circuit_id': 1, 'failed': False},
{'name':'A-to-Bv2', 'cost':40,'capacity':150, 'node':'A',
'remote_node': 'B', 'circuit_id': 2, 'failed': False},
{'name':'A-to-C', 'cost':1,'capacity':200, 'node':'A',
'remote_node': 'C', 'circuit_id': 3, 'failed': False},]
Parameters:network_interfaces – python list of attributes for Interface objects
Returns:self with new Interface objects
get_all_paths_reservable_bw(source_node_name, dest_node_name, include_failed_circuits=True, cutoff=10, needed_bw=0)[source]

For a source and dest node name pair, find all simple path(s) with at least needed_bw reservable bandwidth available less than or equal to cutoff hops long. The amount of simple paths (paths that don’t have repeating nodes) can be very large for larger topologies and so this call can be very expensive. Use the cutoff argument to limit the path length to consider to cut down on the time it takes to run this call.

Parameters:
  • source_node_name – name of source node in path
  • dest_node_name – name of destination node in path
  • include_failed_circuits – include failed circuits in the topology
  • needed_bw – the amount of reservable bandwidth required on the path
  • cutoff – max amount of path hops
Returns:

Return the path(s) in dictionary form:

Example:

>>> model.get_all_paths_reservable_bw('A', 'B', False, 5, 10)
{'path': [
[Interface(name = 'A-to-D', cost = 40, capacity = 20.0,
  node_object = Node('A'), remote_node_object = Node('D'), circuit_id = 2),
Interface(name = 'D-to-B', cost = 20, capacity = 125.0, node_object = Node('D'),
  remote_node_object = Node('B'), circuit_id = 7)],
[Interface(name = 'A-to-D', cost = 40, capacity = 20.0, node_object = Node('A'),
  remote_node_object = Node('D'), circuit_id = 2),
Interface(name = 'D-to-G', cost = 10, capacity = 100.0, node_object = Node('D'),
  remote_node_object = Node('G'), circuit_id = 8),
Interface(name = 'G-to-B', cost = 10, capacity = 100.0, node_object = Node('G'),
  remote_node_object = Node('B'), circuit_id = 9)]
]}
get_interface_object_from_nodes(local_node_name, remote_node_name)[source]

Returns a list of Interface objects with the specified local and remote node names.

Parameters:
  • local_node_name – Name of Interface local node
  • remote_node_name – Name of Interface remote node
Returns:

Interface object with specified local node and remote node names

get_shortest_path(source_node_name, dest_node_name, needed_bw=0)[source]

For a source and dest node name pair, find the shortest path(s) with at least needed_bw available.

Parameters:
  • source_node_name – name of source node in path
  • dest_node_name – name of destination node in path
  • needed_bw – the amount of reservable bandwidth required on the path
Returns:

Return the shortest path in dictionary form

Example:

shortest_path = {'path': [list of shortest path routes], 'cost': path_cost}

get_shortest_path_for_routed_lsp(source_node_name, dest_node_name, lsp, needed_bw)[source]

For a source and dest node name pair, find the shortest path(s) with at least needed_bw available for an LSP that is already routed. This takes into account reserved bandwidth on the Interfaces the LSP already transits, allowing the bandwidth reserved by the LSP to be considered for reservation on any new path for the input LSP Return the shortest path in dictionary form: shortest_path = {‘path’: [list of shortest path routes], ‘cost’: path_cost}

Parameters:
  • source_node_name – name of source node
  • dest_node_name – name of destination node
  • lsp – LSP object
  • needed_bw – reserved bandwidth for LSPs
Returns:

dict {‘path’: [list of lists, each list a shortest path route], ‘cost’: path_cost}

Example::
>>> lsp
RSVP_LSP(source = B, dest = C, lsp_name = 'lsp_b_c_1')
>>> path = model.get_shortest_path_for_routed_lsp('A', 'D', lsp, 10)
>>> path
{'path': [[Interface(name = 'A-to-D', cost = 40, capacity = 20.0, node_object = Node('A'),
remote_node_object = Node('D'), circuit_id = 3)]], 'cost': 40}
classmethod load_model_file(data_file)[source]

Opens a network_modeling data file, returns a model containing the info in the data file, and runs update_simulation().

The data file must be of the appropriate format to produce a valid model. This cannot be used to open multiple models in a single python instance - there may be unpredictable results in the info in the models. The format for the file must be a tab separated value file. This docstring you are reading may not display the table info explanations/examples below correctly on https://pyntm.readthedocs.io/en/latest/api.html. Recommend either using help(Model.load_model_file) at the python3 cli or looking at one of the sample model data_files in github: https://github.com/tim-fiola/network_traffic_modeler_py3/blob/master/examples/sample_network_model_file.csv https://github.com/tim-fiola/network_traffic_modeler_py3/blob/master/examples/lsp_model_test_file.csv The following headers must exist, with the following tab-column names beneath:

INTERFACES_TABLE
- node_object_name - name of node   where interface resides
- remote_node_object_name   - name of remote node
- name - interface name
- cost - IGP cost/metric for interface
- capacity - capacity
- rsvp_enabled (optional) - is interface allowed to carry RSVP LSPs? True|False; default is True
- percent_reservable_bandwidth (optional) - percent of capacity allowed to be reserved by RSVP LSPs; this
value should be given as a percentage value - ie 80% would be given as 80, NOT .80.  Default is 100

Note - The existence of Nodes will be inferred from the INTERFACES_TABLE. So a Node created from an Interface does not have to appear in the NODES_TABLE unless you want to add additional attributes for the Node such as latitude/longitude

NODES_TABLE - - name - name of node - lon - longitude (or y-coordinate) (optional) - lat - latitude (or x-coordinate) (optional)

Note - The NODES_TABLE is present for 2 reasons: - to add a Node that has no interfaces - and/or to add additional attributes for a Node inferred from the INTERFACES_TABLE

DEMANDS_TABLE - source - source node name - dest - destination node name - traffic - amount of traffic on demand - name - name of demand

RSVP_LSP_TABLE - source - LSP’s source node - dest - LSP’s destination node - name - name of LSP - configured_setup_bw (optional) - if LSP has a fixed, static configured setup bandwidth, place that static value here, if LSP is auto-bandwidth, then leave this blank for the LSP - manual_metric (optional) - manually assigned metric for LSP, if not using default metric from topology shortest path

Functional model files can be found in this directory in https://github.com/tim-fiola/network_traffic_modeler_py3/tree/master/examples Here is an example of a data file:

Example:

INTERFACES_TABLE
node_object_name    remote_node_object_name name    cost    capacity    rsvp_enabled    percent_reservable_bandwidth  # noqa E501
A   B       A-to-B  4       100
B   A       B-to-A  4       100

NODES_TABLE
name        lon     lat
A   50      0
B   0       -50

DEMANDS_TABLE
source      dest    traffic name
A   B       80      dmd_a_b_1

RSVP_LSP_TABLE
source      dest    name    configured_setup_bw manual_metric
A   B       lsp_a_b_1   10  15
A   B       lsp_a_b_2       10
Parameters:data_file – file with model info
Returns:Model object
update_simulation()[source]

Updates the simulation state; this needs to be run any time there is a change to the state of the Model, such as failing an interface, adding a Demand, adding/removing and LSP, etc. This call does not carry forward any state from the previous simulation results.

validate_model()[source]

Validates that data fed into the model creates a valid network model

validate_srlg_nodes()[source]

Validate that Nodes in each SRLG have the SRLG in their srlgs set. srlg_errors is a dict of node names as keys and a list of SRLGs that node is a member of in the model but that the SRLG is not in node.srlgs :return: dict where keys are Node names and values are lists of SRLG names; each value will be a single list of SRLG names missing that Node in the SRLG node set

FlexModel

class pyNTM.flex_model.FlexModel(interface_objects={}, node_objects={}, demand_objects={}, rsvp_lsp_objects={})[source]

Bases: pyNTM.master_model._MasterModel

A network model object consisting of the following base components:

  • Interface objects (set): layer 3 Node interfaces. Interfaces have a ‘capacity’ attribute that determines how much traffic it can carry. Note: Interfaces are matched into Circuit objects based on the interface circuit_ids –> A pair of Interfaces with the same circuit_id value get matched into a Circuit
  • Node objects (set): vertices on the network (aka ‘layer 3 devices’) that contain Interface objects. Nodes are connected to each other via a pair of matched Interfaces (Circuits)
  • Demand objects (set): traffic loads on the network. Each demand starts from a source node and transits the network to a destination node. A demand also has a magnitude, representing how much traffic it is carrying. The demand’s magnitude will apply against each interface’s available capacity
  • RSVP LSP objects (set): RSVP LSPs in the Model
  • Circuit objects are created by matching Interface objects using common circuit_id
add_circuit(node_a_object, node_b_object, node_a_interface_name, node_b_interface_name, cost_intf_a=1, cost_intf_b=1, capacity=1000, failed=False, circuit_id=None)[source]

Creates component Interface objects for a new Circuit in the Model. The Circuit object will then be created during the validate_model() call.

Parameters:
  • node_a_object – Node object
  • node_b_object – Node object
  • node_a_interface_name – name of component Interface on node_a
  • node_b_interface_name – name of component Interface on node_b
  • cost_intf_a – metric/cost of node_a_interface component Interface
  • cost_intf_b – metric/cost of node_b_interface component Interface
  • capacity – Circuit’s capacity
  • failed – Should the Circuit be created in a Failed state?
  • circuit_id – Optional. Will be auto-assigned unless specified
Returns:

Model with new Circuit comprised of 2 new Interfaces

add_network_interfaces_from_list(network_interfaces)[source]

A tool that reads network interface info and updates an existing model. Intended to be used from CLI/interactive environment Interface info must be a list of dicts and in format like below example.

Example:

network_interfaces = [
{'name':'A-to-B', 'cost':4,'capacity':100, 'node':'A',
'remote_node': 'B', 'circuit_id': 1, 'failed': False},
{'name':'A-to-Bv2', 'cost':40,'capacity':150, 'node':'A',
'remote_node': 'B', 'circuit_id': 2, 'failed': False},
{'name':'A-to-C', 'cost':1,'capacity':200, 'node':'A',
'remote_node': 'C', 'circuit_id': 3, 'failed': False},]
Parameters:network_interfaces – python list of attributes for Interface objects
Returns:self with new Interface objects
find_igp_shortcuts(paths, node_paths)[source]

Check for LSPs along the shortest path; find the first LSP the demand can take with a source and destination that is on the LSP’s IGP path

  1. examine each IGP path
  2. If none of the nodes on the path have IGP shortcuts, continue to next path
  3. If some nodes have IGP shortcuts enabled, note the hop number (1, 2, 3, etc)
  4. For nodes that have IGP shortcuts, is there an LSP from that node to a downstream node on the path?
  • if yes, compare the IGP metric of the path to the LSP remote node to that of the LSP metric to that node
  • if no, look at next node downstream with IGP shortcuts
  1. Look for manually set RSVP LSP metrics that may alter the path calculations
Parameters:
  • paths – List of lists; each list contains egress Interfaces along the path from source to destination (ordered from source to destination) # noqa E501
  • node_paths – List of lists; each list contains node names along the path from source to destination (ordered from source to destination)
Returns:

List of lists; each list contains Interfaces and/or RSVP LSPs along each path from source to destination # noqa E501

get_all_paths_reservable_bw(source_node_name, dest_node_name, include_failed_circuits=True, cutoff=10, needed_bw=0)[source]

For a source and dest node name pair, find all simple path(s) with at least needed_bw reservable bandwidth available less than or equal to cutoff hops long.

The amount of simple paths (paths that don’t have repeating nodes) can be very large for larger topologies and so this call can be very expensive. Use the cutoff argument to limit the path length to consider to cut down on the time it takes to run this call.

Parameters:
  • source_node_name – name of source node in path
  • dest_node_name – name of destination node in path
  • include_failed_circuits – include failed circuits in the topology
  • needed_bw – the amount of reservable bandwidth required on the path
  • cutoff – max amount of path hops
Returns:

Return the path(s) in dictionary form: path = {‘path’: [list of shortest path routes]}

Example:

>>> model.get_all_paths_reservable_bw('A', 'B', False, 5, 10)
{'path': [
[Interface(name = 'A-to-D', cost = 40, capacity = 20.0,
node_object = Node('A'), remote_node_object = Node('D'), circuit_id = 2),
Interface(name = 'D-to-B', cost = 20, capacity = 125.0, node_object = Node('D'),
remote_node_object = Node('B'), circuit_id = 7)],
[Interface(name = 'A-to-D', cost = 40, capacity = 20.0, node_object = Node('A'),
remote_node_object = Node('D'), circuit_id = 2),
Interface(name = 'D-to-G', cost = 10, capacity = 100.0, node_object = Node('D'),
remote_node_object = Node('G'), circuit_id = 8),
Interface(name = 'G-to-B', cost = 10, capacity = 100.0, node_object = Node('G'),
remote_node_object = Node('B'), circuit_id = 9)]
]}
get_interface_object_from_nodes(local_node_name, remote_node_name, circuit_id=None)[source]

Returns a list of Interface objects with the specified local and remote node names.

If ‘circuit_id’ is not specified, may return a list of len > 1, as multiple/parallel interfaces are allowed in Parallel_Link_Model objects.

If ‘circuit_id’ is specified, will return a list of len == 1, as specifying the ‘circuit_id’ will narrow down any list of multiple interfaces to a single interface because circuit_ids bond interfaces on different nodes into a Circuit object.

Parameters:
  • local_node_name – Name of local node Interface resides on
  • remote_node_name – Name of Interface’s remote Node
  • circuit_id – circuit_id of Interface (optional)
Returns:

list of Interface objects with common local node and remote node

get_shortest_path(source_node_name, dest_node_name, needed_bw=0)[source]

For a source and dest node name pair, find the shortest path(s) with at least needed_bw available.

Parameters:
  • source_node_name – name of source node in path
  • dest_node_name – name of destination node in path
  • needed_bw – the amount of reservable bandwidth required on the path
Returns:

Return the shortest path in dictionary form: shortest_path = {‘path’: [list of shortest path routes], ‘cost’: path_cost}

get_shortest_path_for_routed_lsp(source_node_name, dest_node_name, lsp, needed_bw)[source]

For a source and dest node name pair, find the shortest path(s) with at least needed_bw available for an LSP that is already routed. Return the shortest path in dictionary form: shortest_path = {‘path’: [list of shortest path routes], ‘cost’: path_cost}

Parameters:
  • source_node_name – name of source node
  • dest_node_name – name of destination node
  • lsp – LSP object
  • needed_bw – reserved bandwidth for LSPs
Returns:

dict {‘path’: [list of lists, each list a shortest path route], ‘cost’: path_cost}

classmethod load_model_file(data_file)[source]

Opens a network_modeling data file, returns a model containing the info in the data file, and runs update_simulation().

The data file must be of the appropriate format to produce a valid model. This cannot be used to open multiple models in a single python instance - there may be unpredictable results in the info in the models.

The format for the file must be a tab separated value file.

CIRCUIT ID (circuit_id) MUST BE SPECIFIED AS THIS IS WHAT ALLOWS THE CLASS TO DISCERN WHAT MULTIPLE, PARALLEL INTERFACES BETWEEN THE SAME NODES MATCH UP INTO WHICH CIRCUIT. THE circuit_id CAN BE ANY COMMON KEY, SUCH AS IP SUBNET ID OR DESIGNATED CIRCUIT ID FROM PRODUCTION.

This docstring you are reading may not display the table info explanations/examples below correctly on https://pyntm.readthedocs.io/en/latest/api.html. Recommend either using help(Model.load_model_file) at the python3 cli or looking at one of the sample model data_files in github: https://github.com/tim-fiola/network_traffic_modeler_py3/blob/master/examples/sample_network_model_file.csv https://github.com/tim-fiola/network_traffic_modeler_py3/blob/master/examples/lsp_model_test_file.csv

The following headers must exist, with the following tab-column names beneath:

INTERFACES_TABLE
- node_object_name - name of node   where interface resides
- remote_node_object_name   - name of remote node
- name - interface name
- cost - IGP cost/metric for interface
- capacity - capacity
- circuit_id - id of the circuit; used to match two Interfaces into Circuits;
    - each circuit_id can only appear twice in the model
    - circuit_id can be string or integer
- rsvp_enabled (optional) - is interface allowed to carry RSVP LSPs? True|False; default is True
- percent_reservable_bandwidth (optional) - percent of capacity allowed to be reserved by RSVP LSPs; this
value should be given as a percentage value - ie 80% would be given as 80, NOT .80.  Default is 100

Note - The existence of Nodes will be inferred from the INTERFACES_TABLE.
So a Node created from an Interface does not have to appear in the
NODES_TABLE unless you want to add additional attributes for the Node
such as latitude/longitude

NODES_TABLE -
- name - name of node
- lon - longitude (or y-coordinate)
- lat - latitude (or x-coordinate)
- igp_shortcuts_enabled(default=False)

Note - The NODES_TABLE is present for 2 reasons:
- to add a Node that has no interfaces
- and/or to add additional attributes for a Node inferred from
the INTERFACES_TABLE

DEMANDS_TABLE
- source - source node name
- dest - destination node name
- traffic   - amount of traffic on demand
- name - name of demand

RSVP_LSP_TABLE (this table is optional)
- source - source node name
- dest - destination node name
- name - name of LSP
- configured_setup_bw - if LSP has a fixed, static configured setup bandwidth, place that static value here,
if LSP is auto-bandwidth, then leave this blank for the LSP (optional)
- manual_metric - manually assigned metric for LSP, if not using default metric from topology
shortest path (optional)

Functional model files can be found in this directory in https://github.com/tim-fiola/network_traffic_modeler_py3/tree/master/examples

Here is an example of a data file.

Example:

INTERFACES_TABLE
node_object_name    remote_node_object_name name    cost    capacity    circuit_id  rsvp_enabled    percent_reservable_bandwidth # noqa E501
A   B       A-to-B_1    20  120 1   True  50
B   A       B-to-A_1    20  120 1   True  50
A   B   A-to-B_2    20  150 2
B   A   B-to-A_2    20  150 2
A   B   A-to-B_3    10  200 3   False
B   A   B-to-A_3    10  200 3   False

NODES_TABLE
name        lon     lat igp_shortcuts_enabled(default=False)
A   50      0   True
B   0       -50 False

DEMANDS_TABLE
source      dest    traffic name
A   B       80      dmd_a_b_1

RSVP_LSP_TABLE
source      dest    name    configured_setup_bw manual_metric
A   B       lsp_a_b_1   10  19
A   B       lsp_a_b_2       6
Parameters:data_file – file with model info
Returns:Model object
update_simulation()[source]

Updates the simulation state; this needs to be run any time there is a change to the state of the Model, such as failing an interface, adding a Demand, adding/removing and LSP, etc.

This call does not carry forward any state from the previous simulation results.

validate_model()[source]

Validates that data fed into the model creates a valid network model

Node

class pyNTM.node.Node(name, lat=0, lon=0)[source]

Bases: object

A class to represent a layer 3 device in the model.

Attribute lat, lon can be used as y, x values, respectively for graphing purposes.

add_to_srlg(srlg_name, model, create_if_not_present=False)[source]

Adds self to an SRLG with name=srlg_name in model.

Parameters:
  • srlg_name – name of srlg
  • model – Model object
  • create_if_not_present – Boolean. Create the SRLG if it does not exist in model already. True will create SRLG in model; False will raise ModelException # noqa E501
Returns:

None

adjacent_nodes(model)[source]

Returns a list of adjacent nodes

Parameters:model – model Object
Returns:List of adjacent Nodes in model
failed

Is node failed? Boolean. It is NOT recommended to directly modify this property. Rather, Model methods fail_node(node_name) and unfail_node(node_name)

Returns:Boolean - is node failed?
igp_shortcuts_enabled

Are IGP shortcuts enabled for RSVP LSPs on this Node? This is only applicable in the FlexModel; PerformanceModel subclass ignores this attribute

interfaces(model)[source]

Returns interfaces for a given node

Parameters:model – model structure
Return adjacency_list:
 (list) list of interfaces on the given node
lat

Latitude or y-coordinate of Node on a plot

lon

Longitude or x-coordinate of Node on a plot

remove_from_srlg(srlg_name, model)[source]

Removes self from SRLG with srlg_name in model

Parameters:
  • srlg_name – name of SRLG
  • model – Model object
Returns:

none

srlgs

Interface

class pyNTM.interface.Interface(name, cost, capacity, node_object, remote_node_object, circuit_id=None, rsvp_enabled=True, percent_reservable_bandwidth=100)[source]

Bases: object

An object representing a Node’s Interface

add_to_srlg(srlg_name, model, create_if_not_present=False)[source]

Adds self to an SRLG with name=srlg_name in model. Also finds the remote Interface object and adds that to the SRLG.

Parameters:
  • srlg_name – name of srlg
  • model – Model object
  • create_if_not_present – Boolean. Create the SRLG if it does not exist in model already. True will create SRLG in model; False will raise ModelException # noqa E501
Returns:

None

capacity
cost
demands(model)[source]

Returns list of demands that egress the interface

Parameters:model – model object containing self
Returns:list of Demand objects egressing self
fail_interface(model)[source]

Updates the specified interface and the remote interface with failed==True

Parameters:model – model object containing self
failed

Is interface failed? Boolean. It is NOT recommended to directly modify this property. Rather, use Interface.fail or Interface.unfail.

Returns:Boolean - is Interface failed?
get_circuit_object(model)[source]

Returns the circuit object from the model that an interface is associated with.

Parameters:model – model object containing self
Returns:Circuit object containing self
get_remote_interface(model)[source]

Returns Interface on other side of the Circuit containing self

Parameters:model – model object holding self
Returns:Interface object on remote side of Circuit containing self
lsps(model)[source]

Returns a list of RSVP LSPs that egress the interface

Parameters:model – Model object
Returns:list of RSVP LSPs that egress the interface
remove_from_srlg(srlg_name, model)[source]

Removes self and remote interface object from SRLG with srlg_name in model.

Parameters:
  • srlg_name – name of SRLG
  • model – Model object
Returns:

none

reservable_bandwidth

Amount of bandwidth available for rsvp lsp reservation. If interface is not rsvp_enabled, then reservable_bandwidth is set to -1

reserved_bandwidth

Amount of interface capacity reserved by RSVP LSPs

srlgs
unfail_interface(model)[source]

Updates the specified interface and the remote interface with failed==False

Parameters:model – model object containing self
utilization

Returns utilization percent = (self.traffic/self.capacity)*100

Demand

class pyNTM.demand.Demand(source_node_object, dest_node_object, traffic=0, name='none')[source]

Bases: object

A representation of traffic load on the modeled network

path_detail

Returns a detailed breakdown of the Demand path. Each path will have the following information:

items: The combination of Interfaces and/or LSPs that the Demand takes from source to destination

splits: each item on the path (Interface and/or LSP) and the number of cumulative ECMP path splits that the Demand has transited as it egresses the source node for that element.

Splits can be used to calculate how much of the Demand’s traffic is on a certain path (see path_traffic below) or how much of the Demand’s traffic is on a certain element.

The demand object’s path_detail property can be very useful to determine how much of the demand’s traffic egresses each object (interface, LSP) in the path.

For example, sample demand Demand(source = A, dest = E, traffic = 24, name = 'dmd_a_e_1') has 24 units of traffic.

Here is the path_0 entry for the sample demand:

'path_0': {
    'items': [Interface(name = 'A-to-B', cost = 4, capacity = 100, node_object = Node('A'),
                remote_node_object = Node('B'), circuit_id = '1'),
            Interface(name = 'B-to-E_3', cost = 3, capacity = 200, node_object = Node('B'),
                remote_node_object = Node('E'), circuit_id = '27')
    ],
    'path_traffic': 4.0,
    'splits': {Interface(name = 'A-to-B', cost = 4, capacity = 100, node_object = Node('A'),
                remote_node_object = Node('B'), circuit_id = '1'): 2,
              Interface(name = 'B-to-E_3', cost = 3, capacity = 200, node_object = Node('B'),
                remote_node_object = Node('E'), circuit_id = '27'): 6}
}

The path_0 component of the path_detail property in this example shows the following:

  • Interface(name = 'A-to-B', cost = 4, capacity = 100, node_object = Node('A'), remote_node_object = Node('B'), circuit_id = '1') has 2 splits
  • Interface(name = 'B-to-E_3', cost = 3, capacity = 200, node_object = Node('B'), remote_node_object = Node('E'), circuit_id = '27') has 6 splits

To get the amount of traffic load from the specific demand that transits each interface, divide the amount of traffic that the demand has by the number of splits for the object:

  • Interface(name = 'A-to-B', cost = 4, capacity = 100, node_object = Node('A'), remote_node_object = Node('B'), circuit_id = '1') carries 24 / 2 = 12 units of traffic from the sample demand.
  • Interface(name = 'B-to-E_3', cost = 3, capacity = 200, node_object = Node('B'), remote_node_object = Node('E'), circuit_id = '27') carries 24 / 6 = 4 units of traffic from the sample demand.

Since the minimum amount of traffic found on any object in path_0 is 4 units of traffic, path_traffic for path_0 = 4.

Returns:Dict of path entries (keys). The value for each key is another dict with 3 keys: ‘items’, ‘splits’, and ‘path_traffic’. Each is described above. # noqa E501

Circuit

class pyNTM.circuit.Circuit(interface_a, interface_b)[source]

Bases: object

A circuit is an object consisting of 2 connected interfaces

circuit_id()[source]

Returns the circuit_id, which bonds the two component Interfaces to the Circuit

failed(model)[source]

Is Circuit failed?

Parameters:model – Model containing circuit
Returns:Boolean
get_circuit_interfaces(model)[source]

Return the Circuit’s component Interface objects in model object

Parameters:model – model object containing Circuit
Returns:Component Interfaces in Circuit

RSVP_LSP

class pyNTM.rsvp.RSVP_LSP(source_node_object, dest_node_object, lsp_name='none', configured_setup_bandwidth=None, configured_manual_metric=None)[source]

Bases: object

A class to represent an RSVP label-switched-path in the network model

source_node_object: Node where LSP ingresses the network (LSP starts here)

dest_node_object: Node where LSP egresses the network (LSP ends here)

lsp_name: name of LSP

path:

will either be 'Unrouted' or be a dict containing the following -
- interfaces: list of interfaces that LSP egresses in the order it
    egresses them
- path_cost: sum of costs of the interfaces
- baseline_path_reservable_bw: the amount of reservable bandwidth
    available on the LSP's path when the LSP was signaled, not inclusive
    of the bandwidth already reserved by this LSP on that path (if any)

reserved_bandwidth: amount of bandwidth reserved by this LSP

setup_bandwidth: amount of bandwidth this LSP attempts to signal for when it sets up

demands_on_lsp(model)[source]

Returns demands in model object that LSP is transporting.

Parameters:model – model object containing LSP
Returns:List of demands in model object that LSP carries
effective_metric(model)[source]

Returns the manually assigned manual_metric (if defined) or the metric for the best path. The best path value will be the metric for the shortest possible path from LSP’s source to dest, regardless of whether the LSP takes that shortest path or not.

Parameters:model – model object containing self
Returns:metric for the LSP’s shortest possible path
find_rsvp_path_w_bw(requested_bandwidth, model)[source]

Will search the topology of ‘model’ for a path for self that has at least ‘requested_bandwidth’ of reservable_bandwidth. If there is one, will update self.path; if not, will keep same self.path. When checking paths, this def will take into account its own reserved bandwidth if it is looking at paths that have interfaces already in its path[‘interfaces’] list.

Parameters:
  • model – Model object to search; this will typically be a Model object consisting of only non-failed interfaces # noqa E501
  • requested_bandwidth – number of units set for reserved_bandwidth
Returns:

self with the current or updated path info

manual_metric

Manual metric for LSP. If set, this value will override the default (shortest path) metric for effective_metric.

This value must be a positive integer.

To restore the LSP’s default metric (that of the shortest path) in a live simulation, set this value to -1.

setup_bandwidth

The bandwidth the LSP attempts to signal for.

Returns:the bandwidth the LSP attempts to signal for
topology_metric(model)[source]

Returns the metric sum of the interfaces that the LSP actually transits on the topology.

Parameters:model – model object containing self
Returns:sum of the metrics of the Interfaces that the LSP transits
traffic_on_lsp(model)[source]

Returns the amount of traffic on the LSP

Parameters:model – Model object for LSP
Returns:Units of traffic on the LSP

Exceptions

Exceptions

exception pyNTM.exceptions.ModelException[source]

Bases: Exception