| 1364 | "Retain VLAN PCP information as packets are passed up the stack"); |
| 1365 | |
| 1366 | bool |
| 1367 | ether_8021q_frame(struct mbuf **mp, struct ifnet *ife, struct ifnet *p, |
| 1368 | struct ether_8021q_tag *qtag) |
| 1369 | { |
| 1370 | struct m_tag *mtag; |
| 1371 | int n; |
| 1372 | uint16_t tag; |
| 1373 | static const char pad[8]; /* just zeros */ |
| 1374 | |
| 1375 | /* |
| 1376 | * Pad the frame to the minimum size allowed if told to. |
| 1377 | * This option is in accord with IEEE Std 802.1Q, 2003 Ed., |
| 1378 | * paragraph C.4.4.3.b. It can help to work around buggy |
| 1379 | * bridges that violate paragraph C.4.4.3.a from the same |
| 1380 | * document, i.e., fail to pad short frames after untagging. |
| 1381 | * E.g., a tagged frame 66 bytes long (incl. FCS) is OK, but |
| 1382 | * untagging it will produce a 62-byte frame, which is a runt |
| 1383 | * and requires padding. There are VLAN-enabled network |
| 1384 | * devices that just discard such runts instead or mishandle |
| 1385 | * them somehow. |
| 1386 | */ |
| 1387 | if (V_soft_pad && p->if_type == IFT_ETHER) { |
| 1388 | for (n = ETHERMIN + ETHER_HDR_LEN - (*mp)->m_pkthdr.len; |
| 1389 | n > 0; n -= sizeof(pad)) { |
| 1390 | if (!m_append(*mp, min(n, sizeof(pad)), pad)) |
| 1391 | break; |
| 1392 | } |
| 1393 | if (n > 0) { |
| 1394 | m_freem(*mp); |
| 1395 | *mp = NULL; |
| 1396 | if_printf(ife, "cannot pad short frame"); |
| 1397 | return (false); |
| 1398 | } |
| 1399 | } |
| 1400 | |
| 1401 | /* |
| 1402 | * If PCP is set in mbuf, use it |
| 1403 | */ |
| 1404 | if ((*mp)->m_flags & M_VLANTAG) { |
| 1405 | qtag->pcp = EVL_PRIOFTAG((*mp)->m_pkthdr.ether_vtag); |
| 1406 | } |
| 1407 | |
| 1408 | /* |
| 1409 | * If underlying interface can do VLAN tag insertion itself, |
| 1410 | * just pass the packet along. However, we need some way to |
| 1411 | * tell the interface where the packet came from so that it |
| 1412 | * knows how to find the VLAN tag to use, so we attach a |
| 1413 | * packet tag that holds it. |
| 1414 | */ |
| 1415 | if (vlan_mtag_pcp && (mtag = m_tag_locate(*mp, MTAG_8021Q, |
| 1416 | MTAG_8021Q_PCP_OUT, NULL)) != NULL) |
| 1417 | tag = EVL_MAKETAG(qtag->vid, *(uint8_t *)(mtag + 1), 0); |
| 1418 | else |
| 1419 | tag = EVL_MAKETAG(qtag->vid, qtag->pcp, 0); |
| 1420 | if ((p->if_capenable & IFCAP_VLAN_HWTAGGING) && |
| 1421 | (qtag->proto == ETHERTYPE_VLAN)) { |
| 1422 | (*mp)->m_pkthdr.ether_vtag = tag; |
| 1423 | (*mp)->m_flags |= M_VLANTAG; |
no test coverage detected