Hi, Thanks for the help. Actually, I had already realized that ip_finsih_output2 might be the cause of the bug - it tries to put in a cached header and the skb_push...thats why i had sent the mail regarding bug in ip_finish_output2.... (the hardware header size may not be 16...) what I need to know is the path of the packet after dev_queue_xmit is called. The reason is, that ip_send (which calls dev_queue_xmit) returns success, but sometime after this, I get the skb under panic. So it seems like the dev_queue_xmit functions only queues up the packet for transmission, and later some function actually fills in the hardware header (eth_build_header, eth_rebuild_header after the arp query has been resolved) and sends the packet out. This might be another potential place for the error... I couldn't trace the function pointers ahead of dev_queue_xmit - thats where I am stuck... dev->qdisc->enqueue ().... ? thanks, akshay --- Nivedita Singhvi <nivedita@sequent.com> wrote: > > can someone tell me what the path of an ip packet > is > > after > > you call ip_send (skb)? The problem I am facing > is: > > > > When i call ip_send to send out the packet, the > > function returns sucessfully, but soon after this, > > > i get an skb_under_panic - some function down > below is > > probably trying to push back the skb->data to > attach > > the hardware header, and goes back beyond > skb->head. > > > > How does ip_send return successfully, but then I > get > > an error? > > > [ net/ip.h: 162 ] > > #ifdef CONFIG_INET > static inline int ip_send(struct sk_buff *skb) > { > if (skb->len > skb->dst->pmtu) > return ip_fragment(skb, ip_finish_output); > else > return ip_finish_output(skb); > } > > assuming you've taken care of passing down a > appropriately sized segment, you wont need to > fragment, in which case you'll move on to > ip_finish_output(). > [ net/ipv4/ip_output.c:181 ] > > __inline__ int ip_finish_output(struct sk_buff > *skb) > { > struct net_device *dev = skb->dst->dev; > > skb->dev = dev; > skb->protocol = __constant_htons(ETH_P_IP); > > return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, > NULL, dev, > ip_finish_output2); > } > > if you've configured netfilter, it will do some > netfilter processing first, otherwise will jump to > this next: > [ net/ipv4/ip_output.c: 158 ] > > inline int ip_finish_output2(struct sk_buff *skb) > { > struct dst_entry *dst = skb->dst; > struct hh_cache *hh = dst->hh; > > #ifdef CONFIG_NETFILTER_DEBUG > nf_debug_ip_finish_output2(skb); > #endif /*CONFIG_NETFILTER_DEBUG*/ > > if (hh) { > read_lock_bh(&hh->hh_lock); > memcpy(skb->data - 16, hh->hh_data, 16); > read_unlock_bh(&hh->hh_lock); > skb_push(skb, hh->hh_len); > return hh->hh_output(skb); > } else if (dst->neighbour) > return dst->neighbour->output(skb); > > printk(KERN_DEBUG "khm\n"); > kfree_skb(skb); > return -EINVAL; > } > > if there is a cached hdr already, it will attach it, > and perhaps thats where your code is blowing up: > [ linux/skbuff.h:73 ] > > /** > * skb_push - add data to the start of a > buffer > * @skb: buffer to use > * @len: amount of data to add > * > * This function extends the used data area of > the buffer > at the buffer > * start. If this would exceed the total > buffer headroom > the kernel will > * panic. A pointer to the first byte of the > extra data is > returned. > */ > > static inline unsigned char *skb_push(struct > sk_buff *skb, > unsigned int len) > { > skb->data-=len; > skb->len+=len; > if(skb->data<skb->head) { > skb_under_panic(skb, len, current_text_addr()); > } > return skb->data; > } > > hope that helps, > > thanks, > nivedita > > --- > Nivedita Singhvi (503) > 578-4580 > Linux Technology Center > nivedita@us.ibm.com > IBM Beaverton, OR > nivedita@sequent.com > - > : send the line > "unsubscribe linux-net" in > the body of a message to majordomo@vger.kernel.org __________________________________________________ Do You Yahoo!? Get email at your own domain with Yahoo! Mail. http://personal.mail.yahoo.com/ - : send the line "unsubscribe linux-net" in the body of a message to majordomo@vger.kernel.org