Skip to content

How to build a packet in GNRC (to be continued)

Michael Richardson edited this page Sep 9, 2021 · 34 revisions

This document briefly describes how to build packet snips and construct a packet in the GNRC network stack of RIOT. Also, it briefly shows the packet structure in GNRC, i.e., how a packet is build by linking up several packet snips.

Build a packet in GNRC (sending packet)

Build a new packet snip

Assuming that you are in a network stack that has 3 layers, as shown below, and you are now at the top layer (LAYER_3) for creating a new packet for sending to another node.

For instance, for creating a new packet snip that has a content of ''AAA'' at layer_3, you can use gnrc_pktbuf_add() function as below:

gnrc_pktsnip_t* pkt;     /* the packet snip pointer */
uint8_t raw_data[3] = {'A', 'A', 'A'};
pkt = gnrc_pktbuf_add(NULL, raw_data, sizeof(raw_data) , GNRC_NETTYPE_LAYER_3);

When you want to create a new packet, you need to set the first input-parameter as NULL; the second and the third input-parameters are the pointer to the data and the size of the data content; the final input-parameter is the network type. The return of the function is the pointer to the packet part that represents the new gnrc_pktsnip_t. Now, the packet is composed of only one packet snip, as shown in the following figure.

Add a packet snip (header) to an existing packet

Assuming that the packet created at LAYER_3 has been pushed to LAYER_2 (i.e., the pointer pkt has been relayed to LAYER_2), and, in case that you are now at LAYER_2 for adding a LAYER_2 header to the packet for continuing constructing the packet. To doing this, you use gnrc_pktbuf_add() as below:

uint8_t ly2head[4] = {'B','B','B','B'};    /* the layer_2 header */ 
pkt = gnrc_pktbuf_add(pkt, ly2head, sizeof(ly2head) , GNRC_NETTYPE_LAYER_2); 

By doing this, the layer_2 header is added/attached to the existing packet, and the packet is now composed of two packet snips, as shown in the following figure.

Now, the pointer of the packet (pkt) is pointing to the new packet snip, since the return of the gnrc_pktbuf_add() function is the pointer to the packet part that represents the new gnrc_pktsnip_t.

Note that, the order of the snips in a packet will be reversed depending on if you send the packet or if you received it. For sending (the packet is pushed from higher layer), the snip order is from (in the network stack) lowest protocol snip to the highest, for receiving the order is from highest snip to the lowest.

For locating the previous packet snip after you have added a new snip, you can simply do:

gnrc_pktsnip_t* previous_snip; /* create a snip pointer for holding the previous snip*/
previous_snip = pkt->next;

Now, previous_snip is pointing to the previous packet snip created by (normally) the upper layer (here, it is layer_3) that has a data content of "AAA".

Similarly, when this packet is further pushed to layer_1, the protocol located at layer_1 may probably use gnrc_pktbuf_add() to add its own header to the packet:

uint8_t ly1head[2] = {'C','C'};  /* the layer_1 header */ 
pkt = gnrc_pktbuf_add(pkt, ly1head, sizeof(ly1head) , GNRC_NETTYPE_LAYER_1); 

then, the complete packet may look like in the following figure.

three snips

When the packet is sent out and if everything is correct, the receiver will receive the packet that has a content of "CCBBBBAAA".

How to add a netif (network interface) header

Assume you have received a packet pushed from upper layer (gnrc_pktsnip_t* pkt), and you want to add a netif header to this packet (if there is no netif header yet) before sending, here is an example for how to do this:

gnrc_netif_hdr_t *nethdr;
uint8_t dst_addr[2];
uint8_t src_addr[2];
uint8_t dst_addr_len=2;
uint8_t src_addr_len=2;

dst_addr[0] = 0x12;  /*assume that your destination short address is 0x1234*/
dst_addr[1] = 0x34;
src_addr[0] = 0x56;  /*assume that your source short address is 0x5678*/
src_addr[1] = 0x78;

pkt = gnrc_pktbuf_add(pkt,NULL,sizeof(gnrc_netif_hdr_t)+src_addr_len+dst_addr_len, GNRC_NETTYPE_NETIF);

nethdr = (gnrc_netif_hdr_t*) pkt->data;

gnrc_netif_hdr_init(nethdr, src_addr_len, dst_addr_len);
gnrc_netif_hdr_set_dst_addr(nethdr, dst_addr, dst_addr_len);
gnrc_netif_hdr_set_src_addr(nethdr, src_addr, src_addr_len);

References

Clone this wiki locally