p4utils.utils.topology module

This module includes all the features needed to query the topology.json file generated by P4-Utils upon execution. Indeed, it allows the usage of topology information in the controller code, so that the switches can be configured properly.

The topology file can be imported in a Python script by using the utility load_topo(), as shown in the following example:

from p4utils.utils.helper import load_topo

topo = load_topo('topology.json')
exception p4utils.utils.topology.IntfDoesNotExist(arg1, arg2, mode=0)[source]

Bases: Exception

Exception raised when an interface is not found.

Parameters:
  • arg1 (str) – first argument
  • arg2 (str) – second argument
  • mode (int) – working mode

Possible mode values are the following:

  • 0, then arg1 is the name of the missing interface and arg2 is the name of the node to which the interface belongs.
  • 1, then arg1 is the name of the node to which the interface belongs and arg2 is the name of the node that the interface is facing.
exception p4utils.utils.topology.InvalidHostIP(ip)[source]

Bases: Exception

Exception raised when a wrong host IP is provided.

class p4utils.utils.topology.NetworkGraph(*args, **kwargs)[source]

Bases: networkx.classes.graph.Graph

Querying API that allows retrieving information about the network topology. It also provides useful methods to perform graph computation (e.g. Dijkstra’s algorithm to get shortest paths).

Note

To use this class in your Python code, you need to import the network topology JSON file (automatically generated by any execution of P4-Utils). This can be easily done with the function load_topo().

edge_to_intf[source]

stores interface information indexed by [node1][node2], where the interface belongs to node1 and is facing node2.

Type:dict
node_to_intf[source]

stores interface information indexed by [node][intfName], where the interface belongs to node and is named according to intfName.

Type:dict
ip_to_host[source]

stores hosts information indexed by [ip].

Type:dict
are_neighbors(node1, node2)[source]

Checks if two nodes are direct neighbors.

Parameters:
  • node1 (str) – first node
  • node2 (str) – second node
Returns:

True if the node are neighbors, False otherwise.

Return type:

bool

checkIntf(node1, node2)[source]

Sanity check on interface existence.

Parameters:
  • node1 (str) – name of the first node
  • node2 (str) – name of the second node
Raises:

IntfDoesNotExist – if the given interface does not exist.

checkNode(name)[source]

Sanity check on node existence.

Parameters:name (str) – node name
Raises:NodeDoesNotExist – if the given node does not exist.
get_all_paths_between_nodes(node1, node2)[source]

Compute all the simple paths (i.e. with no repeated nodes) between node1 and node2.

Parameters:
  • node1 – name of the starting node
  • node2 – name of the ending node
Returns:

list of paths.

Return type:

list

Note

Each path is given as a tuple of node names from the first to the last one.

get_cpu_port_index(name, quiet=False)[source]

Retrieves the P4 switch’s CPU port number, used for CPU packets.

Parameters:name (str) – name of the P4 switch
Returns:port number of the P4 switch’s CPU interface.
Return type:int

Note

Returns None if no CPU port is found.

get_cpu_port_intf(name, quiet=False)[source]

Retrieves the P4 switch’s CPU interface, used for CPU packets.

Parameters:name (str) – name of the P4 switch
Returns:name of the P4 switch’s CPU interface.
Return type:str

Note

Returns None if no CPU port is found.

get_ctl_cpu_intf(name)[source]

Gets the controller side CPU interface, used to listen for CPU packets.

Parameters:name (str) – name of the P4 switch
Returns:name of the controller side CPU interface.
Return type:str
get_direct_host_networks_from_switch(name)[source]

Gets all the subnetworks a switch can reach directly.

Parameters:name (str) – switch name
Returns:a set of subnetworks.
get_grpc_ip(name)[source]

Retrieves the P4Runtime switch’s IP where it listens for incoming gRPC connections.

Parameters:name (str) – name of the P4Runtime switch
Returns:IP to connect to.
Return type:str
get_grpc_port(name)[source]

Retrieves the P4Runtime switch’s gRPC port number.

Parameters:name (str) – name of the P4Runtime switch
Returns:gRPC port to connect to.
Return type:int
get_host_first_interface(name)[source]

Gets the first interface of a host.

Parameters:name (str) – host name
Returns:interface name.
Return type:str
get_host_gateway_name(name)[source]

Gets host’s gateway.

Parameters:name (str) – host name
Returns:gateway node name.
Return type:str

Warning

This method assumes that the gateway is connected to the host via its first interface.

get_host_ip(name)[source]

Gets host’s IP address.

Parameters:name (str) – host name
Returns:host’s IP address.
Return type:str

Warning

This method assumes that hosts are single-homed (i.e. with only one interface).

get_host_mac(name)[source]

Gets host’s MAC address.

Parameters:name (str) – host name
Returns:host’s MAC address.
Return type:str

Warning

This method assumes that hosts are single-homed (i.e. with only one interface).

get_host_name(ip)[source]

Gets the host name from an IP address.

Parameters:ip – host IP without prefix length
Returns:name of the host whose IP corresponds to the one provided.
Return type:str
Raises:InvalidHostIP – if the IP provided does not match any host.
get_hosts(fields=[])[source]

Retrieves all the hosts and their configuration parameters.

Parameters:fields (list) – optional list of str that specifies which parameters need to be retrieved (and in which order)
Returns:all the hosts configuration parameters if fields is empty, or a dictionary of tuples, where the first one is indexed by host name and the second ones collect the values of the selected parameters in the exact order they are placed in fields.
Return type:dict

Note

If only one element is present in fields, then no tuple is created and the value is directly put in the dictionary.

Example

Let us consider the following example to clarify:

>>> topo = NetworkGraph()
>>> ...
>>> print(topo.get_hosts())
{'h1':{'isHost': True, 'isSwitch': False, ...}, ...}
>>> print(topo.get_hosts(fields=['isHost', 'isSwitch']))
{'h1': (True, False), ...}
>>> print(topo.get_hosts(fields=['isHost']))
{'h1': True, ...}
get_hosts_connected_to(name)[source]

Gets hosts directly connected to a node.

Parameters:name (str) – node name
Returns:list of hosts names.
Return type:list
get_interfaces(name)[source]

Retrieves all the interfaces of a node.

Parameters:name (str) – node name
Returns:list of interfaces names.
Return type:list
get_interfaces_to_node(node)[source]

Gets dictionary that associates every node’s interface to its connected neighbor.

Parameters:name (str) – node name.
Returns:dictionary of node’s neighbors indexed by the corresponding node’s interfaces.
Return type:dict
get_intfs(fields=[])[source]

Retrieves all the interfaces and their configuration parameters using the nodes as indexes.

Parameters:fields (list) – optional list of str that specifies which parameters need to be retrieved (and in which order)
Returns:the attribute edge_to_intf if fields is empty, or a dictionary of dictionaries of tuples, where the first two dictionaries are indexed by node and the tuples contain the values of the specified interface configuration parameters in the exact order they are placed in fields.
Return type:dict

Note

If only one element is present in fields, then no tuple is created and the value is directly put in the inner dictionary.

Example

Let us consider the following example to clarify:

>>> topo = NetworkGraph()
>>> ...
>>> print(topo.get_intfs())
{'h1': {'s2': {'port': 0, 'port_neigh': 1, ...}, ...}, ...}
>>> print(topo.get_intfs(fields=['port', 'port_neigh']))
{'h1': {'s2': (0, 1), ...}, ...}
>>> print(topo.get_intfs(fields=['port']))
{'h1': {'s2': 0, ...}, ...}
get_neighbors(name)[source]

Retrieves the neighbors of a node.

Parameters:name (str) – node name
Returns:list of neighbors names.
Return type:list
get_node_intfs(fields=[])[source]

Retrieves all the interfaces and their configuration parameters using node and interface name as indexes.

Parameters:fields (list) – optional list of str that specifies which parameters need to be retrieved (and in which order)
Returns:the attribute node_to_intf if fields is empty, or a dictionary of dictionaries of tuples, where the first dictionary is indexed by node, the second one by interface name and the tuples contain the values of the specified interface configuration parameters in the exact order they are placed in fields.
Return type:dict

Note

If only one element is present in fields, then no tuple is created and the value is directly put in the inner dictionary.

Example

Let us consider the following example to clarify:

>>> topo = NetworkGraph()
>>> ...
>>> print(topo.get_node_intfs())
{'h1': {'h1-eth0':{'port': 0, 'port_neigh': 1, ...}, ...}, ...}
>>> print(topo.get_node_intfs(fields=['port', 'port_neigh']))
{'h1': {'h1-eth0': (0, 1), ...}, ...}
>>> print(topo.get_node_intfs(fields=['port']))
{'h1': {'h1-eth0': 0, ...}, ...}
get_nodes(fields=[])[source]

Retrieves all the nodes and their configuration parameters.

Parameters:fields (list) – optional list of str that specifies which parameters need to be retrieved (and in which order)
Returns:all the nodes configuration parameters if fields is empty, or a dictionary of tuples, where the first one is indexed by node name and the second ones collect the values of the selected parameters in the exact order they are placed in fields.
Return type:dict

Note

If only one element is present in fields, then no tuple is created and the value is directly put in the dictionary.

Example

Let us consider the following example to clarify:

>>> topo = NetworkGraph()
>>> ...
>>> print(topo.get_nodes())
{'h1':{'isHost': True, 'isSwitch': False, ...}, ...}
>>> print(topo.get_nodes(fields=['isHost', 'isSwitch']))
{'h1': (True, False), ...}
>>> print(topo.get_nodes(fields=['isHost']))
{'h1': True, ...}
get_p4rtswitches(fields=[])[source]

Retrieves all the P4Runtime switches and their configuration parameters.

Parameters:fields (list) – optional list of str that specifies which parameters need to be retrieved (and in which order)
Returns:all the switches configuration parameters if fields is empty, or a dictionary of tuples, where the first one is indexed by switch name and the second ones collect the values of the selected parameters in the exact order they are placed in fields.
Return type:dict

Note

If only one element is present in fields, then no tuple is created and the value is directly put in the dictionary.

Example

Let us consider the following example to clarify:

>>> topo = NetworkGraph()
>>> ...
>>> print(topo.get_p4rtswitches())
{'s1':{'isHost': False, 'isSwitch': True, ...}, ...}
>>> print(topo.get_p4rtswitches(fields=['isHost', 'isSwitch']))
{'s1': (False, True), ...}
>>> print(topo.get_p4rtswitches(fields=['isHost']))
{'s1': False, ...}
get_p4switch_id(name)[source]

Gets the ID of a P4 switch.

Parameters:name (str) – P4 switch name in the topology
Returns:ID of P4 switch as a string
Return type:int
get_p4switches(fields=[])[source]

Retrieves all the P4 switches and their configuration parameters.

Parameters:fields (list) – optional list of str that specifies which parameters need to be retrieved (and in which order)
Returns:all the switches configuration parameters if fields is empty, or a dictionary of tuples, where the first one is indexed by switch name and the second ones collect the values of the selected parameters in the exact order they are placed in fields.
Return type:dict

Note

If only one element is present in fields, then no tuple is created and the value is directly put in the dictionary.

Example

Let us consider the following example to clarify:

>>> topo = NetworkGraph()
>>> ...
>>> print(topo.get_p4switches())
{'s1':{'isHost': False, 'isSwitch': True, ...}, ...}
>>> print(topo.get_p4switches(fields=['isHost', 'isSwitch']))
{'s1': (False, True), ...}
>>> print(topo.get_p4switches(fields=['isHost']))
{'s1': False, ...}
get_p4switches_connected_to(name)[source]

Gets the P4 switches directly connected to a node.

Parameters:name (str) – node name
Returns:list of P4 switch names.
Return type:list
get_routers(fields=[])[source]

Retrieves all the routers and their configuration parameters.

Parameters:fields (list) – optional list of str that specifies which parameters need to be retrieved (and in which order)
Returns:all the routers configuration parameters if fields is empty, or a dictionary of tuples, where the first one is indexed by router name and the second ones collect the values of the selected parameters in the exact order they are placed in fields.
Return type:dict

Note

If only one element is present in fields, then no tuple is created and the value is directly put in the dictionary.

Example

Let us consider the following example to clarify:

>>> topo = NetworkGraph()
>>> ...
>>> print(topo.get_routers())
{'r1':{'isHost': False, 'isRouter': True, ...}, ...}
>>> print(topo.get_routers(fields=['isHost', 'isRouter']))
{'r1': (False, True), ...}
>>> print(topo.get_routers(fields=['isHost']))
{'r1': False, ...}
get_routers_connected_to(name)[source]

Gets the routers directly connected to a node.

Parameters:name (str) – node name
Returns:list of routers.
Return type:list
get_shortest_paths_between_nodes(node1, node2)[source]

Computes all the shortest paths between node1 and node2.

Parameters:
  • node1 – name of the starting node
  • node2 – name of the ending node
Returns:

list of paths.

Return type:

list

Note

Each path is given as a tuple of node names from the first to the last one.

get_switches(fields=[])[source]

Retrieves all the switches and their configuration parameters.

Parameters:fields (list) – optional list of str that specifies which parameters need to be retrieved (and in which order)
Returns:all the switches configuration parameters if fields is empty, or a dictionary of tuples, where the first one is indexed by switch name and the second ones collect the values of the selected parameters in the exact order they are placed in fields.
Return type:dict

Note

If only one element is present in fields, then no tuple is created and the value is directly put in the dictionary.

Example

Let us consider the following example to clarify:

>>> topo = NetworkGraph()
>>> ...
>>> print(topo.get_switches())
{'s1':{'isHost': False, 'isSwitch': True, ...}, ...}
>>> print(topo.get_switches(fields=['isHost', 'isSwitch']))
{'s1': (False, True), ...}
>>> print(topo.get_switches(fields=['isHost']))
{'s1': False, ...}
get_switches_connected_to(name)[source]

Gets switches directly connected to a node.

Parameters:name (str) – node name
Returns:list of switch names.
Return type:list
get_thrift_ip(name)[source]

Retrieves the P4 switch’s IP where it listens for incoming Thrift connections.

Parameters:name (str) – name of the P4 switch
Returns:IP to connect to.
Return type:str
get_thrift_port(name)[source]

Retrieves the P4 switch’s Thrift port number.

Parameters:name (str) – name of the P4 switch
Returns:Thrift port to connect to.
Return type:int
interface_to_node(node, intf)[source]

Gets name of the node’s neighbor attached to the specified interface.

Parameters:
  • node (str) – node name
  • intf (str) – interface name
Returns:

neighbor name.

Return type:

str

interface_to_port(node, intf)[source]

Gets port number of the the specified interface of a node.

Parameters:
  • node (str) – node name
  • intf (str) – interface name
Returns:

port number.

Return type:

int

isHost(name)[source]

Checks if a node is a host.

Parameters:name (str) – node name
Returns:True if the node is a host, False otherwise.
Return type:bool
isIntf(node1, node2)[source]

Checks if the interface between node1 and node2 exists.

Parameters:
  • node1 (str) – name of the first node
  • node2 (str) – name of the second node
Returns:

True if the interface exists, False otherwise.

Return type:

bool

isNode(name)[source]

Checks if the node exists.

Parameters:name (str) – node name
Returns:True if the node exists, False otherwise.
Return type:bool
isP4RuntimeSwitch(name)[source]

Checks if a node is a P4Runtime switch.

Parameters:name (str) – node name
Returns:True if the node is a P4Runtime switch, False otherwise.
Return type:bool
isP4Switch(name)[source]

Checks if a node is a P4 switch.

Parameters:name (str) – node name
Returns:True if the node is a P4 switch, False otherwise.
Return type:bool
isRouter(name)[source]

Checks if a node is a router.

Parameters:name (str) – node name
Returns:True if the node is a router switch, False otherwise.
Return type:bool
isSwitch(name)[source]

Checks if a node is a switch.

Parameters:name (str) – node name
Returns:True if the node is a switch, False otherwise.
Return type:bool
isType(name, node_type)[source]

Checks custom node type.

Parameters:
  • name (str) – node name
  • node_type (str) – type to check

Possible node_type values are the following:

  • host
  • switch
  • p4switch
  • p4rtswitch
  • router
Returns:True if the node type matches with node_type, False otherwise.
Return type:bool
keep_only_p4switches()[source]

Returns a networkx subgraph including only P4 switches.

keep_only_p4switches_and_hosts()[source]

Returns a networkx subgraph including only hosts and P4 switches.

keep_only_switches()[source]

Returns a networkx subgraph including only switches.

node_interface_bw(node, intf)[source]

Gets the bandwidth of a give node’s interface.

Parameters:
  • node (str) – node name
  • intf (str) – interface name
Returns:

bandwidth capacity of the interface in Mbps.

Return type:

int

Note

If the bandwidth is unlimited, this method returns -1.

node_interface_ip(node, intf)[source]

Gets the IP address a given node’s interface.

Parameters:
  • node (str) – node name
  • intf (str) – interface name
Returns:

IP address of the interface

Return type:

str

node_to_node_interface_bw(node1, node2)[source]

Gets the bandwidth of the interface of node1 facing node2.

Parameters:
  • node1 (str) – name of the first node
  • node2 (str) – name of the second node
Returns:

bandwidth capacity of the interface in Mbps.

Return type:

int

Note

If the bandwidth is unlimited, this method returns -1.

node_to_node_interface_ip(node1, node2)[source]

Gets the IP address and the subnet mask of the interface of node1 facing node2.

Parameters:
  • node1 (str) – name of the first node
  • node2 (str) – name of the second node
Returns:

IP / subnet mask of the interface.

Return type:

str

node_to_node_mac(node1, node2)[source]

Gets the MAC address of the interface of node1 connected to node2.

Parameters:
  • node1 (str) – name of the first node
  • node2 (str) – name of the second node
Returns:

MAC address.

Return type:

str

node_to_node_port_num(node1, node2)[source]

Gets the number of the port of node1 that is connected to node2.

Parameters:
  • node1 (str) – name of the first node
  • node2 (str) – name of the second node
Returns:

port number.

Return type:

int

port_to_node(node, port)[source]

Gets the neighboring node of node connected to port.

Parameters:
  • node (str) – name of the first node
  • port (int) – port number
Returns:

neighbor node.

Return type:

str

set_node_color(node, color)[source]

Sets node’s color. Used when plotting the network.

Parameters:
  • name (str) – node name
  • shape – color to assign
set_node_shape(node, shape)[source]

Sets node’s shape. Used when plotting the network.

Parameters:
  • name (str) – node name
  • shape – shape to assign
set_node_type_color(node_type, color)[source]

Sets the color of the nodes filtered by type. Used when plotting the network.

Parameters:
  • node_type (str) – node type to select
  • color – color to assign to nodes

Possible values for node_types are the following:

  • host
  • switch
  • p4switch
  • p4rtswitch
  • router
set_node_type_shape(node_type, shape)[source]

Sets the shape of the nodes filtered by type. Used when plotting the network.

Parameters:
  • node_type (str) – node type to select
  • shape – shape to assign to nodes

Possible values for node_types are the following:

  • host
  • switch
  • p4switch
  • p4rtswitch
  • router
subnet(node1, node2)[source]

Gets the subnet of the link between node1 and node2.

Parameters:
  • node1 (str) – name of the first node
  • node2 (str) – name of the second node
Returns:

the subnet in CIDR notation.

Return type:

str

total_number_of_paths()[source]

Computes the total number of shortest paths between all host pairs in the network.

Returns:number of paths.
Return type:int
exception p4utils.utils.topology.NodeDoesNotExist(node)[source]

Bases: Exception

Exception raised when a node is not found.