Wireshark-users: Re: [Wireshark-users] Where does libpcap capture frames?
From: Guy Harris <guy@xxxxxxxxxxxx>
Date: Sun, 29 Dec 2013 12:00:48 -0800
On Dec 29, 2013, at 7:50 AM, Stuart Kendrick <stuart.kendrick.sea@xxxxxxxxx> wrote:

> OK, I think I'm following what you're telling me:
> 
> From http://lxr.linux.no/#linux+v3.8/net/core/dev.c
> [...]
> 2361                if (!list_empty(&ptype_all
> ))
> 
> 2362                        dev_queue_xmit_nit(skb, dev
> );
> 
> 2363
> 2364                skb_len = skb->len
> ;
> 
> 2365                rc = ops->ndo_start_xmit(skb, dev
> );
> 
> 2366                trace_net_dev_xmit(skb, rc, dev, skb_len
> );
> 
> 2367                if (rc == NETDEV_TX_OK
> )
> 
> 2368                        txq_trans_update(txq
> );
> 
> 2369                return rc
> ;
> 
> 2370
>         }
> 
> 2371
> 2372gso
> :
> 
> 2373        do {
> [...]
> 
> So libpcap gets called somewhere inside dev_queue_xmit_nit(),

Or, rather, inside dev_queue_xmit_nit(), the packet is delivered to various sockets, and the sockets libpcap sets up are among them.

> and since I see the TCP SYNs in the on-board pcap, I conclude that my precious TCP SYNs reach line #2362
> Line #2364 is just an assignment ... in Line #2365, we call ndo_start_xmit() with the same arguments we sent to dev_queue_xmit_nit() ... I infer from your comment that ndo_start_xmit() gets implemented inside device drivers

More precisely, ndo_start_xmit is a member of a structure, and contains a pointer to a function and, in the case of your network adapter:

>  849        .ndo_start_xmit         = e1000_xmit_frame,

it points to e1000_xmit_frame().

> For example:
> 	if (test_bit(__E1000_DOWN, &adapter->state)) {
> 		dev_kfree_skb_any(skb);
> 		return NETDEV_TX_OK;
> 	}
> 
> ## Does this mean that if link is down, return "Yay!  Transmitted successfully" ? --sk

Well, let's look at the NETDEV_TX_ return values:

	enum netdev_tx {
	        __NETDEV_TX_MIN  = INT_MIN,     /* make sure enum is signed */
	        NETDEV_TX_OK     = 0x00,        /* driver took care of packet */
	        NETDEV_TX_BUSY   = 0x10,        /* driver tx path was busy*/
	        NETDEV_TX_LOCKED = 0x20,        /* driver tx lock was already taken */
	};

So if the link is down, it returns "the transmit path wasn't busy and nobody'd taken the lock, so I was able to take care of the packet, even if that just meant dropping it on the floor".

Ethernet doesn't guarantee packet delivery, so, if the caller cares whether the packet arrives, it needs to implement a protocol that provides acknowledgements, as, for example, TCP does, and retransmit the packet if it doesn't receive an acknowledgement in a reasonable amount of time.

> ## Does this mean that if I've been asked to transmit a zero length frame, that I return "Yay!  Transmitted successfully!" ?  --sk

See above.

> (1) Am I on the right track here, poking through e1000_xmit_frame() inside netdev.c, in my search for where my precious TCP SYNs get dropped?

If that's the device on which connection requests to the server should go, it's probably as good a place as any to start tracking.

> (2) Is there a generic way to ask the kernel to leave tracks in syslog as it transmits frames, to give me clues as to where e1000e is dropping my TCP SYNs?

You might look at SystemTap:

	http://sourceware.org/systemtap/

to see whether you can ask it to report calls to and returns from particular kernel functions, for example.