<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:"Andale Mono";
panose-1:0 0 0 0 0 0 0 0 0 0;}
@font-face
{font-family:Avenir-Book;
panose-1:0 0 0 0 0 0 0 0 0 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
span.EmailStyle19
{mso-style-type:personal-compose;
font-family:"Calibri",sans-serif;
color:windowtext;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;}
@page WordSection1
{size:612.0pt 792.0pt;
margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal">> After digging into the details of multicast by reading in "UNIX Network Programming” the problem may be that joining multicast groups is done at the IP level in the network stack and apparently all sockets on a network interface will
receive the datagrams for all multicasts when there is more than one, so a bind() needs to be done to create a “filter” for each socket so that only datagrams from the configured multicast are sent to each socket.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Yes, this is how IGMPv2 and earlier works. RFC 3367 (IGMPv3) has a paragraph that summarizes it nicely:<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"> Filtering of packets based upon a socket's multicast reception<o:p></o:p></p>
<p class="MsoNormal"> state is a new feature of this service interface. The previous<o:p></o:p></p>
<p class="MsoNormal"> service interface [RFC1112] described no filtering based upon<o:p></o:p></p>
<p class="MsoNormal"> multicast join state; rather, a join on a socket simply caused the<o:p></o:p></p>
<p class="MsoNormal"> host to join a group on the given interface, and packets destined<o:p></o:p></p>
<p class="MsoNormal"> for that group could be delivered to all sockets whether they had<o:p></o:p></p>
<p class="MsoNormal"> joined or not.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">> Maybe the {add_membership…} option includes this bind(), but of course the {raw…} does not.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">The problem isn’t the lack of bind(2) – gen_udp:open/1-2 does that for you – I believe it’s that your OS doesn’t implement RFC 3367 which states that a socket should only receive datagrams from the SSM groups it has joined. RFC 4607 further
clarifies this in section 2:<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"> The source-specific multicast service is defined as follows:<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"> A datagram sent with source IP address S and destination IP<o:p></o:p></p>
<p class="MsoNormal"> address G in the SSM range is delivered to each host socket that<o:p></o:p></p>
<p class="MsoNormal"> has specifically requested delivery of datagrams sent by S to G,<o:p></o:p></p>
<p class="MsoNormal"> and only to those sockets.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Since your OS apparently doesn’t do this, I’m afraid you might have to filter the unwanted datagrams out after the fact. :-(<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">/John<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal"><b>From:</b> erlang-questions <erlang-questions-bounces@erlang.org>
<b>On Behalf Of </b>Mark Geib<br>
<b>Sent:</b> Wednesday, January 20, 2021 17:33<br>
<b>To:</b> Sergej Jurečko <sergej.jurecko@gmail.com><br>
<b>Cc:</b> Erlang Questions <erlang-questions@erlang.org><br>
<b>Subject:</b> Re: multicast join problems (source specific)<o:p></o:p></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Yes, this suggestion is the method to join a any-source, or legacy, multicast. And this does work correctly.<o:p></o:p></p>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">The problem I am having is trying to join a IGMPv3 source-specific multicast where the IP of the source producing the multicast must be included, which is the purpose of the {raw..} option. The normal {add_membership…} does not work with
source-specific multicast.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">After digging into the details of multicast by reading in "UNIX Network Programming” the problem may be that joining multicast groups is done at the IP level in the network stack and apparently all sockets on a network interface will receive
the datagrams for all multicasts when there is more than one, so a bind() needs to be done to create a “filter” for each socket so that only datagrams from the configured multicast are sent to each socket. Maybe the {add_membership…} option includes this bind(),
but of course the {raw…} does not.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">I am thinking the way to address this problem will be using the new socket module, which provides a bind() function.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Thanks.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<p class="MsoNormal" style="margin-bottom:12.0pt"><o:p> </o:p></p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal">On Jan 20, 2021, at 1:54 AM, Sergej Jurečko <<a href="mailto:sergej.jurecko@gmail.com">sergej.jurecko@gmail.com</a>> wrote:<o:p></o:p></p>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div>
<div>
<p class="MsoNormal">Try connecting to multicast like so (Mc is multicast IP, Src is local IP):<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">{ok, SockSrc} = gen_udp:open(Port, [{reuseaddr,true}, <br>
{ip, {0,0,0,0}}, {add_membership, {Mc, Src}},{active,true}, binary,{recbuf, 1024*1024}]);<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Or maybe<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">{ok, SockSrc} = gen_udp:open(Port, [{reuseaddr,true}, <br>
{ip, Src}, {multicast_ttl, 1}, {multicast_loop, false}, binary]),<br>
inet:setopts(SockSrc, [{add_membership, {Mc, Src}}]);<o:p></o:p></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div>
<p class="MsoNormal">On Mon, Jan 18, 2021 at 10:20 PM Mark Geib <<a href="mailto:mark.geib.44@gmail.com">mark.geib.44@gmail.com</a>> wrote:<o:p></o:p></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0cm;margin-bottom:5.0pt">
<div>
<p class="MsoNormal">I have a problem when joining more than one source specific multicast group. The first gen_udp:open() works as expected, I start receiving datagrams sent to the specified multicast address, and coming from the specified source. However,
in another gen_server if I try to do the same, but on a different multicast and source address, I start receiving the datagrams on both the new socket as well as the first socket and from both multicast groups. The open looks like:<o:p></o:p></p>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Port = 3100,<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Andale Mono",serif">Bin = << <<239,0,0,1>>/binary, <<0,0,0,0>>/binary, <<10,0,1,1>>/binary >>,</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Andale Mono",serif">{ok, _Socket} = gen_udp:open(Port,<br>
[binary,<br>
{active, true},<br>
{reuseaddr, true},<br>
{multicast_ttl, 30},<br>
{raw, 0, 39, Bin}]), %% 0 - IPPROTO_IP, 39 - IP_ADD_SOURCE_MEMBERSHIP</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Avenir-Book",serif">I am able to join multiple multicasts, non source specific, and receive only datagrams from the correct group by using an open like:</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<div>
<p class="MsoNormal">Port = 3100,<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Andale Mono",serif">{ok, _Socket} = gen_udp:open(Port,</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Andale Mono",serif"> [binary,<br>
{active, true},<br>
{reuseaddr, true},<br>
{multicast_ttl, 30},</span><o:p></o:p></p>
</div>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Andale Mono",serif"> {add_membership, {239,0,0,1}, {0,0,0,0}}]),</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Avenir-Book",serif">Any suggestions or help would be appreciated.</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal"><span style="font-family:"Avenir-Book",serif">Mark.</span><o:p></o:p></p>
</div>
</div>
</blockquote>
</div>
</div>
</blockquote>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</div>
</body>
</html>