rte_mbuf in dpdk 18.08 doesnt have struct rte_pktmbuf pkt - c

I am getting the below compilation error after upgrading to dpdk 18.08 version.
error: ‘struct rte_mbuf’ has no member named ‘pkt’
m->pkt.data = ((char*)m->pkt.data - (BTG_IP_VHL_HL(ip->version_ihl) << 2));
^
As per the documentation rte_mbuf struct no longer has packet message buffer struct rte_pktmbuf pkt which inturn holds void* data which contains start address of data in segment buffer.
struct rte_mbuf {
.
.
.
union {
struct rte_ctrlmbuf ctrl;
struct rte_pktmbuf pkt;
};
}
struct rte_pktmbuf {
/* valid for any segment */
struct rte_mbuf *next;
void* data; /**< Start address of data in segment buffer. */
Please let me know which other field of rte_mbuf struct can be used with dpdk 18.08 version which means start address of data in the packet message buffer so as to resolve this compilation error.Thanks in advance.

It's rte_pktmbuf_mtod(m, t) macro.
A macro that points to the start of the data in the mbuf.
The returned pointer is cast to type t. Before using this function, the user must ensure that the first segment is large enough to accommodate its data.
Source: DPDK API
Update:
To prepend a packet buffer with some data, there is a dedicated function for that: rte_pktmbuf_prepend() (and here is DPDK documentation)
It's hard to be 100% sure without the context of your old code, but it looks like this fragment must be rewritten to:
rte_pktmbuf_prepend(m,
BTG_IP_VHL_HL(ip->version_ihl) << 2);

Related

How do I obtain rte_pci_device details from rte_device in dpdk 18.08

I want to compare the detected device information ( dev_info of type struct rte_eth_dev_info dev_info ) associated with each port with configured pci device address details ( of type struct rte_pci_addr pciaddr).
for (port = 0; port < nb_sys_ports; port++) {
rte_eth_dev_info_get(port, &dev_info);
}
But In struct struct rte_eth_dev_info, field rte_pci_device *pci_dev has been replaced with field struct rte_device *device.
So how do I obtain the rte_pci_device details from rte_device.
DPDK supports now non-PCI buses, so it's a bit more complicated. But still, there are few examples. Here is a snippet from the Ethtool:
struct rte_pci_device *pci_dev;
rte_eth_dev_info_get(port_id, &dev_info);
if (dev_info.device)
bus = rte_bus_find_by_device(dev_info.device);
if (bus && !strcmp(bus->name, "pci")) {
pci_dev = RTE_DEV_TO_PCI(dev_info.device);
snprintf(drvinfo->bus_info, sizeof(drvinfo->bus_info),
"%04x:%02x:%02x.%x",
pci_dev->addr.domain, pci_dev->addr.bus,
pci_dev->addr.devid, pci_dev->addr.function);
}
Basically, we get the bus of the DPDK port. If it's a PCI, it's safe to use RTE_DEV_TO_PCI() macro. The macro returns a pointer to struct rte_pci_device, which has the PCI address.

Adding flash before erasing and writing into flash

In a program to erase and write into flash, I donot understand the lines
struct kinetis_flash *kf = calloc(1, sizeof(*kf));
struct target_flash *f = &kf->f;
from the below section of the code. And the whole program can be found at https://github.com/blacksphere/blackmagic/blob/master/src/target/kinetis.c
struct kinetis_flash {
struct target_flash f;
uint8_t write_len;
};
static void kl_gen_add_flash(target *t, uint32_t addr, size_t length,
size_t erasesize, size_t write_len)
{
struct kinetis_flash *kf = calloc(1, sizeof(*kf));
struct target_flash *f = &kf->f;
f->start = addr;
f->length = length;
f->blocksize = erasesize;
f->erase = kl_gen_flash_erase;
f->write = kl_gen_flash_write;
f->done = kl_gen_flash_done;
f->erased = 0xff;
kf->write_len = write_len;
target_add_flash(t, f);
}
It would be great if someone helps me understanding above tw lines, thanks in advance.Many targets for example KL25, K22, K64 can be accordingly used what i understood from the project. Are those two lines storing target specific specifications for flash?
In general we donot need to allocate any space for flash right using calloc or malloc like we do it for RAM.
The code in question extends GDB, allowing it to use various JTAG or Serial Wire interfaces to program and debug certain ARM devices. Identifying the attached devices flash device is a time consuming and disruptive (as-in can't run device code) task, so you only want to do it once, hence the local RAM allocation for storing the type and current state of the attached flash.
This line
struct kinetis_flash *kf = calloc(1, sizeof(*kf));
is a dynamic allocation of a struct kinetis_flash somewhere in RAM. It's probably used for holding information about a flash device present in the system.
This line
struct target_flash *f = &kf->f;
makes f point to the struct target_flash - named f - inside struct kinetis_flash so that you can write to it using f->some_var = ...
So the whole function is simply creating and initializing an object of type struct kinetis_flash
Though the code is correct, it's (IMO) a bit confusing to have a variable f pointing to f inside a struct. Perhaps a name like ptr_f would be more clear.
Also notice that the code is equivalent to:
static void kl_gen_add_flash(target *t, uint32_t addr, size_t length,
size_t erasesize, size_t write_len)
{
struct kinetis_flash *kf = calloc(1, sizeof(*kf));
kf->f.start = addr;
kf->f.length = length;
...
}

Initializing, constructing and converting struct to byte array causes misalignment

I am trying to design a data structure (I have made it much shorter to save space here but I think you get the idea) to be used for byte level communication:
/* PACKET.H */
#define CM_HEADER_SIZE 3
#define CM_DATA_SIZE 16
#define CM_FOOTER_SIZE 3
#define CM_PACKET_SIZE (CM_HEADER_SIZE + CM_DATA_SIZE + CM_FOOTER_SIZE)
// + some other definitions
typedef struct cm_header{
uint8_t PacketStart; //Start Indicator 0x5B [
uint8_t DeviceId; //ID Of the device which is sending
uint8_t PacketType;
} CM_Header;
typedef struct cm_footer {
uint16_t DataCrc; //CRC of the 'Data' part of CM_Packet
uint8_t PacketEnd; //should be 0X5D or ]
} CM_Footer;
//Here I am trying to conver a few u8[4] tp u32 (4*u32 = 16 byte, hence data size)
typedef struct cm_data {
union {
struct{
uint8_t Value_0_0:2;
uint8_t Value_0_1:2;
uint8_t Value_0_2:2;
uint8_t Value_0_3:2;
};
uint32_t Value_0;
};
//same thing for Value_1, 2 and 3
} CM_Data;
typedef struct cm_packet {
CM_Header Header;
CM_Data Data;
CM_Footer Footer;
} CM_Packet;
typedef struct cm_inittypedef{
uint8_t DeviceId;
CM_Packet Packet;
} CM_InitTypeDef;
typedef struct cm_appendresult{
uint8_t Result;
uint8_t Reason;
} CM_AppendResult;
extern CM_InitTypeDef cmHandler;
The goal here is to make reliable structure for transmitting data over USB interface. At the end the CM_Packet should be converted to an uint8_t array and be given to data transmit register of an mcu (stm32).
In the main.c file I try to init the structure as well as some other stuff related to this packet:
/* MAIN.C */
uint8_t packet[CM_PACKET_SIZE];
int main(void) {
//use the extern defined in packet.h to init the struct
cmHandler.DeviceId = 0x01; //assign device id
CM_Init(&cmHandler); //construct the handler
//rest of stuff
while(1) {
CM_GetPacket(&cmHandler, (uint8_t*)packet);
CDC_Transmit_FS(&packet, CM_PACKET_SIZE);
}
}
And here is the implementation of packet.h which screws up everything so bad. I added the packet[CM_PACKET_SIZE] to watch but it is like it is just being generated randomly. Sometimes by pure luck I can see in this array some of the values that I am interested in! but it is like 1% of the time!
/* PACKET.C */
CM_InitTypeDef cmHandler;
void CM_Init(CM_InitTypeDef *cm_initer) {
cmHandler.DeviceId = cm_initer->DeviceId;
static CM_Packet cmPacket;
cmPacket.Header.DeviceId = cm_initer->DeviceId;
cmPacket.Header.PacketStart = CM_START;
cmPacket.Footer.PacketEnd = CM_END;
cm_initer->Packet = cmPacket;
}
CM_AppendResult CM_AppendData(CM_InitTypeDef *handler, uint8_t identifier,
uint8_t *data){
CM_AppendResult result;
switch(identifier){
case CM_VALUE_0:
handler->Packet.Data.Value_0_0 = data[0];
handler->Packet.Data.Value_0_1 = data[1];
handler->Packet.Data.Value_0_2 = data[2];
handler->Packet.Data.Value_0_3 = data[3];
break;
//Also cases for CM_VALUE_0, 1 , 2
//to build up the CM_Data sturct of CM_Packet
default:
result.Result = CM_APPEND_FAILURE;
result.Reason = CM_APPEND_CASE_ERROR;
return result;
break;
}
result.Result = CM_APPEND_SUCCESS;
result.Reason = 0x00;
return result;
}
void CM_GetPacket(CM_InitTypeDef *handler, uint8_t *packet){
//copy the whole struct in the given buffer and later send it to USB host
memcpy(packet, &handler->Packet, sizeof(CM_PACKET_SIZE));
}
So, the problem is this code gives me 99% of the time random stuff. It never has the CM_START which is the start indicator of packet to the value I want to. But most of the time it has the CM_END byte correctly! I got really confused and cant find out the reason. Being working on an embedded platform which is hard to debugg I am kind of lost here...
If you transfer data to another (different) architecture, do not just pass a structure as a blob. That is the way to hell: endianess, alignment, padding bytes, etc. all can (and likely will) cause trouble.
Better serialize the struct in a conforming way, possily using some interpreted control stream so you do not have to write every field out manually. (But still use standard functions to generate that stream).
Some areas of potential or likely trouble:
CM_Footer: The second field might very well start at a 32 or 64 bit boundary, so the preceeding field will be followed by padding. Also, the end of that struct is very likely to be padded by at least 1 bytes on a 32 bit architecture to allow for proper alignment if used in an array (the compiler does not care you if you actually need this). It might even be 8 byte aligned.
CM_Header: Here you likely (not guaranteed) get one uint8_t with 4*2 bits with the ordering not standardized. The field my be followed by 3 unused bytes which are required for the uint32_t interprettion of the union.
How do you guarantee the same endianess (for >uint8_t: high byte first or low byte first?) for host and target?
In general, the structs/unions need not have the same layout for host and target. Even if the same compiler is used, their ABIs may differ, etc. Even if it is the same CPU, there might be other system constraints. Also, for some CPUs, different ABIs (application binary interface) exist.

C structure not getting values filled in after sending through socket

I am trying to send a structure over a socket in TCP. However when I receive the data at the structure I am getting an empty structure.
This is the structure being sent by the client:
typedef struct NwInfo
{
void *pvData;
NwTypes e_recv;
}NwInfo;
struct NwInfo test;
test.e_recv = 1;
test.pvData = (void *) &pst; //pst is object of another structure.
int ret =send(sockfd,&test,sizeof(test),0); //ret returns greater than 0
At the server side:
NwInfo *pRecvNwInfo;
pRecvNwInfo = malloc(sizeof(NwInfo));
int nbytes = recv(filedes,pRecvNwInfo,sizeof(NwInfo),0);
//nbytes is the same value as that of ret
struct student *pst;
pst = (struct student *)pRecvNwInfo->pvData;
The pst variable in the server side does not get any data. Could anyone point out the error I am making ?
There is no problem with your Socket Programming.
What you need to look at, is the logic.
Here the Server and Client are two different process, having its own address space.
Your Socket programming is perfectly fine.
For Example:
Client Side :
send(sockfd, &test, sizeof(test), 0)
printf ("Value of test->e_recv = [%d]\n", test.e_recv);
printf ("Value of test->ptr = [%u]\n", test.ptr);
$ ./client 172.16.7.110 56000
Value of test->e_recv = [1]
Value of test->ptr = [3214048236] // Address of some variable in Client address space.
Data Sent!
Server will recieve exactly the same data.
Server Side:
NwInfo *pRecvNwInfo = malloc(sizeof(NwInfo));
int nbytes = recv(filedes, pRecvNwInfo, sizeof(NwInfo), 0);
printf("Value of pRecvNwInfo->e_recv = [%d]\n", pRecvNwInfo->e_recv);
printf("Value of pRecvNwInfo->ptr = [%u]\n", pRecvNwInfo->ptr);
$./server 56000
Here is the message.
Value of pRecvNwInfo->e_recv = [1]
Value of pRecvNwInfo->ptr = [3214048236] // Address received correctly, but it is of client address space
So when you write this:
pst = (struct student *)pRecvNwInfo->pvData;
pst is pointing to the address, which is valid only in client address context.
So accessing it (in server's context) will give you Undefined Behavior, In my case SIGSEGV.
Important Note:
When you send, you are sending the data in the address of test and when you recv it, you are receiving the data in some new container (pRecvNwInfo) with a different address.
How to Rectify this:
Its best to send values and not the address.
Consider the following structure:
typedef struct inner
{
int a;
int b;
}inner_t;
typedef struct outer
{
void *ptr;
int c;
}outer_t;
You may change your Structure definition of outer:
Change the void * to actual data and not address, something like. inner_t var.
send(sockfd, &test, sizeof(test), 0);
Create a temporary structure type (for Sending & Receiving).
/* Temporary Buffer Declaration */
typedef struct temp{
inner_t value_in;
outer_t value_out;
} temp_t;
temp_t to_send;
inner_t buffer_in;
/* Save values instead of address */
memcpy(buffer_in, ptr, sizeof(inner_t));
to_send.value_in = buffer;
to_send.value_out = outer;
/* Send the final structure */
send(sockfd, &to_send, sizeof(temp_t), 0);
These may not be the best practices, I would love to know if there are any better ones.
You need to copy the value of pst in test.pvData member using memcpy. You are just assigning the memory address to test.pvData, value of which wont be available on server side. You can do something like this:
memcpy(test.pvData, &pst, sizeof pst);
Edit: You will also have to give some memory space to pvData instead of just being a pointer.
You cant just use sizeof(test) when sending the buffer since sizeof(test) will hold the size of the struct in the memory and since the data you wish to send is only pointed to by the struct it will NOT be included in that size.
instead,
hold the size of the data you wish to send, and create a stuct that will hold this value in a field and enough space to copy the data to it. then memcpy all the data to the struct and send it as a whole.
Anyhow I suggest you to fill the data directly in a struct you intend to send if you can this will save the memcpy.

alternative to container_of()

I am a newbie trying to code a serial driver(PCI based ) and I don't want to use the container_of() for lack of downward compatibility.The kernel version I may compile the module
would be < 2.6.x so I want to make it compatible with most of the old and new versions.
i want to access the structure member(s) of a serial card driver.the structure is a custom one containing the atomic variable for example - use_count and the related operation on it-- atomic_inc(&serial_card->use_count).I dont want to access them by using the container_of() function which will give me the containing structure
Is there any alternate to container_of() function.If I am not wrong the text LINux device drivers by Allesandro Roubini describes a way on page no 174 | Chapter 6: Advanced Char Driver Operations.
But I am still fixed about how to assign something like struct scull_dev *dev = &scull_s_device.
if the structure itself contains a variable of type struct pc_device *dev,the above statement populates a similar variable and that is assigned to dev,
in my case i have declared a structure and related function as below
struct serial_card
{
unsigned int id; // to identify the each card
//atomic_t use_count; // variable used to check whether the device is already opened or not
wait_queue_head_t rx_queue[64]; // queue in which the process are stored
unsigned int data_ready[64]; // queue in which the process is ready
unsigned int rx_chan; // used by interrupt handler
unsigned int base, len; // holds physical base address , holds the total area ( for each card )
unsigned int *base; // holds virtual address
/*struct cdev cdev; // kernel uses this structure to represent the EACH char device
not using the new method to represent char devices in kernel instead using the old method of register_chrdev();*/
struct pci_dev *device; // pci_dev structure for EACH device.
//struct semaphore sem; //Semaphore needed to handle the co-ordination of processes,use incase need arises
};
static struct serial_card *serial_cards; // pointer to array of structures [ depending on number of cards ],NO_OF_CARDS #defined in header file
static int serialcard_open(struct inode *inode,struct file *filep)
{
//getting the structure details of type struct serialcard,using the pointer inode->i_cdev and field type cdev
//struct serial_card *serial_cards = container_of(inode->i_cdev, struct serial_card, cdev);
// read the current value of use_count
static int Device_Open = 0;
if ( Device_Open ) //Device_Open is static varibale used here for checking the no of times a device is opened
{
printk("cPCIserial: Open attempt rejected\n");
return -EBUSY;
}
Device_Open++;
// using the card so increment use_count
//atomic_inc(&serial_cards->use_count);
//filep->private_data = serial_cards;
return 0;
}
the complete description on page 174 - 175 is as follows
Single-Open Devices
The brute-force way to provide access control is to permit a device to be opened by
only one process at a time (single openness). This technique is best avoided because it
inhibits user ingenuity. A user might want to run different processes on the same
device, one reading status information while the other is writing data. In some cases,
users can get a lot done by running a few simple programs through a shell script, as
long as they can access the device concurrently. In other words, implementing a singleopen
behavior amounts to creating policy, which may get in the way of what your
users want to do. Allowing only a single process to open a device has undesirable properties, but it is also the easiest access control to implement for a device driver, so it’s shown here.
The source code is extracted from a device called scullsingle.
The scullsingle device maintains an atomic_t variable called scull_s_available; that
variable is initialized to a value of one, indicating that the device is indeed available.
The open call decrements and tests scull_s_available and refuses access if somebody
else already has the device open:
static atomic_t scull_s_available = ATOMIC_INIT(1);
static int scull_s_open(struct inode *inode, struct file *filp)
{
struct scull_dev *dev = &scull_s_device; /* device information */
if (! atomic_dec_and_test (&scull_s_available)) {
atomic_inc(&scull_s_available);
return -EBUSY; /* already open */
}
/* then, everything else is copied from the bare scull device */
if ( (filp->f_flags & O_ACCMODE) = = O_WRONLY) {
scull_trim(dev);
filp->private_data = dev;
return 0; /* success */
}
The release call, on the other hand, marks the device as no longer busy:
static int scull_s_release(struct inode *inode, struct file *filp)
{
atomic_inc(&scull_s_available); /* release the device */
return 0;
}
Normally, we recommend that you put the open flag scull_s_available within the
device structure (Scull_Dev here) because, conceptually, it belongs to the device. The
scull driver, however, uses standalone variables to hold the flag so it can use the same
device structure and methods as the bare scull device and minimize code duplication.
Please let me know any alternative for this
thanks and regards
perhaps I am missing the point, but "cotainer_of" is not a function, but a macro. If you have porting concerns, you can safely define it by yourserlf if the system headers don't implement it. Here a basic implementation:
#ifndef container_of
#define container_of(ptr, type, member) \
((type *) \
( ((char *)(ptr)) \
- ((char *)(&((type*)0)->member)) ))
#endif
Or here's the implementation - more accurate - from recent linux headers:
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})
In that code the containerof is used to store and retrieve the correct dev structure easily. The correct structure can be retrieved inside the read and write functions also without accessing to the private_data.
I do not know why you do not want to use private->data and containerof, but you can always retrieve your minor number from the struct file pointer.
int minor=MINOR(filp->f_dentry_d_inode->i__rdev);
then accessing to your multiple devices vector using something like
struct scull_dev* dev = &scull_devices[minor]:
and using it.
You will need to use filp->privatedata to store "per-open" information that you also use in read/write. You will need to decide what to store to ensure that the right information is available.
Probably you want two structures. One "device structure" and one "open structure". The open structure can get dynamically allocated in "open" and stored at private_data. In release, it gets freed. It should have the members such that you can use them in read/write to get access to the data you need.
The device structure is going to be per "card". In your driver init, you probably want to loop on the number of cards and create a new device structure (serial_card) for each. You can make them a static array, or dynamically allocate, it doesn't matter. I would store the minor number in the structure as well. The minor number is chosen by you, so start with 1 and go through #cards. You can reserve "0" for a system level interface, if you want, or just start at 0 for the cards.
In open, you will get the minor number that the user opened. Go through your serial_card list looking for a match. If you don't find it, error out of open. Otherwise, you have your info and can use it to allocate a "open structure", populate it, and store it in filp->private_data.
#Giuseppe Guerrini Some compiler just cannot recognize the linux implementation of container_of.
The basic define is fine, but I wonder if there is any safety or compatibility risk at this implementation:
#ifndef container_of
#define container_of(ptr, type, member) \
((type *) \
( ((char *)(ptr)) \
- ((char *)(&((type*)0)->member)) ))
#endif

Resources