Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/sched/sch_ingress.c
15112 views
1
/* 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/module.h>
11
#include <linux/types.h>
12
#include <linux/list.h>
13
#include <linux/skbuff.h>
14
#include <linux/rtnetlink.h>
15
#include <net/netlink.h>
16
#include <net/pkt_sched.h>
17
18
19
struct ingress_qdisc_data {
20
struct tcf_proto *filter_list;
21
};
22
23
/* ------------------------- Class/flow operations ------------------------- */
24
25
static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
26
{
27
return NULL;
28
}
29
30
static unsigned long ingress_get(struct Qdisc *sch, u32 classid)
31
{
32
return TC_H_MIN(classid) + 1;
33
}
34
35
static unsigned long ingress_bind_filter(struct Qdisc *sch,
36
unsigned long parent, u32 classid)
37
{
38
return ingress_get(sch, classid);
39
}
40
41
static void ingress_put(struct Qdisc *sch, unsigned long cl)
42
{
43
}
44
45
static void ingress_walk(struct Qdisc *sch, struct qdisc_walker *walker)
46
{
47
}
48
49
static struct tcf_proto **ingress_find_tcf(struct Qdisc *sch, unsigned long cl)
50
{
51
struct ingress_qdisc_data *p = qdisc_priv(sch);
52
53
return &p->filter_list;
54
}
55
56
/* --------------------------- Qdisc operations ---------------------------- */
57
58
static int ingress_enqueue(struct sk_buff *skb, struct Qdisc *sch)
59
{
60
struct ingress_qdisc_data *p = qdisc_priv(sch);
61
struct tcf_result res;
62
int result;
63
64
result = tc_classify(skb, p->filter_list, &res);
65
66
qdisc_bstats_update(sch, skb);
67
switch (result) {
68
case TC_ACT_SHOT:
69
result = TC_ACT_SHOT;
70
sch->qstats.drops++;
71
break;
72
case TC_ACT_STOLEN:
73
case TC_ACT_QUEUED:
74
result = TC_ACT_STOLEN;
75
break;
76
case TC_ACT_RECLASSIFY:
77
case TC_ACT_OK:
78
skb->tc_index = TC_H_MIN(res.classid);
79
default:
80
result = TC_ACT_OK;
81
break;
82
}
83
84
return result;
85
}
86
87
/* ------------------------------------------------------------- */
88
89
static void ingress_destroy(struct Qdisc *sch)
90
{
91
struct ingress_qdisc_data *p = qdisc_priv(sch);
92
93
tcf_destroy_chain(&p->filter_list);
94
}
95
96
static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb)
97
{
98
struct nlattr *nest;
99
100
nest = nla_nest_start(skb, TCA_OPTIONS);
101
if (nest == NULL)
102
goto nla_put_failure;
103
nla_nest_end(skb, nest);
104
return skb->len;
105
106
nla_put_failure:
107
nla_nest_cancel(skb, nest);
108
return -1;
109
}
110
111
static const struct Qdisc_class_ops ingress_class_ops = {
112
.leaf = ingress_leaf,
113
.get = ingress_get,
114
.put = ingress_put,
115
.walk = ingress_walk,
116
.tcf_chain = ingress_find_tcf,
117
.bind_tcf = ingress_bind_filter,
118
.unbind_tcf = ingress_put,
119
};
120
121
static struct Qdisc_ops ingress_qdisc_ops __read_mostly = {
122
.cl_ops = &ingress_class_ops,
123
.id = "ingress",
124
.priv_size = sizeof(struct ingress_qdisc_data),
125
.enqueue = ingress_enqueue,
126
.destroy = ingress_destroy,
127
.dump = ingress_dump,
128
.owner = THIS_MODULE,
129
};
130
131
static int __init ingress_module_init(void)
132
{
133
return register_qdisc(&ingress_qdisc_ops);
134
}
135
136
static void __exit ingress_module_exit(void)
137
{
138
unregister_qdisc(&ingress_qdisc_ops);
139
}
140
141
module_init(ingress_module_init)
142
module_exit(ingress_module_exit)
143
MODULE_LICENSE("GPL");
144
145