Commit 4f60a67a authored by Pedro Oliveira's avatar Pedro Oliveira

Use multicast and unicast table id on startup for starting multiple pim-dm daemon processes

parent f3dc94fa
......@@ -41,11 +41,19 @@ To interact with the protocol you need to execute the `pim-dm` command. You may
In order to start the protocol you first need to explicitly start it. This will start a daemon process, which will be running in the background. The command is the following:
```
sudo pim-dm -start
sudo pim-dm -start [-mvrf MULTICAST_TABLE_ID] [-uvrf UNICAST_TABLE_ID]
```
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`.
If `-mvrf` is not defined, the default multicast table id will be used (table id 0).
If `-uvrf` is not defined, the default unicast table id will be used (table id 254).
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.
#### Add interface
......@@ -54,25 +62,25 @@ After starting the protocol process you can enable the protocol in specific inte
- To enable PIM-DM without State-Refresh, in a given interface, you need to run the following command:
```
sudo pim-dm -ai INTERFACE_NAME [-4 | -6]
sudo pim-dm -ai INTERFACE_NAME [-4 | -6] [-mvrf MULTICAST_TABLE_ID]
```
- To enable PIM-DM with State-Refresh, in a given interface, you need to run the following command:
```
sudo pim-dm -aisf INTERFACE_NAME [-4 | -6]
sudo pim-dm -aisf INTERFACE_NAME [-4 | -6] [-mvrf MULTICAST_TABLE_ID]
```
- To enable IGMP/MLD in a given interface, you need to run the following command:
- IGMP:
```
sudo pim-dm -aiigmp INTERFACE_NAME
sudo pim-dm -aiigmp INTERFACE_NAME [-mvrf MULTICAST_TABLE_ID]
```
- MLD:
```
sudo pim-dm -aimld INTERFACE_NAME
sudo pim-dm -aimld INTERFACE_NAME [-mvrf MULTICAST_TABLE_ID]
```
#### Remove interface
......@@ -82,18 +90,18 @@ To remove a previously added interface, you need run the following commands:
- To remove a previously added PIM-DM interface:
```
sudo pim-dm -ri INTERFACE_NAME [-4 | -6]
sudo pim-dm -ri INTERFACE_NAME [-4 | -6] [-mvrf MULTICAST_TABLE_ID]
```
- To remove a previously added IGMP/MLD interface:
- IGMP:
```
sudo pim-dm -riigmp INTERFACE_NAME
sudo pim-dm -riigmp INTERFACE_NAME [-mvrf MULTICAST_TABLE_ID]
```
- MLD:
```
sudo pim-dm -rimld INTERFACE_NAME
sudo pim-dm -rimld INTERFACE_NAME [-mvrf MULTICAST_TABLE_ID]
```
......@@ -101,8 +109,10 @@ To remove a previously added interface, you need run the following commands:
If you want to stop the protocol process, and stop the daemon process, you need to explicitly run this command:
If a specific multicast table id was defined on startup, you need to define the daemon by its multicast table id.
```
sudo pim-dm -stop
sudo pim-dm -stop [-mvrf MULTICAST_TABLE_ID]
```
......@@ -115,28 +125,28 @@ We have built some list commands that can be used to check the "internals" of th
Show all router interfaces and which ones have PIM-DM and IGMP/MLD enabled. For IGMP/MLD enabled interfaces you can check the Querier state.
```
sudo pim-dm -li [-4 | -6]
sudo pim-dm -li [-4 | -6] [-mvrf MULTICAST_TABLE_ID]
```
- #### List neighbors
Verify neighbors that have established a neighborhood relationship.
```
sudo pim-dm -ln [-4 | -6]
sudo pim-dm -ln [-4 | -6] [-mvrf MULTICAST_TABLE_ID]
```
- #### List state
List all state machines and corresponding state of all trees that are being monitored. Also list IGMP state for each group being monitored.
```
sudo pim-dm -ls [-4 | -6]
sudo pim-dm -ls [-4 | -6] [-mvrf MULTICAST_TABLE_ID]
```
- #### Multicast Routing Table
List Linux Multicast Routing Table (equivalent to `ip mroute show`)
```
sudo pim-dm -mr [-4 | -6]
sudo pim-dm -mr [-4 | -6] [-mvrf MULTICAST_TABLE_ID]
```
......@@ -150,7 +160,7 @@ In order to determine which commands and corresponding arguments are available y
## Change settings
Files tree/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.
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.
## Tests
......
......@@ -13,7 +13,7 @@ from pimdm.packet.PacketPimHelloOptions import *
from pimdm.packet.PacketPimHello import PacketPimHello
from pimdm.packet.PacketPimHeader import PacketPimHeader
from pimdm.packet.Packet import Packet
from pimdm.tree.globals import HELLO_HOLD_TIME_TIMEOUT, REFRESH_INTERVAL
from pimdm.tree.pim_globals import HELLO_HOLD_TIME_TIMEOUT, REFRESH_INTERVAL
class InterfacePim(Interface):
......
import os
import socket
import struct
import ipaddress
......@@ -8,7 +9,7 @@ from abc import abstractmethod, ABCMeta
from pimdm import UnicastRouting, Main
from pimdm.rwlock.RWLock import RWLockWrite
from pimdm.tree.globals import MULTICAST_TABLE_ID
from pimdm.tree import pim_globals
from pimdm.InterfaceMLD import InterfaceMLD
from pimdm.InterfaceIGMP import InterfaceIGMP
......@@ -278,9 +279,9 @@ class Kernel4(Kernel):
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IGMP)
# MRT TABLE
if MULTICAST_TABLE_ID != 0:
if pim_globals.MULTICAST_TABLE_ID != 0:
try:
s.setsockopt(socket.IPPROTO_IP, self.MRT_TABLE, MULTICAST_TABLE_ID)
s.setsockopt(socket.IPPROTO_IP, self.MRT_TABLE, pim_globals.MULTICAST_TABLE_ID)
except:
traceback.print_exc()
......@@ -313,6 +314,11 @@ class Kernel4(Kernel):
struct_mrt_add_vif = struct.pack("HBBI 4s 4s", index, flags, 1, 0, ip_interface,
socket.inet_aton("0.0.0.0"))
os.system("ip mrule del iif {}".format(interface_name))
os.system("ip mrule del oif {}".format(interface_name))
if pim_globals.MULTICAST_TABLE_ID != 0:
os.system("ip mrule add iif {} lookup {}".format(interface_name, pim_globals.MULTICAST_TABLE_ID))
os.system("ip mrule add oif {} lookup {}".format(interface_name, pim_globals.MULTICAST_TABLE_ID))
with self.rwlock.genWlock():
self.socket.setsockopt(socket.IPPROTO_IP, self.MRT_ADD_VIF, struct_mrt_add_vif)
self.vif_index_to_name_dic[index] = interface_name
......@@ -330,6 +336,8 @@ class Kernel4(Kernel):
index = self.vif_name_to_index_dic.pop(interface_name, None)
struct_vifctl = struct.pack("HBBI 4s 4s", index, 0, 0, 0, socket.inet_aton("0.0.0.0"), socket.inet_aton("0.0.0.0"))
os.system("ip mrule del iif {}".format(interface_name))
os.system("ip mrule del oif {}".format(interface_name))
self.socket.setsockopt(socket.IPPROTO_IP, self.MRT_DEL_VIF, struct_vifctl)
del self.vif_name_to_index_dic[self.vif_index_to_name_dic[index]]
......@@ -522,9 +530,9 @@ class Kernel6(Kernel):
s = socket.socket(socket.AF_INET6, socket.SOCK_RAW, socket.IPPROTO_ICMPV6)
# MRT TABLE
if MULTICAST_TABLE_ID != 0:
if pim_globals.MULTICAST_TABLE_ID != 0:
try:
s.setsockopt(socket.IPPROTO_IPV6, self.MRT6_TABLE, MULTICAST_TABLE_ID)
s.setsockopt(socket.IPPROTO_IPV6, self.MRT6_TABLE, pim_globals.MULTICAST_TABLE_ID)
except:
traceback.print_exc()
......@@ -550,6 +558,13 @@ class Kernel6(Kernel):
def create_virtual_interface(self, ip_interface, interface_name: str, index, flags=0x0):
physical_if_index = if_nametoindex(interface_name)
struct_mrt_add_vif = struct.pack("HBBHI", index, flags, 1, physical_if_index, 0)
os.system("ip -6 mrule del iif {}".format(interface_name))
os.system("ip -6 mrule del oif {}".format(interface_name))
if pim_globals.MULTICAST_TABLE_ID != 0:
os.system("ip -6 mrule add iif {} lookup {}".format(interface_name, pim_globals.MULTICAST_TABLE_ID))
os.system("ip -6 mrule add oif {} lookup {}".format(interface_name, pim_globals.MULTICAST_TABLE_ID))
with self.rwlock.genWlock():
self.socket.setsockopt(socket.IPPROTO_IPV6, self.MRT6_ADD_MIF, struct_mrt_add_vif)
self.vif_index_to_name_dic[index] = interface_name
......@@ -571,6 +586,9 @@ class Kernel6(Kernel):
struct_vifctl = struct.pack("HBBHI", mif_index, 0, 0, physical_if_index, 0)
self.socket.setsockopt(socket.IPPROTO_IPV6, self.MRT6_DEL_MIF, struct_vifctl)
os.system("ip -6 mrule del iif {}".format(interface_name))
os.system("ip -6 mrule del oif {}".format(interface_name))
# alterar MFC's para colocar a 0 esta interface
with self.rwlock.genWlock():
for source_dict in list(self.routing.values()):
......
......@@ -3,7 +3,7 @@ import logging
from threading import Timer
from threading import Lock, RLock
from pimdm.tree.globals import HELLO_HOLD_TIME_NO_TIMEOUT, HELLO_HOLD_TIME_TIMEOUT
from pimdm.tree.pim_globals import HELLO_HOLD_TIME_NO_TIMEOUT, HELLO_HOLD_TIME_TIMEOUT
from pimdm.utils import TYPE_CHECKING
if TYPE_CHECKING:
from pimdm.InterfacePIM import InterfacePim
......
......@@ -8,10 +8,10 @@ import traceback
import _pickle as pickle
from pimdm import Main
from pimdm.tree import pim_globals
from pimdm.daemon.Daemon import Daemon
from pimdm.tree.globals import MULTICAST_TABLE_ID
VERSION = "1.1.1.1"
VERSION = "1.1.1.2"
def client_socket(data_to_send):
......@@ -19,7 +19,7 @@ def client_socket(data_to_send):
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(MULTICAST_TABLE_ID)
server_address = '/tmp/pim_uds_socket' + str(pim_globals.MULTICAST_TABLE_ID)
#print('connecting to %s' % server_address)
try:
sock.connect(server_address)
......@@ -37,7 +37,7 @@ def client_socket(data_to_send):
class MyDaemon(Daemon):
def run(self):
Main.main()
server_address = '/tmp/pim_uds_socket' + str(MULTICAST_TABLE_ID)
server_address = '/tmp/pim_uds_socket' + str(pim_globals.MULTICAST_TABLE_ID)
# Make sure the socket does not already exist
try:
......@@ -139,6 +139,17 @@ def main():
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("-6", "--ipv6", action="store_true", default=False, help="Setting for IPv6")
group_vrf = parser.add_mutually_exclusive_group(required=False)
group_vrf.add_argument("-mvrf", "--multicast_vrf", nargs=1, default=[pim_globals.MULTICAST_TABLE_ID],
metavar='MULTICAST_VRF_NUMBER', type=int,
help="Define multicast table id. This can be used on -start to explicitly start the daemon"
" process on a given vrf. It can also be used with the other commands "
"(for example add, list, ...) for setting/getting information on a given daemon"
" process")
group_vrf.add_argument("-uvrf", "--unicast_vrf", nargs=1, default=[pim_globals.UNICAST_TABLE_ID],
metavar='UNICAST_VRF_NUMBER', type=int,
help="Define unicast table id for getting unicast information (RPF checks, RPC costs, ...). "
"This information can only be defined at startup with -start command")
args = parser.parse_args()
#print(parser.parse_args())
......@@ -146,7 +157,10 @@ def main():
if os.geteuid() != 0:
sys.exit('PIM-DM must be run as root!')
daemon = MyDaemon('/tmp/Daemon-pim' + str(MULTICAST_TABLE_ID) + '.pid')
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')
if args.start:
print("start")
daemon.start()
......@@ -159,13 +173,13 @@ def main():
daemon.restart()
sys.exit(0)
elif args.verbose:
os.system("tail -f /var/log/pimdm/stdout" + str(MULTICAST_TABLE_ID))
os.system("tail -f /var/log/pimdm/stdout" + str(pim_globals.MULTICAST_TABLE_ID))
sys.exit(0)
elif args.multicast_routes:
if args.ipv4 or not args.ipv6:
os.system("ip mroute show table " + str(MULTICAST_TABLE_ID))
os.system("ip mroute show table " + str(pim_globals.MULTICAST_TABLE_ID))
elif args.ipv6:
os.system("ip -6 mroute show table " + str(MULTICAST_TABLE_ID))
os.system("ip -6 mroute show table " + str(pim_globals.MULTICAST_TABLE_ID))
sys.exit(0)
elif not daemon.is_running():
print("PIM-DM is not running")
......
......@@ -3,7 +3,7 @@ import ipaddress
from threading import RLock
from socket import if_indextoname
from pyroute2 import IPDB
from pimdm.tree.globals import UNICAST_TABLE_ID
from pimdm.tree import pim_globals
def get_route(ip_dst: str):
......@@ -65,18 +65,18 @@ class UnicastRouting(object):
dst_network = str(ipaddress.ip_interface(ip_dst + "/" + str(mask_len)).network)
print(dst_network)
if dst_network in ipdb.routes.tables[UNICAST_TABLE_ID]:
if dst_network in ipdb.routes.tables[pim_globals.UNICAST_TABLE_ID]:
print(info)
if ipdb.routes[{'dst': dst_network, 'family': family,
'table': UNICAST_TABLE_ID}]['ipdb_scope'] != 'gc':
info = ipdb.routes[{'dst': dst_network, 'family': family, 'table': UNICAST_TABLE_ID}]
'table': pim_globals.UNICAST_TABLE_ID}]['ipdb_scope'] != 'gc':
info = ipdb.routes[{'dst': dst_network, 'family': family, 'table': pim_globals.UNICAST_TABLE_ID}]
break
else:
continue
if not info:
print("0.0.0.0/0 or ::/0")
if "default" in ipdb.routes.tables[UNICAST_TABLE_ID]:
info = ipdb.routes[{'dst': 'default', 'family': family, 'table': UNICAST_TABLE_ID}]
if "default" in ipdb.routes.tables[pim_globals.UNICAST_TABLE_ID]:
info = ipdb.routes[{'dst': 'default', 'family': family, 'table': pim_globals.UNICAST_TABLE_ID}]
print(info)
return info
......
"""Generic linux daemon base class for python 3.x."""
import sys, os, time, atexit, signal
from pimdm.tree.globals import MULTICAST_TABLE_ID
from pimdm.tree import pim_globals
class Daemon:
......@@ -45,8 +45,8 @@ class Daemon:
sys.stdout.flush()
sys.stderr.flush()
si = open(os.devnull, 'r')
so = open('stdout' + str(MULTICAST_TABLE_ID), 'a+')
se = open('stderror' + str(MULTICAST_TABLE_ID), 'a+')
so = open('stdout' + str(pim_globals.MULTICAST_TABLE_ID), 'a+')
se = open('stderror' + str(pim_globals.MULTICAST_TABLE_ID), 'a+')
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
......
......@@ -2,7 +2,7 @@ import struct
import socket
from .PacketPimEncodedGroupAddress import PacketPimEncodedGroupAddress
from .PacketPimEncodedUnicastAddress import PacketPimEncodedUnicastAddress
from pimdm.tree.globals import ASSERT_CANCEL_METRIC
from pimdm.tree.pim_globals import ASSERT_CANCEL_METRIC
'''
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
......
from abc import ABCMeta, abstractmethod
import pimdm.tree.globals as pim_globals
from pimdm.tree import pim_globals
from .metric import AssertMetric
from pimdm.utils import TYPE_CHECKING
if TYPE_CHECKING:
......
from abc import ABCMeta, abstractmethod
from . import globals as pim_globals
from . import pim_globals as pim_globals
from pimdm.utils import TYPE_CHECKING
if TYPE_CHECKING:
from .tree_if_downstream import TreeInterfaceDownstream
......
......@@ -2,7 +2,7 @@ from .tree_interface import TreeInterface
from .upstream_prune import UpstreamState
from threading import Timer
from pimdm.custom_timer.RemainingTimer import RemainingTimer
from .globals import *
from .pim_globals import *
import random
from .metric import AssertMetric
from .originator import OriginatorState, OriginatorStateABC
......
......@@ -17,7 +17,7 @@ from pimdm.packet.PacketPimStateRefresh import PacketPimStateRefresh
from .metric import AssertMetric
from threading import Timer
from .local_membership import LocalMembership
from .globals import T_LIMIT
from .pim_globals import T_LIMIT
import logging
......
......@@ -13,7 +13,7 @@ setup(
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.1",
version="1.1.1.2",
url="http://github.com/pedrofran12/pim_dm",
author="Pedro Oliveira",
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