static void shaper_timer(unsigned long data) { struct shaper *shaper = (struct shaper *)data; spin_lock(&shaper->lock); shaper_kick(shaper); spin_unlock(&shaper->lock); }
static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct shaper *shaper = dev->priv; struct sk_buff *ptr; spin_lock(&shaper->lock); ptr=shaper->sendq.prev; /* * Set up our packet details */ SHAPERCB(skb)->shapelatency=0; SHAPERCB(skb)->shapeclock=shaper->recovery; if(time_before(SHAPERCB(skb)->shapeclock, jiffies)) SHAPERCB(skb)->shapeclock=jiffies; skb->priority=0; /* short term bug fix */ SHAPERCB(skb)->shapestamp=jiffies; /* * Time slots for this packet. */ SHAPERCB(skb)->shapelen= shaper_clocks(shaper,skb); { struct sk_buff *tmp; /* * Up our shape clock by the time pending on the queue * (Should keep this in the shaper as a variable..) */ for(tmp=skb_peek(&shaper->sendq); tmp!=NULL && tmp!=(struct sk_buff *)&shaper->sendq; tmp=tmp->next) SHAPERCB(skb)->shapeclock+=SHAPERCB(tmp)->shapelen; /* * Queue over time. Spill packet. */ if(time_after(SHAPERCB(skb)->shapeclock,jiffies + SHAPER_LATENCY)) { dev_kfree_skb(skb); shaper->stats.tx_dropped++; } else skb_queue_tail(&shaper->sendq, skb); } if(sh_debug) printk("Frame queued.\n"); if(skb_queue_len(&shaper->sendq)>SHAPER_QLEN) { ptr=skb_dequeue(&shaper->sendq); dev_kfree_skb(ptr); shaper->stats.collisions++; } shaper_kick(shaper); spin_unlock(&shaper->lock); return 0; }
static int shaper_close(struct net_device *dev) { struct shaper *shaper=dev->priv; struct sk_buff *skb; while ((skb = skb_dequeue(&shaper->sendq)) != NULL) dev_kfree_skb(skb); spin_lock_bh(&shaper->lock); shaper_kick(shaper); spin_unlock_bh(&shaper->lock); del_timer_sync(&shaper->timer); return 0; }
static void shaper_timer(unsigned long data) { struct shaper *sh=(struct shaper *)data; shaper_kick(sh); }
static void shaper_unlock(struct shaper *sh) { clear_bit(0, &sh->locked); wake_up(&sh->wait_queue); shaper_kick(sh); }
static int shaper_qframe(struct shaper *shaper, struct sk_buff *skb) { struct sk_buff *ptr; /* * Get ready to work on this shaper. Lock may fail if its * an interrupt and locked. */ if(!shaper_lock(shaper)) return -1; ptr=shaper->sendq.prev; /* * Set up our packet details */ skb->shapelatency=0; skb->shapeclock=shaper->recovery; if(time_before(skb->shapeclock, jiffies)) skb->shapeclock=jiffies; skb->priority=0; /* short term bug fix */ skb->shapestamp=jiffies; /* * Time slots for this packet. */ skb->shapelen= shaper_clocks(shaper,skb); #ifdef SHAPER_COMPLEX /* and broken.. */ while(ptr && ptr!=(struct sk_buff *)&shaper->sendq) { if(ptr->pri<skb->pri && jiffies - ptr->shapeclock < SHAPER_MAXSLIP) { struct sk_buff *tmp=ptr->prev; /* * It goes before us therefore we slip the length * of the new frame. */ ptr->shapeclock+=skb->shapelen; ptr->shapelatency+=skb->shapelen; /* * The packet may have slipped so far back it * fell off. */ if(ptr->shapelatency > SHAPER_LATENCY) { skb_unlink(ptr); dev_kfree_skb(ptr); } ptr=tmp; } else break; } if(ptr==NULL || ptr==(struct sk_buff *)&shaper->sendq) skb_queue_head(&shaper->sendq,skb); else { struct sk_buff *tmp; /* * Set the packet clock out time according to the * frames ahead. Im sure a bit of thought could drop * this loop. */ for(tmp=skb_peek(&shaper->sendq); tmp!=NULL && tmp!=ptr; tmp=tmp->next) skb->shapeclock+=tmp->shapelen; skb_append(ptr,skb); } #else { struct sk_buff *tmp; /* * Up our shape clock by the time pending on the queue * (Should keep this in the shaper as a variable..) */ for(tmp=skb_peek(&shaper->sendq); tmp!=NULL && tmp!=(struct sk_buff *)&shaper->sendq; tmp=tmp->next) skb->shapeclock+=tmp->shapelen; /* * Queue over time. Spill packet. */ if(skb->shapeclock-jiffies > SHAPER_LATENCY) dev_kfree_skb(skb); else skb_queue_tail(&shaper->sendq, skb); } #endif if(sh_debug) printk("Frame queued.\n"); if(skb_queue_len(&shaper->sendq)>SHAPER_QLEN) { ptr=skb_dequeue(&shaper->sendq); dev_kfree_skb(ptr); } shaper_unlock(shaper); shaper_kick(shaper); return 0; }
static void shaper_unlock(struct shaper *sh) { sh->locked=0; wake_up(&sh->wait_queue); shaper_kick(sh); }