13
13
#include <linux/module.h>
14
14
#include <linux/netdevice.h>
15
15
#include <linux/ethtool.h>
16
+ #include <linux/if_vlan.h>
16
17
#include <linux/ip.h>
17
18
#include <linux/mii.h>
18
19
#include <linux/usb.h>
@@ -107,6 +108,9 @@ static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf)
107
108
108
109
/* MBIM cannot do ARP */
109
110
dev -> net -> flags |= IFF_NOARP ;
111
+
112
+ /* no need to put the VLAN tci in the packet headers */
113
+ dev -> net -> features |= NETIF_F_HW_VLAN_TX ;
110
114
err :
111
115
return ret ;
112
116
}
@@ -131,6 +135,9 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
131
135
struct sk_buff * skb_out ;
132
136
struct cdc_mbim_state * info = (void * )& dev -> data ;
133
137
struct cdc_ncm_ctx * ctx = info -> ctx ;
138
+ __le32 sign = cpu_to_le32 (USB_CDC_MBIM_NDP16_IPS_SIGN );
139
+ u16 tci = 0 ;
140
+ u8 * c ;
134
141
135
142
if (!ctx )
136
143
goto error ;
@@ -139,6 +146,24 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
139
146
if (skb -> len <= sizeof (ETH_HLEN ))
140
147
goto error ;
141
148
149
+ /* mapping VLANs to MBIM sessions:
150
+ * no tag => IPS session <0>
151
+ * 1 - 255 => IPS session <vlanid>
152
+ * 256 - 4095 => unsupported, drop
153
+ */
154
+ vlan_get_tag (skb , & tci );
155
+
156
+ switch (tci & 0x0f00 ) {
157
+ case 0x0000 : /* VLAN ID 0 - 255 */
158
+ c = (u8 * )& sign ;
159
+ c [3 ] = tci ;
160
+ break ;
161
+ default :
162
+ netif_err (dev , tx_err , dev -> net ,
163
+ "unsupported tci=0x%04x\n" , tci );
164
+ goto error ;
165
+ }
166
+
142
167
skb_reset_mac_header (skb );
143
168
switch (eth_hdr (skb )-> h_proto ) {
144
169
case htons (ETH_P_IP ):
@@ -151,7 +176,7 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
151
176
}
152
177
153
178
spin_lock_bh (& ctx -> mtx );
154
- skb_out = cdc_ncm_fill_tx_frame (ctx , skb , cpu_to_le32 ( USB_CDC_MBIM_NDP16_IPS_SIGN ) );
179
+ skb_out = cdc_ncm_fill_tx_frame (ctx , skb , sign );
155
180
spin_unlock_bh (& ctx -> mtx );
156
181
return skb_out ;
157
182
@@ -162,11 +187,14 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
162
187
return NULL ;
163
188
}
164
189
165
- static struct sk_buff * cdc_mbim_process_dgram (struct usbnet * dev , u8 * buf , size_t len )
190
+ static struct sk_buff * cdc_mbim_process_dgram (struct usbnet * dev , u8 * buf , size_t len , u16 tci )
166
191
{
167
192
__be16 proto ;
168
193
struct sk_buff * skb = NULL ;
169
194
195
+ if (len < sizeof (struct iphdr ))
196
+ goto err ;
197
+
170
198
switch (* buf & 0xf0 ) {
171
199
case 0x40 :
172
200
proto = htons (ETH_P_IP );
@@ -191,14 +219,19 @@ static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_
191
219
192
220
/* add datagram */
193
221
memcpy (skb_put (skb , len ), buf , len );
222
+
223
+ /* map MBIM session to VLAN */
224
+ if (tci )
225
+ vlan_put_tag (skb , tci );
194
226
err :
195
227
return skb ;
196
228
}
197
229
198
230
static int cdc_mbim_rx_fixup (struct usbnet * dev , struct sk_buff * skb_in )
199
231
{
200
232
struct sk_buff * skb ;
201
- struct cdc_ncm_ctx * ctx = (struct cdc_ncm_ctx * )dev -> data [0 ];
233
+ struct cdc_mbim_state * info = (void * )& dev -> data ;
234
+ struct cdc_ncm_ctx * ctx = info -> ctx ;
202
235
int len ;
203
236
int nframes ;
204
237
int x ;
@@ -207,6 +240,8 @@ static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
207
240
struct usb_cdc_ncm_dpe16 * dpe16 ;
208
241
int ndpoffset ;
209
242
int loopcount = 50 ; /* arbitrary max preventing infinite loop */
243
+ u8 * c ;
244
+ u16 tci ;
210
245
211
246
ndpoffset = cdc_ncm_rx_verify_nth16 (ctx , skb_in );
212
247
if (ndpoffset < 0 )
@@ -219,9 +254,10 @@ static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
219
254
220
255
ndp16 = (struct usb_cdc_ncm_ndp16 * )(skb_in -> data + ndpoffset );
221
256
222
- /* only supporting IPS Session #0 for now */
223
- switch (ndp16 -> dwSignature ) {
257
+ switch (ndp16 -> dwSignature & cpu_to_le32 (0x00ffffff )) {
224
258
case cpu_to_le32 (USB_CDC_MBIM_NDP16_IPS_SIGN ):
259
+ c = (u8 * )& ndp16 -> dwSignature ;
260
+ tci = c [3 ];
225
261
break ;
226
262
default :
227
263
netif_dbg (dev , rx_err , dev -> net ,
@@ -247,16 +283,15 @@ static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
247
283
}
248
284
249
285
/* sanity checking */
250
- if (((offset + len ) > skb_in -> len ) || (len > ctx -> rx_max ) ||
251
- (len < sizeof (struct iphdr ))) {
286
+ if (((offset + len ) > skb_in -> len ) || (len > ctx -> rx_max )) {
252
287
netif_dbg (dev , rx_err , dev -> net ,
253
288
"invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%p\n" ,
254
289
x , offset , len , skb_in );
255
290
if (!x )
256
291
goto err_ndp ;
257
292
break ;
258
293
} else {
259
- skb = cdc_mbim_process_dgram (dev , skb_in -> data + offset , len );
294
+ skb = cdc_mbim_process_dgram (dev , skb_in -> data + offset , len , tci );
260
295
if (!skb )
261
296
goto error ;
262
297
usbnet_skb_return (dev , skb );
0 commit comments