]>
Commit | Line | Data |
---|---|---|
f1f0bd09 | 1 | #!/usr/bin/env python3 |
acddc0ed | 2 | # SPDX-License-Identifier: ISC |
86439e8d DS |
3 | # |
4 | # mcast-rx.py | |
5 | # | |
6 | # Copyright (c) 2018 Cumulus Networks, Inc. | |
7 | # | |
86439e8d DS |
8 | """ |
9 | Subscribe to a multicast group so that the kernel sends an IGMP JOIN | |
10 | for the multicast group we subscribed to. | |
11 | """ | |
12 | ||
13 | import argparse | |
14 | import logging | |
15 | import re | |
16 | import os | |
17 | import socket | |
18 | import subprocess | |
19 | import struct | |
20 | import sys | |
21 | import time | |
22 | ||
23 | ||
24 | def ifname_to_ifindex(ifname): | |
701a0192 | 25 | output = subprocess.check_output( |
26 | "ip link show %s" % ifname, shell=True, universal_newlines=True | |
27 | ) | |
787e7624 | 28 | first_line = output.split("\n")[0] |
29 | re_index = re.search("^(\d+):", first_line) | |
86439e8d DS |
30 | |
31 | if re_index: | |
32 | return int(re_index.group(1)) | |
33 | ||
34 | log.error("Could not parse the ifindex for %s out of\n%s" % (ifname, first_line)) | |
35 | return None | |
36 | ||
37 | ||
38 | # Thou shalt be root | |
39 | if os.geteuid() != 0: | |
787e7624 | 40 | sys.stderr.write("ERROR: You must have root privileges\n") |
86439e8d DS |
41 | sys.exit(1) |
42 | ||
43 | ||
787e7624 | 44 | logging.basicConfig( |
45 | level=logging.DEBUG, format="%(asctime)s %(levelname)5s: %(message)s" | |
46 | ) | |
86439e8d DS |
47 | |
48 | # Color the errors and warnings in red | |
787e7624 | 49 | logging.addLevelName( |
50 | logging.ERROR, "\033[91m %s\033[0m" % logging.getLevelName(logging.ERROR) | |
51 | ) | |
52 | logging.addLevelName( | |
53 | logging.WARNING, "\033[91m%s\033[0m" % logging.getLevelName(logging.WARNING) | |
54 | ) | |
86439e8d DS |
55 | log = logging.getLogger(__name__) |
56 | ||
f635350e MS |
57 | parser = argparse.ArgumentParser(description="Multicast RX utility") |
58 | ||
787e7624 | 59 | parser.add_argument("group", help="Multicast IP") |
60 | parser.add_argument("ifname", help="Interface name") | |
61 | parser.add_argument("--port", help="UDP port", default=1000) | |
62 | parser.add_argument("--sleep", help="Time to sleep before we stop waiting", default=5) | |
86439e8d DS |
63 | args = parser.parse_args() |
64 | ||
65 | # Create the datagram socket | |
66 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | |
67 | sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
68 | sock.bind((args.group, args.port)) | |
69 | ||
70 | newpid = os.fork() | |
71 | ||
72 | if newpid == 0: | |
73 | ifindex = ifname_to_ifindex(args.ifname) | |
787e7624 | 74 | mreq = struct.pack( |
75 | "=4sLL", socket.inet_aton(args.group), socket.INADDR_ANY, ifindex | |
76 | ) | |
86439e8d DS |
77 | sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) |
78 | time.sleep(float(args.sleep)) | |
79 | sock.close() |