<div dir="auto"><div>Hi Stephen,<div dir="auto"><br></div><div dir="auto">Thank you for the information.</div><div dir="auto">It solved your problem.</div><div dir="auto"><br></div><div dir="auto">Regards.</div><div dir="auto">Lokesh.</div><br><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, 14 Aug, 2024, 20:29 Stephen Hemminger, <<a href="mailto:stephen@networkplumber.org">stephen@networkplumber.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Wed, 14 Aug 2024 17:57:40 +0530<br>
Lokesh Chakka <<a href="mailto:lvenkatakumarchakka@gmail.com" target="_blank" rel="noreferrer">lvenkatakumarchakka@gmail.com</a>> wrote:<br>
<br>
> hi stephen,<br>
> <br>
> Thanks for your response. However it seems the solution is not working. The<br>
> following is the modified snippet....<br>
> <br>
> while( condition )<br>
> {<br>
>      for( pkt_count=0; pkt_count<num_of_pkts_per_queue; pkt_count++ )<br>
>      {<br>
>           rte_mbuf_refcnt_set( mbuf[pkt_count], 2 );// setting to two -<br>
> first and second iteration<br>
>      }<br>
>      for( pkt_count=0; pkt_count<5; pkt_count++ )<br>
>      {<br>
>           fprintf( stderr, "%s %d %u\n", __func__, __LINE__,<br>
> rte_mbuf_refcnt_read( mbuf[pkt_count] ) );//able to print two- first and<br>
> second iteration<br>
>      }<br>
>      if( rte_eth_tx_burst( port_id, 0, mbuf, num_of_pkts_per_queue ) !=<br>
> num_of_pkts_per_queue )<br>
>      {<br>
>           fprintf( stderr, "%s %d %d %s\n", __func__, __LINE__, rte_errno,<br>
> rte_strerror(rte_errno) );//failing second time<br>
>           rte_exit( EXIT_FAILURE, "%s %d rte_eth_tx_burst port id: %u\n",<br>
> __func__, __LINE__, port_id );<br>
>      }<br>
>      fprintf( stderr, "%s %d port: %u sent %u packets\n", __func__,<br>
> __LINE__, port_id, num_of_pkts_per_queue );//able to send once - first<br>
> iteration only<br>
>      for( pkt_count=0; pkt_count<5; pkt_count++ )<br>
>      {<br>
>           fprintf( stderr, "%s %d %u\n", __func__, __LINE__,<br>
> rte_mbuf_refcnt_read( mbuf[pkt_count] ) );//refcnt is printing one<br>
>      }<br>
> }<br>
> <br>
> There seems to be some more gap in my understanding. Could you please help<br>
> understand the issue?<br>
> <br>
> Thanks & Regards<br>
> --<br>
> Lokesh Chakka.<br>
> <br>
> <br>
> On Mon, Aug 12, 2024 at 8:22 PM Stephen Hemminger <<br>
> <a href="mailto:stephen@networkplumber.org" target="_blank" rel="noreferrer">stephen@networkplumber.org</a>> wrote:  <br>
> <br>
> > On Mon, 12 Aug 2024 15:55:50 +0530<br>
> > Lokesh Chakka <<a href="mailto:lvenkatakumarchakka@gmail.com" target="_blank" rel="noreferrer">lvenkatakumarchakka@gmail.com</a>> wrote:<br>
> >  <br>
> > > hello,<br>
> > ><br>
> > > Here is a small piece of code :<br>
> > ><br>
> > > while( condition )<br>
> > > {<br>
> > ><br>
> > >       if( rte_eth_tx_burst( port_id, 0, mbuf, num_of_pkts_per_queue ) !=<br>
> > > num_of_pkts_per_queue )<br>
> > >       {<br>
> > >               fprintf( stderr, "%d %s\n", rte_errno,  <br>
> > rte_strerror(rte_errno) );  <br>
> > >               rte_exit( EXIT_FAILURE, "%s %d rte_eth_tx_burst port id:  <br>
> > %u\n",  <br>
> > > __func__, __LINE__, port_id );//second iteration failing.<br>
> > >       }<br>
> > >       fprintf( stderr, "%s %d port: %u packet: %c sent %u packets\n",<br>
> > > __func__, __LINE__, port_id, argv[3][0], num_of_pkts_per_queue<br>
> > > );//printing once<br>
> > >       for( pkt_count=0; pkt_count<num_of_pkts_per_queue; pkt_count++ )<br>
> > >       {//want to send same data again...!!!<br>
> > >               mbuf[pkt_count]->pkt_len = mbuf[pkt_count]->data_len =  <br>
> > dev_info.max_mtu;  <br>
> > ><br>
> > >       }<br>
> > ><br>
> > > }<br>
> > ><br>
> > > Can someone help me understand how to reuse the packets again to send the<br>
> > > same data ?<br>
> > >  <br>
> ><br>
> > When packet is passed to tx_burst, the ownership of that mbuf is passed<br>
> > to the driver. The driver will free it after it is sent.<br>
> ><br>
> > One option would be to increase the reference count on the packet before<br>
> > sending.<br>
> > Using rte_mbuf_refcnt_update() function to add one to refcount.<br>
> > Then the driver will decrement refcount and the refcount will still be one<br>
> > (not freed).<br>
> ><br>
> > Assume this is some kind of packet generator.<br>
> >  <br>
<br>
<br>
Don't use refcnt_set(), you want to add an additional refcount not force it to two.<br>
The device driver may hold onto the mbuf for a while after it was passed to tx_burst<br>
so can't assume a value of two.<br>
<br>
If the number actually queued is less that the number requested, that means the device<br>
transmit queue is now full. Need to handle that case.<br>
<br>
Something like this might get you started:<br>
<br>
<br>
volatile running = true;<br>
<br>
void flood(uint16_t port_id, struct rte_mbufs *mbufs[], uint16_t num_pkts)<br>
{<br>
<br>
        while (running) {<br>
                /* Add additional reference to retain the packets */<br>
                for (uint16_t i = 0; i < num_pkts; i++)<br>
                        rte_mbuf_refcnt_update(mbufs[i], 1);<br>
<br>
                uint16_t sent = rte_eth_tx_burst(port_id, queue_id, mbufs, num_pkts);<br>
<br>
                if (sent < num_pkts) {<br>
                        /* device transmit queue was full, drop our reference */<br>
                        for (uint16_t i = sent; i < num_pkts; i++)<br>
                                rte_pktmbuf_free(mbufs[i]);<br>
                }<br>
        }<br>
<br>
        /* Don't leak original version */<br>
        rte_pktmbuf_free_bulk(mbufs, num_pkts);<br>
<br>
}<br>
<br>
<br>
</blockquote></div></div></div>