aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhenlei Huang <zlei@FreeBSD.org>2023-09-06 10:15:14 +0000
committerZhenlei Huang <zlei@FreeBSD.org>2023-09-20 10:00:37 +0000
commit8303afca1765148d0069ce5144072b3ae9cab61e (patch)
tree84523e3a9df5926834ae26590b839f248bdef411
parentc3e092dacbc8ba38c0be175f95403b3b15da736f (diff)
downloadsrc-8303afca1765148d0069ce5144072b3ae9cab61e.tar.gz
src-8303afca1765148d0069ce5144072b3ae9cab61e.zip
net: Check per-flow priority code point for untagged traffic
Commit 868aabb4708d introduced per-flow priority. There's a defect in the logic for untagged traffic, it does not check M_VLANTAG set in the mbuf packet header or MTAG_8021Q/MTAG_8021Q_PCP_OUT tag set by firewall, then can result missing desired priority in the outbound packets. For mbuf packet with M_VLANTAG in header, some interfaces happen to work due to bug in the drivers mentioned in D39499. As modern interfaces have VLAN hardware offloading, the defect is barely noticeable unless the feature per-flow priority is widely tested. As a side effect of this defect, the soft padding to work around buggy bridges is bypassed. That may result in regression if soft padding is requested. PR: 273431 Discussed with: kib Fixes: 868aabb4708d Add IP(V6)_VLAN_PCP to set 802.1 priority per-flow MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D39536 (cherry picked from commit 49d6743da15fe378782e43776df8b4fd4f84c8d0) (cherry picked from commit c750055382f73db964c20f8eba855a9ac9e19591)
-rw-r--r--sys/net/if_ethersubr.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index d8043f0551ff..a3466c94d312 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -118,6 +118,8 @@ static int ether_resolvemulti(struct ifnet *, struct sockaddr **,
struct sockaddr *);
static int ether_requestencap(struct ifnet *, struct if_encap_req *);
+static inline bool ether_do_pcp(struct ifnet *, struct mbuf *);
+
#define senderr(e) do { error = (e); goto bad;} while (0)
static void
@@ -466,11 +468,7 @@ ether_set_pcp(struct mbuf **mp, struct ifnet *ifp, uint8_t pcp)
int
ether_output_frame(struct ifnet *ifp, struct mbuf *m)
{
- uint8_t pcp;
-
- pcp = ifp->if_pcp;
- if (pcp != IFNET_PCP_NONE && ifp->if_type != IFT_L2VLAN &&
- !ether_set_pcp(&m, ifp, pcp))
+ if (ether_do_pcp(ifp, m) && !ether_set_pcp(&m, ifp, ifp->if_pcp))
return (0);
if (PFIL_HOOKED_OUT(V_link_pfil_head))
@@ -1355,6 +1353,19 @@ SYSCTL_INT(_net_link_vlan, OID_AUTO, mtag_pcp, CTLFLAG_RW,
&vlan_mtag_pcp, 0,
"Retain VLAN PCP information as packets are passed up the stack");
+static inline bool
+ether_do_pcp(struct ifnet *ifp, struct mbuf *m)
+{
+ if (ifp->if_type == IFT_L2VLAN)
+ return (false);
+ if (ifp->if_pcp != IFNET_PCP_NONE || (m->m_flags & M_VLANTAG) != 0)
+ return (true);
+ if (vlan_mtag_pcp &&
+ m_tag_locate(m, MTAG_8021Q, MTAG_8021Q_PCP_OUT, NULL) != NULL)
+ return (true);
+ return (false);
+}
+
bool
ether_8021q_frame(struct mbuf **mp, struct ifnet *ife, struct ifnet *p,
const struct ether_8021q_tag *qtag)