]>
Commit | Line | Data |
---|---|---|
86439e8d DS |
1 | #!/usr/bin/env python |
2 | # | |
3 | # mcast-tx.py | |
4 | # | |
5 | # Copyright (c) 2018 Cumulus Networks, Inc. | |
6 | # | |
7 | # Permission to use, copy, modify, and/or distribute this software | |
8 | # for any purpose with or without fee is hereby granted, provided | |
9 | # that the above copyright notice and this permission notice appear | |
10 | # in all copies. | |
11 | # | |
12 | # THE SOFTWARE IS PROVIDED "AS IS" AND Cumulus Networks DISCLAIMS ALL WARRANTIES | |
13 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
14 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR | |
15 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY | |
16 | # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
17 | # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS | |
18 | # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
19 | # OF THIS SOFTWARE. | |
20 | # | |
21 | ||
22 | import argparse | |
23 | import logging | |
24 | import socket | |
25 | import struct | |
26 | import time | |
27 | ||
28 | ||
29 | logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)5s: %(message)s') | |
30 | ||
31 | # Color the errors and warnings in red | |
32 | logging.addLevelName(logging.ERROR, "\033[91m %s\033[0m" % logging.getLevelName(logging.ERROR)) | |
33 | logging.addLevelName(logging.WARNING, "\033[91m%s\033[0m" % logging.getLevelName(logging.WARNING)) | |
34 | log = logging.getLogger(__name__) | |
35 | ||
36 | parser = argparse.ArgumentParser(description='Multicast packet generator', version='1.0.0') | |
37 | parser.add_argument('group', help='Multicast IP') | |
38 | parser.add_argument('ifname', help='Interface name') | |
39 | parser.add_argument('--port', type=int, help='UDP port number', default=1000) | |
40 | parser.add_argument('--ttl', type=int, help='time-to-live', default=20) | |
41 | parser.add_argument('--count', type=int, help='Packets to send', default=1) | |
42 | parser.add_argument('--interval', type=int, help='ms between packets', default=100) | |
43 | args = parser.parse_args() | |
44 | ||
45 | # Create the datagram socket | |
46 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | |
47 | ||
48 | # IN.SO_BINDTODEVICE is not defined in some releases of python but it is 25 | |
49 | # https://github.com/sivel/bonding/issues/10 | |
50 | # | |
51 | # Bind our socket to ifname | |
52 | sock.setsockopt(socket.SOL_SOCKET, | |
53 | 25, | |
54 | struct.pack("%ds" % len(args.ifname), args.ifname)) | |
55 | ||
56 | # We need to make sure our sendto() finishes before we close the socket | |
57 | sock.setblocking(1) | |
58 | ||
59 | # Set the time-to-live | |
60 | sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, struct.pack('b', args.ttl)) | |
61 | ||
62 | ms = args.interval / 1000.0 | |
63 | ||
64 | # Send data to the multicast group | |
65 | for x in xrange(args.count): | |
66 | log.info('TX multicast UDP packet to %s:%d on %s' % (args.group, args.port, args.ifname)) | |
67 | sent = sock.sendto('foobar %d' % x, (args.group, args.port)) | |
68 | ||
69 | if args.count > 1 and ms: | |
70 | time.sleep(ms) | |
71 | ||
72 | sock.close() |