Hey, do you remember the 2010s? Wow. What crazy trends we had! Do you remember coconut lattes? Remember vaporwave? Remember “doing it for the ‘Gram”? Remember the petrifying realisation of our own mortality on this doomed planet? Remember avocado on toast? What a time to be alive it was!
What a shame that we didn’t hear more about multicast in the 2010s. Think of the problems it could have solved. Poverty, climate change, and 90% of global wars could have EASILY been solved by a strategic multicast deployment. How? I haven’t got time to answer that. Just trust me when I say that even a few hours spent studying multicast could have brought some much-needed stability to the fragile geo-political scene. Truly, our leaders have a lot to answer for.
But hey: forget I said literally every single word of that.
In my experience, I’ve found – as I’m sure you’ve found – that the majority of engineers know almost nothing about multicast. They know it’s different to broadcast and unicast, they know what it achieves, but that tends to be where the knowledge ends. This situation isn’t helped by the fact that it’s either being removed or de-prioritised from vendor certs. It’s a vicious circle: if people don’t learn it, they don’t understand it. If they don’t understand it, they don’t use it. If no-one uses it, there’s no reason to learn it.
And that’s a shame, because it’s actually a really exciting protocol. That’s why I used Part 1 in this new series to introduce you to the key moving parts of multicast theory. Give it a read if you haven’t yet, because today we’re going to start putting it into practice by learning how to configure IGMP on Juniper routers, and seeing what happens when we turn it on. Specifically we’re going to look at IGMPv2 today. Then, next time we’ll look at IGMPv3 – and we’ll look at some advanced customization options too. As always, you’ll find the full config of each box at the end of this post, so you can play along at home.
Are you ready to turn theory into reality? Let’s go!
SO, WHAT’S THIS “IGMP” THAT ALL THE COOL HOLLYWOOD CELEBS ARE TALKING ABOUT?
In Part 1 we introduced two essential multicast protocols. First, there’s PIM, which is used between routers to build the tree from the FHR to the LHR. Remember what that stands for? That’s right: the First-Hop Router and Last-Hop Router. They’re the first and last routers in the path from source to destination).
Then there’s the Internet Group Management Protocol, or IGMP. This is what hosts use to signal that they’re interested in receiving multicast traffic. It’s also what Last-Hop Routers use to ask everyone on a LAN what multicast traffic they’re interested in receiving.
We’re going to learn about the inner workings today, but in principle it’s really simple: routers send out “queries” asking the network what multicast groups they want to receive traffic on, and hosts reply with “reports” of what they want. Additionally, hosts will send “leave group” messages to stop receiving traffic – to which routers will respond by sending “group-specific queries” out, to see if there’s anyone else still interested. That’s it! If you can understand that paragraph, you understand the principles of IGMP.
There’s actually 3 versions of this protocol. IGMPv2 tends to be the most commonly used one, even though version 3 offers some strong advantages. Here’s a chart that shows some of the improvements each new version brings. At this early stage, some of the terminology might not yet make sense, but as we go through this post we’ll explain every single bit of it.
You’re probably keen to see what those messages look like. Lucky for you then that we’re going to capture packets, and see exactly that!
Here’s our LAN for today. We have two routers, 10 and 11 – one Primary, one Backup – and then we have two receivers, hosts 12 and 13.
The subnet is 220.127.116.11/24.
The two routers talk VRRP with a shared IP of 18.104.22.168. All devices have IPs that match their name, so for example Host 12 is 22.214.171.124.
Why have these boxes been named with seemingly random numbers? Because it’s a small slice of the bigger network we’ll be seeing in future posts! Does it make you happy to see how much I’ve planned this out for you? How hard I’ve worked for you? How I’ve thought about our long-term future together? Perhaps it makes you feel loved? Special, maybe? Perhaps it inspires you to send me $500,000 via PayPal? Do it. Do it for love. Think about the regret you’ll carry with you for the rest of your life if you don’t PayPal me $500,000. Live life to the fullest, my darling.
…sorry, I zoned out for a while there. What was I saying? Oh yeah: 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! Not many folks know you can do this on a Cisco. It’s really handy in a lab, when you want a “host” with full debug functionality.
Cisco routers offer one advantage over Juniper when you’re labbing up IGMP, which is that Juniper routers don’t act as host receivers in quite the way we’d like. Later on, when we’ve learned the basics, I’ll explain why.
Here’s the essential Cisco config on the Cisco, taken from Host 12. Notice that we’ve configured it to be interested in joining the group 126.96.36.199 (AKA 239 dot nice dot nice dot nice).
hostname Host_12_Receiver no ip routing ip default-gateway 188.8.131.52 interface FastEthernet0/0 ip address 184.108.40.206 255.255.255.0 no ip route-cache ip igmp join-group 220.127.116.11
Host 13 has the same config, except that it’s additionally configured to be interested in group 18.104.22.168. Legalise this IP address.
For the time being, all LAN-facing interfaces on all boxes have been shut down. We’ll bring them up one at a time, so we can take an uncluttered look at what IGMP packets get sent out.
TURNING ON IGMP ON JUNIPER ROUTERS
As with a lot of protocols, IGMP theory takes ages to learn, but actually turning it on is as simple as this:
set protocols igmp interface ge-0/0/3.0
Let’s admin-up the ge-0/0/3.0 interface on Router 10, and commit our changes. We can check that IGMP is working on an interface with this command:
root@Router_10_CE_P> show igmp interface ge-0/0/3.0 Interface: ge-0/0/3.0 Querier: 22.214.171.124 State: Up Timeout: None Version: 2 Groups: 0 Immediate leave: Off Promiscuous mode: Off Passive: Off
Notice from the output above that IGMP defaults to version 2. Very good news indeed!
We can also quickly see how many multicast groups are alive on this interface. Later on we’ll see how to check what particular groups this interface knows about. In the mean time, let’s look at what packets this router sends out to the network.
ROUTERS SEND IGMP GENERAL MEMBERSHIP QUERIES
I’ve been running a packet capture since the moment I brought the interface up. Move your eyes two inches down the page, and you can see it for yourself!
(For those new to Wireshark: the Time column goes up in seconds from the moment of the start of the capture. As for the number column, I’m filtering out some packets, which is why it suddenly jumps from packet 5 to packet 142.)
Notice that Router 10 is regularly, though infrequently, sending out a General Membership Query. This is Router 10’s way of asking everyone on the network whether there’s any multicast traffic they’d like to receive. Interestingly, the router initially sends out three queries, and then settles down to just one per-cycle. Why three? Dunno. Better safe than sorry, I guess! (Download the packet capture here)
There’s also two Membership Reports at the top. We’ll come back to those.
Take a look at the payload of this message. Here’s a few interesting things about it:
- The destination address is 126.96.36.199. That’s the “all systems” address – in other words, everyone.
- This IGMP message isn’t sent using TCP or UDP, or even ICMP. Notice that IGMP is its own layer 4 protocol! To be precise, it’s IP protocol 2. Worth memorising if you’re a network trivia fan.
- Notice in the payload that it says “Type: Membership Query”. Nowhere does it specify that it’s a general query, just a “membership query”.
- The multicast address in the payload is all zeros. This is what makes it a general query.
- Finally, notice that there’s a Max Response Time. As you can guess, that’s how long hosts have to reply to this message before the router assumes that no-one wants to know about a stream any more. 10 seconds is the default. In a future blog post we’ll play with this setting.
In IGMPv2, this message is sent out every 125 seconds. Woah, that’s a long time! This introduces an interesting aspect of multicast: it often uses protocols that operate in a soft-state.
WHAT IS A SOFT-STATE PROTOCOL?
Protocols like OSPF involve routers forming neighbor relationships based on some important sanity checks, and based on multiple messages back and forth to truly “establish” the neighborship. Once it’s up, they reliably swap and maintain link-state advertisements that are identical across all routers in the network. A change in one router is replicated everywhere, almost immediately. All routers in the network are aware of the “state” of the other routers.
By contrast, multicast routers don’t necessarily know every single host on the network that’s interested in receiving traffic. It’s good enough to know that one host is interested, as we’ll see in a moment. And even if that person is no longer interested, it’s not a big deal if the router keeps getting sent out into the network for a while.
Indeed, when we come on to PIM you’ll see that although routers claim to form “neighbor” relationships with each other, these actually amount to no more than seeing a hello message from another router, and therefore adding the router to its neighbor table. There’s no back-and-forth exchange of messages to “build” the neighbor relationship like in hard-state protocols. The neighborship is formed silently, and torn down only when the Hello messages stop appearing.
The soft-state of multicast, with its occasional refresh messages, means that the traffic will time out eventually. It’s a disarmingly laid-back protocol!
125 seconds is a very long time indeed, even for a laid back protocol. If you want to increase this number to see more General Query messages in your lab, you could do this:
set protocols igmp query-interval 20
In production, you will decide for yourself whether increased messages add to an increase in efficiency. To be fair, in the year 2020 our hosts and routers can probably handle a few extra IGMP packets per minute, so turning this number way up should – SHOULD – be relatively safe.
HOSTS SEND IGMP MEMBERSHIP REPORTS
You’ll remember that Host 12 has been set up to be interested in group 188.8.131.52 (nice).
Behind the scenes I just admin-down’d the Juniper router’s interface, and then admin-up’d the Cisco host’s interface. The result: no IGMP messages on the network! That’s why this packet capture below starts with 134 seconds of silence. It seems that the Cisco host receiver doesn’t talk IGMP unless it’s spoken to. I’ve seen other vendors and other applications be more proactive, and announce itself as soon as it appears. Indeed, our Juniper did that with its own reports for 184.108.40.206 and 220.127.116.11. Don’t sweat it too much: it’s just a vendor thing.
So, let’s bring the Juniper back onto the network. (Download the packet capture here!)
Once again, we see Router 10 sending out multiple membership queries. A couple of seconds later, the Cisco replies, indicating that it would like to receive traffic for group 18.104.22.168 (nice). It does this using a Membership Report message.
Take a look at that payload. Membership Reports look a heck of a lot like Membership Queries, don’t they? In fact, there’s really only a few differences:
- The “Type” in the payload is now a Membership Report.
- The destination IP address is the multicast group we want to receive traffic from.
- The multicast destination address is also mentioned in the payload of the packet.
We really see the “soft-state” in action here. There’s no reliable back-and-forth between router and host with acknowledgements and confirmations. Instead, our router just sends out General Queries, and our host replies with a Membership Report.
Notice that these Membership Reports don’t yet prompt the router to send out Group-Specific Queries for 22.214.171.124 (nice). This is a good thing: the one general query is enough to get information about all the active groups on the LAN segment.
Here’s a thought: if the host is sending this Membership Report to 126.96.36.199, but our Router 10 isn’t yet set up to listen to traffic on this group, then how does the router know to process this packet? The answer is found in the IP header: the “Router Alert” flag is set in the Options field. This means that all routers will process this packet regardless of the destination IP address. This is combined with a TTL of 1, which means that the packet never leaves the LAN. Very clean!
Let’s see what our Juniper router makes of all this, with the following command:
root@Router_10_CE_P> show igmp group Interface: ge-0/0/3.0, Groups: 1 Group: 188.8.131.52 Source: 0.0.0.0 Last reported by: 184.108.40.206 Timeout: 238 Type: Dynamic Interface: local, Groups: 6 Group: 220.127.116.11 Source: 0.0.0.0 Last reported by: Local Timeout: 0 Type: Dynamic Group: 18.104.22.168 Source: 0.0.0.0 Last reported by: Local Timeout: 0 Type: Dynamic Group: 22.214.171.124 Source: 0.0.0.0 Last reported by: Local Timeout: 0 Type: Dynamic Group: 126.96.36.199 Source: 0.0.0.0 Last reported by: Local Timeout: 0 Type: Dynamic Group: 188.8.131.52 Source: 0.0.0.0 Last reported by: Local Timeout: 0 Type: Dynamic Group: 184.108.40.206 Source: 0.0.0.0 Last reported by: Local Timeout: 0 Type: Dynamic
Notice that this command starts by reporting on the actual interfaces running IGMP (just the one interface in this case), and then goes on to report all the addresses that the “local” box itself is interested in. You’ll have spotted that all those addresses are reserved multicast addresses, like 220.127.116.11. If you know your OSPF you’ll recognise that one for sure!
The “source” isn’t the source of the Membership Report message: it’s the source of where the multicast traffic is coming from. That’s why it’s blank at the moment: we don’t yet have any multicast senders.
One final thing: now you know what a Membership Report is, you can understand why the Juniper is also sending some out. For example, it’s sending a report for the group 18.104.22.168. Weirdly, this is actually the address for IGMPv3, which is interesting because we’re not running version 3. I assume the Juniper is doing this for some kind of forward-compatibility reasons, but it’s probably not worth puzzling over too much.
IGMP LEAVE GROUP MESSAGES
What happens if we do “no ip igmp join-group 22.214.171.124” on the Cisco, aka Host 12? I’ll tell you what happens, Buster: Host 12 sends out a Leave Group message.
Leave messages were introduced in IGMPv2. Can you believe that in version 1 there was no way for a receiver to indicate that they didn’t want to receive the traffic any more? They just had to wait for the LHR to time out the session, based on no-one replying to the router’s General Membership Queries. What a weird design choice, especially in the olden days when bandwidth and router resources were much more precious.
Let’s take a look at this new Leave Group message. Notice that I’ve clicked on the very first packet in the capture. Remember, 126.96.36.199 is the router; 188.8.131.52 is the receiver host. (Download the packets here!)
Once again, the payload is very similar to the rest of the IGMP message we’ve seen. There’s a new type, and the multicast address is the address we want to leave from. The only thing new is the destination IP address: it’s 184.108.40.206 – ie the All Routers address.
When a router receives a Leave Group message, it responds with a new kind of query – the Group-Specific Membership Query. You’ll find this in the same packet capture. I’ve clicked it below so you can see the payload – but by this stage, something tells me you’ll be able to start guessing what you’ll find in it:
Yep: it’s exactly identical to the General Membership Query, apart from the fact that the destination address in the IP header is the multicast group address, and apart from the fact that the “Multicast Address” in the payload is also the group in question.
Look at that response time: one second! Considering that the router sends out general queries once every 125 seconds, I find it funny that it only gives hosts on the LAN a single second to reply to this particular message.
BRINGING A SECOND HOST ONTO THE NETWORK
Now we’ve seen what happens with one receiver on the network, let’s see what happens when we introduce a second. Host 13 is also interested in receiving traffic destined to 220.127.116.11 (nice). In addition though, it’s also interested in receiving traffic destined to 18.104.22.168.
Let’s keep an eye out for two things. First of all, does this new host send out individual membership reports for each group it wants to receive traffic on? Or does Host 13 bundle the reports up into one aggregated message? Secondly, do the two hosts both send out membership reports for their shared group, 22.214.171.124? Or perhaps do they have a way of making things more efficient? Let’s find out. (Download the packet capture here!)
Immediately we can see that Host 13 sends out individual membership reports from each group it wants to receive from. Perhaps now our IGMP version comparison table at the start of this post makes a little bit more sense: IGMPv3 can bundle these reports up into the one aggregated report. By contrast, IGMPv2 sends out one report per group. Not a big deal at all on a tiny example lab network, but potentially a very big deal indeed on a huge LAN with lots of hosts receiving lots of groups.
We also see that only one host replies with a membership report for 126.96.36.199. Host 12 replied to the first query. Then, 125 seconds later, Host 13 replied to the second one. Here’s the concept: when a host receives a General Query, it counts down to a random time between 0 and 10 seconds (by default), and decides to send its Membership Report at the end of the countdown. Every host does this. Remember that 10 second timer from earlier on in the General Query message? Now you know why it’s important!
If another host has randomly chosen a shorter time, and that host replies first, all the other hosts cancel sending their own report. Remember, the report is sent to the group address, so all other hosts in the group will receive the report.
Here’s a debug from Host 13 (which is interested in both 188.8.131.52 and 184.108.40.206), with a few lines deleted for readability:
Host_13_Receiver# *Mar 1 00:39:39.651: IGMP(0): Received v2 Query on FastEthernet0/0 from 220.127.116.11 *Mar 1 00:39:39.651: IGMP(0): Set report delay time to 3.6 seconds for 18.104.22.168 on FastEthernet0/0 *Mar 1 00:39:39.655: IGMP(0): Set report delay time to 7.6 seconds for 22.214.171.124 on FastEthernet0/0 *Mar 1 00:39:43.547: IGMP(0): Send v2 Report for 126.96.36.199 on FastEthernet0/0 *Mar 1 00:39:47.555: IGMP(0): Send v2 Report for 188.8.131.52 on FastEthernet0/0
Meanwhile, here’s the same debug from Host 12 (which remember is only interested in 184.108.40.206):
Host_12_Receiver# *Mar 1 00:39:39.487: IGMP(0): Received v2 Query on FastEthernet0/0 from 220.127.116.11 *Mar 1 00:39:39.487: IGMP(0): Set report delay time to 7.5 seconds for 18.104.22.168 on FastEthernet0/0 *Mar 1 00:39:43.375: IGMP(0): Received v2 Report on FastEthernet0/0 from 22.214.171.124 for 126.96.36.199 *Mar 1 00:39:43.375: IGMP(0): Received Group record for group 188.8.131.52, mode 2 from 184.108.40.206 for 0 sources *Mar 1 00:39:43.375: IGMP(0): Cancel report for 220.127.116.11 on FastEthernet0/0
Great! Host 12 randomly chose a longer time to reply, so it cancels its report when it sees Host 13’s report. If you left the debug going for long enough, you’d see Host 12 replying sometimes, and Host 13 replying other times. Though Host 13 will always be the sole reporter for 18.104.22.168. Host 13 is very brave. Gosh, I hope it doesn’t get lonely.
Okay, we’ve seen what happens when there’s multiple hosts on the network. Now let’s bring a second Last-Hop Router onto the LAN. Router 11, it’s your time to shine!
IGMP QUERIER ELECTION
Take a look at this packet capture. Router 11 comes online at packet 27 – in other words, 18 seconds into the capture.
Notice that, like our other Juniper, the very first thing it does is announce its two groups, after which it sends out a few General Membership Queries. Everyone replies. They’re polite like that.
However, at packet 157 it’s Router 10 that sends out the General Membership Query – and from then on, it’s always router 10 that sends them out. Router 11 doesn’t send any more queries. Why? Because Router 10 won the IGMP Querier Election. (Download the packet capture here!)
This election is a good thing: if both boxes were sending out Membership Queries, it would double the amount of IGMP messages on the network, because everyone would reply to both queries.
The election is always won by the router with the lowest IP address, as we can see from the output of this command on Router 11:
root@Router_11_CE_B> show igmp interface Interface: ge-0/0/2.0 Querier: 22.214.171.124 State: Up Timeout: 229 Version: 2 Groups: 5 Immediate leave: Off Promiscuous mode: Off Passive: Off Configured Parameters: IGMP Query Interval: 125.0 IGMP Query Response Interval: 10.0 IGMP Last Member Query Interval: 1.0 IGMP Robustness Count: 2 Derived Parameters: IGMP Membership Timeout: 260.0 IGMP Other Querier Present Timeout: 255.0
(Hey: did you notice that when you just do “show igmp interface” without specifying a particular interface, you get some extra parameter information? Well worth remembering the difference between the two commands!)
Juniper’s website says “[Devices] with higher IGMP querier source addresses stop sending IGMP queries unless they do not receive IGMP queries for 255 seconds. If a [device] with a higher IGMP querier source address does not receive any IGMP queries during that period, it starts sending queries again.”
From what I can tell, there’s no way to customize which router acts as the querier, and no way to customize this timeout. So I suppose if for some reason you have a preference about which router is the querier, make sure you give that router the lowest IP on your LAN!
SO HEY, WHY ARE WE USING CISCO ROUTERS AGAIN?
THE SHORT VERSION: Junipers aren’t great at simulating being a receiver. Cisco routers do it better and more elegantly.
THE LONG VERSION FOR PEOPLE WITH AN INSATIABLE CURIOSITY: You can configure Juniper routers to receive traffic on a particular group. Here’s the config:
[edit protocols igmp] user@host# set interface ge-0/0/3.0 static group 126.96.36.199
However: a Juniper router won’t send out IGMP Membership Reports onto the LAN for this group. Even if the router receives a General Membership Query from another router on the LAN, the Juniper won’t reply with a Membership Report for this group.
Why? Because this command is specifically used to make our router send PIM Join messages upstream. We’ll learn about those messages in a few posts time; for now, just know that this command actually tests PIM, even though it’s configured under “protocols igmp”.
Can Juniper routers be configured at all to join a group from within a LAN? Not really. The closest we get is that we can turn on a protocol called SAP, or the Session Announcement Protocol:
set protocols sap listen 188.8.131.52
SAP is used to get a directory listing of multimedia multicast sources. It’s not important to know the details of this protocol. Just know that the command above does generate Membership Reports, but it’s a bit of a hack. It doesn’t quite provide the precision we’re after in a lab. It’s not quite as clean as our Cisco routers with their configuration that simply says “I want to join this group”. And next time when we want to learn about IGMPv3 with its source-specific requests, we definitely can’t test it with this SAP hack.
In short, using Cisco routers with routing turned off is the cleanest way to simulate hosts when you’re playing with about with IGMP in a lab.
DOWNLOAD THE FULL TOPOLOGY!
Here you go! Two routers and two hosts, ready-made for you to experiment with. Happy learning!
THAT’S IT – FOR NOW!
In my next post I’ll show you some advanced configuration you can add to break – I mean, tweak – IGMP. Then we’ll look at IGMPv3, and see how different the packets look when we start introducing the ability to request multicast traffic from a specific source. I’m really excited to show you all about it, and I hope you’ll come back for more when the next part goes up!
As always, you’ll be helping me out MASSIVELY if you shared this post on your social media of choice. Do it and help my blog to grow even more.
And hey: if you don’t want to ever miss a post of mine, follow me on Twitter! I’ll always share my new blog updates, as well as give you the luke-warmest takes on the networking world. Alternatively, if you want to miss about 80% of my posts, you can always follow me on LinkedIn, AKA the worst website on the internet. Great!