Skip to content

Commit 6b5eeb7

Browse files
bmorkdavem330
authored andcommitted
net: cdc_mbim: handle unaccelerated VLAN tagged frames
This driver maps 802.1q VLANs to MBIM sessions. The mapping is based on a bogus assumption that all tagged frames will use the acceleration API because we enable NETIF_F_HW_VLAN_CTAG_TX. This fails for e.g. frames tagged in userspace using packet sockets. Such frames will erroneously be considered as untagged and silently dropped based on not being IP. Fix by falling back to looking into the ethernet header for a tag if no accelerated tag was found. Fixes: a82c7ce ("net: cdc_ncm: map MBIM IPS SessionID to VLAN ID") Cc: Greg Suarez <[email protected]> Signed-off-by: Bjørn Mork <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b3d4056 commit 6b5eeb7

File tree

1 file changed

+28
-11
lines changed

1 file changed

+28
-11
lines changed

drivers/net/usb/cdc_mbim.c

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,16 @@ static void cdc_mbim_unbind(struct usbnet *dev, struct usb_interface *intf)
120120
cdc_ncm_unbind(dev, intf);
121121
}
122122

123+
/* verify that the ethernet protocol is IPv4 or IPv6 */
124+
static bool is_ip_proto(__be16 proto)
125+
{
126+
switch (proto) {
127+
case htons(ETH_P_IP):
128+
case htons(ETH_P_IPV6):
129+
return true;
130+
}
131+
return false;
132+
}
123133

124134
static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
125135
{
@@ -128,6 +138,7 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
128138
struct cdc_ncm_ctx *ctx = info->ctx;
129139
__le32 sign = cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN);
130140
u16 tci = 0;
141+
bool is_ip;
131142
u8 *c;
132143

133144
if (!ctx)
@@ -137,25 +148,32 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
137148
if (skb->len <= ETH_HLEN)
138149
goto error;
139150

151+
/* Some applications using e.g. packet sockets will
152+
* bypass the VLAN acceleration and create tagged
153+
* ethernet frames directly. We primarily look for
154+
* the accelerated out-of-band tag, but fall back if
155+
* required
156+
*/
157+
skb_reset_mac_header(skb);
158+
if (vlan_get_tag(skb, &tci) < 0 && skb->len > VLAN_ETH_HLEN &&
159+
__vlan_get_tag(skb, &tci) == 0) {
160+
is_ip = is_ip_proto(vlan_eth_hdr(skb)->h_vlan_encapsulated_proto);
161+
skb_pull(skb, VLAN_ETH_HLEN);
162+
} else {
163+
is_ip = is_ip_proto(eth_hdr(skb)->h_proto);
164+
skb_pull(skb, ETH_HLEN);
165+
}
166+
140167
/* mapping VLANs to MBIM sessions:
141168
* no tag => IPS session <0>
142169
* 1 - 255 => IPS session <vlanid>
143170
* 256 - 511 => DSS session <vlanid - 256>
144171
* 512 - 4095 => unsupported, drop
145172
*/
146-
vlan_get_tag(skb, &tci);
147-
148173
switch (tci & 0x0f00) {
149174
case 0x0000: /* VLAN ID 0 - 255 */
150-
/* verify that datagram is IPv4 or IPv6 */
151-
skb_reset_mac_header(skb);
152-
switch (eth_hdr(skb)->h_proto) {
153-
case htons(ETH_P_IP):
154-
case htons(ETH_P_IPV6):
155-
break;
156-
default:
175+
if (!is_ip)
157176
goto error;
158-
}
159177
c = (u8 *)&sign;
160178
c[3] = tci;
161179
break;
@@ -169,7 +187,6 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
169187
"unsupported tci=0x%04x\n", tci);
170188
goto error;
171189
}
172-
skb_pull(skb, ETH_HLEN);
173190
}
174191

175192
spin_lock_bh(&ctx->mtx);

0 commit comments

Comments
 (0)