📄 shaper.c
字号:
*/ static void shaper_flush(struct shaper *shaper){ struct sk_buff *skb; if(!shaper_lock(shaper)) { printk(KERN_ERR "shaper: shaper_flush() called by an irq!\n"); return; } while((skb=skb_dequeue(&shaper->sendq))!=NULL) dev_kfree_skb(skb); shaper_unlock(shaper);}/* * Bring the interface up. We just disallow this until a * bind. */static int shaper_open(struct net_device *dev){ struct shaper *shaper=dev->priv; /* * Can't open until attached. * Also can't open until speed is set, or we'll get * a division by zero. */ if(shaper->dev==NULL) return -ENODEV; if(shaper->bitspersec==0) return -EINVAL; return 0;}/* * Closing a shaper flushes the queues. */ static int shaper_close(struct net_device *dev){ struct shaper *shaper=dev->priv; shaper_flush(shaper); del_timer_sync(&shaper->timer); return 0;}/* * Revectored calls. We alter the parameters and call the functions * for our attached device. This enables us to bandwidth allocate after * ARP and other resolutions and not before. */static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev){ struct shaper *sh=dev->priv; return shaper_qframe(sh, skb);}static struct net_device_stats *shaper_get_stats(struct net_device *dev){ struct shaper *sh=dev->priv; return &sh->stats;}static int shaper_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len){ struct shaper *sh=dev->priv; int v; if(sh_debug) printk("Shaper header\n"); skb->dev=sh->dev; v=sh->hard_header(skb,sh->dev,type,daddr,saddr,len); skb->dev=dev; return v;}static int shaper_rebuild_header(struct sk_buff *skb){ struct shaper *sh=skb->dev->priv; struct net_device *dev=skb->dev; int v; if(sh_debug) printk("Shaper rebuild header\n"); skb->dev=sh->dev; v=sh->rebuild_header(skb); skb->dev=dev; return v;}#if 0static int shaper_cache(struct neighbour *neigh, struct hh_cache *hh){ struct shaper *sh=neigh->dev->priv; struct net_device *tmp; int ret; if(sh_debug) printk("Shaper header cache bind\n"); tmp=neigh->dev; neigh->dev=sh->dev; ret=sh->hard_header_cache(neigh,hh); neigh->dev=tmp; return ret;}static void shaper_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char *haddr){ struct shaper *sh=dev->priv; if(sh_debug) printk("Shaper cache update\n"); sh->header_cache_update(hh, sh->dev, haddr);}#endif#ifdef CONFIG_INETstatic int shaper_neigh_setup(struct neighbour *n){#ifdef CONFIG_INET if (n->nud_state == NUD_NONE) { n->ops = &arp_broken_ops; n->output = n->ops->output; }#endif return 0;}static int shaper_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p){#ifdef CONFIG_INET if (p->tbl->family == AF_INET) { p->neigh_setup = shaper_neigh_setup; p->ucast_probes = 0; p->mcast_probes = 0; }#endif return 0;}#else /* !(CONFIG_INET) */static int shaper_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p){ return 0;}#endifstatic int shaper_attach(struct net_device *shdev, struct shaper *sh, struct net_device *dev){ sh->dev = dev; sh->hard_start_xmit=dev->hard_start_xmit; sh->get_stats=dev->get_stats; if(dev->hard_header) { sh->hard_header=dev->hard_header; shdev->hard_header = shaper_header; } else shdev->hard_header = NULL; if(dev->rebuild_header) { sh->rebuild_header = dev->rebuild_header; shdev->rebuild_header = shaper_rebuild_header; } else shdev->rebuild_header = NULL; #if 0 if(dev->hard_header_cache) { sh->hard_header_cache = dev->hard_header_cache; shdev->hard_header_cache= shaper_cache; } else { shdev->hard_header_cache= NULL; } if(dev->header_cache_update) { sh->header_cache_update = dev->header_cache_update; shdev->header_cache_update = shaper_cache_update; } else shdev->header_cache_update= NULL;#else shdev->header_cache_update = NULL; shdev->hard_header_cache = NULL;#endif shdev->neigh_setup = shaper_neigh_setup_dev; shdev->hard_header_len=dev->hard_header_len; shdev->type=dev->type; shdev->addr_len=dev->addr_len; shdev->mtu=dev->mtu; sh->bitspersec=0; return 0;}static int shaper_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){ struct shaperconf *ss= (struct shaperconf *)&ifr->ifr_data; struct shaper *sh=dev->priv; if(ss->ss_cmd == SHAPER_SET_DEV || ss->ss_cmd == SHAPER_SET_SPEED) { if(!capable(CAP_NET_ADMIN)) return -EPERM; } switch(ss->ss_cmd) { case SHAPER_SET_DEV: { struct net_device *them=__dev_get_by_name(ss->ss_name); if(them==NULL) return -ENODEV; if(sh->dev) return -EBUSY; return shaper_attach(dev,dev->priv, them); } case SHAPER_GET_DEV: if(sh->dev==NULL) return -ENODEV; strcpy(ss->ss_name, sh->dev->name); return 0; case SHAPER_SET_SPEED: shaper_setspeed(sh,ss->ss_speed); return 0; case SHAPER_GET_SPEED: ss->ss_speed=sh->bitspersec; return 0; default: return -EINVAL; }}static void shaper_init_priv(struct net_device *dev){ struct shaper *sh = dev->priv; skb_queue_head_init(&sh->sendq); init_timer(&sh->timer); sh->timer.function=shaper_timer; sh->timer.data=(unsigned long)sh; init_waitqueue_head(&sh->wait_queue);}/* * Add a shaper device to the system */ static int __init shaper_probe(struct net_device *dev){ /* * Set up the shaper. */ SET_MODULE_OWNER(dev); shaper_init_priv(dev); dev->open = shaper_open; dev->stop = shaper_close; dev->hard_start_xmit = shaper_start_xmit; dev->get_stats = shaper_get_stats; dev->set_multicast_list = NULL; /* * Intialise the packet queues */ dev_init_buffers(dev); /* * Handlers for when we attach to a device. */ dev->hard_header = shaper_header; dev->rebuild_header = shaper_rebuild_header;#if 0 dev->hard_header_cache = shaper_cache; dev->header_cache_update= shaper_cache_update;#endif dev->neigh_setup = shaper_neigh_setup_dev; dev->do_ioctl = shaper_ioctl; dev->hard_header_len = 0; dev->type = ARPHRD_ETHER; /* initially */ dev->set_mac_address = NULL; dev->mtu = 1500; dev->addr_len = 0; dev->tx_queue_len = 10; dev->flags = 0; /* * Shaper is ok */ return 0;} static int shapers = 1;#ifdef MODULEMODULE_PARM(shapers, "i");#else /* MODULE */static int __init set_num_shapers(char *str){ shapers = simple_strtol(str, NULL, 0); return 1;}__setup("shapers=", set_num_shapers);#endif /* MODULE */static struct net_device *devs;static int __init shaper_init(void){ int i, err; size_t alloc_size; struct shaper *sp; unsigned int shapers_registered = 0; if (shapers < 1) return -ENODEV; alloc_size = (sizeof(*devs) * shapers) + (sizeof(struct shaper) * shapers); devs = kmalloc(alloc_size, GFP_KERNEL); if (!devs) return -ENOMEM; memset(devs, 0, alloc_size); sp = (struct shaper *) &devs[shapers]; for (i = 0; i < shapers; i++) { err = dev_alloc_name(&devs[i], "shaper%d"); if (err < 0) break; devs[i].init = shaper_probe; devs[i].priv = &sp[i]; if (register_netdev(&devs[i])) break; shapers_registered++; } if (!shapers_registered) { kfree(devs); devs = NULL; } return (shapers_registered ? 0 : -ENODEV);}static void __exit shaper_exit (void){ kfree(devs); devs = NULL;}module_init(shaper_init);module_exit(shaper_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -