aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/8021q/vlan_dev.c113
1 files changed, 24 insertions, 89 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index e19e49184ae5..57799af51088 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -114,77 +114,49 @@ static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb)
114int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, 114int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
115 struct packet_type *ptype, struct net_device *orig_dev) 115 struct packet_type *ptype, struct net_device *orig_dev)
116{ 116{
117 unsigned char *rawp = NULL; 117 unsigned char *rawp;
118 struct vlan_hdr *vhdr; 118 struct vlan_hdr *vhdr;
119 unsigned short vid; 119 unsigned short vid;
120 struct net_device_stats *stats; 120 struct net_device_stats *stats;
121 unsigned short vlan_TCI; 121 unsigned short vlan_TCI;
122 __be16 proto; 122 __be16 proto;
123 123
124 if (dev->nd_net != &init_net) { 124 if (dev->nd_net != &init_net)
125 kfree_skb(skb); 125 goto err_free;
126 return -1;
127 }
128 126
129 skb = skb_share_check(skb, GFP_ATOMIC); 127 skb = skb_share_check(skb, GFP_ATOMIC);
130 if (skb == NULL) 128 if (skb == NULL)
131 return -1; 129 goto err_free;
132
133 if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) {
134 kfree_skb(skb);
135 return -1;
136 }
137 130
138 vhdr = (struct vlan_hdr *)(skb->data); 131 if (unlikely(!pskb_may_pull(skb, VLAN_HLEN)))
132 goto err_free;
139 133
140 /* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */ 134 vhdr = (struct vlan_hdr *)skb->data;
141 vlan_TCI = ntohs(vhdr->h_vlan_TCI); 135 vlan_TCI = ntohs(vhdr->h_vlan_TCI);
142
143 vid = (vlan_TCI & VLAN_VID_MASK); 136 vid = (vlan_TCI & VLAN_VID_MASK);
144 137
145 /* Ok, we will find the correct VLAN device, strip the header,
146 * and then go on as usual.
147 */
148
149 /* We have 12 bits of vlan ID.
150 *
151 * We must not drop allow preempt until we hold a
152 * reference to the device (netif_rx does that) or we
153 * fail.
154 */
155
156 rcu_read_lock(); 138 rcu_read_lock();
157 skb->dev = __find_vlan_dev(dev, vid); 139 skb->dev = __find_vlan_dev(dev, vid);
158 if (!skb->dev) { 140 if (!skb->dev) {
159 rcu_read_unlock();
160 pr_debug("%s: ERROR: No net_device for VID: %u on dev: %s\n", 141 pr_debug("%s: ERROR: No net_device for VID: %u on dev: %s\n",
161 __FUNCTION__, (unsigned int)vid, dev->name); 142 __FUNCTION__, (unsigned int)vid, dev->name);
162 kfree_skb(skb); 143 goto err_unlock;
163 return -1;
164 } 144 }
165 145
166 skb->dev->last_rx = jiffies; 146 skb->dev->last_rx = jiffies;
167 147
168 /* Bump the rx counters for the VLAN device. */
169 stats = &skb->dev->stats; 148 stats = &skb->dev->stats;
170 stats->rx_packets++; 149 stats->rx_packets++;
171 stats->rx_bytes += skb->len; 150 stats->rx_bytes += skb->len;
172 151
173 /* Take off the VLAN header (4 bytes currently) */
174 skb_pull_rcsum(skb, VLAN_HLEN); 152 skb_pull_rcsum(skb, VLAN_HLEN);
175 153
176 /*
177 * Deal with ingress priority mapping.
178 */
179 skb->priority = vlan_get_ingress_priority(skb->dev, 154 skb->priority = vlan_get_ingress_priority(skb->dev,
180 ntohs(vhdr->h_vlan_TCI)); 155 ntohs(vhdr->h_vlan_TCI));
181 156
182 pr_debug("%s: priority: %u for TCI: %hu\n", 157 pr_debug("%s: priority: %u for TCI: %hu\n",
183 __FUNCTION__, skb->priority, ntohs(vhdr->h_vlan_TCI)); 158 __FUNCTION__, skb->priority, ntohs(vhdr->h_vlan_TCI));
184 159
185 /* The ethernet driver already did the pkt_type calculations
186 * for us...
187 */
188 switch (skb->pkt_type) { 160 switch (skb->pkt_type) {
189 case PACKET_BROADCAST: /* Yeah, stats collect these together.. */ 161 case PACKET_BROADCAST: /* Yeah, stats collect these together.. */
190 /* stats->broadcast ++; // no such counter :-( */ 162 /* stats->broadcast ++; // no such counter :-( */
@@ -201,7 +173,6 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
201 */ 173 */
202 if (!compare_ether_addr(eth_hdr(skb)->h_dest, 174 if (!compare_ether_addr(eth_hdr(skb)->h_dest,
203 skb->dev->dev_addr)) 175 skb->dev->dev_addr))
204 /* It is for our (changed) MAC-address! */
205 skb->pkt_type = PACKET_HOST; 176 skb->pkt_type = PACKET_HOST;
206 break; 177 break;
207 default: 178 default:
@@ -211,81 +182,45 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
211 /* Was a VLAN packet, grab the encapsulated protocol, which the layer 182 /* Was a VLAN packet, grab the encapsulated protocol, which the layer
212 * three protocols care about. 183 * three protocols care about.
213 */ 184 */
214 /* proto = get_unaligned(&vhdr->h_vlan_encapsulated_proto); */
215 proto = vhdr->h_vlan_encapsulated_proto; 185 proto = vhdr->h_vlan_encapsulated_proto;
216
217 skb->protocol = proto;
218 if (ntohs(proto) >= 1536) { 186 if (ntohs(proto) >= 1536) {
219 /* place it back on the queue to be handled by 187 skb->protocol = proto;
220 * true layer 3 protocols. 188 goto recv;
221 */
222
223 /* See if we are configured to re-write the VLAN header
224 * to make it look like ethernet...
225 */
226 skb = vlan_check_reorder_header(skb);
227
228 /* Can be null if skb-clone fails when re-ordering */
229 if (skb) {
230 netif_rx(skb);
231 } else {
232 /* TODO: Add a more specific counter here. */
233 stats->rx_errors++;
234 }
235 rcu_read_unlock();
236 return 0;
237 } 189 }
238 190
239 rawp = skb->data;
240
241 /* 191 /*
242 * This is a magic hack to spot IPX packets. Older Novell breaks 192 * This is a magic hack to spot IPX packets. Older Novell breaks
243 * the protocol design and runs IPX over 802.3 without an 802.2 LLC 193 * the protocol design and runs IPX over 802.3 without an 802.2 LLC
244 * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This 194 * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
245 * won't work for fault tolerant netware but does for the rest. 195 * won't work for fault tolerant netware but does for the rest.
246 */ 196 */
197 rawp = skb->data;
247 if (*(unsigned short *)rawp == 0xFFFF) { 198 if (*(unsigned short *)rawp == 0xFFFF) {
248 skb->protocol = htons(ETH_P_802_3); 199 skb->protocol = htons(ETH_P_802_3);
249 /* place it back on the queue to be handled by true layer 3 200 goto recv;
250 * protocols. */
251
252 /* See if we are configured to re-write the VLAN header
253 * to make it look like ethernet...
254 */
255 skb = vlan_check_reorder_header(skb);
256
257 /* Can be null if skb-clone fails when re-ordering */
258 if (skb) {
259 netif_rx(skb);
260 } else {
261 /* TODO: Add a more specific counter here. */
262 stats->rx_errors++;
263 }
264 rcu_read_unlock();
265 return 0;
266 } 201 }
267 202
268 /* 203 /*
269 * Real 802.2 LLC 204 * Real 802.2 LLC
270 */ 205 */
271 skb->protocol = htons(ETH_P_802_2); 206 skb->protocol = htons(ETH_P_802_2);
272 /* place it back on the queue to be handled by upper layer protocols.
273 */
274 207
275 /* See if we are configured to re-write the VLAN header 208recv:
276 * to make it look like ethernet...
277 */
278 skb = vlan_check_reorder_header(skb); 209 skb = vlan_check_reorder_header(skb);
279 210 if (!skb) {
280 /* Can be null if skb-clone fails when re-ordering */
281 if (skb) {
282 netif_rx(skb);
283 } else {
284 /* TODO: Add a more specific counter here. */
285 stats->rx_errors++; 211 stats->rx_errors++;
212 goto err_unlock;
286 } 213 }
214
215 netif_rx(skb);
287 rcu_read_unlock(); 216 rcu_read_unlock();
288 return 0; 217 return NET_RX_SUCCESS;
218
219err_unlock:
220 rcu_read_unlock();
221err_free:
222 kfree_skb(skb);
223 return NET_RX_DROP;
289} 224}
290 225
291static inline unsigned short 226static inline unsigned short