So guys, now we will going to discuss that how kernel space will going to send data or reply back to
the user space.
So first of all, the kernel space must send data back to the user space only when the user space has
specified the acknowledgment flag in the Netlink message header flags.
By specifying the acknowledgement flag.
The user space application is actually telling the kernel space that hey kernel space, please reply
me with the acknowledgement that you have actually received my message.
Right.
So it is the reason that we are checking and we will reply back to the user space only when this acknowledgment
flag is set in the flag field of this netlink message header.
Now, in order to send a reply to the user space, we would need a memory in order to store a reply
message.
So let us take a character array of size 256 bytes.
We are assuming that the reply which kernel space will send back to the user space do not exceed 256
bytes.
So let us initialize this array using memset function.
So let us now prepare a message which kernel space we are going to send back to the user space.
Right.
So for that we can use s and printf function in order to prepare a formatted string with kernel space
would send to the user space as a reply.
So you can see that kernel space is telling the user space that the message from process percentage,
D percentage D here means the port ID of the user space application has been processed by the kernel.
So it is this string which the kernel space would going to send back to the user space as a reply.
Now that in the buffer kernel reply we already have a message which is to be sent back to the user space.
Now the next thing is to discuss the steps regarding how kernel space can send already available data
to the user space via netlink socket.
So remember, the data is exchanged between the user space and kernel space in the form of socket buffers.
So it is for this reason we will take a pointer to the socket buffer called as KB out.
It.
It is this socket buffer which will be eventually sent out by the kernel space to the user space.
Now as the next step, using the Netlink message, new API, which is provided by the Linux kernel,
we will going to prepare a new socket buffer.
So this API that is netlink message new returns a pointer to the socket buffer.
Right.
And as a first argument to this API, we are passing the size of the message which the kernel space
is willing to send to the user space.
So here we will pass the size of the buffer which we have taken as a local memory.
The second argument you can always pass as zero.
So now we have a pointer to the socket buffer in which in which there is space as much as equal to the
size of this kernel reply, which is 256 bytes.
And this socket buffer can carry a total of 256 bytes of data back to the user space.
Now, the next thing that we need to do is to prepare a message which is eventually to be shipped back
to the user space.
And we already know that the message which needs to go to the user space must have netlink message header
followed by the payload, right.
So for that we will use a new API called Netlink message port.
The first argument to this API is the socket buffer which we have already created in the previous line.
Right.
And we already know that in this SCB out there is already a memory created whose size equal to the size
of this kernel reply array, which is 256 bytes.
So netlink message put function.
Use the memory which we have already created inside the socket buffer and use the portion of that memory
as a netlink message header.
The rest of the members which we have passed to this function are used to populate the fields of that
netlink message header.
Right.
So the first argument is the port ID, which is a member present in the Netlink message header.
Now in this case the sender of the message is the Linux kernel and therefore the port ID is always zero.
The second argument is the sequence number.
The kernel space must send back the message to the user space with the same sequence number with which
the message came from the user space to the kernel space.
Right.
And now there is a netlink message type field in the netlink message header.
We are filling that field with the standard Netlink message type called Netlink message done right.
And then the second last argument is the size of the data which kernel space is sending to the user
space.
In this case, though, the size of the data we are sending is the length of this string.
But anyways, we are passing the size of the array, which is 256 bytes.
And finally the last argument is the flag field of the Netlink message header, which you can for now
set it to zero, right?
So the return value of this netlink message put function is a pointer to the netlink message header.
Right.
Now remember we have prepared the netlink message header completely and this netlink message header
is present inside this socket buffer skb out and the fields of this netlink message header has been
populated, but still we have not yet appended the payload to this netlink message header.
So finally our Linux kernel module can send the data back to the user space using the netlink message.
Unicast.
The first argument to this API is the netlink socket which we have already created in the kernel space.
The second argument is a pointer to the socket buffer which encodes the netlink message header, followed
by the payload to be sent to the user space.
And the third field is the user space applications process ID to which this Linux kernel module is replying
via netlink sockets.
So you can see that that the third argument helps the kernel space to uniquely find out that which user
space application.
The kernel space is replying to.
There could be many or several user space applications running at the same time in the user space.
In case if this netlink message unicast API fails for some reason it returns a negative value.
Right?
And finally, as the last step, we can test the value which is returned by the Netlink message unicast
API that if this API returns the value which is less than zero, it means that the sand of the data
from kernel space to user space has been failed for some reason.
So if so happens then it is our responsibility to free up the dynamic memory allocations if our Linux
kernel module has done any.
So you can see that netlink message new API return a pointer to the socket buffer.
So internally this API does the dynamic memory allocations for the socket buffer.
So we need to free that particular socket buffer.
In this case, the API to free the socket buffer is the free SKB, right.
However, if the netlink message unicast API returns a positive value, it means that the sand of the
message from the kernel space to the user space has been successful and in this case, this socket buffer
internally will be consumed or freed by the kernel.
So in that case you don't have to explicitly because it will be already freed internally in the API.
Netlink message unicast.
So with this we complete all the steps regarding how our Linux kernel module can receive a data from
the user space as well as can send the reply back to the user space.
But the problem here is that we cannot really test our Linux kernel module whether it's working fine
or not until we write a userspace application which will actually send the data to the kernel space.
Unless we have a application which can send the data to the kernel space.
More specifically saying to our Linux kernel module, we cannot really see all this code in action.
So in the next few lecture videos we will discuss how to write userspace application which can send
and receive the data with the Linux kernel module sitting in the kernel space via netlink sockets.
Once we shall be finished with writing userspace application, then we will test both Linux kernel module
and userspace application and see whether they are able to exchange data with each other or not.