Project Home
Project Home
Wiki
Wiki
Discussion Forums
Discussions
Project Information
Project Info
Forum Topic - getting mbuf physical address: (6 Items)
   
getting mbuf physical address  
Hi,

I have a problem regarding getting mbuf physical address. In transmission, for example, when got a network packet, I 
added some additional packet descriptor info into the M_LEADINGSPACE,  between m->pkt_dat and m->m_data. I then need to 
get the physical address starting from the packet descriptor in order for DMA operation. My assumption is that the mbuf 
as a whole is in a contiguous buffer, or at least the buffer between m->pkt_data to the end of m->m_data is. Am I 
correct?

Based on my assumption, I used mem_offset64 to get the physical address of the starting point, i.e., m->pkt_data + 
alignment offset. It seems not getting the correct one. I noticed that there is mbuf_phys, but that seems, from the code
, only get the m->m_data physical address, not the one that I need. 

I have a workaround to copy the mbuf into a contiguous buffer. But I fear for the performance impact.

Any suggestions?

Thanks,

Yurong
Re: getting mbuf physical address  

Use M_PREPEND which checks M_LEADINGSPACE and updates m->m_data,
m->m_len and m_pkthdr.len.  You can then use mbuf_phys() correctly.


-seanb

On Tue, Jan 17, 2012 at 11:13:35AM -0500, Yurong Sun wrote:
> Hi,
> 
> I have a problem regarding getting mbuf physical address. In transmission, for example, when got a network packet, I 
added some additional packet descriptor info into the M_LEADINGSPACE,  between m->pkt_dat and m->m_data. I then need to 
get the physical address starting from the packet descriptor in order for DMA operation. My assumption is that the mbuf 
as a whole is in a contiguous buffer, or at least the buffer between m->pkt_data to the end of m->m_data is. Am I 
correct?
> 
> Based on my assumption, I used mem_offset64 to get the physical address of the starting point, i.e., m->pkt_data + 
alignment offset. It seems not getting the correct one. I noticed that there is mbuf_phys, but that seems, from the code
, only get the m->m_data physical address, not the one that I need. 
> 
> I have a workaround to copy the mbuf into a contiguous buffer. But I fear for the performance impact.
> 
> Any suggestions?
> 
> Thanks,
> 
> Yurong
> 
> 
> 
> _______________________________________________
> 
> Networking Drivers
> http://community.qnx.com/sf/go/post90959
> 
Re: getting mbuf physical address  
Hi Sean

I still see problem with M_PREPEND + mbuf_phys. I did a very simple experiment to prove that the problem is just related
 with the mbuf physical address. See the code snippet below. 

What it does is that I copied m->m_data into another contiguous buffer and use the physical address of the contiguous 
buffer I created works, but not directly from the physical address of mbuf retrieved from mbuf_phys. I even dumped the m
->m_data content and verified that the content is correct. So if I copy the m->m_data into another buffer, and DMA the 
other buffer works, it means the content of mbuf is correct. The only issue is that the address of mbuf for DMA is not 
right.

The function below is on a thread that created by nw_pthread_create, not the io-pkt thread, could this be a problem? 

int send_packet(struct mbuf* m)
{
      int headsize = 22;
      off64_t buf_phy1, buf_phy2;

        M_PREPEND(m, headsize, M_DONTWAIT);
       // initialization of head
       ...
      
       buf_phy1 = mbuf_phys(m);

       //1. directly dma m_buf physical address
       DMA(buf_phy1, m->m_len);   // not working

      //2. workaround to copy mbuf into a contigous buffer
      uint8_t* buffer = mmap(NULL, m->m_len, PROT_READ|PROT_WRITE|PROT_NOCACHE,
                  MAP_PHYS|MAP_ANON, NOFD, 0);

     memcpy(buffer, m->m_data, m->m_len);
     mem_offset64((void*)buffer, NOFD, 1, &buf_phy2, NULL);
      
     DMA(buf_phy2, m->m_len);  //Works!!
  
}

Thanks,

Yurong
Re: getting mbuf physical address  
I logged the logical and physical address of mbuf:
m->m_data 0x2c2dc0, buf_phy1 0x35a30dc0  //not working using buf_phy1

//the contiguous buffer created seperately 
buffer 0x2e9040, buf_phy2 0x3f359040   //working using buf_phy2

The address all meet the alignment requirement for DMA.
Re: getting mbuf physical address  
Sean,

Many thanks. It solved my problem!

Yurong
Re: getting mbuf physical address  
Mbufs are cached.  You may need to flush before and invalidate after dma depending on platform.

-seanb

----- Original Message -----
From: Yurong Sun [mailto:community-noreply@qnx.com]
Sent: Tuesday, January 17, 2012 03:46 PM
To: drivers-networking <post90964@community.qnx.com>
Subject: Re: getting mbuf physical address

Hi Sean

I still see problem with M_PREPEND + mbuf_phys. I did a very simple experiment to prove that the problem is just related
 with the mbuf physical address. See the code snippet below. 

What it does is that I copied m->m_data into another contiguous buffer and use the physical address of the contiguous 
buffer I created works, but not directly from the physical address of mbuf retrieved from mbuf_phys. I even dumped the m
->m_data content and verified that the content is correct. So if I copy the m->m_data into another buffer, and DMA the 
other buffer works, it means the content of mbuf is correct. The only issue is that the address of mbuf for DMA is not 
right.

The function below is on a thread that created by nw_pthread_create, not the io-pkt thread, could this be a problem? 

int send_packet(struct mbuf* m)
{
      int headsize = 22;
      off64_t buf_phy1, buf_phy2;

        M_PREPEND(m, headsize, M_DONTWAIT);
       // initialization of head
       ...
      
       buf_phy1 = mbuf_phys(m);

       //1. directly dma m_buf physical address
       DMA(buf_phy1, m->m_len);   // not working

      //2. workaround to copy mbuf into a contigous buffer
      uint8_t* buffer = mmap(NULL, m->m_len, PROT_READ|PROT_WRITE|PROT_NOCACHE,
                  MAP_PHYS|MAP_ANON, NOFD, 0);

     memcpy(buffer, m->m_data, m->m_len);
     mem_offset64((void*)buffer, NOFD, 1, &buf_phy2, NULL);
      
     DMA(buf_phy2, m->m_len);  //Works!!
  
}

Thanks,

Yurong



_______________________________________________

Networking Drivers
http://community.qnx.com/sf/go/post90964