Search code examples
pythonpython-3.xipv6multicast

Python 3 IPv6 Multicast


I am trying to design a straightforward client/server pair for IPv6 multicast communication in Python. The code I have so far seems conforms to examples I've seen online, but my server never receives data.

I see the subscription in ip maddr show and netstat -g. tcpdump shows: 10:13:36.913546 IP6 (flowlabel 0x77fe8, hlim 5, next-header UDP (17) payload length: 20) **omitted** > ff16::fe.commplex-main: [udp sum ok] UDP, length 12

The client and server are connected to the same switch and the IPv6 unicast addresses are in the same subnet (they can ping eachother).

Server

#!/usr/bin/python3

import socket
import struct

local_addr = ::
mcast_addr = "ff16::fe"
mcast_port = 5000
ifn = "eno1"

# Create socket
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)

sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)

# Set multicast interface
ifi = socket.if_nametoindex(ifn)
ifis = struct.pack("I", ifi)
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, ifis)

# Set multicast group to join
group = socket.inet_pton(socket.AF_INET6, mcast_addr) + ifis
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, group)

sock_addr = socket.getaddrinfo(local_addr, mcast_port, socket.AF_INET6, socket.SOCK_DGRAM)[0][4]
sock.bind(sock_addr)

cmd = ""
while True:
    data, src = sock.recvfrom(1024)
    print("From " + str(src) + ": " + data.decode())

Client

#!/usr/bin/python3

import socket
import struct

message = "Hello world!"
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
sock_addr = socket.getaddrinfo("ff16::fe", 5000, socket.AF_INET6, socket.SOCK_DGRAM)[0][4]

ttl = struct.pack('i', 5)
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, ttl)

sock.sendto(message.encode(), sock_addr)

Any input would be appreciated.


Solution

  • In addition to all the other good advice: you bind the socket on the server to the link local address. This will filter incoming packets so that only packets with that destination address reach your code. Packets addressed to the multicast address will be dropped. Try binding to :: and make sure that works before moving on to something more complex.