Hubs and switches are two typical network devices. Hubs are located in the physical layer, while switches are located in the data link layer, and their behaviors are obviously different. This section prepares two simple experiments to deepen the understanding of theoretical knowledge and gradually master the operation of Linux host network through practice.

Experiment 1: Observe an Ethernet hub

In this experiment, three Linux hosts are connected to a hub to observe the working behavior of the hub. The network topology is shown as follows:

The experimental environment is provided in the form of a Docker container, which can be opened by executing this docker command:

docker run --name hub-lab --rm -it --privileged --cap-add=NET_ADMIN --cap-add=SYS_ADMIN -v /data -h hub-lab Fasionchan/netbox: 0.5 bash/script/hub - lab. ShCopy the code

After opening the experimental environment, you can see three Windows, each representing a host:

This is a window partition implemented with the Tmux command. Press ctrl-B_ followed by the arrow key to switch between different host Windows.

Be careful to press Ctrl-B and release it, then press the arrow keys to cut to the desired host window.

An even faster way to switch is to press Ctrl-B, release it, and then press Q. At this point, each window displays a number. Then, press the corresponding number to cut to the desired window:

Let’s first go to ant and observe its network adapter information, using either ifconfig or IP:

root@ant [~] ➜ ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 ether 32:90:b9:9f:35:56 txqueuelen 1000 (Ethernet) RX packets 6 Bytes 540 (540.0b) RX errors 0 dropped 0 Overruns 0 frame 0 TX packets 3 bytes 270 (270.0b) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: Flags =73<UP,LOOPBACK,RUNNING> MTU 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixLen 128 scopeid 0x10<host> loop Txqueuelen 1000 (Local Loopback) RX packets 0 bytes 0 (0.0b) RX errors 0 Dropped 0 Overruns 0 frame 0 TX packets 0 Bytes 0 (0.0b) TX errors 0 Dropped 0 Overruns 0 carrier 0 collisions 0Copy the code
root@ant [~] ➜ IP Link 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: tunl0@NONE: <NOARP> MTU 1480 qdisc noop state DOWN mode DEFAULT group DEFAULT qlen 1000 Link/ipIP 0.0.0.0 BRD 0.0.0.0 3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/tunnel6 :: brd :: 6: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 32:90:b9:9f:35:56 brd ff:ff:ff:ff:ff:ff link-netnsid 0Copy the code

Next, cut to host Bee and CICada and continue to observe their nic information:

root@bee [~] ➜ IP Link 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: tunl0@NONE: <NOARP> MTU 1480 qdisc noop state DOWN mode DEFAULT group DEFAULT qlen 1000 Link/ipIP 0.0.0.0 BRD 0.0.0.0 3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/tunnel6 :: brd :: 8: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether a2:17:41:bb:cd:98 brd ff:ff:ff:ff:ff:ff link-netnsid 0Copy the code
root@cicada [~] ➜ IP Link 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: tunl0@NONE: <NOARP> MTU 1480 qdisc noop state DOWN mode DEFAULT group DEFAULT qlen 1000 Link/ipIP 0.0.0.0 BRD 0.0.0.0 3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/tunnel6 :: brd :: 10: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether ee:76:f2:37:5e:69 brd ff:ff:ff:ff:ff:ff link-netnsid 0Copy the code

The nic and MAC address information of the three hosts is as follows:

The host The network card The MAC address
ant eth0 32:90:b9:9f:35:56
bee eth0 a2:17:41:bb:cd:98
cicada eth0 ee:76:f2:37:5e:69

Now, let’s send a message from host Ant to host Bee to see if host Bee can receive the message, and at the same time see if host Cicada can also receive the message. Before sending, we run the packet capture tool tcpdump command in BEE and CICada to sniff network traffic:

root@bee [~] ➜ tcpdump -ni eth0 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytesCopy the code
root@cicada [~] ➜ tcpdump -ni eth0 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytesCopy the code

The -i option of the tcpdump command specifies the network adapter to be sniffed. In this case, we sniff the traffic on each host’s eth0 network adapter.

With everything in place, we executed the homemade tool Sendether on host Ant and sent Bee a text message:

root@ant [~] ➜ sendether -i eth0 -t a2:17:41:bb: CD :98 -t 0x0900 -d 'Hello, world! 'Copy the code

Sendether is a homemade command for sending Ethernet frames. In the command, -i specifies the sending network adapter, -t specifies the destination address, -t specifies the data type, and -d specifies the data to be sent. We’ll explain how Sendether encapsulates and sends Ethernet frames in a later programming session.

We immediately see that the tcpdump on the host BEE catches an Ethernet frame, which is hello, World! :

root@bee [~] ➜ tcpdump -ni eth0 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), Capture size 262144 bytes 16:37:27.254658 32:90:b9:9f:35:56 > A2:17:41 :bb: CD :98, etherType Unknown (0x0900), length 27: 0x0000: 6865 6c6c 6f2c 2077 6f72 6c64 21 hello,.world!Copy the code

Note that the host CICada also receives this frame, which matches the hub’s behavior:

root@cicada [~] ➜ tcpdump -ni eth0 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), Capture size 262144 bytes 16:37:27.254624 32:90:b9:9f:35:56 > A2:17:41 :bb: CD :98, etherType Unknown (0x0900), length 27: 0x0000: 6865 6c6c 6f2c 2077 6f72 6c64 21 hello,.world!Copy the code

Since this frame is not destined for a host other than CICADA, the CICADA protocol stack will discard it.

Experiment 2: Observe the Ethernet switch

In this experiment, three Linux hosts are connected to a switch to observe the working behavior of the switch. The network topology is shown as follows:

The experimental environment is also provided by docker container, which can be opened by one click by executing the following command:

docker run --name switch-lab --rm -it --privileged --cap-add=NET_ADMIN --cap-add=SYS_ADMIN -v /data -h switch Fasionchan/netbox: 0.5 bash/script/switch - lab. ShCopy the code

After the experiment environment is started, you can see four Windows divided by TMUx commands, representing three hosts and switches respectively.

To facilitate the observation of the learning process of switch MAC addresses, we set a well-defined MAC address for each host:

The host The network card The MAC address Switch port
ant eth0 40:aa:aa:aa:aa:aa 1
bee eth0 40:bb:bb:bb:bb:bb 2
cicada eth0 40:cc:cc:cc:cc:cc 3

The switch in the experimental environment is simulated by a Bridge virtual device named Switch0:

root@switch [~] ➜ IP link show switch0 4: switch0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 4a:9e:f8:3c:75:40 brd ff:ff:ff:ff:ff:ffCopy the code

Run the BRCTL command to view the current MAC address table of the switch.

root@switch [~] ➜ BRCTL showmacs switch0 Port no MAC addr is local? Ageing Timer 3 4A: 9E: F8 :3c:75:40 YES 0.00 3 4A: 9E: F8 :3c:75:40 Yes 0.00 2 6A :64:44:0 D: D1:55 Yes 0.00 2 6A :64:44:0 D: D1:55 Yes 0.00 1 BE :24:47: BD: F2:52 YES 0.00 1 BE :24:47: BD: F2:52 Yes 0.00 1 BE :24:47: BD: F2:52 Yes 0.00Copy the code

Alas, there Why does the MAC address table already have some entries? We haven’t sent data to any host yet, so the address list should be empty.

In fact, these MAC addresses are the switch’s own. The VALUE of the IS local column is YES. If you filter out the records with the value yes, you can confirm that the MAC address table is indeed empty (no addresses have been learned yet) :

Root @ switch [~] ➜ BRCTL showmacs switch0 | grep -v yes port no MAC addr is local? ageing timerCopy the code

Now we send an Ethernet frame to host BEE on host ANT to observe switch behavior. To start, we run tcpdump on host BEE and CICada to sniff out network traffic.

root@bee [~] ➜ tcpdump -ni eth0Copy the code
root@cicada [~] ➜ tcpdump -ni eth0Copy the code
root@ant [~] ➜ sendether -i eth0 -t 40:bb:bb:bb:bb:bb -d 'Hello, bee! 'Copy the code

After this frame is successfully sent, we observe it on both host BEE and CICada. The reason is that the switch has not yet learned the MAC address of the host BEE and can only forward this frame to all other ports, so CICADA will also receive it.

root@bee [~] ➜ tcpdump -ni eth0 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), Capture size 262144 bytes 16:40:34.437330 40: AA :aa:aa:aa: AA > 40:bb:bb:bb:bb:bb :bb, etherType Unknown (0x0900), Length 25: 0x0000: 6865 6c6c 6f2c 2062 6565 21 hello,.bee!Copy the code
root@cicada [~] ➜ tcpdump -ni eth0 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), Capture size 262144 bytes 16:40:34.437152 40: AA :aa:aa:aa: AA > 40:bb:bb:bb:bb:bb :bb, etherType Unknown (0x0900), Length 25: 0x0000: 6865 6c6c 6f2c 2062 6565 21 hello,.bee!Copy the code

The switch receives Ethernet frames from the host Ant on port 0 with the source address 40: AA: AA :aa:aa: AA, and knows that future frames sent to this address should be forwarded to port 0. In this way, the switch cleverly learns the host Ant’s MAC address:

Root @ switch [~] ➜ BRCTL showmacs switch0 | grep -v yes port no MAC addr is local? Ageing Timer 1 40: AA: AA: AA: AA: AA No 1.97Copy the code

Next, we reply to Ant at host Bee with a message:

root@bee [~] ➜ sendether -i eth0 -t 40:aa:aa:aa:aa:aa -d 'how are you? 'Copy the code

Since the switch has learned ant’s address, it knows that frames going to 40: AA: AA: AA: AA: AA should be forwarded to port 0. The CICada host on port 3 will not receive this frame.

Similarly, during this process, the switch learns the MAC address of host BEE 40:bb:bb:bb:bb:bb:

Root @ switch [~] ➜ BRCTL showmacs switch0 | grep -v yes port no MAC addr is local? Ageing Timer 1 40: AA: AA: AA: AA: AA: AA no 60.17 2 40: BB: BB: BB: BB: BB: BB No 50.14Copy the code

If ant sends bee any more data, Cicada will not receive it either:

root@ant [~] ➜ sendether -i eth0 -t 40:bb:bb:bb:bb:bb -d 'fine, thank you! 'Copy the code

[Xiaocai Network] series of articles first published in the public number [Xiaocai programming], please pay attention to: