Re: kernel programming questions

Alan Cox (alan@lxorguk.ukuu.org.uk)
Tue, 1 Jul 1997 21:33:07 +0100 (BST)


> Using gcc extensions embedded in the C code for the portable kernel
> bits would be bad
>
> You've just counted out the entire IP layer ;-)

Not that badly in the portable parts. Anyway stop bitching and see if
you agree with the way I play with the header cache in this 8)

[CC Linus for 2.1.44]

*
* This should fix the shaper device for 2.1.4x. I'd been avoiding
* doing this hoping we'd get WFQ or CBQ code in the short term but
* that seems not to be occuring.
*
* This isnt the complete fix. I'll tidy it more later. Dave & Alexey
* might want to take a look at the hard/rebuild header functions. They
* play a little bit dirty with the header cache and there is probably
* a "right" way to support this ability [the bridge will also need it
* when I fix that to work as it should].
*
* (shapecfg tool at the bottom of the diff)
*
* [simple use]
* insmod shaper
* shapecfg attach shaper0 eth0
* shapecfg speed shaper0 64000 # 64Kbit
* ifconfig shaper0 my.add.ess.here pointopoint slow.send.host up
*
* Alan
*
--- linux/include/linux/if_shaper.h.old Tue Jul 1 21:18:40 1997
+++ linux/include/linux/if_shaper.h Sat Jun 28 21:02:54 1997
@@ -0,0 +1,61 @@
+#ifndef __LINUX_SHAPER_H
+#define __LINUX_SHAPER_H
+
+#ifdef __KERNEL__
+
+#define SHAPER_QLEN 10
+/*
+ * This is a bit speed dependant (read it shouldnt be a constant!)
+ *
+ * 5 is about right for 28.8 upwards. Below that double for every
+ * halving of speed or so. - ie about 20 for 9600 baud.
+ */
+#define SHAPER_LATENCY (5*HZ)
+#define SHAPER_MAXSLIP 2
+#define SHAPER_BURST (HZ/50) /* Good for >128K then */
+
+struct shaper
+{
+ struct sk_buff_head sendq;
+ __u32 bytespertick;
+ __u32 shapelatency;
+ __u32 shapeclock;
+ __u32 recovery; /* Time we can next clock a packet out on
+ an empty queue */
+ char locked;
+ struct device *dev;
+ int (*hard_start_xmit) (struct sk_buff *skb,
+ struct device *dev);
+ int (*hard_header) (struct sk_buff *skb,
+ struct device *dev,
+ unsigned short type,
+ void *daddr,
+ void *saddr,
+ unsigned len);
+ int (*rebuild_header)(struct sk_buff *skb);
+ int (*hard_header_cache)(struct dst_entry *dst, struct neighbour *neigh,
+ struct hh_cache *hh);
+ void (*header_cache_update)(struct hh_cache *hh, struct device *dev, unsigned char * haddr);
+ struct net_device_stats* (*get_stats)(struct device *dev);
+ struct wait_queue *wait_queue;
+ struct timer_list timer;
+};
+
+#endif
+
+#define SHAPER_SET_DEV 0x0001
+#define SHAPER_SET_SPEED 0x0002
+
+struct shaperconf
+{
+ __u16 ss_cmd;
+ union
+ {
+ char ssu_name[14];
+ __u32 ssu_speed;
+ } ss_u;
+#define ss_speed ss_u.ssu_speed
+#define ss_name ss_u.ssu_name
+};
+
+#endif
--- linux/drivers/net/shaper.h.old Tue Jul 1 21:18:16 1997
+++ linux/drivers/net/shaper.h Tue Jul 1 21:26:38 1997
@@ -1,61 +0,0 @@
-#ifndef __LINUX_SHAPER_H
-#define __LINUX_SHAPER_H
-
-#ifdef __KERNEL__
-
-#define SHAPER_QLEN 10
-/*
- * This is a bit speed dependant (read it shouldnt be a constant!)
- *
- * 5 is about right for 28.8 upwards. Below that double for every
- * halving of speed or so. - ie about 20 for 9600 baud.
- */
-#define SHAPER_LATENCY (5*HZ)
-#define SHAPER_MAXSLIP 2
-#define SHAPER_BURST (HZ/50) /* Good for >128K then */
-
-struct shaper
-{
- struct sk_buff_head sendq;
- __u32 bytespertick;
- __u32 shapelatency;
- __u32 shapeclock;
- __u32 recovery; /* Time we can next clock a packet out on
- an empty queue */
- char locked;
- struct device *dev;
- int (*hard_start_xmit) (struct sk_buff *skb,
- struct device *dev);
- int (*hard_header) (struct sk_buff *skb,
- struct device *dev,
- unsigned short type,
- void *daddr,
- void *saddr,
- unsigned len);
- int (*rebuild_header)(struct sk_buff *skb);
- int (*hard_header_cache)(struct dst_entry *dst, struct neighbour *neigh,
- struct hh_cache *hh);
- void (*header_cache_update)(struct hh_cache *hh, struct device *dev, unsigned char * haddr);
- struct net_device_stats* (*get_stats)(struct device *dev);
- struct wait_queue *wait_queue;
- struct timer_list timer;
-};
-
-#endif
-
-#define SHAPER_SET_DEV 0x0001
-#define SHAPER_SET_SPEED 0x0002
-
-struct shaperconf
-{
- __u16 ss_cmd;
- union
- {
- char ssu_name[14];
- __u32 ssu_speed;
- } ss_u;
-#define ss_speed ss_u.ssu_speed
-#define ss_name ss_u.ssu_name
-};
-
-#endif
--- linux/drivers/net/shaper.c.old Sat Jun 28 21:02:54 1997
+++ linux/drivers/net/shaper.c Tue Jul 1 21:18:59 1997
@@ -70,11 +70,11 @@
#include <linux/if_arp.h>
#include <linux/init.h>
#include <net/dst.h>
-#include "shaper.h"
+#include <linux/if_shaper.h>

int sh_debug; /* Debug flag */

-#define SHAPER_BANNER "CymruNet Traffic Shaper BETA 0.03 for Linux 2.1\n"
+#define SHAPER_BANNER "CymruNet Traffic Shaper BETA 0.04 for Linux 2.1\n"

/*
* Locking
@@ -426,17 +426,26 @@
unsigned short type, void *daddr, void *saddr, unsigned len)
{
struct shaper *sh=dev->priv;
+ int v;
if(sh_debug)
printk("Shaper header\n");
- return sh->hard_header(skb,sh->dev,type,daddr,saddr,len);
+ 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 device *dev=skb->dev;
+ int v;
if(sh_debug)
printk("Shaper rebuild header\n");
- return sh->rebuild_header(skb);
+ skb->dev=sh->dev;
+ v=sh->rebuild_header(skb);
+ skb->dev=dev;
+ return v;
}

static int shaper_cache(struct dst_entry *dst, struct neighbour *neigh, struct hh_cache *hh)
@@ -483,6 +492,7 @@
else
shdev->rebuild_header = NULL;

+#if 0
if(dev->hard_header_cache)
{
sh->hard_header_cache = dev->hard_header_cache;
@@ -500,6 +510,10 @@
}
else
shdev->header_cache_update= NULL;
+#else
+ shdev->header_cache_update = NULL;
+ shdev->hard_header_cache = NULL;
+#endif

shdev->hard_header_len=dev->hard_header_len;
shdev->type=dev->type;

*
* Shapecfg.c
*

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <linux/types.h>
#include <linux/if.h>
#include <linux/if_shaper.h>

void usage(char *name)
{
fprintf(stderr,"%s attach <device> <device>\n%s <device> <speed>\n",
name,name);
exit(1);
}

void main(int argc, char *argv[])
{
int s=socket(AF_INET, SOCK_DGRAM,0);
if(s==-1)
{
perror("socket");
exit(1);
}
if(argc!=4)
usage(argv[0]);
if(strcmp(argv[1],"attach")==0)
{
struct ifreq ifr;
struct shaperconf *shc=(struct shaperconf *)&ifr.ifr_data;
strcpy(ifr.ifr_name,argv[2]);
strcpy(shc->ss_name,argv[3]);
shc->ss_cmd=SHAPER_SET_DEV;
if(ioctl(s,SIOCDEVPRIVATE,&ifr)==-1)
{
perror("shaper");
exit(1);
}
exit(0);
}
if(strcmp(argv[1],"speed")==0)
{
int v;
struct ifreq ifr;
struct shaperconf *shc=(struct shaperconf *)&ifr.ifr_data;
strcpy(ifr.ifr_name,argv[2]);
sscanf(argv[3],"%d",&v);
shc->ss_speed=v;
shc->ss_cmd=SHAPER_SET_SPEED;
if(ioctl(s,SIOCDEVPRIVATE,&ifr)==-1)
{
perror("shaper");
exit(1);
}
exit(0);
}
usage(argv[0]);
}