Commit 1a64d22c authored by Pedro Oliveira's avatar Pedro Oliveira

Add command to list instances && fix issue of -mvr and -uvrf being mutually...

Add command to list instances && fix issue of -mvr and -uvrf being mutually exclusive && fix state refresh deadlock && include originator state on -ls
parent 4f60a67a
...@@ -46,7 +46,7 @@ In order to start the protocol you first need to explicitly start it. This will ...@@ -46,7 +46,7 @@ In order to start the protocol you first need to explicitly start it. This will
IPv4 and IPv6 multicast is supported. By default all commands will be executed on IPv4 daemon. To execute a command on the IPv6 daemon use `-6`. IPv4 and IPv6 multicast is supported. By default all commands will be executed on IPv4 daemon. To execute a command on the IPv6 daemon use `-6`.
We support multiple tables. Each daemon process will be bind to a given multicast and unicast table id, with can be defined at startup with `-mvrf` and `-uvrf`. We support multiple tables. Each daemon process will be bind to a given multicast and unicast table id, which can be defined at startup with `-mvrf` and `-uvrf`.
If `-mvrf` is not defined, the default multicast table id will be used (table id 0). If `-mvrf` is not defined, the default multicast table id will be used (table id 0).
......
...@@ -228,15 +228,14 @@ class InterfacePim(Interface): ...@@ -228,15 +228,14 @@ class InterfacePim(Interface):
""" """
Check StateRefresh capability of interface neighbors Check StateRefresh capability of interface neighbors
""" """
with self.neighbors_lock.genWlock(): if len(self.neighbors) == 0:
if len(self.neighbors) == 0: return False
return False
state_refresh_capable = True state_refresh_capable = True
for neighbor in list(self.neighbors.values()): for neighbor in list(self.neighbors.values()):
state_refresh_capable &= neighbor.state_refresh_capable state_refresh_capable &= neighbor.state_refresh_capable
return state_refresh_capable return state_refresh_capable
''' '''
def change_interface(self): def change_interface(self):
......
...@@ -4,6 +4,7 @@ import netifaces ...@@ -4,6 +4,7 @@ import netifaces
import logging import logging
import logging.handlers import logging.handlers
from prettytable import PrettyTable from prettytable import PrettyTable
from pimdm.tree import pim_globals
from pimdm import UnicastRouting from pimdm import UnicastRouting
from pimdm.TestLogger import RootFilter from pimdm.TestLogger import RootFilter
...@@ -158,7 +159,7 @@ def list_routing_state(ipv4=False, ipv6=False): ...@@ -158,7 +159,7 @@ def list_routing_state(ipv4=False, ipv6=False):
for b in list(a.values()): for b in list(a.values()):
routing_entries.append(b) routing_entries.append(b)
t = PrettyTable(['SourceIP', 'GroupIP', 'Interface', 'PruneState', 'AssertState', 'LocalMembership', "Is Forwarding?"]) t = PrettyTable(['SourceIP', 'GroupIP', 'Interface', 'OriginatorState', 'PruneState', 'AssertState', 'LocalMembership', "Is Forwarding?"])
for entry in routing_entries: for entry in routing_entries:
ip = entry.source_ip ip = entry.source_ip
group = entry.group_ip group = entry.group_ip
...@@ -172,16 +173,29 @@ def list_routing_state(ipv4=False, ipv6=False): ...@@ -172,16 +173,29 @@ def list_routing_state(ipv4=False, ipv6=False):
assert_state = type(interface_state._assert_state).__name__ assert_state = type(interface_state._assert_state).__name__
if index != upstream_if_index: if index != upstream_if_index:
prune_state = type(interface_state._prune_state).__name__ prune_state = type(interface_state._prune_state).__name__
originator_state = "-"
is_forwarding = interface_state.is_forwarding() is_forwarding = interface_state.is_forwarding()
else: else:
prune_state = type(interface_state._graft_prune_state).__name__ prune_state = type(interface_state._graft_prune_state).__name__
is_forwarding = "upstream" is_forwarding = "upstream"
originator_state = type(interface_state._originator_state).__name__
except: except:
originator_state = "-"
prune_state = "-" prune_state = "-"
assert_state = "-" assert_state = "-"
is_forwarding = "-" is_forwarding = "-"
t.add_row([ip, group, interface_name, prune_state, assert_state, local_membership, is_forwarding]) t.add_row([ip, group, interface_name, originator_state, prune_state, assert_state, local_membership, is_forwarding])
return str(t)
def list_instances():
"""
List instance information
"""
t = PrettyTable(['Instance PID', 'Multicast VRF', 'Unicast VRF'])
import os
t.add_row([os.getpid(), pim_globals.MULTICAST_TABLE_ID, pim_globals.UNICAST_TABLE_ID])
return str(t) return str(t)
......
...@@ -2,19 +2,21 @@ ...@@ -2,19 +2,21 @@
import os import os
import sys import sys
import glob
import socket import socket
import argparse import argparse
import traceback import traceback
import _pickle as pickle import _pickle as pickle
from prettytable import PrettyTable
from pimdm import Main from pimdm import Main
from pimdm.tree import pim_globals from pimdm.tree import pim_globals
from pimdm.daemon.Daemon import Daemon from pimdm.daemon.Daemon import Daemon
VERSION = "1.1.1.2" VERSION = "1.1.1.3"
def client_socket(data_to_send): def client_socket(data_to_send, print_output=True):
# Create a UDS socket # Create a UDS socket
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
...@@ -26,7 +28,10 @@ def client_socket(data_to_send): ...@@ -26,7 +28,10 @@ def client_socket(data_to_send):
sock.sendall(pickle.dumps(data_to_send)) sock.sendall(pickle.dumps(data_to_send))
data_rcv = sock.recv(1024 * 256) data_rcv = sock.recv(1024 * 256)
if data_rcv: if data_rcv:
print(pickle.loads(data_rcv)) if print_output:
print(pickle.loads(data_rcv))
else:
return pickle.loads(data_rcv)
except socket.error: except socket.error:
pass pass
finally: finally:
...@@ -92,6 +97,8 @@ class MyDaemon(Daemon): ...@@ -92,6 +97,8 @@ class MyDaemon(Daemon):
elif 'remove_interface_mld' in args and args.remove_interface_mld: elif 'remove_interface_mld' in args and args.remove_interface_mld:
Main.remove_interface(args.remove_interface_mld[0], membership=True, ipv4=False, ipv6=True) Main.remove_interface(args.remove_interface_mld[0], membership=True, ipv4=False, ipv6=True)
connection.shutdown(socket.SHUT_RDWR) connection.shutdown(socket.SHUT_RDWR)
elif 'list_instances' in args and args.list_instances:
connection.sendall(pickle.dumps(Main.list_instances()))
elif 'stop' in args and args.stop: elif 'stop' in args and args.stop:
Main.stop() Main.stop()
connection.shutdown(socket.SHUT_RDWR) connection.shutdown(socket.SHUT_RDWR)
...@@ -121,6 +128,8 @@ def main(): ...@@ -121,6 +128,8 @@ def main():
"Use -4 or -6 to specify IPv4 or IPv6 PIM neighbors.") "Use -4 or -6 to specify IPv4 or IPv6 PIM neighbors.")
group.add_argument("-ls", "--list_state", action="store_true", default=False, help="List IGMP/MLD and PIM-DM state machines." group.add_argument("-ls", "--list_state", action="store_true", default=False, help="List IGMP/MLD and PIM-DM state machines."
" Use -4 or -6 to specify IPv4 or IPv6 state respectively.") " Use -4 or -6 to specify IPv4 or IPv6 state respectively.")
group.add_argument("-instances", "--list_instances", action="store_true", default=False,
help="List running PIM-DM daemon processes.")
group.add_argument("-mr", "--multicast_routes", action="store_true", default=False, help="List Multicast Routing table. " group.add_argument("-mr", "--multicast_routes", action="store_true", default=False, help="List Multicast Routing table. "
"Use -4 or -6 to specify IPv4 or IPv6 multicast routing table.") "Use -4 or -6 to specify IPv4 or IPv6 multicast routing table.")
group.add_argument("-ai", "--add_interface", nargs=1, metavar='INTERFACE_NAME', help="Add PIM interface. " group.add_argument("-ai", "--add_interface", nargs=1, metavar='INTERFACE_NAME', help="Add PIM interface. "
...@@ -139,7 +148,7 @@ def main(): ...@@ -139,7 +148,7 @@ def main():
group_ipversion = parser.add_mutually_exclusive_group(required=False) group_ipversion = parser.add_mutually_exclusive_group(required=False)
group_ipversion.add_argument("-4", "--ipv4", action="store_true", default=False, help="Setting for IPv4") group_ipversion.add_argument("-4", "--ipv4", action="store_true", default=False, help="Setting for IPv4")
group_ipversion.add_argument("-6", "--ipv6", action="store_true", default=False, help="Setting for IPv6") group_ipversion.add_argument("-6", "--ipv6", action="store_true", default=False, help="Setting for IPv6")
group_vrf = parser.add_mutually_exclusive_group(required=False) group_vrf = parser.add_argument_group()
group_vrf.add_argument("-mvrf", "--multicast_vrf", nargs=1, default=[pim_globals.MULTICAST_TABLE_ID], group_vrf.add_argument("-mvrf", "--multicast_vrf", nargs=1, default=[pim_globals.MULTICAST_TABLE_ID],
metavar='MULTICAST_VRF_NUMBER', type=int, metavar='MULTICAST_VRF_NUMBER', type=int,
help="Define multicast table id. This can be used on -start to explicitly start the daemon" help="Define multicast table id. This can be used on -start to explicitly start the daemon"
...@@ -157,6 +166,21 @@ def main(): ...@@ -157,6 +166,21 @@ def main():
if os.geteuid() != 0: if os.geteuid() != 0:
sys.exit('PIM-DM must be run as root!') sys.exit('PIM-DM must be run as root!')
if args.list_instances:
pid_files = glob.glob("/tmp/Daemon-pim*.pid")
t = PrettyTable(['Instance PID', 'Multicast VRF', 'Unicast VRF'])
for pid_file in pid_files:
d = MyDaemon(pid_file)
pim_globals.MULTICAST_TABLE_ID = pid_file[15:-4]
if not d.is_running():
continue
t_new = client_socket(args, print_output=False)
t.add_row(t_new.replace(" ", "").split("\n")[3].split("|")[1:4])
print(t)
return
pim_globals.MULTICAST_TABLE_ID = args.multicast_vrf[0] pim_globals.MULTICAST_TABLE_ID = args.multicast_vrf[0]
pim_globals.UNICAST_TABLE_ID = args.unicast_vrf[0] pim_globals.UNICAST_TABLE_ID = args.unicast_vrf[0]
......
...@@ -149,7 +149,7 @@ class KernelEntry: ...@@ -149,7 +149,7 @@ class KernelEntry:
return return
# refresh limit # refresh limit
timestamp = time() timestamp = time()
if (timestamp - self.timestamp_of_last_state_refresh_message_received) < interval: if (timestamp - self.timestamp_of_last_state_refresh_message_received) < interval - 5:
return return
self.timestamp_of_last_state_refresh_message_received = timestamp self.timestamp_of_last_state_refresh_message_received = timestamp
if ttl == 0: if ttl == 0:
......
...@@ -114,6 +114,7 @@ class TreeInterfaceDownstream(TreeInterface): ...@@ -114,6 +114,7 @@ class TreeInterfaceDownstream(TreeInterface):
# Send messages # Send messages
###################################### ######################################
def send_state_refresh(self, state_refresh_msg_received): def send_state_refresh(self, state_refresh_msg_received):
print("send state refresh")
if state_refresh_msg_received is None: if state_refresh_msg_received is None:
return return
......
...@@ -13,7 +13,7 @@ setup( ...@@ -13,7 +13,7 @@ setup(
long_description=open("README.md", "r").read(), long_description=open("README.md", "r").read(),
long_description_content_type="text/markdown", long_description_content_type="text/markdown",
keywords="PIM-DM Multicast Routing Protocol PIM Dense-Mode Router RFC3973 IPv4 IPv6", keywords="PIM-DM Multicast Routing Protocol PIM Dense-Mode Router RFC3973 IPv4 IPv6",
version="1.1.1.2", version="1.1.1.3",
url="http://github.com/pedrofran12/pim_dm", url="http://github.com/pedrofran12/pim_dm",
author="Pedro Oliveira", author="Pedro Oliveira",
author_email="pedro.francisco.oliveira@tecnico.ulisboa.pt", author_email="pedro.francisco.oliveira@tecnico.ulisboa.pt",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment