diff options
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/act_nat.c | 23 | ||||
-rw-r--r-- | net/sched/cls_flow.c | 96 | ||||
-rw-r--r-- | net/sched/cls_rsvp.h | 12 | ||||
-rw-r--r-- | net/sched/sch_sfq.c | 36 |
4 files changed, 106 insertions, 61 deletions
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c index d0386a413e8d..509a2d53a99d 100644 --- a/net/sched/act_nat.c +++ b/net/sched/act_nat.c | |||
@@ -114,6 +114,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, | |||
114 | int egress; | 114 | int egress; |
115 | int action; | 115 | int action; |
116 | int ihl; | 116 | int ihl; |
117 | int noff; | ||
117 | 118 | ||
118 | spin_lock(&p->tcf_lock); | 119 | spin_lock(&p->tcf_lock); |
119 | 120 | ||
@@ -132,7 +133,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, | |||
132 | if (unlikely(action == TC_ACT_SHOT)) | 133 | if (unlikely(action == TC_ACT_SHOT)) |
133 | goto drop; | 134 | goto drop; |
134 | 135 | ||
135 | if (!pskb_may_pull(skb, sizeof(*iph))) | 136 | noff = skb_network_offset(skb); |
137 | if (!pskb_may_pull(skb, sizeof(*iph) + noff)) | ||
136 | goto drop; | 138 | goto drop; |
137 | 139 | ||
138 | iph = ip_hdr(skb); | 140 | iph = ip_hdr(skb); |
@@ -144,7 +146,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, | |||
144 | 146 | ||
145 | if (!((old_addr ^ addr) & mask)) { | 147 | if (!((old_addr ^ addr) & mask)) { |
146 | if (skb_cloned(skb) && | 148 | if (skb_cloned(skb) && |
147 | !skb_clone_writable(skb, sizeof(*iph)) && | 149 | !skb_clone_writable(skb, sizeof(*iph) + noff) && |
148 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | 150 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) |
149 | goto drop; | 151 | goto drop; |
150 | 152 | ||
@@ -172,9 +174,9 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, | |||
172 | { | 174 | { |
173 | struct tcphdr *tcph; | 175 | struct tcphdr *tcph; |
174 | 176 | ||
175 | if (!pskb_may_pull(skb, ihl + sizeof(*tcph)) || | 177 | if (!pskb_may_pull(skb, ihl + sizeof(*tcph) + noff) || |
176 | (skb_cloned(skb) && | 178 | (skb_cloned(skb) && |
177 | !skb_clone_writable(skb, ihl + sizeof(*tcph)) && | 179 | !skb_clone_writable(skb, ihl + sizeof(*tcph) + noff) && |
178 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) | 180 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) |
179 | goto drop; | 181 | goto drop; |
180 | 182 | ||
@@ -186,9 +188,9 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, | |||
186 | { | 188 | { |
187 | struct udphdr *udph; | 189 | struct udphdr *udph; |
188 | 190 | ||
189 | if (!pskb_may_pull(skb, ihl + sizeof(*udph)) || | 191 | if (!pskb_may_pull(skb, ihl + sizeof(*udph) + noff) || |
190 | (skb_cloned(skb) && | 192 | (skb_cloned(skb) && |
191 | !skb_clone_writable(skb, ihl + sizeof(*udph)) && | 193 | !skb_clone_writable(skb, ihl + sizeof(*udph) + noff) && |
192 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) | 194 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) |
193 | goto drop; | 195 | goto drop; |
194 | 196 | ||
@@ -205,7 +207,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, | |||
205 | { | 207 | { |
206 | struct icmphdr *icmph; | 208 | struct icmphdr *icmph; |
207 | 209 | ||
208 | if (!pskb_may_pull(skb, ihl + sizeof(*icmph))) | 210 | if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + noff)) |
209 | goto drop; | 211 | goto drop; |
210 | 212 | ||
211 | icmph = (void *)(skb_network_header(skb) + ihl); | 213 | icmph = (void *)(skb_network_header(skb) + ihl); |
@@ -215,7 +217,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, | |||
215 | (icmph->type != ICMP_PARAMETERPROB)) | 217 | (icmph->type != ICMP_PARAMETERPROB)) |
216 | break; | 218 | break; |
217 | 219 | ||
218 | if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + sizeof(*iph))) | 220 | if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + sizeof(*iph) + |
221 | noff)) | ||
219 | goto drop; | 222 | goto drop; |
220 | 223 | ||
221 | icmph = (void *)(skb_network_header(skb) + ihl); | 224 | icmph = (void *)(skb_network_header(skb) + ihl); |
@@ -229,8 +232,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, | |||
229 | break; | 232 | break; |
230 | 233 | ||
231 | if (skb_cloned(skb) && | 234 | if (skb_cloned(skb) && |
232 | !skb_clone_writable(skb, | 235 | !skb_clone_writable(skb, ihl + sizeof(*icmph) + |
233 | ihl + sizeof(*icmph) + sizeof(*iph)) && | 236 | sizeof(*iph) + noff) && |
234 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | 237 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) |
235 | goto drop; | 238 | goto drop; |
236 | 239 | ||
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index f73542d2cdd0..e17096e3913c 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c | |||
@@ -65,37 +65,47 @@ static inline u32 addr_fold(void *addr) | |||
65 | return (a & 0xFFFFFFFF) ^ (BITS_PER_LONG > 32 ? a >> 32 : 0); | 65 | return (a & 0xFFFFFFFF) ^ (BITS_PER_LONG > 32 ? a >> 32 : 0); |
66 | } | 66 | } |
67 | 67 | ||
68 | static u32 flow_get_src(const struct sk_buff *skb) | 68 | static u32 flow_get_src(struct sk_buff *skb) |
69 | { | 69 | { |
70 | switch (skb->protocol) { | 70 | switch (skb->protocol) { |
71 | case htons(ETH_P_IP): | 71 | case htons(ETH_P_IP): |
72 | return ntohl(ip_hdr(skb)->saddr); | 72 | if (pskb_network_may_pull(skb, sizeof(struct iphdr))) |
73 | return ntohl(ip_hdr(skb)->saddr); | ||
74 | break; | ||
73 | case htons(ETH_P_IPV6): | 75 | case htons(ETH_P_IPV6): |
74 | return ntohl(ipv6_hdr(skb)->saddr.s6_addr32[3]); | 76 | if (pskb_network_may_pull(skb, sizeof(struct ipv6hdr))) |
75 | default: | 77 | return ntohl(ipv6_hdr(skb)->saddr.s6_addr32[3]); |
76 | return addr_fold(skb->sk); | 78 | break; |
77 | } | 79 | } |
80 | |||
81 | return addr_fold(skb->sk); | ||
78 | } | 82 | } |
79 | 83 | ||
80 | static u32 flow_get_dst(const struct sk_buff *skb) | 84 | static u32 flow_get_dst(struct sk_buff *skb) |
81 | { | 85 | { |
82 | switch (skb->protocol) { | 86 | switch (skb->protocol) { |
83 | case htons(ETH_P_IP): | 87 | case htons(ETH_P_IP): |
84 | return ntohl(ip_hdr(skb)->daddr); | 88 | if (pskb_network_may_pull(skb, sizeof(struct iphdr))) |
89 | return ntohl(ip_hdr(skb)->daddr); | ||
90 | break; | ||
85 | case htons(ETH_P_IPV6): | 91 | case htons(ETH_P_IPV6): |
86 | return ntohl(ipv6_hdr(skb)->daddr.s6_addr32[3]); | 92 | if (pskb_network_may_pull(skb, sizeof(struct ipv6hdr))) |
87 | default: | 93 | return ntohl(ipv6_hdr(skb)->daddr.s6_addr32[3]); |
88 | return addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol; | 94 | break; |
89 | } | 95 | } |
96 | |||
97 | return addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol; | ||
90 | } | 98 | } |
91 | 99 | ||
92 | static u32 flow_get_proto(const struct sk_buff *skb) | 100 | static u32 flow_get_proto(struct sk_buff *skb) |
93 | { | 101 | { |
94 | switch (skb->protocol) { | 102 | switch (skb->protocol) { |
95 | case htons(ETH_P_IP): | 103 | case htons(ETH_P_IP): |
96 | return ip_hdr(skb)->protocol; | 104 | return pskb_network_may_pull(skb, sizeof(struct iphdr)) ? |
105 | ip_hdr(skb)->protocol : 0; | ||
97 | case htons(ETH_P_IPV6): | 106 | case htons(ETH_P_IPV6): |
98 | return ipv6_hdr(skb)->nexthdr; | 107 | return pskb_network_may_pull(skb, sizeof(struct ipv6hdr)) ? |
108 | ipv6_hdr(skb)->nexthdr : 0; | ||
99 | default: | 109 | default: |
100 | return 0; | 110 | return 0; |
101 | } | 111 | } |
@@ -116,58 +126,64 @@ static int has_ports(u8 protocol) | |||
116 | } | 126 | } |
117 | } | 127 | } |
118 | 128 | ||
119 | static u32 flow_get_proto_src(const struct sk_buff *skb) | 129 | static u32 flow_get_proto_src(struct sk_buff *skb) |
120 | { | 130 | { |
121 | u32 res = 0; | ||
122 | |||
123 | switch (skb->protocol) { | 131 | switch (skb->protocol) { |
124 | case htons(ETH_P_IP): { | 132 | case htons(ETH_P_IP): { |
125 | struct iphdr *iph = ip_hdr(skb); | 133 | struct iphdr *iph; |
126 | 134 | ||
135 | if (!pskb_network_may_pull(skb, sizeof(*iph))) | ||
136 | break; | ||
137 | iph = ip_hdr(skb); | ||
127 | if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && | 138 | if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && |
128 | has_ports(iph->protocol)) | 139 | has_ports(iph->protocol) && |
129 | res = ntohs(*(__be16 *)((void *)iph + iph->ihl * 4)); | 140 | pskb_network_may_pull(skb, iph->ihl * 4 + 2)) |
141 | return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4)); | ||
130 | break; | 142 | break; |
131 | } | 143 | } |
132 | case htons(ETH_P_IPV6): { | 144 | case htons(ETH_P_IPV6): { |
133 | struct ipv6hdr *iph = ipv6_hdr(skb); | 145 | struct ipv6hdr *iph; |
134 | 146 | ||
147 | if (!pskb_network_may_pull(skb, sizeof(*iph) + 2)) | ||
148 | break; | ||
149 | iph = ipv6_hdr(skb); | ||
135 | if (has_ports(iph->nexthdr)) | 150 | if (has_ports(iph->nexthdr)) |
136 | res = ntohs(*(__be16 *)&iph[1]); | 151 | return ntohs(*(__be16 *)&iph[1]); |
137 | break; | 152 | break; |
138 | } | 153 | } |
139 | default: | ||
140 | res = addr_fold(skb->sk); | ||
141 | } | 154 | } |
142 | 155 | ||
143 | return res; | 156 | return addr_fold(skb->sk); |
144 | } | 157 | } |
145 | 158 | ||
146 | static u32 flow_get_proto_dst(const struct sk_buff *skb) | 159 | static u32 flow_get_proto_dst(struct sk_buff *skb) |
147 | { | 160 | { |
148 | u32 res = 0; | ||
149 | |||
150 | switch (skb->protocol) { | 161 | switch (skb->protocol) { |
151 | case htons(ETH_P_IP): { | 162 | case htons(ETH_P_IP): { |
152 | struct iphdr *iph = ip_hdr(skb); | 163 | struct iphdr *iph; |
153 | 164 | ||
165 | if (!pskb_network_may_pull(skb, sizeof(*iph))) | ||
166 | break; | ||
167 | iph = ip_hdr(skb); | ||
154 | if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && | 168 | if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && |
155 | has_ports(iph->protocol)) | 169 | has_ports(iph->protocol) && |
156 | res = ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 + 2)); | 170 | pskb_network_may_pull(skb, iph->ihl * 4 + 4)) |
171 | return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 + 2)); | ||
157 | break; | 172 | break; |
158 | } | 173 | } |
159 | case htons(ETH_P_IPV6): { | 174 | case htons(ETH_P_IPV6): { |
160 | struct ipv6hdr *iph = ipv6_hdr(skb); | 175 | struct ipv6hdr *iph; |
161 | 176 | ||
177 | if (!pskb_network_may_pull(skb, sizeof(*iph) + 4)) | ||
178 | break; | ||
179 | iph = ipv6_hdr(skb); | ||
162 | if (has_ports(iph->nexthdr)) | 180 | if (has_ports(iph->nexthdr)) |
163 | res = ntohs(*(__be16 *)((void *)&iph[1] + 2)); | 181 | return ntohs(*(__be16 *)((void *)&iph[1] + 2)); |
164 | break; | 182 | break; |
165 | } | 183 | } |
166 | default: | ||
167 | res = addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol; | ||
168 | } | 184 | } |
169 | 185 | ||
170 | return res; | 186 | return addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol; |
171 | } | 187 | } |
172 | 188 | ||
173 | static u32 flow_get_iif(const struct sk_buff *skb) | 189 | static u32 flow_get_iif(const struct sk_buff *skb) |
@@ -211,7 +227,7 @@ static u32 flow_get_nfct(const struct sk_buff *skb) | |||
211 | }) | 227 | }) |
212 | #endif | 228 | #endif |
213 | 229 | ||
214 | static u32 flow_get_nfct_src(const struct sk_buff *skb) | 230 | static u32 flow_get_nfct_src(struct sk_buff *skb) |
215 | { | 231 | { |
216 | switch (skb->protocol) { | 232 | switch (skb->protocol) { |
217 | case htons(ETH_P_IP): | 233 | case htons(ETH_P_IP): |
@@ -223,7 +239,7 @@ fallback: | |||
223 | return flow_get_src(skb); | 239 | return flow_get_src(skb); |
224 | } | 240 | } |
225 | 241 | ||
226 | static u32 flow_get_nfct_dst(const struct sk_buff *skb) | 242 | static u32 flow_get_nfct_dst(struct sk_buff *skb) |
227 | { | 243 | { |
228 | switch (skb->protocol) { | 244 | switch (skb->protocol) { |
229 | case htons(ETH_P_IP): | 245 | case htons(ETH_P_IP): |
@@ -235,14 +251,14 @@ fallback: | |||
235 | return flow_get_dst(skb); | 251 | return flow_get_dst(skb); |
236 | } | 252 | } |
237 | 253 | ||
238 | static u32 flow_get_nfct_proto_src(const struct sk_buff *skb) | 254 | static u32 flow_get_nfct_proto_src(struct sk_buff *skb) |
239 | { | 255 | { |
240 | return ntohs(CTTUPLE(skb, src.u.all)); | 256 | return ntohs(CTTUPLE(skb, src.u.all)); |
241 | fallback: | 257 | fallback: |
242 | return flow_get_proto_src(skb); | 258 | return flow_get_proto_src(skb); |
243 | } | 259 | } |
244 | 260 | ||
245 | static u32 flow_get_nfct_proto_dst(const struct sk_buff *skb) | 261 | static u32 flow_get_nfct_proto_dst(struct sk_buff *skb) |
246 | { | 262 | { |
247 | return ntohs(CTTUPLE(skb, dst.u.all)); | 263 | return ntohs(CTTUPLE(skb, dst.u.all)); |
248 | fallback: | 264 | fallback: |
@@ -281,7 +297,7 @@ static u32 flow_get_vlan_tag(const struct sk_buff *skb) | |||
281 | return tag & VLAN_VID_MASK; | 297 | return tag & VLAN_VID_MASK; |
282 | } | 298 | } |
283 | 299 | ||
284 | static u32 flow_key_get(const struct sk_buff *skb, int key) | 300 | static u32 flow_key_get(struct sk_buff *skb, int key) |
285 | { | 301 | { |
286 | switch (key) { | 302 | switch (key) { |
287 | case FLOW_KEY_SRC: | 303 | case FLOW_KEY_SRC: |
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h index dd9414e44200..425a1790b048 100644 --- a/net/sched/cls_rsvp.h +++ b/net/sched/cls_rsvp.h | |||
@@ -143,9 +143,17 @@ static int rsvp_classify(struct sk_buff *skb, struct tcf_proto *tp, | |||
143 | u8 tunnelid = 0; | 143 | u8 tunnelid = 0; |
144 | u8 *xprt; | 144 | u8 *xprt; |
145 | #if RSVP_DST_LEN == 4 | 145 | #if RSVP_DST_LEN == 4 |
146 | struct ipv6hdr *nhptr = ipv6_hdr(skb); | 146 | struct ipv6hdr *nhptr; |
147 | |||
148 | if (!pskb_network_may_pull(skb, sizeof(*nhptr))) | ||
149 | return -1; | ||
150 | nhptr = ipv6_hdr(skb); | ||
147 | #else | 151 | #else |
148 | struct iphdr *nhptr = ip_hdr(skb); | 152 | struct iphdr *nhptr; |
153 | |||
154 | if (!pskb_network_may_pull(skb, sizeof(*nhptr))) | ||
155 | return -1; | ||
156 | nhptr = ip_hdr(skb); | ||
149 | #endif | 157 | #endif |
150 | 158 | ||
151 | restart: | 159 | restart: |
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index c65762823f5e..534f33231c17 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c | |||
@@ -122,7 +122,11 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) | |||
122 | switch (skb->protocol) { | 122 | switch (skb->protocol) { |
123 | case htons(ETH_P_IP): | 123 | case htons(ETH_P_IP): |
124 | { | 124 | { |
125 | const struct iphdr *iph = ip_hdr(skb); | 125 | const struct iphdr *iph; |
126 | |||
127 | if (!pskb_network_may_pull(skb, sizeof(*iph))) | ||
128 | goto err; | ||
129 | iph = ip_hdr(skb); | ||
126 | h = (__force u32)iph->daddr; | 130 | h = (__force u32)iph->daddr; |
127 | h2 = (__force u32)iph->saddr ^ iph->protocol; | 131 | h2 = (__force u32)iph->saddr ^ iph->protocol; |
128 | if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && | 132 | if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && |
@@ -131,25 +135,32 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) | |||
131 | iph->protocol == IPPROTO_UDPLITE || | 135 | iph->protocol == IPPROTO_UDPLITE || |
132 | iph->protocol == IPPROTO_SCTP || | 136 | iph->protocol == IPPROTO_SCTP || |
133 | iph->protocol == IPPROTO_DCCP || | 137 | iph->protocol == IPPROTO_DCCP || |
134 | iph->protocol == IPPROTO_ESP)) | 138 | iph->protocol == IPPROTO_ESP) && |
139 | pskb_network_may_pull(skb, iph->ihl * 4 + 4)) | ||
135 | h2 ^= *(((u32*)iph) + iph->ihl); | 140 | h2 ^= *(((u32*)iph) + iph->ihl); |
136 | break; | 141 | break; |
137 | } | 142 | } |
138 | case htons(ETH_P_IPV6): | 143 | case htons(ETH_P_IPV6): |
139 | { | 144 | { |
140 | struct ipv6hdr *iph = ipv6_hdr(skb); | 145 | struct ipv6hdr *iph; |
146 | |||
147 | if (!pskb_network_may_pull(skb, sizeof(*iph))) | ||
148 | goto err; | ||
149 | iph = ipv6_hdr(skb); | ||
141 | h = (__force u32)iph->daddr.s6_addr32[3]; | 150 | h = (__force u32)iph->daddr.s6_addr32[3]; |
142 | h2 = (__force u32)iph->saddr.s6_addr32[3] ^ iph->nexthdr; | 151 | h2 = (__force u32)iph->saddr.s6_addr32[3] ^ iph->nexthdr; |
143 | if (iph->nexthdr == IPPROTO_TCP || | 152 | if ((iph->nexthdr == IPPROTO_TCP || |
144 | iph->nexthdr == IPPROTO_UDP || | 153 | iph->nexthdr == IPPROTO_UDP || |
145 | iph->nexthdr == IPPROTO_UDPLITE || | 154 | iph->nexthdr == IPPROTO_UDPLITE || |
146 | iph->nexthdr == IPPROTO_SCTP || | 155 | iph->nexthdr == IPPROTO_SCTP || |
147 | iph->nexthdr == IPPROTO_DCCP || | 156 | iph->nexthdr == IPPROTO_DCCP || |
148 | iph->nexthdr == IPPROTO_ESP) | 157 | iph->nexthdr == IPPROTO_ESP) && |
158 | pskb_network_may_pull(skb, sizeof(*iph) + 4)) | ||
149 | h2 ^= *(u32*)&iph[1]; | 159 | h2 ^= *(u32*)&iph[1]; |
150 | break; | 160 | break; |
151 | } | 161 | } |
152 | default: | 162 | default: |
163 | err: | ||
153 | h = (unsigned long)skb_dst(skb) ^ (__force u32)skb->protocol; | 164 | h = (unsigned long)skb_dst(skb) ^ (__force u32)skb->protocol; |
154 | h2 = (unsigned long)skb->sk; | 165 | h2 = (unsigned long)skb->sk; |
155 | } | 166 | } |
@@ -502,6 +513,12 @@ static unsigned long sfq_get(struct Qdisc *sch, u32 classid) | |||
502 | return 0; | 513 | return 0; |
503 | } | 514 | } |
504 | 515 | ||
516 | static unsigned long sfq_bind(struct Qdisc *sch, unsigned long parent, | ||
517 | u32 classid) | ||
518 | { | ||
519 | return 0; | ||
520 | } | ||
521 | |||
505 | static struct tcf_proto **sfq_find_tcf(struct Qdisc *sch, unsigned long cl) | 522 | static struct tcf_proto **sfq_find_tcf(struct Qdisc *sch, unsigned long cl) |
506 | { | 523 | { |
507 | struct sfq_sched_data *q = qdisc_priv(sch); | 524 | struct sfq_sched_data *q = qdisc_priv(sch); |
@@ -556,6 +573,7 @@ static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg) | |||
556 | static const struct Qdisc_class_ops sfq_class_ops = { | 573 | static const struct Qdisc_class_ops sfq_class_ops = { |
557 | .get = sfq_get, | 574 | .get = sfq_get, |
558 | .tcf_chain = sfq_find_tcf, | 575 | .tcf_chain = sfq_find_tcf, |
576 | .bind_tcf = sfq_bind, | ||
559 | .dump = sfq_dump_class, | 577 | .dump = sfq_dump_class, |
560 | .dump_stats = sfq_dump_class_stats, | 578 | .dump_stats = sfq_dump_class_stats, |
561 | .walk = sfq_walk, | 579 | .walk = sfq_walk, |