diff --git a/README.md b/README.md index d5ed5e2..9c35827 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,20 @@ If `-uvrf` is not defined, the default unicast table id will be used (table id 2 After starting the protocol process, if the default multicast table is not used, the following commands (for adding interfaces and listing state) need to have the argument `-mvrf` defined to specify the corresponding daemon process. + +#### Multi daemon support + +Multiple daemons are supported, each bind to a given multicast routing table id. + +To perform configurations on one of these daemons use `-mvrf` command and define the daemon by its multicast table id. + + +To see all daemons that are currently running: + + ``` + sudo pim-dm -instances + ``` + #### Add interface After starting the protocol process you can enable the protocol in specific interfaces. You need to specify which interfaces will have IGMP enabled and which interfaces will have PIM-DM enabled. @@ -149,18 +163,33 @@ We have built some list commands that can be used to check the "internals" of th sudo pim-dm -mr [-4 | -6] [-mvrf MULTICAST_TABLE_ID] ``` +## Config File -## Help command -In order to determine which commands and corresponding arguments are available you can call the help command: +It is possible to configure the protocol using a YAML file. This configuration file can be used to set all interfaces that will have PIM-DM/IGMP/MLD enabled, as well to fine tune these protocols by setting their timers. Currently the settings are shared by all interfaces. In a future release it will be possible to set timers per interface. + +To use this feature you need to manually install PyYaml. PyYaml is not automatically installed with `pim-dm` to support older Python versions (as of now PyYaml requires at least Python v3.5). + +[This YAML file](https://github.com/pedrofran12/pim_dm/tree/master/config/config_example.yml) is a configuration file example. + +It it also possible to get an YAML configuration file from the current settings of the daemon. This will output an YAML template that can be used later for enabling the daemon with the same settings (enabled interfaces and timers). The command for this matter is the following: ``` - pim-dm -h + sudo pim-dm -get_config [-mvrf MULTICAST_TABLE_ID] + ``` + +To input an YAML configuration file to the daemon: + + ``` + sudo pim-dm -config CONFIGURATION_FILE_PATH ``` -## Change settings +## Help command +In order to determine which commands and corresponding arguments are available you can call the help command: -Files tree/pim_globals.py, igmp/igmp_globals.py and mld/mld_globals.py store all timer values and some configurations regarding PIM-DM, IGMP and MLD. If you want to tune the implementation, you can change the values of these files. These configurations are used by all interfaces, meaning that there is no tuning per interface. + ``` + pim-dm -h + ``` ## Tests diff --git a/config/config_example.yml b/config/config_example.yml new file mode 100644 index 0000000..d037dfa --- /dev/null +++ b/config/config_example.yml @@ -0,0 +1,72 @@ +MulticastVRF: 0 +UnicastVRF: 254 + +PIM-DM: + DefaultTimers: + ASSERT_TIME: 180 + GRAFT_RETRY_PERIOD: 3 + JP_OVERRIDE_INTERVAL: 3.0 + OVERRIDE_INTERVAL: 2.5 + PROPAGATION_DELAY: 0.5 + REFRESH_INTERVAL: 60 + SOURCE_LIFETIME: 210 + T_LIMIT: 210 + Interfaces: + eth0: + ipv4: + enabled: true + ipv6: + enabled: true + eth1: + ipv4: + enabled: true + ipv6: + enabled: true + eth2: + ipv4: + enabled: true + ipv6: + enabled: true + +IGMP: + Settings: + GROUP_MEMBERSHIP_INTERVAL: 260 + LAST_MEMBER_QUERY_COUNT: 2 + LAST_MEMBER_QUERY_INTERVAL: 1 + MAX_RESPONSE_TIME_LAST_MEMBER_QUERY_INTERVAL: 10 + MAX_RESPONSE_TIME_QUERY_RESPONSE_INTERVAL: 100 + OTHER_QUERIER_PRESENT_INTERVAL: 255.0 + QUERY_INTERVAL: 125 + QUERY_RESPONSE_INTERVAL: 10 + ROBUSTNESS_VARIABLE: 2 + STARTUP_QUERY_COUNT: 2 + STARTUP_QUERY_INTERVAL: 31.25 + UNSOLICITED_REPORT_INTERVAL: 10 + VERSION_1_ROUTER_PRESENT_TIMEOUT: 400 + Interfaces: + eth0: + enabled: true + eth1: + enabled: true + eth2: + enabled: true + +MLD: + Settings: + LAST_LISTENER_QUERY_COUNT: 2 + LAST_LISTENER_QUERY_INTERVAL: 1 + MULTICAST_LISTENER_INTERVAL: 260 + OTHER_QUERIER_PRESENT_INTERVAL: 255.0 + QUERY_INTERVAL: 125 + QUERY_RESPONSE_INTERVAL: 10 + ROBUSTNESS_VARIABLE: 2 + STARTUP_QUERY_COUNT: 2 + STARTUP_QUERY_INTERVAL: 31.25 + UNSOLICITED_REPORT_INTERVAL: 10 + Interfaces: + eth0: + enabled: true + eth1: + enabled: true + eth2: + enabled: true diff --git a/pimdm/Config.py b/pimdm/Config.py new file mode 100644 index 0000000..0e96947 --- /dev/null +++ b/pimdm/Config.py @@ -0,0 +1,186 @@ +import yaml +from pimdm.tree import pim_globals +from pimdm.igmp import igmp_globals +from pimdm.mld import mld_globals +from pimdm import Main + + +def parse_config_file(file_path): + """ + Parse yaml file and set everything on protocol process accordingly + """ + with open(file_path) as f: + data = yaml.load(f, Loader=yaml.FullLoader) + print(data) + + print(type(data.get("UnicastVRF", 254))) + + multicast_vrf = data.get("MulticastVRF", 0) + pim_globals.MULTICAST_TABLE_ID = multicast_vrf + pim_globals.UNICAST_TABLE_ID = data.get("UnicastVRF", 254) + pim_config = data.get("PIM-DM", {}) + igmp_config = data.get("IGMP", {}) + mld_config = data.get("MLD", {}) + + ##### PIM config ###### + if "DefaultTimers" in pim_config: + pim_globals.ASSERT_TIME = pim_config["DefaultTimers"].get("ASSERT_TIME", pim_globals.ASSERT_TIME) + pim_globals.GRAFT_RETRY_PERIOD = pim_config["DefaultTimers"].get("GRAFT_RETRY_PERIOD", pim_globals.GRAFT_RETRY_PERIOD) + pim_globals.JP_OVERRIDE_INTERVAL = pim_config["DefaultTimers"].get("JP_OVERRIDE_INTERVAL", pim_globals.JP_OVERRIDE_INTERVAL) + pim_globals.OVERRIDE_INTERVAL = pim_config["DefaultTimers"].get("OVERRIDE_INTERVAL", pim_globals.OVERRIDE_INTERVAL) + pim_globals.PROPAGATION_DELAY = pim_config["DefaultTimers"].get("PROPAGATION_DELAY", pim_globals.PROPAGATION_DELAY) + pim_globals.REFRESH_INTERVAL = pim_config["DefaultTimers"].get("REFRESH_INTERVAL", pim_globals.REFRESH_INTERVAL) + pim_globals.SOURCE_LIFETIME = pim_config["DefaultTimers"].get("SOURCE_LIFETIME", pim_globals.SOURCE_LIFETIME) + pim_globals.T_LIMIT = pim_config["DefaultTimers"].get("T_LIMIT", pim_globals.T_LIMIT) + + if "Interfaces" in pim_config: + interfaces = pim_config["Interfaces"] # type: dict + + for if_name, if_value in interfaces.items(): + if if_value.get("ipv4", False): + if_ipv4 = if_value["ipv4"] + if if_ipv4.get("enabled", False): + Main.add_pim_interface(interface_name=if_name, ipv4=True, ipv6=False) + + if if_value.get("ipv6", False): + if_ipv6 = if_value["ipv6"] + if if_ipv6.get("enabled", False): + Main.add_pim_interface(interface_name=if_name, ipv4=False, ipv6=True) + + + ##### IGMP config ####### + if "Settings" in igmp_config: + igmp_globals.ROBUSTNESS_VARIABLE = igmp_config["Settings"].get("ROBUSTNESS_VARIABLE", igmp_globals.ROBUSTNESS_VARIABLE) + igmp_globals.QUERY_INTERVAL = igmp_config["Settings"].get("QUERY_INTERVAL", igmp_globals.QUERY_INTERVAL) + igmp_globals.QUERY_RESPONSE_INTERVAL = igmp_config["Settings"].get("QUERY_RESPONSE_INTERVAL", igmp_globals.QUERY_RESPONSE_INTERVAL) + igmp_globals.MAX_RESPONSE_TIME_QUERY_RESPONSE_INTERVAL = igmp_config["Settings"].get("MAX_RESPONSE_TIME_QUERY_RESPONSE_INTERVAL", igmp_globals.QUERY_RESPONSE_INTERVAL*10) + igmp_globals.GROUP_MEMBERSHIP_INTERVAL = igmp_config["Settings"].get("GROUP_MEMBERSHIP_INTERVAL", igmp_globals.ROBUSTNESS_VARIABLE * igmp_globals.QUERY_INTERVAL + igmp_globals.QUERY_RESPONSE_INTERVAL) + igmp_globals.OTHER_QUERIER_PRESENT_INTERVAL = igmp_config["Settings"].get("OTHER_QUERIER_PRESENT_INTERVAL", igmp_globals.ROBUSTNESS_VARIABLE * igmp_globals.QUERY_INTERVAL + igmp_globals.QUERY_RESPONSE_INTERVAL / 2) + igmp_globals.STARTUP_QUERY_INTERVAL = igmp_config["Settings"].get("STARTUP_QUERY_INTERVAL", igmp_globals.QUERY_INTERVAL / 4) + igmp_globals.STARTUP_QUERY_COUNT = igmp_config["Settings"].get("STARTUP_QUERY_COUNT", igmp_globals.ROBUSTNESS_VARIABLE) + igmp_globals.LAST_MEMBER_QUERY_INTERVAL = igmp_config["Settings"].get("LAST_MEMBER_QUERY_INTERVAL", igmp_globals.LAST_MEMBER_QUERY_INTERVAL) + igmp_globals.MAX_RESPONSE_TIME_LAST_MEMBER_QUERY_INTERVAL = igmp_config["Settings"].get("LAST_MEMBER_QUERY_COUNT", igmp_globals.LAST_MEMBER_QUERY_INTERVAL * 10) + igmp_globals.LAST_MEMBER_QUERY_COUNT = igmp_config["Settings"].get("LAST_MEMBER_QUERY_COUNT", igmp_globals.ROBUSTNESS_VARIABLE) + igmp_globals.UNSOLICITED_REPORT_INTERVAL = igmp_config["Settings"].get("UNSOLICITED_REPORT_INTERVAL", igmp_globals.UNSOLICITED_REPORT_INTERVAL) + igmp_globals.VERSION_1_ROUTER_PRESENT_TIMEOUT = igmp_config["Settings"].get("VERSION_1_ROUTER_PRESENT_TIMEOUT", igmp_globals.VERSION_1_ROUTER_PRESENT_TIMEOUT) + + if "Interfaces" in igmp_config: + interfaces = igmp_config["Interfaces"] # type: dict + + for if_name, if_value in interfaces.items(): + if if_value.get("enabled", False): + Main.add_membership_interface(interface_name=if_name, ipv4=True, ipv6=False) + + ##### MLD config ####### + if "Settings" in mld_config: + mld_globals.ROBUSTNESS_VARIABLE = mld_config["Settings"].get("ROBUSTNESS_VARIABLE", mld_globals.ROBUSTNESS_VARIABLE) + mld_globals.QUERY_INTERVAL = mld_config["Settings"].get("QUERY_INTERVAL", mld_globals.QUERY_INTERVAL) + mld_globals.QUERY_RESPONSE_INTERVAL = mld_config["Settings"].get("QUERY_RESPONSE_INTERVAL", mld_globals.QUERY_RESPONSE_INTERVAL) + mld_globals.MULTICAST_LISTENER_INTERVAL = mld_config["Settings"].get("MULTICAST_LISTENER_INTERVAL", (mld_globals.ROBUSTNESS_VARIABLE * mld_globals.QUERY_INTERVAL) + (mld_globals.QUERY_RESPONSE_INTERVAL)) + mld_globals.OTHER_QUERIER_PRESENT_INTERVAL = mld_config["Settings"].get("OTHER_QUERIER_PRESENT_INTERVAL", (mld_globals.ROBUSTNESS_VARIABLE * mld_globals.QUERY_INTERVAL) + 0.5 * mld_globals.QUERY_RESPONSE_INTERVAL) + mld_globals.STARTUP_QUERY_INTERVAL = mld_config["Settings"].get("STARTUP_QUERY_INTERVAL", (1 / 4) * mld_globals.QUERY_INTERVAL) + mld_globals.STARTUP_QUERY_COUNT = mld_config["Settings"].get("STARTUP_QUERY_COUNT", mld_globals.ROBUSTNESS_VARIABLE) + mld_globals.LAST_LISTENER_QUERY_INTERVAL = mld_config["Settings"].get("LAST_LISTENER_QUERY_INTERVAL", mld_globals.LAST_LISTENER_QUERY_INTERVAL) + mld_globals.LAST_LISTENER_QUERY_COUNT = mld_config["Settings"].get("LAST_LISTENER_QUERY_COUNT", mld_globals.ROBUSTNESS_VARIABLE) + mld_globals.UNSOLICITED_REPORT_INTERVAL = mld_config["Settings"].get("UNSOLICITED_REPORT_INTERVAL", mld_globals.UNSOLICITED_REPORT_INTERVAL) + + if "Interfaces" in mld_config: + interfaces = mld_config["Interfaces"] # type: dict + + for if_name, if_value in interfaces.items(): + if if_value.get("enabled", False): + Main.add_membership_interface(interface_name=if_name, ipv4=False, ipv6=True) + + +def get_yaml_file(): + """ + Get configuration file from live protocol process + """ + dict_file = { + 'MulticastVRF': pim_globals.MULTICAST_TABLE_ID, + 'UnicastVRF': pim_globals.UNICAST_TABLE_ID, + 'PIM-DM': { + "DefaultTimers": { + "ASSERT_TIME": pim_globals.ASSERT_TIME, + "GRAFT_RETRY_PERIOD": pim_globals.GRAFT_RETRY_PERIOD, + "JP_OVERRIDE_INTERVAL": pim_globals.JP_OVERRIDE_INTERVAL, + "OVERRIDE_INTERVAL": pim_globals.OVERRIDE_INTERVAL, + "PROPAGATION_DELAY": pim_globals.PROPAGATION_DELAY, + "REFRESH_INTERVAL": pim_globals.REFRESH_INTERVAL, + "SOURCE_LIFETIME": pim_globals.SOURCE_LIFETIME, + "T_LIMIT": pim_globals.T_LIMIT, + }, + "Interfaces": {}, + }, + 'IGMP': { + "Settings": { + "ROBUSTNESS_VARIABLE": igmp_globals.ROBUSTNESS_VARIABLE, + "QUERY_INTERVAL": igmp_globals.QUERY_INTERVAL, + "QUERY_RESPONSE_INTERVAL": igmp_globals.QUERY_RESPONSE_INTERVAL, + "MAX_RESPONSE_TIME_QUERY_RESPONSE_INTERVAL": igmp_globals.MAX_RESPONSE_TIME_QUERY_RESPONSE_INTERVAL, + "GROUP_MEMBERSHIP_INTERVAL": igmp_globals.GROUP_MEMBERSHIP_INTERVAL, + "OTHER_QUERIER_PRESENT_INTERVAL": igmp_globals.OTHER_QUERIER_PRESENT_INTERVAL, + "STARTUP_QUERY_INTERVAL": igmp_globals.STARTUP_QUERY_INTERVAL, + "STARTUP_QUERY_COUNT": igmp_globals.STARTUP_QUERY_COUNT, + "LAST_MEMBER_QUERY_INTERVAL": igmp_globals.LAST_MEMBER_QUERY_INTERVAL, + "MAX_RESPONSE_TIME_LAST_MEMBER_QUERY_INTERVAL": igmp_globals.MAX_RESPONSE_TIME_LAST_MEMBER_QUERY_INTERVAL, + "LAST_MEMBER_QUERY_COUNT": igmp_globals.LAST_MEMBER_QUERY_COUNT, + "UNSOLICITED_REPORT_INTERVAL": igmp_globals.UNSOLICITED_REPORT_INTERVAL, + "VERSION_1_ROUTER_PRESENT_TIMEOUT": igmp_globals.VERSION_1_ROUTER_PRESENT_TIMEOUT, + }, + "Interfaces": {}, + }, + 'MLD': { + "Settings": { + "ROBUSTNESS_VARIABLE": mld_globals.ROBUSTNESS_VARIABLE, + "QUERY_INTERVAL": mld_globals.QUERY_INTERVAL, + "QUERY_RESPONSE_INTERVAL": mld_globals.QUERY_RESPONSE_INTERVAL, + "MULTICAST_LISTENER_INTERVAL": mld_globals.MULTICAST_LISTENER_INTERVAL, + "OTHER_QUERIER_PRESENT_INTERVAL": mld_globals.OTHER_QUERIER_PRESENT_INTERVAL, + "STARTUP_QUERY_INTERVAL": mld_globals.STARTUP_QUERY_INTERVAL, + "STARTUP_QUERY_COUNT": mld_globals.STARTUP_QUERY_COUNT, + "LAST_LISTENER_QUERY_INTERVAL": mld_globals.LAST_LISTENER_QUERY_INTERVAL, + "LAST_LISTENER_QUERY_COUNT": mld_globals.LAST_LISTENER_QUERY_COUNT, + "UNSOLICITED_REPORT_INTERVAL": mld_globals.UNSOLICITED_REPORT_INTERVAL, + }, + "Interfaces": {}, + } + } + + for if_name, if_value in Main.interfaces.items(): + dict_file["PIM-DM"]["Interfaces"][if_name] = {} + dict_file["PIM-DM"]["Interfaces"][if_name]["ipv4"] = { + "enabled": True, + } + + for if_name, if_value in Main.interfaces_v6.items(): + if if_name not in dict_file["PIM-DM"]["Interfaces"]: + dict_file["PIM-DM"]["Interfaces"][if_name] = {} + + dict_file["PIM-DM"]["Interfaces"][if_name]["ipv6"] = { + "enabled": True, + } + + for if_name in Main.igmp_interfaces.keys(): + dict_file["IGMP"]["Interfaces"][if_name] = { + "enabled": True, + } + + for if_name in Main.mld_interfaces.keys(): + dict_file["MLD"]["Interfaces"][if_name] = { + "enabled": True, + } + + return yaml.dump(dict_file) + + +def get_vrfs(file_path): + """ + Get vrf configuration from yaml file. + This is only used by Run.py to create the correct daemons accordingly (daemons are bound to specific VRFs). + """ + with open(file_path) as f: + data = yaml.load(f, Loader=yaml.FullLoader) + multicast_vrf = data.get("MulticastVRF", 0) + unicast_vrf = data.get("UnicastVRF", 254) + return [multicast_vrf, unicast_vrf] diff --git a/pimdm/InterfacePIM.py b/pimdm/InterfacePIM.py index 439f137..7c5472a 100644 --- a/pimdm/InterfacePIM.py +++ b/pimdm/InterfacePIM.py @@ -78,6 +78,8 @@ def __init__(self, interface_name: str, vif_index:int, state_refresh_capable:boo # don't receive outgoing packets s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 0) + #self.drop_packet_type = None + super().__init__(interface_name, s, s, vif_index) super()._enable() self.force_send_hello() @@ -107,6 +109,10 @@ def send(self, data: bytes, group_ip: str=MCAST_GRP): """ Send a new packet destined to group_ip IP """ + #if self.drop_packet_type is not None and data.payload.get_pim_type() == self.drop_packet_type: + # self.drop_packet_type = None + # return + super().send(data=data, group_ip=group_ip) #Random interval for initial Hello message on bootup or triggered Hello message to a rebooting neighbor diff --git a/pimdm/Main.py b/pimdm/Main.py index 9ce7cdf..42d0e89 100644 --- a/pimdm/Main.py +++ b/pimdm/Main.py @@ -217,6 +217,33 @@ def test(router_name, server_logger_ip): logger.addHandler(socketHandler) +def get_config(): + """ + Get live configuration of PIM-DM process + """ + try: + from . import Config + return Config.get_yaml_file() + except ModuleNotFoundError: + return "PYYAML needs to be installed. Execute \"pip3 install pyyaml\"" + + +def set_config(file_path): + """ + Set configuration of PIM-DM process + """ + from . import Config + try: + Config.parse_config_file(file_path) + except: + import traceback + traceback.print_exc() + + +def drop(interface_name, packet_type): + interfaces.get(interface_name).drop_packet_type = packet_type + + def enable_ipv6_kernel(): """ Function to explicitly enable IPv6 Multicast Routing stack. diff --git a/pimdm/Run.py b/pimdm/Run.py index 12a9bca..1889de2 100644 --- a/pimdm/Run.py +++ b/pimdm/Run.py @@ -2,9 +2,11 @@ import os import sys +import time import glob import socket import argparse +import threading import traceback import _pickle as pickle from prettytable import PrettyTable @@ -13,7 +15,7 @@ from pimdm.tree import pim_globals from pimdm.daemon.Daemon import Daemon -VERSION = "1.1.1.4" +VERSION = "1.2" def client_socket(data_to_send, print_output=True): @@ -21,7 +23,7 @@ def client_socket(data_to_send, print_output=True): sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) # Connect the socket to the port where the server is listening - server_address = '/tmp/pim_uds_socket' + str(pim_globals.MULTICAST_TABLE_ID) + server_address = pim_globals.DAEMON_SOCKET.format(pim_globals.MULTICAST_TABLE_ID) #print('connecting to %s' % server_address) try: sock.connect(server_address) @@ -42,7 +44,7 @@ def client_socket(data_to_send, print_output=True): class MyDaemon(Daemon): def run(self): Main.main() - server_address = '/tmp/pim_uds_socket' + str(pim_globals.MULTICAST_TABLE_ID) + server_address = pim_globals.DAEMON_SOCKET.format(pim_globals.MULTICAST_TABLE_ID) # Make sure the socket does not already exist try: @@ -102,15 +104,24 @@ def run(self): elif 'stop' in args and args.stop: Main.stop() connection.shutdown(socket.SHUT_RDWR) + break elif 'test' in args and args.test: Main.test(args.test[0], args.test[1]) connection.shutdown(socket.SHUT_RDWR) + elif 'config' in args and args.config: + Main.set_config(args.config[0]) + connection.shutdown(socket.SHUT_RDWR) + elif 'get_config' in args and args.get_config: + connection.sendall(pickle.dumps(Main.get_config())) + elif 'drop' in args and args.drop: + Main.drop(args.drop[0], int(args.drop[1])) except Exception: connection.shutdown(socket.SHUT_RDWR) traceback.print_exc() finally: # Clean up the connection connection.close() + sock.close() def main(): @@ -144,6 +155,11 @@ def main(): group.add_argument("-rimld", "--remove_interface_mld", nargs=1, metavar='INTERFACE_NAME', help="Remove MLD interface") group.add_argument("-v", "--verbose", action="store_true", default=False, help="Verbose (print all debug messages)") group.add_argument("-t", "--test", nargs=2, metavar=('ROUTER_NAME', 'SERVER_LOG_IP'), help="Tester... send log information to SERVER_LOG_IP. Set the router name to ROUTER_NAME") + group.add_argument("-config", "--config", nargs=1, metavar='CONFIG_FILE_PATH', type=str, + help="File path for configuration file. This command should only be used with -start") + group.add_argument("-get_config", "--get_config", action="store_true", default=False, + help="Get configuration file of live daemon.") + #group.add_argument("-drop", "--drop", nargs=2, metavar=('INTERFACE_NAME', 'PACKET_TYPE'), type=str) group.add_argument("--version", action='version', version='%(prog)s ' + VERSION) group_ipversion = parser.add_mutually_exclusive_group(required=False) group_ipversion.add_argument("-4", "--ipv4", action="store_true", default=False, help="Setting for IPv4") @@ -184,7 +200,7 @@ def main(): pim_globals.MULTICAST_TABLE_ID = args.multicast_vrf[0] pim_globals.UNICAST_TABLE_ID = args.unicast_vrf[0] - daemon = MyDaemon('/tmp/Daemon-pim' + str(pim_globals.MULTICAST_TABLE_ID) + '.pid') + daemon = MyDaemon(pim_globals.DAEMON_PROCESS_FILE.format(pim_globals.MULTICAST_TABLE_ID)) if args.start: print("start") daemon.start() @@ -196,8 +212,25 @@ def main(): elif args.restart: daemon.restart() sys.exit(0) + elif args.config: + try: + from pimdm import Config + args.config[0] = os.path.abspath(args.config[0]) + [pim_globals.MULTICAST_TABLE_ID, pim_globals.UNICAST_TABLE_ID] = Config.get_vrfs(args.config[0]) + daemon = MyDaemon(pim_globals.DAEMON_PROCESS_FILE.format(pim_globals.MULTICAST_TABLE_ID)) + + if not daemon.is_running(): + x = threading.Thread(target=daemon.start, args=()) + x.start() + x.join() + + while not daemon.is_running(): + time.sleep(1) + except ModuleNotFoundError: + print("PYYAML needs to be installed. Execute \"pip3 install pyyaml\"") + sys.exit(0) elif args.verbose: - os.system("tail -f /var/log/pimdm/stdout" + str(pim_globals.MULTICAST_TABLE_ID)) + os.system("tail -f {}".format(pim_globals.DAEMON_LOG_STDOUT_FILE.format(pim_globals.MULTICAST_TABLE_ID))) sys.exit(0) elif args.multicast_routes: if args.ipv4 or not args.ipv6: diff --git a/pimdm/tree/pim_globals.py b/pimdm/tree/pim_globals.py index ab2169b..496d89f 100644 --- a/pimdm/tree/pim_globals.py +++ b/pimdm/tree/pim_globals.py @@ -1,3 +1,9 @@ +# Protocol files +DAEMON_PROCESS_FILE = '/tmp/Daemon-pim{}.pid' +DAEMON_SOCKET = '/tmp/pim_uds_socket{}' +DAEMON_LOG_FOLDER = '/var/log/pimdm/' +DAEMON_LOG_STDOUT_FILE = DAEMON_LOG_FOLDER + 'stdout{}' + # PIM-DM TIMER VARIABLES ASSERT_TIME = 180 GRAFT_RETRY_PERIOD = 3 diff --git a/setup.py b/setup.py index 972f1f5..05e2b96 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ long_description=open("README.md", "r").read(), long_description_content_type="text/markdown", keywords="PIM-DM Multicast Routing Protocol PIM Dense-Mode Router RFC3973 IPv4 IPv6", - version="1.1.1.4", + version="1.2", url="http://github.com/pedrofran12/pim_dm", author="Pedro Oliveira", author_email="pedro.francisco.oliveira@tecnico.ulisboa.pt",