MULTICAST: IGMP VERISON 3 ON JUNIPER ROUTERS (FOR JNCIP & JNCIE STUDENTS)

Welcome back to my Network Fun-Times ongoing series about multicast: an extremely cool protocol that not many people know about. It’s very much a protocol for hipsters, in that respect.

That opening line is my way of shoe-horning in this true story: I genuinely met an engineer once who told me with a straight face that they “were using multicast before it was fashionable”.

What on EARTH could that possibly mean. Is it fashionable now? That’s news to me. Perhaps Armani is about to bring out a new series of multicast jumpers. What a weird thing for that engineer to say. Besides, by definition a multicast jumper wouldn’t make Armani any money: the first customer who bought one would just give duplicates to everyone else who wants one.

Anyway: forget I said every single word of that. A few weeks ago I taught you all about IGMP version 2 on Juniper routers. Click that sweet link if you missed it!

We mentioned that IGMPv1 isn’t really used any more, and that v2 brought benefits including:

  • The ability for hosts to leave a group (in version 1 things just had to time out for traffic to stop being sent)
  • The ability for routers to query hosts about specific groups (in version 1 a router could only ask a General Query: “is anyone interested in anything”? A bold design choice considering that IGMPv1 was RFCd in 1989, a time when the famously cynical Generation X weren’t interested in anything.)

But for whatever reason, the wizards that designed IGMPv2 didn’t include one very important feature: the ability to multicast delicious burritos directly to my mouth. How could they forget??

Also, there was another feature they didn’t include: the ability to request that a group’s traffic is sent from a specific source. That’s where version 3 comes in. In fact, IGMPv3 goes a little bit further. Not only can you request specific sources, but you can also indicate sources that you’re NOT interested in. How? Let’s find out!

 

HOW IS IGMPv3 DIFFERENT TO VERSIONS 1 AND 2?

Later on in this post we’ll do some packet captures, and we’ll see that the way IGMPv3 signals things is radically different to the way that v2 does it.

For a start, IGMPv3 Membership Reports (the message hosts send to indicate their interest in receiving traffic for a group) are all sent to a specific address: 224.0.0.22. You might remember that IGMPv2 hosts send Membership Reports with a destination address of the multicast group itself.

Why does that matter? In IGMPv2 hosts need to send multiple individual Membership Reports for each group they’re interested in. But the fact that IGMPv3 sends all Membership Reports to one single address gives a cool advantage: a host can bundle up those multiple individual messages into into one single Membership Report message. Nice!

Sending messages to one consistent address also offers a tremendous advantage for switches that can do IGMP Snooping.

IGMP snooping is the ability for a switch to listen in on IGMP messages, work out which receivers live out of what ports, and send traffic only to them. Cheaper switches just broadcast all multicast traffic to everyone on the LAN – which kind of defeats the purpose of multicast!

However, in IGMPv2, Snooping wasn’t as accurate as it could be. See, in IGMPv2 it worked like this: when a router sent out a Group-Specific Query, all hosts would set a random timer to reply. But as soon as one host replied, all other hosts receiving for that group would cancel their report. (Remember, the Report would be sent to the multicast group in question, so not only would the routers receive the report, but all hosts subscribed to the group would receive it as well.)

This idea of hosts cancelling their own reports is great if your goal is to keep control-plane traffic low on a segment. But it’s bad for switches who are trying to sensibly send traffic only to interested receivers. If a host isn’t actively reminding everyone that it wants the traffic, the switch only has two options: broadcast traffic everywhere, or listen out for the initial Join message, add that host’s port to the group on the switch, and then just keep sending traffic out of it in the hope that it’s needed.

With v3 though, all hosts reply. In fact, the hosts aren’t actually listening on 224.0.0.22. They send to it, but they don’t listen. As a result, they don’t even process everyone else’s Reports. Everyone checks in on the group they’re interested in – and as such, our switch knows exactly where all receivers live, and can send traffic only to people who definitely want it. Very clean!

 

INCLUDE AND EXCLUDE: A CRUCIAL IGMPv3 MEMBERSHIP REPORT FEATURE

The destination address is the least of it though: IGMPv3 actually uses six – SIX! – different kinds of new sub-message within a Membership Report!

Why? Well, the first thing to know is that there’s not really a concept of a “Leave Group” message like there is in IGMPv2. That’s because IGMPv3 does something clever: by bundling multiple Membership Reports up into one big message, we now have the ability to additionally indicate whether we want to Include or Exclude certain groups – and indeed, certain sources.

So for example, if you want to receive traffic sent to group 234.5.6.7, from a source of 10.1.1.1, you’d send a Multicast Report for that group “including” this source. Easy!

It gets a bit more interesting when you want to receive traffic from any source though, because this is actually done by sending an “Exclude” message, with a source count of zero. In other words, “exclude no-one”.

At this point you might be wondering: That’s an odd way to do it. Why “exclude no-one”, and not “include everyone”?

I can’t find a definitive answer on that, but here’s my best guess: I notice that the “source” in the Membership Report is a single IP, not a subnet. So presumably there’s no way to signal something like “Include 0.0.0.0/0”. If there was then it would probably make more sense to do it like that. But because the “source” has to be an individual IP, it makes more sense to say “exclude no-one” when you want to indicate that you want to receive from everyone.

Of course, that begs the question “Why did they design the protocol so that I can’t signal to receive traffic from a certain subnet, or a certain range of IPs?”. My guess: they probably didn’t see a use case for it, so they didn’t include it. A bit of anti-climatic end to that little story there. If it helps, I just had a nice dessert. So it’s kind of a happy ending for me? Anyway, all of that is just a theory, so take it with a pinch of salt.

So, back to these six new messages. Three of them are to do with including, and three of them are to do with excluding. It’s so much easier to understand it when you can actually see them – so for now, just know they exist. Then, as we do packet captures, I’ll introduce you to the new message types.

 

A REMINDER OF OUR TOPOLOGY

This is the same LAN that we used last time: the LAN that’s a small part of the bigger topology we’ll see in future posts!

Once again we have two routers, 10 and 11 – one Primary, one Backup – and two receivers, hosts 12 and 13. The subnet is 172.1.3.0/24, and all devices have IPs that match their name, so for example Host 12 is 172.1.3.12.

Our two routers on this LAN are Juniper boxes. The switch I’m using is the built-in “bridge” provided by EVE-NG. Here’s the twist though: the two receiver hosts are actually Cisco routers, with routing turned off! Check out my last post for the reason why.

We’ll be adding and taking away groups, and groups-with-sources, as we go. And just like last time, we’re starting with all interface shut down. We’ll bring them up one at a time to see what happens.

 

TURNING ON IGMPv3 ON JUNIPER ROUTERS

Just like in version 2 of the protocol, IGMP3 has the concept of General Queries (where routers ask everyone to report in on all groups they’re interested in), and Group-Specific Queries (in response to hosts leaving a group, to check if anyone is still interested).

In addition, IGMPv3 introduces a new message: the Group-And-Source-Specific Query. It makes sense that this new message would exist, when you remember that the main advantage of IGMPv3 is the ability for a host to request traffic from a specific source. By the way, just like in IGMPv2, these group-specific queries are still sent to the group address in question. It’s only the reports from the hosts that now go to the special address of 224.0.0.22.

Let’s enable IGMPv3 on Router 10, and take a look at the packets on the wire. Turning on version 3 is super easy:

[edit]
root@Router_10_CE_P# set protocols igmp interface ge-0/0/3.0 version 3

At this point, the interface was shut down. I started a packet capture, and then brought the interface up. Here’s what happened:

Starting at the top of the capture: the Juniper router immediately announces itself as being part of two multicast groups. Do you recognise those two addresses? 224.0.0.2 is All Routers, and 224.0.0.22 is All IGMPv3 speakers. Oddly though, it advertised them via IGMPv2! My guess is that this is for backwards compatibility. Version 3 boxes can accept Version 2 packets, but of course the same isn’t true the other way round.

The router then immediately sends out three identical IGMPv3 Membership Queries, in the space of two seconds. Chill out man, it’s not a good look to seem too keen. I thought you were supposed to be the cool protocol?

Anyway, after that we see the usual behaviour of sending one Query every 125 seconds (by default). Let’s take a closer look at what’s actually inside one of these IGMPv3 Membership Queries.

 

A CLOSER LOOK AT MEMBERSHIP QUERY PACKETS IN IGMPv3

Here’s the payload of that message from the previous screenshot. To help you compare v2 and v3, I’ve put a v2 Membership Query in a red box. Can you see it? Can you see the red box? Award yourself ten points if you can.

If you look at the v2 Query line-by-line, you’ll see it’s identical to the v3 Query. We have items including:

  • The version
  • The message “type”
  • The maximum response time (10 seconds by default);
  • The checksum
  • And a multicast address set to 0.0.0.0, indicating “everything” – in other words, this is a General Query. Coincidentally, “General Query” was the name of my leader in the army. It’s true! Don’t look it up.

We also see four new lines in the IGMPv3 message. For example, we see something called “QRV: 2”,  and after that we see “QQIC: 125”.

QRV stands for the Querier’s Robustness Variable. When a host leaves a group, this number sets how many Group-Specific Queries the router will send out. Set this number high to accommodate for packet loss.

“But Chris, surely nowadays we don’t tolerate any packet loss at all?” Yes, that’s true – but remember, multicast is a soft-state protocol. There’s no stateful information and hellos and keepalives, at least not in a meaningful bi-directional confirm-that-everyone-is-in-agreement sense. If you’re running a service where it’s absolutely critical that stuff gets to where it’s supposed to go, you might want to try increasing this number.

(Be careful playing with it though: the more you increase it, the longer routers wait before timing out a group, which may or may not be want you want to happen.)

We had a Querier’s Robustness Variable in IGMPv2 as well. But in IGMPv3 it’s advertised to everyone, so that non-designated queriers can sync themselves with the Designated Querier’s settings.

(And by the way, if you’re unsure what the Designated Querier is, check out my last post for the full explanation on it!)

QQIC stands for the Querier’s Query Interval Code. It’s 125 seconds, which is how long queries will be sent out. And again, we had this in v2. But in v3 it’s included in the payload so that the other routers on the network can see what it is, and copy it.

As for “Num Src: 0“, you can probably guess that it refers to the number of sources you’re interested in, if any. The fact that this specifies no sources and no multicast address is what makes this a General Query. If there was a multicast address it would be a Group-Specific Query. And if there was also a source address, it would be a “Group-and-Source-Specific Query”. The names do exactly what they say, my guy!

It seems that IGMPv3 General Queries aren’t that different to v2! Hold tight though. Things get different very quickly.

 

BRINGING UP THE OTHER JUNIPER ROUTER

Now that Router 10 is sending out queries, let’s also bring up the interface on Router 11.

Nothing unusual happens in the packet capture below: it does everything Router 10 did, including sending out 3 General Query messages. To start with, Router 11 doesn’t realise it’s not the Designated Querier for the segment. Then, notice at packet 49 that Router 10 sends its own query. Once Router 11 sees Router 10’s Query, Router 11 realises it’s lost the election – remember, lowest IP address wins – and from that point onwards it’s only Router 10 that sends queries.

Interesting that the routers reply to IGMPv3 Queries with IGMPv2 Reports! This is totally fine, IGMPv3 can accept Reports from older versions. Again, I suspect this is for backwards compatibility with v2-only speakers on the LAN.

 

CAPTURING MEMBERSHIP REPORT PACKETS IN IGMPv3

I’ve temporarily disabled the interfaces on the Junipers. Let’s now bring up the interface on Host 12 (aka our Cisco router with routing turned off), and see what happens.

Here’s the important config on Host 12. Notice that I’ve turned on IGMPv3, and I’ve also specified two groups, one of which has a specific source.

hostname Host_12_Receiver
no ip routing

interface FastEthernet0/0
 ip address 172.1.3.12 255.255.255.0
 ip igmp join-group 239.69.69.69 source 4.20.4.20
 ip igmp join-group 239.69.69.70
 ip igmp version 3
 shutdown

With no interfaces up on any box on the LAN, let’s now “no shut” this interface, and see what happens:

Just like last time, it seems that the Cisco doesn’t send out any Joins when the interface comes up. That seems very weird to me. We’ve configured groups on this interface, but it doesn’t advertise them. Out of interest, let’s try adding another group:

Host_12_Receiver(config-if)#ip igmp join-group 239.69.69.71

Anything?

Now that’s weird: in IGMPv2, at this point the router would indeed send out a “Join Group” Report. But it seems in IGMPv3 it doesn’t do that! Bizarre.

One final experiment. What happens if we add a new group with a specific source?

Host_12_Receiver(config-if)#ip igmp join-group 239.69.69.72 source 1.2.3.4

The result:

WHAT? WHAT?? WHAT. ACTUALLY WHAT. WHY THE SWEAR-WORD IS THIS HAPPENING. THIS IS ABSURD AND I AM ANGRY.

So, to summarise. On a Cisco router (or at least, on this particular IOS version):

  • If you specify a group with or without a source while the interface is down, then bring the interface up, the Cisco stays quiet.
  • If you specify a group without a source, then even if you do it while the interface is up, the Cisco stays quiet until prompted by a Membership Query.
  • But if you bring the interface up, and then add a group with a source, the Cisco tells everyone. But only if it has a source.

In other words, if your interface flaps, the box won’t re-advertise the groups it’s interested in until it’s asked. Why. WHY. A weird behaviour, but one I wanted to highlight in case you’re ever troubleshooting a weird problem!

(This is specific to IGMPv3, by the way. When I put the interface to v2 and then I leave a group, the Cisco does indeed send an IGMPv2 Leave Group message.)

Anyway, enough of that: let’s look at the IGMPv3 equivalent of a Join message.

 

ANALYSING MEMBERSHIP REPORTS IN IGMPV3

Do you remember earlier that I told you about the six different kinds of Membership Report? Three different Include messages, and three different Exclude message? Remember how I said we’d look at them later? Well guess what: later is now!

In this capture we can see that the Type is “Membership Report” – but once again we see some new fields.

For example, we see a “Num Group Records” field of 1. This is the field that lets us bundle up multiple “Reports” into a single message. Later on we’ll see captures with more than one Group Record in a single message, and believe me when I say that it’s beautiful, truly beautiful.

This particular Group Record is of the type “Allow New Sources“, and once again it does what it says on the tin! We see a Multicast Address we want to receive on, and we see one single source address that we want to receive it from. We are, in a very literal sense, allowing traffic from this new source.

The (5) at the end indicates that this is the 5th of the 6 new messages as defined in the RFC for IGMPv3. Messages (5) and (6) are called Source-List-Change Record types, because they’re specifically to do with – you guessed it – changes to the source list!

What does message (6) look like? Let’s find out, by removing this group/source config from our “host”:

Host_12_Receiver(config-if)#no ip igmp join-group 239.69.69.72 source 1.2.3.4

There it is! Message (6) is the other Source-List-Change Record: a Block Old Sources type. We were previously interested in traffic to 239.69.69.72, but only from a source of 1.2.3.4. We’re now no longer interested in that source – and because that was actually the only source we were interested in, it means that we now don’t want to receive traffic to that group at all, no matter where it comes from. Even if it comes from Bill Gates himself.

In effect, what we’re looking at here is a Leave message. But to be clear, technically there are no specific “leave group” messages in IGMPv3. The signalling to leave a group now happens within the Membership Report. And hey: did you notice that it’s sent to that new destination address of 224.0.0.22?

 

BRINGING BOTH ROUTERS AND HOSTS ONLINE TOGETHER

Okay, let’s bring it all together. Remember, this is what’s currently on our Cisco at the moment:

ip igmp join-group 239.69.69.69 source 4.20.4.20
ip igmp join-group 239.69.69.70

Let’s see what happens when we get routers and hosts talking to each other!

I brought the Juniper interfaces up, then started the packet capture. (I actually brought the host up sometime after 100 seconds, which is why the first actual reply from the host comes at the 247-second mark, as highlighted below.)

And look at that – we see our first IGMPv3 Membership Report carrying multiple groups!

In fact, we also get to see Record Types (1) and (2). These are the two Current-State Record types – the kind that a host generates in response to a Membership Query.

  • Message type (1) is called “Mode Is Include“. In this record, we’re signalling that we want to include one source.
  • Message type (2) is called “Mode Is Exclude“. We can see that this particular message wants to exclude no sources (“Num Src: 0”). In other words, exclude no-one – we’re interested in receiving group traffic from any source.

Maybe you’re starting to see that even though there’s technically six message types, there’s really only two. They’re just ever-so-slightly different depending on the reason that they’re being generated: for example, in response to a Query, or if there’s a change in the source we’re interested in.

(Annoyingly, as hard as I tried, I couldn’t actually get the Cisco to generate record types (3) and (4), which is frustrating because I really wanted to show them to you! The RFC calls these “Filter-Mode-Change Records”. The “filter” refers to include or exclude, and my reading of the RFC is that these are supposed to be generated whenever there’s a change without a source. Hence the need for the type (5) and (6) which do indeed specify a source.

As we saw above, when I add groups without sources, the box does nothing, which is why I can’t create (3) and (4) type records. Perhaps you could close your eyes and imagine what they’re like?)

We can use the following command to confirm that our Juniper knows it’s got receivers interested in the traffic:

root@Router_10_CE_P> show igmp group detail
Interface: ge-0/0/3.0, Groups: 5
 {I've snipped out groups 224.0.0.2, 224.0.0.18 and 224.0.0.22}
    Group: 239.69.69.69
        Group mode: Include
        Source: 4.20.4.20
        Source timeout: 209
        Last reported by: 172.1.3.12
        Group timeout:       0 Type: Dynamic
        Output interface: ge-0/0/3.0
    Group: 239.69.69.70
        Group mode: Exclude
        Source: 0.0.0.0
        Source timeout: 0
        Last reported by: 172.1.3.12
        Group timeout:     209 Type: Dynamic
        Output interface: ge-0/0/3.0

Would you like to see what it looks like when a host bundles up multiple sources into one message? Let’s add this config to Host 12:

Host_12_Receiver(config-if)#ip igmp join-group 239.69.69.71 source 5.6.7.8
Host_12_Receiver(config-if)#ip igmp join-group 239.69.69.71 source 5.6.7.9
Host_12_Receiver(config-if)#ip igmp join-group 239.69.69.71 source 5.6.7.10
Host_12_Receiver(config-if)#ip igmp join-group 239.69.69.71 source 5.6.7.11
Host_12_Receiver(config-if)#ip igmp join-group 239.69.69.71 source 5.6.7.12

Each time I typed a line of config, it generated a new individual unsolicited Membership Report. The box does it instantly as soon as a line of config with a source is added. But from there on, the info is all bundled into this one single reply to a Membership Query. Check out the very last record in the set:

 

So there we go! IGMPv3 has a fairly different message format from Version 2. Some extra things are advertised that were kept internal before. But apart from that, the actual theory isn’t too different!

 

DOWNLOAD THE FULL CONFIGS FOR THIS TOPOLOGY

Good news: the configs are exactly the same as the ones I put at the end of my last post! I gave you the new commands as we went along in this blog post, so you can easily play along at home.

 

THAT’S IT!

Have you ever used IGMPv3? Had any tricky or interesting experiences with it? Let me know in the comments!

Thanks as always for checking out my blog. If you’re on Mastodon, follow me to find out when I make new posts. (2024 edit: I’m also on BlueSky nowadays too. I was once on Twitter, but I’ve given up on it, on account of… well, I don’t need to finish that sentence, do I.)

And hey: if you enjoyed this post, you’d do me the biggest favour if you shared this post on your social media of choice, or maybe even sent it directly to your colleagues. The more folks that read my blog, the more inspired I am to write more.

If you fancy some more learning, take a look through my other posts. I’ve got plenty of cool new networking knowledge for you on this website, especially covering Juniper tech and service provider goodness.

It’s all free for you, although I’ll never say no to a donation. This website is 100% a non-profit endeavour, in fact it costs me money to run. I don’t mind that one bit, but it would be cool if I could break even on the web hosting, and the licenses I buy to bring you this sweet sweet content.

Leave a Reply

Your email address will not be published. Required fields are marked *