OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [sched/] [sch_ingress.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* net/sched/sch_ingress.c - Ingress qdisc
2
 *              This program is free software; you can redistribute it and/or
3
 *              modify it under the terms of the GNU General Public License
4
 *              as published by the Free Software Foundation; either version
5
 *              2 of the License, or (at your option) any later version.
6
 *
7
 * Authors:     Jamal Hadi Salim 1999
8
 */
9
 
10
#include <linux/config.h>
11
#include <linux/module.h>
12
#include <linux/types.h>
13
#include <linux/skbuff.h>
14
#include <linux/netdevice.h>
15
#include <linux/rtnetlink.h>
16
#include <linux/netfilter_ipv4.h>
17
#include <linux/netfilter.h>
18
#include <linux/smp.h>
19
#include <net/pkt_sched.h>
20
#include <asm/byteorder.h>
21
#include <asm/uaccess.h>
22
#include <linux/kmod.h>
23
#include <linux/stat.h>
24
#include <linux/interrupt.h>
25
#include <linux/list.h>
26
 
27
 
28
#undef DEBUG_INGRESS
29
 
30
#ifdef DEBUG_INGRESS  /* control */
31
#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
32
#else
33
#define DPRINTK(format,args...)
34
#endif
35
 
36
#if 0  /* data */
37
#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
38
#else
39
#define D2PRINTK(format,args...)
40
#endif
41
 
42
 
43
#define PRIV(sch) ((struct ingress_qdisc_data *) (sch)->data)
44
 
45
 
46
/* Thanks to Doron Oz for this hack
47
*/
48
static int nf_registered = 0;
49
 
50
struct ingress_qdisc_data {
51
        struct Qdisc            *q;
52
        struct tcf_proto        *filter_list;
53
};
54
 
55
 
56
/* ------------------------- Class/flow operations ------------------------- */
57
 
58
 
59
static int ingress_graft(struct Qdisc *sch,unsigned long arg,
60
    struct Qdisc *new,struct Qdisc **old)
61
{
62
#ifdef DEBUG_INGRESS
63
        struct ingress_qdisc_data *p = PRIV(sch);
64
#endif
65
 
66
        DPRINTK("ingress_graft(sch %p,[qdisc %p],new %p,old %p)\n",
67
                sch, p, new, old);
68
        DPRINTK("\n ingress_graft: You cannot add qdiscs to classes");
69
        return 1;
70
}
71
 
72
 
73
static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
74
{
75
        return NULL;
76
}
77
 
78
 
79
static unsigned long ingress_get(struct Qdisc *sch,u32 classid)
80
{
81
#ifdef DEBUG_INGRESS
82
        struct ingress_qdisc_data *p = PRIV(sch);
83
#endif
84
        DPRINTK("ingress_get(sch %p,[qdisc %p],classid %x)\n", sch, p, classid);
85
        return TC_H_MIN(classid) + 1;
86
}
87
 
88
 
89
static unsigned long ingress_bind_filter(struct Qdisc *sch,
90
    unsigned long parent, u32 classid)
91
{
92
        return ingress_get(sch, classid);
93
}
94
 
95
 
96
static void ingress_put(struct Qdisc *sch, unsigned long cl)
97
{
98
}
99
 
100
 
101
static int ingress_change(struct Qdisc *sch, u32 classid, u32 parent,
102
    struct rtattr **tca, unsigned long *arg)
103
{
104
#ifdef DEBUG_INGRESS
105
        struct ingress_qdisc_data *p = PRIV(sch);
106
#endif
107
        DPRINTK("ingress_change(sch %p,[qdisc %p],classid %x,parent %x),"
108
                "arg 0x%lx\n", sch, p, classid, parent, *arg);
109
        DPRINTK("No effect. sch_ingress doesn't maintain classes at the moment");
110
        return 0;
111
}
112
 
113
 
114
 
115
static void ingress_walk(struct Qdisc *sch,struct qdisc_walker *walker)
116
{
117
#ifdef DEBUG_INGRESS
118
        struct ingress_qdisc_data *p = PRIV(sch);
119
#endif
120
        DPRINTK("ingress_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
121
        DPRINTK("No effect. sch_ingress doesn't maintain classes at the moment");
122
}
123
 
124
 
125
static struct tcf_proto **ingress_find_tcf(struct Qdisc *sch,unsigned long cl)
126
{
127
        struct ingress_qdisc_data *p = PRIV(sch);
128
 
129
        return &p->filter_list;
130
}
131
 
132
 
133
/* --------------------------- Qdisc operations ---------------------------- */
134
 
135
 
136
static int ingress_enqueue(struct sk_buff *skb,struct Qdisc *sch)
137
{
138
        struct ingress_qdisc_data *p = PRIV(sch);
139
        struct tcf_result res;
140
        int result;
141
 
142
        D2PRINTK("ingress_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
143
        result = tc_classify(skb, p->filter_list, &res);
144
        D2PRINTK("result %d class 0x%04x\n", result, res.classid);
145
        /*
146
         * Unlike normal "enqueue" functions, ingress_enqueue returns a
147
         * firewall FW_* code.
148
         */
149
#ifdef CONFIG_NET_CLS_POLICE
150
        switch (result) {
151
                case TC_POLICE_SHOT:
152
                        result = NF_DROP;
153
                        sch->stats.drops++;
154
                        break;
155
                case TC_POLICE_RECLASSIFY: /* DSCP remarking here ? */
156
                case TC_POLICE_OK:
157
                case TC_POLICE_UNSPEC:
158
                default:
159
                        sch->stats.packets++;
160
                        sch->stats.bytes += skb->len;
161
                        result = NF_ACCEPT;
162
                        break;
163
        };
164
#else
165
        sch->stats.packets++;
166
        sch->stats.bytes += skb->len;
167
#endif
168
 
169
        skb->tc_index = TC_H_MIN(res.classid);
170
        return result;
171
}
172
 
173
 
174
static struct sk_buff *ingress_dequeue(struct Qdisc *sch)
175
{
176
/*
177
        struct ingress_qdisc_data *p = PRIV(sch);
178
        D2PRINTK("ingress_dequeue(sch %p,[qdisc %p])\n",sch,PRIV(p));
179
*/
180
        return NULL;
181
}
182
 
183
 
184
static int ingress_requeue(struct sk_buff *skb,struct Qdisc *sch)
185
{
186
/*
187
        struct ingress_qdisc_data *p = PRIV(sch);
188
        D2PRINTK("ingress_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,PRIV(p));
189
*/
190
        return 0;
191
}
192
 
193
static unsigned int ingress_drop(struct Qdisc *sch)
194
{
195
#ifdef DEBUG_INGRESS
196
        struct ingress_qdisc_data *p = PRIV(sch);
197
#endif
198
        DPRINTK("ingress_drop(sch %p,[qdisc %p])\n", sch, p);
199
        return 0;
200
}
201
 
202
static unsigned int
203
ing_hook(unsigned int hook, struct sk_buff **pskb,
204
                             const struct net_device *indev,
205
                             const struct net_device *outdev,
206
                             int (*okfn)(struct sk_buff *))
207
{
208
 
209
        struct Qdisc *q;
210
        struct sk_buff *skb = *pskb;
211
        struct net_device *dev = skb->dev;
212
        int fwres=NF_ACCEPT;
213
 
214
        DPRINTK("ing_hook: skb %s dev=%s len=%u\n",
215
                skb->sk ? "(owned)" : "(unowned)",
216
                skb->dev ? (*pskb)->dev->name : "(no dev)",
217
                skb->len);
218
 
219
/*
220
revisit later: Use a private since lock dev->queue_lock is also
221
used on the egress (might slow things for an iota)
222
*/
223
 
224
        if (dev->qdisc_ingress) {
225
                spin_lock(&dev->queue_lock);
226
                if ((q = dev->qdisc_ingress) != NULL)
227
                        fwres = q->enqueue(skb, q);
228
                spin_unlock(&dev->queue_lock);
229
        }
230
 
231
        return fwres;
232
}
233
 
234
/* after ipt_filter */
235
static struct nf_hook_ops ing_ops =
236
{
237
        { NULL, NULL},
238
        ing_hook,
239
        PF_INET,
240
        NF_IP_PRE_ROUTING,
241
        NF_IP_PRI_FILTER + 1
242
};
243
 
244
int ingress_init(struct Qdisc *sch,struct rtattr *opt)
245
{
246
        struct ingress_qdisc_data *p = PRIV(sch);
247
 
248
        if (!nf_registered) {
249
                if (nf_register_hook(&ing_ops) < 0) {
250
                        printk("ingress qdisc registration error \n");
251
                        goto error;
252
                        }
253
                nf_registered++;
254
        }
255
 
256
        DPRINTK("ingress_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
257
        memset(p, 0, sizeof(*p));
258
        p->filter_list = NULL;
259
        p->q = &noop_qdisc;
260
        MOD_INC_USE_COUNT;
261
        return 0;
262
error:
263
        return -EINVAL;
264
}
265
 
266
 
267
static void ingress_reset(struct Qdisc *sch)
268
{
269
        struct ingress_qdisc_data *p = PRIV(sch);
270
 
271
        DPRINTK("ingress_reset(sch %p,[qdisc %p])\n", sch, p);
272
 
273
/*
274
#if 0
275
*/
276
/* for future use */
277
        qdisc_reset(p->q);
278
/*
279
#endif
280
*/
281
}
282
 
283
/* ------------------------------------------------------------- */
284
 
285
 
286
/* ------------------------------------------------------------- */
287
 
288
static void ingress_destroy(struct Qdisc *sch)
289
{
290
        struct ingress_qdisc_data *p = PRIV(sch);
291
        struct tcf_proto *tp;
292
 
293
        DPRINTK("ingress_destroy(sch %p,[qdisc %p])\n", sch, p);
294
        while (p->filter_list) {
295
                tp = p->filter_list;
296
                p->filter_list = tp->next;
297
                tcf_destroy(tp);
298
        }
299
        memset(p, 0, sizeof(*p));
300
        p->filter_list = NULL;
301
 
302
#if 0
303
/* for future use */
304
        qdisc_destroy(p->q);
305
#endif
306
 
307
        MOD_DEC_USE_COUNT;
308
 
309
}
310
 
311
 
312
static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb)
313
{
314
        unsigned char *b = skb->tail;
315
        struct rtattr *rta;
316
 
317
        rta = (struct rtattr *) b;
318
        RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
319
        rta->rta_len = skb->tail - b;
320
        return skb->len;
321
 
322
rtattr_failure:
323
        skb_trim(skb, b - skb->data);
324
        return -1;
325
}
326
 
327
static struct Qdisc_class_ops ingress_class_ops =
328
{
329
        ingress_graft,                  /* graft */
330
        ingress_leaf,                   /* leaf */
331
        ingress_get,                    /* get */
332
        ingress_put,                    /* put */
333
        ingress_change,                 /* change */
334
        NULL,                           /* delete */
335
        ingress_walk,                           /* walk */
336
 
337
        ingress_find_tcf,               /* tcf_chain */
338
        ingress_bind_filter,            /* bind_tcf */
339
        ingress_put,                    /* unbind_tcf */
340
 
341
        NULL,           /* dump */
342
};
343
 
344
struct Qdisc_ops ingress_qdisc_ops =
345
{
346
        NULL,                           /* next */
347
        &ingress_class_ops,             /* cl_ops */
348
        "ingress",
349
        sizeof(struct ingress_qdisc_data),
350
 
351
        ingress_enqueue,                /* enqueue */
352
        ingress_dequeue,                /* dequeue */
353
        ingress_requeue,                /* requeue */
354
        ingress_drop,                   /* drop */
355
 
356
        ingress_init,                   /* init */
357
        ingress_reset,                  /* reset */
358
        ingress_destroy,                /* destroy */
359
        NULL,                           /* change */
360
 
361
        ingress_dump,                   /* dump */
362
};
363
 
364
 
365
#ifdef MODULE
366
int init_module(void)
367
{
368
        int ret = 0;
369
 
370
        if ((ret = register_qdisc(&ingress_qdisc_ops)) < 0) {
371
                printk("Unable to register Ingress qdisc\n");
372
                return ret;
373
        }
374
 
375
        return ret;
376
}
377
 
378
 
379
void cleanup_module(void)
380
{
381
        unregister_qdisc(&ingress_qdisc_ops);
382
        if (nf_registered)
383
                nf_unregister_hook(&ing_ops);
384
}
385
#endif
386
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.