How do I pass structure variables in a packet field? Is there example code?

Categories:
Solution Number:
S20703
Last Modified:
2013-08-20
Issue

How do I pass structure variables in a packet field? Is there example code?

Solution

Following is an overview and example code on how to pass a structure variable as a packet field element. The general code for setting as well as getting the structure element from the packet are described below. OVERVIEWThe basics steps are:1) Allocate the structure object and set its elements2) Set the structure object in a packet using op_pk_<n>fd_set().3) When you need to process the packet, get the structure object using op_pk_<n>fd_get_ptr() or op_pk_nfd_access().4) If you used op_pk_<n>fd_get_ptr() in step 3, you are then responsible for deallocating the structure object.You should dynamically allocate and deallocate structures used in packet fields. [You should not set statically declared structures into packet fields. Attempting to destroy a statically-declared structure (or a state variable) will result in an error.] The structure fields inside packets should be set using op_pk_fd_set_ptr() /op_pk_nfd_set_ptr() with the special parameter format defined for structure type packet fields in Simulation Kernel manual, Pk Package chapter.When a op_pk_nfd_get() / op_pk_fd_get() is called to get this structure, the packet is stripped of this structure and the process that stripped it off the packet is now responsible for destroying the memory allocated to this structure. On the other hand, if a the packet is destroyed before stripping the structure field, then the de-allocation procedure passed to op_pk_fd_set() /op_pk_nfd_set() will destroy the memory allocated to this structure and, in this case, there is no need to remove the structure field and destroy it, before destroying the packet.Note that OPNET releases 5.1.D and newer have a KP, op_pk_<n>fd_access() which allow you to access a structure field within a packet without stripping it off first. [See note at the end of this FAQ.]For additional details about dealing with structures in packets, you can search in the online FAQs for structure. Also, please read in the online documentation Simulation Kernel -> Packet Package -> Named Field Sub-Package -> op_pk_nfd_set (). [Note that op_pk_nfd_set () is documented for the 3 possible formats of op_pk_nfd_set (). Be sure to read the version used for structure fields].EXAMPLE CODEInclude a construct similar to the following code in the process model where the string value needs to be set in the packet: Header block: ------------- typedef struct { int test_number1; double test_number2; } Test_Data_Type; Temporary Variables block: ---------------- Packet* test_pkptr; Packet* copied_pkptr; Test_Data_Type* test_struct_ptr; In a process state edit pad: ---------------------------- /* Create a packet format. Note that this packet format should be */ /* created in the Packet format editor, and must have a field of type */ /* structure with the field name as test_field and a field of */ /* type integer with its name as test_count. */ test_pkptr = op_pk_create_fmt (test_pk_fmt); /* Allocate memory for the structure field to be set in the */ /* packet pointer. */ test_struct_ptr = (Test_Data_Type *) op_prg_mem_alloc (sizeof(Test_Data_Type)); /* Set the fields of the structure. */ test_struct_ptr->test_number1 = 123; test_struct_ptr->test_number2 = 456.789; /* Set a simple integer field into the pkptr. */ op_pk_nfd_set (test_pkptr, test_count, 0); /* Set the structure field in the pkptr. */ op_pk_nfd_set (test_pkptr, test_field, test_struct_ptr, op_prg_mem_copy_create, op_prg_mem_free, sizeof (Test_Data_Type)); /* Send the packet. */ op_pk_send (test_pkptr, 0);The following code convention should be followed in the process model where you are trying to get the structure element from the packet: Header block: ------------- typedef struct { int test_number1; double test_number2; } Test_Data_Type; Temporary Variables block: ---------------- int test_cnt; Packet* obtained_pkptr; Test_Data_Type* test_struct_ptr; In a process state edit pad: ---------------------------- /* Acquire the packet from the incoming stream. */ obtained_pkptr = op_pk_get (0); /* Obtain the relevant info from the pkptr. */ op_pk_nfd_get (obtained_pkptr, test_count, &test_cnt); op_pk_nfd_get (obtained_pkptr, test_field, &test_struct_ptr); /* Print the contents of the structure elements. */ printf (test_count = %dn, test_cnt); printf (test_struct_ptr->test_number1 = %dn, test_struct_ptr->test_number1); printf (test_struct_ptr->test_number2 = %fn, test_struct_ptr->test_number2); /* Deallocate the memory allocated to the structure element. */ op_prg_mem_free (test_struct_ptr);NOTES:1) More advanced users may wish to use deep data structures (where a structure variable contains pointers to other nested structure variables). If you are doing so, you may need to write your own copy and deallocation procedures and use them in op_pk_nfd_set () in place of op_prg_mem_copy_create() and op_prg_mem_free(). For additional details, please read in the online documentation Simulation Kernel -> Packet Package -> Named Field Sub-Package -> op_pk_nfd_set (). 2) Note that for OPNET products version 5.1.D and later, a new kernel procedure, op_pk_<n>fd_access () has been added. When the structure was being retrieved above, in place of the op_pk_nfd_get() function call, the op_pk_nfd_access() function call could have been used. op_pk_nfd_access() does not strip the structure fields when accessing the values (unlike op_pk_nfd_get ()). In this example, op_pk_nfd_access() would get a pointer to the structure object while the packet would still retain a pointer to the same structure object. The packet would still own the structure object. This implies: a) you should not explicitly destroy the structure object. b) when the packet is destroyed, it will destroy the structure object.As an aside, note that if multiple processes use op_pk_nfd_access() to access the structure object from the same packet, each process would be working on the same structure object (potentially affecting each other unintentionally). 3) Alternatively, instead of duplicating the defintion of the Test_Data_Type in each process model's header block, Test_Data_Type could have been defined in a .h file (e.g. test_data_definitions.h) which is then #include'ed in each processes model's header block like so:#include test_date_type_definitionsThis is a better programming practice, and this is the convention used in the OPNET standard models.

Environment

DES Kernel->Process Modeling/Coding

Attachments
NOTICE: Riverbed® product names have changed. Please refer to the Product List for a complete list of product names.
Can't find an answer? Create a case