Saturday, September 26, 2020

Message Queue - message types reception

Consider this the extension of the previous post on Message Queue.  We will see how we can retrieve messages of different types.

Write2.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>

struct msgbuf {
	long mtype;
	char mtext[20];
} mymsg;

int main()
{
	key_t key;
	int msgid;
	
	key=ftok("dummy.txt",65);
	msgid = msgget(key,0666 | IPC_CREAT);
	printf("Key - %x ;MessageId - %d \n",key,msgid);

	mymsg.mtype = 1;	
	strcpy(mymsg.mtext,"its my world 1 \0");
	msgsnd(msgid,&mymsg,strlen(mymsg.mtext),0);	
	printf("Sent Type: %d Data: %s\n",mymsg.mtype,mymsg.mtext);

	mymsg.mtype = 2;	
	strcpy(mymsg.mtext,"its my world 2 \0");
	msgsnd(msgid,&mymsg,strlen(mymsg.mtext),0);	
	printf("Sent Type: %d Data: %s\n",mymsg.mtype,mymsg.mtext);
	
	mymsg.mtype = 3;	
	strcpy(mymsg.mtext,"its my world 3 \0");
	msgsnd(msgid,&mymsg,strlen(mymsg.mtext),0);	
	printf("Sent Type: %d Data: %s\n",mymsg.mtype,mymsg.mtext);
	
	mymsg.mtype = 4;	
	strcpy(mymsg.mtext,"its my world 4 \0");
	msgsnd(msgid,&mymsg,strlen(mymsg.mtext),0);	
	printf("Sent Type: %d Data: %s\n",mymsg.mtype,mymsg.mtext);
	
	return 0;
}

We have created message queue, and passing 4 messages of different types 1,2,3 and 4.

Read2.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>

struct msgbuf {
	long mtype;
	char mtext[20];
} mymsg;

int main(int argc, char *argv[])
{
	key_t key;
	int msgid;
	int type;
	type = atoi(argv[1]);

	key=ftok("dummy.txt",65);
	msgid=msgget(key,0644);
	printf("Key - %x ;MessageId - %d \n",key,msgid);
	
	while (1)
	{			
		msgrcv(msgid,&mymsg,sizeof(mymsg),type,IPC_NOWAIT);
		if (errno == ENOMSG) {
			printf("No messages\n");
			break;
		} else {
			printf("Received Data,%s\n",mymsg.mtext);
			printf("Received Data type, %d\n\n",mymsg.mtype);
		}
	}
	return 0;
}
  • Line 16 - Passing the 'message type' as command line argument
  • Line 22 - We run the while loop to receive all the messages available with the mentioned message type.
  • Line 24 - The last argument IPC_NOWAIT is used to instruct 'msgrcv' to return immediately if there is no message present in queue.  'errno' will be set with 'ENOMSG' when this happens.

Demonstration

For different values of msgtypes, the msgrcv behave accordingly

Positive: Picks the first message in the queue corresponding to this type

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[root@msgq]# ./write2
Key - 41014da0 ;MessageId - 327680
Sent Type: 1 Data: its my world 1
Sent Type: 2 Data: its my world 2
Sent Type: 3 Data: its my world 3
Sent Type: 4 Data: its my world 4

[root@msgq]# ./read2 3
Key - 41014da0 ;MessageId - 327680
Received Data,its my world 3
Received Data type, 3

No messages

[root@msgq]# ./read2 3
Key - 41014da0 ;MessageId - 327680
No messages

[root@msgq]# ./read2 2
Key - 41014da0 ;MessageId - 327680
Received Data,its my world 2
Received Data type, 2

No messages

[root@msgq]# ./read2 4
Key - 41014da0 ;MessageId - 327680
Received Data,its my world 4
Received Data type, 4

No messages
  • Line 1-6 - Populating 4 types of messages in the message queue
  • Line 8 - Receive message type 3. Successful
  • Line 15 - Receive message type 3.  No message present
  • Line 19 - Receive message type 2. Successful
  • Line 26 - Receive message type 4. Successful
Lets clear the queue using 'ipcrm -a' and proceed to next type

Zero: Reads the first receive message in the whole message queue, irrespective of the type

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@msgq]# ./write2
Key - 41014da0 ;MessageId - 360448
Sent Type: 1 Data: its my world 1
Sent Type: 2 Data: its my world 2
Sent Type: 3 Data: its my world 3
Sent Type: 4 Data: its my world 4

[root@msgq]# ./read2 0
Key - 41014da0 ;MessageId - 360448
Received Data,its my world 1
Received Data type, 1

Received Data,its my world 2
Received Data type, 2

Received Data,its my world 3
Received Data type, 3

Received Data,its my world 4
Received Data type, 4

No messages
  • Line 1-6 - Populating messages of different type
  • Line 8 - Passing the value of type 0
  • Line 10-20 - Receiving the messages 1, 2, 3, 4 in the same order as in lines 1-6
Negative: Receives all the messages belonging to the types less than the absolute value of the number passed in fifo order

 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[root@msgq]# ./write2
Key - 41014da0 ;MessageId - 360448
Sent Type: 1 Data: its my world 1
Sent Type: 2 Data: its my world 2
Sent Type: 3 Data: its my world 3
Sent Type: 4 Data: its my world 4

[root@msgq]# ./read2 -2
Key - 41014da0 ;MessageId - 360448
Received Data,its my world 1
Received Data type, 1

Received Data,its my world 2
Received Data type, 2

No messages

[root@msgq]# ipcrm -a

[root@msgq]# ./write2
Key - 41014da0 ;MessageId - 393216
Sent Type: 1 Data: its my world 1
Sent Type: 2 Data: its my world 2
Sent Type: 3 Data: its my world 3
Sent Type: 4 Data: its my world 4

[root@msgq]# ./read2 -3
Key - 41014da0 ;MessageId - 393216
Received Data,its my world 1
Received Data type, 1

Received Data,its my world 2
Received Data type, 2

Received Data,its my world 3
Received Data type, 3

No messages
  • Line 1-6 - Populating messages of different types
  • Line 8 - Receiving the type '-2', meaning retrieve all messages less than type 2 in FIFO order
  • Line 18 - Clearing the message queue
  • Line 20-25 - Populating messages of different types
  • Line 27 - Receiving the type '-3', meaning retrieve all messages less than type 3 in  FIFO order

Message Queue - Basic

 Today, we see the message queues.  The advantages is available everywhere on the internet.  Summary is one process can communicate with another process.  Better picture is available in this link:

https://www.tutorialspoint.com/inter_process_communication/images/multiple_message_queue.jpg

Here we have two programs 'write.c' and 'read1.c'.  Write.c will write a message into message queue of type 1.  It will be taken by read1.c.

Write.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>

struct msgbuf {
	long mtype;
	char mtext[20];
}mymsg;

int main()
{
	key_t key;
	int msgid;
	
	key=ftok("dummy.txt",65);
	msgid = msgget(key,0666 | IPC_CREAT);
	printf("Key - %x ;MessageId - %d \n",key,msgid);

	mymsg.mtype = 1;	
	strcpy(mymsg.mtext,"its my world 1 \0");
	
	msgsnd(msgid,&mymsg,strlen(mymsg.mtext),0);	
	
	printf("Sent Data\n");

	return 0;
}
  • Line 6 - This is the typical template of message used in message queues.  First long will be message type.  Rest of it is message.  It can be further defined as any data type.
  • Line 16 - We need a unique key for creating a msgq.  We use 'ftok' command that takes in two arguments. File that the process can read and any character.  Retriever process should also use the same arguments and create the key.
  • Line 17 - 'msgget' creates a message queue(because we use IPC_CREAT mask) with key from 'ftok' and some permissions.  It gives message queue identifier, just like file identifier to communicate
  • Line 20-21 - Populate the message with message type '1' and the text.
  • Line 23 - 'msgsnd' to send the message to queue to let others take it.  Arguments will be message identifier, Address of message, size of message(excluding the 'long' type)

Read1.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>

struct msgbuf {
	long mtype;
	char mtext[20];
} mymsg;

int main()
{
	key_t key;
	int msgid;
	
	key=ftok("dummy.txt",65);
	msgid=msgget(key,0644);
	printf("Key - %x ;MessageId - %d \n",key,msgid);
	
	msgrcv(msgid,&mymsg,sizeof(mymsg),1,0);
	printf("Received Data,%s\n",mymsg.mtext);
	printf("Received Data type, %d\n",mymsg.mtype);
	
	msgctl(msgid,IPC_RMID,NULL);
	return 0;
}
  • Line 5-8 - Same as in write.c
  • Line 15 - To 'ftok' we pass the same arguments as in write.c.
  • Line 16 - 'msgget' to get message identifier.  We do not use IPC_CREAT as message queue already created by write.c
  • Line 19 - 'msgrcv' to read the message into mymsg.  4th argument is message type that we wish to read.
  • Line 23 - 'msgctl' to delete the memory of message queue.

Demonstrate

Lets take the programs for a ride

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
[root@msgq]# gcc write.c -o write
[root@msgq]# ./write
Key - 41014da0 ;MessageId - 327680
Sent Data
[root@msgq]# ipcs

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages
0x41014da0 327680     root       666        15           1

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x00000000 131072     root       600        393216     2          dest
0x00000000 262146     root       600        524288     2          dest

------ Semaphore Arrays --------
key        semid      owner      perms      nsems

[root@svtap01end1 msgq]#

We have sent the message to message queue. 'ipcs' is the linux command that shows the details of message queue. 'ipcrm -a' is one of the commands that will delete all the details of the shared memory listed here.  We haven't used it though.  In another terminal or the same terminal lets run read1.c.

1
2
3
4
5
[root@msgq]# gcc read1.c -o read1
[root@msgq]# ./read1
Key - 41014da0 ;MessageId - 294912
Received Data,its my world 1
Received Data type, 1

You see that the message 'its my world 1' is received by read1.c

Tuesday, September 8, 2020

Native VLAN - Demo

 Usually, for a multi-VLAN network the PCs are connected to 'access' ports of the switch.  Instead of 'access' port, we use the combination of 'trunk' port and 'native-vlan'.

Trunk port - Port in switch where VLAN-tagged packets will pass through.
Native VLAN - Packets passing through the port that belongs to Native VLAN Id will have no-VLAN tagging.

Steps usually will be

  1. Create VLANs in the switch that will be used.(vlan x)
  2. Assign vlan id as Native VLAN to the port(switchport trunk native vlan x)
  3. Allow the same vlan id in the port(switchport trunk allowed vlan x)
  4. If there is a switch on the other side of the link, it should also have same native vlan id.  Else port will be blocked by STP.
We use the following topology:


VL20-1 and VL20-2 are separated by series of switches.  VL20-1, connected to Trunk port having native vlan 20.  VL20-2 is connected to access port of vlan 20.

VL30-1 and VL30-2, belonging to VLAN 30, separted by couple of switches.  VL30-1, connected to Trunk port having native vlan 30.  VL30-2 is connected to access port of vlan 30.

Lets go through the configurations of switches one by one. Starting with 

Switch4

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
Switch#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
Switch(config)#vlan 20
Switch(config-vlan)#ex
Switch(config)#vlan 30
Switch(config-vlan)#ex
Switch(config)#int fa0/2
Switch(config-if)#switchport mode access 
Switch(config-if)#switchport access vlan 20
Switch(config-if)#no shut
Switch(config-if)#ex
Switch(config)#int fa0/1
Switch(config-if)#switchport mode access
Switch(config-if)#switchport access vlan 30
Switch(config-if)#ex
Switch(config)#int fa0/3
Switch(config-if)#switchport trunk encapsulation dot1q
Switch(config-if)#switchport mode trunk
Switch(config-if)#switchport trunk allowed vlan 20,30
  • Creating VLAN (Lines 3 to 6)
  • Making Ports fa0/2 and fa0/1 as access ports to vlan 20 and 30 respectively(Lines 8 to 15)
  • Making Port fa0/3 as Trunk port allowing vlans 20 and 30(Lines 16 to 19)

Switch6

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
Switch(config)#vlan 20
Switch(config-vlan)#ex
Switch(config)#vlan 30
Switch(config-vlan)#ex
Switch(config)#int fa0/2
Switch(config-if)#switchport trunk encapsulation dot1q
Switch(config-if)#switchport mode trunk
Switch(config-if)#switchport trunk allowed vlan 20
Switch(config-if)#ex
Switch(config)#int fa0/1
Switch(config-if)#switchport trunk encapsulation dot1q
Switch(config-if)#switchport mode trunk
Switch(config-if)#switchport trunk allowed vlan 20,30
Switch(config-if)#ex
Switch(config)#int fa0/3
Switch(config-if)#switchport trunk encapsulation dot1q
Switch(config-if)#switchport mode trunk
Switch(config-if)#switchport trunk native vlan 30
Switch(config-if)#switchport trunk allowed vlan 30
  • Create VLANs 20 and 30, as both are used in this switch(Lines 1 to 4)
  • Make fa0/2 as Trunk to pass vlan 20 from Switch5(lines 5 to 9)
  • Make fa0/1 as Trunk to pass vlans 20 and 30 to and from Switch4 (Lines 10 to 14)
  • Make fa0/3 as Trunk, to allow vlan30 as Native vlan(equal to access port) (Lines 15 to 19)

Switch5

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Switch#conf t
Switch(config)#vlan 20
Switch(config-vlan)#ex
Switch(config)#int fa0/3
Switch(config-if)#switchport trunk encapsulation dot1q
Switch(config-if)#switchport mode trunk
Switch(config-if)#switchport trunk allowed vlan 20
Switch(config-if)#ex
Switch(config)#int fa0/1
Switch(config-if)#switchport trunk encapsulation dot1q
Switch(config-if)#switchport mode trunk
Switch(config-if)#switchport trunk allowed vlan 20
Switch(config-if)#switchport trunk native vlan 20
Switch(config-if)#ex
  • Create VLAN 20, as it is the only VLAN used (Lines 2 to 3)
  • Make fa0/3 as Trunk to allow vlan 20 to other switches(Lines 4 to 8)
  • Make fa0/1 as Trunk to allow vlan 20 as Native vlan id(equal to access port) (Lines 9 to 14)

Testing

  • Configured VL20-1 and VL20-2 with IP address as 20.0.0.20/8 and 20.0.0.2/8 respectively.  Ping is successful.
  • Configured VL30-1 and VL30-2 with IP addresses 30.0.0.30/8 and 30.0.0.3/8 respectively.  Ping is successful