| 303 |
303 |
altq_etherclassify(&p->if_snd, m, &pktattr);
|
| 304 |
304 |
|
| 305 |
305 |
/*
|
| 306 |
|
* If the LINK0 flag is set, it means the underlying interface
|
| 307 |
|
* can do VLAN tag insertion itself and doesn't require us to
|
| 308 |
|
* create a special header for it. In this case, we just pass
|
| 309 |
|
* the packet along. However, we need some way to tell the
|
| 310 |
|
* interface where the packet came from so that it knows how
|
| 311 |
|
* to find the VLAN tag to use, so we set the rcvif in the
|
| 312 |
|
* mbuf header to our ifnet.
|
|
306 |
* If underlying interface can do VLAN tag insertion itself,
|
|
307 |
* just pass the packet along. However, we need some way to
|
|
308 |
* tell the interface where the packet came from so that it
|
|
309 |
* knows how to find the VLAN tag to use, so we set the rcvif
|
|
310 |
* in the mbuf header to our ifnet.
|
| 313 |
311 |
*
|
| 314 |
312 |
* Note: we also set the M_PROTO1 flag in the mbuf to let
|
| 315 |
313 |
* the parent driver know that the rcvif pointer is really
|
| ... | ... | |
| 320 |
318 |
* following potentially bogus rcvif pointers off into
|
| 321 |
319 |
* never-never land.
|
| 322 |
320 |
*/
|
| 323 |
|
if (ifp->if_flags & IFF_LINK0) {
|
|
321 |
if (p->if_capenable & IFCAP_VLAN_HWTAGGING) {
|
| 324 |
322 |
m->m_pkthdr.rcvif = ifp;
|
| 325 |
323 |
m->m_flags |= M_PROTO1;
|
| 326 |
324 |
} else {
|
| ... | ... | |
| 379 |
377 |
{
|
| 380 |
378 |
struct bpf_if *bif;
|
| 381 |
379 |
struct ifvlan *ifv;
|
| 382 |
|
struct ether_header *eh = mtod(m, struct ether_header *);
|
| 383 |
380 |
struct ifnet *rcvif;
|
| 384 |
381 |
|
| 385 |
|
m_adj(m, ETHER_HDR_LEN);
|
| 386 |
382 |
rcvif = m->m_pkthdr.rcvif;
|
| 387 |
383 |
|
| 388 |
384 |
ASSERT_SERIALIZED(rcvif->if_serializer);
|
| ... | ... | |
| 392 |
388 |
* bpf tap if active.
|
| 393 |
389 |
*/
|
| 394 |
390 |
if ((bif = rcvif->if_bpf) != NULL) {
|
|
391 |
struct ether_header *eh;
|
| 395 |
392 |
struct ether_vlan_header evh;
|
| 396 |
393 |
|
|
394 |
eh = mtod(m, struct ether_header *);
|
|
395 |
m_adj(m, ETHER_HDR_LEN);
|
| 397 |
396 |
bcopy(eh, &evh, 2*ETHER_ADDR_LEN);
|
| 398 |
397 |
evh.evl_encap_proto = htons(ETHERTYPE_VLAN);
|
| 399 |
398 |
evh.evl_tag = htons(t);
|
| 400 |
399 |
evh.evl_proto = eh->ether_type;
|
| 401 |
|
|
| 402 |
400 |
bpf_ptap(bif, m, &evh, ETHER_HDR_LEN + EVL_ENCAPLEN);
|
|
401 |
/* XXX assumes data was left intact */
|
|
402 |
M_PREPEND(m, ETHER_HDR_LEN, MB_WAIT);
|
| 403 |
403 |
}
|
| 404 |
404 |
|
| 405 |
405 |
for (ifv = LIST_FIRST(&ifv_list); ifv != NULL;
|
| ... | ... | |
| 423 |
423 |
ifv->ifv_if.if_ipackets++;
|
| 424 |
424 |
lwkt_serialize_exit(rcvif->if_serializer);
|
| 425 |
425 |
lwkt_serialize_enter(ifv->ifv_if.if_serializer);
|
| 426 |
|
ether_input(&ifv->ifv_if, eh, m);
|
|
426 |
ether_input(&ifv->ifv_if, NULL, m);
|
| 427 |
427 |
lwkt_serialize_exit(ifv->ifv_if.if_serializer);
|
| 428 |
428 |
lwkt_serialize_enter(rcvif->if_serializer);
|
| 429 |
429 |
return 0;
|
| ... | ... | |
| 434 |
434 |
{
|
| 435 |
435 |
struct ifvlan *ifv;
|
| 436 |
436 |
struct ifnet *rcvif;
|
|
437 |
struct ether_header eh_copy;
|
| 437 |
438 |
|
| 438 |
439 |
rcvif = m->m_pkthdr.rcvif;
|
| 439 |
440 |
ASSERT_SERIALIZED(rcvif->if_serializer);
|
| ... | ... | |
| 455 |
456 |
/*
|
| 456 |
457 |
* Having found a valid vlan interface corresponding to
|
| 457 |
458 |
* the given source interface and vlan tag, remove the
|
| 458 |
|
* encapsulation, and run the real packet through
|
| 459 |
|
* ether_input() a second time (it had better be
|
|
459 |
* remaining encapsulation (ether_vlan_header minus the ether_header
|
|
460 |
* that had already been removed) and run the real packet
|
|
461 |
* through ether_input() a second time (it had better be
|
| 460 |
462 |
* reentrant!).
|
| 461 |
463 |
*/
|
|
464 |
eh_copy = *eh;
|
|
465 |
eh_copy.ether_type = mtod(m, u_int16_t *)[1]; /* evl_proto */
|
| 462 |
466 |
m->m_pkthdr.rcvif = &ifv->ifv_if;
|
| 463 |
|
eh->ether_type = mtod(m, u_int16_t *)[1];
|
| 464 |
|
m->m_data += EVL_ENCAPLEN;
|
| 465 |
|
m->m_len -= EVL_ENCAPLEN;
|
| 466 |
|
m->m_pkthdr.len -= EVL_ENCAPLEN;
|
|
467 |
m_adj(m, EVL_ENCAPLEN);
|
|
468 |
M_PREPEND(m, ETHER_HDR_LEN, MB_WAIT);
|
|
469 |
*(struct ether_header *)mtod(m, void *) = eh_copy;
|
| 467 |
470 |
|
| 468 |
471 |
ifv->ifv_if.if_ipackets++;
|
| 469 |
472 |
lwkt_serialize_exit(rcvif->if_serializer);
|
| 470 |
473 |
lwkt_serialize_enter(ifv->ifv_if.if_serializer);
|
| 471 |
|
ether_input(&ifv->ifv_if, eh, m);
|
|
474 |
ether_input(&ifv->ifv_if, NULL, m);
|
| 472 |
475 |
lwkt_serialize_exit(ifv->ifv_if.if_serializer);
|
| 473 |
476 |
lwkt_serialize_enter(rcvif->if_serializer);
|
| 474 |
477 |
return 0;
|
| ... | ... | |
| 484 |
487 |
if (ifv->ifv_p)
|
| 485 |
488 |
return EBUSY;
|
| 486 |
489 |
ifv->ifv_p = p;
|
| 487 |
|
if (p->if_data.ifi_hdrlen == sizeof(struct ether_vlan_header))
|
|
490 |
if (p->if_capenable & IFCAP_VLAN_MTU)
|
| 488 |
491 |
ifv->ifv_if.if_mtu = p->if_mtu;
|
| 489 |
492 |
else
|
| 490 |
493 |
ifv->ifv_if.if_mtu = p->if_data.ifi_mtu - EVL_ENCAPLEN;
|