net: Do not overwrite if_vlan's PCP
In commitc7cffd65c5
the function ether_8021q_frame() was slightly refactored to use pointer of struct ether_8021q_tag as parameter qtag to include the new option proto. It is wrong to write to qtag->pcp as it will effectively change the memory that qtag points to. Unfortunately the transmit routine of if_vlan parses pointer of the member ifv_qtag of its softc which stores vlan interface's PCP internally, when transmitting mbufs that contains PCP the vlan interface's PCP will get overwritten. Fix by operating on a local copy of qtag->pcp. Also mark 'struct ether_8021q_tag' as const so that compilers can pick up such kind of bug. PR: 273304 Reviewed by: kp Fixes:c7cffd65c5
Add support for stacked VLANs (IEEE 802.1ad, AKA Q-in-Q) MFC after: 3 days Differential Revision: https://reviews.freebsd.org/D39505
This commit is contained in:
parent
d18c845f99
commit
838c8c4786
@ -446,7 +446,7 @@ void ether_vlan_mtap(struct bpf_if *, struct mbuf *,
|
||||
void *, u_int);
|
||||
struct mbuf *ether_vlanencap_proto(struct mbuf *, uint16_t, uint16_t);
|
||||
bool ether_8021q_frame(struct mbuf **mp, struct ifnet *ife,
|
||||
struct ifnet *p, struct ether_8021q_tag *);
|
||||
struct ifnet *p, const struct ether_8021q_tag *);
|
||||
void ether_gen_addr(struct ifnet *ifp, struct ether_addr *hwaddr);
|
||||
|
||||
static __inline struct mbuf *ether_vlanencap(struct mbuf *m, uint16_t tag)
|
||||
|
@ -1400,11 +1400,12 @@ SYSCTL_INT(_net_link_vlan, OID_AUTO, mtag_pcp, CTLFLAG_RW | CTLFLAG_VNET,
|
||||
|
||||
bool
|
||||
ether_8021q_frame(struct mbuf **mp, struct ifnet *ife, struct ifnet *p,
|
||||
struct ether_8021q_tag *qtag)
|
||||
const struct ether_8021q_tag *qtag)
|
||||
{
|
||||
struct m_tag *mtag;
|
||||
int n;
|
||||
uint16_t tag;
|
||||
uint8_t pcp = qtag->pcp;
|
||||
static const char pad[8]; /* just zeros */
|
||||
|
||||
/*
|
||||
@ -1437,7 +1438,7 @@ ether_8021q_frame(struct mbuf **mp, struct ifnet *ife, struct ifnet *p,
|
||||
* If PCP is set in mbuf, use it
|
||||
*/
|
||||
if ((*mp)->m_flags & M_VLANTAG) {
|
||||
qtag->pcp = EVL_PRIOFTAG((*mp)->m_pkthdr.ether_vtag);
|
||||
pcp = EVL_PRIOFTAG((*mp)->m_pkthdr.ether_vtag);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1451,7 +1452,7 @@ ether_8021q_frame(struct mbuf **mp, struct ifnet *ife, struct ifnet *p,
|
||||
MTAG_8021Q_PCP_OUT, NULL)) != NULL)
|
||||
tag = EVL_MAKETAG(qtag->vid, *(uint8_t *)(mtag + 1), 0);
|
||||
else
|
||||
tag = EVL_MAKETAG(qtag->vid, qtag->pcp, 0);
|
||||
tag = EVL_MAKETAG(qtag->vid, pcp, 0);
|
||||
if ((p->if_capenable & IFCAP_VLAN_HWTAGGING) &&
|
||||
(qtag->proto == ETHERTYPE_VLAN)) {
|
||||
(*mp)->m_pkthdr.ether_vtag = tag;
|
||||
|
Loading…
Reference in New Issue
Block a user